diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2018-03-26 19:53:20 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2018-03-26 19:53:20 -0700 |
commit | fd906cb17c6b51bcc61d6aea134d3857a294b627 (patch) | |
tree | c0f64658c23371b5bf66570c24985241e901cf45 /vm.c | |
parent | 5f107b22b84b603d6bf4a554a4be729883fd6d7c (diff) | |
download | txr-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.c | 21 |
1 files changed, 21 insertions, 0 deletions
@@ -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; |