;;; -*- Mode:LISP; Package:K-KBUG; Readtable:CL; Base:10; compile-in-roots:("K-GLOBAL") -*- (defmacro dpb-multiple (&rest fields) (labels ((expander (fields) (cond ((null fields) (error "Even number of arguments to ~s" 'dpb-multiple)) ((null (rest fields)) (first fields)) (t `(DPB ,(first fields) ,(second fields) ,(expander (rest (rest fields)))))))) (expander fields))) (defun hex (n) (format t "~x" n)) (defun hex32 (n &optional (stream t)) (format stream "~8,'0x" n)) (defmacro deff (symbol frob) `(EVAL-WHEN (COMPILE LOAD EVAL) (SETF (SYMBOL-FUNCTION (QUOTE ,symbol)) ,frob))) (defvar *system-version* 0) (defvar *version-cache-generation* 0) ;(eval-when (compile eval load) ;(defun memoized (function) ; (let ((last-time -1) ; last-value) ; #'(lambda () ; (if (= last-time *version-cache-generation*) ; last-value ; (prog1 (setq last-value (funcall function)) ; (setq last-time *version-cache-generation*)))))) ;) (defun invalidate-version-cache () (incf *version-cache-generation*)) (defun get-appropriate-constants (constant-list) (let ((best-list-so-far '()) (best-version-so-far 0)) (dolist (l constant-list) (let ((version-number (first l)) (this-list (second l))) (when (and (<= version-number *system-version*) (or (null best-list-so-far) (> version-number best-version-so-far))) (setq best-list-so-far this-list) (setq best-version-so-far version-number)))) (when (null best-list-so-far) (error "Couldn't find appropriate constants.")) best-list-so-far)) ;(do-symbols (s 'k) ; (export s 'k)) (defvar *i-mode* :dis) (defun print-instruction (i &optional (stream t)) (case *i-mode* (:hex (format stream "~16,'0x" i)) (:dis (format stream "~x" (nc::dis i))))) (defun make-fancy-wait-function (outer-wait-function inner-wait-function) (let ((last-time (zl::time-increment (zl:time) -30))) #'(lambda () (or (funcall outer-wait-function) (and (> (zl:time-difference (zl:time) last-time) 30) (progn (setq last-time (zl:time)) (funcall inner-wait-function))))))) (defun k-halted-p () ;dont check k-run-flag here since processor might have been otherwise started (i.e. by MAC hopefully) (or (null k-run-flag) ;unfortunately, this is necessary because we cant read the debug-logic COMMAND ; RUN FUNCTION, can we? (let ((response (lam:k-read-spy-program-halt))) (= 1. response)))) (defun kbug (&optional starting-address offset safe-mode) ;safe-mode assumes PCD is set up and does not molest processor (when (null offset) (setq offset (if (boundp '*code-start*) *code-start* 0))) (lam:falcon-stop) (when starting-address (start starting-address)) (do () (()) (let* ((addr (logand #xFFFFFF (k-read-spy-pc))) (sym-addr (get-symbolic-address addr)) (mmfio (lam::k-read-spy-mmfio))) (if sym-addr (format t "~&~15a(#x~x) ~8,'0x " sym-addr addr mmfio) (format t "~&~6,'0x ~8,'0x " addr mmfio)) (print-instruction (if safe-mode (kbug-generic-read-inst-safe addr) (lam:read-inst (+ addr offset)))) ;** note that this reads a PHYSICAL address ;since the PC is really VIRTUAL, we could get the wrong thing. (let ((input (peek-char))) (lam:falcon-stop) (case input ((#\space #\c-n) (read-char) (lam:falcon-step)) (#\c-p (read-char) (when (eq 'lose-big (proceed-kbug)) (return-from kbug))) (#\c-z (read-char) (lam:falcon-stop)) (#\c-f (read-char) (frames 16)) (#\c-m-f (read-char) (frames-with-types)) (#\q (read-char) (return-from kbug)) ((#\c-l #\clear-screen) (read-char) (zl::send *terminal-io* :clear-window)) (#\m-s (read-char) (show-call-stack)) (#\m-e (read-char) (format t "~%") (show-error)) (#\m-r (read-char) (global:do-forever (if (listen *terminal-io*) (return t)) (lam:falcon-step) (let* ((addr (logand #xFFFFFF (k-read-spy-pc))) (sym-addr (get-symbolic-address addr)) (mmfio (lam::k-read-spy-mmfio))) (if sym-addr (format t "~&~15a(#x~x) ~8,'0x " sym-addr addr mmfio) (format t "~&~6,'0x ~8,'0x " addr mmfio)) (print-instruction (if safe-mode (kbug-generic-read-inst-safe addr) (lam:read-inst (+ addr offset))))))) (#\help (read-char) (debugger-help)) (#\i (read-char) (print-single-step-info)) (#\2 (read-char) (when (= 1. (k-read-spy-program-halt)) (dotimes (i 5.) (lam:falcon-step)) (k-run)) (format t "~%*** Entering KBUG2 ***") (kbug2)) (otherwise (zl:catch-error-restart ((sys:abort) "Return to KBUG.") (multiple-value-bind (sexp flag) (zl:with-input-editing (*terminal-io* '((:full-rubout :full-rubout) (:activation char= #\end) (:prompt prompt-for-kbug))) (read)) (if (eq flag :full-rubout) () (progn (terpri) (prin1 (prog1 (eval sexp) (terpri))))))))))))) (defun proceed-kbug () ;; Crock: Step first four instructions to make halt bit off. ;; This depends upon the behavior of the code at illop. (when (= 1. (k-read-spy-program-halt)) (dotimes (i 5.) (lam:falcon-step))) (lam:falcon-run) (zl:process-wait "Kbug" (let ((stream *terminal-io*)) (make-fancy-wait-function #'(lambda () (listen stream)) #'k-halted-p))) (let ((response (k-read-spy-program-halt))) (cond ((not (numberp response)) (format t "~%Yow! Down in flames.") (return-from proceed-kbug 'lose-big)) ((= 1. (k-read-spy-program-halt)) (format t "~%HALTED: ") (why) (lam:falcon-stop)) (t (lam:falcon-stop) (format t "~%STOP"))))) (defun kbug-read-eval-print-one-form () (multiple-value-bind (sexp flag) (zl:with-input-editing (*terminal-io* '((:full-rubout :full-rubout) (:activation char= #\end) (:prompt prompt-for-kbug))) (read)) (if (eq flag :full-rubout) () (progn (terpri) (prin1 (prog1 (eval sexp) (terpri))))))) (defun kstep (n) (dotimes (i n) (k-step))) (defun print-frame (n stream) (let ((frame-contents (saving-current-k-pc #'(lambda () (k-read-frame n))))) (format stream "~:{~%~x:~:[ ~;*~]~8,'0x~}" (reverse frame-contents)))) (defun read-global (s) (let ((info (get s :register))) (when (null info) (error nil "Couldn't find global ~S" s)) (saving-current-k-pc #'(lambda () (k-read-register (second info) (third info)))))) (defun print-single-step-info () (saving-current-k-pc #'(lambda () ; (let ((trapped-pc (first (read-global 'gr::*save-trap-pc*)))) ; (disassemble-from-virtual-memory trapped-pc 1.)) (let ((hp-sp (k-read-hp-sp))) (format t "~%HP,SP: ~2,'0x ~2,'0x " (ldb (byte 8. 8.) hp-sp) (ldb (byte 8. 0.) hp-sp))) (let ((retpc-rdest (k-read-retpc-rdest))) (format t "RETPC, RDEST: ~6,'0x ~[O~;A~;R~;G~;NO~;NO~;NTO~;NTO~]~2,'0x" (ldb (byte 23. 0.) retpc-rdest) (ldb (byte 3. 28.) retpc-rdest) (ldb (byte 4. 24.) retpc-rdest))) (mapcar #'(lambda (pair) (format t " ~a" (get-symbolic-address (second pair)))) (dump-call-stack))))) (defun dump-call-stack () (saving-hp-csp #'(lambda (hp csp) (declare (ignore hp)) (labels ((dump-csp (depth stuff-so-far) (if (minusp depth) (reverse stuff-so-far) (progn (k-write-hp-csp (dpb depth (byte 8. 0.) 0.)) (let ((retpc-rdest (k-read-retpc-rdest))) (dump-csp (1- depth) (cons (list (ldb (byte 7. 24.) retpc-rdest) (ldb (byte 24. 0.) retpc-rdest)) stuff-so-far))))))) (dump-csp csp '()))))) (defun get-starting-address (fcn &optional default) (cond ((numberp fcn) fcn) (t (let ((f (nc::get-ncompiled-function fcn))) (when f (or (nc::ncompiled-function-starting-address f) default)))))) (defun load-code (code &optional (addr #x100)) "Load a sequence of instructions at starting address" (lisp:map nil #'(lambda (inst) (lam:write-inst addr inst) (incf addr)) code)) (defun load-fcn (fcn &optional (virtual-address (get-starting-address fcn #x100)) (physical-address virtual-address)) (let ((f (nc::get-ncompiled-function fcn))) (nc::link f virtual-address) (load-code (nc::ncompiled-function-code f) physical-address))) ;;; note that this links twice ;;; but that is good because then "forward references" are resolved (defun load-fcns (fcns &optional (starting-address #x100)) (let ((cfuns (map 'list #'nc::get-ncompiled-function fcns))) (setq *loaded-functions* cfuns) (do ((fs cfuns (cdr fs)) (addr starting-address (+ addr (nc::ncompiled-function-length (car fs))))) ((null fs)) (nc::link (car fs) addr nil)) (dolist (f cfuns) (load-fcn f)))) (defun start (addr) (k-start (get-starting-address addr))) (defun run (&optional addr) (if addr (k-go (get-starting-address addr)) (k-run))) (defun read-oar () (declare (values open active return)) (let ((oar (k-read-oar))) (values (ldb hw::%%ch-oar-open oar) (ldb hw::%%ch-oar-active oar) (ldb hw::%%ch-oar-return oar)))) (defun frames-with-types (&optional (stream t) (n 16.)) (let ((old-pc (k-read-spy-pc)) (left (kbug-left)) (right (kbug-right)) (left-boxed (kbug-left-boxed)) (right-boxed (kbug-right-boxed))) (multiple-value-bind (open active return-frame) (read-oar) (new-format stream newline labeled-boxed-32 "Left " (ldb-test (byte 1. 0.) left-boxed) left labeled-boxed-32 " Right " (ldb-test (byte 1. 0.) right-boxed) right labeled-hex-2 " Open #x" open labeled-hex-2 " Active #x" active labeled-hex-2 " Return #x" return-frame newline) (if (= open active) (progn (dotimes (i n (format stream "~%")) (new-format stream "~% ~a~2D" 'a i boxed-32 nil (read-open i) " ") (show-data-type-and-object (read-open i) stream)) (dotimes (i n (format stream "~%")) (new-format stream "~% ~a~2D" 'r i boxed-32 nil (read-return i) " ") (show-data-type-and-object (read-return i) stream))) (progn (dotimes (i n (format stream "~%")) (new-format stream "~% ~a~2D" 'a i boxed-32 nil (read-open i) " ") (show-data-type-and-object (read-open i) stream)) (dotimes (i n (format stream "~%")) (new-format stream "~% ~a~2D" 'r i boxed-32 nil (read-active i) " ") (show-data-type-and-object (read-active i) stream)) (dotimes (i n (format stream "~%")) (new-format stream "~% ~a~2D" 'r i boxed-32 nil (read-return i) " ") (show-data-type-and-object (read-return i) stream))))) (format t "~&Q: ~8,'0x" (read-q)) (k-set-pc old-pc))) (defun frames (&optional (n 16.)) (let ((old-pc (k-read-spy-pc))) (multiple-value-bind (open active return-frame) (read-oar) (format t "~&O: ~x A: ~x R: ~x" open active return-frame) (dotimes (i n) (format t "~&O~2d: ~8,'0x A~2d: ~8,'0x R~2d: ~8,'0x" i (read-open i) i (read-active i) i (read-return i)))) (format t "~&Q: ~8,'0x" (read-q)) (k-set-pc old-pc))) (defun ktrace (fcn &optional (nregs 3)) (let ((addr (get-starting-address fcn))) (do () (()) (do () ((= (k-read-spy-pc) addr))) (k-stop) (terpri) (dotimes (i nregs) (format t "~d " (logand #xFFFFFF (read-active i)))) (k-set-pc (1+ addr)) (k-run)))) (defun show-address (k-address &optional (stream t)) (format stream "~%Address #x~x, quantum #x~x, cluster #x~x, within cluster #x~x" k-address (ldb vinc:%%quantum-number k-address) (ldb vinc:%%cluster-number k-address) (logand k-address #X3FF))) ;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; Memory map functions ;;;;;;;;;;;;;;;;;;;;;;;;;; (defun show-entire-map (&optional (stream t) (starting-at-quantum 0) &aux last-elided) (format stream "~%show-entire-map:~%") (do ((quantum starting-at-quantum (1+ quantum))) ((>= quantum 4096.)) (dotimes (c 16.) (let* ((cluster (+ (* quantum 16.) c)) (map-entry (kbug-read-map-cluster cluster))) (cond ((and last-elided (= map-entry last-elided))) ((member map-entry '(0 #o3200)) ;null or fresh, swapped-out, local (format stream "~%...#x~4,'0x " cluster) (decode-map-entry map-entry stream) (setq last-elided map-entry)) (t (setq last-elided nil) (format stream "~%#x~4,'0x " cluster) (decode-map-entry map-entry stream))))))) (defun show-map (entry stream) (let ((bits (map::read-map entry))) (format stream "~&~5,48x " entry) (decode-map-entry bits stream))) (defun direct-map-location-zero () ;called by pseudo-boot (map::write-map 0 (map::inject-map-status (dpb-multiple hw:$$map-local hw:%%map-local-memory-bit 0 hw:%%map-on-board-address map::$$cluster-not-fresh map::%%map-fresh-cluster 0) map:$$map-status-normal))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; Downloading the cold load ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defvar *loaded-functions* ()) (defvar *code-free-pointer* #x100) (defvar *code-start* 0.) ;physical memory origin of code loaded by cold loader. (as doubleword address) (defvar *code-holes* ()) (defun download-cold-load () (lam::k-reset) (k-init) (setq *breakpoints-installed* nil) (dotimes (i cold::*cold-data-size*) (k-mem-write (ash i 2.) (cold::cold-data-read i))) (let ((instructions-start (truncate (cold::cold-data-read 43.) 2)) (clusters (cold::cold-data-read 44.))) (dotimes (i (* clusters 512.)) ;512 instructions per cluster (lam:write-inst (+ i instructions-start) (cold::cold-code-read i))) (setq *code-free-pointer* (+ instructions-start (* clusters 512))) (setq *code-start* instructions-start) (dolist (f cold::*cold-loaded-functions*) (setf (nc::ncompiled-function-code f) :in-memory)) (setq *loaded-functions* cold::*cold-loaded-functions*) nil )) ;(defun disassemble-fcn-from-memory (fcn) ; (setq fcn (nc::get-ncompiled-function fcn)) ; (format t "~%In memory:") ; ;; No, I don't know why disassemble-from-virtual-memory doesn't work here ; (kbug::disassemble-from-core (+ *code-start* (nc::ncompiled-function-starting-address fcn)) ; (nc::ncompiled-function-length fcn))) (defun compile-defun-to-k-core (form) (let ((fcn (nc::cc form))) (load-fcn fcn (- *code-free-pointer* *code-start*) *code-free-pointer*) (incf *code-free-pointer* (nc::ncompiled-function-length fcn)))) ;(zwei:DEFCOM com-compile-defun-to-k-core "" () ; (zwei::COMPILE-DEFUN-INTERNAL #'compile-defun-to-k-core "Kompiling" "kompiled.") ; zwei::DIS-NONE) ;(zwei::COMMAND-STORE 'com-compile-defun-to-k-core #\h-sh-C zwei::*ZMACS-COMTAB*) (defun get-symbolic-address (addr) (dolist (f *loaded-functions*) (when f (let ((sa (nc::ncompiled-function-starting-address f))) (when (and sa (>= addr sa) (< addr (+ sa (nc::ncompiled-function-length f)))) (let ((name (nc::ncompiled-function-name f))) (return (if (= addr sa) (format nil "~a" name) (format nil "~a+~x" name (- addr sa)))))))))) (defvar *maximum-function-size* 1000.) ;scan back no further than this looking for function header. (defun kbg-symbolic-address (pc) ;kbug-symbolic-address for when k is stopped. scan ourselves. (do* ((current-pc pc (1- current-pc)) (pc-offset -1 (1+ pc-offset)) (inst-low (k-read-virtual-memory (logior #X2000000 (ash current-pc 1.))) (k-read-virtual-memory (logior #X2000000 (ash current-pc 1.)))) (inst-high (k-read-virtual-memory (logior #X2000001 (ash current-pc 1.))) (k-read-virtual-memory (logior #X2000001 (ash current-pc 1.)))) (back-pointer-type (ldb vinc:%%data-type inst-low) (ldb vinc:%%data-type inst-low))) ((= inst-high cons:code-header-instruction-high) (cond ;; Normal functions ((= back-pointer-type vinc:$$dtp-compiled-function) (let* ((fef-struct-base inst-low) ;word after function header is struct pointer. This is (function-symbol (k-read-virtual-memory (1+ fef-struct-base))) ; inst-low since we fetched 64. bits. (function-symbol-data-type (hw:ldb function-symbol vinc:%%data-type 0))) (cond ((= function-symbol-data-type vinc:$$dtp-symbol) (list (read-symbol-name function-symbol) pc-offset)) ((= function-symbol-data-type vinc:$$dtp-cons) ;(internal fctn ...) (list (with-output-to-string (stream) (show-object function-symbol stream)) pc-offset)) (t (format t "~%Bad function symbol pointer:") (show-object function-symbol) (global:fsignal "lose"))))) ;; look back again starting from real call (&REST links) ((= back-pointer-type vinc:$$dtp-unboxed-locative) (kbg-symbolic-address (logand #xffffff (ash inst-low -1)) ;(ldb (byte 24. 1) inst-low) ;avoid lambda bignum screw. )) ;; this should only happen before cold symbols are warm loaded (t nil))) (if (> pc-offset *maximum-function-size*) (return nil)) )) ;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; Disassemble from core ;;;;;;;;;;;;;;;;;;;;;;;;;; ; ;(defun disassemble-from-core (start how-much) ; (dotimes (i how-much) ; (format t "~%#x~x ~s" (- (+ i start) *code-start*) (nc::Dis (lam:read-inst (+ i start)))))) ;(defun disassemble-from-virtual-memory (pc how-much) ; (dotimes (i how-much) ; (let ((low-half (k-read-virtual-memory (logior #X2000000 (ash (+ i pc) 1.)))) ; (high-half (k-read-virtual-memory (logior #x2000001 (ash (+ i pc) 1.))))) ; (format t "~%~x ~s" (+ i pc) (nc::dis (logior (ash high-half 32.) low-half)))))) ;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; Booting the machine ;;;;;;;;;;;;;;;;;;;;;;;;; (defconstant *first-instruction-cluster* #X8000) ;;; Defined for all time. ;;; These are intended to be blown into the all boot proms. (defconstant **boot-vector-origin** 42.) (defconstant **bootprom-version** 0.) (defconstant **initial-code-physical-location-bv-offset** 1.) (defconstant **initial-code-size-in-clusters-bv-offset** 2.) (defconstant **initial-code-entry-point-bv-offset** 3.) (defconstant **physical-memory-block-map** 4.) (defun read-boot-vector (entry) (kbug-generic-read-memory (+ **boot-vector-origin** entry))) (defun write-boot-vector (entry value) (kbug-generic-write-memory (+ **boot-vector-origin** entry) value)) ;;; End of defined for all time. (defun pseudo-boot () ;leaves PC set to starting location. (k-init) (setup-processor-control-register) (setup-memory-control-register) ;; Traps are off here. ;; This is where the virtual page zero location for NIL gets mapped to physical page zero. (direct-map-location-zero) ;; Now, we figure out where to map the initial instructions. (labels ((map-n-instruction-clusters (n physical virtual) (unless (zerop n) (format t "~&Mapping ~X to ~X" virtual physical) (map::write-map virtual (map::inject-map-status (dpb-multiple physical hw:%%map-on-board-address hw:$$map-local hw:%%map-local-memory-bit 0 hw:%%map-volatility 0 hw:%%map-c-trap-bits 0) map::$$map-status-read-only)) (map-n-instruction-clusters (1- n) (1+ physical) (1+ virtual))))) (let ((n (dpb 0 vinc:%%data-type (boot::read-boot-vector **initial-code-size-in-clusters-bv-offset**))) (physical (ash (dpb 0 vinc:%%data-type (boot::read-boot-vector **initial-code-physical-location-bv-offset**)) -10.)) (virtual *first-instruction-cluster*)) (format t "~&n = ~s physical = ~s virtual = ~s" n physical virtual) (map-n-instruction-clusters n physical virtual))) ;; Size the physical memory (let ((size (find-physical-memory))) ;return megabyte-per-bit bit-map. (format t "~%Physical memory (megabyte) bit-map = ~B~%" size) (write-boot-vector **physical-memory-block-map** size)) ;; Inform the K about the bootprom version (write-boot-vector **bootprom-version** 0.) ;(global:fsignal "Ready to proceed K") ;; Mapped in some instructions, jump to them. (hw:jump (read-boot-vector **initial-code-entry-point-bv-offset**)) ) (defun setup-memory-control-register () (hw:write-memory-control (dpb-multiple ;; Top bits will be zero, so traps will be off. hw:$$reset-trap-bit-off hw:%%memory-control-reset-trap-bit hw:$$dram-parity-disable hw:%%memory-control-dram-parity-enable hw:$$bootprom-off hw:%%memory-control-bootprom-disable 0 hw:%%memory-control-transporter-mode hw:$$lisp-map-bits hw:%%memory-control-l-c-map-select hw:$$write-normal-parity hw:%%memory-control-write-wrong-parity hw:$$timer-interrupt-disable-reset hw:%%memory-control-16384-interrupt hw:$$timer-interrupt-disable-reset hw:%%memory-control-1024-interrupt hw:$$icache-trap-disable-reset hw:%%memory-control-icache-error-enable hw:$$nubus-transfer-32-bits hw:%%memory-control-nubus-transfer-mode 7. hw:%%memory-control-leds 0))) (defun falcon-complete-status () (format t "~%PC reads #x~x, halt ~s" (k-read-spy-pc) (k-read-spy-program-halt)) (k-stop) (decode-memory-control-register (hw:read-memory-control)) (decode-memory-status-register (hw:read-memory-status)) (decode-processor-control-register (hw:read-processor-control)) (decode-processor-status-register (hw:read-processor-status)) ) (defun decode-memory-control-register (&optional (memory-bits (hw:read-memory-control))) (format t "~%Traps ~[dis~;en~]abled~ ~%Asynchronous traps ~[dis~;en~]abled~ ~%Overflow trap ~[dis~;en~]abled~ ~%Datatype trap ~[dis~;en~]abled~ ~%Synchronous traps ~[dis~;en~]abled~ ~%Single-step trap ~[dis~;en~]abled~ ~[~;~%**Unused bit is on**~]~ ~%Reset trap bit ~[on~;off~]~ ~[~;~%**Unused bits are on **~]~ ~%Dram parity ~[dis~;en~]abled~ ~%Bootprom ~[on~;off~]~ ~%Transporter mode ~D~ ~%Lisp/C map select ~[Lisp mode~;C mode~]~ ~%Parity select ~[Correct parity~;Wrong parity~]~ ~%16384 interrupt ~[dis~;en~]abled~ ~%1024 interrupt ~[dis~;en~]abled~ ~%Icache errors ~[dis~;en~]abled~ ~%Nubus transfer mode ~[32-bits~;Byte 0~;Block~;Byte 2~;~ Low 16 bits~;Byte 1~;High 16 bits~;Byte 3~]~ ~%Leds ~D~ ~%Statistics polarity ~[true~;invert~]~ ~%Statistics source ~[Icache hit~;Processor memory cycle~;Instruction stat bit~;~ Unused 3~;PC in high core~;Unused 5~;Unused 6~;Unused 7~]~ ~%Statistics mode ~[Edge trigger~;Duration~]" (ldb hw:%%memory-control-master-trap-enable memory-bits) (ldb hw:%%memory-control-asynchronous-trap-enable memory-bits) (ldb hw:%%memory-control-overflow-trap-enable memory-bits) (ldb hw:%%memory-control-datatype-trap-enable memory-bits) (ldb hw:%%memory-control-synchronous-trap-enable memory-bits) (ldb hw:%%memory-control-single-step-enable memory-bits) (ldb (byte 1. 25.) memory-bits) (ldb hw:%%memory-control-reset-trap-bit memory-bits) (ldb (byte 3. 20.) memory-bits) (ldb hw:%%memory-control-dram-parity-enable memory-bits) (ldb hw:%%memory-control-bootprom-disable memory-bits) (ldb hw:%%memory-control-transporter-mode memory-bits) (ldb hw:%%memory-control-l-c-map-select memory-bits) (ldb hw:%%memory-control-write-wrong-parity memory-bits) (ldb hw:%%memory-control-16384-interrupt memory-bits) (ldb hw:%%memory-control-1024-interrupt memory-bits) (ldb hw:%%memory-control-icache-error-enable memory-bits) (ldb hw:%%memory-control-nubus-transfer-mode memory-bits) (logxor 7. (ldb hw:%%memory-control-leds memory-bits)) (ldb hw:%%memory-control-statistics-polarity memory-bits) (ldb hw:%%memory-control-statistics-source memory-bits) (ldb hw:%%memory-control-statistics-mode memory-bits))) (defun setup-processor-control-register () (hw:write-processor-control (dpb-multiple hw:$$icache-set-disable hw:%%processor-control-icache-a-enable hw:$$icache-set-disable hw:%%processor-control-icache-b-enable hw:$$icache-set-disable hw:%%processor-control-icache-z-enable 0 hw:%%processor-control-spare-3 0 hw:%%processor-control-jump-indirect hw:$$floating-point-status-ram-read hw:%%processor-control-floating-point-status-ram-write-enable hw:$$box-mode-normal hw:%%processor-control-box-mode hw:$$run hw:%%processor-control-halt-processor 0 hw:%%processor-control-data-bit 0 hw:%%processor-control-misc 0 hw:%%processor-control-stack-group-number 0 hw:%%processor-control-spare-17 hw:$$call-heap-underflow-trap-disable hw:%%processor-control-heap-underflow-trap-enable hw:$$floating-point-trap-disable hw:%%processor-control-floating-point-trap-enable 0))) (defun decode-processor-control-register (&optional (processor-bits (hw:read-processor-control))) (format t "~[~;~:;~:**Undefined processor control bits 20-23 #x~x.~]~ ~%Floating point trap ~[dis~;en~]abled~ ~%Heap underflow trap ~[dis~;en~]abled~ ~%Call Stack load control ~[normal~;special~]~ ~%Stack group #x~x~ ~%Misc bits #x~x~ ~%Data bit ~b~ ~%Halt bit ~[Run~;Halt~]~ ~%Box mode ~[normal~;register reload~]~ ~%FPS ram write enable ~[Read~;Write~]~ ~%Jump Indirect ~[Fall through~;Jump~]~ ~[~;~%*Spare bit 3 is on*~]~ ~%Low core cache ~[dis~;en~]abled~ ~%Cache set B ~[dis~;en~]abled~ ~%Cache set A ~[dis~;en~]abled" (ldb hw:%%processor-control-spare-20-through-23 processor-bits) (ldb hw:%%processor-control-floating-point-trap-enable processor-bits) (ldb hw:%%processor-control-heap-underflow-trap-enable processor-bits) (ldb hw:%%processor-control-spare-17 processor-bits) (ldb hw:%%processor-control-stack-group-number processor-bits) (ldb hw:%%processor-control-misc processor-bits) (ldb hw:%%processor-control-data-bit processor-bits) (ldb hw:%%processor-control-halt-processor processor-bits) (ldb hw:%%processor-control-box-mode processor-bits) (ldb hw:%%processor-control-floating-point-status-ram-write-enable processor-bits) (ldb hw:%%processor-control-jump-indirect processor-bits) (ldb hw:%%processor-control-spare-3 processor-bits) (ldb hw:%%processor-control-icache-z-enable processor-bits) (ldb hw:%%processor-control-icache-b-enable processor-bits) (ldb hw:%%processor-control-icache-a-enable processor-bits))) (defun decode-memory-status-register (&optional (memstat (hw:read-memory-status))) (format t "~%Memory board has ~[double-~;single-~]sided ram sips.~ ~%Autoboot jumper ~[off~;on~]~ ~%Parity error ~[on~;off~]~ ~[~;~:;~:*~%*Undefined memory status bits 19-20 #x~x*~]~ ~%Transport trap ~[armed~;unarmed~]~ ~%Read fault ~[armed~;unarmed~]~ ~%VMA boxed bit ~[boxed~;unboxed~]~ ~%MD boxed bit ~[boxed~;unboxed~]~ ~%Last cycle type ~[write~*~ ~%GC trap ~[enabled~;disabled~]~;~ read~ ~%Transport type ~[write~;visible-evcp~;transport~;no-transport~]~*~]~ ~%MD written lately ~[yes~;no~]~ ~%Nubus bootstrap mode ~[RESET~;Short reset~:;*undefined*~]~ ~%ECO jumpers #b~4,'0b~ ~%Nubus slot #x~1x" (ldb hw:%%memory-status-16meg memstat) (ldb hw:%%memory-status-autoboot-jumper-bit memstat) (ldb hw:%%memory-status-parity-error memstat) (ldb hw:%%memory-status-spare-19-20 memstat) ;left floating! (ldb hw:%%memory-status-read-md-will-trans-trap memstat) (ldb hw:%%memory-status-read-md-will-fault memstat) (ldb hw:%%memory-status-vma-not-boxed-bit memstat) (ldb hw:%%memory-status-md-not-boxed-bit memstat) (ldb hw:%%memory-status-cycle-type memstat) (ldb hw:%%memory-status-transport-type memstat) (ldb hw:%%memory-status-gc-trap-enable memstat) (ldb hw:%%memory-status-md-written-lately memstat) (ldb hw:%%memory-status-nubus-bootstrap-mode (lognot memstat)) (ldb hw:%%memory-status-eco-jumper-number memstat) (ldb hw:%%memory-status-nubus-slot-id memstat))) (defun decode-processor-status-register (&optional (processor-bits (hw:read-processor-status))) ;< 31:19 @\ Undefined @cr ;< 18 @\ Processor ALU_BOXED bit @cr ;< 17 @\ Processor D_JUMP bit (active low) @cr ;< 16 @\ Processor JUMP bit (active low) @cr ;< 15:13 @\ Undefined @cr ;< 12:9 @\ Return Destination Immediate @cr ;< 8:4 @\ FPU Status Outputs @cr ;< 3:0 @\ ECO jumper number @cr (format t "~%ECO jumpers #b~4,'0b~ ~%Floating point status #x~x~ ~%Floating point ready ~[yes~;no~]~ ~%Global return frame #x~x~ ~%Jump bit ~s~ ~%Delayed jump bit ~s~ ~%Boxed bit ~s~ ~%Return code #x~x~%" (ldb hw:%%processor-status-eco-jumper processor-bits) (ldb hw:%%processor-status-floating-point-status processor-bits) (ldb hw:%%processor-status-floating-point-ready processor-bits) (ldb hw:%%processor-status-global-return-frame processor-bits) ;four bits ;; unused (byte 3. 13.) (ldb hw:%%processor-status-jump-bit processor-bits) (ldb hw:%%processor-status-delayed-jump-bit processor-bits) (ldb hw:%%processor-status-alu-boxed-bit processor-bits) (ldb hw:%%processor-status-return-code processor-bits) ;; unused (byte 12. 18.) )) (defun dump-gc-ram (&optional (stream t)) (format stream "~%GC RAM:~:[ k running ~; k halted ~]~%" (k-halted-p)) (dotimes (q 4096.) (show-gc-ram q stream)) ) (defun show-gc-ram (quantum stream) (let ((bits (read-gc-ram quantum))) (format stream "~&~4,48d Volatility ~d ~:[not oldspace~;oldspace~]" quantum (ldb hw:%%gc-ram-quantum-volatility bits) (= (ldb hw:%%gc-ram-quantum-oldspace bits) hw:$$oldspace)))) (defun dump-gc-ram-brief (&optional (stream t)) (format stream "~%GC RAM brief:~:[ k running ~; k halted ~]~%" (k-halted-p)) (let ((items-per-line 16.)) (dotimes (q (/ 4096. items-per-line)) (format stream "~%~X " q) (dotimes (c items-per-line) (show-gc-ram-brief (+ (* q items-per-line) c) stream)))) ) (defun show-gc-ram-brief (quantum stream) (let ((bits (read-gc-ram quantum))) (format stream "~:[N~;O~]V~d " (= (ldb hw:%%gc-ram-quantum-oldspace bits) hw:$$oldspace) (ldb hw:%%gc-ram-quantum-volatility bits)))) (defun find-physical-memory (&optional (max-chunk 32.)) ;returns a bit map where each 1 implies the existance of 1 mega-byte of memory. (if lam:*local-debugging* (setq max-chunk 16.)) ;better not get bus timeouts in local mode. (labels ((mark-physical-memory (chunk) (if (minusp chunk) (locate-physical-memory 0 0) (progn (k-mem-write (ash chunk 20.) chunk) (mark-physical-memory (1- chunk))))) (locate-physical-memory (chunk map) (cond ((= chunk max-chunk) map) ;check first before you reference! (t (let ((data (k-mem-read (ash chunk 20.)))) (cond ((and (numberp data) (= chunk data)) (locate-physical-memory (1+ chunk) (logior (ash 1. chunk) map))) (t (locate-physical-memory (1+ chunk) map)))))))) (mark-physical-memory (1- max-chunk)))) (defun why () (let ((msg nil)) (if (= 1. (k-read-spy-program-halt)) (setq msg (user#:get-illop-string (ldb (byte 24. 0.) (k-read-spy-mmfio)))) ;above, we want real USER, not K-USER, because get-illop-string is in ; compiler environment. (setq msg "The machine is running.")) (format t "~%~A" msg) msg)) ;;; Used to debug clock error. ;(defun bar () ; (loop ; (let ((foo (random 65000.))) ;; (labels ((map-n-instruction-clusters (n physical virtual) ;; (unless (zerop n) ;; (format t "~&Mapping ~X to ~X" virtual physical) ; (k-write-memory-map 1 4225.) ; (map::inject-map-status ; (dpb-multiple ; 1 hw:%%map-on-board-address ; hw:$$map-local hw:%%map-local-memory-bit ; 0 hw:%%map-volatility ; 0 hw:%%map-c-trap-bits ; 0) ; map::$$map-status-read-only) ;; (find-physical-memory) ; (write-boot-vector 4. (1+ foo)) ; (let ((result (read-boot-vector 4.))) ; (if (= result (1+ foo)) ; (format t "~%succeeded, wrote ~d" (1+ foo)) ; (format t "~%failed, wrote ~d read ~d" (1+ foo) result)))))) (defun dump-transporter-ram (&optional (stream t)) (format stream "~%Transporter RAM: -- vma-boxed, trans-mode(2), trans-type (2)~%") (format stream "--MD boxed(1), datatype(5)~%") (dotimes (md-boxed 2.) (dotimes (datatype 64.) (format stream "~%~B ~2,'0d ]" md-boxed datatype) (dotimes (vma-boxed 2.) (dotimes (transporter-mode 4.) (dotimes (transporter-type 4.) (let ((ram-data (k-read-transporter-ram vma-boxed md-boxed transporter-type transporter-mode datatype))) (format stream " ~X" ram-data)))))))) (defun dump-transporter-ram-via-generic (&optional (stream t)) (let ((items-per-line 32.)) (format stream "~2%Transporter RAM via generic: ~:[ k running ~; k halted ~]" (k-halted-p)) (dotimes (line (/ 4096. items-per-line)) (format stream "~&~3x" (* line items-per-line)) (dotimes (count items-per-line) (let ((data (read-transporter-ram (+ (* line items-per-line) count)))) (format stream " ~X" (logand data #o17))))))) (defun fast-address-test-transporter-via-generic () (lam:fast-address-test-kernal 'write-transporter-ram 'read-transporter-ram 0 4 12. "F.A.T. transporter via generic")) (defun k-decode-transporter-address (address) (values (ldb (byte 1 11.) address) ;unfortunately, these dont have symbolic definitions yet. (ldb (byte 1 10.) address) (ldb (byte 2 8) address) ;trans-type from instruction (ldb (byte 2 6) address) ;trans-mode semi-constant from memory-control-register. (ldb (byte 6 0) address))) (defun kbg-read-transporter-ram (address) (multiple-value-bind (vma-boxed md-boxed transporter-type transporter-mode datatype) (k-decode-transporter-address address) (k-read-transporter-ram vma-boxed md-boxed transporter-type transporter-mode datatype))) (defun kbg-write-transporter-ram (address data) (multiple-value-bind (vma-boxed md-boxed transporter-type transporter-mode datatype) (k-decode-transporter-address address) (k-write-transporter-ram vma-boxed md-boxed transporter-type transporter-mode datatype data))) ;;;;;;;; ;;; PCD ;;;;;;;; (defvar pcd-status-values #("invalid" "wired" "normal" "age-1" "age-2" "age-3" "flushable" "pre-paged")) (defvar pcd-status-values-brief #("I" "W" "N" "A1" "A2" "A3" "F" "P")) (defun decode-pcd (entry stream) (format stream "~5,'0x ~9a ~ ~:[ ~;not-~]modified ~ read-~:[write~;only ~] ~ ~@[~*write-mar~] ~ ~@[~*read-mar~]" (ldb pcd::%%pcd-virtual-cluster-number entry) (aref pcd-status-values (ldb pcd::%%pcd-status entry)) (ldb-test pcd::%%pcd-clean-bit entry) (ldb-test pcd::%%pcd-read-only-bit entry) (ldb-test pcd::%%pcd-write-mar-bit entry) (ldb-test pcd::%%pcd-read-mar-bit entry))) (defun show-entire-pcd (&optional (stream t)) (dotimes (index vinc:*physical-memory-max-clusters*) (show-pcd index stream))) (defun show-pcd (index stream) (format stream "~&~4,'0x " index) (decode-pcd (kbug-read-pcd index) t)) ;(pcd::read-pcd index) (defun show-entire-pcd-brief (&optional (stream t)) (let ((items-per-line 8)) (format stream "~2%PCD brief") (dotimes (line (/ vinc:*physical-memory-max-clusters* items-per-line)) (format stream "~&~3x " (* line items-per-line)) (dotimes (count items-per-line) (let* ((index (+ (* line items-per-line) count)) (pcd (kbug-read-pcd index)) ;(pcd::read-pcd index) (pcd-vcn (ldb pcd::%%pcd-virtual-cluster-number pcd)) (pcd-status (ldb pcd::%%pcd-status pcd)) (pcd-ro (ldb-test pcd::%%pcd-read-only-bit pcd))) (cond ((zerop pcd-status) (format stream ". ")) (t (format stream "~A~A~4,'0x " (aref pcd-status-values-brief pcd-status) (if pcd-ro "R" "W") pcd-vcn))) ))))) (defun kbug-read-pcd (index) ;"safe" with respect to processor! ;seems to wind up at physical #x48! (lam:k-mem-read-word-address (+ (dpb #x48 vinc:%%cluster-number 0) index))) ;boot:*physical-cluster-table-location (defun kbug-map-virtual-address-via-pcd (virt-adr) ;because the map is not directly available, we have to manually search the PCD, which goes the other way. ;to save time, we use a heuristic. We first search up from 0 till we get to a bunch of NULLS, ;then search down from #x800. (this probably should be related to phys-max-memory..) (let ((virt-cluster (ldb vinc::%%cluster-number virt-adr)) (offset (ldb vinc::%%offset-in-cluster virt-adr))) (prog top (index count-nulls pcd) (setq index 0 count-nulls 0) l (cond ((zerop (setq pcd (kbug-read-pcd index))) (cond ((> (incf count-nulls) 5.) (setq index #x800 count-nulls 0) (prog () l (cond ((zerop (setq pcd (kbug-read-pcd (setq index (1- index))))) (cond ((> (incf count-nulls) 5) (return-from top nil)))) ((= virt-cluster (ldb pcd::%%pcd-virtual-cluster-number pcd)) (return-from top (+ offset (ash index 10.))))) (go l))))) ((= virt-cluster (ldb pcd::%%pcd-virtual-cluster-number pcd)) (return-from top (+ offset (ash index 10.))))) (incf index) (go l)))) (defun kbug-generic-read-memory-safe (addr) ;read virtual memory without touching processor or assuming it is in kbug2. ;assumes pcd is set up. (let ((phys-addr (kbug-map-virtual-address-via-pcd addr))) (lam:k-mem-read-word-address phys-addr))) (defvar qm-status-values-brief #("E" "A" "x" "M")) ;MAPPED seems to mean it has been assigned space on swapping device. ; as it stands, only stuff in the cold load seems to wind up in MAPPED status, other stuff in ALLOCATED. (defun decode-quantum-map (entry stream) (format stream "~[EMPTY ~;ALLOCATED~;ERROR ~;MAPPED ~] ~4,48D ~2,48D ~4,48D" (quantum-map::quantum-status-bits entry) (quantum-map::region-origin entry) (quantum-map::quantum-device entry) (quantum-map::quantum-dqin entry))) (defun show-quantum-map (quantum stream) (let ((bits (quantum-map::read-quantum-map quantum))) (format stream "~&~4,'0x " quantum) (decode-quantum-map bits stream) )) (defun show-entire-quantum-map (&optional (stream t)) (dotimes (index 4096.) (show-quantum-map index stream))) (defun show-entire-quantum-map-brief (&optional (stream t)) (let ((items-per-line 16.)) (format stream "~2%Quantum map brief") (dotimes (line (/ 4096. items-per-line)) (format stream "~&~3x " (* line items-per-line)) (dotimes (count items-per-line) (let* ((index (+ (* line items-per-line) count)) (qm (quantum-map::read-quantum-map index)) (qm-status (quantum-map::quantum-status-bits qm)) (qm-ro (quantum-map::region-origin qm)) (qm-dev (quantum-map::quantum-device qm)) (qm-dq (quantum-map::quantum-dqin qm))) (declare (ignore qm-dev qm-dq)) (cond ((zerop qm-status) (format stream ". ")) (t (format stream "~A~4O " (aref qm-status-values-brief qm-status) qm-ro))) ))))) (defun decode-region-bits (bits stream) (format stream "~[static ~;flippable~] ~ ~[copyspace~;newspace ~] ~ ~[free ~;invalid ~;unboxed ~;cons ~;structure~;code ~:;**error**~] ~ read-~:[write~;only ~] ~ ~:[not~; ~] scavengable ~ Swapin quantum: ~d" (ldb region-bits::%%region-bits-flippable bits) (ldb region-bits::%%region-bits-new-space bits) (region-bits:region-space-type bits) (region-bits:region-read-only? bits) (region-bits:region-scavenge-enable? bits) (region-bits:region-swapin-quantum bits))) (defun show-region-bits (entry stream) (format stream "~%~4d " entry) (decode-region-bits (region-bits::read-region-bits entry) stream)) (defstruct (remote-object (:constructor make-remote-object (string type address)) (:predicate remote-object?) (:print-function print-remote-object)) string type address) (defun print-remote-object (object stream depth) (declare (ignore depth)) (si::printing-random-object (object stream) (format stream "~a ~d" (remote-object-string object) (remote-object-address object)))) (defun make-remote-maker (type string) `(DEFUN ,(intern (concatenate 'string "MAKE-" (string type))) (ADDRESS) (MAKE-REMOTE-OBJECT ,string (QUOTE ,type) ADDRESS))) (defun make-remote-predicate (type) `(DEFUN ,(intern (concatenate 'string (string type) "?")) (OBJECT) (AND (REMOTE-OBJECT? OBJECT) (EQ (QUOTE ,type) (REMOTE-OBJECT-TYPE OBJECT))))) (defmacro define-remote-object (type string) `(PROGN ,(make-remote-maker type string) ,(make-remote-predicate type))) (define-remote-object remote-nil "Remote NIL") (define-remote-object remote-cons-cell "Remote CONS") (define-remote-object remote-symbol "Remote SYMBOL") (define-remote-object remote-fixnum "Remote FIXNUM") (defun convert-remote-boxed-object (q) (let ((datatype (ldb vinc::%%data-type q)) (contents (logand q #x3FFFFFF))) ; pointer field (cond ((= datatype vinc:$$dtp-nil) (convert-nil contents)) ((= datatype vinc:$$dtp-symbol) (convert-symbol contents)) ((= datatype vinc:$$dtp-fixnum) (convert-fixnum contents)) ((= datatype vinc:$$dtp-cons) (convert-cons-cell contents)) (t (zl::ferror nil "Cannot convert ~s" q))))) (defun convert-nil (contents) (if (= contents 0) (make-remote-nil 0) (error nil "Bogus NIL found."))) (defun convert-fixnum (contents) (make-remote-fixnum contents)) (defun convert-symbol (contents) (if (= contents 5.) (make-remote-symbol contents) (error "Illegal symbol found."))) (defun convert-cons-cell (address) (make-remote-cons-cell address)) (defun check-remote-type (object type) (check-type object remote-object) (when (not (eq (remote-object-type object) type)) (error "Wrong type argument"))) (defun remote-car (object) (check-type object remote-object) (ecase (remote-object-type object) (remote-nil object) (remote-cons-cell (convert-remote-boxed-object (kbug-generic-read-memory (remote-object-address object)))))) (defun remote-cdr (object) (check-type object remote-object) (ecase (remote-object-type object) (remote-nil object) (remote-cons-cell (convert-remote-boxed-object (kbug-generic-read-memory (logior 1. (remote-object-address object))))))) (defun remote-print (object stream) (check-type object remote-object) (ecase (remote-object-type object) (remote-nil (print-remote-nil stream)) (remote-fixnum (print-remote-fixnum object stream)) (remote-cons-cell (print-remote-cons-cell object stream)))) (defun print-remote-nil (stream) (format stream "()")) (defun print-remote-cons-cell (object stream) (format stream "(") (block print-loop (do ((frob object (remote-cdr frob))) (()) (remote-print (remote-car frob) stream) (if (not (remote-cons-cell? (remote-cdr frob))) (if (remote-nil? (remote-cdr frob)) (progn (return-from print-loop nil)) (progn (format stream " . ") (remote-print (remote-cdr frob) stream) (return-from print-loop nil))) (format stream " ")))) (format stream ")")) (defun print-remote-fixnum (object stream) (format stream "~s" (let ((contents (logand #x03ffffff (remote-object-address object)))) (+ (* (- (expt 2. 24.)) (ldb vinc::%%fixnum-sign-bit contents)) (ldb (byte (1- (byte-position vinc::%%fixnum-sign-bit)) 0) contents))))) ;;;;;;;;;;;;;;;; ;;; Region data ;;;;;;;;;;;;;;;; (defun show-all-regions (&optional (stream t)) (format stream "~2%All regions:") (dotimes (region 4096.) ;max possible number of regions (= # quantums). (let* ((start (vinc:quantum->address region)) ;start is implicit in region number. (end (region-data::region-end region)) (bits (region-bits::read-region-bits region)) (region-space-type (region-bits:region-space-type bits))) (cond ((= region-space-type region-bits::$$region-space-free) (do ((first-region region) (r0 (1+ region) (1+ r0))) ((or (= r0 4096.) (not (= (region-bits:region-space-type (region-bits:read-region-bits r0)) region-bits::$$region-space-free))) (format stream "~%Regions ~D up to ~D free." first-region r0)) (incf region))) ((= region-space-type region-bits::$$region-space-invalid) (global:fsignal "Random invalid region ~D" region)) (t (show-region region stream) (do ((r0 (1+ region) (1+ r0)) (count 1 (1+ count))) ((>= count (vinc:quantum-number (- end start)))) (let* ((r0-bits (region-bits::read-region-bits r0)) (r0-space-type (region-bits:region-space-type r0-bits))) (cond ((not (= r0-space-type region-bits::$$region-space-invalid)) (global:fsignal "Region ~D not invalid, it should have been." r0)))) (incf region))) )))) (defun show-region-data (region stream) (let ((region-free-pointer (region-data::region-free-pointer region)) (region-end (region-data::region-end region))) (format stream "~%Origin #x~8,'0x (cluster #x~x)~ ~%GC pointer #x~8,'0x~ ~%Free pointer #x~8,'0x (cluster #x~x)~ ~%End #x~8,'0x (cluster #x~x)" (vinc:quantum->address region) (vinc:quantum->cluster region) (region-data::region-gc-pointer region) region-free-pointer (if (numberp region-free-pointer) (ldb vinc:%%cluster-number region-free-pointer)) region-end (if (numberp region-end) (ldb vinc:%%cluster-number region-end))))) (defun show-region (region stream) (show-region-bits region stream) (show-region-data region stream)) (defvar *latest-history* nil) (defun kbug-generic-read-inst-via-processor (pc) ;this uses physical machine to do virtual-to-physical translation. (setq pc (logior #x2000000 (ash pc 1))) (logior (ash (kbug-generic-read-memory (1+ pc)) 32.) (kbug-generic-read-memory pc))) (defun kbug-generic-read-inst-safe (pc) ;this uses PCD inverse mapping to do virtual-to-physical translation. (setq pc (logior #x2000000 (ash pc 1))) (let ((phys-adr (kbug-map-virtual-address-via-pcd pc))) (logior (ash (lam:k-mem-read-word-address (1+ phys-adr)) 32.) (lam:k-mem-read-word-address phys-adr)))) (defun kbug-generic-write-inst-via-processor (pc inst) ;caution! map in machine must be set for this to work. See above. (setq pc (logior #x2000000 (ash pc 1))) (let ((w0 (logand inst #xFFFFFFFF inst)) (w1 (ash inst -32.))) (kbug-generic-write-memory pc w0 t) (kbug-generic-write-memory (1+ pc) w1 t))) (defun show-history (&optional reset-history inhibit-symbolic-address print-bits) (let ((history (or (and (null reset-history) *latest-history*) (setq *latest-history* (lam:get-history)))) (current-pointer 0)) (do ((command (peek-char) (peek-char))) (nil) (let* ((addr (logand #xFFFFFF (aref history current-pointer))) (sym-addr (if (null inhibit-symbolic-address) (kbug-symbolic-address addr)))) (if sym-addr (format t "~&#x~x ~30a " addr sym-addr) (format t "~&~6,'0x " addr)) (let ((inst (kbug-generic-read-inst-via-processor addr))) (print-instruction inst) (if print-bits (lam:print-bits inst))) (case command ((#\c-l #\clear-screen) (read-char) (zl:send *terminal-io* :clear-window)) ((#\c-r) (read-char) (setq *latest-history* (lam:get-history) history *latest-history*)) ((#\line #\space #\c-n) (read-char) (incf current-pointer)) ((#\rubout #\c-p) (read-char) (decf current-pointer) (when (minusp current-pointer) (zl:send *terminal-io* :beep) (incf current-pointer))) ((#\quote) (incf current-pointer)) (otherwise (zl:catch-error-restart ((sys:abort) "Return to HISTORY EXAMINER.") (multiple-value-bind (sexp flag) (zl:with-input-editing (*terminal-io* '((:full-rubout :full-rubout) (:activation char= #\end) (:prompt prompt-for-eval))) (read)) (if (eq flag :full-rubout) () (progn (terpri) (prin1 (eval sexp)))))))))))) (defun show-history-to-stream (&optional reset-history (stream t) inhibit-symbolic-address print-bits) (let ((history (or (and (null reset-history) *latest-history*) (setq *latest-history* (lam:get-history))))) (do ((current-pointer 0 (1+ current-pointer)) (end (global:array-length history)) (data nil) (last-inst nil)) ((or (= current-pointer end) (null (setq data (aref history current-pointer))))) (let* ((addr (logand #xFFFFFF data)) (sym-addr (if (null inhibit-symbolic-address) (kbug-symbolic-address addr))) (inst (kbug-generic-read-inst-via-processor addr))) (cond ((or (null last-inst) (not (= inst last-inst))) (format stream "~&")) (t (format stream " .. "))) (if sym-addr (format stream "#x~x~30a " addr sym-addr) (format stream "~6,'0x " addr)) (cond ((or (null last-inst) (not (= inst last-inst))) (format stream " ") (print-instruction inst stream))) ;(if print-bits (lam:print-bits inst)) ;** fix this. (setq last-inst inst) )))) (defun prompt-for-eval (stream ignore) (format stream "~&Eval> ")) (defun show-entire-datatype-ram (&optional (stream t)) (let ((items-per-line 32.)) (format stream "~2%Datatype ram:") (dotimes (line (/ (ash 1 17.) items-per-line)) (format stream "~&~3x " (* line items-per-line)) (dotimes (count items-per-line) (let ((bit (lam:k-read-datatype-ram (+ (* line items-per-line) count)))) (format stream "~o " bit)))))) (defun show-entire-datatype-ram-run-length-encoded (&optional (stream t)) (let ((last-bit 0) (first-adr 0) (count 0)) (do ((adr 0 (1+ adr))) ((>= adr (ash 1 17.)) (format stream "~%#x~x bits starting at #x~x, ~x" count first-adr last-bit)) (let ((bit (lam:k-read-datatype-ram adr))) (cond ((= bit last-bit) (incf count)) (t (format stream "~%#x~x bits starting at #X~x, ~x" count first-adr last-bit) (setq last-bit bit first-adr adr count 1)))))))