summaryrefslogtreecommitdiffstats
path: root/share
diff options
context:
space:
mode:
Diffstat (limited to 'share')
-rw-r--r--share/txr/stdlib/asm.tl40
1 files changed, 40 insertions, 0 deletions
diff --git a/share/txr/stdlib/asm.tl b/share/txr/stdlib/asm.tl
index 88c801e2..bba50b39 100644
--- a/share/txr/stdlib/asm.tl
+++ b/share/txr/stdlib/asm.tl
@@ -279,6 +279,21 @@
(2 (chr-int val))
(t (error "assembler: bad immediate operand: ~s" bits)))))
+(defstruct backpatch-low16 nil
+ (:method backpatch (me asm at offs)
+ (tree-bind (hi lo) asm.(get-pair)
+ asm.(set-pos at)
+ asm.(put-pair hi offs))))
+
+(defstruct backpatch-high16 nil
+ (:method backpatch (me asm at offs)
+ (tree-bind (hi lo) asm.(get-pair)
+ asm.(set-pos at)
+ asm.(put-pair offs lo))))
+
+(defvarl %backpatch-low16% (new backpatch-low16))
+(defvarl %backpatch-high16% (new backpatch-high16))
+
(defmacro defopcode (class symbol code . slot-defs)
^(symacrolet ((auto (pinc %oc-code%)))
(defstruct ,class oc-base
@@ -512,6 +527,31 @@
(defopcode-derived op-ifql ifql auto op-ifq)
+(defopcode op-swtch swtch auto
+ (:method asm (me asm syntax)
+ me.(chk-arg-count-min 1 syntax)
+ (let* ((args asm.(parse-args me syntax '(r)))
+ (lbls (cddr syntax))
+ (tblsz (len lbls)))
+ asm.(put-insn me.code tblsz (car args))
+ (while lbls
+ (let ((x asm.(lookup-label (pop lbls) %backpatch-low16%))
+ (y (if lbls
+ asm.(lookup-label (pop lbls) %backpatch-high16%)
+ 0)))
+ asm.(put-pair y x)))))
+
+ (:method dis (me asm tblsz switch-val)
+ (build
+ (add me.symbol)
+ (add (operand-to-sym switch-val))
+ (while (> tblsz 0)
+ (dec tblsz 2)
+ (tree-bind (y x) asm.(get-pair)
+ (add x)
+ (unless (minusp tblsz)
+ (add y)))))))
+
(defopcode-derived op-uwprot uwprot auto op-jmp)
(defopcode op-block block auto