Assembler con MOVI, DBG flags

This commit is contained in:
Giulio De Pasquale 2017-05-15 12:49:11 +02:00
parent f1060ff86c
commit ec1576e017
6 changed files with 220 additions and 41 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
*.gipu
*.out
.vscode/

View File

@ -5,13 +5,28 @@
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main(int argc, char *argv[]) {
std::ifstream f;
std::streamsize fsize;
uint8_t * bytecode;
if (argc < 2) {
printf("Usage: %s <program>\n", argv[0]);
return 1;
}
/*
reading bytecode
*/
f.open(argv[1], std::ios::binary | std::ios::ate);
fsize = f.tellg();
f.seekg(0, std::ios::beg);
bytecode = new uint8_t[fsize];
f.read((char*)bytecode, fsize);
int main() {
uint8_t bytecode[] = "\x00\x00\x00";
VM vm(bytecode, sizeof(bytecode));
vm.run();
printf("\n\n");
vm.status();
return 0;
}

View File

@ -4,32 +4,56 @@
#include <string.h>
/*
CONSTRUCTORS
DBG UTILS
*/
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);
uint8_t *VM::reg_name(uint8_t regvalue) {
uint8_t *buf = new uint8_t[2];
#ifdef DBG
switch (regvalue) {
case R0:
memcpy(buf, "R0", 2);
break;
case R1:
memcpy(buf, "R1", 2);
break;
case R2:
memcpy(buf, "R2", 2);
break;
case R3:
memcpy(buf, "R3", 2);
break;
case S0:
memcpy(buf, "S0", 2);
break;
case S1:
memcpy(buf, "S1", 2);
break;
case S2:
memcpy(buf, "S2", 2);
break;
case S3:
memcpy(buf, "S3", 2);
break;
case IP:
memcpy(buf, "IP", 2);
break;
case BP:
memcpy(buf, "BP", 2);
break;
case SP:
memcpy(buf, "SP", 2);
break;
default:
memcpy(buf, "??", 2);
break;
}
init_regs();
}
void VM::init_regs(void) {
uint8_t i;
for (i = R0; i <= SP; i++) {
this->regs[i] = 0;
}
return;
#endif
return buf;
}
void VM::status(void) {
#ifdef DBG
uint8_t i;
DBG_INFO(("VM Status:\n"));
DBG_INFO(("~~~~~~~~~~\n"));
@ -71,6 +95,32 @@ void VM::status(void) {
}
}
DBG_INFO(("~~~~~~~~~~\n"));
#endif
return;
}
/*
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();
}
void VM::init_regs(void) {
uint8_t i;
for (i = R0; i <= SP; i++) {
this->regs[i] = 0;
}
return;
}
@ -86,7 +136,7 @@ void VM::exec_movi(void) {
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));
DBG_INFO(("MOVI %s, 0x%x\n", reg_name(dst), imm));
regs[dst] = imm;
return;
}
@ -100,7 +150,7 @@ void VM::exec_movr(void) {
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));
DBG_INFO(("MOVR %s, %s\n", reg_name(dst), reg_name(src)));
regs[dst] = regs[src];
return;
}
@ -113,7 +163,7 @@ void VM::exec_getm(void) {
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));
DBG_INFO(("GETM %s, 0x%x\n", reg_name(dst), src));
regs[dst] = *((uint16_t *)&as.data[src]);
return;
}

View File

@ -45,6 +45,11 @@ private:
uint8_t cf : 1;
};
VMAddrSpace as;
/*
DBG UTILS
*/
uint8_t *reg_name(uint8_t);
/*
IMPLEMENTATIONS
*/

View File

@ -26,32 +26,27 @@ VMAddrSpace::VMAddrSpace(uint32_t ss, uint32_t cs, uint32_t ds) {
bool VMAddrSpace::allocate(void) {
DBG_INFO(("Allocating sections...\n"));
if (code == NULL) {
DBG_INFO(("\tcode...\n"));
code = (uint8_t *)malloc(codesize);
}
if (data == NULL) {
code = new uint8_t[codesize];
DBG_INFO(("\tdata...\n"));
data = (uint8_t *)malloc(datasize);
}
if (stack == NULL) {
data = new uint8_t[datasize];
DBG_INFO(("\tstack...\n"));
stack = (uint8_t *)malloc(stacksize);
}
stack = new uint8_t[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);

113
python/assembler.py Normal file
View File

@ -0,0 +1,113 @@
import sys
import re
import struct
op_names = ["MOVI",
"MOVR",
"GETM",
"PUTM",
"ADDI",
"ADDR",
"SUBI",
"SUBR",
"XORI",
"XORR",
"NOTI",
"NOTR",
"MULI",
"MULR",
"DIVI",
"DIVR",
"PUSH",
"POOP",
"CALL",
"HALT",
"NOPE"]
reg_names = ["R0", "R1", "R2", "R3", "S0", "S1", "S2", "S3", "IP", "BP", "SP"]
section_names = ["DATA:", "CODE:", "STACK:"]
section_flags = {s: i + 1 for i, s in enumerate(section_names)}
ops = {s: i for i, s in enumerate(op_names)}
regs = {s: i for i, s in enumerate(reg_names)}
assembled = bytearray()
def to_uint8(data):
alphanum = re.compile("^[0-9]+$")
if isinstance(data, int):
return struct.pack("<b", data)
elif data.startswith("0x"):
return struct.pack("<b", int(data, 16))
elif alphanum.match(data): # only numbers
return struct.pack("<b", int(data))
else:
return None
def to_uint16(data):
print(data)
alphanum = re.compile("^[0-9]+$")
if isinstance(data, int):
return struct.pack("<h", data)
elif data.startswith("0x"):
return struct.pack("<h", int(data, 16))
elif alphanum.match(data): # only numbers
return struct.pack("<h", int(data))
else:
return None
def is_reg(data):
if data not in reg_names:
return False
return True
def assemble_code(line):
global assembled
sys.stdout.write("CODE:")
instruction = [x for x in re.split('\W', line) if x]
op_name = instruction[0]
if op_name not in op_names:
sys.stderr.write(
"ERROR WHILE ASSEMBLING UNKNOWN OPERATION: {}\n".format(op_name))
return False
if op_name == "MOVI":
op = ops[op_name]
dst = instruction[1]
if (is_reg(dst)):
dst = to_uint8(regs[dst])
src = to_uint16(instruction[2])
print("SRC: {} | DST: {}".format(src, dst))
else:
sys.stderr.write(
"ERROR WHILE ASSEMBLING UNKNOWN REGISTER: {}\n".format(dst))
return False
assembled += to_uint8(op) + dst + src
return True
def assemble_data(line):
sys.stdout.write("DATA:\t")
sys.stdout.write(line.strip(",") + "\n")
def main():
global assembled
with open("./test.gipu", 'r') as f:
gen = (line.strip("\n") for line in f if line != "\n")
for line in gen:
if line.startswith(tuple(section_names)):
flag = section_flags[line]
continue
if flag == section_flags["DATA:"]:
assemble_data(line)
elif flag == section_flags["CODE:"]:
assemble_code(line)
with open("./out.gipu", 'wb') as f:
f.write(assembled)
if __name__ == '__main__':
main()