aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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