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.
This commit is contained in:
184
src/runtime.c
184
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)
|
||||
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;
|
||||
// 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_word_register(vm_t *vm, byte reg)
|
||||
{
|
||||
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_word(vm, DWORD(vm->registers.w[reg]));
|
||||
vm_push_word(vm, DWORD(vm->registers.reg[reg]));
|
||||
}
|
||||
|
||||
void vm_push_float_register(vm_t *vm, word reg)
|
||||
data_t vm_mov_byte(vm_t *vm, byte reg)
|
||||
{
|
||||
if (reg >= VM_FLOAT_REGISTERS)
|
||||
// TODO: Error (reg is not a valid float register)
|
||||
return;
|
||||
else if (vm->stack.ptr >= vm->stack.max)
|
||||
// TODO: Error STACK_OVERFLOW
|
||||
return;
|
||||
vm_push_float(vm, DFLOAT(vm->registers.f[reg]));
|
||||
}
|
||||
|
||||
data_t vm_mov_byte(vm_t *vm, word 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)
|
||||
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 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_word(vm_t *vm, byte reg)
|
||||
{
|
||||
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 DWORD(0);
|
||||
data_t ret = vm_pop_word(vm);
|
||||
vm->registers.w[reg] = ret.as_word;
|
||||
return ret;
|
||||
}
|
||||
|
||||
data_t vm_mov_float(vm_t *vm, word 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))
|
||||
// TODO: Error (STACK UNDERFLOW)
|
||||
return DFLOAT(0);
|
||||
data_t ret = vm_pop_float(vm);
|
||||
vm->registers.f[reg] = ret.as_float;
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user