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
|
*.out
|
||||||
.vscode/
|
.vscode/
|
||||||
|
@ -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;
|
||||||
}
|
}
|
96
cpp/vm.cpp
96
cpp/vm.cpp
@ -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;
|
||||||
}
|
}
|
||||||
|
5
cpp/vm.h
5
cpp/vm.h
@ -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
|
||||||
*/
|
*/
|
||||||
|
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) {
|
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
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