MGen.mod 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363
  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. MaxActDepth = 7;
  12. MaxActN = 63;
  13. (* opcodes, see mc64-spec.md §11 *)
  14. OPdup = 20H; OPswap = 21H;
  15. OPloadGlb = 2DH; OPstoreGlb = 3DH;
  16. OPloadLocal = 2CH; OPstoreLocal = 3CH;
  17. OPloadStk = 2EH;
  18. OPloadIndir0 = 60H; OPstoreIndir0 = 70H;
  19. OPloadOuterN = 11H;
  20. OPloadIndir = 41H; OPstoreIndir = 51H;
  21. OPlocalAddr = 80H; OPglobalAddr = 81H; OPstkAddr = 82H;
  22. OPext = 40H; SUBdrop = 00H;
  23. OPenter = 0D4H; OPprocLeave = 84H; OPfctLeave = 85H;
  24. OPprocCall = 0EDH; OPnestedCall = 0ECH; OPcallFrame = 0EEH;
  25. OPimmB = 8DH; OPimmW = 8EH; OPimm0 = 90H;
  26. OPadd = 0A6H; OPsub = 0A7H; OPumul = 0A8H;
  27. OPudiv = 0A9H; OPumod = 0AAH;
  28. OPaeq0 = 0ABH; OPinc = 0ACH; OPdec = 0ADH;
  29. OPeq = 0A0H; OPne = 0A1H;
  30. OPult = 0A2H; OPugt = 0A3H; OPule = 0A4H; OPuge = 0A5H;
  31. OPilt = 0B2H; OPigt = 0B3H; OPile = 0B4H; OPige = 0B5H;
  32. OPnot = 0B6H;
  33. OPimul = 0B8H; OPidiv = 0B9H;
  34. OPintToLong = 0BDH; OPlongToReal = 0BEH;
  35. OPrCmp = 0D5H; OPrAdd = 0D6H; OPrSub = 0D7H;
  36. OPrMul = 0D8H; OPrDiv = 0D9H;
  37. OPor = 0E6H; OPand = 0E8H;
  38. OPpower2 = 0EAH; OPbitIn = 0E7H;
  39. OPjp = 0E0H; OPjz = 0E1H;
  40. OPsys = 0C3H; OPend = 50H;
  41. (* image layout *)
  42. HeadSize = 64;
  43. DName = 264; DChecksum = 288; DFlags = 292;
  44. DVarCount = 293; DDepCount = 294; DProcs = 296;
  45. DVarSizes = 304;
  46. TYPE
  47. FixRec = RECORD
  48. pos : CARDINAL;
  49. lab : INTEGER;
  50. END;
  51. InitRec = RECORD
  52. idx : CARDINAL;
  53. kind : INTEGER; (* 0 = INTEGER value, 1 = raw 64-bit pattern *)
  54. ival : INTEGER;
  55. bits : LONGCARD;
  56. END;
  57. RealView = RECORD CASE : BOOLEAN OF
  58. | TRUE : r : REAL;
  59. | FALSE : w : LONGCARD;
  60. END;
  61. END;
  62. ActFrame = RECORD
  63. n : CARDINAL;
  64. tmps : ARRAY [0 .. MaxActN] OF INTEGER;
  65. known : BOOLEAN;
  66. nf : CARDINAL;
  67. pn : ARRAY [0 .. 63] OF CHAR;
  68. END;
  69. VAR
  70. code : ARRAY [0 .. MaxCode] OF CHAR;
  71. nCode : CARDINAL;
  72. img : ARRAY [0 .. MaxImg] OF CHAR;
  73. modName : ARRAY [0 .. 63] OF CHAR;
  74. gNames : ARRAY [0 .. MaxGlb] OF ARRAY [0 .. 63] OF CHAR;
  75. vBase : ARRAY [0 .. MaxGlb] OF CARDINAL;
  76. vSize : ARRAY [0 .. MaxGlb] OF CARDINAL;
  77. nVars : CARDINAL;
  78. nGlb : CARDINAL;
  79. inits : ARRAY [0 .. MaxInit] OF InitRec;
  80. nInit : CARDINAL;
  81. inBody : BOOLEAN;
  82. labs : ARRAY [0 .. MaxLab] OF INTEGER;
  83. nLab : CARDINAL;
  84. fixs : ARRAY [0 .. MaxFix] OF FixRec;
  85. nFix : CARDINAL;
  86. loopSt : ARRAY [0 .. MaxLoop] OF INTEGER;
  87. loopTop : CARDINAL;
  88. noSup : CARDINAL;
  89. noEmit : CARDINAL;
  90. actSt : ARRAY [0 .. MaxActDepth] OF ActFrame;
  91. actTop : CARDINAL;
  92. withTmps : ARRAY [0 .. 7] OF INTEGER;
  93. withTyps : ARRAY [0 .. 7] OF INTEGER;
  94. withTop : CARDINAL;
  95. procAddr : ARRAY [0 .. 64] OF INTEGER;
  96. maxNum : CARDINAL;
  97. mainAddr : CARDINAL;
  98. (* ---------------- byte helpers ---------------- *)
  99. PROCEDURE StrLen (s: ARRAY OF CHAR): CARDINAL;
  100. VAR i : CARDINAL;
  101. BEGIN
  102. i := 0;
  103. WHILE (i < HIGH(s)) & (s[i] # 0C) DO INC(i) END;
  104. RETURN i
  105. END StrLen;
  106. PROCEDURE StrCpy (VAR d: ARRAY OF CHAR; s: ARRAY OF CHAR);
  107. VAR i : CARDINAL;
  108. BEGIN
  109. i := 0;
  110. WHILE (i < HIGH(d)) & (i < HIGH(s)) & (s[i] # 0C) DO
  111. d[i] := s[i]; INC(i)
  112. END;
  113. IF i <= HIGH(d) THEN d[i] := 0C END
  114. END StrCpy;
  115. PROCEDURE EmitByte (b: CARDINAL);
  116. BEGIN
  117. IF noEmit > 0 THEN RETURN END;
  118. IF nCode <= MaxCode THEN
  119. code[nCode] := CHR(b MOD 256); INC(nCode)
  120. END
  121. END EmitByte;
  122. PROCEDURE EmitOp (o: CARDINAL);
  123. BEGIN
  124. EmitByte(o)
  125. END EmitOp;
  126. PROCEDURE EmitOpB (o, b: CARDINAL);
  127. BEGIN
  128. EmitByte(o); EmitByte(b)
  129. END EmitOpB;
  130. PROCEDURE EmitW64 (v: LONGCARD);
  131. VAR j : CARDINAL;
  132. BEGIN
  133. FOR j := 0 TO 7 DO
  134. EmitByte(VAL(CARDINAL, v MOD 256)); v := v DIV 256
  135. END
  136. END EmitW64;
  137. PROCEDURE EmitS64 (rel: INTEGER);
  138. (* Appends a signed 64-bit little-endian offset. *)
  139. VAR mag : CARDINAL;
  140. BEGIN
  141. IF rel >= 0 THEN EmitW64(VAL(LONGCARD, VAL(CARDINAL, rel)))
  142. ELSE
  143. IF rel = -2147483647 - 1 THEN mag := 80000000H
  144. ELSE mag := VAL(CARDINAL, -rel)
  145. END;
  146. EmitW64(0FFFFFFFFFFFFFFFFH - VAL(LONGCARD, mag) + 1H)
  147. END
  148. END EmitS64;
  149. PROCEDURE WriteS64At (off: CARDINAL; rel: INTEGER);
  150. (* Backpatches a signed offset into already-emitted code. *)
  151. VAR mag : CARDINAL;
  152. bits : LONGCARD;
  153. j : CARDINAL;
  154. BEGIN
  155. IF rel >= 0 THEN bits := VAL(LONGCARD, VAL(CARDINAL, rel))
  156. ELSE
  157. IF rel = -2147483647 - 1 THEN mag := 80000000H
  158. ELSE mag := VAL(CARDINAL, -rel)
  159. END;
  160. bits := 0FFFFFFFFFFFFFFFFH - VAL(LONGCARD, mag) + 1H
  161. END;
  162. FOR j := 0 TO 7 DO
  163. code[off + j] := CHR(VAL(CARDINAL, bits MOD 256));
  164. bits := bits DIV 256
  165. END
  166. END WriteS64At;
  167. PROCEDURE FindVar (name: ARRAY OF CHAR): INTEGER;
  168. VAR i : CARDINAL;
  169. BEGIN
  170. i := 0;
  171. WHILE i < nVars DO
  172. IF SymTab.Equal(gNames[i], name) THEN
  173. RETURN VAL(INTEGER, vBase[i])
  174. END;
  175. INC(i)
  176. END;
  177. RETURN -1
  178. END FindVar;
  179. PROCEDURE AssignSlots (name: ARRAY OF CHAR; n: CARDINAL): INTEGER;
  180. VAR base : CARDINAL;
  181. BEGIN
  182. IF nVars > MaxGlb THEN RETURN -1 END;
  183. IF n = 0 THEN
  184. StrCpy(gNames[nVars], name);
  185. vBase[nVars] := nGlb;
  186. vSize[nVars] := 0;
  187. INC(nVars);
  188. RETURN VAL(INTEGER, nGlb)
  189. END;
  190. IF nGlb + n - 1 > MaxGlb THEN RETURN -1 END;
  191. StrCpy(gNames[nVars], name);
  192. base := nGlb;
  193. vBase[nVars] := base;
  194. vSize[nVars] := n;
  195. INC(nVars);
  196. nGlb := nGlb + n;
  197. RETURN VAL(INTEGER, base)
  198. END AssignSlots;
  199. PROCEDURE AssignSlot (name: ARRAY OF CHAR): INTEGER;
  200. BEGIN
  201. RETURN AssignSlots(name, 1)
  202. END AssignSlot;
  203. (* ---------------- module / data section ---------------- *)
  204. PROCEDURE OpenModule (name: ARRAY OF CHAR);
  205. VAR i : CARDINAL;
  206. dummy : INTEGER;
  207. BEGIN
  208. StrCpy(modName, name);
  209. nCode := 0; nGlb := 0; nVars := 0; nInit := 0;
  210. nLab := 0; nFix := 0; loopTop := 0; noSup := 0; noEmit := 0;
  211. actTop := 0; withTop := 0;
  212. maxNum := 0; mainAddr := 0;
  213. i := 0;
  214. WHILE i <= 64 DO procAddr[i] := -1; INC(i) END;
  215. inBody := FALSE;
  216. i := 0;
  217. WHILE i <= MaxGlb DO gNames[i][0] := 0C; INC(i) END;
  218. (* slots 0..3 belong to the print helper *)
  219. dummy := AssignSlot(""); dummy := AssignSlot("");
  220. dummy := AssignSlot(""); dummy := AssignSlot("")
  221. END OpenModule;
  222. PROCEDURE DeclVar (name: ARRAY OF CHAR);
  223. VAR idx : INTEGER;
  224. BEGIN
  225. idx := AssignSlot(name);
  226. IF idx < 0 THEN RETURN END
  227. END DeclVar;
  228. PROCEDURE DeclVarSized (name: ARRAY OF CHAR; slots: CARDINAL);
  229. VAR idx : INTEGER;
  230. BEGIN
  231. idx := AssignSlots(name, slots);
  232. IF idx < 0 THEN RETURN END
  233. END DeclVarSized;
  234. PROCEDURE BufInit (idx: INTEGER; kind: INTEGER; ival: INTEGER;
  235. bits: LONGCARD);
  236. BEGIN
  237. IF nInit > MaxInit THEN RETURN END;
  238. inits[nInit].idx := VAL(CARDINAL, idx);
  239. inits[nInit].kind := kind;
  240. inits[nInit].ival := ival;
  241. inits[nInit].bits := bits;
  242. INC(nInit)
  243. END BufInit;
  244. PROCEDURE DeclConst (name: ARRAY OF CHAR; lit: LitStr; t: INTEGER);
  245. VAR idx : INTEGER;
  246. cls : INTEGER;
  247. v : INTEGER;
  248. c : CARDINAL;
  249. b : LONGCARD;
  250. BEGIN
  251. idx := AssignSlot(name);
  252. IF idx < 0 THEN RETURN END;
  253. cls := SymTab.ClassOf(t);
  254. IF ~IsLit(lit) OR (cls = SymTab.ClStr) THEN
  255. BufInit(idx, 0, 0, 0H); RETURN
  256. END;
  257. IF cls = SymTab.ClReal THEN
  258. IF ParseReal(lit, b) THEN BufInit(idx, 1, 0, b)
  259. ELSE BufInit(idx, 1, 0, 0H)
  260. END
  261. ELSIF SymTab.Equal(lit, "TRUE") THEN BufInit(idx, 0, 1, 0H)
  262. ELSIF SymTab.Equal(lit, "FALSE") THEN BufInit(idx, 0, 0, 0H)
  263. ELSIF ParseInt(lit, v) THEN BufInit(idx, 0, v, 0H)
  264. ELSIF ParseCard(lit, c) THEN
  265. BufInit(idx, 1, 0, VAL(LONGCARD, c))
  266. ELSE BufInit(idx, 0, 0, 0H)
  267. END
  268. END DeclConst;
  269. PROCEDURE DeclConstInt (name: ARRAY OF CHAR; v: INTEGER);
  270. VAR idx : INTEGER;
  271. BEGIN
  272. idx := AssignSlot(name);
  273. IF idx < 0 THEN RETURN END;
  274. BufInit(idx, 0, v, 0H)
  275. END DeclConstInt;
  276. PROCEDURE PushValue (kind: INTEGER; ival: INTEGER; bits: LONGCARD);
  277. BEGIN
  278. IF kind = 0 THEN PushInt(ival) ELSE PushBits(bits) END
  279. END PushValue;
  280. PROCEDURE BeginBody;
  281. VAR i : CARDINAL;
  282. BEGIN
  283. IF inBody THEN RETURN END;
  284. inBody := TRUE;
  285. mainAddr := nCode;
  286. i := 0;
  287. WHILE i < nInit DO
  288. PushValue(inits[i].kind, inits[i].ival, inits[i].bits);
  289. EmitOpB(OPstoreGlb, inits[i].idx);
  290. INC(i)
  291. END
  292. END BeginBody;
  293. (* ---------------- loads, stores, pushes ---------------- *)
  294. PROCEDURE LoadVar (name: ARRAY OF CHAR);
  295. VAR idx : INTEGER;
  296. BEGIN
  297. idx := FindVar(name);
  298. IF idx < 0 THEN EmitOp(OPimm0)
  299. ELSE EmitOpB(OPloadGlb, VAL(CARDINAL, idx))
  300. END
  301. END LoadVar;
  302. PROCEDURE StoreVar (name: ARRAY OF CHAR);
  303. VAR idx : INTEGER;
  304. BEGIN
  305. idx := FindVar(name);
  306. IF idx < 0 THEN EmitOp(OPext); EmitOp(SUBdrop)
  307. ELSE EmitOpB(OPstoreGlb, VAL(CARDINAL, idx))
  308. END
  309. END StoreVar;
  310. PROCEDURE LoadTemp (t: INTEGER);
  311. BEGIN
  312. EmitOpB(OPloadGlb, VAL(CARDINAL, t))
  313. END LoadTemp;
  314. PROCEDURE StoreTemp (t: INTEGER);
  315. BEGIN
  316. EmitOpB(OPstoreGlb, VAL(CARDINAL, t))
  317. END StoreTemp;
  318. PROCEDURE TempGlobal (): INTEGER;
  319. VAR idx : INTEGER;
  320. BEGIN
  321. idx := AssignSlot("");
  322. IF idx < 0 THEN RETURN 4 END;
  323. RETURN idx
  324. END TempGlobal;
  325. (* ---------------- frames and procedures ---------------- *)
  326. PROCEDURE EmitSlotB (op: CARDINAL; sl: INTEGER);
  327. (* Byte operand for a (possibly negative) frame slot. *)
  328. BEGIN
  329. IF sl >= 0 THEN EmitOpB(op, VAL(CARDINAL, sl))
  330. ELSE EmitOpB(op, 256 - VAL(CARDINAL, -sl))
  331. END
  332. END EmitSlotB;
  333. PROCEDURE LoadLocal (sl: INTEGER);
  334. BEGIN
  335. EmitSlotB(OPloadLocal, sl)
  336. END LoadLocal;
  337. PROCEDURE StoreLocal (sl: INTEGER);
  338. BEGIN
  339. EmitSlotB(OPstoreLocal, sl)
  340. END StoreLocal;
  341. PROCEDURE LoadIndir0;
  342. BEGIN
  343. EmitOp(OPloadIndir0)
  344. END LoadIndir0;
  345. PROCEDURE StoreIndir0;
  346. BEGIN
  347. EmitOp(OPstoreIndir0)
  348. END StoreIndir0;
  349. PROCEDURE FrameAddr (sl: INTEGER; np: CARDINAL);
  350. (* Pushes (display-frame(np) + slot*8): 11H np, then the offset. *)
  351. BEGIN
  352. EmitOpB(OPloadOuterN, np);
  353. IF sl >= 0 THEN EmitOpB(OPstkAddr, VAL(CARDINAL, sl))
  354. ELSE
  355. PushInt(sl * 8);
  356. EmitOp(OPadd)
  357. END
  358. END FrameAddr;
  359. PROCEDURE LoadIndir;
  360. BEGIN
  361. EmitOp(OPloadIndir)
  362. END LoadIndir;
  363. PROCEDURE StoreIndir;
  364. BEGIN
  365. EmitOp(OPstoreIndir)
  366. END StoreIndir;
  367. PROCEDURE LocalAddr (sl: INTEGER);
  368. BEGIN
  369. EmitSlotB(OPlocalAddr, sl)
  370. END LocalAddr;
  371. PROCEDURE GlobalAddr (name: ARRAY OF CHAR);
  372. VAR idx : INTEGER;
  373. BEGIN
  374. idx := FindVar(name);
  375. IF idx < 0 THEN EmitOp(OPimm0)
  376. ELSE EmitOpB(OPglobalAddr, VAL(CARDINAL, idx))
  377. END
  378. END GlobalAddr;
  379. PROCEDURE PushAddr (name: ARRAY OF CHAR);
  380. (* VAR-actual address: slot contents for VAR params, slot address
  381. for plain variables; display-aware. *)
  382. VAR k, d, D, sl : INTEGER;
  383. np : CARDINAL;
  384. BEGIN
  385. k := SymTab.SymKind(name);
  386. d := SymTab.SymDepth(name);
  387. D := SymTab.CurDepth();
  388. sl := SymTab.SymSlot(name);
  389. IF (k # SymTab.KindVar) & (k # SymTab.KindParam)
  390. & (k # SymTab.KindVarPar) THEN
  391. EmitOp(OPimm0); RETURN
  392. END;
  393. IF k = SymTab.KindVarPar THEN
  394. IF D = d THEN LoadLocal(sl)
  395. ELSE
  396. np := VAL(CARDINAL, D - 1 - d);
  397. FrameAddr(sl, np);
  398. LoadIndir
  399. END
  400. ELSE
  401. IF d = 0 THEN GlobalAddr(name)
  402. ELSIF D = d THEN LocalAddr(sl)
  403. ELSE
  404. np := VAL(CARDINAL, D - 1 - d);
  405. FrameAddr(sl, np)
  406. END
  407. END
  408. END PushAddr;
  409. PROCEDURE StoreSetup (name: ARRAY OF CHAR);
  410. (* Early address for indirect stores; call before the value code. *)
  411. VAR k, d, D, sl : INTEGER;
  412. np : CARDINAL;
  413. BEGIN
  414. k := SymTab.SymKind(name);
  415. IF (k # SymTab.KindVar) & (k # SymTab.KindParam)
  416. & (k # SymTab.KindVarPar) THEN
  417. RETURN
  418. END;
  419. d := SymTab.SymDepth(name);
  420. D := SymTab.CurDepth();
  421. sl := SymTab.SymSlot(name);
  422. IF k = SymTab.KindVarPar THEN
  423. IF D = d THEN LoadLocal(sl)
  424. ELSE
  425. np := VAL(CARDINAL, D - 1 - d);
  426. FrameAddr(sl, np);
  427. LoadIndir
  428. END
  429. ELSIF (d # 0) & (D # d) THEN
  430. np := VAL(CARDINAL, D - 1 - d);
  431. FrameAddr(sl, np)
  432. END
  433. END StoreSetup;
  434. PROCEDURE StoreFinish (name: ARRAY OF CHAR);
  435. (* Completes the store; call after the value code. *)
  436. VAR k, d, D, sl : INTEGER;
  437. BEGIN
  438. k := SymTab.SymKind(name);
  439. IF (k # SymTab.KindVar) & (k # SymTab.KindParam)
  440. & (k # SymTab.KindVarPar) THEN
  441. RETURN
  442. END;
  443. d := SymTab.SymDepth(name);
  444. D := SymTab.CurDepth();
  445. sl := SymTab.SymSlot(name);
  446. IF d = 0 THEN StoreVar(name)
  447. ELSIF D = d THEN
  448. IF k = SymTab.KindVarPar THEN StoreIndir0
  449. ELSE StoreLocal(sl)
  450. END
  451. ELSE
  452. IF k = SymTab.KindVarPar THEN StoreIndir0
  453. ELSE StoreIndir
  454. END
  455. END
  456. END StoreFinish;
  457. PROCEDURE PushVar (name: ARRAY OF CHAR);
  458. (* Frame-aware value load (see PushAddr for the address twin). *)
  459. VAR k, d, D, sl : INTEGER;
  460. np : CARDINAL;
  461. BEGIN
  462. k := SymTab.SymKind(name);
  463. d := SymTab.SymDepth(name);
  464. D := SymTab.CurDepth();
  465. sl := SymTab.SymSlot(name);
  466. IF (k # SymTab.KindVar) & (k # SymTab.KindParam)
  467. & (k # SymTab.KindVarPar) THEN
  468. EmitOp(OPimm0); RETURN
  469. END;
  470. IF d = 0 THEN LoadVar(name)
  471. ELSIF D = d THEN
  472. IF k = SymTab.KindVarPar THEN
  473. LoadLocal(sl); LoadIndir0
  474. ELSE LoadLocal(sl)
  475. END
  476. ELSE
  477. np := VAL(CARDINAL, D - 1 - d);
  478. FrameAddr(sl, np);
  479. LoadIndir;
  480. IF k = SymTab.KindVarPar THEN LoadIndir0 END
  481. END
  482. END PushVar;
  483. PROCEDURE ProcEntry (num: INTEGER; nLoc: CARDINAL);
  484. VAR k : CARDINAL;
  485. BEGIN
  486. IF (num >= 0) & (num <= 64) THEN
  487. procAddr[num] := VAL(INTEGER, nCode);
  488. IF VAL(CARDINAL, num) > maxNum THEN
  489. maxNum := VAL(CARDINAL, num)
  490. END
  491. END;
  492. IF nLoc > 255 THEN k := 255 ELSE k := nLoc END;
  493. EmitOpB(OPenter, 255 - k)
  494. END ProcEntry;
  495. PROCEDURE CallProc (num: INTEGER);
  496. BEGIN
  497. EmitOpB(OPprocCall, VAL(CARDINAL, num))
  498. END CallProc;
  499. PROCEDURE CallNested (num: INTEGER);
  500. BEGIN
  501. EmitOpB(OPnestedCall, VAL(CARDINAL, num))
  502. END CallNested;
  503. PROCEDURE CallDisplay (num: INTEGER; np: CARDINAL);
  504. BEGIN
  505. EmitOpB(OPloadOuterN, np);
  506. EmitOpB(OPcallFrame, VAL(CARDINAL, num))
  507. END CallDisplay;
  508. PROCEDURE Leave (nPar: CARDINAL; func: BOOLEAN);
  509. BEGIN
  510. IF nPar > 255 THEN nPar := 255 END;
  511. IF func THEN EmitOpB(OPfctLeave, nPar)
  512. ELSE EmitOpB(OPprocLeave, nPar)
  513. END
  514. END Leave;
  515. (* ---------------- actual parameters ---------------- *)
  516. PROCEDURE ActFrameIdx (): CARDINAL;
  517. (* Active frame, capped (nesting past the cap reuses the top). *)
  518. BEGIN
  519. IF actTop = 0 THEN RETURN 0 END;
  520. IF actTop - 1 > MaxActDepth THEN RETURN MaxActDepth END;
  521. RETURN actTop - 1
  522. END ActFrameIdx;
  523. PROCEDURE ActBegin (pn: ARRAY OF CHAR);
  524. VAR fr : CARDINAL;
  525. BEGIN
  526. fr := actTop;
  527. IF fr > MaxActDepth THEN fr := MaxActDepth
  528. ELSE INC(actTop)
  529. END;
  530. StrCpy(actSt[fr].pn, pn);
  531. actSt[fr].n := 0;
  532. actSt[fr].known := SymTab.Lookup(pn)
  533. & (SymTab.SymKind(pn) = SymTab.KindProc);
  534. IF actSt[fr].known THEN actSt[fr].nf := SymTab.ProcNPar(pn)
  535. ELSE actSt[fr].nf := 0
  536. END
  537. END ActBegin;
  538. PROCEDURE ActValue (t: INTEGER; v: BOOLEAN;
  539. vn: ARRAY OF CHAR): INTEGER;
  540. VAR fr : CARDINAL;
  541. i : CARDINAL;
  542. ftyp : INTEGER;
  543. fv : BOOLEAN;
  544. err : INTEGER;
  545. BEGIN
  546. err := 0;
  547. fr := ActFrameIdx();
  548. i := actSt[fr].n;
  549. IF i > MaxActN THEN
  550. EmitOp(OPext); EmitOp(SUBdrop);
  551. actSt[fr].n := i + 1;
  552. RETURN 1
  553. END;
  554. IF actSt[fr].known & (i < actSt[fr].nf) THEN
  555. ftyp := SymTab.ParamType(actSt[fr].pn, i);
  556. fv := SymTab.ParamIsVar(actSt[fr].pn, i);
  557. IF fv THEN
  558. IF ~v THEN err := 1
  559. ELSIF ~SymTab.SameType(t, ftyp) THEN err := 1
  560. END;
  561. EmitOp(OPext); EmitOp(SUBdrop);
  562. PushAddr(vn)
  563. ELSE
  564. IF ~SymTab.Assignable(t, ftyp) THEN err := 1
  565. ELSIF SymTab.IsIntFamily(t)
  566. & (SymTab.ClassOf(ftyp) = SymTab.ClReal) THEN
  567. IntToReal
  568. END
  569. END
  570. END;
  571. actSt[fr].tmps[i] := TempGlobal();
  572. StoreTemp(actSt[fr].tmps[i]);
  573. actSt[fr].n := i + 1;
  574. RETURN err
  575. END ActValue;
  576. PROCEDURE ActEnd (pn: ARRAY OF CHAR; sfx, inExpr: BOOLEAN): INTEGER;
  577. VAR fr : CARDINAL;
  578. i : CARDINAL;
  579. n, num, F, d : INTEGER;
  580. BEGIN
  581. fr := ActFrameIdx();
  582. IF actTop > 0 THEN DEC(actTop) END;
  583. n := VAL(INTEGER, actSt[fr].n);
  584. IF ~SymTab.Lookup(pn) THEN
  585. IF inExpr THEN EmitOp(OPimm0) END;
  586. RETURN 0
  587. END;
  588. IF (SymTab.SymKind(pn) # SymTab.KindProc)
  589. OR sfx
  590. OR (n # VAL(INTEGER, SymTab.ProcNPar(pn))) THEN
  591. IF inExpr THEN EmitOp(OPimm0) END;
  592. RETURN 1
  593. END;
  594. IF inExpr & (SymTab.ProcRet(pn) = SymTab.InvalidType) THEN
  595. EmitOp(OPimm0);
  596. RETURN 1
  597. END;
  598. i := actSt[fr].n;
  599. WHILE i > 0 DO
  600. DEC(i);
  601. IF i <= MaxActN THEN LoadTemp(actSt[fr].tmps[i]) END
  602. END;
  603. num := SymTab.ProcNum(pn);
  604. F := SymTab.CurDepth();
  605. d := SymTab.SymDepth(pn);
  606. IF d = 0 THEN CallProc(num)
  607. ELSIF F = d THEN CallNested(num)
  608. ELSE CallDisplay(num, VAL(CARDINAL, F - 1 - d))
  609. END;
  610. IF ~inExpr & (SymTab.ProcRet(pn) # SymTab.InvalidType) THEN
  611. EmitOp(OPext); EmitOp(SUBdrop)
  612. END;
  613. RETURN 0
  614. END ActEnd;
  615. PROCEDURE EmitMag (c: CARDINAL);
  616. BEGIN
  617. IF c <= 255 THEN EmitOpB(OPimmB, c)
  618. ELSE EmitOp(OPimmW); EmitW64(VAL(LONGCARD, c))
  619. END
  620. END EmitMag;
  621. PROCEDURE PushInt (v: INTEGER);
  622. VAR mag : CARDINAL;
  623. BEGIN
  624. IF (v >= 0) & (v <= 15) THEN EmitOp(OPimm0 + VAL(CARDINAL, v))
  625. ELSIF v < 0 THEN
  626. IF v = -2147483647 - 1 THEN mag := 80000000H
  627. ELSE mag := VAL(CARDINAL, -v)
  628. END;
  629. EmitOp(OPimm0); EmitMag(mag); EmitOp(OPsub)
  630. ELSE EmitMag(VAL(CARDINAL, v))
  631. END
  632. END PushInt;
  633. PROCEDURE PushBits (b: LONGCARD);
  634. BEGIN
  635. EmitOp(OPimmW); EmitW64(b)
  636. END PushBits;
  637. (* ---------------- literal parsing ---------------- *)
  638. PROCEDURE DigVal (ch: CHAR): INTEGER;
  639. BEGIN
  640. IF (ch >= "0") & (ch <= "9") THEN RETURN ORD(ch) - ORD("0") END;
  641. IF (ch >= "A") & (ch <= "F") THEN RETURN ORD(ch) - ORD("A") + 10 END;
  642. IF (ch >= "a") & (ch <= "f") THEN RETURN ORD(ch) - ORD("a") + 10 END;
  643. RETURN -1
  644. END DigVal;
  645. PROCEDURE ParseCard (s: ARRAY OF CHAR; VAR v: CARDINAL): BOOLEAN;
  646. VAR i, n : CARDINAL;
  647. hex : BOOLEAN;
  648. d : INTEGER;
  649. acc : LONGCARD;
  650. BEGIN
  651. v := 0;
  652. n := StrLen(s);
  653. IF n = 0 THEN RETURN FALSE END;
  654. hex := (s[n - 1] = "H") OR (s[n - 1] = "h");
  655. IF hex THEN DEC(n) END;
  656. IF n = 0 THEN RETURN FALSE END;
  657. acc := 0H; i := 0;
  658. WHILE i < n DO
  659. d := DigVal(s[i]);
  660. IF hex THEN
  661. IF d < 0 THEN RETURN FALSE END;
  662. acc := acc * 16 + VAL(LONGCARD, VAL(CARDINAL, d))
  663. ELSE
  664. IF (d < 0) OR (d > 9) THEN RETURN FALSE END;
  665. acc := acc * 10 + VAL(LONGCARD, VAL(CARDINAL, d))
  666. END;
  667. IF acc > 0FFFFFFFFH THEN RETURN FALSE END;
  668. INC(i)
  669. END;
  670. v := VAL(CARDINAL, acc);
  671. RETURN TRUE
  672. END ParseCard;
  673. PROCEDURE ParseInt (s: ARRAY OF CHAR; VAR v: INTEGER): BOOLEAN;
  674. VAR i : CARDINAL;
  675. neg : BOOLEAN;
  676. t : ARRAY [0 .. 63] OF CHAR;
  677. c : CARDINAL;
  678. lim : LONGCARD;
  679. BEGIN
  680. v := 0;
  681. IF (StrLen(s) = 0) THEN RETURN FALSE END;
  682. neg := s[0] = "-";
  683. IF neg THEN
  684. i := 1;
  685. WHILE s[i] # 0C DO
  686. IF i - 1 > HIGH(t) THEN RETURN FALSE END;
  687. t[i - 1] := s[i]; INC(i)
  688. END;
  689. IF i - 1 > HIGH(t) THEN RETURN FALSE END;
  690. t[i - 1] := 0C
  691. ELSE StrCpy(t, s)
  692. END;
  693. IF ~ParseCard(t, c) THEN RETURN FALSE END;
  694. IF neg THEN lim := 80000000H ELSE lim := 7FFFFFFFH END;
  695. IF VAL(LONGCARD, c) > lim THEN RETURN FALSE END;
  696. IF neg THEN
  697. IF VAL(LONGCARD, c) = 80000000H THEN v := -2147483647 - 1
  698. ELSE v := -VAL(INTEGER, c)
  699. END
  700. ELSE v := VAL(INTEGER, c)
  701. END;
  702. RETURN TRUE
  703. END ParseInt;
  704. PROCEDURE ParseReal (s: ARRAY OF CHAR; VAR b: LONGCARD): BOOLEAN;
  705. VAR i : CARDINAL;
  706. neg, esign : BOOLEAN;
  707. m, scale : REAL;
  708. e, d : CARDINAL;
  709. rv : RealView;
  710. BEGIN
  711. b := 0H;
  712. i := 0; neg := FALSE;
  713. IF s[0] = "-" THEN neg := TRUE; INC(i) END;
  714. IF (s[i] < "0") OR (s[i] > "9") THEN RETURN FALSE END;
  715. m := 0.0;
  716. WHILE (s[i] >= "0") & (s[i] <= "9") DO
  717. m := m * 10.0 + VAL(REAL, VAL(CARDINAL, ORD(s[i]) - ORD("0")));
  718. INC(i)
  719. END;
  720. IF s[i] = "." THEN
  721. INC(i);
  722. IF (s[i] < "0") OR (s[i] > "9") THEN RETURN FALSE END;
  723. scale := 10.0;
  724. WHILE (s[i] >= "0") & (s[i] <= "9") DO
  725. m := m + VAL(REAL, VAL(CARDINAL, ORD(s[i]) - ORD("0"))) / scale;
  726. scale := scale * 10.0;
  727. INC(i)
  728. END
  729. END;
  730. IF (s[i] = "E") OR (s[i] = "e") THEN
  731. INC(i); esign := FALSE;
  732. IF s[i] = "+" THEN INC(i)
  733. ELSIF s[i] = "-" THEN esign := TRUE; INC(i)
  734. END;
  735. IF (s[i] < "0") OR (s[i] > "9") THEN RETURN FALSE END;
  736. e := 0;
  737. WHILE (s[i] >= "0") & (s[i] <= "9") DO
  738. d := VAL(CARDINAL, ORD(s[i]) - ORD("0"));
  739. IF e <= 9999 THEN e := e * 10 + d END;
  740. INC(i)
  741. END;
  742. WHILE e > 0 DO
  743. IF esign THEN m := m / 10.0 ELSE m := m * 10.0 END;
  744. DEC(e)
  745. END
  746. END;
  747. IF s[i] # 0C THEN RETURN FALSE END;
  748. IF neg THEN m := -m END;
  749. rv.r := m;
  750. b := rv.w;
  751. RETURN TRUE
  752. END ParseReal;
  753. PROCEDURE CharOrd (s: ARRAY OF CHAR): INTEGER;
  754. BEGIN
  755. IF StrLen(s) >= 2 THEN RETURN ORD(s[1]) END;
  756. RETURN 0
  757. END CharOrd;
  758. PROCEDURE NegFold (a: ARRAY OF CHAR; VAR q: LitStr);
  759. (* Safe for a and q being the same variable. *)
  760. VAR tmp : LitStr;
  761. i, j : CARDINAL;
  762. BEGIN
  763. StrCpy(tmp, a);
  764. IF StrLen(tmp) = 0 THEN StrCpy(q, ""); RETURN END;
  765. IF tmp[0] = "-" THEN
  766. i := 1; j := 0;
  767. WHILE (tmp[i] # 0C) & (j < HIGH(q)) DO
  768. q[j] := tmp[i]; INC(i); INC(j)
  769. END;
  770. IF j <= HIGH(q) THEN q[j] := 0C END
  771. ELSE
  772. StrCpy(q, "-");
  773. i := 0; j := StrLen(q);
  774. WHILE (tmp[i] # 0C) & (j < HIGH(q)) DO
  775. q[j] := tmp[i]; INC(i); INC(j)
  776. END;
  777. IF j <= HIGH(q) THEN q[j] := 0C END
  778. END
  779. END NegFold;
  780. PROCEDURE IsLit (s: ARRAY OF CHAR): BOOLEAN;
  781. BEGIN
  782. RETURN StrLen(s) > 0
  783. END IsLit;
  784. (* ---------------- operators ---------------- *)
  785. PROCEDURE Add;
  786. BEGIN EmitOp(OPadd) END Add;
  787. PROCEDURE Sub;
  788. BEGIN EmitOp(OPsub) END Sub;
  789. PROCEDURE MulU;
  790. BEGIN EmitOp(OPumul) END MulU;
  791. PROCEDURE DivU;
  792. BEGIN EmitOp(OPudiv) END DivU;
  793. PROCEDURE ModU;
  794. BEGIN EmitOp(OPumod) END ModU;
  795. PROCEDURE MulI;
  796. BEGIN EmitOp(OPimul) END MulI;
  797. PROCEDURE DivI;
  798. BEGIN EmitOp(OPidiv) END DivI;
  799. PROCEDURE ModI (t: INTEGER);
  800. (* [a b] -> a MOD b (truncation) via temp t. *)
  801. BEGIN
  802. StoreTemp(t);
  803. EmitOp(OPdup);
  804. LoadTemp(t);
  805. EmitOp(OPidiv);
  806. LoadTemp(t);
  807. EmitOp(OPimul);
  808. EmitOp(OPsub)
  809. END ModI;
  810. PROCEDURE RealAdd;
  811. BEGIN EmitOp(OPrAdd) END RealAdd;
  812. PROCEDURE RealSub;
  813. BEGIN EmitOp(OPrSub) END RealSub;
  814. PROCEDURE RealMul;
  815. BEGIN EmitOp(OPrMul) END RealMul;
  816. PROCEDURE RealDiv;
  817. BEGIN EmitOp(OPrDiv) END RealDiv;
  818. PROCEDURE And;
  819. BEGIN EmitOp(OPand) END And;
  820. PROCEDURE Or;
  821. BEGIN EmitOp(OPor) END Or;
  822. PROCEDURE Not;
  823. BEGIN EmitOp(OPnot) END Not;
  824. PROCEDURE Power2;
  825. BEGIN EmitOp(OPpower2) END Power2;
  826. PROCEDURE FieldMask;
  827. BEGIN EmitOp(OPext); EmitOp(04H) END FieldMask;
  828. PROCEDURE BitIn;
  829. BEGIN EmitOp(OPbitIn) END BitIn;
  830. PROCEDURE Eq;
  831. BEGIN EmitOp(OPeq) END Eq;
  832. PROCEDURE Neq;
  833. BEGIN EmitOp(OPne) END Neq;
  834. PROCEDURE ULt;
  835. BEGIN EmitOp(OPult) END ULt;
  836. PROCEDURE ULe;
  837. BEGIN EmitOp(OPule) END ULe;
  838. PROCEDURE UGt;
  839. BEGIN EmitOp(OPugt) END UGt;
  840. PROCEDURE UGe;
  841. BEGIN EmitOp(OPuge) END UGe;
  842. PROCEDURE ILt;
  843. BEGIN EmitOp(OPilt) END ILt;
  844. PROCEDURE ILe;
  845. BEGIN EmitOp(OPile) END ILe;
  846. PROCEDURE IGt;
  847. BEGIN EmitOp(OPigt) END IGt;
  848. PROCEDURE IGe;
  849. BEGIN EmitOp(OPige) END IGe;
  850. PROCEDURE RealEq;
  851. (* [r1 r2] -> (r1 = r2): cmp, or, not. *)
  852. BEGIN EmitOp(OPrCmp); EmitOp(OPor); EmitOp(OPnot) END RealEq;
  853. PROCEDURE RealNe;
  854. (* [r1 r2] -> (r1 # r2): cmp, or. *)
  855. BEGIN EmitOp(OPrCmp); EmitOp(OPor) END RealNe;
  856. PROCEDURE RealLt;
  857. (* [gt lt] -> lt: swap, drop. *)
  858. BEGIN EmitOp(OPswap); EmitOp(OPext); EmitOp(SUBdrop) END RealLt;
  859. PROCEDURE RealLe;
  860. (* [gt lt] -> NOT gt: drop, not. *)
  861. BEGIN EmitOp(OPext); EmitOp(SUBdrop); EmitOp(OPnot) END RealLe;
  862. PROCEDURE RealGt;
  863. (* [gt lt] -> gt: drop. *)
  864. BEGIN EmitOp(OPext); EmitOp(SUBdrop) END RealGt;
  865. PROCEDURE RealGe;
  866. (* [gt lt] -> NOT lt: swap, drop, not. *)
  867. BEGIN
  868. EmitOp(OPswap); EmitOp(OPext); EmitOp(SUBdrop); EmitOp(OPnot)
  869. END RealGe;
  870. PROCEDURE NegInt;
  871. BEGIN EmitOp(OPimm0); EmitOp(OPswap); EmitOp(OPsub) END NegInt;
  872. PROCEDURE NegReal;
  873. BEGIN
  874. EmitOp(OPimmW); EmitW64(0H);
  875. EmitOp(OPswap); EmitOp(OPrSub)
  876. END NegReal;
  877. PROCEDURE IntToReal;
  878. BEGIN EmitOp(OPintToLong); EmitOp(OPlongToReal) END IntToReal;
  879. PROCEDURE Dup;
  880. BEGIN EmitOp(OPdup) END Dup;
  881. PROCEDURE Drop;
  882. BEGIN EmitOp(OPext); EmitOp(SUBdrop) END Drop;
  883. PROCEDURE Swap;
  884. BEGIN EmitOp(OPswap) END Swap;
  885. (* ---------------- composites ---------------- *)
  886. PROCEDURE IdxScale (lo: INTEGER; elemBytes: CARDINAL);
  887. BEGIN
  888. PushInt(lo);
  889. EmitOp(OPsub);
  890. PushInt(VAL(INTEGER, elemBytes));
  891. EmitOp(OPumul);
  892. EmitOp(OPadd)
  893. END IdxScale;
  894. PROCEDURE FieldAdd (offSlots: CARDINAL);
  895. BEGIN
  896. IF offSlots = 0 THEN RETURN END;
  897. PushInt(VAL(INTEGER, offSlots * 8));
  898. EmitOp(OPadd)
  899. END FieldAdd;
  900. PROCEDURE CopyBlock;
  901. BEGIN EmitOp(30H) END CopyBlock;
  902. PROCEDURE LoadByte;
  903. BEGIN
  904. PushInt(0);
  905. EmitOp(0DH)
  906. END LoadByte;
  907. PROCEDURE StoreByte;
  908. BEGIN
  909. PushInt(0);
  910. EmitOp(OPswap);
  911. EmitOp(1DH)
  912. END StoreByte;
  913. PROCEDURE PushBytes (n: CARDINAL);
  914. BEGIN PushInt(VAL(INTEGER, n)) END PushBytes;
  915. PROCEDURE AllocOp;
  916. BEGIN EmitOp(OPext); EmitOp(05H) END AllocOp;
  917. PROCEDURE DeallocOp;
  918. BEGIN EmitOp(OPext); EmitOp(06H) END DeallocOp;
  919. PROCEDURE BitXor;
  920. BEGIN EmitOp(0E9H) END BitXor;
  921. PROCEDURE StrLenOf (s: ARRAY OF CHAR): CARDINAL;
  922. VAR n: CARDINAL;
  923. BEGIN
  924. n := StrLen(s);
  925. IF n < 2 THEN RETURN 0 END;
  926. RETURN n - 2
  927. END StrLenOf;
  928. PROCEDURE EmitString (s: ARRAY OF CHAR);
  929. VAR len, i: CARDINAL;
  930. BEGIN
  931. len := StrLenOf(s);
  932. IF len + 1 > 255 THEN
  933. PushInt(0); RETURN
  934. END;
  935. EmitOp(8CH);
  936. EmitByte(len + 1);
  937. i := 1;
  938. WHILE i <= len DO
  939. EmitByte(ORD(s[i])); INC(i)
  940. END;
  941. EmitByte(0)
  942. END EmitString;
  943. PROCEDURE StrComp;
  944. BEGIN EmitOp(0C4H) END StrComp;
  945. (* ---------------- WITH ---------------- *)
  946. PROCEDURE WithEnter (typ: INTEGER);
  947. VAR tmp: INTEGER;
  948. BEGIN
  949. tmp := TempGlobal();
  950. StoreTemp(tmp);
  951. IF withTop <= 7 THEN
  952. withTmps[withTop] := tmp;
  953. withTyps[withTop] := typ;
  954. INC(withTop)
  955. END
  956. END WithEnter;
  957. PROCEDURE WithExit;
  958. BEGIN
  959. IF withTop > 0 THEN DEC(withTop) END
  960. END WithExit;
  961. PROCEDURE WithDepth (): CARDINAL;
  962. BEGIN RETURN withTop END WithDepth;
  963. PROCEDURE WithAddr (name: ARRAY OF CHAR);
  964. VAR i: CARDINAL;
  965. off: INTEGER;
  966. found: BOOLEAN;
  967. BEGIN
  968. found := FALSE;
  969. i := withTop;
  970. WHILE (i > 0) & ~found DO
  971. DEC(i);
  972. IF SymTab.FieldExists(withTyps[i], name) THEN
  973. off := SymTab.FieldOffset(withTyps[i], name);
  974. LoadTemp(withTmps[i]);
  975. IF off > 0 THEN
  976. PushInt(VAL(INTEGER, VAL(CARDINAL, off) * 8));
  977. EmitOp(OPadd)
  978. ELSIF off < 0 THEN
  979. PushInt(0)
  980. END;
  981. found := TRUE
  982. END
  983. END;
  984. IF ~found THEN PushInt(0) END
  985. END WithAddr;
  986. (* ---------------- control flow ---------------- *)
  987. PROCEDURE NewLabel (): INTEGER;
  988. BEGIN
  989. IF nLab > MaxLab THEN RETURN 0 END;
  990. labs[nLab] := -1;
  991. INC(nLab);
  992. RETURN VAL(INTEGER, nLab - 1)
  993. END NewLabel;
  994. PROCEDURE DefLabel (id: INTEGER);
  995. VAR i : CARDINAL;
  996. rel : INTEGER;
  997. BEGIN
  998. IF (id < 0) OR (id >= VAL(INTEGER, nLab)) THEN RETURN END;
  999. labs[id] := VAL(INTEGER, nCode);
  1000. i := 0;
  1001. WHILE i < nFix DO
  1002. IF fixs[i].lab = id THEN
  1003. rel := labs[id] - VAL(INTEGER, fixs[i].pos + 9);
  1004. WriteS64At(fixs[i].pos + 1, rel);
  1005. fixs[i].lab := -1
  1006. END;
  1007. INC(i)
  1008. END
  1009. END DefLabel;
  1010. PROCEDURE Jump (op: CARDINAL; id: INTEGER);
  1011. VAR pos : CARDINAL;
  1012. j : CARDINAL;
  1013. BEGIN
  1014. pos := nCode;
  1015. EmitOp(op);
  1016. IF (id >= 0) & (id < VAL(INTEGER, nLab)) & (labs[id] >= 0) THEN
  1017. EmitS64(labs[id] - VAL(INTEGER, pos + 9))
  1018. ELSE
  1019. FOR j := 0 TO 7 DO EmitByte(0) END;
  1020. IF (nFix <= MaxFix) & (id >= 0) & (id < VAL(INTEGER, nLab)) THEN
  1021. fixs[nFix].pos := pos; fixs[nFix].lab := id; INC(nFix)
  1022. END
  1023. END
  1024. END Jump;
  1025. PROCEDURE Jmp (id: INTEGER);
  1026. BEGIN
  1027. Jump(OPjp, id)
  1028. END Jmp;
  1029. PROCEDURE Jz (id: INTEGER);
  1030. BEGIN
  1031. Jump(OPjz, id)
  1032. END Jz;
  1033. PROCEDURE PushLoop (exit: INTEGER);
  1034. BEGIN
  1035. IF loopTop <= MaxLoop THEN
  1036. loopSt[loopTop] := exit; INC(loopTop)
  1037. END
  1038. END PushLoop;
  1039. PROCEDURE PopLoop;
  1040. BEGIN
  1041. IF loopTop > 0 THEN DEC(loopTop) END
  1042. END PopLoop;
  1043. PROCEDURE TopLoop (VAR exit: INTEGER): BOOLEAN;
  1044. BEGIN
  1045. IF loopTop = 0 THEN RETURN FALSE END;
  1046. exit := loopSt[loopTop - 1];
  1047. RETURN TRUE
  1048. END TopLoop;
  1049. PROCEDURE NoSupEnter;
  1050. BEGIN
  1051. INC(noSup)
  1052. END NoSupEnter;
  1053. PROCEDURE NoSupExit;
  1054. BEGIN
  1055. IF noSup > 0 THEN DEC(noSup) END
  1056. END NoSupExit;
  1057. PROCEDURE NoSup (): BOOLEAN;
  1058. BEGIN
  1059. RETURN noSup > 0
  1060. END NoSup;
  1061. PROCEDURE CopyName (s: ARRAY OF CHAR; VAR d: ARRAY OF CHAR);
  1062. VAR i : CARDINAL;
  1063. BEGIN
  1064. i := 0;
  1065. WHILE (i < HIGH(d)) & (i < HIGH(s)) & (s[i] # 0C) DO
  1066. d[i] := s[i]; INC(i)
  1067. END;
  1068. IF i <= HIGH(d) THEN d[i] := 0C END
  1069. END CopyName;
  1070. PROCEDURE NoEmitEnter;
  1071. BEGIN
  1072. INC(noEmit)
  1073. END NoEmitEnter;
  1074. PROCEDURE NoEmitExit;
  1075. BEGIN
  1076. IF noEmit > 0 THEN DEC(noEmit) END
  1077. END NoEmitExit;
  1078. (* ---------------- image assembly ---------------- *)
  1079. PROCEDURE Put32At (off: CARDINAL; v: CARDINAL);
  1080. BEGIN
  1081. img[off] := CHR(v MOD 256);
  1082. img[off + 1] := CHR((v DIV 256) MOD 256);
  1083. img[off + 2] := CHR((v DIV 65536) MOD 256);
  1084. img[off + 3] := CHR(v DIV 16777216)
  1085. END Put32At;
  1086. PROCEDURE Put64At (off: CARDINAL; v: LONGCARD);
  1087. VAR j : CARDINAL;
  1088. BEGIN
  1089. FOR j := 0 TO 7 DO
  1090. img[off + j] := CHR(VAL(CARDINAL, v MOD 256));
  1091. v := v DIV 256
  1092. END
  1093. END Put64At;
  1094. PROCEDURE EmitPrint;
  1095. (* proc1: prints the CARDINAL parameter as decimal + CRLF.
  1096. Uses global temps 0..3 (buffer, count, index, char). *)
  1097. VAR l1, l2 : INTEGER;
  1098. BEGIN
  1099. EmitOpB(OPenter, 250);
  1100. EmitOpB(OPimmB, 16); EmitOp(0D2H); EmitOpB(OPstoreGlb, 0);
  1101. EmitOp(OPimm0); EmitOp(OPimm0);
  1102. EmitOpB(OPstoreGlb, 1); EmitOpB(OPstoreGlb, 2);
  1103. EmitOp(03H);
  1104. l1 := NewLabel(); DefLabel(l1);
  1105. EmitOpB(OPloadGlb, 1); EmitOp(OPinc); EmitOpB(OPstoreGlb, 1);
  1106. EmitOp(OPdup); EmitOpB(OPimmB, 10); EmitOp(OPumod);
  1107. EmitOp(OPswap); EmitOpB(OPimmB, 10); EmitOp(OPudiv);
  1108. EmitOp(OPdup); EmitOp(OPaeq0);
  1109. Jz(l1);
  1110. EmitOp(OPext); EmitOp(SUBdrop);
  1111. l2 := NewLabel(); DefLabel(l2);
  1112. EmitOpB(OPimmB, 48); EmitOp(OPadd); EmitOpB(OPstoreGlb, 3);
  1113. EmitOpB(OPloadGlb, 0); EmitOpB(OPloadGlb, 2); EmitOp(OPadd);
  1114. EmitOp(OPimm0); EmitOpB(OPloadGlb, 3); EmitOp(1DH);
  1115. EmitOpB(OPloadGlb, 2); EmitOp(OPinc); EmitOpB(OPstoreGlb, 2);
  1116. EmitOpB(OPloadGlb, 1); EmitOp(OPdec); EmitOpB(OPstoreGlb, 1);
  1117. EmitOpB(OPloadGlb, 1); EmitOp(OPaeq0);
  1118. Jz(l2);
  1119. EmitOpB(OPloadGlb, 0); EmitOpB(OPloadGlb, 2); EmitOp(OPadd);
  1120. EmitOp(OPimm0); EmitOp(OPimm0); EmitOp(1DH);
  1121. EmitOpB(OPloadGlb, 0);
  1122. EmitOpB(OPimmB, 1); EmitOp(OPsys);
  1123. EmitOpB(OPimmB, 3); EmitOp(0D2H);
  1124. EmitOp(OPdup); EmitOp(OPimm0); EmitOpB(OPimmB, 13); EmitOp(1DH);
  1125. EmitOp(OPdup); EmitOpB(OPimmB, 1); EmitOpB(OPimmB, 10); EmitOp(1DH);
  1126. EmitOp(OPdup); EmitOpB(OPimmB, 2); EmitOp(OPimm0); EmitOp(1DH);
  1127. EmitOpB(OPimmB, 1); EmitOp(OPsys);
  1128. EmitOpB(OPfctLeave, 0)
  1129. END EmitPrint;
  1130. PROCEDURE PutS64At (off, addr, slot: CARDINAL);
  1131. (* Procedure-table cell: signed (addr - slot). *)
  1132. VAR mag : LONGCARD;
  1133. bits : LONGCARD;
  1134. j : CARDINAL;
  1135. BEGIN
  1136. IF addr >= slot THEN bits := VAL(LONGCARD, addr - slot)
  1137. ELSE
  1138. mag := VAL(LONGCARD, slot - addr);
  1139. bits := 0FFFFFFFFFFFFFFFFH - mag + 1H
  1140. END;
  1141. FOR j := 0 TO 7 DO
  1142. img[off + j] := CHR(VAL(CARDINAL, bits MOD 256));
  1143. bits := bits DIV 256
  1144. END
  1145. END PutS64At;
  1146. PROCEDURE EndModule;
  1147. VAR i : CARDINAL;
  1148. codeOff, p1, pt, prNum, tabBytes : CARDINAL;
  1149. k : CARDINAL;
  1150. addr : CARDINAL;
  1151. exitIdx : INTEGER;
  1152. sum : CARDINAL;
  1153. fname : ARRAY [0 .. 127] OF CHAR;
  1154. f : FileIO.File;
  1155. ch : CHAR;
  1156. BEGIN
  1157. IF ~inBody THEN mainAddr := nCode END;
  1158. prNum := maxNum + 1;
  1159. (* epilogue: print ExitCode when the convention applies *)
  1160. exitIdx := -1;
  1161. IF SymTab.Lookup("ExitCode")
  1162. & (SymTab.SymKind("ExitCode") = SymTab.KindVar)
  1163. & SymTab.IsIntFamily(SymTab.SymType("ExitCode")) THEN
  1164. exitIdx := FindVar("ExitCode")
  1165. END;
  1166. IF exitIdx >= 0 THEN
  1167. EmitOpB(OPloadGlb, VAL(CARDINAL, exitIdx));
  1168. EmitOpB(OPprocCall, prNum);
  1169. EmitOp(OPext); EmitOp(SUBdrop)
  1170. END;
  1171. EmitOp(OPend);
  1172. p1 := nCode;
  1173. EmitPrint;
  1174. (* assemble the image *)
  1175. i := 0;
  1176. WHILE i <= MaxImg DO img[i] := 0C; INC(i) END;
  1177. img[0] := "M"; img[1] := "C"; img[2] := "6"; img[3] := "4";
  1178. i := 0;
  1179. WHILE (i < 16) & (modName[i] # 0C) DO
  1180. img[HeadSize + DName + i] := modName[i]; INC(i)
  1181. END;
  1182. img[HeadSize + DFlags] := CHR(4);
  1183. img[HeadSize + DVarCount] := CHR(nVars MOD 256);
  1184. img[HeadSize + DDepCount] := 0C;
  1185. codeOff := DVarSizes + nVars * 8;
  1186. i := 0;
  1187. WHILE i < nCode DO
  1188. img[HeadSize + codeOff + i] := code[i]; INC(i)
  1189. END;
  1190. pt := codeOff + nCode;
  1191. tabBytes := (maxNum + 2) * 8;
  1192. Put64At(HeadSize + DProcs, VAL(LONGCARD, pt));
  1193. k := 0;
  1194. WHILE k <= maxNum + 1 DO
  1195. IF k = 0 THEN addr := codeOff + mainAddr
  1196. ELSIF k <= maxNum THEN
  1197. IF procAddr[k] < 0 THEN addr := pt + k * 8
  1198. ELSE addr := VAL(CARDINAL, procAddr[k]) + codeOff
  1199. END
  1200. ELSE addr := codeOff + p1
  1201. END;
  1202. PutS64At(HeadSize + pt + k * 8, addr, pt + k * 8);
  1203. INC(k)
  1204. END;
  1205. i := 0;
  1206. WHILE i < nVars DO
  1207. Put64At(HeadSize + DVarSizes + i * 8,
  1208. VAL(LONGCARD, vSize[i] * 8));
  1209. INC(i)
  1210. END;
  1211. sum := 0;
  1212. i := HeadSize;
  1213. WHILE i < HeadSize + pt + tabBytes DO
  1214. IF ~((i >= 352) & (i <= 355)) THEN
  1215. sum := sum + ORD(img[i])
  1216. END;
  1217. INC(i)
  1218. END;
  1219. Put32At(HeadSize + DChecksum, sum);
  1220. fname[0] := 0C;
  1221. StrCpy(fname, modName);
  1222. i := StrLen(fname);
  1223. fname[i] := "."; fname[i + 1] := "M"; fname[i + 2] := "C";
  1224. fname[i + 3] := "4"; fname[i + 4] := 0C;
  1225. FileIO.Open(f, fname, TRUE);
  1226. IF FileIO.Okay THEN
  1227. i := 0;
  1228. WHILE i < HeadSize + pt + tabBytes DO
  1229. ch := img[i];
  1230. FileIO.Write(f, ch);
  1231. INC(i)
  1232. END;
  1233. FileIO.Close(f)
  1234. END
  1235. END EndModule;
  1236. BEGIN
  1237. nCode := 0; nGlb := 0; nVars := 0; nInit := 0;
  1238. nLab := 0; nFix := 0; loopTop := 0; noSup := 0; noEmit := 0;
  1239. actTop := 0; withTop := 0;
  1240. maxNum := 0; mainAddr := 0;
  1241. inBody := FALSE;
  1242. modName[0] := 0C
  1243. END MGen.