From 020a5062a24b4cd6c06a28609fe0569e1c717a55 Mon Sep 17 00:00:00 2001 From: Giulio De Pasquale Date: Thu, 18 May 2017 15:41:05 +0200 Subject: [PATCH] Polishing. Alcune implementazioni --- {python => assembler}/assembler.py | 137 +++++++++++++--------- {cpp => vm}/debug.h | 0 {cpp => vm}/emulator.cpp | 0 {cpp => vm}/opcodes.h | 33 ++++-- {cpp => vm}/vm.cpp | 176 +++++++++++++++++++++++------ {cpp => vm}/vm.h | 12 +- {cpp => vm}/vmas.cpp | 0 {cpp => vm}/vmas.h | 0 8 files changed, 259 insertions(+), 99 deletions(-) rename {python => assembler}/assembler.py (71%) rename {cpp => vm}/debug.h (100%) rename {cpp => vm}/emulator.cpp (100%) rename {cpp => vm}/opcodes.h (71%) rename {cpp => vm}/vm.cpp (68%) rename {cpp => vm}/vm.h (86%) rename {cpp => vm}/vmas.cpp (100%) rename {cpp => vm}/vmas.h (100%) diff --git a/python/assembler.py b/assembler/assembler.py similarity index 71% rename from python/assembler.py rename to assembler/assembler.py index 9d6928c..20994c3 100644 --- a/python/assembler.py +++ b/assembler/assembler.py @@ -59,7 +59,7 @@ class VMAssembler: self.define_ops(key) def parse(self, instruction): - action = getattr(self, "op_{}".format(instruction.opcode.name)) + action = getattr(self, "{}".format(instruction.opcode.method)) action(instruction) def process_code_line(self, line): @@ -125,36 +125,66 @@ class VMAssembler: self.assembled_code += opcode.uint8() + imm.uint16() + reg.uint8() return - def imm(self, instruction): + def byt2reg(self, instruction): + """ + Intel syntax -> REG, [BYTE]IMM + """ + opcode = instruction.opcode + reg = instruction.args[0] + imm = instruction.args[1] + if reg.name == "ip": + raise IPOverwrite(instruction) + if not imm.isimm(): + raise ExpectedImmediate(imm) + if not reg.isreg(): + raise ExpectedRegister(reg) + if not opcode.uint8() or not reg.uint8() or not imm.uint8(): + raise InvalidValue(instruction) + self.assembled_code += opcode.uint8() + reg.uint8() + imm.uint8() return - def op_movi(self, instruction): - self.imm2reg(instruction) + def regonly(self, instruction): + """ + Instruction with only an argument: a register + """ + opcode = instruction.opcode + reg = instruction.args[0] + if reg.name == "ip": + raise IPOverwrite(instruction) + if not reg.isreg(): + raise ExpectedRegister(reg) + if not opcode.uint8() or not reg.uint8(): + raise InvalidValue(instruction) + self.assembled_code += opcode.uint8() + reg.uint8() + return - def op_movr(self, instruction): - self.reg2reg(instruction) + def immonly(self, instruction): + """ + Instruction with only an argument: an immediate + """ + opcode = instruction.opcode + imm = instruction.args[0] + if not imm.isimm(): + raise ExpectedImmediate(imm) + if not opcode.uint8() or not imm.uint16(): + raise InvalidValue(instruction) + self.assembled_code += opcode.uint8() + imm.uint16() + return - def op_load(self, instruction): - self.imm2reg(instruction) - - def op_stor(self, instruction): - self.reg2imm(instruction) - - def op_addi(self, instruction): - self.imm2reg(instruction) - - def op_addr(self, instruction): - self.reg2reg(instruction) + def single(self, instruction): + """ + Instruction with no arguments + """ + opcode = instruction.opcode + self.assembled_code += opcode.uint8() + return def define_ops(self, key): key_ba = bytearray(key, 'utf-8') olds = copy.deepcopy(ops) for b in key_ba: for op_com in ops: - if b % 2: - op_com.set_value(rol(b ^ op_com.value, b % 8, 8)) - else: - op_com.set_value(rol(b ^ op_com.value, (b + 1) % 8, 8)) + op_com.set_value(rol(b ^ op_com.value, b % 8, 8)) for i in ops: for j in ops: j.set_value(rol(j.value, i.value % 8, 8)) @@ -167,9 +197,10 @@ class VMComponent: Represents a register, operation or an immediate the VM recognizes """ - def __init__(self, name, value): + def __init__(self, name, value, method=None): self.name = name.casefold() self.value = value + self.method = method def __repr__(self): return "{}".format(self.name) @@ -206,7 +237,7 @@ class VMComponent: return True def isop(self): - if self.name not in [x.casefold() for x in op_names]: + if self.name not in [x[0].casefold() for x in op_names]: return False return True @@ -240,38 +271,42 @@ class VMInstruction: def __repr__(self): return "{} {}".format(self.opcode.name, ", ".join([x.name for x in self.args])) -op_names = ["MOVI", - "MOVR", - "LOAD", - "STOR", - "ADDI", - "ADDR", - "SUBI", - "SUBR", - "XORB", - "XORW", - "XORR", - "NOTR", - "MULI", - "MULR", - "DIVI", - "DIVR", - "PUSH", - "POOP", - "CMPI", - "CMPR", - "JUMP", - "JMPA", - "JMPB", - "JMPE", - "SHIT", - "NOPE", - "GRMN"] +op_names = [["MOVI", "imm2reg"], + ["MOVR", "reg2reg"], + ["LOAD", "imm2reg"], + ["STOR", "reg2imm"], + ["ADDI", "imm2reg"], + ["ADDR", "reg2reg"], + ["SUBI", "imm2reg"], + ["SUBR", "reg2reg"], + ["XORB", "byt2reg"], + ["XORW", "imm2reg"], + ["XORR", "reg2reg"], + ["NOTR", "regonly"], + ["MULI", "imm2reg"], + ["MULR", "reg2reg"], + ["DIVI", "imm2reg"], + ["DIVR", "reg2reg"], + ["PUSH", "regonly"], + ["POOP", "regonly"], + ["CMPI", "imm2reg"], + ["CMPR", "reg2reg"], + ["JMPI", "immonly"], + ["JMPR", "regonly"], + ["JPAI", "immonly"], + ["JPAR", "regonly"], + ["JPBI", "immonly"], + ["JPBR", "regonly"], + ["JPEI", "immonly"], + ["JPER", "regonly"], + ["SHIT", "single"], + ["NOPE", "single"], + ["GRMN", "single"]] reg_names = ["R0", "R1", "R2", "R3", "S0", "S1", "S2", "S3", "IP", "BP", "SP"] section_names = ["DATA:", "CODE:", "STACK:"] section_flags = {s.casefold(): i + 1 for i, s in enumerate(section_names)} -ops = [VMComponent(s.casefold(), i) for i, s in enumerate(op_names)] +ops = [VMComponent(le[0], i, le[1]) for i, le in enumerate(op_names)] regs = [VMComponent(s.casefold(), i) for i, s in enumerate(reg_names)] diff --git a/cpp/debug.h b/vm/debug.h similarity index 100% rename from cpp/debug.h rename to vm/debug.h diff --git a/cpp/emulator.cpp b/vm/emulator.cpp similarity index 100% rename from cpp/emulator.cpp rename to vm/emulator.cpp diff --git a/cpp/opcodes.h b/vm/opcodes.h similarity index 71% rename from cpp/opcodes.h rename to vm/opcodes.h index b53a160..4887830 100644 --- a/cpp/opcodes.h +++ b/vm/opcodes.h @@ -22,10 +22,14 @@ enum OPS_STARTING_VALUES { POOP, CMPI, CMPR, - JUMP, - JMPA, - JMPB, - JMPE, + JMPI, + JMPR, + JPAI, + JPAR, + JPBI, + JPBR, + JPEI, + JPER, SHIT, NOPE, GRMN, @@ -41,7 +45,8 @@ INSTRUCTION SIZE TYPES #define IMM2REG 4 #define REG2IMM 4 #define BYT2REG 3 -#define UNARY 2 +#define REGONLY 2 +#define IMMONLY 3 #define SINGLE 1 /* @@ -58,19 +63,23 @@ INSTRUCTION SIZES #define XORB_SIZE BYT2REG #define XORW_SIZE IMM2REG #define XORR_SIZE REG2REG -#define NOTR_SIZE UNARY +#define NOTR_SIZE REGONLY #define MULI_SIZE IMM2REG #define MULR_SIZE REG2REG #define DIVI_SIZE IMM2REG #define DIVR_SIZE REG2REG -#define PUSH_SIZE UNARY -#define POOP_SIZE UNARY +#define PUSH_SIZE REGONLY +#define POOP_SIZE REGONLY #define CMPI_SIZE IMM2REG #define CMPR_SIZE REG2REG -#define JUMP_SIZE UNARY -#define JMPA_SIZE UNARY -#define JMPB_SIZE UNARY -#define JMPE_SIZE UNARY +#define JMPI_SIZE IMMONLY +#define JMPR_SIZE REGONLY +#define JPAI_SIZE IMMONLY +#define JPAR_SIZE REGONLY +#define JPBI_SIZE IMMONLY +#define JPBR_SIZE REGONLY +#define JPEI_SIZE IMMONLY +#define JPER_SIZE REGONLY #define SHIT_SIZE SINGLE #define NOPE_SIZE SINGLE #define GRMN_SIZE SINGLE \ No newline at end of file diff --git a/cpp/vm.cpp b/vm/vm.cpp similarity index 68% rename from cpp/vm.cpp rename to vm/vm.cpp index dd6496a..770d12f 100644 --- a/cpp/vm.cpp +++ b/vm/vm.cpp @@ -14,11 +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++) { - if (key[i] % 2) { OPS[j] = rol(key[i] ^ OPS[j], key[i] % 8, 8); - } else { - OPS[j] = rol(key[i] ^ OPS[j], (key[i] + 1) % 8, 8); - } } } for (i = 0; i < NUM_OPS; i++) { @@ -185,7 +181,7 @@ bool VM::execMOVI(void) { bool VM::execMOVR(void) { /* - MOVR R1, R0 | R1 = R0 + MOVR R1, R0 -> R1 = R0 --------------------- R1, R0 = 0x10 <- DST / SRC are nibbles! */ @@ -203,7 +199,7 @@ bool VM::execMOVR(void) { bool VM::execLOAD(void) { /* - LOAD R0, 0x1000 | R0 = data[0x1000] + LOAD R0, 0x1000 -> R0 = data[0x1000] */ uint8_t dst; uint16_t src; @@ -216,7 +212,7 @@ bool VM::execLOAD(void) { bool VM::execSTOR(void) { /* - STOR 0x1000, R0 | data[0x1000] = R0 + STOR 0x1000, R0 -> data[0x1000] = R0 */ uint16_t dst; uint8_t src; @@ -229,7 +225,7 @@ bool VM::execSTOR(void) { bool VM::execADDI(void) { /* - ADDI R0, 0x2 | R0 += 2 + ADDI R0, 0x2 -> R0 += 2 */ uint8_t dst; uint16_t src; @@ -242,6 +238,9 @@ bool VM::execADDI(void) { } bool VM::execADDR(void) { + /* + ADDR R0, R1 -> R0 += R1 + */ uint8_t dst; uint8_t src; @@ -252,24 +251,124 @@ bool VM::execADDR(void) { return true; } -bool VM::execSUBI(void) { return true; } -bool VM::execSUBR(void) { return true; } -bool VM::execXORB(void) { return true; } -bool VM::execXORW(void) { return true; } -bool VM::execXORR(void) { return true; } -bool VM::execNOTR(void) { return true; } -bool VM::execMULI(void) { return true; } +bool VM::execSUBI(void) { + /* + SUBI R0, 0x2 -> R0 -= 2 + */ + uint8_t dst; + uint16_t src; + + dst = as.code[regs[IP] + 1]; + src = *((uint16_t *)&as.code[regs[IP] + 2]); + DBG_INFO(("SUBI %s, 0x%x\n", getRegName(dst), src)); + regs[dst] -= src; + return true; +} +bool VM::execSUBR(void) { + /* + SUBR 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(("SUBR %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) + */ + uint8_t dst; + uint8_t src; + + dst = as.code[regs[IP] + 1]; + src = as.code[regs[IP] + 2]; + DBG_INFO(("XORB %s, 0x%x\n", getRegName(dst), src)); + regs[dst] ^= src; + return true; +} +bool VM::execXORW(void) { + /* + XORW 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::execXORR(void) { + /* + XORR 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::execNOTR(void) { + /* + NOTR 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(("NOTR %s, 0x%x\n", getRegName(dst), src)); + regs[dst] = ~regs[src]; + return true; +} +bool VM::execMULI(void) { + /* + MULI R0, 0x2 | R0 *= 2 + */ + uint8_t dst; + uint16_t src; + + dst = as.code[regs[IP] + 1]; + src = *((uint16_t *)&as.code[regs[IP] + 2]); + DBG_INFO(("SUBI %s, 0x%x\n", getRegName(dst), src)); + regs[dst] *= src; + return true; +} bool VM::execMULR(void) { return true; } -bool VM::execDIVI(void) { return true; } +bool VM::execDIVI(void) { + /* + DIVI R0, 0x2 | R0 /= 2 + */ + uint8_t dst; + uint16_t src; + + dst = as.code[regs[IP] + 1]; + src = *((uint16_t *)&as.code[regs[IP] + 2]); + DBG_INFO(("DIVI %s, 0x%x\n", getRegName(dst), src)); + 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::execJUMP(void) { return true; } -bool VM::execJMPA(void) { return true; } -bool VM::execJMPB(void) { return true; } -bool VM::execJMPE(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; } void VM::run(void) { uint8_t opcode; @@ -333,22 +432,35 @@ void VM::run(void) { } else if (opcode == OPS[CMPR]) { execCMPR(); regs[IP] += CMPR_SIZE; - } else if (opcode == OPS[JUMP]) { - execJUMP(); - regs[IP] += JUMP_SIZE; - } else if (opcode == OPS[JMPA]) { - execJMPA(); - regs[IP] += JMPA_SIZE; - } else if (opcode == OPS[JMPB]) { - execJMPB(); - regs[IP] += JMPB_SIZE; - } else if (opcode == OPS[JMPE]) { - execJMPE(); - regs[IP] += JMPE_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[GRMN]) { execGRMN(); regs[IP] += GRMN_SIZE; } else if (opcode == OPS[SHIT]) { + DBG_INFO(("Halting.\n")); finished = true; } else if (opcode == OPS[NOPE]) { regs[IP] += NOPE_SIZE; diff --git a/cpp/vm.h b/vm/vm.h similarity index 86% rename from cpp/vm.h rename to vm/vm.h index cf3b37b..b97abd9 100644 --- a/cpp/vm.h +++ b/vm/vm.h @@ -51,10 +51,14 @@ private: bool execPOOP(void); bool execCMPI(void); bool execCMPR(void); - bool execJUMP(void); - bool execJMPA(void); - bool execJMPB(void); - bool execJMPE(void); + bool execJMPI(void); + bool execJMPR(void); + bool execJPAI(void); + bool execJPAR(void); + bool execJPBI(void); + bool execJPBR(void); + bool execJPEI(void); + bool execJPER(void); bool execGRMN(void); public: diff --git a/cpp/vmas.cpp b/vm/vmas.cpp similarity index 100% rename from cpp/vmas.cpp rename to vm/vmas.cpp diff --git a/cpp/vmas.h b/vm/vmas.h similarity index 100% rename from cpp/vmas.h rename to vm/vmas.h