home *** CD-ROM | disk | FTP | other *** search
- (6346) Thu 18 Apr 91 8:35p
- By: Wilbert van.Leijen
- To: George Mcnamara
- Re: I386 Instructions in tp6
- St:
- ------------------------------------------------------------
-
- Hi George,
-
- > How about some sample 386 code, for example 32-bit math
- > routines, in TP6.
-
- The following unit patches 32-bit integer handling... If you have an i386 or
- i486, the LongInt routines in SYSTEM.TPU will be overwritten.
- I released it to the public domain in October 1990.
-
- { PATCH.PAS - Patching Turbo's Runtime Library On The Fly }
-
- Unit Patch;
-
- Interface
-
- {$R-,S-,I- }
-
- { Processor must be i386 or i486 or no go.
- Algorithm copied from Al Williams, "Rolling Your Own Dos Extender"
- Dr. Dobb's Journal, October 1990 }
-
- Function CPUOk : Boolean;
-
- InLine(
- { Sort out 8086/8088 from 80286/i386/i486 }
- $31/$C0/ { XOR AX, AX }
- $50/ { PUSH AX }
- $9D/ { POPF }
- $9C/ { PUSHF }
- $58/ { POP AX }
- { If the flag register holds $F000, then it is a 8086/8088 }
- $25/$00/$F0/ { AND AX, $F000 }
- $3D/$00/$F0/ { CMP AX, $F000 }
- $74/$10/ { JE @@1 }
- { Sort out 80286 from 80386/80486 }
- $B8/$00/$F0/ { MOV AX, $F000 }
- $50/ { PUSH AX }
- $9D/ { POPF }
- $9C/ { PUSHF }
- $58/ { POP AX }
- { If the flag register <> 2, then it is a 80286 }
- $25/$00/$F0/ { AND AX, $F000 }
- $74/$04/ { JZ @@1 }
- $B0/$01/ { MOV AL, True }
- $EB/$02/ { JMP Short @@2 }
- $B0/$00); { @@1: MOV AL, False }
- { @@2: }
- Implementation
-
- Const
- dummy : LongInt = 1;
-
- Type
- SystemProc = Procedure;
- SystemCall = ^SystemProc; { Pointer to the caller's address }
-
- Var
- CallAddr : ^SystemCall; { Pointer to the procedure to be patched }
-
- { Copy instruction pointer of caller from the stack }
-
- Function IPtr : Word;
-
- InLine(
- $8B/$46/$02); { MOV AX, [BP+2] }
-
- { This patch speeds up 4-byte signed integer division by 600% }
-
- Procedure DivisionPatch;
-
- Const
- PatchCode : Array[0..21] of Byte = (
- { Push dividend on the stack, pop it in a 32-bits register
- To avoid division by zero errors, extend it to a quadword }
- $52, { PUSH DX }
- $50, { PUSH AX }
- $66, $58, { POP EAX }
- $66, $99, { CDQ }
- { Push divisor on the stack, pop it in a 32-bit register.
- Perform the division }
- $53, { PUSH BX }
- $51, { PUSH CX }
- $66, $5E, { POP ESI }
- $66, $F7, $FE, { IDIV ESI }
- { Push remainder on the stack, pop it in 16-bits registers }
- $66, $52, { PUSH EDX }
- $59, { POP CX }
- $5B, { POP BX }
- { Push quotient on the stack, pop it in 16-bits registers }
- $66, $50, { PUSH EAX }
- $58, { POP AX }
- $5A, { POP DX }
- $CB); { RETF }
- Begin
- CallAddr := Ptr(CSeg, IPtr-14);
- Move(PatchCode, CallAddr^^, SizeOf(PatchCode));
- end; { LongIntDivisionPatch }
-
- { Provided the product > 2^16, this patch speeds up 4-byte signed integer
- multiplication by 5% }
-
- Procedure MultiplyPatch;
-
- Const
- PatchCode : Array[0..15] of Byte = (
- { Push first operand on the stack, pop it in a 32-bits register }
- $52, { PUSH DX }
- $50, { PUSH AX }
- $66, $58, { POP EAX }
- { Push second operand on the stack, pop it in a 32-bits register
- Perform the multiplication }
- $53, { PUSH BX }
- $51, { PUSH CX }
- $66, $5A, { POP EDX }
- $66, $F7, $EA, { IMUL EDX }
- { Push product on the stack, pop it in 16-bits registers }
- $66, $50, { PUSH EAX }
- $58, { POP AX }
- $5A, { POP DX }
- $CB); { RETF }
- Begin
- CallAddr := Ptr(CSeg, IPtr-14);
- Move(PatchCode, CallAddr^^, SizeOf(PatchCode));
- end; { MultiplyPatch }
-
- { Shift directly across multiple words, rather than in a loop }
-
- Procedure ShiftLeftPatch;
-
- Const
- PatchCode : Array[0..3] of Byte = (
- $0F, $A5, $C2, { SHLD DX, AX, CL }
- $CB); { RETF }
- Begin
- CallAddr := Ptr(CSeg, IPtr-14);
- Move(PatchCode, CallAddr^^, SizeOf(PatchCode));
- end; { ShiftLeftPatch }
-
- { Shift directly across multiple words, rather than in a loop }
-
- Procedure ShiftRightPatch;
-
- Const
- PatchCode : Array[0..3] of Byte = (
- $0F, $AD, $C2, { SHRD DX, AX, CL }
- $CB); { RETF }
- Begin
- CallAddr := Ptr(CSeg, IPtr-14);
- Move(PatchCode, CallAddr^^, SizeOf(PatchCode));
- end; { ShiftRightPatch }
-
- Begin { Patch }
- If CPUOk Then { It's a 32-bitter }
- Begin
- dummy := dummy div dummy;
- DivisionPatch;
- dummy := dummy*dummy;
- MultiplyPatch;
- dummy := dummy shl 1;
- ShiftLeftPatch;
- dummy := dummy shr 1;
- ShiftRightPatch;
- end;
- end. { Patch }
-
-
- --- Dutchie V2.91
- * Origin: -= Point Wilbert | Vaya Con BIOS! =- (2:500/12.10956)
-
-