reg2reg assembler

This commit is contained in:
Giulio De Pasquale 2017-05-17 18:58:00 +02:00
parent 56b8a9c407
commit ffb11f9a2e
5 changed files with 67 additions and 34 deletions

View File

@ -8,7 +8,7 @@
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
std::ifstream bytecode_if; std::ifstream bytecode_if;
std::streamsize bytecode_size; std::streamsize bytecode_size;
uint8_t * bytecode; uint8_t *bytecode;
if (argc < 3) { if (argc < 3) {
printf("Usage: %s <opcodes_key> <program>\n", argv[0]); printf("Usage: %s <opcodes_key> <program>\n", argv[0]);
@ -23,8 +23,8 @@ int main(int argc, char *argv[]) {
bytecode_if.seekg(0, std::ios::beg); bytecode_if.seekg(0, std::ios::beg);
bytecode = new uint8_t[bytecode_size]; bytecode = new uint8_t[bytecode_size];
bytecode_if.read((char*)bytecode, bytecode_size); bytecode_if.read((char *)bytecode, bytecode_size);
VM vm((uint8_t*)argv[1], bytecode, bytecode_size); VM vm((uint8_t *)argv[1], bytecode, bytecode_size);
vm.run(); vm.run();
vm.status(); vm.status();
return 0; return 0;

View File

@ -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,

View File

@ -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;

View File

@ -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 {
@ -23,24 +22,25 @@ private:
// FUNCTIONS // FUNCTIONS
/////////////////////// ///////////////////////
void initVariables(void); void initVariables(void);
void defineOpcodes(uint8_t * key); void defineOpcodes(uint8_t *key);
/* /*
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);
VM(uint8_t * key, uint8_t *code, uint32_t codesize); VM(uint8_t *key, uint8_t *code, uint32_t codesize);
void status(void); void status(void);
void run(); void run();
}; };

View File

@ -48,8 +48,9 @@ class InvalidValue(AssemblerException):
super().__init__("Invalid value while assembling: {}".format(instruction)) super().__init__("Invalid value while assembling: {}".format(instruction))
rol = lambda val, r_bits, max_bits: \ 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:
@ -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: