summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/txr/stdlib/asm.tl300
1 files changed, 150 insertions, 150 deletions
diff --git a/share/txr/stdlib/asm.tl b/share/txr/stdlib/asm.tl
index 911f65de..29decc71 100644
--- a/share/txr/stdlib/asm.tl
+++ b/share/txr/stdlib/asm.tl
@@ -34,156 +34,156 @@
"register destination operand"
"register small destination operand"
"integer"
- "any object")))
-
- (:postinit (me)
- (set me.buf (get-buf-from-stream me.bstr)))
-
- (:method cur-pos (me)
- (seek-stream me.bstr 0 :from-current))
-
- (:method set-pos (me pos)
- (seek-stream me.bstr pos :from-start))
-
- (:method lookup-label (me sym oc)
- (condlet
- (((n [me.labdef sym])) n)
- (t (push (cons oc (trunc me.(cur-pos) 4)) [me.labref sym])
- 0)))
-
- (:method define-label (me sym)
- (let* ((pos me.(cur-pos))
- (ins (trunc pos 4)))
- (set [me.labdef sym] ins)
- (each ((entry (del [me.labref sym])))
- (tree-bind (oc . offs) entry
- me.(set-pos (* 4 offs))
- oc.(backpatch me (* 4 offs) ins)))
- me.(set-pos pos)
- ins))
-
- (:method read-buf (me bytes)
- (let ((buf (make-buf bytes)))
- (when (neql (fill-buf buf 0 me.bstr) bytes)
- (error "assembler: read past instruction block"))
- buf))
-
- (:method put-word (me word)
- (let* ((buf (make-buf 0)))
- (buf-put-u32 buf 0 word)
- (put-buf buf 0 me.bstr)))
-
- (:method put-insn (me code extension operand)
- (let ((word (logior (ash code 26) (ash extension 16) operand))
- (buf (make-buf 0)))
- (buf-put-u32 buf 0 word)
- (put-buf buf 0 me.bstr)))
-
- (:method put-pair (me op1 op2)
- (let ((word (logior (ash op1 16) op2))
- (buf (make-buf 0)))
- (buf-put-u32 buf 0 word)
- (put-buf buf 0 me.bstr)))
-
- (:method get-word (me)
- (let* ((buf me.(read-buf (sizeof uint32))))
- (buf-get-u32 buf 0)))
-
- (:method get-insn (me)
- (let* ((buf me.(read-buf (sizeof uint32)))
- (word (buf-get-u32 buf 0)))
- (list (ash word -26)
- (logtrunc (ash word -16) 10)
- (logtrunc word 16))))
-
- (:method get-pair (me)
- (let* ((buf me.(read-buf (sizeof uint32)))
- (word (buf-get-u32 buf 0)))
- (list (ash word -16) (logtrunc word 16))))
-
- (:method immediate-fits-type (me arg operand-type)
- (and (member (typeof arg)
- '(fixnum bignum chr))
- (<= (+ (width arg)
- [me.sign-bits (typeof arg)]
- 2)
- [me.imm-width operand-type])))
-
- (:method parse-args (me oc syntax pattern)
- (mapcar (lambda (type arg n)
- (let ((parg (caseql type
- ((si mi bi)
- (when me.(immediate-fits-type arg type)
- arg))
- (l (cond
- ((is-label arg) me.(lookup-label arg oc))
- ((integerp arg) arg)))
- (n (if (integerp arg) arg))
- (o arg)
- ((r rs d ds)
- (cond
- ((null arg) 0)
- ((consp arg)
- (parse-compound-operand arg))
- ((symbolp arg)
- (parse-operand (symbol-name arg)))))
- (t (error "assembler: invalid arg type spec")))))
- (unless (or parg (eq type 'o))
- oc.(synerr "argument ~a of ~s invalid; ~a expected"
- n syntax [me.operand-name type]))
- (when (and (member type '(d ds))
- (or (zerop parg) (<= 256 parg 511)))
- oc.(synerr "argument ~a of ~s cannot be destination"
- n syntax))
- (when (and (member type '(rs ds))
- (not (< parg 1024)))
- oc.(synerr "argument ~a of ~s isn't a small register"
- n syntax))
- parg))
- pattern (rest syntax) (range 1)))
-
- (:method asm-one (me syntax)
- (let ((oc (cond
- ((is-label syntax) [%oc-hash% 'label])
- ((consp syntax) [%oc-hash% (car syntax)]))))
- (unless oc
- (error "assembler: invalid instruction ~s" syntax))
- oc.(asm me syntax)))
-
- (:method asm (me insns)
- (each ((i insns))
- me.(asm-one i))
- (unless (empty me.labref)
- (error "assembler: dangling label references"))
- (whenlet ((n (cdr [find-max me.labdef : cdr])))
- (unless (< 0 n (len me.buf))
- (error "assembler: labels outside of code"))))
-
- (:method dis-one (me)
- (tree-bind (code extension operand) me.(get-insn)
- (let ((oc [%oc-hash% code]))
- oc.(dis me extension operand))))
-
- (:method dis (me)
- me.(set-pos 0)
- (build
- (while (< me.(cur-pos) (len me.buf))
- (add me.(dis-one)))))
-
- (:method dis-listing (me : (stream *stdout*))
- (let ((p 0)
- (l (len me.buf)))
- me.(set-pos p)
- (while (< p l)
- (let* ((dis me.(dis-one))
- (dis-txt (cat-str [mapcar tostring dis] " "))
- (q me.(cur-pos)))
- me.(set-pos p)
- (format t "~,5d: ~,08X ~a\n" (trunc p 4) me.(get-word) dis-txt)
- (while (< (inc p 4) q)
- (format t "~,5d: ~,08X\n" (trunc p 4) me.(get-word)))
- me.(set-pos q)
- (set p q))))))
+ "any object"))))
+
+(defmeth assembler :postinit (me)
+ (set me.buf (get-buf-from-stream me.bstr)))
+
+(defmeth assembler cur-pos (me)
+ (seek-stream me.bstr 0 :from-current))
+
+(defmeth assembler set-pos (me pos)
+ (seek-stream me.bstr pos :from-start))
+
+(defmeth assembler lookup-label (me sym oc)
+ (condlet
+ (((n [me.labdef sym])) n)
+ (t (push (cons oc (trunc me.(cur-pos) 4)) [me.labref sym])
+ 0)))
+
+(defmeth assembler define-label (me sym)
+ (let* ((pos me.(cur-pos))
+ (ins (trunc pos 4)))
+ (set [me.labdef sym] ins)
+ (each ((entry (del [me.labref sym])))
+ (tree-bind (oc . offs) entry
+ me.(set-pos (* 4 offs))
+ oc.(backpatch me (* 4 offs) ins)))
+ me.(set-pos pos)
+ ins))
+
+(defmeth assembler read-buf (me bytes)
+ (let ((buf (make-buf bytes)))
+ (when (neql (fill-buf buf 0 me.bstr) bytes)
+ (error "assembler: read past instruction block"))
+ buf))
+
+(defmeth assembler put-word (me word)
+ (let* ((buf (make-buf 0)))
+ (buf-put-u32 buf 0 word)
+ (put-buf buf 0 me.bstr)))
+
+(defmeth assembler put-insn (me code extension operand)
+ (let ((word (logior (ash code 26) (ash extension 16) operand))
+ (buf (make-buf 0)))
+ (buf-put-u32 buf 0 word)
+ (put-buf buf 0 me.bstr)))
+
+(defmeth assembler put-pair (me op1 op2)
+ (let ((word (logior (ash op1 16) op2))
+ (buf (make-buf 0)))
+ (buf-put-u32 buf 0 word)
+ (put-buf buf 0 me.bstr)))
+
+(defmeth assembler get-word (me)
+ (let* ((buf me.(read-buf (sizeof uint32))))
+ (buf-get-u32 buf 0)))
+
+(defmeth assembler get-insn (me)
+ (let* ((buf me.(read-buf (sizeof uint32)))
+ (word (buf-get-u32 buf 0)))
+ (list (ash word -26)
+ (logtrunc (ash word -16) 10)
+ (logtrunc word 16))))
+
+(defmeth assembler get-pair (me)
+ (let* ((buf me.(read-buf (sizeof uint32)))
+ (word (buf-get-u32 buf 0)))
+ (list (ash word -16) (logtrunc word 16))))
+
+(defmeth assembler immediate-fits-type (me arg operand-type)
+ (and (member (typeof arg)
+ '(fixnum bignum chr))
+ (<= (+ (width arg)
+ [me.sign-bits (typeof arg)]
+ 2)
+ [me.imm-width operand-type])))
+
+(defmeth assembler parse-args (me oc syntax pattern)
+ (mapcar (lambda (type arg n)
+ (let ((parg (caseql type
+ ((si mi bi)
+ (when me.(immediate-fits-type arg type)
+ arg))
+ (l (cond
+ ((is-label arg) me.(lookup-label arg oc))
+ ((integerp arg) arg)))
+ (n (if (integerp arg) arg))
+ (o arg)
+ ((r rs d ds)
+ (cond
+ ((null arg) 0)
+ ((consp arg)
+ (parse-compound-operand arg))
+ ((symbolp arg)
+ (parse-operand (symbol-name arg)))))
+ (t (error "assembler: invalid arg type spec")))))
+ (unless (or parg (eq type 'o))
+ oc.(synerr "argument ~a of ~s invalid; ~a expected"
+ n syntax [me.operand-name type]))
+ (when (and (member type '(d ds))
+ (or (zerop parg) (<= 256 parg 511)))
+ oc.(synerr "argument ~a of ~s cannot be destination"
+ n syntax))
+ (when (and (member type '(rs ds))
+ (not (< parg 1024)))
+ oc.(synerr "argument ~a of ~s isn't a small register"
+ n syntax))
+ parg))
+ pattern (rest syntax) (range 1)))
+
+(defmeth assembler asm-one (me syntax)
+ (let ((oc (cond
+ ((is-label syntax) [%oc-hash% 'label])
+ ((consp syntax) [%oc-hash% (car syntax)]))))
+ (unless oc
+ (error "assembler: invalid instruction ~s" syntax))
+ oc.(asm me syntax)))
+
+(defmeth assembler asm (me insns)
+ (each ((i insns))
+ me.(asm-one i))
+ (unless (empty me.labref)
+ (error "assembler: dangling label references"))
+ (whenlet ((n (cdr [find-max me.labdef : cdr])))
+ (unless (< 0 n (len me.buf))
+ (error "assembler: labels outside of code"))))
+
+(defmeth assembler dis-one (me)
+ (tree-bind (code extension operand) me.(get-insn)
+ (let ((oc [%oc-hash% code]))
+ oc.(dis me extension operand))))
+
+(defmeth assembler dis (me)
+ me.(set-pos 0)
+ (build
+ (while (< me.(cur-pos) (len me.buf))
+ (add me.(dis-one)))))
+
+(defmeth assembler dis-listing (me : (stream *stdout*))
+ (let ((p 0)
+ (l (len me.buf)))
+ me.(set-pos p)
+ (while (< p l)
+ (let* ((dis me.(dis-one))
+ (dis-txt (cat-str [mapcar tostring dis] " "))
+ (q me.(cur-pos)))
+ me.(set-pos p)
+ (format t "~,5d: ~,08X ~a\n" (trunc p 4) me.(get-word) dis-txt)
+ (while (< (inc p 4) q)
+ (format t "~,5d: ~,08X\n" (trunc p 4) me.(get-word)))
+ me.(set-pos q)
+ (set p q)))))
(defvarl %oc-list-builder% (new list-builder))