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 *.out
.vscode/ .vscode/

View File

@ -5,13 +5,28 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.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 vm(bytecode, sizeof(bytecode));
vm.run(); vm.run();
printf("\n\n");
vm.status(); vm.status();
return 0; return 0;
} }

View File

@ -4,32 +4,56 @@
#include <string.h> #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) { uint8_t *VM::reg_name(uint8_t regvalue) {
DBG_INFO(("Creating VM with code.\n")); uint8_t *buf = new uint8_t[2];
if (as.allocate()) { #ifdef DBG
as.insCode(code, codesize); 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(); #endif
} return buf;
void VM::init_regs(void) {
uint8_t i;
for (i = R0; i <= SP; i++) {
this->regs[i] = 0;
}
return;
} }
void VM::status(void) { void VM::status(void) {
#ifdef DBG
uint8_t i; uint8_t i;
DBG_INFO(("VM Status:\n")); DBG_INFO(("VM Status:\n"));
DBG_INFO(("~~~~~~~~~~\n")); DBG_INFO(("~~~~~~~~~~\n"));
@ -71,6 +95,32 @@ void VM::status(void) {
} }
} }
DBG_INFO(("~~~~~~~~~~\n")); 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; return;
} }
@ -86,7 +136,7 @@ void VM::exec_movi(void) {
uint16_t imm; uint16_t imm;
dst = as.code[regs[IP] + 1]; dst = as.code[regs[IP] + 1];
imm = *((uint16_t *)&as.code[regs[IP] + 2]); 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; regs[dst] = imm;
return; return;
} }
@ -100,7 +150,7 @@ void VM::exec_movr(void) {
uint8_t dst, src; uint8_t dst, src;
dst = as.code[regs[IP] + 1] >> 4; dst = as.code[regs[IP] + 1] >> 4;
src = as.code[regs[IP] + 1] & 0b00001111; 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]; regs[dst] = regs[src];
return; return;
} }
@ -113,7 +163,7 @@ void VM::exec_getm(void) {
uint16_t src; uint16_t src;
dst = as.code[regs[IP] + 1]; dst = as.code[regs[IP] + 1];
src = *((uint16_t *)&as.code[regs[IP] + 2]); 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]); regs[dst] = *((uint16_t *)&as.data[src]);
return; return;
} }

View File

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

View File

@ -26,32 +26,27 @@ VMAddrSpace::VMAddrSpace(uint32_t ss, uint32_t cs, uint32_t ds) {
bool VMAddrSpace::allocate(void) { bool VMAddrSpace::allocate(void) {
DBG_INFO(("Allocating sections...\n")); DBG_INFO(("Allocating sections...\n"));
if (code == NULL) {
DBG_INFO(("\tcode...\n")); DBG_INFO(("\tcode...\n"));
code = (uint8_t *)malloc(codesize); code = new uint8_t[codesize];
} DBG_INFO(("\tdata...\n"));
if (data == NULL) { data = new uint8_t[datasize];
DBG_INFO(("\tdata...\n")); DBG_INFO(("\tstack...\n"));
data = (uint8_t *)malloc(datasize); stack = new uint8_t[stacksize];
}
if (stack == NULL) {
DBG_INFO(("\tstack...\n"));
stack = (uint8_t *)malloc(stacksize);
}
if (code == NULL) { if (code == NULL) {
DBG_ERROR(("Couldn't allocate code section.\n")); DBG_ERROR(("Couldn't allocate code section.\n"));
return false; return false;
} }
data = (uint8_t *)malloc(datasize);
if (data == NULL) { if (data == NULL) {
DBG_ERROR(("Couldn't allocate data section.\n")); DBG_ERROR(("Couldn't allocate data section.\n"));
return false; return false;
} }
stack = (uint8_t *)malloc(stacksize);
if (stack == NULL) { if (stack == NULL) {
DBG_ERROR(("Couldn't allocate stack section.\n")); DBG_ERROR(("Couldn't allocate stack section.\n"));
return false; return false;
} }
memset(code, 0xff, memset(code, 0xff,
stacksize); // auto halt in case the assembly is not correct stacksize); // auto halt in case the assembly is not correct
memset(stack, 0x0, stacksize); 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()