13d8817e4Smiod /* Instruction printing code for the ARM
23d8817e4Smiod Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
33d8817e4Smiod Free Software Foundation, Inc.
43d8817e4Smiod Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
53d8817e4Smiod Modification by James G. Smith (jsmith@cygnus.co.uk)
63d8817e4Smiod
73d8817e4Smiod This file is part of libopcodes.
83d8817e4Smiod
93d8817e4Smiod This program is free software; you can redistribute it and/or modify it under
103d8817e4Smiod the terms of the GNU General Public License as published by the Free
113d8817e4Smiod Software Foundation; either version 2 of the License, or (at your option)
123d8817e4Smiod any later version.
133d8817e4Smiod
143d8817e4Smiod This program is distributed in the hope that it will be useful, but WITHOUT
153d8817e4Smiod ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
163d8817e4Smiod FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
173d8817e4Smiod more details.
183d8817e4Smiod
193d8817e4Smiod You should have received a copy of the GNU General Public License
203d8817e4Smiod along with this program; if not, write to the Free Software
213d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
223d8817e4Smiod
233d8817e4Smiod #include "sysdep.h"
243d8817e4Smiod
253d8817e4Smiod #include "dis-asm.h"
263d8817e4Smiod #include "opcode/arm.h"
273d8817e4Smiod #include "opintl.h"
283d8817e4Smiod #include "safe-ctype.h"
293d8817e4Smiod
303d8817e4Smiod /* FIXME: This shouldn't be done here. */
313d8817e4Smiod #include "coff/internal.h"
323d8817e4Smiod #include "libcoff.h"
333d8817e4Smiod #include "elf-bfd.h"
343d8817e4Smiod #include "elf/internal.h"
353d8817e4Smiod #include "elf/arm.h"
363d8817e4Smiod
373d8817e4Smiod /* FIXME: Belongs in global header. */
383d8817e4Smiod #ifndef strneq
393d8817e4Smiod #define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
403d8817e4Smiod #endif
413d8817e4Smiod
423d8817e4Smiod #ifndef NUM_ELEM
433d8817e4Smiod #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
443d8817e4Smiod #endif
453d8817e4Smiod
463d8817e4Smiod struct opcode32
473d8817e4Smiod {
483d8817e4Smiod unsigned long arch; /* Architecture defining this insn. */
493d8817e4Smiod unsigned long value, mask; /* Recognise insn if (op&mask)==value. */
503d8817e4Smiod const char *assembler; /* How to disassemble this insn. */
513d8817e4Smiod };
523d8817e4Smiod
533d8817e4Smiod struct opcode16
543d8817e4Smiod {
553d8817e4Smiod unsigned long arch; /* Architecture defining this insn. */
563d8817e4Smiod unsigned short value, mask; /* Recognise insn if (op&mask)==value. */
573d8817e4Smiod const char *assembler; /* How to disassemble this insn. */
583d8817e4Smiod };
593d8817e4Smiod
603d8817e4Smiod /* print_insn_coprocessor recognizes the following format control codes:
613d8817e4Smiod
623d8817e4Smiod %% %
633d8817e4Smiod
643d8817e4Smiod %c print condition code (always bits 28-31)
653d8817e4Smiod %A print address for ldc/stc/ldf/stf instruction
663d8817e4Smiod %I print cirrus signed shift immediate: bits 0..3|4..6
673d8817e4Smiod %F print the COUNT field of a LFM/SFM instruction.
683d8817e4Smiod %P print floating point precision in arithmetic insn
693d8817e4Smiod %Q print floating point precision in ldf/stf insn
703d8817e4Smiod %R print floating point rounding mode
713d8817e4Smiod
723d8817e4Smiod %<bitfield>r print as an ARM register
733d8817e4Smiod %<bitfield>d print the bitfield in decimal
743d8817e4Smiod %<bitfield>x print the bitfield in hex
753d8817e4Smiod %<bitfield>X print the bitfield as 1 hex digit without leading "0x"
763d8817e4Smiod %<bitfield>f print a floating point constant if >7 else a
773d8817e4Smiod floating point register
783d8817e4Smiod %<bitfield>w print as an iWMMXt width field - [bhwd]ss/us
793d8817e4Smiod %<bitfield>g print as an iWMMXt 64-bit register
803d8817e4Smiod %<bitfield>G print as an iWMMXt general purpose or control register
813d8817e4Smiod
823d8817e4Smiod %<code>y print a single precision VFP reg.
833d8817e4Smiod Codes: 0=>Sm, 1=>Sd, 2=>Sn, 3=>multi-list, 4=>Sm pair
843d8817e4Smiod %<code>z print a double precision VFP reg
853d8817e4Smiod Codes: 0=>Dm, 1=>Dd, 2=>Dn, 3=>multi-list
863d8817e4Smiod %<bitnum>'c print specified char iff bit is one
873d8817e4Smiod %<bitnum>`c print specified char iff bit is zero
883d8817e4Smiod %<bitnum>?ab print a if bit is one else print b
893d8817e4Smiod
903d8817e4Smiod %L print as an iWMMXt N/M width field.
913d8817e4Smiod %Z print the Immediate of a WSHUFH instruction.
923d8817e4Smiod %l like 'A' except use byte offsets for 'B' & 'H'
933d8817e4Smiod versions. */
943d8817e4Smiod
953d8817e4Smiod /* Common coprocessor opcodes shared between Arm and Thumb-2. */
963d8817e4Smiod
973d8817e4Smiod static const struct opcode32 coprocessor_opcodes[] =
983d8817e4Smiod {
993d8817e4Smiod /* XScale instructions. */
1003d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e200010, 0x0fff0ff0, "mia%c\tacc0, %0-3r, %12-15r"},
1013d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e280010, 0x0fff0ff0, "miaph%c\tacc0, %0-3r, %12-15r"},
1023d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e2c0010, 0x0ffc0ff0, "mia%17'T%17`B%16'T%16`B%c\tacc0, %0-3r, %12-15r"},
1033d8817e4Smiod {ARM_CEXT_XSCALE, 0x0c400000, 0x0ff00fff, "mar%c\tacc0, %12-15r, %16-19r"},
1043d8817e4Smiod {ARM_CEXT_XSCALE, 0x0c500000, 0x0ff00fff, "mra%c\t%12-15r, %16-19r, acc0"},
1053d8817e4Smiod
1063d8817e4Smiod /* Intel Wireless MMX technology instructions. */
1073d8817e4Smiod #define FIRST_IWMMXT_INSN 0x0e130130
1083d8817e4Smiod #define IWMMXT_INSN_COUNT 47
1093d8817e4Smiod {ARM_CEXT_IWMMXT, 0x0e130130, 0x0f3f0fff, "tandc%22-23w%c\t%12-15r"},
1103d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e400010, 0x0ff00f3f, "tbcst%6-7w%c\t%16-19g, %12-15r"},
1113d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e130170, 0x0f3f0ff8, "textrc%22-23w%c\t%12-15r, #%0-2d"},
1123d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e100070, 0x0f300ff0, "textrm%3?su%22-23w%c\t%12-15r, %16-19g, #%0-2d"},
1133d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e600010, 0x0ff00f38, "tinsr%6-7w%c\t%16-19g, %12-15r, #%0-2d"},
1143d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e000110, 0x0ff00fff, "tmcr%c\t%16-19G, %12-15r"},
1153d8817e4Smiod {ARM_CEXT_XSCALE, 0x0c400000, 0x0ff00ff0, "tmcrr%c\t%0-3g, %12-15r, %16-19r"},
1163d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e2c0010, 0x0ffc0e10, "tmia%17?tb%16?tb%c\t%5-8g, %0-3r, %12-15r"},
1173d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e200010, 0x0fff0e10, "tmia%c\t%5-8g, %0-3r, %12-15r"},
1183d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e280010, 0x0fff0e10, "tmiaph%c\t%5-8g, %0-3r, %12-15r"},
1193d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e100030, 0x0f300fff, "tmovmsk%22-23w%c\t%12-15r, %16-19g"},
1203d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e100110, 0x0ff00ff0, "tmrc%c\t%12-15r, %16-19G"},
1213d8817e4Smiod {ARM_CEXT_XSCALE, 0x0c500000, 0x0ff00ff0, "tmrrc%c\t%12-15r, %16-19r, %0-3g"},
1223d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e130150, 0x0f3f0fff, "torc%22-23w%c\t%12-15r"},
1233d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e0001c0, 0x0f300fff, "wacc%22-23w%c\t%12-15g, %16-19g"},
1243d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e000180, 0x0f000ff0, "wadd%20-23w%c\t%12-15g, %16-19g, %0-3g"},
1253d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e000020, 0x0f800ff0, "waligni%c\t%12-15g, %16-19g, %0-3g, #%20-22d"},
1263d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e800020, 0x0fc00ff0, "walignr%20-21d%c\t%12-15g, %16-19g, %0-3g"},
1273d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e200000, 0x0fe00ff0, "wand%20'n%c\t%12-15g, %16-19g, %0-3g"},
1283d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e800000, 0x0fa00ff0, "wavg2%22?hb%20'r%c\t%12-15g, %16-19g, %0-3g"},
1293d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e000060, 0x0f300ff0, "wcmpeq%22-23w%c\t%12-15g, %16-19g, %0-3g"},
1303d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e100060, 0x0f100ff0, "wcmpgt%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"},
1313d8817e4Smiod {ARM_CEXT_XSCALE, 0xfc100100, 0xfe500f00, "wldrw\t%12-15G, %A"},
1323d8817e4Smiod {ARM_CEXT_XSCALE, 0x0c100000, 0x0e100e00, "wldr%L%c\t%12-15g, %l"},
1333d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e400100, 0x0fc00ff0, "wmac%21?su%20'z%c\t%12-15g, %16-19g, %0-3g"},
1343d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e800100, 0x0fd00ff0, "wmadd%21?su%c\t%12-15g, %16-19g, %0-3g"},
1353d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e000160, 0x0f100ff0, "wmax%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"},
1363d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e100160, 0x0f100ff0, "wmin%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"},
1373d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e000100, 0x0fc00ff0, "wmul%21?su%20?ml%c\t%12-15g, %16-19g, %0-3g"},
1383d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e000000, 0x0ff00ff0, "wor%c\t%12-15g, %16-19g, %0-3g"},
1393d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e000080, 0x0f000ff0, "wpack%20-23w%c\t%12-15g, %16-19g, %0-3g"},
1403d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e300040, 0x0f300ff0, "wror%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"},
1413d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e300148, 0x0f300ffc, "wror%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"},
1423d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e000120, 0x0fa00ff0, "wsad%22?hb%20'z%c\t%12-15g, %16-19g, %0-3g"},
1433d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e0001e0, 0x0f000ff0, "wshufh%c\t%12-15g, %16-19g, #%Z"},
1443d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e100040, 0x0f300ff0, "wsll%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"},
1453d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e100148, 0x0f300ffc, "wsll%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"},
1463d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e000040, 0x0f300ff0, "wsra%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"},
1473d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e000148, 0x0f300ffc, "wsra%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"},
1483d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e200040, 0x0f300ff0, "wsrl%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"},
1493d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e200148, 0x0f300ffc, "wsrl%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"},
1503d8817e4Smiod {ARM_CEXT_XSCALE, 0xfc000100, 0xfe500f00, "wstrw\t%12-15G, %A"},
1513d8817e4Smiod {ARM_CEXT_XSCALE, 0x0c000000, 0x0e100e00, "wstr%L%c\t%12-15g, %l"},
1523d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e0001a0, 0x0f000ff0, "wsub%20-23w%c\t%12-15g, %16-19g, %0-3g"},
1533d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e0000c0, 0x0f100fff, "wunpckeh%21?su%22-23w%c\t%12-15g, %16-19g"},
1543d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e0000e0, 0x0f100fff, "wunpckel%21?su%22-23w%c\t%12-15g, %16-19g"},
1553d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e1000c0, 0x0f300ff0, "wunpckih%22-23w%c\t%12-15g, %16-19g, %0-3g"},
1563d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e1000e0, 0x0f300ff0, "wunpckil%22-23w%c\t%12-15g, %16-19g, %0-3g"},
1573d8817e4Smiod {ARM_CEXT_XSCALE, 0x0e100000, 0x0ff00ff0, "wxor%c\t%12-15g, %16-19g, %0-3g"},
1583d8817e4Smiod
1593d8817e4Smiod /* Floating point coprocessor (FPA) instructions */
1603d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e000100, 0x0ff08f10, "adf%c%P%R\t%12-14f, %16-18f, %0-3f"},
1613d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e100100, 0x0ff08f10, "muf%c%P%R\t%12-14f, %16-18f, %0-3f"},
1623d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e200100, 0x0ff08f10, "suf%c%P%R\t%12-14f, %16-18f, %0-3f"},
1633d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e300100, 0x0ff08f10, "rsf%c%P%R\t%12-14f, %16-18f, %0-3f"},
1643d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e400100, 0x0ff08f10, "dvf%c%P%R\t%12-14f, %16-18f, %0-3f"},
1653d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e500100, 0x0ff08f10, "rdf%c%P%R\t%12-14f, %16-18f, %0-3f"},
1663d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e600100, 0x0ff08f10, "pow%c%P%R\t%12-14f, %16-18f, %0-3f"},
1673d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e700100, 0x0ff08f10, "rpw%c%P%R\t%12-14f, %16-18f, %0-3f"},
1683d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e800100, 0x0ff08f10, "rmf%c%P%R\t%12-14f, %16-18f, %0-3f"},
1693d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e900100, 0x0ff08f10, "fml%c%P%R\t%12-14f, %16-18f, %0-3f"},
1703d8817e4Smiod {FPU_FPA_EXT_V1, 0x0ea00100, 0x0ff08f10, "fdv%c%P%R\t%12-14f, %16-18f, %0-3f"},
1713d8817e4Smiod {FPU_FPA_EXT_V1, 0x0eb00100, 0x0ff08f10, "frd%c%P%R\t%12-14f, %16-18f, %0-3f"},
1723d8817e4Smiod {FPU_FPA_EXT_V1, 0x0ec00100, 0x0ff08f10, "pol%c%P%R\t%12-14f, %16-18f, %0-3f"},
1733d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e008100, 0x0ff08f10, "mvf%c%P%R\t%12-14f, %0-3f"},
1743d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e108100, 0x0ff08f10, "mnf%c%P%R\t%12-14f, %0-3f"},
1753d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e208100, 0x0ff08f10, "abs%c%P%R\t%12-14f, %0-3f"},
1763d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e308100, 0x0ff08f10, "rnd%c%P%R\t%12-14f, %0-3f"},
1773d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e408100, 0x0ff08f10, "sqt%c%P%R\t%12-14f, %0-3f"},
1783d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e508100, 0x0ff08f10, "log%c%P%R\t%12-14f, %0-3f"},
1793d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e608100, 0x0ff08f10, "lgn%c%P%R\t%12-14f, %0-3f"},
1803d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e708100, 0x0ff08f10, "exp%c%P%R\t%12-14f, %0-3f"},
1813d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e808100, 0x0ff08f10, "sin%c%P%R\t%12-14f, %0-3f"},
1823d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e908100, 0x0ff08f10, "cos%c%P%R\t%12-14f, %0-3f"},
1833d8817e4Smiod {FPU_FPA_EXT_V1, 0x0ea08100, 0x0ff08f10, "tan%c%P%R\t%12-14f, %0-3f"},
1843d8817e4Smiod {FPU_FPA_EXT_V1, 0x0eb08100, 0x0ff08f10, "asn%c%P%R\t%12-14f, %0-3f"},
1853d8817e4Smiod {FPU_FPA_EXT_V1, 0x0ec08100, 0x0ff08f10, "acs%c%P%R\t%12-14f, %0-3f"},
1863d8817e4Smiod {FPU_FPA_EXT_V1, 0x0ed08100, 0x0ff08f10, "atn%c%P%R\t%12-14f, %0-3f"},
1873d8817e4Smiod {FPU_FPA_EXT_V1, 0x0ee08100, 0x0ff08f10, "urd%c%P%R\t%12-14f, %0-3f"},
1883d8817e4Smiod {FPU_FPA_EXT_V1, 0x0ef08100, 0x0ff08f10, "nrm%c%P%R\t%12-14f, %0-3f"},
1893d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e000110, 0x0ff00f1f, "flt%c%P%R\t%16-18f, %12-15r"},
1903d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e100110, 0x0fff0f98, "fix%c%R\t%12-15r, %0-2f"},
1913d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e200110, 0x0fff0fff, "wfs%c\t%12-15r"},
1923d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e300110, 0x0fff0fff, "rfs%c\t%12-15r"},
1933d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e400110, 0x0fff0fff, "wfc%c\t%12-15r"},
1943d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e500110, 0x0fff0fff, "rfc%c\t%12-15r"},
1953d8817e4Smiod {FPU_FPA_EXT_V1, 0x0e90f110, 0x0ff8fff0, "cmf%c\t%16-18f, %0-3f"},
1963d8817e4Smiod {FPU_FPA_EXT_V1, 0x0eb0f110, 0x0ff8fff0, "cnf%c\t%16-18f, %0-3f"},
1973d8817e4Smiod {FPU_FPA_EXT_V1, 0x0ed0f110, 0x0ff8fff0, "cmfe%c\t%16-18f, %0-3f"},
1983d8817e4Smiod {FPU_FPA_EXT_V1, 0x0ef0f110, 0x0ff8fff0, "cnfe%c\t%16-18f, %0-3f"},
1993d8817e4Smiod {FPU_FPA_EXT_V1, 0x0c000100, 0x0e100f00, "stf%c%Q\t%12-14f, %A"},
2003d8817e4Smiod {FPU_FPA_EXT_V1, 0x0c100100, 0x0e100f00, "ldf%c%Q\t%12-14f, %A"},
2013d8817e4Smiod {FPU_FPA_EXT_V2, 0x0c000200, 0x0e100f00, "sfm%c\t%12-14f, %F, %A"},
2023d8817e4Smiod {FPU_FPA_EXT_V2, 0x0c100200, 0x0e100f00, "lfm%c\t%12-14f, %F, %A"},
2033d8817e4Smiod
2043d8817e4Smiod /* Floating point coprocessor (VFP) instructions */
2053d8817e4Smiod {FPU_VFP_EXT_V1, 0x0eb00bc0, 0x0fff0ff0, "fabsd%c\t%1z, %0z"},
2063d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0eb00ac0, 0x0fbf0fd0, "fabss%c\t%1y, %0y"},
2073d8817e4Smiod {FPU_VFP_EXT_V1, 0x0e300b00, 0x0ff00ff0, "faddd%c\t%1z, %2z, %0z"},
2083d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0e300a00, 0x0fb00f50, "fadds%c\t%1y, %2y, %0y"},
2093d8817e4Smiod {FPU_VFP_EXT_V1, 0x0eb40b40, 0x0fff0f70, "fcmp%7'ed%c\t%1z, %0z"},
2103d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0eb40a40, 0x0fbf0f50, "fcmp%7'es%c\t%1y, %0y"},
2113d8817e4Smiod {FPU_VFP_EXT_V1, 0x0eb50b40, 0x0fff0f70, "fcmp%7'ezd%c\t%1z"},
2123d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0eb50a40, 0x0fbf0f70, "fcmp%7'ezs%c\t%1y"},
2133d8817e4Smiod {FPU_VFP_EXT_V1, 0x0eb00b40, 0x0fff0ff0, "fcpyd%c\t%1z, %0z"},
2143d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0eb00a40, 0x0fbf0fd0, "fcpys%c\t%1y, %0y"},
2153d8817e4Smiod {FPU_VFP_EXT_V1, 0x0eb70ac0, 0x0fff0fd0, "fcvtds%c\t%1z, %0y"},
2163d8817e4Smiod {FPU_VFP_EXT_V1, 0x0eb70bc0, 0x0fbf0ff0, "fcvtsd%c\t%1y, %0z"},
2173d8817e4Smiod {FPU_VFP_EXT_V1, 0x0e800b00, 0x0ff00ff0, "fdivd%c\t%1z, %2z, %0z"},
2183d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0e800a00, 0x0fb00f50, "fdivs%c\t%1y, %2y, %0y"},
2193d8817e4Smiod {FPU_VFP_EXT_V1, 0x0d100b00, 0x0f700f00, "fldd%c\t%1z, %A"},
2203d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0c900b00, 0x0fd00f00, "fldmia%0?xd%c\t%16-19r%21'!, %3z"},
2213d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0d300b00, 0x0ff00f00, "fldmdb%0?xd%c\t%16-19r!, %3z"},
2223d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0d100a00, 0x0f300f00, "flds%c\t%1y, %A"},
2233d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0c900a00, 0x0f900f00, "fldmias%c\t%16-19r%21'!, %3y"},
2243d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0d300a00, 0x0fb00f00, "fldmdbs%c\t%16-19r!, %3y"},
2253d8817e4Smiod {FPU_VFP_EXT_V1, 0x0e000b00, 0x0ff00ff0, "fmacd%c\t%1z, %2z, %0z"},
2263d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0e000a00, 0x0fb00f50, "fmacs%c\t%1y, %2y, %0y"},
2273d8817e4Smiod {FPU_VFP_EXT_V1, 0x0e200b10, 0x0ff00fff, "fmdhr%c\t%2z, %12-15r"},
2283d8817e4Smiod {FPU_VFP_EXT_V1, 0x0e000b10, 0x0ff00fff, "fmdlr%c\t%2z, %12-15r"},
2293d8817e4Smiod {FPU_VFP_EXT_V2, 0x0c400b10, 0x0ff00ff0, "fmdrr%c\t%0z, %12-15r, %16-19r"},
2303d8817e4Smiod {FPU_VFP_EXT_V1, 0x0e300b10, 0x0ff00fff, "fmrdh%c\t%12-15r, %2z"},
2313d8817e4Smiod {FPU_VFP_EXT_V1, 0x0e100b10, 0x0ff00fff, "fmrdl%c\t%12-15r, %2z"},
2323d8817e4Smiod {FPU_VFP_EXT_V1, 0x0c500b10, 0x0ff00ff0, "fmrrd%c\t%12-15r, %16-19r, %0z"},
2333d8817e4Smiod {FPU_VFP_EXT_V2, 0x0c500a10, 0x0ff00fd0, "fmrrs%c\t%12-15r, %16-19r, %4y"},
2343d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0e100a10, 0x0ff00f7f, "fmrs%c\t%12-15r, %2y"},
2353d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0ef1fa10, 0x0fffffff, "fmstat%c"},
2363d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0ef00a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpsid"},
2373d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0ef10a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpscr"},
2383d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0ef80a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpexc"},
2393d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0ef90a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst\t@ Impl def"},
2403d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0efa0a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst2\t@ Impl def"},
2413d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0ef00a10, 0x0ff00fff, "fmrx%c\t%12-15r, <impl def 0x%16-19x>"},
2423d8817e4Smiod {FPU_VFP_EXT_V1, 0x0e100b00, 0x0ff00ff0, "fmscd%c\t%1z, %2z, %0z"},
2433d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0e100a00, 0x0fb00f50, "fmscs%c\t%1y, %2y, %0y"},
2443d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0e000a10, 0x0ff00f7f, "fmsr%c\t%2y, %12-15r"},
2453d8817e4Smiod {FPU_VFP_EXT_V2, 0x0c400a10, 0x0ff00fd0, "fmsrr%c\t%12-15r, %16-19r, %4y"},
2463d8817e4Smiod {FPU_VFP_EXT_V1, 0x0e200b00, 0x0ff00ff0, "fmuld%c\t%1z, %2z, %0z"},
2473d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0e200a00, 0x0fb00f50, "fmuls%c\t%1y, %2y, %0y"},
2483d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0ee00a10, 0x0fff0fff, "fmxr%c\tfpsid, %12-15r"},
2493d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0ee10a10, 0x0fff0fff, "fmxr%c\tfpscr, %12-15r"},
2503d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0ee80a10, 0x0fff0fff, "fmxr%c\tfpexc, %12-15r"},
2513d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0ee90a10, 0x0fff0fff, "fmxr%c\tfpinst, %12-15r\t@ Impl def"},
2523d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0eea0a10, 0x0fff0fff, "fmxr%c\tfpinst2, %12-15r\t@ Impl def"},
2533d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0ee00a10, 0x0ff00fff, "fmxr%c\t<impl def 0x%16-19x>, %12-15r"},
2543d8817e4Smiod {FPU_VFP_EXT_V1, 0x0eb10b40, 0x0fff0ff0, "fnegd%c\t%1z, %0z"},
2553d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0eb10a40, 0x0fbf0fd0, "fnegs%c\t%1y, %0y"},
2563d8817e4Smiod {FPU_VFP_EXT_V1, 0x0e000b40, 0x0ff00ff0, "fnmacd%c\t%1z, %2z, %0z"},
2573d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0e000a40, 0x0fb00f50, "fnmacs%c\t%1y, %2y, %0y"},
2583d8817e4Smiod {FPU_VFP_EXT_V1, 0x0e100b40, 0x0ff00ff0, "fnmscd%c\t%1z, %2z, %0z"},
2593d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0e100a40, 0x0fb00f50, "fnmscs%c\t%1y, %2y, %0y"},
2603d8817e4Smiod {FPU_VFP_EXT_V1, 0x0e200b40, 0x0ff00ff0, "fnmuld%c\t%1z, %2z, %0z"},
2613d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0e200a40, 0x0fb00f50, "fnmuls%c\t%1y, %2y, %0y"},
2623d8817e4Smiod {FPU_VFP_EXT_V1, 0x0eb80bc0, 0x0fff0fd0, "fsitod%c\t%1z, %0y"},
2633d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0eb80ac0, 0x0fbf0fd0, "fsitos%c\t%1y, %0y"},
2643d8817e4Smiod {FPU_VFP_EXT_V1, 0x0eb10bc0, 0x0fff0ff0, "fsqrtd%c\t%1z, %0z"},
2653d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0eb10ac0, 0x0fbf0fd0, "fsqrts%c\t%1y, %0y"},
2663d8817e4Smiod {FPU_VFP_EXT_V1, 0x0d000b00, 0x0f700f00, "fstd%c\t%1z, %A"},
2673d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0c800b00, 0x0fd00f00, "fstmia%0?xd%c\t%16-19r%21'!, %3z"},
2683d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0d200b00, 0x0ff00f00, "fstmdb%0?xd%c\t%16-19r!, %3z"},
2693d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0d000a00, 0x0f300f00, "fsts%c\t%1y, %A"},
2703d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0c800a00, 0x0f900f00, "fstmias%c\t%16-19r%21'!, %3y"},
2713d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0d200a00, 0x0fb00f00, "fstmdbs%c\t%16-19r!, %3y"},
2723d8817e4Smiod {FPU_VFP_EXT_V1, 0x0e300b40, 0x0ff00ff0, "fsubd%c\t%1z, %2z, %0z"},
2733d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0e300a40, 0x0fb00f50, "fsubs%c\t%1y, %2y, %0y"},
2743d8817e4Smiod {FPU_VFP_EXT_V1, 0x0ebc0b40, 0x0fbe0f70, "fto%16?sui%7'zd%c\t%1y, %0z"},
2753d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0ebc0a40, 0x0fbe0f50, "fto%16?sui%7'zs%c\t%1y, %0y"},
2763d8817e4Smiod {FPU_VFP_EXT_V1, 0x0eb80b40, 0x0fff0fd0, "fuitod%c\t%1z, %0y"},
2773d8817e4Smiod {FPU_VFP_EXT_V1xD, 0x0eb80a40, 0x0fbf0fd0, "fuitos%c\t%1y, %0y"},
2783d8817e4Smiod
2793d8817e4Smiod /* Cirrus coprocessor instructions. */
2803d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0d100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
2813d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0c100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
2823d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0d500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
2833d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0c500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
2843d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0d100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
2853d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0c100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
2863d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0d500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"},
2873d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0c500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"},
2883d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0d000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"},
2893d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0c000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"},
2903d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0d400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"},
2913d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0c400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"},
2923d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0d000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"},
2933d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0c000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"},
2943d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0d400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"},
2953d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0c400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"},
2963d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e000450, 0x0ff00ff0, "cfmvsr%c\tmvf%16-19d, %12-15r"},
2973d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100450, 0x0ff00ff0, "cfmvrs%c\t%12-15r, mvf%16-19d"},
2983d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e000410, 0x0ff00ff0, "cfmvdlr%c\tmvd%16-19d, %12-15r"},
2993d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100410, 0x0ff00ff0, "cfmvrdl%c\t%12-15r, mvd%16-19d"},
3003d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e000430, 0x0ff00ff0, "cfmvdhr%c\tmvd%16-19d, %12-15r"},
3013d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100430, 0x0ff00fff, "cfmvrdh%c\t%12-15r, mvd%16-19d"},
3023d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e000510, 0x0ff00fff, "cfmv64lr%c\tmvdx%16-19d, %12-15r"},
3033d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100510, 0x0ff00fff, "cfmvr64l%c\t%12-15r, mvdx%16-19d"},
3043d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e000530, 0x0ff00fff, "cfmv64hr%c\tmvdx%16-19d, %12-15r"},
3053d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100530, 0x0ff00fff, "cfmvr64h%c\t%12-15r, mvdx%16-19d"},
3063d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e200440, 0x0ff00fff, "cfmval32%c\tmvax%12-15d, mvfx%16-19d"},
3073d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100440, 0x0ff00fff, "cfmv32al%c\tmvfx%12-15d, mvax%16-19d"},
3083d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e200460, 0x0ff00fff, "cfmvam32%c\tmvax%12-15d, mvfx%16-19d"},
3093d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100460, 0x0ff00fff, "cfmv32am%c\tmvfx%12-15d, mvax%16-19d"},
3103d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e200480, 0x0ff00fff, "cfmvah32%c\tmvax%12-15d, mvfx%16-19d"},
3113d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100480, 0x0ff00fff, "cfmv32ah%c\tmvfx%12-15d, mvax%16-19d"},
3123d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e2004a0, 0x0ff00fff, "cfmva32%c\tmvax%12-15d, mvfx%16-19d"},
3133d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e1004a0, 0x0ff00fff, "cfmv32a%c\tmvfx%12-15d, mvax%16-19d"},
3143d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e2004c0, 0x0ff00fff, "cfmva64%c\tmvax%12-15d, mvdx%16-19d"},
3153d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e1004c0, 0x0ff00fff, "cfmv64a%c\tmvdx%12-15d, mvax%16-19d"},
3163d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e2004e0, 0x0fff0fff, "cfmvsc32%c\tdspsc, mvdx%12-15d"},
3173d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e1004e0, 0x0fff0fff, "cfmv32sc%c\tmvdx%12-15d, dspsc"},
3183d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e000400, 0x0ff00fff, "cfcpys%c\tmvf%12-15d, mvf%16-19d"},
3193d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e000420, 0x0ff00fff, "cfcpyd%c\tmvd%12-15d, mvd%16-19d"},
3203d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e000460, 0x0ff00fff, "cfcvtsd%c\tmvd%12-15d, mvf%16-19d"},
3213d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e000440, 0x0ff00fff, "cfcvtds%c\tmvf%12-15d, mvd%16-19d"},
3223d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e000480, 0x0ff00fff, "cfcvt32s%c\tmvf%12-15d, mvfx%16-19d"},
3233d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e0004a0, 0x0ff00fff, "cfcvt32d%c\tmvd%12-15d, mvfx%16-19d"},
3243d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e0004c0, 0x0ff00fff, "cfcvt64s%c\tmvf%12-15d, mvdx%16-19d"},
3253d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e0004e0, 0x0ff00fff, "cfcvt64d%c\tmvd%12-15d, mvdx%16-19d"},
3263d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100580, 0x0ff00fff, "cfcvts32%c\tmvfx%12-15d, mvf%16-19d"},
3273d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e1005a0, 0x0ff00fff, "cfcvtd32%c\tmvfx%12-15d, mvd%16-19d"},
3283d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e1005c0, 0x0ff00fff, "cftruncs32%c\tmvfx%12-15d, mvf%16-19d"},
3293d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e1005e0, 0x0ff00fff, "cftruncd32%c\tmvfx%12-15d, mvd%16-19d"},
3303d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e000550, 0x0ff00ff0, "cfrshl32%c\tmvfx%16-19d, mvfx%0-3d, %12-15r"},
3313d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e000570, 0x0ff00ff0, "cfrshl64%c\tmvdx%16-19d, mvdx%0-3d, %12-15r"},
3323d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e000500, 0x0ff00f10, "cfsh32%c\tmvfx%12-15d, mvfx%16-19d, #%I"},
3333d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e200500, 0x0ff00f10, "cfsh64%c\tmvdx%12-15d, mvdx%16-19d, #%I"},
3343d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100490, 0x0ff00ff0, "cfcmps%c\t%12-15r, mvf%16-19d, mvf%0-3d"},
3353d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e1004b0, 0x0ff00ff0, "cfcmpd%c\t%12-15r, mvd%16-19d, mvd%0-3d"},
3363d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100590, 0x0ff00ff0, "cfcmp32%c\t%12-15r, mvfx%16-19d, mvfx%0-3d"},
3373d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e1005b0, 0x0ff00ff0, "cfcmp64%c\t%12-15r, mvdx%16-19d, mvdx%0-3d"},
3383d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e300400, 0x0ff00fff, "cfabss%c\tmvf%12-15d, mvf%16-19d"},
3393d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e300420, 0x0ff00fff, "cfabsd%c\tmvd%12-15d, mvd%16-19d"},
3403d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e300440, 0x0ff00fff, "cfnegs%c\tmvf%12-15d, mvf%16-19d"},
3413d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e300460, 0x0ff00fff, "cfnegd%c\tmvd%12-15d, mvd%16-19d"},
3423d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e300480, 0x0ff00ff0, "cfadds%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
3433d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e3004a0, 0x0ff00ff0, "cfaddd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
3443d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e3004c0, 0x0ff00ff0, "cfsubs%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
3453d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e3004e0, 0x0ff00ff0, "cfsubd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
3463d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100400, 0x0ff00ff0, "cfmuls%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
3473d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100420, 0x0ff00ff0, "cfmuld%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
3483d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e300500, 0x0ff00fff, "cfabs32%c\tmvfx%12-15d, mvfx%16-19d"},
3493d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e300520, 0x0ff00fff, "cfabs64%c\tmvdx%12-15d, mvdx%16-19d"},
3503d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e300540, 0x0ff00fff, "cfneg32%c\tmvfx%12-15d, mvfx%16-19d"},
3513d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e300560, 0x0ff00fff, "cfneg64%c\tmvdx%12-15d, mvdx%16-19d"},
3523d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e300580, 0x0ff00ff0, "cfadd32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
3533d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e3005a0, 0x0ff00ff0, "cfadd64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
3543d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e3005c0, 0x0ff00ff0, "cfsub32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
3553d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e3005e0, 0x0ff00ff0, "cfsub64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
3563d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100500, 0x0ff00ff0, "cfmul32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
3573d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100520, 0x0ff00ff0, "cfmul64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
3583d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100540, 0x0ff00ff0, "cfmac32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
3593d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100560, 0x0ff00ff0, "cfmsc32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
3603d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e000600, 0x0ff00f10, "cfmadd32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
3613d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e100600, 0x0ff00f10, "cfmsub32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
3623d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e200600, 0x0ff00f10, "cfmadda32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"},
3633d8817e4Smiod {ARM_CEXT_MAVERICK, 0x0e300600, 0x0ff00f10, "cfmsuba32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"},
3643d8817e4Smiod
3653d8817e4Smiod /* Generic coprocessor instructions */
3663d8817e4Smiod {ARM_EXT_V2, 0x0c400000, 0x0ff00000, "mcrr%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
3673d8817e4Smiod {ARM_EXT_V2, 0x0c500000, 0x0ff00000, "mrrc%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
3683d8817e4Smiod {ARM_EXT_V2, 0x0e000000, 0x0f000010, "cdp%c\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"},
3693d8817e4Smiod {ARM_EXT_V2, 0x0e100010, 0x0f100010, "mrc%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
3703d8817e4Smiod {ARM_EXT_V2, 0x0e000010, 0x0f100010, "mcr%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
3713d8817e4Smiod {ARM_EXT_V2, 0x0c000000, 0x0e100000, "stc%c%22'l\t%8-11d, cr%12-15d, %A"},
3723d8817e4Smiod {ARM_EXT_V2, 0x0c100000, 0x0e100000, "ldc%c%22'l\t%8-11d, cr%12-15d, %A"},
3733d8817e4Smiod
3743d8817e4Smiod /* V6 coprocessor instructions */
3753d8817e4Smiod {ARM_EXT_V6, 0xfc500000, 0xfff00000, "mrrc2\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
3763d8817e4Smiod {ARM_EXT_V6, 0xfc400000, 0xfff00000, "mcrr2\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
3773d8817e4Smiod
3783d8817e4Smiod /* V5 coprocessor instructions */
3793d8817e4Smiod {ARM_EXT_V5, 0xfc100000, 0xfe100000, "ldc2%22'l\t%8-11d, cr%12-15d, %A"},
3803d8817e4Smiod {ARM_EXT_V5, 0xfc000000, 0xfe100000, "stc2%22'l\t%8-11d, cr%12-15d, %A"},
3813d8817e4Smiod {ARM_EXT_V5, 0xfe000000, 0xff000010, "cdp2\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"},
3823d8817e4Smiod {ARM_EXT_V5, 0xfe000010, 0xff100010, "mcr2\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
3833d8817e4Smiod {ARM_EXT_V5, 0xfe100010, 0xff100010, "mrc2\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
3843d8817e4Smiod {0, 0, 0, 0}
3853d8817e4Smiod };
3863d8817e4Smiod
3873d8817e4Smiod /* Opcode tables: ARM, 16-bit Thumb, 32-bit Thumb. All three are partially
3883d8817e4Smiod ordered: they must be searched linearly from the top to obtain a correct
3893d8817e4Smiod match. */
3903d8817e4Smiod
3913d8817e4Smiod /* print_insn_arm recognizes the following format control codes:
3923d8817e4Smiod
3933d8817e4Smiod %% %
3943d8817e4Smiod
3953d8817e4Smiod %a print address for ldr/str instruction
3963d8817e4Smiod %s print address for ldr/str halfword/signextend instruction
3973d8817e4Smiod %b print branch destination
3983d8817e4Smiod %c print condition code (always bits 28-31)
3993d8817e4Smiod %m print register mask for ldm/stm instruction
4003d8817e4Smiod %o print operand2 (immediate or register + shift)
4013d8817e4Smiod %p print 'p' iff bits 12-15 are 15
4023d8817e4Smiod %t print 't' iff bit 21 set and bit 24 clear
4033d8817e4Smiod %B print arm BLX(1) destination
4043d8817e4Smiod %C print the PSR sub type.
4053d8817e4Smiod %U print barrier type.
4063d8817e4Smiod %P print address for pli instruction.
4073d8817e4Smiod
4083d8817e4Smiod %<bitfield>r print as an ARM register
4093d8817e4Smiod %<bitfield>d print the bitfield in decimal
4103d8817e4Smiod %<bitfield>W print the bitfield plus one in decimal
4113d8817e4Smiod %<bitfield>x print the bitfield in hex
4123d8817e4Smiod %<bitfield>X print the bitfield as 1 hex digit without leading "0x"
4133d8817e4Smiod
4143d8817e4Smiod %<bitnum>'c print specified char iff bit is one
4153d8817e4Smiod %<bitnum>`c print specified char iff bit is zero
4163d8817e4Smiod %<bitnum>?ab print a if bit is one else print b
4173d8817e4Smiod
4183d8817e4Smiod %e print arm SMI operand (bits 0..7,8..19).
4193d8817e4Smiod %E print the LSB and WIDTH fields of a BFI or BFC instruction.
4203d8817e4Smiod %V print the 16-bit immediate field of a MOVT or MOVW instruction. */
4213d8817e4Smiod
4223d8817e4Smiod static const struct opcode32 arm_opcodes[] =
4233d8817e4Smiod {
4243d8817e4Smiod /* ARM instructions. */
4253d8817e4Smiod {ARM_EXT_V1, 0xe1a00000, 0xffffffff, "nop\t\t\t(mov r0,r0)"},
4263d8817e4Smiod {ARM_EXT_V4T | ARM_EXT_V5, 0x012FFF10, 0x0ffffff0, "bx%c\t%0-3r"},
4273d8817e4Smiod {ARM_EXT_V2, 0x00000090, 0x0fe000f0, "mul%c%20's\t%16-19r, %0-3r, %8-11r"},
4283d8817e4Smiod {ARM_EXT_V2, 0x00200090, 0x0fe000f0, "mla%c%20's\t%16-19r, %0-3r, %8-11r, %12-15r"},
4293d8817e4Smiod {ARM_EXT_V2S, 0x01000090, 0x0fb00ff0, "swp%c%22'b\t%12-15r, %0-3r, [%16-19r]"},
4303d8817e4Smiod {ARM_EXT_V3M, 0x00800090, 0x0fa000f0, "%22?sumull%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"},
4313d8817e4Smiod {ARM_EXT_V3M, 0x00a00090, 0x0fa000f0, "%22?sumlal%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"},
4323d8817e4Smiod
4333d8817e4Smiod /* V7 instructions. */
4343d8817e4Smiod {ARM_EXT_V7, 0xf450f000, 0xfd70f000, "pli\t%P"},
4353d8817e4Smiod {ARM_EXT_V7, 0x0320f0f0, 0x0ffffff0, "dbg%c\t#%0-3d"},
4363d8817e4Smiod {ARM_EXT_V7, 0xf57ff050, 0xfffffff0, "dmb\t%U"},
4373d8817e4Smiod {ARM_EXT_V7, 0xf57ff040, 0xfffffff0, "dsb\t%U"},
4383d8817e4Smiod {ARM_EXT_V7, 0xf57ff060, 0xfffffff0, "isb\t%U"},
4393d8817e4Smiod
4403d8817e4Smiod /* ARM V6T2 instructions. */
4413d8817e4Smiod {ARM_EXT_V6T2, 0x07c0001f, 0x0fe0007f, "bfc%c\t%12-15r, %E"},
4423d8817e4Smiod {ARM_EXT_V6T2, 0x07c00010, 0x0fe00070, "bfi%c\t%12-15r, %0-3r, %E"},
4433d8817e4Smiod {ARM_EXT_V6T2, 0x00600090, 0x0ff000f0, "mls%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
4443d8817e4Smiod {ARM_EXT_V6T2, 0x006000b0, 0x0f7000f0, "str%cht\t%12-15r, %s"},
4453d8817e4Smiod {ARM_EXT_V6T2, 0x00300090, 0x0f300090, "ldr%c%6's%5?hbt\t%12-15r, %s"},
4463d8817e4Smiod {ARM_EXT_V6T2, 0x03000000, 0x0ff00000, "movw%c\t%12-15r, %V"},
4473d8817e4Smiod {ARM_EXT_V6T2, 0x03400000, 0x0ff00000, "movt%c\t%12-15r, %V"},
4483d8817e4Smiod {ARM_EXT_V6T2, 0x03ff0f30, 0x0fff0ff0, "rbit%c\t%12-15r, %0-3r"},
4493d8817e4Smiod {ARM_EXT_V6T2, 0x07a00050, 0x0fa00070, "%22?usbfx%c\t%12-15r, %0-3r, #%7-11d, #%16-20W"},
4503d8817e4Smiod
4513d8817e4Smiod /* ARM V6Z instructions. */
4523d8817e4Smiod {ARM_EXT_V6Z, 0x01600070, 0x0ff000f0, "smc%c\t%e"},
4533d8817e4Smiod
4543d8817e4Smiod /* ARM V6K instructions. */
4553d8817e4Smiod {ARM_EXT_V6K, 0xf57ff01f, 0xffffffff, "clrex"},
4563d8817e4Smiod {ARM_EXT_V6K, 0x01d00f9f, 0x0ff00fff, "ldrexb%c\t%12-15r, [%16-19r]"},
4573d8817e4Smiod {ARM_EXT_V6K, 0x01b00f9f, 0x0ff00fff, "ldrexd%c\t%12-15r, [%16-19r]"},
4583d8817e4Smiod {ARM_EXT_V6K, 0x01f00f9f, 0x0ff00fff, "ldrexh%c\t%12-15r, [%16-19r]"},
4593d8817e4Smiod {ARM_EXT_V6K, 0x01c00f90, 0x0ff00ff0, "strexb%c\t%12-15r, %0-3r, [%16-19r]"},
4603d8817e4Smiod {ARM_EXT_V6K, 0x01a00f90, 0x0ff00ff0, "strexd%c\t%12-15r, %0-3r, [%16-19r]"},
4613d8817e4Smiod {ARM_EXT_V6K, 0x01e00f90, 0x0ff00ff0, "strexh%c\t%12-15r, %0-3r, [%16-19r]"},
4623d8817e4Smiod
4633d8817e4Smiod /* ARM V6K NOP hints. */
4643d8817e4Smiod {ARM_EXT_V6K, 0x0320f001, 0x0fffffff, "yield%c"},
4653d8817e4Smiod {ARM_EXT_V6K, 0x0320f002, 0x0fffffff, "wfe%c"},
4663d8817e4Smiod {ARM_EXT_V6K, 0x0320f003, 0x0fffffff, "wfi%c"},
4673d8817e4Smiod {ARM_EXT_V6K, 0x0320f004, 0x0fffffff, "sev%c"},
4683d8817e4Smiod {ARM_EXT_V6K, 0x0320f000, 0x0fffff00, "nop%c\t{%0-7d}"},
4693d8817e4Smiod
4703d8817e4Smiod /* ARM V6 instructions. */
4713d8817e4Smiod {ARM_EXT_V6, 0xf1080000, 0xfffdfe3f, "cpsie\t%8'a%7'i%6'f"},
4723d8817e4Smiod {ARM_EXT_V6, 0xf1080000, 0xfffdfe20, "cpsie\t%8'a%7'i%6'f,#%0-4d"},
4733d8817e4Smiod {ARM_EXT_V6, 0xf10C0000, 0xfffdfe3f, "cpsid\t%8'a%7'i%6'f"},
4743d8817e4Smiod {ARM_EXT_V6, 0xf10C0000, 0xfffdfe20, "cpsid\t%8'a%7'i%6'f,#%0-4d"},
4753d8817e4Smiod {ARM_EXT_V6, 0xf1000000, 0xfff1fe20, "cps\t#%0-4d"},
4763d8817e4Smiod {ARM_EXT_V6, 0x06800010, 0x0ff00ff0, "pkhbt%c\t%12-15r, %16-19r, %0-3r"},
4773d8817e4Smiod {ARM_EXT_V6, 0x06800010, 0x0ff00070, "pkhbt%c\t%12-15r, %16-19r, %0-3r, LSL #%7-11d"},
4783d8817e4Smiod {ARM_EXT_V6, 0x06800050, 0x0ff00ff0, "pkhtb%c\t%12-15r, %16-19r, %0-3r, ASR #32"},
4793d8817e4Smiod {ARM_EXT_V6, 0x06800050, 0x0ff00070, "pkhtb%c\t%12-15r, %16-19r, %0-3r, ASR #%7-11d"},
4803d8817e4Smiod {ARM_EXT_V6, 0x01900f9f, 0x0ff00fff, "ldrex%c\tr%12-15d, [%16-19r]"},
4813d8817e4Smiod {ARM_EXT_V6, 0x06200f10, 0x0ff00ff0, "qadd16%c\t%12-15r, %16-19r, %0-3r"},
4823d8817e4Smiod {ARM_EXT_V6, 0x06200f90, 0x0ff00ff0, "qadd8%c\t%12-15r, %16-19r, %0-3r"},
4833d8817e4Smiod {ARM_EXT_V6, 0x06200f30, 0x0ff00ff0, "qaddsubx%c\t%12-15r, %16-19r, %0-3r"},
4843d8817e4Smiod {ARM_EXT_V6, 0x06200f70, 0x0ff00ff0, "qsub16%c\t%12-15r, %16-19r, %0-3r"},
4853d8817e4Smiod {ARM_EXT_V6, 0x06200ff0, 0x0ff00ff0, "qsub8%c\t%12-15r, %16-19r, %0-3r"},
4863d8817e4Smiod {ARM_EXT_V6, 0x06200f50, 0x0ff00ff0, "qsubaddx%c\t%12-15r, %16-19r, %0-3r"},
4873d8817e4Smiod {ARM_EXT_V6, 0x06100f10, 0x0ff00ff0, "sadd16%c\t%12-15r, %16-19r, %0-3r"},
4883d8817e4Smiod {ARM_EXT_V6, 0x06100f90, 0x0ff00ff0, "sadd8%c\t%12-15r, %16-19r, %0-3r"},
4893d8817e4Smiod {ARM_EXT_V6, 0x06100f30, 0x0ff00ff0, "saddaddx%c\t%12-15r, %16-19r, %0-3r"},
4903d8817e4Smiod {ARM_EXT_V6, 0x06300f10, 0x0ff00ff0, "shadd16%c\t%12-15r, %16-19r, %0-3r"},
4913d8817e4Smiod {ARM_EXT_V6, 0x06300f90, 0x0ff00ff0, "shadd8%c\t%12-15r, %16-19r, %0-3r"},
4923d8817e4Smiod {ARM_EXT_V6, 0x06300f30, 0x0ff00ff0, "shaddsubx%c\t%12-15r, %16-19r, %0-3r"},
4933d8817e4Smiod {ARM_EXT_V6, 0x06300f70, 0x0ff00ff0, "shsub16%c\t%12-15r, %16-19r, %0-3r"},
4943d8817e4Smiod {ARM_EXT_V6, 0x06300ff0, 0x0ff00ff0, "shsub8%c\t%12-15r, %16-19r, %0-3r"},
4953d8817e4Smiod {ARM_EXT_V6, 0x06300f50, 0x0ff00ff0, "shsubaddx%c\t%12-15r, %16-19r, %0-3r"},
4963d8817e4Smiod {ARM_EXT_V6, 0x06100f70, 0x0ff00ff0, "ssub16%c\t%12-15r, %16-19r, %0-3r"},
4973d8817e4Smiod {ARM_EXT_V6, 0x06100ff0, 0x0ff00ff0, "ssub8%c\t%12-15r, %16-19r, %0-3r"},
4983d8817e4Smiod {ARM_EXT_V6, 0x06100f50, 0x0ff00ff0, "ssubaddx%c\t%12-15r, %16-19r, %0-3r"},
4993d8817e4Smiod {ARM_EXT_V6, 0x06500f10, 0x0ff00ff0, "uadd16%c\t%12-15r, %16-19r, %0-3r"},
5003d8817e4Smiod {ARM_EXT_V6, 0x06500f90, 0x0ff00ff0, "uadd8%c\t%12-15r, %16-19r, %0-3r"},
5013d8817e4Smiod {ARM_EXT_V6, 0x06500f30, 0x0ff00ff0, "uaddsubx%c\t%12-15r, %16-19r, %0-3r"},
5023d8817e4Smiod {ARM_EXT_V6, 0x06700f10, 0x0ff00ff0, "uhadd16%c\t%12-15r, %16-19r, %0-3r"},
5033d8817e4Smiod {ARM_EXT_V6, 0x06700f90, 0x0ff00ff0, "uhadd8%c\t%12-15r, %16-19r, %0-3r"},
5043d8817e4Smiod {ARM_EXT_V6, 0x06700f30, 0x0ff00ff0, "uhaddsubx%c\t%12-15r, %16-19r, %0-3r"},
5053d8817e4Smiod {ARM_EXT_V6, 0x06700f70, 0x0ff00ff0, "uhsub16%c\t%12-15r, %16-19r, %0-3r"},
5063d8817e4Smiod {ARM_EXT_V6, 0x06700ff0, 0x0ff00ff0, "uhsub8%c\t%12-15r, %16-19r, %0-3r"},
5073d8817e4Smiod {ARM_EXT_V6, 0x06700f50, 0x0ff00ff0, "uhsubaddx%c\t%12-15r, %16-19r, %0-3r"},
5083d8817e4Smiod {ARM_EXT_V6, 0x06600f10, 0x0ff00ff0, "uqadd16%c\t%12-15r, %16-19r, %0-3r"},
5093d8817e4Smiod {ARM_EXT_V6, 0x06600f90, 0x0ff00ff0, "uqadd8%c\t%12-15r, %16-19r, %0-3r"},
5103d8817e4Smiod {ARM_EXT_V6, 0x06600f30, 0x0ff00ff0, "uqaddsubx%c\t%12-15r, %16-19r, %0-3r"},
5113d8817e4Smiod {ARM_EXT_V6, 0x06600f70, 0x0ff00ff0, "uqsub16%c\t%12-15r, %16-19r, %0-3r"},
5123d8817e4Smiod {ARM_EXT_V6, 0x06600ff0, 0x0ff00ff0, "uqsub8%c\t%12-15r, %16-19r, %0-3r"},
5133d8817e4Smiod {ARM_EXT_V6, 0x06600f50, 0x0ff00ff0, "uqsubaddx%c\t%12-15r, %16-19r, %0-3r"},
5143d8817e4Smiod {ARM_EXT_V6, 0x06500f70, 0x0ff00ff0, "usub16%c\t%12-15r, %16-19r, %0-3r"},
5153d8817e4Smiod {ARM_EXT_V6, 0x06500ff0, 0x0ff00ff0, "usub8%c\t%12-15r, %16-19r, %0-3r"},
5163d8817e4Smiod {ARM_EXT_V6, 0x06500f50, 0x0ff00ff0, "usubaddx%c\t%12-15r, %16-19r, %0-3r"},
5173d8817e4Smiod {ARM_EXT_V6, 0x06bf0f30, 0x0fff0ff0, "rev%c\t\%12-15r, %0-3r"},
5183d8817e4Smiod {ARM_EXT_V6, 0x06bf0fb0, 0x0fff0ff0, "rev16%c\t\%12-15r, %0-3r"},
5193d8817e4Smiod {ARM_EXT_V6, 0x06ff0fb0, 0x0fff0ff0, "revsh%c\t\%12-15r, %0-3r"},
5203d8817e4Smiod {ARM_EXT_V6, 0xf8100a00, 0xfe50ffff, "rfe%23?id%24?ba\t\%16-19r%21'!"},
5213d8817e4Smiod {ARM_EXT_V6, 0x06bf0070, 0x0fff0ff0, "sxth%c %12-15r,%0-3r"},
5223d8817e4Smiod {ARM_EXT_V6, 0x06bf0470, 0x0fff0ff0, "sxth%c %12-15r,%0-3r, ROR #8"},
5233d8817e4Smiod {ARM_EXT_V6, 0x06bf0870, 0x0fff0ff0, "sxth%c %12-15r,%0-3r, ROR #16"},
5243d8817e4Smiod {ARM_EXT_V6, 0x06bf0c70, 0x0fff0ff0, "sxth%c %12-15r,%0-3r, ROR #24"},
5253d8817e4Smiod {ARM_EXT_V6, 0x068f0070, 0x0fff0ff0, "sxtb16%c %12-15r,%0-3r"},
5263d8817e4Smiod {ARM_EXT_V6, 0x068f0470, 0x0fff0ff0, "sxtb16%c %12-15r,%0-3r, ROR #8"},
5273d8817e4Smiod {ARM_EXT_V6, 0x068f0870, 0x0fff0ff0, "sxtb16%c %12-15r,%0-3r, ROR #16"},
5283d8817e4Smiod {ARM_EXT_V6, 0x068f0c70, 0x0fff0ff0, "sxtb16%c %12-15r,%0-3r, ROR #24"},
5293d8817e4Smiod {ARM_EXT_V6, 0x06af0070, 0x0fff0ff0, "sxtb%c %12-15r,%0-3r"},
5303d8817e4Smiod {ARM_EXT_V6, 0x06af0470, 0x0fff0ff0, "sxtb%c %12-15r,%0-3r, ROR #8"},
5313d8817e4Smiod {ARM_EXT_V6, 0x06af0870, 0x0fff0ff0, "sxtb%c %12-15r,%0-3r, ROR #16"},
5323d8817e4Smiod {ARM_EXT_V6, 0x06af0c70, 0x0fff0ff0, "sxtb%c %12-15r,%0-3r, ROR #24"},
5333d8817e4Smiod {ARM_EXT_V6, 0x06ff0070, 0x0fff0ff0, "uxth%c %12-15r,%0-3r"},
5343d8817e4Smiod {ARM_EXT_V6, 0x06ff0470, 0x0fff0ff0, "uxth%c %12-15r,%0-3r, ROR #8"},
5353d8817e4Smiod {ARM_EXT_V6, 0x06ff0870, 0x0fff0ff0, "uxth%c %12-15r,%0-3r, ROR #16"},
5363d8817e4Smiod {ARM_EXT_V6, 0x06ff0c70, 0x0fff0ff0, "uxth%c %12-15r,%0-3r, ROR #24"},
5373d8817e4Smiod {ARM_EXT_V6, 0x06cf0070, 0x0fff0ff0, "uxtb16%c %12-15r,%0-3r"},
5383d8817e4Smiod {ARM_EXT_V6, 0x06cf0470, 0x0fff0ff0, "uxtb16%c %12-15r,%0-3r, ROR #8"},
5393d8817e4Smiod {ARM_EXT_V6, 0x06cf0870, 0x0fff0ff0, "uxtb16%c %12-15r,%0-3r, ROR #16"},
5403d8817e4Smiod {ARM_EXT_V6, 0x06cf0c70, 0x0fff0ff0, "uxtb16%c %12-15r,%0-3r, ROR #24"},
5413d8817e4Smiod {ARM_EXT_V6, 0x06ef0070, 0x0fff0ff0, "uxtb%c %12-15r,%0-3r"},
5423d8817e4Smiod {ARM_EXT_V6, 0x06ef0470, 0x0fff0ff0, "uxtb%c %12-15r,%0-3r, ROR #8"},
5433d8817e4Smiod {ARM_EXT_V6, 0x06ef0870, 0x0fff0ff0, "uxtb%c %12-15r,%0-3r, ROR #16"},
5443d8817e4Smiod {ARM_EXT_V6, 0x06ef0c70, 0x0fff0ff0, "uxtb%c %12-15r,%0-3r, ROR #24"},
5453d8817e4Smiod {ARM_EXT_V6, 0x06b00070, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r"},
5463d8817e4Smiod {ARM_EXT_V6, 0x06b00470, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
5473d8817e4Smiod {ARM_EXT_V6, 0x06b00870, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
5483d8817e4Smiod {ARM_EXT_V6, 0x06b00c70, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
5493d8817e4Smiod {ARM_EXT_V6, 0x06800070, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r"},
5503d8817e4Smiod {ARM_EXT_V6, 0x06800470, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
5513d8817e4Smiod {ARM_EXT_V6, 0x06800870, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
5523d8817e4Smiod {ARM_EXT_V6, 0x06800c70, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
5533d8817e4Smiod {ARM_EXT_V6, 0x06a00070, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r"},
5543d8817e4Smiod {ARM_EXT_V6, 0x06a00470, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
5553d8817e4Smiod {ARM_EXT_V6, 0x06a00870, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
5563d8817e4Smiod {ARM_EXT_V6, 0x06a00c70, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
5573d8817e4Smiod {ARM_EXT_V6, 0x06f00070, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r"},
5583d8817e4Smiod {ARM_EXT_V6, 0x06f00470, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
5593d8817e4Smiod {ARM_EXT_V6, 0x06f00870, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
5603d8817e4Smiod {ARM_EXT_V6, 0x06f00c70, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
5613d8817e4Smiod {ARM_EXT_V6, 0x06c00070, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r"},
5623d8817e4Smiod {ARM_EXT_V6, 0x06c00470, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
5633d8817e4Smiod {ARM_EXT_V6, 0x06c00870, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
5643d8817e4Smiod {ARM_EXT_V6, 0x06c00c70, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
5653d8817e4Smiod {ARM_EXT_V6, 0x06e00070, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r"},
5663d8817e4Smiod {ARM_EXT_V6, 0x06e00470, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
5673d8817e4Smiod {ARM_EXT_V6, 0x06e00870, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
5683d8817e4Smiod {ARM_EXT_V6, 0x06e00c70, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
5693d8817e4Smiod {ARM_EXT_V6, 0x06800fb0, 0x0ff00ff0, "sel%c\t%12-15r, %16-19r, %0-3r"},
5703d8817e4Smiod {ARM_EXT_V6, 0xf1010000, 0xfffffc00, "setend\t%9?ble"},
5713d8817e4Smiod {ARM_EXT_V6, 0x0700f010, 0x0ff0f0d0, "smuad%5'x%c\t%16-19r, %0-3r, %8-11r"},
5723d8817e4Smiod {ARM_EXT_V6, 0x0700f050, 0x0ff0f0d0, "smusd%5'x%c\t%16-19r, %0-3r, %8-11r"},
5733d8817e4Smiod {ARM_EXT_V6, 0x07000010, 0x0ff000d0, "smlad%5'x%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
5743d8817e4Smiod {ARM_EXT_V6, 0x07400010, 0x0ff000d0, "smlald%5'x%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
5753d8817e4Smiod {ARM_EXT_V6, 0x07000050, 0x0ff000d0, "smlsd%5'x%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
5763d8817e4Smiod {ARM_EXT_V6, 0x07400050, 0x0ff000d0, "smlsld%5'x%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
5773d8817e4Smiod {ARM_EXT_V6, 0x0750f010, 0x0ff0f0d0, "smmul%5'r%c\t%16-19r, %0-3r, %8-11r"},
5783d8817e4Smiod {ARM_EXT_V6, 0x07500010, 0x0ff000d0, "smmla%5'r%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
5793d8817e4Smiod {ARM_EXT_V6, 0x075000d0, 0x0ff000d0, "smmls%5'r%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
5803d8817e4Smiod {ARM_EXT_V6, 0xf84d0500, 0xfe5fffe0, "srs%23?id%24?ba\t#%0-4d%21'!"},
5813d8817e4Smiod {ARM_EXT_V6, 0x06a00010, 0x0fe00ff0, "ssat%c\t%12-15r, #%16-20W, %0-3r"},
5823d8817e4Smiod {ARM_EXT_V6, 0x06a00010, 0x0fe00070, "ssat%c\t%12-15r, #%16-20W, %0-3r, LSL #%7-11d"},
5833d8817e4Smiod {ARM_EXT_V6, 0x06a00050, 0x0fe00070, "ssat%c\t%12-15r, #%16-20W, %0-3r, ASR #%7-11d"},
5843d8817e4Smiod {ARM_EXT_V6, 0x06a00f30, 0x0ff00ff0, "ssat16%c\t%12-15r, #%16-19W, %0-3r"},
5853d8817e4Smiod {ARM_EXT_V6, 0x01800f90, 0x0ff00ff0, "strex%c\t%12-15r, %0-3r, [%16-19r]"},
5863d8817e4Smiod {ARM_EXT_V6, 0x00400090, 0x0ff000f0, "umaal%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
5873d8817e4Smiod {ARM_EXT_V6, 0x0780f010, 0x0ff0f0f0, "usad8%c\t%16-19r, %0-3r, %8-11r"},
5883d8817e4Smiod {ARM_EXT_V6, 0x07800010, 0x0ff000f0, "usada8%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
5893d8817e4Smiod {ARM_EXT_V6, 0x06e00010, 0x0fe00ff0, "usat%c\t%12-15r, #%16-20d, %0-3r"},
5903d8817e4Smiod {ARM_EXT_V6, 0x06e00010, 0x0fe00070, "usat%c\t%12-15r, #%16-20d, %0-3r, LSL #%7-11d"},
5913d8817e4Smiod {ARM_EXT_V6, 0x06e00050, 0x0fe00070, "usat%c\t%12-15r, #%16-20d, %0-3r, ASR #%7-11d"},
5923d8817e4Smiod {ARM_EXT_V6, 0x06e00f30, 0x0ff00ff0, "usat16%c\t%12-15r, #%16-19d, %0-3r"},
5933d8817e4Smiod
5943d8817e4Smiod /* V5J instruction. */
5953d8817e4Smiod {ARM_EXT_V5J, 0x012fff20, 0x0ffffff0, "bxj%c\t%0-3r"},
5963d8817e4Smiod
5973d8817e4Smiod /* V5 Instructions. */
5983d8817e4Smiod {ARM_EXT_V5, 0xe1200070, 0xfff000f0, "bkpt\t0x%16-19X%12-15X%8-11X%0-3X"},
5993d8817e4Smiod {ARM_EXT_V5, 0xfa000000, 0xfe000000, "blx\t%B"},
6003d8817e4Smiod {ARM_EXT_V5, 0x012fff30, 0x0ffffff0, "blx%c\t%0-3r"},
6013d8817e4Smiod {ARM_EXT_V5, 0x016f0f10, 0x0fff0ff0, "clz%c\t%12-15r, %0-3r"},
6023d8817e4Smiod
6033d8817e4Smiod /* V5E "El Segundo" Instructions. */
6043d8817e4Smiod {ARM_EXT_V5E, 0x000000d0, 0x0e1000f0, "ldr%cd\t%12-15r, %s"},
6053d8817e4Smiod {ARM_EXT_V5E, 0x000000f0, 0x0e1000f0, "str%cd\t%12-15r, %s"},
6063d8817e4Smiod {ARM_EXT_V5E, 0xf450f000, 0xfc70f000, "pld\t%a"},
6073d8817e4Smiod {ARM_EXT_V5ExP, 0x01000080, 0x0ff000f0, "smlabb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
6083d8817e4Smiod {ARM_EXT_V5ExP, 0x010000a0, 0x0ff000f0, "smlatb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
6093d8817e4Smiod {ARM_EXT_V5ExP, 0x010000c0, 0x0ff000f0, "smlabt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
6103d8817e4Smiod {ARM_EXT_V5ExP, 0x010000e0, 0x0ff000f0, "smlatt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
6113d8817e4Smiod
6123d8817e4Smiod {ARM_EXT_V5ExP, 0x01200080, 0x0ff000f0, "smlawb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
6133d8817e4Smiod {ARM_EXT_V5ExP, 0x012000c0, 0x0ff000f0, "smlawt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
6143d8817e4Smiod
6153d8817e4Smiod {ARM_EXT_V5ExP, 0x01400080, 0x0ff000f0, "smlalbb%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
6163d8817e4Smiod {ARM_EXT_V5ExP, 0x014000a0, 0x0ff000f0, "smlaltb%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
6173d8817e4Smiod {ARM_EXT_V5ExP, 0x014000c0, 0x0ff000f0, "smlalbt%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
6183d8817e4Smiod {ARM_EXT_V5ExP, 0x014000e0, 0x0ff000f0, "smlaltt%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
6193d8817e4Smiod
6203d8817e4Smiod {ARM_EXT_V5ExP, 0x01600080, 0x0ff0f0f0, "smulbb%c\t%16-19r, %0-3r, %8-11r"},
6213d8817e4Smiod {ARM_EXT_V5ExP, 0x016000a0, 0x0ff0f0f0, "smultb%c\t%16-19r, %0-3r, %8-11r"},
6223d8817e4Smiod {ARM_EXT_V5ExP, 0x016000c0, 0x0ff0f0f0, "smulbt%c\t%16-19r, %0-3r, %8-11r"},
6233d8817e4Smiod {ARM_EXT_V5ExP, 0x016000e0, 0x0ff0f0f0, "smultt%c\t%16-19r, %0-3r, %8-11r"},
6243d8817e4Smiod
6253d8817e4Smiod {ARM_EXT_V5ExP, 0x012000a0, 0x0ff0f0f0, "smulwb%c\t%16-19r, %0-3r, %8-11r"},
6263d8817e4Smiod {ARM_EXT_V5ExP, 0x012000e0, 0x0ff0f0f0, "smulwt%c\t%16-19r, %0-3r, %8-11r"},
6273d8817e4Smiod
6283d8817e4Smiod {ARM_EXT_V5ExP, 0x01000050, 0x0ff00ff0, "qadd%c\t%12-15r, %0-3r, %16-19r"},
6293d8817e4Smiod {ARM_EXT_V5ExP, 0x01400050, 0x0ff00ff0, "qdadd%c\t%12-15r, %0-3r, %16-19r"},
6303d8817e4Smiod {ARM_EXT_V5ExP, 0x01200050, 0x0ff00ff0, "qsub%c\t%12-15r, %0-3r, %16-19r"},
6313d8817e4Smiod {ARM_EXT_V5ExP, 0x01600050, 0x0ff00ff0, "qdsub%c\t%12-15r, %0-3r, %16-19r"},
6323d8817e4Smiod
6333d8817e4Smiod /* ARM Instructions. */
6343d8817e4Smiod {ARM_EXT_V1, 0x00000090, 0x0e100090, "str%c%6's%5?hb\t%12-15r, %s"},
6353d8817e4Smiod {ARM_EXT_V1, 0x00100090, 0x0e100090, "ldr%c%6's%5?hb\t%12-15r, %s"},
6363d8817e4Smiod {ARM_EXT_V1, 0x00000000, 0x0de00000, "and%c%20's\t%12-15r, %16-19r, %o"},
6373d8817e4Smiod {ARM_EXT_V1, 0x00200000, 0x0de00000, "eor%c%20's\t%12-15r, %16-19r, %o"},
6383d8817e4Smiod {ARM_EXT_V1, 0x00400000, 0x0de00000, "sub%c%20's\t%12-15r, %16-19r, %o"},
6393d8817e4Smiod {ARM_EXT_V1, 0x00600000, 0x0de00000, "rsb%c%20's\t%12-15r, %16-19r, %o"},
6403d8817e4Smiod {ARM_EXT_V1, 0x00800000, 0x0de00000, "add%c%20's\t%12-15r, %16-19r, %o"},
6413d8817e4Smiod {ARM_EXT_V1, 0x00a00000, 0x0de00000, "adc%c%20's\t%12-15r, %16-19r, %o"},
6423d8817e4Smiod {ARM_EXT_V1, 0x00c00000, 0x0de00000, "sbc%c%20's\t%12-15r, %16-19r, %o"},
6433d8817e4Smiod {ARM_EXT_V1, 0x00e00000, 0x0de00000, "rsc%c%20's\t%12-15r, %16-19r, %o"},
6443d8817e4Smiod {ARM_EXT_V3, 0x0120f000, 0x0db0f000, "msr%c\t%22?SCPSR%C, %o"},
6453d8817e4Smiod {ARM_EXT_V3, 0x010f0000, 0x0fbf0fff, "mrs%c\t%12-15r, %22?SCPSR"},
6463d8817e4Smiod {ARM_EXT_V1, 0x01000000, 0x0de00000, "tst%c%p\t%16-19r, %o"},
6473d8817e4Smiod {ARM_EXT_V1, 0x01200000, 0x0de00000, "teq%c%p\t%16-19r, %o"},
6483d8817e4Smiod {ARM_EXT_V1, 0x01400000, 0x0de00000, "cmp%c%p\t%16-19r, %o"},
6493d8817e4Smiod {ARM_EXT_V1, 0x01600000, 0x0de00000, "cmn%c%p\t%16-19r, %o"},
6503d8817e4Smiod {ARM_EXT_V1, 0x01800000, 0x0de00000, "orr%c%20's\t%12-15r, %16-19r, %o"},
6513d8817e4Smiod {ARM_EXT_V1, 0x01a00000, 0x0de00000, "mov%c%20's\t%12-15r, %o"},
6523d8817e4Smiod {ARM_EXT_V1, 0x01c00000, 0x0de00000, "bic%c%20's\t%12-15r, %16-19r, %o"},
6533d8817e4Smiod {ARM_EXT_V1, 0x01e00000, 0x0de00000, "mvn%c%20's\t%12-15r, %o"},
6543d8817e4Smiod {ARM_EXT_V1, 0x04000000, 0x0e100000, "str%c%22'b%t\t%12-15r, %a"},
6553d8817e4Smiod {ARM_EXT_V1, 0x06000000, 0x0e100ff0, "str%c%22'b%t\t%12-15r, %a"},
6563d8817e4Smiod {ARM_EXT_V1, 0x04000000, 0x0c100010, "str%c%22'b%t\t%12-15r, %a"},
6573d8817e4Smiod {ARM_EXT_V1, 0x06000010, 0x0e000010, "undefined"},
6583d8817e4Smiod {ARM_EXT_V1, 0x04100000, 0x0c100000, "ldr%c%22'b%t\t%12-15r, %a"},
6593d8817e4Smiod {ARM_EXT_V1, 0x08000000, 0x0e100000, "stm%c%23?id%24?ba\t%16-19r%21'!, %m%22'^"},
6603d8817e4Smiod {ARM_EXT_V1, 0x08100000, 0x0e100000, "ldm%c%23?id%24?ba\t%16-19r%21'!, %m%22'^"},
6613d8817e4Smiod {ARM_EXT_V1, 0x0a000000, 0x0e000000, "b%24'l%c\t%b"},
6623d8817e4Smiod {ARM_EXT_V1, 0x0f000000, 0x0f000000, "svc%c\t%0-23x"},
6633d8817e4Smiod
6643d8817e4Smiod /* The rest. */
6653d8817e4Smiod {ARM_EXT_V1, 0x00000000, 0x00000000, "undefined instruction %0-31x"},
6663d8817e4Smiod {0, 0x00000000, 0x00000000, 0}
6673d8817e4Smiod };
6683d8817e4Smiod
6693d8817e4Smiod /* print_insn_thumb16 recognizes the following format control codes:
6703d8817e4Smiod
6713d8817e4Smiod %S print Thumb register (bits 3..5 as high number if bit 6 set)
6723d8817e4Smiod %D print Thumb register (bits 0..2 as high number if bit 7 set)
6733d8817e4Smiod %<bitfield>I print bitfield as a signed decimal
6743d8817e4Smiod (top bit of range being the sign bit)
6753d8817e4Smiod %N print Thumb register mask (with LR)
6763d8817e4Smiod %O print Thumb register mask (with PC)
6773d8817e4Smiod %M print Thumb register mask
6783d8817e4Smiod %b print CZB's 6-bit unsigned branch destination
6793d8817e4Smiod %s print Thumb right-shift immediate (6..10; 0 == 32).
6803d8817e4Smiod %<bitfield>r print bitfield as an ARM register
6813d8817e4Smiod %<bitfield>d print bitfield as a decimal
6823d8817e4Smiod %<bitfield>H print (bitfield * 2) as a decimal
6833d8817e4Smiod %<bitfield>W print (bitfield * 4) as a decimal
6843d8817e4Smiod %<bitfield>a print (bitfield * 4) as a pc-rel offset + decoded symbol
6853d8817e4Smiod %<bitfield>B print Thumb branch destination (signed displacement)
6863d8817e4Smiod %<bitfield>c print bitfield as a condition code
6873d8817e4Smiod %<bitnum>'c print specified char iff bit is one
6883d8817e4Smiod %<bitnum>?ab print a if bit is one else print b. */
6893d8817e4Smiod
6903d8817e4Smiod static const struct opcode16 thumb_opcodes[] =
6913d8817e4Smiod {
6923d8817e4Smiod /* Thumb instructions. */
6933d8817e4Smiod
6943d8817e4Smiod /* ARM V6K no-argument instructions. */
6953d8817e4Smiod {ARM_EXT_V6K, 0xbf00, 0xffff, "nop"},
6963d8817e4Smiod {ARM_EXT_V6K, 0xbf10, 0xffff, "yield"},
6973d8817e4Smiod {ARM_EXT_V6K, 0xbf20, 0xffff, "wfe"},
6983d8817e4Smiod {ARM_EXT_V6K, 0xbf30, 0xffff, "wfi"},
6993d8817e4Smiod {ARM_EXT_V6K, 0xbf40, 0xffff, "sev"},
7003d8817e4Smiod {ARM_EXT_V6K, 0xbf00, 0xff0f, "nop\t{%4-7d}"},
7013d8817e4Smiod
7023d8817e4Smiod /* ARM V6T2 instructions. */
7033d8817e4Smiod {ARM_EXT_V6T2, 0xb900, 0xfd00, "cbnz\t%0-2r, %b"},
7043d8817e4Smiod {ARM_EXT_V6T2, 0xb100, 0xfd00, "cbz\t%0-2r, %b"},
7053d8817e4Smiod {ARM_EXT_V6T2, 0xbf08, 0xff0f, "it\t%4-7c"},
7063d8817e4Smiod {ARM_EXT_V6T2, 0xbf14, 0xff17, "it%3?te\t%4-7c"},
7073d8817e4Smiod {ARM_EXT_V6T2, 0xbf04, 0xff17, "it%3?et\t%4-7c"},
7083d8817e4Smiod {ARM_EXT_V6T2, 0xbf12, 0xff13, "it%3?te%2?te\t%4-7c"},
7093d8817e4Smiod {ARM_EXT_V6T2, 0xbf02, 0xff13, "it%3?et%2?et\t%4-7c"},
7103d8817e4Smiod {ARM_EXT_V6T2, 0xbf11, 0xff11, "it%3?te%2?te%1?te\t%4-7c"},
7113d8817e4Smiod {ARM_EXT_V6T2, 0xbf01, 0xff11, "it%3?et%2?et%1?et\t%4-7c"},
7123d8817e4Smiod
7133d8817e4Smiod /* ARM V6. */
7143d8817e4Smiod {ARM_EXT_V6, 0xb660, 0xfff8, "cpsie\t%2'a%1'i%0'f"},
7153d8817e4Smiod {ARM_EXT_V6, 0xb670, 0xfff8, "cpsid\t%2'a%1'i%0'f"},
7163d8817e4Smiod {ARM_EXT_V6, 0x4600, 0xffc0, "mov\t%0-2r, %3-5r"},
7173d8817e4Smiod {ARM_EXT_V6, 0xba00, 0xffc0, "rev\t%0-2r, %3-5r"},
7183d8817e4Smiod {ARM_EXT_V6, 0xba40, 0xffc0, "rev16\t%0-2r, %3-5r"},
7193d8817e4Smiod {ARM_EXT_V6, 0xbac0, 0xffc0, "revsh\t%0-2r, %3-5r"},
7203d8817e4Smiod {ARM_EXT_V6, 0xb650, 0xfff7, "setend\t%3?ble"},
7213d8817e4Smiod {ARM_EXT_V6, 0xb200, 0xffc0, "sxth\t%0-2r, %3-5r"},
7223d8817e4Smiod {ARM_EXT_V6, 0xb240, 0xffc0, "sxtb\t%0-2r, %3-5r"},
7233d8817e4Smiod {ARM_EXT_V6, 0xb280, 0xffc0, "uxth\t%0-2r, %3-5r"},
7243d8817e4Smiod {ARM_EXT_V6, 0xb2c0, 0xffc0, "uxtb\t%0-2r, %3-5r"},
7253d8817e4Smiod
7263d8817e4Smiod /* ARM V5 ISA extends Thumb. */
7273d8817e4Smiod {ARM_EXT_V5T, 0xbe00, 0xff00, "bkpt\t%0-7x"},
7283d8817e4Smiod /* This is BLX(2). BLX(1) is a 32-bit instruction. */
7293d8817e4Smiod {ARM_EXT_V5T, 0x4780, 0xff87, "blx\t%3-6r"}, /* note: 4 bit register number. */
7303d8817e4Smiod /* ARM V4T ISA (Thumb v1). */
7313d8817e4Smiod {ARM_EXT_V4T, 0x46C0, 0xFFFF, "nop\t\t\t(mov r8, r8)"},
7323d8817e4Smiod /* Format 4. */
7333d8817e4Smiod {ARM_EXT_V4T, 0x4000, 0xFFC0, "ands\t%0-2r, %3-5r"},
7343d8817e4Smiod {ARM_EXT_V4T, 0x4040, 0xFFC0, "eors\t%0-2r, %3-5r"},
7353d8817e4Smiod {ARM_EXT_V4T, 0x4080, 0xFFC0, "lsls\t%0-2r, %3-5r"},
7363d8817e4Smiod {ARM_EXT_V4T, 0x40C0, 0xFFC0, "lsrs\t%0-2r, %3-5r"},
7373d8817e4Smiod {ARM_EXT_V4T, 0x4100, 0xFFC0, "asrs\t%0-2r, %3-5r"},
7383d8817e4Smiod {ARM_EXT_V4T, 0x4140, 0xFFC0, "adcs\t%0-2r, %3-5r"},
7393d8817e4Smiod {ARM_EXT_V4T, 0x4180, 0xFFC0, "sbcs\t%0-2r, %3-5r"},
7403d8817e4Smiod {ARM_EXT_V4T, 0x41C0, 0xFFC0, "rors\t%0-2r, %3-5r"},
7413d8817e4Smiod {ARM_EXT_V4T, 0x4200, 0xFFC0, "tst\t%0-2r, %3-5r"},
7423d8817e4Smiod {ARM_EXT_V4T, 0x4240, 0xFFC0, "negs\t%0-2r, %3-5r"},
7433d8817e4Smiod {ARM_EXT_V4T, 0x4280, 0xFFC0, "cmp\t%0-2r, %3-5r"},
7443d8817e4Smiod {ARM_EXT_V4T, 0x42C0, 0xFFC0, "cmn\t%0-2r, %3-5r"},
7453d8817e4Smiod {ARM_EXT_V4T, 0x4300, 0xFFC0, "orrs\t%0-2r, %3-5r"},
7463d8817e4Smiod {ARM_EXT_V4T, 0x4340, 0xFFC0, "muls\t%0-2r, %3-5r"},
7473d8817e4Smiod {ARM_EXT_V4T, 0x4380, 0xFFC0, "bics\t%0-2r, %3-5r"},
7483d8817e4Smiod {ARM_EXT_V4T, 0x43C0, 0xFFC0, "mvns\t%0-2r, %3-5r"},
7493d8817e4Smiod /* format 13 */
7503d8817e4Smiod {ARM_EXT_V4T, 0xB000, 0xFF80, "add\tsp, #%0-6W"},
7513d8817e4Smiod {ARM_EXT_V4T, 0xB080, 0xFF80, "sub\tsp, #%0-6W"},
7523d8817e4Smiod /* format 5 */
7533d8817e4Smiod {ARM_EXT_V4T, 0x4700, 0xFF80, "bx\t%S"},
7543d8817e4Smiod {ARM_EXT_V4T, 0x4400, 0xFF00, "add\t%D, %S"},
7553d8817e4Smiod {ARM_EXT_V4T, 0x4500, 0xFF00, "cmp\t%D, %S"},
7563d8817e4Smiod {ARM_EXT_V4T, 0x4600, 0xFF00, "mov\t%D, %S"},
7573d8817e4Smiod /* format 14 */
7583d8817e4Smiod {ARM_EXT_V4T, 0xB400, 0xFE00, "push\t%N"},
7593d8817e4Smiod {ARM_EXT_V4T, 0xBC00, 0xFE00, "pop\t%O"},
7603d8817e4Smiod /* format 2 */
7613d8817e4Smiod {ARM_EXT_V4T, 0x1800, 0xFE00, "adds\t%0-2r, %3-5r, %6-8r"},
7623d8817e4Smiod {ARM_EXT_V4T, 0x1A00, 0xFE00, "subs\t%0-2r, %3-5r, %6-8r"},
7633d8817e4Smiod {ARM_EXT_V4T, 0x1C00, 0xFE00, "adds\t%0-2r, %3-5r, #%6-8d"},
7643d8817e4Smiod {ARM_EXT_V4T, 0x1E00, 0xFE00, "subs\t%0-2r, %3-5r, #%6-8d"},
7653d8817e4Smiod /* format 8 */
7663d8817e4Smiod {ARM_EXT_V4T, 0x5200, 0xFE00, "strh\t%0-2r, [%3-5r, %6-8r]"},
7673d8817e4Smiod {ARM_EXT_V4T, 0x5A00, 0xFE00, "ldrh\t%0-2r, [%3-5r, %6-8r]"},
7683d8817e4Smiod {ARM_EXT_V4T, 0x5600, 0xF600, "ldrs%11?hb\t%0-2r, [%3-5r, %6-8r]"},
7693d8817e4Smiod /* format 7 */
7703d8817e4Smiod {ARM_EXT_V4T, 0x5000, 0xFA00, "str%10'b\t%0-2r, [%3-5r, %6-8r]"},
7713d8817e4Smiod {ARM_EXT_V4T, 0x5800, 0xFA00, "ldr%10'b\t%0-2r, [%3-5r, %6-8r]"},
7723d8817e4Smiod /* format 1 */
7733d8817e4Smiod {ARM_EXT_V4T, 0x0000, 0xF800, "lsls\t%0-2r, %3-5r, #%6-10d"},
7743d8817e4Smiod {ARM_EXT_V4T, 0x0800, 0xF800, "lsrs\t%0-2r, %3-5r, %s"},
7753d8817e4Smiod {ARM_EXT_V4T, 0x1000, 0xF800, "asrs\t%0-2r, %3-5r, %s"},
7763d8817e4Smiod /* format 3 */
7773d8817e4Smiod {ARM_EXT_V4T, 0x2000, 0xF800, "movs\t%8-10r, #%0-7d"},
7783d8817e4Smiod {ARM_EXT_V4T, 0x2800, 0xF800, "cmp\t%8-10r, #%0-7d"},
7793d8817e4Smiod {ARM_EXT_V4T, 0x3000, 0xF800, "adds\t%8-10r, #%0-7d"},
7803d8817e4Smiod {ARM_EXT_V4T, 0x3800, 0xF800, "subs\t%8-10r, #%0-7d"},
7813d8817e4Smiod /* format 6 */
7823d8817e4Smiod {ARM_EXT_V4T, 0x4800, 0xF800, "ldr\t%8-10r, [pc, #%0-7W]\t(%0-7a)"}, /* TODO: Disassemble PC relative "LDR rD,=<symbolic>" */
7833d8817e4Smiod /* format 9 */
7843d8817e4Smiod {ARM_EXT_V4T, 0x6000, 0xF800, "str\t%0-2r, [%3-5r, #%6-10W]"},
7853d8817e4Smiod {ARM_EXT_V4T, 0x6800, 0xF800, "ldr\t%0-2r, [%3-5r, #%6-10W]"},
7863d8817e4Smiod {ARM_EXT_V4T, 0x7000, 0xF800, "strb\t%0-2r, [%3-5r, #%6-10d]"},
7873d8817e4Smiod {ARM_EXT_V4T, 0x7800, 0xF800, "ldrb\t%0-2r, [%3-5r, #%6-10d]"},
7883d8817e4Smiod /* format 10 */
7893d8817e4Smiod {ARM_EXT_V4T, 0x8000, 0xF800, "strh\t%0-2r, [%3-5r, #%6-10H]"},
7903d8817e4Smiod {ARM_EXT_V4T, 0x8800, 0xF800, "ldrh\t%0-2r, [%3-5r, #%6-10H]"},
7913d8817e4Smiod /* format 11 */
7923d8817e4Smiod {ARM_EXT_V4T, 0x9000, 0xF800, "str\t%8-10r, [sp, #%0-7W]"},
7933d8817e4Smiod {ARM_EXT_V4T, 0x9800, 0xF800, "ldr\t%8-10r, [sp, #%0-7W]"},
7943d8817e4Smiod /* format 12 */
7953d8817e4Smiod {ARM_EXT_V4T, 0xA000, 0xF800, "add\t%8-10r, pc, #%0-7W\t(adr %8-10r,%0-7a)"},
7963d8817e4Smiod {ARM_EXT_V4T, 0xA800, 0xF800, "add\t%8-10r, sp, #%0-7W"},
7973d8817e4Smiod /* format 15 */
7983d8817e4Smiod {ARM_EXT_V4T, 0xC000, 0xF800, "stmia\t%8-10r!, %M"},
7993d8817e4Smiod {ARM_EXT_V4T, 0xC800, 0xF800, "ldmia\t%8-10r!, %M"},
8003d8817e4Smiod /* format 17 */
8013d8817e4Smiod {ARM_EXT_V4T, 0xDF00, 0xFF00, "svc\t%0-7d"},
8023d8817e4Smiod /* format 16 */
8033d8817e4Smiod {ARM_EXT_V4T, 0xD000, 0xF000, "b%8-11c.n\t%0-7B"},
8043d8817e4Smiod /* format 18 */
8053d8817e4Smiod {ARM_EXT_V4T, 0xE000, 0xF800, "b.n\t%0-10B"},
8063d8817e4Smiod
8073d8817e4Smiod /* The E800 .. FFFF range is unconditionally redirected to the
8083d8817e4Smiod 32-bit table, because even in pre-V6T2 ISAs, BL and BLX(1) pairs
8093d8817e4Smiod are processed via that table. Thus, we can never encounter a
8103d8817e4Smiod bare "second half of BL/BLX(1)" instruction here. */
8113d8817e4Smiod {ARM_EXT_V1, 0x0000, 0x0000, "undefined"},
8123d8817e4Smiod {0, 0, 0, 0}
8133d8817e4Smiod };
8143d8817e4Smiod
8153d8817e4Smiod /* Thumb32 opcodes use the same table structure as the ARM opcodes.
8163d8817e4Smiod We adopt the convention that hw1 is the high 16 bits of .value and
8173d8817e4Smiod .mask, hw2 the low 16 bits.
8183d8817e4Smiod
8193d8817e4Smiod print_insn_thumb32 recognizes the following format control codes:
8203d8817e4Smiod
8213d8817e4Smiod %% %
8223d8817e4Smiod
8233d8817e4Smiod %I print a 12-bit immediate from hw1[10],hw2[14:12,7:0]
8243d8817e4Smiod %M print a modified 12-bit immediate (same location)
8253d8817e4Smiod %J print a 16-bit immediate from hw1[3:0,10],hw2[14:12,7:0]
8263d8817e4Smiod %K print a 16-bit immediate from hw2[3:0],hw1[3:0],hw2[11:4]
8273d8817e4Smiod %S print a possibly-shifted Rm
8283d8817e4Smiod
8293d8817e4Smiod %a print the address of a plain load/store
8303d8817e4Smiod %w print the width and signedness of a core load/store
8313d8817e4Smiod %m print register mask for ldm/stm
8323d8817e4Smiod
8333d8817e4Smiod %E print the lsb and width fields of a bfc/bfi instruction
8343d8817e4Smiod %F print the lsb and width fields of a sbfx/ubfx instruction
8353d8817e4Smiod %b print a conditional branch offset
8363d8817e4Smiod %B print an unconditional branch offset
8373d8817e4Smiod %s print the shift field of an SSAT instruction
8383d8817e4Smiod %R print the rotation field of an SXT instruction
8393d8817e4Smiod %U print barrier type.
8403d8817e4Smiod %P print address for pli instruction.
8413d8817e4Smiod
8423d8817e4Smiod %<bitfield>d print bitfield in decimal
8433d8817e4Smiod %<bitfield>W print bitfield*4 in decimal
8443d8817e4Smiod %<bitfield>r print bitfield as an ARM register
8453d8817e4Smiod %<bitfield>c print bitfield as a condition code
8463d8817e4Smiod
8473d8817e4Smiod %<bitnum>'c print "c" iff bit is one
8483d8817e4Smiod %<bitnum>`c print "c" iff bit is zero
8493d8817e4Smiod %<bitnum>?ab print "a" if bit is one, else "b"
8503d8817e4Smiod
8513d8817e4Smiod With one exception at the bottom (done because BL and BLX(1) need
8523d8817e4Smiod to come dead last), this table was machine-sorted first in
8533d8817e4Smiod decreasing order of number of bits set in the mask, then in
8543d8817e4Smiod increasing numeric order of mask, then in increasing numeric order
8553d8817e4Smiod of opcode. This order is not the clearest for a human reader, but
8563d8817e4Smiod is guaranteed never to catch a special-case bit pattern with a more
8573d8817e4Smiod general mask, which is important, because this instruction encoding
8583d8817e4Smiod makes heavy use of special-case bit patterns. */
8593d8817e4Smiod static const struct opcode32 thumb32_opcodes[] =
8603d8817e4Smiod {
8613d8817e4Smiod /* V7 instructions. */
8623d8817e4Smiod {ARM_EXT_V7, 0xf910f000, 0xff70f000, "pli\t%a"},
8633d8817e4Smiod {ARM_EXT_V7, 0xf3af80f0, 0xfffffff0, "dbg\t#%0-3d"},
8643d8817e4Smiod {ARM_EXT_V7, 0xf3bf8f50, 0xfffffff0, "dmb\t%U"},
8653d8817e4Smiod {ARM_EXT_V7, 0xf3bf8f40, 0xfffffff0, "dsb\t%U"},
8663d8817e4Smiod {ARM_EXT_V7, 0xf3bf8f60, 0xfffffff0, "isb\t%U"},
8673d8817e4Smiod {ARM_EXT_DIV, 0xfb90f0f0, 0xfff0f0f0, "sdiv\t%8-11r, %16-19r, %0-3r"},
8683d8817e4Smiod {ARM_EXT_DIV, 0xfbb0f0f0, 0xfff0f0f0, "udiv\t%8-11r, %16-19r, %0-3r"},
8693d8817e4Smiod
8703d8817e4Smiod /* Instructions defined in the basic V6T2 set. */
8713d8817e4Smiod {ARM_EXT_V6T2, 0xf3af8000, 0xffffffff, "nop.w"},
8723d8817e4Smiod {ARM_EXT_V6T2, 0xf3af8001, 0xffffffff, "yield.w"},
8733d8817e4Smiod {ARM_EXT_V6T2, 0xf3af8002, 0xffffffff, "wfe.w"},
8743d8817e4Smiod {ARM_EXT_V6T2, 0xf3af8003, 0xffffffff, "wfi.w"},
8753d8817e4Smiod {ARM_EXT_V6T2, 0xf3af9004, 0xffffffff, "sev.w"},
8763d8817e4Smiod {ARM_EXT_V6T2, 0xf3af8000, 0xffffff00, "nop.w\t{%0-7d}"},
8773d8817e4Smiod
8783d8817e4Smiod {ARM_EXT_V6T2, 0xf3bf8f2f, 0xffffffff, "clrex"},
8793d8817e4Smiod {ARM_EXT_V6T2, 0xf3af8400, 0xffffff1f, "cpsie.w\t%7'a%6'i%5'f"},
8803d8817e4Smiod {ARM_EXT_V6T2, 0xf3af8600, 0xffffff1f, "cpsid.w\t%7'a%6'i%5'f"},
8813d8817e4Smiod {ARM_EXT_V6T2, 0xf3c08f00, 0xfff0ffff, "bxj\t%16-19r"},
8823d8817e4Smiod {ARM_EXT_V6T2, 0xe810c000, 0xffd0ffff, "rfedb\t%16-19r%21'!"},
8833d8817e4Smiod {ARM_EXT_V6T2, 0xe990c000, 0xffd0ffff, "rfeia\t%16-19r%21'!"},
8843d8817e4Smiod {ARM_EXT_V6T2, 0xf3ef8000, 0xffeff000, "mrs\t%8-11r, %D"},
8853d8817e4Smiod {ARM_EXT_V6T2, 0xf3af8100, 0xffffffe0, "cps\t#%0-4d"},
8863d8817e4Smiod {ARM_EXT_V6T2, 0xe8d0f000, 0xfff0fff0, "tbb\t[%16-19r, %0-3r]"},
8873d8817e4Smiod {ARM_EXT_V6T2, 0xe8d0f010, 0xfff0fff0, "tbh\t[%16-19r, %0-3r, lsl #1]"},
8883d8817e4Smiod {ARM_EXT_V6T2, 0xf3af8500, 0xffffff00, "cpsie\t%7'a%6'i%5'f, #%0-4d"},
8893d8817e4Smiod {ARM_EXT_V6T2, 0xf3af8700, 0xffffff00, "cpsid\t%7'a%6'i%5'f, #%0-4d"},
8903d8817e4Smiod {ARM_EXT_V6T2, 0xf3de8f00, 0xffffff00, "subs\tpc, lr, #%0-7d"},
8913d8817e4Smiod {ARM_EXT_V6T2, 0xf3808000, 0xffe0f000, "msr\t%C, %16-19r"},
8923d8817e4Smiod {ARM_EXT_V6T2, 0xe8500f00, 0xfff00fff, "ldrex\t%12-15r, [%16-19r]"},
8933d8817e4Smiod {ARM_EXT_V6T2, 0xe8d00f4f, 0xfff00fef, "ldrex%4?hb\t%12-15r, [%16-19r]"},
8943d8817e4Smiod {ARM_EXT_V6T2, 0xe800c000, 0xffd0ffe0, "srsdb\t#%0-4d%21'!"},
8953d8817e4Smiod {ARM_EXT_V6T2, 0xe980c000, 0xffd0ffe0, "srsia\t#%0-4d%21'!"},
8963d8817e4Smiod {ARM_EXT_V6T2, 0xfa0ff080, 0xfffff0c0, "sxth.w\t%8-11r, %0-3r%R"},
8973d8817e4Smiod {ARM_EXT_V6T2, 0xfa1ff080, 0xfffff0c0, "uxth.w\t%8-11r, %0-3r%R"},
8983d8817e4Smiod {ARM_EXT_V6T2, 0xfa2ff080, 0xfffff0c0, "sxtb16\t%8-11r, %0-3r%R"},
8993d8817e4Smiod {ARM_EXT_V6T2, 0xfa3ff080, 0xfffff0c0, "uxtb16\t%8-11r, %0-3r%R"},
9003d8817e4Smiod {ARM_EXT_V6T2, 0xfa4ff080, 0xfffff0c0, "sxtb.w\t%8-11r, %0-3r%R"},
9013d8817e4Smiod {ARM_EXT_V6T2, 0xfa5ff080, 0xfffff0c0, "uxtb.w\t%8-11r, %0-3r%R"},
9023d8817e4Smiod {ARM_EXT_V6T2, 0xe8400000, 0xfff000ff, "strex\t%8-11r, %12-15r, [%16-19r]"},
9033d8817e4Smiod {ARM_EXT_V6T2, 0xe8d0007f, 0xfff000ff, "ldrexd\t%12-15r, %8-11r, [%16-19r]"},
9043d8817e4Smiod {ARM_EXT_V6T2, 0xfa80f000, 0xfff0f0f0, "sadd8\t%8-11r, %16-19r, %0-3r"},
9053d8817e4Smiod {ARM_EXT_V6T2, 0xfa80f010, 0xfff0f0f0, "qadd8\t%8-11r, %16-19r, %0-3r"},
9063d8817e4Smiod {ARM_EXT_V6T2, 0xfa80f020, 0xfff0f0f0, "shadd8\t%8-11r, %16-19r, %0-3r"},
9073d8817e4Smiod {ARM_EXT_V6T2, 0xfa80f040, 0xfff0f0f0, "uadd8\t%8-11r, %16-19r, %0-3r"},
9083d8817e4Smiod {ARM_EXT_V6T2, 0xfa80f050, 0xfff0f0f0, "uqadd8\t%8-11r, %16-19r, %0-3r"},
9093d8817e4Smiod {ARM_EXT_V6T2, 0xfa80f060, 0xfff0f0f0, "uhadd8\t%8-11r, %16-19r, %0-3r"},
9103d8817e4Smiod {ARM_EXT_V6T2, 0xfa80f080, 0xfff0f0f0, "qadd\t%8-11r, %0-3r, %16-19r"},
9113d8817e4Smiod {ARM_EXT_V6T2, 0xfa80f090, 0xfff0f0f0, "qdadd\t%8-11r, %0-3r, %16-19r"},
9123d8817e4Smiod {ARM_EXT_V6T2, 0xfa80f0a0, 0xfff0f0f0, "qsub\t%8-11r, %0-3r, %16-19r"},
9133d8817e4Smiod {ARM_EXT_V6T2, 0xfa80f0b0, 0xfff0f0f0, "qdsub\t%8-11r, %0-3r, %16-19r"},
9143d8817e4Smiod {ARM_EXT_V6T2, 0xfa90f000, 0xfff0f0f0, "sadd16\t%8-11r, %16-19r, %0-3r"},
9153d8817e4Smiod {ARM_EXT_V6T2, 0xfa90f010, 0xfff0f0f0, "qadd16\t%8-11r, %16-19r, %0-3r"},
9163d8817e4Smiod {ARM_EXT_V6T2, 0xfa90f020, 0xfff0f0f0, "shadd16\t%8-11r, %16-19r, %0-3r"},
9173d8817e4Smiod {ARM_EXT_V6T2, 0xfa90f040, 0xfff0f0f0, "uadd16\t%8-11r, %16-19r, %0-3r"},
9183d8817e4Smiod {ARM_EXT_V6T2, 0xfa90f050, 0xfff0f0f0, "uqadd16\t%8-11r, %16-19r, %0-3r"},
9193d8817e4Smiod {ARM_EXT_V6T2, 0xfa90f060, 0xfff0f0f0, "uhadd16\t%8-11r, %16-19r, %0-3r"},
9203d8817e4Smiod {ARM_EXT_V6T2, 0xfa90f080, 0xfff0f0f0, "rev.w\t%8-11r, %16-19r"},
9213d8817e4Smiod {ARM_EXT_V6T2, 0xfa90f090, 0xfff0f0f0, "rev16.w\t%8-11r, %16-19r"},
9223d8817e4Smiod {ARM_EXT_V6T2, 0xfa90f0a0, 0xfff0f0f0, "rbit\t%8-11r, %16-19r"},
9233d8817e4Smiod {ARM_EXT_V6T2, 0xfa90f0b0, 0xfff0f0f0, "revsh.w\t%8-11r, %16-19r"},
9243d8817e4Smiod {ARM_EXT_V6T2, 0xfaa0f000, 0xfff0f0f0, "saddsubx\t%8-11r, %16-19r, %0-3r"},
9253d8817e4Smiod {ARM_EXT_V6T2, 0xfaa0f010, 0xfff0f0f0, "qaddsubx\t%8-11r, %16-19r, %0-3r"},
9263d8817e4Smiod {ARM_EXT_V6T2, 0xfaa0f020, 0xfff0f0f0, "shaddsubx\t%8-11r, %16-19r, %0-3r"},
9273d8817e4Smiod {ARM_EXT_V6T2, 0xfaa0f040, 0xfff0f0f0, "uaddsubx\t%8-11r, %16-19r, %0-3r"},
9283d8817e4Smiod {ARM_EXT_V6T2, 0xfaa0f050, 0xfff0f0f0, "uqaddsubx\t%8-11r, %16-19r, %0-3r"},
9293d8817e4Smiod {ARM_EXT_V6T2, 0xfaa0f060, 0xfff0f0f0, "uhaddsubx\t%8-11r, %16-19r, %0-3r"},
9303d8817e4Smiod {ARM_EXT_V6T2, 0xfaa0f080, 0xfff0f0f0, "sel\t%8-11r, %16-19r, %0-3r"},
9313d8817e4Smiod {ARM_EXT_V6T2, 0xfab0f080, 0xfff0f0f0, "clz\t%8-11r, %16-19r"},
9323d8817e4Smiod {ARM_EXT_V6T2, 0xfac0f000, 0xfff0f0f0, "ssub8\t%8-11r, %16-19r, %0-3r"},
9333d8817e4Smiod {ARM_EXT_V6T2, 0xfac0f010, 0xfff0f0f0, "qsub8\t%8-11r, %16-19r, %0-3r"},
9343d8817e4Smiod {ARM_EXT_V6T2, 0xfac0f020, 0xfff0f0f0, "shsub8\t%8-11r, %16-19r, %0-3r"},
9353d8817e4Smiod {ARM_EXT_V6T2, 0xfac0f040, 0xfff0f0f0, "usub8\t%8-11r, %16-19r, %0-3r"},
9363d8817e4Smiod {ARM_EXT_V6T2, 0xfac0f050, 0xfff0f0f0, "uqsub8\t%8-11r, %16-19r, %0-3r"},
9373d8817e4Smiod {ARM_EXT_V6T2, 0xfac0f060, 0xfff0f0f0, "uhsub8\t%8-11r, %16-19r, %0-3r"},
9383d8817e4Smiod {ARM_EXT_V6T2, 0xfad0f000, 0xfff0f0f0, "ssub16\t%8-11r, %16-19r, %0-3r"},
9393d8817e4Smiod {ARM_EXT_V6T2, 0xfad0f010, 0xfff0f0f0, "qsub16\t%8-11r, %16-19r, %0-3r"},
9403d8817e4Smiod {ARM_EXT_V6T2, 0xfad0f020, 0xfff0f0f0, "shsub16\t%8-11r, %16-19r, %0-3r"},
9413d8817e4Smiod {ARM_EXT_V6T2, 0xfad0f040, 0xfff0f0f0, "usub16\t%8-11r, %16-19r, %0-3r"},
9423d8817e4Smiod {ARM_EXT_V6T2, 0xfad0f050, 0xfff0f0f0, "uqsub16\t%8-11r, %16-19r, %0-3r"},
9433d8817e4Smiod {ARM_EXT_V6T2, 0xfad0f060, 0xfff0f0f0, "uhsub16\t%8-11r, %16-19r, %0-3r"},
9443d8817e4Smiod {ARM_EXT_V6T2, 0xfae0f000, 0xfff0f0f0, "ssubaddx\t%8-11r, %16-19r, %0-3r"},
9453d8817e4Smiod {ARM_EXT_V6T2, 0xfae0f010, 0xfff0f0f0, "qsubaddx\t%8-11r, %16-19r, %0-3r"},
9463d8817e4Smiod {ARM_EXT_V6T2, 0xfae0f020, 0xfff0f0f0, "shsubaddx\t%8-11r, %16-19r, %0-3r"},
9473d8817e4Smiod {ARM_EXT_V6T2, 0xfae0f040, 0xfff0f0f0, "usubaddx\t%8-11r, %16-19r, %0-3r"},
9483d8817e4Smiod {ARM_EXT_V6T2, 0xfae0f050, 0xfff0f0f0, "uqsubaddx\t%8-11r, %16-19r, %0-3r"},
9493d8817e4Smiod {ARM_EXT_V6T2, 0xfae0f060, 0xfff0f0f0, "uhsubaddx\t%8-11r, %16-19r, %0-3r"},
9503d8817e4Smiod {ARM_EXT_V6T2, 0xfb00f000, 0xfff0f0f0, "mul.w\t%8-11r, %16-19r, %0-3r"},
9513d8817e4Smiod {ARM_EXT_V6T2, 0xfb70f000, 0xfff0f0f0, "usad8\t%8-11r, %16-19r, %0-3r"},
9523d8817e4Smiod {ARM_EXT_V6T2, 0xfa00f000, 0xffe0f0f0, "lsl%20's.w\t%8-11r, %16-19r, %0-3r"},
9533d8817e4Smiod {ARM_EXT_V6T2, 0xfa20f000, 0xffe0f0f0, "lsr%20's.w\t%8-11r, %16-19r, %0-3r"},
9543d8817e4Smiod {ARM_EXT_V6T2, 0xfa40f000, 0xffe0f0f0, "asr%20's.w\t%8-11r, %16-19r, %0-3r"},
9553d8817e4Smiod {ARM_EXT_V6T2, 0xfa60f000, 0xffe0f0f0, "ror%20's.w\t%8-11r, %16-19r, %0-3r"},
9563d8817e4Smiod {ARM_EXT_V6T2, 0xe8c00f40, 0xfff00fe0, "strex%4?hb\t%0-3r, %12-15r, [%16-19r]"},
9573d8817e4Smiod {ARM_EXT_V6T2, 0xf3200000, 0xfff0f0e0, "ssat16\t%8-11r, #%0-4d, %16-19r"},
9583d8817e4Smiod {ARM_EXT_V6T2, 0xf3a00000, 0xfff0f0e0, "usat16\t%8-11r, #%0-4d, %16-19r"},
9593d8817e4Smiod {ARM_EXT_V6T2, 0xfb20f000, 0xfff0f0e0, "smuad%4'x\t%8-11r, %16-19r, %0-3r"},
9603d8817e4Smiod {ARM_EXT_V6T2, 0xfb30f000, 0xfff0f0e0, "smulw%4?tb\t%8-11r, %16-19r, %0-3r"},
9613d8817e4Smiod {ARM_EXT_V6T2, 0xfb40f000, 0xfff0f0e0, "smusd%4'x\t%8-11r, %16-19r, %0-3r"},
9623d8817e4Smiod {ARM_EXT_V6T2, 0xfb50f000, 0xfff0f0e0, "smmul%4'r\t%8-11r, %16-19r, %0-3r"},
9633d8817e4Smiod {ARM_EXT_V6T2, 0xfa00f080, 0xfff0f0c0, "sxtah\t%8-11r, %16-19r, %0-3r%R"},
9643d8817e4Smiod {ARM_EXT_V6T2, 0xfa10f080, 0xfff0f0c0, "uxtah\t%8-11r, %16-19r, %0-3r%R"},
9653d8817e4Smiod {ARM_EXT_V6T2, 0xfa20f080, 0xfff0f0c0, "sxtab16\t%8-11r, %16-19r, %0-3r%R"},
9663d8817e4Smiod {ARM_EXT_V6T2, 0xfa30f080, 0xfff0f0c0, "uxtab16\t%8-11r, %16-19r, %0-3r%R"},
9673d8817e4Smiod {ARM_EXT_V6T2, 0xfa40f080, 0xfff0f0c0, "sxtab\t%8-11r, %16-19r, %0-3r%R"},
9683d8817e4Smiod {ARM_EXT_V6T2, 0xfa50f080, 0xfff0f0c0, "uxtab\t%8-11r, %16-19r, %0-3r%R"},
9693d8817e4Smiod {ARM_EXT_V6T2, 0xfb10f000, 0xfff0f0c0, "smul%5?tb%4?tb\t%8-11r, %16-19r, %0-3r"},
9703d8817e4Smiod {ARM_EXT_V6T2, 0xf36f0000, 0xffff8020, "bfc\t%8-11r, %E"},
9713d8817e4Smiod {ARM_EXT_V6T2, 0xea100f00, 0xfff08f00, "tst.w\t%16-19r, %S"},
9723d8817e4Smiod {ARM_EXT_V6T2, 0xea900f00, 0xfff08f00, "teq\t%16-19r, %S"},
9733d8817e4Smiod {ARM_EXT_V6T2, 0xeb100f00, 0xfff08f00, "cmn.w\t%16-19r, %S"},
9743d8817e4Smiod {ARM_EXT_V6T2, 0xebb00f00, 0xfff08f00, "cmp.w\t%16-19r, %S"},
9753d8817e4Smiod {ARM_EXT_V6T2, 0xf0100f00, 0xfbf08f00, "tst.w\t%16-19r, %M"},
9763d8817e4Smiod {ARM_EXT_V6T2, 0xf0900f00, 0xfbf08f00, "teq\t%16-19r, %M"},
9773d8817e4Smiod {ARM_EXT_V6T2, 0xf1100f00, 0xfbf08f00, "cmn.w\t%16-19r, %M"},
9783d8817e4Smiod {ARM_EXT_V6T2, 0xf1b00f00, 0xfbf08f00, "cmp.w\t%16-19r, %M"},
9793d8817e4Smiod {ARM_EXT_V6T2, 0xea4f0000, 0xffef8000, "mov%20's.w\t%8-11r, %S"},
9803d8817e4Smiod {ARM_EXT_V6T2, 0xea6f0000, 0xffef8000, "mvn%20's.w\t%8-11r, %S"},
9813d8817e4Smiod {ARM_EXT_V6T2, 0xe8c00070, 0xfff000f0, "strexd\t%0-3r, %12-15r, %8-11r, [%16-19r]"},
9823d8817e4Smiod {ARM_EXT_V6T2, 0xfb000000, 0xfff000f0, "mla\t%8-11r, %16-19r, %0-3r, %12-15r"},
9833d8817e4Smiod {ARM_EXT_V6T2, 0xfb000010, 0xfff000f0, "mls\t%8-11r, %16-19r, %0-3r, %12-15r"},
9843d8817e4Smiod {ARM_EXT_V6T2, 0xfb700000, 0xfff000f0, "usada8\t%8-11r, %16-19r, %0-3r, %12-15r"},
9853d8817e4Smiod {ARM_EXT_V6T2, 0xfb800000, 0xfff000f0, "smull\t%12-15r, %8-11r, %16-19r, %0-3r"},
9863d8817e4Smiod {ARM_EXT_V6T2, 0xfba00000, 0xfff000f0, "umull\t%12-15r, %8-11r, %16-19r, %0-3r"},
9873d8817e4Smiod {ARM_EXT_V6T2, 0xfbc00000, 0xfff000f0, "smlal\t%12-15r, %8-11r, %16-19r, %0-3r"},
9883d8817e4Smiod {ARM_EXT_V6T2, 0xfbe00000, 0xfff000f0, "umlal\t%12-15r, %8-11r, %16-19r, %0-3r"},
9893d8817e4Smiod {ARM_EXT_V6T2, 0xfbe00060, 0xfff000f0, "umaal\t%12-15r, %8-11r, %16-19r, %0-3r"},
9903d8817e4Smiod {ARM_EXT_V6T2, 0xe8500f00, 0xfff00f00, "ldrex\t%12-15r, [%16-19r, #%0-7W]"},
9913d8817e4Smiod {ARM_EXT_V6T2, 0xf7f08000, 0xfff0f000, "smc\t%K"},
9923d8817e4Smiod {ARM_EXT_V6T2, 0xf04f0000, 0xfbef8000, "mov%20's.w\t%8-11r, %M"},
9933d8817e4Smiod {ARM_EXT_V6T2, 0xf06f0000, 0xfbef8000, "mvn%20's.w\t%8-11r, %M"},
9943d8817e4Smiod {ARM_EXT_V6T2, 0xf810f000, 0xff70f000, "pld\t%a"},
9953d8817e4Smiod {ARM_EXT_V6T2, 0xfb200000, 0xfff000e0, "smlad%4'x\t%8-11r, %16-19r, %0-3r, %12-15r"},
9963d8817e4Smiod {ARM_EXT_V6T2, 0xfb300000, 0xfff000e0, "smlaw%4?tb\t%8-11r, %16-19r, %0-3r, %12-15r"},
9973d8817e4Smiod {ARM_EXT_V6T2, 0xfb400000, 0xfff000e0, "smlsd%4'x\t%8-11r, %16-19r, %0-3r, %12-15r"},
9983d8817e4Smiod {ARM_EXT_V6T2, 0xfb500000, 0xfff000e0, "smmla%4'r\t%8-11r, %16-19r, %0-3r, %12-15r"},
9993d8817e4Smiod {ARM_EXT_V6T2, 0xfb600000, 0xfff000e0, "smmls%4'r\t%8-11r, %16-19r, %0-3r, %12-15r"},
10003d8817e4Smiod {ARM_EXT_V6T2, 0xfbc000c0, 0xfff000e0, "smlald%4'x\t%12-15r, %8-11r, %16-19r, %0-3r"},
10013d8817e4Smiod {ARM_EXT_V6T2, 0xfbd000c0, 0xfff000e0, "smlsld%4'x\t%12-15r, %8-11r, %16-19r, %0-3r"},
10023d8817e4Smiod {ARM_EXT_V6T2, 0xeac00000, 0xfff08030, "pkhbt\t%8-11r, %16-19r, %S"},
10033d8817e4Smiod {ARM_EXT_V6T2, 0xeac00020, 0xfff08030, "pkhtb\t%8-11r, %16-19r, %S"},
10043d8817e4Smiod {ARM_EXT_V6T2, 0xf3400000, 0xfff08020, "sbfx\t%8-11r, %16-19r, %F"},
10053d8817e4Smiod {ARM_EXT_V6T2, 0xf3c00000, 0xfff08020, "ubfx\t%8-11r, %16-19r, %F"},
10063d8817e4Smiod {ARM_EXT_V6T2, 0xf8000e00, 0xff900f00, "str%wt\t%12-15r, %a"},
10073d8817e4Smiod {ARM_EXT_V6T2, 0xfb100000, 0xfff000c0, "smla%5?tb%4?tb\t%8-11r, %16-19r, %0-3r, %12-15r"},
10083d8817e4Smiod {ARM_EXT_V6T2, 0xfbc00080, 0xfff000c0, "smlal%5?tb%4?tb\t%12-15r, %8-11r, %16-19r, %0-3r"},
10093d8817e4Smiod {ARM_EXT_V6T2, 0xf3600000, 0xfff08020, "bfi\t%8-11r, %16-19r, %E"},
10103d8817e4Smiod {ARM_EXT_V6T2, 0xf8100e00, 0xfe900f00, "ldr%wt\t%12-15r, %a"},
10113d8817e4Smiod {ARM_EXT_V6T2, 0xf3000000, 0xffd08020, "ssat\t%8-11r, #%0-4d, %16-19r%s"},
10123d8817e4Smiod {ARM_EXT_V6T2, 0xf3800000, 0xffd08020, "usat\t%8-11r, #%0-4d, %16-19r%s"},
10133d8817e4Smiod {ARM_EXT_V6T2, 0xf2000000, 0xfbf08000, "addw\t%8-11r, %16-19r, %I"},
10143d8817e4Smiod {ARM_EXT_V6T2, 0xf2400000, 0xfbf08000, "movw\t%8-11r, %J"},
10153d8817e4Smiod {ARM_EXT_V6T2, 0xf2a00000, 0xfbf08000, "subw\t%8-11r, %16-19r, %I"},
10163d8817e4Smiod {ARM_EXT_V6T2, 0xf2c00000, 0xfbf08000, "movt\t%8-11r, %J"},
10173d8817e4Smiod {ARM_EXT_V6T2, 0xea000000, 0xffe08000, "and%20's.w\t%8-11r, %16-19r, %S"},
10183d8817e4Smiod {ARM_EXT_V6T2, 0xea200000, 0xffe08000, "bic%20's.w\t%8-11r, %16-19r, %S"},
10193d8817e4Smiod {ARM_EXT_V6T2, 0xea400000, 0xffe08000, "orr%20's.w\t%8-11r, %16-19r, %S"},
10203d8817e4Smiod {ARM_EXT_V6T2, 0xea600000, 0xffe08000, "orn%20's\t%8-11r, %16-19r, %S"},
10213d8817e4Smiod {ARM_EXT_V6T2, 0xea800000, 0xffe08000, "eor%20's.w\t%8-11r, %16-19r, %S"},
10223d8817e4Smiod {ARM_EXT_V6T2, 0xeb000000, 0xffe08000, "add%20's.w\t%8-11r, %16-19r, %S"},
10233d8817e4Smiod {ARM_EXT_V6T2, 0xeb400000, 0xffe08000, "adc%20's.w\t%8-11r, %16-19r, %S"},
10243d8817e4Smiod {ARM_EXT_V6T2, 0xeb600000, 0xffe08000, "sbc%20's.w\t%8-11r, %16-19r, %S"},
10253d8817e4Smiod {ARM_EXT_V6T2, 0xeba00000, 0xffe08000, "sub%20's.w\t%8-11r, %16-19r, %S"},
10263d8817e4Smiod {ARM_EXT_V6T2, 0xebc00000, 0xffe08000, "rsb%20's\t%8-11r, %16-19r, %S"},
10273d8817e4Smiod {ARM_EXT_V6T2, 0xe8400000, 0xfff00000, "strex\t%8-11r, %12-15r, [%16-19r, #%0-7W]"},
10283d8817e4Smiod {ARM_EXT_V6T2, 0xf0000000, 0xfbe08000, "and%20's.w\t%8-11r, %16-19r, %M"},
10293d8817e4Smiod {ARM_EXT_V6T2, 0xf0200000, 0xfbe08000, "bic%20's.w\t%8-11r, %16-19r, %M"},
10303d8817e4Smiod {ARM_EXT_V6T2, 0xf0400000, 0xfbe08000, "orr%20's.w\t%8-11r, %16-19r, %M"},
10313d8817e4Smiod {ARM_EXT_V6T2, 0xf0600000, 0xfbe08000, "orn%20's\t%8-11r, %16-19r, %M"},
10323d8817e4Smiod {ARM_EXT_V6T2, 0xf0800000, 0xfbe08000, "eor%20's.w\t%8-11r, %16-19r, %M"},
10333d8817e4Smiod {ARM_EXT_V6T2, 0xf1000000, 0xfbe08000, "add%20's.w\t%8-11r, %16-19r, %M"},
10343d8817e4Smiod {ARM_EXT_V6T2, 0xf1400000, 0xfbe08000, "adc%20's.w\t%8-11r, %16-19r, %M"},
10353d8817e4Smiod {ARM_EXT_V6T2, 0xf1600000, 0xfbe08000, "sbc%20's.w\t%8-11r, %16-19r, %M"},
10363d8817e4Smiod {ARM_EXT_V6T2, 0xf1a00000, 0xfbe08000, "sub%20's.w\t%8-11r, %16-19r, %M"},
10373d8817e4Smiod {ARM_EXT_V6T2, 0xf1c00000, 0xfbe08000, "rsb%20's\t%8-11r, %16-19r, %M"},
10383d8817e4Smiod {ARM_EXT_V6T2, 0xe8800000, 0xffd00000, "stmia.w\t%16-19r%21'!, %m"},
10393d8817e4Smiod {ARM_EXT_V6T2, 0xe8900000, 0xffd00000, "ldmia.w\t%16-19r%21'!, %m"},
10403d8817e4Smiod {ARM_EXT_V6T2, 0xe9000000, 0xffd00000, "stmdb\t%16-19r%21'!, %m"},
10413d8817e4Smiod {ARM_EXT_V6T2, 0xe9100000, 0xffd00000, "ldmdb\t%16-19r%21'!, %m"},
10423d8817e4Smiod {ARM_EXT_V6T2, 0xe9c00000, 0xffd000ff, "strd\t%12-15r, %8-11r, [%16-19r]"},
10433d8817e4Smiod {ARM_EXT_V6T2, 0xe9d00000, 0xffd000ff, "ldrd\t%12-15r, %8-11r, [%16-19r]"},
10443d8817e4Smiod {ARM_EXT_V6T2, 0xe9400000, 0xff500000, "strd\t%12-15r, %8-11r, [%16-19r, #%23`-%0-7W]"},
10453d8817e4Smiod {ARM_EXT_V6T2, 0xe9500000, 0xff500000, "ldrd\t%12-15r, %8-11r, [%16-19r, #%23`-%0-7W]"},
10463d8817e4Smiod {ARM_EXT_V6T2, 0xf8000000, 0xff100000, "str%w.w\t%12-15r, %a"},
10473d8817e4Smiod {ARM_EXT_V6T2, 0xf8100000, 0xfe100000, "ldr%w.w\t%12-15r, %a"},
10483d8817e4Smiod
10493d8817e4Smiod /* Filter out Bcc with cond=E or F, which are used for other instructions. */
10503d8817e4Smiod {ARM_EXT_V6T2, 0xf3c08000, 0xfbc0d000, "undefined (bcc, cond=0xF)"},
10513d8817e4Smiod {ARM_EXT_V6T2, 0xf3808000, 0xfbc0d000, "undefined (bcc, cond=0xE)"},
10523d8817e4Smiod {ARM_EXT_V6T2, 0xf0008000, 0xf800d000, "b%22-25c.w\t%b"},
10533d8817e4Smiod {ARM_EXT_V6T2, 0xf0009000, 0xf800d000, "b.w\t%B"},
10543d8817e4Smiod
10553d8817e4Smiod /* These have been 32-bit since the invention of Thumb. */
10563d8817e4Smiod {ARM_EXT_V4T, 0xf000c000, 0xf800d000, "blx\t%B"},
10573d8817e4Smiod {ARM_EXT_V4T, 0xf000d000, 0xf800d000, "bl\t%B"},
10583d8817e4Smiod
10593d8817e4Smiod /* Fallback. */
10603d8817e4Smiod {ARM_EXT_V1, 0x00000000, 0x00000000, "undefined"},
10613d8817e4Smiod {0, 0, 0, 0}
10623d8817e4Smiod };
10633d8817e4Smiod
10643d8817e4Smiod static const char *const arm_conditional[] =
10653d8817e4Smiod {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
10663d8817e4Smiod "hi", "ls", "ge", "lt", "gt", "le", "", "<und>"};
10673d8817e4Smiod
10683d8817e4Smiod static const char *const arm_fp_const[] =
10693d8817e4Smiod {"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
10703d8817e4Smiod
10713d8817e4Smiod static const char *const arm_shift[] =
10723d8817e4Smiod {"lsl", "lsr", "asr", "ror"};
10733d8817e4Smiod
10743d8817e4Smiod typedef struct
10753d8817e4Smiod {
10763d8817e4Smiod const char *name;
10773d8817e4Smiod const char *description;
10783d8817e4Smiod const char *reg_names[16];
10793d8817e4Smiod }
10803d8817e4Smiod arm_regname;
10813d8817e4Smiod
10823d8817e4Smiod static const arm_regname regnames[] =
10833d8817e4Smiod {
10843d8817e4Smiod { "raw" , "Select raw register names",
10853d8817e4Smiod { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}},
10863d8817e4Smiod { "gcc", "Select register names used by GCC",
10873d8817e4Smiod { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" }},
10883d8817e4Smiod { "std", "Select register names used in ARM's ISA documentation",
10893d8817e4Smiod { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }},
10903d8817e4Smiod { "apcs", "Select register names used in the APCS",
10913d8817e4Smiod { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl", "fp", "ip", "sp", "lr", "pc" }},
10923d8817e4Smiod { "atpcs", "Select register names used in the ATPCS",
10933d8817e4Smiod { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "IP", "SP", "LR", "PC" }},
10943d8817e4Smiod { "special-atpcs", "Select special register names used in the ATPCS",
10953d8817e4Smiod { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }},
10963d8817e4Smiod };
10973d8817e4Smiod
10983d8817e4Smiod static const char *const iwmmxt_wwnames[] =
10993d8817e4Smiod {"b", "h", "w", "d"};
11003d8817e4Smiod
11013d8817e4Smiod static const char *const iwmmxt_wwssnames[] =
11023d8817e4Smiod {"b", "bus", "b", "bss",
11033d8817e4Smiod "h", "hus", "h", "hss",
11043d8817e4Smiod "w", "wus", "w", "wss",
11053d8817e4Smiod "d", "dus", "d", "dss"
11063d8817e4Smiod };
11073d8817e4Smiod
11083d8817e4Smiod static const char *const iwmmxt_regnames[] =
11093d8817e4Smiod { "wr0", "wr1", "wr2", "wr3", "wr4", "wr5", "wr6", "wr7",
11103d8817e4Smiod "wr8", "wr9", "wr10", "wr11", "wr12", "wr13", "wr14", "wr15"
11113d8817e4Smiod };
11123d8817e4Smiod
11133d8817e4Smiod static const char *const iwmmxt_cregnames[] =
11143d8817e4Smiod { "wcid", "wcon", "wcssf", "wcasf", "reserved", "reserved", "reserved", "reserved",
11153d8817e4Smiod "wcgr0", "wcgr1", "wcgr2", "wcgr3", "reserved", "reserved", "reserved", "reserved"
11163d8817e4Smiod };
11173d8817e4Smiod
11183d8817e4Smiod /* Default to GCC register name set. */
11193d8817e4Smiod static unsigned int regname_selected = 1;
11203d8817e4Smiod
11213d8817e4Smiod #define NUM_ARM_REGNAMES NUM_ELEM (regnames)
11223d8817e4Smiod #define arm_regnames regnames[regname_selected].reg_names
11233d8817e4Smiod
11243d8817e4Smiod static bfd_boolean force_thumb = FALSE;
11253d8817e4Smiod
11263d8817e4Smiod
11273d8817e4Smiod /* Functions. */
11283d8817e4Smiod int
get_arm_regname_num_options(void)11293d8817e4Smiod get_arm_regname_num_options (void)
11303d8817e4Smiod {
11313d8817e4Smiod return NUM_ARM_REGNAMES;
11323d8817e4Smiod }
11333d8817e4Smiod
11343d8817e4Smiod int
set_arm_regname_option(int option)11353d8817e4Smiod set_arm_regname_option (int option)
11363d8817e4Smiod {
11373d8817e4Smiod int old = regname_selected;
11383d8817e4Smiod regname_selected = option;
11393d8817e4Smiod return old;
11403d8817e4Smiod }
11413d8817e4Smiod
11423d8817e4Smiod int
get_arm_regnames(int option,const char ** setname,const char ** setdescription,const char * const ** register_names)11433d8817e4Smiod get_arm_regnames (int option, const char **setname, const char **setdescription,
11443d8817e4Smiod const char *const **register_names)
11453d8817e4Smiod {
11463d8817e4Smiod *setname = regnames[option].name;
11473d8817e4Smiod *setdescription = regnames[option].description;
11483d8817e4Smiod *register_names = regnames[option].reg_names;
11493d8817e4Smiod return 16;
11503d8817e4Smiod }
11513d8817e4Smiod
11523d8817e4Smiod static void
arm_decode_shift(long given,fprintf_ftype func,void * stream)11533d8817e4Smiod arm_decode_shift (long given, fprintf_ftype func, void *stream)
11543d8817e4Smiod {
11553d8817e4Smiod func (stream, "%s", arm_regnames[given & 0xf]);
11563d8817e4Smiod
11573d8817e4Smiod if ((given & 0xff0) != 0)
11583d8817e4Smiod {
11593d8817e4Smiod if ((given & 0x10) == 0)
11603d8817e4Smiod {
11613d8817e4Smiod int amount = (given & 0xf80) >> 7;
11623d8817e4Smiod int shift = (given & 0x60) >> 5;
11633d8817e4Smiod
11643d8817e4Smiod if (amount == 0)
11653d8817e4Smiod {
11663d8817e4Smiod if (shift == 3)
11673d8817e4Smiod {
11683d8817e4Smiod func (stream, ", rrx");
11693d8817e4Smiod return;
11703d8817e4Smiod }
11713d8817e4Smiod
11723d8817e4Smiod amount = 32;
11733d8817e4Smiod }
11743d8817e4Smiod
11753d8817e4Smiod func (stream, ", %s #%d", arm_shift[shift], amount);
11763d8817e4Smiod }
11773d8817e4Smiod else
11783d8817e4Smiod func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5],
11793d8817e4Smiod arm_regnames[(given & 0xf00) >> 8]);
11803d8817e4Smiod }
11813d8817e4Smiod }
11823d8817e4Smiod
11833d8817e4Smiod /* Print one coprocessor instruction on INFO->STREAM.
11843d8817e4Smiod Return TRUE if the instuction matched, FALSE if this is not a
11853d8817e4Smiod recognised coprocessor instruction. */
11863d8817e4Smiod
11873d8817e4Smiod static bfd_boolean
print_insn_coprocessor(struct disassemble_info * info,long given,bfd_boolean thumb)11883d8817e4Smiod print_insn_coprocessor (struct disassemble_info *info, long given,
11893d8817e4Smiod bfd_boolean thumb)
11903d8817e4Smiod {
11913d8817e4Smiod const struct opcode32 *insn;
11923d8817e4Smiod void *stream = info->stream;
11933d8817e4Smiod fprintf_ftype func = info->fprintf_func;
11943d8817e4Smiod unsigned long mask;
11953d8817e4Smiod unsigned long value;
11963d8817e4Smiod
11973d8817e4Smiod for (insn = coprocessor_opcodes; insn->assembler; insn++)
11983d8817e4Smiod {
11993d8817e4Smiod if (insn->value == FIRST_IWMMXT_INSN
12003d8817e4Smiod && info->mach != bfd_mach_arm_XScale
12013d8817e4Smiod && info->mach != bfd_mach_arm_iWMMXt)
12023d8817e4Smiod insn = insn + IWMMXT_INSN_COUNT;
12033d8817e4Smiod
12043d8817e4Smiod mask = insn->mask;
12053d8817e4Smiod value = insn->value;
12063d8817e4Smiod if (thumb)
12073d8817e4Smiod {
12083d8817e4Smiod /* The high 4 bits are 0xe for Arm conditional instructions, and
12093d8817e4Smiod 0xe for arm unconditional instructions. The rest of the
12103d8817e4Smiod encoding is the same. */
12113d8817e4Smiod mask |= 0xf0000000;
12123d8817e4Smiod value |= 0xe0000000;
12133d8817e4Smiod }
12143d8817e4Smiod else
12153d8817e4Smiod {
12163d8817e4Smiod /* Only match unconditional instuctions against unconditional
12173d8817e4Smiod patterns. */
12183d8817e4Smiod if ((given & 0xf0000000) == 0xf0000000)
12193d8817e4Smiod mask |= 0xf0000000;
12203d8817e4Smiod }
12213d8817e4Smiod if ((given & mask) == value)
12223d8817e4Smiod {
12233d8817e4Smiod const char *c;
12243d8817e4Smiod
12253d8817e4Smiod for (c = insn->assembler; *c; c++)
12263d8817e4Smiod {
12273d8817e4Smiod if (*c == '%')
12283d8817e4Smiod {
12293d8817e4Smiod switch (*++c)
12303d8817e4Smiod {
12313d8817e4Smiod case '%':
12323d8817e4Smiod func (stream, "%%");
12333d8817e4Smiod break;
12343d8817e4Smiod
12353d8817e4Smiod case 'A':
12363d8817e4Smiod func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
12373d8817e4Smiod
12383d8817e4Smiod if ((given & (1 << 24)) != 0)
12393d8817e4Smiod {
12403d8817e4Smiod int offset = given & 0xff;
12413d8817e4Smiod
12423d8817e4Smiod if (offset)
12433d8817e4Smiod func (stream, ", #%s%d]%s",
12443d8817e4Smiod ((given & 0x00800000) == 0 ? "-" : ""),
12453d8817e4Smiod offset * 4,
12463d8817e4Smiod ((given & 0x00200000) != 0 ? "!" : ""));
12473d8817e4Smiod else
12483d8817e4Smiod func (stream, "]");
12493d8817e4Smiod }
12503d8817e4Smiod else
12513d8817e4Smiod {
12523d8817e4Smiod int offset = given & 0xff;
12533d8817e4Smiod
12543d8817e4Smiod func (stream, "]");
12553d8817e4Smiod
12563d8817e4Smiod if (given & (1 << 21))
12573d8817e4Smiod {
12583d8817e4Smiod if (offset)
12593d8817e4Smiod func (stream, ", #%s%d",
12603d8817e4Smiod ((given & 0x00800000) == 0 ? "-" : ""),
12613d8817e4Smiod offset * 4);
12623d8817e4Smiod }
12633d8817e4Smiod else
12643d8817e4Smiod func (stream, ", {%d}", offset);
12653d8817e4Smiod }
12663d8817e4Smiod break;
12673d8817e4Smiod
12683d8817e4Smiod case 'c':
12693d8817e4Smiod func (stream, "%s",
12703d8817e4Smiod arm_conditional [(given >> 28) & 0xf]);
12713d8817e4Smiod break;
12723d8817e4Smiod
12733d8817e4Smiod case 'I':
12743d8817e4Smiod /* Print a Cirrus/DSP shift immediate. */
12753d8817e4Smiod /* Immediates are 7bit signed ints with bits 0..3 in
12763d8817e4Smiod bits 0..3 of opcode and bits 4..6 in bits 5..7
12773d8817e4Smiod of opcode. */
12783d8817e4Smiod {
12793d8817e4Smiod int imm;
12803d8817e4Smiod
12813d8817e4Smiod imm = (given & 0xf) | ((given & 0xe0) >> 1);
12823d8817e4Smiod
12833d8817e4Smiod /* Is ``imm'' a negative number? */
12843d8817e4Smiod if (imm & 0x40)
12853d8817e4Smiod imm |= (-1 << 7);
12863d8817e4Smiod
12873d8817e4Smiod func (stream, "%d", imm);
12883d8817e4Smiod }
12893d8817e4Smiod
12903d8817e4Smiod break;
12913d8817e4Smiod
12923d8817e4Smiod case 'F':
12933d8817e4Smiod switch (given & 0x00408000)
12943d8817e4Smiod {
12953d8817e4Smiod case 0:
12963d8817e4Smiod func (stream, "4");
12973d8817e4Smiod break;
12983d8817e4Smiod case 0x8000:
12993d8817e4Smiod func (stream, "1");
13003d8817e4Smiod break;
13013d8817e4Smiod case 0x00400000:
13023d8817e4Smiod func (stream, "2");
13033d8817e4Smiod break;
13043d8817e4Smiod default:
13053d8817e4Smiod func (stream, "3");
13063d8817e4Smiod }
13073d8817e4Smiod break;
13083d8817e4Smiod
13093d8817e4Smiod case 'P':
13103d8817e4Smiod switch (given & 0x00080080)
13113d8817e4Smiod {
13123d8817e4Smiod case 0:
13133d8817e4Smiod func (stream, "s");
13143d8817e4Smiod break;
13153d8817e4Smiod case 0x80:
13163d8817e4Smiod func (stream, "d");
13173d8817e4Smiod break;
13183d8817e4Smiod case 0x00080000:
13193d8817e4Smiod func (stream, "e");
13203d8817e4Smiod break;
13213d8817e4Smiod default:
13223d8817e4Smiod func (stream, _("<illegal precision>"));
13233d8817e4Smiod break;
13243d8817e4Smiod }
13253d8817e4Smiod break;
13263d8817e4Smiod case 'Q':
13273d8817e4Smiod switch (given & 0x00408000)
13283d8817e4Smiod {
13293d8817e4Smiod case 0:
13303d8817e4Smiod func (stream, "s");
13313d8817e4Smiod break;
13323d8817e4Smiod case 0x8000:
13333d8817e4Smiod func (stream, "d");
13343d8817e4Smiod break;
13353d8817e4Smiod case 0x00400000:
13363d8817e4Smiod func (stream, "e");
13373d8817e4Smiod break;
13383d8817e4Smiod default:
13393d8817e4Smiod func (stream, "p");
13403d8817e4Smiod break;
13413d8817e4Smiod }
13423d8817e4Smiod break;
13433d8817e4Smiod case 'R':
13443d8817e4Smiod switch (given & 0x60)
13453d8817e4Smiod {
13463d8817e4Smiod case 0:
13473d8817e4Smiod break;
13483d8817e4Smiod case 0x20:
13493d8817e4Smiod func (stream, "p");
13503d8817e4Smiod break;
13513d8817e4Smiod case 0x40:
13523d8817e4Smiod func (stream, "m");
13533d8817e4Smiod break;
13543d8817e4Smiod default:
13553d8817e4Smiod func (stream, "z");
13563d8817e4Smiod break;
13573d8817e4Smiod }
13583d8817e4Smiod break;
13593d8817e4Smiod
13603d8817e4Smiod case '0': case '1': case '2': case '3': case '4':
13613d8817e4Smiod case '5': case '6': case '7': case '8': case '9':
13623d8817e4Smiod {
13633d8817e4Smiod int bitstart = *c++ - '0';
13643d8817e4Smiod int bitend = 0;
13653d8817e4Smiod while (*c >= '0' && *c <= '9')
13663d8817e4Smiod bitstart = (bitstart * 10) + *c++ - '0';
13673d8817e4Smiod
13683d8817e4Smiod switch (*c)
13693d8817e4Smiod {
13703d8817e4Smiod case '-':
13713d8817e4Smiod c++;
13723d8817e4Smiod
13733d8817e4Smiod while (*c >= '0' && *c <= '9')
13743d8817e4Smiod bitend = (bitend * 10) + *c++ - '0';
13753d8817e4Smiod
13763d8817e4Smiod if (!bitend)
13773d8817e4Smiod abort ();
13783d8817e4Smiod
13793d8817e4Smiod switch (*c)
13803d8817e4Smiod {
13813d8817e4Smiod case 'r':
13823d8817e4Smiod {
13833d8817e4Smiod long reg;
13843d8817e4Smiod
13853d8817e4Smiod reg = given >> bitstart;
13863d8817e4Smiod reg &= (2 << (bitend - bitstart)) - 1;
13873d8817e4Smiod
13883d8817e4Smiod func (stream, "%s", arm_regnames[reg]);
13893d8817e4Smiod }
13903d8817e4Smiod break;
13913d8817e4Smiod case 'd':
13923d8817e4Smiod {
13933d8817e4Smiod long reg;
13943d8817e4Smiod
13953d8817e4Smiod reg = given >> bitstart;
13963d8817e4Smiod reg &= (2 << (bitend - bitstart)) - 1;
13973d8817e4Smiod
13983d8817e4Smiod func (stream, "%ld", reg);
13993d8817e4Smiod }
14003d8817e4Smiod break;
14013d8817e4Smiod case 'f':
14023d8817e4Smiod {
14033d8817e4Smiod long reg;
14043d8817e4Smiod
14053d8817e4Smiod reg = given >> bitstart;
14063d8817e4Smiod reg &= (2 << (bitend - bitstart)) - 1;
14073d8817e4Smiod
14083d8817e4Smiod if (reg > 7)
14093d8817e4Smiod func (stream, "#%s",
14103d8817e4Smiod arm_fp_const[reg & 7]);
14113d8817e4Smiod else
14123d8817e4Smiod func (stream, "f%ld", reg);
14133d8817e4Smiod }
14143d8817e4Smiod break;
14153d8817e4Smiod
14163d8817e4Smiod case 'w':
14173d8817e4Smiod {
14183d8817e4Smiod long reg;
14193d8817e4Smiod
14203d8817e4Smiod if (bitstart != bitend)
14213d8817e4Smiod {
14223d8817e4Smiod reg = given >> bitstart;
14233d8817e4Smiod reg &= (2 << (bitend - bitstart)) - 1;
14243d8817e4Smiod if (bitend - bitstart == 1)
14253d8817e4Smiod func (stream, "%s", iwmmxt_wwnames[reg]);
14263d8817e4Smiod else
14273d8817e4Smiod func (stream, "%s", iwmmxt_wwssnames[reg]);
14283d8817e4Smiod }
14293d8817e4Smiod else
14303d8817e4Smiod {
14313d8817e4Smiod reg = (((given >> 8) & 0x1) |
14323d8817e4Smiod ((given >> 22) & 0x1));
14333d8817e4Smiod func (stream, "%s", iwmmxt_wwnames[reg]);
14343d8817e4Smiod }
14353d8817e4Smiod }
14363d8817e4Smiod break;
14373d8817e4Smiod
14383d8817e4Smiod case 'g':
14393d8817e4Smiod {
14403d8817e4Smiod long reg;
14413d8817e4Smiod reg = given >> bitstart;
14423d8817e4Smiod reg &= (2 << (bitend - bitstart)) - 1;
14433d8817e4Smiod func (stream, "%s", iwmmxt_regnames[reg]);
14443d8817e4Smiod }
14453d8817e4Smiod break;
14463d8817e4Smiod
14473d8817e4Smiod case 'G':
14483d8817e4Smiod {
14493d8817e4Smiod long reg;
14503d8817e4Smiod reg = given >> bitstart;
14513d8817e4Smiod reg &= (2 << (bitend - bitstart)) - 1;
14523d8817e4Smiod func (stream, "%s", iwmmxt_cregnames[reg]);
14533d8817e4Smiod }
14543d8817e4Smiod break;
14553d8817e4Smiod
14563d8817e4Smiod default:
14573d8817e4Smiod abort ();
14583d8817e4Smiod }
14593d8817e4Smiod break;
14603d8817e4Smiod
14613d8817e4Smiod case 'y':
14623d8817e4Smiod case 'z':
14633d8817e4Smiod {
14643d8817e4Smiod int single = *c == 'y';
14653d8817e4Smiod int regno;
14663d8817e4Smiod
14673d8817e4Smiod switch (bitstart)
14683d8817e4Smiod {
14693d8817e4Smiod case 4: /* Sm pair */
14703d8817e4Smiod func (stream, "{");
14713d8817e4Smiod /* Fall through. */
14723d8817e4Smiod case 0: /* Sm, Dm */
14733d8817e4Smiod regno = given & 0x0000000f;
14743d8817e4Smiod if (single)
14753d8817e4Smiod {
14763d8817e4Smiod regno <<= 1;
14773d8817e4Smiod regno += (given >> 5) & 1;
14783d8817e4Smiod }
14793d8817e4Smiod break;
14803d8817e4Smiod
14813d8817e4Smiod case 1: /* Sd, Dd */
14823d8817e4Smiod regno = (given >> 12) & 0x0000000f;
14833d8817e4Smiod if (single)
14843d8817e4Smiod {
14853d8817e4Smiod regno <<= 1;
14863d8817e4Smiod regno += (given >> 22) & 1;
14873d8817e4Smiod }
14883d8817e4Smiod break;
14893d8817e4Smiod
14903d8817e4Smiod case 2: /* Sn, Dn */
14913d8817e4Smiod regno = (given >> 16) & 0x0000000f;
14923d8817e4Smiod if (single)
14933d8817e4Smiod {
14943d8817e4Smiod regno <<= 1;
14953d8817e4Smiod regno += (given >> 7) & 1;
14963d8817e4Smiod }
14973d8817e4Smiod break;
14983d8817e4Smiod
14993d8817e4Smiod case 3: /* List */
15003d8817e4Smiod func (stream, "{");
15013d8817e4Smiod regno = (given >> 12) & 0x0000000f;
15023d8817e4Smiod if (single)
15033d8817e4Smiod {
15043d8817e4Smiod regno <<= 1;
15053d8817e4Smiod regno += (given >> 22) & 1;
15063d8817e4Smiod }
15073d8817e4Smiod break;
15083d8817e4Smiod
15093d8817e4Smiod
15103d8817e4Smiod default:
15113d8817e4Smiod abort ();
15123d8817e4Smiod }
15133d8817e4Smiod
15143d8817e4Smiod func (stream, "%c%d", single ? 's' : 'd', regno);
15153d8817e4Smiod
15163d8817e4Smiod if (bitstart == 3)
15173d8817e4Smiod {
15183d8817e4Smiod int count = given & 0xff;
15193d8817e4Smiod
15203d8817e4Smiod if (single == 0)
15213d8817e4Smiod count >>= 1;
15223d8817e4Smiod
15233d8817e4Smiod if (--count)
15243d8817e4Smiod {
15253d8817e4Smiod func (stream, "-%c%d",
15263d8817e4Smiod single ? 's' : 'd',
15273d8817e4Smiod regno + count);
15283d8817e4Smiod }
15293d8817e4Smiod
15303d8817e4Smiod func (stream, "}");
15313d8817e4Smiod }
15323d8817e4Smiod else if (bitstart == 4)
15333d8817e4Smiod func (stream, ", %c%d}", single ? 's' : 'd',
15343d8817e4Smiod regno + 1);
15353d8817e4Smiod
15363d8817e4Smiod break;
15373d8817e4Smiod }
15383d8817e4Smiod
15393d8817e4Smiod break;
15403d8817e4Smiod
15413d8817e4Smiod case '`':
15423d8817e4Smiod c++;
15433d8817e4Smiod if ((given & (1 << bitstart)) == 0)
15443d8817e4Smiod func (stream, "%c", *c);
15453d8817e4Smiod break;
15463d8817e4Smiod case '\'':
15473d8817e4Smiod c++;
15483d8817e4Smiod if ((given & (1 << bitstart)) != 0)
15493d8817e4Smiod func (stream, "%c", *c);
15503d8817e4Smiod break;
15513d8817e4Smiod case '?':
15523d8817e4Smiod ++c;
15533d8817e4Smiod if ((given & (1 << bitstart)) != 0)
15543d8817e4Smiod func (stream, "%c", *c++);
15553d8817e4Smiod else
15563d8817e4Smiod func (stream, "%c", *++c);
15573d8817e4Smiod break;
15583d8817e4Smiod default:
15593d8817e4Smiod abort ();
15603d8817e4Smiod }
15613d8817e4Smiod break;
15623d8817e4Smiod
15633d8817e4Smiod case 'L':
15643d8817e4Smiod switch (given & 0x00400100)
15653d8817e4Smiod {
15663d8817e4Smiod case 0x00000000: func (stream, "b"); break;
15673d8817e4Smiod case 0x00400000: func (stream, "h"); break;
15683d8817e4Smiod case 0x00000100: func (stream, "w"); break;
15693d8817e4Smiod case 0x00400100: func (stream, "d"); break;
15703d8817e4Smiod default:
15713d8817e4Smiod break;
15723d8817e4Smiod }
15733d8817e4Smiod break;
15743d8817e4Smiod
15753d8817e4Smiod case 'Z':
15763d8817e4Smiod {
15773d8817e4Smiod int value;
15783d8817e4Smiod /* given (20, 23) | given (0, 3) */
15793d8817e4Smiod value = ((given >> 16) & 0xf0) | (given & 0xf);
15803d8817e4Smiod func (stream, "%d", value);
15813d8817e4Smiod }
15823d8817e4Smiod break;
15833d8817e4Smiod
15843d8817e4Smiod case 'l':
15853d8817e4Smiod /* This is like the 'A' operator, except that if
15863d8817e4Smiod the width field "M" is zero, then the offset is
15873d8817e4Smiod *not* multiplied by four. */
15883d8817e4Smiod {
15893d8817e4Smiod int offset = given & 0xff;
15903d8817e4Smiod int multiplier = (given & 0x00000100) ? 4 : 1;
15913d8817e4Smiod
15923d8817e4Smiod func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
15933d8817e4Smiod
15943d8817e4Smiod if (offset)
15953d8817e4Smiod {
15963d8817e4Smiod if ((given & 0x01000000) != 0)
15973d8817e4Smiod func (stream, ", #%s%d]%s",
15983d8817e4Smiod ((given & 0x00800000) == 0 ? "-" : ""),
15993d8817e4Smiod offset * multiplier,
16003d8817e4Smiod ((given & 0x00200000) != 0 ? "!" : ""));
16013d8817e4Smiod else
16023d8817e4Smiod func (stream, "], #%s%d",
16033d8817e4Smiod ((given & 0x00800000) == 0 ? "-" : ""),
16043d8817e4Smiod offset * multiplier);
16053d8817e4Smiod }
16063d8817e4Smiod else
16073d8817e4Smiod func (stream, "]");
16083d8817e4Smiod }
16093d8817e4Smiod break;
16103d8817e4Smiod
16113d8817e4Smiod default:
16123d8817e4Smiod abort ();
16133d8817e4Smiod }
16143d8817e4Smiod }
16153d8817e4Smiod }
16163d8817e4Smiod else
16173d8817e4Smiod func (stream, "%c", *c);
16183d8817e4Smiod }
16193d8817e4Smiod return TRUE;
16203d8817e4Smiod }
16213d8817e4Smiod }
16223d8817e4Smiod return FALSE;
16233d8817e4Smiod }
16243d8817e4Smiod
16253d8817e4Smiod static void
print_arm_address(bfd_vma pc,struct disassemble_info * info,long given)16263d8817e4Smiod print_arm_address (bfd_vma pc, struct disassemble_info *info, long given)
16273d8817e4Smiod {
16283d8817e4Smiod void *stream = info->stream;
16293d8817e4Smiod fprintf_ftype func = info->fprintf_func;
16303d8817e4Smiod
16313d8817e4Smiod if (((given & 0x000f0000) == 0x000f0000)
16323d8817e4Smiod && ((given & 0x02000000) == 0))
16333d8817e4Smiod {
16343d8817e4Smiod int offset = given & 0xfff;
16353d8817e4Smiod
16363d8817e4Smiod func (stream, "[pc");
16373d8817e4Smiod
16383d8817e4Smiod if (given & 0x01000000)
16393d8817e4Smiod {
16403d8817e4Smiod if ((given & 0x00800000) == 0)
16413d8817e4Smiod offset = - offset;
16423d8817e4Smiod
16433d8817e4Smiod /* Pre-indexed. */
16443d8817e4Smiod func (stream, ", #%d]", offset);
16453d8817e4Smiod
16463d8817e4Smiod offset += pc + 8;
16473d8817e4Smiod
16483d8817e4Smiod /* Cope with the possibility of write-back
16493d8817e4Smiod being used. Probably a very dangerous thing
16503d8817e4Smiod for the programmer to do, but who are we to
16513d8817e4Smiod argue ? */
16523d8817e4Smiod if (given & 0x00200000)
16533d8817e4Smiod func (stream, "!");
16543d8817e4Smiod }
16553d8817e4Smiod else
16563d8817e4Smiod {
16573d8817e4Smiod /* Post indexed. */
16583d8817e4Smiod func (stream, "], #%d", offset);
16593d8817e4Smiod
16603d8817e4Smiod /* ie ignore the offset. */
16613d8817e4Smiod offset = pc + 8;
16623d8817e4Smiod }
16633d8817e4Smiod
16643d8817e4Smiod func (stream, "\t; ");
16653d8817e4Smiod info->print_address_func (offset, info);
16663d8817e4Smiod }
16673d8817e4Smiod else
16683d8817e4Smiod {
16693d8817e4Smiod func (stream, "[%s",
16703d8817e4Smiod arm_regnames[(given >> 16) & 0xf]);
16713d8817e4Smiod if ((given & 0x01000000) != 0)
16723d8817e4Smiod {
16733d8817e4Smiod if ((given & 0x02000000) == 0)
16743d8817e4Smiod {
16753d8817e4Smiod int offset = given & 0xfff;
16763d8817e4Smiod if (offset)
16773d8817e4Smiod func (stream, ", #%s%d",
16783d8817e4Smiod (((given & 0x00800000) == 0)
16793d8817e4Smiod ? "-" : ""), offset);
16803d8817e4Smiod }
16813d8817e4Smiod else
16823d8817e4Smiod {
16833d8817e4Smiod func (stream, ", %s",
16843d8817e4Smiod (((given & 0x00800000) == 0)
16853d8817e4Smiod ? "-" : ""));
16863d8817e4Smiod arm_decode_shift (given, func, stream);
16873d8817e4Smiod }
16883d8817e4Smiod
16893d8817e4Smiod func (stream, "]%s",
16903d8817e4Smiod ((given & 0x00200000) != 0) ? "!" : "");
16913d8817e4Smiod }
16923d8817e4Smiod else
16933d8817e4Smiod {
16943d8817e4Smiod if ((given & 0x02000000) == 0)
16953d8817e4Smiod {
16963d8817e4Smiod int offset = given & 0xfff;
16973d8817e4Smiod if (offset)
16983d8817e4Smiod func (stream, "], #%s%d",
16993d8817e4Smiod (((given & 0x00800000) == 0)
17003d8817e4Smiod ? "-" : ""), offset);
17013d8817e4Smiod else
17023d8817e4Smiod func (stream, "]");
17033d8817e4Smiod }
17043d8817e4Smiod else
17053d8817e4Smiod {
17063d8817e4Smiod func (stream, "], %s",
17073d8817e4Smiod (((given & 0x00800000) == 0)
17083d8817e4Smiod ? "-" : ""));
17093d8817e4Smiod arm_decode_shift (given, func, stream);
17103d8817e4Smiod }
17113d8817e4Smiod }
17123d8817e4Smiod }
17133d8817e4Smiod }
17143d8817e4Smiod
17153d8817e4Smiod /* Print one ARM instruction from PC on INFO->STREAM. */
17163d8817e4Smiod
17173d8817e4Smiod static void
print_insn_arm(bfd_vma pc,struct disassemble_info * info,long given)17183d8817e4Smiod print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
17193d8817e4Smiod {
17203d8817e4Smiod const struct opcode32 *insn;
17213d8817e4Smiod void *stream = info->stream;
17223d8817e4Smiod fprintf_ftype func = info->fprintf_func;
17233d8817e4Smiod
17243d8817e4Smiod if (print_insn_coprocessor (info, given, FALSE))
17253d8817e4Smiod return;
17263d8817e4Smiod
17273d8817e4Smiod for (insn = arm_opcodes; insn->assembler; insn++)
17283d8817e4Smiod {
17293d8817e4Smiod if (insn->value == FIRST_IWMMXT_INSN
17303d8817e4Smiod && info->mach != bfd_mach_arm_XScale
17313d8817e4Smiod && info->mach != bfd_mach_arm_iWMMXt)
17323d8817e4Smiod insn = insn + IWMMXT_INSN_COUNT;
17333d8817e4Smiod
17343d8817e4Smiod if ((given & insn->mask) == insn->value
17353d8817e4Smiod /* Special case: an instruction with all bits set in the condition field
17363d8817e4Smiod (0xFnnn_nnnn) is only matched if all those bits are set in insn->mask,
17373d8817e4Smiod or by the catchall at the end of the table. */
17383d8817e4Smiod && ((given & 0xF0000000) != 0xF0000000
17393d8817e4Smiod || (insn->mask & 0xF0000000) == 0xF0000000
17403d8817e4Smiod || (insn->mask == 0 && insn->value == 0)))
17413d8817e4Smiod {
17423d8817e4Smiod const char *c;
17433d8817e4Smiod
17443d8817e4Smiod for (c = insn->assembler; *c; c++)
17453d8817e4Smiod {
17463d8817e4Smiod if (*c == '%')
17473d8817e4Smiod {
17483d8817e4Smiod switch (*++c)
17493d8817e4Smiod {
17503d8817e4Smiod case '%':
17513d8817e4Smiod func (stream, "%%");
17523d8817e4Smiod break;
17533d8817e4Smiod
17543d8817e4Smiod case 'a':
17553d8817e4Smiod print_arm_address (pc, info, given);
17563d8817e4Smiod break;
17573d8817e4Smiod
17583d8817e4Smiod case 'P':
17593d8817e4Smiod /* Set P address bit and use normal address
17603d8817e4Smiod printing routine. */
17613d8817e4Smiod print_arm_address (pc, info, given | (1 << 24));
17623d8817e4Smiod break;
17633d8817e4Smiod
17643d8817e4Smiod case 's':
17653d8817e4Smiod if ((given & 0x004f0000) == 0x004f0000)
17663d8817e4Smiod {
17673d8817e4Smiod /* PC relative with immediate offset. */
17683d8817e4Smiod int offset = ((given & 0xf00) >> 4) | (given & 0xf);
17693d8817e4Smiod
17703d8817e4Smiod if ((given & 0x00800000) == 0)
17713d8817e4Smiod offset = -offset;
17723d8817e4Smiod
17733d8817e4Smiod func (stream, "[pc, #%d]\t; ", offset);
17743d8817e4Smiod info->print_address_func (offset + pc + 8, info);
17753d8817e4Smiod }
17763d8817e4Smiod else
17773d8817e4Smiod {
17783d8817e4Smiod func (stream, "[%s",
17793d8817e4Smiod arm_regnames[(given >> 16) & 0xf]);
17803d8817e4Smiod if ((given & 0x01000000) != 0)
17813d8817e4Smiod {
17823d8817e4Smiod /* Pre-indexed. */
17833d8817e4Smiod if ((given & 0x00400000) == 0x00400000)
17843d8817e4Smiod {
17853d8817e4Smiod /* Immediate. */
17863d8817e4Smiod int offset = ((given & 0xf00) >> 4) | (given & 0xf);
17873d8817e4Smiod if (offset)
17883d8817e4Smiod func (stream, ", #%s%d",
17893d8817e4Smiod (((given & 0x00800000) == 0)
17903d8817e4Smiod ? "-" : ""), offset);
17913d8817e4Smiod }
17923d8817e4Smiod else
17933d8817e4Smiod {
17943d8817e4Smiod /* Register. */
17953d8817e4Smiod func (stream, ", %s%s",
17963d8817e4Smiod (((given & 0x00800000) == 0)
17973d8817e4Smiod ? "-" : ""),
17983d8817e4Smiod arm_regnames[given & 0xf]);
17993d8817e4Smiod }
18003d8817e4Smiod
18013d8817e4Smiod func (stream, "]%s",
18023d8817e4Smiod ((given & 0x00200000) != 0) ? "!" : "");
18033d8817e4Smiod }
18043d8817e4Smiod else
18053d8817e4Smiod {
18063d8817e4Smiod /* Post-indexed. */
18073d8817e4Smiod if ((given & 0x00400000) == 0x00400000)
18083d8817e4Smiod {
18093d8817e4Smiod /* Immediate. */
18103d8817e4Smiod int offset = ((given & 0xf00) >> 4) | (given & 0xf);
18113d8817e4Smiod if (offset)
18123d8817e4Smiod func (stream, "], #%s%d",
18133d8817e4Smiod (((given & 0x00800000) == 0)
18143d8817e4Smiod ? "-" : ""), offset);
18153d8817e4Smiod else
18163d8817e4Smiod func (stream, "]");
18173d8817e4Smiod }
18183d8817e4Smiod else
18193d8817e4Smiod {
18203d8817e4Smiod /* Register. */
18213d8817e4Smiod func (stream, "], %s%s",
18223d8817e4Smiod (((given & 0x00800000) == 0)
18233d8817e4Smiod ? "-" : ""),
18243d8817e4Smiod arm_regnames[given & 0xf]);
18253d8817e4Smiod }
18263d8817e4Smiod }
18273d8817e4Smiod }
18283d8817e4Smiod break;
18293d8817e4Smiod
18303d8817e4Smiod case 'b':
18313d8817e4Smiod {
18323d8817e4Smiod int disp = (((given & 0xffffff) ^ 0x800000) - 0x800000);
18333d8817e4Smiod info->print_address_func (disp*4 + pc + 8, info);
18343d8817e4Smiod }
18353d8817e4Smiod break;
18363d8817e4Smiod
18373d8817e4Smiod case 'c':
18383d8817e4Smiod func (stream, "%s",
18393d8817e4Smiod arm_conditional [(given >> 28) & 0xf]);
18403d8817e4Smiod break;
18413d8817e4Smiod
18423d8817e4Smiod case 'm':
18433d8817e4Smiod {
18443d8817e4Smiod int started = 0;
18453d8817e4Smiod int reg;
18463d8817e4Smiod
18473d8817e4Smiod func (stream, "{");
18483d8817e4Smiod for (reg = 0; reg < 16; reg++)
18493d8817e4Smiod if ((given & (1 << reg)) != 0)
18503d8817e4Smiod {
18513d8817e4Smiod if (started)
18523d8817e4Smiod func (stream, ", ");
18533d8817e4Smiod started = 1;
18543d8817e4Smiod func (stream, "%s", arm_regnames[reg]);
18553d8817e4Smiod }
18563d8817e4Smiod func (stream, "}");
18573d8817e4Smiod }
18583d8817e4Smiod break;
18593d8817e4Smiod
18603d8817e4Smiod case 'o':
18613d8817e4Smiod if ((given & 0x02000000) != 0)
18623d8817e4Smiod {
18633d8817e4Smiod int rotate = (given & 0xf00) >> 7;
18643d8817e4Smiod int immed = (given & 0xff);
18653d8817e4Smiod immed = (((immed << (32 - rotate))
18663d8817e4Smiod | (immed >> rotate)) & 0xffffffff);
18673d8817e4Smiod func (stream, "#%d\t; 0x%x", immed, immed);
18683d8817e4Smiod }
18693d8817e4Smiod else
18703d8817e4Smiod arm_decode_shift (given, func, stream);
18713d8817e4Smiod break;
18723d8817e4Smiod
18733d8817e4Smiod case 'p':
18743d8817e4Smiod if ((given & 0x0000f000) == 0x0000f000)
18753d8817e4Smiod func (stream, "p");
18763d8817e4Smiod break;
18773d8817e4Smiod
18783d8817e4Smiod case 't':
18793d8817e4Smiod if ((given & 0x01200000) == 0x00200000)
18803d8817e4Smiod func (stream, "t");
18813d8817e4Smiod break;
18823d8817e4Smiod
18833d8817e4Smiod case 'A':
18843d8817e4Smiod func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
18853d8817e4Smiod
18863d8817e4Smiod if ((given & (1 << 24)) != 0)
18873d8817e4Smiod {
18883d8817e4Smiod int offset = given & 0xff;
18893d8817e4Smiod
18903d8817e4Smiod if (offset)
18913d8817e4Smiod func (stream, ", #%s%d]%s",
18923d8817e4Smiod ((given & 0x00800000) == 0 ? "-" : ""),
18933d8817e4Smiod offset * 4,
18943d8817e4Smiod ((given & 0x00200000) != 0 ? "!" : ""));
18953d8817e4Smiod else
18963d8817e4Smiod func (stream, "]");
18973d8817e4Smiod }
18983d8817e4Smiod else
18993d8817e4Smiod {
19003d8817e4Smiod int offset = given & 0xff;
19013d8817e4Smiod
19023d8817e4Smiod func (stream, "]");
19033d8817e4Smiod
19043d8817e4Smiod if (given & (1 << 21))
19053d8817e4Smiod {
19063d8817e4Smiod if (offset)
19073d8817e4Smiod func (stream, ", #%s%d",
19083d8817e4Smiod ((given & 0x00800000) == 0 ? "-" : ""),
19093d8817e4Smiod offset * 4);
19103d8817e4Smiod }
19113d8817e4Smiod else
19123d8817e4Smiod func (stream, ", {%d}", offset);
19133d8817e4Smiod }
19143d8817e4Smiod break;
19153d8817e4Smiod
19163d8817e4Smiod case 'B':
19173d8817e4Smiod /* Print ARM V5 BLX(1) address: pc+25 bits. */
19183d8817e4Smiod {
19193d8817e4Smiod bfd_vma address;
19203d8817e4Smiod bfd_vma offset = 0;
19213d8817e4Smiod
19223d8817e4Smiod if (given & 0x00800000)
19233d8817e4Smiod /* Is signed, hi bits should be ones. */
19243d8817e4Smiod offset = (-1) ^ 0x00ffffff;
19253d8817e4Smiod
19263d8817e4Smiod /* Offset is (SignExtend(offset field)<<2). */
19273d8817e4Smiod offset += given & 0x00ffffff;
19283d8817e4Smiod offset <<= 2;
19293d8817e4Smiod address = offset + pc + 8;
19303d8817e4Smiod
19313d8817e4Smiod if (given & 0x01000000)
19323d8817e4Smiod /* H bit allows addressing to 2-byte boundaries. */
19333d8817e4Smiod address += 2;
19343d8817e4Smiod
19353d8817e4Smiod info->print_address_func (address, info);
19363d8817e4Smiod }
19373d8817e4Smiod break;
19383d8817e4Smiod
19393d8817e4Smiod case 'C':
19403d8817e4Smiod func (stream, "_");
19413d8817e4Smiod if (given & 0x80000)
19423d8817e4Smiod func (stream, "f");
19433d8817e4Smiod if (given & 0x40000)
19443d8817e4Smiod func (stream, "s");
19453d8817e4Smiod if (given & 0x20000)
19463d8817e4Smiod func (stream, "x");
19473d8817e4Smiod if (given & 0x10000)
19483d8817e4Smiod func (stream, "c");
19493d8817e4Smiod break;
19503d8817e4Smiod
19513d8817e4Smiod case 'U':
19523d8817e4Smiod switch (given & 0xf)
19533d8817e4Smiod {
1954*0f6fdfcdSjsg case 0x2: func(stream, "oshst"); break;
1955*0f6fdfcdSjsg case 0x3: func(stream, "osh"); break;
1956*0f6fdfcdSjsg case 0x6: func(stream, "nshst"); break;
1957*0f6fdfcdSjsg case 0x7: func(stream, "nsh"); break;
1958*0f6fdfcdSjsg case 0xa: func(stream, "ishst"); break;
1959*0f6fdfcdSjsg case 0xb: func(stream, "ish"); break;
19603d8817e4Smiod case 0xe: func(stream, "st"); break;
1961*0f6fdfcdSjsg case 0xf: func(stream, "sy"); break;
19623d8817e4Smiod default:
19633d8817e4Smiod func(stream, "#%d", (int)given & 0xf);
19643d8817e4Smiod break;
19653d8817e4Smiod }
19663d8817e4Smiod break;
19673d8817e4Smiod
19683d8817e4Smiod case '0': case '1': case '2': case '3': case '4':
19693d8817e4Smiod case '5': case '6': case '7': case '8': case '9':
19703d8817e4Smiod {
19713d8817e4Smiod int bitstart = *c++ - '0';
19723d8817e4Smiod int bitend = 0;
19733d8817e4Smiod while (*c >= '0' && *c <= '9')
19743d8817e4Smiod bitstart = (bitstart * 10) + *c++ - '0';
19753d8817e4Smiod
19763d8817e4Smiod switch (*c)
19773d8817e4Smiod {
19783d8817e4Smiod case '-':
19793d8817e4Smiod c++;
19803d8817e4Smiod
19813d8817e4Smiod while (*c >= '0' && *c <= '9')
19823d8817e4Smiod bitend = (bitend * 10) + *c++ - '0';
19833d8817e4Smiod
19843d8817e4Smiod if (!bitend)
19853d8817e4Smiod abort ();
19863d8817e4Smiod
19873d8817e4Smiod switch (*c)
19883d8817e4Smiod {
19893d8817e4Smiod case 'r':
19903d8817e4Smiod {
19913d8817e4Smiod long reg;
19923d8817e4Smiod
19933d8817e4Smiod reg = given >> bitstart;
19943d8817e4Smiod reg &= (2 << (bitend - bitstart)) - 1;
19953d8817e4Smiod
19963d8817e4Smiod func (stream, "%s", arm_regnames[reg]);
19973d8817e4Smiod }
19983d8817e4Smiod break;
19993d8817e4Smiod case 'd':
20003d8817e4Smiod {
20013d8817e4Smiod long reg;
20023d8817e4Smiod
20033d8817e4Smiod reg = given >> bitstart;
20043d8817e4Smiod reg &= (2 << (bitend - bitstart)) - 1;
20053d8817e4Smiod
20063d8817e4Smiod func (stream, "%ld", reg);
20073d8817e4Smiod }
20083d8817e4Smiod break;
20093d8817e4Smiod case 'W':
20103d8817e4Smiod {
20113d8817e4Smiod long reg;
20123d8817e4Smiod
20133d8817e4Smiod reg = given >> bitstart;
20143d8817e4Smiod reg &= (2 << (bitend - bitstart)) - 1;
20153d8817e4Smiod
20163d8817e4Smiod func (stream, "%ld", reg + 1);
20173d8817e4Smiod }
20183d8817e4Smiod break;
20193d8817e4Smiod case 'x':
20203d8817e4Smiod {
20213d8817e4Smiod long reg;
20223d8817e4Smiod
20233d8817e4Smiod reg = given >> bitstart;
20243d8817e4Smiod reg &= (2 << (bitend - bitstart)) - 1;
20253d8817e4Smiod
20263d8817e4Smiod func (stream, "0x%08lx", reg);
20273d8817e4Smiod
20283d8817e4Smiod /* Some SWI instructions have special
20293d8817e4Smiod meanings. */
20303d8817e4Smiod if ((given & 0x0fffffff) == 0x0FF00000)
20313d8817e4Smiod func (stream, "\t; IMB");
20323d8817e4Smiod else if ((given & 0x0fffffff) == 0x0FF00001)
20333d8817e4Smiod func (stream, "\t; IMBRange");
20343d8817e4Smiod }
20353d8817e4Smiod break;
20363d8817e4Smiod case 'X':
20373d8817e4Smiod {
20383d8817e4Smiod long reg;
20393d8817e4Smiod
20403d8817e4Smiod reg = given >> bitstart;
20413d8817e4Smiod reg &= (2 << (bitend - bitstart)) - 1;
20423d8817e4Smiod
20433d8817e4Smiod func (stream, "%01lx", reg & 0xf);
20443d8817e4Smiod }
20453d8817e4Smiod break;
20463d8817e4Smiod default:
20473d8817e4Smiod abort ();
20483d8817e4Smiod }
20493d8817e4Smiod break;
20503d8817e4Smiod
20513d8817e4Smiod case '`':
20523d8817e4Smiod c++;
20533d8817e4Smiod if ((given & (1 << bitstart)) == 0)
20543d8817e4Smiod func (stream, "%c", *c);
20553d8817e4Smiod break;
20563d8817e4Smiod case '\'':
20573d8817e4Smiod c++;
20583d8817e4Smiod if ((given & (1 << bitstart)) != 0)
20593d8817e4Smiod func (stream, "%c", *c);
20603d8817e4Smiod break;
20613d8817e4Smiod case '?':
20623d8817e4Smiod ++c;
20633d8817e4Smiod if ((given & (1 << bitstart)) != 0)
20643d8817e4Smiod func (stream, "%c", *c++);
20653d8817e4Smiod else
20663d8817e4Smiod func (stream, "%c", *++c);
20673d8817e4Smiod break;
20683d8817e4Smiod default:
20693d8817e4Smiod abort ();
20703d8817e4Smiod }
20713d8817e4Smiod break;
20723d8817e4Smiod
20733d8817e4Smiod case 'e':
20743d8817e4Smiod {
20753d8817e4Smiod int imm;
20763d8817e4Smiod
20773d8817e4Smiod imm = (given & 0xf) | ((given & 0xfff00) >> 4);
20783d8817e4Smiod func (stream, "%d", imm);
20793d8817e4Smiod }
20803d8817e4Smiod break;
20813d8817e4Smiod
20823d8817e4Smiod case 'E':
20833d8817e4Smiod /* LSB and WIDTH fields of BFI or BFC. The machine-
20843d8817e4Smiod language instruction encodes LSB and MSB. */
20853d8817e4Smiod {
20863d8817e4Smiod long msb = (given & 0x001f0000) >> 16;
20873d8817e4Smiod long lsb = (given & 0x00000f80) >> 7;
20883d8817e4Smiod
20893d8817e4Smiod long width = msb - lsb + 1;
20903d8817e4Smiod if (width > 0)
20913d8817e4Smiod func (stream, "#%lu, #%lu", lsb, width);
20923d8817e4Smiod else
20933d8817e4Smiod func (stream, "(invalid: %lu:%lu)", lsb, msb);
20943d8817e4Smiod }
20953d8817e4Smiod break;
20963d8817e4Smiod
20973d8817e4Smiod case 'V':
20983d8817e4Smiod /* 16-bit unsigned immediate from a MOVT or MOVW
20993d8817e4Smiod instruction, encoded in bits 0:11 and 15:19. */
21003d8817e4Smiod {
21013d8817e4Smiod long hi = (given & 0x000f0000) >> 4;
21023d8817e4Smiod long lo = (given & 0x00000fff);
21033d8817e4Smiod long imm16 = hi | lo;
21043d8817e4Smiod func (stream, "#%lu\t; 0x%lx", imm16, imm16);
21053d8817e4Smiod }
21063d8817e4Smiod break;
21073d8817e4Smiod
21083d8817e4Smiod default:
21093d8817e4Smiod abort ();
21103d8817e4Smiod }
21113d8817e4Smiod }
21123d8817e4Smiod }
21133d8817e4Smiod else
21143d8817e4Smiod func (stream, "%c", *c);
21153d8817e4Smiod }
21163d8817e4Smiod return;
21173d8817e4Smiod }
21183d8817e4Smiod }
21193d8817e4Smiod abort ();
21203d8817e4Smiod }
21213d8817e4Smiod
21223d8817e4Smiod /* Print one 16-bit Thumb instruction from PC on INFO->STREAM. */
21233d8817e4Smiod
21243d8817e4Smiod static void
print_insn_thumb16(bfd_vma pc,struct disassemble_info * info,long given)21253d8817e4Smiod print_insn_thumb16 (bfd_vma pc, struct disassemble_info *info, long given)
21263d8817e4Smiod {
21273d8817e4Smiod const struct opcode16 *insn;
21283d8817e4Smiod void *stream = info->stream;
21293d8817e4Smiod fprintf_ftype func = info->fprintf_func;
21303d8817e4Smiod
21313d8817e4Smiod for (insn = thumb_opcodes; insn->assembler; insn++)
21323d8817e4Smiod if ((given & insn->mask) == insn->value)
21333d8817e4Smiod {
21343d8817e4Smiod const char *c = insn->assembler;
21353d8817e4Smiod for (; *c; c++)
21363d8817e4Smiod {
21373d8817e4Smiod int domaskpc = 0;
21383d8817e4Smiod int domasklr = 0;
21393d8817e4Smiod
21403d8817e4Smiod if (*c != '%')
21413d8817e4Smiod {
21423d8817e4Smiod func (stream, "%c", *c);
21433d8817e4Smiod continue;
21443d8817e4Smiod }
21453d8817e4Smiod
21463d8817e4Smiod switch (*++c)
21473d8817e4Smiod {
21483d8817e4Smiod case '%':
21493d8817e4Smiod func (stream, "%%");
21503d8817e4Smiod break;
21513d8817e4Smiod
21523d8817e4Smiod case 'S':
21533d8817e4Smiod {
21543d8817e4Smiod long reg;
21553d8817e4Smiod
21563d8817e4Smiod reg = (given >> 3) & 0x7;
21573d8817e4Smiod if (given & (1 << 6))
21583d8817e4Smiod reg += 8;
21593d8817e4Smiod
21603d8817e4Smiod func (stream, "%s", arm_regnames[reg]);
21613d8817e4Smiod }
21623d8817e4Smiod break;
21633d8817e4Smiod
21643d8817e4Smiod case 'D':
21653d8817e4Smiod {
21663d8817e4Smiod long reg;
21673d8817e4Smiod
21683d8817e4Smiod reg = given & 0x7;
21693d8817e4Smiod if (given & (1 << 7))
21703d8817e4Smiod reg += 8;
21713d8817e4Smiod
21723d8817e4Smiod func (stream, "%s", arm_regnames[reg]);
21733d8817e4Smiod }
21743d8817e4Smiod break;
21753d8817e4Smiod
21763d8817e4Smiod case 'N':
21773d8817e4Smiod if (given & (1 << 8))
21783d8817e4Smiod domasklr = 1;
21793d8817e4Smiod /* Fall through. */
21803d8817e4Smiod case 'O':
21813d8817e4Smiod if (*c == 'O' && (given & (1 << 8)))
21823d8817e4Smiod domaskpc = 1;
21833d8817e4Smiod /* Fall through. */
21843d8817e4Smiod case 'M':
21853d8817e4Smiod {
21863d8817e4Smiod int started = 0;
21873d8817e4Smiod int reg;
21883d8817e4Smiod
21893d8817e4Smiod func (stream, "{");
21903d8817e4Smiod
21913d8817e4Smiod /* It would be nice if we could spot
21923d8817e4Smiod ranges, and generate the rS-rE format: */
21933d8817e4Smiod for (reg = 0; (reg < 8); reg++)
21943d8817e4Smiod if ((given & (1 << reg)) != 0)
21953d8817e4Smiod {
21963d8817e4Smiod if (started)
21973d8817e4Smiod func (stream, ", ");
21983d8817e4Smiod started = 1;
21993d8817e4Smiod func (stream, "%s", arm_regnames[reg]);
22003d8817e4Smiod }
22013d8817e4Smiod
22023d8817e4Smiod if (domasklr)
22033d8817e4Smiod {
22043d8817e4Smiod if (started)
22053d8817e4Smiod func (stream, ", ");
22063d8817e4Smiod started = 1;
22073d8817e4Smiod func (stream, arm_regnames[14] /* "lr" */);
22083d8817e4Smiod }
22093d8817e4Smiod
22103d8817e4Smiod if (domaskpc)
22113d8817e4Smiod {
22123d8817e4Smiod if (started)
22133d8817e4Smiod func (stream, ", ");
22143d8817e4Smiod func (stream, arm_regnames[15] /* "pc" */);
22153d8817e4Smiod }
22163d8817e4Smiod
22173d8817e4Smiod func (stream, "}");
22183d8817e4Smiod }
22193d8817e4Smiod break;
22203d8817e4Smiod
22213d8817e4Smiod case 'b':
22223d8817e4Smiod /* Print ARM V6T2 CZB address: pc+4+6 bits. */
22233d8817e4Smiod {
22243d8817e4Smiod bfd_vma address = (pc + 4
22253d8817e4Smiod + ((given & 0x00f8) >> 2)
22263d8817e4Smiod + ((given & 0x0200) >> 3));
22273d8817e4Smiod info->print_address_func (address, info);
22283d8817e4Smiod }
22293d8817e4Smiod break;
22303d8817e4Smiod
22313d8817e4Smiod case 's':
22323d8817e4Smiod /* Right shift immediate -- bits 6..10; 1-31 print
22333d8817e4Smiod as themselves, 0 prints as 32. */
22343d8817e4Smiod {
22353d8817e4Smiod long imm = (given & 0x07c0) >> 6;
22363d8817e4Smiod if (imm == 0)
22373d8817e4Smiod imm = 32;
22383d8817e4Smiod func (stream, "#%ld", imm);
22393d8817e4Smiod }
22403d8817e4Smiod break;
22413d8817e4Smiod
22423d8817e4Smiod case '0': case '1': case '2': case '3': case '4':
22433d8817e4Smiod case '5': case '6': case '7': case '8': case '9':
22443d8817e4Smiod {
22453d8817e4Smiod int bitstart = *c++ - '0';
22463d8817e4Smiod int bitend = 0;
22473d8817e4Smiod
22483d8817e4Smiod while (*c >= '0' && *c <= '9')
22493d8817e4Smiod bitstart = (bitstart * 10) + *c++ - '0';
22503d8817e4Smiod
22513d8817e4Smiod switch (*c)
22523d8817e4Smiod {
22533d8817e4Smiod case '-':
22543d8817e4Smiod {
22553d8817e4Smiod long reg;
22563d8817e4Smiod
22573d8817e4Smiod c++;
22583d8817e4Smiod while (*c >= '0' && *c <= '9')
22593d8817e4Smiod bitend = (bitend * 10) + *c++ - '0';
22603d8817e4Smiod if (!bitend)
22613d8817e4Smiod abort ();
22623d8817e4Smiod reg = given >> bitstart;
22633d8817e4Smiod reg &= (2 << (bitend - bitstart)) - 1;
22643d8817e4Smiod switch (*c)
22653d8817e4Smiod {
22663d8817e4Smiod case 'r':
22673d8817e4Smiod func (stream, "%s", arm_regnames[reg]);
22683d8817e4Smiod break;
22693d8817e4Smiod
22703d8817e4Smiod case 'd':
22713d8817e4Smiod func (stream, "%ld", reg);
22723d8817e4Smiod break;
22733d8817e4Smiod
22743d8817e4Smiod case 'H':
22753d8817e4Smiod func (stream, "%ld", reg << 1);
22763d8817e4Smiod break;
22773d8817e4Smiod
22783d8817e4Smiod case 'W':
22793d8817e4Smiod func (stream, "%ld", reg << 2);
22803d8817e4Smiod break;
22813d8817e4Smiod
22823d8817e4Smiod case 'a':
22833d8817e4Smiod /* PC-relative address -- the bottom two
22843d8817e4Smiod bits of the address are dropped
22853d8817e4Smiod before the calculation. */
22863d8817e4Smiod info->print_address_func
22873d8817e4Smiod (((pc + 4) & ~3) + (reg << 2), info);
22883d8817e4Smiod break;
22893d8817e4Smiod
22903d8817e4Smiod case 'x':
22913d8817e4Smiod func (stream, "0x%04lx", reg);
22923d8817e4Smiod break;
22933d8817e4Smiod
22943d8817e4Smiod case 'B':
22953d8817e4Smiod reg = ((reg ^ (1 << bitend)) - (1 << bitend));
22963d8817e4Smiod info->print_address_func (reg * 2 + pc + 4, info);
22973d8817e4Smiod break;
22983d8817e4Smiod
22993d8817e4Smiod case 'c':
23003d8817e4Smiod {
23013d8817e4Smiod /* Must print 0xE as 'al' to distinguish
23023d8817e4Smiod unconditional B from conditional BAL. */
23033d8817e4Smiod if (reg == 0xE)
23043d8817e4Smiod func (stream, "al");
23053d8817e4Smiod else
23063d8817e4Smiod func (stream, "%s", arm_conditional [reg]);
23073d8817e4Smiod }
23083d8817e4Smiod break;
23093d8817e4Smiod
23103d8817e4Smiod default:
23113d8817e4Smiod abort ();
23123d8817e4Smiod }
23133d8817e4Smiod }
23143d8817e4Smiod break;
23153d8817e4Smiod
23163d8817e4Smiod case '\'':
23173d8817e4Smiod c++;
23183d8817e4Smiod if ((given & (1 << bitstart)) != 0)
23193d8817e4Smiod func (stream, "%c", *c);
23203d8817e4Smiod break;
23213d8817e4Smiod
23223d8817e4Smiod case '?':
23233d8817e4Smiod ++c;
23243d8817e4Smiod if ((given & (1 << bitstart)) != 0)
23253d8817e4Smiod func (stream, "%c", *c++);
23263d8817e4Smiod else
23273d8817e4Smiod func (stream, "%c", *++c);
23283d8817e4Smiod break;
23293d8817e4Smiod
23303d8817e4Smiod default:
23313d8817e4Smiod abort ();
23323d8817e4Smiod }
23333d8817e4Smiod }
23343d8817e4Smiod break;
23353d8817e4Smiod
23363d8817e4Smiod default:
23373d8817e4Smiod abort ();
23383d8817e4Smiod }
23393d8817e4Smiod }
23403d8817e4Smiod return;
23413d8817e4Smiod }
23423d8817e4Smiod
23433d8817e4Smiod /* No match. */
23443d8817e4Smiod abort ();
23453d8817e4Smiod }
23463d8817e4Smiod
23473d8817e4Smiod /* Return the name of an V7M special register. */
23483d8817e4Smiod static const char *
psr_name(int regno)23493d8817e4Smiod psr_name (int regno)
23503d8817e4Smiod {
23513d8817e4Smiod switch (regno)
23523d8817e4Smiod {
23533d8817e4Smiod case 0: return "APSR";
23543d8817e4Smiod case 1: return "IAPSR";
23553d8817e4Smiod case 2: return "EAPSR";
23563d8817e4Smiod case 3: return "PSR";
23573d8817e4Smiod case 5: return "IPSR";
23583d8817e4Smiod case 6: return "EPSR";
23593d8817e4Smiod case 7: return "IEPSR";
23603d8817e4Smiod case 8: return "MSP";
23613d8817e4Smiod case 9: return "PSP";
23623d8817e4Smiod case 16: return "PRIMASK";
23633d8817e4Smiod case 17: return "BASEPRI";
23643d8817e4Smiod case 18: return "BASEPRI_MASK";
23653d8817e4Smiod case 19: return "FAULTMASK";
23663d8817e4Smiod case 20: return "CONTROL";
23673d8817e4Smiod default: return "<unknown>";
23683d8817e4Smiod }
23693d8817e4Smiod }
23703d8817e4Smiod
23713d8817e4Smiod /* Print one 32-bit Thumb instruction from PC on INFO->STREAM. */
23723d8817e4Smiod
23733d8817e4Smiod static void
print_insn_thumb32(bfd_vma pc,struct disassemble_info * info,long given)23743d8817e4Smiod print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
23753d8817e4Smiod {
23763d8817e4Smiod const struct opcode32 *insn;
23773d8817e4Smiod void *stream = info->stream;
23783d8817e4Smiod fprintf_ftype func = info->fprintf_func;
23793d8817e4Smiod
23803d8817e4Smiod if (print_insn_coprocessor (info, given, TRUE))
23813d8817e4Smiod return;
23823d8817e4Smiod
23833d8817e4Smiod for (insn = thumb32_opcodes; insn->assembler; insn++)
23843d8817e4Smiod if ((given & insn->mask) == insn->value)
23853d8817e4Smiod {
23863d8817e4Smiod const char *c = insn->assembler;
23873d8817e4Smiod for (; *c; c++)
23883d8817e4Smiod {
23893d8817e4Smiod if (*c != '%')
23903d8817e4Smiod {
23913d8817e4Smiod func (stream, "%c", *c);
23923d8817e4Smiod continue;
23933d8817e4Smiod }
23943d8817e4Smiod
23953d8817e4Smiod switch (*++c)
23963d8817e4Smiod {
23973d8817e4Smiod case '%':
23983d8817e4Smiod func (stream, "%%");
23993d8817e4Smiod break;
24003d8817e4Smiod
24013d8817e4Smiod case 'I':
24023d8817e4Smiod {
24033d8817e4Smiod unsigned int imm12 = 0;
24043d8817e4Smiod imm12 |= (given & 0x000000ffu);
24053d8817e4Smiod imm12 |= (given & 0x00007000u) >> 4;
24063d8817e4Smiod imm12 |= (given & 0x04000000u) >> 15;
24073d8817e4Smiod func (stream, "#%u\t; 0x%x", imm12, imm12);
24083d8817e4Smiod }
24093d8817e4Smiod break;
24103d8817e4Smiod
24113d8817e4Smiod case 'M':
24123d8817e4Smiod {
24133d8817e4Smiod unsigned int bits = 0, imm, imm8, mod;
24143d8817e4Smiod bits |= (given & 0x000000ffu);
24153d8817e4Smiod bits |= (given & 0x00007000u) >> 4;
24163d8817e4Smiod bits |= (given & 0x04000000u) >> 15;
24173d8817e4Smiod imm8 = (bits & 0x0ff);
24183d8817e4Smiod mod = (bits & 0xf00) >> 8;
24193d8817e4Smiod switch (mod)
24203d8817e4Smiod {
24213d8817e4Smiod case 0: imm = imm8; break;
24223d8817e4Smiod case 1: imm = ((imm8<<16) | imm8); break;
24233d8817e4Smiod case 2: imm = ((imm8<<24) | (imm8 << 8)); break;
24243d8817e4Smiod case 3: imm = ((imm8<<24) | (imm8 << 16) | (imm8 << 8) | imm8); break;
24253d8817e4Smiod default:
24263d8817e4Smiod mod = (bits & 0xf80) >> 7;
24273d8817e4Smiod imm8 = (bits & 0x07f) | 0x80;
24283d8817e4Smiod imm = (((imm8 << (32 - mod)) | (imm8 >> mod)) & 0xffffffff);
24293d8817e4Smiod }
24303d8817e4Smiod func (stream, "#%u\t; 0x%x", imm, imm);
24313d8817e4Smiod }
24323d8817e4Smiod break;
24333d8817e4Smiod
24343d8817e4Smiod case 'J':
24353d8817e4Smiod {
24363d8817e4Smiod unsigned int imm = 0;
24373d8817e4Smiod imm |= (given & 0x000000ffu);
24383d8817e4Smiod imm |= (given & 0x00007000u) >> 4;
24393d8817e4Smiod imm |= (given & 0x04000000u) >> 15;
24403d8817e4Smiod imm |= (given & 0x000f0000u) >> 4;
24413d8817e4Smiod func (stream, "#%u\t; 0x%x", imm, imm);
24423d8817e4Smiod }
24433d8817e4Smiod break;
24443d8817e4Smiod
24453d8817e4Smiod case 'K':
24463d8817e4Smiod {
24473d8817e4Smiod unsigned int imm = 0;
24483d8817e4Smiod imm |= (given & 0x000f0000u) >> 16;
24493d8817e4Smiod imm |= (given & 0x00000ff0u) >> 0;
24503d8817e4Smiod imm |= (given & 0x0000000fu) << 12;
24513d8817e4Smiod func (stream, "#%u\t; 0x%x", imm, imm);
24523d8817e4Smiod }
24533d8817e4Smiod break;
24543d8817e4Smiod
24553d8817e4Smiod case 'S':
24563d8817e4Smiod {
24573d8817e4Smiod unsigned int reg = (given & 0x0000000fu);
24583d8817e4Smiod unsigned int stp = (given & 0x00000030u) >> 4;
24593d8817e4Smiod unsigned int imm = 0;
24603d8817e4Smiod imm |= (given & 0x000000c0u) >> 6;
24613d8817e4Smiod imm |= (given & 0x00007000u) >> 10;
24623d8817e4Smiod
24633d8817e4Smiod func (stream, "%s", arm_regnames[reg]);
24643d8817e4Smiod switch (stp)
24653d8817e4Smiod {
24663d8817e4Smiod case 0:
24673d8817e4Smiod if (imm > 0)
24683d8817e4Smiod func (stream, ", lsl #%u", imm);
24693d8817e4Smiod break;
24703d8817e4Smiod
24713d8817e4Smiod case 1:
24723d8817e4Smiod if (imm == 0)
24733d8817e4Smiod imm = 32;
24743d8817e4Smiod func (stream, ", lsr #%u", imm);
24753d8817e4Smiod break;
24763d8817e4Smiod
24773d8817e4Smiod case 2:
24783d8817e4Smiod if (imm == 0)
24793d8817e4Smiod imm = 32;
24803d8817e4Smiod func (stream, ", asr #%u", imm);
24813d8817e4Smiod break;
24823d8817e4Smiod
24833d8817e4Smiod case 3:
24843d8817e4Smiod if (imm == 0)
24853d8817e4Smiod func (stream, ", rrx");
24863d8817e4Smiod else
24873d8817e4Smiod func (stream, ", ror #%u", imm);
24883d8817e4Smiod }
24893d8817e4Smiod }
24903d8817e4Smiod break;
24913d8817e4Smiod
24923d8817e4Smiod case 'a':
24933d8817e4Smiod {
24943d8817e4Smiod unsigned int Rn = (given & 0x000f0000) >> 16;
24953d8817e4Smiod unsigned int U = (given & 0x00800000) >> 23;
24963d8817e4Smiod unsigned int op = (given & 0x00000f00) >> 8;
24973d8817e4Smiod unsigned int i12 = (given & 0x00000fff);
24983d8817e4Smiod unsigned int i8 = (given & 0x000000ff);
24993d8817e4Smiod bfd_boolean writeback = FALSE, postind = FALSE;
25003d8817e4Smiod int offset = 0;
25013d8817e4Smiod
25023d8817e4Smiod func (stream, "[%s", arm_regnames[Rn]);
25033d8817e4Smiod if (U) /* 12-bit positive immediate offset */
25043d8817e4Smiod offset = i12;
25053d8817e4Smiod else if (Rn == 15) /* 12-bit negative immediate offset */
25063d8817e4Smiod offset = -(int)i12;
25073d8817e4Smiod else if (op == 0x0) /* shifted register offset */
25083d8817e4Smiod {
25093d8817e4Smiod unsigned int Rm = (i8 & 0x0f);
25103d8817e4Smiod unsigned int sh = (i8 & 0x30) >> 4;
25113d8817e4Smiod func (stream, ", %s", arm_regnames[Rm]);
25123d8817e4Smiod if (sh)
25133d8817e4Smiod func (stream, ", lsl #%u", sh);
25143d8817e4Smiod func (stream, "]");
25153d8817e4Smiod break;
25163d8817e4Smiod }
25173d8817e4Smiod else switch (op)
25183d8817e4Smiod {
25193d8817e4Smiod case 0xE: /* 8-bit positive immediate offset */
25203d8817e4Smiod offset = i8;
25213d8817e4Smiod break;
25223d8817e4Smiod
25233d8817e4Smiod case 0xC: /* 8-bit negative immediate offset */
25243d8817e4Smiod offset = -i8;
25253d8817e4Smiod break;
25263d8817e4Smiod
25273d8817e4Smiod case 0xF: /* 8-bit + preindex with wb */
25283d8817e4Smiod offset = i8;
25293d8817e4Smiod writeback = TRUE;
25303d8817e4Smiod break;
25313d8817e4Smiod
25323d8817e4Smiod case 0xD: /* 8-bit - preindex with wb */
25333d8817e4Smiod offset = -i8;
25343d8817e4Smiod writeback = TRUE;
25353d8817e4Smiod break;
25363d8817e4Smiod
25373d8817e4Smiod case 0xB: /* 8-bit + postindex */
25383d8817e4Smiod offset = i8;
25393d8817e4Smiod postind = TRUE;
25403d8817e4Smiod break;
25413d8817e4Smiod
25423d8817e4Smiod case 0x9: /* 8-bit - postindex */
25433d8817e4Smiod offset = -i8;
25443d8817e4Smiod postind = TRUE;
25453d8817e4Smiod break;
25463d8817e4Smiod
25473d8817e4Smiod default:
25483d8817e4Smiod func (stream, ", <undefined>]");
25493d8817e4Smiod goto skip;
25503d8817e4Smiod }
25513d8817e4Smiod
25523d8817e4Smiod if (postind)
25533d8817e4Smiod func (stream, "], #%d", offset);
25543d8817e4Smiod else
25553d8817e4Smiod {
25563d8817e4Smiod if (offset)
25573d8817e4Smiod func (stream, ", #%d", offset);
25583d8817e4Smiod func (stream, writeback ? "]!" : "]");
25593d8817e4Smiod }
25603d8817e4Smiod
25613d8817e4Smiod if (Rn == 15)
25623d8817e4Smiod {
25633d8817e4Smiod func (stream, "\t; ");
25643d8817e4Smiod info->print_address_func (((pc + 4) & ~3) + offset, info);
25653d8817e4Smiod }
25663d8817e4Smiod }
25673d8817e4Smiod skip:
25683d8817e4Smiod break;
25693d8817e4Smiod
25703d8817e4Smiod case 'A':
25713d8817e4Smiod {
25723d8817e4Smiod unsigned int P = (given & 0x01000000) >> 24;
25733d8817e4Smiod unsigned int U = (given & 0x00800000) >> 23;
25743d8817e4Smiod unsigned int W = (given & 0x00400000) >> 21;
25753d8817e4Smiod unsigned int Rn = (given & 0x000f0000) >> 16;
25763d8817e4Smiod unsigned int off = (given & 0x000000ff);
25773d8817e4Smiod
25783d8817e4Smiod func (stream, "[%s", arm_regnames[Rn]);
25793d8817e4Smiod if (P)
25803d8817e4Smiod {
25813d8817e4Smiod if (off || !U)
25823d8817e4Smiod func (stream, ", #%c%u", U ? '+' : '-', off * 4);
25833d8817e4Smiod func (stream, "]");
25843d8817e4Smiod if (W)
25853d8817e4Smiod func (stream, "!");
25863d8817e4Smiod }
25873d8817e4Smiod else
25883d8817e4Smiod {
25893d8817e4Smiod func (stream, "], ");
25903d8817e4Smiod if (W)
25913d8817e4Smiod func (stream, "#%c%u", U ? '+' : '-', off * 4);
25923d8817e4Smiod else
25933d8817e4Smiod func (stream, "{%u}", off);
25943d8817e4Smiod }
25953d8817e4Smiod }
25963d8817e4Smiod break;
25973d8817e4Smiod
25983d8817e4Smiod case 'w':
25993d8817e4Smiod {
26003d8817e4Smiod unsigned int Sbit = (given & 0x01000000) >> 24;
26013d8817e4Smiod unsigned int type = (given & 0x00600000) >> 21;
26023d8817e4Smiod switch (type)
26033d8817e4Smiod {
26043d8817e4Smiod case 0: func (stream, Sbit ? "sb" : "b"); break;
26053d8817e4Smiod case 1: func (stream, Sbit ? "sh" : "h"); break;
26063d8817e4Smiod case 2:
26073d8817e4Smiod if (Sbit)
26083d8817e4Smiod func (stream, "??");
26093d8817e4Smiod break;
26103d8817e4Smiod case 3:
26113d8817e4Smiod func (stream, "??");
26123d8817e4Smiod break;
26133d8817e4Smiod }
26143d8817e4Smiod }
26153d8817e4Smiod break;
26163d8817e4Smiod
26173d8817e4Smiod case 'm':
26183d8817e4Smiod {
26193d8817e4Smiod int started = 0;
26203d8817e4Smiod int reg;
26213d8817e4Smiod
26223d8817e4Smiod func (stream, "{");
26233d8817e4Smiod for (reg = 0; reg < 16; reg++)
26243d8817e4Smiod if ((given & (1 << reg)) != 0)
26253d8817e4Smiod {
26263d8817e4Smiod if (started)
26273d8817e4Smiod func (stream, ", ");
26283d8817e4Smiod started = 1;
26293d8817e4Smiod func (stream, "%s", arm_regnames[reg]);
26303d8817e4Smiod }
26313d8817e4Smiod func (stream, "}");
26323d8817e4Smiod }
26333d8817e4Smiod break;
26343d8817e4Smiod
26353d8817e4Smiod case 'E':
26363d8817e4Smiod {
26373d8817e4Smiod unsigned int msb = (given & 0x0000001f);
26383d8817e4Smiod unsigned int lsb = 0;
26393d8817e4Smiod lsb |= (given & 0x000000c0u) >> 6;
26403d8817e4Smiod lsb |= (given & 0x00007000u) >> 10;
26413d8817e4Smiod func (stream, "#%u, #%u", lsb, msb - lsb + 1);
26423d8817e4Smiod }
26433d8817e4Smiod break;
26443d8817e4Smiod
26453d8817e4Smiod case 'F':
26463d8817e4Smiod {
26473d8817e4Smiod unsigned int width = (given & 0x0000001f) + 1;
26483d8817e4Smiod unsigned int lsb = 0;
26493d8817e4Smiod lsb |= (given & 0x000000c0u) >> 6;
26503d8817e4Smiod lsb |= (given & 0x00007000u) >> 10;
26513d8817e4Smiod func (stream, "#%u, #%u", lsb, width);
26523d8817e4Smiod }
26533d8817e4Smiod break;
26543d8817e4Smiod
26553d8817e4Smiod case 'b':
26563d8817e4Smiod {
26573d8817e4Smiod unsigned int S = (given & 0x04000000u) >> 26;
26583d8817e4Smiod unsigned int J1 = (given & 0x00002000u) >> 13;
26593d8817e4Smiod unsigned int J2 = (given & 0x00000800u) >> 11;
26603d8817e4Smiod int offset = 0;
26613d8817e4Smiod
26623d8817e4Smiod offset |= !S << 20;
26633d8817e4Smiod offset |= J2 << 19;
26643d8817e4Smiod offset |= J1 << 18;
26653d8817e4Smiod offset |= (given & 0x003f0000) >> 4;
26663d8817e4Smiod offset |= (given & 0x000007ff) << 1;
26673d8817e4Smiod offset -= (1 << 20);
26683d8817e4Smiod
26693d8817e4Smiod info->print_address_func (pc + 4 + offset, info);
26703d8817e4Smiod }
26713d8817e4Smiod break;
26723d8817e4Smiod
26733d8817e4Smiod case 'B':
26743d8817e4Smiod {
26753d8817e4Smiod unsigned int S = (given & 0x04000000u) >> 26;
26763d8817e4Smiod unsigned int I1 = (given & 0x00002000u) >> 13;
26773d8817e4Smiod unsigned int I2 = (given & 0x00000800u) >> 11;
26783d8817e4Smiod int offset = 0;
26793d8817e4Smiod
26803d8817e4Smiod offset |= !S << 24;
26813d8817e4Smiod offset |= !(I1 ^ S) << 23;
26823d8817e4Smiod offset |= !(I2 ^ S) << 22;
26833d8817e4Smiod offset |= (given & 0x03ff0000u) >> 4;
26843d8817e4Smiod offset |= (given & 0x000007ffu) << 1;
26853d8817e4Smiod offset -= (1 << 24);
26863d8817e4Smiod offset += pc + 4;
26873d8817e4Smiod
26883d8817e4Smiod /* BLX target addresses are always word aligned. */
26893d8817e4Smiod if ((given & 0x00001000u) == 0)
26903d8817e4Smiod offset &= ~2u;
26913d8817e4Smiod
26923d8817e4Smiod info->print_address_func (offset, info);
26933d8817e4Smiod }
26943d8817e4Smiod break;
26953d8817e4Smiod
26963d8817e4Smiod case 's':
26973d8817e4Smiod {
26983d8817e4Smiod unsigned int shift = 0;
26993d8817e4Smiod shift |= (given & 0x000000c0u) >> 6;
27003d8817e4Smiod shift |= (given & 0x00007000u) >> 10;
27013d8817e4Smiod if (given & 0x00200000u)
27023d8817e4Smiod func (stream, ", asr #%u", shift);
27033d8817e4Smiod else if (shift)
27043d8817e4Smiod func (stream, ", lsl #%u", shift);
27053d8817e4Smiod /* else print nothing - lsl #0 */
27063d8817e4Smiod }
27073d8817e4Smiod break;
27083d8817e4Smiod
27093d8817e4Smiod case 'R':
27103d8817e4Smiod {
27113d8817e4Smiod unsigned int rot = (given & 0x00000030) >> 4;
27123d8817e4Smiod if (rot)
27133d8817e4Smiod func (stream, ", ror #%u", rot * 8);
27143d8817e4Smiod }
27153d8817e4Smiod break;
27163d8817e4Smiod
27173d8817e4Smiod case 'U':
27183d8817e4Smiod switch (given & 0xf)
27193d8817e4Smiod {
2720*0f6fdfcdSjsg case 0x2: func(stream, "oshst"); break;
2721*0f6fdfcdSjsg case 0x3: func(stream, "osh"); break;
2722*0f6fdfcdSjsg case 0x6: func(stream, "nshst"); break;
2723*0f6fdfcdSjsg case 0x7: func(stream, "nsh"); break;
2724*0f6fdfcdSjsg case 0xa: func(stream, "ishst"); break;
2725*0f6fdfcdSjsg case 0xb: func(stream, "ish"); break;
27263d8817e4Smiod case 0xe: func(stream, "st"); break;
2727*0f6fdfcdSjsg case 0xf: func(stream, "sy"); break;
27283d8817e4Smiod default:
27293d8817e4Smiod func(stream, "#%d", (int)given & 0xf);
27303d8817e4Smiod break;
27313d8817e4Smiod }
27323d8817e4Smiod break;
27333d8817e4Smiod
27343d8817e4Smiod case 'C':
27353d8817e4Smiod if ((given & 0xff) == 0)
27363d8817e4Smiod {
27373d8817e4Smiod func (stream, "%cPSR_", (given & 0x100000) ? 'S' : 'C');
27383d8817e4Smiod if (given & 0x800)
27393d8817e4Smiod func (stream, "f");
27403d8817e4Smiod if (given & 0x400)
27413d8817e4Smiod func (stream, "s");
27423d8817e4Smiod if (given & 0x200)
27433d8817e4Smiod func (stream, "x");
27443d8817e4Smiod if (given & 0x100)
27453d8817e4Smiod func (stream, "c");
27463d8817e4Smiod }
27473d8817e4Smiod else
27483d8817e4Smiod {
27493d8817e4Smiod func (stream, psr_name (given & 0xff));
27503d8817e4Smiod }
27513d8817e4Smiod break;
27523d8817e4Smiod
27533d8817e4Smiod case 'D':
27543d8817e4Smiod if ((given & 0xff) == 0)
27553d8817e4Smiod func (stream, "%cPSR", (given & 0x100000) ? 'S' : 'C');
27563d8817e4Smiod else
27573d8817e4Smiod func (stream, psr_name (given & 0xff));
27583d8817e4Smiod break;
27593d8817e4Smiod
27603d8817e4Smiod case '0': case '1': case '2': case '3': case '4':
27613d8817e4Smiod case '5': case '6': case '7': case '8': case '9':
27623d8817e4Smiod {
27633d8817e4Smiod int bitstart = *c++ - '0';
27643d8817e4Smiod int bitend = 0;
27653d8817e4Smiod unsigned int val;
27663d8817e4Smiod while (*c >= '0' && *c <= '9')
27673d8817e4Smiod bitstart = (bitstart * 10) + *c++ - '0';
27683d8817e4Smiod
27693d8817e4Smiod if (*c == '-')
27703d8817e4Smiod {
27713d8817e4Smiod c++;
27723d8817e4Smiod while (*c >= '0' && *c <= '9')
27733d8817e4Smiod bitend = (bitend * 10) + *c++ - '0';
27743d8817e4Smiod if (!bitend)
27753d8817e4Smiod abort ();
27763d8817e4Smiod
27773d8817e4Smiod val = given >> bitstart;
27783d8817e4Smiod val &= (2 << (bitend - bitstart)) - 1;
27793d8817e4Smiod }
27803d8817e4Smiod else
27813d8817e4Smiod val = (given >> bitstart) & 1;
27823d8817e4Smiod
27833d8817e4Smiod switch (*c)
27843d8817e4Smiod {
27853d8817e4Smiod case 'd': func (stream, "%u", val); break;
27863d8817e4Smiod case 'W': func (stream, "%u", val * 4); break;
27873d8817e4Smiod case 'r': func (stream, "%s", arm_regnames[val]); break;
27883d8817e4Smiod
27893d8817e4Smiod case 'c':
27903d8817e4Smiod if (val == 0xE)
27913d8817e4Smiod func (stream, "al");
27923d8817e4Smiod else
27933d8817e4Smiod func (stream, "%s", arm_conditional[val]);
27943d8817e4Smiod break;
27953d8817e4Smiod
27963d8817e4Smiod case '\'':
27973d8817e4Smiod if (val)
27983d8817e4Smiod func (stream, "%c", c[1]);
27993d8817e4Smiod c++;
28003d8817e4Smiod break;
28013d8817e4Smiod
28023d8817e4Smiod case '`':
28033d8817e4Smiod if (!val)
28043d8817e4Smiod func (stream, "%c", c[1]);
28053d8817e4Smiod c++;
28063d8817e4Smiod break;
28073d8817e4Smiod
28083d8817e4Smiod case '?':
28093d8817e4Smiod func (stream, "%c", val ? c[1] : c[2]);
28103d8817e4Smiod c += 2;
28113d8817e4Smiod break;
28123d8817e4Smiod
28133d8817e4Smiod default:
28143d8817e4Smiod abort ();
28153d8817e4Smiod }
28163d8817e4Smiod }
28173d8817e4Smiod break;
28183d8817e4Smiod
28193d8817e4Smiod default:
28203d8817e4Smiod abort ();
28213d8817e4Smiod }
28223d8817e4Smiod }
28233d8817e4Smiod return;
28243d8817e4Smiod }
28253d8817e4Smiod
28263d8817e4Smiod /* No match. */
28273d8817e4Smiod abort ();
28283d8817e4Smiod }
28293d8817e4Smiod
28303d8817e4Smiod /* Disallow mapping symbols ($a, $b, $d, $t etc) from
28313d8817e4Smiod being displayed in symbol relative addresses. */
28323d8817e4Smiod
28333d8817e4Smiod bfd_boolean
arm_symbol_is_valid(asymbol * sym,struct disassemble_info * info ATTRIBUTE_UNUSED)28343d8817e4Smiod arm_symbol_is_valid (asymbol * sym,
28353d8817e4Smiod struct disassemble_info * info ATTRIBUTE_UNUSED)
28363d8817e4Smiod {
28373d8817e4Smiod const char * name;
28383d8817e4Smiod
28393d8817e4Smiod if (sym == NULL)
28403d8817e4Smiod return FALSE;
28413d8817e4Smiod
28423d8817e4Smiod name = bfd_asymbol_name (sym);
28433d8817e4Smiod
28443d8817e4Smiod return (name && *name != '$');
28453d8817e4Smiod }
28463d8817e4Smiod
28473d8817e4Smiod /* Parse an individual disassembler option. */
28483d8817e4Smiod
28493d8817e4Smiod void
parse_arm_disassembler_option(char * option)28503d8817e4Smiod parse_arm_disassembler_option (char *option)
28513d8817e4Smiod {
28523d8817e4Smiod if (option == NULL)
28533d8817e4Smiod return;
28543d8817e4Smiod
28553d8817e4Smiod if (strneq (option, "reg-names-", 10))
28563d8817e4Smiod {
28573d8817e4Smiod int i;
28583d8817e4Smiod
28593d8817e4Smiod option += 10;
28603d8817e4Smiod
28613d8817e4Smiod for (i = NUM_ARM_REGNAMES; i--;)
28623d8817e4Smiod if (strneq (option, regnames[i].name, strlen (regnames[i].name)))
28633d8817e4Smiod {
28643d8817e4Smiod regname_selected = i;
28653d8817e4Smiod break;
28663d8817e4Smiod }
28673d8817e4Smiod
28683d8817e4Smiod if (i < 0)
28693d8817e4Smiod /* XXX - should break 'option' at following delimiter. */
28703d8817e4Smiod fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
28713d8817e4Smiod }
28723d8817e4Smiod else if (strneq (option, "force-thumb", 11))
28733d8817e4Smiod force_thumb = 1;
28743d8817e4Smiod else if (strneq (option, "no-force-thumb", 14))
28753d8817e4Smiod force_thumb = 0;
28763d8817e4Smiod else
28773d8817e4Smiod /* XXX - should break 'option' at following delimiter. */
28783d8817e4Smiod fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
28793d8817e4Smiod
28803d8817e4Smiod return;
28813d8817e4Smiod }
28823d8817e4Smiod
28833d8817e4Smiod /* Parse the string of disassembler options, spliting it at whitespaces
28843d8817e4Smiod or commas. (Whitespace separators supported for backwards compatibility). */
28853d8817e4Smiod
28863d8817e4Smiod static void
parse_disassembler_options(char * options)28873d8817e4Smiod parse_disassembler_options (char *options)
28883d8817e4Smiod {
28893d8817e4Smiod if (options == NULL)
28903d8817e4Smiod return;
28913d8817e4Smiod
28923d8817e4Smiod while (*options)
28933d8817e4Smiod {
28943d8817e4Smiod parse_arm_disassembler_option (options);
28953d8817e4Smiod
28963d8817e4Smiod /* Skip forward to next seperator. */
28973d8817e4Smiod while ((*options) && (! ISSPACE (*options)) && (*options != ','))
28983d8817e4Smiod ++ options;
28993d8817e4Smiod /* Skip forward past seperators. */
29003d8817e4Smiod while (ISSPACE (*options) || (*options == ','))
29013d8817e4Smiod ++ options;
29023d8817e4Smiod }
29033d8817e4Smiod }
29043d8817e4Smiod
29053d8817e4Smiod /* NOTE: There are no checks in these routines that
29063d8817e4Smiod the relevant number of data bytes exist. */
29073d8817e4Smiod
29083d8817e4Smiod static int
print_insn(bfd_vma pc,struct disassemble_info * info,bfd_boolean little)29093d8817e4Smiod print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
29103d8817e4Smiod {
29113d8817e4Smiod unsigned char b[4];
29123d8817e4Smiod long given;
29133d8817e4Smiod int status;
29143d8817e4Smiod int is_thumb;
29153d8817e4Smiod int size;
29163d8817e4Smiod void (*printer) (bfd_vma, struct disassemble_info *, long);
29173d8817e4Smiod
29183d8817e4Smiod if (info->disassembler_options)
29193d8817e4Smiod {
29203d8817e4Smiod parse_disassembler_options (info->disassembler_options);
29213d8817e4Smiod
29223d8817e4Smiod /* To avoid repeated parsing of these options, we remove them here. */
29233d8817e4Smiod info->disassembler_options = NULL;
29243d8817e4Smiod }
29253d8817e4Smiod
29263d8817e4Smiod is_thumb = force_thumb;
29273d8817e4Smiod
29283d8817e4Smiod if (!is_thumb && info->symbols != NULL)
29293d8817e4Smiod {
29303d8817e4Smiod if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
29313d8817e4Smiod {
29323d8817e4Smiod coff_symbol_type * cs;
29333d8817e4Smiod
29343d8817e4Smiod cs = coffsymbol (*info->symbols);
29353d8817e4Smiod is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT
29363d8817e4Smiod || cs->native->u.syment.n_sclass == C_THUMBSTAT
29373d8817e4Smiod || cs->native->u.syment.n_sclass == C_THUMBLABEL
29383d8817e4Smiod || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
29393d8817e4Smiod || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
29403d8817e4Smiod }
29413d8817e4Smiod else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
29423d8817e4Smiod {
29433d8817e4Smiod elf_symbol_type * es;
29443d8817e4Smiod unsigned int type;
29453d8817e4Smiod
29463d8817e4Smiod es = *(elf_symbol_type **)(info->symbols);
29473d8817e4Smiod type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
29483d8817e4Smiod
29493d8817e4Smiod is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
29503d8817e4Smiod }
29513d8817e4Smiod }
29523d8817e4Smiod
29533d8817e4Smiod info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
29543d8817e4Smiod info->bytes_per_line = 4;
29553d8817e4Smiod
29563d8817e4Smiod if (!is_thumb)
29573d8817e4Smiod {
29583d8817e4Smiod /* In ARM mode endianness is a straightforward issue: the instruction
29593d8817e4Smiod is four bytes long and is either ordered 0123 or 3210. */
29603d8817e4Smiod printer = print_insn_arm;
29613d8817e4Smiod info->bytes_per_chunk = 4;
29623d8817e4Smiod size = 4;
29633d8817e4Smiod
29643d8817e4Smiod status = info->read_memory_func (pc, (bfd_byte *)b, 4, info);
29653d8817e4Smiod if (little)
29663d8817e4Smiod given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
29673d8817e4Smiod else
29683d8817e4Smiod given = (b[3]) | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
29693d8817e4Smiod }
29703d8817e4Smiod else
29713d8817e4Smiod {
29723d8817e4Smiod /* In Thumb mode we have the additional wrinkle of two
29733d8817e4Smiod instruction lengths. Fortunately, the bits that determine
29743d8817e4Smiod the length of the current instruction are always to be found
29753d8817e4Smiod in the first two bytes. */
29763d8817e4Smiod printer = print_insn_thumb16;
29773d8817e4Smiod info->bytes_per_chunk = 2;
29783d8817e4Smiod size = 2;
29793d8817e4Smiod
29803d8817e4Smiod status = info->read_memory_func (pc, (bfd_byte *)b, 2, info);
29813d8817e4Smiod if (little)
29823d8817e4Smiod given = (b[0]) | (b[1] << 8);
29833d8817e4Smiod else
29843d8817e4Smiod given = (b[1]) | (b[0] << 8);
29853d8817e4Smiod
29863d8817e4Smiod if (!status)
29873d8817e4Smiod {
29883d8817e4Smiod /* These bit patterns signal a four-byte Thumb
29893d8817e4Smiod instruction. */
29903d8817e4Smiod if ((given & 0xF800) == 0xF800
29913d8817e4Smiod || (given & 0xF800) == 0xF000
29923d8817e4Smiod || (given & 0xF800) == 0xE800)
29933d8817e4Smiod {
29943d8817e4Smiod status = info->read_memory_func (pc + 2, (bfd_byte *)b, 2, info);
29953d8817e4Smiod if (little)
29963d8817e4Smiod given = (b[0]) | (b[1] << 8) | (given << 16);
29973d8817e4Smiod else
29983d8817e4Smiod given = (b[1]) | (b[0] << 8) | (given << 16);
29993d8817e4Smiod
30003d8817e4Smiod printer = print_insn_thumb32;
30013d8817e4Smiod size = 4;
30023d8817e4Smiod }
30033d8817e4Smiod }
30043d8817e4Smiod }
30053d8817e4Smiod
30063d8817e4Smiod if (status)
30073d8817e4Smiod {
30083d8817e4Smiod info->memory_error_func (status, pc, info);
30093d8817e4Smiod return -1;
30103d8817e4Smiod }
30113d8817e4Smiod if (info->flags & INSN_HAS_RELOC)
30123d8817e4Smiod /* If the instruction has a reloc associated with it, then
30133d8817e4Smiod the offset field in the instruction will actually be the
30143d8817e4Smiod addend for the reloc. (We are using REL type relocs).
30153d8817e4Smiod In such cases, we can ignore the pc when computing
30163d8817e4Smiod addresses, since the addend is not currently pc-relative. */
30173d8817e4Smiod pc = 0;
30183d8817e4Smiod
30193d8817e4Smiod printer (pc, info, given);
30203d8817e4Smiod return size;
30213d8817e4Smiod }
30223d8817e4Smiod
30233d8817e4Smiod int
print_insn_big_arm(bfd_vma pc,struct disassemble_info * info)30243d8817e4Smiod print_insn_big_arm (bfd_vma pc, struct disassemble_info *info)
30253d8817e4Smiod {
30263d8817e4Smiod return print_insn (pc, info, FALSE);
30273d8817e4Smiod }
30283d8817e4Smiod
30293d8817e4Smiod int
print_insn_little_arm(bfd_vma pc,struct disassemble_info * info)30303d8817e4Smiod print_insn_little_arm (bfd_vma pc, struct disassemble_info *info)
30313d8817e4Smiod {
30323d8817e4Smiod return print_insn (pc, info, TRUE);
30333d8817e4Smiod }
30343d8817e4Smiod
30353d8817e4Smiod void
print_arm_disassembler_options(FILE * stream)30363d8817e4Smiod print_arm_disassembler_options (FILE *stream)
30373d8817e4Smiod {
30383d8817e4Smiod int i;
30393d8817e4Smiod
30403d8817e4Smiod fprintf (stream, _("\n\
30413d8817e4Smiod The following ARM specific disassembler options are supported for use with\n\
30423d8817e4Smiod the -M switch:\n"));
30433d8817e4Smiod
30443d8817e4Smiod for (i = NUM_ARM_REGNAMES; i--;)
30453d8817e4Smiod fprintf (stream, " reg-names-%s %*c%s\n",
30463d8817e4Smiod regnames[i].name,
30473d8817e4Smiod (int)(14 - strlen (regnames[i].name)), ' ',
30483d8817e4Smiod regnames[i].description);
30493d8817e4Smiod
30503d8817e4Smiod fprintf (stream, " force-thumb Assume all insns are Thumb insns\n");
30513d8817e4Smiod fprintf (stream, " no-force-thumb Examine preceeding label to determine an insn's type\n\n");
30523d8817e4Smiod }
3053