class Command: def __init__(self, program, pos, name=None, first=None, second=None, third=None, imm=None, label=None): name = name.lower() if name not in rType.keys() and \ name not in iType.keys() and \ name not in jType.keys(): raise "'%s' is not a MIPS assembly command." % (name.lower()) self.program = program self.pos = pos self.name = name self.rs = EmptyRegister() self.rt = EmptyRegister() self.rd = EmptyRegister() registers = ( rType[name][-1] if name in rType else \ iType[name][-1] if name in iType else \ jType[name][-1] ) rList = [x for x in [first, second, third] if x is not None] if len(registers) != len(rList): raise "'%s' requires %d registers." % (name, len(registers)) for _, reg in zip(registers, rList): if _ == "rs": self.rs = Register(reg) if _ == "rd": self.rd = Register(reg) if _ == "rt": self.rt = Register(reg) if isinstance(imm, int): self.imm = imm else: self.imm = eval(imm) if imm is not None else 0 self.label = label if imm is not None and self.label is not None: raise "Label and imm can't both exist." @staticmethod def parseLine(program, pos, line): global commandTypes for m in commandTypes: ans = m.match(line) if ans is not None: group = ans.groupdict() return Command(program=program, pos=pos, **group) raise "'%s' is not a command." % (line) def toBin(self): if self.name in rType.keys(): ans = 0 # opcode ans |= (self.rs.binary() << 21) # rs ans |= (self.rt.binary() << 16) # rt ans |= (self.rd.binary() << 11) # rd ans |= (self.imm << 6) # shamt ans |= (rType[self.name][1] << 0) # funct return ans if self.name in iType.keys(): ans = iType[self.name][0] << 26 # opcode ans |= (self.rs.binary() << 21) # rs ans |= (self.rt.binary() << 16) # rt if len(iType[self.name]) > 2: ans |= (iType[self.name][1] << 16) # rt adjustment if self.label is not None: if "b" == self.name[0]: tmp = self.program.Label(self.label) - self.pos - 1 else: tmp = self.program.Label(self.label) ans |= (tmp & 0xFFFF) else: if "b" == self.name[0]: ans |= (self.imm >> 2 & 0xFFFF) else: ans |= (self.imm & 0xFFFF) return ans if self.name in jType.keys(): ans = jType[self.name][0] << 26 # opcode if self.label is not None: ans |= ((self.program.Label(self.label) + \ self.program.textBase) % (1 << 26)) # label else: ans |= (self.imm % (1 << 26)) # address return ans def Size(self): return 1 def Bytes(self): x = self.toBin() ans = [x >> 24, x >> 16 & 0xFF, x >> 8 & 0xFF, x & 0xFF] return ans def __repr__(self): return "Command(%s, %s, %s, %s, %s, %s)" % \ (self.name, self.rs, self.rt, self.rd, self.imm, self.label)
class Command: def __init__(self, program, pos, name = None, first = None, second = None, third = None, imm = None, label = None): name = name.lower() if name not in rType.keys() and \ name not in iType.keys() and \ name not in jType.keys(): raise "'%s' is not a MIPS assembly command." % (name.lower()) self.program = program self.pos = pos self.name = name self.rs = EmptyRegister() self.rt = EmptyRegister() self.rd = EmptyRegister() registers = ( rType[name][-1] if name in rType else \ iType[name][-1] if name in iType else \ jType[name][-1] ) rList = [x for x in [first, second, third] if x is not None] if len(registers) != len(rList): raise "'%s' requires %d registers." % (name, len(registers)) for _, reg in zip(registers, rList): if _ == "rs": self.rs = Register(reg) if _ == "rd": self.rd = Register(reg) if _ == "rt": self.rt = Register(reg) if isinstance(imm, int): self.imm = imm else: self.imm = eval(imm) if imm is not None else 0 self.label = label if imm is not None and self.label is not None: raise "Label and imm can't both exist." @staticmethod def parseLine(program, pos, line): global commandTypes for m in commandTypes: ans = m.match(line) if ans is not None: group = ans.groupdict() return Command(program = program, pos = pos, **group) raise "'%s' is not a command." % (line) def toBin(self): if self.name in rType.keys(): ans = 0 # opcode ans |= (self.rs.binary() << 21) # rs ans |= (self.rt.binary() << 16) # rt ans |= (self.rd.binary() << 11) # rd ans |= (self.imm << 6) # shamt ans |= (rType[self.name][1] << 0) # funct return ans if self.name in iType.keys(): ans = iType[self.name][0] << 26 # opcode ans |= (self.rs.binary() << 21) # rs ans |= (self.rt.binary() << 16) # rt if len(iType[self.name]) > 2: ans |= (iType[self.name][1] << 16) # rt adjustment if self.label is not None: if "b" == self.name[0]: tmp = self.program.Label(self.label) - self.pos - 1 else: tmp = self.program.Label(self.label) ans |= (tmp & 0xFFFF) else: if "b" == self.name[0]: ans |= (self.imm >> 2 & 0xFFFF) else: ans |= (self.imm & 0xFFFF) return ans if self.name in jType.keys(): ans = jType[self.name][0] << 26 # opcode if self.label is not None: ans |= ((self.program.Label(self.label) + \ self.program.textBase) % (1 << 26)) # label else: ans |= (self.imm % (1 << 26)) # address return ans def Size(self): return 1 def Bytes(self): x = self.toBin() ans = [ x >> 24, x >> 16 & 0xFF, x >> 8 & 0xFF, x & 0xFF ] return ans def __repr__(self): return "Command(%s, %s, %s, %s, %s, %s)" % \ (self.name, self.rs, self.rt, self.rd, self.imm, self.label)
class Instruction: def __init__(self, program, position, name=None, first=None, second=None, third=None, imm=None, label=None, immb=None): name = name.lower() #if imm is not None: #print(imm) #if label is not None: #print(label) if name not in r_type.keys() and \ name not in i_type.keys() and \ name not in s_type.keys() and \ name not in j_type.keys() and \ name not in interrupt_type.keys(): raise Exception("'%s' is not a MIPS opcode" % (name.lower())) self.program = program self.position = position self.name = name self.rs = UnusedRegister() self.rt = UnusedRegister() self.rd = UnusedRegister() # Verify that the right registers are present registers = (r_type[name][-1] if name in r_type else \ s_type[name][-1] if name in s_type else \ i_type[name][-1] if name in i_type else \ j_type[name][-1] if name in j_type else \ interrupt_type[name][-1]) rlist = [x for x in [first, second, third] if x is not None] if len(registers) == 3 and (first is None or second is None \ or third is None): raise Exception("'%s' requires three registers" % (name)) if len(registers) == 2 and (first is None or second is None \ or third is not None): raise Exception("'%s' requires two registers" % (name)) if len(registers) == 1 and (first is None or second is not None \ or third is not None): raise Exception("'%s' requires one register" % (name)) if len(registers) == 0 and (first is not None or second is not None \ or third is not None): raise Exception("'%s' requires no registers" % (name)) for pos, reg in zip(registers, rlist): if pos == "rs": self.rs = Register(reg) if pos == "rd": self.rd = Register(reg) if pos == "rt": self.rt = Register(reg) if isinstance(imm, int): self.imm = imm else: self.imm = eval(imm) if imm is not None else 0 if isinstance(immb, int): self.immb = immb else: self.immb = eval(immb) if immb is not None else 0 self.label = label if imm is not None and self.label is not None: raise Exception("A label and an immediate. Confused.") @staticmethod def parseline(program, position, line): global instruction_types for t in instruction_types: m = t.match(line) if m is not None: g = m.groupdict() if 'name' in g and \ g['name'].lower() in supported_pseudoinstructions: return PseudoInstruction(program, position, **m.groupdict()) return Instruction(program=program, position=position, **g) print line raise Exception("'%s' not an instruction" % (line)) def ToBinary(self): if self.name in r_type.keys(): b = (r_type[self.name][0] << 26) # opcode b |= (self.rs.binary() << 21) # rs b |= (self.rt.binary() << 16) # rt b |= (self.rd.binary() << 11) # rd #b |= (self.imm << 6) # shamt b |= (r_type[self.name][1] << 0) # funct return b if self.name in i_type.keys(): b = i_type[self.name][0] << 26 # opcode #if "jr" == self.name[0]: #print self.rs.binary() b |= (self.rs.binary() << 21) # rs b |= (self.rt.binary() << 16) # rt if self.label is not None: if "b" == self.name[0]: #print "branch" #print self.program.Label(self.label) #print self.position z = (self.program.Label(self.label) - self.position - 1) * 4 else: z = self.program.Label(self.label) b |= (z & 0xFFFF) # label else: b |= (self.imm & 0xFFFF) # imm return b if self.name in j_type.keys(): b = (j_type[self.name][0]) << 26 #opcode if self.label is not None: b |= (self.program.Label( self.label)) * 4 + self.program.text_base else: b |= (self.imm & 0x03FFFFFF) # address return b if self.name in s_type.keys(): b = (s_type[self.name][0] ) << 26 #opcode # opcode b |= (self.rs.binary() << 21) # rs b |= (self.rt.binary() << 16) # rt b |= (self.imm << 12) # spu reg b |= (s_type_op[self.name] << 8) # opcode cont. b |= (self.immb) #delim return b if self.name in interrupt_type.keys(): b = (interrupt_type[self.name][0]) << 26 b |= self.imm return b # The size, in words, of this instruction def Size(self): return 1 def Bytes(self, endian="big"): b = self.ToBinary() bytes = [b >> 24, b >> 16 & 0xFF, b >> 8 & 0xFF, b & 0xFF] return bytes[::-1] if endian.lower() == "little" else bytes def __repr__(self): return "Instruction(%s, %s, %s, %s, %s, %s)"% \ (self.name, self.rs, self.rt, self.rd, self.imm, self.label)