MGen.mod 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657
  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. lens : ARRAY [0 .. MaxActN] OF INTEGER;
  66. addrs : ARRAY [0 .. MaxActN] OF INTEGER;
  67. sfxs : ARRAY [0 .. MaxActN] OF BOOLEAN;
  68. idxs : ARRAY [0 .. MaxActN] OF BOOLEAN;
  69. known : BOOLEAN;
  70. nf : CARDINAL;
  71. pn : ARRAY [0 .. 63] OF CHAR;
  72. byNum : BOOLEAN;
  73. num : INTEGER;
  74. END;
  75. VAR
  76. code : ARRAY [0 .. MaxCode] OF CHAR;
  77. nCode : CARDINAL;
  78. img : ARRAY [0 .. MaxImg] OF CHAR;
  79. modName : ARRAY [0 .. 63] OF CHAR;
  80. gNames : ARRAY [0 .. MaxGlb] OF ARRAY [0 .. 63] OF CHAR;
  81. vBase : ARRAY [0 .. MaxGlb] OF CARDINAL;
  82. vSize : ARRAY [0 .. MaxGlb] OF CARDINAL;
  83. nVars : CARDINAL;
  84. nGlb : CARDINAL;
  85. inits : ARRAY [0 .. MaxInit] OF InitRec;
  86. nInit : CARDINAL;
  87. inBody : BOOLEAN;
  88. labs : ARRAY [0 .. MaxLab] OF INTEGER;
  89. nLab : CARDINAL;
  90. fixs : ARRAY [0 .. MaxFix] OF FixRec;
  91. nFix : CARDINAL;
  92. loopSt : ARRAY [0 .. MaxLoop] OF INTEGER;
  93. loopTop : CARDINAL;
  94. noSup : CARDINAL;
  95. noEmit : CARDINAL;
  96. actSt : ARRAY [0 .. MaxActDepth] OF ActFrame;
  97. actTop : CARDINAL;
  98. withTmps : ARRAY [0 .. 7] OF INTEGER;
  99. withTyps : ARRAY [0 .. 7] OF INTEGER;
  100. withTop : CARDINAL;
  101. procAddr : ARRAY [0 .. 64] OF INTEGER;
  102. maxNum : CARDINAL;
  103. mainAddr : CARDINAL;
  104. initNums : ARRAY [0 .. 7] OF INTEGER;
  105. nInits : CARDINAL;
  106. (* ---------------- byte helpers ---------------- *)
  107. PROCEDURE StrLen (s: ARRAY OF CHAR): CARDINAL;
  108. VAR i : CARDINAL;
  109. BEGIN
  110. i := 0;
  111. WHILE (i < HIGH(s)) & (s[i] # 0C) DO INC(i) END;
  112. RETURN i
  113. END StrLen;
  114. PROCEDURE StrCpy (VAR d: ARRAY OF CHAR; s: ARRAY OF CHAR);
  115. VAR i : CARDINAL;
  116. BEGIN
  117. i := 0;
  118. WHILE (i < HIGH(d)) & (i < HIGH(s)) & (s[i] # 0C) DO
  119. d[i] := s[i]; INC(i)
  120. END;
  121. IF i <= HIGH(d) THEN d[i] := 0C END
  122. END StrCpy;
  123. PROCEDURE EmitByte (b: CARDINAL);
  124. BEGIN
  125. IF noEmit > 0 THEN RETURN END;
  126. IF nCode <= MaxCode THEN
  127. code[nCode] := CHR(b MOD 256); INC(nCode)
  128. END
  129. END EmitByte;
  130. PROCEDURE EmitOp (o: CARDINAL);
  131. BEGIN
  132. EmitByte(o)
  133. END EmitOp;
  134. PROCEDURE EmitOpB (o, b: CARDINAL);
  135. BEGIN
  136. EmitByte(o); EmitByte(b)
  137. END EmitOpB;
  138. PROCEDURE EmitW64 (v: LONGCARD);
  139. VAR j : CARDINAL;
  140. BEGIN
  141. FOR j := 0 TO 7 DO
  142. EmitByte(VAL(CARDINAL, v MOD 256)); v := v DIV 256
  143. END
  144. END EmitW64;
  145. PROCEDURE EmitS64 (rel: INTEGER);
  146. (* Appends a signed 64-bit little-endian offset. *)
  147. VAR mag : CARDINAL;
  148. BEGIN
  149. IF rel >= 0 THEN EmitW64(VAL(LONGCARD, VAL(CARDINAL, rel)))
  150. ELSE
  151. IF rel = -2147483647 - 1 THEN mag := 80000000H
  152. ELSE mag := VAL(CARDINAL, -rel)
  153. END;
  154. EmitW64(0FFFFFFFFFFFFFFFFH - VAL(LONGCARD, mag) + 1H)
  155. END
  156. END EmitS64;
  157. PROCEDURE WriteS64At (off: CARDINAL; rel: INTEGER);
  158. (* Backpatches a signed offset into already-emitted code. *)
  159. VAR mag : CARDINAL;
  160. bits : LONGCARD;
  161. j : CARDINAL;
  162. BEGIN
  163. IF rel >= 0 THEN bits := VAL(LONGCARD, VAL(CARDINAL, rel))
  164. ELSE
  165. IF rel = -2147483647 - 1 THEN mag := 80000000H
  166. ELSE mag := VAL(CARDINAL, -rel)
  167. END;
  168. bits := 0FFFFFFFFFFFFFFFFH - VAL(LONGCARD, mag) + 1H
  169. END;
  170. FOR j := 0 TO 7 DO
  171. code[off + j] := CHR(VAL(CARDINAL, bits MOD 256));
  172. bits := bits DIV 256
  173. END
  174. END WriteS64At;
  175. PROCEDURE FindVar (name: ARRAY OF CHAR): INTEGER;
  176. VAR i : CARDINAL;
  177. BEGIN
  178. i := 0;
  179. WHILE i < nVars DO
  180. IF SymTab.Equal(gNames[i], name) THEN
  181. RETURN VAL(INTEGER, vBase[i])
  182. END;
  183. INC(i)
  184. END;
  185. RETURN -1
  186. END FindVar;
  187. PROCEDURE QualGlob (name: ARRAY OF CHAR; VAR q: ARRAY OF CHAR);
  188. VAR m: SymTab.Name;
  189. i, k: CARDINAL;
  190. BEGIN
  191. IF SymTab.InModule() & (SymTab.SymLev(name) > 0) THEN
  192. SymTab.CurModName(m);
  193. i := 0; k := 0;
  194. WHILE (k < HIGH(q)) & (m[i] # 0C) DO
  195. q[k] := m[i]; INC(k); INC(i)
  196. END;
  197. IF k <= HIGH(q) THEN q[k] := "."; INC(k) END;
  198. i := 0;
  199. WHILE (k < HIGH(q)) & (name[i] # 0C) DO
  200. q[k] := name[i]; INC(k); INC(i)
  201. END;
  202. IF k <= HIGH(q) THEN q[k] := 0C END
  203. ELSE
  204. StrCpy(q, name)
  205. END
  206. END QualGlob;
  207. PROCEDURE AssignSlots (name: ARRAY OF CHAR; n: CARDINAL): INTEGER;
  208. VAR base : CARDINAL;
  209. BEGIN
  210. IF nVars > MaxGlb THEN RETURN -1 END;
  211. IF n = 0 THEN
  212. StrCpy(gNames[nVars], name);
  213. vBase[nVars] := nGlb;
  214. vSize[nVars] := 0;
  215. INC(nVars);
  216. RETURN VAL(INTEGER, nGlb)
  217. END;
  218. IF nGlb + n - 1 > MaxGlb THEN RETURN -1 END;
  219. StrCpy(gNames[nVars], name);
  220. base := nGlb;
  221. vBase[nVars] := base;
  222. vSize[nVars] := n;
  223. INC(nVars);
  224. nGlb := nGlb + n;
  225. RETURN VAL(INTEGER, base)
  226. END AssignSlots;
  227. PROCEDURE AssignSlot (name: ARRAY OF CHAR): INTEGER;
  228. BEGIN
  229. RETURN AssignSlots(name, 1)
  230. END AssignSlot;
  231. (* ---------------- module / data section ---------------- *)
  232. PROCEDURE OpenModule (name: ARRAY OF CHAR);
  233. VAR i : CARDINAL;
  234. dummy : INTEGER;
  235. BEGIN
  236. StrCpy(modName, name);
  237. nCode := 0; nGlb := 0; nVars := 0; nInit := 0;
  238. nLab := 0; nFix := 0; loopTop := 0; noSup := 0; noEmit := 0;
  239. actTop := 0; withTop := 0;
  240. maxNum := 0; mainAddr := 0;
  241. nInits := 0;
  242. i := 0;
  243. WHILE i <= 64 DO procAddr[i] := -1; INC(i) END;
  244. inBody := FALSE;
  245. i := 0;
  246. WHILE i <= MaxGlb DO gNames[i][0] := 0C; INC(i) END;
  247. (* slots 0..3 belong to the print helper *)
  248. dummy := AssignSlot(""); dummy := AssignSlot("");
  249. dummy := AssignSlot(""); dummy := AssignSlot("")
  250. END OpenModule;
  251. PROCEDURE DeclVar (name: ARRAY OF CHAR);
  252. VAR idx : INTEGER;
  253. BEGIN
  254. idx := AssignSlot(name);
  255. IF idx < 0 THEN RETURN END
  256. END DeclVar;
  257. PROCEDURE DeclVarSized (name: ARRAY OF CHAR; slots: CARDINAL);
  258. VAR idx : INTEGER;
  259. q: ARRAY [0 .. 63] OF CHAR;
  260. BEGIN
  261. QualGlob(name, q);
  262. idx := AssignSlots(q, slots);
  263. IF idx < 0 THEN RETURN END
  264. END DeclVarSized;
  265. PROCEDURE BufInit (idx: INTEGER; kind: INTEGER; ival: INTEGER;
  266. bits: LONGCARD);
  267. BEGIN
  268. IF nInit > MaxInit THEN RETURN END;
  269. inits[nInit].idx := VAL(CARDINAL, idx);
  270. inits[nInit].kind := kind;
  271. inits[nInit].ival := ival;
  272. inits[nInit].bits := bits;
  273. INC(nInit)
  274. END BufInit;
  275. PROCEDURE DeclConst (name: ARRAY OF CHAR; lit: LitStr; t: INTEGER);
  276. VAR idx : INTEGER;
  277. cls : INTEGER;
  278. v : INTEGER;
  279. c : CARDINAL;
  280. b : LONGCARD;
  281. q: ARRAY [0 .. 63] OF CHAR;
  282. BEGIN
  283. QualGlob(name, q);
  284. idx := AssignSlot(q);
  285. IF idx < 0 THEN RETURN END;
  286. cls := SymTab.ClassOf(t);
  287. IF ~IsLit(lit) OR (cls = SymTab.ClStr) THEN
  288. BufInit(idx, 0, 0, 0H); RETURN
  289. END;
  290. IF cls = SymTab.ClReal THEN
  291. IF ParseReal(lit, b) THEN BufInit(idx, 1, 0, b)
  292. ELSE BufInit(idx, 1, 0, 0H)
  293. END
  294. ELSIF SymTab.Equal(lit, "TRUE") THEN BufInit(idx, 0, 1, 0H)
  295. ELSIF SymTab.Equal(lit, "FALSE") THEN BufInit(idx, 0, 0, 0H)
  296. ELSIF ParseInt(lit, v) THEN BufInit(idx, 0, v, 0H)
  297. ELSIF ParseCard(lit, c) THEN
  298. BufInit(idx, 1, 0, VAL(LONGCARD, c))
  299. ELSE BufInit(idx, 0, 0, 0H)
  300. END
  301. END DeclConst;
  302. PROCEDURE DeclConstInt (name: ARRAY OF CHAR; v: INTEGER);
  303. VAR idx : INTEGER;
  304. q: ARRAY [0 .. 63] OF CHAR;
  305. BEGIN
  306. QualGlob(name, q);
  307. idx := AssignSlot(q);
  308. IF idx < 0 THEN RETURN END;
  309. BufInit(idx, 0, v, 0H)
  310. END DeclConstInt;
  311. PROCEDURE PushValue (kind: INTEGER; ival: INTEGER; bits: LONGCARD);
  312. BEGIN
  313. IF kind = 0 THEN PushInt(ival) ELSE PushBits(bits) END
  314. END PushValue;
  315. PROCEDURE BeginBody;
  316. VAR i : CARDINAL;
  317. BEGIN
  318. IF inBody THEN RETURN END;
  319. inBody := TRUE;
  320. mainAddr := nCode;
  321. i := 0;
  322. WHILE i < nInit DO
  323. PushValue(inits[i].kind, inits[i].ival, inits[i].bits);
  324. EmitOpB(OPstoreGlb, inits[i].idx);
  325. INC(i)
  326. END;
  327. i := 0;
  328. WHILE i < nInits DO
  329. CallProc(initNums[i]);
  330. INC(i)
  331. END
  332. END BeginBody;
  333. (* ---------------- loads, stores, pushes ---------------- *)
  334. PROCEDURE LoadVar (name: ARRAY OF CHAR);
  335. VAR idx : INTEGER;
  336. q: ARRAY [0 .. 63] OF CHAR;
  337. BEGIN
  338. QualGlob(name, q);
  339. idx := FindVar(q);
  340. IF idx < 0 THEN EmitOp(OPimm0)
  341. ELSE EmitOpB(OPloadGlb, VAL(CARDINAL, idx))
  342. END
  343. END LoadVar;
  344. PROCEDURE StoreVar (name: ARRAY OF CHAR);
  345. VAR idx : INTEGER;
  346. q: ARRAY [0 .. 63] OF CHAR;
  347. BEGIN
  348. QualGlob(name, q);
  349. idx := FindVar(q);
  350. IF idx < 0 THEN EmitOp(OPext); EmitOp(SUBdrop)
  351. ELSE EmitOpB(OPstoreGlb, VAL(CARDINAL, idx))
  352. END
  353. END StoreVar;
  354. PROCEDURE LoadTemp (t: INTEGER);
  355. BEGIN
  356. EmitOpB(OPloadGlb, VAL(CARDINAL, t))
  357. END LoadTemp;
  358. PROCEDURE StoreTemp (t: INTEGER);
  359. BEGIN
  360. EmitOpB(OPstoreGlb, VAL(CARDINAL, t))
  361. END StoreTemp;
  362. PROCEDURE TempGlobal (): INTEGER;
  363. VAR idx : INTEGER;
  364. BEGIN
  365. idx := AssignSlot("");
  366. IF idx < 0 THEN RETURN 4 END;
  367. RETURN idx
  368. END TempGlobal;
  369. (* ---------------- frames and procedures ---------------- *)
  370. PROCEDURE EmitSlotB (op: CARDINAL; sl: INTEGER);
  371. (* Byte operand for a (possibly negative) frame slot. *)
  372. BEGIN
  373. IF sl >= 0 THEN EmitOpB(op, VAL(CARDINAL, sl))
  374. ELSE EmitOpB(op, 256 - VAL(CARDINAL, -sl))
  375. END
  376. END EmitSlotB;
  377. PROCEDURE LoadLocal (sl: INTEGER);
  378. BEGIN
  379. EmitSlotB(OPloadLocal, sl)
  380. END LoadLocal;
  381. PROCEDURE StoreLocal (sl: INTEGER);
  382. BEGIN
  383. EmitSlotB(OPstoreLocal, sl)
  384. END StoreLocal;
  385. PROCEDURE LoadIndir0;
  386. BEGIN
  387. EmitOp(OPloadIndir0)
  388. END LoadIndir0;
  389. PROCEDURE StoreIndir0;
  390. BEGIN
  391. EmitOp(OPstoreIndir0)
  392. END StoreIndir0;
  393. PROCEDURE FrameAddr (sl: INTEGER; np: CARDINAL);
  394. (* Pushes (display-frame(np) + slot*8): 11H np, then the offset. *)
  395. BEGIN
  396. EmitOpB(OPloadOuterN, np);
  397. IF sl >= 0 THEN EmitOpB(OPstkAddr, VAL(CARDINAL, sl))
  398. ELSE
  399. PushInt(sl * 8);
  400. EmitOp(OPadd)
  401. END
  402. END FrameAddr;
  403. PROCEDURE LoadIndir;
  404. BEGIN
  405. EmitOp(OPloadIndir)
  406. END LoadIndir;
  407. PROCEDURE StoreIndir;
  408. BEGIN
  409. EmitOp(OPstoreIndir)
  410. END StoreIndir;
  411. PROCEDURE LocalAddr (sl: INTEGER);
  412. BEGIN
  413. EmitSlotB(OPlocalAddr, sl)
  414. END LocalAddr;
  415. PROCEDURE GlobalAddr (name: ARRAY OF CHAR);
  416. VAR idx : INTEGER;
  417. q: ARRAY [0 .. 63] OF CHAR;
  418. BEGIN
  419. QualGlob(name, q);
  420. idx := FindVar(q);
  421. IF idx < 0 THEN EmitOp(OPimm0)
  422. ELSE EmitOpB(OPglobalAddr, VAL(CARDINAL, idx))
  423. END
  424. END GlobalAddr;
  425. PROCEDURE PushAddr (name: ARRAY OF CHAR);
  426. (* VAR-actual address: slot contents for VAR params, slot address
  427. for plain variables; display-aware. *)
  428. VAR k, d, D, sl : INTEGER;
  429. np : CARDINAL;
  430. BEGIN
  431. k := SymTab.SymKind(name);
  432. d := SymTab.SymDepth(name);
  433. D := SymTab.CurDepth();
  434. sl := SymTab.SymSlot(name);
  435. IF (k # SymTab.KindVar) & (k # SymTab.KindParam)
  436. & (k # SymTab.KindVarPar) THEN
  437. EmitOp(OPimm0); RETURN
  438. END;
  439. IF (k = SymTab.KindVarPar)
  440. OR ((k = SymTab.KindParam)
  441. & SymTab.IsOpen(SymTab.SymType(name))) THEN
  442. IF D = d THEN LoadLocal(sl)
  443. ELSE
  444. np := VAL(CARDINAL, D - 1 - d);
  445. FrameAddr(sl, np);
  446. LoadIndir
  447. END
  448. ELSE
  449. IF d = 0 THEN GlobalAddr(name)
  450. ELSIF D = d THEN LocalAddr(sl)
  451. ELSE
  452. np := VAL(CARDINAL, D - 1 - d);
  453. FrameAddr(sl, np)
  454. END
  455. END
  456. END PushAddr;
  457. PROCEDURE StoreSetup (name: ARRAY OF CHAR);
  458. (* Early address for indirect stores; call before the value code. *)
  459. VAR k, d, D, sl : INTEGER;
  460. np : CARDINAL;
  461. BEGIN
  462. k := SymTab.SymKind(name);
  463. IF (k # SymTab.KindVar) & (k # SymTab.KindParam)
  464. & (k # SymTab.KindVarPar) THEN
  465. RETURN
  466. END;
  467. d := SymTab.SymDepth(name);
  468. D := SymTab.CurDepth();
  469. sl := SymTab.SymSlot(name);
  470. IF k = SymTab.KindVarPar THEN
  471. IF D = d THEN LoadLocal(sl)
  472. ELSE
  473. np := VAL(CARDINAL, D - 1 - d);
  474. FrameAddr(sl, np);
  475. LoadIndir
  476. END
  477. ELSIF (d # 0) & (D # d) THEN
  478. np := VAL(CARDINAL, D - 1 - d);
  479. FrameAddr(sl, np)
  480. END
  481. END StoreSetup;
  482. PROCEDURE StoreFinish (name: ARRAY OF CHAR);
  483. (* Completes the store; call after the value code. *)
  484. VAR k, d, D, sl : INTEGER;
  485. BEGIN
  486. k := SymTab.SymKind(name);
  487. IF (k # SymTab.KindVar) & (k # SymTab.KindParam)
  488. & (k # SymTab.KindVarPar) THEN
  489. RETURN
  490. END;
  491. d := SymTab.SymDepth(name);
  492. D := SymTab.CurDepth();
  493. sl := SymTab.SymSlot(name);
  494. IF d = 0 THEN StoreVar(name)
  495. ELSIF D = d THEN
  496. IF k = SymTab.KindVarPar THEN StoreIndir0
  497. ELSE StoreLocal(sl)
  498. END
  499. ELSE
  500. IF k = SymTab.KindVarPar THEN StoreIndir0
  501. ELSE StoreIndir
  502. END
  503. END
  504. END StoreFinish;
  505. PROCEDURE PushVar (name: ARRAY OF CHAR);
  506. (* Frame-aware value load (see PushAddr for the address twin). *)
  507. VAR k, d, D, sl : INTEGER;
  508. np : CARDINAL;
  509. BEGIN
  510. k := SymTab.SymKind(name);
  511. d := SymTab.SymDepth(name);
  512. D := SymTab.CurDepth();
  513. sl := SymTab.SymSlot(name);
  514. IF (k # SymTab.KindVar) & (k # SymTab.KindParam)
  515. & (k # SymTab.KindVarPar) THEN
  516. EmitOp(OPimm0); RETURN
  517. END;
  518. IF d = 0 THEN LoadVar(name)
  519. ELSIF D = d THEN
  520. IF k = SymTab.KindVarPar THEN
  521. LoadLocal(sl); LoadIndir0
  522. ELSE LoadLocal(sl)
  523. END
  524. ELSE
  525. np := VAL(CARDINAL, D - 1 - d);
  526. FrameAddr(sl, np);
  527. LoadIndir;
  528. IF k = SymTab.KindVarPar THEN LoadIndir0 END
  529. END
  530. END PushVar;
  531. PROCEDURE ProcEntry (num: INTEGER; nLoc: CARDINAL);
  532. VAR k : CARDINAL;
  533. BEGIN
  534. IF (num >= 0) & (num <= 64) THEN
  535. procAddr[num] := VAL(INTEGER, nCode);
  536. IF VAL(CARDINAL, num) > maxNum THEN
  537. maxNum := VAL(CARDINAL, num)
  538. END
  539. END;
  540. IF nLoc > 255 THEN k := 255 ELSE k := nLoc END;
  541. EmitOpB(OPenter, 255 - k)
  542. END ProcEntry;
  543. PROCEDURE CallProc (num: INTEGER);
  544. BEGIN
  545. EmitOpB(OPprocCall, VAL(CARDINAL, num))
  546. END CallProc;
  547. PROCEDURE CallNested (num: INTEGER);
  548. BEGIN
  549. EmitOpB(OPnestedCall, VAL(CARDINAL, num))
  550. END CallNested;
  551. PROCEDURE CallDisplay (num: INTEGER; np: CARDINAL);
  552. BEGIN
  553. EmitOpB(OPloadOuterN, np);
  554. EmitOpB(OPcallFrame, VAL(CARDINAL, num))
  555. END CallDisplay;
  556. PROCEDURE ModInitBegin (): INTEGER;
  557. (* Opens a module init body as a parameterless proper procedure
  558. (module bodies declare no locals; globals are used directly).
  559. Records its number for the startup calls in BeginBody.
  560. The number comes from SymTab's shared proc pool (never
  561. maxNum+1: a later procedure body would otherwise overwrite
  562. this init's table slot on emission). -1 when full. *)
  563. VAR num : INTEGER;
  564. BEGIN
  565. IF nInits > 7 THEN RETURN -1 END;
  566. num := SymTab.AllocInitNum();
  567. IF (num < 1) OR (num > 64) THEN RETURN -1 END;
  568. initNums[nInits] := num;
  569. INC(nInits);
  570. ProcEntry(num, 0);
  571. RETURN num
  572. END ModInitBegin;
  573. PROCEDURE ModInitEnd (num: INTEGER);
  574. (* Closes a module init body (no-op for num < 0). *)
  575. BEGIN
  576. IF num >= 0 THEN Leave(0, FALSE) END
  577. END ModInitEnd;
  578. PROCEDURE Leave (nPar: CARDINAL; func: BOOLEAN);
  579. BEGIN
  580. IF nPar > 255 THEN nPar := 255 END;
  581. IF func THEN EmitOpB(OPfctLeave, nPar)
  582. ELSE EmitOpB(OPprocLeave, nPar)
  583. END
  584. END Leave;
  585. (* ---------------- actual parameters ---------------- *)
  586. PROCEDURE ActFrameIdx (): CARDINAL;
  587. (* Active frame, capped (nesting past the cap reuses the top). *)
  588. BEGIN
  589. IF actTop = 0 THEN RETURN 0 END;
  590. IF actTop - 1 > MaxActDepth THEN RETURN MaxActDepth END;
  591. RETURN actTop - 1
  592. END ActFrameIdx;
  593. PROCEDURE ActIsVarNext (): BOOLEAN;
  594. VAR fr, i: CARDINAL;
  595. BEGIN
  596. IF actTop = 0 THEN RETURN FALSE END;
  597. fr := ActFrameIdx();
  598. IF ~actSt[fr].known THEN RETURN FALSE END;
  599. i := actSt[fr].n;
  600. IF i >= actSt[fr].nf THEN RETURN FALSE END;
  601. RETURN SymTab.ParamIsVar(actSt[fr].pn, i)
  602. END ActIsVarNext;
  603. PROCEDURE NoteSfx (b: BOOLEAN);
  604. VAR fr, i: CARDINAL;
  605. BEGIN
  606. IF actTop = 0 THEN RETURN END;
  607. fr := ActFrameIdx();
  608. i := actSt[fr].n;
  609. IF i <= MaxActN THEN actSt[fr].sfxs[i] := b END
  610. END NoteSfx;
  611. PROCEDURE NoteIdx (b: BOOLEAN);
  612. VAR fr, i: CARDINAL;
  613. BEGIN
  614. IF actTop = 0 THEN RETURN END;
  615. fr := ActFrameIdx();
  616. i := actSt[fr].n;
  617. IF i <= MaxActN THEN actSt[fr].idxs[i] := b END
  618. END NoteIdx;
  619. PROCEDURE ActBegin (pn: ARRAY OF CHAR);
  620. VAR fr : CARDINAL;
  621. k : CARDINAL;
  622. BEGIN
  623. fr := actTop;
  624. IF fr > MaxActDepth THEN fr := MaxActDepth
  625. ELSE INC(actTop)
  626. END;
  627. StrCpy(actSt[fr].pn, pn);
  628. actSt[fr].n := 0;
  629. k := 0;
  630. WHILE k <= MaxActN DO
  631. actSt[fr].lens[k] := -1;
  632. actSt[fr].addrs[k] := -1;
  633. actSt[fr].sfxs[k] := FALSE;
  634. actSt[fr].idxs[k] := TRUE;
  635. INC(k)
  636. END;
  637. actSt[fr].known := SymTab.Lookup(pn)
  638. & (SymTab.SymKind(pn) = SymTab.KindProc);
  639. IF actSt[fr].known THEN actSt[fr].nf := SymTab.ProcNPar(pn)
  640. ELSE actSt[fr].nf := 0
  641. END;
  642. actSt[fr].byNum := FALSE;
  643. actSt[fr].num := -1
  644. END ActBegin;
  645. PROCEDURE ActBeginNum (num: INTEGER);
  646. (* Actuals for a procedure known by number (exported module procs,
  647. whose names vanish with the module body scope). *)
  648. VAR fr : CARDINAL;
  649. k : CARDINAL;
  650. BEGIN
  651. fr := actTop;
  652. IF fr > MaxActDepth THEN fr := MaxActDepth
  653. ELSE INC(actTop)
  654. END;
  655. actSt[fr].pn[0] := 0C;
  656. actSt[fr].n := 0;
  657. k := 0;
  658. WHILE k <= MaxActN DO
  659. actSt[fr].lens[k] := -1;
  660. actSt[fr].addrs[k] := -1;
  661. actSt[fr].sfxs[k] := FALSE;
  662. actSt[fr].idxs[k] := TRUE;
  663. INC(k)
  664. END;
  665. actSt[fr].known := SymTab.ProcValid(num);
  666. IF actSt[fr].known THEN actSt[fr].nf := SymTab.ProcNParByNum(num)
  667. ELSE actSt[fr].nf := 0
  668. END;
  669. actSt[fr].byNum := TRUE;
  670. actSt[fr].num := num
  671. END ActBeginNum;
  672. PROCEDURE ActFormalType (fr, i: CARDINAL): INTEGER;
  673. (* i-th formal type of the frame's callee, by number or by name. *)
  674. BEGIN
  675. IF actSt[fr].byNum THEN
  676. RETURN SymTab.ParamTypeByNum(actSt[fr].num, i)
  677. ELSE
  678. RETURN SymTab.ParamType(actSt[fr].pn, i)
  679. END
  680. END ActFormalType;
  681. PROCEDURE ActFormalIsVar (fr, i: CARDINAL): BOOLEAN;
  682. BEGIN
  683. IF actSt[fr].byNum THEN
  684. RETURN SymTab.ParamIsVarByNum(actSt[fr].num, i)
  685. ELSE
  686. RETURN SymTab.ParamIsVar(actSt[fr].pn, i)
  687. END
  688. END ActFormalIsVar;
  689. PROCEDURE StashAddr;
  690. (* Duplicates the address on top of stack into a per-actual temp of
  691. the current call frame (for VAR actuals with tails: a[i], p^,
  692. fields). The ATG calls this at the Fact tail, when the address is
  693. complete but not yet loaded. Recorded as -1 when unused. *)
  694. VAR fr, i : CARDINAL;
  695. tmp : INTEGER;
  696. BEGIN
  697. IF actTop = 0 THEN RETURN END;
  698. fr := ActFrameIdx();
  699. i := actSt[fr].n;
  700. IF i > MaxActN THEN RETURN END;
  701. tmp := TempGlobal();
  702. actSt[fr].addrs[i] := tmp;
  703. EmitOp(OPdup);
  704. StoreTemp(tmp)
  705. END StashAddr;
  706. PROCEDURE ClrStash;
  707. (* Invalidates the stashed address of the current actual: a
  708. value-combining operator followed, so the address no longer
  709. denotes the actual. Conservative no-op outside calls. *)
  710. VAR fr, i : CARDINAL;
  711. BEGIN
  712. IF actTop = 0 THEN RETURN END;
  713. fr := ActFrameIdx();
  714. i := actSt[fr].n;
  715. IF i <= MaxActN THEN actSt[fr].addrs[i] := -1 END
  716. END ClrStash;
  717. PROCEDURE ActValue (t: INTEGER; v: BOOLEAN;
  718. vn: ARRAY OF CHAR): INTEGER;
  719. VAR fr : CARDINAL;
  720. i : CARDINAL;
  721. ftyp : INTEGER;
  722. fv : BOOLEAN;
  723. err : INTEGER;
  724. BEGIN
  725. err := 0;
  726. fr := ActFrameIdx();
  727. i := actSt[fr].n;
  728. IF i > MaxActN THEN
  729. EmitOp(OPext); EmitOp(SUBdrop);
  730. actSt[fr].n := i + 1;
  731. RETURN 1
  732. END;
  733. IF actSt[fr].known & (i < actSt[fr].nf) THEN
  734. ftyp := ActFormalType(fr, i);
  735. fv := ActFormalIsVar(fr, i);
  736. IF SymTab.IsOpen(ftyp) THEN
  737. IF (t = SymTab.InvalidType)
  738. OR SymTab.IsOpen(t)
  739. OR (SymTab.ClassOf(t) # SymTab.ClArray) THEN
  740. err := 1
  741. ELSIF ~SymTab.SameType(SymTab.ArrayElem(t),
  742. SymTab.ArrayElem(ftyp)) THEN
  743. err := 1
  744. ELSIF fv & ~v & (actSt[fr].addrs[i] < 0) THEN
  745. err := 1
  746. END;
  747. IF (t # SymTab.InvalidType)
  748. & (SymTab.ClassOf(t) = SymTab.ClArray)
  749. & ~SymTab.IsOpen(t) THEN
  750. PushInt(VAL(INTEGER, SymTab.ArrayLen(t)))
  751. ELSE
  752. PushInt(0)
  753. END;
  754. actSt[fr].lens[i] := TempGlobal();
  755. StoreTemp(actSt[fr].lens[i]);
  756. IF fv THEN
  757. IF (err = 0) & (actSt[fr].addrs[i] >= 0) THEN
  758. (* tailed array actual: its address is already on top *)
  759. ELSE
  760. EmitOp(OPext); EmitOp(SUBdrop);
  761. PushAddr(vn)
  762. END
  763. END
  764. ELSIF fv THEN
  765. IF actSt[fr].addrs[i] >= 0 THEN
  766. IF (t # SymTab.InvalidType)
  767. & ((SymTab.ClassOf(t) = SymTab.ClArray)
  768. OR (SymTab.ClassOf(t) = SymTab.ClRecord)) THEN
  769. (* tailed composite actual: address already on top *)
  770. ELSIF SymTab.SameType(t, ftyp) THEN
  771. EmitOp(OPext); EmitOp(SUBdrop);
  772. LoadTemp(actSt[fr].addrs[i])
  773. ELSE
  774. err := 1;
  775. EmitOp(OPext); EmitOp(SUBdrop);
  776. PushAddr(vn)
  777. END
  778. ELSE
  779. IF ~v THEN err := 1
  780. ELSIF ~SymTab.SameType(t, ftyp) THEN err := 1
  781. END;
  782. EmitOp(OPext); EmitOp(SUBdrop);
  783. PushAddr(vn)
  784. END
  785. ELSE
  786. IF ~SymTab.Assignable(t, ftyp) THEN err := 1
  787. ELSIF SymTab.IsIntFamily(t)
  788. & (SymTab.ClassOf(ftyp) = SymTab.ClReal) THEN
  789. IntToReal
  790. END
  791. END
  792. END;
  793. actSt[fr].tmps[i] := TempGlobal();
  794. StoreTemp(actSt[fr].tmps[i]);
  795. actSt[fr].n := i + 1;
  796. RETURN err
  797. END ActValue;
  798. PROCEDURE ActEnd (pn: ARRAY OF CHAR; sfx, inExpr: BOOLEAN): INTEGER;
  799. VAR fr : CARDINAL;
  800. i : CARDINAL;
  801. n, num, F, d : INTEGER;
  802. BEGIN
  803. fr := ActFrameIdx();
  804. IF actTop > 0 THEN DEC(actTop) END;
  805. n := VAL(INTEGER, actSt[fr].n);
  806. IF ~SymTab.Lookup(pn) THEN
  807. IF inExpr THEN EmitOp(OPimm0) END;
  808. RETURN 0
  809. END;
  810. IF (SymTab.SymKind(pn) # SymTab.KindProc)
  811. OR sfx
  812. OR (n # VAL(INTEGER, SymTab.ProcNPar(pn))) THEN
  813. IF inExpr THEN EmitOp(OPimm0) END;
  814. RETURN 1
  815. END;
  816. IF inExpr & (SymTab.ProcRet(pn) = SymTab.InvalidType) THEN
  817. EmitOp(OPimm0);
  818. RETURN 1
  819. END;
  820. i := actSt[fr].n;
  821. WHILE i > 0 DO
  822. DEC(i);
  823. IF i <= MaxActN THEN
  824. IF (actSt[fr].lens[i] >= 0)
  825. & SymTab.IsOpen(SymTab.ParamType(pn, i)) THEN
  826. LoadTemp(actSt[fr].lens[i]);
  827. LoadTemp(actSt[fr].tmps[i])
  828. ELSE
  829. LoadTemp(actSt[fr].tmps[i])
  830. END
  831. END
  832. END;
  833. num := SymTab.ProcNum(pn);
  834. F := SymTab.CurDepth();
  835. d := SymTab.SymDepth(pn);
  836. IF d = 0 THEN CallProc(num)
  837. ELSIF F = d THEN CallNested(num)
  838. ELSE CallDisplay(num, VAL(CARDINAL, F - 1 - d))
  839. END;
  840. IF ~inExpr & (SymTab.ProcRet(pn) # SymTab.InvalidType) THEN
  841. EmitOp(OPext); EmitOp(SUBdrop)
  842. END;
  843. RETURN 0
  844. END ActEnd;
  845. PROCEDURE ActEndNum (num: INTEGER; inExpr: BOOLEAN): INTEGER;
  846. (* Ends a by-number call (module procedures are always global-level,
  847. so a plain global call is correct; the M. prefix is qualification,
  848. not a tail, hence no sfx check). *)
  849. VAR fr : CARDINAL;
  850. i : CARDINAL;
  851. n : INTEGER;
  852. BEGIN
  853. fr := ActFrameIdx();
  854. IF actTop > 0 THEN DEC(actTop) END;
  855. n := VAL(INTEGER, actSt[fr].n);
  856. IF ~SymTab.ProcValid(num)
  857. OR (n # VAL(INTEGER, SymTab.ProcNParByNum(num))) THEN
  858. IF inExpr THEN EmitOp(OPimm0) END;
  859. RETURN 1
  860. END;
  861. IF inExpr & (SymTab.ProcRetByNum(num) = SymTab.InvalidType) THEN
  862. EmitOp(OPimm0);
  863. RETURN 1
  864. END;
  865. i := actSt[fr].n;
  866. WHILE i > 0 DO
  867. DEC(i);
  868. IF i <= MaxActN THEN
  869. IF (actSt[fr].lens[i] >= 0)
  870. & SymTab.IsOpen(SymTab.ParamTypeByNum(num, i)) THEN
  871. LoadTemp(actSt[fr].lens[i]);
  872. LoadTemp(actSt[fr].tmps[i])
  873. ELSE
  874. LoadTemp(actSt[fr].tmps[i])
  875. END
  876. END
  877. END;
  878. CallProc(num);
  879. IF ~inExpr & (SymTab.ProcRetByNum(num) # SymTab.InvalidType) THEN
  880. EmitOp(OPext); EmitOp(SUBdrop)
  881. END;
  882. RETURN 0
  883. END ActEndNum;
  884. PROCEDURE EmitMag (c: CARDINAL);
  885. BEGIN
  886. IF c <= 255 THEN EmitOpB(OPimmB, c)
  887. ELSE EmitOp(OPimmW); EmitW64(VAL(LONGCARD, c))
  888. END
  889. END EmitMag;
  890. PROCEDURE PushInt (v: INTEGER);
  891. VAR mag : CARDINAL;
  892. BEGIN
  893. IF (v >= 0) & (v <= 15) THEN EmitOp(OPimm0 + VAL(CARDINAL, v))
  894. ELSIF v < 0 THEN
  895. IF v = -2147483647 - 1 THEN mag := 80000000H
  896. ELSE mag := VAL(CARDINAL, -v)
  897. END;
  898. EmitOp(OPimm0); EmitMag(mag); EmitOp(OPsub)
  899. ELSE EmitMag(VAL(CARDINAL, v))
  900. END
  901. END PushInt;
  902. PROCEDURE PushBits (b: LONGCARD);
  903. BEGIN
  904. EmitOp(OPimmW); EmitW64(b)
  905. END PushBits;
  906. (* ---------------- literal parsing ---------------- *)
  907. PROCEDURE DigVal (ch: CHAR): INTEGER;
  908. BEGIN
  909. IF (ch >= "0") & (ch <= "9") THEN RETURN ORD(ch) - ORD("0") END;
  910. IF (ch >= "A") & (ch <= "F") THEN RETURN ORD(ch) - ORD("A") + 10 END;
  911. IF (ch >= "a") & (ch <= "f") THEN RETURN ORD(ch) - ORD("a") + 10 END;
  912. RETURN -1
  913. END DigVal;
  914. PROCEDURE ParseCard (s: ARRAY OF CHAR; VAR v: CARDINAL): BOOLEAN;
  915. VAR i, n : CARDINAL;
  916. hex : BOOLEAN;
  917. d : INTEGER;
  918. acc : LONGCARD;
  919. BEGIN
  920. v := 0;
  921. n := StrLen(s);
  922. IF n = 0 THEN RETURN FALSE END;
  923. hex := (s[n - 1] = "H") OR (s[n - 1] = "h");
  924. IF hex THEN DEC(n) END;
  925. IF n = 0 THEN RETURN FALSE END;
  926. acc := 0H; i := 0;
  927. WHILE i < n DO
  928. d := DigVal(s[i]);
  929. IF hex THEN
  930. IF d < 0 THEN RETURN FALSE END;
  931. acc := acc * 16 + VAL(LONGCARD, VAL(CARDINAL, d))
  932. ELSE
  933. IF (d < 0) OR (d > 9) THEN RETURN FALSE END;
  934. acc := acc * 10 + VAL(LONGCARD, VAL(CARDINAL, d))
  935. END;
  936. IF acc > 0FFFFFFFFH THEN RETURN FALSE END;
  937. INC(i)
  938. END;
  939. v := VAL(CARDINAL, acc);
  940. RETURN TRUE
  941. END ParseCard;
  942. PROCEDURE ParseInt (s: ARRAY OF CHAR; VAR v: INTEGER): BOOLEAN;
  943. VAR i : CARDINAL;
  944. neg : BOOLEAN;
  945. t : ARRAY [0 .. 63] OF CHAR;
  946. c : CARDINAL;
  947. lim : LONGCARD;
  948. BEGIN
  949. v := 0;
  950. IF (StrLen(s) = 0) THEN RETURN FALSE END;
  951. neg := s[0] = "-";
  952. IF neg THEN
  953. i := 1;
  954. WHILE s[i] # 0C DO
  955. IF i - 1 > HIGH(t) THEN RETURN FALSE END;
  956. t[i - 1] := s[i]; INC(i)
  957. END;
  958. IF i - 1 > HIGH(t) THEN RETURN FALSE END;
  959. t[i - 1] := 0C
  960. ELSE StrCpy(t, s)
  961. END;
  962. IF ~ParseCard(t, c) THEN RETURN FALSE END;
  963. IF neg THEN lim := 80000000H ELSE lim := 7FFFFFFFH END;
  964. IF VAL(LONGCARD, c) > lim THEN RETURN FALSE END;
  965. IF neg THEN
  966. IF VAL(LONGCARD, c) = 80000000H THEN v := -2147483647 - 1
  967. ELSE v := -VAL(INTEGER, c)
  968. END
  969. ELSE v := VAL(INTEGER, c)
  970. END;
  971. RETURN TRUE
  972. END ParseInt;
  973. PROCEDURE ParseReal (s: ARRAY OF CHAR; VAR b: LONGCARD): BOOLEAN;
  974. VAR i : CARDINAL;
  975. neg, esign : BOOLEAN;
  976. m, scale : REAL;
  977. e, d : CARDINAL;
  978. rv : RealView;
  979. BEGIN
  980. b := 0H;
  981. i := 0; neg := FALSE;
  982. IF s[0] = "-" THEN neg := TRUE; INC(i) END;
  983. IF (s[i] < "0") OR (s[i] > "9") THEN RETURN FALSE END;
  984. m := 0.0;
  985. WHILE (s[i] >= "0") & (s[i] <= "9") DO
  986. m := m * 10.0 + VAL(REAL, VAL(CARDINAL, ORD(s[i]) - ORD("0")));
  987. INC(i)
  988. END;
  989. IF s[i] = "." THEN
  990. INC(i);
  991. IF (s[i] < "0") OR (s[i] > "9") THEN RETURN FALSE END;
  992. scale := 10.0;
  993. WHILE (s[i] >= "0") & (s[i] <= "9") DO
  994. m := m + VAL(REAL, VAL(CARDINAL, ORD(s[i]) - ORD("0"))) / scale;
  995. scale := scale * 10.0;
  996. INC(i)
  997. END
  998. END;
  999. IF (s[i] = "E") OR (s[i] = "e") THEN
  1000. INC(i); esign := FALSE;
  1001. IF s[i] = "+" THEN INC(i)
  1002. ELSIF s[i] = "-" THEN esign := TRUE; INC(i)
  1003. END;
  1004. IF (s[i] < "0") OR (s[i] > "9") THEN RETURN FALSE END;
  1005. e := 0;
  1006. WHILE (s[i] >= "0") & (s[i] <= "9") DO
  1007. d := VAL(CARDINAL, ORD(s[i]) - ORD("0"));
  1008. IF e <= 9999 THEN e := e * 10 + d END;
  1009. INC(i)
  1010. END;
  1011. WHILE e > 0 DO
  1012. IF esign THEN m := m / 10.0 ELSE m := m * 10.0 END;
  1013. DEC(e)
  1014. END
  1015. END;
  1016. IF s[i] # 0C THEN RETURN FALSE END;
  1017. IF neg THEN m := -m END;
  1018. rv.r := m;
  1019. b := rv.w;
  1020. RETURN TRUE
  1021. END ParseReal;
  1022. PROCEDURE CharOrd (s: ARRAY OF CHAR): INTEGER;
  1023. BEGIN
  1024. IF StrLen(s) >= 2 THEN RETURN ORD(s[1]) END;
  1025. RETURN 0
  1026. END CharOrd;
  1027. PROCEDURE NegFold (a: ARRAY OF CHAR; VAR q: LitStr);
  1028. (* Safe for a and q being the same variable. *)
  1029. VAR tmp : LitStr;
  1030. i, j : CARDINAL;
  1031. BEGIN
  1032. StrCpy(tmp, a);
  1033. IF StrLen(tmp) = 0 THEN StrCpy(q, ""); RETURN END;
  1034. IF tmp[0] = "-" THEN
  1035. i := 1; j := 0;
  1036. WHILE (tmp[i] # 0C) & (j < HIGH(q)) DO
  1037. q[j] := tmp[i]; INC(i); INC(j)
  1038. END;
  1039. IF j <= HIGH(q) THEN q[j] := 0C END
  1040. ELSE
  1041. StrCpy(q, "-");
  1042. i := 0; j := StrLen(q);
  1043. WHILE (tmp[i] # 0C) & (j < HIGH(q)) DO
  1044. q[j] := tmp[i]; INC(i); INC(j)
  1045. END;
  1046. IF j <= HIGH(q) THEN q[j] := 0C END
  1047. END
  1048. END NegFold;
  1049. PROCEDURE IsLit (s: ARRAY OF CHAR): BOOLEAN;
  1050. BEGIN
  1051. RETURN StrLen(s) > 0
  1052. END IsLit;
  1053. (* ---------------- operators ---------------- *)
  1054. PROCEDURE Add;
  1055. BEGIN EmitOp(OPadd) END Add;
  1056. PROCEDURE Sub;
  1057. BEGIN EmitOp(OPsub) END Sub;
  1058. PROCEDURE MulU;
  1059. BEGIN EmitOp(OPumul) END MulU;
  1060. PROCEDURE DivU;
  1061. BEGIN EmitOp(OPudiv) END DivU;
  1062. PROCEDURE ModU;
  1063. BEGIN EmitOp(OPumod) END ModU;
  1064. PROCEDURE MulI;
  1065. BEGIN EmitOp(OPimul) END MulI;
  1066. PROCEDURE DivI;
  1067. BEGIN EmitOp(OPidiv) END DivI;
  1068. PROCEDURE ModI (t: INTEGER);
  1069. (* [a b] -> a MOD b (truncation) via temp t. *)
  1070. BEGIN
  1071. StoreTemp(t);
  1072. EmitOp(OPdup);
  1073. LoadTemp(t);
  1074. EmitOp(OPidiv);
  1075. LoadTemp(t);
  1076. EmitOp(OPimul);
  1077. EmitOp(OPsub)
  1078. END ModI;
  1079. PROCEDURE RealAdd;
  1080. BEGIN EmitOp(OPrAdd) END RealAdd;
  1081. PROCEDURE RealSub;
  1082. BEGIN EmitOp(OPrSub) END RealSub;
  1083. PROCEDURE RealMul;
  1084. BEGIN EmitOp(OPrMul) END RealMul;
  1085. PROCEDURE RealDiv;
  1086. BEGIN EmitOp(OPrDiv) END RealDiv;
  1087. PROCEDURE And;
  1088. BEGIN EmitOp(OPand) END And;
  1089. PROCEDURE Or;
  1090. BEGIN EmitOp(OPor) END Or;
  1091. PROCEDURE Not;
  1092. BEGIN EmitOp(OPnot) END Not;
  1093. PROCEDURE Power2;
  1094. BEGIN EmitOp(OPpower2) END Power2;
  1095. PROCEDURE FieldMask;
  1096. BEGIN EmitOp(OPext); EmitOp(04H) END FieldMask;
  1097. PROCEDURE BitIn;
  1098. BEGIN EmitOp(OPbitIn) END BitIn;
  1099. PROCEDURE Eq;
  1100. BEGIN EmitOp(OPeq) END Eq;
  1101. PROCEDURE Neq;
  1102. BEGIN EmitOp(OPne) END Neq;
  1103. PROCEDURE ULt;
  1104. BEGIN EmitOp(OPult) END ULt;
  1105. PROCEDURE ULe;
  1106. BEGIN EmitOp(OPule) END ULe;
  1107. PROCEDURE UGt;
  1108. BEGIN EmitOp(OPugt) END UGt;
  1109. PROCEDURE UGe;
  1110. BEGIN EmitOp(OPuge) END UGe;
  1111. PROCEDURE ILt;
  1112. BEGIN EmitOp(OPilt) END ILt;
  1113. PROCEDURE ILe;
  1114. BEGIN EmitOp(OPile) END ILe;
  1115. PROCEDURE IGt;
  1116. BEGIN EmitOp(OPigt) END IGt;
  1117. PROCEDURE IGe;
  1118. BEGIN EmitOp(OPige) END IGe;
  1119. PROCEDURE RealEq;
  1120. (* [r1 r2] -> (r1 = r2): cmp, or, not. *)
  1121. BEGIN EmitOp(OPrCmp); EmitOp(OPor); EmitOp(OPnot) END RealEq;
  1122. PROCEDURE RealNe;
  1123. (* [r1 r2] -> (r1 # r2): cmp, or. *)
  1124. BEGIN EmitOp(OPrCmp); EmitOp(OPor) END RealNe;
  1125. PROCEDURE RealLt;
  1126. (* [gt lt] -> lt: swap, drop. *)
  1127. BEGIN EmitOp(OPswap); EmitOp(OPext); EmitOp(SUBdrop) END RealLt;
  1128. PROCEDURE RealLe;
  1129. (* [gt lt] -> NOT gt: drop, not. *)
  1130. BEGIN EmitOp(OPext); EmitOp(SUBdrop); EmitOp(OPnot) END RealLe;
  1131. PROCEDURE RealGt;
  1132. (* [gt lt] -> gt: drop. *)
  1133. BEGIN EmitOp(OPext); EmitOp(SUBdrop) END RealGt;
  1134. PROCEDURE RealGe;
  1135. (* [gt lt] -> NOT lt: swap, drop, not. *)
  1136. BEGIN
  1137. EmitOp(OPswap); EmitOp(OPext); EmitOp(SUBdrop); EmitOp(OPnot)
  1138. END RealGe;
  1139. PROCEDURE NegInt;
  1140. BEGIN EmitOp(OPimm0); EmitOp(OPswap); EmitOp(OPsub) END NegInt;
  1141. PROCEDURE NegReal;
  1142. BEGIN
  1143. EmitOp(OPimmW); EmitW64(0H);
  1144. EmitOp(OPswap); EmitOp(OPrSub)
  1145. END NegReal;
  1146. PROCEDURE IntToReal;
  1147. BEGIN EmitOp(OPintToLong); EmitOp(OPlongToReal) END IntToReal;
  1148. PROCEDURE Dup;
  1149. BEGIN EmitOp(OPdup) END Dup;
  1150. PROCEDURE Drop;
  1151. BEGIN EmitOp(OPext); EmitOp(SUBdrop) END Drop;
  1152. PROCEDURE Swap;
  1153. BEGIN EmitOp(OPswap) END Swap;
  1154. (* ---------------- composites ---------------- *)
  1155. PROCEDURE IdxScale (lo: INTEGER; elemBytes: CARDINAL);
  1156. BEGIN
  1157. PushInt(lo);
  1158. EmitOp(OPsub);
  1159. PushInt(VAL(INTEGER, elemBytes));
  1160. EmitOp(OPumul);
  1161. EmitOp(OPadd)
  1162. END IdxScale;
  1163. PROCEDURE FieldAdd (offSlots: CARDINAL);
  1164. BEGIN
  1165. IF offSlots = 0 THEN RETURN END;
  1166. PushInt(VAL(INTEGER, offSlots * 8));
  1167. EmitOp(OPadd)
  1168. END FieldAdd;
  1169. PROCEDURE CopyBlock;
  1170. BEGIN EmitOp(30H) END CopyBlock;
  1171. PROCEDURE LoadByte;
  1172. BEGIN
  1173. PushInt(0);
  1174. EmitOp(0DH)
  1175. END LoadByte;
  1176. PROCEDURE StoreByte;
  1177. BEGIN
  1178. PushInt(0);
  1179. EmitOp(OPswap);
  1180. EmitOp(1DH)
  1181. END StoreByte;
  1182. PROCEDURE PushBytes (n: CARDINAL);
  1183. BEGIN PushInt(VAL(INTEGER, n)) END PushBytes;
  1184. PROCEDURE AllocOp;
  1185. BEGIN EmitOp(OPext); EmitOp(05H) END AllocOp;
  1186. PROCEDURE DeallocOp;
  1187. BEGIN EmitOp(OPext); EmitOp(06H) END DeallocOp;
  1188. PROCEDURE BitXor;
  1189. BEGIN EmitOp(0E9H) END BitXor;
  1190. PROCEDURE StrLenOf (s: ARRAY OF CHAR): CARDINAL;
  1191. VAR n: CARDINAL;
  1192. BEGIN
  1193. n := StrLen(s);
  1194. IF n < 2 THEN RETURN 0 END;
  1195. RETURN n - 2
  1196. END StrLenOf;
  1197. PROCEDURE EmitString (s: ARRAY OF CHAR);
  1198. VAR len, i: CARDINAL;
  1199. BEGIN
  1200. len := StrLenOf(s);
  1201. IF len + 1 > 255 THEN
  1202. PushInt(0); RETURN
  1203. END;
  1204. EmitOp(8CH);
  1205. EmitByte(len + 1);
  1206. i := 1;
  1207. WHILE i <= len DO
  1208. EmitByte(ORD(s[i])); INC(i)
  1209. END;
  1210. EmitByte(0)
  1211. END EmitString;
  1212. PROCEDURE StrComp;
  1213. BEGIN EmitOp(0C4H) END StrComp;
  1214. (* ---------------- WITH ---------------- *)
  1215. PROCEDURE WithEnter (typ: INTEGER);
  1216. VAR tmp: INTEGER;
  1217. BEGIN
  1218. tmp := TempGlobal();
  1219. StoreTemp(tmp);
  1220. IF withTop <= 7 THEN
  1221. withTmps[withTop] := tmp;
  1222. withTyps[withTop] := typ;
  1223. INC(withTop)
  1224. END
  1225. END WithEnter;
  1226. PROCEDURE WithExit;
  1227. BEGIN
  1228. IF withTop > 0 THEN DEC(withTop) END
  1229. END WithExit;
  1230. PROCEDURE WithDepth (): CARDINAL;
  1231. BEGIN RETURN withTop END WithDepth;
  1232. PROCEDURE WithAddr (name: ARRAY OF CHAR);
  1233. VAR i: CARDINAL;
  1234. off: INTEGER;
  1235. found: BOOLEAN;
  1236. BEGIN
  1237. found := FALSE;
  1238. i := withTop;
  1239. WHILE (i > 0) & ~found DO
  1240. DEC(i);
  1241. IF SymTab.FieldExists(withTyps[i], name) THEN
  1242. off := SymTab.FieldOffset(withTyps[i], name);
  1243. LoadTemp(withTmps[i]);
  1244. IF off > 0 THEN
  1245. PushInt(VAL(INTEGER, VAL(CARDINAL, off) * 8));
  1246. EmitOp(OPadd)
  1247. ELSIF off < 0 THEN
  1248. PushInt(0)
  1249. END;
  1250. found := TRUE
  1251. END
  1252. END;
  1253. IF ~found THEN PushInt(0) END
  1254. END WithAddr;
  1255. PROCEDURE PrintNum (): CARDINAL;
  1256. BEGIN RETURN maxNum + 1 END PrintNum;
  1257. PROCEDURE CallPrint;
  1258. BEGIN
  1259. EmitOpB(OPprocCall, maxNum + 1);
  1260. EmitOp(OPext); EmitOp(SUBdrop)
  1261. END CallPrint;
  1262. PROCEDURE SysCall;
  1263. BEGIN EmitOp(OPsys) END SysCall;
  1264. (* ---------------- control flow ---------------- *)
  1265. PROCEDURE NewLabel (): INTEGER;
  1266. BEGIN
  1267. IF nLab > MaxLab THEN RETURN 0 END;
  1268. labs[nLab] := -1;
  1269. INC(nLab);
  1270. RETURN VAL(INTEGER, nLab - 1)
  1271. END NewLabel;
  1272. PROCEDURE DefLabel (id: INTEGER);
  1273. VAR i : CARDINAL;
  1274. rel : INTEGER;
  1275. BEGIN
  1276. IF (id < 0) OR (id >= VAL(INTEGER, nLab)) THEN RETURN END;
  1277. labs[id] := VAL(INTEGER, nCode);
  1278. i := 0;
  1279. WHILE i < nFix DO
  1280. IF fixs[i].lab = id THEN
  1281. rel := labs[id] - VAL(INTEGER, fixs[i].pos + 9);
  1282. WriteS64At(fixs[i].pos + 1, rel);
  1283. fixs[i].lab := -1
  1284. END;
  1285. INC(i)
  1286. END
  1287. END DefLabel;
  1288. PROCEDURE Jump (op: CARDINAL; id: INTEGER);
  1289. VAR pos : CARDINAL;
  1290. j : CARDINAL;
  1291. BEGIN
  1292. pos := nCode;
  1293. EmitOp(op);
  1294. IF (id >= 0) & (id < VAL(INTEGER, nLab)) & (labs[id] >= 0) THEN
  1295. EmitS64(labs[id] - VAL(INTEGER, pos + 9))
  1296. ELSE
  1297. FOR j := 0 TO 7 DO EmitByte(0) END;
  1298. IF (nFix <= MaxFix) & (id >= 0) & (id < VAL(INTEGER, nLab)) THEN
  1299. fixs[nFix].pos := pos; fixs[nFix].lab := id; INC(nFix)
  1300. END
  1301. END
  1302. END Jump;
  1303. PROCEDURE Jmp (id: INTEGER);
  1304. BEGIN
  1305. Jump(OPjp, id)
  1306. END Jmp;
  1307. PROCEDURE Jz (id: INTEGER);
  1308. BEGIN
  1309. Jump(OPjz, id)
  1310. END Jz;
  1311. PROCEDURE PushLoop (exit: INTEGER);
  1312. BEGIN
  1313. IF loopTop <= MaxLoop THEN
  1314. loopSt[loopTop] := exit; INC(loopTop)
  1315. END
  1316. END PushLoop;
  1317. PROCEDURE PopLoop;
  1318. BEGIN
  1319. IF loopTop > 0 THEN DEC(loopTop) END
  1320. END PopLoop;
  1321. PROCEDURE TopLoop (VAR exit: INTEGER): BOOLEAN;
  1322. BEGIN
  1323. IF loopTop = 0 THEN RETURN FALSE END;
  1324. exit := loopSt[loopTop - 1];
  1325. RETURN TRUE
  1326. END TopLoop;
  1327. PROCEDURE NoSupEnter;
  1328. BEGIN
  1329. INC(noSup)
  1330. END NoSupEnter;
  1331. PROCEDURE NoSupExit;
  1332. BEGIN
  1333. IF noSup > 0 THEN DEC(noSup) END
  1334. END NoSupExit;
  1335. PROCEDURE NoSup (): BOOLEAN;
  1336. BEGIN
  1337. RETURN noSup > 0
  1338. END NoSup;
  1339. PROCEDURE CopyName (s: ARRAY OF CHAR; VAR d: ARRAY OF CHAR);
  1340. VAR i : CARDINAL;
  1341. BEGIN
  1342. i := 0;
  1343. WHILE (i < HIGH(d)) & (i < HIGH(s)) & (s[i] # 0C) DO
  1344. d[i] := s[i]; INC(i)
  1345. END;
  1346. IF i <= HIGH(d) THEN d[i] := 0C END
  1347. END CopyName;
  1348. PROCEDURE NoEmitEnter;
  1349. BEGIN
  1350. INC(noEmit)
  1351. END NoEmitEnter;
  1352. PROCEDURE NoEmitExit;
  1353. BEGIN
  1354. IF noEmit > 0 THEN DEC(noEmit) END
  1355. END NoEmitExit;
  1356. (* ---------------- image assembly ---------------- *)
  1357. PROCEDURE Put32At (off: CARDINAL; v: CARDINAL);
  1358. BEGIN
  1359. img[off] := CHR(v MOD 256);
  1360. img[off + 1] := CHR((v DIV 256) MOD 256);
  1361. img[off + 2] := CHR((v DIV 65536) MOD 256);
  1362. img[off + 3] := CHR(v DIV 16777216)
  1363. END Put32At;
  1364. PROCEDURE Put64At (off: CARDINAL; v: LONGCARD);
  1365. VAR j : CARDINAL;
  1366. BEGIN
  1367. FOR j := 0 TO 7 DO
  1368. img[off + j] := CHR(VAL(CARDINAL, v MOD 256));
  1369. v := v DIV 256
  1370. END
  1371. END Put64At;
  1372. PROCEDURE EmitPrint;
  1373. (* proc1: prints the CARDINAL parameter as decimal + CRLF.
  1374. Uses global temps 0..3 (buffer, count, index, char). *)
  1375. VAR l1, l2 : INTEGER;
  1376. BEGIN
  1377. EmitOpB(OPenter, 250);
  1378. EmitOpB(OPimmB, 16); EmitOp(0D2H); EmitOpB(OPstoreGlb, 0);
  1379. EmitOp(OPimm0); EmitOp(OPimm0);
  1380. EmitOpB(OPstoreGlb, 1); EmitOpB(OPstoreGlb, 2);
  1381. EmitOp(03H);
  1382. l1 := NewLabel(); DefLabel(l1);
  1383. EmitOpB(OPloadGlb, 1); EmitOp(OPinc); EmitOpB(OPstoreGlb, 1);
  1384. EmitOp(OPdup); EmitOpB(OPimmB, 10); EmitOp(OPumod);
  1385. EmitOp(OPswap); EmitOpB(OPimmB, 10); EmitOp(OPudiv);
  1386. EmitOp(OPdup); EmitOp(OPaeq0);
  1387. Jz(l1);
  1388. EmitOp(OPext); EmitOp(SUBdrop);
  1389. l2 := NewLabel(); DefLabel(l2);
  1390. EmitOpB(OPimmB, 48); EmitOp(OPadd); EmitOpB(OPstoreGlb, 3);
  1391. EmitOpB(OPloadGlb, 0); EmitOpB(OPloadGlb, 2); EmitOp(OPadd);
  1392. EmitOp(OPimm0); EmitOpB(OPloadGlb, 3); EmitOp(1DH);
  1393. EmitOpB(OPloadGlb, 2); EmitOp(OPinc); EmitOpB(OPstoreGlb, 2);
  1394. EmitOpB(OPloadGlb, 1); EmitOp(OPdec); EmitOpB(OPstoreGlb, 1);
  1395. EmitOpB(OPloadGlb, 1); EmitOp(OPaeq0);
  1396. Jz(l2);
  1397. EmitOpB(OPloadGlb, 0); EmitOpB(OPloadGlb, 2); EmitOp(OPadd);
  1398. EmitOp(OPimm0); EmitOp(OPimm0); EmitOp(1DH);
  1399. EmitOpB(OPloadGlb, 0);
  1400. EmitOpB(OPimmB, 1); EmitOp(OPsys);
  1401. EmitOpB(OPimmB, 3); EmitOp(0D2H);
  1402. EmitOp(OPdup); EmitOp(OPimm0); EmitOpB(OPimmB, 13); EmitOp(1DH);
  1403. EmitOp(OPdup); EmitOpB(OPimmB, 1); EmitOpB(OPimmB, 10); EmitOp(1DH);
  1404. EmitOp(OPdup); EmitOpB(OPimmB, 2); EmitOp(OPimm0); EmitOp(1DH);
  1405. EmitOpB(OPimmB, 1); EmitOp(OPsys);
  1406. EmitOpB(OPfctLeave, 0)
  1407. END EmitPrint;
  1408. PROCEDURE PutS64At (off, addr, slot: CARDINAL);
  1409. (* Procedure-table cell: signed (addr - slot). *)
  1410. VAR mag : LONGCARD;
  1411. bits : LONGCARD;
  1412. j : CARDINAL;
  1413. BEGIN
  1414. IF addr >= slot THEN bits := VAL(LONGCARD, addr - slot)
  1415. ELSE
  1416. mag := VAL(LONGCARD, slot - addr);
  1417. bits := 0FFFFFFFFFFFFFFFFH - mag + 1H
  1418. END;
  1419. FOR j := 0 TO 7 DO
  1420. img[off + j] := CHR(VAL(CARDINAL, bits MOD 256));
  1421. bits := bits DIV 256
  1422. END
  1423. END PutS64At;
  1424. PROCEDURE EndModule;
  1425. VAR i : CARDINAL;
  1426. codeOff, p1, pt, prNum, tabBytes : CARDINAL;
  1427. k : CARDINAL;
  1428. addr : CARDINAL;
  1429. exitIdx : INTEGER;
  1430. sum : CARDINAL;
  1431. fname : ARRAY [0 .. 127] OF CHAR;
  1432. f : FileIO.File;
  1433. ch : CHAR;
  1434. BEGIN
  1435. IF ~inBody THEN mainAddr := nCode END;
  1436. prNum := maxNum + 1;
  1437. (* epilogue: print ExitCode when the convention applies *)
  1438. exitIdx := -1;
  1439. IF SymTab.Lookup("ExitCode")
  1440. & (SymTab.SymKind("ExitCode") = SymTab.KindVar)
  1441. & SymTab.IsIntFamily(SymTab.SymType("ExitCode")) THEN
  1442. exitIdx := FindVar("ExitCode")
  1443. END;
  1444. IF exitIdx >= 0 THEN
  1445. EmitOpB(OPloadGlb, VAL(CARDINAL, exitIdx));
  1446. EmitOpB(OPprocCall, prNum);
  1447. EmitOp(OPext); EmitOp(SUBdrop)
  1448. END;
  1449. EmitOp(OPend);
  1450. p1 := nCode;
  1451. EmitPrint;
  1452. (* assemble the image *)
  1453. i := 0;
  1454. WHILE i <= MaxImg DO img[i] := 0C; INC(i) END;
  1455. img[0] := "M"; img[1] := "C"; img[2] := "6"; img[3] := "4";
  1456. i := 0;
  1457. WHILE (i < 16) & (modName[i] # 0C) DO
  1458. img[HeadSize + DName + i] := modName[i]; INC(i)
  1459. END;
  1460. img[HeadSize + DFlags] := CHR(4);
  1461. img[HeadSize + DVarCount] := CHR(nVars MOD 256);
  1462. img[HeadSize + DDepCount] := 0C;
  1463. codeOff := DVarSizes + nVars * 8;
  1464. i := 0;
  1465. WHILE i < nCode DO
  1466. img[HeadSize + codeOff + i] := code[i]; INC(i)
  1467. END;
  1468. pt := codeOff + nCode;
  1469. tabBytes := (maxNum + 2) * 8;
  1470. Put64At(HeadSize + DProcs, VAL(LONGCARD, pt));
  1471. k := 0;
  1472. WHILE k <= maxNum + 1 DO
  1473. IF k = 0 THEN addr := codeOff + mainAddr
  1474. ELSIF k <= maxNum THEN
  1475. IF procAddr[k] < 0 THEN addr := pt + k * 8
  1476. ELSE addr := VAL(CARDINAL, procAddr[k]) + codeOff
  1477. END
  1478. ELSE addr := codeOff + p1
  1479. END;
  1480. PutS64At(HeadSize + pt + k * 8, addr, pt + k * 8);
  1481. INC(k)
  1482. END;
  1483. i := 0;
  1484. WHILE i < nVars DO
  1485. Put64At(HeadSize + DVarSizes + i * 8,
  1486. VAL(LONGCARD, vSize[i] * 8));
  1487. INC(i)
  1488. END;
  1489. sum := 0;
  1490. i := HeadSize;
  1491. WHILE i < HeadSize + pt + tabBytes DO
  1492. IF ~((i >= 352) & (i <= 355)) THEN
  1493. sum := sum + ORD(img[i])
  1494. END;
  1495. INC(i)
  1496. END;
  1497. Put32At(HeadSize + DChecksum, sum);
  1498. fname[0] := 0C;
  1499. StrCpy(fname, modName);
  1500. i := StrLen(fname);
  1501. fname[i] := "."; fname[i + 1] := "M"; fname[i + 2] := "C";
  1502. fname[i + 3] := "4"; fname[i + 4] := 0C;
  1503. FileIO.Open(f, fname, TRUE);
  1504. IF FileIO.Okay THEN
  1505. i := 0;
  1506. WHILE i < HeadSize + pt + tabBytes DO
  1507. ch := img[i];
  1508. FileIO.Write(f, ch);
  1509. INC(i)
  1510. END;
  1511. FileIO.Close(f)
  1512. END
  1513. END EndModule;
  1514. BEGIN
  1515. nCode := 0; nGlb := 0; nVars := 0; nInit := 0;
  1516. nLab := 0; nFix := 0; loopTop := 0; noSup := 0; noEmit := 0;
  1517. actTop := 0; withTop := 0;
  1518. maxNum := 0; mainAddr := 0;
  1519. nInits := 0;
  1520. inBody := FALSE;
  1521. modName[0] := 0C
  1522. END MGen.