;;; -*- Mode:LISP; Package:(NC LISP); Base:10; Readtable:CL -*- ;;;; Compiled Function Objects and Linker (export '(DEFAFUN NDISASSEMBLE PRINS LINK)) (zl:defsubst nsymbol-function (symbol) (get symbol 'ncompiled-function)) (defun create-ncompiled-function (name code local-refs refs immediates entry-points) (let ((cfun (setf (nsymbol-function name) (make-ncompiled-function :name name)))) (setf (ncompiled-function-starting-address cfun) nil) (setf (ncompiled-function-code cfun) (concatenate 'vector code)) (setf (ncompiled-function-length cfun) (length code)) (setf (ncompiled-function-local-refs cfun) local-refs) (setf (ncompiled-function-refs cfun) refs) (setf (ncompiled-function-immediates cfun) immediates) (setf (ncompiled-function-entry-points cfun) entry-points) cfun)) (defmacro defafun (name arglist &body instructions) "Define an assembly function, takes a body of assembly code. installs a compiled-function structure on the symbol name" `(setf (nsymbol-function ',name) (assemble-instruction-list ',name '(,name . ,instructions) '((,(length arglist) . ,name))))) (defun cc (defun) (let ((f (c defun))) (setf (nsymbol-function (ncompiled-function-name f)) f) f)) (defun get-ncompiled-function (fcn) (cond ((ncompiled-function-p fcn) fcn) ((symbolp fcn) (nsymbol-function fcn)) (t (cerror "foo" "unknown function thing ~s" fcn)))) (defun ndisassemble (fcn) "Print disassembled code of FCN" (let ((f (get-ncompiled-function fcn))) (let ((code (ncompiled-function-code f))) (case code (:in-cold-load (cold::cold-disassemble f)) (:in-memory (kbug::disassemble-fcn-from-memory f)) (t (if (typep code 'sequence) (pr-dis (ncompiled-function-code f)) (error "don't know where this code is: ~a" code)))))) fcn) (defun prins (fcn) "Print instructions of FCN in hex" (let ((f (get-ncompiled-function fcn))) (format t "~&Start: ~x" (ncompiled-function-starting-address f)) (map nil #'(lambda (i) (format t "~&~16,'0x" i)) (ncompiled-function-code f))) fcn) (defun link (function starting-address &optional (do-callees t)) "Relocate and resolve references of FUNCTION given STARTING-ADDRESS" (let* ((cfun (get-ncompiled-function function)) (code (ncompiled-function-code cfun))) ;; do this first to get recursive calls (setf (ncompiled-function-starting-address cfun) starting-address) ;; Link local ref addresses (dolist (local-ref (ncompiled-function-local-refs cfun)) (let ((iaddr (car local-ref))) (setf (aref code iaddr) (dpb (ldb (byte (byte-size hw:%%i-branch-address) 0) (+ starting-address (cdr local-ref))) hw:%%i-branch-address (aref code iaddr))))) ;; Link Refs (dolist (ref (ncompiled-function-refs cfun)) (let ((reffun (get-ncompiled-function (if (symbolp (cdr ref)) (cdr ref) (second ref)))) ; (nargs (third ref)) ) (if reffun (let ((refstart (ncompiled-function-starting-address reffun))) (if refstart (setf (aref code (car ref)) (logior (logand #xFFFFFFFFFF000000 (aref code (car ref))) refstart)) (format t "~&~S is not yet linked" (cdr ref))) (pushnew (cons cfun (car ref)) (ncompiled-function-callees reffun) :test #'equal)) (format t "~&~S is undefined" (cdr ref))))) ;; Do callees ;; do entry points too (when do-callees (dolist (callee (nc::ncompiled-function-callees cfun)) (let ((callee-code (nc::ncompiled-function-code (car callee))) (addr (+ (nc::ncompiled-function-starting-address (car callee)) (cdr callee)))) (case callee-code (:in-memory (kbug::write-inst addr (logior (logand #xFFFFFFFFFF000000 (kbug::read-inst addr)) starting-address))))))) ))