From eff07ba78394d89ebb1026ce849035afca9c9b08 Mon Sep 17 00:00:00 2001 From: Jeremiah Orians Date: Sun, 29 May 2016 13:13:24 -0400 Subject: [PATCH] Minor refactor and started to add opcode/XOPs --- vm.c | 207 ++++++++++++++++++++++++++++------------------------------- vm.h | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 273 insertions(+), 109 deletions(-) create mode 100644 vm.h diff --git a/vm.c b/vm.c index 85892ca..03f0cb2 100644 --- a/vm.c +++ b/vm.c @@ -1,50 +1,5 @@ -#include -#include -#include -#include -#include - -/* Virtual machine state */ -struct lilith -{ - uint64_t *memory; - uint64_t reg[16]; - uint64_t ip; - bool halted; - bool exception; -}; - -struct Instruction -{ - uint64_t ip; - uint8_t opcode; - uint32_t XOP; - uint32_t Immediate; - uint32_t HAL_CODE; - uint8_t reg0; - uint8_t reg1; - uint8_t reg2; - uint8_t reg3; - bool invalid; -}; - -/* Allocate and intialize memory/state */ -struct lilith* create_vm(size_t size) -{ - struct lilith* vm; - vm = calloc(1, sizeof(struct lilith)); - vm->memory = calloc(size, sizeof(uint8_t)); - vm->halted = false; - vm->exception = false; - return vm; -} - -/* Free up the memory we previously allocated */ -void destroy_vm(struct lilith* vm) -{ - free(vm->memory); - free(vm); -} +#include "vm.h" +#define DEBUG true; /* Load program tape into Memory */ void load_program(struct lilith* vm, char **argv) @@ -63,107 +18,140 @@ void load_program(struct lilith* vm, char **argv) fclose(program); } +/* Load instruction addressed at IP */ void read_instruction(struct lilith* vm, struct Instruction *current) { memset(current, 0, sizeof(struct Instruction)); - uint8_t opcode, segment1, segment2, segment3; - /* Store IP for debugging */ current->ip = vm->ip; /* Read the actual bytes and increment the IP */ - opcode = vm->memory[vm->ip]; + current->raw0 = (uint8_t)vm->memory[vm->ip]; vm->ip = vm->ip + 1; - segment1 = vm->memory[vm->ip]; + current->raw1 = (uint8_t)vm->memory[vm->ip]; vm->ip = vm->ip + 1; - segment2 = vm->memory[vm->ip]; + current->raw2 = (uint8_t)vm->memory[vm->ip]; vm->ip = vm->ip + 1; - segment3 = vm->memory[vm->ip]; + current->raw3 = (uint8_t)vm->memory[vm->ip]; vm->ip = vm->ip + 1; + unpack_instruction(current); +} - /* The first byte is always the master opcode */ - current->opcode = opcode; - current->invalid = false; - current->XOP = 0xFFFF; - current->Immediate = 0xFFFF; - current->HAL_CODE = 0xFFFF; - current->reg0 = 0xFF; - current->reg1 = 0xFF; - current->reg2 = 0xFF; - current->reg3 = 0xFF; +/* Process 4OP Integer instructions */ +bool eval_4OP_Int(struct lilith* vm, struct Instruction* c) +{ + return true; +} - /* Extract the fields from the instruction for easier evaluation */ - switch(opcode) +/* Process 3OP Integer instructions */ +bool eval_3OP_Int(struct lilith* vm, struct Instruction* c) +{ + switch(c->raw_XOP) + { + case 0x000: /* ADD */ + { + vm->reg[c->reg0] = vm->reg[c->reg1] + vm->reg[c->reg2]; + break; + } + default: return true; + } + return false; +} + +/* Process 2OP Integer instructions */ +bool eval_2OP_Int(struct lilith* vm, struct Instruction* c) +{ + return true; +} + +/* Process 1OP Integer instructions */ +bool eval_1OP_Int(struct lilith* vm, struct Instruction* c) +{ + return true; +} + +/* Process 2OPI Integer instructions */ +bool eval_2OPI_Int(struct lilith* vm, struct Instruction* c) +{ + /* 0x0E ... 0x2B */ + switch(c->raw0) + { + case 0x0E: /* ADDI */ + { + vm->reg[c->reg0] = (int8_t)(vm->reg[c->reg1] + c->raw_Immediate); + break; + } + case 0x0F: /* ADDUI */ + { + vm->reg[c->reg0] = vm->reg[c->reg1] + c->raw_Immediate; break; + } + default: return true; + } + return false; +} + +/* Use Opcode to decide what to do and then have it done */ +void eval_instruction(struct lilith* vm, struct Instruction* current) +{ + bool invalid = false; + + switch(current->raw0) { case 0x00: /* Deal with NOPs */ { + vm->halted = true; + return; + } + case 0x01: + { + decode_4OP(current); + invalid = eval_4OP_Int(vm, current); + if ( invalid) goto fail; break; } - case 0x01 ... 0x04: /* Deal with 4OP */ + case 0x05: { - current->XOP = segment1; - current->Immediate = 0; - current->reg0 = segment2/16; - current->reg1 = segment2%16; - current->reg2 = segment3/16; - current->reg3 = segment3%16; + decode_3OP(current); + invalid = eval_3OP_Int(vm, current); + if ( invalid) goto fail; break; } - case 0x05 ... 0x08: /* Deal with 3OP */ + case 0x09: { - current->XOP = segment1*16 + segment2/16; - current->Immediate = 0; - current->reg0 = segment2%16; - current->reg1 = segment3/16; - current->reg2 = segment3%16; + decode_2OP(current); + invalid = eval_2OP_Int(vm, current); + if ( invalid) goto fail; break; } - case 0x09 ... 0x0C: /* Deal with 2OP */ + case 0x0D: { - current->XOP = segment1*256 + segment2; - current->Immediate = 0; - current->reg0 = segment3/16; - current->reg1 = segment3%16; + decode_1OP(current); + invalid = eval_1OP_Int(vm, current); + if ( invalid) goto fail; break; } - case 0x0D: /* Deal with 1OP */ + case 0x0E ... 0x2B: { - current->XOP = segment1*4096 + segment2*16 + segment3/16; - current->Immediate = 0; - current->reg0 = segment3%16; + decode_2OPI(current); + invalid = eval_2OPI_Int(vm, current); + if ( invalid) goto fail; break; } - case 0x0E ... 0x2B: /* Deal with 2OPI */ + case 0x2C: { - current->XOP = 0; - current->Immediate = segment2*256 + segment3; - current->reg0 = segment1/16; - current->reg1 = segment1%16; - break; } - case 0x2C ... 0x3B: /* Deal with 1OPI */ + case 0x3C: { - current->XOP = 0; - current->Immediate = (segment1%16)*4096 + segment2*256 + segment3; - current->HAL_CODE = 0; - current->reg0 = segment1/16; - break; } - case 0x3C: /* Deal with 0OPI */ + case 0x42: { - current->XOP = 0; - current->Immediate = segment1*4096 + segment2*256 + segment3; - break; - } - case 0x42: /* Deal with Halcode */ - { - current->XOP = 0; - current->HAL_CODE = segment1*4096 + segment2*256 + segment3; - break; } case 0xFF: /* Deal with illegal instruction */ default: { +fail: + fprintf(stderr, "Unable to execute the following instruction:\n%c %c %c %c\n", current->raw0, current->raw1, current->raw2, current->raw3); + fprintf(stderr, "%s\n", current->operation); current->invalid = true; break; } @@ -178,6 +166,7 @@ void execute_vm(struct lilith* vm) while(!vm->halted) { read_instruction(vm, current); + eval_instruction(vm, current); } free(current); diff --git a/vm.h b/vm.h new file mode 100644 index 0000000..4c2dbf5 --- /dev/null +++ b/vm.h @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include + +/* Virtual machine state */ +struct lilith +{ + uint8_t *memory; + uint64_t reg[16]; + uint64_t ip; + bool halted; + bool exception; +}; + +/* Unpacked instruction */ +struct Instruction +{ + uint64_t ip; + uint8_t raw0, raw1, raw2, raw3; + char opcode[3]; + uint32_t raw_XOP; + char XOP[6]; + char operation[9]; + uint32_t raw_Immediate; + char Immediate[7]; + uint32_t HAL_CODE; + uint8_t reg0; + uint8_t reg1; + uint8_t reg2; + uint8_t reg3; + bool invalid; +}; + +/* Condition Codes */ +enum condition +{ +Carry = 1 << 5, +Borrow = 1 << 4, +Overflow = 1 << 3, +GreaterThan = 1 << 2, +EQual = 1 << 1, +LessThan = 1 +}; + +/* Allocate and intialize memory/state */ +struct lilith* create_vm(size_t size) +{ + struct lilith* vm; + vm = calloc(1, sizeof(struct lilith)); + vm->memory = calloc(size, sizeof(uint8_t)); + vm->halted = false; + vm->exception = false; + return vm; +} + +/* Free up the memory we previously allocated */ +void destroy_vm(struct lilith* vm) +{ + free(vm->memory); + free(vm); +} + +/* Deal with 4OP */ +void decode_4OP(struct Instruction* c) +{ + c->raw_XOP = c->raw1; + c->XOP[0] = c->operation[2]; + c->XOP[1] = c->operation[3]; + c->raw_Immediate = 0; + c->reg0 = c->raw2/16; + c->reg1 = c->raw2%16; + c->reg2 = c->raw3/16; + c->reg3 = c->raw3%16; +} + +/* Deal with 3OP */ +void decode_3OP(struct Instruction* c) +{ + c->raw_XOP = c->raw1*16 + c->raw2/16; + c->XOP[0] = c->operation[2]; + c->XOP[1] = c->operation[3]; + c->XOP[2] = c->operation[4]; + c->raw_Immediate = 0; + c->reg0 = c->raw2%16; + c->reg1 = c->raw3/16; + c->reg2 = c->raw3%16; +} + +/* Deal with 2OP */ +void decode_2OP(struct Instruction* c) +{ + c->raw_XOP = c->raw1*256 + c->raw2; + c->XOP[0] = c->operation[2]; + c->XOP[1] = c->operation[3]; + c->XOP[2] = c->operation[4]; + c->XOP[3] = c->operation[5]; + c->raw_Immediate = 0; + c->reg0 = c->raw3/16; + c->reg1 = c->raw3%16; +} + +/* Deal with 1OP */ +void decode_1OP(struct Instruction* c) +{ + c->raw_XOP = c->raw1*4096 + c->raw2*16 + c->raw3/16; + c->XOP[0] = c->operation[2]; + c->XOP[1] = c->operation[3]; + c->XOP[2] = c->operation[4]; + c->XOP[3] = c->operation[5]; + c->XOP[4] = c->operation[6]; + c->raw_Immediate = 0; + c->reg0 = c->raw3%16; +} + +/* Deal with 2OPI */ +void decode_2OPI(struct Instruction* c) +{ + c->raw_Immediate = c->raw2*256 + c->raw3; + c->Immediate[0] = c->operation[4]; + c->Immediate[1] = c->operation[5]; + c->Immediate[2] = c->operation[6]; + c->Immediate[3] = c->operation[7]; + c->reg0 = c->raw1/16; + c->reg1 = c->raw1%16; +} + +/* Deal with 1OPI */ +void decode_1OPI(struct Instruction* c) +{ + c->raw_Immediate = (c->raw1%16)*4096 + c->raw2*256 + c->raw3; + c->Immediate[0] = c->operation[3]; + c->Immediate[1] = c->operation[4]; + c->Immediate[2] = c->operation[5]; + c->Immediate[3] = c->operation[6]; + c->Immediate[4] = c->operation[7]; + c->HAL_CODE = 0; + c->reg0 = c->raw1/16; +} +/* Deal with 0OPI */ +void decode_0OPI(struct Instruction* c) +{ + c->raw_Immediate = c->raw1*4096 + c->raw2*256 + c->raw3; + c->Immediate[0] = c->operation[2]; + c->Immediate[1] = c->operation[3]; + c->Immediate[2] = c->operation[4]; + c->Immediate[3] = c->operation[5]; + c->Immediate[4] = c->operation[6]; + c->Immediate[5] = c->operation[7]; +} + +/* Deal with Halcode */ +void decode_HALCODE(struct Instruction* c) +{ + c->HAL_CODE = c->raw1*4096 + c->raw2*256 + c->raw3; +} + +/* Useful unpacking functions */ +void unpack_byte(uint8_t a, char* c) +{ + char table[16] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46}; + c[0] = table[a / 16]; + c[1] = table[a % 16]; +} + +void unpack_instruction(struct Instruction* c) +{ + unpack_byte(c->raw0, &(c->operation[0])); + unpack_byte(c->raw1, &(c->operation[2])); + unpack_byte(c->raw2, &(c->operation[4])); + unpack_byte(c->raw3, &(c->operation[6])); + c->opcode[0] = c->operation[0]; + c->opcode[1] = c->operation[1]; +}