4,887,235 273 274 (definst %p-dpb-immed (10-bit-immediate-operand needs-stack) (assign vma top-of-stack) (parallel (start-memory read write) (assign b-temp next-on-stack) (decrement-stack-pointer)) (for-effect (popval)) (parallel (assign memory-data (dpb b-temp macro macro memory-data)) (start-memory write) (next-instruction))) ;8 cycles. %p-store-cdr-code could be done in 4 cycles. Saves occodes... (definst %p-tag-dpb-immed (unsigned-immediate-operand needs-stack) (assign vma top-of-stack) (parallel (start-memory read write) (assign b-temp next-on-stack) (decrement-stack-pointer)) (for-effect (popval)) (assign a-temp-2 memory-data) ;for temporary memory control (assign b-temp-2 (high-tag-field a-temp-2 a-temp-2)) (assign a-temp (strange-ldb b-temp-2 8 34)) ; Rotate left 4 take low 8 bits ; Now we have the tag field right-justified, do the user's DPB (assign b-temp (dpb b-temp macro macro a-temp)) ; Re-assembie the memory word and store it back. Not easy ; because everyone in sight is trying to use U AMWA field. ; Have to do the low & high tag fields separately. (assign b-temp-2 (dpb b-temp 4 28. a-temp-2)) (assign a-temp b-temp-2) (parallel (assign memory-data (dpb-tag-field-high-only b-temp a-temp)) (start-memory write) (next-instruction))) ;Leaves TOS wrong (definst %p-store-contents (no-operand smashes-stack) (parallel (memread next-on-stack) ;--- request write access? (decrement-stack-pointer)) (assign a-temp (merge-cdr top-of-stack memory-data)) (parallel (store-contents a-temp) (decrement-stack-pointer) (next-instruction))) ;Leaves TOS wrong (definst %p-store-cdr-and-contents (no-operand smashes-stack) (parallel (assign vma (amem (stack-pointer -2))) ;Pointer (decrement-stack-pointer)) (parallel (assign b-temp (rotate (amem (stack-pointer 1)) 6)) ;Cdr (decrement-stack-pointer)) (assign a-temp (dpb-cdr-field (ldb b-temp 2 6) (amem (stack-pointer 1)))) ;merge Contents (parallel (store-contents a-temp) (decrement-stack-pointer) (next-instruction))) ;Leoves TOS wrong (definst %p-store-tag-and-pointer (no-operand needs-stack smashes-stack) ; a-temp gets pointer-field. b-temp gets tag-field (parallel (assign a-temp top-of-stack) (assign b-temp next-on-stack)) ; a-temp gets the word to be stored (parallel (assign a-temp (dpb-tag-field b-temp a-temp)) (decrement-stack-pointer)) ; vma gets address to store it into (parallel (assign vma next-on-stack) (decrement-stack-pointer)) ; store it (parallel (start-memory write) (assign memory-data a-temp) (decrement-stack-pointer) (next-instruction))) (definst %p-contents-as-locative (no-operand needs-stack) (memread top-of-stack) (parallel (newtop (set-type memory-data dtp-locative)) (next-instruction))) ;Args are pointer and offset. Follow any structure forwarding in the ;header pointed to by the pointer, then return the result plus the ;offset, as a locative. Offset isn’t type checked since not convenient. ;This used to do a data-type check, forcing the base word to really be a header. ;That turned out to be too inconvenient, and the A machine doesn’t do it, ;so I flushed it. (definst %p-structure-offset no-operand (parallel (memread next-on-stack) (assign b-vma next-on-stack)) (transport header-or-data) (parallel (pop2push (set-type (+ b-vma top-of-stack-a) dtp-locative)) (next-instruction))) 4,887,235 275 276 (definst follow-structure-forwarding no-operand (parallel (memread top-of-stack-a) (assign b-vma top-of-stack-a)) (transport header-or-data) (parallel (newtop (pointer-field b-vma top-of-stack-a)) (next-instruction))) (definst follow-cell-forwarding no-operand (parallel (check-arg-type 0 next-on-stack dtp-locative) (assign vma next-on-stack) (assign b-vma next-on-stack)) (start-memory read) (if (data-type? top-of-stack-a dtp-nil) (parallel (transport bind-write) (pop2push (set-type b-vma dtp-locative)) (next-instruction)) (parallel (transport write) (pop2push (set-type b-vma dtp-locative)) (next-instruction)))) ;Stop the machine. ;For macrocode breakpoint, this must halt before incrementing the PC. Hence ;SEQUENTIAL rather than PARALLEL. (definst %halt no-operand (sequential (halt %halt) (next-instruction))) ;Allow manual proceed ;Read the microsecond clock (definst %microsecond-clock no-operand (assign b-temp (set-type (read-lbus-dev 36 0) dtp-fix)) (parallel (pushval b-temp) (next-instruction))) ;;; Bulk memory initialization ;stack-offset -4 -3 -2 -1 0 ;(%block-store-cdr-and-contents address count cdr contents increment) ;(%block-store-tag-and-pointer address count tag pointer increment) ;a-temp holds word to be stored (definst %block-store-cdr-and-contents (no-operand needs-stack smashes-stack) (assign b-temp (dpb (amem (stack-pointer -2)) 2 6 0)) ;Align cdr code (parallel ;Store-data (assign a-temp (dpb-cdr-field (ldb b-temp 2 6) (amem (stack-pointer -1)))) (jump block-store-start))) (definst %block-store-tag-and-pointer (no-operand needs-stack smashes-stack) (assign b-temp (amem (stack-pointer -2))) ;Tag field (assign a-temp (amem (stack-pointer -1))) ;Pointer field (parallel ;Store-data (assign a-temp (dpb-tag-field b-temp a-temp)) (jump block-store-start))) (defucode block-store-start (assign a-temp (merge-high-tag (- a-temp top-of-stack) a-temp)) ;Pre-decrement store-data (parallel (assign vma (amem (stack-pointer -4))) ;First address in block (jump block-store-fast-loop))) ;Increment data, store result in memory and back in data. ;The increment must not cross a GC space boundary since the GC-map lookup ;is on the unincremented data. The address storing into must not be in Amem. (defmicro store-contents-with-increment (data increment &rest options) '(parallel (assign ,data (merge-high-tag (+ ,data ,increment) ,data)) (store-contents obus obus-as-good-as-abus no-amem . ,options))) (defucode block-store-slow-loop ;; Test count (if (minus-or-zero-fixnum (amem (stack-pointer -3))) (parallel (assign stack-pointer (- stack-pointer (b-constant 5))) (next-instruction)) (drop-through)) (store-contents-with-increment a-temp top-of-stack block) ;;Update arguments (assign (amem (stack-pointer -3)) (set-type (1- (amem (stack-pointer -3))) dtp-fix)) (assign (amem (stack-pointer -4)) (set-type (1+ (amem (stack-pointer -4))) dtp-locative)) (parallel (assign (amem (stack-pointer -1)) (merge-high-tag (+ (amem (stack-pointer -1)) top-of-stack) (amem (stack-pointer -1)))) (jump block-store-slow-loop))) (defucode block-store-fast-loop (if (lesser-fixnum (amem (stack-pointer -3)) (b-constant 8)) (goto block-store-slow-loop) ;Almost done, go slow (drop-through)) ;Block-writa eight words (store-contents-with-increment a-temp top-of-stack block) (store-contents-with-increment a-temp top-of-stack block) (store-contents-with-increment a-temp top-of-stack block) (store-contents-with-increment a-temp top-of-stack block) (store-contents-with-increment a-temp top-of-stack block) 4,887,235 277 278 (store-contents-with-increment a-temp top-of-stack block) (store-contents-with-increment a-temp top-of-stack block) (store-contents-with-increment a-temp top-of-stack block) (assign (amem (stack-pointer -3)) ;Now checkpoint into arguments (set-type (- (amem (stack-pointer -3)) (b-constant 8)) dtp-fix)) (assign (amem (stack-pointer -4)) (set-type (+ (amem (stack-pointer -4)) (b-constant 8)) dtp-locative)) (parallel (assign (amem (stack-pointer -1)) (merge-high-tag (+ (amem (stack-pointer -1)) (dpb top-of-stack 29. 3 0)) ;i.e. multiply by 8 (amem (stack-pointer -1)))) (jump block-store-fast-loop))) ;Read an unsynchronized device register. This relies on the fact that the ;emulator task has its own MD register(s), which can be used as a synchronizer. ;---Take out the forced dtp-fix when we get rid of the rev-1 I/O board, which ;---doesn’t always set the data type when reading registers. (definst %unsynchronized-device-read no-operand (memread top-of-stack-a) (nop) ;Delay 1 cycle before looking at register (parallel (declare-memory-timing data-cycle) ;Fake out error checking in microcode compiler (newtop (set-type memory-data dtp-fix)) (next-instruction))) ;This interlocks against tasks, but cannot interlock against the FEP ;Unlike the A-machine, pclsring enables interlocking to work even if the ;old value is transported. interlocking does not work in the presence ;of forwarding-pointers. however. (definst store-conditional (no-operand needs-stack) (parallel (check-arg-type 0 (amem (stack-pointer -2)) dtp-locative) (memread-write (amem (stack-pointer -2)))) ;First ensure write access (parallel ;Then read it again. interlocked (start-memory read) ;This won’t start if task switch impending (disable-tasking)) ;Prevent task switch before data cycle (parallel (assign b-temp next-on-stack) ;Desired old contents (assign a-temp top-of-stack) ;New contents (decrement-stack-pointer) (disable-tasking)) ;Prevent task switch before store started (parallel (transport) (assign b-temp memory-data) (if (equal-typed-pointer memory-data b-temp) (sequential ;Succecd (store-contents a-temp (cdr b-temp)) (parallel (pop2push quote-t) (next-instruction))) (parallel ;Fail (pop2push quote-nil) (next-instruction))))) F:>lmach>ucode>stack-buffer.lisp.67 ;;; -*- Mode:Lisp; Package:Micro; Base:8; Lowercase:yes -*- ;;; (c) Copyright 1982, Symbolics, Inc. ; Microcode for maintenance of the stack buffer #M (declare (cond ((not (status feature lmucode)) (load 'udcls)))) (declare (special *page-size*)) ;in SIM ;Dump a page out of the stack ;Checks for stack overflow. unmaps the page from the stack buffer, and pushes ;state into the stack, setting stack-load-started. ; first address to dump ; last address to dump +1 ;This stack state allows the instruction to be pclsred during the dumping process ;After the dumping is complete, the stack-buffer-underflow bits are reset to ;reflect the new bottom frame in the stack, the state is removed. stack-load-started ;is cleared, the new page is mapped into A-memory, and the stack-buffer address and ;limit are adjusted. ;flush not attempt to stack-group-switch while stack-load-started flag is set! (definst stack-dump no-operand (if (not (bit stack-load-started)) (sequential (error-if (greater-or-equal-pointer stack-limit %control-stack-limit) stack-overflow) (pushval (set-type %stack-buffer-low dtp-fix)) 4,887,235 279 280 ;;--- Temporary kludge necessary because stacks are arrays, which they ;;--- shouldn’t be, and hence are not page-aligned (if (lesser-pointer top-of-stack %control-stack-low) (newtop (set-type %control-stack-low dtp-fix)) (drop-through)) (pushval (set-type (+ %stack-buffer-low (b-constant *page-size*)) dtp-fix)) (parallel (assign b-temp %stack-buffer-low) ;Unmap old page (assign %stack-buffer-low top-of-stack) (call clear-b-temp-page-from-map-cache)) (parallel (assign stack-load-started (b-constant 1)) (clear-stack-adjustment))) ;Keep this stack state if pclsr (drop-through)) (parallel (assign xbas next-on-stack) (assign vma next-on-stack) (call stack-dump-loop)) (parallel (assign vma (+ %stack-buffer-low (b-constant (* 3 *page-size*)))) (call map-page-to-stack-buffer)) ;Map new fourth page (parallel (decrement-stack-pointer) (assign stack-load-started (b-constant 0))) (parallel (for-effect (popval)) (jump adjust-frame-buffer-underflow-bits))) (defucode stack-dump-loop (if (equal-pointer next-on-stack top-of-stack) (goto set-stack-buffer-limit) ;;Dump 1 word. For real memory control, can change this to do 8 words in a block ;;write. then advance xbas and next-on-stack by 8 instead of 1. Must be careful ;;:not to advance state until after guaranteed not to page-fault. (sequential (store-contents (amem (xbas 0))) (parallel (assign next-on-stack (1+ next-on-stack)) (assign xbas obus) (assign vma obus) (jump stack-dump-loop))))) (defucode set-stack-buffer-limit ;; Now decide how many pages of stack buffer to use. Normally 4, unless we are ;; close to the erd of the stack. ;; Maximum frame size is 400 here. Decrease this to 100 later when compiler detects ;; larce frames and generates explicit checking instructions (assign stack-limit (set-type (+ %stack-buffer-low (b-constant (- 2000 400 1))) dtp-fix)) (if (greater-pointer stack-limit %control-stack-limit) (assign stack-limit %control-stack-limit) (drop-through)) ;; Set %stack-buffer-limit to highest virtual address in stack buffer. ;; This 1+ is hecause the maximum frame size is 400. if it was smaller it could be deleted. (assign %stack-buffer-limit (1+ stack-limit)) (parallel (assign %stack-buffer-limit (set-type (logior %stack-buffer-limit (b-constant (1- *page-size*))) dtp-fix)) (return))) ;Stack-buffer loading. At this point the current frame is not even in ;the stack buffer. ;Find the previous frame and decide how many pages need to be loaded into the ;stack buffer. We need all of the current frame plus the part of its caller ;that contains our arguments. Unmap that many pages from the high end, copy ;the pages from main memory into the stack buffer, then map those addresses ;into A-memory. Adjust the frame-buffer-under-flow bits in the newly-loaded ;frames. ;The following state is kept in the stack across pclsrings, protected by stack-load-started. ; First address to be loaded ; Next address to be loaded ; Last address to be loaded+1 (definst stack-load no-operand (if (not (bit stack-load-started)) (sequential ;; Read frame-previous-top from memory (memread (- frame-pointer (b-constant 4))) (assign a-temp (1+ memory-data)) ;Lowest address in frame ;; Push state (new %stack-buffer-low, range of memory to be loaded) (pushval (set-type (logand a-temp (b-constant (- *page-size*))) dtp-fix)) (pushval top-of-stack) ;;--- Temporary kludge necessary because stacks are arrays, which they ;;--- shouldn’t be, and hence are not page-aligned (if (lesser-pointer top-of-stack %control-stack-low) (newtop (set-type %control-stack-low dtp-fix)) (drop-through)) (pushval (set-type %stack-buffer-low dtp-fix)) (parallel (assign stack-lead-started (b-constant 1)) (clear-stack-adjustment))) ;Keep this stack state if pclsr (drop-through)) (parallel (assign xbas next-on-stack) (call stack-load-loop)) (parallel (assign stack-load-started (b-constant 0)) (call stack-load-setup-map)) (parallel (for-effect (popval)) (jump adjust-frame-buffer-underflow-bits))) 4,887,235 281 282 ;--- Make a temporary debugging test before entering the real stack-load-loop ;--- The original reason for this has been found, but it probably doesn’t hurt ;--- to leave the test around for a while. If the frame-previous-top of a frame ;--- ever gets clobbered, this will causa the machine to halt before the stack ;--- buffer contents get totally trashed. (defucode stack-load-loop (assign b-temp (- top-of-stack next-on-stack)) (parallel (trap-if (greater-pointer b-temp (a-constant 1400)) (halt stack-buffer-fucked-up)) (jump stack-load-loop-1))) (defucode stack-load-loop-1 (if (equal-pointer next-on-stack top-of-stack) (parallel (assign stack-pointer (- stack-pointer (b-constant 2))) (jump fixup-tos)) ;;Load 1 word. For real memory control, can change this to do 8 words in a block ;;read, then advance xbas and next-on-stack by 8 instead of 1. Must be careful ;;not to advance state until after guaranteed not to page-fault. (sequential (assign vma next-on-stack) (start-memory read) (parallel (assign next-on-stack (1+ next-on-stack)) (assign xbas obus)) (parallel (transport) (assign (amem (xbas -1)) memory-data) (jump stack-load-loop-1))))) ;Loop moving %stack-buller-low down a page and mapping that page until all the pages ;that were loaded have been processed ;Also as we go, unmap the pages that used to map into the same Amem page (from the ;other end of the stack buffer) (defucode stack-load-setup-map (assign %stack-buffer-low (- %stack-buffer-low (b-constant *page-size*))) (parallel (assign vma (+ %stack-buffer-low (b-constant (* 4 *page-size*)))) (call clear-page-from-map-cache)) (if (equal-pointer %stack-buffer-low top-of-stack) (parallel (assign vma %stack-buffer-low) (call-and-return-to map-page-to-stack-buffer set-stack-buffer-limit)) (parallel (assign vma %stack-buffer-low) (call-and-return-to map-page-to-stack-buffer stack-load-setup-map)))) ;Adjust the frame-buffer-underflow-bits of all frames in the stack buffer ;so that the lowest completely-in frame has a 1 and the rest have a 0. ;--- Possibilities for bumming this to avoid having to set bits to ;--- zero (saves one cycle per frame). Remember the frame whose bit ;--- is set, and before dumping clear it. Thus when loading all the ;--- bits will be loaded as zero, and when dumping we need not clear ;--- any bits since they are already clear. ;Frame field accessors relative to xbas rather than fp (defatomicro xframe-misc-data (amem (xbas -2))) (defatomicro xframe-previous-top (amem (xbas -4))) (defatomicro xframe-previous-frame (amem (xbas -5))) (defatomic-byte-field xframe-buffer-underflow-bit frame-buffer-underflow-bit xframe-misc-data) (defatomic-byte-field xframe-bottom-bit frame-bottom-bit xframe-misc-data) ;The code (defucode adjust-frame-buffer-underflow-bits (assign b-temp (+ %stack-buffer-low (b-constant 5))) ;Frame underhang (parallel (assign xbas frame-pointer) (assign b-temp-3 obus) (jump adjust-frame-buffer-underflow-bits-1))) (defucode adjust-frame-buffer-underflow-bits-1 (if (lesser-pointer xframe-previous-frame b-temp) ;Prev frame not in (sequential (assign b-temp (1- %stack-buffer-low)) (if (lesser-pointer xframe-previous-top b-temp) ;This frame not all in (assign xbas b-temp-2) ;so back up one frame (drop-through)) (parallel (assign xframe-buffer-underflow-bit (b-constant 1)) (return))) (if (bit xframe-bottom-bit) (return) ;Bottom of stack, all frames in (sequential (assign xframe-buffer-underflow-bit (b-constant 0)) (assign b-temp-2 b-temp-3) (parallel (assign xbas xframe-previous-frame) (assign b-temp-3 obus) (jump adjust-frame-buffer-underflow-bits-1)))))) 4,887,235 283 284 F:>lmach>ucode>sg.lisp.41 ;;: -*- Mode:Lisp; Package:Micro; Base:8; Lowercase:yes -*- ;;; (c) Copyright 1982, Symbolics, Inc. ; Microcode for stack groups ;Get defmicro and all his hosts #M (declare (cond ((not (status feature lmucode)) (load 'udcls)))) (reserve-scratchpad-memory 2444 2450 337 340) (defareg a-stack-group-lock) ;NIL normally, else how far we have gotten ;in the process of switching (see the code) (dafareg a-stack-group-entering) ;stack-group in process of entering (defareg a-stack-group-leaving) ;tracks for debugging only (defareg a-stack-group-argument) ;Value being conveyed across SG switch (defbreg b-binding-boundary) ;Boundary betwesn swapped and unswapped binding stack (define-enumerated-value-constants *sg-arg-status-codes*) ;This instruction is called by the stack-group-switch primitives, as well as ;from an escape function used for sequence breaks and error traps. ;Takes three arguments on the stack: ; The value to be conveyed ; The stack group to switch to ; The new value for SG-STATUS-BITS of this stack group ;Normally the third argument is simply a new value for SG-ARG-STATUS, howevar ;if higher-order bits are on they get IORed in, allowed nonresumability bits to get set. ; ;Will return with a value on the stack unless the new SC-ARC-STATUS is %SC-ARG-N0NE. ;If the new SC-ARG-STATUS is %SC-ARG-BREAK. then the first argument is ths PC to ;be used when this SG is resumed, instead of the current PC, and no value is ;to me returned in the stack either. ; ;Also we have (associated with the stack group lock) an indication of how far ;we have progressed, so that this instruction can be pclsred. ;Proceed as follows: ; If the stack-group lock is already locked, re-enter at appropriate point ; Error if target stack group not resumable ; Shuffle the stack to reflect how us want it to be upon return ; This means leave a slot for the value if necessary, then push the PC ; Lock the stack-group lock ; Dump the entire stack buffer ; Swap the special-variable bindings ; Dump the stack group state (including FP. SP) into main memory ; Load the new stack group state from main memory into A-memory, FP, SP ; Load the stack buffer (for the current frame) ; Stash the argument in the stack if wanted ; Unswap the bindings ; Unlock the stack-group lock ; Popj (definst %stack-group-switch (no-operand needs-stack) ;; Check for retrying after pclsr (parallel (dispatch-after-next (ldb a-stack-group-lock 3 0) ((0) (goto continue-sg-stack-buffer-dump)) ((1) (goto continue-sg-swap-out-bindings)) ((2) (goto sg-dump-state)) ((3) (goto sg-load-state)) ((4) (goto continue-sg-stack-buffer-load)) ((5) (goto continue-sg-swap-in-bindings))) (if (not (data-type? a-stack-group-lock dtp-nil)) (take-dispatch) (assign a-stack-group-leaving %current-stack-group))) ;; Check resumability of new stack group (parallel (check-data-type next-on-stack dtp-array) (memread (+ next-on-stack (b-constant (field-word-offset 'sg-nonresumability))))) (parallel (transport data) (trap-if (not (zero-fixnum (sg-nonresumability memory-data))) (signal-error stack-group-not-resumable))) ;; Process arguments and shuffle the stack appropriately (assign (sg-arg-status %current-stack-group-status-bits) top-of-stack) (parallel (assign %current-stack-group-status-bits (set-type (logior %current-stack-group-status-bits top-of-stack) dtp-fix)) (decrement-stack-pointer)) (parallel (assign a-stack-group-entering top-of-stack-a) (decrement-stack-pointer)) (assign a-stack-group-argument top-of-stack-a) (if (lesser-or-equal-fixnum-unsigned (sg-arg-status %current-stack-group-status-bits) %sg-arg-break) (if (equal-fixnum (sg-arg-status %current-stack-group-status-bits) %sg-arg-break) ;; PC on stack, no value slot under it. pass self as argument 4,887,235 285 286 (assign a-stack-group-argument %current-stack-group) ;; Put PC on stack, no value slot under it (newtop pc)) ;; Normal case, put PC on stack with value slot under it (pushval pc)) ;; Prppare to dumo the stack buffer (pushval (set-type %stack-buffer-low dtp-fix)) ;First address to dump ;;--- Temporary kludge necessary because stacks are arrays, which they ;;--- shouldn’t be, and hence are not page-aligned (if (lesser-pointer top-of-stack %control-stack-low) (newtop (set-type %control-stack-low dtp-fix)) (drop-through)) (pushval (set-type stack-pointer dtp-fix)) ;Last address to dump+1 (parallel (assign a-stack-group-lock (set-type (a-constant 0) dtp-fix)) (clear-stack-adjustment) (jump sg-stack-buffer-dump))) (defucode sg-stack-buffer-dump ;; Unmap all of the stack buffer pages (assign b-temp %stack-buffer-low) (if (lesser-pointer b-temp %stack-buffer-limit) (parallel (assign %stack-buffer-low (+ %stack-buffer-low (b-constant *page-size*))) (call-and-return-to clear-b-temp-page-from-map-cache sg-stack-buffer-dump)) (goto continue-sg-stack-buffer-dump))) (defucode continue-sg-stack-buffer-dump (parallel (assign xbas next-on-stack) (assign vma next-on-stack) (call stack-dump-loop)) ;; Remove stack-dump-loop arguments from the stack (assign stack-pointer (- stack-pointer (b-constant 2))) ;; Trere is now nothing mapped into the stack buffer, set it to highest possible pointer (assign %stack-buffer-low (set-type (a-constant 1777777777) dtp-fix)) ;; Prepare to swap the special-variable bindings (assign b-binding-boundary (1+ %binding-stack-pointer)) (parallel (assign a-stack-group-lock (set-type (a-constant 1) dtp-fix)) (jump continue-sg-swap-out-bindings))) (defucode continue-sg-swap-out-bindings (if (equal-pointer b-binding-boundary %binding-stack-low) ;; Done whole binding stack (goto sg-dump-state) (drop-through)) ;; Read the pointer to the bound location (memread (1- b-binding-boundary)) (parallel (transport) (assign b-temp memory-data)) ;; Read the old contents cf the bound location, checking write access (memread-write (- b-binding-boundary (a-constant 2))) (parallel (transport bind) (assign a-temp-2 memory-data)) ;; Read the current contents of the bound location (memread b-temp) (parallel (transport bind) (assign a-temp memory-data) (assign b-temp memory-data)) ;; Write the old contents there (preserve cdr code) (store-contents a-temp-2 (cdr b-temp)) ;; Store current contents into binding stack (better not pclsr!) (parallel (assign vma (- b-binding-boundary (a-constant 2))) (assign b-binding-boundary (- b-binding-boundary (a-constant 2)))) (parallel (store-contents a-temp) (jump continue-sg-swap-out-bindings))) (defucode sg-dump-state ;; Dump FP, SP, and the A-mem copy of the stack group state into memory ;; If this pclsrs in the middle, it can just start over from the beginning (assign a-stack-group-lock (set-type (a-constant 2) dtp-fix)) ;; Write FP, SP in not-pointer mode to defeat the phantom stack gc that doesn’t exist yet (assign vma (+ %current-stack-group (b-constant (field-word-offset 'sg-frame-pointer)))) (store-contents (set-type frame-pointer dtp-locative) block not-pointer) (store-contents (set-type stack-pointer dtp-locative) block not-pointer) ;; Make sure "active" is cleared in the stored state (assign (sg-active-bit %current-stack-group-status-bits) (b-constant 0)) (assign vma (+ %current-stack-group (b-constant (field-word-offset 'sg-binding-stack-pointer)))) (store-contents %binding-stack-pointer block) (store-contents %catch-block-list block) (parallel (store-contents %current-stack-group-status-bits block) (jump sg-load-state))) ;Micro to simulate block reads. Also does transport. Get a word every 4 cycles. (defatomicro next-memory-data (parallel (declare-memory-timing data-cycle) ;Coder better get it right... (transport data) memory-data (call start-read-next))) 4,887,235 287 288 ;Subroutine for the above (defucode start-read-next (parallel (assign vma (1+ vma)) (jump memread))) (defucode sg-load-state ;; Load FP, SP, and the A-mem copy of the stack group state from memory ;; If this pclsrs in the middle, it can just start over from the beginning (parallel (assign a-stack-group-lock (set-type (a-constant 3) dtp-fix)) (call sg-load-state-internal)) ;; Set up to load the stack buffer. Load from the beginning of the page ;; that includes tne beginning of the current frame up to top of stack. ;; Read frame-previous-top from memory (assign vma (- frame-pointer (b-constant 4))) (start-memory read) (assign a-stack-group-lock (set-type (a-constant 4) dtp-fix)) (assign a-temp (set-type (1+ memory-data) 0)) ;Lowest address in frame (don’t transport’) (pushval (set-type (logand a-temp (b-constant (- *page-size*))) dtp-fix)) (pushval top-of-stack) ;;--- Temporary kludge necessary because stacks are arrays, which they ;;--- shouldn’t be. and hence are not page-aligned (if (lesser-pointer top-of-stack %control-stack-low) (newtop (set-type %control-stack-low dtp-fix)) (drop-through)) (parallel (pushval (set-type (1- stack-pointer) dtp-fix)) ;First addr not to load (clear-stack-adjustment) ;Leave in stack if pcler (jump continue-sg-stack-buffer-load))) (defucode sg-load-state-internal (memread (+ a-stack-group-entering (b-constant (field-word-offset 'sg-frame-pointer)))) (assign frame-pointer next-memory-data) (assign stack-pointer next-memory-data) (assign %control-stack-low next-memory-data) (assign %control-stack-limit next-memory-data) (assign %binding-stack-low next-memory-data) (assign %binding-stack-limit next-memory-data) (assign %binding-stack-pointer next-memory-data) (assign %catch-block-list next-memory-data) (parallel (declare-memory-timing data-cycle) (transport data) (assign %current-stack-group-status-bits memory-data)) (assign %current-stack-group a-stack-group-entering) ;; Set the active bit in this SG’s stored state, clear other nonresumability bits (memread (+ a-stack-group-entering (b-constant (field-word-offset 'sg-active-bit)))) (parallel (check-data-type memory-data dtp-fix) (assign a-temp (andc2 memory-data (b-constant (byte-mask sg-nonresumability))))) (parallel (store-contents (set-type (logior a-temp (b-constant (byte-mask sg-active-bit))) dtp-fix) not-pointer) (return))) (defucode continue-sg-stack-buffer-load ;; Load the current frame into the stack buffer, along with the rest of the page ;; containing the beginning of the current frame. (parallel (assign xbas next-on-stack) (call stack-load-loop)) ;; Decide how much stack buffer to use (parallel (assign %stack-buffer-low top-of-stack-a) (assign top-of-stack top-of-stack-a) (call-and-return-to set-stack-buffer-limit sg-stack-buffer-load-setup-map))) (defucode sg-stack-buffer-load-setup-map ;; Loop mapping all pages that are in the stack buffer ;; including those beyond the current end of the stack. ;; Contorted way of writing it is to avoid getting too many blocks in a row ;; I can’t see a reasonable way to share code with normal stack-buffer maintenance (newtop (+ top-of-stack-a (b-constant *page-size*))) (parallel (assign vma (- top-of-stack-a (b-constant *page-size*))) (call map-page-to-stack-buffer)) (if (lesser-pointer top-of-stack %stack-buffer-limit) (jump sg-stack-buffer-load-setup-map) ;should be goto, but,.. (drop-through)) ;; Finish loading up those frames, finish popping stack-load-loop’s state (parallel (for-effect (popval)) (clear-stack-adjustment) (call adjust-frame-buffer-underflow-bits)) ;; Now stash the argument in the stack, if wanted (if (greater-fixnum-unsigned (sg-arg-status %current-stack-group-status-bits) %sg-arg-break) (assign next-on-stack a-stack-group-argument) (drop-through)) ;; Set up to swap in the bindings (assign b-binding-boundary %binding-stack-low) (parallel (assign a-stack-group-lock (set-type (a-constant 5) dtp-fix)) (jump continue-sg-swap-in-bindings))) 4,887,235 289 290 (defucode continue-sg-swap-in-bindings (if (greater-pointer b-binding-boundary %binding-stack-pointer) ;; Done whole binding stack--we’re all done (parallel (assign a-stack-group-lock quote-nil) (jump popj)) (drop-through)) ;; Read the pointer to the bound location (memread (1+ b-binding-boundary)) (parallel (transport) (assign b-temp memory-data)) ;; Read the bound contents of the bound location, checking write access (memread-write b-binding-boundary) (parallel (transport bind) (assign a-temp-2 memory-data)) ;; Read the current contents of the bound location (memread b-temp) (parallel (transport bind) (assign a-temp memory-data) (assign b-temp memory-data)) ;; Write the bound contents there (preserve cdr code) (store-contents a-temp-2 (cdr b-temp)) ;; Store current contents into binding stack (better- not pclsr!) (assign vma b-binding-boundary) (store-contents a-temp) (parallel (assign b-binding-boundary (+ b-binding-boundary (a-constant 2))] (jump continue-sg-swap-in-bindings))) F:>lmach>ucode>proto-trap.lisp.1 ;;; -*- Mode:Lisp; Package:Micro; Base:8; Lowercase:yes -*- ;;; (c) Copyright 1982, Symbolics, Inc. ; Microcode for Trap Handling on "prototype" machine ;Get defmicro and all his hosts #M (declare (cond ((not (status feature lmucode)) (load 'udcls)))) ;Invisible-pointer traps ;If transporting was needed, it has hanpened already ;Time= 2 cycles trapping + 2 cycles here ;+ 3 more because of the temporary memory control (defucode-at-loc inviz-trap 10012 ;trap-2 handler (parallel (trap-save) (assign vma a-vma-copy) (assign b-vma a-vma-copy)) ;get the memory-data again (start-memory read) (nop) (parallel (assign vma memory-data) (if (data-type? memory-data dtp-body-forward) ;; Body forward points to header forward (sequential (start-memory read) (assign b-vma (- b-vma a-vma-copy)) ;Offset into structure (assign vma (+ memory-data b-vma))) ;Address word in target structure (drop-through))) (trap-restore (start-memory read) (assign b-vma a-vma-copy))) ;Halt here if we accidentally popj with 17 in the CSP (defucode-at-loc no-ifu-present 17774 (parallel (halt no-ifu-present) (jump no-ifu-present))) (defucode-at-loc error-trap 10010 ;trap-0 handler (parallel (trap-save) (lisp (enter-error-handler)) (if (not (zero-fixnum (sg-halt-on-error %current-stack-group-status-bits))) (parallel (halt error-in-error-handler) (jump error-trap)) ;; Fixup the stack first, since we need to push some stuff (call-and-return-to restore-stack-pointer error-trap-1)))) (defucode error-trap-no-restore-stack (parallel (trap-save) (lisp (enter-error-handler)) (if (not (zero-fixnum (sg-halt-on-error %current-stack-group-status-bits))) (parallel (halt error-in-error-handler) (jump error-trap)) ;; Fixup the stack first, since we need to push some stuff (goto error-trap-1)))) 4,887,235 291 292 (defucode error-trap-1 ;; If an error- occurs, halt (assign (sg-halt-on-error %current-stack-group-status-bits) (b-constant 1)) ;; Push the address of the microinstruction that signalled the error (assign b-temp (logand (pop-control-stack) (b-constant 37777))) (pushval (set-type b-temp dtp-fix)) (pushval (set-type a-vma-copy dtp-locative)) ;; Make the pc point such as to retry the failed instruction, The error handler is ;; likely as not going to mess with our state anyway. ; The stack was alr-eadu restored above. (take-pre-trap signal-error preserve-stack)) F:>lmach>ucode>PREDICATE.LISP.14 ;;; -*- Mode:Lisp; Package:Micro; Base:8; Lowercase:yes -*- ;;; (c) Copyright 1982, Symbolics, Inc. ; Microcode for primitive predicates ;Get defaicro and all his hosts #M (declare (cond ((not (status feature lmucode)) (load 'udcls)))) (defucode true1 (parallel (newtop quote-t) (next-instruction))) (defucode false1 (parallel (newtop quote-nil) (next-instruction))) (definst eq (no-operand needs-stack) (parallel (if (equal-typed-pointer top-of-stack next-on-stack) (goto true1) (goto false1)) (decrement-stack-pointer))) (definst eql (no-operand needs-stack) (parallel (if (equal-typed-pointer top-of-stack next-on-stack) (goto true1) (goto false1)) (decrement-stack-pointer) (check-data-type-and-dispatch (next-on-stack dtp-float dtp-extended-number) ;; If the types differ, simply return nil ;; This has the bug that flonum NAN's pass through. ((flonum-fixnum extnum-fixnum extnum-flonum flonum-extnum) (goto false1)) ;; if the types are the same, do appropriate comparison ;; Due to IEEE standard, non-eq flonums can be equal, :; plus and minus zero for example ((flonum-flonum) (goto fequal)) ((extnum-extnum) (jump extnum-equal))))) (definst not no-operand (if (data-type? top-of-stack-a dtp-nil) (goto true1) (goto false1))) (definst atom no-operand (if (data-type? top-of-stack-a dtp-list) (goto false1) (goto true1))) ;This is the Common Lisp version of LISTP, not the present one (comment (definst listp no-operand (if (data-type? top-of-stack-a dtp-list dtp-nil) (goto true1) (goto false1))) );end comment (definst floatp no-operand (if (data-type? top-of-stack-a dtp-float) (goto true1) (drop-through)) (if (not (data-type? top-of-stack-a dtp-extended-number)) (gate false1) (drop-through)) ;--- Here see if it’s an extended-precision float (jump false1))