MGen.mod 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. IMPLEMENTATION MODULE MGen;
  2. IMPORT FileIO, SymTab;
  3. CONST
  4. MaxCode = 8191;
  5. MaxImg = 16383;
  6. MaxGlb = 255;
  7. MaxInit = 255;
  8. MaxLab = 255;
  9. MaxFix = 2047;
  10. MaxLoop = 15;
  11. (* opcodes, see mc64-spec.md §11 *)
  12. OPdup = 20H; OPswap = 21H;
  13. OPloadGlb = 2DH; OPstoreGlb = 3DH;
  14. OPext = 40H; SUBdrop = 00H;
  15. OPenter = 0D4H; OPfctLeave = 85H; OPprocCall = 0EDH;
  16. OPimmB = 8DH; OPimmW = 8EH; OPimm0 = 90H;
  17. OPadd = 0A6H; OPsub = 0A7H; OPumul = 0A8H;
  18. OPudiv = 0A9H; OPumod = 0AAH;
  19. OPaeq0 = 0ABH; OPinc = 0ACH; OPdec = 0ADH;
  20. OPeq = 0A0H; OPne = 0A1H;
  21. OPult = 0A2H; OPugt = 0A3H; OPule = 0A4H; OPuge = 0A5H;
  22. OPilt = 0B2H; OPigt = 0B3H; OPile = 0B4H; OPige = 0B5H;
  23. OPnot = 0B6H;
  24. OPimul = 0B8H; OPidiv = 0B9H;
  25. OPintToLong = 0BDH; OPlongToReal = 0BEH;
  26. OPrCmp = 0D5H; OPrAdd = 0D6H; OPrSub = 0D7H;
  27. OPrMul = 0D8H; OPrDiv = 0D9H;
  28. OPor = 0E6H; OPand = 0E8H;
  29. OPpower2 = 0EAH; OPbitIn = 0E7H;
  30. OPjp = 0E0H; OPjz = 0E1H;
  31. OPsys = 0C3H; OPend = 50H;
  32. (* image layout *)
  33. HeadSize = 64;
  34. DName = 264; DChecksum = 288; DFlags = 292;
  35. DVarCount = 293; DDepCount = 294; DProcs = 296;
  36. DVarSizes = 304;
  37. TYPE
  38. FixRec = RECORD
  39. pos : CARDINAL;
  40. lab : INTEGER;
  41. END;
  42. InitRec = RECORD
  43. idx : CARDINAL;
  44. kind : INTEGER; (* 0 = INTEGER value, 1 = raw 64-bit pattern *)
  45. ival : INTEGER;
  46. bits : LONGCARD;
  47. END;
  48. RealView = RECORD CASE : BOOLEAN OF
  49. | TRUE : r : REAL;
  50. | FALSE : w : LONGCARD;
  51. END;
  52. END;
  53. VAR
  54. code : ARRAY [0 .. MaxCode] OF CHAR;
  55. nCode : CARDINAL;
  56. img : ARRAY [0 .. MaxImg] OF CHAR;
  57. modName : ARRAY [0 .. 63] OF CHAR;
  58. gNames : ARRAY [0 .. MaxGlb] OF ARRAY [0 .. 63] OF CHAR;
  59. nGlb : CARDINAL;
  60. inits : ARRAY [0 .. MaxInit] OF InitRec;
  61. nInit : CARDINAL;
  62. inBody : BOOLEAN;
  63. labs : ARRAY [0 .. MaxLab] OF INTEGER;
  64. nLab : CARDINAL;
  65. fixs : ARRAY [0 .. MaxFix] OF FixRec;
  66. nFix : CARDINAL;
  67. loopSt : ARRAY [0 .. MaxLoop] OF INTEGER;
  68. loopTop : CARDINAL;
  69. noSup : CARDINAL;
  70. noEmit : CARDINAL;
  71. (* ---------------- byte helpers ---------------- *)
  72. PROCEDURE StrLen (s: ARRAY OF CHAR): CARDINAL;
  73. VAR i : CARDINAL;
  74. BEGIN
  75. i := 0;
  76. WHILE (i < HIGH(s)) & (s[i] # 0C) DO INC(i) END;
  77. RETURN i
  78. END StrLen;
  79. PROCEDURE StrCpy (VAR d: ARRAY OF CHAR; s: ARRAY OF CHAR);
  80. VAR i : CARDINAL;
  81. BEGIN
  82. i := 0;
  83. WHILE (i < HIGH(d)) & (i < HIGH(s)) & (s[i] # 0C) DO
  84. d[i] := s[i]; INC(i)
  85. END;
  86. IF i <= HIGH(d) THEN d[i] := 0C END
  87. END StrCpy;
  88. PROCEDURE EmitByte (b: CARDINAL);
  89. BEGIN
  90. IF noEmit > 0 THEN RETURN END;
  91. IF nCode <= MaxCode THEN
  92. code[nCode] := CHR(b MOD 256); INC(nCode)
  93. END
  94. END EmitByte;
  95. PROCEDURE EmitOp (o: CARDINAL);
  96. BEGIN
  97. EmitByte(o)
  98. END EmitOp;
  99. PROCEDURE EmitOpB (o, b: CARDINAL);
  100. BEGIN
  101. EmitByte(o); EmitByte(b)
  102. END EmitOpB;
  103. PROCEDURE EmitW64 (v: LONGCARD);
  104. VAR j : CARDINAL;
  105. BEGIN
  106. FOR j := 0 TO 7 DO
  107. EmitByte(VAL(CARDINAL, v MOD 256)); v := v DIV 256
  108. END
  109. END EmitW64;
  110. PROCEDURE EmitS64 (rel: INTEGER);
  111. (* Appends a signed 64-bit little-endian offset. *)
  112. VAR mag : CARDINAL;
  113. BEGIN
  114. IF rel >= 0 THEN EmitW64(VAL(LONGCARD, VAL(CARDINAL, rel)))
  115. ELSE
  116. IF rel = -2147483647 - 1 THEN mag := 80000000H
  117. ELSE mag := VAL(CARDINAL, -rel)
  118. END;
  119. EmitW64(0FFFFFFFFFFFFFFFFH - VAL(LONGCARD, mag) + 1H)
  120. END
  121. END EmitS64;
  122. PROCEDURE WriteS64At (off: CARDINAL; rel: INTEGER);
  123. (* Backpatches a signed offset into already-emitted code. *)
  124. VAR mag : CARDINAL;
  125. bits : LONGCARD;
  126. j : CARDINAL;
  127. BEGIN
  128. IF rel >= 0 THEN bits := VAL(LONGCARD, VAL(CARDINAL, rel))
  129. ELSE
  130. IF rel = -2147483647 - 1 THEN mag := 80000000H
  131. ELSE mag := VAL(CARDINAL, -rel)
  132. END;
  133. bits := 0FFFFFFFFFFFFFFFFH - VAL(LONGCARD, mag) + 1H
  134. END;
  135. FOR j := 0 TO 7 DO
  136. code[off + j] := CHR(VAL(CARDINAL, bits MOD 256));
  137. bits := bits DIV 256
  138. END
  139. END WriteS64At;
  140. PROCEDURE FindVar (name: ARRAY OF CHAR): INTEGER;
  141. VAR i : CARDINAL;
  142. BEGIN
  143. i := 0;
  144. WHILE i < nGlb DO
  145. IF SymTab.Equal(gNames[i], name) THEN RETURN VAL(INTEGER, i) END;
  146. INC(i)
  147. END;
  148. RETURN -1
  149. END FindVar;
  150. PROCEDURE AssignSlot (name: ARRAY OF CHAR): INTEGER;
  151. BEGIN
  152. IF nGlb > MaxGlb THEN RETURN -1 END;
  153. StrCpy(gNames[nGlb], name);
  154. INC(nGlb);
  155. RETURN VAL(INTEGER, nGlb - 1)
  156. END AssignSlot;
  157. (* ---------------- module / data section ---------------- *)
  158. PROCEDURE OpenModule (name: ARRAY OF CHAR);
  159. VAR i : CARDINAL;
  160. dummy : INTEGER;
  161. BEGIN
  162. StrCpy(modName, name);
  163. nCode := 0; nGlb := 0; nInit := 0;
  164. nLab := 0; nFix := 0; loopTop := 0; noSup := 0; noEmit := 0;
  165. inBody := FALSE;
  166. i := 0;
  167. WHILE i <= MaxGlb DO gNames[i][0] := 0C; INC(i) END;
  168. (* slots 0..3 belong to the print helper *)
  169. dummy := AssignSlot(""); dummy := AssignSlot("");
  170. dummy := AssignSlot(""); dummy := AssignSlot("")
  171. END OpenModule;
  172. PROCEDURE DeclVar (name: ARRAY OF CHAR);
  173. VAR idx : INTEGER;
  174. BEGIN
  175. idx := AssignSlot(name);
  176. IF idx < 0 THEN RETURN END
  177. END DeclVar;
  178. PROCEDURE BufInit (idx: INTEGER; kind: INTEGER; ival: INTEGER;
  179. bits: LONGCARD);
  180. BEGIN
  181. IF nInit > MaxInit THEN RETURN END;
  182. inits[nInit].idx := VAL(CARDINAL, idx);
  183. inits[nInit].kind := kind;
  184. inits[nInit].ival := ival;
  185. inits[nInit].bits := bits;
  186. INC(nInit)
  187. END BufInit;
  188. PROCEDURE DeclConst (name: ARRAY OF CHAR; lit: LitStr; t: INTEGER);
  189. VAR idx : INTEGER;
  190. cls : INTEGER;
  191. v : INTEGER;
  192. c : CARDINAL;
  193. b : LONGCARD;
  194. BEGIN
  195. idx := AssignSlot(name);
  196. IF idx < 0 THEN RETURN END;
  197. cls := SymTab.ClassOf(t);
  198. IF ~IsLit(lit) OR (cls = SymTab.ClStr) THEN
  199. BufInit(idx, 0, 0, 0H); RETURN
  200. END;
  201. IF cls = SymTab.ClReal THEN
  202. IF ParseReal(lit, b) THEN BufInit(idx, 1, 0, b)
  203. ELSE BufInit(idx, 1, 0, 0H)
  204. END
  205. ELSIF SymTab.Equal(lit, "TRUE") THEN BufInit(idx, 0, 1, 0H)
  206. ELSIF SymTab.Equal(lit, "FALSE") THEN BufInit(idx, 0, 0, 0H)
  207. ELSIF ParseInt(lit, v) THEN BufInit(idx, 0, v, 0H)
  208. ELSIF ParseCard(lit, c) THEN
  209. BufInit(idx, 1, 0, VAL(LONGCARD, c))
  210. ELSE BufInit(idx, 0, 0, 0H)
  211. END
  212. END DeclConst;
  213. PROCEDURE DeclConstInt (name: ARRAY OF CHAR; v: INTEGER);
  214. VAR idx : INTEGER;
  215. BEGIN
  216. idx := AssignSlot(name);
  217. IF idx < 0 THEN RETURN END;
  218. BufInit(idx, 0, v, 0H)
  219. END DeclConstInt;
  220. PROCEDURE PushValue (kind: INTEGER; ival: INTEGER; bits: LONGCARD);
  221. BEGIN
  222. IF kind = 0 THEN PushInt(ival) ELSE PushBits(bits) END
  223. END PushValue;
  224. PROCEDURE BeginBody;
  225. VAR i : CARDINAL;
  226. BEGIN
  227. IF inBody THEN RETURN END;
  228. inBody := TRUE;
  229. i := 0;
  230. WHILE i < nInit DO
  231. PushValue(inits[i].kind, inits[i].ival, inits[i].bits);
  232. EmitOpB(OPstoreGlb, inits[i].idx);
  233. INC(i)
  234. END
  235. END BeginBody;
  236. (* ---------------- loads, stores, pushes ---------------- *)
  237. PROCEDURE LoadVar (name: ARRAY OF CHAR);
  238. VAR idx : INTEGER;
  239. BEGIN
  240. idx := FindVar(name);
  241. IF idx < 0 THEN EmitOp(OPimm0)
  242. ELSE EmitOpB(OPloadGlb, VAL(CARDINAL, idx))
  243. END
  244. END LoadVar;
  245. PROCEDURE StoreVar (name: ARRAY OF CHAR);
  246. VAR idx : INTEGER;
  247. BEGIN
  248. idx := FindVar(name);
  249. IF idx < 0 THEN EmitOp(OPext); EmitOp(SUBdrop)
  250. ELSE EmitOpB(OPstoreGlb, VAL(CARDINAL, idx))
  251. END
  252. END StoreVar;
  253. PROCEDURE LoadTemp (t: INTEGER);
  254. BEGIN
  255. EmitOpB(OPloadGlb, VAL(CARDINAL, t))
  256. END LoadTemp;
  257. PROCEDURE StoreTemp (t: INTEGER);
  258. BEGIN
  259. EmitOpB(OPstoreGlb, VAL(CARDINAL, t))
  260. END StoreTemp;
  261. PROCEDURE TempGlobal (): INTEGER;
  262. VAR idx : INTEGER;
  263. BEGIN
  264. idx := AssignSlot("");
  265. IF idx < 0 THEN RETURN 4 END;
  266. RETURN idx
  267. END TempGlobal;
  268. PROCEDURE EmitMag (c: CARDINAL);
  269. BEGIN
  270. IF c <= 255 THEN EmitOpB(OPimmB, c)
  271. ELSE EmitOp(OPimmW); EmitW64(VAL(LONGCARD, c))
  272. END
  273. END EmitMag;
  274. PROCEDURE PushInt (v: INTEGER);
  275. VAR mag : CARDINAL;
  276. BEGIN
  277. IF (v >= 0) & (v <= 15) THEN EmitOp(OPimm0 + VAL(CARDINAL, v))
  278. ELSIF v < 0 THEN
  279. IF v = -2147483647 - 1 THEN mag := 80000000H
  280. ELSE mag := VAL(CARDINAL, -v)
  281. END;
  282. EmitOp(OPimm0); EmitMag(mag); EmitOp(OPsub)
  283. ELSE EmitMag(VAL(CARDINAL, v))
  284. END
  285. END PushInt;
  286. PROCEDURE PushBits (b: LONGCARD);
  287. BEGIN
  288. EmitOp(OPimmW); EmitW64(b)
  289. END PushBits;
  290. (* ---------------- literal parsing ---------------- *)
  291. PROCEDURE DigVal (ch: CHAR): INTEGER;
  292. BEGIN
  293. IF (ch >= "0") & (ch <= "9") THEN RETURN ORD(ch) - ORD("0") END;
  294. IF (ch >= "A") & (ch <= "F") THEN RETURN ORD(ch) - ORD("A") + 10 END;
  295. IF (ch >= "a") & (ch <= "f") THEN RETURN ORD(ch) - ORD("a") + 10 END;
  296. RETURN -1
  297. END DigVal;
  298. PROCEDURE ParseCard (s: ARRAY OF CHAR; VAR v: CARDINAL): BOOLEAN;
  299. VAR i, n : CARDINAL;
  300. hex : BOOLEAN;
  301. d : INTEGER;
  302. acc : LONGCARD;
  303. BEGIN
  304. v := 0;
  305. n := StrLen(s);
  306. IF n = 0 THEN RETURN FALSE END;
  307. hex := (s[n - 1] = "H") OR (s[n - 1] = "h");
  308. IF hex THEN DEC(n) END;
  309. IF n = 0 THEN RETURN FALSE END;
  310. acc := 0H; i := 0;
  311. WHILE i < n DO
  312. d := DigVal(s[i]);
  313. IF hex THEN
  314. IF d < 0 THEN RETURN FALSE END;
  315. acc := acc * 16 + VAL(LONGCARD, VAL(CARDINAL, d))
  316. ELSE
  317. IF (d < 0) OR (d > 9) THEN RETURN FALSE END;
  318. acc := acc * 10 + VAL(LONGCARD, VAL(CARDINAL, d))
  319. END;
  320. IF acc > 0FFFFFFFFH THEN RETURN FALSE END;
  321. INC(i)
  322. END;
  323. v := VAL(CARDINAL, acc);
  324. RETURN TRUE
  325. END ParseCard;
  326. PROCEDURE ParseInt (s: ARRAY OF CHAR; VAR v: INTEGER): BOOLEAN;
  327. VAR i : CARDINAL;
  328. neg : BOOLEAN;
  329. t : ARRAY [0 .. 63] OF CHAR;
  330. c : CARDINAL;
  331. lim : LONGCARD;
  332. BEGIN
  333. v := 0;
  334. IF (StrLen(s) = 0) THEN RETURN FALSE END;
  335. neg := s[0] = "-";
  336. IF neg THEN
  337. i := 1;
  338. WHILE s[i] # 0C DO
  339. IF i - 1 > HIGH(t) THEN RETURN FALSE END;
  340. t[i - 1] := s[i]; INC(i)
  341. END;
  342. IF i - 1 > HIGH(t) THEN RETURN FALSE END;
  343. t[i - 1] := 0C
  344. ELSE StrCpy(t, s)
  345. END;
  346. IF ~ParseCard(t, c) THEN RETURN FALSE END;
  347. IF neg THEN lim := 80000000H ELSE lim := 7FFFFFFFH END;
  348. IF VAL(LONGCARD, c) > lim THEN RETURN FALSE END;
  349. IF neg THEN
  350. IF VAL(LONGCARD, c) = 80000000H THEN v := -2147483647 - 1
  351. ELSE v := -VAL(INTEGER, c)
  352. END
  353. ELSE v := VAL(INTEGER, c)
  354. END;
  355. RETURN TRUE
  356. END ParseInt;
  357. PROCEDURE ParseReal (s: ARRAY OF CHAR; VAR b: LONGCARD): BOOLEAN;
  358. VAR i : CARDINAL;
  359. neg, esign : BOOLEAN;
  360. m, scale : REAL;
  361. e, d : CARDINAL;
  362. rv : RealView;
  363. BEGIN
  364. b := 0H;
  365. i := 0; neg := FALSE;
  366. IF s[0] = "-" THEN neg := TRUE; INC(i) END;
  367. IF (s[i] < "0") OR (s[i] > "9") THEN RETURN FALSE END;
  368. m := 0.0;
  369. WHILE (s[i] >= "0") & (s[i] <= "9") DO
  370. m := m * 10.0 + VAL(REAL, VAL(CARDINAL, ORD(s[i]) - ORD("0")));
  371. INC(i)
  372. END;
  373. IF s[i] = "." THEN
  374. INC(i);
  375. IF (s[i] < "0") OR (s[i] > "9") THEN RETURN FALSE END;
  376. scale := 10.0;
  377. WHILE (s[i] >= "0") & (s[i] <= "9") DO
  378. m := m + VAL(REAL, VAL(CARDINAL, ORD(s[i]) - ORD("0"))) / scale;
  379. scale := scale * 10.0;
  380. INC(i)
  381. END
  382. END;
  383. IF (s[i] = "E") OR (s[i] = "e") THEN
  384. INC(i); esign := FALSE;
  385. IF s[i] = "+" THEN INC(i)
  386. ELSIF s[i] = "-" THEN esign := TRUE; INC(i)
  387. END;
  388. IF (s[i] < "0") OR (s[i] > "9") THEN RETURN FALSE END;
  389. e := 0;
  390. WHILE (s[i] >= "0") & (s[i] <= "9") DO
  391. d := VAL(CARDINAL, ORD(s[i]) - ORD("0"));
  392. IF e <= 9999 THEN e := e * 10 + d END;
  393. INC(i)
  394. END;
  395. WHILE e > 0 DO
  396. IF esign THEN m := m / 10.0 ELSE m := m * 10.0 END;
  397. DEC(e)
  398. END
  399. END;
  400. IF s[i] # 0C THEN RETURN FALSE END;
  401. IF neg THEN m := -m END;
  402. rv.r := m;
  403. b := rv.w;
  404. RETURN TRUE
  405. END ParseReal;
  406. PROCEDURE CharOrd (s: ARRAY OF CHAR): INTEGER;
  407. BEGIN
  408. IF StrLen(s) >= 2 THEN RETURN ORD(s[1]) END;
  409. RETURN 0
  410. END CharOrd;
  411. PROCEDURE NegFold (a: ARRAY OF CHAR; VAR q: LitStr);
  412. (* Safe for a and q being the same variable. *)
  413. VAR tmp : LitStr;
  414. i, j : CARDINAL;
  415. BEGIN
  416. StrCpy(tmp, a);
  417. IF StrLen(tmp) = 0 THEN StrCpy(q, ""); RETURN END;
  418. IF tmp[0] = "-" THEN
  419. i := 1; j := 0;
  420. WHILE (tmp[i] # 0C) & (j < HIGH(q)) DO
  421. q[j] := tmp[i]; INC(i); INC(j)
  422. END;
  423. IF j <= HIGH(q) THEN q[j] := 0C END
  424. ELSE
  425. StrCpy(q, "-");
  426. i := 0; j := StrLen(q);
  427. WHILE (tmp[i] # 0C) & (j < HIGH(q)) DO
  428. q[j] := tmp[i]; INC(i); INC(j)
  429. END;
  430. IF j <= HIGH(q) THEN q[j] := 0C END
  431. END
  432. END NegFold;
  433. PROCEDURE IsLit (s: ARRAY OF CHAR): BOOLEAN;
  434. BEGIN
  435. RETURN StrLen(s) > 0
  436. END IsLit;
  437. (* ---------------- operators ---------------- *)
  438. PROCEDURE Add;
  439. BEGIN EmitOp(OPadd) END Add;
  440. PROCEDURE Sub;
  441. BEGIN EmitOp(OPsub) END Sub;
  442. PROCEDURE MulU;
  443. BEGIN EmitOp(OPumul) END MulU;
  444. PROCEDURE DivU;
  445. BEGIN EmitOp(OPudiv) END DivU;
  446. PROCEDURE ModU;
  447. BEGIN EmitOp(OPumod) END ModU;
  448. PROCEDURE MulI;
  449. BEGIN EmitOp(OPimul) END MulI;
  450. PROCEDURE DivI;
  451. BEGIN EmitOp(OPidiv) END DivI;
  452. PROCEDURE ModI (t: INTEGER);
  453. (* [a b] -> a MOD b (truncation) via temp t. *)
  454. BEGIN
  455. StoreTemp(t);
  456. EmitOp(OPdup);
  457. LoadTemp(t);
  458. EmitOp(OPidiv);
  459. LoadTemp(t);
  460. EmitOp(OPimul);
  461. EmitOp(OPsub)
  462. END ModI;
  463. PROCEDURE RealAdd;
  464. BEGIN EmitOp(OPrAdd) END RealAdd;
  465. PROCEDURE RealSub;
  466. BEGIN EmitOp(OPrSub) END RealSub;
  467. PROCEDURE RealMul;
  468. BEGIN EmitOp(OPrMul) END RealMul;
  469. PROCEDURE RealDiv;
  470. BEGIN EmitOp(OPrDiv) END RealDiv;
  471. PROCEDURE And;
  472. BEGIN EmitOp(OPand) END And;
  473. PROCEDURE Or;
  474. BEGIN EmitOp(OPor) END Or;
  475. PROCEDURE Not;
  476. BEGIN EmitOp(OPnot) END Not;
  477. PROCEDURE Power2;
  478. BEGIN EmitOp(OPpower2) END Power2;
  479. PROCEDURE FieldMask;
  480. BEGIN EmitOp(OPext); EmitOp(04H) END FieldMask;
  481. PROCEDURE BitIn;
  482. BEGIN EmitOp(OPbitIn) END BitIn;
  483. PROCEDURE Eq;
  484. BEGIN EmitOp(OPeq) END Eq;
  485. PROCEDURE Neq;
  486. BEGIN EmitOp(OPne) END Neq;
  487. PROCEDURE ULt;
  488. BEGIN EmitOp(OPult) END ULt;
  489. PROCEDURE ULe;
  490. BEGIN EmitOp(OPule) END ULe;
  491. PROCEDURE UGt;
  492. BEGIN EmitOp(OPugt) END UGt;
  493. PROCEDURE UGe;
  494. BEGIN EmitOp(OPuge) END UGe;
  495. PROCEDURE ILt;
  496. BEGIN EmitOp(OPilt) END ILt;
  497. PROCEDURE ILe;
  498. BEGIN EmitOp(OPile) END ILe;
  499. PROCEDURE IGt;
  500. BEGIN EmitOp(OPigt) END IGt;
  501. PROCEDURE IGe;
  502. BEGIN EmitOp(OPige) END IGe;
  503. PROCEDURE RealEq;
  504. (* [r1 r2] -> (r1 = r2): cmp, or, not. *)
  505. BEGIN EmitOp(OPrCmp); EmitOp(OPor); EmitOp(OPnot) END RealEq;
  506. PROCEDURE RealNe;
  507. (* [r1 r2] -> (r1 # r2): cmp, or. *)
  508. BEGIN EmitOp(OPrCmp); EmitOp(OPor) END RealNe;
  509. PROCEDURE RealLt;
  510. (* [gt lt] -> lt: swap, drop. *)
  511. BEGIN EmitOp(OPswap); EmitOp(OPext); EmitOp(SUBdrop) END RealLt;
  512. PROCEDURE RealLe;
  513. (* [gt lt] -> NOT gt: drop, not. *)
  514. BEGIN EmitOp(OPext); EmitOp(SUBdrop); EmitOp(OPnot) END RealLe;
  515. PROCEDURE RealGt;
  516. (* [gt lt] -> gt: drop. *)
  517. BEGIN EmitOp(OPext); EmitOp(SUBdrop) END RealGt;
  518. PROCEDURE RealGe;
  519. (* [gt lt] -> NOT lt: swap, drop, not. *)
  520. BEGIN
  521. EmitOp(OPswap); EmitOp(OPext); EmitOp(SUBdrop); EmitOp(OPnot)
  522. END RealGe;
  523. PROCEDURE NegInt;
  524. BEGIN EmitOp(OPimm0); EmitOp(OPswap); EmitOp(OPsub) END NegInt;
  525. PROCEDURE NegReal;
  526. BEGIN
  527. EmitOp(OPimmW); EmitW64(0H);
  528. EmitOp(OPswap); EmitOp(OPrSub)
  529. END NegReal;
  530. PROCEDURE IntToReal;
  531. BEGIN EmitOp(OPintToLong); EmitOp(OPlongToReal) END IntToReal;
  532. PROCEDURE Dup;
  533. BEGIN EmitOp(OPdup) END Dup;
  534. PROCEDURE Drop;
  535. BEGIN EmitOp(OPext); EmitOp(SUBdrop) END Drop;
  536. (* ---------------- control flow ---------------- *)
  537. PROCEDURE NewLabel (): INTEGER;
  538. BEGIN
  539. IF nLab > MaxLab THEN RETURN 0 END;
  540. labs[nLab] := -1;
  541. INC(nLab);
  542. RETURN VAL(INTEGER, nLab - 1)
  543. END NewLabel;
  544. PROCEDURE DefLabel (id: INTEGER);
  545. VAR i : CARDINAL;
  546. rel : INTEGER;
  547. BEGIN
  548. IF (id < 0) OR (id >= VAL(INTEGER, nLab)) THEN RETURN END;
  549. labs[id] := VAL(INTEGER, nCode);
  550. i := 0;
  551. WHILE i < nFix DO
  552. IF fixs[i].lab = id THEN
  553. rel := labs[id] - VAL(INTEGER, fixs[i].pos + 9);
  554. WriteS64At(fixs[i].pos + 1, rel);
  555. fixs[i].lab := -1
  556. END;
  557. INC(i)
  558. END
  559. END DefLabel;
  560. PROCEDURE Jump (op: CARDINAL; id: INTEGER);
  561. VAR pos : CARDINAL;
  562. j : CARDINAL;
  563. BEGIN
  564. pos := nCode;
  565. EmitOp(op);
  566. IF (id >= 0) & (id < VAL(INTEGER, nLab)) & (labs[id] >= 0) THEN
  567. EmitS64(labs[id] - VAL(INTEGER, pos + 9))
  568. ELSE
  569. FOR j := 0 TO 7 DO EmitByte(0) END;
  570. IF (nFix <= MaxFix) & (id >= 0) & (id < VAL(INTEGER, nLab)) THEN
  571. fixs[nFix].pos := pos; fixs[nFix].lab := id; INC(nFix)
  572. END
  573. END
  574. END Jump;
  575. PROCEDURE Jmp (id: INTEGER);
  576. BEGIN
  577. Jump(OPjp, id)
  578. END Jmp;
  579. PROCEDURE Jz (id: INTEGER);
  580. BEGIN
  581. Jump(OPjz, id)
  582. END Jz;
  583. PROCEDURE PushLoop (exit: INTEGER);
  584. BEGIN
  585. IF loopTop <= MaxLoop THEN
  586. loopSt[loopTop] := exit; INC(loopTop)
  587. END
  588. END PushLoop;
  589. PROCEDURE PopLoop;
  590. BEGIN
  591. IF loopTop > 0 THEN DEC(loopTop) END
  592. END PopLoop;
  593. PROCEDURE TopLoop (VAR exit: INTEGER): BOOLEAN;
  594. BEGIN
  595. IF loopTop = 0 THEN RETURN FALSE END;
  596. exit := loopSt[loopTop - 1];
  597. RETURN TRUE
  598. END TopLoop;
  599. PROCEDURE NoSupEnter;
  600. BEGIN
  601. INC(noSup)
  602. END NoSupEnter;
  603. PROCEDURE NoSupExit;
  604. BEGIN
  605. IF noSup > 0 THEN DEC(noSup) END
  606. END NoSupExit;
  607. PROCEDURE NoSup (): BOOLEAN;
  608. BEGIN
  609. RETURN noSup > 0
  610. END NoSup;
  611. PROCEDURE CopyName (s: ARRAY OF CHAR; VAR d: ARRAY OF CHAR);
  612. VAR i : CARDINAL;
  613. BEGIN
  614. i := 0;
  615. WHILE (i < HIGH(d)) & (i < HIGH(s)) & (s[i] # 0C) DO
  616. d[i] := s[i]; INC(i)
  617. END;
  618. IF i <= HIGH(d) THEN d[i] := 0C END
  619. END CopyName;
  620. PROCEDURE NoEmitEnter;
  621. BEGIN
  622. INC(noEmit)
  623. END NoEmitEnter;
  624. PROCEDURE NoEmitExit;
  625. BEGIN
  626. IF noEmit > 0 THEN DEC(noEmit) END
  627. END NoEmitExit;
  628. (* ---------------- image assembly ---------------- *)
  629. PROCEDURE Put32At (off: CARDINAL; v: CARDINAL);
  630. BEGIN
  631. img[off] := CHR(v MOD 256);
  632. img[off + 1] := CHR((v DIV 256) MOD 256);
  633. img[off + 2] := CHR((v DIV 65536) MOD 256);
  634. img[off + 3] := CHR(v DIV 16777216)
  635. END Put32At;
  636. PROCEDURE Put64At (off: CARDINAL; v: LONGCARD);
  637. VAR j : CARDINAL;
  638. BEGIN
  639. FOR j := 0 TO 7 DO
  640. img[off + j] := CHR(VAL(CARDINAL, v MOD 256));
  641. v := v DIV 256
  642. END
  643. END Put64At;
  644. PROCEDURE EmitPrint;
  645. (* proc1: prints the CARDINAL parameter as decimal + CRLF.
  646. Uses global temps 0..3 (buffer, count, index, char). *)
  647. VAR l1, l2 : INTEGER;
  648. BEGIN
  649. EmitOpB(OPenter, 250);
  650. EmitOpB(OPimmB, 16); EmitOp(0D2H); EmitOpB(OPstoreGlb, 0);
  651. EmitOp(OPimm0); EmitOp(OPimm0);
  652. EmitOpB(OPstoreGlb, 1); EmitOpB(OPstoreGlb, 2);
  653. EmitOp(03H);
  654. l1 := NewLabel(); DefLabel(l1);
  655. EmitOpB(OPloadGlb, 1); EmitOp(OPinc); EmitOpB(OPstoreGlb, 1);
  656. EmitOp(OPdup); EmitOpB(OPimmB, 10); EmitOp(OPumod);
  657. EmitOp(OPswap); EmitOpB(OPimmB, 10); EmitOp(OPudiv);
  658. EmitOp(OPdup); EmitOp(OPaeq0);
  659. Jz(l1);
  660. EmitOp(OPext); EmitOp(SUBdrop);
  661. l2 := NewLabel(); DefLabel(l2);
  662. EmitOpB(OPimmB, 48); EmitOp(OPadd); EmitOpB(OPstoreGlb, 3);
  663. EmitOpB(OPloadGlb, 0); EmitOpB(OPloadGlb, 2); EmitOp(OPadd);
  664. EmitOp(OPimm0); EmitOpB(OPloadGlb, 3); EmitOp(1DH);
  665. EmitOpB(OPloadGlb, 2); EmitOp(OPinc); EmitOpB(OPstoreGlb, 2);
  666. EmitOpB(OPloadGlb, 1); EmitOp(OPdec); EmitOpB(OPstoreGlb, 1);
  667. EmitOpB(OPloadGlb, 1); EmitOp(OPaeq0);
  668. Jz(l2);
  669. EmitOpB(OPloadGlb, 0); EmitOpB(OPloadGlb, 2); EmitOp(OPadd);
  670. EmitOp(OPimm0); EmitOp(OPimm0); EmitOp(1DH);
  671. EmitOpB(OPloadGlb, 0);
  672. EmitOpB(OPimmB, 1); EmitOp(OPsys);
  673. EmitOpB(OPimmB, 3); EmitOp(0D2H);
  674. EmitOp(OPdup); EmitOp(OPimm0); EmitOpB(OPimmB, 13); EmitOp(1DH);
  675. EmitOp(OPdup); EmitOpB(OPimmB, 1); EmitOpB(OPimmB, 10); EmitOp(1DH);
  676. EmitOp(OPdup); EmitOpB(OPimmB, 2); EmitOp(OPimm0); EmitOp(1DH);
  677. EmitOpB(OPimmB, 1); EmitOp(OPsys);
  678. EmitOpB(OPfctLeave, 0)
  679. END EmitPrint;
  680. PROCEDURE EndModule;
  681. VAR i : CARDINAL;
  682. codeOff, p1, pt : CARDINAL;
  683. exitIdx : INTEGER;
  684. sum : CARDINAL;
  685. fname : ARRAY [0 .. 127] OF CHAR;
  686. f : FileIO.File;
  687. ch : CHAR;
  688. BEGIN
  689. (* epilogue: print ExitCode when the convention applies *)
  690. exitIdx := -1;
  691. IF SymTab.Lookup("ExitCode")
  692. & (SymTab.SymKind("ExitCode") = SymTab.KindVar)
  693. & SymTab.IsIntFamily(SymTab.SymType("ExitCode")) THEN
  694. exitIdx := FindVar("ExitCode")
  695. END;
  696. IF exitIdx >= 0 THEN
  697. EmitOpB(OPloadGlb, VAL(CARDINAL, exitIdx));
  698. EmitOpB(OPprocCall, 1);
  699. EmitOp(OPext); EmitOp(SUBdrop)
  700. END;
  701. EmitOp(OPend);
  702. p1 := nCode;
  703. EmitPrint;
  704. (* assemble the image *)
  705. i := 0;
  706. WHILE i <= MaxImg DO img[i] := 0C; INC(i) END;
  707. img[0] := "M"; img[1] := "C"; img[2] := "6"; img[3] := "4";
  708. i := 0;
  709. WHILE (i < 16) & (modName[i] # 0C) DO
  710. img[HeadSize + DName + i] := modName[i]; INC(i)
  711. END;
  712. img[HeadSize + DFlags] := CHR(4);
  713. img[HeadSize + DVarCount] := CHR(nGlb MOD 256);
  714. img[HeadSize + DDepCount] := 0C;
  715. codeOff := DVarSizes + nGlb * 8;
  716. i := 0;
  717. WHILE i < nCode DO
  718. img[HeadSize + codeOff + i] := code[i]; INC(i)
  719. END;
  720. pt := codeOff + nCode;
  721. Put64At(HeadSize + DProcs, VAL(LONGCARD, pt));
  722. Put64At(HeadSize + pt,
  723. VAL(LONGCARD, codeOff) - VAL(LONGCARD, pt));
  724. Put64At(HeadSize + pt + 8,
  725. VAL(LONGCARD, codeOff + p1) - VAL(LONGCARD, pt + 8));
  726. i := 0;
  727. WHILE i < nGlb DO
  728. Put64At(HeadSize + DVarSizes + i * 8, 8H);
  729. INC(i)
  730. END;
  731. sum := 0;
  732. i := HeadSize;
  733. WHILE i < HeadSize + pt + 16 DO
  734. IF ~((i >= 352) & (i <= 355)) THEN
  735. sum := sum + ORD(img[i])
  736. END;
  737. INC(i)
  738. END;
  739. Put32At(HeadSize + DChecksum, sum);
  740. fname[0] := 0C;
  741. StrCpy(fname, modName);
  742. i := StrLen(fname);
  743. fname[i] := "."; fname[i + 1] := "M"; fname[i + 2] := "C";
  744. fname[i + 3] := "4"; fname[i + 4] := 0C;
  745. FileIO.Open(f, fname, TRUE);
  746. IF FileIO.Okay THEN
  747. i := 0;
  748. WHILE i < HeadSize + pt + 16 DO
  749. ch := img[i];
  750. FileIO.Write(f, ch);
  751. INC(i)
  752. END;
  753. FileIO.Close(f)
  754. END
  755. END EndModule;
  756. BEGIN
  757. nCode := 0; nGlb := 0; nInit := 0;
  758. nLab := 0; nFix := 0; loopTop := 0; noSup := 0; noEmit := 0;
  759. inBody := FALSE;
  760. modName[0] := 0C
  761. END MGen.