4,887,235
	253	254
(defun address-add-macrocode ()
  (address-add (instruction-baseno) (instruction-offset) t))

(defun aref-amem (loc)
  (aref *a-memory* loc))

(defun aref-bmem (loc)
  (aref *b-memory* loc))

(defun aref-bmem-360 ()
  (aref *b-memory* 360))

(defun aset-amem (val loc)
  (aset val *a-memory* loc)
  nil)

(defun aset-bmem (val loc)
  (aset val *b-memory* loc)
  nil)

(defun aset-bmem-360 (val)
  (aset val *b-memory* 360)
  nil)

(defun setq-vma (obus)
  (setq *vma* (pointer-field obus))
  ;Mapping, which really happens in the next cycle
  ;Map miss trap is not simulated, happens when memory-data read or written
  (set-pma-from-vma))

(defun setq-sp (obus)
  (setq *stack-pointer* (pointer-field obus)))

(defun setq-fp (obus)
  (setq *frame-pointer* (pointer-field obus)))

(defun inc-sp ()
  (setq *stack-pointer* (1+ *stack-pointer*)))

(defun dec-sp ()
  (setq *stack-pointer* (1- *stack-pointer*)))

(defun inc-macro ()
  (setq *instruction* (1+ *instruction*)))

;Simulate ALU carry function
(defun carry28 (x y z)
  (bit-test 1_28. (+ (logand #.(1- 1_28.) x) (logand #.(1- 1_28.) y) z)))

(defun carry32 (x y z)
  (bit-test 1_32. (+ (logand #.(1- 1_32.) x) (logand #.(1- 1_32.) y) z)))

;One simulation routine to help with multiplier
(defun 16-bit-sign-extend (n)
  (if (bit-test 1_15. n) (+ 177777+16. n) n))

;Returns a (defun name () --translated-microcode--)
(defun microcode-to-lisp-function (name microcode #Q definition-name)
  (let ((*microlisp-function-name* name))
    '(defun ,name ()
       #Q (declare (sys:function-parent ,definition-name))
       (prog (abus bbus xbus ybus alub obus dispatch alu-output type-map)
	 #M (declare (fixnum abus bbus xbus ybus alub obus dispatch alu-output type-map))
;XXXbrad backquote?
	 (progn abus bbus xbus ybus alub obus dispatch alu-output type-map) ;inhibit warning
	 (setq type-map 0)	;Idiot compiler warning in Maclisp, code bug in Lisp Machine
	 . ,(microcode-to-lisp microcode)))))


(defun microcode-to-lisp (microcode)
  (cone ((eq (car microcode) 'microsequence)
	 (loop for x in (cdr microcode)
	       nconc (microcode-to-lisp x)))
	((eq (car microcode) 'microinstruction)
	 (let ((*microinstruction* microcode))
	   (microlisp-syntax-check microcode)
	   (nconc (microlisp-read-phase microcode)
		  (microlisp-data-path-phase microcode)
		  (microlisp-force-obus-phase microcode)
		  (microlisp-trap-phase microcode)
		  (microlisp-operate-phase microcode)
		  (microlisp-register-write-phase microcode)
		  (microlisp-jump-phase microcode))))
	(t (bletch "Unrecognizable microcode: ~S" microcode))))

(defun microlisp-syntax-check (code)
  (loop for (prop val) on (cdr code) by 'cddr
	unless (or (memq prop read-phase-fields)
		   (memq prop data-path-fields)
		   (memq prop force-obus-fields)
		   (memq prop trap-phase-fields)
		   (memp prop operate-phase-fields)
		   (memq prop register-write-fields)
4,887,235
	255	256
	           (memq prop jump-phase-fields)
		   (memq prop all-over-the-place-fields))
	do (bletch "Unrecognized microcode field: ~S" prop)))

;Generate setqs of the varianles abus, bbus, xbus, ybus

(defun microlisp-read-phase (code)
  (nconc
   (mksetq 'abus
	   (eselectq abus (get code 'abus)
	     (amem
	      (let ((addr (get code 'amem-read-addr)))
		(if (and (not (atom addr)) (eq (car addr) 'constant)) (cadr addr)
		  '(aref-amem ,(amemaddr addr)))))
	     (memory-data '(pma-mem-read))
	     (frame-pointer '*frame-pointer*)
	     (stack-pointer '*stack-pointer*)
	     (vma '*vma*)
	     (pc '*pc*)))
   (mksetq 'bbus
	   (eselectq bbus (get code 'bbus)
	     (bmem
	      (let ((addr (get code bmem-read-addr)))
		(cond ((and (not (atom addr)) (eq (car addr) 'constant))
		       (cadr addr))
		      ((= addr 360)
		       '(aref-bmem-360))
		      (t '(aref-bmem ,addr)))))
	     (macro-signed-immediate (instruction-signed-immediate))
	     (macro-unsigned-immediate '(instruction-unsigned-immediate))))
   (mksetq 'xbus
     (eselectq xbus (get code 'xbus)
       (abus 'abus)
       (bbus 'bbus)
       (product '(* *multiply-x* *multiply-y*))))
   (mksetq 'ybus
     (eselectq ybus (get code 'ybus)
       (abus 'abus)
       (bbus 'bbus)
       ;--- This is really not right, but will do for now I guess
       (ybus-crocks-1 '(ash32 abus -20.))))))

;Generate setqs of the variables alub, alu-outout, and obus

(defun microlisp-data-path-phase (code &aux tem)
  (nconc
   (if (setq tem (get code 'byte-func))		;Using the shifter
       (mksetq 'alub
	 (if (eq tem 'ybus) 'ybus
	   (make-alub-sign-hack
	    (make-merge
	     (make-rot 'ybus (fix-byte-r (second tem)))
	     (if (eq (first tem) 'dpb)		;rotate-mask
		 (make-rot (make-mask (fix-byte-s (third tem)))
			   (fix-byte-r (second tem)))
	       (make-mask (fix-byte-s (third tem))))
	     (if (eq (fourth tem) 'merge) 'xbus 0))
	    (fieldp code 'spec 'alub-sign-hack)))))
   (mksetq2 'obus 'alu-output
	    (eselectq alu (setq tem (get code 'alu))
	      (xbus 'xbus)
	      (alub 'alub)
	      ((X+1 X+1-overflow) '(1+ xbus))
	      ((X-1 X-1-overflow) '(1- xbus))
	      ((X+Y X+Y-overflow) '(+ xbus alub))
	      ((X-Y X-Y-overflow) '(- xbus alub))
	      (X+Y+1 '(+ xbus alub 1))
	      (X-Y-1 '(- xbus alub 1))
	      (X-Y-signed '(- (logxor xbus 1_31.) (logxor alub 1_31.)))
	      (X-Y-1-signed '(- (logxor xbus 1_31.) (logxor alub 1_31.) 1))
	      (and '(logand xbus alub))
	      (nand '(lognot (logand xbus alub)))
	      (ior '(logior xbus alub))
	      (xor '(logxor xbus alub))
	      (andcy '(logand xbus (lognot alub)))))))

;Generate calls to merge32, rot32, and mask32 but try to do them at
;compile time if possible
(defun make-mask (n-bits)
  (if (numberp n-bits) (mask32 n-bits) '(mask32 ,n-bits)))

(defun make-rot (value n-bits)
  (cond ((equal n-bits 0)
	 value)
	((and (numberp value) (numberp n-bits))
	 (rot32 value n-bits))
	(t '(rot32 ,value ,n-bits))))
4,887,235
	257	258
(defun make-merge (foreground mask background)
  (prog (tem)
    ;;Try to use lsh (ash) right instead of rot left, and open-code
    ;;when doing a simple byte extraction
    (and (numberp mask) (equal background 0)
	 (cond ((and (not (atom foreground)) (eq (car foreground) 'rot32))
		(and (numberp (setq tem (caddr foreground)))
		     (or (zerop tem) (<= (haulong mask) tem))
		     (return '(logand ,(if (zerop tem) (cadr foreground)
					 '(ash32 ,(cadr foreground)
						 ,(- tem 32.)))
				      ,mask))))
	       (t (return '(logand ,foreground ,mask)))))
    ;Unoptimizable
    (return '(merge32 ,foreground ,mask ,background))))

(defun make-alub-sign-hack (code hack)
  (if (not hack) code
    '(logxor 1 ,code)))

;Valid forms for addr are:
;	(frame-pointer fixnum)
;	(stack-pointer fixnum)
;	(xbas fixnum)
;	(macrocode)
;	fixnum			;between 0 and 7777 I guess
;	(constant value)
(defun amemaddr (addr)
  (cond ((numberp addr) addr)
	((atom addr) (bletch "Garbage amem address: ~S" addr))
	((eq (car addr) 'frame-pointer)
	 '(address-add-fp ,(cadr addr)))
	((eq (car addr) 'stack-pointer)
	 '(address-add-sp ,(cadr addr)))
	((eq (car addr) 'xbas)
	 '(address-add-xb . (cadr addr)))
	((eq (car addr) 'macrocode)
	 (if (cdr addr) (bletch "Obsolete amem address: ~S" addr))
	 '(address-add-macrocode))
	(t (bletch "Garbage amem address: ~S" addr))))

(defun fix-byte-r (r)
  (cond ((and (fixp r) (>= r 0) (<= r 37)) r)
	((eq r 'byte-r) '*byte-r*)
	((eq r 'macro) '(logand 37 (instruction-unsigned-immediate)))
	(t (bletch "Illegal byte rotation: !S" r))))

(defun fix-byte-s (s)
  (cond ((and (fixp s) (> s 0) (<= s 40)) s)
	((eq s 'byte-s) '(1+ *byte-s*))
	((eq s 'micro) '(+ (lsh (logand (instruction-opcode) 3) 3)
			   (logand 7 (lsh (instruction-unsigned-immediate)
					  -5))
			   1))
	(t (bletch "Illegal byte size: ~S" s))))
;XXXbrad - the following makes no sense - something is missing
  (let ((mask (dpb -1 field 0))
	(pos (lsh field -6))
	(size (logand field 77)))
    (cond ((numberb val)
	   (cond ((zerop val) '(logand ,(lognot mask) ,background))
		 ((= val (1- (ash 1 size))) '(logior ,mask ,background))
		 (t '(logior ,(ash32 val pos)
			     (logand ,(lognot mask) ,background)))))
	  ((memq val '(abus bbus))
	   '(logior (logand ,mask ,val) (logand ,(lognot mask) ,background)))
	  ((eq val 'memory-data)
	   '(logior (logand ,mask (pma-mem-read))
		    (logand ,(lognot mask) ,background)))
	  ((eq val (car hair))
	   '(logior (logand ,(lognot mask) mbackground)
		    (ash32 (logand ,(cadr hair) ,(caddr hair)) ,(cadddr hair))))
	  (t (bletch "~S illegal forcing value--gendpb" val)))))

(defun microlisp-force-obus-phase (code &aux tem)
  (nconc (and (setq tem (get code 'force-obus<31-28>))
	      (ncons '(setq obus ,(gendpb tem 3404 'obus nil))))
	 (and (setq tem (get code 'force-obus<33-32>))
	      (ncons '(setq obus ,(gendpb tem 4002 'obus
					  '(bbus<5-4> bbus 60 28.)))))
	 (and (setq tem (get code 'force-obus<35-34>))
	      (ncons '(setq obus ,(gendpb tem 4202 'obus
					  '(bbus<7-6> bbus 300 28.)))))))
4,887,235
	259	260
(defun microlisp-trap-phase (code &aux tem traps handler)
  (setq traps (get code 'trap-enables)
	handler (cond ((setq handler (get code trap-sequence))
		       (if (atom handler)
			   '(return (,(microcode-lisp-function-name
				       handler)))
			   `(progn . ,(microcode-to-lisp handler))))
		      ((setq handler (get code 'arith-trap-dispatch-table))
		       '(caseq-that-works (+ (logand (ash abus -30.) 14) ;ash considered
					     (logand (ash bbus -32.) 3)) ;harmful...
					  . ,(microlisp-dispatch-clauses handler)))))
  (nconc
   ;; Lower-level traps
   (and (setq tem (get code 'type-map))
	(ncons '(if (zerop (logand
			    (setq type-map
				  (arraycall fixnum *type-map*
					     (+ ,(eval-at-load-time
						  '(lsh (assign-type-map ',tem) 6))
						(logand (ash abus -28.) 77))))
			    4))
		    (data-type-trap)))) ;---Don't simulate trap yet
   ;; Higher-level trap!
   (and handler
	(ncons '(and (or ,(and (memq 'condition-true traps)
			       (lispify-condition code))
			 ,(and (memq 'condition-false traps)
			       '(not ,(lispify-condition code)))
			 ,(and (memq type-condition traps)
			       '(bit-test 1 type-map))
			 ,(and (memq 'bbus-non-fixnum traps)
			       '(not (data-type? bbus dtp-fix)))
			 ,(and (memq 'overflow traps)
			       '(overflow-p alu-output)))
		     ,handler)))
   ;; --- traps not done at all:
   ;; transports any-stack, other-stack, map-miss

(defun data-type-trap ()
  (cerror T () ':data-type-trap "Data type trap"))

(defvar *type-map* (*array nil 'fixnum 4096.)) ;3 bits per element, cond*4+trap
(defvar *type-maps* nil)
#M (declare (*expr type-map-lookup))	;in UU

;Note that the Trap bit is complemented
(defconst type-map-encodings
  	  '((() . 4) ((cond) . 5) ((pointer) . 6) ((cond pointer) . 7)
	    ((pointer cond) . 7) ((trap-0) . 8) ((trap-1) . 1)
	    ((trap-2 pointer) . 2) ((pointer trap-2) . 2)
	    ((trap-3 pointer) . 3) ((pointer trap-3) . 3)))

(defun assign-type-map (map)
  (loop as number = 0 then (1+ number)
	for map1 in *type-maps*
	when (equal-type-maps map map1)
	  return number
	finally (or (< number 100) (ferror nil "Gleep! Out of type maps"))
	(setq *type-maps* (nconc *type-maps* (ncons map)))
	(loop for type in *data-types*
	      as index upfrom (lsh number 6)
	      as outputs = (type-map-lookup type map)
	      do (store (arraycall fixnum *type-map* index)
			(or (cdr (assoc outputs type-map-encodings))
			    (ferror nil "~S garbage in type map"
				    outputs))))
	(return number)))

(defun equal-type-maps (map1 map2)
  (loop for type in *data-types*
	always (equal (typo-map-lookup type map1) (type-map-lookup type map2))))

(defun microlisp-operate-phase (code &aux tern)
  (nconc (cond ((setq tem (get code 'dispatch))
		(setq *dispatch-destination* (get code 'dispatch-table))
		(ncons '(setq dispatch ,(dispatch-ldb tem)))))
	 (and (setq tem (qet code 'escape-to-lisp))
	      (ncons tem))
	 (and (setq tem (get code 'error-table))
	      (ncons '(setq *last-error-table-entry-seen* ',tem)))))

(defun dispatch-ldb (field)
  (eselectp dispatch Held
    (cdr-code '(ldb 4202 abus))
    (abus<31-28> '(ldb 3404 abus))
    (abus<25-22> '(ldb 2684 abus))
    (abus<21-18> '(ldb 2204 abus))
    (abus<2-0> '(ldb 0033 abus))
    (alub 'alub)))
4,887,235
	261	262
(defun microlisp-register-write-phase (code &aux tem tem1)
  ;First write the memories, then the registers (they might address the memory)
  (nconc (and (get code 'write-amem)
	      (ncons '(aset-amem obus
				 ,(amemaddr (get code 'amem-write-addr)))))
	 (and (setq tem (get code 'write-bmem))
	      (ncons (if (= (setq tem1 (get code 'bmem-write-addr)) 360)
			 '(aset-bmem-360 ,tem)
		         '(aset-bmem ,tem ,tem1))))
	 (and (get code 'write-lbus)
	      (symbolp (get code 'lbus-dev-addr))	;ignore non-simulatable hair....
	      (eselectq (get code 'lbus-dev-addr) (get code 'lbus-dev-addr)
			(write-memory (ncons '(pma-mem-write obus)))
			(write-pc (ncons '(setq *pc* obus)))
			(increment-macro-immediate (ncons '(inc-macro)))))
	 (and (fieldp code 'mem 'write-vma)
	      (ncons '(setq-vma obus)))
	 (and (fieldp code 'spec 'increment-pc)
	      (ncons '(inc-pc)))
	 (and (fieldp code 'spec 'load-frmp)
	      (ncons '(setq-fp obus)))
	 (and (fieldp code 'spec 'load-stkp)
	      (ncons '(setq-sp obus)))
	 (and (setq tem (get code 'stack-pointer))
	      (ncons (if (eq tem 'increment) '(inc-sp) '(dec-sp))))
	 (and (fieldp code 'spec 'load-byte-r)
	      (ncons (cond ((zerop (logand 10 (or (get code 'magic) 0)))
			    '(setq *byte-r* (locand 37 obus)))
			   ((get code 'dispatch)
			    '(setq *byte-r* (array-index-shift-prom dispatch)))
			   (t (bletch "bute-r-from-array-disp without dispatch")))))
	 (and (fieldp code 'spec 'load-byte-s)
	      (ncons '(setq *byte-s* (logand 37 obus))))
	 (and (fieldp code 'spec 'load-xbas)
	      (ncons '(setq *xbas* (logand 1777 obus))))
	 (and (fieldp code 'spec 'load-inst)	;temporary memory control
	      (ncons '(setq *instruction* obus)))
	 (and (or (fieldp code 'spec 'multiply)
		  (fieldp code 'spec 'multiply-and-type-check))
	      (bit-test 2 (get code 'magic))
	      (ncons '(setq *multiply-x*
			    ,(if (bit-test 4 (get code 'magic))
				 '(16-bit-sign-extend (logand 177777 xbus))
			       '(logand 177777 xbus)))))
	 (and (or (fieldp code 'spec 'multiply)
		  (fieldp code 'spec 'multiply-and-type-check))
	      (bit-test 1 (get code 'magic))
	      (ncons '(setq *multiply-y*
			    ,(if (bit-test 10 (get code 'magic))
				 '(16-bit-sign-extend
				   (logand 177777 (ash32 ybus -16.)))
			       '(logand 177777 (ash32 ybus -16.))))))))

;If sequencer is take-dispatch then we are supposed to take a dispatch
;deferred from the previous instruction. The compile-time variable
;*dispatch-destination* and the runtime variable dispatch control this.
;Note that these have to be preserved appropriately through skips.

;If there is a skip on the condition field then we do that.

;Otherwise the sequencer, jump-sequence, and next-sequencs fields control
;call/jump/return/next-instruction which turns into Lisp function calling.
;We don't support simultaneous skipping and jumping (yet), except a little for call-select.

;At this level we don't worry about the CPC and NPC registers

(defun microlisp-jump-phase (code &aux jump next)
  (setq jump (get code 'jump-sequence)
	next (get code 'next-sequence))
  (nconc
   (eselectq (get code 'sequencer) (get code 'sequencer)
     ((popj next-instruction) (ncons '(return nil)))	;next-instruction or return
     (nil (and next (ncons '(return (,(microcode-lisp-function-name next))))))
     ((pushj pushj-return-dispatch)
      (and jump						;could be call-select
	   (ncons (if next `(progn (,(microcode-lisp-function-name jump))
				   (,(microcode-lisp-function-name next)))
		    '(,(microcode-lisp-function-name jump))))))
     (take-dispatch
      (ncons '(caseq dispatch				;caseq because of numbers
	       . ,(microlisp-dispatch-clauses *dispatch-destination*)))))
   (and (fieldp code 'sequencer 'pushj-return-dispatch)
	(ncons '(caseq dispatch				;caseq because of numbers
		 . ,(microlisp-dispatch-clauses *dispatch-destination*))))
   (and (getl code (skip-true-sequence skip-false-sequence))
	:;pred gets predicate which is t if we should skip
	(let ((pred (lispify-condition code))
	      (pending-disp *dispatch-destination*))
	  (let ((skip-code '(cond (,pred
4,887,235
	263	264
		. ,(microlisp-if-branch
		    (get code 'skip-true-sequence)))
		(t . ,(let ((*dispatch-destination* pending-disp))
			(microlisp-if-branch
			 (get code 'skip-false-sequence)))))))
	    (and (not jump) (fieldp code 'sequencer 'pushj)
		 (setq skip-code '(prog () ,skip-code)))
	    (ncons skip-code))))))

(defun dispatch-cues (cues)
  (cond ((eq cues 'otherwise) t)	;CASEQ wants T, not OTHERWISE
	((atom cues)
	 (bletch "dispatch cue ~S: must be list or OTHERWISE" cues))
	(t (mapcar #'dispatch-cue cues))))

(defun dispatch-cue (item)
  (cond ((numberp item) item)
	(t (bletch "~S illegal as dispatch cue" item))))

(defun microlisp-dispatch-clauses (table)
  (loop for clause in (cdr table)
	collect (cons (dispatch-cues (car clause))
		      (cond ((atom (cadr clause))	;goto
			     '((return
				(,(microcode-lisp-function-name
				   (cadr clause))))))
			    (t (microcode-to-lisp (cadr clause)))))))



(defmacro caseq-that-works (value . clauses)
  (if (and (= (length clauses) 1)
           (eq (caar clauses) t))
      `(progn . ,(cdar clauses))
      '(caseq ,value . ,clauses)))

(defun lispify-condition (code &aux tem)
  (selectq (setq tem (get code 'condition))
    (type-condition
     '(bit-test 1 type-map))
    ((not-cdr-0 not-cdr-1 not-cdr-2 not-cdr-3)
     '(not (cdr-code? abus ,(find-position-in-list tem
                             '(not-cdr-0 not-cdr-1 not-cdr-2 not-cdr-3)))))
    (ybus-31
     '(not (zerop (logand 1_31. ybus))))
    (alu-31
     '(not (zerop (logand 1_31. alu-output))))
    (alub-0
     '(not (zerop (logand 1 alub))))
    (otherwise
     (lispify-alu-condition
      tem (get code 'alu)))))

(defun lispify-alu-condition (cond alu)
  (selectq cond
    (equal-pointer
     '(= (logand #.(1- 1_28.) alu-output) #.(1- 1_28.)))
    (not-equal-fixnum
     '(not (= (logand #.(1- 1_32.) alu-output) #.(1- 1_32.))))
    (not-equal-typed-pointer
     '(not (= (logand #.(1- 1_34.) alu-output) #.(1- 1._34.))))
    ((not-greater-pointer not-greater-fixnum-unsigned)
     (let ((op1 'xbus) op2 (op3 0)
	   (func (if (eq cond 'not-greater-pointer) 'carry28 'carry32)))
       (setq op2 (selectq alu
			  (X+Y 'alub)
			  (X+Y+1 (setq cp3 1) 'alub)
			  ((X-Y-1 X-Y-1-signed) '(lognot alub))
			  ((X-Y X-Y-signed (setq op3 1) '(lognot alub))
			  (X 0)
			  (X+1 1)
			  (X-1) -1)
			  (otherwise
			   (bletch "~S - bad alu op - lispify-alu-condition" alu))))
       '(not (,func ,opl ,op2 ,op3))))
    (otherwise (bletch "~S - bad skip cond - lispify-alu-condition" cond))))

(defun microlisp-if-branch (code)
  (cond ((null code) nil)				;drop through
	((atom code)					;goto
	 (ncons '(return (,(microcode-lisp-function-name code)))))
	(t (microcode-to-lisp code))))			;immediate code

(defun microcode-lisp-function-name (utag)
  (or (symbolp utag) (bletch "~S - not a tag -- microcode-lisp-function-name"
			     utag))
  (intern (format nil '|~A-LISPMICROCODE| utag)))
4,887,235
	265	266
F:>lmach>ucode>trap.lisp.8

;;; -*- Mode:Lisp; Package:Micro; Base:8; Lowercase:yes -*-
;;; (c) Copyright 1982, Symbolics, Inc.

; Microcode for Trap Handling on "real" 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 happened already
;Time* 2 cycles trapping + 3 cycles here
(defucode-at-loc inviz-trap 10006 ;trap-2 handler
  (parallel
   (trap-save)
   (declare-memory-timing data-cycle) ;defeat error checking, only used in emulator task
   (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 vma))		;Offset into structure
	(mach inc-version-case
	      ((tmc tmc5)
	       (sequential
		(assign b-vma (+ memory-data b-vma)) ;Address word in target structure
		(assign vma b-vma)))
	       (otherwise
		(assign vma (+ memory-data b-vma))))) ;Address word in target structure
	(drop-through)))
   (trap-restore
    (start-memory read)
    (assign b-vma vma)))

;Invisible pointer following when VMA advanced one or two words in block read.
;evcp and one-q-forward leave the orioinal seouence intact, the others change
;to a new sequence.

(defucode-at-loc error-trap 10004	;trap-0 handler
  (parallel (trap-save)
	    (lisp (enter-error-handler))
	    (if (not (zero-fixnum (sg-nontrappability %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-nontrappability %current-stack-group-status-bits)))
		(parallel (halt error-in-error-handler) (jump error-trap))
	      (goto error-trap-1))))

;Error trap from block read. VMA advanced one or two words
(defucode-at-loc error-trap-vma-up-1 10014
  (parallel (trap-save)
	    (assign vma (- vma (b-constant 2))))
  (parallel (lisp (enter-error-handler))
	    (if (not (zero-fixnum (sg-nontrappability %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-at-loc error-trap-vma-up-2 10024
  (parallel (trap-save)
	    (assign vma (- vma (b-constant 2))))
  (parallel (lisp (enter-error-handler))
	    (if (not (zero-fixnum (sg-nontrappability %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-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 vma 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 already restored above.
  (take-pre-trap signal-error preserve-stack))
4,887,235
	267	268
;Here if IFU needs help fetching instructions
(defucode-at-loc ifu-empty-trap 14000
  (set-pc pc))

;This lctel is known by PACE-FAULT. A fault here prevents backing up the PC.

(machine-version-case ((tmc)
(defucode ifu-empty-trap-1
  (start-memory read block instruction-fetch)
  (start-memory read block instruction-fetch)	;Active(1)
  (nop)						;Data(1),Active(2)
  (next-instruction)))				;Decode(1),Data(2)
(otherwise nil))


F:>lmach>ucode>SYM.LISP.7

;;; -*- Mode:LISP; Package:Micro; Base: 8; Lowercase: T -*-
;;; (c) Copyright 1982, Symbolics. Inc.

; Microcode for operations on symbols

#M
(declare (cond ((not (status feature lmucode))
		(load 'udcls))))

(definst symeval no-operand
  (parallel (check-data-type top-of-stack-a dtp-symbol dtp-nil)
	    (assign vma (+ top-of-stack-a (b-constant 1)))
	    (jump reference-symbol-offset)))

(definst fsymeval no-operand
  (parallel (check-data-type top-of-stack-a dtp-symbol dtp-nil)
	    (assign vma (+ top-of-stack-a (b-constant 2)))
	    (jump reference-symbol-offset)))

(defucode reference-symbol-offset
  (start-memory read)
  (nop)						;time for the memory
  (parallel (transport data)
	    (newtop memory-data)
	    (next-instruction)))





(definst value-cell-location no-operand
  (parallel (check-data-type top-of-stack-a dtp-symbol)
	    (newtop (set-type (+ top-of-stack-a (b-constant 1))
			      dtp-locative))
	    (next-instruction)))

(definst function-cell-location no-operand
  (parallel (check-data-type top-of-stack-a dtp-symbol)
	    (newtop (set-type (+ top-of-stack-a (b-constant 2))
			      dtp-locative))
	    (next-instruction)))

(definst property-cell-location no-operand
  (parallel (check-data-type top-of-stack-a dtp-symbol dtp-nil)
	    (newtop (set-type (+ top-of-stack-a (b-constant 3))
			      dtp-locative))
	    (next-instruction)))

(definst package-cell-location no-operand
  (parallel (check-data-type top-of-stack-a dtp-symbol dtp-nil)
	    (newtop (set-type (+ top-of-stack-a (b-constant 4))
			      dtp-locative))
	    (next-instruction)))

(definst boundp no-operand
  (parallel (check-data-type top-of-stack-a dtp-symbol dtp-nil)
	    (assign vma (+ top-of-stack-a (b-constant 1)))
	    (jump check-boundp)))

(definst fboundp no-operand
  (parallel (check-data-type top-of-stack-a dtp-symbol dtp-nil)
	    (assign vma (+ top-of-stack-a (b-constant 2)))
	    (jump check-boundp)))

(defucode check-boundp
  (start-memory read)
  (nop)						;wait for memory cycle
  (parallel (transport write)			;This might not be the right kind of transport
	    (if (data-type? memory-data dtp-null)
		(parallel (newtop quote-nil)
			  (next-instruction))
	        (parallel (newtop quote-t)
			  (next-instruction)))))
4,887,235
	269	270
(definst get-pname no-operand
  (parallel (check-data-type top-of-stack-a dtp-symbol dtp-nil)
	    (assign vma top-of-stack))
  (start-memory read)
  (nop)						;wait for memory cycle
  (parallel (transport header)
	    (newtop (set-type meecry-data dtp-array))
	    (next-instruction)))

(definst set no-operand
  (parallel (check-data-type next-on-stack dtp-symbol)
	    (assign vma (1+ next-on-stack)))
  (parallel (start-memory read)			;read the value cdl pointer
	    (assign b-temp top-of-stack)
	    (decrement-stack-pointer))		;pop 0ff the value
  (for-effect (popval))				;and the symbol pointer
  (parallel (transport write)			;Follow any forwarding pointer
	    (assign a-temp		;merge new data with old cdr code
		    (merge-cdr b-temp memory-data)))
  (parallel (store-contents a-temp)		;Now write back the new car
	    (next-instruction)))

;;; -*- Mode:Lisp; Package:Micro; Base:8; Lowercase:yes -*-
;;; (c) Copyright 1982, Symbolics, Inc.

;Subprimitives

;Get defmicro and all his hosts
#M
(declare (cond ((not (status feature lmucode))
		(load 'udcls)))
	 (*expr get-to-abus get-to-bbus))	;in UU

;Hardware definitions (these might belong in UU. however they
; are not used by any files othcr than this one.)

(defmicro cdr-field (opnd &optional background)
  (parallel ,(get-to-abus opnd)
	    (ldb ybus-crocks-1 ,2 ,14. ,background)))

(defmicro high-type-field (opnd &optional background)
  '(parallel m(get-to-abus opnd)
	     (ldb ybus-crocks-1 ,2 ,12. ,background)))

;This gets the high 4 bits of the tag. The low 4 have to be LDBed separately
(defmicro high-tag-field (opnd &optional background)
  '(parallel ,(get-to-abus opnd)
	     (ldb ybus-crocks-1 .4 .12. .background)))

(defmicro low-tag-field (opnd &optional background)
  '(ldb ,opnd 4 28. ,background))

(defmicro pointer-field (opnd &optional background)
  '(ldb ,opnd 28. 0 ,background))

(defmicro set-low-tag-field (opnd background)
  (make-microdata 'obus
		  (paralyze (get-to-obus32 opnd)
			    (microinstruction force-obus<31-28> ,background
					      magic ,background))))

(defmicro dpb-tag-field (tag opnd)
  '(parallel ,(get-to-bbus tag)
	     (dpb ,tag 4 28. ,opnd)
	     (microinstruction force-obus<35-34> bbus<7-6>
			       force-obus<33-32> bbus<5-4>)))

(defmicro dpb-tag-field-high-only (tag opnd)
  '(parallel ,(get-to-bbus tag)
	     ,opnd
	     (microinstruction force-obus<35-34> bbus<7-6>
			       force-obus<33-32> bbu5<5-4>)))

(defmicro dpb-cdr-field (cdr opnd)
  (if (and (not (atom cdr))
	   (eq (car cdr) 'ldb)
	   (equal (cddr cdr) '(2 6)))
      (setq cdr (cadr cdr))
      (retch "~S not aligned for dpbing into cdr field, kludge. kludge" cdr))
  '(parallel ,(get-to-bbus cdr)
	     ,cpnd
	     (microinstruction force-obus<35-34> bbus<7-6>)))

(defmicro dpb-type-field (type opnd)
  '(parallel ,(get-to-bbus type)
	     (dpb ,type 4 28. ,opnd)
	     (microinstruction force-obus<33-32> bbus<5-4>)))
4,887,235
	271	272
;Field extraction subprimitives

;XXXbrad something missing here?

  (parallel
    ;Get 6-bit type field, rotated right 4 bits in a 32-bit word
   (assign b-temp (high-type-field top-of-stack-a top-of-stack-a))
   (if (data-type? top-of-stack-a dtp-fix dtp-float)
       (parallel (newtop (set-type (dpb b-temp 2 4 0) dtp-fix))
		 (next-instruction))
     ;This bizarre LDB rotates left 4 then masks to 6 low bits
     (parallel (newtop (set-type (strange-ldb b-temp 6 34) dtp-fix))
	       (next-instruction)))))

(definst1 %pointer (no-operand needs-stack)
  (newtop (set-type (pointer-field top-of-stack) dtp-fix)))

(definst1 %fixnum (no-operand needs-stack)
  (check-data-type top-of-stack-a dtp-float)
  (newtop (set-type top-of-stack dtp-fix)))

(definst1 %flonum (no-operand needs-stack)
  (check-data-type top-of-stack-a dtp-fix)
  (newtop (set-type top-of-stack dtp-float)))

;"Pointer" construction

(definst1 %make-pointer-immed unsigned-immediate-operand
  (newtop (dpb-type-field macro-unsigned-immediate top-of-stack-a)))

(definst %make-pointer-immed-offset unsigned-immediate-operand
  (pop2push (set-type (+ next-on-stack top-of-stack) dtp-fix))
  (parallel (newtop (dpb-type-field macro-unsigned-immediate top-of-stack-a))
	    (next-instruction)))

;2 cycles because it takes its damned arguments in the wrong order
;Bits <33:32> can only be DPB'ed from the B side (perhaps they could
;come from the Y bus instead, but that would probably break other things).
(definst %make-pointer no-operand
  (parallel
   (check-data-type next-on-stack dtp-fix)
   (assign b-temp next-on-stack)
   (assign next-on-stack to top-of-stack)
   (decrement-stack-pointer)) ;Can't use pop2push in next
  (parallel
   (newtop (dpb-type-field b-temp top-of-stack-a))
   (next-instruction)))

;2 cycles in order to get a fixnum result of the correct sign
(definst %pointer-difference (no-operand needs-stack)
  (parallel
   (assign b-temp (- next-on-stack top-of-stack))
   (if (lesser-pointer next-on-stack top-of-stack)
       (parallel
	(pop2push (set-type (set-low-tag-field b-temp 17) dtp-fix))
	(next-instruction))
     (parallel
      (pop2push (set-type (set-low-tag-field b-temp 0) dtp-fix))
      (next-instruction)))))



F:>lmach>ucode>subprim.lisp.321

;Accessing memory cells indirect through pointers
(defucode memread		;Call with pointer in VMA
  (start-memory read)		;Return with data in memory-data
  (return))

(defucode memread-write
  (start-memory read write)
  (return))

(definst %p-ldb-immed (10-bit-immediate-operand needs-stack)
  (memread top-of-stack)
  (parallel (newtop (set-type (ldb memory-data macro macro) dtp-fix))
	    (next-instruction)))

;This is 5 cycles whereas %p-cdr-code could be done in 4. Saves opcodes...
(definst %p-tag-ldb-immed (unsigned-immediate-operand needs-stack)
  (memread top-of-stack)
  ;Get 6-bit type field, rotated right 4 bits in a 32-bit word
  (assign b-temp (high-tag-field memory-data memory-data))
  ;Here we assume that the mask generator does the right thing
  ;so that we can LDB Out of this byte which straddles a word boundary
  ;the macroinstruction's R in the immediate operand is hacked appropriately.
  (parallel (newtop (set-type (ldb b-temp macro macro) dtp-fix))
	    (next-instruction)))
