Package envi :: Package archs :: Package arm :: Module thumb
[hide private]
[frames] | no frames]

Source Code for Module envi.archs.arm.thumb

  1  
 
  2  import envi.bits as e_bits 
  3  from envi.bits import binary 
  4  import envi.bintree as e_btree 
  5  
 
  6  import envi.archs.arm.disasm as arm_dis 
  7  import envi.archs.arm.armdisasm as arm_armdis 
  8  import envi.archs.arm.regs as arm_reg 
  9  
 
 10  thumb_32 = [
 
 11          binary('11101'),
 
 12          binary('11110'),
 
 13          binary('11111'),
 
 14  ] 
 15  
 
 16  O_REG = 0 
 17  O_IMM = 1 
 18  
 
19 -def shmaskval(value, shval, mask): #FIXME: unnecessary to make this another fn call. will be called a bajillion times.
20 return (value >> shval) & mask 21
22 -class simpleops:
23 - def __init__(self, *operdef):
24 self.operdef = operdef
25
26 - def __call__(self, va, value):
27 ret = [] 28 for otype, shval, mask in self.operdef: 29 oval = shmaskval(value, shval, mask) 30 31 ret.append( (value >> shval) )
32 33 imm5_rm_rd = simpleops((O_REG, 0, 0x7), (O_REG, 3, 0x7), (O_IMM, 6, 0x1f)) 34 rm_rn_rd = simpleops((O_REG, 0, 0x7), (O_REG, 3, 0x7), (O_REG, 6, 0x7)) 35 imm3_rn_rd = simpleops((O_REG, 0, 0x7), (O_REG, 3, 0x7), (O_IMM, 6, 0x7)) 36 imm8_rd = simpleops((O_REG, 8, 0x7), (O_IMM, 0, 0xff)) 37 rm_rd = simpleops((O_REG, 0, 0x7), (O_REG, 3, 0x7)) 38 rn_rdm = simpleops((O_REG, 0, 0x7), (O_REG, 3, 0x7)) 39 rm_rdn = simpleops((O_REG, 0, 0x7), (O_REG, 3, 0x7)) 40 rm_rd_imm0 = simpleops((O_REG, 0, 0x7), (O_REG, 3, 0x7), (O_IMM, 0, 0)) 41 rm4_shift3 = simpleops((O_REG, 3, 0xf)) 42 rm_rn_rt = simpleops((O_REG, 0, 0x7), (O_REG, 3, 0x7), (O_REG, 6, 0x7)) 43 imm8 = simpleops((O_IMM, 8, 0xff)) 44 imm11 = simpleops((O_IMM, 11, 0x7ff)) 45 46 sh4_imm1 = simpleops((O_IMM, 3, 0x1)) 47
48 -def d1_rm4_rd3(va, value):
49 # 0 1 0 0 0 1 0 0 DN(1) Rm(4) Rdn(3) 50 rdbit = shmaskval(value, 4, 0x8) 51 rd = shmaskval(value, 0, 0x7) + rdbit 52 rm = shmaskval(value, 3, 0xf) 53 return ArmRegOper(rd),ArmRegOper(rn)
54
55 -def rm_rn_rt(va, value):
56 rt = shmask(value, 0, 0x7) # target 57 rn = shmask(value, 3, 0x7) # base 58 rm = shmask(value, 6, 0x7) # offset 59 oper0 = arm_dis.ArmRegOper(rt) 60 oper1 = arm_dis.ArmRegOffsetOper(rn, rm, va) 61 return oper0,oper1
62
63 -def imm5_rn_rt(va, value):
64 imm = shmask(value, 6, 0x1f) 65 rn = shmask(value, 3, 0x7) 66 rt = shmask(value, 0, 0x7) 67 oper0 = arm_dis.ArmRegOper(rt) 68 oper1 = arm_dis.ArmImmOffsetOper(rn, imm, va) 69 return oper0,oper1
70
71 -def rd_sp_imm8(va, value):
72 rd = shmask(value, 8, 0x7) 73 imm = shmask(value, 0, 0xff) 74 oper0 = arm_dis.ArmRegOper(rd) 75 # pre-compute PC relative addr 76 oper1 = arm_dis.ArmImmOffsetOper(REG_SP, imm) 77 return oper0,oper1
78
79 -def rd_pc_imm8(va, value):
80 rd = shmask(value, 8, 0x7) 81 imm = shmask(value, 0, 0xff) 82 oper0 = arm_dis.ArmRegOper(rd) 83 # pre-compute PC relative addr 84 oper1 = arm_dis.ArmImmOper(va+imm) 85 return oper0,oper1
86
87 -def rt_pc_imm8(va, value):
88 rt = shmask(value, 8, 0x7) 89 imm = shmask(value, 0, 0xff) 90 oper0 = arm_dis.ArmRegOper(rt) 91 oper1 = arm_dis.ArmImmOffsetOper() # FIXME offset from PC 92 return oper0,oper1
93
94 -def ldmia(va, value):
95 rd = shmask(value, 8, 0x7) 96 reg_list = value & 0xff 97 oper0 = arm_dis.ArmRegOper(rd) 98 oper1 = arm_dis.ArmRegListOper(reg_list) 99 flags = 1<<11 # W flag indicating that write back should occur (marked by "!") 100 return oper0,oper1 101
102 -def sp_sp_imm7(va, value):
103 imm = shmask(value, 0, 0x7f) 104 o0 = arm_dis.ArmRegOper(arm_reg.REG_SP) 105 o1 = arm_dis.ArmRegOper(arm_reg.REG_SP) 106 o2 = arm_dis.ArmImmOper(imm*4) 107 return o0,o1,o2
108
109 -def rm_reglist(va, value):
110 rm = shmask(value, 8, 0x7) 111 reglist = value & 0xff 112 oper0 = arm_dis.ArmRegOper(rm) 113 oper1 = arm_dis.ArmReglistOper(reglist) 114 return oper0,oper1
115 116 117 # opinfo is: 118 # ( <mnem>, <operdef>, <flags> ) 119 # operdef is: 120 # ( (otype, oshift, omask), ...) 121 thumb_table = [ 122 ('00000', ('lsl', imm5_rm_rd, 0)), # LSL<c> <Rd>,<Rm>,#<imm5> 123 ('00001', ('lsr', imm5_rm_rd, 0)), # LSR<c> <Rd>,<Rm>,#<imm> 124 ('00010', ('asr', imm5_rm_rd, 0)), # ASR<c> <Rd>,<Rm>,#<imm> 125 ('0001100', ('add', rm_rn_rd, 0)), # ADD<c> <Rd>,<Rn>,<Rm> 126 ('0001101', ('sub', rm_rn_rd, 0)), # SUB<c> <Rd>,<Rn>,<Rm> 127 ('0001110', ('add', imm3_rn_rd, 0)), # ADD<c> <Rd>,<Rn>,#<imm3> 128 ('0001111', ('sub', imm3_rn_rd, 0)), # SUB<c> <Rd>,<Rn>,#<imm3> 129 ('00100', ('mov', imm8_rd, 0)), # MOV<c> <Rd>,#<imm8> 130 ('00101', ('cmp', imm8_rd, 0)), # CMP<c> <Rn>,#<imm8> 131 ('00110', ('add', imm8_rd, 0)), # ADD<c> <Rdn>,#<imm8> 132 ('00111', ('sub', imm8_rd, 0)), # SUB<c> <Rdn>,#<imm8> 133 # Data processing instructions 134 ('0100000000', ('and', rm_rdn, 0)), # AND<c> <Rdn>,<Rm> 135 ('0100000001', ('eor', rm_rdn, 0)), # EOR<c> <Rdn>,<Rm> 136 ('0100000010', ('lsl', rm_rdn, 0)), # LSL<c> <Rdn>,<Rm> 137 ('0100000011', ('lsr', rm_rdn, 0)), # LSR<c> <Rdn>,<Rm> 138 ('0100000100', ('asr', rm_rdn, 0)), # ASR<c> <Rdn>,<Rm> 139 ('0100000101', ('adc', rm_rdn, 0)), # ADC<c> <Rdn>,<Rm> 140 ('0100000110', ('sbc', rm_rdn, 0)), # SBC<c> <Rdn>,<Rm> 141 ('0100000111', ('ror', rm_rdn, 0)), # ROR<c> <Rdn>,<Rm> 142 ('0100001000', ('tst', rm_rd, 0)), # TST<c> <Rn>,<Rm> 143 ('0100001001', ('rsb', rm_rd_imm0, 0)), # RSB<c> <Rd>,<Rn>,#0 144 ('0100001010', ('cmp', rm_rd, 0)), # CMP<c> <Rn>,<Rm> 145 ('0100001011', ('cmn', rm_rd, 0)), # CMN<c> <Rn>,<Rm> 146 ('0100001100', ('orr', rm_rdn, 0)), # ORR<c> <Rdn>,<Rm> 147 ('0100001101', ('mul', rn_rdm, 0)), # MUL<c> <Rdm>,<Rn>,<Rdm> 148 ('0100001110', ('bic', rm_rdn, 0)), # BIC<c> <Rdn>,<Rm> 149 ('0100001111', ('mvn', rm_rd, 0)), # MVN<c> <Rd>,<Rm> 150 # Special data instructions and branch and exchange 151 ('0100010000', ('add', d1_rm4_rd3, 0)), # ADD<c> <Rdn>,<Rm> 152 ('0100010001', ('add', d1_rm4_rd3, 0)), # ADD<c> <Rdn>,<Rm> 153 ('010001001', ('add', d1_rm4_rd3, 0)), # ADD<c> <Rdn>,<Rm> 154 ('0100010101', ('cmp', d1_rm4_rd3, 0)), # CMP<c> <Rn>,<Rm> 155 ('010001011', ('cmp', d1_rm4_rd3, 0)), # CMP<c> <Rn>,<Rm> 156 ('0100011000', ('mov', d1_rm4_rd3, 0)), # MOV<c> <Rd>,<Rm> 157 ('0100011001', ('mov', d1_rm4_rd3, 0)), # MOV<c> <Rd>,<Rm> 158 ('0100011010', ('mov', d1_rm4_rd3, 0)), # MOV<c> <Rd>,<Rm> 159 ('010001110', ('bx', rm4_shift3, 0)), # BX<c> <Rm> 160 ('010001111', ('blx', rm4_shift3, 0)), # BLX<c> <Rm> 161 # Load from Literal Pool 162 ('01001', ('ldr', rt_pc_imm8, 0)), # LDR<c> <Rt>,<label> 163 # Load/Stor single data item 164 ('0101000', ('str', rm_rn_rt, 0)), # STR<c> <Rt>,[<Rn>,<Rm>] 165 ('0101001', ('strh', rm_rn_rt, 0)), # STRH<c> <Rt>,[<Rn>,<Rm>] 166 ('0101010', ('strb', rm_rn_rt, 0)), # STRB<c> <Rt>,[<Rn>,<Rm>] 167 ('0101011', ('ldrsb', rm_rn_rt, 0)), # LDRSB<c> <Rt>,[<Rn>,<Rm>] 168 ('0101100', ('ldr', rm_rn_rt, 0)), # LDR<c> <Rt>,[<Rn>,<Rm>] 169 ('0101101', ('ldrh', rm_rn_rt, 0)), # LDRH<c> <Rt>,[<Rn>,<Rm>] 170 ('0101110', ('ldrb', rm_rn_rt, 0)), # LDRB<c> <Rt>,[<Rn>,<Rm>] 171 ('0101111', ('ldrsh', rm_rn_rt, 0)), # LDRSH<c> <Rt>,[<Rn>,<Rm>] 172 ('01100', ('str', imm5_rn_rt, 0)), # STR<c> <Rt>, [<Rn>{,#<imm5>}] 173 ('01101', ('ldr', imm5_rn_rt, 0)), # LDR<c> <Rt>, [<Rn>{,#<imm5>}] 174 ('01110', ('strb', imm5_rn_rt, 0)), # STRB<c> <Rt>,[<Rn>,#<imm5>] 175 ('01111', ('ldrb', imm5_rn_rt, 0)), # LDRB<c> <Rt>,[<Rn>{,#<imm5>}] 176 ('10000', ('strh', imm5_rn_rt, 0)), # STRH<c> <Rt>,[<Rn>{,#<imm>}] 177 ('10001', ('ldrh', imm5_rn_rt, 0)), # LDRH<c> <Rt>,[<Rn>{,#<imm>}] 178 ('10010', ('str', imm5_rn_rt, 0)), # STR<c> <Rt>, [<Rn>{,#<imm>}] 179 ('10011', ('ldr', imm5_rn_rt, 0)), # LDR<c> <Rt>, [<Rn>{,#<imm>}] 180 # Generate PC relative address 181 ('10100', ('add', rd_pc_imm8, 0)), # ADD<c> <Rd>,<label> 182 # Generate SP relative address 183 ('10101', ('add', rd_sp_imm8, 0)), # ADD<c> <Rd>,SP,#<imm> 184 # Miscellaneous instructions 185 ('10110110010', ('setend', sh4_imm1, 0)), # SETEND <endian_specifier> 186 ('10110110011', ('cps', simpleops(),0)), # CPS<effect> <iflags> FIXME 187 ('1011101000', ('rev', rn_rdm, 0)), # REV Rd, Rn 188 ('1011101001', ('rev16', rn_rdm, 0)), # REV16 Rd, Rn 189 ('1011101011', ('revsh', rn_rdm, 0)), # REVSH Rd, Rn 190 ('101100000', ('add', sp_sp_imm7, 0)), # ADD<c> SP,SP,#<imm> 191 ('101100001', ('sub', sp_sp_imm7, 0)), # SUB<c> SP,SP,#<imm> 192 ('10111110', ('bkpt', imm8, 0)), # BKPT <blahblah> 193 # Load / Store Multiple 194 ('11000', ('stmia', rm_reglist, 0x800)), # LDMIA Rd!, reg_list 195 ('11001', ('ldmia', rm_reglist, 0x800)), # STMIA Rd!, reg_list 196 # Conditional Branches 197 ('11010000', ('b', imm8, 0)), 198 ('11010001', ('bn', imm8, 0)), 199 ('11010010', ('bz', imm8, 0)), 200 ('11010011', ('bnz', imm8, 0)), 201 ('11010100', ('bc', imm8, 0)), 202 ('11010101', ('bnc', imm8, 0)), 203 ('11010100', ('bzc', imm8, 0)), 204 ('11010111', ('bnzc', imm8, 0)), 205 ('11011000', ('bv', imm8, 0)), 206 ('11011001', ('bnv', imm8, 0)), 207 ('11011010', ('bzv', imm8, 0)), 208 ('11011011', ('bnzv', imm8, 0)), 209 ('11011100', ('bcv', imm8, 0)), 210 ('11011101', ('bncv', imm8, 0)), 211 ('11011110', ('bzcv', imm8, 0)), 212 ('11011111', ('bnzcv', imm8, 0)), 213 # Software Interrupt 214 ('11011111', ('swi', imm8, 0)), # SWI <blahblah> 215 ('11100', ('b', imm11, 0)), # B <addr11> 216 ('11101', ('blx', imm11, 0)), # BLX suffix <addr11> -- SEE p542 of 14218.pdf manual for how this if gonna fuck with emulation. 217 ('11110', ('bl', imm11, 0)), # BL/BLX prefix <addr11> -- SEE p542 of 14218.pdf manual for how this if gonna fuck with emulation. 218 ('11111', ('blx', imm11, 0)), # BL suffix <addr11> -- SEE p542 of 14218.pdf manual for how this if gonna fuck with emulation. 219 ] 220 221 ttree = e_btree.BinaryTree() 222 for binstr, opinfo in thumb_table: 223 ttree.addBinstr(binstr, opinfo) 224 225 thumb32mask = binary('11111') 226 thumb32min = binary('11100') 227
228 -def is_thumb32(val):
229 ''' 230 Take a 16 bit integer (opcode) value and determine 231 if it is really the first 16 bits of a 32 bit 232 instruction. 233 ''' 234 bval = val >> 11 235 return (bval & thumb32mask) > thumb32min
236 237
238 -class ThumbOpcode(arm_armdis.ArmOpcode):
239 pass
240 241 #class ArmThumbDisasm(arm_armdis.ArmDisasmChild): 242 243 #def disasm(self, bytes, offset, va, trackMode=True): 244 #val = struct.unpack("<L", bytes[offset:offset+2]) 245 #mnem, opermkr, flags = ttree.getInstr(val) 246 #olist = opermkr(va, val) 247 248 #op = ThumbOpcode(va, opcode, mnem, 0xe, 2, olist, flags) 249 #return op 250 #raise Exception("ummm. you could try Implementing disasm first... duh.") 251