aboutsummaryrefslogtreecommitdiff
path: root/opcodes
diff options
context:
space:
mode:
Diffstat (limited to 'opcodes')
-rw-r--r--opcodes/ChangeLog29
-rw-r--r--opcodes/Makefile.am31
-rw-r--r--opcodes/Makefile.in37
-rw-r--r--opcodes/aarch64-asm-2.c345
-rw-r--r--opcodes/aarch64-asm.c1268
-rw-r--r--opcodes/aarch64-asm.h73
-rw-r--r--opcodes/aarch64-dis-2.c7655
-rw-r--r--opcodes/aarch64-dis.c2392
-rw-r--r--opcodes/aarch64-dis.h94
-rw-r--r--opcodes/aarch64-gen.c1317
-rw-r--r--opcodes/aarch64-opc-2.c195
-rw-r--r--opcodes/aarch64-opc.c3074
-rw-r--r--opcodes/aarch64-opc.h392
-rw-r--r--opcodes/aarch64-tbl.h2253
-rwxr-xr-xopcodes/configure1
-rw-r--r--opcodes/configure.in1
-rw-r--r--opcodes/disassemble.c15
17 files changed, 19164 insertions, 8 deletions
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index 4379c1c..91a0dee 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,32 @@
+2012-08-13 Ian Bolton <ian.bolton@arm.com>
+ Laurent Desnogues <laurent.desnogues@arm.com>
+ Jim MacArthur <jim.macarthur@arm.com>
+ Marcus Shawcroft <marcus.shawcroft@arm.com>
+ Nigel Stephens <nigel.stephens@arm.com>
+ Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+ Richard Earnshaw <rearnsha@arm.com>
+ Sofiane Naci <sofiane.naci@arm.com>
+ Tejas Belagod <tejas.belagod@arm.com>
+ Yufeng Zhang <yufeng.zhang@arm.com>
+
+ * Makefile.am: Add AArch64.
+ * Makefile.in: Regenerate.
+ * aarch64-asm.c: New file.
+ * aarch64-asm.h: New file.
+ * aarch64-dis.c: New file.
+ * aarch64-dis.h: New file.
+ * aarch64-gen.c: New file.
+ * aarch64-opc.c: New file.
+ * aarch64-opc.h: New file.
+ * aarch64-tbl.h: New file.
+ * configure.in: Add AArch64.
+ * configure: Regenerate.
+ * disassemble.c: Add AArch64.
+ * aarch64-asm-2.c: New file (automatically generated).
+ * aarch64-dis-2.c: New file (automatically generated).
+ * aarch64-opc-2.c: New file (automatically generated).
+ * po/POTFILES.in: Regenerate.
+
2012-08-13 Maciej W. Rozycki <macro@codesourcery.com>
* micromips-opc.c (micromips_opcodes): Update comment.
diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am
index f76776c..3e6ceeb 100644
--- a/opcodes/Makefile.am
+++ b/opcodes/Makefile.am
@@ -42,6 +42,7 @@ BUILD_LIB_DEPS = @BUILD_LIB_DEPS@
# Header files.
HFILES = \
+ aarch64-asm.h aarch64-dis.h aarch64-opc.h aarch64-tbl.h \
epiphany-desc.h epiphany-opc.h \
fr30-desc.h fr30-opc.h \
frv-desc.h frv-opc.h \
@@ -74,6 +75,12 @@ HFILES = \
# C source files that correspond to .o's ending up in libopcodes
# for all machines.
TARGET_LIBOPCODES_CFILES = \
+ aarch64-asm.c \
+ aarch64-asm-2.c \
+ aarch64-dis.c \
+ aarch64-dis-2.c \
+ aarch64-opc.c \
+ aarch64-opc-2.c \
alpha-dis.c \
alpha-opc.c \
arc-dis.c \
@@ -250,6 +257,7 @@ LIBOPCODES_CFILES = \
# C source files that correspond to .o's.
CFILES = \
$(LIBOPCODES_CFILES) \
+ aarch64-gen.c \
i386-gen.c \
ia64-asmtab.c \
ia64-gen.c \
@@ -481,15 +489,30 @@ stamp-xstormy16: $(CGENDEPS) $(CPUDIR)/xstormy16.cpu $(CPUDIR)/xstormy16.opc
$(MAKE) run-cgen arch=xstormy16 prefix=xstormy16 options= \
archfile=$(CPUDIR)/xstormy16.cpu opcfile=$(CPUDIR)/xstormy16.opc extrafiles=
-MOSTLYCLEANFILES = i386-gen$(EXEEXT_FOR_BUILD) ia64-gen$(EXEEXT_FOR_BUILD) \
- s390-mkopc$(EXEEXT_FOR_BUILD) s390-opc.tab z8kgen$(EXEEXT_FOR_BUILD) \
- opc2c$(EXEEXT_FOR_BUILD)
+MOSTLYCLEANFILES = aarch64-gen$(EXEEXT_FOR_BUILD) i386-gen$(EXEEXT_FOR_BUILD) \
+ ia64-gen$(EXEEXT_FOR_BUILD) s390-mkopc$(EXEEXT_FOR_BUILD) s390-opc.tab \
+ z8kgen$(EXEEXT_FOR_BUILD) opc2c$(EXEEXT_FOR_BUILD)
-MAINTAINERCLEANFILES = $(srcdir)/i386-tbl.h $(srcdir)/i386-init.h \
+MAINTAINERCLEANFILES = $(srcdir)/aarch64-asm-2.c $(srcdir)/aarch64-dis-2.c \
+ $(srcdir)/aarch64-opc-2.c $(srcdir)/i386-tbl.h $(srcdir)/i386-init.h \
$(srcdir)/ia64-asmtab.c $(srcdir)/z8k-opc.h \
$(srcdir)/rl78-decode.c \
$(srcdir)/rx-decode.c
+aarch64-gen$(EXEEXT_FOR_BUILD): aarch64-gen.o $(BUILD_LIB_DEPS)
+ $(LINK_FOR_BUILD) aarch64-gen.o $(BUILD_LIBS)
+
+aarch64-gen.o: aarch64-gen.c $(BFD_H) $(INCDIR)/getopt.h $(INCDIR)/libiberty.h\
+ $(INCDIR)/opcode/aarch64.h config.h aarch64-opc.h aarch64-tbl.h
+ $(COMPILE_FOR_BUILD) -c $(srcdir)/aarch64-gen.c
+
+$(srcdir)/aarch64-asm-2.c: @MAINT@ aarch64-gen$(exeext_for_build)
+ ./aarch64-gen$(exeext_for_build) --gen-asm > $@
+$(srcdir)/aarch64-dis-2.c: @MAINT@ aarch64-gen$(exeext_for_build)
+ ./aarch64-gen$(exeext_for_build) --gen-dis > $@
+$(srcdir)/aarch64-opc-2.c: @MAINT@ aarch64-gen$(exeext_for_build)
+ ./aarch64-gen$(exeext_for_build) --gen-opc > $@
+
i386-gen$(EXEEXT_FOR_BUILD): i386-gen.o $(BUILD_LIB_DEPS)
$(LINK_FOR_BUILD) i386-gen.o $(BUILD_LIBS)
diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in
index f51c98d..56d4734 100644
--- a/opcodes/Makefile.in
+++ b/opcodes/Makefile.in
@@ -312,6 +312,7 @@ BFD_H = ../bfd/bfd.h
# Header files.
HFILES = \
+ aarch64-asm.h aarch64-dis.h aarch64-opc.h aarch64-tbl.h \
epiphany-desc.h epiphany-opc.h \
fr30-desc.h fr30-opc.h \
frv-desc.h frv-opc.h \
@@ -345,6 +346,12 @@ HFILES = \
# C source files that correspond to .o's ending up in libopcodes
# for all machines.
TARGET_LIBOPCODES_CFILES = \
+ aarch64-asm.c \
+ aarch64-asm-2.c \
+ aarch64-dis.c \
+ aarch64-dis-2.c \
+ aarch64-opc.c \
+ aarch64-opc-2.c \
alpha-dis.c \
alpha-opc.c \
arc-dis.c \
@@ -523,6 +530,7 @@ LIBOPCODES_CFILES = \
# C source files that correspond to .o's.
CFILES = \
$(LIBOPCODES_CFILES) \
+ aarch64-gen.c \
i386-gen.c \
ia64-asmtab.c \
ia64-gen.c \
@@ -605,11 +613,12 @@ CGEN_CPUS = epiphany fr30 frv ip2k iq2000 lm32 m32c m32r mep mt openrisc xc16x x
@CGEN_MAINT_TRUE@XC16X_DEPS = stamp-xc16x
@CGEN_MAINT_FALSE@XSTORMY16_DEPS =
@CGEN_MAINT_TRUE@XSTORMY16_DEPS = stamp-xstormy16
-MOSTLYCLEANFILES = i386-gen$(EXEEXT_FOR_BUILD) ia64-gen$(EXEEXT_FOR_BUILD) \
- s390-mkopc$(EXEEXT_FOR_BUILD) s390-opc.tab z8kgen$(EXEEXT_FOR_BUILD) \
- opc2c$(EXEEXT_FOR_BUILD)
+MOSTLYCLEANFILES = aarch64-gen$(EXEEXT_FOR_BUILD) i386-gen$(EXEEXT_FOR_BUILD) \
+ ia64-gen$(EXEEXT_FOR_BUILD) s390-mkopc$(EXEEXT_FOR_BUILD) s390-opc.tab \
+ z8kgen$(EXEEXT_FOR_BUILD) opc2c$(EXEEXT_FOR_BUILD)
-MAINTAINERCLEANFILES = $(srcdir)/i386-tbl.h $(srcdir)/i386-init.h \
+MAINTAINERCLEANFILES = $(srcdir)/aarch64-asm-2.c $(srcdir)/aarch64-dis-2.c \
+ $(srcdir)/aarch64-opc-2.c $(srcdir)/i386-tbl.h $(srcdir)/i386-init.h \
$(srcdir)/ia64-asmtab.c $(srcdir)/z8k-opc.h \
$(srcdir)/rl78-decode.c \
$(srcdir)/rx-decode.c
@@ -730,6 +739,12 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aarch64-asm-2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aarch64-asm.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aarch64-dis-2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aarch64-dis.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aarch64-opc-2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aarch64-opc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alpha-dis.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alpha-opc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arc-dis.Plo@am__quote@
@@ -1345,6 +1360,20 @@ stamp-xstormy16: $(CGENDEPS) $(CPUDIR)/xstormy16.cpu $(CPUDIR)/xstormy16.opc
$(MAKE) run-cgen arch=xstormy16 prefix=xstormy16 options= \
archfile=$(CPUDIR)/xstormy16.cpu opcfile=$(CPUDIR)/xstormy16.opc extrafiles=
+aarch64-gen$(EXEEXT_FOR_BUILD): aarch64-gen.o $(BUILD_LIB_DEPS)
+ $(LINK_FOR_BUILD) aarch64-gen.o $(BUILD_LIBS)
+
+aarch64-gen.o: aarch64-gen.c $(BFD_H) $(INCDIR)/getopt.h $(INCDIR)/libiberty.h\
+ $(INCDIR)/opcode/aarch64.h config.h aarch64-opc.h aarch64-tbl.h
+ $(COMPILE_FOR_BUILD) -c $(srcdir)/aarch64-gen.c
+
+$(srcdir)/aarch64-asm-2.c: @MAINT@ aarch64-gen$(exeext_for_build)
+ ./aarch64-gen$(exeext_for_build) --gen-asm > $@
+$(srcdir)/aarch64-dis-2.c: @MAINT@ aarch64-gen$(exeext_for_build)
+ ./aarch64-gen$(exeext_for_build) --gen-dis > $@
+$(srcdir)/aarch64-opc-2.c: @MAINT@ aarch64-gen$(exeext_for_build)
+ ./aarch64-gen$(exeext_for_build) --gen-opc > $@
+
i386-gen$(EXEEXT_FOR_BUILD): i386-gen.o $(BUILD_LIB_DEPS)
$(LINK_FOR_BUILD) i386-gen.o $(BUILD_LIBS)
diff --git a/opcodes/aarch64-asm-2.c b/opcodes/aarch64-asm-2.c
new file mode 100644
index 0000000..b633b86
--- /dev/null
+++ b/opcodes/aarch64-asm-2.c
@@ -0,0 +1,345 @@
+/* This file is automatically generated by aarch64-gen. Do not edit! */
+/* Copyright 2012 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of the GNU opcodes library.
+
+ This library 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 3, or (at your option)
+ any later version.
+
+ It 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; see the file COPYING3. If not,
+ see <http://www.gnu.org/licenses/>. */
+
+#include "sysdep.h"
+#include "aarch64-asm.h"
+
+
+const aarch64_opcode *
+aarch64_find_real_opcode (const aarch64_opcode *opcode)
+{
+ /* Use the index as the key to locate the real opcode. */
+ int key = opcode - aarch64_opcode_table;
+ int value;
+ switch (key)
+ {
+ case 3: /* ngc */
+ value = 2; /* --> sbc. */
+ break;
+ case 5: /* ngcs */
+ value = 4; /* --> sbcs. */
+ break;
+ case 8: /* cmn */
+ value = 7; /* --> adds. */
+ break;
+ case 11: /* cmp */
+ value = 10; /* --> subs. */
+ break;
+ case 13: /* mov */
+ value = 12; /* --> add. */
+ break;
+ case 15: /* cmn */
+ value = 14; /* --> adds. */
+ break;
+ case 18: /* cmp */
+ value = 17; /* --> subs. */
+ break;
+ case 21: /* cmn */
+ value = 20; /* --> adds. */
+ break;
+ case 23: /* neg */
+ value = 22; /* --> sub. */
+ break;
+ case 26: /* negs */
+ case 25: /* cmp */
+ value = 24; /* --> subs. */
+ break;
+ case 139: /* mov */
+ value = 138; /* --> umov. */
+ break;
+ case 141: /* mov */
+ value = 140; /* --> ins. */
+ break;
+ case 143: /* mov */
+ value = 142; /* --> ins. */
+ break;
+ case 204: /* mvn */
+ value = 203; /* --> not. */
+ break;
+ case 259: /* mov */
+ value = 258; /* --> orr. */
+ break;
+ case 427: /* mov */
+ value = 426; /* --> dup. */
+ break;
+ case 494: /* sxtw */
+ case 493: /* sxth */
+ case 492: /* sxtb */
+ case 495: /* asr */
+ case 491: /* sbfx */
+ case 490: /* sbfiz */
+ value = 489; /* --> sbfm. */
+ break;
+ case 498: /* bfxil */
+ case 497: /* bfi */
+ value = 496; /* --> bfm. */
+ break;
+ case 503: /* uxth */
+ case 502: /* uxtb */
+ case 505: /* lsr */
+ case 504: /* lsl */
+ case 501: /* ubfx */
+ case 500: /* ubfiz */
+ value = 499; /* --> ubfm. */
+ break;
+ case 523: /* cset */
+ case 522: /* cinc */
+ value = 521; /* --> csinc. */
+ break;
+ case 526: /* csetm */
+ case 525: /* cinv */
+ value = 524; /* --> csinv. */
+ break;
+ case 528: /* cneg */
+ value = 527; /* --> csneg. */
+ break;
+ case 553: /* lsl */
+ value = 552; /* --> lslv. */
+ break;
+ case 555: /* lsr */
+ value = 554; /* --> lsrv. */
+ break;
+ case 557: /* asr */
+ value = 556; /* --> asrv. */
+ break;
+ case 559: /* ror */
+ value = 558; /* --> rorv. */
+ break;
+ case 561: /* mul */
+ value = 560; /* --> madd. */
+ break;
+ case 563: /* mneg */
+ value = 562; /* --> msub. */
+ break;
+ case 565: /* smull */
+ value = 564; /* --> smaddl. */
+ break;
+ case 567: /* smnegl */
+ value = 566; /* --> smsubl. */
+ break;
+ case 570: /* umull */
+ value = 569; /* --> umaddl. */
+ break;
+ case 572: /* umnegl */
+ value = 571; /* --> umsubl. */
+ break;
+ case 583: /* ror */
+ value = 582; /* --> extr. */
+ break;
+ case 683: /* strb */
+ value = 681; /* --> sturb. */
+ break;
+ case 684: /* ldrb */
+ value = 682; /* --> ldurb. */
+ break;
+ case 686: /* ldrsb */
+ value = 685; /* --> ldursb. */
+ break;
+ case 689: /* str */
+ value = 687; /* --> stur. */
+ break;
+ case 690: /* ldr */
+ value = 688; /* --> ldur. */
+ break;
+ case 693: /* strh */
+ value = 691; /* --> sturh. */
+ break;
+ case 694: /* ldrh */
+ value = 692; /* --> ldurh. */
+ break;
+ case 696: /* ldrsh */
+ value = 695; /* --> ldursh. */
+ break;
+ case 699: /* str */
+ value = 697; /* --> stur. */
+ break;
+ case 700: /* ldr */
+ value = 698; /* --> ldur. */
+ break;
+ case 702: /* ldrsw */
+ value = 701; /* --> ldursw. */
+ break;
+ case 704: /* prfm */
+ value = 703; /* --> prfum. */
+ break;
+ case 746: /* bic */
+ value = 745; /* --> and. */
+ break;
+ case 748: /* mov */
+ value = 747; /* --> orr. */
+ break;
+ case 751: /* tst */
+ value = 750; /* --> ands. */
+ break;
+ case 756: /* uxtw */
+ case 755: /* mov */
+ value = 754; /* --> orr. */
+ break;
+ case 758: /* mvn */
+ value = 757; /* --> orn. */
+ break;
+ case 762: /* tst */
+ value = 761; /* --> ands. */
+ break;
+ case 765: /* mov */
+ value = 764; /* --> movn. */
+ break;
+ case 767: /* mov */
+ value = 766; /* --> movz. */
+ break;
+ case 778: /* sevl */
+ case 777: /* sev */
+ case 776: /* wfi */
+ case 775: /* wfe */
+ case 774: /* yield */
+ case 773: /* nop */
+ value = 772; /* --> hint. */
+ break;
+ case 787: /* tlbi */
+ case 786: /* ic */
+ case 785: /* dc */
+ case 784: /* at */
+ value = 783; /* --> sys. */
+ break;
+ default: return NULL;
+ }
+
+ return aarch64_opcode_table + value;
+}
+
+const char*
+aarch64_insert_operand (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code, const aarch64_inst *inst)
+{
+ /* Use the index as the key. */
+ int key = self - aarch64_operands;
+ switch (key)
+ {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 34:
+ case 35:
+ return aarch64_ins_regno (self, info, code, inst);
+ case 11:
+ return aarch64_ins_reg_extended (self, info, code, inst);
+ case 12:
+ return aarch64_ins_reg_shifted (self, info, code, inst);
+ case 17:
+ return aarch64_ins_ft (self, info, code, inst);
+ case 27:
+ case 28:
+ case 29:
+ return aarch64_ins_reglane (self, info, code, inst);
+ case 30:
+ return aarch64_ins_reglist (self, info, code, inst);
+ case 31:
+ return aarch64_ins_ldst_reglist (self, info, code, inst);
+ case 32:
+ return aarch64_ins_ldst_reglist_r (self, info, code, inst);
+ case 33:
+ return aarch64_ins_ldst_elemlist (self, info, code, inst);
+ case 36:
+ case 45:
+ case 46:
+ case 47:
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57:
+ case 65:
+ case 66:
+ case 67:
+ case 68:
+ return aarch64_ins_imm (self, info, code, inst);
+ case 37:
+ case 38:
+ return aarch64_ins_advsimd_imm_shift (self, info, code, inst);
+ case 39:
+ case 40:
+ case 41:
+ return aarch64_ins_advsimd_imm_modified (self, info, code, inst);
+ case 58:
+ return aarch64_ins_limm (self, info, code, inst);
+ case 59:
+ return aarch64_ins_aimm (self, info, code, inst);
+ case 60:
+ return aarch64_ins_imm_half (self, info, code, inst);
+ case 61:
+ return aarch64_ins_fbits (self, info, code, inst);
+ case 63:
+ return aarch64_ins_cond (self, info, code, inst);
+ case 69:
+ case 75:
+ return aarch64_ins_addr_simple (self, info, code, inst);
+ case 70:
+ return aarch64_ins_addr_regoff (self, info, code, inst);
+ case 71:
+ case 72:
+ case 73:
+ return aarch64_ins_addr_simm (self, info, code, inst);
+ case 74:
+ return aarch64_ins_addr_uimm12 (self, info, code, inst);
+ case 76:
+ return aarch64_ins_simd_addr_post (self, info, code, inst);
+ case 77:
+ return aarch64_ins_sysreg (self, info, code, inst);
+ case 78:
+ return aarch64_ins_pstatefield (self, info, code, inst);
+ case 79:
+ case 80:
+ case 81:
+ case 82:
+ return aarch64_ins_sysins_op (self, info, code, inst);
+ case 83:
+ case 84:
+ return aarch64_ins_barrier (self, info, code, inst);
+ case 85:
+ return aarch64_ins_prfop (self, info, code, inst);
+ default: assert (0); abort ();
+ }
+}
diff --git a/opcodes/aarch64-asm.c b/opcodes/aarch64-asm.c
new file mode 100644
index 0000000..e10240a
--- /dev/null
+++ b/opcodes/aarch64-asm.c
@@ -0,0 +1,1268 @@
+/* aarch64-asm.c -- AArch64 assembler support.
+ Copyright 2012 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of the GNU opcodes library.
+
+ This library 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 3, or (at your option)
+ any later version.
+
+ It 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; see the file COPYING3. If not,
+ see <http://www.gnu.org/licenses/>. */
+
+#include "sysdep.h"
+#include <stdarg.h>
+#include "aarch64-asm.h"
+
+/* Utilities. */
+
+/* The unnamed arguments consist of the number of fields and information about
+ these fields where the VALUE will be inserted into CODE. MASK can be zero or
+ the base mask of the opcode.
+
+ N.B. the fields are required to be in such an order than the least signficant
+ field for VALUE comes the first, e.g. the <index> in
+ SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
+ is encoded in H:L:M in some cases, the the fields H:L:M should be passed in
+ the order of M, L, H. */
+
+static inline void
+insert_fields (aarch64_insn *code, aarch64_insn value, aarch64_insn mask, ...)
+{
+ uint32_t num;
+ const aarch64_field *field;
+ enum aarch64_field_kind kind;
+ va_list va;
+
+ va_start (va, mask);
+ num = va_arg (va, uint32_t);
+ assert (num <= 5);
+ while (num--)
+ {
+ kind = va_arg (va, enum aarch64_field_kind);
+ field = &fields[kind];
+ insert_field (kind, code, value, mask);
+ value >>= field->width;
+ }
+ va_end (va);
+}
+
+/* Operand inserters. */
+
+/* Insert register number. */
+const char *
+aarch64_ins_regno (const aarch64_operand *self, const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ insert_field (self->fields[0], code, info->reg.regno, 0);
+ return NULL;
+}
+
+/* Insert register number, index and/or other data for SIMD register element
+ operand, e.g. the last source operand in
+ SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]. */
+const char *
+aarch64_ins_reglane (const aarch64_operand *self, const aarch64_opnd_info *info,
+ aarch64_insn *code, const aarch64_inst *inst)
+{
+ /* regno */
+ insert_field (self->fields[0], code, info->reglane.regno, inst->opcode->mask);
+ /* index and/or type */
+ if (inst->opcode->iclass == asisdone || inst->opcode->iclass == asimdins)
+ {
+ int pos = info->qualifier - AARCH64_OPND_QLF_S_B;
+ if (info->type == AARCH64_OPND_En
+ && inst->opcode->operands[0] == AARCH64_OPND_Ed)
+ {
+ /* index2 for e.g. INS <Vd>.<Ts>[<index1>], <Vn>.<Ts>[<index2>]. */
+ assert (info->idx == 1); /* Vn */
+ aarch64_insn value = info->reglane.index << pos;
+ insert_field (FLD_imm4, code, value, 0);
+ }
+ else
+ {
+ /* index and type for e.g. DUP <V><d>, <Vn>.<T>[<index>].
+ imm5<3:0> <V>
+ 0000 RESERVED
+ xxx1 B
+ xx10 H
+ x100 S
+ 1000 D */
+ aarch64_insn value = ((info->reglane.index << 1) | 1) << pos;
+ insert_field (FLD_imm5, code, value, 0);
+ }
+ }
+ else
+ {
+ /* index for e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
+ or SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]. */
+ switch (info->qualifier)
+ {
+ case AARCH64_OPND_QLF_S_H:
+ /* H:L:M */
+ insert_fields (code, info->reglane.index, 0, 3, FLD_M, FLD_L, FLD_H);
+ break;
+ case AARCH64_OPND_QLF_S_S:
+ /* H:L */
+ insert_fields (code, info->reglane.index, 0, 2, FLD_L, FLD_H);
+ break;
+ case AARCH64_OPND_QLF_S_D:
+ /* H */
+ insert_field (FLD_H, code, info->reglane.index, 0);
+ break;
+ default:
+ assert (0);
+ }
+ }
+ return NULL;
+}
+
+/* Insert regno and len field of a register list operand, e.g. Vn in TBL. */
+const char *
+aarch64_ins_reglist (const aarch64_operand *self, const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* R */
+ insert_field (self->fields[0], code, info->reglist.first_regno, 0);
+ /* len */
+ insert_field (FLD_len, code, info->reglist.num_regs - 1, 0);
+ return NULL;
+}
+
+/* Insert Rt and opcode fields for a register list operand, e.g. Vt
+ in AdvSIMD load/store instructions. */
+const char *
+aarch64_ins_ldst_reglist (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst)
+{
+ aarch64_insn value;
+ /* Number of elements in each structure to be loaded/stored. */
+ unsigned num = get_opcode_dependent_value (inst->opcode);
+
+ /* Rt */
+ insert_field (FLD_Rt, code, info->reglist.first_regno, 0);
+ /* opcode */
+ switch (num)
+ {
+ case 1:
+ switch (info->reglist.num_regs)
+ {
+ case 1: value = 0x7; break;
+ case 2: value = 0xa; break;
+ case 3: value = 0x6; break;
+ case 4: value = 0x2; break;
+ default: assert (0);
+ }
+ break;
+ case 2:
+ value = info->reglist.num_regs == 4 ? 0x3 : 0x8;
+ break;
+ case 3:
+ value = 0x4;
+ break;
+ case 4:
+ value = 0x0;
+ break;
+ default:
+ assert (0);
+ }
+ insert_field (FLD_opcode, code, value, 0);
+
+ return NULL;
+}
+
+/* Insert Rt and S fields for a register list operand, e.g. Vt in AdvSIMD load
+ single structure to all lanes instructions. */
+const char *
+aarch64_ins_ldst_reglist_r (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst)
+{
+ aarch64_insn value;
+ /* The opcode dependent area stores the number of elements in
+ each structure to be loaded/stored. */
+ int is_ld1r = get_opcode_dependent_value (inst->opcode) == 1;
+
+ /* Rt */
+ insert_field (FLD_Rt, code, info->reglist.first_regno, 0);
+ /* S */
+ value = (aarch64_insn) 0;
+ if (is_ld1r && info->reglist.num_regs == 2)
+ /* OP_LD1R does not have alternating variant, but have "two consecutive"
+ instead. */
+ value = (aarch64_insn) 1;
+ insert_field (FLD_S, code, value, 0);
+
+ return NULL;
+}
+
+/* Insert Q, opcode<2:1>, S, size and Rt fields for a register element list
+ operand e.g. Vt in AdvSIMD load/store single element instructions. */
+const char *
+aarch64_ins_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ aarch64_field field = {0, 0};
+ aarch64_insn QSsize; /* fields Q:S:size. */
+ aarch64_insn opcodeh2; /* opcode<2:1> */
+
+ assert (info->reglist.has_index);
+
+ /* Rt */
+ insert_field (FLD_Rt, code, info->reglist.first_regno, 0);
+ /* Encode the index, opcode<2:1> and size. */
+ switch (info->qualifier)
+ {
+ case AARCH64_OPND_QLF_S_B:
+ /* Index encoded in "Q:S:size". */
+ QSsize = info->reglist.index;
+ opcodeh2 = 0x0;
+ break;
+ case AARCH64_OPND_QLF_S_H:
+ /* Index encoded in "Q:S:size<1>". */
+ QSsize = info->reglist.index << 1;
+ opcodeh2 = 0x1;
+ break;
+ case AARCH64_OPND_QLF_S_S:
+ /* Index encoded in "Q:S". */
+ QSsize = info->reglist.index << 2;
+ opcodeh2 = 0x2;
+ break;
+ case AARCH64_OPND_QLF_S_D:
+ /* Index encoded in "Q". */
+ QSsize = info->reglist.index << 3 | 0x1;
+ opcodeh2 = 0x2;
+ break;
+ default:
+ assert (0);
+ }
+ insert_fields (code, QSsize, 0, 3, FLD_vldst_size, FLD_S, FLD_Q);
+ gen_sub_field (FLD_asisdlso_opcode, 1, 2, &field);
+ insert_field_2 (&field, code, opcodeh2, 0);
+
+ return NULL;
+}
+
+/* Insert fields immh:immb and/or Q for e.g. the shift immediate in
+ SSHR <Vd>.<T>, <Vn>.<T>, #<shift>
+ or SSHR <V><d>, <V><n>, #<shift>. */
+const char *
+aarch64_ins_advsimd_imm_shift (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code, const aarch64_inst *inst)
+{
+ unsigned val = aarch64_get_qualifier_standard_value (info->qualifier);
+ aarch64_insn Q, imm;
+
+ if (inst->opcode->iclass == asimdshf)
+ {
+ /* Q
+ immh Q <T>
+ 0000 x SEE AdvSIMD modified immediate
+ 0001 0 8B
+ 0001 1 16B
+ 001x 0 4H
+ 001x 1 8H
+ 01xx 0 2S
+ 01xx 1 4S
+ 1xxx 0 RESERVED
+ 1xxx 1 2D */
+ Q = (val & 0x1) ? 1 : 0;
+ insert_field (FLD_Q, code, Q, inst->opcode->mask);
+ val >>= 1;
+ }
+
+ assert (info->type == AARCH64_OPND_IMM_VLSR
+ || info->type == AARCH64_OPND_IMM_VLSL);
+
+ if (info->type == AARCH64_OPND_IMM_VLSR)
+ /* immh:immb
+ immh <shift>
+ 0000 SEE AdvSIMD modified immediate
+ 0001 (16-UInt(immh:immb))
+ 001x (32-UInt(immh:immb))
+ 01xx (64-UInt(immh:immb))
+ 1xxx (128-UInt(immh:immb)) */
+ imm = (16 << (unsigned)val) - info->imm.value;
+ else
+ /* immh:immb
+ immh <shift>
+ 0000 SEE AdvSIMD modified immediate
+ 0001 (UInt(immh:immb)-8)
+ 001x (UInt(immh:immb)-16)
+ 01xx (UInt(immh:immb)-32)
+ 1xxx (UInt(immh:immb)-64) */
+ imm = info->imm.value + (8 << (unsigned)val);
+ insert_fields (code, imm, 0, 2, FLD_immb, FLD_immh);
+
+ return NULL;
+}
+
+/* Insert fields for e.g. the immediate operands in
+ BFM <Wd>, <Wn>, #<immr>, #<imms>. */
+const char *
+aarch64_ins_imm (const aarch64_operand *self, const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ int64_t imm;
+ /* Maximum of two fields to insert. */
+ assert (self->fields[2] == FLD_NIL);
+
+ imm = info->imm.value;
+ if (operand_need_shift_by_two (self))
+ imm >>= 2;
+ if (self->fields[1] == FLD_NIL)
+ insert_field (self->fields[0], code, imm, 0);
+ else
+ /* e.g. TBZ b5:b40. */
+ insert_fields (code, imm, 0, 2, self->fields[1], self->fields[0]);
+ return NULL;
+}
+
+/* Insert immediate and its shift amount for e.g. the last operand in
+ MOVZ <Wd>, #<imm16>{, LSL #<shift>}. */
+const char *
+aarch64_ins_imm_half (const aarch64_operand *self, const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* imm16 */
+ aarch64_ins_imm (self, info, code, inst);
+ /* hw */
+ insert_field (FLD_hw, code, info->shifter.amount >> 4, 0);
+ return NULL;
+}
+
+/* Insert cmode and "a:b:c:d:e:f:g:h" fields for e.g. the last operand in
+ MOVI <Vd>.<T>, #<imm8> {, LSL #<amount>}. */
+const char *
+aarch64_ins_advsimd_imm_modified (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ enum aarch64_opnd_qualifier opnd0_qualifier = inst->operands[0].qualifier;
+ uint64_t imm = info->imm.value;
+ enum aarch64_modifier_kind kind = info->shifter.kind;
+ int amount = info->shifter.amount;
+ aarch64_field field = {0, 0};
+
+ /* a:b:c:d:e:f:g:h */
+ if (!info->imm.is_fp && aarch64_get_qualifier_esize (opnd0_qualifier) == 8)
+ {
+ /* Either MOVI <Dd>, #<imm>
+ or MOVI <Vd>.2D, #<imm>.
+ <imm> is a 64-bit immediate
+ "aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh",
+ encoded in "a:b:c:d:e:f:g:h". */
+ imm = aarch64_shrink_expanded_imm8 (imm);
+ assert ((int)imm >= 0);
+ }
+ assert (imm <= 255);
+ insert_fields (code, imm, 0, 2, FLD_defgh, FLD_abc);
+
+ if (kind == AARCH64_MOD_NONE)
+ return NULL;
+
+ /* shift amount partially in cmode */
+ assert (kind == AARCH64_MOD_LSL || kind == AARCH64_MOD_MSL);
+ if (kind == AARCH64_MOD_LSL)
+ {
+ /* AARCH64_MOD_LSL: shift zeros. */
+ int esize = aarch64_get_qualifier_esize (opnd0_qualifier);
+ assert (esize == 4 || esize == 2);
+ amount >>= 3;
+ if (esize == 4)
+ gen_sub_field (FLD_cmode, 1, 2, &field); /* per word */
+ else
+ gen_sub_field (FLD_cmode, 1, 1, &field); /* per halfword */
+ }
+ else
+ {
+ /* AARCH64_MOD_MSL: shift ones. */
+ amount >>= 4;
+ gen_sub_field (FLD_cmode, 0, 1, &field); /* per word */
+ }
+ insert_field_2 (&field, code, amount, 0);
+
+ return NULL;
+}
+
+/* Insert #<fbits> for the immediate operand in fp fix-point instructions,
+ e.g. SCVTF <Dd>, <Wn>, #<fbits>. */
+const char *
+aarch64_ins_fbits (const aarch64_operand *self, const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ insert_field (self->fields[0], code, 64 - info->imm.value, 0);
+ return NULL;
+}
+
+/* Insert arithmetic immediate for e.g. the last operand in
+ SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}. */
+const char *
+aarch64_ins_aimm (const aarch64_operand *self, const aarch64_opnd_info *info,
+ aarch64_insn *code, const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* shift */
+ aarch64_insn value = info->shifter.amount ? 1 : 0;
+ insert_field (self->fields[0], code, value, 0);
+ /* imm12 (unsigned) */
+ insert_field (self->fields[1], code, info->imm.value, 0);
+ return NULL;
+}
+
+/* Insert logical/bitmask immediate for e.g. the last operand in
+ ORR <Wd|WSP>, <Wn>, #<imm>. */
+const char *
+aarch64_ins_limm (const aarch64_operand *self, const aarch64_opnd_info *info,
+ aarch64_insn *code, const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ aarch64_insn value;
+ uint64_t imm = info->imm.value;
+ int is32 = aarch64_get_qualifier_esize (inst->operands[0].qualifier) == 4;
+
+ if (inst->opcode->op == OP_BIC)
+ imm = ~imm;
+ if (aarch64_logical_immediate_p (imm, is32, &value) == FALSE)
+ /* The constraint check should have guaranteed this wouldn't happen. */
+ assert (0);
+
+ insert_fields (code, value, 0, 3, self->fields[2], self->fields[1],
+ self->fields[0]);
+ return NULL;
+}
+
+/* Encode Ft for e.g. STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]
+ or LDP <Qt1>, <Qt2>, [<Xn|SP>], #<imm>. */
+const char *
+aarch64_ins_ft (const aarch64_operand *self, const aarch64_opnd_info *info,
+ aarch64_insn *code, const aarch64_inst *inst)
+{
+ aarch64_insn value;
+
+ assert (info->idx == 0);
+
+ /* Rt */
+ aarch64_ins_regno (self, info, code, inst);
+ if (inst->opcode->iclass == ldstpair_indexed
+ || inst->opcode->iclass == ldstnapair_offs
+ || inst->opcode->iclass == ldstpair_off
+ || inst->opcode->iclass == loadlit)
+ {
+ /* size */
+ switch (info->qualifier)
+ {
+ case AARCH64_OPND_QLF_S_S: value = 0; break;
+ case AARCH64_OPND_QLF_S_D: value = 1; break;
+ case AARCH64_OPND_QLF_S_Q: value = 2; break;
+ default: assert (0);
+ }
+ insert_field (FLD_ldst_size, code, value, 0);
+ }
+ else
+ {
+ /* opc[1]:size */
+ value = aarch64_get_qualifier_standard_value (info->qualifier);
+ insert_fields (code, value, 0, 2, FLD_ldst_size, FLD_opc1);
+ }
+
+ return NULL;
+}
+
+/* Encode the address operand for e.g. STXRB <Ws>, <Wt>, [<Xn|SP>{,#0}]. */
+const char *
+aarch64_ins_addr_simple (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* Rn */
+ insert_field (FLD_Rn, code, info->addr.base_regno, 0);
+ return NULL;
+}
+
+/* Encode the address operand for e.g.
+ STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
+const char *
+aarch64_ins_addr_regoff (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ aarch64_insn S;
+ enum aarch64_modifier_kind kind = info->shifter.kind;
+
+ /* Rn */
+ insert_field (FLD_Rn, code, info->addr.base_regno, 0);
+ /* Rm */
+ insert_field (FLD_Rm, code, info->addr.offset.regno, 0);
+ /* option */
+ if (kind == AARCH64_MOD_LSL)
+ kind = AARCH64_MOD_UXTX; /* Trick to enable the table-driven. */
+ insert_field (FLD_option, code, aarch64_get_operand_modifier_value (kind), 0);
+ /* S */
+ if (info->qualifier != AARCH64_OPND_QLF_S_B)
+ S = info->shifter.amount != 0;
+ else
+ /* For STR <Bt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}},
+ S <amount>
+ 0 [absent]
+ 1 #0
+ Must be #0 if <extend> is explicitly LSL. */
+ S = info->shifter.operator_present && info->shifter.amount_present;
+ insert_field (FLD_S, code, S, 0);
+
+ return NULL;
+}
+
+/* Encode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>, #<simm>]!. */
+const char *
+aarch64_ins_addr_simm (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code, const aarch64_inst *inst)
+{
+ int imm;
+
+ /* Rn */
+ insert_field (FLD_Rn, code, info->addr.base_regno, 0);
+ /* simm (imm9 or imm7) */
+ imm = info->addr.offset.imm;
+ if (self->fields[0] == FLD_imm7)
+ /* scaled immediate in ld/st pair instructions.. */
+ imm >>= get_logsz (aarch64_get_qualifier_esize (info->qualifier));
+ insert_field (self->fields[0], code, imm, 0);
+ /* pre/post- index */
+ if (info->addr.writeback)
+ {
+ assert (inst->opcode->iclass != ldst_unscaled
+ && inst->opcode->iclass != ldstnapair_offs
+ && inst->opcode->iclass != ldstpair_off
+ && inst->opcode->iclass != ldst_unpriv);
+ assert (info->addr.preind != info->addr.postind);
+ if (info->addr.preind)
+ insert_field (self->fields[1], code, 1, 0);
+ }
+
+ return NULL;
+}
+
+/* Encode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>{, #<pimm>}]. */
+const char *
+aarch64_ins_addr_uimm12 (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ int shift = get_logsz (aarch64_get_qualifier_esize (info->qualifier));
+
+ /* Rn */
+ insert_field (self->fields[0], code, info->addr.base_regno, 0);
+ /* uimm12 */
+ insert_field (self->fields[1], code,info->addr.offset.imm >> shift, 0);
+ return NULL;
+}
+
+/* Encode the address operand for e.g.
+ LD1 {<Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>}, [<Xn|SP>], <Xm|#<amount>>. */
+const char *
+aarch64_ins_simd_addr_post (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* Rn */
+ insert_field (FLD_Rn, code, info->addr.base_regno, 0);
+ /* Rm | #<amount> */
+ if (info->addr.offset.is_reg)
+ insert_field (FLD_Rm, code, info->addr.offset.regno, 0);
+ else
+ insert_field (FLD_Rm, code, 0x1f, 0);
+ return NULL;
+}
+
+/* Encode the condition operand for e.g. CSEL <Xd>, <Xn>, <Xm>, <cond>. */
+const char *
+aarch64_ins_cond (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* cond */
+ insert_field (FLD_cond, code, info->cond->value, 0);
+ return NULL;
+}
+
+/* Encode the system register operand for e.g. MRS <Xt>, <systemreg>. */
+const char *
+aarch64_ins_sysreg (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* op0:op1:CRn:CRm:op2 */
+ insert_fields (code, info->sysreg, inst->opcode->mask, 5,
+ FLD_op2, FLD_CRm, FLD_CRn, FLD_op1, FLD_op0);
+ return NULL;
+}
+
+/* Encode the PSTATE field operand for e.g. MSR <pstatefield>, #<imm>. */
+const char *
+aarch64_ins_pstatefield (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* op1:op2 */
+ insert_fields (code, info->pstatefield, inst->opcode->mask, 2,
+ FLD_op2, FLD_op1);
+ return NULL;
+}
+
+/* Encode the system instruction op operand for e.g. AT <at_op>, <Xt>. */
+const char *
+aarch64_ins_sysins_op (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* op1:CRn:CRm:op2 */
+ insert_fields (code, info->sysins_op->value, inst->opcode->mask, 4,
+ FLD_op2, FLD_CRm, FLD_CRn, FLD_op1);
+ return NULL;
+}
+
+/* Encode the memory barrier option operand for e.g. DMB <option>|#<imm>. */
+
+const char *
+aarch64_ins_barrier (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* CRm */
+ insert_field (FLD_CRm, code, info->barrier->value, 0);
+ return NULL;
+}
+
+/* Encode the prefetch operation option operand for e.g.
+ PRFM <prfop>, [<Xn|SP>{, #<pimm>}]. */
+
+const char *
+aarch64_ins_prfop (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* prfop in Rt */
+ insert_field (FLD_Rt, code, info->prfop->value, 0);
+ return NULL;
+}
+
+/* Encode the extended register operand for e.g.
+ STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
+const char *
+aarch64_ins_reg_extended (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ enum aarch64_modifier_kind kind;
+
+ /* Rm */
+ insert_field (FLD_Rm, code, info->reg.regno, 0);
+ /* option */
+ kind = info->shifter.kind;
+ if (kind == AARCH64_MOD_LSL)
+ kind = info->qualifier == AARCH64_OPND_QLF_W
+ ? AARCH64_MOD_UXTW : AARCH64_MOD_UXTX;
+ insert_field (FLD_option, code, aarch64_get_operand_modifier_value (kind), 0);
+ /* imm3 */
+ insert_field (FLD_imm3, code, info->shifter.amount, 0);
+
+ return NULL;
+}
+
+/* Encode the shifted register operand for e.g.
+ SUBS <Xd>, <Xn>, <Xm> {, <shift> #<amount>}. */
+const char *
+aarch64_ins_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* Rm */
+ insert_field (FLD_Rm, code, info->reg.regno, 0);
+ /* shift */
+ insert_field (FLD_shift, code,
+ aarch64_get_operand_modifier_value (info->shifter.kind), 0);
+ /* imm6 */
+ insert_field (FLD_imm6, code, info->shifter.amount, 0);
+
+ return NULL;
+}
+
+/* Miscellaneous encoding functions. */
+
+/* Encode size[0], i.e. bit 22, for
+ e.g. FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
+
+static void
+encode_asimd_fcvt (aarch64_inst *inst)
+{
+ aarch64_insn value;
+ aarch64_field field = {0, 0};
+ enum aarch64_opnd_qualifier qualifier;
+
+ switch (inst->opcode->op)
+ {
+ case OP_FCVTN:
+ case OP_FCVTN2:
+ /* FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
+ qualifier = inst->operands[1].qualifier;
+ break;
+ case OP_FCVTL:
+ case OP_FCVTL2:
+ /* FCVTL<Q> <Vd>.<Ta>, <Vn>.<Tb>. */
+ qualifier = inst->operands[0].qualifier;
+ break;
+ default:
+ assert (0);
+ }
+ assert (qualifier == AARCH64_OPND_QLF_V_4S
+ || qualifier == AARCH64_OPND_QLF_V_2D);
+ value = (qualifier == AARCH64_OPND_QLF_V_4S) ? 0 : 1;
+ gen_sub_field (FLD_size, 0, 1, &field);
+ insert_field_2 (&field, &inst->value, value, 0);
+}
+
+/* Encode size[0], i.e. bit 22, for
+ e.g. FCVTXN <Vb><d>, <Va><n>. */
+
+static void
+encode_asisd_fcvtxn (aarch64_inst *inst)
+{
+ aarch64_insn val = 1;
+ aarch64_field field = {0, 0};
+ assert (inst->operands[0].qualifier == AARCH64_OPND_QLF_S_S);
+ gen_sub_field (FLD_size, 0, 1, &field);
+ insert_field_2 (&field, &inst->value, val, 0);
+}
+
+/* Encode the 'opc' field for e.g. FCVT <Dd>, <Sn>. */
+static void
+encode_fcvt (aarch64_inst *inst)
+{
+ aarch64_insn val;
+ const aarch64_field field = {15, 2};
+
+ /* opc dstsize */
+ switch (inst->operands[0].qualifier)
+ {
+ case AARCH64_OPND_QLF_S_S: val = 0; break;
+ case AARCH64_OPND_QLF_S_D: val = 1; break;
+ case AARCH64_OPND_QLF_S_H: val = 3; break;
+ default: abort ();
+ }
+ insert_field_2 (&field, &inst->value, val, 0);
+
+ return;
+}
+
+/* Do miscellaneous encodings that are not common enough to be driven by
+ flags. */
+
+static void
+do_misc_encoding (aarch64_inst *inst)
+{
+ switch (inst->opcode->op)
+ {
+ case OP_FCVT:
+ encode_fcvt (inst);
+ break;
+ case OP_FCVTN:
+ case OP_FCVTN2:
+ case OP_FCVTL:
+ case OP_FCVTL2:
+ encode_asimd_fcvt (inst);
+ break;
+ case OP_FCVTXN_S:
+ encode_asisd_fcvtxn (inst);
+ break;
+ default: break;
+ }
+}
+
+/* Encode the 'size' and 'Q' field for e.g. SHADD. */
+static void
+encode_sizeq (aarch64_inst *inst)
+{
+ aarch64_insn sizeq;
+ enum aarch64_field_kind kind;
+ int idx;
+
+ /* Get the index of the operand whose information we are going to use
+ to encode the size and Q fields.
+ This is deduced from the possible valid qualifier lists. */
+ idx = aarch64_select_operand_for_sizeq_field_coding (inst->opcode);
+ DEBUG_TRACE ("idx: %d; qualifier: %s", idx,
+ aarch64_get_qualifier_name (inst->operands[idx].qualifier));
+ sizeq = aarch64_get_qualifier_standard_value (inst->operands[idx].qualifier);
+ /* Q */
+ insert_field (FLD_Q, &inst->value, sizeq & 0x1, inst->opcode->mask);
+ /* size */
+ if (inst->opcode->iclass == asisdlse
+ || inst->opcode->iclass == asisdlsep
+ || inst->opcode->iclass == asisdlso
+ || inst->opcode->iclass == asisdlsop)
+ kind = FLD_vldst_size;
+ else
+ kind = FLD_size;
+ insert_field (kind, &inst->value, (sizeq >> 1) & 0x3, inst->opcode->mask);
+}
+
+/* Opcodes that have fields shared by multiple operands are usually flagged
+ with flags. In this function, we detect such flags and use the
+ information in one of the related operands to do the encoding. The 'one'
+ operand is not any operand but one of the operands that has the enough
+ information for such an encoding. */
+
+static void
+do_special_encoding (struct aarch64_inst *inst)
+{
+ int idx;
+ aarch64_insn value;
+
+ DEBUG_TRACE ("enter with coding 0x%x", (uint32_t) inst->value);
+
+ /* Condition for truly conditional executed instructions, e.g. b.cond. */
+ if (inst->opcode->flags & F_COND)
+ {
+ insert_field (FLD_cond2, &inst->value, inst->cond->value, 0);
+ }
+ if (inst->opcode->flags & F_SF)
+ {
+ idx = select_operand_for_sf_field_coding (inst->opcode);
+ value = (inst->operands[idx].qualifier == AARCH64_OPND_QLF_X
+ || inst->operands[idx].qualifier == AARCH64_OPND_QLF_SP)
+ ? 1 : 0;
+ insert_field (FLD_sf, &inst->value, value, 0);
+ if (inst->opcode->flags & F_N)
+ insert_field (FLD_N, &inst->value, value, inst->opcode->mask);
+ }
+ if (inst->opcode->flags & F_SIZEQ)
+ encode_sizeq (inst);
+ if (inst->opcode->flags & F_FPTYPE)
+ {
+ idx = select_operand_for_fptype_field_coding (inst->opcode);
+ switch (inst->operands[idx].qualifier)
+ {
+ case AARCH64_OPND_QLF_S_S: value = 0; break;
+ case AARCH64_OPND_QLF_S_D: value = 1; break;
+ case AARCH64_OPND_QLF_S_H: value = 3; break;
+ default: assert (0);
+ }
+ insert_field (FLD_type, &inst->value, value, 0);
+ }
+ if (inst->opcode->flags & F_SSIZE)
+ {
+ enum aarch64_opnd_qualifier qualifier;
+ idx = select_operand_for_scalar_size_field_coding (inst->opcode);
+ qualifier = inst->operands[idx].qualifier;
+ assert (qualifier >= AARCH64_OPND_QLF_S_B
+ && qualifier <= AARCH64_OPND_QLF_S_Q);
+ value = aarch64_get_qualifier_standard_value (qualifier);
+ insert_field (FLD_size, &inst->value, value, inst->opcode->mask);
+ }
+ if (inst->opcode->flags & F_T)
+ {
+ int num; /* num of consecutive '0's on the right side of imm5<3:0>. */
+ aarch64_field field = {0, 0};
+ enum aarch64_opnd_qualifier qualifier;
+
+ idx = 0;
+ qualifier = inst->operands[idx].qualifier;
+ assert (aarch64_get_operand_class (inst->opcode->operands[0])
+ == AARCH64_OPND_CLASS_SIMD_REG
+ && qualifier >= AARCH64_OPND_QLF_V_8B
+ && qualifier <= AARCH64_OPND_QLF_V_2D);
+ /* imm5<3:0> q <t>
+ 0000 x reserved
+ xxx1 0 8b
+ xxx1 1 16b
+ xx10 0 4h
+ xx10 1 8h
+ x100 0 2s
+ x100 1 4s
+ 1000 0 reserved
+ 1000 1 2d */
+ value = aarch64_get_qualifier_standard_value (qualifier);
+ insert_field (FLD_Q, &inst->value, value & 0x1, inst->opcode->mask);
+ num = (int) value >> 1;
+ assert (num >= 0 && num <= 3);
+ gen_sub_field (FLD_imm5, 0, num + 1, &field);
+ insert_field_2 (&field, &inst->value, 1 << num, inst->opcode->mask);
+ }
+ if (inst->opcode->flags & F_GPRSIZE_IN_Q)
+ {
+ /* Use Rt to encode in the case of e.g.
+ STXP <Ws>, <Xt1>, <Xt2>, [<Xn|SP>{,#0}]. */
+ enum aarch64_opnd_qualifier qualifier;
+ idx = aarch64_operand_index (inst->opcode->operands, AARCH64_OPND_Rt);
+ if (idx == -1)
+ /* Otherwise use the result operand, which has to be a integer
+ register. */
+ idx = 0;
+ assert (idx == 0 || idx == 1);
+ assert (aarch64_get_operand_class (inst->opcode->operands[idx])
+ == AARCH64_OPND_CLASS_INT_REG);
+ qualifier = inst->operands[idx].qualifier;
+ insert_field (FLD_Q, &inst->value,
+ aarch64_get_qualifier_standard_value (qualifier), 0);
+ }
+ if (inst->opcode->flags & F_LDS_SIZE)
+ {
+ /* e.g. LDRSB <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
+ enum aarch64_opnd_qualifier qualifier;
+ aarch64_field field = {0, 0};
+ assert (aarch64_get_operand_class (inst->opcode->operands[0])
+ == AARCH64_OPND_CLASS_INT_REG);
+ gen_sub_field (FLD_opc, 0, 1, &field);
+ qualifier = inst->operands[0].qualifier;
+ insert_field_2 (&field, &inst->value,
+ 1 - aarch64_get_qualifier_standard_value (qualifier), 0);
+ }
+ /* Miscellaneous encoding as the last step. */
+ if (inst->opcode->flags & F_MISC)
+ do_misc_encoding (inst);
+
+ DEBUG_TRACE ("exit with coding 0x%x", (uint32_t) inst->value);
+}
+
+/* Converters converting an alias opcode instruction to its real form. */
+
+/* ROR <Wd>, <Ws>, #<shift>
+ is equivalent to:
+ EXTR <Wd>, <Ws>, <Ws>, #<shift>. */
+static void
+convert_ror_to_extr (aarch64_inst *inst)
+{
+ copy_operand_info (inst, 3, 2);
+ copy_operand_info (inst, 2, 1);
+}
+
+/* Convert
+ LSR <Xd>, <Xn>, #<shift>
+ to
+ UBFM <Xd>, <Xn>, #<shift>, #63. */
+static void
+convert_sr_to_bfm (aarch64_inst *inst)
+{
+ inst->operands[3].imm.value =
+ inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 31 : 63;
+}
+
+/* Convert MOV to ORR. */
+static void
+convert_mov_to_orr (aarch64_inst *inst)
+{
+ /* MOV <Vd>.<T>, <Vn>.<T>
+ is equivalent to:
+ ORR <Vd>.<T>, <Vn>.<T>, <Vn>.<T>. */
+ copy_operand_info (inst, 2, 1);
+}
+
+/* When <imms> >= <immr>, the instruction written:
+ SBFX <Xd>, <Xn>, #<lsb>, #<width>
+ is equivalent to:
+ SBFM <Xd>, <Xn>, #<lsb>, #(<lsb>+<width>-1). */
+
+static void
+convert_bfx_to_bfm (aarch64_inst *inst)
+{
+ int64_t lsb, width;
+
+ /* Convert the operand. */
+ lsb = inst->operands[2].imm.value;
+ width = inst->operands[3].imm.value;
+ inst->operands[2].imm.value = lsb;
+ inst->operands[3].imm.value = lsb + width - 1;
+}
+
+/* When <imms> < <immr>, the instruction written:
+ SBFIZ <Xd>, <Xn>, #<lsb>, #<width>
+ is equivalent to:
+ SBFM <Xd>, <Xn>, #((64-<lsb>)&0x3f), #(<width>-1). */
+
+static void
+convert_bfi_to_bfm (aarch64_inst *inst)
+{
+ int64_t lsb, width;
+
+ /* Convert the operand. */
+ lsb = inst->operands[2].imm.value;
+ width = inst->operands[3].imm.value;
+ if (inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31)
+ {
+ inst->operands[2].imm.value = (32 - lsb) & 0x1f;
+ inst->operands[3].imm.value = width - 1;
+ }
+ else
+ {
+ inst->operands[2].imm.value = (64 - lsb) & 0x3f;
+ inst->operands[3].imm.value = width - 1;
+ }
+}
+
+/* The instruction written:
+ LSL <Xd>, <Xn>, #<shift>
+ is equivalent to:
+ UBFM <Xd>, <Xn>, #((64-<shift>)&0x3f), #(63-<shift>). */
+
+static void
+convert_lsl_to_ubfm (aarch64_inst *inst)
+{
+ int64_t shift = inst->operands[2].imm.value;
+
+ if (inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31)
+ {
+ inst->operands[2].imm.value = (32 - shift) & 0x1f;
+ inst->operands[3].imm.value = 31 - shift;
+ }
+ else
+ {
+ inst->operands[2].imm.value = (64 - shift) & 0x3f;
+ inst->operands[3].imm.value = 63 - shift;
+ }
+}
+
+/* CINC <Wd>, <Wn>, <cond>
+ is equivalent to:
+ CSINC <Wd>, <Wn>, <Wn>, invert(<cond>). */
+
+static void
+convert_to_csel (aarch64_inst *inst)
+{
+ copy_operand_info (inst, 3, 2);
+ copy_operand_info (inst, 2, 1);
+ inst->operands[3].cond = get_inverted_cond (inst->operands[3].cond);
+}
+
+/* CSET <Wd>, <cond>
+ is equivalent to:
+ CSINC <Wd>, WZR, WZR, invert(<cond>). */
+
+static void
+convert_cset_to_csinc (aarch64_inst *inst)
+{
+ copy_operand_info (inst, 3, 1);
+ copy_operand_info (inst, 2, 0);
+ copy_operand_info (inst, 1, 0);
+ inst->operands[1].reg.regno = 0x1f;
+ inst->operands[2].reg.regno = 0x1f;
+ inst->operands[3].cond = get_inverted_cond (inst->operands[3].cond);
+}
+
+/* MOV <Wd>, #<imm>
+ is equivalent to:
+ MOVZ <Wd>, #<imm16>, LSL #<shift>. */
+
+static void
+convert_mov_to_movewide (aarch64_inst *inst)
+{
+ int is32;
+ uint32_t shift_amount;
+ uint64_t value;
+
+ switch (inst->opcode->op)
+ {
+ case OP_MOV_IMM_WIDE:
+ value = inst->operands[1].imm.value;
+ break;
+ case OP_MOV_IMM_WIDEN:
+ value = ~inst->operands[1].imm.value;
+ break;
+ default:
+ assert (0);
+ }
+ inst->operands[1].type = AARCH64_OPND_HALF;
+ is32 = inst->operands[0].qualifier == AARCH64_OPND_QLF_W;
+ /* This should have been guaranteed by the constraint check. */
+ assert (aarch64_wide_constant_p (value, is32, &shift_amount) == TRUE);
+ value >>= shift_amount;
+ value &= 0xffff;
+ inst->operands[1].imm.value = value;
+ inst->operands[1].shifter.kind = AARCH64_MOD_LSL;
+ inst->operands[1].shifter.amount = shift_amount;
+}
+
+/* MOV <Wd>, #<imm>
+ is equivalent to:
+ ORR <Wd>, WZR, #<imm>. */
+
+static void
+convert_mov_to_movebitmask (aarch64_inst *inst)
+{
+ copy_operand_info (inst, 2, 1);
+ inst->operands[1].reg.regno = 0x1f;
+ inst->operands[1].skip = 0;
+}
+
+/* Some alias opcodes are assembled by being converted to their real-form. */
+
+static void
+convert_to_real (aarch64_inst *inst, const aarch64_opcode *real)
+{
+ const aarch64_opcode *alias = inst->opcode;
+
+ if ((alias->flags & F_CONV) == 0)
+ goto convert_to_real_return;
+
+ switch (alias->op)
+ {
+ case OP_ASR_IMM:
+ case OP_LSR_IMM:
+ convert_sr_to_bfm (inst);
+ break;
+ case OP_LSL_IMM:
+ convert_lsl_to_ubfm (inst);
+ break;
+ case OP_CINC:
+ case OP_CINV:
+ case OP_CNEG:
+ convert_to_csel (inst);
+ break;
+ case OP_CSET:
+ case OP_CSETM:
+ convert_cset_to_csinc (inst);
+ break;
+ case OP_UBFX:
+ case OP_BFXIL:
+ case OP_SBFX:
+ convert_bfx_to_bfm (inst);
+ break;
+ case OP_SBFIZ:
+ case OP_BFI:
+ case OP_UBFIZ:
+ convert_bfi_to_bfm (inst);
+ break;
+ case OP_MOV_V:
+ convert_mov_to_orr (inst);
+ break;
+ case OP_MOV_IMM_WIDE:
+ case OP_MOV_IMM_WIDEN:
+ convert_mov_to_movewide (inst);
+ break;
+ case OP_MOV_IMM_LOG:
+ convert_mov_to_movebitmask (inst);
+ break;
+ case OP_ROR_IMM:
+ convert_ror_to_extr (inst);
+ break;
+ default:
+ break;
+ }
+
+convert_to_real_return:
+ aarch64_replace_opcode (inst, real);
+}
+
+/* Encode *INST_ORI of the opcode code OPCODE.
+ Return the encoded result in *CODE and if QLF_SEQ is not NULL, return the
+ matched operand qualifier sequence in *QLF_SEQ. */
+
+int
+aarch64_opcode_encode (const aarch64_opcode *opcode,
+ const aarch64_inst *inst_ori, aarch64_insn *code,
+ aarch64_opnd_qualifier_t *qlf_seq,
+ aarch64_operand_error *mismatch_detail)
+{
+ int i;
+ const aarch64_opcode *aliased;
+ aarch64_inst copy, *inst;
+
+ DEBUG_TRACE ("enter with %s", opcode->name);
+
+ /* Create a copy of *INST_ORI, so that we can do any change we want. */
+ copy = *inst_ori;
+ inst = &copy;
+
+ assert (inst->opcode == NULL || inst->opcode == opcode);
+ if (inst->opcode == NULL)
+ inst->opcode = opcode;
+
+ /* Constrain the operands.
+ After passing this, the encoding is guaranteed to succeed. */
+ if (aarch64_match_operands_constraint (inst, mismatch_detail) == 0)
+ {
+ DEBUG_TRACE ("FAIL since operand constraint not met");
+ return 0;
+ }
+
+ /* Get the base value.
+ Note: this has to be before the aliasing handling below in order to
+ get the base value from the alias opcode before we move on to the
+ aliased opcode for encoding. */
+ inst->value = opcode->opcode;
+
+ /* No need to do anything else if the opcode does not have any operand. */
+ if (aarch64_num_of_operands (opcode) == 0)
+ goto encoding_exit;
+
+ /* Assign operand indexes and check types. Also put the matched
+ operand qualifiers in *QLF_SEQ to return. */
+ for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
+ {
+ assert (opcode->operands[i] == inst->operands[i].type);
+ inst->operands[i].idx = i;
+ if (qlf_seq != NULL)
+ *qlf_seq = inst->operands[i].qualifier;
+ }
+
+ aliased = aarch64_find_real_opcode (opcode);
+ /* If the opcode is an alias and it does not ask for direct encoding by
+ itself, the instruction will be transformed to the form of real opcode
+ and the encoding will be carried out using the rules for the aliased
+ opcode. */
+ if (aliased != NULL && (opcode->flags & F_CONV))
+ {
+ DEBUG_TRACE ("real opcode '%s' has been found for the alias %s",
+ aliased->name, opcode->name);
+ /* Convert the operands to the form of the real opcode. */
+ convert_to_real (inst, aliased);
+ opcode = aliased;
+ }
+
+ aarch64_opnd_info *info = inst->operands;
+
+ /* Call the inserter of each operand. */
+ for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i, ++info)
+ {
+ const aarch64_operand *opnd;
+ enum aarch64_opnd type = opcode->operands[i];
+ if (type == AARCH64_OPND_NIL)
+ break;
+ if (info->skip)
+ {
+ DEBUG_TRACE ("skip the incomplete operand %d", i);
+ continue;
+ }
+ opnd = &aarch64_operands[type];
+ if (operand_has_inserter (opnd))
+ aarch64_insert_operand (opnd, info, &inst->value, inst);
+ }
+
+ /* Call opcode encoders indicated by flags. */
+ if (opcode_has_special_coder (opcode))
+ do_special_encoding (inst);
+
+encoding_exit:
+ DEBUG_TRACE ("exit with %s", opcode->name);
+
+ *code = inst->value;
+
+ return 1;
+}
diff --git a/opcodes/aarch64-asm.h b/opcodes/aarch64-asm.h
new file mode 100644
index 0000000..b14383b
--- /dev/null
+++ b/opcodes/aarch64-asm.h
@@ -0,0 +1,73 @@
+/* aarch64-asm.h -- Header file for aarch64-asm.c and aarch64-asm-2.c.
+ Copyright 2012 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of the GNU opcodes library.
+
+ This library 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 3, or (at your option)
+ any later version.
+
+ It 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; see the file COPYING3. If not,
+ see <http://www.gnu.org/licenses/>. */
+
+#ifndef OPCODES_AARCH64_ASM_H
+#define OPCODES_AARCH64_ASM_H
+
+#include "aarch64-opc.h"
+
+/* Given OPCODE, return the opcode entry that OPCODE aliases to, e.g.
+ given LSL, return UBFM. */
+
+const aarch64_opcode* aarch64_find_real_opcode (const aarch64_opcode *);
+
+/* Switch-table-based high-level operand inserter. */
+
+const char* aarch64_insert_operand (const aarch64_operand *,
+ const aarch64_opnd_info *, aarch64_insn *,
+ const aarch64_inst *);
+
+/* Operand inserters. */
+
+#define AARCH64_DECL_OPD_INSERTER(x) \
+ const char* aarch64_##x (const aarch64_operand *, const aarch64_opnd_info *, \
+ aarch64_insn *, const aarch64_inst *)
+
+AARCH64_DECL_OPD_INSERTER (ins_regno);
+AARCH64_DECL_OPD_INSERTER (ins_reglane);
+AARCH64_DECL_OPD_INSERTER (ins_reglist);
+AARCH64_DECL_OPD_INSERTER (ins_ldst_reglist);
+AARCH64_DECL_OPD_INSERTER (ins_ldst_reglist_r);
+AARCH64_DECL_OPD_INSERTER (ins_ldst_elemlist);
+AARCH64_DECL_OPD_INSERTER (ins_advsimd_imm_shift);
+AARCH64_DECL_OPD_INSERTER (ins_imm);
+AARCH64_DECL_OPD_INSERTER (ins_imm_half);
+AARCH64_DECL_OPD_INSERTER (ins_advsimd_imm_modified);
+AARCH64_DECL_OPD_INSERTER (ins_fbits);
+AARCH64_DECL_OPD_INSERTER (ins_aimm);
+AARCH64_DECL_OPD_INSERTER (ins_limm);
+AARCH64_DECL_OPD_INSERTER (ins_ft);
+AARCH64_DECL_OPD_INSERTER (ins_addr_simple);
+AARCH64_DECL_OPD_INSERTER (ins_addr_regoff);
+AARCH64_DECL_OPD_INSERTER (ins_addr_simm);
+AARCH64_DECL_OPD_INSERTER (ins_addr_uimm12);
+AARCH64_DECL_OPD_INSERTER (ins_simd_addr_post);
+AARCH64_DECL_OPD_INSERTER (ins_cond);
+AARCH64_DECL_OPD_INSERTER (ins_sysreg);
+AARCH64_DECL_OPD_INSERTER (ins_pstatefield);
+AARCH64_DECL_OPD_INSERTER (ins_sysins_op);
+AARCH64_DECL_OPD_INSERTER (ins_barrier);
+AARCH64_DECL_OPD_INSERTER (ins_prfop);
+AARCH64_DECL_OPD_INSERTER (ins_reg_extended);
+AARCH64_DECL_OPD_INSERTER (ins_reg_shifted);
+
+#undef AARCH64_DECL_OPD_INSERTER
+
+#endif /* OPCODES_AARCH64_ASM_H */
diff --git a/opcodes/aarch64-dis-2.c b/opcodes/aarch64-dis-2.c
new file mode 100644
index 0000000..cf508ae
--- /dev/null
+++ b/opcodes/aarch64-dis-2.c
@@ -0,0 +1,7655 @@
+/* This file is automatically generated by aarch64-gen. Do not edit! */
+/* Copyright 2012 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of the GNU opcodes library.
+
+ This library 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 3, or (at your option)
+ any later version.
+
+ It 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; see the file COPYING3. If not,
+ see <http://www.gnu.org/licenses/>. */
+
+#include "sysdep.h"
+#include "aarch64-dis.h"
+
+/* Called by aarch64_opcode_lookup. */
+
+static int
+aarch64_opcode_lookup_1 (uint32_t word)
+{
+ if (((word >> 26) & 0x1) == 0)
+ {
+ if (((word >> 25) & 0x1) == 0)
+ {
+ if (((word >> 27) & 0x1) == 0)
+ {
+ if (((word >> 24) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxxx0000xxx0
+ adr. */
+ return 769;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxxx0000xxx1
+ adrp. */
+ return 770;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxxx1000x00x
+ add. */
+ return 12;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxxx1000x01x
+ sub. */
+ return 16;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxxx1000x10x
+ adds. */
+ return 14;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxxx1000x11x
+ subs. */
+ return 17;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx0xxxxx000x0010000
+ stxrb. */
+ return 705;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx0xxxxx000x0010010
+ stxrh. */
+ return 711;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx0xxxxx000x00100x1
+ stxr. */
+ return 717;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx0xxxxx100x00100xx
+ stxp. */
+ return 719;
+ }
+ }
+ else
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx1xxxxx000x0010000
+ stlxrb. */
+ return 706;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx1xxxxx000x0010010
+ stlxrh. */
+ return 712;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx1xxxxx000x00100x1
+ stlxr. */
+ return 718;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx1xxxxx100x00100xx
+ stlxp. */
+ return 720;
+ }
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx00x00101xx
+ stnp. */
+ return 727;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx01x0010000
+ stlrb. */
+ return 709;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx01x0010010
+ stlrh. */
+ return 715;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx01x00100x1
+ stlr. */
+ return 725;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx01x00101xx
+ stp. */
+ return 736;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx0xxxxx010x0010000
+ ldxrb. */
+ return 707;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx0xxxxx010x0010010
+ ldxrh. */
+ return 713;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx0xxxxx010x00100x1
+ ldxr. */
+ return 721;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx0xxxxx110x00100xx
+ ldxp. */
+ return 723;
+ }
+ }
+ else
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx1xxxxx010x0010000
+ ldaxrb. */
+ return 708;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx1xxxxx010x0010010
+ ldaxrh. */
+ return 714;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx1xxxxx010x00100x1
+ ldaxr. */
+ return 722;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx1xxxxx110x00100xx
+ ldaxp. */
+ return 724;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx10x001010x
+ ldnp. */
+ return 728;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx10x001011x
+ ldpsw. */
+ return 735;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx11x0010000
+ ldarb. */
+ return 710;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx11x0010010
+ ldarh. */
+ return 716;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx11x00100x1
+ ldar. */
+ return 726;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx11x001010x
+ ldp. */
+ return 737;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx11x001011x
+ ldpsw. */
+ return 740;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 24) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxxx000110x0
+ ldr. */
+ return 741;
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxxx00011001
+ ldrsw. */
+ return 743;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxxx00011011
+ prfm. */
+ return 744;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 10) & 0x1) == 0)
+ {
+ if (((word >> 11) & 0x1) == 0)
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxxx0000011100
+ sturb. */
+ return 681;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxxx0000011110
+ sturh. */
+ return 691;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxxx00000111x1
+ stur. */
+ return 697;
+ }
+ }
+ else
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxxx1000011100
+ ldurb. */
+ return 682;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxxx1000011110
+ ldurh. */
+ return 692;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxxx10000111x1
+ ldur. */
+ return 698;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxxxx100011100
+ ldursb. */
+ return 685;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxxxx100011101
+ ldursw. */
+ return 701;
+ }
+ }
+ else
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxxxx100011110
+ ldursh. */
+ return 695;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxxxx100011111
+ prfum. */
+ return 703;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx00000011100
+ sttrb. */
+ return 672;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx00000011110
+ sttrh. */
+ return 675;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx000000111x1
+ sttr. */
+ return 678;
+ }
+ }
+ else
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx01000011100
+ ldtrb. */
+ return 673;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx01000011110
+ ldtrh. */
+ return 676;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx010000111x1
+ ldtr. */
+ return 679;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx0x100011100
+ ldtrsb. */
+ return 674;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx0x100011101
+ ldtrsw. */
+ return 680;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx0x10001111x
+ ldtrsh. */
+ return 677;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx10000011100
+ strb. */
+ return 660;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx10000011110
+ strh. */
+ return 665;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx100000111x1
+ str. */
+ return 668;
+ }
+ }
+ else
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx11000011100
+ ldrb. */
+ return 661;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx11000011110
+ ldrh. */
+ return 666;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx110000111x1
+ ldr. */
+ return 669;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx1x100011100
+ ldrsb. */
+ return 662;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx1x100011101
+ ldrsw. */
+ return 670;
+ }
+ }
+ else
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx1x100011110
+ ldrsh. */
+ return 667;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx1x100011111
+ prfm. */
+ return 671;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1xxxxxxxxxxx0000011100
+ strb. */
+ return 637;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1xxxxxxxxxxx0000011110
+ strh. */
+ return 642;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1xxxxxxxxxxx00000111x1
+ str. */
+ return 645;
+ }
+ }
+ else
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1xxxxxxxxxxx1000011100
+ ldrb. */
+ return 638;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1xxxxxxxxxxx1000011110
+ ldrh. */
+ return 643;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1xxxxxxxxxxx10000111x1
+ ldr. */
+ return 646;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1xxxxxxxxxxxx100011100
+ ldrsb. */
+ return 639;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1xxxxxxxxxxxx100011101
+ ldrsw. */
+ return 647;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1xxxxxxxxxxxx10001111x
+ ldrsh. */
+ return 644;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx0010011x00
+ strb. */
+ return 648;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx0010011x10
+ strh. */
+ return 653;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx0010011xx1
+ str. */
+ return 656;
+ }
+ }
+ else
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx1010011x00
+ ldrb. */
+ return 649;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx1010011x10
+ ldrh. */
+ return 654;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx1010011xx1
+ ldr. */
+ return 657;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxx110011x00
+ ldrsb. */
+ return 650;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxx110011x01
+ ldrsw. */
+ return 658;
+ }
+ }
+ else
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxx110011x10
+ ldrsh. */
+ return 655;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxx110011x11
+ prfm. */
+ return 659;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 24) & 0x1) == 0)
+ {
+ if (((word >> 27) & 0x1) == 0)
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxx00100x00x
+ and. */
+ return 745;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxx00100x01x
+ eor. */
+ return 749;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxx00100x10x
+ orr. */
+ return 747;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxx00100x11x
+ ands. */
+ return 750;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxx10100x00x
+ movn. */
+ return 764;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxx10100x01x
+ movz. */
+ return 766;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxx10100x1xx
+ movk. */
+ return 768;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx0xx0101000x
+ and. */
+ return 752;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx0xx0101001x
+ eor. */
+ return 759;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx0xx0101010x
+ orr. */
+ return 754;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx0xx0101011x
+ ands. */
+ return 761;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 10) & 0x1) == 0)
+ {
+ if (((word >> 11) & 0x1) == 0)
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxx0000101100x
+ adc. */
+ return 0;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxx0000101101x
+ sbc. */
+ return 2;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxx0000101110x
+ adcs. */
+ return 1;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxx0000101111x
+ sbcs. */
+ return 4;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxx00101011x0x
+ csel. */
+ return 520;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxx00101011x1x
+ csinv. */
+ return 524;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxx01001011x0x
+ ccmn. */
+ return 518;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxx01001011x1x
+ ccmp. */
+ return 519;
+ }
+ }
+ else
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0000xxxxxxx01101011xxx
+ rbit. */
+ return 543;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0001xxxxxxx01101011xxx
+ lslv. */
+ return 552;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001xxxxxxxx01101011xxx
+ clz. */
+ return 547;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx0x001011x0x
+ ccmn. */
+ return 516;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxx0x001011x1x
+ ccmp. */
+ return 517;
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01x0xxxxxxx0x101011x0x
+ udiv. */
+ return 550;
+ }
+ else
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01x0xxxxxxx0x101011x10
+ rev. */
+ return 545;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01x0xxxxxxx0x101011x11
+ rev32. */
+ return 549;
+ }
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01x1xxxxxxx0x101011xxx
+ asrv. */
+ return 556;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 11) & 0x1) == 0)
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx10xxxxxxxxx00x01011x0x
+ csinc. */
+ return 521;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx10xxxxxxxxx00x01011x1x
+ csneg. */
+ return 527;
+ }
+ }
+ else
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1000xxxxxxx01x01011xxx
+ rev16. */
+ return 544;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1001xxxxxxx01x01011xxx
+ lsrv. */
+ return 554;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101xxxxxxxx01x01011xxx
+ cls. */
+ return 548;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx11x0xxxxxxx0xx01011x0x
+ sdiv. */
+ return 551;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx11x0xxxxxxx0xx01011x1x
+ rev. */
+ return 546;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx11x1xxxxxxx0xx01011xxx
+ rorv. */
+ return 558;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx1xx0101x00x
+ bic. */
+ return 753;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx1xx0101x01x
+ eon. */
+ return 760;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx1xx0101x10x
+ orn. */
+ return 757;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx1xx0101x11x
+ bics. */
+ return 763;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 27) & 0x1) == 0)
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxx01100x00x
+ sbfm. */
+ return 489;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxx01100x01x
+ ubfm. */
+ return 499;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxx01100x1xx
+ bfm. */
+ return 496;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxx11100xxxx
+ extr. */
+ return 582;
+ }
+ }
+ else
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx0xx1101000x
+ add. */
+ return 19;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx0xx1101001x
+ sub. */
+ return 22;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx0xx1101010x
+ adds. */
+ return 20;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx0xx1101011x
+ subs. */
+ return 24;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx0xxxxx00x11011xxx
+ madd. */
+ return 560;
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx0xxxxx01011011xxx
+ smulh. */
+ return 568;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx0xxxxx01111011xxx
+ umulh. */
+ return 573;
+ }
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx1xxxxx0xx11011xxx
+ msub. */
+ return 562;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx1x01101000x
+ add. */
+ return 6;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx1x01101001x
+ sub. */
+ return 9;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx1x01101010x
+ adds. */
+ return 7;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx1x01101011x
+ subs. */
+ return 10;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx0xxxxx1x011011xxx
+ smaddl. */
+ return 564;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx1xxxxx1x011011xxx
+ smsubl. */
+ return 566;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx0xxxxx1x11101xxxx
+ umaddl. */
+ return 569;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx1xxxxx1x11101xxxx
+ umsubl. */
+ return 571;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 27) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxxxxx10x000
+ b. */
+ return 506;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxxxxx10x001
+ bl. */
+ return 507;
+ }
+ }
+ else
+ {
+ if (((word >> 24) & 0x1) == 0)
+ {
+ if (((word >> 25) & 0x1) == 0)
+ {
+ if (((word >> 31) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxxx0010x010
+ b.c. */
+ return 515;
+ }
+ else
+ {
+ if (((word >> 0) & 0x1) == 0)
+ {
+ if (((word >> 1) & 0x1) == 0)
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ 00xxxxxxxxxxxxxxxxxxx0xx0010x011
+ hlt. */
+ return 578;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ 00xxxxxxxxxxxxxxxxxxx1xx0010x011
+ brk. */
+ return 577;
+ }
+ }
+ else
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ 01xxxxxxxxxxxxxxxxxxx0xx0010x011
+ hvc. */
+ return 575;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ 01xxxxxxxxxxxxxxxxxxx1xx0010x011
+ dcps2. */
+ return 580;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 1) & 0x1) == 0)
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ 10xxxxxxxxxxxxxxxxxxx0xx0010x011
+ svc. */
+ return 574;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ 10xxxxxxxxxxxxxxxxxxx1xx0010x011
+ dcps1. */
+ return 579;
+ }
+ }
+ else
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ 11xxxxxxxxxxxxxxxxxxx0xx0010x011
+ smc. */
+ return 576;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ 11xxxxxxxxxxxxxxxxxxx1xx0010x011
+ dcps3. */
+ return 581;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx0000110x01x
+ br. */
+ return 508;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx0010110x01x
+ eret. */
+ return 511;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx01x0110x01x
+ ret. */
+ return 510;
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx1x00110x01x
+ blr. */
+ return 509;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx1x10110x01x
+ drps. */
+ return 512;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 20) & 0x1) == 0)
+ {
+ if (((word >> 19) & 0x1) == 0)
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxx00xxxxx00xxx1x10x01x
+ msr. */
+ return 771;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxx01xxxxx00xxx1x10x01x
+ hint. */
+ return 772;
+ }
+ }
+ else
+ {
+ if (((word >> 5) & 0x1) == 0)
+ {
+ if (((word >> 6) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxx00xxxxx1xxxxxx00xxx1x10x01x
+ dsb. */
+ return 780;
+ }
+ else
+ {
+ if (((word >> 7) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxx010xxxx1xxxxxx00xxx1x10x01x
+ clrex. */
+ return 779;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxx011xxxx1xxxxxx00xxx1x10x01x
+ isb. */
+ return 782;
+ }
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxx1xxxxxx1xxxxxx00xxx1x10x01x
+ dmb. */
+ return 781;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxx100xx1x10x01x
+ sys. */
+ return 783;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxx101xx1x10x01x
+ sysl. */
+ return 789;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxx10xx1x10x01x
+ msr. */
+ return 788;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxx11xx1x10x01x
+ mrs. */
+ return 790;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 24) & 0x1) == 0)
+ {
+ if (((word >> 25) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxxx0010x1xx
+ cbz. */
+ return 513;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxxx0110x1xx
+ tbz. */
+ return 791;
+ }
+ }
+ else
+ {
+ if (((word >> 25) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxxx1010x1xx
+ cbnz. */
+ return 514;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxxx1110x1xx
+ tbnz. */
+ return 792;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 25) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 24) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx00001100xx
+ st4. */
+ return 351;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx00001101xx
+ stnp. */
+ return 729;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxx0xxxxxxx000101100xx
+ st1. */
+ return 367;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxx0xxxxxxx100101100xx
+ st2. */
+ return 369;
+ }
+ }
+ else
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxx1xxxxxxx000101100xx
+ st3. */
+ return 368;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxx1xxxxxxx100101100xx
+ st4. */
+ return 370;
+ }
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx00101101xx
+ stp. */
+ return 733;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ if (((word >> 24) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx001001100xx
+ st4. */
+ return 359;
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxx0xxxxxxx001101100xx
+ st1. */
+ return 379;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxx1xxxxxxx001101100xx
+ st3. */
+ return 380;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxx0xxxxxxx101x01100xx
+ st2. */
+ return 381;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxx1xxxxxxx101x01100xx
+ st4. */
+ return 382;
+ }
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx01x01101xx
+ stp. */
+ return 738;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 24) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx10001100xx
+ ld4. */
+ return 355;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx10001101xx
+ ldnp. */
+ return 730;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxx0xxxxxxx010101100xx
+ ld1. */
+ return 371;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxx0xxxxxxx110101100xx
+ ld2. */
+ return 375;
+ }
+ }
+ else
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxx1xxxxxxx010101100xx
+ ld3. */
+ return 372;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxx1xxxxxxx110101100xx
+ ld4. */
+ return 376;
+ }
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx10101101xx
+ ldp. */
+ return 734;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ if (((word >> 24) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxx011001100xx
+ ld4. */
+ return 363;
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxx0xxxxxxx011101100xx
+ ld1. */
+ return 383;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxx1xxxxxxx011101100xx
+ ld3. */
+ return 384;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxx0xxxxxxx111x01100xx
+ ld2. */
+ return 387;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxx1xxxxxxx111x01100xx
+ ld4. */
+ return 388;
+ }
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx11x01101xx
+ ldp. */
+ return 739;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 24) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxxxx001110xx
+ ldr. */
+ return 742;
+ }
+ else
+ {
+ if (((word >> 10) & 0x1) == 0)
+ {
+ if (((word >> 11) & 0x1) == 0)
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxxx0x001111xx
+ stur. */
+ return 687;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00xxxxxxxxxx1x001111xx
+ ldur. */
+ return 688;
+ }
+ }
+ else
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxxx0x001111xx
+ str. */
+ return 663;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01xxxxxxxxxx1x001111xx
+ ldr. */
+ return 664;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1xxxxxxxxxxx0x001111xx
+ str. */
+ return 640;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1xxxxxxxxxxx1x001111xx
+ ldr. */
+ return 641;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx0x10111xxx
+ str. */
+ return 651;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxxxxxxxx1x10111xxx
+ ldr. */
+ return 652;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 24) & 0x1) == 0)
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 10) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 11) & 0x1) == 0)
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000xxxxxxxx0xx011100xx
+ tbl. */
+ return 337;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001xxxxxxxx0xx011100xx
+ tbx. */
+ return 338;
+ }
+ }
+ else
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010x0xxxxxx0xx011100xx
+ trn1. */
+ return 216;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010x1xxxxxx0xx011100xx
+ trn2. */
+ return 219;
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01100xxxxxx0xx011100xx
+ uzp1. */
+ return 215;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01101xxxxxx0xx011100xx
+ uzp2. */
+ return 218;
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01110xxxxxx0xx011100xx
+ zip1. */
+ return 217;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx01111xxxxxx0xx011100xx
+ zip2. */
+ return 220;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0xxxxxxxxxx0xx011101xx
+ ext. */
+ return 119;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 11) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx10xxxxxxxxx0xx011100xx
+ dup. */
+ return 135;
+ }
+ else
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1100xxxxxxx0xx011100xx
+ dup. */
+ return 136;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1101xxxxxxx0xx011100xx
+ smov. */
+ return 137;
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1110xxxxxxx0xx011100xx
+ ins. */
+ return 140;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1111xxxxxxx0xx011100xx
+ umov. */
+ return 138;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1xxxxxxxxxx0xx011101xx
+ ins. */
+ return 142;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ if (((word >> 16) & 0x1) == 0)
+ {
+ if (((word >> 17) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxx00xxx0xx01111x0x
+ fcvtzs. */
+ return 586;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxx01xxx0xx01111x0x
+ scvtf. */
+ return 584;
+ }
+ }
+ else
+ {
+ if (((word >> 17) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxx10xxx0xx01111x0x
+ fcvtzu. */
+ return 587;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxxx11xxx0xx01111x0x
+ ucvtf. */
+ return 585;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 10) & 0x1) == 0)
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x000xxxxxx0xx01111x1x
+ sha1c. */
+ return 536;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x001xxxxxx0xx01111x1x
+ sha256h. */
+ return 540;
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x010xxxxxx0xx01111x1x
+ sha1m. */
+ return 538;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x011xxxxxx0xx01111x1x
+ sha256su1. */
+ return 542;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x100xxxxxx0xx01111x1x
+ sha1p. */
+ return 537;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x101xxxxxx0xx01111x1x
+ sha256h2. */
+ return 541;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x11xxxxxxx0xx01111x1x
+ sha1su0. */
+ return 539;
+ }
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1xxxxxxxxxx0xx01111x1x
+ dup. */
+ return 426;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 10) & 0x1) == 0)
+ {
+ if (((word >> 11) & 0x1) == 0)
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000000xxxxx1xx0111000x
+ saddl. */
+ return 38;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000000xxxxx1xx0111001x
+ saddl2. */
+ return 39;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000000xxxxx1xx0111010x
+ uaddl. */
+ return 70;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000000xxxxx1xx0111011x
+ uaddl2. */
+ return 71;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 16) & 0x1) == 0)
+ {
+ if (((word >> 17) & 0x1) == 0)
+ {
+ if (((word >> 18) & 0x1) == 0)
+ {
+ if (((word >> 19) & 0x1) == 0)
+ {
+ if (((word >> 20) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000000000001xx01111xxx
+ fcvtns. */
+ return 588;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000000000011xx01111xxx
+ fcvtms. */
+ return 598;
+ }
+ }
+ else
+ {
+ if (((word >> 20) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000000000101xx01111xxx
+ fcvtps. */
+ return 596;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000000000111xx01111xxx
+ fcvtzs. */
+ return 600;
+ }
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000000001xx1xx01111xxx
+ fcvtas. */
+ return 592;
+ }
+ }
+ else
+ {
+ if (((word >> 18) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000000010xx1xx01111xxx
+ scvtf. */
+ return 590;
+ }
+ else
+ {
+ if (((word >> 19) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0000000110x1xx01111xxx
+ fmov. */
+ return 594;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0000000111x1xx01111xxx
+ fmov. */
+ return 602;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 17) & 0x1) == 0)
+ {
+ if (((word >> 18) & 0x1) == 0)
+ {
+ if (((word >> 19) & 0x1) == 0)
+ {
+ if (((word >> 20) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000000100001xx01111xxx
+ fcvtnu. */
+ return 589;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000000100011xx01111xxx
+ fcvtmu. */
+ return 599;
+ }
+ }
+ else
+ {
+ if (((word >> 20) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000000100101xx01111xxx
+ fcvtpu. */
+ return 597;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000000100111xx01111xxx
+ fcvtzu. */
+ return 601;
+ }
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000000101xx1xx01111xxx
+ fcvtau. */
+ return 593;
+ }
+ }
+ else
+ {
+ if (((word >> 18) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000000110xx1xx01111xxx
+ ucvtf. */
+ return 591;
+ }
+ else
+ {
+ if (((word >> 19) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0000001110x1xx01111xxx
+ fmov. */
+ return 595;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0000001111x1xx01111xxx
+ fmov. */
+ return 603;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000001xxxxx1xx0111x00x
+ smlal. */
+ return 54;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000001xxxxx1xx0111x01x
+ smlal2. */
+ return 55;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000001xxxxx1xx0111x10x
+ umlal. */
+ return 86;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000001xxxxx1xx0111x11x
+ umlal2. */
+ return 87;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000010xxxxx1xx0111000x
+ addhn. */
+ return 46;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000010xxxxx1xx0111001x
+ addhn2. */
+ return 47;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000010xxxxx1xx0111010x
+ raddhn. */
+ return 78;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000010xxxxx1xx0111011x
+ raddhn2. */
+ return 79;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000011xxxxx1xx0111000x
+ smull. */
+ return 62;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000011xxxxx1xx0111001x
+ smull2. */
+ return 63;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000011xxxxx1xx0111010x
+ umull. */
+ return 90;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000011xxxxx1xx0111011x
+ umull2. */
+ return 91;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 17) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 16) & 0x1) == 0)
+ {
+ if (((word >> 18) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000010000xx1xx01111xxx
+ fmov. */
+ return 610;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000010001xx1xx01111xxx
+ frintn. */
+ return 615;
+ }
+ }
+ else
+ {
+ if (((word >> 18) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000010100xx1xx01111xxx
+ fneg. */
+ return 612;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000010101xx1xx01111xxx
+ frintm. */
+ return 617;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 16) & 0x1) == 0)
+ {
+ if (((word >> 18) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000011000xx1xx01111xxx
+ fabs. */
+ return 611;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000011001xx1xx01111xxx
+ frintp. */
+ return 616;
+ }
+ }
+ else
+ {
+ if (((word >> 18) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000011100xx1xx01111xxx
+ fsqrt. */
+ return 613;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000011101xx1xx01111xxx
+ frintz. */
+ return 618;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 18) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00001xx10xx1xx01111xxx
+ fcvt. */
+ return 614;
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 16) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000010011xx1xx01111xxx
+ frinta. */
+ return 619;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000010111xx1xx01111xxx
+ frintx. */
+ return 620;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000011x11xx1xx01111xxx
+ frinti. */
+ return 621;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000100xxxxx1xx0111000x
+ ssubl. */
+ return 42;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000100xxxxx1xx0111001x
+ ssubl2. */
+ return 43;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000100xxxxx1xx0111010x
+ usubl. */
+ return 74;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000100xxxxx1xx0111011x
+ usubl2. */
+ return 75;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 3) & 0x1) == 0)
+ {
+ if (((word >> 4) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxx00xxxxx000100xxxxx1xx01111xxx
+ fcmp. */
+ return 606;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxx01xxxxx000100xxxxx1xx01111xxx
+ fcmpe. */
+ return 607;
+ }
+ }
+ else
+ {
+ if (((word >> 4) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxx10xxxxx000100xxxxx1xx01111xxx
+ fcmp. */
+ return 608;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxx11xxxxx000100xxxxx1xx01111xxx
+ fcmpe. */
+ return 609;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000101xxxxx1xx0111x00x
+ smlsl. */
+ return 58;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000101xxxxx1xx0111x01x
+ smlsl2. */
+ return 59;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000101xxxxx1xx0111x10x
+ umlsl. */
+ return 88;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000101xxxxx1xx0111x11x
+ umlsl2. */
+ return 89;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000110xxxxx1xx0111x00x
+ subhn. */
+ return 50;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000110xxxxx1xx0111x01x
+ subhn2. */
+ return 51;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000110xxxxx1xx0111x10x
+ rsubhn. */
+ return 82;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000110xxxxx1xx0111x11x
+ rsubhn2. */
+ return 83;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000111xxxxx10x0111xx0x
+ pmull. */
+ return 66;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000111xxxxx10x0111xx1x
+ pmull2. */
+ return 68;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000111xxxxx11x0111xx0x
+ pmull. */
+ return 67;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx000111xxxxx11x0111xx1x
+ pmull2. */
+ return 69;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001000xxxxx1xx0111000x
+ saddw. */
+ return 40;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001000xxxxx1xx0111001x
+ saddw2. */
+ return 41;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001000xxxxx1xx0111010x
+ uaddw. */
+ return 72;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001000xxxxx1xx0111011x
+ uaddw2. */
+ return 73;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001001xxxxx1xx01110x0x
+ sqdmlal. */
+ return 56;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001001xxxxx1xx01110x1x
+ sqdmlal2. */
+ return 57;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001010xxxxx1xx0111000x
+ sabal. */
+ return 48;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001010xxxxx1xx0111001x
+ sabal2. */
+ return 49;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001010xxxxx1xx0111010x
+ uabal. */
+ return 80;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001010xxxxx1xx0111011x
+ uabal2. */
+ return 81;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001011xxxxx1xx01110x0x
+ sqdmull. */
+ return 64;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001011xxxxx1xx01110x1x
+ sqdmull2. */
+ return 65;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001100xxxxx1xx0111000x
+ ssubw. */
+ return 44;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001100xxxxx1xx0111001x
+ ssubw2. */
+ return 45;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001100xxxxx1xx0111010x
+ usubw. */
+ return 76;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001100xxxxx1xx0111011x
+ usubw2. */
+ return 77;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001101xxxxx1xx01110x0x
+ sqdmlsl. */
+ return 60;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001101xxxxx1xx01110x1x
+ sqdmlsl2. */
+ return 61;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00111xxxxxx1xx0111000x
+ sabdl. */
+ return 52;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00111xxxxxx1xx0111001x
+ sabdl2. */
+ return 53;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00111xxxxxx1xx0111010x
+ uabdl. */
+ return 84;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00111xxxxxx1xx0111011x
+ uabdl2. */
+ return 85;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx001xxxxxxxx1xx01111x0x
+ fmov. */
+ return 635;
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00100xxxxxx1xx01111x1x
+ sqdmlal. */
+ return 339;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx00101xxxxxx1xx01111x1x
+ sqdmull. */
+ return 341;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0011xxxxxxx1xx01111x1x
+ sqdmlsl. */
+ return 340;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010000xxxxx1xx011100xx
+ rev64. */
+ return 144;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010000xxxxx1xx011101xx
+ rev32. */
+ return 180;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010000xxxxx1xx01111x0x
+ fmul. */
+ return 622;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010000xxxxx1xx01111x1x
+ sha1h. */
+ return 533;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 16) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100010xxxx1xx011100xx
+ cmgt. */
+ return 152;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100010xxxx1xx011101xx
+ cmge. */
+ return 186;
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100011xxxx1x0011100xx
+ frintn. */
+ return 164;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100011xxxx1x0011101xx
+ frinta. */
+ return 197;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100011xxxx1x101110xxx
+ frintp. */
+ return 174;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010001xxxxx1xx0111100x
+ fnmul. */
+ return 630;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010001xxxxx1xx0111101x
+ cmgt. */
+ return 393;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010001xxxxx1xx011111xx
+ cmge. */
+ return 411;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 16) & 0x1) == 0)
+ {
+ if (((word >> 19) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100100xx0x1xx011100xx
+ cls. */
+ return 148;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100100xx0x1xx011101xx
+ clz. */
+ return 183;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100100xx1x1xx01110xxx
+ aese. */
+ return 529;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100101xxxx1xx0111000x
+ sqxtn. */
+ return 158;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100101xxxx1xx0111001x
+ sqxtn2. */
+ return 159;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100101xxxx1xx0111010x
+ uqxtn. */
+ return 193;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100101xxxx1xx0111011x
+ uqxtn2. */
+ return 194;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010010xxxxx1xx0111100x
+ fmax. */
+ return 626;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010010xxxxx1xx0111101x
+ sqxtn. */
+ return 397;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010010xxxxx1xx011111xx
+ uqxtn. */
+ return 415;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 16) & 0x1) == 0)
+ {
+ if (((word >> 20) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100110xxx01xx011100xx
+ fcmgt. */
+ return 170;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100110xxx01xx011101xx
+ fcmge. */
+ return 206;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100110xxx01xx011110xx
+ fcmgt. */
+ return 402;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100110xxx01xx011111xx
+ fcmge. */
+ return 421;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100110xxx11x001110xxx
+ fmaxnmv. */
+ return 34;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100110xxx11x001111xxx
+ fmaxnmp. */
+ return 429;
+ }
+ }
+ else
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100110xxx11x101110xxx
+ fminnmv. */
+ return 36;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100110xxx11x101111xxx
+ fminnmp. */
+ return 432;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100111xxxx1x0011100xx
+ fcvtas. */
+ return 168;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100111xxxx1x0011101xx
+ fcvtau. */
+ return 201;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100111xxxx1x0011110xx
+ fcvtas. */
+ return 400;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100111xxxx1x0011111xx
+ fcvtau. */
+ return 419;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100111xxxx1x10111x0xx
+ urecpe. */
+ return 178;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0100111xxxx1x10111x1xx
+ ursqrte. */
+ return 212;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 16) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101000xxxx1xx011100xx
+ saddlp. */
+ return 146;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101000xxxx1xx011101xx
+ uaddlp. */
+ return 181;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101001xxxx1xx0111000x
+ xtn. */
+ return 156;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101001xxxx1xx0111001x
+ xtn2. */
+ return 157;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101001xxxx1xx0111010x
+ sqxtun. */
+ return 189;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101001xxxx1xx0111011x
+ sqxtun2. */
+ return 190;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010100xxxxx1xx0111100x
+ fadd. */
+ return 624;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010100xxxxx1xx0111101x
+ sha256su0. */
+ return 535;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010100xxxxx1xx011111xx
+ sqxtun. */
+ return 414;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 16) & 0x1) == 0)
+ {
+ if (((word >> 20) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101010xxx01xx01110xxx
+ cmlt. */
+ return 154;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101010xxx01xx01111xxx
+ cmlt. */
+ return 395;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101010xxx11xx0111x0xx
+ smaxv. */
+ return 28;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101010xxx11xx0111x1xx
+ umaxv. */
+ return 32;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 20) & 0x1) == 0)
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101011xxx01x0011100xx
+ fcvtns. */
+ return 166;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101011xxx01x0011101xx
+ fcvtnu. */
+ return 199;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101011xxx01x0011110xx
+ fcvtns. */
+ return 398;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101011xxx01x0011111xx
+ fcvtnu. */
+ return 417;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101011xxx01x1011100xx
+ fcvtps. */
+ return 176;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101011xxx01x1011101xx
+ fcvtpu. */
+ return 210;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101011xxx01x1011110xx
+ fcvtps. */
+ return 405;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101011xxx01x1011111xx
+ fcvtpu. */
+ return 423;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101011xxx11xx0111x0xx
+ sminv. */
+ return 29;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101011xxx11xx0111x1xx
+ uminv. */
+ return 33;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 16) & 0x1) == 0)
+ {
+ if (((word >> 19) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101100xx0x1xx011100xx
+ sadalp. */
+ return 150;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101100xx0x1xx011101xx
+ uadalp. */
+ return 184;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101100xx1x1xx01110xxx
+ aesmc. */
+ return 531;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101101xxxx1xx0111000x
+ fcvtn. */
+ return 160;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101101xxxx1xx0111001x
+ fcvtn2. */
+ return 161;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101101xxxx1xx0111010x
+ fcvtxn. */
+ return 195;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0101101xxxx1xx0111011x
+ fcvtxn2. */
+ return 196;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010110xxxxx1xx011110xx
+ fmaxnm. */
+ return 628;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010110xxxxx1xx011111xx
+ fcvtxn. */
+ return 416;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010111xxxxx1xx01110xxx
+ fcmlt. */
+ return 172;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx010111xxxxx1xx01111xxx
+ fcmlt. */
+ return 404;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx011000xxxxx1xx01110xxx
+ rev16. */
+ return 145;
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx011000xxxxx1xx01111x0x
+ fdiv. */
+ return 623;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx011000xxxxx1xx01111x1x
+ sha1su1. */
+ return 534;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 16) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110010xxxx1xx011100xx
+ cmeq. */
+ return 153;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110010xxxx1xx011101xx
+ cmle. */
+ return 187;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110010xxxx1xx011110xx
+ cmeq. */
+ return 394;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110010xxxx1xx011111xx
+ cmle. */
+ return 412;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110011xxxx1x00111x0xx
+ frintm. */
+ return 165;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110011xxxx1x00111x1xx
+ frintx. */
+ return 198;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110011xxxx1x10111x0xx
+ frintz. */
+ return 175;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110011xxxx1x10111x1xx
+ frinti. */
+ return 209;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 19) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx011010xxx0x1xx011100xx
+ cnt. */
+ return 149;
+ }
+ else
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx011010xxx0x10x011101xx
+ not. */
+ return 203;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx011010xxx0x11x011101xx
+ rbit. */
+ return 205;
+ }
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx011010xxx1x1xx01110xxx
+ aesd. */
+ return 530;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx011010xxxxx1xx01111xxx
+ fmin. */
+ return 627;
+ }
+ }
+ else
+ {
+ if (((word >> 16) & 0x1) == 0)
+ {
+ if (((word >> 20) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110110xxx01xx011100xx
+ fcmeq. */
+ return 171;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110110xxx01xx011101xx
+ fcmle. */
+ return 207;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110110xxx01xx011110xx
+ fcmeq. */
+ return 403;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110110xxx01xx011111xx
+ fcmle. */
+ return 422;
+ }
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110110xxx11xx0111xxxx
+ faddp. */
+ return 430;
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110111xxxx1x0011100xx
+ scvtf. */
+ return 169;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110111xxxx1x0011101xx
+ ucvtf. */
+ return 202;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110111xxxx1x0011110xx
+ scvtf. */
+ return 401;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110111xxxx1x0011111xx
+ ucvtf. */
+ return 420;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110111xxxx1x1011100xx
+ frecpe. */
+ return 179;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110111xxxx1x1011101xx
+ frsqrte. */
+ return 213;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110111xxxx1x1011110xx
+ frecpe. */
+ return 407;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0110111xxxx1x1011111xx
+ frsqrte. */
+ return 425;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 16) & 0x1) == 0)
+ {
+ if (((word >> 20) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111000xxx01xx011100xx
+ suqadd. */
+ return 147;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111000xxx01xx011101xx
+ usqadd. */
+ return 182;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111000xxx11xx011100xx
+ saddlv. */
+ return 27;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111000xxx11xx011101xx
+ uaddlv. */
+ return 31;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111001xxxx1xx01110x0x
+ shll. */
+ return 191;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111001xxxx1xx01110x1x
+ shll2. */
+ return 192;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx011100xxxxx1xx0111100x
+ fsub. */
+ return 625;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx011100xxxxx1xx0111101x
+ suqadd. */
+ return 391;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx011100xxxxx1xx011111xx
+ usqadd. */
+ return 409;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 16) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111010xxxx1xx011100xx
+ abs. */
+ return 155;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111010xxxx1xx011101xx
+ neg. */
+ return 188;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111010xxxx1xx011110xx
+ abs. */
+ return 396;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111010xxxx1xx011111xx
+ neg. */
+ return 413;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 20) & 0x1) == 0)
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111011xxx01x0011100xx
+ fcvtms. */
+ return 167;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111011xxx01x0011101xx
+ fcvtmu. */
+ return 200;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111011xxx01x0011110xx
+ fcvtms. */
+ return 399;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111011xxx01x0011111xx
+ fcvtmu. */
+ return 418;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111011xxx01x1011100xx
+ fcvtzs. */
+ return 177;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111011xxx01x1011101xx
+ fcvtzu. */
+ return 211;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111011xxx01x1011110xx
+ fcvtzs. */
+ return 406;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111011xxx01x1011111xx
+ fcvtzu. */
+ return 424;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111011xxx11xx01110xxx
+ addv. */
+ return 30;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111011xxx11xx01111xxx
+ addp. */
+ return 428;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 16) & 0x1) == 0)
+ {
+ if (((word >> 19) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111100xx0x1xx011100xx
+ sqabs. */
+ return 151;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111100xx0x1xx011101xx
+ sqneg. */
+ return 185;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111100xx1x1xx01110xxx
+ aesimc. */
+ return 532;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111101xxxx1xx01110x0x
+ fcvtl. */
+ return 162;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111101xxxx1xx01110x1x
+ fcvtl2. */
+ return 163;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx011110xxxxx1xx0111100x
+ fminnm. */
+ return 629;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx011110xxxxx1xx0111101x
+ sqabs. */
+ return 392;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx011110xxxxx1xx011111xx
+ sqneg. */
+ return 410;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 16) & 0x1) == 0)
+ {
+ if (((word >> 20) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111110xxx01xx0111x0xx
+ fabs. */
+ return 173;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111110xxx01xx0111x1xx
+ fneg. */
+ return 208;
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111110xxx11x001110xxx
+ fmaxv. */
+ return 35;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111110xxx11x001111xxx
+ fmaxp. */
+ return 431;
+ }
+ }
+ else
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111110xxx11x101110xxx
+ fminv. */
+ return 37;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111110xxx11x101111xxx
+ fminp. */
+ return 433;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111111xxxx1xx01110xxx
+ fsqrt. */
+ return 214;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0111111xxxx1xx01111xxx
+ frecpx. */
+ return 408;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 11) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100000xxxxx1xx011100xx
+ shadd. */
+ return 221;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100000xxxxx1xx011101xx
+ uhadd. */
+ return 261;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100001xxxxx1xx011100xx
+ add. */
+ return 236;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100001xxxxx1xx011101xx
+ sub. */
+ return 276;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100010xxxxx1xx011100xx
+ sshl. */
+ return 228;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100010xxxxx1xx011101xx
+ ushl. */
+ return 268;
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100011xxxxx1x0011100xx
+ fmaxnm. */
+ return 244;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100011xxxxx1x0011101xx
+ fmaxnmp. */
+ return 283;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100011xxxxx1x1011100xx
+ fminnm. */
+ return 253;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100011xxxxx1x1011101xx
+ fminnmp. */
+ return 292;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100100xxxxx1xx011100xx
+ shsub. */
+ return 224;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100100xxxxx1xx011101xx
+ uhsub. */
+ return 264;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100101xxxxx1xx011100xx
+ smaxp. */
+ return 240;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100101xxxxx1xx011101xx
+ umaxp. */
+ return 280;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100110xxxxx1xx011100xx
+ smax. */
+ return 232;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100110xxxxx1xx011101xx
+ umax. */
+ return 272;
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100111xxxxx1x0011100xx
+ fcmeq. */
+ return 248;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100111xxxxx1x0011101xx
+ fcmge. */
+ return 286;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100111xxxxx1x101110xxx
+ fcmgt. */
+ return 294;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101000xxxxx1xx011100xx
+ srhadd. */
+ return 223;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101000xxxxx1xx011101xx
+ urhadd. */
+ return 263;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101001xxxxx1xx011100xx
+ mla. */
+ return 238;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101001xxxxx1xx011101xx
+ mls. */
+ return 278;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101010xxxxx1xx011100xx
+ srshl. */
+ return 230;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101010xxxxx1xx011101xx
+ urshl. */
+ return 270;
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101011xxxxx1x0011100xx
+ fadd. */
+ return 246;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101011xxxxx1x0011101xx
+ faddp. */
+ return 284;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101011xxxxx1x1011100xx
+ fsub. */
+ return 255;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101011xxxxx1x1011101xx
+ fabd. */
+ return 293;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101100xxxxx1xx011100xx
+ cmgt. */
+ return 226;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101100xxxxx1xx011101xx
+ cmhi. */
+ return 266;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101101xxxxx1xx011100xx
+ sqdmulh. */
+ return 242;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101101xxxxx1xx011101xx
+ sqrdmulh. */
+ return 282;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101110xxxxx1xx011100xx
+ sabd. */
+ return 234;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101110xxxxx1xx011101xx
+ uabd. */
+ return 274;
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101111xxxxx1x0011100xx
+ fmax. */
+ return 249;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101111xxxxx1x0011101xx
+ fmaxp. */
+ return 288;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101111xxxxx1x1011100xx
+ fmin. */
+ return 256;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101111xxxxx1x1011101xx
+ fminp. */
+ return 296;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ if (((word >> 4) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxx0xxxxx10xxxxxxxxx1xx0111100x
+ fccmp. */
+ return 604;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxx1xxxxx10xxxxxxxxx1xx0111100x
+ fccmpe. */
+ return 605;
+ }
+ }
+ else
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx10000xxxxxx1xx0111101x
+ add. */
+ return 447;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx10001xxxxxx1xx0111101x
+ sshl. */
+ return 445;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1001xxxxxxx1xx0111101x
+ fcmeq. */
+ return 440;
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1010xxxxxxx1xx0111101x
+ srshl. */
+ return 446;
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1011x0xxxxx1xx0111101x
+ cmgt. */
+ return 443;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1011x1xxxxx1xx0111101x
+ sqdmulh. */
+ return 438;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx10000xxxxxx1xx011111xx
+ sub. */
+ return 463;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx10001xxxxxx1xx011111xx
+ ushl. */
+ return 461;
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1001xxxxxxx1x0011111xx
+ fcmge. */
+ return 454;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1001xxxxxxx1x1011111xx
+ fcmgt. */
+ return 457;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1010x0xxxxx1xx011111xx
+ urshl. */
+ return 462;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1010x1xxxxx1xx011111xx
+ fabd. */
+ return 456;
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1011x0xxxxx1xx011111xx
+ cmhi. */
+ return 459;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1011x1xxxxx1xx011111xx
+ sqrdmulh. */
+ return 453;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110000xxxxx1xx011100xx
+ sqadd. */
+ return 222;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110000xxxxx1xx011101xx
+ uqadd. */
+ return 262;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110001xxxxx1xx011100xx
+ cmtst. */
+ return 237;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110001xxxxx1xx011101xx
+ cmeq. */
+ return 277;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110010xxxxx1xx011100xx
+ sqshl. */
+ return 229;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110010xxxxx1xx011101xx
+ uqshl. */
+ return 269;
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110011xxxxx1x001110xxx
+ fmla. */
+ return 245;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110011xxxxx1x101110xxx
+ fmls. */
+ return 254;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110100xxxxx1xx011100xx
+ sqsub. */
+ return 225;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110100xxxxx1xx011101xx
+ uqsub. */
+ return 265;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110101xxxxx1xx011100xx
+ sminp. */
+ return 241;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110101xxxxx1xx011101xx
+ uminp. */
+ return 281;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110110xxxxx1xx011100xx
+ smin. */
+ return 233;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110110xxxxx1xx011101xx
+ umin. */
+ return 273;
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110111xxxxx1x001110xxx
+ facge. */
+ return 287;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110111xxxxx1x101110xxx
+ facgt. */
+ return 295;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 22) & 0x1) == 0)
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111000xxxxx100011100xx
+ and. */
+ return 251;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111000xxxxx100011101xx
+ eor. */
+ return 290;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111000xxxxx101011100xx
+ orr. */
+ return 258;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111000xxxxx101011101xx
+ bit. */
+ return 297;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111000xxxxx110011100xx
+ bic. */
+ return 252;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111000xxxxx110011101xx
+ bsl. */
+ return 291;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111000xxxxx111011100xx
+ orn. */
+ return 260;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111000xxxxx111011101xx
+ bif. */
+ return 298;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111001xxxxx1xx011100xx
+ mul. */
+ return 239;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111001xxxxx1xx011101xx
+ pmul. */
+ return 279;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111010xxxxx1xx011100xx
+ sqrshl. */
+ return 231;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111010xxxxx1xx011101xx
+ uqrshl. */
+ return 271;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111011xxxxx1xx011100xx
+ fmulx. */
+ return 247;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111011xxxxx1xx011101xx
+ fmul. */
+ return 285;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111100xxxxx1xx011100xx
+ cmge. */
+ return 227;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111100xxxxx1xx011101xx
+ cmhs. */
+ return 267;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111101xxxxx1xx01110xxx
+ addp. */
+ return 243;
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111110xxxxx1xx011100xx
+ saba. */
+ return 235;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111110xxxxx1xx011101xx
+ uaba. */
+ return 275;
+ }
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111111xxxxx1x0011100xx
+ frecps. */
+ return 250;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111111xxxxx1x0011101xx
+ fdiv. */
+ return 289;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx111111xxxxx1x101110xxx
+ frsqrts. */
+ return 257;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx11xxxxxxxxx1xx0111100x
+ fcsel. */
+ return 636;
+ }
+ else
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110000xxxxx1xx0111101x
+ sqadd. */
+ return 434;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110001xxxxx1xx0111101x
+ cmtst. */
+ return 448;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx11001xxxxxx1xx0111101x
+ sqshl. */
+ return 436;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1101xxxxxxx1xx0111101x
+ sqsub. */
+ return 435;
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1110x0xxxxx1xx0111101x
+ sqrshl. */
+ return 437;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1110x1xxxxx1xx0111101x
+ fmulx. */
+ return 439;
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx11110xxxxxx1xx0111101x
+ cmge. */
+ return 444;
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx11111xxxxxx1x00111101x
+ frecps. */
+ return 441;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx11111xxxxxx1x10111101x
+ frsqrts. */
+ return 442;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110000xxxxx1xx011111xx
+ uqadd. */
+ return 449;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110001xxxxx1xx011111xx
+ cmeq. */
+ return 464;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx11001xxxxxx1xx011111xx
+ uqshl. */
+ return 451;
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx11010xxxxxx1xx011111xx
+ uqsub. */
+ return 450;
+ }
+ else
+ {
+ if (((word >> 23) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx11011xxxxxx1x0011111xx
+ facge. */
+ return 455;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx11011xxxxxx1x1011111xx
+ facgt. */
+ return 458;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1110xxxxxxx1xx011111xx
+ uqrshl. */
+ return 452;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1111xxxxxxx1xx011111xx
+ cmhs. */
+ return 460;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 10) & 0x1) == 0)
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x0000xxxxxxxx11110xxx
+ mla. */
+ return 110;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x0010xxxxxxxx11110xxx
+ mls. */
+ return 113;
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x0100xxxxxxxx1111000x
+ smlal. */
+ return 92;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x0100xxxxxxxx1111001x
+ smlal2. */
+ return 93;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x0100xxxxxxxx1111010x
+ umlal. */
+ return 111;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x0100xxxxxxxx1111011x
+ umlal2. */
+ return 112;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x0110xxxxxxxx1111000x
+ smlsl. */
+ return 96;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x0110xxxxxxxx1111001x
+ smlsl2. */
+ return 97;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x0110xxxxxxxx1111010x
+ umlsl. */
+ return 114;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x0110xxxxxxxx1111011x
+ umlsl2. */
+ return 115;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x1000xxxxxxxx11110xxx
+ fmla. */
+ return 107;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x1010xxxxxxxx11110xxx
+ fmls. */
+ return 108;
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x1100xxxxxxxx11110x0x
+ sqdmlal. */
+ return 94;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x1100xxxxxxxx11110x1x
+ sqdmlal2. */
+ return 95;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x1110xxxxxxxx11110x0x
+ sqdmlsl. */
+ return 98;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x1110xxxxxxxx11110x1x
+ sqdmlsl2. */
+ return 99;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1x0xx0xxxxxxxx111100xx
+ movi. */
+ return 120;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1x0xx0xxxxxxxx111101xx
+ mvni. */
+ return 127;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1x1xx0xxxxxxxx111100xx
+ orr. */
+ return 121;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1x1xx0xxxxxxxx111101xx
+ bic. */
+ return 128;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx0xxxxx0xx1111100x
+ fmadd. */
+ return 631;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx0xxxxx1xx1111100x
+ fnmadd. */
+ return 633;
+ }
+ }
+ else
+ {
+ if (((word >> 10) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0xx000xxxxxxxx1111101x
+ fmla. */
+ return 347;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0xx010xxxxxxxx1111101x
+ fmls. */
+ return 348;
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0xx100xxxxxxxx1111101x
+ sqdmlal. */
+ return 342;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0xx110xxxxxxxx1111101x
+ sqdmlsl. */
+ return 343;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1x00x0xxxxxxxx1111101x
+ sshr. */
+ return 465;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1x01x0xxxxxxxx1111101x
+ srshr. */
+ return 467;
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1x1000xxxxxxxx1111101x
+ ssra. */
+ return 466;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1x1010xxxxxxxx1111101x
+ shl. */
+ return 469;
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1x1100xxxxxxxx1111101x
+ srsra. */
+ return 468;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1x1110xxxxxxxx1111101x
+ sqshl. */
+ return 470;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxx0000xxxxxxxx111111xx
+ ushr. */
+ return 475;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxx0010xxxxxxxx111111xx
+ sri. */
+ return 479;
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxx0100xxxxxxxx111111xx
+ urshr. */
+ return 477;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxx0110xxxxxxxx111111xx
+ sqshlu. */
+ return 481;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxx1000xxxxxxxx111111xx
+ usra. */
+ return 476;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxx1010xxxxxxxx111111xx
+ sli. */
+ return 480;
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxx1100xxxxxxxx111111xx
+ ursra. */
+ return 478;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxx1110xxxxxxxx111111xx
+ uqshl. */
+ return 482;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 28) & 0x1) == 0)
+ {
+ if (((word >> 10) & 0x1) == 0)
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x0001xxxxxxxx11110xxx
+ mul. */
+ return 100;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x0011xxxxxxxx11110xxx
+ sqdmulh. */
+ return 105;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x01x1xxxxxxxx1111000x
+ smull. */
+ return 101;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x01x1xxxxxxxx1111001x
+ smull2. */
+ return 102;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x01x1xxxxxxxx1111010x
+ umull. */
+ return 116;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x01x1xxxxxxxx1111011x
+ umull2. */
+ return 117;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x1001xxxxxxxx111100xx
+ fmul. */
+ return 109;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x1001xxxxxxxx111101xx
+ fmulx. */
+ return 118;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x1011xxxxxxxx11110xxx
+ sqrdmulh. */
+ return 106;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x11x1xxxxxxxx11110x0x
+ sqdmull. */
+ return 103;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x11x1xxxxxxxx11110x1x
+ sqdmull2. */
+ return 104;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 11) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100x01xxxxxxxx111100xx
+ movi. */
+ return 122;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100x01xxxxxxxx111101xx
+ mvni. */
+ return 129;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101x01xxxxxxxx111100xx
+ orr. */
+ return 123;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101x01xxxxxxxx111101xx
+ bic. */
+ return 130;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx10x011xxxxxxxx111100xx
+ movi. */
+ return 124;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx10x011xxxxxxxx111101xx
+ mvni. */
+ return 131;
+ }
+ }
+ else
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100111xxxxxxxx111100xx
+ movi. */
+ return 125;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100111xxxxxxxx111101xx
+ movi. */
+ return 132;
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101111xxxxxxxx111100xx
+ fmov. */
+ return 126;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101111xxxxxxxx111101xx
+ fmov. */
+ return 134;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110xx1xxxxxxxx1111000x
+ rshrn. */
+ return 307;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110xx1xxxxxxxx1111001x
+ rshrn2. */
+ return 308;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110xx1xxxxxxxx1111010x
+ sqrshrun. */
+ return 327;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110xx1xxxxxxxx1111011x
+ sqrshrun2. */
+ return 328;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1110x1xxxxxxxx1111000x
+ sqrshrn. */
+ return 311;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1110x1xxxxxxxx1111001x
+ sqrshrn2. */
+ return 312;
+ }
+ }
+ else
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1110x1xxxxxxxx1111010x
+ uqrshrn. */
+ return 331;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1110x1xxxxxxxx1111011x
+ uqrshrn2. */
+ return 332;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1111x1xxxxxxxx111100xx
+ fcvtzs. */
+ return 316;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1111x1xxxxxxxx111101xx
+ fcvtzu. */
+ return 336;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 29) & 0x1) == 0)
+ {
+ if (((word >> 30) & 0x1) == 0)
+ {
+ if (((word >> 21) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx1xxxxx0xx1111100x
+ fmsub. */
+ return 632;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxxxxxxx1xxxxx1xx1111100x
+ fnmsub. */
+ return 634;
+ }
+ }
+ else
+ {
+ if (((word >> 10) & 0x1) == 0)
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x0xx1xxxxxxxx1111101x
+ sqdmulh. */
+ return 345;
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x1001xxxxxxxx1111101x
+ fmul. */
+ return 349;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x1011xxxxxxxx1111101x
+ sqrdmulh. */
+ return 346;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0x11x1xxxxxxxx1111101x
+ sqdmull. */
+ return 344;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 11) & 0x1) == 0)
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx100xx1xxxxxxxx1111101x
+ scvtf. */
+ return 473;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101xx1xxxxxxxx1111101x
+ sqshrn. */
+ return 471;
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx11x0x1xxxxxxxx1111101x
+ sqrshrn. */
+ return 472;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx11x1x1xxxxxxxx1111101x
+ fcvtzs. */
+ return 474;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 10) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx0xxxx1xxxxxxxx111111xx
+ fmulx. */
+ return 350;
+ }
+ else
+ {
+ if (((word >> 11) & 0x1) == 0)
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1000x1xxxxxxxx111111xx
+ sqshrun. */
+ return 483;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1001x1xxxxxxxx111111xx
+ ucvtf. */
+ return 487;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx101xx1xxxxxxxx111111xx
+ uqshrn. */
+ return 485;
+ }
+ }
+ else
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx110xx1xxxxxxxx111111xx
+ sqrshrun. */
+ return 484;
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1110x1xxxxxxxx111111xx
+ uqrshrn. */
+ return 486;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xxxxxxxxxx1111x1xxxxxxxx111111xx
+ fcvtzu. */
+ return 488;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/* Lookup opcode WORD in the opcode table. N.B. all alias
+ opcodes are ignored here. */
+
+const aarch64_opcode *
+aarch64_opcode_lookup (uint32_t word)
+{
+ return aarch64_opcode_table + aarch64_opcode_lookup_1 (word);
+}
+
+const aarch64_opcode *
+aarch64_find_next_opcode (const aarch64_opcode *opcode)
+{
+ /* Use the index as the key to locate the next opcode. */
+ int key = opcode - aarch64_opcode_table;
+ int value;
+ switch (key)
+ {
+ case 727: value = 731; break; /* stnp --> stp. */
+ case 731: return NULL; /* stp --> NULL. */
+ case 728: value = 732; break; /* ldnp --> ldp. */
+ case 732: return NULL; /* ldp --> NULL. */
+ case 351: value = 352; break; /* st4 --> st1. */
+ case 352: value = 353; break; /* st1 --> st2. */
+ case 353: value = 354; break; /* st2 --> st3. */
+ case 354: return NULL; /* st3 --> NULL. */
+ case 359: value = 360; break; /* st4 --> st1. */
+ case 360: value = 361; break; /* st1 --> st2. */
+ case 361: value = 362; break; /* st2 --> st3. */
+ case 362: return NULL; /* st3 --> NULL. */
+ case 355: value = 356; break; /* ld4 --> ld1. */
+ case 356: value = 357; break; /* ld1 --> ld2. */
+ case 357: value = 358; break; /* ld2 --> ld3. */
+ case 358: return NULL; /* ld3 --> NULL. */
+ case 371: value = 373; break; /* ld1 --> ld1r. */
+ case 373: return NULL; /* ld1r --> NULL. */
+ case 375: value = 377; break; /* ld2 --> ld2r. */
+ case 377: return NULL; /* ld2r --> NULL. */
+ case 372: value = 374; break; /* ld3 --> ld3r. */
+ case 374: return NULL; /* ld3r --> NULL. */
+ case 376: value = 378; break; /* ld4 --> ld4r. */
+ case 378: return NULL; /* ld4r --> NULL. */
+ case 363: value = 364; break; /* ld4 --> ld1. */
+ case 364: value = 365; break; /* ld1 --> ld2. */
+ case 365: value = 366; break; /* ld2 --> ld3. */
+ case 366: return NULL; /* ld3 --> NULL. */
+ case 383: value = 385; break; /* ld1 --> ld1r. */
+ case 385: return NULL; /* ld1r --> NULL. */
+ case 384: value = 386; break; /* ld3 --> ld3r. */
+ case 386: return NULL; /* ld3r --> NULL. */
+ case 387: value = 389; break; /* ld2 --> ld2r. */
+ case 389: return NULL; /* ld2r --> NULL. */
+ case 388: value = 390; break; /* ld4 --> ld4r. */
+ case 390: return NULL; /* ld4r --> NULL. */
+ case 120: value = 299; break; /* movi --> sshr. */
+ case 299: value = 301; break; /* sshr --> srshr. */
+ case 301: return NULL; /* srshr --> NULL. */
+ case 127: value = 317; break; /* mvni --> ushr. */
+ case 317: value = 319; break; /* ushr --> urshr. */
+ case 319: value = 321; break; /* urshr --> sri. */
+ case 321: value = 323; break; /* sri --> sqshlu. */
+ case 323: return NULL; /* sqshlu --> NULL. */
+ case 121: value = 300; break; /* orr --> ssra. */
+ case 300: value = 302; break; /* ssra --> srsra. */
+ case 302: value = 303; break; /* srsra --> shl. */
+ case 303: value = 304; break; /* shl --> sqshl. */
+ case 304: return NULL; /* sqshl --> NULL. */
+ case 128: value = 318; break; /* bic --> usra. */
+ case 318: value = 320; break; /* usra --> ursra. */
+ case 320: value = 322; break; /* ursra --> sli. */
+ case 322: value = 324; break; /* sli --> uqshl. */
+ case 324: return NULL; /* uqshl --> NULL. */
+ case 122: value = 305; break; /* movi --> shrn. */
+ case 305: value = 306; break; /* shrn --> shrn2. */
+ case 306: value = 313; break; /* shrn2 --> sshll. */
+ case 313: value = 314; break; /* sshll --> sshll2. */
+ case 314: return NULL; /* sshll2 --> NULL. */
+ case 129: value = 325; break; /* mvni --> sqshrun. */
+ case 325: value = 326; break; /* sqshrun --> sqshrun2. */
+ case 326: value = 333; break; /* sqshrun2 --> ushll. */
+ case 333: value = 334; break; /* ushll --> ushll2. */
+ case 334: return NULL; /* ushll2 --> NULL. */
+ case 123: value = 309; break; /* orr --> sqshrn. */
+ case 309: value = 310; break; /* sqshrn --> sqshrn2. */
+ case 310: return NULL; /* sqshrn2 --> NULL. */
+ case 130: value = 329; break; /* bic --> uqshrn. */
+ case 329: value = 330; break; /* uqshrn --> uqshrn2. */
+ case 330: return NULL; /* uqshrn2 --> NULL. */
+ case 125: value = 315; break; /* movi --> scvtf. */
+ case 315: return NULL; /* scvtf --> NULL. */
+ case 132: value = 133; break; /* movi --> movi. */
+ case 133: value = 335; break; /* movi --> ucvtf. */
+ case 335: return NULL; /* ucvtf --> NULL. */
+ default: return NULL;
+ }
+
+ return aarch64_opcode_table + value;
+}
+
+const aarch64_opcode *
+aarch64_find_alias_opcode (const aarch64_opcode *opcode)
+{
+ /* Use the index as the key to locate the alias opcode. */
+ int key = opcode - aarch64_opcode_table;
+ int value;
+ switch (key)
+ {
+ case 2: value = 3; break; /* sbc --> ngc. */
+ case 4: value = 5; break; /* sbcs --> ngcs. */
+ case 7: value = 8; break; /* adds --> cmn. */
+ case 10: value = 11; break; /* subs --> cmp. */
+ case 12: value = 13; break; /* add --> mov. */
+ case 14: value = 15; break; /* adds --> cmn. */
+ case 17: value = 18; break; /* subs --> cmp. */
+ case 20: value = 21; break; /* adds --> cmn. */
+ case 22: value = 23; break; /* sub --> neg. */
+ case 24: value = 26; break; /* subs --> negs. */
+ case 138: value = 139; break; /* umov --> mov. */
+ case 140: value = 141; break; /* ins --> mov. */
+ case 142: value = 143; break; /* ins --> mov. */
+ case 203: value = 204; break; /* not --> mvn. */
+ case 258: value = 259; break; /* orr --> mov. */
+ case 426: value = 427; break; /* dup --> mov. */
+ case 489: value = 494; break; /* sbfm --> sxtw. */
+ case 496: value = 498; break; /* bfm --> bfxil. */
+ case 499: value = 503; break; /* ubfm --> uxth. */
+ case 521: value = 523; break; /* csinc --> cset. */
+ case 524: value = 526; break; /* csinv --> csetm. */
+ case 527: value = 528; break; /* csneg --> cneg. */
+ case 552: value = 553; break; /* lslv --> lsl. */
+ case 554: value = 555; break; /* lsrv --> lsr. */
+ case 556: value = 557; break; /* asrv --> asr. */
+ case 558: value = 559; break; /* rorv --> ror. */
+ case 560: value = 561; break; /* madd --> mul. */
+ case 562: value = 563; break; /* msub --> mneg. */
+ case 564: value = 565; break; /* smaddl --> smull. */
+ case 566: value = 567; break; /* smsubl --> smnegl. */
+ case 569: value = 570; break; /* umaddl --> umull. */
+ case 571: value = 572; break; /* umsubl --> umnegl. */
+ case 582: value = 583; break; /* extr --> ror. */
+ case 681: value = 683; break; /* sturb --> strb. */
+ case 682: value = 684; break; /* ldurb --> ldrb. */
+ case 685: value = 686; break; /* ldursb --> ldrsb. */
+ case 687: value = 689; break; /* stur --> str. */
+ case 688: value = 690; break; /* ldur --> ldr. */
+ case 691: value = 693; break; /* sturh --> strh. */
+ case 692: value = 694; break; /* ldurh --> ldrh. */
+ case 695: value = 696; break; /* ldursh --> ldrsh. */
+ case 697: value = 699; break; /* stur --> str. */
+ case 698: value = 700; break; /* ldur --> ldr. */
+ case 701: value = 702; break; /* ldursw --> ldrsw. */
+ case 703: value = 704; break; /* prfum --> prfm. */
+ case 745: value = 746; break; /* and --> bic. */
+ case 747: value = 748; break; /* orr --> mov. */
+ case 750: value = 751; break; /* ands --> tst. */
+ case 754: value = 756; break; /* orr --> uxtw. */
+ case 757: value = 758; break; /* orn --> mvn. */
+ case 761: value = 762; break; /* ands --> tst. */
+ case 764: value = 765; break; /* movn --> mov. */
+ case 766: value = 767; break; /* movz --> mov. */
+ case 772: value = 778; break; /* hint --> sevl. */
+ case 783: value = 787; break; /* sys --> tlbi. */
+ default: return NULL;
+ }
+
+ return aarch64_opcode_table + value;
+}
+
+const aarch64_opcode *
+aarch64_find_next_alias_opcode (const aarch64_opcode *opcode)
+{
+ /* Use the index as the key to locate the next opcode. */
+ int key = opcode - aarch64_opcode_table;
+ int value;
+ switch (key)
+ {
+ case 26: value = 25; break; /* negs --> cmp. */
+ case 494: value = 493; break; /* sxtw --> sxth. */
+ case 493: value = 492; break; /* sxth --> sxtb. */
+ case 492: value = 495; break; /* sxtb --> asr. */
+ case 495: value = 491; break; /* asr --> sbfx. */
+ case 491: value = 490; break; /* sbfx --> sbfiz. */
+ case 498: value = 497; break; /* bfxil --> bfi. */
+ case 503: value = 502; break; /* uxth --> uxtb. */
+ case 502: value = 505; break; /* uxtb --> lsr. */
+ case 505: value = 504; break; /* lsr --> lsl. */
+ case 504: value = 501; break; /* lsl --> ubfx. */
+ case 501: value = 500; break; /* ubfx --> ubfiz. */
+ case 523: value = 522; break; /* cset --> cinc. */
+ case 526: value = 525; break; /* csetm --> cinv. */
+ case 756: value = 755; break; /* uxtw --> mov. */
+ case 778: value = 777; break; /* sevl --> sev. */
+ case 777: value = 776; break; /* sev --> wfi. */
+ case 776: value = 775; break; /* wfi --> wfe. */
+ case 775: value = 774; break; /* wfe --> yield. */
+ case 774: value = 773; break; /* yield --> nop. */
+ case 787: value = 786; break; /* tlbi --> ic. */
+ case 786: value = 785; break; /* ic --> dc. */
+ case 785: value = 784; break; /* dc --> at. */
+ default: return NULL;
+ }
+
+ return aarch64_opcode_table + value;
+}
+
+int
+aarch64_extract_operand (const aarch64_operand *self,
+ aarch64_opnd_info *info,
+ aarch64_insn code, const aarch64_inst *inst)
+{
+ /* Use the index as the key. */
+ int key = self - aarch64_operands;
+ switch (key)
+ {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 9:
+ case 10:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 34:
+ case 35:
+ return aarch64_ext_regno (self, info, code, inst);
+ case 8:
+ return aarch64_ext_regrt_sysins (self, info, code, inst);
+ case 11:
+ return aarch64_ext_reg_extended (self, info, code, inst);
+ case 12:
+ return aarch64_ext_reg_shifted (self, info, code, inst);
+ case 17:
+ return aarch64_ext_ft (self, info, code, inst);
+ case 27:
+ case 28:
+ case 29:
+ return aarch64_ext_reglane (self, info, code, inst);
+ case 30:
+ return aarch64_ext_reglist (self, info, code, inst);
+ case 31:
+ return aarch64_ext_ldst_reglist (self, info, code, inst);
+ case 32:
+ return aarch64_ext_ldst_reglist_r (self, info, code, inst);
+ case 33:
+ return aarch64_ext_ldst_elemlist (self, info, code, inst);
+ case 36:
+ case 45:
+ case 46:
+ case 47:
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57:
+ case 64:
+ case 65:
+ case 66:
+ case 67:
+ case 68:
+ return aarch64_ext_imm (self, info, code, inst);
+ case 37:
+ case 38:
+ return aarch64_ext_advsimd_imm_shift (self, info, code, inst);
+ case 39:
+ case 40:
+ case 41:
+ return aarch64_ext_advsimd_imm_modified (self, info, code, inst);
+ case 42:
+ return aarch64_ext_shll_imm (self, info, code, inst);
+ case 58:
+ return aarch64_ext_limm (self, info, code, inst);
+ case 59:
+ return aarch64_ext_aimm (self, info, code, inst);
+ case 60:
+ return aarch64_ext_imm_half (self, info, code, inst);
+ case 61:
+ return aarch64_ext_fbits (self, info, code, inst);
+ case 63:
+ return aarch64_ext_cond (self, info, code, inst);
+ case 69:
+ case 75:
+ return aarch64_ext_addr_simple (self, info, code, inst);
+ case 70:
+ return aarch64_ext_addr_regoff (self, info, code, inst);
+ case 71:
+ case 72:
+ case 73:
+ return aarch64_ext_addr_simm (self, info, code, inst);
+ case 74:
+ return aarch64_ext_addr_uimm12 (self, info, code, inst);
+ case 76:
+ return aarch64_ext_simd_addr_post (self, info, code, inst);
+ case 77:
+ return aarch64_ext_sysreg (self, info, code, inst);
+ case 78:
+ return aarch64_ext_pstatefield (self, info, code, inst);
+ case 79:
+ case 80:
+ case 81:
+ case 82:
+ return aarch64_ext_sysins_op (self, info, code, inst);
+ case 83:
+ case 84:
+ return aarch64_ext_barrier (self, info, code, inst);
+ case 85:
+ return aarch64_ext_prfop (self, info, code, inst);
+ default: assert (0); abort ();
+ }
+}
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
new file mode 100644
index 0000000..84b7b0a
--- /dev/null
+++ b/opcodes/aarch64-dis.c
@@ -0,0 +1,2392 @@
+/* aarch64-dis.c -- AArch64 disassembler.
+ Copyright 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of the GNU opcodes library.
+
+ This library 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 3, or (at your option)
+ any later version.
+
+ It 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; see the file COPYING3. If not,
+ see <http://www.gnu.org/licenses/>. */
+
+#include "sysdep.h"
+#include "bfd_stdint.h"
+#include "dis-asm.h"
+#include "libiberty.h"
+#include "opintl.h"
+#include "aarch64-dis.h"
+
+#if !defined(EMBEDDED_ENV)
+#define SYMTAB_AVAILABLE 1
+#include "elf-bfd.h"
+#include "elf/aarch64.h"
+#endif
+
+#define ERR_OK 0
+#define ERR_UND -1
+#define ERR_UNP -3
+#define ERR_NYI -5
+
+#define INSNLEN 4
+
+/* Cached mapping symbol state. */
+enum map_type
+{
+ MAP_INSN,
+ MAP_DATA
+};
+
+static enum map_type last_type;
+static int last_mapping_sym = -1;
+static bfd_vma last_mapping_addr = 0;
+
+/* Other options */
+static int no_aliases = 0; /* If set disassemble as most general inst. */
+
+
+static void
+set_default_aarch64_dis_options (struct disassemble_info *info ATTRIBUTE_UNUSED)
+{
+}
+
+static void
+parse_aarch64_dis_option (const char *option, unsigned int len ATTRIBUTE_UNUSED)
+{
+ /* Try to match options that are simple flags */
+ if (CONST_STRNEQ (option, "no-aliases"))
+ {
+ no_aliases = 1;
+ return;
+ }
+
+ if (CONST_STRNEQ (option, "aliases"))
+ {
+ no_aliases = 0;
+ return;
+ }
+
+#ifdef DEBUG_AARCH64
+ if (CONST_STRNEQ (option, "debug_dump"))
+ {
+ debug_dump = 1;
+ return;
+ }
+#endif /* DEBUG_AARCH64 */
+
+ /* Invalid option. */
+ fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
+}
+
+static void
+parse_aarch64_dis_options (const char *options)
+{
+ const char *option_end;
+
+ if (options == NULL)
+ return;
+
+ while (*options != '\0')
+ {
+ /* Skip empty options. */
+ if (*options == ',')
+ {
+ options++;
+ continue;
+ }
+
+ /* We know that *options is neither NUL or a comma. */
+ option_end = options + 1;
+ while (*option_end != ',' && *option_end != '\0')
+ option_end++;
+
+ parse_aarch64_dis_option (options, option_end - options);
+
+ /* Go on to the next one. If option_end points to a comma, it
+ will be skipped above. */
+ options = option_end;
+ }
+}
+
+/* Functions doing the instruction disassembling. */
+
+/* The unnamed arguments consist of the number of fields and information about
+ these fields where the VALUE will be extracted from CODE and returned.
+ MASK can be zero or the base mask of the opcode.
+
+ N.B. the fields are required to be in such an order than the most signficant
+ field for VALUE comes the first, e.g. the <index> in
+ SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
+ is encoded in H:L:M in some cases, the the fields H:L:M should be passed in
+ the order of H, L, M. */
+
+static inline aarch64_insn
+extract_fields (aarch64_insn code, aarch64_insn mask, ...)
+{
+ uint32_t num;
+ const aarch64_field *field;
+ enum aarch64_field_kind kind;
+ va_list va;
+
+ va_start (va, mask);
+ num = va_arg (va, uint32_t);
+ assert (num <= 5);
+ aarch64_insn value = 0x0;
+ while (num--)
+ {
+ kind = va_arg (va, enum aarch64_field_kind);
+ field = &fields[kind];
+ value <<= field->width;
+ value |= extract_field (kind, code, mask);
+ }
+ return value;
+}
+
+/* Sign-extend bit I of VALUE. */
+static inline int32_t
+sign_extend (aarch64_insn value, unsigned i)
+{
+ uint32_t ret = value;
+
+ assert (i < 32);
+ if ((value >> i) & 0x1)
+ {
+ uint32_t val = (uint32_t)(-1) << i;
+ ret = ret | val;
+ }
+ return (int32_t) ret;
+}
+
+/* N.B. the following inline helpfer functions create a dependency on the
+ order of operand qualifier enumerators. */
+
+/* Given VALUE, return qualifier for a general purpose register. */
+static inline enum aarch64_opnd_qualifier
+get_greg_qualifier_from_value (aarch64_insn value)
+{
+ enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_W + value;
+ assert (value <= 0x1
+ && aarch64_get_qualifier_standard_value (qualifier) == value);
+ return qualifier;
+}
+
+/* Given VALUE, return qualifier for a vector register. */
+static inline enum aarch64_opnd_qualifier
+get_vreg_qualifier_from_value (aarch64_insn value)
+{
+ enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_V_8B + value;
+
+ assert (value <= 0x8
+ && aarch64_get_qualifier_standard_value (qualifier) == value);
+ return qualifier;
+}
+
+/* Given VALUE, return qualifier for an FP or AdvSIMD scalar register. */
+static inline enum aarch64_opnd_qualifier
+get_sreg_qualifier_from_value (aarch64_insn value)
+{
+ enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_S_B + value;
+
+ assert (value <= 0x4
+ && aarch64_get_qualifier_standard_value (qualifier) == value);
+ return qualifier;
+}
+
+/* Given the instruction in *INST which is probably half way through the
+ decoding and our caller wants to know the expected qualifier for operand
+ I. Return such a qualifier if we can establish it; otherwise return
+ AARCH64_OPND_QLF_NIL. */
+
+static aarch64_opnd_qualifier_t
+get_expected_qualifier (const aarch64_inst *inst, int i)
+{
+ aarch64_opnd_qualifier_seq_t qualifiers;
+ /* Should not be called if the qualifier is known. */
+ assert (inst->operands[i].qualifier == AARCH64_OPND_QLF_NIL);
+ if (aarch64_find_best_match (inst, inst->opcode->qualifiers_list,
+ i, qualifiers))
+ return qualifiers[i];
+ else
+ return AARCH64_OPND_QLF_NIL;
+}
+
+/* Operand extractors. */
+
+int
+aarch64_ext_regno (const aarch64_operand *self, aarch64_opnd_info *info,
+ const aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ info->reg.regno = extract_field (self->fields[0], code, 0);
+ return 1;
+}
+
+/* e.g. IC <ic_op>{, <Xt>}. */
+int
+aarch64_ext_regrt_sysins (const aarch64_operand *self, aarch64_opnd_info *info,
+ const aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ info->reg.regno = extract_field (self->fields[0], code, 0);
+ assert (info->idx == 1
+ && (aarch64_get_operand_class (inst->operands[0].type)
+ == AARCH64_OPND_CLASS_SYSTEM));
+ /* This will make the constraint checking happy and more importantly will
+ help the disassembler determine whether this operand is optional or
+ not. */
+ info->present = inst->operands[0].sysins_op->has_xt;
+
+ return 1;
+}
+
+/* e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]. */
+int
+aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info,
+ const aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* regno */
+ info->reglane.regno = extract_field (self->fields[0], code,
+ inst->opcode->mask);
+
+ /* Index and/or type. */
+ if (inst->opcode->iclass == asisdone
+ || inst->opcode->iclass == asimdins)
+ {
+ if (info->type == AARCH64_OPND_En
+ && inst->opcode->operands[0] == AARCH64_OPND_Ed)
+ {
+ unsigned shift;
+ /* index2 for e.g. INS <Vd>.<Ts>[<index1>], <Vn>.<Ts>[<index2>]. */
+ assert (info->idx == 1); /* Vn */
+ aarch64_insn value = extract_field (FLD_imm4, code, 0);
+ /* Depend on AARCH64_OPND_Ed to determine the qualifier. */
+ info->qualifier = get_expected_qualifier (inst, info->idx);
+ shift = get_logsz (aarch64_get_qualifier_esize (info->qualifier));
+ info->reglane.index = value >> shift;
+ }
+ else
+ {
+ /* index and type for e.g. DUP <V><d>, <Vn>.<T>[<index>].
+ imm5<3:0> <V>
+ 0000 RESERVED
+ xxx1 B
+ xx10 H
+ x100 S
+ 1000 D */
+ int pos = -1;
+ aarch64_insn value = extract_field (FLD_imm5, code, 0);
+ while (++pos <= 3 && (value & 0x1) == 0)
+ value >>= 1;
+ if (pos > 3)
+ return 0;
+ info->qualifier = get_sreg_qualifier_from_value (pos);
+ info->reglane.index = (unsigned) (value >> 1);
+ }
+ }
+ else
+ {
+ /* Index only for e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
+ or SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]. */
+
+ /* Need information in other operand(s) to help decoding. */
+ info->qualifier = get_expected_qualifier (inst, info->idx);
+ switch (info->qualifier)
+ {
+ case AARCH64_OPND_QLF_S_H:
+ /* h:l:m */
+ info->reglane.index = extract_fields (code, 0, 3, FLD_H, FLD_L,
+ FLD_M);
+ info->reglane.regno &= 0xf;
+ break;
+ case AARCH64_OPND_QLF_S_S:
+ /* h:l */
+ info->reglane.index = extract_fields (code, 0, 2, FLD_H, FLD_L);
+ break;
+ case AARCH64_OPND_QLF_S_D:
+ /* H */
+ info->reglane.index = extract_field (FLD_H, code, 0);
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int
+aarch64_ext_reglist (const aarch64_operand *self, aarch64_opnd_info *info,
+ const aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* R */
+ info->reglist.first_regno = extract_field (self->fields[0], code, 0);
+ /* len */
+ info->reglist.num_regs = extract_field (FLD_len, code, 0) + 1;
+ return 1;
+}
+
+/* Decode Rt and opcode fields of Vt in AdvSIMD load/store instructions. */
+int
+aarch64_ext_ldst_reglist (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info, const aarch64_insn code,
+ const aarch64_inst *inst)
+{
+ aarch64_insn value;
+ /* Number of elements in each structure to be loaded/stored. */
+ unsigned expected_num = get_opcode_dependent_value (inst->opcode);
+
+ struct
+ {
+ unsigned is_reserved;
+ unsigned num_regs;
+ unsigned num_elements;
+ } data [] =
+ { {0, 4, 4},
+ {1, 4, 4},
+ {0, 4, 1},
+ {0, 4, 2},
+ {0, 3, 3},
+ {1, 3, 3},
+ {0, 3, 1},
+ {0, 1, 1},
+ {0, 2, 2},
+ {1, 2, 2},
+ {0, 2, 1},
+ };
+
+ /* Rt */
+ info->reglist.first_regno = extract_field (FLD_Rt, code, 0);
+ /* opcode */
+ value = extract_field (FLD_opcode, code, 0);
+ if (expected_num != data[value].num_elements || data[value].is_reserved)
+ return 0;
+ info->reglist.num_regs = data[value].num_regs;
+
+ return 1;
+}
+
+/* Decode Rt and S fields of Vt in AdvSIMD load single structure to all
+ lanes instructions. */
+int
+aarch64_ext_ldst_reglist_r (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info, const aarch64_insn code,
+ const aarch64_inst *inst)
+{
+ aarch64_insn value;
+
+ /* Rt */
+ info->reglist.first_regno = extract_field (FLD_Rt, code, 0);
+ /* S */
+ value = extract_field (FLD_S, code, 0);
+
+ /* Number of registers is equal to the number of elements in
+ each structure to be loaded/stored. */
+ info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
+ assert (info->reglist.num_regs >= 1 && info->reglist.num_regs <= 4);
+
+ /* Except when it is LD1R. */
+ if (info->reglist.num_regs == 1 && value == (aarch64_insn) 1)
+ info->reglist.num_regs = 2;
+
+ return 1;
+}
+
+/* Decode Q, opcode<2:1>, S, size and Rt fields of Vt in AdvSIMD
+ load/store single element instructions. */
+int
+aarch64_ext_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info, const aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ aarch64_field field = {0, 0};
+ aarch64_insn QSsize; /* fields Q:S:size. */
+ aarch64_insn opcodeh2; /* opcode<2:1> */
+
+ /* Rt */
+ info->reglist.first_regno = extract_field (FLD_Rt, code, 0);
+
+ /* Decode the index, opcode<2:1> and size. */
+ gen_sub_field (FLD_asisdlso_opcode, 1, 2, &field);
+ opcodeh2 = extract_field_2 (&field, code, 0);
+ QSsize = extract_fields (code, 0, 3, FLD_Q, FLD_S, FLD_vldst_size);
+ switch (opcodeh2)
+ {
+ case 0x0:
+ info->qualifier = AARCH64_OPND_QLF_S_B;
+ /* Index encoded in "Q:S:size". */
+ info->reglist.index = QSsize;
+ break;
+ case 0x1:
+ info->qualifier = AARCH64_OPND_QLF_S_H;
+ /* Index encoded in "Q:S:size<1>". */
+ info->reglist.index = QSsize >> 1;
+ break;
+ case 0x2:
+ if ((QSsize & 0x1) == 0)
+ {
+ info->qualifier = AARCH64_OPND_QLF_S_S;
+ /* Index encoded in "Q:S". */
+ info->reglist.index = QSsize >> 2;
+ }
+ else
+ {
+ info->qualifier = AARCH64_OPND_QLF_S_D;
+ /* Index encoded in "Q". */
+ info->reglist.index = QSsize >> 3;
+ if (extract_field (FLD_S, code, 0))
+ /* UND */
+ return 0;
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ info->reglist.has_index = 1;
+ info->reglist.num_regs = 0;
+ /* Number of registers is equal to the number of elements in
+ each structure to be loaded/stored. */
+ info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
+ assert (info->reglist.num_regs >= 1 && info->reglist.num_regs <= 4);
+
+ return 1;
+}
+
+/* Decode fields immh:immb and/or Q for e.g.
+ SSHR <Vd>.<T>, <Vn>.<T>, #<shift>
+ or SSHR <V><d>, <V><n>, #<shift>. */
+
+int
+aarch64_ext_advsimd_imm_shift (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info, const aarch64_insn code,
+ const aarch64_inst *inst)
+{
+ int pos;
+ aarch64_insn Q, imm, immh;
+ enum aarch64_insn_class iclass = inst->opcode->iclass;
+
+ immh = extract_field (FLD_immh, code, 0);
+ if (immh == 0)
+ return 0;
+ imm = extract_fields (code, 0, 2, FLD_immh, FLD_immb);
+ pos = 4;
+ /* Get highest set bit in immh. */
+ while (--pos >= 0 && (immh & 0x8) == 0)
+ immh <<= 1;
+
+ assert ((iclass == asimdshf || iclass == asisdshf)
+ && (info->type == AARCH64_OPND_IMM_VLSR
+ || info->type == AARCH64_OPND_IMM_VLSL));
+
+ if (iclass == asimdshf)
+ {
+ Q = extract_field (FLD_Q, code, 0);
+ /* immh Q <T>
+ 0000 x SEE AdvSIMD modified immediate
+ 0001 0 8B
+ 0001 1 16B
+ 001x 0 4H
+ 001x 1 8H
+ 01xx 0 2S
+ 01xx 1 4S
+ 1xxx 0 RESERVED
+ 1xxx 1 2D */
+ info->qualifier =
+ get_vreg_qualifier_from_value ((pos << 1) | (int) Q);
+ }
+ else
+ info->qualifier = get_sreg_qualifier_from_value (pos);
+
+ if (info->type == AARCH64_OPND_IMM_VLSR)
+ /* immh <shift>
+ 0000 SEE AdvSIMD modified immediate
+ 0001 (16-UInt(immh:immb))
+ 001x (32-UInt(immh:immb))
+ 01xx (64-UInt(immh:immb))
+ 1xxx (128-UInt(immh:immb)) */
+ info->imm.value = (16 << pos) - imm;
+ else
+ /* immh:immb
+ immh <shift>
+ 0000 SEE AdvSIMD modified immediate
+ 0001 (UInt(immh:immb)-8)
+ 001x (UInt(immh:immb)-16)
+ 01xx (UInt(immh:immb)-32)
+ 1xxx (UInt(immh:immb)-64) */
+ info->imm.value = imm - (8 << pos);
+
+ return 1;
+}
+
+/* Decode shift immediate for e.g. sshr (imm). */
+int
+aarch64_ext_shll_imm (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info, const aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ int64_t imm;
+ aarch64_insn val;
+ val = extract_field (FLD_size, code, 0);
+ switch (val)
+ {
+ case 0: imm = 8; break;
+ case 1: imm = 16; break;
+ case 2: imm = 32; break;
+ default: return 0;
+ }
+ info->imm.value = imm;
+ return 1;
+}
+
+/* Decode imm for e.g. BFM <Wd>, <Wn>, #<immr>, #<imms>.
+ value in the field(s) will be extracted as unsigned immediate value. */
+int
+aarch64_ext_imm (const aarch64_operand *self, aarch64_opnd_info *info,
+ const aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ int64_t imm;
+ /* Maximum of two fields to extract. */
+ assert (self->fields[2] == FLD_NIL);
+
+ if (self->fields[1] == FLD_NIL)
+ imm = extract_field (self->fields[0], code, 0);
+ else
+ /* e.g. TBZ b5:b40. */
+ imm = extract_fields (code, 0, 2, self->fields[0], self->fields[1]);
+
+ if (info->type == AARCH64_OPND_FPIMM)
+ info->imm.is_fp = 1;
+
+ if (operand_need_sign_extension (self))
+ imm = sign_extend (imm, get_operand_fields_width (self) - 1);
+
+ if (operand_need_shift_by_two (self))
+ imm <<= 2;
+
+ if (info->type == AARCH64_OPND_ADDR_ADRP)
+ imm <<= 12;
+
+ info->imm.value = imm;
+ return 1;
+}
+
+/* Decode imm and its shifter for e.g. MOVZ <Wd>, #<imm16>{, LSL #<shift>}. */
+int
+aarch64_ext_imm_half (const aarch64_operand *self, aarch64_opnd_info *info,
+ const aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ aarch64_ext_imm (self, info, code, inst);
+ info->shifter.kind = AARCH64_MOD_LSL;
+ info->shifter.amount = extract_field (FLD_hw, code, 0) << 4;
+ return 1;
+}
+
+/* Decode cmode and "a:b:c:d:e:f:g:h" for e.g.
+ MOVI <Vd>.<T>, #<imm8> {, LSL #<amount>}. */
+int
+aarch64_ext_advsimd_imm_modified (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info,
+ const aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ uint64_t imm;
+ enum aarch64_opnd_qualifier opnd0_qualifier = inst->operands[0].qualifier;
+ aarch64_field field = {0, 0};
+
+ assert (info->idx == 1);
+
+ if (info->type == AARCH64_OPND_SIMD_FPIMM)
+ info->imm.is_fp = 1;
+
+ /* a:b:c:d:e:f:g:h */
+ imm = extract_fields (code, 0, 2, FLD_abc, FLD_defgh);
+ if (!info->imm.is_fp && aarch64_get_qualifier_esize (opnd0_qualifier) == 8)
+ {
+ /* Either MOVI <Dd>, #<imm>
+ or MOVI <Vd>.2D, #<imm>.
+ <imm> is a 64-bit immediate
+ 'aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh',
+ encoded in "a:b:c:d:e:f:g:h". */
+ int i;
+ unsigned abcdefgh = imm;
+ for (imm = 0ull, i = 0; i < 8; i++)
+ if (((abcdefgh >> i) & 0x1) != 0)
+ imm |= 0xffull << (8 * i);
+ }
+ info->imm.value = imm;
+
+ /* cmode */
+ info->qualifier = get_expected_qualifier (inst, info->idx);
+ switch (info->qualifier)
+ {
+ case AARCH64_OPND_QLF_NIL:
+ /* no shift */
+ info->shifter.kind = AARCH64_MOD_NONE;
+ return 1;
+ case AARCH64_OPND_QLF_LSL:
+ /* shift zeros */
+ info->shifter.kind = AARCH64_MOD_LSL;
+ switch (aarch64_get_qualifier_esize (opnd0_qualifier))
+ {
+ case 4: gen_sub_field (FLD_cmode, 1, 2, &field); break; /* per word */
+ case 2: gen_sub_field (FLD_cmode, 1, 1, &field); break; /* per half */
+ default: assert (0); return 0;
+ }
+ /* 00: 0; 01: 8; 10:16; 11:24. */
+ info->shifter.amount = extract_field_2 (&field, code, 0) << 3;
+ break;
+ case AARCH64_OPND_QLF_MSL:
+ /* shift ones */
+ info->shifter.kind = AARCH64_MOD_MSL;
+ gen_sub_field (FLD_cmode, 0, 1, &field); /* per word */
+ info->shifter.amount = extract_field_2 (&field, code, 0) ? 16 : 8;
+ break;
+ default:
+ assert (0);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Decode scale for e.g. SCVTF <Dd>, <Wn>, #<fbits>. */
+int
+aarch64_ext_fbits (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info, const aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ info->imm.value = 64- extract_field (FLD_scale, code, 0);
+ return 1;
+}
+
+/* Decode arithmetic immediate for e.g.
+ SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}. */
+int
+aarch64_ext_aimm (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info, const aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ aarch64_insn value;
+
+ info->shifter.kind = AARCH64_MOD_LSL;
+ /* shift */
+ value = extract_field (FLD_shift, code, 0);
+ if (value >= 2)
+ return 0;
+ info->shifter.amount = value ? 12 : 0;
+ /* imm12 (unsigned) */
+ info->imm.value = extract_field (FLD_imm12, code, 0);
+
+ return 1;
+}
+
+/* Decode logical immediate for e.g. ORR <Wd|WSP>, <Wn>, #<imm>. */
+
+int
+aarch64_ext_limm (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info, const aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ uint64_t imm, mask;
+ uint32_t sf;
+ uint32_t N, R, S;
+ unsigned simd_size;
+ aarch64_insn value;
+
+ value = extract_fields (code, 0, 3, FLD_N, FLD_immr, FLD_imms);
+ assert (inst->operands[0].qualifier == AARCH64_OPND_QLF_W
+ || inst->operands[0].qualifier == AARCH64_OPND_QLF_X);
+ sf = aarch64_get_qualifier_esize (inst->operands[0].qualifier) != 4;
+
+ /* value is N:immr:imms. */
+ S = value & 0x3f;
+ R = (value >> 6) & 0x3f;
+ N = (value >> 12) & 0x1;
+
+ if (sf == 0 && N == 1)
+ return 0;
+
+ /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
+ (in other words, right rotated by R), then replicated. */
+ if (N != 0)
+ {
+ simd_size = 64;
+ mask = 0xffffffffffffffffull;
+ }
+ else
+ {
+ switch (S)
+ {
+ case 0x00 ... 0x1f: /* 0xxxxx */ simd_size = 32; break;
+ case 0x20 ... 0x2f: /* 10xxxx */ simd_size = 16; S &= 0xf; break;
+ case 0x30 ... 0x37: /* 110xxx */ simd_size = 8; S &= 0x7; break;
+ case 0x38 ... 0x3b: /* 1110xx */ simd_size = 4; S &= 0x3; break;
+ case 0x3c ... 0x3d: /* 11110x */ simd_size = 2; S &= 0x1; break;
+ default: return 0;
+ }
+ mask = (1ull << simd_size) - 1;
+ /* Top bits are IGNORED. */
+ R &= simd_size - 1;
+ }
+ /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */
+ if (S == simd_size - 1)
+ return 0;
+ /* S+1 consecutive bits to 1. */
+ /* NOTE: S can't be 63 due to detection above. */
+ imm = (1ull << (S + 1)) - 1;
+ /* Rotate to the left by simd_size - R. */
+ if (R != 0)
+ imm = ((imm << (simd_size - R)) & mask) | (imm >> R);
+ /* Replicate the value according to SIMD size. */
+ switch (simd_size)
+ {
+ case 2: imm = (imm << 2) | imm;
+ case 4: imm = (imm << 4) | imm;
+ case 8: imm = (imm << 8) | imm;
+ case 16: imm = (imm << 16) | imm;
+ case 32: imm = (imm << 32) | imm;
+ case 64: break;
+ default: assert (0); return 0;
+ }
+
+ info->imm.value = sf ? imm : imm & 0xffffffff;
+
+ return 1;
+}
+
+/* Decode Ft for e.g. STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]
+ or LDP <Qt1>, <Qt2>, [<Xn|SP>], #<imm>. */
+int
+aarch64_ext_ft (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info,
+ const aarch64_insn code, const aarch64_inst *inst)
+{
+ aarch64_insn value;
+
+ /* Rt */
+ info->reg.regno = extract_field (FLD_Rt, code, 0);
+
+ /* size */
+ value = extract_field (FLD_ldst_size, code, 0);
+ if (inst->opcode->iclass == ldstpair_indexed
+ || inst->opcode->iclass == ldstnapair_offs
+ || inst->opcode->iclass == ldstpair_off
+ || inst->opcode->iclass == loadlit)
+ {
+ enum aarch64_opnd_qualifier qualifier;
+ switch (value)
+ {
+ case 0: qualifier = AARCH64_OPND_QLF_S_S; break;
+ case 1: qualifier = AARCH64_OPND_QLF_S_D; break;
+ case 2: qualifier = AARCH64_OPND_QLF_S_Q; break;
+ default: return 0;
+ }
+ info->qualifier = qualifier;
+ }
+ else
+ {
+ /* opc1:size */
+ value = extract_fields (code, 0, 2, FLD_opc1, FLD_ldst_size);
+ if (value > 0x4)
+ return 0;
+ info->qualifier = get_sreg_qualifier_from_value (value);
+ }
+
+ return 1;
+}
+
+/* Decode the address operand for e.g. STXRB <Ws>, <Wt>, [<Xn|SP>{,#0}]. */
+int
+aarch64_ext_addr_simple (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info,
+ aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* Rn */
+ info->addr.base_regno = extract_field (FLD_Rn, code, 0);
+ return 1;
+}
+
+/* Decode the address operand for e.g.
+ STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
+int
+aarch64_ext_addr_regoff (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info,
+ aarch64_insn code, const aarch64_inst *inst)
+{
+ aarch64_insn S, value;
+
+ /* Rn */
+ info->addr.base_regno = extract_field (FLD_Rn, code, 0);
+ /* Rm */
+ info->addr.offset.regno = extract_field (FLD_Rm, code, 0);
+ /* option */
+ value = extract_field (FLD_option, code, 0);
+ info->shifter.kind =
+ aarch64_get_operand_modifier_from_value (value, TRUE /* extend_p */);
+ /* Fix-up the shifter kind; although the table-driven approach is
+ efficient, it is slightly inflexible, thus needing this fix-up. */
+ if (info->shifter.kind == AARCH64_MOD_UXTX)
+ info->shifter.kind = AARCH64_MOD_LSL;
+ /* S */
+ S = extract_field (FLD_S, code, 0);
+ if (S == 0)
+ {
+ info->shifter.amount = 0;
+ info->shifter.amount_present = 0;
+ }
+ else
+ {
+ int size;
+ /* Need information in other operand(s) to help achieve the decoding
+ from 'S' field. */
+ info->qualifier = get_expected_qualifier (inst, info->idx);
+ /* Get the size of the data element that is accessed, which may be
+ different from that of the source register size, e.g. in strb/ldrb. */
+ size = aarch64_get_qualifier_esize (info->qualifier);
+ info->shifter.amount = get_logsz (size);
+ info->shifter.amount_present = 1;
+ }
+
+ return 1;
+}
+
+/* Decode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>], #<simm>. */
+int
+aarch64_ext_addr_simm (const aarch64_operand *self, aarch64_opnd_info *info,
+ aarch64_insn code, const aarch64_inst *inst)
+{
+ aarch64_insn imm;
+ info->qualifier = get_expected_qualifier (inst, info->idx);
+
+ /* Rn */
+ info->addr.base_regno = extract_field (FLD_Rn, code, 0);
+ /* simm (imm9 or imm7) */
+ imm = extract_field (self->fields[0], code, 0);
+ info->addr.offset.imm = sign_extend (imm, fields[self->fields[0]].width - 1);
+ if (self->fields[0] == FLD_imm7)
+ /* scaled immediate in ld/st pair instructions. */
+ info->addr.offset.imm *= aarch64_get_qualifier_esize (info->qualifier);
+ /* qualifier */
+ if (inst->opcode->iclass == ldst_unscaled
+ || inst->opcode->iclass == ldstnapair_offs
+ || inst->opcode->iclass == ldstpair_off
+ || inst->opcode->iclass == ldst_unpriv)
+ info->addr.writeback = 0;
+ else
+ {
+ /* pre/post- index */
+ info->addr.writeback = 1;
+ if (extract_field (self->fields[1], code, 0) == 1)
+ info->addr.preind = 1;
+ else
+ info->addr.postind = 1;
+ }
+
+ return 1;
+}
+
+/* Decode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>{, #<simm>}]. */
+int
+aarch64_ext_addr_uimm12 (const aarch64_operand *self, aarch64_opnd_info *info,
+ aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ int shift;
+ info->qualifier = get_expected_qualifier (inst, info->idx);
+ shift = get_logsz (aarch64_get_qualifier_esize (info->qualifier));
+ /* Rn */
+ info->addr.base_regno = extract_field (self->fields[0], code, 0);
+ /* uimm12 */
+ info->addr.offset.imm = extract_field (self->fields[1], code, 0) << shift;
+ return 1;
+}
+
+/* Decode the address operand for e.g.
+ LD1 {<Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>}, [<Xn|SP>], <Xm|#<amount>>. */
+int
+aarch64_ext_simd_addr_post (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info,
+ aarch64_insn code, const aarch64_inst *inst)
+{
+ /* The opcode dependent area stores the number of elements in
+ each structure to be loaded/stored. */
+ int is_ld1r = get_opcode_dependent_value (inst->opcode) == 1;
+
+ /* Rn */
+ info->addr.base_regno = extract_field (FLD_Rn, code, 0);
+ /* Rm | #<amount> */
+ info->addr.offset.regno = extract_field (FLD_Rm, code, 0);
+ if (info->addr.offset.regno == 31)
+ {
+ if (inst->opcode->operands[0] == AARCH64_OPND_LVt_AL)
+ /* Special handling of loading single structure to all lane. */
+ info->addr.offset.imm = (is_ld1r ? 1
+ : inst->operands[0].reglist.num_regs)
+ * aarch64_get_qualifier_esize (inst->operands[0].qualifier);
+ else
+ info->addr.offset.imm = inst->operands[0].reglist.num_regs
+ * aarch64_get_qualifier_esize (inst->operands[0].qualifier)
+ * aarch64_get_qualifier_nelem (inst->operands[0].qualifier);
+ }
+ else
+ info->addr.offset.is_reg = 1;
+ info->addr.writeback = 1;
+
+ return 1;
+}
+
+/* Decode the condition operand for e.g. CSEL <Xd>, <Xn>, <Xm>, <cond>. */
+int
+aarch64_ext_cond (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info,
+ aarch64_insn code, const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ aarch64_insn value;
+ /* cond */
+ value = extract_field (FLD_cond, code, 0);
+ info->cond = get_cond_from_value (value);
+ return 1;
+}
+
+/* Decode the system register operand for e.g. MRS <Xt>, <systemreg>. */
+int
+aarch64_ext_sysreg (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info,
+ aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* op0:op1:CRn:CRm:op2 */
+ info->sysreg = extract_fields (code, 0, 5, FLD_op0, FLD_op1, FLD_CRn,
+ FLD_CRm, FLD_op2);
+ return 1;
+}
+
+/* Decode the PSTATE field operand for e.g. MSR <pstatefield>, #<imm>. */
+int
+aarch64_ext_pstatefield (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info, aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ int i;
+ /* op1:op2 */
+ info->pstatefield = extract_fields (code, 0, 2, FLD_op1, FLD_op2);
+ for (i = 0; aarch64_pstatefields[i].name != NULL; ++i)
+ if (aarch64_pstatefields[i].value == (aarch64_insn)info->pstatefield)
+ return 1;
+ /* Reserved value in <pstatefield>. */
+ return 0;
+}
+
+/* Decode the system instruction op operand for e.g. AT <at_op>, <Xt>. */
+int
+aarch64_ext_sysins_op (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info,
+ aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ int i;
+ aarch64_insn value;
+ const aarch64_sys_ins_reg *sysins_ops;
+ /* op0:op1:CRn:CRm:op2 */
+ value = extract_fields (code, 0, 5,
+ FLD_op0, FLD_op1, FLD_CRn,
+ FLD_CRm, FLD_op2);
+
+ switch (info->type)
+ {
+ case AARCH64_OPND_SYSREG_AT: sysins_ops = aarch64_sys_regs_at; break;
+ case AARCH64_OPND_SYSREG_DC: sysins_ops = aarch64_sys_regs_dc; break;
+ case AARCH64_OPND_SYSREG_IC: sysins_ops = aarch64_sys_regs_ic; break;
+ case AARCH64_OPND_SYSREG_TLBI: sysins_ops = aarch64_sys_regs_tlbi; break;
+ default: assert (0); return 0;
+ }
+
+ for (i = 0; sysins_ops[i].template != NULL; ++i)
+ if (sysins_ops[i].value == value)
+ {
+ info->sysins_op = sysins_ops + i;
+ DEBUG_TRACE ("%s found value: %x, has_xt: %d, i: %d.",
+ info->sysins_op->template,
+ (unsigned)info->sysins_op->value,
+ info->sysins_op->has_xt, i);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Decode the memory barrier option operand for e.g. DMB <option>|#<imm>. */
+
+int
+aarch64_ext_barrier (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info,
+ aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* CRm */
+ info->barrier = aarch64_barrier_options + extract_field (FLD_CRm, code, 0);
+ return 1;
+}
+
+/* Decode the prefetch operation option operand for e.g.
+ PRFM <prfop>, [<Xn|SP>{, #<pimm>}]. */
+
+int
+aarch64_ext_prfop (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info,
+ aarch64_insn code, const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* prfop in Rt */
+ info->prfop = aarch64_prfops + extract_field (FLD_Rt, code, 0);
+ return 1;
+}
+
+/* Decode the extended register operand for e.g.
+ STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
+int
+aarch64_ext_reg_extended (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info,
+ aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ aarch64_insn value;
+
+ /* Rm */
+ info->reg.regno = extract_field (FLD_Rm, code, 0);
+ /* option */
+ value = extract_field (FLD_option, code, 0);
+ info->shifter.kind =
+ aarch64_get_operand_modifier_from_value (value, TRUE /* extend_p */);
+ /* imm3 */
+ info->shifter.amount = extract_field (FLD_imm3, code, 0);
+
+ /* This makes the constraint checking happy. */
+ info->shifter.operator_present = 1;
+
+ /* Assume inst->operands[0].qualifier has been resolved. */
+ assert (inst->operands[0].qualifier != AARCH64_OPND_QLF_NIL);
+ info->qualifier = AARCH64_OPND_QLF_W;
+ if (inst->operands[0].qualifier == AARCH64_OPND_QLF_X
+ && (info->shifter.kind == AARCH64_MOD_UXTX
+ || info->shifter.kind == AARCH64_MOD_SXTX))
+ info->qualifier = AARCH64_OPND_QLF_X;
+
+ return 1;
+}
+
+/* Decode the shifted register operand for e.g.
+ SUBS <Xd>, <Xn>, <Xm> {, <shift> #<amount>}. */
+int
+aarch64_ext_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ aarch64_opnd_info *info,
+ aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ aarch64_insn value;
+
+ /* Rm */
+ info->reg.regno = extract_field (FLD_Rm, code, 0);
+ /* shift */
+ value = extract_field (FLD_shift, code, 0);
+ info->shifter.kind =
+ aarch64_get_operand_modifier_from_value (value, FALSE /* extend_p */);
+ if (info->shifter.kind == AARCH64_MOD_ROR
+ && inst->opcode->iclass != log_shift)
+ /* ROR is not available for the shifted register operand in arithmetic
+ instructions. */
+ return 0;
+ /* imm6 */
+ info->shifter.amount = extract_field (FLD_imm6, code, 0);
+
+ /* This makes the constraint checking happy. */
+ info->shifter.operator_present = 1;
+
+ return 1;
+}
+
+/* Bitfields that are commonly used to encode certain operands' information
+ may be partially used as part of the base opcode in some instructions.
+ For example, the bit 1 of the field 'size' in
+ FCVTXN <Vb><d>, <Va><n>
+ is actually part of the base opcode, while only size<0> is available
+ for encoding the register type. Another example is the AdvSIMD
+ instruction ORR (register), in which the field 'size' is also used for
+ the base opcode, leaving only the field 'Q' available to encode the
+ vector register arrangement specifier '8B' or '16B'.
+
+ This function tries to deduce the qualifier from the value of partially
+ constrained field(s). Given the VALUE of such a field or fields, the
+ qualifiers CANDIDATES and the MASK (indicating which bits are valid for
+ operand encoding), the function returns the matching qualifier or
+ AARCH64_OPND_QLF_NIL if nothing matches.
+
+ N.B. CANDIDATES is a group of possible qualifiers that are valid for
+ one operand; it has a maximum of AARCH64_MAX_QLF_SEQ_NUM qualifiers and
+ may end with AARCH64_OPND_QLF_NIL. */
+
+static enum aarch64_opnd_qualifier
+get_qualifier_from_partial_encoding (aarch64_insn value,
+ const enum aarch64_opnd_qualifier* \
+ candidates,
+ aarch64_insn mask)
+{
+ int i;
+ DEBUG_TRACE ("enter with value: %d, mask: %d", (int)value, (int)mask);
+ for (i = 0; i < AARCH64_MAX_QLF_SEQ_NUM; ++i)
+ {
+ aarch64_insn standard_value;
+ if (candidates[i] == AARCH64_OPND_QLF_NIL)
+ break;
+ standard_value = aarch64_get_qualifier_standard_value (candidates[i]);
+ if ((standard_value & mask) == (value & mask))
+ return candidates[i];
+ }
+ return AARCH64_OPND_QLF_NIL;
+}
+
+/* Given a list of qualifier sequences, return all possible valid qualifiers
+ for operand IDX in QUALIFIERS.
+ Assume QUALIFIERS is an array whose length is large enough. */
+
+static void
+get_operand_possible_qualifiers (int idx,
+ const aarch64_opnd_qualifier_seq_t *list,
+ enum aarch64_opnd_qualifier *qualifiers)
+{
+ int i;
+ for (i = 0; i < AARCH64_MAX_QLF_SEQ_NUM; ++i)
+ if ((qualifiers[i] = list[i][idx]) == AARCH64_OPND_QLF_NIL)
+ break;
+}
+
+/* Decode the size Q field for e.g. SHADD.
+ We tag one operand with the qualifer according to the code;
+ whether the qualifier is valid for this opcode or not, it is the
+ duty of the semantic checking. */
+
+static int
+decode_sizeq (aarch64_inst *inst)
+{
+ int idx;
+ enum aarch64_opnd_qualifier qualifier;
+ aarch64_insn code;
+ aarch64_insn value, mask;
+ enum aarch64_field_kind fld_sz;
+ enum aarch64_opnd_qualifier candidates[AARCH64_MAX_QLF_SEQ_NUM];
+
+ if (inst->opcode->iclass == asisdlse
+ || inst->opcode->iclass == asisdlsep
+ || inst->opcode->iclass == asisdlso
+ || inst->opcode->iclass == asisdlsop)
+ fld_sz = FLD_vldst_size;
+ else
+ fld_sz = FLD_size;
+
+ code = inst->value;
+ value = extract_fields (code, inst->opcode->mask, 2, fld_sz, FLD_Q);
+ /* Obtain the info that which bits of fields Q and size are actually
+ available for operand encoding. Opcodes like FMAXNM and FMLA have
+ size[1] unavailable. */
+ mask = extract_fields (~inst->opcode->mask, 0, 2, fld_sz, FLD_Q);
+
+ /* The index of the operand we are going to tag a qualifier and the qualifer
+ itself are reasoned from the value of the size and Q fields and the
+ possible valid qualifier lists. */
+ idx = aarch64_select_operand_for_sizeq_field_coding (inst->opcode);
+ DEBUG_TRACE ("key idx: %d", idx);
+
+ /* For most related instruciton, size:Q are fully available for operand
+ encoding. */
+ if (mask == 0x7)
+ {
+ inst->operands[idx].qualifier = get_vreg_qualifier_from_value (value);
+ return 1;
+ }
+
+ get_operand_possible_qualifiers (idx, inst->opcode->qualifiers_list,
+ candidates);
+#ifdef DEBUG_AARCH64
+ if (debug_dump)
+ {
+ int i;
+ for (i = 0; candidates[i] != AARCH64_OPND_QLF_NIL
+ && i < AARCH64_MAX_QLF_SEQ_NUM; ++i)
+ DEBUG_TRACE ("qualifier %d: %s", i,
+ aarch64_get_qualifier_name(candidates[i]));
+ DEBUG_TRACE ("%d, %d", (int)value, (int)mask);
+ }
+#endif /* DEBUG_AARCH64 */
+
+ qualifier = get_qualifier_from_partial_encoding (value, candidates, mask);
+
+ if (qualifier == AARCH64_OPND_QLF_NIL)
+ return 0;
+
+ inst->operands[idx].qualifier = qualifier;
+ return 1;
+}
+
+/* Decode size[0]:Q, i.e. bit 22 and bit 30, for
+ e.g. FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
+
+static int
+decode_asimd_fcvt (aarch64_inst *inst)
+{
+ aarch64_field field = {0, 0};
+ aarch64_insn value;
+ enum aarch64_opnd_qualifier qualifier;
+
+ gen_sub_field (FLD_size, 0, 1, &field);
+ value = extract_field_2 (&field, inst->value, 0);
+ qualifier = value == 0 ? AARCH64_OPND_QLF_V_4S
+ : AARCH64_OPND_QLF_V_2D;
+ switch (inst->opcode->op)
+ {
+ case OP_FCVTN:
+ case OP_FCVTN2:
+ /* FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
+ inst->operands[1].qualifier = qualifier;
+ break;
+ case OP_FCVTL:
+ case OP_FCVTL2:
+ /* FCVTL<Q> <Vd>.<Ta>, <Vn>.<Tb>. */
+ inst->operands[0].qualifier = qualifier;
+ break;
+ default:
+ assert (0);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Decode size[0], i.e. bit 22, for
+ e.g. FCVTXN <Vb><d>, <Va><n>. */
+
+static int
+decode_asisd_fcvtxn (aarch64_inst *inst)
+{
+ aarch64_field field = {0, 0};
+ gen_sub_field (FLD_size, 0, 1, &field);
+ if (!extract_field_2 (&field, inst->value, 0))
+ return 0;
+ inst->operands[0].qualifier = AARCH64_OPND_QLF_S_S;
+ return 1;
+}
+
+/* Decode the 'opc' field for e.g. FCVT <Dd>, <Sn>. */
+static int
+decode_fcvt (aarch64_inst *inst)
+{
+ enum aarch64_opnd_qualifier qualifier;
+ aarch64_insn value;
+ const aarch64_field field = {15, 2};
+
+ /* opc dstsize */
+ value = extract_field_2 (&field, inst->value, 0);
+ switch (value)
+ {
+ case 0: qualifier = AARCH64_OPND_QLF_S_S; break;
+ case 1: qualifier = AARCH64_OPND_QLF_S_D; break;
+ case 3: qualifier = AARCH64_OPND_QLF_S_H; break;
+ default: return 0;
+ }
+ inst->operands[0].qualifier = qualifier;
+
+ return 1;
+}
+
+/* Do miscellaneous decodings that are not common enough to be driven by
+ flags. */
+
+static int
+do_misc_decoding (aarch64_inst *inst)
+{
+ switch (inst->opcode->op)
+ {
+ case OP_FCVT:
+ return decode_fcvt (inst);
+ case OP_FCVTN:
+ case OP_FCVTN2:
+ case OP_FCVTL:
+ case OP_FCVTL2:
+ return decode_asimd_fcvt (inst);
+ case OP_FCVTXN_S:
+ return decode_asisd_fcvtxn (inst);
+ default:
+ return 0;
+ }
+}
+
+/* Opcodes that have fields shared by multiple operands are usually flagged
+ with flags. In this function, we detect such flags, decode the related
+ field(s) and store the information in one of the related operands. The
+ 'one' operand is not any operand but one of the operands that can
+ accommadate all the information that has been decoded. */
+
+static int
+do_special_decoding (aarch64_inst *inst)
+{
+ int idx;
+ aarch64_insn value;
+ /* Condition for truly conditional executed instructions, e.g. b.cond. */
+ if (inst->opcode->flags & F_COND)
+ {
+ value = extract_field (FLD_cond2, inst->value, 0);
+ inst->cond = get_cond_from_value (value);
+ }
+ /* 'sf' field. */
+ if (inst->opcode->flags & F_SF)
+ {
+ idx = select_operand_for_sf_field_coding (inst->opcode);
+ value = extract_field (FLD_sf, inst->value, 0);
+ inst->operands[idx].qualifier = get_greg_qualifier_from_value (value);
+ if ((inst->opcode->flags & F_N)
+ && extract_field (FLD_N, inst->value, 0) != value)
+ return 0;
+ }
+ /* size:Q fields. */
+ if (inst->opcode->flags & F_SIZEQ)
+ return decode_sizeq (inst);
+
+ if (inst->opcode->flags & F_FPTYPE)
+ {
+ idx = select_operand_for_fptype_field_coding (inst->opcode);
+ value = extract_field (FLD_type, inst->value, 0);
+ switch (value)
+ {
+ case 0: inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_S; break;
+ case 1: inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_D; break;
+ case 3: inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_H; break;
+ default: return 0;
+ }
+ }
+
+ if (inst->opcode->flags & F_SSIZE)
+ {
+ /* N.B. some opcodes like FCMGT <V><d>, <V><n>, #0 have the size[1] as part
+ of the base opcode. */
+ aarch64_insn mask;
+ enum aarch64_opnd_qualifier candidates[AARCH64_MAX_QLF_SEQ_NUM];
+ idx = select_operand_for_scalar_size_field_coding (inst->opcode);
+ value = extract_field (FLD_size, inst->value, inst->opcode->mask);
+ mask = extract_field (FLD_size, ~inst->opcode->mask, 0);
+ /* For most related instruciton, the 'size' field is fully available for
+ operand encoding. */
+ if (mask == 0x3)
+ inst->operands[idx].qualifier = get_sreg_qualifier_from_value (value);
+ else
+ {
+ get_operand_possible_qualifiers (idx, inst->opcode->qualifiers_list,
+ candidates);
+ inst->operands[idx].qualifier
+ = get_qualifier_from_partial_encoding (value, candidates, mask);
+ }
+ }
+
+ if (inst->opcode->flags & F_T)
+ {
+ /* Num of consecutive '0's on the right side of imm5<3:0>. */
+ int num = 0;
+ unsigned val, Q;
+ assert (aarch64_get_operand_class (inst->opcode->operands[0])
+ == AARCH64_OPND_CLASS_SIMD_REG);
+ /* imm5<3:0> q <t>
+ 0000 x reserved
+ xxx1 0 8b
+ xxx1 1 16b
+ xx10 0 4h
+ xx10 1 8h
+ x100 0 2s
+ x100 1 4s
+ 1000 0 reserved
+ 1000 1 2d */
+ val = extract_field (FLD_imm5, inst->value, 0);
+ while ((val & 0x1) == 0 && ++num <= 3)
+ val >>= 1;
+ if (num > 3)
+ return 0;
+ Q = (unsigned) extract_field (FLD_Q, inst->value, inst->opcode->mask);
+ inst->operands[0].qualifier =
+ get_vreg_qualifier_from_value ((num << 1) | Q);
+ }
+
+ if (inst->opcode->flags & F_GPRSIZE_IN_Q)
+ {
+ /* Use Rt to encode in the case of e.g.
+ STXP <Ws>, <Xt1>, <Xt2>, [<Xn|SP>{,#0}]. */
+ idx = aarch64_operand_index (inst->opcode->operands, AARCH64_OPND_Rt);
+ if (idx == -1)
+ {
+ /* Otherwise use the result operand, which has to be a integer
+ register. */
+ assert (aarch64_get_operand_class (inst->opcode->operands[0])
+ == AARCH64_OPND_CLASS_INT_REG);
+ idx = 0;
+ }
+ assert (idx == 0 || idx == 1);
+ value = extract_field (FLD_Q, inst->value, 0);
+ inst->operands[idx].qualifier = get_greg_qualifier_from_value (value);
+ }
+
+ if (inst->opcode->flags & F_LDS_SIZE)
+ {
+ aarch64_field field = {0, 0};
+ assert (aarch64_get_operand_class (inst->opcode->operands[0])
+ == AARCH64_OPND_CLASS_INT_REG);
+ gen_sub_field (FLD_opc, 0, 1, &field);
+ value = extract_field_2 (&field, inst->value, 0);
+ inst->operands[0].qualifier
+ = value ? AARCH64_OPND_QLF_W : AARCH64_OPND_QLF_X;
+ }
+
+ /* Miscellaneous decoding; done as the last step. */
+ if (inst->opcode->flags & F_MISC)
+ return do_misc_decoding (inst);
+
+ return 1;
+}
+
+/* Converters converting a real opcode instruction to its alias form. */
+
+/* ROR <Wd>, <Ws>, #<shift>
+ is equivalent to:
+ EXTR <Wd>, <Ws>, <Ws>, #<shift>. */
+static int
+convert_extr_to_ror (aarch64_inst *inst)
+{
+ if (inst->operands[1].reg.regno == inst->operands[2].reg.regno)
+ {
+ copy_operand_info (inst, 2, 3);
+ inst->operands[3].type = AARCH64_OPND_NIL;
+ return 1;
+ }
+ return 0;
+}
+
+/* Convert
+ UBFM <Xd>, <Xn>, #<shift>, #63.
+ to
+ LSR <Xd>, <Xn>, #<shift>. */
+static int
+convert_bfm_to_sr (aarch64_inst *inst)
+{
+ int64_t imms, val;
+
+ imms = inst->operands[3].imm.value;
+ val = inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 31 : 63;
+ if (imms == val)
+ {
+ inst->operands[3].type = AARCH64_OPND_NIL;
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Convert MOV to ORR. */
+static int
+convert_orr_to_mov (aarch64_inst *inst)
+{
+ /* MOV <Vd>.<T>, <Vn>.<T>
+ is equivalent to:
+ ORR <Vd>.<T>, <Vn>.<T>, <Vn>.<T>. */
+ if (inst->operands[1].reg.regno == inst->operands[2].reg.regno)
+ {
+ inst->operands[2].type = AARCH64_OPND_NIL;
+ return 1;
+ }
+ return 0;
+}
+
+/* When <imms> >= <immr>, the instruction written:
+ SBFX <Xd>, <Xn>, #<lsb>, #<width>
+ is equivalent to:
+ SBFM <Xd>, <Xn>, #<lsb>, #(<lsb>+<width>-1). */
+
+static int
+convert_bfm_to_bfx (aarch64_inst *inst)
+{
+ int64_t immr, imms;
+
+ immr = inst->operands[2].imm.value;
+ imms = inst->operands[3].imm.value;
+ if (imms >= immr)
+ {
+ int64_t lsb = immr;
+ inst->operands[2].imm.value = lsb;
+ inst->operands[3].imm.value = imms + 1 - lsb;
+ /* The two opcodes have different qualifiers for
+ the immediate operands; reset to help the checking. */
+ reset_operand_qualifier (inst, 2);
+ reset_operand_qualifier (inst, 3);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* When <imms> < <immr>, the instruction written:
+ SBFIZ <Xd>, <Xn>, #<lsb>, #<width>
+ is equivalent to:
+ SBFM <Xd>, <Xn>, #((64-<lsb>)&0x3f), #(<width>-1). */
+
+static int
+convert_bfm_to_bfi (aarch64_inst *inst)
+{
+ int64_t immr, imms, val;
+
+ immr = inst->operands[2].imm.value;
+ imms = inst->operands[3].imm.value;
+ val = inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 32 : 64;
+ if (imms < immr)
+ {
+ inst->operands[2].imm.value = (val - immr) & (val - 1);
+ inst->operands[3].imm.value = imms + 1;
+ /* The two opcodes have different qualifiers for
+ the immediate operands; reset to help the checking. */
+ reset_operand_qualifier (inst, 2);
+ reset_operand_qualifier (inst, 3);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* The instruction written:
+ LSL <Xd>, <Xn>, #<shift>
+ is equivalent to:
+ UBFM <Xd>, <Xn>, #((64-<shift>)&0x3f), #(63-<shift>). */
+
+static int
+convert_ubfm_to_lsl (aarch64_inst *inst)
+{
+ int64_t immr = inst->operands[2].imm.value;
+ int64_t imms = inst->operands[3].imm.value;
+ int64_t val
+ = inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 31 : 63;
+
+ if ((immr == 0 && imms == val) || immr == imms + 1)
+ {
+ inst->operands[3].type = AARCH64_OPND_NIL;
+ inst->operands[2].imm.value = val - imms;
+ return 1;
+ }
+
+ return 0;
+}
+
+/* CINC <Wd>, <Wn>, <cond>
+ is equivalent to:
+ CSINC <Wd>, <Wn>, <Wn>, invert(<cond>). */
+
+static int
+convert_from_csel (aarch64_inst *inst)
+{
+ if (inst->operands[1].reg.regno == inst->operands[2].reg.regno)
+ {
+ copy_operand_info (inst, 2, 3);
+ inst->operands[2].cond = get_inverted_cond (inst->operands[3].cond);
+ inst->operands[3].type = AARCH64_OPND_NIL;
+ return 1;
+ }
+ return 0;
+}
+
+/* CSET <Wd>, <cond>
+ is equivalent to:
+ CSINC <Wd>, WZR, WZR, invert(<cond>). */
+
+static int
+convert_csinc_to_cset (aarch64_inst *inst)
+{
+ if (inst->operands[1].reg.regno == 0x1f
+ && inst->operands[2].reg.regno == 0x1f)
+ {
+ copy_operand_info (inst, 1, 3);
+ inst->operands[1].cond = get_inverted_cond (inst->operands[3].cond);
+ inst->operands[3].type = AARCH64_OPND_NIL;
+ inst->operands[2].type = AARCH64_OPND_NIL;
+ return 1;
+ }
+ return 0;
+}
+
+/* MOV <Wd>, #<imm>
+ is equivalent to:
+ MOVZ <Wd>, #<imm16>, LSL #<shift>.
+
+ A disassembler may output ORR, MOVZ and MOVN as a MOV mnemonic, except when
+ ORR has an immediate that could be generated by a MOVZ or MOVN instruction,
+ or where a MOVN has an immediate that could be encoded by MOVZ, or where
+ MOVZ/MOVN #0 have a shift amount other than LSL #0, in which case the
+ machine-instruction mnemonic must be used. */
+
+static int
+convert_movewide_to_mov (aarch64_inst *inst)
+{
+ uint64_t value = inst->operands[1].imm.value;
+ /* MOVZ/MOVN #0 have a shift amount other than LSL #0. */
+ if (value == 0 && inst->operands[1].shifter.amount != 0)
+ return 0;
+ inst->operands[1].type = AARCH64_OPND_IMM_MOV;
+ inst->operands[1].shifter.kind = AARCH64_MOD_NONE;
+ value <<= inst->operands[1].shifter.amount;
+ /* As an alias convertor, it has to be clear that the INST->OPCODE
+ is the opcode of the real instruction. */
+ if (inst->opcode->op == OP_MOVN)
+ {
+ int is32 = inst->operands[0].qualifier == AARCH64_OPND_QLF_W;
+ value = ~value;
+ /* A MOVN has an immediate that could be encoded by MOVZ. */
+ if (aarch64_wide_constant_p (value, is32, NULL) == TRUE)
+ return 0;
+ }
+ inst->operands[1].imm.value = value;
+ inst->operands[1].shifter.amount = 0;
+ return 1;
+}
+
+/* MOV <Wd>, #<imm>
+ is equivalent to:
+ ORR <Wd>, WZR, #<imm>.
+
+ A disassembler may output ORR, MOVZ and MOVN as a MOV mnemonic, except when
+ ORR has an immediate that could be generated by a MOVZ or MOVN instruction,
+ or where a MOVN has an immediate that could be encoded by MOVZ, or where
+ MOVZ/MOVN #0 have a shift amount other than LSL #0, in which case the
+ machine-instruction mnemonic must be used. */
+
+static int
+convert_movebitmask_to_mov (aarch64_inst *inst)
+{
+ int is32;
+ uint64_t value;
+
+ /* Should have been assured by the base opcode value. */
+ assert (inst->operands[1].reg.regno == 0x1f);
+ copy_operand_info (inst, 1, 2);
+ is32 = inst->operands[0].qualifier == AARCH64_OPND_QLF_W;
+ inst->operands[1].type = AARCH64_OPND_IMM_MOV;
+ value = inst->operands[1].imm.value;
+ /* ORR has an immediate that could be generated by a MOVZ or MOVN
+ instruction. */
+ if (inst->operands[0].reg.regno != 0x1f
+ && (aarch64_wide_constant_p (value, is32, NULL) == TRUE
+ || aarch64_wide_constant_p (~value, is32, NULL) == TRUE))
+ return 0;
+
+ inst->operands[2].type = AARCH64_OPND_NIL;
+ return 1;
+}
+
+/* Some alias opcodes are disassembled by being converted from their real-form.
+ N.B. INST->OPCODE is the real opcode rather than the alias. */
+
+static int
+convert_to_alias (aarch64_inst *inst, const aarch64_opcode *alias)
+{
+ switch (alias->op)
+ {
+ case OP_ASR_IMM:
+ case OP_LSR_IMM:
+ return convert_bfm_to_sr (inst);
+ case OP_LSL_IMM:
+ return convert_ubfm_to_lsl (inst);
+ case OP_CINC:
+ case OP_CINV:
+ case OP_CNEG:
+ return convert_from_csel (inst);
+ case OP_CSET:
+ case OP_CSETM:
+ return convert_csinc_to_cset (inst);
+ case OP_UBFX:
+ case OP_BFXIL:
+ case OP_SBFX:
+ return convert_bfm_to_bfx (inst);
+ case OP_SBFIZ:
+ case OP_BFI:
+ case OP_UBFIZ:
+ return convert_bfm_to_bfi (inst);
+ case OP_MOV_V:
+ return convert_orr_to_mov (inst);
+ case OP_MOV_IMM_WIDE:
+ case OP_MOV_IMM_WIDEN:
+ return convert_movewide_to_mov (inst);
+ case OP_MOV_IMM_LOG:
+ return convert_movebitmask_to_mov (inst);
+ case OP_ROR_IMM:
+ return convert_extr_to_ror (inst);
+ default:
+ return 0;
+ }
+}
+
+static int aarch64_opcode_decode (const aarch64_opcode *, const aarch64_insn,
+ aarch64_inst *, int);
+
+/* Given the instruction information in *INST, check if the instruction has
+ any alias form that can be used to represent *INST. If the answer is yes,
+ update *INST to be in the form of the determined alias. */
+
+/* In the opcode description table, the following flags are used in opcode
+ entries to help establish the relations between the real and alias opcodes:
+
+ F_ALIAS: opcode is an alias
+ F_HAS_ALIAS: opcode has alias(es)
+ F_P1
+ F_P2
+ F_P3: Disassembly preference priority 1-3 (the larger the
+ higher). If nothing is specified, it is the priority
+ 0 by default, i.e. the lowest priority.
+
+ Although the relation between the machine and the alias instructions are not
+ explicitly described, it can be easily determined from the base opcode
+ values, masks and the flags F_ALIAS and F_HAS_ALIAS in their opcode
+ description entries:
+
+ The mask of an alias opcode must be equal to or a super-set (i.e. more
+ constrained) of that of the aliased opcode; so is the base opcode value.
+
+ if (opcode_has_alias (real) && alias_opcode_p (opcode)
+ && (opcode->mask & real->mask) == real->mask
+ && (real->mask & opcode->opcode) == (real->mask & real->opcode))
+ then OPCODE is an alias of, and only of, the REAL instruction
+
+ The alias relationship is forced flat-structured to keep related algorithm
+ simple; an opcode entry cannot be flagged with both F_ALIAS and F_HAS_ALIAS.
+
+ During the disassembling, the decoding decision tree (in
+ opcodes/aarch64-dis-2.c) always returns an machine instruction opcode entry;
+ if the decoding of such a machine instruction succeeds (and -Mno-aliases is
+ not specified), the disassembler will check whether there is any alias
+ instruction exists for this real instruction. If there is, the disassembler
+ will try to disassemble the 32-bit binary again using the alias's rule, or
+ try to convert the IR to the form of the alias. In the case of the multiple
+ aliases, the aliases are tried one by one from the highest priority
+ (currently the flag F_P3) to the lowest priority (no priority flag), and the
+ first succeeds first adopted.
+
+ You may ask why there is a need for the conversion of IR from one form to
+ another in handling certain aliases. This is because on one hand it avoids
+ adding more operand code to handle unusual encoding/decoding; on other
+ hand, during the disassembling, the conversion is an effective approach to
+ check the condition of an alias (as an alias may be adopted only if certain
+ conditions are met).
+
+ In order to speed up the alias opcode lookup, aarch64-gen has preprocessed
+ aarch64_opcode_table and generated aarch64_find_alias_opcode and
+ aarch64_find_next_alias_opcode (in opcodes/aarch64-dis-2.c) to help. */
+
+static void
+determine_disassembling_preference (struct aarch64_inst *inst)
+{
+ const aarch64_opcode *opcode;
+ const aarch64_opcode *alias;
+
+ opcode = inst->opcode;
+
+ /* This opcode does not have an alias, so use itself. */
+ if (opcode_has_alias (opcode) == FALSE)
+ return;
+
+ alias = aarch64_find_alias_opcode (opcode);
+ assert (alias);
+
+#ifdef DEBUG_AARCH64
+ if (debug_dump)
+ {
+ const aarch64_opcode *tmp = alias;
+ printf ("#### LIST orderd: ");
+ while (tmp)
+ {
+ printf ("%s, ", tmp->name);
+ tmp = aarch64_find_next_alias_opcode (tmp);
+ }
+ printf ("\n");
+ }
+#endif /* DEBUG_AARCH64 */
+
+ for (; alias; alias = aarch64_find_next_alias_opcode (alias))
+ {
+ DEBUG_TRACE ("try %s", alias->name);
+ assert (alias_opcode_p (alias));
+
+ /* An alias can be a pseudo opcode which will never be used in the
+ disassembly, e.g. BIC logical immediate is such a pseudo opcode
+ aliasing AND. */
+ if (pseudo_opcode_p (alias))
+ {
+ DEBUG_TRACE ("skip pseudo %s", alias->name);
+ continue;
+ }
+
+ if ((inst->value & alias->mask) != alias->opcode)
+ {
+ DEBUG_TRACE ("skip %s as base opcode not match", alias->name);
+ continue;
+ }
+ /* No need to do any complicated transformation on operands, if the alias
+ opcode does not have any operand. */
+ if (aarch64_num_of_operands (alias) == 0 && alias->opcode == inst->value)
+ {
+ DEBUG_TRACE ("succeed with 0-operand opcode %s", alias->name);
+ aarch64_replace_opcode (inst, alias);
+ return;
+ }
+ if (alias->flags & F_CONV)
+ {
+ aarch64_inst copy;
+ memcpy (&copy, inst, sizeof (aarch64_inst));
+ /* ALIAS is the preference as long as the instruction can be
+ successfully converted to the form of ALIAS. */
+ if (convert_to_alias (&copy, alias) == 1)
+ {
+ aarch64_replace_opcode (&copy, alias);
+ assert (aarch64_match_operands_constraint (&copy, NULL));
+ DEBUG_TRACE ("succeed with %s via conversion", alias->name);
+ memcpy (inst, &copy, sizeof (aarch64_inst));
+ return;
+ }
+ }
+ else
+ {
+ /* Directly decode the alias opcode. */
+ aarch64_inst temp;
+ memset (&temp, '\0', sizeof (aarch64_inst));
+ if (aarch64_opcode_decode (alias, inst->value, &temp, 1) == 1)
+ {
+ DEBUG_TRACE ("succeed with %s via direct decoding", alias->name);
+ memcpy (inst, &temp, sizeof (aarch64_inst));
+ return;
+ }
+ }
+ }
+}
+
+/* Decode the CODE according to OPCODE; fill INST. Return 0 if the decoding
+ fails, which meanes that CODE is not an instruction of OPCODE; otherwise
+ return 1.
+
+ If OPCODE has alias(es) and NOALIASES_P is 0, an alias opcode may be
+ determined and used to disassemble CODE; this is done just before the
+ return. */
+
+static int
+aarch64_opcode_decode (const aarch64_opcode *opcode, const aarch64_insn code,
+ aarch64_inst *inst, int noaliases_p)
+{
+ int i;
+
+ DEBUG_TRACE ("enter with %s", opcode->name);
+
+ assert (opcode && inst);
+
+ /* Check the base opcode. */
+ if ((code & opcode->mask) != (opcode->opcode & opcode->mask))
+ {
+ DEBUG_TRACE ("base opcode match FAIL");
+ goto decode_fail;
+ }
+
+ /* Clear inst. */
+ memset (inst, '\0', sizeof (aarch64_inst));
+
+ inst->opcode = opcode;
+ inst->value = code;
+
+ /* Assign operand codes and indexes. */
+ for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
+ {
+ if (opcode->operands[i] == AARCH64_OPND_NIL)
+ break;
+ inst->operands[i].type = opcode->operands[i];
+ inst->operands[i].idx = i;
+ }
+
+ /* Call the opcode decoder indicated by flags. */
+ if (opcode_has_special_coder (opcode) && do_special_decoding (inst) == 0)
+ {
+ DEBUG_TRACE ("opcode flag-based decoder FAIL");
+ goto decode_fail;
+ }
+
+ /* Call operand decoders. */
+ for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
+ {
+ const aarch64_operand *opnd;
+ enum aarch64_opnd type;
+ type = opcode->operands[i];
+ if (type == AARCH64_OPND_NIL)
+ break;
+ opnd = &aarch64_operands[type];
+ if (operand_has_extractor (opnd)
+ && (! aarch64_extract_operand (opnd, &inst->operands[i], code, inst)))
+ {
+ DEBUG_TRACE ("operand decoder FAIL at operand %d", i);
+ goto decode_fail;
+ }
+ }
+
+ /* Match the qualifiers. */
+ if (aarch64_match_operands_constraint (inst, NULL) == 1)
+ {
+ /* Arriving here, the CODE has been determined as a valid instruction
+ of OPCODE and *INST has been filled with information of this OPCODE
+ instruction. Before the return, check if the instruction has any
+ alias and should be disassembled in the form of its alias instead.
+ If the answer is yes, *INST will be updated. */
+ if (!noaliases_p)
+ determine_disassembling_preference (inst);
+ DEBUG_TRACE ("SUCCESS");
+ return 1;
+ }
+ else
+ {
+ DEBUG_TRACE ("constraint matching FAIL");
+ }
+
+decode_fail:
+ return 0;
+}
+
+/* This does some user-friendly fix-up to *INST. It is currently focus on
+ the adjustment of qualifiers to help the printed instruction
+ recognized/understood more easily. */
+
+static void
+user_friendly_fixup (aarch64_inst *inst)
+{
+ switch (inst->opcode->iclass)
+ {
+ case testbranch:
+ /* TBNZ Xn|Wn, #uimm6, label
+ Test and Branch Not Zero: conditionally jumps to label if bit number
+ uimm6 in register Xn is not zero. The bit number implies the width of
+ the register, which may be written and should be disassembled as Wn if
+ uimm is less than 32. Limited to a branch offset range of +/- 32KiB.
+ */
+ if (inst->operands[1].imm.value < 32)
+ inst->operands[0].qualifier = AARCH64_OPND_QLF_W;
+ break;
+ default: break;
+ }
+}
+
+/* Decode INSN and fill in *INST the instruction information. */
+
+static int
+disas_aarch64_insn (uint64_t pc ATTRIBUTE_UNUSED, uint32_t insn,
+ aarch64_inst *inst)
+{
+ const aarch64_opcode *opcode = aarch64_opcode_lookup (insn);
+
+#ifdef DEBUG_AARCH64
+ if (debug_dump)
+ {
+ const aarch64_opcode *tmp = opcode;
+ printf ("\n");
+ DEBUG_TRACE ("opcode lookup:");
+ while (tmp != NULL)
+ {
+ aarch64_verbose (" %s", tmp->name);
+ tmp = aarch64_find_next_opcode (tmp);
+ }
+ }
+#endif /* DEBUG_AARCH64 */
+
+ /* A list of opcodes may have been found, as aarch64_opcode_lookup cannot
+ distinguish some opcodes, e.g. SSHR and MOVI, which almost share the same
+ opcode field and value, apart from the difference that one of them has an
+ extra field as part of the opcode, but such a field is used for operand
+ encoding in other opcode(s) ('immh' in the case of the example). */
+ while (opcode != NULL)
+ {
+ /* But only one opcode can be decoded successfully for, as the
+ decoding routine will check the constraint carefully. */
+ if (aarch64_opcode_decode (opcode, insn, inst, no_aliases) == 1)
+ return ERR_OK;
+ opcode = aarch64_find_next_opcode (opcode);
+ }
+
+ return ERR_UND;
+}
+
+/* Print operands. */
+
+static void
+print_operands (bfd_vma pc, const aarch64_opcode *opcode,
+ const aarch64_opnd_info *opnds, struct disassemble_info *info)
+{
+ int i, pcrel_p, num_printed;
+ for (i = 0, num_printed = 0; i < AARCH64_MAX_OPND_NUM; ++i)
+ {
+ const size_t size = 128;
+ char str[size];
+ /* We regard the opcode operand info more, however we also look into
+ the inst->operands to support the disassembling of the optional
+ operand.
+ The two operand code should be the same in all cases, apart from
+ when the operand can be optional. */
+ if (opcode->operands[i] == AARCH64_OPND_NIL
+ || opnds[i].type == AARCH64_OPND_NIL)
+ break;
+
+ /* Generate the operand string in STR. */
+ aarch64_print_operand (str, size, pc, opcode, opnds, i, &pcrel_p,
+ &info->target);
+
+ /* Print the delimiter (taking account of omitted operand(s)). */
+ if (str[0] != '\0')
+ (*info->fprintf_func) (info->stream, "%s",
+ num_printed++ == 0 ? "\t" : ", ");
+
+ /* Print the operand. */
+ if (pcrel_p)
+ (*info->print_address_func) (info->target, info);
+ else
+ (*info->fprintf_func) (info->stream, "%s", str);
+ }
+}
+
+/* Print the instruction mnemonic name. */
+
+static void
+print_mnemonic_name (const aarch64_inst *inst, struct disassemble_info *info)
+{
+ if (inst->opcode->flags & F_COND)
+ {
+ /* For instructions that are truly conditionally executed, e.g. b.cond,
+ prepare the full mnemonic name with the corresponding condition
+ suffix. */
+ char name[8], *ptr;
+ size_t len;
+
+ ptr = strchr (inst->opcode->name, '.');
+ assert (ptr && inst->cond);
+ len = ptr - inst->opcode->name;
+ assert (len < 8);
+ strncpy (name, inst->opcode->name, len);
+ name [len] = '\0';
+ (*info->fprintf_func) (info->stream, "%s.%s", name, inst->cond->names[0]);
+ }
+ else
+ (*info->fprintf_func) (info->stream, "%s", inst->opcode->name);
+}
+
+/* Print the instruction according to *INST. */
+
+static void
+print_aarch64_insn (bfd_vma pc, const aarch64_inst *inst,
+ struct disassemble_info *info)
+{
+ print_mnemonic_name (inst, info);
+ print_operands (pc, inst->opcode, inst->operands, info);
+}
+
+/* Entry-point of the instruction disassembler and printer. */
+
+static void
+print_insn_aarch64_word (bfd_vma pc,
+ uint32_t word,
+ struct disassemble_info *info)
+{
+ static const char *err_msg[6] =
+ {
+ [ERR_OK] = "_",
+ [-ERR_UND] = "undefined",
+ [-ERR_UNP] = "unpredictable",
+ [-ERR_NYI] = "NYI"
+ };
+
+ int ret;
+ aarch64_inst inst;
+
+ info->insn_info_valid = 1;
+ info->branch_delay_insns = 0;
+ info->data_size = 0;
+ info->target = 0;
+ info->target2 = 0;
+
+ 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. (If 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;
+
+ ret = disas_aarch64_insn (pc, word, &inst);
+
+ if (((word >> 21) & 0x3ff) == 1)
+ {
+ /* RESERVED for ALES. */
+ assert (ret != ERR_OK);
+ ret = ERR_NYI;
+ }
+
+ switch (ret)
+ {
+ case ERR_UND:
+ case ERR_UNP:
+ case ERR_NYI:
+ /* Handle undefined instructions. */
+ info->insn_type = dis_noninsn;
+ (*info->fprintf_func) (info->stream,".inst\t0x%08x ; %s",
+ word, err_msg[-ret]);
+ break;
+ case ERR_OK:
+ user_friendly_fixup (&inst);
+ print_aarch64_insn (pc, &inst, info);
+ break;
+ default:
+ abort ();
+ }
+}
+
+/* Disallow mapping symbols ($x, $d etc) from
+ being displayed in symbol relative addresses. */
+
+bfd_boolean
+aarch64_symbol_is_valid (asymbol * sym,
+ struct disassemble_info * info ATTRIBUTE_UNUSED)
+{
+ const char * name;
+
+ if (sym == NULL)
+ return FALSE;
+
+ name = bfd_asymbol_name (sym);
+
+ return name
+ && (name[0] != '$'
+ || (name[1] != 'x' && name[1] != 'd')
+ || (name[2] != '\0' && name[2] != '.'));
+}
+
+/* Print data bytes on INFO->STREAM. */
+
+static void
+print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED,
+ uint32_t word,
+ struct disassemble_info *info)
+{
+ switch (info->bytes_per_chunk)
+ {
+ case 1:
+ info->fprintf_func (info->stream, ".byte\t0x%02x", word);
+ break;
+ case 2:
+ info->fprintf_func (info->stream, ".short\t0x%04x", word);
+ break;
+ case 4:
+ info->fprintf_func (info->stream, ".word\t0x%08x", word);
+ break;
+ default:
+ abort ();
+ }
+}
+
+/* Try to infer the code or data type from a symbol.
+ Returns nonzero if *MAP_TYPE was set. */
+
+static int
+get_sym_code_type (struct disassemble_info *info, int n,
+ enum map_type *map_type)
+{
+ elf_symbol_type *es;
+ unsigned int type;
+ const char *name;
+
+ es = *(elf_symbol_type **)(info->symtab + n);
+ type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
+
+ /* If the symbol has function type then use that. */
+ if (type == STT_FUNC)
+ {
+ *map_type = MAP_INSN;
+ return TRUE;
+ }
+
+ /* Check for mapping symbols. */
+ name = bfd_asymbol_name(info->symtab[n]);
+ if (name[0] == '$'
+ && (name[1] == 'x' || name[1] == 'd')
+ && (name[2] == '\0' || name[2] == '.'))
+ {
+ *map_type = (name[1] == 'x' ? MAP_INSN : MAP_DATA);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* Entry-point of the AArch64 disassembler. */
+
+int
+print_insn_aarch64 (bfd_vma pc,
+ struct disassemble_info *info)
+{
+ bfd_byte buffer[INSNLEN];
+ int status;
+ void (*printer) (bfd_vma, uint32_t, struct disassemble_info *);
+ bfd_boolean found = FALSE;
+ unsigned int size = 4;
+ unsigned long data;
+
+ if (info->disassembler_options)
+ {
+ set_default_aarch64_dis_options (info);
+
+ parse_aarch64_dis_options (info->disassembler_options);
+
+ /* To avoid repeated parsing of these options, we remove them here. */
+ info->disassembler_options = NULL;
+ }
+
+ /* Aarch64 instructions are always little-endian */
+ info->endian_code = BFD_ENDIAN_LITTLE;
+
+ /* First check the full symtab for a mapping symbol, even if there
+ are no usable non-mapping symbols for this address. */
+ if (info->symtab_size != 0
+ && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour)
+ {
+ enum map_type type = MAP_INSN;
+ int last_sym = -1;
+ bfd_vma addr;
+ int n;
+
+ if (pc <= last_mapping_addr)
+ last_mapping_sym = -1;
+
+ /* 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)
+ n = last_mapping_sym;
+
+ /* No mapping symbol found at this address. Look backwards
+ for a preceeding 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;
+
+ /* Look a little bit ahead to see if we should print out
+ less than four bytes of data. If there's a symbol,
+ mapping or otherwise, after two bytes then don't
+ print more. */
+ if (last_type == MAP_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 (last_type == MAP_DATA)
+ {
+ /* size was set above. */
+ info->bytes_per_chunk = size;
+ info->display_endian = info->endian;
+ printer = print_insn_data;
+ }
+ else
+ {
+ info->bytes_per_chunk = size = INSNLEN;
+ info->display_endian = info->endian_code;
+ printer = print_insn_aarch64_word;
+ }
+
+ status = (*info->read_memory_func) (pc, buffer, size, info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, pc, info);
+ return -1;
+ }
+
+ data = bfd_get_bits (buffer, size * 8,
+ info->display_endian == BFD_ENDIAN_BIG);
+
+ (*printer) (pc, data, info);
+
+ return size;
+}
+
+void
+print_aarch64_disassembler_options (FILE *stream)
+{
+ fprintf (stream, _("\n\
+The following AARCH64 specific disassembler options are supported for use\n\
+with the -M switch (multiple options should be separated by commas):\n"));
+
+ fprintf (stream, _("\n\
+ no-aliases Don't print instruction aliases.\n"));
+
+ fprintf (stream, _("\n\
+ aliases Do print instruction aliases.\n"));
+
+#ifdef DEBUG_AARCH64
+ fprintf (stream, _("\n\
+ debug_dump Temp switch for debug trace.\n"));
+#endif /* DEBUG_AARCH64 */
+
+ fprintf (stream, _("\n"));
+}
diff --git a/opcodes/aarch64-dis.h b/opcodes/aarch64-dis.h
new file mode 100644
index 0000000..2fab319
--- /dev/null
+++ b/opcodes/aarch64-dis.h
@@ -0,0 +1,94 @@
+/* aarch64-dis.h -- Header file for aarch64-dis.c and aarch64-dis-2.c.
+ Copyright 2012 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of the GNU opcodes library.
+
+ This library 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 3, or (at your option)
+ any later version.
+
+ It 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; see the file COPYING3. If not,
+ see <http://www.gnu.org/licenses/>. */
+
+#ifndef OPCODES_AARCH64_DIS_H
+#define OPCODES_AARCH64_DIS_H
+#include "bfd_stdint.h"
+#include "aarch64-opc.h"
+
+/* Lookup opcode WORD in the opcode table.
+
+ In the case of multiple aarch64_opcode candidates, one of them will be
+ returned; for other candidate(s), call aarch64_find_next_opcode to
+ obtain. Note that aarch64_find_next_opcode finds the next
+ aarch64_opcode candidate in a way as if all related aarch64_opcode
+ entries were in a single-link list.
+
+ N.B. all alias opcodes are ignored here. */
+
+const aarch64_opcode* aarch64_opcode_lookup (uint32_t);
+const aarch64_opcode* aarch64_find_next_opcode (const aarch64_opcode *);
+
+/* Given OPCODE, return its alias, e.g. given UBFM, return LSL.
+
+ In the case of multiple alias candidates, the one of the highest priority
+ (or one of several aliases of the same highest priority) will be
+ returned; for the other candidate(s), call aarch64_find_next_alias_opcode
+ to obtain. Note that aarch64_find_next_alias_opcode finds the next
+ alias candidate in a way as if all related aliases were in a single-link
+ list with priority from the highest to the least. */
+
+const aarch64_opcode* aarch64_find_alias_opcode (const aarch64_opcode *);
+const aarch64_opcode* aarch64_find_next_alias_opcode (const aarch64_opcode *);
+
+/* Switch-table-based high-level operand extractor. */
+
+int aarch64_extract_operand (const aarch64_operand *, aarch64_opnd_info *,
+ const aarch64_insn, const aarch64_inst *);
+
+/* Operand extractors. */
+
+#define AARCH64_DECL_OPD_EXTRACTOR(x) \
+ int aarch64_##x (const aarch64_operand *, aarch64_opnd_info *, \
+ const aarch64_insn, const aarch64_inst *)
+
+AARCH64_DECL_OPD_EXTRACTOR (ext_regno);
+AARCH64_DECL_OPD_EXTRACTOR (ext_regrt_sysins);
+AARCH64_DECL_OPD_EXTRACTOR (ext_reglane);
+AARCH64_DECL_OPD_EXTRACTOR (ext_reglist);
+AARCH64_DECL_OPD_EXTRACTOR (ext_ldst_reglist);
+AARCH64_DECL_OPD_EXTRACTOR (ext_ldst_reglist_r);
+AARCH64_DECL_OPD_EXTRACTOR (ext_ldst_elemlist);
+AARCH64_DECL_OPD_EXTRACTOR (ext_advsimd_imm_shift);
+AARCH64_DECL_OPD_EXTRACTOR (ext_shll_imm);
+AARCH64_DECL_OPD_EXTRACTOR (ext_imm);
+AARCH64_DECL_OPD_EXTRACTOR (ext_imm_half);
+AARCH64_DECL_OPD_EXTRACTOR (ext_advsimd_imm_modified);
+AARCH64_DECL_OPD_EXTRACTOR (ext_fbits);
+AARCH64_DECL_OPD_EXTRACTOR (ext_aimm);
+AARCH64_DECL_OPD_EXTRACTOR (ext_limm);
+AARCH64_DECL_OPD_EXTRACTOR (ext_ft);
+AARCH64_DECL_OPD_EXTRACTOR (ext_addr_simple);
+AARCH64_DECL_OPD_EXTRACTOR (ext_addr_regoff);
+AARCH64_DECL_OPD_EXTRACTOR (ext_addr_simm);
+AARCH64_DECL_OPD_EXTRACTOR (ext_addr_uimm12);
+AARCH64_DECL_OPD_EXTRACTOR (ext_simd_addr_post);
+AARCH64_DECL_OPD_EXTRACTOR (ext_cond);
+AARCH64_DECL_OPD_EXTRACTOR (ext_sysreg);
+AARCH64_DECL_OPD_EXTRACTOR (ext_pstatefield);
+AARCH64_DECL_OPD_EXTRACTOR (ext_sysins_op);
+AARCH64_DECL_OPD_EXTRACTOR (ext_barrier);
+AARCH64_DECL_OPD_EXTRACTOR (ext_prfop);
+AARCH64_DECL_OPD_EXTRACTOR (ext_reg_extended);
+AARCH64_DECL_OPD_EXTRACTOR (ext_reg_shifted);
+
+#undef AARCH64_DECL_OPD_EXTRACTOR
+
+#endif /* OPCODES_AARCH64_DIS_H */
diff --git a/opcodes/aarch64-gen.c b/opcodes/aarch64-gen.c
new file mode 100644
index 0000000..95bd016
--- /dev/null
+++ b/opcodes/aarch64-gen.c
@@ -0,0 +1,1317 @@
+/* aarch64-gen.c -- Generate tables and routines for opcode lookup and
+ instruction encoding and decoding.
+ Copyright 2012 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of the GNU opcodes library.
+
+ This library 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 3, or (at your option)
+ any later version.
+
+ It 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; see the file COPYING3. If not,
+ see <http://www.gnu.org/licenses/>. */
+
+#include "sysdep.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "libiberty.h"
+#include "getopt.h"
+#include "opcode/aarch64.h"
+
+#include "aarch64-tbl.h"
+
+static int debug = 0;
+
+/* Structure used in the decoding tree to group a list of aarch64_opcode
+ entries. */
+
+struct opcode_node
+{
+ aarch64_insn opcode;
+ aarch64_insn mask;
+ /* Index of the entry in the original table; the top 2 bits help
+ determine the table. */
+ unsigned int index;
+ struct opcode_node *next;
+};
+
+typedef struct opcode_node opcode_node;
+
+/* Head of the list of the opcode_node after read_table. */
+static opcode_node opcode_nodes_head;
+
+/* Node in the decoding tree. */
+
+struct bittree
+{
+ unsigned int bitno;
+ /* 0, 1, and X (don't care). */
+ struct bittree *bits[2];
+ /* List of opcodes; only valid for the leaf node. */
+ opcode_node *list;
+};
+
+/* Allocate and initialize an opcode_node. */
+static opcode_node*
+new_opcode_node (void)
+{
+ opcode_node* ent = malloc (sizeof (opcode_node));
+
+ if (!ent)
+ abort ();
+
+ ent->opcode = 0;
+ ent->mask = 0;
+ ent->index = -1;
+ ent->next = NULL;
+
+ return ent;
+}
+
+/* Multiple tables are supported, although currently only one table is
+ in use. N.B. there are still some functions have the table name
+ 'aarch64_opcode_table' hard-coded in, e.g. print_find_next_opcode;
+ therefore some amount of work needs to be done if the full support
+ for multiple tables needs to be enabled. */
+static const struct aarch64_opcode *aarch64_opcode_tables[] =
+{aarch64_opcode_table};
+
+/* Use top 2 bits to indiate which table. */
+static unsigned int
+initialize_index (const struct aarch64_opcode* table)
+{
+ int i;
+ const int num_of_tables = sizeof (aarch64_opcode_tables)
+ / sizeof (struct aarch64_opcode *);
+ for (i = 0; i < num_of_tables; ++i)
+ if (table == aarch64_opcode_tables [i])
+ break;
+ if (i == num_of_tables)
+ abort ();
+ return (unsigned int)i << 30;
+}
+
+static inline const struct aarch64_opcode *
+index2table (unsigned int index)
+{
+ return aarch64_opcode_tables[(index >> 30) & 0x3];
+}
+
+static inline unsigned int
+real_index (unsigned int index)
+{
+ return index & ((1 << 30) - 1);
+}
+
+/* Given OPCODE_NODE, return the corresponding aarch64_opcode*. */
+static const aarch64_opcode*
+get_aarch64_opcode (const opcode_node *opcode_node)
+{
+ if (opcode_node == NULL)
+ return NULL;
+ return &index2table (opcode_node->index)[real_index (opcode_node->index)];
+}
+
+static void
+read_table (const struct aarch64_opcode* table)
+{
+ const struct aarch64_opcode *ent = table;
+ opcode_node **new_ent;
+ unsigned int index = initialize_index (table);
+
+ if (!ent->name)
+ return;
+
+ new_ent = &opcode_nodes_head.next;
+
+ while (*new_ent)
+ new_ent = &(*new_ent)->next;
+
+ do
+ {
+ /* F_PSEUDO needs to be used together with F_ALIAS to indicate an alias
+ opcode is a programmer friendly pseudo instruction available only in
+ the assembly code (thus will not show up in the disassembly). */
+ assert (pseudo_opcode_p (ent) == FALSE || alias_opcode_p (ent) == TRUE);
+ /* Skip alias (inc. pseudo) opcode. */
+ if (alias_opcode_p (ent) == TRUE)
+ {
+ index++;
+ continue;
+ }
+ *new_ent = new_opcode_node ();
+ (*new_ent)->opcode = ent->opcode;
+ (*new_ent)->mask = ent->mask;
+ (*new_ent)->index = index++;
+ new_ent = &((*new_ent)->next);
+ } while ((++ent)->name);
+}
+
+static inline void
+print_one_opcode_node (opcode_node* ent)
+{
+ printf ("%s\t%08x\t%08x\t%d\n", get_aarch64_opcode (ent)->name,
+ get_aarch64_opcode (ent)->opcode, get_aarch64_opcode (ent)->mask,
+ (int)real_index (ent->index));
+}
+
+/* As an internal debugging utility, print out the list of nodes pointed
+ by opcode_nodes_head. */
+static void
+print_opcode_nodes (void)
+{
+ opcode_node* ent = opcode_nodes_head.next;
+ printf ("print_opcode_nodes table:\n");
+ while (ent)
+ {
+ print_one_opcode_node (ent);
+ ent = ent->next;
+ }
+}
+
+static struct bittree*
+new_bittree_node (void)
+{
+ struct bittree* node;
+ node = malloc (sizeof (struct bittree));
+ if (!node)
+ abort ();
+ node->bitno = -1;
+ node->bits[0] = NULL;
+ node->bits[1] = NULL;
+ return node;
+}
+
+/* The largest number of opcode entries that exist at a leaf node of the
+ decoding decision tree. The reason that there can be more than one
+ opcode entry is because some opcodes have shared field that is partially
+ constrained and thus cannot be fully isolated using the algorithm
+ here. */
+static int max_num_opcodes_at_leaf_node = 0;
+
+/* Given a list of opcodes headed by *OPCODE, try to establish one bit that
+ is shared by all the opcodes in the list as one of base opcode bits. If
+ such a bit is found, divide the list of the opcodes into two based on the
+ value of the bit.
+
+ Store the bit number in BITTREE->BITNO if the division succeeds. If unable
+ to determine such a bit or there is only one opcode in the list, the list
+ is decided to be undividable and OPCODE will be assigned to BITTREE->LIST.
+
+ The function recursively call itself until OPCODE is undividable.
+
+ N.B. the nature of this algrithm determines that given any value in the
+ 32-bit space, the computed decision tree will always be able to find one or
+ more opcodes entries for it, regardless whether there is a valid instruction
+ defined for this value or not. In order to detect the undefined values,
+ when the caller obtains the opcode entry/entries, it should at least compare
+ the bit-wise AND result of the value and the mask with the base opcode
+ value; if the two are different, it means that the value is undefined
+ (although the value may be still undefined when the comparison is the same,
+ in which case call aarch64_opcode_decode to carry out further checks). */
+
+static void
+divide_table_1 (struct bittree *bittree, opcode_node *opcode)
+{
+ aarch64_insn mask_and;
+ opcode_node *ent;
+ unsigned int bitno;
+ aarch64_insn bitmask;
+ opcode_node list0, list1, **ptr0, **ptr1;
+ static int depth = 0;
+
+ ++depth;
+
+ if (debug)
+ printf ("Enter into depth %d\n", depth);
+
+ assert (opcode != NULL);
+
+ /* Succeed when there is only one opcode left. */
+ if (!opcode->next)
+ {
+ if (debug)
+ {
+ printf ("opcode isolated:\n");
+ print_one_opcode_node (opcode);
+ }
+ goto divide_table_1_finish;
+ }
+
+divide_table_1_try_again:
+ mask_and = -1;
+ ent = opcode;
+ while (ent)
+ {
+ mask_and &= ent->mask;
+ ent = ent->next;
+ }
+
+ if (debug)
+ printf ("mask and result: %08x\n", (unsigned int)mask_and);
+
+ /* If no more bit to look into, we have to accept the reality then. */
+ if (!mask_and)
+ {
+ int i;
+ opcode_node *ptr;
+ if (debug)
+ {
+ ptr = opcode;
+ printf ("Isolated opcode group:\n");
+ do {
+ print_one_opcode_node (ptr);
+ ptr = ptr->next;
+ } while (ptr);
+ }
+ /* Count the number of opcodes. */
+ for (i = 0, ptr = opcode; ptr; ++i)
+ ptr = ptr->next;
+ if (i > max_num_opcodes_at_leaf_node)
+ max_num_opcodes_at_leaf_node = i;
+ goto divide_table_1_finish;
+ }
+
+ /* Pick up the right most bit that is 1. */
+ bitno = 0;
+ while (!(mask_and & (1 << bitno)))
+ ++bitno;
+ bitmask = (1 << bitno);
+
+ if (debug)
+ printf ("use bit %d\n", bitno);
+
+ /* Record in the bittree. */
+ bittree->bitno = bitno;
+
+ /* Get two new opcode lists; adjust their masks. */
+ list0.next = NULL;
+ list1.next = NULL;
+ ptr0 = &list0.next;
+ ptr1 = &list1.next;
+ ent = opcode;
+ while (ent)
+ {
+ if (ent->opcode & bitmask)
+ {
+ ent->mask &= (~bitmask);
+ *ptr1 = ent;
+ ent = ent->next;
+ (*ptr1)->next = NULL;
+ ptr1 = &(*ptr1)->next;
+ }
+ else
+ {
+ ent->mask &= (~bitmask);
+ *ptr0 = ent;
+ ent = ent->next;
+ (*ptr0)->next = NULL;
+ ptr0 = &(*ptr0)->next;
+ }
+ }
+
+ /* If BITNO can NOT divide the opcode group, try next bit. */
+ if (list0.next == NULL)
+ {
+ opcode = list1.next;
+ goto divide_table_1_try_again;
+ }
+ else if (list1.next == NULL)
+ {
+ opcode = list0.next;
+ goto divide_table_1_try_again;
+ }
+
+ /* Further divide. */
+ bittree->bits[0] = new_bittree_node ();
+ bittree->bits[1] = new_bittree_node ();
+ divide_table_1 (bittree->bits[0], list0.next);
+ divide_table_1 (bittree->bits[1], list1.next);
+
+divide_table_1_finish:
+ if (debug)
+ printf ("Leave from depth %d\n", depth);
+ --depth;
+
+ /* Record the opcode entries on this leaf node. */
+ bittree->list = opcode;
+
+ return;
+}
+
+/* Call divide_table_1 to divide the all the opcodes and thus create the
+ decoding decision tree. */
+static struct bittree *
+divide_table (void)
+{
+ struct bittree *bittree = new_bittree_node ();
+ divide_table_1 (bittree, opcode_nodes_head.next);
+ return bittree;
+}
+
+/* Read in all of the tables, create the decoding decision tree and return
+ the tree root. */
+static struct bittree *
+initialize_decoder_tree (void)
+{
+ int i;
+ const int num_of_tables = (sizeof (aarch64_opcode_tables)
+ / sizeof (struct aarch64_opcode *));
+ for (i = 0; i < num_of_tables; ++i)
+ read_table (aarch64_opcode_tables [i]);
+ if (debug)
+ print_opcode_nodes ();
+ return divide_table ();
+}
+
+static void __attribute__ ((format (printf, 2, 3)))
+indented_print (unsigned int indent, const char *format, ...)
+{
+ /* 80 number of spaces pluc a NULL terminator. */
+ static const char spaces[81] =
+ " ";
+ va_list ap;
+ va_start (ap, format);
+ assert (indent <= 80);
+ printf ("%s", &spaces[80 - indent]);
+ vprintf (format, ap);
+ va_end (ap);
+}
+
+/* N.B. read the comment above divide_table_1 for the reason why the generated
+ decision tree function never returns NULL. */
+
+static void
+print_decision_tree_1 (unsigned int indent, struct bittree* bittree)
+{
+ /* PATTERN is only used to generate comment in the code. */
+ static char pattern[33] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+ assert (bittree != NULL);
+
+ /* Leaf node located. */
+ if (bittree->bits[0] == NULL && bittree->bits[1] == NULL)
+ {
+ assert (bittree->list != NULL);
+ indented_print (indent, "/* 33222222222211111111110000000000\n");
+ indented_print (indent, " 10987654321098765432109876543210\n");
+ indented_print (indent, " %s\n", pattern);
+ indented_print (indent, " %s. */\n",
+ get_aarch64_opcode (bittree->list)->name);
+ indented_print (indent, "return %u;\n",
+ real_index (bittree->list->index));
+ return;
+ }
+
+ /* Walk down the decoder tree. */
+ indented_print (indent, "if (((word >> %d) & 0x1) == 0)\n", bittree->bitno);
+ indented_print (indent, " {\n");
+ pattern[bittree->bitno] = '0';
+ print_decision_tree_1 (indent + 4, bittree->bits[0]);
+ indented_print (indent, " }\n");
+ indented_print (indent, "else\n");
+ indented_print (indent, " {\n");
+ pattern[bittree->bitno] = '1';
+ print_decision_tree_1 (indent + 4, bittree->bits[1]);
+ indented_print (indent, " }\n");
+ pattern[bittree->bitno] = 'x';
+}
+
+/* Generate aarch64_opcode_lookup in C code to the standard output. */
+
+static void
+print_decision_tree (struct bittree* bittree)
+{
+ if (debug)
+ printf ("Enter print_decision_tree\n");
+
+ printf ("/* Called by aarch64_opcode_lookup. */\n\n");
+
+ printf ("static int\n");
+ printf ("aarch64_opcode_lookup_1 (uint32_t word)\n");
+ printf ("{\n");
+
+ print_decision_tree_1 (2, bittree);
+
+ printf ("}\n\n");
+
+
+ printf ("/* Lookup opcode WORD in the opcode table. N.B. all alias\n");
+ printf (" opcodes are ignored here. */\n\n");
+
+ printf ("const aarch64_opcode *\n");
+ printf ("aarch64_opcode_lookup (uint32_t word)\n");
+ printf ("{\n");
+ printf (" return aarch64_opcode_table + aarch64_opcode_lookup_1 (word);\n");
+ printf ("}\n");
+}
+
+static void
+print_find_next_opcode_1 (struct bittree* bittree)
+{
+ assert (bittree != NULL);
+
+ /* Leaf node located. */
+ if (bittree->bits[0] == NULL && bittree->bits[1] == NULL)
+ {
+ assert (bittree->list != NULL);
+ /* Find multiple opcode entries in one leaf node. */
+ if (bittree->list->next != NULL)
+ {
+ opcode_node *list = bittree->list;
+ while (list != NULL)
+ {
+ const aarch64_opcode *curr = get_aarch64_opcode (list);
+ const aarch64_opcode *next = get_aarch64_opcode (list->next);
+
+ printf (" case %u: ",
+ (unsigned int)(curr - aarch64_opcode_table));
+ if (list->next != NULL)
+ {
+ printf ("value = %u; break;\t", real_index (list->next->index));
+ printf ("/* %s --> %s. */\n", curr->name, next->name);
+ }
+ else
+ {
+ printf ("return NULL;\t\t");
+ printf ("/* %s --> NULL. */\n", curr->name);
+ }
+
+ list = list->next;
+ }
+ }
+ return;
+ }
+
+ /* Walk down the decoder tree. */
+ print_find_next_opcode_1 (bittree->bits[0]);
+ print_find_next_opcode_1 (bittree->bits[1]);
+}
+
+/* Generate aarch64_find_next_opcode in C code to the standard output. */
+
+static void
+print_find_next_opcode (struct bittree* bittree)
+{
+ if (debug)
+ printf ("Enter print_find_next_opcode\n");
+
+ printf ("\n");
+ printf ("const aarch64_opcode *\n");
+ printf ("aarch64_find_next_opcode (const aarch64_opcode *opcode)\n");
+ printf ("{\n");
+ printf (" /* Use the index as the key to locate the next opcode. */\n");
+ printf (" int key = opcode - aarch64_opcode_table;\n");
+ printf (" int value;\n");
+ printf (" switch (key)\n");
+ printf (" {\n");
+
+ print_find_next_opcode_1 (bittree);
+
+ printf (" default: return NULL;\n");
+ printf (" }\n\n");
+
+ printf (" return aarch64_opcode_table + value;\n");
+ printf ("}\n");
+}
+
+/* Release the dynamic memory resource allocated for the generation of the
+ decoder tree. */
+
+static void
+release_resource_decoder_tree (struct bittree* bittree)
+{
+ assert (bittree != NULL);
+
+ /* Leaf node located. */
+ if (bittree->bits[0] == NULL && bittree->bits[1] == NULL)
+ {
+ assert (bittree->list != NULL);
+ /* Free opcode_nodes. */
+ opcode_node *list = bittree->list;
+ while (list != NULL)
+ {
+ opcode_node *next = list->next;
+ free (list);
+ list = next;
+ }
+ /* Free the tree node. */
+ free (bittree);
+ return;
+ }
+
+ /* Walk down the decoder tree. */
+ release_resource_decoder_tree (bittree->bits[0]);
+ release_resource_decoder_tree (bittree->bits[1]);
+
+ /* Free the tree node. */
+ free (bittree);
+}
+
+/* Generate aarch64_find_real_opcode in C code to the standard output.
+ TABLE points to the alias info table, while NUM indicates the number of
+ entries in the table. */
+
+static void
+print_find_real_opcode (const opcode_node *table, int num)
+{
+ int i;
+
+ if (debug)
+ printf ("Enter print_find_real_opcode\n");
+
+ printf ("\n");
+ printf ("const aarch64_opcode *\n");
+ printf ("aarch64_find_real_opcode (const aarch64_opcode *opcode)\n");
+ printf ("{\n");
+ printf (" /* Use the index as the key to locate the real opcode. */\n");
+ printf (" int key = opcode - aarch64_opcode_table;\n");
+ printf (" int value;\n");
+ printf (" switch (key)\n");
+ printf (" {\n");
+
+ for (i = 0; i < num; ++i)
+ {
+ const opcode_node *real = table + i;
+ const opcode_node *alias = real->next;
+ for (; alias; alias = alias->next)
+ printf (" case %u:\t/* %s */\n", real_index (alias->index),
+ get_aarch64_opcode (alias)->name);
+ printf (" value = %u;\t/* --> %s. */\n", real_index (real->index),
+ get_aarch64_opcode (real)->name);
+ printf (" break;\n");
+ }
+
+ printf (" default: return NULL;\n");
+ printf (" }\n\n");
+
+ printf (" return aarch64_opcode_table + value;\n");
+ printf ("}\n");
+}
+
+/* Generate aarch64_find_alias_opcode in C code to the standard output.
+ TABLE points to the alias info table, while NUM indicates the number of
+ entries in the table. */
+
+static void
+print_find_alias_opcode (const opcode_node *table, int num)
+{
+ int i;
+
+ if (debug)
+ printf ("Enter print_find_alias_opcode\n");
+
+ printf ("\n");
+ printf ("const aarch64_opcode *\n");
+ printf ("aarch64_find_alias_opcode (const aarch64_opcode *opcode)\n");
+ printf ("{\n");
+ printf (" /* Use the index as the key to locate the alias opcode. */\n");
+ printf (" int key = opcode - aarch64_opcode_table;\n");
+ printf (" int value;\n");
+ printf (" switch (key)\n");
+ printf (" {\n");
+
+ for (i = 0; i < num; ++i)
+ {
+ const opcode_node *node = table + i;
+ assert (node->next);
+ printf (" case %u: value = %u; break;", real_index (node->index),
+ real_index (node->next->index));
+ printf ("\t/* %s --> %s. */\n", get_aarch64_opcode (node)->name,
+ get_aarch64_opcode (node->next)->name);
+ }
+
+ printf (" default: return NULL;\n");
+ printf (" }\n\n");
+
+ printf (" return aarch64_opcode_table + value;\n");
+ printf ("}\n");
+}
+
+/* Generate aarch64_find_next_alias_opcode in C code to the standard output.
+ TABLE points to the alias info table, while NUM indicates the number of
+ entries in the table. */
+
+static void
+print_find_next_alias_opcode (const opcode_node *table, int num)
+{
+ int i;
+
+ if (debug)
+ printf ("Enter print_find_next_alias_opcode\n");
+
+ printf ("\n");
+ printf ("const aarch64_opcode *\n");
+ printf ("aarch64_find_next_alias_opcode (const aarch64_opcode *opcode)\n");
+ printf ("{\n");
+ printf (" /* Use the index as the key to locate the next opcode. */\n");
+ printf (" int key = opcode - aarch64_opcode_table;\n");
+ printf (" int value;\n");
+ printf (" switch (key)\n");
+ printf (" {\n");
+
+ for (i = 0; i < num; ++i)
+ {
+ const opcode_node *node = table + i;
+ assert (node->next);
+ if (node->next->next == NULL)
+ continue;
+ while (node->next->next)
+ {
+ printf (" case %u: value = %u; break;", real_index (node->next->index),
+ real_index (node->next->next->index));
+ printf ("\t/* %s --> %s. */\n",
+ get_aarch64_opcode (node->next)->name,
+ get_aarch64_opcode (node->next->next)->name);
+ node = node->next;
+ }
+ }
+
+ printf (" default: return NULL;\n");
+ printf (" }\n\n");
+
+ printf (" return aarch64_opcode_table + value;\n");
+ printf ("}\n");
+}
+
+/* Given OPCODE, establish and return a link list of alias nodes in the
+ preferred order. */
+
+opcode_node *
+find_alias_opcode (const aarch64_opcode *opcode)
+{
+ int i;
+ /* Assume maximum of 8 disassemble preference candidates. */
+ const int max_num_aliases = 8;
+ const aarch64_opcode *ent;
+ const aarch64_opcode *preferred[max_num_aliases];
+ opcode_node head, **next;
+
+ assert (opcode_has_alias (opcode));
+
+ i = 0;
+ ent = aarch64_opcode_table;
+ while (ent->name != NULL)
+ {
+ /* The mask of an alias opcode must be equal to or a super-set (i.e.
+ more constrained) of that of the aliased opcode; so is the base
+ opcode value. */
+ if (alias_opcode_p (ent) == TRUE
+ && (ent->mask & opcode->mask) == opcode->mask
+ && (opcode->mask & ent->opcode) == (opcode->mask & opcode->opcode))
+ {
+ assert (i < max_num_aliases);
+ preferred[i++] = ent;
+ if (debug)
+ printf ("found %s for %s.", ent->name, opcode->name);
+ }
+ ++ent;
+ }
+
+ if (debug)
+ {
+ int m;
+ printf ("un-orderd list: ");
+ for (m = 0; m < i; ++m)
+ printf ("%s, ", preferred[m]->name);
+ printf ("\n");
+ }
+
+ /* There must be at least one alias. */
+ assert (i >= 1);
+
+ /* Sort preferred array according to the priority (from the lowest to the
+ highest. */
+ if (i > 1)
+ {
+ int j, k;
+ for (j = 0; j < i - 1; ++j)
+ {
+ for (k = 0; k < i - 1 - j; ++k)
+ {
+ const aarch64_opcode *t;
+ t = preferred [k+1];
+ if (opcode_priority (t) < opcode_priority (preferred [k]))
+ {
+ preferred [k+1] = preferred [k];
+ preferred [k] = t;
+ }
+ }
+ }
+ }
+
+ if (debug)
+ {
+ int m;
+ printf ("orderd list: ");
+ for (m = 0; m < i; ++m)
+ printf ("%s, ", preferred[m]->name);
+ printf ("\n");
+ }
+
+ /* Create a link-list of opcode_node with disassemble preference from
+ higher to lower. */
+ next = &head.next;
+ --i;
+ while (i >= 0)
+ {
+ const aarch64_opcode *alias = preferred [i];
+ opcode_node *node = new_opcode_node ();
+
+ if (debug)
+ printf ("add %s.\n", alias->name);
+
+ node->index = alias - aarch64_opcode_table;
+ *next = node;
+ next = &node->next;
+
+ --i;
+ }
+ *next = NULL;
+
+ return head.next;
+}
+
+/* Create and return alias information.
+ Return the address of the created alias info table; return the number
+ of table entries in *NUM_PTR. */
+
+opcode_node *
+create_alias_info (int *num_ptr)
+{
+ int i, num;
+ opcode_node *ret;
+ const aarch64_opcode *ent;
+
+ /* Calculate the total number of opcodes that have alias. */
+ num = 0;
+ ent = aarch64_opcode_table;
+ while (ent->name != NULL)
+ {
+ if (opcode_has_alias (ent))
+ {
+ /* Assert the alias relationship be flat-structured to keep
+ algorithms simple; not allow F_ALIAS and F_HAS_ALIAS both
+ specified. */
+ assert (!alias_opcode_p (ent));
+ ++num;
+ }
+ ++ent;
+ }
+ assert (num_ptr);
+ *num_ptr = num;
+
+ /* The array of real opcodes that have alias(es). */
+ ret = malloc (sizeof (opcode_node) * num);
+
+ /* For each opcode, establish a list of alias nodes in a preferred
+ order. */
+ for (i = 0, ent = aarch64_opcode_table; i < num; ++i, ++ent)
+ {
+ opcode_node *node = ret + i;
+ while (ent->name != NULL && !opcode_has_alias (ent))
+ ++ent;
+ assert (ent->name != NULL);
+ node->index = ent - aarch64_opcode_table;
+ node->next = find_alias_opcode (ent);
+ assert (node->next);
+ }
+ assert (i == num);
+
+ return ret;
+}
+
+/* Release the dynamic memory resource allocated for the generation of the
+ alias information. */
+
+void
+release_resource_alias_info (opcode_node *alias_info, int num)
+{
+ int i = 0;
+ opcode_node *node = alias_info;
+
+ /* Free opcode_node list. */
+ for (; i < num; ++i, ++node)
+ {
+ opcode_node *list = node->next;
+ do
+ {
+ opcode_node *next = list->next;
+ free (list);
+ list = next;
+ } while (list != NULL);
+ }
+
+ /* Free opcode_node array. */
+ free (alias_info);
+}
+
+/* As a debugging utility, print out the result of the table division, although
+ it is not doing much this moment. */
+static void
+print_divide_result (const struct bittree *bittree ATTRIBUTE_UNUSED)
+{
+ printf ("max_num_opcodes_at_leaf_node: %d\n", max_num_opcodes_at_leaf_node);
+ return;
+}
+
+/* Structure to help generate the operand table. */
+struct operand
+{
+ const char *class;
+ const char *inserter;
+ const char *extractor;
+ const char *str;
+ const char *flags;
+ const char *fields;
+ const char *desc;
+ unsigned processed : 1;
+ unsigned has_inserter : 1;
+ unsigned has_extractor : 1;
+};
+
+typedef struct operand operand;
+
+#ifdef X
+#undef X
+#endif
+
+#ifdef Y
+#undef Y
+#endif
+
+#ifdef F
+#undef F
+#endif
+
+/* Get the operand information in strings. */
+
+static operand operands[] =
+{
+ {"NIL", "0", "0", "", "0", "{0}", "<none>", 0, 0, 0},
+#define F(...) #__VA_ARGS__
+#define X(a,b,c,d,e,f,g) \
+ {#a, #b, #c, d, #e, "{"f"}", g, 0, 0, 0},
+#define Y(a,b,d,e,f,g) \
+ {#a, "ins_"#b, "ext_"#b, d, #e, "{"f"}", g, 0, 0, 0},
+ AARCH64_OPERANDS
+ {"NIL", "0", "0", "", "0", "{0}", "DUMMY", 0, 0, 0},
+};
+
+#undef F
+#undef X
+
+static void
+process_operand_table (void)
+{
+ int i;
+ operand *opnd;
+ const int num = sizeof (operands) / sizeof (operand);
+
+ for (i = 0, opnd = operands; i < num; ++i, ++opnd)
+ {
+ opnd->has_inserter = opnd->inserter[0] != '0';
+ opnd->has_extractor = opnd->extractor[0] != '0';
+ }
+}
+
+/* Generate aarch64_operands in C to the standard output. */
+
+static void
+print_operand_table (void)
+{
+ int i;
+ operand *opnd;
+ const int num = sizeof (operands) / sizeof (operand);
+
+ if (debug)
+ printf ("Enter print_operand_table\n");
+
+ printf ("\n");
+ printf ("const struct aarch64_operand aarch64_operands[] =\n");
+ printf ("{\n");
+
+ for (i = 0, opnd = operands; i < num; ++i, ++opnd)
+ {
+ char flags[256];
+ flags[0] = '\0';
+ if (opnd->flags[0] != '0')
+ sprintf (flags, "%s", opnd->flags);
+ if (opnd->has_inserter)
+ {
+ if (flags[0] != '\0')
+ strcat (flags, " | ");
+ strcat (flags, "OPD_F_HAS_INSERTER");
+ }
+ if (opnd->has_extractor)
+ {
+ if (flags[0] != '\0')
+ strcat (flags, " | ");
+ strcat (flags, "OPD_F_HAS_EXTRACTOR");
+ }
+ if (flags[0] == '\0')
+ {
+ flags[0] = '0';
+ flags[1] = '\0';
+ }
+ printf (" {AARCH64_OPND_CLASS_%s, \"%s\", %s, %s, \"%s\"},\n",
+ opnd->class, opnd->str, flags, opnd->fields, opnd->desc);
+ }
+ printf ("};\n");
+}
+
+/* Generate aarch64_insert_operand in C to the standard output. */
+
+static void
+print_operand_inserter (void)
+{
+ int i;
+ operand *opnd;
+ const int num = sizeof (operands) / sizeof (operand);
+
+ if (debug)
+ printf ("Enter print_operand_inserter\n");
+
+ printf ("\n");
+ printf ("const char*\n");
+ printf ("aarch64_insert_operand (const aarch64_operand *self,\n\
+ const aarch64_opnd_info *info,\n\
+ aarch64_insn *code, const aarch64_inst *inst)\n");
+ printf ("{\n");
+ printf (" /* Use the index as the key. */\n");
+ printf (" int key = self - aarch64_operands;\n");
+ printf (" switch (key)\n");
+ printf (" {\n");
+
+ for (i = 0, opnd = operands; i < num; ++i, ++opnd)
+ opnd->processed = 0;
+
+ for (i = 0, opnd = operands; i < num; ++i, ++opnd)
+ {
+ if (!opnd->processed && opnd->has_inserter)
+ {
+ int j = i + 1;
+ const int len = strlen (opnd->inserter);
+ operand *opnd2 = opnd + 1;
+ printf (" case %u:\n", (unsigned int)(opnd - operands));
+ opnd->processed = 1;
+ for (; j < num; ++j, ++opnd2)
+ {
+ if (!opnd2->processed
+ && opnd2->has_inserter
+ && len == strlen (opnd2->inserter)
+ && strncmp (opnd->inserter, opnd2->inserter, len) == 0)
+ {
+ printf (" case %u:\n", (unsigned int)(opnd2 - operands));
+ opnd2->processed = 1;
+ }
+ }
+ printf (" return aarch64_%s (self, info, code, inst);\n",
+ opnd->inserter);
+ }
+ }
+
+ printf (" default: assert (0); abort ();\n");
+ printf (" }\n");
+ printf ("}\n");
+}
+
+/* Generate aarch64_extract_operand in C to the standard output. */
+
+static void
+print_operand_extractor (void)
+{
+ int i;
+ operand *opnd;
+ const int num = sizeof (operands) / sizeof (operand);
+
+ if (debug)
+ printf ("Enter print_operand_extractor\n");
+
+ printf ("\n");
+ printf ("int\n");
+ printf ("aarch64_extract_operand (const aarch64_operand *self,\n\
+ aarch64_opnd_info *info,\n\
+ aarch64_insn code, const aarch64_inst *inst)\n");
+ printf ("{\n");
+ printf (" /* Use the index as the key. */\n");
+ printf (" int key = self - aarch64_operands;\n");
+ printf (" switch (key)\n");
+ printf (" {\n");
+
+ for (i = 0, opnd = operands; i < num; ++i, ++opnd)
+ opnd->processed = 0;
+
+ for (i = 0, opnd = operands; i < num; ++i, ++opnd)
+ {
+ if (!opnd->processed && opnd->has_extractor)
+ {
+ int j = i + 1;
+ const int len = strlen (opnd->extractor);
+ operand *opnd2 = opnd + 1;
+ printf (" case %u:\n", (unsigned int)(opnd - operands));
+ opnd->processed = 1;
+ for (; j < num; ++j, ++opnd2)
+ {
+ if (!opnd2->processed
+ && opnd2->has_extractor
+ && len == strlen (opnd2->extractor)
+ && strncmp (opnd->extractor, opnd2->extractor, len) == 0)
+ {
+ printf (" case %u:\n", (unsigned int)(opnd2 - operands));
+ opnd2->processed = 1;
+ }
+ }
+ printf (" return aarch64_%s (self, info, code, inst);\n",
+ opnd->extractor);
+ }
+ }
+
+ printf (" default: assert (0); abort ();\n");
+ printf (" }\n");
+ printf ("}\n");
+}
+
+/* Table indexed by opcode enumerator stores the index of the corresponding
+ opcode entry in aarch64_opcode_table. */
+static unsigned op_enum_table [OP_TOTAL_NUM];
+
+/* Print out the routine which, given the opcode enumerator, returns the
+ corresponding opcode entry pointer. */
+
+static void
+print_get_opcode (void)
+{
+ int i;
+ const int num = OP_TOTAL_NUM;
+ const aarch64_opcode *opcode;
+
+ if (debug)
+ printf ("Enter print_get_opcode\n");
+
+ /* Fill in the internal table. */
+ opcode = aarch64_opcode_table;
+ while (opcode->name != NULL)
+ {
+ if (opcode->op != OP_NIL)
+ {
+ /* Assert opcode enumerator be unique, in other words, no shared by
+ different opcodes. */
+ if (op_enum_table[opcode->op] != 0)
+ {
+ fprintf (stderr, "Opcode %u is shared by different %s and %s.\n",
+ opcode->op,
+ aarch64_opcode_table[op_enum_table[opcode->op]].name,
+ opcode->name);
+ assert (0);
+ abort ();
+ }
+ assert (opcode->op < OP_TOTAL_NUM);
+ op_enum_table[opcode->op] = opcode - aarch64_opcode_table;
+ }
+ ++opcode;
+ }
+
+ /* Print the table. */
+ printf ("\n");
+ printf ("/* Indexed by an enum aarch64_op enumerator, the value is the offset of\n\
+ the corresponding aarch64_opcode entry in the aarch64_opcode_table. */\n\n");
+ printf ("static const unsigned op_enum_table [] =\n");
+ printf ("{\n");
+ for (i = 0; i < num; ++i)
+ printf (" %u,\n", op_enum_table[i]);
+ printf ("};\n");
+
+ /* Print the function. */
+ printf ("\n");
+ printf ("/* Given the opcode enumerator OP, return the pointer to the corresponding\n");
+ printf (" opcode entry. */\n");
+ printf ("\n");
+ printf ("const aarch64_opcode *\n");
+ printf ("aarch64_get_opcode (enum aarch64_op op)\n");
+ printf ("{\n");
+ printf (" return aarch64_opcode_table + op_enum_table[op];\n");
+ printf ("}\n");
+}
+
+/* Print out the content of an opcode table (not in use). */
+static void ATTRIBUTE_UNUSED
+print_table (struct aarch64_opcode* table)
+{
+ struct aarch64_opcode *ent = table;
+ do
+ {
+ printf ("%s\t%08x\t%08x\n", ent->name, (unsigned int)ent->opcode,
+ (unsigned int)ent->mask);
+ } while ((++ent)->name);
+}
+
+static const char * program_name = NULL;
+
+/* Program options. */
+struct option long_options[] =
+{
+ {"debug", no_argument, NULL, 'd'},
+ {"version", no_argument, NULL, 'V'},
+ {"help", no_argument, NULL, 'h'},
+ {"gen-opc", no_argument, NULL, 'c'},
+ {"gen-asm", no_argument, NULL, 'a'},
+ {"gen-dis", no_argument, NULL, 's'},
+ {0, no_argument, NULL, 0}
+};
+
+static void
+print_version (void)
+{
+ printf ("%s: version 1.0\n", program_name);
+ xexit (0);
+}
+
+static void
+usage (FILE * stream, int status)
+{
+ fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--help]\n",
+ program_name);
+ fprintf (stream, "\t[ [-c | --gen-opc] | [-a | --gen-asm] | [-s | --gen-dis] ]\n");
+ xexit (status);
+}
+
+int
+main (int argc, char **argv)
+{
+ extern int chdir (char *);
+ int c;
+ int gen_opcode_p = 0;
+ int gen_assembler_p = 0;
+ int gen_disassembler_p = 0;
+
+ program_name = *argv;
+ xmalloc_set_program_name (program_name);
+
+ while ((c = getopt_long (argc, argv, "vVdhacs", long_options, 0)) != EOF)
+ switch (c)
+ {
+ case 'V':
+ case 'v':
+ print_version ();
+ break;
+ case 'd':
+ debug = 1;
+ break;
+ case 'h':
+ case '?':
+ usage (stderr, 0);
+ break;
+ case 'c':
+ gen_opcode_p = 1;
+ break;
+ case 'a':
+ gen_assembler_p = 1;
+ break;
+ case 's':
+ gen_disassembler_p = 1;
+ break;
+ default:
+ case 0:
+ break;
+ }
+
+ if (argc == 1 || optind != argc)
+ usage (stdout, 1);
+
+ if (gen_opcode_p + gen_assembler_p + gen_disassembler_p > 1)
+ {
+ printf ("Please specify only one of the following options\n\
+ [-c | --gen-opc] [-a | --gen-asm] [-s | --gen-dis]\n");
+ xexit (2);
+ }
+
+ struct bittree *decoder_tree;
+
+ decoder_tree = initialize_decoder_tree ();
+ if (debug)
+ print_divide_result (decoder_tree);
+
+ printf ("/* This file is automatically generated by aarch64-gen. Do not edit! */\n");
+ printf ("/* Copyright 2012 Free Software Foundation, Inc.\n\
+ Contributed by ARM Ltd.\n\
+\n\
+ This file is part of the GNU opcodes library.\n\
+\n\
+ This library is free software; you can redistribute it and/or modify\n\
+ it under the terms of the GNU General Public License as published by\n\
+ the Free Software Foundation; either version 3, or (at your option)\n\
+ any later version.\n\
+\n\
+ It is distributed in the hope that it will be useful, but WITHOUT\n\
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
+ License for more details.\n\
+\n\
+ You should have received a copy of the GNU General Public License\n\
+ along with this program; see the file COPYING3. If not,\n\
+ see <http://www.gnu.org/licenses/>. */\n");
+
+ printf ("\n");
+ printf ("#include \"sysdep.h\"\n");
+ if (gen_opcode_p)
+ printf ("#include \"aarch64-opc.h\"\n");
+ if (gen_assembler_p)
+ printf ("#include \"aarch64-asm.h\"\n");
+ if (gen_disassembler_p)
+ printf ("#include \"aarch64-dis.h\"\n");
+ printf ("\n");
+
+ /* Generate opcode entry lookup for the disassembler. */
+ if (gen_disassembler_p)
+ {
+ print_decision_tree (decoder_tree);
+ print_find_next_opcode (decoder_tree);
+ release_resource_decoder_tree (decoder_tree);
+ }
+
+ /* Generate alias opcode handling for the assembler or the disassembler. */
+ if (gen_assembler_p || gen_disassembler_p)
+ {
+ int num;
+ opcode_node *alias_info = create_alias_info (&num);
+
+ if (gen_assembler_p)
+ print_find_real_opcode (alias_info, num);
+
+ if (gen_disassembler_p)
+ {
+ print_find_alias_opcode (alias_info, num);
+ print_find_next_alias_opcode (alias_info, num);
+ }
+
+ release_resource_alias_info (alias_info, num);
+ }
+
+ /* Generate operand table. */
+ process_operand_table ();
+
+ if (gen_assembler_p)
+ print_operand_inserter ();
+
+ if (gen_disassembler_p)
+ print_operand_extractor ();
+
+ if (gen_opcode_p)
+ print_operand_table ();
+
+ /* Generate utility to return aarch64_opcode entry given an enumerator. */
+ if (gen_opcode_p)
+ print_get_opcode ();
+
+ exit (0);
+}
diff --git a/opcodes/aarch64-opc-2.c b/opcodes/aarch64-opc-2.c
new file mode 100644
index 0000000..68681f6
--- /dev/null
+++ b/opcodes/aarch64-opc-2.c
@@ -0,0 +1,195 @@
+/* This file is automatically generated by aarch64-gen. Do not edit! */
+/* Copyright 2012 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of the GNU opcodes library.
+
+ This library 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 3, or (at your option)
+ any later version.
+
+ It 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; see the file COPYING3. If not,
+ see <http://www.gnu.org/licenses/>. */
+
+#include "sysdep.h"
+#include "aarch64-opc.h"
+
+
+const struct aarch64_operand aarch64_operands[] =
+{
+ {AARCH64_OPND_CLASS_NIL, "", 0, {0}, "<none>"},
+ {AARCH64_OPND_CLASS_INT_REG, "Rd", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rd}, "an integer register"},
+ {AARCH64_OPND_CLASS_INT_REG, "Rn", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "an integer register"},
+ {AARCH64_OPND_CLASS_INT_REG, "Rm", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rm}, "an integer register"},
+ {AARCH64_OPND_CLASS_INT_REG, "Rt", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rt}, "an integer register"},
+ {AARCH64_OPND_CLASS_INT_REG, "Rt2", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rt2}, "an integer register"},
+ {AARCH64_OPND_CLASS_INT_REG, "Rs", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rs}, "an integer register"},
+ {AARCH64_OPND_CLASS_INT_REG, "Ra", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Ra}, "an integer register"},
+ {AARCH64_OPND_CLASS_INT_REG, "Rt_SYS", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rt}, "an integer register"},
+ {AARCH64_OPND_CLASS_INT_REG, "Rd_SP", OPD_F_MAYBE_SP | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rd}, "an integer or stack pointer register"},
+ {AARCH64_OPND_CLASS_INT_REG, "Rn_SP", OPD_F_MAYBE_SP | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "an integer or stack pointer register"},
+ {AARCH64_OPND_CLASS_MODIFIED_REG, "Rm_EXT", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "an integer register with optional extension"},
+ {AARCH64_OPND_CLASS_MODIFIED_REG, "Rm_SFT", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "an integer register with optional shift"},
+ {AARCH64_OPND_CLASS_FP_REG, "Fd", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rd}, "a floating-point register"},
+ {AARCH64_OPND_CLASS_FP_REG, "Fn", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "a floating-point register"},
+ {AARCH64_OPND_CLASS_FP_REG, "Fm", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rm}, "a floating-point register"},
+ {AARCH64_OPND_CLASS_FP_REG, "Fa", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Ra}, "a floating-point register"},
+ {AARCH64_OPND_CLASS_FP_REG, "Ft", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rt}, "a floating-point register"},
+ {AARCH64_OPND_CLASS_FP_REG, "Ft2", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rt2}, "a floating-point register"},
+ {AARCH64_OPND_CLASS_SISD_REG, "Sd", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rd}, "a SIMD scalar register"},
+ {AARCH64_OPND_CLASS_SISD_REG, "Sn", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "a SIMD scalar register"},
+ {AARCH64_OPND_CLASS_SISD_REG, "Sm", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rm}, "a SIMD scalar register"},
+ {AARCH64_OPND_CLASS_SIMD_REG, "Vd", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rd}, "a SIMD vector register"},
+ {AARCH64_OPND_CLASS_SIMD_REG, "Vn", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "a SIMD vector register"},
+ {AARCH64_OPND_CLASS_SIMD_REG, "Vm", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rm}, "a SIMD vector register"},
+ {AARCH64_OPND_CLASS_FP_REG, "VdD1", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rd}, "the top half of a 128-bit FP/SIMD register"},
+ {AARCH64_OPND_CLASS_FP_REG, "VnD1", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "the top half of a 128-bit FP/SIMD register"},
+ {AARCH64_OPND_CLASS_SIMD_ELEMENT, "Ed", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rd}, "a SIMD vector element"},
+ {AARCH64_OPND_CLASS_SIMD_ELEMENT, "En", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "a SIMD vector element"},
+ {AARCH64_OPND_CLASS_SIMD_ELEMENT, "Em", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rm}, "a SIMD vector element"},
+ {AARCH64_OPND_CLASS_SIMD_REGLIST, "LVn", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "a SIMD vector register list"},
+ {AARCH64_OPND_CLASS_SIMD_REGLIST, "LVt", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a SIMD vector register list"},
+ {AARCH64_OPND_CLASS_SIMD_REGLIST, "LVt_AL", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a SIMD vector register list"},
+ {AARCH64_OPND_CLASS_SIMD_REGLIST, "LEt", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a SIMD vector element list"},
+ {AARCH64_OPND_CLASS_CP_REG, "Cn", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_CRn}, "a 4-bit opcode field named for historical reasons C0 - C15"},
+ {AARCH64_OPND_CLASS_CP_REG, "Cm", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_CRm}, "a 4-bit opcode field named for historical reasons C0 - C15"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "IDX", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm4}, "an immediate as the index of the least significant byte"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "IMM_VLSL", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a left shift amount for an AdvSIMD register"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "IMM_VLSR", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a right shift amount for an AdvSIMD register"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "SIMD_IMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "an immediate"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "SIMD_IMM_SFT", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "an 8-bit unsigned immediate with optional shift"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "SIMD_FPIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "an 8-bit floating-point constant"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "SHLL_IMM", OPD_F_HAS_EXTRACTOR, {}, "an immediate shift amount of 8, 16 or 32"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "IMM0", 0, {}, "0"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "FPIMM0", 0, {}, "0.0"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "FPIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm8}, "an 8-bit floating-point constant"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "IMMR", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_immr}, "the right rotate amount"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "IMMS", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm6}, "the leftmost bit number to be moved from the source"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "WIDTH", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm6}, "the width of the bit-field"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "IMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm6}, "an immediate"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "UIMM3_OP1", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_op1}, "a 3-bit unsigned immediate"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "UIMM3_OP2", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_op2}, "a 3-bit unsigned immediate"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "UIMM4", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_CRm}, "a 4-bit unsigned immediate"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "UIMM7", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_CRm, FLD_op2}, "a 7-bit unsigned immediate"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "BIT_NUM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_b5, FLD_b40}, "the bit number to be tested"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "EXCEPTION", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm16}, "a 16-bit unsigned immediate"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "CCMP_IMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm5}, "a 5-bit unsigned immediate"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "NZCV", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_nzcv}, "a flag bit specifier giving an alternative value for each flag"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "LIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_N,FLD_immr,FLD_imms}, "Logical immediate"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "AIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_shift,FLD_imm12}, "a 12-bit unsigned immediate with optional left shift of 12 bits"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "HALF", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm16}, "a 16-bit immediate with optional left shift"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "FBITS", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_scale}, "the number of bits after the binary point in the fixed-point value"},
+ {AARCH64_OPND_CLASS_IMMEDIATE, "IMM_MOV", 0, {}, "an immediate"},
+ {AARCH64_OPND_CLASS_NIL, "COND", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a condition"},
+ {AARCH64_OPND_CLASS_ADDRESS, "ADDR_ADRP", OPD_F_SEXT | OPD_F_HAS_EXTRACTOR, {FLD_immhi, FLD_immlo}, "21-bit PC-relative address of a 4KB page"},
+ {AARCH64_OPND_CLASS_ADDRESS, "ADDR_PCREL14", OPD_F_SEXT | OPD_F_SHIFT_BY_2 | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm14}, "14-bit PC-relative address"},
+ {AARCH64_OPND_CLASS_ADDRESS, "ADDR_PCREL19", OPD_F_SEXT | OPD_F_SHIFT_BY_2 | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm19}, "19-bit PC-relative address"},
+ {AARCH64_OPND_CLASS_ADDRESS, "ADDR_PCREL21", OPD_F_SEXT | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_immhi,FLD_immlo}, "21-bit PC-relative address"},
+ {AARCH64_OPND_CLASS_ADDRESS, "ADDR_PCREL26", OPD_F_SEXT | OPD_F_SHIFT_BY_2 | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm26}, "26-bit PC-relative address"},
+ {AARCH64_OPND_CLASS_ADDRESS, "ADDR_SIMPLE", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "an address with base register (no offset)"},
+ {AARCH64_OPND_CLASS_ADDRESS, "ADDR_REGOFF", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "an address with register offset"},
+ {AARCH64_OPND_CLASS_ADDRESS, "ADDR_SIMM7", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm7,FLD_index2}, "an address with 7-bit signed immediate offset"},
+ {AARCH64_OPND_CLASS_ADDRESS, "ADDR_SIMM9", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm9,FLD_index}, "an address with 9-bit signed immediate offset"},
+ {AARCH64_OPND_CLASS_ADDRESS, "ADDR_SIMM9_2", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm9,FLD_index}, "an address with 9-bit negative or unaligned immediate offset"},
+ {AARCH64_OPND_CLASS_ADDRESS, "ADDR_UIMM12", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn,FLD_imm12}, "an address with scaled, unsigned immediate offset"},
+ {AARCH64_OPND_CLASS_ADDRESS, "SIMD_ADDR_SIMPLE", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "an address with base register (no offset)"},
+ {AARCH64_OPND_CLASS_ADDRESS, "SIMD_ADDR_POST", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a post-indexed address with immediate or register increment"},
+ {AARCH64_OPND_CLASS_SYSTEM, "SYSREG", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a system register"},
+ {AARCH64_OPND_CLASS_SYSTEM, "PSTATEFIELD", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a PSTATE field name"},
+ {AARCH64_OPND_CLASS_SYSTEM, "SYSREG_AT", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "an address translation operation specifier"},
+ {AARCH64_OPND_CLASS_SYSTEM, "SYSREG_DC", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a data cache maintenance operation specifier"},
+ {AARCH64_OPND_CLASS_SYSTEM, "SYSREG_IC", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "an instructin cache maintenance operation specifier"},
+ {AARCH64_OPND_CLASS_SYSTEM, "SYSREG_TLBI", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a TBL invalidation operation specifier"},
+ {AARCH64_OPND_CLASS_SYSTEM, "BARRIER", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a barrier option name"},
+ {AARCH64_OPND_CLASS_SYSTEM, "BARRIER_ISB", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "the ISB option name SY or an optional 4-bit unsigned immediate"},
+ {AARCH64_OPND_CLASS_SYSTEM, "PRFOP", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "an prefetch operation specifier"},
+ {AARCH64_OPND_CLASS_NIL, "", 0, {0}, "DUMMY"},
+};
+
+/* Indexed by an enum aarch64_op enumerator, the value is the offset of
+ the corresponding aarch64_opcode entry in the aarch64_opcode_table. */
+
+static const unsigned op_enum_table [] =
+{
+ 0,
+ 648,
+ 649,
+ 650,
+ 653,
+ 654,
+ 655,
+ 656,
+ 657,
+ 651,
+ 652,
+ 658,
+ 659,
+ 681,
+ 682,
+ 685,
+ 691,
+ 692,
+ 695,
+ 697,
+ 698,
+ 687,
+ 688,
+ 701,
+ 703,
+ 741,
+ 742,
+ 743,
+ 744,
+ 12,
+ 506,
+ 507,
+ 764,
+ 766,
+ 768,
+ 748,
+ 767,
+ 765,
+ 259,
+ 495,
+ 505,
+ 504,
+ 746,
+ 501,
+ 498,
+ 491,
+ 490,
+ 497,
+ 500,
+ 502,
+ 503,
+ 756,
+ 125,
+ 522,
+ 525,
+ 528,
+ 523,
+ 526,
+ 614,
+ 160,
+ 161,
+ 162,
+ 163,
+ 416,
+ 583,
+};
+
+/* Given the opcode enumerator OP, return the pointer to the corresponding
+ opcode entry. */
+
+const aarch64_opcode *
+aarch64_get_opcode (enum aarch64_op op)
+{
+ return aarch64_opcode_table + op_enum_table[op];
+}
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
new file mode 100644
index 0000000..2d66a25
--- /dev/null
+++ b/opcodes/aarch64-opc.c
@@ -0,0 +1,3074 @@
+/* aarch64-opc.c -- AArch64 opcode support.
+ Copyright 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of the GNU opcodes library.
+
+ This library 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 3, or (at your option)
+ any later version.
+
+ It 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; see the file COPYING3. If not,
+ see <http://www.gnu.org/licenses/>. */
+
+#include "sysdep.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <inttypes.h>
+
+#include "opintl.h"
+
+#include "aarch64-opc.h"
+
+#ifdef DEBUG_AARCH64
+int debug_dump = FALSE;
+#endif /* DEBUG_AARCH64 */
+
+/* Helper functions to determine which operand to be used to encode/decode
+ the size:Q fields for AdvSIMD instructions. */
+
+static inline bfd_boolean
+vector_qualifier_p (enum aarch64_opnd_qualifier qualifier)
+{
+ return ((qualifier >= AARCH64_OPND_QLF_V_8B
+ && qualifier <= AARCH64_OPND_QLF_V_1Q) ? TRUE
+ : FALSE);
+}
+
+static inline bfd_boolean
+fp_qualifier_p (enum aarch64_opnd_qualifier qualifier)
+{
+ return ((qualifier >= AARCH64_OPND_QLF_S_B
+ && qualifier <= AARCH64_OPND_QLF_S_Q) ? TRUE
+ : FALSE);
+}
+
+enum data_pattern
+{
+ DP_UNKNOWN,
+ DP_VECTOR_3SAME,
+ DP_VECTOR_LONG,
+ DP_VECTOR_WIDE,
+ DP_VECTOR_ACROSS_LANES,
+};
+
+static const char significant_operand_index [] =
+{
+ 0, /* DP_UNKNOWN, by default using operand 0. */
+ 0, /* DP_VECTOR_3SAME */
+ 1, /* DP_VECTOR_LONG */
+ 2, /* DP_VECTOR_WIDE */
+ 1, /* DP_VECTOR_ACROSS_LANES */
+};
+
+/* Given a sequence of qualifiers in QUALIFIERS, determine and return
+ the data pattern.
+ N.B. QUALIFIERS is a possible sequence of qualifiers each of which
+ corresponds to one of a sequence of operands. */
+
+static enum data_pattern
+get_data_pattern (const aarch64_opnd_qualifier_seq_t qualifiers)
+{
+ if (vector_qualifier_p (qualifiers[0]) == TRUE)
+ {
+ /* e.g. v.4s, v.4s, v.4s
+ or v.4h, v.4h, v.h[3]. */
+ if (qualifiers[0] == qualifiers[1]
+ && vector_qualifier_p (qualifiers[2]) == TRUE
+ && (aarch64_get_qualifier_esize (qualifiers[0])
+ == aarch64_get_qualifier_esize (qualifiers[1]))
+ && (aarch64_get_qualifier_esize (qualifiers[0])
+ == aarch64_get_qualifier_esize (qualifiers[2])))
+ return DP_VECTOR_3SAME;
+ /* e.g. v.8h, v.8b, v.8b.
+ or v.4s, v.4h, v.h[2].
+ or v.8h, v.16b. */
+ if (vector_qualifier_p (qualifiers[1]) == TRUE
+ && aarch64_get_qualifier_esize (qualifiers[0]) != 0
+ && (aarch64_get_qualifier_esize (qualifiers[0])
+ == aarch64_get_qualifier_esize (qualifiers[1]) << 1))
+ return DP_VECTOR_LONG;
+ /* e.g. v.8h, v.8h, v.8b. */
+ if (qualifiers[0] == qualifiers[1]
+ && vector_qualifier_p (qualifiers[2]) == TRUE
+ && aarch64_get_qualifier_esize (qualifiers[0]) != 0
+ && (aarch64_get_qualifier_esize (qualifiers[0])
+ == aarch64_get_qualifier_esize (qualifiers[2]) << 1)
+ && (aarch64_get_qualifier_esize (qualifiers[0])
+ == aarch64_get_qualifier_esize (qualifiers[1])))
+ return DP_VECTOR_WIDE;
+ }
+ else if (fp_qualifier_p (qualifiers[0]) == TRUE)
+ {
+ /* e.g. SADDLV <V><d>, <Vn>.<T>. */
+ if (vector_qualifier_p (qualifiers[1]) == TRUE
+ && qualifiers[2] == AARCH64_OPND_QLF_NIL)
+ return DP_VECTOR_ACROSS_LANES;
+ }
+
+ return DP_UNKNOWN;
+}
+
+/* Select the operand to do the encoding/decoding of the 'size:Q' fields in
+ the AdvSIMD instructions. */
+/* N.B. it is possible to do some optimization that doesn't call
+ get_data_pattern each time when we need to select an operand. We can
+ either buffer the caculated the result or statically generate the data,
+ however, it is not obvious that the optimization will bring significant
+ benefit. */
+
+int
+aarch64_select_operand_for_sizeq_field_coding (const aarch64_opcode *opcode)
+{
+ return
+ significant_operand_index [get_data_pattern (opcode->qualifiers_list[0])];
+}
+
+const aarch64_field fields[] =
+{
+ { 0, 0 }, /* NIL. */
+ { 0, 4 }, /* cond2: condition in truly conditional-executed inst. */
+ { 0, 4 }, /* nzcv: flag bit specifier, encoded in the "nzcv" field. */
+ { 5, 5 }, /* defgh: d:e:f:g:h bits in AdvSIMD modified immediate. */
+ { 16, 3 }, /* abc: a:b:c bits in AdvSIMD modified immediate. */
+ { 5, 19 }, /* imm19: e.g. in CBZ. */
+ { 5, 19 }, /* immhi: e.g. in ADRP. */
+ { 29, 2 }, /* immlo: e.g. in ADRP. */
+ { 22, 2 }, /* size: in most AdvSIMD and floating-point instructions. */
+ { 10, 2 }, /* vldst_size: size field in the AdvSIMD load/store inst. */
+ { 29, 1 }, /* op: in AdvSIMD modified immediate instructions. */
+ { 30, 1 }, /* Q: in most AdvSIMD instructions. */
+ { 0, 5 }, /* Rt: in load/store instructions. */
+ { 0, 5 }, /* Rd: in many integer instructions. */
+ { 5, 5 }, /* Rn: in many integer instructions. */
+ { 10, 5 }, /* Rt2: in load/store pair instructions. */
+ { 10, 5 }, /* Ra: in fp instructions. */
+ { 5, 3 }, /* op2: in the system instructions. */
+ { 8, 4 }, /* CRm: in the system instructions. */
+ { 12, 4 }, /* CRn: in the system instructions. */
+ { 16, 3 }, /* op1: in the system instructions. */
+ { 19, 2 }, /* op0: in the system instructions. */
+ { 10, 3 }, /* imm3: in add/sub extended reg instructions. */
+ { 12, 4 }, /* cond: condition flags as a source operand. */
+ { 12, 4 }, /* opcode: in advsimd load/store instructions. */
+ { 12, 4 }, /* cmode: in advsimd modified immediate instructions. */
+ { 13, 3 }, /* asisdlso_opcode: opcode in advsimd ld/st single element. */
+ { 13, 2 }, /* len: in advsimd tbl/tbx instructions. */
+ { 16, 5 }, /* Rm: in ld/st reg offset and some integer inst. */
+ { 16, 5 }, /* Rs: in load/store exclusive instructions. */
+ { 13, 3 }, /* option: in ld/st reg offset + add/sub extended reg inst. */
+ { 12, 1 }, /* S: in load/store reg offset instructions. */
+ { 21, 2 }, /* hw: in move wide constant instructions. */
+ { 22, 2 }, /* opc: in load/store reg offset instructions. */
+ { 23, 1 }, /* opc1: in load/store reg offset instructions. */
+ { 22, 2 }, /* shift: in add/sub reg/imm shifted instructions. */
+ { 22, 2 }, /* type: floating point type field in fp data inst. */
+ { 30, 2 }, /* ldst_size: size field in ld/st reg offset inst. */
+ { 10, 6 }, /* imm6: in add/sub reg shifted instructions. */
+ { 11, 4 }, /* imm4: in advsimd ext and advsimd ins instructions. */
+ { 16, 5 }, /* imm5: in conditional compare (immediate) instructions. */
+ { 15, 7 }, /* imm7: in load/store pair pre/post index instructions. */
+ { 13, 8 }, /* imm8: in floating-point scalar move immediate inst. */
+ { 12, 9 }, /* imm9: in load/store pre/post index instructions. */
+ { 10, 12 }, /* imm12: in ld/st unsigned imm or add/sub shifted inst. */
+ { 5, 14 }, /* imm14: in test bit and branch instructions. */
+ { 5, 16 }, /* imm16: in exception instructions. */
+ { 0, 26 }, /* imm26: in unconditional branch instructions. */
+ { 10, 6 }, /* imms: in bitfield and logical immediate instructions. */
+ { 16, 6 }, /* immr: in bitfield and logical immediate instructions. */
+ { 16, 3 }, /* immb: in advsimd shift by immediate instructions. */
+ { 19, 4 }, /* immh: in advsimd shift by immediate instructions. */
+ { 22, 1 }, /* N: in logical (immediate) instructions. */
+ { 11, 1 }, /* index: in ld/st inst deciding the pre/post-index. */
+ { 24, 1 }, /* index2: in ld/st pair inst deciding the pre/post-index. */
+ { 31, 1 }, /* sf: in integer data processing instructions. */
+ { 11, 1 }, /* H: in advsimd scalar x indexed element instructions. */
+ { 21, 1 }, /* L: in advsimd scalar x indexed element instructions. */
+ { 20, 1 }, /* M: in advsimd scalar x indexed element instructions. */
+ { 31, 1 }, /* b5: in the test bit and branch instructions. */
+ { 19, 5 }, /* b40: in the test bit and branch instructions. */
+ { 10, 6 }, /* scale: in the fixed-point scalar to fp converting inst. */
+};
+
+enum aarch64_operand_class
+aarch64_get_operand_class (enum aarch64_opnd type)
+{
+ return aarch64_operands[type].op_class;
+}
+
+const char *
+aarch64_get_operand_name (enum aarch64_opnd type)
+{
+ return aarch64_operands[type].name;
+}
+
+/* Get operand description string.
+ This is usually for the diagnosis purpose. */
+const char *
+aarch64_get_operand_desc (enum aarch64_opnd type)
+{
+ return aarch64_operands[type].desc;
+}
+
+/* Table of all conditional affixes. */
+const aarch64_cond aarch64_conds[16] =
+{
+ {{"eq"}, 0x0},
+ {{"ne"}, 0x1},
+ {{"cs", "hs"}, 0x2},
+ {{"cc", "lo", "ul"}, 0x3},
+ {{"mi"}, 0x4},
+ {{"pl"}, 0x5},
+ {{"vs"}, 0x6},
+ {{"vc"}, 0x7},
+ {{"hi"}, 0x8},
+ {{"ls"}, 0x9},
+ {{"ge"}, 0xa},
+ {{"lt"}, 0xb},
+ {{"gt"}, 0xc},
+ {{"le"}, 0xd},
+ {{"al"}, 0xe},
+ {{"nv"}, 0xf},
+};
+
+const aarch64_cond *
+get_cond_from_value (aarch64_insn value)
+{
+ assert (value < 16);
+ return &aarch64_conds[(unsigned int) value];
+}
+
+const aarch64_cond *
+get_inverted_cond (const aarch64_cond *cond)
+{
+ return &aarch64_conds[cond->value ^ 0x1];
+}
+
+/* Table describing the operand extension/shifting operators; indexed by
+ enum aarch64_modifier_kind.
+
+ The value column provides the most common values for encoding modifiers,
+ which enables table-driven encoding/decoding for the modifiers. */
+const struct aarch64_name_value_pair aarch64_operand_modifiers [] =
+{
+ {"none", 0x0},
+ {"msl", 0x0},
+ {"ror", 0x3},
+ {"asr", 0x2},
+ {"lsr", 0x1},
+ {"lsl", 0x0},
+ {"uxtb", 0x0},
+ {"uxth", 0x1},
+ {"uxtw", 0x2},
+ {"uxtx", 0x3},
+ {"sxtb", 0x4},
+ {"sxth", 0x5},
+ {"sxtw", 0x6},
+ {"sxtx", 0x7},
+ {NULL, 0},
+};
+
+enum aarch64_modifier_kind
+aarch64_get_operand_modifier (const struct aarch64_name_value_pair *desc)
+{
+ return desc - aarch64_operand_modifiers;
+}
+
+aarch64_insn
+aarch64_get_operand_modifier_value (enum aarch64_modifier_kind kind)
+{
+ return aarch64_operand_modifiers[kind].value;
+}
+
+enum aarch64_modifier_kind
+aarch64_get_operand_modifier_from_value (aarch64_insn value,
+ bfd_boolean extend_p)
+{
+ if (extend_p == TRUE)
+ return AARCH64_MOD_UXTB + value;
+ else
+ return AARCH64_MOD_LSL - value;
+}
+
+bfd_boolean
+aarch64_extend_operator_p (enum aarch64_modifier_kind kind)
+{
+ return (kind > AARCH64_MOD_LSL && kind <= AARCH64_MOD_SXTX)
+ ? TRUE : FALSE;
+}
+
+static inline bfd_boolean
+aarch64_shift_operator_p (enum aarch64_modifier_kind kind)
+{
+ return (kind >= AARCH64_MOD_ROR && kind <= AARCH64_MOD_LSL)
+ ? TRUE : FALSE;
+}
+
+const struct aarch64_name_value_pair aarch64_barrier_options[16] =
+{
+ { "#0x00", 0x0 },
+ { "oshld", 0x1 },
+ { "oshst", 0x2 },
+ { "osh", 0x3 },
+ { "#0x04", 0x4 },
+ { "nshld", 0x5 },
+ { "nshst", 0x6 },
+ { "nsh", 0x7 },
+ { "#0x08", 0x8 },
+ { "ishld", 0x9 },
+ { "ishst", 0xa },
+ { "ish", 0xb },
+ { "#0x0c", 0xc },
+ { "ld", 0xd },
+ { "st", 0xe },
+ { "sy", 0xf },
+};
+
+/* op -> op: load = 0 store = 1
+ l -> level: 1-3
+ t -> temporal: temporal (retained) = 0 non-temporal (streaming) = 1 */
+#define B(op,l,t) ((((op) * 2) << 3) | (((l) - 1) << 1) | (t))
+const struct aarch64_name_value_pair aarch64_prfops[32] =
+{
+ { "pldl1keep", B(0, 1, 0) },
+ { "pldl1strm", B(0, 1, 1) },
+ { "pldl2keep", B(0, 2, 0) },
+ { "pldl2strm", B(0, 2, 1) },
+ { "pldl3keep", B(0, 3, 0) },
+ { "pldl3strm", B(0, 3, 1) },
+ { "#0x06", 0x06 },
+ { "#0x07", 0x07 },
+ { "#0x08", 0x08 },
+ { "#0x09", 0x09 },
+ { "#0x0a", 0x0a },
+ { "#0x0b", 0x0b },
+ { "#0x0c", 0x0c },
+ { "#0x0d", 0x0d },
+ { "#0x0e", 0x0e },
+ { "#0x0f", 0x0f },
+ { "pstl1keep", B(1, 1, 0) },
+ { "pstl1strm", B(1, 1, 1) },
+ { "pstl2keep", B(1, 2, 0) },
+ { "pstl2strm", B(1, 2, 1) },
+ { "pstl3keep", B(1, 3, 0) },
+ { "pstl3strm", B(1, 3, 1) },
+ { "#0x16", 0x16 },
+ { "#0x17", 0x17 },
+ { "#0x18", 0x18 },
+ { "#0x19", 0x19 },
+ { "#0x1a", 0x1a },
+ { "#0x1b", 0x1b },
+ { "#0x1c", 0x1c },
+ { "#0x1d", 0x1d },
+ { "#0x1e", 0x1e },
+ { "#0x1f", 0x1f },
+};
+#undef B
+
+/* Utilities on value constraint. */
+
+static inline int
+value_in_range_p (int64_t value, int low, int high)
+{
+ return (value >= low && value <= high) ? 1 : 0;
+}
+
+static inline int
+value_aligned_p (int64_t value, int align)
+{
+ return ((value & (align - 1)) == 0) ? 1 : 0;
+}
+
+/* A signed value fits in a field. */
+static inline int
+value_fit_signed_field_p (int64_t value, unsigned width)
+{
+ assert (width < 32);
+ if (width < sizeof (value) * 8)
+ {
+ int64_t lim = (int64_t)1 << (width - 1);
+ if (value >= -lim && value < lim)
+ return 1;
+ }
+ return 0;
+}
+
+/* An unsigned value fits in a field. */
+static inline int
+value_fit_unsigned_field_p (int64_t value, unsigned width)
+{
+ assert (width < 32);
+ if (width < sizeof (value) * 8)
+ {
+ int64_t lim = (int64_t)1 << width;
+ if (value >= 0 && value < lim)
+ return 1;
+ }
+ return 0;
+}
+
+/* Return 1 if OPERAND is SP or WSP. */
+int
+aarch64_stack_pointer_p (const aarch64_opnd_info *operand)
+{
+ return ((aarch64_get_operand_class (operand->type)
+ == AARCH64_OPND_CLASS_INT_REG)
+ && operand_maybe_stack_pointer (aarch64_operands + operand->type)
+ && operand->reg.regno == 31);
+}
+
+/* Return 1 if OPERAND is XZR or WZP. */
+int
+aarch64_zero_register_p (const aarch64_opnd_info *operand)
+{
+ return ((aarch64_get_operand_class (operand->type)
+ == AARCH64_OPND_CLASS_INT_REG)
+ && !operand_maybe_stack_pointer (aarch64_operands + operand->type)
+ && operand->reg.regno == 31);
+}
+
+/* Return true if the operand *OPERAND that has the operand code
+ OPERAND->TYPE and been qualified by OPERAND->QUALIFIER can be also
+ qualified by the qualifier TARGET. */
+
+static inline int
+operand_also_qualified_p (const struct aarch64_opnd_info *operand,
+ aarch64_opnd_qualifier_t target)
+{
+ switch (operand->qualifier)
+ {
+ case AARCH64_OPND_QLF_W:
+ if (target == AARCH64_OPND_QLF_WSP && aarch64_stack_pointer_p (operand))
+ return 1;
+ break;
+ case AARCH64_OPND_QLF_X:
+ if (target == AARCH64_OPND_QLF_SP && aarch64_stack_pointer_p (operand))
+ return 1;
+ break;
+ case AARCH64_OPND_QLF_WSP:
+ if (target == AARCH64_OPND_QLF_W
+ && operand_maybe_stack_pointer (aarch64_operands + operand->type))
+ return 1;
+ break;
+ case AARCH64_OPND_QLF_SP:
+ if (target == AARCH64_OPND_QLF_X
+ && operand_maybe_stack_pointer (aarch64_operands + operand->type))
+ return 1;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* Given qualifier sequence list QSEQ_LIST and the known qualifier KNOWN_QLF
+ for operand KNOWN_IDX, return the expected qualifier for operand IDX.
+
+ Return NIL if more than one expected qualifiers are found. */
+
+aarch64_opnd_qualifier_t
+aarch64_get_expected_qualifier (const aarch64_opnd_qualifier_seq_t *qseq_list,
+ int idx,
+ const aarch64_opnd_qualifier_t known_qlf,
+ int known_idx)
+{
+ int i, saved_i;
+
+ /* Special case.
+
+ When the known qualifier is NIL, we have to assume that there is only
+ one qualifier sequence in the *QSEQ_LIST and return the corresponding
+ qualifier directly. One scenario is that for instruction
+ PRFM <prfop>, [<Xn|SP>, #:lo12:<symbol>]
+ which has only one possible valid qualifier sequence
+ NIL, S_D
+ the caller may pass NIL in KNOWN_QLF to obtain S_D so that it can
+ determine the correct relocation type (i.e. LDST64_LO12) for PRFM.
+
+ Because the qualifier NIL has dual roles in the qualifier sequence:
+ it can mean no qualifier for the operand, or the qualifer sequence is
+ not in use (when all qualifiers in the sequence are NILs), we have to
+ handle this special case here. */
+ if (known_qlf == AARCH64_OPND_NIL)
+ {
+ assert (qseq_list[0][known_idx] == AARCH64_OPND_NIL);
+ return qseq_list[0][idx];
+ }
+
+ for (i = 0, saved_i = -1; i < AARCH64_MAX_QLF_SEQ_NUM; ++i)
+ {
+ if (qseq_list[i][known_idx] == known_qlf)
+ {
+ if (saved_i != -1)
+ /* More than one sequences are found to have KNOWN_QLF at
+ KNOWN_IDX. */
+ return AARCH64_OPND_NIL;
+ saved_i = i;
+ }
+ }
+
+ return qseq_list[saved_i][idx];
+}
+
+enum operand_qualifier_kind
+{
+ OQK_NIL,
+ OQK_OPD_VARIANT,
+ OQK_VALUE_IN_RANGE,
+ OQK_MISC,
+};
+
+/* Operand qualifier description. */
+struct operand_qualifier_data
+{
+ /* The usage of the three data fields depends on the qualifier kind. */
+ int data0;
+ int data1;
+ int data2;
+ /* Description. */
+ const char *desc;
+ /* Kind. */
+ enum operand_qualifier_kind kind;
+};
+
+/* Indexed by the operand qualifier enumerators. */
+struct operand_qualifier_data aarch64_opnd_qualifiers[] =
+{
+ {0, 0, 0, "NIL", OQK_NIL},
+
+ /* Operand variant qualifiers.
+ First 3 fields:
+ element size, number of elements and common value for encoding. */
+
+ {4, 1, 0x0, "w", OQK_OPD_VARIANT},
+ {8, 1, 0x1, "x", OQK_OPD_VARIANT},
+ {4, 1, 0x0, "wsp", OQK_OPD_VARIANT},
+ {8, 1, 0x1, "sp", OQK_OPD_VARIANT},
+
+ {1, 1, 0x0, "b", OQK_OPD_VARIANT},
+ {2, 1, 0x1, "h", OQK_OPD_VARIANT},
+ {4, 1, 0x2, "s", OQK_OPD_VARIANT},
+ {8, 1, 0x3, "d", OQK_OPD_VARIANT},
+ {16, 1, 0x4, "q", OQK_OPD_VARIANT},
+
+ {1, 8, 0x0, "8b", OQK_OPD_VARIANT},
+ {1, 16, 0x1, "16b", OQK_OPD_VARIANT},
+ {2, 4, 0x2, "4h", OQK_OPD_VARIANT},
+ {2, 8, 0x3, "8h", OQK_OPD_VARIANT},
+ {4, 2, 0x4, "2s", OQK_OPD_VARIANT},
+ {4, 4, 0x5, "4s", OQK_OPD_VARIANT},
+ {8, 1, 0x6, "1d", OQK_OPD_VARIANT},
+ {8, 2, 0x7, "2d", OQK_OPD_VARIANT},
+ {16, 1, 0x8, "1q", OQK_OPD_VARIANT},
+
+ /* Qualifiers constraining the value range.
+ First 3 fields:
+ Lower bound, higher bound, unused. */
+
+ {0, 7, 0, "imm_0_7" , OQK_VALUE_IN_RANGE},
+ {0, 15, 0, "imm_0_15", OQK_VALUE_IN_RANGE},
+ {0, 31, 0, "imm_0_31", OQK_VALUE_IN_RANGE},
+ {0, 63, 0, "imm_0_63", OQK_VALUE_IN_RANGE},
+ {1, 32, 0, "imm_1_32", OQK_VALUE_IN_RANGE},
+ {1, 64, 0, "imm_1_64", OQK_VALUE_IN_RANGE},
+
+ /* Qualifiers for miscellaneous purpose.
+ First 3 fields:
+ unused, unused and unused. */
+
+ {0, 0, 0, "lsl", 0},
+ {0, 0, 0, "msl", 0},
+
+ {0, 0, 0, "retrieving", 0},
+};
+
+static inline bfd_boolean
+operand_variant_qualifier_p (aarch64_opnd_qualifier_t qualifier)
+{
+ return (aarch64_opnd_qualifiers[qualifier].kind == OQK_OPD_VARIANT)
+ ? TRUE : FALSE;
+}
+
+static inline bfd_boolean
+qualifier_value_in_range_constraint_p (aarch64_opnd_qualifier_t qualifier)
+{
+ return (aarch64_opnd_qualifiers[qualifier].kind == OQK_VALUE_IN_RANGE)
+ ? TRUE : FALSE;
+}
+
+const char*
+aarch64_get_qualifier_name (aarch64_opnd_qualifier_t qualifier)
+{
+ return aarch64_opnd_qualifiers[qualifier].desc;
+}
+
+/* Given an operand qualifier, return the expected data element size
+ of a qualified operand. */
+unsigned char
+aarch64_get_qualifier_esize (aarch64_opnd_qualifier_t qualifier)
+{
+ assert (operand_variant_qualifier_p (qualifier) == TRUE);
+ return aarch64_opnd_qualifiers[qualifier].data0;
+}
+
+unsigned char
+aarch64_get_qualifier_nelem (aarch64_opnd_qualifier_t qualifier)
+{
+ assert (operand_variant_qualifier_p (qualifier) == TRUE);
+ return aarch64_opnd_qualifiers[qualifier].data1;
+}
+
+aarch64_insn
+aarch64_get_qualifier_standard_value (aarch64_opnd_qualifier_t qualifier)
+{
+ assert (operand_variant_qualifier_p (qualifier) == TRUE);
+ return aarch64_opnd_qualifiers[qualifier].data2;
+}
+
+static int
+get_lower_bound (aarch64_opnd_qualifier_t qualifier)
+{
+ assert (qualifier_value_in_range_constraint_p (qualifier) == TRUE);
+ return aarch64_opnd_qualifiers[qualifier].data0;
+}
+
+static int
+get_upper_bound (aarch64_opnd_qualifier_t qualifier)
+{
+ assert (qualifier_value_in_range_constraint_p (qualifier) == TRUE);
+ return aarch64_opnd_qualifiers[qualifier].data1;
+}
+
+#ifdef DEBUG_AARCH64
+void
+aarch64_verbose (const char *str, ...)
+{
+ va_list ap;
+ va_start (ap, str);
+ printf ("#### ");
+ vprintf (str, ap);
+ printf ("\n");
+ va_end (ap);
+}
+
+static inline void
+dump_qualifier_sequence (const aarch64_opnd_qualifier_t *qualifier)
+{
+ int i;
+ printf ("#### \t");
+ for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i, ++qualifier)
+ printf ("%s,", aarch64_get_qualifier_name (*qualifier));
+ printf ("\n");
+}
+
+static void
+dump_match_qualifiers (const struct aarch64_opnd_info *opnd,
+ const aarch64_opnd_qualifier_t *qualifier)
+{
+ int i;
+ aarch64_opnd_qualifier_t curr[AARCH64_MAX_OPND_NUM];
+
+ aarch64_verbose ("dump_match_qualifiers:");
+ for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
+ curr[i] = opnd[i].qualifier;
+ dump_qualifier_sequence (curr);
+ aarch64_verbose ("against");
+ dump_qualifier_sequence (qualifier);
+}
+#endif /* DEBUG_AARCH64 */
+
+/* TODO improve this, we can have an extra field at the runtime to
+ store the number of operands rather than calculating it every time. */
+
+int
+aarch64_num_of_operands (const aarch64_opcode *opcode)
+{
+ int i = 0;
+ const enum aarch64_opnd *opnds = opcode->operands;
+ while (opnds[i++] != AARCH64_OPND_NIL)
+ ;
+ --i;
+ assert (i >= 0 && i <= AARCH64_MAX_OPND_NUM);
+ return i;
+}
+
+/* Find the best matched qualifier sequence in *QUALIFIERS_LIST for INST.
+ If succeeds, fill the found sequence in *RET, return 1; otherwise return 0.
+
+ N.B. on the entry, it is very likely that only some operands in *INST
+ have had their qualifiers been established.
+
+ If STOP_AT is not -1, the function will only try to match
+ the qualifier sequence for operands before and including the operand
+ of index STOP_AT; and on success *RET will only be filled with the first
+ (STOP_AT+1) qualifiers.
+
+ A couple examples of the matching algorithm:
+
+ X,W,NIL should match
+ X,W,NIL
+
+ NIL,NIL should match
+ X ,NIL
+
+ Apart from serving the main encoding routine, this can also be called
+ during or after the operand decoding. */
+
+int
+aarch64_find_best_match (const aarch64_inst *inst,
+ const aarch64_opnd_qualifier_seq_t *qualifiers_list,
+ int stop_at, aarch64_opnd_qualifier_t *ret)
+{
+ int found = 0;
+ int i, num_opnds;
+ const aarch64_opnd_qualifier_t *qualifiers;
+
+ num_opnds = aarch64_num_of_operands (inst->opcode);
+ if (num_opnds == 0)
+ {
+ DEBUG_TRACE ("SUCCEED: no operand");
+ return 1;
+ }
+
+ if (stop_at < 0 || stop_at >= num_opnds)
+ stop_at = num_opnds - 1;
+
+ /* For each pattern. */
+ for (i = 0; i < AARCH64_MAX_QLF_SEQ_NUM; ++i, ++qualifiers_list)
+ {
+ int j;
+ qualifiers = *qualifiers_list;
+
+ /* Start as positive. */
+ found = 1;
+
+ DEBUG_TRACE ("%d", i);
+#ifdef DEBUG_AARCH64
+ if (debug_dump)
+ dump_match_qualifiers (inst->operands, qualifiers);
+#endif
+
+ /* Most opcodes has much fewer patterns in the list.
+ First NIL qualifier indicates the end in the list. */
+ if (empty_qualifier_sequence_p (qualifiers) == TRUE)
+ {
+ DEBUG_TRACE_IF (i == 0, "SUCCEED: empty qualifier list");
+ if (i)
+ found = 0;
+ break;
+ }
+
+ for (j = 0; j < num_opnds && j <= stop_at; ++j, ++qualifiers)
+ {
+ if (inst->operands[j].qualifier == AARCH64_OPND_QLF_NIL)
+ {
+ /* Either the operand does not have qualifier, or the qualifier
+ for the operand needs to be deduced from the qualifier
+ sequence.
+ In the latter case, any constraint checking related with
+ the obtained qualifier should be done later in
+ operand_general_constraint_met_p. */
+ continue;
+ }
+ else if (*qualifiers != inst->operands[j].qualifier)
+ {
+ /* Unless the target qualifier can also qualify the operand
+ (which has already had a non-nil qualifier), non-equal
+ qualifiers are generally un-matched. */
+ if (operand_also_qualified_p (inst->operands + j, *qualifiers))
+ continue;
+ else
+ {
+ found = 0;
+ break;
+ }
+ }
+ else
+ continue; /* Equal qualifiers are certainly matched. */
+ }
+
+ /* Qualifiers established. */
+ if (found == 1)
+ break;
+ }
+
+ if (found == 1)
+ {
+ /* Fill the result in *RET. */
+ int j;
+ qualifiers = *qualifiers_list;
+
+ DEBUG_TRACE ("complete qualifiers using list %d", i);
+#ifdef DEBUG_AARCH64
+ if (debug_dump)
+ dump_qualifier_sequence (qualifiers);
+#endif
+
+ for (j = 0; j <= stop_at; ++j, ++qualifiers)
+ ret[j] = *qualifiers;
+ for (; j < AARCH64_MAX_OPND_NUM; ++j)
+ ret[j] = AARCH64_OPND_QLF_NIL;
+
+ DEBUG_TRACE ("SUCCESS");
+ return 1;
+ }
+
+ DEBUG_TRACE ("FAIL");
+ return 0;
+}
+
+/* Operand qualifier matching and resolving.
+
+ Return 1 if the operand qualifier(s) in *INST match one of the qualifier
+ sequences in INST->OPCODE->qualifiers_list; otherwise return 0.
+
+ if UPDATE_P == TRUE, update the qualifier(s) in *INST after the matching
+ succeeds. */
+
+static int
+match_operands_qualifier (aarch64_inst *inst, bfd_boolean update_p)
+{
+ int i;
+ aarch64_opnd_qualifier_seq_t qualifiers;
+
+ if (!aarch64_find_best_match (inst, inst->opcode->qualifiers_list, -1,
+ qualifiers))
+ {
+ DEBUG_TRACE ("matching FAIL");
+ return 0;
+ }
+
+ /* Update the qualifiers. */
+ if (update_p == TRUE)
+ for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
+ {
+ if (inst->opcode->operands[i] == AARCH64_OPND_NIL)
+ break;
+ DEBUG_TRACE_IF (inst->operands[i].qualifier != qualifiers[i],
+ "update %s with %s for operand %d",
+ aarch64_get_qualifier_name (inst->operands[i].qualifier),
+ aarch64_get_qualifier_name (qualifiers[i]), i);
+ inst->operands[i].qualifier = qualifiers[i];
+ }
+
+ DEBUG_TRACE ("matching SUCCESS");
+ return 1;
+}
+
+/* Return TRUE if VALUE is a wide constant that can be moved into a general
+ register by MOVZ.
+
+ IS32 indicates whether value is a 32-bit immediate or not.
+ If SHIFT_AMOUNT is not NULL, on the return of TRUE, the logical left shift
+ amount will be returned in *SHIFT_AMOUNT. */
+
+bfd_boolean
+aarch64_wide_constant_p (int64_t value, int is32, unsigned int *shift_amount)
+{
+ int amount;
+
+ DEBUG_TRACE ("enter with 0x%" PRIx64 "(%" PRIi64 ")", value, value);
+
+ if (is32)
+ {
+ /* Allow all zeros or all ones in top 32-bits, so that
+ 32-bit constant expressions like ~0x80000000 are
+ permitted. */
+ uint64_t ext = value;
+ if (ext >> 32 != 0 && ext >> 32 != (uint64_t) 0xffffffff)
+ /* Immediate out of range. */
+ return FALSE;
+ value &= (int64_t) 0xffffffff;
+ }
+
+ /* first, try movz then movn */
+ amount = -1;
+ if ((value & ((int64_t) 0xffff << 0)) == value)
+ amount = 0;
+ else if ((value & ((int64_t) 0xffff << 16)) == value)
+ amount = 16;
+ else if (!is32 && (value & ((int64_t) 0xffff << 32)) == value)
+ amount = 32;
+ else if (!is32 && (value & ((int64_t) 0xffff << 48)) == value)
+ amount = 48;
+
+ if (amount == -1)
+ {
+ DEBUG_TRACE ("exit FALSE with 0x%" PRIx64 "(%" PRIi64 ")", value, value);
+ return FALSE;
+ }
+
+ if (shift_amount != NULL)
+ *shift_amount = amount;
+
+ DEBUG_TRACE ("exit TRUE with amount %d", amount);
+
+ return TRUE;
+}
+
+/* Build the accepted values for immediate logical SIMD instructions.
+
+ The standard encodings of the immediate value are:
+ N imms immr SIMD size R S
+ 1 ssssss rrrrrr 64 UInt(rrrrrr) UInt(ssssss)
+ 0 0sssss 0rrrrr 32 UInt(rrrrr) UInt(sssss)
+ 0 10ssss 00rrrr 16 UInt(rrrr) UInt(ssss)
+ 0 110sss 000rrr 8 UInt(rrr) UInt(sss)
+ 0 1110ss 0000rr 4 UInt(rr) UInt(ss)
+ 0 11110s 00000r 2 UInt(r) UInt(s)
+ where all-ones value of S is reserved.
+
+ Let's call E the SIMD size.
+
+ The immediate value is: S+1 bits '1' rotated to the right by R.
+
+ The total of valid encodings is 64*63 + 32*31 + ... + 2*1 = 5334
+ (remember S != E - 1). */
+
+#define TOTAL_IMM_NB 5334
+
+typedef struct
+{
+ uint64_t imm;
+ aarch64_insn encoding;
+} simd_imm_encoding;
+
+static simd_imm_encoding simd_immediates[TOTAL_IMM_NB];
+
+static int
+simd_imm_encoding_cmp(const void *i1, const void *i2)
+{
+ const simd_imm_encoding *imm1 = (const simd_imm_encoding *)i1;
+ const simd_imm_encoding *imm2 = (const simd_imm_encoding *)i2;
+
+ if (imm1->imm < imm2->imm)
+ return -1;
+ if (imm1->imm > imm2->imm)
+ return +1;
+ return 0;
+}
+
+/* immediate bitfield standard encoding
+ imm13<12> imm13<5:0> imm13<11:6> SIMD size R S
+ 1 ssssss rrrrrr 64 rrrrrr ssssss
+ 0 0sssss 0rrrrr 32 rrrrr sssss
+ 0 10ssss 00rrrr 16 rrrr ssss
+ 0 110sss 000rrr 8 rrr sss
+ 0 1110ss 0000rr 4 rr ss
+ 0 11110s 00000r 2 r s */
+static inline int
+encode_immediate_bitfield (int is64, uint32_t s, uint32_t r)
+{
+ return (is64 << 12) | (r << 6) | s;
+}
+
+static void
+build_immediate_table (void)
+{
+ uint32_t log_e, e, s, r, s_mask;
+ uint64_t mask, imm;
+ int nb_imms;
+ int is64;
+
+ nb_imms = 0;
+ for (log_e = 1; log_e <= 6; log_e++)
+ {
+ /* Get element size. */
+ e = 1u << log_e;
+ if (log_e == 6)
+ {
+ is64 = 1;
+ mask = 0xffffffffffffffffull;
+ s_mask = 0;
+ }
+ else
+ {
+ is64 = 0;
+ mask = (1ull << e) - 1;
+ /* log_e s_mask
+ 1 ((1 << 4) - 1) << 2 = 111100
+ 2 ((1 << 3) - 1) << 3 = 111000
+ 3 ((1 << 2) - 1) << 4 = 110000
+ 4 ((1 << 1) - 1) << 5 = 100000
+ 5 ((1 << 0) - 1) << 6 = 000000 */
+ s_mask = ((1u << (5 - log_e)) - 1) << (log_e + 1);
+ }
+ for (s = 0; s < e - 1; s++)
+ for (r = 0; r < e; r++)
+ {
+ /* s+1 consecutive bits to 1 (s < 63) */
+ imm = (1ull << (s + 1)) - 1;
+ /* rotate right by r */
+ if (r != 0)
+ imm = (imm >> r) | ((imm << (e - r)) & mask);
+ /* replicate the constant depending on SIMD size */
+ switch (log_e)
+ {
+ case 1: imm = (imm << 2) | imm;
+ case 2: imm = (imm << 4) | imm;
+ case 3: imm = (imm << 8) | imm;
+ case 4: imm = (imm << 16) | imm;
+ case 5: imm = (imm << 32) | imm;
+ case 6: break;
+ default: abort ();
+ }
+ simd_immediates[nb_imms].imm = imm;
+ simd_immediates[nb_imms].encoding =
+ encode_immediate_bitfield(is64, s | s_mask, r);
+ nb_imms++;
+ }
+ }
+ assert (nb_imms == TOTAL_IMM_NB);
+ qsort(simd_immediates, nb_imms,
+ sizeof(simd_immediates[0]), simd_imm_encoding_cmp);
+}
+
+/* Return TRUE if VALUE is a valid logical immediate, i.e. bitmask, that can
+ be accepted by logical (immediate) instructions
+ e.g. ORR <Xd|SP>, <Xn>, #<imm>.
+
+ IS32 indicates whether or not VALUE is a 32-bit immediate.
+ If ENCODING is not NULL, on the return of TRUE, the standard encoding for
+ VALUE will be returned in *ENCODING. */
+
+bfd_boolean
+aarch64_logical_immediate_p (uint64_t value, int is32, aarch64_insn *encoding)
+{
+ simd_imm_encoding imm_enc;
+ const simd_imm_encoding *imm_encoding;
+ static bfd_boolean initialized = FALSE;
+
+ DEBUG_TRACE ("enter with 0x%" PRIx64 "(%" PRIi64 "), is32: %d", value,
+ value, is32);
+
+ if (initialized == FALSE)
+ {
+ build_immediate_table ();
+ initialized = TRUE;
+ }
+
+ if (is32)
+ {
+ /* Allow all zeros or all ones in top 32-bits, so that
+ constant expressions like ~1 are permitted. */
+ if (value >> 32 != 0 && value >> 32 != 0xffffffff)
+ return 0xffffffff;
+ /* Replicate the 32 lower bits to the 32 upper bits. */
+ value &= 0xffffffff;
+ value |= value << 32;
+ }
+
+ imm_enc.imm = value;
+ imm_encoding = (const simd_imm_encoding *)
+ bsearch(&imm_enc, simd_immediates, TOTAL_IMM_NB,
+ sizeof(simd_immediates[0]), simd_imm_encoding_cmp);
+ if (imm_encoding == NULL)
+ {
+ DEBUG_TRACE ("exit with FALSE");
+ return FALSE;
+ }
+ if (encoding != NULL)
+ *encoding = imm_encoding->encoding;
+ DEBUG_TRACE ("exit with TRUE");
+ return TRUE;
+}
+
+/* If 64-bit immediate IMM is in the format of
+ "aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh",
+ where a, b, c, d, e, f, g and h are independently 0 or 1, return an integer
+ of value "abcdefgh". Otherwise return -1. */
+int
+aarch64_shrink_expanded_imm8 (uint64_t imm)
+{
+ int i, ret;
+ uint32_t byte;
+
+ ret = 0;
+ for (i = 0; i < 8; i++)
+ {
+ byte = (imm >> (8 * i)) & 0xff;
+ if (byte == 0xff)
+ ret |= 1 << i;
+ else if (byte != 0x00)
+ return -1;
+ }
+ return ret;
+}
+
+/* Utility inline functions for operand_general_constraint_met_p. */
+
+static inline void
+set_error (aarch64_operand_error *mismatch_detail,
+ enum aarch64_operand_error_kind kind, int idx,
+ const char* error)
+{
+ if (mismatch_detail == NULL)
+ return;
+ mismatch_detail->kind = kind;
+ mismatch_detail->index = idx;
+ mismatch_detail->error = error;
+}
+
+static inline void
+set_out_of_range_error (aarch64_operand_error *mismatch_detail,
+ int idx, int lower_bound, int upper_bound,
+ const char* error)
+{
+ if (mismatch_detail == NULL)
+ return;
+ set_error (mismatch_detail, AARCH64_OPDE_OUT_OF_RANGE, idx, error);
+ mismatch_detail->data[0] = lower_bound;
+ mismatch_detail->data[1] = upper_bound;
+}
+
+static inline void
+set_imm_out_of_range_error (aarch64_operand_error *mismatch_detail,
+ int idx, int lower_bound, int upper_bound)
+{
+ if (mismatch_detail == NULL)
+ return;
+ set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
+ _("immediate value"));
+}
+
+static inline void
+set_offset_out_of_range_error (aarch64_operand_error *mismatch_detail,
+ int idx, int lower_bound, int upper_bound)
+{
+ if (mismatch_detail == NULL)
+ return;
+ set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
+ _("immediate offset"));
+}
+
+static inline void
+set_regno_out_of_range_error (aarch64_operand_error *mismatch_detail,
+ int idx, int lower_bound, int upper_bound)
+{
+ if (mismatch_detail == NULL)
+ return;
+ set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
+ _("register number"));
+}
+
+static inline void
+set_elem_idx_out_of_range_error (aarch64_operand_error *mismatch_detail,
+ int idx, int lower_bound, int upper_bound)
+{
+ if (mismatch_detail == NULL)
+ return;
+ set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
+ _("register element index"));
+}
+
+static inline void
+set_sft_amount_out_of_range_error (aarch64_operand_error *mismatch_detail,
+ int idx, int lower_bound, int upper_bound)
+{
+ if (mismatch_detail == NULL)
+ return;
+ set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
+ _("shift amount"));
+}
+
+static inline void
+set_unaligned_error (aarch64_operand_error *mismatch_detail, int idx,
+ int alignment)
+{
+ if (mismatch_detail == NULL)
+ return;
+ set_error (mismatch_detail, AARCH64_OPDE_UNALIGNED, idx, NULL);
+ mismatch_detail->data[0] = alignment;
+}
+
+static inline void
+set_reg_list_error (aarch64_operand_error *mismatch_detail, int idx,
+ int expected_num)
+{
+ if (mismatch_detail == NULL)
+ return;
+ set_error (mismatch_detail, AARCH64_OPDE_REG_LIST, idx, NULL);
+ mismatch_detail->data[0] = expected_num;
+}
+
+static inline void
+set_other_error (aarch64_operand_error *mismatch_detail, int idx,
+ const char* error)
+{
+ if (mismatch_detail == NULL)
+ return;
+ set_error (mismatch_detail, AARCH64_OPDE_OTHER_ERROR, idx, error);
+}
+
+/* General constraint checking based on operand code.
+
+ Return 1 if OPNDS[IDX] meets the general constraint of operand code TYPE
+ as the IDXth operand of opcode OPCODE. Otherwise return 0.
+
+ This function has to be called after the qualifiers for all operands
+ have been resolved.
+
+ Mismatching error message is returned in *MISMATCH_DETAIL upon request,
+ i.e. when MISMATCH_DETAIL is non-NULL. This avoids the generation
+ of error message during the disassembling where error message is not
+ wanted. We avoid the dynamic construction of strings of error messages
+ here (i.e. in libopcodes), as it is costly and complicated; instead, we
+ use a combination of error code, static string and some integer data to
+ represent an error. */
+
+static int
+operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
+ enum aarch64_opnd type,
+ const aarch64_opcode *opcode,
+ aarch64_operand_error *mismatch_detail)
+{
+ unsigned num;
+ unsigned char size;
+ int64_t imm;
+ const aarch64_opnd_info *opnd = opnds + idx;
+ aarch64_opnd_qualifier_t qualifier = opnd->qualifier;
+
+ assert (opcode->operands[idx] == opnd->type && opnd->type == type);
+
+ switch (aarch64_operands[type].op_class)
+ {
+ case AARCH64_OPND_CLASS_INT_REG:
+ /* <Xt> may be optional in some IC and TLBI instructions. */
+ if (type == AARCH64_OPND_Rt_SYS)
+ {
+ assert (idx == 1 && (aarch64_get_operand_class (opnds[0].type)
+ == AARCH64_OPND_CLASS_SYSTEM));
+ if (opnds[1].present && !opnds[0].sysins_op->has_xt)
+ {
+ set_other_error (mismatch_detail, idx, _("extraneous register"));
+ return 0;
+ }
+ if (!opnds[1].present && opnds[0].sysins_op->has_xt)
+ {
+ set_other_error (mismatch_detail, idx, _("missing register"));
+ return 0;
+ }
+ }
+ switch (qualifier)
+ {
+ case AARCH64_OPND_QLF_WSP:
+ case AARCH64_OPND_QLF_SP:
+ if (!aarch64_stack_pointer_p (opnd))
+ {
+ set_other_error (mismatch_detail, idx,
+ _("stack pointer register expected"));
+ return 0;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case AARCH64_OPND_CLASS_ADDRESS:
+ /* Check writeback. */
+ switch (opcode->iclass)
+ {
+ case ldst_pos:
+ case ldst_unscaled:
+ case ldstnapair_offs:
+ case ldstpair_off:
+ case ldst_unpriv:
+ if (opnd->addr.writeback == 1)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("unexpected address writeback"));
+ return 0;
+ }
+ break;
+ case ldst_imm9:
+ case ldstpair_indexed:
+ case asisdlsep:
+ case asisdlsop:
+ if (opnd->addr.writeback == 0)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("address writeback expected"));
+ return 0;
+ }
+ break;
+ default:
+ assert (opnd->addr.writeback == 0);
+ break;
+ }
+ switch (type)
+ {
+ case AARCH64_OPND_ADDR_SIMM7:
+ /* Scaled signed 7 bits immediate offset. */
+ /* Get the size of the data element that is accessed, which may be
+ different from that of the source register size,
+ e.g. in strb/ldrb. */
+ size = aarch64_get_qualifier_esize (opnd->qualifier);
+ if (!value_in_range_p (opnd->addr.offset.imm, -64 * size, 63 * size))
+ {
+ set_offset_out_of_range_error (mismatch_detail, idx,
+ -64 * size, 63 * size);
+ return 0;
+ }
+ if (!value_aligned_p (opnd->addr.offset.imm, size))
+ {
+ set_unaligned_error (mismatch_detail, idx, size);
+ return 0;
+ }
+ break;
+ case AARCH64_OPND_ADDR_SIMM9:
+ /* Unscaled signed 9 bits immediate offset. */
+ if (!value_in_range_p (opnd->addr.offset.imm, -256, 255))
+ {
+ set_offset_out_of_range_error (mismatch_detail, idx, -256, 255);
+ return 0;
+ }
+ break;
+
+ case AARCH64_OPND_ADDR_SIMM9_2:
+ /* Unscaled signed 9 bits immediate offset, which has to be negative
+ or unaligned. */
+ size = aarch64_get_qualifier_esize (qualifier);
+ if ((value_in_range_p (opnd->addr.offset.imm, 0, 255)
+ && !value_aligned_p (opnd->addr.offset.imm, size))
+ || value_in_range_p (opnd->addr.offset.imm, -256, -1))
+ return 1;
+ set_other_error (mismatch_detail, idx,
+ _("negative or unaligned offset expected"));
+ return 0;
+
+ case AARCH64_OPND_SIMD_ADDR_POST:
+ /* AdvSIMD load/store multiple structures, post-index. */
+ assert (idx == 1);
+ if (opnd->addr.offset.is_reg)
+ {
+ if (value_in_range_p (opnd->addr.offset.regno, 0, 30))
+ return 1;
+ else
+ {
+ set_other_error (mismatch_detail, idx,
+ _("invalid register offset"));
+ return 0;
+ }
+ }
+ else
+ {
+ const aarch64_opnd_info *prev = &opnds[idx-1];
+ unsigned num_bytes; /* total number of bytes transferred. */
+ /* The opcode dependent area stores the number of elements in
+ each structure to be loaded/stored. */
+ int is_ld1r = get_opcode_dependent_value (opcode) == 1;
+ if (opcode->operands[0] == AARCH64_OPND_LVt_AL)
+ /* Special handling of loading single structure to all lane. */
+ num_bytes = (is_ld1r ? 1 : prev->reglist.num_regs)
+ * aarch64_get_qualifier_esize (prev->qualifier);
+ else
+ num_bytes = prev->reglist.num_regs
+ * aarch64_get_qualifier_esize (prev->qualifier)
+ * aarch64_get_qualifier_nelem (prev->qualifier);
+ if ((int) num_bytes != opnd->addr.offset.imm)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("invalid post-increment amount"));
+ return 0;
+ }
+ }
+ break;
+
+ case AARCH64_OPND_ADDR_REGOFF:
+ /* Get the size of the data element that is accessed, which may be
+ different from that of the source register size,
+ e.g. in strb/ldrb. */
+ size = aarch64_get_qualifier_esize (opnd->qualifier);
+ /* It is either no shift or shift by the binary logarithm of SIZE. */
+ if (opnd->shifter.amount != 0
+ && opnd->shifter.amount != (int)get_logsz (size))
+ {
+ set_other_error (mismatch_detail, idx,
+ _("invalid shift amount"));
+ return 0;
+ }
+ /* Only UXTW, LSL, SXTW and SXTX are the accepted extending
+ operators. */
+ switch (opnd->shifter.kind)
+ {
+ case AARCH64_MOD_UXTW:
+ case AARCH64_MOD_LSL:
+ case AARCH64_MOD_SXTW:
+ case AARCH64_MOD_SXTX: break;
+ default:
+ set_other_error (mismatch_detail, idx,
+ _("invalid extend/shift operator"));
+ return 0;
+ }
+ break;
+
+ case AARCH64_OPND_ADDR_UIMM12:
+ imm = opnd->addr.offset.imm;
+ /* Get the size of the data element that is accessed, which may be
+ different from that of the source register size,
+ e.g. in strb/ldrb. */
+ size = aarch64_get_qualifier_esize (qualifier);
+ if (!value_in_range_p (opnd->addr.offset.imm, 0, 4095 * size))
+ {
+ set_offset_out_of_range_error (mismatch_detail, idx,
+ 0, 4095 * size);
+ return 0;
+ }
+ if (!value_aligned_p (opnd->shifter.amount, size))
+ {
+ set_unaligned_error (mismatch_detail, idx, size);
+ return 0;
+ }
+ break;
+
+ case AARCH64_OPND_ADDR_PCREL14:
+ case AARCH64_OPND_ADDR_PCREL19:
+ case AARCH64_OPND_ADDR_PCREL21:
+ case AARCH64_OPND_ADDR_PCREL26:
+ imm = opnd->imm.value;
+ if (operand_need_shift_by_two (get_operand_from_code (type)))
+ {
+ /* The offset value in a PC-relative branch instruction is alway
+ 4-byte aligned and is encoded without the lowest 2 bits. */
+ if (!value_aligned_p (imm, 4))
+ {
+ set_unaligned_error (mismatch_detail, idx, 4);
+ return 0;
+ }
+ /* Right shift by 2 so that we can carry out the following check
+ canonically. */
+ imm >>= 2;
+ }
+ size = get_operand_fields_width (get_operand_from_code (type));
+ if (!value_fit_signed_field_p (imm, size))
+ {
+ set_other_error (mismatch_detail, idx,
+ _("immediate out of range"));
+ return 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case AARCH64_OPND_CLASS_SIMD_REGLIST:
+ /* The opcode dependent area stores the number of elements in
+ each structure to be loaded/stored. */
+ num = get_opcode_dependent_value (opcode);
+ switch (type)
+ {
+ case AARCH64_OPND_LVt:
+ assert (num >= 1 && num <= 4);
+ /* Unless LD1/ST1, the number of registers should be equal to that
+ of the structure elements. */
+ if (num != 1 && opnd->reglist.num_regs != num)
+ {
+ set_reg_list_error (mismatch_detail, idx, num);
+ return 0;
+ }
+ break;
+ case AARCH64_OPND_LVt_AL:
+ case AARCH64_OPND_LEt:
+ assert (num >= 1 && num <= 4);
+ /* The number of registers should be equal to that of the structure
+ elements. */
+ if (opnd->reglist.num_regs != num)
+ {
+ set_reg_list_error (mismatch_detail, idx, num);
+ return 0;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case AARCH64_OPND_CLASS_IMMEDIATE:
+ /* Constraint check on immediate operand. */
+ imm = opnd->imm.value;
+ /* E.g. imm_0_31 constrains value to be 0..31. */
+ if (qualifier_value_in_range_constraint_p (qualifier)
+ && !value_in_range_p (imm, get_lower_bound (qualifier),
+ get_upper_bound (qualifier)))
+ {
+ set_imm_out_of_range_error (mismatch_detail, idx,
+ get_lower_bound (qualifier),
+ get_upper_bound (qualifier));
+ return 0;
+ }
+
+ switch (type)
+ {
+ case AARCH64_OPND_AIMM:
+ if (opnd->shifter.kind != AARCH64_MOD_LSL)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("invalid shift operator"));
+ return 0;
+ }
+ if (opnd->shifter.amount != 0 && opnd->shifter.amount != 12)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("shift amount expected to be 0 or 12"));
+ return 0;
+ }
+ if (!value_fit_unsigned_field_p (opnd->imm.value, 12))
+ {
+ set_other_error (mismatch_detail, idx,
+ _("immediate out of range"));
+ return 0;
+ }
+ break;
+
+ case AARCH64_OPND_HALF:
+ assert (idx == 1 && opnds[0].type == AARCH64_OPND_Rd);
+ if (opnd->shifter.kind != AARCH64_MOD_LSL)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("invalid shift operator"));
+ return 0;
+ }
+ size = aarch64_get_qualifier_esize (opnds[0].qualifier);
+ if (!value_aligned_p (opnd->shifter.amount, 16))
+ {
+ set_other_error (mismatch_detail, idx,
+ _("shift amount should be a multiple of 16"));
+ return 0;
+ }
+ if (!value_in_range_p (opnd->shifter.amount, 0, size * 8 - 16))
+ {
+ set_sft_amount_out_of_range_error (mismatch_detail, idx,
+ 0, size * 8 - 16);
+ return 0;
+ }
+ if (opnd->imm.value < 0)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("negative immediate value not allowed"));
+ return 0;
+ }
+ if (!value_fit_unsigned_field_p (opnd->imm.value, 16))
+ {
+ set_other_error (mismatch_detail, idx,
+ _("immediate out of range"));
+ return 0;
+ }
+ break;
+
+ case AARCH64_OPND_IMM_MOV:
+ {
+ int is32 = aarch64_get_qualifier_esize (opnds[0].qualifier) == 4;
+ imm = opnd->imm.value;
+ assert (idx == 1);
+ switch (opcode->op)
+ {
+ case OP_MOV_IMM_WIDEN:
+ imm = ~imm;
+ /* Fall through... */
+ case OP_MOV_IMM_WIDE:
+ if (!aarch64_wide_constant_p (imm, is32, NULL))
+ {
+ set_other_error (mismatch_detail, idx,
+ _("immediate out of range"));
+ return 0;
+ }
+ break;
+ case OP_MOV_IMM_LOG:
+ if (!aarch64_logical_immediate_p (imm, is32, NULL))
+ {
+ set_other_error (mismatch_detail, idx,
+ _("immediate out of range"));
+ return 0;
+ }
+ break;
+ default:
+ assert (0);
+ return 0;
+ }
+ }
+ break;
+
+ case AARCH64_OPND_NZCV:
+ case AARCH64_OPND_CCMP_IMM:
+ case AARCH64_OPND_EXCEPTION:
+ case AARCH64_OPND_UIMM4:
+ case AARCH64_OPND_UIMM7:
+ case AARCH64_OPND_UIMM3_OP1:
+ case AARCH64_OPND_UIMM3_OP2:
+ size = get_operand_fields_width (get_operand_from_code (type));
+ assert (size < 32);
+ if (!value_fit_unsigned_field_p (opnd->imm.value, size))
+ {
+ set_imm_out_of_range_error (mismatch_detail, idx, 0,
+ (1 << size) - 1);
+ return 0;
+ }
+ break;
+
+ case AARCH64_OPND_WIDTH:
+ assert (idx == 3 && opnds[idx-1].type == AARCH64_OPND_IMM
+ && opnds[0].type == AARCH64_OPND_Rd);
+ size = get_upper_bound (qualifier);
+ if (opnd->imm.value + opnds[idx-1].imm.value > size)
+ /* lsb+width <= reg.size */
+ {
+ set_imm_out_of_range_error (mismatch_detail, idx, 1,
+ size - opnds[idx-1].imm.value);
+ return 0;
+ }
+ break;
+
+ case AARCH64_OPND_LIMM:
+ {
+ int is32 = opnds[0].qualifier == AARCH64_OPND_QLF_W;
+ uint64_t uimm = opnd->imm.value;
+ if (opcode->op == OP_BIC)
+ uimm = ~uimm;
+ if (aarch64_logical_immediate_p (uimm, is32, NULL) == FALSE)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("immediate out of range"));
+ return 0;
+ }
+ }
+ break;
+
+ case AARCH64_OPND_IMM0:
+ case AARCH64_OPND_FPIMM0:
+ if (opnd->imm.value != 0)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("immediate zero expected"));
+ return 0;
+ }
+ break;
+
+ case AARCH64_OPND_SHLL_IMM:
+ assert (idx == 2);
+ size = 8 * aarch64_get_qualifier_esize (opnds[idx - 1].qualifier);
+ if (opnd->imm.value != size)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("invalid shift amount"));
+ return 0;
+ }
+ break;
+
+ case AARCH64_OPND_IMM_VLSL:
+ size = aarch64_get_qualifier_esize (qualifier);
+ if (!value_in_range_p (opnd->imm.value, 0, size * 8 - 1))
+ {
+ set_imm_out_of_range_error (mismatch_detail, idx, 0,
+ size * 8 - 1);
+ return 0;
+ }
+ break;
+
+ case AARCH64_OPND_IMM_VLSR:
+ size = aarch64_get_qualifier_esize (qualifier);
+ if (!value_in_range_p (opnd->imm.value, 1, size * 8))
+ {
+ set_imm_out_of_range_error (mismatch_detail, idx, 1, size * 8);
+ return 0;
+ }
+ break;
+
+ case AARCH64_OPND_SIMD_IMM:
+ case AARCH64_OPND_SIMD_IMM_SFT:
+ /* Qualifier check. */
+ switch (qualifier)
+ {
+ case AARCH64_OPND_QLF_LSL:
+ if (opnd->shifter.kind != AARCH64_MOD_LSL)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("invalid shift operator"));
+ return 0;
+ }
+ break;
+ case AARCH64_OPND_QLF_MSL:
+ if (opnd->shifter.kind != AARCH64_MOD_MSL)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("invalid shift operator"));
+ return 0;
+ }
+ break;
+ case AARCH64_OPND_QLF_NIL:
+ if (opnd->shifter.kind != AARCH64_MOD_NONE)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("shift is not permitted"));
+ return 0;
+ }
+ break;
+ default:
+ assert (0);
+ return 0;
+ }
+ /* Is the immediate valid? */
+ assert (idx == 1);
+ if (aarch64_get_qualifier_esize (opnds[0].qualifier) != 8)
+ {
+ /* uimm8 */
+ if (!value_in_range_p (opnd->imm.value, 0, 255))
+ {
+ set_imm_out_of_range_error (mismatch_detail, idx, 0, 255);
+ return 0;
+ }
+ }
+ else if (aarch64_shrink_expanded_imm8 (opnd->imm.value) < 0)
+ {
+ /* uimm64 is not
+ 'aaaaaaaabbbbbbbbccccccccddddddddeeeeeeee
+ ffffffffgggggggghhhhhhhh'. */
+ set_other_error (mismatch_detail, idx,
+ _("invalid value for immediate"));
+ return 0;
+ }
+ /* Is the shift amount valid? */
+ switch (opnd->shifter.kind)
+ {
+ case AARCH64_MOD_LSL:
+ size = aarch64_get_qualifier_esize (opnds[0].qualifier);
+ if (!value_aligned_p (opnd->shifter.amount, 8))
+ {
+ set_unaligned_error (mismatch_detail, idx, 8);
+ return 0;
+ }
+ if (!value_in_range_p (opnd->shifter.amount, 0, (size - 1) * 8))
+ {
+ set_imm_out_of_range_error (mismatch_detail, idx, 0,
+ (size - 1) * 8);
+ return 0;
+ }
+ break;
+ case AARCH64_MOD_MSL:
+ /* Only 8 and 16 are valid shift amount. */
+ if (opnd->shifter.amount != 8 && opnd->shifter.amount != 16)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("shift amount expected to be 0 or 16"));
+ return 0;
+ }
+ break;
+ default:
+ if (opnd->shifter.kind != AARCH64_MOD_NONE)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("invalid shift operator"));
+ return 0;
+ }
+ break;
+ }
+ break;
+
+ case AARCH64_OPND_FPIMM:
+ case AARCH64_OPND_SIMD_FPIMM:
+ if (opnd->imm.is_fp == 0)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("floating-point immediate expected"));
+ return 0;
+ }
+ /* The value is expected to be an 8-bit floating-point constant with
+ sign, 3-bit exponent and normalized 4 bits of precision, encoded
+ in "a:b:c:d:e:f:g:h" or FLD_imm8 (depending on the type of the
+ instruction). */
+ if (!value_in_range_p (opnd->imm.value, 0, 255))
+ {
+ set_other_error (mismatch_detail, idx,
+ _("immediate out of range"));
+ return 0;
+ }
+ if (opnd->shifter.kind != AARCH64_MOD_NONE)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("invalid shift operator"));
+ return 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case AARCH64_OPND_CLASS_CP_REG:
+ /* Cn or Cm: 4-bit opcode field named for historical reasons.
+ valid range: C0 - C15. */
+ if (opnd->reg.regno > 15)
+ {
+ set_regno_out_of_range_error (mismatch_detail, idx, 0, 15);
+ return 0;
+ }
+ break;
+
+ case AARCH64_OPND_CLASS_SYSTEM:
+ switch (type)
+ {
+ case AARCH64_OPND_PSTATEFIELD:
+ assert (idx == 0 && opnds[1].type == AARCH64_OPND_UIMM4);
+ /* MSR SPSel, #uimm4
+ Uses uimm4 as a control value to select the stack pointer: if
+ bit 0 is set it selects the current exception level's stack
+ pointer, if bit 0 is clear it selects shared EL0 stack pointer.
+ Bits 1 to 3 of uimm4 are reserved and should be zero. */
+ if (opnd->pstatefield == 0x05 /* spsel */ && opnds[1].imm.value > 1)
+ {
+ set_imm_out_of_range_error (mismatch_detail, idx, 0, 1);
+ return 0;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case AARCH64_OPND_CLASS_SIMD_ELEMENT:
+ /* Get the upper bound for the element index. */
+ num = 16 / aarch64_get_qualifier_esize (qualifier) - 1;
+ /* Index out-of-range. */
+ if (!value_in_range_p (opnd->reglane.index, 0, num))
+ {
+ set_elem_idx_out_of_range_error (mismatch_detail, idx, 0, num);
+ return 0;
+ }
+ /* SMLAL<Q> <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Ts>[<index>].
+ <Vm> Is the vector register (V0-V31) or (V0-V15), whose
+ number is encoded in "size:M:Rm":
+ size <Vm>
+ 00 RESERVED
+ 01 0:Rm
+ 10 M:Rm
+ 11 RESERVED */
+ if (type == AARCH64_OPND_Em && qualifier == AARCH64_OPND_QLF_S_H
+ && !value_in_range_p (opnd->reglane.regno, 0, 15))
+ {
+ set_regno_out_of_range_error (mismatch_detail, idx, 0, 15);
+ return 0;
+ }
+ break;
+
+ case AARCH64_OPND_CLASS_MODIFIED_REG:
+ assert (idx == 1 || idx == 2);
+ switch (type)
+ {
+ case AARCH64_OPND_Rm_EXT:
+ if (aarch64_extend_operator_p (opnd->shifter.kind) == FALSE
+ && opnd->shifter.kind != AARCH64_MOD_LSL)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("extend operator expected"));
+ return 0;
+ }
+ /* It is not optional unless at least one of "Rd" or "Rn" is '11111'
+ (i.e. SP), in which case it defaults to LSL. The LSL alias is
+ only valid when "Rd" or "Rn" is '11111', and is preferred in that
+ case. */
+ if (!aarch64_stack_pointer_p (opnds + 0)
+ && (idx != 2 || !aarch64_stack_pointer_p (opnds + 1)))
+ {
+ if (!opnd->shifter.operator_present)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("missing extend operator"));
+ return 0;
+ }
+ else if (opnd->shifter.kind == AARCH64_MOD_LSL)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("'LSL' operator not allowed"));
+ return 0;
+ }
+ }
+ assert (opnd->shifter.operator_present /* Default to LSL. */
+ || opnd->shifter.kind == AARCH64_MOD_LSL);
+ if (!value_in_range_p (opnd->shifter.amount, 0, 4))
+ {
+ set_sft_amount_out_of_range_error (mismatch_detail, idx, 0, 4);
+ return 0;
+ }
+ /* In the 64-bit form, the final register operand is written as Wm
+ for all but the (possibly omitted) UXTX/LSL and SXTX
+ operators.
+ N.B. GAS allows X register to be used with any operator as a
+ programming convenience. */
+ if (qualifier == AARCH64_OPND_QLF_X
+ && opnd->shifter.kind != AARCH64_MOD_LSL
+ && opnd->shifter.kind != AARCH64_MOD_UXTX
+ && opnd->shifter.kind != AARCH64_MOD_SXTX)
+ {
+ set_other_error (mismatch_detail, idx, _("W register expected"));
+ return 0;
+ }
+ break;
+
+ case AARCH64_OPND_Rm_SFT:
+ /* ROR is not available to the shifted register operand in
+ arithmetic instructions. */
+ if (aarch64_shift_operator_p (opnd->shifter.kind) == FALSE)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("shift operator expected"));
+ return 0;
+ }
+ if (opnd->shifter.kind == AARCH64_MOD_ROR
+ && opcode->iclass != log_shift)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("'ROR' operator not allowed"));
+ return 0;
+ }
+ num = qualifier == AARCH64_OPND_QLF_W ? 31 : 63;
+ if (!value_in_range_p (opnd->shifter.amount, 0, num))
+ {
+ set_sft_amount_out_of_range_error (mismatch_detail, idx, 0, num);
+ return 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 1;
+}
+
+/* Main entrypoint for the operand constraint checking.
+
+ Return 1 if operands of *INST meet the constraint applied by the operand
+ codes and operand qualifiers; otherwise return 0 and if MISMATCH_DETAIL is
+ not NULL, return the detail of the error in *MISMATCH_DETAIL. N.B. when
+ adding more constraint checking, make sure MISMATCH_DETAIL->KIND is set
+ with a proper error kind rather than AARCH64_OPDE_NIL (GAS asserts non-NIL
+ error kind when it is notified that an instruction does not pass the check).
+
+ Un-determined operand qualifiers may get established during the process. */
+
+int
+aarch64_match_operands_constraint (aarch64_inst *inst,
+ aarch64_operand_error *mismatch_detail)
+{
+ int i;
+
+ DEBUG_TRACE ("enter");
+
+ /* Match operands' qualifier.
+ *INST has already had qualifier establish for some, if not all, of
+ its operands; we need to find out whether these established
+ qualifiers match one of the qualifier sequence in
+ INST->OPCODE->QUALIFIERS_LIST. If yes, we will assign each operand
+ with the corresponding qualifier in such a sequence.
+ Only basic operand constraint checking is done here; the more thorough
+ constraint checking will carried out by operand_general_constraint_met_p,
+ which has be to called after this in order to get all of the operands'
+ qualifiers established. */
+ if (match_operands_qualifier (inst, TRUE /* update_p */) == 0)
+ {
+ DEBUG_TRACE ("FAIL on operand qualifier matching");
+ if (mismatch_detail)
+ {
+ /* Return an error type to indicate that it is the qualifier
+ matching failure; we don't care about which operand as there
+ are enough information in the opcode table to reproduce it. */
+ mismatch_detail->kind = AARCH64_OPDE_INVALID_VARIANT;
+ mismatch_detail->index = -1;
+ mismatch_detail->error = NULL;
+ }
+ return 0;
+ }
+
+ /* Match operands' constraint. */
+ for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
+ {
+ enum aarch64_opnd type = inst->opcode->operands[i];
+ if (type == AARCH64_OPND_NIL)
+ break;
+ if (inst->operands[i].skip)
+ {
+ DEBUG_TRACE ("skip the incomplete operand %d", i);
+ continue;
+ }
+ if (operand_general_constraint_met_p (inst->operands, i, type,
+ inst->opcode, mismatch_detail) == 0)
+ {
+ DEBUG_TRACE ("FAIL on operand %d", i);
+ return 0;
+ }
+ }
+
+ DEBUG_TRACE ("PASS");
+
+ return 1;
+}
+
+/* Replace INST->OPCODE with OPCODE and return the replaced OPCODE.
+ Also updates the TYPE of each INST->OPERANDS with the corresponding
+ value of OPCODE->OPERANDS.
+
+ Note that some operand qualifiers may need to be manually cleared by
+ the caller before it further calls the aarch64_opcode_encode; by
+ doing this, it helps the qualifier matching facilities work
+ properly. */
+
+const aarch64_opcode*
+aarch64_replace_opcode (aarch64_inst *inst, const aarch64_opcode *opcode)
+{
+ int i;
+ const aarch64_opcode *old = inst->opcode;
+
+ inst->opcode = opcode;
+
+ /* Update the operand types. */
+ for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
+ {
+ inst->operands[i].type = opcode->operands[i];
+ if (opcode->operands[i] == AARCH64_OPND_NIL)
+ break;
+ }
+
+ DEBUG_TRACE ("replace %s with %s", old->name, opcode->name);
+
+ return old;
+}
+
+int
+aarch64_operand_index (const enum aarch64_opnd *operands, enum aarch64_opnd operand)
+{
+ int i;
+ for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
+ if (operands[i] == operand)
+ return i;
+ else if (operands[i] == AARCH64_OPND_NIL)
+ break;
+ return -1;
+}
+
+/* [0][0] 32-bit integer regs with sp Wn
+ [0][1] 64-bit integer regs with sp Xn sf=1
+ [1][0] 32-bit integer regs with #0 Wn
+ [1][1] 64-bit integer regs with #0 Xn sf=1 */
+static const char *int_reg[2][2][32] = {
+#define R32 "w"
+#define R64 "x"
+ { { R32 "0", R32 "1", R32 "2", R32 "3", R32 "4", R32 "5", R32 "6", R32 "7",
+ R32 "8", R32 "9", R32 "10", R32 "11", R32 "12", R32 "13", R32 "14", R32 "15",
+ R32 "16", R32 "17", R32 "18", R32 "19", R32 "20", R32 "21", R32 "22", R32 "23",
+ R32 "24", R32 "25", R32 "26", R32 "27", R32 "28", R32 "29", R32 "30", "wsp" },
+ { R64 "0", R64 "1", R64 "2", R64 "3", R64 "4", R64 "5", R64 "6", R64 "7",
+ R64 "8", R64 "9", R64 "10", R64 "11", R64 "12", R64 "13", R64 "14", R64 "15",
+ R64 "16", R64 "17", R64 "18", R64 "19", R64 "20", R64 "21", R64 "22", R64 "23",
+ R64 "24", R64 "25", R64 "26", R64 "27", R64 "28", R64 "29", R64 "30", "sp" } },
+ { { R32 "0", R32 "1", R32 "2", R32 "3", R32 "4", R32 "5", R32 "6", R32 "7",
+ R32 "8", R32 "9", R32 "10", R32 "11", R32 "12", R32 "13", R32 "14", R32 "15",
+ R32 "16", R32 "17", R32 "18", R32 "19", R32 "20", R32 "21", R32 "22", R32 "23",
+ R32 "24", R32 "25", R32 "26", R32 "27", R32 "28", R32 "29", R32 "30", R32 "zr" },
+ { R64 "0", R64 "1", R64 "2", R64 "3", R64 "4", R64 "5", R64 "6", R64 "7",
+ R64 "8", R64 "9", R64 "10", R64 "11", R64 "12", R64 "13", R64 "14", R64 "15",
+ R64 "16", R64 "17", R64 "18", R64 "19", R64 "20", R64 "21", R64 "22", R64 "23",
+ R64 "24", R64 "25", R64 "26", R64 "27", R64 "28", R64 "29", R64 "30", R64 "zr" } }
+#undef R64
+#undef R32
+};
+
+/* Return the integer register name.
+ if SP_REG_P is not 0, R31 is an SP reg, other R31 is the zero reg. */
+
+static inline const char *
+get_int_reg_name (int regno, aarch64_opnd_qualifier_t qualifier, int sp_reg_p)
+{
+ const int has_zr = sp_reg_p ? 0 : 1;
+ const int is_64 = aarch64_get_qualifier_esize (qualifier) == 4 ? 0 : 1;
+ return int_reg[has_zr][is_64][regno];
+}
+
+/* Like get_int_reg_name, but IS_64 is always 1. */
+
+static inline const char *
+get_64bit_int_reg_name (int regno, int sp_reg_p)
+{
+ const int has_zr = sp_reg_p ? 0 : 1;
+ return int_reg[has_zr][1][regno];
+}
+
+/* Types for expanding an encoded 8-bit value to a floating-point value. */
+
+typedef union
+{
+ uint64_t i;
+ double d;
+} double_conv_t;
+
+typedef union
+{
+ uint32_t i;
+ float f;
+} single_conv_t;
+
+/* IMM8 is an 8-bit floating-point constant with sign, 3-bit exponent and
+ normalized 4 bits of precision, encoded in "a:b:c:d:e:f:g:h" or FLD_imm8
+ (depending on the type of the instruction). IMM8 will be expanded to a
+ single-precision floating-point value (IS_DP == 0) or a double-precision
+ floating-point value (IS_DP == 1). The expanded value is returned. */
+
+static uint64_t
+expand_fp_imm (int is_dp, uint32_t imm8)
+{
+ uint64_t imm;
+ uint32_t imm8_7, imm8_6_0, imm8_6, imm8_6_repl4;
+
+ imm8_7 = (imm8 >> 7) & 0x01; /* imm8<7> */
+ imm8_6_0 = imm8 & 0x7f; /* imm8<6:0> */
+ imm8_6 = imm8_6_0 >> 6; /* imm8<6> */
+ imm8_6_repl4 = (imm8_6 << 3) | (imm8_6 << 2)
+ | (imm8_6 << 1) | imm8_6; /* Replicate(imm8<6>,4) */
+ if (is_dp)
+ {
+ imm = (imm8_7 << (63-32)) /* imm8<7> */
+ | ((imm8_6 ^ 1) << (62-32)) /* NOT(imm8<6) */
+ | (imm8_6_repl4 << (58-32)) | (imm8_6 << (57-32))
+ | (imm8_6 << (56-32)) | (imm8_6 << (55-32)) /* Replicate(imm8<6>,7) */
+ | (imm8_6_0 << (48-32)); /* imm8<6>:imm8<5:0> */
+ imm <<= 32;
+ }
+ else
+ {
+ imm = (imm8_7 << 31) /* imm8<7> */
+ | ((imm8_6 ^ 1) << 30) /* NOT(imm8<6>) */
+ | (imm8_6_repl4 << 26) /* Replicate(imm8<6>,4) */
+ | (imm8_6_0 << 19); /* imm8<6>:imm8<5:0> */
+ }
+
+ return imm;
+}
+
+/* Produce the string representation of the register list operand *OPND
+ in the buffer pointed by BUF of size SIZE. */
+static void
+print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd)
+{
+ const int num_regs = opnd->reglist.num_regs;
+ const int first_reg = opnd->reglist.first_regno;
+ const int last_reg = (first_reg + num_regs - 1) & 0x1f;
+ const char *qlf_name = aarch64_get_qualifier_name (opnd->qualifier);
+ char tb[8]; /* Temporary buffer. */
+
+ assert (opnd->type != AARCH64_OPND_LEt || opnd->reglist.has_index);
+ assert (num_regs >= 1 && num_regs <= 4);
+
+ /* Prepare the index if any. */
+ if (opnd->reglist.has_index)
+ snprintf (tb, 8, "[%d]", opnd->reglist.index);
+ else
+ tb[0] = '\0';
+
+ /* The hyphenated form is preferred for disassembly if there are
+ more than two registers in the list, and the register numbers
+ are monotonically increasing in increments of one. */
+ if (num_regs > 2 && last_reg > first_reg)
+ snprintf (buf, size, "{v%d.%s-v%d.%s}%s", first_reg, qlf_name,
+ last_reg, qlf_name, tb);
+ else
+ {
+ const int reg0 = first_reg;
+ const int reg1 = (first_reg + 1) & 0x1f;
+ const int reg2 = (first_reg + 2) & 0x1f;
+ const int reg3 = (first_reg + 3) & 0x1f;
+
+ switch (num_regs)
+ {
+ case 1:
+ snprintf (buf, size, "{v%d.%s}%s", reg0, qlf_name, tb);
+ break;
+ case 2:
+ snprintf (buf, size, "{v%d.%s, v%d.%s}%s", reg0, qlf_name,
+ reg1, qlf_name, tb);
+ break;
+ case 3:
+ snprintf (buf, size, "{v%d.%s, v%d.%s, v%d.%s}%s", reg0, qlf_name,
+ reg1, qlf_name, reg2, qlf_name, tb);
+ break;
+ case 4:
+ snprintf (buf, size, "{v%d.%s, v%d.%s, v%d.%s, v%d.%s}%s",
+ reg0, qlf_name, reg1, qlf_name, reg2, qlf_name,
+ reg3, qlf_name, tb);
+ break;
+ }
+ }
+}
+
+/* Produce the string representation of the register offset address operand
+ *OPND in the buffer pointed by BUF of size SIZE. */
+static void
+print_register_offset_address (char *buf, size_t size,
+ const aarch64_opnd_info *opnd)
+{
+ const size_t tblen = 16;
+ char tb[tblen]; /* Temporary buffer. */
+ bfd_boolean lsl_p = FALSE; /* Is LSL shift operator? */
+ bfd_boolean wm_p = FALSE; /* Should Rm be Wm? */
+ bfd_boolean print_extend_p = TRUE;
+ bfd_boolean print_amount_p = TRUE;
+ const char *shift_name = aarch64_operand_modifiers[opnd->shifter.kind].name;
+
+ switch (opnd->shifter.kind)
+ {
+ case AARCH64_MOD_UXTW: wm_p = TRUE; break;
+ case AARCH64_MOD_LSL : lsl_p = TRUE; break;
+ case AARCH64_MOD_SXTW: wm_p = TRUE; break;
+ case AARCH64_MOD_SXTX: break;
+ default: assert (0);
+ }
+
+ if (!opnd->shifter.amount && (opnd->qualifier != AARCH64_OPND_QLF_S_B
+ || !opnd->shifter.amount_present))
+ {
+ /* Not print the shift/extend amount when the amount is zero and
+ when it is not the special case of 8-bit load/store instruction. */
+ print_amount_p = FALSE;
+ /* Likewise, no need to print the shift operator LSL in such a
+ situation. */
+ if (lsl_p)
+ print_extend_p = FALSE;
+ }
+
+ /* Prepare for the extend/shift. */
+ if (print_extend_p)
+ {
+ if (print_amount_p)
+ snprintf (tb, tblen, ",%s #%d", shift_name, opnd->shifter.amount);
+ else
+ snprintf (tb, tblen, ",%s", shift_name);
+ }
+ else
+ tb[0] = '\0';
+
+ snprintf (buf, size, "[%s,%c%d%s]",
+ get_64bit_int_reg_name (opnd->addr.base_regno, 1),
+ wm_p ? 'w' : 'x', opnd->addr.offset.regno, tb);
+}
+
+/* Generate the string representation of the operand OPNDS[IDX] for OPCODE
+ in *BUF. The caller should pass in the maximum size of *BUF in SIZE.
+ PC, PCREL_P and ADDRESS are used to pass in and return information about
+ the PC-relative address calculation, where the PC value is passed in
+ PC. If the operand is pc-relative related, *PCREL_P (if PCREL_P non-NULL)
+ will return 1 and *ADDRESS (if ADDRESS non-NULL) will return the
+ calculated address; otherwise, *PCREL_P (if PCREL_P non-NULL) returns 0.
+
+ The function serves both the disassembler and the assembler diagnostics
+ issuer, which is the reason why it lives in this file. */
+
+void
+aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
+ const aarch64_opcode *opcode,
+ const aarch64_opnd_info *opnds, int idx, int *pcrel_p,
+ bfd_vma *address)
+{
+ int i;
+ const char *name = NULL;
+ const aarch64_opnd_info *opnd = opnds + idx;
+ enum aarch64_modifier_kind kind;
+ uint64_t addr;
+
+ buf[0] = '\0';
+ if (pcrel_p)
+ *pcrel_p = 0;
+
+ switch (opnd->type)
+ {
+ case AARCH64_OPND_Rd:
+ case AARCH64_OPND_Rn:
+ case AARCH64_OPND_Rm:
+ case AARCH64_OPND_Rt:
+ case AARCH64_OPND_Rt2:
+ case AARCH64_OPND_Rs:
+ case AARCH64_OPND_Ra:
+ case AARCH64_OPND_Rt_SYS:
+ /* The optional-ness of <Xt> in e.g. IC <ic_op>{, <Xt>} is determined by
+ the <ic_op>, therefore we we use opnd->present to override the
+ generic optional-ness information. */
+ if (opnd->type == AARCH64_OPND_Rt_SYS && !opnd->present)
+ break;
+ /* Omit the operand, e.g. RET. */
+ if (optional_operand_p (opcode, idx)
+ && opnd->reg.regno == get_optional_operand_default_value (opcode))
+ break;
+ assert (opnd->qualifier == AARCH64_OPND_QLF_W
+ || opnd->qualifier == AARCH64_OPND_QLF_X);
+ snprintf (buf, size, "%s",
+ get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
+ break;
+
+ case AARCH64_OPND_Rd_SP:
+ case AARCH64_OPND_Rn_SP:
+ assert (opnd->qualifier == AARCH64_OPND_QLF_W
+ || opnd->qualifier == AARCH64_OPND_QLF_WSP
+ || opnd->qualifier == AARCH64_OPND_QLF_X
+ || opnd->qualifier == AARCH64_OPND_QLF_SP);
+ snprintf (buf, size, "%s",
+ get_int_reg_name (opnd->reg.regno, opnd->qualifier, 1));
+ break;
+
+ case AARCH64_OPND_Rm_EXT:
+ kind = opnd->shifter.kind;
+ assert (idx == 1 || idx == 2);
+ if ((aarch64_stack_pointer_p (opnds)
+ || (idx == 2 && aarch64_stack_pointer_p (opnds + 1)))
+ && ((opnd->qualifier == AARCH64_OPND_QLF_W
+ && opnds[0].qualifier == AARCH64_OPND_QLF_W
+ && kind == AARCH64_MOD_UXTW)
+ || (opnd->qualifier == AARCH64_OPND_QLF_X
+ && kind == AARCH64_MOD_UXTX)))
+ {
+ /* 'LSL' is the preferred form in this case. */
+ kind = AARCH64_MOD_LSL;
+ if (opnd->shifter.amount == 0)
+ {
+ /* Shifter omitted. */
+ snprintf (buf, size, "%s",
+ get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
+ break;
+ }
+ }
+ if (opnd->shifter.amount)
+ snprintf (buf, size, "%s, %s #%d",
+ get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
+ aarch64_operand_modifiers[kind].name,
+ opnd->shifter.amount);
+ else
+ snprintf (buf, size, "%s, %s",
+ get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
+ aarch64_operand_modifiers[kind].name);
+ break;
+
+ case AARCH64_OPND_Rm_SFT:
+ assert (opnd->qualifier == AARCH64_OPND_QLF_W
+ || opnd->qualifier == AARCH64_OPND_QLF_X);
+ if (opnd->shifter.amount == 0 && opnd->shifter.kind == AARCH64_MOD_LSL)
+ snprintf (buf, size, "%s",
+ get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
+ else
+ snprintf (buf, size, "%s, %s #%d",
+ get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
+ aarch64_operand_modifiers[opnd->shifter.kind].name,
+ opnd->shifter.amount);
+ break;
+
+ case AARCH64_OPND_Fd:
+ case AARCH64_OPND_Fn:
+ case AARCH64_OPND_Fm:
+ case AARCH64_OPND_Fa:
+ case AARCH64_OPND_Ft:
+ case AARCH64_OPND_Ft2:
+ case AARCH64_OPND_Sd:
+ case AARCH64_OPND_Sn:
+ case AARCH64_OPND_Sm:
+ snprintf (buf, size, "%s%d", aarch64_get_qualifier_name (opnd->qualifier),
+ opnd->reg.regno);
+ break;
+
+ case AARCH64_OPND_Vd:
+ case AARCH64_OPND_Vn:
+ case AARCH64_OPND_Vm:
+ snprintf (buf, size, "v%d.%s", opnd->reg.regno,
+ aarch64_get_qualifier_name (opnd->qualifier));
+ break;
+
+ case AARCH64_OPND_Ed:
+ case AARCH64_OPND_En:
+ case AARCH64_OPND_Em:
+ snprintf (buf, size, "v%d.%s[%d]", opnd->reglane.regno,
+ aarch64_get_qualifier_name (opnd->qualifier),
+ opnd->reglane.index);
+ break;
+
+ case AARCH64_OPND_VdD1:
+ case AARCH64_OPND_VnD1:
+ snprintf (buf, size, "v%d.d[1]", opnd->reg.regno);
+ break;
+
+ case AARCH64_OPND_LVn:
+ case AARCH64_OPND_LVt:
+ case AARCH64_OPND_LVt_AL:
+ case AARCH64_OPND_LEt:
+ print_register_list (buf, size, opnd);
+ break;
+
+ case AARCH64_OPND_Cn:
+ case AARCH64_OPND_Cm:
+ snprintf (buf, size, "C%d", opnd->reg.regno);
+ break;
+
+ case AARCH64_OPND_IDX:
+ case AARCH64_OPND_IMM:
+ case AARCH64_OPND_WIDTH:
+ case AARCH64_OPND_UIMM3_OP1:
+ case AARCH64_OPND_UIMM3_OP2:
+ case AARCH64_OPND_BIT_NUM:
+ case AARCH64_OPND_IMM_VLSL:
+ case AARCH64_OPND_IMM_VLSR:
+ case AARCH64_OPND_SHLL_IMM:
+ case AARCH64_OPND_IMM0:
+ case AARCH64_OPND_IMMR:
+ case AARCH64_OPND_IMMS:
+ case AARCH64_OPND_FBITS:
+ case AARCH64_OPND_IMM_MOV:
+ snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+ break;
+
+ case AARCH64_OPND_FPIMM0:
+ snprintf (buf, size, "#0.0");
+ break;
+
+ case AARCH64_OPND_LIMM:
+ case AARCH64_OPND_AIMM:
+ case AARCH64_OPND_HALF:
+ if (opnd->shifter.amount)
+ snprintf (buf, size, "#0x%" PRIx64 ", lsl #%d", opnd->imm.value,
+ opnd->shifter.amount);
+ else
+ snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
+ break;
+
+ case AARCH64_OPND_SIMD_IMM:
+ case AARCH64_OPND_SIMD_IMM_SFT:
+ if ((! opnd->shifter.amount && opnd->shifter.kind == AARCH64_MOD_LSL)
+ || opnd->shifter.kind == AARCH64_MOD_NONE)
+ snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
+ else
+ snprintf (buf, size, "#0x%" PRIx64 ", %s #%d", opnd->imm.value,
+ aarch64_operand_modifiers[opnd->shifter.kind].name,
+ opnd->shifter.amount);
+ break;
+
+ case AARCH64_OPND_FPIMM:
+ case AARCH64_OPND_SIMD_FPIMM:
+ switch (aarch64_get_qualifier_esize (opnds[0].qualifier))
+ {
+ case 4: /* e.g. FMOV <Vd>.4S, #<imm>. */
+ {
+ single_conv_t c;
+ c.i = expand_fp_imm (0, opnd->imm.value);
+ snprintf (buf, size, "#%.18e", c.f);
+ }
+ break;
+ case 8: /* e.g. FMOV <Sd>, #<imm>. */
+ {
+ double_conv_t c;
+ c.i = expand_fp_imm (1, opnd->imm.value);
+ snprintf (buf, size, "#%.18e", c.d);
+ }
+ break;
+ default: assert (0);
+ }
+ break;
+
+ case AARCH64_OPND_CCMP_IMM:
+ case AARCH64_OPND_NZCV:
+ case AARCH64_OPND_EXCEPTION:
+ case AARCH64_OPND_UIMM4:
+ case AARCH64_OPND_UIMM7:
+ if (optional_operand_p (opcode, idx) == TRUE
+ && (opnd->imm.value ==
+ (int64_t) get_optional_operand_default_value (opcode)))
+ /* Omit the operand, e.g. DCPS1. */
+ break;
+ snprintf (buf, size, "#0x%x", (unsigned int)opnd->imm.value);
+ break;
+
+ case AARCH64_OPND_COND:
+ snprintf (buf, size, "%s", opnd->cond->names[0]);
+ break;
+
+ case AARCH64_OPND_ADDR_ADRP:
+ addr = ((pc + AARCH64_PCREL_OFFSET) & ~(uint64_t)0xfff)
+ + opnd->imm.value;
+ if (pcrel_p)
+ *pcrel_p = 1;
+ if (address)
+ *address = addr;
+ /* This is not necessary during the disassembling, as print_address_func
+ in the disassemble_info will take care of the printing. But some
+ other callers may be still interested in getting the string in *STR,
+ so here we do snprintf regardless. */
+ snprintf (buf, size, "#0x%" PRIx64, addr);
+ break;
+
+ case AARCH64_OPND_ADDR_PCREL14:
+ case AARCH64_OPND_ADDR_PCREL19:
+ case AARCH64_OPND_ADDR_PCREL21:
+ case AARCH64_OPND_ADDR_PCREL26:
+ addr = pc + AARCH64_PCREL_OFFSET + opnd->imm.value;
+ if (pcrel_p)
+ *pcrel_p = 1;
+ if (address)
+ *address = addr;
+ /* This is not necessary during the disassembling, as print_address_func
+ in the disassemble_info will take care of the printing. But some
+ other callers may be still interested in getting the string in *STR,
+ so here we do snprintf regardless. */
+ snprintf (buf, size, "#0x%" PRIx64, addr);
+ break;
+
+ case AARCH64_OPND_ADDR_SIMPLE:
+ case AARCH64_OPND_SIMD_ADDR_SIMPLE:
+ case AARCH64_OPND_SIMD_ADDR_POST:
+ name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
+ if (opnd->type == AARCH64_OPND_SIMD_ADDR_POST)
+ {
+ if (opnd->addr.offset.is_reg)
+ snprintf (buf, size, "[%s], x%d", name, opnd->addr.offset.regno);
+ else
+ snprintf (buf, size, "[%s], #%d", name, opnd->addr.offset.imm);
+ }
+ else
+ snprintf (buf, size, "[%s]", name);
+ break;
+
+ case AARCH64_OPND_ADDR_REGOFF:
+ print_register_offset_address (buf, size, opnd);
+ break;
+
+ case AARCH64_OPND_ADDR_SIMM7:
+ case AARCH64_OPND_ADDR_SIMM9:
+ case AARCH64_OPND_ADDR_SIMM9_2:
+ name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
+ if (opnd->addr.writeback)
+ {
+ if (opnd->addr.preind)
+ snprintf (buf, size, "[%s,#%d]!", name, opnd->addr.offset.imm);
+ else
+ snprintf (buf, size, "[%s],#%d", name, opnd->addr.offset.imm);
+ }
+ else
+ {
+ if (opnd->addr.offset.imm)
+ snprintf (buf, size, "[%s,#%d]", name, opnd->addr.offset.imm);
+ else
+ snprintf (buf, size, "[%s]", name);
+ }
+ break;
+
+ case AARCH64_OPND_ADDR_UIMM12:
+ name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
+ if (opnd->addr.offset.imm)
+ snprintf (buf, size, "[%s,#%d]", name, opnd->addr.offset.imm);
+ else
+ snprintf (buf, size, "[%s]", name);
+ break;
+
+ case AARCH64_OPND_SYSREG:
+ for (i = 0; aarch64_sys_regs[i].name; ++i)
+ if (aarch64_sys_regs[i].value == opnd->sysreg)
+ break;
+ if (aarch64_sys_regs[i].name)
+ snprintf (buf, size, "%s", aarch64_sys_regs[i].name);
+ else
+ {
+ /* Implementation defined system register. */
+ unsigned int value = opnd->sysreg;
+ snprintf (buf, size, "s%u_%u_c%u_c%u_%u", (value >> 14) & 0x3,
+ (value >> 11) & 0x7, (value >> 7) & 0xf, (value >> 3) & 0xf,
+ value & 0x7);
+ }
+ break;
+
+ case AARCH64_OPND_PSTATEFIELD:
+ for (i = 0; aarch64_pstatefields[i].name; ++i)
+ if (aarch64_pstatefields[i].value == opnd->pstatefield)
+ break;
+ assert (aarch64_pstatefields[i].name);
+ snprintf (buf, size, "%s", aarch64_pstatefields[i].name);
+ break;
+
+ case AARCH64_OPND_SYSREG_AT:
+ case AARCH64_OPND_SYSREG_DC:
+ case AARCH64_OPND_SYSREG_IC:
+ case AARCH64_OPND_SYSREG_TLBI:
+ snprintf (buf, size, "%s", opnd->sysins_op->template);
+ break;
+
+ case AARCH64_OPND_BARRIER:
+ snprintf (buf, size, "%s", opnd->barrier->name);
+ break;
+
+ case AARCH64_OPND_BARRIER_ISB:
+ /* Operand can be omitted, e.g. in DCPS1. */
+ if (! optional_operand_p (opcode, idx)
+ || (opnd->barrier->value
+ != get_optional_operand_default_value (opcode)))
+ snprintf (buf, size, "#0x%x", opnd->barrier->value);
+ break;
+
+ case AARCH64_OPND_PRFOP:
+ snprintf (buf, size, "%s", opnd->prfop->name);
+ break;
+
+ default:
+ assert (0);
+ }
+}
+
+#define CPENC(op0,op1,crn,crm,op2) \
+ ((((op0) << 19) | ((op1) << 16) | ((crn) << 12) | ((crm) << 8) | ((op2) << 5)) >> 5)
+ /* for 3.9.3 Instructions for Accessing Special Purpose Registers */
+#define CPEN_(op1,crm,op2) CPENC(3,(op1),4,(crm),(op2))
+ /* for 3.9.10 System Instructions */
+#define CPENS(op1,crn,crm,op2) CPENC(1,(op1),(crn),(crm),(op2))
+
+#define C0 0
+#define C1 1
+#define C2 2
+#define C3 3
+#define C4 4
+#define C5 5
+#define C6 6
+#define C7 7
+#define C8 8
+#define C9 9
+#define C10 10
+#define C11 11
+#define C12 12
+#define C13 13
+#define C14 14
+#define C15 15
+
+/* TODO there are two more issues need to be resolved
+ 1. handle read-only and write-only system registers
+ 2. handle cpu-implementation-defined system registers. */
+const struct aarch64_name_value_pair aarch64_sys_regs [] =
+{
+ { "spsr_el1", CPEN_(0,C0,0) }, /* = spsr_svc */
+ { "elr_el1", CPEN_(0,C0,1) },
+ { "sp_el0", CPEN_(0,C1,0) },
+ { "spsel", CPEN_(0,C2,0) },
+ { "daif", CPEN_(3,C2,1) },
+ { "currentel", CPEN_(0,C2,2) }, /* RO */
+ { "nzcv", CPEN_(3,C2,0) },
+ { "fpcr", CPEN_(3,C4,0) },
+ { "fpsr", CPEN_(3,C4,1) },
+ { "dspsr_el0", CPEN_(3,C5,0) },
+ { "dlr_el0", CPEN_(3,C5,1) },
+ { "spsr_el2", CPEN_(4,C0,0) }, /* = spsr_hyp */
+ { "elr_el2", CPEN_(4,C0,1) },
+ { "sp_el1", CPEN_(4,C1,0) },
+ { "spsr_irq", CPEN_(4,C3,0) },
+ { "spsr_abt", CPEN_(4,C3,1) },
+ { "spsr_und", CPEN_(4,C3,2) },
+ { "spsr_fiq", CPEN_(4,C3,3) },
+ { "spsr_el3", CPEN_(6,C0,0) },
+ { "elr_el3", CPEN_(6,C0,1) },
+ { "sp_el2", CPEN_(6,C1,0) },
+ { "spsr_svc", CPEN_(0,C0,0) }, /* = spsr_el1 */
+ { "spsr_hyp", CPEN_(4,C0,0) }, /* = spsr_el2 */
+ { "midr_el1", CPENC(3,0,C0,C0,0) }, /* RO */
+ { "ctr_el0", CPENC(3,3,C0,C0,1) }, /* RO */
+ { "mpidr_el1", CPENC(3,0,C0,C0,5) }, /* RO */
+ { "revidr_el1", CPENC(3,0,C0,C0,6) }, /* RO */
+ { "aidr_el1", CPENC(3,1,C0,C0,7) }, /* RO */
+ { "dczid_el0", CPENC(3,3,C0,C0,7) }, /* RO */
+ { "id_dfr0_el1", CPENC(3,0,C0,C1,2) }, /* RO */
+ { "id_pfr0_el1", CPENC(3,0,C0,C1,0) }, /* RO */
+ { "id_pfr1_el1", CPENC(3,0,C0,C1,1) }, /* RO */
+ { "id_afr0_el1", CPENC(3,0,C0,C1,3) }, /* RO */
+ { "id_mmfr0_el1", CPENC(3,0,C0,C1,4) }, /* RO */
+ { "id_mmfr1_el1", CPENC(3,0,C0,C1,5) }, /* RO */
+ { "id_mmfr2_el1", CPENC(3,0,C0,C1,6) }, /* RO */
+ { "id_mmfr3_el1", CPENC(3,0,C0,C1,7) }, /* RO */
+ { "id_isar0_el1", CPENC(3,0,C0,C2,0) }, /* RO */
+ { "id_isar1_el1", CPENC(3,0,C0,C2,1) }, /* RO */
+ { "id_isar2_el1", CPENC(3,0,C0,C2,2) }, /* RO */
+ { "id_isar3_el1", CPENC(3,0,C0,C2,3) }, /* RO */
+ { "id_isar4_el1", CPENC(3,0,C0,C2,4) }, /* RO */
+ { "id_isar5_el1", CPENC(3,0,C0,C2,5) }, /* RO */
+ { "mvfr0_el1", CPENC(3,0,C0,C3,0) }, /* RO */
+ { "mvfr1_el1", CPENC(3,0,C0,C3,1) }, /* RO */
+ { "mvfr2_el1", CPENC(3,0,C0,C3,2) }, /* RO */
+ { "ccsidr_el1", CPENC(3,1,C0,C0,0) }, /* RO */
+ { "id_aa64pfr0_el1", CPENC(3,0,C0,C4,0) }, /* RO */
+ { "id_aa64pfr1_el1", CPENC(3,0,C0,C4,1) }, /* RO */
+ { "id_aa64dfr0_el1", CPENC(3,0,C0,C5,0) }, /* RO */
+ { "id_aa64dfr1_el1", CPENC(3,0,C0,C5,1) }, /* RO */
+ { "id_aa64isar0_el1", CPENC(3,0,C0,C6,0) }, /* RO */
+ { "id_aa64isar1_el1", CPENC(3,0,C0,C6,1) }, /* RO */
+ { "id_aa64mmfr0_el1", CPENC(3,0,C0,C7,0) }, /* RO */
+ { "id_aa64mmfr1_el1", CPENC(3,0,C0,C7,1) }, /* RO */
+ { "id_aa64afr0_el1", CPENC(3,0,C0,C5,4) }, /* RO */
+ { "id_aa64afr1_el1", CPENC(3,0,C0,C5,5) }, /* RO */
+ { "clidr_el1", CPENC(3,1,C0,C0,1) }, /* RO */
+ { "csselr_el1", CPENC(3,2,C0,C0,0) }, /* RO */
+ { "vpidr_el2", CPENC(3,4,C0,C0,0) },
+ { "vmpidr_el2", CPENC(3,4,C0,C0,5) },
+ { "sctlr_el1", CPENC(3,0,C1,C0,0) },
+ { "sctlr_el2", CPENC(3,4,C1,C0,0) },
+ { "sctlr_el3", CPENC(3,6,C1,C0,0) },
+ { "actlr_el1", CPENC(3,0,C1,C0,1) },
+ { "actlr_el2", CPENC(3,4,C1,C0,1) },
+ { "actlr_el3", CPENC(3,6,C1,C0,1) },
+ { "cpacr_el1", CPENC(3,0,C1,C0,2) },
+ { "cptr_el2", CPENC(3,4,C1,C1,2) },
+ { "cptr_el3", CPENC(3,6,C1,C1,2) },
+ { "scr_el3", CPENC(3,6,C1,C1,0) },
+ { "hcr_el2", CPENC(3,4,C1,C1,0) },
+ { "mdcr_el2", CPENC(3,4,C1,C1,1) },
+ { "mdcr_el3", CPENC(3,6,C1,C3,1) },
+ { "hstr_el2", CPENC(3,4,C1,C1,3) },
+ { "hacr_el2", CPENC(3,4,C1,C1,7) },
+ { "ttbr0_el1", CPENC(3,0,C2,C0,0) },
+ { "ttbr1_el1", CPENC(3,0,C2,C0,1) },
+ { "ttbr0_el2", CPENC(3,4,C2,C0,0) },
+ { "ttbr0_el3", CPENC(3,6,C2,C0,0) },
+ { "vttbr_el2", CPENC(3,4,C2,C1,0) },
+ { "tcr_el1", CPENC(3,0,C2,C0,2) },
+ { "tcr_el2", CPENC(3,4,C2,C0,2) },
+ { "tcr_el3", CPENC(3,6,C2,C0,2) },
+ { "vtcr_el2", CPENC(3,4,C2,C1,2) },
+ { "afsr0_el1", CPENC(3,0,C5,C1,0) },
+ { "afsr1_el1", CPENC(3,0,C5,C1,1) },
+ { "afsr0_el2", CPENC(3,4,C5,C1,0) },
+ { "afsr1_el2", CPENC(3,4,C5,C1,1) },
+ { "afsr0_el3", CPENC(3,6,C5,C1,0) },
+ { "afsr1_el3", CPENC(3,6,C5,C1,1) },
+ { "esr_el1", CPENC(3,0,C5,C2,0) },
+ { "esr_el2", CPENC(3,4,C5,C2,0) },
+ { "esr_el3", CPENC(3,6,C5,C2,0) },
+ { "fpexc32_el2", CPENC(3,4,C5,C3,0) },
+ { "far_el1", CPENC(3,0,C6,C0,0) },
+ { "far_el2", CPENC(3,4,C6,C0,0) },
+ { "far_el3", CPENC(3,6,C6,C0,0) },
+ { "hpfar_el2", CPENC(3,4,C6,C0,4) },
+ { "par_el1", CPENC(3,0,C7,C4,0) },
+ { "mair_el1", CPENC(3,0,C10,C2,0) },
+ { "mair_el2", CPENC(3,4,C10,C2,0) },
+ { "mair_el3", CPENC(3,6,C10,C2,0) },
+ { "amair_el1", CPENC(3,0,C10,C3,0) },
+ { "amair_el2", CPENC(3,4,C10,C3,0) },
+ { "amair_el3", CPENC(3,6,C10,C3,0) },
+ { "vbar_el1", CPENC(3,0,C12,C0,0) },
+ { "vbar_el2", CPENC(3,4,C12,C0,0) },
+ { "vbar_el3", CPENC(3,6,C12,C0,0) },
+ { "rvbar_el1", CPENC(3,0,C12,C0,1) }, /* RO */
+ { "rvbar_el2", CPENC(3,4,C12,C0,1) }, /* RO */
+ { "rvbar_el3", CPENC(3,6,C12,C0,1) }, /* RO */
+ { "isr_el1", CPENC(3,0,C12,C1,0) }, /* RO */
+ { "contextidr_el1", CPENC(3,0,C13,C0,1) },
+ { "tpidr_el0", CPENC(3,3,C13,C0,2) },
+ { "tpidrro_el0", CPENC(3,3,C13,C0,3) }, /* RO */
+ { "tpidr_el1", CPENC(3,0,C13,C0,4) },
+ { "tpidr_el2", CPENC(3,4,C13,C0,2) },
+ { "tpidr_el3", CPENC(3,6,C13,C0,2) },
+ { "teecr32_el1", CPENC(2,2,C0, C0,0) }, /* See section 3.9.7.1 */
+ { "cntfrq_el0", CPENC(3,3,C14,C0,0) }, /* RO */
+ { "cntpct_el0", CPENC(3,3,C14,C0,1) }, /* RO */
+ { "cntvct_el0", CPENC(3,3,C14,C0,2) }, /* RO */
+ { "cntvoff_el2", CPENC(3,4,C14,C0,3) },
+ { "cntkctl_el1", CPENC(3,0,C14,C1,0) },
+ { "cnthctl_el2", CPENC(3,4,C14,C1,0) },
+ { "cntp_tval_el0", CPENC(3,3,C14,C2,0) },
+ { "cntp_ctl_el0", CPENC(3,3,C14,C2,1) },
+ { "cntp_cval_el0", CPENC(3,3,C14,C2,2) },
+ { "cntv_tval_el0", CPENC(3,3,C14,C3,0) },
+ { "cntv_ctl_el0", CPENC(3,3,C14,C3,1) },
+ { "cntv_cval_el0", CPENC(3,3,C14,C3,2) },
+ { "cnthp_tval_el2", CPENC(3,4,C14,C2,0) },
+ { "cnthp_ctl_el2", CPENC(3,4,C14,C2,1) },
+ { "cnthp_cval_el2", CPENC(3,4,C14,C2,2) },
+ { "cntps_tval_el1", CPENC(3,7,C14,C2,0) },
+ { "cntps_ctl_el1", CPENC(3,7,C14,C2,1) },
+ { "cntps_cval_el1", CPENC(3,7,C14,C2,2) },
+ { "dacr32_el2", CPENC(3,4,C3,C0,0) },
+ { "ifsr32_el2", CPENC(3,4,C5,C0,1) },
+ { "teehbr32_el1", CPENC(2,2,C1,C0,0) },
+ { "sder32_el3", CPENC(3,6,C1,C1,1) },
+ { "mdscr_el1", CPENC(2,0,C0, C2, 2) },
+ { "mdccsr_el0", CPENC(2,3,C0, C1, 0) }, /* r */
+ { "mdccint_el1", CPENC(2,0,C0, C2, 0) },
+ { "dbgdtr_el0", CPENC(2,3,C0, C4, 0) },
+ { "dbgdtrrx_el0", CPENC(2,3,C0, C5, 0) }, /* r */
+ { "dbgdtrtx_el0", CPENC(2,3,C0, C5, 0) }, /* w */
+ { "osdtrrx_el1", CPENC(2,0,C0, C0, 2) }, /* r */
+ { "osdtrtx_el1", CPENC(2,0,C0, C3, 2) }, /* w */
+ { "oseccr_el1", CPENC(2,0,C0, C6, 2) },
+ { "dbgvcr32_el2", CPENC(2,4,C0, C7, 0) },
+ { "dbgbvr0_el1", CPENC(2,0,C0, C0, 4) },
+ { "dbgbvr1_el1", CPENC(2,0,C0, C1, 4) },
+ { "dbgbvr2_el1", CPENC(2,0,C0, C2, 4) },
+ { "dbgbvr3_el1", CPENC(2,0,C0, C3, 4) },
+ { "dbgbvr4_el1", CPENC(2,0,C0, C4, 4) },
+ { "dbgbvr5_el1", CPENC(2,0,C0, C5, 4) },
+ { "dbgbvr6_el1", CPENC(2,0,C0, C6, 4) },
+ { "dbgbvr7_el1", CPENC(2,0,C0, C7, 4) },
+ { "dbgbvr8_el1", CPENC(2,0,C0, C8, 4) },
+ { "dbgbvr9_el1", CPENC(2,0,C0, C9, 4) },
+ { "dbgbvr10_el1", CPENC(2,0,C0, C10,4) },
+ { "dbgbvr11_el1", CPENC(2,0,C0, C11,4) },
+ { "dbgbvr12_el1", CPENC(2,0,C0, C12,4) },
+ { "dbgbvr13_el1", CPENC(2,0,C0, C13,4) },
+ { "dbgbvr14_el1", CPENC(2,0,C0, C14,4) },
+ { "dbgbvr15_el1", CPENC(2,0,C0, C15,4) },
+ { "dbgbcr0_el1", CPENC(2,0,C0, C0, 5) },
+ { "dbgbcr1_el1", CPENC(2,0,C0, C1, 5) },
+ { "dbgbcr2_el1", CPENC(2,0,C0, C2, 5) },
+ { "dbgbcr3_el1", CPENC(2,0,C0, C3, 5) },
+ { "dbgbcr4_el1", CPENC(2,0,C0, C4, 5) },
+ { "dbgbcr5_el1", CPENC(2,0,C0, C5, 5) },
+ { "dbgbcr6_el1", CPENC(2,0,C0, C6, 5) },
+ { "dbgbcr7_el1", CPENC(2,0,C0, C7, 5) },
+ { "dbgbcr8_el1", CPENC(2,0,C0, C8, 5) },
+ { "dbgbcr9_el1", CPENC(2,0,C0, C9, 5) },
+ { "dbgbcr10_el1", CPENC(2,0,C0, C10,5) },
+ { "dbgbcr11_el1", CPENC(2,0,C0, C11,5) },
+ { "dbgbcr12_el1", CPENC(2,0,C0, C12,5) },
+ { "dbgbcr13_el1", CPENC(2,0,C0, C13,5) },
+ { "dbgbcr14_el1", CPENC(2,0,C0, C14,5) },
+ { "dbgbcr15_el1", CPENC(2,0,C0, C15,5) },
+ { "dbgwvr0_el1", CPENC(2,0,C0, C0, 6) },
+ { "dbgwvr1_el1", CPENC(2,0,C0, C1, 6) },
+ { "dbgwvr2_el1", CPENC(2,0,C0, C2, 6) },
+ { "dbgwvr3_el1", CPENC(2,0,C0, C3, 6) },
+ { "dbgwvr4_el1", CPENC(2,0,C0, C4, 6) },
+ { "dbgwvr5_el1", CPENC(2,0,C0, C5, 6) },
+ { "dbgwvr6_el1", CPENC(2,0,C0, C6, 6) },
+ { "dbgwvr7_el1", CPENC(2,0,C0, C7, 6) },
+ { "dbgwvr8_el1", CPENC(2,0,C0, C8, 6) },
+ { "dbgwvr9_el1", CPENC(2,0,C0, C9, 6) },
+ { "dbgwvr10_el1", CPENC(2,0,C0, C10,6) },
+ { "dbgwvr11_el1", CPENC(2,0,C0, C11,6) },
+ { "dbgwvr12_el1", CPENC(2,0,C0, C12,6) },
+ { "dbgwvr13_el1", CPENC(2,0,C0, C13,6) },
+ { "dbgwvr14_el1", CPENC(2,0,C0, C14,6) },
+ { "dbgwvr15_el1", CPENC(2,0,C0, C15,6) },
+ { "dbgwcr0_el1", CPENC(2,0,C0, C0, 7) },
+ { "dbgwcr1_el1", CPENC(2,0,C0, C1, 7) },
+ { "dbgwcr2_el1", CPENC(2,0,C0, C2, 7) },
+ { "dbgwcr3_el1", CPENC(2,0,C0, C3, 7) },
+ { "dbgwcr4_el1", CPENC(2,0,C0, C4, 7) },
+ { "dbgwcr5_el1", CPENC(2,0,C0, C5, 7) },
+ { "dbgwcr6_el1", CPENC(2,0,C0, C6, 7) },
+ { "dbgwcr7_el1", CPENC(2,0,C0, C7, 7) },
+ { "dbgwcr8_el1", CPENC(2,0,C0, C8, 7) },
+ { "dbgwcr9_el1", CPENC(2,0,C0, C9, 7) },
+ { "dbgwcr10_el1", CPENC(2,0,C0, C10,7) },
+ { "dbgwcr11_el1", CPENC(2,0,C0, C11,7) },
+ { "dbgwcr12_el1", CPENC(2,0,C0, C12,7) },
+ { "dbgwcr13_el1", CPENC(2,0,C0, C13,7) },
+ { "dbgwcr14_el1", CPENC(2,0,C0, C14,7) },
+ { "dbgwcr15_el1", CPENC(2,0,C0, C15,7) },
+ { "mdrar_el1", CPENC(2,0,C1, C0, 0) }, /* r */
+ { "oslar_el1", CPENC(2,0,C1, C0, 4) }, /* w */
+ { "oslsr_el1", CPENC(2,0,C1, C1, 4) }, /* r */
+ { "osdlr_el1", CPENC(2,0,C1, C3, 4) },
+ { "dbgprcr_el1", CPENC(2,0,C1, C4, 4) },
+ { "dbgclaimset_el1", CPENC(2,0,C7, C8, 6) },
+ { "dbgclaimclr_el1", CPENC(2,0,C7, C9, 6) },
+ { "dbgauthstatus_el1", CPENC(2,0,C7, C14,6) }, /* r */
+
+ { "pmcr_el0", CPENC(3,3,C9,C12, 0) },
+ { "pmcntenset_el0", CPENC(3,3,C9,C12, 1) },
+ { "pmcntenclr_el0", CPENC(3,3,C9,C12, 2) },
+ { "pmovsclr_el0", CPENC(3,3,C9,C12, 3) },
+ { "pmswinc_el0", CPENC(3,3,C9,C12, 4) }, /* w */
+ { "pmselr_el0", CPENC(3,3,C9,C12, 5) },
+ { "pmceid0_el0", CPENC(3,3,C9,C12, 6) }, /* r */
+ { "pmceid1_el0", CPENC(3,3,C9,C12, 7) }, /* r */
+ { "pmccntr_el0", CPENC(3,3,C9,C13, 0) },
+ { "pmxevtyper_el0", CPENC(3,3,C9,C13, 1) },
+ { "pmxevcntr_el0", CPENC(3,3,C9,C13, 2) },
+ { "pmuserenr_el0", CPENC(3,3,C9,C14, 0) },
+ { "pmintenset_el1", CPENC(3,0,C9,C14, 1) },
+ { "pmintenclr_el1", CPENC(3,0,C9,C14, 2) },
+ { "pmovsset_el0", CPENC(3,3,C9,C14, 3) },
+ { "pmevcntr0_el0", CPENC(3,3,C14,C8, 0) },
+ { "pmevcntr1_el0", CPENC(3,3,C14,C8, 1) },
+ { "pmevcntr2_el0", CPENC(3,3,C14,C8, 2) },
+ { "pmevcntr3_el0", CPENC(3,3,C14,C8, 3) },
+ { "pmevcntr4_el0", CPENC(3,3,C14,C8, 4) },
+ { "pmevcntr5_el0", CPENC(3,3,C14,C8, 5) },
+ { "pmevcntr6_el0", CPENC(3,3,C14,C8, 6) },
+ { "pmevcntr7_el0", CPENC(3,3,C14,C8, 7) },
+ { "pmevcntr8_el0", CPENC(3,3,C14,C9, 0) },
+ { "pmevcntr9_el0", CPENC(3,3,C14,C9, 1) },
+ { "pmevcntr10_el0", CPENC(3,3,C14,C9, 2) },
+ { "pmevcntr11_el0", CPENC(3,3,C14,C9, 3) },
+ { "pmevcntr12_el0", CPENC(3,3,C14,C9, 4) },
+ { "pmevcntr13_el0", CPENC(3,3,C14,C9, 5) },
+ { "pmevcntr14_el0", CPENC(3,3,C14,C9, 6) },
+ { "pmevcntr15_el0", CPENC(3,3,C14,C9, 7) },
+ { "pmevcntr16_el0", CPENC(3,3,C14,C10,0) },
+ { "pmevcntr17_el0", CPENC(3,3,C14,C10,1) },
+ { "pmevcntr18_el0", CPENC(3,3,C14,C10,2) },
+ { "pmevcntr19_el0", CPENC(3,3,C14,C10,3) },
+ { "pmevcntr20_el0", CPENC(3,3,C14,C10,4) },
+ { "pmevcntr21_el0", CPENC(3,3,C14,C10,5) },
+ { "pmevcntr22_el0", CPENC(3,3,C14,C10,6) },
+ { "pmevcntr23_el0", CPENC(3,3,C14,C10,7) },
+ { "pmevcntr24_el0", CPENC(3,3,C14,C11,0) },
+ { "pmevcntr25_el0", CPENC(3,3,C14,C11,1) },
+ { "pmevcntr26_el0", CPENC(3,3,C14,C11,2) },
+ { "pmevcntr27_el0", CPENC(3,3,C14,C11,3) },
+ { "pmevcntr28_el0", CPENC(3,3,C14,C11,4) },
+ { "pmevcntr29_el0", CPENC(3,3,C14,C11,5) },
+ { "pmevcntr30_el0", CPENC(3,3,C14,C11,6) },
+ { "pmevtyper0_el0", CPENC(3,3,C14,C12,0) },
+ { "pmevtyper1_el0", CPENC(3,3,C14,C12,1) },
+ { "pmevtyper2_el0", CPENC(3,3,C14,C12,2) },
+ { "pmevtyper3_el0", CPENC(3,3,C14,C12,3) },
+ { "pmevtyper4_el0", CPENC(3,3,C14,C12,4) },
+ { "pmevtyper5_el0", CPENC(3,3,C14,C12,5) },
+ { "pmevtyper6_el0", CPENC(3,3,C14,C12,6) },
+ { "pmevtyper7_el0", CPENC(3,3,C14,C12,7) },
+ { "pmevtyper8_el0", CPENC(3,3,C14,C13,0) },
+ { "pmevtyper9_el0", CPENC(3,3,C14,C13,1) },
+ { "pmevtyper10_el0", CPENC(3,3,C14,C13,2) },
+ { "pmevtyper11_el0", CPENC(3,3,C14,C13,3) },
+ { "pmevtyper12_el0", CPENC(3,3,C14,C13,4) },
+ { "pmevtyper13_el0", CPENC(3,3,C14,C13,5) },
+ { "pmevtyper14_el0", CPENC(3,3,C14,C13,6) },
+ { "pmevtyper15_el0", CPENC(3,3,C14,C13,7) },
+ { "pmevtyper16_el0", CPENC(3,3,C14,C14,0) },
+ { "pmevtyper17_el0", CPENC(3,3,C14,C14,1) },
+ { "pmevtyper18_el0", CPENC(3,3,C14,C14,2) },
+ { "pmevtyper19_el0", CPENC(3,3,C14,C14,3) },
+ { "pmevtyper20_el0", CPENC(3,3,C14,C14,4) },
+ { "pmevtyper21_el0", CPENC(3,3,C14,C14,5) },
+ { "pmevtyper22_el0", CPENC(3,3,C14,C14,6) },
+ { "pmevtyper23_el0", CPENC(3,3,C14,C14,7) },
+ { "pmevtyper24_el0", CPENC(3,3,C14,C15,0) },
+ { "pmevtyper25_el0", CPENC(3,3,C14,C15,1) },
+ { "pmevtyper26_el0", CPENC(3,3,C14,C15,2) },
+ { "pmevtyper27_el0", CPENC(3,3,C14,C15,3) },
+ { "pmevtyper28_el0", CPENC(3,3,C14,C15,4) },
+ { "pmevtyper29_el0", CPENC(3,3,C14,C15,5) },
+ { "pmevtyper30_el0", CPENC(3,3,C14,C15,6) },
+ { "pmccfiltr_el0", CPENC(3,3,C14,C15,7) },
+
+ { "daifset", CPENC(0,3,C4,C0,6) },
+ { "daifclr", CPENC(0,3,C4,C0,7) },
+
+ { 0, CPENC(0,0,0,0,0) },
+};
+
+const struct aarch64_name_value_pair aarch64_pstatefields [] =
+{
+ { "spsel", 0x05 },
+ { "daifset", 0x1e },
+ { "daifclr", 0x1f },
+ { 0, CPENC(0,0,0,0,0) },
+};
+
+const aarch64_sys_ins_reg aarch64_sys_regs_ic[] =
+{
+ { "ialluis", CPENS(0,C7,C1,0), 0 },
+ { "iallu", CPENS(0,C7,C5,0), 0 },
+ { "ivau", CPENS(3,C7,C5,1), 1 },
+ { 0, CPENS(0,0,0,0), 0 }
+};
+
+const aarch64_sys_ins_reg aarch64_sys_regs_dc[] =
+{
+ { "zva", CPENS(3,C7,C4,1), 1 },
+ { "ivac", CPENS(0,C7,C6,1), 1 },
+ { "isw", CPENS(0,C7,C6,2), 1 },
+ { "cvac", CPENS(3,C7,C10,1), 1 },
+ { "csw", CPENS(0,C7,C10,2), 1 },
+ { "cvau", CPENS(3,C7,C11,1), 1 },
+ { "civac", CPENS(3,C7,C14,1), 1 },
+ { "cisw", CPENS(0,C7,C14,2), 1 },
+ { 0, CPENS(0,0,0,0), 0 }
+};
+
+const aarch64_sys_ins_reg aarch64_sys_regs_at[] =
+{
+ { "s1e1r", CPENS(0,C7,C8,0), 1 },
+ { "s1e1w", CPENS(0,C7,C8,1), 1 },
+ { "s1e0r", CPENS(0,C7,C8,2), 1 },
+ { "s1e0w", CPENS(0,C7,C8,3), 1 },
+ { "s12e1r", CPENS(4,C7,C8,4), 1 },
+ { "s12e1w", CPENS(4,C7,C8,5), 1 },
+ { "s12e0r", CPENS(4,C7,C8,6), 1 },
+ { "s12e0w", CPENS(4,C7,C8,7), 1 },
+ { "s1e2r", CPENS(4,C7,C8,0), 1 },
+ { "s1e2w", CPENS(4,C7,C8,1), 1 },
+ { "s1e3r", CPENS(6,C7,C8,0), 1 },
+ { "s1e3w", CPENS(6,C7,C8,1), 1 },
+ { 0, CPENS(0,0,0,0), 0 }
+};
+
+const aarch64_sys_ins_reg aarch64_sys_regs_tlbi[] =
+{
+ { "vmalle1", CPENS(0,C8,C7,0), 0 },
+ { "vae1", CPENS(0,C8,C7,1), 1 },
+ { "aside1", CPENS(0,C8,C7,2), 1 },
+ { "vaae1", CPENS(0,C8,C7,3), 1 },
+ { "vmalle1is", CPENS(0,C8,C3,0), 0 },
+ { "vae1is", CPENS(0,C8,C3,1), 1 },
+ { "aside1is", CPENS(0,C8,C3,2), 1 },
+ { "vaae1is", CPENS(0,C8,C3,3), 1 },
+ { "ipas2e1is", CPENS(4,C8,C0,1), 1 },
+ { "ipas2le1is",CPENS(4,C8,C0,5), 1 },
+ { "ipas2e1", CPENS(4,C8,C4,1), 1 },
+ { "ipas2le1", CPENS(4,C8,C4,5), 1 },
+ { "vae2", CPENS(4,C8,C7,1), 1 },
+ { "vae2is", CPENS(4,C8,C3,1), 1 },
+ { "vmalls12e1",CPENS(4,C8,C7,6), 0 },
+ { "vmalls12e1is",CPENS(4,C8,C3,6), 0 },
+ { "vae3", CPENS(6,C8,C7,1), 1 },
+ { "vae3is", CPENS(6,C8,C3,1), 1 },
+ { "alle2", CPENS(4,C8,C7,0), 0 },
+ { "alle2is", CPENS(4,C8,C3,0), 0 },
+ { "alle1", CPENS(4,C8,C7,4), 0 },
+ { "alle1is", CPENS(4,C8,C3,4), 0 },
+ { "alle3", CPENS(6,C8,C7,0), 0 },
+ { "alle3is", CPENS(6,C8,C3,0), 0 },
+ { "vale1is", CPENS(0,C8,C3,5), 1 },
+ { "vale2is", CPENS(4,C8,C3,5), 1 },
+ { "vale3is", CPENS(6,C8,C3,5), 1 },
+ { "vaale1is", CPENS(0,C8,C3,7), 1 },
+ { "vale1", CPENS(0,C8,C7,5), 1 },
+ { "vale2", CPENS(4,C8,C7,5), 1 },
+ { "vale3", CPENS(6,C8,C7,5), 1 },
+ { "vaale1", CPENS(0,C8,C7,7), 1 },
+ { 0, CPENS(0,0,0,0), 0 }
+};
+
+#undef C0
+#undef C1
+#undef C2
+#undef C3
+#undef C4
+#undef C5
+#undef C6
+#undef C7
+#undef C8
+#undef C9
+#undef C10
+#undef C11
+#undef C12
+#undef C13
+#undef C14
+#undef C15
+
+/* Include the opcode description table as well as the operand description
+ table. */
+#include "aarch64-tbl.h"
diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h
new file mode 100644
index 0000000..d475fa4
--- /dev/null
+++ b/opcodes/aarch64-opc.h
@@ -0,0 +1,392 @@
+/* aarch64-opc.h -- Header file for aarch64-opc.c and aarch64-opc-2.c.
+ Copyright 2012 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of the GNU opcodes library.
+
+ This library 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 3, or (at your option)
+ any later version.
+
+ It 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; see the file COPYING3. If not,
+ see <http://www.gnu.org/licenses/>. */
+
+#ifndef OPCODES_AARCH64_OPC_H
+#define OPCODES_AARCH64_OPC_H
+
+#include <string.h>
+#include "opcode/aarch64.h"
+
+/* Instruction fields.
+ Keep synced with fields. */
+enum aarch64_field_kind
+{
+ FLD_NIL,
+ FLD_cond2,
+ FLD_nzcv,
+ FLD_defgh,
+ FLD_abc,
+ FLD_imm19,
+ FLD_immhi,
+ FLD_immlo,
+ FLD_size,
+ FLD_vldst_size,
+ FLD_op,
+ FLD_Q,
+ FLD_Rt,
+ FLD_Rd,
+ FLD_Rn,
+ FLD_Rt2,
+ FLD_Ra,
+ FLD_op2,
+ FLD_CRm,
+ FLD_CRn,
+ FLD_op1,
+ FLD_op0,
+ FLD_imm3,
+ FLD_cond,
+ FLD_opcode,
+ FLD_cmode,
+ FLD_asisdlso_opcode,
+ FLD_len,
+ FLD_Rm,
+ FLD_Rs,
+ FLD_option,
+ FLD_S,
+ FLD_hw,
+ FLD_opc,
+ FLD_opc1,
+ FLD_shift,
+ FLD_type,
+ FLD_ldst_size,
+ FLD_imm6,
+ FLD_imm4,
+ FLD_imm5,
+ FLD_imm7,
+ FLD_imm8,
+ FLD_imm9,
+ FLD_imm12,
+ FLD_imm14,
+ FLD_imm16,
+ FLD_imm26,
+ FLD_imms,
+ FLD_immr,
+ FLD_immb,
+ FLD_immh,
+ FLD_N,
+ FLD_index,
+ FLD_index2,
+ FLD_sf,
+ FLD_H,
+ FLD_L,
+ FLD_M,
+ FLD_b5,
+ FLD_b40,
+ FLD_scale,
+};
+
+/* Field description. */
+struct aarch64_field
+{
+ int lsb;
+ int width;
+};
+
+typedef struct aarch64_field aarch64_field;
+
+extern const aarch64_field fields[];
+
+/* Operand description. */
+
+struct aarch64_operand
+{
+ enum aarch64_operand_class op_class;
+
+ /* Name of the operand code; used mainly for the purpose of internal
+ debugging. */
+ const char *name;
+
+ unsigned int flags;
+
+ /* The associated instruction bit-fields; no operand has more than 4
+ bit-fields */
+ enum aarch64_field_kind fields[4];
+
+ /* Brief description */
+ const char *desc;
+};
+
+typedef struct aarch64_operand aarch64_operand;
+
+extern const aarch64_operand aarch64_operands[];
+
+/* Operand flags. */
+
+#define OPD_F_HAS_INSERTER 0x00000001
+#define OPD_F_HAS_EXTRACTOR 0x00000002
+#define OPD_F_SEXT 0x00000004 /* Require sign-extension. */
+#define OPD_F_SHIFT_BY_2 0x00000008 /* Need to left shift the field
+ value by 2 to get the value
+ of an immediate operand. */
+#define OPD_F_MAYBE_SP 0x00000010 /* May potentially be SP. */
+
+static inline bfd_boolean
+operand_has_inserter (const aarch64_operand *operand)
+{
+ return (operand->flags & OPD_F_HAS_INSERTER) ? TRUE : FALSE;
+}
+
+static inline bfd_boolean
+operand_has_extractor (const aarch64_operand *operand)
+{
+ return (operand->flags & OPD_F_HAS_EXTRACTOR) ? TRUE : FALSE;
+}
+
+static inline bfd_boolean
+operand_need_sign_extension (const aarch64_operand *operand)
+{
+ return (operand->flags & OPD_F_SEXT) ? TRUE : FALSE;
+}
+
+static inline bfd_boolean
+operand_need_shift_by_two (const aarch64_operand *operand)
+{
+ return (operand->flags & OPD_F_SHIFT_BY_2) ? TRUE : FALSE;
+}
+
+static inline bfd_boolean
+operand_maybe_stack_pointer (const aarch64_operand *operand)
+{
+ return (operand->flags & OPD_F_MAYBE_SP) ? TRUE : FALSE;
+}
+
+/* Return the total width of the operand *OPERAND. */
+static inline unsigned
+get_operand_fields_width (const aarch64_operand *operand)
+{
+ int i = 0;
+ unsigned width = 0;
+ while (operand->fields[i] != FLD_NIL)
+ width += fields[operand->fields[i++]].width;
+ assert (width > 0 && width < 32);
+ return width;
+}
+
+static inline const aarch64_operand *
+get_operand_from_code (enum aarch64_opnd code)
+{
+ return aarch64_operands + code;
+}
+
+/* Operand qualifier and operand constraint checking. */
+
+int aarch64_match_operands_constraint (aarch64_inst *,
+ aarch64_operand_error *);
+
+/* Operand qualifier related functions. */
+const char* aarch64_get_qualifier_name (aarch64_opnd_qualifier_t);
+unsigned char aarch64_get_qualifier_nelem (aarch64_opnd_qualifier_t);
+aarch64_insn aarch64_get_qualifier_standard_value (aarch64_opnd_qualifier_t);
+int aarch64_find_best_match (const aarch64_inst *,
+ const aarch64_opnd_qualifier_seq_t *,
+ int, aarch64_opnd_qualifier_t *);
+
+static inline void
+reset_operand_qualifier (aarch64_inst *inst, int idx)
+{
+ assert (idx >=0 && idx < aarch64_num_of_operands (inst->opcode));
+ inst->operands[idx].qualifier = AARCH64_OPND_QLF_NIL;
+}
+
+/* Inline functions operating on instruction bit-field(s). */
+
+/* Generate a mask that has WIDTH number of consecutive 1s. */
+
+static inline aarch64_insn
+gen_mask (int width)
+{
+ return ((aarch64_insn) 1 << width) - 1;;
+}
+
+/* LSB_REL is the relative location of the lsb in the sub field, starting from 0. */
+static inline int
+gen_sub_field (enum aarch64_field_kind kind, int lsb_rel, int width, aarch64_field *ret)
+{
+ const aarch64_field *field = &fields[kind];
+ if (lsb_rel < 0 || width <= 0 || lsb_rel + width > field->width)
+ return 0;
+ ret->lsb = field->lsb + lsb_rel;
+ ret->width = width;
+ return 1;
+}
+
+/* Insert VALUE into FIELD of CODE. MASK can be zero or the base mask
+ of the opcode. */
+
+static inline void
+insert_field_2 (const aarch64_field *field, aarch64_insn *code,
+ aarch64_insn value, aarch64_insn mask)
+{
+ assert (field->width < 32 && field->width >= 1 && field->lsb >= 0
+ && field->lsb + field->width <= 32);
+ value &= gen_mask (field->width);
+ value <<= field->lsb;
+ /* In some opcodes, field can be part of the base opcode, e.g. the size
+ field in FADD. The following helps avoid corrupt the base opcode. */
+ value &= ~mask;
+ *code |= value;
+}
+
+/* Extract FIELD of CODE and return the value. MASK can be zero or the base
+ mask of the opcode. */
+
+static inline aarch64_insn
+extract_field_2 (const aarch64_field *field, aarch64_insn code,
+ aarch64_insn mask)
+{
+ aarch64_insn value;
+ /* Clear any bit that is a part of the base opcode. */
+ code &= ~mask;
+ value = (code >> field->lsb) & gen_mask (field->width);
+ return value;
+}
+
+/* Insert VALUE into field KIND of CODE. MASK can be zero or the base mask
+ of the opcode. */
+
+static inline void
+insert_field (enum aarch64_field_kind kind, aarch64_insn *code,
+ aarch64_insn value, aarch64_insn mask)
+{
+ insert_field_2 (&fields[kind], code, value, mask);
+}
+
+/* Extract field KIND of CODE and return the value. MASK can be zero or the
+ base mask of the opcode. */
+
+static inline aarch64_insn
+extract_field (enum aarch64_field_kind kind, aarch64_insn code,
+ aarch64_insn mask)
+{
+ return extract_field_2 (&fields[kind], code, mask);
+}
+
+/* Inline functions selecting operand to do the encoding/decoding for a
+ certain instruction bit-field. */
+
+/* Select the operand to do the encoding/decoding of the 'sf' field.
+ The heuristic-based rule is that the result operand is respected more. */
+
+static inline int
+select_operand_for_sf_field_coding (const aarch64_opcode *opcode)
+{
+ int idx = -1;
+ if (aarch64_get_operand_class (opcode->operands[0])
+ == AARCH64_OPND_CLASS_INT_REG)
+ /* normal case. */
+ idx = 0;
+ else if (aarch64_get_operand_class (opcode->operands[1])
+ == AARCH64_OPND_CLASS_INT_REG)
+ /* e.g. float2fix. */
+ idx = 1;
+ else
+ { assert (0); abort (); }
+ return idx;
+}
+
+/* Select the operand to do the encoding/decoding of the 'type' field in
+ the floating-point instructions.
+ The heuristic-based rule is that the source operand is respected more. */
+
+static inline int
+select_operand_for_fptype_field_coding (const aarch64_opcode *opcode)
+{
+ int idx;
+ if (aarch64_get_operand_class (opcode->operands[1])
+ == AARCH64_OPND_CLASS_FP_REG)
+ /* normal case. */
+ idx = 1;
+ else if (aarch64_get_operand_class (opcode->operands[0])
+ == AARCH64_OPND_CLASS_FP_REG)
+ /* e.g. float2fix. */
+ idx = 0;
+ else
+ { assert (0); abort (); }
+ return idx;
+}
+
+/* Select the operand to do the encoding/decoding of the 'size' field in
+ the AdvSIMD scalar instructions.
+ The heuristic-based rule is that the destination operand is respected
+ more. */
+
+static inline int
+select_operand_for_scalar_size_field_coding (const aarch64_opcode *opcode)
+{
+ int src_size = 0, dst_size = 0;
+ if (aarch64_get_operand_class (opcode->operands[0])
+ == AARCH64_OPND_CLASS_SISD_REG)
+ dst_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][0]);
+ if (aarch64_get_operand_class (opcode->operands[1])
+ == AARCH64_OPND_CLASS_SISD_REG)
+ src_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][1]);
+ if (src_size == dst_size && src_size == 0)
+ { assert (0); abort (); }
+ /* When the result is not a sisd register or it is a long operantion. */
+ if (dst_size == 0 || dst_size == src_size << 1)
+ return 1;
+ else
+ return 0;
+}
+
+/* Select the operand to do the encoding/decoding of the 'size:Q' fields in
+ the AdvSIMD instructions. */
+
+int aarch64_select_operand_for_sizeq_field_coding (const aarch64_opcode *);
+
+/* Miscellaneous. */
+
+aarch64_insn aarch64_get_operand_modifier_value (enum aarch64_modifier_kind);
+enum aarch64_modifier_kind
+aarch64_get_operand_modifier_from_value (aarch64_insn, bfd_boolean);
+
+
+bfd_boolean aarch64_wide_constant_p (int64_t, int, unsigned int *);
+bfd_boolean aarch64_logical_immediate_p (uint64_t, int, aarch64_insn *);
+int aarch64_shrink_expanded_imm8 (uint64_t);
+
+/* Copy the content of INST->OPERANDS[SRC] to INST->OPERANDS[DST]. */
+static inline void
+copy_operand_info (aarch64_inst *inst, int dst, int src)
+{
+ assert (dst >= 0 && src >= 0 && dst < AARCH64_MAX_OPND_NUM
+ && src < AARCH64_MAX_OPND_NUM);
+ memcpy (&inst->operands[dst], &inst->operands[src],
+ sizeof (aarch64_opnd_info));
+ inst->operands[dst].idx = dst;
+}
+
+/* A primitive log caculator. */
+
+static inline unsigned int
+get_logsz (unsigned int size)
+{
+ const unsigned char ls[16] =
+ {0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4};
+ if (size > 16)
+ {
+ assert (0);
+ return -1;
+ }
+ assert (ls[size - 1] != (unsigned char)-1);
+ return ls[size - 1];
+}
+
+#endif /* OPCODES_AARCH64_OPC_H */
diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
new file mode 100644
index 0000000..d360b14
--- /dev/null
+++ b/opcodes/aarch64-tbl.h
@@ -0,0 +1,2253 @@
+/* aarch64-tbl.h -- AArch64 opcode description table and instruction
+ operand description table.
+ Copyright 2012 Free Software Foundation, Inc.
+
+ This file is part of the GNU opcodes library.
+
+ This library 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 3, or (at your option)
+ any later version.
+
+ It 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 file; see the file COPYING. If not, write to the
+ Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "aarch64-opc.h"
+
+/* Operand type. */
+
+#define OPND(x) AARCH64_OPND_##x
+#define OP0() {}
+#define OP1(a) {OPND(a)}
+#define OP2(a,b) {OPND(a), OPND(b)}
+#define OP3(a,b,c) {OPND(a), OPND(b), OPND(c)}
+#define OP4(a,b,c,d) {OPND(a), OPND(b), OPND(c), OPND(d)}
+#define OP5(a,b,c,d,e) {OPND(a), OPND(b), OPND(c), OPND(d), OPND(e)}
+
+#define QLF(x) AARCH64_OPND_QLF_##x
+#define QLF1(a) {QLF(a)}
+#define QLF2(a,b) {QLF(a), QLF(b)}
+#define QLF3(a,b,c) {QLF(a), QLF(b), QLF(c)}
+#define QLF4(a,b,c,d) {QLF(a), QLF(b), QLF(c), QLF(d)}
+#define QLF5(a,b,c,d,e) {QLF(a), QLF(b), QLF(c), QLF(d), QLF(e)}
+
+/* Qualifiers list. */
+
+/* e.g. MSR <systemreg>, <Xt>. */
+#define QL_SRC_X \
+{ \
+ QLF2(NIL,X), \
+}
+
+/* e.g. MRS <Xt>, <systemreg>. */
+#define QL_DST_X \
+{ \
+ QLF2(X,NIL), \
+}
+
+/* e.g. SYS #<op1>, <Cn>, <Cm>, #<op2>{, <Xt>}. */
+#define QL_SYS \
+{ \
+ QLF5(NIL,NIL,NIL,NIL,X), \
+}
+
+/* e.g. SYSL <Xt>, #<op1>, <Cn>, <Cm>, #<op2>. */
+#define QL_SYSL \
+{ \
+ QLF5(X,NIL,NIL,NIL,NIL), \
+}
+
+/* e.g. ADRP <Xd>, <label>. */
+#define QL_ADRP \
+{ \
+ QLF2(X,NIL), \
+}
+
+/* e.g. B.<cond> <label>. */
+#define QL_PCREL_NIL \
+{ \
+ QLF1(NIL), \
+}
+
+/* e.g. TBZ <Xt>, #<imm>, <label>. */
+#define QL_PCREL_14 \
+{ \
+ QLF3(X,imm_0_63,NIL), \
+}
+
+/* e.g. BL <label>. */
+#define QL_PCREL_26 \
+{ \
+ QLF1(NIL), \
+}
+
+/* e.g. LDRSW <Xt>, <label>. */
+#define QL_X_PCREL \
+{ \
+ QLF2(X,NIL), \
+}
+
+/* e.g. LDR <Wt>, <label>. */
+#define QL_R_PCREL \
+{ \
+ QLF2(W,NIL), \
+ QLF2(X,NIL), \
+}
+
+/* e.g. LDR <Dt>, <label>. */
+#define QL_FP_PCREL \
+{ \
+ QLF2(S_S,NIL), \
+ QLF2(S_D,NIL), \
+ QLF2(S_Q,NIL), \
+}
+
+/* e.g. PRFM <prfop>, <label>. */
+#define QL_PRFM_PCREL \
+{ \
+ QLF2(NIL,NIL), \
+}
+
+/* e.g. BR <Xn>. */
+#define QL_I1X \
+{ \
+ QLF1(X), \
+}
+
+/* e.g. RBIT <Wd>, <Wn>. */
+#define QL_I2SAME \
+{ \
+ QLF2(W,W), \
+ QLF2(X,X), \
+}
+
+/* e.g. CMN <Wn|WSP>, <Wm>{, <extend> {#<amount>}}. */
+#define QL_I2_EXT \
+{ \
+ QLF2(W,W), \
+ QLF2(X,W), \
+ QLF2(X,X), \
+}
+
+/* e.g. MOV <Wd|WSP>, <Wn|WSP>, at least one SP. */
+#define QL_I2SP \
+{ \
+ QLF2(WSP,W), \
+ QLF2(W,WSP), \
+ QLF2(SP,X), \
+ QLF2(X,SP), \
+}
+
+/* e.g. REV <Wd>, <Wn>. */
+#define QL_I2SAMEW \
+{ \
+ QLF2(W,W), \
+}
+
+/* e.g. REV32 <Xd>, <Xn>. */
+#define QL_I2SAMEX \
+{ \
+ QLF2(X,X), \
+}
+
+#define QL_I2SAMER \
+{ \
+ QLF2(W,W), \
+ QLF2(X,X), \
+}
+
+/* e.g. SMULH <Xd>, <Xn>, <Xm>. */
+#define QL_I3SAMEX \
+{ \
+ QLF3(X,X,X), \
+}
+
+/* e.g. UDIV <Xd>, <Xn>, <Xm>. */
+#define QL_I3SAMER \
+{ \
+ QLF3(W,W,W), \
+ QLF3(X,X,X), \
+}
+
+/* e.g. ADDS <Xd>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}. */
+#define QL_I3_EXT \
+{ \
+ QLF3(W,W,W), \
+ QLF3(X,X,W), \
+ QLF3(X,X,X), \
+}
+
+/* e.g. MADD <Xd>, <Xn>, <Xm>, <Xa>. */
+#define QL_I4SAMER \
+{ \
+ QLF4(W,W,W,W), \
+ QLF4(X,X,X,X), \
+}
+
+/* e.g. SMADDL <Xd>, <Wn>, <Wm>, <Xa>. */
+#define QL_I3SAMEL \
+{ \
+ QLF3(X,W,W), \
+}
+
+/* e.g. SMADDL <Xd>, <Wn>, <Wm>, <Xa>. */
+#define QL_I4SAMEL \
+{ \
+ QLF4(X,W,W,X), \
+}
+
+/* e.g. CSINC <Xd>, <Xn>, <Xm>, <cond>. */
+#define QL_CSEL \
+{ \
+ QLF4(W, W, W, NIL), \
+ QLF4(X, X, X, NIL), \
+}
+
+/* e.g. CSET <Wd>, <cond>. */
+#define QL_DST_R \
+{ \
+ QLF2(W, NIL), \
+ QLF2(X, NIL), \
+}
+
+/* e.g. BFM <Wd>, <Wn>, #<immr>, #<imms>. */
+#define QL_BF \
+{ \
+ QLF4(W,W,imm_0_31,imm_0_31), \
+ QLF4(X,X,imm_0_63,imm_0_63), \
+}
+
+/* e.g. UBFIZ <Wd>, <Wn>, #<lsb>, #<width>. */
+#define QL_BF2 \
+{ \
+ QLF4(W,W,imm_0_31,imm_1_32), \
+ QLF4(X,X,imm_0_63,imm_1_64), \
+}
+
+/* e.g. SCVTF <Sd>, <Xn>, #<fbits>. */
+#define QL_FIX2FP \
+{ \
+ QLF3(S_D,W,imm_1_32), \
+ QLF3(S_S,W,imm_1_32), \
+ QLF3(S_D,X,imm_1_64), \
+ QLF3(S_S,X,imm_1_64), \
+}
+
+/* e.g. FCVTZS <Wd>, <Dn>, #<fbits>. */
+#define QL_FP2FIX \
+{ \
+ QLF3(W,S_D,imm_1_32), \
+ QLF3(W,S_S,imm_1_32), \
+ QLF3(X,S_D,imm_1_64), \
+ QLF3(X,S_S,imm_1_64), \
+}
+
+/* e.g. SCVTF <Dd>, <Wn>. */
+#define QL_INT2FP \
+{ \
+ QLF2(S_D,W), \
+ QLF2(S_S,W), \
+ QLF2(S_D,X), \
+ QLF2(S_S,X), \
+}
+
+/* e.g. FCVTNS <Xd>, <Dn>. */
+#define QL_FP2INT \
+{ \
+ QLF2(W,S_D), \
+ QLF2(W,S_S), \
+ QLF2(X,S_D), \
+ QLF2(X,S_S), \
+}
+
+/* e.g. FMOV <Xd>, <Vn>.D[1]. */
+#define QL_XVD1 \
+{ \
+ QLF2(X,S_D), \
+}
+
+/* e.g. FMOV <Vd>.D[1], <Xn>. */
+#define QL_VD1X \
+{ \
+ QLF2(S_D,X), \
+}
+
+/* e.g. EXTR <Xd>, <Xn>, <Xm>, #<lsb>. */
+#define QL_EXTR \
+{ \
+ QLF4(W,W,W,imm_0_31), \
+ QLF4(X,X,X,imm_0_63), \
+}
+
+/* e.g. LSL <Wd>, <Wn>, #<uimm>. */
+#define QL_SHIFT \
+{ \
+ QLF3(W,W,imm_0_31), \
+ QLF3(X,X,imm_0_63), \
+}
+
+/* e.g. UXTH <Xd>, <Wn>. */
+#define QL_EXT \
+{ \
+ QLF2(W,W), \
+ QLF2(X,W), \
+}
+
+/* e.g. UXTW <Xd>, <Wn>. */
+#define QL_EXT_W \
+{ \
+ QLF2(X,W), \
+}
+
+/* e.g. SQSHL <V><d>, <V><n>, #<shift>. */
+#define QL_SSHIFT \
+{ \
+ QLF3(S_B , S_B , S_B ), \
+ QLF3(S_H , S_H , S_H ), \
+ QLF3(S_S , S_S , S_S ), \
+ QLF3(S_D , S_D , S_D ) \
+}
+
+/* e.g. SSHR <V><d>, <V><n>, #<shift>. */
+#define QL_SSHIFT_D \
+{ \
+ QLF3(S_D , S_D , S_D ) \
+}
+
+/* e.g. UCVTF <Vd>.<T>, <Vn>.<T>, #<fbits>. */
+#define QL_SSHIFT_SD \
+{ \
+ QLF3(S_S , S_S , S_S ), \
+ QLF3(S_D , S_D , S_D ) \
+}
+
+/* e.g. SQSHRUN <Vb><d>, <Va><n>, #<shift>. */
+#define QL_SSHIFTN \
+{ \
+ QLF3(S_B , S_H , S_B ), \
+ QLF3(S_H , S_S , S_H ), \
+ QLF3(S_S , S_D , S_S ), \
+}
+
+/* e.g. SSHR <Vd>.<T>, <Vn>.<T>, #<shift>.
+ The register operand variant qualifiers are deliberately used for the
+ immediate operand to ease the operand encoding/decoding and qualifier
+ sequence matching. */
+#define QL_VSHIFT \
+{ \
+ QLF3(V_8B , V_8B , V_8B ), \
+ QLF3(V_16B, V_16B, V_16B), \
+ QLF3(V_4H , V_4H , V_4H ), \
+ QLF3(V_8H , V_8H , V_8H ), \
+ QLF3(V_2S , V_2S , V_2S ), \
+ QLF3(V_4S , V_4S , V_4S ), \
+ QLF3(V_2D , V_2D , V_2D ) \
+}
+
+/* e.g. SCVTF <Vd>.<T>, <Vn>.<T>, #<fbits>. */
+#define QL_VSHIFT_SD \
+{ \
+ QLF3(V_2S , V_2S , V_2S ), \
+ QLF3(V_4S , V_4S , V_4S ), \
+ QLF3(V_2D , V_2D , V_2D ) \
+}
+
+/* e.g. SHRN<Q> <Vd>.<Tb>, <Vn>.<Ta>, #<shift>. */
+#define QL_VSHIFTN \
+{ \
+ QLF3(V_8B , V_8H , V_8B ), \
+ QLF3(V_4H , V_4S , V_4H ), \
+ QLF3(V_2S , V_2D , V_2S ), \
+}
+
+/* e.g. SHRN<Q> <Vd>.<Tb>, <Vn>.<Ta>, #<shift>. */
+#define QL_VSHIFTN2 \
+{ \
+ QLF3(V_16B, V_8H, V_16B), \
+ QLF3(V_8H , V_4S , V_8H ), \
+ QLF3(V_4S , V_2D , V_4S ), \
+}
+
+/* e.g. SSHLL<Q> <Vd>.<Ta>, <Vn>.<Tb>, #<shift>.
+ the 3rd qualifier is used to help the encoding. */
+#define QL_VSHIFTL \
+{ \
+ QLF3(V_8H , V_8B , V_8B ), \
+ QLF3(V_4S , V_4H , V_4H ), \
+ QLF3(V_2D , V_2S , V_2S ), \
+}
+
+/* e.g. SSHLL<Q> <Vd>.<Ta>, <Vn>.<Tb>, #<shift>. */
+#define QL_VSHIFTL2 \
+{ \
+ QLF3(V_8H , V_16B, V_16B), \
+ QLF3(V_4S , V_8H , V_8H ), \
+ QLF3(V_2D , V_4S , V_4S ), \
+}
+
+/* e.g. TBL. */
+#define QL_TABLE \
+{ \
+ QLF3(V_8B , V_16B, V_8B ), \
+ QLF3(V_16B, V_16B, V_16B), \
+}
+
+/* e.g. SHA1H. */
+#define QL_2SAMES \
+{ \
+ QLF2(S_S, S_S), \
+}
+
+/* e.g. ABS <V><d>, <V><n>. */
+#define QL_2SAMED \
+{ \
+ QLF2(S_D, S_D), \
+}
+
+/* e.g. CMGT <V><d>, <V><n>, #0. */
+#define QL_SISD_CMP_0 \
+{ \
+ QLF3(S_D, S_D, NIL), \
+}
+
+/* e.g. FCMEQ <V><d>, <V><n>, #0. */
+#define QL_SISD_FCMP_0 \
+{ \
+ QLF3(S_S, S_S, NIL), \
+ QLF3(S_D, S_D, NIL), \
+}
+
+/* e.g. FMAXNMP <V><d>, <Vn>.<T>. */
+#define QL_SISD_PAIR \
+{ \
+ QLF2(S_S, V_2S), \
+ QLF2(S_D, V_2D), \
+}
+
+/* e.g. ADDP <V><d>, <Vn>.<T>. */
+#define QL_SISD_PAIR_D \
+{ \
+ QLF2(S_D, V_2D), \
+}
+
+/* e.g. DUP <V><d>, <Vn>.<T>[<index>]. */
+#define QL_S_2SAME \
+{ \
+ QLF2(S_B, S_B), \
+ QLF2(S_H, S_H), \
+ QLF2(S_S, S_S), \
+ QLF2(S_D, S_D), \
+}
+
+/* e.g. FCVTNS <V><d>, <V><n>. */
+#define QL_S_2SAMESD \
+{ \
+ QLF2(S_S, S_S), \
+ QLF2(S_D, S_D), \
+}
+
+/* e.g. SQXTN <Vb><d>, <Va><n>. */
+#define QL_SISD_NARROW \
+{ \
+ QLF2(S_B, S_H), \
+ QLF2(S_H, S_S), \
+ QLF2(S_S, S_D), \
+}
+
+/* e.g. FCVTXN <Vb><d>, <Va><n>. */
+#define QL_SISD_NARROW_S \
+{ \
+ QLF2(S_S, S_D), \
+}
+
+/* e.g. FCVT. */
+#define QL_FCVT \
+{ \
+ QLF2(S_S, S_H), \
+ QLF2(S_S, S_D), \
+ QLF2(S_D, S_H), \
+ QLF2(S_D, S_S), \
+ QLF2(S_H, S_S), \
+ QLF2(S_H, S_D), \
+}
+
+/* FMOV <Dd>, <Dn>. */
+#define QL_FP2 \
+{ \
+ QLF2(S_S, S_S), \
+ QLF2(S_D, S_D), \
+}
+
+/* e.g. SQADD <V><d>, <V><n>, <V><m>. */
+#define QL_S_3SAME \
+{ \
+ QLF3(S_B, S_B, S_B), \
+ QLF3(S_H, S_H, S_H), \
+ QLF3(S_S, S_S, S_S), \
+ QLF3(S_D, S_D, S_D), \
+}
+
+/* e.g. CMGE <V><d>, <V><n>, <V><m>. */
+#define QL_S_3SAMED \
+{ \
+ QLF3(S_D, S_D, S_D), \
+}
+
+/* e.g. SQDMULH <V><d>, <V><n>, <V><m>. */
+#define QL_SISD_HS \
+{ \
+ QLF3(S_H, S_H, S_H), \
+ QLF3(S_S, S_S, S_S), \
+}
+
+/* e.g. SQDMLAL <Va><d>, <Vb><n>, <Vb><m>. */
+#define QL_SISDL_HS \
+{ \
+ QLF3(S_S, S_H, S_H), \
+ QLF3(S_D, S_S, S_S), \
+}
+
+/* FMUL <Sd>, <Sn>, <Sm>. */
+#define QL_FP3 \
+{ \
+ QLF3(S_S, S_S, S_S), \
+ QLF3(S_D, S_D, S_D), \
+}
+
+/* FMADD <Dd>, <Dn>, <Dm>, <Da>. */
+#define QL_FP4 \
+{ \
+ QLF4(S_S, S_S, S_S, S_S), \
+ QLF4(S_D, S_D, S_D, S_D), \
+}
+
+/* e.g. FCMP <Dn>, #0.0. */
+#define QL_DST_SD \
+{ \
+ QLF2(S_S, NIL), \
+ QLF2(S_D, NIL), \
+}
+
+/* FCSEL <Sd>, <Sn>, <Sm>, <cond>. */
+#define QL_FP_COND \
+{ \
+ QLF4(S_S, S_S, S_S, NIL), \
+ QLF4(S_D, S_D, S_D, NIL), \
+}
+
+/* e.g. CCMN <Xn>, <Xm>, #<nzcv>, <cond>. */
+#define QL_CCMP \
+{ \
+ QLF4(W, W, NIL, NIL), \
+ QLF4(X, X, NIL, NIL), \
+}
+
+/* e.g. CCMN <Xn>, #<imm>, #<nzcv>, <cond>, */
+#define QL_CCMP_IMM \
+{ \
+ QLF4(W, NIL, NIL, NIL), \
+ QLF4(X, NIL, NIL, NIL), \
+}
+
+/* e.g. FCCMP <Sn>, <Sm>, #<nzcv>, <cond>. */
+#define QL_FCCMP \
+{ \
+ QLF4(S_S, S_S, NIL, NIL), \
+ QLF4(S_D, S_D, NIL, NIL), \
+}
+
+/* e.g. DUP <Vd>.<T>, <Vn>.<Ts>[<index>]. */
+#define QL_DUP_VX \
+{ \
+ QLF2(V_8B , S_B ), \
+ QLF2(V_16B, S_B ), \
+ QLF2(V_4H , S_H ), \
+ QLF2(V_8H , S_H ), \
+ QLF2(V_2S , S_S ), \
+ QLF2(V_4S , S_S ), \
+ QLF2(V_2D , S_D ), \
+}
+
+/* e.g. DUP <Vd>.<T>, <Wn>. */
+#define QL_DUP_VR \
+{ \
+ QLF2(V_8B , W ), \
+ QLF2(V_16B, W ), \
+ QLF2(V_4H , W ), \
+ QLF2(V_8H , W ), \
+ QLF2(V_2S , W ), \
+ QLF2(V_4S , W ), \
+ QLF2(V_2D , X ), \
+}
+
+/* e.g. INS <Vd>.<Ts>[<index>], <Wn>. */
+#define QL_INS_XR \
+{ \
+ QLF2(S_H , W ), \
+ QLF2(S_S , W ), \
+ QLF2(S_D , X ), \
+ QLF2(S_B , W ), \
+}
+
+/* e.g. SMOV <Wd>, <Vn>.<Ts>[<index>]. */
+#define QL_SMOV \
+{ \
+ QLF2(W , S_H), \
+ QLF2(X , S_H), \
+ QLF2(X , S_S), \
+ QLF2(W , S_B), \
+ QLF2(X , S_B), \
+}
+
+/* e.g. UMOV <Wd>, <Vn>.<Ts>[<index>]. */
+#define QL_UMOV \
+{ \
+ QLF2(W , S_H), \
+ QLF2(W , S_S), \
+ QLF2(X , S_D), \
+ QLF2(W , S_B), \
+}
+
+/* e.g. MOV <Wd>, <Vn>.<Ts>[<index>]. */
+#define QL_MOV \
+{ \
+ QLF2(W , S_S), \
+ QLF2(X , S_D), \
+}
+
+/* e.g. SUQADD <Vd>.<T>, <Vn>.<T>. */
+#define QL_V2SAME \
+{ \
+ QLF2(V_8B , V_8B ), \
+ QLF2(V_16B, V_16B), \
+ QLF2(V_4H , V_4H ), \
+ QLF2(V_8H , V_8H ), \
+ QLF2(V_2S , V_2S ), \
+ QLF2(V_4S , V_4S ), \
+ QLF2(V_2D , V_2D ), \
+}
+
+/* e.g. URSQRTE <Vd>.<T>, <Vn>.<T>. */
+#define QL_V2SAMES \
+{ \
+ QLF2(V_2S , V_2S ), \
+ QLF2(V_4S , V_4S ), \
+}
+
+/* e.g. REV32 <Vd>.<T>, <Vn>.<T>. */
+#define QL_V2SAMEBH \
+{ \
+ QLF2(V_8B , V_8B ), \
+ QLF2(V_16B, V_16B), \
+ QLF2(V_4H , V_4H ), \
+ QLF2(V_8H , V_8H ), \
+}
+
+/* e.g. FRINTN <Vd>.<T>, <Vn>.<T>. */
+#define QL_V2SAMESD \
+{ \
+ QLF2(V_2S , V_2S ), \
+ QLF2(V_4S , V_4S ), \
+ QLF2(V_2D , V_2D ), \
+}
+
+/* e.g. REV64 <Vd>.<T>, <Vn>.<T>. */
+#define QL_V2SAMEBHS \
+{ \
+ QLF2(V_8B , V_8B ), \
+ QLF2(V_16B, V_16B), \
+ QLF2(V_4H , V_4H ), \
+ QLF2(V_8H , V_8H ), \
+ QLF2(V_2S , V_2S ), \
+ QLF2(V_4S , V_4S ), \
+}
+
+/* e.g. REV16 <Vd>.<T>, <Vn>.<T>. */
+#define QL_V2SAMEB \
+{ \
+ QLF2(V_8B , V_8B ), \
+ QLF2(V_16B, V_16B), \
+}
+
+/* e.g. SADDLP <Vd>.<Ta>, <Vn>.<Tb>. */
+#define QL_V2PAIRWISELONGBHS \
+{ \
+ QLF2(V_4H , V_8B ), \
+ QLF2(V_8H , V_16B), \
+ QLF2(V_2S , V_4H ), \
+ QLF2(V_4S , V_8H ), \
+ QLF2(V_1D , V_2S ), \
+ QLF2(V_2D , V_4S ), \
+}
+
+/* e.g. SHLL<Q> <Vd>.<Ta>, <Vn>.<Tb>, #<shift>. */
+#define QL_V2LONGBHS \
+{ \
+ QLF2(V_8H , V_8B ), \
+ QLF2(V_4S , V_4H ), \
+ QLF2(V_2D , V_2S ), \
+}
+
+/* e.g. SHLL<Q> <Vd>.<Ta>, <Vn>.<Tb>, #<shift>. */
+#define QL_V2LONGBHS2 \
+{ \
+ QLF2(V_8H , V_16B), \
+ QLF2(V_4S , V_8H ), \
+ QLF2(V_2D , V_4S ), \
+}
+
+/* */
+#define QL_V3SAME \
+{ \
+ QLF3(V_8B , V_8B , V_8B ), \
+ QLF3(V_16B, V_16B, V_16B), \
+ QLF3(V_4H , V_4H , V_4H ), \
+ QLF3(V_8H , V_8H , V_8H ), \
+ QLF3(V_2S , V_2S , V_2S ), \
+ QLF3(V_4S , V_4S , V_4S ), \
+ QLF3(V_2D , V_2D , V_2D ) \
+}
+
+/* e.g. SHADD. */
+#define QL_V3SAMEBHS \
+{ \
+ QLF3(V_8B , V_8B , V_8B ), \
+ QLF3(V_16B, V_16B, V_16B), \
+ QLF3(V_4H , V_4H , V_4H ), \
+ QLF3(V_8H , V_8H , V_8H ), \
+ QLF3(V_2S , V_2S , V_2S ), \
+ QLF3(V_4S , V_4S , V_4S ), \
+}
+
+/* e.g. FCVTXN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
+#define QL_V2NARRS \
+{ \
+ QLF2(V_2S , V_2D ), \
+}
+
+/* e.g. FCVTXN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
+#define QL_V2NARRS2 \
+{ \
+ QLF2(V_4S , V_2D ), \
+}
+
+/* e.g. FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
+#define QL_V2NARRHS \
+{ \
+ QLF2(V_4H , V_4S ), \
+ QLF2(V_2S , V_2D ), \
+}
+
+/* e.g. FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
+#define QL_V2NARRHS2 \
+{ \
+ QLF2(V_8H , V_4S ), \
+ QLF2(V_4S , V_2D ), \
+}
+
+/* e.g. FCVTL<Q> <Vd>.<Ta>, <Vn>.<Tb>. */
+#define QL_V2LONGHS \
+{ \
+ QLF2(V_4S , V_4H ), \
+ QLF2(V_2D , V_2S ), \
+}
+
+/* e.g. FCVTL<Q> <Vd>.<Ta>, <Vn>.<Tb>. */
+#define QL_V2LONGHS2 \
+{ \
+ QLF2(V_4S , V_8H ), \
+ QLF2(V_2D , V_4S ), \
+}
+
+/* e.g. XTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
+#define QL_V2NARRBHS \
+{ \
+ QLF2(V_8B , V_8H ), \
+ QLF2(V_4H , V_4S ), \
+ QLF2(V_2S , V_2D ), \
+}
+
+/* e.g. XTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
+#define QL_V2NARRBHS2 \
+{ \
+ QLF2(V_16B, V_8H ), \
+ QLF2(V_8H , V_4S ), \
+ QLF2(V_4S , V_2D ), \
+}
+
+/* e.g. ORR. */
+#define QL_V2SAMEB \
+{ \
+ QLF2(V_8B , V_8B ), \
+ QLF2(V_16B, V_16B), \
+}
+
+/* e.g. AESE. */
+#define QL_V2SAME16B \
+{ \
+ QLF2(V_16B, V_16B), \
+}
+
+/* e.g. SHA1SU1. */
+#define QL_V2SAME4S \
+{ \
+ QLF2(V_4S, V_4S), \
+}
+
+/* e.g. SHA1SU0. */
+#define QL_V3SAME4S \
+{ \
+ QLF3(V_4S, V_4S, V_4S), \
+}
+
+/* e.g. SHADD. */
+#define QL_V3SAMEB \
+{ \
+ QLF3(V_8B , V_8B , V_8B ), \
+ QLF3(V_16B, V_16B, V_16B), \
+}
+
+/* e.g. EXT <Vd>.<T>, <Vn>.<T>, <Vm>.<T>, #<index>. */
+#define QL_VEXT \
+{ \
+ QLF4(V_8B , V_8B , V_8B , imm_0_7), \
+ QLF4(V_16B, V_16B, V_16B, imm_0_15), \
+}
+
+/* e.g. . */
+#define QL_V3SAMEHS \
+{ \
+ QLF3(V_4H , V_4H , V_4H ), \
+ QLF3(V_8H , V_8H , V_8H ), \
+ QLF3(V_2S , V_2S , V_2S ), \
+ QLF3(V_4S , V_4S , V_4S ), \
+}
+
+/* */
+#define QL_V3SAMESD \
+{ \
+ QLF3(V_2S , V_2S , V_2S ), \
+ QLF3(V_4S , V_4S , V_4S ), \
+ QLF3(V_2D , V_2D , V_2D ) \
+}
+
+/* e.g. SQDMLAL<Q> <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>. */
+#define QL_V3LONGHS \
+{ \
+ QLF3(V_4S , V_4H , V_4H ), \
+ QLF3(V_2D , V_2S , V_2S ), \
+}
+
+/* e.g. SQDMLAL<Q> <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>. */
+#define QL_V3LONGHS2 \
+{ \
+ QLF3(V_4S , V_8H , V_8H ), \
+ QLF3(V_2D , V_4S , V_4S ), \
+}
+
+/* e.g. SADDL<Q> <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>. */
+#define QL_V3LONGBHS \
+{ \
+ QLF3(V_8H , V_8B , V_8B ), \
+ QLF3(V_4S , V_4H , V_4H ), \
+ QLF3(V_2D , V_2S , V_2S ), \
+}
+
+/* e.g. SADDL<Q> <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>. */
+#define QL_V3LONGBHS2 \
+{ \
+ QLF3(V_8H , V_16B , V_16B ), \
+ QLF3(V_4S , V_8H , V_8H ), \
+ QLF3(V_2D , V_4S , V_4S ), \
+}
+
+/* e.g. SADDW<Q> <Vd>.<Ta>, <Vn>.<Ta>, <Vm>.<Tb>. */
+#define QL_V3WIDEBHS \
+{ \
+ QLF3(V_8H , V_8H , V_8B ), \
+ QLF3(V_4S , V_4S , V_4H ), \
+ QLF3(V_2D , V_2D , V_2S ), \
+}
+
+/* e.g. SADDW<Q> <Vd>.<Ta>, <Vn>.<Ta>, <Vm>.<Tb>. */
+#define QL_V3WIDEBHS2 \
+{ \
+ QLF3(V_8H , V_8H , V_16B ), \
+ QLF3(V_4S , V_4S , V_8H ), \
+ QLF3(V_2D , V_2D , V_4S ), \
+}
+
+/* e.g. ADDHN<Q> <Vd>.<Tb>, <Vn>.<Ta>, <Vm>.<Ta>. */
+#define QL_V3NARRBHS \
+{ \
+ QLF3(V_8B , V_8H , V_8H ), \
+ QLF3(V_4H , V_4S , V_4S ), \
+ QLF3(V_2S , V_2D , V_2D ), \
+}
+
+/* e.g. ADDHN<Q> <Vd>.<Tb>, <Vn>.<Ta>, <Vm>.<Ta>. */
+#define QL_V3NARRBHS2 \
+{ \
+ QLF3(V_16B , V_8H , V_8H ), \
+ QLF3(V_8H , V_4S , V_4S ), \
+ QLF3(V_4S , V_2D , V_2D ), \
+}
+
+/* e.g. PMULL. */
+#define QL_V3LONGB \
+{ \
+ QLF3(V_8H , V_8B , V_8B ), \
+}
+
+/* e.g. PMULL crypto. */
+#define QL_V3LONGD \
+{ \
+ QLF3(V_1Q , V_1D , V_1D ), \
+}
+
+/* e.g. PMULL2. */
+#define QL_V3LONGB2 \
+{ \
+ QLF3(V_8H , V_16B, V_16B), \
+}
+
+/* e.g. PMULL2 crypto. */
+#define QL_V3LONGD2 \
+{ \
+ QLF3(V_1Q , V_2D , V_2D ), \
+}
+
+/* e.g. SHA1C. */
+#define QL_SHAUPT \
+{ \
+ QLF3(S_Q, S_S, V_4S), \
+}
+
+/* e.g. SHA256H2. */
+#define QL_SHA256UPT \
+{ \
+ QLF3(S_Q, S_Q, V_4S), \
+}
+
+/* e.g. LDXRB <Wt>, [<Xn|SP>{,#0}]. */
+#define QL_W1_LDST_EXC \
+{ \
+ QLF2(W, NIL), \
+}
+
+/* e.g. LDXR <Xt>, [<Xn|SP>{,#0}]. */
+#define QL_R1NIL \
+{ \
+ QLF2(W, NIL), \
+ QLF2(X, NIL), \
+}
+
+/* e.g. STXRB <Ws>, <Wt>, [<Xn|SP>{,#0}]. */
+#define QL_W2_LDST_EXC \
+{ \
+ QLF3(W, W, NIL), \
+}
+
+/* e.g. STXR <Ws>, <Xt>, [<Xn|SP>{,#0}]. */
+#define QL_R2_LDST_EXC \
+{ \
+ QLF3(W, W, NIL), \
+ QLF3(W, X, NIL), \
+}
+
+/* e.g. LDXP <Xt1>, <Xt2>, [<Xn|SP>{,#0}]. */
+#define QL_R2NIL \
+{ \
+ QLF3(W, W, NIL), \
+ QLF3(X, X, NIL), \
+}
+
+/* e.g. STXP <Ws>, <Xt1>, <Xt2>, [<Xn|SP>{,#0}]. */
+#define QL_R3_LDST_EXC \
+{ \
+ QLF4(W, W, W, NIL), \
+ QLF4(W, X, X, NIL), \
+}
+
+/* e.g. STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
+#define QL_LDST_FP \
+{ \
+ QLF2(S_B, S_B), \
+ QLF2(S_H, S_H), \
+ QLF2(S_S, S_S), \
+ QLF2(S_D, S_D), \
+ QLF2(S_Q, S_Q), \
+}
+
+/* e.g. STR <Xt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
+#define QL_LDST_R \
+{ \
+ QLF2(W, S_S), \
+ QLF2(X, S_D), \
+}
+
+/* e.g. STRB <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
+#define QL_LDST_W8 \
+{ \
+ QLF2(W, S_B), \
+}
+
+/* e.g. LDRSB <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
+#define QL_LDST_R8 \
+{ \
+ QLF2(W, S_B), \
+ QLF2(X, S_B), \
+}
+
+/* e.g. STRH <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
+#define QL_LDST_W16 \
+{ \
+ QLF2(W, S_H), \
+}
+
+/* e.g. LDRSW <Xt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
+#define QL_LDST_X32 \
+{ \
+ QLF2(X, S_S), \
+}
+
+/* e.g. LDRSH <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
+#define QL_LDST_R16 \
+{ \
+ QLF2(W, S_H), \
+ QLF2(X, S_H), \
+}
+
+/* e.g. PRFM <prfop>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
+#define QL_LDST_PRFM \
+{ \
+ QLF2(NIL, S_D), \
+}
+
+/* e.g. LDPSW <Xt1>, <Xt2>, [<Xn|SP>{, #<imm>}]. */
+#define QL_LDST_PAIR_X32 \
+{ \
+ QLF3(X, X, S_S), \
+}
+
+/* e.g. STP <Wt1>, <Wt2>, [<Xn|SP>, #<imm>]!. */
+#define QL_LDST_PAIR_R \
+{ \
+ QLF3(W, W, S_S), \
+ QLF3(X, X, S_D), \
+}
+
+/* e.g. STNP <Qt1>, <Qt2>, [<Xn|SP>{, #<imm>}]. */
+#define QL_LDST_PAIR_FP \
+{ \
+ QLF3(S_S, S_S, S_S), \
+ QLF3(S_D, S_D, S_D), \
+ QLF3(S_Q, S_Q, S_Q), \
+}
+
+/* e.g. LD3 {<Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>}, [<Xn|SP>]. */
+#define QL_SIMD_LDST \
+{ \
+ QLF2(V_8B, NIL), \
+ QLF2(V_16B, NIL), \
+ QLF2(V_4H, NIL), \
+ QLF2(V_8H, NIL), \
+ QLF2(V_2S, NIL), \
+ QLF2(V_4S, NIL), \
+ QLF2(V_2D, NIL), \
+}
+
+/* e.g. LD1 {<Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>}, [<Xn|SP>]. */
+#define QL_SIMD_LDST_ANY \
+{ \
+ QLF2(V_8B, NIL), \
+ QLF2(V_16B, NIL), \
+ QLF2(V_4H, NIL), \
+ QLF2(V_8H, NIL), \
+ QLF2(V_2S, NIL), \
+ QLF2(V_4S, NIL), \
+ QLF2(V_1D, NIL), \
+ QLF2(V_2D, NIL), \
+}
+
+/* e.g. LD4 {<Vt>.<T>, <Vt2a>.<T>, <Vt3a>.<T>, <Vt4a>.<T>}[<index>], [<Xn|SP>]. */
+#define QL_SIMD_LDSTONE \
+{ \
+ QLF2(S_B, NIL), \
+ QLF2(S_H, NIL), \
+ QLF2(S_S, NIL), \
+ QLF2(S_D, NIL), \
+}
+
+/* e.g. ADDV <V><d>, <Vn>.<T>. */
+#define QL_XLANES \
+{ \
+ QLF2(S_B, V_8B), \
+ QLF2(S_B, V_16B), \
+ QLF2(S_H, V_4H), \
+ QLF2(S_H, V_8H), \
+ QLF2(S_S, V_4S), \
+}
+
+/* e.g. FMINV <V><d>, <Vn>.<T>. */
+#define QL_XLANES_FP \
+{ \
+ QLF2(S_S, V_4S), \
+}
+
+/* e.g. SADDLV <V><d>, <Vn>.<T>. */
+#define QL_XLANES_L \
+{ \
+ QLF2(S_H, V_8B), \
+ QLF2(S_H, V_16B), \
+ QLF2(S_S, V_4H), \
+ QLF2(S_S, V_8H), \
+ QLF2(S_D, V_4S), \
+}
+
+/* e.g. MUL <Vd>.<T>, <Vn>.<T>, <Vm>.<Ts>[<index>]. */
+#define QL_ELEMENT \
+{ \
+ QLF3(V_4H, V_4H, S_H), \
+ QLF3(V_8H, V_8H, S_H), \
+ QLF3(V_2S, V_2S, S_S), \
+ QLF3(V_4S, V_4S, S_S), \
+}
+
+/* e.g. SMLAL <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Ts>[<index>]. */
+#define QL_ELEMENT_L \
+{ \
+ QLF3(V_4S, V_4H, S_H), \
+ QLF3(V_2D, V_2S, S_S), \
+}
+
+/* e.g. SMLAL2 <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Ts>[<index>]. */
+#define QL_ELEMENT_L2 \
+{ \
+ QLF3(V_4S, V_8H, S_H), \
+ QLF3(V_2D, V_4S, S_S), \
+}
+
+/* e.g. FMLA <V><d>, <V><n>, <Vm>.<Ts>[<index>]. */
+#define QL_ELEMENT_FP \
+{ \
+ QLF3(V_2S, V_2S, S_S), \
+ QLF3(V_4S, V_4S, S_S), \
+ QLF3(V_2D, V_2D, S_D), \
+}
+
+/* e.g. MOVI <Vd>.4S, #<imm8> {, LSL #<amount>}. */
+#define QL_SIMD_IMM_S0W \
+{ \
+ QLF2(V_2S, LSL), \
+ QLF2(V_4S, LSL), \
+}
+
+/* e.g. MOVI <Vd>.4S, #<imm8>, MSL #<amount>. */
+#define QL_SIMD_IMM_S1W \
+{ \
+ QLF2(V_2S, MSL), \
+ QLF2(V_4S, MSL), \
+}
+
+/* e.g. MOVI <Vd>.4H, #<imm8> {, LSL #<amount>}. */
+#define QL_SIMD_IMM_S0H \
+{ \
+ QLF2(V_4H, LSL), \
+ QLF2(V_8H, LSL), \
+}
+
+/* e.g. FMOV <Vd>.<T>, #<imm>. */
+#define QL_SIMD_IMM_S \
+{ \
+ QLF2(V_2S, NIL), \
+ QLF2(V_4S, NIL), \
+}
+
+/* e.g. MOVI <Vd>.8B, #<imm8>. */
+#define QL_SIMD_IMM_B \
+{ \
+ QLF2(V_8B, NIL), \
+ QLF2(V_16B, NIL), \
+}
+/* e.g. MOVI <Dd>, #<imm>. */
+#define QL_SIMD_IMM_D \
+{ \
+ QLF2(S_D, NIL), \
+}
+
+/* e.g. MOVI <Vd>.2D, #<imm>. */
+#define QL_SIMD_IMM_V2D \
+{ \
+ QLF2(V_2D, NIL), \
+}
+
+/* Opcode table. */
+
+static const aarch64_feature_set aarch64_feature_v8 =
+ AARCH64_FEATURE (AARCH64_FEATURE_V8, 0);
+static const aarch64_feature_set aarch64_feature_fp =
+ AARCH64_FEATURE (AARCH64_FEATURE_FP, 0);
+static const aarch64_feature_set aarch64_feature_simd =
+ AARCH64_FEATURE (AARCH64_FEATURE_SIMD, 0);
+static const aarch64_feature_set aarch64_feature_crypto =
+ AARCH64_FEATURE (AARCH64_FEATURE_CRYPTO, 0);
+
+#define CORE &aarch64_feature_v8
+#define FP &aarch64_feature_fp
+#define SIMD &aarch64_feature_simd
+#define CRYPTO &aarch64_feature_crypto
+
+struct aarch64_opcode aarch64_opcode_table[] =
+{
+ /* Add/subtract (with carry). */
+ {"adc", 0x1a000000, 0x7fe0fc00, addsub_carry, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMER, F_SF},
+ {"adcs", 0x3a000000, 0x7fe0fc00, addsub_carry, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMER, F_SF},
+ {"sbc", 0x5a000000, 0x7fe0fc00, addsub_carry, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMER, F_HAS_ALIAS | F_SF},
+ {"ngc", 0x5a0003e0, 0x7fe0ffe0, addsub_carry, 0, CORE, OP2 (Rd, Rm), QL_I2SAME, F_ALIAS | F_SF},
+ {"sbcs", 0x7a000000, 0x7fe0fc00, addsub_carry, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMER, F_HAS_ALIAS | F_SF},
+ {"ngcs", 0x7a0003e0, 0x7fe0ffe0, addsub_carry, 0, CORE, OP2 (Rd, Rm), QL_I2SAME, F_ALIAS | F_SF},
+ /* Add/subtract (extended register). */
+ {"add", 0x0b200000, 0x7fe00000, addsub_ext, 0, CORE, OP3 (Rd_SP, Rn_SP, Rm_EXT), QL_I3_EXT, F_SF},
+ {"adds", 0x2b200000, 0x7fe00000, addsub_ext, 0, CORE, OP3 (Rd, Rn_SP, Rm_EXT), QL_I3_EXT, F_HAS_ALIAS | F_SF},
+ {"cmn", 0x2b20001f, 0x7fe0001f, addsub_ext, 0, CORE, OP2 (Rn_SP, Rm_EXT), QL_I2_EXT, F_ALIAS | F_SF},
+ {"sub", 0x4b200000, 0x7fe00000, addsub_ext, 0, CORE, OP3 (Rd_SP, Rn_SP, Rm_EXT), QL_I3_EXT, F_SF},
+ {"subs", 0x6b200000, 0x7fe00000, addsub_ext, 0, CORE, OP3 (Rd, Rn_SP, Rm_EXT), QL_I3_EXT, F_HAS_ALIAS | F_SF},
+ {"cmp", 0x6b20001f, 0x7fe0001f, addsub_ext, 0, CORE, OP2 (Rn_SP, Rm_EXT), QL_I2_EXT, F_ALIAS | F_SF},
+ /* Add/subtract (immediate). */
+ {"add", 0x11000000, 0x7f000000, addsub_imm, OP_ADD, CORE, OP3 (Rd_SP, Rn_SP, AIMM), QL_R2NIL, F_HAS_ALIAS | F_SF},
+ {"mov", 0x11000000, 0x7ffffc00, addsub_imm, 0, CORE, OP2 (Rd_SP, Rn_SP), QL_I2SP, F_ALIAS | F_SF},
+ {"adds", 0x31000000, 0x7f000000, addsub_imm, 0, CORE, OP3 (Rd, Rn_SP, AIMM), QL_R2NIL, F_HAS_ALIAS | F_SF},
+ {"cmn", 0x3100001f, 0x7f00001f, addsub_imm, 0, CORE, OP2 (Rn_SP, AIMM), QL_R1NIL, F_ALIAS | F_SF},
+ {"sub", 0x51000000, 0x7f000000, addsub_imm, 0, CORE, OP3 (Rd_SP, Rn_SP, AIMM), QL_R2NIL, F_SF},
+ {"subs", 0x71000000, 0x7f000000, addsub_imm, 0, CORE, OP3 (Rd, Rn_SP, AIMM), QL_R2NIL, F_HAS_ALIAS | F_SF},
+ {"cmp", 0x7100001f, 0x7f00001f, addsub_imm, 0, CORE, OP2 (Rn_SP, AIMM), QL_R1NIL, F_ALIAS | F_SF},
+ /* Add/subtract (shifted register). */
+ {"add", 0xb000000, 0x7f200000, addsub_shift, 0, CORE, OP3 (Rd, Rn, Rm_SFT), QL_I3SAMER, F_SF},
+ {"adds", 0x2b000000, 0x7f200000, addsub_shift, 0, CORE, OP3 (Rd, Rn, Rm_SFT), QL_I3SAMER, F_HAS_ALIAS | F_SF},
+ {"cmn", 0x2b00001f, 0x7f20001f, addsub_shift, 0, CORE, OP2 (Rn, Rm_SFT), QL_I2SAME, F_ALIAS | F_SF},
+ {"sub", 0x4b000000, 0x7f200000, addsub_shift, 0, CORE, OP3 (Rd, Rn, Rm_SFT), QL_I3SAMER, F_HAS_ALIAS | F_SF},
+ {"neg", 0x4b0003e0, 0x7f2003e0, addsub_shift, 0, CORE, OP2 (Rd, Rm_SFT), QL_I2SAME, F_ALIAS | F_SF},
+ {"subs", 0x6b000000, 0x7f200000, addsub_shift, 0, CORE, OP3 (Rd, Rn, Rm_SFT), QL_I3SAMER, F_HAS_ALIAS | F_SF},
+ {"cmp", 0x6b00001f, 0x7f20001f, addsub_shift, 0, CORE, OP2 (Rn, Rm_SFT), QL_I2SAME, F_ALIAS | F_SF},
+ {"negs", 0x6b0003e0, 0x7f2003e0, addsub_shift, 0, CORE, OP2 (Rd, Rm_SFT), QL_I2SAME, F_ALIAS | F_SF},
+ /* AdvSIMD across lanes. */
+ {"saddlv", 0xe303800, 0xbf3ffc00, asimdall, 0, SIMD, OP2 (Fd, Vn), QL_XLANES_L, F_SIZEQ},
+ {"smaxv", 0xe30a800, 0xbf3ffc00, asimdall, 0, SIMD, OP2 (Fd, Vn), QL_XLANES, F_SIZEQ},
+ {"sminv", 0xe31a800, 0xbf3ffc00, asimdall, 0, SIMD, OP2 (Fd, Vn), QL_XLANES, F_SIZEQ},
+ {"addv", 0xe31b800, 0xbf3ffc00, asimdall, 0, SIMD, OP2 (Fd, Vn), QL_XLANES, F_SIZEQ},
+ {"uaddlv", 0x2e303800, 0xbf3ffc00, asimdall, 0, SIMD, OP2 (Fd, Vn), QL_XLANES_L, F_SIZEQ},
+ {"umaxv", 0x2e30a800, 0xbf3ffc00, asimdall, 0, SIMD, OP2 (Fd, Vn), QL_XLANES, F_SIZEQ},
+ {"uminv", 0x2e31a800, 0xbf3ffc00, asimdall, 0, SIMD, OP2 (Fd, Vn), QL_XLANES, F_SIZEQ},
+ {"fmaxnmv", 0x2e30c800, 0xbfbffc00, asimdall, 0, SIMD, OP2 (Fd, Vn), QL_XLANES_FP, F_SIZEQ},
+ {"fmaxv", 0x2e30f800, 0xbfbffc00, asimdall, 0, SIMD, OP2 (Fd, Vn), QL_XLANES_FP, F_SIZEQ},
+ {"fminnmv", 0x2eb0c800, 0xbfbffc00, asimdall, 0, SIMD, OP2 (Fd, Vn), QL_XLANES_FP, F_SIZEQ},
+ {"fminv", 0x2eb0f800, 0xbfbffc00, asimdall, 0, SIMD, OP2 (Fd, Vn), QL_XLANES_FP, F_SIZEQ},
+ /* AdvSIMD three different. */
+ {"saddl", 0x0e200000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS, F_SIZEQ},
+ {"saddl2", 0x4e200000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS2, F_SIZEQ},
+ {"saddw", 0x0e201000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3WIDEBHS, F_SIZEQ},
+ {"saddw2", 0x4e201000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3WIDEBHS2, F_SIZEQ},
+ {"ssubl", 0x0e202000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS, F_SIZEQ},
+ {"ssubl2", 0x4e202000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS2, F_SIZEQ},
+ {"ssubw", 0x0e203000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3WIDEBHS, F_SIZEQ},
+ {"ssubw2", 0x4e203000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3WIDEBHS2, F_SIZEQ},
+ {"addhn", 0x0e204000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3NARRBHS, F_SIZEQ},
+ {"addhn2", 0x4e204000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3NARRBHS2, F_SIZEQ},
+ {"sabal", 0x0e205000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS, F_SIZEQ},
+ {"sabal2", 0x4e205000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS2, F_SIZEQ},
+ {"subhn", 0x0e206000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3NARRBHS, F_SIZEQ},
+ {"subhn2", 0x4e206000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3NARRBHS2, F_SIZEQ},
+ {"sabdl", 0x0e207000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS, F_SIZEQ},
+ {"sabdl2", 0x4e207000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS2, F_SIZEQ},
+ {"smlal", 0x0e208000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS, F_SIZEQ},
+ {"smlal2", 0x4e208000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS2, F_SIZEQ},
+ {"sqdmlal", 0x0e209000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGHS, F_SIZEQ},
+ {"sqdmlal2", 0x4e209000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGHS2, F_SIZEQ},
+ {"smlsl", 0x0e20a000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS, F_SIZEQ},
+ {"smlsl2", 0x4e20a000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS2, F_SIZEQ},
+ {"sqdmlsl", 0x0e20b000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGHS, F_SIZEQ},
+ {"sqdmlsl2", 0x4e20b000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGHS2, F_SIZEQ},
+ {"smull", 0x0e20c000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS, F_SIZEQ},
+ {"smull2", 0x4e20c000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS2, F_SIZEQ},
+ {"sqdmull", 0x0e20d000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGHS, F_SIZEQ},
+ {"sqdmull2", 0x4e20d000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGHS2, F_SIZEQ},
+ {"pmull", 0x0e20e000, 0xffe0fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGB, 0},
+ {"pmull", 0x0ee0e000, 0xffe0fc00, asimddiff, 0, CRYPTO, OP3 (Vd, Vn, Vm), QL_V3LONGD, 0},
+ {"pmull2", 0x4e20e000, 0xffe0fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGB2, 0},
+ {"pmull2", 0x4ee0e000, 0xffe0fc00, asimddiff, 0, CRYPTO, OP3 (Vd, Vn, Vm), QL_V3LONGD2, 0},
+ {"uaddl", 0x2e200000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS, F_SIZEQ},
+ {"uaddl2", 0x6e200000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS2, F_SIZEQ},
+ {"uaddw", 0x2e201000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3WIDEBHS, F_SIZEQ},
+ {"uaddw2", 0x6e201000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3WIDEBHS2, F_SIZEQ},
+ {"usubl", 0x2e202000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS, F_SIZEQ},
+ {"usubl2", 0x6e202000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS2, F_SIZEQ},
+ {"usubw", 0x2e203000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3WIDEBHS, F_SIZEQ},
+ {"usubw2", 0x6e203000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3WIDEBHS2, F_SIZEQ},
+ {"raddhn", 0x2e204000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3NARRBHS, F_SIZEQ},
+ {"raddhn2", 0x6e204000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3NARRBHS2, F_SIZEQ},
+ {"uabal", 0x2e205000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS, F_SIZEQ},
+ {"uabal2", 0x6e205000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS2, F_SIZEQ},
+ {"rsubhn", 0x2e206000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3NARRBHS, F_SIZEQ},
+ {"rsubhn2", 0x6e206000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3NARRBHS2, F_SIZEQ},
+ {"uabdl", 0x2e207000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS, F_SIZEQ},
+ {"uabdl2", 0x6e207000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS2, F_SIZEQ},
+ {"umlal", 0x2e208000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS, F_SIZEQ},
+ {"umlal2", 0x6e208000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS2, F_SIZEQ},
+ {"umlsl", 0x2e20a000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS, F_SIZEQ},
+ {"umlsl2", 0x6e20a000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS2, F_SIZEQ},
+ {"umull", 0x2e20c000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS, F_SIZEQ},
+ {"umull2", 0x6e20c000, 0xff20fc00, asimddiff, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3LONGBHS2, F_SIZEQ},
+ /* AdvSIMD vector x indexed element. */
+ {"smlal", 0x0f002000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L, F_SIZEQ},
+ {"smlal2", 0x4f002000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L2, F_SIZEQ},
+ {"sqdmlal", 0x0f003000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L, F_SIZEQ},
+ {"sqdmlal2", 0x4f003000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L2, F_SIZEQ},
+ {"smlsl", 0x0f006000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L, F_SIZEQ},
+ {"smlsl2", 0x4f006000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L2, F_SIZEQ},
+ {"sqdmlsl", 0x0f007000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L, F_SIZEQ},
+ {"sqdmlsl2", 0x4f007000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L2, F_SIZEQ},
+ {"mul", 0xf008000, 0xbf00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT, F_SIZEQ},
+ {"smull", 0x0f00a000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L, F_SIZEQ},
+ {"smull2", 0x4f00a000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L2, F_SIZEQ},
+ {"sqdmull", 0x0f00b000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L, F_SIZEQ},
+ {"sqdmull2", 0x4f00b000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L2, F_SIZEQ},
+ {"sqdmulh", 0xf00c000, 0xbf00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT, F_SIZEQ},
+ {"sqrdmulh", 0xf00d000, 0xbf00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT, F_SIZEQ},
+ {"fmla", 0xf801000, 0xbf80f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_FP, F_SIZEQ},
+ {"fmls", 0xf805000, 0xbf80f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_FP, F_SIZEQ},
+ {"fmul", 0xf809000, 0xbf80f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_FP, F_SIZEQ},
+ {"mla", 0x2f000000, 0xbf00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT, F_SIZEQ},
+ {"umlal", 0x2f002000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L, F_SIZEQ},
+ {"umlal2", 0x6f002000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L2, F_SIZEQ},
+ {"mls", 0x2f004000, 0xbf00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT, F_SIZEQ},
+ {"umlsl", 0x2f006000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L, F_SIZEQ},
+ {"umlsl2", 0x6f006000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L2, F_SIZEQ},
+ {"umull", 0x2f00a000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L, F_SIZEQ},
+ {"umull2", 0x6f00a000, 0xff00f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_L2, F_SIZEQ},
+ {"fmulx", 0x2f809000, 0xbf80f400, asimdelem, 0, SIMD, OP3 (Vd, Vn, Em), QL_ELEMENT_FP, F_SIZEQ},
+ /* AdvSIMD EXT. */
+ {"ext", 0x2e000000, 0xbfe0c400, asimdext, 0, SIMD, OP4 (Vd, Vn, Vm, IDX), QL_VEXT, F_SIZEQ},
+ /* AdvSIMD modified immediate. */
+ {"movi", 0xf000400, 0xbff89c00, asimdimm, 0, SIMD, OP2 (Vd, SIMD_IMM_SFT), QL_SIMD_IMM_S0W, F_SIZEQ},
+ {"orr", 0xf001400, 0xbff89c00, asimdimm, 0, SIMD, OP2 (Vd, SIMD_IMM_SFT), QL_SIMD_IMM_S0W, F_SIZEQ},
+ {"movi", 0xf008400, 0xbff8dc00, asimdimm, 0, SIMD, OP2 (Vd, SIMD_IMM_SFT), QL_SIMD_IMM_S0H, F_SIZEQ},
+ {"orr", 0xf009400, 0xbff8dc00, asimdimm, 0, SIMD, OP2 (Vd, SIMD_IMM_SFT), QL_SIMD_IMM_S0H, F_SIZEQ},
+ {"movi", 0xf00c400, 0xbff8ec00, asimdimm, 0, SIMD, OP2 (Vd, SIMD_IMM_SFT), QL_SIMD_IMM_S1W, F_SIZEQ},
+ {"movi", 0xf00e400, 0xbff8fc00, asimdimm, OP_V_MOVI_B, SIMD, OP2 (Vd, SIMD_IMM), QL_SIMD_IMM_B, F_SIZEQ},
+ {"fmov", 0xf00f400, 0xbff8fc00, asimdimm, 0, SIMD, OP2 (Vd, SIMD_FPIMM), QL_SIMD_IMM_S, F_SIZEQ},
+ {"mvni", 0x2f000400, 0xbff89c00, asimdimm, 0, SIMD, OP2 (Vd, SIMD_IMM_SFT), QL_SIMD_IMM_S0W, F_SIZEQ},
+ {"bic", 0x2f001400, 0xbff89c00, asimdimm, 0, SIMD, OP2 (Vd, SIMD_IMM_SFT), QL_SIMD_IMM_S0W, F_SIZEQ},
+ {"mvni", 0x2f008400, 0xbff8dc00, asimdimm, 0, SIMD, OP2 (Vd, SIMD_IMM_SFT), QL_SIMD_IMM_S0H, F_SIZEQ},
+ {"bic", 0x2f009400, 0xbff8dc00, asimdimm, 0, SIMD, OP2 (Vd, SIMD_IMM_SFT), QL_SIMD_IMM_S0H, F_SIZEQ},
+ {"mvni", 0x2f00c400, 0xbff8ec00, asimdimm, 0, SIMD, OP2 (Vd, SIMD_IMM_SFT), QL_SIMD_IMM_S1W, F_SIZEQ},
+ {"movi", 0x2f00e400, 0xfff8fc00, asimdimm, 0, SIMD, OP2 (Sd, SIMD_IMM), QL_SIMD_IMM_D, F_SIZEQ},
+ {"movi", 0x6f00e400, 0xfff8fc00, asimdimm, 0, SIMD, OP2 (Vd, SIMD_IMM), QL_SIMD_IMM_V2D, F_SIZEQ},
+ {"fmov", 0x6f00f400, 0xfff8fc00, asimdimm, 0, SIMD, OP2 (Vd, SIMD_FPIMM), QL_SIMD_IMM_V2D, F_SIZEQ},
+ /* AdvSIMD copy. */
+ {"dup", 0xe000400, 0xbfe0fc00, asimdins, 0, SIMD, OP2 (Vd, En), QL_DUP_VX, F_T},
+ {"dup", 0xe000c00, 0xbfe0fc00, asimdins, 0, SIMD, OP2 (Vd, Rn), QL_DUP_VR, F_T},
+ {"smov", 0xe002c00, 0xbfe0fc00, asimdins, 0, SIMD, OP2 (Rd, En), QL_SMOV, F_GPRSIZE_IN_Q},
+ {"umov", 0xe003c00, 0xbfe0fc00, asimdins, 0, SIMD, OP2 (Rd, En), QL_UMOV, F_HAS_ALIAS | F_GPRSIZE_IN_Q},
+ {"mov", 0xe003c00, 0xbfe0fc00, asimdins, 0, SIMD, OP2 (Rd, En), QL_MOV, F_ALIAS | F_GPRSIZE_IN_Q},
+ {"ins", 0x4e001c00, 0xffe0fc00, asimdins, 0, SIMD, OP2 (Ed, Rn), QL_INS_XR, F_HAS_ALIAS},
+ {"mov", 0x4e001c00, 0xffe0fc00, asimdins, 0, SIMD, OP2 (Ed, Rn), QL_INS_XR, F_ALIAS},
+ {"ins", 0x6e000400, 0xffe08400, asimdins, 0, SIMD, OP2 (Ed, En), QL_S_2SAME, F_HAS_ALIAS},
+ {"mov", 0x6e000400, 0xffe08400, asimdins, 0, SIMD, OP2 (Ed, En), QL_S_2SAME, F_ALIAS},
+ /* AdvSIMD two-reg misc. */
+ {"rev64", 0xe200800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMEBHS, F_SIZEQ},
+ {"rev16", 0xe201800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMEB, F_SIZEQ},
+ {"saddlp", 0xe202800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2PAIRWISELONGBHS, F_SIZEQ},
+ {"suqadd", 0xe203800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAME, F_SIZEQ},
+ {"cls", 0xe204800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMEBHS, F_SIZEQ},
+ {"cnt", 0xe205800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMEB, F_SIZEQ},
+ {"sadalp", 0xe206800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2PAIRWISELONGBHS, F_SIZEQ},
+ {"sqabs", 0xe207800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAME, F_SIZEQ},
+ {"cmgt", 0xe208800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP3 (Vd, Vn, IMM0), QL_V2SAME, F_SIZEQ},
+ {"cmeq", 0xe209800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP3 (Vd, Vn, IMM0), QL_V2SAME, F_SIZEQ},
+ {"cmlt", 0xe20a800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP3 (Vd, Vn, IMM0), QL_V2SAME, F_SIZEQ},
+ {"abs", 0xe20b800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAME, F_SIZEQ},
+ {"xtn", 0xe212800, 0xff3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2NARRBHS, F_SIZEQ},
+ {"xtn2", 0x4e212800, 0xff3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2NARRBHS2, F_SIZEQ},
+ {"sqxtn", 0xe214800, 0xff3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2NARRBHS, F_SIZEQ},
+ {"sqxtn2", 0x4e214800, 0xff3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2NARRBHS2, F_SIZEQ},
+ {"fcvtn", 0xe216800, 0xffbffc00, asimdmisc, OP_FCVTN, SIMD, OP2 (Vd, Vn), QL_V2NARRHS, F_MISC},
+ {"fcvtn2", 0x4e216800, 0xffbffc00, asimdmisc, OP_FCVTN2, SIMD, OP2 (Vd, Vn), QL_V2NARRHS2, F_MISC},
+ {"fcvtl", 0xe217800, 0xffbffc00, asimdmisc, OP_FCVTL, SIMD, OP2 (Vd, Vn), QL_V2LONGHS, F_MISC},
+ {"fcvtl2", 0x4e217800, 0xffbffc00, asimdmisc, OP_FCVTL2, SIMD, OP2 (Vd, Vn), QL_V2LONGHS2, F_MISC},
+ {"frintn", 0xe218800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"frintm", 0xe219800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"fcvtns", 0xe21a800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"fcvtms", 0xe21b800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"fcvtas", 0xe21c800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"scvtf", 0xe21d800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"fcmgt", 0xea0c800, 0xbfbffc00, asimdmisc, 0, SIMD, OP3 (Vd, Vn, IMM0), QL_V2SAMESD, F_SIZEQ},
+ {"fcmeq", 0xea0d800, 0xbfbffc00, asimdmisc, 0, SIMD, OP3 (Vd, Vn, IMM0), QL_V2SAMESD, F_SIZEQ},
+ {"fcmlt", 0xea0e800, 0xbfbffc00, asimdmisc, 0, SIMD, OP3 (Vd, Vn, IMM0), QL_V2SAMESD, F_SIZEQ},
+ {"fabs", 0xea0f800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"frintp", 0xea18800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"frintz", 0xea19800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"fcvtps", 0xea1a800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"fcvtzs", 0xea1b800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"urecpe", 0xea1c800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMES, F_SIZEQ},
+ {"frecpe", 0xea1d800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"rev32", 0x2e200800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMEBH, F_SIZEQ},
+ {"uaddlp", 0x2e202800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2PAIRWISELONGBHS, F_SIZEQ},
+ {"usqadd", 0x2e203800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAME, F_SIZEQ},
+ {"clz", 0x2e204800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMEBHS, F_SIZEQ},
+ {"uadalp", 0x2e206800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2PAIRWISELONGBHS, F_SIZEQ},
+ {"sqneg", 0x2e207800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAME, F_SIZEQ},
+ {"cmge", 0x2e208800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP3 (Vd, Vn, IMM0), QL_V2SAME, F_SIZEQ},
+ {"cmle", 0x2e209800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP3 (Vd, Vn, IMM0), QL_V2SAME, F_SIZEQ},
+ {"neg", 0x2e20b800, 0xbf3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAME, F_SIZEQ},
+ {"sqxtun", 0x2e212800, 0xff3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2NARRBHS, F_SIZEQ},
+ {"sqxtun2", 0x6e212800, 0xff3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2NARRBHS2, F_SIZEQ},
+ {"shll", 0x2e213800, 0xff3ffc00, asimdmisc, 0, SIMD, OP3 (Vd, Vn, SHLL_IMM), QL_V2LONGBHS, F_SIZEQ},
+ {"shll2", 0x6e213800, 0xff3ffc00, asimdmisc, 0, SIMD, OP3 (Vd, Vn, SHLL_IMM), QL_V2LONGBHS2, F_SIZEQ},
+ {"uqxtn", 0x2e214800, 0xff3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2NARRBHS, F_SIZEQ},
+ {"uqxtn2", 0x6e214800, 0xff3ffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2NARRBHS2, F_SIZEQ},
+ {"fcvtxn", 0x2e616800, 0xfffffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2NARRS, 0},
+ {"fcvtxn2", 0x6e616800, 0xfffffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2NARRS2, 0},
+ {"frinta", 0x2e218800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"frintx", 0x2e219800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"fcvtnu", 0x2e21a800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"fcvtmu", 0x2e21b800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"fcvtau", 0x2e21c800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"ucvtf", 0x2e21d800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"not", 0x2e205800, 0xbffffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMEB, F_SIZEQ | F_HAS_ALIAS},
+ {"mvn", 0x2e205800, 0xbffffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMEB, F_SIZEQ | F_ALIAS},
+ {"rbit", 0x2e605800, 0xbffffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMEB, F_SIZEQ},
+ {"fcmge", 0x2ea0c800, 0xbfbffc00, asimdmisc, 0, SIMD, OP3 (Vd, Vn, IMM0), QL_V2SAMESD, F_SIZEQ},
+ {"fcmle", 0x2ea0d800, 0xbfbffc00, asimdmisc, 0, SIMD, OP3 (Vd, Vn, IMM0), QL_V2SAMESD, F_SIZEQ},
+ {"fneg", 0x2ea0f800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"frinti", 0x2ea19800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"fcvtpu", 0x2ea1a800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"fcvtzu", 0x2ea1b800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"ursqrte", 0x2ea1c800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMES, F_SIZEQ},
+ {"frsqrte", 0x2ea1d800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ {"fsqrt", 0x2ea1f800, 0xbfbffc00, asimdmisc, 0, SIMD, OP2 (Vd, Vn), QL_V2SAMESD, F_SIZEQ},
+ /* AdvSIMD ZIP/UZP/TRN. */
+ {"uzp1", 0xe001800, 0xbf20fc00, asimdperm, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"trn1", 0xe002800, 0xbf20fc00, asimdperm, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"zip1", 0xe003800, 0xbf20fc00, asimdperm, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"uzp2", 0xe005800, 0xbf20fc00, asimdperm, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"trn2", 0xe006800, 0xbf20fc00, asimdperm, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"zip2", 0xe007800, 0xbf20fc00, asimdperm, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ /* AdvSIMD three same. */
+ {"shadd", 0xe200400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"sqadd", 0xe200c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"srhadd", 0xe201400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"shsub", 0xe202400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"sqsub", 0xe202c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"cmgt", 0xe203400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"cmge", 0xe203c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"sshl", 0xe204400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"sqshl", 0xe204c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"srshl", 0xe205400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"sqrshl", 0xe205c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"smax", 0xe206400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"smin", 0xe206c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"sabd", 0xe207400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"saba", 0xe207c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"add", 0xe208400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"cmtst", 0xe208c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"mla", 0xe209400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"mul", 0xe209c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"smaxp", 0xe20a400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"sminp", 0xe20ac00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"sqdmulh", 0xe20b400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEHS, F_SIZEQ},
+ {"addp", 0xe20bc00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"fmaxnm", 0xe20c400, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"fmla", 0xe20cc00, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"fadd", 0xe20d400, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"fmulx", 0xe20dc00, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"fcmeq", 0xe20e400, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"fmax", 0xe20f400, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"frecps", 0xe20fc00, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"and", 0xe201c00, 0xbfe0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEB, F_SIZEQ},
+ {"bic", 0xe601c00, 0xbfe0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEB, F_SIZEQ},
+ {"fminnm", 0xea0c400, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"fmls", 0xea0cc00, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"fsub", 0xea0d400, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"fmin", 0xea0f400, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"frsqrts", 0xea0fc00, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"orr", 0xea01c00, 0xbfe0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEB, F_HAS_ALIAS | F_SIZEQ},
+ {"mov", 0xea01c00, 0xbfe0fc00, asimdsame, OP_MOV_V, SIMD, OP2 (Vd, Vn), QL_V2SAMEB, F_ALIAS | F_CONV},
+ {"orn", 0xee01c00, 0xbfe0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEB, F_SIZEQ},
+ {"uhadd", 0x2e200400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"uqadd", 0x2e200c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"urhadd", 0x2e201400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"uhsub", 0x2e202400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"uqsub", 0x2e202c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"cmhi", 0x2e203400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"cmhs", 0x2e203c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"ushl", 0x2e204400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"uqshl", 0x2e204c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"urshl", 0x2e205400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"uqrshl", 0x2e205c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"umax", 0x2e206400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"umin", 0x2e206c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"uabd", 0x2e207400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"uaba", 0x2e207c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"sub", 0x2e208400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"cmeq", 0x2e208c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAME, F_SIZEQ},
+ {"mls", 0x2e209400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"pmul", 0x2e209c00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEB, F_SIZEQ},
+ {"umaxp", 0x2e20a400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"uminp", 0x2e20ac00, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEBHS, F_SIZEQ},
+ {"sqrdmulh", 0x2e20b400, 0xbf20fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEHS, F_SIZEQ},
+ {"fmaxnmp", 0x2e20c400, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"faddp", 0x2e20d400, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"fmul", 0x2e20dc00, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"fcmge", 0x2e20e400, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"facge", 0x2e20ec00, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"fmaxp", 0x2e20f400, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"fdiv", 0x2e20fc00, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"eor", 0x2e201c00, 0xbfe0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEB, F_SIZEQ},
+ {"bsl", 0x2e601c00, 0xbfe0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEB, F_SIZEQ},
+ {"fminnmp", 0x2ea0c400, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"fabd", 0x2ea0d400, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"fcmgt", 0x2ea0e400, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"facgt", 0x2ea0ec00, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"fminp", 0x2ea0f400, 0xbfa0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMESD, F_SIZEQ},
+ {"bit", 0x2ea01c00, 0xbfe0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEB, F_SIZEQ},
+ {"bif", 0x2ee01c00, 0xbfe0fc00, asimdsame, 0, SIMD, OP3 (Vd, Vn, Vm), QL_V3SAMEB, F_SIZEQ},
+ /* AdvSIMD shift by immediate. */
+ {"sshr", 0xf000400, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFT, 0},
+ {"ssra", 0xf001400, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFT, 0},
+ {"srshr", 0xf002400, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFT, 0},
+ {"srsra", 0xf003400, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFT, 0},
+ {"shl", 0xf005400, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSL), QL_VSHIFT, 0},
+ {"sqshl", 0xf007400, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSL), QL_VSHIFT, 0},
+ {"shrn", 0xf008400, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFTN, 0},
+ {"shrn2", 0x4f008400, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFTN2, 0},
+ {"rshrn", 0xf008c00, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFTN, 0},
+ {"rshrn2", 0x4f008c00, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFTN2, 0},
+ {"sqshrn", 0xf009400, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFTN, 0},
+ {"sqshrn2", 0x4f009400, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFTN2, 0},
+ {"sqrshrn", 0xf009c00, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFTN, 0},
+ {"sqrshrn2", 0x4f009c00, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFTN2, 0},
+ {"sshll", 0xf00a400, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSL), QL_VSHIFTL, 0},
+ {"sshll2", 0x4f00a400, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSL), QL_VSHIFTL2, 0},
+ {"scvtf", 0xf00e400, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFT_SD, 0},
+ {"fcvtzs", 0xf00fc00, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFT_SD, 0},
+ {"ushr", 0x2f000400, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFT, 0},
+ {"usra", 0x2f001400, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFT, 0},
+ {"urshr", 0x2f002400, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFT, 0},
+ {"ursra", 0x2f003400, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFT, 0},
+ {"sri", 0x2f004400, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFT, 0},
+ {"sli", 0x2f005400, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSL), QL_VSHIFT, 0},
+ {"sqshlu", 0x2f006400, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSL), QL_VSHIFT, 0},
+ {"uqshl", 0x2f007400, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSL), QL_VSHIFT, 0},
+ {"sqshrun", 0x2f008400, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFTN, 0},
+ {"sqshrun2", 0x6f008400, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFTN2, 0},
+ {"sqrshrun", 0x2f008c00, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFTN, 0},
+ {"sqrshrun2", 0x6f008c00, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFTN2, 0},
+ {"uqshrn", 0x2f009400, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFTN, 0},
+ {"uqshrn2", 0x6f009400, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFTN2, 0},
+ {"uqrshrn", 0x2f009c00, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFTN, 0},
+ {"uqrshrn2", 0x6f009c00, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFTN2, 0},
+ {"ushll", 0x2f00a400, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSL), QL_VSHIFTL, 0},
+ {"ushll2", 0x6f00a400, 0xff80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSL), QL_VSHIFTL2, 0},
+ {"ucvtf", 0x2f00e400, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFT_SD, 0},
+ {"fcvtzu", 0x2f00fc00, 0xbf80fc00, asimdshf, 0, SIMD, OP3 (Vd, Vn, IMM_VLSR), QL_VSHIFT_SD, 0},
+ /* AdvSIMD TBL/TBX. */
+ {"tbl", 0xe000000, 0xbfe09c00, asimdtbl, 0, SIMD, OP3 (Vd, LVn, Vm), QL_TABLE, F_SIZEQ},
+ {"tbx", 0xe001000, 0xbfe09c00, asimdtbl, 0, SIMD, OP3 (Vd, LVn, Vm), QL_TABLE, F_SIZEQ},
+ /* AdvSIMD scalar three different. */
+ {"sqdmlal", 0x5e209000, 0xff20fc00, asisddiff, 0, SIMD, OP3 (Sd, Sn, Sm), QL_SISDL_HS, F_SSIZE},
+ {"sqdmlsl", 0x5e20b000, 0xff20fc00, asisddiff, 0, SIMD, OP3 (Sd, Sn, Sm), QL_SISDL_HS, F_SSIZE},
+ {"sqdmull", 0x5e20d000, 0xff20fc00, asisddiff, 0, SIMD, OP3 (Sd, Sn, Sm), QL_SISDL_HS, F_SSIZE},
+ /* AdvSIMD scalar x indexed element. */
+ {"sqdmlal", 0x5f003000, 0xff00f400, asisdelem, 0, SIMD, OP3 (Sd, Sn, Em), QL_SISDL_HS, F_SSIZE},
+ {"sqdmlsl", 0x5f007000, 0xff00f400, asisdelem, 0, SIMD, OP3 (Sd, Sn, Em), QL_SISDL_HS, F_SSIZE},
+ {"sqdmull", 0x5f00b000, 0xff00f400, asisdelem, 0, SIMD, OP3 (Sd, Sn, Em), QL_SISDL_HS, F_SSIZE},
+ {"sqdmulh", 0x5f00c000, 0xff00f400, asisdelem, 0, SIMD, OP3 (Sd, Sn, Em), QL_SISD_HS, F_SSIZE},
+ {"sqrdmulh", 0x5f00d000, 0xff00f400, asisdelem, 0, SIMD, OP3 (Sd, Sn, Em), QL_SISD_HS, F_SSIZE},
+ {"fmla", 0x5f801000, 0xff80f400, asisdelem, 0, SIMD, OP3 (Sd, Sn, Em), QL_FP3, F_SSIZE},
+ {"fmls", 0x5f805000, 0xff80f400, asisdelem, 0, SIMD, OP3 (Sd, Sn, Em), QL_FP3, F_SSIZE},
+ {"fmul", 0x5f809000, 0xff80f400, asisdelem, 0, SIMD, OP3 (Sd, Sn, Em), QL_FP3, F_SSIZE},
+ {"fmulx", 0x7f809000, 0xff80f400, asisdelem, 0, SIMD, OP3 (Sd, Sn, Em), QL_FP3, F_SSIZE},
+ /* AdvSIMD load/store multiple structures. */
+ {"st4", 0xc000000, 0xbfff0000, asisdlse, 0, SIMD, OP2 (LVt, SIMD_ADDR_SIMPLE), QL_SIMD_LDST, F_SIZEQ | F_OD(4)},
+ {"st1", 0xc000000, 0xbfff0000, asisdlse, 0, SIMD, OP2 (LVt, SIMD_ADDR_SIMPLE), QL_SIMD_LDST_ANY, F_SIZEQ | F_OD(1)},
+ {"st2", 0xc000000, 0xbfff0000, asisdlse, 0, SIMD, OP2 (LVt, SIMD_ADDR_SIMPLE), QL_SIMD_LDST, F_SIZEQ | F_OD(2)},
+ {"st3", 0xc000000, 0xbfff0000, asisdlse, 0, SIMD, OP2 (LVt, SIMD_ADDR_SIMPLE), QL_SIMD_LDST, F_SIZEQ | F_OD(3)},
+ {"ld4", 0xc400000, 0xbfff0000, asisdlse, 0, SIMD, OP2 (LVt, SIMD_ADDR_SIMPLE), QL_SIMD_LDST, F_SIZEQ | F_OD(4)},
+ {"ld1", 0xc400000, 0xbfff0000, asisdlse, 0, SIMD, OP2 (LVt, SIMD_ADDR_SIMPLE), QL_SIMD_LDST_ANY, F_SIZEQ | F_OD(1)},
+ {"ld2", 0xc400000, 0xbfff0000, asisdlse, 0, SIMD, OP2 (LVt, SIMD_ADDR_SIMPLE), QL_SIMD_LDST, F_SIZEQ | F_OD(2)},
+ {"ld3", 0xc400000, 0xbfff0000, asisdlse, 0, SIMD, OP2 (LVt, SIMD_ADDR_SIMPLE), QL_SIMD_LDST, F_SIZEQ | F_OD(3)},
+ /* AdvSIMD load/store multiple structures (post-indexed). */
+ {"st4", 0xc800000, 0xbfe00000, asisdlsep, 0, SIMD, OP2 (LVt, SIMD_ADDR_POST), QL_SIMD_LDST, F_SIZEQ | F_OD(4)},
+ {"st1", 0xc800000, 0xbfe00000, asisdlsep, 0, SIMD, OP2 (LVt, SIMD_ADDR_POST), QL_SIMD_LDST_ANY, F_SIZEQ | F_OD(1)},
+ {"st2", 0xc800000, 0xbfe00000, asisdlsep, 0, SIMD, OP2 (LVt, SIMD_ADDR_POST), QL_SIMD_LDST, F_SIZEQ | F_OD(2)},
+ {"st3", 0xc800000, 0xbfe00000, asisdlsep, 0, SIMD, OP2 (LVt, SIMD_ADDR_POST), QL_SIMD_LDST, F_SIZEQ | F_OD(3)},
+ {"ld4", 0xcc00000, 0xbfe00000, asisdlsep, 0, SIMD, OP2 (LVt, SIMD_ADDR_POST), QL_SIMD_LDST, F_SIZEQ | F_OD(4)},
+ {"ld1", 0xcc00000, 0xbfe00000, asisdlsep, 0, SIMD, OP2 (LVt, SIMD_ADDR_POST), QL_SIMD_LDST_ANY, F_SIZEQ | F_OD(1)},
+ {"ld2", 0xcc00000, 0xbfe00000, asisdlsep, 0, SIMD, OP2 (LVt, SIMD_ADDR_POST), QL_SIMD_LDST, F_SIZEQ | F_OD(2)},
+ {"ld3", 0xcc00000, 0xbfe00000, asisdlsep, 0, SIMD, OP2 (LVt, SIMD_ADDR_POST), QL_SIMD_LDST, F_SIZEQ | F_OD(3)},
+ /* AdvSIMD load/store single structure. */
+ {"st1", 0xd000000, 0xbfff2000, asisdlso, 0, SIMD, OP2 (LEt, SIMD_ADDR_SIMPLE), QL_SIMD_LDSTONE, F_OD(1)},
+ {"st3", 0xd002000, 0xbfff2000, asisdlso, 0, SIMD, OP2 (LEt, SIMD_ADDR_SIMPLE), QL_SIMD_LDSTONE, F_OD(3)},
+ {"st2", 0xd200000, 0xbfff2000, asisdlso, 0, SIMD, OP2 (LEt, SIMD_ADDR_SIMPLE), QL_SIMD_LDSTONE, F_OD(2)},
+ {"st4", 0xd202000, 0xbfff2000, asisdlso, 0, SIMD, OP2 (LEt, SIMD_ADDR_SIMPLE), QL_SIMD_LDSTONE, F_OD(4)},
+ {"ld1", 0xd400000, 0xbfff2000, asisdlso, 0, SIMD, OP2 (LEt, SIMD_ADDR_SIMPLE), QL_SIMD_LDSTONE, F_OD(1)},
+ {"ld3", 0xd402000, 0xbfff2000, asisdlso, 0, SIMD, OP2 (LEt, SIMD_ADDR_SIMPLE), QL_SIMD_LDSTONE, F_OD(3)},
+ {"ld1r", 0xd40c000, 0xbfffe000, asisdlso, 0, SIMD, OP2 (LVt_AL, SIMD_ADDR_SIMPLE), QL_SIMD_LDST_ANY, F_SIZEQ | F_OD(1)},
+ {"ld3r", 0xd40e000, 0xbfffe000, asisdlso, 0, SIMD, OP2 (LVt_AL, SIMD_ADDR_SIMPLE), QL_SIMD_LDST_ANY, F_SIZEQ | F_OD(3)},
+ {"ld2", 0xd600000, 0xbfff2000, asisdlso, 0, SIMD, OP2 (LEt, SIMD_ADDR_SIMPLE), QL_SIMD_LDSTONE, F_OD(2)},
+ {"ld4", 0xd602000, 0xbfff2000, asisdlso, 0, SIMD, OP2 (LEt, SIMD_ADDR_SIMPLE), QL_SIMD_LDSTONE, F_OD(4)},
+ {"ld2r", 0xd60c000, 0xbfffe000, asisdlso, 0, SIMD, OP2 (LVt_AL, SIMD_ADDR_SIMPLE), QL_SIMD_LDST_ANY, F_SIZEQ | F_OD(2)},
+ {"ld4r", 0xd60e000, 0xbfffe000, asisdlso, 0, SIMD, OP2 (LVt_AL, SIMD_ADDR_SIMPLE), QL_SIMD_LDST_ANY, F_SIZEQ | F_OD(4)},
+ /* AdvSIMD load/store single structure (post-indexed). */
+ {"st1", 0xd800000, 0xbfe02000, asisdlsop, 0, SIMD, OP2 (LEt, SIMD_ADDR_POST), QL_SIMD_LDSTONE, F_OD(1)},
+ {"st3", 0xd802000, 0xbfe02000, asisdlsop, 0, SIMD, OP2 (LEt, SIMD_ADDR_POST), QL_SIMD_LDSTONE, F_OD(3)},
+ {"st2", 0xda00000, 0xbfe02000, asisdlsop, 0, SIMD, OP2 (LEt, SIMD_ADDR_POST), QL_SIMD_LDSTONE, F_OD(2)},
+ {"st4", 0xda02000, 0xbfe02000, asisdlsop, 0, SIMD, OP2 (LEt, SIMD_ADDR_POST), QL_SIMD_LDSTONE, F_OD(4)},
+ {"ld1", 0xdc00000, 0xbfe02000, asisdlsop, 0, SIMD, OP2 (LEt, SIMD_ADDR_POST), QL_SIMD_LDSTONE, F_OD(1)},
+ {"ld3", 0xdc02000, 0xbfe02000, asisdlsop, 0, SIMD, OP2 (LEt, SIMD_ADDR_POST), QL_SIMD_LDSTONE, F_OD(3)},
+ {"ld1r", 0xdc0c000, 0xbfe0e000, asisdlsop, 0, SIMD, OP2 (LVt_AL, SIMD_ADDR_POST), QL_SIMD_LDST_ANY, F_SIZEQ | F_OD(1)},
+ {"ld3r", 0xdc0e000, 0xbfe0e000, asisdlsop, 0, SIMD, OP2 (LVt_AL, SIMD_ADDR_POST), QL_SIMD_LDST_ANY, F_SIZEQ | F_OD(3)},
+ {"ld2", 0xde00000, 0xbfe02000, asisdlsop, 0, SIMD, OP2 (LEt, SIMD_ADDR_POST), QL_SIMD_LDSTONE, F_OD(2)},
+ {"ld4", 0xde02000, 0xbfe02000, asisdlsop, 0, SIMD, OP2 (LEt, SIMD_ADDR_POST), QL_SIMD_LDSTONE, F_OD(4)},
+ {"ld2r", 0xde0c000, 0xbfe0e000, asisdlsop, 0, SIMD, OP2 (LVt_AL, SIMD_ADDR_POST), QL_SIMD_LDST_ANY, F_SIZEQ | F_OD(2)},
+ {"ld4r", 0xde0e000, 0xbfe0e000, asisdlsop, 0, SIMD, OP2 (LVt_AL, SIMD_ADDR_POST), QL_SIMD_LDST_ANY, F_SIZEQ | F_OD(4)},
+ /* AdvSIMD scalar two-reg misc. */
+ {"suqadd", 0x5e203800, 0xff3ffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAME, F_SSIZE},
+ {"sqabs", 0x5e207800, 0xff3ffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAME, F_SSIZE},
+ {"cmgt", 0x5e208800, 0xff3ffc00, asisdmisc, 0, SIMD, OP3 (Sd, Sn, IMM0), QL_SISD_CMP_0, F_SSIZE},
+ {"cmeq", 0x5e209800, 0xff3ffc00, asisdmisc, 0, SIMD, OP3 (Sd, Sn, IMM0), QL_SISD_CMP_0, F_SSIZE},
+ {"cmlt", 0x5e20a800, 0xff3ffc00, asisdmisc, 0, SIMD, OP3 (Sd, Sn, IMM0), QL_SISD_CMP_0, F_SSIZE},
+ {"abs", 0x5e20b800, 0xff3ffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_2SAMED, F_SSIZE},
+ {"sqxtn", 0x5e214800, 0xff3ffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_SISD_NARROW, F_SSIZE},
+ {"fcvtns", 0x5e21a800, 0xffbffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAMESD, F_SSIZE},
+ {"fcvtms", 0x5e21b800, 0xffbffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAMESD, F_SSIZE},
+ {"fcvtas", 0x5e21c800, 0xffbffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAMESD, F_SSIZE},
+ {"scvtf", 0x5e21d800, 0xffbffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAMESD, F_SSIZE},
+ {"fcmgt", 0x5ea0c800, 0xffbffc00, asisdmisc, 0, SIMD, OP3 (Sd, Sn, IMM0), QL_SISD_FCMP_0, F_SSIZE},
+ {"fcmeq", 0x5ea0d800, 0xffbffc00, asisdmisc, 0, SIMD, OP3 (Sd, Sn, IMM0), QL_SISD_FCMP_0, F_SSIZE},
+ {"fcmlt", 0x5ea0e800, 0xffbffc00, asisdmisc, 0, SIMD, OP3 (Sd, Sn, IMM0), QL_SISD_FCMP_0, F_SSIZE},
+ {"fcvtps", 0x5ea1a800, 0xffbffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAMESD, F_SSIZE},
+ {"fcvtzs", 0x5ea1b800, 0xffbffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAMESD, F_SSIZE},
+ {"frecpe", 0x5ea1d800, 0xffbffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAMESD, F_SSIZE},
+ {"frecpx", 0x5ea1f800, 0xffbffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAMESD, F_SSIZE},
+ {"usqadd", 0x7e203800, 0xff3ffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAME, F_SSIZE},
+ {"sqneg", 0x7e207800, 0xff3ffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAME, F_SSIZE},
+ {"cmge", 0x7e208800, 0xff3ffc00, asisdmisc, 0, SIMD, OP3 (Sd, Sn, IMM0), QL_SISD_CMP_0, F_SSIZE},
+ {"cmle", 0x7e209800, 0xff3ffc00, asisdmisc, 0, SIMD, OP3 (Sd, Sn, IMM0), QL_SISD_CMP_0, F_SSIZE},
+ {"neg", 0x7e20b800, 0xff3ffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_2SAMED, F_SSIZE},
+ {"sqxtun", 0x7e212800, 0xff3ffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_SISD_NARROW, F_SSIZE},
+ {"uqxtn", 0x7e214800, 0xff3ffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_SISD_NARROW, F_SSIZE},
+ {"fcvtxn", 0x7e216800, 0xffbffc00, asisdmisc, OP_FCVTXN_S, SIMD, OP2 (Sd, Sn), QL_SISD_NARROW_S, F_MISC},
+ {"fcvtnu", 0x7e21a800, 0xffbffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAMESD, F_SSIZE},
+ {"fcvtmu", 0x7e21b800, 0xffbffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAMESD, F_SSIZE},
+ {"fcvtau", 0x7e21c800, 0xffbffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAMESD, F_SSIZE},
+ {"ucvtf", 0x7e21d800, 0xffbffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAMESD, F_SSIZE},
+ {"fcmge", 0x7ea0c800, 0xffbffc00, asisdmisc, 0, SIMD, OP3 (Sd, Sn, IMM0), QL_SISD_FCMP_0, F_SSIZE},
+ {"fcmle", 0x7ea0d800, 0xffbffc00, asisdmisc, 0, SIMD, OP3 (Sd, Sn, IMM0), QL_SISD_FCMP_0, F_SSIZE},
+ {"fcvtpu", 0x7ea1a800, 0xffbffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAMESD, F_SSIZE},
+ {"fcvtzu", 0x7ea1b800, 0xffbffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAMESD, F_SSIZE},
+ {"frsqrte", 0x7ea1d800, 0xffbffc00, asisdmisc, 0, SIMD, OP2 (Sd, Sn), QL_S_2SAMESD, F_SSIZE},
+ /* AdvSIMD scalar copy. */
+ {"dup", 0x5e000400, 0xffe0fc00, asisdone, 0, SIMD, OP2 (Sd, En), QL_S_2SAME, F_HAS_ALIAS},
+ {"mov", 0x5e000400, 0xffe0fc00, asisdone, 0, SIMD, OP2 (Sd, En), QL_S_2SAME, F_ALIAS},
+ /* AdvSIMD scalar pairwise. */
+ {"addp", 0x5e31b800, 0xff3ffc00, asisdpair, 0, SIMD, OP2 (Sd, Vn), QL_SISD_PAIR_D, F_SIZEQ},
+ {"fmaxnmp", 0x7e30c800, 0xffbffc00, asisdpair, 0, SIMD, OP2 (Sd, Vn), QL_SISD_PAIR, F_SIZEQ},
+ {"faddp", 0x7e30d800, 0xffbffc00, asisdpair, 0, SIMD, OP2 (Sd, Vn), QL_SISD_PAIR, F_SIZEQ},
+ {"fmaxp", 0x7e30f800, 0xffbffc00, asisdpair, 0, SIMD, OP2 (Sd, Vn), QL_SISD_PAIR, F_SIZEQ},
+ {"fminnmp", 0x7eb0c800, 0xffbffc00, asisdpair, 0, SIMD, OP2 (Sd, Vn), QL_SISD_PAIR, F_SIZEQ},
+ {"fminp", 0x7eb0f800, 0xffbffc00, asisdpair, 0, SIMD, OP2 (Sd, Vn), QL_SISD_PAIR, F_SIZEQ},
+ /* AdvSIMD scalar three same. */
+ {"sqadd", 0x5e200c00, 0xff20fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAME, F_SSIZE},
+ {"sqsub", 0x5e202c00, 0xff20fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAME, F_SSIZE},
+ {"sqshl", 0x5e204c00, 0xff20fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAME, F_SSIZE},
+ {"sqrshl", 0x5e205c00, 0xff20fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAME, F_SSIZE},
+ {"sqdmulh", 0x5e20b400, 0xff20fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_SISD_HS, F_SSIZE},
+ {"fmulx", 0x5e20dc00, 0xffa0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_FP3, F_SSIZE},
+ {"fcmeq", 0x5e20e400, 0xffa0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_FP3, F_SSIZE},
+ {"frecps", 0x5e20fc00, 0xffa0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_FP3, F_SSIZE},
+ {"frsqrts", 0x5ea0fc00, 0xffa0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_FP3, F_SSIZE},
+ {"cmgt", 0x5ee03400, 0xffe0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAMED, F_SSIZE},
+ {"cmge", 0x5ee03c00, 0xffe0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAMED, F_SSIZE},
+ {"sshl", 0x5ee04400, 0xffe0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAMED, F_SSIZE},
+ {"srshl", 0x5ee05400, 0xffe0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAMED, F_SSIZE},
+ {"add", 0x5ee08400, 0xffe0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAMED, F_SSIZE},
+ {"cmtst", 0x5ee08c00, 0xffe0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAMED, F_SSIZE},
+ {"uqadd", 0x7e200c00, 0xff20fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAME, F_SSIZE},
+ {"uqsub", 0x7e202c00, 0xff20fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAME, F_SSIZE},
+ {"uqshl", 0x7e204c00, 0xff20fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAME, F_SSIZE},
+ {"uqrshl", 0x7e205c00, 0xff20fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAME, F_SSIZE},
+ {"sqrdmulh", 0x7e20b400, 0xff20fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_SISD_HS, F_SSIZE},
+ {"fcmge", 0x7e20e400, 0xffa0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_FP3, F_SSIZE},
+ {"facge", 0x7e20ec00, 0xffa0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_FP3, F_SSIZE},
+ {"fabd", 0x7ea0d400, 0xffa0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_FP3, F_SSIZE},
+ {"fcmgt", 0x7ea0e400, 0xffa0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_FP3, F_SSIZE},
+ {"facgt", 0x7ea0ec00, 0xffa0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_FP3, F_SSIZE},
+ {"cmhi", 0x7ee03400, 0xffe0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAMED, F_SSIZE},
+ {"cmhs", 0x7ee03c00, 0xffe0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAMED, F_SSIZE},
+ {"ushl", 0x7ee04400, 0xffe0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAMED, F_SSIZE},
+ {"urshl", 0x7ee05400, 0xffe0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAMED, F_SSIZE},
+ {"sub", 0x7ee08400, 0xffe0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAMED, F_SSIZE},
+ {"cmeq", 0x7ee08c00, 0xffe0fc00, asisdsame, 0, SIMD, OP3 (Sd, Sn, Sm), QL_S_3SAMED, F_SSIZE},
+ /* AdvSIMD scalar shift by immediate. */
+ {"sshr", 0x5f000400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFT_D, 0},
+ {"ssra", 0x5f001400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFT_D, 0},
+ {"srshr", 0x5f002400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFT_D, 0},
+ {"srsra", 0x5f003400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFT_D, 0},
+ {"shl", 0x5f005400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSL), QL_SSHIFT_D, 0},
+ {"sqshl", 0x5f007400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSL), QL_SSHIFT, 0},
+ {"sqshrn", 0x5f009400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFTN, 0},
+ {"sqrshrn", 0x5f009c00, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFTN, 0},
+ {"scvtf", 0x5f00e400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFT_SD, 0},
+ {"fcvtzs", 0x5f00fc00, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFT_SD, 0},
+ {"ushr", 0x7f000400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFT_D, 0},
+ {"usra", 0x7f001400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFT_D, 0},
+ {"urshr", 0x7f002400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFT_D, 0},
+ {"ursra", 0x7f003400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFT_D, 0},
+ {"sri", 0x7f004400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFT_D, 0},
+ {"sli", 0x7f005400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSL), QL_SSHIFT_D, 0},
+ {"sqshlu", 0x7f006400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSL), QL_SSHIFT, 0},
+ {"uqshl", 0x7f007400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSL), QL_SSHIFT, 0},
+ {"sqshrun", 0x7f008400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFTN, 0},
+ {"sqrshrun", 0x7f008c00, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFTN, 0},
+ {"uqshrn", 0x7f009400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFTN, 0},
+ {"uqrshrn", 0x7f009c00, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFTN, 0},
+ {"ucvtf", 0x7f00e400, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFT_SD, 0},
+ {"fcvtzu", 0x7f00fc00, 0xff80fc00, asisdshf, 0, SIMD, OP3 (Sd, Sn, IMM_VLSR), QL_SSHIFT_SD, 0},
+ /* Bitfield. */
+ {"sbfm", 0x13000000, 0x7f800000, bitfield, 0, CORE, OP4 (Rd, Rn, IMMR, IMMS), QL_BF, F_HAS_ALIAS | F_SF | F_N},
+ {"sbfiz", 0x13000000, 0x7f800000, bitfield, OP_SBFIZ, CORE, OP4 (Rd, Rn, IMM, WIDTH), QL_BF2, F_ALIAS | F_P1 | F_CONV},
+ {"sbfx", 0x13000000, 0x7f800000, bitfield, OP_SBFX, CORE, OP4 (Rd, Rn, IMM, WIDTH), QL_BF2, F_ALIAS | F_P1 | F_CONV},
+ {"sxtb", 0x13001c00, 0x7fbffc00, bitfield, 0, CORE, OP2 (Rd, Rn), QL_EXT, F_ALIAS | F_P3 | F_SF | F_N},
+ {"sxth", 0x13003c00, 0x7fbffc00, bitfield, 0, CORE, OP2 (Rd, Rn), QL_EXT, F_ALIAS | F_P3 | F_SF | F_N},
+ {"sxtw", 0x93407c00, 0xfffffc00, bitfield, 0, CORE, OP2 (Rd, Rn), QL_EXT_W, F_ALIAS | F_P3},
+ {"asr", 0x13000000, 0x7f800000, bitfield, OP_ASR_IMM, CORE, OP3 (Rd, Rn, IMM), QL_SHIFT, F_ALIAS | F_P2 | F_CONV},
+ {"bfm", 0x33000000, 0x7f800000, bitfield, 0, CORE, OP4 (Rd, Rn, IMMR, IMMS), QL_BF, F_HAS_ALIAS | F_SF | F_N},
+ {"bfi", 0x33000000, 0x7f800000, bitfield, OP_BFI, CORE, OP4 (Rd, Rn, IMM, WIDTH), QL_BF2, F_ALIAS | F_P1 | F_CONV},
+ {"bfxil", 0x33000000, 0x7f800000, bitfield, OP_BFXIL, CORE, OP4 (Rd, Rn, IMM, WIDTH), QL_BF2, F_ALIAS | F_P1 | F_CONV},
+ {"ubfm", 0x53000000, 0x7f800000, bitfield, 0, CORE, OP4 (Rd, Rn, IMMR, IMMS), QL_BF, F_HAS_ALIAS | F_SF | F_N},
+ {"ubfiz", 0x53000000, 0x7f800000, bitfield, OP_UBFIZ, CORE, OP4 (Rd, Rn, IMM, WIDTH), QL_BF2, F_ALIAS | F_P1 | F_CONV},
+ {"ubfx", 0x53000000, 0x7f800000, bitfield, OP_UBFX, CORE, OP4 (Rd, Rn, IMM, WIDTH), QL_BF2, F_ALIAS | F_P1 | F_CONV},
+ {"uxtb", 0x53001c00, 0xfffffc00, bitfield, OP_UXTB, CORE, OP2 (Rd, Rn), QL_I2SAMEW, F_ALIAS | F_P3},
+ {"uxth", 0x53003c00, 0xfffffc00, bitfield, OP_UXTH, CORE, OP2 (Rd, Rn), QL_I2SAMEW, F_ALIAS | F_P3},
+ {"lsl", 0x53000000, 0x7f800000, bitfield, OP_LSL_IMM, CORE, OP3 (Rd, Rn, IMM), QL_SHIFT, F_ALIAS | F_P2 | F_CONV},
+ {"lsr", 0x53000000, 0x7f800000, bitfield, OP_LSR_IMM, CORE, OP3 (Rd, Rn, IMM), QL_SHIFT, F_ALIAS | F_P2 | F_CONV},
+ /* Unconditional branch (immediate). */
+ {"b", 0x14000000, 0xfc000000, branch_imm, OP_B, CORE, OP1 (ADDR_PCREL26), QL_PCREL_26, 0},
+ {"bl", 0x94000000, 0xfc000000, branch_imm, OP_BL, CORE, OP1 (ADDR_PCREL26), QL_PCREL_26, 0},
+ /* Unconditional branch (register). */
+ {"br", 0xd61f0000, 0xfffffc1f, branch_reg, 0, CORE, OP1 (Rn), QL_I1X, 0},
+ {"blr", 0xd63f0000, 0xfffffc1f, branch_reg, 0, CORE, OP1 (Rn), QL_I1X, 0},
+ {"ret", 0xd65f0000, 0xfffffc1f, branch_reg, 0, CORE, OP1 (Rn), QL_I1X, F_OPD0_OPT | F_DEFAULT (30)},
+ {"eret", 0xd69f03e0, 0xffffffff, branch_reg, 0, CORE, OP0 (), {}, 0},
+ {"drps", 0xd6bf03e0, 0xffffffff, branch_reg, 0, CORE, OP0 (), {}, 0},
+ /* Compare & branch (immediate). */
+ {"cbz", 0x34000000, 0x7f000000, compbranch, 0, CORE, OP2 (Rt, ADDR_PCREL19), QL_R_PCREL, F_SF},
+ {"cbnz", 0x35000000, 0x7f000000, compbranch, 0, CORE, OP2 (Rt, ADDR_PCREL19), QL_R_PCREL, F_SF},
+ /* Conditional branch (immediate). */
+ {"b.c", 0x54000000, 0xff000010, condbranch, 0, CORE, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_COND},
+ /* Conditional compare (immediate). */
+ {"ccmn", 0x3a400800, 0x7fe00c10, condcmp_imm, 0, CORE, OP4 (Rn, CCMP_IMM, NZCV, COND), QL_CCMP_IMM, F_SF},
+ {"ccmp", 0x7a400800, 0x7fe00c10, condcmp_imm, 0, CORE, OP4 (Rn, CCMP_IMM, NZCV, COND), QL_CCMP_IMM, F_SF},
+ /* Conditional compare (register). */
+ {"ccmn", 0x3a400000, 0x7fe00c10, condcmp_reg, 0, CORE, OP4 (Rn, Rm, NZCV, COND), QL_CCMP, F_SF},
+ {"ccmp", 0x7a400000, 0x7fe00c10, condcmp_reg, 0, CORE, OP4 (Rn, Rm, NZCV, COND), QL_CCMP, F_SF},
+ /* Conditional select. */
+ {"csel", 0x1a800000, 0x7fe00c00, condsel, 0, CORE, OP4 (Rd, Rn, Rm, COND), QL_CSEL, F_SF},
+ {"csinc", 0x1a800400, 0x7fe00c00, condsel, 0, CORE, OP4 (Rd, Rn, Rm, COND), QL_CSEL, F_HAS_ALIAS | F_SF},
+ {"cinc", 0x1a800400, 0x7fe00c00, condsel, OP_CINC, CORE, OP3 (Rd, Rn, COND), QL_CSEL, F_ALIAS | F_SF | F_CONV},
+ {"cset", 0x1a9f07e0, 0x7fff0fe0, condsel, OP_CSET, CORE, OP2 (Rd, COND), QL_DST_R, F_ALIAS | F_P1 | F_SF | F_CONV},
+ {"csinv", 0x5a800000, 0x7fe00c00, condsel, 0, CORE, OP4 (Rd, Rn, Rm, COND), QL_CSEL, F_HAS_ALIAS | F_SF},
+ {"cinv", 0x5a800000, 0x7fe00c00, condsel, OP_CINV, CORE, OP3 (Rd, Rn, COND), QL_CSEL, F_ALIAS | F_SF | F_CONV},
+ {"csetm", 0x5a9f03e0, 0x7fff0fe0, condsel, OP_CSETM, CORE, OP2 (Rd, COND), QL_DST_R, F_ALIAS | F_P1 | F_SF | F_CONV},
+ {"csneg", 0x5a800400, 0x7fe00c00, condsel, 0, CORE, OP4 (Rd, Rn, Rm, COND), QL_CSEL, F_HAS_ALIAS | F_SF},
+ {"cneg", 0x5a800400, 0x7fe00c00, condsel, OP_CNEG, CORE, OP3 (Rd, Rn, COND), QL_CSEL, F_ALIAS | F_SF | F_CONV},
+ /* Crypto AES. */
+ {"aese", 0x4e284800, 0xfffffc00, cryptoaes, 0, CRYPTO, OP2 (Vd, Vn), QL_V2SAME16B, 0},
+ {"aesd", 0x4e285800, 0xfffffc00, cryptoaes, 0, CRYPTO, OP2 (Vd, Vn), QL_V2SAME16B, 0},
+ {"aesmc", 0x4e286800, 0xfffffc00, cryptoaes, 0, CRYPTO, OP2 (Vd, Vn), QL_V2SAME16B, 0},
+ {"aesimc", 0x4e287800, 0xfffffc00, cryptoaes, 0, CRYPTO, OP2 (Vd, Vn), QL_V2SAME16B, 0},
+ /* Crypto two-reg SHA. */
+ {"sha1h", 0x5e280800, 0xfffffc00, cryptosha2, 0, CRYPTO, OP2 (Fd, Fn), QL_2SAMES, 0},
+ {"sha1su1", 0x5e281800, 0xfffffc00, cryptosha2, 0, CRYPTO, OP2 (Vd, Vn), QL_V2SAME4S, 0},
+ {"sha256su0", 0x5e282800, 0xfffffc00, cryptosha2, 0, CRYPTO, OP2 (Vd, Vn), QL_V2SAME4S, 0},
+ /* Crypto three-reg SHA. */
+ {"sha1c", 0x5e000000, 0xffe0fc00, cryptosha3, 0, CRYPTO, OP3 (Fd, Fn, Vm), QL_SHAUPT, 0},
+ {"sha1p", 0x5e001000, 0xffe0fc00, cryptosha3, 0, CRYPTO, OP3 (Fd, Fn, Vm), QL_SHAUPT, 0},
+ {"sha1m", 0x5e002000, 0xffe0fc00, cryptosha3, 0, CRYPTO, OP3 (Fd, Fn, Vm), QL_SHAUPT, 0},
+ {"sha1su0", 0x5e003000, 0xffe0fc00, cryptosha3, 0, CRYPTO, OP3 (Vd, Vn, Vm), QL_V3SAME4S, 0},
+ {"sha256h", 0x5e004000, 0xffe0fc00, cryptosha3, 0, CRYPTO, OP3 (Fd, Fn, Vm), QL_SHA256UPT, 0},
+ {"sha256h2", 0x5e005000, 0xffe0fc00, cryptosha3, 0, CRYPTO, OP3 (Fd, Fn, Vm), QL_SHA256UPT, 0},
+ {"sha256su1", 0x5e006000, 0xffe0fc00, cryptosha3, 0, CRYPTO, OP3 (Vd, Vn, Vm), QL_V3SAME4S, 0},
+ /* Data-processing (1 source). */
+ {"rbit", 0x5ac00000, 0x7ffffc00, dp_1src, 0, CORE, OP2 (Rd, Rn), QL_I2SAME, F_SF},
+ {"rev16", 0x5ac00400, 0x7ffffc00, dp_1src, 0, CORE, OP2 (Rd, Rn), QL_I2SAME, F_SF},
+ {"rev", 0x5ac00800, 0xfffffc00, dp_1src, 0, CORE, OP2 (Rd, Rn), QL_I2SAMEW, 0},
+ {"rev", 0xdac00c00, 0x7ffffc00, dp_1src, 0, CORE, OP2 (Rd, Rn), QL_I2SAMEX, 0},
+ {"clz", 0x5ac01000, 0x7ffffc00, dp_1src, 0, CORE, OP2 (Rd, Rn), QL_I2SAME, F_SF},
+ {"cls", 0x5ac01400, 0x7ffffc00, dp_1src, 0, CORE, OP2 (Rd, Rn), QL_I2SAME, F_SF},
+ {"rev32", 0xdac00800, 0xfffffc00, dp_1src, 0, CORE, OP2 (Rd, Rn), QL_I2SAMEX, 0},
+ /* Data-processing (2 source). */
+ {"udiv", 0x1ac00800, 0x7fe0fc00, dp_2src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMER, F_SF},
+ {"sdiv", 0x1ac00c00, 0x7fe0fc00, dp_2src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMER, F_SF},
+ {"lslv", 0x1ac02000, 0x7fe0fc00, dp_2src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMER, F_SF | F_HAS_ALIAS},
+ {"lsl", 0x1ac02000, 0x7fe0fc00, dp_2src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMER, F_SF | F_ALIAS},
+ {"lsrv", 0x1ac02400, 0x7fe0fc00, dp_2src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMER, F_SF | F_HAS_ALIAS},
+ {"lsr", 0x1ac02400, 0x7fe0fc00, dp_2src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMER, F_SF | F_ALIAS},
+ {"asrv", 0x1ac02800, 0x7fe0fc00, dp_2src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMER, F_SF | F_HAS_ALIAS},
+ {"asr", 0x1ac02800, 0x7fe0fc00, dp_2src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMER, F_SF | F_ALIAS},
+ {"rorv", 0x1ac02c00, 0x7fe0fc00, dp_2src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMER, F_SF | F_HAS_ALIAS},
+ {"ror", 0x1ac02c00, 0x7fe0fc00, dp_2src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMER, F_SF | F_ALIAS},
+ /* Data-processing (3 source). */
+ {"madd", 0x1b000000, 0x7fe08000, dp_3src, 0, CORE, OP4 (Rd, Rn, Rm, Ra), QL_I4SAMER, F_HAS_ALIAS | F_SF},
+ {"mul", 0x1b007c00, 0x7fe0fc00, dp_3src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMER, F_ALIAS | F_SF},
+ {"msub", 0x1b008000, 0x7fe08000, dp_3src, 0, CORE, OP4 (Rd, Rn, Rm, Ra), QL_I4SAMER, F_HAS_ALIAS | F_SF},
+ {"mneg", 0x1b00fc00, 0x7fe0fc00, dp_3src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMER, F_ALIAS | F_SF},
+ {"smaddl", 0x9b200000, 0xffe08000, dp_3src, 0, CORE, OP4 (Rd, Rn, Rm, Ra), QL_I4SAMEL, F_HAS_ALIAS},
+ {"smull", 0x9b207c00, 0xffe0fc00, dp_3src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMEL, F_ALIAS},
+ {"smsubl", 0x9b208000, 0xffe08000, dp_3src, 0, CORE, OP4 (Rd, Rn, Rm, Ra), QL_I4SAMEL, F_HAS_ALIAS},
+ {"smnegl", 0x9b20fc00, 0xffe0fc00, dp_3src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMEL, F_ALIAS},
+ {"smulh", 0x9b407c00, 0xffe08000, dp_3src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMEX, 0},
+ {"umaddl", 0x9ba00000, 0xffe08000, dp_3src, 0, CORE, OP4 (Rd, Rn, Rm, Ra), QL_I4SAMEL, F_HAS_ALIAS},
+ {"umull", 0x9ba07c00, 0xffe0fc00, dp_3src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMEL, F_ALIAS},
+ {"umsubl", 0x9ba08000, 0xffe08000, dp_3src, 0, CORE, OP4 (Rd, Rn, Rm, Ra), QL_I4SAMEL, F_HAS_ALIAS},
+ {"umnegl", 0x9ba0fc00, 0xffe0fc00, dp_3src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMEL, F_ALIAS},
+ {"umulh", 0x9bc07c00, 0xffe08000, dp_3src, 0, CORE, OP3 (Rd, Rn, Rm), QL_I3SAMEX, 0},
+ /* Excep'n generation. */
+ {"svc", 0xd4000001, 0xffe0001f, exception, 0, CORE, OP1 (EXCEPTION), {}, 0},
+ {"hvc", 0xd4000002, 0xffe0001f, exception, 0, CORE, OP1 (EXCEPTION), {}, 0},
+ {"smc", 0xd4000003, 0xffe0001f, exception, 0, CORE, OP1 (EXCEPTION), {}, 0},
+ {"brk", 0xd4200000, 0xffe0001f, exception, 0, CORE, OP1 (EXCEPTION), {}, 0},
+ {"hlt", 0xd4400000, 0xffe0001f, exception, 0, CORE, OP1 (EXCEPTION), {}, 0},
+ {"dcps1", 0xd4a00001, 0xffe0001f, exception, 0, CORE, OP1 (EXCEPTION), {}, F_OPD0_OPT | F_DEFAULT (0)},
+ {"dcps2", 0xd4a00002, 0xffe0001f, exception, 0, CORE, OP1 (EXCEPTION), {}, F_OPD0_OPT | F_DEFAULT (0)},
+ {"dcps3", 0xd4a00003, 0xffe0001f, exception, 0, CORE, OP1 (EXCEPTION), {}, F_OPD0_OPT | F_DEFAULT (0)},
+ /* Extract. */
+ {"extr", 0x13800000, 0x7fa00000, extract, 0, CORE, OP4 (Rd, Rn, Rm, IMMS), QL_EXTR, F_HAS_ALIAS | F_SF | F_N},
+ {"ror", 0x13800000, 0x7fa00000, extract, OP_ROR_IMM, CORE, OP3 (Rd, Rm, IMMS), QL_SHIFT, F_ALIAS | F_CONV},
+ /* Floating-point<->fixed-point conversions. */
+ {"scvtf", 0x1e020000, 0x7f3f0000, float2fix, 0, FP, OP3 (Fd, Rn, FBITS), QL_FIX2FP, F_FPTYPE | F_SF},
+ {"ucvtf", 0x1e030000, 0x7f3f0000, float2fix, 0, FP, OP3 (Fd, Rn, FBITS), QL_FIX2FP, F_FPTYPE | F_SF},
+ {"fcvtzs", 0x1e180000, 0x7f3f0000, float2fix, 0, FP, OP3 (Rd, Fn, FBITS), QL_FP2FIX, F_FPTYPE | F_SF},
+ {"fcvtzu", 0x1e190000, 0x7f3f0000, float2fix, 0, FP, OP3 (Rd, Fn, FBITS), QL_FP2FIX, F_FPTYPE | F_SF},
+ /* Floating-point<->integer conversions. */
+ {"fcvtns", 0x1e200000, 0x7f3ffc00, float2int, 0, FP, OP2 (Rd, Fn), QL_FP2INT, F_FPTYPE | F_SF},
+ {"fcvtnu", 0x1e210000, 0x7f3ffc00, float2int, 0, FP, OP2 (Rd, Fn), QL_FP2INT, F_FPTYPE | F_SF},
+ {"scvtf", 0x1e220000, 0x7f3ffc00, float2int, 0, FP, OP2 (Fd, Rn), QL_INT2FP, F_FPTYPE | F_SF},
+ {"ucvtf", 0x1e230000, 0x7f3ffc00, float2int, 0, FP, OP2 (Fd, Rn), QL_INT2FP, F_FPTYPE | F_SF},
+ {"fcvtas", 0x1e240000, 0x7f3ffc00, float2int, 0, FP, OP2 (Rd, Fn), QL_FP2INT, F_FPTYPE | F_SF},
+ {"fcvtau", 0x1e250000, 0x7f3ffc00, float2int, 0, FP, OP2 (Rd, Fn), QL_FP2INT, F_FPTYPE | F_SF},
+ {"fmov", 0x1e260000, 0x7f3ffc00, float2int, 0, FP, OP2 (Rd, Fn), QL_FP2INT, F_FPTYPE | F_SF},
+ {"fmov", 0x1e270000, 0x7f3ffc00, float2int, 0, FP, OP2 (Fd, Rn), QL_INT2FP, F_FPTYPE | F_SF},
+ {"fcvtps", 0x1e280000, 0x7f3ffc00, float2int, 0, FP, OP2 (Rd, Fn), QL_FP2INT, F_FPTYPE | F_SF},
+ {"fcvtpu", 0x1e290000, 0x7f3ffc00, float2int, 0, FP, OP2 (Rd, Fn), QL_FP2INT, F_FPTYPE | F_SF},
+ {"fcvtms", 0x1e300000, 0x7f3ffc00, float2int, 0, FP, OP2 (Rd, Fn), QL_FP2INT, F_FPTYPE | F_SF},
+ {"fcvtmu", 0x1e310000, 0x7f3ffc00, float2int, 0, FP, OP2 (Rd, Fn), QL_FP2INT, F_FPTYPE | F_SF},
+ {"fcvtzs", 0x1e380000, 0x7f3ffc00, float2int, 0, FP, OP2 (Rd, Fn), QL_FP2INT, F_FPTYPE | F_SF},
+ {"fcvtzu", 0x1e390000, 0x7f3ffc00, float2int, 0, FP, OP2 (Rd, Fn), QL_FP2INT, F_FPTYPE | F_SF},
+ {"fmov", 0x9eae0000, 0xfffffc00, float2int, 0, FP, OP2 (Rd, VnD1), QL_XVD1, 0},
+ {"fmov", 0x9eaf0000, 0xfffffc00, float2int, 0, FP, OP2 (VdD1, Rn), QL_VD1X, 0},
+ /* Floating-point conditional compare. */
+ {"fccmp", 0x1e200400, 0xff200c10, floatccmp, 0, FP, OP4 (Fn, Fm, NZCV, COND), QL_FCCMP, F_FPTYPE},
+ {"fccmpe", 0x1e200410, 0xff200c10, floatccmp, 0, FP, OP4 (Fn, Fm, NZCV, COND), QL_FCCMP, F_FPTYPE},
+ /* Floating-point compare. */
+ {"fcmp", 0x1e202000, 0xff20fc1f, floatcmp, 0, FP, OP2 (Fn, Fm), QL_FP2, F_FPTYPE},
+ {"fcmpe", 0x1e202010, 0xff20fc1f, floatcmp, 0, FP, OP2 (Fn, Fm), QL_FP2, F_FPTYPE},
+ {"fcmp", 0x1e202008, 0xff20fc1f, floatcmp, 0, FP, OP2 (Fn, FPIMM0), QL_DST_SD, F_FPTYPE},
+ {"fcmpe", 0x1e202018, 0xff20fc1f, floatcmp, 0, FP, OP2 (Fn, FPIMM0), QL_DST_SD, F_FPTYPE},
+ /* Floating-point data-processing (1 source). */
+ {"fmov", 0x1e204000, 0xff3ffc00, floatdp1, 0, FP, OP2 (Fd, Fn), QL_FP2, F_FPTYPE},
+ {"fabs", 0x1e20c000, 0xff3ffc00, floatdp1, 0, FP, OP2 (Fd, Fn), QL_FP2, F_FPTYPE},
+ {"fneg", 0x1e214000, 0xff3ffc00, floatdp1, 0, FP, OP2 (Fd, Fn), QL_FP2, F_FPTYPE},
+ {"fsqrt", 0x1e21c000, 0xff3ffc00, floatdp1, 0, FP, OP2 (Fd, Fn), QL_FP2, F_FPTYPE},
+ {"fcvt", 0x1e224000, 0xff3e7c00, floatdp1, OP_FCVT, FP, OP2 (Fd, Fn), QL_FCVT, F_FPTYPE | F_MISC},
+ {"frintn", 0x1e244000, 0xff3ffc00, floatdp1, 0, FP, OP2 (Fd, Fn), QL_FP2, F_FPTYPE},
+ {"frintp", 0x1e24c000, 0xff3ffc00, floatdp1, 0, FP, OP2 (Fd, Fn), QL_FP2, F_FPTYPE},
+ {"frintm", 0x1e254000, 0xff3ffc00, floatdp1, 0, FP, OP2 (Fd, Fn), QL_FP2, F_FPTYPE},
+ {"frintz", 0x1e25c000, 0xff3ffc00, floatdp1, 0, FP, OP2 (Fd, Fn), QL_FP2, F_FPTYPE},
+ {"frinta", 0x1e264000, 0xff3ffc00, floatdp1, 0, FP, OP2 (Fd, Fn), QL_FP2, F_FPTYPE},
+ {"frintx", 0x1e274000, 0xff3ffc00, floatdp1, 0, FP, OP2 (Fd, Fn), QL_FP2, F_FPTYPE},
+ {"frinti", 0x1e27c000, 0xff3ffc00, floatdp1, 0, FP, OP2 (Fd, Fn), QL_FP2, F_FPTYPE},
+ /* Floating-point data-processing (2 source). */
+ {"fmul", 0x1e200800, 0xff20fc00, floatdp2, 0, FP, OP3 (Fd, Fn, Fm), QL_FP3, F_FPTYPE},
+ {"fdiv", 0x1e201800, 0xff20fc00, floatdp2, 0, FP, OP3 (Fd, Fn, Fm), QL_FP3, F_FPTYPE},
+ {"fadd", 0x1e202800, 0xff20fc00, floatdp2, 0, FP, OP3 (Fd, Fn, Fm), QL_FP3, F_FPTYPE},
+ {"fsub", 0x1e203800, 0xff20fc00, floatdp2, 0, FP, OP3 (Fd, Fn, Fm), QL_FP3, F_FPTYPE},
+ {"fmax", 0x1e204800, 0xff20fc00, floatdp2, 0, FP, OP3 (Fd, Fn, Fm), QL_FP3, F_FPTYPE},
+ {"fmin", 0x1e205800, 0xff20fc00, floatdp2, 0, FP, OP3 (Fd, Fn, Fm), QL_FP3, F_FPTYPE},
+ {"fmaxnm", 0x1e206800, 0xff20fc00, floatdp2, 0, FP, OP3 (Fd, Fn, Fm), QL_FP3, F_FPTYPE},
+ {"fminnm", 0x1e207800, 0xff20fc00, floatdp2, 0, FP, OP3 (Fd, Fn, Fm), QL_FP3, F_FPTYPE},
+ {"fnmul", 0x1e208800, 0xff20fc00, floatdp2, 0, FP, OP3 (Fd, Fn, Fm), QL_FP3, F_FPTYPE},
+ /* Floating-point data-processing (3 source). */
+ {"fmadd", 0x1f000000, 0xff208000, floatdp3, 0, FP, OP4 (Fd, Fn, Fm, Fa), QL_FP4, F_FPTYPE},
+ {"fmsub", 0x1f008000, 0xff208000, floatdp3, 0, FP, OP4 (Fd, Fn, Fm, Fa), QL_FP4, F_FPTYPE},
+ {"fnmadd", 0x1f200000, 0xff208000, floatdp3, 0, FP, OP4 (Fd, Fn, Fm, Fa), QL_FP4, F_FPTYPE},
+ {"fnmsub", 0x1f208000, 0xff208000, floatdp3, 0, FP, OP4 (Fd, Fn, Fm, Fa), QL_FP4, F_FPTYPE},
+ /* Floating-point immediate. */
+ {"fmov", 0x1e201000, 0xff201fe0, floatimm, 0, FP, OP2 (Fd, FPIMM), QL_DST_SD, F_FPTYPE},
+ /* Floating-point conditional select. */
+ {"fcsel", 0x1e200c00, 0xff200c00, floatsel, 0, FP, OP4 (Fd, Fn, Fm, COND), QL_FP_COND, F_FPTYPE},
+ /* Load/store register (immediate indexed). */
+ {"strb", 0x38000400, 0xffe00400, ldst_imm9, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_W8, 0},
+ {"ldrb", 0x38400400, 0xffe00400, ldst_imm9, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_W8, 0},
+ {"ldrsb", 0x38800400, 0xffa00400, ldst_imm9, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_R8, F_LDS_SIZE},
+ {"str", 0x3c000400, 0x3f600400, ldst_imm9, 0, CORE, OP2 (Ft, ADDR_SIMM9), QL_LDST_FP, 0},
+ {"ldr", 0x3c400400, 0x3f600400, ldst_imm9, 0, CORE, OP2 (Ft, ADDR_SIMM9), QL_LDST_FP, 0},
+ {"strh", 0x78000400, 0xffe00400, ldst_imm9, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_W16, 0},
+ {"ldrh", 0x78400400, 0xffe00400, ldst_imm9, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_W16, 0},
+ {"ldrsh", 0x78800400, 0xffa00400, ldst_imm9, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_R16, F_LDS_SIZE},
+ {"str", 0xb8000400, 0xbfe00400, ldst_imm9, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_R, F_GPRSIZE_IN_Q},
+ {"ldr", 0xb8400400, 0xbfe00400, ldst_imm9, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_R, F_GPRSIZE_IN_Q},
+ {"ldrsw", 0xb8800400, 0xffe00400, ldst_imm9, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_X32, 0},
+ /* Load/store register (unsigned immediate). */
+ {"strb", 0x39000000, 0xffc00000, ldst_pos, OP_STRB_POS, CORE, OP2 (Rt, ADDR_UIMM12), QL_LDST_W8, 0},
+ {"ldrb", 0x39400000, 0xffc00000, ldst_pos, OP_LDRB_POS, CORE, OP2 (Rt, ADDR_UIMM12), QL_LDST_W8, 0},
+ {"ldrsb", 0x39800000, 0xff800000, ldst_pos, OP_LDRSB_POS, CORE, OP2 (Rt, ADDR_UIMM12), QL_LDST_R8, F_LDS_SIZE},
+ {"str", 0x3d000000, 0x3f400000, ldst_pos, OP_STRF_POS, CORE, OP2 (Ft, ADDR_UIMM12), QL_LDST_FP, 0},
+ {"ldr", 0x3d400000, 0x3f400000, ldst_pos, OP_LDRF_POS, CORE, OP2 (Ft, ADDR_UIMM12), QL_LDST_FP, 0},
+ {"strh", 0x79000000, 0xffc00000, ldst_pos, OP_STRH_POS, CORE, OP2 (Rt, ADDR_UIMM12), QL_LDST_W16, 0},
+ {"ldrh", 0x79400000, 0xffc00000, ldst_pos, OP_LDRH_POS, CORE, OP2 (Rt, ADDR_UIMM12), QL_LDST_W16, 0},
+ {"ldrsh", 0x79800000, 0xff800000, ldst_pos, OP_LDRSH_POS, CORE, OP2 (Rt, ADDR_UIMM12), QL_LDST_R16, F_LDS_SIZE},
+ {"str", 0xb9000000, 0xbfc00000, ldst_pos, OP_STR_POS, CORE, OP2 (Rt, ADDR_UIMM12), QL_LDST_R, F_GPRSIZE_IN_Q},
+ {"ldr", 0xb9400000, 0xbfc00000, ldst_pos, OP_LDR_POS, CORE, OP2 (Rt, ADDR_UIMM12), QL_LDST_R, F_GPRSIZE_IN_Q},
+ {"ldrsw", 0xb9800000, 0xffc00000, ldst_pos, OP_LDRSW_POS, CORE, OP2 (Rt, ADDR_UIMM12), QL_LDST_X32, 0},
+ {"prfm", 0xf9800000, 0xffc00000, ldst_pos, OP_PRFM_POS, CORE, OP2 (PRFOP, ADDR_UIMM12), QL_LDST_PRFM, 0},
+ /* Load/store register (register offset). */
+ {"strb", 0x38200800, 0xffe00c00, ldst_regoff, 0, CORE, OP2 (Rt, ADDR_REGOFF), QL_LDST_W8, 0},
+ {"ldrb", 0x38600800, 0xffe00c00, ldst_regoff, 0, CORE, OP2 (Rt, ADDR_REGOFF), QL_LDST_W8, 0},
+ {"ldrsb", 0x38a00800, 0xffa00c00, ldst_regoff, 0, CORE, OP2 (Rt, ADDR_REGOFF), QL_LDST_R8, F_LDS_SIZE},
+ {"str", 0x3c200800, 0x3f600c00, ldst_regoff, 0, CORE, OP2 (Ft, ADDR_REGOFF), QL_LDST_FP, 0},
+ {"ldr", 0x3c600800, 0x3f600c00, ldst_regoff, 0, CORE, OP2 (Ft, ADDR_REGOFF), QL_LDST_FP, 0},
+ {"strh", 0x78200800, 0xffe00c00, ldst_regoff, 0, CORE, OP2 (Rt, ADDR_REGOFF), QL_LDST_W16, 0},
+ {"ldrh", 0x78600800, 0xffe00c00, ldst_regoff, 0, CORE, OP2 (Rt, ADDR_REGOFF), QL_LDST_W16, 0},
+ {"ldrsh", 0x78a00800, 0xffa00c00, ldst_regoff, 0, CORE, OP2 (Rt, ADDR_REGOFF), QL_LDST_R16, F_LDS_SIZE},
+ {"str", 0xb8200800, 0xbfe00c00, ldst_regoff, 0, CORE, OP2 (Rt, ADDR_REGOFF), QL_LDST_R, F_GPRSIZE_IN_Q},
+ {"ldr", 0xb8600800, 0xbfe00c00, ldst_regoff, 0, CORE, OP2 (Rt, ADDR_REGOFF), QL_LDST_R, F_GPRSIZE_IN_Q},
+ {"ldrsw", 0xb8a00800, 0xffe00c00, ldst_regoff, 0, CORE, OP2 (Rt, ADDR_REGOFF), QL_LDST_X32, 0},
+ {"prfm", 0xf8a00800, 0xffe00c00, ldst_regoff, 0, CORE, OP2 (PRFOP, ADDR_REGOFF), QL_LDST_PRFM, 0},
+ /* Load/store register (unprivileged). */
+ {"sttrb", 0x38000800, 0xffe00c00, ldst_unpriv, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_W8, 0},
+ {"ldtrb", 0x38400800, 0xffe00c00, ldst_unpriv, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_W8, 0},
+ {"ldtrsb", 0x38800800, 0xffa00c00, ldst_unpriv, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_R8, F_LDS_SIZE},
+ {"sttrh", 0x78000800, 0xffe00c00, ldst_unpriv, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_W16, 0},
+ {"ldtrh", 0x78400800, 0xffe00c00, ldst_unpriv, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_W16, 0},
+ {"ldtrsh", 0x78800800, 0xffa00c00, ldst_unpriv, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_R16, F_LDS_SIZE},
+ {"sttr", 0xb8000800, 0xbfe00c00, ldst_unpriv, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_R, F_GPRSIZE_IN_Q},
+ {"ldtr", 0xb8400800, 0xbfe00c00, ldst_unpriv, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_R, F_GPRSIZE_IN_Q},
+ {"ldtrsw", 0xb8800800, 0xffe00c00, ldst_unpriv, 0, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_X32, 0},
+ /* Load/store register (unscaled immediate). */
+ {"sturb", 0x38000000, 0xffe00c00, ldst_unscaled, OP_STURB, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_W8, F_HAS_ALIAS},
+ {"ldurb", 0x38400000, 0xffe00c00, ldst_unscaled, OP_LDURB, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_W8, F_HAS_ALIAS},
+ {"strb", 0x38000000, 0xffe00c00, ldst_unscaled, 0, CORE, OP2 (Rt, ADDR_SIMM9_2), QL_LDST_W8, F_ALIAS},
+ {"ldrb", 0x38400000, 0xffe00c00, ldst_unscaled, 0, CORE, OP2 (Rt, ADDR_SIMM9_2), QL_LDST_W8, F_ALIAS},
+ {"ldursb", 0x38800000, 0xffa00c00, ldst_unscaled, OP_LDURSB, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_R8, F_HAS_ALIAS | F_LDS_SIZE},
+ {"ldrsb", 0x38800000, 0xffa00c00, ldst_unscaled, 0, CORE, OP2 (Rt, ADDR_SIMM9_2), QL_LDST_R8, F_ALIAS | F_LDS_SIZE},
+ {"stur", 0x3c000000, 0x3f600c00, ldst_unscaled, OP_STURV, CORE, OP2 (Ft, ADDR_SIMM9), QL_LDST_FP, F_HAS_ALIAS},
+ {"ldur", 0x3c400000, 0x3f600c00, ldst_unscaled, OP_LDURV, CORE, OP2 (Ft, ADDR_SIMM9), QL_LDST_FP, F_HAS_ALIAS},
+ {"str", 0x3c000000, 0x3f600c00, ldst_unscaled, 0, CORE, OP2 (Ft, ADDR_SIMM9_2), QL_LDST_FP, F_ALIAS},
+ {"ldr", 0x3c400000, 0x3f600c00, ldst_unscaled, 0, CORE, OP2 (Ft, ADDR_SIMM9_2), QL_LDST_FP, F_ALIAS},
+ {"sturh", 0x78000000, 0xffe00c00, ldst_unscaled, OP_STURH, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_W16, F_HAS_ALIAS},
+ {"ldurh", 0x78400000, 0xffe00c00, ldst_unscaled, OP_LDURH, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_W16, F_HAS_ALIAS},
+ {"strh", 0x78000000, 0xffe00c00, ldst_unscaled, 0, CORE, OP2 (Rt, ADDR_SIMM9_2), QL_LDST_W16, F_ALIAS},
+ {"ldrh", 0x78400000, 0xffe00c00, ldst_unscaled, 0, CORE, OP2 (Rt, ADDR_SIMM9_2), QL_LDST_W16, F_ALIAS},
+ {"ldursh", 0x78800000, 0xffa00c00, ldst_unscaled, OP_LDURSH, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_R16, F_HAS_ALIAS | F_LDS_SIZE},
+ {"ldrsh", 0x78800000, 0xffa00c00, ldst_unscaled, 0, CORE, OP2 (Rt, ADDR_SIMM9_2), QL_LDST_R16, F_ALIAS | F_LDS_SIZE},
+ {"stur", 0xb8000000, 0xbfe00c00, ldst_unscaled, OP_STUR, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_R, F_HAS_ALIAS | F_GPRSIZE_IN_Q},
+ {"ldur", 0xb8400000, 0xbfe00c00, ldst_unscaled, OP_LDUR, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_R, F_HAS_ALIAS | F_GPRSIZE_IN_Q},
+ {"str", 0xb8000000, 0xbfe00c00, ldst_unscaled, 0, CORE, OP2 (Rt, ADDR_SIMM9_2), QL_LDST_R, F_ALIAS | F_GPRSIZE_IN_Q},
+ {"ldr", 0xb8400000, 0xbfe00c00, ldst_unscaled, 0, CORE, OP2 (Rt, ADDR_SIMM9_2), QL_LDST_R, F_ALIAS | F_GPRSIZE_IN_Q},
+ {"ldursw", 0xb8800000, 0xffe00c00, ldst_unscaled, OP_LDURSW, CORE, OP2 (Rt, ADDR_SIMM9), QL_LDST_X32, F_HAS_ALIAS},
+ {"ldrsw", 0xb8800000, 0xffe00c00, ldst_unscaled, 0, CORE, OP2 (Rt, ADDR_SIMM9_2), QL_LDST_X32, F_ALIAS},
+ {"prfum", 0xf8800000, 0xffe00c00, ldst_unscaled, OP_PRFUM, CORE, OP2 (PRFOP, ADDR_SIMM9), QL_LDST_PRFM, F_HAS_ALIAS},
+ {"prfm", 0xf8800000, 0xffe00c00, ldst_unscaled, 0, CORE, OP2 (PRFOP, ADDR_SIMM9_2), QL_LDST_PRFM, F_ALIAS},
+ /* Load/store exclusive. */
+ {"stxrb", 0x8007c00, 0xffe08000, ldstexcl, 0, CORE, OP3 (Rs, Rt, ADDR_SIMPLE), QL_W2_LDST_EXC, 0},
+ {"stlxrb", 0x800fc00, 0xffe08000, ldstexcl, 0, CORE, OP3 (Rs, Rt, ADDR_SIMPLE), QL_W2_LDST_EXC, 0},
+ {"ldxrb", 0x85f7c00, 0xffe08000, ldstexcl, 0, CORE, OP2 (Rt, ADDR_SIMPLE), QL_W1_LDST_EXC, 0},
+ {"ldaxrb", 0x85ffc00, 0xffe08000, ldstexcl, 0, CORE, OP2 (Rt, ADDR_SIMPLE), QL_W1_LDST_EXC, 0},
+ {"stlrb", 0x89ffc00, 0xffe08000, ldstexcl, 0, CORE, OP2 (Rt, ADDR_SIMPLE), QL_W1_LDST_EXC, 0},
+ {"ldarb", 0x8dffc00, 0xffe08000, ldstexcl, 0, CORE, OP2 (Rt, ADDR_SIMPLE), QL_W1_LDST_EXC, 0},
+ {"stxrh", 0x48007c00, 0xffe08000, ldstexcl, 0, CORE, OP3 (Rs, Rt, ADDR_SIMPLE), QL_W2_LDST_EXC, 0},
+ {"stlxrh", 0x4800fc00, 0xffe08000, ldstexcl, 0, CORE, OP3 (Rs, Rt, ADDR_SIMPLE), QL_W2_LDST_EXC, 0},
+ {"ldxrh", 0x485f7c00, 0xffe08000, ldstexcl, 0, CORE, OP2 (Rt, ADDR_SIMPLE), QL_W1_LDST_EXC, 0},
+ {"ldaxrh", 0x485ffc00, 0xffe08000, ldstexcl, 0, CORE, OP2 (Rt, ADDR_SIMPLE), QL_W1_LDST_EXC, 0},
+ {"stlrh", 0x489ffc00, 0xffe08000, ldstexcl, 0, CORE, OP2 (Rt, ADDR_SIMPLE), QL_W1_LDST_EXC, 0},
+ {"ldarh", 0x48dffc00, 0xffe08000, ldstexcl, 0, CORE, OP2 (Rt, ADDR_SIMPLE), QL_W1_LDST_EXC, 0},
+ {"stxr", 0x88007c00, 0xbfe08000, ldstexcl, 0, CORE, OP3 (Rs, Rt, ADDR_SIMPLE), QL_R2_LDST_EXC, F_GPRSIZE_IN_Q},
+ {"stlxr", 0x8800fc00, 0xbfe08000, ldstexcl, 0, CORE, OP3 (Rs, Rt, ADDR_SIMPLE), QL_R2_LDST_EXC, F_GPRSIZE_IN_Q},
+ {"stxp", 0x88200000, 0xbfe08000, ldstexcl, 0, CORE, OP4 (Rs, Rt, Rt2, ADDR_SIMPLE), QL_R3_LDST_EXC, F_GPRSIZE_IN_Q},
+ {"stlxp", 0x88208000, 0xbfe08000, ldstexcl, 0, CORE, OP4 (Rs, Rt, Rt2, ADDR_SIMPLE), QL_R3_LDST_EXC, F_GPRSIZE_IN_Q},
+ {"ldxr", 0x885f7c00, 0xbfe08000, ldstexcl, 0, CORE, OP2 (Rt, ADDR_SIMPLE), QL_R1NIL, F_GPRSIZE_IN_Q},
+ {"ldaxr", 0x885ffc00, 0xbfe08000, ldstexcl, 0, CORE, OP2 (Rt, ADDR_SIMPLE), QL_R1NIL, F_GPRSIZE_IN_Q},
+ {"ldxp", 0x887f0000, 0xbfe08000, ldstexcl, 0, CORE, OP3 (Rt, Rt2, ADDR_SIMPLE), QL_R2NIL, F_GPRSIZE_IN_Q},
+ {"ldaxp", 0x887f8000, 0xbfe08000, ldstexcl, 0, CORE, OP3 (Rt, Rt2, ADDR_SIMPLE), QL_R2NIL, F_GPRSIZE_IN_Q},
+ {"stlr", 0x889ffc00, 0xbfe08000, ldstexcl, 0, CORE, OP2 (Rt, ADDR_SIMPLE), QL_R1NIL, F_GPRSIZE_IN_Q},
+ {"ldar", 0x88dffc00, 0xbfe08000, ldstexcl, 0, CORE, OP2 (Rt, ADDR_SIMPLE), QL_R1NIL, F_GPRSIZE_IN_Q},
+ /* Load/store no-allocate pair (offset). */
+ {"stnp", 0x28000000, 0x7fc00000, ldstnapair_offs, 0, CORE, OP3 (Rt, Rt2, ADDR_SIMM7), QL_LDST_PAIR_R, F_SF},
+ {"ldnp", 0x28400000, 0x7fc00000, ldstnapair_offs, 0, CORE, OP3 (Rt, Rt2, ADDR_SIMM7), QL_LDST_PAIR_R, F_SF},
+ {"stnp", 0x2c000000, 0x3fc00000, ldstnapair_offs, 0, CORE, OP3 (Ft, Ft2, ADDR_SIMM7), QL_LDST_PAIR_FP, 0},
+ {"ldnp", 0x2c400000, 0x3fc00000, ldstnapair_offs, 0, CORE, OP3 (Ft, Ft2, ADDR_SIMM7), QL_LDST_PAIR_FP, 0},
+ /* Load/store register pair (offset). */
+ {"stp", 0x29000000, 0x7ec00000, ldstpair_off, 0, CORE, OP3 (Rt, Rt2, ADDR_SIMM7), QL_LDST_PAIR_R, F_SF},
+ {"ldp", 0x29400000, 0x7ec00000, ldstpair_off, 0, CORE, OP3 (Rt, Rt2, ADDR_SIMM7), QL_LDST_PAIR_R, F_SF},
+ {"stp", 0x2d000000, 0x3fc00000, ldstpair_off, 0, CORE, OP3 (Ft, Ft2, ADDR_SIMM7), QL_LDST_PAIR_FP, 0},
+ {"ldp", 0x2d400000, 0x3fc00000, ldstpair_off, 0, CORE, OP3 (Ft, Ft2, ADDR_SIMM7), QL_LDST_PAIR_FP, 0},
+ {"ldpsw", 0x69400000, 0xffc00000, ldstpair_off, 0, CORE, OP3 (Rt, Rt2, ADDR_SIMM7), QL_LDST_PAIR_X32, 0},
+ /* Load/store register pair (indexed). */
+ {"stp", 0x28800000, 0x7ec00000, ldstpair_indexed, 0, CORE, OP3 (Rt, Rt2, ADDR_SIMM7), QL_LDST_PAIR_R, F_SF},
+ {"ldp", 0x28c00000, 0x7ec00000, ldstpair_indexed, 0, CORE, OP3 (Rt, Rt2, ADDR_SIMM7), QL_LDST_PAIR_R, F_SF},
+ {"stp", 0x2c800000, 0x3ec00000, ldstpair_indexed, 0, CORE, OP3 (Ft, Ft2, ADDR_SIMM7), QL_LDST_PAIR_FP, 0},
+ {"ldp", 0x2cc00000, 0x3ec00000, ldstpair_indexed, 0, CORE, OP3 (Ft, Ft2, ADDR_SIMM7), QL_LDST_PAIR_FP, 0},
+ {"ldpsw", 0x68c00000, 0xfec00000, ldstpair_indexed, 0, CORE, OP3 (Rt, Rt2, ADDR_SIMM7), QL_LDST_PAIR_X32, 0},
+ /* Load register (literal). */
+ {"ldr", 0x18000000, 0xbf000000, loadlit, OP_LDR_LIT, CORE, OP2 (Rt, ADDR_PCREL19), QL_R_PCREL, F_GPRSIZE_IN_Q},
+ {"ldr", 0x1c000000, 0x3f000000, loadlit, OP_LDRV_LIT, CORE, OP2 (Ft, ADDR_PCREL19), QL_FP_PCREL, 0},
+ {"ldrsw", 0x98000000, 0xff000000, loadlit, OP_LDRSW_LIT, CORE, OP2 (Rt, ADDR_PCREL19), QL_X_PCREL, 0},
+ {"prfm", 0xd8000000, 0xff000000, loadlit, OP_PRFM_LIT, CORE, OP2 (PRFOP, ADDR_PCREL19), QL_PRFM_PCREL, 0},
+ /* Logical (immediate). */
+ {"and", 0x12000000, 0x7f800000, log_imm, 0, CORE, OP3 (Rd_SP, Rn, LIMM), QL_R2NIL, F_HAS_ALIAS | F_SF},
+ {"bic", 0x12000000, 0x7f800000, log_imm, OP_BIC, CORE, OP3 (Rd_SP, Rn, LIMM), QL_R2NIL, F_ALIAS | F_PSEUDO | F_SF},
+ {"orr", 0x32000000, 0x7f800000, log_imm, 0, CORE, OP3 (Rd_SP, Rn, LIMM), QL_R2NIL, F_HAS_ALIAS | F_SF},
+ {"mov", 0x320003e0, 0x7f8003e0, log_imm, OP_MOV_IMM_LOG, CORE, OP2 (Rd_SP, IMM_MOV), QL_R1NIL, F_ALIAS | F_PSEUDO | F_P1 | F_SF | F_CONV},
+ {"eor", 0x52000000, 0x7f800000, log_imm, 0, CORE, OP3 (Rd_SP, Rn, LIMM), QL_R2NIL, F_SF},
+ {"ands", 0x72000000, 0x7f800000, log_imm, 0, CORE, OP3 (Rd, Rn, LIMM), QL_R2NIL, F_HAS_ALIAS | F_SF},
+ {"tst", 0x7200001f, 0x7f80001f, log_imm, 0, CORE, OP2 (Rn, LIMM), QL_R1NIL, F_ALIAS | F_SF},
+ /* Logical (shifted register). */
+ {"and", 0xa000000, 0x7f200000, log_shift, 0, CORE, OP3 (Rd, Rn, Rm_SFT), QL_I3SAMER, F_SF},
+ {"bic", 0xa200000, 0x7f200000, log_shift, 0, CORE, OP3 (Rd, Rn, Rm_SFT), QL_I3SAMER, F_SF},
+ {"orr", 0x2a000000, 0x7f200000, log_shift, 0, CORE, OP3 (Rd, Rn, Rm_SFT), QL_I3SAMER, F_HAS_ALIAS | F_SF},
+ {"mov", 0x2a0003e0, 0x7f2003e0, log_shift, 0, CORE, OP2 (Rd, Rm), QL_I2SAMER, F_ALIAS | F_SF},
+ {"uxtw", 0x2a0003e0, 0x7f2003e0, log_shift, OP_UXTW, CORE, OP2 (Rd, Rm), QL_I2SAMEW, F_ALIAS | F_PSEUDO},
+ {"orn", 0x2a200000, 0x7f200000, log_shift, 0, CORE, OP3 (Rd, Rn, Rm_SFT), QL_I3SAMER, F_HAS_ALIAS | F_SF},
+ {"mvn", 0x2a2003e0, 0x7f2003e0, log_shift, 0, CORE, OP2 (Rd, Rm_SFT), QL_I2SAMER, F_ALIAS | F_SF},
+ {"eor", 0x4a000000, 0x7f200000, log_shift, 0, CORE, OP3 (Rd, Rn, Rm_SFT), QL_I3SAMER, F_SF},
+ {"eon", 0x4a200000, 0x7f200000, log_shift, 0, CORE, OP3 (Rd, Rn, Rm_SFT), QL_I3SAMER, F_SF},
+ {"ands", 0x6a000000, 0x7f200000, log_shift, 0, CORE, OP3 (Rd, Rn, Rm_SFT), QL_I3SAMER, F_HAS_ALIAS | F_SF},
+ {"tst", 0x6a00001f, 0x7f20001f, log_shift, 0, CORE, OP2 (Rn, Rm_SFT), QL_I2SAMER, F_ALIAS | F_SF},
+ {"bics", 0x6a200000, 0x7f200000, log_shift, 0, CORE, OP3 (Rd, Rn, Rm_SFT), QL_I3SAMER, F_SF},
+ /* Move wide (immediate). */
+ {"movn", 0x12800000, 0x7f800000, movewide, OP_MOVN, CORE, OP2 (Rd, HALF), QL_DST_R, F_SF | F_HAS_ALIAS},
+ {"mov", 0x12800000, 0x7f800000, movewide, OP_MOV_IMM_WIDEN, CORE, OP2 (Rd, IMM_MOV), QL_DST_R, F_SF | F_ALIAS | F_PSEUDO | F_CONV},
+ {"movz", 0x52800000, 0x7f800000, movewide, OP_MOVZ, CORE, OP2 (Rd, HALF), QL_DST_R, F_SF | F_HAS_ALIAS},
+ {"mov", 0x52800000, 0x7f800000, movewide, OP_MOV_IMM_WIDE, CORE, OP2 (Rd, IMM_MOV), QL_DST_R, F_SF | F_ALIAS | F_PSEUDO | F_CONV},
+ {"movk", 0x72800000, 0x7f800000, movewide, OP_MOVK, CORE, OP2 (Rd, HALF), QL_DST_R, F_SF},
+ /* PC-rel. addressing. */
+ {"adr", 0x10000000, 0x9f000000, pcreladdr, 0, CORE, OP2 (Rd, ADDR_PCREL21), QL_ADRP, 0},
+ {"adrp", 0x90000000, 0x9f000000, pcreladdr, 0, CORE, OP2 (Rd, ADDR_ADRP), QL_ADRP, 0},
+ /* System. */
+ {"msr", 0xd500401f, 0xfff8f01f, ic_system, 0, CORE, OP2 (PSTATEFIELD, UIMM4), {}, 0},
+ {"hint", 0xd503201f, 0xfffff01f, ic_system, 0, CORE, OP1 (UIMM7), {}, F_HAS_ALIAS},
+ {"nop", 0xd503201f, 0xffffffff, ic_system, 0, CORE, OP0 (), {}, F_ALIAS},
+ {"yield", 0xd503203f, 0xffffffff, ic_system, 0, CORE, OP0 (), {}, F_ALIAS},
+ {"wfe", 0xd503205f, 0xffffffff, ic_system, 0, CORE, OP0 (), {}, F_ALIAS},
+ {"wfi", 0xd503207f, 0xffffffff, ic_system, 0, CORE, OP0 (), {}, F_ALIAS},
+ {"sev", 0xd503209f, 0xffffffff, ic_system, 0, CORE, OP0 (), {}, F_ALIAS},
+ {"sevl", 0xd50320bf, 0xffffffff, ic_system, 0, CORE, OP0 (), {}, F_ALIAS},
+ {"clrex", 0xd503305f, 0xfffff0ff, ic_system, 0, CORE, OP1 (UIMM4), {}, F_OPD0_OPT | F_DEFAULT (0xF)},
+ {"dsb", 0xd503309f, 0xfffff0ff, ic_system, 0, CORE, OP1 (BARRIER), {}, 0},
+ {"dmb", 0xd50330bf, 0xfffff0ff, ic_system, 0, CORE, OP1 (BARRIER), {}, 0},
+ {"isb", 0xd50330df, 0xfffff0ff, ic_system, 0, CORE, OP1 (BARRIER_ISB), {}, F_OPD0_OPT | F_DEFAULT (0xF)},
+ {"sys", 0xd5080000, 0xfff80000, ic_system, 0, CORE, OP5 (UIMM3_OP1, Cn, Cm, UIMM3_OP2, Rt), QL_SYS, F_HAS_ALIAS | F_OPD4_OPT | F_DEFAULT (0x1F)},
+ {"at", 0xd5080000, 0xfff80000, ic_system, 0, CORE, OP2 (SYSREG_AT, Rt), QL_SRC_X, F_ALIAS},
+ {"dc", 0xd5080000, 0xfff80000, ic_system, 0, CORE, OP2 (SYSREG_DC, Rt), QL_SRC_X, F_ALIAS},
+ {"ic", 0xd5080000, 0xfff80000, ic_system, 0, CORE, OP2 (SYSREG_IC, Rt_SYS), QL_SRC_X, F_ALIAS | F_OPD1_OPT | F_DEFAULT (0x1F)},
+ {"tlbi", 0xd5080000, 0xfff80000, ic_system, 0, CORE, OP2 (SYSREG_TLBI, Rt_SYS), QL_SRC_X, F_ALIAS | F_OPD1_OPT | F_DEFAULT (0x1F)},
+ {"msr", 0xd5100000, 0xfff00000, ic_system, 0, CORE, OP2 (SYSREG, Rt), QL_SRC_X, 0},
+ {"sysl", 0xd5280000, 0xfff80000, ic_system, 0, CORE, OP5 (Rt, UIMM3_OP1, Cn, Cm, UIMM3_OP2), QL_SYSL, 0},
+ {"mrs", 0xd5300000, 0xfff00000, ic_system, 0, CORE, OP2 (Rt, SYSREG), QL_DST_X, 0},
+ /* Test & branch (immediate). */
+ {"tbz", 0x36000000, 0x7f000000, testbranch, 0, CORE, OP3 (Rt, BIT_NUM, ADDR_PCREL14), QL_PCREL_14, 0},
+ {"tbnz", 0x37000000, 0x7f000000, testbranch, 0, CORE, OP3 (Rt, BIT_NUM, ADDR_PCREL14), QL_PCREL_14, 0},
+ /* The old UAL conditional branch mnemonics (to aid portability). */
+ {"beq", 0x54000000, 0xff00001f, condbranch, 0, CORE, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO},
+ {"bne", 0x54000001, 0xff00001f, condbranch, 0, CORE, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO},
+ {"bcs", 0x54000002, 0xff00001f, condbranch, 0, CORE, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO},
+ {"bhs", 0x54000002, 0xff00001f, condbranch, 0, CORE, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO},
+ {"bcc", 0x54000003, 0xff00001f, condbranch, 0, CORE, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO},
+ {"blo", 0x54000003, 0xff00001f, condbranch, 0, CORE, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO},
+ {"bmi", 0x54000004, 0xff00001f, condbranch, 0, CORE, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO},
+ {"bpl", 0x54000005, 0xff00001f, condbranch, 0, CORE, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO},
+ {"bvs", 0x54000006, 0xff00001f, condbranch, 0, CORE, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO},
+ {"bvc", 0x54000007, 0xff00001f, condbranch, 0, CORE, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO},
+ {"bhi", 0x54000008, 0xff00001f, condbranch, 0, CORE, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO},
+ {"bls", 0x54000009, 0xff00001f, condbranch, 0, CORE, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO},
+ {"bge", 0x5400000a, 0xff00001f, condbranch, 0, CORE, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO},
+ {"blt", 0x5400000b, 0xff00001f, condbranch, 0, CORE, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO},
+ {"bgt", 0x5400000c, 0xff00001f, condbranch, 0, CORE, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO},
+ {"ble", 0x5400000d, 0xff00001f, condbranch, 0, CORE, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO},
+
+ {0, 0, 0, 0, 0, 0, {}, {}, 0},
+};
+
+#ifdef AARCH64_OPERANDS
+#undef AARCH64_OPERANDS
+#endif
+
+/* Macro-based operand decription; this will be fed into aarch64-gen for it
+ to generate the structure aarch64_operands and the function
+ aarch64_insert_operand and aarch64_extract_operand.
+
+ These inserters and extracters in the description execute the conversion
+ between the aarch64_opnd_info and value in the operand-related instruction
+ field(s). */
+
+/* Y expects arguments (left to right) to be operand class, inserter/extractor
+ name suffix, operand name, flags, related bitfield(s) and description.
+ X only differs from Y by having the operand inserter and extractor names
+ listed separately. */
+
+#define AARCH64_OPERANDS \
+ Y(INT_REG, regno, "Rd", 0, F(FLD_Rd), "an integer register") \
+ Y(INT_REG, regno, "Rn", 0, F(FLD_Rn), "an integer register") \
+ Y(INT_REG, regno, "Rm", 0, F(FLD_Rm), "an integer register") \
+ Y(INT_REG, regno, "Rt", 0, F(FLD_Rt), "an integer register") \
+ Y(INT_REG, regno, "Rt2", 0, F(FLD_Rt2), "an integer register") \
+ Y(INT_REG, regno, "Rs", 0, F(FLD_Rs), "an integer register") \
+ Y(INT_REG, regno, "Ra", 0, F(FLD_Ra), "an integer register") \
+ X(INT_REG, ins_regno, ext_regrt_sysins, "Rt_SYS", 0, F(FLD_Rt), \
+ "an integer register") \
+ Y(INT_REG, regno, "Rd_SP", OPD_F_MAYBE_SP, F(FLD_Rd), \
+ "an integer or stack pointer register") \
+ Y(INT_REG, regno, "Rn_SP", OPD_F_MAYBE_SP, F(FLD_Rn), \
+ "an integer or stack pointer register") \
+ Y(MODIFIED_REG, reg_extended, "Rm_EXT", 0, F(), \
+ "an integer register with optional extension") \
+ Y(MODIFIED_REG, reg_shifted, "Rm_SFT", 0, F(), \
+ "an integer register with optional shift") \
+ Y(FP_REG, regno, "Fd", 0, F(FLD_Rd), "a floating-point register") \
+ Y(FP_REG, regno, "Fn", 0, F(FLD_Rn), "a floating-point register") \
+ Y(FP_REG, regno, "Fm", 0, F(FLD_Rm), "a floating-point register") \
+ Y(FP_REG, regno, "Fa", 0, F(FLD_Ra), "a floating-point register") \
+ Y(FP_REG, ft, "Ft", 0, F(FLD_Rt), "a floating-point register") \
+ Y(FP_REG, regno, "Ft2", 0, F(FLD_Rt2), "a floating-point register") \
+ Y(SISD_REG, regno, "Sd", 0, F(FLD_Rd), "a SIMD scalar register") \
+ Y(SISD_REG, regno, "Sn", 0, F(FLD_Rn), "a SIMD scalar register") \
+ Y(SISD_REG, regno, "Sm", 0, F(FLD_Rm), "a SIMD scalar register") \
+ Y(SIMD_REG, regno, "Vd", 0, F(FLD_Rd), "a SIMD vector register") \
+ Y(SIMD_REG, regno, "Vn", 0, F(FLD_Rn), "a SIMD vector register") \
+ Y(SIMD_REG, regno, "Vm", 0, F(FLD_Rm), "a SIMD vector register") \
+ Y(FP_REG, regno, "VdD1", 0, F(FLD_Rd), \
+ "the top half of a 128-bit FP/SIMD register") \
+ Y(FP_REG, regno, "VnD1", 0, F(FLD_Rn), \
+ "the top half of a 128-bit FP/SIMD register") \
+ Y(SIMD_ELEMENT, reglane, "Ed", 0, F(FLD_Rd), \
+ "a SIMD vector element") \
+ Y(SIMD_ELEMENT, reglane, "En", 0, F(FLD_Rn), \
+ "a SIMD vector element") \
+ Y(SIMD_ELEMENT, reglane, "Em", 0, F(FLD_Rm), \
+ "a SIMD vector element") \
+ Y(SIMD_REGLIST, reglist, "LVn", 0, F(FLD_Rn), \
+ "a SIMD vector register list") \
+ Y(SIMD_REGLIST, ldst_reglist, "LVt", 0, F(), \
+ "a SIMD vector register list") \
+ Y(SIMD_REGLIST, ldst_reglist_r, "LVt_AL", 0, F(), \
+ "a SIMD vector register list") \
+ Y(SIMD_REGLIST, ldst_elemlist, "LEt", 0, F(), \
+ "a SIMD vector element list") \
+ Y(CP_REG, regno, "Cn", 0, F(FLD_CRn), \
+ "a 4-bit opcode field named for historical reasons C0 - C15") \
+ Y(CP_REG, regno, "Cm", 0, F(FLD_CRm), \
+ "a 4-bit opcode field named for historical reasons C0 - C15") \
+ Y(IMMEDIATE, imm, "IDX", 0, F(FLD_imm4), \
+ "an immediate as the index of the least significant byte") \
+ Y(IMMEDIATE, advsimd_imm_shift, "IMM_VLSL", 0, F(), \
+ "a left shift amount for an AdvSIMD register") \
+ Y(IMMEDIATE, advsimd_imm_shift, "IMM_VLSR", 0, F(), \
+ "a right shift amount for an AdvSIMD register") \
+ Y(IMMEDIATE, advsimd_imm_modified, "SIMD_IMM", 0, F(), \
+ "an immediate") \
+ Y(IMMEDIATE, advsimd_imm_modified, "SIMD_IMM_SFT", 0, F(), \
+ "an 8-bit unsigned immediate with optional shift") \
+ Y(IMMEDIATE, advsimd_imm_modified, "SIMD_FPIMM", 0, F(), \
+ "an 8-bit floating-point constant") \
+ X(IMMEDIATE, 0, ext_shll_imm, "SHLL_IMM", 0, F(), \
+ "an immediate shift amount of 8, 16 or 32") \
+ X(IMMEDIATE, 0, 0, "IMM0", 0, F(), "0") \
+ X(IMMEDIATE, 0, 0, "FPIMM0", 0, F(), "0.0") \
+ Y(IMMEDIATE, imm, "FPIMM", 0, F(FLD_imm8), \
+ "an 8-bit floating-point constant") \
+ Y(IMMEDIATE, imm, "IMMR", 0, F(FLD_immr), \
+ "the right rotate amount") \
+ Y(IMMEDIATE, imm, "IMMS", 0, F(FLD_imm6), \
+ "the leftmost bit number to be moved from the source") \
+ Y(IMMEDIATE, imm, "WIDTH", 0, F(FLD_imm6), \
+ "the width of the bit-field") \
+ Y(IMMEDIATE, imm, "IMM", 0, F(FLD_imm6), "an immediate") \
+ Y(IMMEDIATE, imm, "UIMM3_OP1", 0, F(FLD_op1), \
+ "a 3-bit unsigned immediate") \
+ Y(IMMEDIATE, imm, "UIMM3_OP2", 0, F(FLD_op2), \
+ "a 3-bit unsigned immediate") \
+ Y(IMMEDIATE, imm, "UIMM4", 0, F(FLD_CRm), \
+ "a 4-bit unsigned immediate") \
+ Y(IMMEDIATE, imm, "UIMM7", 0, F(FLD_CRm, FLD_op2), \
+ "a 7-bit unsigned immediate") \
+ Y(IMMEDIATE, imm, "BIT_NUM", 0, F(FLD_b5, FLD_b40), \
+ "the bit number to be tested") \
+ Y(IMMEDIATE, imm, "EXCEPTION", 0, F(FLD_imm16), \
+ "a 16-bit unsigned immediate") \
+ Y(IMMEDIATE, imm, "CCMP_IMM", 0, F(FLD_imm5), \
+ "a 5-bit unsigned immediate") \
+ Y(IMMEDIATE, imm, "NZCV", 0, F(FLD_nzcv), \
+ "a flag bit specifier giving an alternative value for each flag") \
+ Y(IMMEDIATE, limm, "LIMM", 0, F(FLD_N,FLD_immr,FLD_imms), \
+ "Logical immediate") \
+ Y(IMMEDIATE, aimm, "AIMM", 0, F(FLD_shift,FLD_imm12), \
+ "a 12-bit unsigned immediate with optional left shift of 12 bits")\
+ Y(IMMEDIATE, imm_half, "HALF", 0, F(FLD_imm16), \
+ "a 16-bit immediate with optional left shift") \
+ Y(IMMEDIATE, fbits, "FBITS", 0, F(FLD_scale), \
+ "the number of bits after the binary point in the fixed-point value")\
+ X(IMMEDIATE, 0, 0, "IMM_MOV", 0, F(), "an immediate") \
+ Y(NIL, cond, "COND", 0, F(), "a condition") \
+ X(ADDRESS, 0, ext_imm, "ADDR_ADRP", OPD_F_SEXT, F(FLD_immhi, FLD_immlo),\
+ "21-bit PC-relative address of a 4KB page") \
+ Y(ADDRESS, imm, "ADDR_PCREL14", OPD_F_SEXT | OPD_F_SHIFT_BY_2, \
+ F(FLD_imm14), "14-bit PC-relative address") \
+ Y(ADDRESS, imm, "ADDR_PCREL19", OPD_F_SEXT | OPD_F_SHIFT_BY_2, \
+ F(FLD_imm19), "19-bit PC-relative address") \
+ Y(ADDRESS, imm, "ADDR_PCREL21", OPD_F_SEXT, F(FLD_immhi,FLD_immlo), \
+ "21-bit PC-relative address") \
+ Y(ADDRESS, imm, "ADDR_PCREL26", OPD_F_SEXT | OPD_F_SHIFT_BY_2, \
+ F(FLD_imm26), "26-bit PC-relative address") \
+ Y(ADDRESS, addr_simple, "ADDR_SIMPLE", 0, F(), \
+ "an address with base register (no offset)") \
+ Y(ADDRESS, addr_regoff, "ADDR_REGOFF", 0, F(), \
+ "an address with register offset") \
+ Y(ADDRESS, addr_simm, "ADDR_SIMM7", 0, F(FLD_imm7,FLD_index2), \
+ "an address with 7-bit signed immediate offset") \
+ Y(ADDRESS, addr_simm, "ADDR_SIMM9", 0, F(FLD_imm9,FLD_index), \
+ "an address with 9-bit signed immediate offset") \
+ Y(ADDRESS, addr_simm, "ADDR_SIMM9_2", 0, F(FLD_imm9,FLD_index), \
+ "an address with 9-bit negative or unaligned immediate offset") \
+ Y(ADDRESS, addr_uimm12, "ADDR_UIMM12", 0, F(FLD_Rn,FLD_imm12), \
+ "an address with scaled, unsigned immediate offset") \
+ Y(ADDRESS, addr_simple, "SIMD_ADDR_SIMPLE", 0, F(), \
+ "an address with base register (no offset)") \
+ Y(ADDRESS, simd_addr_post, "SIMD_ADDR_POST", 0, F(), \
+ "a post-indexed address with immediate or register increment") \
+ Y(SYSTEM, sysreg, "SYSREG", 0, F(), "a system register") \
+ Y(SYSTEM, pstatefield, "PSTATEFIELD", 0, F(), \
+ "a PSTATE field name") \
+ Y(SYSTEM, sysins_op, "SYSREG_AT", 0, F(), \
+ "an address translation operation specifier") \
+ Y(SYSTEM, sysins_op, "SYSREG_DC", 0, F(), \
+ "a data cache maintenance operation specifier") \
+ Y(SYSTEM, sysins_op, "SYSREG_IC", 0, F(), \
+ "an instructin cache maintenance operation specifier") \
+ Y(SYSTEM, sysins_op, "SYSREG_TLBI", 0, F(), \
+ "a TBL invalidation operation specifier") \
+ Y(SYSTEM, barrier, "BARRIER", 0, F(), \
+ "a barrier option name") \
+ Y(SYSTEM, barrier, "BARRIER_ISB", 0, F(), \
+ "the ISB option name SY or an optional 4-bit unsigned immediate") \
+ Y(SYSTEM, prfop, "PRFOP", 0, F(), \
+ "an prefetch operation specifier")
diff --git a/opcodes/configure b/opcodes/configure
index 9b6cc7d..708996b 100755
--- a/opcodes/configure
+++ b/opcodes/configure
@@ -12486,6 +12486,7 @@ if test x${all_targets} = xfalse ; then
ad=`echo $arch | sed -e s/bfd_//g -e s/_arch//g`
archdefs="$archdefs -DARCH_$ad"
case "$arch" in
+ bfd_aarch64_arch) ta="$ta aarch64-asm.lo aarch64-dis.lo aarch64-opc.lo aarch64-asm-2.lo aarch64-dis-2.lo aarch64-opc-2.lo" ;;
bfd_alpha_arch) ta="$ta alpha-dis.lo alpha-opc.lo" ;;
bfd_arc_arch) ta="$ta arc-dis.lo arc-opc.lo arc-ext.lo" ;;
bfd_arm_arch) ta="$ta arm-dis.lo" ;;
diff --git a/opcodes/configure.in b/opcodes/configure.in
index 486ffa0..0d6d742 100644
--- a/opcodes/configure.in
+++ b/opcodes/configure.in
@@ -231,6 +231,7 @@ if test x${all_targets} = xfalse ; then
ad=`echo $arch | sed -e s/bfd_//g -e s/_arch//g`
archdefs="$archdefs -DARCH_$ad"
case "$arch" in
+ bfd_aarch64_arch) ta="$ta aarch64-asm.lo aarch64-dis.lo aarch64-opc.lo aarch64-asm-2.lo aarch64-dis-2.lo aarch64-opc-2.lo" ;;
bfd_alpha_arch) ta="$ta alpha-dis.lo alpha-opc.lo" ;;
bfd_arc_arch) ta="$ta arc-dis.lo arc-opc.lo arc-ext.lo" ;;
bfd_arm_arch) ta="$ta arm-dis.lo" ;;
diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c
index 3dad64b..c5887b0 100644
--- a/opcodes/disassemble.c
+++ b/opcodes/disassemble.c
@@ -24,6 +24,7 @@
#include "dis-asm.h"
#ifdef ARCH_all
+#define ARCH_aarch64
#define ARCH_alpha
#define ARCH_arc
#define ARCH_arm
@@ -113,6 +114,11 @@ disassembler (abfd)
{
/* If you add a case to this table, also add it to the
ARCH_all definition right above this function. */
+#ifdef ARCH_aarch64
+ case bfd_arch_aarch64:
+ disassemble = print_insn_aarch64;
+ break;
+#endif
#ifdef ARCH_alpha
case bfd_arch_alpha:
disassemble = print_insn_alpha;
@@ -516,6 +522,9 @@ void
disassembler_usage (stream)
FILE * stream ATTRIBUTE_UNUSED;
{
+#ifdef ARCH_aarch64
+ print_aarch64_disassembler_options (stream);
+#endif
#ifdef ARCH_arm
print_arm_disassembler_options (stream);
#endif
@@ -543,6 +552,12 @@ disassemble_init_for_target (struct disassemble_info * info)
switch (info->arch)
{
+#ifdef ARCH_aarch64
+ case bfd_arch_aarch64:
+ info->symbol_is_valid = aarch64_symbol_is_valid;
+ info->disassembler_needs_relocs = TRUE;
+ break;
+#endif
#ifdef ARCH_arm
case bfd_arch_arm:
info->symbol_is_valid = arm_symbol_is_valid;