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:
2023-10-21 22:57:43 +01:00
parent 266b4e4572
commit dcedb70a5c
5 changed files with 201 additions and 229 deletions

View File

@@ -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);
}