CODEGEN.MOD 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  1. (* Renamed for readability. Semantics unchanged. Original identifiers: see docs/compiler/ + src/compiler/RENAME-MAP.md. *)
  2. IMPLEMENTATION MODULE CodeGen;
  3. IMPORT Scanner, Files, Compiler;
  4. FROM ComLine IMPORT codepos, execute;
  5. FROM SYSTEM IMPORT ADR, MOVE;
  6. CONST
  7. OPINVALID = 0;
  8. OPRAISE = 1;
  9. OPLDPROC = 2;
  10. OPLDPARAM = 3;
  11. OPLLD = 8;
  12. OPLGD = 9;
  13. OPLSD = 0AH;
  14. OPLED = 0BH;
  15. OPLDEXT = 0CH;
  16. OPLXB = 0DH;
  17. OPLXW = 0EH;
  18. OPLXD = 0FH;
  19. OPLDIX = 10H;
  20. OPLDIXN = 11H;
  21. OPLONGREAL= 12H;
  22. OPSETPARM = 13H;
  23. OPSLD = 18H;
  24. OPSGD = 19H;
  25. OPSSD = 1AH;
  26. OPSED = 1BH;
  27. OPSTEXT = 1CH;
  28. OPXSB = 1DH;
  29. OPSXW = 1EH;
  30. OPSXD = 1FH;
  31. OPDUP = 20H;
  32. OPSWAP = 21H;
  33. OPLLW2 = 22H;
  34. OPLLWN = 2CH;
  35. OPLGWN = 2DH;
  36. OPLSWN = 2EH;
  37. OPLEWN = 2FH;
  38. OPMOVB = 30H;
  39. OPMOVS = 31H;
  40. OPSLW2 = 32H;
  41. OPSLWN = 3CH;
  42. OPSGWN = 3DH;
  43. OPSSWN = 3EH;
  44. OPSEWN = 3FH;
  45. OPEXTENDED= 40H;
  46. OPLSD0 = 41H;
  47. OPLGW2 = 42H;
  48. OPENDPROG = 50H;
  49. OPSSD0 = 51H;
  50. OPSGW2 = 52H;
  51. OPLSW0 = 60H;
  52. OPSSW0 = 70H;
  53. OPLLA = 80H;
  54. OPLGA = 81H;
  55. OPLSA = 82H;
  56. OPLEA = 83H;
  57. OPLEAVE = 84H;
  58. OPFLEAVE = 85H;
  59. OPLFLEAVE = 86H;
  60. OPASM = 87H;
  61. OPLEAVE0 = 88H;
  62. OPCALLREL = 8CH;
  63. OPLIB = 8DH;
  64. OPLIW = 8EH;
  65. OPLID = 8FH;
  66. OPLI0 = 90H;
  67. OPLI15 = 9FH;
  68. OPEQUAL = 0A0H;
  69. OPNEQ = 0A1H;
  70. OPLESS = 0A2H;
  71. OPGREATER = 0A3H;
  72. OPLESSEQ = 0A4H;
  73. OPGREATEQ = 0A5H;
  74. OPADD = 0A6H;
  75. OPSUB = 0A7H;
  76. OPMUL = 0A8H;
  77. OPDIV = 0A9H;
  78. OPMOD = 0AAH;
  79. OPEQ0 = 0ABH;
  80. OPINC = 0ACH;
  81. OPDEC = 0ADH;
  82. OPADDN = 0AEH;
  83. OPSUBN = 0AFH;
  84. OPSHL = 0B0H;
  85. OPSHR = 0B1H;
  86. OPILESS = 0B2H;
  87. OPIGREATER= 0B3H;
  88. OPILESSEQ = 0B4H;
  89. OPIGREATEQ= 0B5H;
  90. OPNOT = 0B6H;
  91. OPCOMPL = 0B7H;
  92. OPIMUL = 0B8H;
  93. OPIDIV = 0B9H;
  94. OPLG2CARD = 0BAH;
  95. OPLG2INT = 0BBH;
  96. OPABS = 0BCH;
  97. OPINT2LG = 0BDH;
  98. OPLG2FLOAT= 0BEH;
  99. OPFLOAT2LG= 0BFH;
  100. OPADDOV = 0C0H;
  101. OPSUBOV = 0C1H;
  102. OPMULOV = 0C2H;
  103. OPSYSTEM = 0C3H;
  104. OPSTRCOMP = 0C4H;
  105. OPDCOMP = 0C5H;
  106. OPDADD = 0C6H;
  107. OPDSUB = 0C7H;
  108. OPDDIV = 0C8H;
  109. OPDMOD = 0C9H;
  110. OPNEQ0 = 0CAH;
  111. OPDABS = 0CBH;
  112. OPCASE = 0CDH;
  113. OPRETURN = 0CEH;
  114. OPPUSHREL = 0CFH;
  115. OPIADDOV = 0D0H;
  116. OPISUBOV = 0D1H;
  117. OPSTKRES = 0D2H;
  118. OPSTRRES = 0D3H;
  119. OPENTER = 0D4H;
  120. OPREALCMP = 0D5H;
  121. OPREALADD = 0D6H;
  122. OPREALSUB = 0D7H;
  123. OPREALMUL = 0D8H;
  124. OPREALDIV = 0D9H;
  125. OPRANGE = 0DAH;
  126. OPIRANGE = 0DBH;
  127. OPLIMIT = 0DCH;
  128. OPPOSITIV = 0DDH;
  129. OPANDJP = 0DEH;
  130. OPORJP = 0DFH;
  131. OPJP = 0E0H;
  132. OPJPCOND = 0E1H;
  133. OPJPF = 0E2H;
  134. OPJPFCOND = 0E3H;
  135. OPJPB = 0E4H;
  136. OPJPBCOND = 0E5H;
  137. OPBITOR = 0E6H;
  138. OPBITIN = 0E7H;
  139. OPBITAND = 0E8H;
  140. OPBITXOR = 0E9H;
  141. OPPOWER2 = 0EAH;
  142. OPEXTCALLS= 0EBH;
  143. OPINTCALL = 0ECH;
  144. OPCALL = 0EDH;
  145. OPCALLFRM = 0EEH;
  146. OPEXTCALL2= 0EFH;
  147. OPEXTCALL1= 0F0H;
  148. OPCALL1 = 0F1H;
  149. TYPE Record = RECORD
  150. word0: CARDINAL;
  151. CASE : CARDINAL OF
  152. | 0: word1,word2: CARDINAL;
  153. | 1: ptr1: POINTER TO ARRAY [0..255] OF CHAR;
  154. | 2: long1: LONGINT;
  155. END;
  156. END;
  157. RecordPtr = POINTER TO Record;
  158. VAR
  159. (* 6 *) codeWindow : POINTER TO ARRAY [0..2047] OF BYTE;
  160. (* 7 *) pendMode : [0..9];
  161. (* 8 *) pendSize : [0..5];
  162. (* 9 *) pendDisp : CARDINAL;
  163. (* 10 *) pendOffset: CARDINAL;
  164. (* 11 *) fixupQueue: ARRAY [0..15] OF Record;
  165. (* 12 *) fixupCount: [0..16];
  166. (* 13 *) spare13: WORD;
  167. (* 14 *) pendActive: BOOLEAN;
  168. (* 15 *) checkOverflow: BOOLEAN;
  169. (* 16 *) reservedBytes: ARRAY [0..11] OF BYTE;
  170. (* 17 *) reservedWord: WORD;
  171. EXCEPTION errorfound;
  172. (* $[+ remove procedure names *)
  173. PROCEDURE CodeAssert(cond: BOOLEAN);
  174. EXCEPTION CE;
  175. BEGIN
  176. IF NOT cond THEN RAISE CE END;
  177. END CodeAssert;
  178. PROCEDURE FlushCodeWindow;
  179. BEGIN
  180. Files.SetPos(Scanner.codeFile, LONG(windowBase));
  181. Files.WriteBytes(Scanner.codeFile, ADDRESS(codeWindow), 2048);
  182. INC(windowBase, 2048);
  183. INC(windowLimit, 2048);
  184. MOVE(ADDRESS(codeWindow) + 2048, ADDRESS(codeWindow), nextEmitPos - windowBase);
  185. END FlushCodeWindow;
  186. PROCEDURE SeekCodeWindow;
  187. VAR
  188. baseSec : CARDINAL;
  189. alignedBase : CARDINAL;
  190. needBytes : CARDINAL;
  191. BEGIN
  192. baseSec := nextEmitPos DIV 512;
  193. alignedBase := (baseSec - ORD(baseSec <> 0)) * 512;
  194. IF alignedBase < windowBase THEN
  195. needBytes := windowBase - alignedBase;
  196. IF nextEmitPos > windowBase THEN
  197. MOVE(ADDRESS(codeWindow), ADDRESS(codeWindow)+needBytes, nextEmitPos-windowBase);
  198. END;
  199. Files.SetPos(Scanner.codeFile, LONG(alignedBase));
  200. CodeAssert(Files.ReadBytes(Scanner.codeFile, ADDRESS(codeWindow), needBytes) = needBytes);
  201. windowBase := alignedBase;
  202. windowLimit := windowBase + 4096;
  203. END;
  204. END SeekCodeWindow;
  205. PROCEDURE PeekCodeByte(pos: CARDINAL): CARDINAL;
  206. VAR byte: BYTE;
  207. BEGIN
  208. IF pos >= windowBase THEN RETURN CARDINAL(codeWindow^[pos-windowBase]) END;
  209. Files.SetPos(Scanner.codeFile, LONG(pos));
  210. Files.ReadByte(Scanner.codeFile, byte);
  211. RETURN CARDINAL(byte)
  212. END PeekCodeByte;
  213. PROCEDURE PokeCodeByte(value: BYTE; pos: CARDINAL);
  214. BEGIN
  215. IF pos >= windowBase THEN
  216. codeWindow^[pos-windowBase] := value;
  217. RETURN
  218. END;
  219. Files.SetPos(Scanner.codeFile, LONG(pos));
  220. Files.WriteByte(Scanner.codeFile, value);
  221. END PokeCodeByte;
  222. PROCEDURE CheckCodeOverflow;
  223. BEGIN
  224. IF nextEmitPos >= codepos THEN RAISE errorfound END;
  225. END CheckCodeOverflow;
  226. PROCEDURE Emit1(op: BYTE);
  227. BEGIN
  228. IF nextEmitPos >= windowLimit THEN FlushCodeWindow END;
  229. codeWindow^[nextEmitPos-windowBase] := op;
  230. INC(nextEmitPos);
  231. IF checkOverflow THEN CheckCodeOverflow END;
  232. END Emit1;
  233. PROCEDURE Emit2(op2, op1: BYTE);
  234. BEGIN
  235. IF nextEmitPos + 1 >= windowLimit THEN FlushCodeWindow END;
  236. codeWindow^[nextEmitPos - windowBase] := op2;
  237. codeWindow^[nextEmitPos + 1 - windowBase] := op1;
  238. INC(nextEmitPos, 2);
  239. IF checkOverflow THEN CheckCodeOverflow END;
  240. END Emit2;
  241. PROCEDURE EmitWord(w: WORD);
  242. VAR ptr: ADDRESS;
  243. BEGIN
  244. IF nextEmitPos + 1 >= windowLimit THEN FlushCodeWindow END;
  245. ptr := ADDRESS(codeWindow) + (nextEmitPos - windowBase);
  246. ptr^ := w;
  247. INC(nextEmitPos, 2);
  248. IF checkOverflow THEN CheckCodeOverflow END;
  249. END EmitWord;
  250. PROCEDURE EmitString(s: ADDRESS);
  251. VAR ptr : POINTER TO ARRAY [0..1] OF BYTE;
  252. BEGIN
  253. ptr := s;
  254. REPEAT
  255. Emit1(ptr^[0]);
  256. ptr := ADDRESS(ptr) + 1;
  257. UNTIL ORD(ptr^[0]) = 0;
  258. IF checkOverflow THEN CheckCodeOverflow END;
  259. END EmitString;
  260. PROCEDURE FlushPendingOp;
  261. VAR base: CARDINAL;
  262. PROCEDURE BaseOpCode(mode: CARDINAL): CARDINAL;
  263. BEGIN
  264. CASE mode OF
  265. | 8 : RETURN 60H
  266. | 9 : RETURN 0ECH
  267. | 1, 5 : RETURN 2CH
  268. | 2, 6 : RETURN 08H
  269. | 3, 7 : RETURN 0
  270. END;
  271. END BaseOpCode;
  272. BEGIN
  273. pendActive := FALSE;
  274. base := 0;
  275. IF pendMode <> 9 THEN
  276. pendOffset := pendOffset DIV 2;
  277. base := pendMode DIV 4 * (ORD((pendMode MOD 4) <> 3) * 12 + 4);
  278. END;
  279. IF pendSize = 4 THEN
  280. IF pendDisp = 1
  281. THEN Emit1(OPLDIX)
  282. ELSE Emit2(OPLDIXN, pendDisp)
  283. END;
  284. IF pendOffset >= 128 THEN (* $T+ *)
  285. Emit2(OPSUBN, (256 - pendOffset) * 2);
  286. pendOffset := 0; (* $T- *)
  287. END;
  288. pendSize := 2;
  289. END;
  290. IF pendMode IN {3,7} THEN Emit1(OPLONGREAL) END;
  291. IF pendSize = 5 THEN
  292. IF pendMode IN {3,7}
  293. THEN Emit2(pendMode DIV 4 + 8, 0)
  294. ELSE Emit1(pendMode MOD 4 + base + 13)
  295. END;
  296. ELSE
  297. IF pendMode IN {0,4} THEN INC(pendMode) END;
  298. IF pendSize = 3 THEN
  299. IF (pendOffset <= 15) AND (pendDisp <= 15) AND (pendMode IN {1,5,9})
  300. THEN
  301. IF pendMode = 9 THEN base := 0E4H END;
  302. Emit2(base + 12, pendDisp * 16 + pendOffset);
  303. RETURN
  304. END;
  305. Emit2(BaseOpCode(pendMode)+base+3, pendDisp);
  306. Emit1(pendOffset);
  307. ELSE
  308. CASE pendMode OF
  309. | 9:
  310. IF (pendSize = 1) AND (pendOffset IN {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15})
  311. THEN Emit1(pendOffset + OPEXTCALL1); RETURN
  312. END;
  313. | 8:
  314. IF (pendSize = 2) AND (pendOffset = 0) THEN RETURN END;
  315. | 1, 5:
  316. IF (pendSize <> 2) OR NOT Compiler.rangeCheckEnabled THEN
  317. IF pendSize = 0 THEN
  318. IF pendOffset <= 7 THEN
  319. Emit1(pendOffset + base);
  320. RETURN
  321. ELSIF pendOffset >= 245 THEN
  322. Emit1(base + 288 - pendOffset);
  323. RETURN
  324. END;
  325. ELSE
  326. IF (pendOffset >= (4 - pendSize * 2)) AND (pendOffset <= 15) THEN
  327. Emit1((pendSize + 1) * 32 + pendOffset + base);
  328. RETURN
  329. END;
  330. END;
  331. END;
  332. | 2, 6:
  333. IF (pendSize = 2) AND (pendOffset = 0) THEN
  334. Emit1(base + (OPLGW2 - 1));
  335. RETURN
  336. END;
  337. END;
  338. Emit2(BaseOpCode(pendMode) + pendSize + base, pendOffset);
  339. IF Compiler.rangeCheckEnabled AND (pendMode = 8) AND (pendSize <= 1) THEN
  340. Emit1(pendDisp)
  341. END;
  342. END;
  343. END;
  344. END FlushPendingOp;
  345. PROCEDURE FlushConstQueue;
  346. VAR
  347. idx : CARDINAL;
  348. k : CARDINAL;
  349. w : CARDINAL;
  350. entry : POINTER TO Record;
  351. BEGIN
  352. IF pendActive THEN FlushPendingOp
  353. ELSE
  354. IF fixupCount <> 0 THEN
  355. idx := 0;
  356. WHILE idx < fixupCount DO
  357. entry := ADR(fixupQueue[idx]);
  358. CASE entry^.word0 OF
  359. | 0: (* 02EE *)
  360. IF entry^.word2 <> 0 THEN Emit2(2, entry^.word2)
  361. ELSE Emit2(OPCALLREL, Scanner.StrLenHelper(entry^.word1, 128));
  362. EmitString(entry^.word1);
  363. END;
  364. | 1: (* 0308 *)
  365. IF entry^.word1 <= 255 THEN
  366. IF entry^.word1 <= 15
  367. THEN Emit1(entry^.word1 + OPLI0)
  368. ELSE Emit2(OPLIB, entry^.word1)
  369. END;
  370. ELSE (* 0323 *)
  371. Emit1(OPLIW);
  372. EmitWord(entry^.word1)
  373. END; (* 0329 *)
  374. | 2: (* 032A *)
  375. Emit1(OPLID);
  376. EmitWord(entry^.word1);
  377. EmitWord(entry^.word2);
  378. | 3: (* 0334 *)
  379. w := 8;
  380. REPEAT (* 0336 *)
  381. DEC(w, 4);
  382. Emit1(OPLID);
  383. k := 0;
  384. REPEAT (* 033F *)
  385. Emit1(entry^.ptr1^[w + k]);
  386. INC(k);
  387. UNTIL k > 3;
  388. UNTIL w = 0;
  389. IF Compiler.rangeCheckEnabled THEN Emit2(0, 22) END;
  390. | 4: (* 035B *)
  391. IF CARDINAL(ABS(INTEGER(entry^.word1))) <= 255 THEN
  392. IF entry^.word1 <> NIL THEN
  393. IF ABS(INTEGER(entry^.word1)) = 1 THEN
  394. Emit1(ORD(INTEGER(entry^.word1) < 0) + OPINC)
  395. ELSE (* 0378 *)
  396. Emit2(ORD(INTEGER(entry^.word1) < 0) + OPADDN,
  397. ABS(INTEGER(entry^.word1)));
  398. END;
  399. END; (* 0382 *)
  400. ELSE (* 0384 *)
  401. Emit1(OPLIW);
  402. EmitWord(entry^.word1);
  403. Emit1(OPADD);
  404. END; (* 038d *)
  405. (* $T+ generates ELSE RAISE CaseSelectError *)
  406. END; (* CASE *)
  407. INC(idx);
  408. END; (* 03A8 *)
  409. fixupCount := 0;
  410. END (* 03AA *)
  411. END (* 03aa *);
  412. END FlushConstQueue;
  413. PROCEDURE Reserved33(dummy: WORD);
  414. BEGIN
  415. (* commented contents ? *)
  416. END Reserved33;
  417. PROCEDURE Reserved34(a, b: WORD);
  418. VAR unused: WORD;
  419. BEGIN
  420. (* commented contents ? *)
  421. END Reserved34;
  422. PROCEDURE DiscardPending;
  423. VAR unused: WORD;
  424. BEGIN
  425. IF emitEnabled THEN
  426. fixupCount := fixupCount + ORD(pendActive) - 1;
  427. pendActive := FALSE;
  428. END;
  429. END DiscardPending;
  430. PROCEDURE SetPendingOp(mode, size, disp, off: CARDINAL);
  431. BEGIN
  432. IF emitEnabled THEN
  433. FlushConstQueue;
  434. pendMode := mode;
  435. pendSize := size;
  436. pendDisp := disp;
  437. pendOffset := off;
  438. pendActive := TRUE;
  439. IF mode IN {4,5,6,7,9} THEN FlushPendingOp END;
  440. END;
  441. END SetPendingOp;
  442. (* $T- *)
  443. PROCEDURE QueueConst(value: CARDINAL);
  444. VAR ptr : POINTER TO Record;
  445. BEGIN
  446. IF emitEnabled THEN
  447. IF pendActive THEN FlushPendingOp END;
  448. IF fixupCount >= 16 THEN Scanner.ScannerError(90) END;
  449. ptr := ADR(fixupQueue[fixupCount]);
  450. ptr^.word0 := 1;
  451. ptr^.word1 := value;
  452. INC(fixupCount);
  453. END;
  454. END QueueConst;
  455. PROCEDURE QueueLongConst(kind: CARDINAL; value: LONGINT);
  456. VAR ptr : POINTER TO Record;
  457. BEGIN
  458. IF emitEnabled THEN
  459. IF pendActive THEN FlushPendingOp END;
  460. IF fixupCount >= 16 THEN Scanner.ScannerError(90) END;
  461. ptr := ADR(fixupQueue[fixupCount]);
  462. ptr^.word0 := kind;
  463. ptr^.long1 := value;
  464. INC(fixupCount);
  465. END;
  466. END QueueLongConst;
  467. PROCEDURE EmitTypedOp(subOp, typeKind : CARDINAL);
  468. VAR lastEntry: POINTER TO Record;
  469. extBase : CARDINAL;
  470. prevEntry: POINTER TO Record;
  471. PROCEDURE IsPowerOfTwo(target: CARDINAL): BOOLEAN;
  472. VAR
  473. i: CARDINAL;
  474. j: CARDINAL;
  475. BEGIN
  476. j := 1;
  477. i := 0;
  478. REPEAT
  479. IF j = target THEN lastEntry := ADDRESS(i); RETURN TRUE END;
  480. j := j * 2;
  481. INC(i);
  482. UNTIL i > 14;
  483. RETURN FALSE
  484. END IsPowerOfTwo;
  485. PROCEDURE Reserved36(): CARDINAL;
  486. BEGIN
  487. (* commented contents ? *)
  488. END Reserved36;
  489. BEGIN
  490. IF emitEnabled THEN
  491. IF fixupCount <> 0 THEN
  492. prevEntry := ADR(fixupQueue[fixupCount - 1]);
  493. IF prevEntry^.word0 = 1 THEN
  494. IF (subOp IN {6,7}) AND (typeKind <= 1) THEN
  495. IF subOp = 7 THEN prevEntry^.word1 := -INTEGER(prevEntry^.word1) END;
  496. IF fixupCount > 1 THEN
  497. IF fixupQueue[fixupCount - 2].word0 IN {1,4} THEN
  498. INC(fixupQueue[fixupCount - 2].word1, prevEntry^.word1);
  499. DEC(fixupCount);
  500. END; (* 04A9 *)
  501. END; (* 04A9 *)
  502. prevEntry^.word0 := 4;
  503. RETURN;
  504. ELSE (* 04AF *)
  505. IF (subOp IN {8,9}) AND (typeKind = 0) AND IsPowerOfTwo(prevEntry^.word1) THEN
  506. DEC(fixupCount);
  507. FlushConstQueue;
  508. IF lastEntry <> NIL THEN Emit2(subOp + OPMUL, lastEntry) END; (* 04CE *)
  509. RETURN
  510. ELSE (* 04D1 *)
  511. IF (subOp = 10) AND (typeKind <= 1) AND IsPowerOfTwo(prevEntry^.word1) THEN
  512. DEC(prevEntry^.word1);
  513. FlushConstQueue;
  514. Emit1(OPBITAND);
  515. RETURN
  516. ELSE (* 04EE *)
  517. IF (NOT Compiler.rangeCheckEnabled) AND (prevEntry^.word1 = 0)
  518. AND (subOp IN {0,1,3}) AND (typeKind <= ORD(subOp <> 3)) THEN
  519. DEC(fixupCount);
  520. FlushConstQueue;
  521. Emit1(OPEQ0 + ORD(subOp <> 0) * 32);
  522. RETURN
  523. END; (* 0512 *)
  524. END; (* 0512 *)
  525. END;
  526. END;
  527. END; (* 0512 *)
  528. END; (* 0512 *)
  529. FlushConstQueue;
  530. IF (typeKind = 5) OR (subOp = 18) THEN
  531. extBase := Scanner.EnterModuleSymbol("DOUBLES", 9567H) * 16;
  532. END; (* 0532 *)
  533. CASE typeKind OF
  534. | 0: (* 0536 *)
  535. IF subOp >= 15 THEN
  536. IF Compiler.rangeCheckEnabled THEN Emit1(125) ELSE Emit2(144,33) END;
  537. typeKind := 2;
  538. END; (* 054b *)
  539. | 1: (* 054c *)
  540. IF subOp >= 15 THEN
  541. Emit1(189);
  542. typeKind := 2;
  543. ELSE
  544. IF subOp IN {0,1,6,7,10} THEN typeKind := 0
  545. ELSIF subOp = 11 THEN Emit2(OPCOMPL, OPINC); RETURN
  546. END; (* 056E *)
  547. END; (* 056E *)
  548. | 2: (* 056f *)
  549. IF subOp <= 5 THEN Emit1(OPDCOMP); EmitSystemCall(23); typeKind := 0
  550. ELSIF subOp = 11 THEN
  551. Emit2(OPEXTENDED,3); RETURN
  552. END; (* 0589 *)
  553. | 3: (* 058a *)
  554. IF subOp <= 5 THEN
  555. Emit1(OPREALCMP); EmitSystemCall(23); typeKind := 0
  556. ELSIF subOp IN {11,12} THEN
  557. IF Compiler.rangeCheckEnabled THEN Emit1(subOp + OPSSW0)
  558. ELSE
  559. Emit1(OPSWAP);
  560. IF subOp = 11 THEN
  561. Emit2(OPLI15, OPPOWER2); Emit1(OPBITXOR);
  562. ELSE (* 05BD *)
  563. Emit1(OPLIW); EmitWord(7FFFH); Emit1(OPBITAND);
  564. END; (* 05c7 *)
  565. Emit1(OPSWAP);
  566. END; (* 05ca *)
  567. RETURN
  568. ELSIF subOp IN {13,14,15} THEN
  569. Emit1(OPFLOAT2LG);
  570. typeKind := 2;
  571. END; (* 05d9 *)
  572. | 4: (* 05da *)
  573. IF subOp <= 5 THEN
  574. IF subOp = 5 THEN
  575. Emit1(OPSWAP);
  576. subOp := 4;
  577. END; (* 05E9 *)
  578. IF subOp = 4 THEN Emit2(OPCOMPL, OPBITAND); Emit1(OPLI0); subOp := 0 END; (* 05F8 *)
  579. typeKind := 0
  580. ELSIF subOp = 7 THEN
  581. Emit1(OPCOMPL); subOp := 8
  582. END; (* 0606 *)
  583. | 5: (* 0607 *)
  584. IF subOp <> 18 THEN
  585. Emit1(OPEXTCALL1);
  586. IF subOp <= 5 THEN Emit1(extBase+5); typeKind := 0
  587. ELSIF subOp >= 13 THEN
  588. typeKind := ORD(subOp = 16) + 2;
  589. Emit1(extBase + typeKind - 1);
  590. ELSE Emit1(extBase + subOp)
  591. END; (* 0634*)
  592. IF Compiler.rangeCheckEnabled THEN
  593. Emit2(ORD(subOp <= 9)+1, (ORD(subOp IN {6,7,8,9,10,11,12})+1)*4);
  594. IF subOp <= 5 THEN EmitSystemCall(23) END;
  595. END; (* 064E *)
  596. IF typeKind = 5 THEN RETURN END;
  597. END; (* 0654 *)
  598. (* $T+ generate CaseSelectError exception *)
  599. END; (* 066c *)
  600. (* $T- *)
  601. IF subOp <= 12 THEN
  602. Emit1(subOp + typeKind * 16 + 160);
  603. ELSIF subOp - 13 <> typeKind THEN
  604. IF subOp <= 14 THEN
  605. IF typeKind <= 1 THEN Emit1(221) ELSE Emit1(subOp + 173) END;
  606. ELSIF subOp <= 16 THEN Emit1(typeKind + 188)
  607. ELSE (* 06A3 *)
  608. Emit2(OPEXTCALL1, extBase + typeKind + 1);
  609. IF Compiler.rangeCheckEnabled THEN Emit2(OPRAISE, 8) END;
  610. END; (* 06B1 *)
  611. END; (* 06B1 *)
  612. END; (* 06b1 *)
  613. END EmitTypedOp;
  614. PROCEDURE EmitExtendedOp(subOp, typeKind: CARDINAL);
  615. BEGIN
  616. IF emitEnabled THEN FlushConstQueue; Emit1(typeKind * 16 + subOp + 186) END;
  617. END EmitExtendedOp;
  618. PROCEDURE EmitStandardOp(stdNo: CARDINAL);
  619. VAR ptr: RecordPtr;
  620. BEGIN
  621. IF emitEnabled THEN
  622. IF (stdNo = 0) AND (fixupCount <> 0) THEN
  623. ptr := ADR(fixupQueue[fixupCount-1]);
  624. IF (ptr^.word0 = 1) AND (ptr^.word1 = 0) THEN
  625. DEC(fixupCount);
  626. FlushConstQueue;
  627. Emit1(OPLIMIT);
  628. RETURN
  629. END; (* 06EC *)
  630. END; (* 06EC *)
  631. FlushConstQueue;
  632. IF stdNo >= 23 THEN
  633. Emit1(OPEXTENDED);
  634. END; (* 06F7 *)
  635. (* $T+ *)
  636. Emit1( Compiler.keywordTable[stdNo][0] );
  637. (* $T- *)
  638. END; (* 0701 *)
  639. END EmitStandardOp;
  640. PROCEDURE EmitMiscOp(subOp, n: CARDINAL);
  641. BEGIN
  642. IF emitEnabled THEN
  643. FlushConstQueue;
  644. IF subOp = 5 THEN
  645. IF n >= 10 THEN
  646. Emit2(OPEXTENDED, n - 5)
  647. ELSIF n = 6 THEN
  648. IF Compiler.rangeCheckEnabled THEN Emit1(102)
  649. ELSE
  650. (* generates the bad CAP sequence *)
  651. Emit2(OPDUP, OPLIB); Emit2(040H, OPBITAND);
  652. Emit2(OPSHR, 1); Emit2(OPCOMPL, OPBITAND);
  653. END; (* 073D *)
  654. ELSE (* 073F *)
  655. (* $T+ *)
  656. Emit1(Compiler.keywordTable[n+27][0]);
  657. (* $T- *)
  658. END; (* 074B *)
  659. ELSE (* 074D *)
  660. IF subOp = 4 THEN
  661. Emit2(OPLONGREAL, 10);
  662. Emit1(n);
  663. ELSIF (subOp = 0) AND (n - 128 <= 3) AND (NOT Compiler.rangeCheckEnabled) THEN
  664. Emit1(n + 8)
  665. ELSE
  666. Emit2(subOp + 132, n)
  667. END; (* 0775 *)
  668. END; (* 0775 *)
  669. END; (* 0775 *)
  670. END EmitMiscOp;
  671. PROCEDURE EmitSystemCall(sysNo: CARDINAL);
  672. BEGIN
  673. IF emitEnabled THEN
  674. FlushConstQueue;
  675. IF Compiler.rangeCheckEnabled AND (sysNo <> 20) THEN Emit2(0,sysNo) END;
  676. END;
  677. END EmitSystemCall;
  678. PROCEDURE EmitExtCall3(a, b, c: CARDINAL);
  679. BEGIN
  680. IF emitEnabled THEN
  681. FlushConstQueue;
  682. IF Compiler.rangeCheckEnabled THEN
  683. IF a <> 19 THEN Emit2(0, a) END;
  684. Emit1(b);
  685. IF a >= 3 THEN Emit1(c) END;
  686. END; (* 07aa *)
  687. END;
  688. END EmitExtCall3;
  689. PROCEDURE OpenFixup(VAR fixPos: CARDINAL; shortJump: BOOLEAN);
  690. VAR prevOp: CARDINAL;
  691. BEGIN
  692. IF emitEnabled THEN
  693. fixPos := nextEmitPos;
  694. IF shortJump THEN
  695. prevOp := PeekCodeByte(nextEmitPos - 1);
  696. IF prevOp - 224 <= 1 THEN
  697. PokeCodeByte(prevOp + 2, nextEmitPos - 1);
  698. END;
  699. Emit1(0)
  700. ELSE EmitWord(0)
  701. END;
  702. END;
  703. END OpenFixup;
  704. PROCEDURE CloseFixup(fixPos: CARDINAL; shortJump: BOOLEAN);
  705. BEGIN
  706. IF emitEnabled THEN
  707. IF shortJump AND (nextEmitPos < fixPos + 254) THEN
  708. PokeCodeByte(PeekCodeByte(nextEmitPos - 1) + 4, nextEmitPos - 1);
  709. Emit1(nextEmitPos + 1 - fixPos);
  710. ELSE
  711. EmitWord(fixPos - (nextEmitPos + 1))
  712. END;
  713. END;
  714. END CloseFixup;
  715. PROCEDURE InsertFixup(fixPos: CARDINAL; shortJump: BOOLEAN): BOOLEAN;
  716. VAR
  717. holdByte: BYTE;
  718. prevByte: BYTE;
  719. gapPos: CARDINAL;
  720. moveSrc: ADDRESS;
  721. BEGIN
  722. IF emitEnabled THEN
  723. FlushConstQueue;
  724. gapPos := fixPos + 1;
  725. IF shortJump THEN
  726. IF nextEmitPos > gapPos + 254 THEN
  727. IF gapPos < windowBase THEN
  728. Files.SetPos(Scanner.codeFile, LONG(gapPos));
  729. Files.ReadByte(Scanner.codeFile, holdByte);
  730. INC(gapPos);
  731. WHILE gapPos < windowBase DO
  732. prevByte := holdByte;
  733. Files.ReadByte(Scanner.codeFile, holdByte);
  734. Files.SetPos(Scanner.codeFile, LONG(gapPos));
  735. Files.WriteByte(Scanner.codeFile, prevByte);
  736. INC(gapPos)
  737. END; (* 0842 *)
  738. MOVE(codeWindow, ADDRESS(codeWindow) + 1, nextEmitPos - windowBase);
  739. codeWindow^[0] := holdByte;
  740. ELSE (* 0850 *)
  741. moveSrc := ADDRESS(codeWindow) + gapPos - windowBase;
  742. MOVE(moveSrc, moveSrc + 1, nextEmitPos - gapPos);
  743. END; (* 085e *)
  744. INC(nextEmitPos);
  745. PokeCodeByte( PeekCodeByte(fixPos - 1) - 2, fixPos - 1);
  746. PokeCodeByte( (nextEmitPos - gapPos) MOD 256, fixPos);
  747. PokeCodeByte( (nextEmitPos - gapPos) DIV 256, gapPos);
  748. RETURN FALSE
  749. END; (* 087f *)
  750. PokeCodeByte(nextEmitPos - gapPos, fixPos);
  751. ELSE (* 0887 *)
  752. PokeCodeByte( (nextEmitPos - gapPos) MOD 256, fixPos);
  753. PokeCodeByte( (nextEmitPos - gapPos) DIV 256, gapPos);
  754. END; (* 0898 *)
  755. END; (* 0898 *)
  756. RETURN TRUE
  757. END InsertFixup;
  758. PROCEDURE AdjustFixup(fixPos: CARDINAL);
  759. VAR dist: CARDINAL;
  760. BEGIN
  761. IF emitEnabled THEN
  762. IF PeekCodeByte(fixPos - 1) <= 225 THEN
  763. dist := PeekCodeByte(fixPos) + PeekCodeByte(fixPos + 1) * 256;
  764. IF INTEGER(dist) > 0 THEN INC(dist) ELSE DEC(dist) END;
  765. PokeCodeByte( dist MOD 256, fixPos);
  766. PokeCodeByte( dist DIV 256, fixPos + 1);
  767. ELSE (* 08D2 *)
  768. PokeCodeByte( PeekCodeByte(fixPos) + 1, fixPos);
  769. END; (* 08D9 *)
  770. END; (* 08D9 *)
  771. END AdjustFixup;
  772. PROCEDURE MarkCodePos(n: CARDINAL): CARDINAL;
  773. BEGIN
  774. EmitSystemCall(n);
  775. RETURN nextEmitPos
  776. END MarkCodePos;
  777. PROCEDURE OpenEmitter;
  778. BEGIN
  779. emitEnabled := TRUE;
  780. pendActive := FALSE;
  781. fixupCount := 0;
  782. SeekCodeWindow;
  783. END OpenEmitter;
  784. PROCEDURE InitCodeGenerator;
  785. BEGIN
  786. checkOverflow := (execute = 4);
  787. codeWindow := ADDRESS(Scanner.codeBuffer);
  788. windowBase := 0;
  789. windowLimit := 4096;
  790. nextEmitPos := 16;
  791. OpenEmitter;
  792. END InitCodeGenerator;
  793. END CodeGen.