Interpreter.mod 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  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. Push (ReadSlot (p)) ;
  323. | 42H .. 4FH : (* load_global_n *)
  324. Push (ReadSlot (GetGP () + VAL (LONGCARD, opc MOD 16) * 8)) ;
  325. | 50H : (* end_program *)
  326. RETURN ;
  327. | 51H : (* store_stack_d0 *)
  328. p := Pop () ;
  329. WriteSlot (p, Pop ()) ;
  330. | 52H .. 5FH : (* store_global_n *)
  331. WriteSlot (GetGP () + VAL (LONGCARD, opc MOD 16) * 8, Pop ()) ;
  332. | 60H .. 6FH : (* load_i_n *)
  333. p := Pop () ;
  334. Push (ReadSlot (p + VAL (LONGCARD, opc MOD 16) * 8)) ;
  335. | 70H .. 7FH : (* store_i_n *)
  336. v := Pop () ; p := Pop () ;
  337. WriteSlot (p + VAL (LONGCARD, opc MOD 16) * 8, v) ;
  338. | 80H : (* load_local_addr i8 *)
  339. Push (GetFP () + VAL (LONGCARD, FetchSignedByte ()) * 8) ;
  340. | 81H : (* load_global_addr u8 *)
  341. Push (GetGP () + VAL (LONGCARD, Fetch ()) * 8) ;
  342. | 82H : (* load_stack_addr u8 *)
  343. p := Pop () ;
  344. Push (p + VAL (LONGCARD, Fetch ()) * 8) ;
  345. | 83H : (* load_extern_addr mod,var *)
  346. m := Fetch () ;
  347. Push (GetModuleBase (m) + VAL (LONGCARD, Fetch ()) * 8) ;
  348. | 84H : (* proc_leave *)
  349. Leave (Fetch ()) ;
  350. | 85H : (* fct_leave *)
  351. v := Pop () ;
  352. Leave (Fetch ()) ;
  353. Push (v) ;
  354. | 86H : (* longfct_leave *)
  355. q := Pop () ;
  356. Leave (Fetch ()) ;
  357. Push (q) ;
  358. | 87H : (* asmcode *)
  359. Fatal ("asmcode unimplemented") ;
  360. | 88H .. 8BH : (* leave 0..3, outer return *)
  361. Leave (128 + (opc MOD 4)) ;
  362. | 8CH : (* call_rel u8 *)
  363. LoadString (Fetch ()) ;
  364. | 8DH : (* load_imm_byte *)
  365. Push (VAL (LONGCARD, Fetch ())) ;
  366. | 8EH : (* load_imm_word u64 *)
  367. Push (FetchQuad ()) ;
  368. | 8FH : (* load_imm_quad (16 bytes) : high word first, low on top *)
  369. a := FetchQuad () ;
  370. b := FetchQuad () ;
  371. Push (a) ; Push (b) ;
  372. | 90H .. 9FH : (* load_imm 0..15 *)
  373. Push (VAL (LONGCARD, opc MOD 16)) ;
  374. | 0A0H : (* equal *)
  375. b := Pop () ; a := Pop () ;
  376. PushBool (a = b) ;
  377. | 0A1H : (* not_equal *)
  378. b := Pop () ; a := Pop () ;
  379. PushBool (a # b) ;
  380. | 0A2H : (* uless *)
  381. b := Pop () ; a := Pop () ;
  382. PushBool (Low32 (a) < Low32 (b)) ;
  383. | 0A3H : (* ugreater *)
  384. b := Pop () ; a := Pop () ;
  385. PushBool (Low32 (a) > Low32 (b)) ;
  386. | 0A4H : (* uless_eq *)
  387. b := Pop () ; a := Pop () ;
  388. PushBool (Low32 (a) <= Low32 (b)) ;
  389. | 0A5H : (* ugreater_eq *)
  390. b := Pop () ; a := Pop () ;
  391. PushBool (Low32 (a) >= Low32 (b)) ;
  392. | 0A6H : (* add (CARDINAL mod 2^32) *)
  393. b := Pop () ; a := Pop () ;
  394. Push (VAL (LONGCARD, Low32 (a) + Low32 (b))) ;
  395. | 0A7H : (* sub *)
  396. b := Pop () ; a := Pop () ;
  397. Push (VAL (LONGCARD, Low32 (a) - Low32 (b))) ;
  398. | 0A8H : (* umul *)
  399. b := Pop () ; a := Pop () ;
  400. Push (VAL (LONGCARD, Low32 (a) * Low32 (b))) ;
  401. | 0A9H : (* udiv *)
  402. b := Pop () ; a := Pop () ;
  403. IF Low32 (b) = 0 THEN Fatal ("divide by zero") END ;
  404. Push (VAL (LONGCARD, Low32 (a) DIV Low32 (b))) ;
  405. | 0AAH : (* umod *)
  406. b := Pop () ; a := Pop () ;
  407. IF Low32 (b) = 0 THEN Fatal ("divide by zero") END ;
  408. Push (VAL (LONGCARD, Low32 (a) MOD Low32 (b))) ;
  409. | 0ABH : (* eq0 *)
  410. PushBool (Pop () = 0) ;
  411. | 0ACH : (* inc *)
  412. Push (VAL (LONGCARD, Low32 (Pop ()) + 1)) ;
  413. | 0ADH : (* dec *)
  414. Push (VAL (LONGCARD, Low32 (Pop ()) - 1)) ;
  415. | 0AEH : (* add_imm u8 *)
  416. Push (VAL (LONGCARD, Low32 (Pop ()) + Fetch ())) ;
  417. | 0AFH : (* sub_imm u8 *)
  418. Push (VAL (LONGCARD, Low32 (Pop ()) - Fetch ())) ;
  419. | 0B0H : (* shl_imm u8 *)
  420. n := Fetch () ;
  421. v := Pop () ;
  422. IF n >= 32 THEN
  423. Push (0) ;
  424. ELSE
  425. Push (VAL (LONGCARD, Low32 (v) * VAL (CARDINAL, Shl64 (1, n)))) ;
  426. END ;
  427. | 0B1H : (* shr_imm *)
  428. n := Fetch () ;
  429. v := Pop () ;
  430. IF n >= 32 THEN
  431. Push (0) ;
  432. ELSE
  433. Push (VAL (LONGCARD, Low32 (v) DIV VAL (CARDINAL, Shl64 (1, n)))) ;
  434. END ;
  435. | 0B2H : (* iless *)
  436. b := Pop () ; a := Pop () ;
  437. PushBool (VAL (INTEGER, Low32 (a)) < VAL (INTEGER, Low32 (b))) ;
  438. | 0B3H : (* igreater *)
  439. b := Pop () ; a := Pop () ;
  440. PushBool (VAL (INTEGER, Low32 (a)) > VAL (INTEGER, Low32 (b))) ;
  441. | 0B4H : (* iless_eq *)
  442. b := Pop () ; a := Pop () ;
  443. PushBool (VAL (INTEGER, Low32 (a)) <= VAL (INTEGER, Low32 (b))) ;
  444. | 0B5H : (* igreater_eq *)
  445. b := Pop () ; a := Pop () ;
  446. PushBool (VAL (INTEGER, Low32 (a)) >= VAL (INTEGER, Low32 (b))) ;
  447. | 0B6H : (* not *)
  448. PushBool (NOT PopBool ()) ;
  449. | 0B7H : (* complement (32-bit ~) *)
  450. Push (VAL (LONGCARD, 0FFFFFFFFH - Low32 (Pop ()))) ;
  451. | 0B8H : (* imul (INTEGER mod 2^32) *)
  452. b := Pop () ; a := Pop () ;
  453. Push (VAL (LONGCARD, Low32 (a) * Low32 (b))) ;
  454. | 0B9H : (* idiv *)
  455. b := Pop () ; a := Pop () ;
  456. IF Low32 (b) = 0 THEN Fatal ("divide by zero") END ;
  457. Push (VAL (LONGCARD, VAL (INTEGER, Low32 (a)) DIV VAL (INTEGER, Low32 (b)))) ;
  458. | 0BAH : (* long_to_card *)
  459. Push (VAL (LONGCARD, Low32 (Pop ()))) ;
  460. | 0BBH : (* long_to_int *)
  461. v := Pop () ;
  462. Push (VAL (LONGCARD, VAL (INTEGER, Low32 (v)))) ;
  463. | 0BCH : (* abs *)
  464. v := Pop () ;
  465. IF VAL (INTEGER, Low32 (v)) < 0 THEN
  466. Push (VAL (LONGCARD, 0 - VAL (INTEGER, Low32 (v)))) ;
  467. ELSE
  468. Push (v) ;
  469. END ;
  470. | 0BDH : (* int_to_long *)
  471. Push (VAL (LONGCARD, VAL (INTEGER, Low32 (Pop ())))) ;
  472. | 0BEH : (* long_to_real *)
  473. PushReal (FLOAT (VAL (LONGINT, Pop ()))) ;
  474. | 0BFH : (* real_to_long *)
  475. Push (VAL (LONGCARD, VAL (INTEGER, TRUNC (PopReal ())))) ;
  476. | 0C0H : (* uadd_checked *)
  477. b := Pop () ; a := Pop () ;
  478. IF Low32 (a) + Low32 (b) < Low32 (a) THEN Fatal ("overflow") END ;
  479. Push (VAL (LONGCARD, Low32 (a) + Low32 (b))) ;
  480. | 0C1H : (* usub_checked *)
  481. b := Pop () ; a := Pop () ;
  482. IF Low32 (a) < Low32 (b) THEN Fatal ("overflow") END ;
  483. Push (VAL (LONGCARD, Low32 (a) - Low32 (b))) ;
  484. | 0C2H : (* umul_checked *)
  485. b := Pop () ; a := Pop () ;
  486. w := VAL (LONGCARD, Low32 (a)) * VAL (LONGCARD, Low32 (b)) ;
  487. IF w > 0FFFFFFFFH THEN Fatal ("overflow") END ;
  488. Push (VAL (LONGCARD, Low32 (a) * Low32 (b))) ;
  489. | 0C3H : (* system host call *)
  490. v := Pop () ;
  491. Service (v, Pop ()) ;
  492. | 0C4H : (* string_comp *)
  493. ssz := Pop () ; sz := Pop () ; src := Pop () ; dst := Pop () ;
  494. np := 0 ;
  495. last := 0 ;
  496. done := FALSE ;
  497. WHILE NOT done DO
  498. IF (np >= sz) OR (np >= ssz) THEN done := TRUE
  499. ELSIF ReadByte (src + np) = 0 THEN done := TRUE
  500. ELSIF ReadByte (src + np) > ReadByte (dst + np) THEN
  501. last := 1 ; done := TRUE
  502. ELSIF ReadByte (src + np) < ReadByte (dst + np) THEN
  503. last := 2 ; done := TRUE
  504. ELSE
  505. np := np + 1 ;
  506. END ;
  507. END ;
  508. IF last = 1 THEN
  509. Push (1) ; Push (0) ;
  510. ELSIF last = 2 THEN
  511. Push (0) ; Push (1) ;
  512. ELSE
  513. Push (0) ; Push (0) ;
  514. END ;
  515. | 0C5H : (* long_compare : push (a>b) then (a<b) *)
  516. b := Pop () ; a := Pop () ;
  517. gl := VAL (LONGINT, a) ; bl := VAL (LONGINT, b) ;
  518. IF gl > bl THEN Push (1) ELSE Push (0) END ;
  519. IF gl < bl THEN Push (1) ELSE Push (0) END ;
  520. | 0C6H : (* long_add *)
  521. b := Pop () ; a := Pop () ;
  522. Push (a + b) ;
  523. | 0C7H : (* long_sub *)
  524. b := Pop () ; a := Pop () ;
  525. Push (a - b) ;
  526. | 0C8H : (* long_mul *)
  527. b := Pop () ; a := Pop () ;
  528. Push (Mul64 (a, b)) ;
  529. | 0C9H : (* long_div *)
  530. b := Pop () ; a := Pop () ;
  531. IF b = 0 THEN Fatal ("divide by zero") END ;
  532. Push (VAL (LONGCARD, VAL (LONGINT, a) DIV VAL (LONGINT, b))) ;
  533. | 0CAH : (* long_mod *)
  534. b := Pop () ; a := Pop () ;
  535. IF b = 0 THEN Fatal ("divide by zero") END ;
  536. Push (VAL (LONGCARD, VAL (LONGINT, a) MOD VAL (LONGINT, b))) ;
  537. | 0CBH : (* not_zero *)
  538. PushBool (Pop () # 0) ;
  539. | 0CCH : (* long_abs *)
  540. v := Pop () ;
  541. IF VAL (LONGINT, v) < 0 THEN
  542. Push (0 - v) ;
  543. ELSE
  544. Push (v) ;
  545. END ;
  546. | 0CDH : (* switch *)
  547. v := Pop () ;
  548. loww := FetchQuad () ;
  549. highw := FetchQuad () ;
  550. t := FetchQuad () ; (* retOffset, must be 0 *)
  551. first := GetIP () ;
  552. eot := first + (highw - loww + 1) * 8 ;
  553. IF (v < loww) OR (v > highw) THEN
  554. SetIP (eot) ;
  555. ELSE
  556. cell := first + (v - loww) * 8 ;
  557. off := ReadSlot (cell) ;
  558. IF VAL (LONGINT, off) < 0 THEN
  559. Push (eot + t) ;
  560. END ;
  561. SetIP (cell + 8 + off) ;
  562. END ;
  563. | 0CEH : (* jump_stack : computed jump *)
  564. SetIP (Pop ()) ;
  565. | 0CFH : (* push_code_addr u64 *)
  566. off := FetchQuad () ;
  567. Push (GetIP () - 1 + off) ;
  568. | 0D0H : (* iadd_checked *)
  569. b := Pop () ; a := Pop () ;
  570. tm := VAL (INTEGER, Low32 (a)) + VAL (INTEGER, Low32 (b)) ;
  571. IF ((VAL (INTEGER, Low32 (a)) > 0) AND (VAL (INTEGER, Low32 (b)) > 0)
  572. AND (tm < 0)) OR
  573. ((VAL (INTEGER, Low32 (a)) < 0) AND (VAL (INTEGER, Low32 (b)) < 0)
  574. AND (tm >= 0)) THEN
  575. Fatal ("overflow") ;
  576. END ;
  577. Push (VAL (LONGCARD, tm)) ;
  578. | 0D1H : (* isub_checked *)
  579. b := Pop () ; a := Pop () ;
  580. tm := VAL (INTEGER, Low32 (a)) - VAL (INTEGER, Low32 (b)) ;
  581. IF ((VAL (INTEGER, Low32 (a)) > 0) AND (VAL (INTEGER, Low32 (b)) < 0)
  582. AND (tm < 0)) OR
  583. ((VAL (INTEGER, Low32 (a)) < 0) AND (VAL (INTEGER, Low32 (b)) > 0)
  584. AND (tm >= 0)) THEN
  585. Fatal ("overflow") ;
  586. END ;
  587. Push (VAL (LONGCARD, tm)) ;
  588. | 0D2H : (* reserve *)
  589. sz := Pop () ;
  590. IF GetSP () < sz THEN Fatal ("stack overflow") END ;
  591. SetSP (GetSP () - sz) ;
  592. Push (GetSP ()) ;
  593. | 0D3H : (* reserve_string *)
  594. st := Pop () ;
  595. sz := Pop () ;
  596. nw := VAL (CARDINAL, (sz + 7) DIV 8) ;
  597. dst := GetSP () - VAL (LONGCARD, nw) * 8 ;
  598. SetSP (dst) ;
  599. i := 0 ;
  600. WHILE i < VAL (LONGCARD, nw) DO
  601. WriteSlot (dst + i * 8, ReadSlot (st + i * 8)) ;
  602. i := i + 1 ;
  603. END ;
  604. Push (dst) ;
  605. | 0D4H : (* enter u8 *)
  606. Enter (Fetch ()) ;
  607. | 0D5H : (* real_compare *)
  608. r2 := PopReal () ; r1 := PopReal () ;
  609. IF r1 > r2 THEN Push (1) ELSE Push (0) END ;
  610. IF r1 < r2 THEN Push (1) ELSE Push (0) END ;
  611. | 0D6H : (* real_add *)
  612. r2 := PopReal () ; r1 := PopReal () ;
  613. PushReal (r1 + r2) ;
  614. | 0D7H : (* real_sub *)
  615. r2 := PopReal () ; r1 := PopReal () ;
  616. PushReal (r1 - r2) ;
  617. | 0D8H : (* real_mul *)
  618. r2 := PopReal () ; r1 := PopReal () ;
  619. PushReal (r1 * r2) ;
  620. | 0D9H : (* real_div *)
  621. r2 := PopReal () ; r1 := PopReal () ;
  622. PushReal (r1 / r2) ;
  623. | 0DAH : (* urange_check *)
  624. sz := Pop () ; loww := Pop () ; v := Pop () ;
  625. IF (v < loww) OR (v >= loww + sz) THEN Fatal ("range error") END ;
  626. | 0DBH : (* irange_check *)
  627. sz := Pop () ; loww := Pop () ; v := Pop () ;
  628. IF (VAL (INTEGER, Low32 (v)) < VAL (INTEGER, Low32 (loww))) OR
  629. (VAL (INTEGER, Low32 (v)) >=
  630. VAL (INTEGER, Low32 (loww)) + VAL (INTEGER, Low32 (sz))) THEN
  631. Fatal ("range error") ;
  632. END ;
  633. | 0DCH : (* limit_check u8 *)
  634. n := Fetch () ;
  635. v := Pop () ; Push (v) ;
  636. IF v > VAL (LONGCARD, n) THEN Fatal ("range error") END ;
  637. | 0DDH : (* check_positive *)
  638. v := Pop () ; Push (v) ;
  639. IF VAL (INTEGER, Low32 (v)) < 0 THEN Fatal ("range error") END ;
  640. | 0DEH : (* and_jp u8 *)
  641. n := Fetch () ;
  642. IF NOT PopBool () THEN
  643. Push (0) ;
  644. SetIP (GetIP () + VAL (LONGCARD, n)) ;
  645. END ;
  646. | 0DFH : (* or_jp u8 *)
  647. n := Fetch () ;
  648. IF PopBool () THEN
  649. Push (1) ;
  650. SetIP (GetIP () + VAL (LONGCARD, n)) ;
  651. END ;
  652. | 0E0H : (* jp i64 *)
  653. rel := FetchQuad () ;
  654. SetIP (GetIP () + rel) ;
  655. | 0E1H : (* jpfalse i64 *)
  656. rel := FetchQuad () ;
  657. IF NOT PopBool () THEN
  658. SetIP (GetIP () + rel) ;
  659. END ;
  660. | 0E2H : (* jp_fwd i8 *)
  661. SetIP (GetIP () + VAL (LONGCARD, FetchSignedByte ())) ;
  662. | 0E3H : (* jpfalse_fwd i8 *)
  663. n := FetchSignedByte () ;
  664. IF NOT PopBool () THEN
  665. SetIP (GetIP () + VAL (LONGCARD, n)) ;
  666. END ;
  667. | 0E4H : (* jp_back u8 *)
  668. SetIP (GetIP () - VAL (LONGCARD, Fetch ())) ;
  669. | 0E5H : (* jpfalse_back u8 *)
  670. n := Fetch () ;
  671. IF NOT PopBool () THEN
  672. SetIP (GetIP () - VAL (LONGCARD, n)) ;
  673. END ;
  674. | 0E6H : (* bit_or *)
  675. b := Pop () ; a := Pop () ;
  676. Push (BitOp (a, b, 1)) ;
  677. | 0E7H : (* bit_in *)
  678. b := Pop () ; a := Pop () ;
  679. IF b < 64 THEN
  680. PushBool (BitOp (a, Shl64 (1, VAL (CARDINAL, b)), 0) # 0) ;
  681. ELSE
  682. Push (0) ;
  683. END ;
  684. | 0E8H : (* bit_and *)
  685. b := Pop () ; a := Pop () ;
  686. Push (BitOp (a, b, 0)) ;
  687. | 0E9H : (* bit_xor (OR minus AND) *)
  688. b := Pop () ; a := Pop () ;
  689. Push (BitOp (a, b, 2)) ;
  690. | 0EAH : (* power2 *)
  691. v := Pop () ;
  692. Push (Shl64 (1, VAL (CARDINAL, v) MOD 64)) ;
  693. | 0EBH : (* extern_proc_call *)
  694. v := Pop () ;
  695. p := Pop () ;
  696. SetOFP (GetGP ()) ;
  697. SetGP (p) ;
  698. SetCurrentModule (FindModuleByBase (p)) ;
  699. Push (GetIP ()) ;
  700. SetIP (v) ;
  701. | 0ECH : (* nested_call u8 *)
  702. n := Fetch () ;
  703. SetOFP (GetFP ()) ;
  704. Push (GetIP ()) ;
  705. SetIP (ProcedureAddress (GetCurrentModule (), n)) ;
  706. | 0EDH : (* proc_call u8 *)
  707. n := Fetch () ;
  708. SetOFP (0) ;
  709. Push (GetIP ()) ;
  710. SetIP (ProcedureAddress (GetCurrentModule (), n)) ;
  711. | 0EEH : (* call_with_frame u8 *)
  712. p := Pop () ;
  713. n := Fetch () ;
  714. SetOFP (p) ;
  715. Push (GetIP ()) ;
  716. SetIP (ProcedureAddress (GetCurrentModule (), n)) ;
  717. | 0EFH : (* extern_call mod,proc *)
  718. m := Fetch () ;
  719. n := Fetch () ;
  720. SetOFP (GetGP ()) ;
  721. SetGP (GetModuleBase (m)) ;
  722. SetCurrentModule (m) ;
  723. Push (GetIP ()) ;
  724. SetIP (ProcedureAddress (m, n)) ;
  725. | 0F0H : (* extern_call_nib nibble *)
  726. nw := Fetch () ;
  727. m := nw DIV 16 ;
  728. n := nw MOD 16 ;
  729. SetOFP (GetGP ()) ;
  730. SetGP (GetModuleBase (m)) ;
  731. SetCurrentModule (m) ;
  732. Push (GetIP ()) ;
  733. SetIP (ProcedureAddress (m, n)) ;
  734. | 0F1H .. 0FFH : (* call 1..15 *)
  735. SetOFP (0) ;
  736. Push (GetIP ()) ;
  737. SetIP (ProcedureAddress (GetCurrentModule (), opc MOD 16)) ;
  738. ELSE
  739. Fatal ("internal: opcode not handled") ;
  740. END ; (* CASE *)
  741. END ; (* LOOP *)
  742. END Run ;
  743. END Interpreter.