def insert(self, line): """ Parse the given data line and insert its values in our memory. """ name, dtype, values = line.split(None, 2) name, dtype, values = name[:-1], dtype[1:].lower(), [v.strip() for v in values.split(",")] if dtype not in ["ascii", "asciiz", "byte", "halfword", "word", "space"]: raise ValueError("Invalid data type: {0}".format(dtype)) self.labels[name] = self.offset if dtype == "space": self.offset += getimm(values[0], True) else: for value in values: self[self.offset] = value if "ascii" in dtype else getimm(value, True) self.offset += 1
def runMIPS(self): """ Execute the program using the MIPS instruction set. """ HI, LO = 0, 0 cur_line = 0 while cur_line < len(self.instructions): instr = self.instructions[cur_line] if cur_line in self.labels.values(): pass elif instr.operation in ["add", "addu"]: self.registers[instr.operand0] = self.registers[instr.operand1] + self.registers[instr.operand2] elif instr.operation == "addi": self.registers[instr.operand0] = self.registers[instr.operand1] + getimm(instr.operand2, True) elif instr.operation == "addiu": self.registers[instr.operand0] = self.registers[instr.operand1] + getimm(instr.operand2, False) elif instr.operation == "and": self.registers[instr.operand0] = self.registers[instr.operand1] & self.registers[instr.operand2] elif instr.operation == "andi": self.registers[instr.operand0] = self.registers[instr.operand1] & getimm(instr.operand2, False) elif instr.operation == "beq": if self.registers[instr.operand0] == self.registers[instr.operand1]: cur_line = self.labels[instr.operand2] # jump straight to the label rather than the following instruction because we increment the line counter at the end anyway elif instr.operation == "bgez": if self.registers[instr.operand0] >= 0: cur_line = self.labels[instr.operand1] elif instr.operation == "bgezal": if self.registers[instr.operand0] >= 0: self.registers[31] = cur_line + 1 cur_line = self.labels[instr.operand1] elif instr.operation == "bltz": if self.registers[instr.operand0] < 0: cur_line = self.labels[instr.operand1] elif instr.operation == "bltzal": if self.registers[instr.operand0] < 0: self.registers[31] = cur_line + 1 cur_line = self.labels[instr.operand1] elif instr.operation == "bne": if self.registers[instr.operand0] != self.registers[instr.operand1]: cur_line = self.labels[instr.operand2] elif instr.operation in ["div", "divu"]: LO = self.registers[instr.operand0] // self.registers[instr.operand1] HI = self.registers[instr.operand0] % self.registers[instr.operand1] elif instr.operation == "j": cur_line = self.labels[instr.operand0] elif instr.operation == "jal": self.registers[31] = cur_line + 1 cur_line = self.labels[instr.operand0] elif instr.operation == "jr": cur_line = self.registers[instr.operand0] elif instr.operation == "la": self.registers[instr.operand0] = self.memory.labels[instr.operand1] elif instr.operation in ["lb", "lw"]: outside, inside = parse_address(instr.operand1) address = calcval(outside, self) + calcval(inside, self) self.registers[instr.operand0] = self.memory[address] elif instr.operation == "lui": self.registers[instr.operand0] = getimm(instr.operand1, False) << 16 elif instr.operation == "mfhi": self.registers[instr.operand0] = HI elif instr.operation == "mflo": self.registers[instr.operand0] = LO elif instr.operation in ["mult", "multu"]: LO = self.registers[instr.operand0] * self.registers[instr.operand1] elif instr.operation == "nor": self.registers[instr.operand0] = ~(self.registers[instr.operand1] | self.registers[instr.operand2]) & 0xFFFFFFFF elif instr.operation == "or": self.registers[instr.operand0] = self.registers[instr.operand1] | self.registers[instr.operand2] elif instr.operation == "ori": self.registers[instr.operand0] = self.registers[instr.operand1] | getimm(instr.operand2, False) elif instr.operation == "sb": outside, inside = parse_address(instr.operand1) address = calcval(outside, self) + calcval(inside, self) self.memory[address] = self.registers[instr.operand0] & 0xFF elif instr.operation in ["slt", "sltu"]: self.registers[instr.operand0] = int(self.registers[instr.operand1] < self.registers[instr.operand2]) elif instr.operation == "slti": self.registers[instr.operand0] = int(self.registers[instr.operand1] < getimm(instr.operand2, True)) elif instr.operation == "sltiu": self.registers[instr.operand0] = int(self.registers[instr.operand1] < getimm(instr.operand2, False)) elif instr.operation == "sll": self.registers[instr.operand0] = self.registers[instr.operand1] << getimm(instr.operand2, False) elif instr.operation == "sllv": self.registers[instr.operand0] = self.registers[instr.operand1] << self.registers[instr.operand2] elif instr.operation == "sra": self.registers[instr.operand0] = self.registers[instr.operand1] >> getimm(instr.operand2, True) elif instr.operation == "srl": self.registers[instr.operand0] = self.registers[instr.operand1] >> getimm(instr.operand2, False) elif instr.operation == "srlv": self.registers[instr.operand0] = self.registers[instr.operand1] >> self.registers[instr.operand2] elif instr.operation in ["sub", "subu"]: self.registers[instr.operand0] = self.registers[instr.operand1] - self.registers[instr.operand2] elif instr.operation == "sw": outside, inside = parse_address(instr.operand1) address = calcval(outside, self) + calcval(inside, self) self.memory[address] = self.registers[instr.operand0] elif instr.operation == "syscall": retval = mips_syscall(self.registers[2]) if retval: break elif instr.operation == "xor": self.registers[instr.operand0] = self.registers[instr.operand1] ^ self.registers[instr.operand2] elif instr.operation == "xori": self.registers[instr.operand0] = self.registers[instr.operand1] ^ getimm(instr.operand2, False) elif instr.operation == "break": break else: raise ValueError("Unrecognized operation: {0}".format(instr.operation)) cur_line += 1 return self