aarch64-opc.c revision 1.5.2.1 1 1.1 christos /* aarch64-opc.c -- AArch64 opcode support.
2 1.5.2.1 martin Copyright (C) 2009-2018 Free Software Foundation, Inc.
3 1.1 christos Contributed by ARM Ltd.
4 1.1 christos
5 1.1 christos This file is part of the GNU opcodes library.
6 1.1 christos
7 1.1 christos This library is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3, or (at your option)
10 1.1 christos any later version.
11 1.1 christos
12 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT
13 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 1.1 christos License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program; see the file COPYING3. If not,
19 1.1 christos see <http://www.gnu.org/licenses/>. */
20 1.1 christos
21 1.1 christos #include "sysdep.h"
22 1.1 christos #include <assert.h>
23 1.1 christos #include <stdlib.h>
24 1.1 christos #include <stdio.h>
25 1.1 christos #include <stdint.h>
26 1.1 christos #include <stdarg.h>
27 1.1 christos #include <inttypes.h>
28 1.1 christos
29 1.1 christos #include "opintl.h"
30 1.5.2.1 martin #include "libiberty.h"
31 1.1 christos
32 1.1 christos #include "aarch64-opc.h"
33 1.1 christos
34 1.1 christos #ifdef DEBUG_AARCH64
35 1.1 christos int debug_dump = FALSE;
36 1.1 christos #endif /* DEBUG_AARCH64 */
37 1.1 christos
38 1.5.2.1 martin /* The enumeration strings associated with each value of a 5-bit SVE
39 1.5.2.1 martin pattern operand. A null entry indicates a reserved meaning. */
40 1.5.2.1 martin const char *const aarch64_sve_pattern_array[32] = {
41 1.5.2.1 martin /* 0-7. */
42 1.5.2.1 martin "pow2",
43 1.5.2.1 martin "vl1",
44 1.5.2.1 martin "vl2",
45 1.5.2.1 martin "vl3",
46 1.5.2.1 martin "vl4",
47 1.5.2.1 martin "vl5",
48 1.5.2.1 martin "vl6",
49 1.5.2.1 martin "vl7",
50 1.5.2.1 martin /* 8-15. */
51 1.5.2.1 martin "vl8",
52 1.5.2.1 martin "vl16",
53 1.5.2.1 martin "vl32",
54 1.5.2.1 martin "vl64",
55 1.5.2.1 martin "vl128",
56 1.5.2.1 martin "vl256",
57 1.5.2.1 martin 0,
58 1.5.2.1 martin 0,
59 1.5.2.1 martin /* 16-23. */
60 1.5.2.1 martin 0,
61 1.5.2.1 martin 0,
62 1.5.2.1 martin 0,
63 1.5.2.1 martin 0,
64 1.5.2.1 martin 0,
65 1.5.2.1 martin 0,
66 1.5.2.1 martin 0,
67 1.5.2.1 martin 0,
68 1.5.2.1 martin /* 24-31. */
69 1.5.2.1 martin 0,
70 1.5.2.1 martin 0,
71 1.5.2.1 martin 0,
72 1.5.2.1 martin 0,
73 1.5.2.1 martin 0,
74 1.5.2.1 martin "mul4",
75 1.5.2.1 martin "mul3",
76 1.5.2.1 martin "all"
77 1.5.2.1 martin };
78 1.5.2.1 martin
79 1.5.2.1 martin /* The enumeration strings associated with each value of a 4-bit SVE
80 1.5.2.1 martin prefetch operand. A null entry indicates a reserved meaning. */
81 1.5.2.1 martin const char *const aarch64_sve_prfop_array[16] = {
82 1.5.2.1 martin /* 0-7. */
83 1.5.2.1 martin "pldl1keep",
84 1.5.2.1 martin "pldl1strm",
85 1.5.2.1 martin "pldl2keep",
86 1.5.2.1 martin "pldl2strm",
87 1.5.2.1 martin "pldl3keep",
88 1.5.2.1 martin "pldl3strm",
89 1.5.2.1 martin 0,
90 1.5.2.1 martin 0,
91 1.5.2.1 martin /* 8-15. */
92 1.5.2.1 martin "pstl1keep",
93 1.5.2.1 martin "pstl1strm",
94 1.5.2.1 martin "pstl2keep",
95 1.5.2.1 martin "pstl2strm",
96 1.5.2.1 martin "pstl3keep",
97 1.5.2.1 martin "pstl3strm",
98 1.5.2.1 martin 0,
99 1.5.2.1 martin 0
100 1.5.2.1 martin };
101 1.5.2.1 martin
102 1.1 christos /* Helper functions to determine which operand to be used to encode/decode
103 1.1 christos the size:Q fields for AdvSIMD instructions. */
104 1.1 christos
105 1.1 christos static inline bfd_boolean
106 1.1 christos vector_qualifier_p (enum aarch64_opnd_qualifier qualifier)
107 1.1 christos {
108 1.1 christos return ((qualifier >= AARCH64_OPND_QLF_V_8B
109 1.1 christos && qualifier <= AARCH64_OPND_QLF_V_1Q) ? TRUE
110 1.1 christos : FALSE);
111 1.1 christos }
112 1.1 christos
113 1.1 christos static inline bfd_boolean
114 1.1 christos fp_qualifier_p (enum aarch64_opnd_qualifier qualifier)
115 1.1 christos {
116 1.1 christos return ((qualifier >= AARCH64_OPND_QLF_S_B
117 1.1 christos && qualifier <= AARCH64_OPND_QLF_S_Q) ? TRUE
118 1.1 christos : FALSE);
119 1.1 christos }
120 1.1 christos
121 1.1 christos enum data_pattern
122 1.1 christos {
123 1.1 christos DP_UNKNOWN,
124 1.1 christos DP_VECTOR_3SAME,
125 1.1 christos DP_VECTOR_LONG,
126 1.1 christos DP_VECTOR_WIDE,
127 1.1 christos DP_VECTOR_ACROSS_LANES,
128 1.1 christos };
129 1.1 christos
130 1.1 christos static const char significant_operand_index [] =
131 1.1 christos {
132 1.1 christos 0, /* DP_UNKNOWN, by default using operand 0. */
133 1.1 christos 0, /* DP_VECTOR_3SAME */
134 1.1 christos 1, /* DP_VECTOR_LONG */
135 1.1 christos 2, /* DP_VECTOR_WIDE */
136 1.1 christos 1, /* DP_VECTOR_ACROSS_LANES */
137 1.1 christos };
138 1.1 christos
139 1.1 christos /* Given a sequence of qualifiers in QUALIFIERS, determine and return
140 1.1 christos the data pattern.
141 1.1 christos N.B. QUALIFIERS is a possible sequence of qualifiers each of which
142 1.1 christos corresponds to one of a sequence of operands. */
143 1.1 christos
144 1.1 christos static enum data_pattern
145 1.1 christos get_data_pattern (const aarch64_opnd_qualifier_seq_t qualifiers)
146 1.1 christos {
147 1.1 christos if (vector_qualifier_p (qualifiers[0]) == TRUE)
148 1.1 christos {
149 1.1 christos /* e.g. v.4s, v.4s, v.4s
150 1.1 christos or v.4h, v.4h, v.h[3]. */
151 1.1 christos if (qualifiers[0] == qualifiers[1]
152 1.1 christos && vector_qualifier_p (qualifiers[2]) == TRUE
153 1.1 christos && (aarch64_get_qualifier_esize (qualifiers[0])
154 1.1 christos == aarch64_get_qualifier_esize (qualifiers[1]))
155 1.1 christos && (aarch64_get_qualifier_esize (qualifiers[0])
156 1.1 christos == aarch64_get_qualifier_esize (qualifiers[2])))
157 1.1 christos return DP_VECTOR_3SAME;
158 1.1 christos /* e.g. v.8h, v.8b, v.8b.
159 1.1 christos or v.4s, v.4h, v.h[2].
160 1.1 christos or v.8h, v.16b. */
161 1.1 christos if (vector_qualifier_p (qualifiers[1]) == TRUE
162 1.1 christos && aarch64_get_qualifier_esize (qualifiers[0]) != 0
163 1.1 christos && (aarch64_get_qualifier_esize (qualifiers[0])
164 1.1 christos == aarch64_get_qualifier_esize (qualifiers[1]) << 1))
165 1.1 christos return DP_VECTOR_LONG;
166 1.1 christos /* e.g. v.8h, v.8h, v.8b. */
167 1.1 christos if (qualifiers[0] == qualifiers[1]
168 1.1 christos && vector_qualifier_p (qualifiers[2]) == TRUE
169 1.1 christos && aarch64_get_qualifier_esize (qualifiers[0]) != 0
170 1.1 christos && (aarch64_get_qualifier_esize (qualifiers[0])
171 1.1 christos == aarch64_get_qualifier_esize (qualifiers[2]) << 1)
172 1.1 christos && (aarch64_get_qualifier_esize (qualifiers[0])
173 1.1 christos == aarch64_get_qualifier_esize (qualifiers[1])))
174 1.1 christos return DP_VECTOR_WIDE;
175 1.1 christos }
176 1.1 christos else if (fp_qualifier_p (qualifiers[0]) == TRUE)
177 1.1 christos {
178 1.1 christos /* e.g. SADDLV <V><d>, <Vn>.<T>. */
179 1.1 christos if (vector_qualifier_p (qualifiers[1]) == TRUE
180 1.1 christos && qualifiers[2] == AARCH64_OPND_QLF_NIL)
181 1.1 christos return DP_VECTOR_ACROSS_LANES;
182 1.1 christos }
183 1.1 christos
184 1.1 christos return DP_UNKNOWN;
185 1.1 christos }
186 1.1 christos
187 1.1 christos /* Select the operand to do the encoding/decoding of the 'size:Q' fields in
188 1.1 christos the AdvSIMD instructions. */
189 1.1 christos /* N.B. it is possible to do some optimization that doesn't call
190 1.1 christos get_data_pattern each time when we need to select an operand. We can
191 1.1 christos either buffer the caculated the result or statically generate the data,
192 1.1 christos however, it is not obvious that the optimization will bring significant
193 1.1 christos benefit. */
194 1.1 christos
195 1.1 christos int
196 1.1 christos aarch64_select_operand_for_sizeq_field_coding (const aarch64_opcode *opcode)
197 1.1 christos {
198 1.1 christos return
199 1.1 christos significant_operand_index [get_data_pattern (opcode->qualifiers_list[0])];
200 1.1 christos }
201 1.1 christos
202 1.1 christos const aarch64_field fields[] =
204 1.1 christos {
205 1.1 christos { 0, 0 }, /* NIL. */
206 1.1 christos { 0, 4 }, /* cond2: condition in truly conditional-executed inst. */
207 1.1 christos { 0, 4 }, /* nzcv: flag bit specifier, encoded in the "nzcv" field. */
208 1.1 christos { 5, 5 }, /* defgh: d:e:f:g:h bits in AdvSIMD modified immediate. */
209 1.1 christos { 16, 3 }, /* abc: a:b:c bits in AdvSIMD modified immediate. */
210 1.1 christos { 5, 19 }, /* imm19: e.g. in CBZ. */
211 1.1 christos { 5, 19 }, /* immhi: e.g. in ADRP. */
212 1.1 christos { 29, 2 }, /* immlo: e.g. in ADRP. */
213 1.1 christos { 22, 2 }, /* size: in most AdvSIMD and floating-point instructions. */
214 1.1 christos { 10, 2 }, /* vldst_size: size field in the AdvSIMD load/store inst. */
215 1.1 christos { 29, 1 }, /* op: in AdvSIMD modified immediate instructions. */
216 1.1 christos { 30, 1 }, /* Q: in most AdvSIMD instructions. */
217 1.1 christos { 0, 5 }, /* Rt: in load/store instructions. */
218 1.1 christos { 0, 5 }, /* Rd: in many integer instructions. */
219 1.1 christos { 5, 5 }, /* Rn: in many integer instructions. */
220 1.1 christos { 10, 5 }, /* Rt2: in load/store pair instructions. */
221 1.1 christos { 10, 5 }, /* Ra: in fp instructions. */
222 1.1 christos { 5, 3 }, /* op2: in the system instructions. */
223 1.1 christos { 8, 4 }, /* CRm: in the system instructions. */
224 1.1 christos { 12, 4 }, /* CRn: in the system instructions. */
225 1.1 christos { 16, 3 }, /* op1: in the system instructions. */
226 1.1 christos { 19, 2 }, /* op0: in the system instructions. */
227 1.1 christos { 10, 3 }, /* imm3: in add/sub extended reg instructions. */
228 1.1 christos { 12, 4 }, /* cond: condition flags as a source operand. */
229 1.1 christos { 12, 4 }, /* opcode: in advsimd load/store instructions. */
230 1.1 christos { 12, 4 }, /* cmode: in advsimd modified immediate instructions. */
231 1.1 christos { 13, 3 }, /* asisdlso_opcode: opcode in advsimd ld/st single element. */
232 1.1 christos { 13, 2 }, /* len: in advsimd tbl/tbx instructions. */
233 1.1 christos { 16, 5 }, /* Rm: in ld/st reg offset and some integer inst. */
234 1.1 christos { 16, 5 }, /* Rs: in load/store exclusive instructions. */
235 1.1 christos { 13, 3 }, /* option: in ld/st reg offset + add/sub extended reg inst. */
236 1.1 christos { 12, 1 }, /* S: in load/store reg offset instructions. */
237 1.1 christos { 21, 2 }, /* hw: in move wide constant instructions. */
238 1.1 christos { 22, 2 }, /* opc: in load/store reg offset instructions. */
239 1.1 christos { 23, 1 }, /* opc1: in load/store reg offset instructions. */
240 1.1 christos { 22, 2 }, /* shift: in add/sub reg/imm shifted instructions. */
241 1.1 christos { 22, 2 }, /* type: floating point type field in fp data inst. */
242 1.1 christos { 30, 2 }, /* ldst_size: size field in ld/st reg offset inst. */
243 1.5.2.1 martin { 10, 6 }, /* imm6: in add/sub reg shifted instructions. */
244 1.1 christos { 15, 6 }, /* imm6_2: in rmif instructions. */
245 1.5.2.1 martin { 11, 4 }, /* imm4: in advsimd ext and advsimd ins instructions. */
246 1.1 christos { 0, 4 }, /* imm4_2: in rmif instructions. */
247 1.1 christos { 16, 5 }, /* imm5: in conditional compare (immediate) instructions. */
248 1.1 christos { 15, 7 }, /* imm7: in load/store pair pre/post index instructions. */
249 1.1 christos { 13, 8 }, /* imm8: in floating-point scalar move immediate inst. */
250 1.1 christos { 12, 9 }, /* imm9: in load/store pre/post index instructions. */
251 1.1 christos { 10, 12 }, /* imm12: in ld/st unsigned imm or add/sub shifted inst. */
252 1.1 christos { 5, 14 }, /* imm14: in test bit and branch instructions. */
253 1.1 christos { 5, 16 }, /* imm16: in exception instructions. */
254 1.1 christos { 0, 26 }, /* imm26: in unconditional branch instructions. */
255 1.1 christos { 10, 6 }, /* imms: in bitfield and logical immediate instructions. */
256 1.1 christos { 16, 6 }, /* immr: in bitfield and logical immediate instructions. */
257 1.1 christos { 16, 3 }, /* immb: in advsimd shift by immediate instructions. */
258 1.5.2.1 martin { 19, 4 }, /* immh: in advsimd shift by immediate instructions. */
259 1.1 christos { 22, 1 }, /* S: in LDRAA and LDRAB instructions. */
260 1.1 christos { 22, 1 }, /* N: in logical (immediate) instructions. */
261 1.1 christos { 11, 1 }, /* index: in ld/st inst deciding the pre/post-index. */
262 1.1 christos { 24, 1 }, /* index2: in ld/st pair inst deciding the pre/post-index. */
263 1.3 christos { 31, 1 }, /* sf: in integer data processing instructions. */
264 1.1 christos { 30, 1 }, /* lse_size: in LSE extension atomic instructions. */
265 1.1 christos { 11, 1 }, /* H: in advsimd scalar x indexed element instructions. */
266 1.1 christos { 21, 1 }, /* L: in advsimd scalar x indexed element instructions. */
267 1.1 christos { 20, 1 }, /* M: in advsimd scalar x indexed element instructions. */
268 1.1 christos { 31, 1 }, /* b5: in the test bit and branch instructions. */
269 1.1 christos { 19, 5 }, /* b40: in the test bit and branch instructions. */
270 1.5.2.1 martin { 10, 6 }, /* scale: in the fixed-point scalar to fp converting inst. */
271 1.5.2.1 martin { 4, 1 }, /* SVE_M_4: Merge/zero select, bit 4. */
272 1.5.2.1 martin { 14, 1 }, /* SVE_M_14: Merge/zero select, bit 14. */
273 1.5.2.1 martin { 16, 1 }, /* SVE_M_16: Merge/zero select, bit 16. */
274 1.5.2.1 martin { 17, 1 }, /* SVE_N: SVE equivalent of N. */
275 1.5.2.1 martin { 0, 4 }, /* SVE_Pd: p0-p15, bits [3,0]. */
276 1.5.2.1 martin { 10, 3 }, /* SVE_Pg3: p0-p7, bits [12,10]. */
277 1.5.2.1 martin { 5, 4 }, /* SVE_Pg4_5: p0-p15, bits [8,5]. */
278 1.5.2.1 martin { 10, 4 }, /* SVE_Pg4_10: p0-p15, bits [13,10]. */
279 1.5.2.1 martin { 16, 4 }, /* SVE_Pg4_16: p0-p15, bits [19,16]. */
280 1.5.2.1 martin { 16, 4 }, /* SVE_Pm: p0-p15, bits [19,16]. */
281 1.5.2.1 martin { 5, 4 }, /* SVE_Pn: p0-p15, bits [8,5]. */
282 1.5.2.1 martin { 0, 4 }, /* SVE_Pt: p0-p15, bits [3,0]. */
283 1.5.2.1 martin { 5, 5 }, /* SVE_Rm: SVE alternative position for Rm. */
284 1.5.2.1 martin { 16, 5 }, /* SVE_Rn: SVE alternative position for Rn. */
285 1.5.2.1 martin { 0, 5 }, /* SVE_Vd: Scalar SIMD&FP register, bits [4,0]. */
286 1.5.2.1 martin { 5, 5 }, /* SVE_Vm: Scalar SIMD&FP register, bits [9,5]. */
287 1.5.2.1 martin { 5, 5 }, /* SVE_Vn: Scalar SIMD&FP register, bits [9,5]. */
288 1.5.2.1 martin { 5, 5 }, /* SVE_Za_5: SVE vector register, bits [9,5]. */
289 1.5.2.1 martin { 16, 5 }, /* SVE_Za_16: SVE vector register, bits [20,16]. */
290 1.5.2.1 martin { 0, 5 }, /* SVE_Zd: SVE vector register. bits [4,0]. */
291 1.5.2.1 martin { 5, 5 }, /* SVE_Zm_5: SVE vector register, bits [9,5]. */
292 1.5.2.1 martin { 16, 5 }, /* SVE_Zm_16: SVE vector register, bits [20,16]. */
293 1.5.2.1 martin { 5, 5 }, /* SVE_Zn: SVE vector register, bits [9,5]. */
294 1.5.2.1 martin { 0, 5 }, /* SVE_Zt: SVE vector register, bits [4,0]. */
295 1.5.2.1 martin { 5, 1 }, /* SVE_i1: single-bit immediate. */
296 1.5.2.1 martin { 22, 1 }, /* SVE_i3h: high bit of 3-bit immediate. */
297 1.5.2.1 martin { 16, 3 }, /* SVE_imm3: 3-bit immediate field. */
298 1.5.2.1 martin { 16, 4 }, /* SVE_imm4: 4-bit immediate field. */
299 1.5.2.1 martin { 5, 5 }, /* SVE_imm5: 5-bit immediate field. */
300 1.5.2.1 martin { 16, 5 }, /* SVE_imm5b: secondary 5-bit immediate field. */
301 1.5.2.1 martin { 16, 6 }, /* SVE_imm6: 6-bit immediate field. */
302 1.5.2.1 martin { 14, 7 }, /* SVE_imm7: 7-bit immediate field. */
303 1.5.2.1 martin { 5, 8 }, /* SVE_imm8: 8-bit immediate field. */
304 1.5.2.1 martin { 5, 9 }, /* SVE_imm9: 9-bit immediate field. */
305 1.5.2.1 martin { 11, 6 }, /* SVE_immr: SVE equivalent of immr. */
306 1.5.2.1 martin { 5, 6 }, /* SVE_imms: SVE equivalent of imms. */
307 1.5.2.1 martin { 10, 2 }, /* SVE_msz: 2-bit shift amount for ADR. */
308 1.5.2.1 martin { 5, 5 }, /* SVE_pattern: vector pattern enumeration. */
309 1.5.2.1 martin { 0, 4 }, /* SVE_prfop: prefetch operation for SVE PRF[BHWD]. */
310 1.5.2.1 martin { 16, 1 }, /* SVE_rot1: 1-bit rotation amount. */
311 1.5.2.1 martin { 10, 2 }, /* SVE_rot2: 2-bit rotation amount. */
312 1.5.2.1 martin { 22, 1 }, /* SVE_sz: 1-bit element size select. */
313 1.5.2.1 martin { 16, 4 }, /* SVE_tsz: triangular size select. */
314 1.5.2.1 martin { 22, 2 }, /* SVE_tszh: triangular size select high, bits [23,22]. */
315 1.5.2.1 martin { 8, 2 }, /* SVE_tszl_8: triangular size select low, bits [9,8]. */
316 1.5.2.1 martin { 19, 2 }, /* SVE_tszl_19: triangular size select low, bits [20,19]. */
317 1.5.2.1 martin { 14, 1 }, /* SVE_xs_14: UXTW/SXTW select (bit 14). */
318 1.5.2.1 martin { 22, 1 }, /* SVE_xs_22: UXTW/SXTW select (bit 22). */
319 1.5.2.1 martin { 11, 2 }, /* rotate1: FCMLA immediate rotate. */
320 1.5.2.1 martin { 13, 2 }, /* rotate2: Indexed element FCMLA immediate rotate. */
321 1.5.2.1 martin { 12, 1 }, /* rotate3: FCADD immediate rotate. */
322 1.1 christos { 12, 2 }, /* SM3: Indexed element SM3 2 bits index immediate. */
323 1.1 christos };
324 1.1 christos
325 1.1 christos enum aarch64_operand_class
326 1.1 christos aarch64_get_operand_class (enum aarch64_opnd type)
327 1.1 christos {
328 1.1 christos return aarch64_operands[type].op_class;
329 1.1 christos }
330 1.3 christos
331 1.1 christos const char *
332 1.1 christos aarch64_get_operand_name (enum aarch64_opnd type)
333 1.1 christos {
334 1.1 christos return aarch64_operands[type].name;
335 1.1 christos }
336 1.1 christos
337 1.1 christos /* Get operand description string.
338 1.3 christos This is usually for the diagnosis purpose. */
339 1.1 christos const char *
340 1.1 christos aarch64_get_operand_desc (enum aarch64_opnd type)
341 1.1 christos {
342 1.1 christos return aarch64_operands[type].desc;
343 1.1 christos }
344 1.1 christos
345 1.1 christos /* Table of all conditional affixes. */
346 1.1 christos const aarch64_cond aarch64_conds[16] =
347 1.5.2.1 martin {
348 1.5.2.1 martin {{"eq", "none"}, 0x0},
349 1.5.2.1 martin {{"ne", "any"}, 0x1},
350 1.5.2.1 martin {{"cs", "hs", "nlast"}, 0x2},
351 1.5.2.1 martin {{"cc", "lo", "ul", "last"}, 0x3},
352 1.5.2.1 martin {{"mi", "first"}, 0x4},
353 1.1 christos {{"pl", "nfrst"}, 0x5},
354 1.1 christos {{"vs"}, 0x6},
355 1.5.2.1 martin {{"vc"}, 0x7},
356 1.5.2.1 martin {{"hi", "pmore"}, 0x8},
357 1.5.2.1 martin {{"ls", "plast"}, 0x9},
358 1.5.2.1 martin {{"ge", "tcont"}, 0xa},
359 1.1 christos {{"lt", "tstop"}, 0xb},
360 1.1 christos {{"gt"}, 0xc},
361 1.1 christos {{"le"}, 0xd},
362 1.1 christos {{"al"}, 0xe},
363 1.1 christos {{"nv"}, 0xf},
364 1.1 christos };
365 1.3 christos
366 1.1 christos const aarch64_cond *
367 1.1 christos get_cond_from_value (aarch64_insn value)
368 1.1 christos {
369 1.1 christos assert (value < 16);
370 1.1 christos return &aarch64_conds[(unsigned int) value];
371 1.1 christos }
372 1.3 christos
373 1.1 christos const aarch64_cond *
374 1.1 christos get_inverted_cond (const aarch64_cond *cond)
375 1.1 christos {
376 1.1 christos return &aarch64_conds[cond->value ^ 0x1];
377 1.1 christos }
378 1.1 christos
379 1.1 christos /* Table describing the operand extension/shifting operators; indexed by
380 1.1 christos enum aarch64_modifier_kind.
381 1.1 christos
382 1.1 christos The value column provides the most common values for encoding modifiers,
383 1.1 christos which enables table-driven encoding/decoding for the modifiers. */
384 1.1 christos const struct aarch64_name_value_pair aarch64_operand_modifiers [] =
385 1.1 christos {
386 1.1 christos {"none", 0x0},
387 1.1 christos {"msl", 0x0},
388 1.1 christos {"ror", 0x3},
389 1.1 christos {"asr", 0x2},
390 1.1 christos {"lsr", 0x1},
391 1.1 christos {"lsl", 0x0},
392 1.1 christos {"uxtb", 0x0},
393 1.1 christos {"uxth", 0x1},
394 1.1 christos {"uxtw", 0x2},
395 1.1 christos {"uxtx", 0x3},
396 1.1 christos {"sxtb", 0x4},
397 1.1 christos {"sxth", 0x5},
398 1.1 christos {"sxtw", 0x6},
399 1.5.2.1 martin {"sxtx", 0x7},
400 1.5.2.1 martin {"mul", 0x0},
401 1.1 christos {"mul vl", 0x0},
402 1.1 christos {NULL, 0},
403 1.1 christos };
404 1.1 christos
405 1.1 christos enum aarch64_modifier_kind
406 1.1 christos aarch64_get_operand_modifier (const struct aarch64_name_value_pair *desc)
407 1.1 christos {
408 1.1 christos return desc - aarch64_operand_modifiers;
409 1.1 christos }
410 1.1 christos
411 1.1 christos aarch64_insn
412 1.1 christos aarch64_get_operand_modifier_value (enum aarch64_modifier_kind kind)
413 1.1 christos {
414 1.1 christos return aarch64_operand_modifiers[kind].value;
415 1.1 christos }
416 1.1 christos
417 1.1 christos enum aarch64_modifier_kind
418 1.1 christos aarch64_get_operand_modifier_from_value (aarch64_insn value,
419 1.1 christos bfd_boolean extend_p)
420 1.1 christos {
421 1.1 christos if (extend_p == TRUE)
422 1.1 christos return AARCH64_MOD_UXTB + value;
423 1.1 christos else
424 1.1 christos return AARCH64_MOD_LSL - value;
425 1.1 christos }
426 1.1 christos
427 1.1 christos bfd_boolean
428 1.1 christos aarch64_extend_operator_p (enum aarch64_modifier_kind kind)
429 1.1 christos {
430 1.1 christos return (kind > AARCH64_MOD_LSL && kind <= AARCH64_MOD_SXTX)
431 1.1 christos ? TRUE : FALSE;
432 1.1 christos }
433 1.1 christos
434 1.1 christos static inline bfd_boolean
435 1.1 christos aarch64_shift_operator_p (enum aarch64_modifier_kind kind)
436 1.1 christos {
437 1.1 christos return (kind >= AARCH64_MOD_ROR && kind <= AARCH64_MOD_LSL)
438 1.1 christos ? TRUE : FALSE;
439 1.1 christos }
440 1.1 christos
441 1.1 christos const struct aarch64_name_value_pair aarch64_barrier_options[16] =
442 1.1 christos {
443 1.1 christos { "#0x00", 0x0 },
444 1.1 christos { "oshld", 0x1 },
445 1.1 christos { "oshst", 0x2 },
446 1.1 christos { "osh", 0x3 },
447 1.1 christos { "#0x04", 0x4 },
448 1.1 christos { "nshld", 0x5 },
449 1.1 christos { "nshst", 0x6 },
450 1.1 christos { "nsh", 0x7 },
451 1.1 christos { "#0x08", 0x8 },
452 1.1 christos { "ishld", 0x9 },
453 1.1 christos { "ishst", 0xa },
454 1.1 christos { "ish", 0xb },
455 1.1 christos { "#0x0c", 0xc },
456 1.1 christos { "ld", 0xd },
457 1.1 christos { "st", 0xe },
458 1.1 christos { "sy", 0xf },
459 1.1 christos };
460 1.3 christos
461 1.3 christos /* Table describing the operands supported by the aliases of the HINT
462 1.3 christos instruction.
463 1.3 christos
464 1.3 christos The name column is the operand that is accepted for the alias. The value
465 1.3 christos column is the hint number of the alias. The list of operands is terminated
466 1.3 christos by NULL in the name column. */
467 1.3 christos
468 1.3 christos const struct aarch64_name_value_pair aarch64_hint_options[] =
469 1.3 christos {
470 1.3 christos { "csync", 0x11 }, /* PSB CSYNC. */
471 1.3 christos { NULL, 0x0 },
472 1.3 christos };
473 1.1 christos
474 1.1 christos /* op -> op: load = 0 instruction = 1 store = 2
475 1.1 christos l -> level: 1-3
476 1.1 christos t -> temporal: temporal (retained) = 0 non-temporal (streaming) = 1 */
477 1.1 christos #define B(op,l,t) (((op) << 3) | (((l) - 1) << 1) | (t))
478 1.1 christos const struct aarch64_name_value_pair aarch64_prfops[32] =
479 1.1 christos {
480 1.1 christos { "pldl1keep", B(0, 1, 0) },
481 1.1 christos { "pldl1strm", B(0, 1, 1) },
482 1.1 christos { "pldl2keep", B(0, 2, 0) },
483 1.1 christos { "pldl2strm", B(0, 2, 1) },
484 1.1 christos { "pldl3keep", B(0, 3, 0) },
485 1.1 christos { "pldl3strm", B(0, 3, 1) },
486 1.1 christos { NULL, 0x06 },
487 1.1 christos { NULL, 0x07 },
488 1.1 christos { "plil1keep", B(1, 1, 0) },
489 1.1 christos { "plil1strm", B(1, 1, 1) },
490 1.1 christos { "plil2keep", B(1, 2, 0) },
491 1.1 christos { "plil2strm", B(1, 2, 1) },
492 1.1 christos { "plil3keep", B(1, 3, 0) },
493 1.1 christos { "plil3strm", B(1, 3, 1) },
494 1.1 christos { NULL, 0x0e },
495 1.1 christos { NULL, 0x0f },
496 1.1 christos { "pstl1keep", B(2, 1, 0) },
497 1.1 christos { "pstl1strm", B(2, 1, 1) },
498 1.1 christos { "pstl2keep", B(2, 2, 0) },
499 1.1 christos { "pstl2strm", B(2, 2, 1) },
500 1.1 christos { "pstl3keep", B(2, 3, 0) },
501 1.1 christos { "pstl3strm", B(2, 3, 1) },
502 1.1 christos { NULL, 0x16 },
503 1.1 christos { NULL, 0x17 },
504 1.1 christos { NULL, 0x18 },
505 1.1 christos { NULL, 0x19 },
506 1.1 christos { NULL, 0x1a },
507 1.1 christos { NULL, 0x1b },
508 1.1 christos { NULL, 0x1c },
509 1.1 christos { NULL, 0x1d },
510 1.1 christos { NULL, 0x1e },
511 1.1 christos { NULL, 0x1f },
512 1.1 christos };
513 1.1 christos #undef B
514 1.1 christos
515 1.1 christos /* Utilities on value constraint. */
517 1.1 christos
518 1.1 christos static inline int
519 1.1 christos value_in_range_p (int64_t value, int low, int high)
520 1.1 christos {
521 1.1 christos return (value >= low && value <= high) ? 1 : 0;
522 1.5.2.1 martin }
523 1.1 christos
524 1.1 christos /* Return true if VALUE is a multiple of ALIGN. */
525 1.1 christos static inline int
526 1.5.2.1 martin value_aligned_p (int64_t value, int align)
527 1.1 christos {
528 1.1 christos return (value % align) == 0;
529 1.1 christos }
530 1.1 christos
531 1.1 christos /* A signed value fits in a field. */
532 1.1 christos static inline int
533 1.1 christos value_fit_signed_field_p (int64_t value, unsigned width)
534 1.1 christos {
535 1.1 christos assert (width < 32);
536 1.1 christos if (width < sizeof (value) * 8)
537 1.1 christos {
538 1.1 christos int64_t lim = (int64_t)1 << (width - 1);
539 1.1 christos if (value >= -lim && value < lim)
540 1.1 christos return 1;
541 1.1 christos }
542 1.1 christos return 0;
543 1.1 christos }
544 1.1 christos
545 1.1 christos /* An unsigned value fits in a field. */
546 1.1 christos static inline int
547 1.1 christos value_fit_unsigned_field_p (int64_t value, unsigned width)
548 1.1 christos {
549 1.1 christos assert (width < 32);
550 1.1 christos if (width < sizeof (value) * 8)
551 1.1 christos {
552 1.1 christos int64_t lim = (int64_t)1 << width;
553 1.1 christos if (value >= 0 && value < lim)
554 1.1 christos return 1;
555 1.1 christos }
556 1.1 christos return 0;
557 1.1 christos }
558 1.1 christos
559 1.1 christos /* Return 1 if OPERAND is SP or WSP. */
560 1.1 christos int
561 1.1 christos aarch64_stack_pointer_p (const aarch64_opnd_info *operand)
562 1.1 christos {
563 1.1 christos return ((aarch64_get_operand_class (operand->type)
564 1.1 christos == AARCH64_OPND_CLASS_INT_REG)
565 1.1 christos && operand_maybe_stack_pointer (aarch64_operands + operand->type)
566 1.1 christos && operand->reg.regno == 31);
567 1.1 christos }
568 1.1 christos
569 1.1 christos /* Return 1 if OPERAND is XZR or WZP. */
570 1.1 christos int
571 1.1 christos aarch64_zero_register_p (const aarch64_opnd_info *operand)
572 1.1 christos {
573 1.1 christos return ((aarch64_get_operand_class (operand->type)
574 1.1 christos == AARCH64_OPND_CLASS_INT_REG)
575 1.1 christos && !operand_maybe_stack_pointer (aarch64_operands + operand->type)
576 1.1 christos && operand->reg.regno == 31);
577 1.1 christos }
578 1.1 christos
579 1.1 christos /* Return true if the operand *OPERAND that has the operand code
580 1.1 christos OPERAND->TYPE and been qualified by OPERAND->QUALIFIER can be also
581 1.1 christos qualified by the qualifier TARGET. */
582 1.1 christos
583 1.1 christos static inline int
584 1.1 christos operand_also_qualified_p (const struct aarch64_opnd_info *operand,
585 1.1 christos aarch64_opnd_qualifier_t target)
586 1.1 christos {
587 1.1 christos switch (operand->qualifier)
588 1.1 christos {
589 1.1 christos case AARCH64_OPND_QLF_W:
590 1.1 christos if (target == AARCH64_OPND_QLF_WSP && aarch64_stack_pointer_p (operand))
591 1.1 christos return 1;
592 1.1 christos break;
593 1.1 christos case AARCH64_OPND_QLF_X:
594 1.1 christos if (target == AARCH64_OPND_QLF_SP && aarch64_stack_pointer_p (operand))
595 1.1 christos return 1;
596 1.1 christos break;
597 1.1 christos case AARCH64_OPND_QLF_WSP:
598 1.1 christos if (target == AARCH64_OPND_QLF_W
599 1.1 christos && operand_maybe_stack_pointer (aarch64_operands + operand->type))
600 1.1 christos return 1;
601 1.1 christos break;
602 1.1 christos case AARCH64_OPND_QLF_SP:
603 1.1 christos if (target == AARCH64_OPND_QLF_X
604 1.1 christos && operand_maybe_stack_pointer (aarch64_operands + operand->type))
605 1.1 christos return 1;
606 1.1 christos break;
607 1.1 christos default:
608 1.1 christos break;
609 1.1 christos }
610 1.1 christos
611 1.1 christos return 0;
612 1.1 christos }
613 1.1 christos
614 1.1 christos /* Given qualifier sequence list QSEQ_LIST and the known qualifier KNOWN_QLF
615 1.1 christos for operand KNOWN_IDX, return the expected qualifier for operand IDX.
616 1.1 christos
617 1.1 christos Return NIL if more than one expected qualifiers are found. */
618 1.1 christos
619 1.1 christos aarch64_opnd_qualifier_t
620 1.1 christos aarch64_get_expected_qualifier (const aarch64_opnd_qualifier_seq_t *qseq_list,
621 1.1 christos int idx,
622 1.1 christos const aarch64_opnd_qualifier_t known_qlf,
623 1.1 christos int known_idx)
624 1.1 christos {
625 1.1 christos int i, saved_i;
626 1.1 christos
627 1.1 christos /* Special case.
628 1.1 christos
629 1.1 christos When the known qualifier is NIL, we have to assume that there is only
630 1.1 christos one qualifier sequence in the *QSEQ_LIST and return the corresponding
631 1.1 christos qualifier directly. One scenario is that for instruction
632 1.1 christos PRFM <prfop>, [<Xn|SP>, #:lo12:<symbol>]
633 1.1 christos which has only one possible valid qualifier sequence
634 1.1 christos NIL, S_D
635 1.1 christos the caller may pass NIL in KNOWN_QLF to obtain S_D so that it can
636 1.1 christos determine the correct relocation type (i.e. LDST64_LO12) for PRFM.
637 1.1 christos
638 1.1 christos Because the qualifier NIL has dual roles in the qualifier sequence:
639 1.1 christos it can mean no qualifier for the operand, or the qualifer sequence is
640 1.1 christos not in use (when all qualifiers in the sequence are NILs), we have to
641 1.1 christos handle this special case here. */
642 1.1 christos if (known_qlf == AARCH64_OPND_NIL)
643 1.1 christos {
644 1.1 christos assert (qseq_list[0][known_idx] == AARCH64_OPND_NIL);
645 1.1 christos return qseq_list[0][idx];
646 1.1 christos }
647 1.1 christos
648 1.1 christos for (i = 0, saved_i = -1; i < AARCH64_MAX_QLF_SEQ_NUM; ++i)
649 1.1 christos {
650 1.1 christos if (qseq_list[i][known_idx] == known_qlf)
651 1.1 christos {
652 1.1 christos if (saved_i != -1)
653 1.1 christos /* More than one sequences are found to have KNOWN_QLF at
654 1.1 christos KNOWN_IDX. */
655 1.1 christos return AARCH64_OPND_NIL;
656 1.1 christos saved_i = i;
657 1.1 christos }
658 1.1 christos }
659 1.1 christos
660 1.1 christos return qseq_list[saved_i][idx];
661 1.1 christos }
662 1.1 christos
663 1.1 christos enum operand_qualifier_kind
664 1.1 christos {
665 1.1 christos OQK_NIL,
666 1.1 christos OQK_OPD_VARIANT,
667 1.1 christos OQK_VALUE_IN_RANGE,
668 1.1 christos OQK_MISC,
669 1.1 christos };
670 1.1 christos
671 1.1 christos /* Operand qualifier description. */
672 1.1 christos struct operand_qualifier_data
673 1.1 christos {
674 1.1 christos /* The usage of the three data fields depends on the qualifier kind. */
675 1.1 christos int data0;
676 1.1 christos int data1;
677 1.1 christos int data2;
678 1.1 christos /* Description. */
679 1.1 christos const char *desc;
680 1.1 christos /* Kind. */
681 1.1 christos enum operand_qualifier_kind kind;
682 1.1 christos };
683 1.1 christos
684 1.1 christos /* Indexed by the operand qualifier enumerators. */
685 1.1 christos struct operand_qualifier_data aarch64_opnd_qualifiers[] =
686 1.1 christos {
687 1.1 christos {0, 0, 0, "NIL", OQK_NIL},
688 1.1 christos
689 1.1 christos /* Operand variant qualifiers.
690 1.1 christos First 3 fields:
691 1.1 christos element size, number of elements and common value for encoding. */
692 1.1 christos
693 1.1 christos {4, 1, 0x0, "w", OQK_OPD_VARIANT},
694 1.1 christos {8, 1, 0x1, "x", OQK_OPD_VARIANT},
695 1.1 christos {4, 1, 0x0, "wsp", OQK_OPD_VARIANT},
696 1.1 christos {8, 1, 0x1, "sp", OQK_OPD_VARIANT},
697 1.1 christos
698 1.1 christos {1, 1, 0x0, "b", OQK_OPD_VARIANT},
699 1.1 christos {2, 1, 0x1, "h", OQK_OPD_VARIANT},
700 1.1 christos {4, 1, 0x2, "s", OQK_OPD_VARIANT},
701 1.5.2.1 martin {8, 1, 0x3, "d", OQK_OPD_VARIANT},
702 1.1 christos {16, 1, 0x4, "q", OQK_OPD_VARIANT},
703 1.5.2.1 martin {1, 4, 0x0, "4b", OQK_OPD_VARIANT},
704 1.1 christos
705 1.1 christos {1, 4, 0x0, "4b", OQK_OPD_VARIANT},
706 1.3 christos {1, 8, 0x0, "8b", OQK_OPD_VARIANT},
707 1.1 christos {1, 16, 0x1, "16b", OQK_OPD_VARIANT},
708 1.1 christos {2, 2, 0x0, "2h", OQK_OPD_VARIANT},
709 1.1 christos {2, 4, 0x2, "4h", OQK_OPD_VARIANT},
710 1.1 christos {2, 8, 0x3, "8h", OQK_OPD_VARIANT},
711 1.1 christos {4, 2, 0x4, "2s", OQK_OPD_VARIANT},
712 1.1 christos {4, 4, 0x5, "4s", OQK_OPD_VARIANT},
713 1.1 christos {8, 1, 0x6, "1d", OQK_OPD_VARIANT},
714 1.1 christos {8, 2, 0x7, "2d", OQK_OPD_VARIANT},
715 1.5.2.1 martin {16, 1, 0x8, "1q", OQK_OPD_VARIANT},
716 1.5.2.1 martin
717 1.5.2.1 martin {0, 0, 0, "z", OQK_OPD_VARIANT},
718 1.1 christos {0, 0, 0, "m", OQK_OPD_VARIANT},
719 1.1 christos
720 1.1 christos /* Qualifiers constraining the value range.
721 1.1 christos First 3 fields:
722 1.5.2.1 martin Lower bound, higher bound, unused. */
723 1.1 christos
724 1.1 christos {0, 15, 0, "CR", OQK_VALUE_IN_RANGE},
725 1.1 christos {0, 7, 0, "imm_0_7" , OQK_VALUE_IN_RANGE},
726 1.1 christos {0, 15, 0, "imm_0_15", OQK_VALUE_IN_RANGE},
727 1.1 christos {0, 31, 0, "imm_0_31", OQK_VALUE_IN_RANGE},
728 1.1 christos {0, 63, 0, "imm_0_63", OQK_VALUE_IN_RANGE},
729 1.1 christos {1, 32, 0, "imm_1_32", OQK_VALUE_IN_RANGE},
730 1.1 christos {1, 64, 0, "imm_1_64", OQK_VALUE_IN_RANGE},
731 1.1 christos
732 1.1 christos /* Qualifiers for miscellaneous purpose.
733 1.1 christos First 3 fields:
734 1.1 christos unused, unused and unused. */
735 1.1 christos
736 1.1 christos {0, 0, 0, "lsl", 0},
737 1.1 christos {0, 0, 0, "msl", 0},
738 1.1 christos
739 1.1 christos {0, 0, 0, "retrieving", 0},
740 1.1 christos };
741 1.1 christos
742 1.1 christos static inline bfd_boolean
743 1.1 christos operand_variant_qualifier_p (aarch64_opnd_qualifier_t qualifier)
744 1.1 christos {
745 1.1 christos return (aarch64_opnd_qualifiers[qualifier].kind == OQK_OPD_VARIANT)
746 1.1 christos ? TRUE : FALSE;
747 1.1 christos }
748 1.1 christos
749 1.1 christos static inline bfd_boolean
750 1.1 christos qualifier_value_in_range_constraint_p (aarch64_opnd_qualifier_t qualifier)
751 1.1 christos {
752 1.1 christos return (aarch64_opnd_qualifiers[qualifier].kind == OQK_VALUE_IN_RANGE)
753 1.1 christos ? TRUE : FALSE;
754 1.1 christos }
755 1.1 christos
756 1.1 christos const char*
757 1.1 christos aarch64_get_qualifier_name (aarch64_opnd_qualifier_t qualifier)
758 1.1 christos {
759 1.1 christos return aarch64_opnd_qualifiers[qualifier].desc;
760 1.1 christos }
761 1.1 christos
762 1.1 christos /* Given an operand qualifier, return the expected data element size
763 1.1 christos of a qualified operand. */
764 1.1 christos unsigned char
765 1.1 christos aarch64_get_qualifier_esize (aarch64_opnd_qualifier_t qualifier)
766 1.1 christos {
767 1.1 christos assert (operand_variant_qualifier_p (qualifier) == TRUE);
768 1.1 christos return aarch64_opnd_qualifiers[qualifier].data0;
769 1.1 christos }
770 1.1 christos
771 1.1 christos unsigned char
772 1.1 christos aarch64_get_qualifier_nelem (aarch64_opnd_qualifier_t qualifier)
773 1.1 christos {
774 1.1 christos assert (operand_variant_qualifier_p (qualifier) == TRUE);
775 1.1 christos return aarch64_opnd_qualifiers[qualifier].data1;
776 1.1 christos }
777 1.1 christos
778 1.1 christos aarch64_insn
779 1.1 christos aarch64_get_qualifier_standard_value (aarch64_opnd_qualifier_t qualifier)
780 1.1 christos {
781 1.1 christos assert (operand_variant_qualifier_p (qualifier) == TRUE);
782 1.1 christos return aarch64_opnd_qualifiers[qualifier].data2;
783 1.1 christos }
784 1.1 christos
785 1.1 christos static int
786 1.1 christos get_lower_bound (aarch64_opnd_qualifier_t qualifier)
787 1.1 christos {
788 1.1 christos assert (qualifier_value_in_range_constraint_p (qualifier) == TRUE);
789 1.1 christos return aarch64_opnd_qualifiers[qualifier].data0;
790 1.1 christos }
791 1.1 christos
792 1.1 christos static int
793 1.1 christos get_upper_bound (aarch64_opnd_qualifier_t qualifier)
794 1.1 christos {
795 1.1 christos assert (qualifier_value_in_range_constraint_p (qualifier) == TRUE);
796 1.1 christos return aarch64_opnd_qualifiers[qualifier].data1;
797 1.1 christos }
798 1.1 christos
799 1.1 christos #ifdef DEBUG_AARCH64
800 1.1 christos void
801 1.1 christos aarch64_verbose (const char *str, ...)
802 1.1 christos {
803 1.1 christos va_list ap;
804 1.1 christos va_start (ap, str);
805 1.1 christos printf ("#### ");
806 1.1 christos vprintf (str, ap);
807 1.1 christos printf ("\n");
808 1.1 christos va_end (ap);
809 1.1 christos }
810 1.1 christos
811 1.1 christos static inline void
812 1.1 christos dump_qualifier_sequence (const aarch64_opnd_qualifier_t *qualifier)
813 1.1 christos {
814 1.1 christos int i;
815 1.1 christos printf ("#### \t");
816 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i, ++qualifier)
817 1.1 christos printf ("%s,", aarch64_get_qualifier_name (*qualifier));
818 1.1 christos printf ("\n");
819 1.1 christos }
820 1.1 christos
821 1.1 christos static void
822 1.1 christos dump_match_qualifiers (const struct aarch64_opnd_info *opnd,
823 1.1 christos const aarch64_opnd_qualifier_t *qualifier)
824 1.1 christos {
825 1.1 christos int i;
826 1.1 christos aarch64_opnd_qualifier_t curr[AARCH64_MAX_OPND_NUM];
827 1.1 christos
828 1.1 christos aarch64_verbose ("dump_match_qualifiers:");
829 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
830 1.1 christos curr[i] = opnd[i].qualifier;
831 1.1 christos dump_qualifier_sequence (curr);
832 1.1 christos aarch64_verbose ("against");
833 1.1 christos dump_qualifier_sequence (qualifier);
834 1.1 christos }
835 1.1 christos #endif /* DEBUG_AARCH64 */
836 1.1 christos
837 1.1 christos /* TODO improve this, we can have an extra field at the runtime to
838 1.1 christos store the number of operands rather than calculating it every time. */
839 1.1 christos
840 1.1 christos int
841 1.1 christos aarch64_num_of_operands (const aarch64_opcode *opcode)
842 1.1 christos {
843 1.1 christos int i = 0;
844 1.1 christos const enum aarch64_opnd *opnds = opcode->operands;
845 1.1 christos while (opnds[i++] != AARCH64_OPND_NIL)
846 1.1 christos ;
847 1.1 christos --i;
848 1.1 christos assert (i >= 0 && i <= AARCH64_MAX_OPND_NUM);
849 1.1 christos return i;
850 1.1 christos }
851 1.1 christos
852 1.1 christos /* Find the best matched qualifier sequence in *QUALIFIERS_LIST for INST.
853 1.1 christos If succeeds, fill the found sequence in *RET, return 1; otherwise return 0.
854 1.1 christos
855 1.1 christos N.B. on the entry, it is very likely that only some operands in *INST
856 1.1 christos have had their qualifiers been established.
857 1.1 christos
858 1.1 christos If STOP_AT is not -1, the function will only try to match
859 1.1 christos the qualifier sequence for operands before and including the operand
860 1.1 christos of index STOP_AT; and on success *RET will only be filled with the first
861 1.1 christos (STOP_AT+1) qualifiers.
862 1.1 christos
863 1.1 christos A couple examples of the matching algorithm:
864 1.1 christos
865 1.1 christos X,W,NIL should match
866 1.1 christos X,W,NIL
867 1.1 christos
868 1.1 christos NIL,NIL should match
869 1.1 christos X ,NIL
870 1.1 christos
871 1.1 christos Apart from serving the main encoding routine, this can also be called
872 1.1 christos during or after the operand decoding. */
873 1.1 christos
874 1.1 christos int
875 1.1 christos aarch64_find_best_match (const aarch64_inst *inst,
876 1.1 christos const aarch64_opnd_qualifier_seq_t *qualifiers_list,
877 1.1 christos int stop_at, aarch64_opnd_qualifier_t *ret)
878 1.1 christos {
879 1.1 christos int found = 0;
880 1.1 christos int i, num_opnds;
881 1.1 christos const aarch64_opnd_qualifier_t *qualifiers;
882 1.1 christos
883 1.1 christos num_opnds = aarch64_num_of_operands (inst->opcode);
884 1.1 christos if (num_opnds == 0)
885 1.1 christos {
886 1.1 christos DEBUG_TRACE ("SUCCEED: no operand");
887 1.1 christos return 1;
888 1.1 christos }
889 1.1 christos
890 1.1 christos if (stop_at < 0 || stop_at >= num_opnds)
891 1.1 christos stop_at = num_opnds - 1;
892 1.1 christos
893 1.1 christos /* For each pattern. */
894 1.1 christos for (i = 0; i < AARCH64_MAX_QLF_SEQ_NUM; ++i, ++qualifiers_list)
895 1.1 christos {
896 1.1 christos int j;
897 1.1 christos qualifiers = *qualifiers_list;
898 1.1 christos
899 1.1 christos /* Start as positive. */
900 1.1 christos found = 1;
901 1.1 christos
902 1.1 christos DEBUG_TRACE ("%d", i);
903 1.1 christos #ifdef DEBUG_AARCH64
904 1.1 christos if (debug_dump)
905 1.1 christos dump_match_qualifiers (inst->operands, qualifiers);
906 1.1 christos #endif
907 1.1 christos
908 1.1 christos /* Most opcodes has much fewer patterns in the list.
909 1.1 christos First NIL qualifier indicates the end in the list. */
910 1.1 christos if (empty_qualifier_sequence_p (qualifiers) == TRUE)
911 1.1 christos {
912 1.1 christos DEBUG_TRACE_IF (i == 0, "SUCCEED: empty qualifier list");
913 1.1 christos if (i)
914 1.1 christos found = 0;
915 1.1 christos break;
916 1.1 christos }
917 1.1 christos
918 1.1 christos for (j = 0; j < num_opnds && j <= stop_at; ++j, ++qualifiers)
919 1.1 christos {
920 1.1 christos if (inst->operands[j].qualifier == AARCH64_OPND_QLF_NIL)
921 1.1 christos {
922 1.1 christos /* Either the operand does not have qualifier, or the qualifier
923 1.1 christos for the operand needs to be deduced from the qualifier
924 1.1 christos sequence.
925 1.1 christos In the latter case, any constraint checking related with
926 1.1 christos the obtained qualifier should be done later in
927 1.1 christos operand_general_constraint_met_p. */
928 1.1 christos continue;
929 1.1 christos }
930 1.1 christos else if (*qualifiers != inst->operands[j].qualifier)
931 1.1 christos {
932 1.1 christos /* Unless the target qualifier can also qualify the operand
933 1.1 christos (which has already had a non-nil qualifier), non-equal
934 1.1 christos qualifiers are generally un-matched. */
935 1.1 christos if (operand_also_qualified_p (inst->operands + j, *qualifiers))
936 1.1 christos continue;
937 1.1 christos else
938 1.1 christos {
939 1.1 christos found = 0;
940 1.1 christos break;
941 1.1 christos }
942 1.1 christos }
943 1.1 christos else
944 1.1 christos continue; /* Equal qualifiers are certainly matched. */
945 1.1 christos }
946 1.1 christos
947 1.1 christos /* Qualifiers established. */
948 1.1 christos if (found == 1)
949 1.1 christos break;
950 1.1 christos }
951 1.1 christos
952 1.1 christos if (found == 1)
953 1.1 christos {
954 1.1 christos /* Fill the result in *RET. */
955 1.1 christos int j;
956 1.1 christos qualifiers = *qualifiers_list;
957 1.1 christos
958 1.1 christos DEBUG_TRACE ("complete qualifiers using list %d", i);
959 1.1 christos #ifdef DEBUG_AARCH64
960 1.1 christos if (debug_dump)
961 1.1 christos dump_qualifier_sequence (qualifiers);
962 1.1 christos #endif
963 1.1 christos
964 1.1 christos for (j = 0; j <= stop_at; ++j, ++qualifiers)
965 1.1 christos ret[j] = *qualifiers;
966 1.1 christos for (; j < AARCH64_MAX_OPND_NUM; ++j)
967 1.1 christos ret[j] = AARCH64_OPND_QLF_NIL;
968 1.1 christos
969 1.1 christos DEBUG_TRACE ("SUCCESS");
970 1.1 christos return 1;
971 1.1 christos }
972 1.1 christos
973 1.1 christos DEBUG_TRACE ("FAIL");
974 1.1 christos return 0;
975 1.1 christos }
976 1.1 christos
977 1.1 christos /* Operand qualifier matching and resolving.
978 1.1 christos
979 1.1 christos Return 1 if the operand qualifier(s) in *INST match one of the qualifier
980 1.1 christos sequences in INST->OPCODE->qualifiers_list; otherwise return 0.
981 1.1 christos
982 1.1 christos if UPDATE_P == TRUE, update the qualifier(s) in *INST after the matching
983 1.1 christos succeeds. */
984 1.1 christos
985 1.1 christos static int
986 1.5.2.1 martin match_operands_qualifier (aarch64_inst *inst, bfd_boolean update_p)
987 1.1 christos {
988 1.1 christos int i, nops;
989 1.1 christos aarch64_opnd_qualifier_seq_t qualifiers;
990 1.1 christos
991 1.1 christos if (!aarch64_find_best_match (inst, inst->opcode->qualifiers_list, -1,
992 1.1 christos qualifiers))
993 1.1 christos {
994 1.1 christos DEBUG_TRACE ("matching FAIL");
995 1.1 christos return 0;
996 1.5.2.1 martin }
997 1.5.2.1 martin
998 1.5.2.1 martin if (inst->opcode->flags & F_STRICT)
999 1.5.2.1 martin {
1000 1.5.2.1 martin /* Require an exact qualifier match, even for NIL qualifiers. */
1001 1.5.2.1 martin nops = aarch64_num_of_operands (inst->opcode);
1002 1.5.2.1 martin for (i = 0; i < nops; ++i)
1003 1.5.2.1 martin if (inst->operands[i].qualifier != qualifiers[i])
1004 1.5.2.1 martin return FALSE;
1005 1.1 christos }
1006 1.1 christos
1007 1.1 christos /* Update the qualifiers. */
1008 1.1 christos if (update_p == TRUE)
1009 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
1010 1.1 christos {
1011 1.1 christos if (inst->opcode->operands[i] == AARCH64_OPND_NIL)
1012 1.1 christos break;
1013 1.1 christos DEBUG_TRACE_IF (inst->operands[i].qualifier != qualifiers[i],
1014 1.1 christos "update %s with %s for operand %d",
1015 1.1 christos aarch64_get_qualifier_name (inst->operands[i].qualifier),
1016 1.1 christos aarch64_get_qualifier_name (qualifiers[i]), i);
1017 1.1 christos inst->operands[i].qualifier = qualifiers[i];
1018 1.1 christos }
1019 1.1 christos
1020 1.1 christos DEBUG_TRACE ("matching SUCCESS");
1021 1.1 christos return 1;
1022 1.1 christos }
1023 1.1 christos
1024 1.1 christos /* Return TRUE if VALUE is a wide constant that can be moved into a general
1025 1.1 christos register by MOVZ.
1026 1.1 christos
1027 1.1 christos IS32 indicates whether value is a 32-bit immediate or not.
1028 1.1 christos If SHIFT_AMOUNT is not NULL, on the return of TRUE, the logical left shift
1029 1.1 christos amount will be returned in *SHIFT_AMOUNT. */
1030 1.1 christos
1031 1.1 christos bfd_boolean
1032 1.1 christos aarch64_wide_constant_p (int64_t value, int is32, unsigned int *shift_amount)
1033 1.1 christos {
1034 1.1 christos int amount;
1035 1.1 christos
1036 1.1 christos DEBUG_TRACE ("enter with 0x%" PRIx64 "(%" PRIi64 ")", value, value);
1037 1.1 christos
1038 1.1 christos if (is32)
1039 1.1 christos {
1040 1.1 christos /* Allow all zeros or all ones in top 32-bits, so that
1041 1.1 christos 32-bit constant expressions like ~0x80000000 are
1042 1.1 christos permitted. */
1043 1.1 christos uint64_t ext = value;
1044 1.1 christos if (ext >> 32 != 0 && ext >> 32 != (uint64_t) 0xffffffff)
1045 1.1 christos /* Immediate out of range. */
1046 1.1 christos return FALSE;
1047 1.1 christos value &= (int64_t) 0xffffffff;
1048 1.1 christos }
1049 1.1 christos
1050 1.1 christos /* first, try movz then movn */
1051 1.1 christos amount = -1;
1052 1.1 christos if ((value & ((int64_t) 0xffff << 0)) == value)
1053 1.1 christos amount = 0;
1054 1.1 christos else if ((value & ((int64_t) 0xffff << 16)) == value)
1055 1.1 christos amount = 16;
1056 1.1 christos else if (!is32 && (value & ((int64_t) 0xffff << 32)) == value)
1057 1.1 christos amount = 32;
1058 1.1 christos else if (!is32 && (value & ((int64_t) 0xffff << 48)) == value)
1059 1.1 christos amount = 48;
1060 1.1 christos
1061 1.1 christos if (amount == -1)
1062 1.1 christos {
1063 1.1 christos DEBUG_TRACE ("exit FALSE with 0x%" PRIx64 "(%" PRIi64 ")", value, value);
1064 1.1 christos return FALSE;
1065 1.1 christos }
1066 1.1 christos
1067 1.1 christos if (shift_amount != NULL)
1068 1.1 christos *shift_amount = amount;
1069 1.1 christos
1070 1.1 christos DEBUG_TRACE ("exit TRUE with amount %d", amount);
1071 1.1 christos
1072 1.1 christos return TRUE;
1073 1.1 christos }
1074 1.1 christos
1075 1.1 christos /* Build the accepted values for immediate logical SIMD instructions.
1076 1.1 christos
1077 1.1 christos The standard encodings of the immediate value are:
1078 1.1 christos N imms immr SIMD size R S
1079 1.1 christos 1 ssssss rrrrrr 64 UInt(rrrrrr) UInt(ssssss)
1080 1.1 christos 0 0sssss 0rrrrr 32 UInt(rrrrr) UInt(sssss)
1081 1.1 christos 0 10ssss 00rrrr 16 UInt(rrrr) UInt(ssss)
1082 1.1 christos 0 110sss 000rrr 8 UInt(rrr) UInt(sss)
1083 1.1 christos 0 1110ss 0000rr 4 UInt(rr) UInt(ss)
1084 1.1 christos 0 11110s 00000r 2 UInt(r) UInt(s)
1085 1.1 christos where all-ones value of S is reserved.
1086 1.1 christos
1087 1.1 christos Let's call E the SIMD size.
1088 1.1 christos
1089 1.1 christos The immediate value is: S+1 bits '1' rotated to the right by R.
1090 1.1 christos
1091 1.1 christos The total of valid encodings is 64*63 + 32*31 + ... + 2*1 = 5334
1092 1.1 christos (remember S != E - 1). */
1093 1.1 christos
1094 1.1 christos #define TOTAL_IMM_NB 5334
1095 1.1 christos
1096 1.1 christos typedef struct
1097 1.1 christos {
1098 1.1 christos uint64_t imm;
1099 1.1 christos aarch64_insn encoding;
1100 1.1 christos } simd_imm_encoding;
1101 1.1 christos
1102 1.1 christos static simd_imm_encoding simd_immediates[TOTAL_IMM_NB];
1103 1.1 christos
1104 1.1 christos static int
1105 1.1 christos simd_imm_encoding_cmp(const void *i1, const void *i2)
1106 1.1 christos {
1107 1.1 christos const simd_imm_encoding *imm1 = (const simd_imm_encoding *)i1;
1108 1.1 christos const simd_imm_encoding *imm2 = (const simd_imm_encoding *)i2;
1109 1.1 christos
1110 1.1 christos if (imm1->imm < imm2->imm)
1111 1.1 christos return -1;
1112 1.1 christos if (imm1->imm > imm2->imm)
1113 1.1 christos return +1;
1114 1.1 christos return 0;
1115 1.1 christos }
1116 1.1 christos
1117 1.1 christos /* immediate bitfield standard encoding
1118 1.1 christos imm13<12> imm13<5:0> imm13<11:6> SIMD size R S
1119 1.1 christos 1 ssssss rrrrrr 64 rrrrrr ssssss
1120 1.1 christos 0 0sssss 0rrrrr 32 rrrrr sssss
1121 1.1 christos 0 10ssss 00rrrr 16 rrrr ssss
1122 1.1 christos 0 110sss 000rrr 8 rrr sss
1123 1.1 christos 0 1110ss 0000rr 4 rr ss
1124 1.1 christos 0 11110s 00000r 2 r s */
1125 1.1 christos static inline int
1126 1.1 christos encode_immediate_bitfield (int is64, uint32_t s, uint32_t r)
1127 1.1 christos {
1128 1.1 christos return (is64 << 12) | (r << 6) | s;
1129 1.1 christos }
1130 1.1 christos
1131 1.1 christos static void
1132 1.1 christos build_immediate_table (void)
1133 1.1 christos {
1134 1.1 christos uint32_t log_e, e, s, r, s_mask;
1135 1.1 christos uint64_t mask, imm;
1136 1.1 christos int nb_imms;
1137 1.1 christos int is64;
1138 1.1 christos
1139 1.1 christos nb_imms = 0;
1140 1.1 christos for (log_e = 1; log_e <= 6; log_e++)
1141 1.1 christos {
1142 1.1 christos /* Get element size. */
1143 1.1 christos e = 1u << log_e;
1144 1.1 christos if (log_e == 6)
1145 1.1 christos {
1146 1.1 christos is64 = 1;
1147 1.1 christos mask = 0xffffffffffffffffull;
1148 1.1 christos s_mask = 0;
1149 1.1 christos }
1150 1.1 christos else
1151 1.1 christos {
1152 1.1 christos is64 = 0;
1153 1.1 christos mask = (1ull << e) - 1;
1154 1.1 christos /* log_e s_mask
1155 1.1 christos 1 ((1 << 4) - 1) << 2 = 111100
1156 1.1 christos 2 ((1 << 3) - 1) << 3 = 111000
1157 1.1 christos 3 ((1 << 2) - 1) << 4 = 110000
1158 1.1 christos 4 ((1 << 1) - 1) << 5 = 100000
1159 1.1 christos 5 ((1 << 0) - 1) << 6 = 000000 */
1160 1.1 christos s_mask = ((1u << (5 - log_e)) - 1) << (log_e + 1);
1161 1.1 christos }
1162 1.1 christos for (s = 0; s < e - 1; s++)
1163 1.1 christos for (r = 0; r < e; r++)
1164 1.1 christos {
1165 1.1 christos /* s+1 consecutive bits to 1 (s < 63) */
1166 1.1 christos imm = (1ull << (s + 1)) - 1;
1167 1.1 christos /* rotate right by r */
1168 1.1 christos if (r != 0)
1169 1.1 christos imm = (imm >> r) | ((imm << (e - r)) & mask);
1170 1.1 christos /* replicate the constant depending on SIMD size */
1171 1.1 christos switch (log_e)
1172 1.5.2.1 martin {
1173 1.1 christos case 1: imm = (imm << 2) | imm;
1174 1.5.2.1 martin /* Fall through. */
1175 1.1 christos case 2: imm = (imm << 4) | imm;
1176 1.5.2.1 martin /* Fall through. */
1177 1.1 christos case 3: imm = (imm << 8) | imm;
1178 1.5.2.1 martin /* Fall through. */
1179 1.1 christos case 4: imm = (imm << 16) | imm;
1180 1.5.2.1 martin /* Fall through. */
1181 1.1 christos case 5: imm = (imm << 32) | imm;
1182 1.1 christos /* Fall through. */
1183 1.1 christos case 6: break;
1184 1.1 christos default: abort ();
1185 1.1 christos }
1186 1.1 christos simd_immediates[nb_imms].imm = imm;
1187 1.1 christos simd_immediates[nb_imms].encoding =
1188 1.1 christos encode_immediate_bitfield(is64, s | s_mask, r);
1189 1.1 christos nb_imms++;
1190 1.1 christos }
1191 1.1 christos }
1192 1.1 christos assert (nb_imms == TOTAL_IMM_NB);
1193 1.1 christos qsort(simd_immediates, nb_imms,
1194 1.1 christos sizeof(simd_immediates[0]), simd_imm_encoding_cmp);
1195 1.1 christos }
1196 1.1 christos
1197 1.1 christos /* Return TRUE if VALUE is a valid logical immediate, i.e. bitmask, that can
1198 1.1 christos be accepted by logical (immediate) instructions
1199 1.5.2.1 martin e.g. ORR <Xd|SP>, <Xn>, #<imm>.
1200 1.1 christos
1201 1.1 christos ESIZE is the number of bytes in the decoded immediate value.
1202 1.1 christos If ENCODING is not NULL, on the return of TRUE, the standard encoding for
1203 1.1 christos VALUE will be returned in *ENCODING. */
1204 1.5.2.1 martin
1205 1.1 christos bfd_boolean
1206 1.1 christos aarch64_logical_immediate_p (uint64_t value, int esize, aarch64_insn *encoding)
1207 1.1 christos {
1208 1.1 christos simd_imm_encoding imm_enc;
1209 1.5.2.1 martin const simd_imm_encoding *imm_encoding;
1210 1.5.2.1 martin static bfd_boolean initialized = FALSE;
1211 1.1 christos uint64_t upper;
1212 1.5.2.1 martin int i;
1213 1.5.2.1 martin
1214 1.1 christos DEBUG_TRACE ("enter with 0x%" PRIx64 "(%" PRIi64 "), esize: %d", value,
1215 1.5.2.1 martin value, esize);
1216 1.1 christos
1217 1.1 christos if (!initialized)
1218 1.1 christos {
1219 1.1 christos build_immediate_table ();
1220 1.1 christos initialized = TRUE;
1221 1.5.2.1 martin }
1222 1.5.2.1 martin
1223 1.5.2.1 martin /* Allow all zeros or all ones in top bits, so that
1224 1.5.2.1 martin constant expressions like ~1 are permitted. */
1225 1.5.2.1 martin upper = (uint64_t) -1 << (esize * 4) << (esize * 4);
1226 1.3 christos if ((value & ~upper) != value && (value | upper) != value)
1227 1.5.2.1 martin return FALSE;
1228 1.5.2.1 martin
1229 1.5.2.1 martin /* Replicate to a full 64-bit value. */
1230 1.5.2.1 martin value &= ~upper;
1231 1.1 christos for (i = esize * 8; i < 64; i *= 2)
1232 1.1 christos value |= (value << i);
1233 1.1 christos
1234 1.1 christos imm_enc.imm = value;
1235 1.1 christos imm_encoding = (const simd_imm_encoding *)
1236 1.1 christos bsearch(&imm_enc, simd_immediates, TOTAL_IMM_NB,
1237 1.1 christos sizeof(simd_immediates[0]), simd_imm_encoding_cmp);
1238 1.1 christos if (imm_encoding == NULL)
1239 1.1 christos {
1240 1.1 christos DEBUG_TRACE ("exit with FALSE");
1241 1.1 christos return FALSE;
1242 1.1 christos }
1243 1.1 christos if (encoding != NULL)
1244 1.1 christos *encoding = imm_encoding->encoding;
1245 1.1 christos DEBUG_TRACE ("exit with TRUE");
1246 1.1 christos return TRUE;
1247 1.1 christos }
1248 1.1 christos
1249 1.1 christos /* If 64-bit immediate IMM is in the format of
1250 1.1 christos "aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh",
1251 1.1 christos where a, b, c, d, e, f, g and h are independently 0 or 1, return an integer
1252 1.1 christos of value "abcdefgh". Otherwise return -1. */
1253 1.1 christos int
1254 1.1 christos aarch64_shrink_expanded_imm8 (uint64_t imm)
1255 1.1 christos {
1256 1.1 christos int i, ret;
1257 1.1 christos uint32_t byte;
1258 1.1 christos
1259 1.1 christos ret = 0;
1260 1.1 christos for (i = 0; i < 8; i++)
1261 1.1 christos {
1262 1.1 christos byte = (imm >> (8 * i)) & 0xff;
1263 1.1 christos if (byte == 0xff)
1264 1.1 christos ret |= 1 << i;
1265 1.1 christos else if (byte != 0x00)
1266 1.1 christos return -1;
1267 1.1 christos }
1268 1.1 christos return ret;
1269 1.1 christos }
1270 1.1 christos
1271 1.1 christos /* Utility inline functions for operand_general_constraint_met_p. */
1272 1.1 christos
1273 1.1 christos static inline void
1274 1.1 christos set_error (aarch64_operand_error *mismatch_detail,
1275 1.1 christos enum aarch64_operand_error_kind kind, int idx,
1276 1.1 christos const char* error)
1277 1.1 christos {
1278 1.1 christos if (mismatch_detail == NULL)
1279 1.1 christos return;
1280 1.1 christos mismatch_detail->kind = kind;
1281 1.1 christos mismatch_detail->index = idx;
1282 1.1 christos mismatch_detail->error = error;
1283 1.1 christos }
1284 1.3 christos
1285 1.3 christos static inline void
1286 1.3 christos set_syntax_error (aarch64_operand_error *mismatch_detail, int idx,
1287 1.3 christos const char* error)
1288 1.3 christos {
1289 1.3 christos if (mismatch_detail == NULL)
1290 1.3 christos return;
1291 1.3 christos set_error (mismatch_detail, AARCH64_OPDE_SYNTAX_ERROR, idx, error);
1292 1.3 christos }
1293 1.1 christos
1294 1.1 christos static inline void
1295 1.1 christos set_out_of_range_error (aarch64_operand_error *mismatch_detail,
1296 1.1 christos int idx, int lower_bound, int upper_bound,
1297 1.1 christos const char* error)
1298 1.1 christos {
1299 1.1 christos if (mismatch_detail == NULL)
1300 1.1 christos return;
1301 1.1 christos set_error (mismatch_detail, AARCH64_OPDE_OUT_OF_RANGE, idx, error);
1302 1.1 christos mismatch_detail->data[0] = lower_bound;
1303 1.1 christos mismatch_detail->data[1] = upper_bound;
1304 1.1 christos }
1305 1.1 christos
1306 1.1 christos static inline void
1307 1.1 christos set_imm_out_of_range_error (aarch64_operand_error *mismatch_detail,
1308 1.1 christos int idx, int lower_bound, int upper_bound)
1309 1.1 christos {
1310 1.1 christos if (mismatch_detail == NULL)
1311 1.1 christos return;
1312 1.1 christos set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
1313 1.1 christos _("immediate value"));
1314 1.1 christos }
1315 1.1 christos
1316 1.1 christos static inline void
1317 1.1 christos set_offset_out_of_range_error (aarch64_operand_error *mismatch_detail,
1318 1.1 christos int idx, int lower_bound, int upper_bound)
1319 1.1 christos {
1320 1.1 christos if (mismatch_detail == NULL)
1321 1.1 christos return;
1322 1.1 christos set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
1323 1.1 christos _("immediate offset"));
1324 1.1 christos }
1325 1.1 christos
1326 1.1 christos static inline void
1327 1.1 christos set_regno_out_of_range_error (aarch64_operand_error *mismatch_detail,
1328 1.1 christos int idx, int lower_bound, int upper_bound)
1329 1.1 christos {
1330 1.1 christos if (mismatch_detail == NULL)
1331 1.1 christos return;
1332 1.1 christos set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
1333 1.1 christos _("register number"));
1334 1.1 christos }
1335 1.1 christos
1336 1.1 christos static inline void
1337 1.1 christos set_elem_idx_out_of_range_error (aarch64_operand_error *mismatch_detail,
1338 1.1 christos int idx, int lower_bound, int upper_bound)
1339 1.1 christos {
1340 1.1 christos if (mismatch_detail == NULL)
1341 1.1 christos return;
1342 1.1 christos set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
1343 1.1 christos _("register element index"));
1344 1.1 christos }
1345 1.1 christos
1346 1.1 christos static inline void
1347 1.1 christos set_sft_amount_out_of_range_error (aarch64_operand_error *mismatch_detail,
1348 1.1 christos int idx, int lower_bound, int upper_bound)
1349 1.1 christos {
1350 1.1 christos if (mismatch_detail == NULL)
1351 1.1 christos return;
1352 1.1 christos set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
1353 1.1 christos _("shift amount"));
1354 1.5.2.1 martin }
1355 1.5.2.1 martin
1356 1.5.2.1 martin /* Report that the MUL modifier in operand IDX should be in the range
1357 1.5.2.1 martin [LOWER_BOUND, UPPER_BOUND]. */
1358 1.5.2.1 martin static inline void
1359 1.5.2.1 martin set_multiplier_out_of_range_error (aarch64_operand_error *mismatch_detail,
1360 1.5.2.1 martin int idx, int lower_bound, int upper_bound)
1361 1.5.2.1 martin {
1362 1.5.2.1 martin if (mismatch_detail == NULL)
1363 1.5.2.1 martin return;
1364 1.5.2.1 martin set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
1365 1.5.2.1 martin _("multiplier"));
1366 1.1 christos }
1367 1.1 christos
1368 1.1 christos static inline void
1369 1.1 christos set_unaligned_error (aarch64_operand_error *mismatch_detail, int idx,
1370 1.1 christos int alignment)
1371 1.1 christos {
1372 1.1 christos if (mismatch_detail == NULL)
1373 1.1 christos return;
1374 1.1 christos set_error (mismatch_detail, AARCH64_OPDE_UNALIGNED, idx, NULL);
1375 1.1 christos mismatch_detail->data[0] = alignment;
1376 1.1 christos }
1377 1.1 christos
1378 1.1 christos static inline void
1379 1.1 christos set_reg_list_error (aarch64_operand_error *mismatch_detail, int idx,
1380 1.1 christos int expected_num)
1381 1.1 christos {
1382 1.1 christos if (mismatch_detail == NULL)
1383 1.1 christos return;
1384 1.1 christos set_error (mismatch_detail, AARCH64_OPDE_REG_LIST, idx, NULL);
1385 1.1 christos mismatch_detail->data[0] = expected_num;
1386 1.1 christos }
1387 1.1 christos
1388 1.1 christos static inline void
1389 1.1 christos set_other_error (aarch64_operand_error *mismatch_detail, int idx,
1390 1.1 christos const char* error)
1391 1.1 christos {
1392 1.1 christos if (mismatch_detail == NULL)
1393 1.1 christos return;
1394 1.1 christos set_error (mismatch_detail, AARCH64_OPDE_OTHER_ERROR, idx, error);
1395 1.1 christos }
1396 1.1 christos
1397 1.1 christos /* General constraint checking based on operand code.
1398 1.1 christos
1399 1.1 christos Return 1 if OPNDS[IDX] meets the general constraint of operand code TYPE
1400 1.1 christos as the IDXth operand of opcode OPCODE. Otherwise return 0.
1401 1.1 christos
1402 1.1 christos This function has to be called after the qualifiers for all operands
1403 1.1 christos have been resolved.
1404 1.1 christos
1405 1.1 christos Mismatching error message is returned in *MISMATCH_DETAIL upon request,
1406 1.1 christos i.e. when MISMATCH_DETAIL is non-NULL. This avoids the generation
1407 1.1 christos of error message during the disassembling where error message is not
1408 1.1 christos wanted. We avoid the dynamic construction of strings of error messages
1409 1.1 christos here (i.e. in libopcodes), as it is costly and complicated; instead, we
1410 1.1 christos use a combination of error code, static string and some integer data to
1411 1.1 christos represent an error. */
1412 1.1 christos
1413 1.1 christos static int
1414 1.1 christos operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
1415 1.1 christos enum aarch64_opnd type,
1416 1.1 christos const aarch64_opcode *opcode,
1417 1.5.2.1 martin aarch64_operand_error *mismatch_detail)
1418 1.1 christos {
1419 1.5.2.1 martin unsigned num, modifiers, shift;
1420 1.5.2.1 martin unsigned char size;
1421 1.1 christos int64_t imm, min_value, max_value;
1422 1.1 christos uint64_t uvalue, mask;
1423 1.1 christos const aarch64_opnd_info *opnd = opnds + idx;
1424 1.1 christos aarch64_opnd_qualifier_t qualifier = opnd->qualifier;
1425 1.1 christos
1426 1.1 christos assert (opcode->operands[idx] == opnd->type && opnd->type == type);
1427 1.1 christos
1428 1.1 christos switch (aarch64_operands[type].op_class)
1429 1.3 christos {
1430 1.3 christos case AARCH64_OPND_CLASS_INT_REG:
1431 1.3 christos /* Check pair reg constraints for cas* instructions. */
1432 1.3 christos if (type == AARCH64_OPND_PAIRREG)
1433 1.3 christos {
1434 1.3 christos assert (idx == 1 || idx == 3);
1435 1.3 christos if (opnds[idx - 1].reg.regno % 2 != 0)
1436 1.3 christos {
1437 1.3 christos set_syntax_error (mismatch_detail, idx - 1,
1438 1.3 christos _("reg pair must start from even reg"));
1439 1.3 christos return 0;
1440 1.3 christos }
1441 1.3 christos if (opnds[idx].reg.regno != opnds[idx - 1].reg.regno + 1)
1442 1.3 christos {
1443 1.3 christos set_syntax_error (mismatch_detail, idx,
1444 1.3 christos _("reg pair must be contiguous"));
1445 1.3 christos return 0;
1446 1.3 christos }
1447 1.3 christos break;
1448 1.1 christos }
1449 1.1 christos
1450 1.1 christos /* <Xt> may be optional in some IC and TLBI instructions. */
1451 1.1 christos if (type == AARCH64_OPND_Rt_SYS)
1452 1.1 christos {
1453 1.3 christos assert (idx == 1 && (aarch64_get_operand_class (opnds[0].type)
1454 1.3 christos == AARCH64_OPND_CLASS_SYSTEM));
1455 1.1 christos if (opnds[1].present
1456 1.1 christos && !aarch64_sys_ins_reg_has_xt (opnds[0].sysins_op))
1457 1.1 christos {
1458 1.1 christos set_other_error (mismatch_detail, idx, _("extraneous register"));
1459 1.3 christos return 0;
1460 1.3 christos }
1461 1.1 christos if (!opnds[1].present
1462 1.1 christos && aarch64_sys_ins_reg_has_xt (opnds[0].sysins_op))
1463 1.1 christos {
1464 1.1 christos set_other_error (mismatch_detail, idx, _("missing register"));
1465 1.1 christos return 0;
1466 1.1 christos }
1467 1.1 christos }
1468 1.1 christos switch (qualifier)
1469 1.1 christos {
1470 1.1 christos case AARCH64_OPND_QLF_WSP:
1471 1.1 christos case AARCH64_OPND_QLF_SP:
1472 1.1 christos if (!aarch64_stack_pointer_p (opnd))
1473 1.1 christos {
1474 1.1 christos set_other_error (mismatch_detail, idx,
1475 1.1 christos _("stack pointer register expected"));
1476 1.1 christos return 0;
1477 1.1 christos }
1478 1.1 christos break;
1479 1.1 christos default:
1480 1.1 christos break;
1481 1.1 christos }
1482 1.5.2.1 martin break;
1483 1.5.2.1 martin
1484 1.5.2.1 martin case AARCH64_OPND_CLASS_SVE_REG:
1485 1.5.2.1 martin switch (type)
1486 1.5.2.1 martin {
1487 1.5.2.1 martin case AARCH64_OPND_SVE_Zm3_INDEX:
1488 1.5.2.1 martin case AARCH64_OPND_SVE_Zm3_22_INDEX:
1489 1.5.2.1 martin case AARCH64_OPND_SVE_Zm4_INDEX:
1490 1.5.2.1 martin size = get_operand_fields_width (get_operand_from_code (type));
1491 1.5.2.1 martin shift = get_operand_specific_data (&aarch64_operands[type]);
1492 1.5.2.1 martin mask = (1 << shift) - 1;
1493 1.5.2.1 martin if (opnd->reg.regno > mask)
1494 1.5.2.1 martin {
1495 1.5.2.1 martin assert (mask == 7 || mask == 15);
1496 1.5.2.1 martin set_other_error (mismatch_detail, idx,
1497 1.5.2.1 martin mask == 15
1498 1.5.2.1 martin ? _("z0-z15 expected")
1499 1.5.2.1 martin : _("z0-z7 expected"));
1500 1.5.2.1 martin return 0;
1501 1.5.2.1 martin }
1502 1.5.2.1 martin mask = (1 << (size - shift)) - 1;
1503 1.5.2.1 martin if (!value_in_range_p (opnd->reglane.index, 0, mask))
1504 1.5.2.1 martin {
1505 1.5.2.1 martin set_elem_idx_out_of_range_error (mismatch_detail, idx, 0, mask);
1506 1.5.2.1 martin return 0;
1507 1.5.2.1 martin }
1508 1.5.2.1 martin break;
1509 1.5.2.1 martin
1510 1.5.2.1 martin case AARCH64_OPND_SVE_Zn_INDEX:
1511 1.5.2.1 martin size = aarch64_get_qualifier_esize (opnd->qualifier);
1512 1.5.2.1 martin if (!value_in_range_p (opnd->reglane.index, 0, 64 / size - 1))
1513 1.5.2.1 martin {
1514 1.5.2.1 martin set_elem_idx_out_of_range_error (mismatch_detail, idx,
1515 1.5.2.1 martin 0, 64 / size - 1);
1516 1.5.2.1 martin return 0;
1517 1.5.2.1 martin }
1518 1.5.2.1 martin break;
1519 1.5.2.1 martin
1520 1.5.2.1 martin case AARCH64_OPND_SVE_ZnxN:
1521 1.5.2.1 martin case AARCH64_OPND_SVE_ZtxN:
1522 1.5.2.1 martin if (opnd->reglist.num_regs != get_opcode_dependent_value (opcode))
1523 1.5.2.1 martin {
1524 1.5.2.1 martin set_other_error (mismatch_detail, idx,
1525 1.5.2.1 martin _("invalid register list"));
1526 1.5.2.1 martin return 0;
1527 1.5.2.1 martin }
1528 1.5.2.1 martin break;
1529 1.5.2.1 martin
1530 1.5.2.1 martin default:
1531 1.5.2.1 martin break;
1532 1.5.2.1 martin }
1533 1.5.2.1 martin break;
1534 1.5.2.1 martin
1535 1.5.2.1 martin case AARCH64_OPND_CLASS_PRED_REG:
1536 1.5.2.1 martin if (opnd->reg.regno >= 8
1537 1.5.2.1 martin && get_operand_fields_width (get_operand_from_code (type)) == 3)
1538 1.5.2.1 martin {
1539 1.5.2.1 martin set_other_error (mismatch_detail, idx, _("p0-p7 expected"));
1540 1.5.2.1 martin return 0;
1541 1.5.2.1 martin }
1542 1.3 christos break;
1543 1.3 christos
1544 1.3 christos case AARCH64_OPND_CLASS_COND:
1545 1.3 christos if (type == AARCH64_OPND_COND1
1546 1.3 christos && (opnds[idx].cond->value & 0xe) == 0xe)
1547 1.3 christos {
1548 1.3 christos /* Not allow AL or NV. */
1549 1.3 christos set_syntax_error (mismatch_detail, idx, NULL);
1550 1.3 christos }
1551 1.1 christos break;
1552 1.1 christos
1553 1.1 christos case AARCH64_OPND_CLASS_ADDRESS:
1554 1.1 christos /* Check writeback. */
1555 1.1 christos switch (opcode->iclass)
1556 1.1 christos {
1557 1.1 christos case ldst_pos:
1558 1.1 christos case ldst_unscaled:
1559 1.1 christos case ldstnapair_offs:
1560 1.1 christos case ldstpair_off:
1561 1.1 christos case ldst_unpriv:
1562 1.3 christos if (opnd->addr.writeback == 1)
1563 1.3 christos {
1564 1.1 christos set_syntax_error (mismatch_detail, idx,
1565 1.1 christos _("unexpected address writeback"));
1566 1.1 christos return 0;
1567 1.5.2.1 martin }
1568 1.5.2.1 martin break;
1569 1.5.2.1 martin case ldst_imm10:
1570 1.5.2.1 martin if (opnd->addr.writeback == 1 && opnd->addr.preind != 1)
1571 1.5.2.1 martin {
1572 1.5.2.1 martin set_syntax_error (mismatch_detail, idx,
1573 1.5.2.1 martin _("unexpected address writeback"));
1574 1.5.2.1 martin return 0;
1575 1.1 christos }
1576 1.1 christos break;
1577 1.1 christos case ldst_imm9:
1578 1.1 christos case ldstpair_indexed:
1579 1.1 christos case asisdlsep:
1580 1.1 christos case asisdlsop:
1581 1.3 christos if (opnd->addr.writeback == 0)
1582 1.3 christos {
1583 1.1 christos set_syntax_error (mismatch_detail, idx,
1584 1.1 christos _("address writeback expected"));
1585 1.1 christos return 0;
1586 1.1 christos }
1587 1.1 christos break;
1588 1.1 christos default:
1589 1.1 christos assert (opnd->addr.writeback == 0);
1590 1.1 christos break;
1591 1.1 christos }
1592 1.1 christos switch (type)
1593 1.1 christos {
1594 1.1 christos case AARCH64_OPND_ADDR_SIMM7:
1595 1.1 christos /* Scaled signed 7 bits immediate offset. */
1596 1.1 christos /* Get the size of the data element that is accessed, which may be
1597 1.1 christos different from that of the source register size,
1598 1.1 christos e.g. in strb/ldrb. */
1599 1.1 christos size = aarch64_get_qualifier_esize (opnd->qualifier);
1600 1.1 christos if (!value_in_range_p (opnd->addr.offset.imm, -64 * size, 63 * size))
1601 1.1 christos {
1602 1.1 christos set_offset_out_of_range_error (mismatch_detail, idx,
1603 1.1 christos -64 * size, 63 * size);
1604 1.1 christos return 0;
1605 1.1 christos }
1606 1.1 christos if (!value_aligned_p (opnd->addr.offset.imm, size))
1607 1.1 christos {
1608 1.1 christos set_unaligned_error (mismatch_detail, idx, size);
1609 1.1 christos return 0;
1610 1.5.2.1 martin }
1611 1.1 christos break;
1612 1.1 christos case AARCH64_OPND_ADDR_OFFSET:
1613 1.1 christos case AARCH64_OPND_ADDR_SIMM9:
1614 1.1 christos /* Unscaled signed 9 bits immediate offset. */
1615 1.1 christos if (!value_in_range_p (opnd->addr.offset.imm, -256, 255))
1616 1.1 christos {
1617 1.1 christos set_offset_out_of_range_error (mismatch_detail, idx, -256, 255);
1618 1.1 christos return 0;
1619 1.1 christos }
1620 1.1 christos break;
1621 1.1 christos
1622 1.1 christos case AARCH64_OPND_ADDR_SIMM9_2:
1623 1.1 christos /* Unscaled signed 9 bits immediate offset, which has to be negative
1624 1.1 christos or unaligned. */
1625 1.1 christos size = aarch64_get_qualifier_esize (qualifier);
1626 1.1 christos if ((value_in_range_p (opnd->addr.offset.imm, 0, 255)
1627 1.1 christos && !value_aligned_p (opnd->addr.offset.imm, size))
1628 1.1 christos || value_in_range_p (opnd->addr.offset.imm, -256, -1))
1629 1.1 christos return 1;
1630 1.1 christos set_other_error (mismatch_detail, idx,
1631 1.1 christos _("negative or unaligned offset expected"));
1632 1.5.2.1 martin return 0;
1633 1.5.2.1 martin
1634 1.5.2.1 martin case AARCH64_OPND_ADDR_SIMM10:
1635 1.5.2.1 martin /* Scaled signed 10 bits immediate offset. */
1636 1.5.2.1 martin if (!value_in_range_p (opnd->addr.offset.imm, -4096, 4088))
1637 1.5.2.1 martin {
1638 1.5.2.1 martin set_offset_out_of_range_error (mismatch_detail, idx, -4096, 4088);
1639 1.5.2.1 martin return 0;
1640 1.5.2.1 martin }
1641 1.5.2.1 martin if (!value_aligned_p (opnd->addr.offset.imm, 8))
1642 1.5.2.1 martin {
1643 1.5.2.1 martin set_unaligned_error (mismatch_detail, idx, 8);
1644 1.5.2.1 martin return 0;
1645 1.5.2.1 martin }
1646 1.1 christos break;
1647 1.1 christos
1648 1.1 christos case AARCH64_OPND_SIMD_ADDR_POST:
1649 1.1 christos /* AdvSIMD load/store multiple structures, post-index. */
1650 1.1 christos assert (idx == 1);
1651 1.1 christos if (opnd->addr.offset.is_reg)
1652 1.1 christos {
1653 1.1 christos if (value_in_range_p (opnd->addr.offset.regno, 0, 30))
1654 1.1 christos return 1;
1655 1.1 christos else
1656 1.1 christos {
1657 1.1 christos set_other_error (mismatch_detail, idx,
1658 1.1 christos _("invalid register offset"));
1659 1.1 christos return 0;
1660 1.1 christos }
1661 1.1 christos }
1662 1.1 christos else
1663 1.1 christos {
1664 1.1 christos const aarch64_opnd_info *prev = &opnds[idx-1];
1665 1.1 christos unsigned num_bytes; /* total number of bytes transferred. */
1666 1.1 christos /* The opcode dependent area stores the number of elements in
1667 1.1 christos each structure to be loaded/stored. */
1668 1.1 christos int is_ld1r = get_opcode_dependent_value (opcode) == 1;
1669 1.1 christos if (opcode->operands[0] == AARCH64_OPND_LVt_AL)
1670 1.1 christos /* Special handling of loading single structure to all lane. */
1671 1.1 christos num_bytes = (is_ld1r ? 1 : prev->reglist.num_regs)
1672 1.1 christos * aarch64_get_qualifier_esize (prev->qualifier);
1673 1.1 christos else
1674 1.1 christos num_bytes = prev->reglist.num_regs
1675 1.1 christos * aarch64_get_qualifier_esize (prev->qualifier)
1676 1.1 christos * aarch64_get_qualifier_nelem (prev->qualifier);
1677 1.1 christos if ((int) num_bytes != opnd->addr.offset.imm)
1678 1.1 christos {
1679 1.1 christos set_other_error (mismatch_detail, idx,
1680 1.1 christos _("invalid post-increment amount"));
1681 1.1 christos return 0;
1682 1.1 christos }
1683 1.1 christos }
1684 1.1 christos break;
1685 1.1 christos
1686 1.1 christos case AARCH64_OPND_ADDR_REGOFF:
1687 1.1 christos /* Get the size of the data element that is accessed, which may be
1688 1.1 christos different from that of the source register size,
1689 1.1 christos e.g. in strb/ldrb. */
1690 1.1 christos size = aarch64_get_qualifier_esize (opnd->qualifier);
1691 1.1 christos /* It is either no shift or shift by the binary logarithm of SIZE. */
1692 1.1 christos if (opnd->shifter.amount != 0
1693 1.1 christos && opnd->shifter.amount != (int)get_logsz (size))
1694 1.1 christos {
1695 1.1 christos set_other_error (mismatch_detail, idx,
1696 1.1 christos _("invalid shift amount"));
1697 1.1 christos return 0;
1698 1.1 christos }
1699 1.1 christos /* Only UXTW, LSL, SXTW and SXTX are the accepted extending
1700 1.1 christos operators. */
1701 1.1 christos switch (opnd->shifter.kind)
1702 1.1 christos {
1703 1.1 christos case AARCH64_MOD_UXTW:
1704 1.1 christos case AARCH64_MOD_LSL:
1705 1.1 christos case AARCH64_MOD_SXTW:
1706 1.1 christos case AARCH64_MOD_SXTX: break;
1707 1.1 christos default:
1708 1.1 christos set_other_error (mismatch_detail, idx,
1709 1.1 christos _("invalid extend/shift operator"));
1710 1.1 christos return 0;
1711 1.1 christos }
1712 1.1 christos break;
1713 1.1 christos
1714 1.1 christos case AARCH64_OPND_ADDR_UIMM12:
1715 1.1 christos imm = opnd->addr.offset.imm;
1716 1.1 christos /* Get the size of the data element that is accessed, which may be
1717 1.1 christos different from that of the source register size,
1718 1.1 christos e.g. in strb/ldrb. */
1719 1.1 christos size = aarch64_get_qualifier_esize (qualifier);
1720 1.1 christos if (!value_in_range_p (opnd->addr.offset.imm, 0, 4095 * size))
1721 1.1 christos {
1722 1.1 christos set_offset_out_of_range_error (mismatch_detail, idx,
1723 1.1 christos 0, 4095 * size);
1724 1.1 christos return 0;
1725 1.1 christos }
1726 1.1 christos if (!value_aligned_p (opnd->addr.offset.imm, size))
1727 1.1 christos {
1728 1.1 christos set_unaligned_error (mismatch_detail, idx, size);
1729 1.1 christos return 0;
1730 1.1 christos }
1731 1.1 christos break;
1732 1.1 christos
1733 1.1 christos case AARCH64_OPND_ADDR_PCREL14:
1734 1.1 christos case AARCH64_OPND_ADDR_PCREL19:
1735 1.1 christos case AARCH64_OPND_ADDR_PCREL21:
1736 1.1 christos case AARCH64_OPND_ADDR_PCREL26:
1737 1.1 christos imm = opnd->imm.value;
1738 1.1 christos if (operand_need_shift_by_two (get_operand_from_code (type)))
1739 1.1 christos {
1740 1.1 christos /* The offset value in a PC-relative branch instruction is alway
1741 1.1 christos 4-byte aligned and is encoded without the lowest 2 bits. */
1742 1.1 christos if (!value_aligned_p (imm, 4))
1743 1.1 christos {
1744 1.1 christos set_unaligned_error (mismatch_detail, idx, 4);
1745 1.1 christos return 0;
1746 1.1 christos }
1747 1.1 christos /* Right shift by 2 so that we can carry out the following check
1748 1.1 christos canonically. */
1749 1.1 christos imm >>= 2;
1750 1.1 christos }
1751 1.1 christos size = get_operand_fields_width (get_operand_from_code (type));
1752 1.1 christos if (!value_fit_signed_field_p (imm, size))
1753 1.1 christos {
1754 1.1 christos set_other_error (mismatch_detail, idx,
1755 1.1 christos _("immediate out of range"));
1756 1.1 christos return 0;
1757 1.1 christos }
1758 1.5.2.1 martin break;
1759 1.5.2.1 martin
1760 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_S4xVL:
1761 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_S4x2xVL:
1762 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_S4x3xVL:
1763 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_S4x4xVL:
1764 1.5.2.1 martin min_value = -8;
1765 1.5.2.1 martin max_value = 7;
1766 1.5.2.1 martin sve_imm_offset_vl:
1767 1.5.2.1 martin assert (!opnd->addr.offset.is_reg);
1768 1.5.2.1 martin assert (opnd->addr.preind);
1769 1.5.2.1 martin num = 1 + get_operand_specific_data (&aarch64_operands[type]);
1770 1.5.2.1 martin min_value *= num;
1771 1.5.2.1 martin max_value *= num;
1772 1.5.2.1 martin if ((opnd->addr.offset.imm != 0 && !opnd->shifter.operator_present)
1773 1.5.2.1 martin || (opnd->shifter.operator_present
1774 1.5.2.1 martin && opnd->shifter.kind != AARCH64_MOD_MUL_VL))
1775 1.5.2.1 martin {
1776 1.5.2.1 martin set_other_error (mismatch_detail, idx,
1777 1.5.2.1 martin _("invalid addressing mode"));
1778 1.5.2.1 martin return 0;
1779 1.5.2.1 martin }
1780 1.5.2.1 martin if (!value_in_range_p (opnd->addr.offset.imm, min_value, max_value))
1781 1.5.2.1 martin {
1782 1.5.2.1 martin set_offset_out_of_range_error (mismatch_detail, idx,
1783 1.5.2.1 martin min_value, max_value);
1784 1.5.2.1 martin return 0;
1785 1.5.2.1 martin }
1786 1.5.2.1 martin if (!value_aligned_p (opnd->addr.offset.imm, num))
1787 1.5.2.1 martin {
1788 1.5.2.1 martin set_unaligned_error (mismatch_detail, idx, num);
1789 1.5.2.1 martin return 0;
1790 1.5.2.1 martin }
1791 1.5.2.1 martin break;
1792 1.5.2.1 martin
1793 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_S6xVL:
1794 1.5.2.1 martin min_value = -32;
1795 1.5.2.1 martin max_value = 31;
1796 1.5.2.1 martin goto sve_imm_offset_vl;
1797 1.5.2.1 martin
1798 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_S9xVL:
1799 1.5.2.1 martin min_value = -256;
1800 1.5.2.1 martin max_value = 255;
1801 1.5.2.1 martin goto sve_imm_offset_vl;
1802 1.5.2.1 martin
1803 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_U6:
1804 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_U6x2:
1805 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_U6x4:
1806 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_U6x8:
1807 1.5.2.1 martin min_value = 0;
1808 1.5.2.1 martin max_value = 63;
1809 1.5.2.1 martin sve_imm_offset:
1810 1.5.2.1 martin assert (!opnd->addr.offset.is_reg);
1811 1.5.2.1 martin assert (opnd->addr.preind);
1812 1.5.2.1 martin num = 1 << get_operand_specific_data (&aarch64_operands[type]);
1813 1.5.2.1 martin min_value *= num;
1814 1.5.2.1 martin max_value *= num;
1815 1.5.2.1 martin if (opnd->shifter.operator_present
1816 1.5.2.1 martin || opnd->shifter.amount_present)
1817 1.5.2.1 martin {
1818 1.5.2.1 martin set_other_error (mismatch_detail, idx,
1819 1.5.2.1 martin _("invalid addressing mode"));
1820 1.5.2.1 martin return 0;
1821 1.5.2.1 martin }
1822 1.5.2.1 martin if (!value_in_range_p (opnd->addr.offset.imm, min_value, max_value))
1823 1.5.2.1 martin {
1824 1.5.2.1 martin set_offset_out_of_range_error (mismatch_detail, idx,
1825 1.5.2.1 martin min_value, max_value);
1826 1.5.2.1 martin return 0;
1827 1.5.2.1 martin }
1828 1.5.2.1 martin if (!value_aligned_p (opnd->addr.offset.imm, num))
1829 1.5.2.1 martin {
1830 1.5.2.1 martin set_unaligned_error (mismatch_detail, idx, num);
1831 1.5.2.1 martin return 0;
1832 1.5.2.1 martin }
1833 1.5.2.1 martin break;
1834 1.5.2.1 martin
1835 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_S4x16:
1836 1.5.2.1 martin min_value = -8;
1837 1.5.2.1 martin max_value = 7;
1838 1.5.2.1 martin goto sve_imm_offset;
1839 1.5.2.1 martin
1840 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_R:
1841 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RR:
1842 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RR_LSL1:
1843 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RR_LSL2:
1844 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RR_LSL3:
1845 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RX:
1846 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RX_LSL1:
1847 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RX_LSL2:
1848 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RX_LSL3:
1849 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ:
1850 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_LSL1:
1851 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_LSL2:
1852 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_LSL3:
1853 1.5.2.1 martin modifiers = 1 << AARCH64_MOD_LSL;
1854 1.5.2.1 martin sve_rr_operand:
1855 1.5.2.1 martin assert (opnd->addr.offset.is_reg);
1856 1.5.2.1 martin assert (opnd->addr.preind);
1857 1.5.2.1 martin if ((aarch64_operands[type].flags & OPD_F_NO_ZR) != 0
1858 1.5.2.1 martin && opnd->addr.offset.regno == 31)
1859 1.5.2.1 martin {
1860 1.5.2.1 martin set_other_error (mismatch_detail, idx,
1861 1.5.2.1 martin _("index register xzr is not allowed"));
1862 1.5.2.1 martin return 0;
1863 1.5.2.1 martin }
1864 1.5.2.1 martin if (((1 << opnd->shifter.kind) & modifiers) == 0
1865 1.5.2.1 martin || (opnd->shifter.amount
1866 1.5.2.1 martin != get_operand_specific_data (&aarch64_operands[type])))
1867 1.5.2.1 martin {
1868 1.5.2.1 martin set_other_error (mismatch_detail, idx,
1869 1.5.2.1 martin _("invalid addressing mode"));
1870 1.5.2.1 martin return 0;
1871 1.5.2.1 martin }
1872 1.5.2.1 martin break;
1873 1.5.2.1 martin
1874 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_XTW_14:
1875 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_XTW_22:
1876 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_XTW1_14:
1877 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_XTW1_22:
1878 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_XTW2_14:
1879 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_XTW2_22:
1880 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_XTW3_14:
1881 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_XTW3_22:
1882 1.5.2.1 martin modifiers = (1 << AARCH64_MOD_SXTW) | (1 << AARCH64_MOD_UXTW);
1883 1.5.2.1 martin goto sve_rr_operand;
1884 1.5.2.1 martin
1885 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_ZI_U5:
1886 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_ZI_U5x2:
1887 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_ZI_U5x4:
1888 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_ZI_U5x8:
1889 1.5.2.1 martin min_value = 0;
1890 1.5.2.1 martin max_value = 31;
1891 1.5.2.1 martin goto sve_imm_offset;
1892 1.5.2.1 martin
1893 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_ZZ_LSL:
1894 1.5.2.1 martin modifiers = 1 << AARCH64_MOD_LSL;
1895 1.5.2.1 martin sve_zz_operand:
1896 1.5.2.1 martin assert (opnd->addr.offset.is_reg);
1897 1.5.2.1 martin assert (opnd->addr.preind);
1898 1.5.2.1 martin if (((1 << opnd->shifter.kind) & modifiers) == 0
1899 1.5.2.1 martin || opnd->shifter.amount < 0
1900 1.5.2.1 martin || opnd->shifter.amount > 3)
1901 1.5.2.1 martin {
1902 1.5.2.1 martin set_other_error (mismatch_detail, idx,
1903 1.5.2.1 martin _("invalid addressing mode"));
1904 1.5.2.1 martin return 0;
1905 1.5.2.1 martin }
1906 1.5.2.1 martin break;
1907 1.5.2.1 martin
1908 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_ZZ_SXTW:
1909 1.5.2.1 martin modifiers = (1 << AARCH64_MOD_SXTW);
1910 1.5.2.1 martin goto sve_zz_operand;
1911 1.5.2.1 martin
1912 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_ZZ_UXTW:
1913 1.5.2.1 martin modifiers = 1 << AARCH64_MOD_UXTW;
1914 1.1 christos goto sve_zz_operand;
1915 1.1 christos
1916 1.1 christos default:
1917 1.1 christos break;
1918 1.1 christos }
1919 1.1 christos break;
1920 1.5 christos
1921 1.5 christos case AARCH64_OPND_CLASS_SIMD_REGLIST:
1922 1.5 christos if (type == AARCH64_OPND_LEt)
1923 1.5 christos {
1924 1.5 christos /* Get the upper bound for the element index. */
1925 1.5 christos num = 16 / aarch64_get_qualifier_esize (qualifier) - 1;
1926 1.5 christos if (!value_in_range_p (opnd->reglist.index, 0, num))
1927 1.5 christos {
1928 1.5 christos set_elem_idx_out_of_range_error (mismatch_detail, idx, 0, num);
1929 1.5 christos return 0;
1930 1.1 christos }
1931 1.1 christos }
1932 1.1 christos /* The opcode dependent area stores the number of elements in
1933 1.1 christos each structure to be loaded/stored. */
1934 1.1 christos num = get_opcode_dependent_value (opcode);
1935 1.1 christos switch (type)
1936 1.1 christos {
1937 1.1 christos case AARCH64_OPND_LVt:
1938 1.1 christos assert (num >= 1 && num <= 4);
1939 1.1 christos /* Unless LD1/ST1, the number of registers should be equal to that
1940 1.1 christos of the structure elements. */
1941 1.1 christos if (num != 1 && opnd->reglist.num_regs != num)
1942 1.1 christos {
1943 1.1 christos set_reg_list_error (mismatch_detail, idx, num);
1944 1.1 christos return 0;
1945 1.1 christos }
1946 1.1 christos break;
1947 1.1 christos case AARCH64_OPND_LVt_AL:
1948 1.1 christos case AARCH64_OPND_LEt:
1949 1.1 christos assert (num >= 1 && num <= 4);
1950 1.1 christos /* The number of registers should be equal to that of the structure
1951 1.1 christos elements. */
1952 1.1 christos if (opnd->reglist.num_regs != num)
1953 1.1 christos {
1954 1.1 christos set_reg_list_error (mismatch_detail, idx, num);
1955 1.1 christos return 0;
1956 1.1 christos }
1957 1.1 christos break;
1958 1.1 christos default:
1959 1.1 christos break;
1960 1.1 christos }
1961 1.1 christos break;
1962 1.1 christos
1963 1.1 christos case AARCH64_OPND_CLASS_IMMEDIATE:
1964 1.1 christos /* Constraint check on immediate operand. */
1965 1.1 christos imm = opnd->imm.value;
1966 1.1 christos /* E.g. imm_0_31 constrains value to be 0..31. */
1967 1.1 christos if (qualifier_value_in_range_constraint_p (qualifier)
1968 1.1 christos && !value_in_range_p (imm, get_lower_bound (qualifier),
1969 1.1 christos get_upper_bound (qualifier)))
1970 1.1 christos {
1971 1.1 christos set_imm_out_of_range_error (mismatch_detail, idx,
1972 1.1 christos get_lower_bound (qualifier),
1973 1.1 christos get_upper_bound (qualifier));
1974 1.1 christos return 0;
1975 1.1 christos }
1976 1.1 christos
1977 1.1 christos switch (type)
1978 1.1 christos {
1979 1.1 christos case AARCH64_OPND_AIMM:
1980 1.1 christos if (opnd->shifter.kind != AARCH64_MOD_LSL)
1981 1.1 christos {
1982 1.1 christos set_other_error (mismatch_detail, idx,
1983 1.1 christos _("invalid shift operator"));
1984 1.1 christos return 0;
1985 1.1 christos }
1986 1.1 christos if (opnd->shifter.amount != 0 && opnd->shifter.amount != 12)
1987 1.5.2.1 martin {
1988 1.1 christos set_other_error (mismatch_detail, idx,
1989 1.1 christos _("shift amount must be 0 or 12"));
1990 1.1 christos return 0;
1991 1.1 christos }
1992 1.1 christos if (!value_fit_unsigned_field_p (opnd->imm.value, 12))
1993 1.1 christos {
1994 1.1 christos set_other_error (mismatch_detail, idx,
1995 1.1 christos _("immediate out of range"));
1996 1.1 christos return 0;
1997 1.1 christos }
1998 1.1 christos break;
1999 1.1 christos
2000 1.1 christos case AARCH64_OPND_HALF:
2001 1.1 christos assert (idx == 1 && opnds[0].type == AARCH64_OPND_Rd);
2002 1.1 christos if (opnd->shifter.kind != AARCH64_MOD_LSL)
2003 1.1 christos {
2004 1.1 christos set_other_error (mismatch_detail, idx,
2005 1.1 christos _("invalid shift operator"));
2006 1.1 christos return 0;
2007 1.1 christos }
2008 1.1 christos size = aarch64_get_qualifier_esize (opnds[0].qualifier);
2009 1.1 christos if (!value_aligned_p (opnd->shifter.amount, 16))
2010 1.5.2.1 martin {
2011 1.1 christos set_other_error (mismatch_detail, idx,
2012 1.1 christos _("shift amount must be a multiple of 16"));
2013 1.1 christos return 0;
2014 1.1 christos }
2015 1.1 christos if (!value_in_range_p (opnd->shifter.amount, 0, size * 8 - 16))
2016 1.1 christos {
2017 1.1 christos set_sft_amount_out_of_range_error (mismatch_detail, idx,
2018 1.1 christos 0, size * 8 - 16);
2019 1.1 christos return 0;
2020 1.1 christos }
2021 1.1 christos if (opnd->imm.value < 0)
2022 1.1 christos {
2023 1.1 christos set_other_error (mismatch_detail, idx,
2024 1.1 christos _("negative immediate value not allowed"));
2025 1.1 christos return 0;
2026 1.1 christos }
2027 1.1 christos if (!value_fit_unsigned_field_p (opnd->imm.value, 16))
2028 1.1 christos {
2029 1.1 christos set_other_error (mismatch_detail, idx,
2030 1.1 christos _("immediate out of range"));
2031 1.1 christos return 0;
2032 1.1 christos }
2033 1.1 christos break;
2034 1.1 christos
2035 1.5.2.1 martin case AARCH64_OPND_IMM_MOV:
2036 1.1 christos {
2037 1.1 christos int esize = aarch64_get_qualifier_esize (opnds[0].qualifier);
2038 1.1 christos imm = opnd->imm.value;
2039 1.1 christos assert (idx == 1);
2040 1.1 christos switch (opcode->op)
2041 1.1 christos {
2042 1.5.2.1 martin case OP_MOV_IMM_WIDEN:
2043 1.1 christos imm = ~imm;
2044 1.5.2.1 martin /* Fall through. */
2045 1.1 christos case OP_MOV_IMM_WIDE:
2046 1.1 christos if (!aarch64_wide_constant_p (imm, esize == 4, NULL))
2047 1.1 christos {
2048 1.1 christos set_other_error (mismatch_detail, idx,
2049 1.1 christos _("immediate out of range"));
2050 1.1 christos return 0;
2051 1.1 christos }
2052 1.5.2.1 martin break;
2053 1.1 christos case OP_MOV_IMM_LOG:
2054 1.1 christos if (!aarch64_logical_immediate_p (imm, esize, NULL))
2055 1.1 christos {
2056 1.1 christos set_other_error (mismatch_detail, idx,
2057 1.1 christos _("immediate out of range"));
2058 1.1 christos return 0;
2059 1.1 christos }
2060 1.1 christos break;
2061 1.1 christos default:
2062 1.1 christos assert (0);
2063 1.1 christos return 0;
2064 1.1 christos }
2065 1.1 christos }
2066 1.1 christos break;
2067 1.1 christos
2068 1.1 christos case AARCH64_OPND_NZCV:
2069 1.1 christos case AARCH64_OPND_CCMP_IMM:
2070 1.1 christos case AARCH64_OPND_EXCEPTION:
2071 1.1 christos case AARCH64_OPND_UIMM4:
2072 1.1 christos case AARCH64_OPND_UIMM7:
2073 1.5.2.1 martin case AARCH64_OPND_UIMM3_OP1:
2074 1.5.2.1 martin case AARCH64_OPND_UIMM3_OP2:
2075 1.5.2.1 martin case AARCH64_OPND_SVE_UIMM3:
2076 1.5.2.1 martin case AARCH64_OPND_SVE_UIMM7:
2077 1.1 christos case AARCH64_OPND_SVE_UIMM8:
2078 1.1 christos case AARCH64_OPND_SVE_UIMM8_53:
2079 1.1 christos size = get_operand_fields_width (get_operand_from_code (type));
2080 1.1 christos assert (size < 32);
2081 1.1 christos if (!value_fit_unsigned_field_p (opnd->imm.value, size))
2082 1.1 christos {
2083 1.1 christos set_imm_out_of_range_error (mismatch_detail, idx, 0,
2084 1.1 christos (1 << size) - 1);
2085 1.1 christos return 0;
2086 1.1 christos }
2087 1.5.2.1 martin break;
2088 1.5.2.1 martin
2089 1.5.2.1 martin case AARCH64_OPND_SIMM5:
2090 1.5.2.1 martin case AARCH64_OPND_SVE_SIMM5:
2091 1.5.2.1 martin case AARCH64_OPND_SVE_SIMM5B:
2092 1.5.2.1 martin case AARCH64_OPND_SVE_SIMM6:
2093 1.5.2.1 martin case AARCH64_OPND_SVE_SIMM8:
2094 1.5.2.1 martin size = get_operand_fields_width (get_operand_from_code (type));
2095 1.5.2.1 martin assert (size < 32);
2096 1.5.2.1 martin if (!value_fit_signed_field_p (opnd->imm.value, size))
2097 1.5.2.1 martin {
2098 1.5.2.1 martin set_imm_out_of_range_error (mismatch_detail, idx,
2099 1.5.2.1 martin -(1 << (size - 1)),
2100 1.5.2.1 martin (1 << (size - 1)) - 1);
2101 1.5.2.1 martin return 0;
2102 1.5.2.1 martin }
2103 1.1 christos break;
2104 1.3 christos
2105 1.1 christos case AARCH64_OPND_WIDTH:
2106 1.1 christos assert (idx > 1 && opnds[idx-1].type == AARCH64_OPND_IMM
2107 1.1 christos && opnds[0].type == AARCH64_OPND_Rd);
2108 1.1 christos size = get_upper_bound (qualifier);
2109 1.1 christos if (opnd->imm.value + opnds[idx-1].imm.value > size)
2110 1.1 christos /* lsb+width <= reg.size */
2111 1.1 christos {
2112 1.1 christos set_imm_out_of_range_error (mismatch_detail, idx, 1,
2113 1.1 christos size - opnds[idx-1].imm.value);
2114 1.1 christos return 0;
2115 1.1 christos }
2116 1.1 christos break;
2117 1.5.2.1 martin
2118 1.5.2.1 martin case AARCH64_OPND_LIMM:
2119 1.5.2.1 martin case AARCH64_OPND_SVE_LIMM:
2120 1.5.2.1 martin {
2121 1.5.2.1 martin int esize = aarch64_get_qualifier_esize (opnds[0].qualifier);
2122 1.5.2.1 martin uint64_t uimm = opnd->imm.value;
2123 1.5.2.1 martin if (opcode->op == OP_BIC)
2124 1.5.2.1 martin uimm = ~uimm;
2125 1.5.2.1 martin if (!aarch64_logical_immediate_p (uimm, esize, NULL))
2126 1.5.2.1 martin {
2127 1.5.2.1 martin set_other_error (mismatch_detail, idx,
2128 1.5.2.1 martin _("immediate out of range"));
2129 1.5.2.1 martin return 0;
2130 1.1 christos }
2131 1.1 christos }
2132 1.1 christos break;
2133 1.1 christos
2134 1.1 christos case AARCH64_OPND_IMM0:
2135 1.1 christos case AARCH64_OPND_FPIMM0:
2136 1.1 christos if (opnd->imm.value != 0)
2137 1.1 christos {
2138 1.1 christos set_other_error (mismatch_detail, idx,
2139 1.1 christos _("immediate zero expected"));
2140 1.1 christos return 0;
2141 1.1 christos }
2142 1.5.2.1 martin break;
2143 1.5.2.1 martin
2144 1.5.2.1 martin case AARCH64_OPND_IMM_ROT1:
2145 1.5.2.1 martin case AARCH64_OPND_IMM_ROT2:
2146 1.5.2.1 martin case AARCH64_OPND_SVE_IMM_ROT2:
2147 1.5.2.1 martin if (opnd->imm.value != 0
2148 1.5.2.1 martin && opnd->imm.value != 90
2149 1.5.2.1 martin && opnd->imm.value != 180
2150 1.5.2.1 martin && opnd->imm.value != 270)
2151 1.5.2.1 martin {
2152 1.5.2.1 martin set_other_error (mismatch_detail, idx,
2153 1.5.2.1 martin _("rotate expected to be 0, 90, 180 or 270"));
2154 1.5.2.1 martin return 0;
2155 1.5.2.1 martin }
2156 1.5.2.1 martin break;
2157 1.5.2.1 martin
2158 1.5.2.1 martin case AARCH64_OPND_IMM_ROT3:
2159 1.5.2.1 martin case AARCH64_OPND_SVE_IMM_ROT1:
2160 1.5.2.1 martin if (opnd->imm.value != 90 && opnd->imm.value != 270)
2161 1.5.2.1 martin {
2162 1.5.2.1 martin set_other_error (mismatch_detail, idx,
2163 1.5.2.1 martin _("rotate expected to be 90 or 270"));
2164 1.5.2.1 martin return 0;
2165 1.5.2.1 martin }
2166 1.1 christos break;
2167 1.1 christos
2168 1.1 christos case AARCH64_OPND_SHLL_IMM:
2169 1.1 christos assert (idx == 2);
2170 1.1 christos size = 8 * aarch64_get_qualifier_esize (opnds[idx - 1].qualifier);
2171 1.1 christos if (opnd->imm.value != size)
2172 1.1 christos {
2173 1.1 christos set_other_error (mismatch_detail, idx,
2174 1.1 christos _("invalid shift amount"));
2175 1.1 christos return 0;
2176 1.1 christos }
2177 1.1 christos break;
2178 1.1 christos
2179 1.1 christos case AARCH64_OPND_IMM_VLSL:
2180 1.1 christos size = aarch64_get_qualifier_esize (qualifier);
2181 1.1 christos if (!value_in_range_p (opnd->imm.value, 0, size * 8 - 1))
2182 1.1 christos {
2183 1.1 christos set_imm_out_of_range_error (mismatch_detail, idx, 0,
2184 1.1 christos size * 8 - 1);
2185 1.1 christos return 0;
2186 1.1 christos }
2187 1.1 christos break;
2188 1.1 christos
2189 1.1 christos case AARCH64_OPND_IMM_VLSR:
2190 1.1 christos size = aarch64_get_qualifier_esize (qualifier);
2191 1.1 christos if (!value_in_range_p (opnd->imm.value, 1, size * 8))
2192 1.1 christos {
2193 1.1 christos set_imm_out_of_range_error (mismatch_detail, idx, 1, size * 8);
2194 1.1 christos return 0;
2195 1.1 christos }
2196 1.1 christos break;
2197 1.1 christos
2198 1.1 christos case AARCH64_OPND_SIMD_IMM:
2199 1.1 christos case AARCH64_OPND_SIMD_IMM_SFT:
2200 1.1 christos /* Qualifier check. */
2201 1.1 christos switch (qualifier)
2202 1.1 christos {
2203 1.1 christos case AARCH64_OPND_QLF_LSL:
2204 1.1 christos if (opnd->shifter.kind != AARCH64_MOD_LSL)
2205 1.1 christos {
2206 1.1 christos set_other_error (mismatch_detail, idx,
2207 1.1 christos _("invalid shift operator"));
2208 1.1 christos return 0;
2209 1.1 christos }
2210 1.1 christos break;
2211 1.1 christos case AARCH64_OPND_QLF_MSL:
2212 1.1 christos if (opnd->shifter.kind != AARCH64_MOD_MSL)
2213 1.1 christos {
2214 1.1 christos set_other_error (mismatch_detail, idx,
2215 1.1 christos _("invalid shift operator"));
2216 1.1 christos return 0;
2217 1.1 christos }
2218 1.1 christos break;
2219 1.1 christos case AARCH64_OPND_QLF_NIL:
2220 1.1 christos if (opnd->shifter.kind != AARCH64_MOD_NONE)
2221 1.1 christos {
2222 1.1 christos set_other_error (mismatch_detail, idx,
2223 1.1 christos _("shift is not permitted"));
2224 1.1 christos return 0;
2225 1.1 christos }
2226 1.1 christos break;
2227 1.1 christos default:
2228 1.1 christos assert (0);
2229 1.1 christos return 0;
2230 1.1 christos }
2231 1.1 christos /* Is the immediate valid? */
2232 1.1 christos assert (idx == 1);
2233 1.3 christos if (aarch64_get_qualifier_esize (opnds[0].qualifier) != 8)
2234 1.3 christos {
2235 1.1 christos /* uimm8 or simm8 */
2236 1.3 christos if (!value_in_range_p (opnd->imm.value, -128, 255))
2237 1.1 christos {
2238 1.1 christos set_imm_out_of_range_error (mismatch_detail, idx, -128, 255);
2239 1.1 christos return 0;
2240 1.1 christos }
2241 1.1 christos }
2242 1.1 christos else if (aarch64_shrink_expanded_imm8 (opnd->imm.value) < 0)
2243 1.1 christos {
2244 1.1 christos /* uimm64 is not
2245 1.1 christos 'aaaaaaaabbbbbbbbccccccccddddddddeeeeeeee
2246 1.1 christos ffffffffgggggggghhhhhhhh'. */
2247 1.1 christos set_other_error (mismatch_detail, idx,
2248 1.1 christos _("invalid value for immediate"));
2249 1.1 christos return 0;
2250 1.1 christos }
2251 1.1 christos /* Is the shift amount valid? */
2252 1.1 christos switch (opnd->shifter.kind)
2253 1.1 christos {
2254 1.3 christos case AARCH64_MOD_LSL:
2255 1.1 christos size = aarch64_get_qualifier_esize (opnds[0].qualifier);
2256 1.3 christos if (!value_in_range_p (opnd->shifter.amount, 0, (size - 1) * 8))
2257 1.3 christos {
2258 1.1 christos set_sft_amount_out_of_range_error (mismatch_detail, idx, 0,
2259 1.1 christos (size - 1) * 8);
2260 1.3 christos return 0;
2261 1.1 christos }
2262 1.3 christos if (!value_aligned_p (opnd->shifter.amount, 8))
2263 1.1 christos {
2264 1.1 christos set_unaligned_error (mismatch_detail, idx, 8);
2265 1.1 christos return 0;
2266 1.1 christos }
2267 1.1 christos break;
2268 1.1 christos case AARCH64_MOD_MSL:
2269 1.1 christos /* Only 8 and 16 are valid shift amount. */
2270 1.1 christos if (opnd->shifter.amount != 8 && opnd->shifter.amount != 16)
2271 1.5.2.1 martin {
2272 1.1 christos set_other_error (mismatch_detail, idx,
2273 1.1 christos _("shift amount must be 0 or 16"));
2274 1.1 christos return 0;
2275 1.1 christos }
2276 1.1 christos break;
2277 1.1 christos default:
2278 1.1 christos if (opnd->shifter.kind != AARCH64_MOD_NONE)
2279 1.1 christos {
2280 1.1 christos set_other_error (mismatch_detail, idx,
2281 1.1 christos _("invalid shift operator"));
2282 1.1 christos return 0;
2283 1.1 christos }
2284 1.1 christos break;
2285 1.1 christos }
2286 1.1 christos break;
2287 1.1 christos
2288 1.5.2.1 martin case AARCH64_OPND_FPIMM:
2289 1.1 christos case AARCH64_OPND_SIMD_FPIMM:
2290 1.1 christos case AARCH64_OPND_SVE_FPIMM8:
2291 1.1 christos if (opnd->imm.is_fp == 0)
2292 1.1 christos {
2293 1.1 christos set_other_error (mismatch_detail, idx,
2294 1.1 christos _("floating-point immediate expected"));
2295 1.1 christos return 0;
2296 1.1 christos }
2297 1.1 christos /* The value is expected to be an 8-bit floating-point constant with
2298 1.1 christos sign, 3-bit exponent and normalized 4 bits of precision, encoded
2299 1.1 christos in "a:b:c:d:e:f:g:h" or FLD_imm8 (depending on the type of the
2300 1.1 christos instruction). */
2301 1.1 christos if (!value_in_range_p (opnd->imm.value, 0, 255))
2302 1.1 christos {
2303 1.1 christos set_other_error (mismatch_detail, idx,
2304 1.1 christos _("immediate out of range"));
2305 1.1 christos return 0;
2306 1.1 christos }
2307 1.1 christos if (opnd->shifter.kind != AARCH64_MOD_NONE)
2308 1.1 christos {
2309 1.1 christos set_other_error (mismatch_detail, idx,
2310 1.1 christos _("invalid shift operator"));
2311 1.1 christos return 0;
2312 1.1 christos }
2313 1.5.2.1 martin break;
2314 1.5.2.1 martin
2315 1.5.2.1 martin case AARCH64_OPND_SVE_AIMM:
2316 1.5.2.1 martin min_value = 0;
2317 1.5.2.1 martin sve_aimm:
2318 1.5.2.1 martin assert (opnd->shifter.kind == AARCH64_MOD_LSL);
2319 1.5.2.1 martin size = aarch64_get_qualifier_esize (opnds[0].qualifier);
2320 1.5.2.1 martin mask = ~((uint64_t) -1 << (size * 4) << (size * 4));
2321 1.5.2.1 martin uvalue = opnd->imm.value;
2322 1.5.2.1 martin shift = opnd->shifter.amount;
2323 1.5.2.1 martin if (size == 1)
2324 1.5.2.1 martin {
2325 1.5.2.1 martin if (shift != 0)
2326 1.5.2.1 martin {
2327 1.5.2.1 martin set_other_error (mismatch_detail, idx,
2328 1.5.2.1 martin _("no shift amount allowed for"
2329 1.5.2.1 martin " 8-bit constants"));
2330 1.5.2.1 martin return 0;
2331 1.5.2.1 martin }
2332 1.5.2.1 martin }
2333 1.5.2.1 martin else
2334 1.5.2.1 martin {
2335 1.5.2.1 martin if (shift != 0 && shift != 8)
2336 1.5.2.1 martin {
2337 1.5.2.1 martin set_other_error (mismatch_detail, idx,
2338 1.5.2.1 martin _("shift amount must be 0 or 8"));
2339 1.5.2.1 martin return 0;
2340 1.5.2.1 martin }
2341 1.5.2.1 martin if (shift == 0 && (uvalue & 0xff) == 0)
2342 1.5.2.1 martin {
2343 1.5.2.1 martin shift = 8;
2344 1.5.2.1 martin uvalue = (int64_t) uvalue / 256;
2345 1.5.2.1 martin }
2346 1.5.2.1 martin }
2347 1.5.2.1 martin mask >>= shift;
2348 1.5.2.1 martin if ((uvalue & mask) != uvalue && (uvalue | ~mask) != uvalue)
2349 1.5.2.1 martin {
2350 1.5.2.1 martin set_other_error (mismatch_detail, idx,
2351 1.5.2.1 martin _("immediate too big for element size"));
2352 1.5.2.1 martin return 0;
2353 1.5.2.1 martin }
2354 1.5.2.1 martin uvalue = (uvalue - min_value) & mask;
2355 1.5.2.1 martin if (uvalue > 0xff)
2356 1.5.2.1 martin {
2357 1.5.2.1 martin set_other_error (mismatch_detail, idx,
2358 1.5.2.1 martin _("invalid arithmetic immediate"));
2359 1.1 christos return 0;
2360 1.1 christos }
2361 1.5.2.1 martin break;
2362 1.5.2.1 martin
2363 1.5.2.1 martin case AARCH64_OPND_SVE_ASIMM:
2364 1.5.2.1 martin min_value = -128;
2365 1.5.2.1 martin goto sve_aimm;
2366 1.5.2.1 martin
2367 1.5.2.1 martin case AARCH64_OPND_SVE_I1_HALF_ONE:
2368 1.5.2.1 martin assert (opnd->imm.is_fp);
2369 1.5.2.1 martin if (opnd->imm.value != 0x3f000000 && opnd->imm.value != 0x3f800000)
2370 1.5.2.1 martin {
2371 1.5.2.1 martin set_other_error (mismatch_detail, idx,
2372 1.5.2.1 martin _("floating-point value must be 0.5 or 1.0"));
2373 1.5.2.1 martin return 0;
2374 1.5.2.1 martin }
2375 1.5.2.1 martin break;
2376 1.5.2.1 martin
2377 1.5.2.1 martin case AARCH64_OPND_SVE_I1_HALF_TWO:
2378 1.5.2.1 martin assert (opnd->imm.is_fp);
2379 1.5.2.1 martin if (opnd->imm.value != 0x3f000000 && opnd->imm.value != 0x40000000)
2380 1.5.2.1 martin {
2381 1.5.2.1 martin set_other_error (mismatch_detail, idx,
2382 1.5.2.1 martin _("floating-point value must be 0.5 or 2.0"));
2383 1.5.2.1 martin return 0;
2384 1.5.2.1 martin }
2385 1.5.2.1 martin break;
2386 1.5.2.1 martin
2387 1.5.2.1 martin case AARCH64_OPND_SVE_I1_ZERO_ONE:
2388 1.5.2.1 martin assert (opnd->imm.is_fp);
2389 1.5.2.1 martin if (opnd->imm.value != 0 && opnd->imm.value != 0x3f800000)
2390 1.5.2.1 martin {
2391 1.5.2.1 martin set_other_error (mismatch_detail, idx,
2392 1.5.2.1 martin _("floating-point value must be 0.0 or 1.0"));
2393 1.5.2.1 martin return 0;
2394 1.5.2.1 martin }
2395 1.5.2.1 martin break;
2396 1.5.2.1 martin
2397 1.5.2.1 martin case AARCH64_OPND_SVE_INV_LIMM:
2398 1.5.2.1 martin {
2399 1.5.2.1 martin int esize = aarch64_get_qualifier_esize (opnds[0].qualifier);
2400 1.5.2.1 martin uint64_t uimm = ~opnd->imm.value;
2401 1.5.2.1 martin if (!aarch64_logical_immediate_p (uimm, esize, NULL))
2402 1.5.2.1 martin {
2403 1.5.2.1 martin set_other_error (mismatch_detail, idx,
2404 1.5.2.1 martin _("immediate out of range"));
2405 1.5.2.1 martin return 0;
2406 1.5.2.1 martin }
2407 1.5.2.1 martin }
2408 1.5.2.1 martin break;
2409 1.5.2.1 martin
2410 1.5.2.1 martin case AARCH64_OPND_SVE_LIMM_MOV:
2411 1.5.2.1 martin {
2412 1.5.2.1 martin int esize = aarch64_get_qualifier_esize (opnds[0].qualifier);
2413 1.5.2.1 martin uint64_t uimm = opnd->imm.value;
2414 1.5.2.1 martin if (!aarch64_logical_immediate_p (uimm, esize, NULL))
2415 1.5.2.1 martin {
2416 1.5.2.1 martin set_other_error (mismatch_detail, idx,
2417 1.5.2.1 martin _("immediate out of range"));
2418 1.5.2.1 martin return 0;
2419 1.5.2.1 martin }
2420 1.5.2.1 martin if (!aarch64_sve_dupm_mov_immediate_p (uimm, esize))
2421 1.5.2.1 martin {
2422 1.5.2.1 martin set_other_error (mismatch_detail, idx,
2423 1.5.2.1 martin _("invalid replicated MOV immediate"));
2424 1.5.2.1 martin return 0;
2425 1.5.2.1 martin }
2426 1.5.2.1 martin }
2427 1.5.2.1 martin break;
2428 1.5.2.1 martin
2429 1.5.2.1 martin case AARCH64_OPND_SVE_PATTERN_SCALED:
2430 1.5.2.1 martin assert (opnd->shifter.kind == AARCH64_MOD_MUL);
2431 1.5.2.1 martin if (!value_in_range_p (opnd->shifter.amount, 1, 16))
2432 1.5.2.1 martin {
2433 1.5.2.1 martin set_multiplier_out_of_range_error (mismatch_detail, idx, 1, 16);
2434 1.5.2.1 martin return 0;
2435 1.5.2.1 martin }
2436 1.5.2.1 martin break;
2437 1.5.2.1 martin
2438 1.5.2.1 martin case AARCH64_OPND_SVE_SHLIMM_PRED:
2439 1.5.2.1 martin case AARCH64_OPND_SVE_SHLIMM_UNPRED:
2440 1.5.2.1 martin size = aarch64_get_qualifier_esize (opnds[idx - 1].qualifier);
2441 1.5.2.1 martin if (!value_in_range_p (opnd->imm.value, 0, 8 * size - 1))
2442 1.5.2.1 martin {
2443 1.5.2.1 martin set_imm_out_of_range_error (mismatch_detail, idx,
2444 1.5.2.1 martin 0, 8 * size - 1);
2445 1.5.2.1 martin return 0;
2446 1.5.2.1 martin }
2447 1.5.2.1 martin break;
2448 1.5.2.1 martin
2449 1.5.2.1 martin case AARCH64_OPND_SVE_SHRIMM_PRED:
2450 1.5.2.1 martin case AARCH64_OPND_SVE_SHRIMM_UNPRED:
2451 1.5.2.1 martin size = aarch64_get_qualifier_esize (opnds[idx - 1].qualifier);
2452 1.5.2.1 martin if (!value_in_range_p (opnd->imm.value, 1, 8 * size))
2453 1.5.2.1 martin {
2454 1.5.2.1 martin set_imm_out_of_range_error (mismatch_detail, idx, 1, 8 * size);
2455 1.5.2.1 martin return 0;
2456 1.5.2.1 martin }
2457 1.5.2.1 martin break;
2458 1.5.2.1 martin
2459 1.1 christos default:
2460 1.1 christos break;
2461 1.1 christos }
2462 1.1 christos break;
2463 1.1 christos
2464 1.1 christos case AARCH64_OPND_CLASS_SYSTEM:
2465 1.1 christos switch (type)
2466 1.1 christos {
2467 1.5 christos case AARCH64_OPND_PSTATEFIELD:
2468 1.5 christos assert (idx == 0 && opnds[1].type == AARCH64_OPND_UIMM4);
2469 1.5 christos /* MSR UAO, #uimm4
2470 1.5 christos MSR PAN, #uimm4
2471 1.5.2.1 martin The immediate must be #0 or #1. */
2472 1.5.2.1 martin if ((opnd->pstatefield == 0x03 /* UAO. */
2473 1.5 christos || opnd->pstatefield == 0x04 /* PAN. */
2474 1.5 christos || opnd->pstatefield == 0x1a) /* DIT. */
2475 1.5 christos && opnds[1].imm.value > 1)
2476 1.5 christos {
2477 1.5 christos set_imm_out_of_range_error (mismatch_detail, idx, 0, 1);
2478 1.1 christos return 0;
2479 1.1 christos }
2480 1.1 christos /* MSR SPSel, #uimm4
2481 1.1 christos Uses uimm4 as a control value to select the stack pointer: if
2482 1.1 christos bit 0 is set it selects the current exception level's stack
2483 1.1 christos pointer, if bit 0 is clear it selects shared EL0 stack pointer.
2484 1.1 christos Bits 1 to 3 of uimm4 are reserved and should be zero. */
2485 1.1 christos if (opnd->pstatefield == 0x05 /* spsel */ && opnds[1].imm.value > 1)
2486 1.1 christos {
2487 1.1 christos set_imm_out_of_range_error (mismatch_detail, idx, 0, 1);
2488 1.1 christos return 0;
2489 1.1 christos }
2490 1.1 christos break;
2491 1.1 christos default:
2492 1.1 christos break;
2493 1.1 christos }
2494 1.1 christos break;
2495 1.1 christos
2496 1.5.2.1 martin case AARCH64_OPND_CLASS_SIMD_ELEMENT:
2497 1.5.2.1 martin /* Get the upper bound for the element index. */
2498 1.5.2.1 martin if (opcode->op == OP_FCMLA_ELEM)
2499 1.5.2.1 martin /* FCMLA index range depends on the vector size of other operands
2500 1.5.2.1 martin and is halfed because complex numbers take two elements. */
2501 1.5.2.1 martin num = aarch64_get_qualifier_nelem (opnds[0].qualifier)
2502 1.5.2.1 martin * aarch64_get_qualifier_esize (opnds[0].qualifier) / 2;
2503 1.5.2.1 martin else
2504 1.5.2.1 martin num = 16;
2505 1.1 christos num = num / aarch64_get_qualifier_esize (qualifier) - 1;
2506 1.1 christos
2507 1.1 christos /* Index out-of-range. */
2508 1.1 christos if (!value_in_range_p (opnd->reglane.index, 0, num))
2509 1.1 christos {
2510 1.1 christos set_elem_idx_out_of_range_error (mismatch_detail, idx, 0, num);
2511 1.1 christos return 0;
2512 1.1 christos }
2513 1.1 christos /* SMLAL<Q> <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Ts>[<index>].
2514 1.1 christos <Vm> Is the vector register (V0-V31) or (V0-V15), whose
2515 1.1 christos number is encoded in "size:M:Rm":
2516 1.1 christos size <Vm>
2517 1.1 christos 00 RESERVED
2518 1.1 christos 01 0:Rm
2519 1.5.2.1 martin 10 M:Rm
2520 1.1 christos 11 RESERVED */
2521 1.1 christos if (type == AARCH64_OPND_Em16 && qualifier == AARCH64_OPND_QLF_S_H
2522 1.1 christos && !value_in_range_p (opnd->reglane.regno, 0, 15))
2523 1.1 christos {
2524 1.1 christos set_regno_out_of_range_error (mismatch_detail, idx, 0, 15);
2525 1.1 christos return 0;
2526 1.1 christos }
2527 1.1 christos break;
2528 1.1 christos
2529 1.1 christos case AARCH64_OPND_CLASS_MODIFIED_REG:
2530 1.1 christos assert (idx == 1 || idx == 2);
2531 1.1 christos switch (type)
2532 1.5.2.1 martin {
2533 1.1 christos case AARCH64_OPND_Rm_EXT:
2534 1.1 christos if (!aarch64_extend_operator_p (opnd->shifter.kind)
2535 1.1 christos && opnd->shifter.kind != AARCH64_MOD_LSL)
2536 1.1 christos {
2537 1.1 christos set_other_error (mismatch_detail, idx,
2538 1.1 christos _("extend operator expected"));
2539 1.1 christos return 0;
2540 1.1 christos }
2541 1.1 christos /* It is not optional unless at least one of "Rd" or "Rn" is '11111'
2542 1.1 christos (i.e. SP), in which case it defaults to LSL. The LSL alias is
2543 1.1 christos only valid when "Rd" or "Rn" is '11111', and is preferred in that
2544 1.1 christos case. */
2545 1.1 christos if (!aarch64_stack_pointer_p (opnds + 0)
2546 1.1 christos && (idx != 2 || !aarch64_stack_pointer_p (opnds + 1)))
2547 1.1 christos {
2548 1.1 christos if (!opnd->shifter.operator_present)
2549 1.1 christos {
2550 1.1 christos set_other_error (mismatch_detail, idx,
2551 1.1 christos _("missing extend operator"));
2552 1.1 christos return 0;
2553 1.1 christos }
2554 1.1 christos else if (opnd->shifter.kind == AARCH64_MOD_LSL)
2555 1.1 christos {
2556 1.1 christos set_other_error (mismatch_detail, idx,
2557 1.1 christos _("'LSL' operator not allowed"));
2558 1.1 christos return 0;
2559 1.1 christos }
2560 1.1 christos }
2561 1.1 christos assert (opnd->shifter.operator_present /* Default to LSL. */
2562 1.1 christos || opnd->shifter.kind == AARCH64_MOD_LSL);
2563 1.1 christos if (!value_in_range_p (opnd->shifter.amount, 0, 4))
2564 1.1 christos {
2565 1.1 christos set_sft_amount_out_of_range_error (mismatch_detail, idx, 0, 4);
2566 1.1 christos return 0;
2567 1.1 christos }
2568 1.1 christos /* In the 64-bit form, the final register operand is written as Wm
2569 1.1 christos for all but the (possibly omitted) UXTX/LSL and SXTX
2570 1.1 christos operators.
2571 1.1 christos N.B. GAS allows X register to be used with any operator as a
2572 1.1 christos programming convenience. */
2573 1.1 christos if (qualifier == AARCH64_OPND_QLF_X
2574 1.1 christos && opnd->shifter.kind != AARCH64_MOD_LSL
2575 1.1 christos && opnd->shifter.kind != AARCH64_MOD_UXTX
2576 1.1 christos && opnd->shifter.kind != AARCH64_MOD_SXTX)
2577 1.1 christos {
2578 1.1 christos set_other_error (mismatch_detail, idx, _("W register expected"));
2579 1.1 christos return 0;
2580 1.1 christos }
2581 1.1 christos break;
2582 1.1 christos
2583 1.1 christos case AARCH64_OPND_Rm_SFT:
2584 1.5.2.1 martin /* ROR is not available to the shifted register operand in
2585 1.1 christos arithmetic instructions. */
2586 1.1 christos if (!aarch64_shift_operator_p (opnd->shifter.kind))
2587 1.1 christos {
2588 1.1 christos set_other_error (mismatch_detail, idx,
2589 1.1 christos _("shift operator expected"));
2590 1.1 christos return 0;
2591 1.1 christos }
2592 1.1 christos if (opnd->shifter.kind == AARCH64_MOD_ROR
2593 1.1 christos && opcode->iclass != log_shift)
2594 1.1 christos {
2595 1.1 christos set_other_error (mismatch_detail, idx,
2596 1.1 christos _("'ROR' operator not allowed"));
2597 1.1 christos return 0;
2598 1.1 christos }
2599 1.1 christos num = qualifier == AARCH64_OPND_QLF_W ? 31 : 63;
2600 1.1 christos if (!value_in_range_p (opnd->shifter.amount, 0, num))
2601 1.1 christos {
2602 1.1 christos set_sft_amount_out_of_range_error (mismatch_detail, idx, 0, num);
2603 1.1 christos return 0;
2604 1.1 christos }
2605 1.1 christos break;
2606 1.1 christos
2607 1.1 christos default:
2608 1.1 christos break;
2609 1.1 christos }
2610 1.1 christos break;
2611 1.1 christos
2612 1.1 christos default:
2613 1.1 christos break;
2614 1.1 christos }
2615 1.1 christos
2616 1.1 christos return 1;
2617 1.1 christos }
2618 1.1 christos
2619 1.1 christos /* Main entrypoint for the operand constraint checking.
2620 1.1 christos
2621 1.1 christos Return 1 if operands of *INST meet the constraint applied by the operand
2622 1.1 christos codes and operand qualifiers; otherwise return 0 and if MISMATCH_DETAIL is
2623 1.1 christos not NULL, return the detail of the error in *MISMATCH_DETAIL. N.B. when
2624 1.1 christos adding more constraint checking, make sure MISMATCH_DETAIL->KIND is set
2625 1.1 christos with a proper error kind rather than AARCH64_OPDE_NIL (GAS asserts non-NIL
2626 1.1 christos error kind when it is notified that an instruction does not pass the check).
2627 1.1 christos
2628 1.1 christos Un-determined operand qualifiers may get established during the process. */
2629 1.1 christos
2630 1.1 christos int
2631 1.1 christos aarch64_match_operands_constraint (aarch64_inst *inst,
2632 1.1 christos aarch64_operand_error *mismatch_detail)
2633 1.1 christos {
2634 1.1 christos int i;
2635 1.1 christos
2636 1.5.2.1 martin DEBUG_TRACE ("enter");
2637 1.5.2.1 martin
2638 1.5.2.1 martin /* Check for cases where a source register needs to be the same as the
2639 1.5.2.1 martin destination register. Do this before matching qualifiers since if
2640 1.5.2.1 martin an instruction has both invalid tying and invalid qualifiers,
2641 1.5.2.1 martin the error about qualifiers would suggest several alternative
2642 1.5.2.1 martin instructions that also have invalid tying. */
2643 1.5.2.1 martin i = inst->opcode->tied_operand;
2644 1.5.2.1 martin if (i > 0 && (inst->operands[0].reg.regno != inst->operands[i].reg.regno))
2645 1.5.2.1 martin {
2646 1.5.2.1 martin if (mismatch_detail)
2647 1.5.2.1 martin {
2648 1.5.2.1 martin mismatch_detail->kind = AARCH64_OPDE_UNTIED_OPERAND;
2649 1.5.2.1 martin mismatch_detail->index = i;
2650 1.5.2.1 martin mismatch_detail->error = NULL;
2651 1.5.2.1 martin }
2652 1.5.2.1 martin return 0;
2653 1.1 christos }
2654 1.1 christos
2655 1.1 christos /* Match operands' qualifier.
2656 1.1 christos *INST has already had qualifier establish for some, if not all, of
2657 1.1 christos its operands; we need to find out whether these established
2658 1.1 christos qualifiers match one of the qualifier sequence in
2659 1.1 christos INST->OPCODE->QUALIFIERS_LIST. If yes, we will assign each operand
2660 1.1 christos with the corresponding qualifier in such a sequence.
2661 1.1 christos Only basic operand constraint checking is done here; the more thorough
2662 1.1 christos constraint checking will carried out by operand_general_constraint_met_p,
2663 1.1 christos which has be to called after this in order to get all of the operands'
2664 1.1 christos qualifiers established. */
2665 1.1 christos if (match_operands_qualifier (inst, TRUE /* update_p */) == 0)
2666 1.1 christos {
2667 1.1 christos DEBUG_TRACE ("FAIL on operand qualifier matching");
2668 1.1 christos if (mismatch_detail)
2669 1.1 christos {
2670 1.1 christos /* Return an error type to indicate that it is the qualifier
2671 1.1 christos matching failure; we don't care about which operand as there
2672 1.1 christos are enough information in the opcode table to reproduce it. */
2673 1.1 christos mismatch_detail->kind = AARCH64_OPDE_INVALID_VARIANT;
2674 1.1 christos mismatch_detail->index = -1;
2675 1.1 christos mismatch_detail->error = NULL;
2676 1.1 christos }
2677 1.1 christos return 0;
2678 1.1 christos }
2679 1.1 christos
2680 1.1 christos /* Match operands' constraint. */
2681 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
2682 1.1 christos {
2683 1.1 christos enum aarch64_opnd type = inst->opcode->operands[i];
2684 1.1 christos if (type == AARCH64_OPND_NIL)
2685 1.1 christos break;
2686 1.1 christos if (inst->operands[i].skip)
2687 1.1 christos {
2688 1.1 christos DEBUG_TRACE ("skip the incomplete operand %d", i);
2689 1.1 christos continue;
2690 1.1 christos }
2691 1.1 christos if (operand_general_constraint_met_p (inst->operands, i, type,
2692 1.1 christos inst->opcode, mismatch_detail) == 0)
2693 1.1 christos {
2694 1.1 christos DEBUG_TRACE ("FAIL on operand %d", i);
2695 1.1 christos return 0;
2696 1.1 christos }
2697 1.1 christos }
2698 1.1 christos
2699 1.1 christos DEBUG_TRACE ("PASS");
2700 1.1 christos
2701 1.1 christos return 1;
2702 1.1 christos }
2703 1.1 christos
2704 1.1 christos /* Replace INST->OPCODE with OPCODE and return the replaced OPCODE.
2705 1.1 christos Also updates the TYPE of each INST->OPERANDS with the corresponding
2706 1.1 christos value of OPCODE->OPERANDS.
2707 1.1 christos
2708 1.1 christos Note that some operand qualifiers may need to be manually cleared by
2709 1.1 christos the caller before it further calls the aarch64_opcode_encode; by
2710 1.1 christos doing this, it helps the qualifier matching facilities work
2711 1.1 christos properly. */
2712 1.1 christos
2713 1.1 christos const aarch64_opcode*
2714 1.1 christos aarch64_replace_opcode (aarch64_inst *inst, const aarch64_opcode *opcode)
2715 1.1 christos {
2716 1.1 christos int i;
2717 1.1 christos const aarch64_opcode *old = inst->opcode;
2718 1.1 christos
2719 1.1 christos inst->opcode = opcode;
2720 1.1 christos
2721 1.1 christos /* Update the operand types. */
2722 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
2723 1.1 christos {
2724 1.1 christos inst->operands[i].type = opcode->operands[i];
2725 1.1 christos if (opcode->operands[i] == AARCH64_OPND_NIL)
2726 1.1 christos break;
2727 1.1 christos }
2728 1.1 christos
2729 1.1 christos DEBUG_TRACE ("replace %s with %s", old->name, opcode->name);
2730 1.1 christos
2731 1.1 christos return old;
2732 1.1 christos }
2733 1.1 christos
2734 1.1 christos int
2735 1.1 christos aarch64_operand_index (const enum aarch64_opnd *operands, enum aarch64_opnd operand)
2736 1.1 christos {
2737 1.1 christos int i;
2738 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
2739 1.1 christos if (operands[i] == operand)
2740 1.1 christos return i;
2741 1.1 christos else if (operands[i] == AARCH64_OPND_NIL)
2742 1.1 christos break;
2743 1.1 christos return -1;
2744 1.5.2.1 martin }
2745 1.5.2.1 martin
2746 1.5.2.1 martin /* R0...R30, followed by FOR31. */
2748 1.5.2.1 martin #define BANK(R, FOR31) \
2749 1.5.2.1 martin { R (0), R (1), R (2), R (3), R (4), R (5), R (6), R (7), \
2750 1.1 christos R (8), R (9), R (10), R (11), R (12), R (13), R (14), R (15), \
2751 1.1 christos R (16), R (17), R (18), R (19), R (20), R (21), R (22), R (23), \
2752 1.1 christos R (24), R (25), R (26), R (27), R (28), R (29), R (30), FOR31 }
2753 1.1 christos /* [0][0] 32-bit integer regs with sp Wn
2754 1.1 christos [0][1] 64-bit integer regs with sp Xn sf=1
2755 1.5.2.1 martin [1][0] 32-bit integer regs with #0 Wn
2756 1.5.2.1 martin [1][1] 64-bit integer regs with #0 Xn sf=1 */
2757 1.5.2.1 martin static const char *int_reg[2][2][32] = {
2758 1.5.2.1 martin #define R32(X) "w" #X
2759 1.1 christos #define R64(X) "x" #X
2760 1.1 christos { BANK (R32, "wsp"), BANK (R64, "sp") },
2761 1.1 christos { BANK (R32, "wzr"), BANK (R64, "xzr") }
2762 1.1 christos #undef R64
2763 1.5.2.1 martin #undef R32
2764 1.5.2.1 martin };
2765 1.5.2.1 martin
2766 1.5.2.1 martin /* Names of the SVE vector registers, first with .S suffixes,
2767 1.5.2.1 martin then with .D suffixes. */
2768 1.5.2.1 martin
2769 1.5.2.1 martin static const char *sve_reg[2][32] = {
2770 1.5.2.1 martin #define ZS(X) "z" #X ".s"
2771 1.5.2.1 martin #define ZD(X) "z" #X ".d"
2772 1.5.2.1 martin BANK (ZS, ZS (31)), BANK (ZD, ZD (31))
2773 1.5.2.1 martin #undef ZD
2774 1.5.2.1 martin #undef ZS
2775 1.1 christos };
2776 1.1 christos #undef BANK
2777 1.1 christos
2778 1.1 christos /* Return the integer register name.
2779 1.1 christos if SP_REG_P is not 0, R31 is an SP reg, other R31 is the zero reg. */
2780 1.1 christos
2781 1.1 christos static inline const char *
2782 1.1 christos get_int_reg_name (int regno, aarch64_opnd_qualifier_t qualifier, int sp_reg_p)
2783 1.1 christos {
2784 1.1 christos const int has_zr = sp_reg_p ? 0 : 1;
2785 1.1 christos const int is_64 = aarch64_get_qualifier_esize (qualifier) == 4 ? 0 : 1;
2786 1.1 christos return int_reg[has_zr][is_64][regno];
2787 1.1 christos }
2788 1.1 christos
2789 1.1 christos /* Like get_int_reg_name, but IS_64 is always 1. */
2790 1.1 christos
2791 1.1 christos static inline const char *
2792 1.1 christos get_64bit_int_reg_name (int regno, int sp_reg_p)
2793 1.1 christos {
2794 1.1 christos const int has_zr = sp_reg_p ? 0 : 1;
2795 1.5.2.1 martin return int_reg[has_zr][1][regno];
2796 1.5.2.1 martin }
2797 1.5.2.1 martin
2798 1.5.2.1 martin /* Get the name of the integer offset register in OPND, using the shift type
2799 1.5.2.1 martin to decide whether it's a word or doubleword. */
2800 1.5.2.1 martin
2801 1.5.2.1 martin static inline const char *
2802 1.5.2.1 martin get_offset_int_reg_name (const aarch64_opnd_info *opnd)
2803 1.5.2.1 martin {
2804 1.5.2.1 martin switch (opnd->shifter.kind)
2805 1.5.2.1 martin {
2806 1.5.2.1 martin case AARCH64_MOD_UXTW:
2807 1.5.2.1 martin case AARCH64_MOD_SXTW:
2808 1.5.2.1 martin return get_int_reg_name (opnd->addr.offset.regno, AARCH64_OPND_QLF_W, 0);
2809 1.5.2.1 martin
2810 1.5.2.1 martin case AARCH64_MOD_LSL:
2811 1.5.2.1 martin case AARCH64_MOD_SXTX:
2812 1.5.2.1 martin return get_int_reg_name (opnd->addr.offset.regno, AARCH64_OPND_QLF_X, 0);
2813 1.5.2.1 martin
2814 1.5.2.1 martin default:
2815 1.5.2.1 martin abort ();
2816 1.5.2.1 martin }
2817 1.5.2.1 martin }
2818 1.5.2.1 martin
2819 1.5.2.1 martin /* Get the name of the SVE vector offset register in OPND, using the operand
2820 1.5.2.1 martin qualifier to decide whether the suffix should be .S or .D. */
2821 1.5.2.1 martin
2822 1.5.2.1 martin static inline const char *
2823 1.5.2.1 martin get_addr_sve_reg_name (int regno, aarch64_opnd_qualifier_t qualifier)
2824 1.5.2.1 martin {
2825 1.5.2.1 martin assert (qualifier == AARCH64_OPND_QLF_S_S
2826 1.5.2.1 martin || qualifier == AARCH64_OPND_QLF_S_D);
2827 1.1 christos return sve_reg[qualifier == AARCH64_OPND_QLF_S_D][regno];
2828 1.1 christos }
2829 1.1 christos
2830 1.1 christos /* Types for expanding an encoded 8-bit value to a floating-point value. */
2831 1.1 christos
2832 1.1 christos typedef union
2833 1.1 christos {
2834 1.1 christos uint64_t i;
2835 1.1 christos double d;
2836 1.1 christos } double_conv_t;
2837 1.1 christos
2838 1.1 christos typedef union
2839 1.1 christos {
2840 1.1 christos uint32_t i;
2841 1.3 christos float f;
2842 1.3 christos } single_conv_t;
2843 1.3 christos
2844 1.3 christos typedef union
2845 1.3 christos {
2846 1.3 christos uint32_t i;
2847 1.1 christos float f;
2848 1.1 christos } half_conv_t;
2849 1.1 christos
2850 1.3 christos /* IMM8 is an 8-bit floating-point constant with sign, 3-bit exponent and
2851 1.3 christos normalized 4 bits of precision, encoded in "a:b:c:d:e:f:g:h" or FLD_imm8
2852 1.3 christos (depending on the type of the instruction). IMM8 will be expanded to a
2853 1.3 christos single-precision floating-point value (SIZE == 4) or a double-precision
2854 1.1 christos floating-point value (SIZE == 8). A half-precision floating-point value
2855 1.1 christos (SIZE == 2) is expanded to a single-precision floating-point value. The
2856 1.3 christos expanded value is returned. */
2857 1.1 christos
2858 1.5.2.1 martin static uint64_t
2859 1.1 christos expand_fp_imm (int size, uint32_t imm8)
2860 1.1 christos {
2861 1.1 christos uint64_t imm = 0;
2862 1.1 christos uint32_t imm8_7, imm8_6_0, imm8_6, imm8_6_repl4;
2863 1.1 christos
2864 1.1 christos imm8_7 = (imm8 >> 7) & 0x01; /* imm8<7> */
2865 1.1 christos imm8_6_0 = imm8 & 0x7f; /* imm8<6:0> */
2866 1.3 christos imm8_6 = imm8_6_0 >> 6; /* imm8<6> */
2867 1.1 christos imm8_6_repl4 = (imm8_6 << 3) | (imm8_6 << 2)
2868 1.1 christos | (imm8_6 << 1) | imm8_6; /* Replicate(imm8<6>,4) */
2869 1.1 christos if (size == 8)
2870 1.1 christos {
2871 1.1 christos imm = (imm8_7 << (63-32)) /* imm8<7> */
2872 1.1 christos | ((imm8_6 ^ 1) << (62-32)) /* NOT(imm8<6) */
2873 1.1 christos | (imm8_6_repl4 << (58-32)) | (imm8_6 << (57-32))
2874 1.1 christos | (imm8_6 << (56-32)) | (imm8_6 << (55-32)) /* Replicate(imm8<6>,7) */
2875 1.3 christos | (imm8_6_0 << (48-32)); /* imm8<6>:imm8<5:0> */
2876 1.1 christos imm <<= 32;
2877 1.1 christos }
2878 1.1 christos else if (size == 4 || size == 2)
2879 1.1 christos {
2880 1.1 christos imm = (imm8_7 << 31) /* imm8<7> */
2881 1.1 christos | ((imm8_6 ^ 1) << 30) /* NOT(imm8<6>) */
2882 1.3 christos | (imm8_6_repl4 << 26) /* Replicate(imm8<6>,4) */
2883 1.3 christos | (imm8_6_0 << 19); /* imm8<6>:imm8<5:0> */
2884 1.3 christos }
2885 1.3 christos else
2886 1.3 christos {
2887 1.1 christos /* An unsupported size. */
2888 1.1 christos assert (0);
2889 1.1 christos }
2890 1.1 christos
2891 1.1 christos return imm;
2892 1.5.2.1 martin }
2893 1.5.2.1 martin
2894 1.1 christos /* Produce the string representation of the register list operand *OPND
2895 1.5.2.1 martin in the buffer pointed by BUF of size SIZE. PREFIX is the part of
2896 1.5.2.1 martin the register name that comes before the register number, such as "v". */
2897 1.1 christos static void
2898 1.1 christos print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
2899 1.1 christos const char *prefix)
2900 1.1 christos {
2901 1.1 christos const int num_regs = opnd->reglist.num_regs;
2902 1.1 christos const int first_reg = opnd->reglist.first_regno;
2903 1.1 christos const int last_reg = (first_reg + num_regs - 1) & 0x1f;
2904 1.1 christos const char *qlf_name = aarch64_get_qualifier_name (opnd->qualifier);
2905 1.1 christos char tb[8]; /* Temporary buffer. */
2906 1.1 christos
2907 1.1 christos assert (opnd->type != AARCH64_OPND_LEt || opnd->reglist.has_index);
2908 1.1 christos assert (num_regs >= 1 && num_regs <= 4);
2909 1.5.2.1 martin
2910 1.5.2.1 martin /* Prepare the index if any. */
2911 1.1 christos if (opnd->reglist.has_index)
2912 1.1 christos /* PR 21096: The %100 is to silence a warning about possible truncation. */
2913 1.1 christos snprintf (tb, 8, "[%" PRIi64 "]", (opnd->reglist.index % 100));
2914 1.1 christos else
2915 1.1 christos tb[0] = '\0';
2916 1.1 christos
2917 1.1 christos /* The hyphenated form is preferred for disassembly if there are
2918 1.5.2.1 martin more than two registers in the list, and the register numbers
2919 1.5.2.1 martin are monotonically increasing in increments of one. */
2920 1.1 christos if (num_regs > 2 && last_reg > first_reg)
2921 1.1 christos snprintf (buf, size, "{%s%d.%s-%s%d.%s}%s", prefix, first_reg, qlf_name,
2922 1.1 christos prefix, last_reg, qlf_name, tb);
2923 1.1 christos else
2924 1.1 christos {
2925 1.1 christos const int reg0 = first_reg;
2926 1.1 christos const int reg1 = (first_reg + 1) & 0x1f;
2927 1.1 christos const int reg2 = (first_reg + 2) & 0x1f;
2928 1.1 christos const int reg3 = (first_reg + 3) & 0x1f;
2929 1.1 christos
2930 1.5.2.1 martin switch (num_regs)
2931 1.1 christos {
2932 1.1 christos case 1:
2933 1.5.2.1 martin snprintf (buf, size, "{%s%d.%s}%s", prefix, reg0, qlf_name, tb);
2934 1.5.2.1 martin break;
2935 1.1 christos case 2:
2936 1.1 christos snprintf (buf, size, "{%s%d.%s, %s%d.%s}%s", prefix, reg0, qlf_name,
2937 1.5.2.1 martin prefix, reg1, qlf_name, tb);
2938 1.5.2.1 martin break;
2939 1.5.2.1 martin case 3:
2940 1.1 christos snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s}%s",
2941 1.1 christos prefix, reg0, qlf_name, prefix, reg1, qlf_name,
2942 1.5.2.1 martin prefix, reg2, qlf_name, tb);
2943 1.5.2.1 martin break;
2944 1.5.2.1 martin case 4:
2945 1.1 christos snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s, %s%d.%s}%s",
2946 1.1 christos prefix, reg0, qlf_name, prefix, reg1, qlf_name,
2947 1.1 christos prefix, reg2, qlf_name, prefix, reg3, qlf_name, tb);
2948 1.1 christos break;
2949 1.1 christos }
2950 1.5.2.1 martin }
2951 1.5.2.1 martin }
2952 1.5.2.1 martin
2953 1.5.2.1 martin /* Print the register+immediate address in OPND to BUF, which has SIZE
2954 1.5.2.1 martin characters. BASE is the name of the base register. */
2955 1.5.2.1 martin
2956 1.5.2.1 martin static void
2957 1.5.2.1 martin print_immediate_offset_address (char *buf, size_t size,
2958 1.5.2.1 martin const aarch64_opnd_info *opnd,
2959 1.5.2.1 martin const char *base)
2960 1.5.2.1 martin {
2961 1.5.2.1 martin if (opnd->addr.writeback)
2962 1.5.2.1 martin {
2963 1.5.2.1 martin if (opnd->addr.preind)
2964 1.5.2.1 martin snprintf (buf, size, "[%s, #%d]!", base, opnd->addr.offset.imm);
2965 1.5.2.1 martin else
2966 1.5.2.1 martin snprintf (buf, size, "[%s], #%d", base, opnd->addr.offset.imm);
2967 1.5.2.1 martin }
2968 1.5.2.1 martin else
2969 1.5.2.1 martin {
2970 1.5.2.1 martin if (opnd->shifter.operator_present)
2971 1.5.2.1 martin {
2972 1.5.2.1 martin assert (opnd->shifter.kind == AARCH64_MOD_MUL_VL);
2973 1.5.2.1 martin snprintf (buf, size, "[%s, #%d, mul vl]",
2974 1.5.2.1 martin base, opnd->addr.offset.imm);
2975 1.5.2.1 martin }
2976 1.5.2.1 martin else if (opnd->addr.offset.imm)
2977 1.5.2.1 martin snprintf (buf, size, "[%s, #%d]", base, opnd->addr.offset.imm);
2978 1.5.2.1 martin else
2979 1.5.2.1 martin snprintf (buf, size, "[%s]", base);
2980 1.1 christos }
2981 1.5.2.1 martin }
2982 1.5.2.1 martin
2983 1.1 christos /* Produce the string representation of the register offset address operand
2984 1.1 christos *OPND in the buffer pointed by BUF of size SIZE. BASE and OFFSET are
2985 1.5.2.1 martin the names of the base and offset registers. */
2986 1.5.2.1 martin static void
2987 1.1 christos print_register_offset_address (char *buf, size_t size,
2988 1.5 christos const aarch64_opnd_info *opnd,
2989 1.1 christos const char *base, const char *offset)
2990 1.1 christos {
2991 1.1 christos char tb[16]; /* Temporary buffer. */
2992 1.1 christos bfd_boolean print_extend_p = TRUE;
2993 1.1 christos bfd_boolean print_amount_p = TRUE;
2994 1.1 christos const char *shift_name = aarch64_operand_modifiers[opnd->shifter.kind].name;
2995 1.1 christos
2996 1.1 christos if (!opnd->shifter.amount && (opnd->qualifier != AARCH64_OPND_QLF_S_B
2997 1.1 christos || !opnd->shifter.amount_present))
2998 1.1 christos {
2999 1.1 christos /* Not print the shift/extend amount when the amount is zero and
3000 1.1 christos when it is not the special case of 8-bit load/store instruction. */
3001 1.5.2.1 martin print_amount_p = FALSE;
3002 1.1 christos /* Likewise, no need to print the shift operator LSL in such a
3003 1.1 christos situation. */
3004 1.1 christos if (opnd->shifter.kind == AARCH64_MOD_LSL)
3005 1.1 christos print_extend_p = FALSE;
3006 1.1 christos }
3007 1.1 christos
3008 1.1 christos /* Prepare for the extend/shift. */
3009 1.5.2.1 martin if (print_extend_p)
3010 1.5.2.1 martin {
3011 1.5.2.1 martin if (print_amount_p)
3012 1.1 christos snprintf (tb, sizeof (tb), ", %s #%" PRIi64, shift_name,
3013 1.5.2.1 martin /* PR 21096: The %100 is to silence a warning about possible truncation. */
3014 1.1 christos (opnd->shifter.amount % 100));
3015 1.1 christos else
3016 1.1 christos snprintf (tb, sizeof (tb), ", %s", shift_name);
3017 1.1 christos }
3018 1.5.2.1 martin else
3019 1.1 christos tb[0] = '\0';
3020 1.1 christos
3021 1.1 christos snprintf (buf, size, "[%s, %s%s]", base, offset, tb);
3022 1.1 christos }
3023 1.1 christos
3024 1.1 christos /* Generate the string representation of the operand OPNDS[IDX] for OPCODE
3025 1.1 christos in *BUF. The caller should pass in the maximum size of *BUF in SIZE.
3026 1.1 christos PC, PCREL_P and ADDRESS are used to pass in and return information about
3027 1.1 christos the PC-relative address calculation, where the PC value is passed in
3028 1.1 christos PC. If the operand is pc-relative related, *PCREL_P (if PCREL_P non-NULL)
3029 1.1 christos will return 1 and *ADDRESS (if ADDRESS non-NULL) will return the
3030 1.1 christos calculated address; otherwise, *PCREL_P (if PCREL_P non-NULL) returns 0.
3031 1.1 christos
3032 1.1 christos The function serves both the disassembler and the assembler diagnostics
3033 1.1 christos issuer, which is the reason why it lives in this file. */
3034 1.1 christos
3035 1.1 christos void
3036 1.5.2.1 martin aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
3037 1.1 christos const aarch64_opcode *opcode,
3038 1.5.2.1 martin const aarch64_opnd_info *opnds, int idx, int *pcrel_p,
3039 1.1 christos bfd_vma *address, char** notes ATTRIBUTE_UNUSED)
3040 1.1 christos {
3041 1.1 christos unsigned int i, num_conds;
3042 1.5.2.1 martin const char *name = NULL;
3043 1.1 christos const aarch64_opnd_info *opnd = opnds + idx;
3044 1.1 christos enum aarch64_modifier_kind kind;
3045 1.1 christos uint64_t addr, enum_value;
3046 1.1 christos
3047 1.1 christos buf[0] = '\0';
3048 1.1 christos if (pcrel_p)
3049 1.1 christos *pcrel_p = 0;
3050 1.1 christos
3051 1.1 christos switch (opnd->type)
3052 1.1 christos {
3053 1.1 christos case AARCH64_OPND_Rd:
3054 1.1 christos case AARCH64_OPND_Rn:
3055 1.1 christos case AARCH64_OPND_Rm:
3056 1.1 christos case AARCH64_OPND_Rt:
3057 1.1 christos case AARCH64_OPND_Rt2:
3058 1.3 christos case AARCH64_OPND_Rs:
3059 1.5.2.1 martin case AARCH64_OPND_Ra:
3060 1.1 christos case AARCH64_OPND_Rt_SYS:
3061 1.5.2.1 martin case AARCH64_OPND_PAIRREG:
3062 1.1 christos case AARCH64_OPND_SVE_Rm:
3063 1.5.2.1 martin /* The optional-ness of <Xt> in e.g. IC <ic_op>{, <Xt>} is determined by
3064 1.5.2.1 martin the <ic_op>, therefore we use opnd->present to override the
3065 1.5.2.1 martin generic optional-ness information. */
3066 1.5.2.1 martin if (opnd->type == AARCH64_OPND_Rt_SYS)
3067 1.5.2.1 martin {
3068 1.1 christos if (!opnd->present)
3069 1.5.2.1 martin break;
3070 1.5.2.1 martin }
3071 1.5.2.1 martin /* Omit the operand, e.g. RET. */
3072 1.1 christos else if (optional_operand_p (opcode, idx)
3073 1.1 christos && (opnd->reg.regno
3074 1.1 christos == get_optional_operand_default_value (opcode)))
3075 1.1 christos break;
3076 1.1 christos assert (opnd->qualifier == AARCH64_OPND_QLF_W
3077 1.1 christos || opnd->qualifier == AARCH64_OPND_QLF_X);
3078 1.1 christos snprintf (buf, size, "%s",
3079 1.1 christos get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
3080 1.1 christos break;
3081 1.5.2.1 martin
3082 1.5.2.1 martin case AARCH64_OPND_Rd_SP:
3083 1.1 christos case AARCH64_OPND_Rn_SP:
3084 1.1 christos case AARCH64_OPND_SVE_Rn_SP:
3085 1.1 christos case AARCH64_OPND_Rm_SP:
3086 1.1 christos assert (opnd->qualifier == AARCH64_OPND_QLF_W
3087 1.1 christos || opnd->qualifier == AARCH64_OPND_QLF_WSP
3088 1.1 christos || opnd->qualifier == AARCH64_OPND_QLF_X
3089 1.1 christos || opnd->qualifier == AARCH64_OPND_QLF_SP);
3090 1.1 christos snprintf (buf, size, "%s",
3091 1.1 christos get_int_reg_name (opnd->reg.regno, opnd->qualifier, 1));
3092 1.1 christos break;
3093 1.1 christos
3094 1.1 christos case AARCH64_OPND_Rm_EXT:
3095 1.1 christos kind = opnd->shifter.kind;
3096 1.1 christos assert (idx == 1 || idx == 2);
3097 1.1 christos if ((aarch64_stack_pointer_p (opnds)
3098 1.1 christos || (idx == 2 && aarch64_stack_pointer_p (opnds + 1)))
3099 1.1 christos && ((opnd->qualifier == AARCH64_OPND_QLF_W
3100 1.1 christos && opnds[0].qualifier == AARCH64_OPND_QLF_W
3101 1.1 christos && kind == AARCH64_MOD_UXTW)
3102 1.1 christos || (opnd->qualifier == AARCH64_OPND_QLF_X
3103 1.1 christos && kind == AARCH64_MOD_UXTX)))
3104 1.1 christos {
3105 1.1 christos /* 'LSL' is the preferred form in this case. */
3106 1.1 christos kind = AARCH64_MOD_LSL;
3107 1.1 christos if (opnd->shifter.amount == 0)
3108 1.1 christos {
3109 1.1 christos /* Shifter omitted. */
3110 1.1 christos snprintf (buf, size, "%s",
3111 1.1 christos get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
3112 1.1 christos break;
3113 1.5.2.1 martin }
3114 1.1 christos }
3115 1.1 christos if (opnd->shifter.amount)
3116 1.1 christos snprintf (buf, size, "%s, %s #%" PRIi64,
3117 1.1 christos get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
3118 1.1 christos aarch64_operand_modifiers[kind].name,
3119 1.1 christos opnd->shifter.amount);
3120 1.1 christos else
3121 1.1 christos snprintf (buf, size, "%s, %s",
3122 1.1 christos get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
3123 1.1 christos aarch64_operand_modifiers[kind].name);
3124 1.1 christos break;
3125 1.1 christos
3126 1.1 christos case AARCH64_OPND_Rm_SFT:
3127 1.1 christos assert (opnd->qualifier == AARCH64_OPND_QLF_W
3128 1.1 christos || opnd->qualifier == AARCH64_OPND_QLF_X);
3129 1.1 christos if (opnd->shifter.amount == 0 && opnd->shifter.kind == AARCH64_MOD_LSL)
3130 1.5.2.1 martin snprintf (buf, size, "%s",
3131 1.1 christos get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
3132 1.1 christos else
3133 1.1 christos snprintf (buf, size, "%s, %s #%" PRIi64,
3134 1.1 christos get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
3135 1.1 christos aarch64_operand_modifiers[opnd->shifter.kind].name,
3136 1.1 christos opnd->shifter.amount);
3137 1.1 christos break;
3138 1.1 christos
3139 1.1 christos case AARCH64_OPND_Fd:
3140 1.1 christos case AARCH64_OPND_Fn:
3141 1.1 christos case AARCH64_OPND_Fm:
3142 1.1 christos case AARCH64_OPND_Fa:
3143 1.1 christos case AARCH64_OPND_Ft:
3144 1.1 christos case AARCH64_OPND_Ft2:
3145 1.5.2.1 martin case AARCH64_OPND_Sd:
3146 1.5.2.1 martin case AARCH64_OPND_Sn:
3147 1.5.2.1 martin case AARCH64_OPND_Sm:
3148 1.5.2.1 martin case AARCH64_OPND_SVE_VZn:
3149 1.1 christos case AARCH64_OPND_SVE_Vd:
3150 1.1 christos case AARCH64_OPND_SVE_Vm:
3151 1.1 christos case AARCH64_OPND_SVE_Vn:
3152 1.1 christos snprintf (buf, size, "%s%d", aarch64_get_qualifier_name (opnd->qualifier),
3153 1.5.2.1 martin opnd->reg.regno);
3154 1.1 christos break;
3155 1.1 christos
3156 1.1 christos case AARCH64_OPND_Va:
3157 1.1 christos case AARCH64_OPND_Vd:
3158 1.1 christos case AARCH64_OPND_Vn:
3159 1.1 christos case AARCH64_OPND_Vm:
3160 1.1 christos snprintf (buf, size, "v%d.%s", opnd->reg.regno,
3161 1.1 christos aarch64_get_qualifier_name (opnd->qualifier));
3162 1.1 christos break;
3163 1.1 christos
3164 1.5.2.1 martin case AARCH64_OPND_Ed:
3165 1.5.2.1 martin case AARCH64_OPND_En:
3166 1.5 christos case AARCH64_OPND_Em:
3167 1.1 christos case AARCH64_OPND_Em16:
3168 1.1 christos case AARCH64_OPND_SM3_IMM2:
3169 1.1 christos snprintf (buf, size, "v%d.%s[%" PRIi64 "]", opnd->reglane.regno,
3170 1.1 christos aarch64_get_qualifier_name (opnd->qualifier),
3171 1.1 christos opnd->reglane.index);
3172 1.1 christos break;
3173 1.1 christos
3174 1.1 christos case AARCH64_OPND_VdD1:
3175 1.1 christos case AARCH64_OPND_VnD1:
3176 1.1 christos snprintf (buf, size, "v%d.d[1]", opnd->reg.regno);
3177 1.1 christos break;
3178 1.1 christos
3179 1.1 christos case AARCH64_OPND_LVn:
3180 1.5.2.1 martin case AARCH64_OPND_LVt:
3181 1.5.2.1 martin case AARCH64_OPND_LVt_AL:
3182 1.5.2.1 martin case AARCH64_OPND_LEt:
3183 1.5.2.1 martin print_register_list (buf, size, opnd, "v");
3184 1.5.2.1 martin break;
3185 1.5.2.1 martin
3186 1.5.2.1 martin case AARCH64_OPND_SVE_Pd:
3187 1.5.2.1 martin case AARCH64_OPND_SVE_Pg3:
3188 1.5.2.1 martin case AARCH64_OPND_SVE_Pg4_5:
3189 1.5.2.1 martin case AARCH64_OPND_SVE_Pg4_10:
3190 1.5.2.1 martin case AARCH64_OPND_SVE_Pg4_16:
3191 1.5.2.1 martin case AARCH64_OPND_SVE_Pm:
3192 1.5.2.1 martin case AARCH64_OPND_SVE_Pn:
3193 1.5.2.1 martin case AARCH64_OPND_SVE_Pt:
3194 1.5.2.1 martin if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
3195 1.5.2.1 martin snprintf (buf, size, "p%d", opnd->reg.regno);
3196 1.5.2.1 martin else if (opnd->qualifier == AARCH64_OPND_QLF_P_Z
3197 1.5.2.1 martin || opnd->qualifier == AARCH64_OPND_QLF_P_M)
3198 1.5.2.1 martin snprintf (buf, size, "p%d/%s", opnd->reg.regno,
3199 1.5.2.1 martin aarch64_get_qualifier_name (opnd->qualifier));
3200 1.5.2.1 martin else
3201 1.5.2.1 martin snprintf (buf, size, "p%d.%s", opnd->reg.regno,
3202 1.5.2.1 martin aarch64_get_qualifier_name (opnd->qualifier));
3203 1.5.2.1 martin break;
3204 1.5.2.1 martin
3205 1.5.2.1 martin case AARCH64_OPND_SVE_Za_5:
3206 1.5.2.1 martin case AARCH64_OPND_SVE_Za_16:
3207 1.5.2.1 martin case AARCH64_OPND_SVE_Zd:
3208 1.5.2.1 martin case AARCH64_OPND_SVE_Zm_5:
3209 1.5.2.1 martin case AARCH64_OPND_SVE_Zm_16:
3210 1.5.2.1 martin case AARCH64_OPND_SVE_Zn:
3211 1.5.2.1 martin case AARCH64_OPND_SVE_Zt:
3212 1.5.2.1 martin if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
3213 1.5.2.1 martin snprintf (buf, size, "z%d", opnd->reg.regno);
3214 1.5.2.1 martin else
3215 1.5.2.1 martin snprintf (buf, size, "z%d.%s", opnd->reg.regno,
3216 1.5.2.1 martin aarch64_get_qualifier_name (opnd->qualifier));
3217 1.5.2.1 martin break;
3218 1.5.2.1 martin
3219 1.1 christos case AARCH64_OPND_SVE_ZnxN:
3220 1.1 christos case AARCH64_OPND_SVE_ZtxN:
3221 1.5.2.1 martin print_register_list (buf, size, opnd, "z");
3222 1.5.2.1 martin break;
3223 1.5.2.1 martin
3224 1.5.2.1 martin case AARCH64_OPND_SVE_Zm3_INDEX:
3225 1.5.2.1 martin case AARCH64_OPND_SVE_Zm3_22_INDEX:
3226 1.5.2.1 martin case AARCH64_OPND_SVE_Zm4_INDEX:
3227 1.5.2.1 martin case AARCH64_OPND_SVE_Zn_INDEX:
3228 1.5.2.1 martin snprintf (buf, size, "z%d.%s[%" PRIi64 "]", opnd->reglane.regno,
3229 1.5.2.1 martin aarch64_get_qualifier_name (opnd->qualifier),
3230 1.5.2.1 martin opnd->reglane.index);
3231 1.5.2.1 martin break;
3232 1.5.2.1 martin
3233 1.1 christos case AARCH64_OPND_CRn:
3234 1.1 christos case AARCH64_OPND_CRm:
3235 1.1 christos snprintf (buf, size, "C%" PRIi64, opnd->imm.value);
3236 1.5.2.1 martin break;
3237 1.1 christos
3238 1.5.2.1 martin case AARCH64_OPND_IDX:
3239 1.1 christos case AARCH64_OPND_MASK:
3240 1.1 christos case AARCH64_OPND_IMM:
3241 1.1 christos case AARCH64_OPND_IMM_2:
3242 1.1 christos case AARCH64_OPND_WIDTH:
3243 1.1 christos case AARCH64_OPND_UIMM3_OP1:
3244 1.1 christos case AARCH64_OPND_UIMM3_OP2:
3245 1.1 christos case AARCH64_OPND_BIT_NUM:
3246 1.1 christos case AARCH64_OPND_IMM_VLSL:
3247 1.1 christos case AARCH64_OPND_IMM_VLSR:
3248 1.1 christos case AARCH64_OPND_SHLL_IMM:
3249 1.1 christos case AARCH64_OPND_IMM0:
3250 1.5.2.1 martin case AARCH64_OPND_IMMR:
3251 1.5.2.1 martin case AARCH64_OPND_IMMS:
3252 1.5.2.1 martin case AARCH64_OPND_FBITS:
3253 1.5.2.1 martin case AARCH64_OPND_SIMM5:
3254 1.5.2.1 martin case AARCH64_OPND_SVE_SHLIMM_PRED:
3255 1.5.2.1 martin case AARCH64_OPND_SVE_SHLIMM_UNPRED:
3256 1.5.2.1 martin case AARCH64_OPND_SVE_SHRIMM_PRED:
3257 1.5.2.1 martin case AARCH64_OPND_SVE_SHRIMM_UNPRED:
3258 1.5.2.1 martin case AARCH64_OPND_SVE_SIMM5:
3259 1.5.2.1 martin case AARCH64_OPND_SVE_SIMM5B:
3260 1.5.2.1 martin case AARCH64_OPND_SVE_SIMM6:
3261 1.5.2.1 martin case AARCH64_OPND_SVE_SIMM8:
3262 1.5.2.1 martin case AARCH64_OPND_SVE_UIMM3:
3263 1.5.2.1 martin case AARCH64_OPND_SVE_UIMM7:
3264 1.5.2.1 martin case AARCH64_OPND_SVE_UIMM8:
3265 1.5.2.1 martin case AARCH64_OPND_SVE_UIMM8_53:
3266 1.5.2.1 martin case AARCH64_OPND_IMM_ROT1:
3267 1.5.2.1 martin case AARCH64_OPND_IMM_ROT2:
3268 1.1 christos case AARCH64_OPND_IMM_ROT3:
3269 1.1 christos case AARCH64_OPND_SVE_IMM_ROT1:
3270 1.1 christos case AARCH64_OPND_SVE_IMM_ROT2:
3271 1.5.2.1 martin snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
3272 1.5.2.1 martin break;
3273 1.5.2.1 martin
3274 1.5.2.1 martin case AARCH64_OPND_SVE_I1_HALF_ONE:
3275 1.5.2.1 martin case AARCH64_OPND_SVE_I1_HALF_TWO:
3276 1.5.2.1 martin case AARCH64_OPND_SVE_I1_ZERO_ONE:
3277 1.5.2.1 martin {
3278 1.5.2.1 martin single_conv_t c;
3279 1.5.2.1 martin c.i = opnd->imm.value;
3280 1.5.2.1 martin snprintf (buf, size, "#%.1f", c.f);
3281 1.5.2.1 martin break;
3282 1.5.2.1 martin }
3283 1.5.2.1 martin
3284 1.5.2.1 martin case AARCH64_OPND_SVE_PATTERN:
3285 1.5.2.1 martin if (optional_operand_p (opcode, idx)
3286 1.5.2.1 martin && opnd->imm.value == get_optional_operand_default_value (opcode))
3287 1.5.2.1 martin break;
3288 1.5.2.1 martin enum_value = opnd->imm.value;
3289 1.5.2.1 martin assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
3290 1.5.2.1 martin if (aarch64_sve_pattern_array[enum_value])
3291 1.5.2.1 martin snprintf (buf, size, "%s", aarch64_sve_pattern_array[enum_value]);
3292 1.5.2.1 martin else
3293 1.5.2.1 martin snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
3294 1.5.2.1 martin break;
3295 1.5.2.1 martin
3296 1.5.2.1 martin case AARCH64_OPND_SVE_PATTERN_SCALED:
3297 1.5.2.1 martin if (optional_operand_p (opcode, idx)
3298 1.5.2.1 martin && !opnd->shifter.operator_present
3299 1.5.2.1 martin && opnd->imm.value == get_optional_operand_default_value (opcode))
3300 1.5.2.1 martin break;
3301 1.5.2.1 martin enum_value = opnd->imm.value;
3302 1.5.2.1 martin assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
3303 1.5.2.1 martin if (aarch64_sve_pattern_array[opnd->imm.value])
3304 1.5.2.1 martin snprintf (buf, size, "%s", aarch64_sve_pattern_array[opnd->imm.value]);
3305 1.5.2.1 martin else
3306 1.5.2.1 martin snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
3307 1.5.2.1 martin if (opnd->shifter.operator_present)
3308 1.5.2.1 martin {
3309 1.5.2.1 martin size_t len = strlen (buf);
3310 1.5.2.1 martin snprintf (buf + len, size - len, ", %s #%" PRIi64,
3311 1.5.2.1 martin aarch64_operand_modifiers[opnd->shifter.kind].name,
3312 1.5.2.1 martin opnd->shifter.amount);
3313 1.5.2.1 martin }
3314 1.5.2.1 martin break;
3315 1.5.2.1 martin
3316 1.5.2.1 martin case AARCH64_OPND_SVE_PRFOP:
3317 1.5.2.1 martin enum_value = opnd->imm.value;
3318 1.5.2.1 martin assert (enum_value < ARRAY_SIZE (aarch64_sve_prfop_array));
3319 1.5.2.1 martin if (aarch64_sve_prfop_array[enum_value])
3320 1.5.2.1 martin snprintf (buf, size, "%s", aarch64_sve_prfop_array[enum_value]);
3321 1.5.2.1 martin else
3322 1.1 christos snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
3323 1.1 christos break;
3324 1.1 christos
3325 1.1 christos case AARCH64_OPND_IMM_MOV:
3326 1.1 christos switch (aarch64_get_qualifier_esize (opnds[0].qualifier))
3327 1.1 christos {
3328 1.1 christos case 4: /* e.g. MOV Wd, #<imm32>. */
3329 1.1 christos {
3330 1.1 christos int imm32 = opnd->imm.value;
3331 1.1 christos snprintf (buf, size, "#0x%-20x\t// #%d", imm32, imm32);
3332 1.1 christos }
3333 1.1 christos break;
3334 1.1 christos case 8: /* e.g. MOV Xd, #<imm64>. */
3335 1.1 christos snprintf (buf, size, "#0x%-20" PRIx64 "\t// #%" PRIi64,
3336 1.1 christos opnd->imm.value, opnd->imm.value);
3337 1.1 christos break;
3338 1.1 christos default: assert (0);
3339 1.1 christos }
3340 1.1 christos break;
3341 1.1 christos
3342 1.1 christos case AARCH64_OPND_FPIMM0:
3343 1.1 christos snprintf (buf, size, "#0.0");
3344 1.1 christos break;
3345 1.1 christos
3346 1.5.2.1 martin case AARCH64_OPND_LIMM:
3347 1.5.2.1 martin case AARCH64_OPND_AIMM:
3348 1.5.2.1 martin case AARCH64_OPND_HALF:
3349 1.1 christos case AARCH64_OPND_SVE_INV_LIMM:
3350 1.5.2.1 martin case AARCH64_OPND_SVE_LIMM:
3351 1.1 christos case AARCH64_OPND_SVE_LIMM_MOV:
3352 1.1 christos if (opnd->shifter.amount)
3353 1.1 christos snprintf (buf, size, "#0x%" PRIx64 ", lsl #%" PRIi64, opnd->imm.value,
3354 1.1 christos opnd->shifter.amount);
3355 1.1 christos else
3356 1.1 christos snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
3357 1.1 christos break;
3358 1.1 christos
3359 1.1 christos case AARCH64_OPND_SIMD_IMM:
3360 1.1 christos case AARCH64_OPND_SIMD_IMM_SFT:
3361 1.1 christos if ((! opnd->shifter.amount && opnd->shifter.kind == AARCH64_MOD_LSL)
3362 1.5.2.1 martin || opnd->shifter.kind == AARCH64_MOD_NONE)
3363 1.1 christos snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
3364 1.1 christos else
3365 1.1 christos snprintf (buf, size, "#0x%" PRIx64 ", %s #%" PRIi64, opnd->imm.value,
3366 1.1 christos aarch64_operand_modifiers[opnd->shifter.kind].name,
3367 1.5.2.1 martin opnd->shifter.amount);
3368 1.5.2.1 martin break;
3369 1.5.2.1 martin
3370 1.5.2.1 martin case AARCH64_OPND_SVE_AIMM:
3371 1.5.2.1 martin case AARCH64_OPND_SVE_ASIMM:
3372 1.5.2.1 martin if (opnd->shifter.amount)
3373 1.5.2.1 martin snprintf (buf, size, "#%" PRIi64 ", lsl #%" PRIi64, opnd->imm.value,
3374 1.5.2.1 martin opnd->shifter.amount);
3375 1.5.2.1 martin else
3376 1.1 christos snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
3377 1.1 christos break;
3378 1.5.2.1 martin
3379 1.1 christos case AARCH64_OPND_FPIMM:
3380 1.1 christos case AARCH64_OPND_SIMD_FPIMM:
3381 1.3 christos case AARCH64_OPND_SVE_FPIMM8:
3382 1.3 christos switch (aarch64_get_qualifier_esize (opnds[0].qualifier))
3383 1.3 christos {
3384 1.3 christos case 2: /* e.g. FMOV <Hd>, #<imm>. */
3385 1.3 christos {
3386 1.3 christos half_conv_t c;
3387 1.3 christos c.i = expand_fp_imm (2, opnd->imm.value);
3388 1.1 christos snprintf (buf, size, "#%.18e", c.f);
3389 1.1 christos }
3390 1.1 christos break;
3391 1.3 christos case 4: /* e.g. FMOV <Vd>.4S, #<imm>. */
3392 1.1 christos {
3393 1.1 christos single_conv_t c;
3394 1.1 christos c.i = expand_fp_imm (4, opnd->imm.value);
3395 1.1 christos snprintf (buf, size, "#%.18e", c.f);
3396 1.1 christos }
3397 1.1 christos break;
3398 1.3 christos case 8: /* e.g. FMOV <Sd>, #<imm>. */
3399 1.1 christos {
3400 1.1 christos double_conv_t c;
3401 1.1 christos c.i = expand_fp_imm (8, opnd->imm.value);
3402 1.1 christos snprintf (buf, size, "#%.18e", c.d);
3403 1.1 christos }
3404 1.1 christos break;
3405 1.1 christos default: assert (0);
3406 1.1 christos }
3407 1.1 christos break;
3408 1.1 christos
3409 1.1 christos case AARCH64_OPND_CCMP_IMM:
3410 1.1 christos case AARCH64_OPND_NZCV:
3411 1.1 christos case AARCH64_OPND_EXCEPTION:
3412 1.1 christos case AARCH64_OPND_UIMM4:
3413 1.1 christos case AARCH64_OPND_UIMM7:
3414 1.1 christos if (optional_operand_p (opcode, idx) == TRUE
3415 1.1 christos && (opnd->imm.value ==
3416 1.1 christos (int64_t) get_optional_operand_default_value (opcode)))
3417 1.1 christos /* Omit the operand, e.g. DCPS1. */
3418 1.1 christos break;
3419 1.1 christos snprintf (buf, size, "#0x%x", (unsigned int)opnd->imm.value);
3420 1.3 christos break;
3421 1.1 christos
3422 1.5.2.1 martin case AARCH64_OPND_COND:
3423 1.5.2.1 martin case AARCH64_OPND_COND1:
3424 1.5.2.1 martin snprintf (buf, size, "%s", opnd->cond->names[0]);
3425 1.5.2.1 martin num_conds = ARRAY_SIZE (opnd->cond->names);
3426 1.5.2.1 martin for (i = 1; i < num_conds && opnd->cond->names[i]; ++i)
3427 1.5.2.1 martin {
3428 1.5.2.1 martin size_t len = strlen (buf);
3429 1.5.2.1 martin if (i == 1)
3430 1.5.2.1 martin snprintf (buf + len, size - len, " // %s = %s",
3431 1.5.2.1 martin opnd->cond->names[0], opnd->cond->names[i]);
3432 1.5.2.1 martin else
3433 1.1 christos snprintf (buf + len, size - len, ", %s",
3434 1.1 christos opnd->cond->names[i]);
3435 1.1 christos }
3436 1.1 christos break;
3437 1.1 christos
3438 1.1 christos case AARCH64_OPND_ADDR_ADRP:
3439 1.1 christos addr = ((pc + AARCH64_PCREL_OFFSET) & ~(uint64_t)0xfff)
3440 1.1 christos + opnd->imm.value;
3441 1.1 christos if (pcrel_p)
3442 1.1 christos *pcrel_p = 1;
3443 1.1 christos if (address)
3444 1.1 christos *address = addr;
3445 1.1 christos /* This is not necessary during the disassembling, as print_address_func
3446 1.1 christos in the disassemble_info will take care of the printing. But some
3447 1.1 christos other callers may be still interested in getting the string in *STR,
3448 1.1 christos so here we do snprintf regardless. */
3449 1.1 christos snprintf (buf, size, "#0x%" PRIx64, addr);
3450 1.1 christos break;
3451 1.1 christos
3452 1.1 christos case AARCH64_OPND_ADDR_PCREL14:
3453 1.1 christos case AARCH64_OPND_ADDR_PCREL19:
3454 1.1 christos case AARCH64_OPND_ADDR_PCREL21:
3455 1.1 christos case AARCH64_OPND_ADDR_PCREL26:
3456 1.1 christos addr = pc + AARCH64_PCREL_OFFSET + opnd->imm.value;
3457 1.1 christos if (pcrel_p)
3458 1.1 christos *pcrel_p = 1;
3459 1.1 christos if (address)
3460 1.1 christos *address = addr;
3461 1.1 christos /* This is not necessary during the disassembling, as print_address_func
3462 1.1 christos in the disassemble_info will take care of the printing. But some
3463 1.1 christos other callers may be still interested in getting the string in *STR,
3464 1.1 christos so here we do snprintf regardless. */
3465 1.1 christos snprintf (buf, size, "#0x%" PRIx64, addr);
3466 1.1 christos break;
3467 1.1 christos
3468 1.1 christos case AARCH64_OPND_ADDR_SIMPLE:
3469 1.1 christos case AARCH64_OPND_SIMD_ADDR_SIMPLE:
3470 1.1 christos case AARCH64_OPND_SIMD_ADDR_POST:
3471 1.1 christos name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
3472 1.1 christos if (opnd->type == AARCH64_OPND_SIMD_ADDR_POST)
3473 1.1 christos {
3474 1.1 christos if (opnd->addr.offset.is_reg)
3475 1.1 christos snprintf (buf, size, "[%s], x%d", name, opnd->addr.offset.regno);
3476 1.1 christos else
3477 1.1 christos snprintf (buf, size, "[%s], #%d", name, opnd->addr.offset.imm);
3478 1.1 christos }
3479 1.1 christos else
3480 1.1 christos snprintf (buf, size, "[%s]", name);
3481 1.5.2.1 martin break;
3482 1.5.2.1 martin
3483 1.5.2.1 martin case AARCH64_OPND_ADDR_REGOFF:
3484 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_R:
3485 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RR:
3486 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RR_LSL1:
3487 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RR_LSL2:
3488 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RR_LSL3:
3489 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RX:
3490 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RX_LSL1:
3491 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RX_LSL2:
3492 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RX_LSL3:
3493 1.5.2.1 martin print_register_offset_address
3494 1.5.2.1 martin (buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
3495 1.5.2.1 martin get_offset_int_reg_name (opnd));
3496 1.5.2.1 martin break;
3497 1.5.2.1 martin
3498 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ:
3499 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_LSL1:
3500 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_LSL2:
3501 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_LSL3:
3502 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_XTW_14:
3503 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_XTW_22:
3504 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_XTW1_14:
3505 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_XTW1_22:
3506 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_XTW2_14:
3507 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_XTW2_22:
3508 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_XTW3_14:
3509 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RZ_XTW3_22:
3510 1.1 christos print_register_offset_address
3511 1.1 christos (buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
3512 1.1 christos get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
3513 1.1 christos break;
3514 1.1 christos
3515 1.5.2.1 martin case AARCH64_OPND_ADDR_SIMM7:
3516 1.5.2.1 martin case AARCH64_OPND_ADDR_SIMM9:
3517 1.5.2.1 martin case AARCH64_OPND_ADDR_SIMM9_2:
3518 1.5.2.1 martin case AARCH64_OPND_ADDR_SIMM10:
3519 1.5.2.1 martin case AARCH64_OPND_ADDR_OFFSET:
3520 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_S4x16:
3521 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_S4xVL:
3522 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_S4x2xVL:
3523 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_S4x3xVL:
3524 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_S4x4xVL:
3525 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_S6xVL:
3526 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_S9xVL:
3527 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_U6:
3528 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_U6x2:
3529 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_U6x4:
3530 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_RI_U6x8:
3531 1.5.2.1 martin print_immediate_offset_address
3532 1.5.2.1 martin (buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1));
3533 1.5.2.1 martin break;
3534 1.5.2.1 martin
3535 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_ZI_U5:
3536 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_ZI_U5x2:
3537 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_ZI_U5x4:
3538 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_ZI_U5x8:
3539 1.5.2.1 martin print_immediate_offset_address
3540 1.5.2.1 martin (buf, size, opnd,
3541 1.5.2.1 martin get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier));
3542 1.5.2.1 martin break;
3543 1.5.2.1 martin
3544 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_ZZ_LSL:
3545 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_ZZ_SXTW:
3546 1.5.2.1 martin case AARCH64_OPND_SVE_ADDR_ZZ_UXTW:
3547 1.5.2.1 martin print_register_offset_address
3548 1.1 christos (buf, size, opnd,
3549 1.1 christos get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
3550 1.1 christos get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
3551 1.1 christos break;
3552 1.1 christos
3553 1.5.2.1 martin case AARCH64_OPND_ADDR_UIMM12:
3554 1.1 christos name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
3555 1.1 christos if (opnd->addr.offset.imm)
3556 1.1 christos snprintf (buf, size, "[%s, #%d]", name, opnd->addr.offset.imm);
3557 1.1 christos else
3558 1.1 christos snprintf (buf, size, "[%s]", name);
3559 1.1 christos break;
3560 1.5.2.1 martin
3561 1.5.2.1 martin case AARCH64_OPND_SYSREG:
3562 1.5.2.1 martin for (i = 0; aarch64_sys_regs[i].name; ++i)
3563 1.5.2.1 martin {
3564 1.5.2.1 martin bfd_boolean exact_match
3565 1.5.2.1 martin = (aarch64_sys_regs[i].flags & opnd->sysreg.flags)
3566 1.5.2.1 martin == opnd->sysreg.flags;
3567 1.5.2.1 martin
3568 1.5.2.1 martin /* Try and find an exact match, But if that fails, return the first
3569 1.5.2.1 martin partial match that was found. */
3570 1.5.2.1 martin if (aarch64_sys_regs[i].value == opnd->sysreg.value
3571 1.5.2.1 martin && ! aarch64_sys_reg_deprecated_p (&aarch64_sys_regs[i])
3572 1.5.2.1 martin && (name == NULL || exact_match))
3573 1.5.2.1 martin {
3574 1.5.2.1 martin name = aarch64_sys_regs[i].name;
3575 1.5.2.1 martin if (exact_match)
3576 1.5.2.1 martin {
3577 1.5.2.1 martin if (notes)
3578 1.5.2.1 martin *notes = NULL;
3579 1.5.2.1 martin break;
3580 1.5.2.1 martin }
3581 1.5.2.1 martin
3582 1.5.2.1 martin /* If we didn't match exactly, that means the presense of a flag
3583 1.5.2.1 martin indicates what we didn't want for this instruction. e.g. If
3584 1.5.2.1 martin F_REG_READ is there, that means we were looking for a write
3585 1.5.2.1 martin register. See aarch64_ext_sysreg. */
3586 1.5.2.1 martin if (aarch64_sys_regs[i].flags & F_REG_WRITE)
3587 1.5.2.1 martin *notes = _("reading from a write-only register.");
3588 1.5.2.1 martin else if (aarch64_sys_regs[i].flags & F_REG_READ)
3589 1.5.2.1 martin *notes = _("writing to a read-only register.");
3590 1.5.2.1 martin }
3591 1.5.2.1 martin }
3592 1.1 christos
3593 1.1 christos if (name)
3594 1.1 christos snprintf (buf, size, "%s", name);
3595 1.5.2.1 martin else
3596 1.1 christos {
3597 1.1 christos /* Implementation defined system register. */
3598 1.1 christos unsigned int value = opnd->sysreg.value;
3599 1.1 christos snprintf (buf, size, "s%u_%u_c%u_c%u_%u", (value >> 14) & 0x3,
3600 1.1 christos (value >> 11) & 0x7, (value >> 7) & 0xf, (value >> 3) & 0xf,
3601 1.1 christos value & 0x7);
3602 1.1 christos }
3603 1.1 christos break;
3604 1.1 christos
3605 1.1 christos case AARCH64_OPND_PSTATEFIELD:
3606 1.1 christos for (i = 0; aarch64_pstatefields[i].name; ++i)
3607 1.1 christos if (aarch64_pstatefields[i].value == opnd->pstatefield)
3608 1.1 christos break;
3609 1.1 christos assert (aarch64_pstatefields[i].name);
3610 1.1 christos snprintf (buf, size, "%s", aarch64_pstatefields[i].name);
3611 1.1 christos break;
3612 1.1 christos
3613 1.1 christos case AARCH64_OPND_SYSREG_AT:
3614 1.3 christos case AARCH64_OPND_SYSREG_DC:
3615 1.1 christos case AARCH64_OPND_SYSREG_IC:
3616 1.1 christos case AARCH64_OPND_SYSREG_TLBI:
3617 1.1 christos snprintf (buf, size, "%s", opnd->sysins_op->name);
3618 1.1 christos break;
3619 1.1 christos
3620 1.1 christos case AARCH64_OPND_BARRIER:
3621 1.1 christos snprintf (buf, size, "%s", opnd->barrier->name);
3622 1.1 christos break;
3623 1.1 christos
3624 1.1 christos case AARCH64_OPND_BARRIER_ISB:
3625 1.1 christos /* Operand can be omitted, e.g. in DCPS1. */
3626 1.1 christos if (! optional_operand_p (opcode, idx)
3627 1.1 christos || (opnd->barrier->value
3628 1.1 christos != get_optional_operand_default_value (opcode)))
3629 1.1 christos snprintf (buf, size, "#0x%x", opnd->barrier->value);
3630 1.1 christos break;
3631 1.1 christos
3632 1.1 christos case AARCH64_OPND_PRFOP:
3633 1.1 christos if (opnd->prfop->name != NULL)
3634 1.1 christos snprintf (buf, size, "%s", opnd->prfop->name);
3635 1.1 christos else
3636 1.3 christos snprintf (buf, size, "#0x%02x", opnd->prfop->value);
3637 1.3 christos break;
3638 1.3 christos
3639 1.3 christos case AARCH64_OPND_BARRIER_PSB:
3640 1.1 christos snprintf (buf, size, "%s", opnd->hint_option->name);
3641 1.1 christos break;
3642 1.1 christos
3643 1.1 christos default:
3644 1.1 christos assert (0);
3645 1.1 christos }
3646 1.1 christos }
3647 1.1 christos
3648 1.1 christos #define CPENC(op0,op1,crn,crm,op2) \
3650 1.1 christos ((((op0) << 19) | ((op1) << 16) | ((crn) << 12) | ((crm) << 8) | ((op2) << 5)) >> 5)
3651 1.1 christos /* for 3.9.3 Instructions for Accessing Special Purpose Registers */
3652 1.1 christos #define CPEN_(op1,crm,op2) CPENC(3,(op1),4,(crm),(op2))
3653 1.1 christos /* for 3.9.10 System Instructions */
3654 1.1 christos #define CPENS(op1,crn,crm,op2) CPENC(1,(op1),(crn),(crm),(op2))
3655 1.1 christos
3656 1.1 christos #define C0 0
3657 1.1 christos #define C1 1
3658 1.1 christos #define C2 2
3659 1.1 christos #define C3 3
3660 1.1 christos #define C4 4
3661 1.1 christos #define C5 5
3662 1.1 christos #define C6 6
3663 1.1 christos #define C7 7
3664 1.1 christos #define C8 8
3665 1.1 christos #define C9 9
3666 1.1 christos #define C10 10
3667 1.1 christos #define C11 11
3668 1.1 christos #define C12 12
3669 1.5.2.1 martin #define C13 13
3670 1.5.2.1 martin #define C14 14
3671 1.3 christos #define C15 15
3672 1.1 christos
3673 1.3 christos /* TODO there is one more issues need to be resolved
3674 1.3 christos 1. handle cpu-implementation-defined system registers. */
3675 1.3 christos const aarch64_sys_reg aarch64_sys_regs [] =
3676 1.3 christos {
3677 1.3 christos { "spsr_el1", CPEN_(0,C0,0), 0 }, /* = spsr_svc */
3678 1.3 christos { "spsr_el12", CPEN_ (5, C0, 0), F_ARCHEXT },
3679 1.3 christos { "elr_el1", CPEN_(0,C0,1), 0 },
3680 1.5.2.1 martin { "elr_el12", CPEN_ (5, C0, 1), F_ARCHEXT },
3681 1.3 christos { "sp_el0", CPEN_(0,C1,0), 0 },
3682 1.3 christos { "spsel", CPEN_(0,C2,0), 0 },
3683 1.3 christos { "daif", CPEN_(3,C2,1), 0 },
3684 1.3 christos { "currentel", CPEN_(0,C2,2), F_REG_READ }, /* RO */
3685 1.3 christos { "pan", CPEN_(0,C2,3), F_ARCHEXT },
3686 1.3 christos { "uao", CPEN_ (0, C2, 4), F_ARCHEXT },
3687 1.3 christos { "nzcv", CPEN_(3,C2,0), 0 },
3688 1.3 christos { "fpcr", CPEN_(3,C4,0), 0 },
3689 1.3 christos { "fpsr", CPEN_(3,C4,1), 0 },
3690 1.3 christos { "dspsr_el0", CPEN_(3,C5,0), 0 },
3691 1.3 christos { "dlr_el0", CPEN_(3,C5,1), 0 },
3692 1.3 christos { "spsr_el2", CPEN_(4,C0,0), 0 }, /* = spsr_hyp */
3693 1.3 christos { "elr_el2", CPEN_(4,C0,1), 0 },
3694 1.3 christos { "sp_el1", CPEN_(4,C1,0), 0 },
3695 1.3 christos { "spsr_irq", CPEN_(4,C3,0), 0 },
3696 1.3 christos { "spsr_abt", CPEN_(4,C3,1), 0 },
3697 1.3 christos { "spsr_und", CPEN_(4,C3,2), 0 },
3698 1.3 christos { "spsr_fiq", CPEN_(4,C3,3), 0 },
3699 1.3 christos { "spsr_el3", CPEN_(6,C0,0), 0 },
3700 1.5.2.1 martin { "elr_el3", CPEN_(6,C0,1), 0 },
3701 1.5.2.1 martin { "sp_el2", CPEN_(6,C1,0), 0 },
3702 1.5.2.1 martin { "spsr_svc", CPEN_(0,C0,0), F_DEPRECATED }, /* = spsr_el1 */
3703 1.5.2.1 martin { "spsr_hyp", CPEN_(4,C0,0), F_DEPRECATED }, /* = spsr_el2 */
3704 1.5.2.1 martin { "midr_el1", CPENC(3,0,C0,C0,0), F_REG_READ }, /* RO */
3705 1.5.2.1 martin { "ctr_el0", CPENC(3,3,C0,C0,1), F_REG_READ }, /* RO */
3706 1.5.2.1 martin { "mpidr_el1", CPENC(3,0,C0,C0,5), F_REG_READ }, /* RO */
3707 1.5.2.1 martin { "revidr_el1", CPENC(3,0,C0,C0,6), F_REG_READ }, /* RO */
3708 1.5.2.1 martin { "aidr_el1", CPENC(3,1,C0,C0,7), F_REG_READ }, /* RO */
3709 1.5.2.1 martin { "dczid_el0", CPENC(3,3,C0,C0,7), F_REG_READ }, /* RO */
3710 1.5.2.1 martin { "id_dfr0_el1", CPENC(3,0,C0,C1,2), F_REG_READ }, /* RO */
3711 1.5.2.1 martin { "id_pfr0_el1", CPENC(3,0,C0,C1,0), F_REG_READ }, /* RO */
3712 1.5.2.1 martin { "id_pfr1_el1", CPENC(3,0,C0,C1,1), F_REG_READ }, /* RO */
3713 1.5.2.1 martin { "id_afr0_el1", CPENC(3,0,C0,C1,3), F_REG_READ }, /* RO */
3714 1.5.2.1 martin { "id_mmfr0_el1", CPENC(3,0,C0,C1,4), F_REG_READ }, /* RO */
3715 1.5.2.1 martin { "id_mmfr1_el1", CPENC(3,0,C0,C1,5), F_REG_READ }, /* RO */
3716 1.5.2.1 martin { "id_mmfr2_el1", CPENC(3,0,C0,C1,6), F_REG_READ }, /* RO */
3717 1.5.2.1 martin { "id_mmfr3_el1", CPENC(3,0,C0,C1,7), F_REG_READ }, /* RO */
3718 1.5.2.1 martin { "id_mmfr4_el1", CPENC(3,0,C0,C2,6), F_REG_READ }, /* RO */
3719 1.5.2.1 martin { "id_isar0_el1", CPENC(3,0,C0,C2,0), F_REG_READ }, /* RO */
3720 1.5.2.1 martin { "id_isar1_el1", CPENC(3,0,C0,C2,1), F_REG_READ }, /* RO */
3721 1.5.2.1 martin { "id_isar2_el1", CPENC(3,0,C0,C2,2), F_REG_READ }, /* RO */
3722 1.5.2.1 martin { "id_isar3_el1", CPENC(3,0,C0,C2,3), F_REG_READ }, /* RO */
3723 1.5.2.1 martin { "id_isar4_el1", CPENC(3,0,C0,C2,4), F_REG_READ }, /* RO */
3724 1.5.2.1 martin { "id_isar5_el1", CPENC(3,0,C0,C2,5), F_REG_READ }, /* RO */
3725 1.5.2.1 martin { "mvfr0_el1", CPENC(3,0,C0,C3,0), F_REG_READ }, /* RO */
3726 1.5.2.1 martin { "mvfr1_el1", CPENC(3,0,C0,C3,1), F_REG_READ }, /* RO */
3727 1.5.2.1 martin { "mvfr2_el1", CPENC(3,0,C0,C3,2), F_REG_READ }, /* RO */
3728 1.5.2.1 martin { "ccsidr_el1", CPENC(3,1,C0,C0,0), F_REG_READ }, /* RO */
3729 1.5.2.1 martin { "id_aa64pfr0_el1", CPENC(3,0,C0,C4,0), F_REG_READ }, /* RO */
3730 1.5.2.1 martin { "id_aa64pfr1_el1", CPENC(3,0,C0,C4,1), F_REG_READ }, /* RO */
3731 1.5.2.1 martin { "id_aa64dfr0_el1", CPENC(3,0,C0,C5,0), F_REG_READ }, /* RO */
3732 1.5.2.1 martin { "id_aa64dfr1_el1", CPENC(3,0,C0,C5,1), F_REG_READ }, /* RO */
3733 1.5.2.1 martin { "id_aa64isar0_el1", CPENC(3,0,C0,C6,0), F_REG_READ }, /* RO */
3734 1.5.2.1 martin { "id_aa64isar1_el1", CPENC(3,0,C0,C6,1), F_REG_READ }, /* RO */
3735 1.5.2.1 martin { "id_aa64mmfr0_el1", CPENC(3,0,C0,C7,0), F_REG_READ }, /* RO */
3736 1.5.2.1 martin { "id_aa64mmfr1_el1", CPENC(3,0,C0,C7,1), F_REG_READ }, /* RO */
3737 1.5.2.1 martin { "id_aa64mmfr2_el1", CPENC (3, 0, C0, C7, 2), F_ARCHEXT | F_REG_READ }, /* RO */
3738 1.5.2.1 martin { "id_aa64afr0_el1", CPENC(3,0,C0,C5,4), F_REG_READ }, /* RO */
3739 1.3 christos { "id_aa64afr1_el1", CPENC(3,0,C0,C5,5), F_REG_READ }, /* RO */
3740 1.3 christos { "id_aa64zfr0_el1", CPENC (3, 0, C0, C4, 4), F_ARCHEXT | F_REG_READ }, /* RO */
3741 1.3 christos { "clidr_el1", CPENC(3,1,C0,C0,1), F_REG_READ }, /* RO */
3742 1.3 christos { "csselr_el1", CPENC(3,2,C0,C0,0), 0 },
3743 1.3 christos { "vpidr_el2", CPENC(3,4,C0,C0,0), 0 },
3744 1.3 christos { "vmpidr_el2", CPENC(3,4,C0,C0,5), 0 },
3745 1.3 christos { "sctlr_el1", CPENC(3,0,C1,C0,0), 0 },
3746 1.3 christos { "sctlr_el2", CPENC(3,4,C1,C0,0), 0 },
3747 1.3 christos { "sctlr_el3", CPENC(3,6,C1,C0,0), 0 },
3748 1.3 christos { "sctlr_el12", CPENC (3, 5, C1, C0, 0), F_ARCHEXT },
3749 1.3 christos { "actlr_el1", CPENC(3,0,C1,C0,1), 0 },
3750 1.3 christos { "actlr_el2", CPENC(3,4,C1,C0,1), 0 },
3751 1.3 christos { "actlr_el3", CPENC(3,6,C1,C0,1), 0 },
3752 1.3 christos { "cpacr_el1", CPENC(3,0,C1,C0,2), 0 },
3753 1.3 christos { "cpacr_el12", CPENC (3, 5, C1, C0, 2), F_ARCHEXT },
3754 1.3 christos { "cptr_el2", CPENC(3,4,C1,C1,2), 0 },
3755 1.3 christos { "cptr_el3", CPENC(3,6,C1,C1,2), 0 },
3756 1.3 christos { "scr_el3", CPENC(3,6,C1,C1,0), 0 },
3757 1.3 christos { "hcr_el2", CPENC(3,4,C1,C1,0), 0 },
3758 1.5.2.1 martin { "mdcr_el2", CPENC(3,4,C1,C1,1), 0 },
3759 1.5.2.1 martin { "mdcr_el3", CPENC(3,6,C1,C3,1), 0 },
3760 1.5.2.1 martin { "hstr_el2", CPENC(3,4,C1,C1,3), 0 },
3761 1.5.2.1 martin { "hacr_el2", CPENC(3,4,C1,C1,7), 0 },
3762 1.5.2.1 martin { "zcr_el1", CPENC (3, 0, C1, C2, 0), F_ARCHEXT },
3763 1.3 christos { "zcr_el12", CPENC (3, 5, C1, C2, 0), F_ARCHEXT },
3764 1.3 christos { "zcr_el2", CPENC (3, 4, C1, C2, 0), F_ARCHEXT },
3765 1.3 christos { "zcr_el3", CPENC (3, 6, C1, C2, 0), F_ARCHEXT },
3766 1.3 christos { "zidr_el1", CPENC (3, 0, C0, C0, 7), F_ARCHEXT },
3767 1.3 christos { "ttbr0_el1", CPENC(3,0,C2,C0,0), 0 },
3768 1.3 christos { "ttbr1_el1", CPENC(3,0,C2,C0,1), 0 },
3769 1.3 christos { "ttbr0_el2", CPENC(3,4,C2,C0,0), 0 },
3770 1.3 christos { "ttbr1_el2", CPENC (3, 4, C2, C0, 1), F_ARCHEXT },
3771 1.3 christos { "ttbr0_el3", CPENC(3,6,C2,C0,0), 0 },
3772 1.3 christos { "ttbr0_el12", CPENC (3, 5, C2, C0, 0), F_ARCHEXT },
3773 1.3 christos { "ttbr1_el12", CPENC (3, 5, C2, C0, 1), F_ARCHEXT },
3774 1.3 christos { "vttbr_el2", CPENC(3,4,C2,C1,0), 0 },
3775 1.3 christos { "tcr_el1", CPENC(3,0,C2,C0,2), 0 },
3776 1.5.2.1 martin { "tcr_el2", CPENC(3,4,C2,C0,2), 0 },
3777 1.5.2.1 martin { "tcr_el3", CPENC(3,6,C2,C0,2), 0 },
3778 1.5.2.1 martin { "tcr_el12", CPENC (3, 5, C2, C0, 2), F_ARCHEXT },
3779 1.5.2.1 martin { "vtcr_el2", CPENC(3,4,C2,C1,2), 0 },
3780 1.5.2.1 martin { "apiakeylo_el1", CPENC (3, 0, C2, C1, 0), F_ARCHEXT },
3781 1.5.2.1 martin { "apiakeyhi_el1", CPENC (3, 0, C2, C1, 1), F_ARCHEXT },
3782 1.5.2.1 martin { "apibkeylo_el1", CPENC (3, 0, C2, C1, 2), F_ARCHEXT },
3783 1.5.2.1 martin { "apibkeyhi_el1", CPENC (3, 0, C2, C1, 3), F_ARCHEXT },
3784 1.5.2.1 martin { "apdakeylo_el1", CPENC (3, 0, C2, C2, 0), F_ARCHEXT },
3785 1.5.2.1 martin { "apdakeyhi_el1", CPENC (3, 0, C2, C2, 1), F_ARCHEXT },
3786 1.3 christos { "apdbkeylo_el1", CPENC (3, 0, C2, C2, 2), F_ARCHEXT },
3787 1.3 christos { "apdbkeyhi_el1", CPENC (3, 0, C2, C2, 3), F_ARCHEXT },
3788 1.3 christos { "apgakeylo_el1", CPENC (3, 0, C2, C3, 0), F_ARCHEXT },
3789 1.3 christos { "apgakeyhi_el1", CPENC (3, 0, C2, C3, 1), F_ARCHEXT },
3790 1.3 christos { "afsr0_el1", CPENC(3,0,C5,C1,0), 0 },
3791 1.3 christos { "afsr1_el1", CPENC(3,0,C5,C1,1), 0 },
3792 1.3 christos { "afsr0_el2", CPENC(3,4,C5,C1,0), 0 },
3793 1.3 christos { "afsr1_el2", CPENC(3,4,C5,C1,1), 0 },
3794 1.3 christos { "afsr0_el3", CPENC(3,6,C5,C1,0), 0 },
3795 1.3 christos { "afsr0_el12", CPENC (3, 5, C5, C1, 0), F_ARCHEXT },
3796 1.3 christos { "afsr1_el3", CPENC(3,6,C5,C1,1), 0 },
3797 1.3 christos { "afsr1_el12", CPENC (3, 5, C5, C1, 1), F_ARCHEXT },
3798 1.5.2.1 martin { "esr_el1", CPENC(3,0,C5,C2,0), 0 },
3799 1.3 christos { "esr_el2", CPENC(3,4,C5,C2,0), 0 },
3800 1.5.2.1 martin { "esr_el3", CPENC(3,6,C5,C2,0), 0 },
3801 1.3 christos { "esr_el12", CPENC (3, 5, C5, C2, 0), F_ARCHEXT },
3802 1.5.2.1 martin { "vsesr_el2", CPENC (3, 4, C5, C2, 3), F_ARCHEXT },
3803 1.3 christos { "fpexc32_el2", CPENC(3,4,C5,C3,0), 0 },
3804 1.3 christos { "erridr_el1", CPENC (3, 0, C5, C3, 0), F_ARCHEXT | F_REG_READ }, /* RO */
3805 1.3 christos { "errselr_el1", CPENC (3, 0, C5, C3, 1), F_ARCHEXT },
3806 1.3 christos { "erxfr_el1", CPENC (3, 0, C5, C4, 0), F_ARCHEXT | F_REG_READ }, /* RO */
3807 1.3 christos { "erxctlr_el1", CPENC (3, 0, C5, C4, 1), F_ARCHEXT },
3808 1.3 christos { "erxstatus_el1", CPENC (3, 0, C5, C4, 2), F_ARCHEXT },
3809 1.3 christos { "erxaddr_el1", CPENC (3, 0, C5, C4, 3), F_ARCHEXT },
3810 1.3 christos { "erxmisc0_el1", CPENC (3, 0, C5, C5, 0), F_ARCHEXT },
3811 1.3 christos { "erxmisc1_el1", CPENC (3, 0, C5, C5, 1), F_ARCHEXT },
3812 1.3 christos { "far_el1", CPENC(3,0,C6,C0,0), 0 },
3813 1.3 christos { "far_el2", CPENC(3,4,C6,C0,0), 0 },
3814 1.3 christos { "far_el3", CPENC(3,6,C6,C0,0), 0 },
3815 1.3 christos { "far_el12", CPENC (3, 5, C6, C0, 0), F_ARCHEXT },
3816 1.3 christos { "hpfar_el2", CPENC(3,4,C6,C0,4), 0 },
3817 1.3 christos { "par_el1", CPENC(3,0,C7,C4,0), 0 },
3818 1.3 christos { "mair_el1", CPENC(3,0,C10,C2,0), 0 },
3819 1.3 christos { "mair_el2", CPENC(3,4,C10,C2,0), 0 },
3820 1.3 christos { "mair_el3", CPENC(3,6,C10,C2,0), 0 },
3821 1.3 christos { "mair_el12", CPENC (3, 5, C10, C2, 0), F_ARCHEXT },
3822 1.3 christos { "amair_el1", CPENC(3,0,C10,C3,0), 0 },
3823 1.3 christos { "amair_el2", CPENC(3,4,C10,C3,0), 0 },
3824 1.3 christos { "amair_el3", CPENC(3,6,C10,C3,0), 0 },
3825 1.3 christos { "amair_el12", CPENC (3, 5, C10, C3, 0), F_ARCHEXT },
3826 1.5.2.1 martin { "vbar_el1", CPENC(3,0,C12,C0,0), 0 },
3827 1.5.2.1 martin { "vbar_el2", CPENC(3,4,C12,C0,0), 0 },
3828 1.5.2.1 martin { "vbar_el3", CPENC(3,6,C12,C0,0), 0 },
3829 1.3 christos { "vbar_el12", CPENC (3, 5, C12, C0, 0), F_ARCHEXT },
3830 1.3 christos { "rvbar_el1", CPENC(3,0,C12,C0,1), F_REG_READ }, /* RO */
3831 1.3 christos { "rvbar_el2", CPENC(3,4,C12,C0,1), F_REG_READ }, /* RO */
3832 1.5.2.1 martin { "rvbar_el3", CPENC(3,6,C12,C0,1), F_REG_READ }, /* RO */
3833 1.3 christos { "rmr_el1", CPENC(3,0,C12,C0,2), 0 },
3834 1.3 christos { "rmr_el2", CPENC(3,4,C12,C0,2), 0 },
3835 1.3 christos { "rmr_el3", CPENC(3,6,C12,C0,2), 0 },
3836 1.3 christos { "isr_el1", CPENC(3,0,C12,C1,0), F_REG_READ }, /* RO */
3837 1.3 christos { "disr_el1", CPENC (3, 0, C12, C1, 1), F_ARCHEXT },
3838 1.3 christos { "vdisr_el2", CPENC (3, 4, C12, C1, 1), F_ARCHEXT },
3839 1.5.2.1 martin { "contextidr_el1", CPENC(3,0,C13,C0,1), 0 },
3840 1.3 christos { "contextidr_el2", CPENC (3, 4, C13, C0, 1), F_ARCHEXT },
3841 1.3 christos { "contextidr_el12", CPENC (3, 5, C13, C0, 1), F_ARCHEXT },
3842 1.3 christos { "tpidr_el0", CPENC(3,3,C13,C0,2), 0 },
3843 1.3 christos { "tpidrro_el0", CPENC(3,3,C13,C0,3), 0 }, /* RW */
3844 1.5.2.1 martin { "tpidr_el1", CPENC(3,0,C13,C0,4), 0 },
3845 1.5.2.1 martin { "tpidr_el2", CPENC(3,4,C13,C0,2), 0 },
3846 1.5.2.1 martin { "tpidr_el3", CPENC(3,6,C13,C0,2), 0 },
3847 1.3 christos { "teecr32_el1", CPENC(2,2,C0, C0,0), 0 }, /* See section 3.9.7.1 */
3848 1.3 christos { "cntfrq_el0", CPENC(3,3,C14,C0,0), 0 }, /* RW */
3849 1.3 christos { "cntpct_el0", CPENC(3,3,C14,C0,1), F_REG_READ }, /* RO */
3850 1.3 christos { "cntvct_el0", CPENC(3,3,C14,C0,2), F_REG_READ }, /* RO */
3851 1.3 christos { "cntvoff_el2", CPENC(3,4,C14,C0,3), 0 },
3852 1.3 christos { "cntkctl_el1", CPENC(3,0,C14,C1,0), 0 },
3853 1.3 christos { "cntkctl_el12", CPENC (3, 5, C14, C1, 0), F_ARCHEXT },
3854 1.3 christos { "cnthctl_el2", CPENC(3,4,C14,C1,0), 0 },
3855 1.3 christos { "cntp_tval_el0", CPENC(3,3,C14,C2,0), 0 },
3856 1.3 christos { "cntp_tval_el02", CPENC (3, 5, C14, C2, 0), F_ARCHEXT },
3857 1.3 christos { "cntp_ctl_el0", CPENC(3,3,C14,C2,1), 0 },
3858 1.3 christos { "cntp_ctl_el02", CPENC (3, 5, C14, C2, 1), F_ARCHEXT },
3859 1.3 christos { "cntp_cval_el0", CPENC(3,3,C14,C2,2), 0 },
3860 1.3 christos { "cntp_cval_el02", CPENC (3, 5, C14, C2, 2), F_ARCHEXT },
3861 1.3 christos { "cntv_tval_el0", CPENC(3,3,C14,C3,0), 0 },
3862 1.3 christos { "cntv_tval_el02", CPENC (3, 5, C14, C3, 0), F_ARCHEXT },
3863 1.3 christos { "cntv_ctl_el0", CPENC(3,3,C14,C3,1), 0 },
3864 1.3 christos { "cntv_ctl_el02", CPENC (3, 5, C14, C3, 1), F_ARCHEXT },
3865 1.3 christos { "cntv_cval_el0", CPENC(3,3,C14,C3,2), 0 },
3866 1.3 christos { "cntv_cval_el02", CPENC (3, 5, C14, C3, 2), F_ARCHEXT },
3867 1.3 christos { "cnthp_tval_el2", CPENC(3,4,C14,C2,0), 0 },
3868 1.3 christos { "cnthp_ctl_el2", CPENC(3,4,C14,C2,1), 0 },
3869 1.3 christos { "cnthp_cval_el2", CPENC(3,4,C14,C2,2), 0 },
3870 1.3 christos { "cntps_tval_el1", CPENC(3,7,C14,C2,0), 0 },
3871 1.3 christos { "cntps_ctl_el1", CPENC(3,7,C14,C2,1), 0 },
3872 1.3 christos { "cntps_cval_el1", CPENC(3,7,C14,C2,2), 0 },
3873 1.3 christos { "cnthv_tval_el2", CPENC (3, 4, C14, C3, 0), F_ARCHEXT },
3874 1.3 christos { "cnthv_ctl_el2", CPENC (3, 4, C14, C3, 1), F_ARCHEXT },
3875 1.3 christos { "cnthv_cval_el2", CPENC (3, 4, C14, C3, 2), F_ARCHEXT },
3876 1.3 christos { "dacr32_el2", CPENC(3,4,C3,C0,0), 0 },
3877 1.5.2.1 martin { "ifsr32_el2", CPENC(3,4,C5,C0,1), 0 },
3878 1.3 christos { "teehbr32_el1", CPENC(2,2,C1,C0,0), 0 },
3879 1.3 christos { "sder32_el3", CPENC(3,6,C1,C1,1), 0 },
3880 1.5.2.1 martin { "mdscr_el1", CPENC(2,0,C0, C2, 2), 0 },
3881 1.5.2.1 martin { "mdccsr_el0", CPENC(2,3,C0, C1, 0), F_REG_READ }, /* r */
3882 1.5.2.1 martin { "mdccint_el1", CPENC(2,0,C0, C2, 0), 0 },
3883 1.5.2.1 martin { "dbgdtr_el0", CPENC(2,3,C0, C4, 0), 0 },
3884 1.3 christos { "dbgdtrrx_el0", CPENC(2,3,C0, C5, 0), F_REG_READ }, /* r */
3885 1.3 christos { "dbgdtrtx_el0", CPENC(2,3,C0, C5, 0), F_REG_WRITE }, /* w */
3886 1.3 christos { "osdtrrx_el1", CPENC(2,0,C0, C0, 2), 0 },
3887 1.3 christos { "osdtrtx_el1", CPENC(2,0,C0, C3, 2), 0 },
3888 1.3 christos { "oseccr_el1", CPENC(2,0,C0, C6, 2), 0 },
3889 1.3 christos { "dbgvcr32_el2", CPENC(2,4,C0, C7, 0), 0 },
3890 1.3 christos { "dbgbvr0_el1", CPENC(2,0,C0, C0, 4), 0 },
3891 1.3 christos { "dbgbvr1_el1", CPENC(2,0,C0, C1, 4), 0 },
3892 1.3 christos { "dbgbvr2_el1", CPENC(2,0,C0, C2, 4), 0 },
3893 1.3 christos { "dbgbvr3_el1", CPENC(2,0,C0, C3, 4), 0 },
3894 1.3 christos { "dbgbvr4_el1", CPENC(2,0,C0, C4, 4), 0 },
3895 1.3 christos { "dbgbvr5_el1", CPENC(2,0,C0, C5, 4), 0 },
3896 1.3 christos { "dbgbvr6_el1", CPENC(2,0,C0, C6, 4), 0 },
3897 1.3 christos { "dbgbvr7_el1", CPENC(2,0,C0, C7, 4), 0 },
3898 1.3 christos { "dbgbvr8_el1", CPENC(2,0,C0, C8, 4), 0 },
3899 1.3 christos { "dbgbvr9_el1", CPENC(2,0,C0, C9, 4), 0 },
3900 1.3 christos { "dbgbvr10_el1", CPENC(2,0,C0, C10,4), 0 },
3901 1.3 christos { "dbgbvr11_el1", CPENC(2,0,C0, C11,4), 0 },
3902 1.3 christos { "dbgbvr12_el1", CPENC(2,0,C0, C12,4), 0 },
3903 1.3 christos { "dbgbvr13_el1", CPENC(2,0,C0, C13,4), 0 },
3904 1.3 christos { "dbgbvr14_el1", CPENC(2,0,C0, C14,4), 0 },
3905 1.3 christos { "dbgbvr15_el1", CPENC(2,0,C0, C15,4), 0 },
3906 1.3 christos { "dbgbcr0_el1", CPENC(2,0,C0, C0, 5), 0 },
3907 1.3 christos { "dbgbcr1_el1", CPENC(2,0,C0, C1, 5), 0 },
3908 1.3 christos { "dbgbcr2_el1", CPENC(2,0,C0, C2, 5), 0 },
3909 1.3 christos { "dbgbcr3_el1", CPENC(2,0,C0, C3, 5), 0 },
3910 1.3 christos { "dbgbcr4_el1", CPENC(2,0,C0, C4, 5), 0 },
3911 1.3 christos { "dbgbcr5_el1", CPENC(2,0,C0, C5, 5), 0 },
3912 1.3 christos { "dbgbcr6_el1", CPENC(2,0,C0, C6, 5), 0 },
3913 1.3 christos { "dbgbcr7_el1", CPENC(2,0,C0, C7, 5), 0 },
3914 1.3 christos { "dbgbcr8_el1", CPENC(2,0,C0, C8, 5), 0 },
3915 1.3 christos { "dbgbcr9_el1", CPENC(2,0,C0, C9, 5), 0 },
3916 1.3 christos { "dbgbcr10_el1", CPENC(2,0,C0, C10,5), 0 },
3917 1.3 christos { "dbgbcr11_el1", CPENC(2,0,C0, C11,5), 0 },
3918 1.3 christos { "dbgbcr12_el1", CPENC(2,0,C0, C12,5), 0 },
3919 1.3 christos { "dbgbcr13_el1", CPENC(2,0,C0, C13,5), 0 },
3920 1.3 christos { "dbgbcr14_el1", CPENC(2,0,C0, C14,5), 0 },
3921 1.3 christos { "dbgbcr15_el1", CPENC(2,0,C0, C15,5), 0 },
3922 1.3 christos { "dbgwvr0_el1", CPENC(2,0,C0, C0, 6), 0 },
3923 1.3 christos { "dbgwvr1_el1", CPENC(2,0,C0, C1, 6), 0 },
3924 1.3 christos { "dbgwvr2_el1", CPENC(2,0,C0, C2, 6), 0 },
3925 1.3 christos { "dbgwvr3_el1", CPENC(2,0,C0, C3, 6), 0 },
3926 1.3 christos { "dbgwvr4_el1", CPENC(2,0,C0, C4, 6), 0 },
3927 1.3 christos { "dbgwvr5_el1", CPENC(2,0,C0, C5, 6), 0 },
3928 1.3 christos { "dbgwvr6_el1", CPENC(2,0,C0, C6, 6), 0 },
3929 1.3 christos { "dbgwvr7_el1", CPENC(2,0,C0, C7, 6), 0 },
3930 1.3 christos { "dbgwvr8_el1", CPENC(2,0,C0, C8, 6), 0 },
3931 1.3 christos { "dbgwvr9_el1", CPENC(2,0,C0, C9, 6), 0 },
3932 1.3 christos { "dbgwvr10_el1", CPENC(2,0,C0, C10,6), 0 },
3933 1.3 christos { "dbgwvr11_el1", CPENC(2,0,C0, C11,6), 0 },
3934 1.3 christos { "dbgwvr12_el1", CPENC(2,0,C0, C12,6), 0 },
3935 1.3 christos { "dbgwvr13_el1", CPENC(2,0,C0, C13,6), 0 },
3936 1.3 christos { "dbgwvr14_el1", CPENC(2,0,C0, C14,6), 0 },
3937 1.3 christos { "dbgwvr15_el1", CPENC(2,0,C0, C15,6), 0 },
3938 1.3 christos { "dbgwcr0_el1", CPENC(2,0,C0, C0, 7), 0 },
3939 1.3 christos { "dbgwcr1_el1", CPENC(2,0,C0, C1, 7), 0 },
3940 1.3 christos { "dbgwcr2_el1", CPENC(2,0,C0, C2, 7), 0 },
3941 1.3 christos { "dbgwcr3_el1", CPENC(2,0,C0, C3, 7), 0 },
3942 1.3 christos { "dbgwcr4_el1", CPENC(2,0,C0, C4, 7), 0 },
3943 1.3 christos { "dbgwcr5_el1", CPENC(2,0,C0, C5, 7), 0 },
3944 1.3 christos { "dbgwcr6_el1", CPENC(2,0,C0, C6, 7), 0 },
3945 1.3 christos { "dbgwcr7_el1", CPENC(2,0,C0, C7, 7), 0 },
3946 1.3 christos { "dbgwcr8_el1", CPENC(2,0,C0, C8, 7), 0 },
3947 1.3 christos { "dbgwcr9_el1", CPENC(2,0,C0, C9, 7), 0 },
3948 1.3 christos { "dbgwcr10_el1", CPENC(2,0,C0, C10,7), 0 },
3949 1.3 christos { "dbgwcr11_el1", CPENC(2,0,C0, C11,7), 0 },
3950 1.5.2.1 martin { "dbgwcr12_el1", CPENC(2,0,C0, C12,7), 0 },
3951 1.5.2.1 martin { "dbgwcr13_el1", CPENC(2,0,C0, C13,7), 0 },
3952 1.5.2.1 martin { "dbgwcr14_el1", CPENC(2,0,C0, C14,7), 0 },
3953 1.3 christos { "dbgwcr15_el1", CPENC(2,0,C0, C15,7), 0 },
3954 1.3 christos { "mdrar_el1", CPENC(2,0,C1, C0, 0), F_REG_READ }, /* r */
3955 1.3 christos { "oslar_el1", CPENC(2,0,C1, C0, 4), F_REG_WRITE }, /* w */
3956 1.3 christos { "oslsr_el1", CPENC(2,0,C1, C1, 4), F_REG_READ }, /* r */
3957 1.5.2.1 martin { "osdlr_el1", CPENC(2,0,C1, C3, 4), 0 },
3958 1.3 christos { "dbgprcr_el1", CPENC(2,0,C1, C4, 4), 0 },
3959 1.3 christos { "dbgclaimset_el1", CPENC(2,0,C7, C8, 6), 0 },
3960 1.3 christos { "dbgclaimclr_el1", CPENC(2,0,C7, C9, 6), 0 },
3961 1.5.2.1 martin { "dbgauthstatus_el1", CPENC(2,0,C7, C14,6), F_REG_READ }, /* r */
3962 1.3 christos { "pmblimitr_el1", CPENC (3, 0, C9, C10, 0), F_ARCHEXT }, /* rw */
3963 1.3 christos { "pmbptr_el1", CPENC (3, 0, C9, C10, 1), F_ARCHEXT }, /* rw */
3964 1.3 christos { "pmbsr_el1", CPENC (3, 0, C9, C10, 3), F_ARCHEXT }, /* rw */
3965 1.3 christos { "pmbidr_el1", CPENC (3, 0, C9, C10, 7), F_ARCHEXT | F_REG_READ }, /* ro */
3966 1.3 christos { "pmscr_el1", CPENC (3, 0, C9, C9, 0), F_ARCHEXT }, /* rw */
3967 1.3 christos { "pmsicr_el1", CPENC (3, 0, C9, C9, 2), F_ARCHEXT }, /* rw */
3968 1.5.2.1 martin { "pmsirr_el1", CPENC (3, 0, C9, C9, 3), F_ARCHEXT }, /* rw */
3969 1.3 christos { "pmsfcr_el1", CPENC (3, 0, C9, C9, 4), F_ARCHEXT }, /* rw */
3970 1.3 christos { "pmsevfr_el1", CPENC (3, 0, C9, C9, 5), F_ARCHEXT }, /* rw */
3971 1.3 christos { "pmslatfr_el1", CPENC (3, 0, C9, C9, 6), F_ARCHEXT }, /* rw */
3972 1.3 christos { "pmsidr_el1", CPENC (3, 0, C9, C9, 7), F_ARCHEXT }, /* rw */
3973 1.3 christos { "pmscr_el2", CPENC (3, 4, C9, C9, 0), F_ARCHEXT }, /* rw */
3974 1.3 christos { "pmscr_el12", CPENC (3, 5, C9, C9, 0), F_ARCHEXT }, /* rw */
3975 1.5.2.1 martin { "pmcr_el0", CPENC(3,3,C9,C12, 0), 0 },
3976 1.3 christos { "pmcntenset_el0", CPENC(3,3,C9,C12, 1), 0 },
3977 1.5.2.1 martin { "pmcntenclr_el0", CPENC(3,3,C9,C12, 2), 0 },
3978 1.5.2.1 martin { "pmovsclr_el0", CPENC(3,3,C9,C12, 3), 0 },
3979 1.3 christos { "pmswinc_el0", CPENC(3,3,C9,C12, 4), F_REG_WRITE }, /* w */
3980 1.3 christos { "pmselr_el0", CPENC(3,3,C9,C12, 5), 0 },
3981 1.3 christos { "pmceid0_el0", CPENC(3,3,C9,C12, 6), F_REG_READ }, /* r */
3982 1.3 christos { "pmceid1_el0", CPENC(3,3,C9,C12, 7), F_REG_READ }, /* r */
3983 1.3 christos { "pmccntr_el0", CPENC(3,3,C9,C13, 0), 0 },
3984 1.3 christos { "pmxevtyper_el0", CPENC(3,3,C9,C13, 1), 0 },
3985 1.3 christos { "pmxevcntr_el0", CPENC(3,3,C9,C13, 2), 0 },
3986 1.3 christos { "pmuserenr_el0", CPENC(3,3,C9,C14, 0), 0 },
3987 1.3 christos { "pmintenset_el1", CPENC(3,0,C9,C14, 1), 0 },
3988 1.3 christos { "pmintenclr_el1", CPENC(3,0,C9,C14, 2), 0 },
3989 1.3 christos { "pmovsset_el0", CPENC(3,3,C9,C14, 3), 0 },
3990 1.3 christos { "pmevcntr0_el0", CPENC(3,3,C14,C8, 0), 0 },
3991 1.3 christos { "pmevcntr1_el0", CPENC(3,3,C14,C8, 1), 0 },
3992 1.3 christos { "pmevcntr2_el0", CPENC(3,3,C14,C8, 2), 0 },
3993 1.3 christos { "pmevcntr3_el0", CPENC(3,3,C14,C8, 3), 0 },
3994 1.3 christos { "pmevcntr4_el0", CPENC(3,3,C14,C8, 4), 0 },
3995 1.3 christos { "pmevcntr5_el0", CPENC(3,3,C14,C8, 5), 0 },
3996 1.3 christos { "pmevcntr6_el0", CPENC(3,3,C14,C8, 6), 0 },
3997 1.3 christos { "pmevcntr7_el0", CPENC(3,3,C14,C8, 7), 0 },
3998 1.3 christos { "pmevcntr8_el0", CPENC(3,3,C14,C9, 0), 0 },
3999 1.3 christos { "pmevcntr9_el0", CPENC(3,3,C14,C9, 1), 0 },
4000 1.3 christos { "pmevcntr10_el0", CPENC(3,3,C14,C9, 2), 0 },
4001 1.3 christos { "pmevcntr11_el0", CPENC(3,3,C14,C9, 3), 0 },
4002 1.3 christos { "pmevcntr12_el0", CPENC(3,3,C14,C9, 4), 0 },
4003 1.3 christos { "pmevcntr13_el0", CPENC(3,3,C14,C9, 5), 0 },
4004 1.3 christos { "pmevcntr14_el0", CPENC(3,3,C14,C9, 6), 0 },
4005 1.3 christos { "pmevcntr15_el0", CPENC(3,3,C14,C9, 7), 0 },
4006 1.3 christos { "pmevcntr16_el0", CPENC(3,3,C14,C10,0), 0 },
4007 1.3 christos { "pmevcntr17_el0", CPENC(3,3,C14,C10,1), 0 },
4008 1.3 christos { "pmevcntr18_el0", CPENC(3,3,C14,C10,2), 0 },
4009 1.3 christos { "pmevcntr19_el0", CPENC(3,3,C14,C10,3), 0 },
4010 1.3 christos { "pmevcntr20_el0", CPENC(3,3,C14,C10,4), 0 },
4011 1.3 christos { "pmevcntr21_el0", CPENC(3,3,C14,C10,5), 0 },
4012 1.3 christos { "pmevcntr22_el0", CPENC(3,3,C14,C10,6), 0 },
4013 1.3 christos { "pmevcntr23_el0", CPENC(3,3,C14,C10,7), 0 },
4014 1.3 christos { "pmevcntr24_el0", CPENC(3,3,C14,C11,0), 0 },
4015 1.3 christos { "pmevcntr25_el0", CPENC(3,3,C14,C11,1), 0 },
4016 1.3 christos { "pmevcntr26_el0", CPENC(3,3,C14,C11,2), 0 },
4017 1.3 christos { "pmevcntr27_el0", CPENC(3,3,C14,C11,3), 0 },
4018 1.3 christos { "pmevcntr28_el0", CPENC(3,3,C14,C11,4), 0 },
4019 1.3 christos { "pmevcntr29_el0", CPENC(3,3,C14,C11,5), 0 },
4020 1.3 christos { "pmevcntr30_el0", CPENC(3,3,C14,C11,6), 0 },
4021 1.3 christos { "pmevtyper0_el0", CPENC(3,3,C14,C12,0), 0 },
4022 1.3 christos { "pmevtyper1_el0", CPENC(3,3,C14,C12,1), 0 },
4023 1.3 christos { "pmevtyper2_el0", CPENC(3,3,C14,C12,2), 0 },
4024 1.3 christos { "pmevtyper3_el0", CPENC(3,3,C14,C12,3), 0 },
4025 1.3 christos { "pmevtyper4_el0", CPENC(3,3,C14,C12,4), 0 },
4026 1.3 christos { "pmevtyper5_el0", CPENC(3,3,C14,C12,5), 0 },
4027 1.3 christos { "pmevtyper6_el0", CPENC(3,3,C14,C12,6), 0 },
4028 1.3 christos { "pmevtyper7_el0", CPENC(3,3,C14,C12,7), 0 },
4029 1.3 christos { "pmevtyper8_el0", CPENC(3,3,C14,C13,0), 0 },
4030 1.3 christos { "pmevtyper9_el0", CPENC(3,3,C14,C13,1), 0 },
4031 1.3 christos { "pmevtyper10_el0", CPENC(3,3,C14,C13,2), 0 },
4032 1.3 christos { "pmevtyper11_el0", CPENC(3,3,C14,C13,3), 0 },
4033 1.3 christos { "pmevtyper12_el0", CPENC(3,3,C14,C13,4), 0 },
4034 1.3 christos { "pmevtyper13_el0", CPENC(3,3,C14,C13,5), 0 },
4035 1.3 christos { "pmevtyper14_el0", CPENC(3,3,C14,C13,6), 0 },
4036 1.3 christos { "pmevtyper15_el0", CPENC(3,3,C14,C13,7), 0 },
4037 1.3 christos { "pmevtyper16_el0", CPENC(3,3,C14,C14,0), 0 },
4038 1.3 christos { "pmevtyper17_el0", CPENC(3,3,C14,C14,1), 0 },
4039 1.3 christos { "pmevtyper18_el0", CPENC(3,3,C14,C14,2), 0 },
4040 1.3 christos { "pmevtyper19_el0", CPENC(3,3,C14,C14,3), 0 },
4041 1.3 christos { "pmevtyper20_el0", CPENC(3,3,C14,C14,4), 0 },
4042 1.3 christos { "pmevtyper21_el0", CPENC(3,3,C14,C14,5), 0 },
4043 1.3 christos { "pmevtyper22_el0", CPENC(3,3,C14,C14,6), 0 },
4044 1.3 christos { "pmevtyper23_el0", CPENC(3,3,C14,C14,7), 0 },
4045 1.3 christos { "pmevtyper24_el0", CPENC(3,3,C14,C15,0), 0 },
4046 1.3 christos { "pmevtyper25_el0", CPENC(3,3,C14,C15,1), 0 },
4047 1.3 christos { "pmevtyper26_el0", CPENC(3,3,C14,C15,2), 0 },
4048 1.3 christos { "pmevtyper27_el0", CPENC(3,3,C14,C15,3), 0 },
4049 1.5.2.1 martin { "pmevtyper28_el0", CPENC(3,3,C14,C15,4), 0 },
4050 1.5.2.1 martin { "pmevtyper29_el0", CPENC(3,3,C14,C15,5), 0 },
4051 1.5.2.1 martin { "pmevtyper30_el0", CPENC(3,3,C14,C15,6), 0 },
4052 1.5.2.1 martin { "pmccfiltr_el0", CPENC(3,3,C14,C15,7), 0 },
4053 1.5.2.1 martin
4054 1.5.2.1 martin { "dit", CPEN_ (3, C2, 5), F_ARCHEXT },
4055 1.5.2.1 martin { "vstcr_el2", CPENC(3, 4, C2, C6, 2), F_ARCHEXT },
4056 1.5.2.1 martin { "vsttbr_el2", CPENC(3, 4, C2, C6, 0), F_ARCHEXT },
4057 1.5.2.1 martin { "cnthvs_tval_el2", CPENC(3, 4, C14, C4, 0), F_ARCHEXT },
4058 1.5.2.1 martin { "cnthvs_cval_el2", CPENC(3, 4, C14, C4, 2), F_ARCHEXT },
4059 1.5.2.1 martin { "cnthvs_ctl_el2", CPENC(3, 4, C14, C4, 1), F_ARCHEXT },
4060 1.5.2.1 martin { "cnthps_tval_el2", CPENC(3, 4, C14, C5, 0), F_ARCHEXT },
4061 1.3 christos { "cnthps_cval_el2", CPENC(3, 4, C14, C5, 2), F_ARCHEXT },
4062 1.1 christos { "cnthps_ctl_el2", CPENC(3, 4, C14, C5, 1), F_ARCHEXT },
4063 1.1 christos { "sder32_el2", CPENC(3, 4, C1, C3, 1), F_ARCHEXT },
4064 1.3 christos { "vncr_el2", CPENC(3, 4, C2, C2, 0), F_ARCHEXT },
4065 1.3 christos { 0, CPENC(0,0,0,0,0), 0 },
4066 1.1 christos };
4067 1.3 christos
4068 1.3 christos bfd_boolean
4069 1.3 christos aarch64_sys_reg_deprecated_p (const aarch64_sys_reg *reg)
4070 1.3 christos {
4071 1.3 christos return (reg->flags & F_DEPRECATED) != 0;
4072 1.3 christos }
4073 1.3 christos
4074 1.3 christos bfd_boolean
4075 1.3 christos aarch64_sys_reg_supported_p (const aarch64_feature_set features,
4076 1.3 christos const aarch64_sys_reg *reg)
4077 1.3 christos {
4078 1.3 christos if (!(reg->flags & F_ARCHEXT))
4079 1.3 christos return TRUE;
4080 1.3 christos
4081 1.3 christos /* PAN. Values are from aarch64_sys_regs. */
4082 1.3 christos if (reg->value == CPEN_(0,C2,3)
4083 1.3 christos && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_PAN))
4084 1.3 christos return FALSE;
4085 1.3 christos
4086 1.3 christos /* Virtualization host extensions: system registers. */
4087 1.3 christos if ((reg->value == CPENC (3, 4, C2, C0, 1)
4088 1.3 christos || reg->value == CPENC (3, 4, C13, C0, 1)
4089 1.3 christos || reg->value == CPENC (3, 4, C14, C3, 0)
4090 1.3 christos || reg->value == CPENC (3, 4, C14, C3, 1)
4091 1.3 christos || reg->value == CPENC (3, 4, C14, C3, 2))
4092 1.3 christos && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_1))
4093 1.3 christos return FALSE;
4094 1.3 christos
4095 1.3 christos /* Virtualization host extensions: *_el12 names of *_el1 registers. */
4096 1.3 christos if ((reg->value == CPEN_ (5, C0, 0)
4097 1.3 christos || reg->value == CPEN_ (5, C0, 1)
4098 1.3 christos || reg->value == CPENC (3, 5, C1, C0, 0)
4099 1.3 christos || reg->value == CPENC (3, 5, C1, C0, 2)
4100 1.3 christos || reg->value == CPENC (3, 5, C2, C0, 0)
4101 1.3 christos || reg->value == CPENC (3, 5, C2, C0, 1)
4102 1.3 christos || reg->value == CPENC (3, 5, C2, C0, 2)
4103 1.3 christos || reg->value == CPENC (3, 5, C5, C1, 0)
4104 1.3 christos || reg->value == CPENC (3, 5, C5, C1, 1)
4105 1.3 christos || reg->value == CPENC (3, 5, C5, C2, 0)
4106 1.3 christos || reg->value == CPENC (3, 5, C6, C0, 0)
4107 1.3 christos || reg->value == CPENC (3, 5, C10, C2, 0)
4108 1.3 christos || reg->value == CPENC (3, 5, C10, C3, 0)
4109 1.3 christos || reg->value == CPENC (3, 5, C12, C0, 0)
4110 1.3 christos || reg->value == CPENC (3, 5, C13, C0, 1)
4111 1.3 christos || reg->value == CPENC (3, 5, C14, C1, 0))
4112 1.3 christos && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_1))
4113 1.3 christos return FALSE;
4114 1.3 christos
4115 1.3 christos /* Virtualization host extensions: *_el02 names of *_el0 registers. */
4116 1.3 christos if ((reg->value == CPENC (3, 5, C14, C2, 0)
4117 1.3 christos || reg->value == CPENC (3, 5, C14, C2, 1)
4118 1.3 christos || reg->value == CPENC (3, 5, C14, C2, 2)
4119 1.3 christos || reg->value == CPENC (3, 5, C14, C3, 0)
4120 1.3 christos || reg->value == CPENC (3, 5, C14, C3, 1)
4121 1.3 christos || reg->value == CPENC (3, 5, C14, C3, 2))
4122 1.3 christos && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_1))
4123 1.3 christos return FALSE;
4124 1.3 christos
4125 1.3 christos /* ARMv8.2 features. */
4126 1.3 christos
4127 1.3 christos /* ID_AA64MMFR2_EL1. */
4128 1.3 christos if (reg->value == CPENC (3, 0, C0, C7, 2)
4129 1.3 christos && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
4130 1.3 christos return FALSE;
4131 1.3 christos
4132 1.3 christos /* PSTATE.UAO. */
4133 1.3 christos if (reg->value == CPEN_ (0, C2, 4)
4134 1.3 christos && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
4135 1.5 christos return FALSE;
4136 1.5 christos
4137 1.3 christos /* RAS extension. */
4138 1.5 christos
4139 1.3 christos /* ERRIDR_EL1, ERRSELR_EL1, ERXFR_EL1, ERXCTLR_EL1, ERXSTATUS_EL, ERXADDR_EL1,
4140 1.3 christos ERXMISC0_EL1 AND ERXMISC1_EL1. */
4141 1.5 christos if ((reg->value == CPENC (3, 0, C5, C3, 0)
4142 1.5 christos || reg->value == CPENC (3, 0, C5, C3, 1)
4143 1.5 christos || reg->value == CPENC (3, 0, C5, C3, 2)
4144 1.5 christos || reg->value == CPENC (3, 0, C5, C3, 3)
4145 1.3 christos || reg->value == CPENC (3, 0, C5, C4, 0)
4146 1.3 christos || reg->value == CPENC (3, 0, C5, C4, 1)
4147 1.3 christos || reg->value == CPENC (3, 0, C5, C4, 2)
4148 1.3 christos || reg->value == CPENC (3, 0, C5, C4, 3)
4149 1.3 christos || reg->value == CPENC (3, 0, C5, C5, 0)
4150 1.3 christos || reg->value == CPENC (3, 0, C5, C5, 1))
4151 1.3 christos && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_RAS))
4152 1.3 christos return FALSE;
4153 1.3 christos
4154 1.3 christos /* VSESR_EL2, DISR_EL1 and VDISR_EL2. */
4155 1.3 christos if ((reg->value == CPENC (3, 4, C5, C2, 3)
4156 1.3 christos || reg->value == CPENC (3, 0, C12, C1, 1)
4157 1.3 christos || reg->value == CPENC (3, 4, C12, C1, 1))
4158 1.3 christos && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_RAS))
4159 1.3 christos return FALSE;
4160 1.3 christos
4161 1.3 christos /* Statistical Profiling extension. */
4162 1.3 christos if ((reg->value == CPENC (3, 0, C9, C10, 0)
4163 1.3 christos || reg->value == CPENC (3, 0, C9, C10, 1)
4164 1.3 christos || reg->value == CPENC (3, 0, C9, C10, 3)
4165 1.3 christos || reg->value == CPENC (3, 0, C9, C10, 7)
4166 1.3 christos || reg->value == CPENC (3, 0, C9, C9, 0)
4167 1.3 christos || reg->value == CPENC (3, 0, C9, C9, 2)
4168 1.3 christos || reg->value == CPENC (3, 0, C9, C9, 3)
4169 1.3 christos || reg->value == CPENC (3, 0, C9, C9, 4)
4170 1.3 christos || reg->value == CPENC (3, 0, C9, C9, 5)
4171 1.3 christos || reg->value == CPENC (3, 0, C9, C9, 6)
4172 1.3 christos || reg->value == CPENC (3, 0, C9, C9, 7)
4173 1.3 christos || reg->value == CPENC (3, 4, C9, C9, 0)
4174 1.5.2.1 martin || reg->value == CPENC (3, 5, C9, C9, 0))
4175 1.5.2.1 martin && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_PROFILE))
4176 1.5.2.1 martin return FALSE;
4177 1.5.2.1 martin
4178 1.5.2.1 martin /* ARMv8.3 Pointer authentication keys. */
4179 1.5.2.1 martin if ((reg->value == CPENC (3, 0, C2, C1, 0)
4180 1.5.2.1 martin || reg->value == CPENC (3, 0, C2, C1, 1)
4181 1.5.2.1 martin || reg->value == CPENC (3, 0, C2, C1, 2)
4182 1.5.2.1 martin || reg->value == CPENC (3, 0, C2, C1, 3)
4183 1.5.2.1 martin || reg->value == CPENC (3, 0, C2, C2, 0)
4184 1.5.2.1 martin || reg->value == CPENC (3, 0, C2, C2, 1)
4185 1.5.2.1 martin || reg->value == CPENC (3, 0, C2, C2, 2)
4186 1.5.2.1 martin || reg->value == CPENC (3, 0, C2, C2, 3)
4187 1.5.2.1 martin || reg->value == CPENC (3, 0, C2, C3, 0)
4188 1.5.2.1 martin || reg->value == CPENC (3, 0, C2, C3, 1))
4189 1.5.2.1 martin && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_3))
4190 1.5.2.1 martin return FALSE;
4191 1.5.2.1 martin
4192 1.5.2.1 martin /* SVE. */
4193 1.5.2.1 martin if ((reg->value == CPENC (3, 0, C0, C4, 4)
4194 1.5.2.1 martin || reg->value == CPENC (3, 0, C1, C2, 0)
4195 1.5.2.1 martin || reg->value == CPENC (3, 4, C1, C2, 0)
4196 1.5.2.1 martin || reg->value == CPENC (3, 6, C1, C2, 0)
4197 1.5.2.1 martin || reg->value == CPENC (3, 5, C1, C2, 0)
4198 1.5.2.1 martin || reg->value == CPENC (3, 0, C0, C0, 7))
4199 1.5.2.1 martin && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_SVE))
4200 1.5.2.1 martin return FALSE;
4201 1.5.2.1 martin
4202 1.5.2.1 martin /* ARMv8.4 features. */
4203 1.5.2.1 martin
4204 1.5.2.1 martin /* PSTATE.DIT. */
4205 1.5.2.1 martin if (reg->value == CPEN_ (3, C2, 5)
4206 1.5.2.1 martin && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_4))
4207 1.5.2.1 martin return FALSE;
4208 1.5.2.1 martin
4209 1.5.2.1 martin /* Virtualization extensions. */
4210 1.5.2.1 martin if ((reg->value == CPENC(3, 4, C2, C6, 2)
4211 1.5.2.1 martin || reg->value == CPENC(3, 4, C2, C6, 0)
4212 1.5.2.1 martin || reg->value == CPENC(3, 4, C14, C4, 0)
4213 1.5.2.1 martin || reg->value == CPENC(3, 4, C14, C4, 2)
4214 1.5.2.1 martin || reg->value == CPENC(3, 4, C14, C4, 1)
4215 1.5.2.1 martin || reg->value == CPENC(3, 4, C14, C5, 0)
4216 1.5.2.1 martin || reg->value == CPENC(3, 4, C14, C5, 2)
4217 1.5.2.1 martin || reg->value == CPENC(3, 4, C14, C5, 1)
4218 1.5.2.1 martin || reg->value == CPENC(3, 4, C1, C3, 1)
4219 1.5.2.1 martin || reg->value == CPENC(3, 4, C2, C2, 0))
4220 1.5.2.1 martin && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_4))
4221 1.5.2.1 martin return FALSE;
4222 1.5.2.1 martin
4223 1.5.2.1 martin /* ARMv8.4 TLB instructions. */
4224 1.5.2.1 martin if ((reg->value == CPENS (0, C8, C1, 0)
4225 1.5.2.1 martin || reg->value == CPENS (0, C8, C1, 1)
4226 1.5.2.1 martin || reg->value == CPENS (0, C8, C1, 2)
4227 1.5.2.1 martin || reg->value == CPENS (0, C8, C1, 3)
4228 1.5.2.1 martin || reg->value == CPENS (0, C8, C1, 5)
4229 1.5.2.1 martin || reg->value == CPENS (0, C8, C1, 7)
4230 1.5.2.1 martin || reg->value == CPENS (4, C8, C4, 0)
4231 1.5.2.1 martin || reg->value == CPENS (4, C8, C4, 4)
4232 1.5.2.1 martin || reg->value == CPENS (4, C8, C1, 1)
4233 1.5.2.1 martin || reg->value == CPENS (4, C8, C1, 5)
4234 1.5.2.1 martin || reg->value == CPENS (4, C8, C1, 6)
4235 1.5.2.1 martin || reg->value == CPENS (6, C8, C1, 1)
4236 1.5.2.1 martin || reg->value == CPENS (6, C8, C1, 5)
4237 1.5.2.1 martin || reg->value == CPENS (4, C8, C1, 0)
4238 1.5.2.1 martin || reg->value == CPENS (4, C8, C1, 4)
4239 1.5.2.1 martin || reg->value == CPENS (6, C8, C1, 0)
4240 1.5.2.1 martin || reg->value == CPENS (0, C8, C6, 1)
4241 1.5.2.1 martin || reg->value == CPENS (0, C8, C6, 3)
4242 1.5.2.1 martin || reg->value == CPENS (0, C8, C6, 5)
4243 1.5.2.1 martin || reg->value == CPENS (0, C8, C6, 7)
4244 1.5.2.1 martin || reg->value == CPENS (0, C8, C2, 1)
4245 1.5.2.1 martin || reg->value == CPENS (0, C8, C2, 3)
4246 1.5.2.1 martin || reg->value == CPENS (0, C8, C2, 5)
4247 1.5.2.1 martin || reg->value == CPENS (0, C8, C2, 7)
4248 1.5.2.1 martin || reg->value == CPENS (0, C8, C5, 1)
4249 1.5.2.1 martin || reg->value == CPENS (0, C8, C5, 3)
4250 1.5.2.1 martin || reg->value == CPENS (0, C8, C5, 5)
4251 1.5.2.1 martin || reg->value == CPENS (0, C8, C5, 7)
4252 1.5.2.1 martin || reg->value == CPENS (4, C8, C0, 2)
4253 1.5.2.1 martin || reg->value == CPENS (4, C8, C0, 6)
4254 1.5.2.1 martin || reg->value == CPENS (4, C8, C4, 2)
4255 1.5.2.1 martin || reg->value == CPENS (4, C8, C4, 6)
4256 1.5.2.1 martin || reg->value == CPENS (4, C8, C4, 3)
4257 1.5.2.1 martin || reg->value == CPENS (4, C8, C4, 7)
4258 1.5.2.1 martin || reg->value == CPENS (4, C8, C6, 1)
4259 1.5.2.1 martin || reg->value == CPENS (4, C8, C6, 5)
4260 1.5.2.1 martin || reg->value == CPENS (4, C8, C2, 1)
4261 1.5.2.1 martin || reg->value == CPENS (4, C8, C2, 5)
4262 1.5.2.1 martin || reg->value == CPENS (4, C8, C5, 1)
4263 1.5.2.1 martin || reg->value == CPENS (4, C8, C5, 5)
4264 1.5.2.1 martin || reg->value == CPENS (6, C8, C6, 1)
4265 1.5.2.1 martin || reg->value == CPENS (6, C8, C6, 5)
4266 1.5.2.1 martin || reg->value == CPENS (6, C8, C2, 1)
4267 1.5.2.1 martin || reg->value == CPENS (6, C8, C2, 5)
4268 1.5.2.1 martin || reg->value == CPENS (6, C8, C5, 1)
4269 1.3 christos || reg->value == CPENS (6, C8, C5, 5))
4270 1.3 christos && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_4))
4271 1.3 christos return FALSE;
4272 1.5.2.1 martin
4273 1.5.2.1 martin return TRUE;
4274 1.5.2.1 martin }
4275 1.5.2.1 martin
4276 1.5.2.1 martin /* The CPENC below is fairly misleading, the fields
4277 1.5.2.1 martin here are not in CPENC form. They are in op2op1 form. The fields are encoded
4278 1.5.2.1 martin by ins_pstatefield, which just shifts the value by the width of the fields
4279 1.3 christos in a loop. So if you CPENC them only the first value will be set, the rest
4280 1.3 christos are masked out to 0. As an example. op2 = 3, op1=2. CPENC would produce a
4281 1.3 christos value of 0b110000000001000000 (0x30040) while what you want is
4282 1.3 christos 0b011010 (0x1a). */
4283 1.3 christos const aarch64_sys_reg aarch64_pstatefields [] =
4284 1.3 christos {
4285 1.3 christos { "spsel", 0x05, 0 },
4286 1.5.2.1 martin { "daifset", 0x1e, 0 },
4287 1.3 christos { "daifclr", 0x1f, 0 },
4288 1.1 christos { "pan", 0x04, F_ARCHEXT },
4289 1.1 christos { "uao", 0x03, F_ARCHEXT },
4290 1.3 christos { "dit", 0x1a, F_ARCHEXT },
4291 1.3 christos { 0, CPENC(0,0,0,0,0), 0 },
4292 1.3 christos };
4293 1.3 christos
4294 1.3 christos bfd_boolean
4295 1.3 christos aarch64_pstatefield_supported_p (const aarch64_feature_set features,
4296 1.3 christos const aarch64_sys_reg *reg)
4297 1.3 christos {
4298 1.3 christos if (!(reg->flags & F_ARCHEXT))
4299 1.3 christos return TRUE;
4300 1.3 christos
4301 1.3 christos /* PAN. Values are from aarch64_pstatefields. */
4302 1.3 christos if (reg->value == 0x04
4303 1.3 christos && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_PAN))
4304 1.3 christos return FALSE;
4305 1.3 christos
4306 1.3 christos /* UAO. Values are from aarch64_pstatefields. */
4307 1.5.2.1 martin if (reg->value == 0x03
4308 1.5.2.1 martin && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
4309 1.5.2.1 martin return FALSE;
4310 1.5.2.1 martin
4311 1.5.2.1 martin /* DIT. Values are from aarch64_pstatefields. */
4312 1.3 christos if (reg->value == 0x1a
4313 1.3 christos && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_4))
4314 1.3 christos return FALSE;
4315 1.1 christos
4316 1.1 christos return TRUE;
4317 1.1 christos }
4318 1.1 christos
4319 1.3 christos const aarch64_sys_ins_reg aarch64_sys_regs_ic[] =
4320 1.1 christos {
4321 1.1 christos { "ialluis", CPENS(0,C7,C1,0), 0 },
4322 1.1 christos { "iallu", CPENS(0,C7,C5,0), 0 },
4323 1.1 christos { "ivau", CPENS (3, C7, C5, 1), F_HASXT },
4324 1.1 christos { 0, CPENS(0,0,0,0), 0 }
4325 1.3 christos };
4326 1.3 christos
4327 1.3 christos const aarch64_sys_ins_reg aarch64_sys_regs_dc[] =
4328 1.3 christos {
4329 1.3 christos { "zva", CPENS (3, C7, C4, 1), F_HASXT },
4330 1.3 christos { "ivac", CPENS (0, C7, C6, 1), F_HASXT },
4331 1.3 christos { "isw", CPENS (0, C7, C6, 2), F_HASXT },
4332 1.3 christos { "cvac", CPENS (3, C7, C10, 1), F_HASXT },
4333 1.3 christos { "csw", CPENS (0, C7, C10, 2), F_HASXT },
4334 1.1 christos { "cvau", CPENS (3, C7, C11, 1), F_HASXT },
4335 1.1 christos { "cvap", CPENS (3, C7, C12, 1), F_HASXT | F_ARCHEXT },
4336 1.1 christos { "civac", CPENS (3, C7, C14, 1), F_HASXT },
4337 1.1 christos { "cisw", CPENS (0, C7, C14, 2), F_HASXT },
4338 1.1 christos { 0, CPENS(0,0,0,0), 0 }
4339 1.3 christos };
4340 1.3 christos
4341 1.3 christos const aarch64_sys_ins_reg aarch64_sys_regs_at[] =
4342 1.3 christos {
4343 1.3 christos { "s1e1r", CPENS (0, C7, C8, 0), F_HASXT },
4344 1.3 christos { "s1e1w", CPENS (0, C7, C8, 1), F_HASXT },
4345 1.3 christos { "s1e0r", CPENS (0, C7, C8, 2), F_HASXT },
4346 1.3 christos { "s1e0w", CPENS (0, C7, C8, 3), F_HASXT },
4347 1.3 christos { "s12e1r", CPENS (4, C7, C8, 4), F_HASXT },
4348 1.3 christos { "s12e1w", CPENS (4, C7, C8, 5), F_HASXT },
4349 1.3 christos { "s12e0r", CPENS (4, C7, C8, 6), F_HASXT },
4350 1.3 christos { "s12e0w", CPENS (4, C7, C8, 7), F_HASXT },
4351 1.3 christos { "s1e2r", CPENS (4, C7, C8, 0), F_HASXT },
4352 1.3 christos { "s1e2w", CPENS (4, C7, C8, 1), F_HASXT },
4353 1.1 christos { "s1e3r", CPENS (6, C7, C8, 0), F_HASXT },
4354 1.1 christos { "s1e3w", CPENS (6, C7, C8, 1), F_HASXT },
4355 1.1 christos { "s1e1rp", CPENS (0, C7, C9, 0), F_HASXT | F_ARCHEXT },
4356 1.1 christos { "s1e1wp", CPENS (0, C7, C9, 1), F_HASXT | F_ARCHEXT },
4357 1.1 christos { 0, CPENS(0,0,0,0), 0 }
4358 1.1 christos };
4359 1.3 christos
4360 1.3 christos const aarch64_sys_ins_reg aarch64_sys_regs_tlbi[] =
4361 1.3 christos {
4362 1.1 christos { "vmalle1", CPENS(0,C8,C7,0), 0 },
4363 1.3 christos { "vae1", CPENS (0, C8, C7, 1), F_HASXT },
4364 1.3 christos { "aside1", CPENS (0, C8, C7, 2), F_HASXT },
4365 1.3 christos { "vaae1", CPENS (0, C8, C7, 3), F_HASXT },
4366 1.3 christos { "vmalle1is", CPENS(0,C8,C3,0), 0 },
4367 1.3 christos { "vae1is", CPENS (0, C8, C3, 1), F_HASXT },
4368 1.3 christos { "aside1is", CPENS (0, C8, C3, 2), F_HASXT },
4369 1.3 christos { "vaae1is", CPENS (0, C8, C3, 3), F_HASXT },
4370 1.3 christos { "ipas2e1is", CPENS (4, C8, C0, 1), F_HASXT },
4371 1.3 christos { "ipas2le1is",CPENS (4, C8, C0, 5), F_HASXT },
4372 1.1 christos { "ipas2e1", CPENS (4, C8, C4, 1), F_HASXT },
4373 1.1 christos { "ipas2le1", CPENS (4, C8, C4, 5), F_HASXT },
4374 1.3 christos { "vae2", CPENS (4, C8, C7, 1), F_HASXT },
4375 1.3 christos { "vae2is", CPENS (4, C8, C3, 1), F_HASXT },
4376 1.1 christos { "vmalls12e1",CPENS(4,C8,C7,6), 0 },
4377 1.1 christos { "vmalls12e1is",CPENS(4,C8,C3,6), 0 },
4378 1.1 christos { "vae3", CPENS (6, C8, C7, 1), F_HASXT },
4379 1.1 christos { "vae3is", CPENS (6, C8, C3, 1), F_HASXT },
4380 1.1 christos { "alle2", CPENS(4,C8,C7,0), 0 },
4381 1.1 christos { "alle2is", CPENS(4,C8,C3,0), 0 },
4382 1.3 christos { "alle1", CPENS(4,C8,C7,4), 0 },
4383 1.3 christos { "alle1is", CPENS(4,C8,C3,4), 0 },
4384 1.3 christos { "alle3", CPENS(6,C8,C7,0), 0 },
4385 1.3 christos { "alle3is", CPENS(6,C8,C3,0), 0 },
4386 1.3 christos { "vale1is", CPENS (0, C8, C3, 5), F_HASXT },
4387 1.3 christos { "vale2is", CPENS (4, C8, C3, 5), F_HASXT },
4388 1.3 christos { "vale3is", CPENS (6, C8, C3, 5), F_HASXT },
4389 1.3 christos { "vaale1is", CPENS (0, C8, C3, 7), F_HASXT },
4390 1.5.2.1 martin { "vale1", CPENS (0, C8, C7, 5), F_HASXT },
4391 1.5.2.1 martin { "vale2", CPENS (4, C8, C7, 5), F_HASXT },
4392 1.5.2.1 martin { "vale3", CPENS (6, C8, C7, 5), F_HASXT },
4393 1.5.2.1 martin { "vaale1", CPENS (0, C8, C7, 7), F_HASXT },
4394 1.5.2.1 martin
4395 1.5.2.1 martin { "vmalle1os", CPENS (0, C8, C1, 0), F_ARCHEXT },
4396 1.5.2.1 martin { "vae1os", CPENS (0, C8, C1, 1), F_HASXT | F_ARCHEXT },
4397 1.5.2.1 martin { "aside1os", CPENS (0, C8, C1, 2), F_HASXT | F_ARCHEXT },
4398 1.5.2.1 martin { "vaae1os", CPENS (0, C8, C1, 3), F_HASXT | F_ARCHEXT },
4399 1.5.2.1 martin { "vale1os", CPENS (0, C8, C1, 5), F_HASXT | F_ARCHEXT },
4400 1.5.2.1 martin { "vaale1os", CPENS (0, C8, C1, 7), F_HASXT | F_ARCHEXT },
4401 1.5.2.1 martin { "ipas2e1os", CPENS (4, C8, C4, 0), F_HASXT | F_ARCHEXT },
4402 1.5.2.1 martin { "ipas2le1os", CPENS (4, C8, C4, 4), F_HASXT | F_ARCHEXT },
4403 1.5.2.1 martin { "vae2os", CPENS (4, C8, C1, 1), F_HASXT | F_ARCHEXT },
4404 1.5.2.1 martin { "vale2os", CPENS (4, C8, C1, 5), F_HASXT | F_ARCHEXT },
4405 1.5.2.1 martin { "vmalls12e1os", CPENS (4, C8, C1, 6), F_ARCHEXT },
4406 1.5.2.1 martin { "vae3os", CPENS (6, C8, C1, 1), F_HASXT | F_ARCHEXT },
4407 1.5.2.1 martin { "vale3os", CPENS (6, C8, C1, 5), F_HASXT | F_ARCHEXT },
4408 1.5.2.1 martin { "alle2os", CPENS (4, C8, C1, 0), F_ARCHEXT },
4409 1.5.2.1 martin { "alle1os", CPENS (4, C8, C1, 4), F_ARCHEXT },
4410 1.5.2.1 martin { "alle3os", CPENS (6, C8, C1, 0), F_ARCHEXT },
4411 1.5.2.1 martin
4412 1.5.2.1 martin { "rvae1", CPENS (0, C8, C6, 1), F_HASXT | F_ARCHEXT },
4413 1.5.2.1 martin { "rvaae1", CPENS (0, C8, C6, 3), F_HASXT | F_ARCHEXT },
4414 1.5.2.1 martin { "rvale1", CPENS (0, C8, C6, 5), F_HASXT | F_ARCHEXT },
4415 1.5.2.1 martin { "rvaale1", CPENS (0, C8, C6, 7), F_HASXT | F_ARCHEXT },
4416 1.5.2.1 martin { "rvae1is", CPENS (0, C8, C2, 1), F_HASXT | F_ARCHEXT },
4417 1.5.2.1 martin { "rvaae1is", CPENS (0, C8, C2, 3), F_HASXT | F_ARCHEXT },
4418 1.5.2.1 martin { "rvale1is", CPENS (0, C8, C2, 5), F_HASXT | F_ARCHEXT },
4419 1.5.2.1 martin { "rvaale1is", CPENS (0, C8, C2, 7), F_HASXT | F_ARCHEXT },
4420 1.5.2.1 martin { "rvae1os", CPENS (0, C8, C5, 1), F_HASXT | F_ARCHEXT },
4421 1.5.2.1 martin { "rvaae1os", CPENS (0, C8, C5, 3), F_HASXT | F_ARCHEXT },
4422 1.5.2.1 martin { "rvale1os", CPENS (0, C8, C5, 5), F_HASXT | F_ARCHEXT },
4423 1.5.2.1 martin { "rvaale1os", CPENS (0, C8, C5, 7), F_HASXT | F_ARCHEXT },
4424 1.5.2.1 martin { "ripas2e1is", CPENS (4, C8, C0, 2), F_HASXT | F_ARCHEXT },
4425 1.5.2.1 martin { "ripas2le1is",CPENS (4, C8, C0, 6), F_HASXT | F_ARCHEXT },
4426 1.5.2.1 martin { "ripas2e1", CPENS (4, C8, C4, 2), F_HASXT | F_ARCHEXT },
4427 1.5.2.1 martin { "ripas2le1", CPENS (4, C8, C4, 6), F_HASXT | F_ARCHEXT },
4428 1.5.2.1 martin { "ripas2e1os", CPENS (4, C8, C4, 3), F_HASXT | F_ARCHEXT },
4429 1.5.2.1 martin { "ripas2le1os",CPENS (4, C8, C4, 7), F_HASXT | F_ARCHEXT },
4430 1.5.2.1 martin { "rvae2", CPENS (4, C8, C6, 1), F_HASXT | F_ARCHEXT },
4431 1.5.2.1 martin { "rvale2", CPENS (4, C8, C6, 5), F_HASXT | F_ARCHEXT },
4432 1.5.2.1 martin { "rvae2is", CPENS (4, C8, C2, 1), F_HASXT | F_ARCHEXT },
4433 1.5.2.1 martin { "rvale2is", CPENS (4, C8, C2, 5), F_HASXT | F_ARCHEXT },
4434 1.5.2.1 martin { "rvae2os", CPENS (4, C8, C5, 1), F_HASXT | F_ARCHEXT },
4435 1.5.2.1 martin { "rvale2os", CPENS (4, C8, C5, 5), F_HASXT | F_ARCHEXT },
4436 1.5.2.1 martin { "rvae3", CPENS (6, C8, C6, 1), F_HASXT | F_ARCHEXT },
4437 1.5.2.1 martin { "rvale3", CPENS (6, C8, C6, 5), F_HASXT | F_ARCHEXT },
4438 1.5.2.1 martin { "rvae3is", CPENS (6, C8, C2, 1), F_HASXT | F_ARCHEXT },
4439 1.1 christos { "rvale3is", CPENS (6, C8, C2, 5), F_HASXT | F_ARCHEXT },
4440 1.1 christos { "rvae3os", CPENS (6, C8, C5, 1), F_HASXT | F_ARCHEXT },
4441 1.1 christos { "rvale3os", CPENS (6, C8, C5, 5), F_HASXT | F_ARCHEXT },
4442 1.3 christos
4443 1.3 christos { 0, CPENS(0,0,0,0), 0 }
4444 1.3 christos };
4445 1.3 christos
4446 1.3 christos bfd_boolean
4447 1.3 christos aarch64_sys_ins_reg_has_xt (const aarch64_sys_ins_reg *sys_ins_reg)
4448 1.3 christos {
4449 1.3 christos return (sys_ins_reg->flags & F_HASXT) != 0;
4450 1.3 christos }
4451 1.3 christos
4452 1.3 christos extern bfd_boolean
4453 1.3 christos aarch64_sys_ins_reg_supported_p (const aarch64_feature_set features,
4454 1.3 christos const aarch64_sys_ins_reg *reg)
4455 1.3 christos {
4456 1.3 christos if (!(reg->flags & F_ARCHEXT))
4457 1.3 christos return TRUE;
4458 1.3 christos
4459 1.3 christos /* DC CVAP. Values are from aarch64_sys_regs_dc. */
4460 1.3 christos if (reg->value == CPENS (3, C7, C12, 1)
4461 1.3 christos && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
4462 1.3 christos return FALSE;
4463 1.3 christos
4464 1.3 christos /* AT S1E1RP, AT S1E1WP. Values are from aarch64_sys_regs_at. */
4465 1.3 christos if ((reg->value == CPENS (0, C7, C9, 0)
4466 1.3 christos || reg->value == CPENS (0, C7, C9, 1))
4467 1.3 christos && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
4468 1.3 christos return FALSE;
4469 1.1 christos
4470 1.1 christos return TRUE;
4471 1.1 christos }
4472 1.1 christos
4473 1.1 christos #undef C0
4474 1.1 christos #undef C1
4475 1.1 christos #undef C2
4476 1.1 christos #undef C3
4477 1.1 christos #undef C4
4478 1.1 christos #undef C5
4479 1.1 christos #undef C6
4480 1.1 christos #undef C7
4481 1.1 christos #undef C8
4482 1.1 christos #undef C9
4483 1.1 christos #undef C10
4484 1.1 christos #undef C11
4485 1.1 christos #undef C12
4486 1.5 christos #undef C13
4487 1.5 christos #undef C14
4488 1.5 christos #undef C15
4489 1.5 christos
4490 1.5 christos #define BIT(INSN,BT) (((INSN) >> (BT)) & 1)
4491 1.5 christos #define BITS(INSN,HI,LO) (((INSN) >> (LO)) & ((1 << (((HI) - (LO)) + 1)) - 1))
4492 1.5 christos
4493 1.5 christos static bfd_boolean
4494 1.5 christos verify_ldpsw (const struct aarch64_opcode * opcode ATTRIBUTE_UNUSED,
4495 1.5 christos const aarch64_insn insn)
4496 1.5 christos {
4497 1.5 christos int t = BITS (insn, 4, 0);
4498 1.5 christos int n = BITS (insn, 9, 5);
4499 1.5 christos int t2 = BITS (insn, 14, 10);
4500 1.5 christos
4501 1.5 christos if (BIT (insn, 23))
4502 1.5 christos {
4503 1.5 christos /* Write back enabled. */
4504 1.5 christos if ((t == n || t2 == n) && n != 31)
4505 1.5 christos return FALSE;
4506 1.5 christos }
4507 1.5 christos
4508 1.5 christos if (BIT (insn, 22))
4509 1.5 christos {
4510 1.5 christos /* Load */
4511 1.5 christos if (t == t2)
4512 1.5 christos return FALSE;
4513 1.5 christos }
4514 1.5.2.1 martin
4515 1.5.2.1 martin return TRUE;
4516 1.5.2.1 martin }
4517 1.5.2.1 martin
4518 1.5.2.1 martin /* Return true if VALUE cannot be moved into an SVE register using DUP
4519 1.5.2.1 martin (with any element size, not just ESIZE) and if using DUPM would
4520 1.5.2.1 martin therefore be OK. ESIZE is the number of bytes in the immediate. */
4521 1.5.2.1 martin
4522 1.5.2.1 martin bfd_boolean
4523 1.5.2.1 martin aarch64_sve_dupm_mov_immediate_p (uint64_t uvalue, int esize)
4524 1.5.2.1 martin {
4525 1.5.2.1 martin int64_t svalue = uvalue;
4526 1.5.2.1 martin uint64_t upper = (uint64_t) -1 << (esize * 4) << (esize * 4);
4527 1.5.2.1 martin
4528 1.5.2.1 martin if ((uvalue & ~upper) != uvalue && (uvalue | upper) != uvalue)
4529 1.5.2.1 martin return FALSE;
4530 1.5.2.1 martin if (esize <= 4 || (uint32_t) uvalue == (uint32_t) (uvalue >> 32))
4531 1.5.2.1 martin {
4532 1.5.2.1 martin svalue = (int32_t) uvalue;
4533 1.5.2.1 martin if (esize <= 2 || (uint16_t) uvalue == (uint16_t) (uvalue >> 16))
4534 1.5.2.1 martin {
4535 1.5.2.1 martin svalue = (int16_t) uvalue;
4536 1.5.2.1 martin if (esize == 1 || (uint8_t) uvalue == (uint8_t) (uvalue >> 8))
4537 1.5.2.1 martin return FALSE;
4538 1.5.2.1 martin }
4539 1.5.2.1 martin }
4540 1.5.2.1 martin if ((svalue & 0xff) == 0)
4541 1.1 christos svalue /= 256;
4542 1.1 christos return svalue < -128 || svalue >= 128;
4543 1.5 christos }
4544 1.1 christos
4545 /* Include the opcode description table as well as the operand description
4546 table. */
4547 #define VERIFIER(x) verify_##x
4548 #include "aarch64-tbl.h"
4549