MGen.mod 36 KB

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