diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2018-04-17 21:48:32 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2018-04-17 21:48:32 -0700 |
commit | bdb2fac227cda2f1a4e28818824d3e060c9b3100 (patch) | |
tree | 1741d8d2c8f950a541cf350a4b43014c7062e802 /share | |
parent | ee0993a71dbf89dbd7322863b8e4750b1b701392 (diff) | |
download | txr-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.tl | 19 | ||||
-rw-r--r-- | share/txr/stdlib/compiler.tl | 4 |
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)))) |