!*********************************** !* WARNING * !* An extra null string has been * !* added to the PRIM ID array to * !* get rid of an obscure bug * !* which shows up in the following * !* trivial Pascal program when * !* compiled with all checks: * !* * !* program f; * !* var a:array[1..100] of integer * !* begin * !* end. * !*********************************** {###################################} {# Copyright (C) 1987 #} {# 3L Limited #} {# Scotland #} {# #} {# All rights reserved #} {###################################} {Pass3 for ARM compiler} ! Bugs: ! 1. Record diagnostics are currently global to the whole file; ! they need to be made block-local so that they can be removed ! when the containing block is unused. %externalstring(3) P3 Version = "002" %constinteger AOF Version = 150 ! ! Revision history ! 002 22-Jun-88 PSR Converted to run native on an A310 ! Changed strings for diags to 127 from 3 ! 001 4-FEB-88 PSR Started inserted support for ARM Debugger ! - Removed Position-independent bit from Code area definition ! 21-aug-86 AET corrected static initialisation of char pointer variables ! in C. ! ! 0.3 22-jul-86 PSR corrected absorb jumps in the case: if a & b then c else d ! 25-jun-86 AET changed pass3 to create output file in new ARM format ! using a similar method as in the P.E. pass3. ! ! 0.2 26-Mar-86 PSR changed module info to be relative to start of info ! rather than each element self-relative. ! - made line tables default code increment to 4 (was 1) ! - changed processing of if then else to include ! calls and return + increased the range slightly ! 24-Mar-86 PSR Released to Acorn ! 0.1 15-FEB-86 PSR cloned from M68K Version 2.6 %from IMP %include HEAP %externalintegerfnspec Encoded Value %externalroutinespec Dump Encoded(%integer N) %externalroutinespec Open Object File(%integer Size) %externalstring(7)%spec P1 Version, P2 Version %externalstring(31)%spec Product Code, Version, Release, Revision %externalintegerspec Debug Options %alias "3L_DEBUG_OPTIONS" %constinteger W = 4 {Bytes per word} %owninteger Current Line = 0 %from IMP %include Interfac, Option3l, Stream3l, Spec3l, Attr, Comm23 %externalroutine PASS 3(%record(CommFm)%name Interface) %integer Options = Interface_Options, {001} DEBUG = Options&LL Debug {001} %recordformatspec Blockfm %recordformat Itemfm(%record(Itemfm)%name Link, %integer Ca, (%byte Cond, Type, %short Flags %or %byte Prim %or %byte X1, X2, %short Ahead %or %byte Args), (%record(Itemfm)%name Label %or %record(Blockfm)%name Head %or %short Lb, Ub %or %integer Value)) {Item Types} %constinteger Label Type = 0, Return Type = 1, Array Disp Type = 3, External Type = 5, Addr Type = 6, Caddr Type = 8, Cload Type = 9, Rload Type = 10, Sload Type = 11, xThunk Type = 12 %constinteger Type Bias = 13 %constinteger Branch Type = Type Bias+0,{these types have valid LABEL fields} Call Type = Type Bias+1, Prim Type = Type Bias+2, Disp Type = Type Bias+4, Jump Type = Type Bias+6, Thunk Type = Type Bias+7, Final Type = Type Bias+7 {Block flags} %constinteger Used = 16_ 0 01, No Entry = 16_ 1 00, Ext Flag = 16_ 4 00, Displ Flag = 16_ 8 00 {Item flags} %constinteger Conditional = 1<<0, Long = 1<<1, VeryLong = 1<<2, Minimum = 1<<3, Deleted = 1<<7, Marked = 1<<8, Duplicated = 1<<9, Forward = 1<<10, Label Used = 1<<11, Absorbed = 1<<12, Referenced = 1<<13 %recordformat Xfm(%integer Disp, {entry disp from start of global area} %integer Flags, {string index<<8 ! flags} %integer Value, {entry value for definitions} %string(31) Text) %const %integer Ext Defn = 1<<0, Ext Code = 1<<1, Ext Prim = 1<<2, Ext Allocated = 1<<5, Ext Dumped = 1<<6 %recordformat Usefm(%record(Usefm)%name Link, %record(Xfm)%name X) %constrecord(Usefm)%name UsefmType == 0 %ownrecord(Usefm)%name Total Uses == 0 %owninteger Main Program = 0, String Size = 4, {skip initial string-table size} User String Base = 0, SymTsize, ActiveSize, Total Size, Header Size %ownstring(31) Main Entry Id {IMP___ENTRY_POINT or PASCAL___ENTRY_POINT} %recordformat Blockfm( - %record(Itemfm)%name Label, Items, %byte Pregs, Return, %integer Flags, Attr, Display, Event Mask, Event Label, Event Body, Ca, Body, Code Size, Code Base, Line Size, Line Base, Diag Size, Diag Base, Frame, Pframe, %record(Xfm)%name X, %record(Usefm)%name Uses, %record(Blockfm)%name Link) %include "inc.DEBUG" {001} %include "inc.DEBUGFM" %constbytearray Inverse(0:23) = 7, 6, 5, 4, 3, 2, 1, 0, 9, 8, 0, 16, 15, 14, 13, 12, 11, 10, 19, 18, 21, 20, 23, 22 %owninteger Ip = 0, {item poiter} Bp = 0 {block pointer} %integer Other Basis = 0, {these are global to all blocks} Record Basis = 0, Global Basis = 0, Bugs Basis = 0 %constinteger CSeg = 0, DSeg = 1, Bseg = 2 {001} %integer Code Size, Data Size, Bugs Size = 0 {001} %integer Files Size = 0, NN {The following are displacements into the string table} %constinteger CodeArea = 16_04, DataArea = 16_0E, DbugArea = 16_18, {001} FreeArea = 16_22 %constinteger CSym = 0, DSym = 1, BSym = 2, ESym = 3 {Bases for constant and global areas, note that code base is local to dump} {block as the code size isn't known to Pass2 so code is divided into a} {number of local areas, 1 per block} %owninteger Min SB = 0, Max SB = 0 ! Sb ! | ! Min SB - - - - * + + + + Max SB ! | | | ! v v v ! *----------*-*-------------* ! | | | | ! *----------*-*-------------* %owninteger Bias = 0, Reloc = 0, Xreloc = 0, Record Size = 0, Number of Blocks = 0, Start Point = -1, Ep %recordformat Linefm(%integer Ca, Last Ca, Line, Last Line, Pending) %recordformat Areafm(%integer Code, Constant, Block, Line, Diag, Record, Global, Global Array) %ownintegername Ca == 0 {is pointed into Area Base} %owninteger Previous Ca = 0 %record(Itemfm) %array Items(0:Interface_Total Items) %record(Blockfm)%array Blocks(0:Interface_Total Blocks) %short %array Formpt(1:Interface_Total Formats) %record(Xfm) %array External(0:Interface_Total Externals) NN = Interface_Total Formats NN = 1 %if Debug = 0 %record(DFormatPFm)%array DebugFm(1:NN) %record(Blockfm)%name Block List == Nil, Main Head == Nil, Entry Head == Nil %record(Xfm)%name Entry X == NIL %owninteger Max External = 0 %owninteger Xentry = 0, Xentry Base = 0, Extra Base = 0 {Prim data} %constinteger Last Prim = 57 {*****see top comment about null string ***} %constinteger Sw Jump = 4, {**** known in PRIM file ****} Sw Error = 24, {disp of error in SWJUMP routine} Enter Prim = 55 {prim number of ENTER} %conststring(9)%array Prim Id(1:Last Prim) = { 1} "SIGNAL", "CSCOMP", "SRES", "SWJUMP", "INTEXP", { 6} "REALEXP", "GENMOVE", "SCONC", "SCOMP", "SJAM", {11} "SETIN", "RESFLOP", "TESTNIL","MAKELOCAL", "AREF", {16} "DYNRANGE", "DYNAMICN", "FRAG1","RTMONITOR", "SETBIT", {21} "CAPTEST", "ASSTEST", "LTRACE", "FRAG2", "CLEARBIT", {26} "TESTNEW", "TESTNIL", "SETBITS", "SETADD", "SETSUB", {31} "SETINTER", "SETGE", "RANGE", "TESTMOD", "CLEARBITS", {36} "TESTVAR", "PRIMMUL", "PRIMDIV", "TESTREAL", "PRIMCOMP", {41} "REALINTPT", "MODULUS","DYNAMIC1", "DYNAMIC2", "PSYM", {46} "SETRANGE", "READCH", "NEXTCH", "PRIMUDIV", "SETZERO", {51} "SETEQUAL", "REALINT", "REALRND", "CALLP", "ENTERP", {56} "DALLOC", "" %ownintegerarray Prim Map(1:Last Prim) = 0(*) %ownbytearray Prim Used(1:Last Prim) = 0(*) %ownstring(63) Block Id = "" %string(127) Included File = "", Swork %ownrecord (Areafm) Area size = 0 {area sizes} %ownrecord (Areafm) Area base = 0 {area base addresses} %ownrecord(Procedurefm) Debug Base {001} %owninteger Total Debug List = 0 {001} %ownrecord(DvarFm)%name DGlobals == 0 %ownrecord(DformatFm)%name Fglobals == 0 %ownrecord(Filefm)%name DebugF == 0, DebugFiles == 0 %routine CSR(%string(255) Why) %routine Err(%integer Stream) Select Output(Stream) Printstring("Pass 3 fails -- ".Why) Printstring(" at line"); Write(Current Line, 1) %if Included File # "" %start Printstring(" in include file ") Printstring(Included File) %finish Newline %end Err(Listing) {listing} Err(Report) {terminal} %monitor %stop %end %routine A Error(%integer Ca, Lim) CSR("Address error CA:".ItoS(Ca, 0)." Lim:".ItoS(Lim, 0)) %end %routine Show Code(%integer N) Select Output(Report) Printstring("Code:") Write(N, 0) Newline Select Output(Object Out) %end %routine Warn(%string(255) What) Select Output(Report) Printstring("Warning -- ".What) Printstring(" at line "); Write(Current Line, 0) Newline Select Output(Object Out) %end %integerfn Padded(%string(*)%name S) %result = (Length(S)+1+3)&(\3) %end %routine Set Debug Line(%integer Ca, Line) %record(DlineFm)%name L, X %return %if Debug = 0 {build a circular line-number list} L == DebugF_Frag_Lines {pointer to LAST entry} %if L == NIL %start {first line} X == NEW(DlineFmType) X_Line = Line X_Ca = Ca X_Link == X DebugF_Frag_Lines == X %else %if L_Ca = Ca {no code generated since last line} L_Line = Line {just overwrite the line number} %else {add a new line item} X == NEW(DlineFmType) X_Line = Line X_Ca = Ca X_Link == L_Link {forward pointer} L_Link == X DebugF_Frag_Lines == X %finish %end %record(Filefm)%map New Debug File %record(Filefm)%name F F == NEW(FilefmType) F_Frag == NIL F_Flink == NIL F_Link == DebugFiles DebugFiles == F %result == F %end %routine Debug New Fragment(%integer Ca, Line) %record(FragmentFm)%name Fr %return %if Debug = 0 Fr == DebugF_Frag %if Fr == NIL %or Fr_From <= Fr_To %start {get a new one or overwrite} Fr == NEW(FragmentFmType) Fr_Link == DebugF_Frag DebugF_Frag == Fr %finish Fr_Code = Ca; Fr_CodeSize = 0 Fr_From = Line; Fr_To = 0 Fr_Lines == NIL Set Debug Line(Ca, Line) %end %routine Debug Terminate Fragment(%integer Ca, Line) %record(FragmentFm)%name Fr %record(Dlinefm)%name L %return %if Debug = 0 %return %if DebugF == NIL Fr == DebugF_Frag Fr_To = Line Fr_CodeSize = Ca-Fr_Code L == Fr_Lines %if L ## NIL %start {break the loop} Fr_Lines == L_Link {point to the first one} L_Link == NIL {and terminate the list} %finish %end %routine Debug Include(%string(255) File, %integer Ca, Line) %record(Filefm)%name F %return %if Debug = 0 %if File # "" %start {going into a new include file} Debug Terminate Fragment(Ca, Current Line-1) F == New Debug File F_File == Heap String(File) F_Flink == DebugF DebugF == F %else {leaving an include file} Debug Terminate Fragment(Ca, Current Line) DebugF == DebugF_Flink %finish Debug New Fragment(Ca, Line) %end {object format control items} %recordformat Symbolfm(%integer Name, Value, %byte Area, Attributes, %record(SYmbolfm)%name Link) %constrecord(Symbolfm)%name SymbolfmType == 0 %integer Symbol Entry No = -1 %record(Symbolfm) Symbol Base %record(Symbolfm)%name Symbol List == Symbol Base %integerfn Symbol Entry(%integer Name, Attributes, Value, Area) %record(Symbolfm)%name S == NEW(SymbolfmType) S_Name = Name S_Value = Value S_Area = Area S_Attributes = Attributes Symbol List_Link == S Symbol List == S Symbol Entry No = Symbol Entry No+1 %result = Symbol Entry No %end %recordformat Relocfm(%integer Vaddr, Code, %record(Relocfm)%name Link) %constrecord(Relocfm)%name Relocfm Type == 0 %constinteger SymbolReloc = 2_1010, PcReloc = 2_0110 %recordformat SegmentRfm(%record(Relocfm)%name R, %integer Entries, Base) %record(SegmentRfm)%array Segment Reloc(Cseg:Bseg) %owninteger Current Address = 0, Current Limit = 0 %ownintegerarray Segment Base(Cseg:Bseg) = 0, 0, 0 %ownintegerarray Segment Limit(Cseg:Bseg) = 0, 0, 0 %routine Dump String(%string(255) S) %integer N String(Current Address) = S N = Length(S)+1 Current Address = Current Address + N %if Current Address > Current Limit %start A Error(Current Address, Current Limit) %finish Ca = Ca+N %end %routine Select(%integer Segment, Displacement) {Segment is either CSeg or DSeg} Current Address = Segment Base(Segment) + Displacement Current Limit = Segment Limit(Segment) %if Displacement < 0 %or Current Address > Current Limit %start A Error(Current Address, Current Limit) %finish {permit selecting a NULL area} %end %routine Select Global Area(%integer Bias) Ca == Global Basis Ca = Area Base_Global + Bias Select(DSeg, Ca - Min SB) %end %routine Get String(%string(*)%name S, %integer Limit) %integer Sym, L Readsymbol(L) S = "" %while L > 0 %cycle L = L-1 Readsymbol(Sym); S = S.Tostring(Sym) %unless Length(S) = Limit %repeat %end %routine Put String(%string(255) S) %integer P Printsymbol(Length(S)) Printsymbol(Charno(S,P)) %for P = 1, 1, Length(S) %end %routine Skip Bytes(%integer N) %while N > 0 %cycle N = N-1; Skipsymbol %repeat %end %integerfn Displacement Size(%integer N) %result = 1 %if 16_FFFF FFC0 <= N <= 16_0000 003F %result = 2 %if 16_FFFF E000 <= N <= 16_0000 1FFF %result = 4 %end %routine Input Block(%integer Block Label, Level) %switch D(1: Max Dir) {002} %record(Blockfm)%name Head %record(Itemfm) Base %record(Itemfm)%name Item, Terminal == Base, Basep %integer Code, N, Q, Label, Lb, Ub, Needs %integer Diag Size, Record Diags = 0 %integer Diag Inc %integer Line Size, Local Code Base, Dummy Code Base = 0 {These are used to guestimate the size of the line-number table} {Last Ca is moved back whenever a stretchable object is defined} {This should overestimate the size of the line area, which is safe} {The line table is of the form: } { [nnnnnn00] 6-bit code increment} { [nnnnnn10] 6-bit line increment} { [nnnnnnnn] [nnnnnn01] 14-bit code increment} { [nnnnnnnn] [nnnnnn11] 14-bit line increment} %record(Xfm)%name X %record(Linefm) Line Info = 0 %integer D1, D2 %routine Allocate Line Diag %integer N, C Line Info_Line = Current Line Line Info_Ca = Ca N = Line Info_Line - Line Info_Last Line C = Line Info_Ca - Line Info_Last Ca-1 %if N > 0 %and C > 0 %and Options&LL Lines # 0 %start Line Info_Last Line = Line Info_Line Line Info_Last Ca = Line Info_Ca Line Size = Line Size+1 Line Size = Line Size+1 %if C >= 64 {too big, needs a reset} %if N # 1 %start {needs an explicit increment} N = N-2 Line Size = Line Size+1 Line Size = Line Size+1 %if N >= 64 {needs a big increment} %finish %finish %end %routine Alloc Diag %integer L, F, Key, N, Type, Xtype %string(127) S {002} Get String(S, 127); L = Length(S) Key = Encoded Value; Type = Key>>2&15 Xtype = Encoded Value N = Encoded Value %if Key = 0 %start {enumerated name} L = L+1 %else L = L+1 {string size} +1 {key} +Displacement Size(N) %if Key&64 # 0 %start {format follows} F = Encoded Value L = L+2 %finish L = L+1 %if Xtype # 0 %finish %if Record Diags = 0 %then Diag Inc = Diag Inc+L - %else Record Size = Record Size+L %end %record(Itemfm)%map New Item(%integer Type) %record(Itemfm)%name P Ip = Ip+1; P == Items(Ip) P_Type = Type P_Ca = Ca P_Flags = 0 Terminal_Link == P Terminal == P Line Info_Last Ca = Line Info_Last Ca-3 {assume the worst} %result == P %end %routine Set Prim(%integer N) %record(Itemfm)%name Item Item == New Item(Prim Type) Ca = Ca+4 Item_Flags = Minimum Item_Prim = N; Prim Used(N) = 1 %end %routine Add Use(%integer Xn) %record(Usefm)%name U %record(Xfm)%name X X == External(Xn) U == Head_Uses %while U ## Nil %cycle %return %if U_X == X U == U_Link %repeat U == NEW(UsefmType) U_X == X U_Link == Head_Uses; Head_Uses == U %end Line Info_Line = Current Line; Line Info_Last Line = Current Line Line Info_Ca = 0; Line Info_Last Ca = 0 Ca == Local Code Base {revert to code area} Ca = 0 {start at the beginning} Bp = Bp+1; Head == Blocks(Bp); Head = 0 Head_Label == Items(Block Label); Head_Label = 0 Head_Label_Head == Head Head_Link == Block List %and Block List == Head %unless Level < 0 {remove} Line Size = 0 {unwanted} Diag Size = 4 + Length(Block Id)+1 {blocks} Diag Inc = 0 Needs = 0 %cycle Readsymbol(Code) %unless 1 <= Code <= Max Dir %start {002} D(*): CSR("Corrupt p1 directive".ItoS(Code, 1)) %finish Show Code(Code) %if Options&LL Mon # 0 ->D(Code) {******** Debugger Support ********} D(Dir DEBUG Start Proc): D1 = Encoded Value {Type} {001} D2 = Encoded Value {Sourcepos} {001} %continue {001} {001} D(Dir DEBUG End Proc): D2 = Encoded Value {Sourcepos} {001} %continue {001} {**********************************} D(Dir Start Block): N = Encoded Value+Reloc Get String(Block Id, 127) {002} Input Block(N, Level+1) Ca == Local Code Base %continue D(Dir Diag): Alloc Diag; %continue D(Dir DEBUG Var): %begin %integer N %string(255) S Get String(S, 255) N = Encoded Value {Primary type} N = Encoded Value {Indirect bit} N = Encoded Value {Base: 1=Local, 2=Static} N = Encoded Value {BaseType} N = Encoded Value {PointerType} N = Encoded Value {Displacement} N = Encoded Value {Format} N = Encoded Value {Size} %end %continue D(Dir DEBUG Array): %begin %integer N %string(255) S Get String(S, 255) N = Encoded Value {Lower bound} N = Encoded Value {Upper Bound} N = Encoded Value {Total Size} N = Encoded Value {Type} N = Encoded Value {Format} %end %continue D(Dir Line): Current Line = Encoded Value Allocate Line Diag; %continue D(Dir Include): Get String(Included File, 255); %continue D(Dir Record On): Record Diags = Encoded Value Formpt(Record Diags) = Record Size %continue D(Dir Record Off): Record Diags = 0 Record Size = Record Size + 1 ; %continue D(Dir Slabel): D(Dir Label): Label = Encoded Value+Reloc Item == Items(Label) Item_Flags = 0 %if Code = Dir Slabel %and Item_Ca >= 0 %start Item_Flags = Duplicated Basep == Base {already defined - S(*): } %cycle {search for & remove old copy} CSR("corrupt switch") %if Basep == Nil %exit %if Basep_Link == Item Basep == Basep_Link %repeat Basep_Link == Item_Link Terminal == Basep %if Terminal == Item {beware last one} %finish Item_Ca = Ca Item_Type = Label Type Item_Head == Head Terminal_Link == Item; Terminal == Item %continue D(Dir Mark User): Item_Flags = Item_Flags!Marked; %continue {show it's user-defined} D(Dir Const Addr): Item == New Item(Caddr Type) Item_Cond = Encoded Value {register} Item_Value = Encoded Value Item_Flags = 0 Ca = Ca+4 %continue D(Dir Const Load): Item == New Item(Cload Type) Item_Cond = Encoded Value {register} Item_Value = Encoded Value Item_Flags = 0 Ca = Ca+4 %continue D(Dir Real Load): Item == New Item(Rload Type) Item_Cond = Encoded Value {register} Item_Value = Encoded Value N = Encoded Value {0=short, 1=long} Item_Flags = 0 Ca = Ca+4 %continue D(Dir Spec Load): Item == New Item(Sload Type) Item_Cond = Encoded Value {register} N = Encoded Value+Xreloc {external index} Add Use(N) Item_Value = N Needs = Needs ! Attr Needs Gp Item_Flags = 0 Ca = Ca+4 %continue D(Dir Branch): Label = Encoded Value+Reloc Item == New Item(Branch Type) Ca = Ca+4 Item_Cond = Encoded Value Item_Flags = Item_Flags ! Conditional %if Item_Cond # 7 - %and Item_Cond # 17 Item_Label == Items(Label) %continue D(Dir McLabel): Label = Encoded Value+Reloc {label} N = Encoded Value {instruction} Ca = Ca+4 %continue D(Dir Modify): N = Encoded Value {address} N = Encoded Value {auto increment} %continue D(Dir Header): N = Encoded Value {area} N = Encoded Value {zero'th} N = Encoded Value {dope vector} Ca = Ca+8 %continue D(Dir Thunk): Label = Encoded Value+Reloc {procedure to call} N = Encoded Value {Static slot} Item == New Item(Thunk Type) Item_Label == Items(Label) %continue D(Dir xThunk): N = Encoded Value+Xreloc {external procedure to call} Q = Encoded Value {Static slot} Add Use(N) %continue D(Dir Call): Label = Encoded Value+Reloc Item == New Item(Call Type) Ca = Ca+4 Item_Flags = Minimum Item_Label == Items(Label) %continue D(Dir Ext): Max External = Max External+1 X == External(Max External) Get String(X_Text, 31) X_Flags = Encoded Value X_Disp = Encoded Value X_Value = -1 Main Program = 1 %if X_Text = "3L___main_program" - %and X_Flags&Ext Code # 0 - %and X_Flags&Ext Defn # 0 Add Use(Max External) %if X_Flags&Ext Defn # 0 - %and X_Flags&Ext Prim = 0 %continue D(Dir Xref): N = Encoded Value+Xreloc {external index} Add Use(N) Q = Encoded Value Ca = Ca+4 %continue D(Dir xCall): N = Encoded Value+Xreloc Add Use(N) Item == New Item(External Type) Ca = Ca+4 Item_Flags = Minimum Item_Value = N Needs = Needs ! Attr Needs Gp %continue D(Dir Assigned): Set Prim(22); %continue D(Dir Prim): N = Encoded Value; Set Prim(N); %continue D(Dir Return): Item == New Item(Return Type); Ca = Ca+4 Item_Flags = Minimum Item_Value = Encoded Value %continue D(Dir Area): Q = Encoded Value {area} Dummy Code Base = Encoded Value {offset} Ca == Dummy Code Base Ca == Local Code Base %if Q = 0 {offset is ignored} %continue D(Dir Swdef): Lb = Encoded Value+Reloc Ub = Encoded Value+Reloc Items(N)_Ca = -1 %for N = Lb, 1, Ub %continue D(Dir Sw Ref): N = Encoded Value; Ca = Ca+4; %continue D(Dir Init): N = Encoded Value N = Encoded Value Ca = Ca+4 %continue D(Dir Dump): N = Encoded Value; Skip Bytes(N); Ca = Ca+N %repeat D(Dir End Block): Head_Frame = Encoded Value&(\3)+20 {negative} Head_Code Size = Encoded Value Head_Pframe = Encoded Value-4 Head_Pregs = Encoded Value Head_Display = Encoded Value N = Encoded Value N = Encoded Value Head_Attr = Encoded Value ! Needs N = Encoded Value Head_Event Mask = Encoded Value Head_Event Label = Encoded Value+Reloc Head_Event Body = Encoded Value+Reloc Terminal_Link == Nil Head_Items == Base_Link %if Head_Attr&Attr Prim # 0 %start {strip external bits} Head_Attr = Head_Attr & (Attr Needs Gp!Attr Prim) %finish Diag Inc = 0 %if Options&LL Vars = 0 - %or Head_Attr&Attr Prim # 0 Head_Line Size = (Line Size+5+3)&(\3) {a bit spare} Diag Size = 0 %if Options&LL Vars = 0 Head_Diag Size = (Diag Size+Diag Inc+1+3)&(\3) {+ term} Head_Line Size = 0 %if Options&LL Lines = 0 Head_Diag Size = 0 %if Options&LL Trace = 0 %end %routine Define Prim Map %integer J, Failed = 0 %record(Xfm)%name X %routine Define Prim(%string(31) Text, %integer Value) %integer M = 0 %while M # Last Prim %cycle M = M+1 %if Prim Id(M) = Text %start CSR("duplicate Prim routine ".X_Text) %if Prim Map(M) # 0 Prim Map(M) = Value %return %finish %repeat {unknown - just ignore it} %end %for J = Interface_External Count+1, 1, Interface_Total Externals %cycle X == External(J) Define Prim(X_Text, X_Disp+Reloc) %if X_Flags&2_100 # 0 {a Prim def} %repeat %for J = 1, 1, Last Prim %cycle %if Prim Used(J) # 0 %and Prim Map(J) = 0 %start Warn("missing Prim routine ".Prim Id(J)) Failed = 1 %finish %repeat CSR("Missing primitive procedures") %if Failed # 0 %end %integerfn Place String(%string(255) S) %integer P = String Size String Size = String Size + Length(S)+1 %result = P %end %routine Allocate External(%record(Xfm)%name X) %record(Blockfm)%name H %return %if X_Flags & Ext Prim # 0 {ignore prim routines} X_Flags = X_Flags ! Ext Allocated ! Place String(X_Text)<<8 %if X_Flags&Ext Defn = 0 %start {reference} %if X_Flags&Ext Code = 0 %start {only allocate data references} %if Max SB <= 4094 %start X_Disp = Max SB; Max SB = Max SB+4 %else Min SB = Min SB-4; X_Disp = Min SB CSR("Too many external references") %if Min SB < -4096 %finish %finish %else %if X_Flags&Ext Code # 0 {code definition} H == Items(X_Disp)_Head %if X_Text = "3L___main_program" %start Interface_Specials = Interface_Specials ! Special Main Main Head == H Start Point = X_Disp CSR("main program found") %if Main Program = 0 %else %if X_Text = "3L_imp___entry_point" - %or X_Text = "3L_pascal___entry_point" Entry Head == H Entry X == X %finish H_X == X {back link from block header} %finish %end %routine Mark Unused Blocks %record(Blockfm)%name This Block %record(Usefm)%name U, UU %integer N %routine Mark blocks used by(%record(Blockfm)%name This Block, %integername Attr) %integer A %record(Blockfm)%name B %record(Itemfm)%name Item == This Block_Items This Block_Flags = This Block_Flags!Used %if This Block_Attr&Attr Both # 0 %start {uses non-locals} This Block_Flags = This Block_Flags ! Displ Flag %finish %if This Block_Attr&Attr Prim # 0 %start {is a Primitive block} This Block_Line Size = 0 This Block_Frame = 0 This Block_Flags = This Block_Flags!No Entry %finish %while Item ## Nil %cycle %if Item_Type >= Branch Type %start %if Item_Type = Prim Type %and Item_Flags&Minimum # 0 %start Item_Flags = Item_Flags-Minimum Item_Label == Items(Prim Map(Item_Prim)) %finish B == Item_Label_Head B_Attr = B_Attr ! Attr Xdef %if Item_Type = Thunk Type A = B_Attr&Attr Needs Gp Attr = Attr ! A This Block_Attr = This Block_Attr ! A Mark blocks used by(B, Attr) %if B_Flags&(Ext Flag!Used) = 0 %finish Item == Item_Link %repeat %end {mark the initial entries as unused} This Block == Block List %while This Block ## Nil %cycle %if This Block_Attr&Attr Xdef # 0 %start {trace from external root} %if This Block_Flags&Used = 0 %start This Block_Flags = This Block_Flags ! Ext Flag Mark blocks used by(This Block, This Block_Attr) %finish %finish This Block == This Block_Link %repeat {finally build the list of used blocks} Number of Blocks = 0 U == Blocks(0)_Uses %while U ## NIL %cycle UU == U_Link %if U_X_Flags&Ext Defn # 0 %start U_Link == Total Uses; Total Uses == U %finish U == UU %repeat %record (blockfm) %name B This Block == Block List Block List == Nil %while This Block ## Nil %cycle B == This Block_Link %if This Block_Flags&Used # 0 %start {the block has been used} This Block_Link == Block List Block List == This Block Area Size_Line = Area Size_Line + This Block_Line Size {sum sizes for use} Area Size_Diag = Area Size_Diag + This Block_Diag Size {in allocating segm.} U == This Block_Uses %if U ## NIL %start U == U_Link %while U_Link ## NIL U_Link == Total Uses Total Uses == This Block_Uses %finish Number of Blocks = Number of Blocks+1 %else {not been used} U == This Block_Uses {keep data definitions} %while U ## NIL %cycle UU == U U == U_Link %if UU_X_Flags&Ext Defn # 0 %and - UU_X_Flags&Ext Code = 0 %start UU_Link == Total Uses; Total Uses == UU %finish %repeat %finish This Block == B %repeat {now allocate the externals, done here to ensure the correct order} N = Place String("$CODEAREA") N = Place String("$DATAAREA") N = Place String("$DBUGAREA") %if Debug # 0 N = Place String(Main Entry Id) %if Main Program # 0 User String Base = String Size U == Total Uses %while U ## NIL %cycle %if U_X_Flags&Ext Allocated = 0 %start Allocate External(U_X) %else U_X == NIL %finish U == U_Link %repeat %end %predicate Compatible(%integer CC1, CC2) %integer M1, M2 %constinteger G=1, E=2, L=4, Ug=8, Ul=16, N=0, A = 31 %constbytearray CC Map(0:23) = N, E, L, L!E, G, G!E, G!L!Ug!Ul, A, E, N, N, { BEQL, BLSS, BLEQ, BGTR, BGEQ, BNEQ, BRB, BFS, BFC, E, Ul, Ul!E, Ug, Ug!E, G!L!Ug!Ul, A, E, N, { BEQL, BLSSU, BLEQU, BGTRU, BGEQU, BNEQ, BRB, BFS, BFC, N, N, N, N { BBS, BBC, BLBS, BLBC %false %if CC1&128 # 0 %or CC2&128 # 0 M1 = CC Map(CC1) M2 = CC Map(CC2) %true %if M1 = M1&M2 %false %end %routine Absorb Jumps(%record(Blockfm)%name Head) %integer Mod %record(Itemfm)%name It %routine Absorb(%record(Itemfm)%name I) %record(Itemfm)%name Next, Dest, Else {I is known to be a conditional branch} Dest == I_Label {destination of the branch} ->NO %unless 0 <= Dest_Ca-I_Ca <= 24 {not too far away} ->NO %if Dest_Flags&Referenced # 0 {already in use} {???why???} Next == I_Link {skip safe things} %cycle ->NO %if Next == NIL %exit %unless Next_Type = Call Type - %or (Next_Type = Prim Type %and Next_Prim # 22) - %or Next_Type = External Type - %or Next_Type = Return Type %if Next_Type = Prim Type %start {BEWARE - prim changes the condition code} ->NO %if Next_Link ## Dest %or Next_Link_Ca # Next_Ca+4 %finish Next == Next_Link %repeat %if Next == Dest %start {IF ... THEN ... FI } {^ ^ } {I Next=Dest} I_Flags = I_Flags ! Absorbed {make it go away} I_Cond = Inverse(I_Cond) {onto the TRUE condition} I_Ca = I_Ca+4 {to compensate for MOD} Dest_Flags = Dest_Flags!Label Used {probably unnecessary now} Mod = Mod-4 {we've removed 1 branch} %else %if Next_Type = Branch Type {IF ... THEN ... ELSE ... FI } {^ ^ ^ ^ } {I Next Dest Else} ->NO %unless Next_Link == Dest - %and Next_Flags&Conditional = 0 - %and Dest_Ca = Next_Ca+4 Else == Dest_Link {skip safe things} %cycle ->NO %if Else == NIL %exit %unless Else_Type = Call Type - %or Else_Type = Prim Type - %or Else_Type = External Type - %or Else_Type = Return Type %if Else_Type = Prim Type %start {BEWARE - prim changes the condition code} ->NO %if Else_Link ## Next_Label %or Else_Link_Ca # Else_Ca+4 %finish Else == Else_Link %repeat ->NO %unless Else == Next_Label - %and 0 <= Else_Ca-Dest_Ca <= 24 - {not too far away} %and Else_Flags&Referenced = 0 {not otherwise used} I_Flags = I_Flags ! Absorbed Next_Flags = Next_Flags ! Absorbed Dest_Flags = Dest_Flags ! Label Used Else_Flags = Else_Flags ! Label Used Next_Cond = I_Cond I_Cond = Inverse(I_Cond) I_Ca = I_Ca+8 {to compensate for MOD} Mod = Mod-8 %finish %return NO: {mark the destination label as having been referenced} Dest_Flags = Dest_Flags ! Referenced %end It == Head_Items Mod = 0 %while It ## Nil %cycle Absorb(It) %if It_Type = Branch Type %and It_Flags&Conditional # 0 - %and It_Flags&Absorbed = 0 It_Ca = It_Ca+Mod It == It_Link %repeat Head_Code Size = Head_Code Size+Mod %end %routine Process Block(%record(Blockfm)%name Head) %record(Itemfm)%name It, New, Next, Dest %record(Itemfm) Base %integer Mod, Altered, Here %cycle Mod = 0; Altered = 0 It == Head_Items %while It ## Nil %cycle Dest == It_Label Here = It_Ca Next == It_Link %if It_Flags&Absorbed # 0 %start Dest_Flags = Dest_Flags!Label Used %else %if It_Type = Branch Type %if It_Flags&Conditional # 0 %and {conditional jump} Next ## Nil %and {followed by ..} Next_Ca = Here+4 %and {something near} Next_Type = Branch Type %and {a branch} Next_Flags&Conditional = 0 %and {which is uncond} Next_Cond&128 = 0 %and {not m-code} Next_Link ## Nil %and {followed by ..} Next_Link_Type = Label Type %and {the first label} Dest == Next_Link %and Next_Link_Ca = Here+8 %start ! Remove jumps around jumps ! X: B true X+4 ! X+4: B Y ! X+4: .......... ! becomes ! X: B false Y ! X+4: (deleted) It_Cond = Inverse(It_Cond) It_Label== Next_Label Next_Flags = Deleted It_Link == Next_Link It_Ca = It_Ca+4 {to compensate for MOD} Mod = Mod-4; Altered = 1 It_Label_Flags = It_Label_Flags!Label Used %else %if Dest_Link ## Nil %and Dest_Link_Ca = Dest_Ca %and Dest_Link_Type = Branch Type %and Dest_Link_Label ## Dest %and Compatible(It_Cond, Dest_Link_Cond) ! Remove jumps to jumps ! X: B Y ! .. ! Y: B Z ! Becomes ! X: B Z ! .. ! Y: B Z It_Label == Dest_Link_Label Altered = 1 It_Label_Flags = It_Label_Flags!Label Used %else %if It_Flags&Conditional = 0 %and It_Cond&128 = 0 %and Next ## Nil %and Next_Type = Branch Type ! X B fred ! X+n B jim ! is reduced to ! X B fred ! as the jump at X+4 can never be reached (note that ! it has NO LABEL on it). Next_Flags = Deleted; Next == Next_Link It_Ca = It_Ca+4 {to compensate for MOD} Mod = Mod-4 Altered = 1 It_Label_Flags = It_Label_Flags!Label Used %else %if It_Label == It_Link %and It_Label_Ca = It_Ca+4 ! REMOVE DEGENERATE JUMPS ! X B jim ! X+4 jim: ! is reduced to ! X jim: ! NB that this is done by marking for deletion ! which is performed in the label-reduction step ! later on. Mod = Mod-4 It_Flags = Deleted Altered = 1 %else It_Label_Flags = It_Label_Flags!Label Used {mark used} %finish %else %if It_Type = Jump Type %or It_Type = Disp Type It_Label_Flags = It_Label_Flags!Label Used {mark used} %finish It_Ca = It_Ca+Mod It == Next %repeat Head_Code Size = Head_Code Size+Mod %exit %if Altered = 0 {remove unused compiler-defined labels and deleted items} New == Base It == Head_Items %while It ## Nil %cycle New_Link == It %if It_Type = Label Type %start %if It_Flags&(Marked!Label Used) # 0 %start New == It {keep it} It_Flags = It_Flags&(\Label Used) {drop used bit} %else It_Flags = Deleted %finish %else New == It %if It_Flags&Deleted = 0 {keep it} %finish It == It_Link %repeat New_Link == Nil Head_Items == Base_Link %repeat Absorb Jumps(Head) %end %routine Process Blocks %record(Blockfm)%name B B == Block List %while B ## Nil %cycle Process Block(B) B == B_Link %repeat %end %routine Stretch(%record(Blockfm)%name Head) {the global BIAS is updated} %record(Itemfm)%name It %integer Here, Mod, Disp, Type %switch T(Label Type:Final Type) Mod = Bias; Bias = 0 Head_Code Base = Head_Code Base+Mod Head_Body = Head_Body+Mod Head_Ca = Head_Ca+Mod Head_Label_Ca = Head_Ca Head_Code Size = Head_Code Size-Mod {to correct for final addition} It == Head_Items %while It ## Nil %cycle Here = It_Ca It_Ca = It_Ca+Mod {relocate it} Type = It_Type ->T(Type) T(*): CSR("Corrupt item type".ItoS(It_Type, 1)) T(Addr Type): ->Next %if It_Flags&Long # 0 Disp = (It_Ca+8+Mod)-(Area Base_Constant+It_Value) %unless 16_FFFF8000 <= Disp <= 16_0000 7FFF %start It_Flags = It_Flags ! Long Mod = Mod+4 %finish ->Next T(Caddr Type): ->Next %if It_Flags&VeryLong # 0 Disp = (It_Ca+8+Mod)-(Area Base_Constant+It_Value) Disp = Disp>>2 %if Disp&3 = 0 {will be scaled when loaded} %unless Disp <= 255 %start %if It_Flags&Long = 0 %start It_Flags = It_Flags ! Long Mod = Mod+4 {Disp = M<<8 + N} {ADD _ R, Pc, #M<<8} {LDR _ R, [R, #N]} %else %if Disp > 16_FFFF It_Flags = It_Flags ! VeryLong Mod = Mod+4 {Disp = L<<16 ! M<<8 ! N} %finish %finish ->Next T(Rload Type): ->Next %if It_Flags&VeryLong # 0 Disp =((It_Ca+8+Mod)-(Area Base_Constant+It_Value))>>2 %unless Disp <= 255 %start %if It_Flags&Long = 0 %start It_Flags = It_Flags ! Long Mod = Mod+4 {Disp = M<<8 + N} {SUB _ R, Pc, #M<<(8+2)} {LDR _ R, [R, #N]} %else %if Disp > 16_FFFF It_Flags = It_Flags ! VeryLong Mod = Mod+4 {Disp = X<<16 ! M<<8 ! N} %finish %finish ->Next T(Cload Type): ->Next %if It_Flags&VeryLong # 0 Disp = (It_Ca+8+Mod)-(Area Base_Constant+It_Value) %unless Disp <= 4095 %start %if It_Flags&Long = 0 %start It_Flags = It_Flags ! Long Mod = Mod+4 {Disp = M<<12 + N} {ADD _ R, Pc, #M<<12} {LDR _ R, [R, #N]} %else %if Disp > 16_FF FFF It_Flags = It_Flags ! VeryLong Mod = Mod+4 {Disp = X<<20 ! M<<12 ! N} %finish %finish ->Next T(Thunk Type): T(Sload Type): T(Disp Type): T(Jump Type): T(Prim Type): T(Branch Type): T(Call Type): T(External Type): ->Next T(Return Type): %if It_Flags&Minimum # 0 %start It_Flags = It_Flags-Minimum Mod = Mod+Head_Return %finish ->Next T(Label Type): Next: It == It_Link %repeat Head_Code Size = Head_Code Size+Mod Bias = Bias+Mod %end %routine Stretch blocks %record(Blockfm)%name B %cycle Bias = 0 B == Block List Stretch(B) %and B == B_Link %while B ## Nil Area Size_Code = Area Size_Code+Bias {new actual size} Xentry Base = Xentry Base+Bias Extra Base = Extra Base + Bias Code Size = Code Size + Bias %repeat %until Bias = 0 %end %routine Mark Forward %record(Blockfm)%name B %record(Itemfm)%name I B == Block List %while B ## Nil %cycle I == B_Items %while I ## Nil %cycle %if I_Type >= Branch Type %start I_Flags = I_Flags ! Forward %if I_Label_Ca > I_Ca %finish I == I_Link %repeat B == B_Link %repeat %end %routine Allocate(%record(Blockfm)%name B, %integer At) { <...pre-entry sequence...> } { ^ ^ } { Code Base Ca } %integer Extra = 0, Frame, N, Amod = 0 %record(Itemfm)%name It B_Code Base = At Amod = 4 {block flags, display & link} Extra = 4 %and ->OK %if B == Entry Head %if B_Flags&No Entry = 0 %start Amod = Amod+12 %if B_Event Mask # 0 {Mask, Limit, Ep} Frame = -B_Frame Extra = Extra+8 {STM, MOV} %if B_Attr&Attr Xdef # 0 %start {set up SB} %if B_Attr&Attr Needs Gp # 0 %start Amod = Amod+4 {SB pointer} %if B_Attr&Attr Both = 0 %start Extra = Extra+4 {LDR _ Sb, []} %else Extra = Extra+8 {LDR, R7, []; MOV Sb, R7} %finish %finish %finish %if B_Attr&Attr Both # 0 %start Extra = Extra + 8 {LRD _ R7, Olddisplay & STR} B_Return = B_Return+8 %finish %if Options&LL Assigned # 0 %start N = Frame>>2 {words to set unassigned} %if N # 0 %start Extra = Extra+4 {needs one load instruction} %if N <= 4 %start Extra = Extra+4 {only one store} %else %if N&3 # 0 %start Extra = Extra+4 {one store for the remainder} N = N&(\3) %finish N = N>>2 {now in fours} %if N <= 5 %start Extra = Extra + 4*N {one store each} %else Extra = Extra+12 {load count, decrement & branch} %cycle {calculate size of LOAD instrn} N = N>>2 %while N&3 = 0 Extra = Extra+4 N = N>>8 %repeat %until N = 0 %finish %finish %finish %else N = Frame %while N # 0 %cycle N = N>>2 %while N&3 = 0 Extra = Extra+4 N = N>>8 %repeat %finish Extra = Extra+4 Extra = Extra+4 %if B_Pframe # 0 %finish OK: At = At+Amod {pre-entry sequence} B_Code Size = B_Code Size+Extra+Amod B_Ca = At B_Label_Ca = At At = At+Extra {entry sequence} B_Body = At It == B_Items {relocate labels & jumps} %while It ## Nil %cycle It_Ca = It_Ca+At %unless It_Type = Array Disp Type It == It_Link %repeat %end %routine Allocate Blocks %integer Dp, Cp, N %record(Blockfm)%name B Area Size_Code = 0 N = (Length(Interface_Module) + 1 + 1 + 3)&(\3) Area Size_Block = N + 4 + 4*Number of Blocks + 4 {environs} + 4 {MARK} Area Size_Block = 4 %if Options&LL Trace = 0 Area Size_Record = Record Size Area Size_Record = 0 %if Options&LL Records = 0 Area Size_Diag = 0 %if Options&LL Vars = 0 Area Size_Line = 0 %if Options&LL Lines = 0 Area Size_Global = Max SB-Min SB Area Size_Diag = (Area Size_Diag+3)&(\3) + (Area Size_Line+3)&(\3) Area Size_Record = (Area Size_Record+3)&(\3) Area Base_Diag = 0 Area Base_Diag = 4 %if Main Program # 0 {ref to ?___ENTRY_POINT} Area Base_Record = Area Base_Diag + Area Size_Diag Area Base_Constant= Area Base_Record + Area Size_Record Area Base_Block = Area Base_Constant + Area Size_Constant Area Base_Code = Area Base_Block + Area Size_Block Area Base_Global = 0 Area Base_Global Array = Area Size_Global Data Size = (Area Size_Global + Area Size_Global Array + 3)&(\3) Data Size = 4 %if Data Size = 0 {Sad - but can't have empty areas} Cp = Area Base_Code; Dp = Area Base_Diag B == Block List %while B ## Nil %cycle Allocate(B, Cp) B_Diag Base = Dp B_Line Base = Dp + B_Diag Size Dp = Dp + B_Diag Size + B_Line Size Cp = Cp + B_Code Size B == B_Link %repeat Extra Base = Cp Xentry Base = Cp Code Size = Xentry Base + Xentry Area Size_Code = Code Size - Area Base_Code %end %routine Allocate Debug Information(%record(ProcedureFm)%name P) {001} %integer Dummy = 0 %integer Disp = 0 {001} {First, calculate size of debug area} {001} {001} %routine Allocate Var(%record(DvarFm)%name V, %integername Args) %return %if V_Class = -1 Disp = Disp+W + 4*W + Padded(V_Ident) Args = Args+1 %if V_Class = 3 %and V_Offset > 0 {a parameter} %end %routine Allocate Variables(%record(DvarFm)%name Z, %integername Args) %record(DvarFm)%name D D == Z %if D ## NIL %start %cycle D == D_Link Allocate Var(D, Args) %repeat %until D == Z %finish %end %routine Allocate Format(%record(Dformatfm)%name F) %record(DvarFm)%name V, Z F_Bytes = 0 F_Disp = Disp F_Fields = 0 F_Size = W + 2*W Z == F_Vars V == Z %if V ## NIL %start %cycle F_Fields = F_Fields+1 F_Bytes = F_Bytes+V_Size F_Size = F_Size + 2*W + Padded(V_Ident) V == V_Link %repeat %until V == Z %finish %if F_Fields = 1 %and F_Vars_Class = -1 %start {really an array} F_Size = W + 5*W F_Fields = -1 %finish Disp = Disp+F_Size %end %routine Allocate Formats(%record(DformatFm)%name Z) %record(DFormatFm)%name D D == Z %if D ## NIL %start %cycle D == D_Link Allocate Format(D) %repeat %until D == Z %finish %end %routine Allocate Procedures(%record(Procedurefm)%name P) {001} %cycle %return %if P == NIL {001} Disp = Disp + 8*W + Padded(P_Name) %if Debug Options&2 = 0 %start Allocate Formats(P_Formats) Allocate Variables(P_Vars, P_Args) %finish Allocate Procedures(P_Inner) P_EndItem = Disp Disp = Disp + 5*W + 4*P_Nreturns {001} P == P_Next %repeat %end {001} {001} %routine Allocate Files(%record(Filefm)%name F) %integer N = 0, Size, Fsize %record(FragmentFm)%name Fr, X %integerfn Frag Size(%record(FragmentFm)%name F) %integerfn LineNo Size(%record(DLinefm)%name L) %integer Size = 0 %routine Count(%integer LineInc, CodeInc) %return %if LineInc < 0 %or CodeInc <= 0 Size = Size+2 Size = Size+4 %if LineInc > 255 %or CodeInc > 255 %end %result = 0 %if Debug Options&1 # 0 %result = 0 %if L == NIL %cycle %exit %if L_Link == NIL {this is the last line} Count(L_Link_Line-L_Line, L_Link_Ca-L_Ca) L == L_Link %repeat Count(F_To-L_Line, F_Code+F_CodeSize-L_Ca) %result = Size %end F_Size = 5*W + LineNo Size(F_Lines) F_Padding = F_Size&2 F_Size = F_Size+F_Padding %result = F_Size %end %routine Merge(%record(FragmentFm)%name A, B) %record(Dlinefm)%name L {Fragment B follows immediately from A} {combine them - be careful with line-no info} A_To = B_To A_CodeSize = A_CodeSize+B_CodeSize %if A_Lines == NIL %start A_Lines == B_Lines %else %if B_Lines ## NIL L == A_Lines L == L_Link %while L_Link ## NIL L_Link == B_Lines %finish %end %integerfn File Size(%record(Filefm)%name F) %integer Size, N %record(FragmentFm)%name A, B {First, reverse the list and try to merge fragments} A == F_Frag; F_Frag == NIL %while A ## NIL %cycle B == A A == B_Link %continue %if B_From = 0 %or B_To = 0 {empty item} %if A_To+1 = B_From %and A_Code+A_CodeSize = B_Code %start Merge(A, B) %continue %finish B_Link == F_Frag F_Frag == B %repeat {Now, calculate the size} Size = 3*W + Padded(F_File) N = 0 A == F_Frag %while A ## NIL %cycle Size = Size+Frag Size(A) N = N+1 A == A_Link %repeat F_N = N F_Size = Size %result = Size %end Files Size = 4 {code word} %if Debug Options&4 = 0 %start %while F ## NIL %cycle F_Disp = Disp+Files Size Files Size = Files Size+File Size(F) F == F_Link %repeat %finish Files Size = Files Size+4 {terminator} Disp = Disp+Files Size %end Disp = 4 + 1 + 2 + 1 + 6*W + Padded(Interface_Module) {001} %if Debug Options&2 = 0 %start Allocate Formats(Fglobals) Allocate Variables(Dglobals, Dummy) %finish Allocate Procedures(P) {procedure information} {001} Allocate Files(DebugFiles) Bugs Size = Disp CSR("Debug alignment") %if Bugs Size&3 # 0 %end {001} %routine Allocate Buffer(%integer Segment, Size) {001} %integer N CSR("Null Area") %if Size <= 0 N = Get Space(Size) {001} Segment Base(Segment) = N {001} Segment Limit(Segment) = N+Size {001} %end {001} %routine Dump Block(%integer Level, Finish, InPrim, %integername DebugA) {001} %routinespec Dump(%integer B) %constbytearray Branch(0:23) = 16_FA, { BNV 16_0A, 16_BA, 16_DA, 16_CA, 16_AA, 16_1A, 16_EA, 16_1A, 16_0A, 0, { BEQL, BLSS, BLEQ, BGTR, BGEQ, BNEQ, BRB, BFS, BFC, 16_0A, 16_3A, 16_9A, 16_8A, 16_2A, 16_1A, 16_EA, 16_1A, 16_0A, { BEQL, BLSSU, BLEQU, BGTRU, BGEQU, BNEQ, BRB, BFS, BFC, 16_FA, 16_FA, 16_FA, 16_FA { BNV, BNV, BNVS, BNV %switch D(1 : Max Dir) {002} %integer Code Basis, Line Basis, Diag Basis %integer Code, N, M, Frame, Display, Disp, Lb, Ub, Work, Op, C %integer At, Set CC = 0 %integer Wanted, Xxx, Bflags %integer Record Diags = 0 %integer Rel1 No, Rel2 No, Rel3 No {001} %owninteger Entry Reference = 0 %record(Itemfm)%name Item, CC Label == NIL %record(Blockfm)%name Head %record(Linefm) Line Info = 0 %record(Xfm)%name X %integer D1, D2 %record(Procedurefm) Debug Base {001} %record(Procedurefm)%name DebugP == NIL, {001} Debug List == Debug Base {001} %record(DFormatPFm)%name Dfm == NIL %routine Dump Cstring (%string(255) S, %integer N) %integer J %if N # 0 %start {add null} S = S.Tostring(0) %if N = 2 %start {round up to multiple of 4} S = S.Tostring(0) %while Length(S)&3 # 0 %finish %finish Printsymbol(Charno(S, J)) %for J = 1, 1, Length(S) %end %routine Select Diag Area Ca == Diag Basis Select(CSeg, Ca) %end %routine Select Record Area Ca == Record Basis Select(CSeg, Ca) %end %routine Select Line Area Ca == Line Basis Select(CSeg, Ca) %end %routine Select Code Area Ca == Code Basis Select(CSeg, Ca) %end %routine Select Debug Area Ca == Bugs Basis Select(BSeg, Ca) %end %routine Select Pure Area(%integer Bias) Ca == Other Basis Ca = Bias Select(CSeg, Ca) %end %routine Enter Line Diagnostic %integer Nl = Line Info_Line - Line Info_Last Line, Nc = Line Info_Ca - Line Info_Last Ca-4 %return %if Nl <= 0 %or Nc <= 0 {treat it as one line} Select Line Area %if Nl > 1 %start Nl = Nl-2 %if Nl >= 64 %start Dump((Nl<<2)&255+2_11) Dump(Nl>>6) %else Dump(Nl<<2+2_10) %finish %finish %if Nc >= 64 %start {big CA} Dump((Nc<<2)&255+2_01) Dump(Nc>>6) %else {small CA} Dump(Nc<<2 + 2_00) %finish Select Code Area Line Info_Last Ca = Ca Line Info_Last Line = Line Info_Line Line Info_Pending = 0 %end %routine Dump(%integer N) Enter Line Diagnostic %if Line Info_Pending # 0 - %and Line Info_Ca = Ca - %and Ca == Code Basis Byte(Current Address) = N Current Address = Current Address + 1 %if Current Address > Current Limit %start A Error(Current Address, Current Limit) %finish Ca = Ca+1 %end %routine Dump2(%integer N) Enter Line Diagnostic %if Line Info_Pending # 0 - %and Line Info_Ca = Ca - %and Ca == Code Basis Byte(Current Address+0) = (N>>0)&255 Byte(Current Address+1) = (N>>8)&255 Current Address = Current Address + 2 %if Current Address > Current Limit %start A Error(Current Address, Current Limit) %finish Ca = Ca+2 %end %routine Dump4(%integer N) Enter Line Diagnostic %if Line Info_Pending # 0 - %and Line Info_Ca = Ca - %and Ca == Code Basis %if Set CC # 0 %and Ca == Code Basis %start CSR("Bad cc to change") %unless N>>28 = 16_E N = N !! (Set CC<<24) %finish Byte(Current Address + 0) = (N>>00)&255 Byte(Current Address + 1) = (N>>08)&255 Byte(Current Address + 2) = (N>>16)&255 Byte(Current Address + 3) = (N>>24)&255 Current Address = Current Address + 4 %if Current Address > Current Limit %start A Error(Current Address, Current Limit) %finish Ca = Ca + 4 %end %routine Dump4bytes(%integer N) Printsymbol(N&255) Printsymbol(N>>8&255) Printsymbol(N>>16&255) Printsymbol(N>>24&255) %end %integerfn External Index(%record(Xfm)%name X) {This function returns an index into the symbol table} {corresponding to the external object X} %integer At, Value, Area %if X_Flags & Ext Dumped = 0 %start {not yet in symbol table} X_Flags = X_Flags ! Ext Dumped %if X_Flags&Ext Defn # 0 %start {external definition} At = 2_0011 %if X_Flags&Ext Code # 0 %start {code definition} Value = Items(X_Disp)_Ca Area = CodeArea %else {data definition} Value = X_Disp-Min SB Area = DataArea %finish %else {external reference} At = 2_0010 Value = 0; Area = DataArea {the VALUE field is not needed} %finish X_Value = Symbol Entry(X_Flags>>8, At, Value, Area) %finish %result = X_Value %end %routine Relocate(%integer Data, Segment, Xindex, Mode) ! Mode: SymbolReloc, PcReloc %record(Relocfm)%name R %record(SegmentRfm)%name Sr %integer Displacement = Ca Displacement = Displacement-Min SB %if Segment = DSeg Dump4(Data) R == NEW(Relocfm Type) R_Vaddr = Displacement R_Code = Xindex ! Mode<<16 Sr == Segment Reloc(Segment) R_Link == Sr_R; Sr_R == R Sr_Entries = Sr_Entries+1 %end %routine Dump Header %integer Len, N, Areas %string(63) Compiler = ProductCode.":".Version.".".Release.".".Revision %integer Chunk Offset %routine Chunk Entry(%string(8) Id, %integer Size) Dump Cstring(Id, 0) %if Size = 0 %start Dump4Bytes(0) {zero offset for not-in-use} Dump4Bytes(0) {zero size too} %else Dump4Bytes(Chunk Offset) Dump4Bytes(Size) Chunk Offset = Chunk Offset + Size %finish %end Areas = 2 Areas = 3 %if Debug # 0 N = Code Size; CSR("Bad alignment") %if N&3 # 0 Len = (Length(Compiler) + 4)&(\3) Header Size = 6*4 + 5*4*Areas SymTsize = (Symbol Entry No+1)*16 ActiveSize = Code Size + Data Size + Bugs Size - {001} + (Rel1No+Rel2No+Rel3No)*8 {001} String Size = (String Size+3)&(\3) Total Size = 16_8C + Header Size + Len - + String Size + SymTSize + Active Size Open Object File(Total Size) Select Output(Object Out) Dump4bytes(16_C3CB C6C5) {chunk header} Dump4bytes(8) {max no. chunks} Dump4bytes(5) {actual no. chunks} Chunk Offset = 16_8C {size of chunk header} Chunk Entry("OBJ_HEAD", Header Size) {object header} Chunk Entry("OBJ_IDFN", Len) {identification} Chunk Entry("OBJ_STRT", String Size) {string table} Chunk Entry("OBJ_SYMT", SymTsize) {symbol table} Chunk Entry("OBJ_AREA", ActiveSize) {code & data areas} Chunk Entry("OBJ_UNU1", 0) Chunk Entry("OBJ_UNU1", 0) Chunk Entry("OBJ_UNU1", 0) {header chunk} Dump4bytes(16_C5E2D080) {obj_header} Dump4bytes(AOF Version) {001} Dump4bytes(Areas) {no. of areas} Dump4bytes(Symbol Entry No+1) {no. of symbols} %if Entry Head == Nil %start {no entry address} Dump4bytes(0) Dump4Bytes(0) %else {an entry address} Dump4bytes(1) {first area is code area} Dump4bytes(Entry Head_Label_Ca) %finish {area declarations} %routine Declare Area(%integer Name Offset, AtAl, Size, Rels) Dump4bytes(Name Offset) {offset for area name} Dump4bytes(AtAl) {at,al} Dump4bytes(Size) {size of area} Dump4bytes(Rels) {no. of relocations} Dump4bytes(0) {base addr} %end Declare Area(CodeArea, 16_2202, Code Size, Rel1 No) {Bit5+Bit2} Declare Area(DataArea, 16_0002, Data Size, Rel2 No) {no bits} %if Debug # 0 %start Declare Area(DbugArea, 16_A002, Bugs Size, Rel3 No) {Bit7+Bit5} {001} %finish {identification chunk} Dump Cstring(Compiler, 2) {obj_idfn} %end %routine Dump Strings %integer P = User String Base %record(Usefm)%name U %record(Xfm)%name X Dump4Bytes(String Size) Dump Cstring("$CODEAREA", 1) {set up AREA names} Dump Cstring("$DATAAREA", 1) Dump Cstring("$DBUGAREA", 1) %if Debug # 0 Dump Cstring(Main Entry Id, 1) %if Main Program # 0 U == Total Uses %while U ## NIL %cycle X == U_X %if X ## NIL %start CSR("shuffled strings") %unless P = X_Flags>>8 P = P+Length(X_Text)+1 Dump Cstring(X_Text,1) %finish U == U_Link %repeat Printsymbol(0) %and P = P+1 %while P&3 # 0 CSR("corrupt string table") %if P # String Size %end %routine Dump Symbols %record(Symbolfm)%name S Symbol List_Link == NIL S == Symbol Base_Link %while S ## NIL %cycle Dump4Bytes(S_Name) Dump4Bytes(S_Attributes) Dump4Bytes(S_Value) Dump4Bytes(S_Area) S == S_Link %repeat %end %routine Dump Relocation(%integer S) %record(Relocfm)%name R R == Segment Reloc(S)_R %while R ## NIL %cycle Dump4bytes(R_Vaddr) {virtual address of reference} Dump4bytes(R_Code) {index into symbol table} R == R_Link %repeat %end %routine Dump Segment(%integer N) %integer P Printsymbol(Byte(P)) %for P = Segment Base(N), 1, Segment Limit(N)-1 %end %routine Dump Branch(%integer Op, Dest) %integer Disp = (Dest-Ca-8)>>2 Dump4(Op<<24 ! Disp&16_00FF FFFF) %end %routine Next Prim(%integer Fn) Ip = Ip+1; Item == Items(Ip) CSR("corrupt Prim") %unless Item_Type = Prim Type %return %if Wanted = 0 Dump Branch(Fn, Item_Label_Ca) %end %routine Update Line Set Debug Line(Ca, Current Line) %return %if Options&LL Lines = 0 - %or Head_Attr&Attr Prim # 0 - %or Head_Line Size = 0 Line Info_Line = Current Line; Line Info_Ca = Ca Line Info_Pending = 1 %end %predicate Dumping Diags(%string(255) Id) {"" is a special to terminate} %integer J, L %false %if Head_Flags&Used = 0 - %or Head_Diag Size = 0 - %or Head_Attr&Attr Prim # 0 %if Record Diags = 0 %start {normal variables} %false %if Options&LL Vars = 0 Select Diag Area %else {record subfields} %false %if Options&LL Records = 0 Select Record Area %finish L = Length(Id) Dump(L); Dump(Charno(Id, J)) %for J = 1, 1, L %true %end %routine Dump Diag Entry %string(127) Id {002} %integer N, Key, L, F = 0, Type, Xtype Get String(Id, 127); L = Length(Id) {002} Key = Encoded Value; Type = Key>>2&15 Xtype = Encoded Value N = Encoded Value F = Encoded Value %if Key&64 # 0 %return %unless Dumping Diags(Id) %if Key # 0 %start Dump(Key) Dump(Xtype) %if Xtype # 0 %if -64 <= N <= 63 %start Dump(N&16_7F) %else %if 16_FFFF E000 <= N <= 16_0000 1FFF Dump((N>>8)&16_3F ! 2_10 000000) Dump(N&255) %else Dump((N>>24)&16_3F ! 2_11 000000) Dump(N>>16&255) Dump(N>>8&255) Dump(N&255) %finish %if Key&64 # 0 %start F = Formpt(F) %if F&16_8000 = 0 Dump2(F&16_FFFF) %finish %finish Select Code Area %end %record(Itemfm)%map Next Item(%integer Type) %record(Itemfm)%name I Ip = Ip+1 I == Items(Ip) %result == I %if I_Type = Type CSR("corrupt item type") %end %routine Update Include(%string(255) S) %recordformat Sfm(%record(Sfm)%name Link, %integer Line, %string(127) S) %constrecord(Sfm)%name Stype == 0 %record(Sfm)%name Sl %ownrecord(Sfm)%name List == 0 %if S = "" %start {end of include file} Sl == List CSR("badly nested includes") %if Sl == Nil List == Sl_Link Included File = Sl_S Debug Include(S, Ca, Sl_Line+1) DISPOSE(Sl) %else Sl == NEW(Stype) Sl_S = Included File Sl_Link == List Sl_Line = Current Line List == Sl Included File = S Debug Include(S, Ca, 1) %finish Included File = Interface_Source File %if Included File = "" %end %routine Dump Debug Information(%record(Procedurefm)%name P){001} %routine Reloc(%integer Value, Area) %record(Relocfm)%name R == NEW(Relocfm Type) %record(SegmentRfm)%name Sr == Segment Reloc(Bseg) R_Vaddr = Ca R_Code = Area ! SymbolReloc<<16 R_Link == Sr_R; Sr_R == R Sr_Entries = Sr_Entries+1 Dump4(Value) %end %routine Dump Debug String(%string(255) S) {001} %integer J, L {001} L = Length(S) {001} Dump(L) {001} Dump(Charno(S, J)) %for J = 1, 1, L {001} %cycle {001} L = L+1 {001} %exit %if L&3 = 0 {001} Dump(0) {001} %repeat {001} %end {001} %routine Dump Section %integer N = 4+ 1+2+1+6*W + Padded(Interface_Module) {001} %integer Flags Flags = 0 Flags = Flags ! Source and Line Flag %if Debug Options&1 = 0 Flags = Flags ! Variable Name Flag %if Debug Options&2 = 0 Dump4(N<<16 ! Debug Section) Dump(Language Pascal) { 0:language} Dump2(Flags) { 1:sectionflags} Dump(1) { 3:debugversion} Reloc(0, Cseg) { 4:codeaddr} Reloc(0, Dseg) { 8:dataaddr} Dump4(Code Size) { C:codesize} Dump4(Data Size) {10:datasize} Dump4(Bugs Size-Files Size) {14:fileinfo} Dump4(Bugs Size) {18:debugsize} Dump Debug String(Interface_Module) %end %routine Dump Var(%record(DvarFm)%name V) %integer Size = W + 4*W + Padded(V_Ident) %integer Type = V_Type, I %if Type < 0 %start {a record} I = Type&255 Type = (Type>>8) ! 16_FF000000 {propagate sign-bit} Type = (-DebugFm(-Type)_F_Disp)<<8 ! I %finish Dump4(Size<<16 ! Debug Variable) Dump4(Type) {Type} Dump4(V_SourcePos) {Sourcepos} Dump4(V_Class) {Storage class} %if V_Class = 2 %start {Static} Reloc(V_Offset, Dseg) {Absolute location} %else {other} Dump4(V_Offset) {relative location} %finish Dump Debug String(V_Ident) {name} %end %routine Dump Variables(%record(DvarFm)%name Z) %record(DvarFm)%name D D == Z %if D ## NIL %start %cycle D == D_Link Dump Var(D) %repeat %until D == Z %finish %end %routine Dump Format(%record(DformatFm)%name F) %record(DvarFm)%name V, Z %record(ArrayFm)%name A %if F_Fields = -1 %start {special for arrays} Dump4(F_Size<<16 ! Debug Array) A == F_Vars_Array Dump4(A_Total) Dump4(2_1010) Dump4(A_Type) Dump4(A_Lower) Dump4(A_Upper) %return %finish Dump4(F_Size<<16 ! Debug Struct) Dump4(F_Fields) Dump4(F_Bytes) {Dump the fields} Z == F_Vars V == Z %if V ## NIL %start %cycle V == V_Link Dump4(V_Offset) {Offset} Dump4(V_Type) {Type} Dump Debug String(V_Ident) {Name} %repeat %until V == Z %finish %end %routine Dump Formats(%record(DformatFm)%name Z) %record(DFormatFm)%name D D == Z %if D ## NIL %start %cycle D == D_Link Dump Format(D) %repeat %until D == Z %finish %end %routine Dump Procedures(%record(Procedurefm)%name P) {001} %integer N, X {001} %record(PreturnFm)%name R %while P ## NIL %cycle {001} N = 4+ 4*7 + Padded(P_Name) {001} Dump4(N<<16 ! Debug Procedure) {001} Dump4(P_Type) {001} Dump4(P_Args) {001} Dump4(P_StartPos) {001} Reloc(P_Proc_Ca, Cseg) {001} Reloc(P_Proc_Body, Cseg) {001} Dump4(P_EndItem) {001} Dump4(P_StartFile_Disp) {001} Dump Debug String(P_Name) {001} %if Debug Options&2 = 0 %start Dump Formats(P_Formats) Dump Variables(P_Vars) %finish Dump Procedures(P_Inner) {001} X = P_Nreturns N = 4+ 4*4 + 4*X {001} Dump4(N<<16 ! Debug Endproc) {001} Dump4(P_EndPos) {001} Reloc(P_Proc_Code Base+P_Proc_Code Size, Cseg) {001} Dump4(P_EndFile_Disp) {001} Dump4(X) {001} R == P_Return %while R ## NIL %cycle Reloc(R_Ca, Cseg) X = X-1 R == R_Link %repeat Csr("Missing returns") %if X # 0 P == P_Next {001} %repeat {001} %end {001} %routine Dump Fileinfo {001} %record(Filefm)%name F %routine Dump Line(%integer LineInc, CodeInc) %if LineInc > 255 %or CodeInc > 255 %start Dump2(0) Dump2(LineInc); Dump2(CodeInc) %else %if CodeInc > 0 %and LineInc >= 0 Dump(CodeInc); Dump(LineInc) %finish %end %routine Dump Fragment(%record(FragmentFm)%name F) %record(DlineFm)%name L Dump4(F_Size) Dump4(F_From) Dump4(F_To) Reloc(F_Code, Cseg) Dump4(F_CodeSize) %return %if Debug Options&1 # 0 L == F_Lines %return %if L == NIL %while L_Link ## NIL %cycle Dump Line(L_Link_Line-L_Line, L_Link_Ca-L_Ca) L == L_Link %repeat Dump Line(F_To-L_Line, F_Code+F_CodeSize-L_Ca) Dump2(16_0101) %if F_Padding # 0 %end %routine Dump File(%record(Filefm)%name F) %record(FragmentFm)%name Fr Dump4(F_Size) Dump4(0) {date} Dump Debug String(F_File) Dump4(F_N) Fr == F_Frag %while Fr ## NIL %cycle Dump Fragment(Fr) Fr == Fr_Link %repeat %end Dump4(Files Size<<16 ! Debug Fileinfo) {001} %if Debug Options&4 = 0 %start F == Debug Files %while F ## NIL %cycle Dump File(F) F == F_Link %repeat %finish Dump4(0) {terminating length} {001} %end {001} Select Debug Area {001} Dump Section {001} %if Debug Options&2 = 0 %start Dump Formats(Fglobals) Dump Variables(Dglobals) %finish Dump Procedures(P) {001} Dump FileInfo {001} Select Code Area {001} %end {001} Bp = Bp+1; Head == Blocks(Bp) Display = Head_Display Wanted = Head_Flags&Used Line Basis = Head_Line Base Diag Basis = Head_Diag Base Code Basis = Head_Code Base Line Info_Pending = 0 Line Info_Line = Current Line Line Info_Last Line = Current Line Line Info_ Ca = Code Basis Line Info_Last Ca = Code Basis Bflags = 0 Bflags = Bflags ! 16_80 %if Head == Block List %and Options&LL Trace # 0 Bflags = Bflags ! 16_20 %if Head == Main Head Bflags = Bflags ! 16_10 %if Head_Attr&Attr Prim # 0 Bflags = Bflags ! 16_04 %if Head_Attr&Attr Both # 0 Bflags = Bflags ! 16_02 %if Head_Attr&Attr Xdef # 0 Bflags = Bflags ! 16_01 %if Head_Event Mask # 0 DebugA = 0 {001} Select Code Area %if Wanted # 0 %start %if DEBUG # 0 %start {001} Debug New Fragment(Ca, Current Line) %if InPrim = 0 DebugP == NEW(ProcedurefmType) {001} DebugA = Addr(DebugP) {001} DebugP = 0 {001} DebugP_Proc == Head {001} %finish {001} %if Options&LL Decode # 0 %start Select Output(Decode Out) Dump Encoded(-1) Dump Encoded(Head_Code Base) Dump Encoded(Head_Ca) N = Current Line; N = 0 %if Head_Attr&Attr Prim # 0 Dump Encoded(N); Put String (Block Id) Select Output(Object Out) %finish Frame = -Head_Frame %if Head == Entry Head %start Relocate(-Min SB, Cseg, Dsym, SymbolReloc) Dump4(16_E51F9000 + 8 +4) {LDR _ Sb, [.-12]} ->OK %finish %if Head_Link == NIL %start N = 0 %else N = (Head_Link_Code Base-Ca)>>2 CSR("code block too large") %if N>>16 #0 %finish Dump2(N&16_FFFF); Dump(Bflags); Dump((Display>>2)&255) %if Bflags&1 # 0 %start Dump4(Head_Event Mask) Dump4(Items(Head_Event Body)_Ca-Head_Code Base) Dump4(Items(Head_Event Label)_Ca-Head_Code Base) %finish %if Head_Attr&Attr Xdef # 0 %and Head_Attr&Attr Needs Gp # 0 %start At = Ca Relocate(-Min SB, Cseg, Dsym, SymbolReloc) %finish %if Options&LL Vars # 0 %start Select Diag Area Dump2(Current Line&16_FFFF) Dump2(Head_Diag Size) Dump(Length(Block Id)) Dump(Charno(Block Id, N)) %for N = 1, 1, Length(Block Id) Select Code Area %finish %if Head_Flags&No Entry = 0 %start Warn("Misplaced block ".ItoS(Head_Ca,0).ItoS(Ca, 1)) %if Head_Ca # Ca %if Head_Attr&Attr Xdef # 0 %and Head_Attr&Attr Needs Gp # 0 %start %if Head_Attr&Attr Both # 0 %start Dump4(16_E51F7000 + 8 + Ca - At) {LDR_R7, [.-12]} %finish %finish {can be squeezed if no locals & no parameters} %if Head_Attr&Attr Both # 0 %start {simple display updating} %if Head_Attr&Attr Xdef # 0 %start Dump4(16_E5175000 - Display) {LDR _ R5, D(R7)} %else Dump4(16_E5195000 - Display) {LDR _ R5, D(Sb)} %finish %finish Warn("parameter overflow") %if Head_Pframe>>10 # 0 Dump4(16_E1A0B00C) {MOV _ R11, R12} %if Head_Pframe # 0 %start N = 16_E52C0004 {STR _ R0, [Sp, #-4]!} %if Head_Pframe > 4 %start N = 16_E92C0003 {STM _ Sp!, } %if Head_Pframe > 8 %start N = N ! 2_0100 {STM _ Sp!, } %if Head_Pframe > 12 %start N = N ! 2_1000 {STM _ Sp!, } %finish %finish %finish Dump4(N) %finish Dump4(16_E92CCE20) {STMDB _ Sp!, } Dump4(16_E28CAF05) {ADD _ Fp, Sp, #20} {onto PC} %if Head_Attr&Attr Xdef # 0 %and Head_Attr&Attr Needs Gp # 0 %start %if Head_Attr&Attr Both = 0 %start Dump4(16_E51F9000 + 8 + Ca - At) {LDR _ Sb, [.-12]} %else Dump4(16_E1A09007) {MOV _ Sb, R7} %finish %finish %if Head_Attr&Attr Both # 0 %start {simple display updating} Dump4(16_E509A000 - Display) {STR _ Fp, D(Sb)} %finish {Now allocate the stack frame} %constintegerarray ULDR(1:4) = 16_E4994000, {LDR _ 4, [SB]} 16_E8990030, {LDMIA _ Sb, <4,5>} 16_E8990070, {LDMIA _ Sb, <4,5,6>} 16_E89900F0 {LDMIA _ Sb, <4,5,6,7>} %constintegerarray USTR(1:3) = 16_E52C4004, {STR _ 4, [SP, #-4]!} 16_E92C0030, {STMDB _ SP!, <4,5>} 16_E92C0070 {STMDB _ SP!, <4,5,6>} %constinteger STM4 = 16_E92C00F0 {STMDB _ SP!, <4,5,6,7>} %if Frame # 0 %start %if Options&LL Assigned # 0 %start N = Frame>>2; M = N&3 %if N <= 3 %then M = N %else M = 4 Dump4(ULDR(M)) M = N&3 %if M # 0 %start Dump4(USTR(M)) N = N-M %finish %if N # 0 %start N = N>>2 %if N <= 5 %start %cycle Dump4(STM4) N = N-1 %repeat %until N = 0 %else Op = 16_E3A0 8000 {MOV _ 8, #0} M = 16 %cycle M = M-1 %and N = N>>2 %while N&3 = 0 Dump4(Op ! (M&15)<<8 ! N&255) {MOV _ 8, #n} Op = 16_E388 8000 {ORR _ 8, 8, #0} M = M-4 {another 8 bits worth} N = N>>8 %repeat %until N = 0 Dump4(STM4) Dump4(16_E2588001) Dump4(16_CAFF FFFC) %finish %finish %else N = Frame M = 16 %while N # 0 %cycle M = M-1 %and N = N>>2 %while N&3 = 0 Dump4(16_E24CC000 ! (M&15)<<8 ! N&255) {SUB _ Sp, #n} M = M-4 {another 8 bits worth} N = N>>8 %repeat %finish %finish %finish %finish OK: %cycle Readsymbol(Code) %unless 1 <= Code <= Max Dir %start D(*): CSR("Corrupt p2 directive".ItoS(Code, 1)) %finish Show Code(Code) %if Options&LL Mon # 0 ->D(Code) {******** Debugger Support ********} D(Dir DEBUG Start Proc): D1 = Encoded Value {Type} {001} D2 = Encoded Value {Sourcepos} {001} %if DebugP ## NIL %start {001} DebugP_Type = D1 {001} DebugP_StartPos = D2 {001} DebugP_Args = 0 DebugP_Name == Heap String(BlockId) {001} DebugP_StartFile == DebugF %finish {001} %continue {001} {001} D(Dir DEBUG End Proc): D2 = Encoded Value {Sourcepos} {001} %if DebugP ## NIL %start {001} DebugP_EndPos = D2 {001} DebugP_EndFile == DebugF %finish {001} %continue {001} {**********************************} D(Dir Start Block): N = Encoded Value Get String(Block Id, 127) {002} %if Debug # 0 %and Wanted # 0 %and InPrim = 0 %start Debug Terminate Fragment(Ca, Current Line-1) Dump Block(Level+1, 0, InPrim, D1) {001} Debug New Fragment(Code Basis, Current Line) %else Dump Block(Level+1, 0, InPrim, D1) {001} %finish %if DEBUG # 0 %and D1 # 0 %start {001} {Add D1 to the proc list at this level} {001} Debug List_Next == Record(D1) {001} Debug List == Record(D1) {001} %finish {001} %if Options&LL Decode # 0 %start Select Output (Decode Out) Dump Encoded(-2); Dump Encoded(Previous Ca) Dump Encoded(Code Basis) Select Output (Object Out) %finish Select Code Area %continue D(Dir Diag): Dump Diag Entry %continue %integerfn Type Map(%integer Prt, Fm, Ptype) %switch T(0:15) ->T(Prt) T( 0): %result = 0 T( 1): {integer} %result = Type Signed Word <<8 + 0 T( 2): {short} %result = Type Signed Half <<8 + 0 T( 3): {byte} %result = Type Unsigned Byte <<8 + 0 T( 4): {real} %result = Type Float <<8 + 0 T( 5): {longreal} %result = Type Double <<8 + 0 T( 6): {string} %result = Type Unsigned Byte <<8 + 0 T( 7): {record} %result = (-Fm) <<8 + 0 T( 8): {boolean} %result = Type Unsigned Byte <<8 + 0 T( 9): {char} %result = Type Unsigned Byte <<8 + 0 T(10): {byte-enum} %result = Type Unsigned Byte <<8 + 0 T(11): {word-enum} %result = Type Unsigned Half <<8 + 0 T(12): {pointer} %result = Type Map(Ptype, Fm, 0) <<8 + 1 T(13): {set} %result = 0 T(14): {unknown} %result = 0 T(15): %result = Type Map(Ptype, Fm, Ptype) + 1 %end %routine Append Diag(%record(DvarFm)%name D) %if Dfm ## NIL %start {to records} %if Dfm_F_Vars == NIL %start D_Link == D %else D_Link == Dfm_F_Vars_Link Dfm_F_Vars_Link == D %finish Dfm_F_Vars == D %else %if DebugP == NIL {to globals} %if Dglobals == NIL %start D_Link == D %else D_Link == Dglobals_Link Dglobals_Link == D %finish Dglobals == D %else {to locals} %if DebugP_Vars == NIL %start D_Link == D %else D_Link == DebugP_Vars_Link DebugP_Vars_Link == D %finish DebugP_Vars == D %finish %end D(Dir DEBUG Var): %begin %record(DvarFm)%name D %integer N, Prt, Ind, Base, Btype, Ptype, Disp, Fm, Type %integer Offset, Size %string(255) Id Get String(Id, 255) Prt = Encoded Value {Primary type} Ind = Encoded Value {Indirect bit} N = Encoded Value {Class: 1=Local, 2=Static} %if N = 1 %start N = 3 {Automatic} %else %if N = 2 N = 2 {Static} %else N = 0 {Unknown} %finish Btype = Encoded Value {BaseType} Ptype = Encoded Value {PointerType} Offset = Encoded Value {Displacement} Fm = Encoded Value {Format} Size = Encoded Value {Size} %return %if Prt = 0 {Enumerated definition?} D == NEW(DvarFmType); D = 0 D_Ident == Heap String(Id) D_Class = N D_Size = Size D_Offset = Offset D_SourcePos = Current Line D_Type = Type Map(Prt, Fm, Ptype) D_Type = D_Type+1 %if Ind # 0 Append Diag(D) %end %continue D(Dir DEBUG Array): %begin %integer Type, Fm %record(DvarFm)%name D %record(ArrayFm)%name A %string(255) S D == NEW(DvarFmType) D = 0 Get String(S, 255) D_Ident == Heap String(S) D_Class = -1 {array marker} A == NEW(ArrayFmType) D_Array == A A_Lower = Encoded Value {Lower bound} A_Upper = Encoded Value {Upper Bound} A_Total = Encoded Value {Total Size} Type = Encoded Value {Type} Fm = Encoded Value {Format} A_Type = Type Map(Type, Fm, 0) Append Diag(D) %end %continue D(Dir Record On): Record Diags = Encoded Value Record Basis = Formpt(Record Diags) + Area Base_Record %if DEBUG # 0 %start Dfm == DebugFm(Record Diags) Dfm_F == NEW(DFormatFmType) Dfm_F_Vars == NIL %if DebugP == NIL %start {global} %if Fglobals == NIL %start Dfm_F_Link == Dfm_F %else Dfm_F_Link == Fglobals_Link Fglobals_Link == Dfm_F %finish Fglobals == Dfm_F %else %if DebugP_Formats == NIL %start Dfm_F_Link == Dfm_F %else Dfm_F_Link == DebugP_Formats_Link DebugP_Formats_Link == Dfm_F %finish DebugP_Formats == Dfm_F %finish %finish %continue D(Dir Record Off): %if Dumping Diags("") %start ;%finish Select Code Area Record Diags = 0 %if DEBUG # 0 %start Dfm == NIL %finish %continue D(Dir Slabel): D(Dir Label): N = Encoded Value+Reloc Item == Items(N) %continue %if Wanted = 0 %or Item_Flags&Deleted # 0 Set CC = 0 %if Item == CC Label %if Item_Flags&Duplicated # 0 %start Item_Flags = Item_Flags-Duplicated %continue %finish %unless Item_Ca = Ca %start Select Output(Report) Printstring("Label error at line") Write(Current Line, 1) Printstring(" -- label actually at") Write(Ca, 5) Printstring(" but expected at") Write(Item_Ca, 5) Newline %monitor %if Options&LL Mon # 0 Select Output(Object Out) %finish D(Dir Mark User): %continue D(Dir Const Addr): N = Encoded Value N = Encoded Value Item == Next Item(Caddr Type) %continue %if Wanted = 0 C = Item_Cond At = (Ca+8) - (Item_Value+Area Base_Constant) %if At&3 # 0 %start %if Item_Flags&VeryLong # 0 %start Dump4(16_E24F 0800 ! C<<12 ! At>>16) Dump4(16_E240 0C00 ! C<<12 ! C<<16 ! At>>08&255) Dump4(16_E240 0000 ! C<<12 ! C<<16 ! At&255) %else %if Item_Flags&Long # 0 Dump4(16_E24F 0C00 ! C<<12 ! At>>8) Dump4(16_E240 0000 ! C<<12 ! C<<16 ! At&255) %else CSR("bad Caddr") %unless 0 <= At <= 255 Dump4(16_E24F 0000 ! C<<12 ! At) %finish %else At = At>>2 %if Item_Flags&VeryLong # 0 %start Dump4(16_E24F 0700 ! C<<12 ! At>>16) Dump4(16_E240 0B00 ! C<<12 ! C<<16 ! At>>08&255) Dump4(16_E240 0F00 ! C<<12 ! C<<16 ! At&255) %else %if Item_Flags&Long # 0 Dump4(16_E24F 0B00 ! C<<12 ! At>>8) Dump4(16_E240 0F00 ! C<<12 ! C<<16 ! At&255) %else CSR("bad Caddr") %unless 0 <= At <= 255 Dump4(16_E24F 0F00 ! C<<12 ! At) %finish %finish %continue D(Dir Const Load): N = Encoded Value N = Encoded Value Item == Next Item(Cload Type) %continue %if Wanted = 0 C = Item_Cond At = (Ca+8)-(Item_Value+Area Base_Constant) {-ve disp} {At = {X<<20 ! Y<<12 ! Z} %if Item_Flags&VeryLong # 0 %start {SUB _ R14, Pc, Z<<20} {SUB _ R14, R14, Y<<12} {LDR _ R?, [R14, Z]} Dump4(16_E24F 0600 ! C<<12 ! At>>20) Dump4(16_E240 0A00 ! C<<12 ! C<<16 ! At>>12&255) Dump4(16_E510 0000 ! C<<12 ! C<<16 ! At&16_FFF) %else %if Item_Flags&Long # 0 CSR("bad long cload") %unless At>>(12+8) = 0 {SUB _ R14, Pc, Y<<12} {LDR _ R?, [R14, Z]} Dump4(16_E24F 0A00 ! C<<12 ! At>>12) Dump4(16_E510 0000 ! C<<12 ! C<<16 ! At&16_FFF) %else CSR("Bad Cload") %unless 0 <= At <= 16_0FFF Dump4(16_E51F 0000 ! C<<12 ! At&16_FFF) %finish %continue D(Dir Real Load): N = Encoded Value N = Encoded Value N = Encoded Value<<15 {type flag: 0=short, 1=long} Item == Next Item(Rload Type) %continue %if Wanted = 0 At = ((Ca+8)-(Area Base_Constant+Item_Value))>>2 {-ve disp} {Disp = At<<2 = X<<18 ! Y<<10 ! Z<<2} %if Item_Flags&VeryLong # 0 %start {SUB _ R14, Pc, X<<18} {SUB _ R14, R14, Y<<10} {LDF _ R?, [R14, Z]} Dump4(16_E24F E700 ! At>>16) Dump4(16_E24E EB00 ! At>>8&255) Dump4(16_ED1E 0100 ! Item_Cond<<12 ! At&16_FF ! N) %else %if Item_Flags&Long # 0 CSR("bad long cload") %unless At>>16 = 0 {SUB _ R14, Pc, Y<<12} {LDF _ R?, [R14, Z]} Dump4(16_E24F EB00 ! At>>8) Dump4(16_ED1E 0100 ! Item_Cond<<12 ! At&16_FF ! N) %else CSR("Bad Cload") %unless 0 <= At <= 16_0FF Dump4(16_ED1F 0100 ! At ! Item_Cond<<12 ! N) %finish %continue D(Dir Spec Load): N = Encoded Value N = Encoded Value Item == Next Item(Sload Type) %continue %if Wanted = 0 X == External(Item_Value) N = 16_E599 0000 ! Item_Cond<<12 At = X_Disp N = N !! 16_0080 0000 %and At = -At %if At < 0 CSR("external out of reach") %unless N < 4096 Dump4(N ! At) %continue D(Dir Branch): N = Encoded Value N = Encoded Value Item == Next Item(Branch Type) %continue %if Item_Flags = Deleted %or Wanted = 0 CSR("label deleted") %if Item_Label_Flags&Deleted # 0 %if Item_Flags&Absorbed # 0 %start Set CC = (Branch(Item_Cond)&16_F0) !! 16_E0 CC Label == Item_Label %else At = Item_Label_Ca CSR("Jump to missing switch label") %if At < 0 Dump Branch(Branch(Item_Cond), At) %finish %continue D(Dir McLabel): M = Encoded Value+Reloc {the label} N = Encoded Value {the instruction} %continue %if Wanted = 0 M = Items(M)_Ca {address of label} Dump4(N ! ((M-Ca-8)>>2)&16_00FF FFFF) %continue D(Dir Line): Current Line = Encoded Value Update Line %if Wanted # 0 %and Head_Attr&Attr Prim = 0 %if Options&LL Decode # 0 %start Select Output(Decode Out) Dump Encoded(Current Line); Dump Encoded(Ca) Select Output(Object Out) %finish %continue D(Dir Include): Get String(Swork, 127); Update Include(Swork) %continue D(Dir Return): {*** return from block ***} Item == Next Item(Return Type) N = Encoded Value %continue %if Wanted = 0 %if Debug # 0 %and DebugP ## NIL %start %begin %record(PreturnFm)%name P == NEW(PreturnFmType) P_Ca = Ca P_Link == DebugP_Return DebugP_Return == P DebugP_Nreturns = DebugP_Nreturns+1 %end %finish %if Head_Attr&Attr Both # 0 %start Dump4(16_E51A5014) {LDR _ R5, -20(Fp)} Dump4(16_E5095000 - Display) {STR _ R5, D(Sb)} %finish Dump4(16_E95A9600) {LDMDB _ Sb, Fp, Sp, Pc^} %continue D(Dir Ext): {*** external object definition ***} Readsymbol(N) Skip Bytes(N+1) N = Encoded Value %continue D(Dir Call): N = Encoded Value Item == Next Item(Call Type) %continue %if Wanted = 0 Dump Branch(16_EB, Item_Label_Ca) %continue D(Dir Xref): N = Encoded Value+Xreloc {external reference} M = Encoded Value {register} %continue %if Wanted = 0 X == External(N) N = X_Disp; N = 16_0080 0000 - N %if N < 0 Dump4(16_E5990000 !! N ! M<<12) %continue D(Dir xCall): N = Encoded Value Item == Next Item(External Type) %continue %if Wanted = 0 X == External(Item_Value) Relocate(16_EB000000, CSeg, External Index(X), PcReloc) %continue D(Dir Assigned): Next Prim(16_0B); %continue D(Dir Prim): N = Encoded Value %if N = Enter Prim %then Op = 16_AB %else Op = 16_EB Next Prim(Op); %continue D(Dir Area): M = Encoded Value {area} N = Encoded Value {offset} %if M = 0 %start {code area} Select Code Area %else %if M = 1 {global area} Select Global Area(N) %else %if M = 2 {constant area} Select Pure Area(Area Base_Constant + N) %else %if M = 3 {global array area} Select Global Area(Area Base_Global Array + N + Min SB) %else CSR("Area/1") %finish %continue D(Dir Swdef): Lb = Encoded Value+Reloc Ub = Encoded Value+Reloc %for N = Lb, 1, Ub %cycle At = Items(N)_Ca %if At < 0 %start {missing} M = Prim Map(Sw Jump) At = Items(M)_Ca+Sw Error %if M # 0 %finish Relocate(At, CSeg, CSym, SymbolReloc) %repeat %continue D(Dir Sw Ref): N = Encoded Value %continue %if Wanted = 0 Relocate(Area Base_Constant+N, CSeg, CSym, SymbolReloc) %continue D(Dir Modify): N = Encoded Value {address} M = Encoded Value {increment} N = Current Address-N Byte(N+3) = Byte(N+3) & (\1) {->post indexed} Byte(N+2) = Byte(N+2) & 127 %and M = -M %if M < 0 Byte(N+1) = Byte(N+1) ! (M>>8)&15 Byte(N+0) = M&255 CSR("bad modification") %if M>>16 # 0 %continue D(Dir Header): N = Encoded Value {area code} M = Encoded Value {zero'th addr} %if N = 1 %start {own area} Relocate(M-Min SB, DSeg, DSym, SymbolReloc){add in own base} %else %if N = 2 {constant area} Relocate(M+Area Base_Constant, DSeg, CSym, SymbolReloc) {add in code base} %else %if N = 3 {own array area} Relocate(M+Area Base_Global Array, DSeg, DSym, SymbolReloc){add in own base} %else CSR("Bad header area") %finish Relocate(Encoded Value+Area Base_Constant, DSeg, CSym, SymbolReloc) {relocate DV} %continue D(Dir Init): N = Encoded Value {area flag} Work = Encoded Value {disp} %if N = 0 %start {SB relative} Relocate(N-Min SB, DSeg, DSym, SymbolReloc) %else %if N = -1 {constant area} Relocate(Work+Area Base_Constant, DSeg, CSym, SymbolReloc) %else {external} CSR("INIT") %finish %continue D(Dir Thunk): N = Encoded Value+Reloc {procedure to call} M = Encoded Value {static slot} Item == Next Item(Thunk Type) %continue %if Wanted = 0 Select Global Area(M) Relocate(Item_Label_Ca, Dseg, Csym, SymbolReloc) Select Code Area %continue D(Dir xThunk): N = Encoded Value+Xreloc M = Encoded Value %continue %if Wanted = 0 Select Global Area(M) Relocate(0, Dseg, External Index(External(N)), SymbolReloc) Select Code Area %continue D(Dir Dump): N = Encoded Value %if Ca == Code Basis %start %if Wanted = 0 %start Skip Bytes(N) %else %cycle N = N-1 Readsymbol(xxx) %if Set CC # 0 %and N&3 = 0 %start CSR("bad CC to change") %if xxx>>4 # 14 xxx = xxx !! Set CC %finish Dump(xxx) %repeat %until N <= 0 %finish %else %cycle Readsymbol(xxx); Dump(xxx) N = N-1 %repeat %until N <= 0 %finish %repeat D(Dir End Block): N = Encoded Value { 1} N = Encoded Value { 2} N = Encoded Value { 3} N = Encoded Value { 4} N = Encoded Value { 5} N = Encoded Value { 6} N = Encoded Value { 7} N = Encoded Value { 8} N = Encoded Value { 9} N = Encoded Value {10} N = Encoded Value {11} N = Encoded Value {12} %if Debug # 0 %start {001} %if Wanted # 0 %and InPrim = 0 %start Debug Terminate Fragment(Code Basis, Current Line) %finish Debug List_Next == NIL {001} %if DebugP ## NIL %start {001} DebugP_Inner == Debug Base_Next {001} %else {001} DebugA = Addr(Debug Base_Next) {001} %finish {001} %finish {001} Previous Ca = Ca %if Wanted # 0 %and Level >= 0 %start %if Head_Attr&Attr Prim = 0 %start Current Line = Current Line+1 %if Dumping Diags("") %start ;%finish %finish %finish %return %if Finish >= 0 %if Debug # 0 %start {001} DebugP == Record(Total Debug List) {001} Allocate Debug Information(DebugP) {001} Allocate Buffer(Bseg, Bugs Size) {001} Dump Debug Information(DebugP) {001} %finish {001} {close off object file} %if Options&LL Decode # 0 %start Select Output(Decode Out) Dump Encoded(-5) Dump Encoded(Extra Base); Dump Encoded(Xentry Base + Xentry) Select Output(Object Out) %finish %if Options&LL Assigned # 0 %start {4-words to speed up unassigning} Select Global Area(0) Dump2(16_8080); Dump2(16_8080) Dump2(16_8080); Dump2(16_8080) Dump2(16_8080); Dump2(16_8080) Dump2(16_8080); Dump2(16_8080) %finish %begin {fill in external data links and add external definitions} %record(Usefm)%name U %record(Xfm)%name X %integer N U == Total Uses %while U ## NIL %cycle X == U_X; U == U_Link %continue %if X == NIL %or X_Flags&Ext Prim # 0 N = External Index(X) %if X_Flags&Ext Defn = 0 %start {external reference} %if X_Flags&Ext Code = 0 %start {data reference} Select Global Area(X_Disp) {SB relative} Relocate(0, DSeg, N, SymbolReloc) {S-area relative} %finish %finish %repeat %end %begin {fill in BLOCK area} %integer J, N %string(255) M %routine Dump Block Diag Pointer(%record(Blockfm)%name B) {NOTE: these are dumped in reverse order} %if B ## NIL %start Dump Block Diag Pointer(B_Link) Relocate(B_Diag Base, CSeg, CSym, SymbolReloc) %finish %end Select Pure Area(Area Base_Block) %if Options&LL Trace # 0 %start Dump(Interface_Language) M = Interface_Module N = Length(M) Dump(N); Dump(Charno(M, J)) %for J = 1, 1, N N = N+1 %cycle N = N+1 %exit %if N&3 = 0 Dump(0) %repeat Dump Block Diag Pointer(Block List) %if Options&LL Records = 0 %start Dump4(0) %else Relocate(Area Base_Record, CSeg, CSym, SymbolReloc) %finish Relocate(Area Base_Block, CSeg, CSym, SymbolReloc) %finish Dump4(16_F82F0000) {Magic marker} %end %if Main Program # 0 %start {pull in the main entry point} Select Pure Area(0) %if Debug = 0 %start Relocate(16_EA000000, CSeg, BSym, Pc Reloc) {B _ startup} %else Relocate(16_EA000000, CSeg, ESym, Pc Reloc) {B _ startup} %finish Entry Reference = 1 %finish Rel1 No = Segment Reloc(CSeg)_Entries Rel2 No = Segment Reloc(DSeg)_Entries Rel3 No = Segment Reloc(Bseg)_Entries Dump Header Dump Strings Dump Symbols Dump Segment(CSeg); Dump Relocation(CSeg) Dump Segment(DSeg); Dump Relocation(DSeg) %return %if Debug = 0 Dump Segment(BSeg); Dump Relocation(BSeg) %end %integer Z %if Interface_Language = 0 %start Main Entry Id = "3L_imp___entry_point" %else %if Interface_Language = 1 Main Entry Id = "3L_pascal___entry_point" %else Main Entry Id = "3L_?___entry_point" %finish Debug Base = 0 {001} Select Output(Report) Bp = -1 Reloc = 0 Xreloc = 0 Ip = Interface_Def Count Select Input(Directives In) Input Block(0, -1) Interface_Block Count = Bp {correct the guess} Ep = Encoded Value Z = Encoded Value Min SB = Encoded Value Max SB = (Interface_Global Size + Interface_Prim Global Size+3)&(\3) Area Size_Global Array = (Interface_Global Array Size+3)&(\3) Area Size_Constant = (Interface_Constant Size - + Interface_Prim Constant Size + 3)&(\3) Reloc = Interface_Def Count + Interface_Ref Count+1 Xreloc = Interface_External Count Ip = Reloc + Interface_Prim Def Count Select Input(PrimDir In) Input Block(Ip, -1) Define Prim Map Mark Unused Blocks Process Blocks Allocate Blocks Mark Forward Stretch Blocks Allocate Buffer(CSeg, Code Size) Allocate Buffer(DSeg, Data Size) Segment Reloc(Cseg) = 0; Segment Reloc(Cseg)_Base = 0 {001} Segment Reloc(Dseg) = 0; Segment Reloc(Dseg)_Base = Code Size {001} Segment Reloc(Bseg) = 0; Segment Reloc(Bseg)_Base = Code Size+Data Size {001} Select Output(Object Out) Bp = -1 %if Options&LL Decode # 0 %start %begin %string(127) Compiler Id Compiler Id = "*Compiled by ". Product Code . ":" - . P1Version . "-" - . P2Version . "-" - . P3Version . " " - . Date . " " - . Time Select Output(Decode Out) Dump Encoded(-3); Put String (Compiler Id ); Dump Encoded(0) Dump Encoded(0);Dump Encoded(0) Put String (Interface_Source File) Select Output(Object Out) %end %finish Z = Symbol Entry(CodeArea, 1, 0, CodeArea) {$CODEAREA} Z = Symbol Entry(DataArea, 1, 0, DataArea) {$DATAAREA} %if Debug # 0 %start Z = Symbol Entry(DbugArea, 1, 0, DbugArea) {$BUGSAREA} Z = Symbol Entry(FreeArea, 2, 0, DataArea) %if Main Program # 0 {?___ENTRY_POINT} %else Z = Symbol Entry(DbugArea, 2, 0, DataArea) %if Main Program # 0 {?___ENTRY_POINT} %finish Reloc = 0; Xreloc = 0 Ip = Interface_Def Count Select Input(Directives In); Reset Input Debug Include(Interface_Source File, 0, 0) Dump Block(-1, 1, 0, Total Debug List) Reloc = Interface_Def Count + Interface_Ref Count+1 Xreloc = Interface_External Count Ip = Reloc + Interface_Prim Def Count Select Input(PrimDir In); Reset Input Z = Encoded Value {skip ref count} Z = Encoded Value {skip def count} Z = Encoded Value {skip block count} Z = Encoded Value {skip external count} Z = Encoded Value {skip global size} Z = Encoded Value {skip formats} Dump Block(-1, -1, 1, Z {dummy}) {001} %if Options&LL Decode # 0 %start Select Output(Decode Out) Dump Encoded(-4) Select Output(Object Out) %finish %end %endoffile