Interpreter.mod 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  1. IMPLEMENTATION MODULE Interpreter ;
  2. FROM Local IMPORT GetIP, SetIP, GetSP, SetSP, GetFP, GetGP, GetOFP, SetOFP, SetGP ;
  3. FROM Memory IMPORT ReadByte, WriteByte, ReadSlot, WriteSlot,
  4. ReadWord, WriteWord, CopyBytes, FillBytes, ArenaBase, MaxMem ;
  5. FROM Stack IMPORT Push, Pop, PopBool, PopReal, PushReal, Reserve ;
  6. FROM Instruction IMPORT Fetch, FetchSignedByte, FetchQuad, LoadString,
  7. ProcedureAddress, Enter, Leave ;
  8. FROM Global IMPORT GetModuleBase, GetModuleProcs, GetCurrentModule,
  9. SetCurrentModule, FindModuleByBase ;
  10. FROM Console IMPORT Fatal, WriteChar ;
  11. FROM Extended IMPORT Execute ;
  12. FROM StdChans IMPORT StdInChan ;
  13. FROM IOChan IMPORT Look, Skip ;
  14. FROM IOConsts IMPORT ReadResults, endOfLine, endOfInput ;
  15. PROCEDURE PushBool (b: BOOLEAN) ;
  16. BEGIN
  17. IF b THEN Push (1) ELSE Push (0) END ;
  18. END PushBool ;
  19. PROCEDURE Shl64 (u: LONGCARD; n: CARDINAL) : LONGCARD ;
  20. VAR i: CARDINAL ;
  21. BEGIN
  22. IF n >= 64 THEN
  23. RETURN 0 ;
  24. END ;
  25. FOR i := 1 TO n DO
  26. u := u * 2 ;
  27. END ;
  28. RETURN u ;
  29. END Shl64 ;
  30. PROCEDURE ShrLog (u: LONGCARD; n: CARDINAL) : LONGCARD ;
  31. VAR i: CARDINAL ;
  32. BEGIN
  33. IF n >= 64 THEN
  34. RETURN 0 ;
  35. END ;
  36. FOR i := 1 TO n DO
  37. u := u DIV 2 ;
  38. END ;
  39. RETURN u ;
  40. END ShrLog ;
  41. PROCEDURE Mul64 (a, b: LONGCARD) : LONGCARD ;
  42. VAR ah, al, bh, bl, lolo, mid: LONGCARD ;
  43. BEGIN
  44. ah := a DIV 4294967296 ;
  45. al := a MOD 4294967296 ;
  46. bh := b DIV 4294967296 ;
  47. bl := b MOD 4294967296 ;
  48. lolo := al * bl ;
  49. mid := VAL (LONGCARD, VAL (CARDINAL, ah * bl + al * bh)) ;
  50. RETURN lolo + mid * 4294967296 ;
  51. END Mul64 ;
  52. PROCEDURE Low32 (u: LONGCARD) : CARDINAL ;
  53. BEGIN
  54. RETURN VAL (CARDINAL, u) ;
  55. END Low32 ;
  56. PROCEDURE BitOp (a, b: LONGCARD; mode: CARDINAL) : LONGCARD ;
  57. VAR res, m: LONGCARD ; p: CARDINAL ; ba, bb: CARDINAL ;
  58. BEGIN
  59. res := 0 ;
  60. m := 1 ;
  61. FOR p := 0 TO 63 DO
  62. ba := VAL (CARDINAL, (a DIV m) MOD 2) ;
  63. bb := VAL (CARDINAL, (b DIV m) MOD 2) ;
  64. IF mode = 0 THEN (* AND *)
  65. IF (ba = 1) AND (bb = 1) THEN res := res + m END ;
  66. ELSIF mode = 1 THEN (* OR *)
  67. IF (ba = 1) OR (bb = 1) THEN res := res + m END ;
  68. ELSE (* XOR *)
  69. IF ba # bb THEN res := res + m END ;
  70. END ;
  71. m := m * 2 ;
  72. END ;
  73. RETURN res ;
  74. END BitOp ;
  75. PROCEDURE ReadLine (dst: LONGCARD) ;
  76. (* SYSTEM service 2 : read one line from the host standard input.
  77. Characters up to (but not including) the line mark, or end of input,
  78. are stored at dst; a NUL terminator is appended and the VM stack
  79. receives the number of bytes read (excluding the terminator).
  80. An empty line or immediate end of input yields 0. *)
  81. VAR p: LONGCARD ; ch: CHAR ; res: ReadResults ;
  82. done, over: BOOLEAN ;
  83. BEGIN
  84. p := dst ;
  85. done := FALSE ;
  86. over := FALSE ;
  87. WHILE NOT done DO
  88. Look (StdInChan (), ch, res) ;
  89. IF res = endOfInput THEN
  90. done := TRUE ;
  91. ELSIF res = endOfLine THEN
  92. Skip (StdInChan ()) ;
  93. done := TRUE ;
  94. ELSIF over THEN
  95. Skip (StdInChan ()) ;
  96. ELSIF p >= VAL (LONGCARD, MaxMem) THEN
  97. over := TRUE ;
  98. ELSE
  99. WriteByte (p, ORD (ch)) ;
  100. p := p + 1 ;
  101. Skip (StdInChan ()) ;
  102. END ;
  103. END ;
  104. IF p < VAL (LONGCARD, MaxMem) THEN
  105. WriteByte (p, 0) ;
  106. p := p + 1 ;
  107. END ;
  108. Push (p - dst - 1) ;
  109. END ReadLine ;
  110. PROCEDURE Service (id, param: LONGCARD) ;
  111. VAR c: CARDINAL ; p: LONGCARD ;
  112. BEGIN
  113. CASE id OF
  114. | 0 : (* EXIT *)
  115. RETURN ;
  116. | 1 : (* write NUL-terminated string at param *)
  117. p := param ;
  118. c := ReadByte (p) ;
  119. WHILE c # 0 DO
  120. WriteChar (CHR (c)) ;
  121. p := p + 1 ;
  122. c := ReadByte (p) ;
  123. END ;
  124. | 2 : (* read line into buffer at param *)
  125. ReadLine (param) ;
  126. ELSE
  127. Fatal ("system: unknown service") ;
  128. END ;
  129. END Service ;
  130. PROCEDURE Run ;
  131. VAR opc, n, m, tm, lo, hi, nw: CARDINAL ;
  132. v, w, a, b, p, q, sz, sz2, ssz, t, off, cell, loww, highw, last,
  133. st, dv, src, dst, first, eot, np, rel, md: LONGCARD ;
  134. sgn: LONGINT ;
  135. gl, bl: LONGINT ;
  136. r1, r2: REAL ;
  137. i64: LONGCARD ;
  138. i: LONGCARD ;
  139. done: BOOLEAN ;
  140. BEGIN
  141. done := FALSE ;
  142. LOOP
  143. opc := Fetch () ;
  144. CASE opc OF
  145. | 00H : (* reserved -> IllegalInstruction *)
  146. Fatal ("illegal instruction 00H") ;
  147. | 01H : (* RAISE : unimplemented *)
  148. Fatal ("RAISE unimplemented") ;
  149. | 02H : (* load_proc_addr u8 *)
  150. n := Fetch () ;
  151. Push (ProcedureAddress (GetCurrentModule (), n)) ;
  152. | 03H .. 07H : (* load_param n : push FP[op] for params 1..5 *)
  153. Push (ReadSlot (GetFP () + VAL (LONGCARD, opc) * 8)) ;
  154. | 08H : (* load_local_dw i8 *)
  155. Push (ReadSlot (GetFP () + VAL (LONGCARD, FetchSignedByte ()) * 8)) ;
  156. | 09H : (* load_global_dw u8 *)
  157. Push (ReadSlot (GetGP () + VAL (LONGCARD, Fetch ()) * 8)) ;
  158. | 0AH : (* load_stack_dw u8 *)
  159. p := Pop () ;
  160. Push (ReadSlot (p + VAL (LONGCARD, Fetch ()) * 8)) ;
  161. | 0BH : (* load_extern_dw mod,var *)
  162. m := Fetch () ;
  163. Push (ReadSlot (GetModuleBase (m) + VAL (LONGCARD, Fetch ()) * 8)) ;
  164. | 0CH : (* load_extern_w nibble *)
  165. nw := Fetch () ;
  166. Push (ReadSlot (GetModuleBase (nw DIV 16) + VAL (LONGCARD, nw MOD 16) * 8)) ;
  167. | 0DH : (* load_indexed_byte *)
  168. v := Pop () ; p := Pop () ;
  169. Push (VAL (LONGCARD, ReadByte (p + v))) ;
  170. | 0EH : (* load_indexed_w *)
  171. v := Pop () ; p := Pop () ;
  172. Push (ReadSlot (p + v * 8)) ;
  173. | 0FH : (* load_indexed_q *)
  174. v := Pop () ; p := Pop () ;
  175. Push (ReadSlot (p + v * 8 + 8)) ;
  176. Push (ReadSlot (p + v * 8)) ;
  177. | 10H : (* load_outer : push enclosing frame pointer *)
  178. Push (GetOFP ()) ;
  179. | 11H : (* load_outer_n u8 : walk the display *)
  180. np := Fetch () ;
  181. p := GetOFP () ;
  182. i := 0 ;
  183. WHILE i < VAL (LONGCARD, np) DO
  184. p := ReadSlot (p) ;
  185. i := i + 1 ;
  186. END ;
  187. Push (p) ;
  188. | 12H : (* LONGREAL/quad sub-opcode dispatch ... *)
  189. nw := Fetch () ;
  190. CASE nw OF
  191. | 0 : (* load_local_q i8 *)
  192. sgn := VAL (LONGINT, FetchSignedByte ()) ;
  193. Push (ReadSlot (GetFP () + (VAL (LONGCARD, sgn) + 1) * 8)) ;
  194. Push (ReadSlot (GetFP () + VAL (LONGCARD, sgn) * 8)) ;
  195. | 1 : (* load_global_q u8 *)
  196. n := Fetch () ;
  197. Push (ReadSlot (GetGP () + (VAL (LONGCARD, n) + 1) * 8)) ;
  198. Push (ReadSlot (GetGP () + VAL (LONGCARD, n) * 8)) ;
  199. | 2 : (* load_i_q u8 *)
  200. n := Fetch () ;
  201. p := Pop () ;
  202. Push (ReadSlot (p + (VAL (LONGCARD, n) + 1) * 8)) ;
  203. Push (ReadSlot (p + VAL (LONGCARD, n) * 8)) ;
  204. | 3 : (* load_extern_q mod,var *)
  205. m := Fetch () ;
  206. n := Fetch () ;
  207. Push (ReadSlot (GetModuleBase (m) + (VAL (LONGCARD, n) + 1) * 8)) ;
  208. Push (ReadSlot (GetModuleBase (m) + VAL (LONGCARD, n) * 8)) ;
  209. | 4 : (* store_local_q i8 *)
  210. sgn := VAL (LONGINT, FetchSignedByte ()) ;
  211. loww := Pop () ; a := Pop () ;
  212. WriteSlot (GetFP () + VAL (LONGCARD, sgn) * 8, loww) ;
  213. WriteSlot (GetFP () + (VAL (LONGCARD, sgn) + 1) * 8, a) ;
  214. | 5 : (* store_global_q u8 *)
  215. n := Fetch () ;
  216. q := Pop () ;
  217. WriteSlot (GetGP () + VAL (LONGCARD, n) * 8, q) ;
  218. q := Pop () ;
  219. WriteSlot (GetGP () + (VAL (LONGCARD, n) + 1) * 8, q) ;
  220. | 6 : (* store_i_q u8 *)
  221. n := Fetch () ;
  222. p := Pop () ;
  223. q := Pop () ;
  224. WriteSlot (p + VAL (LONGCARD, n) * 8, q) ;
  225. q := Pop () ;
  226. WriteSlot (p + (VAL (LONGCARD, n) + 1) * 8, q) ;
  227. | 7 : (* store_extern_q mod,var *)
  228. m := Fetch () ;
  229. n := Fetch () ;
  230. q := Pop () ;
  231. WriteSlot (GetModuleBase (m) + VAL (LONGCARD, n) * 8, q) ;
  232. q := Pop () ;
  233. WriteSlot (GetModuleBase (m) + (VAL (LONGCARD, n) + 1) * 8, q) ;
  234. | 8 : (* load_indexed_q *)
  235. v := Pop () ; p := Pop () ;
  236. Push (ReadSlot (p + v * 8 + 8)) ;
  237. Push (ReadSlot (p + v * 8)) ;
  238. | 9 : (* store_indexed_q *)
  239. loww := Pop () ; a := Pop () ; v := Pop () ; p := Pop () ;
  240. WriteSlot (p + v * 8, loww) ;
  241. WriteSlot (p + v * 8 + 8, a) ;
  242. | 0AH : (* quad_fct_leave u8 *)
  243. n := Fetch () ;
  244. q := Pop () ;
  245. Leave (n) ;
  246. Push (q) ;
  247. ELSE
  248. Fatal ("quad sub-opcode illegal") ;
  249. END ; (* inner CASE *)
  250. | 13H .. 17H : (* store_param n : FP[op] := value *)
  251. WriteSlot (GetFP () + VAL (LONGCARD, opc) * 8, Pop ()) ;
  252. | 18H : (* store_local_dw i8 *)
  253. WriteSlot (GetFP () + VAL (LONGCARD, FetchSignedByte ()) * 8, Pop ()) ;
  254. | 19H : (* store_global_dw u8 *)
  255. WriteSlot (GetGP () + VAL (LONGCARD, Fetch ()) * 8, Pop ()) ;
  256. | 1AH : (* store_stack_dw u8 *)
  257. p := Pop () ;
  258. WriteSlot (p + VAL (LONGCARD, Fetch ()) * 8, Pop ()) ;
  259. | 1BH : (* store_extern_dw mod,var *)
  260. m := Fetch () ;
  261. WriteSlot (GetModuleBase (m) + VAL (LONGCARD, Fetch ()) * 8, Pop ()) ;
  262. | 1CH : (* store_extern_w nibble *)
  263. nw := Fetch () ;
  264. WriteSlot (GetModuleBase (nw DIV 16) + VAL (LONGCARD, nw MOD 16) * 8, Pop ()) ;
  265. | 1DH : (* store_indexed_byte *)
  266. v := Pop () ; i64 := Pop () ; p := Pop () ;
  267. WriteByte (p + i64, Low32 (v)) ;
  268. | 1EH : (* store_indexed_w *)
  269. v := Pop () ; i64 := Pop () ; p := Pop () ;
  270. WriteSlot (p + i64 * 8, v) ;
  271. | 1FH : (* store_indexed_q *)
  272. loww := Pop () ; a := Pop () ; i64 := Pop () ; p := Pop () ;
  273. WriteSlot (p + i64 * 8, loww) ;
  274. WriteSlot (p + i64 * 8 + 8, a) ;
  275. | 20H : (* dup *)
  276. v := Pop () ;
  277. Push (v) ; Push (v) ;
  278. | 21H : (* swap *)
  279. a := Pop () ; b := Pop () ;
  280. Push (a) ; Push (b) ;
  281. | 22H .. 2BH : (* load_local_n *)
  282. Push (ReadSlot (GetFP () - VAL (LONGCARD, opc MOD 16) * 8)) ;
  283. | 2CH : (* load_local i8 *)
  284. Push (ReadSlot (GetFP () + VAL (LONGCARD, FetchSignedByte ()) * 8)) ;
  285. | 2DH : (* load_global u8 *)
  286. Push (ReadSlot (GetGP () + VAL (LONGCARD, Fetch ()) * 8)) ;
  287. | 2EH : (* load_stack u8 *)
  288. p := Pop () ;
  289. Push (ReadSlot (p + VAL (LONGCARD, Fetch ()) * 8)) ;
  290. | 2FH : (* load_extern mod,var *)
  291. m := Fetch () ;
  292. Push (ReadSlot (GetModuleBase (m) + VAL (LONGCARD, Fetch ()) * 8)) ;
  293. | 30H : (* copy_block *)
  294. sz := Pop () ; src := Pop () ; dst := Pop () ;
  295. CopyBytes (src, dst, sz) ;
  296. | 31H : (* copy_string *)
  297. ssz := Pop () ; sz := Pop () ; src := Pop () ; dst := Pop () ;
  298. n := 0 ;
  299. np := 0 ;
  300. WHILE np < sz DO
  301. IF ReadByte (src + np) = 0 THEN EXIT END ;
  302. IF np >= ssz THEN EXIT END ;
  303. WriteByte (dst + np, ReadByte (src + np)) ;
  304. np := np + 1 ;
  305. END ;
  306. | 32H .. 3BH : (* store_local_n *)
  307. WriteSlot (GetFP () - VAL (LONGCARD, opc MOD 16) * 8, Pop ()) ;
  308. | 3CH : (* store_local i8 *)
  309. WriteSlot (GetFP () + VAL (LONGCARD, FetchSignedByte ()) * 8, Pop ()) ;
  310. | 3DH : (* store_global u8 *)
  311. WriteSlot (GetGP () + VAL (LONGCARD, Fetch ()) * 8, Pop ()) ;
  312. | 3EH : (* store_stack u8 *)
  313. p := Pop () ;
  314. WriteSlot (p + VAL (LONGCARD, Fetch ()) * 8, Pop ()) ;
  315. | 3FH : (* store_extern mod,var *)
  316. m := Fetch () ;
  317. WriteSlot (GetModuleBase (m) + VAL (LONGCARD, Fetch ()) * 8, Pop ()) ;
  318. | 40H :
  319. Execute () ;
  320. | 41H : (* load_stack_d0 *)
  321. p := Pop () ;
  322. IF p = 0 THEN Fatal ("NIL dereference") END ;
  323. Push (ReadSlot (p)) ;
  324. | 42H .. 4FH : (* load_global_n *)
  325. Push (ReadSlot (GetGP () + VAL (LONGCARD, opc MOD 16) * 8)) ;
  326. | 50H : (* end_program *)
  327. RETURN ;
  328. | 51H : (* store_stack_d0 *)
  329. p := Pop () ;
  330. IF p = 0 THEN Fatal ("NIL dereference") END ;
  331. WriteSlot (p, Pop ()) ;
  332. | 52H .. 5FH : (* store_global_n *)
  333. WriteSlot (GetGP () + VAL (LONGCARD, opc MOD 16) * 8, Pop ()) ;
  334. | 60H .. 6FH : (* load_i_n *)
  335. p := Pop () ;
  336. IF p = 0 THEN Fatal ("NIL dereference") END ;
  337. Push (ReadSlot (p + VAL (LONGCARD, opc MOD 16) * 8)) ;
  338. | 70H .. 7FH : (* store_i_n *)
  339. v := Pop () ; p := Pop () ;
  340. IF p = 0 THEN Fatal ("NIL dereference") END ;
  341. WriteSlot (p + VAL (LONGCARD, opc MOD 16) * 8, v) ;
  342. | 80H : (* load_local_addr i8 *)
  343. Push (GetFP () + VAL (LONGCARD, FetchSignedByte ()) * 8) ;
  344. | 81H : (* load_global_addr u8 *)
  345. Push (GetGP () + VAL (LONGCARD, Fetch ()) * 8) ;
  346. | 82H : (* load_stack_addr u8 *)
  347. p := Pop () ;
  348. Push (p + VAL (LONGCARD, Fetch ()) * 8) ;
  349. | 83H : (* load_extern_addr mod,var *)
  350. m := Fetch () ;
  351. Push (GetModuleBase (m) + VAL (LONGCARD, Fetch ()) * 8) ;
  352. | 84H : (* proc_leave *)
  353. Leave (Fetch ()) ;
  354. | 85H : (* fct_leave *)
  355. v := Pop () ;
  356. Leave (Fetch ()) ;
  357. Push (v) ;
  358. | 86H : (* longfct_leave *)
  359. q := Pop () ;
  360. Leave (Fetch ()) ;
  361. Push (q) ;
  362. | 87H : (* asmcode *)
  363. Fatal ("asmcode unimplemented") ;
  364. | 88H .. 8BH : (* leave 0..3, outer return *)
  365. Leave (128 + (opc MOD 4)) ;
  366. | 8CH : (* call_rel u8 *)
  367. LoadString (Fetch ()) ;
  368. | 8DH : (* load_imm_byte *)
  369. Push (VAL (LONGCARD, Fetch ())) ;
  370. | 8EH : (* load_imm_word u64 *)
  371. Push (FetchQuad ()) ;
  372. | 8FH : (* load_imm_quad (16 bytes) : high word first, low on top *)
  373. a := FetchQuad () ;
  374. b := FetchQuad () ;
  375. Push (a) ; Push (b) ;
  376. | 90H .. 9FH : (* load_imm 0..15 *)
  377. Push (VAL (LONGCARD, opc MOD 16)) ;
  378. | 0A0H : (* equal *)
  379. b := Pop () ; a := Pop () ;
  380. PushBool (a = b) ;
  381. | 0A1H : (* not_equal *)
  382. b := Pop () ; a := Pop () ;
  383. PushBool (a # b) ;
  384. | 0A2H : (* uless *)
  385. b := Pop () ; a := Pop () ;
  386. PushBool (Low32 (a) < Low32 (b)) ;
  387. | 0A3H : (* ugreater *)
  388. b := Pop () ; a := Pop () ;
  389. PushBool (Low32 (a) > Low32 (b)) ;
  390. | 0A4H : (* uless_eq *)
  391. b := Pop () ; a := Pop () ;
  392. PushBool (Low32 (a) <= Low32 (b)) ;
  393. | 0A5H : (* ugreater_eq *)
  394. b := Pop () ; a := Pop () ;
  395. PushBool (Low32 (a) >= Low32 (b)) ;
  396. | 0A6H : (* add (CARDINAL mod 2^32) *)
  397. b := Pop () ; a := Pop () ;
  398. Push (VAL (LONGCARD, Low32 (a) + Low32 (b))) ;
  399. | 0A7H : (* sub *)
  400. b := Pop () ; a := Pop () ;
  401. Push (VAL (LONGCARD, Low32 (a) - Low32 (b))) ;
  402. | 0A8H : (* umul *)
  403. b := Pop () ; a := Pop () ;
  404. Push (VAL (LONGCARD, Low32 (a) * Low32 (b))) ;
  405. | 0A9H : (* udiv *)
  406. b := Pop () ; a := Pop () ;
  407. IF Low32 (b) = 0 THEN Fatal ("divide by zero") END ;
  408. Push (VAL (LONGCARD, Low32 (a) DIV Low32 (b))) ;
  409. | 0AAH : (* umod *)
  410. b := Pop () ; a := Pop () ;
  411. IF Low32 (b) = 0 THEN Fatal ("divide by zero") END ;
  412. Push (VAL (LONGCARD, Low32 (a) MOD Low32 (b))) ;
  413. | 0ABH : (* eq0 *)
  414. PushBool (Pop () = 0) ;
  415. | 0ACH : (* inc *)
  416. Push (VAL (LONGCARD, Low32 (Pop ()) + 1)) ;
  417. | 0ADH : (* dec *)
  418. Push (VAL (LONGCARD, Low32 (Pop ()) - 1)) ;
  419. | 0AEH : (* add_imm u8 *)
  420. Push (VAL (LONGCARD, Low32 (Pop ()) + Fetch ())) ;
  421. | 0AFH : (* sub_imm u8 *)
  422. Push (VAL (LONGCARD, Low32 (Pop ()) - Fetch ())) ;
  423. | 0B0H : (* shl_imm u8 *)
  424. n := Fetch () ;
  425. v := Pop () ;
  426. IF n >= 32 THEN
  427. Push (0) ;
  428. ELSE
  429. Push (VAL (LONGCARD, Low32 (v) * VAL (CARDINAL, Shl64 (1, n)))) ;
  430. END ;
  431. | 0B1H : (* shr_imm *)
  432. n := Fetch () ;
  433. v := Pop () ;
  434. IF n >= 32 THEN
  435. Push (0) ;
  436. ELSE
  437. Push (VAL (LONGCARD, Low32 (v) DIV VAL (CARDINAL, Shl64 (1, n)))) ;
  438. END ;
  439. | 0B2H : (* iless *)
  440. b := Pop () ; a := Pop () ;
  441. PushBool (VAL (INTEGER, Low32 (a)) < VAL (INTEGER, Low32 (b))) ;
  442. | 0B3H : (* igreater *)
  443. b := Pop () ; a := Pop () ;
  444. PushBool (VAL (INTEGER, Low32 (a)) > VAL (INTEGER, Low32 (b))) ;
  445. | 0B4H : (* iless_eq *)
  446. b := Pop () ; a := Pop () ;
  447. PushBool (VAL (INTEGER, Low32 (a)) <= VAL (INTEGER, Low32 (b))) ;
  448. | 0B5H : (* igreater_eq *)
  449. b := Pop () ; a := Pop () ;
  450. PushBool (VAL (INTEGER, Low32 (a)) >= VAL (INTEGER, Low32 (b))) ;
  451. | 0B6H : (* not *)
  452. PushBool (NOT PopBool ()) ;
  453. | 0B7H : (* complement (32-bit ~) *)
  454. Push (VAL (LONGCARD, 0FFFFFFFFH - Low32 (Pop ()))) ;
  455. | 0B8H : (* imul (INTEGER mod 2^32) *)
  456. b := Pop () ; a := Pop () ;
  457. Push (VAL (LONGCARD, Low32 (a) * Low32 (b))) ;
  458. | 0B9H : (* idiv *)
  459. b := Pop () ; a := Pop () ;
  460. IF Low32 (b) = 0 THEN Fatal ("divide by zero") END ;
  461. Push (VAL (LONGCARD, VAL (INTEGER, Low32 (a)) DIV VAL (INTEGER, Low32 (b)))) ;
  462. | 0BAH : (* long_to_card *)
  463. Push (VAL (LONGCARD, Low32 (Pop ()))) ;
  464. | 0BBH : (* long_to_int *)
  465. v := Pop () ;
  466. Push (VAL (LONGCARD, VAL (INTEGER, Low32 (v)))) ;
  467. | 0BCH : (* abs *)
  468. v := Pop () ;
  469. IF VAL (INTEGER, Low32 (v)) < 0 THEN
  470. Push (VAL (LONGCARD, 0 - VAL (INTEGER, Low32 (v)))) ;
  471. ELSE
  472. Push (v) ;
  473. END ;
  474. | 0BDH : (* int_to_long *)
  475. Push (VAL (LONGCARD, VAL (INTEGER, Low32 (Pop ())))) ;
  476. | 0BEH : (* long_to_real *)
  477. PushReal (FLOAT (VAL (LONGINT, Pop ()))) ;
  478. | 0BFH : (* real_to_long *)
  479. Push (VAL (LONGCARD, VAL (INTEGER, TRUNC (PopReal ())))) ;
  480. | 0C0H : (* uadd_checked *)
  481. b := Pop () ; a := Pop () ;
  482. IF Low32 (a) + Low32 (b) < Low32 (a) THEN Fatal ("overflow") END ;
  483. Push (VAL (LONGCARD, Low32 (a) + Low32 (b))) ;
  484. | 0C1H : (* usub_checked *)
  485. b := Pop () ; a := Pop () ;
  486. IF Low32 (a) < Low32 (b) THEN Fatal ("overflow") END ;
  487. Push (VAL (LONGCARD, Low32 (a) - Low32 (b))) ;
  488. | 0C2H : (* umul_checked *)
  489. b := Pop () ; a := Pop () ;
  490. w := VAL (LONGCARD, Low32 (a)) * VAL (LONGCARD, Low32 (b)) ;
  491. IF w > 0FFFFFFFFH THEN Fatal ("overflow") END ;
  492. Push (VAL (LONGCARD, Low32 (a) * Low32 (b))) ;
  493. | 0C3H : (* system host call *)
  494. v := Pop () ;
  495. Service (v, Pop ()) ;
  496. | 0C4H : (* string_comp *)
  497. ssz := Pop () ; sz := Pop () ; src := Pop () ; dst := Pop () ;
  498. np := 0 ;
  499. last := 0 ;
  500. done := FALSE ;
  501. WHILE NOT done DO
  502. IF (np >= sz) OR (np >= ssz) THEN done := TRUE
  503. ELSIF ReadByte (src + np) = 0 THEN
  504. IF ReadByte (dst + np) # 0 THEN last := 1 END ;
  505. done := TRUE
  506. ELSIF ReadByte (src + np) > ReadByte (dst + np) THEN
  507. last := 2 ; done := TRUE
  508. ELSIF ReadByte (src + np) < ReadByte (dst + np) THEN
  509. last := 1 ; done := TRUE
  510. ELSE
  511. np := np + 1 ;
  512. END ;
  513. END ;
  514. IF last = 1 THEN
  515. Push (1) ; Push (0) ;
  516. ELSIF last = 2 THEN
  517. Push (0) ; Push (1) ;
  518. ELSE
  519. Push (0) ; Push (0) ;
  520. END ;
  521. | 0C5H : (* long_compare : push (a>b) then (a<b) *)
  522. b := Pop () ; a := Pop () ;
  523. gl := VAL (LONGINT, a) ; bl := VAL (LONGINT, b) ;
  524. IF gl > bl THEN Push (1) ELSE Push (0) END ;
  525. IF gl < bl THEN Push (1) ELSE Push (0) END ;
  526. | 0C6H : (* long_add *)
  527. b := Pop () ; a := Pop () ;
  528. Push (a + b) ;
  529. | 0C7H : (* long_sub *)
  530. b := Pop () ; a := Pop () ;
  531. Push (a - b) ;
  532. | 0C8H : (* long_mul *)
  533. b := Pop () ; a := Pop () ;
  534. Push (Mul64 (a, b)) ;
  535. | 0C9H : (* long_div *)
  536. b := Pop () ; a := Pop () ;
  537. IF b = 0 THEN Fatal ("divide by zero") END ;
  538. Push (VAL (LONGCARD, VAL (LONGINT, a) DIV VAL (LONGINT, b))) ;
  539. | 0CAH : (* long_mod *)
  540. b := Pop () ; a := Pop () ;
  541. IF b = 0 THEN Fatal ("divide by zero") END ;
  542. Push (VAL (LONGCARD, VAL (LONGINT, a) MOD VAL (LONGINT, b))) ;
  543. | 0CBH : (* not_zero *)
  544. PushBool (Pop () # 0) ;
  545. | 0CCH : (* long_abs *)
  546. v := Pop () ;
  547. IF VAL (LONGINT, v) < 0 THEN
  548. Push (0 - v) ;
  549. ELSE
  550. Push (v) ;
  551. END ;
  552. | 0CDH : (* switch *)
  553. v := Pop () ;
  554. loww := FetchQuad () ;
  555. highw := FetchQuad () ;
  556. t := FetchQuad () ; (* retOffset, must be 0 *)
  557. first := GetIP () ;
  558. eot := first + (highw - loww + 1) * 8 ;
  559. IF (v < loww) OR (v > highw) THEN
  560. SetIP (eot) ;
  561. ELSE
  562. cell := first + (v - loww) * 8 ;
  563. off := ReadSlot (cell) ;
  564. IF VAL (LONGINT, off) < 0 THEN
  565. Push (eot + t) ;
  566. END ;
  567. SetIP (cell + 8 + off) ;
  568. END ;
  569. | 0CEH : (* jump_stack : computed jump *)
  570. SetIP (Pop ()) ;
  571. | 0CFH : (* push_code_addr u64 *)
  572. off := FetchQuad () ;
  573. Push (GetIP () - 1 + off) ;
  574. | 0D0H : (* iadd_checked *)
  575. b := Pop () ; a := Pop () ;
  576. tm := VAL (INTEGER, Low32 (a)) + VAL (INTEGER, Low32 (b)) ;
  577. IF ((VAL (INTEGER, Low32 (a)) > 0) AND (VAL (INTEGER, Low32 (b)) > 0)
  578. AND (tm < 0)) OR
  579. ((VAL (INTEGER, Low32 (a)) < 0) AND (VAL (INTEGER, Low32 (b)) < 0)
  580. AND (tm >= 0)) THEN
  581. Fatal ("overflow") ;
  582. END ;
  583. Push (VAL (LONGCARD, tm)) ;
  584. | 0D1H : (* isub_checked *)
  585. b := Pop () ; a := Pop () ;
  586. tm := VAL (INTEGER, Low32 (a)) - VAL (INTEGER, Low32 (b)) ;
  587. IF ((VAL (INTEGER, Low32 (a)) > 0) AND (VAL (INTEGER, Low32 (b)) < 0)
  588. AND (tm < 0)) OR
  589. ((VAL (INTEGER, Low32 (a)) < 0) AND (VAL (INTEGER, Low32 (b)) > 0)
  590. AND (tm >= 0)) THEN
  591. Fatal ("overflow") ;
  592. END ;
  593. Push (VAL (LONGCARD, tm)) ;
  594. | 0D2H : (* reserve *)
  595. sz := Pop () ;
  596. IF GetSP () < sz THEN Fatal ("stack overflow") END ;
  597. SetSP (GetSP () - sz) ;
  598. Push (GetSP ()) ;
  599. | 0D3H : (* reserve_string *)
  600. st := Pop () ;
  601. sz := Pop () ;
  602. nw := VAL (CARDINAL, (sz + 7) DIV 8) ;
  603. dst := GetSP () - VAL (LONGCARD, nw) * 8 ;
  604. SetSP (dst) ;
  605. i := 0 ;
  606. WHILE i < VAL (LONGCARD, nw) DO
  607. WriteSlot (dst + i * 8, ReadSlot (st + i * 8)) ;
  608. i := i + 1 ;
  609. END ;
  610. Push (dst) ;
  611. | 0D4H : (* enter u8 *)
  612. Enter (Fetch ()) ;
  613. | 0D5H : (* real_compare *)
  614. r2 := PopReal () ; r1 := PopReal () ;
  615. IF r1 > r2 THEN Push (1) ELSE Push (0) END ;
  616. IF r1 < r2 THEN Push (1) ELSE Push (0) END ;
  617. | 0D6H : (* real_add *)
  618. r2 := PopReal () ; r1 := PopReal () ;
  619. PushReal (r1 + r2) ;
  620. | 0D7H : (* real_sub *)
  621. r2 := PopReal () ; r1 := PopReal () ;
  622. PushReal (r1 - r2) ;
  623. | 0D8H : (* real_mul *)
  624. r2 := PopReal () ; r1 := PopReal () ;
  625. PushReal (r1 * r2) ;
  626. | 0D9H : (* real_div *)
  627. r2 := PopReal () ; r1 := PopReal () ;
  628. PushReal (r1 / r2) ;
  629. | 0DAH : (* urange_check *)
  630. sz := Pop () ; loww := Pop () ; v := Pop () ;
  631. IF (v < loww) OR (v >= loww + sz) THEN Fatal ("range error") END ;
  632. | 0DBH : (* irange_check *)
  633. sz := Pop () ; loww := Pop () ; v := Pop () ;
  634. IF (VAL (INTEGER, Low32 (v)) < VAL (INTEGER, Low32 (loww))) OR
  635. (VAL (INTEGER, Low32 (v)) >=
  636. VAL (INTEGER, Low32 (loww)) + VAL (INTEGER, Low32 (sz))) THEN
  637. Fatal ("range error") ;
  638. END ;
  639. | 0DCH : (* limit_check u8 *)
  640. n := Fetch () ;
  641. v := Pop () ; Push (v) ;
  642. IF v > VAL (LONGCARD, n) THEN Fatal ("range error") END ;
  643. | 0DDH : (* check_positive *)
  644. v := Pop () ; Push (v) ;
  645. IF VAL (INTEGER, Low32 (v)) < 0 THEN Fatal ("range error") END ;
  646. | 0DEH : (* and_jp u8 *)
  647. n := Fetch () ;
  648. IF NOT PopBool () THEN
  649. Push (0) ;
  650. SetIP (GetIP () + VAL (LONGCARD, n)) ;
  651. END ;
  652. | 0DFH : (* or_jp u8 *)
  653. n := Fetch () ;
  654. IF PopBool () THEN
  655. Push (1) ;
  656. SetIP (GetIP () + VAL (LONGCARD, n)) ;
  657. END ;
  658. | 0E0H : (* jp i64 *)
  659. rel := FetchQuad () ;
  660. SetIP (GetIP () + rel) ;
  661. | 0E1H : (* jpfalse i64 *)
  662. rel := FetchQuad () ;
  663. IF NOT PopBool () THEN
  664. SetIP (GetIP () + rel) ;
  665. END ;
  666. | 0E2H : (* jp_fwd i8 *)
  667. SetIP (GetIP () + VAL (LONGCARD, FetchSignedByte ())) ;
  668. | 0E3H : (* jpfalse_fwd i8 *)
  669. n := FetchSignedByte () ;
  670. IF NOT PopBool () THEN
  671. SetIP (GetIP () + VAL (LONGCARD, n)) ;
  672. END ;
  673. | 0E4H : (* jp_back u8 *)
  674. SetIP (GetIP () - VAL (LONGCARD, Fetch ())) ;
  675. | 0E5H : (* jpfalse_back u8 *)
  676. n := Fetch () ;
  677. IF NOT PopBool () THEN
  678. SetIP (GetIP () - VAL (LONGCARD, n)) ;
  679. END ;
  680. | 0E6H : (* bit_or *)
  681. b := Pop () ; a := Pop () ;
  682. Push (BitOp (a, b, 1)) ;
  683. | 0E7H : (* bit_in : stack [element, set] (set on top),
  684. per spec §11.8 and the original MCode
  685. "op := Pop(); Push(Pop() IN BITSET(op))" *)
  686. b := Pop () ; a := Pop () ;
  687. IF a < 64 THEN
  688. PushBool (BitOp (b, Shl64 (1, VAL (CARDINAL, a)), 0) # 0) ;
  689. ELSE
  690. Push (0) ;
  691. END ;
  692. | 0E8H : (* bit_and *)
  693. b := Pop () ; a := Pop () ;
  694. Push (BitOp (a, b, 0)) ;
  695. | 0E9H : (* bit_xor (OR minus AND) *)
  696. b := Pop () ; a := Pop () ;
  697. Push (BitOp (a, b, 2)) ;
  698. | 0EAH : (* power2 *)
  699. v := Pop () ;
  700. Push (Shl64 (1, VAL (CARDINAL, v) MOD 64)) ;
  701. | 0EBH : (* extern_proc_call *)
  702. v := Pop () ;
  703. p := Pop () ;
  704. SetOFP (GetGP ()) ;
  705. SetGP (p) ;
  706. SetCurrentModule (FindModuleByBase (p)) ;
  707. Push (GetIP ()) ;
  708. SetIP (v) ;
  709. | 0ECH : (* nested_call u8 *)
  710. n := Fetch () ;
  711. SetOFP (GetFP ()) ;
  712. Push (GetIP ()) ;
  713. SetIP (ProcedureAddress (GetCurrentModule (), n)) ;
  714. | 0EDH : (* proc_call u8 *)
  715. n := Fetch () ;
  716. SetOFP (0) ;
  717. Push (GetIP ()) ;
  718. SetIP (ProcedureAddress (GetCurrentModule (), n)) ;
  719. | 0EEH : (* call_with_frame u8 *)
  720. p := Pop () ;
  721. n := Fetch () ;
  722. SetOFP (p) ;
  723. Push (GetIP ()) ;
  724. SetIP (ProcedureAddress (GetCurrentModule (), n)) ;
  725. | 0EFH : (* extern_call mod,proc *)
  726. m := Fetch () ;
  727. n := Fetch () ;
  728. SetOFP (GetGP ()) ;
  729. SetGP (GetModuleBase (m)) ;
  730. SetCurrentModule (m) ;
  731. Push (GetIP ()) ;
  732. SetIP (ProcedureAddress (m, n)) ;
  733. | 0F0H : (* extern_call_nib nibble *)
  734. nw := Fetch () ;
  735. m := nw DIV 16 ;
  736. n := nw MOD 16 ;
  737. SetOFP (GetGP ()) ;
  738. SetGP (GetModuleBase (m)) ;
  739. SetCurrentModule (m) ;
  740. Push (GetIP ()) ;
  741. SetIP (ProcedureAddress (m, n)) ;
  742. | 0F1H .. 0FFH : (* call 1..15 *)
  743. SetOFP (0) ;
  744. Push (GetIP ()) ;
  745. SetIP (ProcedureAddress (GetCurrentModule (), opc MOD 16)) ;
  746. ELSE
  747. Fatal ("internal: opcode not handled") ;
  748. END ; (* CASE *)
  749. END ; (* LOOP *)
  750. END Run ;
  751. END Interpreter.