summaryrefslogtreecommitdiffstats
path: root/vm.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-03-26 19:53:20 -0700
committerKaz Kylheku <kaz@kylheku.com>2018-03-26 19:53:20 -0700
commitfd906cb17c6b51bcc61d6aea134d3857a294b627 (patch)
treec0f64658c23371b5bf66570c24985241e901cf45 /vm.c
parent5f107b22b84b603d6bf4a554a4be729883fd6d7c (diff)
downloadtxr-fd906cb17c6b51bcc61d6aea134d3857a294b627.tar.gz
txr-fd906cb17c6b51bcc61d6aea134d3857a294b627.tar.bz2
txr-fd906cb17c6b51bcc61d6aea134d3857a294b627.zip
vm/asm: new swtch instruction.
* share/txr/stdlib/asm.tl (backpatch-low16, backpatch-high16): New struct types. (%backpatch-low16%, %backpatch-high16%): New global variables. (swtch): New opcode. (op-swtch): New opcode class. * vm.c (vm_swtch): New static function. (vm_execute): Handle SWTCH opcode via vm_swtch. * vmop.h: Regenerated.
Diffstat (limited to 'vm.c')
-rw-r--r--vm.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/vm.c b/vm.c
index 2e42d211..cc1df792 100644
--- a/vm.c
+++ b/vm.c
@@ -45,6 +45,7 @@
#include "args.h"
#include "itypes.h"
#include "buf.h"
+#include "arith.h"
#include "vmop.h"
#include "vm.h"
@@ -585,6 +586,23 @@ static void vm_ifql(struct vm *vm, vm_word_t insn)
vm->ip = vm_insn_bigop(ip);
}
+static void vm_swtch(struct vm *vm, vm_word_t insn)
+{
+ unsigned tblsz = vm_insn_extra(insn);
+ ucnum idx = c_unum(vm_get(vm->dspl, vm_insn_operand(insn)));
+
+ if (idx < tblsz) {
+ vm_word_t tgt = vm->code[vm->ip + idx / 2];
+ unsigned shift = (idx % 2) * 16;
+ vm->ip = (tgt >> shift) & 0xFFFFU;
+ } else {
+ struct vm_desc *vd = vm->vd;
+ eval_error(vd->bytecode,
+ lit("switch index ~s is out of range"),
+ num(idx), nao);
+ }
+}
+
static void vm_uwprot(struct vm *vm, vm_word_t insn)
{
int saved_lev = vm->lev;
@@ -846,6 +864,9 @@ static val vm_execute(struct vm *vm)
case IFQL:
vm_ifql(vm, insn);
break;
+ case SWTCH:
+ vm_swtch(vm, insn);
+ break;
case UWPROT:
vm_uwprot(vm, insn);
break;