-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathOBE.Mod
973 lines (918 loc) · 42.2 KB
/
OBE.Mod
1
MODULE OBE; (*NW 7.6.87 / 10.7.93*) IMPORT SYSTEM, OBS, OBT, OBC; CONST (*instruction formats*) 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; Stk0 = 10; Coc = 11; Reg = 12; Fld = 13; Typ = 14; 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; (*frequent operation codes: 5C, 5D, 5F = MOVQi, 14, 15, 17 = MOVi, 27 = ADDR*) VAR inxchk*: BOOLEAN; inxloc*, tchkloc*: INTEGER; log: INTEGER; (*side effect of mant*) lengcode: ARRAY 18 OF INTEGER; intSet, realSet: SET; PROCEDURE inverted(x: LONGINT): LONGINT; BEGIN (*inverted sense of condition code*) IF ODD(x) THEN RETURN x-1 ELSE RETURN x+1 END END inverted; PROCEDURE load(VAR x: OBT.Item); VAR y: OBT.Item; BEGIN IF x.mode < Reg THEN y := x; OBC.GetReg(x); IF (y.mode = Con) & (-8 <= y.a0) & (y.a0 <= 7) THEN OBC.PutF2(lengcode[x.typ.form] + 5CH, y.a0, x) ELSE OBC.PutF4(lengcode[x.typ.form] + 14H, x, y) END ELSIF x.mode > Reg THEN OBS.Mark(126) END END load; PROCEDURE loadX(VAR x: OBT.Item); VAR y: OBT.Item; BEGIN IF x.mode <= Reg THEN y := x; OBC.GetReg(x); IF (y.mode = Con) & (-8 <= y.a0) & (y.a0 <= 7) THEN OBC.PutF2(5FH, y.a0, x) ELSE OBC.Put(F7, lengcode[x.typ.form] + 1CH, x, y) (*MOVXiD*) END ELSIF x.mode > Reg THEN OBS.Mark(126) END END loadX; PROCEDURE loadF(VAR x: OBT.Item); VAR y: OBT.Item; BEGIN IF x.mode < Reg THEN y := x; OBC.GetFReg(x); OBC.Put(F11, lengcode[x.typ.form] + 4, x, y) (*MOVf*) ELSIF x.mode > Reg THEN OBS.Mark(126) END END loadF; PROCEDURE loadB(VAR x: OBT.Item); (*Coc-Mode*) VAR L0, L1: LONGINT; BEGIN IF (x.a1 = 0) & (x.a2 = 0) THEN L0 := x.a0; OBC.GetReg(x); OBC.PutF2(3CH, L0, x) ELSE OBC.PutF0(inverted(x.a0)); OBC.PutWord(x.a2); L0 := OBC.pc - 2; OBC.FixLink(x.a1); OBC.GetReg(x); OBC.PutF2(5CH, 1, x); OBC.PutF0(14); L1 := OBC.pc; OBC.PutWord(0); OBC.FixLink(L0); OBC.PutF2(5CH, 0, x); OBC.fixup(L1) END END loadB; PROCEDURE loadAdr(VAR x: OBT.Item); VAR y: OBT.Item; BEGIN IF x.mode < Con THEN y := x; OBC.GetReg(x); IF (y.mode = Ind) & (y.a1 = 0) THEN y.mode := Var; OBC.PutF4(17H, x, y) ELSE OBC.PutF4(27H, x, y); x.a1 := 0 END ; x.mode := RegI; x.obj := NIL ELSE OBS.Mark(127) END END loadAdr; PROCEDURE setCC(VAR x: OBT.Item; cc: LONGINT); BEGIN x.typ := OBT.booltyp; x.mode := Coc; x.a0 := cc; x.a1 := 0; x.a2 := 0 END setCC; PROCEDURE cmp(L: INTEGER; VAR x, y: OBT.Item); BEGIN IF (y.mode = Con) & (y.a0 <= 7) & (y.a0 >= -8) THEN OBC.PutF2(L+1CH, y.a0, x) (*CMPQi*) ELSE OBC.PutF4(L+4, x, y) (*CMPi*) END END cmp; PROCEDURE add(L: INTEGER; VAR x, y: OBT.Item); BEGIN IF (y.mode = Con) & (y.a0 <= 7) & (y.a0 >= -8) THEN OBC.PutF2(L+0CH, y.a0, x) (*ADDQi*) ELSE OBC.PutF4(L, x, y) (*ADDi*) END END add; PROCEDURE sub(L: INTEGER; VAR x, y: OBT.Item); BEGIN IF (y.mode = Con) & (y.a0 <= 8) & (y.a0 >= -7) THEN OBC.PutF2(L+0CH, -y.a0, x) (*ADDQi*) ELSE OBC.PutF4(L+20H, x, y) (*SUBi*) END END sub; PROCEDURE mant(x: LONGINT): LONGINT; (*x DIV 2^log*) BEGIN log := 0; IF x > 0 THEN WHILE ~ODD(x) DO x := x DIV 2; INC(log) END END ; RETURN x END mant; PROCEDURE Inc*(VAR x, y: OBT.Item); BEGIN add(lengcode[x.typ.form], x, y) END Inc; PROCEDURE SetIntType*(VAR x: OBT.Item); VAR v: LONGINT; BEGIN v := x.a0; IF (-80H <= v) & (v <= 7FH) THEN x.typ := OBT.sinttyp ELSIF (-8000H <= v) & (v <= 7FFFH) THEN x.typ := OBT.inttyp ELSE x.typ := OBT.linttyp END END SetIntType; PROCEDURE Index*(VAR x, y: OBT.Item); VAR f, L: INTEGER; i, n: LONGINT; eltyp: OBT.Struct; z, r: OBT.Item; BEGIN f := y.typ.form; IF ~(f IN intSet) THEN OBS.Mark(80); y.typ := OBT.inttyp END ; IF x.typ = NIL THEN HALT(80) END ; IF x.typ.form = Array THEN eltyp := x.typ.BaseTyp; IF eltyp = NIL THEN HALT(81) END ; n := x.typ.size DIV eltyp.size; IF y.mode = Con THEN IF (0 <= y.a0) & (y.a0 < n) THEN i := y.a0 * eltyp.size ELSE OBS.Mark(81); i := 0 END ; IF (x.mode = Var) & (x.lev >= 0) THEN INC(x.a0, i) ELSIF (x.mode = Ind) OR (x.mode = RegI) THEN INC(x.a1, i); x.obj := NIL ELSE loadAdr(x); x.a1 := i END ELSE IF f = LInt THEN load(y) ELSE loadX(y) END ; IF inxchk THEN (*z = len*) z.mode := Con; z.typ := y.typ; z.a0 := n; OBC.PutF4(lengcode[f]+4, z, y); OBC.PutF0(11); L := OBC.pc; OBC.PutWord(inxloc); inxloc := L END ; f := x.mode; IF x.mode = Var THEN x.mode := VarX; x.a2 := y.a0 ELSIF x.mode = Ind THEN x.mode := IndX; x.a2 := y.a0 ELSIF x.mode = RegI THEN x.mode := RegX; x.a2 := y.a0 ELSIF x.mode IN {VarX, IndX, RegX} THEN z.mode := Con; n := x.typ.size DIV eltyp.size; r.mode := Reg; r.a0 := x.a2; IF mant(n) = 1 THEN z.a0 := log; z.typ := OBT.sinttyp; OBC.Put(F6, 7, r, z) (*ASHD log, r*) ELSE z.a0 := n; z.typ := OBT.linttyp; OBC.Put(F7, 23H, r, z) (*MULD n, r*) END ; OBC.PutF4(3, r, y) (*ADDD y, r*) ELSE loadAdr(x); x.mode := RegX; x.a1 := 0; x.a2 := y.a0 END END ; x.typ := eltyp ELSIF x.typ.form = DynArr THEN IF f = LInt THEN load(y) ELSE loadX(y) END ; IF inxchk THEN z.mode := Var; z.a0 := x.a0 + x.typ.adr; z.lev := x.lev; OBC.PutF4(7, z, y); OBC.PutF0(11); L := OBC.pc; OBC.PutWord(inxloc); inxloc := L END ; IF x.mode IN {Var, Ind} THEN x.mode := IndX; x.a2 := y.a0 ELSIF x.mode = RegI THEN x.mode := RegX; x.a2 := y.a0 ELSIF x.mode IN {IndX, RegX} THEN z.mode := Var; z.a0 := x.a0 + x.typ.adr; z.lev := x.lev; r.mode := Reg; r.a0 := x.a2; OBC.Put(F7, 23H, r, z); OBC.PutF4(3, r, y) (*MULD z,r ADDD y,r*) ELSE loadAdr(x); x.mode := RegX; x.a1 := 0; x.a2 := y.a0 END ; x.typ := x.typ.BaseTyp ELSE OBS.Mark(82) END END Index; PROCEDURE Field*(VAR x: OBT.Item; y: OBT.Object); BEGIN (*x.typ.form = Record*) IF (y # NIL) & (y.mode = Fld) THEN IF (x.mode = Var) & (x.lev >= 0) THEN INC(x.a0, y.a0) ELSIF (x.mode = Ind) OR (x.mode = RegI) THEN INC(x.a1, y.a0) ELSE loadAdr(x); x.mode := RegI; x.a1 := y.a0 END ; x.typ := y.typ; x.obj := NIL ELSE OBS.Mark(83); x.typ := OBT.undftyp; x.mode := Var END END Field; PROCEDURE DeRef*(VAR x: OBT.Item); BEGIN IF x.typ.form = Pointer THEN IF (x.mode = Var) & (x.lev > 0) THEN x.mode := Ind ELSE load(x); x.mode := RegI END ; x.typ := x.typ.BaseTyp; x.obj := OBC.wasderef ELSE OBS.Mark(84) END ; x.a1 := 0 END DeRef; PROCEDURE TypTest*(VAR x, y: OBT.Item; test: BOOLEAN); PROCEDURE GTT(t0, t1: OBT.Struct; varpar: BOOLEAN); VAR t: OBT.Struct; L: INTEGER; xt, tdes, p: OBT.Item; BEGIN t := t0; WHILE (t # NIL) & (t # t1) DO t := t.BaseTyp END ; IF t # t1 THEN t := t1; REPEAT t := t.BaseTyp UNTIL (t = NIL) OR (t = t0); IF t # NIL THEN x.typ := y.typ; IF OBC.typchk OR test THEN xt := x; IF varpar THEN xt.mode := Ind; xt.a0 := x.a0+4 ELSIF (x.mode = Var) & (x.lev > 0) THEN xt.mode := Ind; xt.a1 := -4; load(xt); xt.mode := RegI ELSE load(xt); p := xt; p.mode := RegI; p.a1 := -4; OBC.PutF4(17H, xt, p); (*MOVD -4(xt), xt *) xt.mode := RegI END ; xt.a1 := t1.extlev * 4; tdes.mode := Var; tdes.lev := -t1.mno; tdes.a0 := t1.adr; OBC.PutF4(7, tdes, xt); (*CMPD*) IF ~test THEN OBC.PutF0(1); L := OBC.pc; OBC.PutWord(tchkloc); tchkloc := L ELSE setCC(x, 0) END END ELSE OBS.Mark(85); IF test THEN x.typ := OBT.booltyp END END ELSIF test THEN setCC(x, 14) END END GTT; BEGIN IF x.typ.form = Pointer THEN IF y.typ.form = Pointer THEN GTT(x.typ.BaseTyp, y.typ.BaseTyp, FALSE) ELSE OBS.Mark(86) END ELSIF (x.typ.form = Record) & (x.mode = Ind) & (x.obj # NIL) & (x.obj # OBC.wasderef) & (y.typ.form = Record) THEN GTT(x.typ, y.typ, TRUE) ELSE OBS.Mark(87) END END TypTest; PROCEDURE In*(VAR x, y: OBT.Item); VAR f: INTEGER; BEGIN f := x.typ.form; IF (f IN intSet) & (y.typ.form = Set) THEN IF y.mode = Con THEN load(y) END ; OBC.PutF4(lengcode[f]+34H, y, x); setCC(x, 8) (*TBITi*) ELSE OBS.Mark(92); x.mode := Reg END ; x.typ := OBT.booltyp; OBC.Release(y) END In; PROCEDURE Set0*(VAR x, y: OBT.Item); VAR one: LONGINT; BEGIN x.mode := Reg; x.a0 := 0; x.typ := OBT.settyp; IF y.typ.form IN intSet THEN IF y.mode = Con THEN x.mode := Con; IF (0 <= y.a0) & (y.a0 < 32) THEN one := 1; x.a0 := SYSTEM.LSH(one, y.a0) ELSE OBS.Mark(202) END ELSE OBC.GetReg(x); OBC.PutF2(5FH, 1, x); OBC.Put(F6, 17H, x, y); (*LSHD*) OBC.Release(y) END ; ELSE OBS.Mark(93) END END Set0; PROCEDURE Set1*(VAR x, y, z: OBT.Item); VAR s: LONGINT; BEGIN x.mode := Reg; x.a0 := 0; x.typ := OBT.settyp; IF (y.typ.form IN intSet) & (z.typ.form IN intSet) THEN IF y.mode = Con THEN IF (0 <= y.a0) & (y.a0 < 32) THEN y.typ := OBT.settyp; s := -1; y.a0 := SYSTEM.LSH(s, y.a0); IF z.mode = Con THEN x.mode := Con; IF (y.a0 <= z.a0) & (z.a0 < 32) THEN s := -2; x.a0 := y.a0 - SYSTEM.LSH(s, z.a0) ELSE OBS.Mark(202); x.a0 := 0 END ELSIF y.a0 = -1 THEN OBC.GetReg(x); OBC.PutF2(5FH, -2, x); OBC.Put(F6, 17H, x, z); OBC.Put(F6, 37H, x, x) (*LSHD, COMD*) ELSE OBC.GetReg(x); OBC.PutF4(17H, x, y); OBC.GetReg(y); OBC.PutF2(5FH, -2, y); OBC.Put(F6, 17H, y, z); OBC.PutF4(0BH, x, y) (*BICD*) END ELSE OBS.Mark(202) END ELSE OBC.GetReg(x); OBC.PutF2(5FH, -1, x); OBC.Put(F6, 17H, x, y); IF z.mode = Con THEN IF (0 <= z.a0) & (z.a0 < 32) THEN y.typ := OBT.settyp; y.mode := Con; s := -2; y.a0 := SYSTEM.LSH(s, z.a0) ELSE OBS.Mark(202) END ELSE OBC.GetReg(y); OBC.PutF2(5FH, -2, y); OBC.Put(F6, 17H, y, z); (*LSHD*) OBC.Release(y); OBC.Release(z) END ; OBC.PutF4(0BH, x, y) (*BICD*) END ELSE OBS.Mark(93) END END Set1; PROCEDURE MOp*(op: INTEGER; VAR x: OBT.Item); VAR f: INTEGER; a: LONGINT; xr: REAL; xl: LONGREAL; y: OBT.Item; BEGIN f := x.typ.form; OBC.Release(x); CASE op OF 5: (*&*) IF x.mode = Coc THEN OBC.PutF0(inverted(x.a0)); OBC.PutWord(x.a2); x.a2 := OBC.pc-2; OBC.FixLink(x.a1) ELSIF (x.typ.form = Bool) & (x.mode # Con) THEN OBC.PutF2(1CH, 1, x); setCC(x, 0); OBC.PutF0(1); OBC.PutWord(x.a2); x.a2 := OBC.pc-2; OBC.FixLink(x.a1) ELSIF x.typ.form # Bool THEN OBS.Mark(94); x.mode := Con; x.typ := OBT.booltyp; x.a0 := 0 END | 6: (*+*) IF ~(f IN intSet + realSet) THEN OBS.Mark(96) END | 7: (*-*) y := x; IF f IN intSet THEN IF x.mode = Con THEN x.a0 := -x.a0; SetIntType(x) ELSE OBC.GetReg(x); OBC.Put(F6, lengcode[f]+20H, x, y) (*NEGi*) END ELSIF f = Real THEN IF x.mode = Con THEN a := SYSTEM.ADR(x.a0); SYSTEM.GET(a, xr); SYSTEM.PUT(a, -xr) ELSE OBC.GetFReg(x); OBC.Put(F11, 15H, x, y) (*NEGF*) END ELSIF f = LReal THEN IF x.mode = Con THEN a := SYSTEM.ADR(x.a0); SYSTEM.GET(a, xl); SYSTEM.PUT(a, -xl) ELSE OBC.GetFReg(x); OBC.Put(F11, 14H, x, y) (*NEGL*) END ELSIF f = Set THEN OBC.GetReg(x); OBC.Put(F6, 37H, x, y) (*COMD*) ELSE OBS.Mark(97) END | 8: (*OR*) IF x.mode = Coc THEN OBC.PutF0(x.a0); OBC.PutWord(x.a1); x.a1 := OBC.pc-2; OBC.FixLink(x.a2) ELSIF (x.typ.form = Bool) & (x.mode # Con) THEN OBC.PutF2(1CH, 1, x); setCC(x, 0); OBC.PutF0(0); OBC.PutWord(x.a1); x.a1 := OBC.pc-2; OBC.FixLink(x.a2) ELSIF x.typ.form # Bool THEN OBS.Mark(95); x.mode := Con; x.typ := OBT.booltyp; x.a0 := 1 END | 9 .. 14: (*relations*) IF x.mode = Coc THEN loadB(x) END | 32: (*~*) IF x.typ.form = Bool THEN IF x.mode = Coc THEN x.a0 := inverted(x.a0); a := x.a1; x.a1 := x.a2; x.a2 := a ELSE OBC.PutF2(1CH, 0, x); setCC(x, 0) END ELSE OBS.Mark(98) END END END MOp; PROCEDURE convert1(VAR x: OBT.Item; typ: OBT.Struct); VAR y: OBT.Item; op: INTEGER; BEGIN IF x.mode # Con THEN y := x; IF typ.form = Int THEN op := 10H ELSE op := lengcode[x.typ.form] + 1CH END; IF x.mode < Reg THEN OBC.GetReg(x) END ; OBC.Put(F7, op, x, y) (*MOVij*) END ; x.typ := typ END convert1; PROCEDURE convert2(VAR x: OBT.Item; typ: OBT.Struct); VAR y: OBT.Item; BEGIN y := x; OBC.GetFReg(x); (*MOVif*) OBC.Put(F9, lengcode[typ.form]*4 + lengcode[x.typ.form], x, y); x.typ := typ END convert2; PROCEDURE convert3(VAR x: OBT.Item); VAR y: OBT.Item; BEGIN y := x; IF x.mode < Reg THEN OBC.GetFReg(x) END ; OBC.Put(F9, 1BH, x, y); x.typ := OBT.lrltyp (*MOVFL*) END convert3; PROCEDURE CompStrings(VAR x, y: OBT.Item; f, g: INTEGER; Q: BOOLEAN); VAR z: OBT.Item; BEGIN z.mode := Reg; z.a0 := 2; IF f = DynArr THEN OBC.DynArrAdr(z, x) ELSE OBC.PutF4(27H, z, x) END ; z.a0 := 1; IF g = DynArr THEN OBC.DynArrAdr(z, y) ELSE OBC.PutF4(27H, z, y) END ; z.a0 := 0; OBC.PutF2(5FH, -1, z); (*MOVQD -1, R0*) z.a0 := 4; OBC.PutF2(5FH, 0, z); (*MOVQD 0, R4*) OBC.PutF1(14); OBC.PutF1(4); OBC.PutF1(6); (*CMPSB 6*) IF Q THEN (*compare also with zero byte*) OBC.PutF0(9); OBC.PutDisp(5); (*BFC*) z.mode := RegI; z.a0 := 2; z.a1 := 0; OBC.PutF2(1CH, 0, z) (*CMPQB*) END END CompStrings; PROCEDURE Op*(op: INTEGER; VAR x, y: OBT.Item); VAR f, g, L: INTEGER; p, q, r: OBT.Struct; PROCEDURE strings(): BOOLEAN; BEGIN RETURN ((((f=Array) OR (f=DynArr)) & (x.typ.BaseTyp.form=Char)) OR (f=String)) & ((((g=Array) OR (g=DynArr)) & (y.typ.BaseTyp.form=Char)) OR (g=String)) END strings; PROCEDURE CompBool(cc: INTEGER); BEGIN IF y.mode = Coc THEN loadB(y) END ; OBC.PutF4(4, x, y); setCC(x, cc) END CompBool; BEGIN IF x.typ # y.typ THEN g := y.typ.form; CASE x.typ.form OF Undef: | SInt: IF g = Int THEN convert1(x, y.typ) ELSIF g = LInt THEN convert1(x, y.typ) ELSIF g = Real THEN convert2(x, y.typ) ELSIF g = LReal THEN convert2(x, y.typ) ELSE OBS.Mark(100) END | Int: IF g = SInt THEN convert1(y, x.typ) ELSIF g = LInt THEN convert1(x, y.typ) ELSIF g = Real THEN convert2(x, y.typ) ELSIF g = LReal THEN convert2(x, y.typ) ELSE OBS.Mark(100) END | LInt: IF g = SInt THEN convert1(y, x.typ) ELSIF g = Int THEN convert1(y, x.typ) ELSIF g = Real THEN convert2(x, y.typ) ELSIF g = LReal THEN convert2(x, y.typ) ELSE OBS.Mark(100) END | Real: IF g = SInt THEN convert2(y, x.typ) ELSIF g = Int THEN convert2(y, x.typ) ELSIF g = LInt THEN convert2(y, x.typ) ELSIF g = LReal THEN convert3(x) ELSE OBS.Mark(100) END | LReal: IF g = SInt THEN convert2(y, x.typ) ELSIF g = Int THEN convert2(y, x.typ) ELSIF g = LInt THEN convert2(y, x.typ) ELSIF g = Real THEN convert3(y) ELSE OBS.Mark(100) END | NilTyp: IF g # Pointer THEN OBS.Mark(100) END | Pointer: IF g = Pointer THEN p := x.typ.BaseTyp; q := y.typ.BaseTyp; IF (p.form = Record) & (q.form = Record) THEN IF p.extlev < q.extlev THEN r := p; p := q; q := r END; WHILE (p # q) & (p # NIL) DO p := p.BaseTyp END; IF p = NIL THEN OBS.Mark(100) END ELSE OBS.Mark(100) END ELSIF g # NilTyp THEN OBS.Mark(100) END | ProcTyp: IF g # NilTyp THEN OBS.Mark(100) END | Array, DynArr, String: | Byte, Bool, Char, Set, NoTyp, Record: OBS.Mark(100) END END ; f := x.typ.form; g := y.typ.form; L := lengcode[f]; CASE op OF 1: IF f IN intSet THEN (***) IF (x.mode = Con) & (y.mode = Con) THEN (*ovfl test missing*) x.a0 := x.a0 * y.a0; SetIntType(x) ELSIF (x.mode = Con) & (mant(x.a0) = 1) THEN x.a0 := log; x.typ := OBT.sinttyp; load(y); OBC.Put(F6, L+4, y, x); (*ASHi*) x := y; y.mode := Con (*prevent release of register*) ELSIF (y.mode = Con) & (mant(y.a0) = 1) THEN y.a0 := log; y.typ := OBT.sinttyp; load(x); OBC.Put(F6, L+4, x, y) (*ASHi*) ELSE load(x); OBC.Put(F7, L+20H, x, y) (*MULi*) END ELSIF f IN realSet THEN loadF(x); OBC.Put(F11, 30H+L, x, y) (*MULf*) ELSIF f = Set THEN load(x); OBC.PutF4(2BH, x, y) (*ANDD*) ELSIF f # Undef THEN OBS.Mark(101) END | 2: IF f IN realSet THEN (*/*) loadF(x); OBC.Put(F11, 20H+L, x, y) (*DIVf*) ELSIF f IN intSet THEN convert2(x, OBT.realtyp); convert2(y, OBT.realtyp); OBC.Put(F11, 21H, x, y) (*DIVF*) ELSIF f = Set THEN load(x); OBC.PutF4(3BH, x, y) (*XORD*) ELSIF f # Undef THEN OBS.Mark(102) END | 3: IF f IN intSet THEN (*DIV*) IF (x.mode = Con) & (y.mode = Con) THEN IF y.a0 # 0 THEN x.a0 := x.a0 DIV y.a0; SetIntType(x) ELSE OBS.Mark(205) END ELSIF (y.mode = Con) & (mant(y.a0) = 1) THEN y.a0 := -log; y.typ := OBT.sinttyp; load(x); OBC.Put(F6, L+4, x, y) (*ASHi*) ELSE load(x); OBC.Put(F7, L+3CH, x, y) (*DIVi*) END ELSIF f # Undef THEN OBS.Mark(103) END | 4: IF f IN intSet THEN (*MOD*) IF (x.mode = Con) & (y.mode = Con) THEN IF y.a0 # 0 THEN x.a0 := x.a0 MOD y.a0; x.typ := y.typ ELSE OBS.Mark(205) END ELSIF (y.mode = Con) & (mant(y.a0) = 1) THEN y.a0 := ASH(-1, log); load(x); OBC.PutF4(L+8, x, y) (*BICi*) ELSE load(x); OBC.Put(F7, L+38H, x, y) (*MODi*) END ELSIF f # Undef THEN OBS.Mark(104) END | 5: IF y.mode # Coc THEN (*&*) IF y.mode = Con THEN IF y.a0 = 1 THEN setCC(y, 14) ELSE setCC(y, 15) END ELSIF y.mode <= Reg THEN OBC.PutF2(1CH, 1, y); setCC(y, 0) ELSE OBS.Mark(94); setCC(y, 0) END END ; IF x.mode = Con THEN IF x.a0 = 0 THEN OBC.FixLink(y.a1); OBC.FixLink(y.a2); setCC(y, 15) END ; setCC(x, 0) END; IF y.a2 # 0 THEN x.a2 := OBC.MergedLinks(x.a2, y.a2) END ; x.a0 := y.a0; x.a1 := y.a1 | 6: IF f IN intSet THEN (*+*) IF (x.mode = Con) & (y.mode = Con) THEN INC(x.a0, y.a0); SetIntType(x) (*ovfl test missing*) ELSE load(x); add(L, x, y) END ELSIF f IN realSet THEN loadF(x); OBC.Put(F11, L, x, y) (*ADDf*) ELSIF f = Set THEN IF (x.mode = Con) & (y.mode = Con) THEN x.a0 := SYSTEM.VAL (LONGINT, SYSTEM.VAL(SET, x.a0) + SYSTEM.VAL(SET, y.a0)) ELSE load(x); OBC.PutF4(1BH, x, y) (*ORD*) END ELSIF f # Undef THEN OBS.Mark(105) END | 7: IF f IN intSet THEN (*-*) IF (x.mode = Con) & (y.mode = Con) THEN DEC(x.a0, y.a0); SetIntType(x) (*ovfl test missing*) ELSE load(x); sub(L, x, y) END ELSIF f IN realSet THEN loadF(x); OBC.Put(F11, 10H+L, x, y) (*SUBf*) ELSIF f = Set THEN load(x); OBC.PutF4(0BH, x, y) (*BICD*) ELSIF f # Undef THEN OBS.Mark(106) END | 8: IF y.mode # Coc THEN (*OR*) IF y.mode = Con THEN IF y.a0 = 1 THEN setCC(y, 14) ELSE setCC(y, 15) END ELSIF y.mode <= Reg THEN OBC.PutF2(1CH, 1, y); setCC(y, 0) ELSE OBS.Mark(95); setCC(y, 0) END END ; IF x.mode = Con THEN IF x.a0 = 1 THEN OBC.FixLink(y.a1); OBC.FixLink(y.a2); setCC(y, 14) END ; setCC(x, 0) END; IF y.a1 # 0 THEN x.a1 := OBC.MergedLinks(x.a1, y.a1) END ; x.a0 := y.a0; x.a2 := y.a2 | 9: IF f IN {Undef, Char..LInt, Set, NilTyp, Pointer, ProcTyp} THEN (* = *) cmp(L, x, y); setCC(x, 0) ELSIF f IN realSet THEN OBC.Put(F11, 8+L, x, y); setCC(x, 0) ELSIF f = Bool THEN CompBool(0) ELSIF strings() THEN CompStrings(x, y, f, g, TRUE); setCC(x, 0) ELSE OBS.Mark(107) END | 10: IF f IN {Undef, Char..LInt, Set, NilTyp, Pointer, ProcTyp} THEN (* # *) cmp(L, x, y); setCC(x, 1) ELSIF f IN realSet THEN OBC.Put(F11, 8+L, x, y); setCC(x, 1) ELSIF f = Bool THEN CompBool(1) ELSIF strings() THEN CompStrings(x, y, f, g, TRUE); setCC(x, 1) ELSE OBS.Mark(107) END | 11: IF f IN intSet THEN cmp(L, x, y); setCC(x, 6) (* < *) ELSIF f = Char THEN cmp(0, x, y); setCC(x, 4) ELSIF f IN realSet THEN OBC.Put(F11, 8+L, x, y); setCC(x, 6) ELSIF strings() THEN CompStrings(x, y, f, g, FALSE); setCC(x, 4) ELSE OBS.Mark(108) END | 12: IF f IN intSet THEN cmp(L, x, y); setCC(x, 13) (* <= *) ELSIF f = Char THEN cmp(0, x, y); setCC(x, 11) ELSIF f IN realSet THEN OBC.Put(F11, 8+L, x, y); setCC(x, 13) ELSIF strings() THEN CompStrings(y, x, g, f, FALSE); setCC(x, 5) ELSE OBS.Mark(108) END | 13: IF f IN intSet THEN cmp(L, x, y); setCC(x, 12) (* > *) ELSIF f = Char THEN cmp(0, x, y); setCC(x, 10) ELSIF f IN realSet THEN OBC.Put(F11, 8+L, x, y); setCC(x, 12) ELSIF strings() THEN CompStrings(y, x, g, f, FALSE); setCC(x, 4) ELSE OBS.Mark(108) END | 14: IF f IN intSet THEN cmp(L, x, y); setCC(x, 7) (* >= *) ELSIF f = Char THEN cmp(0, x, y); setCC(x, 5) ELSIF f IN realSet THEN OBC.Put(F11, 8+L, x, y); setCC(x, 7) ELSIF strings() THEN CompStrings(x, y, f, g, FALSE); setCC(x, 5) ELSE OBS.Mark(108) END END ; OBC.Release(y) END Op; PROCEDURE StPar1*(VAR x: OBT.Item; fctno: INTEGER); VAR f, L: INTEGER; y: OBT.Item; BEGIN f := x.typ.form; CASE fctno OF 0: (*HALT*) IF (f = SInt) & (x.mode = Con) THEN IF x.a0 >= 20 THEN OBC.PutF1(0F2H); OBC.PutByte(x.a0) (*BPT*) ELSE OBS.Mark(218) END ELSE OBS.Mark(217) END ; x.typ := OBT.notyp | 1: (*NEW*) y.mode := Reg; IF f = Pointer THEN y.a0 := 0; OBC.PutF4(27H, y, x); x.typ := x.typ.BaseTyp; f := x.typ.form; IF x.typ.size > 7FFF80H THEN OBS.Mark(227) ELSIF f = Record THEN y.a0 := 1; x.mode := Var; x.lev := -x.typ.mno; x.a0 := x.typ.adr; OBC.PutF4(17H, y, x); OBC.PutF1(0E2H); OBC.PutByte(0) (*SVC 0*) ELSIF f = Array THEN y.a0 := 2; x.a0 := x.typ.size; x.mode := Con; x.typ := OBT.linttyp; OBC.PutF4(17H, y, x); OBC.PutF1(0E2H); OBC.PutByte(1) (*SVC 1*) ELSE OBS.Mark(111) END ELSE OBS.Mark(111) END ; x.typ := OBT.notyp | 2: (*SYSTEM.CC*) IF (f = SInt) & (x.mode = Con) THEN IF (0 <= x.a0) & (x.a0 < 16) THEN setCC(x, x.a0) ELSE OBS.Mark(219) END ELSE OBS.Mark(217) END | 3: (*ABS*) y := x; L := lengcode[f]; IF f IN intSet THEN IF x.mode = Con THEN x.a0 := ABS(x.a0) ELSE OBC.GetReg(x); OBC.Put(F6, 30H+L, x, y) (*ABSi*) END ELSIF f IN realSet THEN OBC.GetFReg(x); OBC.Put(F11, 34H+L, x, y) (*ABSf*) ELSE OBS.Mark(111) END | 4: (*CAP*) y.mode := Con; y.typ := OBT.chartyp; y.a0 := 5FH; IF f = Char THEN load(x); OBC.PutF4(28H, x, y) (*ANDB*) ELSE OBS.Mark(111); x.typ := OBT.chartyp END | 5: (*ORD*) IF (f = Char) OR (f = Byte) THEN IF x.mode # Con THEN y := x; OBC.GetReg(x); OBC.Put(F7, 14H, x, y) (*MOVZBW*) END ELSE OBS.Mark(111) END ; x.typ := OBT.inttyp | 6: (*ENTIER*) IF f IN realSet THEN y := x; OBC.GetReg(x); OBC.Put(F9, lengcode[f]*4 + 3BH, x, y) (*FLOORfD*) ELSE OBS.Mark(111) END ; x.typ := OBT.linttyp | 7: (*SYSTEM.SIZE*) IF (x.mode = Typ) & (x.typ.form # Undef) THEN x.a0 := x.typ.size ELSE OBS.Mark(110); x.a0 := 1 END ; x.mode := Con; SetIntType(x) | 8: (*ODD*) IF f IN intSet THEN y.mode := Con; y.typ := OBT.sinttyp; y.a0 := 0; OBC.PutF4(34H, x, y) (*TBITB 0*) ELSE OBS.Mark(111) END ; setCC(x, 8) | 9: (*SYSTEM.ADR*) IF f = DynArr THEN y := x; OBC.GetReg(x); OBC.DynArrAdr(x, y) ELSE loadAdr(x); x.mode := Reg END ; x.typ := OBT.linttyp | 10: (*MIN*) IF x.mode = Typ THEN x.mode := Con; CASE f OF Bool, Char: x.a0 := 0 | SInt: x.a0 := -80H | Int: x.a0 := -8000H | LInt: x.a0 := 80000000H | Real: x.a0 := 0FF7FFFFFH | LReal: x.a0 := 0FFFFFFFFH; x.a1 := 0FFEFFFFFH | Set: x.a0 := 0; x.typ := OBT.inttyp | Undef, NilTyp .. Record: OBS.Mark(111) END ELSE OBS.Mark(110) END | 11: (*MAX*) IF x.mode = Typ THEN x.mode := Con; CASE f OF Bool: x.a0 := 1 | Char: x.a0 := 0FFH | SInt: x.a0 := 7FH | Int: x.a0 := 7FFFH | LInt: x.a0 := 7FFFFFFFH | Real: x.a0 := 7F7FFFFFH | LReal: x.a0 := 0FFFFFFFFH; x.a1 := 7FEFFFFFH | Set: x.a0 := 31; x.typ := OBT.inttyp | Undef, NilTyp .. Record: OBS.Mark(111) END ELSE OBS.Mark(110) END | | 12: (*CHR*) IF ~(f IN {Undef, Byte, SInt, Int, LInt}) THEN OBS.Mark(111) END ; IF (x.mode = VarX) OR (x.mode = IndX) THEN load(x) END ; x.typ := OBT.chartyp | 13: (*SHORT*) IF f = LInt THEN (*range test missing*) IF (x.mode = VarX) OR (x.mode = IndX) THEN load(x) ELSIF x.mode = Con THEN SetIntType(x); IF x.typ.form = LInt THEN OBS.Mark(203) END END ; x.typ := OBT.inttyp ELSIF f = LReal THEN (*MOVLF*) y := x; OBC.GetFReg(x); OBC.Put(F9, 16H, x, y); x.typ := OBT.realtyp ELSIF f = Int THEN (*range test missing*) IF (x.mode = VarX) OR (x.mode = IndX) THEN load(x) ELSIF x.mode = Con THEN SetIntType(x); IF x.typ.form # SInt THEN OBS.Mark(203) END END ; x.typ := OBT.sinttyp ELSE OBS.Mark(111) END | 14: (*LONG*) IF f = Int THEN convert1(x, OBT.linttyp) ELSIF f = Real THEN convert3(x) ELSIF f = SInt THEN convert1(x, OBT.inttyp) ELSIF (f = Char) OR (f = Byte) THEN y := x; OBC.GetReg(x); OBC.Put(F7, 18H, x, y); x.typ := OBT.linttyp (*MOVZBD*) ELSE OBS.Mark(111) END | 15: | 16,17: (*INC DEC*) IF x.mode >= Con THEN OBS.Mark(112) ELSIF ~(f IN intSet) THEN OBS.Mark(111) END | 18,19: (*INCL EXCL*) IF x.mode >= Con THEN OBS.Mark(112) ELSIF x.typ.form # Set THEN OBS.Mark(111); x.typ := OBT.settyp END | 20: (*LEN*) IF (f # DynArr) & (f # Array) THEN OBS.Mark(131) END | 21: (*ASH*) IF f = LInt THEN load(x) ELSIF f IN intSet THEN loadX(x); x.typ := OBT.linttyp ELSE OBS.Mark(111) END | 22, 23: (*SYSTEM.LSH SYSTEM.ROT*) IF f IN {Char, SInt, Int, LInt, Set} THEN load(x) ELSE OBS.Mark(111) END | 24 .. 26: (*SYSTEM.GET, SYSTEM.PUT, SYSTEM.BIT*) IF (f IN intSet) & (x.mode = Con) THEN x.mode := Abs ELSIF f = LInt THEN IF (x.mode = Var) & (x.lev > 0) THEN x.mode := Ind; x.a1 := 0 ELSE load(x); x.mode := RegI; x.a1 := 0 END ELSE OBS.Mark(111) END | 28: (*SYSTEM.VAL*) IF x.mode # Typ THEN OBS.Mark(110) END | 29: (*SYSTEM.NEW*) IF (f = Pointer) & (x.mode < Con) THEN y.mode := Reg; y.a0 := 0; OBC.PutF4(27H, y, x); ELSE OBS.Mark(111) END | 30: (*COPY*) IF (((f=Array) OR (f=DynArr)) & (x.typ.BaseTyp.form = Char)) OR (f = String) THEN y.mode := Reg; y.a0 := 1; IF f = DynArr THEN OBC.DynArrAdr(y, x) ELSE OBC.PutF4(27H, y, x) END ELSE OBS.Mark(111) END | 31: (*SYSTEM.MOVE*) IF f = LInt THEN y.mode := Reg; y.a0 := 1; OBC.PutF4(17H, y, x) ELSE OBS.Mark(111) END END END StPar1; PROCEDURE StPar2*(VAR p, x: OBT.Item; fctno: INTEGER); VAR f, L: INTEGER; y: OBT.Item; typ: OBT.Struct; BEGIN f := x.typ.form; IF fctno < 16 THEN OBS.Mark(64); RETURN END ; CASE fctno OF 16, 17: (*INC DEC*) IF x.typ # p.typ THEN IF (x.mode = Con) & (x.typ.form IN intSet) THEN x.typ := p.typ ELSE OBS.Mark(111) END END ; L := lengcode[p.typ.form]; IF fctno = 16 THEN add(L, p, x) ELSE sub(L, p, x) END ; p.typ := OBT.notyp | 18: (*INCL*) Set0(y, x); OBC.PutF4(1BH, p, y); p.typ := OBT.notyp (*ORD*) | 19: (*EXCL*) Set0(y, x); OBC.PutF4(0BH, p, y); p.typ := OBT.notyp (*BICD*) | 20: (*LEN*) IF (x.mode = Con) & (f = SInt) THEN L := SHORT(x.a0); typ := p.typ; WHILE (L > 0) & (typ.form IN {DynArr, Array}) DO typ := typ.BaseTyp; DEC(L) END; IF (L # 0) OR ~(typ.form IN {DynArr, Array}) THEN OBS.Mark(132) ELSE IF typ.form = DynArr THEN p.mode := Var; p.typ := OBT.linttyp; INC(p.a0, typ.adr) ELSE p := x; p.a0 := typ.size DIV typ.BaseTyp.size; SetIntType(p) END END ELSE OBS.Mark(111) END | 21, 22, 23: (*ASH SYSTEM.LSH SYSTEM.ROT*) IF f IN intSet THEN IF fctno = 21 THEN L := 4 ELSIF fctno = 22 THEN L := 14H ELSE L := 0 END ; IF (x.mode = VarX) OR (x.mode = IndX) THEN load(x) END ; x.typ := OBT.sinttyp; OBC.Put(F6, lengcode[p.typ.form]+L, p, x) ELSE OBS.Mark(111) END | 24: (*SYSTEM.GET*) IF x.mode >= Con THEN OBS.Mark(112) ELSIF f IN {Undef..LInt, Set, Pointer, ProcTyp} THEN OBC.PutF4(lengcode[f]+14H, x, p) ELSIF f IN realSet THEN OBC.Put(F11, lengcode[f]+4, x, p) (*MOVf*) END ; p.typ := OBT.notyp | 25: (*SYSTEM.PUT*) IF f IN {Undef..LInt, Set, Pointer, ProcTyp} THEN OBC.PutF4(lengcode[f]+14H, p, x) ELSIF f IN realSet THEN OBC.Put(F11, lengcode[f]+4, p, x) (*MOVf*) ELSE OBS.Mark(111) END ; p.typ := OBT.notyp | 26: (*SYSTEM.BIT*) IF f IN intSet THEN OBC.PutF4(lengcode[f] + 34H, p, x) (*TBITi*) ELSE OBS.Mark(111) END ; setCC(p, 8) | 27: | 28: (*SYSTEM.VAL*) x.typ := p.typ; p := x | 29: (*SYSTEM.NEW*) y.mode := Reg; y.a0 := 2; IF f = LInt THEN OBC.PutF4(17H, y, x) ELSIF f = Int THEN OBC.Put(F7, 1DH, y, x) (*MOVXWD*) ELSIF f = SInt THEN OBC.Put(F7, 1CH, y, x) (*MOVXBD*) ELSE OBS.Mark(111) END ; OBC.PutF1(0E2H); OBC.PutByte(1); (*SVC 1*) p.typ := OBT.notyp | 30: (*COPY*) IF ((f = Array) OR (f = DynArr)) & (x.typ.BaseTyp.form = Char) THEN y.mode := Reg; y.a0 := 2; y.a1 := 0; IF f = DynArr THEN p := x; OBC.DynArrAdr(y, x); y.a0 := 0; p.mode := Var; INC(p.a0, p.typ.adr); OBC.PutF4(17H, y, p) ELSE OBC.PutF4(27H, y, x); y.a0 := 0; p.mode := Con; p.typ := OBT.inttyp; p.a0:= x.typ.size-1; OBC.Put(F7, 19H, y, p); (*MOVZWD*) END; y.a0 := 4; OBC.PutF2(5FH, 0, y); (*MOVQD*) OBC.PutF1(14); OBC.PutF1(0); OBC.PutF1(6); (*MOVSB*) y.mode := RegI; y.a0 := 2; OBC.PutF2(5CH, 0, y) (*MOVQB*) ELSE OBS.Mark(111) END ; p.typ := OBT.notyp | 31: (*SYSTEM.MOVE*) IF f = LInt THEN y.mode := Reg; y.a0 := 2; OBC.PutF4(17H, y, x) ELSE OBS.Mark(111) END END END StPar2; PROCEDURE StPar3*(VAR p, x: OBT.Item; fctno: INTEGER); VAR f: INTEGER; y: OBT.Item; BEGIN f := x.typ.form; IF fctno = 31 THEN (*SYSTEM.MOVE*) y.mode := Reg; y.a0 := 0; IF f = Int THEN OBC.Put(F7, 1DH, y, x) ELSIF f = SInt THEN OBC.Put(F7, 1CH, y, x) ELSIF f = LInt THEN OBC.PutF4(17H, y, x) ELSE OBS.Mark(111) END ; OBC.PutF1(14); OBC.PutF1(0); OBC.PutF1(0); p.typ := OBT.notyp (*MOVSB*) ELSE OBS.Mark(64) END END StPar3; PROCEDURE StFct*(VAR p: OBT.Item; fctno, parno: INTEGER); BEGIN IF fctno >= 16 THEN IF (fctno = 16) & (parno = 1) THEN (*INC*) OBC.PutF2(lengcode[p.typ.form]+0CH, 1, p); p.typ := OBT.notyp ELSIF (fctno = 17) & (parno = 1) THEN (*DEC*) OBC.PutF2(lengcode[p.typ.form]+0CH, -1, p); p.typ := OBT.notyp ELSIF (fctno = 20) & (parno = 1) THEN (*LEN*) IF p.typ.form = DynArr THEN p.mode := Var; INC(p.a0, p.typ.adr); p.typ := OBT.linttyp ELSIF p.typ.form = Array THEN p.mode := Con; p.a0 := p.typ.size DIV p.typ.BaseTyp.size; SetIntType(p) END ELSIF (parno < 2) OR (fctno = 31) & (parno < 3) THEN OBS.Mark(65) END ELSIF parno < 1 THEN OBS.Mark(65) END END StFct;BEGIN intSet := {SInt, Int, LInt}; realSet := {Real, LReal}; 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 OBE.