From 4e8c983e12b8235cfd4fa3594c8064d51fcb67c6 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Mon, 16 Apr 2018 21:42:45 -0700 Subject: vm/asm/compiler: parametrize display parameters. In this patch we replace some hard-coded constants related to the dimensions of the frame display, which will make it easier to experiment with changes to the configuration: to set up wider frames at the cost of max display depth. The encoding of small operands needs to be abstracted because games can be played here. A 10 bit small operand can be configured in various ways: for instance a 5:5 split would mean that the first 32 entries in the first 32 levels can be small operands. That's independent of the display configuration. * share/txr/stdlib/asm.tl: Load vm-param to get some fundamental constants. (small-op-p): New macro. (assembler parse-args, parse-compound-operand, parse-operand, operand-to-sym): Use constants. (enc-small-oip, small-op-to-sym): New macros. (op-frame asm): Use constants. Small range check problem fixed here: a frame level of 1 mustn't be allowed. (op-movrs, op-movsr, op-mov-pseudo, op-movsmi, op-movrbi, op-movi-pseudo, op-retsr, op-retrs, op-retrr, op-ret-pseudo, op-getv, op-setv): Deal with small operand via functions. (op-close): Use constants. Off-by-one problem: frame size of 256 must be allowed. * share/txr/stdlib/compiler.tl: Load vm-param to get constants. (compiler get-dreg, compiler get-funvec): Use constant for max frame size. (compiler new-env): Check for maximum levels being exceeded. (compiler comp-atom): Use constant for maximum immediate integer operand width. * share/txr/stdlib/vm-param.tl: New file. * vm.c (vm_insn_extra_dec_small): New macro. (VM_LEV_BITS, VM_LEV_MASK, VM_SM_LEV_BITS, VM_SM_LEV_MASK): New preprocessor constants. (vm_lev, vm_idx, vm_sm_lev, vm_sm_idx): New macros. (vm_get, vm_set): Use macros instead of literals. (vm_sm_get, vm_sm_set): New inline functions. (vm_movrs, vm_movsr, vm_movsmi, vm_retsr, vm_retrs, vm_abscsr, vm_get_binding, vm_bindv): Use vm_sm_get or vm_sm_set to access the display using the small operand. (vm_close): Use preprocessor symbols instead of hard-coded literals. --- vm.c | 58 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 13 deletions(-) (limited to 'vm.c') diff --git a/vm.c b/vm.c index 26e9f692..d06c2ee2 100644 --- a/vm.c +++ b/vm.c @@ -293,18 +293,49 @@ static void vm_reset(struct vm *vm, struct vm_desc *vd, #define vm_insn_bigop(insn) (((insn) & 0x3FFFFFFU)) #define vm_arg_operand_lo(arg) ((arg) & 0xFFFFU) #define vm_arg_operand_hi(arg) ((arg) >> 16) +#define VM_LEV_BITS 8 +#define VM_LEV_MASK 0xFF +#define VM_SM_LEV_BITS 8 +#define VM_SM_LEV_MASK 0xFF +#define vm_lev(arg) ((arg) >> VM_LEV_BITS) +#define vm_idx(arg) ((arg) & VM_LEV_MASK) +#define vm_sm_lev(arg) ((arg) >> VM_SM_LEV_BITS) +#define vm_sm_idx(arg) ((arg) & VM_SM_LEV_MASK) static val vm_execute(struct vm *vm); INLINE val vm_get(struct vm_env *dspl, unsigned ref) { - return dspl[ref >> 8].mem[ref & 0xFF]; + return dspl[vm_lev(ref)].mem[vm_idx(ref)]; +} + +INLINE val vm_sm_get(struct vm_env *dspl, unsigned ref) +{ + return dspl[vm_sm_lev(ref)].mem[vm_sm_idx(ref)]; } INLINE void vm_set(struct vm_env *dspl, unsigned ref, val newval) { - unsigned d = ref >> 8; - unsigned i = ref & 0xFF; + unsigned d = vm_lev(ref); + unsigned i = vm_idx(ref); + struct vm_env *env = &dspl[d]; + + if (d == 1) + uw_throwf(error_s, lit("modification of VM static data"), nao); + + if (ref == 0) + uw_throwf(error_s, lit("modification of t00/nil"), nao); + + env->mem[i] = newval; + + if (is_ptr(env->vec)) + mut(env->vec); +} + +INLINE void vm_sm_set(struct vm_env *dspl, unsigned ref, val newval) +{ + unsigned d = vm_sm_lev(ref); + unsigned i = vm_sm_idx(ref); struct vm_env *env = &dspl[d]; if (d == 1) @@ -319,6 +350,7 @@ INLINE void vm_set(struct vm_env *dspl, unsigned ref, val newval) mut(env->vec); } + static void vm_do_frame(struct vm *vm, vm_word_t insn, int capturable) { int lev = vm_insn_extra(insn); @@ -511,14 +543,14 @@ static void vm_gapply(struct vm *vm, vm_word_t insn) static void vm_movrs(struct vm *vm, vm_word_t insn) { - val datum = vm_get(vm->dspl, vm_insn_extra(insn)); + val datum = vm_sm_get(vm->dspl, vm_insn_extra(insn)); vm_set(vm->dspl, vm_insn_operand(insn), datum); } static void vm_movsr(struct vm *vm, vm_word_t insn) { val datum = vm_get(vm->dspl, vm_insn_operand(insn)); - vm_set(vm->dspl, vm_insn_extra(insn), datum); + vm_sm_set(vm->dspl, vm_insn_extra(insn), datum); } static void vm_movrr(struct vm *vm, vm_word_t insn) @@ -549,7 +581,7 @@ static void vm_movsmi(struct vm *vm, vm_word_t insn) if ((imm & TAG_MASK) == NUM && (imm & 0x8000)) imm |= negmask; - vm_set(vm->dspl, dst, coerce(val, imm)); + vm_sm_set(vm->dspl, dst, coerce(val, imm)); } static void vm_movrbi(struct vm *vm, vm_word_t insn) @@ -669,7 +701,7 @@ static void vm_no_block_err(struct vm *vm, val name) static void vm_retsr(struct vm *vm, vm_word_t insn) { val res = vm_get(vm->dspl, vm_insn_operand(insn)); - val tag = vm_get(vm->dspl, vm_insn_extra(insn)); + val tag = vm_sm_get(vm->dspl, vm_insn_extra(insn)); uw_block_return(tag, res); vm_no_block_err(vm, tag); @@ -677,7 +709,7 @@ static void vm_retsr(struct vm *vm, vm_word_t insn) static void vm_retrs(struct vm *vm, vm_word_t insn) { - val res = vm_get(vm->dspl, vm_insn_extra(insn)); + val res = vm_sm_get(vm->dspl, vm_insn_extra(insn)); val tag = vm_get(vm->dspl, vm_insn_operand(insn)); uw_block_return(tag, res); @@ -697,7 +729,7 @@ static void vm_retrr(struct vm *vm, vm_word_t insn) static void vm_abscsr(struct vm *vm, vm_word_t insn) { val res = vm_get(vm->dspl, vm_insn_operand(insn)); - val tag = vm_get(vm->dspl, vm_insn_extra(insn)); + val tag = vm_sm_get(vm->dspl, vm_insn_extra(insn)); uw_block_abscond(tag, res); vm_no_block_err(vm, tag); @@ -750,7 +782,7 @@ static val vm_get_binding(struct vm *vm, vm_word_t insn, val (*lookup_fn)(val env, val sym), val kind_str) { - val sym = vm_get(vm->dspl, vm_insn_extra(insn)); + val sym = vm_sm_get(vm->dspl, vm_insn_extra(insn)); val binding = lookup_fn(nil, sym); if (nilp(binding)) @@ -788,7 +820,7 @@ static void vm_setsym(struct vm *vm, vm_word_t insn, static void vm_bindv(struct vm *vm, vm_word_t insn) { - val sym = vm_get(vm->dspl, vm_insn_extra(insn)); + val sym = vm_sm_get(vm->dspl, vm_insn_extra(insn)); int src = vm_insn_operand(insn); if (nilp(dyn_env)) @@ -804,8 +836,8 @@ static void vm_close(struct vm *vm, vm_word_t insn) vm_word_t arg1 = vm->code[vm->ip++]; vm_word_t arg2 = vm->code[vm->ip++]; unsigned vari_fr = vm_arg_operand_hi(arg1); - int variadic = vari_fr & 0x100; - int frsz = vari_fr & 0xFF; + int variadic = vari_fr & (1 << VM_LEV_BITS); + int frsz = vari_fr & VM_LEV_MASK; unsigned reg = vm_arg_operand_lo(arg1); int reqargs = vm_arg_operand_hi(arg2); int fixparam = vm_arg_operand_lo(arg2); -- cgit v1.2.3