Compare commits
2 Commits
a0cd944080
...
f1060ff86c
Author | SHA1 | Date | |
---|---|---|---|
|
f1060ff86c | ||
|
f818b5548e |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
*.out
|
*.out
|
||||||
|
.vscode/
|
||||||
|
@ -8,19 +8,10 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
ifstream vmbytecode;
|
uint8_t bytecode[] = "\x00\x00\x00";
|
||||||
VM vm;
|
VM vm(bytecode, sizeof(bytecode));
|
||||||
uint8_t *data;
|
vm.run();
|
||||||
|
printf("\n\n");
|
||||||
vm.status();
|
vm.status();
|
||||||
// vm.status();
|
|
||||||
/*
|
|
||||||
if (vmbytecode != NULL) {
|
|
||||||
fread()
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Couldn't open bytecode!\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
118
cpp/vm.cpp
118
cpp/vm.cpp
@ -3,15 +3,21 @@
|
|||||||
#include "vmas.h"
|
#include "vmas.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
CONSTRUCTORS
|
||||||
|
*/
|
||||||
VM::VM() {
|
VM::VM() {
|
||||||
DBG_INFO(("Creating VM without code.\n"));
|
DBG_INFO(("Creating VM without code.\n"));
|
||||||
|
as.allocate();
|
||||||
init_regs();
|
init_regs();
|
||||||
}
|
}
|
||||||
|
|
||||||
VM::VM(uint8_t *code, uint32_t codesize) {
|
VM::VM(uint8_t *code, uint32_t codesize) {
|
||||||
DBG_INFO(("Creating VM with code.\n"));
|
DBG_INFO(("Creating VM with code.\n"));
|
||||||
|
if (as.allocate()) {
|
||||||
|
as.insCode(code, codesize);
|
||||||
|
}
|
||||||
init_regs();
|
init_regs();
|
||||||
as.insCode(code, codesize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VM::init_regs(void) {
|
void VM::init_regs(void) {
|
||||||
@ -68,4 +74,112 @@ void VM::status(void) {
|
|||||||
return;
|
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
|
#ifndef VM_H
|
||||||
#define VM_H
|
#define VM_H
|
||||||
#include <stdint.h>
|
|
||||||
#include "vmas.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 };
|
enum regs { R0, R1, R2, R3, S0, S1, S2, S3, IP, BP, SP };
|
||||||
|
|
||||||
|
/*
|
||||||
|
MEMORY LOCATIONS AND IMMEDIATES ARE 16 BITS LONG
|
||||||
|
*/
|
||||||
enum ins {
|
enum ins {
|
||||||
MOVI,
|
MOVI,
|
||||||
MOVR,
|
MOVR,
|
||||||
MOVM,
|
GETM,
|
||||||
|
PUTM,
|
||||||
ADDI,
|
ADDI,
|
||||||
ADDR,
|
ADDR,
|
||||||
ADDM,
|
|
||||||
SUBI,
|
SUBI,
|
||||||
SUBR,
|
SUBR,
|
||||||
SUBM,
|
|
||||||
XORI,
|
XORI,
|
||||||
XORR,
|
XORR,
|
||||||
XORM,
|
|
||||||
NOTI,
|
NOTI,
|
||||||
NOTR,
|
NOTR,
|
||||||
NOTM,
|
|
||||||
MULI,
|
MULI,
|
||||||
MULR,
|
MULR,
|
||||||
MULM,
|
|
||||||
DIVI,
|
DIVI,
|
||||||
DIVR,
|
DIVR,
|
||||||
DIVM,
|
|
||||||
PUSH,
|
PUSH,
|
||||||
POOP,
|
POOP,
|
||||||
CALL,
|
CALL,
|
||||||
@ -35,19 +38,29 @@ enum ins {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class VM {
|
class VM {
|
||||||
|
private:
|
||||||
uint16_t regs[0xb];
|
uint16_t regs[0xb];
|
||||||
struct flags {
|
struct flags {
|
||||||
uint8_t zf : 1;
|
uint8_t zf : 1;
|
||||||
uint8_t cf : 1;
|
uint8_t cf : 1;
|
||||||
};
|
};
|
||||||
VMAddrSpace as;
|
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:
|
public:
|
||||||
VM();
|
VM();
|
||||||
VM(uint8_t *code, uint32_t codesize);
|
VM(uint8_t *code, uint32_t codesize);
|
||||||
void init_regs(void);
|
void init_regs(void);
|
||||||
void status(void);
|
void status(void);
|
||||||
void run(uint8_t *code);
|
void run();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
98
cpp/vmas.cpp
98
cpp/vmas.cpp
@ -1,22 +1,94 @@
|
|||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "vmas.h"
|
#include "vmas.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
void VMAddrSpace::insCode(uint8_t * buf, uint8_t size) {
|
VMAddrSpace::VMAddrSpace() {
|
||||||
DBG_INFO(("Copying buffer into code section.\n"));
|
stack = NULL;
|
||||||
memcpy(&this->code, buf, size);
|
code = NULL;
|
||||||
return;
|
data = NULL;
|
||||||
|
stacksize = DEFAULT_STACKSIZE;
|
||||||
|
codesize = DEFAULT_CODESIZE;
|
||||||
|
datasize = DEFAULT_DATASIZE;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VMAddrSpace::insStack(uint8_t * buf, uint8_t size) {
|
VMAddrSpace::VMAddrSpace(uint32_t ss, uint32_t cs, uint32_t ds) {
|
||||||
DBG_INFO(("Copying buffer into code section.\n"));
|
stack = NULL;
|
||||||
memcpy(&this->stack, buf, size);
|
code = NULL;
|
||||||
return;
|
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"));
|
DBG_INFO(("Copying buffer into data section.\n"));
|
||||||
memcpy(&this->data, buf, size);
|
memcpy(data, buf, size);
|
||||||
return;
|
} 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
|
#ifndef VMAS_H
|
||||||
#define VMAS_H
|
#define VMAS_H
|
||||||
|
#include <stdint.h>
|
||||||
|
#define DEFAULT_STACKSIZE 0x100
|
||||||
|
#define DEFAULT_CODESIZE 0x300
|
||||||
|
#define DEFAULT_DATASIZE 0x100
|
||||||
|
|
||||||
class VMAddrSpace {
|
class VMAddrSpace {
|
||||||
uint8_t stack[0x100], code[0x300], data[0x500];
|
private:
|
||||||
|
uint32_t stacksize, codesize, datasize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void assemble(void);
|
VMAddrSpace();
|
||||||
void insStack(uint8_t *buf, uint8_t size);
|
VMAddrSpace(uint32_t ss, uint32_t cs, uint32_t ds);
|
||||||
void insCode(uint8_t *buf, uint8_t size);
|
uint8_t *stack, *code, *data;
|
||||||
void insData(uint8_t *buf, uint8_t size);
|
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
|
#endif
|
Loading…
Reference in New Issue
Block a user