ES:DI Address Loading
Turbo Pascal tries to optimize loading of addresses to ES:DI
register pair. For this purpose it uses few intermediate code instructions that track addresses that need to be loaded. The first intermediate code instruction will load local variable address to ES:DI
registers.
Procedure Load_ES_DI (LocalVarProcedure: Word; LocalVarDisplacement: Integer; IntermediateCodeToSaveAddress: Word);
begin
With PIntermediateCodeRecord (IncreaseSymbolTable (stIntermediateCode, 7))^ do
begin
RecordType := icLoad_ES_DI;
DestinationProcedure := LocalVarProcedure;
Displacement := LocalVarDisplacement;
SaveAddressCode := IntermediateCodeToSaveAddress;
end;
end;
Turbo Pascal assumes that the address in the ES:DI
register pair will remain unchanged. Everywhere where either ES
or DI
registers are changed, Turbo Pascal generates intermediate code instruction to indicate that the address is no longer in registers.
Procedure ES_DI_PointerDestroyed;
begin
PIntermediateCodeRecord (IncreaseSymbolTable (stIntermediateCode, 1))^.RecordType := ic_ES_DI_Destroyed;
end;
At the code generation phase Turbo Pascal goes through all intermediate code instructions for ES:DI
loading and removes redundant loads.
Procedure RemoveRedundant_ES_DI_AddressLoading;
Var IntermediateCodePointer: PIntermediateCodeRecord;
IntermediateCodePointerRec: PtrRec absolute IntermediateCodePointer;
CurrentLoadedAddress_Displacement: Integer;
CurrentLoadedAddress_Procedure: Word;
begin
IntermediateCodePointer := Ptr (SymbolTable [stIntermediateCode].Segment, LastIntermediateCodeSubroutine);
CurrentLoadedAddress_Displacement := 0;
CurrentLoadedAddress_Procedure := 0;
Repeat
Case IntermediateCodePointer^.RecordType of
icGoSub: begin
Asm
MOV AX, WORD PTR IntermediateCodePointer
ADD AX, 3
PUSH AX
end;
IntermediateCodePointerRec.Ofs := IntermediateCodePointer^.NewOffset;
end;
icReturn: Asm
POP WORD PTR IntermediateCodePointer
end;
icByte,
ic12: Inc (IntermediateCodePointerRec.Ofs, 2);
icWord,
icSourceLineNumber,
icSkippedGoSubSaveAddress: Inc (IntermediateCodePointerRec.Ofs, 3);
icJumpNear,
icJumpShort: Inc (IntermediateCodePointerRec.Ofs, 8);
icLabel: begin
Inc (IntermediateCodePointerRec.Ofs, 3);
CurrentLoadedAddress_Displacement := 0;
CurrentLoadedAddress_Procedure := 0;
end;
icReference,
icReferenceAsmBlock: Inc (IntermediateCodePointerRec.Ofs, 7);
icLoad_ES_DI: With IntermediateCodePointer^ do
begin
If (CurrentLoadedAddress_Procedure = DestinationProcedure) and
(CurrentLoadedAddress_Displacement = Displacement) then RecordType := ic_ES_DI_Loaded
else begin
CurrentLoadedAddress_Procedure := DestinationProcedure;
CurrentLoadedAddress_Displacement := Displacement;
If SaveAddressCode <> 0 then PIntermediateCodeRecord (
Ptr (IntermediateCodePointerRec.Seg,
SaveAddressCode))^.RecordType := icGoSub;
end;
Inc (IntermediateCodePointerRec.Ofs, 7);
end;
ic_ES_DI_Loaded: With IntermediateCodePointer^ do
begin
CurrentLoadedAddress_Procedure := DestinationProcedure;
CurrentLoadedAddress_Displacement := Displacement;
Inc (IntermediateCodePointerRec.Ofs, 7);
end;
ic_ES_DI_Destroyed: begin
CurrentLoadedAddress_Displacement := 0;
CurrentLoadedAddress_Procedure := 0;
Inc (IntermediateCodePointerRec.Ofs);
end;
icEnd: Break;
{$IFDEF DEBUG}
else Writeln (#13#10'ERROR: Unknown ic CODE'); { ERROR, not in TPC }
{$ENDIF}
end;
until False;
end;