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

Source Code for Module envi.archs.arm.emu

  1   
  2  """ 
  3  The initial arm module. 
  4  """ 
  5   
  6  import struct 
  7   
  8  import envi 
  9  from envi.archs.arm import ArmModule 
 10  from envi.archs.arm.regs import * 
 11  from envi.archs.arm.thumbdisasm import *    #this gets both arm and thumb 
 12   
 13   
 14   
 15  # CPU state (memory, regs inc SPSRs and banked registers) 
 16  # CPU mode  (User, FIQ, IRQ, supervisor, Abort, Undefined, System) 
 17  #  
 18  # instruction code 
 19  # exception handler code 
 20  # FIXME: SPSR handling is not certain.   
 21   
 22  # calling conventions 
23 -class ArmArchitectureProcedureCall(envi.CallingConvention):
24 """ 25 Implement calling conventions for your arch. 26 """
27 - def setReturnValue(self, emu, value, ccinfo=None):
28 esp = emu.getRegister(REG_ESP) 29 eip = struct.unpack("<L", emu.readMemory(esp, 4))[0] 30 esp += 4 # For the saved eip 31 esp += (4 * argc) # Cleanup saved args 32 33 emu.setRegister(REG_ESP, esp) 34 emu.setRegister(REG_EAX, value) 35 emu.setProgramCounter(eip)
36 37
38 - def getCallArgs(self, emu, count):
39 return emu.getRegisters(0xf) # r0-r3 are used to hand in parameters. additional parms are stored and pointed to by r0
40 41 aapcs = ArmArchitectureProcedureCall() 42
43 -class CoProcEmulator: # useful for prototyping, but should be subclassed
44 - def __init__(self):
45 pass
46
47 - def stc(self, parms):
48 print >>sys.stderr,"CoProcEmu: stc(%s)"%repr(parms)
49 - def ldc(self, parms):
50 print >>sys.stderr,"CoProcEmu: ldc(%s)"%repr(parms)
51 - def cdp(self, parms):
52 print >>sys.stderr,"CoProcEmu: cdp(%s)"%repr(parms)
53 - def mcr(self, parms):
54 print >>sys.stderr,"CoProcEmu: mcr(%s)"%repr(parms)
55 - def mcrr(self, parms):
56 print >>sys.stderr,"CoProcEmu: mcrr(%s)"%repr(parms)
57 - def mrc(self, parms):
58 print >>sys.stderr,"CoProcEmu: mrc(%s)"%repr(parms)
59 - def mrrc(self, parms):
60 print >>sys.stderr,"CoProcEmu: mrrc(%s)"%repr(parms)
61 62 63
64 -class ArmEmulator(ArmModule, ArmRegisterContext, envi.Emulator):
65
66 - def __init__(self):
67 ArmModule.__init__(self) 68 69 self.coprocs = [CoProcEmulator() for x in xrange(16)] # FIXME: this should be None's, and added in for each real coproc... but this will work for now. 70 71 seglist = [ (0,0xffffffff) for x in xrange(6) ] 72 envi.Emulator.__init__(self, segs=seglist) 73 74 ArmRegisterContext.__init__(self) 75 76 self.addCallingConvention("Arm Arch Procedure Call", aapcs)
77
78 - def undefFlags(self):
79 """ 80 Used in PDE. 81 A flag setting operation has resulted in un-defined value. Set 82 the flags to un-defined as well. 83 """ 84 self.setRegister(REG_EFLAGS, None)
85
86 - def setFlag(self, which, state, mode=PM_usr): # FIXME: CPSR?
87 flags = self.getSPSR(mode) 88 if state: 89 flags |= which 90 else: 91 flags &= ~which 92 self.setSPSR(mode, flags)
93
94 - def getFlag(self, which, mode=PM_usr): # FIXME: CPSR?
95 #if (flags_reg == None): 96 # flags_reg = proc_modes[self.getProcMode()][5] 97 #flags = self.getRegister(flags_reg) 98 flags = self.getSPSR(mode) 99 if flags == None: 100 raise envi.PDEUndefinedFlag(self) 101 return bool(flags & which) 102
103 - def readMemValue(self, addr, size):
104 bytes = self.readMemory(addr, size) 105 if bytes == None: 106 return None 107 #FIXME change this (and all uses of it) to passing in format... 108 #FIXME: Remove byte check and possibly half-word check. (possibly all but word?) 109 if len(bytes) != size: 110 raise Exception("Read Gave Wrong Length At 0x%.8x (va: 0x%.8x wanted %d got %d)" % (self.getProgramCounter(),addr, size, len(bytes))) 111 if size == 1: 112 return struct.unpack("B", bytes)[0] 113 elif size == 2: 114 return struct.unpack("<H", bytes)[0] 115 elif size == 4: 116 return struct.unpack("<L", bytes)[0] 117 elif size == 8: 118 return struct.unpack("<Q", bytes)[0]
119
120 - def writeMemValue(self, addr, value, size):
121 #FIXME change this (and all uses of it) to passing in format... 122 #FIXME: Remove byte check and possibly half-word check. (possibly all but word?) 123 if size == 1: 124 bytes = struct.pack("B",value & 0xff) 125 elif size == 2: 126 bytes = struct.pack("<H",value & 0xffff) 127 elif size == 4: 128 bytes = struct.pack("<L", value & 0xffffffff) 129 elif size == 8: 130 bytes = struct.pack("<Q", value & 0xffffffffffffffff) 131 self.writeMemory(addr, bytes)
132
133 - def readMemSignedValue(self, addr, size):
134 #FIXME: Remove byte check and possibly half-word check. (possibly all but word?) 135 bytes = self.readMemory(addr, size) 136 if bytes == None: 137 return None 138 if size == 1: 139 return struct.unpack("b", bytes)[0] 140 elif size == 2: 141 return struct.unpack("<h", bytes)[0] 142 elif size == 4: 143 return struct.unpack("<l", bytes)[0]
144
145 - def executeOpcode(self, op):
146 # NOTE: If an opcode method returns 147 # other than None, that is the new eip 148 x = None 149 if op.prefixes >= 0xe or op.prefixes == (self.getRegister(REG_FLAGS)>>28): #nearly every opcode is optional 150 meth = self.op_methods.get(op.mnem, None) 151 if meth == None: 152 raise envi.UnsupportedInstruction(self, op) 153 x = meth(op) 154 print >>sys.stderr,"executed instruction, returned: %s"%x 155 156 if x == None: 157 pc = self.getProgramCounter() 158 x = pc+op.size 159 160 self.setProgramCounter(x)
161
162 - def doPush(self, val):
163 esp = self.getRegister(REG_ESP) 164 esp -= 4 165 self.writeMemValue(esp, val, 4) 166 self.setRegister(REG_ESP, esp)
167
168 - def doPop(self):
169 esp = self.getRegister(REG_ESP) 170 val = self.readMemValue(esp, 4) 171 self.setRegister(REG_ESP, esp+4) 172 return val
173
174 - def getProcMode(self):
175 return self._rctx_vals[REG_CPSR] & 0x1f # obfuscated for speed. could call getCPSR but it's not as fast
176
177 - def getCPSR(self):
178 return self._rctx_vals[REG_CPSR]
179
180 - def setCPSR(self, psr):
181 self._rctx_vals[REG_CPSR] = psr
182
183 - def getSPSR(self, mode):
184 return self._rctx_vals[((mode&0xf)*17)+16]
185
186 - def setSPSR(self, mode, psr):
187 self._rctx_vals[((mode&0xf)*17)+16] = psr
188
189 - def setProcMode(self, mode):
190 # write current psr to the saved psr register for current mode 191 curSPSRidx = proc_modes[self.getProcMode()][5] 192 self._rctx_vals[curSPSRidx] = self._rctx_vals[REG_CPSR] 193 194 # do we restore saved spsr? 195 cpsr = self._rctx_vals[REG_CPSR] & 0xffffffe0 196 self._rctx_vals[REG_CPSR] = cpsr | mode
197
198 - def getRegister(self, index, mode=None):
199 """ 200 Return the current value of the specified register index. 201 """ 202 if mode == None: 203 mode = self.getProcMode() & 0xf 204 else: 205 mode &= 0xf 206 idx = (index & 0xffff) 207 ridx = idx + (mode*17) # account for different banks of registers 208 ridx = reg_table[ridx][2] # magic pointers allowing overlapping banks of registers 209 if idx == index: 210 return self._rctx_vals[ridx] 211 212 offset = (index >> 24) & 0xff 213 width = (index >> 16) & 0xff 214 215 mask = (2**width)-1 216 return (self._rctx_vals[ridx] >> offset) & mask
217
218 - def setRegister(self, index, value, mode=None):
219 """ 220 Set a register value by index. 221 """ 222 if mode == None: 223 mode = self.getProcMode() & 0xf 224 else: 225 mode &= 0xf 226 227 self._rctx_dirty = True 228 229 idx = (index & 0xffff) 230 ridx = idx + (mode*17) # account for different banks of registers 231 ridx = reg_table[ridx][2] # magic pointers allowing overlapping banks of registers 232 if idx == index: 233 self._rctx_vals[ridx] = (value & self._rctx_masks[ridx]) # FIXME: hack. should look up index in proc_modes dict? 234 return 235 236 # If we get here, it's a meta register index. 237 # NOTE: offset/width are in bits... 238 offset = (index >> 24) & 0xff 239 width = (index >> 16) & 0xff 240 241 #FIXME is it faster to generate or look thses up? 242 mask = (2**width)-1 243 mask = mask << offset 244 245 # NOTE: basewidth is in *bits* 246 basewidth = self._rctx_widths[ridx] 247 basemask = (2**basewidth)-1 248 249 # cut a whole in basemask at the size/offset of mask 250 finalmask = basemask ^ mask 251 252 curval = self._rctx_vals[ridx] 253 254 self._rctx_vals[ridx] = (curval & finalmask) | (value << offset)
255
256 - def integerSubtraction(self, op):
257 """ 258 Do the core of integer subtraction but only *return* the 259 resulting value rather than assigning it. 260 (allows cmp and sub to use the same code) 261 """ 262 # Src op gets sign extended to dst 263 #FIXME account for same operand with zero result for PDE 264 src1 = self.getOperValue(op, 1) 265 src2 = self.getOperValue(op, 2) 266 Sflag = op.iflags & IF_PSR_S 267 268 if src1 == None or src2 == None: 269 self.undefFlags() 270 return None 271 272 return self.intSubBase(src1, src2, Sflag)
273
274 - def intSubBase(self, src1, src2, Sflag=0, rd=0):
275 # So we can either do a BUNCH of crazyness with xor and shifting to 276 # get the necissary flags here, *or* we can just do both a signed and 277 # unsigned sub and use the results. 278 279 280 usrc = e_bits.unsigned(src1, 4) 281 udst = e_bits.unsigned(src2, 4) 282 283 ssrc = e_bits.signed(src1, 4) 284 sdst = e_bits.signed(src2, 4) 285 286 ures = udst - usrc 287 sres = sdst - ssrc 288 289 if Sflag: 290 curmode = self.getProcMode() 291 if rd == 15: 292 if(curmode != PM_sys and curmode != PM_usr): 293 self.setCPSR(self.getSPSR(curmode)) 294 else: 295 raise Exception("Messed up opcode... adding to r15 from PM_usr or PM_sys") 296 self.setFlag(PSR_C, e_bits.is_unsigned_carry(ures, 4)) 297 self.setFlag(PSR_Z, not ures) 298 self.setFlag(PSR_N, e_bits.is_signed(ures, 4)) 299 self.setFlag(PSR_V, e_bits.is_signed_overflow(sres, 4)) 300 301 #print "s2size/s1size: %d %d" % (s2size, s1size) 302 #print "unsigned: %d %d %d" % (usrc, udst, ures) 303 #print "signed: %d %d %d" % (ssrc, sdst, sres) 304 305 #if Sflag: 306 # self.setFlag(PSR_N, sres>>32) 307 # self.setFlag(PSR_Z, sres==0) 308 # self.setFlag(PSR_C, e_bits.is_unsigned_carry(ures, s2size)) 309 # self.setFlag(PSR_V, e_bits.is_signed_overflow(sres, s2size)) 310 311 return ures
312 313
314 - def logicalAnd(self, op):
315 src1 = self.getOperValue(op, 1) 316 src2 = self.getOperValue(op, 2) 317 318 # PDE 319 if src1 == None or src2 == None: 320 self.undefFlags() 321 self.setOperValue(op, 0, None) 322 return 323 324 res = src1 & src2 325 326 self.setFlag(PSR_N, 0) 327 self.setFlag(PSR_V, 0) 328 self.setFlag(PSR_C, 0) 329 self.setFlag(PSR_Z, not res) 330 return res
331
332 - def i_and(self, op):
333 res = self.logicalAnd(op) 334 self.setOperValue(op, 0, res)
335
336 - def i_stm(self, op):
337 srcreg = self.getOperValue(op,0) 338 regmask = self.getOperValue(op,1) 339 pc = self.getRegister(REG_PC) # store for later check 340 341 start_address = self.getRegister(srcreg) 342 addr = start_address 343 for reg in xrange(16): 344 if reg in regmask: 345 val = self.getRegister(reg) 346 if op.iflags & IF_DAIB_B: 347 if op.iflags & IF_DAIB_I: 348 addr += 4 349 else: 350 addr -= 4 351 self.writeMemValue(addr, val, 4) 352 else: 353 self.writeMemValue(addr, val, 4) 354 if op.iflags & IF_DAIB_I: 355 addr += 4 356 else: 357 addr -= 4 358 if op.opers[0].oflags & OF_W: 359 self.setRegister(srcreg,addr) 360 #FIXME: add "shared memory" functionality? prolly just in strex which will be handled in i_strex 361 # is the following necessary? 362 newpc = self.getRegister(REG_PC) # check whether pc has changed 363 if pc != newpc: 364 return newpc
365 366 i_stmia = i_stm 367 368
369 - def i_ldm(self, op):
370 srcreg = self.getOperValue(op,0) 371 regmask = self.getOperValue(op,1) 372 pc = self.getRegister(REG_PC) # store for later check 373 374 start_address = self.getRegister(srcreg) 375 addr = start_address 376 for reg in xrange(16): 377 if reg in regmask: 378 if op.iflags & IF_DAIB_B: 379 if op.iflags & IF_DAIB_I: 380 addr += 4 381 else: 382 addr -= 4 383 regval = self.readMemValue(addr, 4) 384 self.setRegister(reg, regval) 385 else: 386 regval = self.readMemValue(addr, 4) 387 self.setRegister(reg, regval) 388 if op.iflags & IF_DAIB_I: 389 addr += 4 390 else: 391 addr -= 4 392 if op.opers[0].oflags & OF_W: 393 self.setRegister(srcreg,addr) 394 #FIXME: add "shared memory" functionality? prolly just in ldrex which will be handled in i_ldrex 395 # is the following necessary? 396 newpc = self.getRegister(REG_PC) # check whether pc has changed 397 if pc != newpc: 398 return newpc
399 400 i_ldmia = i_ldm 401
402 - def i_ldr(self, op):
403 # hint: covers ldr, ldrb, ldrbt, ldrd, ldrh, ldrsh, ldrsb, ldrt (any instr where the syntax is ldr{condition}stuff) 404 val = self.getOperValue(op, 1) 405 self.setOperValue(op, 0, val) 406 if op.opers[0].reg == REG_PC: 407 return val
408 409 410 411 412
413 - def i_add(self, op):
414 src1 = self.getOperValue(op, 1) 415 src2 = self.getOperValue(op, 2) 416 417 #FIXME PDE and flags 418 if src1 == None or src2 == None: 419 self.undefFlags() 420 self.setOperValue(op, 0, None) 421 return 422 423 dsize = op.opers[0].tsize 424 ssize = op.opers[1].tsize 425 s2size = op.opers[2].tsize 426 427 usrc1 = e_bits.unsigned(src1, 4) 428 usrc2 = e_bits.unsigned(src2, 4) 429 ssrc1 = e_bits.signed(src1, 4) 430 ssrc2 = e_bits.signed(src2, 4) 431 432 ures = usrc1 + usrc2 433 sres = ssrc1 + ssrc2 434 435 436 self.setOperValue(op, 0, ures) 437 438 curmode = self.getProcMode() 439 if op.flags & IF_S: 440 if op.opers[0].reg == 15 and (curmode != PM_sys and curmode != PM_usr): 441 self.setCPSR(self.getSPSR(curmode)) 442 else: 443 raise Exception("Messed up opcode... adding to r15 from PM_usr or PM_sys") 444 self.setFlag(PSR_C, e_bits.is_unsigned_carry(ures, dsize)) 445 self.setFlag(PSR_Z, not ures) 446 self.setFlag(PSR_N, e_bits.is_signed(ures, dsize)) 447 self.setFlag(PSR_V, e_bits.is_signed_overflow(sres, dsize))
448
449 - def i_b(self, op):
450 return self.getOperValue(op, 0)
451
452 - def i_bl(self, op):
453 self.setRegister(REG_LR, self.getRegister(REG_PC)) 454 return self.getOperValue(op, 0)
455
456 - def i_tst(self, op):
457 src1 = self.getOperValue(op, 0) 458 src2 = self.getOperValue(op, 1) 459 460 dsize = op.opers[0].tsize 461 ures = src1 & src2 462 463 self.setFlag(PSR_N, e_bits.is_signed(ures, dsize)) 464 self.setFlag(PSR_Z, (0,1)[ures==0]) 465 self.setFlag(PSR_C, e_bits.is_unsigned_carry(ures, dsize))
466 #self.setFlag(PSR_V, e_bits.is_signed_overflow(sres, dsize)) 467
468 - def i_rsb(self, op):
469 src1 = self.getOperValue(op, 1) 470 src2 = self.getOperValue(op, 2) 471 472 #FIXME PDE and flags 473 if src1 == None or src2 == None: 474 self.undefFlags() 475 self.setOperValue(op, 0, None) 476 return 477 478 dsize = op.opers[0].tsize 479 ssize = op.opers[1].tsize 480 s2size = op.opers[2].tsize 481 482 usrc1 = e_bits.unsigned(src1, 4) 483 usrc2 = e_bits.unsigned(src2, 4) 484 ssrc1 = e_bits.signed(src1, 4) 485 ssrc2 = e_bits.signed(src2, 4) 486 487 ures = usrc2 - usrc1 488 sres = ssrc2 - ssrc1 489 490 491 self.setOperValue(op, 0, ures) 492 493 curmode = self.getProcMode() 494 if op.flags & IF_S: 495 if op.opers[0].reg == 15: 496 if (curmode != PM_sys and curmode != PM_usr): 497 self.setCPSR(self.getSPSR(curmode)) 498 else: 499 raise Exception("Messed up opcode... adding to r15 from PM_usr or PM_sys") 500 self.setFlag(PSR_C, e_bits.is_unsigned_carry(ures, dsize)) 501 self.setFlag(PSR_Z, not ures) 502 self.setFlag(PSR_N, e_bits.is_signed(ures, dsize)) 503 self.setFlag(PSR_V, e_bits.is_signed_overflow(sres, dsize))
504
505 - def i_rsb(self, op):
506 # Src op gets sign extended to dst 507 #FIXME account for same operand with zero result for PDE 508 src1 = self.getOperValue(op, 1) 509 src2 = self.getOperValue(op, 2) 510 Sflag = op.iflags & IF_PSR_S 511 512 if src1 == None or src2 == None: 513 self.undefFlags() 514 return None 515 516 res = self.intSubBase(src2, src1, Sflag, op.opers[0].reg) 517 self.setOperValue(op, 0, res)
518
519 - def i_sub(self, op):
520 # Src op gets sign extended to dst 521 #FIXME account for same operand with zero result for PDE 522 src1 = self.getOperValue(op, 1) 523 src2 = self.getOperValue(op, 2) 524 Sflag = op.iflags & IF_PSR_S 525 526 if src1 == None or src2 == None: 527 self.undefFlags() 528 return None 529 530 res = self.intSubBase(src1, src2, Sflag, op.opers[0].reg) 531 self.setOperValue(op, 0, res)
532
533 - def i_eor(self, op):
534 src1 = self.getOperValue(op, 1) 535 src2 = self.getOperValue(op, 2) 536 537 #FIXME PDE and flags 538 if src1 == None or src2 == None: 539 self.undefFlags() 540 self.setOperValue(op, 0, None) 541 return 542 543 usrc1 = e_bits.unsigned(src1, 4) 544 usrc2 = e_bits.unsigned(src2, 4) 545 546 ures = usrc1 ^ usrc2 547 548 self.setOperValue(op, 0, ures) 549 550 curmode = self.getProcMode() 551 if op.iflags & IF_S: 552 if op.opers[0].reg == 15: 553 if (curmode != PM_sys and curmode != PM_usr): 554 self.setCPSR(self.getSPSR(curmode)) 555 else: 556 raise Exception("Messed up opcode... adding to r15 from PM_usr or PM_sys") 557 self.setFlag(PSR_C, e_bits.is_unsigned_carry(ures, 4)) 558 self.setFlag(PSR_Z, not ures) 559 self.setFlag(PSR_N, e_bits.is_signed(ures, 4)) 560 self.setFlag(PSR_V, e_bits.is_signed_overflow(sres, 4))
561 562 563 564 565 # Coprocessor Instructions
566 - def i_stc(self, op):
567 cpnum = op.opers[0] 568 coproc = self._getCoProc(cpnum) 569 coproc.stc(op.opers)
570
571 - def i_ldc(self, op):
572 cpnum = op.opers[0] 573 coproc = self._getCoProc(cpnum) 574 coproc.ldc(op.opers)
575
576 - def i_cdp(self, op):
577 cpnum = op.opers[0] 578 coproc = self._getCoProc(cpnum) 579 coproc.cdp(op.opers)
580
581 - def i_mrc(self, op):
582 cpnum = op.opers[0] 583 coproc = self._getCoProc(cpnum) 584 coproc.mrc(op.opers)
585
586 - def i_mrrc(self, op):
587 cpnum = op.opers[0] 588 coproc = self._getCoProc(cpnum) 589 coproc.mrrc(op.opers)
590
591 - def i_mcr(self, op):
592 cpnum = op.opers[0] 593 coproc = self._getCoProc(cpnum) 594 coproc.mrrc(op.opers)
595
596 - def i_mcrr(self, op):
597 cpnum = op.opers[0] 598 coproc = self._getCoProc(cpnum) 599 coproc.mcrr(op.opers)
600 601 602 603 604 opcode_dist = \ 605 [('and', 4083),# 606 ('stm', 1120),# 607 ('ldr', 1064),# 608 ('add', 917),# 609 ('stc', 859),# 610 ('str', 770),# 611 ('bl', 725),# 612 ('ldm', 641),# 613 ('b', 472),# 614 ('ldc', 469),# 615 ('tst', 419),# 616 ('rsb', 196),# 617 ('eor', 180),# 618 ('mul', 159), 619 ('swi', 128), 620 ('sub', 110),# 621 ('adc', 96), 622 ('cdp', 74),# 623 ('orr', 66), 624 ('cmn', 59), 625 ('mcr', 55),# 626 ('stc2', 54), 627 ('ldc2', 52), 628 ('mrc', 49),# 629 ('mvn', 47), 630 ('rsc', 46), 631 ('teq', 45), 632 ('cmp', 41), 633 ('sbc', 40), 634 ('mov', 35), 635 ('bic', 34), 636 ('mcr2', 29),# 637 ('mrc2', 28),# 638 ('swp', 28), 639 ('mcrr', 21),# 640 ('mrrc', 20),# 641 ('usada8', 20), 642 ('qadd', 13), 643 ('mrrc2', 10),# 644 ('add16', 9), 645 ('mla', 9), 646 ('mcrr2', 7),# 647 ('uqsub16', 6), 648 ('uqadd16', 5), 649 ('sub16', 5), 650 ('umull', 4), 651 ('uq', 3), 652 ('smlsdx', 3), 653 ('uhsub16', 3), 654 ('uqsubaddx', 3), 655 ('qdsub', 2), 656 ('subaddx', 2), 657 ('uqadd8', 2), 658 ('ssat', 2), 659 ('uqaddsubx', 2), 660 ('smull', 2), 661 ('blx', 2), 662 ('smlal', 2), 663 ('shsub16', 1), 664 ('', 1), 665 ('smlsd', 1), 666 ('pkhbt', 1), 667 ('revsh', 1), 668 ('qadd16', 1), 669 ('uqsub8', 1), 670 ('ssub16', 1), 671 ('usad8', 1), 672 ('uadd16', 1), 673 ('smladx', 1), 674 ('swpb', 1), 675 ('smlaldx', 1), 676 ('usat', 1), 677 ('umlal', 1), 678 ('rev16', 1), 679 ('sadd16', 1), 680 ('sel', 1), 681 ('sub8', 1), 682 ('pkhtb', 1), 683 ('umaal', 1), 684 ('addsubx', 1), 685 ('add8', 1), 686 ('smlad', 1), 687 ('sxtb', 1), 688 ('sadd8', 1)] 689