1*a9fa9459Szrj /* AArch64 assembler/disassembler support.
2*a9fa9459Szrj
3*a9fa9459Szrj Copyright (C) 2009-2016 Free Software Foundation, Inc.
4*a9fa9459Szrj Contributed by ARM Ltd.
5*a9fa9459Szrj
6*a9fa9459Szrj This file is part of GNU Binutils.
7*a9fa9459Szrj
8*a9fa9459Szrj This program is free software; you can redistribute it and/or modify
9*a9fa9459Szrj it under the terms of the GNU General Public License as published by
10*a9fa9459Szrj the Free Software Foundation; either version 3 of the license, or
11*a9fa9459Szrj (at your option) any later version.
12*a9fa9459Szrj
13*a9fa9459Szrj This program is distributed in the hope that it will be useful,
14*a9fa9459Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
15*a9fa9459Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16*a9fa9459Szrj GNU General Public License for more details.
17*a9fa9459Szrj
18*a9fa9459Szrj You should have received a copy of the GNU General Public License
19*a9fa9459Szrj along with this program; see the file COPYING3. If not,
20*a9fa9459Szrj see <http://www.gnu.org/licenses/>. */
21*a9fa9459Szrj
22*a9fa9459Szrj #ifndef OPCODE_AARCH64_H
23*a9fa9459Szrj #define OPCODE_AARCH64_H
24*a9fa9459Szrj
25*a9fa9459Szrj #include "bfd.h"
26*a9fa9459Szrj #include "bfd_stdint.h"
27*a9fa9459Szrj #include <assert.h>
28*a9fa9459Szrj #include <stdlib.h>
29*a9fa9459Szrj
30*a9fa9459Szrj #ifdef __cplusplus
31*a9fa9459Szrj extern "C" {
32*a9fa9459Szrj #endif
33*a9fa9459Szrj
34*a9fa9459Szrj /* The offset for pc-relative addressing is currently defined to be 0. */
35*a9fa9459Szrj #define AARCH64_PCREL_OFFSET 0
36*a9fa9459Szrj
37*a9fa9459Szrj typedef uint32_t aarch64_insn;
38*a9fa9459Szrj
39*a9fa9459Szrj /* The following bitmasks control CPU features. */
40*a9fa9459Szrj #define AARCH64_FEATURE_V8 0x00000001 /* All processors. */
41*a9fa9459Szrj #define AARCH64_FEATURE_V8_2 0x00000020 /* ARMv8.2 processors. */
42*a9fa9459Szrj #define AARCH64_FEATURE_CRYPTO 0x00010000 /* Crypto instructions. */
43*a9fa9459Szrj #define AARCH64_FEATURE_FP 0x00020000 /* FP instructions. */
44*a9fa9459Szrj #define AARCH64_FEATURE_SIMD 0x00040000 /* SIMD instructions. */
45*a9fa9459Szrj #define AARCH64_FEATURE_CRC 0x00080000 /* CRC instructions. */
46*a9fa9459Szrj #define AARCH64_FEATURE_LSE 0x00100000 /* LSE instructions. */
47*a9fa9459Szrj #define AARCH64_FEATURE_PAN 0x00200000 /* PAN instructions. */
48*a9fa9459Szrj #define AARCH64_FEATURE_LOR 0x00400000 /* LOR instructions. */
49*a9fa9459Szrj #define AARCH64_FEATURE_RDMA 0x00800000 /* v8.1 SIMD instructions. */
50*a9fa9459Szrj #define AARCH64_FEATURE_V8_1 0x01000000 /* v8.1 features. */
51*a9fa9459Szrj #define AARCH64_FEATURE_F16 0x02000000 /* v8.2 FP16 instructions. */
52*a9fa9459Szrj #define AARCH64_FEATURE_RAS 0x04000000 /* RAS Extensions. */
53*a9fa9459Szrj #define AARCH64_FEATURE_PROFILE 0x08000000 /* Statistical Profiling. */
54*a9fa9459Szrj
55*a9fa9459Szrj /* Architectures are the sum of the base and extensions. */
56*a9fa9459Szrj #define AARCH64_ARCH_V8 AARCH64_FEATURE (AARCH64_FEATURE_V8, \
57*a9fa9459Szrj AARCH64_FEATURE_FP \
58*a9fa9459Szrj | AARCH64_FEATURE_SIMD)
59*a9fa9459Szrj #define AARCH64_ARCH_V8_1 AARCH64_FEATURE (AARCH64_FEATURE_V8, \
60*a9fa9459Szrj AARCH64_FEATURE_FP \
61*a9fa9459Szrj | AARCH64_FEATURE_SIMD \
62*a9fa9459Szrj | AARCH64_FEATURE_CRC \
63*a9fa9459Szrj | AARCH64_FEATURE_V8_1 \
64*a9fa9459Szrj | AARCH64_FEATURE_LSE \
65*a9fa9459Szrj | AARCH64_FEATURE_PAN \
66*a9fa9459Szrj | AARCH64_FEATURE_LOR \
67*a9fa9459Szrj | AARCH64_FEATURE_RDMA)
68*a9fa9459Szrj #define AARCH64_ARCH_V8_2 AARCH64_FEATURE (AARCH64_FEATURE_V8, \
69*a9fa9459Szrj AARCH64_FEATURE_V8_2 \
70*a9fa9459Szrj | AARCH64_FEATURE_F16 \
71*a9fa9459Szrj | AARCH64_FEATURE_RAS \
72*a9fa9459Szrj | AARCH64_FEATURE_FP \
73*a9fa9459Szrj | AARCH64_FEATURE_SIMD \
74*a9fa9459Szrj | AARCH64_FEATURE_CRC \
75*a9fa9459Szrj | AARCH64_FEATURE_V8_1 \
76*a9fa9459Szrj | AARCH64_FEATURE_LSE \
77*a9fa9459Szrj | AARCH64_FEATURE_PAN \
78*a9fa9459Szrj | AARCH64_FEATURE_LOR \
79*a9fa9459Szrj | AARCH64_FEATURE_RDMA)
80*a9fa9459Szrj
81*a9fa9459Szrj #define AARCH64_ARCH_NONE AARCH64_FEATURE (0, 0)
82*a9fa9459Szrj #define AARCH64_ANY AARCH64_FEATURE (-1, 0) /* Any basic core. */
83*a9fa9459Szrj
84*a9fa9459Szrj /* CPU-specific features. */
85*a9fa9459Szrj typedef unsigned long aarch64_feature_set;
86*a9fa9459Szrj
87*a9fa9459Szrj #define AARCH64_CPU_HAS_FEATURE(CPU,FEAT) \
88*a9fa9459Szrj (((CPU) & (FEAT)) != 0)
89*a9fa9459Szrj
90*a9fa9459Szrj #define AARCH64_MERGE_FEATURE_SETS(TARG,F1,F2) \
91*a9fa9459Szrj do \
92*a9fa9459Szrj { \
93*a9fa9459Szrj (TARG) = (F1) | (F2); \
94*a9fa9459Szrj } \
95*a9fa9459Szrj while (0)
96*a9fa9459Szrj
97*a9fa9459Szrj #define AARCH64_CLEAR_FEATURE(TARG,F1,F2) \
98*a9fa9459Szrj do \
99*a9fa9459Szrj { \
100*a9fa9459Szrj (TARG) = (F1) &~ (F2); \
101*a9fa9459Szrj } \
102*a9fa9459Szrj while (0)
103*a9fa9459Szrj
104*a9fa9459Szrj #define AARCH64_FEATURE(core,coproc) ((core) | (coproc))
105*a9fa9459Szrj
106*a9fa9459Szrj #define AARCH64_OPCODE_HAS_FEATURE(OPC,FEAT) \
107*a9fa9459Szrj (((OPC) & (FEAT)) != 0)
108*a9fa9459Szrj
109*a9fa9459Szrj enum aarch64_operand_class
110*a9fa9459Szrj {
111*a9fa9459Szrj AARCH64_OPND_CLASS_NIL,
112*a9fa9459Szrj AARCH64_OPND_CLASS_INT_REG,
113*a9fa9459Szrj AARCH64_OPND_CLASS_MODIFIED_REG,
114*a9fa9459Szrj AARCH64_OPND_CLASS_FP_REG,
115*a9fa9459Szrj AARCH64_OPND_CLASS_SIMD_REG,
116*a9fa9459Szrj AARCH64_OPND_CLASS_SIMD_ELEMENT,
117*a9fa9459Szrj AARCH64_OPND_CLASS_SISD_REG,
118*a9fa9459Szrj AARCH64_OPND_CLASS_SIMD_REGLIST,
119*a9fa9459Szrj AARCH64_OPND_CLASS_CP_REG,
120*a9fa9459Szrj AARCH64_OPND_CLASS_ADDRESS,
121*a9fa9459Szrj AARCH64_OPND_CLASS_IMMEDIATE,
122*a9fa9459Szrj AARCH64_OPND_CLASS_SYSTEM,
123*a9fa9459Szrj AARCH64_OPND_CLASS_COND,
124*a9fa9459Szrj };
125*a9fa9459Szrj
126*a9fa9459Szrj /* Operand code that helps both parsing and coding.
127*a9fa9459Szrj Keep AARCH64_OPERANDS synced. */
128*a9fa9459Szrj
129*a9fa9459Szrj enum aarch64_opnd
130*a9fa9459Szrj {
131*a9fa9459Szrj AARCH64_OPND_NIL, /* no operand---MUST BE FIRST!*/
132*a9fa9459Szrj
133*a9fa9459Szrj AARCH64_OPND_Rd, /* Integer register as destination. */
134*a9fa9459Szrj AARCH64_OPND_Rn, /* Integer register as source. */
135*a9fa9459Szrj AARCH64_OPND_Rm, /* Integer register as source. */
136*a9fa9459Szrj AARCH64_OPND_Rt, /* Integer register used in ld/st instructions. */
137*a9fa9459Szrj AARCH64_OPND_Rt2, /* Integer register used in ld/st pair instructions. */
138*a9fa9459Szrj AARCH64_OPND_Rs, /* Integer register used in ld/st exclusive. */
139*a9fa9459Szrj AARCH64_OPND_Ra, /* Integer register used in ddp_3src instructions. */
140*a9fa9459Szrj AARCH64_OPND_Rt_SYS, /* Integer register used in system instructions. */
141*a9fa9459Szrj
142*a9fa9459Szrj AARCH64_OPND_Rd_SP, /* Integer Rd or SP. */
143*a9fa9459Szrj AARCH64_OPND_Rn_SP, /* Integer Rn or SP. */
144*a9fa9459Szrj AARCH64_OPND_PAIRREG, /* Paired register operand. */
145*a9fa9459Szrj AARCH64_OPND_Rm_EXT, /* Integer Rm extended. */
146*a9fa9459Szrj AARCH64_OPND_Rm_SFT, /* Integer Rm shifted. */
147*a9fa9459Szrj
148*a9fa9459Szrj AARCH64_OPND_Fd, /* Floating-point Fd. */
149*a9fa9459Szrj AARCH64_OPND_Fn, /* Floating-point Fn. */
150*a9fa9459Szrj AARCH64_OPND_Fm, /* Floating-point Fm. */
151*a9fa9459Szrj AARCH64_OPND_Fa, /* Floating-point Fa. */
152*a9fa9459Szrj AARCH64_OPND_Ft, /* Floating-point Ft. */
153*a9fa9459Szrj AARCH64_OPND_Ft2, /* Floating-point Ft2. */
154*a9fa9459Szrj
155*a9fa9459Szrj AARCH64_OPND_Sd, /* AdvSIMD Scalar Sd. */
156*a9fa9459Szrj AARCH64_OPND_Sn, /* AdvSIMD Scalar Sn. */
157*a9fa9459Szrj AARCH64_OPND_Sm, /* AdvSIMD Scalar Sm. */
158*a9fa9459Szrj
159*a9fa9459Szrj AARCH64_OPND_Vd, /* AdvSIMD Vector Vd. */
160*a9fa9459Szrj AARCH64_OPND_Vn, /* AdvSIMD Vector Vn. */
161*a9fa9459Szrj AARCH64_OPND_Vm, /* AdvSIMD Vector Vm. */
162*a9fa9459Szrj AARCH64_OPND_VdD1, /* AdvSIMD <Vd>.D[1]; for FMOV only. */
163*a9fa9459Szrj AARCH64_OPND_VnD1, /* AdvSIMD <Vn>.D[1]; for FMOV only. */
164*a9fa9459Szrj AARCH64_OPND_Ed, /* AdvSIMD Vector Element Vd. */
165*a9fa9459Szrj AARCH64_OPND_En, /* AdvSIMD Vector Element Vn. */
166*a9fa9459Szrj AARCH64_OPND_Em, /* AdvSIMD Vector Element Vm. */
167*a9fa9459Szrj AARCH64_OPND_LVn, /* AdvSIMD Vector register list used in e.g. TBL. */
168*a9fa9459Szrj AARCH64_OPND_LVt, /* AdvSIMD Vector register list used in ld/st. */
169*a9fa9459Szrj AARCH64_OPND_LVt_AL, /* AdvSIMD Vector register list for loading single
170*a9fa9459Szrj structure to all lanes. */
171*a9fa9459Szrj AARCH64_OPND_LEt, /* AdvSIMD Vector Element list. */
172*a9fa9459Szrj
173*a9fa9459Szrj AARCH64_OPND_Cn, /* Co-processor register in CRn field. */
174*a9fa9459Szrj AARCH64_OPND_Cm, /* Co-processor register in CRm field. */
175*a9fa9459Szrj
176*a9fa9459Szrj AARCH64_OPND_IDX, /* AdvSIMD EXT index operand. */
177*a9fa9459Szrj AARCH64_OPND_IMM_VLSL,/* Immediate for shifting vector registers left. */
178*a9fa9459Szrj AARCH64_OPND_IMM_VLSR,/* Immediate for shifting vector registers right. */
179*a9fa9459Szrj AARCH64_OPND_SIMD_IMM,/* AdvSIMD modified immediate without shift. */
180*a9fa9459Szrj AARCH64_OPND_SIMD_IMM_SFT, /* AdvSIMD modified immediate with shift. */
181*a9fa9459Szrj AARCH64_OPND_SIMD_FPIMM,/* AdvSIMD 8-bit fp immediate. */
182*a9fa9459Szrj AARCH64_OPND_SHLL_IMM,/* Immediate shift for AdvSIMD SHLL instruction
183*a9fa9459Szrj (no encoding). */
184*a9fa9459Szrj AARCH64_OPND_IMM0, /* Immediate for #0. */
185*a9fa9459Szrj AARCH64_OPND_FPIMM0, /* Immediate for #0.0. */
186*a9fa9459Szrj AARCH64_OPND_FPIMM, /* Floating-point Immediate. */
187*a9fa9459Szrj AARCH64_OPND_IMMR, /* Immediate #<immr> in e.g. BFM. */
188*a9fa9459Szrj AARCH64_OPND_IMMS, /* Immediate #<imms> in e.g. BFM. */
189*a9fa9459Szrj AARCH64_OPND_WIDTH, /* Immediate #<width> in e.g. BFI. */
190*a9fa9459Szrj AARCH64_OPND_IMM, /* Immediate. */
191*a9fa9459Szrj AARCH64_OPND_UIMM3_OP1,/* Unsigned 3-bit immediate in the op1 field. */
192*a9fa9459Szrj AARCH64_OPND_UIMM3_OP2,/* Unsigned 3-bit immediate in the op2 field. */
193*a9fa9459Szrj AARCH64_OPND_UIMM4, /* Unsigned 4-bit immediate in the CRm field. */
194*a9fa9459Szrj AARCH64_OPND_UIMM7, /* Unsigned 7-bit immediate in the CRm:op2 fields. */
195*a9fa9459Szrj AARCH64_OPND_BIT_NUM, /* Immediate. */
196*a9fa9459Szrj AARCH64_OPND_EXCEPTION,/* imm16 operand in exception instructions. */
197*a9fa9459Szrj AARCH64_OPND_CCMP_IMM,/* Immediate in conditional compare instructions. */
198*a9fa9459Szrj AARCH64_OPND_NZCV, /* Flag bit specifier giving an alternative value for
199*a9fa9459Szrj each condition flag. */
200*a9fa9459Szrj
201*a9fa9459Szrj AARCH64_OPND_LIMM, /* Logical Immediate. */
202*a9fa9459Szrj AARCH64_OPND_AIMM, /* Arithmetic immediate. */
203*a9fa9459Szrj AARCH64_OPND_HALF, /* #<imm16>{, LSL #<shift>} operand in move wide. */
204*a9fa9459Szrj AARCH64_OPND_FBITS, /* FP #<fbits> operand in e.g. SCVTF */
205*a9fa9459Szrj AARCH64_OPND_IMM_MOV, /* Immediate operand for the MOV alias. */
206*a9fa9459Szrj
207*a9fa9459Szrj AARCH64_OPND_COND, /* Standard condition as the last operand. */
208*a9fa9459Szrj AARCH64_OPND_COND1, /* Same as the above, but excluding AL and NV. */
209*a9fa9459Szrj
210*a9fa9459Szrj AARCH64_OPND_ADDR_ADRP, /* Memory address for ADRP */
211*a9fa9459Szrj AARCH64_OPND_ADDR_PCREL14, /* 14-bit PC-relative address for e.g. TBZ. */
212*a9fa9459Szrj AARCH64_OPND_ADDR_PCREL19, /* 19-bit PC-relative address for e.g. LDR. */
213*a9fa9459Szrj AARCH64_OPND_ADDR_PCREL21, /* 21-bit PC-relative address for e.g. ADR. */
214*a9fa9459Szrj AARCH64_OPND_ADDR_PCREL26, /* 26-bit PC-relative address for e.g. BL. */
215*a9fa9459Szrj
216*a9fa9459Szrj AARCH64_OPND_ADDR_SIMPLE, /* Address of ld/st exclusive. */
217*a9fa9459Szrj AARCH64_OPND_ADDR_REGOFF, /* Address of register offset. */
218*a9fa9459Szrj AARCH64_OPND_ADDR_SIMM7, /* Address of signed 7-bit immediate. */
219*a9fa9459Szrj AARCH64_OPND_ADDR_SIMM9, /* Address of signed 9-bit immediate. */
220*a9fa9459Szrj AARCH64_OPND_ADDR_SIMM9_2, /* Same as the above, but the immediate is
221*a9fa9459Szrj negative or unaligned and there is
222*a9fa9459Szrj no writeback allowed. This operand code
223*a9fa9459Szrj is only used to support the programmer-
224*a9fa9459Szrj friendly feature of using LDR/STR as the
225*a9fa9459Szrj the mnemonic name for LDUR/STUR instructions
226*a9fa9459Szrj wherever there is no ambiguity. */
227*a9fa9459Szrj AARCH64_OPND_ADDR_UIMM12, /* Address of unsigned 12-bit immediate. */
228*a9fa9459Szrj AARCH64_OPND_SIMD_ADDR_SIMPLE,/* Address of ld/st multiple structures. */
229*a9fa9459Szrj AARCH64_OPND_SIMD_ADDR_POST, /* Address of ld/st multiple post-indexed. */
230*a9fa9459Szrj
231*a9fa9459Szrj AARCH64_OPND_SYSREG, /* System register operand. */
232*a9fa9459Szrj AARCH64_OPND_PSTATEFIELD, /* PSTATE field name operand. */
233*a9fa9459Szrj AARCH64_OPND_SYSREG_AT, /* System register <at_op> operand. */
234*a9fa9459Szrj AARCH64_OPND_SYSREG_DC, /* System register <dc_op> operand. */
235*a9fa9459Szrj AARCH64_OPND_SYSREG_IC, /* System register <ic_op> operand. */
236*a9fa9459Szrj AARCH64_OPND_SYSREG_TLBI, /* System register <tlbi_op> operand. */
237*a9fa9459Szrj AARCH64_OPND_BARRIER, /* Barrier operand. */
238*a9fa9459Szrj AARCH64_OPND_BARRIER_ISB, /* Barrier operand for ISB. */
239*a9fa9459Szrj AARCH64_OPND_PRFOP, /* Prefetch operation. */
240*a9fa9459Szrj AARCH64_OPND_BARRIER_PSB, /* Barrier operand for PSB. */
241*a9fa9459Szrj };
242*a9fa9459Szrj
243*a9fa9459Szrj /* Qualifier constrains an operand. It either specifies a variant of an
244*a9fa9459Szrj operand type or limits values available to an operand type.
245*a9fa9459Szrj
246*a9fa9459Szrj N.B. Order is important; keep aarch64_opnd_qualifiers synced. */
247*a9fa9459Szrj
248*a9fa9459Szrj enum aarch64_opnd_qualifier
249*a9fa9459Szrj {
250*a9fa9459Szrj /* Indicating no further qualification on an operand. */
251*a9fa9459Szrj AARCH64_OPND_QLF_NIL,
252*a9fa9459Szrj
253*a9fa9459Szrj /* Qualifying an operand which is a general purpose (integer) register;
254*a9fa9459Szrj indicating the operand data size or a specific register. */
255*a9fa9459Szrj AARCH64_OPND_QLF_W, /* Wn, WZR or WSP. */
256*a9fa9459Szrj AARCH64_OPND_QLF_X, /* Xn, XZR or XSP. */
257*a9fa9459Szrj AARCH64_OPND_QLF_WSP, /* WSP. */
258*a9fa9459Szrj AARCH64_OPND_QLF_SP, /* SP. */
259*a9fa9459Szrj
260*a9fa9459Szrj /* Qualifying an operand which is a floating-point register, a SIMD
261*a9fa9459Szrj vector element or a SIMD vector element list; indicating operand data
262*a9fa9459Szrj size or the size of each SIMD vector element in the case of a SIMD
263*a9fa9459Szrj vector element list.
264*a9fa9459Szrj These qualifiers are also used to qualify an address operand to
265*a9fa9459Szrj indicate the size of data element a load/store instruction is
266*a9fa9459Szrj accessing.
267*a9fa9459Szrj They are also used for the immediate shift operand in e.g. SSHR. Such
268*a9fa9459Szrj a use is only for the ease of operand encoding/decoding and qualifier
269*a9fa9459Szrj sequence matching; such a use should not be applied widely; use the value
270*a9fa9459Szrj constraint qualifiers for immediate operands wherever possible. */
271*a9fa9459Szrj AARCH64_OPND_QLF_S_B,
272*a9fa9459Szrj AARCH64_OPND_QLF_S_H,
273*a9fa9459Szrj AARCH64_OPND_QLF_S_S,
274*a9fa9459Szrj AARCH64_OPND_QLF_S_D,
275*a9fa9459Szrj AARCH64_OPND_QLF_S_Q,
276*a9fa9459Szrj
277*a9fa9459Szrj /* Qualifying an operand which is a SIMD vector register or a SIMD vector
278*a9fa9459Szrj register list; indicating register shape.
279*a9fa9459Szrj They are also used for the immediate shift operand in e.g. SSHR. Such
280*a9fa9459Szrj a use is only for the ease of operand encoding/decoding and qualifier
281*a9fa9459Szrj sequence matching; such a use should not be applied widely; use the value
282*a9fa9459Szrj constraint qualifiers for immediate operands wherever possible. */
283*a9fa9459Szrj AARCH64_OPND_QLF_V_8B,
284*a9fa9459Szrj AARCH64_OPND_QLF_V_16B,
285*a9fa9459Szrj AARCH64_OPND_QLF_V_2H,
286*a9fa9459Szrj AARCH64_OPND_QLF_V_4H,
287*a9fa9459Szrj AARCH64_OPND_QLF_V_8H,
288*a9fa9459Szrj AARCH64_OPND_QLF_V_2S,
289*a9fa9459Szrj AARCH64_OPND_QLF_V_4S,
290*a9fa9459Szrj AARCH64_OPND_QLF_V_1D,
291*a9fa9459Szrj AARCH64_OPND_QLF_V_2D,
292*a9fa9459Szrj AARCH64_OPND_QLF_V_1Q,
293*a9fa9459Szrj
294*a9fa9459Szrj /* Constraint on value. */
295*a9fa9459Szrj AARCH64_OPND_QLF_imm_0_7,
296*a9fa9459Szrj AARCH64_OPND_QLF_imm_0_15,
297*a9fa9459Szrj AARCH64_OPND_QLF_imm_0_31,
298*a9fa9459Szrj AARCH64_OPND_QLF_imm_0_63,
299*a9fa9459Szrj AARCH64_OPND_QLF_imm_1_32,
300*a9fa9459Szrj AARCH64_OPND_QLF_imm_1_64,
301*a9fa9459Szrj
302*a9fa9459Szrj /* Indicate whether an AdvSIMD modified immediate operand is shift-zeros
303*a9fa9459Szrj or shift-ones. */
304*a9fa9459Szrj AARCH64_OPND_QLF_LSL,
305*a9fa9459Szrj AARCH64_OPND_QLF_MSL,
306*a9fa9459Szrj
307*a9fa9459Szrj /* Special qualifier helping retrieve qualifier information during the
308*a9fa9459Szrj decoding time (currently not in use). */
309*a9fa9459Szrj AARCH64_OPND_QLF_RETRIEVE,
310*a9fa9459Szrj };
311*a9fa9459Szrj
312*a9fa9459Szrj /* Instruction class. */
313*a9fa9459Szrj
314*a9fa9459Szrj enum aarch64_insn_class
315*a9fa9459Szrj {
316*a9fa9459Szrj addsub_carry,
317*a9fa9459Szrj addsub_ext,
318*a9fa9459Szrj addsub_imm,
319*a9fa9459Szrj addsub_shift,
320*a9fa9459Szrj asimdall,
321*a9fa9459Szrj asimddiff,
322*a9fa9459Szrj asimdelem,
323*a9fa9459Szrj asimdext,
324*a9fa9459Szrj asimdimm,
325*a9fa9459Szrj asimdins,
326*a9fa9459Szrj asimdmisc,
327*a9fa9459Szrj asimdperm,
328*a9fa9459Szrj asimdsame,
329*a9fa9459Szrj asimdshf,
330*a9fa9459Szrj asimdtbl,
331*a9fa9459Szrj asisddiff,
332*a9fa9459Szrj asisdelem,
333*a9fa9459Szrj asisdlse,
334*a9fa9459Szrj asisdlsep,
335*a9fa9459Szrj asisdlso,
336*a9fa9459Szrj asisdlsop,
337*a9fa9459Szrj asisdmisc,
338*a9fa9459Szrj asisdone,
339*a9fa9459Szrj asisdpair,
340*a9fa9459Szrj asisdsame,
341*a9fa9459Szrj asisdshf,
342*a9fa9459Szrj bitfield,
343*a9fa9459Szrj branch_imm,
344*a9fa9459Szrj branch_reg,
345*a9fa9459Szrj compbranch,
346*a9fa9459Szrj condbranch,
347*a9fa9459Szrj condcmp_imm,
348*a9fa9459Szrj condcmp_reg,
349*a9fa9459Szrj condsel,
350*a9fa9459Szrj cryptoaes,
351*a9fa9459Szrj cryptosha2,
352*a9fa9459Szrj cryptosha3,
353*a9fa9459Szrj dp_1src,
354*a9fa9459Szrj dp_2src,
355*a9fa9459Szrj dp_3src,
356*a9fa9459Szrj exception,
357*a9fa9459Szrj extract,
358*a9fa9459Szrj float2fix,
359*a9fa9459Szrj float2int,
360*a9fa9459Szrj floatccmp,
361*a9fa9459Szrj floatcmp,
362*a9fa9459Szrj floatdp1,
363*a9fa9459Szrj floatdp2,
364*a9fa9459Szrj floatdp3,
365*a9fa9459Szrj floatimm,
366*a9fa9459Szrj floatsel,
367*a9fa9459Szrj ldst_immpost,
368*a9fa9459Szrj ldst_immpre,
369*a9fa9459Szrj ldst_imm9, /* immpost or immpre */
370*a9fa9459Szrj ldst_pos,
371*a9fa9459Szrj ldst_regoff,
372*a9fa9459Szrj ldst_unpriv,
373*a9fa9459Szrj ldst_unscaled,
374*a9fa9459Szrj ldstexcl,
375*a9fa9459Szrj ldstnapair_offs,
376*a9fa9459Szrj ldstpair_off,
377*a9fa9459Szrj ldstpair_indexed,
378*a9fa9459Szrj loadlit,
379*a9fa9459Szrj log_imm,
380*a9fa9459Szrj log_shift,
381*a9fa9459Szrj lse_atomic,
382*a9fa9459Szrj movewide,
383*a9fa9459Szrj pcreladdr,
384*a9fa9459Szrj ic_system,
385*a9fa9459Szrj testbranch,
386*a9fa9459Szrj };
387*a9fa9459Szrj
388*a9fa9459Szrj /* Opcode enumerators. */
389*a9fa9459Szrj
390*a9fa9459Szrj enum aarch64_op
391*a9fa9459Szrj {
392*a9fa9459Szrj OP_NIL,
393*a9fa9459Szrj OP_STRB_POS,
394*a9fa9459Szrj OP_LDRB_POS,
395*a9fa9459Szrj OP_LDRSB_POS,
396*a9fa9459Szrj OP_STRH_POS,
397*a9fa9459Szrj OP_LDRH_POS,
398*a9fa9459Szrj OP_LDRSH_POS,
399*a9fa9459Szrj OP_STR_POS,
400*a9fa9459Szrj OP_LDR_POS,
401*a9fa9459Szrj OP_STRF_POS,
402*a9fa9459Szrj OP_LDRF_POS,
403*a9fa9459Szrj OP_LDRSW_POS,
404*a9fa9459Szrj OP_PRFM_POS,
405*a9fa9459Szrj
406*a9fa9459Szrj OP_STURB,
407*a9fa9459Szrj OP_LDURB,
408*a9fa9459Szrj OP_LDURSB,
409*a9fa9459Szrj OP_STURH,
410*a9fa9459Szrj OP_LDURH,
411*a9fa9459Szrj OP_LDURSH,
412*a9fa9459Szrj OP_STUR,
413*a9fa9459Szrj OP_LDUR,
414*a9fa9459Szrj OP_STURV,
415*a9fa9459Szrj OP_LDURV,
416*a9fa9459Szrj OP_LDURSW,
417*a9fa9459Szrj OP_PRFUM,
418*a9fa9459Szrj
419*a9fa9459Szrj OP_LDR_LIT,
420*a9fa9459Szrj OP_LDRV_LIT,
421*a9fa9459Szrj OP_LDRSW_LIT,
422*a9fa9459Szrj OP_PRFM_LIT,
423*a9fa9459Szrj
424*a9fa9459Szrj OP_ADD,
425*a9fa9459Szrj OP_B,
426*a9fa9459Szrj OP_BL,
427*a9fa9459Szrj
428*a9fa9459Szrj OP_MOVN,
429*a9fa9459Szrj OP_MOVZ,
430*a9fa9459Szrj OP_MOVK,
431*a9fa9459Szrj
432*a9fa9459Szrj OP_MOV_IMM_LOG, /* MOV alias for moving bitmask immediate. */
433*a9fa9459Szrj OP_MOV_IMM_WIDE, /* MOV alias for moving wide immediate. */
434*a9fa9459Szrj OP_MOV_IMM_WIDEN, /* MOV alias for moving wide immediate (negated). */
435*a9fa9459Szrj
436*a9fa9459Szrj OP_MOV_V, /* MOV alias for moving vector register. */
437*a9fa9459Szrj
438*a9fa9459Szrj OP_ASR_IMM,
439*a9fa9459Szrj OP_LSR_IMM,
440*a9fa9459Szrj OP_LSL_IMM,
441*a9fa9459Szrj
442*a9fa9459Szrj OP_BIC,
443*a9fa9459Szrj
444*a9fa9459Szrj OP_UBFX,
445*a9fa9459Szrj OP_BFXIL,
446*a9fa9459Szrj OP_SBFX,
447*a9fa9459Szrj OP_SBFIZ,
448*a9fa9459Szrj OP_BFI,
449*a9fa9459Szrj OP_BFC, /* ARMv8.2. */
450*a9fa9459Szrj OP_UBFIZ,
451*a9fa9459Szrj OP_UXTB,
452*a9fa9459Szrj OP_UXTH,
453*a9fa9459Szrj OP_UXTW,
454*a9fa9459Szrj
455*a9fa9459Szrj OP_CINC,
456*a9fa9459Szrj OP_CINV,
457*a9fa9459Szrj OP_CNEG,
458*a9fa9459Szrj OP_CSET,
459*a9fa9459Szrj OP_CSETM,
460*a9fa9459Szrj
461*a9fa9459Szrj OP_FCVT,
462*a9fa9459Szrj OP_FCVTN,
463*a9fa9459Szrj OP_FCVTN2,
464*a9fa9459Szrj OP_FCVTL,
465*a9fa9459Szrj OP_FCVTL2,
466*a9fa9459Szrj OP_FCVTXN_S, /* Scalar version. */
467*a9fa9459Szrj
468*a9fa9459Szrj OP_ROR_IMM,
469*a9fa9459Szrj
470*a9fa9459Szrj OP_SXTL,
471*a9fa9459Szrj OP_SXTL2,
472*a9fa9459Szrj OP_UXTL,
473*a9fa9459Szrj OP_UXTL2,
474*a9fa9459Szrj
475*a9fa9459Szrj OP_TOTAL_NUM, /* Pseudo. */
476*a9fa9459Szrj };
477*a9fa9459Szrj
478*a9fa9459Szrj /* Maximum number of operands an instruction can have. */
479*a9fa9459Szrj #define AARCH64_MAX_OPND_NUM 6
480*a9fa9459Szrj /* Maximum number of qualifier sequences an instruction can have. */
481*a9fa9459Szrj #define AARCH64_MAX_QLF_SEQ_NUM 10
482*a9fa9459Szrj /* Operand qualifier typedef; optimized for the size. */
483*a9fa9459Szrj typedef unsigned char aarch64_opnd_qualifier_t;
484*a9fa9459Szrj /* Operand qualifier sequence typedef. */
485*a9fa9459Szrj typedef aarch64_opnd_qualifier_t \
486*a9fa9459Szrj aarch64_opnd_qualifier_seq_t [AARCH64_MAX_OPND_NUM];
487*a9fa9459Szrj
488*a9fa9459Szrj /* FIXME: improve the efficiency. */
489*a9fa9459Szrj static inline bfd_boolean
empty_qualifier_sequence_p(const aarch64_opnd_qualifier_t * qualifiers)490*a9fa9459Szrj empty_qualifier_sequence_p (const aarch64_opnd_qualifier_t *qualifiers)
491*a9fa9459Szrj {
492*a9fa9459Szrj int i;
493*a9fa9459Szrj for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
494*a9fa9459Szrj if (qualifiers[i] != AARCH64_OPND_QLF_NIL)
495*a9fa9459Szrj return FALSE;
496*a9fa9459Szrj return TRUE;
497*a9fa9459Szrj }
498*a9fa9459Szrj
499*a9fa9459Szrj /* This structure holds information for a particular opcode. */
500*a9fa9459Szrj
501*a9fa9459Szrj struct aarch64_opcode
502*a9fa9459Szrj {
503*a9fa9459Szrj /* The name of the mnemonic. */
504*a9fa9459Szrj const char *name;
505*a9fa9459Szrj
506*a9fa9459Szrj /* The opcode itself. Those bits which will be filled in with
507*a9fa9459Szrj operands are zeroes. */
508*a9fa9459Szrj aarch64_insn opcode;
509*a9fa9459Szrj
510*a9fa9459Szrj /* The opcode mask. This is used by the disassembler. This is a
511*a9fa9459Szrj mask containing ones indicating those bits which must match the
512*a9fa9459Szrj opcode field, and zeroes indicating those bits which need not
513*a9fa9459Szrj match (and are presumably filled in by operands). */
514*a9fa9459Szrj aarch64_insn mask;
515*a9fa9459Szrj
516*a9fa9459Szrj /* Instruction class. */
517*a9fa9459Szrj enum aarch64_insn_class iclass;
518*a9fa9459Szrj
519*a9fa9459Szrj /* Enumerator identifier. */
520*a9fa9459Szrj enum aarch64_op op;
521*a9fa9459Szrj
522*a9fa9459Szrj /* Which architecture variant provides this instruction. */
523*a9fa9459Szrj const aarch64_feature_set *avariant;
524*a9fa9459Szrj
525*a9fa9459Szrj /* An array of operand codes. Each code is an index into the
526*a9fa9459Szrj operand table. They appear in the order which the operands must
527*a9fa9459Szrj appear in assembly code, and are terminated by a zero. */
528*a9fa9459Szrj enum aarch64_opnd operands[AARCH64_MAX_OPND_NUM];
529*a9fa9459Szrj
530*a9fa9459Szrj /* A list of operand qualifier code sequence. Each operand qualifier
531*a9fa9459Szrj code qualifies the corresponding operand code. Each operand
532*a9fa9459Szrj qualifier sequence specifies a valid opcode variant and related
533*a9fa9459Szrj constraint on operands. */
534*a9fa9459Szrj aarch64_opnd_qualifier_seq_t qualifiers_list[AARCH64_MAX_QLF_SEQ_NUM];
535*a9fa9459Szrj
536*a9fa9459Szrj /* Flags providing information about this instruction */
537*a9fa9459Szrj uint32_t flags;
538*a9fa9459Szrj
539*a9fa9459Szrj /* If non-NULL, a function to verify that a given instruction is valid. */
540*a9fa9459Szrj bfd_boolean (* verifier) (const struct aarch64_opcode *, const aarch64_insn);
541*a9fa9459Szrj };
542*a9fa9459Szrj
543*a9fa9459Szrj typedef struct aarch64_opcode aarch64_opcode;
544*a9fa9459Szrj
545*a9fa9459Szrj /* Table describing all the AArch64 opcodes. */
546*a9fa9459Szrj extern aarch64_opcode aarch64_opcode_table[];
547*a9fa9459Szrj
548*a9fa9459Szrj /* Opcode flags. */
549*a9fa9459Szrj #define F_ALIAS (1 << 0)
550*a9fa9459Szrj #define F_HAS_ALIAS (1 << 1)
551*a9fa9459Szrj /* Disassembly preference priority 1-3 (the larger the higher). If nothing
552*a9fa9459Szrj is specified, it is the priority 0 by default, i.e. the lowest priority. */
553*a9fa9459Szrj #define F_P1 (1 << 2)
554*a9fa9459Szrj #define F_P2 (2 << 2)
555*a9fa9459Szrj #define F_P3 (3 << 2)
556*a9fa9459Szrj /* Flag an instruction that is truly conditional executed, e.g. b.cond. */
557*a9fa9459Szrj #define F_COND (1 << 4)
558*a9fa9459Szrj /* Instruction has the field of 'sf'. */
559*a9fa9459Szrj #define F_SF (1 << 5)
560*a9fa9459Szrj /* Instruction has the field of 'size:Q'. */
561*a9fa9459Szrj #define F_SIZEQ (1 << 6)
562*a9fa9459Szrj /* Floating-point instruction has the field of 'type'. */
563*a9fa9459Szrj #define F_FPTYPE (1 << 7)
564*a9fa9459Szrj /* AdvSIMD scalar instruction has the field of 'size'. */
565*a9fa9459Szrj #define F_SSIZE (1 << 8)
566*a9fa9459Szrj /* AdvSIMD vector register arrangement specifier encoded in "imm5<3:0>:Q". */
567*a9fa9459Szrj #define F_T (1 << 9)
568*a9fa9459Szrj /* Size of GPR operand in AdvSIMD instructions encoded in Q. */
569*a9fa9459Szrj #define F_GPRSIZE_IN_Q (1 << 10)
570*a9fa9459Szrj /* Size of Rt load signed instruction encoded in opc[0], i.e. bit 22. */
571*a9fa9459Szrj #define F_LDS_SIZE (1 << 11)
572*a9fa9459Szrj /* Optional operand; assume maximum of 1 operand can be optional. */
573*a9fa9459Szrj #define F_OPD0_OPT (1 << 12)
574*a9fa9459Szrj #define F_OPD1_OPT (2 << 12)
575*a9fa9459Szrj #define F_OPD2_OPT (3 << 12)
576*a9fa9459Szrj #define F_OPD3_OPT (4 << 12)
577*a9fa9459Szrj #define F_OPD4_OPT (5 << 12)
578*a9fa9459Szrj /* Default value for the optional operand when omitted from the assembly. */
579*a9fa9459Szrj #define F_DEFAULT(X) (((X) & 0x1f) << 15)
580*a9fa9459Szrj /* Instruction that is an alias of another instruction needs to be
581*a9fa9459Szrj encoded/decoded by converting it to/from the real form, followed by
582*a9fa9459Szrj the encoding/decoding according to the rules of the real opcode.
583*a9fa9459Szrj This compares to the direct coding using the alias's information.
584*a9fa9459Szrj N.B. this flag requires F_ALIAS to be used together. */
585*a9fa9459Szrj #define F_CONV (1 << 20)
586*a9fa9459Szrj /* Use together with F_ALIAS to indicate an alias opcode is a programmer
587*a9fa9459Szrj friendly pseudo instruction available only in the assembly code (thus will
588*a9fa9459Szrj not show up in the disassembly). */
589*a9fa9459Szrj #define F_PSEUDO (1 << 21)
590*a9fa9459Szrj /* Instruction has miscellaneous encoding/decoding rules. */
591*a9fa9459Szrj #define F_MISC (1 << 22)
592*a9fa9459Szrj /* Instruction has the field of 'N'; used in conjunction with F_SF. */
593*a9fa9459Szrj #define F_N (1 << 23)
594*a9fa9459Szrj /* Opcode dependent field. */
595*a9fa9459Szrj #define F_OD(X) (((X) & 0x7) << 24)
596*a9fa9459Szrj /* Instruction has the field of 'sz'. */
597*a9fa9459Szrj #define F_LSE_SZ (1 << 27)
598*a9fa9459Szrj /* Next bit is 28. */
599*a9fa9459Szrj
600*a9fa9459Szrj static inline bfd_boolean
alias_opcode_p(const aarch64_opcode * opcode)601*a9fa9459Szrj alias_opcode_p (const aarch64_opcode *opcode)
602*a9fa9459Szrj {
603*a9fa9459Szrj return (opcode->flags & F_ALIAS) ? TRUE : FALSE;
604*a9fa9459Szrj }
605*a9fa9459Szrj
606*a9fa9459Szrj static inline bfd_boolean
opcode_has_alias(const aarch64_opcode * opcode)607*a9fa9459Szrj opcode_has_alias (const aarch64_opcode *opcode)
608*a9fa9459Szrj {
609*a9fa9459Szrj return (opcode->flags & F_HAS_ALIAS) ? TRUE : FALSE;
610*a9fa9459Szrj }
611*a9fa9459Szrj
612*a9fa9459Szrj /* Priority for disassembling preference. */
613*a9fa9459Szrj static inline int
opcode_priority(const aarch64_opcode * opcode)614*a9fa9459Szrj opcode_priority (const aarch64_opcode *opcode)
615*a9fa9459Szrj {
616*a9fa9459Szrj return (opcode->flags >> 2) & 0x3;
617*a9fa9459Szrj }
618*a9fa9459Szrj
619*a9fa9459Szrj static inline bfd_boolean
pseudo_opcode_p(const aarch64_opcode * opcode)620*a9fa9459Szrj pseudo_opcode_p (const aarch64_opcode *opcode)
621*a9fa9459Szrj {
622*a9fa9459Szrj return (opcode->flags & F_PSEUDO) != 0lu ? TRUE : FALSE;
623*a9fa9459Szrj }
624*a9fa9459Szrj
625*a9fa9459Szrj static inline bfd_boolean
optional_operand_p(const aarch64_opcode * opcode,unsigned int idx)626*a9fa9459Szrj optional_operand_p (const aarch64_opcode *opcode, unsigned int idx)
627*a9fa9459Szrj {
628*a9fa9459Szrj return (((opcode->flags >> 12) & 0x7) == idx + 1)
629*a9fa9459Szrj ? TRUE : FALSE;
630*a9fa9459Szrj }
631*a9fa9459Szrj
632*a9fa9459Szrj static inline aarch64_insn
get_optional_operand_default_value(const aarch64_opcode * opcode)633*a9fa9459Szrj get_optional_operand_default_value (const aarch64_opcode *opcode)
634*a9fa9459Szrj {
635*a9fa9459Szrj return (opcode->flags >> 15) & 0x1f;
636*a9fa9459Szrj }
637*a9fa9459Szrj
638*a9fa9459Szrj static inline unsigned int
get_opcode_dependent_value(const aarch64_opcode * opcode)639*a9fa9459Szrj get_opcode_dependent_value (const aarch64_opcode *opcode)
640*a9fa9459Szrj {
641*a9fa9459Szrj return (opcode->flags >> 24) & 0x7;
642*a9fa9459Szrj }
643*a9fa9459Szrj
644*a9fa9459Szrj static inline bfd_boolean
opcode_has_special_coder(const aarch64_opcode * opcode)645*a9fa9459Szrj opcode_has_special_coder (const aarch64_opcode *opcode)
646*a9fa9459Szrj {
647*a9fa9459Szrj return (opcode->flags & (F_SF | F_LSE_SZ | F_SIZEQ | F_FPTYPE | F_SSIZE | F_T
648*a9fa9459Szrj | F_GPRSIZE_IN_Q | F_LDS_SIZE | F_MISC | F_N | F_COND)) ? TRUE
649*a9fa9459Szrj : FALSE;
650*a9fa9459Szrj }
651*a9fa9459Szrj
652*a9fa9459Szrj struct aarch64_name_value_pair
653*a9fa9459Szrj {
654*a9fa9459Szrj const char * name;
655*a9fa9459Szrj aarch64_insn value;
656*a9fa9459Szrj };
657*a9fa9459Szrj
658*a9fa9459Szrj extern const struct aarch64_name_value_pair aarch64_operand_modifiers [];
659*a9fa9459Szrj extern const struct aarch64_name_value_pair aarch64_barrier_options [16];
660*a9fa9459Szrj extern const struct aarch64_name_value_pair aarch64_prfops [32];
661*a9fa9459Szrj extern const struct aarch64_name_value_pair aarch64_hint_options [];
662*a9fa9459Szrj
663*a9fa9459Szrj typedef struct
664*a9fa9459Szrj {
665*a9fa9459Szrj const char * name;
666*a9fa9459Szrj aarch64_insn value;
667*a9fa9459Szrj uint32_t flags;
668*a9fa9459Szrj } aarch64_sys_reg;
669*a9fa9459Szrj
670*a9fa9459Szrj extern const aarch64_sys_reg aarch64_sys_regs [];
671*a9fa9459Szrj extern const aarch64_sys_reg aarch64_pstatefields [];
672*a9fa9459Szrj extern bfd_boolean aarch64_sys_reg_deprecated_p (const aarch64_sys_reg *);
673*a9fa9459Szrj extern bfd_boolean aarch64_sys_reg_supported_p (const aarch64_feature_set,
674*a9fa9459Szrj const aarch64_sys_reg *);
675*a9fa9459Szrj extern bfd_boolean aarch64_pstatefield_supported_p (const aarch64_feature_set,
676*a9fa9459Szrj const aarch64_sys_reg *);
677*a9fa9459Szrj
678*a9fa9459Szrj typedef struct
679*a9fa9459Szrj {
680*a9fa9459Szrj const char *name;
681*a9fa9459Szrj uint32_t value;
682*a9fa9459Szrj uint32_t flags ;
683*a9fa9459Szrj } aarch64_sys_ins_reg;
684*a9fa9459Szrj
685*a9fa9459Szrj extern bfd_boolean aarch64_sys_ins_reg_has_xt (const aarch64_sys_ins_reg *);
686*a9fa9459Szrj extern bfd_boolean
687*a9fa9459Szrj aarch64_sys_ins_reg_supported_p (const aarch64_feature_set,
688*a9fa9459Szrj const aarch64_sys_ins_reg *);
689*a9fa9459Szrj
690*a9fa9459Szrj extern const aarch64_sys_ins_reg aarch64_sys_regs_ic [];
691*a9fa9459Szrj extern const aarch64_sys_ins_reg aarch64_sys_regs_dc [];
692*a9fa9459Szrj extern const aarch64_sys_ins_reg aarch64_sys_regs_at [];
693*a9fa9459Szrj extern const aarch64_sys_ins_reg aarch64_sys_regs_tlbi [];
694*a9fa9459Szrj
695*a9fa9459Szrj /* Shift/extending operator kinds.
696*a9fa9459Szrj N.B. order is important; keep aarch64_operand_modifiers synced. */
697*a9fa9459Szrj enum aarch64_modifier_kind
698*a9fa9459Szrj {
699*a9fa9459Szrj AARCH64_MOD_NONE,
700*a9fa9459Szrj AARCH64_MOD_MSL,
701*a9fa9459Szrj AARCH64_MOD_ROR,
702*a9fa9459Szrj AARCH64_MOD_ASR,
703*a9fa9459Szrj AARCH64_MOD_LSR,
704*a9fa9459Szrj AARCH64_MOD_LSL,
705*a9fa9459Szrj AARCH64_MOD_UXTB,
706*a9fa9459Szrj AARCH64_MOD_UXTH,
707*a9fa9459Szrj AARCH64_MOD_UXTW,
708*a9fa9459Szrj AARCH64_MOD_UXTX,
709*a9fa9459Szrj AARCH64_MOD_SXTB,
710*a9fa9459Szrj AARCH64_MOD_SXTH,
711*a9fa9459Szrj AARCH64_MOD_SXTW,
712*a9fa9459Szrj AARCH64_MOD_SXTX,
713*a9fa9459Szrj };
714*a9fa9459Szrj
715*a9fa9459Szrj bfd_boolean
716*a9fa9459Szrj aarch64_extend_operator_p (enum aarch64_modifier_kind);
717*a9fa9459Szrj
718*a9fa9459Szrj enum aarch64_modifier_kind
719*a9fa9459Szrj aarch64_get_operand_modifier (const struct aarch64_name_value_pair *);
720*a9fa9459Szrj /* Condition. */
721*a9fa9459Szrj
722*a9fa9459Szrj typedef struct
723*a9fa9459Szrj {
724*a9fa9459Szrj /* A list of names with the first one as the disassembly preference;
725*a9fa9459Szrj terminated by NULL if fewer than 3. */
726*a9fa9459Szrj const char *names[3];
727*a9fa9459Szrj aarch64_insn value;
728*a9fa9459Szrj } aarch64_cond;
729*a9fa9459Szrj
730*a9fa9459Szrj extern const aarch64_cond aarch64_conds[16];
731*a9fa9459Szrj
732*a9fa9459Szrj const aarch64_cond* get_cond_from_value (aarch64_insn value);
733*a9fa9459Szrj const aarch64_cond* get_inverted_cond (const aarch64_cond *cond);
734*a9fa9459Szrj
735*a9fa9459Szrj /* Structure representing an operand. */
736*a9fa9459Szrj
737*a9fa9459Szrj struct aarch64_opnd_info
738*a9fa9459Szrj {
739*a9fa9459Szrj enum aarch64_opnd type;
740*a9fa9459Szrj aarch64_opnd_qualifier_t qualifier;
741*a9fa9459Szrj int idx;
742*a9fa9459Szrj
743*a9fa9459Szrj union
744*a9fa9459Szrj {
745*a9fa9459Szrj struct
746*a9fa9459Szrj {
747*a9fa9459Szrj unsigned regno;
748*a9fa9459Szrj } reg;
749*a9fa9459Szrj struct
750*a9fa9459Szrj {
751*a9fa9459Szrj unsigned int regno;
752*a9fa9459Szrj int64_t index;
753*a9fa9459Szrj } reglane;
754*a9fa9459Szrj /* e.g. LVn. */
755*a9fa9459Szrj struct
756*a9fa9459Szrj {
757*a9fa9459Szrj unsigned first_regno : 5;
758*a9fa9459Szrj unsigned num_regs : 3;
759*a9fa9459Szrj /* 1 if it is a list of reg element. */
760*a9fa9459Szrj unsigned has_index : 1;
761*a9fa9459Szrj /* Lane index; valid only when has_index is 1. */
762*a9fa9459Szrj int64_t index;
763*a9fa9459Szrj } reglist;
764*a9fa9459Szrj /* e.g. immediate or pc relative address offset. */
765*a9fa9459Szrj struct
766*a9fa9459Szrj {
767*a9fa9459Szrj int64_t value;
768*a9fa9459Szrj unsigned is_fp : 1;
769*a9fa9459Szrj } imm;
770*a9fa9459Szrj /* e.g. address in STR (register offset). */
771*a9fa9459Szrj struct
772*a9fa9459Szrj {
773*a9fa9459Szrj unsigned base_regno;
774*a9fa9459Szrj struct
775*a9fa9459Szrj {
776*a9fa9459Szrj union
777*a9fa9459Szrj {
778*a9fa9459Szrj int imm;
779*a9fa9459Szrj unsigned regno;
780*a9fa9459Szrj };
781*a9fa9459Szrj unsigned is_reg;
782*a9fa9459Szrj } offset;
783*a9fa9459Szrj unsigned pcrel : 1; /* PC-relative. */
784*a9fa9459Szrj unsigned writeback : 1;
785*a9fa9459Szrj unsigned preind : 1; /* Pre-indexed. */
786*a9fa9459Szrj unsigned postind : 1; /* Post-indexed. */
787*a9fa9459Szrj } addr;
788*a9fa9459Szrj const aarch64_cond *cond;
789*a9fa9459Szrj /* The encoding of the system register. */
790*a9fa9459Szrj aarch64_insn sysreg;
791*a9fa9459Szrj /* The encoding of the PSTATE field. */
792*a9fa9459Szrj aarch64_insn pstatefield;
793*a9fa9459Szrj const aarch64_sys_ins_reg *sysins_op;
794*a9fa9459Szrj const struct aarch64_name_value_pair *barrier;
795*a9fa9459Szrj const struct aarch64_name_value_pair *hint_option;
796*a9fa9459Szrj const struct aarch64_name_value_pair *prfop;
797*a9fa9459Szrj };
798*a9fa9459Szrj
799*a9fa9459Szrj /* Operand shifter; in use when the operand is a register offset address,
800*a9fa9459Szrj add/sub extended reg, etc. e.g. <R><m>{, <extend> {#<amount>}}. */
801*a9fa9459Szrj struct
802*a9fa9459Szrj {
803*a9fa9459Szrj enum aarch64_modifier_kind kind;
804*a9fa9459Szrj int amount;
805*a9fa9459Szrj unsigned operator_present: 1; /* Only valid during encoding. */
806*a9fa9459Szrj /* Value of the 'S' field in ld/st reg offset; used only in decoding. */
807*a9fa9459Szrj unsigned amount_present: 1;
808*a9fa9459Szrj } shifter;
809*a9fa9459Szrj
810*a9fa9459Szrj unsigned skip:1; /* Operand is not completed if there is a fixup needed
811*a9fa9459Szrj to be done on it. In some (but not all) of these
812*a9fa9459Szrj cases, we need to tell libopcodes to skip the
813*a9fa9459Szrj constraint checking and the encoding for this
814*a9fa9459Szrj operand, so that the libopcodes can pick up the
815*a9fa9459Szrj right opcode before the operand is fixed-up. This
816*a9fa9459Szrj flag should only be used during the
817*a9fa9459Szrj assembling/encoding. */
818*a9fa9459Szrj unsigned present:1; /* Whether this operand is present in the assembly
819*a9fa9459Szrj line; not used during the disassembly. */
820*a9fa9459Szrj };
821*a9fa9459Szrj
822*a9fa9459Szrj typedef struct aarch64_opnd_info aarch64_opnd_info;
823*a9fa9459Szrj
824*a9fa9459Szrj /* Structure representing an instruction.
825*a9fa9459Szrj
826*a9fa9459Szrj It is used during both the assembling and disassembling. The assembler
827*a9fa9459Szrj fills an aarch64_inst after a successful parsing and then passes it to the
828*a9fa9459Szrj encoding routine to do the encoding. During the disassembling, the
829*a9fa9459Szrj disassembler calls the decoding routine to decode a binary instruction; on a
830*a9fa9459Szrj successful return, such a structure will be filled with information of the
831*a9fa9459Szrj instruction; then the disassembler uses the information to print out the
832*a9fa9459Szrj instruction. */
833*a9fa9459Szrj
834*a9fa9459Szrj struct aarch64_inst
835*a9fa9459Szrj {
836*a9fa9459Szrj /* The value of the binary instruction. */
837*a9fa9459Szrj aarch64_insn value;
838*a9fa9459Szrj
839*a9fa9459Szrj /* Corresponding opcode entry. */
840*a9fa9459Szrj const aarch64_opcode *opcode;
841*a9fa9459Szrj
842*a9fa9459Szrj /* Condition for a truly conditional-executed instrutions, e.g. b.cond. */
843*a9fa9459Szrj const aarch64_cond *cond;
844*a9fa9459Szrj
845*a9fa9459Szrj /* Operands information. */
846*a9fa9459Szrj aarch64_opnd_info operands[AARCH64_MAX_OPND_NUM];
847*a9fa9459Szrj };
848*a9fa9459Szrj
849*a9fa9459Szrj typedef struct aarch64_inst aarch64_inst;
850*a9fa9459Szrj
851*a9fa9459Szrj /* Diagnosis related declaration and interface. */
852*a9fa9459Szrj
853*a9fa9459Szrj /* Operand error kind enumerators.
854*a9fa9459Szrj
855*a9fa9459Szrj AARCH64_OPDE_RECOVERABLE
856*a9fa9459Szrj Less severe error found during the parsing, very possibly because that
857*a9fa9459Szrj GAS has picked up a wrong instruction template for the parsing.
858*a9fa9459Szrj
859*a9fa9459Szrj AARCH64_OPDE_SYNTAX_ERROR
860*a9fa9459Szrj General syntax error; it can be either a user error, or simply because
861*a9fa9459Szrj that GAS is trying a wrong instruction template.
862*a9fa9459Szrj
863*a9fa9459Szrj AARCH64_OPDE_FATAL_SYNTAX_ERROR
864*a9fa9459Szrj Definitely a user syntax error.
865*a9fa9459Szrj
866*a9fa9459Szrj AARCH64_OPDE_INVALID_VARIANT
867*a9fa9459Szrj No syntax error, but the operands are not a valid combination, e.g.
868*a9fa9459Szrj FMOV D0,S0
869*a9fa9459Szrj
870*a9fa9459Szrj AARCH64_OPDE_OUT_OF_RANGE
871*a9fa9459Szrj Error about some immediate value out of a valid range.
872*a9fa9459Szrj
873*a9fa9459Szrj AARCH64_OPDE_UNALIGNED
874*a9fa9459Szrj Error about some immediate value not properly aligned (i.e. not being a
875*a9fa9459Szrj multiple times of a certain value).
876*a9fa9459Szrj
877*a9fa9459Szrj AARCH64_OPDE_REG_LIST
878*a9fa9459Szrj Error about the register list operand having unexpected number of
879*a9fa9459Szrj registers.
880*a9fa9459Szrj
881*a9fa9459Szrj AARCH64_OPDE_OTHER_ERROR
882*a9fa9459Szrj Error of the highest severity and used for any severe issue that does not
883*a9fa9459Szrj fall into any of the above categories.
884*a9fa9459Szrj
885*a9fa9459Szrj The enumerators are only interesting to GAS. They are declared here (in
886*a9fa9459Szrj libopcodes) because that some errors are detected (and then notified to GAS)
887*a9fa9459Szrj by libopcodes (rather than by GAS solely).
888*a9fa9459Szrj
889*a9fa9459Szrj The first three errors are only deteced by GAS while the
890*a9fa9459Szrj AARCH64_OPDE_INVALID_VARIANT error can only be spotted by libopcodes as
891*a9fa9459Szrj only libopcodes has the information about the valid variants of each
892*a9fa9459Szrj instruction.
893*a9fa9459Szrj
894*a9fa9459Szrj The enumerators have an increasing severity. This is helpful when there are
895*a9fa9459Szrj multiple instruction templates available for a given mnemonic name (e.g.
896*a9fa9459Szrj FMOV); this mechanism will help choose the most suitable template from which
897*a9fa9459Szrj the generated diagnostics can most closely describe the issues, if any. */
898*a9fa9459Szrj
899*a9fa9459Szrj enum aarch64_operand_error_kind
900*a9fa9459Szrj {
901*a9fa9459Szrj AARCH64_OPDE_NIL,
902*a9fa9459Szrj AARCH64_OPDE_RECOVERABLE,
903*a9fa9459Szrj AARCH64_OPDE_SYNTAX_ERROR,
904*a9fa9459Szrj AARCH64_OPDE_FATAL_SYNTAX_ERROR,
905*a9fa9459Szrj AARCH64_OPDE_INVALID_VARIANT,
906*a9fa9459Szrj AARCH64_OPDE_OUT_OF_RANGE,
907*a9fa9459Szrj AARCH64_OPDE_UNALIGNED,
908*a9fa9459Szrj AARCH64_OPDE_REG_LIST,
909*a9fa9459Szrj AARCH64_OPDE_OTHER_ERROR
910*a9fa9459Szrj };
911*a9fa9459Szrj
912*a9fa9459Szrj /* N.B. GAS assumes that this structure work well with shallow copy. */
913*a9fa9459Szrj struct aarch64_operand_error
914*a9fa9459Szrj {
915*a9fa9459Szrj enum aarch64_operand_error_kind kind;
916*a9fa9459Szrj int index;
917*a9fa9459Szrj const char *error;
918*a9fa9459Szrj int data[3]; /* Some data for extra information. */
919*a9fa9459Szrj };
920*a9fa9459Szrj
921*a9fa9459Szrj typedef struct aarch64_operand_error aarch64_operand_error;
922*a9fa9459Szrj
923*a9fa9459Szrj /* Encoding entrypoint. */
924*a9fa9459Szrj
925*a9fa9459Szrj extern int
926*a9fa9459Szrj aarch64_opcode_encode (const aarch64_opcode *, const aarch64_inst *,
927*a9fa9459Szrj aarch64_insn *, aarch64_opnd_qualifier_t *,
928*a9fa9459Szrj aarch64_operand_error *);
929*a9fa9459Szrj
930*a9fa9459Szrj extern const aarch64_opcode *
931*a9fa9459Szrj aarch64_replace_opcode (struct aarch64_inst *,
932*a9fa9459Szrj const aarch64_opcode *);
933*a9fa9459Szrj
934*a9fa9459Szrj /* Given the opcode enumerator OP, return the pointer to the corresponding
935*a9fa9459Szrj opcode entry. */
936*a9fa9459Szrj
937*a9fa9459Szrj extern const aarch64_opcode *
938*a9fa9459Szrj aarch64_get_opcode (enum aarch64_op);
939*a9fa9459Szrj
940*a9fa9459Szrj /* Generate the string representation of an operand. */
941*a9fa9459Szrj extern void
942*a9fa9459Szrj aarch64_print_operand (char *, size_t, bfd_vma, const aarch64_opcode *,
943*a9fa9459Szrj const aarch64_opnd_info *, int, int *, bfd_vma *);
944*a9fa9459Szrj
945*a9fa9459Szrj /* Miscellaneous interface. */
946*a9fa9459Szrj
947*a9fa9459Szrj extern int
948*a9fa9459Szrj aarch64_operand_index (const enum aarch64_opnd *, enum aarch64_opnd);
949*a9fa9459Szrj
950*a9fa9459Szrj extern aarch64_opnd_qualifier_t
951*a9fa9459Szrj aarch64_get_expected_qualifier (const aarch64_opnd_qualifier_seq_t *, int,
952*a9fa9459Szrj const aarch64_opnd_qualifier_t, int);
953*a9fa9459Szrj
954*a9fa9459Szrj extern int
955*a9fa9459Szrj aarch64_num_of_operands (const aarch64_opcode *);
956*a9fa9459Szrj
957*a9fa9459Szrj extern int
958*a9fa9459Szrj aarch64_stack_pointer_p (const aarch64_opnd_info *);
959*a9fa9459Szrj
960*a9fa9459Szrj extern int
961*a9fa9459Szrj aarch64_zero_register_p (const aarch64_opnd_info *);
962*a9fa9459Szrj
963*a9fa9459Szrj extern int
964*a9fa9459Szrj aarch64_decode_insn (aarch64_insn, aarch64_inst *, bfd_boolean);
965*a9fa9459Szrj
966*a9fa9459Szrj /* Given an operand qualifier, return the expected data element size
967*a9fa9459Szrj of a qualified operand. */
968*a9fa9459Szrj extern unsigned char
969*a9fa9459Szrj aarch64_get_qualifier_esize (aarch64_opnd_qualifier_t);
970*a9fa9459Szrj
971*a9fa9459Szrj extern enum aarch64_operand_class
972*a9fa9459Szrj aarch64_get_operand_class (enum aarch64_opnd);
973*a9fa9459Szrj
974*a9fa9459Szrj extern const char *
975*a9fa9459Szrj aarch64_get_operand_name (enum aarch64_opnd);
976*a9fa9459Szrj
977*a9fa9459Szrj extern const char *
978*a9fa9459Szrj aarch64_get_operand_desc (enum aarch64_opnd);
979*a9fa9459Szrj
980*a9fa9459Szrj #ifdef DEBUG_AARCH64
981*a9fa9459Szrj extern int debug_dump;
982*a9fa9459Szrj
983*a9fa9459Szrj extern void
984*a9fa9459Szrj aarch64_verbose (const char *, ...) __attribute__ ((format (printf, 1, 2)));
985*a9fa9459Szrj
986*a9fa9459Szrj #define DEBUG_TRACE(M, ...) \
987*a9fa9459Szrj { \
988*a9fa9459Szrj if (debug_dump) \
989*a9fa9459Szrj aarch64_verbose ("%s: " M ".", __func__, ##__VA_ARGS__); \
990*a9fa9459Szrj }
991*a9fa9459Szrj
992*a9fa9459Szrj #define DEBUG_TRACE_IF(C, M, ...) \
993*a9fa9459Szrj { \
994*a9fa9459Szrj if (debug_dump && (C)) \
995*a9fa9459Szrj aarch64_verbose ("%s: " M ".", __func__, ##__VA_ARGS__); \
996*a9fa9459Szrj }
997*a9fa9459Szrj #else /* !DEBUG_AARCH64 */
998*a9fa9459Szrj #define DEBUG_TRACE(M, ...) ;
999*a9fa9459Szrj #define DEBUG_TRACE_IF(C, M, ...) ;
1000*a9fa9459Szrj #endif /* DEBUG_AARCH64 */
1001*a9fa9459Szrj
1002*a9fa9459Szrj #ifdef __cplusplus
1003*a9fa9459Szrj }
1004*a9fa9459Szrj #endif
1005*a9fa9459Szrj
1006*a9fa9459Szrj #endif /* OPCODE_AARCH64_H */
1007