From f818b5548ef696d31b0fa1e72d33280a459885c4 Mon Sep 17 00:00:00 2001 From: Giulio De Pasquale Date: Sun, 14 May 2017 22:10:58 +0200 Subject: [PATCH] MOVI,MOVR,PUTM,GETM,ADDI --- .gitignore | 1 + cpp/emulator.cpp | 16 ++----- cpp/vm.cpp | 118 ++++++++++++++++++++++++++++++++++++++++++++++- cpp/vm.h | 31 +++++++++---- cpp/vmas.cpp | 85 ++++++++++++++++++++++++++++------ cpp/vmas.h | 18 ++++++-- 6 files changed, 227 insertions(+), 42 deletions(-) diff --git a/.gitignore b/.gitignore index f47cb20..a6ac9c9 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.out +.vscode/ diff --git a/cpp/emulator.cpp b/cpp/emulator.cpp index 7aed252..e0535f0 100644 --- a/cpp/emulator.cpp +++ b/cpp/emulator.cpp @@ -8,19 +8,9 @@ using namespace std; int main() { - ifstream vmbytecode; - VM vm; - uint8_t *data; - + VM vm((uint8_t*)"\x00\x00\x50\x50\x03\x10\x00\x00\x02\x04\x10\x00\x04\x04\x01\x00\x13", 107); + vm.run(); + printf("\n\n"); vm.status(); - // vm.status(); - /* - if (vmbytecode != NULL) { - fread() - } else { - fprintf(stderr, "Couldn't open bytecode!\n"); - return 1; - } - */ return 0; } \ No newline at end of file diff --git a/cpp/vm.cpp b/cpp/vm.cpp index 2ec5f0e..1f7c04e 100644 --- a/cpp/vm.cpp +++ b/cpp/vm.cpp @@ -3,15 +3,21 @@ #include "vmas.h" #include +/* +CONSTRUCTORS +*/ VM::VM() { DBG_INFO(("Creating VM without code.\n")); + as.allocate(); init_regs(); } VM::VM(uint8_t *code, uint32_t codesize) { DBG_INFO(("Creating VM with code.\n")); + if (as.allocate()) { + as.insCode(code, codesize); + } init_regs(); - as.insCode(code, codesize); } void VM::init_regs(void) { @@ -68,4 +74,112 @@ void VM::status(void) { return; } -void VM::run(uint8_t *code) { return; } \ No newline at end of file +/* +INSTRUCTIONS IMPLEMENTATIONS +*/ + +void VM::exec_movi(void) { + /* + MOVI R0, 0x2400 | R0 = 0x2400 + */ + uint8_t dst; + uint16_t imm; + dst = as.code[regs[IP] + 1]; + imm = *((uint16_t *)&as.code[regs[IP] + 2]); + DBG_INFO(("MOVI 0x%x 0x%x\n", dst, imm)); + regs[dst] = imm; + return; +} + +void VM::exec_movr(void) { + /* + MOVR R1, R0 | R1 = R0 + --------------------- + R1, R0 = 0x10 <- DST / SRC are nibbles! + */ + uint8_t dst, src; + dst = as.code[regs[IP] + 1] >> 4; + src = as.code[regs[IP] + 1] & 0b00001111; + DBG_INFO(("MOVR 0x%x 0x%x\n", dst, src)); + regs[dst] = regs[src]; + return; +} + +void VM::exec_getm(void) { + /* + GETM R0, 0x1000 | R0 = data[0x1000] + */ + uint8_t dst; + uint16_t src; + dst = as.code[regs[IP] + 1]; + src = *((uint16_t *)&as.code[regs[IP] + 2]); + DBG_INFO(("GETM 0x%x 0x%x\n", dst, src)); + regs[dst] = *((uint16_t *)&as.data[src]); + return; +} + +void VM::exec_putm(void) { + /* + PUTM 0x1000, R0 | data[0x1000] = R0 + */ + uint16_t dst; + uint8_t src; + dst = *((uint16_t *)&as.code[regs[IP] + 1]); + src = as.code[regs[IP] + 3]; + DBG_INFO(("PUTM 0x%x 0x%x\n", dst, src)); + *((uint16_t *)&as.data[dst]) = regs[src]; + return; +} + +void VM::exec_addi(void) { + /* + ADDI R0, 0x2 | R0 += 2 + */ + uint8_t dst; + uint16_t src; + + dst = as.code[regs[IP] + 1]; + src = *((uint16_t *)&as.code[regs[IP] + 2]); + DBG_INFO(("ADDI 0x%x 0x%x\n", dst, src)); + regs[dst] += src; + return; +} + +void VM::run(void) { + uint8_t opcode; + bool finished = false; + while (!finished) { + opcode = (uint8_t)as.code[regs[IP]]; + switch (opcode) { + case MOVI: + exec_movi(); + regs[IP] += MOVI_SIZE; + break; + case MOVR: + exec_movr(); + regs[IP] += MOVR_SIZE; + break; + case GETM: + exec_getm(); + regs[IP] += GETM_SIZE; + break; + case PUTM: + exec_putm(); + regs[IP] += PUTM_SIZE; + break; + case ADDI: + exec_addi(); + regs[IP] += ADDI_SIZE; + break; + case HALT: + DBG_INFO(("HALT\n")); + finished = true; + break; + default: + DBG_INFO(("WAT: 0x%x\n", opcode)); + return; + break; + } + } + return; +} \ No newline at end of file diff --git a/cpp/vm.h b/cpp/vm.h index 0316583..dd93b26 100644 --- a/cpp/vm.h +++ b/cpp/vm.h @@ -1,32 +1,35 @@ #ifndef VM_H #define VM_H -#include #include "vmas.h" +#include +#define MOVI_SIZE 4 +#define MOVR_SIZE 2 +#define GETM_SIZE 4 +#define PUTM_SIZE 4 +#define ADDI_SIZE 4 enum regs { R0, R1, R2, R3, S0, S1, S2, S3, IP, BP, SP }; +/* +MEMORY LOCATIONS AND IMMEDIATES ARE 16 BITS LONG +*/ enum ins { MOVI, MOVR, - MOVM, + GETM, + PUTM, ADDI, ADDR, - ADDM, SUBI, SUBR, - SUBM, XORI, XORR, - XORM, NOTI, NOTR, - NOTM, MULI, MULR, - MULM, DIVI, DIVR, - DIVM, PUSH, POOP, CALL, @@ -35,19 +38,29 @@ enum ins { }; class VM { +private: uint16_t regs[0xb]; struct flags { uint8_t zf : 1; uint8_t cf : 1; }; VMAddrSpace as; + /* + IMPLEMENTATIONS + */ + void exec_movi(void); + void exec_movr(void); + void exec_movm(void); + void exec_getm(void); + void exec_putm(void); + void exec_addi(void); public: VM(); VM(uint8_t *code, uint32_t codesize); void init_regs(void); void status(void); - void run(uint8_t *code); + void run(); }; #endif \ No newline at end of file diff --git a/cpp/vmas.cpp b/cpp/vmas.cpp index f6a7ff2..c547f2b 100644 --- a/cpp/vmas.cpp +++ b/cpp/vmas.cpp @@ -1,22 +1,81 @@ -#include -#include #include "vmas.h" #include "debug.h" +#include +#include +#include -void VMAddrSpace::insCode(uint8_t * buf, uint8_t size) { - DBG_INFO(("Copying buffer into code section.\n")); - memcpy(&this->code, buf, size); - return; +VMAddrSpace::VMAddrSpace() { + stacksize = DEFAULT_STACKSIZE; + codesize = DEFAULT_CODESIZE; + datasize = DEFAULT_DATASIZE; + return; } -void VMAddrSpace::insStack(uint8_t * buf, uint8_t size) { - DBG_INFO(("Copying buffer into code section.\n")); - memcpy(&this->stack, buf, size); - return; +VMAddrSpace::VMAddrSpace(uint32_t ss, uint32_t cs, uint32_t ds) { + stacksize = ss; + codesize = cs; + datasize = ds; + return; } -void VMAddrSpace::insData(uint8_t * buf, uint8_t size) { +bool VMAddrSpace::allocate(void) { + DBG_INFO(("Allocating sections...\n")); + if (code == NULL) { + code = (uint8_t *)malloc(codesize); + } + if (data == NULL) { + data = (uint8_t *)malloc(datasize); + } + if (stack == NULL) { + stack = (uint8_t *)malloc(stacksize); + } + if (code == NULL) { + DBG_ERROR(("Couldn't allocate code section.\n")); + return false; + } + data = (uint8_t *)malloc(datasize); + if (data == NULL) { + DBG_ERROR(("Couldn't allocate data section.\n")); + return false; + } + stack = (uint8_t *)malloc(stacksize); + if (stack == NULL) { + DBG_ERROR(("Couldn't allocate stack section.\n")); + return false; + } + DBG_SUCC(("Done!\n")); + return true; +} + +bool VMAddrSpace::insCode(uint8_t *buf, uint8_t size) { + if (code) { + DBG_INFO(("Copying buffer into code section.\n")); + memcpy(code, buf, size); + } else { + DBG_ERROR(("Couldn't write into code section.\n")); + return false; + } + return true; +} + +bool VMAddrSpace::insStack(uint8_t *buf, uint8_t size) { + if (stack) { + DBG_INFO(("Copying buffer into stack section.\n")); + memcpy(stack, buf, size); + } else { + DBG_ERROR(("Couldn't write into stack section.\n")); + return false; + } + return true; +} + +bool VMAddrSpace::insData(uint8_t *buf, uint8_t size) { + if (this->code) { DBG_INFO(("Copying buffer into data section.\n")); - memcpy(&this->data, buf, size); - return; + memcpy(data, buf, size); + } else { + DBG_ERROR(("Couldn't write into data section.\n")); + return false; + } + return true; } \ No newline at end of file diff --git a/cpp/vmas.h b/cpp/vmas.h index 730123d..68bd2d6 100644 --- a/cpp/vmas.h +++ b/cpp/vmas.h @@ -1,14 +1,22 @@ #ifndef VMAS_H #define VMAS_H +#include +#define DEFAULT_STACKSIZE 0x100 +#define DEFAULT_CODESIZE 0x300 +#define DEFAULT_DATASIZE 0x100 class VMAddrSpace { - uint8_t stack[0x100], code[0x300], data[0x500]; +private: + uint32_t stacksize, codesize, datasize; public: - void assemble(void); - void insStack(uint8_t *buf, uint8_t size); - void insCode(uint8_t *buf, uint8_t size); - void insData(uint8_t *buf, uint8_t size); + VMAddrSpace(); + VMAddrSpace(uint32_t ss, uint32_t cs, uint32_t ds); + uint8_t *stack, *code, *data; + bool allocate(void); + bool insStack(uint8_t *buf, uint8_t size); + bool insCode(uint8_t *buf, uint8_t size); + bool insData(uint8_t *buf, uint8_t size); }; #endif \ No newline at end of file