diff options
-rw-r--r-- | src/base.h | 14 | ||||
-rw-r--r-- | src/inst.c | 134 | ||||
-rw-r--r-- | src/inst.h | 56 | ||||
-rw-r--r-- | src/runtime.c | 170 | ||||
-rw-r--r-- | src/runtime.h | 44 |
5 files changed, 195 insertions, 223 deletions
@@ -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) @@ -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 @@ -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 |