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 | 
