M2IImpl.mesa
Modula-2 Code-Generator, Part 2
Last Edted by: Gutknecht, October 7, 1985 3:54:22 pm PDT
Satterthwaite March 11, 1986 5:36:58 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 CARDINALLOOPHOLE [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.STREAMFS.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;
ObjFile.Close [] };
END.