aarch64-opc.c revision 1.1 1 1.1 christos /* aarch64-opc.c -- AArch64 opcode support.
2 1.1 christos Copyright 2009, 2010, 2011, 2012, 2013 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.1 christos
31 1.1 christos #include "aarch64-opc.h"
32 1.1 christos
33 1.1 christos #ifdef DEBUG_AARCH64
34 1.1 christos int debug_dump = FALSE;
35 1.1 christos #endif /* DEBUG_AARCH64 */
36 1.1 christos
37 1.1 christos /* Helper functions to determine which operand to be used to encode/decode
38 1.1 christos the size:Q fields for AdvSIMD instructions. */
39 1.1 christos
40 1.1 christos static inline bfd_boolean
41 1.1 christos vector_qualifier_p (enum aarch64_opnd_qualifier qualifier)
42 1.1 christos {
43 1.1 christos return ((qualifier >= AARCH64_OPND_QLF_V_8B
44 1.1 christos && qualifier <= AARCH64_OPND_QLF_V_1Q) ? TRUE
45 1.1 christos : FALSE);
46 1.1 christos }
47 1.1 christos
48 1.1 christos static inline bfd_boolean
49 1.1 christos fp_qualifier_p (enum aarch64_opnd_qualifier qualifier)
50 1.1 christos {
51 1.1 christos return ((qualifier >= AARCH64_OPND_QLF_S_B
52 1.1 christos && qualifier <= AARCH64_OPND_QLF_S_Q) ? TRUE
53 1.1 christos : FALSE);
54 1.1 christos }
55 1.1 christos
56 1.1 christos enum data_pattern
57 1.1 christos {
58 1.1 christos DP_UNKNOWN,
59 1.1 christos DP_VECTOR_3SAME,
60 1.1 christos DP_VECTOR_LONG,
61 1.1 christos DP_VECTOR_WIDE,
62 1.1 christos DP_VECTOR_ACROSS_LANES,
63 1.1 christos };
64 1.1 christos
65 1.1 christos static const char significant_operand_index [] =
66 1.1 christos {
67 1.1 christos 0, /* DP_UNKNOWN, by default using operand 0. */
68 1.1 christos 0, /* DP_VECTOR_3SAME */
69 1.1 christos 1, /* DP_VECTOR_LONG */
70 1.1 christos 2, /* DP_VECTOR_WIDE */
71 1.1 christos 1, /* DP_VECTOR_ACROSS_LANES */
72 1.1 christos };
73 1.1 christos
74 1.1 christos /* Given a sequence of qualifiers in QUALIFIERS, determine and return
75 1.1 christos the data pattern.
76 1.1 christos N.B. QUALIFIERS is a possible sequence of qualifiers each of which
77 1.1 christos corresponds to one of a sequence of operands. */
78 1.1 christos
79 1.1 christos static enum data_pattern
80 1.1 christos get_data_pattern (const aarch64_opnd_qualifier_seq_t qualifiers)
81 1.1 christos {
82 1.1 christos if (vector_qualifier_p (qualifiers[0]) == TRUE)
83 1.1 christos {
84 1.1 christos /* e.g. v.4s, v.4s, v.4s
85 1.1 christos or v.4h, v.4h, v.h[3]. */
86 1.1 christos if (qualifiers[0] == qualifiers[1]
87 1.1 christos && vector_qualifier_p (qualifiers[2]) == TRUE
88 1.1 christos && (aarch64_get_qualifier_esize (qualifiers[0])
89 1.1 christos == aarch64_get_qualifier_esize (qualifiers[1]))
90 1.1 christos && (aarch64_get_qualifier_esize (qualifiers[0])
91 1.1 christos == aarch64_get_qualifier_esize (qualifiers[2])))
92 1.1 christos return DP_VECTOR_3SAME;
93 1.1 christos /* e.g. v.8h, v.8b, v.8b.
94 1.1 christos or v.4s, v.4h, v.h[2].
95 1.1 christos or v.8h, v.16b. */
96 1.1 christos if (vector_qualifier_p (qualifiers[1]) == TRUE
97 1.1 christos && aarch64_get_qualifier_esize (qualifiers[0]) != 0
98 1.1 christos && (aarch64_get_qualifier_esize (qualifiers[0])
99 1.1 christos == aarch64_get_qualifier_esize (qualifiers[1]) << 1))
100 1.1 christos return DP_VECTOR_LONG;
101 1.1 christos /* e.g. v.8h, v.8h, v.8b. */
102 1.1 christos if (qualifiers[0] == qualifiers[1]
103 1.1 christos && vector_qualifier_p (qualifiers[2]) == TRUE
104 1.1 christos && aarch64_get_qualifier_esize (qualifiers[0]) != 0
105 1.1 christos && (aarch64_get_qualifier_esize (qualifiers[0])
106 1.1 christos == aarch64_get_qualifier_esize (qualifiers[2]) << 1)
107 1.1 christos && (aarch64_get_qualifier_esize (qualifiers[0])
108 1.1 christos == aarch64_get_qualifier_esize (qualifiers[1])))
109 1.1 christos return DP_VECTOR_WIDE;
110 1.1 christos }
111 1.1 christos else if (fp_qualifier_p (qualifiers[0]) == TRUE)
112 1.1 christos {
113 1.1 christos /* e.g. SADDLV <V><d>, <Vn>.<T>. */
114 1.1 christos if (vector_qualifier_p (qualifiers[1]) == TRUE
115 1.1 christos && qualifiers[2] == AARCH64_OPND_QLF_NIL)
116 1.1 christos return DP_VECTOR_ACROSS_LANES;
117 1.1 christos }
118 1.1 christos
119 1.1 christos return DP_UNKNOWN;
120 1.1 christos }
121 1.1 christos
122 1.1 christos /* Select the operand to do the encoding/decoding of the 'size:Q' fields in
123 1.1 christos the AdvSIMD instructions. */
124 1.1 christos /* N.B. it is possible to do some optimization that doesn't call
125 1.1 christos get_data_pattern each time when we need to select an operand. We can
126 1.1 christos either buffer the caculated the result or statically generate the data,
127 1.1 christos however, it is not obvious that the optimization will bring significant
128 1.1 christos benefit. */
129 1.1 christos
130 1.1 christos int
131 1.1 christos aarch64_select_operand_for_sizeq_field_coding (const aarch64_opcode *opcode)
132 1.1 christos {
133 1.1 christos return
134 1.1 christos significant_operand_index [get_data_pattern (opcode->qualifiers_list[0])];
135 1.1 christos }
136 1.1 christos
137 1.1 christos const aarch64_field fields[] =
139 1.1 christos {
140 1.1 christos { 0, 0 }, /* NIL. */
141 1.1 christos { 0, 4 }, /* cond2: condition in truly conditional-executed inst. */
142 1.1 christos { 0, 4 }, /* nzcv: flag bit specifier, encoded in the "nzcv" field. */
143 1.1 christos { 5, 5 }, /* defgh: d:e:f:g:h bits in AdvSIMD modified immediate. */
144 1.1 christos { 16, 3 }, /* abc: a:b:c bits in AdvSIMD modified immediate. */
145 1.1 christos { 5, 19 }, /* imm19: e.g. in CBZ. */
146 1.1 christos { 5, 19 }, /* immhi: e.g. in ADRP. */
147 1.1 christos { 29, 2 }, /* immlo: e.g. in ADRP. */
148 1.1 christos { 22, 2 }, /* size: in most AdvSIMD and floating-point instructions. */
149 1.1 christos { 10, 2 }, /* vldst_size: size field in the AdvSIMD load/store inst. */
150 1.1 christos { 29, 1 }, /* op: in AdvSIMD modified immediate instructions. */
151 1.1 christos { 30, 1 }, /* Q: in most AdvSIMD instructions. */
152 1.1 christos { 0, 5 }, /* Rt: in load/store instructions. */
153 1.1 christos { 0, 5 }, /* Rd: in many integer instructions. */
154 1.1 christos { 5, 5 }, /* Rn: in many integer instructions. */
155 1.1 christos { 10, 5 }, /* Rt2: in load/store pair instructions. */
156 1.1 christos { 10, 5 }, /* Ra: in fp instructions. */
157 1.1 christos { 5, 3 }, /* op2: in the system instructions. */
158 1.1 christos { 8, 4 }, /* CRm: in the system instructions. */
159 1.1 christos { 12, 4 }, /* CRn: in the system instructions. */
160 1.1 christos { 16, 3 }, /* op1: in the system instructions. */
161 1.1 christos { 19, 2 }, /* op0: in the system instructions. */
162 1.1 christos { 10, 3 }, /* imm3: in add/sub extended reg instructions. */
163 1.1 christos { 12, 4 }, /* cond: condition flags as a source operand. */
164 1.1 christos { 12, 4 }, /* opcode: in advsimd load/store instructions. */
165 1.1 christos { 12, 4 }, /* cmode: in advsimd modified immediate instructions. */
166 1.1 christos { 13, 3 }, /* asisdlso_opcode: opcode in advsimd ld/st single element. */
167 1.1 christos { 13, 2 }, /* len: in advsimd tbl/tbx instructions. */
168 1.1 christos { 16, 5 }, /* Rm: in ld/st reg offset and some integer inst. */
169 1.1 christos { 16, 5 }, /* Rs: in load/store exclusive instructions. */
170 1.1 christos { 13, 3 }, /* option: in ld/st reg offset + add/sub extended reg inst. */
171 1.1 christos { 12, 1 }, /* S: in load/store reg offset instructions. */
172 1.1 christos { 21, 2 }, /* hw: in move wide constant instructions. */
173 1.1 christos { 22, 2 }, /* opc: in load/store reg offset instructions. */
174 1.1 christos { 23, 1 }, /* opc1: in load/store reg offset instructions. */
175 1.1 christos { 22, 2 }, /* shift: in add/sub reg/imm shifted instructions. */
176 1.1 christos { 22, 2 }, /* type: floating point type field in fp data inst. */
177 1.1 christos { 30, 2 }, /* ldst_size: size field in ld/st reg offset inst. */
178 1.1 christos { 10, 6 }, /* imm6: in add/sub reg shifted instructions. */
179 1.1 christos { 11, 4 }, /* imm4: in advsimd ext and advsimd ins instructions. */
180 1.1 christos { 16, 5 }, /* imm5: in conditional compare (immediate) instructions. */
181 1.1 christos { 15, 7 }, /* imm7: in load/store pair pre/post index instructions. */
182 1.1 christos { 13, 8 }, /* imm8: in floating-point scalar move immediate inst. */
183 1.1 christos { 12, 9 }, /* imm9: in load/store pre/post index instructions. */
184 1.1 christos { 10, 12 }, /* imm12: in ld/st unsigned imm or add/sub shifted inst. */
185 1.1 christos { 5, 14 }, /* imm14: in test bit and branch instructions. */
186 1.1 christos { 5, 16 }, /* imm16: in exception instructions. */
187 1.1 christos { 0, 26 }, /* imm26: in unconditional branch instructions. */
188 1.1 christos { 10, 6 }, /* imms: in bitfield and logical immediate instructions. */
189 1.1 christos { 16, 6 }, /* immr: in bitfield and logical immediate instructions. */
190 1.1 christos { 16, 3 }, /* immb: in advsimd shift by immediate instructions. */
191 1.1 christos { 19, 4 }, /* immh: in advsimd shift by immediate instructions. */
192 1.1 christos { 22, 1 }, /* N: in logical (immediate) instructions. */
193 1.1 christos { 11, 1 }, /* index: in ld/st inst deciding the pre/post-index. */
194 1.1 christos { 24, 1 }, /* index2: in ld/st pair inst deciding the pre/post-index. */
195 1.1 christos { 31, 1 }, /* sf: in integer data processing instructions. */
196 1.1 christos { 11, 1 }, /* H: in advsimd scalar x indexed element instructions. */
197 1.1 christos { 21, 1 }, /* L: in advsimd scalar x indexed element instructions. */
198 1.1 christos { 20, 1 }, /* M: in advsimd scalar x indexed element instructions. */
199 1.1 christos { 31, 1 }, /* b5: in the test bit and branch instructions. */
200 1.1 christos { 19, 5 }, /* b40: in the test bit and branch instructions. */
201 1.1 christos { 10, 6 }, /* scale: in the fixed-point scalar to fp converting inst. */
202 1.1 christos };
203 1.1 christos
204 1.1 christos enum aarch64_operand_class
205 1.1 christos aarch64_get_operand_class (enum aarch64_opnd type)
206 1.1 christos {
207 1.1 christos return aarch64_operands[type].op_class;
208 1.1 christos }
209 1.1 christos
210 1.1 christos const char *
211 1.1 christos aarch64_get_operand_name (enum aarch64_opnd type)
212 1.1 christos {
213 1.1 christos return aarch64_operands[type].name;
214 1.1 christos }
215 1.1 christos
216 1.1 christos /* Get operand description string.
217 1.1 christos This is usually for the diagnosis purpose. */
218 1.1 christos const char *
219 1.1 christos aarch64_get_operand_desc (enum aarch64_opnd type)
220 1.1 christos {
221 1.1 christos return aarch64_operands[type].desc;
222 1.1 christos }
223 1.1 christos
224 1.1 christos /* Table of all conditional affixes. */
225 1.1 christos const aarch64_cond aarch64_conds[16] =
226 1.1 christos {
227 1.1 christos {{"eq"}, 0x0},
228 1.1 christos {{"ne"}, 0x1},
229 1.1 christos {{"cs", "hs"}, 0x2},
230 1.1 christos {{"cc", "lo", "ul"}, 0x3},
231 1.1 christos {{"mi"}, 0x4},
232 1.1 christos {{"pl"}, 0x5},
233 1.1 christos {{"vs"}, 0x6},
234 1.1 christos {{"vc"}, 0x7},
235 1.1 christos {{"hi"}, 0x8},
236 1.1 christos {{"ls"}, 0x9},
237 1.1 christos {{"ge"}, 0xa},
238 1.1 christos {{"lt"}, 0xb},
239 1.1 christos {{"gt"}, 0xc},
240 1.1 christos {{"le"}, 0xd},
241 1.1 christos {{"al"}, 0xe},
242 1.1 christos {{"nv"}, 0xf},
243 1.1 christos };
244 1.1 christos
245 1.1 christos const aarch64_cond *
246 1.1 christos get_cond_from_value (aarch64_insn value)
247 1.1 christos {
248 1.1 christos assert (value < 16);
249 1.1 christos return &aarch64_conds[(unsigned int) value];
250 1.1 christos }
251 1.1 christos
252 1.1 christos const aarch64_cond *
253 1.1 christos get_inverted_cond (const aarch64_cond *cond)
254 1.1 christos {
255 1.1 christos return &aarch64_conds[cond->value ^ 0x1];
256 1.1 christos }
257 1.1 christos
258 1.1 christos /* Table describing the operand extension/shifting operators; indexed by
259 1.1 christos enum aarch64_modifier_kind.
260 1.1 christos
261 1.1 christos The value column provides the most common values for encoding modifiers,
262 1.1 christos which enables table-driven encoding/decoding for the modifiers. */
263 1.1 christos const struct aarch64_name_value_pair aarch64_operand_modifiers [] =
264 1.1 christos {
265 1.1 christos {"none", 0x0},
266 1.1 christos {"msl", 0x0},
267 1.1 christos {"ror", 0x3},
268 1.1 christos {"asr", 0x2},
269 1.1 christos {"lsr", 0x1},
270 1.1 christos {"lsl", 0x0},
271 1.1 christos {"uxtb", 0x0},
272 1.1 christos {"uxth", 0x1},
273 1.1 christos {"uxtw", 0x2},
274 1.1 christos {"uxtx", 0x3},
275 1.1 christos {"sxtb", 0x4},
276 1.1 christos {"sxth", 0x5},
277 1.1 christos {"sxtw", 0x6},
278 1.1 christos {"sxtx", 0x7},
279 1.1 christos {NULL, 0},
280 1.1 christos };
281 1.1 christos
282 1.1 christos enum aarch64_modifier_kind
283 1.1 christos aarch64_get_operand_modifier (const struct aarch64_name_value_pair *desc)
284 1.1 christos {
285 1.1 christos return desc - aarch64_operand_modifiers;
286 1.1 christos }
287 1.1 christos
288 1.1 christos aarch64_insn
289 1.1 christos aarch64_get_operand_modifier_value (enum aarch64_modifier_kind kind)
290 1.1 christos {
291 1.1 christos return aarch64_operand_modifiers[kind].value;
292 1.1 christos }
293 1.1 christos
294 1.1 christos enum aarch64_modifier_kind
295 1.1 christos aarch64_get_operand_modifier_from_value (aarch64_insn value,
296 1.1 christos bfd_boolean extend_p)
297 1.1 christos {
298 1.1 christos if (extend_p == TRUE)
299 1.1 christos return AARCH64_MOD_UXTB + value;
300 1.1 christos else
301 1.1 christos return AARCH64_MOD_LSL - value;
302 1.1 christos }
303 1.1 christos
304 1.1 christos bfd_boolean
305 1.1 christos aarch64_extend_operator_p (enum aarch64_modifier_kind kind)
306 1.1 christos {
307 1.1 christos return (kind > AARCH64_MOD_LSL && kind <= AARCH64_MOD_SXTX)
308 1.1 christos ? TRUE : FALSE;
309 1.1 christos }
310 1.1 christos
311 1.1 christos static inline bfd_boolean
312 1.1 christos aarch64_shift_operator_p (enum aarch64_modifier_kind kind)
313 1.1 christos {
314 1.1 christos return (kind >= AARCH64_MOD_ROR && kind <= AARCH64_MOD_LSL)
315 1.1 christos ? TRUE : FALSE;
316 1.1 christos }
317 1.1 christos
318 1.1 christos const struct aarch64_name_value_pair aarch64_barrier_options[16] =
319 1.1 christos {
320 1.1 christos { "#0x00", 0x0 },
321 1.1 christos { "oshld", 0x1 },
322 1.1 christos { "oshst", 0x2 },
323 1.1 christos { "osh", 0x3 },
324 1.1 christos { "#0x04", 0x4 },
325 1.1 christos { "nshld", 0x5 },
326 1.1 christos { "nshst", 0x6 },
327 1.1 christos { "nsh", 0x7 },
328 1.1 christos { "#0x08", 0x8 },
329 1.1 christos { "ishld", 0x9 },
330 1.1 christos { "ishst", 0xa },
331 1.1 christos { "ish", 0xb },
332 1.1 christos { "#0x0c", 0xc },
333 1.1 christos { "ld", 0xd },
334 1.1 christos { "st", 0xe },
335 1.1 christos { "sy", 0xf },
336 1.1 christos };
337 1.1 christos
338 1.1 christos /* op -> op: load = 0 instruction = 1 store = 2
339 1.1 christos l -> level: 1-3
340 1.1 christos t -> temporal: temporal (retained) = 0 non-temporal (streaming) = 1 */
341 1.1 christos #define B(op,l,t) (((op) << 3) | (((l) - 1) << 1) | (t))
342 1.1 christos const struct aarch64_name_value_pair aarch64_prfops[32] =
343 1.1 christos {
344 1.1 christos { "pldl1keep", B(0, 1, 0) },
345 1.1 christos { "pldl1strm", B(0, 1, 1) },
346 1.1 christos { "pldl2keep", B(0, 2, 0) },
347 1.1 christos { "pldl2strm", B(0, 2, 1) },
348 1.1 christos { "pldl3keep", B(0, 3, 0) },
349 1.1 christos { "pldl3strm", B(0, 3, 1) },
350 1.1 christos { NULL, 0x06 },
351 1.1 christos { NULL, 0x07 },
352 1.1 christos { "plil1keep", B(1, 1, 0) },
353 1.1 christos { "plil1strm", B(1, 1, 1) },
354 1.1 christos { "plil2keep", B(1, 2, 0) },
355 1.1 christos { "plil2strm", B(1, 2, 1) },
356 1.1 christos { "plil3keep", B(1, 3, 0) },
357 1.1 christos { "plil3strm", B(1, 3, 1) },
358 1.1 christos { NULL, 0x0e },
359 1.1 christos { NULL, 0x0f },
360 1.1 christos { "pstl1keep", B(2, 1, 0) },
361 1.1 christos { "pstl1strm", B(2, 1, 1) },
362 1.1 christos { "pstl2keep", B(2, 2, 0) },
363 1.1 christos { "pstl2strm", B(2, 2, 1) },
364 1.1 christos { "pstl3keep", B(2, 3, 0) },
365 1.1 christos { "pstl3strm", B(2, 3, 1) },
366 1.1 christos { NULL, 0x16 },
367 1.1 christos { NULL, 0x17 },
368 1.1 christos { NULL, 0x18 },
369 1.1 christos { NULL, 0x19 },
370 1.1 christos { NULL, 0x1a },
371 1.1 christos { NULL, 0x1b },
372 1.1 christos { NULL, 0x1c },
373 1.1 christos { NULL, 0x1d },
374 1.1 christos { NULL, 0x1e },
375 1.1 christos { NULL, 0x1f },
376 1.1 christos };
377 1.1 christos #undef B
378 1.1 christos
379 1.1 christos /* Utilities on value constraint. */
381 1.1 christos
382 1.1 christos static inline int
383 1.1 christos value_in_range_p (int64_t value, int low, int high)
384 1.1 christos {
385 1.1 christos return (value >= low && value <= high) ? 1 : 0;
386 1.1 christos }
387 1.1 christos
388 1.1 christos static inline int
389 1.1 christos value_aligned_p (int64_t value, int align)
390 1.1 christos {
391 1.1 christos return ((value & (align - 1)) == 0) ? 1 : 0;
392 1.1 christos }
393 1.1 christos
394 1.1 christos /* A signed value fits in a field. */
395 1.1 christos static inline int
396 1.1 christos value_fit_signed_field_p (int64_t value, unsigned width)
397 1.1 christos {
398 1.1 christos assert (width < 32);
399 1.1 christos if (width < sizeof (value) * 8)
400 1.1 christos {
401 1.1 christos int64_t lim = (int64_t)1 << (width - 1);
402 1.1 christos if (value >= -lim && value < lim)
403 1.1 christos return 1;
404 1.1 christos }
405 1.1 christos return 0;
406 1.1 christos }
407 1.1 christos
408 1.1 christos /* An unsigned value fits in a field. */
409 1.1 christos static inline int
410 1.1 christos value_fit_unsigned_field_p (int64_t value, unsigned width)
411 1.1 christos {
412 1.1 christos assert (width < 32);
413 1.1 christos if (width < sizeof (value) * 8)
414 1.1 christos {
415 1.1 christos int64_t lim = (int64_t)1 << width;
416 1.1 christos if (value >= 0 && value < lim)
417 1.1 christos return 1;
418 1.1 christos }
419 1.1 christos return 0;
420 1.1 christos }
421 1.1 christos
422 1.1 christos /* Return 1 if OPERAND is SP or WSP. */
423 1.1 christos int
424 1.1 christos aarch64_stack_pointer_p (const aarch64_opnd_info *operand)
425 1.1 christos {
426 1.1 christos return ((aarch64_get_operand_class (operand->type)
427 1.1 christos == AARCH64_OPND_CLASS_INT_REG)
428 1.1 christos && operand_maybe_stack_pointer (aarch64_operands + operand->type)
429 1.1 christos && operand->reg.regno == 31);
430 1.1 christos }
431 1.1 christos
432 1.1 christos /* Return 1 if OPERAND is XZR or WZP. */
433 1.1 christos int
434 1.1 christos aarch64_zero_register_p (const aarch64_opnd_info *operand)
435 1.1 christos {
436 1.1 christos return ((aarch64_get_operand_class (operand->type)
437 1.1 christos == AARCH64_OPND_CLASS_INT_REG)
438 1.1 christos && !operand_maybe_stack_pointer (aarch64_operands + operand->type)
439 1.1 christos && operand->reg.regno == 31);
440 1.1 christos }
441 1.1 christos
442 1.1 christos /* Return true if the operand *OPERAND that has the operand code
443 1.1 christos OPERAND->TYPE and been qualified by OPERAND->QUALIFIER can be also
444 1.1 christos qualified by the qualifier TARGET. */
445 1.1 christos
446 1.1 christos static inline int
447 1.1 christos operand_also_qualified_p (const struct aarch64_opnd_info *operand,
448 1.1 christos aarch64_opnd_qualifier_t target)
449 1.1 christos {
450 1.1 christos switch (operand->qualifier)
451 1.1 christos {
452 1.1 christos case AARCH64_OPND_QLF_W:
453 1.1 christos if (target == AARCH64_OPND_QLF_WSP && aarch64_stack_pointer_p (operand))
454 1.1 christos return 1;
455 1.1 christos break;
456 1.1 christos case AARCH64_OPND_QLF_X:
457 1.1 christos if (target == AARCH64_OPND_QLF_SP && aarch64_stack_pointer_p (operand))
458 1.1 christos return 1;
459 1.1 christos break;
460 1.1 christos case AARCH64_OPND_QLF_WSP:
461 1.1 christos if (target == AARCH64_OPND_QLF_W
462 1.1 christos && operand_maybe_stack_pointer (aarch64_operands + operand->type))
463 1.1 christos return 1;
464 1.1 christos break;
465 1.1 christos case AARCH64_OPND_QLF_SP:
466 1.1 christos if (target == AARCH64_OPND_QLF_X
467 1.1 christos && operand_maybe_stack_pointer (aarch64_operands + operand->type))
468 1.1 christos return 1;
469 1.1 christos break;
470 1.1 christos default:
471 1.1 christos break;
472 1.1 christos }
473 1.1 christos
474 1.1 christos return 0;
475 1.1 christos }
476 1.1 christos
477 1.1 christos /* Given qualifier sequence list QSEQ_LIST and the known qualifier KNOWN_QLF
478 1.1 christos for operand KNOWN_IDX, return the expected qualifier for operand IDX.
479 1.1 christos
480 1.1 christos Return NIL if more than one expected qualifiers are found. */
481 1.1 christos
482 1.1 christos aarch64_opnd_qualifier_t
483 1.1 christos aarch64_get_expected_qualifier (const aarch64_opnd_qualifier_seq_t *qseq_list,
484 1.1 christos int idx,
485 1.1 christos const aarch64_opnd_qualifier_t known_qlf,
486 1.1 christos int known_idx)
487 1.1 christos {
488 1.1 christos int i, saved_i;
489 1.1 christos
490 1.1 christos /* Special case.
491 1.1 christos
492 1.1 christos When the known qualifier is NIL, we have to assume that there is only
493 1.1 christos one qualifier sequence in the *QSEQ_LIST and return the corresponding
494 1.1 christos qualifier directly. One scenario is that for instruction
495 1.1 christos PRFM <prfop>, [<Xn|SP>, #:lo12:<symbol>]
496 1.1 christos which has only one possible valid qualifier sequence
497 1.1 christos NIL, S_D
498 1.1 christos the caller may pass NIL in KNOWN_QLF to obtain S_D so that it can
499 1.1 christos determine the correct relocation type (i.e. LDST64_LO12) for PRFM.
500 1.1 christos
501 1.1 christos Because the qualifier NIL has dual roles in the qualifier sequence:
502 1.1 christos it can mean no qualifier for the operand, or the qualifer sequence is
503 1.1 christos not in use (when all qualifiers in the sequence are NILs), we have to
504 1.1 christos handle this special case here. */
505 1.1 christos if (known_qlf == AARCH64_OPND_NIL)
506 1.1 christos {
507 1.1 christos assert (qseq_list[0][known_idx] == AARCH64_OPND_NIL);
508 1.1 christos return qseq_list[0][idx];
509 1.1 christos }
510 1.1 christos
511 1.1 christos for (i = 0, saved_i = -1; i < AARCH64_MAX_QLF_SEQ_NUM; ++i)
512 1.1 christos {
513 1.1 christos if (qseq_list[i][known_idx] == known_qlf)
514 1.1 christos {
515 1.1 christos if (saved_i != -1)
516 1.1 christos /* More than one sequences are found to have KNOWN_QLF at
517 1.1 christos KNOWN_IDX. */
518 1.1 christos return AARCH64_OPND_NIL;
519 1.1 christos saved_i = i;
520 1.1 christos }
521 1.1 christos }
522 1.1 christos
523 1.1 christos return qseq_list[saved_i][idx];
524 1.1 christos }
525 1.1 christos
526 1.1 christos enum operand_qualifier_kind
527 1.1 christos {
528 1.1 christos OQK_NIL,
529 1.1 christos OQK_OPD_VARIANT,
530 1.1 christos OQK_VALUE_IN_RANGE,
531 1.1 christos OQK_MISC,
532 1.1 christos };
533 1.1 christos
534 1.1 christos /* Operand qualifier description. */
535 1.1 christos struct operand_qualifier_data
536 1.1 christos {
537 1.1 christos /* The usage of the three data fields depends on the qualifier kind. */
538 1.1 christos int data0;
539 1.1 christos int data1;
540 1.1 christos int data2;
541 1.1 christos /* Description. */
542 1.1 christos const char *desc;
543 1.1 christos /* Kind. */
544 1.1 christos enum operand_qualifier_kind kind;
545 1.1 christos };
546 1.1 christos
547 1.1 christos /* Indexed by the operand qualifier enumerators. */
548 1.1 christos struct operand_qualifier_data aarch64_opnd_qualifiers[] =
549 1.1 christos {
550 1.1 christos {0, 0, 0, "NIL", OQK_NIL},
551 1.1 christos
552 1.1 christos /* Operand variant qualifiers.
553 1.1 christos First 3 fields:
554 1.1 christos element size, number of elements and common value for encoding. */
555 1.1 christos
556 1.1 christos {4, 1, 0x0, "w", OQK_OPD_VARIANT},
557 1.1 christos {8, 1, 0x1, "x", OQK_OPD_VARIANT},
558 1.1 christos {4, 1, 0x0, "wsp", OQK_OPD_VARIANT},
559 1.1 christos {8, 1, 0x1, "sp", OQK_OPD_VARIANT},
560 1.1 christos
561 1.1 christos {1, 1, 0x0, "b", OQK_OPD_VARIANT},
562 1.1 christos {2, 1, 0x1, "h", OQK_OPD_VARIANT},
563 1.1 christos {4, 1, 0x2, "s", OQK_OPD_VARIANT},
564 1.1 christos {8, 1, 0x3, "d", OQK_OPD_VARIANT},
565 1.1 christos {16, 1, 0x4, "q", OQK_OPD_VARIANT},
566 1.1 christos
567 1.1 christos {1, 8, 0x0, "8b", OQK_OPD_VARIANT},
568 1.1 christos {1, 16, 0x1, "16b", OQK_OPD_VARIANT},
569 1.1 christos {2, 4, 0x2, "4h", OQK_OPD_VARIANT},
570 1.1 christos {2, 8, 0x3, "8h", OQK_OPD_VARIANT},
571 1.1 christos {4, 2, 0x4, "2s", OQK_OPD_VARIANT},
572 1.1 christos {4, 4, 0x5, "4s", OQK_OPD_VARIANT},
573 1.1 christos {8, 1, 0x6, "1d", OQK_OPD_VARIANT},
574 1.1 christos {8, 2, 0x7, "2d", OQK_OPD_VARIANT},
575 1.1 christos {16, 1, 0x8, "1q", OQK_OPD_VARIANT},
576 1.1 christos
577 1.1 christos /* Qualifiers constraining the value range.
578 1.1 christos First 3 fields:
579 1.1 christos Lower bound, higher bound, unused. */
580 1.1 christos
581 1.1 christos {0, 7, 0, "imm_0_7" , OQK_VALUE_IN_RANGE},
582 1.1 christos {0, 15, 0, "imm_0_15", OQK_VALUE_IN_RANGE},
583 1.1 christos {0, 31, 0, "imm_0_31", OQK_VALUE_IN_RANGE},
584 1.1 christos {0, 63, 0, "imm_0_63", OQK_VALUE_IN_RANGE},
585 1.1 christos {1, 32, 0, "imm_1_32", OQK_VALUE_IN_RANGE},
586 1.1 christos {1, 64, 0, "imm_1_64", OQK_VALUE_IN_RANGE},
587 1.1 christos
588 1.1 christos /* Qualifiers for miscellaneous purpose.
589 1.1 christos First 3 fields:
590 1.1 christos unused, unused and unused. */
591 1.1 christos
592 1.1 christos {0, 0, 0, "lsl", 0},
593 1.1 christos {0, 0, 0, "msl", 0},
594 1.1 christos
595 1.1 christos {0, 0, 0, "retrieving", 0},
596 1.1 christos };
597 1.1 christos
598 1.1 christos static inline bfd_boolean
599 1.1 christos operand_variant_qualifier_p (aarch64_opnd_qualifier_t qualifier)
600 1.1 christos {
601 1.1 christos return (aarch64_opnd_qualifiers[qualifier].kind == OQK_OPD_VARIANT)
602 1.1 christos ? TRUE : FALSE;
603 1.1 christos }
604 1.1 christos
605 1.1 christos static inline bfd_boolean
606 1.1 christos qualifier_value_in_range_constraint_p (aarch64_opnd_qualifier_t qualifier)
607 1.1 christos {
608 1.1 christos return (aarch64_opnd_qualifiers[qualifier].kind == OQK_VALUE_IN_RANGE)
609 1.1 christos ? TRUE : FALSE;
610 1.1 christos }
611 1.1 christos
612 1.1 christos const char*
613 1.1 christos aarch64_get_qualifier_name (aarch64_opnd_qualifier_t qualifier)
614 1.1 christos {
615 1.1 christos return aarch64_opnd_qualifiers[qualifier].desc;
616 1.1 christos }
617 1.1 christos
618 1.1 christos /* Given an operand qualifier, return the expected data element size
619 1.1 christos of a qualified operand. */
620 1.1 christos unsigned char
621 1.1 christos aarch64_get_qualifier_esize (aarch64_opnd_qualifier_t qualifier)
622 1.1 christos {
623 1.1 christos assert (operand_variant_qualifier_p (qualifier) == TRUE);
624 1.1 christos return aarch64_opnd_qualifiers[qualifier].data0;
625 1.1 christos }
626 1.1 christos
627 1.1 christos unsigned char
628 1.1 christos aarch64_get_qualifier_nelem (aarch64_opnd_qualifier_t qualifier)
629 1.1 christos {
630 1.1 christos assert (operand_variant_qualifier_p (qualifier) == TRUE);
631 1.1 christos return aarch64_opnd_qualifiers[qualifier].data1;
632 1.1 christos }
633 1.1 christos
634 1.1 christos aarch64_insn
635 1.1 christos aarch64_get_qualifier_standard_value (aarch64_opnd_qualifier_t qualifier)
636 1.1 christos {
637 1.1 christos assert (operand_variant_qualifier_p (qualifier) == TRUE);
638 1.1 christos return aarch64_opnd_qualifiers[qualifier].data2;
639 1.1 christos }
640 1.1 christos
641 1.1 christos static int
642 1.1 christos get_lower_bound (aarch64_opnd_qualifier_t qualifier)
643 1.1 christos {
644 1.1 christos assert (qualifier_value_in_range_constraint_p (qualifier) == TRUE);
645 1.1 christos return aarch64_opnd_qualifiers[qualifier].data0;
646 1.1 christos }
647 1.1 christos
648 1.1 christos static int
649 1.1 christos get_upper_bound (aarch64_opnd_qualifier_t qualifier)
650 1.1 christos {
651 1.1 christos assert (qualifier_value_in_range_constraint_p (qualifier) == TRUE);
652 1.1 christos return aarch64_opnd_qualifiers[qualifier].data1;
653 1.1 christos }
654 1.1 christos
655 1.1 christos #ifdef DEBUG_AARCH64
656 1.1 christos void
657 1.1 christos aarch64_verbose (const char *str, ...)
658 1.1 christos {
659 1.1 christos va_list ap;
660 1.1 christos va_start (ap, str);
661 1.1 christos printf ("#### ");
662 1.1 christos vprintf (str, ap);
663 1.1 christos printf ("\n");
664 1.1 christos va_end (ap);
665 1.1 christos }
666 1.1 christos
667 1.1 christos static inline void
668 1.1 christos dump_qualifier_sequence (const aarch64_opnd_qualifier_t *qualifier)
669 1.1 christos {
670 1.1 christos int i;
671 1.1 christos printf ("#### \t");
672 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i, ++qualifier)
673 1.1 christos printf ("%s,", aarch64_get_qualifier_name (*qualifier));
674 1.1 christos printf ("\n");
675 1.1 christos }
676 1.1 christos
677 1.1 christos static void
678 1.1 christos dump_match_qualifiers (const struct aarch64_opnd_info *opnd,
679 1.1 christos const aarch64_opnd_qualifier_t *qualifier)
680 1.1 christos {
681 1.1 christos int i;
682 1.1 christos aarch64_opnd_qualifier_t curr[AARCH64_MAX_OPND_NUM];
683 1.1 christos
684 1.1 christos aarch64_verbose ("dump_match_qualifiers:");
685 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
686 1.1 christos curr[i] = opnd[i].qualifier;
687 1.1 christos dump_qualifier_sequence (curr);
688 1.1 christos aarch64_verbose ("against");
689 1.1 christos dump_qualifier_sequence (qualifier);
690 1.1 christos }
691 1.1 christos #endif /* DEBUG_AARCH64 */
692 1.1 christos
693 1.1 christos /* TODO improve this, we can have an extra field at the runtime to
694 1.1 christos store the number of operands rather than calculating it every time. */
695 1.1 christos
696 1.1 christos int
697 1.1 christos aarch64_num_of_operands (const aarch64_opcode *opcode)
698 1.1 christos {
699 1.1 christos int i = 0;
700 1.1 christos const enum aarch64_opnd *opnds = opcode->operands;
701 1.1 christos while (opnds[i++] != AARCH64_OPND_NIL)
702 1.1 christos ;
703 1.1 christos --i;
704 1.1 christos assert (i >= 0 && i <= AARCH64_MAX_OPND_NUM);
705 1.1 christos return i;
706 1.1 christos }
707 1.1 christos
708 1.1 christos /* Find the best matched qualifier sequence in *QUALIFIERS_LIST for INST.
709 1.1 christos If succeeds, fill the found sequence in *RET, return 1; otherwise return 0.
710 1.1 christos
711 1.1 christos N.B. on the entry, it is very likely that only some operands in *INST
712 1.1 christos have had their qualifiers been established.
713 1.1 christos
714 1.1 christos If STOP_AT is not -1, the function will only try to match
715 1.1 christos the qualifier sequence for operands before and including the operand
716 1.1 christos of index STOP_AT; and on success *RET will only be filled with the first
717 1.1 christos (STOP_AT+1) qualifiers.
718 1.1 christos
719 1.1 christos A couple examples of the matching algorithm:
720 1.1 christos
721 1.1 christos X,W,NIL should match
722 1.1 christos X,W,NIL
723 1.1 christos
724 1.1 christos NIL,NIL should match
725 1.1 christos X ,NIL
726 1.1 christos
727 1.1 christos Apart from serving the main encoding routine, this can also be called
728 1.1 christos during or after the operand decoding. */
729 1.1 christos
730 1.1 christos int
731 1.1 christos aarch64_find_best_match (const aarch64_inst *inst,
732 1.1 christos const aarch64_opnd_qualifier_seq_t *qualifiers_list,
733 1.1 christos int stop_at, aarch64_opnd_qualifier_t *ret)
734 1.1 christos {
735 1.1 christos int found = 0;
736 1.1 christos int i, num_opnds;
737 1.1 christos const aarch64_opnd_qualifier_t *qualifiers;
738 1.1 christos
739 1.1 christos num_opnds = aarch64_num_of_operands (inst->opcode);
740 1.1 christos if (num_opnds == 0)
741 1.1 christos {
742 1.1 christos DEBUG_TRACE ("SUCCEED: no operand");
743 1.1 christos return 1;
744 1.1 christos }
745 1.1 christos
746 1.1 christos if (stop_at < 0 || stop_at >= num_opnds)
747 1.1 christos stop_at = num_opnds - 1;
748 1.1 christos
749 1.1 christos /* For each pattern. */
750 1.1 christos for (i = 0; i < AARCH64_MAX_QLF_SEQ_NUM; ++i, ++qualifiers_list)
751 1.1 christos {
752 1.1 christos int j;
753 1.1 christos qualifiers = *qualifiers_list;
754 1.1 christos
755 1.1 christos /* Start as positive. */
756 1.1 christos found = 1;
757 1.1 christos
758 1.1 christos DEBUG_TRACE ("%d", i);
759 1.1 christos #ifdef DEBUG_AARCH64
760 1.1 christos if (debug_dump)
761 1.1 christos dump_match_qualifiers (inst->operands, qualifiers);
762 1.1 christos #endif
763 1.1 christos
764 1.1 christos /* Most opcodes has much fewer patterns in the list.
765 1.1 christos First NIL qualifier indicates the end in the list. */
766 1.1 christos if (empty_qualifier_sequence_p (qualifiers) == TRUE)
767 1.1 christos {
768 1.1 christos DEBUG_TRACE_IF (i == 0, "SUCCEED: empty qualifier list");
769 1.1 christos if (i)
770 1.1 christos found = 0;
771 1.1 christos break;
772 1.1 christos }
773 1.1 christos
774 1.1 christos for (j = 0; j < num_opnds && j <= stop_at; ++j, ++qualifiers)
775 1.1 christos {
776 1.1 christos if (inst->operands[j].qualifier == AARCH64_OPND_QLF_NIL)
777 1.1 christos {
778 1.1 christos /* Either the operand does not have qualifier, or the qualifier
779 1.1 christos for the operand needs to be deduced from the qualifier
780 1.1 christos sequence.
781 1.1 christos In the latter case, any constraint checking related with
782 1.1 christos the obtained qualifier should be done later in
783 1.1 christos operand_general_constraint_met_p. */
784 1.1 christos continue;
785 1.1 christos }
786 1.1 christos else if (*qualifiers != inst->operands[j].qualifier)
787 1.1 christos {
788 1.1 christos /* Unless the target qualifier can also qualify the operand
789 1.1 christos (which has already had a non-nil qualifier), non-equal
790 1.1 christos qualifiers are generally un-matched. */
791 1.1 christos if (operand_also_qualified_p (inst->operands + j, *qualifiers))
792 1.1 christos continue;
793 1.1 christos else
794 1.1 christos {
795 1.1 christos found = 0;
796 1.1 christos break;
797 1.1 christos }
798 1.1 christos }
799 1.1 christos else
800 1.1 christos continue; /* Equal qualifiers are certainly matched. */
801 1.1 christos }
802 1.1 christos
803 1.1 christos /* Qualifiers established. */
804 1.1 christos if (found == 1)
805 1.1 christos break;
806 1.1 christos }
807 1.1 christos
808 1.1 christos if (found == 1)
809 1.1 christos {
810 1.1 christos /* Fill the result in *RET. */
811 1.1 christos int j;
812 1.1 christos qualifiers = *qualifiers_list;
813 1.1 christos
814 1.1 christos DEBUG_TRACE ("complete qualifiers using list %d", i);
815 1.1 christos #ifdef DEBUG_AARCH64
816 1.1 christos if (debug_dump)
817 1.1 christos dump_qualifier_sequence (qualifiers);
818 1.1 christos #endif
819 1.1 christos
820 1.1 christos for (j = 0; j <= stop_at; ++j, ++qualifiers)
821 1.1 christos ret[j] = *qualifiers;
822 1.1 christos for (; j < AARCH64_MAX_OPND_NUM; ++j)
823 1.1 christos ret[j] = AARCH64_OPND_QLF_NIL;
824 1.1 christos
825 1.1 christos DEBUG_TRACE ("SUCCESS");
826 1.1 christos return 1;
827 1.1 christos }
828 1.1 christos
829 1.1 christos DEBUG_TRACE ("FAIL");
830 1.1 christos return 0;
831 1.1 christos }
832 1.1 christos
833 1.1 christos /* Operand qualifier matching and resolving.
834 1.1 christos
835 1.1 christos Return 1 if the operand qualifier(s) in *INST match one of the qualifier
836 1.1 christos sequences in INST->OPCODE->qualifiers_list; otherwise return 0.
837 1.1 christos
838 1.1 christos if UPDATE_P == TRUE, update the qualifier(s) in *INST after the matching
839 1.1 christos succeeds. */
840 1.1 christos
841 1.1 christos static int
842 1.1 christos match_operands_qualifier (aarch64_inst *inst, bfd_boolean update_p)
843 1.1 christos {
844 1.1 christos int i;
845 1.1 christos aarch64_opnd_qualifier_seq_t qualifiers;
846 1.1 christos
847 1.1 christos if (!aarch64_find_best_match (inst, inst->opcode->qualifiers_list, -1,
848 1.1 christos qualifiers))
849 1.1 christos {
850 1.1 christos DEBUG_TRACE ("matching FAIL");
851 1.1 christos return 0;
852 1.1 christos }
853 1.1 christos
854 1.1 christos /* Update the qualifiers. */
855 1.1 christos if (update_p == TRUE)
856 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
857 1.1 christos {
858 1.1 christos if (inst->opcode->operands[i] == AARCH64_OPND_NIL)
859 1.1 christos break;
860 1.1 christos DEBUG_TRACE_IF (inst->operands[i].qualifier != qualifiers[i],
861 1.1 christos "update %s with %s for operand %d",
862 1.1 christos aarch64_get_qualifier_name (inst->operands[i].qualifier),
863 1.1 christos aarch64_get_qualifier_name (qualifiers[i]), i);
864 1.1 christos inst->operands[i].qualifier = qualifiers[i];
865 1.1 christos }
866 1.1 christos
867 1.1 christos DEBUG_TRACE ("matching SUCCESS");
868 1.1 christos return 1;
869 1.1 christos }
870 1.1 christos
871 1.1 christos /* Return TRUE if VALUE is a wide constant that can be moved into a general
872 1.1 christos register by MOVZ.
873 1.1 christos
874 1.1 christos IS32 indicates whether value is a 32-bit immediate or not.
875 1.1 christos If SHIFT_AMOUNT is not NULL, on the return of TRUE, the logical left shift
876 1.1 christos amount will be returned in *SHIFT_AMOUNT. */
877 1.1 christos
878 1.1 christos bfd_boolean
879 1.1 christos aarch64_wide_constant_p (int64_t value, int is32, unsigned int *shift_amount)
880 1.1 christos {
881 1.1 christos int amount;
882 1.1 christos
883 1.1 christos DEBUG_TRACE ("enter with 0x%" PRIx64 "(%" PRIi64 ")", value, value);
884 1.1 christos
885 1.1 christos if (is32)
886 1.1 christos {
887 1.1 christos /* Allow all zeros or all ones in top 32-bits, so that
888 1.1 christos 32-bit constant expressions like ~0x80000000 are
889 1.1 christos permitted. */
890 1.1 christos uint64_t ext = value;
891 1.1 christos if (ext >> 32 != 0 && ext >> 32 != (uint64_t) 0xffffffff)
892 1.1 christos /* Immediate out of range. */
893 1.1 christos return FALSE;
894 1.1 christos value &= (int64_t) 0xffffffff;
895 1.1 christos }
896 1.1 christos
897 1.1 christos /* first, try movz then movn */
898 1.1 christos amount = -1;
899 1.1 christos if ((value & ((int64_t) 0xffff << 0)) == value)
900 1.1 christos amount = 0;
901 1.1 christos else if ((value & ((int64_t) 0xffff << 16)) == value)
902 1.1 christos amount = 16;
903 1.1 christos else if (!is32 && (value & ((int64_t) 0xffff << 32)) == value)
904 1.1 christos amount = 32;
905 1.1 christos else if (!is32 && (value & ((int64_t) 0xffff << 48)) == value)
906 1.1 christos amount = 48;
907 1.1 christos
908 1.1 christos if (amount == -1)
909 1.1 christos {
910 1.1 christos DEBUG_TRACE ("exit FALSE with 0x%" PRIx64 "(%" PRIi64 ")", value, value);
911 1.1 christos return FALSE;
912 1.1 christos }
913 1.1 christos
914 1.1 christos if (shift_amount != NULL)
915 1.1 christos *shift_amount = amount;
916 1.1 christos
917 1.1 christos DEBUG_TRACE ("exit TRUE with amount %d", amount);
918 1.1 christos
919 1.1 christos return TRUE;
920 1.1 christos }
921 1.1 christos
922 1.1 christos /* Build the accepted values for immediate logical SIMD instructions.
923 1.1 christos
924 1.1 christos The standard encodings of the immediate value are:
925 1.1 christos N imms immr SIMD size R S
926 1.1 christos 1 ssssss rrrrrr 64 UInt(rrrrrr) UInt(ssssss)
927 1.1 christos 0 0sssss 0rrrrr 32 UInt(rrrrr) UInt(sssss)
928 1.1 christos 0 10ssss 00rrrr 16 UInt(rrrr) UInt(ssss)
929 1.1 christos 0 110sss 000rrr 8 UInt(rrr) UInt(sss)
930 1.1 christos 0 1110ss 0000rr 4 UInt(rr) UInt(ss)
931 1.1 christos 0 11110s 00000r 2 UInt(r) UInt(s)
932 1.1 christos where all-ones value of S is reserved.
933 1.1 christos
934 1.1 christos Let's call E the SIMD size.
935 1.1 christos
936 1.1 christos The immediate value is: S+1 bits '1' rotated to the right by R.
937 1.1 christos
938 1.1 christos The total of valid encodings is 64*63 + 32*31 + ... + 2*1 = 5334
939 1.1 christos (remember S != E - 1). */
940 1.1 christos
941 1.1 christos #define TOTAL_IMM_NB 5334
942 1.1 christos
943 1.1 christos typedef struct
944 1.1 christos {
945 1.1 christos uint64_t imm;
946 1.1 christos aarch64_insn encoding;
947 1.1 christos } simd_imm_encoding;
948 1.1 christos
949 1.1 christos static simd_imm_encoding simd_immediates[TOTAL_IMM_NB];
950 1.1 christos
951 1.1 christos static int
952 1.1 christos simd_imm_encoding_cmp(const void *i1, const void *i2)
953 1.1 christos {
954 1.1 christos const simd_imm_encoding *imm1 = (const simd_imm_encoding *)i1;
955 1.1 christos const simd_imm_encoding *imm2 = (const simd_imm_encoding *)i2;
956 1.1 christos
957 1.1 christos if (imm1->imm < imm2->imm)
958 1.1 christos return -1;
959 1.1 christos if (imm1->imm > imm2->imm)
960 1.1 christos return +1;
961 1.1 christos return 0;
962 1.1 christos }
963 1.1 christos
964 1.1 christos /* immediate bitfield standard encoding
965 1.1 christos imm13<12> imm13<5:0> imm13<11:6> SIMD size R S
966 1.1 christos 1 ssssss rrrrrr 64 rrrrrr ssssss
967 1.1 christos 0 0sssss 0rrrrr 32 rrrrr sssss
968 1.1 christos 0 10ssss 00rrrr 16 rrrr ssss
969 1.1 christos 0 110sss 000rrr 8 rrr sss
970 1.1 christos 0 1110ss 0000rr 4 rr ss
971 1.1 christos 0 11110s 00000r 2 r s */
972 1.1 christos static inline int
973 1.1 christos encode_immediate_bitfield (int is64, uint32_t s, uint32_t r)
974 1.1 christos {
975 1.1 christos return (is64 << 12) | (r << 6) | s;
976 1.1 christos }
977 1.1 christos
978 1.1 christos static void
979 1.1 christos build_immediate_table (void)
980 1.1 christos {
981 1.1 christos uint32_t log_e, e, s, r, s_mask;
982 1.1 christos uint64_t mask, imm;
983 1.1 christos int nb_imms;
984 1.1 christos int is64;
985 1.1 christos
986 1.1 christos nb_imms = 0;
987 1.1 christos for (log_e = 1; log_e <= 6; log_e++)
988 1.1 christos {
989 1.1 christos /* Get element size. */
990 1.1 christos e = 1u << log_e;
991 1.1 christos if (log_e == 6)
992 1.1 christos {
993 1.1 christos is64 = 1;
994 1.1 christos mask = 0xffffffffffffffffull;
995 1.1 christos s_mask = 0;
996 1.1 christos }
997 1.1 christos else
998 1.1 christos {
999 1.1 christos is64 = 0;
1000 1.1 christos mask = (1ull << e) - 1;
1001 1.1 christos /* log_e s_mask
1002 1.1 christos 1 ((1 << 4) - 1) << 2 = 111100
1003 1.1 christos 2 ((1 << 3) - 1) << 3 = 111000
1004 1.1 christos 3 ((1 << 2) - 1) << 4 = 110000
1005 1.1 christos 4 ((1 << 1) - 1) << 5 = 100000
1006 1.1 christos 5 ((1 << 0) - 1) << 6 = 000000 */
1007 1.1 christos s_mask = ((1u << (5 - log_e)) - 1) << (log_e + 1);
1008 1.1 christos }
1009 1.1 christos for (s = 0; s < e - 1; s++)
1010 1.1 christos for (r = 0; r < e; r++)
1011 1.1 christos {
1012 1.1 christos /* s+1 consecutive bits to 1 (s < 63) */
1013 1.1 christos imm = (1ull << (s + 1)) - 1;
1014 1.1 christos /* rotate right by r */
1015 1.1 christos if (r != 0)
1016 1.1 christos imm = (imm >> r) | ((imm << (e - r)) & mask);
1017 1.1 christos /* replicate the constant depending on SIMD size */
1018 1.1 christos switch (log_e)
1019 1.1 christos {
1020 1.1 christos case 1: imm = (imm << 2) | imm;
1021 1.1 christos case 2: imm = (imm << 4) | imm;
1022 1.1 christos case 3: imm = (imm << 8) | imm;
1023 1.1 christos case 4: imm = (imm << 16) | imm;
1024 1.1 christos case 5: imm = (imm << 32) | imm;
1025 1.1 christos case 6: break;
1026 1.1 christos default: abort ();
1027 1.1 christos }
1028 1.1 christos simd_immediates[nb_imms].imm = imm;
1029 1.1 christos simd_immediates[nb_imms].encoding =
1030 1.1 christos encode_immediate_bitfield(is64, s | s_mask, r);
1031 1.1 christos nb_imms++;
1032 1.1 christos }
1033 1.1 christos }
1034 1.1 christos assert (nb_imms == TOTAL_IMM_NB);
1035 1.1 christos qsort(simd_immediates, nb_imms,
1036 1.1 christos sizeof(simd_immediates[0]), simd_imm_encoding_cmp);
1037 1.1 christos }
1038 1.1 christos
1039 1.1 christos /* Return TRUE if VALUE is a valid logical immediate, i.e. bitmask, that can
1040 1.1 christos be accepted by logical (immediate) instructions
1041 1.1 christos e.g. ORR <Xd|SP>, <Xn>, #<imm>.
1042 1.1 christos
1043 1.1 christos IS32 indicates whether or not VALUE is a 32-bit immediate.
1044 1.1 christos If ENCODING is not NULL, on the return of TRUE, the standard encoding for
1045 1.1 christos VALUE will be returned in *ENCODING. */
1046 1.1 christos
1047 1.1 christos bfd_boolean
1048 1.1 christos aarch64_logical_immediate_p (uint64_t value, int is32, aarch64_insn *encoding)
1049 1.1 christos {
1050 1.1 christos simd_imm_encoding imm_enc;
1051 1.1 christos const simd_imm_encoding *imm_encoding;
1052 1.1 christos static bfd_boolean initialized = FALSE;
1053 1.1 christos
1054 1.1 christos DEBUG_TRACE ("enter with 0x%" PRIx64 "(%" PRIi64 "), is32: %d", value,
1055 1.1 christos value, is32);
1056 1.1 christos
1057 1.1 christos if (initialized == FALSE)
1058 1.1 christos {
1059 1.1 christos build_immediate_table ();
1060 1.1 christos initialized = TRUE;
1061 1.1 christos }
1062 1.1 christos
1063 1.1 christos if (is32)
1064 1.1 christos {
1065 1.1 christos /* Allow all zeros or all ones in top 32-bits, so that
1066 1.1 christos constant expressions like ~1 are permitted. */
1067 1.1 christos if (value >> 32 != 0 && value >> 32 != 0xffffffff)
1068 1.1 christos return FALSE;
1069 1.1 christos
1070 1.1 christos /* Replicate the 32 lower bits to the 32 upper bits. */
1071 1.1 christos value &= 0xffffffff;
1072 1.1 christos value |= value << 32;
1073 1.1 christos }
1074 1.1 christos
1075 1.1 christos imm_enc.imm = value;
1076 1.1 christos imm_encoding = (const simd_imm_encoding *)
1077 1.1 christos bsearch(&imm_enc, simd_immediates, TOTAL_IMM_NB,
1078 1.1 christos sizeof(simd_immediates[0]), simd_imm_encoding_cmp);
1079 1.1 christos if (imm_encoding == NULL)
1080 1.1 christos {
1081 1.1 christos DEBUG_TRACE ("exit with FALSE");
1082 1.1 christos return FALSE;
1083 1.1 christos }
1084 1.1 christos if (encoding != NULL)
1085 1.1 christos *encoding = imm_encoding->encoding;
1086 1.1 christos DEBUG_TRACE ("exit with TRUE");
1087 1.1 christos return TRUE;
1088 1.1 christos }
1089 1.1 christos
1090 1.1 christos /* If 64-bit immediate IMM is in the format of
1091 1.1 christos "aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh",
1092 1.1 christos where a, b, c, d, e, f, g and h are independently 0 or 1, return an integer
1093 1.1 christos of value "abcdefgh". Otherwise return -1. */
1094 1.1 christos int
1095 1.1 christos aarch64_shrink_expanded_imm8 (uint64_t imm)
1096 1.1 christos {
1097 1.1 christos int i, ret;
1098 1.1 christos uint32_t byte;
1099 1.1 christos
1100 1.1 christos ret = 0;
1101 1.1 christos for (i = 0; i < 8; i++)
1102 1.1 christos {
1103 1.1 christos byte = (imm >> (8 * i)) & 0xff;
1104 1.1 christos if (byte == 0xff)
1105 1.1 christos ret |= 1 << i;
1106 1.1 christos else if (byte != 0x00)
1107 1.1 christos return -1;
1108 1.1 christos }
1109 1.1 christos return ret;
1110 1.1 christos }
1111 1.1 christos
1112 1.1 christos /* Utility inline functions for operand_general_constraint_met_p. */
1113 1.1 christos
1114 1.1 christos static inline void
1115 1.1 christos set_error (aarch64_operand_error *mismatch_detail,
1116 1.1 christos enum aarch64_operand_error_kind kind, int idx,
1117 1.1 christos const char* error)
1118 1.1 christos {
1119 1.1 christos if (mismatch_detail == NULL)
1120 1.1 christos return;
1121 1.1 christos mismatch_detail->kind = kind;
1122 1.1 christos mismatch_detail->index = idx;
1123 1.1 christos mismatch_detail->error = error;
1124 1.1 christos }
1125 1.1 christos
1126 1.1 christos static inline void
1127 1.1 christos set_syntax_error (aarch64_operand_error *mismatch_detail, int idx,
1128 1.1 christos const char* error)
1129 1.1 christos {
1130 1.1 christos if (mismatch_detail == NULL)
1131 1.1 christos return;
1132 1.1 christos set_error (mismatch_detail, AARCH64_OPDE_SYNTAX_ERROR, idx, error);
1133 1.1 christos }
1134 1.1 christos
1135 1.1 christos static inline void
1136 1.1 christos set_out_of_range_error (aarch64_operand_error *mismatch_detail,
1137 1.1 christos int idx, int lower_bound, int upper_bound,
1138 1.1 christos const char* error)
1139 1.1 christos {
1140 1.1 christos if (mismatch_detail == NULL)
1141 1.1 christos return;
1142 1.1 christos set_error (mismatch_detail, AARCH64_OPDE_OUT_OF_RANGE, idx, error);
1143 1.1 christos mismatch_detail->data[0] = lower_bound;
1144 1.1 christos mismatch_detail->data[1] = upper_bound;
1145 1.1 christos }
1146 1.1 christos
1147 1.1 christos static inline void
1148 1.1 christos set_imm_out_of_range_error (aarch64_operand_error *mismatch_detail,
1149 1.1 christos int idx, int lower_bound, int upper_bound)
1150 1.1 christos {
1151 1.1 christos if (mismatch_detail == NULL)
1152 1.1 christos return;
1153 1.1 christos set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
1154 1.1 christos _("immediate value"));
1155 1.1 christos }
1156 1.1 christos
1157 1.1 christos static inline void
1158 1.1 christos set_offset_out_of_range_error (aarch64_operand_error *mismatch_detail,
1159 1.1 christos int idx, int lower_bound, int upper_bound)
1160 1.1 christos {
1161 1.1 christos if (mismatch_detail == NULL)
1162 1.1 christos return;
1163 1.1 christos set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
1164 1.1 christos _("immediate offset"));
1165 1.1 christos }
1166 1.1 christos
1167 1.1 christos static inline void
1168 1.1 christos set_regno_out_of_range_error (aarch64_operand_error *mismatch_detail,
1169 1.1 christos int idx, int lower_bound, int upper_bound)
1170 1.1 christos {
1171 1.1 christos if (mismatch_detail == NULL)
1172 1.1 christos return;
1173 1.1 christos set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
1174 1.1 christos _("register number"));
1175 1.1 christos }
1176 1.1 christos
1177 1.1 christos static inline void
1178 1.1 christos set_elem_idx_out_of_range_error (aarch64_operand_error *mismatch_detail,
1179 1.1 christos int idx, int lower_bound, int upper_bound)
1180 1.1 christos {
1181 1.1 christos if (mismatch_detail == NULL)
1182 1.1 christos return;
1183 1.1 christos set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
1184 1.1 christos _("register element index"));
1185 1.1 christos }
1186 1.1 christos
1187 1.1 christos static inline void
1188 1.1 christos set_sft_amount_out_of_range_error (aarch64_operand_error *mismatch_detail,
1189 1.1 christos int idx, int lower_bound, int upper_bound)
1190 1.1 christos {
1191 1.1 christos if (mismatch_detail == NULL)
1192 1.1 christos return;
1193 1.1 christos set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
1194 1.1 christos _("shift amount"));
1195 1.1 christos }
1196 1.1 christos
1197 1.1 christos static inline void
1198 1.1 christos set_unaligned_error (aarch64_operand_error *mismatch_detail, int idx,
1199 1.1 christos int alignment)
1200 1.1 christos {
1201 1.1 christos if (mismatch_detail == NULL)
1202 1.1 christos return;
1203 1.1 christos set_error (mismatch_detail, AARCH64_OPDE_UNALIGNED, idx, NULL);
1204 1.1 christos mismatch_detail->data[0] = alignment;
1205 1.1 christos }
1206 1.1 christos
1207 1.1 christos static inline void
1208 1.1 christos set_reg_list_error (aarch64_operand_error *mismatch_detail, int idx,
1209 1.1 christos int expected_num)
1210 1.1 christos {
1211 1.1 christos if (mismatch_detail == NULL)
1212 1.1 christos return;
1213 1.1 christos set_error (mismatch_detail, AARCH64_OPDE_REG_LIST, idx, NULL);
1214 1.1 christos mismatch_detail->data[0] = expected_num;
1215 1.1 christos }
1216 1.1 christos
1217 1.1 christos static inline void
1218 1.1 christos set_other_error (aarch64_operand_error *mismatch_detail, int idx,
1219 1.1 christos const char* error)
1220 1.1 christos {
1221 1.1 christos if (mismatch_detail == NULL)
1222 1.1 christos return;
1223 1.1 christos set_error (mismatch_detail, AARCH64_OPDE_OTHER_ERROR, idx, error);
1224 1.1 christos }
1225 1.1 christos
1226 1.1 christos /* General constraint checking based on operand code.
1227 1.1 christos
1228 1.1 christos Return 1 if OPNDS[IDX] meets the general constraint of operand code TYPE
1229 1.1 christos as the IDXth operand of opcode OPCODE. Otherwise return 0.
1230 1.1 christos
1231 1.1 christos This function has to be called after the qualifiers for all operands
1232 1.1 christos have been resolved.
1233 1.1 christos
1234 1.1 christos Mismatching error message is returned in *MISMATCH_DETAIL upon request,
1235 1.1 christos i.e. when MISMATCH_DETAIL is non-NULL. This avoids the generation
1236 1.1 christos of error message during the disassembling where error message is not
1237 1.1 christos wanted. We avoid the dynamic construction of strings of error messages
1238 1.1 christos here (i.e. in libopcodes), as it is costly and complicated; instead, we
1239 1.1 christos use a combination of error code, static string and some integer data to
1240 1.1 christos represent an error. */
1241 1.1 christos
1242 1.1 christos static int
1243 1.1 christos operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
1244 1.1 christos enum aarch64_opnd type,
1245 1.1 christos const aarch64_opcode *opcode,
1246 1.1 christos aarch64_operand_error *mismatch_detail)
1247 1.1 christos {
1248 1.1 christos unsigned num;
1249 1.1 christos unsigned char size;
1250 1.1 christos int64_t imm;
1251 1.1 christos const aarch64_opnd_info *opnd = opnds + idx;
1252 1.1 christos aarch64_opnd_qualifier_t qualifier = opnd->qualifier;
1253 1.1 christos
1254 1.1 christos assert (opcode->operands[idx] == opnd->type && opnd->type == type);
1255 1.1 christos
1256 1.1 christos switch (aarch64_operands[type].op_class)
1257 1.1 christos {
1258 1.1 christos case AARCH64_OPND_CLASS_INT_REG:
1259 1.1 christos /* <Xt> may be optional in some IC and TLBI instructions. */
1260 1.1 christos if (type == AARCH64_OPND_Rt_SYS)
1261 1.1 christos {
1262 1.1 christos assert (idx == 1 && (aarch64_get_operand_class (opnds[0].type)
1263 1.1 christos == AARCH64_OPND_CLASS_SYSTEM));
1264 1.1 christos if (opnds[1].present && !opnds[0].sysins_op->has_xt)
1265 1.1 christos {
1266 1.1 christos set_other_error (mismatch_detail, idx, _("extraneous register"));
1267 1.1 christos return 0;
1268 1.1 christos }
1269 1.1 christos if (!opnds[1].present && opnds[0].sysins_op->has_xt)
1270 1.1 christos {
1271 1.1 christos set_other_error (mismatch_detail, idx, _("missing register"));
1272 1.1 christos return 0;
1273 1.1 christos }
1274 1.1 christos }
1275 1.1 christos switch (qualifier)
1276 1.1 christos {
1277 1.1 christos case AARCH64_OPND_QLF_WSP:
1278 1.1 christos case AARCH64_OPND_QLF_SP:
1279 1.1 christos if (!aarch64_stack_pointer_p (opnd))
1280 1.1 christos {
1281 1.1 christos set_other_error (mismatch_detail, idx,
1282 1.1 christos _("stack pointer register expected"));
1283 1.1 christos return 0;
1284 1.1 christos }
1285 1.1 christos break;
1286 1.1 christos default:
1287 1.1 christos break;
1288 1.1 christos }
1289 1.1 christos break;
1290 1.1 christos
1291 1.1 christos case AARCH64_OPND_CLASS_COND:
1292 1.1 christos if (type == AARCH64_OPND_COND1
1293 1.1 christos && (opnds[idx].cond->value & 0xe) == 0xe)
1294 1.1 christos {
1295 1.1 christos /* Not allow AL or NV. */
1296 1.1 christos set_syntax_error (mismatch_detail, idx, NULL);
1297 1.1 christos }
1298 1.1 christos break;
1299 1.1 christos
1300 1.1 christos case AARCH64_OPND_CLASS_ADDRESS:
1301 1.1 christos /* Check writeback. */
1302 1.1 christos switch (opcode->iclass)
1303 1.1 christos {
1304 1.1 christos case ldst_pos:
1305 1.1 christos case ldst_unscaled:
1306 1.1 christos case ldstnapair_offs:
1307 1.1 christos case ldstpair_off:
1308 1.1 christos case ldst_unpriv:
1309 1.1 christos if (opnd->addr.writeback == 1)
1310 1.1 christos {
1311 1.1 christos set_syntax_error (mismatch_detail, idx,
1312 1.1 christos _("unexpected address writeback"));
1313 1.1 christos return 0;
1314 1.1 christos }
1315 1.1 christos break;
1316 1.1 christos case ldst_imm9:
1317 1.1 christos case ldstpair_indexed:
1318 1.1 christos case asisdlsep:
1319 1.1 christos case asisdlsop:
1320 1.1 christos if (opnd->addr.writeback == 0)
1321 1.1 christos {
1322 1.1 christos set_syntax_error (mismatch_detail, idx,
1323 1.1 christos _("address writeback expected"));
1324 1.1 christos return 0;
1325 1.1 christos }
1326 1.1 christos break;
1327 1.1 christos default:
1328 1.1 christos assert (opnd->addr.writeback == 0);
1329 1.1 christos break;
1330 1.1 christos }
1331 1.1 christos switch (type)
1332 1.1 christos {
1333 1.1 christos case AARCH64_OPND_ADDR_SIMM7:
1334 1.1 christos /* Scaled signed 7 bits immediate offset. */
1335 1.1 christos /* Get the size of the data element that is accessed, which may be
1336 1.1 christos different from that of the source register size,
1337 1.1 christos e.g. in strb/ldrb. */
1338 1.1 christos size = aarch64_get_qualifier_esize (opnd->qualifier);
1339 1.1 christos if (!value_in_range_p (opnd->addr.offset.imm, -64 * size, 63 * size))
1340 1.1 christos {
1341 1.1 christos set_offset_out_of_range_error (mismatch_detail, idx,
1342 1.1 christos -64 * size, 63 * size);
1343 1.1 christos return 0;
1344 1.1 christos }
1345 1.1 christos if (!value_aligned_p (opnd->addr.offset.imm, size))
1346 1.1 christos {
1347 1.1 christos set_unaligned_error (mismatch_detail, idx, size);
1348 1.1 christos return 0;
1349 1.1 christos }
1350 1.1 christos break;
1351 1.1 christos case AARCH64_OPND_ADDR_SIMM9:
1352 1.1 christos /* Unscaled signed 9 bits immediate offset. */
1353 1.1 christos if (!value_in_range_p (opnd->addr.offset.imm, -256, 255))
1354 1.1 christos {
1355 1.1 christos set_offset_out_of_range_error (mismatch_detail, idx, -256, 255);
1356 1.1 christos return 0;
1357 1.1 christos }
1358 1.1 christos break;
1359 1.1 christos
1360 1.1 christos case AARCH64_OPND_ADDR_SIMM9_2:
1361 1.1 christos /* Unscaled signed 9 bits immediate offset, which has to be negative
1362 1.1 christos or unaligned. */
1363 1.1 christos size = aarch64_get_qualifier_esize (qualifier);
1364 1.1 christos if ((value_in_range_p (opnd->addr.offset.imm, 0, 255)
1365 1.1 christos && !value_aligned_p (opnd->addr.offset.imm, size))
1366 1.1 christos || value_in_range_p (opnd->addr.offset.imm, -256, -1))
1367 1.1 christos return 1;
1368 1.1 christos set_other_error (mismatch_detail, idx,
1369 1.1 christos _("negative or unaligned offset expected"));
1370 1.1 christos return 0;
1371 1.1 christos
1372 1.1 christos case AARCH64_OPND_SIMD_ADDR_POST:
1373 1.1 christos /* AdvSIMD load/store multiple structures, post-index. */
1374 1.1 christos assert (idx == 1);
1375 1.1 christos if (opnd->addr.offset.is_reg)
1376 1.1 christos {
1377 1.1 christos if (value_in_range_p (opnd->addr.offset.regno, 0, 30))
1378 1.1 christos return 1;
1379 1.1 christos else
1380 1.1 christos {
1381 1.1 christos set_other_error (mismatch_detail, idx,
1382 1.1 christos _("invalid register offset"));
1383 1.1 christos return 0;
1384 1.1 christos }
1385 1.1 christos }
1386 1.1 christos else
1387 1.1 christos {
1388 1.1 christos const aarch64_opnd_info *prev = &opnds[idx-1];
1389 1.1 christos unsigned num_bytes; /* total number of bytes transferred. */
1390 1.1 christos /* The opcode dependent area stores the number of elements in
1391 1.1 christos each structure to be loaded/stored. */
1392 1.1 christos int is_ld1r = get_opcode_dependent_value (opcode) == 1;
1393 1.1 christos if (opcode->operands[0] == AARCH64_OPND_LVt_AL)
1394 1.1 christos /* Special handling of loading single structure to all lane. */
1395 1.1 christos num_bytes = (is_ld1r ? 1 : prev->reglist.num_regs)
1396 1.1 christos * aarch64_get_qualifier_esize (prev->qualifier);
1397 1.1 christos else
1398 1.1 christos num_bytes = prev->reglist.num_regs
1399 1.1 christos * aarch64_get_qualifier_esize (prev->qualifier)
1400 1.1 christos * aarch64_get_qualifier_nelem (prev->qualifier);
1401 1.1 christos if ((int) num_bytes != opnd->addr.offset.imm)
1402 1.1 christos {
1403 1.1 christos set_other_error (mismatch_detail, idx,
1404 1.1 christos _("invalid post-increment amount"));
1405 1.1 christos return 0;
1406 1.1 christos }
1407 1.1 christos }
1408 1.1 christos break;
1409 1.1 christos
1410 1.1 christos case AARCH64_OPND_ADDR_REGOFF:
1411 1.1 christos /* Get the size of the data element that is accessed, which may be
1412 1.1 christos different from that of the source register size,
1413 1.1 christos e.g. in strb/ldrb. */
1414 1.1 christos size = aarch64_get_qualifier_esize (opnd->qualifier);
1415 1.1 christos /* It is either no shift or shift by the binary logarithm of SIZE. */
1416 1.1 christos if (opnd->shifter.amount != 0
1417 1.1 christos && opnd->shifter.amount != (int)get_logsz (size))
1418 1.1 christos {
1419 1.1 christos set_other_error (mismatch_detail, idx,
1420 1.1 christos _("invalid shift amount"));
1421 1.1 christos return 0;
1422 1.1 christos }
1423 1.1 christos /* Only UXTW, LSL, SXTW and SXTX are the accepted extending
1424 1.1 christos operators. */
1425 1.1 christos switch (opnd->shifter.kind)
1426 1.1 christos {
1427 1.1 christos case AARCH64_MOD_UXTW:
1428 1.1 christos case AARCH64_MOD_LSL:
1429 1.1 christos case AARCH64_MOD_SXTW:
1430 1.1 christos case AARCH64_MOD_SXTX: break;
1431 1.1 christos default:
1432 1.1 christos set_other_error (mismatch_detail, idx,
1433 1.1 christos _("invalid extend/shift operator"));
1434 1.1 christos return 0;
1435 1.1 christos }
1436 1.1 christos break;
1437 1.1 christos
1438 1.1 christos case AARCH64_OPND_ADDR_UIMM12:
1439 1.1 christos imm = opnd->addr.offset.imm;
1440 1.1 christos /* Get the size of the data element that is accessed, which may be
1441 1.1 christos different from that of the source register size,
1442 1.1 christos e.g. in strb/ldrb. */
1443 1.1 christos size = aarch64_get_qualifier_esize (qualifier);
1444 1.1 christos if (!value_in_range_p (opnd->addr.offset.imm, 0, 4095 * size))
1445 1.1 christos {
1446 1.1 christos set_offset_out_of_range_error (mismatch_detail, idx,
1447 1.1 christos 0, 4095 * size);
1448 1.1 christos return 0;
1449 1.1 christos }
1450 1.1 christos if (!value_aligned_p (opnd->addr.offset.imm, size))
1451 1.1 christos {
1452 1.1 christos set_unaligned_error (mismatch_detail, idx, size);
1453 1.1 christos return 0;
1454 1.1 christos }
1455 1.1 christos break;
1456 1.1 christos
1457 1.1 christos case AARCH64_OPND_ADDR_PCREL14:
1458 1.1 christos case AARCH64_OPND_ADDR_PCREL19:
1459 1.1 christos case AARCH64_OPND_ADDR_PCREL21:
1460 1.1 christos case AARCH64_OPND_ADDR_PCREL26:
1461 1.1 christos imm = opnd->imm.value;
1462 1.1 christos if (operand_need_shift_by_two (get_operand_from_code (type)))
1463 1.1 christos {
1464 1.1 christos /* The offset value in a PC-relative branch instruction is alway
1465 1.1 christos 4-byte aligned and is encoded without the lowest 2 bits. */
1466 1.1 christos if (!value_aligned_p (imm, 4))
1467 1.1 christos {
1468 1.1 christos set_unaligned_error (mismatch_detail, idx, 4);
1469 1.1 christos return 0;
1470 1.1 christos }
1471 1.1 christos /* Right shift by 2 so that we can carry out the following check
1472 1.1 christos canonically. */
1473 1.1 christos imm >>= 2;
1474 1.1 christos }
1475 1.1 christos size = get_operand_fields_width (get_operand_from_code (type));
1476 1.1 christos if (!value_fit_signed_field_p (imm, size))
1477 1.1 christos {
1478 1.1 christos set_other_error (mismatch_detail, idx,
1479 1.1 christos _("immediate out of range"));
1480 1.1 christos return 0;
1481 1.1 christos }
1482 1.1 christos break;
1483 1.1 christos
1484 1.1 christos default:
1485 1.1 christos break;
1486 1.1 christos }
1487 1.1 christos break;
1488 1.1 christos
1489 1.1 christos case AARCH64_OPND_CLASS_SIMD_REGLIST:
1490 1.1 christos /* The opcode dependent area stores the number of elements in
1491 1.1 christos each structure to be loaded/stored. */
1492 1.1 christos num = get_opcode_dependent_value (opcode);
1493 1.1 christos switch (type)
1494 1.1 christos {
1495 1.1 christos case AARCH64_OPND_LVt:
1496 1.1 christos assert (num >= 1 && num <= 4);
1497 1.1 christos /* Unless LD1/ST1, the number of registers should be equal to that
1498 1.1 christos of the structure elements. */
1499 1.1 christos if (num != 1 && opnd->reglist.num_regs != num)
1500 1.1 christos {
1501 1.1 christos set_reg_list_error (mismatch_detail, idx, num);
1502 1.1 christos return 0;
1503 1.1 christos }
1504 1.1 christos break;
1505 1.1 christos case AARCH64_OPND_LVt_AL:
1506 1.1 christos case AARCH64_OPND_LEt:
1507 1.1 christos assert (num >= 1 && num <= 4);
1508 1.1 christos /* The number of registers should be equal to that of the structure
1509 1.1 christos elements. */
1510 1.1 christos if (opnd->reglist.num_regs != num)
1511 1.1 christos {
1512 1.1 christos set_reg_list_error (mismatch_detail, idx, num);
1513 1.1 christos return 0;
1514 1.1 christos }
1515 1.1 christos break;
1516 1.1 christos default:
1517 1.1 christos break;
1518 1.1 christos }
1519 1.1 christos break;
1520 1.1 christos
1521 1.1 christos case AARCH64_OPND_CLASS_IMMEDIATE:
1522 1.1 christos /* Constraint check on immediate operand. */
1523 1.1 christos imm = opnd->imm.value;
1524 1.1 christos /* E.g. imm_0_31 constrains value to be 0..31. */
1525 1.1 christos if (qualifier_value_in_range_constraint_p (qualifier)
1526 1.1 christos && !value_in_range_p (imm, get_lower_bound (qualifier),
1527 1.1 christos get_upper_bound (qualifier)))
1528 1.1 christos {
1529 1.1 christos set_imm_out_of_range_error (mismatch_detail, idx,
1530 1.1 christos get_lower_bound (qualifier),
1531 1.1 christos get_upper_bound (qualifier));
1532 1.1 christos return 0;
1533 1.1 christos }
1534 1.1 christos
1535 1.1 christos switch (type)
1536 1.1 christos {
1537 1.1 christos case AARCH64_OPND_AIMM:
1538 1.1 christos if (opnd->shifter.kind != AARCH64_MOD_LSL)
1539 1.1 christos {
1540 1.1 christos set_other_error (mismatch_detail, idx,
1541 1.1 christos _("invalid shift operator"));
1542 1.1 christos return 0;
1543 1.1 christos }
1544 1.1 christos if (opnd->shifter.amount != 0 && opnd->shifter.amount != 12)
1545 1.1 christos {
1546 1.1 christos set_other_error (mismatch_detail, idx,
1547 1.1 christos _("shift amount expected to be 0 or 12"));
1548 1.1 christos return 0;
1549 1.1 christos }
1550 1.1 christos if (!value_fit_unsigned_field_p (opnd->imm.value, 12))
1551 1.1 christos {
1552 1.1 christos set_other_error (mismatch_detail, idx,
1553 1.1 christos _("immediate out of range"));
1554 1.1 christos return 0;
1555 1.1 christos }
1556 1.1 christos break;
1557 1.1 christos
1558 1.1 christos case AARCH64_OPND_HALF:
1559 1.1 christos assert (idx == 1 && opnds[0].type == AARCH64_OPND_Rd);
1560 1.1 christos if (opnd->shifter.kind != AARCH64_MOD_LSL)
1561 1.1 christos {
1562 1.1 christos set_other_error (mismatch_detail, idx,
1563 1.1 christos _("invalid shift operator"));
1564 1.1 christos return 0;
1565 1.1 christos }
1566 1.1 christos size = aarch64_get_qualifier_esize (opnds[0].qualifier);
1567 1.1 christos if (!value_aligned_p (opnd->shifter.amount, 16))
1568 1.1 christos {
1569 1.1 christos set_other_error (mismatch_detail, idx,
1570 1.1 christos _("shift amount should be a multiple of 16"));
1571 1.1 christos return 0;
1572 1.1 christos }
1573 1.1 christos if (!value_in_range_p (opnd->shifter.amount, 0, size * 8 - 16))
1574 1.1 christos {
1575 1.1 christos set_sft_amount_out_of_range_error (mismatch_detail, idx,
1576 1.1 christos 0, size * 8 - 16);
1577 1.1 christos return 0;
1578 1.1 christos }
1579 1.1 christos if (opnd->imm.value < 0)
1580 1.1 christos {
1581 1.1 christos set_other_error (mismatch_detail, idx,
1582 1.1 christos _("negative immediate value not allowed"));
1583 1.1 christos return 0;
1584 1.1 christos }
1585 1.1 christos if (!value_fit_unsigned_field_p (opnd->imm.value, 16))
1586 1.1 christos {
1587 1.1 christos set_other_error (mismatch_detail, idx,
1588 1.1 christos _("immediate out of range"));
1589 1.1 christos return 0;
1590 1.1 christos }
1591 1.1 christos break;
1592 1.1 christos
1593 1.1 christos case AARCH64_OPND_IMM_MOV:
1594 1.1 christos {
1595 1.1 christos int is32 = aarch64_get_qualifier_esize (opnds[0].qualifier) == 4;
1596 1.1 christos imm = opnd->imm.value;
1597 1.1 christos assert (idx == 1);
1598 1.1 christos switch (opcode->op)
1599 1.1 christos {
1600 1.1 christos case OP_MOV_IMM_WIDEN:
1601 1.1 christos imm = ~imm;
1602 1.1 christos /* Fall through... */
1603 1.1 christos case OP_MOV_IMM_WIDE:
1604 1.1 christos if (!aarch64_wide_constant_p (imm, is32, NULL))
1605 1.1 christos {
1606 1.1 christos set_other_error (mismatch_detail, idx,
1607 1.1 christos _("immediate out of range"));
1608 1.1 christos return 0;
1609 1.1 christos }
1610 1.1 christos break;
1611 1.1 christos case OP_MOV_IMM_LOG:
1612 1.1 christos if (!aarch64_logical_immediate_p (imm, is32, NULL))
1613 1.1 christos {
1614 1.1 christos set_other_error (mismatch_detail, idx,
1615 1.1 christos _("immediate out of range"));
1616 1.1 christos return 0;
1617 1.1 christos }
1618 1.1 christos break;
1619 1.1 christos default:
1620 1.1 christos assert (0);
1621 1.1 christos return 0;
1622 1.1 christos }
1623 1.1 christos }
1624 1.1 christos break;
1625 1.1 christos
1626 1.1 christos case AARCH64_OPND_NZCV:
1627 1.1 christos case AARCH64_OPND_CCMP_IMM:
1628 1.1 christos case AARCH64_OPND_EXCEPTION:
1629 1.1 christos case AARCH64_OPND_UIMM4:
1630 1.1 christos case AARCH64_OPND_UIMM7:
1631 1.1 christos case AARCH64_OPND_UIMM3_OP1:
1632 1.1 christos case AARCH64_OPND_UIMM3_OP2:
1633 1.1 christos size = get_operand_fields_width (get_operand_from_code (type));
1634 1.1 christos assert (size < 32);
1635 1.1 christos if (!value_fit_unsigned_field_p (opnd->imm.value, size))
1636 1.1 christos {
1637 1.1 christos set_imm_out_of_range_error (mismatch_detail, idx, 0,
1638 1.1 christos (1 << size) - 1);
1639 1.1 christos return 0;
1640 1.1 christos }
1641 1.1 christos break;
1642 1.1 christos
1643 1.1 christos case AARCH64_OPND_WIDTH:
1644 1.1 christos assert (idx == 3 && opnds[idx-1].type == AARCH64_OPND_IMM
1645 1.1 christos && opnds[0].type == AARCH64_OPND_Rd);
1646 1.1 christos size = get_upper_bound (qualifier);
1647 1.1 christos if (opnd->imm.value + opnds[idx-1].imm.value > size)
1648 1.1 christos /* lsb+width <= reg.size */
1649 1.1 christos {
1650 1.1 christos set_imm_out_of_range_error (mismatch_detail, idx, 1,
1651 1.1 christos size - opnds[idx-1].imm.value);
1652 1.1 christos return 0;
1653 1.1 christos }
1654 1.1 christos break;
1655 1.1 christos
1656 1.1 christos case AARCH64_OPND_LIMM:
1657 1.1 christos {
1658 1.1 christos int is32 = opnds[0].qualifier == AARCH64_OPND_QLF_W;
1659 1.1 christos uint64_t uimm = opnd->imm.value;
1660 1.1 christos if (opcode->op == OP_BIC)
1661 1.1 christos uimm = ~uimm;
1662 1.1 christos if (aarch64_logical_immediate_p (uimm, is32, NULL) == FALSE)
1663 1.1 christos {
1664 1.1 christos set_other_error (mismatch_detail, idx,
1665 1.1 christos _("immediate out of range"));
1666 1.1 christos return 0;
1667 1.1 christos }
1668 1.1 christos }
1669 1.1 christos break;
1670 1.1 christos
1671 1.1 christos case AARCH64_OPND_IMM0:
1672 1.1 christos case AARCH64_OPND_FPIMM0:
1673 1.1 christos if (opnd->imm.value != 0)
1674 1.1 christos {
1675 1.1 christos set_other_error (mismatch_detail, idx,
1676 1.1 christos _("immediate zero expected"));
1677 1.1 christos return 0;
1678 1.1 christos }
1679 1.1 christos break;
1680 1.1 christos
1681 1.1 christos case AARCH64_OPND_SHLL_IMM:
1682 1.1 christos assert (idx == 2);
1683 1.1 christos size = 8 * aarch64_get_qualifier_esize (opnds[idx - 1].qualifier);
1684 1.1 christos if (opnd->imm.value != size)
1685 1.1 christos {
1686 1.1 christos set_other_error (mismatch_detail, idx,
1687 1.1 christos _("invalid shift amount"));
1688 1.1 christos return 0;
1689 1.1 christos }
1690 1.1 christos break;
1691 1.1 christos
1692 1.1 christos case AARCH64_OPND_IMM_VLSL:
1693 1.1 christos size = aarch64_get_qualifier_esize (qualifier);
1694 1.1 christos if (!value_in_range_p (opnd->imm.value, 0, size * 8 - 1))
1695 1.1 christos {
1696 1.1 christos set_imm_out_of_range_error (mismatch_detail, idx, 0,
1697 1.1 christos size * 8 - 1);
1698 1.1 christos return 0;
1699 1.1 christos }
1700 1.1 christos break;
1701 1.1 christos
1702 1.1 christos case AARCH64_OPND_IMM_VLSR:
1703 1.1 christos size = aarch64_get_qualifier_esize (qualifier);
1704 1.1 christos if (!value_in_range_p (opnd->imm.value, 1, size * 8))
1705 1.1 christos {
1706 1.1 christos set_imm_out_of_range_error (mismatch_detail, idx, 1, size * 8);
1707 1.1 christos return 0;
1708 1.1 christos }
1709 1.1 christos break;
1710 1.1 christos
1711 1.1 christos case AARCH64_OPND_SIMD_IMM:
1712 1.1 christos case AARCH64_OPND_SIMD_IMM_SFT:
1713 1.1 christos /* Qualifier check. */
1714 1.1 christos switch (qualifier)
1715 1.1 christos {
1716 1.1 christos case AARCH64_OPND_QLF_LSL:
1717 1.1 christos if (opnd->shifter.kind != AARCH64_MOD_LSL)
1718 1.1 christos {
1719 1.1 christos set_other_error (mismatch_detail, idx,
1720 1.1 christos _("invalid shift operator"));
1721 1.1 christos return 0;
1722 1.1 christos }
1723 1.1 christos break;
1724 1.1 christos case AARCH64_OPND_QLF_MSL:
1725 1.1 christos if (opnd->shifter.kind != AARCH64_MOD_MSL)
1726 1.1 christos {
1727 1.1 christos set_other_error (mismatch_detail, idx,
1728 1.1 christos _("invalid shift operator"));
1729 1.1 christos return 0;
1730 1.1 christos }
1731 1.1 christos break;
1732 1.1 christos case AARCH64_OPND_QLF_NIL:
1733 1.1 christos if (opnd->shifter.kind != AARCH64_MOD_NONE)
1734 1.1 christos {
1735 1.1 christos set_other_error (mismatch_detail, idx,
1736 1.1 christos _("shift is not permitted"));
1737 1.1 christos return 0;
1738 1.1 christos }
1739 1.1 christos break;
1740 1.1 christos default:
1741 1.1 christos assert (0);
1742 1.1 christos return 0;
1743 1.1 christos }
1744 1.1 christos /* Is the immediate valid? */
1745 1.1 christos assert (idx == 1);
1746 1.1 christos if (aarch64_get_qualifier_esize (opnds[0].qualifier) != 8)
1747 1.1 christos {
1748 1.1 christos /* uimm8 or simm8 */
1749 1.1 christos if (!value_in_range_p (opnd->imm.value, -128, 255))
1750 1.1 christos {
1751 1.1 christos set_imm_out_of_range_error (mismatch_detail, idx, -128, 255);
1752 1.1 christos return 0;
1753 1.1 christos }
1754 1.1 christos }
1755 1.1 christos else if (aarch64_shrink_expanded_imm8 (opnd->imm.value) < 0)
1756 1.1 christos {
1757 1.1 christos /* uimm64 is not
1758 1.1 christos 'aaaaaaaabbbbbbbbccccccccddddddddeeeeeeee
1759 1.1 christos ffffffffgggggggghhhhhhhh'. */
1760 1.1 christos set_other_error (mismatch_detail, idx,
1761 1.1 christos _("invalid value for immediate"));
1762 1.1 christos return 0;
1763 1.1 christos }
1764 1.1 christos /* Is the shift amount valid? */
1765 1.1 christos switch (opnd->shifter.kind)
1766 1.1 christos {
1767 1.1 christos case AARCH64_MOD_LSL:
1768 1.1 christos size = aarch64_get_qualifier_esize (opnds[0].qualifier);
1769 1.1 christos if (!value_in_range_p (opnd->shifter.amount, 0, (size - 1) * 8))
1770 1.1 christos {
1771 1.1 christos set_sft_amount_out_of_range_error (mismatch_detail, idx, 0,
1772 1.1 christos (size - 1) * 8);
1773 1.1 christos return 0;
1774 1.1 christos }
1775 1.1 christos if (!value_aligned_p (opnd->shifter.amount, 8))
1776 1.1 christos {
1777 1.1 christos set_unaligned_error (mismatch_detail, idx, 8);
1778 1.1 christos return 0;
1779 1.1 christos }
1780 1.1 christos break;
1781 1.1 christos case AARCH64_MOD_MSL:
1782 1.1 christos /* Only 8 and 16 are valid shift amount. */
1783 1.1 christos if (opnd->shifter.amount != 8 && opnd->shifter.amount != 16)
1784 1.1 christos {
1785 1.1 christos set_other_error (mismatch_detail, idx,
1786 1.1 christos _("shift amount expected to be 0 or 16"));
1787 1.1 christos return 0;
1788 1.1 christos }
1789 1.1 christos break;
1790 1.1 christos default:
1791 1.1 christos if (opnd->shifter.kind != AARCH64_MOD_NONE)
1792 1.1 christos {
1793 1.1 christos set_other_error (mismatch_detail, idx,
1794 1.1 christos _("invalid shift operator"));
1795 1.1 christos return 0;
1796 1.1 christos }
1797 1.1 christos break;
1798 1.1 christos }
1799 1.1 christos break;
1800 1.1 christos
1801 1.1 christos case AARCH64_OPND_FPIMM:
1802 1.1 christos case AARCH64_OPND_SIMD_FPIMM:
1803 1.1 christos if (opnd->imm.is_fp == 0)
1804 1.1 christos {
1805 1.1 christos set_other_error (mismatch_detail, idx,
1806 1.1 christos _("floating-point immediate expected"));
1807 1.1 christos return 0;
1808 1.1 christos }
1809 1.1 christos /* The value is expected to be an 8-bit floating-point constant with
1810 1.1 christos sign, 3-bit exponent and normalized 4 bits of precision, encoded
1811 1.1 christos in "a:b:c:d:e:f:g:h" or FLD_imm8 (depending on the type of the
1812 1.1 christos instruction). */
1813 1.1 christos if (!value_in_range_p (opnd->imm.value, 0, 255))
1814 1.1 christos {
1815 1.1 christos set_other_error (mismatch_detail, idx,
1816 1.1 christos _("immediate out of range"));
1817 1.1 christos return 0;
1818 1.1 christos }
1819 1.1 christos if (opnd->shifter.kind != AARCH64_MOD_NONE)
1820 1.1 christos {
1821 1.1 christos set_other_error (mismatch_detail, idx,
1822 1.1 christos _("invalid shift operator"));
1823 1.1 christos return 0;
1824 1.1 christos }
1825 1.1 christos break;
1826 1.1 christos
1827 1.1 christos default:
1828 1.1 christos break;
1829 1.1 christos }
1830 1.1 christos break;
1831 1.1 christos
1832 1.1 christos case AARCH64_OPND_CLASS_CP_REG:
1833 1.1 christos /* Cn or Cm: 4-bit opcode field named for historical reasons.
1834 1.1 christos valid range: C0 - C15. */
1835 1.1 christos if (opnd->reg.regno > 15)
1836 1.1 christos {
1837 1.1 christos set_regno_out_of_range_error (mismatch_detail, idx, 0, 15);
1838 1.1 christos return 0;
1839 1.1 christos }
1840 1.1 christos break;
1841 1.1 christos
1842 1.1 christos case AARCH64_OPND_CLASS_SYSTEM:
1843 1.1 christos switch (type)
1844 1.1 christos {
1845 1.1 christos case AARCH64_OPND_PSTATEFIELD:
1846 1.1 christos assert (idx == 0 && opnds[1].type == AARCH64_OPND_UIMM4);
1847 1.1 christos /* MSR SPSel, #uimm4
1848 1.1 christos Uses uimm4 as a control value to select the stack pointer: if
1849 1.1 christos bit 0 is set it selects the current exception level's stack
1850 1.1 christos pointer, if bit 0 is clear it selects shared EL0 stack pointer.
1851 1.1 christos Bits 1 to 3 of uimm4 are reserved and should be zero. */
1852 1.1 christos if (opnd->pstatefield == 0x05 /* spsel */ && opnds[1].imm.value > 1)
1853 1.1 christos {
1854 1.1 christos set_imm_out_of_range_error (mismatch_detail, idx, 0, 1);
1855 1.1 christos return 0;
1856 1.1 christos }
1857 1.1 christos break;
1858 1.1 christos default:
1859 1.1 christos break;
1860 1.1 christos }
1861 1.1 christos break;
1862 1.1 christos
1863 1.1 christos case AARCH64_OPND_CLASS_SIMD_ELEMENT:
1864 1.1 christos /* Get the upper bound for the element index. */
1865 1.1 christos num = 16 / aarch64_get_qualifier_esize (qualifier) - 1;
1866 1.1 christos /* Index out-of-range. */
1867 1.1 christos if (!value_in_range_p (opnd->reglane.index, 0, num))
1868 1.1 christos {
1869 1.1 christos set_elem_idx_out_of_range_error (mismatch_detail, idx, 0, num);
1870 1.1 christos return 0;
1871 1.1 christos }
1872 1.1 christos /* SMLAL<Q> <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Ts>[<index>].
1873 1.1 christos <Vm> Is the vector register (V0-V31) or (V0-V15), whose
1874 1.1 christos number is encoded in "size:M:Rm":
1875 1.1 christos size <Vm>
1876 1.1 christos 00 RESERVED
1877 1.1 christos 01 0:Rm
1878 1.1 christos 10 M:Rm
1879 1.1 christos 11 RESERVED */
1880 1.1 christos if (type == AARCH64_OPND_Em && qualifier == AARCH64_OPND_QLF_S_H
1881 1.1 christos && !value_in_range_p (opnd->reglane.regno, 0, 15))
1882 1.1 christos {
1883 1.1 christos set_regno_out_of_range_error (mismatch_detail, idx, 0, 15);
1884 1.1 christos return 0;
1885 1.1 christos }
1886 1.1 christos break;
1887 1.1 christos
1888 1.1 christos case AARCH64_OPND_CLASS_MODIFIED_REG:
1889 1.1 christos assert (idx == 1 || idx == 2);
1890 1.1 christos switch (type)
1891 1.1 christos {
1892 1.1 christos case AARCH64_OPND_Rm_EXT:
1893 1.1 christos if (aarch64_extend_operator_p (opnd->shifter.kind) == FALSE
1894 1.1 christos && opnd->shifter.kind != AARCH64_MOD_LSL)
1895 1.1 christos {
1896 1.1 christos set_other_error (mismatch_detail, idx,
1897 1.1 christos _("extend operator expected"));
1898 1.1 christos return 0;
1899 1.1 christos }
1900 1.1 christos /* It is not optional unless at least one of "Rd" or "Rn" is '11111'
1901 1.1 christos (i.e. SP), in which case it defaults to LSL. The LSL alias is
1902 1.1 christos only valid when "Rd" or "Rn" is '11111', and is preferred in that
1903 1.1 christos case. */
1904 1.1 christos if (!aarch64_stack_pointer_p (opnds + 0)
1905 1.1 christos && (idx != 2 || !aarch64_stack_pointer_p (opnds + 1)))
1906 1.1 christos {
1907 1.1 christos if (!opnd->shifter.operator_present)
1908 1.1 christos {
1909 1.1 christos set_other_error (mismatch_detail, idx,
1910 1.1 christos _("missing extend operator"));
1911 1.1 christos return 0;
1912 1.1 christos }
1913 1.1 christos else if (opnd->shifter.kind == AARCH64_MOD_LSL)
1914 1.1 christos {
1915 1.1 christos set_other_error (mismatch_detail, idx,
1916 1.1 christos _("'LSL' operator not allowed"));
1917 1.1 christos return 0;
1918 1.1 christos }
1919 1.1 christos }
1920 1.1 christos assert (opnd->shifter.operator_present /* Default to LSL. */
1921 1.1 christos || opnd->shifter.kind == AARCH64_MOD_LSL);
1922 1.1 christos if (!value_in_range_p (opnd->shifter.amount, 0, 4))
1923 1.1 christos {
1924 1.1 christos set_sft_amount_out_of_range_error (mismatch_detail, idx, 0, 4);
1925 1.1 christos return 0;
1926 1.1 christos }
1927 1.1 christos /* In the 64-bit form, the final register operand is written as Wm
1928 1.1 christos for all but the (possibly omitted) UXTX/LSL and SXTX
1929 1.1 christos operators.
1930 1.1 christos N.B. GAS allows X register to be used with any operator as a
1931 1.1 christos programming convenience. */
1932 1.1 christos if (qualifier == AARCH64_OPND_QLF_X
1933 1.1 christos && opnd->shifter.kind != AARCH64_MOD_LSL
1934 1.1 christos && opnd->shifter.kind != AARCH64_MOD_UXTX
1935 1.1 christos && opnd->shifter.kind != AARCH64_MOD_SXTX)
1936 1.1 christos {
1937 1.1 christos set_other_error (mismatch_detail, idx, _("W register expected"));
1938 1.1 christos return 0;
1939 1.1 christos }
1940 1.1 christos break;
1941 1.1 christos
1942 1.1 christos case AARCH64_OPND_Rm_SFT:
1943 1.1 christos /* ROR is not available to the shifted register operand in
1944 1.1 christos arithmetic instructions. */
1945 1.1 christos if (aarch64_shift_operator_p (opnd->shifter.kind) == FALSE)
1946 1.1 christos {
1947 1.1 christos set_other_error (mismatch_detail, idx,
1948 1.1 christos _("shift operator expected"));
1949 1.1 christos return 0;
1950 1.1 christos }
1951 1.1 christos if (opnd->shifter.kind == AARCH64_MOD_ROR
1952 1.1 christos && opcode->iclass != log_shift)
1953 1.1 christos {
1954 1.1 christos set_other_error (mismatch_detail, idx,
1955 1.1 christos _("'ROR' operator not allowed"));
1956 1.1 christos return 0;
1957 1.1 christos }
1958 1.1 christos num = qualifier == AARCH64_OPND_QLF_W ? 31 : 63;
1959 1.1 christos if (!value_in_range_p (opnd->shifter.amount, 0, num))
1960 1.1 christos {
1961 1.1 christos set_sft_amount_out_of_range_error (mismatch_detail, idx, 0, num);
1962 1.1 christos return 0;
1963 1.1 christos }
1964 1.1 christos break;
1965 1.1 christos
1966 1.1 christos default:
1967 1.1 christos break;
1968 1.1 christos }
1969 1.1 christos break;
1970 1.1 christos
1971 1.1 christos default:
1972 1.1 christos break;
1973 1.1 christos }
1974 1.1 christos
1975 1.1 christos return 1;
1976 1.1 christos }
1977 1.1 christos
1978 1.1 christos /* Main entrypoint for the operand constraint checking.
1979 1.1 christos
1980 1.1 christos Return 1 if operands of *INST meet the constraint applied by the operand
1981 1.1 christos codes and operand qualifiers; otherwise return 0 and if MISMATCH_DETAIL is
1982 1.1 christos not NULL, return the detail of the error in *MISMATCH_DETAIL. N.B. when
1983 1.1 christos adding more constraint checking, make sure MISMATCH_DETAIL->KIND is set
1984 1.1 christos with a proper error kind rather than AARCH64_OPDE_NIL (GAS asserts non-NIL
1985 1.1 christos error kind when it is notified that an instruction does not pass the check).
1986 1.1 christos
1987 1.1 christos Un-determined operand qualifiers may get established during the process. */
1988 1.1 christos
1989 1.1 christos int
1990 1.1 christos aarch64_match_operands_constraint (aarch64_inst *inst,
1991 1.1 christos aarch64_operand_error *mismatch_detail)
1992 1.1 christos {
1993 1.1 christos int i;
1994 1.1 christos
1995 1.1 christos DEBUG_TRACE ("enter");
1996 1.1 christos
1997 1.1 christos /* Match operands' qualifier.
1998 1.1 christos *INST has already had qualifier establish for some, if not all, of
1999 1.1 christos its operands; we need to find out whether these established
2000 1.1 christos qualifiers match one of the qualifier sequence in
2001 1.1 christos INST->OPCODE->QUALIFIERS_LIST. If yes, we will assign each operand
2002 1.1 christos with the corresponding qualifier in such a sequence.
2003 1.1 christos Only basic operand constraint checking is done here; the more thorough
2004 1.1 christos constraint checking will carried out by operand_general_constraint_met_p,
2005 1.1 christos which has be to called after this in order to get all of the operands'
2006 1.1 christos qualifiers established. */
2007 1.1 christos if (match_operands_qualifier (inst, TRUE /* update_p */) == 0)
2008 1.1 christos {
2009 1.1 christos DEBUG_TRACE ("FAIL on operand qualifier matching");
2010 1.1 christos if (mismatch_detail)
2011 1.1 christos {
2012 1.1 christos /* Return an error type to indicate that it is the qualifier
2013 1.1 christos matching failure; we don't care about which operand as there
2014 1.1 christos are enough information in the opcode table to reproduce it. */
2015 1.1 christos mismatch_detail->kind = AARCH64_OPDE_INVALID_VARIANT;
2016 1.1 christos mismatch_detail->index = -1;
2017 1.1 christos mismatch_detail->error = NULL;
2018 1.1 christos }
2019 1.1 christos return 0;
2020 1.1 christos }
2021 1.1 christos
2022 1.1 christos /* Match operands' constraint. */
2023 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
2024 1.1 christos {
2025 1.1 christos enum aarch64_opnd type = inst->opcode->operands[i];
2026 1.1 christos if (type == AARCH64_OPND_NIL)
2027 1.1 christos break;
2028 1.1 christos if (inst->operands[i].skip)
2029 1.1 christos {
2030 1.1 christos DEBUG_TRACE ("skip the incomplete operand %d", i);
2031 1.1 christos continue;
2032 1.1 christos }
2033 1.1 christos if (operand_general_constraint_met_p (inst->operands, i, type,
2034 1.1 christos inst->opcode, mismatch_detail) == 0)
2035 1.1 christos {
2036 1.1 christos DEBUG_TRACE ("FAIL on operand %d", i);
2037 1.1 christos return 0;
2038 1.1 christos }
2039 1.1 christos }
2040 1.1 christos
2041 1.1 christos DEBUG_TRACE ("PASS");
2042 1.1 christos
2043 1.1 christos return 1;
2044 1.1 christos }
2045 1.1 christos
2046 1.1 christos /* Replace INST->OPCODE with OPCODE and return the replaced OPCODE.
2047 1.1 christos Also updates the TYPE of each INST->OPERANDS with the corresponding
2048 1.1 christos value of OPCODE->OPERANDS.
2049 1.1 christos
2050 1.1 christos Note that some operand qualifiers may need to be manually cleared by
2051 1.1 christos the caller before it further calls the aarch64_opcode_encode; by
2052 1.1 christos doing this, it helps the qualifier matching facilities work
2053 1.1 christos properly. */
2054 1.1 christos
2055 1.1 christos const aarch64_opcode*
2056 1.1 christos aarch64_replace_opcode (aarch64_inst *inst, const aarch64_opcode *opcode)
2057 1.1 christos {
2058 1.1 christos int i;
2059 1.1 christos const aarch64_opcode *old = inst->opcode;
2060 1.1 christos
2061 1.1 christos inst->opcode = opcode;
2062 1.1 christos
2063 1.1 christos /* Update the operand types. */
2064 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
2065 1.1 christos {
2066 1.1 christos inst->operands[i].type = opcode->operands[i];
2067 1.1 christos if (opcode->operands[i] == AARCH64_OPND_NIL)
2068 1.1 christos break;
2069 1.1 christos }
2070 1.1 christos
2071 1.1 christos DEBUG_TRACE ("replace %s with %s", old->name, opcode->name);
2072 1.1 christos
2073 1.1 christos return old;
2074 1.1 christos }
2075 1.1 christos
2076 1.1 christos int
2077 1.1 christos aarch64_operand_index (const enum aarch64_opnd *operands, enum aarch64_opnd operand)
2078 1.1 christos {
2079 1.1 christos int i;
2080 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
2081 1.1 christos if (operands[i] == operand)
2082 1.1 christos return i;
2083 1.1 christos else if (operands[i] == AARCH64_OPND_NIL)
2084 1.1 christos break;
2085 1.1 christos return -1;
2086 1.1 christos }
2087 1.1 christos
2088 1.1 christos /* [0][0] 32-bit integer regs with sp Wn
2090 1.1 christos [0][1] 64-bit integer regs with sp Xn sf=1
2091 1.1 christos [1][0] 32-bit integer regs with #0 Wn
2092 1.1 christos [1][1] 64-bit integer regs with #0 Xn sf=1 */
2093 1.1 christos static const char *int_reg[2][2][32] = {
2094 1.1 christos #define R32 "w"
2095 1.1 christos #define R64 "x"
2096 1.1 christos { { R32 "0", R32 "1", R32 "2", R32 "3", R32 "4", R32 "5", R32 "6", R32 "7",
2097 1.1 christos R32 "8", R32 "9", R32 "10", R32 "11", R32 "12", R32 "13", R32 "14", R32 "15",
2098 1.1 christos R32 "16", R32 "17", R32 "18", R32 "19", R32 "20", R32 "21", R32 "22", R32 "23",
2099 1.1 christos R32 "24", R32 "25", R32 "26", R32 "27", R32 "28", R32 "29", R32 "30", "wsp" },
2100 1.1 christos { R64 "0", R64 "1", R64 "2", R64 "3", R64 "4", R64 "5", R64 "6", R64 "7",
2101 1.1 christos R64 "8", R64 "9", R64 "10", R64 "11", R64 "12", R64 "13", R64 "14", R64 "15",
2102 1.1 christos R64 "16", R64 "17", R64 "18", R64 "19", R64 "20", R64 "21", R64 "22", R64 "23",
2103 1.1 christos R64 "24", R64 "25", R64 "26", R64 "27", R64 "28", R64 "29", R64 "30", "sp" } },
2104 1.1 christos { { R32 "0", R32 "1", R32 "2", R32 "3", R32 "4", R32 "5", R32 "6", R32 "7",
2105 1.1 christos R32 "8", R32 "9", R32 "10", R32 "11", R32 "12", R32 "13", R32 "14", R32 "15",
2106 1.1 christos R32 "16", R32 "17", R32 "18", R32 "19", R32 "20", R32 "21", R32 "22", R32 "23",
2107 1.1 christos R32 "24", R32 "25", R32 "26", R32 "27", R32 "28", R32 "29", R32 "30", R32 "zr" },
2108 1.1 christos { R64 "0", R64 "1", R64 "2", R64 "3", R64 "4", R64 "5", R64 "6", R64 "7",
2109 1.1 christos R64 "8", R64 "9", R64 "10", R64 "11", R64 "12", R64 "13", R64 "14", R64 "15",
2110 1.1 christos R64 "16", R64 "17", R64 "18", R64 "19", R64 "20", R64 "21", R64 "22", R64 "23",
2111 1.1 christos R64 "24", R64 "25", R64 "26", R64 "27", R64 "28", R64 "29", R64 "30", R64 "zr" } }
2112 1.1 christos #undef R64
2113 1.1 christos #undef R32
2114 1.1 christos };
2115 1.1 christos
2116 1.1 christos /* Return the integer register name.
2117 1.1 christos if SP_REG_P is not 0, R31 is an SP reg, other R31 is the zero reg. */
2118 1.1 christos
2119 1.1 christos static inline const char *
2120 1.1 christos get_int_reg_name (int regno, aarch64_opnd_qualifier_t qualifier, int sp_reg_p)
2121 1.1 christos {
2122 1.1 christos const int has_zr = sp_reg_p ? 0 : 1;
2123 1.1 christos const int is_64 = aarch64_get_qualifier_esize (qualifier) == 4 ? 0 : 1;
2124 1.1 christos return int_reg[has_zr][is_64][regno];
2125 1.1 christos }
2126 1.1 christos
2127 1.1 christos /* Like get_int_reg_name, but IS_64 is always 1. */
2128 1.1 christos
2129 1.1 christos static inline const char *
2130 1.1 christos get_64bit_int_reg_name (int regno, int sp_reg_p)
2131 1.1 christos {
2132 1.1 christos const int has_zr = sp_reg_p ? 0 : 1;
2133 1.1 christos return int_reg[has_zr][1][regno];
2134 1.1 christos }
2135 1.1 christos
2136 1.1 christos /* Types for expanding an encoded 8-bit value to a floating-point value. */
2137 1.1 christos
2138 1.1 christos typedef union
2139 1.1 christos {
2140 1.1 christos uint64_t i;
2141 1.1 christos double d;
2142 1.1 christos } double_conv_t;
2143 1.1 christos
2144 1.1 christos typedef union
2145 1.1 christos {
2146 1.1 christos uint32_t i;
2147 1.1 christos float f;
2148 1.1 christos } single_conv_t;
2149 1.1 christos
2150 1.1 christos /* IMM8 is an 8-bit floating-point constant with sign, 3-bit exponent and
2151 1.1 christos normalized 4 bits of precision, encoded in "a:b:c:d:e:f:g:h" or FLD_imm8
2152 1.1 christos (depending on the type of the instruction). IMM8 will be expanded to a
2153 1.1 christos single-precision floating-point value (IS_DP == 0) or a double-precision
2154 1.1 christos floating-point value (IS_DP == 1). The expanded value is returned. */
2155 1.1 christos
2156 1.1 christos static uint64_t
2157 1.1 christos expand_fp_imm (int is_dp, uint32_t imm8)
2158 1.1 christos {
2159 1.1 christos uint64_t imm;
2160 1.1 christos uint32_t imm8_7, imm8_6_0, imm8_6, imm8_6_repl4;
2161 1.1 christos
2162 1.1 christos imm8_7 = (imm8 >> 7) & 0x01; /* imm8<7> */
2163 1.1 christos imm8_6_0 = imm8 & 0x7f; /* imm8<6:0> */
2164 1.1 christos imm8_6 = imm8_6_0 >> 6; /* imm8<6> */
2165 1.1 christos imm8_6_repl4 = (imm8_6 << 3) | (imm8_6 << 2)
2166 1.1 christos | (imm8_6 << 1) | imm8_6; /* Replicate(imm8<6>,4) */
2167 1.1 christos if (is_dp)
2168 1.1 christos {
2169 1.1 christos imm = (imm8_7 << (63-32)) /* imm8<7> */
2170 1.1 christos | ((imm8_6 ^ 1) << (62-32)) /* NOT(imm8<6) */
2171 1.1 christos | (imm8_6_repl4 << (58-32)) | (imm8_6 << (57-32))
2172 1.1 christos | (imm8_6 << (56-32)) | (imm8_6 << (55-32)) /* Replicate(imm8<6>,7) */
2173 1.1 christos | (imm8_6_0 << (48-32)); /* imm8<6>:imm8<5:0> */
2174 1.1 christos imm <<= 32;
2175 1.1 christos }
2176 1.1 christos else
2177 1.1 christos {
2178 1.1 christos imm = (imm8_7 << 31) /* imm8<7> */
2179 1.1 christos | ((imm8_6 ^ 1) << 30) /* NOT(imm8<6>) */
2180 1.1 christos | (imm8_6_repl4 << 26) /* Replicate(imm8<6>,4) */
2181 1.1 christos | (imm8_6_0 << 19); /* imm8<6>:imm8<5:0> */
2182 1.1 christos }
2183 1.1 christos
2184 1.1 christos return imm;
2185 1.1 christos }
2186 1.1 christos
2187 1.1 christos /* Produce the string representation of the register list operand *OPND
2188 1.1 christos in the buffer pointed by BUF of size SIZE. */
2189 1.1 christos static void
2190 1.1 christos print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd)
2191 1.1 christos {
2192 1.1 christos const int num_regs = opnd->reglist.num_regs;
2193 1.1 christos const int first_reg = opnd->reglist.first_regno;
2194 1.1 christos const int last_reg = (first_reg + num_regs - 1) & 0x1f;
2195 1.1 christos const char *qlf_name = aarch64_get_qualifier_name (opnd->qualifier);
2196 1.1 christos char tb[8]; /* Temporary buffer. */
2197 1.1 christos
2198 1.1 christos assert (opnd->type != AARCH64_OPND_LEt || opnd->reglist.has_index);
2199 1.1 christos assert (num_regs >= 1 && num_regs <= 4);
2200 1.1 christos
2201 1.1 christos /* Prepare the index if any. */
2202 1.1 christos if (opnd->reglist.has_index)
2203 1.1 christos snprintf (tb, 8, "[%d]", opnd->reglist.index);
2204 1.1 christos else
2205 1.1 christos tb[0] = '\0';
2206 1.1 christos
2207 1.1 christos /* The hyphenated form is preferred for disassembly if there are
2208 1.1 christos more than two registers in the list, and the register numbers
2209 1.1 christos are monotonically increasing in increments of one. */
2210 1.1 christos if (num_regs > 2 && last_reg > first_reg)
2211 1.1 christos snprintf (buf, size, "{v%d.%s-v%d.%s}%s", first_reg, qlf_name,
2212 1.1 christos last_reg, qlf_name, tb);
2213 1.1 christos else
2214 1.1 christos {
2215 1.1 christos const int reg0 = first_reg;
2216 1.1 christos const int reg1 = (first_reg + 1) & 0x1f;
2217 1.1 christos const int reg2 = (first_reg + 2) & 0x1f;
2218 1.1 christos const int reg3 = (first_reg + 3) & 0x1f;
2219 1.1 christos
2220 1.1 christos switch (num_regs)
2221 1.1 christos {
2222 1.1 christos case 1:
2223 1.1 christos snprintf (buf, size, "{v%d.%s}%s", reg0, qlf_name, tb);
2224 1.1 christos break;
2225 1.1 christos case 2:
2226 1.1 christos snprintf (buf, size, "{v%d.%s, v%d.%s}%s", reg0, qlf_name,
2227 1.1 christos reg1, qlf_name, tb);
2228 1.1 christos break;
2229 1.1 christos case 3:
2230 1.1 christos snprintf (buf, size, "{v%d.%s, v%d.%s, v%d.%s}%s", reg0, qlf_name,
2231 1.1 christos reg1, qlf_name, reg2, qlf_name, tb);
2232 1.1 christos break;
2233 1.1 christos case 4:
2234 1.1 christos snprintf (buf, size, "{v%d.%s, v%d.%s, v%d.%s, v%d.%s}%s",
2235 1.1 christos reg0, qlf_name, reg1, qlf_name, reg2, qlf_name,
2236 1.1 christos reg3, qlf_name, tb);
2237 1.1 christos break;
2238 1.1 christos }
2239 1.1 christos }
2240 1.1 christos }
2241 1.1 christos
2242 1.1 christos /* Produce the string representation of the register offset address operand
2243 1.1 christos *OPND in the buffer pointed by BUF of size SIZE. */
2244 1.1 christos static void
2245 1.1 christos print_register_offset_address (char *buf, size_t size,
2246 1.1 christos const aarch64_opnd_info *opnd)
2247 1.1 christos {
2248 1.1 christos const size_t tblen = 16;
2249 1.1 christos char tb[tblen]; /* Temporary buffer. */
2250 1.1 christos bfd_boolean lsl_p = FALSE; /* Is LSL shift operator? */
2251 1.1 christos bfd_boolean wm_p = FALSE; /* Should Rm be Wm? */
2252 1.1 christos bfd_boolean print_extend_p = TRUE;
2253 1.1 christos bfd_boolean print_amount_p = TRUE;
2254 1.1 christos const char *shift_name = aarch64_operand_modifiers[opnd->shifter.kind].name;
2255 1.1 christos
2256 1.1 christos switch (opnd->shifter.kind)
2257 1.1 christos {
2258 1.1 christos case AARCH64_MOD_UXTW: wm_p = TRUE; break;
2259 1.1 christos case AARCH64_MOD_LSL : lsl_p = TRUE; break;
2260 1.1 christos case AARCH64_MOD_SXTW: wm_p = TRUE; break;
2261 1.1 christos case AARCH64_MOD_SXTX: break;
2262 1.1 christos default: assert (0);
2263 1.1 christos }
2264 1.1 christos
2265 1.1 christos if (!opnd->shifter.amount && (opnd->qualifier != AARCH64_OPND_QLF_S_B
2266 1.1 christos || !opnd->shifter.amount_present))
2267 1.1 christos {
2268 1.1 christos /* Not print the shift/extend amount when the amount is zero and
2269 1.1 christos when it is not the special case of 8-bit load/store instruction. */
2270 1.1 christos print_amount_p = FALSE;
2271 1.1 christos /* Likewise, no need to print the shift operator LSL in such a
2272 1.1 christos situation. */
2273 1.1 christos if (lsl_p)
2274 1.1 christos print_extend_p = FALSE;
2275 1.1 christos }
2276 1.1 christos
2277 1.1 christos /* Prepare for the extend/shift. */
2278 1.1 christos if (print_extend_p)
2279 1.1 christos {
2280 1.1 christos if (print_amount_p)
2281 1.1 christos snprintf (tb, tblen, ",%s #%d", shift_name, opnd->shifter.amount);
2282 1.1 christos else
2283 1.1 christos snprintf (tb, tblen, ",%s", shift_name);
2284 1.1 christos }
2285 1.1 christos else
2286 1.1 christos tb[0] = '\0';
2287 1.1 christos
2288 1.1 christos snprintf (buf, size, "[%s,%c%d%s]",
2289 1.1 christos get_64bit_int_reg_name (opnd->addr.base_regno, 1),
2290 1.1 christos wm_p ? 'w' : 'x', opnd->addr.offset.regno, tb);
2291 1.1 christos }
2292 1.1 christos
2293 1.1 christos /* Generate the string representation of the operand OPNDS[IDX] for OPCODE
2294 1.1 christos in *BUF. The caller should pass in the maximum size of *BUF in SIZE.
2295 1.1 christos PC, PCREL_P and ADDRESS are used to pass in and return information about
2296 1.1 christos the PC-relative address calculation, where the PC value is passed in
2297 1.1 christos PC. If the operand is pc-relative related, *PCREL_P (if PCREL_P non-NULL)
2298 1.1 christos will return 1 and *ADDRESS (if ADDRESS non-NULL) will return the
2299 1.1 christos calculated address; otherwise, *PCREL_P (if PCREL_P non-NULL) returns 0.
2300 1.1 christos
2301 1.1 christos The function serves both the disassembler and the assembler diagnostics
2302 1.1 christos issuer, which is the reason why it lives in this file. */
2303 1.1 christos
2304 1.1 christos void
2305 1.1 christos aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
2306 1.1 christos const aarch64_opcode *opcode,
2307 1.1 christos const aarch64_opnd_info *opnds, int idx, int *pcrel_p,
2308 1.1 christos bfd_vma *address)
2309 1.1 christos {
2310 1.1 christos int i;
2311 1.1 christos const char *name = NULL;
2312 1.1 christos const aarch64_opnd_info *opnd = opnds + idx;
2313 1.1 christos enum aarch64_modifier_kind kind;
2314 1.1 christos uint64_t addr;
2315 1.1 christos
2316 1.1 christos buf[0] = '\0';
2317 1.1 christos if (pcrel_p)
2318 1.1 christos *pcrel_p = 0;
2319 1.1 christos
2320 1.1 christos switch (opnd->type)
2321 1.1 christos {
2322 1.1 christos case AARCH64_OPND_Rd:
2323 1.1 christos case AARCH64_OPND_Rn:
2324 1.1 christos case AARCH64_OPND_Rm:
2325 1.1 christos case AARCH64_OPND_Rt:
2326 1.1 christos case AARCH64_OPND_Rt2:
2327 1.1 christos case AARCH64_OPND_Rs:
2328 1.1 christos case AARCH64_OPND_Ra:
2329 1.1 christos case AARCH64_OPND_Rt_SYS:
2330 1.1 christos /* The optional-ness of <Xt> in e.g. IC <ic_op>{, <Xt>} is determined by
2331 1.1 christos the <ic_op>, therefore we we use opnd->present to override the
2332 1.1 christos generic optional-ness information. */
2333 1.1 christos if (opnd->type == AARCH64_OPND_Rt_SYS && !opnd->present)
2334 1.1 christos break;
2335 1.1 christos /* Omit the operand, e.g. RET. */
2336 1.1 christos if (optional_operand_p (opcode, idx)
2337 1.1 christos && opnd->reg.regno == get_optional_operand_default_value (opcode))
2338 1.1 christos break;
2339 1.1 christos assert (opnd->qualifier == AARCH64_OPND_QLF_W
2340 1.1 christos || opnd->qualifier == AARCH64_OPND_QLF_X);
2341 1.1 christos snprintf (buf, size, "%s",
2342 1.1 christos get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
2343 1.1 christos break;
2344 1.1 christos
2345 1.1 christos case AARCH64_OPND_Rd_SP:
2346 1.1 christos case AARCH64_OPND_Rn_SP:
2347 1.1 christos assert (opnd->qualifier == AARCH64_OPND_QLF_W
2348 1.1 christos || opnd->qualifier == AARCH64_OPND_QLF_WSP
2349 1.1 christos || opnd->qualifier == AARCH64_OPND_QLF_X
2350 1.1 christos || opnd->qualifier == AARCH64_OPND_QLF_SP);
2351 1.1 christos snprintf (buf, size, "%s",
2352 1.1 christos get_int_reg_name (opnd->reg.regno, opnd->qualifier, 1));
2353 1.1 christos break;
2354 1.1 christos
2355 1.1 christos case AARCH64_OPND_Rm_EXT:
2356 1.1 christos kind = opnd->shifter.kind;
2357 1.1 christos assert (idx == 1 || idx == 2);
2358 1.1 christos if ((aarch64_stack_pointer_p (opnds)
2359 1.1 christos || (idx == 2 && aarch64_stack_pointer_p (opnds + 1)))
2360 1.1 christos && ((opnd->qualifier == AARCH64_OPND_QLF_W
2361 1.1 christos && opnds[0].qualifier == AARCH64_OPND_QLF_W
2362 1.1 christos && kind == AARCH64_MOD_UXTW)
2363 1.1 christos || (opnd->qualifier == AARCH64_OPND_QLF_X
2364 1.1 christos && kind == AARCH64_MOD_UXTX)))
2365 1.1 christos {
2366 1.1 christos /* 'LSL' is the preferred form in this case. */
2367 1.1 christos kind = AARCH64_MOD_LSL;
2368 1.1 christos if (opnd->shifter.amount == 0)
2369 1.1 christos {
2370 1.1 christos /* Shifter omitted. */
2371 1.1 christos snprintf (buf, size, "%s",
2372 1.1 christos get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
2373 1.1 christos break;
2374 1.1 christos }
2375 1.1 christos }
2376 1.1 christos if (opnd->shifter.amount)
2377 1.1 christos snprintf (buf, size, "%s, %s #%d",
2378 1.1 christos get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
2379 1.1 christos aarch64_operand_modifiers[kind].name,
2380 1.1 christos opnd->shifter.amount);
2381 1.1 christos else
2382 1.1 christos snprintf (buf, size, "%s, %s",
2383 1.1 christos get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
2384 1.1 christos aarch64_operand_modifiers[kind].name);
2385 1.1 christos break;
2386 1.1 christos
2387 1.1 christos case AARCH64_OPND_Rm_SFT:
2388 1.1 christos assert (opnd->qualifier == AARCH64_OPND_QLF_W
2389 1.1 christos || opnd->qualifier == AARCH64_OPND_QLF_X);
2390 1.1 christos if (opnd->shifter.amount == 0 && opnd->shifter.kind == AARCH64_MOD_LSL)
2391 1.1 christos snprintf (buf, size, "%s",
2392 1.1 christos get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
2393 1.1 christos else
2394 1.1 christos snprintf (buf, size, "%s, %s #%d",
2395 1.1 christos get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
2396 1.1 christos aarch64_operand_modifiers[opnd->shifter.kind].name,
2397 1.1 christos opnd->shifter.amount);
2398 1.1 christos break;
2399 1.1 christos
2400 1.1 christos case AARCH64_OPND_Fd:
2401 1.1 christos case AARCH64_OPND_Fn:
2402 1.1 christos case AARCH64_OPND_Fm:
2403 1.1 christos case AARCH64_OPND_Fa:
2404 1.1 christos case AARCH64_OPND_Ft:
2405 1.1 christos case AARCH64_OPND_Ft2:
2406 1.1 christos case AARCH64_OPND_Sd:
2407 1.1 christos case AARCH64_OPND_Sn:
2408 1.1 christos case AARCH64_OPND_Sm:
2409 1.1 christos snprintf (buf, size, "%s%d", aarch64_get_qualifier_name (opnd->qualifier),
2410 1.1 christos opnd->reg.regno);
2411 1.1 christos break;
2412 1.1 christos
2413 1.1 christos case AARCH64_OPND_Vd:
2414 1.1 christos case AARCH64_OPND_Vn:
2415 1.1 christos case AARCH64_OPND_Vm:
2416 1.1 christos snprintf (buf, size, "v%d.%s", opnd->reg.regno,
2417 1.1 christos aarch64_get_qualifier_name (opnd->qualifier));
2418 1.1 christos break;
2419 1.1 christos
2420 1.1 christos case AARCH64_OPND_Ed:
2421 1.1 christos case AARCH64_OPND_En:
2422 1.1 christos case AARCH64_OPND_Em:
2423 1.1 christos snprintf (buf, size, "v%d.%s[%d]", opnd->reglane.regno,
2424 1.1 christos aarch64_get_qualifier_name (opnd->qualifier),
2425 1.1 christos opnd->reglane.index);
2426 1.1 christos break;
2427 1.1 christos
2428 1.1 christos case AARCH64_OPND_VdD1:
2429 1.1 christos case AARCH64_OPND_VnD1:
2430 1.1 christos snprintf (buf, size, "v%d.d[1]", opnd->reg.regno);
2431 1.1 christos break;
2432 1.1 christos
2433 1.1 christos case AARCH64_OPND_LVn:
2434 1.1 christos case AARCH64_OPND_LVt:
2435 1.1 christos case AARCH64_OPND_LVt_AL:
2436 1.1 christos case AARCH64_OPND_LEt:
2437 1.1 christos print_register_list (buf, size, opnd);
2438 1.1 christos break;
2439 1.1 christos
2440 1.1 christos case AARCH64_OPND_Cn:
2441 1.1 christos case AARCH64_OPND_Cm:
2442 1.1 christos snprintf (buf, size, "C%d", opnd->reg.regno);
2443 1.1 christos break;
2444 1.1 christos
2445 1.1 christos case AARCH64_OPND_IDX:
2446 1.1 christos case AARCH64_OPND_IMM:
2447 1.1 christos case AARCH64_OPND_WIDTH:
2448 1.1 christos case AARCH64_OPND_UIMM3_OP1:
2449 1.1 christos case AARCH64_OPND_UIMM3_OP2:
2450 1.1 christos case AARCH64_OPND_BIT_NUM:
2451 1.1 christos case AARCH64_OPND_IMM_VLSL:
2452 1.1 christos case AARCH64_OPND_IMM_VLSR:
2453 1.1 christos case AARCH64_OPND_SHLL_IMM:
2454 1.1 christos case AARCH64_OPND_IMM0:
2455 1.1 christos case AARCH64_OPND_IMMR:
2456 1.1 christos case AARCH64_OPND_IMMS:
2457 1.1 christos case AARCH64_OPND_FBITS:
2458 1.1 christos snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
2459 1.1 christos break;
2460 1.1 christos
2461 1.1 christos case AARCH64_OPND_IMM_MOV:
2462 1.1 christos switch (aarch64_get_qualifier_esize (opnds[0].qualifier))
2463 1.1 christos {
2464 1.1 christos case 4: /* e.g. MOV Wd, #<imm32>. */
2465 1.1 christos {
2466 1.1 christos int imm32 = opnd->imm.value;
2467 1.1 christos snprintf (buf, size, "#0x%-20x\t// #%d", imm32, imm32);
2468 1.1 christos }
2469 1.1 christos break;
2470 1.1 christos case 8: /* e.g. MOV Xd, #<imm64>. */
2471 1.1 christos snprintf (buf, size, "#0x%-20" PRIx64 "\t// #%" PRIi64,
2472 1.1 christos opnd->imm.value, opnd->imm.value);
2473 1.1 christos break;
2474 1.1 christos default: assert (0);
2475 1.1 christos }
2476 1.1 christos break;
2477 1.1 christos
2478 1.1 christos case AARCH64_OPND_FPIMM0:
2479 1.1 christos snprintf (buf, size, "#0.0");
2480 1.1 christos break;
2481 1.1 christos
2482 1.1 christos case AARCH64_OPND_LIMM:
2483 1.1 christos case AARCH64_OPND_AIMM:
2484 1.1 christos case AARCH64_OPND_HALF:
2485 1.1 christos if (opnd->shifter.amount)
2486 1.1 christos snprintf (buf, size, "#0x%" PRIx64 ", lsl #%d", opnd->imm.value,
2487 1.1 christos opnd->shifter.amount);
2488 1.1 christos else
2489 1.1 christos snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
2490 1.1 christos break;
2491 1.1 christos
2492 1.1 christos case AARCH64_OPND_SIMD_IMM:
2493 1.1 christos case AARCH64_OPND_SIMD_IMM_SFT:
2494 1.1 christos if ((! opnd->shifter.amount && opnd->shifter.kind == AARCH64_MOD_LSL)
2495 1.1 christos || opnd->shifter.kind == AARCH64_MOD_NONE)
2496 1.1 christos snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
2497 1.1 christos else
2498 1.1 christos snprintf (buf, size, "#0x%" PRIx64 ", %s #%d", opnd->imm.value,
2499 1.1 christos aarch64_operand_modifiers[opnd->shifter.kind].name,
2500 1.1 christos opnd->shifter.amount);
2501 1.1 christos break;
2502 1.1 christos
2503 1.1 christos case AARCH64_OPND_FPIMM:
2504 1.1 christos case AARCH64_OPND_SIMD_FPIMM:
2505 1.1 christos switch (aarch64_get_qualifier_esize (opnds[0].qualifier))
2506 1.1 christos {
2507 1.1 christos case 4: /* e.g. FMOV <Vd>.4S, #<imm>. */
2508 1.1 christos {
2509 1.1 christos single_conv_t c;
2510 1.1 christos c.i = expand_fp_imm (0, opnd->imm.value);
2511 1.1 christos snprintf (buf, size, "#%.18e", c.f);
2512 1.1 christos }
2513 1.1 christos break;
2514 1.1 christos case 8: /* e.g. FMOV <Sd>, #<imm>. */
2515 1.1 christos {
2516 1.1 christos double_conv_t c;
2517 1.1 christos c.i = expand_fp_imm (1, opnd->imm.value);
2518 1.1 christos snprintf (buf, size, "#%.18e", c.d);
2519 1.1 christos }
2520 1.1 christos break;
2521 1.1 christos default: assert (0);
2522 1.1 christos }
2523 1.1 christos break;
2524 1.1 christos
2525 1.1 christos case AARCH64_OPND_CCMP_IMM:
2526 1.1 christos case AARCH64_OPND_NZCV:
2527 1.1 christos case AARCH64_OPND_EXCEPTION:
2528 1.1 christos case AARCH64_OPND_UIMM4:
2529 1.1 christos case AARCH64_OPND_UIMM7:
2530 1.1 christos if (optional_operand_p (opcode, idx) == TRUE
2531 1.1 christos && (opnd->imm.value ==
2532 1.1 christos (int64_t) get_optional_operand_default_value (opcode)))
2533 1.1 christos /* Omit the operand, e.g. DCPS1. */
2534 1.1 christos break;
2535 1.1 christos snprintf (buf, size, "#0x%x", (unsigned int)opnd->imm.value);
2536 1.1 christos break;
2537 1.1 christos
2538 1.1 christos case AARCH64_OPND_COND:
2539 1.1 christos case AARCH64_OPND_COND1:
2540 1.1 christos snprintf (buf, size, "%s", opnd->cond->names[0]);
2541 1.1 christos break;
2542 1.1 christos
2543 1.1 christos case AARCH64_OPND_ADDR_ADRP:
2544 1.1 christos addr = ((pc + AARCH64_PCREL_OFFSET) & ~(uint64_t)0xfff)
2545 1.1 christos + opnd->imm.value;
2546 1.1 christos if (pcrel_p)
2547 1.1 christos *pcrel_p = 1;
2548 1.1 christos if (address)
2549 1.1 christos *address = addr;
2550 1.1 christos /* This is not necessary during the disassembling, as print_address_func
2551 1.1 christos in the disassemble_info will take care of the printing. But some
2552 1.1 christos other callers may be still interested in getting the string in *STR,
2553 1.1 christos so here we do snprintf regardless. */
2554 1.1 christos snprintf (buf, size, "#0x%" PRIx64, addr);
2555 1.1 christos break;
2556 1.1 christos
2557 1.1 christos case AARCH64_OPND_ADDR_PCREL14:
2558 1.1 christos case AARCH64_OPND_ADDR_PCREL19:
2559 1.1 christos case AARCH64_OPND_ADDR_PCREL21:
2560 1.1 christos case AARCH64_OPND_ADDR_PCREL26:
2561 1.1 christos addr = pc + AARCH64_PCREL_OFFSET + opnd->imm.value;
2562 1.1 christos if (pcrel_p)
2563 1.1 christos *pcrel_p = 1;
2564 1.1 christos if (address)
2565 1.1 christos *address = addr;
2566 1.1 christos /* This is not necessary during the disassembling, as print_address_func
2567 1.1 christos in the disassemble_info will take care of the printing. But some
2568 1.1 christos other callers may be still interested in getting the string in *STR,
2569 1.1 christos so here we do snprintf regardless. */
2570 1.1 christos snprintf (buf, size, "#0x%" PRIx64, addr);
2571 1.1 christos break;
2572 1.1 christos
2573 1.1 christos case AARCH64_OPND_ADDR_SIMPLE:
2574 1.1 christos case AARCH64_OPND_SIMD_ADDR_SIMPLE:
2575 1.1 christos case AARCH64_OPND_SIMD_ADDR_POST:
2576 1.1 christos name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
2577 1.1 christos if (opnd->type == AARCH64_OPND_SIMD_ADDR_POST)
2578 1.1 christos {
2579 1.1 christos if (opnd->addr.offset.is_reg)
2580 1.1 christos snprintf (buf, size, "[%s], x%d", name, opnd->addr.offset.regno);
2581 1.1 christos else
2582 1.1 christos snprintf (buf, size, "[%s], #%d", name, opnd->addr.offset.imm);
2583 1.1 christos }
2584 1.1 christos else
2585 1.1 christos snprintf (buf, size, "[%s]", name);
2586 1.1 christos break;
2587 1.1 christos
2588 1.1 christos case AARCH64_OPND_ADDR_REGOFF:
2589 1.1 christos print_register_offset_address (buf, size, opnd);
2590 1.1 christos break;
2591 1.1 christos
2592 1.1 christos case AARCH64_OPND_ADDR_SIMM7:
2593 1.1 christos case AARCH64_OPND_ADDR_SIMM9:
2594 1.1 christos case AARCH64_OPND_ADDR_SIMM9_2:
2595 1.1 christos name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
2596 1.1 christos if (opnd->addr.writeback)
2597 1.1 christos {
2598 1.1 christos if (opnd->addr.preind)
2599 1.1 christos snprintf (buf, size, "[%s,#%d]!", name, opnd->addr.offset.imm);
2600 1.1 christos else
2601 1.1 christos snprintf (buf, size, "[%s],#%d", name, opnd->addr.offset.imm);
2602 1.1 christos }
2603 1.1 christos else
2604 1.1 christos {
2605 1.1 christos if (opnd->addr.offset.imm)
2606 1.1 christos snprintf (buf, size, "[%s,#%d]", name, opnd->addr.offset.imm);
2607 1.1 christos else
2608 1.1 christos snprintf (buf, size, "[%s]", name);
2609 1.1 christos }
2610 1.1 christos break;
2611 1.1 christos
2612 1.1 christos case AARCH64_OPND_ADDR_UIMM12:
2613 1.1 christos name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
2614 1.1 christos if (opnd->addr.offset.imm)
2615 1.1 christos snprintf (buf, size, "[%s,#%d]", name, opnd->addr.offset.imm);
2616 1.1 christos else
2617 1.1 christos snprintf (buf, size, "[%s]", name);
2618 1.1 christos break;
2619 1.1 christos
2620 1.1 christos case AARCH64_OPND_SYSREG:
2621 1.1 christos for (i = 0; aarch64_sys_regs[i].name; ++i)
2622 1.1 christos if (aarch64_sys_regs[i].value == opnd->sysreg
2623 1.1 christos && ! aarch64_sys_reg_deprecated_p (&aarch64_sys_regs[i]))
2624 1.1 christos break;
2625 1.1 christos if (aarch64_sys_regs[i].name)
2626 1.1 christos snprintf (buf, size, "%s", aarch64_sys_regs[i].name);
2627 1.1 christos else
2628 1.1 christos {
2629 1.1 christos /* Implementation defined system register. */
2630 1.1 christos unsigned int value = opnd->sysreg;
2631 1.1 christos snprintf (buf, size, "s%u_%u_c%u_c%u_%u", (value >> 14) & 0x3,
2632 1.1 christos (value >> 11) & 0x7, (value >> 7) & 0xf, (value >> 3) & 0xf,
2633 1.1 christos value & 0x7);
2634 1.1 christos }
2635 1.1 christos break;
2636 1.1 christos
2637 1.1 christos case AARCH64_OPND_PSTATEFIELD:
2638 1.1 christos for (i = 0; aarch64_pstatefields[i].name; ++i)
2639 1.1 christos if (aarch64_pstatefields[i].value == opnd->pstatefield)
2640 1.1 christos break;
2641 1.1 christos assert (aarch64_pstatefields[i].name);
2642 1.1 christos snprintf (buf, size, "%s", aarch64_pstatefields[i].name);
2643 1.1 christos break;
2644 1.1 christos
2645 1.1 christos case AARCH64_OPND_SYSREG_AT:
2646 1.1 christos case AARCH64_OPND_SYSREG_DC:
2647 1.1 christos case AARCH64_OPND_SYSREG_IC:
2648 1.1 christos case AARCH64_OPND_SYSREG_TLBI:
2649 1.1 christos snprintf (buf, size, "%s", opnd->sysins_op->template);
2650 1.1 christos break;
2651 1.1 christos
2652 1.1 christos case AARCH64_OPND_BARRIER:
2653 1.1 christos snprintf (buf, size, "%s", opnd->barrier->name);
2654 1.1 christos break;
2655 1.1 christos
2656 1.1 christos case AARCH64_OPND_BARRIER_ISB:
2657 1.1 christos /* Operand can be omitted, e.g. in DCPS1. */
2658 1.1 christos if (! optional_operand_p (opcode, idx)
2659 1.1 christos || (opnd->barrier->value
2660 1.1 christos != get_optional_operand_default_value (opcode)))
2661 1.1 christos snprintf (buf, size, "#0x%x", opnd->barrier->value);
2662 1.1 christos break;
2663 1.1 christos
2664 1.1 christos case AARCH64_OPND_PRFOP:
2665 1.1 christos if (opnd->prfop->name != NULL)
2666 1.1 christos snprintf (buf, size, "%s", opnd->prfop->name);
2667 1.1 christos else
2668 1.1 christos snprintf (buf, size, "#0x%02x", opnd->prfop->value);
2669 1.1 christos break;
2670 1.1 christos
2671 1.1 christos default:
2672 1.1 christos assert (0);
2673 1.1 christos }
2674 1.1 christos }
2675 1.1 christos
2676 1.1 christos #define CPENC(op0,op1,crn,crm,op2) \
2678 1.1 christos ((((op0) << 19) | ((op1) << 16) | ((crn) << 12) | ((crm) << 8) | ((op2) << 5)) >> 5)
2679 1.1 christos /* for 3.9.3 Instructions for Accessing Special Purpose Registers */
2680 1.1 christos #define CPEN_(op1,crm,op2) CPENC(3,(op1),4,(crm),(op2))
2681 1.1 christos /* for 3.9.10 System Instructions */
2682 1.1 christos #define CPENS(op1,crn,crm,op2) CPENC(1,(op1),(crn),(crm),(op2))
2683 1.1 christos
2684 1.1 christos #define C0 0
2685 1.1 christos #define C1 1
2686 1.1 christos #define C2 2
2687 1.1 christos #define C3 3
2688 1.1 christos #define C4 4
2689 1.1 christos #define C5 5
2690 1.1 christos #define C6 6
2691 1.1 christos #define C7 7
2692 1.1 christos #define C8 8
2693 1.1 christos #define C9 9
2694 1.1 christos #define C10 10
2695 1.1 christos #define C11 11
2696 1.1 christos #define C12 12
2697 1.1 christos #define C13 13
2698 1.1 christos #define C14 14
2699 1.1 christos #define C15 15
2700 1.1 christos
2701 1.1 christos #ifdef F_DEPRECATED
2702 1.1 christos #undef F_DEPRECATED
2703 1.1 christos #endif
2704 1.1 christos #define F_DEPRECATED 0x1 /* Deprecated system register. */
2705 1.1 christos
2706 1.1 christos /* TODO there are two more issues need to be resolved
2707 1.1 christos 1. handle read-only and write-only system registers
2708 1.1 christos 2. handle cpu-implementation-defined system registers. */
2709 1.1 christos const aarch64_sys_reg aarch64_sys_regs [] =
2710 1.1 christos {
2711 1.1 christos { "spsr_el1", CPEN_(0,C0,0), 0 }, /* = spsr_svc */
2712 1.1 christos { "elr_el1", CPEN_(0,C0,1), 0 },
2713 1.1 christos { "sp_el0", CPEN_(0,C1,0), 0 },
2714 1.1 christos { "spsel", CPEN_(0,C2,0), 0 },
2715 1.1 christos { "daif", CPEN_(3,C2,1), 0 },
2716 1.1 christos { "currentel", CPEN_(0,C2,2), 0 }, /* RO */
2717 1.1 christos { "nzcv", CPEN_(3,C2,0), 0 },
2718 1.1 christos { "fpcr", CPEN_(3,C4,0), 0 },
2719 1.1 christos { "fpsr", CPEN_(3,C4,1), 0 },
2720 1.1 christos { "dspsr_el0", CPEN_(3,C5,0), 0 },
2721 1.1 christos { "dlr_el0", CPEN_(3,C5,1), 0 },
2722 1.1 christos { "spsr_el2", CPEN_(4,C0,0), 0 }, /* = spsr_hyp */
2723 1.1 christos { "elr_el2", CPEN_(4,C0,1), 0 },
2724 1.1 christos { "sp_el1", CPEN_(4,C1,0), 0 },
2725 1.1 christos { "spsr_irq", CPEN_(4,C3,0), 0 },
2726 1.1 christos { "spsr_abt", CPEN_(4,C3,1), 0 },
2727 1.1 christos { "spsr_und", CPEN_(4,C3,2), 0 },
2728 1.1 christos { "spsr_fiq", CPEN_(4,C3,3), 0 },
2729 1.1 christos { "spsr_el3", CPEN_(6,C0,0), 0 },
2730 1.1 christos { "elr_el3", CPEN_(6,C0,1), 0 },
2731 1.1 christos { "sp_el2", CPEN_(6,C1,0), 0 },
2732 1.1 christos { "spsr_svc", CPEN_(0,C0,0), F_DEPRECATED }, /* = spsr_el1 */
2733 1.1 christos { "spsr_hyp", CPEN_(4,C0,0), F_DEPRECATED }, /* = spsr_el2 */
2734 1.1 christos { "midr_el1", CPENC(3,0,C0,C0,0), 0 }, /* RO */
2735 1.1 christos { "ctr_el0", CPENC(3,3,C0,C0,1), 0 }, /* RO */
2736 1.1 christos { "mpidr_el1", CPENC(3,0,C0,C0,5), 0 }, /* RO */
2737 1.1 christos { "revidr_el1", CPENC(3,0,C0,C0,6), 0 }, /* RO */
2738 1.1 christos { "aidr_el1", CPENC(3,1,C0,C0,7), 0 }, /* RO */
2739 1.1 christos { "dczid_el0", CPENC(3,3,C0,C0,7), 0 }, /* RO */
2740 1.1 christos { "id_dfr0_el1", CPENC(3,0,C0,C1,2), 0 }, /* RO */
2741 1.1 christos { "id_pfr0_el1", CPENC(3,0,C0,C1,0), 0 }, /* RO */
2742 1.1 christos { "id_pfr1_el1", CPENC(3,0,C0,C1,1), 0 }, /* RO */
2743 1.1 christos { "id_afr0_el1", CPENC(3,0,C0,C1,3), 0 }, /* RO */
2744 1.1 christos { "id_mmfr0_el1", CPENC(3,0,C0,C1,4), 0 }, /* RO */
2745 1.1 christos { "id_mmfr1_el1", CPENC(3,0,C0,C1,5), 0 }, /* RO */
2746 1.1 christos { "id_mmfr2_el1", CPENC(3,0,C0,C1,6), 0 }, /* RO */
2747 1.1 christos { "id_mmfr3_el1", CPENC(3,0,C0,C1,7), 0 }, /* RO */
2748 1.1 christos { "id_isar0_el1", CPENC(3,0,C0,C2,0), 0 }, /* RO */
2749 1.1 christos { "id_isar1_el1", CPENC(3,0,C0,C2,1), 0 }, /* RO */
2750 1.1 christos { "id_isar2_el1", CPENC(3,0,C0,C2,2), 0 }, /* RO */
2751 1.1 christos { "id_isar3_el1", CPENC(3,0,C0,C2,3), 0 }, /* RO */
2752 1.1 christos { "id_isar4_el1", CPENC(3,0,C0,C2,4), 0 }, /* RO */
2753 1.1 christos { "id_isar5_el1", CPENC(3,0,C0,C2,5), 0 }, /* RO */
2754 1.1 christos { "mvfr0_el1", CPENC(3,0,C0,C3,0), 0 }, /* RO */
2755 1.1 christos { "mvfr1_el1", CPENC(3,0,C0,C3,1), 0 }, /* RO */
2756 1.1 christos { "mvfr2_el1", CPENC(3,0,C0,C3,2), 0 }, /* RO */
2757 1.1 christos { "ccsidr_el1", CPENC(3,1,C0,C0,0), 0 }, /* RO */
2758 1.1 christos { "id_aa64pfr0_el1", CPENC(3,0,C0,C4,0), 0 }, /* RO */
2759 1.1 christos { "id_aa64pfr1_el1", CPENC(3,0,C0,C4,1), 0 }, /* RO */
2760 1.1 christos { "id_aa64dfr0_el1", CPENC(3,0,C0,C5,0), 0 }, /* RO */
2761 1.1 christos { "id_aa64dfr1_el1", CPENC(3,0,C0,C5,1), 0 }, /* RO */
2762 1.1 christos { "id_aa64isar0_el1", CPENC(3,0,C0,C6,0), 0 }, /* RO */
2763 1.1 christos { "id_aa64isar1_el1", CPENC(3,0,C0,C6,1), 0 }, /* RO */
2764 1.1 christos { "id_aa64mmfr0_el1", CPENC(3,0,C0,C7,0), 0 }, /* RO */
2765 1.1 christos { "id_aa64mmfr1_el1", CPENC(3,0,C0,C7,1), 0 }, /* RO */
2766 1.1 christos { "id_aa64afr0_el1", CPENC(3,0,C0,C5,4), 0 }, /* RO */
2767 1.1 christos { "id_aa64afr1_el1", CPENC(3,0,C0,C5,5), 0 }, /* RO */
2768 1.1 christos { "clidr_el1", CPENC(3,1,C0,C0,1), 0 }, /* RO */
2769 1.1 christos { "csselr_el1", CPENC(3,2,C0,C0,0), 0 }, /* RO */
2770 1.1 christos { "vpidr_el2", CPENC(3,4,C0,C0,0), 0 },
2771 1.1 christos { "vmpidr_el2", CPENC(3,4,C0,C0,5), 0 },
2772 1.1 christos { "sctlr_el1", CPENC(3,0,C1,C0,0), 0 },
2773 1.1 christos { "sctlr_el2", CPENC(3,4,C1,C0,0), 0 },
2774 1.1 christos { "sctlr_el3", CPENC(3,6,C1,C0,0), 0 },
2775 1.1 christos { "actlr_el1", CPENC(3,0,C1,C0,1), 0 },
2776 1.1 christos { "actlr_el2", CPENC(3,4,C1,C0,1), 0 },
2777 1.1 christos { "actlr_el3", CPENC(3,6,C1,C0,1), 0 },
2778 1.1 christos { "cpacr_el1", CPENC(3,0,C1,C0,2), 0 },
2779 1.1 christos { "cptr_el2", CPENC(3,4,C1,C1,2), 0 },
2780 1.1 christos { "cptr_el3", CPENC(3,6,C1,C1,2), 0 },
2781 1.1 christos { "scr_el3", CPENC(3,6,C1,C1,0), 0 },
2782 1.1 christos { "hcr_el2", CPENC(3,4,C1,C1,0), 0 },
2783 1.1 christos { "mdcr_el2", CPENC(3,4,C1,C1,1), 0 },
2784 1.1 christos { "mdcr_el3", CPENC(3,6,C1,C3,1), 0 },
2785 1.1 christos { "hstr_el2", CPENC(3,4,C1,C1,3), 0 },
2786 1.1 christos { "hacr_el2", CPENC(3,4,C1,C1,7), 0 },
2787 1.1 christos { "ttbr0_el1", CPENC(3,0,C2,C0,0), 0 },
2788 1.1 christos { "ttbr1_el1", CPENC(3,0,C2,C0,1), 0 },
2789 1.1 christos { "ttbr0_el2", CPENC(3,4,C2,C0,0), 0 },
2790 1.1 christos { "ttbr0_el3", CPENC(3,6,C2,C0,0), 0 },
2791 1.1 christos { "vttbr_el2", CPENC(3,4,C2,C1,0), 0 },
2792 1.1 christos { "tcr_el1", CPENC(3,0,C2,C0,2), 0 },
2793 1.1 christos { "tcr_el2", CPENC(3,4,C2,C0,2), 0 },
2794 1.1 christos { "tcr_el3", CPENC(3,6,C2,C0,2), 0 },
2795 1.1 christos { "vtcr_el2", CPENC(3,4,C2,C1,2), 0 },
2796 1.1 christos { "afsr0_el1", CPENC(3,0,C5,C1,0), 0 },
2797 1.1 christos { "afsr1_el1", CPENC(3,0,C5,C1,1), 0 },
2798 1.1 christos { "afsr0_el2", CPENC(3,4,C5,C1,0), 0 },
2799 1.1 christos { "afsr1_el2", CPENC(3,4,C5,C1,1), 0 },
2800 1.1 christos { "afsr0_el3", CPENC(3,6,C5,C1,0), 0 },
2801 1.1 christos { "afsr1_el3", CPENC(3,6,C5,C1,1), 0 },
2802 1.1 christos { "esr_el1", CPENC(3,0,C5,C2,0), 0 },
2803 1.1 christos { "esr_el2", CPENC(3,4,C5,C2,0), 0 },
2804 1.1 christos { "esr_el3", CPENC(3,6,C5,C2,0), 0 },
2805 1.1 christos { "fpexc32_el2", CPENC(3,4,C5,C3,0), 0 },
2806 1.1 christos { "far_el1", CPENC(3,0,C6,C0,0), 0 },
2807 1.1 christos { "far_el2", CPENC(3,4,C6,C0,0), 0 },
2808 1.1 christos { "far_el3", CPENC(3,6,C6,C0,0), 0 },
2809 1.1 christos { "hpfar_el2", CPENC(3,4,C6,C0,4), 0 },
2810 1.1 christos { "par_el1", CPENC(3,0,C7,C4,0), 0 },
2811 1.1 christos { "mair_el1", CPENC(3,0,C10,C2,0), 0 },
2812 1.1 christos { "mair_el2", CPENC(3,4,C10,C2,0), 0 },
2813 1.1 christos { "mair_el3", CPENC(3,6,C10,C2,0), 0 },
2814 1.1 christos { "amair_el1", CPENC(3,0,C10,C3,0), 0 },
2815 1.1 christos { "amair_el2", CPENC(3,4,C10,C3,0), 0 },
2816 1.1 christos { "amair_el3", CPENC(3,6,C10,C3,0), 0 },
2817 1.1 christos { "vbar_el1", CPENC(3,0,C12,C0,0), 0 },
2818 1.1 christos { "vbar_el2", CPENC(3,4,C12,C0,0), 0 },
2819 1.1 christos { "vbar_el3", CPENC(3,6,C12,C0,0), 0 },
2820 1.1 christos { "rvbar_el1", CPENC(3,0,C12,C0,1), 0 }, /* RO */
2821 1.1 christos { "rvbar_el2", CPENC(3,4,C12,C0,1), 0 }, /* RO */
2822 1.1 christos { "rvbar_el3", CPENC(3,6,C12,C0,1), 0 }, /* RO */
2823 1.1 christos { "rmr_el1", CPENC(3,0,C12,C0,2), 0 },
2824 1.1 christos { "rmr_el2", CPENC(3,4,C12,C0,2), 0 },
2825 1.1 christos { "rmr_el3", CPENC(3,6,C12,C0,2), 0 },
2826 1.1 christos { "isr_el1", CPENC(3,0,C12,C1,0), 0 }, /* RO */
2827 1.1 christos { "contextidr_el1", CPENC(3,0,C13,C0,1), 0 },
2828 1.1 christos { "tpidr_el0", CPENC(3,3,C13,C0,2), 0 },
2829 1.1 christos { "tpidrro_el0", CPENC(3,3,C13,C0,3), 0 }, /* RO */
2830 1.1 christos { "tpidr_el1", CPENC(3,0,C13,C0,4), 0 },
2831 1.1 christos { "tpidr_el2", CPENC(3,4,C13,C0,2), 0 },
2832 1.1 christos { "tpidr_el3", CPENC(3,6,C13,C0,2), 0 },
2833 1.1 christos { "teecr32_el1", CPENC(2,2,C0, C0,0), 0 }, /* See section 3.9.7.1 */
2834 1.1 christos { "cntfrq_el0", CPENC(3,3,C14,C0,0), 0 }, /* RO */
2835 1.1 christos { "cntpct_el0", CPENC(3,3,C14,C0,1), 0 }, /* RO */
2836 1.1 christos { "cntvct_el0", CPENC(3,3,C14,C0,2), 0 }, /* RO */
2837 1.1 christos { "cntvoff_el2", CPENC(3,4,C14,C0,3), 0 },
2838 1.1 christos { "cntkctl_el1", CPENC(3,0,C14,C1,0), 0 },
2839 1.1 christos { "cnthctl_el2", CPENC(3,4,C14,C1,0), 0 },
2840 1.1 christos { "cntp_tval_el0", CPENC(3,3,C14,C2,0), 0 },
2841 1.1 christos { "cntp_ctl_el0", CPENC(3,3,C14,C2,1), 0 },
2842 1.1 christos { "cntp_cval_el0", CPENC(3,3,C14,C2,2), 0 },
2843 1.1 christos { "cntv_tval_el0", CPENC(3,3,C14,C3,0), 0 },
2844 1.1 christos { "cntv_ctl_el0", CPENC(3,3,C14,C3,1), 0 },
2845 1.1 christos { "cntv_cval_el0", CPENC(3,3,C14,C3,2), 0 },
2846 1.1 christos { "cnthp_tval_el2", CPENC(3,4,C14,C2,0), 0 },
2847 1.1 christos { "cnthp_ctl_el2", CPENC(3,4,C14,C2,1), 0 },
2848 1.1 christos { "cnthp_cval_el2", CPENC(3,4,C14,C2,2), 0 },
2849 1.1 christos { "cntps_tval_el1", CPENC(3,7,C14,C2,0), 0 },
2850 1.1 christos { "cntps_ctl_el1", CPENC(3,7,C14,C2,1), 0 },
2851 1.1 christos { "cntps_cval_el1", CPENC(3,7,C14,C2,2), 0 },
2852 1.1 christos { "dacr32_el2", CPENC(3,4,C3,C0,0), 0 },
2853 1.1 christos { "ifsr32_el2", CPENC(3,4,C5,C0,1), 0 },
2854 1.1 christos { "teehbr32_el1", CPENC(2,2,C1,C0,0), 0 },
2855 1.1 christos { "sder32_el3", CPENC(3,6,C1,C1,1), 0 },
2856 1.1 christos { "mdscr_el1", CPENC(2,0,C0, C2, 2), 0 },
2857 1.1 christos { "mdccsr_el0", CPENC(2,3,C0, C1, 0), 0 }, /* r */
2858 1.1 christos { "mdccint_el1", CPENC(2,0,C0, C2, 0), 0 },
2859 1.1 christos { "dbgdtr_el0", CPENC(2,3,C0, C4, 0), 0 },
2860 1.1 christos { "dbgdtrrx_el0", CPENC(2,3,C0, C5, 0), 0 }, /* r */
2861 1.1 christos { "dbgdtrtx_el0", CPENC(2,3,C0, C5, 0), 0 }, /* w */
2862 1.1 christos { "osdtrrx_el1", CPENC(2,0,C0, C0, 2), 0 }, /* r */
2863 1.1 christos { "osdtrtx_el1", CPENC(2,0,C0, C3, 2), 0 }, /* w */
2864 1.1 christos { "oseccr_el1", CPENC(2,0,C0, C6, 2), 0 },
2865 1.1 christos { "dbgvcr32_el2", CPENC(2,4,C0, C7, 0), 0 },
2866 1.1 christos { "dbgbvr0_el1", CPENC(2,0,C0, C0, 4), 0 },
2867 1.1 christos { "dbgbvr1_el1", CPENC(2,0,C0, C1, 4), 0 },
2868 1.1 christos { "dbgbvr2_el1", CPENC(2,0,C0, C2, 4), 0 },
2869 1.1 christos { "dbgbvr3_el1", CPENC(2,0,C0, C3, 4), 0 },
2870 1.1 christos { "dbgbvr4_el1", CPENC(2,0,C0, C4, 4), 0 },
2871 1.1 christos { "dbgbvr5_el1", CPENC(2,0,C0, C5, 4), 0 },
2872 1.1 christos { "dbgbvr6_el1", CPENC(2,0,C0, C6, 4), 0 },
2873 1.1 christos { "dbgbvr7_el1", CPENC(2,0,C0, C7, 4), 0 },
2874 1.1 christos { "dbgbvr8_el1", CPENC(2,0,C0, C8, 4), 0 },
2875 1.1 christos { "dbgbvr9_el1", CPENC(2,0,C0, C9, 4), 0 },
2876 1.1 christos { "dbgbvr10_el1", CPENC(2,0,C0, C10,4), 0 },
2877 1.1 christos { "dbgbvr11_el1", CPENC(2,0,C0, C11,4), 0 },
2878 1.1 christos { "dbgbvr12_el1", CPENC(2,0,C0, C12,4), 0 },
2879 1.1 christos { "dbgbvr13_el1", CPENC(2,0,C0, C13,4), 0 },
2880 1.1 christos { "dbgbvr14_el1", CPENC(2,0,C0, C14,4), 0 },
2881 1.1 christos { "dbgbvr15_el1", CPENC(2,0,C0, C15,4), 0 },
2882 1.1 christos { "dbgbcr0_el1", CPENC(2,0,C0, C0, 5), 0 },
2883 1.1 christos { "dbgbcr1_el1", CPENC(2,0,C0, C1, 5), 0 },
2884 1.1 christos { "dbgbcr2_el1", CPENC(2,0,C0, C2, 5), 0 },
2885 1.1 christos { "dbgbcr3_el1", CPENC(2,0,C0, C3, 5), 0 },
2886 1.1 christos { "dbgbcr4_el1", CPENC(2,0,C0, C4, 5), 0 },
2887 1.1 christos { "dbgbcr5_el1", CPENC(2,0,C0, C5, 5), 0 },
2888 1.1 christos { "dbgbcr6_el1", CPENC(2,0,C0, C6, 5), 0 },
2889 1.1 christos { "dbgbcr7_el1", CPENC(2,0,C0, C7, 5), 0 },
2890 1.1 christos { "dbgbcr8_el1", CPENC(2,0,C0, C8, 5), 0 },
2891 1.1 christos { "dbgbcr9_el1", CPENC(2,0,C0, C9, 5), 0 },
2892 1.1 christos { "dbgbcr10_el1", CPENC(2,0,C0, C10,5), 0 },
2893 1.1 christos { "dbgbcr11_el1", CPENC(2,0,C0, C11,5), 0 },
2894 1.1 christos { "dbgbcr12_el1", CPENC(2,0,C0, C12,5), 0 },
2895 1.1 christos { "dbgbcr13_el1", CPENC(2,0,C0, C13,5), 0 },
2896 1.1 christos { "dbgbcr14_el1", CPENC(2,0,C0, C14,5), 0 },
2897 1.1 christos { "dbgbcr15_el1", CPENC(2,0,C0, C15,5), 0 },
2898 1.1 christos { "dbgwvr0_el1", CPENC(2,0,C0, C0, 6), 0 },
2899 1.1 christos { "dbgwvr1_el1", CPENC(2,0,C0, C1, 6), 0 },
2900 1.1 christos { "dbgwvr2_el1", CPENC(2,0,C0, C2, 6), 0 },
2901 1.1 christos { "dbgwvr3_el1", CPENC(2,0,C0, C3, 6), 0 },
2902 1.1 christos { "dbgwvr4_el1", CPENC(2,0,C0, C4, 6), 0 },
2903 1.1 christos { "dbgwvr5_el1", CPENC(2,0,C0, C5, 6), 0 },
2904 1.1 christos { "dbgwvr6_el1", CPENC(2,0,C0, C6, 6), 0 },
2905 1.1 christos { "dbgwvr7_el1", CPENC(2,0,C0, C7, 6), 0 },
2906 1.1 christos { "dbgwvr8_el1", CPENC(2,0,C0, C8, 6), 0 },
2907 1.1 christos { "dbgwvr9_el1", CPENC(2,0,C0, C9, 6), 0 },
2908 1.1 christos { "dbgwvr10_el1", CPENC(2,0,C0, C10,6), 0 },
2909 1.1 christos { "dbgwvr11_el1", CPENC(2,0,C0, C11,6), 0 },
2910 1.1 christos { "dbgwvr12_el1", CPENC(2,0,C0, C12,6), 0 },
2911 1.1 christos { "dbgwvr13_el1", CPENC(2,0,C0, C13,6), 0 },
2912 1.1 christos { "dbgwvr14_el1", CPENC(2,0,C0, C14,6), 0 },
2913 1.1 christos { "dbgwvr15_el1", CPENC(2,0,C0, C15,6), 0 },
2914 1.1 christos { "dbgwcr0_el1", CPENC(2,0,C0, C0, 7), 0 },
2915 1.1 christos { "dbgwcr1_el1", CPENC(2,0,C0, C1, 7), 0 },
2916 1.1 christos { "dbgwcr2_el1", CPENC(2,0,C0, C2, 7), 0 },
2917 1.1 christos { "dbgwcr3_el1", CPENC(2,0,C0, C3, 7), 0 },
2918 1.1 christos { "dbgwcr4_el1", CPENC(2,0,C0, C4, 7), 0 },
2919 1.1 christos { "dbgwcr5_el1", CPENC(2,0,C0, C5, 7), 0 },
2920 1.1 christos { "dbgwcr6_el1", CPENC(2,0,C0, C6, 7), 0 },
2921 1.1 christos { "dbgwcr7_el1", CPENC(2,0,C0, C7, 7), 0 },
2922 1.1 christos { "dbgwcr8_el1", CPENC(2,0,C0, C8, 7), 0 },
2923 1.1 christos { "dbgwcr9_el1", CPENC(2,0,C0, C9, 7), 0 },
2924 1.1 christos { "dbgwcr10_el1", CPENC(2,0,C0, C10,7), 0 },
2925 1.1 christos { "dbgwcr11_el1", CPENC(2,0,C0, C11,7), 0 },
2926 1.1 christos { "dbgwcr12_el1", CPENC(2,0,C0, C12,7), 0 },
2927 1.1 christos { "dbgwcr13_el1", CPENC(2,0,C0, C13,7), 0 },
2928 1.1 christos { "dbgwcr14_el1", CPENC(2,0,C0, C14,7), 0 },
2929 1.1 christos { "dbgwcr15_el1", CPENC(2,0,C0, C15,7), 0 },
2930 1.1 christos { "mdrar_el1", CPENC(2,0,C1, C0, 0), 0 }, /* r */
2931 1.1 christos { "oslar_el1", CPENC(2,0,C1, C0, 4), 0 }, /* w */
2932 1.1 christos { "oslsr_el1", CPENC(2,0,C1, C1, 4), 0 }, /* r */
2933 1.1 christos { "osdlr_el1", CPENC(2,0,C1, C3, 4), 0 },
2934 1.1 christos { "dbgprcr_el1", CPENC(2,0,C1, C4, 4), 0 },
2935 1.1 christos { "dbgclaimset_el1", CPENC(2,0,C7, C8, 6), 0 },
2936 1.1 christos { "dbgclaimclr_el1", CPENC(2,0,C7, C9, 6), 0 },
2937 1.1 christos { "dbgauthstatus_el1", CPENC(2,0,C7, C14,6), 0 }, /* r */
2938 1.1 christos
2939 1.1 christos { "pmcr_el0", CPENC(3,3,C9,C12, 0), 0 },
2940 1.1 christos { "pmcntenset_el0", CPENC(3,3,C9,C12, 1), 0 },
2941 1.1 christos { "pmcntenclr_el0", CPENC(3,3,C9,C12, 2), 0 },
2942 1.1 christos { "pmovsclr_el0", CPENC(3,3,C9,C12, 3), 0 },
2943 1.1 christos { "pmswinc_el0", CPENC(3,3,C9,C12, 4), 0 }, /* w */
2944 1.1 christos { "pmselr_el0", CPENC(3,3,C9,C12, 5), 0 },
2945 1.1 christos { "pmceid0_el0", CPENC(3,3,C9,C12, 6), 0 }, /* r */
2946 1.1 christos { "pmceid1_el0", CPENC(3,3,C9,C12, 7), 0 }, /* r */
2947 1.1 christos { "pmccntr_el0", CPENC(3,3,C9,C13, 0), 0 },
2948 1.1 christos { "pmxevtyper_el0", CPENC(3,3,C9,C13, 1), 0 },
2949 1.1 christos { "pmxevcntr_el0", CPENC(3,3,C9,C13, 2), 0 },
2950 1.1 christos { "pmuserenr_el0", CPENC(3,3,C9,C14, 0), 0 },
2951 1.1 christos { "pmintenset_el1", CPENC(3,0,C9,C14, 1), 0 },
2952 1.1 christos { "pmintenclr_el1", CPENC(3,0,C9,C14, 2), 0 },
2953 1.1 christos { "pmovsset_el0", CPENC(3,3,C9,C14, 3), 0 },
2954 1.1 christos { "pmevcntr0_el0", CPENC(3,3,C14,C8, 0), 0 },
2955 1.1 christos { "pmevcntr1_el0", CPENC(3,3,C14,C8, 1), 0 },
2956 1.1 christos { "pmevcntr2_el0", CPENC(3,3,C14,C8, 2), 0 },
2957 1.1 christos { "pmevcntr3_el0", CPENC(3,3,C14,C8, 3), 0 },
2958 1.1 christos { "pmevcntr4_el0", CPENC(3,3,C14,C8, 4), 0 },
2959 1.1 christos { "pmevcntr5_el0", CPENC(3,3,C14,C8, 5), 0 },
2960 1.1 christos { "pmevcntr6_el0", CPENC(3,3,C14,C8, 6), 0 },
2961 1.1 christos { "pmevcntr7_el0", CPENC(3,3,C14,C8, 7), 0 },
2962 1.1 christos { "pmevcntr8_el0", CPENC(3,3,C14,C9, 0), 0 },
2963 1.1 christos { "pmevcntr9_el0", CPENC(3,3,C14,C9, 1), 0 },
2964 1.1 christos { "pmevcntr10_el0", CPENC(3,3,C14,C9, 2), 0 },
2965 1.1 christos { "pmevcntr11_el0", CPENC(3,3,C14,C9, 3), 0 },
2966 1.1 christos { "pmevcntr12_el0", CPENC(3,3,C14,C9, 4), 0 },
2967 1.1 christos { "pmevcntr13_el0", CPENC(3,3,C14,C9, 5), 0 },
2968 1.1 christos { "pmevcntr14_el0", CPENC(3,3,C14,C9, 6), 0 },
2969 1.1 christos { "pmevcntr15_el0", CPENC(3,3,C14,C9, 7), 0 },
2970 1.1 christos { "pmevcntr16_el0", CPENC(3,3,C14,C10,0), 0 },
2971 1.1 christos { "pmevcntr17_el0", CPENC(3,3,C14,C10,1), 0 },
2972 1.1 christos { "pmevcntr18_el0", CPENC(3,3,C14,C10,2), 0 },
2973 1.1 christos { "pmevcntr19_el0", CPENC(3,3,C14,C10,3), 0 },
2974 1.1 christos { "pmevcntr20_el0", CPENC(3,3,C14,C10,4), 0 },
2975 1.1 christos { "pmevcntr21_el0", CPENC(3,3,C14,C10,5), 0 },
2976 1.1 christos { "pmevcntr22_el0", CPENC(3,3,C14,C10,6), 0 },
2977 1.1 christos { "pmevcntr23_el0", CPENC(3,3,C14,C10,7), 0 },
2978 1.1 christos { "pmevcntr24_el0", CPENC(3,3,C14,C11,0), 0 },
2979 1.1 christos { "pmevcntr25_el0", CPENC(3,3,C14,C11,1), 0 },
2980 1.1 christos { "pmevcntr26_el0", CPENC(3,3,C14,C11,2), 0 },
2981 1.1 christos { "pmevcntr27_el0", CPENC(3,3,C14,C11,3), 0 },
2982 1.1 christos { "pmevcntr28_el0", CPENC(3,3,C14,C11,4), 0 },
2983 1.1 christos { "pmevcntr29_el0", CPENC(3,3,C14,C11,5), 0 },
2984 1.1 christos { "pmevcntr30_el0", CPENC(3,3,C14,C11,6), 0 },
2985 1.1 christos { "pmevtyper0_el0", CPENC(3,3,C14,C12,0), 0 },
2986 1.1 christos { "pmevtyper1_el0", CPENC(3,3,C14,C12,1), 0 },
2987 1.1 christos { "pmevtyper2_el0", CPENC(3,3,C14,C12,2), 0 },
2988 1.1 christos { "pmevtyper3_el0", CPENC(3,3,C14,C12,3), 0 },
2989 1.1 christos { "pmevtyper4_el0", CPENC(3,3,C14,C12,4), 0 },
2990 1.1 christos { "pmevtyper5_el0", CPENC(3,3,C14,C12,5), 0 },
2991 1.1 christos { "pmevtyper6_el0", CPENC(3,3,C14,C12,6), 0 },
2992 1.1 christos { "pmevtyper7_el0", CPENC(3,3,C14,C12,7), 0 },
2993 1.1 christos { "pmevtyper8_el0", CPENC(3,3,C14,C13,0), 0 },
2994 1.1 christos { "pmevtyper9_el0", CPENC(3,3,C14,C13,1), 0 },
2995 1.1 christos { "pmevtyper10_el0", CPENC(3,3,C14,C13,2), 0 },
2996 1.1 christos { "pmevtyper11_el0", CPENC(3,3,C14,C13,3), 0 },
2997 1.1 christos { "pmevtyper12_el0", CPENC(3,3,C14,C13,4), 0 },
2998 1.1 christos { "pmevtyper13_el0", CPENC(3,3,C14,C13,5), 0 },
2999 1.1 christos { "pmevtyper14_el0", CPENC(3,3,C14,C13,6), 0 },
3000 1.1 christos { "pmevtyper15_el0", CPENC(3,3,C14,C13,7), 0 },
3001 1.1 christos { "pmevtyper16_el0", CPENC(3,3,C14,C14,0), 0 },
3002 1.1 christos { "pmevtyper17_el0", CPENC(3,3,C14,C14,1), 0 },
3003 1.1 christos { "pmevtyper18_el0", CPENC(3,3,C14,C14,2), 0 },
3004 1.1 christos { "pmevtyper19_el0", CPENC(3,3,C14,C14,3), 0 },
3005 1.1 christos { "pmevtyper20_el0", CPENC(3,3,C14,C14,4), 0 },
3006 1.1 christos { "pmevtyper21_el0", CPENC(3,3,C14,C14,5), 0 },
3007 1.1 christos { "pmevtyper22_el0", CPENC(3,3,C14,C14,6), 0 },
3008 1.1 christos { "pmevtyper23_el0", CPENC(3,3,C14,C14,7), 0 },
3009 1.1 christos { "pmevtyper24_el0", CPENC(3,3,C14,C15,0), 0 },
3010 1.1 christos { "pmevtyper25_el0", CPENC(3,3,C14,C15,1), 0 },
3011 1.1 christos { "pmevtyper26_el0", CPENC(3,3,C14,C15,2), 0 },
3012 1.1 christos { "pmevtyper27_el0", CPENC(3,3,C14,C15,3), 0 },
3013 1.1 christos { "pmevtyper28_el0", CPENC(3,3,C14,C15,4), 0 },
3014 1.1 christos { "pmevtyper29_el0", CPENC(3,3,C14,C15,5), 0 },
3015 1.1 christos { "pmevtyper30_el0", CPENC(3,3,C14,C15,6), 0 },
3016 1.1 christos { "pmccfiltr_el0", CPENC(3,3,C14,C15,7), 0 },
3017 1.1 christos { 0, CPENC(0,0,0,0,0), 0 },
3018 1.1 christos };
3019 1.1 christos
3020 1.1 christos bfd_boolean
3021 1.1 christos aarch64_sys_reg_deprecated_p (const aarch64_sys_reg *reg)
3022 1.1 christos {
3023 1.1 christos return (reg->flags & F_DEPRECATED) != 0;
3024 1.1 christos }
3025 1.1 christos
3026 1.1 christos const aarch64_sys_reg aarch64_pstatefields [] =
3027 1.1 christos {
3028 1.1 christos { "spsel", 0x05, 0 },
3029 1.1 christos { "daifset", 0x1e, 0 },
3030 1.1 christos { "daifclr", 0x1f, 0 },
3031 1.1 christos { 0, CPENC(0,0,0,0,0), 0 },
3032 1.1 christos };
3033 1.1 christos
3034 1.1 christos const aarch64_sys_ins_reg aarch64_sys_regs_ic[] =
3035 1.1 christos {
3036 1.1 christos { "ialluis", CPENS(0,C7,C1,0), 0 },
3037 1.1 christos { "iallu", CPENS(0,C7,C5,0), 0 },
3038 1.1 christos { "ivau", CPENS(3,C7,C5,1), 1 },
3039 1.1 christos { 0, CPENS(0,0,0,0), 0 }
3040 1.1 christos };
3041 1.1 christos
3042 1.1 christos const aarch64_sys_ins_reg aarch64_sys_regs_dc[] =
3043 1.1 christos {
3044 1.1 christos { "zva", CPENS(3,C7,C4,1), 1 },
3045 1.1 christos { "ivac", CPENS(0,C7,C6,1), 1 },
3046 1.1 christos { "isw", CPENS(0,C7,C6,2), 1 },
3047 1.1 christos { "cvac", CPENS(3,C7,C10,1), 1 },
3048 1.1 christos { "csw", CPENS(0,C7,C10,2), 1 },
3049 1.1 christos { "cvau", CPENS(3,C7,C11,1), 1 },
3050 1.1 christos { "civac", CPENS(3,C7,C14,1), 1 },
3051 1.1 christos { "cisw", CPENS(0,C7,C14,2), 1 },
3052 1.1 christos { 0, CPENS(0,0,0,0), 0 }
3053 1.1 christos };
3054 1.1 christos
3055 1.1 christos const aarch64_sys_ins_reg aarch64_sys_regs_at[] =
3056 1.1 christos {
3057 1.1 christos { "s1e1r", CPENS(0,C7,C8,0), 1 },
3058 1.1 christos { "s1e1w", CPENS(0,C7,C8,1), 1 },
3059 1.1 christos { "s1e0r", CPENS(0,C7,C8,2), 1 },
3060 1.1 christos { "s1e0w", CPENS(0,C7,C8,3), 1 },
3061 1.1 christos { "s12e1r", CPENS(4,C7,C8,4), 1 },
3062 1.1 christos { "s12e1w", CPENS(4,C7,C8,5), 1 },
3063 1.1 christos { "s12e0r", CPENS(4,C7,C8,6), 1 },
3064 1.1 christos { "s12e0w", CPENS(4,C7,C8,7), 1 },
3065 1.1 christos { "s1e2r", CPENS(4,C7,C8,0), 1 },
3066 1.1 christos { "s1e2w", CPENS(4,C7,C8,1), 1 },
3067 1.1 christos { "s1e3r", CPENS(6,C7,C8,0), 1 },
3068 1.1 christos { "s1e3w", CPENS(6,C7,C8,1), 1 },
3069 1.1 christos { 0, CPENS(0,0,0,0), 0 }
3070 1.1 christos };
3071 1.1 christos
3072 1.1 christos const aarch64_sys_ins_reg aarch64_sys_regs_tlbi[] =
3073 1.1 christos {
3074 1.1 christos { "vmalle1", CPENS(0,C8,C7,0), 0 },
3075 1.1 christos { "vae1", CPENS(0,C8,C7,1), 1 },
3076 1.1 christos { "aside1", CPENS(0,C8,C7,2), 1 },
3077 1.1 christos { "vaae1", CPENS(0,C8,C7,3), 1 },
3078 1.1 christos { "vmalle1is", CPENS(0,C8,C3,0), 0 },
3079 1.1 christos { "vae1is", CPENS(0,C8,C3,1), 1 },
3080 1.1 christos { "aside1is", CPENS(0,C8,C3,2), 1 },
3081 1.1 christos { "vaae1is", CPENS(0,C8,C3,3), 1 },
3082 1.1 christos { "ipas2e1is", CPENS(4,C8,C0,1), 1 },
3083 1.1 christos { "ipas2le1is",CPENS(4,C8,C0,5), 1 },
3084 1.1 christos { "ipas2e1", CPENS(4,C8,C4,1), 1 },
3085 1.1 christos { "ipas2le1", CPENS(4,C8,C4,5), 1 },
3086 1.1 christos { "vae2", CPENS(4,C8,C7,1), 1 },
3087 1.1 christos { "vae2is", CPENS(4,C8,C3,1), 1 },
3088 1.1 christos { "vmalls12e1",CPENS(4,C8,C7,6), 0 },
3089 1.1 christos { "vmalls12e1is",CPENS(4,C8,C3,6), 0 },
3090 1.1 christos { "vae3", CPENS(6,C8,C7,1), 1 },
3091 1.1 christos { "vae3is", CPENS(6,C8,C3,1), 1 },
3092 1.1 christos { "alle2", CPENS(4,C8,C7,0), 0 },
3093 1.1 christos { "alle2is", CPENS(4,C8,C3,0), 0 },
3094 1.1 christos { "alle1", CPENS(4,C8,C7,4), 0 },
3095 1.1 christos { "alle1is", CPENS(4,C8,C3,4), 0 },
3096 1.1 christos { "alle3", CPENS(6,C8,C7,0), 0 },
3097 1.1 christos { "alle3is", CPENS(6,C8,C3,0), 0 },
3098 1.1 christos { "vale1is", CPENS(0,C8,C3,5), 1 },
3099 1.1 christos { "vale2is", CPENS(4,C8,C3,5), 1 },
3100 1.1 christos { "vale3is", CPENS(6,C8,C3,5), 1 },
3101 1.1 christos { "vaale1is", CPENS(0,C8,C3,7), 1 },
3102 1.1 christos { "vale1", CPENS(0,C8,C7,5), 1 },
3103 1.1 christos { "vale2", CPENS(4,C8,C7,5), 1 },
3104 1.1 christos { "vale3", CPENS(6,C8,C7,5), 1 },
3105 1.1 christos { "vaale1", CPENS(0,C8,C7,7), 1 },
3106 1.1 christos { 0, CPENS(0,0,0,0), 0 }
3107 1.1 christos };
3108 1.1 christos
3109 1.1 christos #undef C0
3110 1.1 christos #undef C1
3111 1.1 christos #undef C2
3112 1.1 christos #undef C3
3113 1.1 christos #undef C4
3114 1.1 christos #undef C5
3115 1.1 christos #undef C6
3116 1.1 christos #undef C7
3117 1.1 christos #undef C8
3118 1.1 christos #undef C9
3119 1.1 christos #undef C10
3120 1.1 christos #undef C11
3121 1.1 christos #undef C12
3122 1.1 christos #undef C13
3123 1.1 christos #undef C14
3124 1.1 christos #undef C15
3125
3126 /* Include the opcode description table as well as the operand description
3127 table. */
3128 #include "aarch64-tbl.h"
3129