Calculating Code Size and Offsets
Before the target code is generated Turbo Pascal needs to know code size and offsets of instructions. This procedure processes intermediate code instructions and calculates the size of generated code, offsets of near jump instructions, offsets of labels and size of reference records.
Procedure CalculateCodeSizeAndOffsets;
Var IntermediateCodePointer: PIntermediateCodeRecord;
IntermediateCodePointerRec: PtrRec absolute IntermediateCodePointer;
CodeOffset, AdditionalReferencesSize, LastNearJumpRecord: Word;
OpCode: Byte;
Procedure CalculateLoadAddressCodeSize (DestinationDisplacement: Integer; DestinationProc: Word);
Var ProcedureIdentifier: PIdentifier;
ProcedureIdentifierRec: PtrRec absolute ProcedureIdentifier;
ProcedureIdentifierData: PProcedureIdentifierData absolute ProcedureIdentifier;
ProcedureIdentifierDataRec: PtrRec absolute ProcedureIdentifier;
begin
If DestinationProc <> CurrentProcedureIdentifier then
begin
ProcedureIdentifierData := Ptr (SymbolTable [stMain].Segment, ProcedureIdentifierDataOffset);
Inc (CodeOffset, 3);
Repeat
ProcedureIdentifierRec.Ofs := ProcedureIdentifierData^.OuterBlockProcedureIdentifier;
If ProcedureIdentifierRec.Ofs = DestinationProc then Break;
Inc (ProcedureIdentifierRec.Ofs, ProcedureIdentifier^.Name.Len + 4);
Inc (CodeOffset, 4);
until False;
If DestinationDisplacement = 0 then Exit;
Inc (CodeOffset);
end;
Inc (CodeOffset, 3);
If DestinationDisplacement <> ShortInt (DestinationDisplacement) then Inc (CodeOffset);
end;
begin
AdditionalReferencesSize := 0;
LastNearJumpRecord := 0;
IntermediateCodePointer := Ptr (SymbolTable [stIntermediateCode].Segment, LastIntermediateCodeSubroutine);
CodeOffset := SymbolTable [stCode].UsedSize;
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: begin
Inc (CodeOffset);
Inc (IntermediateCodePointerRec.Ofs, 2);
end;
icWord: begin
Inc (CodeOffset, 2);
Inc (IntermediateCodePointerRec.Ofs, 3);
end;
icJumpNear: With IntermediateCodePointer^ do
begin
JumpCodeOffset := CodeOffset;
OpCode := JumpOpCode;
Previous_icJumpNear := LastNearJumpRecord;
LastNearJumpRecord := IntermediateCodePointerRec.Ofs;
Inc (IntermediateCodePointerRec.Ofs, 8);
Inc (CodeOffset, 3); { JMP_Near size }
If OpCode < JMP_ConditionalShortLimit then Inc (CodeOffset, 2); { In case conditional jump will }
end; { become two jumps, short and near }
icJumpShort: begin
Inc (IntermediateCodePointerRec.Ofs, 8);
Inc (CodeOffset, 2);
end;
icLabel: begin
IntermediateCodePointer^.LabelAddress := CodeOffset;
Inc (IntermediateCodePointerRec.Ofs, 3);
end;
icReference,
icReferenceAsmBlock: begin
Inc (AdditionalReferencesSize, 8);
Inc (CodeOffset, 2);
If IntermediateCodePointer^.Flags * [rfSegment, rfOffset] = [rfSegment, rfOffset] then
Inc (CodeOffset, 2);
Inc (IntermediateCodePointerRec.Ofs, 7);
end;
ic12,
icSourceLineNumber,
icSkippedGoSubSaveAddress: Inc (IntermediateCodePointerRec.Ofs, 3);
icLoad_ES_DI: With IntermediateCodePointer^ do
begin
CalculateLoadAddressCodeSize (Displacement, DestinationProcedure);
Inc (IntermediateCodePointerRec.Ofs, 7);
end;
ic_ES_DI_Loaded: Inc (IntermediateCodePointerRec.Ofs, 7);
ic_ES_DI_Destroyed: Inc (IntermediateCodePointerRec.Ofs);
icEnd: Break;
end;
until False;
SizeOfCodeReferenceRecords := AdditionalReferencesSize;
Last_icJumpNear := LastNearJumpRecord;
SizeOfGeneratedCode := CodeOffset - SymbolTable [stCode].UsedSize;
end;