Press enter to see results or esc to cancel.

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;