summaryrefslogtreecommitdiffstats
path: root/vm.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-04-16 21:42:45 -0700
committerKaz Kylheku <kaz@kylheku.com>2018-04-16 21:42:45 -0700
commit4e8c983e12b8235cfd4fa3594c8064d51fcb67c6 (patch)
tree1b0caddd2600849ab505aadf17636413d5296d4f /vm.c
parent49249272d243f6b27af4cf8cebbbb63d16dcdce7 (diff)
downloadtxr-4e8c983e12b8235cfd4fa3594c8064d51fcb67c6.tar.gz
txr-4e8c983e12b8235cfd4fa3594c8064d51fcb67c6.tar.bz2
txr-4e8c983e12b8235cfd4fa3594c8064d51fcb67c6.zip
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.
Diffstat (limited to 'vm.c')
-rw-r--r--vm.c58
1 files changed, 45 insertions, 13 deletions
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);