DataMuseum.dk

Presents historical artifacts from the history of:

DANOSI

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DANOSI

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦678dad406⟧ TextFile

    Length: 58112 (0xe300)
    Types: TextFile
    Names: »P4CODE.PAS«

Derivation

└─⟦02956c927⟧ Bits:30010510 DVBS1.SW2114.src.2.14-1 SW2114 REAL #1/4 TIME PASCAL SOURCE REL 2.14
    └─⟦this⟧ »RTP\P4CODE.PAS« 
└─⟦4f587ad96⟧ Bits:30010518 DVBS1.SW2114.src.2.7-1 SW2114 1/4 Real Time Pascal 2.7 92.06.16
    └─⟦this⟧ »RTP\P4CODE.PAS« 
└─⟦a2a9e188c⟧ Bits:30010526 DVBS1.SW2114.src.2.6-4 RTP Compiler Source SW2104+SW2114 Disk 1 92.02.03 HEJ HHA
    └─⟦this⟧ »RTP\P4CODE.PAS« 
└─⟦b607d6035⟧ Bits:30010532 RTP compiler Source 1 2.14 26/9(?)-92 DVBS1.SW2114.src.2.14-8
    └─⟦this⟧ »P4CODE.PAS« 
└─⟦fd2665794⟧ Bits:30010523 DVBS1.SW2114.src.2.6-1 RTP compiler source SW2104+SW2114 Disk#1 30/1-92 HHA
    └─⟦this⟧ »RTP\P4CODE.PAS« 

TextFile

{$O+,F+}\r
unit p4code;\r
  (* This module impl. procedure called when generating code *)\r
interface\r
uses pscplm,mpaunit,sthunit,sthcom,p4unit;\r
\r
\r
\r
\r
\r
  (* --------- PUBLIC CODEGENERATOR -----------CODEGENERATOR --*)\r
\r
\r
\r
    CONST\r
\r
\r
      LengthOfSharedType = 10;\r
\r
      LengthOfSemaphore = 8;\r
\r
      SharedCounterOffset = 4;\r
\r
      LockedOffset  = 2;\r
\r
      DataSizeOffset = 4;\r
\r
      OffsetOffset = 6;\r
\r
      DataPartOffset = 8;\r
\r
      TopOffset = 10;\r
\r
      StackBoundOffset = 28;\r
        (* Offset to field StackBound in PI3 type Process_Descriptor *)\r
\r
      NoParamOffset = 29;\r
        (* offset to the field Noparam in the pi3 type program_describtion *)\r
\r
      SubProgsHeadOffset = 74;\r
        (* offset to the SubProgsHead field in pi3 type program_describtion *)\r
\r
      ParamsizeForCreate = 20;\r
        (* no of bytes for the parameter to create *)\r
\r
\r
      (* The following constant gives the interupt parameter to an exception *)\r
\r
      RefLockExc = 1;  (*3;*)\r
\r
      IndexOutOfRangeInt = 5;\r
      IndexOutOfRangeExc = 2;   (* fault 50 *)\r
\r
      StackOverFlowInt = 30;\r
      StackOverFlowExc = 3;  (* fault 51 *)\r
        (* Parametre to interrupt when stack overflow *)\r
\r
      OutOfRangeInt = 29;\r
      OutOfRangeExc = 4;  (* fault 52 *)\r
\r
      OtherwiseInt = 28;\r
      OtherwiseExc = 5;  (* 53 *)\r
\r
      LockInt = 27;\r
      LockExc = 6;  (* 54 *)\r
\r
      AccessCheckInt = 26;\r
      AccessCheckExc = 7;  (* 55 *)\r
        (* Parametre to interupt when accesscheck error *)\r
\r
      PointerNilInt = 25;\r
      PointerNilExc = 8;   (* 56 *)\r
\r
      CheckParamInt = 24;\r
      CheckParamExc = 9;  (* 57 *)\r
\r
      StrucInt =  23;\r
      StrucExc =  10;  (* 58  *)\r
\r
      SubRangeInt = 22;\r
      SubRangeExc = 11;  (* 59 *)\r
\r
      WithInt = 21;\r
      WithExc = 12;  (* 60 *)\r
\r
      IntOnFault = 31;\r
\r
      DynArrayExc = 13;  (*64*)\r
\r
      DynRecordExc = 13;  (* 64 *)\r
\r
\r
\r
\r
      (* PI3 constant *)\r
      call_frame = 20;\r
      (* The following gives the number for the predefined external routines *)\r
      Fault = 1;\r
      Resume = 2;\r
      AllocPool = 3;\r
      Init_Semaphore = 4;\r
      WaitS = 5;\r
      Set_Exception = 6;\r
      Init_Reference = 7;\r
      Init_Chain = 8;\r
      Init_Shared = 9;\r
      Init_Mailbox = 10;\r
      Init_Process = 11;\r
      Init_Internal = 12;\r
      Init_External = 13;\r
      Init_Port = 14;\r
      SignalS = 15;\r
      Init_Pool = 16;\r
      EndProcess = 17;\r
      Mark_LocalRef = 18;\r
      UnChain_LocalRef = 19;\r
      Init_LocalRef = 20;\r
\r
   (* External set Routine *)\r
      AssignSet = 21;\r
      PushSet = 22;\r
      AddSet = 23;\r
      SubSet = 24;\r
      MultSet= 25;\r
      GESet = 26;\r
      EQSet= 27;\r
      NESet= 28;\r
      LESet = 29;\r
      InSet = 30;\r
      MakeSet = 31;\r
\r
\r
      NoOfPI3Routines = 20;\r
      NoOfSetRoutines = 11;\r
      NoOfPI3RoutinesAndSetRoutines = 31;\r
    TYPE\r
\r
\r
\r
\r
\r
\r
\r
      JumpRang = iJE..iJCXZ;\r
\r
      NegInstTable = ARRAY[JumpRang] OF Instruction;\r
\r
\r
\r
    VAR\r
\r
      (* List contains the  external routines *)\r
      FirstExtDec : St_Address;\r
\r
      NoExtDecl, NoPreExtDecl : Word;\r
\r
      LengthOfAllPreExtName, LengthOfAllExtName : Word;\r
\r
\r
      CodeOn : boolean;\r
           (* Symbolic code is generated if true *)\r
\r
 \r
      NegInstruction : NegInstTable;\r
               (* Tabel contains the negation of the cond jumps *)\r
\r
      LastNameEntry : St_Address;\r
\r
      LengthOfNameTabel : word;\r
\r
      LineTabel : boolean;\r
\r
      Spacing : word;\r
\r
      CurrentSegNo : Word;\r
\r
\r
  (* Declarations which has to do with pass4_2  TURBO *)\r
\r
    CONST\r
\r
\r
      OpCodeLongJmp = $EA; (* 11101010B;*)\r
\r
      OpcodeCallExt = $9A; (*10011010B;*)\r
\r
\r
\r
\r
\r
      LengthOfExternalLBDR = 29;\r
\r
      LengthOfInternalLBDR = 8;\r
\r
\r
\r
\r
      Max4Bit = 16;\r
\r
      MaxByte = 256;\r
\r
\r
      (* the following constant gives the type of records on codefile *)\r
      Frstrc = $0B0;  (* First record *)\r
\r
      Lastrc = $0B2;\r
\r
      TypDef = $8E;\r
\r
\r
\r
\r
    TYPE\r
      CodeFormat = (DeclareLabel, ExternalCall, ShortJump, NearUnCondJump,\r
                    NearCondJump, CaseLabList, AddLabelToDis,\r
                    InternalLBDR, ExternalLBDR, LineNo, SetCode,\r
                    RoutineStartStop, ContextEnd,\r
                    LongCall, LongJump,ExternalJump);\r
\r
      CodeName = PACKED ARRAY[1..6] OF char;\r
\r
\r
\r
      TypeExternalLBDR =\r
        RECORD\r
          CASE b : Boolean OF\r
           \r
            true : ( EntryPoint : Word;\r
                     LineTable : word;\r
                     GlobalSize : Word;\r
                     Appetite : Word;\r
                     SegSize : Word;\r
                     LinkCount : Byte;\r
                     Next1,Next2 : integer; (* a pointer *)\r
                     BlName : String[12];\r
                     BlKind : Byte );\r
\r
\r
            false : ( Byt :ARRAY[1..LengthOfExternalLBDR] OF Byte);\r
        END;\r
\r
\r
\r
    VAR\r
\r
\r
      InstructionName : ARRAY[ iXLAT..iXCHG ] OF CodeName;\r
        (* Tabel of names of instructiones *)\r
\r
      PreExtName : ARRAY[1..NoOfPI3RoutinesAndSetRoutines] of SpixRange;\r
      PreExtCalled : ARRAY[1..NoOfPI3Routines] of boolean;\r
\r
      FirstFixUpp, LastFixUpp : St_Address;\r
        (* List of FixUpp *)\r
\r
      NoFixUpp : Word;\r
        (* Number of FixUpp *)\r
\r
\r
\r
\r
      (* The following variabels are tabels containing opcode for\r
         instructions *)\r
\r
      OpcodeShort : ARRAY[ iJE .. iJMP ] OF Byte;\r
            (* Tabel of opcodes for short jumps *)\r
\r
      OpcodeNear : ARRAY [ iJMP .. iCALL ] OF Byte;\r
             (* Tabel of opcodes for near jumps *)\r
\r
      ContextEndOffset : Word;\r
\r
\r
      VersionNumber : Array[1..4] OF Word;\r
\r
\r
      FilePtrToSecSegDef : longint;\r
\r
    (* -------------------------------------------- *)\r
\r
\r
    PROCEDURE InitCodeGenerator;\r
       (* The procedure initialize the codegenerator *)\r
\r
    PROCEDURE MakeExternalLBDR( SymbolPoint : St_Address;\r
                                EntryPoint : St_Address;\r
                                LineTable : integer;\r
                                GlobalSize : Word;\r
                                Appetite : Word;\r
                                BlName : SpixRange;\r
                                BlKind : integer );\r
      (* The procedure makes a external LBDR *)\r
\r
    PROCEDURE MakeInternalLBDR( EntryPoint : St_Address;\r
                                LineTable : integer;\r
                                GlobalSize : Word;\r
                                Appetite : Word );\r
      (* The procedure makes a internal LBDR *)\r
\r
\r
\r
    PROCEDURE MakeProgramDesc(ProgOffset : Word; ProgState : State;\r
                              PoolParam : boolean; Lab : St_Address );\r
      (* The procedure generate code to make the program describtion at \r
         address 'Addr'. This procedure has to be change if the pi3 type\r
         programdescribtion is change *)\r
\r
\r
\r
    PROCEDURE StopBlock;\r
      (* The procedure is called when where is no more code for\r
         that block. The procedure makes the <object block> on file\r
         codefile. That is the 2. pass of the block is made *)\r
\r
    PROCEDURE StopCodeGene;\r
      (* The procedure is called when where is no more code to be\r
         generated. *)\r
\r
    PROCEDURE GenCode(Inst : Instruction);\r
      (* Generate a instruction without parameter *)\r
\r
    PROCEDURE CodeConst(Inst : Instruction; Value : word   );\r
      (* Generate a instruction with a constant parametre *)\r
\r
    PROCEDURE CodeAddr(Inst : Instruction; InstType : InstrucType;\r
                                          VAR a : Address);\r
      (* Generate a instruction with a address as parametre *)\r
\r
    PROCEDURE CodeReg(Inst : Instruction; InstType : InstrucType;\r
                                            r : Register );\r
      (* Generate a instruction with a register as parametre *)\r
\r
    PROCEDURE CodeAddrConst(Inst : Instruction; InstType : InstrucType;\r
                            VAR a : Address; Value : word   );\r
      (* Generate a instruction with a address as the first parametre\r
         and a constant as the secend parametre *)\r
\r
\r
    PROCEDURE CodeAddrReg(Inst : Instruction; InstType : InstrucType;\r
                          VAR a : Address; r : Register );\r
      (* Generate a instruction with an address as first parametre\r
         and an register as secend parameter      *)\r
\r
    PROCEDURE CodeRegAddr(Inst : Instruction; InstType : InstrucType;\r
                                r : Register; VAR a : Address   );\r
      (* Generate a instruction with a register as first parametre\r
         and an adddress as secend parametre  *)\r
\r
    PROCEDURE CodeRegConst(Inst : Instruction; InstType : InstrucType;\r
                                   r : Register; Value : word );\r
      (* Generate a instruction with a register as the first\r
         parametre and a constant as the secend parametre *)\r
\r
    PROCEDURE CodeRegReg(Inst : Instruction; InstType : InstrucType;\r
                                             r1, r2 : Register );\r
      (* Generate a instruction where both parametres are registers *)\r
\r
    PROCEDURE CallRoutine(Spix : SpixRange; Number : word; RKind :\r
                                                             St_DeclareMode);\r
      (* The procedure generates code for an external or open routine call *)\r
\r
\r
    PROCEDURE CodeJump(Inst : Instruction; Lab : St_Address);\r
      (* Generate a instruction with a label as parameter *)\r
\r
\r
    PROCEDURE CodeIndJump(Lab : St_Address; IndexReg : Register);\r
      (* Generate a indirect jump at address CS: Lab.Offset [IndexReg] *)\r
\r
    PROCEDURE CodeFaultAX( ErrorInt, ErrorExc: WORD);\r
\r
    PROCEDURE CodeFault( ErrorInt, ErrorExc: WORD);\r
    \r
\r
    PROCEDURE CodeLoadEffAddr(Reg : Register; Lab : St_Address; Offset : Word);\r
      (* Generate code to load reg with the effectiv address of Lab:+ Offset *)\r
\r
    PROCEDURE GenerateLabel(Lab : St_Address);\r
      (* Generate the label given by Lab *)\r
\r
    PROCEDURE GenAsLabel(Lab1, Lab2 : St_Address);\r
      (* The offset of Lab1 is given by the offset of Lab2\r
         A command is made in the code if Lab2 has been generate *)\r
\r
    PROCEDURE DumpConst(ConstAddr : St_Address );\r
      (* the structured constant given by ConstAddr is dumped in the code *)\r
\r
\r
    PROCEDURE DumpCaseTabel(CaseTab : St_Address; Size : word;\r
                                               OtherwiseLab : St_Address);\r
      (* The casetabel is generated *)\r
\r
\r
    PROCEDURE NewLine(Line : Word);\r
      (* The procedure write the linenumber to codelist if codeon *)\r
\r
    PROCEDURE SetCodeTo(Bool : Boolean);\r
      (* The procedure change the option codeon *)\r
\r
    Procedure ContextStop;\r
      (* The procedure is called when leaving linetabel. Only used when\r
         making linetabel *)\r
\r
\r
    Procedure RoutineDecl(Symbol : St_Address; start : boolean );\r
       (* the routine is called when making a routine, program or a familie\r
          declaration. Only used when making nameentry *)\r
\r
\r
\r
    PROCEDURE MakeLongCall(Symbol : St_Address);\r
      (* Makes a call to an other segment using segment fixup *)\r
\r
    PROCEDURE  DumpRoutineTabel;\r
      (* Dumps the routine tabel . Only used when more than one segment *)\r
\r
    Procedure MakeJumpToNextSegment;\r
      (* Only used when more than one segment *)\r
\r
  (* ----- END PUPLIC CODEGENERATOR --------CODEGENERATOR -- *)\r
\r
\r
IMPLEMENTATION\r
  (* ---------- IMPORTS --------------------IMPORTS ---------*)\r
\r
uses sthp34,files,rtp86p4,p4;\r
\r
\r
  (* ------------IMPORTS END --------------IMPORTS END --------*)\r
\r
\r
\r
  (* --------PRIVATE CODEGENERATOR ------ CODEGENERATOR -----*)\r
\r
    Const\r
      FirstExc = RefLockExc;\r
      LastExc = DynRecordExc;\r
\r
    VAR\r
      FaultInfo :\r
        Array[FirstExc..LastExc] OF\r
          Record\r
            used : boolean;\r
            number : byte;\r
            faultThunk : St_address;\r
          end;\r
\r
\r
\r
    CONST\r
\r
      MaxLengthOfOpenRoutines = 2000;\r
        (* this constant must be changed if new opernroutins is made *)\r
\r
      LengthOfCodeBuffer = 500; (* length of internal buffer *)\r
\r
\r
      OpcodeMovImmToReg = $B0; (*10110000B;*)\r
\r
      OpcodeMovR_MToSeg = $8E; (*10001110B;*)\r
\r
      OpCodeMovSegToR_M = $8C; (*10001100B;*)\r
\r
\r
      OpcodePreFix = $26; (* 00100110B;*)\r
\r
      OpcodeCSPreFix = $2E; (*00101110B;*)\r
\r
      CRegFieldJumpIndirect = $4; (*100B;*)\r
\r
      OpcodeJumpIndirect = $FF; (*11111111B;*)\r
\r
\r
\r
\r
\r
    VAR\r
\r
      CodeBuffer : ARRAY[0..LengthOfCodeBuffer] OF byte;\r
                   (* the internal buffer *)\r
      BufferIndex : Word;\r
                   (* Index to the codebuffer where to put the\r
                      next byte *)\r
      FirstIndex : Word;\r
            (* Index to codebuffer to the first insert byte *)\r
\r
      NoBytesInBuffer : word;\r
                   (* Number of bytes i codebuffer *)\r
      InternalOffset : Word;\r
                   (* Offset to next byte to be insert in codebuffer *)\r
      FileOffset : Word;\r
                   (* Offset to next byte to be written to TBinFile *)\r
\r
      LastInternalLBDROffset : Word;\r
        (* The offset of the last internalLBDR written to TBinFile *)\r
\r
\r
\r
      LastJMPOffset : Word; (* internaloffset after generating the last\r
                               JMP instruction *)\r
\r
      LastLabelOffset : Word;\r
                   (* InternalOffset of the last generated label *)\r
\r
      LastLabel : St_Address;  (* pointer to last generated label *)\r
\r
             (* LastJMPOffset, LastLabelOffset and LastLabel is used to\r
                eliminat superflous jumps *)\r
\r
\r
\r
      (* The following variabels are tabels containing opcode for\r
         instructions *)\r
\r
      OpcodeNoOpr : ARRAY[ iXLAT..iRETIS ] OF Byte;\r
            (* Tabel of opcodes for instruction with no operands *)\r
\r
      OpcodeCOpr : ARRAY[ iInt..iRETIS ] OF Byte;\r
            (* Tabel of opcodes for instructions with a constant\r
               operand *)\r
\r
      OpcodeSROpr : ARRAY[ iPUSH .. iPOP ] OF Byte;\r
            (* Tabel of opcodes for instructions with a Seg Register *)\r
\r
      OpcodeRegOpr : ARRAY[ iPUSH .. iDEC ] OF Byte;\r
            (* Tabel of opcodes for instructions with a register \r
               packed into the opcode *)\r
\r
      OpcodeR_M : ARRAY[ iPUSH .. iXCHG ] OF Byte;\r
            (* Tabel of opcodes for instructions with a register or a\r
               address as operand. Operand of type R_M *)\r
\r
      OpcodeCRegField : ARRAY[ iPUSH .. iMOV ] OF 0..7;\r
            (* Tabel of the value of the reg field for instruction\r
               of type R_M not useing the RegField ( only one operand\r
               or a constant operand *) \r
\r
      OpcodeConstandAcc : ARRAY[ iADD..iXOR ] OF Byte;\r
            (* Tabel of opcode for instruction with a accumulate\r
               and a const as operands *)\r
\r
      OpcodeR_MandConst : ARRAY[ iADD .. iMOV ] OF Byte;\r
            (* Tabel of opcode for instruction with a R_M operand\r
               and a const *)\r
\r
      CodeOfOpenRoutines : ARRAY[ 0 .. MaxLengthOfOpenRoutines ] OF Byte;\r
            (* tabels contains the code for the open routines *)\r
\r
\r
      ShiftFactor : ARRAY[0..7] OF Byte;\r
\r
\r
      WordByte : RECORD\r
                   CASE Int : integer OF\r
                     1 : (i : Integer);\r
                     2 : (Byte1 : 0..255;\r
                          Byte2 : 0..255);\r
                     3 : (w : Word);\r
                 END;\r
               (* Used to convert a integer/Word to two bytes or two bytes\r
                  to a integer/Word *)\r
\r
      Filebufferindex : integer;\r
    (* -------------------------------------------- *)\r
\r
 procedure emptyfilebuffer;\r
 BEGIN\r
  blockwrite(tbinfile,filebufferptr^,filebufferindex);\r
  filebufferindex := 0;\r
 end;\r
\r
 Procedure puttbinfile( x: byte);\r
 BEGIN\r
  if Filebufferindex = Lengthoffilebuffer then\r
    emptyfilebuffer;\r
  filebufferindex := filebufferindex + 1;\r
  filebufferptr^[filebufferindex] := x;\r
END;\r
\r
\r
Procedure InitFaultInfo;\r
  VAR i : integer;\r
  BEGIN\r
    FOR i := firstExc TO LastExc DO FaultInfo[i].used := false;\r
    FaultInfo[RefLockExc].Number := 3;\r
    FaultInfo[IndexOutOfRangeExc].Number := 50;\r
    FaultInfo[StackOverFlowExc].Number :=  51;\r
    FaultInfo[OutOfRangeExc].Number := 52;\r
    FaultInfo[OtherwiseExc].Number := 53;\r
    FaultInfo[LockExc].Number := 54;\r
    FaultInfo[AccessCheckExc].Number := 55;\r
    FaultInfo[PointerNilExc].Number :=56;\r
    FaultInfo[CheckParamExc].Number := 57;\r
    FaultInfo[StrucExc].Number :=58;\r
    FaultInfo[SubRangeExc].Number := 59;\r
    FaultInfo[WithExc].Number := 60;\r
    FaultInfo[DynArrayExc].Number :=64;\r
    FaultInfo[DynRecordExc].Number := 64;\r
  END;\r
\r
Procedure DumpFaultThunk;\r
  VAR i : integer;\r
      first : boolean;\r
  BEGIN\r
    first := true;\r
    FOR i := FirstExc TO LastExc DO\r
     WITH FaultInfo[i] DO\r
     IF used THEN\r
       BEGIN\r
         IF not first THEN GenCode(iNOOP2);\r
         First := false;\r
         GenerateLabel(FaultThunk);\r
         CodeRegConst(iMOV,b,AL,Number);\r
       END;\r
     IF Not First THEN\r
       BEGIN\r
         CodeRegReg(iXOR,b,AH,AH);\r
         CodeReg(iPOP,w,DX);\r
         CodeReg(iPUSH,w,AX);\r
         CodeReg(iPUSH,w,CS);\r
         CodeReg(IPUSH,w,DX);\r
         CallRoutine(Anonymousspix,Fault,St_Jump);\r
       END;\r
  END;\r
\r
 PROCEDURE PackField(VAR x : Byte; RightPos: integer;\r
                                         FieldValue : integer );\r
      (* The procedure packed the FieldValue into x. The lowest bit\r
         is packed into x at bit possition "RightPos". It is assumed\r
         that the bits in x where fieldvalue is insert is 0   *)\r
\r
      BEGIN\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' START',' PackField ',x,' ',RightPos,' ',\r
                                                         FieldValue);\r
          (*ENDTEST#*)\r
\r
        FieldValue := FieldValue * ShiftFactor[RightPos];\r
        x := ( x + FieldValue) MOD MaxByte;\r
\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' SLUT','  PackField ',x);\r
          (*ENDTEST#*)\r
      END;   (* PackField *)\r
\r
\r
    (* -------------------------------------------------------*)\r
\r
\r
    FUNCTION RegField( r : Register) : integer;\r
      (* The function returns the value of the regfield *)\r
\r
      BEGIN\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' START','  RegField ',ord(r));\r
          (*ENDTEST#*)\r
        RegField := ord(r) MOD ord(AL);\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' SLUT','  RegField ');\r
          (*ENDTEST#*)\r
      END;  (* RegField *)\r
\r
\r
    (* ------------------------------------------------------- *)\r
\r
    PROCEDURE MakeFreeCodeBuffer( No : Integer);\r
      (* The procedure makes at least No bytes free in the codebuffer\r
         That is done by writting to the file TBinFile *)\r
\r
      VAR\r
        i,j,codelength, Diff,iii : integer;\r
        helpbyte : byte;\r
        Lab : St_Address;\r
        Ptr : St_ElemPtr;\r
        WordIndex,help : Word;\r
        DeleteJump : boolean;\r
        Str : ptr_String;\r
        WordByte : RECORD\r
                     CASE Int : integer OF\r
                       1 : (i : Integer);\r
                       2 : (Byte1 : 0..255;\r
                            Byte2 : 0..255);\r
                       3 : (w : Word);\r
                   END;\r
               (* Used to convert a integer/Word to two bytes or two bytes\r
                  to a integer/Word *)\r
\r
\r
      PROCEDURE WriteBytesToTBinFile(No : integer);\r
        VAR\r
          i : integer;\r
        BEGIN\r
          FOR i := 1 TO No DO\r
            BEGIN\r
             (* TURBO\r
              TBinFile^ := CodeBuffer[FirstIndex];\r
              put(TBinFile); *)\r
              PutTBinFile(CodeBuffer[FirstIndex]);\r
              FirstIndex := (FirstIndex + 1) MOD LengthOfCodeBuffer;\r
              NoBytesInBuffer := NoBytesInBuffer - 1;\r
            END;\r
\r
        END;\r
\r
\r
      BEGIN\r
          (*#BEGINTEST\r
             IF TestPass4 > 2 THEN\r
               writeln(TestOutput,' START',' MakeFreeCodeBuffer',No,' ',\r
                                                 NoBytesInBuffer);\r
             IF TestPass4 >= 0 THEN write('.');\r
          (*ENDTEST#*)\r
\r
        WHILE (((InternalOffset - FileOffset) > 130) OR\r
               ((LengthOfCodeBuffer - NoBytesInBuffer) < No)) DO\r
          BEGIN (* write a codeformat to TBinFile *)\r
            codelength := CodeBuffer[FirstIndex];\r
\r
            IF CodeLength <> 0 THEN\r
              BEGIN\r
                WriteBytesToTBinFile(CodeLength + 1);\r
\r
                FileOffset := FileOffset + codelength;\r
              END\r
\r
            ELSE  (* codelength = 0 *)\r
              BEGIN  (* a jump or a label or a  LBDR or a external call*)\r
\r
                FirstIndex := (FirstIndex + 1) Mod LengthOfCodeBuffer;\r
                NoBytesInBuffer := NoBytesInBuffer - 1;\r
\r
                IF ((CodeBuffer[FirstIndex] <> ord(ExternalCall) ) AND\r
                    (CodeBuffer[FirstIndex] <> ord(ExternalJump) ) AND\r
                    (CodeBuffer[FirstIndex] <> ord(ShortJump) ) AND\r
                    (CodeBuffer[FirstIndex] <> ord(NearunCondJump) ) AND\r
                    (CodeBuffer[FirstIndex] <> ord(NearCondJump) ) AND\r
                    (CodeBuffer[FirstIndex] <> ord(RoutineStartStop) )) THEN\r
                  BEGIN  (* not external Call and not a jump *)\r
                    (*TBinFile^ := 0;\r
                      put(TBinFile);*)\r
                    helpbyte := 0;\r
                    putTBinFile(helpbyte);\r
                  END;\r
\r
\r
                CASE CodeFormat(CodeBuffer[FirstIndex]) OF\r
\r
                DeclareLabel:\r
                  BEGIN  (* a label *)\r
                    WriteBytesToTBinFile(1);\r
\r
                    (* Get Label *)\r
                    WordByte.Byte1 := CodeBuffer[FirstIndex] ; \r
                    WordByte.Byte2 := CodeBuffer[(FirstIndex+1) MOD\r
                                              LengthOfCodeBuffer];\r
                    Lab.Va_Low := WordByte.w;\r
                    WordByte.Byte1 := CodeBuffer[(FirstIndex+2) MOD\r
                                              LengthOfCodeBuffer] ; \r
                    WordByte.Byte2 := CodeBuffer[(FirstIndex+3) MOD\r
                                              LengthOfCodeBuffer];\r
                    Lab.Va_High := WordByte.w;\r
\r
\r
                    St_Get(Lab,Ptr);\r
 \r
                    Ptr^.Label_Offset := FileOffset;\r
\r
                    (* write the label to TBinFile *)\r
                    WriteBytesToTBinFile(4);\r
                  END;\r
\r
\r
                RoutineStartStop :\r
                  BEGIN  \r
                    FirstIndex := (FirstIndex + 1) MOD LengthOfCodeBuffer;\r
                    NoBytesInBuffer := NoBytesInBuffer - 1;\r
\r
                    (* Get Routine node *)\r
                    WordByte.Byte1 := CodeBuffer[FirstIndex] ; \r
                    WordByte.Byte2 := CodeBuffer[(FirstIndex+1) MOD\r
                                              LengthOfCodeBuffer];\r
                    Lab.Va_Low := WordByte.w;\r
                    WordByte.Byte1 := CodeBuffer[(FirstIndex+2) MOD\r
                                              LengthOfCodeBuffer] ; \r
                    WordByte.Byte2 := CodeBuffer[(FirstIndex+3) MOD\r
                                              LengthOfCodeBuffer];\r
                    Lab.Va_High := WordByte.w;\r
\r
                    j := CodeBuffer[(FirstIndex+4) MOD\r
                                              LengthOfCodeBuffer];\r
\r
\r
                    St_Get(Lab,Ptr);\r
                    IF Ptr^.St_Kind = cType THEN\r
                      BEGIN\r
                        IF j = 1 THEN (* Start *)\r
                          BEGIN\r
                            Ptr^.T_First_Offset := FileOffset;\r
                            Ptr^.t_Name_Entry_List := LastNameEntry;\r
                          END\r
                        ELSE (* Stop *)\r
                          Ptr^.T_Last_Offset := FileOffset;\r
                      END\r
                    ELSE\r
                      BEGIN\r
                        IF j = 1 THEN (* Start *)\r
                          BEGIN\r
                            Ptr^.First_Offset := FileOffset;\r
                            Ptr^.Name_Entry_List := LastNameEntry;\r
                          END\r
                            \r
                        ELSE (* Stop *)\r
                          BEGIN\r
                            Ptr^.Last_Offset := FileOffset;\r
                            St_Retrieve(Ptr^.St_Label,Ptr);\r
                            WHILE Not Equal_Addr(Ptr^.DefAsLabel,St_NillAddr) DO\r
                              St_Retrieve(Ptr^.DefAsLabel,Ptr);\r
                            help := ptr^.label_offset;\r
                            St_Get(Lab,Ptr);\r
                            Ptr^.First_Offset :=help;\r
                          END;\r
                      END;\r
\r
                    IF j = 1 THEN\r
                      BEGIN\r
                         LastNameEntry := Lab;\r
                         (* update lengthofnametabel *)\r
                         st_NameofSpix(Ptr^.St_Spix,Str);\r
                         LengthOfNameTabel := LengthOfNameTabel + length(Str^)\r
                                                      + 8;\r
                       END;\r
\r
                    FirstIndex := (FirstIndex + 5) MOD LengthOfCodeBuffer;\r
                    NoBytesInBuffer := NoBytesInBuffer - 5;\r
\r
                  END;\r
\r
                LongJump :\r
                  BEGIN\r
                    WriteBytesToTBinFile(4);\r
                    FileOffset := FileOffset + 5;\r
                  END;\r
\r
                LongCall :\r
                  BEGIN\r
                    WriteBytesToTBinFile(5);\r
                    FileOffset := FileOffset + 5;\r
                  END;\r
\r
\r
                LineNo:\r
                  BEGIN\r
                    WriteBytesToTBinFile(3);\r
                  END;\r
\r
\r
                SetCode:\r
                  BEGIN\r
                    WriteBytesToTBinFile(2);\r
                  END;\r
\r
                ContextEnd :\r
                  BEGIN\r
                    WriteBytesToTBinFile(1);\r
                    ContextEndOffset := FileOffset;\r
                  END;\r
\r
\r
                AddLabelToDis :\r
                  BEGIN\r
                    CodeLength := CodeBuffer[(FirstIndex + 1)\r
                                                MOD LengthOfCodeBuffer];\r
\r
                    WriteBytesToTBinFile(CodeLength + 6);\r
                    FileOffset := FileOffset + CodeLength;\r
\r
                  END;\r
\r
\r
\r
\r
                CaseLabList :    (* a case tabel *) \r
                  BEGIN\r
                    (* get the length *)\r
                    WordByte.Byte1 := CodeBuffer[(FirstIndex + 1) MOD\r
                                                           LengthOfCodeBuffer];\r
                    WordByte.Byte2 := CodeBuffer[(FirstIndex + 2) MOD\r
                                                           LengthOfCodeBuffer];\r
          \r
                    (* No of labels in WordByte.w *)\r
                    FileOffset := FileOffset + ( WordByte.w * 2);\r
\r
                    (* write the labels to TBinFile *)\r
                    WriteBytesToTBinFile(11);\r
\r
\r
                  END;\r
\r
\r
\r
\r
                InternalLBDR:\r
                  BEGIN (* A Internal LBDR *)\r
\r
                    LastInternalLBDROffset := FileOffset;\r
\r
                    WriteBytesToTBinFile(LengthOfInternalLBDR + 5);\r
\r
                    FileOffset := FileOffset + LengthOfInternalLBDR;\r
\r
                  END;\r
                \r
\r
\r
                ExternalLBDR:\r
                  BEGIN (* A External LBDR *)\r
                    WriteBytesToTBinFile(LengthOfExternalLBDR + 5);\r
\r
\r
                    FileOffset := LengthOfExternalLBDR;\r
\r
                  END;\r
                \r
\r
\r
\r
                ExternalCall,\r
                ExternalJump :\r
\r
                    BEGIN (* an External call *)\r
                      (*TBinFile^ := 5;\r
                      Put(TBinFile);\r
                      TBinFile^ := OpcodeCallExt;\r
                      Put(TBinFile);*)\r
                      helpbyte := 5;\r
                      PutTBinFile(helpbyte);\r
                      IF CodeFormat(CodeBuffer[FirstIndex]) = ExternalCall\r
                        THEN helpbyte := OpcodeCallExt\r
                        ELSE Helpbyte := OpcodeLongJmp;\r
                      PutTBinFile(helpbyte);\r
\r
                      FOR i := 1 TO 4 DO\r
                        BEGIN\r
                          (*TBinFile^ := 0;\r
                          Put(TBinfile);*)\r
                          helpbyte := 0;\r
                          putTBinFile(helpbyte);\r
                        END;\r
\r
                      FirstIndex := (FirstIndex + 1) Mod LengthOfCodeBuffer;\r
                      NoBytesInBuffer := NoBytesInBuffer - 1;\r
\r
                      WordByte.Byte1 := CodeBuffer[FirstIndex];\r
                      FirstIndex := (FirstIndex + 1) Mod LengthOfCodeBuffer;\r
                      NoBytesInBuffer := NoBytesInBuffer - 1;\r
\r
\r
                      WordByte.Byte2 := CodeBuffer[FirstIndex];\r
                      FirstIndex := (FirstIndex + 1) Mod LengthOfCodeBuffer;\r
                      NoBytesInBuffer := NoBytesInBuffer - 1;\r
\r
\r
                      St_New_FixUpp(WordByte.w,FileOffset + 1,\r
                                   FirstFixUpp,LastFixUpp);\r
\r
                      NoFixUpp := NoFixUpp + 1;\r
\r
\r
                      FileOffset := FileOffset + 5;\r
\r
                    END;\r
\r
\r
\r
                NearUnCondJump, NearCondJump:\r
                  BEGIN  (* a jump *)\r
                    DeleteJump := false; \r
\r
                    IF CodeBuffer[FirstIndex] = ord(NearUnCondJump)\r
                      THEN CodeLength := 3\r
                      ELSE CodeLength := 5;\r
\r
           \r
                    IF( CodeBuffer[(FirstIndex + 1) MOD LengthOfCodeBuffer]\r
                                      <> ord(iCALL)) \r
                    THEN\r
                      BEGIN  (* a near jump\r
                                check if it can be change to a short jump *)\r
\r
\r
                        (* Get Label *)\r
                        WordByte.Byte1 := CodeBuffer[(FirstIndex + 2)\r
                                             MOD LengthOfCodeBuffer];\r
                        WordByte.Byte2 := CodeBuffer[(FirstIndex+3) MOD\r
                                                  LengthOfCodeBuffer];\r
                        Lab.Va_Low := WordByte.w;\r
\r
                        WordByte.Byte1 := CodeBuffer[(FirstIndex + 4)\r
                                             MOD LengthOfCodeBuffer];\r
                        WordByte.Byte2 := CodeBuffer[(FirstIndex + 5) MOD\r
                                                  LengthOfCodeBuffer];\r
                        Lab.Va_High := WordByte.w;\r
\r
\r
                        St_Retrieve(Lab,Ptr);\r
                        WHILE NOT Equal_Addr(Ptr^.DefAsLabel,St_NillAddr) DO\r
                          St_Retrieve(Ptr^.DefAsLabel,Ptr);\r
\r
                        IF Ptr^.Label_Offset <> 0\r
                        THEN\r
                          BEGIN (* The label has been generated *)\r
(* $NoCheck *)\r
                            IF (Ptr^.Label_Offset > FileOffset)\r
                            THEN\r
                              Diff := Ptr^.Label_Offset - CodeLength\r
                                          + 2  - (FileOffset + 2)\r
                            ELSE\r
                              Diff := Ptr^.Label_Offset - (FileOffset + 2);\r
\r
                            IF Diff = 0 THEN\r
                              BEGIN\r
                                (* The jump can be deleted *)\r
                                DeleteJump := true;\r
                                InternalOffset := InternalOffset -\r
                                                CodeLength;\r
                                IF LastJMPOffset <> 0 THEN\r
                                  LastJMPOffset := LastJMPOffset - CodeLength;\r
                                IF LastLabelOffset <> 0 THEN\r
                                  LastLabelOffset := LastLabelOffset -\r
                                                                   CodeLength;\r
                              END\r
                            ELSE\r
                              IF ((-128 <= Diff) AND (Diff <= 127))\r
                              THEN\r
                                BEGIN  (* Near jump can bee short *)\r
                                  InternalOffset := InternalOffset -\r
                                               CodeLength + 2;\r
                                  IF LastJMPOffset <> 0 THEN\r
                                    LastJMPOffset := LastJMPOffset -\r
                                                   CodeLength + 2;\r
                                  IF LastLabelOffset <> 0 THEN\r
                                    LastLabelOffset := LastLabelOffset -\r
                                                               CodeLength + 2;\r
                                  CodeLength := 2;\r
                                  CodeBuffer[FirstIndex] := Ord(ShortJump);\r
                                END;\r
                          END;\r
\r
                      END;\r
\r
\r
                    IF NOT DeleteJump THEN\r
                      BEGIN\r
                        (* write the jump instruction to TBinFile *)\r
\r
                        FileOffset := FileOffset + CodeLength;\r
                        (* TURBO\r
                        TBinFile^:=0;\r
                        Put(TBinFile); *)\r
                        helpbyte := 0;\r
                        PutTBinFile(helpbyte);\r
\r
                        WriteBytesToTBinFile(6);\r
                      END\r
                    ELSE\r
                      BEGIN\r
                        (* delete the jump instruction *)\r
                        FirstIndex := (FirstIndex + 6 ) MOD LengthOfCodeBuffer;\r
                        NoBytesInBuffer := NoBytesInBuffer - 6;\r
                      END;\r
                  END;\r
                \r
\r
\r
                END; (* END Case *)\r
\r
              END;\r
\r
          END; (* end While *)\r
              \r
 \r
\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' SLUT',' MakeFreeCodeBuffer ',Fileoffset);\r
          (*#ENDTEST#*)\r
      END;  (* MakeFreeCodeBuffer *)\r
\r
\r
    (* --------------------------------------------- *)\r
\r
\r
\r
\r
    \r
\r
\r
   (* The following routines is used to insert in the codebuffer *)\r
\r
\r
    PROCEDURE PutCodeBuffer( x : Byte);\r
      (* Puts a byte into the internal buffer. If the buffer is full\r
         write the buffer out on TBinFile *)\r
\r
      BEGIN\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' START','  PutCodeBuffer ',x,' ',\r
                                                        NoBytesInBuffer);\r
          (*ENDTEST#*)\r
\r
        IF NoBytesInBuffer = LengthOfCodeBuffer THEN\r
          MakeFreeCodeBuffer(1);\r
\r
        CodeBuffer[ BufferIndex ] := x;\r
        BufferIndex := (BufferIndex + 1 ) MOD LengthOfCodeBuffer;\r
        NoBytesInBuffer := NoBytesInBuffer + 1;\r
\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' SLUT','  PutCodeBuffer ');\r
          (*ENDTEST#*)\r
      END;  (* PutCodeBuffer *)\r
\r
\r
    (* ------------------------------------------------------- *)\r
\r
\r
\r
    PROCEDURE Put1CodeFormat( x : Byte);\r
       (* Puts a codeformat of length 1 into the internal buffer *)\r
\r
      BEGIN\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' START','  Put1CodeFormat ',x,' ',\r
                                                        NoBytesInBuffer);\r
          (*ENDTEST#*)\r
\r
        IF NoBytesInBuffer + 2 > LengthOfCodeBuffer THEN\r
          MakeFreeCodeBuffer(2);\r
\r
        CodeBuffer[ BufferIndex ] := 1;\r
        BufferIndex := (BufferIndex + 1 ) MOD LengthOfCodeBuffer;\r
        CodeBuffer[ BufferIndex ] := x;\r
        BufferIndex := (BufferIndex + 1 ) MOD LengthOfCodeBuffer;\r
        NoBytesInBuffer := NoBytesInBuffer + 2;\r
\r
        IF ( InternalOffset > (Max_Word - 1)) THEN Fatal_Error(Pass4,4);\r
        InternalOffset := InternalOffset + 1;\r
\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' SLUT','  Put1CodeFormat ');\r
          (*ENDTEST#*)\r
      END;  (* Put1CodeFormat *)\r
\r
\r
\r
\r
    (* ------------------------------------------------------- *)\r
\r
\r
\r
    PROCEDURE Put2CodeFormat( x1, x2 : Byte);\r
       (* Puts a codeformat of length 2 into the internal buffer *)\r
\r
      BEGIN\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' START','  Put2CodeFormat ',x1,' ',x2,' ',\r
                                                        NoBytesInBuffer);\r
          (*ENDTEST#*)\r
\r
        IF NoBytesInBuffer + 3 > LengthOfCodeBuffer THEN\r
          MakeFreeCodeBuffer(3);\r
\r
        CodeBuffer[ BufferIndex ] := 2;\r
        BufferIndex := (BufferIndex + 1 ) MOD LengthOfCodeBuffer;\r
        CodeBuffer[ BufferIndex ] := x1;\r
        BufferIndex := (BufferIndex + 1 ) MOD LengthOfCodeBuffer;\r
        CodeBuffer[ BufferIndex ] := x2;\r
        BufferIndex := (BufferIndex + 1 ) MOD LengthOfCodeBuffer;\r
        NoBytesInBuffer := NoBytesInBuffer + 3;\r
\r
\r
        IF ( InternalOffset > (Max_Word - 2)) THEN Fatal_Error(Pass4,4);\r
        InternalOffset := InternalOffset + 2;\r
\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' SLUT','  Put2CodeFormat ');\r
          (*ENDTEST#*)\r
      END;  (* Put2CodeFormat *)\r
\r
\r
\r
\r
\r
    (* ------------------------------------------------------- *)\r
\r
\r
\r
    PROCEDURE Put3CodeFormat( x1, x2, x3 : Byte);\r
       (* Puts a codeformat of length 3 into the internal buffer *)\r
\r
      BEGIN\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' START','  Put3CodeFormat ',x1,' ',x2,\r
                                        ' ',x3,' ',NoBytesInBuffer);\r
          (*ENDTEST#*)\r
\r
        IF NoBytesInBuffer + 4 > LengthOfCodeBuffer THEN\r
          MakeFreeCodeBuffer(4);\r
\r
        CodeBuffer[ BufferIndex ] := 3;\r
        BufferIndex := (BufferIndex + 1 ) MOD LengthOfCodeBuffer;\r
        CodeBuffer[ BufferIndex ] := x1;\r
        BufferIndex := (BufferIndex + 1 ) MOD LengthOfCodeBuffer;\r
        CodeBuffer[ BufferIndex ] := x2;\r
        BufferIndex := (BufferIndex + 1 ) MOD LengthOfCodeBuffer;\r
        CodeBuffer[ BufferIndex ] := x3;\r
        BufferIndex := (BufferIndex + 1 ) MOD LengthOfCodeBuffer;\r
        NoBytesInBuffer := NoBytesInBuffer + 4;\r
\r
        IF ( InternalOffset > (Max_Word - 3)) THEN Fatal_Error(Pass4,4);\r
        InternalOffset := InternalOffset + 3;\r
\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' SLUT','  Put3CodeFormat ');\r
          (*ENDTEST#*)\r
      END;  (* Put3CodeFormat *)\r
\r
\r
\r
\r
    (* ------------------------------------------------------- *)\r
\r
\r
\r
    PROCEDURE Put4CodeFormat( x1, x2, x3, x4 : Byte);\r
       (* Puts a codeformat of length 4 into the internal buffer *)\r
\r
      BEGIN\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' START','  Put4CodeFormat ',x1,' ',x2,\r
                                          ' ',x3,' ',x4,' ', NoBytesInBuffer);\r
          (*ENDTEST#*)\r
\r
        IF NoBytesInBuffer + 5 > LengthOfCodeBuffer THEN\r
          MakeFreeCodeBuffer(5);\r
\r
        CodeBuffer[ BufferIndex ] := 4;\r
        BufferIndex := (BufferIndex + 1 ) MOD LengthOfCodeBuffer;\r
        CodeBuffer[ BufferIndex ] := x1;\r
        BufferIndex := (BufferIndex + 1 ) MOD LengthOfCodeBuffer;\r
        CodeBuffer[ BufferIndex ] := x2;\r
        BufferIndex := (BufferIndex + 1 ) MOD LengthOfCodeBuffer;\r
        CodeBuffer[ BufferIndex ] := x3;\r
        BufferIndex := (BufferIndex + 1 ) MOD LengthOfCodeBuffer;\r
        CodeBuffer[ BufferIndex ] := x4;\r
        BufferIndex := (BufferIndex + 1 ) MOD LengthOfCodeBuffer;\r
        NoBytesInBuffer := NoBytesInBuffer + 5;\r
\r
        IF ( InternalOffset > (Max_Word - 4)) THEN Fatal_Error(Pass4,4);\r
        InternalOffset := InternalOffset + 4;\r
\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' SLUT','  Put4CodeFormat ');\r
          (*ENDTEST#*)\r
      END;  (* Put4CodeFormat *)\r
\r
\r
\r
  (* ------------------------------------------------------------- *)\r
\r
\r
    PROCEDURE PutR_MOperand(op : byte;VAR  Addr : Address; \r
                                                  Reg : integer);\r
      (* Puts a instruction with operand op and operand of type R_M\r
         into the codebuffer. The operand is given by Addr and the \r
         Regfield by Reg. If the instruction have to be prefixed\r
         this is done  *)\r
\r
      VAR \r
        LengthIndex : integer;\r
        CodeLength : integer;\r
        PreOp : Byte;\r
        LengthOfDisplacement : integer;\r
        R_M, ModField : Byte;\r
\r
\r
      BEGIN\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' START','  PutR_MOperand ',op,' ',Reg);\r
          (*ENDTEST#*)\r
\r
        WITH Addr DO\r
          BEGIN\r
            IF NoBytesInBuffer + 8 > LengthOfCodeBuffer THEN\r
               MakeFreeCodeBuffer(8);\r
               (* make 8 free. No test in PutR_MOpr_AndConst *)\r
\r
            LengthIndex := BufferIndex;\r
            CodeLength := 0;\r
            BufferIndex := (BufferIndex + 1) MOD LengthOfCodeBuffer;\r
\r
            IF (( Seg <> DS) AND (Seg <> SS)) OR \r
                (DSIsChange AND (Addr.Base = RNIL)) THEN\r
              BEGIN  (* The instruction has to be prefixed by Seg *)\r
                IF Seg = DS THEN Seg := SS;\r
                PreOp := OpcodePreFix;\r
                PackField(PreOp, 3, ord(Seg) - ord(ES));\r
                CodeBuffer[BufferIndex] := PreOp;\r
                BufferIndex := (BufferIndex + 1) MOD LengthOfCodeBuffer;\r
                CodeLength := 1;\r
              END;\r
\r
\r
            (* Calculation of the R_MField *)\r
            IF (Index = Rnil) THEN\r
               IF (Base = BX) THEN R_M := $07 (*111B*)\r
                              ELSE R_M := $06 (*110B*)\r
\r
            ELSE\r
              IF (Base = BX) THEN R_M := $00 (*000B*) - ord(SI) + ord(Index)\r
              ELSE\r
                IF (Base = BP) THEN R_M := $02 (*010B*) - ord(SI) + ord(Index)\r
                               ELSE R_M := $04 (*100B*) - ord(SI) + ord(Index);\r
\r
\r
\r
            wordByte.w := Displacement;\r
            (* Calculation of the mod field *)\r
            IF (( Base = RNil) AND (R_M = $06 (*110B*) ))\r
            THEN\r
              BEGIN\r
                ModField := $00;  (* 000B;*)\r
                LengthOfDisplacement := 2;\r
              END\r
            ELSE\r
              BEGIN\r
                IF((-128 <= wordbyte.i) AND (wordbyte.i <= 127))\r
                THEN IF Displacement = 0 THEN LengthOfDisplacement := 0\r
                                    ELSE LengthOFDisplacement := 1\r
                ELSE LengthOfDisplacement := 2;\r
\r
                ModField := LengthOfDisplacement;\r
              END;\r
\r
\r
            PackField(R_M, 3, Reg);\r
            PackField(R_M, 6, ModField);\r
\r
            CodeBuffer[BufferIndex] := Op;\r
            BufferIndex := (BufferIndex + 1) Mod LengthOfCodeBuffer;\r
\r
            CodeBuffer[BufferIndex] := R_M;\r
            BufferIndex := (BufferIndex + 1) MOD LengthOfCodeBuffer;\r
            CodeLength := CodeLength + 2;\r
\r
\r
            IF LengthOfDisplacement = 1 THEN\r
              BEGIN\r
                CodeBuffer[BufferIndex] := WordByte.Byte1;\r
                BufferIndex := (BufferIndex + 1) MOD LengthOfCodeBuffer;\r
              END\r
            ELSE\r
              IF LengthOfDisplacement = 2\r
              THEN\r
                BEGIN\r
                  CodeBuffer[BufferIndex] := WordByte.Byte1;\r
                  BufferIndex := (BufferIndex + 1) MOD LengthOfCodeBuffer;\r
                  CodeBuffer[BufferIndex] := WordByte.Byte2;\r
                  BufferIndex := (BufferIndex + 1) MOD LengthOfCodeBuffer;\r
                END;\r
            CodeLength := CodeLength + LengthOfDisplacement;\r
\r
\r
            CodeBuffer[LengthIndex] := CodeLength;\r
            NoBytesInBuffer := NoBytesInBuffer + CodeLength + 1;\r
\r
            IF ( InternalOffset > (Max_Word - CodeLength)) THEN Fatal_Error(Pass4,4);\r
            InternalOffset := InternalOffset + CodeLength;\r
\r
          END; (* With Addr *)\r
\r
\r
\r
\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' SLUT','  PutR_MOperand');\r
          (*ENDTEST#*)\r
      END; (* PutR_MOperand *)\r
\r
\r
    (* --------------------------------------------------------- *)\r
\r
\r
    PROCEDURE PutR_MOprAndConst(op : Byte; VAR Addr : Address; Reg : integer;\r
                            InstType : InstrucType; Value : Word );\r
      (* The procedure puts a instruction with opcode op and one \r
         operand of type R_M and one of type const into the codebuffer.\r
         The first operand is given by addr (RegField by Reg ) and\r
         the secend operand by value (InstType tells if byte or word)*)\r
\r
      VAR\r
        LengthIndex, CodeLength : integer;\r
\r
      BEGIN\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' START',' PutR_MOprAndConst ',op,' ',Reg,\r
                           ' ',ord(InstType),' ',Value);\r
          (*ENDTEST#*)\r
        LengthIndex := BufferIndex;\r
\r
        PutR_MOperand(op,Addr,Reg);\r
\r
        WordByte.w := Value;\r
\r
        IF InstType = b\r
        THEN\r
          BEGIN\r
            CodeBuffer[BufferIndex] := WordByte.Byte1;\r
            BufferIndex := (BufferIndex + 1) MOD LengthOfCodeBuffer;\r
            CodeLength := 1;\r
          END\r
        ELSE\r
          BEGIN\r
            CodeBuffer[BufferIndex] := WordByte.Byte1;\r
            BufferIndex := (BufferIndex + 1) MOD LengthOfCodeBuffer;\r
            CodeBuffer[BufferIndex] := WordByte.Byte2;\r
            BufferIndex := (BufferIndex + 1) MOD LengthOfCodeBuffer;\r
            CodeLength := 2;\r
          END;\r
\r
        CodeBuffer[LengthIndex] := CodeBuffer[LengthIndex] +\r
                                                    CodeLength;\r
\r
        IF ( InternalOffset > (Max_Word - CodeLength)) THEN Fatal_Error(Pass4,4);\r
        InternalOffset := InternalOffset + CodeLength;\r
        NoBytesInBuffer := NoBytesInBuffer + CodeLength;\r
\r
\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' SLUT','  PutR_MOprAndConst');\r
          (*ENDTEST#*)\r
      END;  (* PutR_MOprAndConst *)\r
\r
\r
    (* ------------------------------------------------------------ *)\r
\r
\r
\r
\r
    (* The following routines is used to print operands to symbolic\r
       code *)\r
\r
\r
    PROCEDURE PrintReg(r : Register; InstType : InstrucType);\r
      (* The procedure prints the register r *)\r
 \r
      BEGIN\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' START',' PrintReg ',ord(r),' ',\r
                                                     ord(InstType));\r
          (*ENDTEST#*)\r
\r
        CASE r OF\r
 \r
          AX : IF ((InstType = w) OR (InstType = vw))\r
               THEN write(TSymFile,'AX')\r
               ELSE write(TSymFile,'AL');\r
 \r
          BX : IF ((InstType = w) OR (InstType = vw))\r
               THEN write(TSymFile,'BX')\r
               ELSE write(TSymFile,'BL');\r
 \r
          CX : IF ((InstType = w) OR (InstType = vw))\r
               THEN write(TSymFile,'CX')\r
               ELSE write(TSymFile,'CL');\r
 \r
          DX : IF ((InstType = w) OR (InstType = vw))\r
               THEN write(TSymFile,'DX')\r
               ELSE write(TSymFile,'DL');\r
 \r
          AL : write(TSymFile,'AL');\r
\r
          BL : write(TSymFile,'BL');\r
\r
          CL : write(TSymFile,'CL');\r
\r
          DL : write(TSymFile,'DL');\r
\r
          AH : write(TSymFile,'AH');\r
\r
          BH : write(TSymFile,'BH');\r
\r
          CH : write(TSymFile,'CH');\r
\r
          DH : write(TSymFile,'DH');\r
\r
          SI : write(TSymFile,'SI');\r
\r
          DI : write(TSymFile,'DI');\r
\r
          SP : write(TSymFile,'SP');\r
 \r
          BP : write(TSymFile,'BP');\r
\r
          ES : write(TSymFile,'ES');\r
 \r
          CS : write(TSymFile,'CS');\r
\r
          SS : write(TSymFile,'SS');\r
 \r
          DS : write(TSymFile,'DS');\r
\r
          Rnil : write(TSymFile,'Rnil');\r
\r
        END; (* End case *)\r
\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' SLUT','  PrintReg');\r
          (*ENDTEST#*)\r
      END; (* PrintReg *)\r
\r
\r
    (* ---------------------------------------------------- *)\r
\r
\r
    PROCEDURE PrintAddr(VAR Addr : Address);\r
      (* Print Addr *)\r
\r
      VAR\r
        i : integer;\r
        Str : ptr_String;\r
        PreFix : Boolean;\r
          (* indicates if the address has to be prefixed by a segment register *)\r
\r
      BEGIN\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' START','  PrintAddr');\r
          (*ENDTEST#*)\r
\r
        WITH Addr DO\r
          BEGIN\r
            IF ((Addr.Seg <> DS) AND (Addr.Seg <> SS)) \r
                OR ( DSISChange AND ( Addr.Base = RNil) ) THEN PreFix := True\r
            ELSE                            \r
              IF ((Addr.Base = RNil) AND (Addr.Index = RNil)) THEN\r
                PreFix := true\r
              ELSE\r
                PreFix := false;\r
\r
            IF PreFix THEN\r
              BEGIN\r
                PrintReg(Seg,w);\r
                write(TSymFile,': ');\r
              END;\r
\r
            IF Base <> Rnil THEN\r
              BEGIN\r
                write(TSymFile,'[');\r
                PrintReg(Base,w);\r
                write(TSymFile,'] ');\r
              END;\r
\r
            IF Spix <> Anonymousspix THEN\r
              BEGIN\r
                St_NameOfSpix(Spix,Str);\r
                For i := 1 To length(Str^) DO\r
                  write(TSymFile,Str^[i]);\r
                write(TSymfile,'(=',Displacement,')');\r
              END\r
            ELSE\r
              IF Displacement <> 0 THEN\r
                write(TSymFile,Displacement,' ');\r
 \r
            IF Index <> Rnil THEN\r
              BEGIN\r
                write(TSymFile,'[');\r
                PrintReg(Index,w);\r
                write(TSymFile,']');\r
              END;\r
          END;  (* End With *)\r
\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' SLUT','  PrintAddr');\r
          (*ENDTEST#*)\r
      END;  (*  PrintAddr *)\r
\r
\r
\r
\r
  (* ------------------------------------------------------ *)\r
\r
\r
\r
    (* ---------------------------------------------------------- *)\r
\r
\r
\r
\r
\r
    PROCEDURE DumpConst(ConstAddr : St_Address );\r
      (* the structured constant given by ConstAddr is dumped in the code *)\r
      VAR\r
        Ptr : St_elemPtr;\r
        More : boolean;\r
        i , No : word;\r
        Length , index : word;\r
        ch : char;\r
\r
      BEGIN\r
        More := true;\r
        While More Do\r
          BEGIN\r
            St_Retrieve(ConstAddr,Ptr);\r
            Length := Ptr^.St_Size;\r
  \r
            IF ( InternalOffset > (Max_Word - Length)) THEN\r
              Fatal_Error(Pass4,4);\r
            More := Not Ptr^.St_ListEnd;\r
            ConstAddr := Ptr^.ListRef;\r
            Index := 0;\r
            WHILE Length > 0 DO\r
              BEGIN\r
                IF Length > 10 THEN No := 10\r
                               ELSE No := Length;\r
                Length := Length - No;\r
                PutCodeBuffer(No);\r
                FOR i := (index + 1) TO (No + index) DO\r
                  PutCodeBuffer(Ptr^.Data_area[i]);\r
                InternalOffset := InternalOffset + No;\r
     \r
                IF CodeOn THEN\r
                  BEGIN\r
                    FOR i := (index + 1) TO (No + index) DO\r
                      BEGIN\r
                        ch := chr(Ptr^.Data_area[i]);\r
                        IF (( ord(' ') > ord(ch)) OR (ord(ch) > ord('}'))) \r
                          THEN ch := '.';\r
    \r
                        write(TSymFile,ch)\r
                      END;\r
                    Writeln(TSymFile);\r
                  END;\r
\r
                index := index + No;\r
              END;\r
          END;\r
      END; (* DumpConst *)\r
\r
    (* ---------------------------------------------------------- *)\r
\r
\r
\r
    PROCEDURE DumpCaseTabel(CaseTab : St_Address; Size : Word;\r
                                               OtherwiseLab : St_Address);\r
      (* The casetabel is generated *)\r
\r
      VAR\r
        Lab : St_Address;\r
        Index : integer;\r
      BEGIN\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' START','  DumpCaseTabel');\r
          (*ENDTEST#*)\r
\r
        PutCodeBuffer(0);\r
        PutCodeBuffer(ord(CaseLabList));\r
\r
        WordByte.w := Size;\r
        PutCodeBuffer(WordByte.Byte1);\r
        PutCodeBuffer(WordByte.Byte2);\r
\r
\r
        WordByte.w := CaseTab.Va_Low;\r
        PutCodeBuffer(WordByte.Byte1);\r
        PutCodeBuffer(WordByte.Byte2);\r
        WordByte.w := CaseTab.Va_High;\r
        PutCodeBuffer(WordByte.Byte1);\r
        PutCodeBuffer(WordByte.Byte2);\r
\r
        WordByte.w := OtherwiseLab.Va_Low;\r
        PutCodeBuffer(WordByte.Byte1);\r
        PutCodeBuffer(WordByte.Byte2);\r
        WordByte.w := OtherwiseLab.Va_High;\r
        PutCodeBuffer(WordByte.Byte1);\r
        PutCodeBuffer(WordByte.Byte2);\r
\r
        IF ( InternalOffset > (Max_Word - (Size * 2))) THEN\r
          Fatal_Error(Pass4,4);\r
\r
        InternalOffset := InternalOffset + (Size * 2);\r
\r
          (*#BEGINTEST\r
             IF TestPass4 >= 10 THEN\r
               writeln(TestOutput,' SLUT','  DumpCaseTabel');\r
          (*ENDTEST#*)\r
      END;  (* DumpCaseTabel *)\r
\r
\r
\r
\r
    (*------------------------------------------------------------------*)\r
\r
\r
       PROCEDURE NewLine(Line : Word);\r
         BEGIN\r
           IF CodeOn or LineTabel THEN\r
             BEGIN\r
               PutCodeBuffer(0);\r
               PutCodeBuffer(ord(LineNo));\r
               WordByte.w := Line;\r
               PutCodeBuffer(WordByte.Byte1);\r
               PutCodeBuffer(WordByte.Byte2);\r
             END;\r
         END;\r
\r
\r
     (*------------------------------------------------------------------- *)\r
\r
\r
\r
\r
       PROCEDURE SetCodeTo(Bool : Boolean);\r
         BEGIN\r
           PutCodeBuffer(0);\r
           PutCodeBuffer(ord(SetCode));\r
           IF Bool THEN PutCodeBuffer(SourceNumber)\r
                   ELSE PutCodeBuffer(255);\r
           CodeOn := Bool;\r
         END;\r
\r
\r
\r
\r
    Procedure ContextStop;\r
      (* The procedure is called when leaving context. Only used when\r
         making linetabel *)\r
      BEGIN\r
         PutCodeBuffer(0);\r
         PutCodeBuffer(ord(ContextEnd));\r
      END;\r
\r
\r
    Procedure RoutineDecl(Symbol : St_Address; start : boolean );\r
       (* the routine is called when making a routine, program or a familie\r
          declaration. Only used when making nameentry *)\r
      BEGIN\r
        PutCodeBuffer(0);\r
        PutCodeBuffer(ord(RoutineStartStop));\r
\r
        WordByte.w := Symbol.Va_Low;\r
        PutCodeBuffer(WordByte.Byte1);\r
        PutCodeBuffer(WordByte.Byte2);\r
        WordByte.w := Symbol.Va_High;\r
        PutCodeBuffer(WordByte.Byte1);\r
        PutCodeBuffer(WordByte.Byte2);\r
        IF Start THEN PutCodeBuffer(1) ELSE PutCodeBuffer(0);\r
          \r
      END;\r
\r
\r
   PROCEDURE MakeLongCall(Symbol : St_Address);\r
     BEGIN\r
       PutCodeBuffer(0);\r
       PutCodeBuffer(Ord(LongCall));\r
       (* Put Label *)\r
\r
        WordByte.w := Symbol.Va_Low;\r
        PutCodeBuffer(WordByte.Byte1);\r
        PutCodeBuffer(WordByte.Byte2);\r
        WordByte.w := Symbol.Va_High;\r
        PutCodeBuffer(WordByte.Byte1);\r
        PutCodeBuffer(WordByte.Byte2);\r
\r
        IF InternalOffset > (Max_Word - 5) THEN Fatal_Error(Pass4,4);\r
        InternalOffset := InternalOffset + 5;\r
     END;\r
\r
   PROCEDURE DumpRoutineTabel;\r
     VAR Ptr : St_ElemPtr;\r
         Symb : Ptr_Symbol_Chain;\r
         i : integer;\r
     BEGIN\r
       Symb := Segment_Info[CurrentSegNo].List;\r
       FOR i := 1 TO Segment_Info[CurrentSegNo].No_Of_Symbol DO\r
         BEGIN\r
           St_Retrieve(Symb^.Symbol,Ptr);\r
           (* No Optimize *)\r
           LastLabelOffset := 0;\r
           LastJmpOffset := 0;\r
          \r
           CodeJump(iJMP,Ptr^.St_Label);\r
           Symb := Symb^.Next;\r
         END;\r
       (* Make sure that all jumps are 3 bytes jumps *)\r
       LastJmpOffset := 0;\r
       MakeFreeCodeBuffer(LengthOfCodeBuffer);\r
     END;\r
\r
\r
   PROCEDURE MakeJumpToNextSegment;\r
     BEGIN\r
       PutCodeBuffer(0);\r
       PutCodeBuffer(Ord(LongJump));\r
       PutCodeBuffer(CurrentSegNo + 1);\r
       WordByte.w := LengthOfExternalLBDR + (Segment_Info[CurrentSegNo + 1].\r
                                 No_Of_Symbol * 3);\r
       PutCodeBuffer(WordByte.Byte1);\r
       PutCodeBuffer(WordByte.Byte2);\r
    \r
\r
       IF InternalOffset > (Max_Word - 5) THEN Fatal_Error(Pass4,4);\r
       InternalOffset := InternalOffset + 5;\r
     END;\r
\r
\r
\r
    (* --------------------------------------------------- *)\r
{$I p4code1}\r
\r
END\r
  .\r
\r
\r
\r
\r
  (* -------- PRIVATE CODEGENERATOR  ----------- CODEGENERATOR --*)\r
\r
\r
\r
\r
\r
«eof»