diff --git a/assembler/assembler.py b/assembler/assembler.py index 8ff6d52..aaef128 100644 --- a/assembler/assembler.py +++ b/assembler/assembler.py @@ -49,6 +49,7 @@ class InvalidValue(AssemblerException): class VMAssembler: + def __init__(self, key, data): self.data = data self.assembled_code = bytearray() @@ -79,13 +80,15 @@ class VMAssembler: # putting main in first position in order to assemble it first for i, f in enumerate(self.functions): - if f.name == "main" and i is not 0: - self.functions[0], self.functions[i] = self.functions[i], self.functions[0] - break + if f.name == "main" and i is not 0: + self.functions[0], self.functions[ + i] = self.functions[i], self.functions[0] + break # calculating functions offsets for i in range(1, len(self.functions)): - prev_fun_tot_size = self.functions[i-1].size + self.functions[i-1].offset + prev_fun_tot_size = self.functions[ + i - 1].size + self.functions[i - 1].offset cur_fun_size = self.functions[i].size self.functions[i].set_offset(prev_fun_tot_size) return @@ -209,7 +212,8 @@ class VMAssembler: # the symbal has not been resolved if dst.name == dst.value: # check whether it is a function - val = next((x.offset for x in self.functions if x.name == dst.name), None) + val = next( + (x.offset for x in self.functions if x.name == dst.name), None) # check whether it is a label if val == None: for f in self.functions: @@ -254,7 +258,9 @@ class VMAssembler: for o, n in zip(olds, ops): print("{} : {}->{}".format(o.name, hex(o.value), hex(n.value))) + class VMFunction: + def __init__(self, name, code): self.name = name self.size = 0 @@ -269,11 +275,12 @@ class VMFunction: label = label_re.match(line) if label: label_name = label.group(1) - self.instructions.append(VMInstruction(code[i+1], label_name)) + self.instructions.append( + VMInstruction(code[i + 1], label_name)) i += 2 elif ins: self.instructions.append(VMInstruction(line)) - i+= 1 + i += 1 else: raise InvalidOperation(line) self.calc_size() @@ -297,6 +304,7 @@ class VMFunction: def __repr__(self): return "{}: size {}, offset {}".format(self.name, hex(self.size), hex(self.offset)) + class VMInstruction: """ Represents an instruction the VM recognizes. @@ -305,7 +313,7 @@ class VMInstruction: opcode args """ - def __init__(self, line, label = None): + def __init__(self, line, label=None): self.opcode = None self.args = [] self.size = 1 @@ -314,11 +322,11 @@ class VMInstruction: ins = instruction_re.match(line) symcall = symcall_re.match(line) - opcode = ins.group(1) + opcode = ins.group(1) self.opcode = next((x for x in ops if x.name == opcode), None) if self.opcode == None: raise InvalidOperation(opcode) - + args = [x for x in ins.groups()[1:] if x is not None] for a in args: if immediate_re.match(a) or symcall: @@ -344,7 +352,7 @@ class VMComponent: Represents a register, operation or an immediate the VM recognizes """ - def __init__(self, name, value, method = None): + def __init__(self, name, value, method=None): self.name = name.casefold() self.value = value self.method = method @@ -420,6 +428,10 @@ op_names = [["MOVI", "imm2reg"], ["MULR", "reg2reg"], ["DIVI", "imm2reg"], ["DIVR", "reg2reg"], + ["SHLI", "imm2reg"], + ["SHLR", "reg2reg"], + ["SHRI", "imm2reg"], + ["SHRR", "reg2reg"], ["PUSH", "regonly"], ["POOP", "regonly"], ["CMPI", "imm2reg"], @@ -442,7 +454,8 @@ op_names = [["MOVI", "imm2reg"], reg_names = ["R0", "R1", "R2", "R3", "S0", "S1", "S2", "S3", "IP", "BP", "SP"] 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)] -instruction_re = re.compile("^([\w]{4})(?:\ +(?:([\w]+)\ *(?:,[\ ]*([\w]+))*))?$") # 1: opcode 2+: args +instruction_re = re.compile( + "^([\w]{4})(?:\ +(?:([\w]+)\ *(?:,[\ ]*([\w]+))*))?$") # 1: opcode 2+: args function_re = re.compile("(?:def\ )([a-zA-Z]*)\:") immediate_re = re.compile("(?:0x)?[0-9a-fA-F]+$") alpha_re = re.compile("^[a-zA-Z]*$") @@ -450,6 +463,7 @@ register_re = re.compile("(^[rRsS][0-4]$)|([iIrRsS][pP]$)") label_re = re.compile("^([a-zA-Z]+)\:$") symcall_re = re.compile("^([jJ][pPmM][pPaAbBeEnN][iIrR])\ +([\w]*)$") + def main(): if len(sys.argv) < 4: print("Usage: {} opcodes_key file_to_assemble output".format( diff --git a/vm/opcodes.h b/vm/opcodes.h index a0b1f13..e783d4a 100644 --- a/vm/opcodes.h +++ b/vm/opcodes.h @@ -24,6 +24,10 @@ enum OPS_STARTING_VALUES { MULR, DIVI, DIVR, + SHLI, + SHLR, + SHRI, + SHRR, PUSH, POOP, CMPI, @@ -83,6 +87,10 @@ INSTRUCTION SIZES #define MULR_SIZE REG2REG #define DIVI_SIZE IMM2REG #define DIVR_SIZE REG2REG +#define SHLI_SIZE IMM2REG +#define SHLR_SIZE REG2REG +#define SHRI_SIZE IMM2REG +#define SHRR_SIZE REG2REG #define PUSH_SIZE REGONLY #define POOP_SIZE REGONLY #define CMPI_SIZE IMM2REG diff --git a/vm/vm.cpp b/vm/vm.cpp index abd1ad7..a150135 100644 --- a/vm/vm.cpp +++ b/vm/vm.cpp @@ -459,10 +459,62 @@ bool VM::execDIVR(void) { dst = as.code[regs[IP] + 1] >> 4; src = as.code[regs[IP] + 1] & 0b00001111; - DBG_INFO(("ADDR %s, 0x%x\n", getRegName(dst), src)); + DBG_INFO(("DIVR %s, 0x%x\n", getRegName(dst), src)); regs[dst] /= regs[src]; return true; } +bool VM::execSHLI(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(("SHLI %s, 0x%x\n", getRegName(dst), src)); + regs[dst] = regs[dst] << src; + return true; +} +bool VM::execSHLR(void) { + /* + SHLR 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(("SHLR %s, 0x%x\n", getRegName(dst), src)); + regs[dst] = regs[dst] << regs[src]; + return true; +} +bool VM::execSHRI(void) { + /* + SHRI 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(("SHRI %s, 0x%x\n", getRegName(dst), src)); + regs[dst] = regs[dst] >> src; + return true; +} +bool VM::execSHRR(void) { + /* + SHRR 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(("SHRR %s, 0x%x\n", getRegName(dst), src)); + regs[dst] = regs[dst] >> regs[src]; + return true; +} bool VM::execPUSH(void) { // TODO: STACK < 0 uint8_t src; @@ -755,6 +807,21 @@ void VM::run(void) { } else if (opcode == OPS[DIVI]) { execDIVI(); regs[IP] += DIVI_SIZE; + } else if (opcode == OPS[DIVR]) { + execDIVR(); + regs[IP] += DIVR_SIZE; + } else if (opcode == OPS[SHLI]) { + execSHLI(); + regs[IP] += SHLI_SIZE; + } else if (opcode == OPS[SHLR]) { + execSHLR(); + regs[IP] += SHLR_SIZE; + } else if (opcode == OPS[SHRI]) { + execSHRI(); + regs[IP] += SHRI_SIZE; + } else if (opcode == OPS[SHRR]) { + execSHRR(); + regs[IP] += SHRR_SIZE; } else if (opcode == OPS[PUSH]) { execPUSH(); regs[IP] += PUSH_SIZE; diff --git a/vm/vm.h b/vm/vm.h index cab22ae..ad48d27 100644 --- a/vm/vm.h +++ b/vm/vm.h @@ -54,6 +54,10 @@ private: bool execMULR(void); bool execDIVI(void); bool execDIVR(void); + bool execSHLI(void); + bool execSHLR(void); + bool execSHRI(void); + bool execSHRR(void); bool execPUSH(void); bool execPOOP(void); bool execCMPI(void);