prim.scm 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. ; -*- Mode: Scheme; Syntax: Scheme; Package: Scheme; -*-
  2. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  3. ; Scalar primitives
  4. (define-primitive eq? (any-> any->) vm-eq? return-boolean)
  5. (define-primitive char? (any->) vm-char? return-boolean)
  6. (define-primitive char=? (vm-char-> vm-char->) vm-char=? return-boolean)
  7. (define-primitive char<? (vm-char-> vm-char->) vm-char<? return-boolean)
  8. (define-primitive char->scalar-value (char-scalar-value->) (lambda (c) c) return-fixnum)
  9. ; Unicode surrogates are not scalar values
  10. (define (scalar-value? x)
  11. (and (>= x 0)
  12. (or (<= x #xd7ff)
  13. (and (>= x #xe000) (<= x #x10ffff)))))
  14. (define-primitive scalar-value->char
  15. (fixnum->)
  16. (lambda (x)
  17. (if (scalar-value? x)
  18. (goto return (scalar-value->char x))
  19. (raise-exception wrong-type-argument 0 (enter-fixnum x)))))
  20. (define-primitive scalar-value?
  21. (fixnum->)
  22. scalar-value?
  23. return-boolean)
  24. (define-syntax define-encode-char
  25. (syntax-rules ()
  26. ((define-encode-char ?name ?cont)
  27. (define-primitive ?name (fixnum-> char-scalar-value-> code-vector-> fixnum-> fixnum->)
  28. (lambda (encoding value buffer start count)
  29. (if (or (immutable? buffer)
  30. (> 0 start)
  31. (> 0 count)
  32. (> (+ start count) (code-vector-length buffer)))
  33. (raise-exception wrong-type-argument 0
  34. (enter-fixnum encoding)
  35. (scalar-value->char value)
  36. buffer (enter-fixnum start) (enter-fixnum count))
  37. (call-with-values
  38. (lambda ()
  39. (encode-scalar-value encoding value
  40. (address+ (address-after-header buffer) start)
  41. count))
  42. (lambda (encoding-ok? ok? out-of-space? count)
  43. (if encoding-ok?
  44. (call-with-values
  45. (lambda () (values ok? out-of-space? count))
  46. ?cont)
  47. (raise-exception bad-option 0
  48. (enter-fixnum encoding)))))))))))
  49. (define-encode-char encode-char
  50. (lambda (ok? out-of-space? count)
  51. (push (enter-boolean (and ok? (not out-of-space?))))
  52. (push (if ok? (enter-fixnum count) false))
  53. (goto return-values 2 null 0)))
  54. (define-encode-char encode-char!
  55. (lambda (ok? out-of-space? count)
  56. (goto return unspecific-value)))
  57. (define-syntax define-decode-char
  58. (syntax-rules ()
  59. ((define-decode-char ?name ?cont)
  60. (define-primitive ?name (fixnum-> code-vector-> fixnum-> fixnum->)
  61. (lambda (encoding buffer start count)
  62. (if (or (> 0 start)
  63. (> 0 count)
  64. (> (+ start count) (code-vector-length buffer)))
  65. (raise-exception wrong-type-argument 0
  66. (enter-fixnum encoding) buffer (enter-fixnum start) (enter-fixnum count))
  67. (call-with-values
  68. (lambda ()
  69. (decode-scalar-value encoding
  70. (address+ (address-after-header buffer) start)
  71. count))
  72. (lambda (encoding-ok? ok? incomplete? value count)
  73. (if (not encoding-ok?)
  74. (raise-exception bad-option 0
  75. (enter-fixnum encoding))
  76. (call-with-values
  77. (lambda () (values ok? incomplete? value count))
  78. ?cont))))))))))
  79. (define-decode-char decode-char
  80. (lambda (ok? incomplete? value count)
  81. (push (if (and ok? (not incomplete?))
  82. (scalar-value->char value)
  83. false))
  84. (push (if ok? (enter-fixnum count) false))
  85. (goto return-values 2 null 0)))
  86. ; this makes limited sense: we only get the exception side effect
  87. (define-decode-char decode-char!
  88. (lambda (ok? incomplete? value count)
  89. (goto return unspecific-value)))
  90. (define-primitive eof-object?
  91. (any->)
  92. (lambda (x) (vm-eq? x eof-object))
  93. return-boolean)
  94. ;----------------
  95. (define-primitive stored-object-has-type?
  96. (any->)
  97. (lambda (x)
  98. (goto continue-with-value
  99. (enter-boolean (stob-of-type? x (code-byte 0)))
  100. 1)))
  101. (define-primitive stored-object-length
  102. (any->)
  103. (lambda (stob)
  104. (let ((type (code-byte 0)))
  105. (if (stob-of-type? stob type)
  106. (goto continue-with-value
  107. (enter-fixnum (d-vector-length stob))
  108. 1)
  109. (raise-exception wrong-type-argument 1 stob (enter-fixnum type))))))
  110. ; for the benefit of the native-code compiler
  111. (define-primitive env-set!
  112. (any->)
  113. (lambda (value)
  114. (d-vector-set! (stack-ref (code-byte 0)) (code-byte 1) value)
  115. (goto continue-with-value unspecific-value 2)))
  116. (define-primitive big-env-set!
  117. (any->)
  118. (lambda (value)
  119. (d-vector-set! (stack-ref (code-offset 0)) (code-offset 1) value)
  120. (goto continue-with-value unspecific-value 4)))
  121. ; Closures
  122. ; This is only generated by the byte-code optimizer, and primarily for
  123. ; use in native code. There, we have flat closures which contain the
  124. ; free variables directly.
  125. ; Template is in *val*, free variables are on the stack
  126. (define-primitive make-flat-closure ()
  127. (lambda ()
  128. (let* ((free-count (code-offset 0))
  129. (size (+ free-count 1))
  130. (key (ensure-space (+ stob-overhead size)))
  131. (closure (make-d-vector (enum stob closure) size key)))
  132. (d-vector-init! closure 0 *val*)
  133. (do ((i free-count (- i 1)))
  134. ((= 0 i)
  135. (unspecific)) ; for the type checker
  136. (d-vector-init! closure i (pop)))
  137. (goto continue-with-value closure 2))))
  138. ; Constructors
  139. (define-primitive make-stored-object ()
  140. (lambda ()
  141. (let* ((len (code-byte 0))
  142. (key (ensure-space (+ stob-overhead len)))
  143. (new (make-d-vector (code-byte 1) len key)))
  144. (cond ((>= len 1)
  145. (d-vector-init! new (- len 1) *val*)
  146. (do ((i (- len 2) (- i 1)))
  147. ((> 0 i)
  148. (unspecific)) ; for the type checker!
  149. (d-vector-init! new i (pop)))))
  150. (goto continue-with-value new 2))))
  151. ; This is for the closed compiled versions of VECTOR and RECORD.
  152. ; *stack* = arg0 arg1 ... argN rest-list N+1 total-nargs
  153. (define-primitive closed-make-stored-object ()
  154. (lambda ()
  155. (let* ((len (extract-fixnum (pop)))
  156. (key (ensure-space (+ stob-overhead len)))
  157. (new (make-d-vector (code-byte 0) len key))
  158. (stack-nargs (extract-fixnum (pop)))
  159. (rest-list (pop)))
  160. (do ((i (- stack-nargs 1) (- i 1)))
  161. ((> 0 i)
  162. (unspecific)) ; for the type checker!
  163. (d-vector-init! new i (pop)))
  164. (do ((i stack-nargs (+ i 1))
  165. (rest-list rest-list (vm-cdr rest-list)))
  166. ((vm-eq? rest-list null)
  167. (unspecific)) ; for the type checker!
  168. (d-vector-init! new i (vm-car rest-list)))
  169. (goto continue-with-value new 1))))
  170. (define-primitive make-vector-object (any-> any->)
  171. (lambda (len init)
  172. (let ((type (code-byte 0)))
  173. (if (fixnum? len)
  174. (let* ((len (extract-fixnum len))
  175. (size (vm-vector-size len)))
  176. (if (or (< len 0)
  177. (> size max-stob-size-in-cells))
  178. (raise-exception wrong-type-argument 1
  179. (enter-fixnum type) (enter-fixnum len) init)
  180. (begin
  181. (save-temp0! init)
  182. (let* ((v (maybe-make-d-vector+gc type len))
  183. (init (recover-temp0!)))
  184. (if (false? v)
  185. (raise-exception heap-overflow 1
  186. (enter-fixnum type) (enter-fixnum len)
  187. init)
  188. (begin
  189. (do ((i (- len 1) (- i 1)))
  190. ((< i 0))
  191. (d-vector-set! v i init))
  192. (goto continue-with-value v 1)))))))
  193. (raise-exception wrong-type-argument 1
  194. (enter-fixnum type) len init)))))
  195. ; Doubles
  196. (define-primitive make-double ()
  197. (lambda ()
  198. (let* ((len 8) ; IEEE 754 double precision
  199. (new (maybe-make-b-vector+gc (enum stob double) len)))
  200. (if (false? new)
  201. (raise-exception heap-overflow 0
  202. (enter-fixnum (enum stob double)))
  203. (begin
  204. ; (do ((i (- len 1) (- i 1)))
  205. ; ((< i 0))
  206. ; (b-vector-set! new i 0))
  207. (goto return new))))))
  208. ; Strings and byte vectors
  209. (define-primitive string-length
  210. (string->)
  211. (lambda (string)
  212. (goto return-fixnum (vm-string-length string))))
  213. (define-primitive byte-vector-length
  214. (code-vector->)
  215. (lambda (byte-vector)
  216. (goto return-fixnum (code-vector-length byte-vector))))
  217. (define (make-byte-ref ref length returner)
  218. (lambda (vector index)
  219. (if (valid-index? index (length vector))
  220. (goto returner (ref vector index))
  221. (raise-exception index-out-of-range 0 vector (enter-fixnum index)))))
  222. (let ((proc (make-byte-ref vm-string-ref vm-string-length return-scalar-value-char)))
  223. (define-primitive string-ref (string-> fixnum->) proc))
  224. (let ((proc (make-byte-ref code-vector-ref code-vector-length return-fixnum)))
  225. (define-primitive byte-vector-ref (code-vector-> fixnum->) proc))
  226. (define (make-byte-setter setter length enter-elt)
  227. (lambda (vector index char)
  228. (cond ((immutable? vector)
  229. (raise-exception wrong-type-argument 0
  230. vector (enter-fixnum index) (enter-elt char)))
  231. ((valid-index? index (length vector))
  232. (setter vector index char)
  233. (goto no-result))
  234. (else
  235. (raise-exception index-out-of-range 0
  236. vector (enter-fixnum index) (enter-elt char))))))
  237. (let ((proc (make-byte-setter vm-string-set! vm-string-length scalar-value->char)))
  238. (define-primitive string-set! (string-> fixnum-> char-scalar-value->) proc))
  239. (let ((proc (make-byte-setter code-vector-set! code-vector-length enter-fixnum)))
  240. (define-primitive byte-vector-set! (code-vector-> fixnum-> fixnum->) proc))
  241. (define (byte-vector-maker size bytes type initialize setter enter-elt)
  242. (lambda (len init)
  243. (let ((size (size len)))
  244. (if (or (< len 0)
  245. (> size max-stob-size-in-cells))
  246. (raise-exception wrong-type-argument
  247. 0
  248. (enter-fixnum len)
  249. (enter-elt init))
  250. (let ((vector (maybe-make-b-vector+gc type (bytes len))))
  251. (if (false? vector)
  252. (raise-exception heap-overflow
  253. 0
  254. (enter-fixnum len)
  255. (enter-elt init))
  256. (begin
  257. (initialize vector len)
  258. (do ((i (- len 1) (- i 1)))
  259. ((< i 0))
  260. (setter vector i init))
  261. (goto return vector))))))))
  262. (let ((proc (byte-vector-maker vm-string-size
  263. scalar-value-units->bytes
  264. (enum stob string)
  265. (lambda (string length)
  266. 0)
  267. vm-string-set!
  268. scalar-value->char)))
  269. (define-primitive make-string (fixnum-> char-scalar-value->) proc))
  270. (let ((proc (byte-vector-maker code-vector-size
  271. (lambda (len) len)
  272. (enum stob byte-vector)
  273. (lambda (byte-vector length) 0)
  274. code-vector-set!
  275. enter-fixnum)))
  276. (define-primitive make-byte-vector (fixnum-> fixnum->) proc))
  277. (define-primitive copy-string-chars! (string-> fixnum-> string-> fixnum-> fixnum->)
  278. (lambda (from from-index to to-index count)
  279. (cond ((not (and (okay-copy-string? from from-index count)
  280. (okay-copy-string? to to-index count)
  281. (not (immutable? to))
  282. (<= 0 count)))
  283. (raise-exception wrong-type-argument 0
  284. from (enter-fixnum from-index)
  285. to (enter-fixnum to-index)
  286. (enter-fixnum count)))
  287. (else
  288. (copy-vm-string-chars! from from-index to to-index count)
  289. (goto continue-with-value unspecific-value 0)))))
  290. (define (okay-copy-string? s index count)
  291. (and (<= 0 index)
  292. (<= (+ index count)
  293. (vm-string-length s))))
  294. ; Locations & mutability
  295. (define-primitive location-defined? (location->)
  296. (lambda (loc)
  297. (return-boolean (or (not (undefined? (contents loc)))
  298. (= (contents loc) unassigned-marker)))))
  299. (define-primitive set-location-defined?! (location-> boolean->)
  300. (lambda (loc value)
  301. (cond ((not value)
  302. (set-contents! loc unbound-marker))
  303. ((undefined? (contents loc))
  304. (set-contents! loc unassigned-marker))))
  305. return-unspecific)
  306. (define-primitive immutable? (any->) immutable? return-boolean)
  307. (define-primitive make-immutable! (any->)
  308. (lambda (thing)
  309. (make-immutable! thing)
  310. (goto return thing)))
  311. (define-primitive make-weak-pointer (any->)
  312. (lambda (init)
  313. (let ((weak-pointer (make-weak-pointer init weak-pointer-size)))
  314. (goto continue-with-value
  315. weak-pointer
  316. 0))))
  317. ;----------------
  318. ; Misc
  319. (define-primitive false ()
  320. (lambda ()
  321. (goto return false)))
  322. (define-primitive eof-object ()
  323. (lambda ()
  324. (goto return eof-object)))
  325. (define-primitive trap (any->)
  326. (lambda (arg)
  327. (raise-exception trap 0 arg)))
  328. (define-primitive find-all (fixnum->)
  329. (lambda (type)
  330. (let loop ((first? #t))
  331. (let ((vector (s48-find-all type)))
  332. (cond ((not (false? vector))
  333. (goto return vector))
  334. (first?
  335. ;; if the result vector couldn't be created force a
  336. ;; major collection and try again once.
  337. (s48-collect #t)
  338. (loop #f))
  339. (else
  340. (raise-exception heap-overflow 0 (enter-fixnum type))))))))
  341. (define-primitive find-all-records (any->)
  342. (lambda (type)
  343. (let loop ((first? #t) (type type))
  344. (let ((vector (s48-find-all-records type)))
  345. (cond ((not (false? vector))
  346. (goto return vector))
  347. (first?
  348. (save-temp0! type)
  349. (s48-collect #t)
  350. (loop #f (recover-temp0!)))
  351. (else
  352. (raise-exception heap-overflow 0 type)))))))
  353. (define-primitive collect ()
  354. (lambda ()
  355. ;; does a major collection in any case
  356. (set! *val* unspecific-value)
  357. (s48-collect #t)
  358. (goto continue 0)))
  359. (define-consing-primitive add-finalizer! (any-> any->)
  360. (lambda (n) (* 2 vm-pair-size))
  361. (lambda (stob proc key)
  362. (cond ((not (and (stob? stob)
  363. (closure? proc)))
  364. (raise-exception wrong-type-argument 0 stob proc))
  365. ; This would be useful but could get quite expensive
  366. ; ((vm-assq stob *finalizer-alist*)
  367. ; (raise-exception has-finalizer 0 stob proc))
  368. (else
  369. (get-proposal-lock!)
  370. (shared-set! *finalizer-alist*
  371. (vm-cons (vm-cons stob proc key)
  372. (shared-ref *finalizer-alist*)
  373. key))
  374. (release-proposal-lock!)
  375. (goto no-result)))))
  376. (define-primitive memory-status (fixnum-> any->)
  377. (lambda (key other)
  378. (enum-case memory-status-option key
  379. ((pointer-hash)
  380. (goto return (descriptor->fixnum other)))
  381. ((available)
  382. (goto return-fixnum (s48-available)))
  383. ((heap-size)
  384. (goto return-fixnum (bytes->cells (s48-heap-size))))
  385. ((max-heap-size)
  386. (goto return-fixnum (s48-max-heap-size)))
  387. ((stack-size)
  388. (goto return-fixnum (stack-size)))
  389. ((gc-count)
  390. (goto return-fixnum (s48-gc-count)))
  391. ((expand-heap!)
  392. (raise-exception unimplemented-instruction 0 (enter-fixnum key) other))
  393. (else
  394. (raise-exception bad-option 0 (enter-fixnum key) other)))))
  395. (define-primitive time (fixnum-> any->)
  396. (lambda (option other)
  397. (enum-case time-option option
  398. ((cheap-time)
  399. (goto return-fixnum (cheap-time)))
  400. ((run-time)
  401. (receive (seconds mseconds)
  402. (run-time)
  403. (goto return-time-value option seconds mseconds)))
  404. ((real-time)
  405. (receive (seconds mseconds)
  406. (real-time)
  407. (goto return-time-value option seconds mseconds)))
  408. ((gc-run-time)
  409. (receive (seconds mseconds)
  410. (s48-gc-run-time)
  411. (goto return-time-value option seconds mseconds)))
  412. (else
  413. (raise-exception bad-option 0 (enter-fixnum option) other)))))
  414. ; The largest number of seconds that can be converted into a fixnum number
  415. ; of milliseconds.
  416. (define maximum-seconds (quotient (- greatest-fixnum-value 1000) 1000))
  417. (define (return-time-value option seconds mseconds)
  418. (if (> seconds maximum-seconds)
  419. (raise-exception arithmetic-overflow 0
  420. (enter-fixnum option)
  421. (enter-fixnum seconds)
  422. (enter-fixnum mseconds))
  423. (goto return-fixnum (+ (* seconds 1000) mseconds))))
  424. (define-primitive schedule-interrupt (fixnum->)
  425. (lambda (delta)
  426. (clear-interrupt! (enum interrupt alarm))
  427. (goto return-fixnum (schedule-interrupt delta))))
  428. ; Convert from the user's exponent to the system's.
  429. ;(define (adjust-time mantissa exponent)
  430. ; (let ((system (clock-exponent)))
  431. ; (cond ((= exponent system)
  432. ; mantissa)
  433. ; ((> system exponent)
  434. ; (quotient mantissa (expt 10 (- system exponent))))
  435. ; (else
  436. ; (* mantissa (expt 10 (- exponent system)))))))
  437. (define-primitive system-parameter (fixnum->)
  438. (lambda (key)
  439. (enum-case system-parameter-option key
  440. ((host-architecture)
  441. (goto return (enter-string+gc host-architecture)))
  442. ((os-string-encoding)
  443. (goto return (enter-string+gc (get-os-string-encoding))))
  444. (else
  445. (raise-exception bad-option 0 (enter-fixnum key))))))
  446. (define-enumeration vm-extension-status
  447. (okay
  448. exception
  449. ))
  450. (define s48-*extension-value*)
  451. (define-primitive vm-extension (fixnum-> any->)
  452. (lambda (key value)
  453. (let ((status (extended-vm key value)))
  454. (cond ((vm-eq? status (enum vm-extension-status okay))
  455. (goto return s48-*extension-value*))
  456. ((vm-eq? status (enum vm-extension-status exception))
  457. (raise-exception extension-exception 0 (enter-fixnum key) value))
  458. (else
  459. (raise-exception extension-return-error 0 (enter-fixnum key) value))))))
  460. ; This is exported to keep s48-*EXTENSION-VALUE* from being eliminated by the
  461. ; compiler.
  462. (define (s48-set-extension-value! value)
  463. (set! s48-*extension-value* value))
  464. ; Used to indicate which stack block we are returning to. Set to FALSE if we are
  465. ; returning from the VM as a whole.
  466. (define s48-*callback-return-stack-block* false)
  467. (define-primitive return-from-callback (any-> any->)
  468. (lambda (stack-block value)
  469. (enable-interrupts!) ; Disabled to ensure that we return to the right
  470. ; stack block.
  471. (set! s48-*callback-return-stack-block* stack-block)
  472. value)) ; the interpreter returns this value
  473. (define-primitive current-thread ()
  474. (lambda () *current-thread*)
  475. return-any)
  476. (define-primitive set-current-thread! (any->)
  477. (lambda (state)
  478. (set! *current-thread* state))
  479. return-unspecific)
  480. (define-primitive session-data ()
  481. (lambda () (shared-ref *session-data*))
  482. return-any)
  483. (define-primitive set-session-data! (any->)
  484. (lambda (state)
  485. (shared-set! *session-data* state))
  486. return-unspecific)
  487. ; Unnecessary primitives
  488. (define-primitive string=? (string-> string->) vm-string=? return-boolean)
  489. ; Special primitive called by the reader.
  490. ; Primitive for the sake of speed. Probably should be flushed.
  491. (define-consing-primitive reverse-list->string (any-> fixnum->)
  492. (lambda (n) (vm-string-size (extract-fixnum n)))
  493. (lambda (l n k)
  494. (if (not (or (vm-pair? l) (vm-eq? l null)))
  495. (raise-exception wrong-type-argument 0 l (enter-fixnum n))
  496. (let ((obj (vm-make-string n k)))
  497. (do ((l l (vm-cdr l))
  498. (i (- n 1) (- i 1)))
  499. ((< i 0)
  500. (goto return obj))
  501. (vm-string-set! obj i (char->scalar-value (vm-car l))))))))
  502. (define-primitive string-hash (string->) vm-string-hash return-fixnum)
  503. ; Messy because we have to detect circular lists (alternatively we
  504. ; could check for interrupts and then pclsr). ***
  505. (define-primitive assq (any-> any->)
  506. (lambda (thing list)
  507. (let ((lose (lambda ()
  508. (raise-exception wrong-type-argument 0 thing list))))
  509. (let loop ((list list) (slow list) (move-slow? #t))
  510. (cond ((vm-eq? list null)
  511. (goto return-boolean #f))
  512. ((not (vm-pair? list))
  513. (lose))
  514. (else
  515. (let ((head (vm-car list)))
  516. (cond ((not (vm-pair? head))
  517. (lose))
  518. ((vm-eq? (vm-car head) thing)
  519. (goto return head))
  520. (else
  521. (let ((list (vm-cdr list)))
  522. (cond ((eq? list slow)
  523. (lose))
  524. (move-slow?
  525. (loop list (vm-cdr slow) #f))
  526. (else
  527. (loop list slow #t)))))))))))))
  528. ; Eventually add make-table, table-ref, table-set! as primitives?
  529. ; No -- write a compiler instead.
  530. ; *** Our entry for the obscure comment of the year contest.
  531. ;
  532. ; Pclsring is the term in ITS for the mechanism that makes the operating system
  533. ; appear to be a virtual machine. The paradigm is that of the BLT instruction
  534. ; on the PDP-10: its arguments are in a set of registers, and if the instruction
  535. ; gets interrupted in the middle, the registers reflect the intermediate state;
  536. ; the PC is set to the BLT instruction itself, and the process can be resumed
  537. ; in the usual way.
  538. ; For more on pclsring see `Pclsring: Keeping Process State Modular' by Alan
  539. ; Bawden (ftp.ai.mit.edu:pub/alan/pclsr.memo).