reg2reg assembler
This commit is contained in:
parent
56b8a9c407
commit
ffb11f9a2e
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
MEMORY LOCATIONS AND IMMEDIATES ARE 16 BITS LONG
|
MEMORY LOCATIONS AND IMMEDIATES ARE 16 BITS LONG
|
||||||
*/
|
*/
|
||||||
enum ops_starting_values {
|
enum OPS_STARTING_VALUES {
|
||||||
MOVI,
|
MOVI,
|
||||||
MOVR,
|
MOVR,
|
||||||
LOAD,
|
LOAD,
|
||||||
|
43
cpp/vm.cpp
43
cpp/vm.cpp
@ -40,7 +40,7 @@ void VM::defineOpcodes(uint8_t *key) {
|
|||||||
DBG UTILS
|
DBG UTILS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uint8_t *VM::reg_name(uint8_t regvalue) {
|
uint8_t *VM::getRegName(uint8_t regvalue) {
|
||||||
uint8_t *buf = new uint8_t[2];
|
uint8_t *buf = new uint8_t[2];
|
||||||
#ifdef DBG
|
#ifdef DBG
|
||||||
switch (regvalue) {
|
switch (regvalue) {
|
||||||
@ -166,7 +166,7 @@ void VM::initVariables(void) {
|
|||||||
INSTRUCTIONS IMPLEMENTATIONS
|
INSTRUCTIONS IMPLEMENTATIONS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool VM::exec_movi(void) {
|
bool VM::execMOVI(void) {
|
||||||
/*
|
/*
|
||||||
MOVI R0, 0x2400 | R0 = 0x2400
|
MOVI R0, 0x2400 | R0 = 0x2400
|
||||||
*/
|
*/
|
||||||
@ -174,7 +174,7 @@ bool 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 %s, 0x%x\n", reg_name(dst), imm));
|
DBG_INFO(("MOVI %s, 0x%x\n", getRegName(dst), imm));
|
||||||
if (dst == IP) {
|
if (dst == IP) {
|
||||||
DBG_ERROR(("Can't MOVI to IP!\n"));
|
DBG_ERROR(("Can't MOVI to IP!\n"));
|
||||||
return false;
|
return false;
|
||||||
@ -183,7 +183,7 @@ bool VM::exec_movi(void) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VM::exec_movr(void) {
|
bool VM::execMOVR(void) {
|
||||||
/*
|
/*
|
||||||
MOVR R1, R0 | R1 = R0
|
MOVR R1, R0 | R1 = R0
|
||||||
---------------------
|
---------------------
|
||||||
@ -192,7 +192,7 @@ bool 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 %s, %s\n", reg_name(dst), reg_name(src)));
|
DBG_INFO(("MOVR %s, %s\n", getRegName(dst), getRegName(src)));
|
||||||
if (dst == IP || src == IP) {
|
if (dst == IP || src == IP) {
|
||||||
DBG_ERROR(("Can't MOVR IP!\n"));
|
DBG_ERROR(("Can't MOVR IP!\n"));
|
||||||
return false;
|
return false;
|
||||||
@ -201,7 +201,7 @@ bool VM::exec_movr(void) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VM::exec_load(void) {
|
bool VM::execLOAD(void) {
|
||||||
/*
|
/*
|
||||||
LOAD R0, 0x1000 | R0 = data[0x1000]
|
LOAD R0, 0x1000 | R0 = data[0x1000]
|
||||||
*/
|
*/
|
||||||
@ -209,12 +209,12 @@ bool VM::exec_load(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(("LOAD %s, 0x%x\n", reg_name(dst), src));
|
DBG_INFO(("LOAD %s, 0x%x\n", getRegName(dst), src));
|
||||||
regs[dst] = *((uint16_t *)&as.data[src]);
|
regs[dst] = *((uint16_t *)&as.data[src]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VM::exec_stor(void) {
|
bool VM::execSTOR(void) {
|
||||||
/*
|
/*
|
||||||
STOR 0x1000, R0 | data[0x1000] = R0
|
STOR 0x1000, R0 | data[0x1000] = R0
|
||||||
*/
|
*/
|
||||||
@ -222,12 +222,12 @@ bool VM::exec_stor(void) {
|
|||||||
uint8_t src;
|
uint8_t src;
|
||||||
dst = *((uint16_t *)&as.code[regs[IP] + 1]);
|
dst = *((uint16_t *)&as.code[regs[IP] + 1]);
|
||||||
src = as.code[regs[IP] + 3];
|
src = as.code[regs[IP] + 3];
|
||||||
DBG_INFO(("STOR 0x%x, %s\n", dst, reg_name(src)));
|
DBG_INFO(("STOR 0x%x, %s\n", dst, getRegName(src)));
|
||||||
*((uint16_t *)&as.data[dst]) = regs[src];
|
*((uint16_t *)&as.data[dst]) = regs[src];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VM::exec_addi(void) {
|
bool VM::execADDI(void) {
|
||||||
/*
|
/*
|
||||||
ADDI R0, 0x2 | R0 += 2
|
ADDI R0, 0x2 | R0 += 2
|
||||||
*/
|
*/
|
||||||
@ -236,30 +236,41 @@ bool VM::exec_addi(void) {
|
|||||||
|
|
||||||
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(("ADDI %s, 0x%x\n", reg_name(dst), src));
|
DBG_INFO(("ADDI %s, 0x%x\n", getRegName(dst), src));
|
||||||
regs[dst] += src;
|
regs[dst] += src;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VM::execADDR(void) {
|
||||||
|
uint8_t dst;
|
||||||
|
uint8_t src;
|
||||||
|
|
||||||
|
dst = as.code[regs[IP] + 1] >> 4;
|
||||||
|
src = as.code[regs[IP] + 1] & 0b00001111;
|
||||||
|
DBG_INFO(("ADDR %s, 0x%x\n", getRegName(dst), src));
|
||||||
|
regs[dst] += regs[src];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void VM::run(void) {
|
void VM::run(void) {
|
||||||
uint8_t opcode;
|
uint8_t opcode;
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
while (!finished) {
|
while (!finished) {
|
||||||
opcode = (uint8_t)as.code[regs[IP]];
|
opcode = (uint8_t)as.code[regs[IP]];
|
||||||
if (opcode == OPS[MOVI]) {
|
if (opcode == OPS[MOVI]) {
|
||||||
exec_movi();
|
execMOVI();
|
||||||
regs[IP] += MOVI_SIZE;
|
regs[IP] += MOVI_SIZE;
|
||||||
} else if (opcode == OPS[MOVR]) {
|
} else if (opcode == OPS[MOVR]) {
|
||||||
exec_movr();
|
execMOVR();
|
||||||
regs[IP] += MOVR_SIZE;
|
regs[IP] += MOVR_SIZE;
|
||||||
} else if (opcode == OPS[LOAD]) {
|
} else if (opcode == OPS[LOAD]) {
|
||||||
exec_load();
|
execLOAD();
|
||||||
regs[IP] += LOAD_SIZE;
|
regs[IP] += LOAD_SIZE;
|
||||||
} else if (opcode == OPS[STOR]) {
|
} else if (opcode == OPS[STOR]) {
|
||||||
exec_stor();
|
execSTOR();
|
||||||
regs[IP] += STOR_SIZE;
|
regs[IP] += STOR_SIZE;
|
||||||
} else if (opcode == OPS[ADDI]) {
|
} else if (opcode == OPS[ADDI]) {
|
||||||
exec_addi();
|
execADDI();
|
||||||
regs[IP] += ADDI_SIZE;
|
regs[IP] += ADDI_SIZE;
|
||||||
} else if (opcode == OPS[SHIT]) {
|
} else if (opcode == OPS[SHIT]) {
|
||||||
finished = true;
|
finished = true;
|
||||||
|
16
cpp/vm.h
16
cpp/vm.h
@ -3,7 +3,6 @@
|
|||||||
#include "vmas.h"
|
#include "vmas.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
enum regs { R0, R1, R2, R3, S0, S1, S2, S3, IP, BP, SP, NUM_REGS };
|
enum regs { R0, R1, R2, R3, S0, S1, S2, S3, IP, BP, SP, NUM_REGS };
|
||||||
|
|
||||||
class VM {
|
class VM {
|
||||||
@ -27,16 +26,17 @@ private:
|
|||||||
/*
|
/*
|
||||||
DBG UTILS
|
DBG UTILS
|
||||||
*/
|
*/
|
||||||
uint8_t *reg_name(uint8_t);
|
uint8_t *getRegName(uint8_t);
|
||||||
/*
|
/*
|
||||||
IMPLEMENTATIONS
|
IMPLEMENTATIONS
|
||||||
*/
|
*/
|
||||||
bool exec_movi(void);
|
bool execMOVI(void);
|
||||||
bool exec_movr(void);
|
bool execMOVR(void);
|
||||||
bool exec_movm(void);
|
bool execMOVM(void);
|
||||||
bool exec_load(void);
|
bool execLOAD(void);
|
||||||
bool exec_stor(void);
|
bool execSTOR(void);
|
||||||
bool exec_addi(void);
|
bool execADDI(void);
|
||||||
|
void execADDR(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VM(uint8_t *key);
|
VM(uint8_t *key);
|
||||||
|
@ -51,6 +51,7 @@ rol = lambda val, r_bits, max_bits: \
|
|||||||
(val << r_bits % max_bits) & (2**max_bits - 1) | \
|
(val << r_bits % max_bits) & (2**max_bits - 1) | \
|
||||||
((val & (2**max_bits - 1)) >> (max_bits - (r_bits % max_bits)))
|
((val & (2**max_bits - 1)) >> (max_bits - (r_bits % max_bits)))
|
||||||
|
|
||||||
|
|
||||||
class VMAssembler:
|
class VMAssembler:
|
||||||
|
|
||||||
def __init__(self, key):
|
def __init__(self, key):
|
||||||
@ -87,6 +88,23 @@ class VMAssembler:
|
|||||||
return
|
return
|
||||||
|
|
||||||
def reg2reg(self, instruction):
|
def reg2reg(self, instruction):
|
||||||
|
"""
|
||||||
|
Intel syntax -> DST_REG, SRC_REG
|
||||||
|
"""
|
||||||
|
opcode = instruction.opcode
|
||||||
|
dst_reg = instruction.args[0]
|
||||||
|
src_reg = instruction.args[1]
|
||||||
|
if dst_reg.name == "ip" or src_reg.name == "ip":
|
||||||
|
raise IPOverwrite(instruction)
|
||||||
|
if not dst_reg.isreg():
|
||||||
|
raise ExpectedRegister(dst_reg)
|
||||||
|
if not src_reg.isreg():
|
||||||
|
raise ExpectedRegister(src_reg)
|
||||||
|
if not opcode.uint8() or not dst_reg.uint8() or not src_reg.uint8():
|
||||||
|
raise InvalidValue(instruction)
|
||||||
|
byte_with_nibbles = struct.pack("<B", dst_reg.uint8()[0] << 4 ^ (
|
||||||
|
src_reg.uint8()[0] & 0b00001111))
|
||||||
|
self.assembled_code += opcode.uint8() + byte_with_nibbles
|
||||||
return
|
return
|
||||||
|
|
||||||
def reg2imm(self, instruction):
|
def reg2imm(self, instruction):
|
||||||
@ -125,6 +143,9 @@ class VMAssembler:
|
|||||||
def op_addi(self, instruction):
|
def op_addi(self, instruction):
|
||||||
self.imm2reg(instruction)
|
self.imm2reg(instruction)
|
||||||
|
|
||||||
|
def op_addr(self, instruction):
|
||||||
|
self.reg2reg(instruction)
|
||||||
|
|
||||||
def define_ops(self, key):
|
def define_ops(self, key):
|
||||||
key_ba = bytearray(key, 'utf-8')
|
key_ba = bytearray(key, 'utf-8')
|
||||||
olds = copy.deepcopy(ops)
|
olds = copy.deepcopy(ops)
|
||||||
@ -281,7 +302,8 @@ def assemble_data(line):
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
if len(sys.argv) < 4:
|
if len(sys.argv) < 4:
|
||||||
print("Usage: {} opcodes_key file_to_assemble output".format(sys.argv[0]))
|
print("Usage: {} opcodes_key file_to_assemble output".format(
|
||||||
|
sys.argv[0]))
|
||||||
return
|
return
|
||||||
vma = VMAssembler(sys.argv[1])
|
vma = VMAssembler(sys.argv[1])
|
||||||
with open(sys.argv[2], 'r') as f:
|
with open(sys.argv[2], 'r') as f:
|
||||||
|
Loading…
Reference in New Issue
Block a user