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

Source Code for Module envi.arm

  1   
  2  """ 
  3  The initial arm module. 
  4  """ 
  5   
  6  import struct 
  7   
  8  import envi 
  9   
 10  # FIXME put this in envi bits. 
11 -def binary(s):
12 x = 0 13 for c in s: 14 x = (x << 1) + int(c) 15 return x
16 17 # Universal opcode things: 18 # len 19 # mode 20 21 IF_PSR_S = 0x100 22 23 COND_EQ = 0x0 # z==1 (equal) 24 COND_NE = 0x1 # z==0 (not equal) 25 COND_CS = 0x2 # c==1 (carry set/unsigned higher or same) 26 COND_CC = 0x3 # c==0 (carry clear/unsigned lower) 27 COND_MI = 0x4 # n==1 (minus/negative) 28 COND_PL = 0x5 # n==0 (plus/positive or zero) 29 COND_VS = 0x6 # v==1 (overflow) 30 COND_VC = 0x7 # v==0 (no overflow) 31 COND_HI = 0x8 # c==1 and z==0 (unsigned higher) 32 COND_LO = 0x9 # c==0 or z==1 (unsigned lower or same) 33 COND_GE = 0xA # n==v (signed greater than or equal) (n==1 and v==1) or (n==0 and v==0) 34 COND_LT = 0xB # n!=v (signed less than) (n==1 and v==0) or (n==0 and v==1) 35 COND_GT = 0xC # z==0 and n==v (signed greater than) 36 COND_LE = 0xD # z==1 and n!=v (signed less than or equal) 37 COND_AL = 0xE # always 38 COND_EXTENDED = 0xF # special case - see conditional 0b1111 39 40 COND_EQ = 0 41 COND_NE = 1 42 COND_CS = 2 43 COND_CC = 3 44 COND_MI = 4 45 COND_PL = 5 46 COND_VS = 6 47 COND_VC = 7 48 COND_HI = 8 49 COND_LS = 9 50 COND_GE = 10 51 COND_LT = 11 52 COND_GT = 12 53 COND_LE = 13 54 COND_AL = 14 55 COND_EXTENDED = 15 56 57 cond_codes = { 58 COND_EQ:"EQ", # Equal Z set 59 COND_NE:"NE", # Not equal Z clear 60 COND_CS:"CS", #/HS Carry set/unsigned higher or same C set 61 COND_CC:"CC", #/LO Carry clear/unsigned lower C clear 62 COND_MI:"MI", # Minus/negative N set 63 COND_PL:"PL", # Plus/positive or zero N clear 64 COND_VS:"VS", # Overflow V set 65 COND_VC:"VC", # No overflow V clear 66 COND_HI:"HI", # Unsigned higher C set and Z clear 67 COND_LS:"LS", # Unsigned lower or same C clear or Z set 68 COND_GE:"GE", # Signed greater than or equal N set and V set, or N clear and V clear (N == V) 69 COND_LT:"LT", # Signed less than N set and V clear, or N clear and V set (N!= V) 70 COND_GT:"GT", # Signed greater than Z clear, and either N set and V set, or N clear and V clear (Z == 0,N == V) 71 COND_LE:"LE", # Signed less than or equal Z set, or N set and V clear, or N clear and V set (Z == 1 or N!= V) 72 COND_AL:"AL", # Always (unconditional) - 73 COND_EXTENDED:"EXTENDED", # See extended opcode table 74 } 75 76 INST_ENC_DP_IMM = 0 # Data Processing Immediate Shift 77 INST_ENC_MISC = 1 # Misc Instructions 78 79 # Instruction encodings in arm v5 80 IENC_DP_IMM_SHIFT = 0 # Data processing immediate shift 81 IENC_MISC = 1 # Miscellaneous instructions 82 IENC_DP_REG_SHIFT = 2 # Data processing register shift 83 IENC_MISC1 = 3 # Miscellaneous instructions again 84 IENC_MULT = 4 # Multiplies & Extra load/stores 85 IENC_DP_IMM = 5 # Data processing immediate 86 IENC_UNDEF = 6 # Undefined instruction 87 IENC_MOV_IMM_STAT = 7 # Move immediate to status register 88 IENC_LOAD_IMM_OFF = 8 # Load/Store immediate offset 89 IENC_LOAD_REG_OFF = 9 # Load/Store register offset 90 IENC_MEDIA = 10 # Media instructions 91 IENC_ARCH_UNDEF = 11 # Architecturally undefined 92 IENC_LOAD_MULT = 12 # Load/Store Multiple 93 IENC_BRANCH = 13 # Branch 94 IENC_COPROC_LOAD = 14 # Coprocessor load/store and double reg xfers 95 IENC_COPROC_DP = 15 # Coprocessor data processing 96 IENC_COPROC_REG_XFER = 16 # Coprocessor register transfers 97 IENC_SWINT = 17 # Sofware interrupts 98 99 #################################################################### 100 # Parsers for the multiply family of instruction encodings 101
102 -def chopmul(opcode):
103 op1 = (opcode >> 20) & 0xff 104 a = (opcode >> 16) & 0xf 105 b = (opcode >> 12) & 0xf 106 c = (opcode >> 8) & 0xf 107 d = (opcode >> 4) & 0xf 108 e = opcode & 0xf 109 return (op1<<4)+d,(a,b,c,d,e)
110 111 # The keys in this table are made of the 112 # concat of bits 27-21 and 7-4 (only when 113 # ienc == mul! 114 iencmul_codes = { 115 # Basic multiplication opcodes 116 binary("000000001001"): ("mul",(0,4,2), 0), 117 binary("000000011001"): ("mul",(0,4,2), IF_PSR_S), 118 binary("000000101001"): ("mla",(0,4,2,1), 0), 119 binary("000000111001"): ("mla",(0,4,2,1), IF_PSR_S), 120 binary("000001001001"): ("umaal",(1,0,4,2), 0), 121 binary("000010001001"): ("umull",(1,0,4,2), 0), 122 binary("000010011001"): ("umull",(1,0,4,2), IF_PSR_S), 123 binary("000010101001"): ("umlal",(1,0,4,2), 0), 124 binary("000010111001"): ("umlal",(1,0,4,2), IF_PSR_S), 125 binary("000011001001"): ("smull",(1,0,4,2), 0), 126 binary("000011011001"): ("smull",(1,0,4,2), IF_PSR_S), 127 binary("000011101001"): ("smlal",(1,0,4,2), 0), 128 binary("000011111001"): ("smlal",(1,0,4,2), IF_PSR_S), 129 130 # multiplys with <x><y> 131 # "B" 132 binary("000100001000"): ("smlabb", (0,4,2,1), 0), 133 binary("000100001010"): ("smlatb", (0,4,2,1), 0), 134 binary("000100001100"): ("smlabt", (0,4,2,1), 0), 135 binary("000100001110"): ("smlatt", (0,4,2,1), 0), 136 binary("000100101010"): ("smulwb", (0,4,2), 0), 137 binary("000100101110"): ("smulwt", (0,4,2), 0), 138 binary("000100101000"): ("smlawb", (0,4,2), 0), 139 binary("000100101100"): ("smlawt", (0,4,2), 0), 140 binary("000101001000"): ("smlalbb", (1,0,4,2), 0), 141 binary("000101001010"): ("smlaltb", (1,0,4,2), 0), 142 binary("000101001100"): ("smlalbt", (1,0,4,2), 0), 143 binary("000101001110"): ("smlaltt", (1,0,4,2), 0), 144 binary("000101101000"): ("smulbb", (0,4,2), 0), 145 binary("000101101010"): ("smultb", (0,4,2), 0), 146 binary("000101101100"): ("smulbt", (0,4,2), 0), 147 binary("000101101110"): ("smultt", (0,4,2), 0), 148 149 # type 2 multiplys 150 151 binary("011100000001"): ("smuad", (0,4,2), 0), 152 binary("011100000011"): ("smuadx", (0,4,2), 0), 153 binary("011100000101"): ("smusd", (0,4,2), 0), 154 binary("011100000111"): ("smusdx", (0,4,2), 0), 155 binary("011100000001"): ("smlad", (0,4,2), 0), 156 binary("011100000011"): ("smladx", (0,4,2), 0), 157 binary("011100000101"): ("smlsd", (0,4,2), 0), 158 binary("011100000111"): ("smlsdx", (0,4,2), 0), 159 binary("011101000001"): ("smlald", (0,4,2), 0), 160 binary("011101000011"): ("smlaldx", (0,4,2), 0), 161 binary("011101000101"): ("smlsld", (0,4,2), 0), 162 binary("011101000111"): ("smlsldx", (0,4,2), 0), 163 binary("011101010001"): ("smmla", (0,4,2,1), 0), 164 binary("011101010011"): ("smmlar", (0,4,2,1), 0), 165 binary("011101011101"): ("smmls", (0,4,2,1), 0), 166 binary("011101011111"): ("smmlsr", (0,4,2,1), 0), 167 binary("011101010001"): ("smmul", (0,4,2), 0), 168 binary("011101010011"): ("smmulr", (0,4,2), 0), 169 } 170 171 #################################################################### 172 # Mnemonic tables for opcode based mnemonic lookup 173 174 # Dataprocessing mnemonics 175 dp_mnem = ("and","eor","sub","rsb","add","adc","sbc","rsc","tst","teq","cmp","cmn","orr","mov","bic","mvn"), 176 misc_mnem = ("mrs","msr","bxj") 177
178 -def dpbase(opval):
179 """ 180 Parse and return opcode,sflag,Rn,Rd for a standard 181 dataprocessing instruction. 182 """ 183 ocode = (opval >> 21) & 0xf 184 sflag = (opval >> 20) & 0x1 185 Rn = (opval >> 16) & 0xf 186 Rd = (opval >> 12) & 0xf 187 #print "DPBASE:",ocode,sflag,Rn,Rd 188 return ocode,sflag,Rn,Rd
189 190 #################################################################### 191 # Parser functions for each of the instruction encodings 192
193 -def p_dp_imm_shift(opval):
194 ocode,sflag,Rn,Rd = dpbase(opval) 195 Rm = opval & 0xf 196 shtype = (opval >> 5) & 0x3 197 shval = (opval >> 7) & 0x1f 198 199 olist = [ 200 ArmOperand(OM_REG, Rn), 201 ArmOperand(OM_REG, Rd), 202 ArmOperand(OM_REG, Rm, shtype=shtype, shval=shval), 203 ] 204 205 opcode = (IENC_DP_IMM_SHIFT << 16) + ocode 206 return ArmOpcode(opcode, dp_mnem[ocode], olist)
207
208 -def p_misc(opval):
209 pass
210
211 -def p_dp_reg_shift(opval):
212 ocode,sflag,Rn,Rd = dpbase(opval) 213 Rm = opval & 0xf 214 shtype = (opval >> 5) & 0x3 215 Rs = (opval >> 8) & 0xf 216 217 olist = [ 218 ArmOperand(OM_REG, Rn), 219 ArmOperand(OM_REG, Rd), 220 ArmOperand(OM_REG, Rm, oflags=OFLAG_SHIFT_REG, shtype=shtype, shval=shval), 221 ] 222 223 opcode = (IENC_DP_IMM_SHIFT << 16) + ocode 224 return ArmOpcode(opcode, dp_mnem[ocode], olist)
225
226 -def p_misc1(opval):
227 pass
228
229 -def p_mult(opval):
230 ocode, vals = chopmul(opval) 231 232 mnem, opindexes, flags = iencmul_codes.get(ocode) 233 234 olist = [] 235 for i in opindexes: 236 olist.append(ArmOperand(OM_REG, vals[i])) 237 238 opcode = (IENC_MULT << 16) + ocode 239 return ArmOpcode(opcode, mnem, olist, iflags=flags)
240
241 -def p_dp_imm(opval):
242 ocode,sflag,Rn,Rd = dpbase(opval) 243 imm = opval & 0xff 244 rot = (opval >> 8) & 0xf
245
246 -def p_undef(opval):
247 pass
248
249 -def p_mov_imm_stat(opval):
250 pass
251
252 -def p_load_imm_off(opval):
253 pass
254
255 -def p_load_reg_off(opval):
256 pass
257
258 -def p_media(opval):
259 pass
260
261 -def p_arch_undef(opval):
262 pass
263
264 -def p_load_mult(opval):
265 pass
266
267 -def p_branch(opval):
268 pass
269
270 -def p_coproc_load(opval):
271 pass
272
273 -def p_coproc_dp(opval):
274 pass
275
276 -def p_coproc_reg_xfer(opval):
277 pass
278
279 -def p_swint(opval):
280 pass
281 282 #################################################################### 283 # Table of the parser functions 284 285 ienc_parsers = ( 286 p_dp_imm_shift, 287 p_misc, 288 p_dp_reg_shift, 289 p_misc1, 290 p_mult, 291 p_dp_imm, 292 p_undef, 293 p_mov_imm_stat, 294 p_load_imm_off, 295 p_load_reg_off, 296 p_media, 297 p_arch_undef, 298 p_load_mult, 299 p_branch, 300 p_coproc_load, 301 p_coproc_dp, 302 p_coproc_reg_xfer, 303 p_swint, 304 ) 305 306 #################################################################### 307 308 # the primary table is index'd by the 3 bits following the 309 # conditional and are structured as follows: 310 # ( ENC, nexttable ) 311 # If ENC != None, those 3 bits were enough for us to know the 312 # encoding type, otherwise move on to the second table. 313 314 # The secondary tables have the format: 315 # (mask, value, ENC). If the opcode is masked with "mask" 316 # resulting in "value" we have found the instruction encoding. 317 # NOTE: All entries in these tables *must* be from most specific 318 # to least! 319 320 # Table for initial 3 bit == 0 321 s_0_table = ( 322 # Order is critical here... 323 (binary("00000001100100000000000000010000"), binary("00000001000000000000000000000000"), IENC_MISC), 324 (binary("00000000000000000000000000010000"), binary("00000000000000000000000000000000"), IENC_DP_IMM_SHIFT), 325 (binary("00000000000000000000000010010000"), binary("00000000000000000000000010010000"), IENC_MULT), 326 (binary("00000001100000000000000010010000"), binary("00000001000000000000000000010000"), IENC_MISC1), 327 (binary("00000000000000000000000010010000"), binary("00000000000000000000000000010000"), IENC_DP_REG_SHIFT), 328 ) 329 330 s_1_table = ( 331 (binary("00000001100110000000000000000000"), binary("00000001000000000000000000000000"), IENC_UNDEF), 332 (binary("00000001100110000000000000000000"), binary("00000001001000000000000000000000"), IENC_MOV_IMM_STAT), 333 (0,0, IENC_DP_IMM), 334 ) 335 336 s_3_table = ( 337 (binary("00000001111100000000000011110000"),binary("00000001111100000000000011110000"), IENC_ARCH_UNDEF), 338 (binary("00000000000000000000000000010000"),binary("00000000000000000000000000010000"), IENC_MEDIA), 339 (0,0, IENC_LOAD_REG_OFF), 340 ) 341 342 s_7_table = ( 343 (binary("00000001000000000000000000000000"),binary("00000001000000000000000000000000"), IENC_SWINT), 344 (binary("00000001000000000000000000010000"),binary("00000000000000000000000000010000"), IENC_COPROC_REG_XFER), 345 (0, 0, IENC_COPROC_DP), 346 ) 347 348 # Initial 3 (non conditional) primary table 349 inittable = [ 350 (None, s_0_table), 351 (None, s_1_table), 352 (IENC_LOAD_IMM_OFF, None), # Load or store an immediate 353 (None, s_3_table), 354 (IENC_LOAD_MULT, None), 355 (IENC_BRANCH, None), 356 (IENC_COPROC_LOAD, None), 357 (None, s_7_table), 358 ] 359 360 OFLAG_SHIFT_REG = 1 # Is the shval a register? 361 362 # The supported types of operand shifts (by the 2 bit field) 363 S_LSL = 0 364 S_LSR = 1 365 S_ASR = 2 366 S_ROR = 3 367 S_RRX = 4 # FIXME HACK XXX add this 368 369 shift_names = ["lsl", "lsr", "asr", "ror", "rrx"] 370 371 # FIXME for emulation... 372 #def s_lsl(val, shval): 373 #pass 374 375 #def s_lsr(val, shval): 376 #pass 377 378 # These are indexed by the 2 bit "shift" value in some DP encodings 379 #shift_handlers = ( 380 #s_lsl, 381 #s_lsr, 382 #s_asr, 383 #s_ror, 384 #) 385 386 endian_names = ("LE","BE") 387
388 -class ArmOpcode(envi.Opcode):
389
390 - def __init__(self, opcode, mnem, opers, cond=COND_AL, iflags=0):
391 envi.Opcode.__init__(self, opcode, mnem, 0, 4, opers, iflags) 392 self.cond = cond
393
394 - def __repr__(self):
395 x = [self.mnem, cond_codes.get(self.cond)] 396 # FIXME put in S flag! 397 for o in self.opers: 398 x.append(repr(o)) 399 return " ".join(x)
400 401 # Arm specific opcode flags 402 IF_PSR_S = 0x100 # Instruction updates S field in PSR (for some opcodes it's optional) 403 404 OM_IMM = 0 # imm (with possible shift and offset) 405 OM_REG = 1 # reg (with possible shift and offset) 406 OM_REG_MULT = 2 # reg is regmask of effected registers 407 OM_PSR = 3 # Process state register (like intel elfags) 408 OM_ENDIAN = 4 # boolean operand used in one instruction... *sigh*... 409 OM_COPROC_OP = 5 # The subsequent opcode for a coprocessing instruction 410
411 -class ArmOperand(envi.Operand):
412 - def __init__(self, mode, val, oflags=0, shtype=None, shval=None):
413 envi.Operand.__init__(self, mode) 414 self.val = val # depending on mode, this is reg/imm 415 self.oflags = oflags 416 self.shval = shval 417 self.shtype = shtype
418
419 - def __eq__(self, oper):
420 if not envi.Operand.__eq__(self, oper): 421 return False 422 if self.val != oper.val: 423 return False 424 if self.oflags != oper.oflags: 425 return False 426 if self.shval != oper.shval: 427 return False 428 if self.shtype != oper.shtype: 429 return False 430 return True
431
432 - def __repr__(self):
433 if self.mode == OM_IMM: 434 return "#%d" % self.val 435 436 if self.mode == OM_REG: 437 base = "r%d" % self.val 438 if self.shtype != None: 439 if self.oflags & OFLAG_SHIFT_REG: 440 base = "%s %s %s" % (base, shift_names[self.shtype], "r%d" % self.shval) # FIXME regnames 441 else: 442 base = "%s %s %s" % (base, shift_names[self.shtype], "#%d" % self.shval) # FIXME regnames 443 return base 444 445 if self.mode == OM_PSR: 446 return "FIXME DO PSR" 447 448 if self.mode == OM_ENDIAN: 449 return endian_names[self.val] 450 451 if self.mode == OM_REG_MULT: 452 return "FIXME REG MULT"
453
454 -class ArmModule(envi.ArchitectureModule):
455
456 - def __init__(self):
457 envi.ArchitectureModule.__init__(self, "armv5", maxinst=4)
458
459 - def makeOpcode(self, bytes, offset):
460 opval = struct.unpack("<L", bytes[offset:offset+4])[0] 461 462 cond = opval >> 28 463 464 if cond == COND_EXTENDED: 465 return "FIXME - make extended opcode parser" 466 467 # Begin the table lookup sequence with the first 3 non-cond bits 468 encfam = (opval >> 25) & 0x7 469 enc,nexttab = inittable[encfam] 470 if nexttab != None: # we have to sub-parse... 471 for mask,val,penc in nexttab: 472 if (opval & mask) == val: 473 enc = penc 474 break 475 476 # If we don't know the encoding by here, we never will ;) 477 if enc == None: 478 raise InvalidInstruction("omg") 479 480 #print "ENCFAM",encfam 481 #print "COND",cond 482 #print "ENCODING",enc 483 484 op = ienc_parsers[enc](opval) 485 op.cond = cond 486 487 return op
488 489 a = ArmModule() 490 #a.makeOpcode("\x0d\xc0\xa0\xe1", 0) 491 #e2833004 add r3, r3, #4 492 print repr(a.makeOpcode("\x92\x10\x93\x00", 0)) 493 print repr(a.makeOpcode("\x04\x30\x83\xe2", 0)) 494