diff --git a/assembler/assembler.py b/assembler/assembler.py index 20994c3..1446d0e 100644 --- a/assembler/assembler.py +++ b/assembler/assembler.py @@ -258,6 +258,8 @@ class VMInstruction: def __init__(self, opcode, instr_list): immediate_regexp = re.compile("^(0x*|[0-9]*$)") self.opcode = next((x for x in ops if x.name == opcode), None) + if self.opcode == None: + raise InvalidOperation(opcode) self.args = [] for el in instr_list: if not immediate_regexp.match(el): @@ -279,6 +281,12 @@ op_names = [["MOVI", "imm2reg"], ["ADDR", "reg2reg"], ["SUBI", "imm2reg"], ["SUBR", "reg2reg"], + ["ANDB", "byt2reg"], + ["ANDW", "imm2reg"], + ["ANDR", "reg2reg"], + ["YORB", "byt2reg"], + ["YORW", "imm2reg"], + ["YORR", "reg2reg"], ["XORB", "byt2reg"], ["XORW", "imm2reg"], ["XORR", "reg2reg"], @@ -299,6 +307,8 @@ op_names = [["MOVI", "imm2reg"], ["JPBR", "regonly"], ["JPEI", "immonly"], ["JPER", "regonly"], + ["JPNI", "immonly"], + ["JPNR", "regonly"], ["SHIT", "single"], ["NOPE", "single"], ["GRMN", "single"]] diff --git a/vm/opcodes.h b/vm/opcodes.h index 4887830..cc83155 100644 --- a/vm/opcodes.h +++ b/vm/opcodes.h @@ -10,6 +10,12 @@ enum OPS_STARTING_VALUES { ADDR, SUBI, SUBR, + ANDB, + ANDW, + ANDR, + YORB, + YORW, + YORR, XORB, XORW, XORR, @@ -30,6 +36,8 @@ enum OPS_STARTING_VALUES { JPBR, JPEI, JPER, + JPNI, + JPNR, SHIT, NOPE, GRMN, @@ -60,6 +68,12 @@ INSTRUCTION SIZES #define ADDR_SIZE REG2REG #define SUBI_SIZE IMM2REG #define SUBR_SIZE REG2REG +#define ANDB_SIZE BYT2REG +#define ANDW_SIZE IMM2REG +#define ANDR_SIZE REG2REG +#define YORB_SIZE BYT2REG +#define YORW_SIZE IMM2REG +#define YORR_SIZE REG2REG #define XORB_SIZE BYT2REG #define XORW_SIZE IMM2REG #define XORR_SIZE REG2REG @@ -80,6 +94,8 @@ INSTRUCTION SIZES #define JPBR_SIZE REGONLY #define JPEI_SIZE IMMONLY #define JPER_SIZE REGONLY +#define JPNI_SIZE IMMONLY +#define JPNR_SIZE REGONLY #define SHIT_SIZE SINGLE #define NOPE_SIZE SINGLE #define GRMN_SIZE SINGLE \ No newline at end of file diff --git a/vm/vm.cpp b/vm/vm.cpp index 770d12f..ec6ff6c 100644 --- a/vm/vm.cpp +++ b/vm/vm.cpp @@ -14,7 +14,7 @@ void VM::defineOpcodes(uint8_t *key) { keysize = strlen((char *)key); for (i = 0; i < keysize; i++) { for (j = 0; j < NUM_OPS; j++) { - OPS[j] = rol(key[i] ^ OPS[j], key[i] % 8, 8); + OPS[j] = rol(key[i] ^ OPS[j], key[i] % 8, 8); } } for (i = 0; i < NUM_OPS; i++) { @@ -123,6 +123,7 @@ void VM::status(void) { break; } } + DBG_INFO(("Flags: ZF = %d, CF = %d\n", flags.ZF, flags.CF)); DBG_SUCC(("~~~~~~~~~~\n")); #endif return; @@ -277,6 +278,84 @@ bool VM::execSUBR(void) { regs[dst] -= regs[src]; return true; } +bool VM::execANDB(void) { + /* + ANDB R0, 0x2 -> R0 &= 0x02 or R0 &= [BYTE] 0x02 (low byte) + */ + uint8_t dst; + uint8_t src; + + dst = as.code[regs[IP] + 1]; + src = as.code[regs[IP] + 2]; + DBG_INFO(("ANDB %s, 0x%x\n", getRegName(dst), src)); + regs[dst] &= src; + return true; +} +bool VM::execANDW(void) { + /* + ANDW R0, 0x2 -> R0 &= 0x0002 or R0, ^= [WORD] 0x2 + */ + uint8_t dst; + uint16_t src; + + dst = as.code[regs[IP] + 1]; + src = *((uint16_t *)&as.code[regs[IP] + 2]); + DBG_INFO(("XORW %s, 0x%x\n", getRegName(dst), src)); + regs[dst] &= src; + return true; +} +bool VM::execANDR(void) { + /* + ANDR R0, R1 -> R0 ^= R1 + */ + uint8_t dst; + uint8_t src; + + dst = as.code[regs[IP] + 1] >> 4; + src = as.code[regs[IP] + 1] & 0b00001111; + DBG_INFO(("ANDR %s, 0x%x\n", getRegName(dst), src)); + regs[dst] &= regs[src]; + return true; +} +bool VM::execYORB(void) { + /* + YORB R0, 0x2 -> R0 |= 0x02 or R0 |= [BYTE] 0x02 (low byte) + */ + uint8_t dst; + uint8_t src; + + dst = as.code[regs[IP] + 1]; + src = as.code[regs[IP] + 2]; + DBG_INFO(("YORB %s, 0x%x\n", getRegName(dst), src)); + regs[dst] |= src; + return true; +} +bool VM::execYORW(void) { + /* + YORW R0, 0x2 -> R0 |= 0x0002 or R0, |= [WORD] 0x2 + */ + uint8_t dst; + uint16_t src; + + dst = as.code[regs[IP] + 1]; + src = *((uint16_t *)&as.code[regs[IP] + 2]); + DBG_INFO(("XORW %s, 0x%x\n", getRegName(dst), src)); + regs[dst] |= src; + return true; +} +bool VM::execYORR(void) { + /* + YORR R0, R1 -> R0 |= R1 + */ + uint8_t dst; + uint8_t src; + + dst = as.code[regs[IP] + 1] >> 4; + src = as.code[regs[IP] + 1] & 0b00001111; + DBG_INFO(("XORR %s, 0x%x\n", getRegName(dst), src)); + regs[dst] |= regs[src]; + return true; +} bool VM::execXORB(void) { /* XORB R0, 0x2 -> R0 ^= 0x02 or R0 ^= [BYTE] 0x02 (low byte) @@ -342,7 +421,19 @@ bool VM::execMULI(void) { regs[dst] *= src; return true; } -bool VM::execMULR(void) { return true; } +bool VM::execMULR(void) { + /* + MULR R0, R1 -> R0 *= R1 + */ + uint8_t dst; + uint8_t src; + + dst = as.code[regs[IP] + 1] >> 4; + src = as.code[regs[IP] + 1] & 0b00001111; + DBG_INFO(("MULR %s, 0x%x\n", getRegName(dst), src)); + regs[dst] *= regs[src]; + return true; +} bool VM::execDIVI(void) { /* DIVI R0, 0x2 | R0 /= 2 @@ -356,20 +447,224 @@ bool VM::execDIVI(void) { regs[dst] /= src; return true; } -bool VM::execDIVR(void) { return true; } -bool VM::execPUSH(void) { return true; } -bool VM::execPOOP(void) { return true; } -bool VM::execCMPI(void) { return true; } -bool VM::execCMPR(void) { return true; } -bool VM::execJMPI(void) { return true; } -bool VM::execJMPR(void) { return true; } -bool VM::execJPAI(void) { return true; } -bool VM::execJPAR(void) { return true; } -bool VM::execJPBI(void) { return true; } -bool VM::execJPBR(void) { return true; } -bool VM::execJPEI(void) { return true; } -bool VM::execJPER(void) { return true; } -bool VM::execGRMN(void) { return true; } +bool VM::execDIVR(void) { + /* + DIVR R0, R1 -> R0 /= R1 + */ + 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 true; +} +bool VM::execPUSH(void) { + // TODO: STACK < 0 + uint8_t src; + + src = as.code[regs[IP] + 1]; + DBG_INFO(("PUSH %s\n", getRegName(src))); + memcpy(&as.stack[regs[SP]], ®s[src], sizeof(uint16_t)); + regs[SP] += sizeof(uint16_t); + return true; +} +bool VM::execPOOP(void) { + // TODO: STACK < 0 + uint8_t dst; + + dst = as.code[regs[IP] + 1]; + DBG_INFO(("POOP %s\n", getRegName(dst))); + regs[SP] -= sizeof(uint16_t); + memcpy(®s[dst], &as.stack[regs[SP]], sizeof(uint16_t)); + return true; +} +bool VM::execCMPI(void) { + /* + CMPI R0, 0x2 -> Compare immediate with register + */ + uint8_t reg; + uint16_t imm; + + reg = as.code[regs[IP] + 1]; + imm = *((uint16_t *)&as.code[regs[IP] + 2]); + DBG_INFO(("CMPI %s, 0x%x\n", getRegName(reg), imm)); + if (regs[reg] == imm) { + flags.ZF = 1; + } else { + flags.ZF = 0; + } + if (regs[reg] > imm) { + flags.CF = 1; + } else { + flags.CF = 0; + } + return true; +} +bool VM::execCMPR(void) { + /* + CMPR R0, R1 -> Compares 2 registers + */ + uint8_t r1; + uint8_t r2; + + r1 = as.code[regs[IP] + 1] >> 4; + r2 = as.code[regs[IP] + 1] & 0b00001111; + DBG_INFO(("CMPR %s, %s\n", getRegName(r1), getRegName(r2))); + if (regs[r1] == regs[r2]) { + flags.ZF = 1; + } else { + flags.ZF = 0; + } + if (regs[r1] > regs[r2]) { + flags.CF = 1; + } else { + flags.CF = 0; + } + return true; +} +bool VM::execJMPI(void) { + /* + JMPI 0x2000 -> IP = 0x2000 + */ + uint16_t imm; + + imm = *(uint16_t *)&as.code[regs[IP] + 1]; + DBG_INFO(("JMPI 0x%x\n", imm)); + regs[IP] = imm; + return true; +} +bool VM::execJMPR(void) { + /* + JMPR R0 -> IP = R0 + */ + uint8_t reg; + + reg = as.code[regs[IP] + 1]; + DBG_INFO(("JMPR %s = 0x%x\n", getRegName(reg), regs[reg])); + regs[IP] = regs[reg]; + return true; +} +bool VM::execJPAI(void) { + /* + JPAI 0x2000 -> Jump to 0x2000 if above + */ + uint16_t imm; + + imm = *(uint16_t *)&as.code[regs[IP] + 1]; + DBG_INFO(("JPAI 0x%x\n", imm)); + if (flags.CF == 1) { + regs[IP] = imm; + return true; + } + return false; +} +bool VM::execJPAR(void) { + /* + JPAR R0 -> Jump to [R0] if above + */ + uint8_t reg; + + reg = as.code[regs[IP] + 1]; + DBG_INFO(("JPAR %s = 0x%x\n", getRegName(reg), regs[reg])); + if (flags.CF == 1) { + regs[IP] = reg; + return true; + } + return false; +} +bool VM::execJPBI(void) { + /* + JPBI 0x2000 -> Jump to 0x2000 if below + */ + uint16_t imm; + + imm = *(uint16_t *)&as.code[regs[IP] + 1]; + DBG_INFO(("JPBI 0x%x\n", imm)); + if (flags.CF == 0) { + regs[IP] = imm; + return true; + } + return false; +} +bool VM::execJPBR(void) { + /* + JPBR R0 -> Jump to [R0] if below + */ + uint8_t reg; + + reg = as.code[regs[IP] + 1]; + DBG_INFO(("JPBR %s = 0x%x\n", getRegName(reg), regs[reg])); + if (flags.CF == 0) { + regs[IP] = reg; + return true; + } + return false; +} +bool VM::execJPEI(void) { + /* + JPEI 0x2000 -> Jump to 0x2000 if equal + */ + uint16_t imm; + + imm = *(uint16_t *)&as.code[regs[IP] + 1]; + DBG_INFO(("JPEI 0x%x\n", imm)); + if (flags.ZF == 1) { + regs[IP] = imm; + return true; + } + return false; +} +bool VM::execJPER(void) { + /* + JPNR R0 -> Jump to [R0] if equal + */ + uint8_t reg; + + reg = as.code[regs[IP] + 1]; + DBG_INFO(("JPER %s = 0x%x\n", getRegName(reg), regs[reg])); + if (flags.ZF == 1) { + regs[IP] = reg; + return true; + } + return false; +} +bool VM::execJPNI(void) { + /* + JPEI 0x2000 -> Jump to 0x2000 if not equal + */ + uint16_t imm; + + imm = *(uint16_t *)&as.code[regs[IP] + 1]; + DBG_INFO(("JPNI 0x%x\n", imm)); + if (flags.ZF == 0) { + regs[IP] = imm; + return true; + } + return false; +} +bool VM::execJPNR(void) { + /* + JPER R0 -> Jump to [R0] if not equal + */ + uint8_t reg; + + reg = as.code[regs[IP] + 1]; + DBG_INFO(("JPNR %s = 0x%x\n", getRegName(reg), regs[reg])); + if (flags.ZF == 0) { + regs[IP] = reg; + return true; + } + return false; +} +bool VM::execGRMN(void) { + uint8_t i; + for (i = 0; i < NUM_REGS; i++) { + regs[i] = 0x4747; + } + return true; +} void VM::run(void) { uint8_t opcode; bool finished = false; @@ -399,6 +694,24 @@ void VM::run(void) { } else if (opcode == OPS[SUBR]) { execSUBR(); regs[IP] += SUBR_SIZE; + } else if (opcode == OPS[ANDB]) { + execANDB(); + regs[IP] += ANDB_SIZE; + } else if (opcode == OPS[ANDW]) { + execANDW(); + regs[IP] += ANDW_SIZE; + } else if (opcode == OPS[ANDR]) { + execANDR(); + regs[IP] += ANDR_SIZE; + } else if (opcode == OPS[YORB]) { + execYORB(); + regs[IP] += YORB_SIZE; + } else if (opcode == OPS[YORW]) { + execYORW(); + regs[IP] += YORW_SIZE; + } else if (opcode == OPS[YORR]) { + execYORR(); + regs[IP] += YORR_SIZE; } else if (opcode == OPS[XORB]) { execXORB(); regs[IP] += XORB_SIZE; @@ -434,28 +747,40 @@ void VM::run(void) { regs[IP] += CMPR_SIZE; } else if (opcode == OPS[JMPI]) { execJMPI(); - regs[IP] += JMPI_SIZE; } else if (opcode == OPS[JMPR]) { execJMPR(); - regs[IP] += JMPR_SIZE; - }else if (opcode == OPS[JPAI]) { - execJPAI(); - regs[IP] += JPAI_SIZE; - }else if (opcode == OPS[JPAR]) { - execJPAR(); - regs[IP] += JPAR_SIZE; - }else if (opcode == OPS[JPBI]) { - execJPBI(); - regs[IP] += JPBI_SIZE; - }else if (opcode == OPS[JPBR]) { - execJPBR(); - regs[IP] += JPBR_SIZE; - }else if (opcode == OPS[JPEI]) { - execJPEI(); - regs[IP] += JPEI_SIZE; - }else if (opcode == OPS[JPER]) { - execJPER(); - regs[IP] += JPER_SIZE; + } else if (opcode == OPS[JPAI]) { + if (!execJPAI()) { + regs[IP] += JPAI_SIZE; + } + } else if (opcode == OPS[JPAR]) { + if (!execJPAR()) { + regs[IP] += JPAR_SIZE; + } + } else if (opcode == OPS[JPBI]) { + if (!execJPBI()) { + regs[IP] += JPBI_SIZE; + } + } else if (opcode == OPS[JPBR]) { + if (!execJPBR()) { + regs[IP] += JPBR_SIZE; + } + } else if (opcode == OPS[JPEI]) { + if (!execJPEI()) { + regs[IP] += JPEI_SIZE; + } + } else if (opcode == OPS[JPER]) { + if (!execJPER()) { + regs[IP] += JPER_SIZE; + } + } else if (opcode == OPS[JPNI]) { + if (!execJPNI()) { + regs[IP] += JPNI_SIZE; + } + } else if (opcode == OPS[JPNR]) { + if (!execJPNR()) { + regs[IP] += JPNR_SIZE; + } } else if (opcode == OPS[GRMN]) { execGRMN(); regs[IP] += GRMN_SIZE; diff --git a/vm/vm.h b/vm/vm.h index b97abd9..6ff3ec6 100644 --- a/vm/vm.h +++ b/vm/vm.h @@ -4,6 +4,10 @@ #include enum regs { R0, R1, R2, R3, S0, S1, S2, S3, IP, BP, SP, NUM_REGS }; +typedef struct flags { + uint8_t ZF : 1; + uint8_t CF : 1; +} flags_t; class VM { private: @@ -12,12 +16,9 @@ private: //////////////////////// uint16_t regs[0xb]; - struct flags { - uint8_t zf : 1; - uint8_t cf : 1; - }; - VMAddrSpace as; + flags_t flags; + VMAddrSpace as; //////////////////////// // FUNCTIONS /////////////////////// @@ -39,6 +40,12 @@ private: bool execADDR(void); bool execSUBI(void); bool execSUBR(void); + bool execANDB(void); + bool execANDW(void); + bool execANDR(void); + bool execYORB(void); + bool execYORW(void); + bool execYORR(void); bool execXORB(void); bool execXORW(void); bool execXORR(void); @@ -59,6 +66,8 @@ private: bool execJPBR(void); bool execJPEI(void); bool execJPER(void); + bool execJPNI(void); + bool execJPNR(void); bool execGRMN(void); public: diff --git a/vm/vmas.cpp b/vm/vmas.cpp index 14a2502..9425e5b 100644 --- a/vm/vmas.cpp +++ b/vm/vmas.cpp @@ -46,11 +46,10 @@ bool VMAddrSpace::allocate(void) { DBG_ERROR(("Couldn't allocate stack section.\n")); return false; } - - memset(code, 0xff, - stacksize); // auto halt in case the assembly is not correct + + memset(code, 0xff, codesize); // auto halt in case the assembly is not correct memset(stack, 0x0, stacksize); - memset(data, 0x0, stacksize); + memset(data, 0x0, datasize); DBG_SUCC(("Done!\n")); return true; }