def get_j_type(self, opcode, address): OP = opcode >> 26 target = opcode & 0x3ffffff DR = self.decode_register if OP == 2: return ("j", [ir.jump(ir.constant_operand(((target<<2)&0xfffffff) + (address&0xf0000000)))]) elif OP == 3: return ("jal", [ir.operation(DR("$ra"),'=',DR('$pc'),'+',ir.constant_operand(4)), ir.call(ir.constant_operand(((target<<2)&0xfffffff) + (address&0xf0000000)), relative=0)])
def find_prologue(code, index, max_dist = 10): #only operation and store implemented right now #if you need a new IR type matched implement it above prologues = [ #push ebp; mov ebp, esp [ir.operation('stack', '=', 'stack', '-', ir.constant_operand(4)), ir.store('ebp','stack'), ir.operation('ebp', '=', 'stack')], #push 0; mov ebp, esp; and ebp, -16 [ir.operation('stack', '=', 'stack', '-', ir.constant_operand(4)), ir.store(ir.constant_operand(0),'stack'), ir.operation('ebp', '=', 'stack'), ir.operation('stack', '=', 'stack', '&', ir.constant_operand(-16))], #lea ecx, [4+esp] #gcc4.x main weirdness [ir.operation('tmem', '=', 'stack','+',ir.constant_operand(4)), ir.operation('ecx', '=', 'tmem')] ] #move backwards until a prologue or # a nop or # an epilogue is found # # for now the backwards limit is default 4 for pattern in prologues: j = 1 while j <= max_dist: if code[index-j].type == 'ret': return index - j + 1 elif code[index-j].type == 'operation': if 'NOP' in code[index-j].ops: return index - j + 1 sample = code[index-j:index-j+len(pattern)] if len(sample) == len(pattern): if match_template(pattern, code[index-j:index-j+len(pattern)]): return index - j j += 1 #return the original otherwise return index
def makeIR(self, instruction, size, operands, TMEM_IR, OPmode, addr): """ instruction -> dictionary of instruction information operands -> list of operand type and value TMEM_IR -> IR for complex memory access """ #print "-----make IR ------" m = instruction['mnemonic'] preload = False poststore = False #figure out if TMEM_IR is LOAD or STORE if TMEM_IR: #first operand is destination if 'reg/mem' in operands[0][0]: preload = True poststore = True elif 'reg/mem' in operands[1][0]: preload = True elif 'moffset' in operands[1][0]: preload = True IR = [] if m == "ADC": IR = [ir.operation(operands[0][1],'=',operands[0][1],'+',operands[1][1],'+',self.DR("CF"))] elif m == "ADD": IR = [ir.operation(operands[0][1],'=',operands[0][1],'+',operands[1][1])] elif m == "AND": IR = [ir.operation(operands[0][1],'=',operands[0][1],'&',operands[1][1])] elif m == "CALL": if poststore: poststore = False IR = [ir.operation(self.DR("TVAL"),'=',self.DR("EIP"),"+",ir.constant_operand(size)), ir.operation(self.DR("ESP",OPmode),'=',self.DR("ESP"),'-',ir.constant_operand(4)), ir.store(self.DR("TVAL"),self.DR("ESP",OPmode))] #absolute jump vs relative jump if 'rel' in operands[0][0]: IR += [ir.operation(self.DR("tval"),'=',self.DR("EIP"),"+",operands[0][1],'+',ir.constant_operand(size)), ir.call(self.DR("tval"), relative=True) ] else: IR += [ir.call(operands[0][1])] #controversial... analyzer must know callee _should_ do this #IR += [ir.operation(self.DR('esp'),'=',self.DR('esp'),'+',ir.constant_operand(4))] elif m == "CLC": IR = [ir.operation(self.DR("CF"), '=', ir.constant_operand(0))] elif m == "CLD": IR = [ir.operation(self.DR("DF"), '=', ir.constant_operand(0))] elif m == "CMP": if poststore: poststore = False IR = [ir.operation(operands[0][1],'-',operands[1][1])] elif m == "DEC": IR = [ir.operation(operands[0][1],'=',operands[0][1],'-',ir.constant_operand(1))] elif m == "INC": IR = [ir.operation(operands[0][1],'=',operands[0][1],'+',ir.constant_operand(1))] elif m == "IMUL": #XXXXX TODO FIX ME #EDX:EAX = a*b || IR = [ir.operation(operands[0][1], '=', operands[0][1], '*', operands[1][1])] if operands[0][1].register_name == 'eax': #TODO SIZE IR += [ir.operation(self.DR("EDX"), '=', '(', operands[0][1], '*', operands[1][1], ')', '>>', ir.constant_operand(32))] elif m == "JMP": if poststore: poststore = False #absolute jump vs relative jump if isinstance(operands[0][1], ir.constant_operand): DEST = ir.constant_operand(int(size + operands[0][1].value)) else: DEST = operands[0][1] if 'rel' in operands[0][0]: IR += [ir.jump(DEST,relative=True)] else: IR += [ir.jump(DEST)] elif 'J' == m[0]: #IR = [ir.operation(self.DR("tval"),'=',self.DR("EIP"),"+",operands[0][1])] DEST = ir.constant_operand(int(size + operands[0][1].value)) IR = [] if m == "JO": IR += [ir.operation(self.DR('OF'),'==',ir.constant_operand(1))] elif m == "JNO": IR += [ir.operation(self.DR('OF'),'==',ir.constant_operand(0))] elif m == "JB": IR += [ir.operation(self.DR('CF'),'==',ir.constant_operand(1))] elif m == "JNC": IR += [ir.operation(self.DR('CF'),'==',ir.constant_operand(0))] elif m == "JBE": IR += [ir.operation(self.DR('ZF'),'==',ir.constant_operand(1), '||', self.DR("CF"), '==', ir.constant_operand(1))] elif m == "JNBE": IR += [ir.operation(self.DR('ZF'),'==',ir.constant_operand(0), '&&', self.DR("CF"), '==', ir.constant_operand(0))] elif m == "JS": IR += [ir.operation(self.DR('SF'),'==',ir.constant_operand(1))] elif m == "JNS": IR += [ir.operation(self.DR('SF'),'==',ir.constant_operand(0))] elif m == "JP": IR += [ir.operation(self.DR('PF'),'==',ir.constant_operand(1))] elif m == "JNP": IR += [ir.operation(self.DR('PF'),'==',ir.constant_operand(0))] elif m == "JL": IR += [ir.operation(self.DR('SF'),'!=',self.DR('OF'))] elif m == "JNL": IR += [ir.operation(self.DR('SF'),'==',self.DR('OF'))] elif m == "JLE": IR += [ir.operation(self.DR('ZF'),'==',ir.constant_operand(1), '||', self.DR("SF"), '!=', self.DR("OF"))] elif m == "JNLE": IR += [ir.operation(self.DR('ZF'),'==',ir.constant_operand(0), '&&', self.DR("SF"), '==', self.DR("OF"))] elif m == "JNZ": IR += [ir.operation(self.DR('ZF'),'==',ir.constant_operand(1))] elif m == "JZ": IR += [ir.operation(self.DR('ZF'), '==', ir.constant_operand(0))] if 'rel' in operands[0][0]: IR += [ir.branch_true(DEST)] else: IR += [ir.branch_true(operands[0][1])] elif m == "LEA": preload = False poststore = False IR = [ir.operation(operands[0][1], '=', self.DR("TMEM"))] elif m == "LEAVE": # mov esp, ebp # pop ebp IR = [ir.operation(self.DR("ESP"),'=',self.DR("EBP")), ir.load(self.DR("ESP"), self.DR("EBP")), ir.operation(self.DR("ESP",OPmode), '=', self.DR("ESP",OPmode),"+",ir.constant_operand(4)) ] elif m == "MOV": #print hex(addr), operands if preload: if 'moffset' not in operands[1][0]: if operands[1][1].type != 'register' or operands[1][1].register_name != 'tval': preload = False if operands[0][1].type == 'register' and operands[0][1].register_name == 'tval': IR = [ir.operation(operands[1][1])] else: IR = [ir.operation(operands[0][1], '=', operands[1][1])] elif m == "MOVSX": #XXXXXX TODO sign extend IR = [ir.operation(operands[0][1], '=', operands[1][1])] elif m == "MOVZX": if '16' in operands[1][0]: mask = 0xff else: mask = 0xffff IR = [ir.operation(operands[0][1], '=', operands[1][1], '&', ir.constant_operand(mask))] elif m == "NOT": IR = [ir.operation(operands[0][1],'=','~',operands[0][1])] elif m == "OR": IR = [ir.operation(operands[0][1],'=',operands[0][1],'|',operands[1][1])] elif m == "POP": #TODO 0x20b6: pushl 0xff5b(%eax) no handled correctly IR = [ir.load(self.DR("ESP",OPmode), operands[0][1]), ir.operation(self.DR("ESP",OPmode), '=', self.DR("ESP",OPmode),"+",ir.constant_operand(4))] elif m == "PUSH": if type(operands[0][1]) == str: IR = [ir.unhandled_instruction(instruction['mnemonic'])] else: IR = [ir.operation(self.DR("ESP",OPmode), '=', self.DR("ESP",OPmode),"-",ir.constant_operand(4)), ir.store(operands[0][1], self.DR("ESP",OPmode)), ] if operands[0][1].type == 'register' and operands[0][1].register_name != 'tval': poststore = False elif m == "RET": #pop eip preload = True IR = [ir.load(self.DR("ESP",OPmode), self.DR('TVAL')), ir.operation(self.DR('ESP',OPmode),'=',self.DR("ESP",OPmode),'+',ir.constant_operand(4)), ir.ret(self.DR('TVAL'))] elif m == "ROL": #XXX TODO FIX sz here sz = operands[0][1].size IR = [ir.operation(operands[0][1], '=', operands[0][1], '<<', operands[1][1], '|', operands[0][1],'>>', '(', ir.constant_operand(sz),'-',operands[1][1],')')] elif m == "ROR": sz = operands[0][1].size IR = [ir.operation(operands[0][1], '=', operands[0][1], '>>', operands[1][1], '|', operands[0][1],'<<', '(', ir.constant_operand(sz),'-',operands[1][1],')')] elif m == "SAL": IR = [ir.operation(operands[0][1],'=', '(', self.DR("CF"), '<<', ir.constant_operand(32), '+', operands[0][1], ')','>>',operands[1][1])] elif m == "SAR": IR = [ir.operation(operands[0][1],'=', '(', self.DR("CF"), '>>', ir.constant_operand(32), '+', operands[0][1], ')','<<',operands[1][1])] elif m == "SHL": IR = [ir.operation(operands[0][1],'=', operands[0][1],'<<',operands[1][1])] elif m == "SHR": IR = [ir.operation(operands[0][1],'=', operands[0][1],'>>',operands[1][1])] elif m == "SUB": IR = [ir.operation(operands[0][1],'=', operands[0][1],'-',operands[1][1])] elif m == "TEST": IR = [ir.operation(operands[0][1],'&',operands[1][1])] elif m == "XCHG": have_nop = 0 if operands[0][1].type == 'register' and operands[1][1].type == 'register': if operands[0][1].register_name == "eax" and operands[1][1].register_name == "eax": have_nop = 1 #TODO does not play well with TMEM if have_nop: IR = [ir.operation("NOP")] else: #XXXXX TODO TMEM IR = [ir.operation(self.DR("tval"),'=',operands[0][1]), ir.operation(operands[0][1],'=', operands[1][1]), ir.operation(operands[1][1],'=', self.DR("TVAL"))] elif m == "XOR": IR = [ir.operation(operands[0][1],'=', operands[0][1],'^',operands[1][1])] else: IR = [ir.unhandled_instruction(instruction['mnemonic'])] if TMEM_IR: #print "@@"#, preload, poststore, TMEM_IR out = [] if preload: out += TMEM_IR + [ir.load(self.DR("TMEM"),self.DR("TVAL"))] elif TMEM_IR: if not poststore: out += TMEM_IR if poststore: if IR[0].type == 'operation': #XXX implicit load store hack if len(IR[0].ops) == 1: IR = [ir.operation(self.DR('tval'),'=', *(IR[0].ops))] out += IR + TMEM_IR + [ir.store(self.DR("tval"), self.DR('TMEM'))] else: out += IR return out return IR
def decode_operands(self, OP, instruction, data, mode): """ OP -> opcode instruction -> dictionary w/ instruction data data -> bytes following opcode mode -> addressing mode (based on prefixes) """ #helper functions def get_imm(sz, offset, data, signed=1): if sz == 1: return ir.constant_operand(ord(data[offset]), size=sz, signed=signed) elif sz == 2: return ir.constant_operand(struct.unpack('<H',data[offset:offset+2])[0], size=sz, signed=signed) elif sz == 4: return ir.constant_operand(struct.unpack('<L',data[offset:offset+4])[0], size=sz, signed=signed) else: print sz raise Exception("bad imm value") ##### operands = [] TMEM_IR = [] #IR translation for complex memory access reg_mem = None reg = None sib_displ = False sz = 0 if not instruction['modrm'] or '+' in instruction['modrm']: reg = self.DR(OP & 7, mode) else: #modrm looks like [mm][reg2][reg1] modrm = ord(data[sz]); sz += 1 mod = modrm >> 6 reg1 = modrm & 7 reg2 = (modrm>>3)& 7 Offset = None sib = None if mod != 3 and reg1 == 4: sib = ord(data[1]) sz += 1 #print 'modrm',mod if mod == 0: if reg1 == 5: #[displacement] TMEM_IR = [ir.operation(self.DR("TMEM",mode), '=', get_imm(mode/8, sz, data))] reg_mem = self.DR("TVAL", mode) sz += mode/8 else: #[reg1] -> store into temporary memory RegOne = self.DR(modrm & 7, mode) TMEM_IR = [ir.operation(self.DR("TMEM",mode),'=',RegOne)] reg_mem = self.DR("TVAL", mode) elif mod == 1: #[reg+ib] RegOne = self.DR(modrm & 7, mode) Offset = get_imm(1, sz, data) TMEM_IR = [ir.operation(self.DR("TMEM",mode),'=',RegOne,'+', Offset)] reg_mem = self.DR("TVAL", mode) sz += 1 elif mod == 2: #[reg+mode_offset] RegOne = self.DR(modrm & 7, mode) Offset = get_imm(mode/8, sz, data) TMEM_IR = [ir.operation(self.DR("TMEM",mode),'=',RegOne,'+', Offset)] reg_mem = self.DR("TVAL", mode) sz += mode/8 elif mod == 3: #reg + reg RegOne = self.DR(modrm & 7, mode) reg_mem = RegOne RegTwo = self.DR( (modrm >> 3)&7, mode) if sib: #redo TMEM_IR #ModRM with SIB: the reg field of the ModRM byte and the base and index fields of the SIB byte. #(Case 3 in Figure1-3 on page15 shows an example of this). #decode SIB #scale, index, base #[2][3][3] base = sib & 7 index = (sib >> 3)&7 scale = sib >> 6 base_reg = None index_reg = None if base != 5: base_reg = self.DR(base, mode) else: sib_displ = True base_reg = reg_mem #displacement value if index != 4: index_reg = self.DR(index, mode) #base + index*scale + offset oplist = [self.DR("TMEM",mode),'=',] if base_reg: oplist.append(base_reg) if index_reg: if len(oplist): oplist += ['+', index_reg, '*', ir.constant_operand(2**scale)] else: oplist += [index_reg,'*', ir.constant_operand(2**scale)] if Offset: oplist += ['+',Offset] TMEM_IR = [ir.operation(*oplist)] reg = RegTwo Immediate = None if instruction['immediate']: #XXXX signedness strings = {'ib': 1, 'iw' : 2, 'id': 4, 'iq': 8} length = strings[instruction['immediate']] #if mode == self.mode/2: # length /= 2 Immediate = get_imm(length, sz, data) sz += length code_offset = None if instruction['code_offset']: strings = {'cb': 1, 'cw' : 2, 'cd': 4, 'cq': 8, 'm64': 8} length = strings[instruction['code_offset']] code_offset = get_imm(length, sz, data) sz += length mem_addr = None #check for memory offsets in operand ( MOV A3 opcode, etc) for oper in instruction['operands']: if 'moffset%d'%mode in oper: length = mode/8 imm = get_imm(length, sz, data) mem_addr = self.DR("TVAL", mode) TMEM_IR = [ir.operation(self.DR("TMEM",mode),'=', imm)] sz += length #if sib had an immediate that didnt get picked up if sib_displ: if not mem_addr and not code_offset and not Immediate: length = self.mode/8 Immediate = get_imm(length, sz, data) TMEM_IR[0].ops = tuple(list(TMEM_IR[0].ops) + ['+', Immediate]) sz += length for oper in instruction['operands']: value = "" if 'reg/mem' in oper: value = reg_mem elif 'reg' in oper: value = reg elif 'moffset' in oper: value = mem_addr elif 'rel' in oper: if code_offset: value = code_offset else: value = Immediate elif 'imm' in oper: value = Immediate elif 'mem' in oper: value = reg_mem elif type(oper) == str: for y in ['EAX','AX','AL','DX','DL']: if y in oper.upper(): value = self.DR(y, mode) break elif 'EAX' in oper: value = self.DR('EAX', mode) elif 'AX' in oper: value = self.DR('AX', mode) elif 'AL' in oper: value = self.DR('AL', mode) else: print "XXX Hmmmm", oper operands.append((oper,value)) return sz, operands, TMEM_IR
def get_r_type(self, opcode): function = opcode & 0x3f rs = (opcode>>21) & 0x1f rt = (opcode>>16) & 0x1f rd = (opcode>>11) & 0x1f sa = (opcode>>6) & 0x1f DR = self.decode_register instructions = { 0 : ("sll rd = rt << sa", [ir.operation(DR(rd),"=",DR(rs),"<<",DR(sa), signed=0)]), 2 : ("srl rd = rt >> sa", [ir.operation(DR(rd),"=",DR(rs),">>",DR(sa), signed=0)]), 3 : ("sra rd = rt >> sa", [ir.operation(DR(rd),"=",DR(rs),">>",DR(sa))]), 4 : "sllv", 6 : "srlv", 7 : "srav", 8 : ("jr PC = rs", [ir.jump(DR(rs))]), 9 : ("jalr rd = return_addr, PC = rs ", [ir.operation(DR(rd),'=',DR("$pc"),"+",ir.constant_operand(4)), ir.call(DR(rs))]), 12 : "syscall", 13 : "break", 15 : "sync", 16 : ("mfhi", [ir.operation(DR(rd),'=',DR("HILO"))]), 17 : ("mthi", [ir.operation(DR("HILO"),'=',DR(rs),'<<',ir.constant_operand(32))]), 18 : ("mflo", [ir.operation(DR(rd),'=',DR("HILO"))]), 19 : ("mtlo", [ir.operation(DR("HILO"),'=',DR(rs))]), 24 : ("mult LO,HI = rs*rt", [ir.operation(DR("HILO"),"=",DR(rs),"*",DR(rt))]), 25 : ("multu", [ir.operation(DR("HILO"),"=",DR(rs),"*",DR(rt), signed=0)]), 26 : ("div", [ir.operation(DR("HILO"),"=",DR(rs),"/",DR(rt))]), 27 : ("divu", [ir.operation(DR("HILO"),"=",DR(rs),"/",DR(rt), signed=0)]), 28 : "dmult", 29 : "dmultu", 30 : "ddiv", 31 : "ddivu", 32 : ("add rd = rs + rt", [ir.operation(DR(rd),"=",DR(rs),"+",DR(rt))]), 33 : ("addu", [ir.operation(DR(rd),"=",DR(rs),"+",DR(rt), signed=0)]), 34 : ("sub", [ir.operation(DR(rd),'=',DR(rs),"-",DR(rt))]), 35 : ("subu", [ir.operation(DR(rd),'=',DR(rs),"-",DR(rt), signed=0)]), 36 : ("and", [ir.operation(DR(rd),"=",DR(rs),"&",DR(rt))]), 37 : ("or", [ir.operation(DR(rd),"=",DR(rs),"|",DR(rt))]), 38 : ("xor", [ir.operation(DR(rd),"=",DR(rs),"^",DR(rt))]), 39 : ("nor", [ir.operation(DR(rd),'=',DR(rs),"~",DR(rt))]), 42 : ("slt", [ir.operation(DR(rd),'=',DR(rs), "<", DR(rt))]), 43 : ("sltu", [ir.operation(DR(rd),'=',DR(rs), "<", DR(rt), signed=0)]), 45 : ("daddu", [ir.operation(DR(rd),'=',DR(rs), "+", DR(rt), signed=0)]), 47 : ("dsubu", [ir.operation(DR(rd),'=',DR(rs), "-", DR(rt), signed=0)]), 52 : "teq", 56 : "dssl", 58 : "todo", 59 : "dsra", 60 : "dsll32", 62 : "dsrl32", 63 : "dsra32" } if function in instructions: instr = instructions[function] if "jr" in instr[0]: if instr[1][0].dest == DR("$ra"): #this instruction is considered a 'ret' instr[1][0] = ir.ret(DR("$ra")) return instr else: raise Exception("unknown function code for R types: %d"%function)
def get_i_type(self, opcode): OP = opcode >> 26 offset = opcode & 0xffff rs = (opcode>>21) & 0x1f rt = (opcode>>16) & 0x1f rd = (opcode>>11) & 0x1f DR = self.decode_register instructions = { 4 : ("beq", [ir.operation(DR(rs),'==',DR(rt)), ir.branch_true(ir.constant_operand(((ir.sext16(offset)<<2)&0xfffffffff) + 4))]), 5 : ("bne", [ir.operation(DR(rs),'!=',DR(rt)), ir.branch_true(ir.constant_operand(((ir.sext16(offset)<<2)&0xfffffffff) + 4))]), 6 : ("blez", [ir.operation(DR(rs),'<=',ir.constant_operand(0)), ir.branch_true(ir.constant_operand(((ir.sext16(offset)<<2)&0xfffffffff) + 4))]), 7 : ("bgtz", [ir.operation(DR(rs),'>',ir.constant_operand(0)), ir.branch_true(ir.constant_operand(((ir.sext16(offset)<<2)&0xfffffffff) + 4))]), 8 : ("addi", #rt = rs + immediate [ir.operation(DR(rt),'=',DR(rs),'+',ir.constant_operand(offset,size=2))]), 9 : ("addiu", [ir.operation(DR(rt),'=',DR(rs),'+',ir.constant_operand(offset,size=2))]), 10 : ("slti", [ir.operation(DR(rt),'=',DR(rs),'<',ir.constant_operand(offset,size=2))]), 11 : ("sltiu", [ir.operation(DR(rt),'=',DR(rs),'<',ir.constant_operand(offset,size=2))]), 12 : ("andi", [ir.operation(DR(rt),'=',DR(rs),'&',ir.constant_operand(offset,size=2))]), 13 : ("ori", [ir.operation(DR(rt),'=',DR(rs),'|',ir.constant_operand(offset,size=2))]), 14 : ("xori", [ir.operation(DR(rd),"=",DR(rs),"^",ir.constant_operand(offset,size=2))]), 15 : ("lui", [ir.operation(DR(rt),'=',ir.constant_operand(offset,size=2),'<<',ir.constant_operand(16))]), 20 : ("beqzl", [ir.operation(DR(rs),'==',DR(rt)), ir.branch_true(ir.constant_operand(((ir.sext16(offset)<<2)&0xfffffffff) + 4))]), 21 : ("bnezl", [ir.operation(DR(rs),'!=',DR(rt)), ir.branch_true(ir.constant_operand(((ir.sext16(offset)<<2)&0xfffffffff) + 4))]), 22 : ("blezl", [ir.operation(DR(rs),'<=',ir.constant_operand(0)), ir.branch_true(ir.constant_operand(((ir.sext16(offset)<<2)&0xfffffffff) + 4))]), 23 : ("bgtzl", [ir.operation(DR(rs),'>',ir.constant_operand(0)), ir.branch_true(ir.constant_operand(((ir.sext16(offset)<<2)&0xfffffffff) + 4))]), 24 : ("daddi", [ir.operation(DR(rt),'=',DR(rs),'+',ir.constant_operand(offset,size=2,signed=1))]), 25 : ("daddiu", #unsigned is a misnomer [ir.operation(DR(rt),'=',DR(rs),'+',ir.constant_operand(offset,size=2,signed=1))]), 26 : "ldl", 27 : "ldr", 29 : "JALX", 32 : ("lb", [ir.operation(DR('TMEM'),'=',DR(rs),'+',ir.constant_operand(offset,size=2)), ir.load(DR('TMEM'), DR(rt),size=1)]), 33 : ("ll", #atmoic load words [ir.operation(DR('TMEM'),'=',DR(rs),'+',ir.constant_operand(offset,size=2)), ir.load(DR('TMEM'), DR(rt))]), 34 : "lwl", 35 : ("lw", [ir.operation(DR('TMEM'),'=',DR(rs),'+',ir.constant_operand(offset,size=2)), ir.load(DR('TMEM'),DR(rt))]), 36 : ("lbu", [ir.operation(DR('TMEM'),'=',DR(rs),'+',ir.constant_operand(offset,size=2)), ir.load(DR('TMEM'),DR(rt),size=1,signed=0)]), 37 : ("lhu", [ir.operation(DR('TMEM'),'=',DR(rs),'+',ir.constant_operand(offset,size=2)), ir.load(DR('TMEM'),DR(rt),size=2,signed=0)]), 38 : "lwr", #todo 39 : ("lw", [ir.operation(DR('TMEM'),'=',DR(rs),'+',ir.constant_operand(offset,size=2)), ir.load(DR('TMEM'),DR(rt))]), 40 : ("sb", [ir.operation(DR('TMEM'),'=',DR(rs),'+',ir.constant_operand(offset,size=2)), ir.store(DR(rt),DR('TMEM'),size=1)]), 41 : ("sh", [ir.operation(DR('TMEM'),'=',DR(rs),'+',ir.constant_operand(offset,size=2)), ir.store(DR(rt),DR('TMEM'),size=2)]), 42 : "swl", 43 : ("sw", [ir.operation(DR('TMEM'),'=',DR(rs),'+',ir.constant_operand(offset,size=2)), ir.store(DR(rt),DR('TMEM'))]), 44 : "sdl", 45 : "sdr", 46 : "swr", 49 : "lwc1", 53 : "ldc1", 55 : ("ld", [ir.operation(DR('TMEM'),'=',DR(rs),'+',ir.constant_operand(offset,size=2)), ir.load(DR('TMEM'),DR(rt),size=8)]), 57 : "swc1", 61 : "sdc1", 63 : ("sd", [ir.operation(DR('TMEM'),'=',DR(rs),'+',ir.constant_operand(offset,size=2)), ir.store(DR(rt), DR('TMEM'),size=8)]) } try: if OP == 1: code = rt if code in [0,2]: #BLTZ, BLTZL instr = ("bltz",[ir.operation(DR(rs),'<',ir.constant_operand(0)), ir.branch_true(ir.constant_operand(((ir.sext16(offset)<<2)&0xfffffffff) + 4))]) elif code in [1,3]: #BGEZ, BGEZL instr = ("bltz",[ir.operation(DR(rs),'>=',ir.constant_operand(0)), ir.branch_true(ir.constant_operand(((ir.sext16(offset)<<2)&0xfffffffff) + 4))]) elif code in [16,18]: #BLTZAL, BLTZALL instr = ("bltzal",[ir.operation(DR(rs),'<',ir.constant_operand(0)), ir.operation(DR("$ra"),'=',DR("$pc"),'+',ir.constant_operand(4)), ir.call(ir.constant_operand(((ir.sext16(offset)<<2)&0xfffffffff) + 4),relative=0)]) elif code in [17,19]: #BGEZAL,BGEZALL instr = ("bgezal",[ir.operation(DR(rs),'>=',ir.constant_operand(0)), ir.operation(DR("$ra"),'=',DR("$pc"),'+',ir.constant_operand(4)), ir.call(ir.constant_operand(((ir.sext16(offset)<<2)&0xfffffffff) + 4), relative=0)]) else: instr = instructions[OP] return instr except KeyError: raise KeyError("unknown op code for I types: %d"%OP)