summaryrefslogtreecommitdiffstats
path: root/share
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-04-17 21:48:32 -0700
committerKaz Kylheku <kaz@kylheku.com>2018-04-17 21:48:32 -0700
commitbdb2fac227cda2f1a4e28818824d3e060c9b3100 (patch)
tree1741d8d2c8f950a541cf350a4b43014c7062e802 /share
parentee0993a71dbf89dbd7322863b8e4750b1b701392 (diff)
downloadtxr-bdb2fac227cda2f1a4e28818824d3e060c9b3100.tar.gz
txr-bdb2fac227cda2f1a4e28818824d3e060c9b3100.tar.bz2
txr-bdb2fac227cda2f1a4e28818824d3e060c9b3100.zip
asm: deal with too large d regs in getv/setv.
Only registers d00 through d3f can now fit into a small operand, but the setv, getv and derived instructions only take a small operand as the name. If a function accesses more than 64 dynamic variables, it can't be compiled and assembled. (Fewer, if it uses symbols for anything else.) The approach we take here is to relax the name operand in getv and setv: it can be a large or small operand. When assembling these instructions, we check the size: if the operand is large, we emit an extra mov instruction to move the operand to a register that is itself a small operand. Then we use that register as the operand. To do this, we need a dedicated assembler temporary register, like the "at" register on MIPS. We reserve t1 as the assembler temporary; the compiler must be adjusted not to use it. Future task: the following optimization is possible: the machine code can be scanned for uses of d registers. The d registers can be globally renumbered/reassigned (along with a rearrangement of the order of the datavec) such that the getv and setv instructions can use the lowest-numbered d registers, minimizing or eliminating these extra mov instructions. * share/txr/stdlib/asm.tl (operand-to-exp): New function. (op-getv, op-setv): Change name operand from rs to r, allowing a large operand. If the operand is large, emit the extra mov instruction into the temp register, and designate that register as the name for the getv/setv. * share/txr/stdlib/compiler.tl (compiler): Initialize t register counter to 2 rather than 1 so we don't allocate the assembler temporary t001. (compiler check-treg-leak): The balance check must cover a deficit of two registers now: t000 and t001.
Diffstat (limited to 'share')
-rw-r--r--share/txr/stdlib/asm.tl19
-rw-r--r--share/txr/stdlib/compiler.tl4
2 files changed, 19 insertions, 4 deletions
diff --git a/share/txr/stdlib/asm.tl b/share/txr/stdlib/asm.tl
index eafc322d..ed7ae1a0 100644
--- a/share/txr/stdlib/asm.tl
+++ b/share/txr/stdlib/asm.tl
@@ -285,6 +285,15 @@
(1 (intern (fmt "d~,02X" ix)))
(t (intern (fmt "v~,02X~,03X" (ssucc lv) ix))))))
+(defun operand-to-exp (val)
+ (with-lev-idx (lv ix) val
+ (caseql lv
+ (0 (if (zerop ix)
+ nil
+ ^(t ,ix)))
+ (1 ^(d ,ix))
+ (t ^(v ,lv ,ix)))))
+
(defun bits-to-obj (bits width)
(let ((tag (logtrunc bits 2))
(val (ash bits -2)))
@@ -676,7 +685,10 @@
(defopcode op-getv getv auto
(:method asm (me asm syntax)
me.(chk-arg-count 2 syntax)
- (tree-bind (reg name) asm.(parse-args me syntax '(d rs))
+ (tree-bind (reg name) asm.(parse-args me syntax '(d r))
+ (unless (small-op-p name)
+ asm.(asm-one ^(mov (t 1) ,(operand-to-exp name)))
+ (set name 1))
asm.(put-insn me.code (enc-small-op name) reg)))
(:method dis (me asm name reg)
^(,me.symbol ,(operand-to-sym reg) ,(small-op-to-sym name))))
@@ -694,7 +706,10 @@
(defopcode op-setv setv auto
(:method asm (me asm syntax)
me.(chk-arg-count 2 syntax)
- (tree-bind (reg name) asm.(parse-args me syntax '(r rs))
+ (tree-bind (reg name) asm.(parse-args me syntax '(r r))
+ (unless (small-op-p name)
+ asm.(asm-one ^(mov (t 1) ,(operand-to-exp name)))
+ (set name 1))
asm.(put-insn me.code (enc-small-op name) reg)))
(:method dis (me asm name reg)
^(,me.symbol ,(operand-to-sym reg) ,(small-op-to-sym name))))
diff --git a/share/txr/stdlib/compiler.tl b/share/txr/stdlib/compiler.tl
index 0571e10c..f649b8e9 100644
--- a/share/txr/stdlib/compiler.tl
+++ b/share/txr/stdlib/compiler.tl
@@ -107,7 +107,7 @@
(compile-only
(defstruct compiler nil
- (treg-cntr 1)
+ (treg-cntr 2)
(dreg-cntr 0)
(fidx-cntr 0)
(nlev 2)
@@ -215,7 +215,7 @@
me.(free-treg treg)))
(defmeth compiler check-treg-leak (me)
- (let ((balance (- (pred me.treg-cntr) (len me.tregs))))
+ (let ((balance (- (ppred me.treg-cntr) (len me.tregs))))
(unless (zerop balance)
(error "t-register leak in compiler: ~s outstanding" balance))))