Ejemplo n.º 1
0
 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)])
Ejemplo n.º 2
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    
Ejemplo n.º 3
0
  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
Ejemplo n.º 4
0
  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
Ejemplo n.º 5
0
 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)
Ejemplo n.º 6
0
  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)