Compare commits
2 Commits
a0cd944080
...
f1060ff86c
Author | SHA1 | Date | |
---|---|---|---|
|
f1060ff86c | ||
|
f818b5548e |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
*.out
|
||||
.vscode/
|
||||
|
@ -8,19 +8,10 @@
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
ifstream vmbytecode;
|
||||
VM vm;
|
||||
uint8_t *data;
|
||||
|
||||
uint8_t bytecode[] = "\x00\x00\x00";
|
||||
VM vm(bytecode, sizeof(bytecode));
|
||||
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;
|
||||
}
|
118
cpp/vm.cpp
118
cpp/vm.cpp
@ -3,15 +3,21 @@
|
||||
#include "vmas.h"
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
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; }
|
||||
/*
|
||||
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));
|
||||
finished = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
31
cpp/vm.h
31
cpp/vm.h
@ -1,32 +1,35 @@
|
||||
#ifndef VM_H
|
||||
#define VM_H
|
||||
#include <stdint.h>
|
||||
#include "vmas.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
98
cpp/vmas.cpp
98
cpp/vmas.cpp
@ -1,22 +1,94 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "vmas.h"
|
||||
#include "debug.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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() {
|
||||
stack = NULL;
|
||||
code = NULL;
|
||||
data = NULL;
|
||||
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) {
|
||||
stack = NULL;
|
||||
code = NULL;
|
||||
data = NULL;
|
||||
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) {
|
||||
DBG_INFO(("\tcode...\n"));
|
||||
code = (uint8_t *)malloc(codesize);
|
||||
}
|
||||
if (data == NULL) {
|
||||
DBG_INFO(("\tdata...\n"));
|
||||
data = (uint8_t *)malloc(datasize);
|
||||
}
|
||||
if (stack == NULL) {
|
||||
DBG_INFO(("\tstack...\n"));
|
||||
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;
|
||||
}
|
||||
memset(code, 0xff,
|
||||
stacksize); // auto halt in case the assembly is not correct
|
||||
memset(stack, 0x0, stacksize);
|
||||
memset(data, 0x0, stacksize);
|
||||
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;
|
||||
}
|
18
cpp/vmas.h
18
cpp/vmas.h
@ -1,14 +1,22 @@
|
||||
#ifndef VMAS_H
|
||||
#define VMAS_H
|
||||
#include <stdint.h>
|
||||
#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
|
Loading…
Reference in New Issue
Block a user