aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAryadev Chavali <aryadev@aryadevchavali.com>2023-10-21 22:57:43 +0100
committerAryadev Chavali <aryadev@aryadevchavali.com>2023-10-21 22:57:43 +0100
commitdcedb70a5ccead41574cf857b369d264c87dd7e0 (patch)
tree45f4f9eb7a5258fc7ee1e25fbe4edaa05f82093f
parent266b4e4572be015dca986b423896ec6fa14b4318 (diff)
downloadovm-dcedb70a5ccead41574cf857b369d264c87dd7e0.tar.gz
ovm-dcedb70a5ccead41574cf857b369d264c87dd7e0.tar.bz2
ovm-dcedb70a5ccead41574cf857b369d264c87dd7e0.zip
Switched from floats to halfword
Registers are now just words, with pushing from and moving to registers with specified subtypes just pushing those types into the word registers. That means there are 8 word registers which can act as 16 half word registers, which themselves can act as 64 byte registers.
-rw-r--r--src/base.h14
-rw-r--r--src/inst.c134
-rw-r--r--src/inst.h56
-rw-r--r--src/runtime.c170
-rw-r--r--src/runtime.h44
5 files changed, 195 insertions, 223 deletions
diff --git a/src/base.h b/src/base.h
index 670aa81..e8ddfdb 100644
--- a/src/base.h
+++ b/src/base.h
@@ -26,27 +26,29 @@ typedef float f32;
typedef double f64;
typedef uint8_t byte;
+typedef u32 hword;
typedef u64 word;
typedef union
{
byte as_byte;
+ hword as_hword;
word as_word;
- f64 as_float;
} data_t;
typedef enum
{
- DATA_TYPE_NIL = 0,
- DATA_TYPE_BYTE = 1,
- DATA_TYPE_WORD = 3,
- DATA_TYPE_FLOAT = 5,
+ DATA_TYPE_NIL = 0,
+ DATA_TYPE_BYTE,
+ DATA_TYPE_HWORD,
+ DATA_TYPE_WORD,
} data_type_t;
#define DBYTE(BYTE) ((data_t){.as_byte = (BYTE)})
+#define DHWORD(HWORD) ((data_t){.as_hword = (HWORD)})
#define DWORD(WORD) ((data_t){.as_word = (WORD)})
-#define DFLOAT(FLOAT) ((data_t){.as_float = (FLOAT)})
+#define HWORD_SIZE sizeof(hword)
#define WORD_SIZE sizeof(word)
#define FLOAT_SIZE sizeof(f64)
diff --git a/src/inst.c b/src/inst.c
index 26f7fa5..d7edd94 100644
--- a/src/inst.c
+++ b/src/inst.c
@@ -29,17 +29,17 @@ const char *opcode_as_cstr(opcode_t code)
case OP_PUSH_WORD:
return "PUSH_WORD";
break;
- case OP_PUSH_FLOAT:
- return "PUSH_FLOAT";
+ case OP_PUSH_HWORD:
+ return "PUSH_HWORD";
break;
- case OP_PUSH_BYTE_REGISTER:
- return "PUSH_BYTE_REGISTER";
+ case OP_PUSH_REGISTER_BYTE:
+ return "PUSH_REGISTER_BYTE";
break;
- case OP_PUSH_WORD_REGISTER:
- return "PUSH_WORD_REGISTER";
+ case OP_PUSH_REGISTER_WORD:
+ return "PUSH_REGISTER_WORD";
break;
- case OP_PUSH_FLOAT_REGISTER:
- return "PUSH_FLOAT_REGISTER";
+ case OP_PUSH_REGISTER_HWORD:
+ return "PUSH_REGISTER_HWORD";
break;
case OP_POP_BYTE:
return "POP_BYTE";
@@ -47,8 +47,8 @@ const char *opcode_as_cstr(opcode_t code)
case OP_POP_WORD:
return "POP_WORD";
break;
- case OP_POP_FLOAT:
- return "POP_FLOAT";
+ case OP_POP_HWORD:
+ return "POP_HWORD";
break;
case OP_MOV_BYTE:
return "MOV_BYTE";
@@ -56,8 +56,8 @@ const char *opcode_as_cstr(opcode_t code)
case OP_MOV_WORD:
return "MOV_WORD";
break;
- case OP_MOV_FLOAT:
- return "MOV_FLOAT";
+ case OP_MOV_HWORD:
+ return "MOV_HWORD";
break;
case OP_HALT:
return "HALT";
@@ -66,24 +66,6 @@ const char *opcode_as_cstr(opcode_t code)
return "";
}
-const char *opcode_type_as_cstr(opcode_type_t type)
-{
- switch (type)
- {
- case OP_TYPE_PUSH:
- return "TYPE_PUSH";
- case OP_TYPE_PUSH_REGISTER:
- return "TYPE_PUSH_REGISTER";
- case OP_TYPE_POP:
- return "TYPE_POP";
- case OP_TYPE_MOV:
- return "TYPE_MOV";
- case OP_TYPE_HALT:
- return "TYPE_HALT";
- }
- return "";
-}
-
void data_print(data_t datum, data_type_t type, FILE *fp)
{
switch (type)
@@ -93,25 +75,25 @@ void data_print(data_t datum, data_type_t type, FILE *fp)
case DATA_TYPE_BYTE:
fprintf(fp, "%X", datum.as_byte);
break;
+ case DATA_TYPE_HWORD:
+ fprintf(fp, "%d", datum.as_hword);
+ break;
case DATA_TYPE_WORD:
fprintf(fp, "%lX", datum.as_word);
break;
- case DATA_TYPE_FLOAT:
- fprintf(fp, "%f", datum.as_float);
- break;
}
}
data_type_t get_opcode_data_type(opcode_t opcode)
{
data_type_t type = DATA_TYPE_NIL;
- if (OPCODE_IS_TYPE(opcode, OP_TYPE_PUSH))
+ if (OPCODE_IS_TYPE(opcode, OP_PUSH))
type = (data_type_t)opcode;
- else if (OPCODE_IS_TYPE(opcode, OP_TYPE_PUSH_REGISTER))
+ else if (OPCODE_IS_TYPE(opcode, OP_PUSH_REGISTER))
type = opcode >> 1;
- else if (OPCODE_IS_TYPE(opcode, OP_TYPE_POP))
+ else if (OPCODE_IS_TYPE(opcode, OP_POP))
type = opcode >> 2;
- else if (OPCODE_IS_TYPE(opcode, OP_TYPE_MOV))
+ else if (OPCODE_IS_TYPE(opcode, OP_MOV))
type = opcode >> 3;
return type;
}
@@ -119,16 +101,16 @@ data_type_t get_opcode_data_type(opcode_t opcode)
void inst_print(inst_t instruction, FILE *fp)
{
fprintf(fp, "(%s", opcode_as_cstr(instruction.opcode));
- if (OPCODE_IS_TYPE(instruction.opcode, OP_TYPE_PUSH))
+ if (OPCODE_IS_TYPE(instruction.opcode, OP_PUSH))
{
data_type_t type = get_opcode_data_type(instruction.opcode);
- fprintf(fp, ", datum=");
+ fprintf(fp, ", datum=0x");
data_print(instruction.operand, type, fp);
}
- else if (OPCODE_IS_TYPE(instruction.opcode, OP_TYPE_PUSH_REGISTER) ||
- OPCODE_IS_TYPE(instruction.opcode, OP_TYPE_MOV))
+ else if (OPCODE_IS_TYPE(instruction.opcode, OP_PUSH_REGISTER) ||
+ OPCODE_IS_TYPE(instruction.opcode, OP_MOV))
{
- fprintf(fp, ", reg=");
+ fprintf(fp, ", reg=0x");
data_print(instruction.operand, DATA_TYPE_BYTE, fp);
}
fprintf(fp, ")");
@@ -137,32 +119,22 @@ void inst_print(inst_t instruction, FILE *fp)
size_t inst_bytecode_size(inst_t inst)
{
size_t size = 1; // for opcode
- if (OPCODE_IS_TYPE(inst.opcode, OP_TYPE_PUSH))
+ if (OPCODE_IS_TYPE(inst.opcode, OP_PUSH))
{
if (inst.opcode == OP_PUSH_BYTE)
++size;
+ else if (inst.opcode == OP_PUSH_HWORD)
+ size += sizeof(i32);
else if (inst.opcode == OP_PUSH_WORD)
size += sizeof(word);
- else if (inst.opcode == OP_PUSH_FLOAT)
- size += sizeof(f64);
}
- else if (OPCODE_IS_TYPE(inst.opcode, OP_TYPE_PUSH_REGISTER))
+ else if (OPCODE_IS_TYPE(inst.opcode, OP_PUSH_REGISTER) ||
+ OPCODE_IS_TYPE(inst.opcode, OP_MOV))
+ // Only need a byte for the register
++size;
- else if (OPCODE_IS_TYPE(inst.opcode, OP_TYPE_POP))
- {
- // No operand or register so leave as is
- }
- else if (OPCODE_IS_TYPE(inst.opcode, OP_TYPE_MOV))
- {
- if (inst.opcode == OP_MOV_BYTE)
- ++size;
- else if (inst.opcode == OP_MOV_WORD)
- size += sizeof(word);
- else if (inst.opcode == OP_MOV_FLOAT)
- size += sizeof(f64);
- // For the register
- ++size;
- }
+ else if (OPCODE_IS_TYPE(inst.opcode, OP_POP))
+ // No operand or register so leave as is
+ {}
return size;
}
@@ -172,10 +144,10 @@ void inst_write_bytecode(inst_t inst, darr_t *darr)
darr_append_byte(darr, inst.opcode);
// Then append 0 or more operands
data_type_t to_append = DATA_TYPE_NIL;
- if (OPCODE_IS_TYPE(inst.opcode, OP_TYPE_PUSH))
+ if (OPCODE_IS_TYPE(inst.opcode, OP_PUSH))
to_append = (data_type_t)inst.opcode;
- else if (OPCODE_IS_TYPE(inst.opcode, OP_TYPE_PUSH_REGISTER) ||
- OPCODE_IS_TYPE(inst.opcode, OP_TYPE_MOV))
+ else if (OPCODE_IS_TYPE(inst.opcode, OP_PUSH_REGISTER) ||
+ OPCODE_IS_TYPE(inst.opcode, OP_MOV))
to_append = DATA_TYPE_BYTE;
switch (to_append)
@@ -185,11 +157,13 @@ void inst_write_bytecode(inst_t inst, darr_t *darr)
case DATA_TYPE_BYTE:
darr_append_byte(darr, inst.operand.as_byte);
break;
- case DATA_TYPE_WORD:
- darr_append_bytes(darr, (byte *)&inst.operand.as_word, sizeof(word));
+ case DATA_TYPE_HWORD:
+ darr_append_bytes(darr, (byte *)&inst.operand.as_hword,
+ sizeof(inst.operand.as_hword));
break;
- case DATA_TYPE_FLOAT:
- darr_append_bytes(darr, (byte *)&inst.operand.as_float, sizeof(f64));
+ case DATA_TYPE_WORD:
+ darr_append_bytes(darr, (byte *)&inst.operand.as_word,
+ sizeof(inst.operand.as_word));
break;
}
}
@@ -206,6 +180,15 @@ data_t read_type_from_darr(darr_t *darr, data_type_t type)
return DBYTE(0);
return DBYTE(darr->data[darr->used++]);
break;
+ case DATA_TYPE_HWORD:
+ if (darr->used + HWORD_SIZE >= darr->available)
+ // TODO: Error (darr has no space left)
+ return DWORD(0);
+ hword u = 0;
+ memcpy(&u, darr->data + darr->used, sizeof(u));
+ darr->used += sizeof(u);
+ return DHWORD(u);
+ break;
case DATA_TYPE_WORD:
if (darr->used + sizeof(word) >= darr->available)
// TODO: Error (darr has no space left)
@@ -215,15 +198,6 @@ data_t read_type_from_darr(darr_t *darr, data_type_t type)
darr->used += sizeof(w);
return DWORD(w);
break;
- case DATA_TYPE_FLOAT:
- if (darr->used + sizeof(word) >= darr->available)
- // TODO: Error (darr has no space left)
- return DWORD(0);
- f64 f = 0;
- memcpy(&f, darr->data + darr->used, sizeof(f));
- darr->used += sizeof(f);
- return DFLOAT(f);
- break;
}
// TODO: Error (unrecognised type)
return DBYTE(0);
@@ -239,11 +213,11 @@ inst_t inst_read_bytecode(darr_t *darr)
// Translate to NOOP
return inst;
// Read operands
- if (OPCODE_IS_TYPE(opcode, OP_TYPE_PUSH))
+ if (OPCODE_IS_TYPE(opcode, OP_PUSH))
inst.operand = read_type_from_darr(darr, get_opcode_data_type(opcode));
// Read register (as a byte)
- else if (OPCODE_IS_TYPE(opcode, OP_TYPE_PUSH_REGISTER) ||
- OPCODE_IS_TYPE(opcode, OP_TYPE_MOV))
+ else if (OPCODE_IS_TYPE(opcode, OP_PUSH_REGISTER) ||
+ OPCODE_IS_TYPE(opcode, OP_MOV))
inst.operand = read_type_from_darr(darr, DATA_TYPE_BYTE);
// Otherwise opcode doesn't take operands
diff --git a/src/inst.h b/src/inst.h
index 2748c7f..f5ab4ae 100644
--- a/src/inst.h
+++ b/src/inst.h
@@ -23,41 +23,29 @@ typedef enum
{
OP_NOOP = 0,
- // 0b0001
- OP_PUSH_BYTE = 0b00000001,
- OP_PUSH_WORD = 0b00000011,
- OP_PUSH_FLOAT = 0b00000101,
- // 0b0010
- OP_PUSH_BYTE_REGISTER = 0b00000010,
- OP_PUSH_WORD_REGISTER = 0b00000110,
- OP_PUSH_FLOAT_REGISTER = 0b00001010,
- // 0b0100
- OP_POP_BYTE = 0b00000100,
- OP_POP_WORD = 0b00001100,
- OP_POP_FLOAT = 0b00010100,
- // 0b1000
- OP_MOV_BYTE = 0b00001000,
- OP_MOV_WORD = 0b00011000,
- OP_MOV_FLOAT = 0b00101000,
-
- OP_HALT = 0b10000000, // top of the byte is a HALT
-} opcode_t;
+ OP_PUSH_BYTE,
+ OP_PUSH_HWORD,
+ OP_PUSH_WORD,
-const char *opcode_as_cstr(opcode_t);
+ OP_PUSH_REGISTER_BYTE,
+ OP_PUSH_REGISTER_HWORD,
+ OP_PUSH_REGISTER_WORD,
-// Masks and values to check if an opcode is of a type
-typedef enum
-{
- OP_TYPE_PUSH = 0b00000001,
- OP_TYPE_PUSH_REGISTER = 0b00000010,
- OP_TYPE_POP = 0b00000100,
- OP_TYPE_MOV = 0b00001000,
- OP_TYPE_HALT = 0b10000000,
-} opcode_type_t;
+ OP_POP_BYTE,
+ OP_POP_HWORD,
+ OP_POP_WORD,
-const char *opcode_type_as_cstr(opcode_type_t);
+ OP_MOV_BYTE,
+ OP_MOV_HWORD,
+ OP_MOV_WORD,
+
+ OP_HALT = 0b11111111, // top of the byte is a HALT
+} opcode_t;
+
+const char *opcode_as_cstr(opcode_t);
-#define OPCODE_IS_TYPE(OPCODE, OP_TYPE) (((OPCODE) & (OP_TYPE)) == (OP_TYPE))
+#define OPCODE_IS_TYPE(OPCODE, OP_TYPE) \
+ (((OPCODE) >= OP_TYPE##_BYTE) && ((OPCODE) <= OP_TYPE##_WORD))
typedef struct
{
@@ -96,12 +84,12 @@ inst_t inst_read_bytecode(darr_t *);
#define INST_FPOP ((inst_t){.opcode = OP_POP_FLOAT})
#define INST_BPUSH_REG(REG) \
- ((inst_t){.opcode = OP_PUSH_BYTE_REGISTER, .operand = DBYTE(REG)})
+ ((inst_t){.opcode = OP_PUSH_REGISTER_BYTE, .operand = DBYTE(REG)})
#define INST_WPUSH_REG(REG) \
- ((inst_t){.opcode = OP_PUSH_WORD_REGISTER, .operand = DBYTE(REG)})
+ ((inst_t){.opcode = OP_PUSH_REGISTER_WORD, .operand = DBYTE(REG)})
#define INST_FPUSH_REG(REG) \
- ((inst_t){.opcode = OP_PUSH_FLOAT_REGISTER, .operand = DBYTE(REG)})
+ ((inst_t){.opcode = OP_PUSH_REGISTER_FLOAT, .operand = DBYTE(REG)})
#endif
diff --git a/src/runtime.c b/src/runtime.c
index b744530..218bba7 100644
--- a/src/runtime.c
+++ b/src/runtime.c
@@ -24,26 +24,26 @@ void vm_execute(vm_t *vm)
return;
inst_t instruction = prog->instructions[prog->ptr];
- if (OPCODE_IS_TYPE(instruction.opcode, OP_TYPE_PUSH))
+ if (OPCODE_IS_TYPE(instruction.opcode, OP_PUSH))
{
PUSH_ROUTINES[instruction.opcode](vm, instruction.operand);
vm->registers.ret = instruction.operand.as_word;
prog->ptr++;
}
- else if (OPCODE_IS_TYPE(instruction.opcode, OP_TYPE_PUSH_REGISTER))
+ else if (OPCODE_IS_TYPE(instruction.opcode, OP_PUSH_REGISTER))
{
PUSH_REG_ROUTINES[instruction.opcode](vm, instruction.operand.as_word);
vm->registers.ret = instruction.operand.as_word;
prog->ptr++;
}
- else if (OPCODE_IS_TYPE(instruction.opcode, OP_TYPE_POP))
+ else if (OPCODE_IS_TYPE(instruction.opcode, OP_POP))
{
// NOTE: We use the `ret` register for the result of this pop
data_t d = POP_ROUTINES[instruction.opcode](vm);
vm->registers.ret = d.as_word;
prog->ptr++;
}
- else if (OPCODE_IS_TYPE(instruction.opcode, OP_TYPE_MOV))
+ else if (OPCODE_IS_TYPE(instruction.opcode, OP_MOV))
{
data_t d =
MOV_ROUTINES[instruction.opcode](vm, instruction.operand.as_word);
@@ -74,37 +74,21 @@ void vm_load_program(vm_t *vm, inst_t *instructions, size_t size)
void vm_print_registers(vm_t *vm, FILE *fp)
{
struct Registers reg = vm->registers;
- fprintf(fp, "Registers.ret = %lX\n", reg.ret);
- fprintf(fp, "Registers.b = [");
- for (size_t i = 0; i < VM_BYTE_REGISTERS; ++i)
+ fprintf(fp, "Registers.ret = 0x%lX\n", reg.ret);
+ fprintf(fp, "Registers.reg = [");
+ for (size_t i = 0; i < VM_REGISTERS; ++i)
{
- fprintf(fp, "{%lu:%X}", i, reg.b[i]);
- if (i != VM_BYTE_REGISTERS - 1)
+ fprintf(fp, "{%lu:%lX}", i, reg.reg[i]);
+ if (i != VM_REGISTERS - 1)
fprintf(fp, ", ");
}
fprintf(fp, "]\n");
- fprintf(fp, "Registers.w = [");
- for (size_t i = 0; i < VM_WORD_REGISTERS; ++i)
- {
- fprintf(fp, "{%lu:%lX}", i, reg.w[i]);
- if (i != VM_WORD_REGISTERS - 1)
- fprintf(fp, reg.w[i] == 0 ? ", " : ",\n");
- }
- fprintf(fp, "]\n");
- fprintf(fp, "Registers.f = [");
- for (size_t i = 0; i < VM_FLOAT_REGISTERS; ++i)
- {
- fprintf(fp, "{%lu:%f}", i, reg.f[i]);
- if (i != VM_FLOAT_REGISTERS - 1)
- fprintf(fp, reg.f[i] == 0 ? ", " : ",\n");
- }
- fprintf(fp, "]\n");
}
void vm_print_stack(vm_t *vm, FILE *fp)
{
struct Stack stack = vm->stack;
- fprintf(fp, "Stack.max = %lu\nStack.ptr = %lu\nStack.data = [", stack.max,
+ fprintf(fp, "Stack.max = %lu\nStack.ptr = %lu\nStack.data = [", stack.max,
stack.ptr);
if (stack.ptr == 0)
{
@@ -127,7 +111,9 @@ void vm_print_stack(vm_t *vm, FILE *fp)
void vm_print_program(vm_t *vm, FILE *fp)
{
struct Program program = vm->program;
- fprintf(fp, "Program.max = %lu\nProgram.ptr = %lu\nProgram.instructions = [",
+ fprintf(fp,
+ "Program.max = %lu\nProgram.ptr = "
+ "%lu\nProgram.instructions = [",
program.max, program.ptr);
if (program.ptr == 0)
{
@@ -185,6 +171,19 @@ void vm_push_byte(vm_t *vm, data_t b)
vm->stack.data[vm->stack.ptr++] = b.as_byte;
}
+void vm_push_hword(vm_t *vm, data_t f)
+{
+ if (vm->stack.ptr + HWORD_SIZE >= vm->stack.max)
+ // TODO: Error STACK_OVERFLOW
+ return;
+ for (size_t i = 32; i > 0; i -= 8)
+ {
+ const word mask = ((word)0b11111111) << (i - 8);
+ byte b = (f.as_hword & mask) >> (i - 8);
+ vm_push_byte(vm, DBYTE(b));
+ }
+}
+
void vm_push_word(vm_t *vm, data_t w)
{
if (vm->stack.ptr + WORD_SIZE >= vm->stack.max)
@@ -199,86 +198,94 @@ void vm_push_word(vm_t *vm, data_t w)
}
}
-void vm_push_float(vm_t *vm, data_t f)
-{
- if (vm->stack.ptr + FLOAT_SIZE >= vm->stack.max)
- // TODO: Error STACK_OVERFLOW
- return;
- // TODO: Make this machine independent (encode IEEE754 floats
- // yourself?)
- memcpy(vm->stack.data + vm->stack.ptr, &f.as_float, FLOAT_SIZE);
- vm->stack.ptr += FLOAT_SIZE;
-}
+#define WORD_NTH_BYTE(WORD, N) (((WORD) >> ((N)*8)) & 0b11111111)
+#define WORD_NTH_HWORD(WORD, N) \
+ (((WORD) >> ((N)*2)) & 0b11111111111111111111111111111111)
-void vm_push_byte_register(vm_t *vm, word reg)
+void vm_push_byte_register(vm_t *vm, byte reg)
{
- if (reg >= VM_BYTE_REGISTERS)
+ if (reg >= VM_REGISTERS * 8)
// TODO: Error (reg is not a valid byte register)
return;
else if (vm->stack.ptr >= vm->stack.max)
// TODO: Error STACK_OVERFLOW
return;
- vm_push_byte(vm, DBYTE(vm->registers.b[reg]));
+
+ // Interpret each word based register as 8 byte registers
+ word ind = reg / 8;
+ word nth_byte = reg % 8;
+ word reg_ptr = vm->registers.reg[ind];
+
+ byte b = WORD_NTH_BYTE(reg_ptr, nth_byte);
+
+ vm_push_byte(vm, DBYTE(b));
}
-void vm_push_word_register(vm_t *vm, word reg)
+void vm_push_hword_register(vm_t *vm, byte reg)
{
- if (reg >= VM_WORD_REGISTERS)
- // TODO: Error (reg is not a valid word register)
+ if (reg >= VM_REGISTERS * 2)
+ // TODO: Error (reg is not a valid hword register)
return;
else if (vm->stack.ptr >= vm->stack.max)
// TODO: Error STACK_OVERFLOW
return;
- vm_push_word(vm, DWORD(vm->registers.w[reg]));
+ // Interpret each word based register as 2 hword registers
+ word ind = reg / 2;
+ word nth_hword = reg % 2;
+ word reg_ptr = vm->registers.reg[ind];
+ hword hw = WORD_NTH_HWORD(reg_ptr, nth_hword);
+ vm_push_hword(vm, DHWORD(hw));
}
-void vm_push_float_register(vm_t *vm, word reg)
+void vm_push_word_register(vm_t *vm, byte reg)
{
- if (reg >= VM_FLOAT_REGISTERS)
- // TODO: Error (reg is not a valid float register)
+ if (reg >= VM_REGISTERS)
+ // TODO: Error (reg is not a valid word register)
return;
else if (vm->stack.ptr >= vm->stack.max)
// TODO: Error STACK_OVERFLOW
return;
- vm_push_float(vm, DFLOAT(vm->registers.f[reg]));
+ vm_push_word(vm, DWORD(vm->registers.reg[reg]));
}
-data_t vm_mov_byte(vm_t *vm, word reg)
+data_t vm_mov_byte(vm_t *vm, byte reg)
{
- if (reg >= VM_BYTE_REGISTERS)
+ if (reg >= VM_REGISTERS)
// TODO: Error (reg is not a valid byte register)
return DBYTE(0);
else if (vm->stack.ptr == 0)
// TODO: Error (STACK UNDERFLOW)
return DBYTE(0);
- data_t ret = vm_pop_byte(vm);
- vm->registers.b[reg] = ret.as_byte;
+ data_t ret = vm_pop_byte(vm);
+ word *reg_ptr = &vm->registers.reg[reg / 8];
+ *reg_ptr = (*reg_ptr) | ((word)ret.as_word) << ((reg % 8) * 8);
return ret;
}
-data_t vm_mov_word(vm_t *vm, word reg)
+data_t vm_mov_hword(vm_t *vm, byte reg)
{
- if (reg >= VM_WORD_REGISTERS)
- // TODO: Error (reg is not a valid word register)
- return DWORD(0);
- else if (vm->stack.ptr < sizeof(word))
+ if (reg >= VM_REGISTERS)
+ // TODO: Error (reg is not a valid hword register)
+ return DHWORD(0);
+ else if (vm->stack.ptr < sizeof(f64))
// TODO: Error (STACK UNDERFLOW)
- return DWORD(0);
- data_t ret = vm_pop_word(vm);
- vm->registers.w[reg] = ret.as_word;
+ return DHWORD(0);
+ data_t ret = vm_pop_hword(vm);
+ word *reg_ptr = &vm->registers.reg[reg / 2];
+ *reg_ptr = (*reg_ptr) | ((word)ret.as_word) << ((reg % 2) * 2);
return ret;
}
-data_t vm_mov_float(vm_t *vm, word reg)
+data_t vm_mov_word(vm_t *vm, byte reg)
{
- if (reg >= VM_WORD_REGISTERS)
- // TODO: Error (reg is not a valid float register)
- return DFLOAT(0);
- else if (vm->stack.ptr < sizeof(f64))
+ if (reg >= VM_REGISTERS)
+ // TODO: Error (reg is not a valid word register)
+ return DWORD(0);
+ else if (vm->stack.ptr < sizeof(word))
// TODO: Error (STACK UNDERFLOW)
- return DFLOAT(0);
- data_t ret = vm_pop_float(vm);
- vm->registers.f[reg] = ret.as_float;
+ return DWORD(0);
+ data_t ret = vm_pop_word(vm);
+ vm->registers.reg[reg] = ret.as_word;
return ret;
}
@@ -290,6 +297,20 @@ data_t vm_pop_byte(vm_t *vm)
return DBYTE(vm->stack.data[--vm->stack.ptr]);
}
+data_t vm_pop_hword(vm_t *vm)
+{
+ if (vm->stack.ptr < HWORD_SIZE)
+ // TODO: Error STACK_UNDERFLOW
+ return DHWORD(0);
+ hword h = 0;
+ for (size_t i = 0; i < HWORD_SIZE; ++i)
+ {
+ data_t b = vm_pop_byte(vm);
+ h = h | ((word)(b.as_byte) << (i * 8));
+ }
+ return DWORD(h);
+}
+
data_t vm_pop_word(vm_t *vm)
{
if (vm->stack.ptr < WORD_SIZE)
@@ -303,16 +324,3 @@ data_t vm_pop_word(vm_t *vm)
}
return DWORD(w);
}
-
-data_t vm_pop_float(vm_t *vm)
-{
- if (vm->stack.ptr < FLOAT_SIZE)
- // TODO: Error STACK_UNDERFLOW
- return DFLOAT(0);
- f64 f = 0;
- // TODO: Make this machine independent (encode IEEE754 floats
- // yourself?)
- memcpy(&f, vm->stack.data + vm->stack.ptr - FLOAT_SIZE, FLOAT_SIZE);
- vm->stack.ptr -= FLOAT_SIZE;
- return DFLOAT(f);
-}
diff --git a/src/runtime.h b/src/runtime.h
index f512992..e588541 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -19,17 +19,13 @@
#include "./base.h"
#include "./inst.h"
-#define VM_BYTE_REGISTERS 8
-#define VM_WORD_REGISTERS 8
-#define VM_FLOAT_REGISTERS 8
+#define VM_REGISTERS 8
typedef struct
{
struct Registers
{
word ret;
- byte b[VM_BYTE_REGISTERS];
- word w[VM_WORD_REGISTERS];
- f64 f[VM_FLOAT_REGISTERS];
+ word reg[VM_REGISTERS];
} registers;
struct Stack
{
@@ -43,6 +39,10 @@ typedef struct
} program;
} vm_t;
+#define VM_REG_BYTE(REG) ((REG)&0b11111111)
+#define VM_REG_HWORD(REG) ((REG)&0b11111111111111111111111111111111)
+#define VM_REG_WORD(REG) ((REG))
+
void vm_execute(vm_t *);
void vm_load_stack(vm_t *, byte *, size_t);
@@ -56,47 +56,47 @@ void vm_print_program(vm_t *, FILE *);
void vm_print_all(vm_t *, FILE *);
void vm_push_byte(vm_t *, data_t);
+void vm_push_hword(vm_t *, data_t);
void vm_push_word(vm_t *, data_t);
-void vm_push_float(vm_t *, data_t);
typedef void (*push_f)(vm_t *, data_t);
static const push_f PUSH_ROUTINES[] = {
[OP_PUSH_BYTE] = vm_push_byte,
+ [OP_PUSH_HWORD] = vm_push_hword,
[OP_PUSH_WORD] = vm_push_word,
- [OP_PUSH_FLOAT] = vm_push_float,
};
-void vm_push_byte_register(vm_t *, word);
-void vm_push_word_register(vm_t *, word);
-void vm_push_float_register(vm_t *, word);
+void vm_push_byte_register(vm_t *, byte);
+void vm_push_hword_register(vm_t *, byte);
+void vm_push_word_register(vm_t *, byte);
-typedef void (*push_reg_f)(vm_t *, word);
+typedef void (*push_reg_f)(vm_t *, byte);
static const push_reg_f PUSH_REG_ROUTINES[] = {
- [OP_PUSH_BYTE_REGISTER] = vm_push_byte_register,
- [OP_PUSH_WORD_REGISTER] = vm_push_word_register,
- [OP_PUSH_FLOAT_REGISTER] = vm_push_float_register,
+ [OP_PUSH_REGISTER_BYTE] = vm_push_byte_register,
+ [OP_PUSH_REGISTER_HWORD] = vm_push_hword_register,
+ [OP_PUSH_REGISTER_WORD] = vm_push_word_register,
};
-data_t vm_mov_byte(vm_t *, word);
-data_t vm_mov_word(vm_t *, word);
-data_t vm_mov_float(vm_t *, word);
+data_t vm_mov_byte(vm_t *, byte);
+data_t vm_mov_hword(vm_t *, byte);
+data_t vm_mov_word(vm_t *, byte);
-typedef data_t (*mov_f)(vm_t *, word);
+typedef data_t (*mov_f)(vm_t *, byte);
static const mov_f MOV_ROUTINES[] = {
[OP_MOV_BYTE] = vm_mov_byte,
+ [OP_MOV_HWORD] = vm_mov_hword,
[OP_MOV_WORD] = vm_mov_word,
- [OP_MOV_FLOAT] = vm_mov_float,
};
data_t vm_pop_byte(vm_t *);
+data_t vm_pop_hword(vm_t *);
data_t vm_pop_word(vm_t *);
-data_t vm_pop_float(vm_t *);
typedef data_t (*pop_f)(vm_t *);
static const pop_f POP_ROUTINES[] = {
[OP_POP_BYTE] = vm_pop_byte,
+ [OP_POP_HWORD] = vm_pop_hword,
[OP_POP_WORD] = vm_pop_word,
- [OP_POP_FLOAT] = vm_pop_float,
};
#endif