Assembler con MOVI, DBG flags
This commit is contained in:
parent
f1060ff86c
commit
ec1576e017
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
*.gipu
|
||||
*.out
|
||||
.vscode/
|
||||
|
@ -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;
|
||||
}
|
96
cpp/vm.cpp
96
cpp/vm.cpp
@ -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;
|
||||
}
|
||||
|
5
cpp/vm.h
5
cpp/vm.h
@ -45,6 +45,11 @@ private:
|
||||
uint8_t cf : 1;
|
||||
};
|
||||
VMAddrSpace as;
|
||||
|
||||
/*
|
||||
DBG UTILS
|
||||
*/
|
||||
uint8_t *reg_name(uint8_t);
|
||||
/*
|
||||
IMPLEMENTATIONS
|
||||
*/
|
||||
|
23
cpp/vmas.cpp
23
cpp/vmas.cpp
@ -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) {
|
||||
DBG_INFO(("\tdata...\n"));
|
||||
data = (uint8_t *)malloc(datasize);
|
||||
}
|
||||
if (stack == NULL) {
|
||||
DBG_INFO(("\tstack...\n"));
|
||||
stack = (uint8_t *)malloc(stacksize);
|
||||
}
|
||||
|
||||
DBG_INFO(("\tcode...\n"));
|
||||
code = new uint8_t[codesize];
|
||||
DBG_INFO(("\tdata...\n"));
|
||||
data = new uint8_t[datasize];
|
||||
DBG_INFO(("\tstack...\n"));
|
||||
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
113
python/assembler.py
Normal 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()
|
Loading…
Reference in New Issue
Block a user