| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769 |
- IMPLEMENTATION MODULE Interpreter ;
- FROM Local IMPORT GetIP, SetIP, GetSP, SetSP, GetFP, GetGP, GetOFP, SetOFP, SetGP ;
- FROM Memory IMPORT ReadByte, WriteByte, ReadSlot, WriteSlot,
- ReadWord, WriteWord, CopyBytes, FillBytes, ArenaBase, MaxMem ;
- FROM Stack IMPORT Push, Pop, PopBool, PopReal, PushReal, Reserve ;
- FROM Instruction IMPORT Fetch, FetchSignedByte, FetchQuad, LoadString,
- ProcedureAddress, Enter, Leave ;
- FROM Global IMPORT GetModuleBase, GetModuleProcs, GetCurrentModule,
- SetCurrentModule, FindModuleByBase ;
- FROM Console IMPORT Fatal, WriteChar ;
- FROM Extended IMPORT Execute ;
- FROM StdChans IMPORT StdInChan ;
- FROM IOChan IMPORT Look, Skip ;
- FROM IOConsts IMPORT ReadResults, endOfLine, endOfInput ;
- PROCEDURE PushBool (b: BOOLEAN) ;
- BEGIN
- IF b THEN Push (1) ELSE Push (0) END ;
- END PushBool ;
- PROCEDURE Shl64 (u: LONGCARD; n: CARDINAL) : LONGCARD ;
- VAR i: CARDINAL ;
- BEGIN
- IF n >= 64 THEN
- RETURN 0 ;
- END ;
- FOR i := 1 TO n DO
- u := u * 2 ;
- END ;
- RETURN u ;
- END Shl64 ;
- PROCEDURE ShrLog (u: LONGCARD; n: CARDINAL) : LONGCARD ;
- VAR i: CARDINAL ;
- BEGIN
- IF n >= 64 THEN
- RETURN 0 ;
- END ;
- FOR i := 1 TO n DO
- u := u DIV 2 ;
- END ;
- RETURN u ;
- END ShrLog ;
- PROCEDURE Mul64 (a, b: LONGCARD) : LONGCARD ;
- VAR ah, al, bh, bl, lolo, mid: LONGCARD ;
- BEGIN
- ah := a DIV 4294967296 ;
- al := a MOD 4294967296 ;
- bh := b DIV 4294967296 ;
- bl := b MOD 4294967296 ;
- lolo := al * bl ;
- mid := VAL (LONGCARD, VAL (CARDINAL, ah * bl + al * bh)) ;
- RETURN lolo + mid * 4294967296 ;
- END Mul64 ;
- PROCEDURE Low32 (u: LONGCARD) : CARDINAL ;
- BEGIN
- RETURN VAL (CARDINAL, u) ;
- END Low32 ;
- PROCEDURE BitOp (a, b: LONGCARD; mode: CARDINAL) : LONGCARD ;
- VAR res, m: LONGCARD ; p: CARDINAL ; ba, bb: CARDINAL ;
- BEGIN
- res := 0 ;
- m := 1 ;
- FOR p := 0 TO 63 DO
- ba := VAL (CARDINAL, (a DIV m) MOD 2) ;
- bb := VAL (CARDINAL, (b DIV m) MOD 2) ;
- IF mode = 0 THEN (* AND *)
- IF (ba = 1) AND (bb = 1) THEN res := res + m END ;
- ELSIF mode = 1 THEN (* OR *)
- IF (ba = 1) OR (bb = 1) THEN res := res + m END ;
- ELSE (* XOR *)
- IF ba # bb THEN res := res + m END ;
- END ;
- m := m * 2 ;
- END ;
- RETURN res ;
- END BitOp ;
- PROCEDURE ReadLine (dst: LONGCARD) ;
- (* SYSTEM service 2 : read one line from the host standard input.
- Characters up to (but not including) the line mark, or end of input,
- are stored at dst; a NUL terminator is appended and the VM stack
- receives the number of bytes read (excluding the terminator).
- An empty line or immediate end of input yields 0. *)
- VAR p: LONGCARD ; ch: CHAR ; res: ReadResults ;
- done, over: BOOLEAN ;
- BEGIN
- p := dst ;
- done := FALSE ;
- over := FALSE ;
- WHILE NOT done DO
- Look (StdInChan (), ch, res) ;
- IF res = endOfInput THEN
- done := TRUE ;
- ELSIF res = endOfLine THEN
- Skip (StdInChan ()) ;
- done := TRUE ;
- ELSIF over THEN
- Skip (StdInChan ()) ;
- ELSIF p >= VAL (LONGCARD, MaxMem) THEN
- over := TRUE ;
- ELSE
- WriteByte (p, ORD (ch)) ;
- p := p + 1 ;
- Skip (StdInChan ()) ;
- END ;
- END ;
- IF p < VAL (LONGCARD, MaxMem) THEN
- WriteByte (p, 0) ;
- p := p + 1 ;
- END ;
- Push (p - dst - 1) ;
- END ReadLine ;
- PROCEDURE Service (id, param: LONGCARD) ;
- VAR c: CARDINAL ; p: LONGCARD ;
- BEGIN
- CASE id OF
- | 0 : (* EXIT *)
- RETURN ;
- | 1 : (* write NUL-terminated string at param *)
- p := param ;
- c := ReadByte (p) ;
- WHILE c # 0 DO
- WriteChar (CHR (c)) ;
- p := p + 1 ;
- c := ReadByte (p) ;
- END ;
- | 2 : (* read line into buffer at param *)
- ReadLine (param) ;
- ELSE
- Fatal ("system: unknown service") ;
- END ;
- END Service ;
- PROCEDURE Run ;
- VAR opc, n, m, tm, lo, hi, nw: CARDINAL ;
- v, w, a, b, p, q, sz, sz2, ssz, t, off, cell, loww, highw, last,
- st, dv, src, dst, first, eot, np, rel, md: LONGCARD ;
- sgn: LONGINT ;
- gl, bl: LONGINT ;
- r1, r2: REAL ;
- i64: LONGCARD ;
- i: LONGCARD ;
- done: BOOLEAN ;
- BEGIN
- done := FALSE ;
- LOOP
- opc := Fetch () ;
- CASE opc OF
- | 00H : (* reserved -> IllegalInstruction *)
- Fatal ("illegal instruction 00H") ;
- | 01H : (* RAISE : unimplemented *)
- Fatal ("RAISE unimplemented") ;
- | 02H : (* load_proc_addr u8 *)
- n := Fetch () ;
- Push (ProcedureAddress (GetCurrentModule (), n)) ;
- | 03H .. 07H : (* load_param n : push FP[op] for params 1..5 *)
- Push (ReadSlot (GetFP () + VAL (LONGCARD, opc) * 8)) ;
- | 08H : (* load_local_dw i8 *)
- Push (ReadSlot (GetFP () + VAL (LONGCARD, FetchSignedByte ()) * 8)) ;
- | 09H : (* load_global_dw u8 *)
- Push (ReadSlot (GetGP () + VAL (LONGCARD, Fetch ()) * 8)) ;
- | 0AH : (* load_stack_dw u8 *)
- p := Pop () ;
- Push (ReadSlot (p + VAL (LONGCARD, Fetch ()) * 8)) ;
- | 0BH : (* load_extern_dw mod,var *)
- m := Fetch () ;
- Push (ReadSlot (GetModuleBase (m) + VAL (LONGCARD, Fetch ()) * 8)) ;
- | 0CH : (* load_extern_w nibble *)
- nw := Fetch () ;
- Push (ReadSlot (GetModuleBase (nw DIV 16) + VAL (LONGCARD, nw MOD 16) * 8)) ;
- | 0DH : (* load_indexed_byte *)
- v := Pop () ; p := Pop () ;
- Push (VAL (LONGCARD, ReadByte (p + v))) ;
- | 0EH : (* load_indexed_w *)
- v := Pop () ; p := Pop () ;
- Push (ReadSlot (p + v * 8)) ;
- | 0FH : (* load_indexed_q *)
- v := Pop () ; p := Pop () ;
- Push (ReadSlot (p + v * 8 + 8)) ;
- Push (ReadSlot (p + v * 8)) ;
- | 10H : (* load_outer : push enclosing frame pointer *)
- Push (GetOFP ()) ;
- | 11H : (* load_outer_n u8 : walk the display *)
- np := Fetch () ;
- p := GetOFP () ;
- i := 0 ;
- WHILE i < VAL (LONGCARD, np) DO
- p := ReadSlot (p) ;
- i := i + 1 ;
- END ;
- Push (p) ;
- | 12H : (* LONGREAL/quad sub-opcode dispatch ... *)
- nw := Fetch () ;
- CASE nw OF
- | 0 : (* load_local_q i8 *)
- sgn := VAL (LONGINT, FetchSignedByte ()) ;
- Push (ReadSlot (GetFP () + (VAL (LONGCARD, sgn) + 1) * 8)) ;
- Push (ReadSlot (GetFP () + VAL (LONGCARD, sgn) * 8)) ;
- | 1 : (* load_global_q u8 *)
- n := Fetch () ;
- Push (ReadSlot (GetGP () + (VAL (LONGCARD, n) + 1) * 8)) ;
- Push (ReadSlot (GetGP () + VAL (LONGCARD, n) * 8)) ;
- | 2 : (* load_i_q u8 *)
- n := Fetch () ;
- p := Pop () ;
- Push (ReadSlot (p + (VAL (LONGCARD, n) + 1) * 8)) ;
- Push (ReadSlot (p + VAL (LONGCARD, n) * 8)) ;
- | 3 : (* load_extern_q mod,var *)
- m := Fetch () ;
- n := Fetch () ;
- Push (ReadSlot (GetModuleBase (m) + (VAL (LONGCARD, n) + 1) * 8)) ;
- Push (ReadSlot (GetModuleBase (m) + VAL (LONGCARD, n) * 8)) ;
- | 4 : (* store_local_q i8 *)
- sgn := VAL (LONGINT, FetchSignedByte ()) ;
- loww := Pop () ; a := Pop () ;
- WriteSlot (GetFP () + VAL (LONGCARD, sgn) * 8, loww) ;
- WriteSlot (GetFP () + (VAL (LONGCARD, sgn) + 1) * 8, a) ;
- | 5 : (* store_global_q u8 *)
- n := Fetch () ;
- q := Pop () ;
- WriteSlot (GetGP () + VAL (LONGCARD, n) * 8, q) ;
- q := Pop () ;
- WriteSlot (GetGP () + (VAL (LONGCARD, n) + 1) * 8, q) ;
- | 6 : (* store_i_q u8 *)
- n := Fetch () ;
- p := Pop () ;
- q := Pop () ;
- WriteSlot (p + VAL (LONGCARD, n) * 8, q) ;
- q := Pop () ;
- WriteSlot (p + (VAL (LONGCARD, n) + 1) * 8, q) ;
- | 7 : (* store_extern_q mod,var *)
- m := Fetch () ;
- n := Fetch () ;
- q := Pop () ;
- WriteSlot (GetModuleBase (m) + VAL (LONGCARD, n) * 8, q) ;
- q := Pop () ;
- WriteSlot (GetModuleBase (m) + (VAL (LONGCARD, n) + 1) * 8, q) ;
- | 8 : (* load_indexed_q *)
- v := Pop () ; p := Pop () ;
- Push (ReadSlot (p + v * 8 + 8)) ;
- Push (ReadSlot (p + v * 8)) ;
- | 9 : (* store_indexed_q *)
- loww := Pop () ; a := Pop () ; v := Pop () ; p := Pop () ;
- WriteSlot (p + v * 8, loww) ;
- WriteSlot (p + v * 8 + 8, a) ;
- | 0AH : (* quad_fct_leave u8 *)
- n := Fetch () ;
- q := Pop () ;
- Leave (n) ;
- Push (q) ;
- ELSE
- Fatal ("quad sub-opcode illegal") ;
- END ; (* inner CASE *)
- | 13H .. 17H : (* store_param n : FP[op] := value *)
- WriteSlot (GetFP () + VAL (LONGCARD, opc) * 8, Pop ()) ;
- | 18H : (* store_local_dw i8 *)
- WriteSlot (GetFP () + VAL (LONGCARD, FetchSignedByte ()) * 8, Pop ()) ;
- | 19H : (* store_global_dw u8 *)
- WriteSlot (GetGP () + VAL (LONGCARD, Fetch ()) * 8, Pop ()) ;
- | 1AH : (* store_stack_dw u8 *)
- p := Pop () ;
- WriteSlot (p + VAL (LONGCARD, Fetch ()) * 8, Pop ()) ;
- | 1BH : (* store_extern_dw mod,var *)
- m := Fetch () ;
- WriteSlot (GetModuleBase (m) + VAL (LONGCARD, Fetch ()) * 8, Pop ()) ;
- | 1CH : (* store_extern_w nibble *)
- nw := Fetch () ;
- WriteSlot (GetModuleBase (nw DIV 16) + VAL (LONGCARD, nw MOD 16) * 8, Pop ()) ;
- | 1DH : (* store_indexed_byte *)
- v := Pop () ; i64 := Pop () ; p := Pop () ;
- WriteByte (p + i64, Low32 (v)) ;
- | 1EH : (* store_indexed_w *)
- v := Pop () ; i64 := Pop () ; p := Pop () ;
- WriteSlot (p + i64 * 8, v) ;
- | 1FH : (* store_indexed_q *)
- loww := Pop () ; a := Pop () ; i64 := Pop () ; p := Pop () ;
- WriteSlot (p + i64 * 8, loww) ;
- WriteSlot (p + i64 * 8 + 8, a) ;
- | 20H : (* dup *)
- v := Pop () ;
- Push (v) ; Push (v) ;
- | 21H : (* swap *)
- a := Pop () ; b := Pop () ;
- Push (a) ; Push (b) ;
- | 22H .. 2BH : (* load_local_n *)
- Push (ReadSlot (GetFP () - VAL (LONGCARD, opc MOD 16) * 8)) ;
- | 2CH : (* load_local i8 *)
- Push (ReadSlot (GetFP () + VAL (LONGCARD, FetchSignedByte ()) * 8)) ;
- | 2DH : (* load_global u8 *)
- Push (ReadSlot (GetGP () + VAL (LONGCARD, Fetch ()) * 8)) ;
- | 2EH : (* load_stack u8 *)
- p := Pop () ;
- Push (ReadSlot (p + VAL (LONGCARD, Fetch ()) * 8)) ;
- | 2FH : (* load_extern mod,var *)
- m := Fetch () ;
- Push (ReadSlot (GetModuleBase (m) + VAL (LONGCARD, Fetch ()) * 8)) ;
- | 30H : (* copy_block *)
- sz := Pop () ; src := Pop () ; dst := Pop () ;
- CopyBytes (src, dst, sz) ;
- | 31H : (* copy_string *)
- ssz := Pop () ; sz := Pop () ; src := Pop () ; dst := Pop () ;
- n := 0 ;
- np := 0 ;
- WHILE np < sz DO
- IF ReadByte (src + np) = 0 THEN EXIT END ;
- IF np >= ssz THEN EXIT END ;
- WriteByte (dst + np, ReadByte (src + np)) ;
- np := np + 1 ;
- END ;
- | 32H .. 3BH : (* store_local_n *)
- WriteSlot (GetFP () - VAL (LONGCARD, opc MOD 16) * 8, Pop ()) ;
- | 3CH : (* store_local i8 *)
- WriteSlot (GetFP () + VAL (LONGCARD, FetchSignedByte ()) * 8, Pop ()) ;
- | 3DH : (* store_global u8 *)
- WriteSlot (GetGP () + VAL (LONGCARD, Fetch ()) * 8, Pop ()) ;
- | 3EH : (* store_stack u8 *)
- p := Pop () ;
- WriteSlot (p + VAL (LONGCARD, Fetch ()) * 8, Pop ()) ;
- | 3FH : (* store_extern mod,var *)
- m := Fetch () ;
- WriteSlot (GetModuleBase (m) + VAL (LONGCARD, Fetch ()) * 8, Pop ()) ;
- | 40H :
- Execute () ;
- | 41H : (* load_stack_d0 *)
- p := Pop () ;
- IF p = 0 THEN Fatal ("NIL dereference") END ;
- Push (ReadSlot (p)) ;
- | 42H .. 4FH : (* load_global_n *)
- Push (ReadSlot (GetGP () + VAL (LONGCARD, opc MOD 16) * 8)) ;
- | 50H : (* end_program *)
- RETURN ;
- | 51H : (* store_stack_d0 *)
- p := Pop () ;
- IF p = 0 THEN Fatal ("NIL dereference") END ;
- WriteSlot (p, Pop ()) ;
- | 52H .. 5FH : (* store_global_n *)
- WriteSlot (GetGP () + VAL (LONGCARD, opc MOD 16) * 8, Pop ()) ;
- | 60H .. 6FH : (* load_i_n *)
- p := Pop () ;
- IF p = 0 THEN Fatal ("NIL dereference") END ;
- Push (ReadSlot (p + VAL (LONGCARD, opc MOD 16) * 8)) ;
- | 70H .. 7FH : (* store_i_n *)
- v := Pop () ; p := Pop () ;
- IF p = 0 THEN Fatal ("NIL dereference") END ;
- WriteSlot (p + VAL (LONGCARD, opc MOD 16) * 8, v) ;
- | 80H : (* load_local_addr i8 *)
- Push (GetFP () + VAL (LONGCARD, FetchSignedByte ()) * 8) ;
- | 81H : (* load_global_addr u8 *)
- Push (GetGP () + VAL (LONGCARD, Fetch ()) * 8) ;
- | 82H : (* load_stack_addr u8 *)
- p := Pop () ;
- Push (p + VAL (LONGCARD, Fetch ()) * 8) ;
- | 83H : (* load_extern_addr mod,var *)
- m := Fetch () ;
- Push (GetModuleBase (m) + VAL (LONGCARD, Fetch ()) * 8) ;
- | 84H : (* proc_leave *)
- Leave (Fetch ()) ;
- | 85H : (* fct_leave *)
- v := Pop () ;
- Leave (Fetch ()) ;
- Push (v) ;
- | 86H : (* longfct_leave *)
- q := Pop () ;
- Leave (Fetch ()) ;
- Push (q) ;
- | 87H : (* asmcode *)
- Fatal ("asmcode unimplemented") ;
- | 88H .. 8BH : (* leave 0..3, outer return *)
- Leave (128 + (opc MOD 4)) ;
- | 8CH : (* call_rel u8 *)
- LoadString (Fetch ()) ;
- | 8DH : (* load_imm_byte *)
- Push (VAL (LONGCARD, Fetch ())) ;
- | 8EH : (* load_imm_word u64 *)
- Push (FetchQuad ()) ;
- | 8FH : (* load_imm_quad (16 bytes) : high word first, low on top *)
- a := FetchQuad () ;
- b := FetchQuad () ;
- Push (a) ; Push (b) ;
- | 90H .. 9FH : (* load_imm 0..15 *)
- Push (VAL (LONGCARD, opc MOD 16)) ;
- | 0A0H : (* equal *)
- b := Pop () ; a := Pop () ;
- PushBool (a = b) ;
- | 0A1H : (* not_equal *)
- b := Pop () ; a := Pop () ;
- PushBool (a # b) ;
- | 0A2H : (* uless *)
- b := Pop () ; a := Pop () ;
- PushBool (Low32 (a) < Low32 (b)) ;
- | 0A3H : (* ugreater *)
- b := Pop () ; a := Pop () ;
- PushBool (Low32 (a) > Low32 (b)) ;
- | 0A4H : (* uless_eq *)
- b := Pop () ; a := Pop () ;
- PushBool (Low32 (a) <= Low32 (b)) ;
- | 0A5H : (* ugreater_eq *)
- b := Pop () ; a := Pop () ;
- PushBool (Low32 (a) >= Low32 (b)) ;
- | 0A6H : (* add (CARDINAL mod 2^32) *)
- b := Pop () ; a := Pop () ;
- Push (VAL (LONGCARD, Low32 (a) + Low32 (b))) ;
- | 0A7H : (* sub *)
- b := Pop () ; a := Pop () ;
- Push (VAL (LONGCARD, Low32 (a) - Low32 (b))) ;
- | 0A8H : (* umul *)
- b := Pop () ; a := Pop () ;
- Push (VAL (LONGCARD, Low32 (a) * Low32 (b))) ;
- | 0A9H : (* udiv *)
- b := Pop () ; a := Pop () ;
- IF Low32 (b) = 0 THEN Fatal ("divide by zero") END ;
- Push (VAL (LONGCARD, Low32 (a) DIV Low32 (b))) ;
- | 0AAH : (* umod *)
- b := Pop () ; a := Pop () ;
- IF Low32 (b) = 0 THEN Fatal ("divide by zero") END ;
- Push (VAL (LONGCARD, Low32 (a) MOD Low32 (b))) ;
- | 0ABH : (* eq0 *)
- PushBool (Pop () = 0) ;
- | 0ACH : (* inc *)
- Push (VAL (LONGCARD, Low32 (Pop ()) + 1)) ;
- | 0ADH : (* dec *)
- Push (VAL (LONGCARD, Low32 (Pop ()) - 1)) ;
- | 0AEH : (* add_imm u8 *)
- Push (VAL (LONGCARD, Low32 (Pop ()) + Fetch ())) ;
- | 0AFH : (* sub_imm u8 *)
- Push (VAL (LONGCARD, Low32 (Pop ()) - Fetch ())) ;
- | 0B0H : (* shl_imm u8 *)
- n := Fetch () ;
- v := Pop () ;
- IF n >= 32 THEN
- Push (0) ;
- ELSE
- Push (VAL (LONGCARD, Low32 (v) * VAL (CARDINAL, Shl64 (1, n)))) ;
- END ;
- | 0B1H : (* shr_imm *)
- n := Fetch () ;
- v := Pop () ;
- IF n >= 32 THEN
- Push (0) ;
- ELSE
- Push (VAL (LONGCARD, Low32 (v) DIV VAL (CARDINAL, Shl64 (1, n)))) ;
- END ;
- | 0B2H : (* iless *)
- b := Pop () ; a := Pop () ;
- PushBool (VAL (INTEGER, Low32 (a)) < VAL (INTEGER, Low32 (b))) ;
- | 0B3H : (* igreater *)
- b := Pop () ; a := Pop () ;
- PushBool (VAL (INTEGER, Low32 (a)) > VAL (INTEGER, Low32 (b))) ;
- | 0B4H : (* iless_eq *)
- b := Pop () ; a := Pop () ;
- PushBool (VAL (INTEGER, Low32 (a)) <= VAL (INTEGER, Low32 (b))) ;
- | 0B5H : (* igreater_eq *)
- b := Pop () ; a := Pop () ;
- PushBool (VAL (INTEGER, Low32 (a)) >= VAL (INTEGER, Low32 (b))) ;
- | 0B6H : (* not *)
- PushBool (NOT PopBool ()) ;
- | 0B7H : (* complement (32-bit ~) *)
- Push (VAL (LONGCARD, 0FFFFFFFFH - Low32 (Pop ()))) ;
- | 0B8H : (* imul (INTEGER mod 2^32) *)
- b := Pop () ; a := Pop () ;
- Push (VAL (LONGCARD, Low32 (a) * Low32 (b))) ;
- | 0B9H : (* idiv *)
- b := Pop () ; a := Pop () ;
- IF Low32 (b) = 0 THEN Fatal ("divide by zero") END ;
- Push (VAL (LONGCARD, VAL (INTEGER, Low32 (a)) DIV VAL (INTEGER, Low32 (b)))) ;
- | 0BAH : (* long_to_card *)
- Push (VAL (LONGCARD, Low32 (Pop ()))) ;
- | 0BBH : (* long_to_int *)
- v := Pop () ;
- Push (VAL (LONGCARD, VAL (INTEGER, Low32 (v)))) ;
- | 0BCH : (* abs *)
- v := Pop () ;
- IF VAL (INTEGER, Low32 (v)) < 0 THEN
- Push (VAL (LONGCARD, 0 - VAL (INTEGER, Low32 (v)))) ;
- ELSE
- Push (v) ;
- END ;
- | 0BDH : (* int_to_long *)
- Push (VAL (LONGCARD, VAL (INTEGER, Low32 (Pop ())))) ;
- | 0BEH : (* long_to_real *)
- PushReal (FLOAT (VAL (LONGINT, Pop ()))) ;
- | 0BFH : (* real_to_long *)
- Push (VAL (LONGCARD, VAL (INTEGER, TRUNC (PopReal ())))) ;
- | 0C0H : (* uadd_checked *)
- b := Pop () ; a := Pop () ;
- IF Low32 (a) + Low32 (b) < Low32 (a) THEN Fatal ("overflow") END ;
- Push (VAL (LONGCARD, Low32 (a) + Low32 (b))) ;
- | 0C1H : (* usub_checked *)
- b := Pop () ; a := Pop () ;
- IF Low32 (a) < Low32 (b) THEN Fatal ("overflow") END ;
- Push (VAL (LONGCARD, Low32 (a) - Low32 (b))) ;
- | 0C2H : (* umul_checked *)
- b := Pop () ; a := Pop () ;
- w := VAL (LONGCARD, Low32 (a)) * VAL (LONGCARD, Low32 (b)) ;
- IF w > 0FFFFFFFFH THEN Fatal ("overflow") END ;
- Push (VAL (LONGCARD, Low32 (a) * Low32 (b))) ;
- | 0C3H : (* system host call *)
- v := Pop () ;
- Service (v, Pop ()) ;
- | 0C4H : (* string_comp *)
- ssz := Pop () ; sz := Pop () ; src := Pop () ; dst := Pop () ;
- np := 0 ;
- last := 0 ;
- done := FALSE ;
- WHILE NOT done DO
- IF (np >= sz) OR (np >= ssz) THEN done := TRUE
- ELSIF ReadByte (src + np) = 0 THEN
- IF ReadByte (dst + np) # 0 THEN last := 1 END ;
- done := TRUE
- ELSIF ReadByte (src + np) > ReadByte (dst + np) THEN
- last := 2 ; done := TRUE
- ELSIF ReadByte (src + np) < ReadByte (dst + np) THEN
- last := 1 ; done := TRUE
- ELSE
- np := np + 1 ;
- END ;
- END ;
- IF last = 1 THEN
- Push (1) ; Push (0) ;
- ELSIF last = 2 THEN
- Push (0) ; Push (1) ;
- ELSE
- Push (0) ; Push (0) ;
- END ;
- | 0C5H : (* long_compare : push (a>b) then (a<b) *)
- b := Pop () ; a := Pop () ;
- gl := VAL (LONGINT, a) ; bl := VAL (LONGINT, b) ;
- IF gl > bl THEN Push (1) ELSE Push (0) END ;
- IF gl < bl THEN Push (1) ELSE Push (0) END ;
- | 0C6H : (* long_add *)
- b := Pop () ; a := Pop () ;
- Push (a + b) ;
- | 0C7H : (* long_sub *)
- b := Pop () ; a := Pop () ;
- Push (a - b) ;
- | 0C8H : (* long_mul *)
- b := Pop () ; a := Pop () ;
- Push (Mul64 (a, b)) ;
- | 0C9H : (* long_div *)
- b := Pop () ; a := Pop () ;
- IF b = 0 THEN Fatal ("divide by zero") END ;
- Push (VAL (LONGCARD, VAL (LONGINT, a) DIV VAL (LONGINT, b))) ;
- | 0CAH : (* long_mod *)
- b := Pop () ; a := Pop () ;
- IF b = 0 THEN Fatal ("divide by zero") END ;
- Push (VAL (LONGCARD, VAL (LONGINT, a) MOD VAL (LONGINT, b))) ;
- | 0CBH : (* not_zero *)
- PushBool (Pop () # 0) ;
- | 0CCH : (* long_abs *)
- v := Pop () ;
- IF VAL (LONGINT, v) < 0 THEN
- Push (0 - v) ;
- ELSE
- Push (v) ;
- END ;
- | 0CDH : (* switch *)
- v := Pop () ;
- loww := FetchQuad () ;
- highw := FetchQuad () ;
- t := FetchQuad () ; (* retOffset, must be 0 *)
- first := GetIP () ;
- eot := first + (highw - loww + 1) * 8 ;
- IF (v < loww) OR (v > highw) THEN
- SetIP (eot) ;
- ELSE
- cell := first + (v - loww) * 8 ;
- off := ReadSlot (cell) ;
- IF VAL (LONGINT, off) < 0 THEN
- Push (eot + t) ;
- END ;
- SetIP (cell + 8 + off) ;
- END ;
- | 0CEH : (* jump_stack : computed jump *)
- SetIP (Pop ()) ;
- | 0CFH : (* push_code_addr u64 *)
- off := FetchQuad () ;
- Push (GetIP () - 1 + off) ;
- | 0D0H : (* iadd_checked *)
- b := Pop () ; a := Pop () ;
- tm := VAL (INTEGER, Low32 (a)) + VAL (INTEGER, Low32 (b)) ;
- IF ((VAL (INTEGER, Low32 (a)) > 0) AND (VAL (INTEGER, Low32 (b)) > 0)
- AND (tm < 0)) OR
- ((VAL (INTEGER, Low32 (a)) < 0) AND (VAL (INTEGER, Low32 (b)) < 0)
- AND (tm >= 0)) THEN
- Fatal ("overflow") ;
- END ;
- Push (VAL (LONGCARD, tm)) ;
- | 0D1H : (* isub_checked *)
- b := Pop () ; a := Pop () ;
- tm := VAL (INTEGER, Low32 (a)) - VAL (INTEGER, Low32 (b)) ;
- IF ((VAL (INTEGER, Low32 (a)) > 0) AND (VAL (INTEGER, Low32 (b)) < 0)
- AND (tm < 0)) OR
- ((VAL (INTEGER, Low32 (a)) < 0) AND (VAL (INTEGER, Low32 (b)) > 0)
- AND (tm >= 0)) THEN
- Fatal ("overflow") ;
- END ;
- Push (VAL (LONGCARD, tm)) ;
- | 0D2H : (* reserve *)
- sz := Pop () ;
- IF GetSP () < sz THEN Fatal ("stack overflow") END ;
- SetSP (GetSP () - sz) ;
- Push (GetSP ()) ;
- | 0D3H : (* reserve_string *)
- st := Pop () ;
- sz := Pop () ;
- nw := VAL (CARDINAL, (sz + 7) DIV 8) ;
- dst := GetSP () - VAL (LONGCARD, nw) * 8 ;
- SetSP (dst) ;
- i := 0 ;
- WHILE i < VAL (LONGCARD, nw) DO
- WriteSlot (dst + i * 8, ReadSlot (st + i * 8)) ;
- i := i + 1 ;
- END ;
- Push (dst) ;
- | 0D4H : (* enter u8 *)
- Enter (Fetch ()) ;
- | 0D5H : (* real_compare *)
- r2 := PopReal () ; r1 := PopReal () ;
- IF r1 > r2 THEN Push (1) ELSE Push (0) END ;
- IF r1 < r2 THEN Push (1) ELSE Push (0) END ;
- | 0D6H : (* real_add *)
- r2 := PopReal () ; r1 := PopReal () ;
- PushReal (r1 + r2) ;
- | 0D7H : (* real_sub *)
- r2 := PopReal () ; r1 := PopReal () ;
- PushReal (r1 - r2) ;
- | 0D8H : (* real_mul *)
- r2 := PopReal () ; r1 := PopReal () ;
- PushReal (r1 * r2) ;
- | 0D9H : (* real_div *)
- r2 := PopReal () ; r1 := PopReal () ;
- PushReal (r1 / r2) ;
- | 0DAH : (* urange_check *)
- sz := Pop () ; loww := Pop () ; v := Pop () ;
- IF (v < loww) OR (v >= loww + sz) THEN Fatal ("range error") END ;
- | 0DBH : (* irange_check *)
- sz := Pop () ; loww := Pop () ; v := Pop () ;
- IF (VAL (INTEGER, Low32 (v)) < VAL (INTEGER, Low32 (loww))) OR
- (VAL (INTEGER, Low32 (v)) >=
- VAL (INTEGER, Low32 (loww)) + VAL (INTEGER, Low32 (sz))) THEN
- Fatal ("range error") ;
- END ;
- | 0DCH : (* limit_check u8 *)
- n := Fetch () ;
- v := Pop () ; Push (v) ;
- IF v > VAL (LONGCARD, n) THEN Fatal ("range error") END ;
- | 0DDH : (* check_positive *)
- v := Pop () ; Push (v) ;
- IF VAL (INTEGER, Low32 (v)) < 0 THEN Fatal ("range error") END ;
- | 0DEH : (* and_jp u8 *)
- n := Fetch () ;
- IF NOT PopBool () THEN
- Push (0) ;
- SetIP (GetIP () + VAL (LONGCARD, n)) ;
- END ;
- | 0DFH : (* or_jp u8 *)
- n := Fetch () ;
- IF PopBool () THEN
- Push (1) ;
- SetIP (GetIP () + VAL (LONGCARD, n)) ;
- END ;
- | 0E0H : (* jp i64 *)
- rel := FetchQuad () ;
- SetIP (GetIP () + rel) ;
- | 0E1H : (* jpfalse i64 *)
- rel := FetchQuad () ;
- IF NOT PopBool () THEN
- SetIP (GetIP () + rel) ;
- END ;
- | 0E2H : (* jp_fwd i8 *)
- SetIP (GetIP () + VAL (LONGCARD, FetchSignedByte ())) ;
- | 0E3H : (* jpfalse_fwd i8 *)
- n := FetchSignedByte () ;
- IF NOT PopBool () THEN
- SetIP (GetIP () + VAL (LONGCARD, n)) ;
- END ;
- | 0E4H : (* jp_back u8 *)
- SetIP (GetIP () - VAL (LONGCARD, Fetch ())) ;
- | 0E5H : (* jpfalse_back u8 *)
- n := Fetch () ;
- IF NOT PopBool () THEN
- SetIP (GetIP () - VAL (LONGCARD, n)) ;
- END ;
- | 0E6H : (* bit_or *)
- b := Pop () ; a := Pop () ;
- Push (BitOp (a, b, 1)) ;
- | 0E7H : (* bit_in : stack [element, set] (set on top),
- per spec §11.8 and the original MCode
- "op := Pop(); Push(Pop() IN BITSET(op))" *)
- b := Pop () ; a := Pop () ;
- IF a < 64 THEN
- PushBool (BitOp (b, Shl64 (1, VAL (CARDINAL, a)), 0) # 0) ;
- ELSE
- Push (0) ;
- END ;
- | 0E8H : (* bit_and *)
- b := Pop () ; a := Pop () ;
- Push (BitOp (a, b, 0)) ;
- | 0E9H : (* bit_xor (OR minus AND) *)
- b := Pop () ; a := Pop () ;
- Push (BitOp (a, b, 2)) ;
- | 0EAH : (* power2 *)
- v := Pop () ;
- Push (Shl64 (1, VAL (CARDINAL, v) MOD 64)) ;
- | 0EBH : (* extern_proc_call *)
- v := Pop () ;
- p := Pop () ;
- SetOFP (GetGP ()) ;
- SetGP (p) ;
- SetCurrentModule (FindModuleByBase (p)) ;
- Push (GetIP ()) ;
- SetIP (v) ;
- | 0ECH : (* nested_call u8 *)
- n := Fetch () ;
- SetOFP (GetFP ()) ;
- Push (GetIP ()) ;
- SetIP (ProcedureAddress (GetCurrentModule (), n)) ;
- | 0EDH : (* proc_call u8 *)
- n := Fetch () ;
- SetOFP (0) ;
- Push (GetIP ()) ;
- SetIP (ProcedureAddress (GetCurrentModule (), n)) ;
- | 0EEH : (* call_with_frame u8 *)
- p := Pop () ;
- n := Fetch () ;
- SetOFP (p) ;
- Push (GetIP ()) ;
- SetIP (ProcedureAddress (GetCurrentModule (), n)) ;
- | 0EFH : (* extern_call mod,proc *)
- m := Fetch () ;
- n := Fetch () ;
- SetOFP (GetGP ()) ;
- SetGP (GetModuleBase (m)) ;
- SetCurrentModule (m) ;
- Push (GetIP ()) ;
- SetIP (ProcedureAddress (m, n)) ;
- | 0F0H : (* extern_call_nib nibble *)
- nw := Fetch () ;
- m := nw DIV 16 ;
- n := nw MOD 16 ;
- SetOFP (GetGP ()) ;
- SetGP (GetModuleBase (m)) ;
- SetCurrentModule (m) ;
- Push (GetIP ()) ;
- SetIP (ProcedureAddress (m, n)) ;
- | 0F1H .. 0FFH : (* call 1..15 *)
- SetOFP (0) ;
- Push (GetIP ()) ;
- SetIP (ProcedureAddress (GetCurrentModule (), opc MOD 16)) ;
- ELSE
- Fatal ("internal: opcode not handled") ;
- END ; (* CASE *)
- END ; (* LOOP *)
- END Run ;
- END Interpreter.
|