Oberon/V2/OCH
< Oberon
MODULE OCH; (*NW 7.6.87 / 15.2.91*)
IMPORT OCS, OCT, OCC;
CONST (*instruction format prefixes*)
F6 = 4EH; F7 = 0CEH; F9 = 3EH; F11 = 0BEH;
(*object and item modes*)
Var = 1; VarX = 2; Ind = 3; IndX = 4; RegI = 5;
RegX = 6; Abs = 7; Con = 8; Stk = 9; Coc = 10;
Reg = 11; Fld = 12; LProc = 14; XProc = 15;
CProc = 17; IProc = 18; Mod = 19;
(*structure forms*)
Undef = 0; Byte = 1; Bool = 2; Char = 3; SInt = 4; Int = 5; LInt = 6;
Real = 7; LReal = 8; Set = 9; String = 10; NilTyp = 11; NoTyp = 12;
Pointer = 13; ProcTyp = 14; Array = 15; DynArr = 16; Record = 17;
TYPE LabelRange* = RECORD low*, high*: INTEGER; label*: INTEGER END ;
VAR lengcode: ARRAY 18 OF INTEGER;
PROCEDURE setCC(VAR x: OCT.Item; cc: LONGINT);
BEGIN x.typ := OCT.booltyp; x.mode := Coc; x.a0 := cc; x.a1 := 0; x.a2 := 0
END setCC;
PROCEDURE AdjustSP(n: LONGINT);
BEGIN (*ADJSPB n*)
IF n <= 127 THEN OCC.PutF3(-5A84H); OCC.PutByte(n)
ELSE OCC.PutF3(-5A83H); OCC.PutWord(n)
END
END AdjustSP;
PROCEDURE move(L: INTEGER; VAR x, y: OCT.Item);
BEGIN
IF (y.mode = Con) & (y.a0 <= 7) & (y.a0 >= -8) THEN
OCC.PutF2(L+5CH, y.a0, x) (*MOVQi*)
ELSE OCC.PutF4(L+14H, x, y) (*MOVi*)
END
END move;
PROCEDURE load(VAR x: OCT.Item);
VAR y: OCT.Item;
BEGIN
IF x.mode # Reg THEN
y := x; OCC.GetReg(x); move(lengcode[x.typ.form], x, y)
END
END load;
PROCEDURE moveBW(VAR x, y: OCT.Item);
BEGIN
IF (y.mode = Con) & (y.a0 <= 7) & (y.a0 >= -8) THEN
OCC.PutF2(5DH, y.a0, x)
ELSE OCC.Put(F7, 10H, x, y) (*MOVXBW*)
END
END moveBW;
PROCEDURE moveBD(VAR x, y: OCT.Item);
BEGIN
IF (y.mode = Con) & (y.a0 <= 7) & (y.a0 >= -8) THEN
OCC.PutF2(5FH, y.a0, x)
ELSE OCC.Put(F7, 1CH, x, y) (*MOVXBD*)
END
END moveBD;
PROCEDURE moveWD(VAR x, y: OCT.Item);
BEGIN
IF (y.mode = Con) & (y.a0 <= 7) & (y.a0 >= -8) THEN
OCC.PutF2(5FH, y.a0, x)
ELSE OCC.Put(F7, 1DH, x, y) (*MOVXWD*)
END
END moveWD;
PROCEDURE Leng(VAR x: OCT.Item; L: LONGINT);
VAR y: OCT.Item;
BEGIN
IF L <= 7 THEN OCC.PutF2(5FH, L, x) (*MOVQD*)
ELSE y.mode := Con; y.a0 := L; (*MOVZBD*)
IF L <= 255 THEN y.typ := OCT.sinttyp; OCC.Put(F7, 18H, x, y)
ELSE y.typ := OCT.inttyp; OCC.Put(F7, 19H, x, y)
END
END
END Leng;
PROCEDURE MoveBlock(VAR x, y: OCT.Item; s: LONGINT; param: BOOLEAN);
VAR L: INTEGER; z: OCT.Item;
BEGIN
IF s > 0 THEN
IF param THEN
s := (s+3) DIV 4 * 4; AdjustSP(s)
END ;
IF s <= 16 THEN
OCC.Put(F7, 0, x, y); OCC.PutDisp(s-1) (*MOVMB*)
ELSE
z.mode := Reg; z.a0 := 1; OCC.PutF4(27H, z, y); (*ADDR y,R1*)
z.a0 := 2; OCC.PutF4(27H, z, x); z.a0 := 0;
(*ADDR x,R2*)
IF s MOD 4 = 0 THEN L := 3; s := s DIV 4
ELSIF s MOD 2 = 0 THEN L := 1; s := s DIV 2
ELSE L := 0
END ;
Leng(z, s);
OCC.PutF1(14); OCC.PutByte(L); OCC.PutByte(0) (*MOVS*)
END
END
END MoveBlock;
PROCEDURE DynArrBnd(ftyp, atyp: OCT.Struct; lev: INTEGER;
adr: LONGINT; varpar: BOOLEAN);
VAR f, s: INTEGER; x, y, z: OCT.Item;
BEGIN (* ftyp.form = DynArr *)
x.mode := Stk; y.mode := Var;
IF varpar & (ftyp.BaseTyp = OCT.bytetyp) THEN
IF atyp.form # DynArr THEN Leng(x, atyp.size-1)
ELSE y.lev := lev; y.a0 := adr + atyp.adr; y.typ := OCT.linttyp;
atyp := atyp.BaseTyp;
IF atyp.form # DynArr THEN
IF atyp.size > 1 THEN
z.mode := Con; z.typ := OCT.linttyp; z.a0 := atyp.size;
load(y); OCC.Put(F7, 23H, y, z); (* MULD z, Ry *)
z.mode := Con; z.typ := OCT.linttyp; z.a0 := atyp.size-1;
IF z.a0 < 8 THEN OCC.PutF2(0FH, z.a0, y) (* ADDQD size-1, Ry *)
ELSE OCC.PutF4(3, y, z) (* ADDD size-1, Ry *)
END
END
ELSE load(y); OCC.PutF2(0FH, 1, y);
REPEAT z.mode := Var; z.lev := lev; z.a0 := atyp.adr + adr; z.typ := OCT.linttyp;
load(z); OCC.PutF2(0FH, 1, z); (* ADDQD 1, Rz *)
OCC.Put(F7, 23H, y, z); (* MULD Rz, Ry *)
atyp := atyp.BaseTyp
UNTIL atyp.form # DynArr;
IF atyp.size > 1 THEN
z.mode := Con; z.typ := OCT.linttyp; z.a0 := atyp.size;
OCC.Put(F7, 23H, y, z) (* MULD z, Ry *)
END ;
OCC.PutF2(0FH, -1, y) (* ADDQD -1, Ry *)
END ;
OCC.PutF4(17H, x, y) (* MOVD apdynarrlen-1, TOS *)
END
ELSE
LOOP f := atyp.form;
IF f = Array THEN y.lev := -atyp.mno; y.a0 := atyp.adr
ELSIF f = DynArr THEN y.lev := lev; y.a0 := atyp.adr + adr
ELSE OCS.Mark(66); EXIT
END ;
OCC.PutF4(17H, x, y); ftyp := ftyp.BaseTyp; atyp := atyp.BaseTyp;
IF ftyp.form # DynArr THEN
IF ftyp # atyp THEN OCS.Mark(67) END ;
EXIT
END
END
END
END DynArrBnd;
PROCEDURE Trap*(n: INTEGER);
BEGIN OCC.PutF1(0F2H); OCC.PutByte(n) (*BPT n*)
END Trap;
PROCEDURE CompareParLists*(x, y: OCT.Object);
VAR xt, yt: OCT.Struct;
BEGIN
WHILE x # NIL DO
IF y # NIL THEN
xt := x.typ; yt := y.typ;
WHILE (xt.form = DynArr) & (yt.form = DynArr) DO
xt := xt.BaseTyp; yt := yt.BaseTyp
END ;
IF x.mode # y.mode THEN OCS.Mark(115)
ELSIF xt # yt THEN
IF (xt.form = ProcTyp) & (yt.form = ProcTyp) THEN
CompareParLists(xt.link, yt.link)
ELSE OCS.Mark(115)
END
END ;
y := y.next
ELSE OCS.Mark(116)
END ;
x := x.next
END ;
IF (y # NIL) & (y.mode <= Ind) & (y.a0 > 0) THEN OCS.Mark(117) END
END CompareParLists;
PROCEDURE Assign*(VAR x, y: OCT.Item; param: BOOLEAN);
VAR f, g, L, u: INTEGER; s, vsz: LONGINT;
p, q: OCT.Struct;
xp, yp: OCT.Object;
tag, tdes: OCT.Item;
BEGIN f := x.typ.form; g := y.typ.form;
IF x.mode = Con THEN OCS.Mark(56) END ;
CASE f OF
Undef, String:
| Byte: IF g IN {Undef, Byte, Char, SInt} THEN
IF param THEN moveBD(x, y) ELSE move(0, x, y) END
ELSE OCS.Mark(113)
END
| Bool: IF param THEN u := 3 ELSE u := 0 END ;
IF y.mode = Coc THEN
IF (y.a1 = 0) & (y.a2 = 0) THEN OCC.PutF2(u+3CH, y.a0, x)
ELSE
IF ODD(y.a0) THEN OCC.PutF0(y.a0-1) ELSE OCC.PutF0(y.a0+1) END ;
OCC.PutWord(y.a2); y.a2 := OCC.pc-2;
OCC.FixLink(y.a1); OCC.PutF2(u+5CH, 1, x);
OCC.PutF0(14); L := OCC.pc; OCC.PutWord(0);
OCC.FixLink(y.a2); OCC.PutF2(u+5CH, 0, x); OCC.fixup(L)
END
ELSIF g = Bool THEN
IF y.mode = Con THEN OCC.PutF2(u+5CH, y.a0, x)
ELSIF param THEN OCC.Put(F7, 18H, x, y) (*MOVZBD*)
ELSE OCC.PutF4(14H, x, y)
END
ELSE OCS.Mark(113)
END
| Char, SInt:
IF g = f THEN
IF param THEN moveBD(x, y) ELSE move(0, x, y) END
ELSE OCS.Mark(113)
END
| Int: IF g = Int THEN
IF param THEN moveWD(x, y) ELSE move(1, x, y) END
ELSIF g = SInt THEN
IF param THEN moveBD(x, y) ELSE moveBW(x, y) END
ELSE OCS.Mark(113)
END
| LInt: IF g = LInt THEN move(3, x, y)
ELSIF g = Int THEN moveWD(x, y)
ELSIF g = SInt THEN moveBD(x, y)
ELSE OCS.Mark(113)
END
| Real: IF g = Real THEN OCC.Put(F11, 5, x, y)
ELSIF (SInt <= g) & (g <= LInt) THEN OCC.Put(F9, lengcode[g]+4, x, y)
ELSE OCS.Mark(113)
END
| LReal: IF g = LReal THEN OCC.Put(F11, 4, x, y)
ELSIF g = Real THEN OCC.Put(F9, 1BH, x, y)
ELSIF (SInt <= g) & (g <= LInt) THEN OCC.Put(F9, lengcode[g], x, y)
ELSE OCS.Mark(113)
END
| Set: IF g = f THEN move(3, x, y) ELSE OCS.Mark(113) END
| Pointer:
IF x.typ = y.typ THEN move(3, x, y)
ELSIF g = NilTyp THEN OCC.PutF2(5FH, 0, x)
ELSIF g = Pointer THEN
p := x.typ.BaseTyp; q := y.typ.BaseTyp;
IF (p.form = Record) & (q.form = Record) THEN
WHILE (q # p) & (q # NIL) DO q := q.BaseTyp END ;
IF q # NIL THEN move(3, x, y) ELSE OCS.Mark(113) END
ELSE OCS.Mark(113)
END
ELSE OCS.Mark(113)
END
| Array: s := x.typ.size;
IF x.typ = y.typ THEN MoveBlock(x, y, s, param)
ELSIF (g = String) & (x.typ.BaseTyp = OCT.chartyp) THEN
s := y.a1; vsz := x.typ.n; (*check length of string*)
IF s > vsz THEN OCS.Mark(114) END ;
IF param THEN
vsz := (vsz+3) DIV 4 - (s+3) DIV 4;
IF vsz > 0 THEN AdjustSP(vsz*4) END
END ;
MoveBlock(x, y, s, param)
ELSE OCS.Mark(113)
END
| DynArr: s := x.typ.size;
IF param THEN (*formal parameter is open array*)
IF (g = String) & (x.typ.BaseTyp.form = Char) THEN Leng(x, y.a1-1)
ELSIF y.mode >= Abs THEN OCS.Mark(59)
ELSE DynArrBnd(x.typ, y.typ, y.lev, y.a0, FALSE)
END ;
IF g = DynArr THEN OCC.DynArrAdr(x, y)
ELSE OCC.PutF4(27H, x, y)
END
ELSE OCS.Mark(113)
END
| Record: s := x.typ.size;
IF x.typ # y.typ THEN
IF g = Record THEN
q := y.typ.BaseTyp;
WHILE (q # NIL) & (q # x.typ) DO q := q.BaseTyp END ;
IF q = NIL THEN OCS.Mark(113) END
ELSE OCS.Mark(113)
END
END ;
IF OCC.typchk & ~param &
( ((x.mode = Ind) OR (x.mode = RegI)) & (x.obj = OCC.wasderef) (* p^ := *)
OR (x.mode = Ind) & (x.obj # NIL) & (x.obj # OCC.wasderef) ) THEN
tag := x; tdes.mode := Var; tdes.lev := -x.typ.mno; tdes.a0 := x.typ.adr;
IF x.obj = OCC.wasderef THEN tag.a1 := - 4
ELSE tag.mode := Var; INC(tag.a0, 4)
END;
OCC.PutF4(7, tdes, tag); (* CMPD tag, tdes *)
OCC.PutF0(0); OCC.PutDisp(4); (* BEQ continue *)
OCC.PutF1(0F2H); OCC.PutByte(19) (* BPT 19 *)
END ;
MoveBlock(x, y, s, param)
| ProcTyp:
IF (x.typ = y.typ) OR (y.typ = OCT.niltyp) THEN OCC.PutF4(17H, x, y)
ELSIF (y.mode = XProc) OR (y.mode = IProc) THEN
(*procedure y to proc. variable x; check compatibility*)
IF x.typ.BaseTyp = y.typ THEN
CompareParLists(x.typ.link, y.obj.dsc);
IF y.a1 = 0 THEN
y.a1 := OCC.LinkAdr(-y.lev, y.a0); y.obj.a1 := y.a1
END ;
y.mode := Var; y.lev := SHORT(-y.a1); y.a0 := 0;
OCC.PutF4(27H, x, y) (*LXPD*)
ELSE OCS.Mark(118)
END
ELSIF y.mode = LProc THEN OCS.Mark(119)
ELSE OCS.Mark(111)
END
| NoTyp, NilTyp: OCS.Mark(111)
END
END Assign;
PROCEDURE FJ*(VAR loc: INTEGER);
BEGIN OCC.PutF0(14); OCC.PutWord(loc); loc := OCC.pc-2
END FJ;
PROCEDURE CFJ*(VAR x: OCT.Item; VAR loc: INTEGER);
BEGIN
IF x.typ.form = Bool THEN
IF x.mode # Coc THEN OCC.PutF2(1CH, 1, x); setCC(x, 0) END
ELSE OCS.Mark(120); setCC(x, 0)
END ;
IF ODD(x.a0) THEN OCC.PutF0(x.a0-1) ELSE OCC.PutF0(x.a0+1) END ;
loc := OCC.pc; OCC.PutWord(x.a2); OCC.FixLink(x.a1)
END CFJ;
PROCEDURE BJ*(loc: INTEGER);
BEGIN OCC.PutF0(14); OCC.PutDisp(loc - OCC.pc + 1)
END BJ;
PROCEDURE CBJ*(VAR x: OCT.Item; loc: INTEGER);
BEGIN
IF x.typ.form = Bool THEN
IF x.mode # Coc THEN OCC.PutF2(1CH, 1, x); setCC(x,0) END
ELSE OCS.Mark(120); setCC(x, 0)
END ;
IF ODD(x.a0) THEN OCC.PutF0(x.a0-1) ELSE OCC.PutF0(x.a0+1) END ;
OCC.PutDisp(loc - OCC.pc + 1);
OCC.FixLinkWith(x.a2, loc); OCC.FixLink(x.a1)
END CBJ;
PROCEDURE LFJ*(VAR loc: INTEGER);
BEGIN OCC.PutF0(14); OCC.PutWord(-4000H); OCC.PutWord(0); loc := OCC.pc-4
END LFJ;
PROCEDURE PrepCall*(VAR x: OCT.Item; VAR fpar: OCT.Object);
BEGIN
IF (x.mode = LProc) OR (x.mode = XProc) OR (x.mode = CProc) THEN
fpar := x.obj.dsc
ELSIF (x.typ # NIL) & (x.typ.form = ProcTyp) THEN
fpar := x.typ.link
ELSE OCS.Mark(121); fpar := NIL; x.typ := OCT.undftyp
END
END PrepCall;
PROCEDURE Param*(VAR ap: OCT.Item; f: OCT.Object);
VAR q: OCT.Struct; fp, tag: OCT.Item;
BEGIN fp.mode := Stk; fp.typ := f.typ;
IF f.mode = Ind THEN (*VAR parameter*)
IF ap.mode >= Con THEN OCS.Mark(122) END ;
IF fp.typ.form = DynArr THEN
DynArrBnd(fp.typ, ap.typ, ap.lev, ap.a0, TRUE);
IF ap.typ.form = DynArr THEN OCC.DynArrAdr(fp, ap)
ELSE OCC.PutF4(27H, fp, ap)
END
ELSIF (fp.typ.form = Record) & (ap.typ.form = Record) THEN
q := ap.typ;
WHILE (q # fp.typ) & (q # NIL) DO q := q.BaseTyp END ;
IF q # NIL THEN
IF (ap.mode = Ind) & (ap.obj # NIL) & (ap.obj # OCC.wasderef) THEN
(*actual par is VAR-par*) ap.mode := Var; ap.a0 := ap.a0 + 4;
OCC.PutF4(17H, fp, ap); ap.a0 := ap.a0 - 4; OCC.PutF4(17H, fp, ap)
ELSIF ((ap.mode = Ind) OR (ap.mode = RegI)) & (ap.obj = OCC.wasderef) THEN
(*actual par is p^*) ap.a1 := - 4; OCC.PutF4(17H, fp, ap);
IF ap.mode = Ind THEN ap.mode := Var ELSE ap.mode := Reg END;
OCC.PutF4(17H, fp, ap)
ELSE
tag.mode := Var; tag.lev := -ap.typ.mno; tag.a0 := ap.typ.adr;
OCC.PutF4(17H, fp, tag); OCC.PutF4(27H, fp, ap)
END
ELSE OCS.Mark(111)
END
ELSIF (ap.typ = fp.typ) OR ((fp.typ.form = Byte)&(ap.typ.form IN {Char, SInt})) THEN
IF (ap.mode = Ind) & (ap.a1 = 0) THEN (*actual var par*)
ap.mode := Var; OCC.PutF4(17H, fp, ap)
ELSE OCC.PutF4(27H, fp, ap)
END
ELSE OCS.Mark(123)
END
ELSE Assign(fp, ap, TRUE)
END
END Param;
PROCEDURE Call*(VAR x: OCT.Item);
VAR stk, sL: OCT.Item;
BEGIN
IF x.mode = LProc THEN
IF x.lev > 0 THEN
sL.mode := Var; sL.typ := OCT.linttyp; sL.lev := x.lev; sL.a0 := 0;
stk.mode := Stk; OCC.PutF4(27H, stk, sL) (*static link*)
END ;
OCC.PutF1(2); OCC.PutDisp(x.a0 - OCC.pc + 1) (*BSR*)
ELSIF x.mode = XProc THEN
IF x.a1 = 0 THEN
x.a1 := OCC.LinkAdr(-x.lev, x.a0); x.obj.a1 := x.a1
END ;
OCC.PutF1(22H); OCC.PutDisp(SHORT(x.a1)) (*CXP*)
ELSIF (x.mode < Con) & (x.typ # OCT.undftyp) THEN (*CXPD*)
OCC.PutF2(7FH, 0, x); x.typ := x.typ.BaseTyp
ELSIF x.mode = CProc THEN
OCC.PutF1(0E2H); OCC.PutByte(x.a0) (*SVC n*)
ELSE OCS.Mark(121)
END
(*function result is marked when restoring registers*)
END Call;
PROCEDURE Enter*(mode: SHORTINT; pno: LONGINT; VAR L: INTEGER);
BEGIN
IF mode # LProc THEN OCC.SetEntry(SHORT(pno)) END ;
OCC.PutF1(82H); (*ENTER*)
IF mode = IProc THEN OCC.PutByte(0C0H) ELSE OCC.PutByte(0) END ;
IF mode # Mod THEN L := OCC.pc; OCC.PutWord(0) ELSE OCC.PutByte(0) END
END Enter;
PROCEDURE CopyDynArray*(adr: LONGINT; typ: OCT.Struct);
VAR size, ptr, m2, tos: OCT.Item; add: SHORTINT;
PROCEDURE DynArrSize(typ: OCT.Struct);
VAR len: OCT.Item;
BEGIN
IF typ.form = DynArr THEN DynArrSize(typ.BaseTyp);
len.mode := Var; len.lev := OCC.level; len.typ := OCT.linttyp;
len.a0 := adr + typ.adr; load(len);
IF (size.mode # Con) OR (size.a0 # 1) THEN
IF add = 4 THEN OCC.PutF2(0FH, 1, size) END; (* ADDQD 1, size *)
OCC.PutF2(0FH, 1, len); add := 3; (* ADDQD 1, len *)
OCC.Put(F7, 23H, len, size) (* MULD size, len *)
ELSE add := 4
END;
size := len
ELSE size.mode := Con; size.typ := OCT.linttyp; size.a0 := typ.size
END
END DynArrSize;
BEGIN add := 3;
DynArrSize(typ); (* load total byte size of dyn array *)
OCC.PutF2(0FH, add, size); (* ADDQD 3 or 4, size *)
m2.mode := Con; m2.typ := OCT.sinttyp;
m2.a0 := -2; OCC.Put(F6, 7, size, m2); (* ASHD -2, size *)
ptr.mode := Var; ptr.lev := OCC.level; ptr.typ := OCT.linttyp;
ptr.a0 := adr; load(ptr);
ptr.mode := RegX; ptr.a1 := -4; ptr.a2 := size.a0; tos.mode := Stk;
OCC.PutF4(17H, tos, ptr); (* loop: MOVD -4(ptr)[size:D], TOS *)
OCC.PutF2(4FH, -1, size); OCC.PutDisp(-4); (* ACBD -1, size, loop *)
OCC.PutF3(-31D9H); OCC.PutDisp(0); OCC.PutDisp(adr); (* ADDR adr(FP) *)
OCC.FreeRegs({})
END CopyDynArray;
PROCEDURE Result*(VAR x: OCT.Item; typ: OCT.Struct);
VAR res: OCT.Item;
BEGIN res.mode := Reg; res.typ := typ; res.a0 := 0;
Assign(res, x, FALSE)
END Result;
PROCEDURE Return*(mode: INTEGER; psize: LONGINT);
BEGIN OCC.PutF1(92H); (*EXIT*)
IF mode = LProc THEN
OCC.PutByte(0); OCC.PutF1(12H); OCC.PutDisp(psize-8) (*RET*)
ELSIF mode = XProc THEN
OCC.PutByte(0); OCC.PutF1(32H); OCC.PutDisp(psize-12) (*RXP*)
ELSIF mode = IProc THEN
OCC.PutByte(3); OCC.PutF1(42H); OCC.PutDisp(0) (*RETT 0*)
END
END Return;
PROCEDURE CaseIn*(VAR x: OCT.Item; VAR L0, L1: INTEGER);
VAR f: INTEGER; r, x0, lim: OCT.Item;
BEGIN f := x.typ.form;
IF f # Int THEN
IF f = Char THEN
x0 := x; OCC.GetReg(x); OCC.Put(F7, 14H, x, x0) (*MOVZBW*)
ELSIF f = SInt THEN
x0 := x; OCC.GetReg(x); OCC.Put(F7, 10H, x, x0) (*MOVXBW*)
ELSIF f # LInt THEN OCS.Mark(125)
END ;
f := Int
END ;
IF (x.mode IN {VarX, IndX, RegX}) OR
(x.mode # Reg) & (x.lev > 0) & (x.lev < OCC.level) THEN
x0 := x; OCC.GetReg(x); OCC.PutF4(15H, x, x0) (*MOVW*)
END ;
L0 := OCC.pc+3; (*fixup loc for bounds adr*)
lim.mode := Var; lim.typ := OCT.inttyp; lim.lev := 0; lim.a0 := 100H;
OCC.GetReg(r); OCC.Put(0EEH, SHORT(r.a0)*8 + 1, x, lim); (*CHECK*)
OCC.PutF0(8); OCC.PutWord(0); L1 := OCC.pc;
(*BFS*)
lim.mode := VarX; lim.a2 := r.a0; OCC.PutF2(7DH, 14, lim) (*CASE*)
END CaseIn;
PROCEDURE CaseOut*(L0, L1, L2, L3, n: INTEGER;
VAR tab: ARRAY OF LabelRange);
VAR i, j, lim: INTEGER; k: LONGINT;
BEGIN (*generate jump table*)
IF n > 0 THEN OCC.AllocBounds(tab[0].low, tab[n-1].high, k)
ELSE (*no cases*) OCC.AllocBounds(1, 0, k)
END ;
j := SHORT(k);
OCC.FixupWith(L0, j); (*bounds address in check*)
OCC.FixupWith(L1-2, L2-L1+3); (*out of bounds jump addr*)
OCC.FixupWith(L1+3, j+4); (*jump address to table*)
i := 0; j := tab[0].low;
WHILE i < n DO
lim := tab[i].high;
WHILE j < tab[i].low DO
OCC.AllocInt(L2-L1); INC(j) (*else*)
END ;
WHILE j <= lim DO
OCC.AllocInt(tab[i].label-L1); INC(j)
END ;
INC(i)
END ;
OCC.FixLink(L3)
END CaseOut;
BEGIN lengcode[Undef] := 0;
lengcode[Byte] := 0; lengcode[Bool] := 0; lengcode[Char] := 0; lengcode[SInt] := 0;
lengcode[Int] := 1; lengcode[LInt] := 3; lengcode[Real] := 1; lengcode[LReal] := 0;
lengcode[Set] := 3; lengcode[String] := 0; lengcode[NilTyp] := 3; lengcode[ProcTyp] := 3;
lengcode[Pointer] := 3; lengcode[Array] := 1; lengcode[DynArr] := 1; lengcode[Record] := 1
END OCH.