summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/txr/stdlib/asm.tl17
-rw-r--r--vm.c28
-rw-r--r--vmop.h36
3 files changed, 64 insertions, 17 deletions
diff --git a/share/txr/stdlib/asm.tl b/share/txr/stdlib/asm.tl
index a82ce156..2fc8b6fd 100644
--- a/share/txr/stdlib/asm.tl
+++ b/share/txr/stdlib/asm.tl
@@ -438,6 +438,23 @@
(reg (cadr asm.(get-pair))))
^(,me.symbol ,(operand-to-sym reg) ,dst))))
+(defopcode op-ifq ifq auto
+ (:method asm (me asm syntax)
+ me.(chk-arg-count 3 syntax)
+ (tree-bind (lreg rreg dst) asm.(parse-args me syntax '(r r l))
+ asm.(put-insn me.code (ash dst -16) (logtrunc dst 16))
+ asm.(put-pair lreg rreg)))
+
+ (:method backpatch (me asm at dst)
+ asm.(put-insn me.code (ash dst -16) (logtrunc dst 16)))
+
+ (:method dis (me asm high16 low16)
+ (let ((dst (logior (ash high16 16) low16)))
+ (tree-bind (lreg rreg) asm.(get-pair)
+ ^(,me.symbol ,(operand-to-sym lreg) ,(operand-to-sym rreg) ,dst)))))
+
+(defopcode-derived op-ifql ifql auto op-ifq)
+
(defopcode-derived op-uwprot uwprot auto op-jmp)
(defopcode op-block block auto
diff --git a/vm.c b/vm.c
index 4edf4a85..450165f0 100644
--- a/vm.c
+++ b/vm.c
@@ -441,6 +441,28 @@ static void vm_if(struct vm *vm, vm_word_t insn)
vm->ip = vm_insn_bigop(ip);
}
+static void vm_ifq(struct vm *vm, vm_word_t insn)
+{
+ unsigned ip = vm_insn_bigop(insn);
+ vm_word_t arg = vm->code[vm->ip++];
+ val a = vm_get(vm->dspl, vm_arg_operand_lo(arg));
+ val b = vm_get(vm->dspl, vm_arg_operand_hi(arg));
+
+ if (a != b)
+ vm->ip = vm_insn_bigop(ip);
+}
+
+static void vm_ifql(struct vm *vm, vm_word_t insn)
+{
+ unsigned ip = vm_insn_bigop(insn);
+ vm_word_t arg = vm->code[vm->ip++];
+ val a = vm_get(vm->dspl, vm_arg_operand_lo(arg));
+ val b = vm_get(vm->dspl, vm_arg_operand_hi(arg));
+
+ if (!eql(a, b))
+ vm->ip = vm_insn_bigop(ip);
+}
+
static void vm_uwprot(struct vm *vm, vm_word_t insn)
{
int saved_lev = vm->lev;
@@ -667,6 +689,12 @@ static val vm_execute(struct vm *vm)
case IF:
vm_if(vm, insn);
break;
+ case IFQ:
+ vm_ifq(vm, insn);
+ break;
+ case IFQL:
+ vm_ifql(vm, insn);
+ break;
case UWPROT:
vm_uwprot(vm, insn);
break;
diff --git a/vmop.h b/vmop.h
index 6783b25d..db907c32 100644
--- a/vmop.h
+++ b/vmop.h
@@ -42,21 +42,23 @@ typedef enum vm_op {
MOVRBI = 13,
JMP = 14,
IF = 15,
- UWPROT = 16,
- BLOCK = 17,
- RETSR = 18,
- RETRS = 19,
- RETRR = 20,
- CATCH = 21,
- HANDLE = 22,
- GETV = 23,
- GETF = 24,
- GETL1 = 25,
- GETVB = 26,
- GETFB = 27,
- GETL1B = 28,
- SETV = 29,
- SETL1 = 30,
- BINDV = 31,
- CLOSE = 32,
+ IFQ = 16,
+ IFQL = 17,
+ UWPROT = 18,
+ BLOCK = 19,
+ RETSR = 20,
+ RETRS = 21,
+ RETRR = 22,
+ CATCH = 23,
+ HANDLE = 24,
+ GETV = 25,
+ GETF = 26,
+ GETL1 = 27,
+ GETVB = 28,
+ GETFB = 29,
+ GETL1B = 30,
+ SETV = 31,
+ SETL1 = 32,
+ BINDV = 33,
+ CLOSE = 34,
} vm_op_t;