From fd906cb17c6b51bcc61d6aea134d3857a294b627 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Mon, 26 Mar 2018 19:53:20 -0700 Subject: 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. --- vm.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'vm.c') 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; -- cgit v1.2.3