
<<M2IImpl.mesa>>
<<Modula-2 Code-Generator, Part 2>>
<<Last Edted by: Gutknecht, October 7, 1985 3:54:22 pm PDT>>
    <<Satterthwaite December 10, 1985 5:52:12 pm PST>>

DIRECTORY
Rope: TYPE USING [ROPE],
FS: TYPE USING [StreamOpen],
IO: TYPE USING [STREAM, PutChar, Close],
M2D: TYPE USING [ObjPtr, ModulePtr],
M2S: TYPE USING [IdBuf, Mark],
M2I: TYPE USING [Relation, inv];

M2IImpl: CEDAR PROGRAM 
IMPORTS FS, IO, M2S
EXPORTS M2I = 

BEGIN OPEN M2I;

DFC: CARDINAL = 61B; LIQB: CARDINAL = 62B; J5: CARDINAL = 66B; DJ: CARDINAL = 67B; CALL: CARDINAL = 70B; RX: CARDINAL = 102B; BC: 
CARDINAL = 103B; ADD: CARDINAL = 104B; SUB: CARDINAL = 105B; LADD: CARDINAL = 106B; LSUB: CARDINAL = 107B; DUP: CARDINAL = 110B; 
DIS: CARDINAL = 111B; EXDIS: CARDINAL = 113B; SFC: CARDINAL = 114B; SFCI: CARDINAL = 115B; RETN: CARDINAL = 116B; SMUL: CARDINAL = 
121B; UDIV: CARDINAL = 122B; KFC: CARDINAL = 124B; J1: CARDINAL = 126B; SJ: CARDINAL = 127B; LC: CARDINAL = 130B; LR: CARDINAL = 
140B; SR: CARDINAL = 160B; QOR: CARDINAL = 200B; QAND: CARDINAL = 201B; QRX: CARDINAL = 202B; QBC: CARDINAL = 203B; QADD: CARDINAL 
= 204B; QSUB: CARDINAL = 205B; QLADD: CARDINAL = 206B; QLSUB: CARDINAL = 207; ALS: CARDINAL = 210B; AL: CARDINAL = 211B; ASL: 
CARDINAL = 212B;  AS: CARDINAL = 213B; CST: CARDINAL = 214B; RET: CARDINAL = 216B;  RETK: CARDINAL = 217B; LIP: CARDINAL = 220B; 
SIP: CARDINAL = 221B; LIB: CARDINAL = 222B; SFP: CARDINAL = 223B; ADDB: CARDINAL = 224B; SUBB: CARDINAL = 225B; J2: CARDINAL = 
226B; JB: CARDINAL = 227B; RB: CARDINAL = 230B; WB: CARDINAL = 231B; RSB: CARDINAL = 232B; WSB: CARDINAL = 233B; PIN: CARDINAL = 
234B; POUT: CARDINAL = 235B; PSB: CARDINAL = 237B; LRI: CARDINAL = 240B; SRI: CARDINAL = 260B; ROR: CARDINAL = 300B; RAND: CARDINAL 
= 301B; RRX: CARDINAL = 302B; RBC: CARDINAL = 303B; RADD: CARDINAL = 304B; RSUB: CARDINAL = 305B; RLADD: CARDINAL = 306B; RLSUB: 
CARDINAL = 307B; RXOR: CARDINAL = 310B; RFU: CARDINAL = 312B; RVADD: CARDINAL = 314B; RVSUB: CARDINAL = 315B; RUADD: CARDINAL = 
316B; RUSUB: CARDINAL = 317B; LGF: CARDINAL = 320B; LFC: CARDINAL = 321B; LIDB: CARDINAL = 322B; ADDDB: CARDINAL = 324B; SUBDB: 
CARDINAL = 325B; J3: CARDINAL = 326B; JDB: CARDINAL = 327B; RAI: CARDINAL = 330B; WAI: CARDINAL = 331B; RRI: CARDINAL = 332B; WRI: 
CARDINAL = 333B; INP: CARDINAL = 334B; OUT: CARDINAL = 335B; RJEB: CARDINAL = 341B; RJLB: CARDINAL = 342B; RJLEB: CARDINAL = 343B; 
RJNEB: CARDINAL = 345B; RJGEB: CARDINAL = 346B; RJGB: CARDINAL = 347B; RJNEJ: CARDINAL = 351B; RJGEJ: CARDINAL = 352B; RJGBJ: 
CARDINAL = 353B; RJEBJ: CARDINAL = 355B; RJLBJ: CARDINAL = 356B; RJLEJ: CARDINAL = 357B; JEBB: CARDINAL = 360B; JNEBB: CARDINAL = 
361B; JEBBJ: CARDINAL = 362B; JNEBJ: CARDINAL = 363B; SHL: CARDINAL = 370B; SHR: CARDINAL = 371B; SHD: CARDINAL = 372B; FSDB: 
CARDINAL = 373B; FLIP: CARDINAL = 374B; FLOP: CARDINAL = 375B;

LIPC: CARDINAL = 323B; --load PC; virtual opcode to signal adj opd to optimizing pass

Trap: CARDINAL = 0; Move: CARDINAL = 1; Mult: CARDINAL = 2; Div: CARDINAL = 3; Mod: CARDINAL = 4; RealAdd: CARDINAL = 5; RealSub: 
CARDINAL = 6; RealMult: CARDINAL = 7; RealDiv: CARDINAL = 8; Alloc: CARDINAL = 9; Dealloc: CARDINAL = 10; MakeBit: CARDINAL = 11; 
MakeBits: CARDINAL = 12;

OBJFILE: CARDINAL = 220;

MaxPC: CARDINAL = 12000;
CodeArray: TYPE = PACKED ARRAY [0..MaxPC] OF [0..255];
code: REF CodeArray _ NEW [CodeArray];
pc: PUBLIC CARDINAL;

MaxEntry: CARDINAL = 256;
EntryArray: TYPE = ARRAY [0..MaxEntry] OF CARDINAL;
ent: REF EntryArray _ NEW [EntryArray _ ALL [0]];
prc: REF EntryArray _ NEW [EntryArray _ ALL [0]];
ec: CARDINAL;

MaxRel: CARDINAL = 1000;
RelArray: TYPE = ARRAY [0..MaxRel] OF CARDINAL;
rel: REF RelArray _ NEW [RelArray];
rc: CARDINAL;

MaxSec: CARDINAL = 1000;
SecArray: TYPE = ARRAY [0..MaxSec] OF CARDINAL;
sec: REF SecArray _ NEW [SecArray];

MaxStr: CARDINAL = 1000;
StrArray: TYPE = PACKED ARRAY [0..MaxStr] OF CHAR;
str: REF StrArray _ NEW [StrArray];
strx: CARDINAL;

len: ARRAY [0B..37B] OF CARDINAL =
[1, 1, 1, 1, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3];

jop: ARRAY Relation OF CARDINAL = [J3, RJNEB, RJLB, RJLEB, RJGEB, RJGB, RJEB, JDB];

neg: ARRAY [341B .. 361B] OF CARDINAL =
[RJNEB, RJGEB, RJGB, 0, RJEB, RJLB, RJLEB, 0, 0, 0, 0, 0, 0, 0, 0, JNEBB, JEBB];

err: PROC [n: CARDINAL] = { M2S.Mark [n] };

InitGenerator: PUBLIC PROC = { strx _ 0; pc _ 0; rc _ 0; ec _ 0; PutOI [J1] };

Entry: PUBLIC PROC [no: CARDINAL] = { ent[ec] _ pc; prc [no] _ ec;
IF ec < MaxEntry THEN ec _ ec + 1 ELSE { err[226]; ec _ 0 }};

Reloc: PUBLIC PROC = { rel[rc] _ pc;
IF rc < MaxRel THEN rc _ rc + 1 ELSE { err[226]; rc _ 0 }};

AllocString: PUBLIC PROC [id: CARDINAL] RETURNS [adr, length: CARDINAL] =
{ L: CARDINAL _ M2S.IdBuf[id].ORD; adr _ strx;
IF strx + L > MaxStr THEN { err [225]; strx _ 0 };
id _ id + 1; L _ L - 1; length _ L;
WHILE L > 0 DO
str [strx] _ M2S.IdBuf [id]; strx _ strx + 1; id _ id + 1; L _ L - 1
ENDLOOP;
str [strx] _ '\000; strx _ strx + 1 };

PutOI: PUBLIC PROC [op: CARDINAL] = { code [pc] _ op; pc _ pc + 1 };

PutOB: PUBLIC PROC [op, lit: CARDINAL] =
{ code [pc] _ op; code [pc+1] _ lit; pc _ pc + 2 };

PutODB: PUBLIC PROC [op, lit: CARDINAL] =
{ code [pc] _ op; code [pc+1] _ lit/256; code [pc+2] _ lit MOD 256; pc _ pc + 3 };

PutOQB: PUBLIC PROC [op: CARDINAL, lit: LONG INTEGER] =
{ code [pc] _ op; FixLong [pc+1, lit]; pc _ pc + 5 };

PutJBB: PUBLIC PROC [op: CARDINAL, dist: INTEGER, lit: CARDINAL] = { code [pc] _ op;
IF dist >= 0 THEN code [pc+1] _ dist ELSE code [pc+1] _ dist + 256;
code [pc+2] _ lit; pc _ pc + 3 };

PutLR: PUBLIC PROC [op: CARDINAL] = { code [pc] _ op; pc _ pc + 1 };

PutLRB: PUBLIC PROC [op, dsp: CARDINAL] =
{ code [pc] _ op; code [pc+1] _ dsp; pc _ pc + 2 };

PutLRRB: PUBLIC PROC [op, dsp: CARDINAL, reg1, reg2: [0..15]] = { code [pc] _ op;
code [pc+1] _ dsp; code [pc+2] _ reg1*16 + reg2; pc _ pc + 3 };

PutRR: PUBLIC PROC [op: CARDINAL, cOpt, aOpt, bOpt, aux: [0..1], c, a, b: [0..15]] =
{ code [pc] _ op; code [pc+1] _ cOpt*128 + aOpt*64 + bOpt*32 + aux*16 + c;
code [pc+2] _ a*16+b; pc _ pc + 3 };

PutQR: PUBLIC PROC [op: CARDINAL, bOpt, aux: [0..1], b: [0..15]] =
{ code [pc] _ op; code [pc+1] _ bOpt*32 + aux*16 + b; pc _ pc + 2 };

PutRJB: PUBLIC PROC [op: CARDINAL, sdd, sd, opt, aux: [0..1], reg: [0..15], dist: INTEGER] =
{ code [pc] _ op;
code [pc+1] _ sdd*128 + sd*64 + opt*32 + aux*16 + reg;
IF dist >= 0 THEN code [pc+2] _ dist ELSE code [pc+2] _ dist + 256;
pc _ pc + 3 };

PutExch: PUBLIC PROC =
{ PutRR [RXOR, 1, 1, 1, 0, 12, 13, 12];
PutRR [RXOR, 1, 1, 1, 0, 13, 13, 12];
PutRR [RXOR, 1, 1, 1, 0, 12, 13, 12] };

PutLod: PUBLIC PROC [lit: LONG INTEGER] =
{ IF lit >= 65536 THEN PutOQB [LIQB, lit]
ELSE IF lit >= 256 THEN PutODB [LIDB, lit]
ELSE IF lit >= 4 THEN PutOB [LIB, lit]
ELSE IF lit >= 0 THEN PutOI [LC+lit]
ELSE PutOQB [LIQB, lit] };

PutAdd: PUBLIC PROC [lit: LONG INTEGER] =
{ IF lit >= 65536 THEN { PutLod [lit]; PutOI [ADD] }
ELSE IF lit >= 256 THEN PutODB [ADDDB, lit]
ELSE IF lit > 0 THEN PutOB [ADDB, lit]
ELSE IF lit < 0 THEN PutSub [-lit] };

PutSub: PUBLIC PROC [lit: LONG INTEGER] =
{ IF lit >= 65536 THEN { PutLod [lit]; PutOI [SUB] }
ELSE IF lit >= 256 THEN PutODB [SUBDB, lit]
ELSE IF lit > 0 THEN PutOB [SUBB, lit]
ELSE IF lit < 0 THEN PutAdd [-lit] };

PutSOp: PUBLIC PROC [opr, opt1, reg1, opt2, reg2: CARDINAL] =
{ IF opr = RADD THEN
IF opt1 = 1 THEN
            IF reg1 >= 12 THEN
                IF opt2 = 1 THEN
                    IF reg2 >= 12 THEN PutOI [ADD] ELSE PutAdd [reg2]
                ELSE PutQR [QADD, opt2, 0, reg2]
            ELSE IF opt2 = 1 THEN PutAdd [reg1]
            ELSE PutRR [RADD, 1, opt1, opt2, 0, 15, reg1, reg2]
        ELSE IF (opt2 = 1) AND (reg2 >= 12) THEN PutQR [QADD, opt1, 0, reg1]
        ELSE PutRR [RADD, 1, opt1, opt2, 0, 15, reg1, reg2]
ELSE IF opr = RSUB THEN
IF (opt1 = 1) AND (reg1 >= 12) THEN
            IF opt2 = 1 THEN
                IF reg2 >= 12 THEN PutOI [SUB] ELSE PutSub [reg2]
            ELSE PutQR [QSUB, opt2, 0, reg2]
        ELSE PutRR [RSUB, 1, opt1, opt2, 0, 15, reg1, reg2 ]
ELSE IF opr = RAND THEN
IF (opt1 = 1) AND (reg1 >= 12) THEN
            IF (opt2 = 1) AND (reg2 >= 12) THEN PutRR [RAND, 1, opt1, opt2, 0, 13, 14, 13 ]
            ELSE PutQR [QAND, opt2, 0, reg2]
        ELSE IF (opt2 = 1) AND (reg2 >= 12) THEN PutQR [QAND, opt1, 0, reg1]
        ELSE PutRR [RAND, 1, opt1, opt2, 0, 15, reg1, reg2 ]
ELSE IF opr = ROR THEN
IF (opt1 = 1) AND (reg1 >= 12) THEN
            IF (opt2 = 1) AND (reg2 >= 12) THEN PutRR [ROR, 1, opt1, opt2, 0, 15, 15, 14 ]
            ELSE PutQR [QOR, opt2, 0, reg2]
        ELSE IF (opt2 = 1) AND (reg2 >= 12) THEN PutQR [QOR, opt1, 0, reg1]
        ELSE PutRR [ROR, 1, opt1, opt2, 0, 15, reg1, reg2 ]
ELSE IF opr = RXOR THEN
IF (opt1 = 1) AND (reg1 >= 12) AND (opt2 = 1) AND (reg2 >= 12) THEN
            PutRR [RXOR, 1, opt1, opt2, 0, 13, 14, 13 ]
        ELSE IF (opt1 = 1) AND (reg1 >= 12) OR (opt2 = 1) AND (reg2 >= 12) THEN
            PutRR [RXOR, 1, opt1, opt2, 0, 12, reg1, reg2 ]
        ELSE PutRR [RXOR, 1, opt1, opt2, 0, 15, reg1, reg2 ] };

PutROp: PUBLIC PROC [opr, resReg, opt1, reg1, opt2, reg2: CARDINAL] =
{ IF (opt1 = 1) AND (reg1 >= 12) THEN
    IF (opt2 = 1) AND (reg2 >= 12) THEN
        PutRR [opr, 0, opt1, opt2, 0, resReg, 15, 14]
    ELSE PutRR [opr, 0, opt1, opt2, 0, resReg, 14, reg2]
ELSE IF (opt2 = 1) AND (reg2 >= 12) THEN
    PutRR [opr, 0, opt1, opt2, 0, resReg, reg1, 14 ]
ELSE PutRR [opr, 0, opt1, opt2, 0, resReg, reg1, reg2] };

PutBJ: PUBLIC PROC [rel: Relation, opt, reg, loc: CARDINAL] =
{ d: INTEGER _ - (pc - loc);
IF rel = false THEN PutODB [J3, d]
ELSE IF rel = true THEN PutODB [JDB, d]
ELSE IF d >= -128 THEN
IF (rel = EQ) AND (opt = 1) AND (reg < 5) THEN PutJBB [JEBB, d, reg]
ELSE IF (rel = NE) AND (opt = 1) AND (reg < 5) THEN PutJBB [JNEBB, d, reg]
ELSE IF (opt = 1) AND (reg >= 12) THEN PutRJB [jop[rel], 1, 1, 1, 0, 14, d]
ELSE PutRJB [jop[rel], 1, 0, opt, 0, reg, d]
ELSE
{ IF (rel = EQ) AND (opt = 1) AND (reg < 5) THEN PutJBB [JNEBB, 6, reg]
ELSE IF (rel = NE) AND (opt = 1) AND (reg < 5) THEN PutJBB [JEBB, 6, reg]
ELSE IF (opt = 1) AND (reg >= 12) THEN PutRJB [jop[inv[rel]], 1, 1, 1, 0, 14, 6]
ELSE PutRJB [jop[inv[rel]], 1, 0, opt, 0, reg, 6];
PutODB [JDB, LOOPHOLE[d, CARDINAL]] }};

PutFJ: PUBLIC PROC [rel: Relation, opt, reg, loc: CARDINAL] RETURNS [Loc: CARDINAL] =
{ IF rel = false THEN { Loc _ pc; PutODB [J3, loc] }
ELSE IF rel = true THEN { Loc _ pc; PutODB [JDB, loc] }
ELSE
{ IF (rel = EQ) AND (opt = 1) AND (reg < 5) THEN PutJBB [JNEBB, 6, reg]
ELSE IF (rel = NE) AND (opt = 1) AND (reg < 5) THEN PutJBB [JEBB, 6, reg]
ELSE IF (opt = 1) AND (reg >= 12) THEN PutRJB [jop[inv[rel]], 1, 1, 1, 0, 14, 6]
ELSE PutRJB [jop[inv[rel]], 1, 0, opt, 0, reg, 6];
Loc _ pc; PutODB [JDB, loc] }};

FixByte: PUBLIC PROC [byte: CARDINAL] = { code [pc] _ byte; pc _ pc + 1 };

FixInt: PUBLIC PROC [loc: CARDINAL, i: INTEGER] =
{ n: CARDINAL = LOOPHOLE [i, CARDINAL];
code[loc] _ n/256; code[loc+1] _ n MOD 256 };

FixLong: PUBLIC PROC [loc: CARDINAL, i: LONG INTEGER] =
{ n: LONG CARDINAL _ LOOPHOLE [i, LONG CARDINAL];
code[loc+3] _ n MOD 256; n _ n/256;
code[loc+2] _ n MOD 256; n _ n/256;
code[loc+1] _ n MOD 256; n _ n/256;
code[loc] _ n };

FixAD: PUBLIC PROC [loc, LMF, size: CARDINAL] =
{ DO
loc1: CARDINAL = code[loc+1]*256 + code[loc+2];
IF loc1 = 0 THEN EXIT;
IF size > 0 THEN
{ code [loc] _ LR+LMF; code [loc+1] _ CALL; FixLong [loc+2, Dealloc] };
loc _ loc1
ENDLOOP;
IF size > 0 THEN
{ code [loc] _ LIDB; code [loc+1] _ size/256; code [loc+2] _ size MOD 256;
code [loc+3] _ CALL; FixLong [loc+4, Alloc] }
ELSE { code[loc] _ LC+0; code [loc+1] _ J2; code [loc+3] _ J5 }};

FixSL: PUBLIC PROC [loc, SL: CARDINAL] =
{ code [loc] _ WRI; code [loc+1] _ SL; code [loc+2] _ SL+1 };

FixDO: PUBLIC PROC [loc, off: CARDINAL] =
{ code [loc] _ DUP;
IF off > 0 THEN { code [loc+1] _ ADDB; code [loc+2] _ off }};

FixLR: PUBLIC PROC [loc, cell, cell1: CARDINAL] =
{ WHILE (cell # cell1) AND (cell < 15) DO
code [loc] _ DUP; cell _ cell + 1; loc _ loc + 1
ENDLOOP };

FixJmp: PUBLIC PROC [loc, dest: CARDINAL] =
{ n: CARDINAL = LOOPHOLE [dest - loc, CARDINAL];
code[loc+1] _ n/256; code[loc+2] _ n MOD 256 };

FixLink: PUBLIC PROC [loc, dest: CARDINAL] =
{ loc1: CARDINAL;
DO IF loc = 0 THEN EXIT;
loc1 _ code[loc+1]*256 + code[loc+2];
FixJmp [loc, dest]; loc _ loc1
ENDLOOP };

MergedLinks: PUBLIC PROC [L0, L1: CARDINAL] RETURNS [CARDINAL] =
{ L2, L3: CARDINAL;
IF L0 # 0 THEN { L2 _ L0;
DO L3 _ code[L2+1]*256 + code[L2+2];
IF L3 = 0 THEN EXIT;
L2 _ L3
ENDLOOP;
code [L2+1] _ L1/256; code [L2+2] _ L1 MOD 256;
RETURN [L0] }
ELSE RETURN [L1] };

CheckCode: PUBLIC PROC =
{ IF pc > MaxPC THEN { err[226]; pc _ 0 }};

OutCodeFile: PUBLIC PROC [name: Rope.ROPE, np, size, modNo: CARDINAL, mod: M2D.ObjPtr] = { ObjFile: IO.STREAM _ FS.StreamOpen 
[name, $create];
e, r, s, S, p, P, op, adj: CARDINAL; n: CARDINAL; i: INTEGER;

WriteNo: PROC [n: CARDINAL] =
{ ObjFile.PutChar ['\000 + n/256]; ObjFile.PutChar ['\000 + n MOD 256] };

WriteId: PROC [i: CARDINAL] =
{ I: CARDINAL _ M2S.IdBuf [i].ORD;
I _ i + I;
DO ObjFile.PutChar [M2S.IdBuf [i]]; i _ i + 1;
IF i = I THEN EXIT
ENDLOOP };

fix: PROC [d: CARDINAL] =
{ WHILE ent [e] < p DO ent [e] _ ent [e] - adj; e _ e + 1 ENDLOOP;
WHILE rel [r] < p DO rel [r] _ rel[r] - adj; r _ r + 1 ENDLOOP;
sec [s] _ p; incs; adj _ adj + d };

incs: PROC = { IF s < MaxSec THEN s _ s + 1 ELSE err [226] };

D: PROC [s, p, q: CARDINAL] RETURNS [d: INTEGER] =
{ d _ 0;
IF p <= q THEN
WHILE sec [s+1] < q DO s _ s + 1; d _ d + code [sec[s]] ENDLOOP
ELSE WHILE sec [s] > q DO d _ d - code [sec[s]]; s _ s - 1 ENDLOOP };

ent [ec] _ pc; rel [rc] _ pc; e _ 0; r _ 0;
sec[0] _ 0; s _ 0; p _ 0; adj _ 0;
WHILE p # pc DO op _ code[p];
IF (op >= 340B) AND (op < 360B) AND (code[p+2] = 6) AND (code[p+3] = JDB) THEN
{ n _ code[p+4]*256 + code[p+5];
IF n < 128 THEN
{ code [p] _ 3; code[p+3] _ neg [op]; code[p+4] _ code [p+1];
code [p+5] _ n; fix [3] };
p _ p + 6 }
ELSE IF (op >= 360B) AND (op < 370B) AND (code[p+1] = 6) AND (code[p+3] = JDB) THEN
{ n _ code[p+4]*256 + code[p+5];
IF n < 128 THEN
{ code [p] _ 3; code[p+3] _ neg [op]; code[p+4] _ n;
code [p+5] _ code[p+2]; fix [3] };
p _ p + 6 }
ELSE IF op = J1 THEN { code [p] _ 1; fix [1]; p _ p + 1 }
ELSE IF op = J2 THEN { code [p] _ 2; fix [2]; p _ p + 2 }
ELSE IF op = J3 THEN { code [p] _ 3; fix [3]; p _ p + 3 }
ELSE IF op = J5 THEN { code [p] _ 5; fix [5]; p _ p + 5 }
ELSE p _ p + len[op/8]
ENDLOOP;
code [p] _ 0; fix [0]; S _ s; sec [S] _ pc;
<<>>
<<header>>
WriteNo [OBJFILE];
<<imports>>
WriteNo [modNo];
WHILE mod # NIL DO
module: M2D.ModulePtr _ NARROW [mod];
WriteNo [module^.key/65536]; WriteNo [module^.key MOD 65536];
WriteId [mod^.name]; mod _ mod^.next
ENDLOOP;
<<code>>
WriteNo [pc-adj]; p _ 0; s _ 0;
WHILE s # S DO p _ p + code [p];
WHILE p # sec[s+1] DO op _ code[p];
IF (op >= 340B) AND (op < 360B) THEN { n _ code[p+2];
IF n < 128 THEN i _ n ELSE i _ - (256 - n);
i _ i - D [s, p, p+i]; 
IF i >= 0 THEN code[p+2] _ i ELSE code [p+2] _ i + 256 }
ELSE IF (op >= 360B) AND (op < 370B) THEN { n _ code[p+1];
IF n < 128 THEN i _ n ELSE i _ - (256 - n);
i _ i - D [s, p, p+i]; 
IF i >= 0 THEN code[p+1] _ i ELSE code [p+1] _ i + 256 }
ELSE IF op = JB THEN { n _ code[p+1];
IF n < 128 THEN i _ n ELSE i _ - (256 - n);
i _ i - D [s, p, p+i]; 
IF i >= 0 THEN code[p+2] _ i ELSE code [p+1] _ i + 256 }
ELSE IF (op = JDB) OR (op = LFC) THEN
{ i _ LOOPHOLE [code[p+1]*256 + code[p+2], INTEGER];
i _ i - D [s, p, p+i]; n _ LOOPHOLE [i, CARDINAL];
code[p+1] _ n/256; code[p+2] _ n MOD 256 }
ELSE IF op = LIPC THEN
{ n _ ent [prc[code[p+1]*256 + code[p+2]]]; 
code [p] _ LIDB; code [p+1] _ n/256; code[p+2] _ n MOD 256 };
P _ p + len[op/8];
DO
ObjFile.PutChar ['\000 + code[p]] ; p _ p + 1;
IF p = P THEN EXIT
ENDLOOP
ENDLOOP;
s _ s + 1
ENDLOOP;
<<entries>>
WriteNo [np]; n _ 0;
WHILE n # np DO WriteNo [ent[prc[n]]]; n _ n + 1 ENDLOOP;
<<relocation>>
WriteNo [rc]; r _ 0;
WHILE r # rc DO WriteNo [rel[r]]; r _ r + 1 ENDLOOP;
<<frame size>>
WriteNo [size];
<<literals>>
WriteNo [strx]; s _ 0;
WHILE s # strx DO ObjFile.PutChar [str[s]]; s _ s + 1 ENDLOOP;

IO.Close [ObjFile] };

END.
