| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835 |
- IMPLEMENTATION MODULE MGen;
- IMPORT FileIO, SymTab;
- CONST
- MaxCode = 8191;
- MaxImg = 16383;
- MaxGlb = 255;
- MaxInit = 255;
- MaxLab = 255;
- MaxFix = 2047;
- MaxLoop = 15;
- (* opcodes, see mc64-spec.md §11 *)
- OPdup = 20H; OPswap = 21H;
- OPloadGlb = 2DH; OPstoreGlb = 3DH;
- OPext = 40H; SUBdrop = 00H;
- OPenter = 0D4H; OPfctLeave = 85H; OPprocCall = 0EDH;
- OPimmB = 8DH; OPimmW = 8EH; OPimm0 = 90H;
- OPadd = 0A6H; OPsub = 0A7H; OPumul = 0A8H;
- OPudiv = 0A9H; OPumod = 0AAH;
- OPaeq0 = 0ABH; OPinc = 0ACH; OPdec = 0ADH;
- OPeq = 0A0H; OPne = 0A1H;
- OPult = 0A2H; OPugt = 0A3H; OPule = 0A4H; OPuge = 0A5H;
- OPilt = 0B2H; OPigt = 0B3H; OPile = 0B4H; OPige = 0B5H;
- OPnot = 0B6H;
- OPimul = 0B8H; OPidiv = 0B9H;
- OPintToLong = 0BDH; OPlongToReal = 0BEH;
- OPrCmp = 0D5H; OPrAdd = 0D6H; OPrSub = 0D7H;
- OPrMul = 0D8H; OPrDiv = 0D9H;
- OPor = 0E6H; OPand = 0E8H;
- OPpower2 = 0EAH; OPbitIn = 0E7H;
- OPjp = 0E0H; OPjz = 0E1H;
- OPsys = 0C3H; OPend = 50H;
- (* image layout *)
- HeadSize = 64;
- DName = 264; DChecksum = 288; DFlags = 292;
- DVarCount = 293; DDepCount = 294; DProcs = 296;
- DVarSizes = 304;
- TYPE
- FixRec = RECORD
- pos : CARDINAL;
- lab : INTEGER;
- END;
- InitRec = RECORD
- idx : CARDINAL;
- kind : INTEGER; (* 0 = INTEGER value, 1 = raw 64-bit pattern *)
- ival : INTEGER;
- bits : LONGCARD;
- END;
- RealView = RECORD CASE : BOOLEAN OF
- | TRUE : r : REAL;
- | FALSE : w : LONGCARD;
- END;
- END;
- VAR
- code : ARRAY [0 .. MaxCode] OF CHAR;
- nCode : CARDINAL;
- img : ARRAY [0 .. MaxImg] OF CHAR;
- modName : ARRAY [0 .. 63] OF CHAR;
- gNames : ARRAY [0 .. MaxGlb] OF ARRAY [0 .. 63] OF CHAR;
- nGlb : CARDINAL;
- inits : ARRAY [0 .. MaxInit] OF InitRec;
- nInit : CARDINAL;
- inBody : BOOLEAN;
- labs : ARRAY [0 .. MaxLab] OF INTEGER;
- nLab : CARDINAL;
- fixs : ARRAY [0 .. MaxFix] OF FixRec;
- nFix : CARDINAL;
- loopSt : ARRAY [0 .. MaxLoop] OF INTEGER;
- loopTop : CARDINAL;
- noSup : CARDINAL;
- noEmit : CARDINAL;
- (* ---------------- byte helpers ---------------- *)
- PROCEDURE StrLen (s: ARRAY OF CHAR): CARDINAL;
- VAR i : CARDINAL;
- BEGIN
- i := 0;
- WHILE (i < HIGH(s)) & (s[i] # 0C) DO INC(i) END;
- RETURN i
- END StrLen;
- PROCEDURE StrCpy (VAR d: ARRAY OF CHAR; s: ARRAY OF CHAR);
- VAR i : CARDINAL;
- BEGIN
- i := 0;
- WHILE (i < HIGH(d)) & (i < HIGH(s)) & (s[i] # 0C) DO
- d[i] := s[i]; INC(i)
- END;
- IF i <= HIGH(d) THEN d[i] := 0C END
- END StrCpy;
- PROCEDURE EmitByte (b: CARDINAL);
- BEGIN
- IF noEmit > 0 THEN RETURN END;
- IF nCode <= MaxCode THEN
- code[nCode] := CHR(b MOD 256); INC(nCode)
- END
- END EmitByte;
- PROCEDURE EmitOp (o: CARDINAL);
- BEGIN
- EmitByte(o)
- END EmitOp;
- PROCEDURE EmitOpB (o, b: CARDINAL);
- BEGIN
- EmitByte(o); EmitByte(b)
- END EmitOpB;
- PROCEDURE EmitW64 (v: LONGCARD);
- VAR j : CARDINAL;
- BEGIN
- FOR j := 0 TO 7 DO
- EmitByte(VAL(CARDINAL, v MOD 256)); v := v DIV 256
- END
- END EmitW64;
- PROCEDURE EmitS64 (rel: INTEGER);
- (* Appends a signed 64-bit little-endian offset. *)
- VAR mag : CARDINAL;
- BEGIN
- IF rel >= 0 THEN EmitW64(VAL(LONGCARD, VAL(CARDINAL, rel)))
- ELSE
- IF rel = -2147483647 - 1 THEN mag := 80000000H
- ELSE mag := VAL(CARDINAL, -rel)
- END;
- EmitW64(0FFFFFFFFFFFFFFFFH - VAL(LONGCARD, mag) + 1H)
- END
- END EmitS64;
- PROCEDURE WriteS64At (off: CARDINAL; rel: INTEGER);
- (* Backpatches a signed offset into already-emitted code. *)
- VAR mag : CARDINAL;
- bits : LONGCARD;
- j : CARDINAL;
- BEGIN
- IF rel >= 0 THEN bits := VAL(LONGCARD, VAL(CARDINAL, rel))
- ELSE
- IF rel = -2147483647 - 1 THEN mag := 80000000H
- ELSE mag := VAL(CARDINAL, -rel)
- END;
- bits := 0FFFFFFFFFFFFFFFFH - VAL(LONGCARD, mag) + 1H
- END;
- FOR j := 0 TO 7 DO
- code[off + j] := CHR(VAL(CARDINAL, bits MOD 256));
- bits := bits DIV 256
- END
- END WriteS64At;
- PROCEDURE FindVar (name: ARRAY OF CHAR): INTEGER;
- VAR i : CARDINAL;
- BEGIN
- i := 0;
- WHILE i < nGlb DO
- IF SymTab.Equal(gNames[i], name) THEN RETURN VAL(INTEGER, i) END;
- INC(i)
- END;
- RETURN -1
- END FindVar;
- PROCEDURE AssignSlot (name: ARRAY OF CHAR): INTEGER;
- BEGIN
- IF nGlb > MaxGlb THEN RETURN -1 END;
- StrCpy(gNames[nGlb], name);
- INC(nGlb);
- RETURN VAL(INTEGER, nGlb - 1)
- END AssignSlot;
- (* ---------------- module / data section ---------------- *)
- PROCEDURE OpenModule (name: ARRAY OF CHAR);
- VAR i : CARDINAL;
- dummy : INTEGER;
- BEGIN
- StrCpy(modName, name);
- nCode := 0; nGlb := 0; nInit := 0;
- nLab := 0; nFix := 0; loopTop := 0; noSup := 0; noEmit := 0;
- inBody := FALSE;
- i := 0;
- WHILE i <= MaxGlb DO gNames[i][0] := 0C; INC(i) END;
- (* slots 0..3 belong to the print helper *)
- dummy := AssignSlot(""); dummy := AssignSlot("");
- dummy := AssignSlot(""); dummy := AssignSlot("")
- END OpenModule;
- PROCEDURE DeclVar (name: ARRAY OF CHAR);
- VAR idx : INTEGER;
- BEGIN
- idx := AssignSlot(name);
- IF idx < 0 THEN RETURN END
- END DeclVar;
- PROCEDURE BufInit (idx: INTEGER; kind: INTEGER; ival: INTEGER;
- bits: LONGCARD);
- BEGIN
- IF nInit > MaxInit THEN RETURN END;
- inits[nInit].idx := VAL(CARDINAL, idx);
- inits[nInit].kind := kind;
- inits[nInit].ival := ival;
- inits[nInit].bits := bits;
- INC(nInit)
- END BufInit;
- PROCEDURE DeclConst (name: ARRAY OF CHAR; lit: LitStr; t: INTEGER);
- VAR idx : INTEGER;
- cls : INTEGER;
- v : INTEGER;
- c : CARDINAL;
- b : LONGCARD;
- BEGIN
- idx := AssignSlot(name);
- IF idx < 0 THEN RETURN END;
- cls := SymTab.ClassOf(t);
- IF ~IsLit(lit) OR (cls = SymTab.ClStr) THEN
- BufInit(idx, 0, 0, 0H); RETURN
- END;
- IF cls = SymTab.ClReal THEN
- IF ParseReal(lit, b) THEN BufInit(idx, 1, 0, b)
- ELSE BufInit(idx, 1, 0, 0H)
- END
- ELSIF SymTab.Equal(lit, "TRUE") THEN BufInit(idx, 0, 1, 0H)
- ELSIF SymTab.Equal(lit, "FALSE") THEN BufInit(idx, 0, 0, 0H)
- ELSIF ParseInt(lit, v) THEN BufInit(idx, 0, v, 0H)
- ELSIF ParseCard(lit, c) THEN
- BufInit(idx, 1, 0, VAL(LONGCARD, c))
- ELSE BufInit(idx, 0, 0, 0H)
- END
- END DeclConst;
- PROCEDURE DeclConstInt (name: ARRAY OF CHAR; v: INTEGER);
- VAR idx : INTEGER;
- BEGIN
- idx := AssignSlot(name);
- IF idx < 0 THEN RETURN END;
- BufInit(idx, 0, v, 0H)
- END DeclConstInt;
- PROCEDURE PushValue (kind: INTEGER; ival: INTEGER; bits: LONGCARD);
- BEGIN
- IF kind = 0 THEN PushInt(ival) ELSE PushBits(bits) END
- END PushValue;
- PROCEDURE BeginBody;
- VAR i : CARDINAL;
- BEGIN
- IF inBody THEN RETURN END;
- inBody := TRUE;
- i := 0;
- WHILE i < nInit DO
- PushValue(inits[i].kind, inits[i].ival, inits[i].bits);
- EmitOpB(OPstoreGlb, inits[i].idx);
- INC(i)
- END
- END BeginBody;
- (* ---------------- loads, stores, pushes ---------------- *)
- PROCEDURE LoadVar (name: ARRAY OF CHAR);
- VAR idx : INTEGER;
- BEGIN
- idx := FindVar(name);
- IF idx < 0 THEN EmitOp(OPimm0)
- ELSE EmitOpB(OPloadGlb, VAL(CARDINAL, idx))
- END
- END LoadVar;
- PROCEDURE StoreVar (name: ARRAY OF CHAR);
- VAR idx : INTEGER;
- BEGIN
- idx := FindVar(name);
- IF idx < 0 THEN EmitOp(OPext); EmitOp(SUBdrop)
- ELSE EmitOpB(OPstoreGlb, VAL(CARDINAL, idx))
- END
- END StoreVar;
- PROCEDURE LoadTemp (t: INTEGER);
- BEGIN
- EmitOpB(OPloadGlb, VAL(CARDINAL, t))
- END LoadTemp;
- PROCEDURE StoreTemp (t: INTEGER);
- BEGIN
- EmitOpB(OPstoreGlb, VAL(CARDINAL, t))
- END StoreTemp;
- PROCEDURE TempGlobal (): INTEGER;
- VAR idx : INTEGER;
- BEGIN
- idx := AssignSlot("");
- IF idx < 0 THEN RETURN 4 END;
- RETURN idx
- END TempGlobal;
- PROCEDURE EmitMag (c: CARDINAL);
- BEGIN
- IF c <= 255 THEN EmitOpB(OPimmB, c)
- ELSE EmitOp(OPimmW); EmitW64(VAL(LONGCARD, c))
- END
- END EmitMag;
- PROCEDURE PushInt (v: INTEGER);
- VAR mag : CARDINAL;
- BEGIN
- IF (v >= 0) & (v <= 15) THEN EmitOp(OPimm0 + VAL(CARDINAL, v))
- ELSIF v < 0 THEN
- IF v = -2147483647 - 1 THEN mag := 80000000H
- ELSE mag := VAL(CARDINAL, -v)
- END;
- EmitOp(OPimm0); EmitMag(mag); EmitOp(OPsub)
- ELSE EmitMag(VAL(CARDINAL, v))
- END
- END PushInt;
- PROCEDURE PushBits (b: LONGCARD);
- BEGIN
- EmitOp(OPimmW); EmitW64(b)
- END PushBits;
- (* ---------------- literal parsing ---------------- *)
- PROCEDURE DigVal (ch: CHAR): INTEGER;
- BEGIN
- IF (ch >= "0") & (ch <= "9") THEN RETURN ORD(ch) - ORD("0") END;
- IF (ch >= "A") & (ch <= "F") THEN RETURN ORD(ch) - ORD("A") + 10 END;
- IF (ch >= "a") & (ch <= "f") THEN RETURN ORD(ch) - ORD("a") + 10 END;
- RETURN -1
- END DigVal;
- PROCEDURE ParseCard (s: ARRAY OF CHAR; VAR v: CARDINAL): BOOLEAN;
- VAR i, n : CARDINAL;
- hex : BOOLEAN;
- d : INTEGER;
- acc : LONGCARD;
- BEGIN
- v := 0;
- n := StrLen(s);
- IF n = 0 THEN RETURN FALSE END;
- hex := (s[n - 1] = "H") OR (s[n - 1] = "h");
- IF hex THEN DEC(n) END;
- IF n = 0 THEN RETURN FALSE END;
- acc := 0H; i := 0;
- WHILE i < n DO
- d := DigVal(s[i]);
- IF hex THEN
- IF d < 0 THEN RETURN FALSE END;
- acc := acc * 16 + VAL(LONGCARD, VAL(CARDINAL, d))
- ELSE
- IF (d < 0) OR (d > 9) THEN RETURN FALSE END;
- acc := acc * 10 + VAL(LONGCARD, VAL(CARDINAL, d))
- END;
- IF acc > 0FFFFFFFFH THEN RETURN FALSE END;
- INC(i)
- END;
- v := VAL(CARDINAL, acc);
- RETURN TRUE
- END ParseCard;
- PROCEDURE ParseInt (s: ARRAY OF CHAR; VAR v: INTEGER): BOOLEAN;
- VAR i : CARDINAL;
- neg : BOOLEAN;
- t : ARRAY [0 .. 63] OF CHAR;
- c : CARDINAL;
- lim : LONGCARD;
- BEGIN
- v := 0;
- IF (StrLen(s) = 0) THEN RETURN FALSE END;
- neg := s[0] = "-";
- IF neg THEN
- i := 1;
- WHILE s[i] # 0C DO
- IF i - 1 > HIGH(t) THEN RETURN FALSE END;
- t[i - 1] := s[i]; INC(i)
- END;
- IF i - 1 > HIGH(t) THEN RETURN FALSE END;
- t[i - 1] := 0C
- ELSE StrCpy(t, s)
- END;
- IF ~ParseCard(t, c) THEN RETURN FALSE END;
- IF neg THEN lim := 80000000H ELSE lim := 7FFFFFFFH END;
- IF VAL(LONGCARD, c) > lim THEN RETURN FALSE END;
- IF neg THEN
- IF VAL(LONGCARD, c) = 80000000H THEN v := -2147483647 - 1
- ELSE v := -VAL(INTEGER, c)
- END
- ELSE v := VAL(INTEGER, c)
- END;
- RETURN TRUE
- END ParseInt;
- PROCEDURE ParseReal (s: ARRAY OF CHAR; VAR b: LONGCARD): BOOLEAN;
- VAR i : CARDINAL;
- neg, esign : BOOLEAN;
- m, scale : REAL;
- e, d : CARDINAL;
- rv : RealView;
- BEGIN
- b := 0H;
- i := 0; neg := FALSE;
- IF s[0] = "-" THEN neg := TRUE; INC(i) END;
- IF (s[i] < "0") OR (s[i] > "9") THEN RETURN FALSE END;
- m := 0.0;
- WHILE (s[i] >= "0") & (s[i] <= "9") DO
- m := m * 10.0 + VAL(REAL, VAL(CARDINAL, ORD(s[i]) - ORD("0")));
- INC(i)
- END;
- IF s[i] = "." THEN
- INC(i);
- IF (s[i] < "0") OR (s[i] > "9") THEN RETURN FALSE END;
- scale := 10.0;
- WHILE (s[i] >= "0") & (s[i] <= "9") DO
- m := m + VAL(REAL, VAL(CARDINAL, ORD(s[i]) - ORD("0"))) / scale;
- scale := scale * 10.0;
- INC(i)
- END
- END;
- IF (s[i] = "E") OR (s[i] = "e") THEN
- INC(i); esign := FALSE;
- IF s[i] = "+" THEN INC(i)
- ELSIF s[i] = "-" THEN esign := TRUE; INC(i)
- END;
- IF (s[i] < "0") OR (s[i] > "9") THEN RETURN FALSE END;
- e := 0;
- WHILE (s[i] >= "0") & (s[i] <= "9") DO
- d := VAL(CARDINAL, ORD(s[i]) - ORD("0"));
- IF e <= 9999 THEN e := e * 10 + d END;
- INC(i)
- END;
- WHILE e > 0 DO
- IF esign THEN m := m / 10.0 ELSE m := m * 10.0 END;
- DEC(e)
- END
- END;
- IF s[i] # 0C THEN RETURN FALSE END;
- IF neg THEN m := -m END;
- rv.r := m;
- b := rv.w;
- RETURN TRUE
- END ParseReal;
- PROCEDURE CharOrd (s: ARRAY OF CHAR): INTEGER;
- BEGIN
- IF StrLen(s) >= 2 THEN RETURN ORD(s[1]) END;
- RETURN 0
- END CharOrd;
- PROCEDURE NegFold (a: ARRAY OF CHAR; VAR q: LitStr);
- (* Safe for a and q being the same variable. *)
- VAR tmp : LitStr;
- i, j : CARDINAL;
- BEGIN
- StrCpy(tmp, a);
- IF StrLen(tmp) = 0 THEN StrCpy(q, ""); RETURN END;
- IF tmp[0] = "-" THEN
- i := 1; j := 0;
- WHILE (tmp[i] # 0C) & (j < HIGH(q)) DO
- q[j] := tmp[i]; INC(i); INC(j)
- END;
- IF j <= HIGH(q) THEN q[j] := 0C END
- ELSE
- StrCpy(q, "-");
- i := 0; j := StrLen(q);
- WHILE (tmp[i] # 0C) & (j < HIGH(q)) DO
- q[j] := tmp[i]; INC(i); INC(j)
- END;
- IF j <= HIGH(q) THEN q[j] := 0C END
- END
- END NegFold;
- PROCEDURE IsLit (s: ARRAY OF CHAR): BOOLEAN;
- BEGIN
- RETURN StrLen(s) > 0
- END IsLit;
- (* ---------------- operators ---------------- *)
- PROCEDURE Add;
- BEGIN EmitOp(OPadd) END Add;
- PROCEDURE Sub;
- BEGIN EmitOp(OPsub) END Sub;
- PROCEDURE MulU;
- BEGIN EmitOp(OPumul) END MulU;
- PROCEDURE DivU;
- BEGIN EmitOp(OPudiv) END DivU;
- PROCEDURE ModU;
- BEGIN EmitOp(OPumod) END ModU;
- PROCEDURE MulI;
- BEGIN EmitOp(OPimul) END MulI;
- PROCEDURE DivI;
- BEGIN EmitOp(OPidiv) END DivI;
- PROCEDURE ModI (t: INTEGER);
- (* [a b] -> a MOD b (truncation) via temp t. *)
- BEGIN
- StoreTemp(t);
- EmitOp(OPdup);
- LoadTemp(t);
- EmitOp(OPidiv);
- LoadTemp(t);
- EmitOp(OPimul);
- EmitOp(OPsub)
- END ModI;
- PROCEDURE RealAdd;
- BEGIN EmitOp(OPrAdd) END RealAdd;
- PROCEDURE RealSub;
- BEGIN EmitOp(OPrSub) END RealSub;
- PROCEDURE RealMul;
- BEGIN EmitOp(OPrMul) END RealMul;
- PROCEDURE RealDiv;
- BEGIN EmitOp(OPrDiv) END RealDiv;
- PROCEDURE And;
- BEGIN EmitOp(OPand) END And;
- PROCEDURE Or;
- BEGIN EmitOp(OPor) END Or;
- PROCEDURE Not;
- BEGIN EmitOp(OPnot) END Not;
- PROCEDURE Power2;
- BEGIN EmitOp(OPpower2) END Power2;
- PROCEDURE FieldMask;
- BEGIN EmitOp(OPext); EmitOp(04H) END FieldMask;
- PROCEDURE BitIn;
- BEGIN EmitOp(OPbitIn) END BitIn;
- PROCEDURE Eq;
- BEGIN EmitOp(OPeq) END Eq;
- PROCEDURE Neq;
- BEGIN EmitOp(OPne) END Neq;
- PROCEDURE ULt;
- BEGIN EmitOp(OPult) END ULt;
- PROCEDURE ULe;
- BEGIN EmitOp(OPule) END ULe;
- PROCEDURE UGt;
- BEGIN EmitOp(OPugt) END UGt;
- PROCEDURE UGe;
- BEGIN EmitOp(OPuge) END UGe;
- PROCEDURE ILt;
- BEGIN EmitOp(OPilt) END ILt;
- PROCEDURE ILe;
- BEGIN EmitOp(OPile) END ILe;
- PROCEDURE IGt;
- BEGIN EmitOp(OPigt) END IGt;
- PROCEDURE IGe;
- BEGIN EmitOp(OPige) END IGe;
- PROCEDURE RealEq;
- (* [r1 r2] -> (r1 = r2): cmp, or, not. *)
- BEGIN EmitOp(OPrCmp); EmitOp(OPor); EmitOp(OPnot) END RealEq;
- PROCEDURE RealNe;
- (* [r1 r2] -> (r1 # r2): cmp, or. *)
- BEGIN EmitOp(OPrCmp); EmitOp(OPor) END RealNe;
- PROCEDURE RealLt;
- (* [gt lt] -> lt: swap, drop. *)
- BEGIN EmitOp(OPswap); EmitOp(OPext); EmitOp(SUBdrop) END RealLt;
- PROCEDURE RealLe;
- (* [gt lt] -> NOT gt: drop, not. *)
- BEGIN EmitOp(OPext); EmitOp(SUBdrop); EmitOp(OPnot) END RealLe;
- PROCEDURE RealGt;
- (* [gt lt] -> gt: drop. *)
- BEGIN EmitOp(OPext); EmitOp(SUBdrop) END RealGt;
- PROCEDURE RealGe;
- (* [gt lt] -> NOT lt: swap, drop, not. *)
- BEGIN
- EmitOp(OPswap); EmitOp(OPext); EmitOp(SUBdrop); EmitOp(OPnot)
- END RealGe;
- PROCEDURE NegInt;
- BEGIN EmitOp(OPimm0); EmitOp(OPswap); EmitOp(OPsub) END NegInt;
- PROCEDURE NegReal;
- BEGIN
- EmitOp(OPimmW); EmitW64(0H);
- EmitOp(OPswap); EmitOp(OPrSub)
- END NegReal;
- PROCEDURE IntToReal;
- BEGIN EmitOp(OPintToLong); EmitOp(OPlongToReal) END IntToReal;
- PROCEDURE Dup;
- BEGIN EmitOp(OPdup) END Dup;
- PROCEDURE Drop;
- BEGIN EmitOp(OPext); EmitOp(SUBdrop) END Drop;
- (* ---------------- control flow ---------------- *)
- PROCEDURE NewLabel (): INTEGER;
- BEGIN
- IF nLab > MaxLab THEN RETURN 0 END;
- labs[nLab] := -1;
- INC(nLab);
- RETURN VAL(INTEGER, nLab - 1)
- END NewLabel;
- PROCEDURE DefLabel (id: INTEGER);
- VAR i : CARDINAL;
- rel : INTEGER;
- BEGIN
- IF (id < 0) OR (id >= VAL(INTEGER, nLab)) THEN RETURN END;
- labs[id] := VAL(INTEGER, nCode);
- i := 0;
- WHILE i < nFix DO
- IF fixs[i].lab = id THEN
- rel := labs[id] - VAL(INTEGER, fixs[i].pos + 9);
- WriteS64At(fixs[i].pos + 1, rel);
- fixs[i].lab := -1
- END;
- INC(i)
- END
- END DefLabel;
- PROCEDURE Jump (op: CARDINAL; id: INTEGER);
- VAR pos : CARDINAL;
- j : CARDINAL;
- BEGIN
- pos := nCode;
- EmitOp(op);
- IF (id >= 0) & (id < VAL(INTEGER, nLab)) & (labs[id] >= 0) THEN
- EmitS64(labs[id] - VAL(INTEGER, pos + 9))
- ELSE
- FOR j := 0 TO 7 DO EmitByte(0) END;
- IF (nFix <= MaxFix) & (id >= 0) & (id < VAL(INTEGER, nLab)) THEN
- fixs[nFix].pos := pos; fixs[nFix].lab := id; INC(nFix)
- END
- END
- END Jump;
- PROCEDURE Jmp (id: INTEGER);
- BEGIN
- Jump(OPjp, id)
- END Jmp;
- PROCEDURE Jz (id: INTEGER);
- BEGIN
- Jump(OPjz, id)
- END Jz;
- PROCEDURE PushLoop (exit: INTEGER);
- BEGIN
- IF loopTop <= MaxLoop THEN
- loopSt[loopTop] := exit; INC(loopTop)
- END
- END PushLoop;
- PROCEDURE PopLoop;
- BEGIN
- IF loopTop > 0 THEN DEC(loopTop) END
- END PopLoop;
- PROCEDURE TopLoop (VAR exit: INTEGER): BOOLEAN;
- BEGIN
- IF loopTop = 0 THEN RETURN FALSE END;
- exit := loopSt[loopTop - 1];
- RETURN TRUE
- END TopLoop;
- PROCEDURE NoSupEnter;
- BEGIN
- INC(noSup)
- END NoSupEnter;
- PROCEDURE NoSupExit;
- BEGIN
- IF noSup > 0 THEN DEC(noSup) END
- END NoSupExit;
- PROCEDURE NoSup (): BOOLEAN;
- BEGIN
- RETURN noSup > 0
- END NoSup;
- PROCEDURE CopyName (s: ARRAY OF CHAR; VAR d: ARRAY OF CHAR);
- VAR i : CARDINAL;
- BEGIN
- i := 0;
- WHILE (i < HIGH(d)) & (i < HIGH(s)) & (s[i] # 0C) DO
- d[i] := s[i]; INC(i)
- END;
- IF i <= HIGH(d) THEN d[i] := 0C END
- END CopyName;
- PROCEDURE NoEmitEnter;
- BEGIN
- INC(noEmit)
- END NoEmitEnter;
- PROCEDURE NoEmitExit;
- BEGIN
- IF noEmit > 0 THEN DEC(noEmit) END
- END NoEmitExit;
- (* ---------------- image assembly ---------------- *)
- PROCEDURE Put32At (off: CARDINAL; v: CARDINAL);
- BEGIN
- img[off] := CHR(v MOD 256);
- img[off + 1] := CHR((v DIV 256) MOD 256);
- img[off + 2] := CHR((v DIV 65536) MOD 256);
- img[off + 3] := CHR(v DIV 16777216)
- END Put32At;
- PROCEDURE Put64At (off: CARDINAL; v: LONGCARD);
- VAR j : CARDINAL;
- BEGIN
- FOR j := 0 TO 7 DO
- img[off + j] := CHR(VAL(CARDINAL, v MOD 256));
- v := v DIV 256
- END
- END Put64At;
- PROCEDURE EmitPrint;
- (* proc1: prints the CARDINAL parameter as decimal + CRLF.
- Uses global temps 0..3 (buffer, count, index, char). *)
- VAR l1, l2 : INTEGER;
- BEGIN
- EmitOpB(OPenter, 250);
- EmitOpB(OPimmB, 16); EmitOp(0D2H); EmitOpB(OPstoreGlb, 0);
- EmitOp(OPimm0); EmitOp(OPimm0);
- EmitOpB(OPstoreGlb, 1); EmitOpB(OPstoreGlb, 2);
- EmitOp(03H);
- l1 := NewLabel(); DefLabel(l1);
- EmitOpB(OPloadGlb, 1); EmitOp(OPinc); EmitOpB(OPstoreGlb, 1);
- EmitOp(OPdup); EmitOpB(OPimmB, 10); EmitOp(OPumod);
- EmitOp(OPswap); EmitOpB(OPimmB, 10); EmitOp(OPudiv);
- EmitOp(OPdup); EmitOp(OPaeq0);
- Jz(l1);
- EmitOp(OPext); EmitOp(SUBdrop);
- l2 := NewLabel(); DefLabel(l2);
- EmitOpB(OPimmB, 48); EmitOp(OPadd); EmitOpB(OPstoreGlb, 3);
- EmitOpB(OPloadGlb, 0); EmitOpB(OPloadGlb, 2); EmitOp(OPadd);
- EmitOp(OPimm0); EmitOpB(OPloadGlb, 3); EmitOp(1DH);
- EmitOpB(OPloadGlb, 2); EmitOp(OPinc); EmitOpB(OPstoreGlb, 2);
- EmitOpB(OPloadGlb, 1); EmitOp(OPdec); EmitOpB(OPstoreGlb, 1);
- EmitOpB(OPloadGlb, 1); EmitOp(OPaeq0);
- Jz(l2);
- EmitOpB(OPloadGlb, 0); EmitOpB(OPloadGlb, 2); EmitOp(OPadd);
- EmitOp(OPimm0); EmitOp(OPimm0); EmitOp(1DH);
- EmitOpB(OPloadGlb, 0);
- EmitOpB(OPimmB, 1); EmitOp(OPsys);
- EmitOpB(OPimmB, 3); EmitOp(0D2H);
- EmitOp(OPdup); EmitOp(OPimm0); EmitOpB(OPimmB, 13); EmitOp(1DH);
- EmitOp(OPdup); EmitOpB(OPimmB, 1); EmitOpB(OPimmB, 10); EmitOp(1DH);
- EmitOp(OPdup); EmitOpB(OPimmB, 2); EmitOp(OPimm0); EmitOp(1DH);
- EmitOpB(OPimmB, 1); EmitOp(OPsys);
- EmitOpB(OPfctLeave, 0)
- END EmitPrint;
- PROCEDURE EndModule;
- VAR i : CARDINAL;
- codeOff, p1, pt : CARDINAL;
- exitIdx : INTEGER;
- sum : CARDINAL;
- fname : ARRAY [0 .. 127] OF CHAR;
- f : FileIO.File;
- ch : CHAR;
- BEGIN
- (* epilogue: print ExitCode when the convention applies *)
- exitIdx := -1;
- IF SymTab.Lookup("ExitCode")
- & (SymTab.SymKind("ExitCode") = SymTab.KindVar)
- & SymTab.IsIntFamily(SymTab.SymType("ExitCode")) THEN
- exitIdx := FindVar("ExitCode")
- END;
- IF exitIdx >= 0 THEN
- EmitOpB(OPloadGlb, VAL(CARDINAL, exitIdx));
- EmitOpB(OPprocCall, 1);
- EmitOp(OPext); EmitOp(SUBdrop)
- END;
- EmitOp(OPend);
- p1 := nCode;
- EmitPrint;
- (* assemble the image *)
- i := 0;
- WHILE i <= MaxImg DO img[i] := 0C; INC(i) END;
- img[0] := "M"; img[1] := "C"; img[2] := "6"; img[3] := "4";
- i := 0;
- WHILE (i < 16) & (modName[i] # 0C) DO
- img[HeadSize + DName + i] := modName[i]; INC(i)
- END;
- img[HeadSize + DFlags] := CHR(4);
- img[HeadSize + DVarCount] := CHR(nGlb MOD 256);
- img[HeadSize + DDepCount] := 0C;
- codeOff := DVarSizes + nGlb * 8;
- i := 0;
- WHILE i < nCode DO
- img[HeadSize + codeOff + i] := code[i]; INC(i)
- END;
- pt := codeOff + nCode;
- Put64At(HeadSize + DProcs, VAL(LONGCARD, pt));
- Put64At(HeadSize + pt,
- VAL(LONGCARD, codeOff) - VAL(LONGCARD, pt));
- Put64At(HeadSize + pt + 8,
- VAL(LONGCARD, codeOff + p1) - VAL(LONGCARD, pt + 8));
- i := 0;
- WHILE i < nGlb DO
- Put64At(HeadSize + DVarSizes + i * 8, 8H);
- INC(i)
- END;
- sum := 0;
- i := HeadSize;
- WHILE i < HeadSize + pt + 16 DO
- IF ~((i >= 352) & (i <= 355)) THEN
- sum := sum + ORD(img[i])
- END;
- INC(i)
- END;
- Put32At(HeadSize + DChecksum, sum);
- fname[0] := 0C;
- StrCpy(fname, modName);
- i := StrLen(fname);
- fname[i] := "."; fname[i + 1] := "M"; fname[i + 2] := "C";
- fname[i + 3] := "D"; fname[i + 4] := 0C;
- FileIO.Open(f, fname, TRUE);
- IF FileIO.Okay THEN
- i := 0;
- WHILE i < HeadSize + pt + 16 DO
- ch := img[i];
- FileIO.Write(f, ch);
- INC(i)
- END;
- FileIO.Close(f)
- END
- END EndModule;
- BEGIN
- nCode := 0; nGlb := 0; nInit := 0;
- nLab := 0; nFix := 0; loopTop := 0; noSup := 0; noEmit := 0;
- inBody := FALSE;
- modName[0] := 0C
- END MGen.
|