home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / 386PATCH.ZIP / PATCH.PAS
Encoding:
Pascal/Delphi Source File  |  1991-04-23  |  6.1 KB  |  177 lines

  1. (6346)  Thu 18 Apr 91  8:35p
  2. By: Wilbert van.Leijen
  3. To: George Mcnamara
  4. Re: I386 Instructions in tp6
  5. St:
  6. ------------------------------------------------------------
  7.  
  8. Hi George,
  9.  
  10.  >    How about some sample 386 code, for example 32-bit math
  11.  > routines, in TP6.
  12.  
  13. The following unit patches 32-bit integer handling...  If you have an i386 or
  14. i486, the LongInt routines in SYSTEM.TPU will be overwritten.
  15. I released it to the public domain in October 1990.
  16.  
  17. { PATCH.PAS - Patching Turbo's Runtime Library On The Fly }
  18.  
  19. Unit Patch;
  20.  
  21. Interface
  22.  
  23. {$R-,S-,I- }
  24.  
  25. { Processor must be i386 or i486 or no go.
  26.   Algorithm copied from Al Williams, "Rolling Your Own Dos Extender"
  27.   Dr. Dobb's Journal, October 1990 }
  28.  
  29. Function CPUOk : Boolean;
  30.  
  31. InLine(
  32.            { Sort out 8086/8088 from 80286/i386/i486 }
  33.   $31/$C0/               {      XOR   AX, AX     }
  34.   $50/                   {      PUSH  AX         }
  35.   $9D/                   {      POPF             }
  36.   $9C/                   {      PUSHF            }
  37.   $58/                   {      POP   AX         }
  38.            { If the flag register holds $F000, then it is a 8086/8088 }
  39.   $25/$00/$F0/           {      AND   AX, $F000  }
  40.   $3D/$00/$F0/           {      CMP   AX, $F000  }
  41.   $74/$10/               {      JE    @@1        }
  42.            { Sort out 80286 from 80386/80486 }
  43.   $B8/$00/$F0/           {      MOV   AX, $F000  }
  44.   $50/                   {      PUSH  AX         }
  45.   $9D/                   {      POPF             }
  46.   $9C/                   {      PUSHF            }
  47.   $58/                   {      POP   AX         }
  48.            { If the flag register <> 2, then it is a 80286 }
  49.   $25/$00/$F0/           {      AND   AX, $F000  }
  50.   $74/$04/               {      JZ    @@1        }
  51.   $B0/$01/               {      MOV   AL, True   }
  52.   $EB/$02/               {      JMP   Short @@2  }
  53.   $B0/$00);              { @@1: MOV   AL, False  }
  54.                          { @@2: }
  55. Implementation
  56.  
  57. Const
  58.   dummy        : LongInt = 1;
  59.  
  60. Type
  61.   SystemProc   = Procedure;
  62.   SystemCall   = ^SystemProc;      { Pointer to the caller's address }
  63.  
  64. Var
  65.   CallAddr     : ^SystemCall;      { Pointer to the procedure to be patched }
  66.  
  67. { Copy instruction pointer of caller from the stack }
  68.  
  69. Function IPtr : Word;
  70.  
  71. InLine(
  72.   $8B/$46/$02);          {      MOV   AX, [BP+2] }
  73.  
  74. { This patch speeds up 4-byte signed integer division by 600% }
  75.  
  76. Procedure DivisionPatch;
  77.  
  78. Const
  79.   PatchCode    : Array[0..21] of Byte = (
  80.            { Push dividend on the stack, pop it in a 32-bits register
  81.              To avoid division by zero errors, extend it to a quadword }
  82.                    $52,            {  PUSH  DX        }
  83.                    $50,            {  PUSH  AX        }
  84.                    $66, $58,       {  POP   EAX       }
  85.                    $66, $99,       {  CDQ             }
  86.            { Push divisor on the stack, pop it in a 32-bit register.
  87.              Perform the division }
  88.                    $53,            {  PUSH  BX        }
  89.                    $51,            {  PUSH  CX        }
  90.                    $66, $5E,       {  POP   ESI       }
  91.                    $66, $F7, $FE,  {  IDIV  ESI       }
  92.            { Push remainder on the stack, pop it in 16-bits registers }
  93.                    $66, $52,       {  PUSH  EDX       }
  94.                    $59,            {  POP   CX        }
  95.                    $5B,            {  POP   BX        }
  96.            { Push quotient on the stack, pop it in 16-bits registers }
  97.                    $66, $50,       {  PUSH  EAX       }
  98.                    $58,            {  POP   AX        }
  99.                    $5A,            {  POP   DX        }
  100.                    $CB);           {  RETF            }
  101. Begin
  102.   CallAddr := Ptr(CSeg, IPtr-14);
  103.   Move(PatchCode, CallAddr^^, SizeOf(PatchCode));
  104. end;  { LongIntDivisionPatch }
  105.  
  106. { Provided the product > 2^16, this patch speeds up 4-byte signed integer
  107.    multiplication by 5%  }
  108.  
  109. Procedure MultiplyPatch;
  110.  
  111. Const
  112.   PatchCode    : Array[0..15] of Byte = (
  113.            { Push first operand on the stack, pop it in a 32-bits register }
  114.                    $52,            {  PUSH  DX        }
  115.                    $50,            {  PUSH  AX        }
  116.                    $66, $58,       {  POP   EAX       }
  117.            { Push second operand on the stack, pop it in a 32-bits register
  118.              Perform the multiplication }
  119.                    $53,            {  PUSH  BX        }
  120.                    $51,            {  PUSH  CX        }
  121.                    $66, $5A,       {  POP   EDX       }
  122.                    $66, $F7, $EA,  {  IMUL  EDX       }
  123.            { Push product on the stack, pop it in 16-bits registers }
  124.                    $66, $50,       {  PUSH  EAX       }
  125.                    $58,            {  POP   AX        }
  126.                    $5A,            {  POP   DX        }
  127.                    $CB);           {  RETF            }
  128. Begin
  129.   CallAddr := Ptr(CSeg, IPtr-14);
  130.   Move(PatchCode, CallAddr^^, SizeOf(PatchCode));
  131. end;  { MultiplyPatch }
  132.  
  133. { Shift directly across multiple words, rather than in a loop }
  134.  
  135. Procedure ShiftLeftPatch;
  136.  
  137. Const
  138.   PatchCode    : Array[0..3] of Byte = (
  139.                    $0F, $A5, $C2,  {  SHLD DX, AX, CL }
  140.                    $CB);           {  RETF            }
  141. Begin
  142.   CallAddr := Ptr(CSeg, IPtr-14);
  143.   Move(PatchCode, CallAddr^^, SizeOf(PatchCode));
  144. end;  { ShiftLeftPatch }
  145.  
  146. { Shift directly across multiple words, rather than in a loop }
  147.  
  148. Procedure ShiftRightPatch;
  149.  
  150. Const
  151.   PatchCode    : Array[0..3] of Byte = (
  152.                    $0F, $AD, $C2,  {  SHRD DX, AX, CL }
  153.                    $CB);           {  RETF            }
  154. Begin
  155.   CallAddr := Ptr(CSeg, IPtr-14);
  156.   Move(PatchCode, CallAddr^^, SizeOf(PatchCode));
  157. end;  { ShiftRightPatch }
  158.  
  159. Begin  { Patch }
  160.   If CPUOk Then                        { It's a 32-bitter }
  161.     Begin
  162.       dummy := dummy div dummy;
  163.       DivisionPatch;
  164.       dummy := dummy*dummy;
  165.       MultiplyPatch;
  166.       dummy := dummy shl 1;
  167.       ShiftLeftPatch;
  168.       dummy := dummy shr 1;
  169.       ShiftRightPatch;
  170.     end;
  171. end.  { Patch }
  172.  
  173.  
  174. --- Dutchie V2.91
  175.  * Origin: -= Point Wilbert | Vaya Con BIOS! =- (2:500/12.10956)
  176.  
  177.