MGen.mod 38 KB

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