[Back to MISC SWAG index] [Back to Main SWAG index] [Original]
{
George Kalemanis <usr5086a@tso.uc.edu>
PATCH.PAS - Patching Turbo's Runtime Library On The Fly
}
Unit patch;
Interface
{$R-,S-,I- }
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 }
[Back to MISC SWAG index] [Back to Main SWAG index] [Original]