Removed m*_stack_* opcodes, make them default behaviour

Memory operations used operands to encode positional/size arguments,
with stack variants in case the user wanted to programmatically do so.
In most large scale cases I don't see the non-stack variants being
used; many cases require using the stack for additions and
subtractions to create values such as indexes or sizes.  Therefore,
it's better to be stack-first.

One counter point is inline optimisation of code at runtime: if an
compile-time-known object is pushed then immediately used in an
operation, we can instead encode the value directly into an operand
based instruction which will speed up execution time because it's
slower to pop the value off the stack than have it available as part
of the instruction.
This commit is contained in:
2024-07-06 20:51:48 +01:00
parent 2b1e7a49d2
commit ebdb1a948d
4 changed files with 111 additions and 239 deletions

View File

@@ -76,14 +76,6 @@ const char *opcode_as_cstr(opcode_t code)
return "MALLOC_HWORD";
case OP_MALLOC_WORD:
return "MALLOC_WORD";
case OP_MALLOC_STACK_BYTE:
return "MALLOC_STACK_BYTE";
case OP_MALLOC_STACK_SHORT:
return "MALLOC_STACK_SHORT";
case OP_MALLOC_STACK_HWORD:
return "MALLOC_STACK_HWORD";
case OP_MALLOC_STACK_WORD:
return "MALLOC_STACK_WORD";
case OP_MSET_BYTE:
return "MSET_BYTE";
case OP_MSET_SHORT:
@@ -92,14 +84,6 @@ const char *opcode_as_cstr(opcode_t code)
return "MSET_HWORD";
case OP_MSET_WORD:
return "MSET_WORD";
case OP_MSET_STACK_BYTE:
return "MSET_STACK_BYTE";
case OP_MSET_STACK_SHORT:
return "MSET_STACK_SHORT";
case OP_MSET_STACK_HWORD:
return "MSET_STACK_HWORD";
case OP_MSET_STACK_WORD:
return "MSET_STACK_WORD";
case OP_MGET_BYTE:
return "MGET_BYTE";
case OP_MGET_SHORT:
@@ -108,14 +92,6 @@ const char *opcode_as_cstr(opcode_t code)
return "MGET_HWORD";
case OP_MGET_WORD:
return "MGET_WORD";
case OP_MGET_STACK_BYTE:
return "MGET_STACK_BYTE";
case OP_MGET_STACK_SHORT:
return "MGET_STACK_SHORT";
case OP_MGET_STACK_HWORD:
return "MGET_STACK_HWORD";
case OP_MGET_STACK_WORD:
return "MGET_STACK_WORD";
case OP_MDELETE:
return "MDELETE";
case OP_MSIZE:
@@ -311,7 +287,7 @@ void data_print(data_t datum, data_type_t type, FILE *fp)
void inst_print(inst_t instruction, FILE *fp)
{
static_assert(NUMBER_OF_OPCODES == 129, "inst_print: Out of date");
static_assert(NUMBER_OF_OPCODES == 117, "inst_print: Out of date");
fprintf(fp, "%s(", opcode_as_cstr(instruction.opcode));
if (UNSIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_PUSH))
{
@@ -325,10 +301,7 @@ void inst_print(inst_t instruction, FILE *fp)
fprintf(fp, "reg=0x");
data_print(instruction.operand, DATA_TYPE_BYTE, fp);
}
else if (UNSIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_DUP) ||
UNSIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_MALLOC) ||
UNSIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_MSET) ||
UNSIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_MGET))
else if (UNSIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_DUP))
{
fprintf(fp, "n=0x%lX", instruction.operand.as_word);
}
@@ -344,7 +317,7 @@ void inst_print(inst_t instruction, FILE *fp)
size_t opcode_bytecode_size(opcode_t opcode)
{
static_assert(NUMBER_OF_OPCODES == 129, "inst_bytecode_size: Out of date");
static_assert(NUMBER_OF_OPCODES == 117, "inst_bytecode_size: Out of date");
size_t size = 1; // for opcode
if (UNSIGNED_OPCODE_IS_TYPE(opcode, OP_PUSH))
{
@@ -369,7 +342,7 @@ size_t opcode_bytecode_size(opcode_t opcode)
size_t inst_write_bytecode(inst_t inst, byte_t *bytes)
{
static_assert(NUMBER_OF_OPCODES == 129, "inst_write_bytecode: Out of date");
static_assert(NUMBER_OF_OPCODES == 117, "inst_write_bytecode: Out of date");
bytes[0] = inst.opcode;
size_t written = 1;
@@ -381,9 +354,6 @@ size_t inst_write_bytecode(inst_t inst, byte_t *bytes)
UNSIGNED_OPCODE_IS_TYPE(inst.opcode, OP_DUP) ||
UNSIGNED_OPCODE_IS_TYPE(inst.opcode, OP_MOV) ||
UNSIGNED_OPCODE_IS_TYPE(inst.opcode, OP_DUP) ||
UNSIGNED_OPCODE_IS_TYPE(inst.opcode, OP_MALLOC) ||
UNSIGNED_OPCODE_IS_TYPE(inst.opcode, OP_MSET) ||
UNSIGNED_OPCODE_IS_TYPE(inst.opcode, OP_MGET) ||
UNSIGNED_OPCODE_IS_TYPE(inst.opcode, OP_JUMP_IF) ||
inst.opcode == OP_JUMP_ABS || inst.opcode == OP_CALL)
to_append = DATA_TYPE_WORD;
@@ -456,7 +426,7 @@ bool read_type_from_darr(byte_t *bytes, size_t size, data_type_t type,
int inst_read_bytecode(inst_t *ptr, byte_t *bytes, size_t size_bytes)
{
static_assert(NUMBER_OF_OPCODES == 129, "inst_read_bytecode: Out of date");
static_assert(NUMBER_OF_OPCODES == 117, "inst_read_bytecode: Out of date");
opcode_t opcode = *(bytes++);
if (opcode >= NUMBER_OF_OPCODES || opcode < OP_NOOP)
@@ -471,13 +441,10 @@ int inst_read_bytecode(inst_t *ptr, byte_t *bytes, size_t size_bytes)
if (UNSIGNED_OPCODE_IS_TYPE(opcode, OP_PUSH))
success = read_type_from_darr(bytes, size_bytes, (data_type_t)opcode,
&inst.operand);
// Read register (as a byte)
// Read operand as a word
else if (UNSIGNED_OPCODE_IS_TYPE(opcode, OP_PUSH_REGISTER) ||
UNSIGNED_OPCODE_IS_TYPE(opcode, OP_MOV) ||
UNSIGNED_OPCODE_IS_TYPE(opcode, OP_DUP) ||
UNSIGNED_OPCODE_IS_TYPE(opcode, OP_MALLOC) ||
UNSIGNED_OPCODE_IS_TYPE(opcode, OP_MSET) ||
UNSIGNED_OPCODE_IS_TYPE(opcode, OP_MGET) ||
UNSIGNED_OPCODE_IS_TYPE(opcode, OP_JUMP_IF) ||
opcode == OP_JUMP_ABS || opcode == OP_CALL)
success =

View File

@@ -64,31 +64,16 @@ typedef enum
OP_MALLOC_HWORD,
OP_MALLOC_WORD,
OP_MALLOC_STACK_BYTE,
OP_MALLOC_STACK_SHORT,
OP_MALLOC_STACK_HWORD,
OP_MALLOC_STACK_WORD,
OP_MSET_BYTE,
OP_MSET_SHORT,
OP_MSET_HWORD,
OP_MSET_WORD,
OP_MSET_STACK_BYTE,
OP_MSET_STACK_SHORT,
OP_MSET_STACK_HWORD,
OP_MSET_STACK_WORD,
OP_MGET_BYTE,
OP_MGET_SHORT,
OP_MGET_HWORD,
OP_MGET_WORD,
OP_MGET_STACK_BYTE,
OP_MGET_STACK_SHORT,
OP_MGET_STACK_HWORD,
OP_MGET_STACK_WORD,
OP_MDELETE,
OP_MSIZE,

View File

@@ -61,7 +61,7 @@ const char *err_as_cstr(err_t err)
}
}
static_assert(NUMBER_OF_OPCODES == 129, "vm_execute: Out of date");
static_assert(NUMBER_OF_OPCODES == 117, "vm_execute: Out of date");
err_t vm_execute(vm_t *vm)
{
@@ -118,13 +118,13 @@ err_t vm_execute(vm_t *vm)
UNSIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_PLUS) ||
UNSIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_SUB) ||
UNSIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_MULT) ||
UNSIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_MALLOC_STACK) ||
UNSIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_MSET_STACK) ||
UNSIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_MGET_STACK) ||
SIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_LT) ||
SIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_LTE) ||
SIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_GT) ||
SIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_GTE) ||
UNSIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_MALLOC) ||
UNSIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_MSET) ||
UNSIGNED_OPCODE_IS_TYPE(instruction.opcode, OP_MGET) ||
instruction.opcode == OP_MDELETE || instruction.opcode == OP_MSIZE)
{
err_t err = STACK_ROUTINES[instruction.opcode](vm);
@@ -511,11 +511,15 @@ VM_DUP_CONSTR(short, SHORT)
VM_DUP_CONSTR(hword, HWORD)
VM_DUP_CONSTR(word, WORD)
#define VM_MALLOC_CONSTR(TYPE, TYPE_CAP) \
err_t vm_malloc_##TYPE(vm_t *vm, word_t n) \
{ \
page_t *page = heap_allocate(&vm->heap, n * TYPE_CAP##_SIZE); \
return vm_push_word(vm, DWORD((word_t)page)); \
#define VM_MALLOC_CONSTR(TYPE, TYPE_CAP) \
err_t vm_malloc_##TYPE(vm_t *vm) \
{ \
data_t n = {0}; \
err_t err = vm_pop_word(vm, &n); \
if (err) \
return err; \
page_t *page = heap_allocate(&vm->heap, n.as_word * TYPE_CAP##_SIZE); \
return vm_push_word(vm, DWORD((word_t)page)); \
}
VM_MALLOC_CONSTR(byte, BYTE)
@@ -523,22 +527,26 @@ VM_MALLOC_CONSTR(short, SHORT)
VM_MALLOC_CONSTR(hword, HWORD)
VM_MALLOC_CONSTR(word, WORD)
#define VM_MSET_CONSTR(TYPE, TYPE_CAP) \
err_t vm_mset_##TYPE(vm_t *vm, word_t nth) \
{ \
data_t object = {0}; \
err_t err = vm_pop_##TYPE(vm, &object); \
if (err) \
return err; \
data_t ptr = {0}; \
err = vm_pop_word(vm, &ptr); \
if (err) \
return err; \
page_t *page = (page_t *)ptr.as_word; \
if (nth >= (page->available / TYPE_CAP##_SIZE)) \
return ERR_OUT_OF_BOUNDS; \
DARR_AT(TYPE##_t, page->data, nth) = object.as_##TYPE; \
return ERR_OK; \
#define VM_MSET_CONSTR(TYPE, TYPE_CAP) \
err_t vm_mset_##TYPE(vm_t *vm) \
{ \
data_t object = {0}; \
err_t err = vm_pop_##TYPE(vm, &object); \
if (err) \
return err; \
data_t n = {0}; \
err = vm_pop_word(vm, &n); \
if (err) \
return err; \
data_t ptr = {0}; \
err = vm_pop_word(vm, &ptr); \
if (err) \
return err; \
page_t *page = (page_t *)ptr.as_word; \
if (n.as_word >= (page->available / TYPE_CAP##_SIZE)) \
return ERR_OUT_OF_BOUNDS; \
DARR_AT(TYPE##_t, page->data, n.as_word) = object.as_##TYPE; \
return ERR_OK; \
}
VM_MSET_CONSTR(byte, BYTE)
@@ -546,22 +554,26 @@ VM_MSET_CONSTR(short, SHORT)
VM_MSET_CONSTR(hword, HWORD)
VM_MSET_CONSTR(word, WORD)
#define VM_MGET_CONSTR(TYPE, TYPE_CAP) \
err_t vm_mget_##TYPE(vm_t *vm, word_t n) \
{ \
data_t ptr = {0}; \
err_t err = vm_pop_word(vm, &ptr); \
if (err) \
return err; \
page_t *page = (page_t *)ptr.as_word; \
if (n >= (page->available / TYPE_CAP##_SIZE)) \
return ERR_OUT_OF_BOUNDS; \
else if (vm->stack.ptr + TYPE_CAP##_SIZE >= vm->stack.max) \
return ERR_STACK_OVERFLOW; \
memcpy(vm->stack.data + vm->stack.ptr, \
page->data + (n * (TYPE_CAP##_SIZE)), TYPE_CAP##_SIZE); \
vm->stack.ptr += TYPE_CAP##_SIZE; \
return ERR_OK; \
#define VM_MGET_CONSTR(TYPE, TYPE_CAP) \
err_t vm_mget_##TYPE(vm_t *vm) \
{ \
data_t n = {0}; \
err_t err = vm_pop_word(vm, &n); \
if (err) \
return (err); \
data_t ptr = {0}; \
err = vm_pop_word(vm, &ptr); \
if (err) \
return err; \
page_t *page = (page_t *)ptr.as_word; \
if (n.as_word >= (page->available / TYPE_CAP##_SIZE)) \
return ERR_OUT_OF_BOUNDS; \
else if (vm->stack.ptr + TYPE_CAP##_SIZE >= vm->stack.max) \
return ERR_STACK_OVERFLOW; \
memcpy(vm->stack.data + vm->stack.ptr, \
page->data + (n.as_word * (TYPE_CAP##_SIZE)), TYPE_CAP##_SIZE); \
vm->stack.ptr += TYPE_CAP##_SIZE; \
return ERR_OK; \
}
VM_MGET_CONSTR(byte, BYTE)
@@ -569,30 +581,6 @@ VM_MGET_CONSTR(short, SHORT)
VM_MGET_CONSTR(hword, HWORD)
VM_MGET_CONSTR(word, WORD)
// TODO: rename this to something more appropriate
#define VM_MEMORY_STACK_CONSTR(ACTION, TYPE) \
err_t vm_##ACTION##_stack_##TYPE(vm_t *vm) \
{ \
data_t n = {0}; \
err_t err = vm_pop_word(vm, &n); \
if (err) \
return err; \
return vm_##ACTION##_##TYPE(vm, n.as_word); \
}
VM_MEMORY_STACK_CONSTR(malloc, byte)
VM_MEMORY_STACK_CONSTR(malloc, short)
VM_MEMORY_STACK_CONSTR(malloc, hword)
VM_MEMORY_STACK_CONSTR(malloc, word)
VM_MEMORY_STACK_CONSTR(mset, byte)
VM_MEMORY_STACK_CONSTR(mset, short)
VM_MEMORY_STACK_CONSTR(mset, hword)
VM_MEMORY_STACK_CONSTR(mset, word)
VM_MEMORY_STACK_CONSTR(mget, byte)
VM_MEMORY_STACK_CONSTR(mget, short)
VM_MEMORY_STACK_CONSTR(mget, hword)
VM_MEMORY_STACK_CONSTR(mget, word)
err_t vm_mdelete(vm_t *vm)
{
data_t ptr = {0};

View File

@@ -85,21 +85,6 @@ err_t vm_dup_short(vm_t *, word_t);
err_t vm_dup_hword(vm_t *, word_t);
err_t vm_dup_word(vm_t *, word_t);
err_t vm_malloc_byte(vm_t *, word_t);
err_t vm_malloc_short(vm_t *, word_t);
err_t vm_malloc_hword(vm_t *, word_t);
err_t vm_malloc_word(vm_t *, word_t);
err_t vm_mset_byte(vm_t *, word_t);
err_t vm_mset_short(vm_t *, word_t);
err_t vm_mset_hword(vm_t *, word_t);
err_t vm_mset_word(vm_t *, word_t);
err_t vm_mget_byte(vm_t *, word_t);
err_t vm_mget_short(vm_t *, word_t);
err_t vm_mget_hword(vm_t *, word_t);
err_t vm_mget_word(vm_t *, word_t);
typedef err_t (*word_f)(vm_t *, word_t);
static const word_f WORD_ROUTINES[] = {
[OP_PUSH_REGISTER_BYTE] = vm_push_byte_register,
@@ -116,38 +101,23 @@ static const word_f WORD_ROUTINES[] = {
[OP_DUP_SHORT] = vm_dup_short,
[OP_DUP_HWORD] = vm_dup_hword,
[OP_DUP_WORD] = vm_dup_word,
[OP_MALLOC_BYTE] = vm_malloc_byte,
[OP_MALLOC_SHORT] = vm_malloc_short,
[OP_MALLOC_HWORD] = vm_malloc_hword,
[OP_MALLOC_WORD] = vm_malloc_word,
[OP_MGET_BYTE] = vm_mget_byte,
[OP_MGET_SHORT] = vm_mget_short,
[OP_MGET_HWORD] = vm_mget_hword,
[OP_MGET_WORD] = vm_mget_word,
[OP_MSET_BYTE] = vm_mset_byte,
[OP_MSET_SHORT] = vm_mset_short,
[OP_MSET_HWORD] = vm_mset_hword,
[OP_MSET_WORD] = vm_mset_word,
};
/* Operations that take input from the stack */
err_t vm_malloc_stack_byte(vm_t *);
err_t vm_malloc_stack_short(vm_t *);
err_t vm_malloc_stack_hword(vm_t *);
err_t vm_malloc_stack_word(vm_t *);
err_t vm_malloc_byte(vm_t *);
err_t vm_malloc_short(vm_t *);
err_t vm_malloc_hword(vm_t *);
err_t vm_malloc_word(vm_t *);
err_t vm_mset_stack_byte(vm_t *);
err_t vm_mset_stack_short(vm_t *);
err_t vm_mset_stack_hword(vm_t *);
err_t vm_mset_stack_word(vm_t *);
err_t vm_mset_byte(vm_t *);
err_t vm_mset_short(vm_t *);
err_t vm_mset_hword(vm_t *);
err_t vm_mset_word(vm_t *);
err_t vm_mget_stack_byte(vm_t *);
err_t vm_mget_stack_short(vm_t *);
err_t vm_mget_stack_hword(vm_t *);
err_t vm_mget_stack_word(vm_t *);
err_t vm_mget_byte(vm_t *);
err_t vm_mget_short(vm_t *);
err_t vm_mget_hword(vm_t *);
err_t vm_mget_word(vm_t *);
err_t vm_mdelete(vm_t *);
err_t vm_msize(vm_t *);
@@ -234,97 +204,59 @@ err_t vm_mult_word(vm_t *);
typedef err_t (*stack_f)(vm_t *);
static const stack_f STACK_ROUTINES[] = {
[OP_MALLOC_STACK_BYTE] = vm_malloc_stack_byte,
[OP_MALLOC_STACK_SHORT] = vm_malloc_stack_short,
[OP_MALLOC_STACK_HWORD] = vm_malloc_stack_hword,
[OP_MALLOC_STACK_WORD] = vm_malloc_stack_word,
[OP_MALLOC_BYTE] = vm_malloc_byte, [OP_MALLOC_SHORT] = vm_malloc_short,
[OP_MALLOC_HWORD] = vm_malloc_hword, [OP_MALLOC_WORD] = vm_malloc_word,
[OP_MGET_STACK_BYTE] = vm_mget_stack_byte,
[OP_MGET_STACK_SHORT] = vm_mget_stack_short,
[OP_MGET_STACK_HWORD] = vm_mget_stack_hword,
[OP_MGET_STACK_WORD] = vm_mget_stack_word,
[OP_MSET_STACK_BYTE] = vm_mset_stack_byte,
[OP_MSET_STACK_SHORT] = vm_mset_stack_short,
[OP_MSET_STACK_HWORD] = vm_mset_stack_hword,
[OP_MSET_STACK_WORD] = vm_mset_stack_word,
[OP_MGET_BYTE] = vm_mget_byte, [OP_MGET_SHORT] = vm_mget_short,
[OP_MGET_HWORD] = vm_mget_hword, [OP_MGET_WORD] = vm_mget_word,
[OP_MDELETE] = vm_mdelete,
[OP_MSIZE] = vm_msize,
[OP_MSET_BYTE] = vm_mset_byte, [OP_MSET_SHORT] = vm_mset_short,
[OP_MSET_HWORD] = vm_mset_hword, [OP_MSET_WORD] = vm_mset_word,
[OP_NOT_BYTE] = vm_not_byte,
[OP_NOT_SHORT] = vm_not_short,
[OP_NOT_HWORD] = vm_not_hword,
[OP_NOT_WORD] = vm_not_word,
[OP_MDELETE] = vm_mdelete, [OP_MSIZE] = vm_msize,
[OP_OR_BYTE] = vm_or_byte,
[OP_OR_SHORT] = vm_or_short,
[OP_OR_HWORD] = vm_or_hword,
[OP_OR_WORD] = vm_or_word,
[OP_NOT_BYTE] = vm_not_byte, [OP_NOT_SHORT] = vm_not_short,
[OP_NOT_HWORD] = vm_not_hword, [OP_NOT_WORD] = vm_not_word,
[OP_AND_BYTE] = vm_and_byte,
[OP_AND_SHORT] = vm_and_short,
[OP_AND_HWORD] = vm_and_hword,
[OP_AND_WORD] = vm_and_word,
[OP_OR_BYTE] = vm_or_byte, [OP_OR_SHORT] = vm_or_short,
[OP_OR_HWORD] = vm_or_hword, [OP_OR_WORD] = vm_or_word,
[OP_XOR_BYTE] = vm_xor_byte,
[OP_XOR_SHORT] = vm_xor_short,
[OP_XOR_HWORD] = vm_xor_hword,
[OP_XOR_WORD] = vm_xor_word,
[OP_AND_BYTE] = vm_and_byte, [OP_AND_SHORT] = vm_and_short,
[OP_AND_HWORD] = vm_and_hword, [OP_AND_WORD] = vm_and_word,
[OP_EQ_BYTE] = vm_eq_byte,
[OP_EQ_SHORT] = vm_eq_short,
[OP_EQ_HWORD] = vm_eq_hword,
[OP_EQ_WORD] = vm_eq_word,
[OP_XOR_BYTE] = vm_xor_byte, [OP_XOR_SHORT] = vm_xor_short,
[OP_XOR_HWORD] = vm_xor_hword, [OP_XOR_WORD] = vm_xor_word,
[OP_LT_BYTE] = vm_lt_byte,
[OP_LT_SBYTE] = vm_lt_sbyte,
[OP_LT_SHORT] = vm_lt_short,
[OP_LT_SSHORT] = vm_lt_sshort,
[OP_LT_SHWORD] = vm_lt_shword,
[OP_LT_HWORD] = vm_lt_hword,
[OP_LT_SWORD] = vm_lt_sword,
[OP_LT_WORD] = vm_lt_word,
[OP_EQ_BYTE] = vm_eq_byte, [OP_EQ_SHORT] = vm_eq_short,
[OP_EQ_HWORD] = vm_eq_hword, [OP_EQ_WORD] = vm_eq_word,
[OP_LTE_BYTE] = vm_lte_byte,
[OP_LTE_SBYTE] = vm_lte_sbyte,
[OP_LTE_SHORT] = vm_lte_short,
[OP_LTE_SSHORT] = vm_lte_sshort,
[OP_LTE_SHWORD] = vm_lte_shword,
[OP_LTE_HWORD] = vm_lte_hword,
[OP_LTE_SWORD] = vm_lte_sword,
[OP_LTE_WORD] = vm_lte_word,
[OP_LT_BYTE] = vm_lt_byte, [OP_LT_SBYTE] = vm_lt_sbyte,
[OP_LT_SHORT] = vm_lt_short, [OP_LT_SSHORT] = vm_lt_sshort,
[OP_LT_SHWORD] = vm_lt_shword, [OP_LT_HWORD] = vm_lt_hword,
[OP_LT_SWORD] = vm_lt_sword, [OP_LT_WORD] = vm_lt_word,
[OP_GT_BYTE] = vm_gt_byte,
[OP_GT_SBYTE] = vm_gt_sbyte,
[OP_GT_SHORT] = vm_gt_short,
[OP_GT_SSHORT] = vm_gt_sshort,
[OP_GT_SHWORD] = vm_gt_shword,
[OP_GT_HWORD] = vm_gt_hword,
[OP_GT_SWORD] = vm_gt_sword,
[OP_GT_WORD] = vm_gt_word,
[OP_LTE_BYTE] = vm_lte_byte, [OP_LTE_SBYTE] = vm_lte_sbyte,
[OP_LTE_SHORT] = vm_lte_short, [OP_LTE_SSHORT] = vm_lte_sshort,
[OP_LTE_SHWORD] = vm_lte_shword, [OP_LTE_HWORD] = vm_lte_hword,
[OP_LTE_SWORD] = vm_lte_sword, [OP_LTE_WORD] = vm_lte_word,
[OP_GTE_BYTE] = vm_gte_byte,
[OP_GTE_SBYTE] = vm_gte_sbyte,
[OP_GTE_SHORT] = vm_gte_short,
[OP_GTE_SSHORT] = vm_gte_sshort,
[OP_GTE_SHWORD] = vm_gte_shword,
[OP_GTE_HWORD] = vm_gte_hword,
[OP_GTE_SWORD] = vm_gte_sword,
[OP_GTE_WORD] = vm_gte_word,
[OP_GT_BYTE] = vm_gt_byte, [OP_GT_SBYTE] = vm_gt_sbyte,
[OP_GT_SHORT] = vm_gt_short, [OP_GT_SSHORT] = vm_gt_sshort,
[OP_GT_SHWORD] = vm_gt_shword, [OP_GT_HWORD] = vm_gt_hword,
[OP_GT_SWORD] = vm_gt_sword, [OP_GT_WORD] = vm_gt_word,
[OP_PLUS_BYTE] = vm_plus_byte,
[OP_PLUS_SHORT] = vm_plus_short,
[OP_PLUS_HWORD] = vm_plus_hword,
[OP_PLUS_WORD] = vm_plus_word,
[OP_SUB_BYTE] = vm_sub_byte,
[OP_SUB_SHORT] = vm_sub_short,
[OP_SUB_HWORD] = vm_sub_hword,
[OP_SUB_WORD] = vm_sub_word,
[OP_GTE_BYTE] = vm_gte_byte, [OP_GTE_SBYTE] = vm_gte_sbyte,
[OP_GTE_SHORT] = vm_gte_short, [OP_GTE_SSHORT] = vm_gte_sshort,
[OP_GTE_SHWORD] = vm_gte_shword, [OP_GTE_HWORD] = vm_gte_hword,
[OP_GTE_SWORD] = vm_gte_sword, [OP_GTE_WORD] = vm_gte_word,
[OP_MULT_BYTE] = vm_mult_byte,
[OP_MULT_SHORT] = vm_mult_short,
[OP_MULT_HWORD] = vm_mult_hword,
[OP_MULT_WORD] = vm_mult_word,
[OP_PLUS_BYTE] = vm_plus_byte, [OP_PLUS_SHORT] = vm_plus_short,
[OP_PLUS_HWORD] = vm_plus_hword, [OP_PLUS_WORD] = vm_plus_word,
[OP_SUB_BYTE] = vm_sub_byte, [OP_SUB_SHORT] = vm_sub_short,
[OP_SUB_HWORD] = vm_sub_hword, [OP_SUB_WORD] = vm_sub_word,
[OP_MULT_BYTE] = vm_mult_byte, [OP_MULT_SHORT] = vm_mult_short,
[OP_MULT_HWORD] = vm_mult_hword, [OP_MULT_WORD] = vm_mult_word,
};
#endif