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

Source Code for Module envi.archs.arm.armdisasm

   1  import sys 
   2  import struct 
   3  import traceback 
   4   
   5  import envi 
   6  import envi.bits as e_bits 
   7  from envi.bits import binary 
   8   
   9  from envi.archs.arm.const import * 
  10  from envi.archs.arm.regs import * 
  11   
  12  # Universal opcode things: 
  13  # len 
  14  # mode 
  15   
  16  #FIXME: TODO 
  17  #   * Thumb Extension Parser 
  18  #   * Jazelle Extension Parser 
  19  #   * Emulators 
  20   
  21  #################################################################### 
  22  # Parsers for the multiply family of instruction encodings 
  23   
24 -def chopmul(opcode):
25 op1 = (opcode >> 20) & 0xff 26 a = (opcode >> 16) & 0xf 27 b = (opcode >> 12) & 0xf 28 c = (opcode >> 8) & 0xf 29 d = (opcode >> 4) & 0xf 30 e = opcode & 0xf 31 return (op1<<4)+d,(a,b,c,d,e)
32 33 # FIXME this seems to be universal...
34 -def addrToName(mcanv, va):
35 sym = mcanv.syms.getSymByAddr(va) 36 if sym != None: 37 return repr(sym) 38 return "0x%.8x" % va
39 40 # The keys in this table are made of the 41 # concat of bits 27-21 and 7-4 (only when 42 # ienc == mul! 43 iencmul_codes = { 44 # Basic multiplication opcodes 45 binary("000000001001"): ("mul",(0,4,2), 0), 46 binary("000000011001"): ("mul",(0,4,2), IF_PSR_S), 47 binary("000000101001"): ("mla",(0,4,2,1), 0), 48 binary("000000111001"): ("mla",(0,4,2,1), IF_PSR_S), 49 binary("000001001001"): ("umaal",(1,0,4,2), 0), 50 binary("000010001001"): ("umull",(1,0,4,2), 0), 51 binary("000010011001"): ("umull",(1,0,4,2), IF_PSR_S), 52 binary("000010101001"): ("umlal",(1,0,4,2), 0), 53 binary("000010111001"): ("umlal",(1,0,4,2), IF_PSR_S), 54 binary("000011001001"): ("smull",(1,0,4,2), 0), 55 binary("000011011001"): ("smull",(1,0,4,2), IF_PSR_S), 56 binary("000011101001"): ("smlal",(1,0,4,2), 0), 57 binary("000011111001"): ("smlal",(1,0,4,2), IF_PSR_S), 58 59 # multiplys with <x><y> 60 # "B" 61 binary("000100001000"): ("smlabb", (0,4,2,1), 0), 62 binary("000100001010"): ("smlatb", (0,4,2,1), 0), 63 binary("000100001100"): ("smlabt", (0,4,2,1), 0), 64 binary("000100001110"): ("smlatt", (0,4,2,1), 0), 65 binary("000100101010"): ("smulwb", (0,4,2), 0), 66 binary("000100101110"): ("smulwt", (0,4,2), 0), 67 binary("000100101000"): ("smlawb", (0,4,2), 0), 68 binary("000100101100"): ("smlawt", (0,4,2), 0), 69 binary("000101001000"): ("smlalbb", (1,0,4,2), 0), 70 binary("000101001010"): ("smlaltb", (1,0,4,2), 0), 71 binary("000101001100"): ("smlalbt", (1,0,4,2), 0), 72 binary("000101001110"): ("smlaltt", (1,0,4,2), 0), 73 binary("000101101000"): ("smulbb", (0,4,2), 0), 74 binary("000101101010"): ("smultb", (0,4,2), 0), 75 binary("000101101100"): ("smulbt", (0,4,2), 0), 76 binary("000101101110"): ("smultt", (0,4,2), 0), 77 78 # type 2 multiplys 79 80 binary("011100000001"): ("smuad", (0,4,2), 0), 81 binary("011100000011"): ("smuadx", (0,4,2), 0), 82 binary("011100000101"): ("smusd", (0,4,2), 0), 83 binary("011100000111"): ("smusdx", (0,4,2), 0), 84 binary("011100000001"): ("smlad", (0,4,2), 0), 85 binary("011100000011"): ("smladx", (0,4,2), 0), 86 binary("011100000101"): ("smlsd", (0,4,2), 0), 87 binary("011100000111"): ("smlsdx", (0,4,2), 0), 88 binary("011101000001"): ("smlald", (0,4,2), 0), 89 binary("011101000011"): ("smlaldx", (0,4,2), 0), 90 binary("011101000101"): ("smlsld", (0,4,2), 0), 91 binary("011101000111"): ("smlsldx", (0,4,2), 0), 92 binary("011101010001"): ("smmla", (0,4,2,1), 0), 93 binary("011101010011"): ("smmlar", (0,4,2,1), 0), 94 binary("011101011101"): ("smmls", (0,4,2,1), 0), 95 binary("011101011111"): ("smmlsr", (0,4,2,1), 0), 96 binary("011101010001"): ("smmul", (0,4,2), 0), 97 binary("011101010011"): ("smmulr", (0,4,2), 0), 98 } 99
100 -def sh_lsl(num,shval):
101 return (num&0xffffffff) << shval
102 -def sh_lsr(num,shval):
103 return (num&0xffffffff) >> shval
104 -def sh_asr(num,shval):
105 return num >> shval
106 -def sh_ror(num,shval):
107 return (((num&0xffffffff) >> shval) | (num<< (32-shval))) & 0xffffffff
108 -def sh_rrx(num,shval, emu=None):
109 half1 = (num&0xffffffff) >> shval 110 half2 = num<<(33-shval) 111 newC = (num>>(shval-1)) & 1 112 if emu != None: 113 flags = emu.getFlags() 114 oldC = (flags>>PSR_C) & 1 115 emu.setFlags(flags & PSR_C_mask | newC) #part of the change 116 else: 117 oldC = 0 # FIXME: 118 retval = (half1 | half2 | (oldC << (32-shval))) & 0xffffffff 119 return retval
120 121 shifters = ( 122 sh_lsl, 123 sh_lsr, 124 sh_asr, 125 sh_ror, 126 sh_rrx, 127 ) 128 129 130 #################################################################### 131 # Mnemonic tables for opcode based mnemonic lookup 132 133 # Dataprocessing mnemonics 134 dp_mnem = ("and","eor","sub","rsb","add","adc","sbc","rsc","tst","teq","cmp","cmn","orr","mov","bic","mvn",) 135 136 # FIXME: THIS IS FUGLY 137 dp_noRn = (13,15) 138 dp_noRd = (8,9,10,11) 139 140 # FIXME: !!! Don't make SBZ and SBO's part of the list of opers !!! 141 # first parm SBZ: mov,mvn 142 # second parm SBZ: tst,teq,cmp,cmn,
143 -def dpbase(opval):
144 """ 145 Parse and return opcode,sflag,Rn,Rd for a standard 146 dataprocessing instruction. 147 """ 148 ocode = (opval >> 21) & 0xf 149 sflag = (opval >> 20) & 0x1 150 Rn = (opval >> 16) & 0xf 151 Rd = (opval >> 12) & 0xf 152 #print "DPBASE:",ocode,sflag,Rn,Rd 153 return ocode,sflag,Rn,Rd
154 155 #################################################################### 156 # Parser functions for each of the instruction encodings 157
158 -def p_dp_imm_shift(opval, va):
159 ocode,sflag,Rn,Rd = dpbase(opval) 160 Rm = opval & 0xf 161 shtype = (opval >> 5) & 0x3 162 shval = (opval >> 7) & 0x1f #CHECKME: is this correctly done? 163 164 if ocode in dp_noRn:# FIXME: FUGLY (and slow...) 165 olist = ( 166 ArmRegOper(Rd), 167 ArmRegShiftImmOper(Rm, shtype, shval), 168 ) 169 elif ocode in dp_noRd: 170 olist = ( 171 ArmRegOper(Rn), 172 ArmRegShiftImmOper(Rm, shtype, shval), 173 ) 174 else: 175 olist = ( 176 ArmRegOper(Rd), 177 ArmRegOper(Rn), 178 ArmRegShiftImmOper(Rm, shtype, shval), 179 ) 180 181 opcode = (IENC_DP_IMM_SHIFT << 16) + ocode 182 if sflag > 0: 183 iflags = IF_PSR_S 184 else: 185 iflags = 0 186 return (opcode, dp_mnem[ocode], olist, iflags)
187 188 # specialized mnemonics for p_misc 189 qop_mnem = ('qadd','qsub','qdadd','qdsub') 190 smla_mnem = ('smlabb','smlabt','smlatb','smlatt',) 191 smlal_mnem = ('smlalbb','smlalbt','smlaltb','smlaltt',) 192 smul_mnem = ('smulbb','smulbt','smultb','smultt',) 193 smlaw_mnem = ('smlawb','smlawt',) 194 smlaw_mnem = ('smulwb','smulwt',) 195
196 -def p_misc(opval, va):
197 # 0x0f900000 = 0x01000000 or 0x01000010 (misc and misc1 are both parsed at the same time. see the footnote [2] on dp instructions in the Atmel AT91SAM7 docs 198 if opval & 0x0fc00000 == 0x01000000: 199 opcode = (IENC_MISC << 16) + 1 200 mnem = 'mrs' 201 r = (opval>>22) & 1 202 Rd = (opval>>12) & 0xf 203 olist = ( 204 ArmRegOper(Rd), 205 ArmPgmStatRegOper(r), 206 ) 207 elif opval & 0x0fc000f0 == 0x01200000: 208 opcode = (IENC_MISC << 16) + 2 209 mnem = 'msr' 210 r = (opval>>22) & 1 211 Rd = (opval>>12) & 0xf 212 olist = ( 213 ArmPgmStatRegOper(r), 214 ArmRegOper(Rd), 215 ) 216 elif opval & 0x0ff000f0 == 0x01200020: 217 opcode = (IENC_MISC << 16) + 5 218 mnem = 'bxj' 219 Rm = opval & 0xf 220 olist = ( ArmRegOper(Rm), ) 221 222 elif opval & 0x0ff00090 == 0x01000080: 223 opcode = (IENC_MISC << 16) + 9 224 xy = (opval>>5)&3 225 mnem = smla_mnem[xy] 226 Rd = (opval>>16) & 0xf 227 Rn = (opval>>12) & 0xf 228 Rs = (opval>>8) & 0xf 229 Rm = opval & 0xf 230 olist = ( 231 ArmRegOper(Rd), 232 ArmRegOper(Rm), 233 ArmRegOper(Rs), 234 ArmRegOper(Rn), 235 ) 236 elif opval & 0x0ff000b0 == 0x01200080: 237 opcode = (IENC_MISC << 16) + 10 238 y = (opval>>6)&1 239 mnem = smlaw_mnem[y] 240 Rd = (opval>>16) & 0xf 241 Rn = (opval>>12) & 0xf 242 Rs = (opval>>8) & 0xf 243 Rm = opval & 0xf 244 olist = ( 245 ArmRegOper(Rd), 246 ArmRegOper(Rm), 247 ArmRegOper(Rs), 248 ArmRegOper(Rn), 249 ) 250 elif opval & 0x0ff000b0 == 0x012000a0: 251 opcode = (IENC_MISC << 16) + 11 252 y = (opval>>6)&1 253 mnem = smulw_mnem[y] 254 Rd = (opval>>16) & 0xf 255 Rs = (opval>>8) & 0xf 256 Rm = opval & 0xf 257 olist = ( 258 ArmRegOper(Rd), 259 ArmRegOper(Rm), 260 ArmRegOper(Rs), 261 ) 262 elif opval & 0x0ff00090 == 0x01400080: 263 opcode = (IENC_MISC << 16) + 12 264 xy = (opval>>5)&3 265 mnem = smlal_mnem[xy] 266 Rdhi = (opval>>16) & 0xf 267 Rdlo = (opval>>12) & 0xf 268 Rs = (opval>>8) & 0xf 269 Rm = opval & 0xf 270 olist = ( 271 ArmRegOper(Rdlo), 272 ArmRegOper(Rdhi), 273 ArmRegOper(Rs), 274 ArmRegOper(Rn), 275 ) 276 elif opval & 0x0ff00090 == 0x01600080: 277 opcode = (IENC_MISC << 16) + 13 278 xy = (opval>>5)&3 279 mnem = smulxy_mnem[xy] 280 Rd = (opval>>16) & 0xf 281 Rs = (opval>>8) & 0xf 282 Rm = opval & 0xf 283 olist = ( 284 ArmRegOper(Rd), 285 ArmRegOper(Rm), 286 ArmRegOper(Rs), 287 ) 288 mnem = 'smul' #xy 289 #elif opval & 0x0fc00000 == 0x03200000: 290 #mnem = 'msr' 291 else: 292 raise Exception("p_misc: invalid instruction: %.8x:\t%.8x"%(va,opval)) 293 opcode = IENC_UNDEF 294 mnem = "undefined instruction" 295 olist = () 296 297 return (opcode, mnem, olist, 0) 298 299 300 #### these actually belong to the media section, and already exist there. FIXME: DELETE 301 #misc1_mnem = ("pkhbt", "pkhtb", "rev", "rev16", "revsh", "sel", "ssat", "ssat16", "usat", "usat16", ) 302
303 -def p_misc1(opval, va): #
304 #R = (opval>>22) & 1 305 #Rn = (opval>>16) & 0xf 306 #Rd = (opval>>12) & 0xf 307 #rot_imm = (opval>>8) & 0xf 308 #imm = opval & 0xff 309 #Rm = opval & 0xf 310 if opval & 0x0ff000f0 == 0x01200010: 311 opcode = INS_BX 312 mnem = 'bx' 313 Rm = opval & 0xf 314 olist = ( ArmRegOper(Rm), ) 315 316 elif opval & 0x0ff000f0 == 0x01600010: 317 opcode = (IENC_MISC << 16) + 4 318 mnem = 'clz' 319 Rd = (opval>>12) & 0xf 320 Rm = opval & 0xf 321 olist = ( 322 ArmRegOper(Rd), 323 ArmRegOper(Rm), 324 ) 325 elif opval & 0x0ff000f0 == 0x01200030: 326 #opcode = (IENC_MISC << 16) + 6 327 opcode = INS_BLX 328 mnem = 'blx' 329 Rm = opval & 0xf 330 olist = ( ArmRegOper(Rm), ) 331 332 elif opval & 0x0f9000f0 == 0x01000050: #all qadd/qsub's 333 opcode = (IENC_MISC << 16) + 7 334 qop = (opval>>21)&3 335 mnem = qop_mnem[qop] 336 Rn = (opval>>16) & 0xf 337 Rd = (opval>>12) & 0xf 338 Rm = opval & 0xf 339 olist = ( 340 ArmRegOper(Rd), 341 ArmRegOper(Rm), 342 ArmRegOper(Rn), 343 ) 344 345 elif opval & 0x0ff000f0 == 0x01200070: 346 opcode = (IENC_MISC << 16) + 8 347 mnem = 'bkpt' 348 immed = ((opval>>4)&0xfff0) + (opval&0xf) 349 olist = ( ArmImmOper(immed), ) 350 351 else: 352 raise Exception("p_misc1: invalid instruction: %.8x:\t%.8x"%(va,opval)) 353 354 return (opcode, mnem, olist, 0) 355 356 357 358 swap_mnem = ("swp","swpb",) 359 strex_mnem = ("strex","ldrex",) # actual full instructions 360 #strh_mnem = ("strh","ldrh",) 361 #ldrs_mnem = ("ldrsh","ldrsb",) 362 #ldrd_mnem = ("ldrd","strd",) 363 strh_mnem = (("str",IF_H),("ldr",IF_H),) # IF_H 364 ldrs_mnem = (("ldr",IF_S|IF_H),("ldr",IF_S|IF_B),) # IF_SH, IF_SB 365 ldrd_mnem = (("ldr",IF_D),("str",IF_D),) # IF_D
366 -def p_extra_load_store(opval, va):
367 pubwl = (opval>>20) & 0x1f 368 Rn = (opval>>16) & 0xf 369 Rd = (opval>>12) & 0xf 370 Rs = (opval>>8) & 0xf 371 op1 = (opval>>5) & 0x3 372 Rm = opval & 0xf 373 iflags = 0 374 375 if opval&0x0fb000f0==0x01000090:# swp/swpb 376 idx = (pubwl>>2)&1 377 opcode = (IENC_EXTRA_LOAD << 16) + idx 378 mnem = swap_mnem[idx] 379 olist = ( 380 ArmRegOper(Rd), 381 ArmRegOper(Rm), 382 ArmImmOffsetOper(Rn, 0, va), 383 ) 384 elif opval&0x0fe000f0==0x01800090:# strex/ldrex 385 idx = pubwl&1 386 opcode = (IENC_EXTRA_LOAD << 16) + 2 + idx 387 mnem = strex_mnem[idx] 388 olist = ( 389 ArmRegOper(Rd), 390 ArmRegOper(Rm), 391 ArmRegOper(Rn), 392 ) 393 elif opval&0x0e4000f0==0x000000b0:# strh/ldrh regoffset 394 idx = pubwl&1 395 opcode = (IENC_EXTRA_LOAD << 16) + 4 + idx 396 mnem,iflags = strh_mnem[idx] 397 olist = ( 398 ArmRegOper(Rd), 399 ArmRegOffsetOper(Rn, Rm, va, pubwl), 400 ) 401 elif opval&0x0e4000f0==0x004000b0:# strh/ldrh immoffset 402 idx = pubwl&1 403 opcode = (IENC_EXTRA_LOAD << 16) + 6 + idx 404 mnem,iflags = strh_mnem[idx] 405 olist = ( 406 ArmRegOper(Rd), 407 ArmImmOffsetOper(Rn,(Rs<<4)+Rm, va), 408 ) 409 elif opval&0x0e4000d0==0x004000d0:# ldrsh/b immoffset 410 idx = (opval>>5)&1 411 opcode = (IENC_EXTRA_LOAD << 16) + 8 + idx 412 mnem,iflags = ldrs_mnem[idx] 413 olist = ( 414 ArmRegOper(Rd), 415 ArmImmOffsetOper(Rn, (Rs<<4)+Rm, va, pubwl), 416 ) 417 elif opval&0x0e4000d0==0x000000d0:# ldrsh/b regoffset 418 idx = (opval>>5)&1 419 opcode = (IENC_EXTRA_LOAD << 16) + 10 + idx 420 mnem,iflags = ldrs_mnem[idx] 421 olist = ( 422 ArmRegOper(Rd), 423 ArmRegOffsetOper(Rn, Rm, va, pubwl), 424 ) 425 elif opval&0x0e5000d0==0x000000d0:# ldrd/strd regoffset 426 idx = (opval>>5)&1 427 opcode = (IENC_EXTRA_LOAD << 16) + 12 + idx 428 mnem,iflags = ldrd_mnem[idx] 429 olist = ( 430 ArmRegOper(Rd), 431 ArmRegOffsetOper(Rn, Rm, va, pubwl), 432 ) 433 elif opval&0x0e5000d0==0x004000d0:# ldrd/strd immoffset 434 idx = (opval>>5)&1 435 opcode = (IENC_EXTRA_LOAD << 16) + 14 + idx 436 mnem,iflags = ldrd_mnem[idx] 437 olist = ( 438 ArmRegOper(Rd), 439 ArmImmOffsetOper(Rn, (Rs<<4)+Rm), 440 ) 441 else: 442 raise Exception("extra_load_store: invalid instruction: %.8x:\t%.8x"%(va,opval)) 443 444 return (opcode, mnem, olist, iflags)
445 446
447 -def p_dp_reg_shift(opval, va):
448 ocode,sflag,Rn,Rd = dpbase(opval) 449 Rm = opval & 0xf 450 shtype = (opval >> 5) & 0x3 451 Rs = (opval >> 8) & 0xf 452 453 if ocode in dp_noRn:# FIXME: FUGLY 454 olist = ( 455 ArmRegOper(Rd), 456 ArmRegShiftRegOper(Rm, shtype, Rs), 457 ) 458 elif ocode in dp_noRd: 459 olist = ( 460 ArmRegOper(Rn), 461 ArmRegShiftRegOper(Rm, shtype, Rs), 462 ) 463 else: 464 olist = ( 465 ArmRegOper(Rd), 466 ArmRegOper(Rn), 467 ArmRegShiftRegOper(Rm, shtype, Rs), 468 ) 469 470 opcode = (IENC_DP_REG_SHIFT << 16) + ocode 471 if sflag > 0: 472 iflags = IF_PSR_S 473 else: 474 iflags = 0 475 return (opcode, dp_mnem[ocode], olist, iflags)
476 477 multfail = (None, None, None,)
478 -def p_mult(opval, va):
479 ocode, vals = chopmul(opval) 480 481 mnem, opindexes, flags = iencmul_codes.get(ocode, multfail) 482 if mnem == None: 483 raise Exception("p_mult: invalid instruction: %.8x:\t%.8x"%(va,opval)) 484 485 olist = [] 486 for i in opindexes: 487 olist.append(ArmRegOper(vals[i])) 488 489 opcode = (IENC_MULT << 16) + ocode 490 return (opcode, mnem, olist, flags)
491
492 -def p_dp_imm(opval, va):
493 ocode,sflag,Rn,Rd = dpbase(opval) 494 imm = opval & 0xff 495 rot = (opval >> 7) & 0x1e # effectively, rot*2 496 497 498 if ocode in dp_noRn:# FIXME: FUGLY 499 olist = ( 500 ArmRegOper(Rd), 501 ArmImmOper(imm, rot, S_ROR), 502 ) 503 elif ocode in dp_noRd: 504 olist = ( 505 ArmRegOper(Rn), 506 ArmImmOper(imm, rot, S_ROR), 507 ) 508 else: 509 olist = ( 510 ArmRegOper(Rd), 511 ArmRegOper(Rn), 512 ArmImmOper(imm, rot, S_ROR), 513 ) 514 515 opcode = (IENC_DP_IMM << 16) + ocode 516 if sflag > 0: 517 iflags = IF_PSR_S 518 else: 519 iflags = 0 520 return (opcode, dp_mnem[ocode], olist, iflags)
521
522 -def p_undef(opval, va):
523 raise Exception("p_undef: invalid instruction (by definition in ARM spec): %.8x:\t%.8x"%(va,opval)) 524 opcode = IENC_UNDEF 525 mnem = "undefined instruction" 526 olist = ( 527 ArmImmOper(opval), 528 ) 529 530 return (opcode, mnem, olist, 0)
531
532 -def p_mov_imm_stat(opval, va): # only one instruction: "msr"
533 imm = opval & 0xff 534 rot = (opval>>8) & 0xf 535 r = (opval>>22) & 1 536 mask = (opval>>16) & 0xf 537 538 immed = ((imm>>rot) + (imm<<(32-rot))) & 0xffffffff 539 540 olist = ( 541 ArmPgmStatRegOper(mask), 542 ArmImmOper(immed), 543 ) 544 545 opcode = (IENC_MOV_IMM_STAT << 16) 546 return (opcode, "msr", olist, 0) 547 548 ldr_mnem = ("str", "ldr") 549 tsizes = (4, 1,)
550 -def p_load_imm_off(opval, va):
551 pubwl = (opval>>20) & 0x1f 552 Rn = (opval>>16) & 0xf 553 Rd = (opval>>12) & 0xf 554 imm = opval & 0xfff 555 556 if pubwl & 4: # B 557 iflags = IF_B 558 if (pubwl & 0x12) == 2: 559 iflags |= IF_T 560 else: 561 iflags = 0 562 563 olist = ( 564 ArmRegOper(Rd), 565 ArmImmOffsetOper(Rn, imm, va, pubwl=pubwl) # u=-/+, b=word/byte 566 ) 567 568 opcode = (IENC_LOAD_IMM_OFF << 16) 569 return (opcode, ldr_mnem[pubwl&1], olist, iflags)
570
571 -def p_load_reg_off(opval, va):
572 pubwl = (opval>>20) & 0x1f 573 Rd = (opval>>12) & 0xf 574 Rn = (opval>>16) & 0xf 575 Rm = opval & 0xf 576 shtype = (opval>>5) & 0x3 577 shval = (opval>>7) & 0x1f 578 579 if pubwl & 4: # B 580 iflags = IF_B 581 if (pubwl & 0x12) == 2: 582 iflags |= IF_T 583 else: 584 iflags = 0 585 586 olist = ( 587 ArmRegOper(Rd), 588 ArmScaledOffsetOper(Rn, Rm, shtype, shval, va, pubwl), # u=-/+, b=word/byte 589 ) 590 591 opcode = (IENC_LOAD_REG_OFF << 16) 592 return (opcode, ldr_mnem[pubwl&1], olist, iflags)
593 594
595 -def p_media(opval, va):
596 """ 597 27:20, 7:4 598 """ 599 # media is a parent for the following: 600 # parallel add/sub 01100 601 # pkh, ssat, ssat16, usat, usat16, sel 01101 602 # rev, rev16, revsh 01101 603 # smlad, smlsd, smlald, smusd 01110 604 # usad8, usada8 01111 605 definer = (opval>>23) & 0x1f 606 if definer == 0xc: 607 return p_media_parallel(opval, va) 608 elif definer == 0xd: 609 return p_media_pack_sat_rev_extend(opval, va) 610 elif definer == 0xe: 611 return p_mult(opval, va) 612 return p_media_smul(opval, va) 613 else: 614 return p_media_usada(opval, va)
615 616 #generate mnemonics for parallel instructions (could do manually like last time...) 617 parallel_mnem = [] 618 par_suffixes = ("add16", "addsubx", "subaddx", "sub16", "add8", "sub8", "", "") 619 par_prefixes = ("","s","q","sh","","u","uq","uh") 620 for pre in par_prefixes: 621 for suf in par_suffixes: 622 parallel_mnem.append(pre+suf) 623 624 parallel_mnem = tuple(parallel_mnem) 625
626 -def p_media_parallel(opval, va):
627 628 opc1 = (opval>>17) & 0x38 629 Rn = (opval>>16) & 0xf 630 Rd = (opval>>12) & 0xf 631 opc1 += (opval>>5) & 7 632 Rm = opval & 0xf 633 mnem = parallel_mnem[opc1] 634 635 olist = ( 636 ArmRegOper(Rd), 637 ArmRegOper(Rn), 638 ArmRegOper(Rm), 639 ) 640 opcode = IENC_MEDIA_PARALLEL + opc1 641 return (opcode, mnem, olist, 0)
642 643 644 xtnd_mnem = [] 645 xtnd_suffixes = ("xtab16","xtab","xtah","xtb16","xtb","xth",) 646 xtnd_prefixes = ("s","u") 647 for pre in xtnd_prefixes: 648 for suf in xtnd_suffixes: 649 xtnd_mnem.append(pre+suf) 650 651 xtnd_mnem = tuple(xtnd_mnem) 652 653 pkh_mnem = ('pkhbt', 'pkhtb',) 654 sat_mnem = ('ssat','usat') 655 sat16_mnem = ('ssat16','usat16') 656 rev_mnem = ('rev','rev16',None,'revsh',) 657
658 -def p_media_pack_sat_rev_extend(opval, va):
659 ## part of p_media 660 # assume bit 23 == 1 661 opc1 = (opval>>20) & 7 662 opc2 = (opval>>4) & 0xf 663 opc25 = opc2 & 3 664 opcode = 0 665 666 if opc1 == 0 and opc25 == 1: #pkh 667 mnem = pkh_mnem[(opval>>6)&1] 668 Rn = (opval>>16) & 0xf 669 Rd = (opval>>12) & 0xf 670 shift_imm = (opval>>7) & 0x1f 671 Rm = opval & 0xf 672 673 # 'FIXME WHAT WAS OPCODE SUPPOSED TO BE HERE @las?' 674 # 'dear visi, read the code ;) move the "mnem =" line if you prefer' 675 676 olist = ( 677 ArmRegOper(Rd), 678 ArmRegOper(Rn), 679 ArmRegShiftImmOper(Rm, S_LSL, shift_imm), 680 ) 681 682 elif (opc1 & 2) and opc25 == 1: #word sat 683 opidx = (opval>>22)&1 684 sat_imm = 1 + (opval>>16) & 0xf 685 Rd = (opval>>12) & 0xf 686 Rm = opval & 0xf 687 if opc1 & 0x10: # ?sat16 688 mnem = sat16_mnem[opidx] 689 olist = ( 690 ArmRegOper(Rd), 691 ArmImmOper(sat_imm), 692 ArmRegOper(Rm), 693 ) 694 opcode = IENC_MEDIA_SAT + opidx 695 else: 696 mnem = sat_mnem[opidx] 697 shift_imm = (opval>>7) & 0x1f 698 sh = (opval>>5) & 2 699 olist = ( 700 ArmRegOper(Rd), 701 ArmImmOper(sat_imm), 702 ArmRegShiftImmOper(Rm, sh, shift_imm), 703 ) 704 opcode = IENC_MEDIA_SAT + 2 + opidx 705 706 elif (opc1 & 3) == 2 and opc2 == 3: #parallel half-word sat 707 raise Exception("WTF! Parallel Half-Word Saturate... what is that instruction?") 708 709 elif (opc1 > 0) and (opc2 & 7) == 3: # byte rev word 710 opidx = ((opval>>21) & 2) + ((opval>>7) & 1) 711 mnem = rev_mnem[opidx] 712 if mnem == None: 713 raise Exception("p_media_pack_sat_rev_extend: invalid instruction: %.8x:\t%.8x"%(va,opval)) 714 715 Rd = (opval>>12) & 0xf 716 Rm = opval & 0xf 717 olist = ( 718 ArmRegOper(Rd), 719 ArmRegOper(Rm), 720 ) 721 opcode = IENC_MEDIA_REV + opidx 722 #elif opc1 == 3 and opc2 == 0xb: # byte rev pkt halfword 723 #elif opc1 == 7 and opc2 == 0xb: # byte rev signed halfword 724 elif opc1 == 0 and opc2 == 0xb: # select bytes 725 mnem = "sel" 726 Rn = (opval>>16) & 0xf 727 Rd = (opval>>12) & 0xf 728 Rm = opval & 0xf 729 olist = ( 730 ArmRegOper(Rd), 731 ArmRegOper(Rn), 732 ArmRegOper(Rm), 733 ) 734 opcode = IENC_MEDIA_SEL 735 elif opc2 == 7: # sign extend 736 mnem = xtnd_mnem[opc1] 737 Rn = (opval>>16) & 0xf 738 Rd = (opval>>12) & 0xf 739 rot = (opval>>10) & 3 740 Rm = opval & 0xf 741 742 olist = ( 743 ArmRegOper(Rd), 744 ArmRegOper(Rn), 745 ArmRegShiftImmOper(Rm, S_ROR, rot), 746 ) 747 opcode = IENC_MEDIA_EXTEND + opc1 748 else: 749 raise Exception("p_media_extend: invalid instruction: %.8x:\t%.8x"%(va,opval)) 750 751 return (opcode, mnem, olist, 0)
752 753 #smult3_mnem = ('smlad','smlsd',,,'smlald')
754 -def p_media_smul(opval, va):
755 raise Exception("Should not reach here. If we reach here, we'll have to implement MEDIA_SMUL extended multiplication (type 3)")
756 # hmmm, is this already handled? 757
758 -def p_media_usada(opval, va):
759 Rd = (opval>>16) & 0xf 760 Rn = (opval>>12) & 0xf 761 Rs = (opval>>8) & 0xf 762 Rm = opval & 0xf 763 764 if Rn == 0xf: 765 mnem = "usad8" 766 olist = ( 767 ArmRegOper(Rd), 768 ArmRegOper(Rm), 769 ArmRegOper(Rs), 770 ) 771 opcode = IENC_MEDIA_USAD8 772 else: 773 mnem = "usada8" 774 olist = ( 775 ArmRegOper(Rd), 776 ArmRegOper(Rm), 777 ArmRegOper(Rs), 778 ArmRegOper(Rn), 779 ) 780 opcode = IENC_MEDIA_USADA8 781 782 return (opcode, mnem, olist, 0)
783
784 -def p_arch_undef(opval, va):
785 raise Exception("p_arch_undef: invalid instruction (by definition in ARM spec): %.8x:\t%.8x"%(va,opval)) 786 #print >>sys.stderr,("implementme: p_arch_undef") 787 return (IENC_ARCH_UNDEF, 'arch undefined', (ArmImmOper(opval),), 0)
788 789 ldm_mnem = ("stm", "ldm") 790
791 -def p_load_mult(opval, va):
792 puswl = (opval>>20) & 0x1f 793 mnem = ldm_mnem[(puswl&1)] 794 #flags = ((puswl<<10) & 0x3000) + IF_DA # ???? WTF? 795 flags = ((puswl&0x18)<<21) + IF_DA # store bits for decoding whether to dec/inc before/after between ldr/str. IF_DA tells the repr to print the the DAIB extension after the conditional 796 Rn = (opval>>16) & 0xf 797 reg_list = opval & 0xffff 798 799 olist = ( 800 ArmRegOper(Rn), 801 ArmRegListOper(reg_list, puswl), 802 ) 803 if puswl & 2: # W (mnemonic: "!") 804 flags |= IF_W 805 olist[0].oflags |= OF_W 806 if puswl & 4: # UM - usermode, or mov current SPSR -> CPSR if r15 included 807 flags |= IF_UM 808 olist[1].oflags |= OF_UM 809 810 811 opcode = (IENC_LOAD_MULT << 16) 812 return (opcode, mnem, olist, flags)
813
814 -def instrenc(encoding, index):
815 return (encoding << 16) + index
816 817 INS_B = instrenc(IENC_BRANCH, 0) 818 INS_BL = instrenc(IENC_BRANCH, 1) 819 INS_BX = instrenc(IENC_MISC, 3) 820 INS_BXJ = instrenc(IENC_MISC, 5) 821 INS_BLX = IENC_UNCOND_BLX 822 823 b_mnem = ("b", "bl",)
824 -def p_branch(opval, va): # primary branch encoding. others were added later in the media section
825 off = e_bits.signed(opval, 3) 826 off <<= 2 827 link = (opval>>24) & 1 828 829 #FIXME this assumes A1 branch encoding. 830 831 olist = ( ArmOffsetOper(off, va),) 832 if link: 833 flags = envi.IF_CALL 834 else: 835 flags = envi.IF_BRANCH 836 837 opcode = (IENC_BRANCH << 16) + link 838 return (opcode, b_mnem[link], olist, flags) 839 840 ldc_mnem = ("stc", "ldc",)
841 -def p_coproc_load(opval, va): #FIXME: MRRC, MCRR encoded here.
842 punwl = (opval>>20) & 0x1f 843 Rn = (opval>>16) & 0xf 844 CRd = (opval>>12) & 0xf 845 cp_num = (opval>>8) & 0xf 846 offset = opval & 0xff 847 848 if punwl & 4: # L 849 iflags = IF_L 850 else: 851 iflags = 0 852 853 olist = ( 854 ArmCoprocOper(cp_num), 855 ArmCoprocRegOper(CRd), 856 ArmImmOffsetOper(Rn, offset*4, va, pubwl=punwl), 857 ) 858 859 opcode = (IENC_COPROC_LOAD << 16) 860 return (opcode, ldc_mnem[punwl&1], olist, iflags) 861 862 mcrr_mnem = ("mcrr", "mrrc")
863 -def p_coproc_dbl_reg_xfer(opval, va):
864 Rn = (opval>>16) & 0xf 865 Rd = (opval>>12) & 0xf 866 cp_num = (opval>>8) & 0xf 867 opcode = (opval>>4) & 0xf 868 CRm = opval & 0xf 869 mnem = mcrr_mnem[(opval>>20) & 1] 870 871 olist = ( 872 ArmCoprocOper(cp_num), 873 ArmCoprocOpcodeOper(opcode), 874 ArmRegOper(Rd), 875 ArmRegOper(Rn), 876 ArmCoprocRegOper(CRm), 877 ) 878 opcode = IENC_COPROC_RREG_XFER<<16 879 return (opcode, mnem, olist, 0)
880 881 cdp_mnem = ["cdp" for x in range(15)] 882 cdp_mnem.append("cdp2") 883
884 -def p_coproc_dp(opval, va):
885 opcode1 = (opval>>20) & 0xf 886 CRn = (opval>>16) & 0xf 887 CRd = (opval>>12) & 0xf 888 cp_num = (opval>>8) & 0xf 889 opcode2 = (opval>>5) & 0x7 890 CRm = opval & 0xf 891 mnem = cdp_mnem[opval>>28] 892 893 olist = ( 894 ArmCoprocOper(cp_num), 895 ArmCoprocOpcodeOper(opcode1), 896 ArmCoprocRegOper(CRd), 897 ArmCoprocRegOper(CRn), 898 ArmCoprocRegOper(CRm), 899 ArmCoprocOpcodeOper(opcode2), 900 ) 901 902 opcode = (IENC_COPROC_DP << 16) 903 return (opcode, mnem, olist, 0) #FIXME: CDP2 (cond = 0b1111) also needs handling.
904 905 mcr_mnem = ("mcr", "mrc")
906 -def p_coproc_reg_xfer(opval, va):
907 opcode1 = (opval>>21) & 0x7 908 load = (opval>>20) & 1 909 CRn = (opval>>16) & 0xf 910 Rd = (opval>>12) & 0xf 911 cp_num = (opval>>8) & 0xf 912 opcode2 = (opval>>5) & 0x7 913 CRm = opval & 0xf 914 915 olist = ( 916 ArmCoprocOper(cp_num), 917 ArmCoprocOpcodeOper(opcode1), 918 ArmRegOper(Rd), 919 ArmCoprocRegOper(CRn), 920 ArmCoprocRegOper(CRm), 921 ArmCoprocOpcodeOper(opcode2), 922 ) 923 924 opcode = (IENC_COPROC_REG_XFER << 16) 925 return (opcode, mcr_mnem[load], olist, 0)
926
927 -def p_swint(opval, va):
928 swint = opval & 0xffffff 929 930 olist = ( ArmImmOper(swint), ) 931 opcode = IENC_SWINT << 16 + 1 932 return (opcode, "swi", olist, 0)
933 934 cps_mnem = ("cps","cps FAIL-bad encoding","cpsie","cpsid") 935 mcrr2_mnem = ("mcrr2", "mrrc2") 936 ldc2_mnem = ("stc2", "ldc2",) 937 mcr2_mnem = ("mcr2", "mrc2")
938 -def p_uncond(opval, va):
939 940 if opval & 0x0f000000 == 0x0f000000: 941 # FIXME THIS IS HORKED 942 opcode = IENC_SWINT << 16 + 2 943 immval = opval & 0x00ffffff 944 return (opcode, 'swi', (ArmImmOper(immval),), 0) 945 946 optop = ( opval >> 26 ) & 0x3 947 if optop == 0: 948 if opval & 0xfff10020 == 0xf1000000: 949 #cps 950 imod = (opval>>18)&3 951 mmod = (opval>>17)&1 952 aif = (opval>>5)&7 953 mode = opval&0x1f 954 mnem = cps_mnem[imod] 955 956 if imod & 2: 957 olist = [ 958 ArmCPSFlagsOper(aif) # if mode is set... 959 ] 960 else: 961 olist = [] 962 if mmod: 963 olist.append(ArmImmOper(mode)) 964 965 opcode = IENC_UNCOND_CPS + imod 966 return (opcode, mnem, olist, 0) 967 elif (opval & 0xffff00f0) == 0xf1010000: 968 #setend 969 e = (opval>>9) & 1 970 mnem = "setend" 971 olist = ( ArmEndianOper(e), ) 972 opcode = IENC_UNCOND_SETEND 973 return (opcode, mnem, olist, 0) 974 else: 975 raise Exception("p_uncond (ontop=0): invalid instruction: %.8x:\t%.8x"%(va,opval)) 976 elif optop == 1: 977 if (opval & 0xf570f000) == 0xf550f000: 978 #cache preload - also known as a nop on most platforms... does nothing except prefetch instructions from cache. 979 # i'm tempted to cut the parsing of it and just return a canned something. 980 mnem = "pld" 981 I = (opval>>25) & 1 # what the freak am i supposed to do with "i"??? 982 Rn = (opval>>16) & 0xf 983 U = (opval>>23) & 1 984 opcode = IENC_UNCOND_PLD 985 if I: 986 immoffset = opval & 0xfff 987 olist = (ArmImmOffsetOper(Rn, immoffset, va, U<<3),) 988 else: 989 Rm = opval & 0xf 990 shtype = (opval>>5) & 3 991 shval = (opval>>7) & 0x1f 992 olist = (ArmScaledOffsetOper(Rn, Rm, shtype, shval, va, pubwl), ) 993 return (opcode, mnem, olist, 0) 994 else: 995 raise Exception("p_uncond (ontop=1): invalid instruction: %.8x:\t%.8x"%(va,opval)) 996 elif optop == 2: 997 if (opval & 0xfe5f0f00) == 0xf84d0500: 998 #save return state 999 pu_w = (opval>>21) & 0xf 1000 mnem = "srs" 1001 flags = ((pu_w<<10) & 0x3000) + IF_DA 1002 mode = opval & 0xf 1003 1004 olist = ( 1005 ArmModeOper(mode, pu_w&1), 1006 ) 1007 opcode = IENC_UNCOND_SRS 1008 return (opcode, mnem, olist, flags) 1009 elif (opval & 0xfe500f00) == 0xf8100a00: 1010 #rfe 1011 pu = (opval>>23) & 3 1012 mnem = "rfe" 1013 flags = (pu<<12) + IF_DA 1014 Rn = (opval>>16) & 0xf 1015 1016 olist = ( 1017 ArmRegOper(Rn), 1018 ) 1019 opcode = IENC_UNCOND_RFE 1020 return (opcode, mnem, olist, flags) 1021 1022 elif (opval & 0xfe000000) == 0xfa000000: 1023 #blx 1024 mnem = "blx" 1025 h = (opval>>23) & 2 1026 imm_offset = e_bits.signed(opval, 3) + h 1027 1028 olist = ( 1029 ArmOffsetOper(imm_offset, va), 1030 ) 1031 1032 opcode = INS_BLX #should this be IENC_UNCOND_BLX? 1033 return (opcode, mnem, olist, 0) 1034 else: 1035 raise Exception("p_uncond (ontop=2): invalid instruction: %.8x:\t%.8x"%(va,opval)) 1036 else: 1037 if (opval & 0xffe00000) == 0xfc400000: 1038 #MRCC2/MRRC2 1039 Rn = (opval>>16) & 0xf 1040 Rd = (opval>>12) & 0xf 1041 cp_num = (opval>>8) & 0xf 1042 opcode = (opval>>4) & 0xf 1043 CRm = opval & 0xf 1044 mnem = mcrr2_mnem[(opval>>20) & 1] 1045 1046 olist = ( 1047 ArmCoprocOper(cp_num), 1048 ArmCoprocOpcodeOper(opcode), 1049 ArmRegOper(Rd), 1050 ArmRegOper(Rn), 1051 ArmCoprocRegOper(CRm), 1052 ) 1053 opcode = IENC_COPROC_RREG_XFER<<16 1054 return (opcode, mnem, olist, 0) 1055 1056 elif (opval & 0xfe000000) == 0xfc000000: 1057 #stc2/ldc2 1058 punwl = (opval>>20) & 0x1f 1059 Rn = (opval>>16) & 0xf 1060 CRd = (opval>>12) & 0xf 1061 cp_num = (opval>>8) & 0xf 1062 offset = opval & 0xff 1063 1064 if punwl & 4: # L 1065 iflags = IF_L 1066 else: 1067 iflags = 0 1068 1069 olist = ( 1070 ArmCoprocOper(cp_num), 1071 ArmCoprocRegOper(CRd), 1072 ArmImmOffsetOper(Rn, offset*4, va, pubwl=punwl), 1073 ) 1074 1075 opcode = (IENC_COPROC_LOAD << 16) 1076 return (opcode, ldc2_mnem[punwl&1], olist, iflags) 1077 1078 elif (opval & 0xff000010) == 0xfe000000: 1079 #coproc dp (cdp2) 1080 return p_coproc_dp(opval) 1081 elif (opval & 0xff000010) == 0xfe000010: 1082 #mcr2/mrc2 1083 opcode1 = (opval>>21) & 0x7 1084 load = (opval>>20) & 1 1085 CRn = (opval>>16) & 0xf 1086 Rd = (opval>>12) & 0xf 1087 cp_num = (opval>>8) & 0xf 1088 opcode2 = (opval>>5) & 0x7 1089 CRm = opval & 0xf 1090 1091 olist = ( 1092 ArmCoprocOper(cp_num), 1093 ArmCoprocOpcodeOper(opcode1), 1094 ArmRegOper(Rd), 1095 ArmCoprocRegOper(CRn), 1096 ArmCoprocRegOper(CRm), 1097 ArmCoprocOpcodeOper(opcode2), 1098 ) 1099 1100 opcode = (IENC_COPROC_REG_XFER << 16) 1101 return (opcode, mcr2_mnem[load], olist, 0) 1102 else: 1103 raise Exception("p_uncond (ontop=3): invalid instruction: %.8x:\t%.8x"%(va,opval))
1104 1105 #################################################################### 1106 # Table of the parser functions 1107 ienc_parsers_tmp = [None for x in range(21)] 1108 1109 ienc_parsers_tmp[IENC_DP_IMM_SHIFT] = p_dp_imm_shift 1110 ienc_parsers_tmp[IENC_MISC] = p_misc 1111 ienc_parsers_tmp[IENC_MISC1] = p_misc1 1112 ienc_parsers_tmp[IENC_EXTRA_LOAD] = p_extra_load_store 1113 ienc_parsers_tmp[IENC_DP_REG_SHIFT] = p_dp_reg_shift 1114 ienc_parsers_tmp[IENC_MULT] = p_mult 1115 ienc_parsers_tmp[IENC_UNDEF] = p_undef 1116 ienc_parsers_tmp[IENC_MOV_IMM_STAT] = p_mov_imm_stat 1117 ienc_parsers_tmp[IENC_DP_IMM] = p_dp_imm 1118 ienc_parsers_tmp[IENC_LOAD_IMM_OFF] = p_load_imm_off 1119 ienc_parsers_tmp[IENC_LOAD_REG_OFF] = p_load_reg_off 1120 ienc_parsers_tmp[IENC_ARCH_UNDEF] = p_arch_undef 1121 ienc_parsers_tmp[IENC_MEDIA] = p_media 1122 ienc_parsers_tmp[IENC_LOAD_MULT] = p_load_mult 1123 ienc_parsers_tmp[IENC_BRANCH] = p_branch 1124 ienc_parsers_tmp[IENC_COPROC_RREG_XFER] = p_coproc_dbl_reg_xfer 1125 ienc_parsers_tmp[IENC_COPROC_LOAD] = p_coproc_load 1126 ienc_parsers_tmp[IENC_COPROC_DP] = p_coproc_dp 1127 ienc_parsers_tmp[IENC_COPROC_REG_XFER] = p_coproc_reg_xfer 1128 ienc_parsers_tmp[IENC_SWINT] = p_swint 1129 ienc_parsers_tmp[IENC_UNCOND] = p_uncond 1130 1131 ienc_parsers = tuple(ienc_parsers_tmp) 1132 1133 #################################################################### 1134 1135 # the primary table is index'd by the 3 bits following the 1136 # conditional and are structured as follows: 1137 # ( ENC, nexttable ) 1138 # If ENC != None, those 3 bits were enough for us to know the 1139 # encoding type, otherwise move on to the second table. 1140 1141 # The secondary tables have the format: 1142 # (mask, value, ENC). If the opcode is masked with "mask" 1143 # resulting in "value" we have found the instruction encoding. 1144 # NOTE: All entries in these tables *must* be from most specific 1145 # to least! 1146 1147 # Table for initial 3 bit == 0 1148 s_0_table = ( 1149 # Order is critical here... 1150 (binary("00000000000000000000000000010000"), binary("00000000000000000000000000000000"), IENC_DP_IMM_SHIFT), 1151 (binary("00000001100100000000000000010000"), binary("00000001000000000000000000000000"), IENC_MISC), 1152 (binary("00000001100100000000000010010000"), binary("00000001000000000000000000010000"), IENC_MISC1), 1153 (binary("00000001000000000000000011110000"), binary("00000000000000000000000010010000"), IENC_MULT), 1154 (binary("00000001001000000000000010010000"), binary("00000001001000000000000010010000"), IENC_EXTRA_LOAD), 1155 (binary("00000000000000000000000010010000"), binary("00000000000000000000000010010000"), IENC_EXTRA_LOAD), 1156 (binary("00000000000000000000000010010000"), binary("00000000000000000000000000010000"), IENC_DP_REG_SHIFT), 1157 (0,0, IENC_UNDEF), #catch-all 1158 ) 1159 1160 s_1_table = ( 1161 (binary("00000001100110000000000000000000"), binary("00000001000000000000000000000000"), IENC_UNDEF), 1162 (binary("00000001100110000000000000000000"), binary("00000001001000000000000000000000"), IENC_MOV_IMM_STAT), 1163 (0,0, IENC_DP_IMM), 1164 ) 1165 1166 s_3_table = ( 1167 (binary("00000001111100000000000011110000"),binary("00000001111100000000000011110000"), IENC_ARCH_UNDEF), 1168 (binary("00000000000000000000000000010000"),binary("00000000000000000000000000010000"), IENC_MEDIA), 1169 (0,0, IENC_LOAD_REG_OFF), 1170 ) 1171 1172 s_6_table = ( 1173 (binary("00001111111000000000000000000000"),binary("00001100010000000000000000000000"), IENC_COPROC_RREG_XFER), 1174 (binary("00001110000000000000000000000000"),binary("00001100000000000000000000000000"), IENC_COPROC_LOAD), 1175 ) 1176 1177 s_7_table = ( 1178 (binary("00000001000000000000000000000000"),binary("00000001000000000000000000000000"), IENC_SWINT), 1179 (binary("00000001000000000000000000010000"),binary("00000000000000000000000000010000"), IENC_COPROC_REG_XFER), 1180 (0, 0, IENC_COPROC_DP), 1181 ) 1182 1183 # Initial 3 (non conditional) primary table 1184 inittable = [ 1185 (None, s_0_table), 1186 (None, s_1_table), 1187 (IENC_LOAD_IMM_OFF, None), # Load or store an immediate 1188 (None, s_3_table), 1189 (IENC_LOAD_MULT, None), 1190 (IENC_BRANCH, None), 1191 (None, s_6_table), 1192 (None, s_7_table), 1193 (IENC_UNCOND, None), 1194 ] 1195 1196 # FIXME for emulation... 1197 #def s_lsl(val, shval): 1198 #pass 1199 1200 #def s_lsr(val, shval): 1201 #pass 1202 1203 # These are indexed by the 2 bit "shift" value in some DP encodings 1204 #shift_handlers = ( 1205 #s_lsl, 1206 #s_lsr, 1207 #s_asr, 1208 #s_ror, 1209 #) 1210 1211 endian_names = ("le","be") 1212 1213 #FIXME IF_NOFALL (and other envi flags) 1214
1215 -class ArmOpcode(envi.Opcode):
1216
1217 - def __hash__(self):
1218 return int(hash(self.mnem) ^ (self.size << 4))
1219
1220 - def __len__(self):
1221 return int(self.size)
1222
1223 - def getBranches(self, emu=None):
1224 """ 1225 Return a list of tuples. Each tuple contains the target VA of the 1226 branch, and a possible set of flags showing what type of branch it is. 1227 1228 See the BR_FOO types for all the supported envi branch flags.... 1229 Example: for bva,bflags in op.getBranches(): 1230 """ 1231 ret = [] 1232 1233 if not self.iflags & envi.IF_NOFALL: 1234 ret.append((self.va + self.size, envi.BR_FALL)) 1235 1236 # FIXME if this is a move to PC god help us... 1237 flags = 0 1238 if self.prefixes != COND_AL: 1239 flags |= envi.BR_COND 1240 if self.opcode == INS_B: 1241 oper = self.opers[0] 1242 ret.append((oper.getOperValue(self), flags)) 1243 elif self.opcode == INS_BL: 1244 oper = self.opers[0] 1245 ret.append((oper.getOperValue(self), flags | envi.BR_PROC)) 1246 return ret
1247
1248 - def render(self, mcanv):
1249 """ 1250 Render this opcode to the specified memory canvas 1251 """ 1252 mnem = self.mnem + cond_codes.get(self.prefixes) 1253 mcanv.addNameText(mnem, typename="mnemonic") 1254 mcanv.addText(" ") 1255 1256 # Allow each of our operands to render 1257 imax = len(self.opers) 1258 lasti = imax - 1 1259 for i in xrange(imax): 1260 oper = self.opers[i] 1261 oper.render(mcanv, self, i) 1262 if i != lasti: 1263 mcanv.addText(",")
1264 #mcanv.addText('; %s' % repr(self)) 1265
1266 - def __repr__(self):
1267 mnem = self.mnem + cond_codes.get(self.prefixes) 1268 # FIXME put in S flag! -- scratch that... optimize and preload a list of these combos! 1269 1270 # FIXME actually all these are broke... (iflags) 1271 # FIXME handle these in parsing too! 1272 daib_flags = self.iflags & IF_DAIB_MASK 1273 if self.iflags & IF_L: 1274 mnem += 'l' 1275 elif self.iflags & IF_PSR_S: 1276 mnem += 's' 1277 elif daib_flags > 0: 1278 idx = ((daib_flags)>>24) 1279 mnem += daib[idx] 1280 else: 1281 if self.iflags & IF_S: 1282 mnem += 's' 1283 if self.iflags & IF_B: 1284 mnem += 'b' 1285 if self.iflags & IF_H: 1286 mnem += 'h' 1287 elif self.iflags & IF_T: 1288 mnem += 't' 1289 1290 x = [] 1291 1292 for o in self.opers: 1293 x.append(o.repr(self)) 1294 return mnem + " " + ", ".join(x)
1295
1296 -class ArmRegOper(envi.Operand):
1297 - def __init__(self, reg, oflags=0):
1298 self.reg = reg 1299 self.oflags = oflags
1300
1301 - def __eq__(self, oper):
1302 if not isinstance(oper, self.__class__): 1303 return False 1304 if self.reg != oper.reg: 1305 return False 1306 if self.oflags != oper.oflags: 1307 return False 1308 return True
1309
1310 - def involvesPC(self):
1311 return self.reg == 15
1312
1313 - def getOperValue(self, op, emu=None):
1314 if emu == None: 1315 return None 1316 return emu.getRegister(self.reg)
1317
1318 - def setOperValue(self, op, emu=None, val=None):
1319 if emu == None: 1320 return None 1321 emu.setRegister(self.reg, val)
1322
1323 - def render(self, mcanv, op, idx):
1324 rname = arm_regs[self.reg][0] 1325 if self.oflags & OF_W: 1326 rname += "!" 1327 mcanv.addNameText(rname, typename='registers')
1328 1329
1330 - def repr(self, op):
1331 rname = arm_regs[self.reg][0] 1332 if self.oflags & OF_W: 1333 rname += "!" 1334 return rname
1335
1336 -class ArmRegShiftRegOper(envi.Operand):
1337
1338 - def __init__(self, reg, shtype, shreg):
1339 self.reg = reg 1340 self.shtype = shtype 1341 self.shreg = shreg
1342
1343 - def __eq__(self, oper):
1344 if not isinstance(oper, self.__class__): 1345 return False 1346 if self.reg != oper.reg: 1347 return False 1348 if self.shtype != oper.shtype: 1349 return False 1350 if self.shreg != oper.shreg: 1351 return False 1352 return True
1353
1354 - def involvesPC(self):
1355 return self.reg == 15
1356
1357 - def getOperValue(self, op, emu=None):
1358 if emu == None: 1359 return None 1360 return shifters[self.shtype](emu.getRegister(self.reg), emu.getRegister(shreg))
1361
1362 - def render(self, mcanv, op, idx):
1363 rname = arm_regs[self.reg][0] 1364 mcanv.addNameText(rname, typename='registers') 1365 mcanv.addText(', ') 1366 mcanv.addNameText(shift_names[self.shtype]) 1367 mcanv.addText(' ') 1368 mcanv.addNameText(arm_regs[self.shreg][0], typename='registers')
1369
1370 - def repr(self, op):
1371 rname = arm_regs[self.reg][0]+"," 1372 return " ".join([rname, shift_names[self.shtype], arm_regs[self.shreg][0]])
1373
1374 -class ArmRegShiftImmOper(envi.Operand):
1375
1376 - def __init__(self, reg, shtype, shimm):
1377 if shimm == 0: 1378 if shtype == S_ROR: 1379 shtype = S_RRX 1380 elif shtype == S_LSR or shtype == S_ASR: 1381 shimm = 32 1382 self.reg = reg 1383 self.shtype = shtype 1384 self.shimm = shimm
1385
1386 - def __eq__(self, oper):
1387 if not isinstance(oper, self.__class__): 1388 return False 1389 if self.reg != oper.reg: 1390 return False 1391 if self.shtype != oper.shtype: 1392 return False 1393 if self.shimm != oper.shimm: 1394 return False 1395 return True
1396
1397 - def involvesPC(self):
1398 return self.reg == 15
1399
1400 - def getOperValue(self, op, emu=None):
1401 if emu == None: 1402 return None 1403 return shifters[self.shtype](emu.getRegister(self.reg), self.shimm)
1404
1405 - def render(self, mcanv, op, idx):
1406 rname = arm_regs[self.reg][0] 1407 mcanv.addNameText(rname, typename='registers') 1408 if self.shimm != 0: 1409 mcanv.addText(', ') 1410 mcanv.addNameText(shift_names[self.shtype]) 1411 mcanv.addText(' ') 1412 mcanv.addNameText('#%d' % self.shimm) 1413 elif self.shtype == S_RRX: 1414 mcanv.addText(', ') 1415 mcanv.addNameText(shift_names[self.shtype])
1416
1417 - def repr(self, op):
1418 rname = arm_regs[self.reg][0] 1419 retval = [ rname ] 1420 if self.shimm != 0: 1421 retval.append(", "+shift_names[self.shtype]) 1422 retval.append("#%d"%self.shimm) 1423 elif self.shtype == S_RRX: 1424 retval.append(shift_names[self.shtype]) 1425 return " ".join(retval)
1426
1427 -class ArmImmOper(envi.Operand):
1428
1429 - def __init__(self, val, shval=0, shtype=S_ROR):
1430 self.val = val 1431 self.shval = shval 1432 self.shtype = shtype
1433
1434 - def __eq__(self, oper):
1435 if not isinstance(oper, self.__class__): 1436 return False 1437 if self.getOperValue(None) != oper.getOperValue(None): 1438 return False 1439 return True
1440
1441 - def involvesPC(self):
1442 return False
1443
1444 - def getOperValue(self, op, emu=None):
1445 return shifters[self.shtype](self.val, self.shval)
1446
1447 - def render(self, mcanv, op, idx):
1448 if self.shval != 0: 1449 mcanv.addNameText('#0x%.2x,%d' % (self.val, self.shval)) 1450 else: 1451 mcanv.addNameText('#0x%.2x' % (self.val))
1452
1453 - def repr(self, op):
1454 if self.shval != 0: 1455 return '#0x%.2x,%d' % (self.val, self.shval) 1456 else: 1457 return '#0x%.2x' % (self.val)
1458
1459 -class ArmScaledOffsetOper(envi.Operand):
1460 - def __init__(self, base_reg, offset_reg, shtype, shval, va, pubwl=0):
1461 if shval == 0: 1462 if shtype == S_ROR: 1463 shtype = S_RRX 1464 elif shtype == S_LSR or shtype == S_ASR: 1465 shval = 32 1466 self.base_reg = base_reg 1467 self.offset_reg = offset_reg 1468 self.shtype = shtype 1469 self.shval = shval 1470 self.pubwl = pubwl
1471
1472 - def __eq__(self, oper):
1473 if not isinstance(oper, self.__class__): 1474 return False 1475 if self.base_reg != oper.base_reg: 1476 return False 1477 if self.offset_reg != oper.offset_reg: 1478 return False 1479 if self.shtype != oper.shtype: 1480 return False 1481 if self.shval != oper.shval: 1482 return False 1483 if self.pubwl != oper.pubwl: 1484 return False 1485 return True
1486
1487 - def involvesPC(self):
1488 return self.base_reg == 15
1489
1490 - def getOperValue(self, op, emu=None):
1491 if emu == None: 1492 return None 1493 raise Exception("FIXME: Implement ArmScaledOffsetOper.getOperValue()") 1494 return None # FIXME
1495
1496 - def render(self, mcanv, op, idx):
1497 pom = ('-','')[(self.pubwl>>4)&1] 1498 idxing = self.pubwl & 0x12 1499 basereg = arm_regs[self.base_reg][0] 1500 offreg = arm_regs[self.offset_reg][0] 1501 shname = shift_names[self.shtype] 1502 1503 mcanv.addText('[') 1504 mcanv.addNameText(basereg, typename='registers') 1505 if (idxing&0x10) == 0: 1506 mcanv.addText('], ') 1507 else: 1508 mcanv.addText(', ') 1509 mcanv.addText(pom) 1510 mcanv.addNameText(offreg, typename='registers') 1511 mcanv.addText(' ') 1512 if self.shval != 0: 1513 mcanv.addNameText(shname) 1514 mcanv.addText(' ') 1515 mcanv.addNameText('#%d' % self.shval) 1516 if idxing == 0x10: 1517 mcanv.addText(']') 1518 elif idxing != 0: 1519 mcanv.addText(']!')
1520
1521 - def repr(self, op):
1522 pom = ('-','')[(self.pubwl>>4)&1] 1523 idxing = self.pubwl & 0x12 1524 basereg = arm_regs[self.base_reg][0] 1525 offreg = arm_regs[self.offset_reg][0] 1526 shname = shift_names[self.shtype] 1527 if self.shval != 0: 1528 shval = "%s #%d"%(shname,self.shval) 1529 elif self.shtype == S_RRX: 1530 shval = shname 1531 else: 1532 shval = "" 1533 if (idxing&0x10) == 0: # post-indexed 1534 tname = '[%s], %s%s %s' % (basereg, pom, offreg, shval) 1535 elif idxing == 0x10: 1536 tname = '[%s, %s%s %s]' % (basereg, pom, offreg, shval) 1537 else: # pre-indexed 1538 tname = '[%s, %s%s %s]!' % (basereg, pom, offreg, shval) 1539 return tname
1540
1541 -class ArmRegOffsetOper(envi.Operand):
1542 - def __init__(self, base_reg, offset_reg, va, pubwl=0):
1543 self.base_reg = base_reg 1544 self.offset_reg = offset_reg 1545 self.pubwl = pubwl
1546
1547 - def __eq__(self, oper):
1548 if not isinstance(oper, self.__class__): 1549 return False 1550 if self.base_reg != oper.base_reg: 1551 return False 1552 if self.offset_reg != oper.offset_reg: 1553 return False 1554 if self.pubwl != oper.pubwl: 1555 return False 1556 return True
1557
1558 - def involvesPC(self):
1559 return self.base_reg == 15
1560
1561 - def getOperValue(self, op, emu=None):
1562 if emu == None: 1563 return None 1564 raise Exception("FIXME: Implement ArmRegOffsetOper.getOperValue()")
1565
1566 - def render(self, mcanv, op, idx):
1567 pom = ('-','')[(self.pubwl>>4)&1] 1568 idxing = self.pubwl & 0x12 1569 basereg = arm_regs[self.base_reg][0] 1570 offreg = arm_regs[self.offset_reg][0] 1571 1572 mcanv.addText('[') 1573 mcanv.addNameText(basereg, typename='registers') 1574 if (idxing&0x10) == 0: 1575 mcanv.addText('] ') 1576 else: 1577 mcanv.addText(', ') 1578 mcanv.addText(pom) 1579 mcanv.addNameText(offreg, typename='registers') 1580 if idxing == 0x10: 1581 mcanv.addText(']') 1582 elif idxing != 0: 1583 mcanv.addText(']!')
1584
1585 - def repr(self, op):
1586 pom = ('-','')[(self.pubwl>>4)&1] 1587 idxing = self.pubwl & 0x12 1588 basereg = arm_regs[self.base_reg][0] 1589 offreg = arm_regs[self.offset_reg][0] 1590 if (idxing&0x10) == 0: # post-indexed 1591 tname = '[%s], %s%s' % (basereg, pom, offreg) 1592 elif idxing == 0x10: # offset addressing, not updated 1593 tname = '[%s, %s%s]' % (basereg, pom, offreg) 1594 else: # pre-indexed 1595 tname = '[%s, %s%s]!' % (basereg, pom, offreg) 1596 return tname
1597
1598 -class ArmImmOffsetOper(envi.Operand):
1599 - def __init__(self, base_reg, offset, va, pubwl=8):
1600 self.base_reg = base_reg 1601 self.offset = offset 1602 self.pubwl = pubwl
1603
1604 - def __eq__(self, oper):
1605 if not isinstance(oper, self.__class__): 1606 return False 1607 if self.base_reg != oper.base_reg: 1608 return False 1609 if self.offset != oper.offset: 1610 return False 1611 if self.pubwl != oper.pubwl: 1612 return False 1613 return True
1614
1615 - def involvesPC(self):
1616 return self.base_reg == 15
1617
1618 - def getOperValue(self, op, emu=None):
1619 if emu == None: 1620 return None 1621 1622 pubwl = self.pubwl >> 1 1623 w = pubwl & 1 1624 pubwl >>=1 1625 b = pubwl & 1 1626 pubwl >>=1 1627 u = pubwl & 1 1628 pubwl >>=1 1629 p = pubwl 1630 1631 addr = emu.getRegister(self.basereg) 1632 if u: 1633 addr += self.offset 1634 else: 1635 addr -= self.offset 1636 1637 fmt = ("B", "<L")[b] 1638 ret = emu.readMemoryFormat(addr, fmt) 1639 return ret
1640
1641 - def render(self, mcanv, op, idx):
1642 pom = ('-','')[(self.pubwl>>4)&1] 1643 idxing = self.pubwl & 0x12 1644 basereg = arm_regs[self.base_reg][0] 1645 mcanv.addText('[') 1646 mcanv.addNameText(basereg, typename='registers') 1647 if self.offset == 0: 1648 mcanv.addText(']') 1649 else: 1650 if (idxing&0x10) == 0: 1651 mcanv.addText('] ') 1652 else: 1653 mcanv.addText(', ') 1654 1655 mcanv.addNameText('#%s0x%x' % (pom,self.offset)) 1656 1657 if idxing == 0x10: 1658 mcanv.addText(']') 1659 elif idxing != 0: 1660 mcanv.addText(']!')
1661
1662 - def repr(self, op):
1663 pom = ('-','')[(self.pubwl>>4)&1] 1664 idxing = (self.pubwl) & 0x12 1665 basereg = arm_regs[self.base_reg][0] 1666 if self.offset != 0: 1667 offset = ", #%s0x%x"%(pom,self.offset) 1668 else: 1669 offset = "" 1670 1671 if (idxing&0x10) == 0: # post-indexed 1672 tname = '[%s]%s' % (basereg, offset) 1673 else: 1674 if idxing == 0x10: # offset addressing, not updated 1675 tname = '[%s%s]' % (basereg,offset) 1676 else: # pre-indexed 1677 tname = '[%s%s]!' % (basereg,offset) 1678 return tname
1679
1680 -class ArmOffsetOper(envi.Operand): # ArmImmOper but for Branches
1681 - def __init__(self, val, va):
1682 self.val = val # depending on mode, this is reg/imm 1683 self.va = va
1684
1685 - def __eq__(self, oper):
1686 if not isinstance(oper, self.__class__): 1687 return False 1688 if self.val != oper.val: 1689 return False 1690 if self.va != oper.va: 1691 return False 1692 return True
1693
1694 - def involvesPC(self):
1695 return True
1696
1697 - def getOperValue(self, op, emu=None):
1698 return self.va + self.val + op.size + 4 # FIXME WTF?
1699
1700 - def render(self, mcanv, op, idx):
1701 value = self.getOperValue(op) 1702 if mcanv.mem.isValidPointer(value): 1703 name = addrToName(mcanv, value) 1704 mcanv.addVaText(name, value) 1705 else: 1706 mcanv.addVaText('0x%.8x' % value, value)
1707
1708 - def repr(self, op):
1709 targ = self.getOperValue(op) 1710 tname = "#0x%.8x" % targ 1711 return tname
1712 1713 psrs = ("CPSR", "SPSR")
1714 -class ArmPgmStatRegOper(envi.Operand):
1715 - def __init__(self, val):
1716 self.val = val
1717
1718 - def __eq__(self, oper):
1719 if not isinstance(oper, self.__class__): 1720 return False 1721 if self.val != oper.val: 1722 return False 1723 return True
1724
1725 - def involvesPC(self):
1726 return False
1727
1728 - def getOperValue(self, op, emu=None):
1729 if emu == None: 1730 return None 1731 raise Exception("FIXME: Implement ArmPgmStatRegOper.getOperValue()") 1732 return None # FIXME
1733
1734 - def repr(self, op):
1735 return psrs[self.val]
1736
1737 -class ArmPgmStatFlagsOper(envi.Operand):
1738 # FIXED: visi: sorry, i accidentally overrode the previous class to have two meanings
1739 - def __init__(self, val):
1740 self.val = val
1741
1742 - def __eq__(self, oper):
1743 if not isinstance(oper, self.__class__): 1744 return False 1745 if self.val != oper.val: 1746 return False 1747 return True
1748
1749 - def involvesPC(self):
1750 return False
1751
1752 - def getOperValue(self, op, emu=None):
1753 if emu == None: 1754 return None 1755 raise Exception("FIXME: Implement ArmPgmStatRegOper.getOperValue()") 1756 return None # FIXME
1757
1758 - def repr(self, op):
1759 s = ["PSR_",psr_fields[self.val]] 1760 return "".join(s)
1761
1762 -class ArmEndianOper(ArmImmOper):
1763 - def repr(self, op):
1764 return endian_names[self.val]
1765
1766 - def involvesPC(self):
1767 return False
1768
1769 - def getOperValue(self, op, emu=None):
1770 return self.val
1771
1772 -class ArmRegListOper(envi.Operand):
1773 - def __init__(self, val, oflags=0):
1774 self.val = val 1775 self.oflags = oflags
1776
1777 - def __eq__(self, oper):
1778 if not isinstance(oper, self.__class__): 1779 return False 1780 if self.val != oper.val: 1781 return False 1782 if self.oflags != oper.oflags: 1783 return False 1784 return True
1785
1786 - def involvesPC(self):
1787 return self.val & 0x80 == 0x80
1788
1789 - def render(self, mcanv, op, idx):
1790 mcanv.addText('{') 1791 for l in xrange(16): 1792 if self.val & 1<<l: 1793 mcanv.addNameText(arm_regs[l][0], typename='registers') 1794 mcanv.addText(', ') 1795 mcanv.addText('}') 1796 if self.oflags & OF_UM: 1797 mcanv.addText('^')
1798
1799 - def getOperValue(self, op, emu=None):
1800 if emu == None: 1801 return None 1802 reglist = [] 1803 for regidx in xrange(16): 1804 #FIXME: check processor mode (abort, system, user, etc... use banked registers?) 1805 if self.val & (1<<regidx): 1806 reg = emu.getRegister(regidx) 1807 reglist.append(reg) 1808 return reglist
1809
1810 - def repr(self, op):
1811 s = [ "{" ] 1812 for l in xrange(16): 1813 if (self.val & (1<<l)): 1814 s.append(arm_regs[l][0]) 1815 s.append('}') 1816 if self.oflags & OF_UM: 1817 s.append('^') 1818 return " ".join(s)
1819 1820 aif_flags = (None, 'f','i','if','a','af','ai','aif')
1821 -class ArmPSRFlagsOper(envi.Operand):
1822 - def __init__(self, flags):
1823 self.flags = flags
1824
1825 - def __eq__(self, oper):
1826 if not isinstance(oper, self.__class__): 1827 return False 1828 if self.flags != oper.flags: 1829 return False 1830 return True
1831
1832 - def involvesPC(self):
1833 return False
1834
1835 - def getOperValue(self, op, emu=None):
1836 if emu == None: 1837 return None 1838 raise Exception("FIXME: Implement ArmPSRFlagsOper.getOperValue() (does it want to be a bitmask? or the actual value according to the PSR?)") 1839 return None # FIXME
1840
1841 - def repr(self, op):
1842 return aif_flags[self.flags]
1843
1844 -class ArmCoprocOpcodeOper(envi.Operand):
1845 - def __init__(self, val):
1846 self.val = val
1847
1848 - def __eq__(self, oper):
1849 if not isinstance(oper, self.__class__): 1850 return False 1851 if self.val != oper.val: 1852 return False 1853 return True
1854
1855 - def involvesPC(self):
1856 return False
1857
1858 - def getOperValue(self, op, emu=None):
1859 return self.val
1860
1861 - def repr(self, op):
1862 return "%d"%self.val
1863
1864 -class ArmCoprocOper(envi.Operand):
1865 - def __init__(self, val):
1866 self.val = val
1867
1868 - def __eq__(self, oper):
1869 if not isinstance(oper, self.__class__): 1870 return False 1871 if self.val != oper.val: 1872 return False 1873 return True
1874
1875 - def involvesPC(self):
1876 return False
1877
1878 - def getOperValue(self, op, emu=None):
1879 return self.val
1880
1881 - def repr(self, op):
1882 return "p%d"%self.val
1883
1884 -class ArmCoprocRegOper(envi.Operand):
1885 - def __init__(self, val, shtype=None, shval=None):
1886 self.val = val # depending on mode, this is reg/imm 1887 self.shval = shval 1888 self.shtype = shtype
1889
1890 - def __eq__(self, oper):
1891 if not isinstance(oper, self.__class__): 1892 return False 1893 if self.val != oper.val: 1894 return False 1895 if self.shval != oper.shval: 1896 return False 1897 if self.shtype != oper.shtype: 1898 return False 1899 return True
1900
1901 - def involvesPC(self):
1902 return False
1903
1904 - def getOperValue(self, op, emu=None):
1905 if emu == None: 1906 return None 1907 raise Exception("FIXME: Implement ArmCoprocRegOper.getOperValue()") 1908 return None # FIXME
1909
1910 - def repr(self, op):
1911 return "c%d"%self.val
1912 1913 1914
1915 -class ArmStdDisasm:
1916
1917 - def disasm(self, bytes, offset, va, trackMode=False):
1918 """ 1919 Parse a sequence of bytes out into an envi.Opcode instance. 1920 """ 1921 opbytes = bytes[offset:offset+4] 1922 opval, = struct.unpack("<L", opbytes) 1923 1924 cond = opval >> 28 1925 1926 # Begin the table lookup sequence with the first 3 non-cond bits 1927 encfam = (opval >> 25) & 0x7 1928 if cond == COND_EXTENDED: 1929 enc = IENC_UNCOND 1930 1931 else: 1932 1933 enc,nexttab = inittable[encfam] 1934 if nexttab != None: # we have to sub-parse... 1935 for mask,val,penc in nexttab: 1936 if (opval & mask) == val: 1937 enc = penc 1938 break 1939 1940 # If we don't know the encoding by here, we never will ;) 1941 if enc == None: 1942 raise InvalidInstruction(bytes[:4]) 1943 1944 opcode, mnem, olist, flags = ienc_parsers[enc](opval, va) 1945 # Ok... if we're a non-conditional branch, *or* we manipulate PC unconditionally, 1946 # lets call ourself envi.IF_NOFALL 1947 if cond == COND_AL: 1948 if opcode in (INS_B, INS_BX): 1949 flags |= envi.IF_NOFALL 1950 1951 elif ( len(olist) and 1952 isinstance(olist[0], ArmRegOper) and 1953 olist[0].involvesPC() ): 1954 1955 showop = True 1956 flags |= envi.IF_NOFALL 1957 1958 1959 # FIXME conditionals are currently plumbed as "prefixes". Perhaps normalize to that... 1960 op = ArmOpcode(va, opcode, mnem, cond, 4, olist, flags) 1961 op.encoder = enc #FIXME: DEBUG CODE 1962 1963 return op
1964
1965 - def checkSetMode(self, op): # FIXME: i'm forked. bx references a register... emulation required unless we want to trust it to always mean a jump to thumb...
1966 # CHANGE TO THUMB MODE FROM ARM 1967 # if bx or blx and target is odd 1968 # if dst is r15 and target is odd 1969 # if set T bit in SPSR then reload CPSR from SPSR (sh*t, emulation here we come) 1970 olist = op.opers 1971 if op.opcode == INS_BX: 1972 self.parent.setMode( olist[0]&1 ) # fornicated because we don't know what the register value is 1973 self.parent.setMode( 1 ) # FIXME: HACK! assumes always a call to bx 1974 elif ( len(olist) > 1 and 1975 isinstance(olist[0], ArmRegOper) and 1976 olist[0].reg == REG_PC ): 1977 mode = olist[1].getOperValue(op) 1978 if mode != None: 1979 self.parent.setMode( mode&1 ) 1980 1981 # CHANGE TO JAZELLE MODE 1982 # if bxj is called and jazelle is available and enabled.... sheesh this is gonna get complex 1983 elif op.opcode == INS_BXJ: 1984 if self.parent.jzl_enabled: 1985 self.parent.setMode( 2 ) 1986 else: 1987 pass # how do we change PC from here? bxj changes to jazelle mode,
1988 # but if it's unavailable, the operand is the Arm/Thumb "handler" 1989