Extended.mod 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. IMPLEMENTATION MODULE Extended ;
  2. FROM Instruction IMPORT Fetch ;
  3. FROM Stack IMPORT Pop, Push, PopReal, PushReal ;
  4. FROM Memory IMPORT CopyBytes, FillBytes, WriteSlot, ReadSlot ;
  5. FROM Local IMPORT GetSP, SetSP ;
  6. FROM Console IMPORT Fatal ;
  7. VAR
  8. hp : LONGCARD ;
  9. PROCEDURE SetHeapBase (b: LONGCARD) ;
  10. BEGIN
  11. hp := b ;
  12. END SetHeapBase ;
  13. PROCEDURE HeapPtr () : LONGCARD ;
  14. BEGIN
  15. RETURN hp ;
  16. END HeapPtr ;
  17. PROCEDURE Shl64 (u: LONGCARD; n: CARDINAL) : LONGCARD ;
  18. VAR i: CARDINAL ;
  19. BEGIN
  20. IF n >= 64 THEN
  21. RETURN 0 ;
  22. END ;
  23. FOR i := 1 TO n DO
  24. u := u * 2 ;
  25. END ;
  26. RETURN u ;
  27. END Shl64 ;
  28. PROCEDURE Mul64 (a, b: LONGCARD) : LONGCARD ;
  29. VAR ah, al, bh, bl, lolo, mid: LONGCARD ;
  30. BEGIN
  31. ah := a DIV 4294967296 ;
  32. al := a MOD 4294967296 ;
  33. bh := b DIV 4294967296 ;
  34. bl := b MOD 4294967296 ;
  35. lolo := al * bl ;
  36. mid := VAL (LONGCARD, VAL (CARDINAL, ah * bl + al * bh)) ;
  37. RETURN lolo + mid * 4294967296 ;
  38. END Mul64 ;
  39. PROCEDURE AllocateHeap (size: LONGCARD) : LONGCARD ;
  40. VAR sz, base: LONGCARD ;
  41. BEGIN
  42. sz := size ;
  43. IF (sz MOD 8) # 0 THEN
  44. sz := sz + 8 - (sz MOD 8) ;
  45. END ;
  46. base := hp ;
  47. IF base + sz >= GetSP () THEN
  48. Fatal ("extended: OutOfMemory (heap meets stack)") ;
  49. END ;
  50. hp := base + sz ;
  51. RETURN base ;
  52. END AllocateHeap ;
  53. PROCEDURE Execute ;
  54. VAR sfun, hbit, lbit: CARDINAL ;
  55. dst, src, size, a, b, v, mark: LONGCARD ;
  56. nw, i, sp: LONGCARD ;
  57. BEGIN
  58. sfun := Fetch () ;
  59. CASE sfun OF
  60. | 0 : (* drop *)
  61. v := Pop () ;
  62. | 1, 2 : (* enter/leave monitor : no-op *)
  63. | 3 : (* long_negate *)
  64. v := Pop () ;
  65. Push (0 - v) ;
  66. | 4 : (* build_field_mask : (1<<hi) - (1<<lo) *)
  67. hbit := VAL (CARDINAL, Pop ()) ;
  68. lbit := VAL (CARDINAL, Pop ()) ;
  69. Push (Shl64 (1, hbit MOD 64) - Shl64 (1, lbit MOD 64)) ;
  70. | 5 : (* ALLOCATE *)
  71. size := Pop () ;
  72. dst := Pop () ;
  73. WriteSlot (dst, AllocateHeap (size)) ;
  74. | 6 : (* DEALLOCATE (no-op free) *)
  75. size := Pop () ;
  76. dst := Pop () ;
  77. WriteSlot (dst, 0) ;
  78. | 7 : (* MARK *)
  79. dst := Pop () ;
  80. WriteSlot (dst, HeapPtr ()) ;
  81. | 8 : (* RELEASE *)
  82. dst := Pop () ;
  83. mark := ReadSlot (dst) ;
  84. hp := mark ;
  85. WriteSlot (dst, 0) ;
  86. | 9 : (* FREEMEM *)
  87. Push (GetSP () - HeapPtr ()) ;
  88. | 0AH, 0BH, 0CH : (* TRANSFER/IOTRANSFER/NEWPROCESS *)
  89. Fatal ("extended: processes unimplemented") ;
  90. | 0DH : (* BIOS (no-op) *)
  91. sfun := VAL (CARDINAL, Pop ()) ;
  92. v := Pop () ;
  93. | 0EH : (* MOVE *)
  94. size := Pop () ;
  95. dst := Pop () ;
  96. src := Pop () ;
  97. CopyBytes (src, dst, size) ;
  98. | 0FH : (* FILL *)
  99. v := Pop () ;
  100. size := Pop () ;
  101. src := Pop () ;
  102. FillBytes (src, size, VAL (CARDINAL, v)) ;
  103. | 10H : (* INP (no-op) *)
  104. Push (0) ;
  105. | 11H : (* OUT (no-op) *)
  106. sfun := VAL (CARDINAL, Pop ()) ;
  107. v := Pop () ;
  108. | 12H : (* reserve_string *)
  109. src := Pop () ;
  110. size := Pop () ;
  111. nw := (size + 7) DIV 8 ;
  112. dst := GetSP () - nw * 8 ;
  113. SetSP (dst) ;
  114. i := 0 ;
  115. WHILE i < nw DO
  116. WriteSlot (dst + i * 8, ReadSlot (src + i * 8)) ;
  117. i := i + 1 ;
  118. END ;
  119. Push (dst) ;
  120. | 13H : (* assert : pop 0 -> raise RangeError *)
  121. v := Pop () ;
  122. IF v = 0 THEN
  123. Fatal ("assertion failed") ;
  124. END ;
  125. | 14H : (* uc_less *)
  126. b := Pop () ; a := Pop () ;
  127. IF a < b THEN Push (1) ELSE Push (0) END ;
  128. | 15H : (* uc_less_eq *)
  129. b := Pop () ; a := Pop () ;
  130. IF a <= b THEN Push (1) ELSE Push (0) END ;
  131. | 16H : (* uc_greater *)
  132. b := Pop () ; a := Pop () ;
  133. IF a > b THEN Push (1) ELSE Push (0) END ;
  134. | 17H : (* uc_greater_eq *)
  135. b := Pop () ; a := Pop () ;
  136. IF a >= b THEN Push (1) ELSE Push (0) END ;
  137. | 18H : (* uc_add *)
  138. b := Pop () ; a := Pop () ;
  139. Push (a + b) ;
  140. | 19H : (* uc_sub *)
  141. b := Pop () ; a := Pop () ;
  142. Push (a - b) ;
  143. | 1AH : (* uc_mul *)
  144. b := Pop () ; a := Pop () ;
  145. Push (Mul64 (a, b)) ;
  146. | 1BH : (* uc_div *)
  147. b := Pop () ; a := Pop () ;
  148. IF b = 0 THEN Fatal ("divide by zero") END ;
  149. Push (a DIV b) ;
  150. | 1CH : (* uc_mod *)
  151. b := Pop () ; a := Pop () ;
  152. IF b = 0 THEN Fatal ("divide by zero") END ;
  153. Push (a MOD b) ;
  154. | 1DH : (* uc_to_real *)
  155. v := Pop () ;
  156. PushReal (FLOAT (VAL (LONGINT, v))) ;
  157. | 1EH : (* real_to_uc *)
  158. Push (VAL (LONGCARD, VAL (INTEGER, TRUNC (PopReal ())))) ;
  159. ELSE
  160. Fatal ("extended: illegal sub-opcode") ;
  161. END ; (* CASE *)
  162. END Execute ;
  163. END Extended.