aboutsummaryrefslogtreecommitdiff
path: root/disas
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2012-10-24 11:12:21 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2012-12-19 08:29:06 +0100
commit76cad71136b7eb371cf2a2a4e1621cfe8d9c769a (patch)
tree88d6951ea0620e95d2bad4d458f2c51147b4218b /disas
parentc1c9367216c97ca93de79e90822045a425d7e76d (diff)
downloadqemu-arm-76cad71136b7eb371cf2a2a4e1621cfe8d9c769a.tar.gz
build: kill libdis, move disassemblers to disas/
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'disas')
-rw-r--r--disas/Makefile.objs16
-rw-r--r--disas/alpha.c1916
-rw-r--r--disas/arm.c4136
-rw-r--r--disas/cris.c2871
-rw-r--r--disas/hppa.c2831
-rw-r--r--disas/i386.c6562
-rw-r--r--disas/ia64.c10602
-rw-r--r--disas/lm32.c361
-rw-r--r--disas/m68k.c5051
-rw-r--r--disas/microblaze.c1100
-rw-r--r--disas/mips.c4873
-rw-r--r--disas/ppc.c5412
-rw-r--r--disas/s390.c1796
-rw-r--r--disas/sh4.c2077
-rw-r--r--disas/sparc.c3275
-rw-r--r--disas/tci.c59
16 files changed, 52938 insertions, 0 deletions
diff --git a/disas/Makefile.objs b/disas/Makefile.objs
new file mode 100644
index 0000000000..9134429845
--- /dev/null
+++ b/disas/Makefile.objs
@@ -0,0 +1,16 @@
+universal-obj-$(CONFIG_ALPHA_DIS) += alpha.o
+universal-obj-$(CONFIG_ARM_DIS) += arm.o
+universal-obj-$(CONFIG_CRIS_DIS) += cris.o
+universal-obj-$(CONFIG_HPPA_DIS) += hppa.o
+universal-obj-$(CONFIG_I386_DIS) += i386.o
+universal-obj-$(CONFIG_IA64_DIS) += ia64.o
+universal-obj-$(CONFIG_M68K_DIS) += m68k.o
+universal-obj-$(CONFIG_MICROBLAZE_DIS) += microblaze.o
+universal-obj-$(CONFIG_MIPS_DIS) += mips.o
+universal-obj-$(CONFIG_PPC_DIS) += ppc.o
+universal-obj-$(CONFIG_S390_DIS) += s390.o
+universal-obj-$(CONFIG_SH4_DIS) += sh4.o
+universal-obj-$(CONFIG_SPARC_DIS) += sparc.o
+universal-obj-$(CONFIG_LM32_DIS) += lm32.o
+
+universal-obj-$(CONFIG_TCI_DIS) += tci.o
diff --git a/disas/alpha.c b/disas/alpha.c
new file mode 100644
index 0000000000..a950b9cee0
--- /dev/null
+++ b/disas/alpha.c
@@ -0,0 +1,1916 @@
+/* alpha-dis.c -- Disassemble Alpha AXP instructions
+ Copyright 1996, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@tamu.edu>,
+ patterned after the PPC opcode handling written by Ian Lance Taylor.
+
+This file is part of GDB, GAS, and the GNU binutils.
+
+GDB, GAS, and the GNU binutils are free software; you can redistribute
+them and/or modify them under the terms of the GNU General Public
+License as published by the Free Software Foundation; either version
+2, or (at your option) any later version.
+
+GDB, GAS, and the GNU binutils are distributed in the hope that they
+will be useful, but WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this file; see the file COPYING. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include "disas/bfd.h"
+
+/* MAX is redefined below, so remove any previous definition. */
+#undef MAX
+
+/* The opcode table is an array of struct alpha_opcode. */
+
+struct alpha_opcode
+{
+ /* The opcode name. */
+ const char *name;
+
+ /* The opcode itself. Those bits which will be filled in with
+ operands are zeroes. */
+ unsigned opcode;
+
+ /* The opcode mask. This is used by the disassembler. This is a
+ mask containing ones indicating those bits which must match the
+ opcode field, and zeroes indicating those bits which need not
+ match (and are presumably filled in by operands). */
+ unsigned mask;
+
+ /* One bit flags for the opcode. These are primarily used to
+ indicate specific processors and environments support the
+ instructions. The defined values are listed below. */
+ unsigned flags;
+
+ /* An array of operand codes. Each code is an index into the
+ operand table. They appear in the order which the operands must
+ appear in assembly code, and are terminated by a zero. */
+ unsigned char operands[4];
+};
+
+/* The table itself is sorted by major opcode number, and is otherwise
+ in the order in which the disassembler should consider
+ instructions. */
+extern const struct alpha_opcode alpha_opcodes[];
+extern const unsigned alpha_num_opcodes;
+
+/* Values defined for the flags field of a struct alpha_opcode. */
+
+/* CPU Availability */
+#define AXP_OPCODE_BASE 0x0001 /* Base architecture -- all cpus. */
+#define AXP_OPCODE_EV4 0x0002 /* EV4 specific PALcode insns. */
+#define AXP_OPCODE_EV5 0x0004 /* EV5 specific PALcode insns. */
+#define AXP_OPCODE_EV6 0x0008 /* EV6 specific PALcode insns. */
+#define AXP_OPCODE_BWX 0x0100 /* Byte/word extension (amask bit 0). */
+#define AXP_OPCODE_CIX 0x0200 /* "Count" extension (amask bit 1). */
+#define AXP_OPCODE_MAX 0x0400 /* Multimedia extension (amask bit 8). */
+
+#define AXP_OPCODE_NOPAL (~(AXP_OPCODE_EV4|AXP_OPCODE_EV5|AXP_OPCODE_EV6))
+
+/* A macro to extract the major opcode from an instruction. */
+#define AXP_OP(i) (((i) >> 26) & 0x3F)
+
+/* The total number of major opcodes. */
+#define AXP_NOPS 0x40
+
+
+/* The operands table is an array of struct alpha_operand. */
+
+struct alpha_operand
+{
+ /* The number of bits in the operand. */
+ unsigned int bits : 5;
+
+ /* How far the operand is left shifted in the instruction. */
+ unsigned int shift : 5;
+
+ /* The default relocation type for this operand. */
+ signed int default_reloc : 16;
+
+ /* One bit syntax flags. */
+ unsigned int flags : 16;
+
+ /* Insertion function. This is used by the assembler. To insert an
+ operand value into an instruction, check this field.
+
+ If it is NULL, execute
+ i |= (op & ((1 << o->bits) - 1)) << o->shift;
+ (i is the instruction which we are filling in, o is a pointer to
+ this structure, and op is the opcode value; this assumes twos
+ complement arithmetic).
+
+ If this field is not NULL, then simply call it with the
+ instruction and the operand value. It will return the new value
+ of the instruction. If the ERRMSG argument is not NULL, then if
+ the operand value is illegal, *ERRMSG will be set to a warning
+ string (the operand will be inserted in any case). If the
+ operand value is legal, *ERRMSG will be unchanged (most operands
+ can accept any value). */
+ unsigned (*insert) (unsigned instruction, int op,
+ const char **errmsg);
+
+ /* Extraction function. This is used by the disassembler. To
+ extract this operand type from an instruction, check this field.
+
+ If it is NULL, compute
+ op = ((i) >> o->shift) & ((1 << o->bits) - 1);
+ if ((o->flags & AXP_OPERAND_SIGNED) != 0
+ && (op & (1 << (o->bits - 1))) != 0)
+ op -= 1 << o->bits;
+ (i is the instruction, o is a pointer to this structure, and op
+ is the result; this assumes twos complement arithmetic).
+
+ If this field is not NULL, then simply call it with the
+ instruction value. It will return the value of the operand. If
+ the INVALID argument is not NULL, *INVALID will be set to
+ non-zero if this operand type can not actually be extracted from
+ this operand (i.e., the instruction does not match). If the
+ operand is valid, *INVALID will not be changed. */
+ int (*extract) (unsigned instruction, int *invalid);
+};
+
+/* Elements in the table are retrieved by indexing with values from
+ the operands field of the alpha_opcodes table. */
+
+extern const struct alpha_operand alpha_operands[];
+extern const unsigned alpha_num_operands;
+
+/* Values defined for the flags field of a struct alpha_operand. */
+
+/* Mask for selecting the type for typecheck purposes */
+#define AXP_OPERAND_TYPECHECK_MASK \
+ (AXP_OPERAND_PARENS | AXP_OPERAND_COMMA | AXP_OPERAND_IR | \
+ AXP_OPERAND_FPR | AXP_OPERAND_RELATIVE | AXP_OPERAND_SIGNED | \
+ AXP_OPERAND_UNSIGNED)
+
+/* This operand does not actually exist in the assembler input. This
+ is used to support extended mnemonics, for which two operands fields
+ are identical. The assembler should call the insert function with
+ any op value. The disassembler should call the extract function,
+ ignore the return value, and check the value placed in the invalid
+ argument. */
+#define AXP_OPERAND_FAKE 01
+
+/* The operand should be wrapped in parentheses rather than separated
+ from the previous by a comma. This is used for the load and store
+ instructions which want their operands to look like "Ra,disp(Rb)". */
+#define AXP_OPERAND_PARENS 02
+
+/* Used in combination with PARENS, this suppresses the suppression of
+ the comma. This is used for "jmp Ra,(Rb),hint". */
+#define AXP_OPERAND_COMMA 04
+
+/* This operand names an integer register. */
+#define AXP_OPERAND_IR 010
+
+/* This operand names a floating point register. */
+#define AXP_OPERAND_FPR 020
+
+/* This operand is a relative branch displacement. The disassembler
+ prints these symbolically if possible. */
+#define AXP_OPERAND_RELATIVE 040
+
+/* This operand takes signed values. */
+#define AXP_OPERAND_SIGNED 0100
+
+/* This operand takes unsigned values. This exists primarily so that
+ a flags value of 0 can be treated as end-of-arguments. */
+#define AXP_OPERAND_UNSIGNED 0200
+
+/* Suppress overflow detection on this field. This is used for hints. */
+#define AXP_OPERAND_NOOVERFLOW 0400
+
+/* Mask for optional argument default value. */
+#define AXP_OPERAND_OPTIONAL_MASK 07000
+
+/* This operand defaults to zero. This is used for jump hints. */
+#define AXP_OPERAND_DEFAULT_ZERO 01000
+
+/* This operand should default to the first (real) operand and is used
+ in conjunction with AXP_OPERAND_OPTIONAL. This allows
+ "and $0,3,$0" to be written as "and $0,3", etc. I don't like
+ it, but it's what DEC does. */
+#define AXP_OPERAND_DEFAULT_FIRST 02000
+
+/* Similarly, this operand should default to the second (real) operand.
+ This allows "negl $0" instead of "negl $0,$0". */
+#define AXP_OPERAND_DEFAULT_SECOND 04000
+
+
+/* Register common names */
+
+#define AXP_REG_V0 0
+#define AXP_REG_T0 1
+#define AXP_REG_T1 2
+#define AXP_REG_T2 3
+#define AXP_REG_T3 4
+#define AXP_REG_T4 5
+#define AXP_REG_T5 6
+#define AXP_REG_T6 7
+#define AXP_REG_T7 8
+#define AXP_REG_S0 9
+#define AXP_REG_S1 10
+#define AXP_REG_S2 11
+#define AXP_REG_S3 12
+#define AXP_REG_S4 13
+#define AXP_REG_S5 14
+#define AXP_REG_FP 15
+#define AXP_REG_A0 16
+#define AXP_REG_A1 17
+#define AXP_REG_A2 18
+#define AXP_REG_A3 19
+#define AXP_REG_A4 20
+#define AXP_REG_A5 21
+#define AXP_REG_T8 22
+#define AXP_REG_T9 23
+#define AXP_REG_T10 24
+#define AXP_REG_T11 25
+#define AXP_REG_RA 26
+#define AXP_REG_PV 27
+#define AXP_REG_T12 27
+#define AXP_REG_AT 28
+#define AXP_REG_GP 29
+#define AXP_REG_SP 30
+#define AXP_REG_ZERO 31
+
+enum bfd_reloc_code_real {
+ BFD_RELOC_23_PCREL_S2,
+ BFD_RELOC_ALPHA_HINT
+};
+
+/* This file holds the Alpha AXP opcode table. The opcode table includes
+ almost all of the extended instruction mnemonics. This permits the
+ disassembler to use them, and simplifies the assembler logic, at the
+ cost of increasing the table size. The table is strictly constant
+ data, so the compiler should be able to put it in the text segment.
+
+ This file also holds the operand table. All knowledge about inserting
+ and extracting operands from instructions is kept in this file.
+
+ The information for the base instruction set was compiled from the
+ _Alpha Architecture Handbook_, Digital Order Number EC-QD2KB-TE,
+ version 2.
+
+ The information for the post-ev5 architecture extensions BWX, CIX and
+ MAX came from version 3 of this same document, which is also available
+ on-line at http://ftp.digital.com/pub/Digital/info/semiconductor
+ /literature/alphahb2.pdf
+
+ The information for the EV4 PALcode instructions was compiled from
+ _DECchip 21064 and DECchip 21064A Alpha AXP Microprocessors Hardware
+ Reference Manual_, Digital Order Number EC-Q9ZUA-TE, preliminary
+ revision dated June 1994.
+
+ The information for the EV5 PALcode instructions was compiled from
+ _Alpha 21164 Microprocessor Hardware Reference Manual_, Digital
+ Order Number EC-QAEQB-TE, preliminary revision dated April 1995. */
+
+/* Local insertion and extraction functions */
+
+static unsigned insert_rba (unsigned, int, const char **);
+static unsigned insert_rca (unsigned, int, const char **);
+static unsigned insert_za (unsigned, int, const char **);
+static unsigned insert_zb (unsigned, int, const char **);
+static unsigned insert_zc (unsigned, int, const char **);
+static unsigned insert_bdisp (unsigned, int, const char **);
+static unsigned insert_jhint (unsigned, int, const char **);
+static unsigned insert_ev6hwjhint (unsigned, int, const char **);
+
+static int extract_rba (unsigned, int *);
+static int extract_rca (unsigned, int *);
+static int extract_za (unsigned, int *);
+static int extract_zb (unsigned, int *);
+static int extract_zc (unsigned, int *);
+static int extract_bdisp (unsigned, int *);
+static int extract_jhint (unsigned, int *);
+static int extract_ev6hwjhint (unsigned, int *);
+
+
+/* The operands table */
+
+const struct alpha_operand alpha_operands[] =
+{
+ /* The fields are bits, shift, insert, extract, flags */
+ /* The zero index is used to indicate end-of-list */
+#define UNUSED 0
+ { 0, 0, 0, 0, 0, 0 },
+
+ /* The plain integer register fields */
+#define RA (UNUSED + 1)
+ { 5, 21, 0, AXP_OPERAND_IR, 0, 0 },
+#define RB (RA + 1)
+ { 5, 16, 0, AXP_OPERAND_IR, 0, 0 },
+#define RC (RB + 1)
+ { 5, 0, 0, AXP_OPERAND_IR, 0, 0 },
+
+ /* The plain fp register fields */
+#define FA (RC + 1)
+ { 5, 21, 0, AXP_OPERAND_FPR, 0, 0 },
+#define FB (FA + 1)
+ { 5, 16, 0, AXP_OPERAND_FPR, 0, 0 },
+#define FC (FB + 1)
+ { 5, 0, 0, AXP_OPERAND_FPR, 0, 0 },
+
+ /* The integer registers when they are ZERO */
+#define ZA (FC + 1)
+ { 5, 21, 0, AXP_OPERAND_FAKE, insert_za, extract_za },
+#define ZB (ZA + 1)
+ { 5, 16, 0, AXP_OPERAND_FAKE, insert_zb, extract_zb },
+#define ZC (ZB + 1)
+ { 5, 0, 0, AXP_OPERAND_FAKE, insert_zc, extract_zc },
+
+ /* The RB field when it needs parentheses */
+#define PRB (ZC + 1)
+ { 5, 16, 0, AXP_OPERAND_IR|AXP_OPERAND_PARENS, 0, 0 },
+
+ /* The RB field when it needs parentheses _and_ a preceding comma */
+#define CPRB (PRB + 1)
+ { 5, 16, 0,
+ AXP_OPERAND_IR|AXP_OPERAND_PARENS|AXP_OPERAND_COMMA, 0, 0 },
+
+ /* The RB field when it must be the same as the RA field */
+#define RBA (CPRB + 1)
+ { 5, 16, 0, AXP_OPERAND_FAKE, insert_rba, extract_rba },
+
+ /* The RC field when it must be the same as the RB field */
+#define RCA (RBA + 1)
+ { 5, 0, 0, AXP_OPERAND_FAKE, insert_rca, extract_rca },
+
+ /* The RC field when it can *default* to RA */
+#define DRC1 (RCA + 1)
+ { 5, 0, 0,
+ AXP_OPERAND_IR|AXP_OPERAND_DEFAULT_FIRST, 0, 0 },
+
+ /* The RC field when it can *default* to RB */
+#define DRC2 (DRC1 + 1)
+ { 5, 0, 0,
+ AXP_OPERAND_IR|AXP_OPERAND_DEFAULT_SECOND, 0, 0 },
+
+ /* The FC field when it can *default* to RA */
+#define DFC1 (DRC2 + 1)
+ { 5, 0, 0,
+ AXP_OPERAND_FPR|AXP_OPERAND_DEFAULT_FIRST, 0, 0 },
+
+ /* The FC field when it can *default* to RB */
+#define DFC2 (DFC1 + 1)
+ { 5, 0, 0,
+ AXP_OPERAND_FPR|AXP_OPERAND_DEFAULT_SECOND, 0, 0 },
+
+ /* The unsigned 8-bit literal of Operate format insns */
+#define LIT (DFC2 + 1)
+ { 8, 13, -LIT, AXP_OPERAND_UNSIGNED, 0, 0 },
+
+ /* The signed 16-bit displacement of Memory format insns. From here
+ we can't tell what relocation should be used, so don't use a default. */
+#define MDISP (LIT + 1)
+ { 16, 0, -MDISP, AXP_OPERAND_SIGNED, 0, 0 },
+
+ /* The signed "23-bit" aligned displacement of Branch format insns */
+#define BDISP (MDISP + 1)
+ { 21, 0, BFD_RELOC_23_PCREL_S2,
+ AXP_OPERAND_RELATIVE, insert_bdisp, extract_bdisp },
+
+ /* The 26-bit PALcode function */
+#define PALFN (BDISP + 1)
+ { 26, 0, -PALFN, AXP_OPERAND_UNSIGNED, 0, 0 },
+
+ /* The optional signed "16-bit" aligned displacement of the JMP/JSR hint */
+#define JMPHINT (PALFN + 1)
+ { 14, 0, BFD_RELOC_ALPHA_HINT,
+ AXP_OPERAND_RELATIVE|AXP_OPERAND_DEFAULT_ZERO|AXP_OPERAND_NOOVERFLOW,
+ insert_jhint, extract_jhint },
+
+ /* The optional hint to RET/JSR_COROUTINE */
+#define RETHINT (JMPHINT + 1)
+ { 14, 0, -RETHINT,
+ AXP_OPERAND_UNSIGNED|AXP_OPERAND_DEFAULT_ZERO, 0, 0 },
+
+ /* The 12-bit displacement for the ev[46] hw_{ld,st} (pal1b/pal1f) insns */
+#define EV4HWDISP (RETHINT + 1)
+#define EV6HWDISP (EV4HWDISP)
+ { 12, 0, -EV4HWDISP, AXP_OPERAND_SIGNED, 0, 0 },
+
+ /* The 5-bit index for the ev4 hw_m[ft]pr (pal19/pal1d) insns */
+#define EV4HWINDEX (EV4HWDISP + 1)
+ { 5, 0, -EV4HWINDEX, AXP_OPERAND_UNSIGNED, 0, 0 },
+
+ /* The 8-bit index for the oddly unqualified hw_m[tf]pr insns
+ that occur in DEC PALcode. */
+#define EV4EXTHWINDEX (EV4HWINDEX + 1)
+ { 8, 0, -EV4EXTHWINDEX, AXP_OPERAND_UNSIGNED, 0, 0 },
+
+ /* The 10-bit displacement for the ev5 hw_{ld,st} (pal1b/pal1f) insns */
+#define EV5HWDISP (EV4EXTHWINDEX + 1)
+ { 10, 0, -EV5HWDISP, AXP_OPERAND_SIGNED, 0, 0 },
+
+ /* The 16-bit index for the ev5 hw_m[ft]pr (pal19/pal1d) insns */
+#define EV5HWINDEX (EV5HWDISP + 1)
+ { 16, 0, -EV5HWINDEX, AXP_OPERAND_UNSIGNED, 0, 0 },
+
+ /* The 16-bit combined index/scoreboard mask for the ev6
+ hw_m[ft]pr (pal19/pal1d) insns */
+#define EV6HWINDEX (EV5HWINDEX + 1)
+ { 16, 0, -EV6HWINDEX, AXP_OPERAND_UNSIGNED, 0, 0 },
+
+ /* The 13-bit branch hint for the ev6 hw_jmp/jsr (pal1e) insn */
+#define EV6HWJMPHINT (EV6HWINDEX+ 1)
+ { 8, 0, -EV6HWJMPHINT,
+ AXP_OPERAND_RELATIVE|AXP_OPERAND_DEFAULT_ZERO|AXP_OPERAND_NOOVERFLOW,
+ insert_ev6hwjhint, extract_ev6hwjhint }
+};
+
+const unsigned alpha_num_operands = sizeof(alpha_operands)/sizeof(*alpha_operands);
+
+/* The RB field when it is the same as the RA field in the same insn.
+ This operand is marked fake. The insertion function just copies
+ the RA field into the RB field, and the extraction function just
+ checks that the fields are the same. */
+
+/*ARGSUSED*/
+static unsigned
+insert_rba(unsigned insn, int value ATTRIBUTE_UNUSED, const char **errmsg ATTRIBUTE_UNUSED)
+{
+ return insn | (((insn >> 21) & 0x1f) << 16);
+}
+
+static int
+extract_rba(unsigned insn, int *invalid)
+{
+ if (invalid != (int *) NULL
+ && ((insn >> 21) & 0x1f) != ((insn >> 16) & 0x1f))
+ *invalid = 1;
+ return 0;
+}
+
+
+/* The same for the RC field */
+
+/*ARGSUSED*/
+static unsigned
+insert_rca(unsigned insn, int value ATTRIBUTE_UNUSED, const char **errmsg ATTRIBUTE_UNUSED)
+{
+ return insn | ((insn >> 21) & 0x1f);
+}
+
+static int
+extract_rca(unsigned insn, int *invalid)
+{
+ if (invalid != (int *) NULL
+ && ((insn >> 21) & 0x1f) != (insn & 0x1f))
+ *invalid = 1;
+ return 0;
+}
+
+
+/* Fake arguments in which the registers must be set to ZERO */
+
+/*ARGSUSED*/
+static unsigned
+insert_za(unsigned insn, int value ATTRIBUTE_UNUSED, const char **errmsg ATTRIBUTE_UNUSED)
+{
+ return insn | (31 << 21);
+}
+
+static int
+extract_za(unsigned insn, int *invalid)
+{
+ if (invalid != (int *) NULL && ((insn >> 21) & 0x1f) != 31)
+ *invalid = 1;
+ return 0;
+}
+
+/*ARGSUSED*/
+static unsigned
+insert_zb(unsigned insn, int value ATTRIBUTE_UNUSED, const char **errmsg ATTRIBUTE_UNUSED)
+{
+ return insn | (31 << 16);
+}
+
+static int
+extract_zb(unsigned insn, int *invalid)
+{
+ if (invalid != (int *) NULL && ((insn >> 16) & 0x1f) != 31)
+ *invalid = 1;
+ return 0;
+}
+
+/*ARGSUSED*/
+static unsigned
+insert_zc(unsigned insn, int value ATTRIBUTE_UNUSED, const char **errmsg ATTRIBUTE_UNUSED)
+{
+ return insn | 31;
+}
+
+static int
+extract_zc(unsigned insn, int *invalid)
+{
+ if (invalid != (int *) NULL && (insn & 0x1f) != 31)
+ *invalid = 1;
+ return 0;
+}
+
+
+/* The displacement field of a Branch format insn. */
+
+static unsigned
+insert_bdisp(unsigned insn, int value, const char **errmsg)
+{
+ if (errmsg != (const char **)NULL && (value & 3))
+ *errmsg = _("branch operand unaligned");
+ return insn | ((value / 4) & 0x1FFFFF);
+}
+
+/*ARGSUSED*/
+static int
+extract_bdisp(unsigned insn, int *invalid ATTRIBUTE_UNUSED)
+{
+ return 4 * (((insn & 0x1FFFFF) ^ 0x100000) - 0x100000);
+}
+
+
+/* The hint field of a JMP/JSR insn. */
+
+static unsigned
+insert_jhint(unsigned insn, int value, const char **errmsg)
+{
+ if (errmsg != (const char **)NULL && (value & 3))
+ *errmsg = _("jump hint unaligned");
+ return insn | ((value / 4) & 0x3FFF);
+}
+
+/*ARGSUSED*/
+static int
+extract_jhint(unsigned insn, int *invalid ATTRIBUTE_UNUSED)
+{
+ return 4 * (((insn & 0x3FFF) ^ 0x2000) - 0x2000);
+}
+
+/* The hint field of an EV6 HW_JMP/JSR insn. */
+
+static unsigned
+insert_ev6hwjhint(unsigned insn, int value, const char **errmsg)
+{
+ if (errmsg != (const char **)NULL && (value & 3))
+ *errmsg = _("jump hint unaligned");
+ return insn | ((value / 4) & 0x1FFF);
+}
+
+/*ARGSUSED*/
+static int
+extract_ev6hwjhint(unsigned insn, int *invalid ATTRIBUTE_UNUSED)
+{
+ return 4 * (((insn & 0x1FFF) ^ 0x1000) - 0x1000);
+}
+
+
+/* Macros used to form opcodes */
+
+/* The main opcode */
+#define OP(x) (((x) & 0x3F) << 26)
+#define OP_MASK 0xFC000000
+
+/* Branch format instructions */
+#define BRA_(oo) OP(oo)
+#define BRA_MASK OP_MASK
+#define BRA(oo) BRA_(oo), BRA_MASK
+
+/* Floating point format instructions */
+#define FP_(oo,fff) (OP(oo) | (((fff) & 0x7FF) << 5))
+#define FP_MASK (OP_MASK | 0xFFE0)
+#define FP(oo,fff) FP_(oo,fff), FP_MASK
+
+/* Memory format instructions */
+#define MEM_(oo) OP(oo)
+#define MEM_MASK OP_MASK
+#define MEM(oo) MEM_(oo), MEM_MASK
+
+/* Memory/Func Code format instructions */
+#define MFC_(oo,ffff) (OP(oo) | ((ffff) & 0xFFFF))
+#define MFC_MASK (OP_MASK | 0xFFFF)
+#define MFC(oo,ffff) MFC_(oo,ffff), MFC_MASK
+
+/* Memory/Branch format instructions */
+#define MBR_(oo,h) (OP(oo) | (((h) & 3) << 14))
+#define MBR_MASK (OP_MASK | 0xC000)
+#define MBR(oo,h) MBR_(oo,h), MBR_MASK
+
+/* Operate format instructions. The OPRL variant specifies a
+ literal second argument. */
+#define OPR_(oo,ff) (OP(oo) | (((ff) & 0x7F) << 5))
+#define OPRL_(oo,ff) (OPR_((oo),(ff)) | 0x1000)
+#define OPR_MASK (OP_MASK | 0x1FE0)
+#define OPR(oo,ff) OPR_(oo,ff), OPR_MASK
+#define OPRL(oo,ff) OPRL_(oo,ff), OPR_MASK
+
+/* Generic PALcode format instructions */
+#define PCD_(oo) OP(oo)
+#define PCD_MASK OP_MASK
+#define PCD(oo) PCD_(oo), PCD_MASK
+
+/* Specific PALcode instructions */
+#define SPCD_(oo,ffff) (OP(oo) | ((ffff) & 0x3FFFFFF))
+#define SPCD_MASK 0xFFFFFFFF
+#define SPCD(oo,ffff) SPCD_(oo,ffff), SPCD_MASK
+
+/* Hardware memory (hw_{ld,st}) instructions */
+#define EV4HWMEM_(oo,f) (OP(oo) | (((f) & 0xF) << 12))
+#define EV4HWMEM_MASK (OP_MASK | 0xF000)
+#define EV4HWMEM(oo,f) EV4HWMEM_(oo,f), EV4HWMEM_MASK
+
+#define EV5HWMEM_(oo,f) (OP(oo) | (((f) & 0x3F) << 10))
+#define EV5HWMEM_MASK (OP_MASK | 0xF800)
+#define EV5HWMEM(oo,f) EV5HWMEM_(oo,f), EV5HWMEM_MASK
+
+#define EV6HWMEM_(oo,f) (OP(oo) | (((f) & 0xF) << 12))
+#define EV6HWMEM_MASK (OP_MASK | 0xF000)
+#define EV6HWMEM(oo,f) EV6HWMEM_(oo,f), EV6HWMEM_MASK
+
+#define EV6HWMBR_(oo,h) (OP(oo) | (((h) & 7) << 13))
+#define EV6HWMBR_MASK (OP_MASK | 0xE000)
+#define EV6HWMBR(oo,h) EV6HWMBR_(oo,h), EV6HWMBR_MASK
+
+/* Abbreviations for instruction subsets. */
+#define BASE AXP_OPCODE_BASE
+#define EV4 AXP_OPCODE_EV4
+#define EV5 AXP_OPCODE_EV5
+#define EV6 AXP_OPCODE_EV6
+#define BWX AXP_OPCODE_BWX
+#define CIX AXP_OPCODE_CIX
+#define MAX AXP_OPCODE_MAX
+
+/* Common combinations of arguments */
+#define ARG_NONE { 0 }
+#define ARG_BRA { RA, BDISP }
+#define ARG_FBRA { FA, BDISP }
+#define ARG_FP { FA, FB, DFC1 }
+#define ARG_FPZ1 { ZA, FB, DFC1 }
+#define ARG_MEM { RA, MDISP, PRB }
+#define ARG_FMEM { FA, MDISP, PRB }
+#define ARG_OPR { RA, RB, DRC1 }
+#define ARG_OPRL { RA, LIT, DRC1 }
+#define ARG_OPRZ1 { ZA, RB, DRC1 }
+#define ARG_OPRLZ1 { ZA, LIT, RC }
+#define ARG_PCD { PALFN }
+#define ARG_EV4HWMEM { RA, EV4HWDISP, PRB }
+#define ARG_EV4HWMPR { RA, RBA, EV4HWINDEX }
+#define ARG_EV5HWMEM { RA, EV5HWDISP, PRB }
+#define ARG_EV6HWMEM { RA, EV6HWDISP, PRB }
+
+/* The opcode table.
+
+ The format of the opcode table is:
+
+ NAME OPCODE MASK { OPERANDS }
+
+ NAME is the name of the instruction.
+
+ OPCODE is the instruction opcode.
+
+ MASK is the opcode mask; this is used to tell the disassembler
+ which bits in the actual opcode must match OPCODE.
+
+ OPERANDS is the list of operands.
+
+ The preceding macros merge the text of the OPCODE and MASK fields.
+
+ The disassembler reads the table in order and prints the first
+ instruction which matches, so this table is sorted to put more
+ specific instructions before more general instructions.
+
+ Otherwise, it is sorted by major opcode and minor function code.
+
+ There are three classes of not-really-instructions in this table:
+
+ ALIAS is another name for another instruction. Some of
+ these come from the Architecture Handbook, some
+ come from the original gas opcode tables. In all
+ cases, the functionality of the opcode is unchanged.
+
+ PSEUDO a stylized code form endorsed by Chapter A.4 of the
+ Architecture Handbook.
+
+ EXTRA a stylized code form found in the original gas tables.
+
+ And two annotations:
+
+ EV56 BUT opcodes that are officially introduced as of the ev56,
+ but with defined results on previous implementations.
+
+ EV56 UNA opcodes that were introduced as of the ev56 with
+ presumably undefined results on previous implementations
+ that were not assigned to a particular extension.
+*/
+
+const struct alpha_opcode alpha_opcodes[] = {
+ { "halt", SPCD(0x00,0x0000), BASE, ARG_NONE },
+ { "draina", SPCD(0x00,0x0002), BASE, ARG_NONE },
+ { "bpt", SPCD(0x00,0x0080), BASE, ARG_NONE },
+ { "bugchk", SPCD(0x00,0x0081), BASE, ARG_NONE },
+ { "callsys", SPCD(0x00,0x0083), BASE, ARG_NONE },
+ { "chmk", SPCD(0x00,0x0083), BASE, ARG_NONE },
+ { "imb", SPCD(0x00,0x0086), BASE, ARG_NONE },
+ { "rduniq", SPCD(0x00,0x009e), BASE, ARG_NONE },
+ { "wruniq", SPCD(0x00,0x009f), BASE, ARG_NONE },
+ { "gentrap", SPCD(0x00,0x00aa), BASE, ARG_NONE },
+ { "call_pal", PCD(0x00), BASE, ARG_PCD },
+ { "pal", PCD(0x00), BASE, ARG_PCD }, /* alias */
+
+ { "lda", MEM(0x08), BASE, { RA, MDISP, ZB } }, /* pseudo */
+ { "lda", MEM(0x08), BASE, ARG_MEM },
+ { "ldah", MEM(0x09), BASE, { RA, MDISP, ZB } }, /* pseudo */
+ { "ldah", MEM(0x09), BASE, ARG_MEM },
+ { "ldbu", MEM(0x0A), BWX, ARG_MEM },
+ { "unop", MEM_(0x0B) | (30 << 16),
+ MEM_MASK, BASE, { ZA } }, /* pseudo */
+ { "ldq_u", MEM(0x0B), BASE, ARG_MEM },
+ { "ldwu", MEM(0x0C), BWX, ARG_MEM },
+ { "stw", MEM(0x0D), BWX, ARG_MEM },
+ { "stb", MEM(0x0E), BWX, ARG_MEM },
+ { "stq_u", MEM(0x0F), BASE, ARG_MEM },
+
+ { "sextl", OPR(0x10,0x00), BASE, ARG_OPRZ1 }, /* pseudo */
+ { "sextl", OPRL(0x10,0x00), BASE, ARG_OPRLZ1 }, /* pseudo */
+ { "addl", OPR(0x10,0x00), BASE, ARG_OPR },
+ { "addl", OPRL(0x10,0x00), BASE, ARG_OPRL },
+ { "s4addl", OPR(0x10,0x02), BASE, ARG_OPR },
+ { "s4addl", OPRL(0x10,0x02), BASE, ARG_OPRL },
+ { "negl", OPR(0x10,0x09), BASE, ARG_OPRZ1 }, /* pseudo */
+ { "negl", OPRL(0x10,0x09), BASE, ARG_OPRLZ1 }, /* pseudo */
+ { "subl", OPR(0x10,0x09), BASE, ARG_OPR },
+ { "subl", OPRL(0x10,0x09), BASE, ARG_OPRL },
+ { "s4subl", OPR(0x10,0x0B), BASE, ARG_OPR },
+ { "s4subl", OPRL(0x10,0x0B), BASE, ARG_OPRL },
+ { "cmpbge", OPR(0x10,0x0F), BASE, ARG_OPR },
+ { "cmpbge", OPRL(0x10,0x0F), BASE, ARG_OPRL },
+ { "s8addl", OPR(0x10,0x12), BASE, ARG_OPR },
+ { "s8addl", OPRL(0x10,0x12), BASE, ARG_OPRL },
+ { "s8subl", OPR(0x10,0x1B), BASE, ARG_OPR },
+ { "s8subl", OPRL(0x10,0x1B), BASE, ARG_OPRL },
+ { "cmpult", OPR(0x10,0x1D), BASE, ARG_OPR },
+ { "cmpult", OPRL(0x10,0x1D), BASE, ARG_OPRL },
+ { "addq", OPR(0x10,0x20), BASE, ARG_OPR },
+ { "addq", OPRL(0x10,0x20), BASE, ARG_OPRL },
+ { "s4addq", OPR(0x10,0x22), BASE, ARG_OPR },
+ { "s4addq", OPRL(0x10,0x22), BASE, ARG_OPRL },
+ { "negq", OPR(0x10,0x29), BASE, ARG_OPRZ1 }, /* pseudo */
+ { "negq", OPRL(0x10,0x29), BASE, ARG_OPRLZ1 }, /* pseudo */
+ { "subq", OPR(0x10,0x29), BASE, ARG_OPR },
+ { "subq", OPRL(0x10,0x29), BASE, ARG_OPRL },
+ { "s4subq", OPR(0x10,0x2B), BASE, ARG_OPR },
+ { "s4subq", OPRL(0x10,0x2B), BASE, ARG_OPRL },
+ { "cmpeq", OPR(0x10,0x2D), BASE, ARG_OPR },
+ { "cmpeq", OPRL(0x10,0x2D), BASE, ARG_OPRL },
+ { "s8addq", OPR(0x10,0x32), BASE, ARG_OPR },
+ { "s8addq", OPRL(0x10,0x32), BASE, ARG_OPRL },
+ { "s8subq", OPR(0x10,0x3B), BASE, ARG_OPR },
+ { "s8subq", OPRL(0x10,0x3B), BASE, ARG_OPRL },
+ { "cmpule", OPR(0x10,0x3D), BASE, ARG_OPR },
+ { "cmpule", OPRL(0x10,0x3D), BASE, ARG_OPRL },
+ { "addl/v", OPR(0x10,0x40), BASE, ARG_OPR },
+ { "addl/v", OPRL(0x10,0x40), BASE, ARG_OPRL },
+ { "negl/v", OPR(0x10,0x49), BASE, ARG_OPRZ1 }, /* pseudo */
+ { "negl/v", OPRL(0x10,0x49), BASE, ARG_OPRLZ1 }, /* pseudo */
+ { "subl/v", OPR(0x10,0x49), BASE, ARG_OPR },
+ { "subl/v", OPRL(0x10,0x49), BASE, ARG_OPRL },
+ { "cmplt", OPR(0x10,0x4D), BASE, ARG_OPR },
+ { "cmplt", OPRL(0x10,0x4D), BASE, ARG_OPRL },
+ { "addq/v", OPR(0x10,0x60), BASE, ARG_OPR },
+ { "addq/v", OPRL(0x10,0x60), BASE, ARG_OPRL },
+ { "negq/v", OPR(0x10,0x69), BASE, ARG_OPRZ1 }, /* pseudo */
+ { "negq/v", OPRL(0x10,0x69), BASE, ARG_OPRLZ1 }, /* pseudo */
+ { "subq/v", OPR(0x10,0x69), BASE, ARG_OPR },
+ { "subq/v", OPRL(0x10,0x69), BASE, ARG_OPRL },
+ { "cmple", OPR(0x10,0x6D), BASE, ARG_OPR },
+ { "cmple", OPRL(0x10,0x6D), BASE, ARG_OPRL },
+
+ { "and", OPR(0x11,0x00), BASE, ARG_OPR },
+ { "and", OPRL(0x11,0x00), BASE, ARG_OPRL },
+ { "andnot", OPR(0x11,0x08), BASE, ARG_OPR }, /* alias */
+ { "andnot", OPRL(0x11,0x08), BASE, ARG_OPRL }, /* alias */
+ { "bic", OPR(0x11,0x08), BASE, ARG_OPR },
+ { "bic", OPRL(0x11,0x08), BASE, ARG_OPRL },
+ { "cmovlbs", OPR(0x11,0x14), BASE, ARG_OPR },
+ { "cmovlbs", OPRL(0x11,0x14), BASE, ARG_OPRL },
+ { "cmovlbc", OPR(0x11,0x16), BASE, ARG_OPR },
+ { "cmovlbc", OPRL(0x11,0x16), BASE, ARG_OPRL },
+ { "nop", OPR(0x11,0x20), BASE, { ZA, ZB, ZC } }, /* pseudo */
+ { "clr", OPR(0x11,0x20), BASE, { ZA, ZB, RC } }, /* pseudo */
+ { "mov", OPR(0x11,0x20), BASE, { ZA, RB, RC } }, /* pseudo */
+ { "mov", OPR(0x11,0x20), BASE, { RA, RBA, RC } }, /* pseudo */
+ { "mov", OPRL(0x11,0x20), BASE, { ZA, LIT, RC } }, /* pseudo */
+ { "or", OPR(0x11,0x20), BASE, ARG_OPR }, /* alias */
+ { "or", OPRL(0x11,0x20), BASE, ARG_OPRL }, /* alias */
+ { "bis", OPR(0x11,0x20), BASE, ARG_OPR },
+ { "bis", OPRL(0x11,0x20), BASE, ARG_OPRL },
+ { "cmoveq", OPR(0x11,0x24), BASE, ARG_OPR },
+ { "cmoveq", OPRL(0x11,0x24), BASE, ARG_OPRL },
+ { "cmovne", OPR(0x11,0x26), BASE, ARG_OPR },
+ { "cmovne", OPRL(0x11,0x26), BASE, ARG_OPRL },
+ { "not", OPR(0x11,0x28), BASE, ARG_OPRZ1 }, /* pseudo */
+ { "not", OPRL(0x11,0x28), BASE, ARG_OPRLZ1 }, /* pseudo */
+ { "ornot", OPR(0x11,0x28), BASE, ARG_OPR },
+ { "ornot", OPRL(0x11,0x28), BASE, ARG_OPRL },
+ { "xor", OPR(0x11,0x40), BASE, ARG_OPR },
+ { "xor", OPRL(0x11,0x40), BASE, ARG_OPRL },
+ { "cmovlt", OPR(0x11,0x44), BASE, ARG_OPR },
+ { "cmovlt", OPRL(0x11,0x44), BASE, ARG_OPRL },
+ { "cmovge", OPR(0x11,0x46), BASE, ARG_OPR },
+ { "cmovge", OPRL(0x11,0x46), BASE, ARG_OPRL },
+ { "eqv", OPR(0x11,0x48), BASE, ARG_OPR },
+ { "eqv", OPRL(0x11,0x48), BASE, ARG_OPRL },
+ { "xornot", OPR(0x11,0x48), BASE, ARG_OPR }, /* alias */
+ { "xornot", OPRL(0x11,0x48), BASE, ARG_OPRL }, /* alias */
+ { "amask", OPR(0x11,0x61), BASE, ARG_OPRZ1 }, /* ev56 but */
+ { "amask", OPRL(0x11,0x61), BASE, ARG_OPRLZ1 }, /* ev56 but */
+ { "cmovle", OPR(0x11,0x64), BASE, ARG_OPR },
+ { "cmovle", OPRL(0x11,0x64), BASE, ARG_OPRL },
+ { "cmovgt", OPR(0x11,0x66), BASE, ARG_OPR },
+ { "cmovgt", OPRL(0x11,0x66), BASE, ARG_OPRL },
+ { "implver", OPRL_(0x11,0x6C)|(31<<21)|(1<<13),
+ 0xFFFFFFE0, BASE, { RC } }, /* ev56 but */
+
+ { "mskbl", OPR(0x12,0x02), BASE, ARG_OPR },
+ { "mskbl", OPRL(0x12,0x02), BASE, ARG_OPRL },
+ { "extbl", OPR(0x12,0x06), BASE, ARG_OPR },
+ { "extbl", OPRL(0x12,0x06), BASE, ARG_OPRL },
+ { "insbl", OPR(0x12,0x0B), BASE, ARG_OPR },
+ { "insbl", OPRL(0x12,0x0B), BASE, ARG_OPRL },
+ { "mskwl", OPR(0x12,0x12), BASE, ARG_OPR },
+ { "mskwl", OPRL(0x12,0x12), BASE, ARG_OPRL },
+ { "extwl", OPR(0x12,0x16), BASE, ARG_OPR },
+ { "extwl", OPRL(0x12,0x16), BASE, ARG_OPRL },
+ { "inswl", OPR(0x12,0x1B), BASE, ARG_OPR },
+ { "inswl", OPRL(0x12,0x1B), BASE, ARG_OPRL },
+ { "mskll", OPR(0x12,0x22), BASE, ARG_OPR },
+ { "mskll", OPRL(0x12,0x22), BASE, ARG_OPRL },
+ { "extll", OPR(0x12,0x26), BASE, ARG_OPR },
+ { "extll", OPRL(0x12,0x26), BASE, ARG_OPRL },
+ { "insll", OPR(0x12,0x2B), BASE, ARG_OPR },
+ { "insll", OPRL(0x12,0x2B), BASE, ARG_OPRL },
+ { "zap", OPR(0x12,0x30), BASE, ARG_OPR },
+ { "zap", OPRL(0x12,0x30), BASE, ARG_OPRL },
+ { "zapnot", OPR(0x12,0x31), BASE, ARG_OPR },
+ { "zapnot", OPRL(0x12,0x31), BASE, ARG_OPRL },
+ { "mskql", OPR(0x12,0x32), BASE, ARG_OPR },
+ { "mskql", OPRL(0x12,0x32), BASE, ARG_OPRL },
+ { "srl", OPR(0x12,0x34), BASE, ARG_OPR },
+ { "srl", OPRL(0x12,0x34), BASE, ARG_OPRL },
+ { "extql", OPR(0x12,0x36), BASE, ARG_OPR },
+ { "extql", OPRL(0x12,0x36), BASE, ARG_OPRL },
+ { "sll", OPR(0x12,0x39), BASE, ARG_OPR },
+ { "sll", OPRL(0x12,0x39), BASE, ARG_OPRL },
+ { "insql", OPR(0x12,0x3B), BASE, ARG_OPR },
+ { "insql", OPRL(0x12,0x3B), BASE, ARG_OPRL },
+ { "sra", OPR(0x12,0x3C), BASE, ARG_OPR },
+ { "sra", OPRL(0x12,0x3C), BASE, ARG_OPRL },
+ { "mskwh", OPR(0x12,0x52), BASE, ARG_OPR },
+ { "mskwh", OPRL(0x12,0x52), BASE, ARG_OPRL },
+ { "inswh", OPR(0x12,0x57), BASE, ARG_OPR },
+ { "inswh", OPRL(0x12,0x57), BASE, ARG_OPRL },
+ { "extwh", OPR(0x12,0x5A), BASE, ARG_OPR },
+ { "extwh", OPRL(0x12,0x5A), BASE, ARG_OPRL },
+ { "msklh", OPR(0x12,0x62), BASE, ARG_OPR },
+ { "msklh", OPRL(0x12,0x62), BASE, ARG_OPRL },
+ { "inslh", OPR(0x12,0x67), BASE, ARG_OPR },
+ { "inslh", OPRL(0x12,0x67), BASE, ARG_OPRL },
+ { "extlh", OPR(0x12,0x6A), BASE, ARG_OPR },
+ { "extlh", OPRL(0x12,0x6A), BASE, ARG_OPRL },
+ { "mskqh", OPR(0x12,0x72), BASE, ARG_OPR },
+ { "mskqh", OPRL(0x12,0x72), BASE, ARG_OPRL },
+ { "insqh", OPR(0x12,0x77), BASE, ARG_OPR },
+ { "insqh", OPRL(0x12,0x77), BASE, ARG_OPRL },
+ { "extqh", OPR(0x12,0x7A), BASE, ARG_OPR },
+ { "extqh", OPRL(0x12,0x7A), BASE, ARG_OPRL },
+
+ { "mull", OPR(0x13,0x00), BASE, ARG_OPR },
+ { "mull", OPRL(0x13,0x00), BASE, ARG_OPRL },
+ { "mulq", OPR(0x13,0x20), BASE, ARG_OPR },
+ { "mulq", OPRL(0x13,0x20), BASE, ARG_OPRL },
+ { "umulh", OPR(0x13,0x30), BASE, ARG_OPR },
+ { "umulh", OPRL(0x13,0x30), BASE, ARG_OPRL },
+ { "mull/v", OPR(0x13,0x40), BASE, ARG_OPR },
+ { "mull/v", OPRL(0x13,0x40), BASE, ARG_OPRL },
+ { "mulq/v", OPR(0x13,0x60), BASE, ARG_OPR },
+ { "mulq/v", OPRL(0x13,0x60), BASE, ARG_OPRL },
+
+ { "itofs", FP(0x14,0x004), CIX, { RA, ZB, FC } },
+ { "sqrtf/c", FP(0x14,0x00A), CIX, ARG_FPZ1 },
+ { "sqrts/c", FP(0x14,0x00B), CIX, ARG_FPZ1 },
+ { "itoff", FP(0x14,0x014), CIX, { RA, ZB, FC } },
+ { "itoft", FP(0x14,0x024), CIX, { RA, ZB, FC } },
+ { "sqrtg/c", FP(0x14,0x02A), CIX, ARG_FPZ1 },
+ { "sqrtt/c", FP(0x14,0x02B), CIX, ARG_FPZ1 },
+ { "sqrts/m", FP(0x14,0x04B), CIX, ARG_FPZ1 },
+ { "sqrtt/m", FP(0x14,0x06B), CIX, ARG_FPZ1 },
+ { "sqrtf", FP(0x14,0x08A), CIX, ARG_FPZ1 },
+ { "sqrts", FP(0x14,0x08B), CIX, ARG_FPZ1 },
+ { "sqrtg", FP(0x14,0x0AA), CIX, ARG_FPZ1 },
+ { "sqrtt", FP(0x14,0x0AB), CIX, ARG_FPZ1 },
+ { "sqrts/d", FP(0x14,0x0CB), CIX, ARG_FPZ1 },
+ { "sqrtt/d", FP(0x14,0x0EB), CIX, ARG_FPZ1 },
+ { "sqrtf/uc", FP(0x14,0x10A), CIX, ARG_FPZ1 },
+ { "sqrts/uc", FP(0x14,0x10B), CIX, ARG_FPZ1 },
+ { "sqrtg/uc", FP(0x14,0x12A), CIX, ARG_FPZ1 },
+ { "sqrtt/uc", FP(0x14,0x12B), CIX, ARG_FPZ1 },
+ { "sqrts/um", FP(0x14,0x14B), CIX, ARG_FPZ1 },
+ { "sqrtt/um", FP(0x14,0x16B), CIX, ARG_FPZ1 },
+ { "sqrtf/u", FP(0x14,0x18A), CIX, ARG_FPZ1 },
+ { "sqrts/u", FP(0x14,0x18B), CIX, ARG_FPZ1 },
+ { "sqrtg/u", FP(0x14,0x1AA), CIX, ARG_FPZ1 },
+ { "sqrtt/u", FP(0x14,0x1AB), CIX, ARG_FPZ1 },
+ { "sqrts/ud", FP(0x14,0x1CB), CIX, ARG_FPZ1 },
+ { "sqrtt/ud", FP(0x14,0x1EB), CIX, ARG_FPZ1 },
+ { "sqrtf/sc", FP(0x14,0x40A), CIX, ARG_FPZ1 },
+ { "sqrtg/sc", FP(0x14,0x42A), CIX, ARG_FPZ1 },
+ { "sqrtf/s", FP(0x14,0x48A), CIX, ARG_FPZ1 },
+ { "sqrtg/s", FP(0x14,0x4AA), CIX, ARG_FPZ1 },
+ { "sqrtf/suc", FP(0x14,0x50A), CIX, ARG_FPZ1 },
+ { "sqrts/suc", FP(0x14,0x50B), CIX, ARG_FPZ1 },
+ { "sqrtg/suc", FP(0x14,0x52A), CIX, ARG_FPZ1 },
+ { "sqrtt/suc", FP(0x14,0x52B), CIX, ARG_FPZ1 },
+ { "sqrts/sum", FP(0x14,0x54B), CIX, ARG_FPZ1 },
+ { "sqrtt/sum", FP(0x14,0x56B), CIX, ARG_FPZ1 },
+ { "sqrtf/su", FP(0x14,0x58A), CIX, ARG_FPZ1 },
+ { "sqrts/su", FP(0x14,0x58B), CIX, ARG_FPZ1 },
+ { "sqrtg/su", FP(0x14,0x5AA), CIX, ARG_FPZ1 },
+ { "sqrtt/su", FP(0x14,0x5AB), CIX, ARG_FPZ1 },
+ { "sqrts/sud", FP(0x14,0x5CB), CIX, ARG_FPZ1 },
+ { "sqrtt/sud", FP(0x14,0x5EB), CIX, ARG_FPZ1 },
+ { "sqrts/suic", FP(0x14,0x70B), CIX, ARG_FPZ1 },
+ { "sqrtt/suic", FP(0x14,0x72B), CIX, ARG_FPZ1 },
+ { "sqrts/suim", FP(0x14,0x74B), CIX, ARG_FPZ1 },
+ { "sqrtt/suim", FP(0x14,0x76B), CIX, ARG_FPZ1 },
+ { "sqrts/sui", FP(0x14,0x78B), CIX, ARG_FPZ1 },
+ { "sqrtt/sui", FP(0x14,0x7AB), CIX, ARG_FPZ1 },
+ { "sqrts/suid", FP(0x14,0x7CB), CIX, ARG_FPZ1 },
+ { "sqrtt/suid", FP(0x14,0x7EB), CIX, ARG_FPZ1 },
+
+ { "addf/c", FP(0x15,0x000), BASE, ARG_FP },
+ { "subf/c", FP(0x15,0x001), BASE, ARG_FP },
+ { "mulf/c", FP(0x15,0x002), BASE, ARG_FP },
+ { "divf/c", FP(0x15,0x003), BASE, ARG_FP },
+ { "cvtdg/c", FP(0x15,0x01E), BASE, ARG_FPZ1 },
+ { "addg/c", FP(0x15,0x020), BASE, ARG_FP },
+ { "subg/c", FP(0x15,0x021), BASE, ARG_FP },
+ { "mulg/c", FP(0x15,0x022), BASE, ARG_FP },
+ { "divg/c", FP(0x15,0x023), BASE, ARG_FP },
+ { "cvtgf/c", FP(0x15,0x02C), BASE, ARG_FPZ1 },
+ { "cvtgd/c", FP(0x15,0x02D), BASE, ARG_FPZ1 },
+ { "cvtgq/c", FP(0x15,0x02F), BASE, ARG_FPZ1 },
+ { "cvtqf/c", FP(0x15,0x03C), BASE, ARG_FPZ1 },
+ { "cvtqg/c", FP(0x15,0x03E), BASE, ARG_FPZ1 },
+ { "addf", FP(0x15,0x080), BASE, ARG_FP },
+ { "negf", FP(0x15,0x081), BASE, ARG_FPZ1 }, /* pseudo */
+ { "subf", FP(0x15,0x081), BASE, ARG_FP },
+ { "mulf", FP(0x15,0x082), BASE, ARG_FP },
+ { "divf", FP(0x15,0x083), BASE, ARG_FP },
+ { "cvtdg", FP(0x15,0x09E), BASE, ARG_FPZ1 },
+ { "addg", FP(0x15,0x0A0), BASE, ARG_FP },
+ { "negg", FP(0x15,0x0A1), BASE, ARG_FPZ1 }, /* pseudo */
+ { "subg", FP(0x15,0x0A1), BASE, ARG_FP },
+ { "mulg", FP(0x15,0x0A2), BASE, ARG_FP },
+ { "divg", FP(0x15,0x0A3), BASE, ARG_FP },
+ { "cmpgeq", FP(0x15,0x0A5), BASE, ARG_FP },
+ { "cmpglt", FP(0x15,0x0A6), BASE, ARG_FP },
+ { "cmpgle", FP(0x15,0x0A7), BASE, ARG_FP },
+ { "cvtgf", FP(0x15,0x0AC), BASE, ARG_FPZ1 },
+ { "cvtgd", FP(0x15,0x0AD), BASE, ARG_FPZ1 },
+ { "cvtgq", FP(0x15,0x0AF), BASE, ARG_FPZ1 },
+ { "cvtqf", FP(0x15,0x0BC), BASE, ARG_FPZ1 },
+ { "cvtqg", FP(0x15,0x0BE), BASE, ARG_FPZ1 },
+ { "addf/uc", FP(0x15,0x100), BASE, ARG_FP },
+ { "subf/uc", FP(0x15,0x101), BASE, ARG_FP },
+ { "mulf/uc", FP(0x15,0x102), BASE, ARG_FP },
+ { "divf/uc", FP(0x15,0x103), BASE, ARG_FP },
+ { "cvtdg/uc", FP(0x15,0x11E), BASE, ARG_FPZ1 },
+ { "addg/uc", FP(0x15,0x120), BASE, ARG_FP },
+ { "subg/uc", FP(0x15,0x121), BASE, ARG_FP },
+ { "mulg/uc", FP(0x15,0x122), BASE, ARG_FP },
+ { "divg/uc", FP(0x15,0x123), BASE, ARG_FP },
+ { "cvtgf/uc", FP(0x15,0x12C), BASE, ARG_FPZ1 },
+ { "cvtgd/uc", FP(0x15,0x12D), BASE, ARG_FPZ1 },
+ { "cvtgq/vc", FP(0x15,0x12F), BASE, ARG_FPZ1 },
+ { "addf/u", FP(0x15,0x180), BASE, ARG_FP },
+ { "subf/u", FP(0x15,0x181), BASE, ARG_FP },
+ { "mulf/u", FP(0x15,0x182), BASE, ARG_FP },
+ { "divf/u", FP(0x15,0x183), BASE, ARG_FP },
+ { "cvtdg/u", FP(0x15,0x19E), BASE, ARG_FPZ1 },
+ { "addg/u", FP(0x15,0x1A0), BASE, ARG_FP },
+ { "subg/u", FP(0x15,0x1A1), BASE, ARG_FP },
+ { "mulg/u", FP(0x15,0x1A2), BASE, ARG_FP },
+ { "divg/u", FP(0x15,0x1A3), BASE, ARG_FP },
+ { "cvtgf/u", FP(0x15,0x1AC), BASE, ARG_FPZ1 },
+ { "cvtgd/u", FP(0x15,0x1AD), BASE, ARG_FPZ1 },
+ { "cvtgq/v", FP(0x15,0x1AF), BASE, ARG_FPZ1 },
+ { "addf/sc", FP(0x15,0x400), BASE, ARG_FP },
+ { "subf/sc", FP(0x15,0x401), BASE, ARG_FP },
+ { "mulf/sc", FP(0x15,0x402), BASE, ARG_FP },
+ { "divf/sc", FP(0x15,0x403), BASE, ARG_FP },
+ { "cvtdg/sc", FP(0x15,0x41E), BASE, ARG_FPZ1 },
+ { "addg/sc", FP(0x15,0x420), BASE, ARG_FP },
+ { "subg/sc", FP(0x15,0x421), BASE, ARG_FP },
+ { "mulg/sc", FP(0x15,0x422), BASE, ARG_FP },
+ { "divg/sc", FP(0x15,0x423), BASE, ARG_FP },
+ { "cvtgf/sc", FP(0x15,0x42C), BASE, ARG_FPZ1 },
+ { "cvtgd/sc", FP(0x15,0x42D), BASE, ARG_FPZ1 },
+ { "cvtgq/sc", FP(0x15,0x42F), BASE, ARG_FPZ1 },
+ { "addf/s", FP(0x15,0x480), BASE, ARG_FP },
+ { "negf/s", FP(0x15,0x481), BASE, ARG_FPZ1 }, /* pseudo */
+ { "subf/s", FP(0x15,0x481), BASE, ARG_FP },
+ { "mulf/s", FP(0x15,0x482), BASE, ARG_FP },
+ { "divf/s", FP(0x15,0x483), BASE, ARG_FP },
+ { "cvtdg/s", FP(0x15,0x49E), BASE, ARG_FPZ1 },
+ { "addg/s", FP(0x15,0x4A0), BASE, ARG_FP },
+ { "negg/s", FP(0x15,0x4A1), BASE, ARG_FPZ1 }, /* pseudo */
+ { "subg/s", FP(0x15,0x4A1), BASE, ARG_FP },
+ { "mulg/s", FP(0x15,0x4A2), BASE, ARG_FP },
+ { "divg/s", FP(0x15,0x4A3), BASE, ARG_FP },
+ { "cmpgeq/s", FP(0x15,0x4A5), BASE, ARG_FP },
+ { "cmpglt/s", FP(0x15,0x4A6), BASE, ARG_FP },
+ { "cmpgle/s", FP(0x15,0x4A7), BASE, ARG_FP },
+ { "cvtgf/s", FP(0x15,0x4AC), BASE, ARG_FPZ1 },
+ { "cvtgd/s", FP(0x15,0x4AD), BASE, ARG_FPZ1 },
+ { "cvtgq/s", FP(0x15,0x4AF), BASE, ARG_FPZ1 },
+ { "addf/suc", FP(0x15,0x500), BASE, ARG_FP },
+ { "subf/suc", FP(0x15,0x501), BASE, ARG_FP },
+ { "mulf/suc", FP(0x15,0x502), BASE, ARG_FP },
+ { "divf/suc", FP(0x15,0x503), BASE, ARG_FP },
+ { "cvtdg/suc", FP(0x15,0x51E), BASE, ARG_FPZ1 },
+ { "addg/suc", FP(0x15,0x520), BASE, ARG_FP },
+ { "subg/suc", FP(0x15,0x521), BASE, ARG_FP },
+ { "mulg/suc", FP(0x15,0x522), BASE, ARG_FP },
+ { "divg/suc", FP(0x15,0x523), BASE, ARG_FP },
+ { "cvtgf/suc", FP(0x15,0x52C), BASE, ARG_FPZ1 },
+ { "cvtgd/suc", FP(0x15,0x52D), BASE, ARG_FPZ1 },
+ { "cvtgq/svc", FP(0x15,0x52F), BASE, ARG_FPZ1 },
+ { "addf/su", FP(0x15,0x580), BASE, ARG_FP },
+ { "subf/su", FP(0x15,0x581), BASE, ARG_FP },
+ { "mulf/su", FP(0x15,0x582), BASE, ARG_FP },
+ { "divf/su", FP(0x15,0x583), BASE, ARG_FP },
+ { "cvtdg/su", FP(0x15,0x59E), BASE, ARG_FPZ1 },
+ { "addg/su", FP(0x15,0x5A0), BASE, ARG_FP },
+ { "subg/su", FP(0x15,0x5A1), BASE, ARG_FP },
+ { "mulg/su", FP(0x15,0x5A2), BASE, ARG_FP },
+ { "divg/su", FP(0x15,0x5A3), BASE, ARG_FP },
+ { "cvtgf/su", FP(0x15,0x5AC), BASE, ARG_FPZ1 },
+ { "cvtgd/su", FP(0x15,0x5AD), BASE, ARG_FPZ1 },
+ { "cvtgq/sv", FP(0x15,0x5AF), BASE, ARG_FPZ1 },
+
+ { "adds/c", FP(0x16,0x000), BASE, ARG_FP },
+ { "subs/c", FP(0x16,0x001), BASE, ARG_FP },
+ { "muls/c", FP(0x16,0x002), BASE, ARG_FP },
+ { "divs/c", FP(0x16,0x003), BASE, ARG_FP },
+ { "addt/c", FP(0x16,0x020), BASE, ARG_FP },
+ { "subt/c", FP(0x16,0x021), BASE, ARG_FP },
+ { "mult/c", FP(0x16,0x022), BASE, ARG_FP },
+ { "divt/c", FP(0x16,0x023), BASE, ARG_FP },
+ { "cvtts/c", FP(0x16,0x02C), BASE, ARG_FPZ1 },
+ { "cvttq/c", FP(0x16,0x02F), BASE, ARG_FPZ1 },
+ { "cvtqs/c", FP(0x16,0x03C), BASE, ARG_FPZ1 },
+ { "cvtqt/c", FP(0x16,0x03E), BASE, ARG_FPZ1 },
+ { "adds/m", FP(0x16,0x040), BASE, ARG_FP },
+ { "subs/m", FP(0x16,0x041), BASE, ARG_FP },
+ { "muls/m", FP(0x16,0x042), BASE, ARG_FP },
+ { "divs/m", FP(0x16,0x043), BASE, ARG_FP },
+ { "addt/m", FP(0x16,0x060), BASE, ARG_FP },
+ { "subt/m", FP(0x16,0x061), BASE, ARG_FP },
+ { "mult/m", FP(0x16,0x062), BASE, ARG_FP },
+ { "divt/m", FP(0x16,0x063), BASE, ARG_FP },
+ { "cvtts/m", FP(0x16,0x06C), BASE, ARG_FPZ1 },
+ { "cvttq/m", FP(0x16,0x06F), BASE, ARG_FPZ1 },
+ { "cvtqs/m", FP(0x16,0x07C), BASE, ARG_FPZ1 },
+ { "cvtqt/m", FP(0x16,0x07E), BASE, ARG_FPZ1 },
+ { "adds", FP(0x16,0x080), BASE, ARG_FP },
+ { "negs", FP(0x16,0x081), BASE, ARG_FPZ1 }, /* pseudo */
+ { "subs", FP(0x16,0x081), BASE, ARG_FP },
+ { "muls", FP(0x16,0x082), BASE, ARG_FP },
+ { "divs", FP(0x16,0x083), BASE, ARG_FP },
+ { "addt", FP(0x16,0x0A0), BASE, ARG_FP },
+ { "negt", FP(0x16,0x0A1), BASE, ARG_FPZ1 }, /* pseudo */
+ { "subt", FP(0x16,0x0A1), BASE, ARG_FP },
+ { "mult", FP(0x16,0x0A2), BASE, ARG_FP },
+ { "divt", FP(0x16,0x0A3), BASE, ARG_FP },
+ { "cmptun", FP(0x16,0x0A4), BASE, ARG_FP },
+ { "cmpteq", FP(0x16,0x0A5), BASE, ARG_FP },
+ { "cmptlt", FP(0x16,0x0A6), BASE, ARG_FP },
+ { "cmptle", FP(0x16,0x0A7), BASE, ARG_FP },
+ { "cvtts", FP(0x16,0x0AC), BASE, ARG_FPZ1 },
+ { "cvttq", FP(0x16,0x0AF), BASE, ARG_FPZ1 },
+ { "cvtqs", FP(0x16,0x0BC), BASE, ARG_FPZ1 },
+ { "cvtqt", FP(0x16,0x0BE), BASE, ARG_FPZ1 },
+ { "adds/d", FP(0x16,0x0C0), BASE, ARG_FP },
+ { "subs/d", FP(0x16,0x0C1), BASE, ARG_FP },
+ { "muls/d", FP(0x16,0x0C2), BASE, ARG_FP },
+ { "divs/d", FP(0x16,0x0C3), BASE, ARG_FP },
+ { "addt/d", FP(0x16,0x0E0), BASE, ARG_FP },
+ { "subt/d", FP(0x16,0x0E1), BASE, ARG_FP },
+ { "mult/d", FP(0x16,0x0E2), BASE, ARG_FP },
+ { "divt/d", FP(0x16,0x0E3), BASE, ARG_FP },
+ { "cvtts/d", FP(0x16,0x0EC), BASE, ARG_FPZ1 },
+ { "cvttq/d", FP(0x16,0x0EF), BASE, ARG_FPZ1 },
+ { "cvtqs/d", FP(0x16,0x0FC), BASE, ARG_FPZ1 },
+ { "cvtqt/d", FP(0x16,0x0FE), BASE, ARG_FPZ1 },
+ { "adds/uc", FP(0x16,0x100), BASE, ARG_FP },
+ { "subs/uc", FP(0x16,0x101), BASE, ARG_FP },
+ { "muls/uc", FP(0x16,0x102), BASE, ARG_FP },
+ { "divs/uc", FP(0x16,0x103), BASE, ARG_FP },
+ { "addt/uc", FP(0x16,0x120), BASE, ARG_FP },
+ { "subt/uc", FP(0x16,0x121), BASE, ARG_FP },
+ { "mult/uc", FP(0x16,0x122), BASE, ARG_FP },
+ { "divt/uc", FP(0x16,0x123), BASE, ARG_FP },
+ { "cvtts/uc", FP(0x16,0x12C), BASE, ARG_FPZ1 },
+ { "cvttq/vc", FP(0x16,0x12F), BASE, ARG_FPZ1 },
+ { "adds/um", FP(0x16,0x140), BASE, ARG_FP },
+ { "subs/um", FP(0x16,0x141), BASE, ARG_FP },
+ { "muls/um", FP(0x16,0x142), BASE, ARG_FP },
+ { "divs/um", FP(0x16,0x143), BASE, ARG_FP },
+ { "addt/um", FP(0x16,0x160), BASE, ARG_FP },
+ { "subt/um", FP(0x16,0x161), BASE, ARG_FP },
+ { "mult/um", FP(0x16,0x162), BASE, ARG_FP },
+ { "divt/um", FP(0x16,0x163), BASE, ARG_FP },
+ { "cvtts/um", FP(0x16,0x16C), BASE, ARG_FPZ1 },
+ { "cvttq/vm", FP(0x16,0x16F), BASE, ARG_FPZ1 },
+ { "adds/u", FP(0x16,0x180), BASE, ARG_FP },
+ { "subs/u", FP(0x16,0x181), BASE, ARG_FP },
+ { "muls/u", FP(0x16,0x182), BASE, ARG_FP },
+ { "divs/u", FP(0x16,0x183), BASE, ARG_FP },
+ { "addt/u", FP(0x16,0x1A0), BASE, ARG_FP },
+ { "subt/u", FP(0x16,0x1A1), BASE, ARG_FP },
+ { "mult/u", FP(0x16,0x1A2), BASE, ARG_FP },
+ { "divt/u", FP(0x16,0x1A3), BASE, ARG_FP },
+ { "cvtts/u", FP(0x16,0x1AC), BASE, ARG_FPZ1 },
+ { "cvttq/v", FP(0x16,0x1AF), BASE, ARG_FPZ1 },
+ { "adds/ud", FP(0x16,0x1C0), BASE, ARG_FP },
+ { "subs/ud", FP(0x16,0x1C1), BASE, ARG_FP },
+ { "muls/ud", FP(0x16,0x1C2), BASE, ARG_FP },
+ { "divs/ud", FP(0x16,0x1C3), BASE, ARG_FP },
+ { "addt/ud", FP(0x16,0x1E0), BASE, ARG_FP },
+ { "subt/ud", FP(0x16,0x1E1), BASE, ARG_FP },
+ { "mult/ud", FP(0x16,0x1E2), BASE, ARG_FP },
+ { "divt/ud", FP(0x16,0x1E3), BASE, ARG_FP },
+ { "cvtts/ud", FP(0x16,0x1EC), BASE, ARG_FPZ1 },
+ { "cvttq/vd", FP(0x16,0x1EF), BASE, ARG_FPZ1 },
+ { "cvtst", FP(0x16,0x2AC), BASE, ARG_FPZ1 },
+ { "adds/suc", FP(0x16,0x500), BASE, ARG_FP },
+ { "subs/suc", FP(0x16,0x501), BASE, ARG_FP },
+ { "muls/suc", FP(0x16,0x502), BASE, ARG_FP },
+ { "divs/suc", FP(0x16,0x503), BASE, ARG_FP },
+ { "addt/suc", FP(0x16,0x520), BASE, ARG_FP },
+ { "subt/suc", FP(0x16,0x521), BASE, ARG_FP },
+ { "mult/suc", FP(0x16,0x522), BASE, ARG_FP },
+ { "divt/suc", FP(0x16,0x523), BASE, ARG_FP },
+ { "cvtts/suc", FP(0x16,0x52C), BASE, ARG_FPZ1 },
+ { "cvttq/svc", FP(0x16,0x52F), BASE, ARG_FPZ1 },
+ { "adds/sum", FP(0x16,0x540), BASE, ARG_FP },
+ { "subs/sum", FP(0x16,0x541), BASE, ARG_FP },
+ { "muls/sum", FP(0x16,0x542), BASE, ARG_FP },
+ { "divs/sum", FP(0x16,0x543), BASE, ARG_FP },
+ { "addt/sum", FP(0x16,0x560), BASE, ARG_FP },
+ { "subt/sum", FP(0x16,0x561), BASE, ARG_FP },
+ { "mult/sum", FP(0x16,0x562), BASE, ARG_FP },
+ { "divt/sum", FP(0x16,0x563), BASE, ARG_FP },
+ { "cvtts/sum", FP(0x16,0x56C), BASE, ARG_FPZ1 },
+ { "cvttq/svm", FP(0x16,0x56F), BASE, ARG_FPZ1 },
+ { "adds/su", FP(0x16,0x580), BASE, ARG_FP },
+ { "negs/su", FP(0x16,0x581), BASE, ARG_FPZ1 }, /* pseudo */
+ { "subs/su", FP(0x16,0x581), BASE, ARG_FP },
+ { "muls/su", FP(0x16,0x582), BASE, ARG_FP },
+ { "divs/su", FP(0x16,0x583), BASE, ARG_FP },
+ { "addt/su", FP(0x16,0x5A0), BASE, ARG_FP },
+ { "negt/su", FP(0x16,0x5A1), BASE, ARG_FPZ1 }, /* pseudo */
+ { "subt/su", FP(0x16,0x5A1), BASE, ARG_FP },
+ { "mult/su", FP(0x16,0x5A2), BASE, ARG_FP },
+ { "divt/su", FP(0x16,0x5A3), BASE, ARG_FP },
+ { "cmptun/su", FP(0x16,0x5A4), BASE, ARG_FP },
+ { "cmpteq/su", FP(0x16,0x5A5), BASE, ARG_FP },
+ { "cmptlt/su", FP(0x16,0x5A6), BASE, ARG_FP },
+ { "cmptle/su", FP(0x16,0x5A7), BASE, ARG_FP },
+ { "cvtts/su", FP(0x16,0x5AC), BASE, ARG_FPZ1 },
+ { "cvttq/sv", FP(0x16,0x5AF), BASE, ARG_FPZ1 },
+ { "adds/sud", FP(0x16,0x5C0), BASE, ARG_FP },
+ { "subs/sud", FP(0x16,0x5C1), BASE, ARG_FP },
+ { "muls/sud", FP(0x16,0x5C2), BASE, ARG_FP },
+ { "divs/sud", FP(0x16,0x5C3), BASE, ARG_FP },
+ { "addt/sud", FP(0x16,0x5E0), BASE, ARG_FP },
+ { "subt/sud", FP(0x16,0x5E1), BASE, ARG_FP },
+ { "mult/sud", FP(0x16,0x5E2), BASE, ARG_FP },
+ { "divt/sud", FP(0x16,0x5E3), BASE, ARG_FP },
+ { "cvtts/sud", FP(0x16,0x5EC), BASE, ARG_FPZ1 },
+ { "cvttq/svd", FP(0x16,0x5EF), BASE, ARG_FPZ1 },
+ { "cvtst/s", FP(0x16,0x6AC), BASE, ARG_FPZ1 },
+ { "adds/suic", FP(0x16,0x700), BASE, ARG_FP },
+ { "subs/suic", FP(0x16,0x701), BASE, ARG_FP },
+ { "muls/suic", FP(0x16,0x702), BASE, ARG_FP },
+ { "divs/suic", FP(0x16,0x703), BASE, ARG_FP },
+ { "addt/suic", FP(0x16,0x720), BASE, ARG_FP },
+ { "subt/suic", FP(0x16,0x721), BASE, ARG_FP },
+ { "mult/suic", FP(0x16,0x722), BASE, ARG_FP },
+ { "divt/suic", FP(0x16,0x723), BASE, ARG_FP },
+ { "cvtts/suic", FP(0x16,0x72C), BASE, ARG_FPZ1 },
+ { "cvttq/svic", FP(0x16,0x72F), BASE, ARG_FPZ1 },
+ { "cvtqs/suic", FP(0x16,0x73C), BASE, ARG_FPZ1 },
+ { "cvtqt/suic", FP(0x16,0x73E), BASE, ARG_FPZ1 },
+ { "adds/suim", FP(0x16,0x740), BASE, ARG_FP },
+ { "subs/suim", FP(0x16,0x741), BASE, ARG_FP },
+ { "muls/suim", FP(0x16,0x742), BASE, ARG_FP },
+ { "divs/suim", FP(0x16,0x743), BASE, ARG_FP },
+ { "addt/suim", FP(0x16,0x760), BASE, ARG_FP },
+ { "subt/suim", FP(0x16,0x761), BASE, ARG_FP },
+ { "mult/suim", FP(0x16,0x762), BASE, ARG_FP },
+ { "divt/suim", FP(0x16,0x763), BASE, ARG_FP },
+ { "cvtts/suim", FP(0x16,0x76C), BASE, ARG_FPZ1 },
+ { "cvttq/svim", FP(0x16,0x76F), BASE, ARG_FPZ1 },
+ { "cvtqs/suim", FP(0x16,0x77C), BASE, ARG_FPZ1 },
+ { "cvtqt/suim", FP(0x16,0x77E), BASE, ARG_FPZ1 },
+ { "adds/sui", FP(0x16,0x780), BASE, ARG_FP },
+ { "negs/sui", FP(0x16,0x781), BASE, ARG_FPZ1 }, /* pseudo */
+ { "subs/sui", FP(0x16,0x781), BASE, ARG_FP },
+ { "muls/sui", FP(0x16,0x782), BASE, ARG_FP },
+ { "divs/sui", FP(0x16,0x783), BASE, ARG_FP },
+ { "addt/sui", FP(0x16,0x7A0), BASE, ARG_FP },
+ { "negt/sui", FP(0x16,0x7A1), BASE, ARG_FPZ1 }, /* pseudo */
+ { "subt/sui", FP(0x16,0x7A1), BASE, ARG_FP },
+ { "mult/sui", FP(0x16,0x7A2), BASE, ARG_FP },
+ { "divt/sui", FP(0x16,0x7A3), BASE, ARG_FP },
+ { "cvtts/sui", FP(0x16,0x7AC), BASE, ARG_FPZ1 },
+ { "cvttq/svi", FP(0x16,0x7AF), BASE, ARG_FPZ1 },
+ { "cvtqs/sui", FP(0x16,0x7BC), BASE, ARG_FPZ1 },
+ { "cvtqt/sui", FP(0x16,0x7BE), BASE, ARG_FPZ1 },
+ { "adds/suid", FP(0x16,0x7C0), BASE, ARG_FP },
+ { "subs/suid", FP(0x16,0x7C1), BASE, ARG_FP },
+ { "muls/suid", FP(0x16,0x7C2), BASE, ARG_FP },
+ { "divs/suid", FP(0x16,0x7C3), BASE, ARG_FP },
+ { "addt/suid", FP(0x16,0x7E0), BASE, ARG_FP },
+ { "subt/suid", FP(0x16,0x7E1), BASE, ARG_FP },
+ { "mult/suid", FP(0x16,0x7E2), BASE, ARG_FP },
+ { "divt/suid", FP(0x16,0x7E3), BASE, ARG_FP },
+ { "cvtts/suid", FP(0x16,0x7EC), BASE, ARG_FPZ1 },
+ { "cvttq/svid", FP(0x16,0x7EF), BASE, ARG_FPZ1 },
+ { "cvtqs/suid", FP(0x16,0x7FC), BASE, ARG_FPZ1 },
+ { "cvtqt/suid", FP(0x16,0x7FE), BASE, ARG_FPZ1 },
+
+ { "cvtlq", FP(0x17,0x010), BASE, ARG_FPZ1 },
+ { "fnop", FP(0x17,0x020), BASE, { ZA, ZB, ZC } }, /* pseudo */
+ { "fclr", FP(0x17,0x020), BASE, { ZA, ZB, FC } }, /* pseudo */
+ { "fabs", FP(0x17,0x020), BASE, ARG_FPZ1 }, /* pseudo */
+ { "fmov", FP(0x17,0x020), BASE, { FA, RBA, FC } }, /* pseudo */
+ { "cpys", FP(0x17,0x020), BASE, ARG_FP },
+ { "fneg", FP(0x17,0x021), BASE, { FA, RBA, FC } }, /* pseudo */
+ { "cpysn", FP(0x17,0x021), BASE, ARG_FP },
+ { "cpyse", FP(0x17,0x022), BASE, ARG_FP },
+ { "mt_fpcr", FP(0x17,0x024), BASE, { FA, RBA, RCA } },
+ { "mf_fpcr", FP(0x17,0x025), BASE, { FA, RBA, RCA } },
+ { "fcmoveq", FP(0x17,0x02A), BASE, ARG_FP },
+ { "fcmovne", FP(0x17,0x02B), BASE, ARG_FP },
+ { "fcmovlt", FP(0x17,0x02C), BASE, ARG_FP },
+ { "fcmovge", FP(0x17,0x02D), BASE, ARG_FP },
+ { "fcmovle", FP(0x17,0x02E), BASE, ARG_FP },
+ { "fcmovgt", FP(0x17,0x02F), BASE, ARG_FP },
+ { "cvtql", FP(0x17,0x030), BASE, ARG_FPZ1 },
+ { "cvtql/v", FP(0x17,0x130), BASE, ARG_FPZ1 },
+ { "cvtql/sv", FP(0x17,0x530), BASE, ARG_FPZ1 },
+
+ { "trapb", MFC(0x18,0x0000), BASE, ARG_NONE },
+ { "draint", MFC(0x18,0x0000), BASE, ARG_NONE }, /* alias */
+ { "excb", MFC(0x18,0x0400), BASE, ARG_NONE },
+ { "mb", MFC(0x18,0x4000), BASE, ARG_NONE },
+ { "wmb", MFC(0x18,0x4400), BASE, ARG_NONE },
+ { "fetch", MFC(0x18,0x8000), BASE, { ZA, PRB } },
+ { "fetch_m", MFC(0x18,0xA000), BASE, { ZA, PRB } },
+ { "rpcc", MFC(0x18,0xC000), BASE, { RA } },
+ { "rc", MFC(0x18,0xE000), BASE, { RA } },
+ { "ecb", MFC(0x18,0xE800), BASE, { ZA, PRB } }, /* ev56 una */
+ { "rs", MFC(0x18,0xF000), BASE, { RA } },
+ { "wh64", MFC(0x18,0xF800), BASE, { ZA, PRB } }, /* ev56 una */
+ { "wh64en", MFC(0x18,0xFC00), BASE, { ZA, PRB } }, /* ev7 una */
+
+ { "hw_mfpr", OPR(0x19,0x00), EV4, { RA, RBA, EV4EXTHWINDEX } },
+ { "hw_mfpr", OP(0x19), OP_MASK, EV5, { RA, RBA, EV5HWINDEX } },
+ { "hw_mfpr", OP(0x19), OP_MASK, EV6, { RA, ZB, EV6HWINDEX } },
+ { "hw_mfpr/i", OPR(0x19,0x01), EV4, ARG_EV4HWMPR },
+ { "hw_mfpr/a", OPR(0x19,0x02), EV4, ARG_EV4HWMPR },
+ { "hw_mfpr/ai", OPR(0x19,0x03), EV4, ARG_EV4HWMPR },
+ { "hw_mfpr/p", OPR(0x19,0x04), EV4, ARG_EV4HWMPR },
+ { "hw_mfpr/pi", OPR(0x19,0x05), EV4, ARG_EV4HWMPR },
+ { "hw_mfpr/pa", OPR(0x19,0x06), EV4, ARG_EV4HWMPR },
+ { "hw_mfpr/pai", OPR(0x19,0x07), EV4, ARG_EV4HWMPR },
+ { "pal19", PCD(0x19), BASE, ARG_PCD },
+
+ { "jmp", MBR_(0x1A,0), MBR_MASK | 0x3FFF, /* pseudo */
+ BASE, { ZA, CPRB } },
+ { "jmp", MBR(0x1A,0), BASE, { RA, CPRB, JMPHINT } },
+ { "jsr", MBR(0x1A,1), BASE, { RA, CPRB, JMPHINT } },
+ { "ret", MBR_(0x1A,2) | (31 << 21) | (26 << 16) | 1,/* pseudo */
+ 0xFFFFFFFF, BASE, { 0 } },
+ { "ret", MBR(0x1A,2), BASE, { RA, CPRB, RETHINT } },
+ { "jcr", MBR(0x1A,3), BASE, { RA, CPRB, RETHINT } }, /* alias */
+ { "jsr_coroutine", MBR(0x1A,3), BASE, { RA, CPRB, RETHINT } },
+
+ { "hw_ldl", EV4HWMEM(0x1B,0x0), EV4, ARG_EV4HWMEM },
+ { "hw_ldl", EV5HWMEM(0x1B,0x00), EV5, ARG_EV5HWMEM },
+ { "hw_ldl", EV6HWMEM(0x1B,0x8), EV6, ARG_EV6HWMEM },
+ { "hw_ldl/a", EV4HWMEM(0x1B,0x4), EV4, ARG_EV4HWMEM },
+ { "hw_ldl/a", EV5HWMEM(0x1B,0x10), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/a", EV6HWMEM(0x1B,0xC), EV6, ARG_EV6HWMEM },
+ { "hw_ldl/al", EV5HWMEM(0x1B,0x11), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/ar", EV4HWMEM(0x1B,0x6), EV4, ARG_EV4HWMEM },
+ { "hw_ldl/av", EV5HWMEM(0x1B,0x12), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/avl", EV5HWMEM(0x1B,0x13), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/aw", EV5HWMEM(0x1B,0x18), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/awl", EV5HWMEM(0x1B,0x19), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/awv", EV5HWMEM(0x1B,0x1a), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/awvl", EV5HWMEM(0x1B,0x1b), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/l", EV5HWMEM(0x1B,0x01), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/p", EV4HWMEM(0x1B,0x8), EV4, ARG_EV4HWMEM },
+ { "hw_ldl/p", EV5HWMEM(0x1B,0x20), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/p", EV6HWMEM(0x1B,0x0), EV6, ARG_EV6HWMEM },
+ { "hw_ldl/pa", EV4HWMEM(0x1B,0xC), EV4, ARG_EV4HWMEM },
+ { "hw_ldl/pa", EV5HWMEM(0x1B,0x30), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/pal", EV5HWMEM(0x1B,0x31), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/par", EV4HWMEM(0x1B,0xE), EV4, ARG_EV4HWMEM },
+ { "hw_ldl/pav", EV5HWMEM(0x1B,0x32), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/pavl", EV5HWMEM(0x1B,0x33), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/paw", EV5HWMEM(0x1B,0x38), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/pawl", EV5HWMEM(0x1B,0x39), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/pawv", EV5HWMEM(0x1B,0x3a), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/pawvl", EV5HWMEM(0x1B,0x3b), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/pl", EV5HWMEM(0x1B,0x21), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/pr", EV4HWMEM(0x1B,0xA), EV4, ARG_EV4HWMEM },
+ { "hw_ldl/pv", EV5HWMEM(0x1B,0x22), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/pvl", EV5HWMEM(0x1B,0x23), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/pw", EV5HWMEM(0x1B,0x28), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/pwl", EV5HWMEM(0x1B,0x29), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/pwv", EV5HWMEM(0x1B,0x2a), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/pwvl", EV5HWMEM(0x1B,0x2b), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/r", EV4HWMEM(0x1B,0x2), EV4, ARG_EV4HWMEM },
+ { "hw_ldl/v", EV5HWMEM(0x1B,0x02), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/v", EV6HWMEM(0x1B,0x4), EV6, ARG_EV6HWMEM },
+ { "hw_ldl/vl", EV5HWMEM(0x1B,0x03), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/w", EV5HWMEM(0x1B,0x08), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/w", EV6HWMEM(0x1B,0xA), EV6, ARG_EV6HWMEM },
+ { "hw_ldl/wa", EV6HWMEM(0x1B,0xE), EV6, ARG_EV6HWMEM },
+ { "hw_ldl/wl", EV5HWMEM(0x1B,0x09), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/wv", EV5HWMEM(0x1B,0x0a), EV5, ARG_EV5HWMEM },
+ { "hw_ldl/wvl", EV5HWMEM(0x1B,0x0b), EV5, ARG_EV5HWMEM },
+ { "hw_ldl_l", EV5HWMEM(0x1B,0x01), EV5, ARG_EV5HWMEM },
+ { "hw_ldl_l/a", EV5HWMEM(0x1B,0x11), EV5, ARG_EV5HWMEM },
+ { "hw_ldl_l/av", EV5HWMEM(0x1B,0x13), EV5, ARG_EV5HWMEM },
+ { "hw_ldl_l/aw", EV5HWMEM(0x1B,0x19), EV5, ARG_EV5HWMEM },
+ { "hw_ldl_l/awv", EV5HWMEM(0x1B,0x1b), EV5, ARG_EV5HWMEM },
+ { "hw_ldl_l/p", EV5HWMEM(0x1B,0x21), EV5, ARG_EV5HWMEM },
+ { "hw_ldl_l/p", EV6HWMEM(0x1B,0x2), EV6, ARG_EV6HWMEM },
+ { "hw_ldl_l/pa", EV5HWMEM(0x1B,0x31), EV5, ARG_EV5HWMEM },
+ { "hw_ldl_l/pav", EV5HWMEM(0x1B,0x33), EV5, ARG_EV5HWMEM },
+ { "hw_ldl_l/paw", EV5HWMEM(0x1B,0x39), EV5, ARG_EV5HWMEM },
+ { "hw_ldl_l/pawv", EV5HWMEM(0x1B,0x3b), EV5, ARG_EV5HWMEM },
+ { "hw_ldl_l/pv", EV5HWMEM(0x1B,0x23), EV5, ARG_EV5HWMEM },
+ { "hw_ldl_l/pw", EV5HWMEM(0x1B,0x29), EV5, ARG_EV5HWMEM },
+ { "hw_ldl_l/pwv", EV5HWMEM(0x1B,0x2b), EV5, ARG_EV5HWMEM },
+ { "hw_ldl_l/v", EV5HWMEM(0x1B,0x03), EV5, ARG_EV5HWMEM },
+ { "hw_ldl_l/w", EV5HWMEM(0x1B,0x09), EV5, ARG_EV5HWMEM },
+ { "hw_ldl_l/wv", EV5HWMEM(0x1B,0x0b), EV5, ARG_EV5HWMEM },
+ { "hw_ldq", EV4HWMEM(0x1B,0x1), EV4, ARG_EV4HWMEM },
+ { "hw_ldq", EV5HWMEM(0x1B,0x04), EV5, ARG_EV5HWMEM },
+ { "hw_ldq", EV6HWMEM(0x1B,0x9), EV6, ARG_EV6HWMEM },
+ { "hw_ldq/a", EV4HWMEM(0x1B,0x5), EV4, ARG_EV4HWMEM },
+ { "hw_ldq/a", EV5HWMEM(0x1B,0x14), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/a", EV6HWMEM(0x1B,0xD), EV6, ARG_EV6HWMEM },
+ { "hw_ldq/al", EV5HWMEM(0x1B,0x15), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/ar", EV4HWMEM(0x1B,0x7), EV4, ARG_EV4HWMEM },
+ { "hw_ldq/av", EV5HWMEM(0x1B,0x16), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/avl", EV5HWMEM(0x1B,0x17), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/aw", EV5HWMEM(0x1B,0x1c), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/awl", EV5HWMEM(0x1B,0x1d), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/awv", EV5HWMEM(0x1B,0x1e), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/awvl", EV5HWMEM(0x1B,0x1f), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/l", EV5HWMEM(0x1B,0x05), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/p", EV4HWMEM(0x1B,0x9), EV4, ARG_EV4HWMEM },
+ { "hw_ldq/p", EV5HWMEM(0x1B,0x24), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/p", EV6HWMEM(0x1B,0x1), EV6, ARG_EV6HWMEM },
+ { "hw_ldq/pa", EV4HWMEM(0x1B,0xD), EV4, ARG_EV4HWMEM },
+ { "hw_ldq/pa", EV5HWMEM(0x1B,0x34), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/pal", EV5HWMEM(0x1B,0x35), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/par", EV4HWMEM(0x1B,0xF), EV4, ARG_EV4HWMEM },
+ { "hw_ldq/pav", EV5HWMEM(0x1B,0x36), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/pavl", EV5HWMEM(0x1B,0x37), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/paw", EV5HWMEM(0x1B,0x3c), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/pawl", EV5HWMEM(0x1B,0x3d), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/pawv", EV5HWMEM(0x1B,0x3e), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/pawvl", EV5HWMEM(0x1B,0x3f), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/pl", EV5HWMEM(0x1B,0x25), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/pr", EV4HWMEM(0x1B,0xB), EV4, ARG_EV4HWMEM },
+ { "hw_ldq/pv", EV5HWMEM(0x1B,0x26), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/pvl", EV5HWMEM(0x1B,0x27), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/pw", EV5HWMEM(0x1B,0x2c), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/pwl", EV5HWMEM(0x1B,0x2d), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/pwv", EV5HWMEM(0x1B,0x2e), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/pwvl", EV5HWMEM(0x1B,0x2f), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/r", EV4HWMEM(0x1B,0x3), EV4, ARG_EV4HWMEM },
+ { "hw_ldq/v", EV5HWMEM(0x1B,0x06), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/v", EV6HWMEM(0x1B,0x5), EV6, ARG_EV6HWMEM },
+ { "hw_ldq/vl", EV5HWMEM(0x1B,0x07), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/w", EV5HWMEM(0x1B,0x0c), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/w", EV6HWMEM(0x1B,0xB), EV6, ARG_EV6HWMEM },
+ { "hw_ldq/wa", EV6HWMEM(0x1B,0xF), EV6, ARG_EV6HWMEM },
+ { "hw_ldq/wl", EV5HWMEM(0x1B,0x0d), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/wv", EV5HWMEM(0x1B,0x0e), EV5, ARG_EV5HWMEM },
+ { "hw_ldq/wvl", EV5HWMEM(0x1B,0x0f), EV5, ARG_EV5HWMEM },
+ { "hw_ldq_l", EV5HWMEM(0x1B,0x05), EV5, ARG_EV5HWMEM },
+ { "hw_ldq_l/a", EV5HWMEM(0x1B,0x15), EV5, ARG_EV5HWMEM },
+ { "hw_ldq_l/av", EV5HWMEM(0x1B,0x17), EV5, ARG_EV5HWMEM },
+ { "hw_ldq_l/aw", EV5HWMEM(0x1B,0x1d), EV5, ARG_EV5HWMEM },
+ { "hw_ldq_l/awv", EV5HWMEM(0x1B,0x1f), EV5, ARG_EV5HWMEM },
+ { "hw_ldq_l/p", EV5HWMEM(0x1B,0x25), EV5, ARG_EV5HWMEM },
+ { "hw_ldq_l/p", EV6HWMEM(0x1B,0x3), EV6, ARG_EV6HWMEM },
+ { "hw_ldq_l/pa", EV5HWMEM(0x1B,0x35), EV5, ARG_EV5HWMEM },
+ { "hw_ldq_l/pav", EV5HWMEM(0x1B,0x37), EV5, ARG_EV5HWMEM },
+ { "hw_ldq_l/paw", EV5HWMEM(0x1B,0x3d), EV5, ARG_EV5HWMEM },
+ { "hw_ldq_l/pawv", EV5HWMEM(0x1B,0x3f), EV5, ARG_EV5HWMEM },
+ { "hw_ldq_l/pv", EV5HWMEM(0x1B,0x27), EV5, ARG_EV5HWMEM },
+ { "hw_ldq_l/pw", EV5HWMEM(0x1B,0x2d), EV5, ARG_EV5HWMEM },
+ { "hw_ldq_l/pwv", EV5HWMEM(0x1B,0x2f), EV5, ARG_EV5HWMEM },
+ { "hw_ldq_l/v", EV5HWMEM(0x1B,0x07), EV5, ARG_EV5HWMEM },
+ { "hw_ldq_l/w", EV5HWMEM(0x1B,0x0d), EV5, ARG_EV5HWMEM },
+ { "hw_ldq_l/wv", EV5HWMEM(0x1B,0x0f), EV5, ARG_EV5HWMEM },
+ { "hw_ld", EV4HWMEM(0x1B,0x0), EV4, ARG_EV4HWMEM },
+ { "hw_ld", EV5HWMEM(0x1B,0x00), EV5, ARG_EV5HWMEM },
+ { "hw_ld/a", EV4HWMEM(0x1B,0x4), EV4, ARG_EV4HWMEM },
+ { "hw_ld/a", EV5HWMEM(0x1B,0x10), EV5, ARG_EV5HWMEM },
+ { "hw_ld/al", EV5HWMEM(0x1B,0x11), EV5, ARG_EV5HWMEM },
+ { "hw_ld/aq", EV4HWMEM(0x1B,0x5), EV4, ARG_EV4HWMEM },
+ { "hw_ld/aq", EV5HWMEM(0x1B,0x14), EV5, ARG_EV5HWMEM },
+ { "hw_ld/aql", EV5HWMEM(0x1B,0x15), EV5, ARG_EV5HWMEM },
+ { "hw_ld/aqv", EV5HWMEM(0x1B,0x16), EV5, ARG_EV5HWMEM },
+ { "hw_ld/aqvl", EV5HWMEM(0x1B,0x17), EV5, ARG_EV5HWMEM },
+ { "hw_ld/ar", EV4HWMEM(0x1B,0x6), EV4, ARG_EV4HWMEM },
+ { "hw_ld/arq", EV4HWMEM(0x1B,0x7), EV4, ARG_EV4HWMEM },
+ { "hw_ld/av", EV5HWMEM(0x1B,0x12), EV5, ARG_EV5HWMEM },
+ { "hw_ld/avl", EV5HWMEM(0x1B,0x13), EV5, ARG_EV5HWMEM },
+ { "hw_ld/aw", EV5HWMEM(0x1B,0x18), EV5, ARG_EV5HWMEM },
+ { "hw_ld/awl", EV5HWMEM(0x1B,0x19), EV5, ARG_EV5HWMEM },
+ { "hw_ld/awq", EV5HWMEM(0x1B,0x1c), EV5, ARG_EV5HWMEM },
+ { "hw_ld/awql", EV5HWMEM(0x1B,0x1d), EV5, ARG_EV5HWMEM },
+ { "hw_ld/awqv", EV5HWMEM(0x1B,0x1e), EV5, ARG_EV5HWMEM },
+ { "hw_ld/awqvl", EV5HWMEM(0x1B,0x1f), EV5, ARG_EV5HWMEM },
+ { "hw_ld/awv", EV5HWMEM(0x1B,0x1a), EV5, ARG_EV5HWMEM },
+ { "hw_ld/awvl", EV5HWMEM(0x1B,0x1b), EV5, ARG_EV5HWMEM },
+ { "hw_ld/l", EV5HWMEM(0x1B,0x01), EV5, ARG_EV5HWMEM },
+ { "hw_ld/p", EV4HWMEM(0x1B,0x8), EV4, ARG_EV4HWMEM },
+ { "hw_ld/p", EV5HWMEM(0x1B,0x20), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pa", EV4HWMEM(0x1B,0xC), EV4, ARG_EV4HWMEM },
+ { "hw_ld/pa", EV5HWMEM(0x1B,0x30), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pal", EV5HWMEM(0x1B,0x31), EV5, ARG_EV5HWMEM },
+ { "hw_ld/paq", EV4HWMEM(0x1B,0xD), EV4, ARG_EV4HWMEM },
+ { "hw_ld/paq", EV5HWMEM(0x1B,0x34), EV5, ARG_EV5HWMEM },
+ { "hw_ld/paql", EV5HWMEM(0x1B,0x35), EV5, ARG_EV5HWMEM },
+ { "hw_ld/paqv", EV5HWMEM(0x1B,0x36), EV5, ARG_EV5HWMEM },
+ { "hw_ld/paqvl", EV5HWMEM(0x1B,0x37), EV5, ARG_EV5HWMEM },
+ { "hw_ld/par", EV4HWMEM(0x1B,0xE), EV4, ARG_EV4HWMEM },
+ { "hw_ld/parq", EV4HWMEM(0x1B,0xF), EV4, ARG_EV4HWMEM },
+ { "hw_ld/pav", EV5HWMEM(0x1B,0x32), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pavl", EV5HWMEM(0x1B,0x33), EV5, ARG_EV5HWMEM },
+ { "hw_ld/paw", EV5HWMEM(0x1B,0x38), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pawl", EV5HWMEM(0x1B,0x39), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pawq", EV5HWMEM(0x1B,0x3c), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pawql", EV5HWMEM(0x1B,0x3d), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pawqv", EV5HWMEM(0x1B,0x3e), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pawqvl", EV5HWMEM(0x1B,0x3f), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pawv", EV5HWMEM(0x1B,0x3a), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pawvl", EV5HWMEM(0x1B,0x3b), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pl", EV5HWMEM(0x1B,0x21), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pq", EV4HWMEM(0x1B,0x9), EV4, ARG_EV4HWMEM },
+ { "hw_ld/pq", EV5HWMEM(0x1B,0x24), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pql", EV5HWMEM(0x1B,0x25), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pqv", EV5HWMEM(0x1B,0x26), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pqvl", EV5HWMEM(0x1B,0x27), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pr", EV4HWMEM(0x1B,0xA), EV4, ARG_EV4HWMEM },
+ { "hw_ld/prq", EV4HWMEM(0x1B,0xB), EV4, ARG_EV4HWMEM },
+ { "hw_ld/pv", EV5HWMEM(0x1B,0x22), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pvl", EV5HWMEM(0x1B,0x23), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pw", EV5HWMEM(0x1B,0x28), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pwl", EV5HWMEM(0x1B,0x29), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pwq", EV5HWMEM(0x1B,0x2c), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pwql", EV5HWMEM(0x1B,0x2d), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pwqv", EV5HWMEM(0x1B,0x2e), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pwqvl", EV5HWMEM(0x1B,0x2f), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pwv", EV5HWMEM(0x1B,0x2a), EV5, ARG_EV5HWMEM },
+ { "hw_ld/pwvl", EV5HWMEM(0x1B,0x2b), EV5, ARG_EV5HWMEM },
+ { "hw_ld/q", EV4HWMEM(0x1B,0x1), EV4, ARG_EV4HWMEM },
+ { "hw_ld/q", EV5HWMEM(0x1B,0x04), EV5, ARG_EV5HWMEM },
+ { "hw_ld/ql", EV5HWMEM(0x1B,0x05), EV5, ARG_EV5HWMEM },
+ { "hw_ld/qv", EV5HWMEM(0x1B,0x06), EV5, ARG_EV5HWMEM },
+ { "hw_ld/qvl", EV5HWMEM(0x1B,0x07), EV5, ARG_EV5HWMEM },
+ { "hw_ld/r", EV4HWMEM(0x1B,0x2), EV4, ARG_EV4HWMEM },
+ { "hw_ld/rq", EV4HWMEM(0x1B,0x3), EV4, ARG_EV4HWMEM },
+ { "hw_ld/v", EV5HWMEM(0x1B,0x02), EV5, ARG_EV5HWMEM },
+ { "hw_ld/vl", EV5HWMEM(0x1B,0x03), EV5, ARG_EV5HWMEM },
+ { "hw_ld/w", EV5HWMEM(0x1B,0x08), EV5, ARG_EV5HWMEM },
+ { "hw_ld/wl", EV5HWMEM(0x1B,0x09), EV5, ARG_EV5HWMEM },
+ { "hw_ld/wq", EV5HWMEM(0x1B,0x0c), EV5, ARG_EV5HWMEM },
+ { "hw_ld/wql", EV5HWMEM(0x1B,0x0d), EV5, ARG_EV5HWMEM },
+ { "hw_ld/wqv", EV5HWMEM(0x1B,0x0e), EV5, ARG_EV5HWMEM },
+ { "hw_ld/wqvl", EV5HWMEM(0x1B,0x0f), EV5, ARG_EV5HWMEM },
+ { "hw_ld/wv", EV5HWMEM(0x1B,0x0a), EV5, ARG_EV5HWMEM },
+ { "hw_ld/wvl", EV5HWMEM(0x1B,0x0b), EV5, ARG_EV5HWMEM },
+ { "pal1b", PCD(0x1B), BASE, ARG_PCD },
+
+ { "sextb", OPR(0x1C, 0x00), BWX, ARG_OPRZ1 },
+ { "sextw", OPR(0x1C, 0x01), BWX, ARG_OPRZ1 },
+ { "ctpop", OPR(0x1C, 0x30), CIX, ARG_OPRZ1 },
+ { "perr", OPR(0x1C, 0x31), MAX, ARG_OPR },
+ { "ctlz", OPR(0x1C, 0x32), CIX, ARG_OPRZ1 },
+ { "cttz", OPR(0x1C, 0x33), CIX, ARG_OPRZ1 },
+ { "unpkbw", OPR(0x1C, 0x34), MAX, ARG_OPRZ1 },
+ { "unpkbl", OPR(0x1C, 0x35), MAX, ARG_OPRZ1 },
+ { "pkwb", OPR(0x1C, 0x36), MAX, ARG_OPRZ1 },
+ { "pklb", OPR(0x1C, 0x37), MAX, ARG_OPRZ1 },
+ { "minsb8", OPR(0x1C, 0x38), MAX, ARG_OPR },
+ { "minsb8", OPRL(0x1C, 0x38), MAX, ARG_OPRL },
+ { "minsw4", OPR(0x1C, 0x39), MAX, ARG_OPR },
+ { "minsw4", OPRL(0x1C, 0x39), MAX, ARG_OPRL },
+ { "minub8", OPR(0x1C, 0x3A), MAX, ARG_OPR },
+ { "minub8", OPRL(0x1C, 0x3A), MAX, ARG_OPRL },
+ { "minuw4", OPR(0x1C, 0x3B), MAX, ARG_OPR },
+ { "minuw4", OPRL(0x1C, 0x3B), MAX, ARG_OPRL },
+ { "maxub8", OPR(0x1C, 0x3C), MAX, ARG_OPR },
+ { "maxub8", OPRL(0x1C, 0x3C), MAX, ARG_OPRL },
+ { "maxuw4", OPR(0x1C, 0x3D), MAX, ARG_OPR },
+ { "maxuw4", OPRL(0x1C, 0x3D), MAX, ARG_OPRL },
+ { "maxsb8", OPR(0x1C, 0x3E), MAX, ARG_OPR },
+ { "maxsb8", OPRL(0x1C, 0x3E), MAX, ARG_OPRL },
+ { "maxsw4", OPR(0x1C, 0x3F), MAX, ARG_OPR },
+ { "maxsw4", OPRL(0x1C, 0x3F), MAX, ARG_OPRL },
+ { "ftoit", FP(0x1C, 0x70), CIX, { FA, ZB, RC } },
+ { "ftois", FP(0x1C, 0x78), CIX, { FA, ZB, RC } },
+
+ { "hw_mtpr", OPR(0x1D,0x00), EV4, { RA, RBA, EV4EXTHWINDEX } },
+ { "hw_mtpr", OP(0x1D), OP_MASK, EV5, { RA, RBA, EV5HWINDEX } },
+ { "hw_mtpr", OP(0x1D), OP_MASK, EV6, { ZA, RB, EV6HWINDEX } },
+ { "hw_mtpr/i", OPR(0x1D,0x01), EV4, ARG_EV4HWMPR },
+ { "hw_mtpr/a", OPR(0x1D,0x02), EV4, ARG_EV4HWMPR },
+ { "hw_mtpr/ai", OPR(0x1D,0x03), EV4, ARG_EV4HWMPR },
+ { "hw_mtpr/p", OPR(0x1D,0x04), EV4, ARG_EV4HWMPR },
+ { "hw_mtpr/pi", OPR(0x1D,0x05), EV4, ARG_EV4HWMPR },
+ { "hw_mtpr/pa", OPR(0x1D,0x06), EV4, ARG_EV4HWMPR },
+ { "hw_mtpr/pai", OPR(0x1D,0x07), EV4, ARG_EV4HWMPR },
+ { "pal1d", PCD(0x1D), BASE, ARG_PCD },
+
+ { "hw_rei", SPCD(0x1E,0x3FF8000), EV4|EV5, ARG_NONE },
+ { "hw_rei_stall", SPCD(0x1E,0x3FFC000), EV5, ARG_NONE },
+ { "hw_jmp", EV6HWMBR(0x1E,0x0), EV6, { ZA, PRB, EV6HWJMPHINT } },
+ { "hw_jsr", EV6HWMBR(0x1E,0x2), EV6, { ZA, PRB, EV6HWJMPHINT } },
+ { "hw_ret", EV6HWMBR(0x1E,0x4), EV6, { ZA, PRB } },
+ { "hw_jcr", EV6HWMBR(0x1E,0x6), EV6, { ZA, PRB } },
+ { "hw_coroutine", EV6HWMBR(0x1E,0x6), EV6, { ZA, PRB } }, /* alias */
+ { "hw_jmp/stall", EV6HWMBR(0x1E,0x1), EV6, { ZA, PRB, EV6HWJMPHINT } },
+ { "hw_jsr/stall", EV6HWMBR(0x1E,0x3), EV6, { ZA, PRB, EV6HWJMPHINT } },
+ { "hw_ret/stall", EV6HWMBR(0x1E,0x5), EV6, { ZA, PRB } },
+ { "hw_jcr/stall", EV6HWMBR(0x1E,0x7), EV6, { ZA, PRB } },
+ { "hw_coroutine/stall", EV6HWMBR(0x1E,0x7), EV6, { ZA, PRB } }, /* alias */
+ { "pal1e", PCD(0x1E), BASE, ARG_PCD },
+
+ { "hw_stl", EV4HWMEM(0x1F,0x0), EV4, ARG_EV4HWMEM },
+ { "hw_stl", EV5HWMEM(0x1F,0x00), EV5, ARG_EV5HWMEM },
+ { "hw_stl", EV6HWMEM(0x1F,0x4), EV6, ARG_EV6HWMEM }, /* ??? 8 */
+ { "hw_stl/a", EV4HWMEM(0x1F,0x4), EV4, ARG_EV4HWMEM },
+ { "hw_stl/a", EV5HWMEM(0x1F,0x10), EV5, ARG_EV5HWMEM },
+ { "hw_stl/a", EV6HWMEM(0x1F,0xC), EV6, ARG_EV6HWMEM },
+ { "hw_stl/ac", EV5HWMEM(0x1F,0x11), EV5, ARG_EV5HWMEM },
+ { "hw_stl/ar", EV4HWMEM(0x1F,0x6), EV4, ARG_EV4HWMEM },
+ { "hw_stl/av", EV5HWMEM(0x1F,0x12), EV5, ARG_EV5HWMEM },
+ { "hw_stl/avc", EV5HWMEM(0x1F,0x13), EV5, ARG_EV5HWMEM },
+ { "hw_stl/c", EV5HWMEM(0x1F,0x01), EV5, ARG_EV5HWMEM },
+ { "hw_stl/p", EV4HWMEM(0x1F,0x8), EV4, ARG_EV4HWMEM },
+ { "hw_stl/p", EV5HWMEM(0x1F,0x20), EV5, ARG_EV5HWMEM },
+ { "hw_stl/p", EV6HWMEM(0x1F,0x0), EV6, ARG_EV6HWMEM },
+ { "hw_stl/pa", EV4HWMEM(0x1F,0xC), EV4, ARG_EV4HWMEM },
+ { "hw_stl/pa", EV5HWMEM(0x1F,0x30), EV5, ARG_EV5HWMEM },
+ { "hw_stl/pac", EV5HWMEM(0x1F,0x31), EV5, ARG_EV5HWMEM },
+ { "hw_stl/pav", EV5HWMEM(0x1F,0x32), EV5, ARG_EV5HWMEM },
+ { "hw_stl/pavc", EV5HWMEM(0x1F,0x33), EV5, ARG_EV5HWMEM },
+ { "hw_stl/pc", EV5HWMEM(0x1F,0x21), EV5, ARG_EV5HWMEM },
+ { "hw_stl/pr", EV4HWMEM(0x1F,0xA), EV4, ARG_EV4HWMEM },
+ { "hw_stl/pv", EV5HWMEM(0x1F,0x22), EV5, ARG_EV5HWMEM },
+ { "hw_stl/pvc", EV5HWMEM(0x1F,0x23), EV5, ARG_EV5HWMEM },
+ { "hw_stl/r", EV4HWMEM(0x1F,0x2), EV4, ARG_EV4HWMEM },
+ { "hw_stl/v", EV5HWMEM(0x1F,0x02), EV5, ARG_EV5HWMEM },
+ { "hw_stl/vc", EV5HWMEM(0x1F,0x03), EV5, ARG_EV5HWMEM },
+ { "hw_stl_c", EV5HWMEM(0x1F,0x01), EV5, ARG_EV5HWMEM },
+ { "hw_stl_c/a", EV5HWMEM(0x1F,0x11), EV5, ARG_EV5HWMEM },
+ { "hw_stl_c/av", EV5HWMEM(0x1F,0x13), EV5, ARG_EV5HWMEM },
+ { "hw_stl_c/p", EV5HWMEM(0x1F,0x21), EV5, ARG_EV5HWMEM },
+ { "hw_stl_c/p", EV6HWMEM(0x1F,0x2), EV6, ARG_EV6HWMEM },
+ { "hw_stl_c/pa", EV5HWMEM(0x1F,0x31), EV5, ARG_EV5HWMEM },
+ { "hw_stl_c/pav", EV5HWMEM(0x1F,0x33), EV5, ARG_EV5HWMEM },
+ { "hw_stl_c/pv", EV5HWMEM(0x1F,0x23), EV5, ARG_EV5HWMEM },
+ { "hw_stl_c/v", EV5HWMEM(0x1F,0x03), EV5, ARG_EV5HWMEM },
+ { "hw_stq", EV4HWMEM(0x1F,0x1), EV4, ARG_EV4HWMEM },
+ { "hw_stq", EV5HWMEM(0x1F,0x04), EV5, ARG_EV5HWMEM },
+ { "hw_stq", EV6HWMEM(0x1F,0x5), EV6, ARG_EV6HWMEM }, /* ??? 9 */
+ { "hw_stq/a", EV4HWMEM(0x1F,0x5), EV4, ARG_EV4HWMEM },
+ { "hw_stq/a", EV5HWMEM(0x1F,0x14), EV5, ARG_EV5HWMEM },
+ { "hw_stq/a", EV6HWMEM(0x1F,0xD), EV6, ARG_EV6HWMEM },
+ { "hw_stq/ac", EV5HWMEM(0x1F,0x15), EV5, ARG_EV5HWMEM },
+ { "hw_stq/ar", EV4HWMEM(0x1F,0x7), EV4, ARG_EV4HWMEM },
+ { "hw_stq/av", EV5HWMEM(0x1F,0x16), EV5, ARG_EV5HWMEM },
+ { "hw_stq/avc", EV5HWMEM(0x1F,0x17), EV5, ARG_EV5HWMEM },
+ { "hw_stq/c", EV5HWMEM(0x1F,0x05), EV5, ARG_EV5HWMEM },
+ { "hw_stq/p", EV4HWMEM(0x1F,0x9), EV4, ARG_EV4HWMEM },
+ { "hw_stq/p", EV5HWMEM(0x1F,0x24), EV5, ARG_EV5HWMEM },
+ { "hw_stq/p", EV6HWMEM(0x1F,0x1), EV6, ARG_EV6HWMEM },
+ { "hw_stq/pa", EV4HWMEM(0x1F,0xD), EV4, ARG_EV4HWMEM },
+ { "hw_stq/pa", EV5HWMEM(0x1F,0x34), EV5, ARG_EV5HWMEM },
+ { "hw_stq/pac", EV5HWMEM(0x1F,0x35), EV5, ARG_EV5HWMEM },
+ { "hw_stq/par", EV4HWMEM(0x1F,0xE), EV4, ARG_EV4HWMEM },
+ { "hw_stq/par", EV4HWMEM(0x1F,0xF), EV4, ARG_EV4HWMEM },
+ { "hw_stq/pav", EV5HWMEM(0x1F,0x36), EV5, ARG_EV5HWMEM },
+ { "hw_stq/pavc", EV5HWMEM(0x1F,0x37), EV5, ARG_EV5HWMEM },
+ { "hw_stq/pc", EV5HWMEM(0x1F,0x25), EV5, ARG_EV5HWMEM },
+ { "hw_stq/pr", EV4HWMEM(0x1F,0xB), EV4, ARG_EV4HWMEM },
+ { "hw_stq/pv", EV5HWMEM(0x1F,0x26), EV5, ARG_EV5HWMEM },
+ { "hw_stq/pvc", EV5HWMEM(0x1F,0x27), EV5, ARG_EV5HWMEM },
+ { "hw_stq/r", EV4HWMEM(0x1F,0x3), EV4, ARG_EV4HWMEM },
+ { "hw_stq/v", EV5HWMEM(0x1F,0x06), EV5, ARG_EV5HWMEM },
+ { "hw_stq/vc", EV5HWMEM(0x1F,0x07), EV5, ARG_EV5HWMEM },
+ { "hw_stq_c", EV5HWMEM(0x1F,0x05), EV5, ARG_EV5HWMEM },
+ { "hw_stq_c/a", EV5HWMEM(0x1F,0x15), EV5, ARG_EV5HWMEM },
+ { "hw_stq_c/av", EV5HWMEM(0x1F,0x17), EV5, ARG_EV5HWMEM },
+ { "hw_stq_c/p", EV5HWMEM(0x1F,0x25), EV5, ARG_EV5HWMEM },
+ { "hw_stq_c/p", EV6HWMEM(0x1F,0x3), EV6, ARG_EV6HWMEM },
+ { "hw_stq_c/pa", EV5HWMEM(0x1F,0x35), EV5, ARG_EV5HWMEM },
+ { "hw_stq_c/pav", EV5HWMEM(0x1F,0x37), EV5, ARG_EV5HWMEM },
+ { "hw_stq_c/pv", EV5HWMEM(0x1F,0x27), EV5, ARG_EV5HWMEM },
+ { "hw_stq_c/v", EV5HWMEM(0x1F,0x07), EV5, ARG_EV5HWMEM },
+ { "hw_st", EV4HWMEM(0x1F,0x0), EV4, ARG_EV4HWMEM },
+ { "hw_st", EV5HWMEM(0x1F,0x00), EV5, ARG_EV5HWMEM },
+ { "hw_st/a", EV4HWMEM(0x1F,0x4), EV4, ARG_EV4HWMEM },
+ { "hw_st/a", EV5HWMEM(0x1F,0x10), EV5, ARG_EV5HWMEM },
+ { "hw_st/ac", EV5HWMEM(0x1F,0x11), EV5, ARG_EV5HWMEM },
+ { "hw_st/aq", EV4HWMEM(0x1F,0x5), EV4, ARG_EV4HWMEM },
+ { "hw_st/aq", EV5HWMEM(0x1F,0x14), EV5, ARG_EV5HWMEM },
+ { "hw_st/aqc", EV5HWMEM(0x1F,0x15), EV5, ARG_EV5HWMEM },
+ { "hw_st/aqv", EV5HWMEM(0x1F,0x16), EV5, ARG_EV5HWMEM },
+ { "hw_st/aqvc", EV5HWMEM(0x1F,0x17), EV5, ARG_EV5HWMEM },
+ { "hw_st/ar", EV4HWMEM(0x1F,0x6), EV4, ARG_EV4HWMEM },
+ { "hw_st/arq", EV4HWMEM(0x1F,0x7), EV4, ARG_EV4HWMEM },
+ { "hw_st/av", EV5HWMEM(0x1F,0x12), EV5, ARG_EV5HWMEM },
+ { "hw_st/avc", EV5HWMEM(0x1F,0x13), EV5, ARG_EV5HWMEM },
+ { "hw_st/c", EV5HWMEM(0x1F,0x01), EV5, ARG_EV5HWMEM },
+ { "hw_st/p", EV4HWMEM(0x1F,0x8), EV4, ARG_EV4HWMEM },
+ { "hw_st/p", EV5HWMEM(0x1F,0x20), EV5, ARG_EV5HWMEM },
+ { "hw_st/pa", EV4HWMEM(0x1F,0xC), EV4, ARG_EV4HWMEM },
+ { "hw_st/pa", EV5HWMEM(0x1F,0x30), EV5, ARG_EV5HWMEM },
+ { "hw_st/pac", EV5HWMEM(0x1F,0x31), EV5, ARG_EV5HWMEM },
+ { "hw_st/paq", EV4HWMEM(0x1F,0xD), EV4, ARG_EV4HWMEM },
+ { "hw_st/paq", EV5HWMEM(0x1F,0x34), EV5, ARG_EV5HWMEM },
+ { "hw_st/paqc", EV5HWMEM(0x1F,0x35), EV5, ARG_EV5HWMEM },
+ { "hw_st/paqv", EV5HWMEM(0x1F,0x36), EV5, ARG_EV5HWMEM },
+ { "hw_st/paqvc", EV5HWMEM(0x1F,0x37), EV5, ARG_EV5HWMEM },
+ { "hw_st/par", EV4HWMEM(0x1F,0xE), EV4, ARG_EV4HWMEM },
+ { "hw_st/parq", EV4HWMEM(0x1F,0xF), EV4, ARG_EV4HWMEM },
+ { "hw_st/pav", EV5HWMEM(0x1F,0x32), EV5, ARG_EV5HWMEM },
+ { "hw_st/pavc", EV5HWMEM(0x1F,0x33), EV5, ARG_EV5HWMEM },
+ { "hw_st/pc", EV5HWMEM(0x1F,0x21), EV5, ARG_EV5HWMEM },
+ { "hw_st/pq", EV4HWMEM(0x1F,0x9), EV4, ARG_EV4HWMEM },
+ { "hw_st/pq", EV5HWMEM(0x1F,0x24), EV5, ARG_EV5HWMEM },
+ { "hw_st/pqc", EV5HWMEM(0x1F,0x25), EV5, ARG_EV5HWMEM },
+ { "hw_st/pqv", EV5HWMEM(0x1F,0x26), EV5, ARG_EV5HWMEM },
+ { "hw_st/pqvc", EV5HWMEM(0x1F,0x27), EV5, ARG_EV5HWMEM },
+ { "hw_st/pr", EV4HWMEM(0x1F,0xA), EV4, ARG_EV4HWMEM },
+ { "hw_st/prq", EV4HWMEM(0x1F,0xB), EV4, ARG_EV4HWMEM },
+ { "hw_st/pv", EV5HWMEM(0x1F,0x22), EV5, ARG_EV5HWMEM },
+ { "hw_st/pvc", EV5HWMEM(0x1F,0x23), EV5, ARG_EV5HWMEM },
+ { "hw_st/q", EV4HWMEM(0x1F,0x1), EV4, ARG_EV4HWMEM },
+ { "hw_st/q", EV5HWMEM(0x1F,0x04), EV5, ARG_EV5HWMEM },
+ { "hw_st/qc", EV5HWMEM(0x1F,0x05), EV5, ARG_EV5HWMEM },
+ { "hw_st/qv", EV5HWMEM(0x1F,0x06), EV5, ARG_EV5HWMEM },
+ { "hw_st/qvc", EV5HWMEM(0x1F,0x07), EV5, ARG_EV5HWMEM },
+ { "hw_st/r", EV4HWMEM(0x1F,0x2), EV4, ARG_EV4HWMEM },
+ { "hw_st/v", EV5HWMEM(0x1F,0x02), EV5, ARG_EV5HWMEM },
+ { "hw_st/vc", EV5HWMEM(0x1F,0x03), EV5, ARG_EV5HWMEM },
+ { "pal1f", PCD(0x1F), BASE, ARG_PCD },
+
+ { "ldf", MEM(0x20), BASE, ARG_FMEM },
+ { "ldg", MEM(0x21), BASE, ARG_FMEM },
+ { "lds", MEM(0x22), BASE, ARG_FMEM },
+ { "ldt", MEM(0x23), BASE, ARG_FMEM },
+ { "stf", MEM(0x24), BASE, ARG_FMEM },
+ { "stg", MEM(0x25), BASE, ARG_FMEM },
+ { "sts", MEM(0x26), BASE, ARG_FMEM },
+ { "stt", MEM(0x27), BASE, ARG_FMEM },
+
+ { "ldl", MEM(0x28), BASE, ARG_MEM },
+ { "ldq", MEM(0x29), BASE, ARG_MEM },
+ { "ldl_l", MEM(0x2A), BASE, ARG_MEM },
+ { "ldq_l", MEM(0x2B), BASE, ARG_MEM },
+ { "stl", MEM(0x2C), BASE, ARG_MEM },
+ { "stq", MEM(0x2D), BASE, ARG_MEM },
+ { "stl_c", MEM(0x2E), BASE, ARG_MEM },
+ { "stq_c", MEM(0x2F), BASE, ARG_MEM },
+
+ { "br", BRA(0x30), BASE, { ZA, BDISP } }, /* pseudo */
+ { "br", BRA(0x30), BASE, ARG_BRA },
+ { "fbeq", BRA(0x31), BASE, ARG_FBRA },
+ { "fblt", BRA(0x32), BASE, ARG_FBRA },
+ { "fble", BRA(0x33), BASE, ARG_FBRA },
+ { "bsr", BRA(0x34), BASE, ARG_BRA },
+ { "fbne", BRA(0x35), BASE, ARG_FBRA },
+ { "fbge", BRA(0x36), BASE, ARG_FBRA },
+ { "fbgt", BRA(0x37), BASE, ARG_FBRA },
+ { "blbc", BRA(0x38), BASE, ARG_BRA },
+ { "beq", BRA(0x39), BASE, ARG_BRA },
+ { "blt", BRA(0x3A), BASE, ARG_BRA },
+ { "ble", BRA(0x3B), BASE, ARG_BRA },
+ { "blbs", BRA(0x3C), BASE, ARG_BRA },
+ { "bne", BRA(0x3D), BASE, ARG_BRA },
+ { "bge", BRA(0x3E), BASE, ARG_BRA },
+ { "bgt", BRA(0x3F), BASE, ARG_BRA },
+};
+
+const unsigned alpha_num_opcodes = sizeof(alpha_opcodes)/sizeof(*alpha_opcodes);
+
+/* OSF register names. */
+
+static const char * const osf_regnames[64] = {
+ "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
+ "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp",
+ "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
+ "t10", "t11", "ra", "t12", "at", "gp", "sp", "zero",
+ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
+ "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
+ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
+ "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
+};
+
+/* VMS register names. */
+
+static const char * const vms_regnames[64] = {
+ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
+ "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
+ "R16", "R17", "R18", "R19", "R20", "R21", "R22", "R23",
+ "R24", "AI", "RA", "PV", "AT", "FP", "SP", "RZ",
+ "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7",
+ "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15",
+ "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23",
+ "F24", "F25", "F26", "F27", "F28", "F29", "F30", "FZ"
+};
+
+/* Disassemble Alpha instructions. */
+
+int
+print_insn_alpha (bfd_vma memaddr, struct disassemble_info *info)
+{
+ static const struct alpha_opcode *opcode_index[AXP_NOPS+1];
+ const char * const * regnames;
+ const struct alpha_opcode *opcode, *opcode_end;
+ const unsigned char *opindex;
+ unsigned insn, op, isa_mask;
+ int need_comma;
+
+ /* Initialize the majorop table the first time through */
+ if (!opcode_index[0])
+ {
+ opcode = alpha_opcodes;
+ opcode_end = opcode + alpha_num_opcodes;
+
+ for (op = 0; op < AXP_NOPS; ++op)
+ {
+ opcode_index[op] = opcode;
+ while (opcode < opcode_end && op == AXP_OP (opcode->opcode))
+ ++opcode;
+ }
+ opcode_index[op] = opcode;
+ }
+
+ if (info->flavour == bfd_target_evax_flavour)
+ regnames = vms_regnames;
+ else
+ regnames = osf_regnames;
+
+ isa_mask = AXP_OPCODE_NOPAL;
+ switch (info->mach)
+ {
+ case bfd_mach_alpha_ev4:
+ isa_mask |= AXP_OPCODE_EV4;
+ break;
+ case bfd_mach_alpha_ev5:
+ isa_mask |= AXP_OPCODE_EV5;
+ break;
+ case bfd_mach_alpha_ev6:
+ isa_mask |= AXP_OPCODE_EV6;
+ break;
+ }
+
+ /* Read the insn into a host word */
+ {
+ bfd_byte buffer[4];
+ int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, memaddr, info);
+ return -1;
+ }
+ insn = bfd_getl32 (buffer);
+ }
+
+ /* Get the major opcode of the instruction. */
+ op = AXP_OP (insn);
+
+ /* Find the first match in the opcode table. */
+ opcode_end = opcode_index[op + 1];
+ for (opcode = opcode_index[op]; opcode < opcode_end; ++opcode)
+ {
+ if ((insn ^ opcode->opcode) & opcode->mask)
+ continue;
+
+ if (!(opcode->flags & isa_mask))
+ continue;
+
+ /* Make two passes over the operands. First see if any of them
+ have extraction functions, and, if they do, make sure the
+ instruction is valid. */
+ {
+ int invalid = 0;
+ for (opindex = opcode->operands; *opindex != 0; opindex++)
+ {
+ const struct alpha_operand *operand = alpha_operands + *opindex;
+ if (operand->extract)
+ (*operand->extract) (insn, &invalid);
+ }
+ if (invalid)
+ continue;
+ }
+
+ /* The instruction is valid. */
+ goto found;
+ }
+
+ /* No instruction found */
+ (*info->fprintf_func) (info->stream, ".long %#08x", insn);
+
+ return 4;
+
+found:
+ (*info->fprintf_func) (info->stream, "%s", opcode->name);
+ if (opcode->operands[0] != 0)
+ (*info->fprintf_func) (info->stream, "\t");
+
+ /* Now extract and print the operands. */
+ need_comma = 0;
+ for (opindex = opcode->operands; *opindex != 0; opindex++)
+ {
+ const struct alpha_operand *operand = alpha_operands + *opindex;
+ int value;
+
+ /* Operands that are marked FAKE are simply ignored. We
+ already made sure that the extract function considered
+ the instruction to be valid. */
+ if ((operand->flags & AXP_OPERAND_FAKE) != 0)
+ continue;
+
+ /* Extract the value from the instruction. */
+ if (operand->extract)
+ value = (*operand->extract) (insn, (int *) NULL);
+ else
+ {
+ value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
+ if (operand->flags & AXP_OPERAND_SIGNED)
+ {
+ int signbit = 1 << (operand->bits - 1);
+ value = (value ^ signbit) - signbit;
+ }
+ }
+
+ if (need_comma &&
+ ((operand->flags & (AXP_OPERAND_PARENS | AXP_OPERAND_COMMA))
+ != AXP_OPERAND_PARENS))
+ {
+ (*info->fprintf_func) (info->stream, ",");
+ }
+ if (operand->flags & AXP_OPERAND_PARENS)
+ (*info->fprintf_func) (info->stream, "(");
+
+ /* Print the operand as directed by the flags. */
+ if (operand->flags & AXP_OPERAND_IR)
+ (*info->fprintf_func) (info->stream, "%s", regnames[value]);
+ else if (operand->flags & AXP_OPERAND_FPR)
+ (*info->fprintf_func) (info->stream, "%s", regnames[value + 32]);
+ else if (operand->flags & AXP_OPERAND_RELATIVE)
+ (*info->print_address_func) (memaddr + 4 + value, info);
+ else if (operand->flags & AXP_OPERAND_SIGNED)
+ (*info->fprintf_func) (info->stream, "%d", value);
+ else
+ (*info->fprintf_func) (info->stream, "%#x", value);
+
+ if (operand->flags & AXP_OPERAND_PARENS)
+ (*info->fprintf_func) (info->stream, ")");
+ need_comma = 1;
+ }
+
+ return 4;
+}
diff --git a/disas/arm.c b/disas/arm.c
new file mode 100644
index 0000000000..4927d8ad7c
--- /dev/null
+++ b/disas/arm.c
@@ -0,0 +1,4136 @@
+/* Instruction printing code for the ARM
+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ 2007, Free Software Foundation, Inc.
+ Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
+ Modification by James G. Smith (jsmith@cygnus.co.uk)
+
+ This file is part of libopcodes.
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>. */
+
+/* Start of qemu specific additions. Mostly this is stub definitions
+ for things we don't care about. */
+
+#include "disas/bfd.h"
+#define ATTRIBUTE_UNUSED __attribute__((unused))
+#define ISSPACE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n')
+
+#define ARM_EXT_V1 0
+#define ARM_EXT_V2 0
+#define ARM_EXT_V2S 0
+#define ARM_EXT_V3 0
+#define ARM_EXT_V3M 0
+#define ARM_EXT_V4 0
+#define ARM_EXT_V4T 0
+#define ARM_EXT_V5 0
+#define ARM_EXT_V5T 0
+#define ARM_EXT_V5ExP 0
+#define ARM_EXT_V5E 0
+#define ARM_EXT_V5J 0
+#define ARM_EXT_V6 0
+#define ARM_EXT_V6K 0
+#define ARM_EXT_V6Z 0
+#define ARM_EXT_V6T2 0
+#define ARM_EXT_V7 0
+#define ARM_EXT_DIV 0
+
+/* Co-processor space extensions. */
+#define ARM_CEXT_XSCALE 0
+#define ARM_CEXT_MAVERICK 0
+#define ARM_CEXT_IWMMXT 0
+
+#define FPU_FPA_EXT_V1 0
+#define FPU_FPA_EXT_V2 0
+#define FPU_VFP_EXT_NONE 0
+#define FPU_VFP_EXT_V1xD 0
+#define FPU_VFP_EXT_V1 0
+#define FPU_VFP_EXT_V2 0
+#define FPU_MAVERICK 0
+#define FPU_VFP_EXT_V3 0
+#define FPU_NEON_EXT_V1 0
+
+/* Assume host uses ieee float. */
+static void floatformat_to_double (unsigned char *data, double *dest)
+{
+ union {
+ uint32_t i;
+ float f;
+ } u;
+ u.i = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
+ *dest = u.f;
+}
+
+/* End of qemu specific additions. */
+
+/* FIXME: Belongs in global header. */
+#ifndef strneq
+#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
+#endif
+
+#ifndef NUM_ELEM
+#define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
+#endif
+
+struct opcode32
+{
+ unsigned long arch; /* Architecture defining this insn. */
+ unsigned long value, mask; /* Recognise insn if (op&mask)==value. */
+ const char *assembler; /* How to disassemble this insn. */
+};
+
+struct opcode16
+{
+ unsigned long arch; /* Architecture defining this insn. */
+ unsigned short value, mask; /* Recognise insn if (op&mask)==value. */
+ const char *assembler; /* How to disassemble this insn. */
+};
+
+/* print_insn_coprocessor recognizes the following format control codes:
+
+ %% %
+
+ %c print condition code (always bits 28-31 in ARM mode)
+ %q print shifter argument
+ %u print condition code (unconditional in ARM mode)
+ %A print address for ldc/stc/ldf/stf instruction
+ %B print vstm/vldm register list
+ %C print vstr/vldr address operand
+ %I print cirrus signed shift immediate: bits 0..3|4..6
+ %F print the COUNT field of a LFM/SFM instruction.
+ %P print floating point precision in arithmetic insn
+ %Q print floating point precision in ldf/stf insn
+ %R print floating point rounding mode
+
+ %<bitfield>r print as an ARM register
+ %<bitfield>d print the bitfield in decimal
+ %<bitfield>k print immediate for VFPv3 conversion instruction
+ %<bitfield>x print the bitfield in hex
+ %<bitfield>X print the bitfield as 1 hex digit without leading "0x"
+ %<bitfield>f print a floating point constant if >7 else a
+ floating point register
+ %<bitfield>w print as an iWMMXt width field - [bhwd]ss/us
+ %<bitfield>g print as an iWMMXt 64-bit register
+ %<bitfield>G print as an iWMMXt general purpose or control register
+ %<bitfield>D print as a NEON D register
+ %<bitfield>Q print as a NEON Q register
+
+ %y<code> print a single precision VFP reg.
+ Codes: 0=>Sm, 1=>Sd, 2=>Sn, 3=>multi-list, 4=>Sm pair
+ %z<code> print a double precision VFP reg
+ Codes: 0=>Dm, 1=>Dd, 2=>Dn, 3=>multi-list
+
+ %<bitfield>'c print specified char iff bitfield is all ones
+ %<bitfield>`c print specified char iff bitfield is all zeroes
+ %<bitfield>?ab... select from array of values in big endian order
+
+ %L print as an iWMMXt N/M width field.
+ %Z print the Immediate of a WSHUFH instruction.
+ %l like 'A' except use byte offsets for 'B' & 'H'
+ versions.
+ %i print 5-bit immediate in bits 8,3..0
+ (print "32" when 0)
+ %r print register offset address for wldt/wstr instruction
+*/
+
+/* Common coprocessor opcodes shared between Arm and Thumb-2. */
+
+static const struct opcode32 coprocessor_opcodes[] =
+{
+ /* XScale instructions. */
+ {ARM_CEXT_XSCALE, 0x0e200010, 0x0fff0ff0, "mia%c\tacc0, %0-3r, %12-15r"},
+ {ARM_CEXT_XSCALE, 0x0e280010, 0x0fff0ff0, "miaph%c\tacc0, %0-3r, %12-15r"},
+ {ARM_CEXT_XSCALE, 0x0e2c0010, 0x0ffc0ff0, "mia%17'T%17`B%16'T%16`B%c\tacc0, %0-3r, %12-15r"},
+ {ARM_CEXT_XSCALE, 0x0c400000, 0x0ff00fff, "mar%c\tacc0, %12-15r, %16-19r"},
+ {ARM_CEXT_XSCALE, 0x0c500000, 0x0ff00fff, "mra%c\t%12-15r, %16-19r, acc0"},
+
+ /* Intel Wireless MMX technology instructions. */
+#define FIRST_IWMMXT_INSN 0x0e130130
+#define IWMMXT_INSN_COUNT 73
+ {ARM_CEXT_IWMMXT, 0x0e130130, 0x0f3f0fff, "tandc%22-23w%c\t%12-15r"},
+ {ARM_CEXT_XSCALE, 0x0e400010, 0x0ff00f3f, "tbcst%6-7w%c\t%16-19g, %12-15r"},
+ {ARM_CEXT_XSCALE, 0x0e130170, 0x0f3f0ff8, "textrc%22-23w%c\t%12-15r, #%0-2d"},
+ {ARM_CEXT_XSCALE, 0x0e100070, 0x0f300ff0, "textrm%3?su%22-23w%c\t%12-15r, %16-19g, #%0-2d"},
+ {ARM_CEXT_XSCALE, 0x0e600010, 0x0ff00f38, "tinsr%6-7w%c\t%16-19g, %12-15r, #%0-2d"},
+ {ARM_CEXT_XSCALE, 0x0e000110, 0x0ff00fff, "tmcr%c\t%16-19G, %12-15r"},
+ {ARM_CEXT_XSCALE, 0x0c400000, 0x0ff00ff0, "tmcrr%c\t%0-3g, %12-15r, %16-19r"},
+ {ARM_CEXT_XSCALE, 0x0e2c0010, 0x0ffc0e10, "tmia%17?tb%16?tb%c\t%5-8g, %0-3r, %12-15r"},
+ {ARM_CEXT_XSCALE, 0x0e200010, 0x0fff0e10, "tmia%c\t%5-8g, %0-3r, %12-15r"},
+ {ARM_CEXT_XSCALE, 0x0e280010, 0x0fff0e10, "tmiaph%c\t%5-8g, %0-3r, %12-15r"},
+ {ARM_CEXT_XSCALE, 0x0e100030, 0x0f300fff, "tmovmsk%22-23w%c\t%12-15r, %16-19g"},
+ {ARM_CEXT_XSCALE, 0x0e100110, 0x0ff00ff0, "tmrc%c\t%12-15r, %16-19G"},
+ {ARM_CEXT_XSCALE, 0x0c500000, 0x0ff00ff0, "tmrrc%c\t%12-15r, %16-19r, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e130150, 0x0f3f0fff, "torc%22-23w%c\t%12-15r"},
+ {ARM_CEXT_XSCALE, 0x0e130190, 0x0f3f0fff, "torvsc%22-23w%c\t%12-15r"},
+ {ARM_CEXT_XSCALE, 0x0e2001c0, 0x0f300fff, "wabs%22-23w%c\t%12-15g, %16-19g"},
+ {ARM_CEXT_XSCALE, 0x0e0001c0, 0x0f300fff, "wacc%22-23w%c\t%12-15g, %16-19g"},
+ {ARM_CEXT_XSCALE, 0x0e000180, 0x0f000ff0, "wadd%20-23w%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e2001a0, 0x0f300ff0, "waddbhus%22?ml%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0ea001a0, 0x0ff00ff0, "waddsubhx%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e000020, 0x0f800ff0, "waligni%c\t%12-15g, %16-19g, %0-3g, #%20-22d"},
+ {ARM_CEXT_XSCALE, 0x0e800020, 0x0fc00ff0, "walignr%20-21d%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e200000, 0x0fe00ff0, "wand%20'n%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e800000, 0x0fa00ff0, "wavg2%22?hb%20'r%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e400000, 0x0fe00ff0, "wavg4%20'r%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e000060, 0x0f300ff0, "wcmpeq%22-23w%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e100060, 0x0f100ff0, "wcmpgt%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0xfc500100, 0xfe500f00, "wldrd\t%12-15g, %r"},
+ {ARM_CEXT_XSCALE, 0xfc100100, 0xfe500f00, "wldrw\t%12-15G, %A"},
+ {ARM_CEXT_XSCALE, 0x0c100000, 0x0e100e00, "wldr%L%c\t%12-15g, %l"},
+ {ARM_CEXT_XSCALE, 0x0e400100, 0x0fc00ff0, "wmac%21?su%20'z%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e800100, 0x0fc00ff0, "wmadd%21?su%20'x%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0ec00100, 0x0fd00ff0, "wmadd%21?sun%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e000160, 0x0f100ff0, "wmax%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e000080, 0x0f100fe0, "wmerge%c\t%12-15g, %16-19g, %0-3g, #%21-23d"},
+ {ARM_CEXT_XSCALE, 0x0e0000a0, 0x0f800ff0, "wmia%21?tb%20?tb%22'n%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e800120, 0x0f800ff0, "wmiaw%21?tb%20?tb%22'n%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e100160, 0x0f100ff0, "wmin%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e000100, 0x0fc00ff0, "wmul%21?su%20?ml%23'r%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0ed00100, 0x0fd00ff0, "wmul%21?sumr%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0ee000c0, 0x0fe00ff0, "wmulwsm%20`r%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0ec000c0, 0x0fe00ff0, "wmulwum%20`r%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0eb000c0, 0x0ff00ff0, "wmulwl%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e8000a0, 0x0f800ff0, "wqmia%21?tb%20?tb%22'n%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e100080, 0x0fd00ff0, "wqmulm%21'r%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0ec000e0, 0x0fd00ff0, "wqmulwm%21'r%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e000000, 0x0ff00ff0, "wor%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e000080, 0x0f000ff0, "wpack%20-23w%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0xfe300040, 0xff300ef0, "wror%22-23w\t%12-15g, %16-19g, #%i"},
+ {ARM_CEXT_XSCALE, 0x0e300040, 0x0f300ff0, "wror%22-23w%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e300140, 0x0f300ff0, "wror%22-23wg%c\t%12-15g, %16-19g, %0-3G"},
+ {ARM_CEXT_XSCALE, 0x0e000120, 0x0fa00ff0, "wsad%22?hb%20'z%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e0001e0, 0x0f000ff0, "wshufh%c\t%12-15g, %16-19g, #%Z"},
+ {ARM_CEXT_XSCALE, 0xfe100040, 0xff300ef0, "wsll%22-23w\t%12-15g, %16-19g, #%i"},
+ {ARM_CEXT_XSCALE, 0x0e100040, 0x0f300ff0, "wsll%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e100148, 0x0f300ffc, "wsll%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"},
+ {ARM_CEXT_XSCALE, 0xfe000040, 0xff300ef0, "wsra%22-23w\t%12-15g, %16-19g, #%i"},
+ {ARM_CEXT_XSCALE, 0x0e000040, 0x0f300ff0, "wsra%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e000148, 0x0f300ffc, "wsra%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"},
+ {ARM_CEXT_XSCALE, 0xfe200040, 0xff300ef0, "wsrl%22-23w\t%12-15g, %16-19g, #%i"},
+ {ARM_CEXT_XSCALE, 0x0e200040, 0x0f300ff0, "wsrl%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e200148, 0x0f300ffc, "wsrl%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"},
+ {ARM_CEXT_XSCALE, 0xfc400100, 0xfe500f00, "wstrd\t%12-15g, %r"},
+ {ARM_CEXT_XSCALE, 0xfc000100, 0xfe500f00, "wstrw\t%12-15G, %A"},
+ {ARM_CEXT_XSCALE, 0x0c000000, 0x0e100e00, "wstr%L%c\t%12-15g, %l"},
+ {ARM_CEXT_XSCALE, 0x0e0001a0, 0x0f000ff0, "wsub%20-23w%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0ed001c0, 0x0ff00ff0, "wsubaddhx%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e1001c0, 0x0f300ff0, "wabsdiff%22-23w%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e0000c0, 0x0fd00fff, "wunpckeh%21?sub%c\t%12-15g, %16-19g"},
+ {ARM_CEXT_XSCALE, 0x0e4000c0, 0x0fd00fff, "wunpckeh%21?suh%c\t%12-15g, %16-19g"},
+ {ARM_CEXT_XSCALE, 0x0e8000c0, 0x0fd00fff, "wunpckeh%21?suw%c\t%12-15g, %16-19g"},
+ {ARM_CEXT_XSCALE, 0x0e0000e0, 0x0f100fff, "wunpckel%21?su%22-23w%c\t%12-15g, %16-19g"},
+ {ARM_CEXT_XSCALE, 0x0e1000c0, 0x0f300ff0, "wunpckih%22-23w%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e1000e0, 0x0f300ff0, "wunpckil%22-23w%c\t%12-15g, %16-19g, %0-3g"},
+ {ARM_CEXT_XSCALE, 0x0e100000, 0x0ff00ff0, "wxor%c\t%12-15g, %16-19g, %0-3g"},
+
+ /* Floating point coprocessor (FPA) instructions */
+ {FPU_FPA_EXT_V1, 0x0e000100, 0x0ff08f10, "adf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e100100, 0x0ff08f10, "muf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e200100, 0x0ff08f10, "suf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e300100, 0x0ff08f10, "rsf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e400100, 0x0ff08f10, "dvf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e500100, 0x0ff08f10, "rdf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e600100, 0x0ff08f10, "pow%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e700100, 0x0ff08f10, "rpw%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e800100, 0x0ff08f10, "rmf%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e900100, 0x0ff08f10, "fml%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0ea00100, 0x0ff08f10, "fdv%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0eb00100, 0x0ff08f10, "frd%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0ec00100, 0x0ff08f10, "pol%c%P%R\t%12-14f, %16-18f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e008100, 0x0ff08f10, "mvf%c%P%R\t%12-14f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e108100, 0x0ff08f10, "mnf%c%P%R\t%12-14f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e208100, 0x0ff08f10, "abs%c%P%R\t%12-14f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e308100, 0x0ff08f10, "rnd%c%P%R\t%12-14f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e408100, 0x0ff08f10, "sqt%c%P%R\t%12-14f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e508100, 0x0ff08f10, "log%c%P%R\t%12-14f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e608100, 0x0ff08f10, "lgn%c%P%R\t%12-14f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e708100, 0x0ff08f10, "exp%c%P%R\t%12-14f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e808100, 0x0ff08f10, "sin%c%P%R\t%12-14f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e908100, 0x0ff08f10, "cos%c%P%R\t%12-14f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0ea08100, 0x0ff08f10, "tan%c%P%R\t%12-14f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0eb08100, 0x0ff08f10, "asn%c%P%R\t%12-14f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0ec08100, 0x0ff08f10, "acs%c%P%R\t%12-14f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0ed08100, 0x0ff08f10, "atn%c%P%R\t%12-14f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0ee08100, 0x0ff08f10, "urd%c%P%R\t%12-14f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0ef08100, 0x0ff08f10, "nrm%c%P%R\t%12-14f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0e000110, 0x0ff00f1f, "flt%c%P%R\t%16-18f, %12-15r"},
+ {FPU_FPA_EXT_V1, 0x0e100110, 0x0fff0f98, "fix%c%R\t%12-15r, %0-2f"},
+ {FPU_FPA_EXT_V1, 0x0e200110, 0x0fff0fff, "wfs%c\t%12-15r"},
+ {FPU_FPA_EXT_V1, 0x0e300110, 0x0fff0fff, "rfs%c\t%12-15r"},
+ {FPU_FPA_EXT_V1, 0x0e400110, 0x0fff0fff, "wfc%c\t%12-15r"},
+ {FPU_FPA_EXT_V1, 0x0e500110, 0x0fff0fff, "rfc%c\t%12-15r"},
+ {FPU_FPA_EXT_V1, 0x0e90f110, 0x0ff8fff0, "cmf%c\t%16-18f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0eb0f110, 0x0ff8fff0, "cnf%c\t%16-18f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0ed0f110, 0x0ff8fff0, "cmfe%c\t%16-18f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0ef0f110, 0x0ff8fff0, "cnfe%c\t%16-18f, %0-3f"},
+ {FPU_FPA_EXT_V1, 0x0c000100, 0x0e100f00, "stf%c%Q\t%12-14f, %A"},
+ {FPU_FPA_EXT_V1, 0x0c100100, 0x0e100f00, "ldf%c%Q\t%12-14f, %A"},
+ {FPU_FPA_EXT_V2, 0x0c000200, 0x0e100f00, "sfm%c\t%12-14f, %F, %A"},
+ {FPU_FPA_EXT_V2, 0x0c100200, 0x0e100f00, "lfm%c\t%12-14f, %F, %A"},
+
+ /* Register load/store */
+ {FPU_NEON_EXT_V1, 0x0d200b00, 0x0fb00f01, "vstmdb%c\t%16-19r%21'!, %B"},
+ {FPU_NEON_EXT_V1, 0x0d300b00, 0x0fb00f01, "vldmdb%c\t%16-19r%21'!, %B"},
+ {FPU_NEON_EXT_V1, 0x0c800b00, 0x0f900f01, "vstmia%c\t%16-19r%21'!, %B"},
+ {FPU_NEON_EXT_V1, 0x0c900b00, 0x0f900f01, "vldmia%c\t%16-19r%21'!, %B"},
+ {FPU_NEON_EXT_V1, 0x0d000b00, 0x0f300f00, "vstr%c\t%12-15,22D, %C"},
+ {FPU_NEON_EXT_V1, 0x0d100b00, 0x0f300f00, "vldr%c\t%12-15,22D, %C"},
+
+ /* Data transfer between ARM and NEON registers */
+ {FPU_NEON_EXT_V1, 0x0e800b10, 0x0ff00f70, "vdup%c.32\t%16-19,7D, %12-15r"},
+ {FPU_NEON_EXT_V1, 0x0e800b30, 0x0ff00f70, "vdup%c.16\t%16-19,7D, %12-15r"},
+ {FPU_NEON_EXT_V1, 0x0ea00b10, 0x0ff00f70, "vdup%c.32\t%16-19,7Q, %12-15r"},
+ {FPU_NEON_EXT_V1, 0x0ea00b30, 0x0ff00f70, "vdup%c.16\t%16-19,7Q, %12-15r"},
+ {FPU_NEON_EXT_V1, 0x0ec00b10, 0x0ff00f70, "vdup%c.8\t%16-19,7D, %12-15r"},
+ {FPU_NEON_EXT_V1, 0x0ee00b10, 0x0ff00f70, "vdup%c.8\t%16-19,7Q, %12-15r"},
+ {FPU_NEON_EXT_V1, 0x0c400b10, 0x0ff00fd0, "vmov%c\t%0-3,5D, %12-15r, %16-19r"},
+ {FPU_NEON_EXT_V1, 0x0c500b10, 0x0ff00fd0, "vmov%c\t%12-15r, %16-19r, %0-3,5D"},
+ {FPU_NEON_EXT_V1, 0x0e000b10, 0x0fd00f70, "vmov%c.32\t%16-19,7D[%21d], %12-15r"},
+ {FPU_NEON_EXT_V1, 0x0e100b10, 0x0f500f70, "vmov%c.32\t%12-15r, %16-19,7D[%21d]"},
+ {FPU_NEON_EXT_V1, 0x0e000b30, 0x0fd00f30, "vmov%c.16\t%16-19,7D[%6,21d], %12-15r"},
+ {FPU_NEON_EXT_V1, 0x0e100b30, 0x0f500f30, "vmov%c.%23?us16\t%12-15r, %16-19,7D[%6,21d]"},
+ {FPU_NEON_EXT_V1, 0x0e400b10, 0x0fd00f10, "vmov%c.8\t%16-19,7D[%5,6,21d], %12-15r"},
+ {FPU_NEON_EXT_V1, 0x0e500b10, 0x0f500f10, "vmov%c.%23?us8\t%12-15r, %16-19,7D[%5,6,21d]"},
+
+ /* Floating point coprocessor (VFP) instructions */
+ {FPU_VFP_EXT_V1xD, 0x0ef1fa10, 0x0fffffff, "fmstat%c"},
+ {FPU_VFP_EXT_V1xD, 0x0ee00a10, 0x0fff0fff, "fmxr%c\tfpsid, %12-15r"},
+ {FPU_VFP_EXT_V1xD, 0x0ee10a10, 0x0fff0fff, "fmxr%c\tfpscr, %12-15r"},
+ {FPU_VFP_EXT_V1xD, 0x0ee60a10, 0x0fff0fff, "fmxr%c\tmvfr1, %12-15r"},
+ {FPU_VFP_EXT_V1xD, 0x0ee70a10, 0x0fff0fff, "fmxr%c\tmvfr0, %12-15r"},
+ {FPU_VFP_EXT_V1xD, 0x0ee80a10, 0x0fff0fff, "fmxr%c\tfpexc, %12-15r"},
+ {FPU_VFP_EXT_V1xD, 0x0ee90a10, 0x0fff0fff, "fmxr%c\tfpinst, %12-15r\t@ Impl def"},
+ {FPU_VFP_EXT_V1xD, 0x0eea0a10, 0x0fff0fff, "fmxr%c\tfpinst2, %12-15r\t@ Impl def"},
+ {FPU_VFP_EXT_V1xD, 0x0ef00a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpsid"},
+ {FPU_VFP_EXT_V1xD, 0x0ef10a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpscr"},
+ {FPU_VFP_EXT_V1xD, 0x0ef60a10, 0x0fff0fff, "fmrx%c\t%12-15r, mvfr1"},
+ {FPU_VFP_EXT_V1xD, 0x0ef70a10, 0x0fff0fff, "fmrx%c\t%12-15r, mvfr0"},
+ {FPU_VFP_EXT_V1xD, 0x0ef80a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpexc"},
+ {FPU_VFP_EXT_V1xD, 0x0ef90a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst\t@ Impl def"},
+ {FPU_VFP_EXT_V1xD, 0x0efa0a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst2\t@ Impl def"},
+ {FPU_VFP_EXT_V1, 0x0e000b10, 0x0ff00fff, "fmdlr%c\t%z2, %12-15r"},
+ {FPU_VFP_EXT_V1, 0x0e100b10, 0x0ff00fff, "fmrdl%c\t%12-15r, %z2"},
+ {FPU_VFP_EXT_V1, 0x0e200b10, 0x0ff00fff, "fmdhr%c\t%z2, %12-15r"},
+ {FPU_VFP_EXT_V1, 0x0e300b10, 0x0ff00fff, "fmrdh%c\t%12-15r, %z2"},
+ {FPU_VFP_EXT_V1xD, 0x0ee00a10, 0x0ff00fff, "fmxr%c\t<impl def %16-19x>, %12-15r"},
+ {FPU_VFP_EXT_V1xD, 0x0ef00a10, 0x0ff00fff, "fmrx%c\t%12-15r, <impl def %16-19x>"},
+ {FPU_VFP_EXT_V1xD, 0x0e000a10, 0x0ff00f7f, "fmsr%c\t%y2, %12-15r"},
+ {FPU_VFP_EXT_V1xD, 0x0e100a10, 0x0ff00f7f, "fmrs%c\t%12-15r, %y2"},
+ {FPU_VFP_EXT_V1xD, 0x0eb50a40, 0x0fbf0f70, "fcmp%7'ezs%c\t%y1"},
+ {FPU_VFP_EXT_V1, 0x0eb50b40, 0x0fbf0f70, "fcmp%7'ezd%c\t%z1"},
+ {FPU_VFP_EXT_V1xD, 0x0eb00a40, 0x0fbf0fd0, "fcpys%c\t%y1, %y0"},
+ {FPU_VFP_EXT_V1xD, 0x0eb00ac0, 0x0fbf0fd0, "fabss%c\t%y1, %y0"},
+ {FPU_VFP_EXT_V1, 0x0eb00b40, 0x0fbf0fd0, "fcpyd%c\t%z1, %z0"},
+ {FPU_VFP_EXT_V1, 0x0eb00bc0, 0x0fbf0fd0, "fabsd%c\t%z1, %z0"},
+ {FPU_VFP_EXT_V1xD, 0x0eb10a40, 0x0fbf0fd0, "fnegs%c\t%y1, %y0"},
+ {FPU_VFP_EXT_V1xD, 0x0eb10ac0, 0x0fbf0fd0, "fsqrts%c\t%y1, %y0"},
+ {FPU_VFP_EXT_V1, 0x0eb10b40, 0x0fbf0fd0, "fnegd%c\t%z1, %z0"},
+ {FPU_VFP_EXT_V1, 0x0eb10bc0, 0x0fbf0fd0, "fsqrtd%c\t%z1, %z0"},
+ {FPU_VFP_EXT_V1, 0x0eb70ac0, 0x0fbf0fd0, "fcvtds%c\t%z1, %y0"},
+ {FPU_VFP_EXT_V1, 0x0eb70bc0, 0x0fbf0fd0, "fcvtsd%c\t%y1, %z0"},
+ {FPU_VFP_EXT_V1xD, 0x0eb80a40, 0x0fbf0fd0, "fuitos%c\t%y1, %y0"},
+ {FPU_VFP_EXT_V1xD, 0x0eb80ac0, 0x0fbf0fd0, "fsitos%c\t%y1, %y0"},
+ {FPU_VFP_EXT_V1, 0x0eb80b40, 0x0fbf0fd0, "fuitod%c\t%z1, %y0"},
+ {FPU_VFP_EXT_V1, 0x0eb80bc0, 0x0fbf0fd0, "fsitod%c\t%z1, %y0"},
+ {FPU_VFP_EXT_V1xD, 0x0eb40a40, 0x0fbf0f50, "fcmp%7'es%c\t%y1, %y0"},
+ {FPU_VFP_EXT_V1, 0x0eb40b40, 0x0fbf0f50, "fcmp%7'ed%c\t%z1, %z0"},
+ {FPU_VFP_EXT_V3, 0x0eba0a40, 0x0fbe0f50, "f%16?us%7?lhtos%c\t%y1, #%5,0-3k"},
+ {FPU_VFP_EXT_V3, 0x0eba0b40, 0x0fbe0f50, "f%16?us%7?lhtod%c\t%z1, #%5,0-3k"},
+ {FPU_VFP_EXT_V1xD, 0x0ebc0a40, 0x0fbe0f50, "fto%16?sui%7'zs%c\t%y1, %y0"},
+ {FPU_VFP_EXT_V1, 0x0ebc0b40, 0x0fbe0f50, "fto%16?sui%7'zd%c\t%y1, %z0"},
+ {FPU_VFP_EXT_V3, 0x0ebe0a40, 0x0fbe0f50, "fto%16?us%7?lhs%c\t%y1, #%5,0-3k"},
+ {FPU_VFP_EXT_V3, 0x0ebe0b40, 0x0fbe0f50, "fto%16?us%7?lhd%c\t%z1, #%5,0-3k"},
+ {FPU_VFP_EXT_V1, 0x0c500b10, 0x0fb00ff0, "fmrrd%c\t%12-15r, %16-19r, %z0"},
+ {FPU_VFP_EXT_V3, 0x0eb00a00, 0x0fb00ff0, "fconsts%c\t%y1, #%0-3,16-19d"},
+ {FPU_VFP_EXT_V3, 0x0eb00b00, 0x0fb00ff0, "fconstd%c\t%z1, #%0-3,16-19d"},
+ {FPU_VFP_EXT_V2, 0x0c400a10, 0x0ff00fd0, "fmsrr%c\t%y4, %12-15r, %16-19r"},
+ {FPU_VFP_EXT_V2, 0x0c400b10, 0x0ff00fd0, "fmdrr%c\t%z0, %12-15r, %16-19r"},
+ {FPU_VFP_EXT_V2, 0x0c500a10, 0x0ff00fd0, "fmrrs%c\t%12-15r, %16-19r, %y4"},
+ {FPU_VFP_EXT_V1xD, 0x0e000a00, 0x0fb00f50, "fmacs%c\t%y1, %y2, %y0"},
+ {FPU_VFP_EXT_V1xD, 0x0e000a40, 0x0fb00f50, "fnmacs%c\t%y1, %y2, %y0"},
+ {FPU_VFP_EXT_V1, 0x0e000b00, 0x0fb00f50, "fmacd%c\t%z1, %z2, %z0"},
+ {FPU_VFP_EXT_V1, 0x0e000b40, 0x0fb00f50, "fnmacd%c\t%z1, %z2, %z0"},
+ {FPU_VFP_EXT_V1xD, 0x0e100a00, 0x0fb00f50, "fmscs%c\t%y1, %y2, %y0"},
+ {FPU_VFP_EXT_V1xD, 0x0e100a40, 0x0fb00f50, "fnmscs%c\t%y1, %y2, %y0"},
+ {FPU_VFP_EXT_V1, 0x0e100b00, 0x0fb00f50, "fmscd%c\t%z1, %z2, %z0"},
+ {FPU_VFP_EXT_V1, 0x0e100b40, 0x0fb00f50, "fnmscd%c\t%z1, %z2, %z0"},
+ {FPU_VFP_EXT_V1xD, 0x0e200a00, 0x0fb00f50, "fmuls%c\t%y1, %y2, %y0"},
+ {FPU_VFP_EXT_V1xD, 0x0e200a40, 0x0fb00f50, "fnmuls%c\t%y1, %y2, %y0"},
+ {FPU_VFP_EXT_V1, 0x0e200b00, 0x0fb00f50, "fmuld%c\t%z1, %z2, %z0"},
+ {FPU_VFP_EXT_V1, 0x0e200b40, 0x0fb00f50, "fnmuld%c\t%z1, %z2, %z0"},
+ {FPU_VFP_EXT_V1xD, 0x0e300a00, 0x0fb00f50, "fadds%c\t%y1, %y2, %y0"},
+ {FPU_VFP_EXT_V1xD, 0x0e300a40, 0x0fb00f50, "fsubs%c\t%y1, %y2, %y0"},
+ {FPU_VFP_EXT_V1, 0x0e300b00, 0x0fb00f50, "faddd%c\t%z1, %z2, %z0"},
+ {FPU_VFP_EXT_V1, 0x0e300b40, 0x0fb00f50, "fsubd%c\t%z1, %z2, %z0"},
+ {FPU_VFP_EXT_V1xD, 0x0e800a00, 0x0fb00f50, "fdivs%c\t%y1, %y2, %y0"},
+ {FPU_VFP_EXT_V1, 0x0e800b00, 0x0fb00f50, "fdivd%c\t%z1, %z2, %z0"},
+ {FPU_VFP_EXT_V1xD, 0x0d200a00, 0x0fb00f00, "fstmdbs%c\t%16-19r!, %y3"},
+ {FPU_VFP_EXT_V1xD, 0x0d200b00, 0x0fb00f00, "fstmdb%0?xd%c\t%16-19r!, %z3"},
+ {FPU_VFP_EXT_V1xD, 0x0d300a00, 0x0fb00f00, "fldmdbs%c\t%16-19r!, %y3"},
+ {FPU_VFP_EXT_V1xD, 0x0d300b00, 0x0fb00f00, "fldmdb%0?xd%c\t%16-19r!, %z3"},
+ {FPU_VFP_EXT_V1xD, 0x0d000a00, 0x0f300f00, "fsts%c\t%y1, %A"},
+ {FPU_VFP_EXT_V1, 0x0d000b00, 0x0f300f00, "fstd%c\t%z1, %A"},
+ {FPU_VFP_EXT_V1xD, 0x0d100a00, 0x0f300f00, "flds%c\t%y1, %A"},
+ {FPU_VFP_EXT_V1, 0x0d100b00, 0x0f300f00, "fldd%c\t%z1, %A"},
+ {FPU_VFP_EXT_V1xD, 0x0c800a00, 0x0f900f00, "fstmias%c\t%16-19r%21'!, %y3"},
+ {FPU_VFP_EXT_V1xD, 0x0c800b00, 0x0f900f00, "fstmia%0?xd%c\t%16-19r%21'!, %z3"},
+ {FPU_VFP_EXT_V1xD, 0x0c900a00, 0x0f900f00, "fldmias%c\t%16-19r%21'!, %y3"},
+ {FPU_VFP_EXT_V1xD, 0x0c900b00, 0x0f900f00, "fldmia%0?xd%c\t%16-19r%21'!, %z3"},
+
+ /* Cirrus coprocessor instructions. */
+ {ARM_CEXT_MAVERICK, 0x0d100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
+ {ARM_CEXT_MAVERICK, 0x0c100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
+ {ARM_CEXT_MAVERICK, 0x0d500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
+ {ARM_CEXT_MAVERICK, 0x0c500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
+ {ARM_CEXT_MAVERICK, 0x0d100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
+ {ARM_CEXT_MAVERICK, 0x0c100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
+ {ARM_CEXT_MAVERICK, 0x0d500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"},
+ {ARM_CEXT_MAVERICK, 0x0c500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"},
+ {ARM_CEXT_MAVERICK, 0x0d000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"},
+ {ARM_CEXT_MAVERICK, 0x0c000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"},
+ {ARM_CEXT_MAVERICK, 0x0d400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"},
+ {ARM_CEXT_MAVERICK, 0x0c400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"},
+ {ARM_CEXT_MAVERICK, 0x0d000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"},
+ {ARM_CEXT_MAVERICK, 0x0c000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"},
+ {ARM_CEXT_MAVERICK, 0x0d400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"},
+ {ARM_CEXT_MAVERICK, 0x0c400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"},
+ {ARM_CEXT_MAVERICK, 0x0e000450, 0x0ff00ff0, "cfmvsr%c\tmvf%16-19d, %12-15r"},
+ {ARM_CEXT_MAVERICK, 0x0e100450, 0x0ff00ff0, "cfmvrs%c\t%12-15r, mvf%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e000410, 0x0ff00ff0, "cfmvdlr%c\tmvd%16-19d, %12-15r"},
+ {ARM_CEXT_MAVERICK, 0x0e100410, 0x0ff00ff0, "cfmvrdl%c\t%12-15r, mvd%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e000430, 0x0ff00ff0, "cfmvdhr%c\tmvd%16-19d, %12-15r"},
+ {ARM_CEXT_MAVERICK, 0x0e100430, 0x0ff00fff, "cfmvrdh%c\t%12-15r, mvd%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e000510, 0x0ff00fff, "cfmv64lr%c\tmvdx%16-19d, %12-15r"},
+ {ARM_CEXT_MAVERICK, 0x0e100510, 0x0ff00fff, "cfmvr64l%c\t%12-15r, mvdx%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e000530, 0x0ff00fff, "cfmv64hr%c\tmvdx%16-19d, %12-15r"},
+ {ARM_CEXT_MAVERICK, 0x0e100530, 0x0ff00fff, "cfmvr64h%c\t%12-15r, mvdx%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e200440, 0x0ff00fff, "cfmval32%c\tmvax%12-15d, mvfx%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e100440, 0x0ff00fff, "cfmv32al%c\tmvfx%12-15d, mvax%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e200460, 0x0ff00fff, "cfmvam32%c\tmvax%12-15d, mvfx%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e100460, 0x0ff00fff, "cfmv32am%c\tmvfx%12-15d, mvax%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e200480, 0x0ff00fff, "cfmvah32%c\tmvax%12-15d, mvfx%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e100480, 0x0ff00fff, "cfmv32ah%c\tmvfx%12-15d, mvax%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e2004a0, 0x0ff00fff, "cfmva32%c\tmvax%12-15d, mvfx%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e1004a0, 0x0ff00fff, "cfmv32a%c\tmvfx%12-15d, mvax%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e2004c0, 0x0ff00fff, "cfmva64%c\tmvax%12-15d, mvdx%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e1004c0, 0x0ff00fff, "cfmv64a%c\tmvdx%12-15d, mvax%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e2004e0, 0x0fff0fff, "cfmvsc32%c\tdspsc, mvdx%12-15d"},
+ {ARM_CEXT_MAVERICK, 0x0e1004e0, 0x0fff0fff, "cfmv32sc%c\tmvdx%12-15d, dspsc"},
+ {ARM_CEXT_MAVERICK, 0x0e000400, 0x0ff00fff, "cfcpys%c\tmvf%12-15d, mvf%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e000420, 0x0ff00fff, "cfcpyd%c\tmvd%12-15d, mvd%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e000460, 0x0ff00fff, "cfcvtsd%c\tmvd%12-15d, mvf%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e000440, 0x0ff00fff, "cfcvtds%c\tmvf%12-15d, mvd%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e000480, 0x0ff00fff, "cfcvt32s%c\tmvf%12-15d, mvfx%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e0004a0, 0x0ff00fff, "cfcvt32d%c\tmvd%12-15d, mvfx%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e0004c0, 0x0ff00fff, "cfcvt64s%c\tmvf%12-15d, mvdx%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e0004e0, 0x0ff00fff, "cfcvt64d%c\tmvd%12-15d, mvdx%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e100580, 0x0ff00fff, "cfcvts32%c\tmvfx%12-15d, mvf%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e1005a0, 0x0ff00fff, "cfcvtd32%c\tmvfx%12-15d, mvd%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e1005c0, 0x0ff00fff, "cftruncs32%c\tmvfx%12-15d, mvf%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e1005e0, 0x0ff00fff, "cftruncd32%c\tmvfx%12-15d, mvd%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e000550, 0x0ff00ff0, "cfrshl32%c\tmvfx%16-19d, mvfx%0-3d, %12-15r"},
+ {ARM_CEXT_MAVERICK, 0x0e000570, 0x0ff00ff0, "cfrshl64%c\tmvdx%16-19d, mvdx%0-3d, %12-15r"},
+ {ARM_CEXT_MAVERICK, 0x0e000500, 0x0ff00f10, "cfsh32%c\tmvfx%12-15d, mvfx%16-19d, #%I"},
+ {ARM_CEXT_MAVERICK, 0x0e200500, 0x0ff00f10, "cfsh64%c\tmvdx%12-15d, mvdx%16-19d, #%I"},
+ {ARM_CEXT_MAVERICK, 0x0e100490, 0x0ff00ff0, "cfcmps%c\t%12-15r, mvf%16-19d, mvf%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e1004b0, 0x0ff00ff0, "cfcmpd%c\t%12-15r, mvd%16-19d, mvd%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e100590, 0x0ff00ff0, "cfcmp32%c\t%12-15r, mvfx%16-19d, mvfx%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e1005b0, 0x0ff00ff0, "cfcmp64%c\t%12-15r, mvdx%16-19d, mvdx%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e300400, 0x0ff00fff, "cfabss%c\tmvf%12-15d, mvf%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e300420, 0x0ff00fff, "cfabsd%c\tmvd%12-15d, mvd%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e300440, 0x0ff00fff, "cfnegs%c\tmvf%12-15d, mvf%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e300460, 0x0ff00fff, "cfnegd%c\tmvd%12-15d, mvd%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e300480, 0x0ff00ff0, "cfadds%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e3004a0, 0x0ff00ff0, "cfaddd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e3004c0, 0x0ff00ff0, "cfsubs%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e3004e0, 0x0ff00ff0, "cfsubd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e100400, 0x0ff00ff0, "cfmuls%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e100420, 0x0ff00ff0, "cfmuld%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e300500, 0x0ff00fff, "cfabs32%c\tmvfx%12-15d, mvfx%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e300520, 0x0ff00fff, "cfabs64%c\tmvdx%12-15d, mvdx%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e300540, 0x0ff00fff, "cfneg32%c\tmvfx%12-15d, mvfx%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e300560, 0x0ff00fff, "cfneg64%c\tmvdx%12-15d, mvdx%16-19d"},
+ {ARM_CEXT_MAVERICK, 0x0e300580, 0x0ff00ff0, "cfadd32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e3005a0, 0x0ff00ff0, "cfadd64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e3005c0, 0x0ff00ff0, "cfsub32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e3005e0, 0x0ff00ff0, "cfsub64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e100500, 0x0ff00ff0, "cfmul32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e100520, 0x0ff00ff0, "cfmul64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e100540, 0x0ff00ff0, "cfmac32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e100560, 0x0ff00ff0, "cfmsc32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e000600, 0x0ff00f10, "cfmadd32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e100600, 0x0ff00f10, "cfmsub32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e200600, 0x0ff00f10, "cfmadda32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"},
+ {ARM_CEXT_MAVERICK, 0x0e300600, 0x0ff00f10, "cfmsuba32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"},
+
+ /* Generic coprocessor instructions */
+ {ARM_EXT_V2, 0x0c400000, 0x0ff00000, "mcrr%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
+ {ARM_EXT_V2, 0x0c500000, 0x0ff00000, "mrrc%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
+ {ARM_EXT_V2, 0x0e000000, 0x0f000010, "cdp%c\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"},
+ {ARM_EXT_V2, 0x0e100010, 0x0f100010, "mrc%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
+ {ARM_EXT_V2, 0x0e000010, 0x0f100010, "mcr%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
+ {ARM_EXT_V2, 0x0c000000, 0x0e100000, "stc%22'l%c\t%8-11d, cr%12-15d, %A"},
+ {ARM_EXT_V2, 0x0c100000, 0x0e100000, "ldc%22'l%c\t%8-11d, cr%12-15d, %A"},
+
+ /* V6 coprocessor instructions */
+ {ARM_EXT_V6, 0xfc500000, 0xfff00000, "mrrc2%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
+ {ARM_EXT_V6, 0xfc400000, 0xfff00000, "mcrr2%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
+
+ /* V5 coprocessor instructions */
+ {ARM_EXT_V5, 0xfc100000, 0xfe100000, "ldc2%22'l%c\t%8-11d, cr%12-15d, %A"},
+ {ARM_EXT_V5, 0xfc000000, 0xfe100000, "stc2%22'l%c\t%8-11d, cr%12-15d, %A"},
+ {ARM_EXT_V5, 0xfe000000, 0xff000010, "cdp2%c\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"},
+ {ARM_EXT_V5, 0xfe000010, 0xff100010, "mcr2%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
+ {ARM_EXT_V5, 0xfe100010, 0xff100010, "mrc2%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
+
+ {0, 0, 0, 0}
+};
+
+/* Neon opcode table: This does not encode the top byte -- that is
+ checked by the print_insn_neon routine, as it depends on whether we are
+ doing thumb32 or arm32 disassembly. */
+
+/* print_insn_neon recognizes the following format control codes:
+
+ %% %
+
+ %c print condition code
+ %A print v{st,ld}[1234] operands
+ %B print v{st,ld}[1234] any one operands
+ %C print v{st,ld}[1234] single->all operands
+ %D print scalar
+ %E print vmov, vmvn, vorr, vbic encoded constant
+ %F print vtbl,vtbx register list
+
+ %<bitfield>r print as an ARM register
+ %<bitfield>d print the bitfield in decimal
+ %<bitfield>e print the 2^N - bitfield in decimal
+ %<bitfield>D print as a NEON D register
+ %<bitfield>Q print as a NEON Q register
+ %<bitfield>R print as a NEON D or Q register
+ %<bitfield>Sn print byte scaled width limited by n
+ %<bitfield>Tn print short scaled width limited by n
+ %<bitfield>Un print long scaled width limited by n
+
+ %<bitfield>'c print specified char iff bitfield is all ones
+ %<bitfield>`c print specified char iff bitfield is all zeroes
+ %<bitfield>?ab... select from array of values in big endian order */
+
+static const struct opcode32 neon_opcodes[] =
+{
+ /* Extract */
+ {FPU_NEON_EXT_V1, 0xf2b00840, 0xffb00850, "vext%c.8\t%12-15,22R, %16-19,7R, %0-3,5R, #%8-11d"},
+ {FPU_NEON_EXT_V1, 0xf2b00000, 0xffb00810, "vext%c.8\t%12-15,22R, %16-19,7R, %0-3,5R, #%8-11d"},
+
+ /* Move data element to all lanes */
+ {FPU_NEON_EXT_V1, 0xf3b40c00, 0xffb70f90, "vdup%c.32\t%12-15,22R, %0-3,5D[%19d]"},
+ {FPU_NEON_EXT_V1, 0xf3b20c00, 0xffb30f90, "vdup%c.16\t%12-15,22R, %0-3,5D[%18-19d]"},
+ {FPU_NEON_EXT_V1, 0xf3b10c00, 0xffb10f90, "vdup%c.8\t%12-15,22R, %0-3,5D[%17-19d]"},
+
+ /* Table lookup */
+ {FPU_NEON_EXT_V1, 0xf3b00800, 0xffb00c50, "vtbl%c.8\t%12-15,22D, %F, %0-3,5D"},
+ {FPU_NEON_EXT_V1, 0xf3b00840, 0xffb00c50, "vtbx%c.8\t%12-15,22D, %F, %0-3,5D"},
+
+ /* Two registers, miscellaneous */
+ {FPU_NEON_EXT_V1, 0xf2880a10, 0xfebf0fd0, "vmovl%c.%24?us8\t%12-15,22Q, %0-3,5D"},
+ {FPU_NEON_EXT_V1, 0xf2900a10, 0xfebf0fd0, "vmovl%c.%24?us16\t%12-15,22Q, %0-3,5D"},
+ {FPU_NEON_EXT_V1, 0xf2a00a10, 0xfebf0fd0, "vmovl%c.%24?us32\t%12-15,22Q, %0-3,5D"},
+ {FPU_NEON_EXT_V1, 0xf3b00500, 0xffbf0f90, "vcnt%c.8\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b00580, 0xffbf0f90, "vmvn%c\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b20000, 0xffbf0f90, "vswp%c\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b20200, 0xffb30fd0, "vmovn%c.i%18-19T2\t%12-15,22D, %0-3,5Q"},
+ {FPU_NEON_EXT_V1, 0xf3b20240, 0xffb30fd0, "vqmovun%c.s%18-19T2\t%12-15,22D, %0-3,5Q"},
+ {FPU_NEON_EXT_V1, 0xf3b20280, 0xffb30fd0, "vqmovn%c.s%18-19T2\t%12-15,22D, %0-3,5Q"},
+ {FPU_NEON_EXT_V1, 0xf3b202c0, 0xffb30fd0, "vqmovn%c.u%18-19T2\t%12-15,22D, %0-3,5Q"},
+ {FPU_NEON_EXT_V1, 0xf3b20300, 0xffb30fd0, "vshll%c.i%18-19S2\t%12-15,22Q, %0-3,5D, #%18-19S2"},
+ {FPU_NEON_EXT_V1, 0xf3bb0400, 0xffbf0e90, "vrecpe%c.%8?fu%18-19S2\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3bb0480, 0xffbf0e90, "vrsqrte%c.%8?fu%18-19S2\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b00000, 0xffb30f90, "vrev64%c.%18-19S2\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b00080, 0xffb30f90, "vrev32%c.%18-19S2\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b00100, 0xffb30f90, "vrev16%c.%18-19S2\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b00400, 0xffb30f90, "vcls%c.s%18-19S2\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b00480, 0xffb30f90, "vclz%c.i%18-19S2\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b00700, 0xffb30f90, "vqabs%c.s%18-19S2\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b00780, 0xffb30f90, "vqneg%c.s%18-19S2\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b20080, 0xffb30f90, "vtrn%c.%18-19S2\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b20100, 0xffb30f90, "vuzp%c.%18-19S2\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b20180, 0xffb30f90, "vzip%c.%18-19S2\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b10000, 0xffb30b90, "vcgt%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R, #0"},
+ {FPU_NEON_EXT_V1, 0xf3b10080, 0xffb30b90, "vcge%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R, #0"},
+ {FPU_NEON_EXT_V1, 0xf3b10100, 0xffb30b90, "vceq%c.%10?fi%18-19S2\t%12-15,22R, %0-3,5R, #0"},
+ {FPU_NEON_EXT_V1, 0xf3b10180, 0xffb30b90, "vcle%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R, #0"},
+ {FPU_NEON_EXT_V1, 0xf3b10200, 0xffb30b90, "vclt%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R, #0"},
+ {FPU_NEON_EXT_V1, 0xf3b10300, 0xffb30b90, "vabs%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b10380, 0xffb30b90, "vneg%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b00200, 0xffb30f10, "vpaddl%c.%7?us%18-19S2\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b00600, 0xffb30f10, "vpadal%c.%7?us%18-19S2\t%12-15,22R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3b30600, 0xffb30e10, "vcvt%c.%7-8?usff%18-19Sa.%7-8?ffus%18-19Sa\t%12-15,22R, %0-3,5R"},
+
+ /* Three registers of the same length */
+ {FPU_NEON_EXT_V1, 0xf2000110, 0xffb00f10, "vand%c\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2100110, 0xffb00f10, "vbic%c\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2200110, 0xffb00f10, "vorr%c\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2300110, 0xffb00f10, "vorn%c\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3000110, 0xffb00f10, "veor%c\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3100110, 0xffb00f10, "vbsl%c\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3200110, 0xffb00f10, "vbit%c\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3300110, 0xffb00f10, "vbif%c\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000d00, 0xffa00f10, "vadd%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000d10, 0xffa00f10, "vmla%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000e00, 0xffa00f10, "vceq%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000f00, 0xffa00f10, "vmax%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000f10, 0xffa00f10, "vrecps%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2200d00, 0xffa00f10, "vsub%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2200d10, 0xffa00f10, "vmls%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2200f00, 0xffa00f10, "vmin%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2200f10, 0xffa00f10, "vrsqrts%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3000d00, 0xffa00f10, "vpadd%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3000d10, 0xffa00f10, "vmul%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3000e00, 0xffa00f10, "vcge%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3000e10, 0xffa00f10, "vacge%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3000f00, 0xffa00f10, "vpmax%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3200d00, 0xffa00f10, "vabd%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3200e00, 0xffa00f10, "vcgt%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3200e10, 0xffa00f10, "vacgt%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3200f00, 0xffa00f10, "vpmin%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000800, 0xff800f10, "vadd%c.i%20-21S3\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000810, 0xff800f10, "vtst%c.%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000900, 0xff800f10, "vmla%c.i%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000b00, 0xff800f10, "vqdmulh%c.s%20-21S6\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000b10, 0xff800f10, "vpadd%c.i%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3000800, 0xff800f10, "vsub%c.i%20-21S3\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3000810, 0xff800f10, "vceq%c.i%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3000900, 0xff800f10, "vmls%c.i%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf3000b00, 0xff800f10, "vqrdmulh%c.s%20-21S6\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000000, 0xfe800f10, "vhadd%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000010, 0xfe800f10, "vqadd%c.%24?us%20-21S3\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000100, 0xfe800f10, "vrhadd%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000200, 0xfe800f10, "vhsub%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000210, 0xfe800f10, "vqsub%c.%24?us%20-21S3\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000300, 0xfe800f10, "vcgt%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000310, 0xfe800f10, "vcge%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000400, 0xfe800f10, "vshl%c.%24?us%20-21S3\t%12-15,22R, %0-3,5R, %16-19,7R"},
+ {FPU_NEON_EXT_V1, 0xf2000410, 0xfe800f10, "vqshl%c.%24?us%20-21S3\t%12-15,22R, %0-3,5R, %16-19,7R"},
+ {FPU_NEON_EXT_V1, 0xf2000500, 0xfe800f10, "vrshl%c.%24?us%20-21S3\t%12-15,22R, %0-3,5R, %16-19,7R"},
+ {FPU_NEON_EXT_V1, 0xf2000510, 0xfe800f10, "vqrshl%c.%24?us%20-21S3\t%12-15,22R, %0-3,5R, %16-19,7R"},
+ {FPU_NEON_EXT_V1, 0xf2000600, 0xfe800f10, "vmax%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000610, 0xfe800f10, "vmin%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000700, 0xfe800f10, "vabd%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000710, 0xfe800f10, "vaba%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000910, 0xfe800f10, "vmul%c.%24?pi%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000a00, 0xfe800f10, "vpmax%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"},
+ {FPU_NEON_EXT_V1, 0xf2000a10, 0xfe800f10, "vpmin%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"},
+
+ /* One register and an immediate value */
+ {FPU_NEON_EXT_V1, 0xf2800e10, 0xfeb80fb0, "vmov%c.i8\t%12-15,22R, %E"},
+ {FPU_NEON_EXT_V1, 0xf2800e30, 0xfeb80fb0, "vmov%c.i64\t%12-15,22R, %E"},
+ {FPU_NEON_EXT_V1, 0xf2800f10, 0xfeb80fb0, "vmov%c.f32\t%12-15,22R, %E"},
+ {FPU_NEON_EXT_V1, 0xf2800810, 0xfeb80db0, "vmov%c.i16\t%12-15,22R, %E"},
+ {FPU_NEON_EXT_V1, 0xf2800830, 0xfeb80db0, "vmvn%c.i16\t%12-15,22R, %E"},
+ {FPU_NEON_EXT_V1, 0xf2800910, 0xfeb80db0, "vorr%c.i16\t%12-15,22R, %E"},
+ {FPU_NEON_EXT_V1, 0xf2800930, 0xfeb80db0, "vbic%c.i16\t%12-15,22R, %E"},
+ {FPU_NEON_EXT_V1, 0xf2800c10, 0xfeb80eb0, "vmov%c.i32\t%12-15,22R, %E"},
+ {FPU_NEON_EXT_V1, 0xf2800c30, 0xfeb80eb0, "vmvn%c.i32\t%12-15,22R, %E"},
+ {FPU_NEON_EXT_V1, 0xf2800110, 0xfeb809b0, "vorr%c.i32\t%12-15,22R, %E"},
+ {FPU_NEON_EXT_V1, 0xf2800130, 0xfeb809b0, "vbic%c.i32\t%12-15,22R, %E"},
+ {FPU_NEON_EXT_V1, 0xf2800010, 0xfeb808b0, "vmov%c.i32\t%12-15,22R, %E"},
+ {FPU_NEON_EXT_V1, 0xf2800030, 0xfeb808b0, "vmvn%c.i32\t%12-15,22R, %E"},
+
+ /* Two registers and a shift amount */
+ {FPU_NEON_EXT_V1, 0xf2880810, 0xffb80fd0, "vshrn%c.i16\t%12-15,22D, %0-3,5Q, #%16-18e"},
+ {FPU_NEON_EXT_V1, 0xf2880850, 0xffb80fd0, "vrshrn%c.i16\t%12-15,22D, %0-3,5Q, #%16-18e"},
+ {FPU_NEON_EXT_V1, 0xf2880810, 0xfeb80fd0, "vqshrun%c.s16\t%12-15,22D, %0-3,5Q, #%16-18e"},
+ {FPU_NEON_EXT_V1, 0xf2880850, 0xfeb80fd0, "vqrshrun%c.s16\t%12-15,22D, %0-3,5Q, #%16-18e"},
+ {FPU_NEON_EXT_V1, 0xf2880910, 0xfeb80fd0, "vqshrn%c.%24?us16\t%12-15,22D, %0-3,5Q, #%16-18e"},
+ {FPU_NEON_EXT_V1, 0xf2880950, 0xfeb80fd0, "vqrshrn%c.%24?us16\t%12-15,22D, %0-3,5Q, #%16-18e"},
+ {FPU_NEON_EXT_V1, 0xf2880a10, 0xfeb80fd0, "vshll%c.%24?us8\t%12-15,22D, %0-3,5Q, #%16-18d"},
+ {FPU_NEON_EXT_V1, 0xf2900810, 0xffb00fd0, "vshrn%c.i32\t%12-15,22D, %0-3,5Q, #%16-19e"},
+ {FPU_NEON_EXT_V1, 0xf2900850, 0xffb00fd0, "vrshrn%c.i32\t%12-15,22D, %0-3,5Q, #%16-19e"},
+ {FPU_NEON_EXT_V1, 0xf2880510, 0xffb80f90, "vshl%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18d"},
+ {FPU_NEON_EXT_V1, 0xf3880410, 0xffb80f90, "vsri%c.8\t%12-15,22R, %0-3,5R, #%16-18e"},
+ {FPU_NEON_EXT_V1, 0xf3880510, 0xffb80f90, "vsli%c.8\t%12-15,22R, %0-3,5R, #%16-18d"},
+ {FPU_NEON_EXT_V1, 0xf3880610, 0xffb80f90, "vqshlu%c.s8\t%12-15,22R, %0-3,5R, #%16-18d"},
+ {FPU_NEON_EXT_V1, 0xf2900810, 0xfeb00fd0, "vqshrun%c.s32\t%12-15,22D, %0-3,5Q, #%16-19e"},
+ {FPU_NEON_EXT_V1, 0xf2900850, 0xfeb00fd0, "vqrshrun%c.s32\t%12-15,22D, %0-3,5Q, #%16-19e"},
+ {FPU_NEON_EXT_V1, 0xf2900910, 0xfeb00fd0, "vqshrn%c.%24?us32\t%12-15,22D, %0-3,5Q, #%16-19e"},
+ {FPU_NEON_EXT_V1, 0xf2900950, 0xfeb00fd0, "vqrshrn%c.%24?us32\t%12-15,22D, %0-3,5Q, #%16-19e"},
+ {FPU_NEON_EXT_V1, 0xf2900a10, 0xfeb00fd0, "vshll%c.%24?us16\t%12-15,22D, %0-3,5Q, #%16-19d"},
+ {FPU_NEON_EXT_V1, 0xf2880010, 0xfeb80f90, "vshr%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18e"},
+ {FPU_NEON_EXT_V1, 0xf2880110, 0xfeb80f90, "vsra%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18e"},
+ {FPU_NEON_EXT_V1, 0xf2880210, 0xfeb80f90, "vrshr%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18e"},
+ {FPU_NEON_EXT_V1, 0xf2880310, 0xfeb80f90, "vrsra%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18e"},
+ {FPU_NEON_EXT_V1, 0xf2880710, 0xfeb80f90, "vqshl%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18d"},
+ {FPU_NEON_EXT_V1, 0xf2a00810, 0xffa00fd0, "vshrn%c.i64\t%12-15,22D, %0-3,5Q, #%16-20e"},
+ {FPU_NEON_EXT_V1, 0xf2a00850, 0xffa00fd0, "vrshrn%c.i64\t%12-15,22D, %0-3,5Q, #%16-20e"},
+ {FPU_NEON_EXT_V1, 0xf2900510, 0xffb00f90, "vshl%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19d"},
+ {FPU_NEON_EXT_V1, 0xf3900410, 0xffb00f90, "vsri%c.16\t%12-15,22R, %0-3,5R, #%16-19e"},
+ {FPU_NEON_EXT_V1, 0xf3900510, 0xffb00f90, "vsli%c.16\t%12-15,22R, %0-3,5R, #%16-19d"},
+ {FPU_NEON_EXT_V1, 0xf3900610, 0xffb00f90, "vqshlu%c.s16\t%12-15,22R, %0-3,5R, #%16-19d"},
+ {FPU_NEON_EXT_V1, 0xf2a00a10, 0xfea00fd0, "vshll%c.%24?us32\t%12-15,22D, %0-3,5Q, #%16-20d"},
+ {FPU_NEON_EXT_V1, 0xf2900010, 0xfeb00f90, "vshr%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19e"},
+ {FPU_NEON_EXT_V1, 0xf2900110, 0xfeb00f90, "vsra%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19e"},
+ {FPU_NEON_EXT_V1, 0xf2900210, 0xfeb00f90, "vrshr%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19e"},
+ {FPU_NEON_EXT_V1, 0xf2900310, 0xfeb00f90, "vrsra%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19e"},
+ {FPU_NEON_EXT_V1, 0xf2900710, 0xfeb00f90, "vqshl%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19d"},
+ {FPU_NEON_EXT_V1, 0xf2800810, 0xfec00fd0, "vqshrun%c.s64\t%12-15,22D, %0-3,5Q, #%16-20e"},
+ {FPU_NEON_EXT_V1, 0xf2800850, 0xfec00fd0, "vqrshrun%c.s64\t%12-15,22D, %0-3,5Q, #%16-20e"},
+ {FPU_NEON_EXT_V1, 0xf2800910, 0xfec00fd0, "vqshrn%c.%24?us64\t%12-15,22D, %0-3,5Q, #%16-20e"},
+ {FPU_NEON_EXT_V1, 0xf2800950, 0xfec00fd0, "vqrshrn%c.%24?us64\t%12-15,22D, %0-3,5Q, #%16-20e"},
+ {FPU_NEON_EXT_V1, 0xf2a00510, 0xffa00f90, "vshl%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20d"},
+ {FPU_NEON_EXT_V1, 0xf3a00410, 0xffa00f90, "vsri%c.32\t%12-15,22R, %0-3,5R, #%16-20e"},
+ {FPU_NEON_EXT_V1, 0xf3a00510, 0xffa00f90, "vsli%c.32\t%12-15,22R, %0-3,5R, #%16-20d"},
+ {FPU_NEON_EXT_V1, 0xf3a00610, 0xffa00f90, "vqshlu%c.s32\t%12-15,22R, %0-3,5R, #%16-20d"},
+ {FPU_NEON_EXT_V1, 0xf2a00010, 0xfea00f90, "vshr%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20e"},
+ {FPU_NEON_EXT_V1, 0xf2a00110, 0xfea00f90, "vsra%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20e"},
+ {FPU_NEON_EXT_V1, 0xf2a00210, 0xfea00f90, "vrshr%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20e"},
+ {FPU_NEON_EXT_V1, 0xf2a00310, 0xfea00f90, "vrsra%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20e"},
+ {FPU_NEON_EXT_V1, 0xf2a00710, 0xfea00f90, "vqshl%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20d"},
+ {FPU_NEON_EXT_V1, 0xf2800590, 0xff800f90, "vshl%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21d"},
+ {FPU_NEON_EXT_V1, 0xf3800490, 0xff800f90, "vsri%c.64\t%12-15,22R, %0-3,5R, #%16-21e"},
+ {FPU_NEON_EXT_V1, 0xf3800590, 0xff800f90, "vsli%c.64\t%12-15,22R, %0-3,5R, #%16-21d"},
+ {FPU_NEON_EXT_V1, 0xf3800690, 0xff800f90, "vqshlu%c.s64\t%12-15,22R, %0-3,5R, #%16-21d"},
+ {FPU_NEON_EXT_V1, 0xf2800090, 0xfe800f90, "vshr%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21e"},
+ {FPU_NEON_EXT_V1, 0xf2800190, 0xfe800f90, "vsra%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21e"},
+ {FPU_NEON_EXT_V1, 0xf2800290, 0xfe800f90, "vrshr%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21e"},
+ {FPU_NEON_EXT_V1, 0xf2800390, 0xfe800f90, "vrsra%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21e"},
+ {FPU_NEON_EXT_V1, 0xf2800790, 0xfe800f90, "vqshl%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21d"},
+ {FPU_NEON_EXT_V1, 0xf2a00e10, 0xfea00e90, "vcvt%c.%24,8?usff32.%24,8?ffus32\t%12-15,22R, %0-3,5R, #%16-20e"},
+
+ /* Three registers of different lengths */
+ {FPU_NEON_EXT_V1, 0xf2800e00, 0xfea00f50, "vmull%c.p%20S0\t%12-15,22Q, %16-19,7D, %0-3,5D"},
+ {FPU_NEON_EXT_V1, 0xf2800400, 0xff800f50, "vaddhn%c.i%20-21T2\t%12-15,22D, %16-19,7Q, %0-3,5Q"},
+ {FPU_NEON_EXT_V1, 0xf2800600, 0xff800f50, "vsubhn%c.i%20-21T2\t%12-15,22D, %16-19,7Q, %0-3,5Q"},
+ {FPU_NEON_EXT_V1, 0xf2800900, 0xff800f50, "vqdmlal%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %0-3,5D"},
+ {FPU_NEON_EXT_V1, 0xf2800b00, 0xff800f50, "vqdmlsl%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %0-3,5D"},
+ {FPU_NEON_EXT_V1, 0xf2800d00, 0xff800f50, "vqdmull%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %0-3,5D"},
+ {FPU_NEON_EXT_V1, 0xf3800400, 0xff800f50, "vraddhn%c.i%20-21T2\t%12-15,22D, %16-19,7Q, %0-3,5Q"},
+ {FPU_NEON_EXT_V1, 0xf3800600, 0xff800f50, "vrsubhn%c.i%20-21T2\t%12-15,22D, %16-19,7Q, %0-3,5Q"},
+ {FPU_NEON_EXT_V1, 0xf2800000, 0xfe800f50, "vaddl%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"},
+ {FPU_NEON_EXT_V1, 0xf2800100, 0xfe800f50, "vaddw%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7Q, %0-3,5D"},
+ {FPU_NEON_EXT_V1, 0xf2800200, 0xfe800f50, "vsubl%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"},
+ {FPU_NEON_EXT_V1, 0xf2800300, 0xfe800f50, "vsubw%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7Q, %0-3,5D"},
+ {FPU_NEON_EXT_V1, 0xf2800500, 0xfe800f50, "vabal%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"},
+ {FPU_NEON_EXT_V1, 0xf2800700, 0xfe800f50, "vabdl%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"},
+ {FPU_NEON_EXT_V1, 0xf2800800, 0xfe800f50, "vmlal%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"},
+ {FPU_NEON_EXT_V1, 0xf2800a00, 0xfe800f50, "vmlsl%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"},
+ {FPU_NEON_EXT_V1, 0xf2800c00, 0xfe800f50, "vmull%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"},
+
+ /* Two registers and a scalar */
+ {FPU_NEON_EXT_V1, 0xf2800040, 0xff800f50, "vmla%c.i%20-21S6\t%12-15,22D, %16-19,7D, %D"},
+ {FPU_NEON_EXT_V1, 0xf2800140, 0xff800f50, "vmla%c.f%20-21Sa\t%12-15,22D, %16-19,7D, %D"},
+ {FPU_NEON_EXT_V1, 0xf2800340, 0xff800f50, "vqdmlal%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %D"},
+ {FPU_NEON_EXT_V1, 0xf2800440, 0xff800f50, "vmls%c.i%20-21S6\t%12-15,22D, %16-19,7D, %D"},
+ {FPU_NEON_EXT_V1, 0xf2800540, 0xff800f50, "vmls%c.f%20-21S6\t%12-15,22D, %16-19,7D, %D"},
+ {FPU_NEON_EXT_V1, 0xf2800740, 0xff800f50, "vqdmlsl%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %D"},
+ {FPU_NEON_EXT_V1, 0xf2800840, 0xff800f50, "vmul%c.i%20-21S6\t%12-15,22D, %16-19,7D, %D"},
+ {FPU_NEON_EXT_V1, 0xf2800940, 0xff800f50, "vmul%c.f%20-21Sa\t%12-15,22D, %16-19,7D, %D"},
+ {FPU_NEON_EXT_V1, 0xf2800b40, 0xff800f50, "vqdmull%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %D"},
+ {FPU_NEON_EXT_V1, 0xf2800c40, 0xff800f50, "vqdmulh%c.s%20-21S6\t%12-15,22D, %16-19,7D, %D"},
+ {FPU_NEON_EXT_V1, 0xf2800d40, 0xff800f50, "vqrdmulh%c.s%20-21S6\t%12-15,22D, %16-19,7D, %D"},
+ {FPU_NEON_EXT_V1, 0xf3800040, 0xff800f50, "vmla%c.i%20-21S6\t%12-15,22Q, %16-19,7Q, %D"},
+ {FPU_NEON_EXT_V1, 0xf3800140, 0xff800f50, "vmla%c.f%20-21Sa\t%12-15,22Q, %16-19,7Q, %D"},
+ {FPU_NEON_EXT_V1, 0xf3800440, 0xff800f50, "vmls%c.i%20-21S6\t%12-15,22Q, %16-19,7Q, %D"},
+ {FPU_NEON_EXT_V1, 0xf3800540, 0xff800f50, "vmls%c.f%20-21Sa\t%12-15,22Q, %16-19,7Q, %D"},
+ {FPU_NEON_EXT_V1, 0xf3800840, 0xff800f50, "vmul%c.i%20-21S6\t%12-15,22Q, %16-19,7Q, %D"},
+ {FPU_NEON_EXT_V1, 0xf3800940, 0xff800f50, "vmul%c.f%20-21Sa\t%12-15,22Q, %16-19,7Q, %D"},
+ {FPU_NEON_EXT_V1, 0xf3800c40, 0xff800f50, "vqdmulh%c.s%20-21S6\t%12-15,22Q, %16-19,7Q, %D"},
+ {FPU_NEON_EXT_V1, 0xf3800d40, 0xff800f50, "vqrdmulh%c.s%20-21S6\t%12-15,22Q, %16-19,7Q, %D"},
+ {FPU_NEON_EXT_V1, 0xf2800240, 0xfe800f50, "vmlal%c.%24?us%20-21S6\t%12-15,22Q, %16-19,7D, %D"},
+ {FPU_NEON_EXT_V1, 0xf2800640, 0xfe800f50, "vmlsl%c.%24?us%20-21S6\t%12-15,22Q, %16-19,7D, %D"},
+ {FPU_NEON_EXT_V1, 0xf2800a40, 0xfe800f50, "vmull%c.%24?us%20-21S6\t%12-15,22Q, %16-19,7D, %D"},
+
+ /* Element and structure load/store */
+ {FPU_NEON_EXT_V1, 0xf4a00fc0, 0xffb00fc0, "vld4%c.32\t%C"},
+ {FPU_NEON_EXT_V1, 0xf4a00c00, 0xffb00f00, "vld1%c.%6-7S2\t%C"},
+ {FPU_NEON_EXT_V1, 0xf4a00d00, 0xffb00f00, "vld2%c.%6-7S2\t%C"},
+ {FPU_NEON_EXT_V1, 0xf4a00e00, 0xffb00f00, "vld3%c.%6-7S2\t%C"},
+ {FPU_NEON_EXT_V1, 0xf4a00f00, 0xffb00f00, "vld4%c.%6-7S2\t%C"},
+ {FPU_NEON_EXT_V1, 0xf4000200, 0xff900f00, "v%21?ls%21?dt1%c.%6-7S3\t%A"},
+ {FPU_NEON_EXT_V1, 0xf4000300, 0xff900f00, "v%21?ls%21?dt2%c.%6-7S2\t%A"},
+ {FPU_NEON_EXT_V1, 0xf4000400, 0xff900f00, "v%21?ls%21?dt3%c.%6-7S2\t%A"},
+ {FPU_NEON_EXT_V1, 0xf4000500, 0xff900f00, "v%21?ls%21?dt3%c.%6-7S2\t%A"},
+ {FPU_NEON_EXT_V1, 0xf4000600, 0xff900f00, "v%21?ls%21?dt1%c.%6-7S3\t%A"},
+ {FPU_NEON_EXT_V1, 0xf4000700, 0xff900f00, "v%21?ls%21?dt1%c.%6-7S3\t%A"},
+ {FPU_NEON_EXT_V1, 0xf4000800, 0xff900f00, "v%21?ls%21?dt2%c.%6-7S2\t%A"},
+ {FPU_NEON_EXT_V1, 0xf4000900, 0xff900f00, "v%21?ls%21?dt2%c.%6-7S2\t%A"},
+ {FPU_NEON_EXT_V1, 0xf4000a00, 0xff900f00, "v%21?ls%21?dt1%c.%6-7S3\t%A"},
+ {FPU_NEON_EXT_V1, 0xf4000000, 0xff900e00, "v%21?ls%21?dt4%c.%6-7S2\t%A"},
+ {FPU_NEON_EXT_V1, 0xf4800000, 0xff900300, "v%21?ls%21?dt1%c.%10-11S2\t%B"},
+ {FPU_NEON_EXT_V1, 0xf4800100, 0xff900300, "v%21?ls%21?dt2%c.%10-11S2\t%B"},
+ {FPU_NEON_EXT_V1, 0xf4800200, 0xff900300, "v%21?ls%21?dt3%c.%10-11S2\t%B"},
+ {FPU_NEON_EXT_V1, 0xf4800300, 0xff900300, "v%21?ls%21?dt4%c.%10-11S2\t%B"},
+
+ {0,0 ,0, 0}
+};
+
+/* Opcode tables: ARM, 16-bit Thumb, 32-bit Thumb. All three are partially
+ ordered: they must be searched linearly from the top to obtain a correct
+ match. */
+
+/* print_insn_arm recognizes the following format control codes:
+
+ %% %
+
+ %a print address for ldr/str instruction
+ %s print address for ldr/str halfword/signextend instruction
+ %b print branch destination
+ %c print condition code (always bits 28-31)
+ %m print register mask for ldm/stm instruction
+ %o print operand2 (immediate or register + shift)
+ %p print 'p' iff bits 12-15 are 15
+ %t print 't' iff bit 21 set and bit 24 clear
+ %B print arm BLX(1) destination
+ %C print the PSR sub type.
+ %U print barrier type.
+ %P print address for pli instruction.
+
+ %<bitfield>r print as an ARM register
+ %<bitfield>d print the bitfield in decimal
+ %<bitfield>W print the bitfield plus one in decimal
+ %<bitfield>x print the bitfield in hex
+ %<bitfield>X print the bitfield as 1 hex digit without leading "0x"
+
+ %<bitfield>'c print specified char iff bitfield is all ones
+ %<bitfield>`c print specified char iff bitfield is all zeroes
+ %<bitfield>?ab... select from array of values in big endian order
+
+ %e print arm SMI operand (bits 0..7,8..19).
+ %E print the LSB and WIDTH fields of a BFI or BFC instruction.
+ %V print the 16-bit immediate field of a MOVT or MOVW instruction. */
+
+static const struct opcode32 arm_opcodes[] =
+{
+ /* ARM instructions. */
+ {ARM_EXT_V1, 0xe1a00000, 0xffffffff, "nop\t\t\t(mov r0,r0)"},
+ {ARM_EXT_V4T | ARM_EXT_V5, 0x012FFF10, 0x0ffffff0, "bx%c\t%0-3r"},
+ {ARM_EXT_V2, 0x00000090, 0x0fe000f0, "mul%20's%c\t%16-19r, %0-3r, %8-11r"},
+ {ARM_EXT_V2, 0x00200090, 0x0fe000f0, "mla%20's%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+ {ARM_EXT_V2S, 0x01000090, 0x0fb00ff0, "swp%22'b%c\t%12-15r, %0-3r, [%16-19r]"},
+ {ARM_EXT_V3M, 0x00800090, 0x0fa000f0, "%22?sumull%20's%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
+ {ARM_EXT_V3M, 0x00a00090, 0x0fa000f0, "%22?sumlal%20's%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
+
+ /* V7 instructions. */
+ {ARM_EXT_V7, 0xf450f000, 0xfd70f000, "pli\t%P"},
+ {ARM_EXT_V7, 0x0320f0f0, 0x0ffffff0, "dbg%c\t#%0-3d"},
+ {ARM_EXT_V7, 0xf57ff050, 0xfffffff0, "dmb\t%U"},
+ {ARM_EXT_V7, 0xf57ff040, 0xfffffff0, "dsb\t%U"},
+ {ARM_EXT_V7, 0xf57ff060, 0xfffffff0, "isb\t%U"},
+
+ /* ARM V6T2 instructions. */
+ {ARM_EXT_V6T2, 0x07c0001f, 0x0fe0007f, "bfc%c\t%12-15r, %E"},
+ {ARM_EXT_V6T2, 0x07c00010, 0x0fe00070, "bfi%c\t%12-15r, %0-3r, %E"},
+ {ARM_EXT_V6T2, 0x00600090, 0x0ff000f0, "mls%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+ {ARM_EXT_V6T2, 0x006000b0, 0x0f7000f0, "strht%c\t%12-15r, %s"},
+ {ARM_EXT_V6T2, 0x00300090, 0x0f300090, "ldr%6's%5?hbt%c\t%12-15r, %s"},
+ {ARM_EXT_V6T2, 0x03000000, 0x0ff00000, "movw%c\t%12-15r, %V"},
+ {ARM_EXT_V6T2, 0x03400000, 0x0ff00000, "movt%c\t%12-15r, %V"},
+ {ARM_EXT_V6T2, 0x06ff0f30, 0x0fff0ff0, "rbit%c\t%12-15r, %0-3r"},
+ {ARM_EXT_V6T2, 0x07a00050, 0x0fa00070, "%22?usbfx%c\t%12-15r, %0-3r, #%7-11d, #%16-20W"},
+
+ /* ARM V6Z instructions. */
+ {ARM_EXT_V6Z, 0x01600070, 0x0ff000f0, "smc%c\t%e"},
+
+ /* ARM V6K instructions. */
+ {ARM_EXT_V6K, 0xf57ff01f, 0xffffffff, "clrex"},
+ {ARM_EXT_V6K, 0x01d00f9f, 0x0ff00fff, "ldrexb%c\t%12-15r, [%16-19r]"},
+ {ARM_EXT_V6K, 0x01b00f9f, 0x0ff00fff, "ldrexd%c\t%12-15r, [%16-19r]"},
+ {ARM_EXT_V6K, 0x01f00f9f, 0x0ff00fff, "ldrexh%c\t%12-15r, [%16-19r]"},
+ {ARM_EXT_V6K, 0x01c00f90, 0x0ff00ff0, "strexb%c\t%12-15r, %0-3r, [%16-19r]"},
+ {ARM_EXT_V6K, 0x01a00f90, 0x0ff00ff0, "strexd%c\t%12-15r, %0-3r, [%16-19r]"},
+ {ARM_EXT_V6K, 0x01e00f90, 0x0ff00ff0, "strexh%c\t%12-15r, %0-3r, [%16-19r]"},
+
+ /* ARM V6K NOP hints. */
+ {ARM_EXT_V6K, 0x0320f001, 0x0fffffff, "yield%c"},
+ {ARM_EXT_V6K, 0x0320f002, 0x0fffffff, "wfe%c"},
+ {ARM_EXT_V6K, 0x0320f003, 0x0fffffff, "wfi%c"},
+ {ARM_EXT_V6K, 0x0320f004, 0x0fffffff, "sev%c"},
+ {ARM_EXT_V6K, 0x0320f000, 0x0fffff00, "nop%c\t{%0-7d}"},
+
+ /* ARM V6 instructions. */
+ {ARM_EXT_V6, 0xf1080000, 0xfffffe3f, "cpsie\t%8'a%7'i%6'f"},
+ {ARM_EXT_V6, 0xf10a0000, 0xfffffe20, "cpsie\t%8'a%7'i%6'f,#%0-4d"},
+ {ARM_EXT_V6, 0xf10C0000, 0xfffffe3f, "cpsid\t%8'a%7'i%6'f"},
+ {ARM_EXT_V6, 0xf10e0000, 0xfffffe20, "cpsid\t%8'a%7'i%6'f,#%0-4d"},
+ {ARM_EXT_V6, 0xf1000000, 0xfff1fe20, "cps\t#%0-4d"},
+ {ARM_EXT_V6, 0x06800010, 0x0ff00ff0, "pkhbt%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06800010, 0x0ff00070, "pkhbt%c\t%12-15r, %16-19r, %0-3r, lsl #%7-11d"},
+ {ARM_EXT_V6, 0x06800050, 0x0ff00ff0, "pkhtb%c\t%12-15r, %16-19r, %0-3r, asr #32"},
+ {ARM_EXT_V6, 0x06800050, 0x0ff00070, "pkhtb%c\t%12-15r, %16-19r, %0-3r, asr #%7-11d"},
+ {ARM_EXT_V6, 0x01900f9f, 0x0ff00fff, "ldrex%c\tr%12-15d, [%16-19r]"},
+ {ARM_EXT_V6, 0x06200f10, 0x0ff00ff0, "qadd16%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06200f90, 0x0ff00ff0, "qadd8%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06200f30, 0x0ff00ff0, "qaddsubx%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06200f70, 0x0ff00ff0, "qsub16%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06200ff0, 0x0ff00ff0, "qsub8%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06200f50, 0x0ff00ff0, "qsubaddx%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06100f10, 0x0ff00ff0, "sadd16%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06100f90, 0x0ff00ff0, "sadd8%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06100f30, 0x0ff00ff0, "saddaddx%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06300f10, 0x0ff00ff0, "shadd16%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06300f90, 0x0ff00ff0, "shadd8%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06300f30, 0x0ff00ff0, "shaddsubx%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06300f70, 0x0ff00ff0, "shsub16%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06300ff0, 0x0ff00ff0, "shsub8%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06300f50, 0x0ff00ff0, "shsubaddx%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06100f70, 0x0ff00ff0, "ssub16%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06100ff0, 0x0ff00ff0, "ssub8%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06100f50, 0x0ff00ff0, "ssubaddx%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06500f10, 0x0ff00ff0, "uadd16%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06500f90, 0x0ff00ff0, "uadd8%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06500f30, 0x0ff00ff0, "uaddsubx%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06700f10, 0x0ff00ff0, "uhadd16%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06700f90, 0x0ff00ff0, "uhadd8%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06700f30, 0x0ff00ff0, "uhaddsubx%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06700f70, 0x0ff00ff0, "uhsub16%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06700ff0, 0x0ff00ff0, "uhsub8%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06700f50, 0x0ff00ff0, "uhsubaddx%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06600f10, 0x0ff00ff0, "uqadd16%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06600f90, 0x0ff00ff0, "uqadd8%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06600f30, 0x0ff00ff0, "uqaddsubx%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06600f70, 0x0ff00ff0, "uqsub16%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06600ff0, 0x0ff00ff0, "uqsub8%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06600f50, 0x0ff00ff0, "uqsubaddx%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06500f70, 0x0ff00ff0, "usub16%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06500ff0, 0x0ff00ff0, "usub8%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06500f50, 0x0ff00ff0, "usubaddx%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06bf0f30, 0x0fff0ff0, "rev%c\t\%12-15r, %0-3r"},
+ {ARM_EXT_V6, 0x06bf0fb0, 0x0fff0ff0, "rev16%c\t\%12-15r, %0-3r"},
+ {ARM_EXT_V6, 0x06ff0fb0, 0x0fff0ff0, "revsh%c\t\%12-15r, %0-3r"},
+ {ARM_EXT_V6, 0xf8100a00, 0xfe50ffff, "rfe%23?id%24?ba\t\%16-19r%21'!"},
+ {ARM_EXT_V6, 0x06bf0070, 0x0fff0ff0, "sxth%c\t%12-15r, %0-3r"},
+ {ARM_EXT_V6, 0x06bf0470, 0x0fff0ff0, "sxth%c\t%12-15r, %0-3r, ror #8"},
+ {ARM_EXT_V6, 0x06bf0870, 0x0fff0ff0, "sxth%c\t%12-15r, %0-3r, ror #16"},
+ {ARM_EXT_V6, 0x06bf0c70, 0x0fff0ff0, "sxth%c\t%12-15r, %0-3r, ror #24"},
+ {ARM_EXT_V6, 0x068f0070, 0x0fff0ff0, "sxtb16%c\t%12-15r, %0-3r"},
+ {ARM_EXT_V6, 0x068f0470, 0x0fff0ff0, "sxtb16%c\t%12-15r, %0-3r, ror #8"},
+ {ARM_EXT_V6, 0x068f0870, 0x0fff0ff0, "sxtb16%c\t%12-15r, %0-3r, ror #16"},
+ {ARM_EXT_V6, 0x068f0c70, 0x0fff0ff0, "sxtb16%c\t%12-15r, %0-3r, ror #24"},
+ {ARM_EXT_V6, 0x06af0070, 0x0fff0ff0, "sxtb%c\t%12-15r, %0-3r"},
+ {ARM_EXT_V6, 0x06af0470, 0x0fff0ff0, "sxtb%c\t%12-15r, %0-3r, ror #8"},
+ {ARM_EXT_V6, 0x06af0870, 0x0fff0ff0, "sxtb%c\t%12-15r, %0-3r, ror #16"},
+ {ARM_EXT_V6, 0x06af0c70, 0x0fff0ff0, "sxtb%c\t%12-15r, %0-3r, ror #24"},
+ {ARM_EXT_V6, 0x06ff0070, 0x0fff0ff0, "uxth%c\t%12-15r, %0-3r"},
+ {ARM_EXT_V6, 0x06ff0470, 0x0fff0ff0, "uxth%c\t%12-15r, %0-3r, ror #8"},
+ {ARM_EXT_V6, 0x06ff0870, 0x0fff0ff0, "uxth%c\t%12-15r, %0-3r, ror #16"},
+ {ARM_EXT_V6, 0x06ff0c70, 0x0fff0ff0, "uxth%c\t%12-15r, %0-3r, ror #24"},
+ {ARM_EXT_V6, 0x06cf0070, 0x0fff0ff0, "uxtb16%c\t%12-15r, %0-3r"},
+ {ARM_EXT_V6, 0x06cf0470, 0x0fff0ff0, "uxtb16%c\t%12-15r, %0-3r, ror #8"},
+ {ARM_EXT_V6, 0x06cf0870, 0x0fff0ff0, "uxtb16%c\t%12-15r, %0-3r, ror #16"},
+ {ARM_EXT_V6, 0x06cf0c70, 0x0fff0ff0, "uxtb16%c\t%12-15r, %0-3r, ror #24"},
+ {ARM_EXT_V6, 0x06ef0070, 0x0fff0ff0, "uxtb%c\t%12-15r, %0-3r"},
+ {ARM_EXT_V6, 0x06ef0470, 0x0fff0ff0, "uxtb%c\t%12-15r, %0-3r, ror #8"},
+ {ARM_EXT_V6, 0x06ef0870, 0x0fff0ff0, "uxtb%c\t%12-15r, %0-3r, ror #16"},
+ {ARM_EXT_V6, 0x06ef0c70, 0x0fff0ff0, "uxtb%c\t%12-15r, %0-3r, ror #24"},
+ {ARM_EXT_V6, 0x06b00070, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06b00470, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ror #8"},
+ {ARM_EXT_V6, 0x06b00870, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ror #16"},
+ {ARM_EXT_V6, 0x06b00c70, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ror #24"},
+ {ARM_EXT_V6, 0x06800070, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06800470, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ror #8"},
+ {ARM_EXT_V6, 0x06800870, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ror #16"},
+ {ARM_EXT_V6, 0x06800c70, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ror #24"},
+ {ARM_EXT_V6, 0x06a00070, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06a00470, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ror #8"},
+ {ARM_EXT_V6, 0x06a00870, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ror #16"},
+ {ARM_EXT_V6, 0x06a00c70, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ror #24"},
+ {ARM_EXT_V6, 0x06f00070, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06f00470, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ror #8"},
+ {ARM_EXT_V6, 0x06f00870, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ror #16"},
+ {ARM_EXT_V6, 0x06f00c70, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ror #24"},
+ {ARM_EXT_V6, 0x06c00070, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06c00470, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ror #8"},
+ {ARM_EXT_V6, 0x06c00870, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ror #16"},
+ {ARM_EXT_V6, 0x06c00c70, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
+ {ARM_EXT_V6, 0x06e00070, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0x06e00470, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ror #8"},
+ {ARM_EXT_V6, 0x06e00870, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ror #16"},
+ {ARM_EXT_V6, 0x06e00c70, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ror #24"},
+ {ARM_EXT_V6, 0x06800fb0, 0x0ff00ff0, "sel%c\t%12-15r, %16-19r, %0-3r"},
+ {ARM_EXT_V6, 0xf1010000, 0xfffffc00, "setend\t%9?ble"},
+ {ARM_EXT_V6, 0x0700f010, 0x0ff0f0d0, "smuad%5'x%c\t%16-19r, %0-3r, %8-11r"},
+ {ARM_EXT_V6, 0x0700f050, 0x0ff0f0d0, "smusd%5'x%c\t%16-19r, %0-3r, %8-11r"},
+ {ARM_EXT_V6, 0x07000010, 0x0ff000d0, "smlad%5'x%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+ {ARM_EXT_V6, 0x07400010, 0x0ff000d0, "smlald%5'x%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
+ {ARM_EXT_V6, 0x07000050, 0x0ff000d0, "smlsd%5'x%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+ {ARM_EXT_V6, 0x07400050, 0x0ff000d0, "smlsld%5'x%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
+ {ARM_EXT_V6, 0x0750f010, 0x0ff0f0d0, "smmul%5'r%c\t%16-19r, %0-3r, %8-11r"},
+ {ARM_EXT_V6, 0x07500010, 0x0ff000d0, "smmla%5'r%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+ {ARM_EXT_V6, 0x075000d0, 0x0ff000d0, "smmls%5'r%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+ {ARM_EXT_V6, 0xf84d0500, 0xfe5fffe0, "srs%23?id%24?ba\t%16-19r%21'!, #%0-4d"},
+ {ARM_EXT_V6, 0x06a00010, 0x0fe00ff0, "ssat%c\t%12-15r, #%16-20W, %0-3r"},
+ {ARM_EXT_V6, 0x06a00010, 0x0fe00070, "ssat%c\t%12-15r, #%16-20W, %0-3r, lsl #%7-11d"},
+ {ARM_EXT_V6, 0x06a00050, 0x0fe00070, "ssat%c\t%12-15r, #%16-20W, %0-3r, asr #%7-11d"},
+ {ARM_EXT_V6, 0x06a00f30, 0x0ff00ff0, "ssat16%c\t%12-15r, #%16-19W, %0-3r"},
+ {ARM_EXT_V6, 0x01800f90, 0x0ff00ff0, "strex%c\t%12-15r, %0-3r, [%16-19r]"},
+ {ARM_EXT_V6, 0x00400090, 0x0ff000f0, "umaal%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
+ {ARM_EXT_V6, 0x0780f010, 0x0ff0f0f0, "usad8%c\t%16-19r, %0-3r, %8-11r"},
+ {ARM_EXT_V6, 0x07800010, 0x0ff000f0, "usada8%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+ {ARM_EXT_V6, 0x06e00010, 0x0fe00ff0, "usat%c\t%12-15r, #%16-20d, %0-3r"},
+ {ARM_EXT_V6, 0x06e00010, 0x0fe00070, "usat%c\t%12-15r, #%16-20d, %0-3r, lsl #%7-11d"},
+ {ARM_EXT_V6, 0x06e00050, 0x0fe00070, "usat%c\t%12-15r, #%16-20d, %0-3r, asr #%7-11d"},
+ {ARM_EXT_V6, 0x06e00f30, 0x0ff00ff0, "usat16%c\t%12-15r, #%16-19d, %0-3r"},
+
+ /* V5J instruction. */
+ {ARM_EXT_V5J, 0x012fff20, 0x0ffffff0, "bxj%c\t%0-3r"},
+
+ /* V5 Instructions. */
+ {ARM_EXT_V5, 0xe1200070, 0xfff000f0, "bkpt\t0x%16-19X%12-15X%8-11X%0-3X"},
+ {ARM_EXT_V5, 0xfa000000, 0xfe000000, "blx\t%B"},
+ {ARM_EXT_V5, 0x012fff30, 0x0ffffff0, "blx%c\t%0-3r"},
+ {ARM_EXT_V5, 0x016f0f10, 0x0fff0ff0, "clz%c\t%12-15r, %0-3r"},
+
+ /* V5E "El Segundo" Instructions. */
+ {ARM_EXT_V5E, 0x000000d0, 0x0e1000f0, "ldrd%c\t%12-15r, %s"},
+ {ARM_EXT_V5E, 0x000000f0, 0x0e1000f0, "strd%c\t%12-15r, %s"},
+ {ARM_EXT_V5E, 0xf450f000, 0xfc70f000, "pld\t%a"},
+ {ARM_EXT_V5ExP, 0x01000080, 0x0ff000f0, "smlabb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+ {ARM_EXT_V5ExP, 0x010000a0, 0x0ff000f0, "smlatb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+ {ARM_EXT_V5ExP, 0x010000c0, 0x0ff000f0, "smlabt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+ {ARM_EXT_V5ExP, 0x010000e0, 0x0ff000f0, "smlatt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+
+ {ARM_EXT_V5ExP, 0x01200080, 0x0ff000f0, "smlawb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+ {ARM_EXT_V5ExP, 0x012000c0, 0x0ff000f0, "smlawt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
+
+ {ARM_EXT_V5ExP, 0x01400080, 0x0ff000f0, "smlalbb%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
+ {ARM_EXT_V5ExP, 0x014000a0, 0x0ff000f0, "smlaltb%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
+ {ARM_EXT_V5ExP, 0x014000c0, 0x0ff000f0, "smlalbt%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
+ {ARM_EXT_V5ExP, 0x014000e0, 0x0ff000f0, "smlaltt%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
+
+ {ARM_EXT_V5ExP, 0x01600080, 0x0ff0f0f0, "smulbb%c\t%16-19r, %0-3r, %8-11r"},
+ {ARM_EXT_V5ExP, 0x016000a0, 0x0ff0f0f0, "smultb%c\t%16-19r, %0-3r, %8-11r"},
+ {ARM_EXT_V5ExP, 0x016000c0, 0x0ff0f0f0, "smulbt%c\t%16-19r, %0-3r, %8-11r"},
+ {ARM_EXT_V5ExP, 0x016000e0, 0x0ff0f0f0, "smultt%c\t%16-19r, %0-3r, %8-11r"},
+
+ {ARM_EXT_V5ExP, 0x012000a0, 0x0ff0f0f0, "smulwb%c\t%16-19r, %0-3r, %8-11r"},
+ {ARM_EXT_V5ExP, 0x012000e0, 0x0ff0f0f0, "smulwt%c\t%16-19r, %0-3r, %8-11r"},
+
+ {ARM_EXT_V5ExP, 0x01000050, 0x0ff00ff0, "qadd%c\t%12-15r, %0-3r, %16-19r"},
+ {ARM_EXT_V5ExP, 0x01400050, 0x0ff00ff0, "qdadd%c\t%12-15r, %0-3r, %16-19r"},
+ {ARM_EXT_V5ExP, 0x01200050, 0x0ff00ff0, "qsub%c\t%12-15r, %0-3r, %16-19r"},
+ {ARM_EXT_V5ExP, 0x01600050, 0x0ff00ff0, "qdsub%c\t%12-15r, %0-3r, %16-19r"},
+
+ /* ARM Instructions. */
+ {ARM_EXT_V1, 0x00000090, 0x0e100090, "str%6's%5?hb%c\t%12-15r, %s"},
+ {ARM_EXT_V1, 0x00100090, 0x0e100090, "ldr%6's%5?hb%c\t%12-15r, %s"},
+ {ARM_EXT_V1, 0x00000000, 0x0de00000, "and%20's%c\t%12-15r, %16-19r, %o"},
+ {ARM_EXT_V1, 0x00200000, 0x0de00000, "eor%20's%c\t%12-15r, %16-19r, %o"},
+ {ARM_EXT_V1, 0x00400000, 0x0de00000, "sub%20's%c\t%12-15r, %16-19r, %o"},
+ {ARM_EXT_V1, 0x00600000, 0x0de00000, "rsb%20's%c\t%12-15r, %16-19r, %o"},
+ {ARM_EXT_V1, 0x00800000, 0x0de00000, "add%20's%c\t%12-15r, %16-19r, %o"},
+ {ARM_EXT_V1, 0x00a00000, 0x0de00000, "adc%20's%c\t%12-15r, %16-19r, %o"},
+ {ARM_EXT_V1, 0x00c00000, 0x0de00000, "sbc%20's%c\t%12-15r, %16-19r, %o"},
+ {ARM_EXT_V1, 0x00e00000, 0x0de00000, "rsc%20's%c\t%12-15r, %16-19r, %o"},
+ {ARM_EXT_V3, 0x0120f000, 0x0db0f000, "msr%c\t%22?SCPSR%C, %o"},
+ {ARM_EXT_V3, 0x010f0000, 0x0fbf0fff, "mrs%c\t%12-15r, %22?SCPSR"},
+ {ARM_EXT_V1, 0x01000000, 0x0de00000, "tst%p%c\t%16-19r, %o"},
+ {ARM_EXT_V1, 0x01200000, 0x0de00000, "teq%p%c\t%16-19r, %o"},
+ {ARM_EXT_V1, 0x01400000, 0x0de00000, "cmp%p%c\t%16-19r, %o"},
+ {ARM_EXT_V1, 0x01600000, 0x0de00000, "cmn%p%c\t%16-19r, %o"},
+ {ARM_EXT_V1, 0x01800000, 0x0de00000, "orr%20's%c\t%12-15r, %16-19r, %o"},
+ {ARM_EXT_V1, 0x03a00000, 0x0fef0000, "mov%20's%c\t%12-15r, %o"},
+ {ARM_EXT_V1, 0x01a00000, 0x0def0ff0, "mov%20's%c\t%12-15r, %0-3r"},
+ {ARM_EXT_V1, 0x01a00000, 0x0def0060, "lsl%20's%c\t%12-15r, %q"},
+ {ARM_EXT_V1, 0x01a00020, 0x0def0060, "lsr%20's%c\t%12-15r, %q"},
+ {ARM_EXT_V1, 0x01a00040, 0x0def0060, "asr%20's%c\t%12-15r, %q"},
+ {ARM_EXT_V1, 0x01a00060, 0x0def0ff0, "rrx%20's%c\t%12-15r, %0-3r"},
+ {ARM_EXT_V1, 0x01a00060, 0x0def0060, "ror%20's%c\t%12-15r, %q"},
+ {ARM_EXT_V1, 0x01c00000, 0x0de00000, "bic%20's%c\t%12-15r, %16-19r, %o"},
+ {ARM_EXT_V1, 0x01e00000, 0x0de00000, "mvn%20's%c\t%12-15r, %o"},
+ {ARM_EXT_V1, 0x052d0004, 0x0fff0fff, "push%c\t{%12-15r}\t\t; (str%c %12-15r, %a)"},
+ {ARM_EXT_V1, 0x04000000, 0x0e100000, "str%22'b%t%c\t%12-15r, %a"},
+ {ARM_EXT_V1, 0x06000000, 0x0e100ff0, "str%22'b%t%c\t%12-15r, %a"},
+ {ARM_EXT_V1, 0x04000000, 0x0c100010, "str%22'b%t%c\t%12-15r, %a"},
+ {ARM_EXT_V1, 0x06000010, 0x0e000010, "undefined"},
+ {ARM_EXT_V1, 0x049d0004, 0x0fff0fff, "pop%c\t{%12-15r}\t\t; (ldr%c %12-15r, %a)"},
+ {ARM_EXT_V1, 0x04100000, 0x0c100000, "ldr%22'b%t%c\t%12-15r, %a"},
+ {ARM_EXT_V1, 0x092d0000, 0x0fff0000, "push%c\t%m"},
+ {ARM_EXT_V1, 0x08800000, 0x0ff00000, "stm%c\t%16-19r%21'!, %m%22'^"},
+ {ARM_EXT_V1, 0x08000000, 0x0e100000, "stm%23?id%24?ba%c\t%16-19r%21'!, %m%22'^"},
+ {ARM_EXT_V1, 0x08bd0000, 0x0fff0000, "pop%c\t%m"},
+ {ARM_EXT_V1, 0x08900000, 0x0f900000, "ldm%c\t%16-19r%21'!, %m%22'^"},
+ {ARM_EXT_V1, 0x08100000, 0x0e100000, "ldm%23?id%24?ba%c\t%16-19r%21'!, %m%22'^"},
+ {ARM_EXT_V1, 0x0a000000, 0x0e000000, "b%24'l%c\t%b"},
+ {ARM_EXT_V1, 0x0f000000, 0x0f000000, "svc%c\t%0-23x"},
+
+ /* The rest. */
+ {ARM_EXT_V1, 0x00000000, 0x00000000, "undefined instruction %0-31x"},
+ {0, 0x00000000, 0x00000000, 0}
+};
+
+/* print_insn_thumb16 recognizes the following format control codes:
+
+ %S print Thumb register (bits 3..5 as high number if bit 6 set)
+ %D print Thumb register (bits 0..2 as high number if bit 7 set)
+ %<bitfield>I print bitfield as a signed decimal
+ (top bit of range being the sign bit)
+ %N print Thumb register mask (with LR)
+ %O print Thumb register mask (with PC)
+ %M print Thumb register mask
+ %b print CZB's 6-bit unsigned branch destination
+ %s print Thumb right-shift immediate (6..10; 0 == 32).
+ %c print the condition code
+ %C print the condition code, or "s" if not conditional
+ %x print warning if conditional an not at end of IT block"
+ %X print "\t; unpredictable <IT:code>" if conditional
+ %I print IT instruction suffix and operands
+ %<bitfield>r print bitfield as an ARM register
+ %<bitfield>d print bitfield as a decimal
+ %<bitfield>H print (bitfield * 2) as a decimal
+ %<bitfield>W print (bitfield * 4) as a decimal
+ %<bitfield>a print (bitfield * 4) as a pc-rel offset + decoded symbol
+ %<bitfield>B print Thumb branch destination (signed displacement)
+ %<bitfield>c print bitfield as a condition code
+ %<bitnum>'c print specified char iff bit is one
+ %<bitnum>?ab print a if bit is one else print b. */
+
+static const struct opcode16 thumb_opcodes[] =
+{
+ /* Thumb instructions. */
+
+ /* ARM V6K no-argument instructions. */
+ {ARM_EXT_V6K, 0xbf00, 0xffff, "nop%c"},
+ {ARM_EXT_V6K, 0xbf10, 0xffff, "yield%c"},
+ {ARM_EXT_V6K, 0xbf20, 0xffff, "wfe%c"},
+ {ARM_EXT_V6K, 0xbf30, 0xffff, "wfi%c"},
+ {ARM_EXT_V6K, 0xbf40, 0xffff, "sev%c"},
+ {ARM_EXT_V6K, 0xbf00, 0xff0f, "nop%c\t{%4-7d}"},
+
+ /* ARM V6T2 instructions. */
+ {ARM_EXT_V6T2, 0xb900, 0xfd00, "cbnz\t%0-2r, %b%X"},
+ {ARM_EXT_V6T2, 0xb100, 0xfd00, "cbz\t%0-2r, %b%X"},
+ {ARM_EXT_V6T2, 0xbf00, 0xff00, "it%I%X"},
+
+ /* ARM V6. */
+ {ARM_EXT_V6, 0xb660, 0xfff8, "cpsie\t%2'a%1'i%0'f%X"},
+ {ARM_EXT_V6, 0xb670, 0xfff8, "cpsid\t%2'a%1'i%0'f%X"},
+ {ARM_EXT_V6, 0x4600, 0xffc0, "mov%c\t%0-2r, %3-5r"},
+ {ARM_EXT_V6, 0xba00, 0xffc0, "rev%c\t%0-2r, %3-5r"},
+ {ARM_EXT_V6, 0xba40, 0xffc0, "rev16%c\t%0-2r, %3-5r"},
+ {ARM_EXT_V6, 0xbac0, 0xffc0, "revsh%c\t%0-2r, %3-5r"},
+ {ARM_EXT_V6, 0xb650, 0xfff7, "setend\t%3?ble%X"},
+ {ARM_EXT_V6, 0xb200, 0xffc0, "sxth%c\t%0-2r, %3-5r"},
+ {ARM_EXT_V6, 0xb240, 0xffc0, "sxtb%c\t%0-2r, %3-5r"},
+ {ARM_EXT_V6, 0xb280, 0xffc0, "uxth%c\t%0-2r, %3-5r"},
+ {ARM_EXT_V6, 0xb2c0, 0xffc0, "uxtb%c\t%0-2r, %3-5r"},
+
+ /* ARM V5 ISA extends Thumb. */
+ {ARM_EXT_V5T, 0xbe00, 0xff00, "bkpt\t%0-7x"}, /* Is always unconditional. */
+ /* This is BLX(2). BLX(1) is a 32-bit instruction. */
+ {ARM_EXT_V5T, 0x4780, 0xff87, "blx%c\t%3-6r%x"}, /* note: 4 bit register number. */
+ /* ARM V4T ISA (Thumb v1). */
+ {ARM_EXT_V4T, 0x46C0, 0xFFFF, "nop%c\t\t\t(mov r8, r8)"},
+ /* Format 4. */
+ {ARM_EXT_V4T, 0x4000, 0xFFC0, "and%C\t%0-2r, %3-5r"},
+ {ARM_EXT_V4T, 0x4040, 0xFFC0, "eor%C\t%0-2r, %3-5r"},
+ {ARM_EXT_V4T, 0x4080, 0xFFC0, "lsl%C\t%0-2r, %3-5r"},
+ {ARM_EXT_V4T, 0x40C0, 0xFFC0, "lsr%C\t%0-2r, %3-5r"},
+ {ARM_EXT_V4T, 0x4100, 0xFFC0, "asr%C\t%0-2r, %3-5r"},
+ {ARM_EXT_V4T, 0x4140, 0xFFC0, "adc%C\t%0-2r, %3-5r"},
+ {ARM_EXT_V4T, 0x4180, 0xFFC0, "sbc%C\t%0-2r, %3-5r"},
+ {ARM_EXT_V4T, 0x41C0, 0xFFC0, "ror%C\t%0-2r, %3-5r"},
+ {ARM_EXT_V4T, 0x4200, 0xFFC0, "tst%c\t%0-2r, %3-5r"},
+ {ARM_EXT_V4T, 0x4240, 0xFFC0, "neg%C\t%0-2r, %3-5r"},
+ {ARM_EXT_V4T, 0x4280, 0xFFC0, "cmp%c\t%0-2r, %3-5r"},
+ {ARM_EXT_V4T, 0x42C0, 0xFFC0, "cmn%c\t%0-2r, %3-5r"},
+ {ARM_EXT_V4T, 0x4300, 0xFFC0, "orr%C\t%0-2r, %3-5r"},
+ {ARM_EXT_V4T, 0x4340, 0xFFC0, "mul%C\t%0-2r, %3-5r"},
+ {ARM_EXT_V4T, 0x4380, 0xFFC0, "bic%C\t%0-2r, %3-5r"},
+ {ARM_EXT_V4T, 0x43C0, 0xFFC0, "mvn%C\t%0-2r, %3-5r"},
+ /* format 13 */
+ {ARM_EXT_V4T, 0xB000, 0xFF80, "add%c\tsp, #%0-6W"},
+ {ARM_EXT_V4T, 0xB080, 0xFF80, "sub%c\tsp, #%0-6W"},
+ /* format 5 */
+ {ARM_EXT_V4T, 0x4700, 0xFF80, "bx%c\t%S%x"},
+ {ARM_EXT_V4T, 0x4400, 0xFF00, "add%c\t%D, %S"},
+ {ARM_EXT_V4T, 0x4500, 0xFF00, "cmp%c\t%D, %S"},
+ {ARM_EXT_V4T, 0x4600, 0xFF00, "mov%c\t%D, %S"},
+ /* format 14 */
+ {ARM_EXT_V4T, 0xB400, 0xFE00, "push%c\t%N"},
+ {ARM_EXT_V4T, 0xBC00, 0xFE00, "pop%c\t%O"},
+ /* format 2 */
+ {ARM_EXT_V4T, 0x1800, 0xFE00, "add%C\t%0-2r, %3-5r, %6-8r"},
+ {ARM_EXT_V4T, 0x1A00, 0xFE00, "sub%C\t%0-2r, %3-5r, %6-8r"},
+ {ARM_EXT_V4T, 0x1C00, 0xFE00, "add%C\t%0-2r, %3-5r, #%6-8d"},
+ {ARM_EXT_V4T, 0x1E00, 0xFE00, "sub%C\t%0-2r, %3-5r, #%6-8d"},
+ /* format 8 */
+ {ARM_EXT_V4T, 0x5200, 0xFE00, "strh%c\t%0-2r, [%3-5r, %6-8r]"},
+ {ARM_EXT_V4T, 0x5A00, 0xFE00, "ldrh%c\t%0-2r, [%3-5r, %6-8r]"},
+ {ARM_EXT_V4T, 0x5600, 0xF600, "ldrs%11?hb%c\t%0-2r, [%3-5r, %6-8r]"},
+ /* format 7 */
+ {ARM_EXT_V4T, 0x5000, 0xFA00, "str%10'b%c\t%0-2r, [%3-5r, %6-8r]"},
+ {ARM_EXT_V4T, 0x5800, 0xFA00, "ldr%10'b%c\t%0-2r, [%3-5r, %6-8r]"},
+ /* format 1 */
+ {ARM_EXT_V4T, 0x0000, 0xF800, "lsl%C\t%0-2r, %3-5r, #%6-10d"},
+ {ARM_EXT_V4T, 0x0800, 0xF800, "lsr%C\t%0-2r, %3-5r, %s"},
+ {ARM_EXT_V4T, 0x1000, 0xF800, "asr%C\t%0-2r, %3-5r, %s"},
+ /* format 3 */
+ {ARM_EXT_V4T, 0x2000, 0xF800, "mov%C\t%8-10r, #%0-7d"},
+ {ARM_EXT_V4T, 0x2800, 0xF800, "cmp%c\t%8-10r, #%0-7d"},
+ {ARM_EXT_V4T, 0x3000, 0xF800, "add%C\t%8-10r, #%0-7d"},
+ {ARM_EXT_V4T, 0x3800, 0xF800, "sub%C\t%8-10r, #%0-7d"},
+ /* format 6 */
+ {ARM_EXT_V4T, 0x4800, 0xF800, "ldr%c\t%8-10r, [pc, #%0-7W]\t(%0-7a)"}, /* TODO: Disassemble PC relative "LDR rD,=<symbolic>" */
+ /* format 9 */
+ {ARM_EXT_V4T, 0x6000, 0xF800, "str%c\t%0-2r, [%3-5r, #%6-10W]"},
+ {ARM_EXT_V4T, 0x6800, 0xF800, "ldr%c\t%0-2r, [%3-5r, #%6-10W]"},
+ {ARM_EXT_V4T, 0x7000, 0xF800, "strb%c\t%0-2r, [%3-5r, #%6-10d]"},
+ {ARM_EXT_V4T, 0x7800, 0xF800, "ldrb%c\t%0-2r, [%3-5r, #%6-10d]"},
+ /* format 10 */
+ {ARM_EXT_V4T, 0x8000, 0xF800, "strh%c\t%0-2r, [%3-5r, #%6-10H]"},
+ {ARM_EXT_V4T, 0x8800, 0xF800, "ldrh%c\t%0-2r, [%3-5r, #%6-10H]"},
+ /* format 11 */
+ {ARM_EXT_V4T, 0x9000, 0xF800, "str%c\t%8-10r, [sp, #%0-7W]"},
+ {ARM_EXT_V4T, 0x9800, 0xF800, "ldr%c\t%8-10r, [sp, #%0-7W]"},
+ /* format 12 */
+ {ARM_EXT_V4T, 0xA000, 0xF800, "add%c\t%8-10r, pc, #%0-7W\t(adr %8-10r, %0-7a)"},
+ {ARM_EXT_V4T, 0xA800, 0xF800, "add%c\t%8-10r, sp, #%0-7W"},
+ /* format 15 */
+ {ARM_EXT_V4T, 0xC000, 0xF800, "stmia%c\t%8-10r!, %M"},
+ {ARM_EXT_V4T, 0xC800, 0xF800, "ldmia%c\t%8-10r!, %M"},
+ /* format 17 */
+ {ARM_EXT_V4T, 0xDF00, 0xFF00, "svc%c\t%0-7d"},
+ /* format 16 */
+ {ARM_EXT_V4T, 0xDE00, 0xFE00, "undefined"},
+ {ARM_EXT_V4T, 0xD000, 0xF000, "b%8-11c.n\t%0-7B%X"},
+ /* format 18 */
+ {ARM_EXT_V4T, 0xE000, 0xF800, "b%c.n\t%0-10B%x"},
+
+ /* The E800 .. FFFF range is unconditionally redirected to the
+ 32-bit table, because even in pre-V6T2 ISAs, BL and BLX(1) pairs
+ are processed via that table. Thus, we can never encounter a
+ bare "second half of BL/BLX(1)" instruction here. */
+ {ARM_EXT_V1, 0x0000, 0x0000, "undefined"},
+ {0, 0, 0, 0}
+};
+
+/* Thumb32 opcodes use the same table structure as the ARM opcodes.
+ We adopt the convention that hw1 is the high 16 bits of .value and
+ .mask, hw2 the low 16 bits.
+
+ print_insn_thumb32 recognizes the following format control codes:
+
+ %% %
+
+ %I print a 12-bit immediate from hw1[10],hw2[14:12,7:0]
+ %M print a modified 12-bit immediate (same location)
+ %J print a 16-bit immediate from hw1[3:0,10],hw2[14:12,7:0]
+ %K print a 16-bit immediate from hw2[3:0],hw1[3:0],hw2[11:4]
+ %S print a possibly-shifted Rm
+
+ %a print the address of a plain load/store
+ %w print the width and signedness of a core load/store
+ %m print register mask for ldm/stm
+
+ %E print the lsb and width fields of a bfc/bfi instruction
+ %F print the lsb and width fields of a sbfx/ubfx instruction
+ %b print a conditional branch offset
+ %B print an unconditional branch offset
+ %s print the shift field of an SSAT instruction
+ %R print the rotation field of an SXT instruction
+ %U print barrier type.
+ %P print address for pli instruction.
+ %c print the condition code
+ %x print warning if conditional an not at end of IT block"
+ %X print "\t; unpredictable <IT:code>" if conditional
+
+ %<bitfield>d print bitfield in decimal
+ %<bitfield>W print bitfield*4 in decimal
+ %<bitfield>r print bitfield as an ARM register
+ %<bitfield>c print bitfield as a condition code
+
+ %<bitfield>'c print specified char iff bitfield is all ones
+ %<bitfield>`c print specified char iff bitfield is all zeroes
+ %<bitfield>?ab... select from array of values in big endian order
+
+ With one exception at the bottom (done because BL and BLX(1) need
+ to come dead last), this table was machine-sorted first in
+ decreasing order of number of bits set in the mask, then in
+ increasing numeric order of mask, then in increasing numeric order
+ of opcode. This order is not the clearest for a human reader, but
+ is guaranteed never to catch a special-case bit pattern with a more
+ general mask, which is important, because this instruction encoding
+ makes heavy use of special-case bit patterns. */
+static const struct opcode32 thumb32_opcodes[] =
+{
+ /* V7 instructions. */
+ {ARM_EXT_V7, 0xf910f000, 0xff70f000, "pli%c\t%a"},
+ {ARM_EXT_V7, 0xf3af80f0, 0xfffffff0, "dbg%c\t#%0-3d"},
+ {ARM_EXT_V7, 0xf3bf8f50, 0xfffffff0, "dmb%c\t%U"},
+ {ARM_EXT_V7, 0xf3bf8f40, 0xfffffff0, "dsb%c\t%U"},
+ {ARM_EXT_V7, 0xf3bf8f60, 0xfffffff0, "isb%c\t%U"},
+ {ARM_EXT_DIV, 0xfb90f0f0, 0xfff0f0f0, "sdiv%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_DIV, 0xfbb0f0f0, 0xfff0f0f0, "udiv%c\t%8-11r, %16-19r, %0-3r"},
+
+ /* Instructions defined in the basic V6T2 set. */
+ {ARM_EXT_V6T2, 0xf3af8000, 0xffffffff, "nop%c.w"},
+ {ARM_EXT_V6T2, 0xf3af8001, 0xffffffff, "yield%c.w"},
+ {ARM_EXT_V6T2, 0xf3af8002, 0xffffffff, "wfe%c.w"},
+ {ARM_EXT_V6T2, 0xf3af8003, 0xffffffff, "wfi%c.w"},
+ {ARM_EXT_V6T2, 0xf3af9004, 0xffffffff, "sev%c.w"},
+ {ARM_EXT_V6T2, 0xf3af8000, 0xffffff00, "nop%c.w\t{%0-7d}"},
+
+ {ARM_EXT_V6T2, 0xf3bf8f2f, 0xffffffff, "clrex%c"},
+ {ARM_EXT_V6T2, 0xf3af8400, 0xffffff1f, "cpsie.w\t%7'a%6'i%5'f%X"},
+ {ARM_EXT_V6T2, 0xf3af8600, 0xffffff1f, "cpsid.w\t%7'a%6'i%5'f%X"},
+ {ARM_EXT_V6T2, 0xf3c08f00, 0xfff0ffff, "bxj%c\t%16-19r%x"},
+ {ARM_EXT_V6T2, 0xe810c000, 0xffd0ffff, "rfedb%c\t%16-19r%21'!"},
+ {ARM_EXT_V6T2, 0xe990c000, 0xffd0ffff, "rfeia%c\t%16-19r%21'!"},
+ {ARM_EXT_V6T2, 0xf3ef8000, 0xffeff000, "mrs%c\t%8-11r, %D"},
+ {ARM_EXT_V6T2, 0xf3af8100, 0xffffffe0, "cps\t#%0-4d%X"},
+ {ARM_EXT_V6T2, 0xe8d0f000, 0xfff0fff0, "tbb%c\t[%16-19r, %0-3r]%x"},
+ {ARM_EXT_V6T2, 0xe8d0f010, 0xfff0fff0, "tbh%c\t[%16-19r, %0-3r, lsl #1]%x"},
+ {ARM_EXT_V6T2, 0xf3af8500, 0xffffff00, "cpsie\t%7'a%6'i%5'f, #%0-4d%X"},
+ {ARM_EXT_V6T2, 0xf3af8700, 0xffffff00, "cpsid\t%7'a%6'i%5'f, #%0-4d%X"},
+ {ARM_EXT_V6T2, 0xf3de8f00, 0xffffff00, "subs%c\tpc, lr, #%0-7d"},
+ {ARM_EXT_V6T2, 0xf3808000, 0xffe0f000, "msr%c\t%C, %16-19r"},
+ {ARM_EXT_V6T2, 0xe8500f00, 0xfff00fff, "ldrex%c\t%12-15r, [%16-19r]"},
+ {ARM_EXT_V6T2, 0xe8d00f4f, 0xfff00fef, "ldrex%4?hb%c\t%12-15r, [%16-19r]"},
+ {ARM_EXT_V6T2, 0xe800c000, 0xffd0ffe0, "srsdb%c\t%16-19r%21'!, #%0-4d"},
+ {ARM_EXT_V6T2, 0xe980c000, 0xffd0ffe0, "srsia%c\t%16-19r%21'!, #%0-4d"},
+ {ARM_EXT_V6T2, 0xfa0ff080, 0xfffff0c0, "sxth%c.w\t%8-11r, %0-3r%R"},
+ {ARM_EXT_V6T2, 0xfa1ff080, 0xfffff0c0, "uxth%c.w\t%8-11r, %0-3r%R"},
+ {ARM_EXT_V6T2, 0xfa2ff080, 0xfffff0c0, "sxtb16%c\t%8-11r, %0-3r%R"},
+ {ARM_EXT_V6T2, 0xfa3ff080, 0xfffff0c0, "uxtb16%c\t%8-11r, %0-3r%R"},
+ {ARM_EXT_V6T2, 0xfa4ff080, 0xfffff0c0, "sxtb%c.w\t%8-11r, %0-3r%R"},
+ {ARM_EXT_V6T2, 0xfa5ff080, 0xfffff0c0, "uxtb%c.w\t%8-11r, %0-3r%R"},
+ {ARM_EXT_V6T2, 0xe8400000, 0xfff000ff, "strex%c\t%8-11r, %12-15r, [%16-19r]"},
+ {ARM_EXT_V6T2, 0xe8d0007f, 0xfff000ff, "ldrexd%c\t%12-15r, %8-11r, [%16-19r]"},
+ {ARM_EXT_V6T2, 0xfa80f000, 0xfff0f0f0, "sadd8%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfa80f010, 0xfff0f0f0, "qadd8%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfa80f020, 0xfff0f0f0, "shadd8%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfa80f040, 0xfff0f0f0, "uadd8%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfa80f050, 0xfff0f0f0, "uqadd8%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfa80f060, 0xfff0f0f0, "uhadd8%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfa80f080, 0xfff0f0f0, "qadd%c\t%8-11r, %0-3r, %16-19r"},
+ {ARM_EXT_V6T2, 0xfa80f090, 0xfff0f0f0, "qdadd%c\t%8-11r, %0-3r, %16-19r"},
+ {ARM_EXT_V6T2, 0xfa80f0a0, 0xfff0f0f0, "qsub%c\t%8-11r, %0-3r, %16-19r"},
+ {ARM_EXT_V6T2, 0xfa80f0b0, 0xfff0f0f0, "qdsub%c\t%8-11r, %0-3r, %16-19r"},
+ {ARM_EXT_V6T2, 0xfa90f000, 0xfff0f0f0, "sadd16%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfa90f010, 0xfff0f0f0, "qadd16%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfa90f020, 0xfff0f0f0, "shadd16%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfa90f040, 0xfff0f0f0, "uadd16%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfa90f050, 0xfff0f0f0, "uqadd16%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfa90f060, 0xfff0f0f0, "uhadd16%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfa90f080, 0xfff0f0f0, "rev%c.w\t%8-11r, %16-19r"},
+ {ARM_EXT_V6T2, 0xfa90f090, 0xfff0f0f0, "rev16%c.w\t%8-11r, %16-19r"},
+ {ARM_EXT_V6T2, 0xfa90f0a0, 0xfff0f0f0, "rbit%c\t%8-11r, %16-19r"},
+ {ARM_EXT_V6T2, 0xfa90f0b0, 0xfff0f0f0, "revsh%c.w\t%8-11r, %16-19r"},
+ {ARM_EXT_V6T2, 0xfaa0f000, 0xfff0f0f0, "saddsubx%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfaa0f010, 0xfff0f0f0, "qaddsubx%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfaa0f020, 0xfff0f0f0, "shaddsubx%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfaa0f040, 0xfff0f0f0, "uaddsubx%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfaa0f050, 0xfff0f0f0, "uqaddsubx%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfaa0f060, 0xfff0f0f0, "uhaddsubx%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfaa0f080, 0xfff0f0f0, "sel%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfab0f080, 0xfff0f0f0, "clz%c\t%8-11r, %16-19r"},
+ {ARM_EXT_V6T2, 0xfac0f000, 0xfff0f0f0, "ssub8%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfac0f010, 0xfff0f0f0, "qsub8%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfac0f020, 0xfff0f0f0, "shsub8%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfac0f040, 0xfff0f0f0, "usub8%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfac0f050, 0xfff0f0f0, "uqsub8%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfac0f060, 0xfff0f0f0, "uhsub8%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfad0f000, 0xfff0f0f0, "ssub16%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfad0f010, 0xfff0f0f0, "qsub16%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfad0f020, 0xfff0f0f0, "shsub16%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfad0f040, 0xfff0f0f0, "usub16%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfad0f050, 0xfff0f0f0, "uqsub16%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfad0f060, 0xfff0f0f0, "uhsub16%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfae0f000, 0xfff0f0f0, "ssubaddx%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfae0f010, 0xfff0f0f0, "qsubaddx%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfae0f020, 0xfff0f0f0, "shsubaddx%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfae0f040, 0xfff0f0f0, "usubaddx%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfae0f050, 0xfff0f0f0, "uqsubaddx%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfae0f060, 0xfff0f0f0, "uhsubaddx%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfb00f000, 0xfff0f0f0, "mul%c.w\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfb70f000, 0xfff0f0f0, "usad8%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfa00f000, 0xffe0f0f0, "lsl%20's%c.w\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfa20f000, 0xffe0f0f0, "lsr%20's%c.w\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfa40f000, 0xffe0f0f0, "asr%20's%c.w\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfa60f000, 0xffe0f0f0, "ror%20's%c.w\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xe8c00f40, 0xfff00fe0, "strex%4?hb%c\t%0-3r, %12-15r, [%16-19r]"},
+ {ARM_EXT_V6T2, 0xf3200000, 0xfff0f0e0, "ssat16%c\t%8-11r, #%0-4d, %16-19r"},
+ {ARM_EXT_V6T2, 0xf3a00000, 0xfff0f0e0, "usat16%c\t%8-11r, #%0-4d, %16-19r"},
+ {ARM_EXT_V6T2, 0xfb20f000, 0xfff0f0e0, "smuad%4'x%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfb30f000, 0xfff0f0e0, "smulw%4?tb%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfb40f000, 0xfff0f0e0, "smusd%4'x%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfb50f000, 0xfff0f0e0, "smmul%4'r%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfa00f080, 0xfff0f0c0, "sxtah%c\t%8-11r, %16-19r, %0-3r%R"},
+ {ARM_EXT_V6T2, 0xfa10f080, 0xfff0f0c0, "uxtah%c\t%8-11r, %16-19r, %0-3r%R"},
+ {ARM_EXT_V6T2, 0xfa20f080, 0xfff0f0c0, "sxtab16%c\t%8-11r, %16-19r, %0-3r%R"},
+ {ARM_EXT_V6T2, 0xfa30f080, 0xfff0f0c0, "uxtab16%c\t%8-11r, %16-19r, %0-3r%R"},
+ {ARM_EXT_V6T2, 0xfa40f080, 0xfff0f0c0, "sxtab%c\t%8-11r, %16-19r, %0-3r%R"},
+ {ARM_EXT_V6T2, 0xfa50f080, 0xfff0f0c0, "uxtab%c\t%8-11r, %16-19r, %0-3r%R"},
+ {ARM_EXT_V6T2, 0xfb10f000, 0xfff0f0c0, "smul%5?tb%4?tb%c\t%8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xf36f0000, 0xffff8020, "bfc%c\t%8-11r, %E"},
+ {ARM_EXT_V6T2, 0xea100f00, 0xfff08f00, "tst%c.w\t%16-19r, %S"},
+ {ARM_EXT_V6T2, 0xea900f00, 0xfff08f00, "teq%c\t%16-19r, %S"},
+ {ARM_EXT_V6T2, 0xeb100f00, 0xfff08f00, "cmn%c.w\t%16-19r, %S"},
+ {ARM_EXT_V6T2, 0xebb00f00, 0xfff08f00, "cmp%c.w\t%16-19r, %S"},
+ {ARM_EXT_V6T2, 0xf0100f00, 0xfbf08f00, "tst%c.w\t%16-19r, %M"},
+ {ARM_EXT_V6T2, 0xf0900f00, 0xfbf08f00, "teq%c\t%16-19r, %M"},
+ {ARM_EXT_V6T2, 0xf1100f00, 0xfbf08f00, "cmn%c.w\t%16-19r, %M"},
+ {ARM_EXT_V6T2, 0xf1b00f00, 0xfbf08f00, "cmp%c.w\t%16-19r, %M"},
+ {ARM_EXT_V6T2, 0xea4f0000, 0xffef8000, "mov%20's%c.w\t%8-11r, %S"},
+ {ARM_EXT_V6T2, 0xea6f0000, 0xffef8000, "mvn%20's%c.w\t%8-11r, %S"},
+ {ARM_EXT_V6T2, 0xe8c00070, 0xfff000f0, "strexd%c\t%0-3r, %12-15r, %8-11r, [%16-19r]"},
+ {ARM_EXT_V6T2, 0xfb000000, 0xfff000f0, "mla%c\t%8-11r, %16-19r, %0-3r, %12-15r"},
+ {ARM_EXT_V6T2, 0xfb000010, 0xfff000f0, "mls%c\t%8-11r, %16-19r, %0-3r, %12-15r"},
+ {ARM_EXT_V6T2, 0xfb700000, 0xfff000f0, "usada8%c\t%8-11r, %16-19r, %0-3r, %12-15r"},
+ {ARM_EXT_V6T2, 0xfb800000, 0xfff000f0, "smull%c\t%12-15r, %8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfba00000, 0xfff000f0, "umull%c\t%12-15r, %8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfbc00000, 0xfff000f0, "smlal%c\t%12-15r, %8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfbe00000, 0xfff000f0, "umlal%c\t%12-15r, %8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfbe00060, 0xfff000f0, "umaal%c\t%12-15r, %8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xe8500f00, 0xfff00f00, "ldrex%c\t%12-15r, [%16-19r, #%0-7W]"},
+ {ARM_EXT_V6T2, 0xf7f08000, 0xfff0f000, "smc%c\t%K"},
+ {ARM_EXT_V6T2, 0xf04f0000, 0xfbef8000, "mov%20's%c.w\t%8-11r, %M"},
+ {ARM_EXT_V6T2, 0xf06f0000, 0xfbef8000, "mvn%20's%c.w\t%8-11r, %M"},
+ {ARM_EXT_V6T2, 0xf810f000, 0xff70f000, "pld%c\t%a"},
+ {ARM_EXT_V6T2, 0xfb200000, 0xfff000e0, "smlad%4'x%c\t%8-11r, %16-19r, %0-3r, %12-15r"},
+ {ARM_EXT_V6T2, 0xfb300000, 0xfff000e0, "smlaw%4?tb%c\t%8-11r, %16-19r, %0-3r, %12-15r"},
+ {ARM_EXT_V6T2, 0xfb400000, 0xfff000e0, "smlsd%4'x%c\t%8-11r, %16-19r, %0-3r, %12-15r"},
+ {ARM_EXT_V6T2, 0xfb500000, 0xfff000e0, "smmla%4'r%c\t%8-11r, %16-19r, %0-3r, %12-15r"},
+ {ARM_EXT_V6T2, 0xfb600000, 0xfff000e0, "smmls%4'r%c\t%8-11r, %16-19r, %0-3r, %12-15r"},
+ {ARM_EXT_V6T2, 0xfbc000c0, 0xfff000e0, "smlald%4'x%c\t%12-15r, %8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xfbd000c0, 0xfff000e0, "smlsld%4'x%c\t%12-15r, %8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xeac00000, 0xfff08030, "pkhbt%c\t%8-11r, %16-19r, %S"},
+ {ARM_EXT_V6T2, 0xeac00020, 0xfff08030, "pkhtb%c\t%8-11r, %16-19r, %S"},
+ {ARM_EXT_V6T2, 0xf3400000, 0xfff08020, "sbfx%c\t%8-11r, %16-19r, %F"},
+ {ARM_EXT_V6T2, 0xf3c00000, 0xfff08020, "ubfx%c\t%8-11r, %16-19r, %F"},
+ {ARM_EXT_V6T2, 0xf8000e00, 0xff900f00, "str%wt%c\t%12-15r, %a"},
+ {ARM_EXT_V6T2, 0xfb100000, 0xfff000c0, "smla%5?tb%4?tb%c\t%8-11r, %16-19r, %0-3r, %12-15r"},
+ {ARM_EXT_V6T2, 0xfbc00080, 0xfff000c0, "smlal%5?tb%4?tb%c\t%12-15r, %8-11r, %16-19r, %0-3r"},
+ {ARM_EXT_V6T2, 0xf3600000, 0xfff08020, "bfi%c\t%8-11r, %16-19r, %E"},
+ {ARM_EXT_V6T2, 0xf8100e00, 0xfe900f00, "ldr%wt%c\t%12-15r, %a"},
+ {ARM_EXT_V6T2, 0xf3000000, 0xffd08020, "ssat%c\t%8-11r, #%0-4d, %16-19r%s"},
+ {ARM_EXT_V6T2, 0xf3800000, 0xffd08020, "usat%c\t%8-11r, #%0-4d, %16-19r%s"},
+ {ARM_EXT_V6T2, 0xf2000000, 0xfbf08000, "addw%c\t%8-11r, %16-19r, %I"},
+ {ARM_EXT_V6T2, 0xf2400000, 0xfbf08000, "movw%c\t%8-11r, %J"},
+ {ARM_EXT_V6T2, 0xf2a00000, 0xfbf08000, "subw%c\t%8-11r, %16-19r, %I"},
+ {ARM_EXT_V6T2, 0xf2c00000, 0xfbf08000, "movt%c\t%8-11r, %J"},
+ {ARM_EXT_V6T2, 0xea000000, 0xffe08000, "and%20's%c.w\t%8-11r, %16-19r, %S"},
+ {ARM_EXT_V6T2, 0xea200000, 0xffe08000, "bic%20's%c.w\t%8-11r, %16-19r, %S"},
+ {ARM_EXT_V6T2, 0xea400000, 0xffe08000, "orr%20's%c.w\t%8-11r, %16-19r, %S"},
+ {ARM_EXT_V6T2, 0xea600000, 0xffe08000, "orn%20's%c\t%8-11r, %16-19r, %S"},
+ {ARM_EXT_V6T2, 0xea800000, 0xffe08000, "eor%20's%c.w\t%8-11r, %16-19r, %S"},
+ {ARM_EXT_V6T2, 0xeb000000, 0xffe08000, "add%20's%c.w\t%8-11r, %16-19r, %S"},
+ {ARM_EXT_V6T2, 0xeb400000, 0xffe08000, "adc%20's%c.w\t%8-11r, %16-19r, %S"},
+ {ARM_EXT_V6T2, 0xeb600000, 0xffe08000, "sbc%20's%c.w\t%8-11r, %16-19r, %S"},
+ {ARM_EXT_V6T2, 0xeba00000, 0xffe08000, "sub%20's%c.w\t%8-11r, %16-19r, %S"},
+ {ARM_EXT_V6T2, 0xebc00000, 0xffe08000, "rsb%20's%c\t%8-11r, %16-19r, %S"},
+ {ARM_EXT_V6T2, 0xe8400000, 0xfff00000, "strex%c\t%8-11r, %12-15r, [%16-19r, #%0-7W]"},
+ {ARM_EXT_V6T2, 0xf0000000, 0xfbe08000, "and%20's%c.w\t%8-11r, %16-19r, %M"},
+ {ARM_EXT_V6T2, 0xf0200000, 0xfbe08000, "bic%20's%c.w\t%8-11r, %16-19r, %M"},
+ {ARM_EXT_V6T2, 0xf0400000, 0xfbe08000, "orr%20's%c.w\t%8-11r, %16-19r, %M"},
+ {ARM_EXT_V6T2, 0xf0600000, 0xfbe08000, "orn%20's%c\t%8-11r, %16-19r, %M"},
+ {ARM_EXT_V6T2, 0xf0800000, 0xfbe08000, "eor%20's%c.w\t%8-11r, %16-19r, %M"},
+ {ARM_EXT_V6T2, 0xf1000000, 0xfbe08000, "add%20's%c.w\t%8-11r, %16-19r, %M"},
+ {ARM_EXT_V6T2, 0xf1400000, 0xfbe08000, "adc%20's%c.w\t%8-11r, %16-19r, %M"},
+ {ARM_EXT_V6T2, 0xf1600000, 0xfbe08000, "sbc%20's%c.w\t%8-11r, %16-19r, %M"},
+ {ARM_EXT_V6T2, 0xf1a00000, 0xfbe08000, "sub%20's%c.w\t%8-11r, %16-19r, %M"},
+ {ARM_EXT_V6T2, 0xf1c00000, 0xfbe08000, "rsb%20's%c\t%8-11r, %16-19r, %M"},
+ {ARM_EXT_V6T2, 0xe8800000, 0xffd00000, "stmia%c.w\t%16-19r%21'!, %m"},
+ {ARM_EXT_V6T2, 0xe8900000, 0xffd00000, "ldmia%c.w\t%16-19r%21'!, %m"},
+ {ARM_EXT_V6T2, 0xe9000000, 0xffd00000, "stmdb%c\t%16-19r%21'!, %m"},
+ {ARM_EXT_V6T2, 0xe9100000, 0xffd00000, "ldmdb%c\t%16-19r%21'!, %m"},
+ {ARM_EXT_V6T2, 0xe9c00000, 0xffd000ff, "strd%c\t%12-15r, %8-11r, [%16-19r]"},
+ {ARM_EXT_V6T2, 0xe9d00000, 0xffd000ff, "ldrd%c\t%12-15r, %8-11r, [%16-19r]"},
+ {ARM_EXT_V6T2, 0xe9400000, 0xff500000, "strd%c\t%12-15r, %8-11r, [%16-19r, #%23`-%0-7W]%21'!"},
+ {ARM_EXT_V6T2, 0xe9500000, 0xff500000, "ldrd%c\t%12-15r, %8-11r, [%16-19r, #%23`-%0-7W]%21'!"},
+ {ARM_EXT_V6T2, 0xe8600000, 0xff700000, "strd%c\t%12-15r, %8-11r, [%16-19r], #%23`-%0-7W"},
+ {ARM_EXT_V6T2, 0xe8700000, 0xff700000, "ldrd%c\t%12-15r, %8-11r, [%16-19r], #%23`-%0-7W"},
+ {ARM_EXT_V6T2, 0xf8000000, 0xff100000, "str%w%c.w\t%12-15r, %a"},
+ {ARM_EXT_V6T2, 0xf8100000, 0xfe100000, "ldr%w%c.w\t%12-15r, %a"},
+
+ /* Filter out Bcc with cond=E or F, which are used for other instructions. */
+ {ARM_EXT_V6T2, 0xf3c08000, 0xfbc0d000, "undefined (bcc, cond=0xF)"},
+ {ARM_EXT_V6T2, 0xf3808000, 0xfbc0d000, "undefined (bcc, cond=0xE)"},
+ {ARM_EXT_V6T2, 0xf0008000, 0xf800d000, "b%22-25c.w\t%b%X"},
+ {ARM_EXT_V6T2, 0xf0009000, 0xf800d000, "b%c.w\t%B%x"},
+
+ /* These have been 32-bit since the invention of Thumb. */
+ {ARM_EXT_V4T, 0xf000c000, 0xf800d000, "blx%c\t%B%x"},
+ {ARM_EXT_V4T, 0xf000d000, 0xf800d000, "bl%c\t%B%x"},
+
+ /* Fallback. */
+ {ARM_EXT_V1, 0x00000000, 0x00000000, "undefined"},
+ {0, 0, 0, 0}
+};
+
+static const char *const arm_conditional[] =
+{"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
+ "hi", "ls", "ge", "lt", "gt", "le", "al", "<und>", ""};
+
+static const char *const arm_fp_const[] =
+{"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
+
+static const char *const arm_shift[] =
+{"lsl", "lsr", "asr", "ror"};
+
+typedef struct
+{
+ const char *name;
+ const char *description;
+ const char *reg_names[16];
+}
+arm_regname;
+
+static const arm_regname regnames[] =
+{
+ { "raw" , "Select raw register names",
+ { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}},
+ { "gcc", "Select register names used by GCC",
+ { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" }},
+ { "std", "Select register names used in ARM's ISA documentation",
+ { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }},
+ { "apcs", "Select register names used in the APCS",
+ { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl", "fp", "ip", "sp", "lr", "pc" }},
+ { "atpcs", "Select register names used in the ATPCS",
+ { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "IP", "SP", "LR", "PC" }},
+ { "special-atpcs", "Select special register names used in the ATPCS",
+ { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }},
+};
+
+static const char *const iwmmxt_wwnames[] =
+{"b", "h", "w", "d"};
+
+static const char *const iwmmxt_wwssnames[] =
+{"b", "bus", "bc", "bss",
+ "h", "hus", "hc", "hss",
+ "w", "wus", "wc", "wss",
+ "d", "dus", "dc", "dss"
+};
+
+static const char *const iwmmxt_regnames[] =
+{ "wr0", "wr1", "wr2", "wr3", "wr4", "wr5", "wr6", "wr7",
+ "wr8", "wr9", "wr10", "wr11", "wr12", "wr13", "wr14", "wr15"
+};
+
+static const char *const iwmmxt_cregnames[] =
+{ "wcid", "wcon", "wcssf", "wcasf", "reserved", "reserved", "reserved", "reserved",
+ "wcgr0", "wcgr1", "wcgr2", "wcgr3", "reserved", "reserved", "reserved", "reserved"
+};
+
+/* Default to GCC register name set. */
+static unsigned int regname_selected = 1;
+
+#define NUM_ARM_REGNAMES NUM_ELEM (regnames)
+#define arm_regnames regnames[regname_selected].reg_names
+
+static bfd_boolean force_thumb = false;
+
+/* Current IT instruction state. This contains the same state as the IT
+ bits in the CPSR. */
+static unsigned int ifthen_state;
+/* IT state for the next instruction. */
+static unsigned int ifthen_next_state;
+/* The address of the insn for which the IT state is valid. */
+static bfd_vma ifthen_address;
+#define IFTHEN_COND ((ifthen_state >> 4) & 0xf)
+
+/* Cached mapping symbol state. */
+enum map_type {
+ MAP_ARM,
+ MAP_THUMB,
+ MAP_DATA
+};
+
+enum map_type last_type;
+int last_mapping_sym = -1;
+bfd_vma last_mapping_addr = 0;
+
+/* Decode a bitfield of the form matching regexp (N(-N)?,)*N(-N)?.
+ Returns pointer to following character of the format string and
+ fills in *VALUEP and *WIDTHP with the extracted value and number of
+ bits extracted. WIDTHP can be NULL. */
+
+static const char *
+arm_decode_bitfield (const char *ptr, unsigned long insn,
+ unsigned long *valuep, int *widthp)
+{
+ unsigned long value = 0;
+ int width = 0;
+
+ do
+ {
+ int start, end;
+ int bits;
+
+ for (start = 0; *ptr >= '0' && *ptr <= '9'; ptr++)
+ start = start * 10 + *ptr - '0';
+ if (*ptr == '-')
+ for (end = 0, ptr++; *ptr >= '0' && *ptr <= '9'; ptr++)
+ end = end * 10 + *ptr - '0';
+ else
+ end = start;
+ bits = end - start;
+ if (bits < 0)
+ abort ();
+ value |= ((insn >> start) & ((2ul << bits) - 1)) << width;
+ width += bits + 1;
+ }
+ while (*ptr++ == ',');
+ *valuep = value;
+ if (widthp)
+ *widthp = width;
+ return ptr - 1;
+}
+
+static void
+arm_decode_shift (long given, fprintf_function func, void *stream,
+ int print_shift)
+{
+ func (stream, "%s", arm_regnames[given & 0xf]);
+
+ if ((given & 0xff0) != 0)
+ {
+ if ((given & 0x10) == 0)
+ {
+ int amount = (given & 0xf80) >> 7;
+ int shift = (given & 0x60) >> 5;
+
+ if (amount == 0)
+ {
+ if (shift == 3)
+ {
+ func (stream, ", rrx");
+ return;
+ }
+
+ amount = 32;
+ }
+
+ if (print_shift)
+ func (stream, ", %s #%d", arm_shift[shift], amount);
+ else
+ func (stream, ", #%d", amount);
+ }
+ else if (print_shift)
+ func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5],
+ arm_regnames[(given & 0xf00) >> 8]);
+ else
+ func (stream, ", %s", arm_regnames[(given & 0xf00) >> 8]);
+ }
+}
+
+/* Print one coprocessor instruction on INFO->STREAM.
+ Return true if the instruction matched, false if this is not a
+ recognised coprocessor instruction. */
+
+static bfd_boolean
+print_insn_coprocessor (bfd_vma pc, struct disassemble_info *info, long given,
+ bfd_boolean thumb)
+{
+ const struct opcode32 *insn;
+ void *stream = info->stream;
+ fprintf_function func = info->fprintf_func;
+ unsigned long mask;
+ unsigned long value;
+ int cond;
+
+ for (insn = coprocessor_opcodes; insn->assembler; insn++)
+ {
+ if (insn->value == FIRST_IWMMXT_INSN
+ && info->mach != bfd_mach_arm_XScale
+ && info->mach != bfd_mach_arm_iWMMXt
+ && info->mach != bfd_mach_arm_iWMMXt2)
+ insn = insn + IWMMXT_INSN_COUNT;
+
+ mask = insn->mask;
+ value = insn->value;
+ if (thumb)
+ {
+ /* The high 4 bits are 0xe for Arm conditional instructions, and
+ 0xe for arm unconditional instructions. The rest of the
+ encoding is the same. */
+ mask |= 0xf0000000;
+ value |= 0xe0000000;
+ if (ifthen_state)
+ cond = IFTHEN_COND;
+ else
+ cond = 16;
+ }
+ else
+ {
+ /* Only match unconditional instuctions against unconditional
+ patterns. */
+ if ((given & 0xf0000000) == 0xf0000000)
+ {
+ mask |= 0xf0000000;
+ cond = 16;
+ }
+ else
+ {
+ cond = (given >> 28) & 0xf;
+ if (cond == 0xe)
+ cond = 16;
+ }
+ }
+ if ((given & mask) == value)
+ {
+ const char *c;
+
+ for (c = insn->assembler; *c; c++)
+ {
+ if (*c == '%')
+ {
+ switch (*++c)
+ {
+ case '%':
+ func (stream, "%%");
+ break;
+
+ case 'A':
+ func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
+
+ if ((given & (1 << 24)) != 0)
+ {
+ int offset = given & 0xff;
+
+ if (offset)
+ func (stream, ", #%s%d]%s",
+ ((given & 0x00800000) == 0 ? "-" : ""),
+ offset * 4,
+ ((given & 0x00200000) != 0 ? "!" : ""));
+ else
+ func (stream, "]");
+ }
+ else
+ {
+ int offset = given & 0xff;
+
+ func (stream, "]");
+
+ if (given & (1 << 21))
+ {
+ if (offset)
+ func (stream, ", #%s%d",
+ ((given & 0x00800000) == 0 ? "-" : ""),
+ offset * 4);
+ }
+ else
+ func (stream, ", {%d}", offset);
+ }
+ break;
+
+ case 'B':
+ {
+ int regno = ((given >> 12) & 0xf) | ((given >> (22 - 4)) & 0x10);
+ int offset = (given >> 1) & 0x3f;
+
+ if (offset == 1)
+ func (stream, "{d%d}", regno);
+ else if (regno + offset > 32)
+ func (stream, "{d%d-<overflow reg d%d>}", regno, regno + offset - 1);
+ else
+ func (stream, "{d%d-d%d}", regno, regno + offset - 1);
+ }
+ break;
+
+ case 'C':
+ {
+ int rn = (given >> 16) & 0xf;
+ int offset = (given & 0xff) * 4;
+ int add = (given >> 23) & 1;
+
+ func (stream, "[%s", arm_regnames[rn]);
+
+ if (offset)
+ {
+ if (!add)
+ offset = -offset;
+ func (stream, ", #%d", offset);
+ }
+ func (stream, "]");
+ if (rn == 15)
+ {
+ func (stream, "\t; ");
+ /* FIXME: Unsure if info->bytes_per_chunk is the
+ right thing to use here. */
+ info->print_address_func (offset + pc
+ + info->bytes_per_chunk * 2, info);
+ }
+ }
+ break;
+
+ case 'c':
+ func (stream, "%s", arm_conditional[cond]);
+ break;
+
+ case 'I':
+ /* Print a Cirrus/DSP shift immediate. */
+ /* Immediates are 7bit signed ints with bits 0..3 in
+ bits 0..3 of opcode and bits 4..6 in bits 5..7
+ of opcode. */
+ {
+ int imm;
+
+ imm = (given & 0xf) | ((given & 0xe0) >> 1);
+
+ /* Is ``imm'' a negative number? */
+ if (imm & 0x40)
+ imm |= (-1 << 7);
+
+ func (stream, "%d", imm);
+ }
+
+ break;
+
+ case 'F':
+ switch (given & 0x00408000)
+ {
+ case 0:
+ func (stream, "4");
+ break;
+ case 0x8000:
+ func (stream, "1");
+ break;
+ case 0x00400000:
+ func (stream, "2");
+ break;
+ default:
+ func (stream, "3");
+ }
+ break;
+
+ case 'P':
+ switch (given & 0x00080080)
+ {
+ case 0:
+ func (stream, "s");
+ break;
+ case 0x80:
+ func (stream, "d");
+ break;
+ case 0x00080000:
+ func (stream, "e");
+ break;
+ default:
+ func (stream, _("<illegal precision>"));
+ break;
+ }
+ break;
+ case 'Q':
+ switch (given & 0x00408000)
+ {
+ case 0:
+ func (stream, "s");
+ break;
+ case 0x8000:
+ func (stream, "d");
+ break;
+ case 0x00400000:
+ func (stream, "e");
+ break;
+ default:
+ func (stream, "p");
+ break;
+ }
+ break;
+ case 'R':
+ switch (given & 0x60)
+ {
+ case 0:
+ break;
+ case 0x20:
+ func (stream, "p");
+ break;
+ case 0x40:
+ func (stream, "m");
+ break;
+ default:
+ func (stream, "z");
+ break;
+ }
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ int width;
+ unsigned long value;
+
+ c = arm_decode_bitfield (c, given, &value, &width);
+
+ switch (*c)
+ {
+ case 'r':
+ func (stream, "%s", arm_regnames[value]);
+ break;
+ case 'D':
+ func (stream, "d%ld", value);
+ break;
+ case 'Q':
+ if (value & 1)
+ func (stream, "<illegal reg q%ld.5>", value >> 1);
+ else
+ func (stream, "q%ld", value >> 1);
+ break;
+ case 'd':
+ func (stream, "%ld", value);
+ break;
+ case 'k':
+ {
+ int from = (given & (1 << 7)) ? 32 : 16;
+ func (stream, "%ld", from - value);
+ }
+ break;
+
+ case 'f':
+ if (value > 7)
+ func (stream, "#%s", arm_fp_const[value & 7]);
+ else
+ func (stream, "f%ld", value);
+ break;
+
+ case 'w':
+ if (width == 2)
+ func (stream, "%s", iwmmxt_wwnames[value]);
+ else
+ func (stream, "%s", iwmmxt_wwssnames[value]);
+ break;
+
+ case 'g':
+ func (stream, "%s", iwmmxt_regnames[value]);
+ break;
+ case 'G':
+ func (stream, "%s", iwmmxt_cregnames[value]);
+ break;
+
+ case 'x':
+ func (stream, "0x%lx", value);
+ break;
+
+ case '`':
+ c++;
+ if (value == 0)
+ func (stream, "%c", *c);
+ break;
+ case '\'':
+ c++;
+ if (value == ((1ul << width) - 1))
+ func (stream, "%c", *c);
+ break;
+ case '?':
+ func (stream, "%c", c[(1 << width) - (int)value]);
+ c += 1 << width;
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case 'y':
+ case 'z':
+ {
+ int single = *c++ == 'y';
+ int regno;
+
+ switch (*c)
+ {
+ case '4': /* Sm pair */
+ func (stream, "{");
+ /* Fall through. */
+ case '0': /* Sm, Dm */
+ regno = given & 0x0000000f;
+ if (single)
+ {
+ regno <<= 1;
+ regno += (given >> 5) & 1;
+ }
+ else
+ regno += ((given >> 5) & 1) << 4;
+ break;
+
+ case '1': /* Sd, Dd */
+ regno = (given >> 12) & 0x0000000f;
+ if (single)
+ {
+ regno <<= 1;
+ regno += (given >> 22) & 1;
+ }
+ else
+ regno += ((given >> 22) & 1) << 4;
+ break;
+
+ case '2': /* Sn, Dn */
+ regno = (given >> 16) & 0x0000000f;
+ if (single)
+ {
+ regno <<= 1;
+ regno += (given >> 7) & 1;
+ }
+ else
+ regno += ((given >> 7) & 1) << 4;
+ break;
+
+ case '3': /* List */
+ func (stream, "{");
+ regno = (given >> 12) & 0x0000000f;
+ if (single)
+ {
+ regno <<= 1;
+ regno += (given >> 22) & 1;
+ }
+ else
+ regno += ((given >> 22) & 1) << 4;
+ break;
+
+ default:
+ abort ();
+ }
+
+ func (stream, "%c%d", single ? 's' : 'd', regno);
+
+ if (*c == '3')
+ {
+ int count = given & 0xff;
+
+ if (single == 0)
+ count >>= 1;
+
+ if (--count)
+ {
+ func (stream, "-%c%d",
+ single ? 's' : 'd',
+ regno + count);
+ }
+
+ func (stream, "}");
+ }
+ else if (*c == '4')
+ func (stream, ", %c%d}", single ? 's' : 'd',
+ regno + 1);
+ }
+ break;
+
+ case 'L':
+ switch (given & 0x00400100)
+ {
+ case 0x00000000: func (stream, "b"); break;
+ case 0x00400000: func (stream, "h"); break;
+ case 0x00000100: func (stream, "w"); break;
+ case 0x00400100: func (stream, "d"); break;
+ default:
+ break;
+ }
+ break;
+
+ case 'Z':
+ {
+ int value;
+ /* given (20, 23) | given (0, 3) */
+ value = ((given >> 16) & 0xf0) | (given & 0xf);
+ func (stream, "%d", value);
+ }
+ break;
+
+ case 'l':
+ /* This is like the 'A' operator, except that if
+ the width field "M" is zero, then the offset is
+ *not* multiplied by four. */
+ {
+ int offset = given & 0xff;
+ int multiplier = (given & 0x00000100) ? 4 : 1;
+
+ func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
+
+ if (offset)
+ {
+ if ((given & 0x01000000) != 0)
+ func (stream, ", #%s%d]%s",
+ ((given & 0x00800000) == 0 ? "-" : ""),
+ offset * multiplier,
+ ((given & 0x00200000) != 0 ? "!" : ""));
+ else
+ func (stream, "], #%s%d",
+ ((given & 0x00800000) == 0 ? "-" : ""),
+ offset * multiplier);
+ }
+ else
+ func (stream, "]");
+ }
+ break;
+
+ case 'r':
+ {
+ int imm4 = (given >> 4) & 0xf;
+ int puw_bits = ((given >> 22) & 6) | ((given >> 21) & 1);
+ int ubit = (given >> 23) & 1;
+ const char *rm = arm_regnames [given & 0xf];
+ const char *rn = arm_regnames [(given >> 16) & 0xf];
+
+ switch (puw_bits)
+ {
+ case 1:
+ /* fall through */
+ case 3:
+ func (stream, "[%s], %c%s", rn, ubit ? '+' : '-', rm);
+ if (imm4)
+ func (stream, ", lsl #%d", imm4);
+ break;
+
+ case 4:
+ /* fall through */
+ case 5:
+ /* fall through */
+ case 6:
+ /* fall through */
+ case 7:
+ func (stream, "[%s, %c%s", rn, ubit ? '+' : '-', rm);
+ if (imm4 > 0)
+ func (stream, ", lsl #%d", imm4);
+ func (stream, "]");
+ if (puw_bits == 5 || puw_bits == 7)
+ func (stream, "!");
+ break;
+
+ default:
+ func (stream, "INVALID");
+ }
+ }
+ break;
+
+ case 'i':
+ {
+ long imm5;
+ imm5 = ((given & 0x100) >> 4) | (given & 0xf);
+ func (stream, "%ld", (imm5 == 0) ? 32 : imm5);
+ }
+ break;
+
+ default:
+ abort ();
+ }
+ }
+ }
+ else
+ func (stream, "%c", *c);
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+static void
+print_arm_address (bfd_vma pc, struct disassemble_info *info, long given)
+{
+ void *stream = info->stream;
+ fprintf_function func = info->fprintf_func;
+
+ if (((given & 0x000f0000) == 0x000f0000)
+ && ((given & 0x02000000) == 0))
+ {
+ int offset = given & 0xfff;
+
+ func (stream, "[pc");
+
+ if (given & 0x01000000)
+ {
+ if ((given & 0x00800000) == 0)
+ offset = - offset;
+
+ /* Pre-indexed. */
+ func (stream, ", #%d]", offset);
+
+ offset += pc + 8;
+
+ /* Cope with the possibility of write-back
+ being used. Probably a very dangerous thing
+ for the programmer to do, but who are we to
+ argue ? */
+ if (given & 0x00200000)
+ func (stream, "!");
+ }
+ else
+ {
+ /* Post indexed. */
+ func (stream, "], #%d", offset);
+
+ /* ie ignore the offset. */
+ offset = pc + 8;
+ }
+
+ func (stream, "\t; ");
+ info->print_address_func (offset, info);
+ }
+ else
+ {
+ func (stream, "[%s",
+ arm_regnames[(given >> 16) & 0xf]);
+ if ((given & 0x01000000) != 0)
+ {
+ if ((given & 0x02000000) == 0)
+ {
+ int offset = given & 0xfff;
+ if (offset)
+ func (stream, ", #%s%d",
+ (((given & 0x00800000) == 0)
+ ? "-" : ""), offset);
+ }
+ else
+ {
+ func (stream, ", %s",
+ (((given & 0x00800000) == 0)
+ ? "-" : ""));
+ arm_decode_shift (given, func, stream, 1);
+ }
+
+ func (stream, "]%s",
+ ((given & 0x00200000) != 0) ? "!" : "");
+ }
+ else
+ {
+ if ((given & 0x02000000) == 0)
+ {
+ int offset = given & 0xfff;
+ if (offset)
+ func (stream, "], #%s%d",
+ (((given & 0x00800000) == 0)
+ ? "-" : ""), offset);
+ else
+ func (stream, "]");
+ }
+ else
+ {
+ func (stream, "], %s",
+ (((given & 0x00800000) == 0)
+ ? "-" : ""));
+ arm_decode_shift (given, func, stream, 1);
+ }
+ }
+ }
+}
+
+/* Print one neon instruction on INFO->STREAM.
+ Return true if the instruction matched, false if this is not a
+ recognised neon instruction. */
+
+static bfd_boolean
+print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb)
+{
+ const struct opcode32 *insn;
+ void *stream = info->stream;
+ fprintf_function func = info->fprintf_func;
+
+ if (thumb)
+ {
+ if ((given & 0xef000000) == 0xef000000)
+ {
+ /* move bit 28 to bit 24 to translate Thumb2 to ARM encoding. */
+ unsigned long bit28 = given & (1 << 28);
+
+ given &= 0x00ffffff;
+ if (bit28)
+ given |= 0xf3000000;
+ else
+ given |= 0xf2000000;
+ }
+ else if ((given & 0xff000000) == 0xf9000000)
+ given ^= 0xf9000000 ^ 0xf4000000;
+ else
+ return false;
+ }
+
+ for (insn = neon_opcodes; insn->assembler; insn++)
+ {
+ if ((given & insn->mask) == insn->value)
+ {
+ const char *c;
+
+ for (c = insn->assembler; *c; c++)
+ {
+ if (*c == '%')
+ {
+ switch (*++c)
+ {
+ case '%':
+ func (stream, "%%");
+ break;
+
+ case 'c':
+ if (thumb && ifthen_state)
+ func (stream, "%s", arm_conditional[IFTHEN_COND]);
+ break;
+
+ case 'A':
+ {
+ static const unsigned char enc[16] =
+ {
+ 0x4, 0x14, /* st4 0,1 */
+ 0x4, /* st1 2 */
+ 0x4, /* st2 3 */
+ 0x3, /* st3 4 */
+ 0x13, /* st3 5 */
+ 0x3, /* st1 6 */
+ 0x1, /* st1 7 */
+ 0x2, /* st2 8 */
+ 0x12, /* st2 9 */
+ 0x2, /* st1 10 */
+ 0, 0, 0, 0, 0
+ };
+ int rd = ((given >> 12) & 0xf) | (((given >> 22) & 1) << 4);
+ int rn = ((given >> 16) & 0xf);
+ int rm = ((given >> 0) & 0xf);
+ int align = ((given >> 4) & 0x3);
+ int type = ((given >> 8) & 0xf);
+ int n = enc[type] & 0xf;
+ int stride = (enc[type] >> 4) + 1;
+ int ix;
+
+ func (stream, "{");
+ if (stride > 1)
+ for (ix = 0; ix != n; ix++)
+ func (stream, "%sd%d", ix ? "," : "", rd + ix * stride);
+ else if (n == 1)
+ func (stream, "d%d", rd);
+ else
+ func (stream, "d%d-d%d", rd, rd + n - 1);
+ func (stream, "}, [%s", arm_regnames[rn]);
+ if (align)
+ func (stream, ", :%d", 32 << align);
+ func (stream, "]");
+ if (rm == 0xd)
+ func (stream, "!");
+ else if (rm != 0xf)
+ func (stream, ", %s", arm_regnames[rm]);
+ }
+ break;
+
+ case 'B':
+ {
+ int rd = ((given >> 12) & 0xf) | (((given >> 22) & 1) << 4);
+ int rn = ((given >> 16) & 0xf);
+ int rm = ((given >> 0) & 0xf);
+ int idx_align = ((given >> 4) & 0xf);
+ int align = 0;
+ int size = ((given >> 10) & 0x3);
+ int idx = idx_align >> (size + 1);
+ int length = ((given >> 8) & 3) + 1;
+ int stride = 1;
+ int i;
+
+ if (length > 1 && size > 0)
+ stride = (idx_align & (1 << size)) ? 2 : 1;
+
+ switch (length)
+ {
+ case 1:
+ {
+ int amask = (1 << size) - 1;
+ if ((idx_align & (1 << size)) != 0)
+ return false;
+ if (size > 0)
+ {
+ if ((idx_align & amask) == amask)
+ align = 8 << size;
+ else if ((idx_align & amask) != 0)
+ return false;
+ }
+ }
+ break;
+
+ case 2:
+ if (size == 2 && (idx_align & 2) != 0)
+ return false;
+ align = (idx_align & 1) ? 16 << size : 0;
+ break;
+
+ case 3:
+ if ((size == 2 && (idx_align & 3) != 0)
+ || (idx_align & 1) != 0)
+ return false;
+ break;
+
+ case 4:
+ if (size == 2)
+ {
+ if ((idx_align & 3) == 3)
+ return false;
+ align = (idx_align & 3) * 64;
+ }
+ else
+ align = (idx_align & 1) ? 32 << size : 0;
+ break;
+
+ default:
+ abort ();
+ }
+
+ func (stream, "{");
+ for (i = 0; i < length; i++)
+ func (stream, "%sd%d[%d]", (i == 0) ? "" : ",",
+ rd + i * stride, idx);
+ func (stream, "}, [%s", arm_regnames[rn]);
+ if (align)
+ func (stream, ", :%d", align);
+ func (stream, "]");
+ if (rm == 0xd)
+ func (stream, "!");
+ else if (rm != 0xf)
+ func (stream, ", %s", arm_regnames[rm]);
+ }
+ break;
+
+ case 'C':
+ {
+ int rd = ((given >> 12) & 0xf) | (((given >> 22) & 1) << 4);
+ int rn = ((given >> 16) & 0xf);
+ int rm = ((given >> 0) & 0xf);
+ int align = ((given >> 4) & 0x1);
+ int size = ((given >> 6) & 0x3);
+ int type = ((given >> 8) & 0x3);
+ int n = type + 1;
+ int stride = ((given >> 5) & 0x1);
+ int ix;
+
+ if (stride && (n == 1))
+ n++;
+ else
+ stride++;
+
+ func (stream, "{");
+ if (stride > 1)
+ for (ix = 0; ix != n; ix++)
+ func (stream, "%sd%d[]", ix ? "," : "", rd + ix * stride);
+ else if (n == 1)
+ func (stream, "d%d[]", rd);
+ else
+ func (stream, "d%d[]-d%d[]", rd, rd + n - 1);
+ func (stream, "}, [%s", arm_regnames[rn]);
+ if (align)
+ {
+ int align = (8 * (type + 1)) << size;
+ if (type == 3)
+ align = (size > 1) ? align >> 1 : align;
+ if (type == 2 || (type == 0 && !size))
+ func (stream, ", :<bad align %d>", align);
+ else
+ func (stream, ", :%d", align);
+ }
+ func (stream, "]");
+ if (rm == 0xd)
+ func (stream, "!");
+ else if (rm != 0xf)
+ func (stream, ", %s", arm_regnames[rm]);
+ }
+ break;
+
+ case 'D':
+ {
+ int raw_reg = (given & 0xf) | ((given >> 1) & 0x10);
+ int size = (given >> 20) & 3;
+ int reg = raw_reg & ((4 << size) - 1);
+ int ix = raw_reg >> size >> 2;
+
+ func (stream, "d%d[%d]", reg, ix);
+ }
+ break;
+
+ case 'E':
+ /* Neon encoded constant for mov, mvn, vorr, vbic */
+ {
+ int bits = 0;
+ int cmode = (given >> 8) & 0xf;
+ int op = (given >> 5) & 0x1;
+ unsigned long value = 0, hival = 0;
+ unsigned shift;
+ int size = 0;
+ int isfloat = 0;
+
+ bits |= ((given >> 24) & 1) << 7;
+ bits |= ((given >> 16) & 7) << 4;
+ bits |= ((given >> 0) & 15) << 0;
+
+ if (cmode < 8)
+ {
+ shift = (cmode >> 1) & 3;
+ value = (unsigned long)bits << (8 * shift);
+ size = 32;
+ }
+ else if (cmode < 12)
+ {
+ shift = (cmode >> 1) & 1;
+ value = (unsigned long)bits << (8 * shift);
+ size = 16;
+ }
+ else if (cmode < 14)
+ {
+ shift = (cmode & 1) + 1;
+ value = (unsigned long)bits << (8 * shift);
+ value |= (1ul << (8 * shift)) - 1;
+ size = 32;
+ }
+ else if (cmode == 14)
+ {
+ if (op)
+ {
+ /* bit replication into bytes */
+ int ix;
+ unsigned long mask;
+
+ value = 0;
+ hival = 0;
+ for (ix = 7; ix >= 0; ix--)
+ {
+ mask = ((bits >> ix) & 1) ? 0xff : 0;
+ if (ix <= 3)
+ value = (value << 8) | mask;
+ else
+ hival = (hival << 8) | mask;
+ }
+ size = 64;
+ }
+ else
+ {
+ /* byte replication */
+ value = (unsigned long)bits;
+ size = 8;
+ }
+ }
+ else if (!op)
+ {
+ /* floating point encoding */
+ int tmp;
+
+ value = (unsigned long)(bits & 0x7f) << 19;
+ value |= (unsigned long)(bits & 0x80) << 24;
+ tmp = bits & 0x40 ? 0x3c : 0x40;
+ value |= (unsigned long)tmp << 24;
+ size = 32;
+ isfloat = 1;
+ }
+ else
+ {
+ func (stream, "<illegal constant %.8x:%x:%x>",
+ bits, cmode, op);
+ break;
+ }
+ switch (size)
+ {
+ case 8:
+ func (stream, "#%ld\t; 0x%.2lx", value, value);
+ break;
+
+ case 16:
+ func (stream, "#%ld\t; 0x%.4lx", value, value);
+ break;
+
+ case 32:
+ if (isfloat)
+ {
+ unsigned char valbytes[4];
+ double fvalue;
+
+ /* Do this a byte at a time so we don't have to
+ worry about the host's endianness. */
+ valbytes[0] = value & 0xff;
+ valbytes[1] = (value >> 8) & 0xff;
+ valbytes[2] = (value >> 16) & 0xff;
+ valbytes[3] = (value >> 24) & 0xff;
+
+ floatformat_to_double (valbytes, &fvalue);
+
+ func (stream, "#%.7g\t; 0x%.8lx", fvalue,
+ value);
+ }
+ else
+ func (stream, "#%ld\t; 0x%.8lx",
+ (long) ((value & 0x80000000)
+ ? value | ~0xffffffffl : value), value);
+ break;
+
+ case 64:
+ func (stream, "#0x%.8lx%.8lx", hival, value);
+ break;
+
+ default:
+ abort ();
+ }
+ }
+ break;
+
+ case 'F':
+ {
+ int regno = ((given >> 16) & 0xf) | ((given >> (7 - 4)) & 0x10);
+ int num = (given >> 8) & 0x3;
+
+ if (!num)
+ func (stream, "{d%d}", regno);
+ else if (num + regno >= 32)
+ func (stream, "{d%d-<overflow reg d%d}", regno, regno + num);
+ else
+ func (stream, "{d%d-d%d}", regno, regno + num);
+ }
+ break;
+
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ int width;
+ unsigned long value;
+
+ c = arm_decode_bitfield (c, given, &value, &width);
+
+ switch (*c)
+ {
+ case 'r':
+ func (stream, "%s", arm_regnames[value]);
+ break;
+ case 'd':
+ func (stream, "%ld", value);
+ break;
+ case 'e':
+ func (stream, "%ld", (1ul << width) - value);
+ break;
+
+ case 'S':
+ case 'T':
+ case 'U':
+ /* various width encodings */
+ {
+ int base = 8 << (*c - 'S'); /* 8,16 or 32 */
+ int limit;
+ unsigned low, high;
+
+ c++;
+ if (*c >= '0' && *c <= '9')
+ limit = *c - '0';
+ else if (*c >= 'a' && *c <= 'f')
+ limit = *c - 'a' + 10;
+ else
+ abort ();
+ low = limit >> 2;
+ high = limit & 3;
+
+ if (value < low || value > high)
+ func (stream, "<illegal width %d>", base << value);
+ else
+ func (stream, "%d", base << value);
+ }
+ break;
+ case 'R':
+ if (given & (1 << 6))
+ goto Q;
+ /* FALLTHROUGH */
+ case 'D':
+ func (stream, "d%ld", value);
+ break;
+ case 'Q':
+ Q:
+ if (value & 1)
+ func (stream, "<illegal reg q%ld.5>", value >> 1);
+ else
+ func (stream, "q%ld", value >> 1);
+ break;
+
+ case '`':
+ c++;
+ if (value == 0)
+ func (stream, "%c", *c);
+ break;
+ case '\'':
+ c++;
+ if (value == ((1ul << width) - 1))
+ func (stream, "%c", *c);
+ break;
+ case '?':
+ func (stream, "%c", c[(1 << width) - (int)value]);
+ c += 1 << width;
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ default:
+ abort ();
+ }
+ }
+ }
+ else
+ func (stream, "%c", *c);
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Print one ARM instruction from PC on INFO->STREAM. */
+
+static void
+print_insn_arm_internal (bfd_vma pc, struct disassemble_info *info, long given)
+{
+ const struct opcode32 *insn;
+ void *stream = info->stream;
+ fprintf_function func = info->fprintf_func;
+
+ if (print_insn_coprocessor (pc, info, given, false))
+ return;
+
+ if (print_insn_neon (info, given, false))
+ return;
+
+ for (insn = arm_opcodes; insn->assembler; insn++)
+ {
+ if (insn->value == FIRST_IWMMXT_INSN
+ && info->mach != bfd_mach_arm_XScale
+ && info->mach != bfd_mach_arm_iWMMXt)
+ insn = insn + IWMMXT_INSN_COUNT;
+
+ if ((given & insn->mask) == insn->value
+ /* Special case: an instruction with all bits set in the condition field
+ (0xFnnn_nnnn) is only matched if all those bits are set in insn->mask,
+ or by the catchall at the end of the table. */
+ && ((given & 0xF0000000) != 0xF0000000
+ || (insn->mask & 0xF0000000) == 0xF0000000
+ || (insn->mask == 0 && insn->value == 0)))
+ {
+ const char *c;
+
+ for (c = insn->assembler; *c; c++)
+ {
+ if (*c == '%')
+ {
+ switch (*++c)
+ {
+ case '%':
+ func (stream, "%%");
+ break;
+
+ case 'a':
+ print_arm_address (pc, info, given);
+ break;
+
+ case 'P':
+ /* Set P address bit and use normal address
+ printing routine. */
+ print_arm_address (pc, info, given | (1 << 24));
+ break;
+
+ case 's':
+ if ((given & 0x004f0000) == 0x004f0000)
+ {
+ /* PC relative with immediate offset. */
+ int offset = ((given & 0xf00) >> 4) | (given & 0xf);
+
+ if ((given & 0x00800000) == 0)
+ offset = -offset;
+
+ func (stream, "[pc, #%d]\t; ", offset);
+ info->print_address_func (offset + pc + 8, info);
+ }
+ else
+ {
+ func (stream, "[%s",
+ arm_regnames[(given >> 16) & 0xf]);
+ if ((given & 0x01000000) != 0)
+ {
+ /* Pre-indexed. */
+ if ((given & 0x00400000) == 0x00400000)
+ {
+ /* Immediate. */
+ int offset = ((given & 0xf00) >> 4) | (given & 0xf);
+ if (offset)
+ func (stream, ", #%s%d",
+ (((given & 0x00800000) == 0)
+ ? "-" : ""), offset);
+ }
+ else
+ {
+ /* Register. */
+ func (stream, ", %s%s",
+ (((given & 0x00800000) == 0)
+ ? "-" : ""),
+ arm_regnames[given & 0xf]);
+ }
+
+ func (stream, "]%s",
+ ((given & 0x00200000) != 0) ? "!" : "");
+ }
+ else
+ {
+ /* Post-indexed. */
+ if ((given & 0x00400000) == 0x00400000)
+ {
+ /* Immediate. */
+ int offset = ((given & 0xf00) >> 4) | (given & 0xf);
+ if (offset)
+ func (stream, "], #%s%d",
+ (((given & 0x00800000) == 0)
+ ? "-" : ""), offset);
+ else
+ func (stream, "]");
+ }
+ else
+ {
+ /* Register. */
+ func (stream, "], %s%s",
+ (((given & 0x00800000) == 0)
+ ? "-" : ""),
+ arm_regnames[given & 0xf]);
+ }
+ }
+ }
+ break;
+
+ case 'b':
+ {
+ int disp = (((given & 0xffffff) ^ 0x800000) - 0x800000);
+ info->print_address_func (disp*4 + pc + 8, info);
+ }
+ break;
+
+ case 'c':
+ if (((given >> 28) & 0xf) != 0xe)
+ func (stream, "%s",
+ arm_conditional [(given >> 28) & 0xf]);
+ break;
+
+ case 'm':
+ {
+ int started = 0;
+ int reg;
+
+ func (stream, "{");
+ for (reg = 0; reg < 16; reg++)
+ if ((given & (1 << reg)) != 0)
+ {
+ if (started)
+ func (stream, ", ");
+ started = 1;
+ func (stream, "%s", arm_regnames[reg]);
+ }
+ func (stream, "}");
+ }
+ break;
+
+ case 'q':
+ arm_decode_shift (given, func, stream, 0);
+ break;
+
+ case 'o':
+ if ((given & 0x02000000) != 0)
+ {
+ int rotate = (given & 0xf00) >> 7;
+ int immed = (given & 0xff);
+ immed = (((immed << (32 - rotate))
+ | (immed >> rotate)) & 0xffffffff);
+ func (stream, "#%d\t; 0x%x", immed, immed);
+ }
+ else
+ arm_decode_shift (given, func, stream, 1);
+ break;
+
+ case 'p':
+ if ((given & 0x0000f000) == 0x0000f000)
+ func (stream, "p");
+ break;
+
+ case 't':
+ if ((given & 0x01200000) == 0x00200000)
+ func (stream, "t");
+ break;
+
+ case 'A':
+ func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
+
+ if ((given & (1 << 24)) != 0)
+ {
+ int offset = given & 0xff;
+
+ if (offset)
+ func (stream, ", #%s%d]%s",
+ ((given & 0x00800000) == 0 ? "-" : ""),
+ offset * 4,
+ ((given & 0x00200000) != 0 ? "!" : ""));
+ else
+ func (stream, "]");
+ }
+ else
+ {
+ int offset = given & 0xff;
+
+ func (stream, "]");
+
+ if (given & (1 << 21))
+ {
+ if (offset)
+ func (stream, ", #%s%d",
+ ((given & 0x00800000) == 0 ? "-" : ""),
+ offset * 4);
+ }
+ else
+ func (stream, ", {%d}", offset);
+ }
+ break;
+
+ case 'B':
+ /* Print ARM V5 BLX(1) address: pc+25 bits. */
+ {
+ bfd_vma address;
+ bfd_vma offset = 0;
+
+ if (given & 0x00800000)
+ /* Is signed, hi bits should be ones. */
+ offset = (-1) ^ 0x00ffffff;
+
+ /* Offset is (SignExtend(offset field)<<2). */
+ offset += given & 0x00ffffff;
+ offset <<= 2;
+ address = offset + pc + 8;
+
+ if (given & 0x01000000)
+ /* H bit allows addressing to 2-byte boundaries. */
+ address += 2;
+
+ info->print_address_func (address, info);
+ }
+ break;
+
+ case 'C':
+ func (stream, "_");
+ if (given & 0x80000)
+ func (stream, "f");
+ if (given & 0x40000)
+ func (stream, "s");
+ if (given & 0x20000)
+ func (stream, "x");
+ if (given & 0x10000)
+ func (stream, "c");
+ break;
+
+ case 'U':
+ switch (given & 0xf)
+ {
+ case 0xf: func(stream, "sy"); break;
+ case 0x7: func(stream, "un"); break;
+ case 0xe: func(stream, "st"); break;
+ case 0x6: func(stream, "unst"); break;
+ default:
+ func(stream, "#%d", (int)given & 0xf);
+ break;
+ }
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ int width;
+ unsigned long value;
+
+ c = arm_decode_bitfield (c, given, &value, &width);
+
+ switch (*c)
+ {
+ case 'r':
+ func (stream, "%s", arm_regnames[value]);
+ break;
+ case 'd':
+ func (stream, "%ld", value);
+ break;
+ case 'b':
+ func (stream, "%ld", value * 8);
+ break;
+ case 'W':
+ func (stream, "%ld", value + 1);
+ break;
+ case 'x':
+ func (stream, "0x%08lx", value);
+
+ /* Some SWI instructions have special
+ meanings. */
+ if ((given & 0x0fffffff) == 0x0FF00000)
+ func (stream, "\t; IMB");
+ else if ((given & 0x0fffffff) == 0x0FF00001)
+ func (stream, "\t; IMBRange");
+ break;
+ case 'X':
+ func (stream, "%01lx", value & 0xf);
+ break;
+ case '`':
+ c++;
+ if (value == 0)
+ func (stream, "%c", *c);
+ break;
+ case '\'':
+ c++;
+ if (value == ((1ul << width) - 1))
+ func (stream, "%c", *c);
+ break;
+ case '?':
+ func (stream, "%c", c[(1 << width) - (int)value]);
+ c += 1 << width;
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case 'e':
+ {
+ int imm;
+
+ imm = (given & 0xf) | ((given & 0xfff00) >> 4);
+ func (stream, "%d", imm);
+ }
+ break;
+
+ case 'E':
+ /* LSB and WIDTH fields of BFI or BFC. The machine-
+ language instruction encodes LSB and MSB. */
+ {
+ long msb = (given & 0x001f0000) >> 16;
+ long lsb = (given & 0x00000f80) >> 7;
+
+ long width = msb - lsb + 1;
+ if (width > 0)
+ func (stream, "#%lu, #%lu", lsb, width);
+ else
+ func (stream, "(invalid: %lu:%lu)", lsb, msb);
+ }
+ break;
+
+ case 'V':
+ /* 16-bit unsigned immediate from a MOVT or MOVW
+ instruction, encoded in bits 0:11 and 15:19. */
+ {
+ long hi = (given & 0x000f0000) >> 4;
+ long lo = (given & 0x00000fff);
+ long imm16 = hi | lo;
+ func (stream, "#%lu\t; 0x%lx", imm16, imm16);
+ }
+ break;
+
+ default:
+ abort ();
+ }
+ }
+ }
+ else
+ func (stream, "%c", *c);
+ }
+ return;
+ }
+ }
+ abort ();
+}
+
+/* Print one 16-bit Thumb instruction from PC on INFO->STREAM. */
+
+static void
+print_insn_thumb16 (bfd_vma pc, struct disassemble_info *info, long given)
+{
+ const struct opcode16 *insn;
+ void *stream = info->stream;
+ fprintf_function func = info->fprintf_func;
+
+ for (insn = thumb_opcodes; insn->assembler; insn++)
+ if ((given & insn->mask) == insn->value)
+ {
+ const char *c = insn->assembler;
+ for (; *c; c++)
+ {
+ int domaskpc = 0;
+ int domasklr = 0;
+
+ if (*c != '%')
+ {
+ func (stream, "%c", *c);
+ continue;
+ }
+
+ switch (*++c)
+ {
+ case '%':
+ func (stream, "%%");
+ break;
+
+ case 'c':
+ if (ifthen_state)
+ func (stream, "%s", arm_conditional[IFTHEN_COND]);
+ break;
+
+ case 'C':
+ if (ifthen_state)
+ func (stream, "%s", arm_conditional[IFTHEN_COND]);
+ else
+ func (stream, "s");
+ break;
+
+ case 'I':
+ {
+ unsigned int tmp;
+
+ ifthen_next_state = given & 0xff;
+ for (tmp = given << 1; tmp & 0xf; tmp <<= 1)
+ func (stream, ((given ^ tmp) & 0x10) ? "e" : "t");
+ func (stream, "\t%s", arm_conditional[(given >> 4) & 0xf]);
+ }
+ break;
+
+ case 'x':
+ if (ifthen_next_state)
+ func (stream, "\t; unpredictable branch in IT block\n");
+ break;
+
+ case 'X':
+ if (ifthen_state)
+ func (stream, "\t; unpredictable <IT:%s>",
+ arm_conditional[IFTHEN_COND]);
+ break;
+
+ case 'S':
+ {
+ long reg;
+
+ reg = (given >> 3) & 0x7;
+ if (given & (1 << 6))
+ reg += 8;
+
+ func (stream, "%s", arm_regnames[reg]);
+ }
+ break;
+
+ case 'D':
+ {
+ long reg;
+
+ reg = given & 0x7;
+ if (given & (1 << 7))
+ reg += 8;
+
+ func (stream, "%s", arm_regnames[reg]);
+ }
+ break;
+
+ case 'N':
+ if (given & (1 << 8))
+ domasklr = 1;
+ /* Fall through. */
+ case 'O':
+ if (*c == 'O' && (given & (1 << 8)))
+ domaskpc = 1;
+ /* Fall through. */
+ case 'M':
+ {
+ int started = 0;
+ int reg;
+
+ func (stream, "{");
+
+ /* It would be nice if we could spot
+ ranges, and generate the rS-rE format: */
+ for (reg = 0; (reg < 8); reg++)
+ if ((given & (1 << reg)) != 0)
+ {
+ if (started)
+ func (stream, ", ");
+ started = 1;
+ func (stream, "%s", arm_regnames[reg]);
+ }
+
+ if (domasklr)
+ {
+ if (started)
+ func (stream, ", ");
+ started = 1;
+ func (stream, "%s", arm_regnames[14] /* "lr" */);
+ }
+
+ if (domaskpc)
+ {
+ if (started)
+ func (stream, ", ");
+ func (stream, "%s", arm_regnames[15] /* "pc" */);
+ }
+
+ func (stream, "}");
+ }
+ break;
+
+ case 'b':
+ /* Print ARM V6T2 CZB address: pc+4+6 bits. */
+ {
+ bfd_vma address = (pc + 4
+ + ((given & 0x00f8) >> 2)
+ + ((given & 0x0200) >> 3));
+ info->print_address_func (address, info);
+ }
+ break;
+
+ case 's':
+ /* Right shift immediate -- bits 6..10; 1-31 print
+ as themselves, 0 prints as 32. */
+ {
+ long imm = (given & 0x07c0) >> 6;
+ if (imm == 0)
+ imm = 32;
+ func (stream, "#%ld", imm);
+ }
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ int bitstart = *c++ - '0';
+ int bitend = 0;
+
+ while (*c >= '0' && *c <= '9')
+ bitstart = (bitstart * 10) + *c++ - '0';
+
+ switch (*c)
+ {
+ case '-':
+ {
+ long reg;
+
+ c++;
+ while (*c >= '0' && *c <= '9')
+ bitend = (bitend * 10) + *c++ - '0';
+ if (!bitend)
+ abort ();
+ reg = given >> bitstart;
+ reg &= (2 << (bitend - bitstart)) - 1;
+ switch (*c)
+ {
+ case 'r':
+ func (stream, "%s", arm_regnames[reg]);
+ break;
+
+ case 'd':
+ func (stream, "%ld", reg);
+ break;
+
+ case 'H':
+ func (stream, "%ld", reg << 1);
+ break;
+
+ case 'W':
+ func (stream, "%ld", reg << 2);
+ break;
+
+ case 'a':
+ /* PC-relative address -- the bottom two
+ bits of the address are dropped
+ before the calculation. */
+ info->print_address_func
+ (((pc + 4) & ~3) + (reg << 2), info);
+ break;
+
+ case 'x':
+ func (stream, "0x%04lx", reg);
+ break;
+
+ case 'B':
+ reg = ((reg ^ (1 << bitend)) - (1 << bitend));
+ info->print_address_func (reg * 2 + pc + 4, info);
+ break;
+
+ case 'c':
+ func (stream, "%s", arm_conditional [reg]);
+ break;
+
+ default:
+ abort ();
+ }
+ }
+ break;
+
+ case '\'':
+ c++;
+ if ((given & (1 << bitstart)) != 0)
+ func (stream, "%c", *c);
+ break;
+
+ case '?':
+ ++c;
+ if ((given & (1 << bitstart)) != 0)
+ func (stream, "%c", *c++);
+ else
+ func (stream, "%c", *++c);
+ break;
+
+ default:
+ abort ();
+ }
+ }
+ break;
+
+ default:
+ abort ();
+ }
+ }
+ return;
+ }
+
+ /* No match. */
+ abort ();
+}
+
+/* Return the name of an V7M special register. */
+static const char *
+psr_name (int regno)
+{
+ switch (regno)
+ {
+ case 0: return "APSR";
+ case 1: return "IAPSR";
+ case 2: return "EAPSR";
+ case 3: return "PSR";
+ case 5: return "IPSR";
+ case 6: return "EPSR";
+ case 7: return "IEPSR";
+ case 8: return "MSP";
+ case 9: return "PSP";
+ case 16: return "PRIMASK";
+ case 17: return "BASEPRI";
+ case 18: return "BASEPRI_MASK";
+ case 19: return "FAULTMASK";
+ case 20: return "CONTROL";
+ default: return "<unknown>";
+ }
+}
+
+/* Print one 32-bit Thumb instruction from PC on INFO->STREAM. */
+
+static void
+print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
+{
+ const struct opcode32 *insn;
+ void *stream = info->stream;
+ fprintf_function func = info->fprintf_func;
+
+ if (print_insn_coprocessor (pc, info, given, true))
+ return;
+
+ if (print_insn_neon (info, given, true))
+ return;
+
+ for (insn = thumb32_opcodes; insn->assembler; insn++)
+ if ((given & insn->mask) == insn->value)
+ {
+ const char *c = insn->assembler;
+ for (; *c; c++)
+ {
+ if (*c != '%')
+ {
+ func (stream, "%c", *c);
+ continue;
+ }
+
+ switch (*++c)
+ {
+ case '%':
+ func (stream, "%%");
+ break;
+
+ case 'c':
+ if (ifthen_state)
+ func (stream, "%s", arm_conditional[IFTHEN_COND]);
+ break;
+
+ case 'x':
+ if (ifthen_next_state)
+ func (stream, "\t; unpredictable branch in IT block\n");
+ break;
+
+ case 'X':
+ if (ifthen_state)
+ func (stream, "\t; unpredictable <IT:%s>",
+ arm_conditional[IFTHEN_COND]);
+ break;
+
+ case 'I':
+ {
+ unsigned int imm12 = 0;
+ imm12 |= (given & 0x000000ffu);
+ imm12 |= (given & 0x00007000u) >> 4;
+ imm12 |= (given & 0x04000000u) >> 15;
+ func (stream, "#%u\t; 0x%x", imm12, imm12);
+ }
+ break;
+
+ case 'M':
+ {
+ unsigned int bits = 0, imm, imm8, mod;
+ bits |= (given & 0x000000ffu);
+ bits |= (given & 0x00007000u) >> 4;
+ bits |= (given & 0x04000000u) >> 15;
+ imm8 = (bits & 0x0ff);
+ mod = (bits & 0xf00) >> 8;
+ switch (mod)
+ {
+ case 0: imm = imm8; break;
+ case 1: imm = ((imm8<<16) | imm8); break;
+ case 2: imm = ((imm8<<24) | (imm8 << 8)); break;
+ case 3: imm = ((imm8<<24) | (imm8 << 16) | (imm8 << 8) | imm8); break;
+ default:
+ mod = (bits & 0xf80) >> 7;
+ imm8 = (bits & 0x07f) | 0x80;
+ imm = (((imm8 << (32 - mod)) | (imm8 >> mod)) & 0xffffffff);
+ }
+ func (stream, "#%u\t; 0x%x", imm, imm);
+ }
+ break;
+
+ case 'J':
+ {
+ unsigned int imm = 0;
+ imm |= (given & 0x000000ffu);
+ imm |= (given & 0x00007000u) >> 4;
+ imm |= (given & 0x04000000u) >> 15;
+ imm |= (given & 0x000f0000u) >> 4;
+ func (stream, "#%u\t; 0x%x", imm, imm);
+ }
+ break;
+
+ case 'K':
+ {
+ unsigned int imm = 0;
+ imm |= (given & 0x000f0000u) >> 16;
+ imm |= (given & 0x00000ff0u) >> 0;
+ imm |= (given & 0x0000000fu) << 12;
+ func (stream, "#%u\t; 0x%x", imm, imm);
+ }
+ break;
+
+ case 'S':
+ {
+ unsigned int reg = (given & 0x0000000fu);
+ unsigned int stp = (given & 0x00000030u) >> 4;
+ unsigned int imm = 0;
+ imm |= (given & 0x000000c0u) >> 6;
+ imm |= (given & 0x00007000u) >> 10;
+
+ func (stream, "%s", arm_regnames[reg]);
+ switch (stp)
+ {
+ case 0:
+ if (imm > 0)
+ func (stream, ", lsl #%u", imm);
+ break;
+
+ case 1:
+ if (imm == 0)
+ imm = 32;
+ func (stream, ", lsr #%u", imm);
+ break;
+
+ case 2:
+ if (imm == 0)
+ imm = 32;
+ func (stream, ", asr #%u", imm);
+ break;
+
+ case 3:
+ if (imm == 0)
+ func (stream, ", rrx");
+ else
+ func (stream, ", ror #%u", imm);
+ }
+ }
+ break;
+
+ case 'a':
+ {
+ unsigned int Rn = (given & 0x000f0000) >> 16;
+ unsigned int U = (given & 0x00800000) >> 23;
+ unsigned int op = (given & 0x00000f00) >> 8;
+ unsigned int i12 = (given & 0x00000fff);
+ unsigned int i8 = (given & 0x000000ff);
+ bfd_boolean writeback = false, postind = false;
+ int offset = 0;
+
+ func (stream, "[%s", arm_regnames[Rn]);
+ if (U) /* 12-bit positive immediate offset */
+ offset = i12;
+ else if (Rn == 15) /* 12-bit negative immediate offset */
+ offset = -(int)i12;
+ else if (op == 0x0) /* shifted register offset */
+ {
+ unsigned int Rm = (i8 & 0x0f);
+ unsigned int sh = (i8 & 0x30) >> 4;
+ func (stream, ", %s", arm_regnames[Rm]);
+ if (sh)
+ func (stream, ", lsl #%u", sh);
+ func (stream, "]");
+ break;
+ }
+ else switch (op)
+ {
+ case 0xE: /* 8-bit positive immediate offset */
+ offset = i8;
+ break;
+
+ case 0xC: /* 8-bit negative immediate offset */
+ offset = -i8;
+ break;
+
+ case 0xF: /* 8-bit + preindex with wb */
+ offset = i8;
+ writeback = true;
+ break;
+
+ case 0xD: /* 8-bit - preindex with wb */
+ offset = -i8;
+ writeback = true;
+ break;
+
+ case 0xB: /* 8-bit + postindex */
+ offset = i8;
+ postind = true;
+ break;
+
+ case 0x9: /* 8-bit - postindex */
+ offset = -i8;
+ postind = true;
+ break;
+
+ default:
+ func (stream, ", <undefined>]");
+ goto skip;
+ }
+
+ if (postind)
+ func (stream, "], #%d", offset);
+ else
+ {
+ if (offset)
+ func (stream, ", #%d", offset);
+ func (stream, writeback ? "]!" : "]");
+ }
+
+ if (Rn == 15)
+ {
+ func (stream, "\t; ");
+ info->print_address_func (((pc + 4) & ~3) + offset, info);
+ }
+ }
+ skip:
+ break;
+
+ case 'A':
+ {
+ unsigned int P = (given & 0x01000000) >> 24;
+ unsigned int U = (given & 0x00800000) >> 23;
+ unsigned int W = (given & 0x00400000) >> 21;
+ unsigned int Rn = (given & 0x000f0000) >> 16;
+ unsigned int off = (given & 0x000000ff);
+
+ func (stream, "[%s", arm_regnames[Rn]);
+ if (P)
+ {
+ if (off || !U)
+ func (stream, ", #%c%u", U ? '+' : '-', off * 4);
+ func (stream, "]");
+ if (W)
+ func (stream, "!");
+ }
+ else
+ {
+ func (stream, "], ");
+ if (W)
+ func (stream, "#%c%u", U ? '+' : '-', off * 4);
+ else
+ func (stream, "{%u}", off);
+ }
+ }
+ break;
+
+ case 'w':
+ {
+ unsigned int Sbit = (given & 0x01000000) >> 24;
+ unsigned int type = (given & 0x00600000) >> 21;
+ switch (type)
+ {
+ case 0: func (stream, Sbit ? "sb" : "b"); break;
+ case 1: func (stream, Sbit ? "sh" : "h"); break;
+ case 2:
+ if (Sbit)
+ func (stream, "??");
+ break;
+ case 3:
+ func (stream, "??");
+ break;
+ }
+ }
+ break;
+
+ case 'm':
+ {
+ int started = 0;
+ int reg;
+
+ func (stream, "{");
+ for (reg = 0; reg < 16; reg++)
+ if ((given & (1 << reg)) != 0)
+ {
+ if (started)
+ func (stream, ", ");
+ started = 1;
+ func (stream, "%s", arm_regnames[reg]);
+ }
+ func (stream, "}");
+ }
+ break;
+
+ case 'E':
+ {
+ unsigned int msb = (given & 0x0000001f);
+ unsigned int lsb = 0;
+ lsb |= (given & 0x000000c0u) >> 6;
+ lsb |= (given & 0x00007000u) >> 10;
+ func (stream, "#%u, #%u", lsb, msb - lsb + 1);
+ }
+ break;
+
+ case 'F':
+ {
+ unsigned int width = (given & 0x0000001f) + 1;
+ unsigned int lsb = 0;
+ lsb |= (given & 0x000000c0u) >> 6;
+ lsb |= (given & 0x00007000u) >> 10;
+ func (stream, "#%u, #%u", lsb, width);
+ }
+ break;
+
+ case 'b':
+ {
+ unsigned int S = (given & 0x04000000u) >> 26;
+ unsigned int J1 = (given & 0x00002000u) >> 13;
+ unsigned int J2 = (given & 0x00000800u) >> 11;
+ int offset = 0;
+
+ offset |= !S << 20;
+ offset |= J2 << 19;
+ offset |= J1 << 18;
+ offset |= (given & 0x003f0000) >> 4;
+ offset |= (given & 0x000007ff) << 1;
+ offset -= (1 << 20);
+
+ info->print_address_func (pc + 4 + offset, info);
+ }
+ break;
+
+ case 'B':
+ {
+ unsigned int S = (given & 0x04000000u) >> 26;
+ unsigned int I1 = (given & 0x00002000u) >> 13;
+ unsigned int I2 = (given & 0x00000800u) >> 11;
+ int offset = 0;
+
+ offset |= !S << 24;
+ offset |= !(I1 ^ S) << 23;
+ offset |= !(I2 ^ S) << 22;
+ offset |= (given & 0x03ff0000u) >> 4;
+ offset |= (given & 0x000007ffu) << 1;
+ offset -= (1 << 24);
+ offset += pc + 4;
+
+ /* BLX target addresses are always word aligned. */
+ if ((given & 0x00001000u) == 0)
+ offset &= ~2u;
+
+ info->print_address_func (offset, info);
+ }
+ break;
+
+ case 's':
+ {
+ unsigned int shift = 0;
+ shift |= (given & 0x000000c0u) >> 6;
+ shift |= (given & 0x00007000u) >> 10;
+ if (given & 0x00200000u)
+ func (stream, ", asr #%u", shift);
+ else if (shift)
+ func (stream, ", lsl #%u", shift);
+ /* else print nothing - lsl #0 */
+ }
+ break;
+
+ case 'R':
+ {
+ unsigned int rot = (given & 0x00000030) >> 4;
+ if (rot)
+ func (stream, ", ror #%u", rot * 8);
+ }
+ break;
+
+ case 'U':
+ switch (given & 0xf)
+ {
+ case 0xf: func(stream, "sy"); break;
+ case 0x7: func(stream, "un"); break;
+ case 0xe: func(stream, "st"); break;
+ case 0x6: func(stream, "unst"); break;
+ default:
+ func(stream, "#%d", (int)given & 0xf);
+ break;
+ }
+ break;
+
+ case 'C':
+ if ((given & 0xff) == 0)
+ {
+ func (stream, "%cPSR_", (given & 0x100000) ? 'S' : 'C');
+ if (given & 0x800)
+ func (stream, "f");
+ if (given & 0x400)
+ func (stream, "s");
+ if (given & 0x200)
+ func (stream, "x");
+ if (given & 0x100)
+ func (stream, "c");
+ }
+ else
+ {
+ func (stream, "%s", psr_name (given & 0xff));
+ }
+ break;
+
+ case 'D':
+ if ((given & 0xff) == 0)
+ func (stream, "%cPSR", (given & 0x100000) ? 'S' : 'C');
+ else
+ func (stream, "%s", psr_name (given & 0xff));
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ int width;
+ unsigned long val;
+
+ c = arm_decode_bitfield (c, given, &val, &width);
+
+ switch (*c)
+ {
+ case 'd': func (stream, "%lu", val); break;
+ case 'W': func (stream, "%lu", val * 4); break;
+ case 'r': func (stream, "%s", arm_regnames[val]); break;
+
+ case 'c':
+ func (stream, "%s", arm_conditional[val]);
+ break;
+
+ case '\'':
+ c++;
+ if (val == ((1ul << width) - 1))
+ func (stream, "%c", *c);
+ break;
+
+ case '`':
+ c++;
+ if (val == 0)
+ func (stream, "%c", *c);
+ break;
+
+ case '?':
+ func (stream, "%c", c[(1 << width) - (int)val]);
+ c += 1 << width;
+ break;
+
+ default:
+ abort ();
+ }
+ }
+ break;
+
+ default:
+ abort ();
+ }
+ }
+ return;
+ }
+
+ /* No match. */
+ abort ();
+}
+
+/* Print data bytes on INFO->STREAM. */
+
+static void
+print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED, struct disassemble_info *info,
+ long given)
+{
+ switch (info->bytes_per_chunk)
+ {
+ case 1:
+ info->fprintf_func (info->stream, ".byte\t0x%02lx", given);
+ break;
+ case 2:
+ info->fprintf_func (info->stream, ".short\t0x%04lx", given);
+ break;
+ case 4:
+ info->fprintf_func (info->stream, ".word\t0x%08lx", given);
+ break;
+ default:
+ abort ();
+ }
+}
+
+/* Search back through the insn stream to determine if this instruction is
+ conditionally executed. */
+static void
+find_ifthen_state (bfd_vma pc, struct disassemble_info *info,
+ bfd_boolean little)
+{
+ unsigned char b[2];
+ unsigned int insn;
+ int status;
+ /* COUNT is twice the number of instructions seen. It will be odd if we
+ just crossed an instruction boundary. */
+ int count;
+ int it_count;
+ unsigned int seen_it;
+ bfd_vma addr;
+
+ ifthen_address = pc;
+ ifthen_state = 0;
+
+ addr = pc;
+ count = 1;
+ it_count = 0;
+ seen_it = 0;
+ /* Scan backwards looking for IT instructions, keeping track of where
+ instruction boundaries are. We don't know if something is actually an
+ IT instruction until we find a definite instruction boundary. */
+ for (;;)
+ {
+ if (addr == 0 || info->symbol_at_address_func(addr, info))
+ {
+ /* A symbol must be on an instruction boundary, and will not
+ be within an IT block. */
+ if (seen_it && (count & 1))
+ break;
+
+ return;
+ }
+ addr -= 2;
+ status = info->read_memory_func (addr, (bfd_byte *)b, 2, info);
+ if (status)
+ return;
+
+ if (little)
+ insn = (b[0]) | (b[1] << 8);
+ else
+ insn = (b[1]) | (b[0] << 8);
+ if (seen_it)
+ {
+ if ((insn & 0xf800) < 0xe800)
+ {
+ /* Addr + 2 is an instruction boundary. See if this matches
+ the expected boundary based on the position of the last
+ IT candidate. */
+ if (count & 1)
+ break;
+ seen_it = 0;
+ }
+ }
+ if ((insn & 0xff00) == 0xbf00 && (insn & 0xf) != 0)
+ {
+ /* This could be an IT instruction. */
+ seen_it = insn;
+ it_count = count >> 1;
+ }
+ if ((insn & 0xf800) >= 0xe800)
+ count++;
+ else
+ count = (count + 2) | 1;
+ /* IT blocks contain at most 4 instructions. */
+ if (count >= 8 && !seen_it)
+ return;
+ }
+ /* We found an IT instruction. */
+ ifthen_state = (seen_it & 0xe0) | ((seen_it << it_count) & 0x1f);
+ if ((ifthen_state & 0xf) == 0)
+ ifthen_state = 0;
+}
+
+/* NOTE: There are no checks in these routines that
+ the relevant number of data bytes exist. */
+
+int
+print_insn_arm (bfd_vma pc, struct disassemble_info *info)
+{
+ unsigned char b[4];
+ long given;
+ int status;
+ int is_thumb = false;
+ int is_data = false;
+ unsigned int size = 4;
+ void (*printer) (bfd_vma, struct disassemble_info *, long);
+#if 0
+ bfd_boolean found = false;
+
+ if (info->disassembler_options)
+ {
+ parse_disassembler_options (info->disassembler_options);
+
+ /* To avoid repeated parsing of these options, we remove them here. */
+ info->disassembler_options = NULL;
+ }
+
+ /* First check the full symtab for a mapping symbol, even if there
+ are no usable non-mapping symbols for this address. */
+ if (info->symtab != NULL
+ && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour)
+ {
+ bfd_vma addr;
+ int n;
+ int last_sym = -1;
+ enum map_type type = MAP_ARM;
+
+ if (pc <= last_mapping_addr)
+ last_mapping_sym = -1;
+ is_thumb = (last_type == MAP_THUMB);
+ found = false;
+ /* Start scanning at the start of the function, or wherever
+ we finished last time. */
+ n = info->symtab_pos + 1;
+ if (n < last_mapping_sym)
+ n = last_mapping_sym;
+
+ /* Scan up to the location being disassembled. */
+ for (; n < info->symtab_size; n++)
+ {
+ addr = bfd_asymbol_value (info->symtab[n]);
+ if (addr > pc)
+ break;
+ if ((info->section == NULL
+ || info->section == info->symtab[n]->section)
+ && get_sym_code_type (info, n, &type))
+ {
+ last_sym = n;
+ found = true;
+ }
+ }
+
+ if (!found)
+ {
+ n = info->symtab_pos;
+ if (n < last_mapping_sym - 1)
+ n = last_mapping_sym - 1;
+
+ /* No mapping symbol found at this address. Look backwards
+ for a preceding one. */
+ for (; n >= 0; n--)
+ {
+ if (get_sym_code_type (info, n, &type))
+ {
+ last_sym = n;
+ found = true;
+ break;
+ }
+ }
+ }
+
+ last_mapping_sym = last_sym;
+ last_type = type;
+ is_thumb = (last_type == MAP_THUMB);
+ is_data = (last_type == MAP_DATA);
+
+ /* Look a little bit ahead to see if we should print out
+ two or four bytes of data. If there's a symbol,
+ mapping or otherwise, after two bytes then don't
+ print more. */
+ if (is_data)
+ {
+ size = 4 - (pc & 3);
+ for (n = last_sym + 1; n < info->symtab_size; n++)
+ {
+ addr = bfd_asymbol_value (info->symtab[n]);
+ if (addr > pc)
+ {
+ if (addr - pc < size)
+ size = addr - pc;
+ break;
+ }
+ }
+ /* If the next symbol is after three bytes, we need to
+ print only part of the data, so that we can use either
+ .byte or .short. */
+ if (size == 3)
+ size = (pc & 1) ? 1 : 2;
+ }
+ }
+
+ if (info->symbols != NULL)
+ {
+ if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
+ {
+ coff_symbol_type * cs;
+
+ cs = coffsymbol (*info->symbols);
+ is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT
+ || cs->native->u.syment.n_sclass == C_THUMBSTAT
+ || cs->native->u.syment.n_sclass == C_THUMBLABEL
+ || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
+ || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
+ }
+ else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour
+ && !found)
+ {
+ /* If no mapping symbol has been found then fall back to the type
+ of the function symbol. */
+ elf_symbol_type * es;
+ unsigned int type;
+
+ es = *(elf_symbol_type **)(info->symbols);
+ type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
+
+ is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
+ }
+ }
+#else
+ int little;
+
+ little = (info->endian == BFD_ENDIAN_LITTLE);
+ is_thumb |= (pc & 1);
+ pc &= ~(bfd_vma)1;
+#endif
+
+ if (force_thumb)
+ is_thumb = true;
+
+ info->bytes_per_line = 4;
+
+ if (is_data)
+ {
+ int i;
+
+ /* size was already set above. */
+ info->bytes_per_chunk = size;
+ printer = print_insn_data;
+
+ status = info->read_memory_func (pc, (bfd_byte *)b, size, info);
+ given = 0;
+ if (little)
+ for (i = size - 1; i >= 0; i--)
+ given = b[i] | (given << 8);
+ else
+ for (i = 0; i < (int) size; i++)
+ given = b[i] | (given << 8);
+ }
+ else if (!is_thumb)
+ {
+ /* In ARM mode endianness is a straightforward issue: the instruction
+ is four bytes long and is either ordered 0123 or 3210. */
+ printer = print_insn_arm_internal;
+ info->bytes_per_chunk = 4;
+ size = 4;
+
+ status = info->read_memory_func (pc, (bfd_byte *)b, 4, info);
+ if (little)
+ given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
+ else
+ given = (b[3]) | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
+ }
+ else
+ {
+ /* In Thumb mode we have the additional wrinkle of two
+ instruction lengths. Fortunately, the bits that determine
+ the length of the current instruction are always to be found
+ in the first two bytes. */
+ printer = print_insn_thumb16;
+ info->bytes_per_chunk = 2;
+ size = 2;
+
+ status = info->read_memory_func (pc, (bfd_byte *)b, 2, info);
+ if (little)
+ given = (b[0]) | (b[1] << 8);
+ else
+ given = (b[1]) | (b[0] << 8);
+
+ if (!status)
+ {
+ /* These bit patterns signal a four-byte Thumb
+ instruction. */
+ if ((given & 0xF800) == 0xF800
+ || (given & 0xF800) == 0xF000
+ || (given & 0xF800) == 0xE800)
+ {
+ status = info->read_memory_func (pc + 2, (bfd_byte *)b, 2, info);
+ if (little)
+ given = (b[0]) | (b[1] << 8) | (given << 16);
+ else
+ given = (b[1]) | (b[0] << 8) | (given << 16);
+
+ printer = print_insn_thumb32;
+ size = 4;
+ }
+ }
+
+ if (ifthen_address != pc)
+ find_ifthen_state(pc, info, little);
+
+ if (ifthen_state)
+ {
+ if ((ifthen_state & 0xf) == 0x8)
+ ifthen_next_state = 0;
+ else
+ ifthen_next_state = (ifthen_state & 0xe0)
+ | ((ifthen_state & 0xf) << 1);
+ }
+ }
+
+ if (status)
+ {
+ info->memory_error_func (status, pc, info);
+ return -1;
+ }
+ if (info->flags & INSN_HAS_RELOC)
+ /* If the instruction has a reloc associated with it, then
+ the offset field in the instruction will actually be the
+ addend for the reloc. (We are using REL type relocs).
+ In such cases, we can ignore the pc when computing
+ addresses, since the addend is not currently pc-relative. */
+ pc = 0;
+
+ /* We include the hexdump of the instruction. The format here
+ matches that used by objdump and the ARM ARM (in particular,
+ 32 bit Thumb instructions are displayed as pairs of halfwords,
+ not as a single word.) */
+ if (is_thumb)
+ {
+ if (size == 2)
+ {
+ info->fprintf_func(info->stream, "%04lx ",
+ ((unsigned long)given) & 0xffff);
+ }
+ else
+ {
+ info->fprintf_func(info->stream, "%04lx %04lx ",
+ (((unsigned long)given) >> 16) & 0xffff,
+ ((unsigned long)given) & 0xffff);
+ }
+ }
+ else
+ {
+ info->fprintf_func(info->stream, "%08lx ",
+ ((unsigned long)given) & 0xffffffff);
+ }
+
+ printer (pc, info, given);
+
+ if (is_thumb)
+ {
+ ifthen_state = ifthen_next_state;
+ ifthen_address += size;
+ }
+ return size;
+}
diff --git a/disas/cris.c b/disas/cris.c
new file mode 100644
index 0000000000..9dfb4e3885
--- /dev/null
+++ b/disas/cris.c
@@ -0,0 +1,2871 @@
+/* Disassembler code for CRIS.
+ Copyright 2000, 2001, 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
+ Contributed by Axis Communications AB, Lund, Sweden.
+ Written by Hans-Peter Nilsson.
+
+ This file is part of the GNU binutils and GDB, the GNU debugger.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>. */
+
+#include "qemu-common.h"
+#include "disas/bfd.h"
+//#include "sysdep.h"
+#include "target-cris/opcode-cris.h"
+//#include "libiberty.h"
+
+#define CONST_STRNEQ(STR1,STR2) (strncmp ((STR1), (STR2), sizeof (STR2) - 1) == 0)
+
+/* cris-opc.c -- Table of opcodes for the CRIS processor.
+ Copyright 2000, 2001, 2004 Free Software Foundation, Inc.
+ Contributed by Axis Communications AB, Lund, Sweden.
+ Originally written for GAS 1.38.1 by Mikael Asker.
+ Reorganized by Hans-Peter Nilsson.
+
+This file is part of GAS, GDB and the GNU binutils.
+
+GAS, GDB, and GNU binutils is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2, or (at your
+option) any later version.
+
+GAS, GDB, and GNU binutils are distributed in the hope that they will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef NULL
+#define NULL (0)
+#endif
+
+/* This table isn't used for CRISv32 and the size of immediate operands. */
+const struct cris_spec_reg
+cris_spec_regs[] =
+{
+ {"bz", 0, 1, cris_ver_v32p, NULL},
+ {"p0", 0, 1, 0, NULL},
+ {"vr", 1, 1, 0, NULL},
+ {"p1", 1, 1, 0, NULL},
+ {"pid", 2, 1, cris_ver_v32p, NULL},
+ {"p2", 2, 1, cris_ver_v32p, NULL},
+ {"p2", 2, 1, cris_ver_warning, NULL},
+ {"srs", 3, 1, cris_ver_v32p, NULL},
+ {"p3", 3, 1, cris_ver_v32p, NULL},
+ {"p3", 3, 1, cris_ver_warning, NULL},
+ {"wz", 4, 2, cris_ver_v32p, NULL},
+ {"p4", 4, 2, 0, NULL},
+ {"ccr", 5, 2, cris_ver_v0_10, NULL},
+ {"exs", 5, 4, cris_ver_v32p, NULL},
+ {"p5", 5, 2, cris_ver_v0_10, NULL},
+ {"p5", 5, 4, cris_ver_v32p, NULL},
+ {"dcr0",6, 2, cris_ver_v0_3, NULL},
+ {"eda", 6, 4, cris_ver_v32p, NULL},
+ {"p6", 6, 2, cris_ver_v0_3, NULL},
+ {"p6", 6, 4, cris_ver_v32p, NULL},
+ {"dcr1/mof", 7, 4, cris_ver_v10p,
+ "Register `dcr1/mof' with ambiguous size specified. Guessing 4 bytes"},
+ {"dcr1/mof", 7, 2, cris_ver_v0_3,
+ "Register `dcr1/mof' with ambiguous size specified. Guessing 2 bytes"},
+ {"mof", 7, 4, cris_ver_v10p, NULL},
+ {"dcr1",7, 2, cris_ver_v0_3, NULL},
+ {"p7", 7, 4, cris_ver_v10p, NULL},
+ {"p7", 7, 2, cris_ver_v0_3, NULL},
+ {"dz", 8, 4, cris_ver_v32p, NULL},
+ {"p8", 8, 4, 0, NULL},
+ {"ibr", 9, 4, cris_ver_v0_10, NULL},
+ {"ebp", 9, 4, cris_ver_v32p, NULL},
+ {"p9", 9, 4, 0, NULL},
+ {"irp", 10, 4, cris_ver_v0_10, NULL},
+ {"erp", 10, 4, cris_ver_v32p, NULL},
+ {"p10", 10, 4, 0, NULL},
+ {"srp", 11, 4, 0, NULL},
+ {"p11", 11, 4, 0, NULL},
+ /* For disassembly use only. Accept at assembly with a warning. */
+ {"bar/dtp0", 12, 4, cris_ver_warning,
+ "Ambiguous register `bar/dtp0' specified"},
+ {"nrp", 12, 4, cris_ver_v32p, NULL},
+ {"bar", 12, 4, cris_ver_v8_10, NULL},
+ {"dtp0",12, 4, cris_ver_v0_3, NULL},
+ {"p12", 12, 4, 0, NULL},
+ /* For disassembly use only. Accept at assembly with a warning. */
+ {"dccr/dtp1",13, 4, cris_ver_warning,
+ "Ambiguous register `dccr/dtp1' specified"},
+ {"ccs", 13, 4, cris_ver_v32p, NULL},
+ {"dccr",13, 4, cris_ver_v8_10, NULL},
+ {"dtp1",13, 4, cris_ver_v0_3, NULL},
+ {"p13", 13, 4, 0, NULL},
+ {"brp", 14, 4, cris_ver_v3_10, NULL},
+ {"usp", 14, 4, cris_ver_v32p, NULL},
+ {"p14", 14, 4, cris_ver_v3p, NULL},
+ {"usp", 15, 4, cris_ver_v10, NULL},
+ {"spc", 15, 4, cris_ver_v32p, NULL},
+ {"p15", 15, 4, cris_ver_v10p, NULL},
+ {NULL, 0, 0, cris_ver_version_all, NULL}
+};
+
+/* Add version specifiers to this table when necessary.
+ The (now) regular coding of register names suggests a simpler
+ implementation. */
+const struct cris_support_reg cris_support_regs[] =
+{
+ {"s0", 0},
+ {"s1", 1},
+ {"s2", 2},
+ {"s3", 3},
+ {"s4", 4},
+ {"s5", 5},
+ {"s6", 6},
+ {"s7", 7},
+ {"s8", 8},
+ {"s9", 9},
+ {"s10", 10},
+ {"s11", 11},
+ {"s12", 12},
+ {"s13", 13},
+ {"s14", 14},
+ {"s15", 15},
+ {NULL, 0}
+};
+
+/* All CRIS opcodes are 16 bits.
+
+ - The match component is a mask saying which bits must match a
+ particular opcode in order for an instruction to be an instance
+ of that opcode.
+
+ - The args component is a string containing characters symbolically
+ matching the operands of an instruction. Used for both assembly
+ and disassembly.
+
+ Operand-matching characters:
+ [ ] , space
+ Verbatim.
+ A The string "ACR" (case-insensitive).
+ B Not really an operand. It causes a "BDAP -size,SP" prefix to be
+ output for the PUSH alias-instructions and recognizes a push-
+ prefix at disassembly. This letter isn't recognized for v32.
+ Must be followed by a R or P letter.
+ ! Non-match pattern, will not match if there's a prefix insn.
+ b Non-matching operand, used for branches with 16-bit
+ displacement. Only recognized by the disassembler.
+ c 5-bit unsigned immediate in bits <4:0>.
+ C 4-bit unsigned immediate in bits <3:0>.
+ d At assembly, optionally (as in put other cases before this one)
+ ".d" or ".D" at the start of the operands, followed by one space
+ character. At disassembly, nothing.
+ D General register in bits <15:12> and <3:0>.
+ f List of flags in bits <15:12> and <3:0>.
+ i 6-bit signed immediate in bits <5:0>.
+ I 6-bit unsigned immediate in bits <5:0>.
+ M Size modifier (B, W or D) for CLEAR instructions.
+ m Size modifier (B, W or D) in bits <5:4>
+ N A 32-bit dword, like in the difference between s and y.
+ This has no effect on bits in the opcode. Can also be expressed
+ as "[pc+]" in input.
+ n As N, but PC-relative (to the start of the instruction).
+ o [-128..127] word offset in bits <7:1> and <0>. Used by 8-bit
+ branch instructions.
+ O [-128..127] offset in bits <7:0>. Also matches a comma and a
+ general register after the expression, in bits <15:12>. Used
+ only for the BDAP prefix insn (in v32 the ADDOQ insn; same opcode).
+ P Special register in bits <15:12>.
+ p Indicates that the insn is a prefix insn. Must be first
+ character.
+ Q As O, but don't relax; force an 8-bit offset.
+ R General register in bits <15:12>.
+ r General register in bits <3:0>.
+ S Source operand in bit <10> and a prefix; a 3-operand prefix
+ without side-effect.
+ s Source operand in bits <10> and <3:0>, optionally with a
+ side-effect prefix, except [pc] (the name, not R15 as in ACR)
+ isn't allowed for v32 and higher.
+ T Support register in bits <15:12>.
+ u 4-bit (PC-relative) unsigned immediate word offset in bits <3:0>.
+ U Relaxes to either u or n, instruction is assumed LAPCQ or LAPC.
+ Not recognized at disassembly.
+ x Register-dot-modifier, for example "r5.w" in bits <15:12> and <5:4>.
+ y Like 's' but do not allow an integer at assembly.
+ Y The difference s-y; only an integer is allowed.
+ z Size modifier (B or W) in bit <4>. */
+
+
+/* Please note the order of the opcodes in this table is significant.
+ The assembler requires that all instances of the same mnemonic must
+ be consecutive. If they aren't, the assembler might not recognize
+ them, or may indicate an internal error.
+
+ The disassembler should not normally care about the order of the
+ opcodes, but will prefer an earlier alternative if the "match-score"
+ (see cris-dis.c) is computed as equal.
+
+ It should not be significant for proper execution that this table is
+ in alphabetical order, but please follow that convention for an easy
+ overview. */
+
+const struct cris_opcode
+cris_opcodes[] =
+{
+ {"abs", 0x06B0, 0x0940, "r,R", 0, SIZE_NONE, 0,
+ cris_abs_op},
+
+ {"add", 0x0600, 0x09c0, "m r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"add", 0x0A00, 0x01c0, "m s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"add", 0x0A00, 0x01c0, "m S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"add", 0x0a00, 0x05c0, "m S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_add_sub_cmp_and_or_op},
+
+ {"add", 0x0A00, 0x01c0, "m s,R", 0, SIZE_FIELD,
+ cris_ver_v32p,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"addc", 0x0570, 0x0A80, "r,R", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"addc", 0x09A0, 0x0250, "s,R", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"addi", 0x0540, 0x0A80, "x,r,A", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_addi_op},
+
+ {"addi", 0x0500, 0x0Ac0, "x,r", 0, SIZE_NONE, 0,
+ cris_addi_op},
+
+ /* This collates after "addo", but we want to disassemble as "addoq",
+ not "addo". */
+ {"addoq", 0x0100, 0x0E00, "Q,A", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"addo", 0x0940, 0x0280, "m s,R,A", 0, SIZE_FIELD_SIGNED,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ /* This must be located after the insn above, lest we misinterpret
+ "addo.b -1,r0,acr" as "addo .b-1,r0,acr". FIXME: Sounds like a
+ parser bug. */
+ {"addo", 0x0100, 0x0E00, "O,A", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"addq", 0x0200, 0x0Dc0, "I,R", 0, SIZE_NONE, 0,
+ cris_quick_mode_add_sub_op},
+
+ {"adds", 0x0420, 0x0Bc0, "z r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ /* FIXME: SIZE_FIELD_SIGNED and all necessary changes. */
+ {"adds", 0x0820, 0x03c0, "z s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"adds", 0x0820, 0x03c0, "z S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"adds", 0x0820, 0x07c0, "z S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_add_sub_cmp_and_or_op},
+
+ {"addu", 0x0400, 0x0be0, "z r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes. */
+ {"addu", 0x0800, 0x03e0, "z s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"addu", 0x0800, 0x03e0, "z S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"addu", 0x0800, 0x07e0, "z S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_add_sub_cmp_and_or_op},
+
+ {"and", 0x0700, 0x08C0, "m r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"and", 0x0B00, 0x00C0, "m s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"and", 0x0B00, 0x00C0, "m S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"and", 0x0B00, 0x04C0, "m S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_add_sub_cmp_and_or_op},
+
+ {"andq", 0x0300, 0x0CC0, "i,R", 0, SIZE_NONE, 0,
+ cris_quick_mode_and_cmp_move_or_op},
+
+ {"asr", 0x0780, 0x0840, "m r,R", 0, SIZE_NONE, 0,
+ cris_asr_op},
+
+ {"asrq", 0x03a0, 0x0c40, "c,R", 0, SIZE_NONE, 0,
+ cris_asrq_op},
+
+ {"ax", 0x15B0, 0xEA4F, "", 0, SIZE_NONE, 0,
+ cris_ax_ei_setf_op},
+
+ /* FIXME: Should use branch #defines. */
+ {"b", 0x0dff, 0x0200, "b", 1, SIZE_NONE, 0,
+ cris_sixteen_bit_offset_branch_op},
+
+ {"ba",
+ BA_QUICK_OPCODE,
+ 0x0F00+(0xF-CC_A)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ /* Needs to come after the usual "ba o", which might be relaxed to
+ this one. */
+ {"ba", BA_DWORD_OPCODE,
+ 0xffff & (~BA_DWORD_OPCODE), "n", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_none_reg_mode_jump_op},
+
+ {"bas", 0x0EBF, 0x0140, "n,P", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_none_reg_mode_jump_op},
+
+ {"basc", 0x0EFF, 0x0100, "n,P", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_none_reg_mode_jump_op},
+
+ {"bcc",
+ BRANCH_QUICK_OPCODE+CC_CC*0x1000,
+ 0x0f00+(0xF-CC_CC)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bcs",
+ BRANCH_QUICK_OPCODE+CC_CS*0x1000,
+ 0x0f00+(0xF-CC_CS)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bdap",
+ BDAP_INDIR_OPCODE, BDAP_INDIR_Z_BITS, "pm s,R", 0, SIZE_FIELD_SIGNED,
+ cris_ver_v0_10,
+ cris_bdap_prefix},
+
+ {"bdap",
+ BDAP_QUICK_OPCODE, BDAP_QUICK_Z_BITS, "pO", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_quick_mode_bdap_prefix},
+
+ {"beq",
+ BRANCH_QUICK_OPCODE+CC_EQ*0x1000,
+ 0x0f00+(0xF-CC_EQ)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ /* This is deliberately put before "bext" to trump it, even though not
+ in alphabetical order, since we don't do excluding version checks
+ for v0..v10. */
+ {"bwf",
+ BRANCH_QUICK_OPCODE+CC_EXT*0x1000,
+ 0x0f00+(0xF-CC_EXT)*0x1000, "o", 1, SIZE_NONE,
+ cris_ver_v10,
+ cris_eight_bit_offset_branch_op},
+
+ {"bext",
+ BRANCH_QUICK_OPCODE+CC_EXT*0x1000,
+ 0x0f00+(0xF-CC_EXT)*0x1000, "o", 1, SIZE_NONE,
+ cris_ver_v0_3,
+ cris_eight_bit_offset_branch_op},
+
+ {"bge",
+ BRANCH_QUICK_OPCODE+CC_GE*0x1000,
+ 0x0f00+(0xF-CC_GE)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bgt",
+ BRANCH_QUICK_OPCODE+CC_GT*0x1000,
+ 0x0f00+(0xF-CC_GT)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bhi",
+ BRANCH_QUICK_OPCODE+CC_HI*0x1000,
+ 0x0f00+(0xF-CC_HI)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bhs",
+ BRANCH_QUICK_OPCODE+CC_HS*0x1000,
+ 0x0f00+(0xF-CC_HS)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"biap", BIAP_OPCODE, BIAP_Z_BITS, "pm r,R", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_biap_prefix},
+
+ {"ble",
+ BRANCH_QUICK_OPCODE+CC_LE*0x1000,
+ 0x0f00+(0xF-CC_LE)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"blo",
+ BRANCH_QUICK_OPCODE+CC_LO*0x1000,
+ 0x0f00+(0xF-CC_LO)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bls",
+ BRANCH_QUICK_OPCODE+CC_LS*0x1000,
+ 0x0f00+(0xF-CC_LS)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"blt",
+ BRANCH_QUICK_OPCODE+CC_LT*0x1000,
+ 0x0f00+(0xF-CC_LT)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bmi",
+ BRANCH_QUICK_OPCODE+CC_MI*0x1000,
+ 0x0f00+(0xF-CC_MI)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bmod", 0x0ab0, 0x0140, "s,R", 0, SIZE_FIX_32,
+ cris_ver_sim_v0_10,
+ cris_not_implemented_op},
+
+ {"bmod", 0x0ab0, 0x0140, "S,D", 0, SIZE_NONE,
+ cris_ver_sim_v0_10,
+ cris_not_implemented_op},
+
+ {"bmod", 0x0ab0, 0x0540, "S,R,r", 0, SIZE_NONE,
+ cris_ver_sim_v0_10,
+ cris_not_implemented_op},
+
+ {"bne",
+ BRANCH_QUICK_OPCODE+CC_NE*0x1000,
+ 0x0f00+(0xF-CC_NE)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bound", 0x05c0, 0x0A00, "m r,R", 0, SIZE_NONE, 0,
+ cris_two_operand_bound_op},
+ /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes. */
+ {"bound", 0x09c0, 0x0200, "m s,R", 0, SIZE_FIELD,
+ cris_ver_v0_10,
+ cris_two_operand_bound_op},
+ /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes. */
+ {"bound", 0x0dcf, 0x0200, "m Y,R", 0, SIZE_FIELD, 0,
+ cris_two_operand_bound_op},
+ {"bound", 0x09c0, 0x0200, "m S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_two_operand_bound_op},
+ {"bound", 0x09c0, 0x0600, "m S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_bound_op},
+
+ {"bpl",
+ BRANCH_QUICK_OPCODE+CC_PL*0x1000,
+ 0x0f00+(0xF-CC_PL)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"break", 0xe930, 0x16c0, "C", 0, SIZE_NONE,
+ cris_ver_v3p,
+ cris_break_op},
+
+ {"bsb",
+ BRANCH_QUICK_OPCODE+CC_EXT*0x1000,
+ 0x0f00+(0xF-CC_EXT)*0x1000, "o", 1, SIZE_NONE,
+ cris_ver_v32p,
+ cris_eight_bit_offset_branch_op},
+
+ {"bsr", 0xBEBF, 0x4140, "n", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_none_reg_mode_jump_op},
+
+ {"bsrc", 0xBEFF, 0x4100, "n", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_none_reg_mode_jump_op},
+
+ {"bstore", 0x0af0, 0x0100, "s,R", 0, SIZE_FIX_32,
+ cris_ver_warning,
+ cris_not_implemented_op},
+
+ {"bstore", 0x0af0, 0x0100, "S,D", 0, SIZE_NONE,
+ cris_ver_warning,
+ cris_not_implemented_op},
+
+ {"bstore", 0x0af0, 0x0500, "S,R,r", 0, SIZE_NONE,
+ cris_ver_warning,
+ cris_not_implemented_op},
+
+ {"btst", 0x04F0, 0x0B00, "r,R", 0, SIZE_NONE, 0,
+ cris_btst_nop_op},
+ {"btstq", 0x0380, 0x0C60, "c,R", 0, SIZE_NONE, 0,
+ cris_btst_nop_op},
+
+ {"bvc",
+ BRANCH_QUICK_OPCODE+CC_VC*0x1000,
+ 0x0f00+(0xF-CC_VC)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"bvs",
+ BRANCH_QUICK_OPCODE+CC_VS*0x1000,
+ 0x0f00+(0xF-CC_VS)*0x1000, "o", 1, SIZE_NONE, 0,
+ cris_eight_bit_offset_branch_op},
+
+ {"clear", 0x0670, 0x3980, "M r", 0, SIZE_NONE, 0,
+ cris_reg_mode_clear_op},
+
+ {"clear", 0x0A70, 0x3180, "M y", 0, SIZE_NONE, 0,
+ cris_none_reg_mode_clear_test_op},
+
+ {"clear", 0x0A70, 0x3180, "M S", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_clear_test_op},
+
+ {"clearf", 0x05F0, 0x0A00, "f", 0, SIZE_NONE, 0,
+ cris_clearf_di_op},
+
+ {"cmp", 0x06C0, 0x0900, "m r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"cmp", 0x0Ac0, 0x0100, "m s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"cmp", 0x0Ac0, 0x0100, "m S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"cmpq", 0x02C0, 0x0D00, "i,R", 0, SIZE_NONE, 0,
+ cris_quick_mode_and_cmp_move_or_op},
+
+ /* FIXME: SIZE_FIELD_SIGNED and all necessary changes. */
+ {"cmps", 0x08e0, 0x0300, "z s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"cmps", 0x08e0, 0x0300, "z S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes. */
+ {"cmpu", 0x08c0, 0x0320, "z s,R" , 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"cmpu", 0x08c0, 0x0320, "z S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"di", 0x25F0, 0xDA0F, "", 0, SIZE_NONE, 0,
+ cris_clearf_di_op},
+
+ {"dip", DIP_OPCODE, DIP_Z_BITS, "ps", 0, SIZE_FIX_32,
+ cris_ver_v0_10,
+ cris_dip_prefix},
+
+ {"div", 0x0980, 0x0640, "m R,r", 0, SIZE_FIELD, 0,
+ cris_not_implemented_op},
+
+ {"dstep", 0x06f0, 0x0900, "r,R", 0, SIZE_NONE, 0,
+ cris_dstep_logshift_mstep_neg_not_op},
+
+ {"ei", 0x25B0, 0xDA4F, "", 0, SIZE_NONE, 0,
+ cris_ax_ei_setf_op},
+
+ {"fidxd", 0x0ab0, 0xf540, "[r]", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"fidxi", 0x0d30, 0xF2C0, "[r]", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"ftagd", 0x1AB0, 0xE540, "[r]", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"ftagi", 0x1D30, 0xE2C0, "[r]", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"halt", 0xF930, 0x06CF, "", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"jas", 0x09B0, 0x0640, "r,P", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_reg_mode_jump_op},
+
+ {"jas", 0x0DBF, 0x0240, "N,P", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_reg_mode_jump_op},
+
+ {"jasc", 0x0B30, 0x04C0, "r,P", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_reg_mode_jump_op},
+
+ {"jasc", 0x0F3F, 0x00C0, "N,P", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_reg_mode_jump_op},
+
+ {"jbrc", 0x69b0, 0x9640, "r", 0, SIZE_NONE,
+ cris_ver_v8_10,
+ cris_reg_mode_jump_op},
+
+ {"jbrc", 0x6930, 0x92c0, "s", 0, SIZE_FIX_32,
+ cris_ver_v8_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jbrc", 0x6930, 0x92c0, "S", 0, SIZE_NONE,
+ cris_ver_v8_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jir", 0xA9b0, 0x5640, "r", 0, SIZE_NONE,
+ cris_ver_v8_10,
+ cris_reg_mode_jump_op},
+
+ {"jir", 0xA930, 0x52c0, "s", 0, SIZE_FIX_32,
+ cris_ver_v8_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jir", 0xA930, 0x52c0, "S", 0, SIZE_NONE,
+ cris_ver_v8_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jirc", 0x29b0, 0xd640, "r", 0, SIZE_NONE,
+ cris_ver_v8_10,
+ cris_reg_mode_jump_op},
+
+ {"jirc", 0x2930, 0xd2c0, "s", 0, SIZE_FIX_32,
+ cris_ver_v8_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jirc", 0x2930, 0xd2c0, "S", 0, SIZE_NONE,
+ cris_ver_v8_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jsr", 0xB9b0, 0x4640, "r", 0, SIZE_NONE, 0,
+ cris_reg_mode_jump_op},
+
+ {"jsr", 0xB930, 0x42c0, "s", 0, SIZE_FIX_32,
+ cris_ver_v0_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jsr", 0xBDBF, 0x4240, "N", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_none_reg_mode_jump_op},
+
+ {"jsr", 0xB930, 0x42c0, "S", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jsrc", 0x39b0, 0xc640, "r", 0, SIZE_NONE,
+ cris_ver_v8_10,
+ cris_reg_mode_jump_op},
+
+ {"jsrc", 0x3930, 0xc2c0, "s", 0, SIZE_FIX_32,
+ cris_ver_v8_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jsrc", 0x3930, 0xc2c0, "S", 0, SIZE_NONE,
+ cris_ver_v8_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jsrc", 0xBB30, 0x44C0, "r", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_reg_mode_jump_op},
+
+ {"jsrc", 0xBF3F, 0x40C0, "N", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_reg_mode_jump_op},
+
+ {"jump", 0x09b0, 0xF640, "r", 0, SIZE_NONE, 0,
+ cris_reg_mode_jump_op},
+
+ {"jump",
+ JUMP_INDIR_OPCODE, JUMP_INDIR_Z_BITS, "s", 0, SIZE_FIX_32,
+ cris_ver_v0_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jump",
+ JUMP_INDIR_OPCODE, JUMP_INDIR_Z_BITS, "S", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_jump_op},
+
+ {"jump", 0x09F0, 0x060F, "P", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_none_reg_mode_jump_op},
+
+ {"jump",
+ JUMP_PC_INCR_OPCODE_V32,
+ (0xffff & ~JUMP_PC_INCR_OPCODE_V32), "N", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_none_reg_mode_jump_op},
+
+ {"jmpu", 0x8930, 0x72c0, "s", 0, SIZE_FIX_32,
+ cris_ver_v10,
+ cris_none_reg_mode_jump_op},
+
+ {"jmpu", 0x8930, 0x72c0, "S", 0, SIZE_NONE,
+ cris_ver_v10,
+ cris_none_reg_mode_jump_op},
+
+ {"lapc", 0x0970, 0x0680, "U,R", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"lapc", 0x0D7F, 0x0280, "dn,R", 0, SIZE_FIX_32,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"lapcq", 0x0970, 0x0680, "u,R", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_addi_op},
+
+ {"lsl", 0x04C0, 0x0B00, "m r,R", 0, SIZE_NONE, 0,
+ cris_dstep_logshift_mstep_neg_not_op},
+
+ {"lslq", 0x03c0, 0x0C20, "c,R", 0, SIZE_NONE, 0,
+ cris_dstep_logshift_mstep_neg_not_op},
+
+ {"lsr", 0x07C0, 0x0800, "m r,R", 0, SIZE_NONE, 0,
+ cris_dstep_logshift_mstep_neg_not_op},
+
+ {"lsrq", 0x03e0, 0x0C00, "c,R", 0, SIZE_NONE, 0,
+ cris_dstep_logshift_mstep_neg_not_op},
+
+ {"lz", 0x0730, 0x08C0, "r,R", 0, SIZE_NONE,
+ cris_ver_v3p,
+ cris_not_implemented_op},
+
+ {"mcp", 0x07f0, 0x0800, "P,r", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"move", 0x0640, 0x0980, "m r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"move", 0x0A40, 0x0180, "m s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"move", 0x0A40, 0x0180, "m S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"move", 0x0630, 0x09c0, "r,P", 0, SIZE_NONE, 0,
+ cris_move_to_preg_op},
+
+ {"move", 0x0670, 0x0980, "P,r", 0, SIZE_NONE, 0,
+ cris_reg_mode_move_from_preg_op},
+
+ {"move", 0x0BC0, 0x0000, "m R,y", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"move", 0x0BC0, 0x0000, "m D,S", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"move",
+ MOVE_M_TO_PREG_OPCODE, MOVE_M_TO_PREG_ZBITS,
+ "s,P", 0, SIZE_SPEC_REG, 0,
+ cris_move_to_preg_op},
+
+ {"move", 0x0A30, 0x01c0, "S,P", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_move_to_preg_op},
+
+ {"move", 0x0A70, 0x0180, "P,y", 0, SIZE_SPEC_REG, 0,
+ cris_none_reg_mode_move_from_preg_op},
+
+ {"move", 0x0A70, 0x0180, "P,S", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_move_from_preg_op},
+
+ {"move", 0x0B70, 0x0480, "r,T", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"move", 0x0F70, 0x0080, "T,r", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"movem", 0x0BF0, 0x0000, "R,y", 0, SIZE_FIX_32, 0,
+ cris_move_reg_to_mem_movem_op},
+
+ {"movem", 0x0BF0, 0x0000, "D,S", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_move_reg_to_mem_movem_op},
+
+ {"movem", 0x0BB0, 0x0040, "s,R", 0, SIZE_FIX_32, 0,
+ cris_move_mem_to_reg_movem_op},
+
+ {"movem", 0x0BB0, 0x0040, "S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_move_mem_to_reg_movem_op},
+
+ {"moveq", 0x0240, 0x0D80, "i,R", 0, SIZE_NONE, 0,
+ cris_quick_mode_and_cmp_move_or_op},
+
+ {"movs", 0x0460, 0x0B80, "z r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ /* FIXME: SIZE_FIELD_SIGNED and all necessary changes. */
+ {"movs", 0x0860, 0x0380, "z s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"movs", 0x0860, 0x0380, "z S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"movu", 0x0440, 0x0Ba0, "z r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes. */
+ {"movu", 0x0840, 0x03a0, "z s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"movu", 0x0840, 0x03a0, "z S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"mstep", 0x07f0, 0x0800, "r,R", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_dstep_logshift_mstep_neg_not_op},
+
+ {"muls", 0x0d00, 0x02c0, "m r,R", 0, SIZE_NONE,
+ cris_ver_v10p,
+ cris_muls_op},
+
+ {"mulu", 0x0900, 0x06c0, "m r,R", 0, SIZE_NONE,
+ cris_ver_v10p,
+ cris_mulu_op},
+
+ {"neg", 0x0580, 0x0A40, "m r,R", 0, SIZE_NONE, 0,
+ cris_dstep_logshift_mstep_neg_not_op},
+
+ {"nop", NOP_OPCODE, NOP_Z_BITS, "", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_btst_nop_op},
+
+ {"nop", NOP_OPCODE_V32, NOP_Z_BITS_V32, "", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_btst_nop_op},
+
+ {"not", 0x8770, 0x7880, "r", 0, SIZE_NONE, 0,
+ cris_dstep_logshift_mstep_neg_not_op},
+
+ {"or", 0x0740, 0x0880, "m r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"or", 0x0B40, 0x0080, "m s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"or", 0x0B40, 0x0080, "m S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"or", 0x0B40, 0x0480, "m S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_add_sub_cmp_and_or_op},
+
+ {"orq", 0x0340, 0x0C80, "i,R", 0, SIZE_NONE, 0,
+ cris_quick_mode_and_cmp_move_or_op},
+
+ {"pop", 0x0E6E, 0x0191, "!R", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"pop", 0x0e3e, 0x01c1, "!P", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_move_from_preg_op},
+
+ {"push", 0x0FEE, 0x0011, "BR", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"push", 0x0E7E, 0x0181, "BP", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_move_to_preg_op},
+
+ {"rbf", 0x3b30, 0xc0c0, "y", 0, SIZE_NONE,
+ cris_ver_v10,
+ cris_not_implemented_op},
+
+ {"rbf", 0x3b30, 0xc0c0, "S", 0, SIZE_NONE,
+ cris_ver_v10,
+ cris_not_implemented_op},
+
+ {"rfe", 0x2930, 0xD6CF, "", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"rfg", 0x4930, 0xB6CF, "", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"rfn", 0x5930, 0xA6CF, "", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ {"ret", 0xB67F, 0x4980, "", 1, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_reg_mode_move_from_preg_op},
+
+ {"ret", 0xB9F0, 0x460F, "", 1, SIZE_NONE,
+ cris_ver_v32p,
+ cris_reg_mode_move_from_preg_op},
+
+ {"retb", 0xe67f, 0x1980, "", 1, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_reg_mode_move_from_preg_op},
+
+ {"rete", 0xA9F0, 0x560F, "", 1, SIZE_NONE,
+ cris_ver_v32p,
+ cris_reg_mode_move_from_preg_op},
+
+ {"reti", 0xA67F, 0x5980, "", 1, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_reg_mode_move_from_preg_op},
+
+ {"retn", 0xC9F0, 0x360F, "", 1, SIZE_NONE,
+ cris_ver_v32p,
+ cris_reg_mode_move_from_preg_op},
+
+ {"sbfs", 0x3b70, 0xc080, "y", 0, SIZE_NONE,
+ cris_ver_v10,
+ cris_not_implemented_op},
+
+ {"sbfs", 0x3b70, 0xc080, "S", 0, SIZE_NONE,
+ cris_ver_v10,
+ cris_not_implemented_op},
+
+ {"sa",
+ 0x0530+CC_A*0x1000,
+ 0x0AC0+(0xf-CC_A)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"ssb",
+ 0x0530+CC_EXT*0x1000,
+ 0x0AC0+(0xf-CC_EXT)*0x1000, "r", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_scc_op},
+
+ {"scc",
+ 0x0530+CC_CC*0x1000,
+ 0x0AC0+(0xf-CC_CC)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"scs",
+ 0x0530+CC_CS*0x1000,
+ 0x0AC0+(0xf-CC_CS)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"seq",
+ 0x0530+CC_EQ*0x1000,
+ 0x0AC0+(0xf-CC_EQ)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"setf", 0x05b0, 0x0A40, "f", 0, SIZE_NONE, 0,
+ cris_ax_ei_setf_op},
+
+ {"sfe", 0x3930, 0xC6CF, "", 0, SIZE_NONE,
+ cris_ver_v32p,
+ cris_not_implemented_op},
+
+ /* Need to have "swf" in front of "sext" so it is the one displayed in
+ disassembly. */
+ {"swf",
+ 0x0530+CC_EXT*0x1000,
+ 0x0AC0+(0xf-CC_EXT)*0x1000, "r", 0, SIZE_NONE,
+ cris_ver_v10,
+ cris_scc_op},
+
+ {"sext",
+ 0x0530+CC_EXT*0x1000,
+ 0x0AC0+(0xf-CC_EXT)*0x1000, "r", 0, SIZE_NONE,
+ cris_ver_v0_3,
+ cris_scc_op},
+
+ {"sge",
+ 0x0530+CC_GE*0x1000,
+ 0x0AC0+(0xf-CC_GE)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"sgt",
+ 0x0530+CC_GT*0x1000,
+ 0x0AC0+(0xf-CC_GT)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"shi",
+ 0x0530+CC_HI*0x1000,
+ 0x0AC0+(0xf-CC_HI)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"shs",
+ 0x0530+CC_HS*0x1000,
+ 0x0AC0+(0xf-CC_HS)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"sle",
+ 0x0530+CC_LE*0x1000,
+ 0x0AC0+(0xf-CC_LE)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"slo",
+ 0x0530+CC_LO*0x1000,
+ 0x0AC0+(0xf-CC_LO)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"sls",
+ 0x0530+CC_LS*0x1000,
+ 0x0AC0+(0xf-CC_LS)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"slt",
+ 0x0530+CC_LT*0x1000,
+ 0x0AC0+(0xf-CC_LT)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"smi",
+ 0x0530+CC_MI*0x1000,
+ 0x0AC0+(0xf-CC_MI)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"sne",
+ 0x0530+CC_NE*0x1000,
+ 0x0AC0+(0xf-CC_NE)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"spl",
+ 0x0530+CC_PL*0x1000,
+ 0x0AC0+(0xf-CC_PL)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"sub", 0x0680, 0x0940, "m r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"sub", 0x0a80, 0x0140, "m s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"sub", 0x0a80, 0x0140, "m S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"sub", 0x0a80, 0x0540, "m S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_add_sub_cmp_and_or_op},
+
+ {"subq", 0x0280, 0x0d40, "I,R", 0, SIZE_NONE, 0,
+ cris_quick_mode_add_sub_op},
+
+ {"subs", 0x04a0, 0x0b40, "z r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ /* FIXME: SIZE_FIELD_SIGNED and all necessary changes. */
+ {"subs", 0x08a0, 0x0340, "z s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"subs", 0x08a0, 0x0340, "z S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"subs", 0x08a0, 0x0740, "z S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_add_sub_cmp_and_or_op},
+
+ {"subu", 0x0480, 0x0b60, "z r,R", 0, SIZE_NONE, 0,
+ cris_reg_mode_add_sub_cmp_and_or_move_op},
+
+ /* FIXME: SIZE_FIELD_UNSIGNED and all necessary changes. */
+ {"subu", 0x0880, 0x0360, "z s,R", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"subu", 0x0880, 0x0360, "z S,D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_add_sub_cmp_and_or_move_op},
+
+ {"subu", 0x0880, 0x0760, "z S,R,r", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_three_operand_add_sub_cmp_and_or_op},
+
+ {"svc",
+ 0x0530+CC_VC*0x1000,
+ 0x0AC0+(0xf-CC_VC)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ {"svs",
+ 0x0530+CC_VS*0x1000,
+ 0x0AC0+(0xf-CC_VS)*0x1000, "r", 0, SIZE_NONE, 0,
+ cris_scc_op},
+
+ /* The insn "swapn" is the same as "not" and will be disassembled as
+ such, but the swap* family of mnmonics are generally v8-and-higher
+ only, so count it in. */
+ {"swapn", 0x8770, 0x7880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapw", 0x4770, 0xb880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapnw", 0xc770, 0x3880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapb", 0x2770, 0xd880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapnb", 0xA770, 0x5880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapwb", 0x6770, 0x9880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapnwb", 0xE770, 0x1880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapr", 0x1770, 0xe880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapnr", 0x9770, 0x6880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapwr", 0x5770, 0xa880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapnwr", 0xd770, 0x2880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapbr", 0x3770, 0xc880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapnbr", 0xb770, 0x4880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapwbr", 0x7770, 0x8880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"swapnwbr", 0xf770, 0x0880, "r", 0, SIZE_NONE,
+ cris_ver_v8p,
+ cris_not_implemented_op},
+
+ {"test", 0x0640, 0x0980, "m D", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_reg_mode_test_op},
+
+ {"test", 0x0b80, 0xf040, "m y", 0, SIZE_FIELD, 0,
+ cris_none_reg_mode_clear_test_op},
+
+ {"test", 0x0b80, 0xf040, "m S", 0, SIZE_NONE,
+ cris_ver_v0_10,
+ cris_none_reg_mode_clear_test_op},
+
+ {"xor", 0x07B0, 0x0840, "r,R", 0, SIZE_NONE, 0,
+ cris_xor_op},
+
+ {NULL, 0, 0, NULL, 0, 0, 0, cris_not_implemented_op}
+};
+
+/* Condition-names, indexed by the CC_* numbers as found in cris.h. */
+const char * const
+cris_cc_strings[] =
+{
+ "hs",
+ "lo",
+ "ne",
+ "eq",
+ "vc",
+ "vs",
+ "pl",
+ "mi",
+ "ls",
+ "hi",
+ "ge",
+ "lt",
+ "gt",
+ "le",
+ "a",
+ /* This is a placeholder. In v0, this would be "ext". In v32, this
+ is "sb". See cris_conds15. */
+ "wf"
+};
+
+/* Different names and semantics for condition 1111 (0xf). */
+const struct cris_cond15 cris_cond15s[] =
+{
+ /* FIXME: In what version did condition "ext" disappear? */
+ {"ext", cris_ver_v0_3},
+ {"wf", cris_ver_v10},
+ {"sb", cris_ver_v32p},
+ {NULL, 0}
+};
+
+
+/*
+ * Local variables:
+ * eval: (c-set-style "gnu")
+ * indent-tabs-mode: t
+ * End:
+ */
+
+
+/* No instruction will be disassembled longer than this. In theory, and
+ in silicon, address prefixes can be cascaded. In practice, cascading
+ is not used by GCC, and not supported by the assembler. */
+#ifndef MAX_BYTES_PER_CRIS_INSN
+#define MAX_BYTES_PER_CRIS_INSN 8
+#endif
+
+/* Whether or not to decode prefixes, folding it into the following
+ instruction. FIXME: Make this optional later. */
+#ifndef PARSE_PREFIX
+#define PARSE_PREFIX 1
+#endif
+
+/* Sometimes we prefix all registers with this character. */
+#define REGISTER_PREFIX_CHAR '$'
+
+/* Whether or not to trace the following sequence:
+ sub* X,r%d
+ bound* Y,r%d
+ adds.w [pc+r%d.w],pc
+
+ This is the assembly form of a switch-statement in C.
+ The "sub is optional. If there is none, then X will be zero.
+ X is the value of the first case,
+ Y is the number of cases (including default).
+
+ This results in case offsets printed on the form:
+ case N: -> case_address
+ where N is an estimation on the corresponding 'case' operand in C,
+ and case_address is where execution of that case continues after the
+ sequence presented above.
+
+ The old style of output was to print the offsets as instructions,
+ which made it hard to follow "case"-constructs in the disassembly,
+ and caused a lot of annoying warnings about undefined instructions.
+
+ FIXME: Make this optional later. */
+#ifndef TRACE_CASE
+#define TRACE_CASE (disdata->trace_case)
+#endif
+
+enum cris_disass_family
+ { cris_dis_v0_v10, cris_dis_common_v10_v32, cris_dis_v32 };
+
+/* Stored in the disasm_info->private_data member. */
+struct cris_disasm_data
+{
+ /* Whether to print something less confusing if we find something
+ matching a switch-construct. */
+ bfd_boolean trace_case;
+
+ /* Whether this code is flagged as crisv32. FIXME: Should be an enum
+ that includes "compatible". */
+ enum cris_disass_family distype;
+};
+
+/* Value of first element in switch. */
+static long case_offset = 0;
+
+/* How many more case-offsets to print. */
+static long case_offset_counter = 0;
+
+/* Number of case offsets. */
+static long no_of_case_offsets = 0;
+
+/* Candidate for next case_offset. */
+static long last_immediate = 0;
+
+static int cris_constraint
+ (const char *, unsigned, unsigned, struct cris_disasm_data *);
+
+/* Parse disassembler options and store state in info. FIXME: For the
+ time being, we abuse static variables. */
+
+static bfd_boolean
+cris_parse_disassembler_options (disassemble_info *info,
+ enum cris_disass_family distype)
+{
+ struct cris_disasm_data *disdata;
+
+ info->private_data = calloc (1, sizeof (struct cris_disasm_data));
+ disdata = (struct cris_disasm_data *) info->private_data;
+ if (disdata == NULL)
+ return false;
+
+ /* Default true. */
+ disdata->trace_case
+ = (info->disassembler_options == NULL
+ || (strcmp (info->disassembler_options, "nocase") != 0));
+
+ disdata->distype = distype;
+ return true;
+}
+
+static const struct cris_spec_reg *
+spec_reg_info (unsigned int sreg, enum cris_disass_family distype)
+{
+ int i;
+
+ for (i = 0; cris_spec_regs[i].name != NULL; i++)
+ {
+ if (cris_spec_regs[i].number == sreg)
+ {
+ if (distype == cris_dis_v32)
+ switch (cris_spec_regs[i].applicable_version)
+ {
+ case cris_ver_warning:
+ case cris_ver_version_all:
+ case cris_ver_v3p:
+ case cris_ver_v8p:
+ case cris_ver_v10p:
+ case cris_ver_v32p:
+ /* No ambiguous sizes or register names with CRISv32. */
+ if (cris_spec_regs[i].warning == NULL)
+ return &cris_spec_regs[i];
+ default:
+ ;
+ }
+ else if (cris_spec_regs[i].applicable_version != cris_ver_v32p)
+ return &cris_spec_regs[i];
+ }
+ }
+
+ return NULL;
+}
+
+/* Return the number of bits in the argument. */
+
+static int
+number_of_bits (unsigned int val)
+{
+ int bits;
+
+ for (bits = 0; val != 0; val &= val - 1)
+ bits++;
+
+ return bits;
+}
+
+/* Get an entry in the opcode-table. */
+
+static const struct cris_opcode *
+get_opcode_entry (unsigned int insn,
+ unsigned int prefix_insn,
+ struct cris_disasm_data *disdata)
+{
+ /* For non-prefixed insns, we keep a table of pointers, indexed by the
+ insn code. Each entry is initialized when found to be NULL. */
+ static const struct cris_opcode **opc_table = NULL;
+
+ const struct cris_opcode *max_matchedp = NULL;
+ const struct cris_opcode **prefix_opc_table = NULL;
+
+ /* We hold a table for each prefix that need to be handled differently. */
+ static const struct cris_opcode **dip_prefixes = NULL;
+ static const struct cris_opcode **bdapq_m1_prefixes = NULL;
+ static const struct cris_opcode **bdapq_m2_prefixes = NULL;
+ static const struct cris_opcode **bdapq_m4_prefixes = NULL;
+ static const struct cris_opcode **rest_prefixes = NULL;
+
+ /* Allocate and clear the opcode-table. */
+ if (opc_table == NULL)
+ {
+ opc_table = g_new0(const struct cris_opcode *, 65536);
+ dip_prefixes = g_new0(const struct cris_opcode *, 65536);
+ bdapq_m1_prefixes = g_new0(const struct cris_opcode *, 65536);
+ bdapq_m2_prefixes = g_new0(const struct cris_opcode *, 65536);
+ bdapq_m4_prefixes = g_new0(const struct cris_opcode *, 65536);
+ rest_prefixes = g_new0(const struct cris_opcode *, 65536);
+ }
+
+ /* Get the right table if this is a prefix.
+ This code is connected to cris_constraints in that it knows what
+ prefixes play a role in recognition of patterns; the necessary
+ state is reflected by which table is used. If constraints
+ involving match or non-match of prefix insns are changed, then this
+ probably needs changing too. */
+ if (prefix_insn != NO_CRIS_PREFIX)
+ {
+ const struct cris_opcode *popcodep
+ = (opc_table[prefix_insn] != NULL
+ ? opc_table[prefix_insn]
+ : get_opcode_entry (prefix_insn, NO_CRIS_PREFIX, disdata));
+
+ if (popcodep == NULL)
+ return NULL;
+
+ if (popcodep->match == BDAP_QUICK_OPCODE)
+ {
+ /* Since some offsets are recognized with "push" macros, we
+ have to have different tables for them. */
+ int offset = (prefix_insn & 255);
+
+ if (offset > 127)
+ offset -= 256;
+
+ switch (offset)
+ {
+ case -4:
+ prefix_opc_table = bdapq_m4_prefixes;
+ break;
+
+ case -2:
+ prefix_opc_table = bdapq_m2_prefixes;
+ break;
+
+ case -1:
+ prefix_opc_table = bdapq_m1_prefixes;
+ break;
+
+ default:
+ prefix_opc_table = rest_prefixes;
+ break;
+ }
+ }
+ else if (popcodep->match == DIP_OPCODE)
+ /* We don't allow postincrement when the prefix is DIP, so use a
+ different table for DIP. */
+ prefix_opc_table = dip_prefixes;
+ else
+ prefix_opc_table = rest_prefixes;
+ }
+
+ if (prefix_insn != NO_CRIS_PREFIX
+ && prefix_opc_table[insn] != NULL)
+ max_matchedp = prefix_opc_table[insn];
+ else if (prefix_insn == NO_CRIS_PREFIX && opc_table[insn] != NULL)
+ max_matchedp = opc_table[insn];
+ else
+ {
+ const struct cris_opcode *opcodep;
+ int max_level_of_match = -1;
+
+ for (opcodep = cris_opcodes;
+ opcodep->name != NULL;
+ opcodep++)
+ {
+ int level_of_match;
+
+ if (disdata->distype == cris_dis_v32)
+ {
+ switch (opcodep->applicable_version)
+ {
+ case cris_ver_version_all:
+ break;
+
+ case cris_ver_v0_3:
+ case cris_ver_v0_10:
+ case cris_ver_v3_10:
+ case cris_ver_sim_v0_10:
+ case cris_ver_v8_10:
+ case cris_ver_v10:
+ case cris_ver_warning:
+ continue;
+
+ case cris_ver_v3p:
+ case cris_ver_v8p:
+ case cris_ver_v10p:
+ case cris_ver_v32p:
+ break;
+
+ case cris_ver_v8:
+ abort ();
+ default:
+ abort ();
+ }
+ }
+ else
+ {
+ switch (opcodep->applicable_version)
+ {
+ case cris_ver_version_all:
+ case cris_ver_v0_3:
+ case cris_ver_v3p:
+ case cris_ver_v0_10:
+ case cris_ver_v8p:
+ case cris_ver_v8_10:
+ case cris_ver_v10:
+ case cris_ver_sim_v0_10:
+ case cris_ver_v10p:
+ case cris_ver_warning:
+ break;
+
+ case cris_ver_v32p:
+ continue;
+
+ case cris_ver_v8:
+ abort ();
+ default:
+ abort ();
+ }
+ }
+
+ /* We give a double lead for bits matching the template in
+ cris_opcodes. Not even, because then "move p8,r10" would
+ be given 2 bits lead over "clear.d r10". When there's a
+ tie, the first entry in the table wins. This is
+ deliberate, to avoid a more complicated recognition
+ formula. */
+ if ((opcodep->match & insn) == opcodep->match
+ && (opcodep->lose & insn) == 0
+ && ((level_of_match
+ = cris_constraint (opcodep->args,
+ insn,
+ prefix_insn,
+ disdata))
+ >= 0)
+ && ((level_of_match
+ += 2 * number_of_bits (opcodep->match
+ | opcodep->lose))
+ > max_level_of_match))
+ {
+ max_matchedp = opcodep;
+ max_level_of_match = level_of_match;
+
+ /* If there was a full match, never mind looking
+ further. */
+ if (level_of_match >= 2 * 16)
+ break;
+ }
+ }
+ /* Fill in the new entry.
+
+ If there are changes to the opcode-table involving prefixes, and
+ disassembly then does not work correctly, try removing the
+ else-clause below that fills in the prefix-table. If that
+ helps, you need to change the prefix_opc_table setting above, or
+ something related. */
+ if (prefix_insn == NO_CRIS_PREFIX)
+ opc_table[insn] = max_matchedp;
+ else
+ prefix_opc_table[insn] = max_matchedp;
+ }
+
+ return max_matchedp;
+}
+
+/* Return -1 if the constraints of a bitwise-matched instruction say
+ that there is no match. Otherwise return a nonnegative number
+ indicating the confidence in the match (higher is better). */
+
+static int
+cris_constraint (const char *cs,
+ unsigned int insn,
+ unsigned int prefix_insn,
+ struct cris_disasm_data *disdata)
+{
+ int retval = 0;
+ int tmp;
+ int prefix_ok = 0;
+ const char *s;
+
+ for (s = cs; *s; s++)
+ switch (*s)
+ {
+ case '!':
+ /* Do not recognize "pop" if there's a prefix and then only for
+ v0..v10. */
+ if (prefix_insn != NO_CRIS_PREFIX
+ || disdata->distype != cris_dis_v0_v10)
+ return -1;
+ break;
+
+ case 'U':
+ /* Not recognized at disassembly. */
+ return -1;
+
+ case 'M':
+ /* Size modifier for "clear", i.e. special register 0, 4 or 8.
+ Check that it is one of them. Only special register 12 could
+ be mismatched, but checking for matches is more logical than
+ checking for mismatches when there are only a few cases. */
+ tmp = ((insn >> 12) & 0xf);
+ if (tmp != 0 && tmp != 4 && tmp != 8)
+ return -1;
+ break;
+
+ case 'm':
+ if ((insn & 0x30) == 0x30)
+ return -1;
+ break;
+
+ case 'S':
+ /* A prefix operand without side-effect. */
+ if (prefix_insn != NO_CRIS_PREFIX && (insn & 0x400) == 0)
+ {
+ prefix_ok = 1;
+ break;
+ }
+ else
+ return -1;
+
+ case 's':
+ case 'y':
+ case 'Y':
+ /* If this is a prefixed insn with postincrement (side-effect),
+ the prefix must not be DIP. */
+ if (prefix_insn != NO_CRIS_PREFIX)
+ {
+ if (insn & 0x400)
+ {
+ const struct cris_opcode *prefix_opcodep
+ = get_opcode_entry (prefix_insn, NO_CRIS_PREFIX, disdata);
+
+ if (prefix_opcodep->match == DIP_OPCODE)
+ return -1;
+ }
+
+ prefix_ok = 1;
+ }
+ break;
+
+ case 'B':
+ /* If we don't fall through, then the prefix is ok. */
+ prefix_ok = 1;
+
+ /* A "push" prefix. Check for valid "push" size.
+ In case of special register, it may be != 4. */
+ if (prefix_insn != NO_CRIS_PREFIX)
+ {
+ /* Match the prefix insn to BDAPQ. */
+ const struct cris_opcode *prefix_opcodep
+ = get_opcode_entry (prefix_insn, NO_CRIS_PREFIX, disdata);
+
+ if (prefix_opcodep->match == BDAP_QUICK_OPCODE)
+ {
+ int pushsize = (prefix_insn & 255);
+
+ if (pushsize > 127)
+ pushsize -= 256;
+
+ if (s[1] == 'P')
+ {
+ unsigned int spec_reg = (insn >> 12) & 15;
+ const struct cris_spec_reg *sregp
+ = spec_reg_info (spec_reg, disdata->distype);
+
+ /* For a special-register, the "prefix size" must
+ match the size of the register. */
+ if (sregp && sregp->reg_size == (unsigned int) -pushsize)
+ break;
+ }
+ else if (s[1] == 'R')
+ {
+ if ((insn & 0x30) == 0x20 && pushsize == -4)
+ break;
+ }
+ /* FIXME: Should abort here; next constraint letter
+ *must* be 'P' or 'R'. */
+ }
+ }
+ return -1;
+
+ case 'D':
+ retval = (((insn >> 12) & 15) == (insn & 15));
+ if (!retval)
+ return -1;
+ else
+ retval += 4;
+ break;
+
+ case 'P':
+ {
+ const struct cris_spec_reg *sregp
+ = spec_reg_info ((insn >> 12) & 15, disdata->distype);
+
+ /* Since we match four bits, we will give a value of 4-1 = 3
+ in a match. If there is a corresponding exact match of a
+ special register in another pattern, it will get a value of
+ 4, which will be higher. This should be correct in that an
+ exact pattern would match better than a general pattern.
+
+ Note that there is a reason for not returning zero; the
+ pattern for "clear" is partly matched in the bit-pattern
+ (the two lower bits must be zero), while the bit-pattern
+ for a move from a special register is matched in the
+ register constraint. */
+
+ if (sregp != NULL)
+ {
+ retval += 3;
+ break;
+ }
+ else
+ return -1;
+ }
+ }
+
+ if (prefix_insn != NO_CRIS_PREFIX && ! prefix_ok)
+ return -1;
+
+ return retval;
+}
+
+/* Format number as hex with a leading "0x" into outbuffer. */
+
+static char *
+format_hex (unsigned long number,
+ char *outbuffer,
+ struct cris_disasm_data *disdata)
+{
+ /* Truncate negative numbers on >32-bit hosts. */
+ number &= 0xffffffff;
+
+ sprintf (outbuffer, "0x%lx", number);
+
+ /* Save this value for the "case" support. */
+ if (TRACE_CASE)
+ last_immediate = number;
+
+ return outbuffer + strlen (outbuffer);
+}
+
+/* Format number as decimal into outbuffer. Parameter signedp says
+ whether the number should be formatted as signed (!= 0) or
+ unsigned (== 0). */
+
+static char *
+format_dec (long number, char *outbuffer, int signedp)
+{
+ last_immediate = number;
+ sprintf (outbuffer, signedp ? "%ld" : "%lu", number);
+
+ return outbuffer + strlen (outbuffer);
+}
+
+/* Format the name of the general register regno into outbuffer. */
+
+static char *
+format_reg (struct cris_disasm_data *disdata,
+ int regno,
+ char *outbuffer_start,
+ bfd_boolean with_reg_prefix)
+{
+ char *outbuffer = outbuffer_start;
+
+ if (with_reg_prefix)
+ *outbuffer++ = REGISTER_PREFIX_CHAR;
+
+ switch (regno)
+ {
+ case 15:
+ /* For v32, there is no context in which we output PC. */
+ if (disdata->distype == cris_dis_v32)
+ strcpy (outbuffer, "acr");
+ else
+ strcpy (outbuffer, "pc");
+ break;
+
+ case 14:
+ strcpy (outbuffer, "sp");
+ break;
+
+ default:
+ sprintf (outbuffer, "r%d", regno);
+ break;
+ }
+
+ return outbuffer_start + strlen (outbuffer_start);
+}
+
+/* Format the name of a support register into outbuffer. */
+
+static char *
+format_sup_reg (unsigned int regno,
+ char *outbuffer_start,
+ bfd_boolean with_reg_prefix)
+{
+ char *outbuffer = outbuffer_start;
+ int i;
+
+ if (with_reg_prefix)
+ *outbuffer++ = REGISTER_PREFIX_CHAR;
+
+ for (i = 0; cris_support_regs[i].name != NULL; i++)
+ if (cris_support_regs[i].number == regno)
+ {
+ sprintf (outbuffer, "%s", cris_support_regs[i].name);
+ return outbuffer_start + strlen (outbuffer_start);
+ }
+
+ /* There's supposed to be register names covering all numbers, though
+ some may be generic names. */
+ sprintf (outbuffer, "format_sup_reg-BUG");
+ return outbuffer_start + strlen (outbuffer_start);
+}
+
+/* Return the length of an instruction. */
+
+static unsigned
+bytes_to_skip (unsigned int insn,
+ const struct cris_opcode *matchedp,
+ enum cris_disass_family distype,
+ const struct cris_opcode *prefix_matchedp)
+{
+ /* Each insn is a word plus "immediate" operands. */
+ unsigned to_skip = 2;
+ const char *template = matchedp->args;
+ const char *s;
+
+ for (s = template; *s; s++)
+ if ((*s == 's' || *s == 'N' || *s == 'Y')
+ && (insn & 0x400) && (insn & 15) == 15
+ && prefix_matchedp == NULL)
+ {
+ /* Immediate via [pc+], so we have to check the size of the
+ operand. */
+ int mode_size = 1 << ((insn >> 4) & (*template == 'z' ? 1 : 3));
+
+ if (matchedp->imm_oprnd_size == SIZE_FIX_32)
+ to_skip += 4;
+ else if (matchedp->imm_oprnd_size == SIZE_SPEC_REG)
+ {
+ const struct cris_spec_reg *sregp
+ = spec_reg_info ((insn >> 12) & 15, distype);
+
+ /* FIXME: Improve error handling; should have been caught
+ earlier. */
+ if (sregp == NULL)
+ return 2;
+
+ /* PC is incremented by two, not one, for a byte. Except on
+ CRISv32, where constants are always DWORD-size for
+ special registers. */
+ to_skip +=
+ distype == cris_dis_v32 ? 4 : (sregp->reg_size + 1) & ~1;
+ }
+ else
+ to_skip += (mode_size + 1) & ~1;
+ }
+ else if (*s == 'n')
+ to_skip += 4;
+ else if (*s == 'b')
+ to_skip += 2;
+
+ return to_skip;
+}
+
+/* Print condition code flags. */
+
+static char *
+print_flags (struct cris_disasm_data *disdata, unsigned int insn, char *cp)
+{
+ /* Use the v8 (Etrax 100) flag definitions for disassembly.
+ The differences with v0 (Etrax 1..4) vs. Svinto are:
+ v0 'd' <=> v8 'm'
+ v0 'e' <=> v8 'b'.
+ FIXME: Emit v0..v3 flag names somehow. */
+ static const char v8_fnames[] = "cvznxibm";
+ static const char v32_fnames[] = "cvznxiup";
+ const char *fnames
+ = disdata->distype == cris_dis_v32 ? v32_fnames : v8_fnames;
+
+ unsigned char flagbits = (((insn >> 8) & 0xf0) | (insn & 15));
+ int i;
+
+ for (i = 0; i < 8; i++)
+ if (flagbits & (1 << i))
+ *cp++ = fnames[i];
+
+ return cp;
+}
+
+/* Print out an insn with its operands, and update the info->insn_type
+ fields. The prefix_opcodep and the rest hold a prefix insn that is
+ supposed to be output as an address mode. */
+
+static void
+print_with_operands (const struct cris_opcode *opcodep,
+ unsigned int insn,
+ unsigned char *buffer,
+ bfd_vma addr,
+ disassemble_info *info,
+ /* If a prefix insn was before this insn (and is supposed
+ to be output as an address), here is a description of
+ it. */
+ const struct cris_opcode *prefix_opcodep,
+ unsigned int prefix_insn,
+ unsigned char *prefix_buffer,
+ bfd_boolean with_reg_prefix)
+{
+ /* Get a buffer of somewhat reasonable size where we store
+ intermediate parts of the insn. */
+ char temp[sizeof (".d [$r13=$r12-2147483648],$r10") * 2];
+ char *tp = temp;
+ static const char mode_char[] = "bwd?";
+ const char *s;
+ const char *cs;
+ struct cris_disasm_data *disdata
+ = (struct cris_disasm_data *) info->private_data;
+
+ /* Print out the name first thing we do. */
+ (*info->fprintf_func) (info->stream, "%s", opcodep->name);
+
+ cs = opcodep->args;
+ s = cs;
+
+ /* Ignore any prefix indicator. */
+ if (*s == 'p')
+ s++;
+
+ if (*s == 'm' || *s == 'M' || *s == 'z')
+ {
+ *tp++ = '.';
+
+ /* Get the size-letter. */
+ *tp++ = *s == 'M'
+ ? (insn & 0x8000 ? 'd'
+ : insn & 0x4000 ? 'w' : 'b')
+ : mode_char[(insn >> 4) & (*s == 'z' ? 1 : 3)];
+
+ /* Ignore the size and the space character that follows. */
+ s += 2;
+ }
+
+ /* Add a space if this isn't a long-branch, because for those will add
+ the condition part of the name later. */
+ if (opcodep->match != (BRANCH_PC_LOW + BRANCH_INCR_HIGH * 256))
+ *tp++ = ' ';
+
+ /* Fill in the insn-type if deducible from the name (and there's no
+ better way). */
+ if (opcodep->name[0] == 'j')
+ {
+ if (CONST_STRNEQ (opcodep->name, "jsr"))
+ /* It's "jsr" or "jsrc". */
+ info->insn_type = dis_jsr;
+ else
+ /* Any other jump-type insn is considered a branch. */
+ info->insn_type = dis_branch;
+ }
+
+ /* We might know some more fields right now. */
+ info->branch_delay_insns = opcodep->delayed;
+
+ /* Handle operands. */
+ for (; *s; s++)
+ {
+ switch (*s)
+ {
+ case 'T':
+ tp = format_sup_reg ((insn >> 12) & 15, tp, with_reg_prefix);
+ break;
+
+ case 'A':
+ if (with_reg_prefix)
+ *tp++ = REGISTER_PREFIX_CHAR;
+ *tp++ = 'a';
+ *tp++ = 'c';
+ *tp++ = 'r';
+ break;
+
+ case '[':
+ case ']':
+ case ',':
+ *tp++ = *s;
+ break;
+
+ case '!':
+ /* Ignore at this point; used at earlier stages to avoid
+ recognition if there's a prefix at something that in other
+ ways looks like a "pop". */
+ break;
+
+ case 'd':
+ /* Ignore. This is an optional ".d " on the large one of
+ relaxable insns. */
+ break;
+
+ case 'B':
+ /* This was the prefix that made this a "push". We've already
+ handled it by recognizing it, so signal that the prefix is
+ handled by setting it to NULL. */
+ prefix_opcodep = NULL;
+ break;
+
+ case 'D':
+ case 'r':
+ tp = format_reg (disdata, insn & 15, tp, with_reg_prefix);
+ break;
+
+ case 'R':
+ tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix);
+ break;
+
+ case 'n':
+ {
+ /* Like N but pc-relative to the start of the insn. */
+ unsigned long number
+ = (buffer[2] + buffer[3] * 256 + buffer[4] * 65536
+ + buffer[5] * 0x1000000 + addr);
+
+ /* Finish off and output previous formatted bytes. */
+ *tp = 0;
+ if (temp[0])
+ (*info->fprintf_func) (info->stream, "%s", temp);
+ tp = temp;
+
+ (*info->print_address_func) ((bfd_vma) number, info);
+ }
+ break;
+
+ case 'u':
+ {
+ /* Like n but the offset is bits <3:0> in the instruction. */
+ unsigned long number = (buffer[0] & 0xf) * 2 + addr;
+
+ /* Finish off and output previous formatted bytes. */
+ *tp = 0;
+ if (temp[0])
+ (*info->fprintf_func) (info->stream, "%s", temp);
+ tp = temp;
+
+ (*info->print_address_func) ((bfd_vma) number, info);
+ }
+ break;
+
+ case 'N':
+ case 'y':
+ case 'Y':
+ case 'S':
+ case 's':
+ /* Any "normal" memory operand. */
+ if ((insn & 0x400) && (insn & 15) == 15 && prefix_opcodep == NULL)
+ {
+ /* We're looking at [pc+], i.e. we need to output an immediate
+ number, where the size can depend on different things. */
+ long number;
+ int signedp
+ = ((*cs == 'z' && (insn & 0x20))
+ || opcodep->match == BDAP_QUICK_OPCODE);
+ int nbytes;
+
+ if (opcodep->imm_oprnd_size == SIZE_FIX_32)
+ nbytes = 4;
+ else if (opcodep->imm_oprnd_size == SIZE_SPEC_REG)
+ {
+ const struct cris_spec_reg *sregp
+ = spec_reg_info ((insn >> 12) & 15, disdata->distype);
+
+ /* A NULL return should have been as a non-match earlier,
+ so catch it as an internal error in the error-case
+ below. */
+ if (sregp == NULL)
+ /* Whatever non-valid size. */
+ nbytes = 42;
+ else
+ /* PC is always incremented by a multiple of two.
+ For CRISv32, immediates are always 4 bytes for
+ special registers. */
+ nbytes = disdata->distype == cris_dis_v32
+ ? 4 : (sregp->reg_size + 1) & ~1;
+ }
+ else
+ {
+ int mode_size = 1 << ((insn >> 4) & (*cs == 'z' ? 1 : 3));
+
+ if (mode_size == 1)
+ nbytes = 2;
+ else
+ nbytes = mode_size;
+ }
+
+ switch (nbytes)
+ {
+ case 1:
+ number = buffer[2];
+ if (signedp && number > 127)
+ number -= 256;
+ break;
+
+ case 2:
+ number = buffer[2] + buffer[3] * 256;
+ if (signedp && number > 32767)
+ number -= 65536;
+ break;
+
+ case 4:
+ number
+ = buffer[2] + buffer[3] * 256 + buffer[4] * 65536
+ + buffer[5] * 0x1000000;
+ break;
+
+ default:
+ strcpy (tp, "bug");
+ tp += 3;
+ number = 42;
+ }
+
+ if ((*cs == 'z' && (insn & 0x20))
+ || (opcodep->match == BDAP_QUICK_OPCODE
+ && (nbytes <= 2 || buffer[1 + nbytes] == 0)))
+ tp = format_dec (number, tp, signedp);
+ else
+ {
+ unsigned int highbyte = (number >> 24) & 0xff;
+
+ /* Either output this as an address or as a number. If it's
+ a dword with the same high-byte as the address of the
+ insn, assume it's an address, and also if it's a non-zero
+ non-0xff high-byte. If this is a jsr or a jump, then
+ it's definitely an address. */
+ if (nbytes == 4
+ && (highbyte == ((addr >> 24) & 0xff)
+ || (highbyte != 0 && highbyte != 0xff)
+ || info->insn_type == dis_branch
+ || info->insn_type == dis_jsr))
+ {
+ /* Finish off and output previous formatted bytes. */
+ *tp = 0;
+ tp = temp;
+ if (temp[0])
+ (*info->fprintf_func) (info->stream, "%s", temp);
+
+ (*info->print_address_func) ((bfd_vma) number, info);
+
+ info->target = number;
+ }
+ else
+ tp = format_hex (number, tp, disdata);
+ }
+ }
+ else
+ {
+ /* Not an immediate number. Then this is a (possibly
+ prefixed) memory operand. */
+ if (info->insn_type != dis_nonbranch)
+ {
+ int mode_size
+ = 1 << ((insn >> 4)
+ & (opcodep->args[0] == 'z' ? 1 : 3));
+ int size;
+ info->insn_type = dis_dref;
+ info->flags |= CRIS_DIS_FLAG_MEMREF;
+
+ if (opcodep->imm_oprnd_size == SIZE_FIX_32)
+ size = 4;
+ else if (opcodep->imm_oprnd_size == SIZE_SPEC_REG)
+ {
+ const struct cris_spec_reg *sregp
+ = spec_reg_info ((insn >> 12) & 15, disdata->distype);
+
+ /* FIXME: Improve error handling; should have been caught
+ earlier. */
+ if (sregp == NULL)
+ size = 4;
+ else
+ size = sregp->reg_size;
+ }
+ else
+ size = mode_size;
+
+ info->data_size = size;
+ }
+
+ *tp++ = '[';
+
+ if (prefix_opcodep
+ /* We don't match dip with a postincremented field
+ as a side-effect address mode. */
+ && ((insn & 0x400) == 0
+ || prefix_opcodep->match != DIP_OPCODE))
+ {
+ if (insn & 0x400)
+ {
+ tp = format_reg (disdata, insn & 15, tp, with_reg_prefix);
+ *tp++ = '=';
+ }
+
+
+ /* We mainly ignore the prefix format string when the
+ address-mode syntax is output. */
+ switch (prefix_opcodep->match)
+ {
+ case DIP_OPCODE:
+ /* It's [r], [r+] or [pc+]. */
+ if ((prefix_insn & 0x400) && (prefix_insn & 15) == 15)
+ {
+ /* It's [pc+]. This cannot possibly be anything
+ but an address. */
+ unsigned long number
+ = prefix_buffer[2] + prefix_buffer[3] * 256
+ + prefix_buffer[4] * 65536
+ + prefix_buffer[5] * 0x1000000;
+
+ info->target = (bfd_vma) number;
+
+ /* Finish off and output previous formatted
+ data. */
+ *tp = 0;
+ tp = temp;
+ if (temp[0])
+ (*info->fprintf_func) (info->stream, "%s", temp);
+
+ (*info->print_address_func) ((bfd_vma) number, info);
+ }
+ else
+ {
+ /* For a memref in an address, we use target2.
+ In this case, target is zero. */
+ info->flags
+ |= (CRIS_DIS_FLAG_MEM_TARGET2_IS_REG
+ | CRIS_DIS_FLAG_MEM_TARGET2_MEM);
+
+ info->target2 = prefix_insn & 15;
+
+ *tp++ = '[';
+ tp = format_reg (disdata, prefix_insn & 15, tp,
+ with_reg_prefix);
+ if (prefix_insn & 0x400)
+ *tp++ = '+';
+ *tp++ = ']';
+ }
+ break;
+
+ case BDAP_QUICK_OPCODE:
+ {
+ int number;
+
+ number = prefix_buffer[0];
+ if (number > 127)
+ number -= 256;
+
+ /* Output "reg+num" or, if num < 0, "reg-num". */
+ tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp,
+ with_reg_prefix);
+ if (number >= 0)
+ *tp++ = '+';
+ tp = format_dec (number, tp, 1);
+
+ info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
+ info->target = (prefix_insn >> 12) & 15;
+ info->target2 = (bfd_vma) number;
+ break;
+ }
+
+ case BIAP_OPCODE:
+ /* Output "r+R.m". */
+ tp = format_reg (disdata, prefix_insn & 15, tp,
+ with_reg_prefix);
+ *tp++ = '+';
+ tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp,
+ with_reg_prefix);
+ *tp++ = '.';
+ *tp++ = mode_char[(prefix_insn >> 4) & 3];
+
+ info->flags
+ |= (CRIS_DIS_FLAG_MEM_TARGET2_IS_REG
+ | CRIS_DIS_FLAG_MEM_TARGET_IS_REG
+
+ | ((prefix_insn & 0x8000)
+ ? CRIS_DIS_FLAG_MEM_TARGET2_MULT4
+ : ((prefix_insn & 0x8000)
+ ? CRIS_DIS_FLAG_MEM_TARGET2_MULT2 : 0)));
+
+ /* Is it the casejump? It's a "adds.w [pc+r%d.w],pc". */
+ if (insn == 0xf83f && (prefix_insn & ~0xf000) == 0x55f)
+ /* Then start interpreting data as offsets. */
+ case_offset_counter = no_of_case_offsets;
+ break;
+
+ case BDAP_INDIR_OPCODE:
+ /* Output "r+s.m", or, if "s" is [pc+], "r+s" or
+ "r-s". */
+ tp = format_reg (disdata, (prefix_insn >> 12) & 15, tp,
+ with_reg_prefix);
+
+ if ((prefix_insn & 0x400) && (prefix_insn & 15) == 15)
+ {
+ long number;
+ unsigned int nbytes;
+
+ /* It's a value. Get its size. */
+ int mode_size = 1 << ((prefix_insn >> 4) & 3);
+
+ if (mode_size == 1)
+ nbytes = 2;
+ else
+ nbytes = mode_size;
+
+ switch (nbytes)
+ {
+ case 1:
+ number = prefix_buffer[2];
+ if (number > 127)
+ number -= 256;
+ break;
+
+ case 2:
+ number = prefix_buffer[2] + prefix_buffer[3] * 256;
+ if (number > 32767)
+ number -= 65536;
+ break;
+
+ case 4:
+ number
+ = prefix_buffer[2] + prefix_buffer[3] * 256
+ + prefix_buffer[4] * 65536
+ + prefix_buffer[5] * 0x1000000;
+ break;
+
+ default:
+ strcpy (tp, "bug");
+ tp += 3;
+ number = 42;
+ }
+
+ info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
+ info->target2 = (bfd_vma) number;
+
+ /* If the size is dword, then assume it's an
+ address. */
+ if (nbytes == 4)
+ {
+ /* Finish off and output previous formatted
+ bytes. */
+ *tp++ = '+';
+ *tp = 0;
+ tp = temp;
+ (*info->fprintf_func) (info->stream, "%s", temp);
+
+ (*info->print_address_func) ((bfd_vma) number, info);
+ }
+ else
+ {
+ if (number >= 0)
+ *tp++ = '+';
+ tp = format_dec (number, tp, 1);
+ }
+ }
+ else
+ {
+ /* Output "r+[R].m" or "r+[R+].m". */
+ *tp++ = '+';
+ *tp++ = '[';
+ tp = format_reg (disdata, prefix_insn & 15, tp,
+ with_reg_prefix);
+ if (prefix_insn & 0x400)
+ *tp++ = '+';
+ *tp++ = ']';
+ *tp++ = '.';
+ *tp++ = mode_char[(prefix_insn >> 4) & 3];
+
+ info->flags
+ |= (CRIS_DIS_FLAG_MEM_TARGET2_IS_REG
+ | CRIS_DIS_FLAG_MEM_TARGET2_MEM
+ | CRIS_DIS_FLAG_MEM_TARGET_IS_REG
+
+ | (((prefix_insn >> 4) == 2)
+ ? 0
+ : (((prefix_insn >> 4) & 3) == 1
+ ? CRIS_DIS_FLAG_MEM_TARGET2_MEM_WORD
+ : CRIS_DIS_FLAG_MEM_TARGET2_MEM_BYTE)));
+ }
+ break;
+
+ default:
+ (*info->fprintf_func) (info->stream, "?prefix-bug");
+ }
+
+ /* To mark that the prefix is used, reset it. */
+ prefix_opcodep = NULL;
+ }
+ else
+ {
+ tp = format_reg (disdata, insn & 15, tp, with_reg_prefix);
+
+ info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG;
+ info->target = insn & 15;
+
+ if (insn & 0x400)
+ *tp++ = '+';
+ }
+ *tp++ = ']';
+ }
+ break;
+
+ case 'x':
+ tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix);
+ *tp++ = '.';
+ *tp++ = mode_char[(insn >> 4) & 3];
+ break;
+
+ case 'I':
+ tp = format_dec (insn & 63, tp, 0);
+ break;
+
+ case 'b':
+ {
+ int where = buffer[2] + buffer[3] * 256;
+
+ if (where > 32767)
+ where -= 65536;
+
+ where += addr + ((disdata->distype == cris_dis_v32) ? 0 : 4);
+
+ if (insn == BA_PC_INCR_OPCODE)
+ info->insn_type = dis_branch;
+ else
+ info->insn_type = dis_condbranch;
+
+ info->target = (bfd_vma) where;
+
+ *tp = 0;
+ tp = temp;
+ (*info->fprintf_func) (info->stream, "%s%s ",
+ temp, cris_cc_strings[insn >> 12]);
+
+ (*info->print_address_func) ((bfd_vma) where, info);
+ }
+ break;
+
+ case 'c':
+ tp = format_dec (insn & 31, tp, 0);
+ break;
+
+ case 'C':
+ tp = format_dec (insn & 15, tp, 0);
+ break;
+
+ case 'o':
+ {
+ long offset = insn & 0xfe;
+ bfd_vma target;
+
+ if (insn & 1)
+ offset |= ~0xff;
+
+ if (opcodep->match == BA_QUICK_OPCODE)
+ info->insn_type = dis_branch;
+ else
+ info->insn_type = dis_condbranch;
+
+ target = addr + ((disdata->distype == cris_dis_v32) ? 0 : 2) + offset;
+ info->target = target;
+ *tp = 0;
+ tp = temp;
+ (*info->fprintf_func) (info->stream, "%s", temp);
+ (*info->print_address_func) (target, info);
+ }
+ break;
+
+ case 'Q':
+ case 'O':
+ {
+ long number = buffer[0];
+
+ if (number > 127)
+ number = number - 256;
+
+ tp = format_dec (number, tp, 1);
+ *tp++ = ',';
+ tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix);
+ }
+ break;
+
+ case 'f':
+ tp = print_flags (disdata, insn, tp);
+ break;
+
+ case 'i':
+ tp = format_dec ((insn & 32) ? (insn & 31) | ~31L : insn & 31, tp, 1);
+ break;
+
+ case 'P':
+ {
+ const struct cris_spec_reg *sregp
+ = spec_reg_info ((insn >> 12) & 15, disdata->distype);
+
+ if (sregp->name == NULL)
+ /* Should have been caught as a non-match eariler. */
+ *tp++ = '?';
+ else
+ {
+ if (with_reg_prefix)
+ *tp++ = REGISTER_PREFIX_CHAR;
+ strcpy (tp, sregp->name);
+ tp += strlen (tp);
+ }
+ }
+ break;
+
+ default:
+ strcpy (tp, "???");
+ tp += 3;
+ }
+ }
+
+ *tp = 0;
+
+ if (prefix_opcodep)
+ (*info->fprintf_func) (info->stream, " (OOPS unused prefix \"%s: %s\")",
+ prefix_opcodep->name, prefix_opcodep->args);
+
+ (*info->fprintf_func) (info->stream, "%s", temp);
+
+ /* Get info for matching case-tables, if we don't have any active.
+ We assume that the last constant seen is used; either in the insn
+ itself or in a "move.d const,rN, sub.d rN,rM"-like sequence. */
+ if (TRACE_CASE && case_offset_counter == 0)
+ {
+ if (CONST_STRNEQ (opcodep->name, "sub"))
+ case_offset = last_immediate;
+
+ /* It could also be an "add", if there are negative case-values. */
+ else if (CONST_STRNEQ (opcodep->name, "add"))
+ /* The first case is the negated operand to the add. */
+ case_offset = -last_immediate;
+
+ /* A bound insn will tell us the number of cases. */
+ else if (CONST_STRNEQ (opcodep->name, "bound"))
+ no_of_case_offsets = last_immediate + 1;
+
+ /* A jump or jsr or branch breaks the chain of insns for a
+ case-table, so assume default first-case again. */
+ else if (info->insn_type == dis_jsr
+ || info->insn_type == dis_branch
+ || info->insn_type == dis_condbranch)
+ case_offset = 0;
+ }
+}
+
+
+/* Print the CRIS instruction at address memaddr on stream. Returns
+ length of the instruction, in bytes. Prefix register names with `$' if
+ WITH_REG_PREFIX. */
+
+static int
+print_insn_cris_generic (bfd_vma memaddr,
+ disassemble_info *info,
+ bfd_boolean with_reg_prefix)
+{
+ int nbytes;
+ unsigned int insn;
+ const struct cris_opcode *matchedp;
+ int advance = 0;
+ struct cris_disasm_data *disdata
+ = (struct cris_disasm_data *) info->private_data;
+
+ /* No instruction will be disassembled as longer than this number of
+ bytes; stacked prefixes will not be expanded. */
+ unsigned char buffer[MAX_BYTES_PER_CRIS_INSN];
+ unsigned char *bufp;
+ int status = 0;
+ bfd_vma addr;
+
+ /* There will be an "out of range" error after the last instruction.
+ Reading pairs of bytes in decreasing number, we hope that we will get
+ at least the amount that we will consume.
+
+ If we can't get any data, or we do not get enough data, we print
+ the error message. */
+
+ nbytes = info->buffer_length;
+ if (nbytes > MAX_BYTES_PER_CRIS_INSN)
+ nbytes = MAX_BYTES_PER_CRIS_INSN;
+ status = (*info->read_memory_func) (memaddr, buffer, nbytes, info);
+
+ /* If we did not get all we asked for, then clear the rest.
+ Hopefully this makes a reproducible result in case of errors. */
+ if (nbytes != MAX_BYTES_PER_CRIS_INSN)
+ memset (buffer + nbytes, 0, MAX_BYTES_PER_CRIS_INSN - nbytes);
+
+ addr = memaddr;
+ bufp = buffer;
+
+ /* Set some defaults for the insn info. */
+ info->insn_info_valid = 1;
+ info->branch_delay_insns = 0;
+ info->data_size = 0;
+ info->insn_type = dis_nonbranch;
+ info->flags = 0;
+ info->target = 0;
+ info->target2 = 0;
+
+ /* If we got any data, disassemble it. */
+ if (nbytes != 0)
+ {
+ matchedp = NULL;
+
+ insn = bufp[0] + bufp[1] * 256;
+
+ /* If we're in a case-table, don't disassemble the offsets. */
+ if (TRACE_CASE && case_offset_counter != 0)
+ {
+ info->insn_type = dis_noninsn;
+ advance += 2;
+
+ /* If to print data as offsets, then shortcut here. */
+ (*info->fprintf_func) (info->stream, "case %ld%s: -> ",
+ case_offset + no_of_case_offsets
+ - case_offset_counter,
+ case_offset_counter == 1 ? "/default" :
+ "");
+
+ (*info->print_address_func) ((bfd_vma)
+ ((short) (insn)
+ + (long) (addr
+ - (no_of_case_offsets
+ - case_offset_counter)
+ * 2)), info);
+ case_offset_counter--;
+
+ /* The default case start (without a "sub" or "add") must be
+ zero. */
+ if (case_offset_counter == 0)
+ case_offset = 0;
+ }
+ else if (insn == 0)
+ {
+ /* We're often called to disassemble zeroes. While this is a
+ valid "bcc .+2" insn, it is also useless enough and enough
+ of a nuiscance that we will just output "bcc .+2" for it
+ and signal it as a noninsn. */
+ (*info->fprintf_func) (info->stream,
+ disdata->distype == cris_dis_v32
+ ? "bcc ." : "bcc .+2");
+ info->insn_type = dis_noninsn;
+ advance += 2;
+ }
+ else
+ {
+ const struct cris_opcode *prefix_opcodep = NULL;
+ unsigned char *prefix_buffer = bufp;
+ unsigned int prefix_insn = insn;
+ int prefix_size = 0;
+
+ matchedp = get_opcode_entry (insn, NO_CRIS_PREFIX, disdata);
+
+ /* Check if we're supposed to write out prefixes as address
+ modes and if this was a prefix. */
+ if (matchedp != NULL && PARSE_PREFIX && matchedp->args[0] == 'p')
+ {
+ /* If it's a prefix, put it into the prefix vars and get the
+ main insn. */
+ prefix_size = bytes_to_skip (prefix_insn, matchedp,
+ disdata->distype, NULL);
+ prefix_opcodep = matchedp;
+
+ insn = bufp[prefix_size] + bufp[prefix_size + 1] * 256;
+ matchedp = get_opcode_entry (insn, prefix_insn, disdata);
+
+ if (matchedp != NULL)
+ {
+ addr += prefix_size;
+ bufp += prefix_size;
+ advance += prefix_size;
+ }
+ else
+ {
+ /* The "main" insn wasn't valid, at least not when
+ prefixed. Put back things enough to output the
+ prefix insn only, as a normal insn. */
+ matchedp = prefix_opcodep;
+ insn = prefix_insn;
+ prefix_opcodep = NULL;
+ }
+ }
+
+ if (matchedp == NULL)
+ {
+ (*info->fprintf_func) (info->stream, "??0x%x", insn);
+ advance += 2;
+
+ info->insn_type = dis_noninsn;
+ }
+ else
+ {
+ advance
+ += bytes_to_skip (insn, matchedp, disdata->distype,
+ prefix_opcodep);
+
+ /* The info_type and assorted fields will be set according
+ to the operands. */
+ print_with_operands (matchedp, insn, bufp, addr, info,
+ prefix_opcodep, prefix_insn,
+ prefix_buffer, with_reg_prefix);
+ }
+ }
+ }
+ else
+ info->insn_type = dis_noninsn;
+
+ /* If we read less than MAX_BYTES_PER_CRIS_INSN, i.e. we got an error
+ status when reading that much, and the insn decoding indicated a
+ length exceeding what we read, there is an error. */
+ if (status != 0 && (nbytes == 0 || advance > nbytes))
+ {
+ (*info->memory_error_func) (status, memaddr, info);
+ return -1;
+ }
+
+ /* Max supported insn size with one folded prefix insn. */
+ info->bytes_per_line = MAX_BYTES_PER_CRIS_INSN;
+
+ /* I would like to set this to a fixed value larger than the actual
+ number of bytes to print in order to avoid spaces between bytes,
+ but objdump.c (2.9.1) does not like that, so we print 16-bit
+ chunks, which is the next choice. */
+ info->bytes_per_chunk = 2;
+
+ /* Printing bytes in order of increasing addresses makes sense,
+ especially on a little-endian target.
+ This is completely the opposite of what you think; setting this to
+ BFD_ENDIAN_LITTLE will print bytes in order N..0 rather than the 0..N
+ we want. */
+ info->display_endian = BFD_ENDIAN_BIG;
+
+ return advance;
+}
+
+/* Disassemble, prefixing register names with `$'. CRIS v0..v10. */
+static int
+print_insn_cris_with_register_prefix (bfd_vma vma,
+ disassemble_info *info)
+{
+ if (info->private_data == NULL
+ && !cris_parse_disassembler_options (info, cris_dis_v0_v10))
+ return -1;
+ return print_insn_cris_generic (vma, info, true);
+}
+/* Disassemble, prefixing register names with `$'. CRIS v32. */
+
+static int
+print_insn_crisv32_with_register_prefix (bfd_vma vma,
+ disassemble_info *info)
+{
+ if (info->private_data == NULL
+ && !cris_parse_disassembler_options (info, cris_dis_v32))
+ return -1;
+ return print_insn_cris_generic (vma, info, true);
+}
+
+#if 0
+/* Disassemble, prefixing register names with `$'.
+ Common v10 and v32 subset. */
+
+static int
+print_insn_crisv10_v32_with_register_prefix (bfd_vma vma,
+ disassemble_info *info)
+{
+ if (info->private_data == NULL
+ && !cris_parse_disassembler_options (info, cris_dis_common_v10_v32))
+ return -1;
+ return print_insn_cris_generic (vma, info, true);
+}
+
+/* Disassemble, no prefixes on register names. CRIS v0..v10. */
+
+static int
+print_insn_cris_without_register_prefix (bfd_vma vma,
+ disassemble_info *info)
+{
+ if (info->private_data == NULL
+ && !cris_parse_disassembler_options (info, cris_dis_v0_v10))
+ return -1;
+ return print_insn_cris_generic (vma, info, false);
+}
+
+/* Disassemble, no prefixes on register names. CRIS v32. */
+
+static int
+print_insn_crisv32_without_register_prefix (bfd_vma vma,
+ disassemble_info *info)
+{
+ if (info->private_data == NULL
+ && !cris_parse_disassembler_options (info, cris_dis_v32))
+ return -1;
+ return print_insn_cris_generic (vma, info, false);
+}
+
+/* Disassemble, no prefixes on register names.
+ Common v10 and v32 subset. */
+
+static int
+print_insn_crisv10_v32_without_register_prefix (bfd_vma vma,
+ disassemble_info *info)
+{
+ if (info->private_data == NULL
+ && !cris_parse_disassembler_options (info, cris_dis_common_v10_v32))
+ return -1;
+ return print_insn_cris_generic (vma, info, false);
+}
+#endif
+
+int
+print_insn_crisv10 (bfd_vma vma,
+ disassemble_info *info)
+{
+ return print_insn_cris_with_register_prefix(vma, info);
+}
+
+int
+print_insn_crisv32 (bfd_vma vma,
+ disassemble_info *info)
+{
+ return print_insn_crisv32_with_register_prefix(vma, info);
+}
+
+/* Return a disassembler-function that prints registers with a `$' prefix,
+ or one that prints registers without a prefix.
+ FIXME: We should improve the solution to avoid the multitude of
+ functions seen above. */
+#if 0
+disassembler_ftype
+cris_get_disassembler (bfd *abfd)
+{
+ /* If there's no bfd in sight, we return what is valid as input in all
+ contexts if fed back to the assembler: disassembly *with* register
+ prefix. Unfortunately this will be totally wrong for v32. */
+ if (abfd == NULL)
+ return print_insn_cris_with_register_prefix;
+
+ if (bfd_get_symbol_leading_char (abfd) == 0)
+ {
+ if (bfd_get_mach (abfd) == bfd_mach_cris_v32)
+ return print_insn_crisv32_with_register_prefix;
+ if (bfd_get_mach (abfd) == bfd_mach_cris_v10_v32)
+ return print_insn_crisv10_v32_with_register_prefix;
+
+ /* We default to v10. This may be specifically specified in the
+ bfd mach, but is also the default setting. */
+ return print_insn_cris_with_register_prefix;
+ }
+
+ if (bfd_get_mach (abfd) == bfd_mach_cris_v32)
+ return print_insn_crisv32_without_register_prefix;
+ if (bfd_get_mach (abfd) == bfd_mach_cris_v10_v32)
+ return print_insn_crisv10_v32_without_register_prefix;
+ return print_insn_cris_without_register_prefix;
+}
+#endif
+/* Local variables:
+ eval: (c-set-style "gnu")
+ indent-tabs-mode: t
+ End: */
diff --git a/disas/hppa.c b/disas/hppa.c
new file mode 100644
index 0000000000..c7c8be66a2
--- /dev/null
+++ b/disas/hppa.c
@@ -0,0 +1,2831 @@
+/* Disassembler for the PA-RISC. Somewhat derived from sparc-pinsn.c.
+ Copyright 1989, 1990, 1992, 1993, 1994, 1995, 1998, 1999, 2000, 2001, 2003,
+ 2005 Free Software Foundation, Inc.
+
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>. */
+
+#include "disas/bfd.h"
+
+/* HP PA-RISC SOM object file format: definitions internal to BFD.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
+ 2003 Free Software Foundation, Inc.
+
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _LIBHPPA_H
+#define _LIBHPPA_H
+
+#define BYTES_IN_WORD 4
+#define PA_PAGESIZE 0x1000
+
+/* The PA instruction set variants. */
+enum pa_arch {pa10 = 10, pa11 = 11, pa20 = 20, pa20w = 25};
+
+/* HP PA-RISC relocation types */
+
+enum hppa_reloc_field_selector_type
+ {
+ R_HPPA_FSEL = 0x0,
+ R_HPPA_LSSEL = 0x1,
+ R_HPPA_RSSEL = 0x2,
+ R_HPPA_LSEL = 0x3,
+ R_HPPA_RSEL = 0x4,
+ R_HPPA_LDSEL = 0x5,
+ R_HPPA_RDSEL = 0x6,
+ R_HPPA_LRSEL = 0x7,
+ R_HPPA_RRSEL = 0x8,
+ R_HPPA_NSEL = 0x9,
+ R_HPPA_NLSEL = 0xa,
+ R_HPPA_NLRSEL = 0xb,
+ R_HPPA_PSEL = 0xc,
+ R_HPPA_LPSEL = 0xd,
+ R_HPPA_RPSEL = 0xe,
+ R_HPPA_TSEL = 0xf,
+ R_HPPA_LTSEL = 0x10,
+ R_HPPA_RTSEL = 0x11,
+ R_HPPA_LTPSEL = 0x12,
+ R_HPPA_RTPSEL = 0x13
+ };
+
+/* /usr/include/reloc.h defines these to constants. We want to use
+ them in enums, so #undef them before we start using them. We might
+ be able to fix this another way by simply managing not to include
+ /usr/include/reloc.h, but currently GDB picks up these defines
+ somewhere. */
+#undef e_fsel
+#undef e_lssel
+#undef e_rssel
+#undef e_lsel
+#undef e_rsel
+#undef e_ldsel
+#undef e_rdsel
+#undef e_lrsel
+#undef e_rrsel
+#undef e_nsel
+#undef e_nlsel
+#undef e_nlrsel
+#undef e_psel
+#undef e_lpsel
+#undef e_rpsel
+#undef e_tsel
+#undef e_ltsel
+#undef e_rtsel
+#undef e_one
+#undef e_two
+#undef e_pcrel
+#undef e_con
+#undef e_plabel
+#undef e_abs
+
+/* for compatibility */
+enum hppa_reloc_field_selector_type_alt
+ {
+ e_fsel = R_HPPA_FSEL,
+ e_lssel = R_HPPA_LSSEL,
+ e_rssel = R_HPPA_RSSEL,
+ e_lsel = R_HPPA_LSEL,
+ e_rsel = R_HPPA_RSEL,
+ e_ldsel = R_HPPA_LDSEL,
+ e_rdsel = R_HPPA_RDSEL,
+ e_lrsel = R_HPPA_LRSEL,
+ e_rrsel = R_HPPA_RRSEL,
+ e_nsel = R_HPPA_NSEL,
+ e_nlsel = R_HPPA_NLSEL,
+ e_nlrsel = R_HPPA_NLRSEL,
+ e_psel = R_HPPA_PSEL,
+ e_lpsel = R_HPPA_LPSEL,
+ e_rpsel = R_HPPA_RPSEL,
+ e_tsel = R_HPPA_TSEL,
+ e_ltsel = R_HPPA_LTSEL,
+ e_rtsel = R_HPPA_RTSEL,
+ e_ltpsel = R_HPPA_LTPSEL,
+ e_rtpsel = R_HPPA_RTPSEL
+ };
+
+enum hppa_reloc_expr_type
+ {
+ R_HPPA_E_ONE = 0,
+ R_HPPA_E_TWO = 1,
+ R_HPPA_E_PCREL = 2,
+ R_HPPA_E_CON = 3,
+ R_HPPA_E_PLABEL = 7,
+ R_HPPA_E_ABS = 18
+ };
+
+/* for compatibility */
+enum hppa_reloc_expr_type_alt
+ {
+ e_one = R_HPPA_E_ONE,
+ e_two = R_HPPA_E_TWO,
+ e_pcrel = R_HPPA_E_PCREL,
+ e_con = R_HPPA_E_CON,
+ e_plabel = R_HPPA_E_PLABEL,
+ e_abs = R_HPPA_E_ABS
+ };
+
+
+/* Relocations for function calls must be accompanied by parameter
+ relocation bits. These bits describe exactly where the caller has
+ placed the function's arguments and where it expects to find a return
+ value.
+
+ Both ELF and SOM encode this information within the addend field
+ of the call relocation. (Note this could break very badly if one
+ was to make a call like bl foo + 0x12345678).
+
+ The high order 10 bits contain parameter relocation information,
+ the low order 22 bits contain the constant offset. */
+
+#define HPPA_R_ARG_RELOC(a) \
+ (((a) >> 22) & 0x3ff)
+#define HPPA_R_CONSTANT(a) \
+ ((((bfd_signed_vma)(a)) << (BFD_ARCH_SIZE-22)) >> (BFD_ARCH_SIZE-22))
+#define HPPA_R_ADDEND(r, c) \
+ (((r) << 22) + ((c) & 0x3fffff))
+
+
+/* Some functions to manipulate PA instructions. */
+
+/* Declare the functions with the unused attribute to avoid warnings. */
+static inline int sign_extend (int, int) ATTRIBUTE_UNUSED;
+static inline int low_sign_extend (int, int) ATTRIBUTE_UNUSED;
+static inline int sign_unext (int, int) ATTRIBUTE_UNUSED;
+static inline int low_sign_unext (int, int) ATTRIBUTE_UNUSED;
+static inline int re_assemble_3 (int) ATTRIBUTE_UNUSED;
+static inline int re_assemble_12 (int) ATTRIBUTE_UNUSED;
+static inline int re_assemble_14 (int) ATTRIBUTE_UNUSED;
+static inline int re_assemble_16 (int) ATTRIBUTE_UNUSED;
+static inline int re_assemble_17 (int) ATTRIBUTE_UNUSED;
+static inline int re_assemble_21 (int) ATTRIBUTE_UNUSED;
+static inline int re_assemble_22 (int) ATTRIBUTE_UNUSED;
+static inline bfd_signed_vma hppa_field_adjust
+ (bfd_vma, bfd_signed_vma, enum hppa_reloc_field_selector_type_alt)
+ ATTRIBUTE_UNUSED;
+static inline int hppa_rebuild_insn (int, int, int) ATTRIBUTE_UNUSED;
+
+
+/* The *sign_extend functions are used to assemble various bitfields
+ taken from an instruction and return the resulting immediate
+ value. */
+
+static inline int
+sign_extend (int x, int len)
+{
+ int signbit = (1 << (len - 1));
+ int mask = (signbit << 1) - 1;
+ return ((x & mask) ^ signbit) - signbit;
+}
+
+static inline int
+low_sign_extend (int x, int len)
+{
+ return (x >> 1) - ((x & 1) << (len - 1));
+}
+
+
+/* The re_assemble_* functions prepare an immediate value for
+ insertion into an opcode. pa-risc uses all sorts of weird bitfields
+ in the instruction to hold the value. */
+
+static inline int
+sign_unext (int x, int len)
+{
+ int len_ones;
+
+ len_ones = (1 << len) - 1;
+
+ return x & len_ones;
+}
+
+static inline int
+low_sign_unext (int x, int len)
+{
+ int temp;
+ int sign;
+
+ sign = (x >> (len-1)) & 1;
+
+ temp = sign_unext (x, len-1);
+
+ return (temp << 1) | sign;
+}
+
+static inline int
+re_assemble_3 (int as3)
+{
+ return (( (as3 & 4) << (13-2))
+ | ((as3 & 3) << (13+1)));
+}
+
+static inline int
+re_assemble_12 (int as12)
+{
+ return (( (as12 & 0x800) >> 11)
+ | ((as12 & 0x400) >> (10 - 2))
+ | ((as12 & 0x3ff) << (1 + 2)));
+}
+
+static inline int
+re_assemble_14 (int as14)
+{
+ return (( (as14 & 0x1fff) << 1)
+ | ((as14 & 0x2000) >> 13));
+}
+
+static inline int
+re_assemble_16 (int as16)
+{
+ int s, t;
+
+ /* Unusual 16-bit encoding, for wide mode only. */
+ t = (as16 << 1) & 0xffff;
+ s = (as16 & 0x8000);
+ return (t ^ s ^ (s >> 1)) | (s >> 15);
+}
+
+static inline int
+re_assemble_17 (int as17)
+{
+ return (( (as17 & 0x10000) >> 16)
+ | ((as17 & 0x0f800) << (16 - 11))
+ | ((as17 & 0x00400) >> (10 - 2))
+ | ((as17 & 0x003ff) << (1 + 2)));
+}
+
+static inline int
+re_assemble_21 (int as21)
+{
+ return (( (as21 & 0x100000) >> 20)
+ | ((as21 & 0x0ffe00) >> 8)
+ | ((as21 & 0x000180) << 7)
+ | ((as21 & 0x00007c) << 14)
+ | ((as21 & 0x000003) << 12));
+}
+
+static inline int
+re_assemble_22 (int as22)
+{
+ return (( (as22 & 0x200000) >> 21)
+ | ((as22 & 0x1f0000) << (21 - 16))
+ | ((as22 & 0x00f800) << (16 - 11))
+ | ((as22 & 0x000400) >> (10 - 2))
+ | ((as22 & 0x0003ff) << (1 + 2)));
+}
+
+
+/* Handle field selectors for PA instructions.
+ The L and R (and LS, RS etc.) selectors are used in pairs to form a
+ full 32 bit address. eg.
+
+ LDIL L'start,%r1 ; put left part into r1
+ LDW R'start(%r1),%r2 ; add r1 and right part to form address
+
+ This function returns sign extended values in all cases.
+*/
+
+static inline bfd_signed_vma
+hppa_field_adjust (bfd_vma sym_val,
+ bfd_signed_vma addend,
+ enum hppa_reloc_field_selector_type_alt r_field)
+{
+ bfd_signed_vma value;
+
+ value = sym_val + addend;
+ switch (r_field)
+ {
+ case e_fsel:
+ /* F: No change. */
+ break;
+
+ case e_nsel:
+ /* N: null selector. I don't really understand what this is all
+ about, but HP's documentation says "this indicates that zero
+ bits are to be used for the displacement on the instruction.
+ This fixup is used to identify three-instruction sequences to
+ access data (for importing shared library data)." */
+ value = 0;
+ break;
+
+ case e_lsel:
+ case e_nlsel:
+ /* L: Select top 21 bits. */
+ value = value >> 11;
+ break;
+
+ case e_rsel:
+ /* R: Select bottom 11 bits. */
+ value = value & 0x7ff;
+ break;
+
+ case e_lssel:
+ /* LS: Round to nearest multiple of 2048 then select top 21 bits. */
+ value = value + 0x400;
+ value = value >> 11;
+ break;
+
+ case e_rssel:
+ /* RS: Select bottom 11 bits for LS.
+ We need to return a value such that 2048 * LS'x + RS'x == x.
+ ie. RS'x = x - ((x + 0x400) & -0x800)
+ this is just a sign extension from bit 21. */
+ value = ((value & 0x7ff) ^ 0x400) - 0x400;
+ break;
+
+ case e_ldsel:
+ /* LD: Round to next multiple of 2048 then select top 21 bits.
+ Yes, if we are already on a multiple of 2048, we go up to the
+ next one. RD in this case will be -2048. */
+ value = value + 0x800;
+ value = value >> 11;
+ break;
+
+ case e_rdsel:
+ /* RD: Set bits 0-20 to one. */
+ value = value | -0x800;
+ break;
+
+ case e_lrsel:
+ case e_nlrsel:
+ /* LR: L with rounding of the addend to nearest 8k. */
+ value = sym_val + ((addend + 0x1000) & -0x2000);
+ value = value >> 11;
+ break;
+
+ case e_rrsel:
+ /* RR: R with rounding of the addend to nearest 8k.
+ We need to return a value such that 2048 * LR'x + RR'x == x
+ ie. RR'x = s+a - (s + (((a + 0x1000) & -0x2000) & -0x800))
+ . = s+a - ((s & -0x800) + ((a + 0x1000) & -0x2000))
+ . = (s & 0x7ff) + a - ((a + 0x1000) & -0x2000) */
+ value = (sym_val & 0x7ff) + (((addend & 0x1fff) ^ 0x1000) - 0x1000);
+ break;
+
+ default:
+ abort ();
+ }
+ return value;
+}
+
+/* PA-RISC OPCODES */
+#define get_opcode(insn) (((insn) >> 26) & 0x3f)
+
+enum hppa_opcode_type
+{
+ /* None of the opcodes in the first group generate relocs, so we
+ aren't too concerned about them. */
+ OP_SYSOP = 0x00,
+ OP_MEMMNG = 0x01,
+ OP_ALU = 0x02,
+ OP_NDXMEM = 0x03,
+ OP_SPOP = 0x04,
+ OP_DIAG = 0x05,
+ OP_FMPYADD = 0x06,
+ OP_UNDEF07 = 0x07,
+ OP_COPRW = 0x09,
+ OP_COPRDW = 0x0b,
+ OP_COPR = 0x0c,
+ OP_FLOAT = 0x0e,
+ OP_PRDSPEC = 0x0f,
+ OP_UNDEF15 = 0x15,
+ OP_UNDEF1d = 0x1d,
+ OP_FMPYSUB = 0x26,
+ OP_FPFUSED = 0x2e,
+ OP_SHEXDP0 = 0x34,
+ OP_SHEXDP1 = 0x35,
+ OP_SHEXDP2 = 0x36,
+ OP_UNDEF37 = 0x37,
+ OP_SHEXDP3 = 0x3c,
+ OP_SHEXDP4 = 0x3d,
+ OP_MULTMED = 0x3e,
+ OP_UNDEF3f = 0x3f,
+
+ OP_LDIL = 0x08,
+ OP_ADDIL = 0x0a,
+
+ OP_LDO = 0x0d,
+ OP_LDB = 0x10,
+ OP_LDH = 0x11,
+ OP_LDW = 0x12,
+ OP_LDWM = 0x13,
+ OP_STB = 0x18,
+ OP_STH = 0x19,
+ OP_STW = 0x1a,
+ OP_STWM = 0x1b,
+
+ OP_LDD = 0x14,
+ OP_STD = 0x1c,
+
+ OP_FLDW = 0x16,
+ OP_LDWL = 0x17,
+ OP_FSTW = 0x1e,
+ OP_STWL = 0x1f,
+
+ OP_COMBT = 0x20,
+ OP_COMIBT = 0x21,
+ OP_COMBF = 0x22,
+ OP_COMIBF = 0x23,
+ OP_CMPBDT = 0x27,
+ OP_ADDBT = 0x28,
+ OP_ADDIBT = 0x29,
+ OP_ADDBF = 0x2a,
+ OP_ADDIBF = 0x2b,
+ OP_CMPBDF = 0x2f,
+ OP_BVB = 0x30,
+ OP_BB = 0x31,
+ OP_MOVB = 0x32,
+ OP_MOVIB = 0x33,
+ OP_CMPIBD = 0x3b,
+
+ OP_COMICLR = 0x24,
+ OP_SUBI = 0x25,
+ OP_ADDIT = 0x2c,
+ OP_ADDI = 0x2d,
+
+ OP_BE = 0x38,
+ OP_BLE = 0x39,
+ OP_BL = 0x3a
+};
+
+
+/* Insert VALUE into INSN using R_FORMAT to determine exactly what
+ bits to change. */
+
+static inline int
+hppa_rebuild_insn (int insn, int value, int r_format)
+{
+ switch (r_format)
+ {
+ case 11:
+ return (insn & ~ 0x7ff) | low_sign_unext (value, 11);
+
+ case 12:
+ return (insn & ~ 0x1ffd) | re_assemble_12 (value);
+
+
+ case 10:
+ return (insn & ~ 0x3ff1) | re_assemble_14 (value & -8);
+
+ case -11:
+ return (insn & ~ 0x3ff9) | re_assemble_14 (value & -4);
+
+ case 14:
+ return (insn & ~ 0x3fff) | re_assemble_14 (value);
+
+
+ case -10:
+ return (insn & ~ 0xfff1) | re_assemble_16 (value & -8);
+
+ case -16:
+ return (insn & ~ 0xfff9) | re_assemble_16 (value & -4);
+
+ case 16:
+ return (insn & ~ 0xffff) | re_assemble_16 (value);
+
+
+ case 17:
+ return (insn & ~ 0x1f1ffd) | re_assemble_17 (value);
+
+ case 21:
+ return (insn & ~ 0x1fffff) | re_assemble_21 (value);
+
+ case 22:
+ return (insn & ~ 0x3ff1ffd) | re_assemble_22 (value);
+
+ case 32:
+ return value;
+
+ default:
+ abort ();
+ }
+ return insn;
+}
+
+#endif /* _LIBHPPA_H */
+/* Table of opcodes for the PA-RISC.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
+ 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+This file is part of GAS, the GNU Assembler, and GDB, the GNU disassembler.
+
+GAS/GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS/GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS or GDB; see the file COPYING.
+If not, see <http://www.gnu.org/licenses/>. */
+
+#if !defined(__STDC__) && !defined(const)
+#define const
+#endif
+
+/*
+ * Structure of an opcode table entry.
+ */
+
+/* There are two kinds of delay slot nullification: normal which is
+ * controlled by the nullification bit, and conditional, which depends
+ * on the direction of the branch and its success or failure.
+ *
+ * NONE is unfortunately #defined in the hiux system include files.
+ * #undef it away.
+ */
+#undef NONE
+struct pa_opcode
+{
+ const char *name;
+ unsigned long int match; /* Bits that must be set... */
+ unsigned long int mask; /* ... in these bits. */
+ const char *args;
+ enum pa_arch arch;
+ char flags;
+};
+
+/* Enables strict matching. Opcodes with match errors are skipped
+ when this bit is set. */
+#define FLAG_STRICT 0x1
+
+/*
+ All hppa opcodes are 32 bits.
+
+ The match component is a mask saying which bits must match a
+ particular opcode in order for an instruction to be an instance
+ of that opcode.
+
+ The args component is a string containing one character for each operand of
+ the instruction. Characters used as a prefix allow any second character to
+ be used without conflicting with the main operand characters.
+
+ Bit positions in this description follow HP usage of lsb = 31,
+ "at" is lsb of field.
+
+ In the args field, the following characters must match exactly:
+
+ '+,() '
+
+ In the args field, the following characters are unused:
+
+ ' " - / 34 6789:; '
+ '@ C M [\] '
+ '` e g } '
+
+ Here are all the characters:
+
+ ' !"#$%&'()*+-,./0123456789:;<=>?'
+ '@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_'
+ '`abcdefghijklmnopqrstuvwxyz{|}~ '
+
+Kinds of operands:
+ x integer register field at 15.
+ b integer register field at 10.
+ t integer register field at 31.
+ a integer register field at 10 and 15 (for PERMH)
+ 5 5 bit immediate at 15.
+ s 2 bit space specifier at 17.
+ S 3 bit space specifier at 18.
+ V 5 bit immediate value at 31
+ i 11 bit immediate value at 31
+ j 14 bit immediate value at 31
+ k 21 bit immediate value at 31
+ l 16 bit immediate value at 31 (wide mode only, unusual encoding).
+ n nullification for branch instructions
+ N nullification for spop and copr instructions
+ w 12 bit branch displacement
+ W 17 bit branch displacement (PC relative)
+ X 22 bit branch displacement (PC relative)
+ z 17 bit branch displacement (just a number, not an address)
+
+Also these:
+
+ . 2 bit shift amount at 25
+ * 4 bit shift amount at 25
+ p 5 bit shift count at 26 (to support the SHD instruction) encoded as
+ 31-p
+ ~ 6 bit shift count at 20,22:26 encoded as 63-~.
+ P 5 bit bit position at 26
+ q 6 bit bit position at 20,22:26
+ T 5 bit field length at 31 (encoded as 32-T)
+ % 6 bit field length at 23,27:31 (variable extract/deposit)
+ | 6 bit field length at 19,27:31 (fixed extract/deposit)
+ A 13 bit immediate at 18 (to support the BREAK instruction)
+ ^ like b, but describes a control register
+ ! sar (cr11) register
+ D 26 bit immediate at 31 (to support the DIAG instruction)
+ $ 9 bit immediate at 28 (to support POPBTS)
+
+ v 3 bit Special Function Unit identifier at 25
+ O 20 bit Special Function Unit operation split between 15 bits at 20
+ and 5 bits at 31
+ o 15 bit Special Function Unit operation at 20
+ 2 22 bit Special Function Unit operation split between 17 bits at 20
+ and 5 bits at 31
+ 1 15 bit Special Function Unit operation split between 10 bits at 20
+ and 5 bits at 31
+ 0 10 bit Special Function Unit operation split between 5 bits at 20
+ and 5 bits at 31
+ u 3 bit coprocessor unit identifier at 25
+ F Source Floating Point Operand Format Completer encoded 2 bits at 20
+ I Source Floating Point Operand Format Completer encoded 1 bits at 20
+ (for 0xe format FP instructions)
+ G Destination Floating Point Operand Format Completer encoded 2 bits at 18
+ H Floating Point Operand Format at 26 for 'fmpyadd' and 'fmpysub'
+ (very similar to 'F')
+
+ r 5 bit immediate value at 31 (for the break instruction)
+ (very similar to V above, except the value is unsigned instead of
+ low_sign_ext)
+ R 5 bit immediate value at 15 (for the ssm, rsm, probei instructions)
+ (same as r above, except the value is in a different location)
+ U 10 bit immediate value at 15 (for SSM, RSM on pa2.0)
+ Q 5 bit immediate value at 10 (a bit position specified in
+ the bb instruction. It's the same as r above, except the
+ value is in a different location)
+ B 5 bit immediate value at 10 (a bit position specified in
+ the bb instruction. Similar to Q, but 64 bit handling is
+ different.
+ Z %r1 -- implicit target of addil instruction.
+ L ,%r2 completer for new syntax branch
+ { Source format completer for fcnv
+ _ Destination format completer for fcnv
+ h cbit for fcmp
+ = gfx tests for ftest
+ d 14 bit offset for single precision FP long load/store.
+ # 14 bit offset for double precision FP load long/store.
+ J Yet another 14 bit offset for load/store with ma,mb completers.
+ K Yet another 14 bit offset for load/store with ma,mb completers.
+ y 16 bit offset for word aligned load/store (PA2.0 wide).
+ & 16 bit offset for dword aligned load/store (PA2.0 wide).
+ < 16 bit offset for load/store with ma,mb completers (PA2.0 wide).
+ > 16 bit offset for load/store with ma,mb completers (PA2.0 wide).
+ Y %sr0,%r31 -- implicit target of be,l instruction.
+ @ implicit immediate value of 0
+
+Completer operands all have 'c' as the prefix:
+
+ cx indexed load and store completer.
+ cX indexed load and store completer. Like cx, but emits a space
+ after in disassembler.
+ cm short load and store completer.
+ cM short load and store completer. Like cm, but emits a space
+ after in disassembler.
+ cq long load and store completer (like cm, but inserted into a
+ different location in the target instruction).
+ cs store bytes short completer.
+ cA store bytes short completer. Like cs, but emits a space
+ after in disassembler.
+ ce long load/store completer for LDW/STW with a different encoding
+ than the others
+ cc load cache control hint
+ cd load and clear cache control hint
+ cC store cache control hint
+ co ordered access
+
+ cp branch link and push completer
+ cP branch pop completer
+ cl branch link completer
+ cg branch gate completer
+
+ cw read/write completer for PROBE
+ cW wide completer for MFCTL
+ cL local processor completer for cache control
+ cZ System Control Completer (to support LPA, LHA, etc.)
+
+ ci correction completer for DCOR
+ ca add completer
+ cy 32 bit add carry completer
+ cY 64 bit add carry completer
+ cv signed overflow trap completer
+ ct trap on condition completer for ADDI, SUB
+ cT trap on condition completer for UADDCM
+ cb 32 bit borrow completer for SUB
+ cB 64 bit borrow completer for SUB
+
+ ch left/right half completer
+ cH signed/unsigned saturation completer
+ cS signed/unsigned completer at 21
+ cz zero/sign extension completer.
+ c* permutation completer
+
+Condition operands all have '?' as the prefix:
+
+ ?f Floating point compare conditions (encoded as 5 bits at 31)
+
+ ?a add conditions
+ ?A 64 bit add conditions
+ ?@ add branch conditions followed by nullify
+ ?d non-negated add branch conditions
+ ?D negated add branch conditions
+ ?w wide mode non-negated add branch conditions
+ ?W wide mode negated add branch conditions
+
+ ?s compare/subtract conditions
+ ?S 64 bit compare/subtract conditions
+ ?t non-negated compare and branch conditions
+ ?n 32 bit compare and branch conditions followed by nullify
+ ?N 64 bit compare and branch conditions followed by nullify
+ ?Q 64 bit compare and branch conditions for CMPIB instruction
+
+ ?l logical conditions
+ ?L 64 bit logical conditions
+
+ ?b branch on bit conditions
+ ?B 64 bit branch on bit conditions
+
+ ?x shift/extract/deposit conditions
+ ?X 64 bit shift/extract/deposit conditions
+ ?y shift/extract/deposit conditions followed by nullify for conditional
+ branches
+
+ ?u unit conditions
+ ?U 64 bit unit conditions
+
+Floating point registers all have 'f' as a prefix:
+
+ ft target register at 31
+ fT target register with L/R halves at 31
+ fa operand 1 register at 10
+ fA operand 1 register with L/R halves at 10
+ fX Same as fA, except prints a space before register during disasm
+ fb operand 2 register at 15
+ fB operand 2 register with L/R halves at 15
+ fC operand 3 register with L/R halves at 16:18,21:23
+ fe Like fT, but encoding is different.
+ fE Same as fe, except prints a space before register during disasm.
+ fx target register at 15 (only for PA 2.0 long format FLDD/FSTD).
+
+Float registers for fmpyadd and fmpysub:
+
+ fi mult operand 1 register at 10
+ fj mult operand 2 register at 15
+ fk mult target register at 20
+ fl add/sub operand register at 25
+ fm add/sub target register at 31
+
+*/
+
+
+#if 0
+/* List of characters not to put a space after. Note that
+ "," is included, as the "spopN" operations use literal
+ commas in their completer sections. */
+static const char *const completer_chars = ",CcY<>?!@+&U~FfGHINnOoZMadu|/=0123%e$m}";
+#endif
+
+/* The order of the opcodes in this table is significant:
+
+ * The assembler requires that all instances of the same mnemonic be
+ consecutive. If they aren't, the assembler will bomb at runtime.
+
+ * Immediate fields use pa_get_absolute_expression to parse the
+ string. It will generate a "bad expression" error if passed
+ a register name. Thus, register index variants of an opcode
+ need to precede immediate variants.
+
+ * The disassembler does not care about the order of the opcodes
+ except in cases where implicit addressing is used.
+
+ Here are the rules for ordering the opcodes of a mnemonic:
+
+ 1) Opcodes with FLAG_STRICT should precede opcodes without
+ FLAG_STRICT.
+
+ 2) Opcodes with FLAG_STRICT should be ordered as follows:
+ register index opcodes, short immediate opcodes, and finally
+ long immediate opcodes. When both pa10 and pa11 variants
+ of the same opcode are available, the pa10 opcode should
+ come first for correct architectural promotion.
+
+ 3) When implicit addressing is available for an opcode, the
+ implicit opcode should precede the explicit opcode.
+
+ 4) Opcodes without FLAG_STRICT should be ordered as follows:
+ register index opcodes, long immediate opcodes, and finally
+ short immediate opcodes. */
+
+static const struct pa_opcode pa_opcodes[] =
+{
+
+/* Pseudo-instructions. */
+
+{ "ldi", 0x34000000, 0xffe00000, "l,x", pa20w, 0},/* ldo val(r0),r */
+{ "ldi", 0x34000000, 0xffe0c000, "j,x", pa10, 0},/* ldo val(r0),r */
+
+{ "cmpib", 0xec000000, 0xfc000000, "?Qn5,b,w", pa20, FLAG_STRICT},
+{ "cmpib", 0x84000000, 0xf4000000, "?nn5,b,w", pa10, FLAG_STRICT},
+{ "comib", 0x84000000, 0xfc000000, "?nn5,b,w", pa10, 0}, /* comib{tf}*/
+/* This entry is for the disassembler only. It will never be used by
+ assembler. */
+{ "comib", 0x8c000000, 0xfc000000, "?nn5,b,w", pa10, 0}, /* comib{tf}*/
+{ "cmpb", 0x9c000000, 0xdc000000, "?Nnx,b,w", pa20, FLAG_STRICT},
+{ "cmpb", 0x80000000, 0xf4000000, "?nnx,b,w", pa10, FLAG_STRICT},
+{ "comb", 0x80000000, 0xfc000000, "?nnx,b,w", pa10, 0}, /* comb{tf} */
+/* This entry is for the disassembler only. It will never be used by
+ assembler. */
+{ "comb", 0x88000000, 0xfc000000, "?nnx,b,w", pa10, 0}, /* comb{tf} */
+{ "addb", 0xa0000000, 0xf4000000, "?Wnx,b,w", pa20w, FLAG_STRICT},
+{ "addb", 0xa0000000, 0xfc000000, "?@nx,b,w", pa10, 0}, /* addb{tf} */
+/* This entry is for the disassembler only. It will never be used by
+ assembler. */
+{ "addb", 0xa8000000, 0xfc000000, "?@nx,b,w", pa10, 0},
+{ "addib", 0xa4000000, 0xf4000000, "?Wn5,b,w", pa20w, FLAG_STRICT},
+{ "addib", 0xa4000000, 0xfc000000, "?@n5,b,w", pa10, 0}, /* addib{tf}*/
+/* This entry is for the disassembler only. It will never be used by
+ assembler. */
+{ "addib", 0xac000000, 0xfc000000, "?@n5,b,w", pa10, 0}, /* addib{tf}*/
+{ "nop", 0x08000240, 0xffffffff, "", pa10, 0}, /* or 0,0,0 */
+{ "copy", 0x08000240, 0xffe0ffe0, "x,t", pa10, 0}, /* or r,0,t */
+{ "mtsar", 0x01601840, 0xffe0ffff, "x", pa10, 0}, /* mtctl r,cr11 */
+
+/* Loads and Stores for integer registers. */
+
+{ "ldd", 0x0c0000c0, 0xfc00d3c0, "cxccx(b),t", pa20, FLAG_STRICT},
+{ "ldd", 0x0c0000c0, 0xfc0013c0, "cxccx(s,b),t", pa20, FLAG_STRICT},
+{ "ldd", 0x0c0010e0, 0xfc1ff3e0, "cocc@(b),t", pa20, FLAG_STRICT},
+{ "ldd", 0x0c0010e0, 0xfc1f33e0, "cocc@(s,b),t", pa20, FLAG_STRICT},
+{ "ldd", 0x0c0010c0, 0xfc00d3c0, "cmcc5(b),t", pa20, FLAG_STRICT},
+{ "ldd", 0x0c0010c0, 0xfc0013c0, "cmcc5(s,b),t", pa20, FLAG_STRICT},
+{ "ldd", 0x50000000, 0xfc000002, "cq&(b),x", pa20w, FLAG_STRICT},
+{ "ldd", 0x50000000, 0xfc00c002, "cq#(b),x", pa20, FLAG_STRICT},
+{ "ldd", 0x50000000, 0xfc000002, "cq#(s,b),x", pa20, FLAG_STRICT},
+{ "ldw", 0x0c000080, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldw", 0x0c000080, 0xfc001fc0, "cXx(s,b),t", pa10, FLAG_STRICT},
+{ "ldw", 0x0c000080, 0xfc00d3c0, "cxccx(b),t", pa11, FLAG_STRICT},
+{ "ldw", 0x0c000080, 0xfc0013c0, "cxccx(s,b),t", pa11, FLAG_STRICT},
+{ "ldw", 0x0c0010a0, 0xfc1ff3e0, "cocc@(b),t", pa20, FLAG_STRICT},
+{ "ldw", 0x0c0010a0, 0xfc1f33e0, "cocc@(s,b),t", pa20, FLAG_STRICT},
+{ "ldw", 0x0c001080, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldw", 0x0c001080, 0xfc001fc0, "cM5(s,b),t", pa10, FLAG_STRICT},
+{ "ldw", 0x0c001080, 0xfc00d3c0, "cmcc5(b),t", pa11, FLAG_STRICT},
+{ "ldw", 0x0c001080, 0xfc0013c0, "cmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "ldw", 0x4c000000, 0xfc000000, "ce<(b),x", pa20w, FLAG_STRICT},
+{ "ldw", 0x5c000004, 0xfc000006, "ce>(b),x", pa20w, FLAG_STRICT},
+{ "ldw", 0x48000000, 0xfc000000, "l(b),x", pa20w, FLAG_STRICT},
+{ "ldw", 0x5c000004, 0xfc00c006, "ceK(b),x", pa20, FLAG_STRICT},
+{ "ldw", 0x5c000004, 0xfc000006, "ceK(s,b),x", pa20, FLAG_STRICT},
+{ "ldw", 0x4c000000, 0xfc00c000, "ceJ(b),x", pa10, FLAG_STRICT},
+{ "ldw", 0x4c000000, 0xfc000000, "ceJ(s,b),x", pa10, FLAG_STRICT},
+{ "ldw", 0x48000000, 0xfc00c000, "j(b),x", pa10, 0},
+{ "ldw", 0x48000000, 0xfc000000, "j(s,b),x", pa10, 0},
+{ "ldh", 0x0c000040, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldh", 0x0c000040, 0xfc001fc0, "cXx(s,b),t", pa10, FLAG_STRICT},
+{ "ldh", 0x0c000040, 0xfc00d3c0, "cxccx(b),t", pa11, FLAG_STRICT},
+{ "ldh", 0x0c000040, 0xfc0013c0, "cxccx(s,b),t", pa11, FLAG_STRICT},
+{ "ldh", 0x0c001060, 0xfc1ff3e0, "cocc@(b),t", pa20, FLAG_STRICT},
+{ "ldh", 0x0c001060, 0xfc1f33e0, "cocc@(s,b),t", pa20, FLAG_STRICT},
+{ "ldh", 0x0c001040, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldh", 0x0c001040, 0xfc001fc0, "cM5(s,b),t", pa10, FLAG_STRICT},
+{ "ldh", 0x0c001040, 0xfc00d3c0, "cmcc5(b),t", pa11, FLAG_STRICT},
+{ "ldh", 0x0c001040, 0xfc0013c0, "cmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "ldh", 0x44000000, 0xfc000000, "l(b),x", pa20w, FLAG_STRICT},
+{ "ldh", 0x44000000, 0xfc00c000, "j(b),x", pa10, 0},
+{ "ldh", 0x44000000, 0xfc000000, "j(s,b),x", pa10, 0},
+{ "ldb", 0x0c000000, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldb", 0x0c000000, 0xfc001fc0, "cXx(s,b),t", pa10, FLAG_STRICT},
+{ "ldb", 0x0c000000, 0xfc00d3c0, "cxccx(b),t", pa11, FLAG_STRICT},
+{ "ldb", 0x0c000000, 0xfc0013c0, "cxccx(s,b),t", pa11, FLAG_STRICT},
+{ "ldb", 0x0c001020, 0xfc1ff3e0, "cocc@(b),t", pa20, FLAG_STRICT},
+{ "ldb", 0x0c001020, 0xfc1f33e0, "cocc@(s,b),t", pa20, FLAG_STRICT},
+{ "ldb", 0x0c001000, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldb", 0x0c001000, 0xfc001fc0, "cM5(s,b),t", pa10, FLAG_STRICT},
+{ "ldb", 0x0c001000, 0xfc00d3c0, "cmcc5(b),t", pa11, FLAG_STRICT},
+{ "ldb", 0x0c001000, 0xfc0013c0, "cmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "ldb", 0x40000000, 0xfc000000, "l(b),x", pa20w, FLAG_STRICT},
+{ "ldb", 0x40000000, 0xfc00c000, "j(b),x", pa10, 0},
+{ "ldb", 0x40000000, 0xfc000000, "j(s,b),x", pa10, 0},
+{ "std", 0x0c0012e0, 0xfc00f3ff, "cocCx,@(b)", pa20, FLAG_STRICT},
+{ "std", 0x0c0012e0, 0xfc0033ff, "cocCx,@(s,b)", pa20, FLAG_STRICT},
+{ "std", 0x0c0012c0, 0xfc00d3c0, "cmcCx,V(b)", pa20, FLAG_STRICT},
+{ "std", 0x0c0012c0, 0xfc0013c0, "cmcCx,V(s,b)", pa20, FLAG_STRICT},
+{ "std", 0x70000000, 0xfc000002, "cqx,&(b)", pa20w, FLAG_STRICT},
+{ "std", 0x70000000, 0xfc00c002, "cqx,#(b)", pa20, FLAG_STRICT},
+{ "std", 0x70000000, 0xfc000002, "cqx,#(s,b)", pa20, FLAG_STRICT},
+{ "stw", 0x0c0012a0, 0xfc00f3ff, "cocCx,@(b)", pa20, FLAG_STRICT},
+{ "stw", 0x0c0012a0, 0xfc0033ff, "cocCx,@(s,b)", pa20, FLAG_STRICT},
+{ "stw", 0x0c001280, 0xfc00dfc0, "cMx,V(b)", pa10, FLAG_STRICT},
+{ "stw", 0x0c001280, 0xfc001fc0, "cMx,V(s,b)", pa10, FLAG_STRICT},
+{ "stw", 0x0c001280, 0xfc00d3c0, "cmcCx,V(b)", pa11, FLAG_STRICT},
+{ "stw", 0x0c001280, 0xfc0013c0, "cmcCx,V(s,b)", pa11, FLAG_STRICT},
+{ "stw", 0x6c000000, 0xfc000000, "cex,<(b)", pa20w, FLAG_STRICT},
+{ "stw", 0x7c000004, 0xfc000006, "cex,>(b)", pa20w, FLAG_STRICT},
+{ "stw", 0x68000000, 0xfc000000, "x,l(b)", pa20w, FLAG_STRICT},
+{ "stw", 0x7c000004, 0xfc00c006, "cex,K(b)", pa20, FLAG_STRICT},
+{ "stw", 0x7c000004, 0xfc000006, "cex,K(s,b)", pa20, FLAG_STRICT},
+{ "stw", 0x6c000000, 0xfc00c000, "cex,J(b)", pa10, FLAG_STRICT},
+{ "stw", 0x6c000000, 0xfc000000, "cex,J(s,b)", pa10, FLAG_STRICT},
+{ "stw", 0x68000000, 0xfc00c000, "x,j(b)", pa10, 0},
+{ "stw", 0x68000000, 0xfc000000, "x,j(s,b)", pa10, 0},
+{ "sth", 0x0c001260, 0xfc00f3ff, "cocCx,@(b)", pa20, FLAG_STRICT},
+{ "sth", 0x0c001260, 0xfc0033ff, "cocCx,@(s,b)", pa20, FLAG_STRICT},
+{ "sth", 0x0c001240, 0xfc00dfc0, "cMx,V(b)", pa10, FLAG_STRICT},
+{ "sth", 0x0c001240, 0xfc001fc0, "cMx,V(s,b)", pa10, FLAG_STRICT},
+{ "sth", 0x0c001240, 0xfc00d3c0, "cmcCx,V(b)", pa11, FLAG_STRICT},
+{ "sth", 0x0c001240, 0xfc0013c0, "cmcCx,V(s,b)", pa11, FLAG_STRICT},
+{ "sth", 0x64000000, 0xfc000000, "x,l(b)", pa20w, FLAG_STRICT},
+{ "sth", 0x64000000, 0xfc00c000, "x,j(b)", pa10, 0},
+{ "sth", 0x64000000, 0xfc000000, "x,j(s,b)", pa10, 0},
+{ "stb", 0x0c001220, 0xfc00f3ff, "cocCx,@(b)", pa20, FLAG_STRICT},
+{ "stb", 0x0c001220, 0xfc0033ff, "cocCx,@(s,b)", pa20, FLAG_STRICT},
+{ "stb", 0x0c001200, 0xfc00dfc0, "cMx,V(b)", pa10, FLAG_STRICT},
+{ "stb", 0x0c001200, 0xfc001fc0, "cMx,V(s,b)", pa10, FLAG_STRICT},
+{ "stb", 0x0c001200, 0xfc00d3c0, "cmcCx,V(b)", pa11, FLAG_STRICT},
+{ "stb", 0x0c001200, 0xfc0013c0, "cmcCx,V(s,b)", pa11, FLAG_STRICT},
+{ "stb", 0x60000000, 0xfc000000, "x,l(b)", pa20w, FLAG_STRICT},
+{ "stb", 0x60000000, 0xfc00c000, "x,j(b)", pa10, 0},
+{ "stb", 0x60000000, 0xfc000000, "x,j(s,b)", pa10, 0},
+{ "ldwm", 0x4c000000, 0xfc00c000, "j(b),x", pa10, 0},
+{ "ldwm", 0x4c000000, 0xfc000000, "j(s,b),x", pa10, 0},
+{ "stwm", 0x6c000000, 0xfc00c000, "x,j(b)", pa10, 0},
+{ "stwm", 0x6c000000, 0xfc000000, "x,j(s,b)", pa10, 0},
+{ "ldwx", 0x0c000080, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldwx", 0x0c000080, 0xfc001fc0, "cXx(s,b),t", pa10, FLAG_STRICT},
+{ "ldwx", 0x0c000080, 0xfc00d3c0, "cxccx(b),t", pa11, FLAG_STRICT},
+{ "ldwx", 0x0c000080, 0xfc0013c0, "cxccx(s,b),t", pa11, FLAG_STRICT},
+{ "ldwx", 0x0c000080, 0xfc00dfc0, "cXx(b),t", pa10, 0},
+{ "ldwx", 0x0c000080, 0xfc001fc0, "cXx(s,b),t", pa10, 0},
+{ "ldhx", 0x0c000040, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldhx", 0x0c000040, 0xfc001fc0, "cXx(s,b),t", pa10, FLAG_STRICT},
+{ "ldhx", 0x0c000040, 0xfc00d3c0, "cxccx(b),t", pa11, FLAG_STRICT},
+{ "ldhx", 0x0c000040, 0xfc0013c0, "cxccx(s,b),t", pa11, FLAG_STRICT},
+{ "ldhx", 0x0c000040, 0xfc00dfc0, "cXx(b),t", pa10, 0},
+{ "ldhx", 0x0c000040, 0xfc001fc0, "cXx(s,b),t", pa10, 0},
+{ "ldbx", 0x0c000000, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldbx", 0x0c000000, 0xfc001fc0, "cXx(s,b),t", pa10, FLAG_STRICT},
+{ "ldbx", 0x0c000000, 0xfc00d3c0, "cxccx(b),t", pa11, FLAG_STRICT},
+{ "ldbx", 0x0c000000, 0xfc0013c0, "cxccx(s,b),t", pa11, FLAG_STRICT},
+{ "ldbx", 0x0c000000, 0xfc00dfc0, "cXx(b),t", pa10, 0},
+{ "ldbx", 0x0c000000, 0xfc001fc0, "cXx(s,b),t", pa10, 0},
+{ "ldwa", 0x0c000180, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldwa", 0x0c000180, 0xfc00d3c0, "cxccx(b),t", pa11, FLAG_STRICT},
+{ "ldwa", 0x0c0011a0, 0xfc1ff3e0, "cocc@(b),t", pa20, FLAG_STRICT},
+{ "ldwa", 0x0c001180, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldwa", 0x0c001180, 0xfc00d3c0, "cmcc5(b),t", pa11, FLAG_STRICT},
+{ "ldcw", 0x0c0001c0, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldcw", 0x0c0001c0, 0xfc001fc0, "cXx(s,b),t", pa10, FLAG_STRICT},
+{ "ldcw", 0x0c0001c0, 0xfc00d3c0, "cxcdx(b),t", pa11, FLAG_STRICT},
+{ "ldcw", 0x0c0001c0, 0xfc0013c0, "cxcdx(s,b),t", pa11, FLAG_STRICT},
+{ "ldcw", 0x0c0011c0, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldcw", 0x0c0011c0, 0xfc001fc0, "cM5(s,b),t", pa10, FLAG_STRICT},
+{ "ldcw", 0x0c0011c0, 0xfc00d3c0, "cmcd5(b),t", pa11, FLAG_STRICT},
+{ "ldcw", 0x0c0011c0, 0xfc0013c0, "cmcd5(s,b),t", pa11, FLAG_STRICT},
+{ "stwa", 0x0c0013a0, 0xfc00d3ff, "cocCx,@(b)", pa20, FLAG_STRICT},
+{ "stwa", 0x0c001380, 0xfc00dfc0, "cMx,V(b)", pa10, FLAG_STRICT},
+{ "stwa", 0x0c001380, 0xfc00d3c0, "cmcCx,V(b)", pa11, FLAG_STRICT},
+{ "stby", 0x0c001300, 0xfc00dfc0, "cAx,V(b)", pa10, FLAG_STRICT},
+{ "stby", 0x0c001300, 0xfc001fc0, "cAx,V(s,b)", pa10, FLAG_STRICT},
+{ "stby", 0x0c001300, 0xfc00d3c0, "cscCx,V(b)", pa11, FLAG_STRICT},
+{ "stby", 0x0c001300, 0xfc0013c0, "cscCx,V(s,b)", pa11, FLAG_STRICT},
+{ "ldda", 0x0c000100, 0xfc00d3c0, "cxccx(b),t", pa20, FLAG_STRICT},
+{ "ldda", 0x0c001120, 0xfc1ff3e0, "cocc@(b),t", pa20, FLAG_STRICT},
+{ "ldda", 0x0c001100, 0xfc00d3c0, "cmcc5(b),t", pa20, FLAG_STRICT},
+{ "ldcd", 0x0c000140, 0xfc00d3c0, "cxcdx(b),t", pa20, FLAG_STRICT},
+{ "ldcd", 0x0c000140, 0xfc0013c0, "cxcdx(s,b),t", pa20, FLAG_STRICT},
+{ "ldcd", 0x0c001140, 0xfc00d3c0, "cmcd5(b),t", pa20, FLAG_STRICT},
+{ "ldcd", 0x0c001140, 0xfc0013c0, "cmcd5(s,b),t", pa20, FLAG_STRICT},
+{ "stda", 0x0c0013e0, 0xfc00f3ff, "cocCx,@(b)", pa20, FLAG_STRICT},
+{ "stda", 0x0c0013c0, 0xfc00d3c0, "cmcCx,V(b)", pa20, FLAG_STRICT},
+{ "ldwax", 0x0c000180, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldwax", 0x0c000180, 0xfc00d3c0, "cxccx(b),t", pa11, FLAG_STRICT},
+{ "ldwax", 0x0c000180, 0xfc00dfc0, "cXx(b),t", pa10, 0},
+{ "ldcwx", 0x0c0001c0, 0xfc00dfc0, "cXx(b),t", pa10, FLAG_STRICT},
+{ "ldcwx", 0x0c0001c0, 0xfc001fc0, "cXx(s,b),t", pa10, FLAG_STRICT},
+{ "ldcwx", 0x0c0001c0, 0xfc00d3c0, "cxcdx(b),t", pa11, FLAG_STRICT},
+{ "ldcwx", 0x0c0001c0, 0xfc0013c0, "cxcdx(s,b),t", pa11, FLAG_STRICT},
+{ "ldcwx", 0x0c0001c0, 0xfc00dfc0, "cXx(b),t", pa10, 0},
+{ "ldcwx", 0x0c0001c0, 0xfc001fc0, "cXx(s,b),t", pa10, 0},
+{ "ldws", 0x0c001080, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldws", 0x0c001080, 0xfc001fc0, "cM5(s,b),t", pa10, FLAG_STRICT},
+{ "ldws", 0x0c001080, 0xfc00d3c0, "cmcc5(b),t", pa11, FLAG_STRICT},
+{ "ldws", 0x0c001080, 0xfc0013c0, "cmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "ldws", 0x0c001080, 0xfc00dfc0, "cM5(b),t", pa10, 0},
+{ "ldws", 0x0c001080, 0xfc001fc0, "cM5(s,b),t", pa10, 0},
+{ "ldhs", 0x0c001040, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldhs", 0x0c001040, 0xfc001fc0, "cM5(s,b),t", pa10, FLAG_STRICT},
+{ "ldhs", 0x0c001040, 0xfc00d3c0, "cmcc5(b),t", pa11, FLAG_STRICT},
+{ "ldhs", 0x0c001040, 0xfc0013c0, "cmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "ldhs", 0x0c001040, 0xfc00dfc0, "cM5(b),t", pa10, 0},
+{ "ldhs", 0x0c001040, 0xfc001fc0, "cM5(s,b),t", pa10, 0},
+{ "ldbs", 0x0c001000, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldbs", 0x0c001000, 0xfc001fc0, "cM5(s,b),t", pa10, FLAG_STRICT},
+{ "ldbs", 0x0c001000, 0xfc00d3c0, "cmcc5(b),t", pa11, FLAG_STRICT},
+{ "ldbs", 0x0c001000, 0xfc0013c0, "cmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "ldbs", 0x0c001000, 0xfc00dfc0, "cM5(b),t", pa10, 0},
+{ "ldbs", 0x0c001000, 0xfc001fc0, "cM5(s,b),t", pa10, 0},
+{ "ldwas", 0x0c001180, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldwas", 0x0c001180, 0xfc00d3c0, "cmcc5(b),t", pa11, FLAG_STRICT},
+{ "ldwas", 0x0c001180, 0xfc00dfc0, "cM5(b),t", pa10, 0},
+{ "ldcws", 0x0c0011c0, 0xfc00dfc0, "cM5(b),t", pa10, FLAG_STRICT},
+{ "ldcws", 0x0c0011c0, 0xfc001fc0, "cM5(s,b),t", pa10, FLAG_STRICT},
+{ "ldcws", 0x0c0011c0, 0xfc00d3c0, "cmcd5(b),t", pa11, FLAG_STRICT},
+{ "ldcws", 0x0c0011c0, 0xfc0013c0, "cmcd5(s,b),t", pa11, FLAG_STRICT},
+{ "ldcws", 0x0c0011c0, 0xfc00dfc0, "cM5(b),t", pa10, 0},
+{ "ldcws", 0x0c0011c0, 0xfc001fc0, "cM5(s,b),t", pa10, 0},
+{ "stws", 0x0c001280, 0xfc00dfc0, "cMx,V(b)", pa10, FLAG_STRICT},
+{ "stws", 0x0c001280, 0xfc001fc0, "cMx,V(s,b)", pa10, FLAG_STRICT},
+{ "stws", 0x0c001280, 0xfc00d3c0, "cmcCx,V(b)", pa11, FLAG_STRICT},
+{ "stws", 0x0c001280, 0xfc0013c0, "cmcCx,V(s,b)", pa11, FLAG_STRICT},
+{ "stws", 0x0c001280, 0xfc00dfc0, "cMx,V(b)", pa10, 0},
+{ "stws", 0x0c001280, 0xfc001fc0, "cMx,V(s,b)", pa10, 0},
+{ "sths", 0x0c001240, 0xfc00dfc0, "cMx,V(b)", pa10, FLAG_STRICT},
+{ "sths", 0x0c001240, 0xfc001fc0, "cMx,V(s,b)", pa10, FLAG_STRICT},
+{ "sths", 0x0c001240, 0xfc00d3c0, "cmcCx,V(b)", pa11, FLAG_STRICT},
+{ "sths", 0x0c001240, 0xfc0013c0, "cmcCx,V(s,b)", pa11, FLAG_STRICT},
+{ "sths", 0x0c001240, 0xfc00dfc0, "cMx,V(b)", pa10, 0},
+{ "sths", 0x0c001240, 0xfc001fc0, "cMx,V(s,b)", pa10, 0},
+{ "stbs", 0x0c001200, 0xfc00dfc0, "cMx,V(b)", pa10, FLAG_STRICT},
+{ "stbs", 0x0c001200, 0xfc001fc0, "cMx,V(s,b)", pa10, FLAG_STRICT},
+{ "stbs", 0x0c001200, 0xfc00d3c0, "cmcCx,V(b)", pa11, FLAG_STRICT},
+{ "stbs", 0x0c001200, 0xfc0013c0, "cmcCx,V(s,b)", pa11, FLAG_STRICT},
+{ "stbs", 0x0c001200, 0xfc00dfc0, "cMx,V(b)", pa10, 0},
+{ "stbs", 0x0c001200, 0xfc001fc0, "cMx,V(s,b)", pa10, 0},
+{ "stwas", 0x0c001380, 0xfc00dfc0, "cMx,V(b)", pa10, FLAG_STRICT},
+{ "stwas", 0x0c001380, 0xfc00d3c0, "cmcCx,V(b)", pa11, FLAG_STRICT},
+{ "stwas", 0x0c001380, 0xfc00dfc0, "cMx,V(b)", pa10, 0},
+{ "stdby", 0x0c001340, 0xfc00d3c0, "cscCx,V(b)", pa20, FLAG_STRICT},
+{ "stdby", 0x0c001340, 0xfc0013c0, "cscCx,V(s,b)", pa20, FLAG_STRICT},
+{ "stbys", 0x0c001300, 0xfc00dfc0, "cAx,V(b)", pa10, FLAG_STRICT},
+{ "stbys", 0x0c001300, 0xfc001fc0, "cAx,V(s,b)", pa10, FLAG_STRICT},
+{ "stbys", 0x0c001300, 0xfc00d3c0, "cscCx,V(b)", pa11, FLAG_STRICT},
+{ "stbys", 0x0c001300, 0xfc0013c0, "cscCx,V(s,b)", pa11, FLAG_STRICT},
+{ "stbys", 0x0c001300, 0xfc00dfc0, "cAx,V(b)", pa10, 0},
+{ "stbys", 0x0c001300, 0xfc001fc0, "cAx,V(s,b)", pa10, 0},
+
+/* Immediate instructions. */
+{ "ldo", 0x34000000, 0xfc000000, "l(b),x", pa20w, 0},
+{ "ldo", 0x34000000, 0xfc00c000, "j(b),x", pa10, 0},
+{ "ldil", 0x20000000, 0xfc000000, "k,b", pa10, 0},
+{ "addil", 0x28000000, 0xfc000000, "k,b,Z", pa10, 0},
+{ "addil", 0x28000000, 0xfc000000, "k,b", pa10, 0},
+
+/* Branching instructions. */
+{ "b", 0xe8008000, 0xfc00e000, "cpnXL", pa20, FLAG_STRICT},
+{ "b", 0xe800a000, 0xfc00e000, "clnXL", pa20, FLAG_STRICT},
+{ "b", 0xe8000000, 0xfc00e000, "clnW,b", pa10, FLAG_STRICT},
+{ "b", 0xe8002000, 0xfc00e000, "cgnW,b", pa10, FLAG_STRICT},
+{ "b", 0xe8000000, 0xffe0e000, "nW", pa10, 0}, /* b,l foo,r0 */
+{ "bl", 0xe8000000, 0xfc00e000, "nW,b", pa10, 0},
+{ "gate", 0xe8002000, 0xfc00e000, "nW,b", pa10, 0},
+{ "blr", 0xe8004000, 0xfc00e001, "nx,b", pa10, 0},
+{ "bv", 0xe800c000, 0xfc00fffd, "nx(b)", pa10, 0},
+{ "bv", 0xe800c000, 0xfc00fffd, "n(b)", pa10, 0},
+{ "bve", 0xe800f001, 0xfc1ffffd, "cpn(b)L", pa20, FLAG_STRICT},
+{ "bve", 0xe800f000, 0xfc1ffffd, "cln(b)L", pa20, FLAG_STRICT},
+{ "bve", 0xe800d001, 0xfc1ffffd, "cPn(b)", pa20, FLAG_STRICT},
+{ "bve", 0xe800d000, 0xfc1ffffd, "n(b)", pa20, FLAG_STRICT},
+{ "be", 0xe4000000, 0xfc000000, "clnz(S,b),Y", pa10, FLAG_STRICT},
+{ "be", 0xe4000000, 0xfc000000, "clnz(b),Y", pa10, FLAG_STRICT},
+{ "be", 0xe0000000, 0xfc000000, "nz(S,b)", pa10, 0},
+{ "be", 0xe0000000, 0xfc000000, "nz(b)", pa10, 0},
+{ "ble", 0xe4000000, 0xfc000000, "nz(S,b)", pa10, 0},
+{ "movb", 0xc8000000, 0xfc000000, "?ynx,b,w", pa10, 0},
+{ "movib", 0xcc000000, 0xfc000000, "?yn5,b,w", pa10, 0},
+{ "combt", 0x80000000, 0xfc000000, "?tnx,b,w", pa10, 0},
+{ "combf", 0x88000000, 0xfc000000, "?tnx,b,w", pa10, 0},
+{ "comibt", 0x84000000, 0xfc000000, "?tn5,b,w", pa10, 0},
+{ "comibf", 0x8c000000, 0xfc000000, "?tn5,b,w", pa10, 0},
+{ "addbt", 0xa0000000, 0xfc000000, "?dnx,b,w", pa10, 0},
+{ "addbf", 0xa8000000, 0xfc000000, "?dnx,b,w", pa10, 0},
+{ "addibt", 0xa4000000, 0xfc000000, "?dn5,b,w", pa10, 0},
+{ "addibf", 0xac000000, 0xfc000000, "?dn5,b,w", pa10, 0},
+{ "bb", 0xc0004000, 0xffe06000, "?bnx,!,w", pa10, FLAG_STRICT},
+{ "bb", 0xc0006000, 0xffe06000, "?Bnx,!,w", pa20, FLAG_STRICT},
+{ "bb", 0xc4004000, 0xfc006000, "?bnx,Q,w", pa10, FLAG_STRICT},
+{ "bb", 0xc4004000, 0xfc004000, "?Bnx,B,w", pa20, FLAG_STRICT},
+{ "bvb", 0xc0004000, 0xffe04000, "?bnx,w", pa10, 0},
+{ "clrbts", 0xe8004005, 0xffffffff, "", pa20, FLAG_STRICT},
+{ "popbts", 0xe8004005, 0xfffff007, "$", pa20, FLAG_STRICT},
+{ "pushnom", 0xe8004001, 0xffffffff, "", pa20, FLAG_STRICT},
+{ "pushbts", 0xe8004001, 0xffe0ffff, "x", pa20, FLAG_STRICT},
+
+/* Computation Instructions. */
+
+{ "cmpclr", 0x080008a0, 0xfc000fe0, "?Sx,b,t", pa20, FLAG_STRICT},
+{ "cmpclr", 0x08000880, 0xfc000fe0, "?sx,b,t", pa10, FLAG_STRICT},
+{ "comclr", 0x08000880, 0xfc000fe0, "?sx,b,t", pa10, 0},
+{ "or", 0x08000260, 0xfc000fe0, "?Lx,b,t", pa20, FLAG_STRICT},
+{ "or", 0x08000240, 0xfc000fe0, "?lx,b,t", pa10, 0},
+{ "xor", 0x080002a0, 0xfc000fe0, "?Lx,b,t", pa20, FLAG_STRICT},
+{ "xor", 0x08000280, 0xfc000fe0, "?lx,b,t", pa10, 0},
+{ "and", 0x08000220, 0xfc000fe0, "?Lx,b,t", pa20, FLAG_STRICT},
+{ "and", 0x08000200, 0xfc000fe0, "?lx,b,t", pa10, 0},
+{ "andcm", 0x08000020, 0xfc000fe0, "?Lx,b,t", pa20, FLAG_STRICT},
+{ "andcm", 0x08000000, 0xfc000fe0, "?lx,b,t", pa10, 0},
+{ "uxor", 0x080003a0, 0xfc000fe0, "?Ux,b,t", pa20, FLAG_STRICT},
+{ "uxor", 0x08000380, 0xfc000fe0, "?ux,b,t", pa10, 0},
+{ "uaddcm", 0x080009a0, 0xfc000fa0, "cT?Ux,b,t", pa20, FLAG_STRICT},
+{ "uaddcm", 0x08000980, 0xfc000fa0, "cT?ux,b,t", pa10, FLAG_STRICT},
+{ "uaddcm", 0x08000980, 0xfc000fe0, "?ux,b,t", pa10, 0},
+{ "uaddcmt", 0x080009c0, 0xfc000fe0, "?ux,b,t", pa10, 0},
+{ "dcor", 0x08000ba0, 0xfc1f0fa0, "ci?Ub,t", pa20, FLAG_STRICT},
+{ "dcor", 0x08000b80, 0xfc1f0fa0, "ci?ub,t", pa10, FLAG_STRICT},
+{ "dcor", 0x08000b80, 0xfc1f0fe0, "?ub,t", pa10, 0},
+{ "idcor", 0x08000bc0, 0xfc1f0fe0, "?ub,t", pa10, 0},
+{ "addi", 0xb0000000, 0xfc000000, "ct?ai,b,x", pa10, FLAG_STRICT},
+{ "addi", 0xb4000000, 0xfc000000, "cv?ai,b,x", pa10, FLAG_STRICT},
+{ "addi", 0xb4000000, 0xfc000800, "?ai,b,x", pa10, 0},
+{ "addio", 0xb4000800, 0xfc000800, "?ai,b,x", pa10, 0},
+{ "addit", 0xb0000000, 0xfc000800, "?ai,b,x", pa10, 0},
+{ "addito", 0xb0000800, 0xfc000800, "?ai,b,x", pa10, 0},
+{ "add", 0x08000720, 0xfc0007e0, "cY?Ax,b,t", pa20, FLAG_STRICT},
+{ "add", 0x08000700, 0xfc0007e0, "cy?ax,b,t", pa10, FLAG_STRICT},
+{ "add", 0x08000220, 0xfc0003e0, "ca?Ax,b,t", pa20, FLAG_STRICT},
+{ "add", 0x08000200, 0xfc0003e0, "ca?ax,b,t", pa10, FLAG_STRICT},
+{ "add", 0x08000600, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "addl", 0x08000a00, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "addo", 0x08000e00, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "addc", 0x08000700, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "addco", 0x08000f00, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sub", 0x080004e0, 0xfc0007e0, "ct?Sx,b,t", pa20, FLAG_STRICT},
+{ "sub", 0x080004c0, 0xfc0007e0, "ct?sx,b,t", pa10, FLAG_STRICT},
+{ "sub", 0x08000520, 0xfc0007e0, "cB?Sx,b,t", pa20, FLAG_STRICT},
+{ "sub", 0x08000500, 0xfc0007e0, "cb?sx,b,t", pa10, FLAG_STRICT},
+{ "sub", 0x08000420, 0xfc0007e0, "cv?Sx,b,t", pa20, FLAG_STRICT},
+{ "sub", 0x08000400, 0xfc0007e0, "cv?sx,b,t", pa10, FLAG_STRICT},
+{ "sub", 0x08000400, 0xfc000fe0, "?sx,b,t", pa10, 0},
+{ "subo", 0x08000c00, 0xfc000fe0, "?sx,b,t", pa10, 0},
+{ "subb", 0x08000500, 0xfc000fe0, "?sx,b,t", pa10, 0},
+{ "subbo", 0x08000d00, 0xfc000fe0, "?sx,b,t", pa10, 0},
+{ "subt", 0x080004c0, 0xfc000fe0, "?sx,b,t", pa10, 0},
+{ "subto", 0x08000cc0, 0xfc000fe0, "?sx,b,t", pa10, 0},
+{ "ds", 0x08000440, 0xfc000fe0, "?sx,b,t", pa10, 0},
+{ "subi", 0x94000000, 0xfc000000, "cv?si,b,x", pa10, FLAG_STRICT},
+{ "subi", 0x94000000, 0xfc000800, "?si,b,x", pa10, 0},
+{ "subio", 0x94000800, 0xfc000800, "?si,b,x", pa10, 0},
+{ "cmpiclr", 0x90000800, 0xfc000800, "?Si,b,x", pa20, FLAG_STRICT},
+{ "cmpiclr", 0x90000000, 0xfc000800, "?si,b,x", pa10, FLAG_STRICT},
+{ "comiclr", 0x90000000, 0xfc000800, "?si,b,x", pa10, 0},
+{ "shladd", 0x08000220, 0xfc000320, "ca?Ax,.,b,t", pa20, FLAG_STRICT},
+{ "shladd", 0x08000200, 0xfc000320, "ca?ax,.,b,t", pa10, FLAG_STRICT},
+{ "sh1add", 0x08000640, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sh1addl", 0x08000a40, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sh1addo", 0x08000e40, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sh2add", 0x08000680, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sh2addl", 0x08000a80, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sh2addo", 0x08000e80, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sh3add", 0x080006c0, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sh3addl", 0x08000ac0, 0xfc000fe0, "?ax,b,t", pa10, 0},
+{ "sh3addo", 0x08000ec0, 0xfc000fe0, "?ax,b,t", pa10, 0},
+
+/* Subword Operation Instructions. */
+
+{ "hadd", 0x08000300, 0xfc00ff20, "cHx,b,t", pa20, FLAG_STRICT},
+{ "havg", 0x080002c0, 0xfc00ffe0, "x,b,t", pa20, FLAG_STRICT},
+{ "hshl", 0xf8008800, 0xffe0fc20, "x,*,t", pa20, FLAG_STRICT},
+{ "hshladd", 0x08000700, 0xfc00ff20, "x,.,b,t", pa20, FLAG_STRICT},
+{ "hshr", 0xf800c800, 0xfc1ff820, "cSb,*,t", pa20, FLAG_STRICT},
+{ "hshradd", 0x08000500, 0xfc00ff20, "x,.,b,t", pa20, FLAG_STRICT},
+{ "hsub", 0x08000100, 0xfc00ff20, "cHx,b,t", pa20, FLAG_STRICT},
+{ "mixh", 0xf8008400, 0xfc009fe0, "chx,b,t", pa20, FLAG_STRICT},
+{ "mixw", 0xf8008000, 0xfc009fe0, "chx,b,t", pa20, FLAG_STRICT},
+{ "permh", 0xf8000000, 0xfc009020, "c*a,t", pa20, FLAG_STRICT},
+
+
+/* Extract and Deposit Instructions. */
+
+{ "shrpd", 0xd0000200, 0xfc001fe0, "?Xx,b,!,t", pa20, FLAG_STRICT},
+{ "shrpd", 0xd0000400, 0xfc001400, "?Xx,b,~,t", pa20, FLAG_STRICT},
+{ "shrpw", 0xd0000000, 0xfc001fe0, "?xx,b,!,t", pa10, FLAG_STRICT},
+{ "shrpw", 0xd0000800, 0xfc001c00, "?xx,b,p,t", pa10, FLAG_STRICT},
+{ "vshd", 0xd0000000, 0xfc001fe0, "?xx,b,t", pa10, 0},
+{ "shd", 0xd0000800, 0xfc001c00, "?xx,b,p,t", pa10, 0},
+{ "extrd", 0xd0001200, 0xfc001ae0, "cS?Xb,!,%,x", pa20, FLAG_STRICT},
+{ "extrd", 0xd8000000, 0xfc000000, "cS?Xb,q,|,x", pa20, FLAG_STRICT},
+{ "extrw", 0xd0001000, 0xfc001be0, "cS?xb,!,T,x", pa10, FLAG_STRICT},
+{ "extrw", 0xd0001800, 0xfc001800, "cS?xb,P,T,x", pa10, FLAG_STRICT},
+{ "vextru", 0xd0001000, 0xfc001fe0, "?xb,T,x", pa10, 0},
+{ "vextrs", 0xd0001400, 0xfc001fe0, "?xb,T,x", pa10, 0},
+{ "extru", 0xd0001800, 0xfc001c00, "?xb,P,T,x", pa10, 0},
+{ "extrs", 0xd0001c00, 0xfc001c00, "?xb,P,T,x", pa10, 0},
+{ "depd", 0xd4000200, 0xfc001ae0, "cz?Xx,!,%,b", pa20, FLAG_STRICT},
+{ "depd", 0xf0000000, 0xfc000000, "cz?Xx,~,|,b", pa20, FLAG_STRICT},
+{ "depdi", 0xd4001200, 0xfc001ae0, "cz?X5,!,%,b", pa20, FLAG_STRICT},
+{ "depdi", 0xf4000000, 0xfc000000, "cz?X5,~,|,b", pa20, FLAG_STRICT},
+{ "depw", 0xd4000000, 0xfc001be0, "cz?xx,!,T,b", pa10, FLAG_STRICT},
+{ "depw", 0xd4000800, 0xfc001800, "cz?xx,p,T,b", pa10, FLAG_STRICT},
+{ "depwi", 0xd4001000, 0xfc001be0, "cz?x5,!,T,b", pa10, FLAG_STRICT},
+{ "depwi", 0xd4001800, 0xfc001800, "cz?x5,p,T,b", pa10, FLAG_STRICT},
+{ "zvdep", 0xd4000000, 0xfc001fe0, "?xx,T,b", pa10, 0},
+{ "vdep", 0xd4000400, 0xfc001fe0, "?xx,T,b", pa10, 0},
+{ "zdep", 0xd4000800, 0xfc001c00, "?xx,p,T,b", pa10, 0},
+{ "dep", 0xd4000c00, 0xfc001c00, "?xx,p,T,b", pa10, 0},
+{ "zvdepi", 0xd4001000, 0xfc001fe0, "?x5,T,b", pa10, 0},
+{ "vdepi", 0xd4001400, 0xfc001fe0, "?x5,T,b", pa10, 0},
+{ "zdepi", 0xd4001800, 0xfc001c00, "?x5,p,T,b", pa10, 0},
+{ "depi", 0xd4001c00, 0xfc001c00, "?x5,p,T,b", pa10, 0},
+
+/* System Control Instructions. */
+
+{ "break", 0x00000000, 0xfc001fe0, "r,A", pa10, 0},
+{ "rfi", 0x00000c00, 0xffffff1f, "cr", pa10, FLAG_STRICT},
+{ "rfi", 0x00000c00, 0xffffffff, "", pa10, 0},
+{ "rfir", 0x00000ca0, 0xffffffff, "", pa11, 0},
+{ "ssm", 0x00000d60, 0xfc00ffe0, "U,t", pa20, FLAG_STRICT},
+{ "ssm", 0x00000d60, 0xffe0ffe0, "R,t", pa10, 0},
+{ "rsm", 0x00000e60, 0xfc00ffe0, "U,t", pa20, FLAG_STRICT},
+{ "rsm", 0x00000e60, 0xffe0ffe0, "R,t", pa10, 0},
+{ "mtsm", 0x00001860, 0xffe0ffff, "x", pa10, 0},
+{ "ldsid", 0x000010a0, 0xfc1fffe0, "(b),t", pa10, 0},
+{ "ldsid", 0x000010a0, 0xfc1f3fe0, "(s,b),t", pa10, 0},
+{ "mtsp", 0x00001820, 0xffe01fff, "x,S", pa10, 0},
+{ "mtctl", 0x00001840, 0xfc00ffff, "x,^", pa10, 0},
+{ "mtsarcm", 0x016018C0, 0xffe0ffff, "x", pa20, FLAG_STRICT},
+{ "mfia", 0x000014A0, 0xffffffe0, "t", pa20, FLAG_STRICT},
+{ "mfsp", 0x000004a0, 0xffff1fe0, "S,t", pa10, 0},
+{ "mfctl", 0x016048a0, 0xffffffe0, "cW!,t", pa20, FLAG_STRICT},
+{ "mfctl", 0x000008a0, 0xfc1fffe0, "^,t", pa10, 0},
+{ "sync", 0x00000400, 0xffffffff, "", pa10, 0},
+{ "syncdma", 0x00100400, 0xffffffff, "", pa10, 0},
+{ "probe", 0x04001180, 0xfc00ffa0, "cw(b),x,t", pa10, FLAG_STRICT},
+{ "probe", 0x04001180, 0xfc003fa0, "cw(s,b),x,t", pa10, FLAG_STRICT},
+{ "probei", 0x04003180, 0xfc00ffa0, "cw(b),R,t", pa10, FLAG_STRICT},
+{ "probei", 0x04003180, 0xfc003fa0, "cw(s,b),R,t", pa10, FLAG_STRICT},
+{ "prober", 0x04001180, 0xfc00ffe0, "(b),x,t", pa10, 0},
+{ "prober", 0x04001180, 0xfc003fe0, "(s,b),x,t", pa10, 0},
+{ "proberi", 0x04003180, 0xfc00ffe0, "(b),R,t", pa10, 0},
+{ "proberi", 0x04003180, 0xfc003fe0, "(s,b),R,t", pa10, 0},
+{ "probew", 0x040011c0, 0xfc00ffe0, "(b),x,t", pa10, 0},
+{ "probew", 0x040011c0, 0xfc003fe0, "(s,b),x,t", pa10, 0},
+{ "probewi", 0x040031c0, 0xfc00ffe0, "(b),R,t", pa10, 0},
+{ "probewi", 0x040031c0, 0xfc003fe0, "(s,b),R,t", pa10, 0},
+{ "lpa", 0x04001340, 0xfc00ffc0, "cZx(b),t", pa10, 0},
+{ "lpa", 0x04001340, 0xfc003fc0, "cZx(s,b),t", pa10, 0},
+{ "lci", 0x04001300, 0xfc00ffe0, "x(b),t", pa11, 0},
+{ "lci", 0x04001300, 0xfc003fe0, "x(s,b),t", pa11, 0},
+{ "pdtlb", 0x04001600, 0xfc00ffdf, "cLcZx(b)", pa20, FLAG_STRICT},
+{ "pdtlb", 0x04001600, 0xfc003fdf, "cLcZx(s,b)", pa20, FLAG_STRICT},
+{ "pdtlb", 0x04001600, 0xfc1fffdf, "cLcZ@(b)", pa20, FLAG_STRICT},
+{ "pdtlb", 0x04001600, 0xfc1f3fdf, "cLcZ@(s,b)", pa20, FLAG_STRICT},
+{ "pdtlb", 0x04001200, 0xfc00ffdf, "cZx(b)", pa10, 0},
+{ "pdtlb", 0x04001200, 0xfc003fdf, "cZx(s,b)", pa10, 0},
+{ "pitlb", 0x04000600, 0xfc001fdf, "cLcZx(S,b)", pa20, FLAG_STRICT},
+{ "pitlb", 0x04000600, 0xfc1f1fdf, "cLcZ@(S,b)", pa20, FLAG_STRICT},
+{ "pitlb", 0x04000200, 0xfc001fdf, "cZx(S,b)", pa10, 0},
+{ "pdtlbe", 0x04001240, 0xfc00ffdf, "cZx(b)", pa10, 0},
+{ "pdtlbe", 0x04001240, 0xfc003fdf, "cZx(s,b)", pa10, 0},
+{ "pitlbe", 0x04000240, 0xfc001fdf, "cZx(S,b)", pa10, 0},
+{ "idtlba", 0x04001040, 0xfc00ffff, "x,(b)", pa10, 0},
+{ "idtlba", 0x04001040, 0xfc003fff, "x,(s,b)", pa10, 0},
+{ "iitlba", 0x04000040, 0xfc001fff, "x,(S,b)", pa10, 0},
+{ "idtlbp", 0x04001000, 0xfc00ffff, "x,(b)", pa10, 0},
+{ "idtlbp", 0x04001000, 0xfc003fff, "x,(s,b)", pa10, 0},
+{ "iitlbp", 0x04000000, 0xfc001fff, "x,(S,b)", pa10, 0},
+{ "pdc", 0x04001380, 0xfc00ffdf, "cZx(b)", pa10, 0},
+{ "pdc", 0x04001380, 0xfc003fdf, "cZx(s,b)", pa10, 0},
+{ "fdc", 0x04001280, 0xfc00ffdf, "cZx(b)", pa10, FLAG_STRICT},
+{ "fdc", 0x04001280, 0xfc003fdf, "cZx(s,b)", pa10, FLAG_STRICT},
+{ "fdc", 0x04003280, 0xfc00ffff, "5(b)", pa20, FLAG_STRICT},
+{ "fdc", 0x04003280, 0xfc003fff, "5(s,b)", pa20, FLAG_STRICT},
+{ "fdc", 0x04001280, 0xfc00ffdf, "cZx(b)", pa10, 0},
+{ "fdc", 0x04001280, 0xfc003fdf, "cZx(s,b)", pa10, 0},
+{ "fic", 0x040013c0, 0xfc00dfdf, "cZx(b)", pa20, FLAG_STRICT},
+{ "fic", 0x04000280, 0xfc001fdf, "cZx(S,b)", pa10, 0},
+{ "fdce", 0x040012c0, 0xfc00ffdf, "cZx(b)", pa10, 0},
+{ "fdce", 0x040012c0, 0xfc003fdf, "cZx(s,b)", pa10, 0},
+{ "fice", 0x040002c0, 0xfc001fdf, "cZx(S,b)", pa10, 0},
+{ "diag", 0x14000000, 0xfc000000, "D", pa10, 0},
+{ "idtlbt", 0x04001800, 0xfc00ffff, "x,b", pa20, FLAG_STRICT},
+{ "iitlbt", 0x04000800, 0xfc00ffff, "x,b", pa20, FLAG_STRICT},
+
+/* These may be specific to certain versions of the PA. Joel claimed
+ they were 72000 (7200?) specific. However, I'm almost certain the
+ mtcpu/mfcpu were undocumented, but available in the older 700 machines. */
+{ "mtcpu", 0x14001600, 0xfc00ffff, "x,^", pa10, 0},
+{ "mfcpu", 0x14001A00, 0xfc00ffff, "^,x", pa10, 0},
+{ "tocen", 0x14403600, 0xffffffff, "", pa10, 0},
+{ "tocdis", 0x14401620, 0xffffffff, "", pa10, 0},
+{ "shdwgr", 0x14402600, 0xffffffff, "", pa10, 0},
+{ "grshdw", 0x14400620, 0xffffffff, "", pa10, 0},
+
+/* gfw and gfr are not in the HP PA 1.1 manual, but they are in either
+ the Timex FPU or the Mustang ERS (not sure which) manual. */
+{ "gfw", 0x04001680, 0xfc00ffdf, "cZx(b)", pa11, 0},
+{ "gfw", 0x04001680, 0xfc003fdf, "cZx(s,b)", pa11, 0},
+{ "gfr", 0x04001a80, 0xfc00ffdf, "cZx(b)", pa11, 0},
+{ "gfr", 0x04001a80, 0xfc003fdf, "cZx(s,b)", pa11, 0},
+
+/* Floating Point Coprocessor Instructions. */
+
+{ "fldw", 0x24000000, 0xfc00df80, "cXx(b),fT", pa10, FLAG_STRICT},
+{ "fldw", 0x24000000, 0xfc001f80, "cXx(s,b),fT", pa10, FLAG_STRICT},
+{ "fldw", 0x24000000, 0xfc00d380, "cxccx(b),fT", pa11, FLAG_STRICT},
+{ "fldw", 0x24000000, 0xfc001380, "cxccx(s,b),fT", pa11, FLAG_STRICT},
+{ "fldw", 0x24001020, 0xfc1ff3a0, "cocc@(b),fT", pa20, FLAG_STRICT},
+{ "fldw", 0x24001020, 0xfc1f33a0, "cocc@(s,b),fT", pa20, FLAG_STRICT},
+{ "fldw", 0x24001000, 0xfc00df80, "cM5(b),fT", pa10, FLAG_STRICT},
+{ "fldw", 0x24001000, 0xfc001f80, "cM5(s,b),fT", pa10, FLAG_STRICT},
+{ "fldw", 0x24001000, 0xfc00d380, "cmcc5(b),fT", pa11, FLAG_STRICT},
+{ "fldw", 0x24001000, 0xfc001380, "cmcc5(s,b),fT", pa11, FLAG_STRICT},
+{ "fldw", 0x5c000000, 0xfc000004, "y(b),fe", pa20w, FLAG_STRICT},
+{ "fldw", 0x58000000, 0xfc000000, "cJy(b),fe", pa20w, FLAG_STRICT},
+{ "fldw", 0x5c000000, 0xfc00c004, "d(b),fe", pa20, FLAG_STRICT},
+{ "fldw", 0x5c000000, 0xfc000004, "d(s,b),fe", pa20, FLAG_STRICT},
+{ "fldw", 0x58000000, 0xfc00c000, "cJd(b),fe", pa20, FLAG_STRICT},
+{ "fldw", 0x58000000, 0xfc000000, "cJd(s,b),fe", pa20, FLAG_STRICT},
+{ "fldd", 0x2c000000, 0xfc00dfc0, "cXx(b),ft", pa10, FLAG_STRICT},
+{ "fldd", 0x2c000000, 0xfc001fc0, "cXx(s,b),ft", pa10, FLAG_STRICT},
+{ "fldd", 0x2c000000, 0xfc00d3c0, "cxccx(b),ft", pa11, FLAG_STRICT},
+{ "fldd", 0x2c000000, 0xfc0013c0, "cxccx(s,b),ft", pa11, FLAG_STRICT},
+{ "fldd", 0x2c001020, 0xfc1ff3e0, "cocc@(b),ft", pa20, FLAG_STRICT},
+{ "fldd", 0x2c001020, 0xfc1f33e0, "cocc@(s,b),ft", pa20, FLAG_STRICT},
+{ "fldd", 0x2c001000, 0xfc00dfc0, "cM5(b),ft", pa10, FLAG_STRICT},
+{ "fldd", 0x2c001000, 0xfc001fc0, "cM5(s,b),ft", pa10, FLAG_STRICT},
+{ "fldd", 0x2c001000, 0xfc00d3c0, "cmcc5(b),ft", pa11, FLAG_STRICT},
+{ "fldd", 0x2c001000, 0xfc0013c0, "cmcc5(s,b),ft", pa11, FLAG_STRICT},
+{ "fldd", 0x50000002, 0xfc000002, "cq&(b),fx", pa20w, FLAG_STRICT},
+{ "fldd", 0x50000002, 0xfc00c002, "cq#(b),fx", pa20, FLAG_STRICT},
+{ "fldd", 0x50000002, 0xfc000002, "cq#(s,b),fx", pa20, FLAG_STRICT},
+{ "fstw", 0x24000200, 0xfc00df80, "cXfT,x(b)", pa10, FLAG_STRICT},
+{ "fstw", 0x24000200, 0xfc001f80, "cXfT,x(s,b)", pa10, FLAG_STRICT},
+{ "fstw", 0x24000200, 0xfc00d380, "cxcCfT,x(b)", pa11, FLAG_STRICT},
+{ "fstw", 0x24000200, 0xfc001380, "cxcCfT,x(s,b)", pa11, FLAG_STRICT},
+{ "fstw", 0x24001220, 0xfc1ff3a0, "cocCfT,@(b)", pa20, FLAG_STRICT},
+{ "fstw", 0x24001220, 0xfc1f33a0, "cocCfT,@(s,b)", pa20, FLAG_STRICT},
+{ "fstw", 0x24001200, 0xfc00df80, "cMfT,5(b)", pa10, FLAG_STRICT},
+{ "fstw", 0x24001200, 0xfc001f80, "cMfT,5(s,b)", pa10, FLAG_STRICT},
+{ "fstw", 0x24001200, 0xfc00df80, "cMfT,5(b)", pa10, FLAG_STRICT},
+{ "fstw", 0x24001200, 0xfc001f80, "cMfT,5(s,b)", pa10, FLAG_STRICT},
+{ "fstw", 0x7c000000, 0xfc000004, "fE,y(b)", pa20w, FLAG_STRICT},
+{ "fstw", 0x78000000, 0xfc000000, "cJfE,y(b)", pa20w, FLAG_STRICT},
+{ "fstw", 0x7c000000, 0xfc00c004, "fE,d(b)", pa20, FLAG_STRICT},
+{ "fstw", 0x7c000000, 0xfc000004, "fE,d(s,b)", pa20, FLAG_STRICT},
+{ "fstw", 0x78000000, 0xfc00c000, "cJfE,d(b)", pa20, FLAG_STRICT},
+{ "fstw", 0x78000000, 0xfc000000, "cJfE,d(s,b)", pa20, FLAG_STRICT},
+{ "fstd", 0x2c000200, 0xfc00dfc0, "cXft,x(b)", pa10, FLAG_STRICT},
+{ "fstd", 0x2c000200, 0xfc001fc0, "cXft,x(s,b)", pa10, FLAG_STRICT},
+{ "fstd", 0x2c000200, 0xfc00d3c0, "cxcCft,x(b)", pa11, FLAG_STRICT},
+{ "fstd", 0x2c000200, 0xfc0013c0, "cxcCft,x(s,b)", pa11, FLAG_STRICT},
+{ "fstd", 0x2c001220, 0xfc1ff3e0, "cocCft,@(b)", pa20, FLAG_STRICT},
+{ "fstd", 0x2c001220, 0xfc1f33e0, "cocCft,@(s,b)", pa20, FLAG_STRICT},
+{ "fstd", 0x2c001200, 0xfc00dfc0, "cMft,5(b)", pa10, FLAG_STRICT},
+{ "fstd", 0x2c001200, 0xfc001fc0, "cMft,5(s,b)", pa10, FLAG_STRICT},
+{ "fstd", 0x2c001200, 0xfc00d3c0, "cmcCft,5(b)", pa11, FLAG_STRICT},
+{ "fstd", 0x2c001200, 0xfc0013c0, "cmcCft,5(s,b)", pa11, FLAG_STRICT},
+{ "fstd", 0x70000002, 0xfc000002, "cqfx,&(b)", pa20w, FLAG_STRICT},
+{ "fstd", 0x70000002, 0xfc00c002, "cqfx,#(b)", pa20, FLAG_STRICT},
+{ "fstd", 0x70000002, 0xfc000002, "cqfx,#(s,b)", pa20, FLAG_STRICT},
+{ "fldwx", 0x24000000, 0xfc00df80, "cXx(b),fT", pa10, FLAG_STRICT},
+{ "fldwx", 0x24000000, 0xfc001f80, "cXx(s,b),fT", pa10, FLAG_STRICT},
+{ "fldwx", 0x24000000, 0xfc00d380, "cxccx(b),fT", pa11, FLAG_STRICT},
+{ "fldwx", 0x24000000, 0xfc001380, "cxccx(s,b),fT", pa11, FLAG_STRICT},
+{ "fldwx", 0x24000000, 0xfc00df80, "cXx(b),fT", pa10, 0},
+{ "fldwx", 0x24000000, 0xfc001f80, "cXx(s,b),fT", pa10, 0},
+{ "flddx", 0x2c000000, 0xfc00dfc0, "cXx(b),ft", pa10, FLAG_STRICT},
+{ "flddx", 0x2c000000, 0xfc001fc0, "cXx(s,b),ft", pa10, FLAG_STRICT},
+{ "flddx", 0x2c000000, 0xfc00d3c0, "cxccx(b),ft", pa11, FLAG_STRICT},
+{ "flddx", 0x2c000000, 0xfc0013c0, "cxccx(s,b),ft", pa11, FLAG_STRICT},
+{ "flddx", 0x2c000000, 0xfc00dfc0, "cXx(b),ft", pa10, 0},
+{ "flddx", 0x2c000000, 0xfc001fc0, "cXx(s,b),ft", pa10, 0},
+{ "fstwx", 0x24000200, 0xfc00df80, "cxfT,x(b)", pa10, FLAG_STRICT},
+{ "fstwx", 0x24000200, 0xfc001f80, "cxfT,x(s,b)", pa10, FLAG_STRICT},
+{ "fstwx", 0x24000200, 0xfc00d380, "cxcCfT,x(b)", pa11, FLAG_STRICT},
+{ "fstwx", 0x24000200, 0xfc001380, "cxcCfT,x(s,b)", pa11, FLAG_STRICT},
+{ "fstwx", 0x24000200, 0xfc00df80, "cxfT,x(b)", pa10, 0},
+{ "fstwx", 0x24000200, 0xfc001f80, "cxfT,x(s,b)", pa10, 0},
+{ "fstdx", 0x2c000200, 0xfc00dfc0, "cxft,x(b)", pa10, FLAG_STRICT},
+{ "fstdx", 0x2c000200, 0xfc001fc0, "cxft,x(s,b)", pa10, FLAG_STRICT},
+{ "fstdx", 0x2c000200, 0xfc00d3c0, "cxcCft,x(b)", pa11, FLAG_STRICT},
+{ "fstdx", 0x2c000200, 0xfc0013c0, "cxcCft,x(s,b)", pa11, FLAG_STRICT},
+{ "fstdx", 0x2c000200, 0xfc00dfc0, "cxft,x(b)", pa10, 0},
+{ "fstdx", 0x2c000200, 0xfc001fc0, "cxft,x(s,b)", pa10, 0},
+{ "fstqx", 0x3c000200, 0xfc00dfc0, "cxft,x(b)", pa10, 0},
+{ "fstqx", 0x3c000200, 0xfc001fc0, "cxft,x(s,b)", pa10, 0},
+{ "fldws", 0x24001000, 0xfc00df80, "cm5(b),fT", pa10, FLAG_STRICT},
+{ "fldws", 0x24001000, 0xfc001f80, "cm5(s,b),fT", pa10, FLAG_STRICT},
+{ "fldws", 0x24001000, 0xfc00d380, "cmcc5(b),fT", pa11, FLAG_STRICT},
+{ "fldws", 0x24001000, 0xfc001380, "cmcc5(s,b),fT", pa11, FLAG_STRICT},
+{ "fldws", 0x24001000, 0xfc00df80, "cm5(b),fT", pa10, 0},
+{ "fldws", 0x24001000, 0xfc001f80, "cm5(s,b),fT", pa10, 0},
+{ "fldds", 0x2c001000, 0xfc00dfc0, "cm5(b),ft", pa10, FLAG_STRICT},
+{ "fldds", 0x2c001000, 0xfc001fc0, "cm5(s,b),ft", pa10, FLAG_STRICT},
+{ "fldds", 0x2c001000, 0xfc00d3c0, "cmcc5(b),ft", pa11, FLAG_STRICT},
+{ "fldds", 0x2c001000, 0xfc0013c0, "cmcc5(s,b),ft", pa11, FLAG_STRICT},
+{ "fldds", 0x2c001000, 0xfc00dfc0, "cm5(b),ft", pa10, 0},
+{ "fldds", 0x2c001000, 0xfc001fc0, "cm5(s,b),ft", pa10, 0},
+{ "fstws", 0x24001200, 0xfc00df80, "cmfT,5(b)", pa10, FLAG_STRICT},
+{ "fstws", 0x24001200, 0xfc001f80, "cmfT,5(s,b)", pa10, FLAG_STRICT},
+{ "fstws", 0x24001200, 0xfc00d380, "cmcCfT,5(b)", pa11, FLAG_STRICT},
+{ "fstws", 0x24001200, 0xfc001380, "cmcCfT,5(s,b)", pa11, FLAG_STRICT},
+{ "fstws", 0x24001200, 0xfc00df80, "cmfT,5(b)", pa10, 0},
+{ "fstws", 0x24001200, 0xfc001f80, "cmfT,5(s,b)", pa10, 0},
+{ "fstds", 0x2c001200, 0xfc00dfc0, "cmft,5(b)", pa10, FLAG_STRICT},
+{ "fstds", 0x2c001200, 0xfc001fc0, "cmft,5(s,b)", pa10, FLAG_STRICT},
+{ "fstds", 0x2c001200, 0xfc00d3c0, "cmcCft,5(b)", pa11, FLAG_STRICT},
+{ "fstds", 0x2c001200, 0xfc0013c0, "cmcCft,5(s,b)", pa11, FLAG_STRICT},
+{ "fstds", 0x2c001200, 0xfc00dfc0, "cmft,5(b)", pa10, 0},
+{ "fstds", 0x2c001200, 0xfc001fc0, "cmft,5(s,b)", pa10, 0},
+{ "fstqs", 0x3c001200, 0xfc00dfc0, "cmft,5(b)", pa10, 0},
+{ "fstqs", 0x3c001200, 0xfc001fc0, "cmft,5(s,b)", pa10, 0},
+{ "fadd", 0x30000600, 0xfc00e7e0, "Ffa,fb,fT", pa10, 0},
+{ "fadd", 0x38000600, 0xfc00e720, "IfA,fB,fT", pa10, 0},
+{ "fsub", 0x30002600, 0xfc00e7e0, "Ffa,fb,fT", pa10, 0},
+{ "fsub", 0x38002600, 0xfc00e720, "IfA,fB,fT", pa10, 0},
+{ "fmpy", 0x30004600, 0xfc00e7e0, "Ffa,fb,fT", pa10, 0},
+{ "fmpy", 0x38004600, 0xfc00e720, "IfA,fB,fT", pa10, 0},
+{ "fdiv", 0x30006600, 0xfc00e7e0, "Ffa,fb,fT", pa10, 0},
+{ "fdiv", 0x38006600, 0xfc00e720, "IfA,fB,fT", pa10, 0},
+{ "fsqrt", 0x30008000, 0xfc1fe7e0, "Ffa,fT", pa10, 0},
+{ "fsqrt", 0x38008000, 0xfc1fe720, "FfA,fT", pa10, 0},
+{ "fabs", 0x30006000, 0xfc1fe7e0, "Ffa,fT", pa10, 0},
+{ "fabs", 0x38006000, 0xfc1fe720, "FfA,fT", pa10, 0},
+{ "frem", 0x30008600, 0xfc00e7e0, "Ffa,fb,fT", pa10, 0},
+{ "frem", 0x38008600, 0xfc00e720, "FfA,fB,fT", pa10, 0},
+{ "frnd", 0x3000a000, 0xfc1fe7e0, "Ffa,fT", pa10, 0},
+{ "frnd", 0x3800a000, 0xfc1fe720, "FfA,fT", pa10, 0},
+{ "fcpy", 0x30004000, 0xfc1fe7e0, "Ffa,fT", pa10, 0},
+{ "fcpy", 0x38004000, 0xfc1fe720, "FfA,fT", pa10, 0},
+{ "fcnvff", 0x30000200, 0xfc1f87e0, "FGfa,fT", pa10, 0},
+{ "fcnvff", 0x38000200, 0xfc1f8720, "FGfA,fT", pa10, 0},
+{ "fcnvxf", 0x30008200, 0xfc1f87e0, "FGfa,fT", pa10, 0},
+{ "fcnvxf", 0x38008200, 0xfc1f8720, "FGfA,fT", pa10, 0},
+{ "fcnvfx", 0x30010200, 0xfc1f87e0, "FGfa,fT", pa10, 0},
+{ "fcnvfx", 0x38010200, 0xfc1f8720, "FGfA,fT", pa10, 0},
+{ "fcnvfxt", 0x30018200, 0xfc1f87e0, "FGfa,fT", pa10, 0},
+{ "fcnvfxt", 0x38018200, 0xfc1f8720, "FGfA,fT", pa10, 0},
+{ "fmpyfadd", 0xb8000000, 0xfc000020, "IfA,fB,fC,fT", pa20, FLAG_STRICT},
+{ "fmpynfadd", 0xb8000020, 0xfc000020, "IfA,fB,fC,fT", pa20, FLAG_STRICT},
+{ "fneg", 0x3000c000, 0xfc1fe7e0, "Ffa,fT", pa20, FLAG_STRICT},
+{ "fneg", 0x3800c000, 0xfc1fe720, "IfA,fT", pa20, FLAG_STRICT},
+{ "fnegabs", 0x3000e000, 0xfc1fe7e0, "Ffa,fT", pa20, FLAG_STRICT},
+{ "fnegabs", 0x3800e000, 0xfc1fe720, "IfA,fT", pa20, FLAG_STRICT},
+{ "fcnv", 0x30000200, 0xfc1c0720, "{_fa,fT", pa20, FLAG_STRICT},
+{ "fcnv", 0x38000200, 0xfc1c0720, "FGfA,fT", pa20, FLAG_STRICT},
+{ "fcmp", 0x30000400, 0xfc00e7e0, "F?ffa,fb", pa10, FLAG_STRICT},
+{ "fcmp", 0x38000400, 0xfc00e720, "I?ffA,fB", pa10, FLAG_STRICT},
+{ "fcmp", 0x30000400, 0xfc0007e0, "F?ffa,fb,h", pa20, FLAG_STRICT},
+{ "fcmp", 0x38000400, 0xfc000720, "I?ffA,fB,h", pa20, FLAG_STRICT},
+{ "fcmp", 0x30000400, 0xfc00e7e0, "F?ffa,fb", pa10, 0},
+{ "fcmp", 0x38000400, 0xfc00e720, "I?ffA,fB", pa10, 0},
+{ "xmpyu", 0x38004700, 0xfc00e720, "fX,fB,fT", pa11, 0},
+{ "fmpyadd", 0x18000000, 0xfc000000, "Hfi,fj,fk,fl,fm", pa11, 0},
+{ "fmpysub", 0x98000000, 0xfc000000, "Hfi,fj,fk,fl,fm", pa11, 0},
+{ "ftest", 0x30002420, 0xffffffff, "", pa10, FLAG_STRICT},
+{ "ftest", 0x30002420, 0xffffffe0, ",=", pa20, FLAG_STRICT},
+{ "ftest", 0x30000420, 0xffff1fff, "m", pa20, FLAG_STRICT},
+{ "fid", 0x30000000, 0xffffffff, "", pa11, 0},
+
+/* Performance Monitor Instructions. */
+
+{ "pmdis", 0x30000280, 0xffffffdf, "N", pa20, FLAG_STRICT},
+{ "pmenb", 0x30000680, 0xffffffff, "", pa20, FLAG_STRICT},
+
+/* Assist Instructions. */
+
+{ "spop0", 0x10000000, 0xfc000600, "v,ON", pa10, 0},
+{ "spop1", 0x10000200, 0xfc000600, "v,oNt", pa10, 0},
+{ "spop2", 0x10000400, 0xfc000600, "v,1Nb", pa10, 0},
+{ "spop3", 0x10000600, 0xfc000600, "v,0Nx,b", pa10, 0},
+{ "copr", 0x30000000, 0xfc000000, "u,2N", pa10, 0},
+{ "cldw", 0x24000000, 0xfc00de00, "ucXx(b),t", pa10, FLAG_STRICT},
+{ "cldw", 0x24000000, 0xfc001e00, "ucXx(s,b),t", pa10, FLAG_STRICT},
+{ "cldw", 0x24000000, 0xfc00d200, "ucxccx(b),t", pa11, FLAG_STRICT},
+{ "cldw", 0x24000000, 0xfc001200, "ucxccx(s,b),t", pa11, FLAG_STRICT},
+{ "cldw", 0x24001000, 0xfc00d200, "ucocc@(b),t", pa20, FLAG_STRICT},
+{ "cldw", 0x24001000, 0xfc001200, "ucocc@(s,b),t", pa20, FLAG_STRICT},
+{ "cldw", 0x24001000, 0xfc00de00, "ucM5(b),t", pa10, FLAG_STRICT},
+{ "cldw", 0x24001000, 0xfc001e00, "ucM5(s,b),t", pa10, FLAG_STRICT},
+{ "cldw", 0x24001000, 0xfc00d200, "ucmcc5(b),t", pa11, FLAG_STRICT},
+{ "cldw", 0x24001000, 0xfc001200, "ucmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "cldd", 0x2c000000, 0xfc00de00, "ucXx(b),t", pa10, FLAG_STRICT},
+{ "cldd", 0x2c000000, 0xfc001e00, "ucXx(s,b),t", pa10, FLAG_STRICT},
+{ "cldd", 0x2c000000, 0xfc00d200, "ucxccx(b),t", pa11, FLAG_STRICT},
+{ "cldd", 0x2c000000, 0xfc001200, "ucxccx(s,b),t", pa11, FLAG_STRICT},
+{ "cldd", 0x2c001000, 0xfc00d200, "ucocc@(b),t", pa20, FLAG_STRICT},
+{ "cldd", 0x2c001000, 0xfc001200, "ucocc@(s,b),t", pa20, FLAG_STRICT},
+{ "cldd", 0x2c001000, 0xfc00de00, "ucM5(b),t", pa10, FLAG_STRICT},
+{ "cldd", 0x2c001000, 0xfc001e00, "ucM5(s,b),t", pa10, FLAG_STRICT},
+{ "cldd", 0x2c001000, 0xfc00d200, "ucmcc5(b),t", pa11, FLAG_STRICT},
+{ "cldd", 0x2c001000, 0xfc001200, "ucmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "cstw", 0x24000200, 0xfc00de00, "ucXt,x(b)", pa10, FLAG_STRICT},
+{ "cstw", 0x24000200, 0xfc001e00, "ucXt,x(s,b)", pa10, FLAG_STRICT},
+{ "cstw", 0x24000200, 0xfc00d200, "ucxcCt,x(b)", pa11, FLAG_STRICT},
+{ "cstw", 0x24000200, 0xfc001200, "ucxcCt,x(s,b)", pa11, FLAG_STRICT},
+{ "cstw", 0x24001200, 0xfc00d200, "ucocCt,@(b)", pa20, FLAG_STRICT},
+{ "cstw", 0x24001200, 0xfc001200, "ucocCt,@(s,b)", pa20, FLAG_STRICT},
+{ "cstw", 0x24001200, 0xfc00de00, "ucMt,5(b)", pa10, FLAG_STRICT},
+{ "cstw", 0x24001200, 0xfc001e00, "ucMt,5(s,b)", pa10, FLAG_STRICT},
+{ "cstw", 0x24001200, 0xfc00d200, "ucmcCt,5(b)", pa11, FLAG_STRICT},
+{ "cstw", 0x24001200, 0xfc001200, "ucmcCt,5(s,b)", pa11, FLAG_STRICT},
+{ "cstd", 0x2c000200, 0xfc00de00, "ucXt,x(b)", pa10, FLAG_STRICT},
+{ "cstd", 0x2c000200, 0xfc001e00, "ucXt,x(s,b)", pa10, FLAG_STRICT},
+{ "cstd", 0x2c000200, 0xfc00d200, "ucxcCt,x(b)", pa11, FLAG_STRICT},
+{ "cstd", 0x2c000200, 0xfc001200, "ucxcCt,x(s,b)", pa11, FLAG_STRICT},
+{ "cstd", 0x2c001200, 0xfc00d200, "ucocCt,@(b)", pa20, FLAG_STRICT},
+{ "cstd", 0x2c001200, 0xfc001200, "ucocCt,@(s,b)", pa20, FLAG_STRICT},
+{ "cstd", 0x2c001200, 0xfc00de00, "ucMt,5(b)", pa10, FLAG_STRICT},
+{ "cstd", 0x2c001200, 0xfc001e00, "ucMt,5(s,b)", pa10, FLAG_STRICT},
+{ "cstd", 0x2c001200, 0xfc00d200, "ucmcCt,5(b)", pa11, FLAG_STRICT},
+{ "cstd", 0x2c001200, 0xfc001200, "ucmcCt,5(s,b)", pa11, FLAG_STRICT},
+{ "cldwx", 0x24000000, 0xfc00de00, "ucXx(b),t", pa10, FLAG_STRICT},
+{ "cldwx", 0x24000000, 0xfc001e00, "ucXx(s,b),t", pa10, FLAG_STRICT},
+{ "cldwx", 0x24000000, 0xfc00d200, "ucxccx(b),t", pa11, FLAG_STRICT},
+{ "cldwx", 0x24000000, 0xfc001200, "ucxccx(s,b),t", pa11, FLAG_STRICT},
+{ "cldwx", 0x24000000, 0xfc00de00, "ucXx(b),t", pa10, 0},
+{ "cldwx", 0x24000000, 0xfc001e00, "ucXx(s,b),t", pa10, 0},
+{ "clddx", 0x2c000000, 0xfc00de00, "ucXx(b),t", pa10, FLAG_STRICT},
+{ "clddx", 0x2c000000, 0xfc001e00, "ucXx(s,b),t", pa10, FLAG_STRICT},
+{ "clddx", 0x2c000000, 0xfc00d200, "ucxccx(b),t", pa11, FLAG_STRICT},
+{ "clddx", 0x2c000000, 0xfc001200, "ucxccx(s,b),t", pa11, FLAG_STRICT},
+{ "clddx", 0x2c000000, 0xfc00de00, "ucXx(b),t", pa10, 0},
+{ "clddx", 0x2c000000, 0xfc001e00, "ucXx(s,b),t", pa10, 0},
+{ "cstwx", 0x24000200, 0xfc00de00, "ucXt,x(b)", pa10, FLAG_STRICT},
+{ "cstwx", 0x24000200, 0xfc001e00, "ucXt,x(s,b)", pa10, FLAG_STRICT},
+{ "cstwx", 0x24000200, 0xfc00d200, "ucxcCt,x(b)", pa11, FLAG_STRICT},
+{ "cstwx", 0x24000200, 0xfc001200, "ucxcCt,x(s,b)", pa11, FLAG_STRICT},
+{ "cstwx", 0x24000200, 0xfc00de00, "ucXt,x(b)", pa10, 0},
+{ "cstwx", 0x24000200, 0xfc001e00, "ucXt,x(s,b)", pa10, 0},
+{ "cstdx", 0x2c000200, 0xfc00de00, "ucXt,x(b)", pa10, FLAG_STRICT},
+{ "cstdx", 0x2c000200, 0xfc001e00, "ucXt,x(s,b)", pa10, FLAG_STRICT},
+{ "cstdx", 0x2c000200, 0xfc00d200, "ucxcCt,x(b)", pa11, FLAG_STRICT},
+{ "cstdx", 0x2c000200, 0xfc001200, "ucxcCt,x(s,b)", pa11, FLAG_STRICT},
+{ "cstdx", 0x2c000200, 0xfc00de00, "ucXt,x(b)", pa10, 0},
+{ "cstdx", 0x2c000200, 0xfc001e00, "ucXt,x(s,b)", pa10, 0},
+{ "cldws", 0x24001000, 0xfc00de00, "ucM5(b),t", pa10, FLAG_STRICT},
+{ "cldws", 0x24001000, 0xfc001e00, "ucM5(s,b),t", pa10, FLAG_STRICT},
+{ "cldws", 0x24001000, 0xfc00d200, "ucmcc5(b),t", pa11, FLAG_STRICT},
+{ "cldws", 0x24001000, 0xfc001200, "ucmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "cldws", 0x24001000, 0xfc00de00, "ucM5(b),t", pa10, 0},
+{ "cldws", 0x24001000, 0xfc001e00, "ucM5(s,b),t", pa10, 0},
+{ "cldds", 0x2c001000, 0xfc00de00, "ucM5(b),t", pa10, FLAG_STRICT},
+{ "cldds", 0x2c001000, 0xfc001e00, "ucM5(s,b),t", pa10, FLAG_STRICT},
+{ "cldds", 0x2c001000, 0xfc00d200, "ucmcc5(b),t", pa11, FLAG_STRICT},
+{ "cldds", 0x2c001000, 0xfc001200, "ucmcc5(s,b),t", pa11, FLAG_STRICT},
+{ "cldds", 0x2c001000, 0xfc00de00, "ucM5(b),t", pa10, 0},
+{ "cldds", 0x2c001000, 0xfc001e00, "ucM5(s,b),t", pa10, 0},
+{ "cstws", 0x24001200, 0xfc00de00, "ucMt,5(b)", pa10, FLAG_STRICT},
+{ "cstws", 0x24001200, 0xfc001e00, "ucMt,5(s,b)", pa10, FLAG_STRICT},
+{ "cstws", 0x24001200, 0xfc00d200, "ucmcCt,5(b)", pa11, FLAG_STRICT},
+{ "cstws", 0x24001200, 0xfc001200, "ucmcCt,5(s,b)", pa11, FLAG_STRICT},
+{ "cstws", 0x24001200, 0xfc00de00, "ucMt,5(b)", pa10, 0},
+{ "cstws", 0x24001200, 0xfc001e00, "ucMt,5(s,b)", pa10, 0},
+{ "cstds", 0x2c001200, 0xfc00de00, "ucMt,5(b)", pa10, FLAG_STRICT},
+{ "cstds", 0x2c001200, 0xfc001e00, "ucMt,5(s,b)", pa10, FLAG_STRICT},
+{ "cstds", 0x2c001200, 0xfc00d200, "ucmcCt,5(b)", pa11, FLAG_STRICT},
+{ "cstds", 0x2c001200, 0xfc001200, "ucmcCt,5(s,b)", pa11, FLAG_STRICT},
+{ "cstds", 0x2c001200, 0xfc00de00, "ucMt,5(b)", pa10, 0},
+{ "cstds", 0x2c001200, 0xfc001e00, "ucMt,5(s,b)", pa10, 0},
+
+/* More pseudo instructions which must follow the main table. */
+{ "call", 0xe800f000, 0xfc1ffffd, "n(b)", pa20, FLAG_STRICT},
+{ "call", 0xe800a000, 0xffe0e000, "nW", pa10, FLAG_STRICT},
+{ "ret", 0xe840d000, 0xfffffffd, "n", pa20, FLAG_STRICT},
+
+};
+
+#define NUMOPCODES ((sizeof pa_opcodes)/(sizeof pa_opcodes[0]))
+
+/* SKV 12/18/92. Added some denotations for various operands. */
+
+#define PA_IMM11_AT_31 'i'
+#define PA_IMM14_AT_31 'j'
+#define PA_IMM21_AT_31 'k'
+#define PA_DISP12 'w'
+#define PA_DISP17 'W'
+
+#define N_HPPA_OPERAND_FORMATS 5
+
+/* Integer register names, indexed by the numbers which appear in the
+ opcodes. */
+static const char *const reg_names[] =
+{
+ "flags", "r1", "rp", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
+ "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19",
+ "r20", "r21", "r22", "r23", "r24", "r25", "r26", "dp", "ret0", "ret1",
+ "sp", "r31"
+};
+
+/* Floating point register names, indexed by the numbers which appear in the
+ opcodes. */
+static const char *const fp_reg_names[] =
+{
+ "fpsr", "fpe2", "fpe4", "fpe6",
+ "fr4", "fr5", "fr6", "fr7", "fr8",
+ "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
+ "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",
+ "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31"
+};
+
+typedef unsigned int CORE_ADDR;
+
+/* Get at various relevant fields of an instruction word. */
+
+#define MASK_5 0x1f
+#define MASK_10 0x3ff
+#define MASK_11 0x7ff
+#define MASK_14 0x3fff
+#define MASK_16 0xffff
+#define MASK_21 0x1fffff
+
+/* These macros get bit fields using HP's numbering (MSB = 0). */
+
+#define GET_FIELD(X, FROM, TO) \
+ ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
+
+#define GET_BIT(X, WHICH) \
+ GET_FIELD (X, WHICH, WHICH)
+
+/* Some of these have been converted to 2-d arrays because they
+ consume less storage this way. If the maintenance becomes a
+ problem, convert them back to const 1-d pointer arrays. */
+static const char *const control_reg[] =
+{
+ "rctr", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
+ "pidr1", "pidr2", "ccr", "sar", "pidr3", "pidr4",
+ "iva", "eiem", "itmr", "pcsq", "pcoq", "iir", "isr",
+ "ior", "ipsw", "eirr", "tr0", "tr1", "tr2", "tr3",
+ "tr4", "tr5", "tr6", "tr7"
+};
+
+static const char *const compare_cond_names[] =
+{
+ "", ",=", ",<", ",<=", ",<<", ",<<=", ",sv", ",od",
+ ",tr", ",<>", ",>=", ",>", ",>>=", ",>>", ",nsv", ",ev"
+};
+static const char *const compare_cond_64_names[] =
+{
+ "", ",*=", ",*<", ",*<=", ",*<<", ",*<<=", ",*sv", ",*od",
+ ",*tr", ",*<>", ",*>=", ",*>", ",*>>=", ",*>>", ",*nsv", ",*ev"
+};
+static const char *const cmpib_cond_64_names[] =
+{
+ ",*<<", ",*=", ",*<", ",*<=", ",*>>=", ",*<>", ",*>=", ",*>"
+};
+static const char *const add_cond_names[] =
+{
+ "", ",=", ",<", ",<=", ",nuv", ",znv", ",sv", ",od",
+ ",tr", ",<>", ",>=", ",>", ",uv", ",vnz", ",nsv", ",ev"
+};
+static const char *const add_cond_64_names[] =
+{
+ "", ",*=", ",*<", ",*<=", ",*nuv", ",*znv", ",*sv", ",*od",
+ ",*tr", ",*<>", ",*>=", ",*>", ",*uv", ",*vnz", ",*nsv", ",*ev"
+};
+static const char *const wide_add_cond_names[] =
+{
+ "", ",=", ",<", ",<=", ",nuv", ",*=", ",*<", ",*<=",
+ ",tr", ",<>", ",>=", ",>", ",uv", ",*<>", ",*>=", ",*>"
+};
+static const char *const logical_cond_names[] =
+{
+ "", ",=", ",<", ",<=", 0, 0, 0, ",od",
+ ",tr", ",<>", ",>=", ",>", 0, 0, 0, ",ev"};
+static const char *const logical_cond_64_names[] =
+{
+ "", ",*=", ",*<", ",*<=", 0, 0, 0, ",*od",
+ ",*tr", ",*<>", ",*>=", ",*>", 0, 0, 0, ",*ev"};
+static const char *const unit_cond_names[] =
+{
+ "", ",swz", ",sbz", ",shz", ",sdc", ",swc", ",sbc", ",shc",
+ ",tr", ",nwz", ",nbz", ",nhz", ",ndc", ",nwc", ",nbc", ",nhc"
+};
+static const char *const unit_cond_64_names[] =
+{
+ "", ",*swz", ",*sbz", ",*shz", ",*sdc", ",*swc", ",*sbc", ",*shc",
+ ",*tr", ",*nwz", ",*nbz", ",*nhz", ",*ndc", ",*nwc", ",*nbc", ",*nhc"
+};
+static const char *const shift_cond_names[] =
+{
+ "", ",=", ",<", ",od", ",tr", ",<>", ",>=", ",ev"
+};
+static const char *const shift_cond_64_names[] =
+{
+ "", ",*=", ",*<", ",*od", ",*tr", ",*<>", ",*>=", ",*ev"
+};
+static const char *const bb_cond_64_names[] =
+{
+ ",*<", ",*>="
+};
+static const char *const index_compl_names[] = {"", ",m", ",s", ",sm"};
+static const char *const short_ldst_compl_names[] = {"", ",ma", "", ",mb"};
+static const char *const short_bytes_compl_names[] =
+{
+ "", ",b,m", ",e", ",e,m"
+};
+static const char *const float_format_names[] = {",sgl", ",dbl", "", ",quad"};
+static const char *const fcnv_fixed_names[] = {",w", ",dw", "", ",qw"};
+static const char *const fcnv_ufixed_names[] = {",uw", ",udw", "", ",uqw"};
+static const char *const float_comp_names[] =
+{
+ ",false?", ",false", ",?", ",!<=>", ",=", ",=t", ",?=", ",!<>",
+ ",!?>=", ",<", ",?<", ",!>=", ",!?>", ",<=", ",?<=", ",!>",
+ ",!?<=", ",>", ",?>", ",!<=", ",!?<", ",>=", ",?>=", ",!<",
+ ",!?=", ",<>", ",!=", ",!=t", ",!?", ",<=>", ",true?", ",true"
+};
+static const char *const signed_unsigned_names[] = {",u", ",s"};
+static const char *const mix_half_names[] = {",l", ",r"};
+static const char *const saturation_names[] = {",us", ",ss", 0, ""};
+static const char *const read_write_names[] = {",r", ",w"};
+static const char *const add_compl_names[] = { 0, "", ",l", ",tsv" };
+
+/* For a bunch of different instructions form an index into a
+ completer name table. */
+#define GET_COMPL(insn) (GET_FIELD (insn, 26, 26) | \
+ GET_FIELD (insn, 18, 18) << 1)
+
+#define GET_COND(insn) (GET_FIELD ((insn), 16, 18) + \
+ (GET_FIELD ((insn), 19, 19) ? 8 : 0))
+
+/* Utility function to print registers. Put these first, so gcc's function
+ inlining can do its stuff. */
+
+#define fputs_filtered(STR,F) (*info->fprintf_func) (info->stream, "%s", STR)
+
+static void
+fput_reg (unsigned reg, disassemble_info *info)
+{
+ (*info->fprintf_func) (info->stream, "%s", reg ? reg_names[reg] : "r0");
+}
+
+static void
+fput_fp_reg (unsigned reg, disassemble_info *info)
+{
+ (*info->fprintf_func) (info->stream, "%s", reg ? fp_reg_names[reg] : "fr0");
+}
+
+static void
+fput_fp_reg_r (unsigned reg, disassemble_info *info)
+{
+ /* Special case floating point exception registers. */
+ if (reg < 4)
+ (*info->fprintf_func) (info->stream, "fpe%d", reg * 2 + 1);
+ else
+ (*info->fprintf_func) (info->stream, "%sR",
+ reg ? fp_reg_names[reg] : "fr0");
+}
+
+static void
+fput_creg (unsigned reg, disassemble_info *info)
+{
+ (*info->fprintf_func) (info->stream, "%s", control_reg[reg]);
+}
+
+/* Print constants with sign. */
+
+static void
+fput_const (unsigned num, disassemble_info *info)
+{
+ if ((int) num < 0)
+ (*info->fprintf_func) (info->stream, "-%x", - (int) num);
+ else
+ (*info->fprintf_func) (info->stream, "%x", num);
+}
+
+/* Routines to extract various sized constants out of hppa
+ instructions. */
+
+/* Extract a 3-bit space register number from a be, ble, mtsp or mfsp. */
+static int
+extract_3 (unsigned word)
+{
+ return GET_FIELD (word, 18, 18) << 2 | GET_FIELD (word, 16, 17);
+}
+
+static int
+extract_5_load (unsigned word)
+{
+ return low_sign_extend (word >> 16 & MASK_5, 5);
+}
+
+/* Extract the immediate field from a st{bhw}s instruction. */
+
+static int
+extract_5_store (unsigned word)
+{
+ return low_sign_extend (word & MASK_5, 5);
+}
+
+/* Extract the immediate field from a break instruction. */
+
+static unsigned
+extract_5r_store (unsigned word)
+{
+ return (word & MASK_5);
+}
+
+/* Extract the immediate field from a {sr}sm instruction. */
+
+static unsigned
+extract_5R_store (unsigned word)
+{
+ return (word >> 16 & MASK_5);
+}
+
+/* Extract the 10 bit immediate field from a {sr}sm instruction. */
+
+static unsigned
+extract_10U_store (unsigned word)
+{
+ return (word >> 16 & MASK_10);
+}
+
+/* Extract the immediate field from a bb instruction. */
+
+static unsigned
+extract_5Q_store (unsigned word)
+{
+ return (word >> 21 & MASK_5);
+}
+
+/* Extract an 11 bit immediate field. */
+
+static int
+extract_11 (unsigned word)
+{
+ return low_sign_extend (word & MASK_11, 11);
+}
+
+/* Extract a 14 bit immediate field. */
+
+static int
+extract_14 (unsigned word)
+{
+ return low_sign_extend (word & MASK_14, 14);
+}
+
+/* Extract a 16 bit immediate field (PA2.0 wide only). */
+
+static int
+extract_16 (unsigned word)
+{
+ int m15, m0, m1;
+
+ m0 = GET_BIT (word, 16);
+ m1 = GET_BIT (word, 17);
+ m15 = GET_BIT (word, 31);
+ word = (word >> 1) & 0x1fff;
+ word = word | (m15 << 15) | ((m15 ^ m0) << 14) | ((m15 ^ m1) << 13);
+ return sign_extend (word, 16);
+}
+
+/* Extract a 21 bit constant. */
+
+static int
+extract_21 (unsigned word)
+{
+ int val;
+
+ word &= MASK_21;
+ word <<= 11;
+ val = GET_FIELD (word, 20, 20);
+ val <<= 11;
+ val |= GET_FIELD (word, 9, 19);
+ val <<= 2;
+ val |= GET_FIELD (word, 5, 6);
+ val <<= 5;
+ val |= GET_FIELD (word, 0, 4);
+ val <<= 2;
+ val |= GET_FIELD (word, 7, 8);
+ return sign_extend (val, 21) << 11;
+}
+
+/* Extract a 12 bit constant from branch instructions. */
+
+static int
+extract_12 (unsigned word)
+{
+ return sign_extend (GET_FIELD (word, 19, 28)
+ | GET_FIELD (word, 29, 29) << 10
+ | (word & 0x1) << 11, 12) << 2;
+}
+
+/* Extract a 17 bit constant from branch instructions, returning the
+ 19 bit signed value. */
+
+static int
+extract_17 (unsigned word)
+{
+ return sign_extend (GET_FIELD (word, 19, 28)
+ | GET_FIELD (word, 29, 29) << 10
+ | GET_FIELD (word, 11, 15) << 11
+ | (word & 0x1) << 16, 17) << 2;
+}
+
+static int
+extract_22 (unsigned word)
+{
+ return sign_extend (GET_FIELD (word, 19, 28)
+ | GET_FIELD (word, 29, 29) << 10
+ | GET_FIELD (word, 11, 15) << 11
+ | GET_FIELD (word, 6, 10) << 16
+ | (word & 0x1) << 21, 22) << 2;
+}
+
+/* Print one instruction. */
+
+int
+print_insn_hppa (bfd_vma memaddr, disassemble_info *info)
+{
+ bfd_byte buffer[4];
+ unsigned int insn, i;
+
+ {
+ int status =
+ (*info->read_memory_func) (memaddr, buffer, sizeof (buffer), info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, memaddr, info);
+ return -1;
+ }
+ }
+
+ insn = bfd_getb32 (buffer);
+
+ for (i = 0; i < NUMOPCODES; ++i)
+ {
+ const struct pa_opcode *opcode = &pa_opcodes[i];
+
+ if ((insn & opcode->mask) == opcode->match)
+ {
+ const char *s;
+#ifndef BFD64
+ if (opcode->arch == pa20w)
+ continue;
+#endif
+ (*info->fprintf_func) (info->stream, "%s", opcode->name);
+
+ if (!strchr ("cfCY?-+nHNZFIuv{", opcode->args[0]))
+ (*info->fprintf_func) (info->stream, " ");
+ for (s = opcode->args; *s != '\0'; ++s)
+ {
+ switch (*s)
+ {
+ case 'x':
+ fput_reg (GET_FIELD (insn, 11, 15), info);
+ break;
+ case 'a':
+ case 'b':
+ fput_reg (GET_FIELD (insn, 6, 10), info);
+ break;
+ case '^':
+ fput_creg (GET_FIELD (insn, 6, 10), info);
+ break;
+ case 't':
+ fput_reg (GET_FIELD (insn, 27, 31), info);
+ break;
+
+ /* Handle floating point registers. */
+ case 'f':
+ switch (*++s)
+ {
+ case 't':
+ fput_fp_reg (GET_FIELD (insn, 27, 31), info);
+ break;
+ case 'T':
+ if (GET_FIELD (insn, 25, 25))
+ fput_fp_reg_r (GET_FIELD (insn, 27, 31), info);
+ else
+ fput_fp_reg (GET_FIELD (insn, 27, 31), info);
+ break;
+ case 'a':
+ if (GET_FIELD (insn, 25, 25))
+ fput_fp_reg_r (GET_FIELD (insn, 6, 10), info);
+ else
+ fput_fp_reg (GET_FIELD (insn, 6, 10), info);
+ break;
+
+ /* 'fA' will not generate a space before the regsiter
+ name. Normally that is fine. Except that it
+ causes problems with xmpyu which has no FP format
+ completer. */
+ case 'X':
+ fputs_filtered (" ", info);
+ /* FALLTHRU */
+
+ case 'A':
+ if (GET_FIELD (insn, 24, 24))
+ fput_fp_reg_r (GET_FIELD (insn, 6, 10), info);
+ else
+ fput_fp_reg (GET_FIELD (insn, 6, 10), info);
+ break;
+ case 'b':
+ if (GET_FIELD (insn, 25, 25))
+ fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
+ else
+ fput_fp_reg (GET_FIELD (insn, 11, 15), info);
+ break;
+ case 'B':
+ if (GET_FIELD (insn, 19, 19))
+ fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
+ else
+ fput_fp_reg (GET_FIELD (insn, 11, 15), info);
+ break;
+ case 'C':
+ {
+ int reg = GET_FIELD (insn, 21, 22);
+ reg |= GET_FIELD (insn, 16, 18) << 2;
+ if (GET_FIELD (insn, 23, 23) != 0)
+ fput_fp_reg_r (reg, info);
+ else
+ fput_fp_reg (reg, info);
+ break;
+ }
+ case 'i':
+ {
+ int reg = GET_FIELD (insn, 6, 10);
+
+ reg |= (GET_FIELD (insn, 26, 26) << 4);
+ fput_fp_reg (reg, info);
+ break;
+ }
+ case 'j':
+ {
+ int reg = GET_FIELD (insn, 11, 15);
+
+ reg |= (GET_FIELD (insn, 26, 26) << 4);
+ fput_fp_reg (reg, info);
+ break;
+ }
+ case 'k':
+ {
+ int reg = GET_FIELD (insn, 27, 31);
+
+ reg |= (GET_FIELD (insn, 26, 26) << 4);
+ fput_fp_reg (reg, info);
+ break;
+ }
+ case 'l':
+ {
+ int reg = GET_FIELD (insn, 21, 25);
+
+ reg |= (GET_FIELD (insn, 26, 26) << 4);
+ fput_fp_reg (reg, info);
+ break;
+ }
+ case 'm':
+ {
+ int reg = GET_FIELD (insn, 16, 20);
+
+ reg |= (GET_FIELD (insn, 26, 26) << 4);
+ fput_fp_reg (reg, info);
+ break;
+ }
+
+ /* 'fe' will not generate a space before the register
+ name. Normally that is fine. Except that it
+ causes problems with fstw fe,y(b) which has no FP
+ format completer. */
+ case 'E':
+ fputs_filtered (" ", info);
+ /* FALLTHRU */
+
+ case 'e':
+ if (GET_FIELD (insn, 30, 30))
+ fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
+ else
+ fput_fp_reg (GET_FIELD (insn, 11, 15), info);
+ break;
+ case 'x':
+ fput_fp_reg (GET_FIELD (insn, 11, 15), info);
+ break;
+ }
+ break;
+
+ case '5':
+ fput_const (extract_5_load (insn), info);
+ break;
+ case 's':
+ {
+ int space = GET_FIELD (insn, 16, 17);
+ /* Zero means implicit addressing, not use of sr0. */
+ if (space != 0)
+ (*info->fprintf_func) (info->stream, "sr%d", space);
+ }
+ break;
+
+ case 'S':
+ (*info->fprintf_func) (info->stream, "sr%d",
+ extract_3 (insn));
+ break;
+
+ /* Handle completers. */
+ case 'c':
+ switch (*++s)
+ {
+ case 'x':
+ (*info->fprintf_func)
+ (info->stream, "%s",
+ index_compl_names[GET_COMPL (insn)]);
+ break;
+ case 'X':
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ index_compl_names[GET_COMPL (insn)]);
+ break;
+ case 'm':
+ (*info->fprintf_func)
+ (info->stream, "%s",
+ short_ldst_compl_names[GET_COMPL (insn)]);
+ break;
+ case 'M':
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ short_ldst_compl_names[GET_COMPL (insn)]);
+ break;
+ case 'A':
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ short_bytes_compl_names[GET_COMPL (insn)]);
+ break;
+ case 's':
+ (*info->fprintf_func)
+ (info->stream, "%s",
+ short_bytes_compl_names[GET_COMPL (insn)]);
+ break;
+ case 'c':
+ case 'C':
+ switch (GET_FIELD (insn, 20, 21))
+ {
+ case 1:
+ (*info->fprintf_func) (info->stream, ",bc ");
+ break;
+ case 2:
+ (*info->fprintf_func) (info->stream, ",sl ");
+ break;
+ default:
+ (*info->fprintf_func) (info->stream, " ");
+ }
+ break;
+ case 'd':
+ switch (GET_FIELD (insn, 20, 21))
+ {
+ case 1:
+ (*info->fprintf_func) (info->stream, ",co ");
+ break;
+ default:
+ (*info->fprintf_func) (info->stream, " ");
+ }
+ break;
+ case 'o':
+ (*info->fprintf_func) (info->stream, ",o");
+ break;
+ case 'g':
+ (*info->fprintf_func) (info->stream, ",gate");
+ break;
+ case 'p':
+ (*info->fprintf_func) (info->stream, ",l,push");
+ break;
+ case 'P':
+ (*info->fprintf_func) (info->stream, ",pop");
+ break;
+ case 'l':
+ case 'L':
+ (*info->fprintf_func) (info->stream, ",l");
+ break;
+ case 'w':
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ read_write_names[GET_FIELD (insn, 25, 25)]);
+ break;
+ case 'W':
+ (*info->fprintf_func) (info->stream, ",w ");
+ break;
+ case 'r':
+ if (GET_FIELD (insn, 23, 26) == 5)
+ (*info->fprintf_func) (info->stream, ",r");
+ break;
+ case 'Z':
+ if (GET_FIELD (insn, 26, 26))
+ (*info->fprintf_func) (info->stream, ",m ");
+ else
+ (*info->fprintf_func) (info->stream, " ");
+ break;
+ case 'i':
+ if (GET_FIELD (insn, 25, 25))
+ (*info->fprintf_func) (info->stream, ",i");
+ break;
+ case 'z':
+ if (!GET_FIELD (insn, 21, 21))
+ (*info->fprintf_func) (info->stream, ",z");
+ break;
+ case 'a':
+ (*info->fprintf_func)
+ (info->stream, "%s",
+ add_compl_names[GET_FIELD (insn, 20, 21)]);
+ break;
+ case 'Y':
+ (*info->fprintf_func)
+ (info->stream, ",dc%s",
+ add_compl_names[GET_FIELD (insn, 20, 21)]);
+ break;
+ case 'y':
+ (*info->fprintf_func)
+ (info->stream, ",c%s",
+ add_compl_names[GET_FIELD (insn, 20, 21)]);
+ break;
+ case 'v':
+ if (GET_FIELD (insn, 20, 20))
+ (*info->fprintf_func) (info->stream, ",tsv");
+ break;
+ case 't':
+ (*info->fprintf_func) (info->stream, ",tc");
+ if (GET_FIELD (insn, 20, 20))
+ (*info->fprintf_func) (info->stream, ",tsv");
+ break;
+ case 'B':
+ (*info->fprintf_func) (info->stream, ",db");
+ if (GET_FIELD (insn, 20, 20))
+ (*info->fprintf_func) (info->stream, ",tsv");
+ break;
+ case 'b':
+ (*info->fprintf_func) (info->stream, ",b");
+ if (GET_FIELD (insn, 20, 20))
+ (*info->fprintf_func) (info->stream, ",tsv");
+ break;
+ case 'T':
+ if (GET_FIELD (insn, 25, 25))
+ (*info->fprintf_func) (info->stream, ",tc");
+ break;
+ case 'S':
+ /* EXTRD/W has a following condition. */
+ if (*(s + 1) == '?')
+ (*info->fprintf_func)
+ (info->stream, "%s",
+ signed_unsigned_names[GET_FIELD (insn, 21, 21)]);
+ else
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ signed_unsigned_names[GET_FIELD (insn, 21, 21)]);
+ break;
+ case 'h':
+ (*info->fprintf_func)
+ (info->stream, "%s",
+ mix_half_names[GET_FIELD (insn, 17, 17)]);
+ break;
+ case 'H':
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ saturation_names[GET_FIELD (insn, 24, 25)]);
+ break;
+ case '*':
+ (*info->fprintf_func)
+ (info->stream, ",%d%d%d%d ",
+ GET_FIELD (insn, 17, 18), GET_FIELD (insn, 20, 21),
+ GET_FIELD (insn, 22, 23), GET_FIELD (insn, 24, 25));
+ break;
+
+ case 'q':
+ {
+ int m, a;
+
+ m = GET_FIELD (insn, 28, 28);
+ a = GET_FIELD (insn, 29, 29);
+
+ if (m && !a)
+ fputs_filtered (",ma ", info);
+ else if (m && a)
+ fputs_filtered (",mb ", info);
+ else
+ fputs_filtered (" ", info);
+ break;
+ }
+
+ case 'J':
+ {
+ int opc = GET_FIELD (insn, 0, 5);
+
+ if (opc == 0x16 || opc == 0x1e)
+ {
+ if (GET_FIELD (insn, 29, 29) == 0)
+ fputs_filtered (",ma ", info);
+ else
+ fputs_filtered (",mb ", info);
+ }
+ else
+ fputs_filtered (" ", info);
+ break;
+ }
+
+ case 'e':
+ {
+ int opc = GET_FIELD (insn, 0, 5);
+
+ if (opc == 0x13 || opc == 0x1b)
+ {
+ if (GET_FIELD (insn, 18, 18) == 1)
+ fputs_filtered (",mb ", info);
+ else
+ fputs_filtered (",ma ", info);
+ }
+ else if (opc == 0x17 || opc == 0x1f)
+ {
+ if (GET_FIELD (insn, 31, 31) == 1)
+ fputs_filtered (",ma ", info);
+ else
+ fputs_filtered (",mb ", info);
+ }
+ else
+ fputs_filtered (" ", info);
+
+ break;
+ }
+ }
+ break;
+
+ /* Handle conditions. */
+ case '?':
+ {
+ s++;
+ switch (*s)
+ {
+ case 'f':
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ float_comp_names[GET_FIELD (insn, 27, 31)]);
+ break;
+
+ /* These four conditions are for the set of instructions
+ which distinguish true/false conditions by opcode
+ rather than by the 'f' bit (sigh): comb, comib,
+ addb, addib. */
+ case 't':
+ fputs_filtered
+ (compare_cond_names[GET_FIELD (insn, 16, 18)], info);
+ break;
+ case 'n':
+ fputs_filtered
+ (compare_cond_names[GET_FIELD (insn, 16, 18)
+ + GET_FIELD (insn, 4, 4) * 8],
+ info);
+ break;
+ case 'N':
+ fputs_filtered
+ (compare_cond_64_names[GET_FIELD (insn, 16, 18)
+ + GET_FIELD (insn, 2, 2) * 8],
+ info);
+ break;
+ case 'Q':
+ fputs_filtered
+ (cmpib_cond_64_names[GET_FIELD (insn, 16, 18)],
+ info);
+ break;
+ case '@':
+ fputs_filtered
+ (add_cond_names[GET_FIELD (insn, 16, 18)
+ + GET_FIELD (insn, 4, 4) * 8],
+ info);
+ break;
+ case 's':
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ compare_cond_names[GET_COND (insn)]);
+ break;
+ case 'S':
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ compare_cond_64_names[GET_COND (insn)]);
+ break;
+ case 'a':
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ add_cond_names[GET_COND (insn)]);
+ break;
+ case 'A':
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ add_cond_64_names[GET_COND (insn)]);
+ break;
+ case 'd':
+ (*info->fprintf_func)
+ (info->stream, "%s",
+ add_cond_names[GET_FIELD (insn, 16, 18)]);
+ break;
+
+ case 'W':
+ (*info->fprintf_func)
+ (info->stream, "%s",
+ wide_add_cond_names[GET_FIELD (insn, 16, 18) +
+ GET_FIELD (insn, 4, 4) * 8]);
+ break;
+
+ case 'l':
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ logical_cond_names[GET_COND (insn)]);
+ break;
+ case 'L':
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ logical_cond_64_names[GET_COND (insn)]);
+ break;
+ case 'u':
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ unit_cond_names[GET_COND (insn)]);
+ break;
+ case 'U':
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ unit_cond_64_names[GET_COND (insn)]);
+ break;
+ case 'y':
+ case 'x':
+ case 'b':
+ (*info->fprintf_func)
+ (info->stream, "%s",
+ shift_cond_names[GET_FIELD (insn, 16, 18)]);
+
+ /* If the next character in args is 'n', it will handle
+ putting out the space. */
+ if (s[1] != 'n')
+ (*info->fprintf_func) (info->stream, " ");
+ break;
+ case 'X':
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ shift_cond_64_names[GET_FIELD (insn, 16, 18)]);
+ break;
+ case 'B':
+ (*info->fprintf_func)
+ (info->stream, "%s",
+ bb_cond_64_names[GET_FIELD (insn, 16, 16)]);
+
+ /* If the next character in args is 'n', it will handle
+ putting out the space. */
+ if (s[1] != 'n')
+ (*info->fprintf_func) (info->stream, " ");
+ break;
+ }
+ break;
+ }
+
+ case 'V':
+ fput_const (extract_5_store (insn), info);
+ break;
+ case 'r':
+ fput_const (extract_5r_store (insn), info);
+ break;
+ case 'R':
+ fput_const (extract_5R_store (insn), info);
+ break;
+ case 'U':
+ fput_const (extract_10U_store (insn), info);
+ break;
+ case 'B':
+ case 'Q':
+ fput_const (extract_5Q_store (insn), info);
+ break;
+ case 'i':
+ fput_const (extract_11 (insn), info);
+ break;
+ case 'j':
+ fput_const (extract_14 (insn), info);
+ break;
+ case 'k':
+ fputs_filtered ("L%", info);
+ fput_const (extract_21 (insn), info);
+ break;
+ case '<':
+ case 'l':
+ /* 16-bit long disp., PA2.0 wide only. */
+ fput_const (extract_16 (insn), info);
+ break;
+ case 'n':
+ if (insn & 0x2)
+ (*info->fprintf_func) (info->stream, ",n ");
+ else
+ (*info->fprintf_func) (info->stream, " ");
+ break;
+ case 'N':
+ if ((insn & 0x20) && s[1])
+ (*info->fprintf_func) (info->stream, ",n ");
+ else if (insn & 0x20)
+ (*info->fprintf_func) (info->stream, ",n");
+ else if (s[1])
+ (*info->fprintf_func) (info->stream, " ");
+ break;
+ case 'w':
+ (*info->print_address_func)
+ (memaddr + 8 + extract_12 (insn), info);
+ break;
+ case 'W':
+ /* 17 bit PC-relative branch. */
+ (*info->print_address_func)
+ ((memaddr + 8 + extract_17 (insn)), info);
+ break;
+ case 'z':
+ /* 17 bit displacement. This is an offset from a register
+ so it gets disasssembled as just a number, not any sort
+ of address. */
+ fput_const (extract_17 (insn), info);
+ break;
+
+ case 'Z':
+ /* addil %r1 implicit output. */
+ fputs_filtered ("r1", info);
+ break;
+
+ case 'Y':
+ /* be,l %sr0,%r31 implicit output. */
+ fputs_filtered ("sr0,r31", info);
+ break;
+
+ case '@':
+ (*info->fprintf_func) (info->stream, "0");
+ break;
+
+ case '.':
+ (*info->fprintf_func) (info->stream, "%d",
+ GET_FIELD (insn, 24, 25));
+ break;
+ case '*':
+ (*info->fprintf_func) (info->stream, "%d",
+ GET_FIELD (insn, 22, 25));
+ break;
+ case '!':
+ fputs_filtered ("sar", info);
+ break;
+ case 'p':
+ (*info->fprintf_func) (info->stream, "%d",
+ 31 - GET_FIELD (insn, 22, 26));
+ break;
+ case '~':
+ {
+ int num;
+ num = GET_FIELD (insn, 20, 20) << 5;
+ num |= GET_FIELD (insn, 22, 26);
+ (*info->fprintf_func) (info->stream, "%d", 63 - num);
+ break;
+ }
+ case 'P':
+ (*info->fprintf_func) (info->stream, "%d",
+ GET_FIELD (insn, 22, 26));
+ break;
+ case 'q':
+ {
+ int num;
+ num = GET_FIELD (insn, 20, 20) << 5;
+ num |= GET_FIELD (insn, 22, 26);
+ (*info->fprintf_func) (info->stream, "%d", num);
+ break;
+ }
+ case 'T':
+ (*info->fprintf_func) (info->stream, "%d",
+ 32 - GET_FIELD (insn, 27, 31));
+ break;
+ case '%':
+ {
+ int num;
+ num = (GET_FIELD (insn, 23, 23) + 1) * 32;
+ num -= GET_FIELD (insn, 27, 31);
+ (*info->fprintf_func) (info->stream, "%d", num);
+ break;
+ }
+ case '|':
+ {
+ int num;
+ num = (GET_FIELD (insn, 19, 19) + 1) * 32;
+ num -= GET_FIELD (insn, 27, 31);
+ (*info->fprintf_func) (info->stream, "%d", num);
+ break;
+ }
+ case '$':
+ fput_const (GET_FIELD (insn, 20, 28), info);
+ break;
+ case 'A':
+ fput_const (GET_FIELD (insn, 6, 18), info);
+ break;
+ case 'D':
+ fput_const (GET_FIELD (insn, 6, 31), info);
+ break;
+ case 'v':
+ (*info->fprintf_func) (info->stream, ",%d",
+ GET_FIELD (insn, 23, 25));
+ break;
+ case 'O':
+ fput_const ((GET_FIELD (insn, 6,20) << 5 |
+ GET_FIELD (insn, 27, 31)), info);
+ break;
+ case 'o':
+ fput_const (GET_FIELD (insn, 6, 20), info);
+ break;
+ case '2':
+ fput_const ((GET_FIELD (insn, 6, 22) << 5 |
+ GET_FIELD (insn, 27, 31)), info);
+ break;
+ case '1':
+ fput_const ((GET_FIELD (insn, 11, 20) << 5 |
+ GET_FIELD (insn, 27, 31)), info);
+ break;
+ case '0':
+ fput_const ((GET_FIELD (insn, 16, 20) << 5 |
+ GET_FIELD (insn, 27, 31)), info);
+ break;
+ case 'u':
+ (*info->fprintf_func) (info->stream, ",%d",
+ GET_FIELD (insn, 23, 25));
+ break;
+ case 'F':
+ /* If no destination completer and not before a completer
+ for fcmp, need a space here. */
+ if (s[1] == 'G' || s[1] == '?')
+ fputs_filtered
+ (float_format_names[GET_FIELD (insn, 19, 20)], info);
+ else
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ float_format_names[GET_FIELD (insn, 19, 20)]);
+ break;
+ case 'G':
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ float_format_names[GET_FIELD (insn, 17, 18)]);
+ break;
+ case 'H':
+ if (GET_FIELD (insn, 26, 26) == 1)
+ (*info->fprintf_func) (info->stream, "%s ",
+ float_format_names[0]);
+ else
+ (*info->fprintf_func) (info->stream, "%s ",
+ float_format_names[1]);
+ break;
+ case 'I':
+ /* If no destination completer and not before a completer
+ for fcmp, need a space here. */
+ if (s[1] == '?')
+ fputs_filtered
+ (float_format_names[GET_FIELD (insn, 20, 20)], info);
+ else
+ (*info->fprintf_func)
+ (info->stream, "%s ",
+ float_format_names[GET_FIELD (insn, 20, 20)]);
+ break;
+
+ case 'J':
+ fput_const (extract_14 (insn), info);
+ break;
+
+ case '#':
+ {
+ int sign = GET_FIELD (insn, 31, 31);
+ int imm10 = GET_FIELD (insn, 18, 27);
+ int disp;
+
+ if (sign)
+ disp = (-1 << 10) | imm10;
+ else
+ disp = imm10;
+
+ disp <<= 3;
+ fput_const (disp, info);
+ break;
+ }
+ case 'K':
+ case 'd':
+ {
+ int sign = GET_FIELD (insn, 31, 31);
+ int imm11 = GET_FIELD (insn, 18, 28);
+ int disp;
+
+ if (sign)
+ disp = (-1 << 11) | imm11;
+ else
+ disp = imm11;
+
+ disp <<= 2;
+ fput_const (disp, info);
+ break;
+ }
+
+ case '>':
+ case 'y':
+ {
+ /* 16-bit long disp., PA2.0 wide only. */
+ int disp = extract_16 (insn);
+ disp &= ~3;
+ fput_const (disp, info);
+ break;
+ }
+
+ case '&':
+ {
+ /* 16-bit long disp., PA2.0 wide only. */
+ int disp = extract_16 (insn);
+ disp &= ~7;
+ fput_const (disp, info);
+ break;
+ }
+
+ case '_':
+ break; /* Dealt with by '{' */
+
+ case '{':
+ {
+ int sub = GET_FIELD (insn, 14, 16);
+ int df = GET_FIELD (insn, 17, 18);
+ int sf = GET_FIELD (insn, 19, 20);
+ const char * const * source = float_format_names;
+ const char * const * dest = float_format_names;
+ const char *t = "";
+
+ if (sub == 4)
+ {
+ fputs_filtered (",UND ", info);
+ break;
+ }
+ if ((sub & 3) == 3)
+ t = ",t";
+ if ((sub & 3) == 1)
+ source = sub & 4 ? fcnv_ufixed_names : fcnv_fixed_names;
+ if (sub & 2)
+ dest = sub & 4 ? fcnv_ufixed_names : fcnv_fixed_names;
+
+ (*info->fprintf_func) (info->stream, "%s%s%s ",
+ t, source[sf], dest[df]);
+ break;
+ }
+
+ case 'm':
+ {
+ int y = GET_FIELD (insn, 16, 18);
+
+ if (y != 1)
+ fput_const ((y ^ 1) - 1, info);
+ }
+ break;
+
+ case 'h':
+ {
+ int cbit;
+
+ cbit = GET_FIELD (insn, 16, 18);
+
+ if (cbit > 0)
+ (*info->fprintf_func) (info->stream, ",%d", cbit - 1);
+ break;
+ }
+
+ case '=':
+ {
+ int cond = GET_FIELD (insn, 27, 31);
+
+ switch (cond)
+ {
+ case 0: fputs_filtered (" ", info); break;
+ case 1: fputs_filtered ("acc ", info); break;
+ case 2: fputs_filtered ("rej ", info); break;
+ case 5: fputs_filtered ("acc8 ", info); break;
+ case 6: fputs_filtered ("rej8 ", info); break;
+ case 9: fputs_filtered ("acc6 ", info); break;
+ case 13: fputs_filtered ("acc4 ", info); break;
+ case 17: fputs_filtered ("acc2 ", info); break;
+ default: break;
+ }
+ break;
+ }
+
+ case 'X':
+ (*info->print_address_func)
+ (memaddr + 8 + extract_22 (insn), info);
+ break;
+ case 'L':
+ fputs_filtered (",rp", info);
+ break;
+ default:
+ (*info->fprintf_func) (info->stream, "%c", *s);
+ break;
+ }
+ }
+ return sizeof (insn);
+ }
+ }
+ (*info->fprintf_func) (info->stream, "#%8x", insn);
+ return sizeof (insn);
+}
diff --git a/disas/i386.c b/disas/i386.c
new file mode 100644
index 0000000000..3b006b13e0
--- /dev/null
+++ b/disas/i386.c
@@ -0,0 +1,6562 @@
+/* opcodes/i386-dis.c r1.126 */
+/* Print i386 instructions for GDB, the GNU debugger.
+ Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>. */
+
+/* 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
+ July 1988
+ modified by John Hassey (hassey@dg-rtp.dg.com)
+ x86-64 support added by Jan Hubicka (jh@suse.cz)
+ VIA PadLock support by Michal Ludvig (mludvig@suse.cz). */
+
+/* The main tables describing the instructions is essentially a copy
+ of the "Opcode Map" chapter (Appendix A) of the Intel 80386
+ Programmers Manual. Usually, there is a capital letter, followed
+ by a small letter. The capital letter tell the addressing mode,
+ and the small letter tells about the operand size. Refer to
+ the Intel manual for details. */
+
+#include <stdlib.h>
+#include "disas/bfd.h"
+/* include/opcode/i386.h r1.78 */
+
+/* opcode/i386.h -- Intel 80386 opcode macros
+ Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler, and GDB, the GNU Debugger.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>. */
+
+/* The SystemV/386 SVR3.2 assembler, and probably all AT&T derived
+ ix86 Unix assemblers, generate floating point instructions with
+ reversed source and destination registers in certain cases.
+ Unfortunately, gcc and possibly many other programs use this
+ reversed syntax, so we're stuck with it.
+
+ eg. `fsub %st(3),%st' results in st = st - st(3) as expected, but
+ `fsub %st,%st(3)' results in st(3) = st - st(3), rather than
+ the expected st(3) = st(3) - st
+
+ This happens with all the non-commutative arithmetic floating point
+ operations with two register operands, where the source register is
+ %st, and destination register is %st(i).
+
+ The affected opcode map is dceX, dcfX, deeX, defX. */
+
+#ifndef SYSV386_COMPAT
+/* Set non-zero for broken, compatible instructions. Set to zero for
+ non-broken opcodes at your peril. gcc generates SystemV/386
+ compatible instructions. */
+#define SYSV386_COMPAT 1
+#endif
+#ifndef OLDGCC_COMPAT
+/* Set non-zero to cater for old (<= 2.8.1) versions of gcc that could
+ generate nonsense fsubp, fsubrp, fdivp and fdivrp with operands
+ reversed. */
+#define OLDGCC_COMPAT SYSV386_COMPAT
+#endif
+
+#define MOV_AX_DISP32 0xa0
+#define POP_SEG_SHORT 0x07
+#define JUMP_PC_RELATIVE 0xeb
+#define INT_OPCODE 0xcd
+#define INT3_OPCODE 0xcc
+/* The opcode for the fwait instruction, which disassembler treats as a
+ prefix when it can. */
+#define FWAIT_OPCODE 0x9b
+#define ADDR_PREFIX_OPCODE 0x67
+#define DATA_PREFIX_OPCODE 0x66
+#define LOCK_PREFIX_OPCODE 0xf0
+#define CS_PREFIX_OPCODE 0x2e
+#define DS_PREFIX_OPCODE 0x3e
+#define ES_PREFIX_OPCODE 0x26
+#define FS_PREFIX_OPCODE 0x64
+#define GS_PREFIX_OPCODE 0x65
+#define SS_PREFIX_OPCODE 0x36
+#define REPNE_PREFIX_OPCODE 0xf2
+#define REPE_PREFIX_OPCODE 0xf3
+
+#define TWO_BYTE_OPCODE_ESCAPE 0x0f
+#define NOP_OPCODE (char) 0x90
+
+/* register numbers */
+#define EBP_REG_NUM 5
+#define ESP_REG_NUM 4
+
+/* modrm_byte.regmem for twobyte escape */
+#define ESCAPE_TO_TWO_BYTE_ADDRESSING ESP_REG_NUM
+/* index_base_byte.index for no index register addressing */
+#define NO_INDEX_REGISTER ESP_REG_NUM
+/* index_base_byte.base for no base register addressing */
+#define NO_BASE_REGISTER EBP_REG_NUM
+#define NO_BASE_REGISTER_16 6
+
+/* modrm.mode = REGMEM_FIELD_HAS_REG when a register is in there */
+#define REGMEM_FIELD_HAS_REG 0x3/* always = 0x3 */
+#define REGMEM_FIELD_HAS_MEM (~REGMEM_FIELD_HAS_REG)
+
+/* x86-64 extension prefix. */
+#define REX_OPCODE 0x40
+
+/* Indicates 64 bit operand size. */
+#define REX_W 8
+/* High extension to reg field of modrm byte. */
+#define REX_R 4
+/* High extension to SIB index field. */
+#define REX_X 2
+/* High extension to base field of modrm or SIB, or reg field of opcode. */
+#define REX_B 1
+
+/* max operands per insn */
+#define MAX_OPERANDS 4
+
+/* max immediates per insn (lcall, ljmp, insertq, extrq) */
+#define MAX_IMMEDIATE_OPERANDS 2
+
+/* max memory refs per insn (string ops) */
+#define MAX_MEMORY_OPERANDS 2
+
+/* max size of insn mnemonics. */
+#define MAX_MNEM_SIZE 16
+
+/* max size of register name in insn mnemonics. */
+#define MAX_REG_NAME_SIZE 8
+
+/* opcodes/i386-dis.c r1.126 */
+#include "qemu-common.h"
+
+#include <setjmp.h>
+
+static int fetch_data2(struct disassemble_info *, bfd_byte *);
+static int fetch_data(struct disassemble_info *, bfd_byte *);
+static void ckprefix (void);
+static const char *prefix_name (int, int);
+static int print_insn (bfd_vma, disassemble_info *);
+static void dofloat (int);
+static void OP_ST (int, int);
+static void OP_STi (int, int);
+static int putop (const char *, int);
+static void oappend (const char *);
+static void append_seg (void);
+static void OP_indirE (int, int);
+static void print_operand_value (char *buf, size_t bufsize, int hex, bfd_vma disp);
+static void print_displacement (char *, bfd_vma);
+static void OP_E (int, int);
+static void OP_G (int, int);
+static bfd_vma get64 (void);
+static bfd_signed_vma get32 (void);
+static bfd_signed_vma get32s (void);
+static int get16 (void);
+static void set_op (bfd_vma, int);
+static void OP_REG (int, int);
+static void OP_IMREG (int, int);
+static void OP_I (int, int);
+static void OP_I64 (int, int);
+static void OP_sI (int, int);
+static void OP_J (int, int);
+static void OP_SEG (int, int);
+static void OP_DIR (int, int);
+static void OP_OFF (int, int);
+static void OP_OFF64 (int, int);
+static void ptr_reg (int, int);
+static void OP_ESreg (int, int);
+static void OP_DSreg (int, int);
+static void OP_C (int, int);
+static void OP_D (int, int);
+static void OP_T (int, int);
+static void OP_R (int, int);
+static void OP_MMX (int, int);
+static void OP_XMM (int, int);
+static void OP_EM (int, int);
+static void OP_EX (int, int);
+static void OP_EMC (int,int);
+static void OP_MXC (int,int);
+static void OP_MS (int, int);
+static void OP_XS (int, int);
+static void OP_M (int, int);
+static void OP_VMX (int, int);
+static void OP_0fae (int, int);
+static void OP_0f07 (int, int);
+static void NOP_Fixup1 (int, int);
+static void NOP_Fixup2 (int, int);
+static void OP_3DNowSuffix (int, int);
+static void OP_SIMD_Suffix (int, int);
+static void SIMD_Fixup (int, int);
+static void PNI_Fixup (int, int);
+static void SVME_Fixup (int, int);
+static void INVLPG_Fixup (int, int);
+static void BadOp (void);
+static void VMX_Fixup (int, int);
+static void REP_Fixup (int, int);
+static void CMPXCHG8B_Fixup (int, int);
+static void XMM_Fixup (int, int);
+static void CRC32_Fixup (int, int);
+
+struct dis_private {
+ /* Points to first byte not fetched. */
+ bfd_byte *max_fetched;
+ bfd_byte the_buffer[MAX_MNEM_SIZE];
+ bfd_vma insn_start;
+ int orig_sizeflag;
+ jmp_buf bailout;
+};
+
+enum address_mode
+{
+ mode_16bit,
+ mode_32bit,
+ mode_64bit
+};
+
+static enum address_mode address_mode;
+
+/* Flags for the prefixes for the current instruction. See below. */
+static int prefixes;
+
+/* REX prefix the current instruction. See below. */
+static int rex;
+/* Bits of REX we've already used. */
+static int rex_used;
+/* Mark parts used in the REX prefix. When we are testing for
+ empty prefix (for 8bit register REX extension), just mask it
+ out. Otherwise test for REX bit is excuse for existence of REX
+ only in case value is nonzero. */
+#define USED_REX(value) \
+ { \
+ if (value) \
+ { \
+ if ((rex & value)) \
+ rex_used |= (value) | REX_OPCODE; \
+ } \
+ else \
+ rex_used |= REX_OPCODE; \
+ }
+
+/* Flags for prefixes which we somehow handled when printing the
+ current instruction. */
+static int used_prefixes;
+
+/* Flags stored in PREFIXES. */
+#define PREFIX_REPZ 1
+#define PREFIX_REPNZ 2
+#define PREFIX_LOCK 4
+#define PREFIX_CS 8
+#define PREFIX_SS 0x10
+#define PREFIX_DS 0x20
+#define PREFIX_ES 0x40
+#define PREFIX_FS 0x80
+#define PREFIX_GS 0x100
+#define PREFIX_DATA 0x200
+#define PREFIX_ADDR 0x400
+#define PREFIX_FWAIT 0x800
+
+/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
+ to ADDR (exclusive) are valid. Returns 1 for success, longjmps
+ on error. */
+static int
+fetch_data2(struct disassemble_info *info, bfd_byte *addr)
+{
+ int status;
+ struct dis_private *priv = (struct dis_private *) info->private_data;
+ bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
+
+ if (addr <= priv->the_buffer + MAX_MNEM_SIZE)
+ status = (*info->read_memory_func) (start,
+ priv->max_fetched,
+ addr - priv->max_fetched,
+ info);
+ else
+ status = -1;
+ if (status != 0)
+ {
+ /* If we did manage to read at least one byte, then
+ print_insn_i386 will do something sensible. Otherwise, print
+ an error. We do that here because this is where we know
+ STATUS. */
+ if (priv->max_fetched == priv->the_buffer)
+ (*info->memory_error_func) (status, start, info);
+ longjmp (priv->bailout, 1);
+ }
+ else
+ priv->max_fetched = addr;
+ return 1;
+}
+
+static int
+fetch_data(struct disassemble_info *info, bfd_byte *addr)
+{
+ if (addr <= ((struct dis_private *) (info->private_data))->max_fetched) {
+ return 1;
+ } else {
+ return fetch_data2(info, addr);
+ }
+}
+
+
+#define XX { NULL, 0 }
+
+#define Eb { OP_E, b_mode }
+#define Ev { OP_E, v_mode }
+#define Ed { OP_E, d_mode }
+#define Edq { OP_E, dq_mode }
+#define Edqw { OP_E, dqw_mode }
+#define Edqb { OP_E, dqb_mode }
+#define Edqd { OP_E, dqd_mode }
+#define indirEv { OP_indirE, stack_v_mode }
+#define indirEp { OP_indirE, f_mode }
+#define stackEv { OP_E, stack_v_mode }
+#define Em { OP_E, m_mode }
+#define Ew { OP_E, w_mode }
+#define M { OP_M, 0 } /* lea, lgdt, etc. */
+#define Ma { OP_M, v_mode }
+#define Mp { OP_M, f_mode } /* 32 or 48 bit memory operand for LDS, LES etc */
+#define Mq { OP_M, q_mode }
+#define Gb { OP_G, b_mode }
+#define Gv { OP_G, v_mode }
+#define Gd { OP_G, d_mode }
+#define Gdq { OP_G, dq_mode }
+#define Gm { OP_G, m_mode }
+#define Gw { OP_G, w_mode }
+#define Rd { OP_R, d_mode }
+#define Rm { OP_R, m_mode }
+#define Ib { OP_I, b_mode }
+#define sIb { OP_sI, b_mode } /* sign extened byte */
+#define Iv { OP_I, v_mode }
+#define Iq { OP_I, q_mode }
+#define Iv64 { OP_I64, v_mode }
+#define Iw { OP_I, w_mode }
+#define I1 { OP_I, const_1_mode }
+#define Jb { OP_J, b_mode }
+#define Jv { OP_J, v_mode }
+#define Cm { OP_C, m_mode }
+#define Dm { OP_D, m_mode }
+#define Td { OP_T, d_mode }
+
+#define RMeAX { OP_REG, eAX_reg }
+#define RMeBX { OP_REG, eBX_reg }
+#define RMeCX { OP_REG, eCX_reg }
+#define RMeDX { OP_REG, eDX_reg }
+#define RMeSP { OP_REG, eSP_reg }
+#define RMeBP { OP_REG, eBP_reg }
+#define RMeSI { OP_REG, eSI_reg }
+#define RMeDI { OP_REG, eDI_reg }
+#define RMrAX { OP_REG, rAX_reg }
+#define RMrBX { OP_REG, rBX_reg }
+#define RMrCX { OP_REG, rCX_reg }
+#define RMrDX { OP_REG, rDX_reg }
+#define RMrSP { OP_REG, rSP_reg }
+#define RMrBP { OP_REG, rBP_reg }
+#define RMrSI { OP_REG, rSI_reg }
+#define RMrDI { OP_REG, rDI_reg }
+#define RMAL { OP_REG, al_reg }
+#define RMAL { OP_REG, al_reg }
+#define RMCL { OP_REG, cl_reg }
+#define RMDL { OP_REG, dl_reg }
+#define RMBL { OP_REG, bl_reg }
+#define RMAH { OP_REG, ah_reg }
+#define RMCH { OP_REG, ch_reg }
+#define RMDH { OP_REG, dh_reg }
+#define RMBH { OP_REG, bh_reg }
+#define RMAX { OP_REG, ax_reg }
+#define RMDX { OP_REG, dx_reg }
+
+#define eAX { OP_IMREG, eAX_reg }
+#define eBX { OP_IMREG, eBX_reg }
+#define eCX { OP_IMREG, eCX_reg }
+#define eDX { OP_IMREG, eDX_reg }
+#define eSP { OP_IMREG, eSP_reg }
+#define eBP { OP_IMREG, eBP_reg }
+#define eSI { OP_IMREG, eSI_reg }
+#define eDI { OP_IMREG, eDI_reg }
+#define AL { OP_IMREG, al_reg }
+#define CL { OP_IMREG, cl_reg }
+#define DL { OP_IMREG, dl_reg }
+#define BL { OP_IMREG, bl_reg }
+#define AH { OP_IMREG, ah_reg }
+#define CH { OP_IMREG, ch_reg }
+#define DH { OP_IMREG, dh_reg }
+#define BH { OP_IMREG, bh_reg }
+#define AX { OP_IMREG, ax_reg }
+#define DX { OP_IMREG, dx_reg }
+#define zAX { OP_IMREG, z_mode_ax_reg }
+#define indirDX { OP_IMREG, indir_dx_reg }
+
+#define Sw { OP_SEG, w_mode }
+#define Sv { OP_SEG, v_mode }
+#define Ap { OP_DIR, 0 }
+#define Ob { OP_OFF64, b_mode }
+#define Ov { OP_OFF64, v_mode }
+#define Xb { OP_DSreg, eSI_reg }
+#define Xv { OP_DSreg, eSI_reg }
+#define Xz { OP_DSreg, eSI_reg }
+#define Yb { OP_ESreg, eDI_reg }
+#define Yv { OP_ESreg, eDI_reg }
+#define DSBX { OP_DSreg, eBX_reg }
+
+#define es { OP_REG, es_reg }
+#define ss { OP_REG, ss_reg }
+#define cs { OP_REG, cs_reg }
+#define ds { OP_REG, ds_reg }
+#define fs { OP_REG, fs_reg }
+#define gs { OP_REG, gs_reg }
+
+#define MX { OP_MMX, 0 }
+#define XM { OP_XMM, 0 }
+#define EM { OP_EM, v_mode }
+#define EMd { OP_EM, d_mode }
+#define EMq { OP_EM, q_mode }
+#define EXd { OP_EX, d_mode }
+#define EXq { OP_EX, q_mode }
+#define EXx { OP_EX, x_mode }
+#define MS { OP_MS, v_mode }
+#define XS { OP_XS, v_mode }
+#define EMC { OP_EMC, v_mode }
+#define MXC { OP_MXC, 0 }
+#define VM { OP_VMX, q_mode }
+#define OPSUF { OP_3DNowSuffix, 0 }
+#define OPSIMD { OP_SIMD_Suffix, 0 }
+#define XMM0 { XMM_Fixup, 0 }
+
+/* Used handle "rep" prefix for string instructions. */
+#define Xbr { REP_Fixup, eSI_reg }
+#define Xvr { REP_Fixup, eSI_reg }
+#define Ybr { REP_Fixup, eDI_reg }
+#define Yvr { REP_Fixup, eDI_reg }
+#define Yzr { REP_Fixup, eDI_reg }
+#define indirDXr { REP_Fixup, indir_dx_reg }
+#define ALr { REP_Fixup, al_reg }
+#define eAXr { REP_Fixup, eAX_reg }
+
+#define cond_jump_flag { NULL, cond_jump_mode }
+#define loop_jcxz_flag { NULL, loop_jcxz_mode }
+
+/* bits in sizeflag */
+#define SUFFIX_ALWAYS 4
+#define AFLAG 2
+#define DFLAG 1
+
+#define b_mode 1 /* byte operand */
+#define v_mode 2 /* operand size depends on prefixes */
+#define w_mode 3 /* word operand */
+#define d_mode 4 /* double word operand */
+#define q_mode 5 /* quad word operand */
+#define t_mode 6 /* ten-byte operand */
+#define x_mode 7 /* 16-byte XMM operand */
+#define m_mode 8 /* d_mode in 32bit, q_mode in 64bit mode. */
+#define cond_jump_mode 9
+#define loop_jcxz_mode 10
+#define dq_mode 11 /* operand size depends on REX prefixes. */
+#define dqw_mode 12 /* registers like dq_mode, memory like w_mode. */
+#define f_mode 13 /* 4- or 6-byte pointer operand */
+#define const_1_mode 14
+#define stack_v_mode 15 /* v_mode for stack-related opcodes. */
+#define z_mode 16 /* non-quad operand size depends on prefixes */
+#define o_mode 17 /* 16-byte operand */
+#define dqb_mode 18 /* registers like dq_mode, memory like b_mode. */
+#define dqd_mode 19 /* registers like dq_mode, memory like d_mode. */
+
+#define es_reg 100
+#define cs_reg 101
+#define ss_reg 102
+#define ds_reg 103
+#define fs_reg 104
+#define gs_reg 105
+
+#define eAX_reg 108
+#define eCX_reg 109
+#define eDX_reg 110
+#define eBX_reg 111
+#define eSP_reg 112
+#define eBP_reg 113
+#define eSI_reg 114
+#define eDI_reg 115
+
+#define al_reg 116
+#define cl_reg 117
+#define dl_reg 118
+#define bl_reg 119
+#define ah_reg 120
+#define ch_reg 121
+#define dh_reg 122
+#define bh_reg 123
+
+#define ax_reg 124
+#define cx_reg 125
+#define dx_reg 126
+#define bx_reg 127
+#define sp_reg 128
+#define bp_reg 129
+#define si_reg 130
+#define di_reg 131
+
+#define rAX_reg 132
+#define rCX_reg 133
+#define rDX_reg 134
+#define rBX_reg 135
+#define rSP_reg 136
+#define rBP_reg 137
+#define rSI_reg 138
+#define rDI_reg 139
+
+#define z_mode_ax_reg 149
+#define indir_dx_reg 150
+
+#define FLOATCODE 1
+#define USE_GROUPS 2
+#define USE_PREFIX_USER_TABLE 3
+#define X86_64_SPECIAL 4
+#define IS_3BYTE_OPCODE 5
+
+#define FLOAT NULL, { { NULL, FLOATCODE } }
+
+#define GRP1a NULL, { { NULL, USE_GROUPS }, { NULL, 0 } }
+#define GRP1b NULL, { { NULL, USE_GROUPS }, { NULL, 1 } }
+#define GRP1S NULL, { { NULL, USE_GROUPS }, { NULL, 2 } }
+#define GRP1Ss NULL, { { NULL, USE_GROUPS }, { NULL, 3 } }
+#define GRP2b NULL, { { NULL, USE_GROUPS }, { NULL, 4 } }
+#define GRP2S NULL, { { NULL, USE_GROUPS }, { NULL, 5 } }
+#define GRP2b_one NULL, { { NULL, USE_GROUPS }, { NULL, 6 } }
+#define GRP2S_one NULL, { { NULL, USE_GROUPS }, { NULL, 7 } }
+#define GRP2b_cl NULL, { { NULL, USE_GROUPS }, { NULL, 8 } }
+#define GRP2S_cl NULL, { { NULL, USE_GROUPS }, { NULL, 9 } }
+#define GRP3b NULL, { { NULL, USE_GROUPS }, { NULL, 10 } }
+#define GRP3S NULL, { { NULL, USE_GROUPS }, { NULL, 11 } }
+#define GRP4 NULL, { { NULL, USE_GROUPS }, { NULL, 12 } }
+#define GRP5 NULL, { { NULL, USE_GROUPS }, { NULL, 13 } }
+#define GRP6 NULL, { { NULL, USE_GROUPS }, { NULL, 14 } }
+#define GRP7 NULL, { { NULL, USE_GROUPS }, { NULL, 15 } }
+#define GRP8 NULL, { { NULL, USE_GROUPS }, { NULL, 16 } }
+#define GRP9 NULL, { { NULL, USE_GROUPS }, { NULL, 17 } }
+#define GRP11_C6 NULL, { { NULL, USE_GROUPS }, { NULL, 18 } }
+#define GRP11_C7 NULL, { { NULL, USE_GROUPS }, { NULL, 19 } }
+#define GRP12 NULL, { { NULL, USE_GROUPS }, { NULL, 20 } }
+#define GRP13 NULL, { { NULL, USE_GROUPS }, { NULL, 21 } }
+#define GRP14 NULL, { { NULL, USE_GROUPS }, { NULL, 22 } }
+#define GRP15 NULL, { { NULL, USE_GROUPS }, { NULL, 23 } }
+#define GRP16 NULL, { { NULL, USE_GROUPS }, { NULL, 24 } }
+#define GRPAMD NULL, { { NULL, USE_GROUPS }, { NULL, 25 } }
+#define GRPPADLCK1 NULL, { { NULL, USE_GROUPS }, { NULL, 26 } }
+#define GRPPADLCK2 NULL, { { NULL, USE_GROUPS }, { NULL, 27 } }
+
+#define PREGRP0 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 0 } }
+#define PREGRP1 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 1 } }
+#define PREGRP2 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 2 } }
+#define PREGRP3 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 3 } }
+#define PREGRP4 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 4 } }
+#define PREGRP5 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 5 } }
+#define PREGRP6 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 6 } }
+#define PREGRP7 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 7 } }
+#define PREGRP8 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 8 } }
+#define PREGRP9 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 9 } }
+#define PREGRP10 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 10 } }
+#define PREGRP11 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 11 } }
+#define PREGRP12 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 12 } }
+#define PREGRP13 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 13 } }
+#define PREGRP14 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 14 } }
+#define PREGRP15 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 15 } }
+#define PREGRP16 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 16 } }
+#define PREGRP17 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 17 } }
+#define PREGRP18 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 18 } }
+#define PREGRP19 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 19 } }
+#define PREGRP20 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 20 } }
+#define PREGRP21 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 21 } }
+#define PREGRP22 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 22 } }
+#define PREGRP23 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 23 } }
+#define PREGRP24 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 24 } }
+#define PREGRP25 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 25 } }
+#define PREGRP26 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 26 } }
+#define PREGRP27 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 27 } }
+#define PREGRP28 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 28 } }
+#define PREGRP29 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 29 } }
+#define PREGRP30 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 30 } }
+#define PREGRP31 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 31 } }
+#define PREGRP32 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 32 } }
+#define PREGRP33 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 33 } }
+#define PREGRP34 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 34 } }
+#define PREGRP35 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 35 } }
+#define PREGRP36 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 36 } }
+#define PREGRP37 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 37 } }
+#define PREGRP38 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 38 } }
+#define PREGRP39 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 39 } }
+#define PREGRP40 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 40 } }
+#define PREGRP41 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 41 } }
+#define PREGRP42 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 42 } }
+#define PREGRP43 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 43 } }
+#define PREGRP44 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 44 } }
+#define PREGRP45 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 45 } }
+#define PREGRP46 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 46 } }
+#define PREGRP47 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 47 } }
+#define PREGRP48 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 48 } }
+#define PREGRP49 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 49 } }
+#define PREGRP50 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 50 } }
+#define PREGRP51 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 51 } }
+#define PREGRP52 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 52 } }
+#define PREGRP53 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 53 } }
+#define PREGRP54 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 54 } }
+#define PREGRP55 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 55 } }
+#define PREGRP56 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 56 } }
+#define PREGRP57 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 57 } }
+#define PREGRP58 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 58 } }
+#define PREGRP59 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 59 } }
+#define PREGRP60 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 60 } }
+#define PREGRP61 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 61 } }
+#define PREGRP62 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 62 } }
+#define PREGRP63 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 63 } }
+#define PREGRP64 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 64 } }
+#define PREGRP65 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 65 } }
+#define PREGRP66 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 66 } }
+#define PREGRP67 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 67 } }
+#define PREGRP68 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 68 } }
+#define PREGRP69 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 69 } }
+#define PREGRP70 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 70 } }
+#define PREGRP71 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 71 } }
+#define PREGRP72 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 72 } }
+#define PREGRP73 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 73 } }
+#define PREGRP74 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 74 } }
+#define PREGRP75 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 75 } }
+#define PREGRP76 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 76 } }
+#define PREGRP77 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 77 } }
+#define PREGRP78 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 78 } }
+#define PREGRP79 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 79 } }
+#define PREGRP80 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 80 } }
+#define PREGRP81 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 81 } }
+#define PREGRP82 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 82 } }
+#define PREGRP83 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 83 } }
+#define PREGRP84 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 84 } }
+#define PREGRP85 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 85 } }
+#define PREGRP86 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 86 } }
+#define PREGRP87 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 87 } }
+#define PREGRP88 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 88 } }
+#define PREGRP89 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 89 } }
+#define PREGRP90 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 90 } }
+#define PREGRP91 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 91 } }
+#define PREGRP92 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 92 } }
+#define PREGRP93 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 93 } }
+#define PREGRP94 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 94 } }
+#define PREGRP95 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 95 } }
+#define PREGRP96 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 96 } }
+#define PREGRP97 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 97 } }
+
+
+#define X86_64_0 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 0 } }
+#define X86_64_1 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 1 } }
+#define X86_64_2 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 2 } }
+#define X86_64_3 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 3 } }
+
+#define THREE_BYTE_0 NULL, { { NULL, IS_3BYTE_OPCODE }, { NULL, 0 } }
+#define THREE_BYTE_1 NULL, { { NULL, IS_3BYTE_OPCODE }, { NULL, 1 } }
+
+typedef void (*op_rtn) (int bytemode, int sizeflag);
+
+struct dis386 {
+ const char *name;
+ struct
+ {
+ op_rtn rtn;
+ int bytemode;
+ } op[MAX_OPERANDS];
+};
+
+/* Upper case letters in the instruction names here are macros.
+ 'A' => print 'b' if no register operands or suffix_always is true
+ 'B' => print 'b' if suffix_always is true
+ 'C' => print 's' or 'l' ('w' or 'd' in Intel mode) depending on operand
+ . size prefix
+ 'D' => print 'w' if no register operands or 'w', 'l' or 'q', if
+ . suffix_always is true
+ 'E' => print 'e' if 32-bit form of jcxz
+ 'F' => print 'w' or 'l' depending on address size prefix (loop insns)
+ 'G' => print 'w' or 'l' depending on operand size prefix (i/o insns)
+ 'H' => print ",pt" or ",pn" branch hint
+ 'I' => honor following macro letter even in Intel mode (implemented only
+ . for some of the macro letters)
+ 'J' => print 'l'
+ 'K' => print 'd' or 'q' if rex prefix is present.
+ 'L' => print 'l' if suffix_always is true
+ 'N' => print 'n' if instruction has no wait "prefix"
+ 'O' => print 'd' or 'o' (or 'q' in Intel mode)
+ 'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix,
+ . or suffix_always is true. print 'q' if rex prefix is present.
+ 'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always
+ . is true
+ 'R' => print 'w', 'l' or 'q' ('d' for 'l' and 'e' in Intel mode)
+ 'S' => print 'w', 'l' or 'q' if suffix_always is true
+ 'T' => print 'q' in 64bit mode and behave as 'P' otherwise
+ 'U' => print 'q' in 64bit mode and behave as 'Q' otherwise
+ 'V' => print 'q' in 64bit mode and behave as 'S' otherwise
+ 'W' => print 'b', 'w' or 'l' ('d' in Intel mode)
+ 'X' => print 's', 'd' depending on data16 prefix (for XMM)
+ 'Y' => 'q' if instruction has an REX 64bit overwrite prefix
+ 'Z' => print 'q' in 64bit mode and behave as 'L' otherwise
+
+ Many of the above letters print nothing in Intel mode. See "putop"
+ for the details.
+
+ Braces '{' and '}', and vertical bars '|', indicate alternative
+ mnemonic strings for AT&T, Intel, X86_64 AT&T, and X86_64 Intel
+ modes. In cases where there are only two alternatives, the X86_64
+ instruction is reserved, and "(bad)" is printed.
+*/
+
+static const struct dis386 dis386[] = {
+ /* 00 */
+ { "addB", { Eb, Gb } },
+ { "addS", { Ev, Gv } },
+ { "addB", { Gb, Eb } },
+ { "addS", { Gv, Ev } },
+ { "addB", { AL, Ib } },
+ { "addS", { eAX, Iv } },
+ { "push{T|}", { es } },
+ { "pop{T|}", { es } },
+ /* 08 */
+ { "orB", { Eb, Gb } },
+ { "orS", { Ev, Gv } },
+ { "orB", { Gb, Eb } },
+ { "orS", { Gv, Ev } },
+ { "orB", { AL, Ib } },
+ { "orS", { eAX, Iv } },
+ { "push{T|}", { cs } },
+ { "(bad)", { XX } }, /* 0x0f extended opcode escape */
+ /* 10 */
+ { "adcB", { Eb, Gb } },
+ { "adcS", { Ev, Gv } },
+ { "adcB", { Gb, Eb } },
+ { "adcS", { Gv, Ev } },
+ { "adcB", { AL, Ib } },
+ { "adcS", { eAX, Iv } },
+ { "push{T|}", { ss } },
+ { "pop{T|}", { ss } },
+ /* 18 */
+ { "sbbB", { Eb, Gb } },
+ { "sbbS", { Ev, Gv } },
+ { "sbbB", { Gb, Eb } },
+ { "sbbS", { Gv, Ev } },
+ { "sbbB", { AL, Ib } },
+ { "sbbS", { eAX, Iv } },
+ { "push{T|}", { ds } },
+ { "pop{T|}", { ds } },
+ /* 20 */
+ { "andB", { Eb, Gb } },
+ { "andS", { Ev, Gv } },
+ { "andB", { Gb, Eb } },
+ { "andS", { Gv, Ev } },
+ { "andB", { AL, Ib } },
+ { "andS", { eAX, Iv } },
+ { "(bad)", { XX } }, /* SEG ES prefix */
+ { "daa{|}", { XX } },
+ /* 28 */
+ { "subB", { Eb, Gb } },
+ { "subS", { Ev, Gv } },
+ { "subB", { Gb, Eb } },
+ { "subS", { Gv, Ev } },
+ { "subB", { AL, Ib } },
+ { "subS", { eAX, Iv } },
+ { "(bad)", { XX } }, /* SEG CS prefix */
+ { "das{|}", { XX } },
+ /* 30 */
+ { "xorB", { Eb, Gb } },
+ { "xorS", { Ev, Gv } },
+ { "xorB", { Gb, Eb } },
+ { "xorS", { Gv, Ev } },
+ { "xorB", { AL, Ib } },
+ { "xorS", { eAX, Iv } },
+ { "(bad)", { XX } }, /* SEG SS prefix */
+ { "aaa{|}", { XX } },
+ /* 38 */
+ { "cmpB", { Eb, Gb } },
+ { "cmpS", { Ev, Gv } },
+ { "cmpB", { Gb, Eb } },
+ { "cmpS", { Gv, Ev } },
+ { "cmpB", { AL, Ib } },
+ { "cmpS", { eAX, Iv } },
+ { "(bad)", { XX } }, /* SEG DS prefix */
+ { "aas{|}", { XX } },
+ /* 40 */
+ { "inc{S|}", { RMeAX } },
+ { "inc{S|}", { RMeCX } },
+ { "inc{S|}", { RMeDX } },
+ { "inc{S|}", { RMeBX } },
+ { "inc{S|}", { RMeSP } },
+ { "inc{S|}", { RMeBP } },
+ { "inc{S|}", { RMeSI } },
+ { "inc{S|}", { RMeDI } },
+ /* 48 */
+ { "dec{S|}", { RMeAX } },
+ { "dec{S|}", { RMeCX } },
+ { "dec{S|}", { RMeDX } },
+ { "dec{S|}", { RMeBX } },
+ { "dec{S|}", { RMeSP } },
+ { "dec{S|}", { RMeBP } },
+ { "dec{S|}", { RMeSI } },
+ { "dec{S|}", { RMeDI } },
+ /* 50 */
+ { "pushV", { RMrAX } },
+ { "pushV", { RMrCX } },
+ { "pushV", { RMrDX } },
+ { "pushV", { RMrBX } },
+ { "pushV", { RMrSP } },
+ { "pushV", { RMrBP } },
+ { "pushV", { RMrSI } },
+ { "pushV", { RMrDI } },
+ /* 58 */
+ { "popV", { RMrAX } },
+ { "popV", { RMrCX } },
+ { "popV", { RMrDX } },
+ { "popV", { RMrBX } },
+ { "popV", { RMrSP } },
+ { "popV", { RMrBP } },
+ { "popV", { RMrSI } },
+ { "popV", { RMrDI } },
+ /* 60 */
+ { X86_64_0 },
+ { X86_64_1 },
+ { X86_64_2 },
+ { X86_64_3 },
+ { "(bad)", { XX } }, /* seg fs */
+ { "(bad)", { XX } }, /* seg gs */
+ { "(bad)", { XX } }, /* op size prefix */
+ { "(bad)", { XX } }, /* adr size prefix */
+ /* 68 */
+ { "pushT", { Iq } },
+ { "imulS", { Gv, Ev, Iv } },
+ { "pushT", { sIb } },
+ { "imulS", { Gv, Ev, sIb } },
+ { "ins{b||b|}", { Ybr, indirDX } },
+ { "ins{R||G|}", { Yzr, indirDX } },
+ { "outs{b||b|}", { indirDXr, Xb } },
+ { "outs{R||G|}", { indirDXr, Xz } },
+ /* 70 */
+ { "joH", { Jb, XX, cond_jump_flag } },
+ { "jnoH", { Jb, XX, cond_jump_flag } },
+ { "jbH", { Jb, XX, cond_jump_flag } },
+ { "jaeH", { Jb, XX, cond_jump_flag } },
+ { "jeH", { Jb, XX, cond_jump_flag } },
+ { "jneH", { Jb, XX, cond_jump_flag } },
+ { "jbeH", { Jb, XX, cond_jump_flag } },
+ { "jaH", { Jb, XX, cond_jump_flag } },
+ /* 78 */
+ { "jsH", { Jb, XX, cond_jump_flag } },
+ { "jnsH", { Jb, XX, cond_jump_flag } },
+ { "jpH", { Jb, XX, cond_jump_flag } },
+ { "jnpH", { Jb, XX, cond_jump_flag } },
+ { "jlH", { Jb, XX, cond_jump_flag } },
+ { "jgeH", { Jb, XX, cond_jump_flag } },
+ { "jleH", { Jb, XX, cond_jump_flag } },
+ { "jgH", { Jb, XX, cond_jump_flag } },
+ /* 80 */
+ { GRP1b },
+ { GRP1S },
+ { "(bad)", { XX } },
+ { GRP1Ss },
+ { "testB", { Eb, Gb } },
+ { "testS", { Ev, Gv } },
+ { "xchgB", { Eb, Gb } },
+ { "xchgS", { Ev, Gv } },
+ /* 88 */
+ { "movB", { Eb, Gb } },
+ { "movS", { Ev, Gv } },
+ { "movB", { Gb, Eb } },
+ { "movS", { Gv, Ev } },
+ { "movD", { Sv, Sw } },
+ { "leaS", { Gv, M } },
+ { "movD", { Sw, Sv } },
+ { GRP1a },
+ /* 90 */
+ { PREGRP38 },
+ { "xchgS", { RMeCX, eAX } },
+ { "xchgS", { RMeDX, eAX } },
+ { "xchgS", { RMeBX, eAX } },
+ { "xchgS", { RMeSP, eAX } },
+ { "xchgS", { RMeBP, eAX } },
+ { "xchgS", { RMeSI, eAX } },
+ { "xchgS", { RMeDI, eAX } },
+ /* 98 */
+ { "cW{t||t|}R", { XX } },
+ { "cR{t||t|}O", { XX } },
+ { "Jcall{T|}", { Ap } },
+ { "(bad)", { XX } }, /* fwait */
+ { "pushfT", { XX } },
+ { "popfT", { XX } },
+ { "sahf{|}", { XX } },
+ { "lahf{|}", { XX } },
+ /* a0 */
+ { "movB", { AL, Ob } },
+ { "movS", { eAX, Ov } },
+ { "movB", { Ob, AL } },
+ { "movS", { Ov, eAX } },
+ { "movs{b||b|}", { Ybr, Xb } },
+ { "movs{R||R|}", { Yvr, Xv } },
+ { "cmps{b||b|}", { Xb, Yb } },
+ { "cmps{R||R|}", { Xv, Yv } },
+ /* a8 */
+ { "testB", { AL, Ib } },
+ { "testS", { eAX, Iv } },
+ { "stosB", { Ybr, AL } },
+ { "stosS", { Yvr, eAX } },
+ { "lodsB", { ALr, Xb } },
+ { "lodsS", { eAXr, Xv } },
+ { "scasB", { AL, Yb } },
+ { "scasS", { eAX, Yv } },
+ /* b0 */
+ { "movB", { RMAL, Ib } },
+ { "movB", { RMCL, Ib } },
+ { "movB", { RMDL, Ib } },
+ { "movB", { RMBL, Ib } },
+ { "movB", { RMAH, Ib } },
+ { "movB", { RMCH, Ib } },
+ { "movB", { RMDH, Ib } },
+ { "movB", { RMBH, Ib } },
+ /* b8 */
+ { "movS", { RMeAX, Iv64 } },
+ { "movS", { RMeCX, Iv64 } },
+ { "movS", { RMeDX, Iv64 } },
+ { "movS", { RMeBX, Iv64 } },
+ { "movS", { RMeSP, Iv64 } },
+ { "movS", { RMeBP, Iv64 } },
+ { "movS", { RMeSI, Iv64 } },
+ { "movS", { RMeDI, Iv64 } },
+ /* c0 */
+ { GRP2b },
+ { GRP2S },
+ { "retT", { Iw } },
+ { "retT", { XX } },
+ { "les{S|}", { Gv, Mp } },
+ { "ldsS", { Gv, Mp } },
+ { GRP11_C6 },
+ { GRP11_C7 },
+ /* c8 */
+ { "enterT", { Iw, Ib } },
+ { "leaveT", { XX } },
+ { "lretP", { Iw } },
+ { "lretP", { XX } },
+ { "int3", { XX } },
+ { "int", { Ib } },
+ { "into{|}", { XX } },
+ { "iretP", { XX } },
+ /* d0 */
+ { GRP2b_one },
+ { GRP2S_one },
+ { GRP2b_cl },
+ { GRP2S_cl },
+ { "aam{|}", { sIb } },
+ { "aad{|}", { sIb } },
+ { "(bad)", { XX } },
+ { "xlat", { DSBX } },
+ /* d8 */
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ /* e0 */
+ { "loopneFH", { Jb, XX, loop_jcxz_flag } },
+ { "loopeFH", { Jb, XX, loop_jcxz_flag } },
+ { "loopFH", { Jb, XX, loop_jcxz_flag } },
+ { "jEcxzH", { Jb, XX, loop_jcxz_flag } },
+ { "inB", { AL, Ib } },
+ { "inG", { zAX, Ib } },
+ { "outB", { Ib, AL } },
+ { "outG", { Ib, zAX } },
+ /* e8 */
+ { "callT", { Jv } },
+ { "jmpT", { Jv } },
+ { "Jjmp{T|}", { Ap } },
+ { "jmp", { Jb } },
+ { "inB", { AL, indirDX } },
+ { "inG", { zAX, indirDX } },
+ { "outB", { indirDX, AL } },
+ { "outG", { indirDX, zAX } },
+ /* f0 */
+ { "(bad)", { XX } }, /* lock prefix */
+ { "icebp", { XX } },
+ { "(bad)", { XX } }, /* repne */
+ { "(bad)", { XX } }, /* repz */
+ { "hlt", { XX } },
+ { "cmc", { XX } },
+ { GRP3b },
+ { GRP3S },
+ /* f8 */
+ { "clc", { XX } },
+ { "stc", { XX } },
+ { "cli", { XX } },
+ { "sti", { XX } },
+ { "cld", { XX } },
+ { "std", { XX } },
+ { GRP4 },
+ { GRP5 },
+};
+
+static const struct dis386 dis386_twobyte[] = {
+ /* 00 */
+ { GRP6 },
+ { GRP7 },
+ { "larS", { Gv, Ew } },
+ { "lslS", { Gv, Ew } },
+ { "(bad)", { XX } },
+ { "syscall", { XX } },
+ { "clts", { XX } },
+ { "sysretP", { XX } },
+ /* 08 */
+ { "invd", { XX } },
+ { "wbinvd", { XX } },
+ { "(bad)", { XX } },
+ { "ud2a", { XX } },
+ { "(bad)", { XX } },
+ { GRPAMD },
+ { "femms", { XX } },
+ { "", { MX, EM, OPSUF } }, /* See OP_3DNowSuffix. */
+ /* 10 */
+ { PREGRP8 },
+ { PREGRP9 },
+ { PREGRP30 },
+ { "movlpX", { EXq, XM, { SIMD_Fixup, 'h' } } },
+ { "unpcklpX", { XM, EXq } },
+ { "unpckhpX", { XM, EXq } },
+ { PREGRP31 },
+ { "movhpX", { EXq, XM, { SIMD_Fixup, 'l' } } },
+ /* 18 */
+ { GRP16 },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "nopQ", { Ev } },
+ /* 20 */
+ { "movZ", { Rm, Cm } },
+ { "movZ", { Rm, Dm } },
+ { "movZ", { Cm, Rm } },
+ { "movZ", { Dm, Rm } },
+ { "movL", { Rd, Td } },
+ { "(bad)", { XX } },
+ { "movL", { Td, Rd } },
+ { "(bad)", { XX } },
+ /* 28 */
+ { "movapX", { XM, EXx } },
+ { "movapX", { EXx, XM } },
+ { PREGRP2 },
+ { PREGRP33 },
+ { PREGRP4 },
+ { PREGRP3 },
+ { PREGRP93 },
+ { PREGRP94 },
+ /* 30 */
+ { "wrmsr", { XX } },
+ { "rdtsc", { XX } },
+ { "rdmsr", { XX } },
+ { "rdpmc", { XX } },
+ { "sysenter", { XX } },
+ { "sysexit", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 38 */
+ { THREE_BYTE_0 },
+ { "(bad)", { XX } },
+ { THREE_BYTE_1 },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 40 */
+ { "cmovo", { Gv, Ev } },
+ { "cmovno", { Gv, Ev } },
+ { "cmovb", { Gv, Ev } },
+ { "cmovae", { Gv, Ev } },
+ { "cmove", { Gv, Ev } },
+ { "cmovne", { Gv, Ev } },
+ { "cmovbe", { Gv, Ev } },
+ { "cmova", { Gv, Ev } },
+ /* 48 */
+ { "cmovs", { Gv, Ev } },
+ { "cmovns", { Gv, Ev } },
+ { "cmovp", { Gv, Ev } },
+ { "cmovnp", { Gv, Ev } },
+ { "cmovl", { Gv, Ev } },
+ { "cmovge", { Gv, Ev } },
+ { "cmovle", { Gv, Ev } },
+ { "cmovg", { Gv, Ev } },
+ /* 50 */
+ { "movmskpX", { Gdq, XS } },
+ { PREGRP13 },
+ { PREGRP12 },
+ { PREGRP11 },
+ { "andpX", { XM, EXx } },
+ { "andnpX", { XM, EXx } },
+ { "orpX", { XM, EXx } },
+ { "xorpX", { XM, EXx } },
+ /* 58 */
+ { PREGRP0 },
+ { PREGRP10 },
+ { PREGRP17 },
+ { PREGRP16 },
+ { PREGRP14 },
+ { PREGRP7 },
+ { PREGRP5 },
+ { PREGRP6 },
+ /* 60 */
+ { PREGRP95 },
+ { PREGRP96 },
+ { PREGRP97 },
+ { "packsswb", { MX, EM } },
+ { "pcmpgtb", { MX, EM } },
+ { "pcmpgtw", { MX, EM } },
+ { "pcmpgtd", { MX, EM } },
+ { "packuswb", { MX, EM } },
+ /* 68 */
+ { "punpckhbw", { MX, EM } },
+ { "punpckhwd", { MX, EM } },
+ { "punpckhdq", { MX, EM } },
+ { "packssdw", { MX, EM } },
+ { PREGRP26 },
+ { PREGRP24 },
+ { "movd", { MX, Edq } },
+ { PREGRP19 },
+ /* 70 */
+ { PREGRP22 },
+ { GRP12 },
+ { GRP13 },
+ { GRP14 },
+ { "pcmpeqb", { MX, EM } },
+ { "pcmpeqw", { MX, EM } },
+ { "pcmpeqd", { MX, EM } },
+ { "emms", { XX } },
+ /* 78 */
+ { PREGRP34 },
+ { PREGRP35 },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { PREGRP28 },
+ { PREGRP29 },
+ { PREGRP23 },
+ { PREGRP20 },
+ /* 80 */
+ { "joH", { Jv, XX, cond_jump_flag } },
+ { "jnoH", { Jv, XX, cond_jump_flag } },
+ { "jbH", { Jv, XX, cond_jump_flag } },
+ { "jaeH", { Jv, XX, cond_jump_flag } },
+ { "jeH", { Jv, XX, cond_jump_flag } },
+ { "jneH", { Jv, XX, cond_jump_flag } },
+ { "jbeH", { Jv, XX, cond_jump_flag } },
+ { "jaH", { Jv, XX, cond_jump_flag } },
+ /* 88 */
+ { "jsH", { Jv, XX, cond_jump_flag } },
+ { "jnsH", { Jv, XX, cond_jump_flag } },
+ { "jpH", { Jv, XX, cond_jump_flag } },
+ { "jnpH", { Jv, XX, cond_jump_flag } },
+ { "jlH", { Jv, XX, cond_jump_flag } },
+ { "jgeH", { Jv, XX, cond_jump_flag } },
+ { "jleH", { Jv, XX, cond_jump_flag } },
+ { "jgH", { Jv, XX, cond_jump_flag } },
+ /* 90 */
+ { "seto", { Eb } },
+ { "setno", { Eb } },
+ { "setb", { Eb } },
+ { "setae", { Eb } },
+ { "sete", { Eb } },
+ { "setne", { Eb } },
+ { "setbe", { Eb } },
+ { "seta", { Eb } },
+ /* 98 */
+ { "sets", { Eb } },
+ { "setns", { Eb } },
+ { "setp", { Eb } },
+ { "setnp", { Eb } },
+ { "setl", { Eb } },
+ { "setge", { Eb } },
+ { "setle", { Eb } },
+ { "setg", { Eb } },
+ /* a0 */
+ { "pushT", { fs } },
+ { "popT", { fs } },
+ { "cpuid", { XX } },
+ { "btS", { Ev, Gv } },
+ { "shldS", { Ev, Gv, Ib } },
+ { "shldS", { Ev, Gv, CL } },
+ { GRPPADLCK2 },
+ { GRPPADLCK1 },
+ /* a8 */
+ { "pushT", { gs } },
+ { "popT", { gs } },
+ { "rsm", { XX } },
+ { "btsS", { Ev, Gv } },
+ { "shrdS", { Ev, Gv, Ib } },
+ { "shrdS", { Ev, Gv, CL } },
+ { GRP15 },
+ { "imulS", { Gv, Ev } },
+ /* b0 */
+ { "cmpxchgB", { Eb, Gb } },
+ { "cmpxchgS", { Ev, Gv } },
+ { "lssS", { Gv, Mp } },
+ { "btrS", { Ev, Gv } },
+ { "lfsS", { Gv, Mp } },
+ { "lgsS", { Gv, Mp } },
+ { "movz{bR|x|bR|x}", { Gv, Eb } },
+ { "movz{wR|x|wR|x}", { Gv, Ew } }, /* yes, there really is movzww ! */
+ /* b8 */
+ { PREGRP37 },
+ { "ud2b", { XX } },
+ { GRP8 },
+ { "btcS", { Ev, Gv } },
+ { "bsfS", { Gv, Ev } },
+ { PREGRP36 },
+ { "movs{bR|x|bR|x}", { Gv, Eb } },
+ { "movs{wR|x|wR|x}", { Gv, Ew } }, /* yes, there really is movsww ! */
+ /* c0 */
+ { "xaddB", { Eb, Gb } },
+ { "xaddS", { Ev, Gv } },
+ { PREGRP1 },
+ { "movntiS", { Ev, Gv } },
+ { "pinsrw", { MX, Edqw, Ib } },
+ { "pextrw", { Gdq, MS, Ib } },
+ { "shufpX", { XM, EXx, Ib } },
+ { GRP9 },
+ /* c8 */
+ { "bswap", { RMeAX } },
+ { "bswap", { RMeCX } },
+ { "bswap", { RMeDX } },
+ { "bswap", { RMeBX } },
+ { "bswap", { RMeSP } },
+ { "bswap", { RMeBP } },
+ { "bswap", { RMeSI } },
+ { "bswap", { RMeDI } },
+ /* d0 */
+ { PREGRP27 },
+ { "psrlw", { MX, EM } },
+ { "psrld", { MX, EM } },
+ { "psrlq", { MX, EM } },
+ { "paddq", { MX, EM } },
+ { "pmullw", { MX, EM } },
+ { PREGRP21 },
+ { "pmovmskb", { Gdq, MS } },
+ /* d8 */
+ { "psubusb", { MX, EM } },
+ { "psubusw", { MX, EM } },
+ { "pminub", { MX, EM } },
+ { "pand", { MX, EM } },
+ { "paddusb", { MX, EM } },
+ { "paddusw", { MX, EM } },
+ { "pmaxub", { MX, EM } },
+ { "pandn", { MX, EM } },
+ /* e0 */
+ { "pavgb", { MX, EM } },
+ { "psraw", { MX, EM } },
+ { "psrad", { MX, EM } },
+ { "pavgw", { MX, EM } },
+ { "pmulhuw", { MX, EM } },
+ { "pmulhw", { MX, EM } },
+ { PREGRP15 },
+ { PREGRP25 },
+ /* e8 */
+ { "psubsb", { MX, EM } },
+ { "psubsw", { MX, EM } },
+ { "pminsw", { MX, EM } },
+ { "por", { MX, EM } },
+ { "paddsb", { MX, EM } },
+ { "paddsw", { MX, EM } },
+ { "pmaxsw", { MX, EM } },
+ { "pxor", { MX, EM } },
+ /* f0 */
+ { PREGRP32 },
+ { "psllw", { MX, EM } },
+ { "pslld", { MX, EM } },
+ { "psllq", { MX, EM } },
+ { "pmuludq", { MX, EM } },
+ { "pmaddwd", { MX, EM } },
+ { "psadbw", { MX, EM } },
+ { PREGRP18 },
+ /* f8 */
+ { "psubb", { MX, EM } },
+ { "psubw", { MX, EM } },
+ { "psubd", { MX, EM } },
+ { "psubq", { MX, EM } },
+ { "paddb", { MX, EM } },
+ { "paddw", { MX, EM } },
+ { "paddd", { MX, EM } },
+ { "(bad)", { XX } },
+};
+
+static const unsigned char onebyte_has_modrm[256] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ /* 00 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 00 */
+ /* 10 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 10 */
+ /* 20 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 20 */
+ /* 30 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 30 */
+ /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40 */
+ /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */
+ /* 60 */ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0, /* 60 */
+ /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */
+ /* 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 80 */
+ /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 90 */
+ /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* a0 */
+ /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* b0 */
+ /* c0 */ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* c0 */
+ /* d0 */ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* d0 */
+ /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* e0 */
+ /* f0 */ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1 /* f0 */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+};
+
+static const unsigned char twobyte_has_modrm[256] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0f */
+ /* 10 */ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1, /* 1f */
+ /* 20 */ 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 2f */
+ /* 30 */ 0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, /* 3f */
+ /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */
+ /* 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 5f */
+ /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */
+ /* 70 */ 1,1,1,1,1,1,1,0,1,1,0,0,1,1,1,1, /* 7f */
+ /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+ /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */
+ /* a0 */ 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1, /* af */
+ /* b0 */ 1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1, /* bf */
+ /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */
+ /* d0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* df */
+ /* e0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* ef */
+ /* f0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 /* ff */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+};
+
+static const unsigned char twobyte_uses_DATA_prefix[256] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+ /* 10 */ 1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0, /* 1f */
+ /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, /* 2f */
+ /* 30 */ 0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, /* 3f */
+ /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+ /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */
+ /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1, /* 6f */
+ /* 70 */ 1,0,0,0,0,0,0,0,1,1,0,0,1,1,1,1, /* 7f */
+ /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+ /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+ /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+ /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+ /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+ /* d0 */ 1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */
+ /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */
+ /* f0 */ 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 /* ff */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+};
+
+static const unsigned char twobyte_uses_REPNZ_prefix[256] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+ /* 10 */ 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
+ /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, /* 2f */
+ /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+ /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+ /* 50 */ 0,1,0,0,0,0,0,0,1,1,1,0,1,1,1,1, /* 5f */
+ /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */
+ /* 70 */ 1,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0, /* 7f */
+ /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+ /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+ /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+ /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+ /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+ /* d0 */ 1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */
+ /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */
+ /* f0 */ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+};
+
+static const unsigned char twobyte_uses_REPZ_prefix[256] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+ /* 10 */ 1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0, /* 1f */
+ /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, /* 2f */
+ /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+ /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+ /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */
+ /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, /* 6f */
+ /* 70 */ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1, /* 7f */
+ /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+ /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+ /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+ /* b0 */ 0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0, /* bf */
+ /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+ /* d0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */
+ /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */
+ /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+};
+
+/* This is used to determine if opcode 0f 38 XX uses DATA prefix. */
+static const unsigned char threebyte_0x38_uses_DATA_prefix[256] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ /* 00 */ 1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0, /* 0f */
+ /* 10 */ 1,0,0,0,1,1,0,1,0,0,0,0,1,1,1,0, /* 1f */
+ /* 20 */ 1,1,1,1,1,1,0,0,1,1,1,1,0,0,0,0, /* 2f */
+ /* 30 */ 1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1, /* 3f */
+ /* 40 */ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+ /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */
+ /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */
+ /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */
+ /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+ /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+ /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+ /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+ /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+ /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */
+ /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */
+ /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+};
+
+/* This is used to determine if opcode 0f 38 XX uses REPNZ prefix. */
+static const unsigned char threebyte_0x38_uses_REPNZ_prefix[256] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+ /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
+ /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */
+ /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+ /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+ /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */
+ /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */
+ /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */
+ /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+ /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+ /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+ /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+ /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+ /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */
+ /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */
+ /* f0 */ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+};
+
+/* This is used to determine if opcode 0f 38 XX uses REPZ prefix. */
+static const unsigned char threebyte_0x38_uses_REPZ_prefix[256] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+ /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
+ /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */
+ /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+ /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+ /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */
+ /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */
+ /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */
+ /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+ /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+ /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+ /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+ /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+ /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */
+ /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */
+ /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+};
+
+/* This is used to determine if opcode 0f 3a XX uses DATA prefix. */
+static const unsigned char threebyte_0x3a_uses_DATA_prefix[256] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ /* 00 */ 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1, /* 0f */
+ /* 10 */ 0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* 1f */
+ /* 20 */ 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */
+ /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+ /* 40 */ 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+ /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */
+ /* 60 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */
+ /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */
+ /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+ /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+ /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+ /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+ /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+ /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */
+ /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */
+ /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+};
+
+/* This is used to determine if opcode 0f 3a XX uses REPNZ prefix. */
+static const unsigned char threebyte_0x3a_uses_REPNZ_prefix[256] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+ /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
+ /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */
+ /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+ /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+ /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */
+ /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */
+ /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */
+ /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+ /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+ /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+ /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+ /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+ /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */
+ /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */
+ /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+};
+
+/* This is used to determine if opcode 0f 3a XX uses REPZ prefix. */
+static const unsigned char threebyte_0x3a_uses_REPZ_prefix[256] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+ /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
+ /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */
+ /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+ /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+ /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */
+ /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */
+ /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */
+ /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+ /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+ /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+ /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+ /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+ /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */
+ /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */
+ /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+};
+
+static char obuf[100];
+static char *obufp;
+static char scratchbuf[100];
+static unsigned char *start_codep;
+static unsigned char *insn_codep;
+static unsigned char *codep;
+static disassemble_info *the_info;
+static struct
+ {
+ int mod;
+ int reg;
+ int rm;
+ }
+modrm;
+static unsigned char need_modrm;
+
+/* If we are accessing mod/rm/reg without need_modrm set, then the
+ values are stale. Hitting this abort likely indicates that you
+ need to update onebyte_has_modrm or twobyte_has_modrm. */
+#define MODRM_CHECK if (!need_modrm) abort ()
+
+static const char * const *names64;
+static const char * const *names32;
+static const char * const *names16;
+static const char * const *names8;
+static const char * const *names8rex;
+static const char * const *names_seg;
+static const char * const *index16;
+
+static const char * const intel_names64[] = {
+ "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+};
+static const char * const intel_names32[] = {
+ "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
+ "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
+};
+static const char * const intel_names16[] = {
+ "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
+ "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
+};
+static const char * const intel_names8[] = {
+ "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
+};
+static const char * const intel_names8rex[] = {
+ "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
+ "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
+};
+static const char * const intel_names_seg[] = {
+ "es", "cs", "ss", "ds", "fs", "gs", "?", "?",
+};
+static const char * const intel_index16[] = {
+ "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx"
+};
+
+static const char * const att_names64[] = {
+ "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
+ "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
+};
+static const char * const att_names32[] = {
+ "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
+ "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
+};
+static const char * const att_names16[] = {
+ "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
+ "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
+};
+static const char * const att_names8[] = {
+ "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
+};
+static const char * const att_names8rex[] = {
+ "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil",
+ "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
+};
+static const char * const att_names_seg[] = {
+ "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "%?", "%?",
+};
+static const char * const att_index16[] = {
+ "%bx,%si", "%bx,%di", "%bp,%si", "%bp,%di", "%si", "%di", "%bp", "%bx"
+};
+
+static const struct dis386 grps[][8] = {
+ /* GRP1a */
+ {
+ { "popU", { stackEv } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ },
+ /* GRP1b */
+ {
+ { "addA", { Eb, Ib } },
+ { "orA", { Eb, Ib } },
+ { "adcA", { Eb, Ib } },
+ { "sbbA", { Eb, Ib } },
+ { "andA", { Eb, Ib } },
+ { "subA", { Eb, Ib } },
+ { "xorA", { Eb, Ib } },
+ { "cmpA", { Eb, Ib } },
+ },
+ /* GRP1S */
+ {
+ { "addQ", { Ev, Iv } },
+ { "orQ", { Ev, Iv } },
+ { "adcQ", { Ev, Iv } },
+ { "sbbQ", { Ev, Iv } },
+ { "andQ", { Ev, Iv } },
+ { "subQ", { Ev, Iv } },
+ { "xorQ", { Ev, Iv } },
+ { "cmpQ", { Ev, Iv } },
+ },
+ /* GRP1Ss */
+ {
+ { "addQ", { Ev, sIb } },
+ { "orQ", { Ev, sIb } },
+ { "adcQ", { Ev, sIb } },
+ { "sbbQ", { Ev, sIb } },
+ { "andQ", { Ev, sIb } },
+ { "subQ", { Ev, sIb } },
+ { "xorQ", { Ev, sIb } },
+ { "cmpQ", { Ev, sIb } },
+ },
+ /* GRP2b */
+ {
+ { "rolA", { Eb, Ib } },
+ { "rorA", { Eb, Ib } },
+ { "rclA", { Eb, Ib } },
+ { "rcrA", { Eb, Ib } },
+ { "shlA", { Eb, Ib } },
+ { "shrA", { Eb, Ib } },
+ { "(bad)", { XX } },
+ { "sarA", { Eb, Ib } },
+ },
+ /* GRP2S */
+ {
+ { "rolQ", { Ev, Ib } },
+ { "rorQ", { Ev, Ib } },
+ { "rclQ", { Ev, Ib } },
+ { "rcrQ", { Ev, Ib } },
+ { "shlQ", { Ev, Ib } },
+ { "shrQ", { Ev, Ib } },
+ { "(bad)", { XX } },
+ { "sarQ", { Ev, Ib } },
+ },
+ /* GRP2b_one */
+ {
+ { "rolA", { Eb, I1 } },
+ { "rorA", { Eb, I1 } },
+ { "rclA", { Eb, I1 } },
+ { "rcrA", { Eb, I1 } },
+ { "shlA", { Eb, I1 } },
+ { "shrA", { Eb, I1 } },
+ { "(bad)", { XX } },
+ { "sarA", { Eb, I1 } },
+ },
+ /* GRP2S_one */
+ {
+ { "rolQ", { Ev, I1 } },
+ { "rorQ", { Ev, I1 } },
+ { "rclQ", { Ev, I1 } },
+ { "rcrQ", { Ev, I1 } },
+ { "shlQ", { Ev, I1 } },
+ { "shrQ", { Ev, I1 } },
+ { "(bad)", { XX } },
+ { "sarQ", { Ev, I1 } },
+ },
+ /* GRP2b_cl */
+ {
+ { "rolA", { Eb, CL } },
+ { "rorA", { Eb, CL } },
+ { "rclA", { Eb, CL } },
+ { "rcrA", { Eb, CL } },
+ { "shlA", { Eb, CL } },
+ { "shrA", { Eb, CL } },
+ { "(bad)", { XX } },
+ { "sarA", { Eb, CL } },
+ },
+ /* GRP2S_cl */
+ {
+ { "rolQ", { Ev, CL } },
+ { "rorQ", { Ev, CL } },
+ { "rclQ", { Ev, CL } },
+ { "rcrQ", { Ev, CL } },
+ { "shlQ", { Ev, CL } },
+ { "shrQ", { Ev, CL } },
+ { "(bad)", { XX } },
+ { "sarQ", { Ev, CL } },
+ },
+ /* GRP3b */
+ {
+ { "testA", { Eb, Ib } },
+ { "(bad)", { Eb } },
+ { "notA", { Eb } },
+ { "negA", { Eb } },
+ { "mulA", { Eb } }, /* Don't print the implicit %al register, */
+ { "imulA", { Eb } }, /* to distinguish these opcodes from other */
+ { "divA", { Eb } }, /* mul/imul opcodes. Do the same for div */
+ { "idivA", { Eb } }, /* and idiv for consistency. */
+ },
+ /* GRP3S */
+ {
+ { "testQ", { Ev, Iv } },
+ { "(bad)", { XX } },
+ { "notQ", { Ev } },
+ { "negQ", { Ev } },
+ { "mulQ", { Ev } }, /* Don't print the implicit register. */
+ { "imulQ", { Ev } },
+ { "divQ", { Ev } },
+ { "idivQ", { Ev } },
+ },
+ /* GRP4 */
+ {
+ { "incA", { Eb } },
+ { "decA", { Eb } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ },
+ /* GRP5 */
+ {
+ { "incQ", { Ev } },
+ { "decQ", { Ev } },
+ { "callT", { indirEv } },
+ { "JcallT", { indirEp } },
+ { "jmpT", { indirEv } },
+ { "JjmpT", { indirEp } },
+ { "pushU", { stackEv } },
+ { "(bad)", { XX } },
+ },
+ /* GRP6 */
+ {
+ { "sldtD", { Sv } },
+ { "strD", { Sv } },
+ { "lldt", { Ew } },
+ { "ltr", { Ew } },
+ { "verr", { Ew } },
+ { "verw", { Ew } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ },
+ /* GRP7 */
+ {
+ { "sgdt{Q|IQ||}", { { VMX_Fixup, 0 } } },
+ { "sidt{Q|IQ||}", { { PNI_Fixup, 0 } } },
+ { "lgdt{Q|Q||}", { M } },
+ { "lidt{Q|Q||}", { { SVME_Fixup, 0 } } },
+ { "smswD", { Sv } },
+ { "(bad)", { XX } },
+ { "lmsw", { Ew } },
+ { "invlpg", { { INVLPG_Fixup, w_mode } } },
+ },
+ /* GRP8 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "btQ", { Ev, Ib } },
+ { "btsQ", { Ev, Ib } },
+ { "btrQ", { Ev, Ib } },
+ { "btcQ", { Ev, Ib } },
+ },
+ /* GRP9 */
+ {
+ { "(bad)", { XX } },
+ { "cmpxchg8b", { { CMPXCHG8B_Fixup, q_mode } } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "", { VM } }, /* See OP_VMX. */
+ { "vmptrst", { Mq } },
+ },
+ /* GRP11_C6 */
+ {
+ { "movA", { Eb, Ib } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ },
+ /* GRP11_C7 */
+ {
+ { "movQ", { Ev, Iv } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ },
+ /* GRP12 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "psrlw", { MS, Ib } },
+ { "(bad)", { XX } },
+ { "psraw", { MS, Ib } },
+ { "(bad)", { XX } },
+ { "psllw", { MS, Ib } },
+ { "(bad)", { XX } },
+ },
+ /* GRP13 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "psrld", { MS, Ib } },
+ { "(bad)", { XX } },
+ { "psrad", { MS, Ib } },
+ { "(bad)", { XX } },
+ { "pslld", { MS, Ib } },
+ { "(bad)", { XX } },
+ },
+ /* GRP14 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "psrlq", { MS, Ib } },
+ { "psrldq", { MS, Ib } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "psllq", { MS, Ib } },
+ { "pslldq", { MS, Ib } },
+ },
+ /* GRP15 */
+ {
+ { "fxsave", { Ev } },
+ { "fxrstor", { Ev } },
+ { "ldmxcsr", { Ev } },
+ { "stmxcsr", { Ev } },
+ { "(bad)", { XX } },
+ { "lfence", { { OP_0fae, 0 } } },
+ { "mfence", { { OP_0fae, 0 } } },
+ { "clflush", { { OP_0fae, 0 } } },
+ },
+ /* GRP16 */
+ {
+ { "prefetchnta", { Ev } },
+ { "prefetcht0", { Ev } },
+ { "prefetcht1", { Ev } },
+ { "prefetcht2", { Ev } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ },
+ /* GRPAMD */
+ {
+ { "prefetch", { Eb } },
+ { "prefetchw", { Eb } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ },
+ /* GRPPADLCK1 */
+ {
+ { "xstore-rng", { { OP_0f07, 0 } } },
+ { "xcrypt-ecb", { { OP_0f07, 0 } } },
+ { "xcrypt-cbc", { { OP_0f07, 0 } } },
+ { "xcrypt-ctr", { { OP_0f07, 0 } } },
+ { "xcrypt-cfb", { { OP_0f07, 0 } } },
+ { "xcrypt-ofb", { { OP_0f07, 0 } } },
+ { "(bad)", { { OP_0f07, 0 } } },
+ { "(bad)", { { OP_0f07, 0 } } },
+ },
+ /* GRPPADLCK2 */
+ {
+ { "montmul", { { OP_0f07, 0 } } },
+ { "xsha1", { { OP_0f07, 0 } } },
+ { "xsha256", { { OP_0f07, 0 } } },
+ { "(bad)", { { OP_0f07, 0 } } },
+ { "(bad)", { { OP_0f07, 0 } } },
+ { "(bad)", { { OP_0f07, 0 } } },
+ { "(bad)", { { OP_0f07, 0 } } },
+ { "(bad)", { { OP_0f07, 0 } } },
+ }
+};
+
+static const struct dis386 prefix_user_table[][4] = {
+ /* PREGRP0 */
+ {
+ { "addps", { XM, EXx } },
+ { "addss", { XM, EXd } },
+ { "addpd", { XM, EXx } },
+ { "addsd", { XM, EXq } },
+ },
+ /* PREGRP1 */
+ {
+ { "", { XM, EXx, OPSIMD } }, /* See OP_SIMD_SUFFIX. */
+ { "", { XM, EXx, OPSIMD } },
+ { "", { XM, EXx, OPSIMD } },
+ { "", { XM, EXx, OPSIMD } },
+ },
+ /* PREGRP2 */
+ {
+ { "cvtpi2ps", { XM, EMC } },
+ { "cvtsi2ssY", { XM, Ev } },
+ { "cvtpi2pd", { XM, EMC } },
+ { "cvtsi2sdY", { XM, Ev } },
+ },
+ /* PREGRP3 */
+ {
+ { "cvtps2pi", { MXC, EXx } },
+ { "cvtss2siY", { Gv, EXx } },
+ { "cvtpd2pi", { MXC, EXx } },
+ { "cvtsd2siY", { Gv, EXx } },
+ },
+ /* PREGRP4 */
+ {
+ { "cvttps2pi", { MXC, EXx } },
+ { "cvttss2siY", { Gv, EXx } },
+ { "cvttpd2pi", { MXC, EXx } },
+ { "cvttsd2siY", { Gv, EXx } },
+ },
+ /* PREGRP5 */
+ {
+ { "divps", { XM, EXx } },
+ { "divss", { XM, EXx } },
+ { "divpd", { XM, EXx } },
+ { "divsd", { XM, EXx } },
+ },
+ /* PREGRP6 */
+ {
+ { "maxps", { XM, EXx } },
+ { "maxss", { XM, EXx } },
+ { "maxpd", { XM, EXx } },
+ { "maxsd", { XM, EXx } },
+ },
+ /* PREGRP7 */
+ {
+ { "minps", { XM, EXx } },
+ { "minss", { XM, EXx } },
+ { "minpd", { XM, EXx } },
+ { "minsd", { XM, EXx } },
+ },
+ /* PREGRP8 */
+ {
+ { "movups", { XM, EXx } },
+ { "movss", { XM, EXx } },
+ { "movupd", { XM, EXx } },
+ { "movsd", { XM, EXx } },
+ },
+ /* PREGRP9 */
+ {
+ { "movups", { EXx, XM } },
+ { "movss", { EXx, XM } },
+ { "movupd", { EXx, XM } },
+ { "movsd", { EXx, XM } },
+ },
+ /* PREGRP10 */
+ {
+ { "mulps", { XM, EXx } },
+ { "mulss", { XM, EXx } },
+ { "mulpd", { XM, EXx } },
+ { "mulsd", { XM, EXx } },
+ },
+ /* PREGRP11 */
+ {
+ { "rcpps", { XM, EXx } },
+ { "rcpss", { XM, EXx } },
+ { "(bad)", { XM, EXx } },
+ { "(bad)", { XM, EXx } },
+ },
+ /* PREGRP12 */
+ {
+ { "rsqrtps",{ XM, EXx } },
+ { "rsqrtss",{ XM, EXx } },
+ { "(bad)", { XM, EXx } },
+ { "(bad)", { XM, EXx } },
+ },
+ /* PREGRP13 */
+ {
+ { "sqrtps", { XM, EXx } },
+ { "sqrtss", { XM, EXx } },
+ { "sqrtpd", { XM, EXx } },
+ { "sqrtsd", { XM, EXx } },
+ },
+ /* PREGRP14 */
+ {
+ { "subps", { XM, EXx } },
+ { "subss", { XM, EXx } },
+ { "subpd", { XM, EXx } },
+ { "subsd", { XM, EXx } },
+ },
+ /* PREGRP15 */
+ {
+ { "(bad)", { XM, EXx } },
+ { "cvtdq2pd", { XM, EXq } },
+ { "cvttpd2dq", { XM, EXx } },
+ { "cvtpd2dq", { XM, EXx } },
+ },
+ /* PREGRP16 */
+ {
+ { "cvtdq2ps", { XM, EXx } },
+ { "cvttps2dq", { XM, EXx } },
+ { "cvtps2dq", { XM, EXx } },
+ { "(bad)", { XM, EXx } },
+ },
+ /* PREGRP17 */
+ {
+ { "cvtps2pd", { XM, EXq } },
+ { "cvtss2sd", { XM, EXx } },
+ { "cvtpd2ps", { XM, EXx } },
+ { "cvtsd2ss", { XM, EXx } },
+ },
+ /* PREGRP18 */
+ {
+ { "maskmovq", { MX, MS } },
+ { "(bad)", { XM, EXx } },
+ { "maskmovdqu", { XM, XS } },
+ { "(bad)", { XM, EXx } },
+ },
+ /* PREGRP19 */
+ {
+ { "movq", { MX, EM } },
+ { "movdqu", { XM, EXx } },
+ { "movdqa", { XM, EXx } },
+ { "(bad)", { XM, EXx } },
+ },
+ /* PREGRP20 */
+ {
+ { "movq", { EM, MX } },
+ { "movdqu", { EXx, XM } },
+ { "movdqa", { EXx, XM } },
+ { "(bad)", { EXx, XM } },
+ },
+ /* PREGRP21 */
+ {
+ { "(bad)", { EXx, XM } },
+ { "movq2dq",{ XM, MS } },
+ { "movq", { EXx, XM } },
+ { "movdq2q",{ MX, XS } },
+ },
+ /* PREGRP22 */
+ {
+ { "pshufw", { MX, EM, Ib } },
+ { "pshufhw",{ XM, EXx, Ib } },
+ { "pshufd", { XM, EXx, Ib } },
+ { "pshuflw",{ XM, EXx, Ib } },
+ },
+ /* PREGRP23 */
+ {
+ { "movd", { Edq, MX } },
+ { "movq", { XM, EXx } },
+ { "movd", { Edq, XM } },
+ { "(bad)", { Ed, XM } },
+ },
+ /* PREGRP24 */
+ {
+ { "(bad)", { MX, EXx } },
+ { "(bad)", { XM, EXx } },
+ { "punpckhqdq", { XM, EXx } },
+ { "(bad)", { XM, EXx } },
+ },
+ /* PREGRP25 */
+ {
+ { "movntq", { EM, MX } },
+ { "(bad)", { EM, XM } },
+ { "movntdq",{ EM, XM } },
+ { "(bad)", { EM, XM } },
+ },
+ /* PREGRP26 */
+ {
+ { "(bad)", { MX, EXx } },
+ { "(bad)", { XM, EXx } },
+ { "punpcklqdq", { XM, EXx } },
+ { "(bad)", { XM, EXx } },
+ },
+ /* PREGRP27 */
+ {
+ { "(bad)", { MX, EXx } },
+ { "(bad)", { XM, EXx } },
+ { "addsubpd", { XM, EXx } },
+ { "addsubps", { XM, EXx } },
+ },
+ /* PREGRP28 */
+ {
+ { "(bad)", { MX, EXx } },
+ { "(bad)", { XM, EXx } },
+ { "haddpd", { XM, EXx } },
+ { "haddps", { XM, EXx } },
+ },
+ /* PREGRP29 */
+ {
+ { "(bad)", { MX, EXx } },
+ { "(bad)", { XM, EXx } },
+ { "hsubpd", { XM, EXx } },
+ { "hsubps", { XM, EXx } },
+ },
+ /* PREGRP30 */
+ {
+ { "movlpX", { XM, EXq, { SIMD_Fixup, 'h' } } }, /* really only 2 operands */
+ { "movsldup", { XM, EXx } },
+ { "movlpd", { XM, EXq } },
+ { "movddup", { XM, EXq } },
+ },
+ /* PREGRP31 */
+ {
+ { "movhpX", { XM, EXq, { SIMD_Fixup, 'l' } } },
+ { "movshdup", { XM, EXx } },
+ { "movhpd", { XM, EXq } },
+ { "(bad)", { XM, EXq } },
+ },
+ /* PREGRP32 */
+ {
+ { "(bad)", { XM, EXx } },
+ { "(bad)", { XM, EXx } },
+ { "(bad)", { XM, EXx } },
+ { "lddqu", { XM, M } },
+ },
+ /* PREGRP33 */
+ {
+ {"movntps", { Ev, XM } },
+ {"movntss", { Ev, XM } },
+ {"movntpd", { Ev, XM } },
+ {"movntsd", { Ev, XM } },
+ },
+
+ /* PREGRP34 */
+ {
+ {"vmread", { Em, Gm } },
+ {"(bad)", { XX } },
+ {"extrq", { XS, Ib, Ib } },
+ {"insertq", { XM, XS, Ib, Ib } },
+ },
+
+ /* PREGRP35 */
+ {
+ {"vmwrite", { Gm, Em } },
+ {"(bad)", { XX } },
+ {"extrq", { XM, XS } },
+ {"insertq", { XM, XS } },
+ },
+
+ /* PREGRP36 */
+ {
+ { "bsrS", { Gv, Ev } },
+ { "lzcntS", { Gv, Ev } },
+ { "bsrS", { Gv, Ev } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP37 */
+ {
+ { "(bad)", { XX } },
+ { "popcntS", { Gv, Ev } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP38 */
+ {
+ { "xchgS", { { NOP_Fixup1, eAX_reg }, { NOP_Fixup2, eAX_reg } } },
+ { "pause", { XX } },
+ { "xchgS", { { NOP_Fixup1, eAX_reg }, { NOP_Fixup2, eAX_reg } } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP39 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pblendvb", {XM, EXx, XMM0 } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP40 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "blendvps", {XM, EXx, XMM0 } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP41 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "blendvpd", { XM, EXx, XMM0 } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP42 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "ptest", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP43 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmovsxbw", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP44 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmovsxbd", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP45 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmovsxbq", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP46 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmovsxwd", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP47 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmovsxwq", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP48 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmovsxdq", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP49 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmuldq", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP50 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pcmpeqq", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP51 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "movntdqa", { XM, EM } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP52 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "packusdw", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP53 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmovzxbw", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP54 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmovzxbd", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP55 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmovzxbq", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP56 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmovzxwd", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP57 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmovzxwq", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP58 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmovzxdq", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP59 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pminsb", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP60 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pminsd", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP61 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pminuw", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP62 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pminud", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP63 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmaxsb", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP64 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmaxsd", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP65 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmaxuw", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP66 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmaxud", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP67 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pmulld", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP68 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "phminposuw", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP69 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "roundps", { XM, EXx, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP70 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "roundpd", { XM, EXx, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP71 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "roundss", { XM, EXx, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP72 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "roundsd", { XM, EXx, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP73 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "blendps", { XM, EXx, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP74 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "blendpd", { XM, EXx, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP75 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pblendw", { XM, EXx, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP76 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pextrb", { Edqb, XM, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP77 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pextrw", { Edqw, XM, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP78 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pextrK", { Edq, XM, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP79 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "extractps", { Edqd, XM, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP80 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pinsrb", { XM, Edqb, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP81 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "insertps", { XM, EXx, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP82 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pinsrK", { XM, Edq, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP83 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "dpps", { XM, EXx, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP84 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "dppd", { XM, EXx, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP85 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "mpsadbw", { XM, EXx, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP86 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pcmpgtq", { XM, EXx } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP87 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "crc32", { Gdq, { CRC32_Fixup, b_mode } } },
+ },
+
+ /* PREGRP88 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "crc32", { Gdq, { CRC32_Fixup, v_mode } } },
+ },
+
+ /* PREGRP89 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pcmpestrm", { XM, EXx, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP90 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pcmpestri", { XM, EXx, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP91 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pcmpistrm", { XM, EXx, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP92 */
+ {
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pcmpistri", { XM, EXx, Ib } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP93 */
+ {
+ { "ucomiss",{ XM, EXd } },
+ { "(bad)", { XX } },
+ { "ucomisd",{ XM, EXq } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP94 */
+ {
+ { "comiss", { XM, EXd } },
+ { "(bad)", { XX } },
+ { "comisd", { XM, EXq } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP95 */
+ {
+ { "punpcklbw",{ MX, EMd } },
+ { "(bad)", { XX } },
+ { "punpcklbw",{ MX, EMq } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP96 */
+ {
+ { "punpcklwd",{ MX, EMd } },
+ { "(bad)", { XX } },
+ { "punpcklwd",{ MX, EMq } },
+ { "(bad)", { XX } },
+ },
+
+ /* PREGRP97 */
+ {
+ { "punpckldq",{ MX, EMd } },
+ { "(bad)", { XX } },
+ { "punpckldq",{ MX, EMq } },
+ { "(bad)", { XX } },
+ },
+};
+
+static const struct dis386 x86_64_table[][2] = {
+ {
+ { "pusha{P|}", { XX } },
+ { "(bad)", { XX } },
+ },
+ {
+ { "popa{P|}", { XX } },
+ { "(bad)", { XX } },
+ },
+ {
+ { "bound{S|}", { Gv, Ma } },
+ { "(bad)", { XX } },
+ },
+ {
+ { "arpl", { Ew, Gw } },
+ { "movs{||lq|xd}", { Gv, Ed } },
+ },
+};
+
+static const struct dis386 three_byte_table[][256] = {
+ /* THREE_BYTE_0 */
+ {
+ /* 00 */
+ { "pshufb", { MX, EM } },
+ { "phaddw", { MX, EM } },
+ { "phaddd", { MX, EM } },
+ { "phaddsw", { MX, EM } },
+ { "pmaddubsw", { MX, EM } },
+ { "phsubw", { MX, EM } },
+ { "phsubd", { MX, EM } },
+ { "phsubsw", { MX, EM } },
+ /* 08 */
+ { "psignb", { MX, EM } },
+ { "psignw", { MX, EM } },
+ { "psignd", { MX, EM } },
+ { "pmulhrsw", { MX, EM } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 10 */
+ { PREGRP39 },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { PREGRP40 },
+ { PREGRP41 },
+ { "(bad)", { XX } },
+ { PREGRP42 },
+ /* 18 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "pabsb", { MX, EM } },
+ { "pabsw", { MX, EM } },
+ { "pabsd", { MX, EM } },
+ { "(bad)", { XX } },
+ /* 20 */
+ { PREGRP43 },
+ { PREGRP44 },
+ { PREGRP45 },
+ { PREGRP46 },
+ { PREGRP47 },
+ { PREGRP48 },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 28 */
+ { PREGRP49 },
+ { PREGRP50 },
+ { PREGRP51 },
+ { PREGRP52 },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 30 */
+ { PREGRP53 },
+ { PREGRP54 },
+ { PREGRP55 },
+ { PREGRP56 },
+ { PREGRP57 },
+ { PREGRP58 },
+ { "(bad)", { XX } },
+ { PREGRP86 },
+ /* 38 */
+ { PREGRP59 },
+ { PREGRP60 },
+ { PREGRP61 },
+ { PREGRP62 },
+ { PREGRP63 },
+ { PREGRP64 },
+ { PREGRP65 },
+ { PREGRP66 },
+ /* 40 */
+ { PREGRP67 },
+ { PREGRP68 },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 48 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 50 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 58 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 60 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 68 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 70 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 78 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 80 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 88 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 90 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 98 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* a0 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* a8 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* b0 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* b8 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* c0 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* c8 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* d0 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* d8 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* e0 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* e8 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* f0 */
+ { PREGRP87 },
+ { PREGRP88 },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* f8 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ },
+ /* THREE_BYTE_1 */
+ {
+ /* 00 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 08 */
+ { PREGRP69 },
+ { PREGRP70 },
+ { PREGRP71 },
+ { PREGRP72 },
+ { PREGRP73 },
+ { PREGRP74 },
+ { PREGRP75 },
+ { "palignr", { MX, EM, Ib } },
+ /* 10 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { PREGRP76 },
+ { PREGRP77 },
+ { PREGRP78 },
+ { PREGRP79 },
+ /* 18 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 20 */
+ { PREGRP80 },
+ { PREGRP81 },
+ { PREGRP82 },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 28 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 30 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 38 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 40 */
+ { PREGRP83 },
+ { PREGRP84 },
+ { PREGRP85 },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 48 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 50 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 58 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 60 */
+ { PREGRP89 },
+ { PREGRP90 },
+ { PREGRP91 },
+ { PREGRP92 },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 68 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 70 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 78 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 80 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 88 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 90 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* 98 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* a0 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* a8 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* b0 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* b8 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* c0 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* c8 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* d0 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* d8 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* e0 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* e8 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* f0 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ /* f8 */
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ }
+};
+
+#define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>")
+
+static void
+ckprefix (void)
+{
+ int newrex;
+ rex = 0;
+ prefixes = 0;
+ used_prefixes = 0;
+ rex_used = 0;
+ while (1)
+ {
+ fetch_data(the_info, codep + 1);
+ newrex = 0;
+ switch (*codep)
+ {
+ /* REX prefixes family. */
+ case 0x40:
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ case 0x45:
+ case 0x46:
+ case 0x47:
+ case 0x48:
+ case 0x49:
+ case 0x4a:
+ case 0x4b:
+ case 0x4c:
+ case 0x4d:
+ case 0x4e:
+ case 0x4f:
+ if (address_mode == mode_64bit)
+ newrex = *codep;
+ else
+ return;
+ break;
+ case 0xf3:
+ prefixes |= PREFIX_REPZ;
+ break;
+ case 0xf2:
+ prefixes |= PREFIX_REPNZ;
+ break;
+ case 0xf0:
+ prefixes |= PREFIX_LOCK;
+ break;
+ case 0x2e:
+ prefixes |= PREFIX_CS;
+ break;
+ case 0x36:
+ prefixes |= PREFIX_SS;
+ break;
+ case 0x3e:
+ prefixes |= PREFIX_DS;
+ break;
+ case 0x26:
+ prefixes |= PREFIX_ES;
+ break;
+ case 0x64:
+ prefixes |= PREFIX_FS;
+ break;
+ case 0x65:
+ prefixes |= PREFIX_GS;
+ break;
+ case 0x66:
+ prefixes |= PREFIX_DATA;
+ break;
+ case 0x67:
+ prefixes |= PREFIX_ADDR;
+ break;
+ case FWAIT_OPCODE:
+ /* fwait is really an instruction. If there are prefixes
+ before the fwait, they belong to the fwait, *not* to the
+ following instruction. */
+ if (prefixes || rex)
+ {
+ prefixes |= PREFIX_FWAIT;
+ codep++;
+ return;
+ }
+ prefixes = PREFIX_FWAIT;
+ break;
+ default:
+ return;
+ }
+ /* Rex is ignored when followed by another prefix. */
+ if (rex)
+ {
+ rex_used = rex;
+ return;
+ }
+ rex = newrex;
+ codep++;
+ }
+}
+
+/* Return the name of the prefix byte PREF, or NULL if PREF is not a
+ prefix byte. */
+
+static const char *
+prefix_name (int pref, int sizeflag)
+{
+ static const char * const rexes [16] =
+ {
+ "rex", /* 0x40 */
+ "rex.B", /* 0x41 */
+ "rex.X", /* 0x42 */
+ "rex.XB", /* 0x43 */
+ "rex.R", /* 0x44 */
+ "rex.RB", /* 0x45 */
+ "rex.RX", /* 0x46 */
+ "rex.RXB", /* 0x47 */
+ "rex.W", /* 0x48 */
+ "rex.WB", /* 0x49 */
+ "rex.WX", /* 0x4a */
+ "rex.WXB", /* 0x4b */
+ "rex.WR", /* 0x4c */
+ "rex.WRB", /* 0x4d */
+ "rex.WRX", /* 0x4e */
+ "rex.WRXB", /* 0x4f */
+ };
+
+ switch (pref)
+ {
+ /* REX prefixes family. */
+ case 0x40:
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ case 0x45:
+ case 0x46:
+ case 0x47:
+ case 0x48:
+ case 0x49:
+ case 0x4a:
+ case 0x4b:
+ case 0x4c:
+ case 0x4d:
+ case 0x4e:
+ case 0x4f:
+ return rexes [pref - 0x40];
+ case 0xf3:
+ return "repz";
+ case 0xf2:
+ return "repnz";
+ case 0xf0:
+ return "lock";
+ case 0x2e:
+ return "cs";
+ case 0x36:
+ return "ss";
+ case 0x3e:
+ return "ds";
+ case 0x26:
+ return "es";
+ case 0x64:
+ return "fs";
+ case 0x65:
+ return "gs";
+ case 0x66:
+ return (sizeflag & DFLAG) ? "data16" : "data32";
+ case 0x67:
+ if (address_mode == mode_64bit)
+ return (sizeflag & AFLAG) ? "addr32" : "addr64";
+ else
+ return (sizeflag & AFLAG) ? "addr16" : "addr32";
+ case FWAIT_OPCODE:
+ return "fwait";
+ default:
+ return NULL;
+ }
+}
+
+static char op_out[MAX_OPERANDS][100];
+static int op_ad, op_index[MAX_OPERANDS];
+static int two_source_ops;
+static bfd_vma op_address[MAX_OPERANDS];
+static bfd_vma op_riprel[MAX_OPERANDS];
+static bfd_vma start_pc;
+
+/*
+ * On the 386's of 1988, the maximum length of an instruction is 15 bytes.
+ * (see topic "Redundant prefixes" in the "Differences from 8086"
+ * section of the "Virtual 8086 Mode" chapter.)
+ * 'pc' should be the address of this instruction, it will
+ * be used to print the target address if this is a relative jump or call
+ * The function returns the length of this instruction in bytes.
+ */
+
+static char intel_syntax;
+static char open_char;
+static char close_char;
+static char separator_char;
+static char scale_char;
+
+int
+print_insn_i386 (bfd_vma pc, disassemble_info *info)
+{
+ intel_syntax = -1;
+
+ return print_insn (pc, info);
+}
+
+static int
+print_insn (bfd_vma pc, disassemble_info *info)
+{
+ const struct dis386 *dp;
+ int i;
+ char *op_txt[MAX_OPERANDS];
+ int needcomma;
+ unsigned char uses_DATA_prefix, uses_LOCK_prefix;
+ unsigned char uses_REPNZ_prefix, uses_REPZ_prefix;
+ int sizeflag;
+ const char *p;
+ struct dis_private priv;
+ unsigned char op;
+
+ if (info->mach == bfd_mach_x86_64_intel_syntax
+ || info->mach == bfd_mach_x86_64)
+ address_mode = mode_64bit;
+ else
+ address_mode = mode_32bit;
+
+ if (intel_syntax == (char) -1)
+ intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax
+ || info->mach == bfd_mach_x86_64_intel_syntax);
+
+ if (info->mach == bfd_mach_i386_i386
+ || info->mach == bfd_mach_x86_64
+ || info->mach == bfd_mach_i386_i386_intel_syntax
+ || info->mach == bfd_mach_x86_64_intel_syntax)
+ priv.orig_sizeflag = AFLAG | DFLAG;
+ else if (info->mach == bfd_mach_i386_i8086)
+ priv.orig_sizeflag = 0;
+ else
+ abort ();
+
+ for (p = info->disassembler_options; p != NULL; )
+ {
+ if (strncmp (p, "x86-64", 6) == 0)
+ {
+ address_mode = mode_64bit;
+ priv.orig_sizeflag = AFLAG | DFLAG;
+ }
+ else if (strncmp (p, "i386", 4) == 0)
+ {
+ address_mode = mode_32bit;
+ priv.orig_sizeflag = AFLAG | DFLAG;
+ }
+ else if (strncmp (p, "i8086", 5) == 0)
+ {
+ address_mode = mode_16bit;
+ priv.orig_sizeflag = 0;
+ }
+ else if (strncmp (p, "intel", 5) == 0)
+ {
+ intel_syntax = 1;
+ }
+ else if (strncmp (p, "att", 3) == 0)
+ {
+ intel_syntax = 0;
+ }
+ else if (strncmp (p, "addr", 4) == 0)
+ {
+ if (address_mode == mode_64bit)
+ {
+ if (p[4] == '3' && p[5] == '2')
+ priv.orig_sizeflag &= ~AFLAG;
+ else if (p[4] == '6' && p[5] == '4')
+ priv.orig_sizeflag |= AFLAG;
+ }
+ else
+ {
+ if (p[4] == '1' && p[5] == '6')
+ priv.orig_sizeflag &= ~AFLAG;
+ else if (p[4] == '3' && p[5] == '2')
+ priv.orig_sizeflag |= AFLAG;
+ }
+ }
+ else if (strncmp (p, "data", 4) == 0)
+ {
+ if (p[4] == '1' && p[5] == '6')
+ priv.orig_sizeflag &= ~DFLAG;
+ else if (p[4] == '3' && p[5] == '2')
+ priv.orig_sizeflag |= DFLAG;
+ }
+ else if (strncmp (p, "suffix", 6) == 0)
+ priv.orig_sizeflag |= SUFFIX_ALWAYS;
+
+ p = strchr (p, ',');
+ if (p != NULL)
+ p++;
+ }
+
+ if (intel_syntax)
+ {
+ names64 = intel_names64;
+ names32 = intel_names32;
+ names16 = intel_names16;
+ names8 = intel_names8;
+ names8rex = intel_names8rex;
+ names_seg = intel_names_seg;
+ index16 = intel_index16;
+ open_char = '[';
+ close_char = ']';
+ separator_char = '+';
+ scale_char = '*';
+ }
+ else
+ {
+ names64 = att_names64;
+ names32 = att_names32;
+ names16 = att_names16;
+ names8 = att_names8;
+ names8rex = att_names8rex;
+ names_seg = att_names_seg;
+ index16 = att_index16;
+ open_char = '(';
+ close_char = ')';
+ separator_char = ',';
+ scale_char = ',';
+ }
+
+ /* The output looks better if we put 7 bytes on a line, since that
+ puts most long word instructions on a single line. */
+ info->bytes_per_line = 7;
+
+ info->private_data = &priv;
+ priv.max_fetched = priv.the_buffer;
+ priv.insn_start = pc;
+
+ obuf[0] = 0;
+ for (i = 0; i < MAX_OPERANDS; ++i)
+ {
+ op_out[i][0] = 0;
+ op_index[i] = -1;
+ }
+
+ the_info = info;
+ start_pc = pc;
+ start_codep = priv.the_buffer;
+ codep = priv.the_buffer;
+
+ if (setjmp (priv.bailout) != 0)
+ {
+ const char *name;
+
+ /* Getting here means we tried for data but didn't get it. That
+ means we have an incomplete instruction of some sort. Just
+ print the first byte as a prefix or a .byte pseudo-op. */
+ if (codep > priv.the_buffer)
+ {
+ name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
+ if (name != NULL)
+ (*info->fprintf_func) (info->stream, "%s", name);
+ else
+ {
+ /* Just print the first byte as a .byte instruction. */
+ (*info->fprintf_func) (info->stream, ".byte 0x%x",
+ (unsigned int) priv.the_buffer[0]);
+ }
+
+ return 1;
+ }
+
+ return -1;
+ }
+
+ obufp = obuf;
+ ckprefix ();
+
+ insn_codep = codep;
+ sizeflag = priv.orig_sizeflag;
+
+ fetch_data(info, codep + 1);
+ two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
+
+ if (((prefixes & PREFIX_FWAIT)
+ && ((*codep < 0xd8) || (*codep > 0xdf)))
+ || (rex && rex_used))
+ {
+ const char *name;
+
+ /* fwait not followed by floating point instruction, or rex followed
+ by other prefixes. Print the first prefix. */
+ name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
+ if (name == NULL)
+ name = INTERNAL_DISASSEMBLER_ERROR;
+ (*info->fprintf_func) (info->stream, "%s", name);
+ return 1;
+ }
+
+ op = 0;
+ if (*codep == 0x0f)
+ {
+ unsigned char threebyte;
+ fetch_data(info, codep + 2);
+ threebyte = *++codep;
+ dp = &dis386_twobyte[threebyte];
+ need_modrm = twobyte_has_modrm[*codep];
+ uses_DATA_prefix = twobyte_uses_DATA_prefix[*codep];
+ uses_REPNZ_prefix = twobyte_uses_REPNZ_prefix[*codep];
+ uses_REPZ_prefix = twobyte_uses_REPZ_prefix[*codep];
+ uses_LOCK_prefix = (*codep & ~0x02) == 0x20;
+ codep++;
+ if (dp->name == NULL && dp->op[0].bytemode == IS_3BYTE_OPCODE)
+ {
+ fetch_data(info, codep + 2);
+ op = *codep++;
+ switch (threebyte)
+ {
+ case 0x38:
+ uses_DATA_prefix = threebyte_0x38_uses_DATA_prefix[op];
+ uses_REPNZ_prefix = threebyte_0x38_uses_REPNZ_prefix[op];
+ uses_REPZ_prefix = threebyte_0x38_uses_REPZ_prefix[op];
+ break;
+ case 0x3a:
+ uses_DATA_prefix = threebyte_0x3a_uses_DATA_prefix[op];
+ uses_REPNZ_prefix = threebyte_0x3a_uses_REPNZ_prefix[op];
+ uses_REPZ_prefix = threebyte_0x3a_uses_REPZ_prefix[op];
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else
+ {
+ dp = &dis386[*codep];
+ need_modrm = onebyte_has_modrm[*codep];
+ uses_DATA_prefix = 0;
+ uses_REPNZ_prefix = 0;
+ /* pause is 0xf3 0x90. */
+ uses_REPZ_prefix = *codep == 0x90;
+ uses_LOCK_prefix = 0;
+ codep++;
+ }
+
+ if (!uses_REPZ_prefix && (prefixes & PREFIX_REPZ))
+ {
+ oappend ("repz ");
+ used_prefixes |= PREFIX_REPZ;
+ }
+ if (!uses_REPNZ_prefix && (prefixes & PREFIX_REPNZ))
+ {
+ oappend ("repnz ");
+ used_prefixes |= PREFIX_REPNZ;
+ }
+
+ if (!uses_LOCK_prefix && (prefixes & PREFIX_LOCK))
+ {
+ oappend ("lock ");
+ used_prefixes |= PREFIX_LOCK;
+ }
+
+ if (prefixes & PREFIX_ADDR)
+ {
+ sizeflag ^= AFLAG;
+ if (dp->op[2].bytemode != loop_jcxz_mode || intel_syntax)
+ {
+ if ((sizeflag & AFLAG) || address_mode == mode_64bit)
+ oappend ("addr32 ");
+ else
+ oappend ("addr16 ");
+ used_prefixes |= PREFIX_ADDR;
+ }
+ }
+
+ if (!uses_DATA_prefix && (prefixes & PREFIX_DATA))
+ {
+ sizeflag ^= DFLAG;
+ if (dp->op[2].bytemode == cond_jump_mode
+ && dp->op[0].bytemode == v_mode
+ && !intel_syntax)
+ {
+ if (sizeflag & DFLAG)
+ oappend ("data32 ");
+ else
+ oappend ("data16 ");
+ used_prefixes |= PREFIX_DATA;
+ }
+ }
+
+ if (dp->name == NULL && dp->op[0].bytemode == IS_3BYTE_OPCODE)
+ {
+ dp = &three_byte_table[dp->op[1].bytemode][op];
+ modrm.mod = (*codep >> 6) & 3;
+ modrm.reg = (*codep >> 3) & 7;
+ modrm.rm = *codep & 7;
+ }
+ else if (need_modrm)
+ {
+ fetch_data(info, codep + 1);
+ modrm.mod = (*codep >> 6) & 3;
+ modrm.reg = (*codep >> 3) & 7;
+ modrm.rm = *codep & 7;
+ }
+
+ if (dp->name == NULL && dp->op[0].bytemode == FLOATCODE)
+ {
+ dofloat (sizeflag);
+ }
+ else
+ {
+ int index;
+ if (dp->name == NULL)
+ {
+ switch (dp->op[0].bytemode)
+ {
+ case USE_GROUPS:
+ dp = &grps[dp->op[1].bytemode][modrm.reg];
+ break;
+
+ case USE_PREFIX_USER_TABLE:
+ index = 0;
+ used_prefixes |= (prefixes & PREFIX_REPZ);
+ if (prefixes & PREFIX_REPZ)
+ index = 1;
+ else
+ {
+ /* We should check PREFIX_REPNZ and PREFIX_REPZ
+ before PREFIX_DATA. */
+ used_prefixes |= (prefixes & PREFIX_REPNZ);
+ if (prefixes & PREFIX_REPNZ)
+ index = 3;
+ else
+ {
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ if (prefixes & PREFIX_DATA)
+ index = 2;
+ }
+ }
+ dp = &prefix_user_table[dp->op[1].bytemode][index];
+ break;
+
+ case X86_64_SPECIAL:
+ index = address_mode == mode_64bit ? 1 : 0;
+ dp = &x86_64_table[dp->op[1].bytemode][index];
+ break;
+
+ default:
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
+ break;
+ }
+ }
+
+ if (putop (dp->name, sizeflag) == 0)
+ {
+ for (i = 0; i < MAX_OPERANDS; ++i)
+ {
+ obufp = op_out[i];
+ op_ad = MAX_OPERANDS - 1 - i;
+ if (dp->op[i].rtn)
+ (*dp->op[i].rtn) (dp->op[i].bytemode, sizeflag);
+ }
+ }
+ }
+
+ /* See if any prefixes were not used. If so, print the first one
+ separately. If we don't do this, we'll wind up printing an
+ instruction stream which does not precisely correspond to the
+ bytes we are disassembling. */
+ if ((prefixes & ~used_prefixes) != 0)
+ {
+ const char *name;
+
+ name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
+ if (name == NULL)
+ name = INTERNAL_DISASSEMBLER_ERROR;
+ (*info->fprintf_func) (info->stream, "%s", name);
+ return 1;
+ }
+ if (rex & ~rex_used)
+ {
+ const char *name;
+ name = prefix_name (rex | 0x40, priv.orig_sizeflag);
+ if (name == NULL)
+ name = INTERNAL_DISASSEMBLER_ERROR;
+ (*info->fprintf_func) (info->stream, "%s ", name);
+ }
+
+ obufp = obuf + strlen (obuf);
+ for (i = strlen (obuf); i < 6; i++)
+ oappend (" ");
+ oappend (" ");
+ (*info->fprintf_func) (info->stream, "%s", obuf);
+
+ /* The enter and bound instructions are printed with operands in the same
+ order as the intel book; everything else is printed in reverse order. */
+ if (intel_syntax || two_source_ops)
+ {
+ bfd_vma riprel;
+
+ for (i = 0; i < MAX_OPERANDS; ++i)
+ op_txt[i] = op_out[i];
+
+ for (i = 0; i < (MAX_OPERANDS >> 1); ++i)
+ {
+ op_ad = op_index[i];
+ op_index[i] = op_index[MAX_OPERANDS - 1 - i];
+ op_index[MAX_OPERANDS - 1 - i] = op_ad;
+ riprel = op_riprel[i];
+ op_riprel[i] = op_riprel [MAX_OPERANDS - 1 - i];
+ op_riprel[MAX_OPERANDS - 1 - i] = riprel;
+ }
+ }
+ else
+ {
+ for (i = 0; i < MAX_OPERANDS; ++i)
+ op_txt[MAX_OPERANDS - 1 - i] = op_out[i];
+ }
+
+ needcomma = 0;
+ for (i = 0; i < MAX_OPERANDS; ++i)
+ if (*op_txt[i])
+ {
+ if (needcomma)
+ (*info->fprintf_func) (info->stream, ",");
+ if (op_index[i] != -1 && !op_riprel[i])
+ (*info->print_address_func) ((bfd_vma) op_address[op_index[i]], info);
+ else
+ (*info->fprintf_func) (info->stream, "%s", op_txt[i]);
+ needcomma = 1;
+ }
+
+ for (i = 0; i < MAX_OPERANDS; i++)
+ if (op_index[i] != -1 && op_riprel[i])
+ {
+ (*info->fprintf_func) (info->stream, " # ");
+ (*info->print_address_func) ((bfd_vma) (start_pc + codep - start_codep
+ + op_address[op_index[i]]), info);
+ break;
+ }
+ return codep - priv.the_buffer;
+}
+
+static const char *float_mem[] = {
+ /* d8 */
+ "fadd{s||s|}",
+ "fmul{s||s|}",
+ "fcom{s||s|}",
+ "fcomp{s||s|}",
+ "fsub{s||s|}",
+ "fsubr{s||s|}",
+ "fdiv{s||s|}",
+ "fdivr{s||s|}",
+ /* d9 */
+ "fld{s||s|}",
+ "(bad)",
+ "fst{s||s|}",
+ "fstp{s||s|}",
+ "fldenvIC",
+ "fldcw",
+ "fNstenvIC",
+ "fNstcw",
+ /* da */
+ "fiadd{l||l|}",
+ "fimul{l||l|}",
+ "ficom{l||l|}",
+ "ficomp{l||l|}",
+ "fisub{l||l|}",
+ "fisubr{l||l|}",
+ "fidiv{l||l|}",
+ "fidivr{l||l|}",
+ /* db */
+ "fild{l||l|}",
+ "fisttp{l||l|}",
+ "fist{l||l|}",
+ "fistp{l||l|}",
+ "(bad)",
+ "fld{t||t|}",
+ "(bad)",
+ "fstp{t||t|}",
+ /* dc */
+ "fadd{l||l|}",
+ "fmul{l||l|}",
+ "fcom{l||l|}",
+ "fcomp{l||l|}",
+ "fsub{l||l|}",
+ "fsubr{l||l|}",
+ "fdiv{l||l|}",
+ "fdivr{l||l|}",
+ /* dd */
+ "fld{l||l|}",
+ "fisttp{ll||ll|}",
+ "fst{l||l|}",
+ "fstp{l||l|}",
+ "frstorIC",
+ "(bad)",
+ "fNsaveIC",
+ "fNstsw",
+ /* de */
+ "fiadd",
+ "fimul",
+ "ficom",
+ "ficomp",
+ "fisub",
+ "fisubr",
+ "fidiv",
+ "fidivr",
+ /* df */
+ "fild",
+ "fisttp",
+ "fist",
+ "fistp",
+ "fbld",
+ "fild{ll||ll|}",
+ "fbstp",
+ "fistp{ll||ll|}",
+};
+
+static const unsigned char float_mem_mode[] = {
+ /* d8 */
+ d_mode,
+ d_mode,
+ d_mode,
+ d_mode,
+ d_mode,
+ d_mode,
+ d_mode,
+ d_mode,
+ /* d9 */
+ d_mode,
+ 0,
+ d_mode,
+ d_mode,
+ 0,
+ w_mode,
+ 0,
+ w_mode,
+ /* da */
+ d_mode,
+ d_mode,
+ d_mode,
+ d_mode,
+ d_mode,
+ d_mode,
+ d_mode,
+ d_mode,
+ /* db */
+ d_mode,
+ d_mode,
+ d_mode,
+ d_mode,
+ 0,
+ t_mode,
+ 0,
+ t_mode,
+ /* dc */
+ q_mode,
+ q_mode,
+ q_mode,
+ q_mode,
+ q_mode,
+ q_mode,
+ q_mode,
+ q_mode,
+ /* dd */
+ q_mode,
+ q_mode,
+ q_mode,
+ q_mode,
+ 0,
+ 0,
+ 0,
+ w_mode,
+ /* de */
+ w_mode,
+ w_mode,
+ w_mode,
+ w_mode,
+ w_mode,
+ w_mode,
+ w_mode,
+ w_mode,
+ /* df */
+ w_mode,
+ w_mode,
+ w_mode,
+ w_mode,
+ t_mode,
+ q_mode,
+ t_mode,
+ q_mode
+};
+
+#define ST { OP_ST, 0 }
+#define STi { OP_STi, 0 }
+
+#define FGRPd9_2 NULL, { { NULL, 0 } }
+#define FGRPd9_4 NULL, { { NULL, 1 } }
+#define FGRPd9_5 NULL, { { NULL, 2 } }
+#define FGRPd9_6 NULL, { { NULL, 3 } }
+#define FGRPd9_7 NULL, { { NULL, 4 } }
+#define FGRPda_5 NULL, { { NULL, 5 } }
+#define FGRPdb_4 NULL, { { NULL, 6 } }
+#define FGRPde_3 NULL, { { NULL, 7 } }
+#define FGRPdf_4 NULL, { { NULL, 8 } }
+
+static const struct dis386 float_reg[][8] = {
+ /* d8 */
+ {
+ { "fadd", { ST, STi } },
+ { "fmul", { ST, STi } },
+ { "fcom", { STi } },
+ { "fcomp", { STi } },
+ { "fsub", { ST, STi } },
+ { "fsubr", { ST, STi } },
+ { "fdiv", { ST, STi } },
+ { "fdivr", { ST, STi } },
+ },
+ /* d9 */
+ {
+ { "fld", { STi } },
+ { "fxch", { STi } },
+ { FGRPd9_2 },
+ { "(bad)", { XX } },
+ { FGRPd9_4 },
+ { FGRPd9_5 },
+ { FGRPd9_6 },
+ { FGRPd9_7 },
+ },
+ /* da */
+ {
+ { "fcmovb", { ST, STi } },
+ { "fcmove", { ST, STi } },
+ { "fcmovbe",{ ST, STi } },
+ { "fcmovu", { ST, STi } },
+ { "(bad)", { XX } },
+ { FGRPda_5 },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ },
+ /* db */
+ {
+ { "fcmovnb",{ ST, STi } },
+ { "fcmovne",{ ST, STi } },
+ { "fcmovnbe",{ ST, STi } },
+ { "fcmovnu",{ ST, STi } },
+ { FGRPdb_4 },
+ { "fucomi", { ST, STi } },
+ { "fcomi", { ST, STi } },
+ { "(bad)", { XX } },
+ },
+ /* dc */
+ {
+ { "fadd", { STi, ST } },
+ { "fmul", { STi, ST } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+#if SYSV386_COMPAT
+ { "fsub", { STi, ST } },
+ { "fsubr", { STi, ST } },
+ { "fdiv", { STi, ST } },
+ { "fdivr", { STi, ST } },
+#else
+ { "fsubr", { STi, ST } },
+ { "fsub", { STi, ST } },
+ { "fdivr", { STi, ST } },
+ { "fdiv", { STi, ST } },
+#endif
+ },
+ /* dd */
+ {
+ { "ffree", { STi } },
+ { "(bad)", { XX } },
+ { "fst", { STi } },
+ { "fstp", { STi } },
+ { "fucom", { STi } },
+ { "fucomp", { STi } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ },
+ /* de */
+ {
+ { "faddp", { STi, ST } },
+ { "fmulp", { STi, ST } },
+ { "(bad)", { XX } },
+ { FGRPde_3 },
+#if SYSV386_COMPAT
+ { "fsubp", { STi, ST } },
+ { "fsubrp", { STi, ST } },
+ { "fdivp", { STi, ST } },
+ { "fdivrp", { STi, ST } },
+#else
+ { "fsubrp", { STi, ST } },
+ { "fsubp", { STi, ST } },
+ { "fdivrp", { STi, ST } },
+ { "fdivp", { STi, ST } },
+#endif
+ },
+ /* df */
+ {
+ { "ffreep", { STi } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { "(bad)", { XX } },
+ { FGRPdf_4 },
+ { "fucomip", { ST, STi } },
+ { "fcomip", { ST, STi } },
+ { "(bad)", { XX } },
+ },
+};
+
+static const char *fgrps[][8] = {
+ /* d9_2 0 */
+ {
+ "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* d9_4 1 */
+ {
+ "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
+ },
+
+ /* d9_5 2 */
+ {
+ "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
+ },
+
+ /* d9_6 3 */
+ {
+ "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
+ },
+
+ /* d9_7 4 */
+ {
+ "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
+ },
+
+ /* da_5 5 */
+ {
+ "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* db_4 6 */
+ {
+ "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
+ "fNsetpm(287 only)","(bad)","(bad)","(bad)",
+ },
+
+ /* de_3 7 */
+ {
+ "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* df_4 8 */
+ {
+ "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+};
+
+static void
+dofloat (int sizeflag)
+{
+ const struct dis386 *dp;
+ unsigned char floatop;
+
+ floatop = codep[-1];
+
+ if (modrm.mod != 3)
+ {
+ int fp_indx = (floatop - 0xd8) * 8 + modrm.reg;
+
+ putop (float_mem[fp_indx], sizeflag);
+ obufp = op_out[0];
+ op_ad = 2;
+ OP_E (float_mem_mode[fp_indx], sizeflag);
+ return;
+ }
+ /* Skip mod/rm byte. */
+ MODRM_CHECK;
+ codep++;
+
+ dp = &float_reg[floatop - 0xd8][modrm.reg];
+ if (dp->name == NULL)
+ {
+ putop (fgrps[dp->op[0].bytemode][modrm.rm], sizeflag);
+
+ /* Instruction fnstsw is only one with strange arg. */
+ if (floatop == 0xdf && codep[-1] == 0xe0)
+ pstrcpy (op_out[0], sizeof(op_out[0]), names16[0]);
+ }
+ else
+ {
+ putop (dp->name, sizeflag);
+
+ obufp = op_out[0];
+ op_ad = 2;
+ if (dp->op[0].rtn)
+ (*dp->op[0].rtn) (dp->op[0].bytemode, sizeflag);
+
+ obufp = op_out[1];
+ op_ad = 1;
+ if (dp->op[1].rtn)
+ (*dp->op[1].rtn) (dp->op[1].bytemode, sizeflag);
+ }
+}
+
+static void
+OP_ST (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+ oappend ("%st" + intel_syntax);
+}
+
+static void
+OP_STi (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+ snprintf (scratchbuf, sizeof(scratchbuf), "%%st(%d)", modrm.rm);
+ oappend (scratchbuf + intel_syntax);
+}
+
+/* Capital letters in template are macros. */
+static int
+putop (const char *template, int sizeflag)
+{
+ const char *p;
+ int alt = 0;
+
+ for (p = template; *p; p++)
+ {
+ switch (*p)
+ {
+ default:
+ *obufp++ = *p;
+ break;
+ case '{':
+ alt = 0;
+ if (intel_syntax)
+ alt += 1;
+ if (address_mode == mode_64bit)
+ alt += 2;
+ while (alt != 0)
+ {
+ while (*++p != '|')
+ {
+ if (*p == '}')
+ {
+ /* Alternative not valid. */
+ pstrcpy (obuf, sizeof(obuf), "(bad)");
+ obufp = obuf + 5;
+ return 1;
+ }
+ else if (*p == '\0')
+ abort ();
+ }
+ alt--;
+ }
+ /* Fall through. */
+ case 'I':
+ alt = 1;
+ continue;
+ case '|':
+ while (*++p != '}')
+ {
+ if (*p == '\0')
+ abort ();
+ }
+ break;
+ case '}':
+ break;
+ case 'A':
+ if (intel_syntax)
+ break;
+ if (modrm.mod != 3 || (sizeflag & SUFFIX_ALWAYS))
+ *obufp++ = 'b';
+ break;
+ case 'B':
+ if (intel_syntax)
+ break;
+ if (sizeflag & SUFFIX_ALWAYS)
+ *obufp++ = 'b';
+ break;
+ case 'C':
+ if (intel_syntax && !alt)
+ break;
+ if ((prefixes & PREFIX_DATA) || (sizeflag & SUFFIX_ALWAYS))
+ {
+ if (sizeflag & DFLAG)
+ *obufp++ = intel_syntax ? 'd' : 'l';
+ else
+ *obufp++ = intel_syntax ? 'w' : 's';
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ }
+ break;
+ case 'D':
+ if (intel_syntax || !(sizeflag & SUFFIX_ALWAYS))
+ break;
+ USED_REX (REX_W);
+ if (modrm.mod == 3)
+ {
+ if (rex & REX_W)
+ *obufp++ = 'q';
+ else if (sizeflag & DFLAG)
+ *obufp++ = intel_syntax ? 'd' : 'l';
+ else
+ *obufp++ = 'w';
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ }
+ else
+ *obufp++ = 'w';
+ break;
+ case 'E': /* For jcxz/jecxz */
+ if (address_mode == mode_64bit)
+ {
+ if (sizeflag & AFLAG)
+ *obufp++ = 'r';
+ else
+ *obufp++ = 'e';
+ }
+ else
+ if (sizeflag & AFLAG)
+ *obufp++ = 'e';
+ used_prefixes |= (prefixes & PREFIX_ADDR);
+ break;
+ case 'F':
+ if (intel_syntax)
+ break;
+ if ((prefixes & PREFIX_ADDR) || (sizeflag & SUFFIX_ALWAYS))
+ {
+ if (sizeflag & AFLAG)
+ *obufp++ = address_mode == mode_64bit ? 'q' : 'l';
+ else
+ *obufp++ = address_mode == mode_64bit ? 'l' : 'w';
+ used_prefixes |= (prefixes & PREFIX_ADDR);
+ }
+ break;
+ case 'G':
+ if (intel_syntax || (obufp[-1] != 's' && !(sizeflag & SUFFIX_ALWAYS)))
+ break;
+ if ((rex & REX_W) || (sizeflag & DFLAG))
+ *obufp++ = 'l';
+ else
+ *obufp++ = 'w';
+ if (!(rex & REX_W))
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ case 'H':
+ if (intel_syntax)
+ break;
+ if ((prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_CS
+ || (prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_DS)
+ {
+ used_prefixes |= prefixes & (PREFIX_CS | PREFIX_DS);
+ *obufp++ = ',';
+ *obufp++ = 'p';
+ if (prefixes & PREFIX_DS)
+ *obufp++ = 't';
+ else
+ *obufp++ = 'n';
+ }
+ break;
+ case 'J':
+ if (intel_syntax)
+ break;
+ *obufp++ = 'l';
+ break;
+ case 'K':
+ USED_REX (REX_W);
+ if (rex & REX_W)
+ *obufp++ = 'q';
+ else
+ *obufp++ = 'd';
+ break;
+ case 'Z':
+ if (intel_syntax)
+ break;
+ if (address_mode == mode_64bit && (sizeflag & SUFFIX_ALWAYS))
+ {
+ *obufp++ = 'q';
+ break;
+ }
+ /* Fall through. */
+ case 'L':
+ if (intel_syntax)
+ break;
+ if (sizeflag & SUFFIX_ALWAYS)
+ *obufp++ = 'l';
+ break;
+ case 'N':
+ if ((prefixes & PREFIX_FWAIT) == 0)
+ *obufp++ = 'n';
+ else
+ used_prefixes |= PREFIX_FWAIT;
+ break;
+ case 'O':
+ USED_REX (REX_W);
+ if (rex & REX_W)
+ *obufp++ = 'o';
+ else if (intel_syntax && (sizeflag & DFLAG))
+ *obufp++ = 'q';
+ else
+ *obufp++ = 'd';
+ if (!(rex & REX_W))
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ case 'T':
+ if (intel_syntax)
+ break;
+ if (address_mode == mode_64bit && (sizeflag & DFLAG))
+ {
+ *obufp++ = 'q';
+ break;
+ }
+ /* Fall through. */
+ case 'P':
+ if (intel_syntax)
+ break;
+ if ((prefixes & PREFIX_DATA)
+ || (rex & REX_W)
+ || (sizeflag & SUFFIX_ALWAYS))
+ {
+ USED_REX (REX_W);
+ if (rex & REX_W)
+ *obufp++ = 'q';
+ else
+ {
+ if (sizeflag & DFLAG)
+ *obufp++ = 'l';
+ else
+ *obufp++ = 'w';
+ }
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ }
+ break;
+ case 'U':
+ if (intel_syntax)
+ break;
+ if (address_mode == mode_64bit && (sizeflag & DFLAG))
+ {
+ if (modrm.mod != 3 || (sizeflag & SUFFIX_ALWAYS))
+ *obufp++ = 'q';
+ break;
+ }
+ /* Fall through. */
+ case 'Q':
+ if (intel_syntax && !alt)
+ break;
+ USED_REX (REX_W);
+ if (modrm.mod != 3 || (sizeflag & SUFFIX_ALWAYS))
+ {
+ if (rex & REX_W)
+ *obufp++ = 'q';
+ else
+ {
+ if (sizeflag & DFLAG)
+ *obufp++ = intel_syntax ? 'd' : 'l';
+ else
+ *obufp++ = 'w';
+ }
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ }
+ break;
+ case 'R':
+ USED_REX (REX_W);
+ if (rex & REX_W)
+ *obufp++ = 'q';
+ else if (sizeflag & DFLAG)
+ {
+ if (intel_syntax)
+ *obufp++ = 'd';
+ else
+ *obufp++ = 'l';
+ }
+ else
+ *obufp++ = 'w';
+ if (intel_syntax && !p[1]
+ && ((rex & REX_W) || (sizeflag & DFLAG)))
+ *obufp++ = 'e';
+ if (!(rex & REX_W))
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ case 'V':
+ if (intel_syntax)
+ break;
+ if (address_mode == mode_64bit && (sizeflag & DFLAG))
+ {
+ if (sizeflag & SUFFIX_ALWAYS)
+ *obufp++ = 'q';
+ break;
+ }
+ /* Fall through. */
+ case 'S':
+ if (intel_syntax)
+ break;
+ if (sizeflag & SUFFIX_ALWAYS)
+ {
+ if (rex & REX_W)
+ *obufp++ = 'q';
+ else
+ {
+ if (sizeflag & DFLAG)
+ *obufp++ = 'l';
+ else
+ *obufp++ = 'w';
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ }
+ }
+ break;
+ case 'X':
+ if (prefixes & PREFIX_DATA)
+ *obufp++ = 'd';
+ else
+ *obufp++ = 's';
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ case 'Y':
+ if (intel_syntax)
+ break;
+ if (rex & REX_W)
+ {
+ USED_REX (REX_W);
+ *obufp++ = 'q';
+ }
+ break;
+ /* implicit operand size 'l' for i386 or 'q' for x86-64 */
+ case 'W':
+ /* operand size flag for cwtl, cbtw */
+ USED_REX (REX_W);
+ if (rex & REX_W)
+ {
+ if (intel_syntax)
+ *obufp++ = 'd';
+ else
+ *obufp++ = 'l';
+ }
+ else if (sizeflag & DFLAG)
+ *obufp++ = 'w';
+ else
+ *obufp++ = 'b';
+ if (!(rex & REX_W))
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ }
+ alt = 0;
+ }
+ *obufp = 0;
+ return 0;
+}
+
+static void
+oappend (const char *s)
+{
+ strcpy (obufp, s);
+ obufp += strlen (s);
+}
+
+static void
+append_seg (void)
+{
+ if (prefixes & PREFIX_CS)
+ {
+ used_prefixes |= PREFIX_CS;
+ oappend ("%cs:" + intel_syntax);
+ }
+ if (prefixes & PREFIX_DS)
+ {
+ used_prefixes |= PREFIX_DS;
+ oappend ("%ds:" + intel_syntax);
+ }
+ if (prefixes & PREFIX_SS)
+ {
+ used_prefixes |= PREFIX_SS;
+ oappend ("%ss:" + intel_syntax);
+ }
+ if (prefixes & PREFIX_ES)
+ {
+ used_prefixes |= PREFIX_ES;
+ oappend ("%es:" + intel_syntax);
+ }
+ if (prefixes & PREFIX_FS)
+ {
+ used_prefixes |= PREFIX_FS;
+ oappend ("%fs:" + intel_syntax);
+ }
+ if (prefixes & PREFIX_GS)
+ {
+ used_prefixes |= PREFIX_GS;
+ oappend ("%gs:" + intel_syntax);
+ }
+}
+
+static void
+OP_indirE (int bytemode, int sizeflag)
+{
+ if (!intel_syntax)
+ oappend ("*");
+ OP_E (bytemode, sizeflag);
+}
+
+static void
+print_operand_value (char *buf, size_t bufsize, int hex, bfd_vma disp)
+{
+ if (address_mode == mode_64bit)
+ {
+ if (hex)
+ {
+ char tmp[30];
+ int i;
+ buf[0] = '0';
+ buf[1] = 'x';
+ snprintf_vma (tmp, sizeof(tmp), disp);
+ for (i = 0; tmp[i] == '0' && tmp[i + 1]; i++);
+ pstrcpy (buf + 2, bufsize - 2, tmp + i);
+ }
+ else
+ {
+ bfd_signed_vma v = disp;
+ char tmp[30];
+ int i;
+ if (v < 0)
+ {
+ *(buf++) = '-';
+ v = -disp;
+ /* Check for possible overflow on 0x8000000000000000. */
+ if (v < 0)
+ {
+ pstrcpy (buf, bufsize, "9223372036854775808");
+ return;
+ }
+ }
+ if (!v)
+ {
+ pstrcpy (buf, bufsize, "0");
+ return;
+ }
+
+ i = 0;
+ tmp[29] = 0;
+ while (v)
+ {
+ tmp[28 - i] = (v % 10) + '0';
+ v /= 10;
+ i++;
+ }
+ pstrcpy (buf, bufsize, tmp + 29 - i);
+ }
+ }
+ else
+ {
+ if (hex)
+ snprintf (buf, bufsize, "0x%x", (unsigned int) disp);
+ else
+ snprintf (buf, bufsize, "%d", (int) disp);
+ }
+}
+
+/* Put DISP in BUF as signed hex number. */
+
+static void
+print_displacement (char *buf, bfd_vma disp)
+{
+ bfd_signed_vma val = disp;
+ char tmp[30];
+ int i, j = 0;
+
+ if (val < 0)
+ {
+ buf[j++] = '-';
+ val = -disp;
+
+ /* Check for possible overflow. */
+ if (val < 0)
+ {
+ switch (address_mode)
+ {
+ case mode_64bit:
+ strcpy (buf + j, "0x8000000000000000");
+ break;
+ case mode_32bit:
+ strcpy (buf + j, "0x80000000");
+ break;
+ case mode_16bit:
+ strcpy (buf + j, "0x8000");
+ break;
+ }
+ return;
+ }
+ }
+
+ buf[j++] = '0';
+ buf[j++] = 'x';
+
+ snprintf_vma (tmp, sizeof(tmp), val);
+ for (i = 0; tmp[i] == '0'; i++)
+ continue;
+ if (tmp[i] == '\0')
+ i--;
+ strcpy (buf + j, tmp + i);
+}
+
+static void
+intel_operand_size (int bytemode, int sizeflag)
+{
+ switch (bytemode)
+ {
+ case b_mode:
+ case dqb_mode:
+ oappend ("BYTE PTR ");
+ break;
+ case w_mode:
+ case dqw_mode:
+ oappend ("WORD PTR ");
+ break;
+ case stack_v_mode:
+ if (address_mode == mode_64bit && (sizeflag & DFLAG))
+ {
+ oappend ("QWORD PTR ");
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ }
+ /* FALLTHRU */
+ case v_mode:
+ case dq_mode:
+ USED_REX (REX_W);
+ if (rex & REX_W)
+ oappend ("QWORD PTR ");
+ else if ((sizeflag & DFLAG) || bytemode == dq_mode)
+ oappend ("DWORD PTR ");
+ else
+ oappend ("WORD PTR ");
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ case z_mode:
+ if ((rex & REX_W) || (sizeflag & DFLAG))
+ *obufp++ = 'D';
+ oappend ("WORD PTR ");
+ if (!(rex & REX_W))
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ case d_mode:
+ case dqd_mode:
+ oappend ("DWORD PTR ");
+ break;
+ case q_mode:
+ oappend ("QWORD PTR ");
+ break;
+ case m_mode:
+ if (address_mode == mode_64bit)
+ oappend ("QWORD PTR ");
+ else
+ oappend ("DWORD PTR ");
+ break;
+ case f_mode:
+ if (sizeflag & DFLAG)
+ oappend ("FWORD PTR ");
+ else
+ oappend ("DWORD PTR ");
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ case t_mode:
+ oappend ("TBYTE PTR ");
+ break;
+ case x_mode:
+ oappend ("XMMWORD PTR ");
+ break;
+ case o_mode:
+ oappend ("OWORD PTR ");
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+OP_E (int bytemode, int sizeflag)
+{
+ bfd_vma disp;
+ int add = 0;
+ int riprel = 0;
+ USED_REX (REX_B);
+ if (rex & REX_B)
+ add += 8;
+
+ /* Skip mod/rm byte. */
+ MODRM_CHECK;
+ codep++;
+
+ if (modrm.mod == 3)
+ {
+ switch (bytemode)
+ {
+ case b_mode:
+ USED_REX (0);
+ if (rex)
+ oappend (names8rex[modrm.rm + add]);
+ else
+ oappend (names8[modrm.rm + add]);
+ break;
+ case w_mode:
+ oappend (names16[modrm.rm + add]);
+ break;
+ case d_mode:
+ oappend (names32[modrm.rm + add]);
+ break;
+ case q_mode:
+ oappend (names64[modrm.rm + add]);
+ break;
+ case m_mode:
+ if (address_mode == mode_64bit)
+ oappend (names64[modrm.rm + add]);
+ else
+ oappend (names32[modrm.rm + add]);
+ break;
+ case stack_v_mode:
+ if (address_mode == mode_64bit && (sizeflag & DFLAG))
+ {
+ oappend (names64[modrm.rm + add]);
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ }
+ bytemode = v_mode;
+ /* FALLTHRU */
+ case v_mode:
+ case dq_mode:
+ case dqb_mode:
+ case dqd_mode:
+ case dqw_mode:
+ USED_REX (REX_W);
+ if (rex & REX_W)
+ oappend (names64[modrm.rm + add]);
+ else if ((sizeflag & DFLAG) || bytemode != v_mode)
+ oappend (names32[modrm.rm + add]);
+ else
+ oappend (names16[modrm.rm + add]);
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ case 0:
+ break;
+ default:
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
+ break;
+ }
+ return;
+ }
+
+ disp = 0;
+ if (intel_syntax)
+ intel_operand_size (bytemode, sizeflag);
+ append_seg ();
+
+ if ((sizeflag & AFLAG) || address_mode == mode_64bit)
+ {
+ /* 32/64 bit address mode */
+ int havedisp;
+ int havesib;
+ int havebase;
+ int base;
+ int index = 0;
+ int scale = 0;
+
+ havesib = 0;
+ havebase = 1;
+ base = modrm.rm;
+
+ if (base == 4)
+ {
+ havesib = 1;
+ fetch_data(the_info, codep + 1);
+ index = (*codep >> 3) & 7;
+ if (address_mode == mode_64bit || index != 0x4)
+ /* When INDEX == 0x4 in 32 bit mode, SCALE is ignored. */
+ scale = (*codep >> 6) & 3;
+ base = *codep & 7;
+ USED_REX (REX_X);
+ if (rex & REX_X)
+ index += 8;
+ codep++;
+ }
+ base += add;
+
+ switch (modrm.mod)
+ {
+ case 0:
+ if ((base & 7) == 5)
+ {
+ havebase = 0;
+ if (address_mode == mode_64bit && !havesib)
+ riprel = 1;
+ disp = get32s ();
+ }
+ break;
+ case 1:
+ fetch_data (the_info, codep + 1);
+ disp = *codep++;
+ if ((disp & 0x80) != 0)
+ disp -= 0x100;
+ break;
+ case 2:
+ disp = get32s ();
+ break;
+ }
+
+ havedisp = havebase || (havesib && (index != 4 || scale != 0));
+
+ if (!intel_syntax)
+ if (modrm.mod != 0 || (base & 7) == 5)
+ {
+ if (havedisp || riprel)
+ print_displacement (scratchbuf, disp);
+ else
+ print_operand_value (scratchbuf, sizeof(scratchbuf), 1, disp);
+ oappend (scratchbuf);
+ if (riprel)
+ {
+ set_op (disp, 1);
+ oappend ("(%rip)");
+ }
+ }
+
+ if (havedisp || (intel_syntax && riprel))
+ {
+ *obufp++ = open_char;
+ if (intel_syntax && riprel)
+ {
+ set_op (disp, 1);
+ oappend ("rip");
+ }
+ *obufp = '\0';
+ if (havebase)
+ oappend (address_mode == mode_64bit && (sizeflag & AFLAG)
+ ? names64[base] : names32[base]);
+ if (havesib)
+ {
+ if (index != 4)
+ {
+ if (!intel_syntax || havebase)
+ {
+ *obufp++ = separator_char;
+ *obufp = '\0';
+ }
+ oappend (address_mode == mode_64bit && (sizeflag & AFLAG)
+ ? names64[index] : names32[index]);
+ }
+ if (scale != 0 || (!intel_syntax && index != 4))
+ {
+ *obufp++ = scale_char;
+ *obufp = '\0';
+ snprintf (scratchbuf, sizeof(scratchbuf), "%d", 1 << scale);
+ oappend (scratchbuf);
+ }
+ }
+ if (intel_syntax
+ && (disp || modrm.mod != 0 || (base & 7) == 5))
+ {
+ if ((bfd_signed_vma) disp >= 0)
+ {
+ *obufp++ = '+';
+ *obufp = '\0';
+ }
+ else if (modrm.mod != 1)
+ {
+ *obufp++ = '-';
+ *obufp = '\0';
+ disp = - (bfd_signed_vma) disp;
+ }
+
+ print_displacement (scratchbuf, disp);
+ oappend (scratchbuf);
+ }
+
+ *obufp++ = close_char;
+ *obufp = '\0';
+ }
+ else if (intel_syntax)
+ {
+ if (modrm.mod != 0 || (base & 7) == 5)
+ {
+ if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
+ | PREFIX_ES | PREFIX_FS | PREFIX_GS))
+ ;
+ else
+ {
+ oappend (names_seg[ds_reg - es_reg]);
+ oappend (":");
+ }
+ print_operand_value (scratchbuf, sizeof(scratchbuf), 1, disp);
+ oappend (scratchbuf);
+ }
+ }
+ }
+ else
+ { /* 16 bit address mode */
+ switch (modrm.mod)
+ {
+ case 0:
+ if (modrm.rm == 6)
+ {
+ disp = get16 ();
+ if ((disp & 0x8000) != 0)
+ disp -= 0x10000;
+ }
+ break;
+ case 1:
+ fetch_data(the_info, codep + 1);
+ disp = *codep++;
+ if ((disp & 0x80) != 0)
+ disp -= 0x100;
+ break;
+ case 2:
+ disp = get16 ();
+ if ((disp & 0x8000) != 0)
+ disp -= 0x10000;
+ break;
+ }
+
+ if (!intel_syntax)
+ if (modrm.mod != 0 || modrm.rm == 6)
+ {
+ print_displacement (scratchbuf, disp);
+ oappend (scratchbuf);
+ }
+
+ if (modrm.mod != 0 || modrm.rm != 6)
+ {
+ *obufp++ = open_char;
+ *obufp = '\0';
+ oappend (index16[modrm.rm]);
+ if (intel_syntax
+ && (disp || modrm.mod != 0 || modrm.rm == 6))
+ {
+ if ((bfd_signed_vma) disp >= 0)
+ {
+ *obufp++ = '+';
+ *obufp = '\0';
+ }
+ else if (modrm.mod != 1)
+ {
+ *obufp++ = '-';
+ *obufp = '\0';
+ disp = - (bfd_signed_vma) disp;
+ }
+
+ print_displacement (scratchbuf, disp);
+ oappend (scratchbuf);
+ }
+
+ *obufp++ = close_char;
+ *obufp = '\0';
+ }
+ else if (intel_syntax)
+ {
+ if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
+ | PREFIX_ES | PREFIX_FS | PREFIX_GS))
+ ;
+ else
+ {
+ oappend (names_seg[ds_reg - es_reg]);
+ oappend (":");
+ }
+ print_operand_value (scratchbuf, sizeof(scratchbuf), 1,
+ disp & 0xffff);
+ oappend (scratchbuf);
+ }
+ }
+}
+
+static void
+OP_G (int bytemode, int sizeflag)
+{
+ int add = 0;
+ USED_REX (REX_R);
+ if (rex & REX_R)
+ add += 8;
+ switch (bytemode)
+ {
+ case b_mode:
+ USED_REX (0);
+ if (rex)
+ oappend (names8rex[modrm.reg + add]);
+ else
+ oappend (names8[modrm.reg + add]);
+ break;
+ case w_mode:
+ oappend (names16[modrm.reg + add]);
+ break;
+ case d_mode:
+ oappend (names32[modrm.reg + add]);
+ break;
+ case q_mode:
+ oappend (names64[modrm.reg + add]);
+ break;
+ case v_mode:
+ case dq_mode:
+ case dqb_mode:
+ case dqd_mode:
+ case dqw_mode:
+ USED_REX (REX_W);
+ if (rex & REX_W)
+ oappend (names64[modrm.reg + add]);
+ else if ((sizeflag & DFLAG) || bytemode != v_mode)
+ oappend (names32[modrm.reg + add]);
+ else
+ oappend (names16[modrm.reg + add]);
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ case m_mode:
+ if (address_mode == mode_64bit)
+ oappend (names64[modrm.reg + add]);
+ else
+ oappend (names32[modrm.reg + add]);
+ break;
+ default:
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
+ break;
+ }
+}
+
+static bfd_vma
+get64 (void)
+{
+ bfd_vma x;
+#ifdef BFD64
+ unsigned int a;
+ unsigned int b;
+
+ fetch_data(the_info, codep + 8);
+ a = *codep++ & 0xff;
+ a |= (*codep++ & 0xff) << 8;
+ a |= (*codep++ & 0xff) << 16;
+ a |= (*codep++ & 0xff) << 24;
+ b = *codep++ & 0xff;
+ b |= (*codep++ & 0xff) << 8;
+ b |= (*codep++ & 0xff) << 16;
+ b |= (*codep++ & 0xff) << 24;
+ x = a + ((bfd_vma) b << 32);
+#else
+ abort ();
+ x = 0;
+#endif
+ return x;
+}
+
+static bfd_signed_vma
+get32 (void)
+{
+ bfd_signed_vma x = 0;
+
+ fetch_data(the_info, codep + 4);
+ x = *codep++ & (bfd_signed_vma) 0xff;
+ x |= (*codep++ & (bfd_signed_vma) 0xff) << 8;
+ x |= (*codep++ & (bfd_signed_vma) 0xff) << 16;
+ x |= (*codep++ & (bfd_signed_vma) 0xff) << 24;
+ return x;
+}
+
+static bfd_signed_vma
+get32s (void)
+{
+ bfd_signed_vma x = 0;
+
+ fetch_data(the_info, codep + 4);
+ x = *codep++ & (bfd_signed_vma) 0xff;
+ x |= (*codep++ & (bfd_signed_vma) 0xff) << 8;
+ x |= (*codep++ & (bfd_signed_vma) 0xff) << 16;
+ x |= (*codep++ & (bfd_signed_vma) 0xff) << 24;
+
+ x = (x ^ ((bfd_signed_vma) 1 << 31)) - ((bfd_signed_vma) 1 << 31);
+
+ return x;
+}
+
+static int
+get16 (void)
+{
+ int x = 0;
+
+ fetch_data(the_info, codep + 2);
+ x = *codep++ & 0xff;
+ x |= (*codep++ & 0xff) << 8;
+ return x;
+}
+
+static void
+set_op (bfd_vma op, int riprel)
+{
+ op_index[op_ad] = op_ad;
+ if (address_mode == mode_64bit)
+ {
+ op_address[op_ad] = op;
+ op_riprel[op_ad] = riprel;
+ }
+ else
+ {
+ /* Mask to get a 32-bit address. */
+ op_address[op_ad] = op & 0xffffffff;
+ op_riprel[op_ad] = riprel & 0xffffffff;
+ }
+}
+
+static void
+OP_REG (int code, int sizeflag)
+{
+ const char *s;
+ int add = 0;
+ USED_REX (REX_B);
+ if (rex & REX_B)
+ add = 8;
+
+ switch (code)
+ {
+ case ax_reg: case cx_reg: case dx_reg: case bx_reg:
+ case sp_reg: case bp_reg: case si_reg: case di_reg:
+ s = names16[code - ax_reg + add];
+ break;
+ case es_reg: case ss_reg: case cs_reg:
+ case ds_reg: case fs_reg: case gs_reg:
+ s = names_seg[code - es_reg + add];
+ break;
+ case al_reg: case ah_reg: case cl_reg: case ch_reg:
+ case dl_reg: case dh_reg: case bl_reg: case bh_reg:
+ USED_REX (0);
+ if (rex)
+ s = names8rex[code - al_reg + add];
+ else
+ s = names8[code - al_reg];
+ break;
+ case rAX_reg: case rCX_reg: case rDX_reg: case rBX_reg:
+ case rSP_reg: case rBP_reg: case rSI_reg: case rDI_reg:
+ if (address_mode == mode_64bit && (sizeflag & DFLAG))
+ {
+ s = names64[code - rAX_reg + add];
+ break;
+ }
+ code += eAX_reg - rAX_reg;
+ /* Fall through. */
+ case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
+ case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
+ USED_REX (REX_W);
+ if (rex & REX_W)
+ s = names64[code - eAX_reg + add];
+ else if (sizeflag & DFLAG)
+ s = names32[code - eAX_reg + add];
+ else
+ s = names16[code - eAX_reg + add];
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ default:
+ s = INTERNAL_DISASSEMBLER_ERROR;
+ break;
+ }
+ oappend (s);
+}
+
+static void
+OP_IMREG (int code, int sizeflag)
+{
+ const char *s;
+
+ switch (code)
+ {
+ case indir_dx_reg:
+ if (intel_syntax)
+ s = "dx";
+ else
+ s = "(%dx)";
+ break;
+ case ax_reg: case cx_reg: case dx_reg: case bx_reg:
+ case sp_reg: case bp_reg: case si_reg: case di_reg:
+ s = names16[code - ax_reg];
+ break;
+ case es_reg: case ss_reg: case cs_reg:
+ case ds_reg: case fs_reg: case gs_reg:
+ s = names_seg[code - es_reg];
+ break;
+ case al_reg: case ah_reg: case cl_reg: case ch_reg:
+ case dl_reg: case dh_reg: case bl_reg: case bh_reg:
+ USED_REX (0);
+ if (rex)
+ s = names8rex[code - al_reg];
+ else
+ s = names8[code - al_reg];
+ break;
+ case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
+ case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
+ USED_REX (REX_W);
+ if (rex & REX_W)
+ s = names64[code - eAX_reg];
+ else if (sizeflag & DFLAG)
+ s = names32[code - eAX_reg];
+ else
+ s = names16[code - eAX_reg];
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ case z_mode_ax_reg:
+ if ((rex & REX_W) || (sizeflag & DFLAG))
+ s = *names32;
+ else
+ s = *names16;
+ if (!(rex & REX_W))
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ default:
+ s = INTERNAL_DISASSEMBLER_ERROR;
+ break;
+ }
+ oappend (s);
+}
+
+static void
+OP_I (int bytemode, int sizeflag)
+{
+ bfd_signed_vma op;
+ bfd_signed_vma mask = -1;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ fetch_data(the_info, codep + 1);
+ op = *codep++;
+ mask = 0xff;
+ break;
+ case q_mode:
+ if (address_mode == mode_64bit)
+ {
+ op = get32s ();
+ break;
+ }
+ /* Fall through. */
+ case v_mode:
+ USED_REX (REX_W);
+ if (rex & REX_W)
+ op = get32s ();
+ else if (sizeflag & DFLAG)
+ {
+ op = get32 ();
+ mask = 0xffffffff;
+ }
+ else
+ {
+ op = get16 ();
+ mask = 0xfffff;
+ }
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ case w_mode:
+ mask = 0xfffff;
+ op = get16 ();
+ break;
+ case const_1_mode:
+ if (intel_syntax)
+ oappend ("1");
+ return;
+ default:
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
+ return;
+ }
+
+ op &= mask;
+ scratchbuf[0] = '$';
+ print_operand_value (scratchbuf + 1, sizeof(scratchbuf) - 1, 1, op);
+ oappend (scratchbuf + intel_syntax);
+ scratchbuf[0] = '\0';
+}
+
+static void
+OP_I64 (int bytemode, int sizeflag)
+{
+ bfd_signed_vma op;
+ bfd_signed_vma mask = -1;
+
+ if (address_mode != mode_64bit)
+ {
+ OP_I (bytemode, sizeflag);
+ return;
+ }
+
+ switch (bytemode)
+ {
+ case b_mode:
+ fetch_data(the_info, codep + 1);
+ op = *codep++;
+ mask = 0xff;
+ break;
+ case v_mode:
+ USED_REX (REX_W);
+ if (rex & REX_W)
+ op = get64 ();
+ else if (sizeflag & DFLAG)
+ {
+ op = get32 ();
+ mask = 0xffffffff;
+ }
+ else
+ {
+ op = get16 ();
+ mask = 0xfffff;
+ }
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ case w_mode:
+ mask = 0xfffff;
+ op = get16 ();
+ break;
+ default:
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
+ return;
+ }
+
+ op &= mask;
+ scratchbuf[0] = '$';
+ print_operand_value (scratchbuf + 1, sizeof(scratchbuf) - 1, 1, op);
+ oappend (scratchbuf + intel_syntax);
+ scratchbuf[0] = '\0';
+}
+
+static void
+OP_sI (int bytemode, int sizeflag)
+{
+ bfd_signed_vma op;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ fetch_data(the_info, codep + 1);
+ op = *codep++;
+ if ((op & 0x80) != 0)
+ op -= 0x100;
+ break;
+ case v_mode:
+ USED_REX (REX_W);
+ if (rex & REX_W)
+ op = get32s ();
+ else if (sizeflag & DFLAG)
+ {
+ op = get32s ();
+ }
+ else
+ {
+ op = get16 ();
+ if ((op & 0x8000) != 0)
+ op -= 0x10000;
+ }
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ case w_mode:
+ op = get16 ();
+ if ((op & 0x8000) != 0)
+ op -= 0x10000;
+ break;
+ default:
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
+ return;
+ }
+
+ scratchbuf[0] = '$';
+ print_operand_value (scratchbuf + 1, sizeof(scratchbuf) - 1, 1, op);
+ oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_J (int bytemode, int sizeflag)
+{
+ bfd_vma disp;
+ bfd_vma mask = -1;
+ bfd_vma segment = 0;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ fetch_data(the_info, codep + 1);
+ disp = *codep++;
+ if ((disp & 0x80) != 0)
+ disp -= 0x100;
+ break;
+ case v_mode:
+ if ((sizeflag & DFLAG) || (rex & REX_W))
+ disp = get32s ();
+ else
+ {
+ disp = get16 ();
+ if ((disp & 0x8000) != 0)
+ disp -= 0x10000;
+ /* In 16bit mode, address is wrapped around at 64k within
+ the same segment. Otherwise, a data16 prefix on a jump
+ instruction means that the pc is masked to 16 bits after
+ the displacement is added! */
+ mask = 0xffff;
+ if ((prefixes & PREFIX_DATA) == 0)
+ segment = ((start_pc + codep - start_codep)
+ & ~((bfd_vma) 0xffff));
+ }
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ default:
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
+ return;
+ }
+ disp = ((start_pc + codep - start_codep + disp) & mask) | segment;
+ set_op (disp, 0);
+ print_operand_value (scratchbuf, sizeof(scratchbuf), 1, disp);
+ oappend (scratchbuf);
+}
+
+static void
+OP_SEG (int bytemode, int sizeflag)
+{
+ if (bytemode == w_mode)
+ oappend (names_seg[modrm.reg]);
+ else
+ OP_E (modrm.mod == 3 ? bytemode : w_mode, sizeflag);
+}
+
+static void
+OP_DIR (int dummy ATTRIBUTE_UNUSED, int sizeflag)
+{
+ int seg, offset;
+
+ if (sizeflag & DFLAG)
+ {
+ offset = get32 ();
+ seg = get16 ();
+ }
+ else
+ {
+ offset = get16 ();
+ seg = get16 ();
+ }
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ if (intel_syntax)
+ snprintf (scratchbuf, sizeof(scratchbuf), "0x%x:0x%x", seg, offset);
+ else
+ snprintf (scratchbuf, sizeof(scratchbuf), "$0x%x,$0x%x", seg, offset);
+ oappend (scratchbuf);
+}
+
+static void
+OP_OFF (int bytemode, int sizeflag)
+{
+ bfd_vma off;
+
+ if (intel_syntax && (sizeflag & SUFFIX_ALWAYS))
+ intel_operand_size (bytemode, sizeflag);
+ append_seg ();
+
+ if ((sizeflag & AFLAG) || address_mode == mode_64bit)
+ off = get32 ();
+ else
+ off = get16 ();
+
+ if (intel_syntax)
+ {
+ if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
+ | PREFIX_ES | PREFIX_FS | PREFIX_GS)))
+ {
+ oappend (names_seg[ds_reg - es_reg]);
+ oappend (":");
+ }
+ }
+ print_operand_value (scratchbuf, sizeof(scratchbuf), 1, off);
+ oappend (scratchbuf);
+}
+
+static void
+OP_OFF64 (int bytemode, int sizeflag)
+{
+ bfd_vma off;
+
+ if (address_mode != mode_64bit
+ || (prefixes & PREFIX_ADDR))
+ {
+ OP_OFF (bytemode, sizeflag);
+ return;
+ }
+
+ if (intel_syntax && (sizeflag & SUFFIX_ALWAYS))
+ intel_operand_size (bytemode, sizeflag);
+ append_seg ();
+
+ off = get64 ();
+
+ if (intel_syntax)
+ {
+ if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
+ | PREFIX_ES | PREFIX_FS | PREFIX_GS)))
+ {
+ oappend (names_seg[ds_reg - es_reg]);
+ oappend (":");
+ }
+ }
+ print_operand_value (scratchbuf, sizeof(scratchbuf), 1, off);
+ oappend (scratchbuf);
+}
+
+static void
+ptr_reg (int code, int sizeflag)
+{
+ const char *s;
+
+ *obufp++ = open_char;
+ used_prefixes |= (prefixes & PREFIX_ADDR);
+ if (address_mode == mode_64bit)
+ {
+ if (!(sizeflag & AFLAG))
+ s = names32[code - eAX_reg];
+ else
+ s = names64[code - eAX_reg];
+ }
+ else if (sizeflag & AFLAG)
+ s = names32[code - eAX_reg];
+ else
+ s = names16[code - eAX_reg];
+ oappend (s);
+ *obufp++ = close_char;
+ *obufp = 0;
+}
+
+static void
+OP_ESreg (int code, int sizeflag)
+{
+ if (intel_syntax)
+ {
+ switch (codep[-1])
+ {
+ case 0x6d: /* insw/insl */
+ intel_operand_size (z_mode, sizeflag);
+ break;
+ case 0xa5: /* movsw/movsl/movsq */
+ case 0xa7: /* cmpsw/cmpsl/cmpsq */
+ case 0xab: /* stosw/stosl */
+ case 0xaf: /* scasw/scasl */
+ intel_operand_size (v_mode, sizeflag);
+ break;
+ default:
+ intel_operand_size (b_mode, sizeflag);
+ }
+ }
+ oappend ("%es:" + intel_syntax);
+ ptr_reg (code, sizeflag);
+}
+
+static void
+OP_DSreg (int code, int sizeflag)
+{
+ if (intel_syntax)
+ {
+ switch (codep[-1])
+ {
+ case 0x6f: /* outsw/outsl */
+ intel_operand_size (z_mode, sizeflag);
+ break;
+ case 0xa5: /* movsw/movsl/movsq */
+ case 0xa7: /* cmpsw/cmpsl/cmpsq */
+ case 0xad: /* lodsw/lodsl/lodsq */
+ intel_operand_size (v_mode, sizeflag);
+ break;
+ default:
+ intel_operand_size (b_mode, sizeflag);
+ }
+ }
+ if ((prefixes
+ & (PREFIX_CS
+ | PREFIX_DS
+ | PREFIX_SS
+ | PREFIX_ES
+ | PREFIX_FS
+ | PREFIX_GS)) == 0)
+ prefixes |= PREFIX_DS;
+ append_seg ();
+ ptr_reg (code, sizeflag);
+}
+
+static void
+OP_C (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+ int add = 0;
+ if (rex & REX_R)
+ {
+ USED_REX (REX_R);
+ add = 8;
+ }
+ else if (address_mode != mode_64bit && (prefixes & PREFIX_LOCK))
+ {
+ used_prefixes |= PREFIX_LOCK;
+ add = 8;
+ }
+ snprintf (scratchbuf, sizeof(scratchbuf), "%%cr%d", modrm.reg + add);
+ oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_D (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+ int add = 0;
+ USED_REX (REX_R);
+ if (rex & REX_R)
+ add = 8;
+ if (intel_syntax)
+ snprintf (scratchbuf, sizeof(scratchbuf), "db%d", modrm.reg + add);
+ else
+ snprintf (scratchbuf, sizeof(scratchbuf), "%%db%d", modrm.reg + add);
+ oappend (scratchbuf);
+}
+
+static void
+OP_T (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+ snprintf (scratchbuf, sizeof(scratchbuf), "%%tr%d", modrm.reg);
+ oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_R (int bytemode, int sizeflag)
+{
+ if (modrm.mod == 3)
+ OP_E (bytemode, sizeflag);
+ else
+ BadOp ();
+}
+
+static void
+OP_MMX (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ if (prefixes & PREFIX_DATA)
+ {
+ int add = 0;
+ USED_REX (REX_R);
+ if (rex & REX_R)
+ add = 8;
+ snprintf (scratchbuf, sizeof(scratchbuf), "%%xmm%d", modrm.reg + add);
+ }
+ else
+ snprintf (scratchbuf, sizeof(scratchbuf), "%%mm%d", modrm.reg);
+ oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_XMM (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+ int add = 0;
+ USED_REX (REX_R);
+ if (rex & REX_R)
+ add = 8;
+ snprintf (scratchbuf, sizeof(scratchbuf), "%%xmm%d", modrm.reg + add);
+ oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_EM (int bytemode, int sizeflag)
+{
+ if (modrm.mod != 3)
+ {
+ if (intel_syntax && bytemode == v_mode)
+ {
+ bytemode = (prefixes & PREFIX_DATA) ? x_mode : q_mode;
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ }
+ OP_E (bytemode, sizeflag);
+ return;
+ }
+
+ /* Skip mod/rm byte. */
+ MODRM_CHECK;
+ codep++;
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ if (prefixes & PREFIX_DATA)
+ {
+ int add = 0;
+
+ USED_REX (REX_B);
+ if (rex & REX_B)
+ add = 8;
+ snprintf (scratchbuf, sizeof(scratchbuf), "%%xmm%d", modrm.rm + add);
+ }
+ else
+ snprintf (scratchbuf, sizeof(scratchbuf), "%%mm%d", modrm.rm);
+ oappend (scratchbuf + intel_syntax);
+}
+
+/* cvt* are the only instructions in sse2 which have
+ both SSE and MMX operands and also have 0x66 prefix
+ in their opcode. 0x66 was originally used to differentiate
+ between SSE and MMX instruction(operands). So we have to handle the
+ cvt* separately using OP_EMC and OP_MXC */
+static void
+OP_EMC (int bytemode, int sizeflag)
+{
+ if (modrm.mod != 3)
+ {
+ if (intel_syntax && bytemode == v_mode)
+ {
+ bytemode = (prefixes & PREFIX_DATA) ? x_mode : q_mode;
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ }
+ OP_E (bytemode, sizeflag);
+ return;
+ }
+
+ /* Skip mod/rm byte. */
+ MODRM_CHECK;
+ codep++;
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ snprintf (scratchbuf, sizeof(scratchbuf), "%%mm%d", modrm.rm);
+ oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_MXC (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ snprintf (scratchbuf, sizeof(scratchbuf), "%%mm%d", modrm.reg);
+ oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_EX (int bytemode, int sizeflag)
+{
+ int add = 0;
+ if (modrm.mod != 3)
+ {
+ OP_E (bytemode, sizeflag);
+ return;
+ }
+ USED_REX (REX_B);
+ if (rex & REX_B)
+ add = 8;
+
+ /* Skip mod/rm byte. */
+ MODRM_CHECK;
+ codep++;
+ snprintf (scratchbuf, sizeof(scratchbuf), "%%xmm%d", modrm.rm + add);
+ oappend (scratchbuf + intel_syntax);
+}
+
+static void
+OP_MS (int bytemode, int sizeflag)
+{
+ if (modrm.mod == 3)
+ OP_EM (bytemode, sizeflag);
+ else
+ BadOp ();
+}
+
+static void
+OP_XS (int bytemode, int sizeflag)
+{
+ if (modrm.mod == 3)
+ OP_EX (bytemode, sizeflag);
+ else
+ BadOp ();
+}
+
+static void
+OP_M (int bytemode, int sizeflag)
+{
+ if (modrm.mod == 3)
+ /* bad bound,lea,lds,les,lfs,lgs,lss,cmpxchg8b,vmptrst modrm */
+ BadOp ();
+ else
+ OP_E (bytemode, sizeflag);
+}
+
+static void
+OP_0f07 (int bytemode, int sizeflag)
+{
+ if (modrm.mod != 3 || modrm.rm != 0)
+ BadOp ();
+ else
+ OP_E (bytemode, sizeflag);
+}
+
+static void
+OP_0fae (int bytemode, int sizeflag)
+{
+ if (modrm.mod == 3)
+ {
+ if (modrm.reg == 7)
+ strcpy (obuf + strlen (obuf) - sizeof ("clflush") + 1, "sfence");
+
+ if (modrm.reg < 5 || modrm.rm != 0)
+ {
+ BadOp (); /* bad sfence, mfence, or lfence */
+ return;
+ }
+ }
+ else if (modrm.reg != 7)
+ {
+ BadOp (); /* bad clflush */
+ return;
+ }
+
+ OP_E (bytemode, sizeflag);
+}
+
+/* NOP is an alias of "xchg %ax,%ax" in 16bit mode, "xchg %eax,%eax" in
+ 32bit mode and "xchg %rax,%rax" in 64bit mode. */
+
+static void
+NOP_Fixup1 (int bytemode, int sizeflag)
+{
+ if ((prefixes & PREFIX_DATA) != 0
+ || (rex != 0
+ && rex != 0x48
+ && address_mode == mode_64bit))
+ OP_REG (bytemode, sizeflag);
+ else
+ strcpy (obuf, "nop");
+}
+
+static void
+NOP_Fixup2 (int bytemode, int sizeflag)
+{
+ if ((prefixes & PREFIX_DATA) != 0
+ || (rex != 0
+ && rex != 0x48
+ && address_mode == mode_64bit))
+ OP_IMREG (bytemode, sizeflag);
+}
+
+static const char *Suffix3DNow[] = {
+/* 00 */ NULL, NULL, NULL, NULL,
+/* 04 */ NULL, NULL, NULL, NULL,
+/* 08 */ NULL, NULL, NULL, NULL,
+/* 0C */ "pi2fw", "pi2fd", NULL, NULL,
+/* 10 */ NULL, NULL, NULL, NULL,
+/* 14 */ NULL, NULL, NULL, NULL,
+/* 18 */ NULL, NULL, NULL, NULL,
+/* 1C */ "pf2iw", "pf2id", NULL, NULL,
+/* 20 */ NULL, NULL, NULL, NULL,
+/* 24 */ NULL, NULL, NULL, NULL,
+/* 28 */ NULL, NULL, NULL, NULL,
+/* 2C */ NULL, NULL, NULL, NULL,
+/* 30 */ NULL, NULL, NULL, NULL,
+/* 34 */ NULL, NULL, NULL, NULL,
+/* 38 */ NULL, NULL, NULL, NULL,
+/* 3C */ NULL, NULL, NULL, NULL,
+/* 40 */ NULL, NULL, NULL, NULL,
+/* 44 */ NULL, NULL, NULL, NULL,
+/* 48 */ NULL, NULL, NULL, NULL,
+/* 4C */ NULL, NULL, NULL, NULL,
+/* 50 */ NULL, NULL, NULL, NULL,
+/* 54 */ NULL, NULL, NULL, NULL,
+/* 58 */ NULL, NULL, NULL, NULL,
+/* 5C */ NULL, NULL, NULL, NULL,
+/* 60 */ NULL, NULL, NULL, NULL,
+/* 64 */ NULL, NULL, NULL, NULL,
+/* 68 */ NULL, NULL, NULL, NULL,
+/* 6C */ NULL, NULL, NULL, NULL,
+/* 70 */ NULL, NULL, NULL, NULL,
+/* 74 */ NULL, NULL, NULL, NULL,
+/* 78 */ NULL, NULL, NULL, NULL,
+/* 7C */ NULL, NULL, NULL, NULL,
+/* 80 */ NULL, NULL, NULL, NULL,
+/* 84 */ NULL, NULL, NULL, NULL,
+/* 88 */ NULL, NULL, "pfnacc", NULL,
+/* 8C */ NULL, NULL, "pfpnacc", NULL,
+/* 90 */ "pfcmpge", NULL, NULL, NULL,
+/* 94 */ "pfmin", NULL, "pfrcp", "pfrsqrt",
+/* 98 */ NULL, NULL, "pfsub", NULL,
+/* 9C */ NULL, NULL, "pfadd", NULL,
+/* A0 */ "pfcmpgt", NULL, NULL, NULL,
+/* A4 */ "pfmax", NULL, "pfrcpit1", "pfrsqit1",
+/* A8 */ NULL, NULL, "pfsubr", NULL,
+/* AC */ NULL, NULL, "pfacc", NULL,
+/* B0 */ "pfcmpeq", NULL, NULL, NULL,
+/* B4 */ "pfmul", NULL, "pfrcpit2", "pmulhrw",
+/* B8 */ NULL, NULL, NULL, "pswapd",
+/* BC */ NULL, NULL, NULL, "pavgusb",
+/* C0 */ NULL, NULL, NULL, NULL,
+/* C4 */ NULL, NULL, NULL, NULL,
+/* C8 */ NULL, NULL, NULL, NULL,
+/* CC */ NULL, NULL, NULL, NULL,
+/* D0 */ NULL, NULL, NULL, NULL,
+/* D4 */ NULL, NULL, NULL, NULL,
+/* D8 */ NULL, NULL, NULL, NULL,
+/* DC */ NULL, NULL, NULL, NULL,
+/* E0 */ NULL, NULL, NULL, NULL,
+/* E4 */ NULL, NULL, NULL, NULL,
+/* E8 */ NULL, NULL, NULL, NULL,
+/* EC */ NULL, NULL, NULL, NULL,
+/* F0 */ NULL, NULL, NULL, NULL,
+/* F4 */ NULL, NULL, NULL, NULL,
+/* F8 */ NULL, NULL, NULL, NULL,
+/* FC */ NULL, NULL, NULL, NULL,
+};
+
+static void
+OP_3DNowSuffix (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+ const char *mnemonic;
+
+ fetch_data(the_info, codep + 1);
+ /* AMD 3DNow! instructions are specified by an opcode suffix in the
+ place where an 8-bit immediate would normally go. ie. the last
+ byte of the instruction. */
+ obufp = obuf + strlen (obuf);
+ mnemonic = Suffix3DNow[*codep++ & 0xff];
+ if (mnemonic)
+ oappend (mnemonic);
+ else
+ {
+ /* Since a variable sized modrm/sib chunk is between the start
+ of the opcode (0x0f0f) and the opcode suffix, we need to do
+ all the modrm processing first, and don't know until now that
+ we have a bad opcode. This necessitates some cleaning up. */
+ op_out[0][0] = '\0';
+ op_out[1][0] = '\0';
+ BadOp ();
+ }
+}
+
+static const char *simd_cmp_op[] = {
+ "eq",
+ "lt",
+ "le",
+ "unord",
+ "neq",
+ "nlt",
+ "nle",
+ "ord"
+};
+
+static void
+OP_SIMD_Suffix (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+ unsigned int cmp_type;
+
+ fetch_data(the_info, codep + 1);
+ obufp = obuf + strlen (obuf);
+ cmp_type = *codep++ & 0xff;
+ if (cmp_type < 8)
+ {
+ char suffix1 = 'p', suffix2 = 's';
+ used_prefixes |= (prefixes & PREFIX_REPZ);
+ if (prefixes & PREFIX_REPZ)
+ suffix1 = 's';
+ else
+ {
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ if (prefixes & PREFIX_DATA)
+ suffix2 = 'd';
+ else
+ {
+ used_prefixes |= (prefixes & PREFIX_REPNZ);
+ if (prefixes & PREFIX_REPNZ)
+ suffix1 = 's', suffix2 = 'd';
+ }
+ }
+ snprintf (scratchbuf, sizeof(scratchbuf), "cmp%s%c%c",
+ simd_cmp_op[cmp_type], suffix1, suffix2);
+ used_prefixes |= (prefixes & PREFIX_REPZ);
+ oappend (scratchbuf);
+ }
+ else
+ {
+ /* We have a bad extension byte. Clean up. */
+ op_out[0][0] = '\0';
+ op_out[1][0] = '\0';
+ BadOp ();
+ }
+}
+
+static void
+SIMD_Fixup (int extrachar, int sizeflag ATTRIBUTE_UNUSED)
+{
+ /* Change movlps/movhps to movhlps/movlhps for 2 register operand
+ forms of these instructions. */
+ if (modrm.mod == 3)
+ {
+ char *p = obuf + strlen (obuf);
+ *(p + 1) = '\0';
+ *p = *(p - 1);
+ *(p - 1) = *(p - 2);
+ *(p - 2) = *(p - 3);
+ *(p - 3) = extrachar;
+ }
+}
+
+static void
+PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
+{
+ if (modrm.mod == 3 && modrm.reg == 1 && modrm.rm <= 1)
+ {
+ /* Override "sidt". */
+ size_t olen = strlen (obuf);
+ char *p = obuf + olen - 4;
+ const char * const *names = (address_mode == mode_64bit
+ ? names64 : names32);
+
+ /* We might have a suffix when disassembling with -Msuffix. */
+ if (*p == 'i')
+ --p;
+
+ /* Remove "addr16/addr32" if we aren't in Intel mode. */
+ if (!intel_syntax
+ && (prefixes & PREFIX_ADDR)
+ && olen >= (4 + 7)
+ && *(p - 1) == ' '
+ && strncmp (p - 7, "addr", 4) == 0
+ && (strncmp (p - 3, "16", 2) == 0
+ || strncmp (p - 3, "32", 2) == 0))
+ p -= 7;
+
+ if (modrm.rm)
+ {
+ /* mwait %eax,%ecx */
+ strcpy (p, "mwait");
+ if (!intel_syntax)
+ strcpy (op_out[0], names[0]);
+ }
+ else
+ {
+ /* monitor %eax,%ecx,%edx" */
+ strcpy (p, "monitor");
+ if (!intel_syntax)
+ {
+ const char * const *op1_names;
+ if (!(prefixes & PREFIX_ADDR))
+ op1_names = (address_mode == mode_16bit
+ ? names16 : names);
+ else
+ {
+ op1_names = (address_mode != mode_32bit
+ ? names32 : names16);
+ used_prefixes |= PREFIX_ADDR;
+ }
+ strcpy (op_out[0], op1_names[0]);
+ strcpy (op_out[2], names[2]);
+ }
+ }
+ if (!intel_syntax)
+ {
+ strcpy (op_out[1], names[1]);
+ two_source_ops = 1;
+ }
+
+ codep++;
+ }
+ else
+ OP_M (0, sizeflag);
+}
+
+static void
+SVME_Fixup (int bytemode, int sizeflag)
+{
+ const char *alt;
+ char *p;
+
+ switch (*codep)
+ {
+ case 0xd8:
+ alt = "vmrun";
+ break;
+ case 0xd9:
+ alt = "vmmcall";
+ break;
+ case 0xda:
+ alt = "vmload";
+ break;
+ case 0xdb:
+ alt = "vmsave";
+ break;
+ case 0xdc:
+ alt = "stgi";
+ break;
+ case 0xdd:
+ alt = "clgi";
+ break;
+ case 0xde:
+ alt = "skinit";
+ break;
+ case 0xdf:
+ alt = "invlpga";
+ break;
+ default:
+ OP_M (bytemode, sizeflag);
+ return;
+ }
+ /* Override "lidt". */
+ p = obuf + strlen (obuf) - 4;
+ /* We might have a suffix. */
+ if (*p == 'i')
+ --p;
+ strcpy (p, alt);
+ if (!(prefixes & PREFIX_ADDR))
+ {
+ ++codep;
+ return;
+ }
+ used_prefixes |= PREFIX_ADDR;
+ switch (*codep++)
+ {
+ case 0xdf:
+ strcpy (op_out[1], names32[1]);
+ two_source_ops = 1;
+ /* Fall through. */
+ case 0xd8:
+ case 0xda:
+ case 0xdb:
+ *obufp++ = open_char;
+ if (address_mode == mode_64bit || (sizeflag & AFLAG))
+ alt = names32[0];
+ else
+ alt = names16[0];
+ strcpy (obufp, alt);
+ obufp += strlen (alt);
+ *obufp++ = close_char;
+ *obufp = '\0';
+ break;
+ }
+}
+
+static void
+INVLPG_Fixup (int bytemode, int sizeflag)
+{
+ const char *alt;
+
+ switch (*codep)
+ {
+ case 0xf8:
+ alt = "swapgs";
+ break;
+ case 0xf9:
+ alt = "rdtscp";
+ break;
+ default:
+ OP_M (bytemode, sizeflag);
+ return;
+ }
+ /* Override "invlpg". */
+ strcpy (obuf + strlen (obuf) - 6, alt);
+ codep++;
+}
+
+static void
+BadOp (void)
+{
+ /* Throw away prefixes and 1st. opcode byte. */
+ codep = insn_codep + 1;
+ oappend ("(bad)");
+}
+
+static void
+VMX_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
+{
+ if (modrm.mod == 3
+ && modrm.reg == 0
+ && modrm.rm >=1
+ && modrm.rm <= 4)
+ {
+ /* Override "sgdt". */
+ char *p = obuf + strlen (obuf) - 4;
+
+ /* We might have a suffix when disassembling with -Msuffix. */
+ if (*p == 'g')
+ --p;
+
+ switch (modrm.rm)
+ {
+ case 1:
+ strcpy (p, "vmcall");
+ break;
+ case 2:
+ strcpy (p, "vmlaunch");
+ break;
+ case 3:
+ strcpy (p, "vmresume");
+ break;
+ case 4:
+ strcpy (p, "vmxoff");
+ break;
+ }
+
+ codep++;
+ }
+ else
+ OP_E (0, sizeflag);
+}
+
+static void
+OP_VMX (int bytemode, int sizeflag)
+{
+ used_prefixes |= (prefixes & (PREFIX_DATA | PREFIX_REPZ));
+ if (prefixes & PREFIX_DATA)
+ strcpy (obuf, "vmclear");
+ else if (prefixes & PREFIX_REPZ)
+ strcpy (obuf, "vmxon");
+ else
+ strcpy (obuf, "vmptrld");
+ OP_E (bytemode, sizeflag);
+}
+
+static void
+REP_Fixup (int bytemode, int sizeflag)
+{
+ /* The 0xf3 prefix should be displayed as "rep" for ins, outs, movs,
+ lods and stos. */
+ size_t ilen = 0;
+
+ if (prefixes & PREFIX_REPZ)
+ switch (*insn_codep)
+ {
+ case 0x6e: /* outsb */
+ case 0x6f: /* outsw/outsl */
+ case 0xa4: /* movsb */
+ case 0xa5: /* movsw/movsl/movsq */
+ if (!intel_syntax)
+ ilen = 5;
+ else
+ ilen = 4;
+ break;
+ case 0xaa: /* stosb */
+ case 0xab: /* stosw/stosl/stosq */
+ case 0xac: /* lodsb */
+ case 0xad: /* lodsw/lodsl/lodsq */
+ if (!intel_syntax && (sizeflag & SUFFIX_ALWAYS))
+ ilen = 5;
+ else
+ ilen = 4;
+ break;
+ case 0x6c: /* insb */
+ case 0x6d: /* insl/insw */
+ if (!intel_syntax)
+ ilen = 4;
+ else
+ ilen = 3;
+ break;
+ default:
+ abort ();
+ break;
+ }
+
+ if (ilen != 0)
+ {
+ size_t olen;
+ char *p;
+
+ olen = strlen (obuf);
+ p = obuf + olen - ilen - 1 - 4;
+ /* Handle "repz [addr16|addr32]". */
+ if ((prefixes & PREFIX_ADDR))
+ p -= 1 + 6;
+
+ memmove (p + 3, p + 4, olen - (p + 3 - obuf));
+ }
+
+ switch (bytemode)
+ {
+ case al_reg:
+ case eAX_reg:
+ case indir_dx_reg:
+ OP_IMREG (bytemode, sizeflag);
+ break;
+ case eDI_reg:
+ OP_ESreg (bytemode, sizeflag);
+ break;
+ case eSI_reg:
+ OP_DSreg (bytemode, sizeflag);
+ break;
+ default:
+ abort ();
+ break;
+ }
+}
+
+static void
+CMPXCHG8B_Fixup (int bytemode, int sizeflag)
+{
+ USED_REX (REX_W);
+ if (rex & REX_W)
+ {
+ /* Change cmpxchg8b to cmpxchg16b. */
+ char *p = obuf + strlen (obuf) - 2;
+ strcpy (p, "16b");
+ bytemode = o_mode;
+ }
+ OP_M (bytemode, sizeflag);
+}
+
+static void
+XMM_Fixup (int reg, int sizeflag ATTRIBUTE_UNUSED)
+{
+ snprintf (scratchbuf, sizeof(scratchbuf), "%%xmm%d", reg);
+ oappend (scratchbuf + intel_syntax);
+}
+
+static void
+CRC32_Fixup (int bytemode, int sizeflag)
+{
+ /* Add proper suffix to "crc32". */
+ char *p = obuf + strlen (obuf);
+
+ switch (bytemode)
+ {
+ case b_mode:
+ if (intel_syntax)
+ break;
+
+ *p++ = 'b';
+ break;
+ case v_mode:
+ if (intel_syntax)
+ break;
+
+ USED_REX (REX_W);
+ if (rex & REX_W)
+ *p++ = 'q';
+ else if (sizeflag & DFLAG)
+ *p++ = 'l';
+ else
+ *p++ = 'w';
+ used_prefixes |= (prefixes & PREFIX_DATA);
+ break;
+ default:
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
+ break;
+ }
+ *p = '\0';
+
+ if (modrm.mod == 3)
+ {
+ int add;
+
+ /* Skip mod/rm byte. */
+ MODRM_CHECK;
+ codep++;
+
+ USED_REX (REX_B);
+ add = (rex & REX_B) ? 8 : 0;
+ if (bytemode == b_mode)
+ {
+ USED_REX (0);
+ if (rex)
+ oappend (names8rex[modrm.rm + add]);
+ else
+ oappend (names8[modrm.rm + add]);
+ }
+ else
+ {
+ USED_REX (REX_W);
+ if (rex & REX_W)
+ oappend