aarch64-dis.c revision 1.10 1 1.1 christos /* aarch64-dis.c -- AArch64 disassembler.
2 1.10 christos Copyright (C) 2009-2025 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.8 christos #include <stdint.h>
23 1.6 christos #include "disassemble.h"
24 1.1 christos #include "libiberty.h"
25 1.1 christos #include "opintl.h"
26 1.1 christos #include "aarch64-dis.h"
27 1.1 christos #include "elf-bfd.h"
28 1.9 christos #include "safe-ctype.h"
29 1.9 christos #include "obstack.h"
30 1.9 christos
31 1.9 christos #define obstack_chunk_alloc xmalloc
32 1.9 christos #define obstack_chunk_free free
33 1.1 christos
34 1.1 christos #define INSNLEN 4
35 1.1 christos
36 1.9 christos /* This character is used to encode style information within the output
37 1.9 christos buffers. See get_style_text and print_operands for more details. */
38 1.9 christos #define STYLE_MARKER_CHAR '\002'
39 1.9 christos
40 1.1 christos /* Cached mapping symbol state. */
41 1.1 christos enum map_type
42 1.1 christos {
43 1.1 christos MAP_INSN,
44 1.1 christos MAP_DATA
45 1.1 christos };
46 1.1 christos
47 1.8 christos static aarch64_feature_set arch_variant; /* See select_aarch64_variant. */
48 1.1 christos static enum map_type last_type;
49 1.1 christos static int last_mapping_sym = -1;
50 1.7 christos static bfd_vma last_stop_offset = 0;
51 1.1 christos static bfd_vma last_mapping_addr = 0;
52 1.1 christos
53 1.1 christos /* Other options */
54 1.1 christos static int no_aliases = 0; /* If set disassemble as most general inst. */
55 1.6 christos static int no_notes = 1; /* If set do not print disassemble notes in the
57 1.1 christos output as comments. */
58 1.7 christos
59 1.7 christos /* Currently active instruction sequence. */
60 1.7 christos static aarch64_instr_sequence insn_sequence;
61 1.1 christos
62 1.1 christos static void
63 1.1 christos set_default_aarch64_dis_options (struct disassemble_info *info ATTRIBUTE_UNUSED)
64 1.1 christos {
65 1.1 christos }
66 1.1 christos
67 1.1 christos static void
68 1.1 christos parse_aarch64_dis_option (const char *option, unsigned int len ATTRIBUTE_UNUSED)
69 1.1 christos {
70 1.8 christos /* Try to match options that are simple flags */
71 1.1 christos if (startswith (option, "no-aliases"))
72 1.1 christos {
73 1.1 christos no_aliases = 1;
74 1.1 christos return;
75 1.1 christos }
76 1.8 christos
77 1.1 christos if (startswith (option, "aliases"))
78 1.1 christos {
79 1.1 christos no_aliases = 0;
80 1.1 christos return;
81 1.1 christos }
82 1.8 christos
83 1.6 christos if (startswith (option, "no-notes"))
84 1.6 christos {
85 1.6 christos no_notes = 1;
86 1.6 christos return;
87 1.6 christos }
88 1.8 christos
89 1.6 christos if (startswith (option, "notes"))
90 1.6 christos {
91 1.6 christos no_notes = 0;
92 1.6 christos return;
93 1.6 christos }
94 1.1 christos
95 1.8 christos #ifdef DEBUG_AARCH64
96 1.1 christos if (startswith (option, "debug_dump"))
97 1.1 christos {
98 1.1 christos debug_dump = 1;
99 1.1 christos return;
100 1.1 christos }
101 1.1 christos #endif /* DEBUG_AARCH64 */
102 1.1 christos
103 1.6 christos /* Invalid option. */
104 1.1 christos opcodes_error_handler (_("unrecognised disassembler option: %s"), option);
105 1.1 christos }
106 1.1 christos
107 1.1 christos static void
108 1.1 christos parse_aarch64_dis_options (const char *options)
109 1.1 christos {
110 1.1 christos const char *option_end;
111 1.1 christos
112 1.1 christos if (options == NULL)
113 1.1 christos return;
114 1.1 christos
115 1.1 christos while (*options != '\0')
116 1.1 christos {
117 1.1 christos /* Skip empty options. */
118 1.1 christos if (*options == ',')
119 1.1 christos {
120 1.1 christos options++;
121 1.1 christos continue;
122 1.1 christos }
123 1.1 christos
124 1.1 christos /* We know that *options is neither NUL or a comma. */
125 1.1 christos option_end = options + 1;
126 1.1 christos while (*option_end != ',' && *option_end != '\0')
127 1.1 christos option_end++;
128 1.1 christos
129 1.1 christos parse_aarch64_dis_option (options, option_end - options);
130 1.1 christos
131 1.1 christos /* Go on to the next one. If option_end points to a comma, it
132 1.1 christos will be skipped above. */
133 1.1 christos options = option_end;
134 1.1 christos }
135 1.1 christos }
136 1.1 christos
137 1.1 christos /* Functions doing the instruction disassembling. */
139 1.1 christos
140 1.1 christos /* The unnamed arguments consist of the number of fields and information about
141 1.1 christos these fields where the VALUE will be extracted from CODE and returned.
142 1.1 christos MASK can be zero or the base mask of the opcode.
143 1.1 christos
144 1.1 christos N.B. the fields are required to be in such an order than the most signficant
145 1.3 christos field for VALUE comes the first, e.g. the <index> in
146 1.1 christos SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
147 1.1 christos is encoded in H:L:M in some cases, the fields H:L:M should be passed in
148 1.6 christos the order of H, L, M. */
149 1.1 christos
150 1.1 christos aarch64_insn
151 1.1 christos extract_fields (aarch64_insn code, aarch64_insn mask, ...)
152 1.1 christos {
153 1.1 christos uint32_t num;
154 1.1 christos const aarch64_field *field;
155 1.3 christos enum aarch64_field_kind kind;
156 1.1 christos va_list va;
157 1.1 christos
158 1.1 christos va_start (va, mask);
159 1.1 christos num = va_arg (va, uint32_t);
160 1.1 christos assert (num <= 5);
161 1.1 christos aarch64_insn value = 0x0;
162 1.1 christos while (num--)
163 1.1 christos {
164 1.1 christos kind = va_arg (va, enum aarch64_field_kind);
165 1.1 christos field = &fields[kind];
166 1.1 christos value <<= field->width;
167 1.8 christos value |= extract_field (kind, code, mask);
168 1.1 christos }
169 1.1 christos va_end (va);
170 1.1 christos return value;
171 1.9 christos }
172 1.9 christos
173 1.6 christos /* Extract the value of all fields in SELF->fields after START from
174 1.6 christos instruction CODE. The least significant bit comes from the final field. */
175 1.9 christos
176 1.9 christos static aarch64_insn
177 1.6 christos extract_all_fields_after (const aarch64_operand *self, unsigned int start,
178 1.6 christos aarch64_insn code)
179 1.6 christos {
180 1.6 christos aarch64_insn value;
181 1.6 christos unsigned int i;
182 1.6 christos enum aarch64_field_kind kind;
183 1.9 christos
184 1.9 christos value = 0;
185 1.6 christos for (i = start;
186 1.6 christos i < ARRAY_SIZE (self->fields) && self->fields[i] != FLD_NIL; ++i)
187 1.6 christos {
188 1.6 christos kind = self->fields[i];
189 1.6 christos value <<= fields[kind].width;
190 1.6 christos value |= extract_field (kind, code, 0);
191 1.6 christos }
192 1.6 christos return value;
193 1.9 christos }
194 1.9 christos
195 1.9 christos /* Extract the value of all fields in SELF->fields from instruction CODE.
196 1.9 christos The least significant bit comes from the final field. */
197 1.9 christos
198 1.9 christos static aarch64_insn
199 1.9 christos extract_all_fields (const aarch64_operand *self, aarch64_insn code)
200 1.9 christos {
201 1.9 christos return extract_all_fields_after (self, 0, code);
202 1.1 christos }
203 1.7 christos
204 1.1 christos /* Sign-extend bit I of VALUE. */
205 1.1 christos static inline uint64_t
206 1.7 christos sign_extend (aarch64_insn value, unsigned i)
207 1.3 christos {
208 1.1 christos uint64_t ret, sign;
209 1.7 christos
210 1.7 christos assert (i < 32);
211 1.7 christos ret = value;
212 1.1 christos sign = (uint64_t) 1 << i;
213 1.1 christos return ((ret & (sign + sign - 1)) ^ sign) - sign;
214 1.1 christos }
215 1.1 christos
216 1.1 christos /* N.B. the following inline helpfer functions create a dependency on the
217 1.1 christos order of operand qualifier enumerators. */
218 1.1 christos
219 1.1 christos /* Given VALUE, return qualifier for a general purpose register. */
220 1.1 christos static inline enum aarch64_opnd_qualifier
221 1.1 christos get_greg_qualifier_from_value (aarch64_insn value)
222 1.10 christos {
223 1.10 christos enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_W + value;
224 1.10 christos if (value <= 0x1
225 1.10 christos && aarch64_get_qualifier_standard_value (qualifier) == value)
226 1.1 christos return qualifier;
227 1.1 christos return AARCH64_OPND_QLF_ERR;
228 1.3 christos }
229 1.3 christos
230 1.3 christos /* Given VALUE, return qualifier for a vector register. This does not support
231 1.1 christos decoding instructions that accept the 2H vector type. */
232 1.1 christos
233 1.1 christos static inline enum aarch64_opnd_qualifier
234 1.1 christos get_vreg_qualifier_from_value (aarch64_insn value)
235 1.3 christos {
236 1.3 christos enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_V_8B + value;
237 1.3 christos
238 1.3 christos /* Instructions using vector type 2H should not call this function. Skip over
239 1.3 christos the 2H qualifier. */
240 1.3 christos if (qualifier >= AARCH64_OPND_QLF_V_2H)
241 1.10 christos qualifier += 1;
242 1.10 christos
243 1.10 christos if (value <= 0x8
244 1.10 christos && aarch64_get_qualifier_standard_value (qualifier) == value)
245 1.1 christos return qualifier;
246 1.1 christos return AARCH64_OPND_QLF_ERR;
247 1.1 christos }
248 1.1 christos
249 1.1 christos /* Given VALUE, return qualifier for an FP or AdvSIMD scalar register. */
250 1.1 christos static inline enum aarch64_opnd_qualifier
251 1.1 christos get_sreg_qualifier_from_value (aarch64_insn value)
252 1.3 christos {
253 1.10 christos enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_S_B + value;
254 1.10 christos
255 1.10 christos if (value <= 0x4
256 1.10 christos && aarch64_get_qualifier_standard_value (qualifier) == value)
257 1.1 christos return qualifier;
258 1.1 christos return AARCH64_OPND_QLF_ERR;
259 1.1 christos }
260 1.1 christos
261 1.1 christos /* Given the instruction in *INST which is probably half way through the
262 1.1 christos decoding and our caller wants to know the expected qualifier for operand
263 1.1 christos I. Return such a qualifier if we can establish it; otherwise return
264 1.1 christos AARCH64_OPND_QLF_NIL. */
265 1.1 christos
266 1.1 christos static aarch64_opnd_qualifier_t
267 1.1 christos get_expected_qualifier (const aarch64_inst *inst, int i)
268 1.1 christos {
269 1.10 christos aarch64_opnd_qualifier_seq_t qualifiers;
270 1.10 christos /* Should not be called if the qualifier is known. */
271 1.10 christos if (inst->operands[i].qualifier == AARCH64_OPND_QLF_NIL)
272 1.10 christos {
273 1.10 christos int invalid_count;
274 1.10 christos if (aarch64_find_best_match (inst, inst->opcode->qualifiers_list,
275 1.10 christos i, qualifiers, &invalid_count))
276 1.10 christos return qualifiers[i];
277 1.10 christos else
278 1.1 christos return AARCH64_OPND_QLF_NIL;
279 1.10 christos }
280 1.1 christos else
281 1.1 christos return AARCH64_OPND_QLF_ERR;
282 1.1 christos }
283 1.1 christos
284 1.8 christos /* Operand extractors. */
285 1.8 christos
286 1.8 christos bool
287 1.8 christos aarch64_ext_none (const aarch64_operand *self ATTRIBUTE_UNUSED,
288 1.8 christos aarch64_opnd_info *info ATTRIBUTE_UNUSED,
289 1.8 christos const aarch64_insn code ATTRIBUTE_UNUSED,
290 1.8 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
291 1.8 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
292 1.8 christos {
293 1.8 christos return true;
294 1.8 christos }
295 1.1 christos
296 1.1 christos bool
297 1.6 christos aarch64_ext_regno (const aarch64_operand *self, aarch64_opnd_info *info,
298 1.6 christos const aarch64_insn code,
299 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
300 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
301 1.9 christos {
302 1.8 christos info->reg.regno = (extract_field (self->fields[0], code, 0)
303 1.1 christos + get_operand_specific_data (self));
304 1.1 christos return true;
305 1.8 christos }
306 1.3 christos
307 1.3 christos bool
308 1.6 christos aarch64_ext_regno_pair (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info,
309 1.6 christos const aarch64_insn code ATTRIBUTE_UNUSED,
310 1.3 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
311 1.3 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
312 1.9 christos {
313 1.9 christos assert (info->idx == 1
314 1.9 christos || info->idx == 2
315 1.9 christos || info->idx == 3
316 1.9 christos || info->idx == 5);
317 1.9 christos
318 1.9 christos unsigned prev_regno = inst->operands[info->idx - 1].reg.regno;
319 1.8 christos info->reg.regno = (prev_regno == 0x1f) ? 0x1f
320 1.3 christos : prev_regno + 1;
321 1.3 christos return true;
322 1.1 christos }
323 1.8 christos
324 1.1 christos /* e.g. IC <ic_op>{, <Xt>}. */
325 1.1 christos bool
326 1.6 christos aarch64_ext_regrt_sysins (const aarch64_operand *self, aarch64_opnd_info *info,
327 1.6 christos const aarch64_insn code,
328 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
329 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
330 1.1 christos {
331 1.1 christos info->reg.regno = extract_field (self->fields[0], code, 0);
332 1.1 christos assert (info->idx == 1
333 1.1 christos && (aarch64_get_operand_class (inst->operands[0].type)
334 1.1 christos == AARCH64_OPND_CLASS_SYSTEM));
335 1.1 christos /* This will make the constraint checking happy and more importantly will
336 1.3 christos help the disassembler determine whether this operand is optional or
337 1.1 christos not. */
338 1.8 christos info->present = aarch64_sys_ins_reg_has_xt (inst->operands[0].sysins_op);
339 1.1 christos
340 1.1 christos return true;
341 1.1 christos }
342 1.8 christos
343 1.1 christos /* e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]. */
344 1.1 christos bool
345 1.6 christos aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info,
346 1.6 christos const aarch64_insn code,
347 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
348 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
349 1.1 christos {
350 1.1 christos /* regno */
351 1.1 christos info->reglane.regno = extract_field (self->fields[0], code,
352 1.3 christos inst->opcode->mask);
353 1.1 christos
354 1.1 christos /* Index and/or type. */
355 1.1 christos if (inst->opcode->iclass == asisdone
356 1.1 christos || inst->opcode->iclass == asimdins)
357 1.1 christos {
358 1.1 christos if (info->type == AARCH64_OPND_En
359 1.1 christos && inst->opcode->operands[0] == AARCH64_OPND_Ed)
360 1.1 christos {
361 1.1 christos unsigned shift;
362 1.9 christos /* index2 for e.g. INS <Vd>.<Ts>[<index1>], <Vn>.<Ts>[<index2>]. */
363 1.1 christos assert (info->idx == 1); /* Vn */
364 1.1 christos aarch64_insn value = extract_field (FLD_imm4_11, code, 0);
365 1.10 christos /* Depend on AARCH64_OPND_Ed to determine the qualifier. */
366 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx);
367 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR)
368 1.1 christos return 0;
369 1.1 christos shift = get_logsz (aarch64_get_qualifier_esize (info->qualifier));
370 1.1 christos info->reglane.index = value >> shift;
371 1.1 christos }
372 1.1 christos else
373 1.1 christos {
374 1.1 christos /* index and type for e.g. DUP <V><d>, <Vn>.<T>[<index>].
375 1.1 christos imm5<3:0> <V>
376 1.1 christos 0000 RESERVED
377 1.1 christos xxx1 B
378 1.1 christos xx10 H
379 1.1 christos x100 S
380 1.1 christos 1000 D */
381 1.1 christos int pos = -1;
382 1.1 christos aarch64_insn value = extract_field (FLD_imm5, code, 0);
383 1.1 christos while (++pos <= 3 && (value & 0x1) == 0)
384 1.8 christos value >>= 1;
385 1.1 christos if (pos > 3)
386 1.10 christos return false;
387 1.10 christos info->qualifier = get_sreg_qualifier_from_value (pos);
388 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR)
389 1.1 christos return 0;
390 1.1 christos info->reglane.index = (unsigned) (value >> 1);
391 1.6 christos }
392 1.6 christos }
393 1.6 christos else if (inst->opcode->iclass == dotproduct)
394 1.6 christos {
395 1.10 christos /* Need information in other operand(s) to help decoding. */
396 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx);
397 1.6 christos if (info->qualifier == AARCH64_OPND_QLF_ERR)
398 1.6 christos return 0;
399 1.6 christos switch (info->qualifier)
400 1.7 christos {
401 1.6 christos case AARCH64_OPND_QLF_S_4B:
402 1.6 christos case AARCH64_OPND_QLF_S_2H:
403 1.6 christos /* L:H */
404 1.6 christos info->reglane.index = extract_fields (code, 0, 2, FLD_H, FLD_L);
405 1.10 christos info->reglane.regno &= 0x1f;
406 1.10 christos break;
407 1.10 christos case AARCH64_OPND_QLF_S_2B:
408 1.10 christos /* h:l:m */
409 1.10 christos info->reglane.index = extract_fields (code, 0, 3, FLD_H, FLD_L,
410 1.10 christos FLD_M);
411 1.6 christos info->reglane.regno &= 0xf;
412 1.8 christos break;
413 1.6 christos default:
414 1.6 christos return false;
415 1.6 christos }
416 1.6 christos }
417 1.6 christos else if (inst->opcode->iclass == cryptosm3)
418 1.6 christos {
419 1.6 christos /* index for e.g. SM3TT2A <Vd>.4S, <Vn>.4S, <Vm>S[<imm2>]. */
420 1.1 christos info->reglane.index = extract_field (FLD_SM3_imm2, code, 0);
421 1.1 christos }
422 1.3 christos else
423 1.1 christos {
424 1.1 christos /* Index only for e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
425 1.1 christos or SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]. */
426 1.1 christos
427 1.10 christos /* Need information in other operand(s) to help decoding. */
428 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx);
429 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR)
430 1.1 christos return 0;
431 1.10 christos switch (info->qualifier)
432 1.10 christos {
433 1.10 christos case AARCH64_OPND_QLF_S_B:
434 1.10 christos /* H:imm3 */
435 1.10 christos info->reglane.index = extract_fields (code, 0, 2, FLD_H,
436 1.10 christos FLD_imm3_19);
437 1.10 christos info->reglane.regno &= 0x7;
438 1.1 christos break;
439 1.10 christos
440 1.6 christos case AARCH64_OPND_QLF_S_H:
441 1.6 christos case AARCH64_OPND_QLF_S_2B:
442 1.6 christos if (info->type == AARCH64_OPND_Em16)
443 1.6 christos {
444 1.6 christos /* h:l:m */
445 1.6 christos info->reglane.index = extract_fields (code, 0, 3, FLD_H, FLD_L,
446 1.6 christos FLD_M);
447 1.6 christos info->reglane.regno &= 0xf;
448 1.6 christos }
449 1.6 christos else
450 1.6 christos {
451 1.6 christos /* h:l */
452 1.1 christos info->reglane.index = extract_fields (code, 0, 2, FLD_H, FLD_L);
453 1.1 christos }
454 1.10 christos break;
455 1.1 christos case AARCH64_OPND_QLF_S_S:
456 1.1 christos case AARCH64_OPND_QLF_S_4B:
457 1.1 christos /* h:l */
458 1.1 christos info->reglane.index = extract_fields (code, 0, 2, FLD_H, FLD_L);
459 1.1 christos break;
460 1.1 christos case AARCH64_OPND_QLF_S_D:
461 1.1 christos /* H */
462 1.1 christos info->reglane.index = extract_field (FLD_H, code, 0);
463 1.8 christos break;
464 1.6 christos default:
465 1.6 christos return false;
466 1.6 christos }
467 1.6 christos
468 1.6 christos if (inst->opcode->op == OP_FCMLA_ELEM
469 1.6 christos && info->qualifier != AARCH64_OPND_QLF_S_H)
470 1.6 christos {
471 1.8 christos /* Complex operand takes two elements. */
472 1.6 christos if (info->reglane.index & 1)
473 1.1 christos return false;
474 1.1 christos info->reglane.index /= 2;
475 1.1 christos }
476 1.8 christos }
477 1.1 christos
478 1.1 christos return true;
479 1.8 christos }
480 1.1 christos
481 1.1 christos bool
482 1.6 christos aarch64_ext_reglist (const aarch64_operand *self, aarch64_opnd_info *info,
483 1.6 christos const aarch64_insn code,
484 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
485 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
486 1.1 christos {
487 1.1 christos /* R */
488 1.1 christos info->reglist.first_regno = extract_field (self->fields[0], code, 0);
489 1.9 christos /* len */
490 1.8 christos info->reglist.num_regs = extract_field (FLD_len, code, 0) + 1;
491 1.1 christos info->reglist.stride = 1;
492 1.1 christos return true;
493 1.1 christos }
494 1.8 christos
495 1.1 christos /* Decode Rt and opcode fields of Vt in AdvSIMD load/store instructions. */
496 1.1 christos bool
497 1.6 christos aarch64_ext_ldst_reglist (const aarch64_operand *self ATTRIBUTE_UNUSED,
498 1.6 christos aarch64_opnd_info *info, const aarch64_insn code,
499 1.1 christos const aarch64_inst *inst,
500 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
501 1.1 christos {
502 1.1 christos aarch64_insn value;
503 1.1 christos /* Number of elements in each structure to be loaded/stored. */
504 1.1 christos unsigned expected_num = get_opcode_dependent_value (inst->opcode);
505 1.1 christos
506 1.1 christos struct
507 1.1 christos {
508 1.1 christos unsigned is_reserved;
509 1.1 christos unsigned num_regs;
510 1.1 christos unsigned num_elements;
511 1.1 christos } data [] =
512 1.1 christos { {0, 4, 4},
513 1.1 christos {1, 4, 4},
514 1.1 christos {0, 4, 1},
515 1.1 christos {0, 4, 2},
516 1.1 christos {0, 3, 3},
517 1.1 christos {1, 3, 3},
518 1.1 christos {0, 3, 1},
519 1.1 christos {0, 1, 1},
520 1.1 christos {0, 2, 2},
521 1.1 christos {1, 2, 2},
522 1.1 christos {0, 2, 1},
523 1.1 christos };
524 1.1 christos
525 1.1 christos /* Rt */
526 1.1 christos info->reglist.first_regno = extract_field (FLD_Rt, code, 0);
527 1.6 christos /* opcode */
528 1.6 christos value = extract_field (FLD_opcode, code, 0);
529 1.8 christos /* PR 21595: Check for a bogus value. */
530 1.1 christos if (value >= ARRAY_SIZE (data))
531 1.8 christos return false;
532 1.1 christos if (expected_num != data[value].num_elements || data[value].is_reserved)
533 1.9 christos return false;
534 1.1 christos info->reglist.num_regs = data[value].num_regs;
535 1.8 christos info->reglist.stride = 1;
536 1.1 christos
537 1.1 christos return true;
538 1.1 christos }
539 1.1 christos
540 1.8 christos /* Decode Rt and S fields of Vt in AdvSIMD load single structure to all
541 1.1 christos lanes instructions. */
542 1.1 christos bool
543 1.6 christos aarch64_ext_ldst_reglist_r (const aarch64_operand *self ATTRIBUTE_UNUSED,
544 1.6 christos aarch64_opnd_info *info, const aarch64_insn code,
545 1.1 christos const aarch64_inst *inst,
546 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
547 1.1 christos {
548 1.1 christos aarch64_insn value;
549 1.1 christos
550 1.1 christos /* Rt */
551 1.1 christos info->reglist.first_regno = extract_field (FLD_Rt, code, 0);
552 1.1 christos /* S */
553 1.1 christos value = extract_field (FLD_S, code, 0);
554 1.1 christos
555 1.1 christos /* Number of registers is equal to the number of elements in
556 1.1 christos each structure to be loaded/stored. */
557 1.1 christos info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
558 1.1 christos assert (info->reglist.num_regs >= 1 && info->reglist.num_regs <= 4);
559 1.1 christos
560 1.1 christos /* Except when it is LD1R. */
561 1.1 christos if (info->reglist.num_regs == 1 && value == (aarch64_insn) 1)
562 1.9 christos info->reglist.num_regs = 2;
563 1.8 christos
564 1.1 christos info->reglist.stride = 1;
565 1.1 christos return true;
566 1.10 christos }
567 1.10 christos
568 1.10 christos /* Decode AdvSIMD vector register list for AdvSIMD lut instructions.
569 1.10 christos The number of of registers in the list is determined by the opcode
570 1.10 christos flag. */
571 1.10 christos bool
572 1.10 christos aarch64_ext_lut_reglist (const aarch64_operand *self, aarch64_opnd_info *info,
573 1.10 christos const aarch64_insn code,
574 1.10 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
575 1.10 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
576 1.10 christos {
577 1.10 christos info->reglist.first_regno = extract_field (self->fields[0], code, 0);
578 1.10 christos info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
579 1.10 christos info->reglist.stride = 1;
580 1.10 christos return true;
581 1.1 christos }
582 1.1 christos
583 1.8 christos /* Decode Q, opcode<2:1>, S, size and Rt fields of Vt in AdvSIMD
584 1.1 christos load/store single element instructions. */
585 1.1 christos bool
586 1.6 christos aarch64_ext_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED,
587 1.6 christos aarch64_opnd_info *info, const aarch64_insn code,
588 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
589 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
590 1.1 christos {
591 1.1 christos aarch64_field field = {0, 0};
592 1.1 christos aarch64_insn QSsize; /* fields Q:S:size. */
593 1.1 christos aarch64_insn opcodeh2; /* opcode<2:1> */
594 1.1 christos
595 1.1 christos /* Rt */
596 1.1 christos info->reglist.first_regno = extract_field (FLD_Rt, code, 0);
597 1.1 christos
598 1.1 christos /* Decode the index, opcode<2:1> and size. */
599 1.1 christos gen_sub_field (FLD_asisdlso_opcode, 1, 2, &field);
600 1.1 christos opcodeh2 = extract_field_2 (&field, code, 0);
601 1.1 christos QSsize = extract_fields (code, 0, 3, FLD_Q, FLD_S, FLD_vldst_size);
602 1.1 christos switch (opcodeh2)
603 1.1 christos {
604 1.1 christos case 0x0:
605 1.1 christos info->qualifier = AARCH64_OPND_QLF_S_B;
606 1.1 christos /* Index encoded in "Q:S:size". */
607 1.1 christos info->reglist.index = QSsize;
608 1.3 christos break;
609 1.3 christos case 0x1:
610 1.8 christos if (QSsize & 0x1)
611 1.1 christos /* UND. */
612 1.1 christos return false;
613 1.1 christos info->qualifier = AARCH64_OPND_QLF_S_H;
614 1.1 christos /* Index encoded in "Q:S:size<1>". */
615 1.1 christos info->reglist.index = QSsize >> 1;
616 1.3 christos break;
617 1.3 christos case 0x2:
618 1.8 christos if ((QSsize >> 1) & 0x1)
619 1.1 christos /* UND. */
620 1.1 christos return false;
621 1.1 christos if ((QSsize & 0x1) == 0)
622 1.1 christos {
623 1.1 christos info->qualifier = AARCH64_OPND_QLF_S_S;
624 1.1 christos /* Index encoded in "Q:S". */
625 1.1 christos info->reglist.index = QSsize >> 2;
626 1.1 christos }
627 1.3 christos else
628 1.3 christos {
629 1.8 christos if (extract_field (FLD_S, code, 0))
630 1.1 christos /* UND */
631 1.1 christos return false;
632 1.1 christos info->qualifier = AARCH64_OPND_QLF_S_D;
633 1.1 christos /* Index encoded in "Q". */
634 1.1 christos info->reglist.index = QSsize >> 3;
635 1.1 christos }
636 1.8 christos break;
637 1.1 christos default:
638 1.1 christos return false;
639 1.1 christos }
640 1.1 christos
641 1.9 christos info->reglist.has_index = 1;
642 1.1 christos info->reglist.num_regs = 0;
643 1.1 christos info->reglist.stride = 1;
644 1.1 christos /* Number of registers is equal to the number of elements in
645 1.1 christos each structure to be loaded/stored. */
646 1.1 christos info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
647 1.8 christos assert (info->reglist.num_regs >= 1 && info->reglist.num_regs <= 4);
648 1.1 christos
649 1.1 christos return true;
650 1.1 christos }
651 1.1 christos
652 1.1 christos /* Decode fields immh:immb and/or Q for e.g.
653 1.1 christos SSHR <Vd>.<T>, <Vn>.<T>, #<shift>
654 1.8 christos or SSHR <V><d>, <V><n>, #<shift>. */
655 1.1 christos
656 1.1 christos bool
657 1.6 christos aarch64_ext_advsimd_imm_shift (const aarch64_operand *self ATTRIBUTE_UNUSED,
658 1.6 christos aarch64_opnd_info *info, const aarch64_insn code,
659 1.1 christos const aarch64_inst *inst,
660 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
661 1.1 christos {
662 1.1 christos int pos;
663 1.1 christos aarch64_insn Q, imm, immh;
664 1.1 christos enum aarch64_insn_class iclass = inst->opcode->iclass;
665 1.1 christos
666 1.8 christos immh = extract_field (FLD_immh, code, 0);
667 1.1 christos if (immh == 0)
668 1.1 christos return false;
669 1.1 christos imm = extract_fields (code, 0, 2, FLD_immh, FLD_immb);
670 1.1 christos pos = 4;
671 1.1 christos /* Get highest set bit in immh. */
672 1.1 christos while (--pos >= 0 && (immh & 0x8) == 0)
673 1.1 christos immh <<= 1;
674 1.1 christos
675 1.1 christos assert ((iclass == asimdshf || iclass == asisdshf)
676 1.1 christos && (info->type == AARCH64_OPND_IMM_VLSR
677 1.1 christos || info->type == AARCH64_OPND_IMM_VLSL));
678 1.1 christos
679 1.1 christos if (iclass == asimdshf)
680 1.1 christos {
681 1.1 christos Q = extract_field (FLD_Q, code, 0);
682 1.1 christos /* immh Q <T>
683 1.1 christos 0000 x SEE AdvSIMD modified immediate
684 1.1 christos 0001 0 8B
685 1.1 christos 0001 1 16B
686 1.1 christos 001x 0 4H
687 1.1 christos 001x 1 8H
688 1.1 christos 01xx 0 2S
689 1.1 christos 01xx 1 4S
690 1.1 christos 1xxx 0 RESERVED
691 1.1 christos 1xxx 1 2D */
692 1.10 christos info->qualifier =
693 1.10 christos get_vreg_qualifier_from_value ((pos << 1) | (int) Q);
694 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR)
695 1.1 christos return false;
696 1.10 christos }
697 1.10 christos else
698 1.10 christos {
699 1.10 christos info->qualifier = get_sreg_qualifier_from_value (pos);
700 1.10 christos if (info->qualifier == AARCH64_OPND_QLF_ERR)
701 1.1 christos return 0;
702 1.1 christos }
703 1.1 christos
704 1.1 christos if (info->type == AARCH64_OPND_IMM_VLSR)
705 1.1 christos /* immh <shift>
706 1.1 christos 0000 SEE AdvSIMD modified immediate
707 1.1 christos 0001 (16-UInt(immh:immb))
708 1.1 christos 001x (32-UInt(immh:immb))
709 1.1 christos 01xx (64-UInt(immh:immb))
710 1.1 christos 1xxx (128-UInt(immh:immb)) */
711 1.1 christos info->imm.value = (16 << pos) - imm;
712 1.1 christos else
713 1.1 christos /* immh:immb
714 1.1 christos immh <shift>
715 1.1 christos 0000 SEE AdvSIMD modified immediate
716 1.1 christos 0001 (UInt(immh:immb)-8)
717 1.1 christos 001x (UInt(immh:immb)-16)
718 1.1 christos 01xx (UInt(immh:immb)-32)
719 1.1 christos 1xxx (UInt(immh:immb)-64) */
720 1.8 christos info->imm.value = imm - (8 << pos);
721 1.1 christos
722 1.1 christos return true;
723 1.1 christos }
724 1.8 christos
725 1.1 christos /* Decode shift immediate for e.g. sshr (imm). */
726 1.1 christos bool
727 1.6 christos aarch64_ext_shll_imm (const aarch64_operand *self ATTRIBUTE_UNUSED,
728 1.6 christos aarch64_opnd_info *info, const aarch64_insn code,
729 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
730 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
731 1.1 christos {
732 1.1 christos int64_t imm;
733 1.1 christos aarch64_insn val;
734 1.1 christos val = extract_field (FLD_size, code, 0);
735 1.1 christos switch (val)
736 1.1 christos {
737 1.1 christos case 0: imm = 8; break;
738 1.8 christos case 1: imm = 16; break;
739 1.1 christos case 2: imm = 32; break;
740 1.1 christos default: return false;
741 1.8 christos }
742 1.1 christos info->imm.value = imm;
743 1.1 christos return true;
744 1.1 christos }
745 1.1 christos
746 1.8 christos /* Decode imm for e.g. BFM <Wd>, <Wn>, #<immr>, #<imms>.
747 1.1 christos value in the field(s) will be extracted as unsigned immediate value. */
748 1.1 christos bool
749 1.8 christos aarch64_ext_imm (const aarch64_operand *self, aarch64_opnd_info *info,
750 1.6 christos const aarch64_insn code,
751 1.1 christos const aarch64_inst *inst,
752 1.7 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
753 1.1 christos {
754 1.6 christos uint64_t imm;
755 1.1 christos
756 1.1 christos imm = extract_all_fields (self, code);
757 1.1 christos
758 1.1 christos if (operand_need_sign_extension (self))
759 1.1 christos imm = sign_extend (imm, get_operand_fields_width (self) - 1);
760 1.1 christos
761 1.9 christos if (operand_need_shift_by_two (self))
762 1.9 christos imm <<= 2;
763 1.7 christos else if (operand_need_shift_by_three (self))
764 1.7 christos imm <<= 3;
765 1.1 christos else if (operand_need_shift_by_four (self))
766 1.1 christos imm <<= 4;
767 1.1 christos
768 1.1 christos if (info->type == AARCH64_OPND_ADDR_ADRP)
769 1.8 christos imm <<= 12;
770 1.8 christos
771 1.8 christos if (inst->operands[0].type == AARCH64_OPND_PSTATEFIELD
772 1.8 christos && inst->operands[0].sysreg.flags & F_IMM_IN_CRM)
773 1.1 christos imm &= PSTATE_DECODE_CRM_IMM (inst->operands[0].sysreg.flags);
774 1.8 christos
775 1.1 christos info->imm.value = imm;
776 1.1 christos return true;
777 1.1 christos }
778 1.8 christos
779 1.1 christos /* Decode imm and its shifter for e.g. MOVZ <Wd>, #<imm16>{, LSL #<shift>}. */
780 1.1 christos bool
781 1.6 christos aarch64_ext_imm_half (const aarch64_operand *self, aarch64_opnd_info *info,
782 1.6 christos const aarch64_insn code,
783 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
784 1.6 christos aarch64_operand_error *errors)
785 1.1 christos {
786 1.1 christos aarch64_ext_imm (self, info, code, inst, errors);
787 1.8 christos info->shifter.kind = AARCH64_MOD_LSL;
788 1.1 christos info->shifter.amount = extract_field (FLD_hw, code, 0) << 4;
789 1.1 christos return true;
790 1.1 christos }
791 1.1 christos
792 1.8 christos /* Decode cmode and "a:b:c:d:e:f:g:h" for e.g.
793 1.1 christos MOVI <Vd>.<T>, #<imm8> {, LSL #<amount>}. */
794 1.1 christos bool
795 1.1 christos aarch64_ext_advsimd_imm_modified (const aarch64_operand *self ATTRIBUTE_UNUSED,
796 1.6 christos aarch64_opnd_info *info,
797 1.6 christos const aarch64_insn code,
798 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
799 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
800 1.1 christos {
801 1.1 christos uint64_t imm;
802 1.1 christos enum aarch64_opnd_qualifier opnd0_qualifier = inst->operands[0].qualifier;
803 1.1 christos aarch64_field field = {0, 0};
804 1.1 christos
805 1.1 christos assert (info->idx == 1);
806 1.1 christos
807 1.1 christos if (info->type == AARCH64_OPND_SIMD_FPIMM)
808 1.1 christos info->imm.is_fp = 1;
809 1.1 christos
810 1.1 christos /* a:b:c:d:e:f:g:h */
811 1.1 christos imm = extract_fields (code, 0, 2, FLD_abc, FLD_defgh);
812 1.1 christos if (!info->imm.is_fp && aarch64_get_qualifier_esize (opnd0_qualifier) == 8)
813 1.1 christos {
814 1.1 christos /* Either MOVI <Dd>, #<imm>
815 1.1 christos or MOVI <Vd>.2D, #<imm>.
816 1.1 christos <imm> is a 64-bit immediate
817 1.1 christos 'aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh',
818 1.1 christos encoded in "a:b:c:d:e:f:g:h". */
819 1.1 christos int i;
820 1.1 christos unsigned abcdefgh = imm;
821 1.1 christos for (imm = 0ull, i = 0; i < 8; i++)
822 1.1 christos if (((abcdefgh >> i) & 0x1) != 0)
823 1.1 christos imm |= 0xffull << (8 * i);
824 1.1 christos }
825 1.1 christos info->imm.value = imm;
826 1.1 christos
827 1.10 christos /* cmode */
828 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx);
829 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR)
830 1.1 christos return 0;
831 1.1 christos switch (info->qualifier)
832 1.1 christos {
833 1.1 christos case AARCH64_OPND_QLF_NIL:
834 1.1 christos /* no shift */
835 1.1 christos info->shifter.kind = AARCH64_MOD_NONE;
836 1.1 christos return 1;
837 1.1 christos case AARCH64_OPND_QLF_LSL:
838 1.1 christos /* shift zeros */
839 1.1 christos info->shifter.kind = AARCH64_MOD_LSL;
840 1.1 christos switch (aarch64_get_qualifier_esize (opnd0_qualifier))
841 1.1 christos {
842 1.3 christos case 4: gen_sub_field (FLD_cmode, 1, 2, &field); break; /* per word */
843 1.8 christos case 2: gen_sub_field (FLD_cmode, 1, 1, &field); break; /* per half */
844 1.1 christos case 1: gen_sub_field (FLD_cmode, 1, 0, &field); break; /* per byte */
845 1.1 christos default: return false;
846 1.1 christos }
847 1.1 christos /* 00: 0; 01: 8; 10:16; 11:24. */
848 1.1 christos info->shifter.amount = extract_field_2 (&field, code, 0) << 3;
849 1.1 christos break;
850 1.1 christos case AARCH64_OPND_QLF_MSL:
851 1.1 christos /* shift ones */
852 1.1 christos info->shifter.kind = AARCH64_MOD_MSL;
853 1.1 christos gen_sub_field (FLD_cmode, 0, 1, &field); /* per word */
854 1.1 christos info->shifter.amount = extract_field_2 (&field, code, 0) ? 16 : 8;
855 1.8 christos break;
856 1.1 christos default:
857 1.1 christos return false;
858 1.8 christos }
859 1.6 christos
860 1.6 christos return true;
861 1.6 christos }
862 1.8 christos
863 1.6 christos /* Decode an 8-bit floating-point immediate. */
864 1.6 christos bool
865 1.6 christos aarch64_ext_fpimm (const aarch64_operand *self, aarch64_opnd_info *info,
866 1.6 christos const aarch64_insn code,
867 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
868 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
869 1.6 christos {
870 1.8 christos info->imm.value = extract_all_fields (self, code);
871 1.6 christos info->imm.is_fp = 1;
872 1.6 christos return true;
873 1.6 christos }
874 1.8 christos
875 1.6 christos /* Decode a 1-bit rotate immediate (#90 or #270). */
876 1.6 christos bool
877 1.6 christos aarch64_ext_imm_rotate1 (const aarch64_operand *self, aarch64_opnd_info *info,
878 1.6 christos const aarch64_insn code,
879 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
880 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
881 1.6 christos {
882 1.6 christos uint64_t rot = extract_field (self->fields[0], code, 0);
883 1.8 christos assert (rot < 2U);
884 1.6 christos info->imm.value = rot * 180 + 90;
885 1.6 christos return true;
886 1.6 christos }
887 1.8 christos
888 1.6 christos /* Decode a 2-bit rotate immediate (#0, #90, #180 or #270). */
889 1.6 christos bool
890 1.6 christos aarch64_ext_imm_rotate2 (const aarch64_operand *self, aarch64_opnd_info *info,
891 1.6 christos const aarch64_insn code,
892 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
893 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
894 1.6 christos {
895 1.6 christos uint64_t rot = extract_field (self->fields[0], code, 0);
896 1.8 christos assert (rot < 4U);
897 1.1 christos info->imm.value = rot * 90;
898 1.1 christos return true;
899 1.1 christos }
900 1.8 christos
901 1.1 christos /* Decode scale for e.g. SCVTF <Dd>, <Wn>, #<fbits>. */
902 1.1 christos bool
903 1.6 christos aarch64_ext_fbits (const aarch64_operand *self ATTRIBUTE_UNUSED,
904 1.6 christos aarch64_opnd_info *info, const aarch64_insn code,
905 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
906 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
907 1.8 christos {
908 1.1 christos info->imm.value = 64- extract_field (FLD_scale, code, 0);
909 1.1 christos return true;
910 1.1 christos }
911 1.1 christos
912 1.8 christos /* Decode arithmetic immediate for e.g.
913 1.1 christos SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}. */
914 1.1 christos bool
915 1.6 christos aarch64_ext_aimm (const aarch64_operand *self ATTRIBUTE_UNUSED,
916 1.6 christos aarch64_opnd_info *info, const aarch64_insn code,
917 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
918 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
919 1.1 christos {
920 1.1 christos aarch64_insn value;
921 1.1 christos
922 1.1 christos info->shifter.kind = AARCH64_MOD_LSL;
923 1.1 christos /* shift */
924 1.8 christos value = extract_field (FLD_shift, code, 0);
925 1.1 christos if (value >= 2)
926 1.1 christos return false;
927 1.1 christos info->shifter.amount = value ? 12 : 0;
928 1.1 christos /* imm12 (unsigned) */
929 1.8 christos info->imm.value = extract_field (FLD_imm12, code, 0);
930 1.1 christos
931 1.1 christos return true;
932 1.6 christos }
933 1.6 christos
934 1.6 christos /* Return true if VALUE is a valid logical immediate encoding, storing the
935 1.8 christos decoded value in *RESULT if so. ESIZE is the number of bytes in the
936 1.6 christos decoded immediate. */
937 1.1 christos static bool
938 1.1 christos decode_limm (uint32_t esize, aarch64_insn value, int64_t *result)
939 1.1 christos {
940 1.1 christos uint64_t imm, mask;
941 1.1 christos uint32_t N, R, S;
942 1.1 christos unsigned simd_size;
943 1.1 christos
944 1.1 christos /* value is N:immr:imms. */
945 1.1 christos S = value & 0x3f;
946 1.1 christos R = (value >> 6) & 0x3f;
947 1.1 christos N = (value >> 12) & 0x1;
948 1.3 christos
949 1.1 christos /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
950 1.1 christos (in other words, right rotated by R), then replicated. */
951 1.1 christos if (N != 0)
952 1.1 christos {
953 1.1 christos simd_size = 64;
954 1.1 christos mask = 0xffffffffffffffffull;
955 1.1 christos }
956 1.1 christos else
957 1.1 christos {
958 1.1 christos switch (S)
959 1.1 christos {
960 1.1 christos case 0x00 ... 0x1f: /* 0xxxxx */ simd_size = 32; break;
961 1.1 christos case 0x20 ... 0x2f: /* 10xxxx */ simd_size = 16; S &= 0xf; break;
962 1.1 christos case 0x30 ... 0x37: /* 110xxx */ simd_size = 8; S &= 0x7; break;
963 1.8 christos case 0x38 ... 0x3b: /* 1110xx */ simd_size = 4; S &= 0x3; break;
964 1.1 christos case 0x3c ... 0x3d: /* 11110x */ simd_size = 2; S &= 0x1; break;
965 1.1 christos default: return false;
966 1.1 christos }
967 1.1 christos mask = (1ull << simd_size) - 1;
968 1.1 christos /* Top bits are IGNORED. */
969 1.6 christos R &= simd_size - 1;
970 1.6 christos }
971 1.8 christos
972 1.6 christos if (simd_size > esize * 8)
973 1.1 christos return false;
974 1.1 christos
975 1.8 christos /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */
976 1.1 christos if (S == simd_size - 1)
977 1.1 christos return false;
978 1.1 christos /* S+1 consecutive bits to 1. */
979 1.1 christos /* NOTE: S can't be 63 due to detection above. */
980 1.1 christos imm = (1ull << (S + 1)) - 1;
981 1.1 christos /* Rotate to the left by simd_size - R. */
982 1.1 christos if (R != 0)
983 1.1 christos imm = ((imm << (simd_size - R)) & mask) | (imm >> R);
984 1.1 christos /* Replicate the value according to SIMD size. */
985 1.1 christos switch (simd_size)
986 1.6 christos {
987 1.1 christos case 2: imm = (imm << 2) | imm;
988 1.6 christos /* Fall through. */
989 1.1 christos case 4: imm = (imm << 4) | imm;
990 1.6 christos /* Fall through. */
991 1.1 christos case 8: imm = (imm << 8) | imm;
992 1.6 christos /* Fall through. */
993 1.1 christos case 16: imm = (imm << 16) | imm;
994 1.6 christos /* Fall through. */
995 1.1 christos case 32: imm = (imm << 32) | imm;
996 1.8 christos /* Fall through. */
997 1.1 christos case 64: break;
998 1.1 christos default: return 0;
999 1.6 christos }
1000 1.6 christos
1001 1.8 christos *result = imm & ~((uint64_t) -1 << (esize * 4) << (esize * 4));
1002 1.6 christos
1003 1.6 christos return true;
1004 1.6 christos }
1005 1.8 christos
1006 1.6 christos /* Decode a logical immediate for e.g. ORR <Wd|WSP>, <Wn>, #<imm>. */
1007 1.6 christos bool
1008 1.6 christos aarch64_ext_limm (const aarch64_operand *self,
1009 1.6 christos aarch64_opnd_info *info, const aarch64_insn code,
1010 1.6 christos const aarch64_inst *inst,
1011 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1012 1.6 christos {
1013 1.6 christos uint32_t esize;
1014 1.6 christos aarch64_insn value;
1015 1.6 christos
1016 1.6 christos value = extract_fields (code, 0, 3, self->fields[0], self->fields[1],
1017 1.6 christos self->fields[2]);
1018 1.6 christos esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier);
1019 1.1 christos return decode_limm (esize, value, &info->imm.value);
1020 1.6 christos }
1021 1.8 christos
1022 1.6 christos /* Decode a logical immediate for the BIC alias of AND (etc.). */
1023 1.6 christos bool
1024 1.6 christos aarch64_ext_inv_limm (const aarch64_operand *self,
1025 1.6 christos aarch64_opnd_info *info, const aarch64_insn code,
1026 1.6 christos const aarch64_inst *inst,
1027 1.6 christos aarch64_operand_error *errors)
1028 1.8 christos {
1029 1.6 christos if (!aarch64_ext_limm (self, info, code, inst, errors))
1030 1.8 christos return false;
1031 1.1 christos info->imm.value = ~info->imm.value;
1032 1.1 christos return true;
1033 1.1 christos }
1034 1.1 christos
1035 1.8 christos /* Decode Ft for e.g. STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]
1036 1.1 christos or LDP <Qt1>, <Qt2>, [<Xn|SP>], #<imm>. */
1037 1.1 christos bool
1038 1.6 christos aarch64_ext_ft (const aarch64_operand *self ATTRIBUTE_UNUSED,
1039 1.6 christos aarch64_opnd_info *info,
1040 1.1 christos const aarch64_insn code, const aarch64_inst *inst,
1041 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1042 1.1 christos {
1043 1.1 christos aarch64_insn value;
1044 1.1 christos
1045 1.1 christos /* Rt */
1046 1.1 christos info->reg.regno = extract_field (FLD_Rt, code, 0);
1047 1.1 christos
1048 1.1 christos /* size */
1049 1.1 christos value = extract_field (FLD_ldst_size, code, 0);
1050 1.1 christos if (inst->opcode->iclass == ldstpair_indexed
1051 1.1 christos || inst->opcode->iclass == ldstnapair_offs
1052 1.1 christos || inst->opcode->iclass == ldstpair_off
1053 1.1 christos || inst->opcode->iclass == loadlit)
1054 1.1 christos {
1055 1.1 christos enum aarch64_opnd_qualifier qualifier;
1056 1.1 christos switch (value)
1057 1.1 christos {
1058 1.1 christos case 0: qualifier = AARCH64_OPND_QLF_S_S; break;
1059 1.8 christos case 1: qualifier = AARCH64_OPND_QLF_S_D; break;
1060 1.1 christos case 2: qualifier = AARCH64_OPND_QLF_S_Q; break;
1061 1.1 christos default: return false;
1062 1.1 christos }
1063 1.1 christos info->qualifier = qualifier;
1064 1.1 christos }
1065 1.1 christos else
1066 1.1 christos {
1067 1.1 christos /* opc1:size */
1068 1.8 christos value = extract_fields (code, 0, 2, FLD_opc1, FLD_ldst_size);
1069 1.1 christos if (value > 0x4)
1070 1.10 christos return false;
1071 1.10 christos info->qualifier = get_sreg_qualifier_from_value (value);
1072 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR)
1073 1.1 christos return false;
1074 1.8 christos }
1075 1.1 christos
1076 1.1 christos return true;
1077 1.1 christos }
1078 1.8 christos
1079 1.1 christos /* Decode the address operand for e.g. STXRB <Ws>, <Wt>, [<Xn|SP>{,#0}]. */
1080 1.1 christos bool
1081 1.1 christos aarch64_ext_addr_simple (const aarch64_operand *self ATTRIBUTE_UNUSED,
1082 1.6 christos aarch64_opnd_info *info,
1083 1.6 christos aarch64_insn code,
1084 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1085 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1086 1.1 christos {
1087 1.8 christos /* Rn */
1088 1.6 christos info->addr.base_regno = extract_field (FLD_Rn, code, 0);
1089 1.6 christos return true;
1090 1.9 christos }
1091 1.9 christos
1092 1.9 christos /* Decode the address operand for rcpc3 instructions with optional load/store
1093 1.9 christos datasize offset, e.g. STILPP <Xs>, <Xt>, [<Xn|SP>{,#-16}]! and
1094 1.9 christos LIDAP <Xs>, <Xt>, [<Xn|SP>]{,#-16}. */
1095 1.9 christos bool
1096 1.9 christos aarch64_ext_rcpc3_addr_opt_offset (const aarch64_operand *self ATTRIBUTE_UNUSED,
1097 1.9 christos aarch64_opnd_info *info,
1098 1.9 christos aarch64_insn code,
1099 1.9 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1100 1.9 christos aarch64_operand_error *err ATTRIBUTE_UNUSED)
1101 1.9 christos {
1102 1.9 christos info->addr.base_regno = extract_field (FLD_Rn, code, 0);
1103 1.9 christos if (!extract_field (FLD_opc2, code, 0))
1104 1.9 christos {
1105 1.9 christos info->addr.writeback = 1;
1106 1.9 christos
1107 1.9 christos enum aarch64_opnd type;
1108 1.9 christos for (int i = 0; i < AARCH64_MAX_OPND_NUM; i++)
1109 1.9 christos {
1110 1.9 christos aarch64_opnd_info opnd = info[i];
1111 1.9 christos type = opnd.type;
1112 1.9 christos if (aarch64_operands[type].op_class == AARCH64_OPND_CLASS_ADDRESS)
1113 1.9 christos break;
1114 1.9 christos }
1115 1.9 christos
1116 1.9 christos assert (aarch64_operands[type].op_class == AARCH64_OPND_CLASS_ADDRESS);
1117 1.9 christos int offset = calc_ldst_datasize (inst->operands);
1118 1.9 christos
1119 1.9 christos switch (type)
1120 1.9 christos {
1121 1.9 christos case AARCH64_OPND_RCPC3_ADDR_OPT_PREIND_WB:
1122 1.9 christos case AARCH64_OPND_RCPC3_ADDR_PREIND_WB:
1123 1.9 christos info->addr.offset.imm = -offset;
1124 1.9 christos info->addr.preind = 1;
1125 1.9 christos break;
1126 1.9 christos case AARCH64_OPND_RCPC3_ADDR_OPT_POSTIND:
1127 1.9 christos case AARCH64_OPND_RCPC3_ADDR_POSTIND:
1128 1.9 christos info->addr.offset.imm = offset;
1129 1.9 christos info->addr.postind = 1;
1130 1.9 christos break;
1131 1.9 christos default:
1132 1.9 christos return false;
1133 1.9 christos }
1134 1.9 christos }
1135 1.9 christos return true;
1136 1.9 christos }
1137 1.9 christos
1138 1.9 christos bool
1139 1.9 christos aarch64_ext_rcpc3_addr_offset (const aarch64_operand *self ATTRIBUTE_UNUSED,
1140 1.9 christos aarch64_opnd_info *info,
1141 1.9 christos aarch64_insn code,
1142 1.9 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1143 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1144 1.10 christos {
1145 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx);
1146 1.9 christos if (info->qualifier == AARCH64_OPND_QLF_ERR)
1147 1.9 christos return 0;
1148 1.9 christos
1149 1.9 christos /* Rn */
1150 1.9 christos info->addr.base_regno = extract_field (self->fields[0], code, 0);
1151 1.9 christos
1152 1.9 christos /* simm9 */
1153 1.9 christos aarch64_insn imm = extract_fields (code, 0, 1, self->fields[1]);
1154 1.9 christos info->addr.offset.imm = sign_extend (imm, 8);
1155 1.9 christos return true;
1156 1.6 christos }
1157 1.6 christos
1158 1.8 christos /* Decode the address operand for e.g.
1159 1.6 christos stlur <Xt>, [<Xn|SP>{, <amount>}]. */
1160 1.6 christos bool
1161 1.6 christos aarch64_ext_addr_offset (const aarch64_operand *self ATTRIBUTE_UNUSED,
1162 1.6 christos aarch64_opnd_info *info,
1163 1.6 christos aarch64_insn code, const aarch64_inst *inst,
1164 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1165 1.10 christos {
1166 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx);
1167 1.6 christos if (info->qualifier == AARCH64_OPND_QLF_ERR)
1168 1.6 christos return 0;
1169 1.6 christos
1170 1.6 christos /* Rn */
1171 1.6 christos info->addr.base_regno = extract_field (self->fields[0], code, 0);
1172 1.6 christos
1173 1.6 christos /* simm9 */
1174 1.6 christos aarch64_insn imm = extract_fields (code, 0, 1, self->fields[1]);
1175 1.6 christos info->addr.offset.imm = sign_extend (imm, 8);
1176 1.6 christos if (extract_field (self->fields[2], code, 0) == 1) {
1177 1.6 christos info->addr.writeback = 1;
1178 1.8 christos info->addr.preind = 1;
1179 1.1 christos }
1180 1.1 christos return true;
1181 1.1 christos }
1182 1.1 christos
1183 1.8 christos /* Decode the address operand for e.g.
1184 1.1 christos STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
1185 1.1 christos bool
1186 1.6 christos aarch64_ext_addr_regoff (const aarch64_operand *self ATTRIBUTE_UNUSED,
1187 1.6 christos aarch64_opnd_info *info,
1188 1.1 christos aarch64_insn code, const aarch64_inst *inst,
1189 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1190 1.1 christos {
1191 1.1 christos aarch64_insn S, value;
1192 1.1 christos
1193 1.1 christos /* Rn */
1194 1.1 christos info->addr.base_regno = extract_field (FLD_Rn, code, 0);
1195 1.1 christos /* Rm */
1196 1.1 christos info->addr.offset.regno = extract_field (FLD_Rm, code, 0);
1197 1.1 christos /* option */
1198 1.8 christos value = extract_field (FLD_option, code, 0);
1199 1.1 christos info->shifter.kind =
1200 1.1 christos aarch64_get_operand_modifier_from_value (value, true /* extend_p */);
1201 1.1 christos /* Fix-up the shifter kind; although the table-driven approach is
1202 1.1 christos efficient, it is slightly inflexible, thus needing this fix-up. */
1203 1.1 christos if (info->shifter.kind == AARCH64_MOD_UXTX)
1204 1.1 christos info->shifter.kind = AARCH64_MOD_LSL;
1205 1.1 christos /* S */
1206 1.1 christos S = extract_field (FLD_S, code, 0);
1207 1.1 christos if (S == 0)
1208 1.1 christos {
1209 1.1 christos info->shifter.amount = 0;
1210 1.1 christos info->shifter.amount_present = 0;
1211 1.1 christos }
1212 1.1 christos else
1213 1.1 christos {
1214 1.1 christos int size;
1215 1.1 christos /* Need information in other operand(s) to help achieve the decoding
1216 1.10 christos from 'S' field. */
1217 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx);
1218 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR)
1219 1.1 christos return 0;
1220 1.1 christos /* Get the size of the data element that is accessed, which may be
1221 1.1 christos different from that of the source register size, e.g. in strb/ldrb. */
1222 1.1 christos size = aarch64_get_qualifier_esize (info->qualifier);
1223 1.1 christos info->shifter.amount = get_logsz (size);
1224 1.1 christos info->shifter.amount_present = 1;
1225 1.8 christos }
1226 1.1 christos
1227 1.1 christos return true;
1228 1.1 christos }
1229 1.8 christos
1230 1.1 christos /* Decode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>], #<simm>. */
1231 1.6 christos bool
1232 1.6 christos aarch64_ext_addr_simm (const aarch64_operand *self, aarch64_opnd_info *info,
1233 1.1 christos aarch64_insn code, const aarch64_inst *inst,
1234 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1235 1.1 christos {
1236 1.10 christos aarch64_insn imm;
1237 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx);
1238 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR)
1239 1.1 christos return 0;
1240 1.1 christos
1241 1.1 christos /* Rn */
1242 1.1 christos info->addr.base_regno = extract_field (FLD_Rn, code, 0);
1243 1.1 christos /* simm (imm9 or imm7) */
1244 1.7 christos imm = extract_field (self->fields[0], code, 0);
1245 1.7 christos info->addr.offset.imm = sign_extend (imm, fields[self->fields[0]].width - 1);
1246 1.1 christos if (self->fields[0] == FLD_imm7
1247 1.1 christos || info->qualifier == AARCH64_OPND_QLF_imm_tag)
1248 1.1 christos /* scaled immediate in ld/st pair instructions. */
1249 1.1 christos info->addr.offset.imm *= aarch64_get_qualifier_esize (info->qualifier);
1250 1.1 christos /* qualifier */
1251 1.1 christos if (inst->opcode->iclass == ldst_unscaled
1252 1.1 christos || inst->opcode->iclass == ldstnapair_offs
1253 1.1 christos || inst->opcode->iclass == ldstpair_off
1254 1.1 christos || inst->opcode->iclass == ldst_unpriv)
1255 1.1 christos info->addr.writeback = 0;
1256 1.1 christos else
1257 1.1 christos {
1258 1.1 christos /* pre/post- index */
1259 1.1 christos info->addr.writeback = 1;
1260 1.1 christos if (extract_field (self->fields[1], code, 0) == 1)
1261 1.1 christos info->addr.preind = 1;
1262 1.1 christos else
1263 1.1 christos info->addr.postind = 1;
1264 1.8 christos }
1265 1.1 christos
1266 1.1 christos return true;
1267 1.1 christos }
1268 1.8 christos
1269 1.1 christos /* Decode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>{, #<simm>}]. */
1270 1.1 christos bool
1271 1.6 christos aarch64_ext_addr_uimm12 (const aarch64_operand *self, aarch64_opnd_info *info,
1272 1.6 christos aarch64_insn code,
1273 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1274 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1275 1.1 christos {
1276 1.10 christos int shift;
1277 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx);
1278 1.1 christos if (info->qualifier == AARCH64_OPND_QLF_ERR)
1279 1.1 christos return 0;
1280 1.1 christos shift = get_logsz (aarch64_get_qualifier_esize (info->qualifier));
1281 1.1 christos /* Rn */
1282 1.1 christos info->addr.base_regno = extract_field (self->fields[0], code, 0);
1283 1.8 christos /* uimm12 */
1284 1.6 christos info->addr.offset.imm = extract_field (self->fields[1], code, 0) << shift;
1285 1.6 christos return true;
1286 1.6 christos }
1287 1.8 christos
1288 1.6 christos /* Decode the address operand for e.g. LDRAA <Xt>, [<Xn|SP>{, #<simm>}]. */
1289 1.6 christos bool
1290 1.6 christos aarch64_ext_addr_simm10 (const aarch64_operand *self, aarch64_opnd_info *info,
1291 1.6 christos aarch64_insn code,
1292 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1293 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1294 1.6 christos {
1295 1.6 christos aarch64_insn imm;
1296 1.10 christos
1297 1.10 christos info->qualifier = get_expected_qualifier (inst, info->idx);
1298 1.6 christos if (info->qualifier == AARCH64_OPND_QLF_ERR)
1299 1.6 christos return 0;
1300 1.6 christos /* Rn */
1301 1.6 christos info->addr.base_regno = extract_field (self->fields[0], code, 0);
1302 1.6 christos /* simm10 */
1303 1.6 christos imm = extract_fields (code, 0, 2, self->fields[1], self->fields[2]);
1304 1.6 christos info->addr.offset.imm = sign_extend (imm, 9) << 3;
1305 1.6 christos if (extract_field (self->fields[3], code, 0) == 1) {
1306 1.6 christos info->addr.writeback = 1;
1307 1.8 christos info->addr.preind = 1;
1308 1.1 christos }
1309 1.1 christos return true;
1310 1.1 christos }
1311 1.1 christos
1312 1.8 christos /* Decode the address operand for e.g.
1313 1.1 christos LD1 {<Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>}, [<Xn|SP>], <Xm|#<amount>>. */
1314 1.1 christos bool
1315 1.6 christos aarch64_ext_simd_addr_post (const aarch64_operand *self ATTRIBUTE_UNUSED,
1316 1.6 christos aarch64_opnd_info *info,
1317 1.1 christos aarch64_insn code, const aarch64_inst *inst,
1318 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1319 1.1 christos {
1320 1.1 christos /* The opcode dependent area stores the number of elements in
1321 1.1 christos each structure to be loaded/stored. */
1322 1.1 christos int is_ld1r = get_opcode_dependent_value (inst->opcode) == 1;
1323 1.1 christos
1324 1.1 christos /* Rn */
1325 1.1 christos info->addr.base_regno = extract_field (FLD_Rn, code, 0);
1326 1.1 christos /* Rm | #<amount> */
1327 1.1 christos info->addr.offset.regno = extract_field (FLD_Rm, code, 0);
1328 1.1 christos if (info->addr.offset.regno == 31)
1329 1.1 christos {
1330 1.1 christos if (inst->opcode->operands[0] == AARCH64_OPND_LVt_AL)
1331 1.1 christos /* Special handling of loading single structure to all lane. */
1332 1.1 christos info->addr.offset.imm = (is_ld1r ? 1
1333 1.1 christos : inst->operands[0].reglist.num_regs)
1334 1.1 christos * aarch64_get_qualifier_esize (inst->operands[0].qualifier);
1335 1.1 christos else
1336 1.1 christos info->addr.offset.imm = inst->operands[0].reglist.num_regs
1337 1.1 christos * aarch64_get_qualifier_esize (inst->operands[0].qualifier)
1338 1.1 christos * aarch64_get_qualifier_nelem (inst->operands[0].qualifier);
1339 1.1 christos }
1340 1.1 christos else
1341 1.1 christos info->addr.offset.is_reg = 1;
1342 1.8 christos info->addr.writeback = 1;
1343 1.1 christos
1344 1.1 christos return true;
1345 1.1 christos }
1346 1.8 christos
1347 1.1 christos /* Decode the condition operand for e.g. CSEL <Xd>, <Xn>, <Xm>, <cond>. */
1348 1.1 christos bool
1349 1.6 christos aarch64_ext_cond (const aarch64_operand *self ATTRIBUTE_UNUSED,
1350 1.6 christos aarch64_opnd_info *info,
1351 1.1 christos aarch64_insn code, const aarch64_inst *inst ATTRIBUTE_UNUSED,
1352 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1353 1.1 christos {
1354 1.1 christos aarch64_insn value;
1355 1.1 christos /* cond */
1356 1.8 christos value = extract_field (FLD_cond, code, 0);
1357 1.1 christos info->cond = get_cond_from_value (value);
1358 1.1 christos return true;
1359 1.1 christos }
1360 1.8 christos
1361 1.1 christos /* Decode the system register operand for e.g. MRS <Xt>, <systemreg>. */
1362 1.1 christos bool
1363 1.1 christos aarch64_ext_sysreg (const aarch64_operand *self ATTRIBUTE_UNUSED,
1364 1.6 christos aarch64_opnd_info *info,
1365 1.6 christos aarch64_insn code,
1366 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1367 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1368 1.6 christos {
1369 1.6 christos /* op0:op1:CRn:CRm:op2 */
1370 1.6 christos info->sysreg.value = extract_fields (code, 0, 5, FLD_op0, FLD_op1, FLD_CRn,
1371 1.6 christos FLD_CRm, FLD_op2);
1372 1.6 christos info->sysreg.flags = 0;
1373 1.6 christos
1374 1.6 christos /* If a system instruction, check which restrictions should be on the register
1375 1.6 christos value during decoding, these will be enforced then. */
1376 1.6 christos if (inst->opcode->iclass == ic_system)
1377 1.6 christos {
1378 1.6 christos /* Check to see if it's read-only, else check if it's write only.
1379 1.6 christos if it's both or unspecified don't care. */
1380 1.6 christos if ((inst->opcode->flags & (F_SYS_READ | F_SYS_WRITE)) == F_SYS_READ)
1381 1.6 christos info->sysreg.flags = F_REG_READ;
1382 1.6 christos else if ((inst->opcode->flags & (F_SYS_READ | F_SYS_WRITE))
1383 1.6 christos == F_SYS_WRITE)
1384 1.6 christos info->sysreg.flags = F_REG_WRITE;
1385 1.8 christos }
1386 1.1 christos
1387 1.1 christos return true;
1388 1.1 christos }
1389 1.8 christos
1390 1.1 christos /* Decode the PSTATE field operand for e.g. MSR <pstatefield>, #<imm>. */
1391 1.1 christos bool
1392 1.6 christos aarch64_ext_pstatefield (const aarch64_operand *self ATTRIBUTE_UNUSED,
1393 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
1394 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1395 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1396 1.8 christos {
1397 1.1 christos int i;
1398 1.1 christos aarch64_insn fld_crm = extract_field (FLD_CRm, code, 0);
1399 1.1 christos /* op1:op2 */
1400 1.1 christos info->pstatefield = extract_fields (code, 0, 2, FLD_op1, FLD_op2);
1401 1.8 christos for (i = 0; aarch64_pstatefields[i].name != NULL; ++i)
1402 1.8 christos if (aarch64_pstatefields[i].value == (aarch64_insn)info->pstatefield)
1403 1.8 christos {
1404 1.8 christos /* PSTATEFIELD name can be encoded partially in CRm[3:1]. */
1405 1.8 christos uint32_t flags = aarch64_pstatefields[i].flags;
1406 1.8 christos if ((flags & F_REG_IN_CRM)
1407 1.8 christos && ((fld_crm & 0xe) != PSTATE_DECODE_CRM (flags)))
1408 1.8 christos continue;
1409 1.8 christos info->sysreg.flags = flags;
1410 1.1 christos return true;
1411 1.8 christos }
1412 1.1 christos /* Reserved value in <pstatefield>. */
1413 1.1 christos return false;
1414 1.1 christos }
1415 1.8 christos
1416 1.1 christos /* Decode the system instruction op operand for e.g. AT <at_op>, <Xt>. */
1417 1.1 christos bool
1418 1.1 christos aarch64_ext_sysins_op (const aarch64_operand *self ATTRIBUTE_UNUSED,
1419 1.6 christos aarch64_opnd_info *info,
1420 1.6 christos aarch64_insn code,
1421 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1422 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1423 1.1 christos {
1424 1.1 christos int i;
1425 1.1 christos aarch64_insn value;
1426 1.1 christos const aarch64_sys_ins_reg *sysins_ops;
1427 1.1 christos /* op0:op1:CRn:CRm:op2 */
1428 1.1 christos value = extract_fields (code, 0, 5,
1429 1.1 christos FLD_op0, FLD_op1, FLD_CRn,
1430 1.1 christos FLD_CRm, FLD_op2);
1431 1.1 christos
1432 1.1 christos switch (info->type)
1433 1.1 christos {
1434 1.1 christos case AARCH64_OPND_SYSREG_AT: sysins_ops = aarch64_sys_regs_at; break;
1435 1.1 christos case AARCH64_OPND_SYSREG_DC: sysins_ops = aarch64_sys_regs_dc; break;
1436 1.9 christos case AARCH64_OPND_SYSREG_IC: sysins_ops = aarch64_sys_regs_ic; break;
1437 1.7 christos case AARCH64_OPND_SYSREG_TLBI: sysins_ops = aarch64_sys_regs_tlbi; break;
1438 1.7 christos case AARCH64_OPND_SYSREG_TLBIP: sysins_ops = aarch64_sys_regs_tlbi; break;
1439 1.7 christos case AARCH64_OPND_SYSREG_SR:
1440 1.7 christos sysins_ops = aarch64_sys_regs_sr;
1441 1.7 christos /* Let's remove op2 for rctx. Refer to comments in the definition of
1442 1.7 christos aarch64_sys_regs_sr[]. */
1443 1.8 christos value = value & ~(0x7);
1444 1.1 christos break;
1445 1.1 christos default: return false;
1446 1.3 christos }
1447 1.1 christos
1448 1.1 christos for (i = 0; sysins_ops[i].name != NULL; ++i)
1449 1.1 christos if (sysins_ops[i].value == value)
1450 1.1 christos {
1451 1.3 christos info->sysins_op = sysins_ops + i;
1452 1.1 christos DEBUG_TRACE ("%s found value: %x, has_xt: %d, i: %d.",
1453 1.3 christos info->sysins_op->name,
1454 1.8 christos (unsigned)info->sysins_op->value,
1455 1.1 christos aarch64_sys_ins_reg_has_xt (info->sysins_op), i);
1456 1.1 christos return true;
1457 1.8 christos }
1458 1.1 christos
1459 1.1 christos return false;
1460 1.1 christos }
1461 1.1 christos
1462 1.8 christos /* Decode the memory barrier option operand for e.g. DMB <option>|#<imm>. */
1463 1.1 christos
1464 1.1 christos bool
1465 1.1 christos aarch64_ext_barrier (const aarch64_operand *self ATTRIBUTE_UNUSED,
1466 1.6 christos aarch64_opnd_info *info,
1467 1.6 christos aarch64_insn code,
1468 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1469 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1470 1.1 christos {
1471 1.8 christos /* CRm */
1472 1.8 christos info->barrier = aarch64_barrier_options + extract_field (FLD_CRm, code, 0);
1473 1.8 christos return true;
1474 1.8 christos }
1475 1.8 christos
1476 1.8 christos /* Decode the memory barrier option operand for DSB <option>nXS|#<imm>. */
1477 1.8 christos
1478 1.8 christos bool
1479 1.8 christos aarch64_ext_barrier_dsb_nxs (const aarch64_operand *self ATTRIBUTE_UNUSED,
1480 1.8 christos aarch64_opnd_info *info,
1481 1.8 christos aarch64_insn code,
1482 1.8 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1483 1.8 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1484 1.8 christos {
1485 1.8 christos /* For the DSB nXS barrier variant immediate is encoded in 2-bit field. */
1486 1.8 christos aarch64_insn field = extract_field (FLD_CRm_dsb_nxs, code, 0);
1487 1.1 christos info->barrier = aarch64_barrier_dsb_nxs_options + field;
1488 1.1 christos return true;
1489 1.1 christos }
1490 1.1 christos
1491 1.1 christos /* Decode the prefetch operation option operand for e.g.
1492 1.8 christos PRFM <prfop>, [<Xn|SP>{, #<pimm>}]. */
1493 1.1 christos
1494 1.1 christos bool
1495 1.6 christos aarch64_ext_prfop (const aarch64_operand *self ATTRIBUTE_UNUSED,
1496 1.6 christos aarch64_opnd_info *info,
1497 1.1 christos aarch64_insn code, const aarch64_inst *inst ATTRIBUTE_UNUSED,
1498 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1499 1.1 christos {
1500 1.8 christos /* prfop in Rt */
1501 1.1 christos info->prfop = aarch64_prfops + extract_field (FLD_Rt, code, 0);
1502 1.1 christos return true;
1503 1.3 christos }
1504 1.3 christos
1505 1.3 christos /* Decode the hint number for an alias taking an operand. Set info->hint_option
1506 1.8 christos to the matching name/value pair in aarch64_hint_options. */
1507 1.3 christos
1508 1.3 christos bool
1509 1.3 christos aarch64_ext_hint (const aarch64_operand *self ATTRIBUTE_UNUSED,
1510 1.6 christos aarch64_opnd_info *info,
1511 1.6 christos aarch64_insn code,
1512 1.3 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1513 1.3 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1514 1.3 christos {
1515 1.3 christos /* CRm:op2. */
1516 1.3 christos unsigned hint_number;
1517 1.3 christos int i;
1518 1.3 christos
1519 1.3 christos hint_number = extract_fields (code, 0, 2, FLD_CRm, FLD_op2);
1520 1.3 christos
1521 1.7 christos for (i = 0; aarch64_hint_options[i].name != NULL; i++)
1522 1.3 christos {
1523 1.3 christos if (hint_number == HINT_VAL (aarch64_hint_options[i].value))
1524 1.8 christos {
1525 1.3 christos info->hint_option = &(aarch64_hint_options[i]);
1526 1.3 christos return true;
1527 1.3 christos }
1528 1.8 christos }
1529 1.3 christos
1530 1.3 christos return false;
1531 1.1 christos }
1532 1.1 christos
1533 1.8 christos /* Decode the extended register operand for e.g.
1534 1.1 christos STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
1535 1.1 christos bool
1536 1.1 christos aarch64_ext_reg_extended (const aarch64_operand *self ATTRIBUTE_UNUSED,
1537 1.6 christos aarch64_opnd_info *info,
1538 1.6 christos aarch64_insn code,
1539 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1540 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1541 1.1 christos {
1542 1.1 christos aarch64_insn value;
1543 1.1 christos
1544 1.1 christos /* Rm */
1545 1.1 christos info->reg.regno = extract_field (FLD_Rm, code, 0);
1546 1.1 christos /* option */
1547 1.8 christos value = extract_field (FLD_option, code, 0);
1548 1.1 christos info->shifter.kind =
1549 1.9 christos aarch64_get_operand_modifier_from_value (value, true /* extend_p */);
1550 1.1 christos /* imm3 */
1551 1.1 christos info->shifter.amount = extract_field (FLD_imm3_10, code, 0);
1552 1.1 christos
1553 1.1 christos /* This makes the constraint checking happy. */
1554 1.1 christos info->shifter.operator_present = 1;
1555 1.1 christos
1556 1.1 christos /* Assume inst->operands[0].qualifier has been resolved. */
1557 1.1 christos assert (inst->operands[0].qualifier != AARCH64_OPND_QLF_NIL);
1558 1.1 christos info->qualifier = AARCH64_OPND_QLF_W;
1559 1.1 christos if (inst->operands[0].qualifier == AARCH64_OPND_QLF_X
1560 1.1 christos && (info->shifter.kind == AARCH64_MOD_UXTX
1561 1.1 christos || info->shifter.kind == AARCH64_MOD_SXTX))
1562 1.8 christos info->qualifier = AARCH64_OPND_QLF_X;
1563 1.1 christos
1564 1.1 christos return true;
1565 1.1 christos }
1566 1.1 christos
1567 1.8 christos /* Decode the shifted register operand for e.g.
1568 1.1 christos SUBS <Xd>, <Xn>, <Xm> {, <shift> #<amount>}. */
1569 1.1 christos bool
1570 1.1 christos aarch64_ext_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED,
1571 1.6 christos aarch64_opnd_info *info,
1572 1.6 christos aarch64_insn code,
1573 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1574 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1575 1.1 christos {
1576 1.1 christos aarch64_insn value;
1577 1.1 christos
1578 1.1 christos /* Rm */
1579 1.1 christos info->reg.regno = extract_field (FLD_Rm, code, 0);
1580 1.1 christos /* shift */
1581 1.8 christos value = extract_field (FLD_shift, code, 0);
1582 1.1 christos info->shifter.kind =
1583 1.1 christos aarch64_get_operand_modifier_from_value (value, false /* extend_p */);
1584 1.1 christos if (info->shifter.kind == AARCH64_MOD_ROR
1585 1.1 christos && inst->opcode->iclass != log_shift)
1586 1.8 christos /* ROR is not available for the shifted register operand in arithmetic
1587 1.1 christos instructions. */
1588 1.9 christos return false;
1589 1.1 christos /* imm6 */
1590 1.1 christos info->shifter.amount = extract_field (FLD_imm6_10, code, 0);
1591 1.1 christos
1592 1.1 christos /* This makes the constraint checking happy. */
1593 1.8 christos info->shifter.operator_present = 1;
1594 1.6 christos
1595 1.6 christos return true;
1596 1.10 christos }
1597 1.10 christos
1598 1.10 christos /* Decode the LSL-shifted register operand for e.g.
1599 1.10 christos ADDPT <Xd|SP>, <Xn|SP>, <Xm>{, LSL #<amount>}. */
1600 1.10 christos bool
1601 1.10 christos aarch64_ext_reg_lsl_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED,
1602 1.10 christos aarch64_opnd_info *info,
1603 1.10 christos aarch64_insn code,
1604 1.10 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1605 1.10 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1606 1.10 christos {
1607 1.10 christos /* Rm */
1608 1.10 christos info->reg.regno = extract_field (FLD_Rm, code, 0);
1609 1.10 christos /* imm3 */
1610 1.10 christos info->shifter.kind = AARCH64_MOD_LSL;
1611 1.10 christos info->shifter.amount = extract_field (FLD_imm3_10, code, 0);
1612 1.10 christos return true;
1613 1.6 christos }
1614 1.6 christos
1615 1.6 christos /* Decode an SVE address [<base>, #<offset>*<factor>, MUL VL],
1616 1.6 christos where <offset> is given by the OFFSET parameter and where <factor> is
1617 1.8 christos 1 plus SELF's operand-dependent value. fields[0] specifies the field
1618 1.6 christos that holds <base>. */
1619 1.6 christos static bool
1620 1.6 christos aarch64_ext_sve_addr_reg_mul_vl (const aarch64_operand *self,
1621 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
1622 1.6 christos int64_t offset)
1623 1.6 christos {
1624 1.8 christos info->addr.base_regno = extract_field (self->fields[0], code, 0);
1625 1.8 christos info->addr.offset.imm = offset * (1 + get_operand_specific_data (self));
1626 1.8 christos info->addr.offset.is_reg = false;
1627 1.6 christos info->addr.writeback = false;
1628 1.6 christos info->addr.preind = true;
1629 1.6 christos if (offset != 0)
1630 1.6 christos info->shifter.kind = AARCH64_MOD_MUL_VL;
1631 1.8 christos info->shifter.amount = 1;
1632 1.8 christos info->shifter.operator_present = (info->addr.offset.imm != 0);
1633 1.6 christos info->shifter.amount_present = false;
1634 1.6 christos return true;
1635 1.6 christos }
1636 1.6 christos
1637 1.6 christos /* Decode an SVE address [<base>, #<simm4>*<factor>, MUL VL],
1638 1.6 christos where <simm4> is a 4-bit signed value and where <factor> is 1 plus
1639 1.8 christos SELF's operand-dependent value. fields[0] specifies the field that
1640 1.6 christos holds <base>. <simm4> is encoded in the SVE_imm4 field. */
1641 1.6 christos bool
1642 1.6 christos aarch64_ext_sve_addr_ri_s4xvl (const aarch64_operand *self,
1643 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
1644 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1645 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1646 1.6 christos {
1647 1.6 christos int offset;
1648 1.6 christos
1649 1.6 christos offset = extract_field (FLD_SVE_imm4, code, 0);
1650 1.6 christos offset = ((offset + 8) & 15) - 8;
1651 1.6 christos return aarch64_ext_sve_addr_reg_mul_vl (self, info, code, offset);
1652 1.6 christos }
1653 1.6 christos
1654 1.6 christos /* Decode an SVE address [<base>, #<simm6>*<factor>, MUL VL],
1655 1.6 christos where <simm6> is a 6-bit signed value and where <factor> is 1 plus
1656 1.8 christos SELF's operand-dependent value. fields[0] specifies the field that
1657 1.6 christos holds <base>. <simm6> is encoded in the SVE_imm6 field. */
1658 1.6 christos bool
1659 1.6 christos aarch64_ext_sve_addr_ri_s6xvl (const aarch64_operand *self,
1660 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
1661 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1662 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1663 1.6 christos {
1664 1.6 christos int offset;
1665 1.6 christos
1666 1.6 christos offset = extract_field (FLD_SVE_imm6, code, 0);
1667 1.6 christos offset = (((offset + 32) & 63) - 32);
1668 1.6 christos return aarch64_ext_sve_addr_reg_mul_vl (self, info, code, offset);
1669 1.6 christos }
1670 1.6 christos
1671 1.6 christos /* Decode an SVE address [<base>, #<simm9>*<factor>, MUL VL],
1672 1.6 christos where <simm9> is a 9-bit signed value and where <factor> is 1 plus
1673 1.6 christos SELF's operand-dependent value. fields[0] specifies the field that
1674 1.8 christos holds <base>. <simm9> is encoded in the concatenation of the SVE_imm6
1675 1.6 christos and imm3 fields, with imm3 being the less-significant part. */
1676 1.6 christos bool
1677 1.6 christos aarch64_ext_sve_addr_ri_s9xvl (const aarch64_operand *self,
1678 1.6 christos aarch64_opnd_info *info,
1679 1.6 christos aarch64_insn code,
1680 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1681 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1682 1.6 christos {
1683 1.9 christos int offset;
1684 1.6 christos
1685 1.6 christos offset = extract_fields (code, 0, 2, FLD_SVE_imm6, FLD_imm3_10);
1686 1.6 christos offset = (((offset + 256) & 511) - 256);
1687 1.6 christos return aarch64_ext_sve_addr_reg_mul_vl (self, info, code, offset);
1688 1.6 christos }
1689 1.6 christos
1690 1.6 christos /* Decode an SVE address [<base>, #<offset> << <shift>], where <offset>
1691 1.8 christos is given by the OFFSET parameter and where <shift> is SELF's operand-
1692 1.6 christos dependent value. fields[0] specifies the base register field <base>. */
1693 1.6 christos static bool
1694 1.6 christos aarch64_ext_sve_addr_reg_imm (const aarch64_operand *self,
1695 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
1696 1.6 christos int64_t offset)
1697 1.6 christos {
1698 1.8 christos info->addr.base_regno = extract_field (self->fields[0], code, 0);
1699 1.8 christos info->addr.offset.imm = offset * (1 << get_operand_specific_data (self));
1700 1.8 christos info->addr.offset.is_reg = false;
1701 1.8 christos info->addr.writeback = false;
1702 1.8 christos info->addr.preind = true;
1703 1.8 christos info->shifter.operator_present = false;
1704 1.6 christos info->shifter.amount_present = false;
1705 1.6 christos return true;
1706 1.6 christos }
1707 1.6 christos
1708 1.6 christos /* Decode an SVE address [X<n>, #<SVE_imm4> << <shift>], where <SVE_imm4>
1709 1.8 christos is a 4-bit signed number and where <shift> is SELF's operand-dependent
1710 1.6 christos value. fields[0] specifies the base register field. */
1711 1.6 christos bool
1712 1.6 christos aarch64_ext_sve_addr_ri_s4 (const aarch64_operand *self,
1713 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
1714 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1715 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1716 1.6 christos {
1717 1.6 christos int offset = sign_extend (extract_field (FLD_SVE_imm4, code, 0), 3);
1718 1.6 christos return aarch64_ext_sve_addr_reg_imm (self, info, code, offset);
1719 1.6 christos }
1720 1.6 christos
1721 1.6 christos /* Decode an SVE address [X<n>, #<SVE_imm6> << <shift>], where <SVE_imm6>
1722 1.8 christos is a 6-bit unsigned number and where <shift> is SELF's operand-dependent
1723 1.6 christos value. fields[0] specifies the base register field. */
1724 1.6 christos bool
1725 1.6 christos aarch64_ext_sve_addr_ri_u6 (const aarch64_operand *self,
1726 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
1727 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1728 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1729 1.6 christos {
1730 1.6 christos int offset = extract_field (FLD_SVE_imm6, code, 0);
1731 1.6 christos return aarch64_ext_sve_addr_reg_imm (self, info, code, offset);
1732 1.6 christos }
1733 1.6 christos
1734 1.6 christos /* Decode an SVE address [X<n>, X<m>{, LSL #<shift>}], where <shift>
1735 1.8 christos is SELF's operand-dependent value. fields[0] specifies the base
1736 1.6 christos register field and fields[1] specifies the offset register field. */
1737 1.6 christos bool
1738 1.6 christos aarch64_ext_sve_addr_rr_lsl (const aarch64_operand *self,
1739 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
1740 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1741 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1742 1.6 christos {
1743 1.6 christos int index_regno;
1744 1.6 christos
1745 1.8 christos index_regno = extract_field (self->fields[1], code, 0);
1746 1.6 christos if (index_regno == 31 && (self->flags & OPD_F_NO_ZR) != 0)
1747 1.6 christos return false;
1748 1.6 christos
1749 1.8 christos info->addr.base_regno = extract_field (self->fields[0], code, 0);
1750 1.8 christos info->addr.offset.regno = index_regno;
1751 1.8 christos info->addr.offset.is_reg = true;
1752 1.6 christos info->addr.writeback = false;
1753 1.6 christos info->addr.preind = true;
1754 1.6 christos info->shifter.kind = AARCH64_MOD_LSL;
1755 1.6 christos info->shifter.amount = get_operand_specific_data (self);
1756 1.8 christos info->shifter.operator_present = (info->shifter.amount != 0);
1757 1.6 christos info->shifter.amount_present = (info->shifter.amount != 0);
1758 1.6 christos return true;
1759 1.6 christos }
1760 1.6 christos
1761 1.6 christos /* Decode an SVE address [X<n>, Z<m>.<T>, (S|U)XTW {#<shift>}], where
1762 1.6 christos <shift> is SELF's operand-dependent value. fields[0] specifies the
1763 1.8 christos base register field, fields[1] specifies the offset register field and
1764 1.6 christos fields[2] is a single-bit field that selects SXTW over UXTW. */
1765 1.6 christos bool
1766 1.6 christos aarch64_ext_sve_addr_rz_xtw (const aarch64_operand *self,
1767 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
1768 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1769 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1770 1.6 christos {
1771 1.8 christos info->addr.base_regno = extract_field (self->fields[0], code, 0);
1772 1.8 christos info->addr.offset.regno = extract_field (self->fields[1], code, 0);
1773 1.8 christos info->addr.offset.is_reg = true;
1774 1.6 christos info->addr.writeback = false;
1775 1.6 christos info->addr.preind = true;
1776 1.6 christos if (extract_field (self->fields[2], code, 0))
1777 1.6 christos info->shifter.kind = AARCH64_MOD_SXTW;
1778 1.6 christos else
1779 1.8 christos info->shifter.kind = AARCH64_MOD_UXTW;
1780 1.6 christos info->shifter.amount = get_operand_specific_data (self);
1781 1.8 christos info->shifter.operator_present = true;
1782 1.6 christos info->shifter.amount_present = (info->shifter.amount != 0);
1783 1.6 christos return true;
1784 1.6 christos }
1785 1.6 christos
1786 1.6 christos /* Decode an SVE address [Z<n>.<T>, #<imm5> << <shift>], where <imm5> is a
1787 1.8 christos 5-bit unsigned number and where <shift> is SELF's operand-dependent value.
1788 1.6 christos fields[0] specifies the base register field. */
1789 1.6 christos bool
1790 1.6 christos aarch64_ext_sve_addr_zi_u5 (const aarch64_operand *self,
1791 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
1792 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1793 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1794 1.6 christos {
1795 1.6 christos int offset = extract_field (FLD_imm5, code, 0);
1796 1.6 christos return aarch64_ext_sve_addr_reg_imm (self, info, code, offset);
1797 1.6 christos }
1798 1.6 christos
1799 1.6 christos /* Decode an SVE address [Z<n>.<T>, Z<m>.<T>{, <modifier> {#<msz>}}],
1800 1.6 christos where <modifier> is given by KIND and where <msz> is a 2-bit unsigned
1801 1.8 christos number. fields[0] specifies the base register field and fields[1]
1802 1.6 christos specifies the offset register field. */
1803 1.6 christos static bool
1804 1.6 christos aarch64_ext_sve_addr_zz (const aarch64_operand *self, aarch64_opnd_info *info,
1805 1.6 christos aarch64_insn code, enum aarch64_modifier_kind kind)
1806 1.6 christos {
1807 1.8 christos info->addr.base_regno = extract_field (self->fields[0], code, 0);
1808 1.8 christos info->addr.offset.regno = extract_field (self->fields[1], code, 0);
1809 1.8 christos info->addr.offset.is_reg = true;
1810 1.6 christos info->addr.writeback = false;
1811 1.6 christos info->addr.preind = true;
1812 1.6 christos info->shifter.kind = kind;
1813 1.6 christos info->shifter.amount = extract_field (FLD_SVE_msz, code, 0);
1814 1.6 christos info->shifter.operator_present = (kind != AARCH64_MOD_LSL
1815 1.8 christos || info->shifter.amount != 0);
1816 1.6 christos info->shifter.amount_present = (info->shifter.amount != 0);
1817 1.6 christos return true;
1818 1.6 christos }
1819 1.6 christos
1820 1.6 christos /* Decode an SVE address [Z<n>.<T>, Z<m>.<T>{, LSL #<msz>}], where
1821 1.8 christos <msz> is a 2-bit unsigned number. fields[0] specifies the base register
1822 1.6 christos field and fields[1] specifies the offset register field. */
1823 1.6 christos bool
1824 1.6 christos aarch64_ext_sve_addr_zz_lsl (const aarch64_operand *self,
1825 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
1826 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1827 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1828 1.6 christos {
1829 1.6 christos return aarch64_ext_sve_addr_zz (self, info, code, AARCH64_MOD_LSL);
1830 1.6 christos }
1831 1.6 christos
1832 1.6 christos /* Decode an SVE address [Z<n>.<T>, Z<m>.<T>, SXTW {#<msz>}], where
1833 1.8 christos <msz> is a 2-bit unsigned number. fields[0] specifies the base register
1834 1.6 christos field and fields[1] specifies the offset register field. */
1835 1.6 christos bool
1836 1.6 christos aarch64_ext_sve_addr_zz_sxtw (const aarch64_operand *self,
1837 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
1838 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1839 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1840 1.6 christos {
1841 1.6 christos return aarch64_ext_sve_addr_zz (self, info, code, AARCH64_MOD_SXTW);
1842 1.6 christos }
1843 1.6 christos
1844 1.6 christos /* Decode an SVE address [Z<n>.<T>, Z<m>.<T>, UXTW {#<msz>}], where
1845 1.8 christos <msz> is a 2-bit unsigned number. fields[0] specifies the base register
1846 1.6 christos field and fields[1] specifies the offset register field. */
1847 1.6 christos bool
1848 1.6 christos aarch64_ext_sve_addr_zz_uxtw (const aarch64_operand *self,
1849 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
1850 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1851 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1852 1.6 christos {
1853 1.6 christos return aarch64_ext_sve_addr_zz (self, info, code, AARCH64_MOD_UXTW);
1854 1.6 christos }
1855 1.6 christos
1856 1.8 christos /* Finish decoding an SVE arithmetic immediate, given that INFO already
1857 1.6 christos has the raw field value and that the low 8 bits decode to VALUE. */
1858 1.6 christos static bool
1859 1.6 christos decode_sve_aimm (aarch64_opnd_info *info, int64_t value)
1860 1.6 christos {
1861 1.6 christos info->shifter.kind = AARCH64_MOD_LSL;
1862 1.6 christos info->shifter.amount = 0;
1863 1.6 christos if (info->imm.value & 0x100)
1864 1.6 christos {
1865 1.6 christos if (value == 0)
1866 1.6 christos /* Decode 0x100 as #0, LSL #8. */
1867 1.6 christos info->shifter.amount = 8;
1868 1.6 christos else
1869 1.6 christos value *= 256;
1870 1.6 christos }
1871 1.6 christos info->shifter.operator_present = (info->shifter.amount != 0);
1872 1.8 christos info->shifter.amount_present = (info->shifter.amount != 0);
1873 1.6 christos info->imm.value = value;
1874 1.6 christos return true;
1875 1.6 christos }
1876 1.8 christos
1877 1.6 christos /* Decode an SVE ADD/SUB immediate. */
1878 1.6 christos bool
1879 1.6 christos aarch64_ext_sve_aimm (const aarch64_operand *self,
1880 1.6 christos aarch64_opnd_info *info, const aarch64_insn code,
1881 1.6 christos const aarch64_inst *inst,
1882 1.6 christos aarch64_operand_error *errors)
1883 1.6 christos {
1884 1.6 christos return (aarch64_ext_imm (self, info, code, inst, errors)
1885 1.6 christos && decode_sve_aimm (info, (uint8_t) info->imm.value));
1886 1.9 christos }
1887 1.9 christos
1888 1.9 christos bool
1889 1.9 christos aarch64_ext_sve_aligned_reglist (const aarch64_operand *self,
1890 1.9 christos aarch64_opnd_info *info, aarch64_insn code,
1891 1.9 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1892 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1893 1.9 christos {
1894 1.9 christos unsigned int num_regs = get_operand_specific_data (self);
1895 1.9 christos unsigned int val = extract_field (self->fields[0], code, 0);
1896 1.9 christos info->reglist.first_regno = val * num_regs;
1897 1.9 christos info->reglist.num_regs = num_regs;
1898 1.9 christos info->reglist.stride = 1;
1899 1.9 christos return true;
1900 1.6 christos }
1901 1.8 christos
1902 1.6 christos /* Decode an SVE CPY/DUP immediate. */
1903 1.6 christos bool
1904 1.6 christos aarch64_ext_sve_asimm (const aarch64_operand *self,
1905 1.6 christos aarch64_opnd_info *info, const aarch64_insn code,
1906 1.6 christos const aarch64_inst *inst,
1907 1.6 christos aarch64_operand_error *errors)
1908 1.6 christos {
1909 1.6 christos return (aarch64_ext_imm (self, info, code, inst, errors)
1910 1.6 christos && decode_sve_aimm (info, (int8_t) info->imm.value));
1911 1.6 christos }
1912 1.6 christos
1913 1.8 christos /* Decode a single-bit immediate that selects between #0.5 and #1.0.
1914 1.6 christos The fields array specifies which field to use. */
1915 1.6 christos bool
1916 1.6 christos aarch64_ext_sve_float_half_one (const aarch64_operand *self,
1917 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
1918 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1919 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1920 1.6 christos {
1921 1.6 christos if (extract_field (self->fields[0], code, 0))
1922 1.6 christos info->imm.value = 0x3f800000;
1923 1.8 christos else
1924 1.8 christos info->imm.value = 0x3f000000;
1925 1.6 christos info->imm.is_fp = true;
1926 1.6 christos return true;
1927 1.6 christos }
1928 1.6 christos
1929 1.8 christos /* Decode a single-bit immediate that selects between #0.5 and #2.0.
1930 1.6 christos The fields array specifies which field to use. */
1931 1.6 christos bool
1932 1.6 christos aarch64_ext_sve_float_half_two (const aarch64_operand *self,
1933 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
1934 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1935 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1936 1.6 christos {
1937 1.6 christos if (extract_field (self->fields[0], code, 0))
1938 1.6 christos info->imm.value = 0x40000000;
1939 1.8 christos else
1940 1.8 christos info->imm.value = 0x3f000000;
1941 1.6 christos info->imm.is_fp = true;
1942 1.6 christos return true;
1943 1.6 christos }
1944 1.6 christos
1945 1.8 christos /* Decode a single-bit immediate that selects between #0.0 and #1.0.
1946 1.6 christos The fields array specifies which field to use. */
1947 1.6 christos bool
1948 1.6 christos aarch64_ext_sve_float_zero_one (const aarch64_operand *self,
1949 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
1950 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1951 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1952 1.6 christos {
1953 1.6 christos if (extract_field (self->fields[0], code, 0))
1954 1.6 christos info->imm.value = 0x3f800000;
1955 1.8 christos else
1956 1.8 christos info->imm.value = 0x0;
1957 1.8 christos info->imm.is_fp = true;
1958 1.8 christos return true;
1959 1.10 christos }
1960 1.10 christos
1961 1.10 christos /* Decode SME instruction such as MOVZA ZA tile slice to vector. */
1962 1.10 christos bool
1963 1.10 christos aarch64_ext_sme_za_tile_to_vec (const aarch64_operand *self,
1964 1.10 christos aarch64_opnd_info *info, aarch64_insn code,
1965 1.10 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
1966 1.10 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
1967 1.10 christos {
1968 1.10 christos aarch64_insn Qsize; /* fields Q:S:size. */
1969 1.10 christos int fld_v = extract_field (self->fields[0], code, 0);
1970 1.10 christos int fld_rv = extract_field (self->fields[1], code, 0);
1971 1.10 christos int fld_zan_imm = extract_field (FLD_imm4_5, code, 0);
1972 1.10 christos
1973 1.10 christos Qsize = extract_fields (inst->value, 0, 2, FLD_SME_size_22, FLD_SME_Q);
1974 1.10 christos switch (Qsize)
1975 1.10 christos {
1976 1.10 christos case 0x0:
1977 1.10 christos info->qualifier = AARCH64_OPND_QLF_S_B;
1978 1.10 christos info->indexed_za.regno = 0;
1979 1.10 christos info->indexed_za.index.imm = fld_zan_imm;
1980 1.10 christos break;
1981 1.10 christos case 0x2:
1982 1.10 christos info->qualifier = AARCH64_OPND_QLF_S_H;
1983 1.10 christos info->indexed_za.regno = fld_zan_imm >> 3;
1984 1.10 christos info->indexed_za.index.imm = fld_zan_imm & 0x07;
1985 1.10 christos break;
1986 1.10 christos case 0x4:
1987 1.10 christos info->qualifier = AARCH64_OPND_QLF_S_S;
1988 1.10 christos info->indexed_za.regno = fld_zan_imm >> 2;
1989 1.10 christos info->indexed_za.index.imm = fld_zan_imm & 0x03;
1990 1.10 christos break;
1991 1.10 christos case 0x6:
1992 1.10 christos info->qualifier = AARCH64_OPND_QLF_S_D;
1993 1.10 christos info->indexed_za.regno = fld_zan_imm >> 1;
1994 1.10 christos info->indexed_za.index.imm = fld_zan_imm & 0x01;
1995 1.10 christos break;
1996 1.10 christos case 0x7:
1997 1.10 christos info->qualifier = AARCH64_OPND_QLF_S_Q;
1998 1.10 christos info->indexed_za.regno = fld_zan_imm;
1999 1.10 christos break;
2000 1.10 christos default:
2001 1.10 christos return false;
2002 1.10 christos }
2003 1.10 christos
2004 1.10 christos info->indexed_za.index.regno = fld_rv + 12;
2005 1.10 christos info->indexed_za.v = fld_v;
2006 1.10 christos
2007 1.10 christos return true;
2008 1.8 christos }
2009 1.8 christos
2010 1.8 christos /* Decode ZA tile vector, vector indicator, vector selector, qualifier and
2011 1.8 christos immediate on numerous SME instruction fields such as MOVA. */
2012 1.8 christos bool
2013 1.8 christos aarch64_ext_sme_za_hv_tiles (const aarch64_operand *self,
2014 1.8 christos aarch64_opnd_info *info, aarch64_insn code,
2015 1.8 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
2016 1.8 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
2017 1.8 christos {
2018 1.8 christos int fld_size = extract_field (self->fields[0], code, 0);
2019 1.8 christos int fld_q = extract_field (self->fields[1], code, 0);
2020 1.8 christos int fld_v = extract_field (self->fields[2], code, 0);
2021 1.8 christos int fld_rv = extract_field (self->fields[3], code, 0);
2022 1.8 christos int fld_zan_imm = extract_field (self->fields[4], code, 0);
2023 1.8 christos
2024 1.9 christos /* Deduce qualifier encoded in size and Q fields. */
2025 1.9 christos if (fld_size == 0)
2026 1.9 christos {
2027 1.9 christos info->indexed_za.regno = 0;
2028 1.8 christos info->indexed_za.index.imm = fld_zan_imm;
2029 1.9 christos }
2030 1.9 christos else if (fld_size == 1)
2031 1.9 christos {
2032 1.9 christos info->indexed_za.regno = fld_zan_imm >> 3;
2033 1.8 christos info->indexed_za.index.imm = fld_zan_imm & 0x07;
2034 1.9 christos }
2035 1.9 christos else if (fld_size == 2)
2036 1.9 christos {
2037 1.9 christos info->indexed_za.regno = fld_zan_imm >> 2;
2038 1.8 christos info->indexed_za.index.imm = fld_zan_imm & 0x03;
2039 1.9 christos }
2040 1.9 christos else if (fld_size == 3 && fld_q == 0)
2041 1.9 christos {
2042 1.9 christos info->indexed_za.regno = fld_zan_imm >> 1;
2043 1.8 christos info->indexed_za.index.imm = fld_zan_imm & 0x01;
2044 1.9 christos }
2045 1.9 christos else if (fld_size == 3 && fld_q == 1)
2046 1.9 christos {
2047 1.9 christos info->indexed_za.regno = fld_zan_imm;
2048 1.9 christos info->indexed_za.index.imm = 0;
2049 1.9 christos }
2050 1.8 christos else
2051 1.9 christos return false;
2052 1.9 christos
2053 1.9 christos info->indexed_za.index.regno = fld_rv + 12;
2054 1.9 christos info->indexed_za.v = fld_v;
2055 1.9 christos
2056 1.9 christos return true;
2057 1.9 christos }
2058 1.9 christos
2059 1.9 christos bool
2060 1.9 christos aarch64_ext_sme_za_hv_tiles_range (const aarch64_operand *self,
2061 1.9 christos aarch64_opnd_info *info, aarch64_insn code,
2062 1.9 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
2063 1.9 christos aarch64_operand_error *errors
2064 1.9 christos ATTRIBUTE_UNUSED)
2065 1.9 christos {
2066 1.9 christos int ebytes = aarch64_get_qualifier_esize (info->qualifier);
2067 1.9 christos int range_size = get_opcode_dependent_value (inst->opcode);
2068 1.9 christos int fld_v = extract_field (self->fields[0], code, 0);
2069 1.9 christos int fld_rv = extract_field (self->fields[1], code, 0);
2070 1.8 christos int fld_zan_imm = extract_field (self->fields[2], code, 0);
2071 1.9 christos int max_value = 16 / range_size / ebytes;
2072 1.9 christos
2073 1.9 christos if (max_value == 0)
2074 1.9 christos max_value = 1;
2075 1.9 christos
2076 1.9 christos int regno = fld_zan_imm / max_value;
2077 1.9 christos if (regno >= ebytes)
2078 1.9 christos return false;
2079 1.9 christos
2080 1.9 christos info->indexed_za.regno = regno;
2081 1.9 christos info->indexed_za.index.imm = (fld_zan_imm % max_value) * range_size;
2082 1.9 christos info->indexed_za.index.countm1 = range_size - 1;
2083 1.8 christos info->indexed_za.index.regno = fld_rv + 12;
2084 1.8 christos info->indexed_za.v = fld_v;
2085 1.8 christos
2086 1.8 christos return true;
2087 1.8 christos }
2088 1.8 christos
2089 1.8 christos /* Decode in SME instruction ZERO list of up to eight 64-bit element tile names
2090 1.8 christos separated by commas, encoded in the "imm8" field.
2091 1.8 christos
2092 1.8 christos For programmer convenience an assembler must also accept the names of
2093 1.8 christos 32-bit, 16-bit and 8-bit element tiles which are converted into the
2094 1.8 christos corresponding set of 64-bit element tiles.
2095 1.8 christos */
2096 1.8 christos bool
2097 1.8 christos aarch64_ext_sme_za_list (const aarch64_operand *self,
2098 1.8 christos aarch64_opnd_info *info, aarch64_insn code,
2099 1.8 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
2100 1.8 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
2101 1.8 christos {
2102 1.8 christos int mask = extract_field (self->fields[0], code, 0);
2103 1.8 christos info->imm.value = mask;
2104 1.8 christos return true;
2105 1.8 christos }
2106 1.9 christos
2107 1.8 christos /* Decode ZA array vector select register (Rv field), optional vector and
2108 1.8 christos memory offset (imm4_11 field).
2109 1.8 christos */
2110 1.8 christos bool
2111 1.9 christos aarch64_ext_sme_za_array (const aarch64_operand *self,
2112 1.8 christos aarch64_opnd_info *info, aarch64_insn code,
2113 1.8 christos const aarch64_inst *inst,
2114 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
2115 1.9 christos {
2116 1.9 christos int regno = extract_field (self->fields[0], code, 0);
2117 1.9 christos if (info->type == AARCH64_OPND_SME_ZA_array_off4)
2118 1.9 christos regno += 12;
2119 1.8 christos else
2120 1.9 christos regno += 8;
2121 1.9 christos int imm = extract_field (self->fields[1], code, 0);
2122 1.9 christos int num_offsets = get_operand_specific_data (self);
2123 1.9 christos if (num_offsets == 0)
2124 1.9 christos num_offsets = 1;
2125 1.9 christos info->indexed_za.index.regno = regno;
2126 1.9 christos info->indexed_za.index.imm = imm * num_offsets;
2127 1.9 christos info->indexed_za.index.countm1 = num_offsets - 1;
2128 1.9 christos info->indexed_za.group_size = get_opcode_dependent_value (inst->opcode);
2129 1.9 christos return true;
2130 1.9 christos }
2131 1.9 christos
2132 1.9 christos /* Decode two ZA tile slice (V, Rv, off3| ZAn ,off2 | ZAn, ol| ZAn) feilds. */
2133 1.9 christos bool
2134 1.9 christos aarch64_ext_sme_za_vrs1 (const aarch64_operand *self,
2135 1.9 christos aarch64_opnd_info *info, aarch64_insn code,
2136 1.9 christos const aarch64_inst *inst,
2137 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
2138 1.9 christos {
2139 1.9 christos int v = extract_field (self->fields[0], code, 0);
2140 1.9 christos int regno = 12 + extract_field (self->fields[1], code, 0);
2141 1.9 christos int imm, za_reg, num_offset = 2;
2142 1.9 christos
2143 1.9 christos switch (info->qualifier)
2144 1.9 christos {
2145 1.9 christos case AARCH64_OPND_QLF_S_B:
2146 1.9 christos imm = extract_field (self->fields[2], code, 0);
2147 1.9 christos info->indexed_za.index.imm = imm * num_offset;
2148 1.9 christos break;
2149 1.9 christos case AARCH64_OPND_QLF_S_H:
2150 1.9 christos case AARCH64_OPND_QLF_S_S:
2151 1.9 christos za_reg = extract_field (self->fields[2], code, 0);
2152 1.9 christos imm = extract_field (self->fields[3], code, 0);
2153 1.9 christos info->indexed_za.index.imm = imm * num_offset;
2154 1.9 christos info->indexed_za.regno = za_reg;
2155 1.9 christos break;
2156 1.9 christos case AARCH64_OPND_QLF_S_D:
2157 1.9 christos za_reg = extract_field (self->fields[2], code, 0);
2158 1.9 christos info->indexed_za.regno = za_reg;
2159 1.9 christos break;
2160 1.9 christos default:
2161 1.9 christos return false;
2162 1.9 christos }
2163 1.9 christos
2164 1.9 christos info->indexed_za.index.regno = regno;
2165 1.9 christos info->indexed_za.index.countm1 = num_offset - 1;
2166 1.9 christos info->indexed_za.v = v;
2167 1.9 christos info->indexed_za.group_size = get_opcode_dependent_value (inst->opcode);
2168 1.9 christos return true;
2169 1.9 christos }
2170 1.9 christos
2171 1.9 christos /* Decode four ZA tile slice (V, Rv, off3| ZAn ,off2 | ZAn, ol| ZAn) feilds. */
2172 1.9 christos bool
2173 1.9 christos aarch64_ext_sme_za_vrs2 (const aarch64_operand *self,
2174 1.9 christos aarch64_opnd_info *info, aarch64_insn code,
2175 1.9 christos const aarch64_inst *inst,
2176 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
2177 1.9 christos {
2178 1.9 christos int v = extract_field (self->fields[0], code, 0);
2179 1.9 christos int regno = 12 + extract_field (self->fields[1], code, 0);
2180 1.9 christos int imm, za_reg, num_offset =4;
2181 1.9 christos
2182 1.9 christos switch (info->qualifier)
2183 1.9 christos {
2184 1.9 christos case AARCH64_OPND_QLF_S_B:
2185 1.9 christos imm = extract_field (self->fields[2], code, 0);
2186 1.9 christos info->indexed_za.index.imm = imm * num_offset;
2187 1.9 christos break;
2188 1.9 christos case AARCH64_OPND_QLF_S_H:
2189 1.9 christos za_reg = extract_field (self->fields[2], code, 0);
2190 1.9 christos imm = extract_field (self->fields[3], code, 0);
2191 1.9 christos info->indexed_za.index.imm = imm * num_offset;
2192 1.9 christos info->indexed_za.regno = za_reg;
2193 1.9 christos break;
2194 1.9 christos case AARCH64_OPND_QLF_S_S:
2195 1.9 christos case AARCH64_OPND_QLF_S_D:
2196 1.9 christos za_reg = extract_field (self->fields[2], code, 0);
2197 1.9 christos info->indexed_za.regno = za_reg;
2198 1.9 christos break;
2199 1.9 christos default:
2200 1.9 christos return false;
2201 1.9 christos }
2202 1.9 christos
2203 1.9 christos info->indexed_za.index.regno = regno;
2204 1.9 christos info->indexed_za.index.countm1 = num_offset - 1;
2205 1.8 christos info->indexed_za.v = v;
2206 1.8 christos info->indexed_za.group_size = get_opcode_dependent_value (inst->opcode);
2207 1.8 christos return true;
2208 1.8 christos }
2209 1.8 christos
2210 1.8 christos bool
2211 1.8 christos aarch64_ext_sme_addr_ri_u4xvl (const aarch64_operand *self,
2212 1.8 christos aarch64_opnd_info *info, aarch64_insn code,
2213 1.8 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
2214 1.8 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
2215 1.8 christos {
2216 1.8 christos int regno = extract_field (self->fields[0], code, 0);
2217 1.8 christos int imm = extract_field (self->fields[1], code, 0);
2218 1.8 christos info->addr.base_regno = regno;
2219 1.8 christos info->addr.offset.imm = imm;
2220 1.8 christos /* MUL VL operator is always present for this operand. */
2221 1.8 christos info->shifter.kind = AARCH64_MOD_MUL_VL;
2222 1.8 christos info->shifter.operator_present = (imm != 0);
2223 1.8 christos return true;
2224 1.8 christos }
2225 1.8 christos
2226 1.8 christos /* Decode {SM|ZA} filed for SMSTART and SMSTOP instructions. */
2227 1.8 christos bool
2228 1.8 christos aarch64_ext_sme_sm_za (const aarch64_operand *self,
2229 1.8 christos aarch64_opnd_info *info, aarch64_insn code,
2230 1.8 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
2231 1.8 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
2232 1.8 christos {
2233 1.8 christos info->pstatefield = 0x1b;
2234 1.8 christos aarch64_insn fld_crm = extract_field (self->fields[0], code, 0);
2235 1.8 christos fld_crm >>= 1; /* CRm[3:1]. */
2236 1.8 christos
2237 1.8 christos if (fld_crm == 0x1)
2238 1.8 christos info->reg.regno = 's';
2239 1.8 christos else if (fld_crm == 0x2)
2240 1.8 christos info->reg.regno = 'z';
2241 1.8 christos else
2242 1.8 christos return false;
2243 1.8 christos
2244 1.8 christos return true;
2245 1.8 christos }
2246 1.8 christos
2247 1.8 christos bool
2248 1.8 christos aarch64_ext_sme_pred_reg_with_index (const aarch64_operand *self,
2249 1.8 christos aarch64_opnd_info *info, aarch64_insn code,
2250 1.8 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
2251 1.8 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
2252 1.8 christos {
2253 1.8 christos aarch64_insn fld_rm = extract_field (self->fields[0], code, 0);
2254 1.8 christos aarch64_insn fld_pn = extract_field (self->fields[1], code, 0);
2255 1.8 christos aarch64_insn fld_i1 = extract_field (self->fields[2], code, 0);
2256 1.8 christos aarch64_insn fld_tszh = extract_field (self->fields[3], code, 0);
2257 1.8 christos aarch64_insn fld_tszl = extract_field (self->fields[4], code, 0);
2258 1.9 christos int imm;
2259 1.9 christos
2260 1.8 christos info->indexed_za.regno = fld_pn;
2261 1.9 christos info->indexed_za.index.regno = fld_rm + 12;
2262 1.9 christos
2263 1.9 christos if (fld_tszl & 0x1)
2264 1.9 christos imm = (fld_i1 << 3) | (fld_tszh << 2) | (fld_tszl >> 1);
2265 1.9 christos else if (fld_tszl & 0x2)
2266 1.9 christos imm = (fld_i1 << 2) | (fld_tszh << 1) | (fld_tszl >> 2);
2267 1.9 christos else if (fld_tszl & 0x4)
2268 1.9 christos imm = (fld_i1 << 1) | fld_tszh;
2269 1.8 christos else if (fld_tszh)
2270 1.8 christos imm = fld_i1;
2271 1.8 christos else
2272 1.9 christos return false;
2273 1.8 christos
2274 1.6 christos info->indexed_za.index.imm = imm;
2275 1.6 christos return true;
2276 1.6 christos }
2277 1.6 christos
2278 1.6 christos /* Decode Zn[MM], where MM has a 7-bit triangular encoding. The fields
2279 1.6 christos array specifies which field to use for Zn. MM is encoded in the
2280 1.8 christos concatenation of imm5 and SVE_tszh, with imm5 being the less
2281 1.6 christos significant part. */
2282 1.6 christos bool
2283 1.6 christos aarch64_ext_sve_index (const aarch64_operand *self,
2284 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
2285 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
2286 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
2287 1.6 christos {
2288 1.6 christos int val;
2289 1.10 christos
2290 1.6 christos info->reglane.regno = extract_field (self->fields[0], code, 0);
2291 1.6 christos val = extract_all_fields_after (self, 1, code);
2292 1.6 christos if ((val & 31) == 0)
2293 1.6 christos return 0;
2294 1.6 christos while ((val & 1) == 0)
2295 1.8 christos val /= 2;
2296 1.6 christos info->reglane.index = val / 2;
2297 1.6 christos return true;
2298 1.6 christos }
2299 1.8 christos
2300 1.6 christos /* Decode a logical immediate for the MOV alias of SVE DUPM. */
2301 1.6 christos bool
2302 1.6 christos aarch64_ext_sve_limm_mov (const aarch64_operand *self,
2303 1.6 christos aarch64_opnd_info *info, const aarch64_insn code,
2304 1.6 christos const aarch64_inst *inst,
2305 1.6 christos aarch64_operand_error *errors)
2306 1.6 christos {
2307 1.6 christos int esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier);
2308 1.6 christos return (aarch64_ext_limm (self, info, code, inst, errors)
2309 1.6 christos && aarch64_sve_dupm_mov_immediate_p (info->imm.value, esize));
2310 1.6 christos }
2311 1.6 christos
2312 1.6 christos /* Decode Zn[MM], where Zn occupies the least-significant part of the field
2313 1.8 christos and where MM occupies the most-significant part. The operand-dependent
2314 1.6 christos value specifies the number of bits in Zn. */
2315 1.6 christos bool
2316 1.6 christos aarch64_ext_sve_quad_index (const aarch64_operand *self,
2317 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
2318 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
2319 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
2320 1.6 christos {
2321 1.6 christos unsigned int reg_bits = get_operand_specific_data (self);
2322 1.6 christos unsigned int val = extract_all_fields (self, code);
2323 1.8 christos info->reglane.regno = val & ((1 << reg_bits) - 1);
2324 1.6 christos info->reglane.index = val >> reg_bits;
2325 1.6 christos return true;
2326 1.6 christos }
2327 1.6 christos
2328 1.6 christos /* Decode {Zn.<T> - Zm.<T>}. The fields array specifies which field
2329 1.8 christos to use for Zn. The opcode-dependent value specifies the number
2330 1.6 christos of registers in the list. */
2331 1.6 christos bool
2332 1.6 christos aarch64_ext_sve_reglist (const aarch64_operand *self,
2333 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
2334 1.6 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
2335 1.6 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
2336 1.6 christos {
2337 1.9 christos info->reglist.first_regno = extract_field (self->fields[0], code, 0);
2338 1.9 christos info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
2339 1.9 christos info->reglist.stride = 1;
2340 1.9 christos return true;
2341 1.9 christos }
2342 1.9 christos
2343 1.9 christos /* Decode {Zn.<T> , Zm.<T>}. The fields array specifies which field
2344 1.9 christos to use for Zn. The opcode-dependent value specifies the number
2345 1.9 christos of registers in the list. */
2346 1.9 christos bool
2347 1.9 christos aarch64_ext_sve_reglist_zt (const aarch64_operand *self,
2348 1.9 christos aarch64_opnd_info *info, aarch64_insn code,
2349 1.9 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
2350 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
2351 1.9 christos {
2352 1.9 christos info->reglist.first_regno = extract_field (self->fields[0], code, 0);
2353 1.9 christos info->reglist.num_regs = get_operand_specific_data (self);
2354 1.9 christos info->reglist.stride = 1;
2355 1.9 christos return true;
2356 1.9 christos }
2357 1.9 christos
2358 1.9 christos /* Decode a strided register list. The first field holds the top bit
2359 1.9 christos (0 or 16) and the second field holds the lower bits. The stride is
2360 1.9 christos 16 divided by the list length. */
2361 1.9 christos bool
2362 1.9 christos aarch64_ext_sve_strided_reglist (const aarch64_operand *self,
2363 1.9 christos aarch64_opnd_info *info, aarch64_insn code,
2364 1.9 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
2365 1.9 christos aarch64_operand_error *errors
2366 1.9 christos ATTRIBUTE_UNUSED)
2367 1.9 christos {
2368 1.9 christos unsigned int upper = extract_field (self->fields[0], code, 0);
2369 1.9 christos unsigned int lower = extract_field (self->fields[1], code, 0);
2370 1.9 christos info->reglist.first_regno = upper * 16 + lower;
2371 1.8 christos info->reglist.num_regs = get_operand_specific_data (self);
2372 1.6 christos info->reglist.stride = 16 / info->reglist.num_regs;
2373 1.6 christos return true;
2374 1.6 christos }
2375 1.6 christos
2376 1.6 christos /* Decode <pattern>{, MUL #<amount>}. The fields array specifies which
2377 1.8 christos fields to use for <pattern>. <amount> - 1 is encoded in the SVE_imm4
2378 1.6 christos field. */
2379 1.6 christos bool
2380 1.6 christos aarch64_ext_sve_scale (const aarch64_operand *self,
2381 1.6 christos aarch64_opnd_info *info, aarch64_insn code,
2382 1.6 christos const aarch64_inst *inst, aarch64_operand_error *errors)
2383 1.6 christos {
2384 1.6 christos int val;
2385 1.8 christos
2386 1.6 christos if (!aarch64_ext_imm (self, info, code, inst, errors))
2387 1.6 christos return false;
2388 1.6 christos val = extract_field (FLD_SVE_imm4, code, 0);
2389 1.6 christos info->shifter.kind = AARCH64_MOD_MUL;
2390 1.6 christos info->shifter.amount = val + 1;
2391 1.8 christos info->shifter.operator_present = (val != 0);
2392 1.6 christos info->shifter.amount_present = (val != 0);
2393 1.6 christos return true;
2394 1.6 christos }
2395 1.6 christos
2396 1.6 christos /* Return the top set bit in VALUE, which is expected to be relatively
2397 1.6 christos small. */
2398 1.6 christos static uint64_t
2399 1.6 christos get_top_bit (uint64_t value)
2400 1.6 christos {
2401 1.6 christos while ((value & -value) != value)
2402 1.6 christos value -= value & -value;
2403 1.6 christos return value;
2404 1.6 christos }
2405 1.8 christos
2406 1.6 christos /* Decode an SVE shift-left immediate. */
2407 1.6 christos bool
2408 1.6 christos aarch64_ext_sve_shlimm (const aarch64_operand *self,
2409 1.6 christos aarch64_opnd_info *info, const aarch64_insn code,
2410 1.6 christos const aarch64_inst *inst, aarch64_operand_error *errors)
2411 1.6 christos {
2412 1.8 christos if (!aarch64_ext_imm (self, info, code, inst, errors)
2413 1.6 christos || info->imm.value == 0)
2414 1.6 christos return false;
2415 1.8 christos
2416 1.6 christos info->imm.value -= get_top_bit (info->imm.value);
2417 1.6 christos return true;
2418 1.6 christos }
2419 1.8 christos
2420 1.6 christos /* Decode an SVE shift-right immediate. */
2421 1.6 christos bool
2422 1.6 christos aarch64_ext_sve_shrimm (const aarch64_operand *self,
2423 1.6 christos aarch64_opnd_info *info, const aarch64_insn code,
2424 1.6 christos const aarch64_inst *inst, aarch64_operand_error *errors)
2425 1.6 christos {
2426 1.8 christos if (!aarch64_ext_imm (self, info, code, inst, errors)
2427 1.6 christos || info->imm.value == 0)
2428 1.6 christos return false;
2429 1.8 christos
2430 1.8 christos info->imm.value = get_top_bit (info->imm.value) * 2 - info->imm.value;
2431 1.8 christos return true;
2432 1.8 christos }
2433 1.8 christos
2434 1.8 christos /* Decode X0-X30. Register 31 is unallocated. */
2435 1.8 christos bool
2436 1.8 christos aarch64_ext_x0_to_x30 (const aarch64_operand *self, aarch64_opnd_info *info,
2437 1.8 christos const aarch64_insn code,
2438 1.8 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
2439 1.8 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
2440 1.8 christos {
2441 1.1 christos info->reg.regno = extract_field (self->fields[0], code, 0);
2442 1.9 christos return info->reg.regno <= 30;
2443 1.9 christos }
2444 1.9 christos
2445 1.9 christos /* Decode an indexed register, with the first field being the register
2446 1.9 christos number and the remaining fields being the index. */
2447 1.9 christos bool
2448 1.9 christos aarch64_ext_simple_index (const aarch64_operand *self, aarch64_opnd_info *info,
2449 1.9 christos const aarch64_insn code,
2450 1.9 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
2451 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
2452 1.9 christos {
2453 1.9 christos int bias = get_operand_specific_data (self);
2454 1.9 christos info->reglane.regno = extract_field (self->fields[0], code, 0) + bias;
2455 1.9 christos info->reglane.index = extract_all_fields_after (self, 1, code);
2456 1.9 christos return true;
2457 1.9 christos }
2458 1.9 christos
2459 1.9 christos /* Decode a plain shift-right immediate, when there is only a single
2460 1.9 christos element size. */
2461 1.9 christos bool
2462 1.9 christos aarch64_ext_plain_shrimm (const aarch64_operand *self, aarch64_opnd_info *info,
2463 1.9 christos const aarch64_insn code,
2464 1.9 christos const aarch64_inst *inst ATTRIBUTE_UNUSED,
2465 1.9 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
2466 1.9 christos {
2467 1.9 christos unsigned int base = 1 << get_operand_field_width (self, 0);
2468 1.9 christos info->imm.value = base - extract_field (self->fields[0], code, 0);
2469 1.1 christos return true;
2470 1.1 christos }
2471 1.1 christos
2472 1.1 christos /* Bitfields that are commonly used to encode certain operands' information
2474 1.1 christos may be partially used as part of the base opcode in some instructions.
2475 1.1 christos For example, the bit 1 of the field 'size' in
2476 1.1 christos FCVTXN <Vb><d>, <Va><n>
2477 1.1 christos is actually part of the base opcode, while only size<0> is available
2478 1.1 christos for encoding the register type. Another example is the AdvSIMD
2479 1.1 christos instruction ORR (register), in which the field 'size' is also used for
2480 1.1 christos the base opcode, leaving only the field 'Q' available to encode the
2481 1.1 christos vector register arrangement specifier '8B' or '16B'.
2482 1.1 christos
2483 1.1 christos This function tries to deduce the qualifier from the value of partially
2484 1.1 christos constrained field(s). Given the VALUE of such a field or fields, the
2485 1.1 christos qualifiers CANDIDATES and the MASK (indicating which bits are valid for
2486 1.1 christos operand encoding), the function returns the matching qualifier or
2487 1.1 christos AARCH64_OPND_QLF_NIL if nothing matches.
2488 1.1 christos
2489 1.1 christos N.B. CANDIDATES is a group of possible qualifiers that are valid for
2490 1.1 christos one operand; it has a maximum of AARCH64_MAX_QLF_SEQ_NUM qualifiers and
2491 1.1 christos may end with AARCH64_OPND_QLF_NIL. */
2492 1.1 christos
2493 1.1 christos static enum aarch64_opnd_qualifier
2494 1.1 christos get_qualifier_from_partial_encoding (aarch64_insn value,
2495 1.1 christos const enum aarch64_opnd_qualifier* \
2496 1.1 christos candidates,
2497 1.1 christos aarch64_insn mask)
2498 1.1 christos {
2499 1.1 christos int i;
2500 1.1 christos DEBUG_TRACE ("enter with value: %d, mask: %d", (int)value, (int)mask);
2501 1.1 christos for (i = 0; i < AARCH64_MAX_QLF_SEQ_NUM; ++i)
2502 1.1 christos {
2503 1.1 christos aarch64_insn standard_value;
2504 1.1 christos if (candidates[i] == AARCH64_OPND_QLF_NIL)
2505 1.1 christos break;
2506 1.1 christos standard_value = aarch64_get_qualifier_standard_value (candidates[i]);
2507 1.1 christos if ((standard_value & mask) == (value & mask))
2508 1.1 christos return candidates[i];
2509 1.1 christos }
2510 1.1 christos return AARCH64_OPND_QLF_NIL;
2511 1.1 christos }
2512 1.1 christos
2513 1.1 christos /* Given a list of qualifier sequences, return all possible valid qualifiers
2514 1.1 christos for operand IDX in QUALIFIERS.
2515 1.1 christos Assume QUALIFIERS is an array whose length is large enough. */
2516 1.1 christos
2517 1.1 christos static void
2518 1.1 christos get_operand_possible_qualifiers (int idx,
2519 1.1 christos const aarch64_opnd_qualifier_seq_t *list,
2520 1.1 christos enum aarch64_opnd_qualifier *qualifiers)
2521 1.1 christos {
2522 1.1 christos int i;
2523 1.1 christos for (i = 0; i < AARCH64_MAX_QLF_SEQ_NUM; ++i)
2524 1.1 christos if ((qualifiers[i] = list[i][idx]) == AARCH64_OPND_QLF_NIL)
2525 1.1 christos break;
2526 1.1 christos }
2527 1.1 christos
2528 1.1 christos /* Decode the size Q field for e.g. SHADD.
2529 1.1 christos We tag one operand with the qualifer according to the code;
2530 1.1 christos whether the qualifier is valid for this opcode or not, it is the
2531 1.1 christos duty of the semantic checking. */
2532 1.1 christos
2533 1.1 christos static int
2534 1.1 christos decode_sizeq (aarch64_inst *inst)
2535 1.1 christos {
2536 1.1 christos int idx;
2537 1.1 christos enum aarch64_opnd_qualifier qualifier;
2538 1.1 christos aarch64_insn code;
2539 1.1 christos aarch64_insn value, mask;
2540 1.1 christos enum aarch64_field_kind fld_sz;
2541 1.1 christos enum aarch64_opnd_qualifier candidates[AARCH64_MAX_QLF_SEQ_NUM];
2542 1.1 christos
2543 1.1 christos if (inst->opcode->iclass == asisdlse
2544 1.1 christos || inst->opcode->iclass == asisdlsep
2545 1.1 christos || inst->opcode->iclass == asisdlso
2546 1.1 christos || inst->opcode->iclass == asisdlsop)
2547 1.1 christos fld_sz = FLD_vldst_size;
2548 1.1 christos else
2549 1.1 christos fld_sz = FLD_size;
2550 1.1 christos
2551 1.1 christos code = inst->value;
2552 1.1 christos value = extract_fields (code, inst->opcode->mask, 2, fld_sz, FLD_Q);
2553 1.1 christos /* Obtain the info that which bits of fields Q and size are actually
2554 1.1 christos available for operand encoding. Opcodes like FMAXNM and FMLA have
2555 1.1 christos size[1] unavailable. */
2556 1.1 christos mask = extract_fields (~inst->opcode->mask, 0, 2, fld_sz, FLD_Q);
2557 1.1 christos
2558 1.1 christos /* The index of the operand we are going to tag a qualifier and the qualifer
2559 1.1 christos itself are reasoned from the value of the size and Q fields and the
2560 1.1 christos possible valid qualifier lists. */
2561 1.1 christos idx = aarch64_select_operand_for_sizeq_field_coding (inst->opcode);
2562 1.1 christos DEBUG_TRACE ("key idx: %d", idx);
2563 1.1 christos
2564 1.1 christos /* For most related instruciton, size:Q are fully available for operand
2565 1.1 christos encoding. */
2566 1.10 christos if (mask == 0x7)
2567 1.10 christos {
2568 1.1 christos inst->operands[idx].qualifier = get_vreg_qualifier_from_value (value);
2569 1.1 christos if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR)
2570 1.1 christos return 0;
2571 1.1 christos return 1;
2572 1.1 christos }
2573 1.1 christos
2574 1.1 christos get_operand_possible_qualifiers (idx, inst->opcode->qualifiers_list,
2575 1.1 christos candidates);
2576 1.1 christos #ifdef DEBUG_AARCH64
2577 1.1 christos if (debug_dump)
2578 1.1 christos {
2579 1.1 christos int i;
2580 1.1 christos for (i = 0; candidates[i] != AARCH64_OPND_QLF_NIL
2581 1.1 christos && i < AARCH64_MAX_QLF_SEQ_NUM; ++i)
2582 1.1 christos DEBUG_TRACE ("qualifier %d: %s", i,
2583 1.1 christos aarch64_get_qualifier_name(candidates[i]));
2584 1.1 christos DEBUG_TRACE ("%d, %d", (int)value, (int)mask);
2585 1.1 christos }
2586 1.1 christos #endif /* DEBUG_AARCH64 */
2587 1.1 christos
2588 1.1 christos qualifier = get_qualifier_from_partial_encoding (value, candidates, mask);
2589 1.1 christos
2590 1.1 christos if (qualifier == AARCH64_OPND_QLF_NIL)
2591 1.1 christos return 0;
2592 1.1 christos
2593 1.1 christos inst->operands[idx].qualifier = qualifier;
2594 1.1 christos return 1;
2595 1.1 christos }
2596 1.1 christos
2597 1.1 christos /* Decode size[0]:Q, i.e. bit 22 and bit 30, for
2598 1.1 christos e.g. FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
2599 1.1 christos
2600 1.1 christos static int
2601 1.1 christos decode_asimd_fcvt (aarch64_inst *inst)
2602 1.1 christos {
2603 1.1 christos aarch64_field field = {0, 0};
2604 1.1 christos aarch64_insn value;
2605 1.1 christos enum aarch64_opnd_qualifier qualifier;
2606 1.1 christos
2607 1.1 christos gen_sub_field (FLD_size, 0, 1, &field);
2608 1.1 christos value = extract_field_2 (&field, inst->value, 0);
2609 1.1 christos qualifier = value == 0 ? AARCH64_OPND_QLF_V_4S
2610 1.1 christos : AARCH64_OPND_QLF_V_2D;
2611 1.1 christos switch (inst->opcode->op)
2612 1.1 christos {
2613 1.1 christos case OP_FCVTN:
2614 1.1 christos case OP_FCVTN2:
2615 1.1 christos /* FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
2616 1.1 christos inst->operands[1].qualifier = qualifier;
2617 1.1 christos break;
2618 1.1 christos case OP_FCVTL:
2619 1.1 christos case OP_FCVTL2:
2620 1.1 christos /* FCVTL<Q> <Vd>.<Ta>, <Vn>.<Tb>. */
2621 1.1 christos inst->operands[0].qualifier = qualifier;
2622 1.1 christos break;
2623 1.1 christos default:
2624 1.1 christos return 0;
2625 1.1 christos }
2626 1.1 christos
2627 1.1 christos return 1;
2628 1.1 christos }
2629 1.1 christos
2630 1.1 christos /* Decode size[0], i.e. bit 22, for
2631 1.1 christos e.g. FCVTXN <Vb><d>, <Va><n>. */
2632 1.1 christos
2633 1.1 christos static int
2634 1.1 christos decode_asisd_fcvtxn (aarch64_inst *inst)
2635 1.1 christos {
2636 1.1 christos aarch64_field field = {0, 0};
2637 1.1 christos gen_sub_field (FLD_size, 0, 1, &field);
2638 1.1 christos if (!extract_field_2 (&field, inst->value, 0))
2639 1.1 christos return 0;
2640 1.1 christos inst->operands[0].qualifier = AARCH64_OPND_QLF_S_S;
2641 1.1 christos return 1;
2642 1.1 christos }
2643 1.1 christos
2644 1.1 christos /* Decode the 'opc' field for e.g. FCVT <Dd>, <Sn>. */
2645 1.1 christos static int
2646 1.1 christos decode_fcvt (aarch64_inst *inst)
2647 1.1 christos {
2648 1.1 christos enum aarch64_opnd_qualifier qualifier;
2649 1.1 christos aarch64_insn value;
2650 1.1 christos const aarch64_field field = {15, 2};
2651 1.1 christos
2652 1.1 christos /* opc dstsize */
2653 1.1 christos value = extract_field_2 (&field, inst->value, 0);
2654 1.1 christos switch (value)
2655 1.1 christos {
2656 1.1 christos case 0: qualifier = AARCH64_OPND_QLF_S_S; break;
2657 1.1 christos case 1: qualifier = AARCH64_OPND_QLF_S_D; break;
2658 1.1 christos case 3: qualifier = AARCH64_OPND_QLF_S_H; break;
2659 1.1 christos default: return 0;
2660 1.1 christos }
2661 1.1 christos inst->operands[0].qualifier = qualifier;
2662 1.1 christos
2663 1.1 christos return 1;
2664 1.1 christos }
2665 1.1 christos
2666 1.1 christos /* Do miscellaneous decodings that are not common enough to be driven by
2667 1.1 christos flags. */
2668 1.1 christos
2669 1.6 christos static int
2670 1.1 christos do_misc_decoding (aarch64_inst *inst)
2671 1.1 christos {
2672 1.1 christos unsigned int value;
2673 1.1 christos switch (inst->opcode->op)
2674 1.6 christos {
2675 1.1 christos case OP_FCVT:
2676 1.1 christos return decode_fcvt (inst);
2677 1.1 christos
2678 1.1 christos case OP_FCVTN:
2679 1.1 christos case OP_FCVTN2:
2680 1.6 christos case OP_FCVTL:
2681 1.1 christos case OP_FCVTL2:
2682 1.1 christos return decode_asimd_fcvt (inst);
2683 1.6 christos
2684 1.6 christos case OP_FCVTXN_S:
2685 1.6 christos return decode_asisd_fcvtxn (inst);
2686 1.6 christos
2687 1.6 christos case OP_MOV_P_P:
2688 1.6 christos case OP_MOVS_P_P:
2689 1.6 christos value = extract_field (FLD_SVE_Pn, inst->value, 0);
2690 1.6 christos return (value == extract_field (FLD_SVE_Pm, inst->value, 0)
2691 1.6 christos && value == extract_field (FLD_SVE_Pg4_10, inst->value, 0));
2692 1.6 christos
2693 1.6 christos case OP_MOV_Z_P_Z:
2694 1.6 christos return (extract_field (FLD_SVE_Zd, inst->value, 0)
2695 1.6 christos == extract_field (FLD_SVE_Zm_16, inst->value, 0));
2696 1.6 christos
2697 1.6 christos case OP_MOV_Z_V:
2698 1.6 christos /* Index must be zero. */
2699 1.6 christos value = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_imm5);
2700 1.6 christos return value > 0 && value <= 16 && value == (value & -value);
2701 1.6 christos
2702 1.6 christos case OP_MOV_Z_Z:
2703 1.6 christos return (extract_field (FLD_SVE_Zn, inst->value, 0)
2704 1.6 christos == extract_field (FLD_SVE_Zm_16, inst->value, 0));
2705 1.6 christos
2706 1.6 christos case OP_MOV_Z_Zi:
2707 1.6 christos /* Index must be nonzero. */
2708 1.6 christos value = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_imm5);
2709 1.6 christos return value > 0 && value != (value & -value);
2710 1.6 christos
2711 1.6 christos case OP_MOVM_P_P_P:
2712 1.6 christos return (extract_field (FLD_SVE_Pd, inst->value, 0)
2713 1.6 christos == extract_field (FLD_SVE_Pm, inst->value, 0));
2714 1.6 christos
2715 1.6 christos case OP_MOVZS_P_P_P:
2716 1.6 christos case OP_MOVZ_P_P_P:
2717 1.6 christos return (extract_field (FLD_SVE_Pn, inst->value, 0)
2718 1.6 christos == extract_field (FLD_SVE_Pm, inst->value, 0));
2719 1.6 christos
2720 1.6 christos case OP_NOTS_P_P_P_Z:
2721 1.6 christos case OP_NOT_P_P_P_Z:
2722 1.1 christos return (extract_field (FLD_SVE_Pm, inst->value, 0)
2723 1.1 christos == extract_field (FLD_SVE_Pg4_10, inst->value, 0));
2724 1.1 christos
2725 1.1 christos default:
2726 1.1 christos return 0;
2727 1.1 christos }
2728 1.1 christos }
2729 1.1 christos
2730 1.1 christos /* Opcodes that have fields shared by multiple operands are usually flagged
2731 1.1 christos with flags. In this function, we detect such flags, decode the related
2732 1.1 christos field(s) and store the information in one of the related operands. The
2733 1.1 christos 'one' operand is not any operand but one of the operands that can
2734 1.1 christos accommadate all the information that has been decoded. */
2735 1.1 christos
2736 1.1 christos static int
2737 1.1 christos do_special_decoding (aarch64_inst *inst)
2738 1.1 christos {
2739 1.1 christos int idx;
2740 1.1 christos aarch64_insn value;
2741 1.1 christos /* Condition for truly conditional executed instructions, e.g. b.cond. */
2742 1.1 christos if (inst->opcode->flags & F_COND)
2743 1.1 christos {
2744 1.1 christos value = extract_field (FLD_cond2, inst->value, 0);
2745 1.1 christos inst->cond = get_cond_from_value (value);
2746 1.1 christos }
2747 1.1 christos /* 'sf' field. */
2748 1.1 christos if (inst->opcode->flags & F_SF)
2749 1.10 christos {
2750 1.10 christos idx = select_operand_for_sf_field_coding (inst->opcode);
2751 1.10 christos value = extract_field (FLD_sf, inst->value, 0);
2752 1.10 christos if (inst->opcode->iclass == fprcvtfloat2int
2753 1.10 christos || inst->opcode->iclass == fprcvtint2float)
2754 1.10 christos {
2755 1.10 christos if (value == 0)
2756 1.10 christos inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_S;
2757 1.10 christos else
2758 1.10 christos inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_D;
2759 1.10 christos }
2760 1.10 christos else
2761 1.1 christos inst->operands[idx].qualifier = get_greg_qualifier_from_value (value);
2762 1.1 christos if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR)
2763 1.1 christos return 0;
2764 1.1 christos if ((inst->opcode->flags & F_N)
2765 1.3 christos && extract_field (FLD_N, inst->value, 0) != value)
2766 1.3 christos return 0;
2767 1.3 christos }
2768 1.3 christos /* 'sf' field. */
2769 1.3 christos if (inst->opcode->flags & F_LSE_SZ)
2770 1.3 christos {
2771 1.10 christos idx = select_operand_for_sf_field_coding (inst->opcode);
2772 1.10 christos value = extract_field (FLD_lse_sz, inst->value, 0);
2773 1.3 christos inst->operands[idx].qualifier = get_greg_qualifier_from_value (value);
2774 1.9 christos if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR)
2775 1.9 christos return 0;
2776 1.9 christos }
2777 1.9 christos /* rcpc3 'size' field. */
2778 1.9 christos if (inst->opcode->flags & F_RCPC3_SIZE)
2779 1.9 christos {
2780 1.9 christos value = extract_field (FLD_rcpc3_size, inst->value, 0);
2781 1.9 christos for (int i = 0;
2782 1.9 christos aarch64_operands[inst->operands[i].type].op_class != AARCH64_OPND_CLASS_ADDRESS;
2783 1.9 christos i++)
2784 1.10 christos {
2785 1.10 christos if (aarch64_operands[inst->operands[i].type].op_class
2786 1.10 christos == AARCH64_OPND_CLASS_INT_REG)
2787 1.10 christos {
2788 1.10 christos inst->operands[i].qualifier = get_greg_qualifier_from_value (value & 1);
2789 1.9 christos if (inst->operands[i].qualifier == AARCH64_OPND_QLF_ERR)
2790 1.9 christos return 0;
2791 1.9 christos }
2792 1.9 christos else if (aarch64_operands[inst->operands[i].type].op_class
2793 1.9 christos == AARCH64_OPND_CLASS_FP_REG)
2794 1.10 christos {
2795 1.10 christos value += (extract_field (FLD_opc1, inst->value, 0) << 2);
2796 1.9 christos inst->operands[i].qualifier = get_sreg_qualifier_from_value (value);
2797 1.9 christos if (inst->operands[i].qualifier == AARCH64_OPND_QLF_ERR)
2798 1.9 christos return 0;
2799 1.9 christos }
2800 1.1 christos }
2801 1.1 christos }
2802 1.1 christos
2803 1.1 christos /* size:Q fields. */
2804 1.1 christos if (inst->opcode->flags & F_SIZEQ)
2805 1.1 christos return decode_sizeq (inst);
2806 1.1 christos
2807 1.1 christos if (inst->opcode->flags & F_FPTYPE)
2808 1.1 christos {
2809 1.1 christos idx = select_operand_for_fptype_field_coding (inst->opcode);
2810 1.1 christos value = extract_field (FLD_type, inst->value, 0);
2811 1.1 christos switch (value)
2812 1.1 christos {
2813 1.1 christos case 0: inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_S; break;
2814 1.1 christos case 1: inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_D; break;
2815 1.1 christos case 3: inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_H; break;
2816 1.1 christos default: return 0;
2817 1.1 christos }
2818 1.1 christos }
2819 1.1 christos
2820 1.1 christos if (inst->opcode->flags & F_SSIZE)
2821 1.1 christos {
2822 1.1 christos /* N.B. some opcodes like FCMGT <V><d>, <V><n>, #0 have the size[1] as part
2823 1.1 christos of the base opcode. */
2824 1.1 christos aarch64_insn mask;
2825 1.1 christos enum aarch64_opnd_qualifier candidates[AARCH64_MAX_QLF_SEQ_NUM];
2826 1.1 christos idx = select_operand_for_scalar_size_field_coding (inst->opcode);
2827 1.1 christos value = extract_field (FLD_size, inst->value, inst->opcode->mask);
2828 1.1 christos mask = extract_field (FLD_size, ~inst->opcode->mask, 0);
2829 1.10 christos /* For most related instruciton, the 'size' field is fully available for
2830 1.10 christos operand encoding. */
2831 1.10 christos if (mask == 0x3)
2832 1.10 christos {
2833 1.10 christos inst->operands[idx].qualifier = get_sreg_qualifier_from_value (value);
2834 1.1 christos if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR)
2835 1.1 christos return 0;
2836 1.1 christos }
2837 1.1 christos else
2838 1.1 christos {
2839 1.1 christos get_operand_possible_qualifiers (idx, inst->opcode->qualifiers_list,
2840 1.1 christos candidates);
2841 1.1 christos inst->operands[idx].qualifier
2842 1.1 christos = get_qualifier_from_partial_encoding (value, candidates, mask);
2843 1.10 christos }
2844 1.10 christos }
2845 1.10 christos
2846 1.10 christos if (inst->opcode->flags & F_LSFE_SZ)
2847 1.10 christos {
2848 1.10 christos value = extract_field (FLD_ldst_size, inst->value, 0);
2849 1.10 christos
2850 1.10 christos if (value > 0x3)
2851 1.10 christos return 0;
2852 1.10 christos
2853 1.10 christos for (int i = 0;
2854 1.10 christos aarch64_operands[inst->operands[i].type].op_class != AARCH64_OPND_CLASS_ADDRESS;
2855 1.10 christos i++)
2856 1.10 christos {
2857 1.10 christos inst->operands[i].qualifier = get_sreg_qualifier_from_value (value);
2858 1.10 christos if (inst->operands[i].qualifier == AARCH64_OPND_QLF_ERR)
2859 1.10 christos return 0;
2860 1.1 christos }
2861 1.1 christos }
2862 1.1 christos
2863 1.1 christos if (inst->opcode->flags & F_T)
2864 1.1 christos {
2865 1.1 christos /* Num of consecutive '0's on the right side of imm5<3:0>. */
2866 1.1 christos int num = 0;
2867 1.1 christos unsigned val, Q;
2868 1.1 christos assert (aarch64_get_operand_class (inst->opcode->operands[0])
2869 1.1 christos == AARCH64_OPND_CLASS_SIMD_REG);
2870 1.1 christos /* imm5<3:0> q <t>
2871 1.1 christos 0000 x reserved
2872 1.1 christos xxx1 0 8b
2873 1.1 christos xxx1 1 16b
2874 1.1 christos xx10 0 4h
2875 1.1 christos xx10 1 8h
2876 1.1 christos x100 0 2s
2877 1.1 christos x100 1 4s
2878 1.1 christos 1000 0 reserved
2879 1.1 christos 1000 1 2d */
2880 1.1 christos val = extract_field (FLD_imm5, inst->value, 0);
2881 1.1 christos while ((val & 0x1) == 0 && ++num <= 3)
2882 1.1 christos val >>= 1;
2883 1.1 christos if (num > 3)
2884 1.1 christos return 0;
2885 1.10 christos Q = (unsigned) extract_field (FLD_Q, inst->value, inst->opcode->mask);
2886 1.10 christos inst->operands[0].qualifier =
2887 1.10 christos get_vreg_qualifier_from_value ((num << 1) | Q);
2888 1.1 christos if (inst->operands[0].qualifier == AARCH64_OPND_QLF_ERR)
2889 1.1 christos return 0;
2890 1.9 christos
2891 1.9 christos }
2892 1.9 christos
2893 1.9 christos if ((inst->opcode->flags & F_OPD_SIZE) && inst->opcode->iclass == sve2_urqvs)
2894 1.9 christos {
2895 1.9 christos unsigned size;
2896 1.9 christos size = (unsigned) extract_field (FLD_size, inst->value,
2897 1.10 christos inst->opcode->mask);
2898 1.10 christos inst->operands[0].qualifier
2899 1.9 christos = get_vreg_qualifier_from_value (1 + (size << 1));
2900 1.10 christos if (inst->operands[0].qualifier == AARCH64_OPND_QLF_ERR)
2901 1.10 christos return 0;
2902 1.9 christos inst->operands[2].qualifier = get_sreg_qualifier_from_value (size);
2903 1.9 christos if (inst->operands[2].qualifier == AARCH64_OPND_QLF_ERR)
2904 1.1 christos return 0;
2905 1.1 christos }
2906 1.1 christos
2907 1.1 christos if (inst->opcode->flags & F_GPRSIZE_IN_Q)
2908 1.1 christos {
2909 1.1 christos /* Use Rt to encode in the case of e.g.
2910 1.1 christos STXP <Ws>, <Xt1>, <Xt2>, [<Xn|SP>{,#0}]. */
2911 1.1 christos idx = aarch64_operand_index (inst->opcode->operands, AARCH64_OPND_Rt);
2912 1.1 christos if (idx == -1)
2913 1.1 christos {
2914 1.1 christos /* Otherwise use the result operand, which has to be a integer
2915 1.1 christos register. */
2916 1.1 christos assert (aarch64_get_operand_class (inst->opcode->operands[0])
2917 1.1 christos == AARCH64_OPND_CLASS_INT_REG);
2918 1.1 christos idx = 0;
2919 1.1 christos }
2920 1.10 christos assert (idx == 0 || idx == 1);
2921 1.10 christos value = extract_field (FLD_Q, inst->value, 0);
2922 1.1 christos inst->operands[idx].qualifier = get_greg_qualifier_from_value (value);
2923 1.1 christos if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR)
2924 1.1 christos return 0;
2925 1.1 christos }
2926 1.1 christos
2927 1.1 christos if (inst->opcode->flags & F_LDS_SIZE)
2928 1.1 christos {
2929 1.1 christos aarch64_field field = {0, 0};
2930 1.1 christos assert (aarch64_get_operand_class (inst->opcode->operands[0])
2931 1.1 christos == AARCH64_OPND_CLASS_INT_REG);
2932 1.1 christos gen_sub_field (FLD_opc, 0, 1, &field);
2933 1.1 christos value = extract_field_2 (&field, inst->value, 0);
2934 1.1 christos inst->operands[0].qualifier
2935 1.1 christos = value ? AARCH64_OPND_QLF_W : AARCH64_OPND_QLF_X;
2936 1.1 christos }
2937 1.1 christos
2938 1.1 christos /* Miscellaneous decoding; done as the last step. */
2939 1.1 christos if (inst->opcode->flags & F_MISC)
2940 1.1 christos return do_misc_decoding (inst);
2941 1.1 christos
2942 1.1 christos return 1;
2943 1.1 christos }
2944 1.1 christos
2945 1.1 christos /* Converters converting a real opcode instruction to its alias form. */
2946 1.1 christos
2947 1.1 christos /* ROR <Wd>, <Ws>, #<shift>
2948 1.1 christos is equivalent to:
2949 1.1 christos EXTR <Wd>, <Ws>, <Ws>, #<shift>. */
2950 1.1 christos static int
2951 1.1 christos convert_extr_to_ror (aarch64_inst *inst)
2952 1.1 christos {
2953 1.1 christos if (inst->operands[1].reg.regno == inst->operands[2].reg.regno)
2954 1.1 christos {
2955 1.1 christos copy_operand_info (inst, 2, 3);
2956 1.1 christos inst->operands[3].type = AARCH64_OPND_NIL;
2957 1.1 christos return 1;
2958 1.1 christos }
2959 1.1 christos return 0;
2960 1.1 christos }
2961 1.1 christos
2962 1.1 christos /* UXTL<Q> <Vd>.<Ta>, <Vn>.<Tb>
2963 1.1 christos is equivalent to:
2964 1.1 christos USHLL<Q> <Vd>.<Ta>, <Vn>.<Tb>, #0. */
2965 1.1 christos static int
2966 1.1 christos convert_shll_to_xtl (aarch64_inst *inst)
2967 1.1 christos {
2968 1.1 christos if (inst->operands[2].imm.value == 0)
2969 1.1 christos {
2970 1.1 christos inst->operands[2].type = AARCH64_OPND_NIL;
2971 1.1 christos return 1;
2972 1.1 christos }
2973 1.1 christos return 0;
2974 1.1 christos }
2975 1.1 christos
2976 1.1 christos /* Convert
2977 1.1 christos UBFM <Xd>, <Xn>, #<shift>, #63.
2978 1.1 christos to
2979 1.1 christos LSR <Xd>, <Xn>, #<shift>. */
2980 1.1 christos static int
2981 1.1 christos convert_bfm_to_sr (aarch64_inst *inst)
2982 1.1 christos {
2983 1.1 christos int64_t imms, val;
2984 1.1 christos
2985 1.1 christos imms = inst->operands[3].imm.value;
2986 1.1 christos val = inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 31 : 63;
2987 1.1 christos if (imms == val)
2988 1.1 christos {
2989 1.1 christos inst->operands[3].type = AARCH64_OPND_NIL;
2990 1.1 christos return 1;
2991 1.1 christos }
2992 1.1 christos
2993 1.1 christos return 0;
2994 1.1 christos }
2995 1.1 christos
2996 1.1 christos /* Convert MOV to ORR. */
2997 1.1 christos static int
2998 1.1 christos convert_orr_to_mov (aarch64_inst *inst)
2999 1.1 christos {
3000 1.1 christos /* MOV <Vd>.<T>, <Vn>.<T>
3001 1.1 christos is equivalent to:
3002 1.1 christos ORR <Vd>.<T>, <Vn>.<T>, <Vn>.<T>. */
3003 1.1 christos if (inst->operands[1].reg.regno == inst->operands[2].reg.regno)
3004 1.1 christos {
3005 1.1 christos inst->operands[2].type = AARCH64_OPND_NIL;
3006 1.1 christos return 1;
3007 1.1 christos }
3008 1.1 christos return 0;
3009 1.1 christos }
3010 1.1 christos
3011 1.1 christos /* When <imms> >= <immr>, the instruction written:
3012 1.1 christos SBFX <Xd>, <Xn>, #<lsb>, #<width>
3013 1.1 christos is equivalent to:
3014 1.1 christos SBFM <Xd>, <Xn>, #<lsb>, #(<lsb>+<width>-1). */
3015 1.1 christos
3016 1.1 christos static int
3017 1.1 christos convert_bfm_to_bfx (aarch64_inst *inst)
3018 1.1 christos {
3019 1.1 christos int64_t immr, imms;
3020 1.1 christos
3021 1.1 christos immr = inst->operands[2].imm.value;
3022 1.1 christos imms = inst->operands[3].imm.value;
3023 1.1 christos if (imms >= immr)
3024 1.1 christos {
3025 1.1 christos int64_t lsb = immr;
3026 1.1 christos inst->operands[2].imm.value = lsb;
3027 1.1 christos inst->operands[3].imm.value = imms + 1 - lsb;
3028 1.1 christos /* The two opcodes have different qualifiers for
3029 1.1 christos the immediate operands; reset to help the checking. */
3030 1.1 christos reset_operand_qualifier (inst, 2);
3031 1.1 christos reset_operand_qualifier (inst, 3);
3032 1.1 christos return 1;
3033 1.1 christos }
3034 1.1 christos
3035 1.1 christos return 0;
3036 1.1 christos }
3037 1.1 christos
3038 1.1 christos /* When <imms> < <immr>, the instruction written:
3039 1.1 christos SBFIZ <Xd>, <Xn>, #<lsb>, #<width>
3040 1.1 christos is equivalent to:
3041 1.1 christos SBFM <Xd>, <Xn>, #((64-<lsb>)&0x3f), #(<width>-1). */
3042 1.1 christos
3043 1.1 christos static int
3044 1.1 christos convert_bfm_to_bfi (aarch64_inst *inst)
3045 1.1 christos {
3046 1.1 christos int64_t immr, imms, val;
3047 1.1 christos
3048 1.1 christos immr = inst->operands[2].imm.value;
3049 1.1 christos imms = inst->operands[3].imm.value;
3050 1.1 christos val = inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 32 : 64;
3051 1.1 christos if (imms < immr)
3052 1.1 christos {
3053 1.1 christos inst->operands[2].imm.value = (val - immr) & (val - 1);
3054 1.1 christos inst->operands[3].imm.value = imms + 1;
3055 1.1 christos /* The two opcodes have different qualifiers for
3056 1.1 christos the immediate operands; reset to help the checking. */
3057 1.1 christos reset_operand_qualifier (inst, 2);
3058 1.1 christos reset_operand_qualifier (inst, 3);
3059 1.1 christos return 1;
3060 1.1 christos }
3061 1.1 christos
3062 1.1 christos return 0;
3063 1.3 christos }
3064 1.3 christos
3065 1.3 christos /* The instruction written:
3066 1.3 christos BFC <Xd>, #<lsb>, #<width>
3067 1.3 christos is equivalent to:
3068 1.3 christos BFM <Xd>, XZR, #((64-<lsb>)&0x3f), #(<width>-1). */
3069 1.3 christos
3070 1.3 christos static int
3071 1.3 christos convert_bfm_to_bfc (aarch64_inst *inst)
3072 1.3 christos {
3073 1.3 christos int64_t immr, imms, val;
3074 1.3 christos
3075 1.3 christos /* Should have been assured by the base opcode value. */
3076 1.3 christos assert (inst->operands[1].reg.regno == 0x1f);
3077 1.3 christos
3078 1.3 christos immr = inst->operands[2].imm.value;
3079 1.3 christos imms = inst->operands[3].imm.value;
3080 1.3 christos val = inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 32 : 64;
3081 1.3 christos if (imms < immr)
3082 1.3 christos {
3083 1.3 christos /* Drop XZR from the second operand. */
3084 1.3 christos copy_operand_info (inst, 1, 2);
3085 1.3 christos copy_operand_info (inst, 2, 3);
3086 1.3 christos inst->operands[3].type = AARCH64_OPND_NIL;
3087 1.3 christos
3088 1.3 christos /* Recalculate the immediates. */
3089 1.3 christos inst->operands[1].imm.value = (val - immr) & (val - 1);
3090 1.3 christos inst->operands[2].imm.value = imms + 1;
3091 1.3 christos
3092 1.3 christos /* The two opcodes have different qualifiers for the operands; reset to
3093 1.3 christos help the checking. */
3094 1.3 christos reset_operand_qualifier (inst, 1);
3095 1.3 christos reset_operand_qualifier (inst, 2);
3096 1.3 christos reset_operand_qualifier (inst, 3);
3097 1.3 christos
3098 1.3 christos return 1;
3099 1.3 christos }
3100 1.3 christos
3101 1.3 christos return 0;
3102 1.1 christos }
3103 1.1 christos
3104 1.1 christos /* The instruction written:
3105 1.1 christos LSL <Xd>, <Xn>, #<shift>
3106 1.1 christos is equivalent to:
3107 1.1 christos UBFM <Xd>, <Xn>, #((64-<shift>)&0x3f), #(63-<shift>). */
3108 1.1 christos
3109 1.1 christos static int
3110 1.1 christos convert_ubfm_to_lsl (aarch64_inst *inst)
3111 1.1 christos {
3112 1.1 christos int64_t immr = inst->operands[2].imm.value;
3113 1.1 christos int64_t imms = inst->operands[3].imm.value;
3114 1.1 christos int64_t val
3115 1.1 christos = inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 31 : 63;
3116 1.1 christos
3117 1.1 christos if ((immr == 0 && imms == val) || immr == imms + 1)
3118 1.1 christos {
3119 1.1 christos inst->operands[3].type = AARCH64_OPND_NIL;
3120 1.1 christos inst->operands[2].imm.value = val - imms;
3121 1.1 christos return 1;
3122 1.1 christos }
3123 1.1 christos
3124 1.1 christos return 0;
3125 1.1 christos }
3126 1.3 christos
3127 1.3 christos /* CINC <Wd>, <Wn>, <cond>
3128 1.1 christos is equivalent to:
3129 1.1 christos CSINC <Wd>, <Wn>, <Wn>, invert(<cond>)
3130 1.1 christos where <cond> is not AL or NV. */
3131 1.1 christos
3132 1.3 christos static int
3133 1.3 christos convert_from_csel (aarch64_inst *inst)
3134 1.1 christos {
3135 1.1 christos if (inst->operands[1].reg.regno == inst->operands[2].reg.regno
3136 1.1 christos && (inst->operands[3].cond->value & 0xe) != 0xe)
3137 1.1 christos {
3138 1.1 christos copy_operand_info (inst, 2, 3);
3139 1.1 christos inst->operands[2].cond = get_inverted_cond (inst->operands[3].cond);
3140 1.1 christos inst->operands[3].type = AARCH64_OPND_NIL;
3141 1.1 christos return 1;
3142 1.1 christos }
3143 1.1 christos return 0;
3144 1.1 christos }
3145 1.3 christos
3146 1.3 christos /* CSET <Wd>, <cond>
3147 1.1 christos is equivalent to:
3148 1.1 christos CSINC <Wd>, WZR, WZR, invert(<cond>)
3149 1.1 christos where <cond> is not AL or NV. */
3150 1.1 christos
3151 1.1 christos static int
3152 1.3 christos convert_csinc_to_cset (aarch64_inst *inst)
3153 1.3 christos {
3154 1.1 christos if (inst->operands[1].reg.regno == 0x1f
3155 1.1 christos && inst->operands[2].reg.regno == 0x1f
3156 1.1 christos && (inst->operands[3].cond->value & 0xe) != 0xe)
3157 1.1 christos {
3158 1.1 christos copy_operand_info (inst, 1, 3);
3159 1.1 christos inst->operands[1].cond = get_inverted_cond (inst->operands[3].cond);
3160 1.1 christos inst->operands[3].type = AARCH64_OPND_NIL;
3161 1.1 christos inst->operands[2].type = AARCH64_OPND_NIL;
3162 1.1 christos return 1;
3163 1.1 christos }
3164 1.1 christos return 0;
3165 1.1 christos }
3166 1.9 christos
3167 1.1 christos /* MOV <Wd>, #<imm>
3168 1.1 christos is equivalent to:
3169 1.1 christos MOVZ <Wd>, #<imm16_5>, LSL #<shift>.
3170 1.1 christos
3171 1.1 christos A disassembler may output ORR, MOVZ and MOVN as a MOV mnemonic, except when
3172 1.1 christos ORR has an immediate that could be generated by a MOVZ or MOVN instruction,
3173 1.1 christos or where a MOVN has an immediate that could be encoded by MOVZ, or where
3174 1.1 christos MOVZ/MOVN #0 have a shift amount other than LSL #0, in which case the
3175 1.1 christos machine-instruction mnemonic must be used. */
3176 1.1 christos
3177 1.1 christos static int
3178 1.1 christos convert_movewide_to_mov (aarch64_inst *inst)
3179 1.1 christos {
3180 1.1 christos uint64_t value = inst->operands[1].imm.value;
3181 1.1 christos /* MOVZ/MOVN #0 have a shift amount other than LSL #0. */
3182 1.1 christos if (value == 0 && inst->operands[1].shifter.amount != 0)
3183 1.1 christos return 0;
3184 1.1 christos inst->operands[1].type = AARCH64_OPND_IMM_MOV;
3185 1.1 christos inst->operands[1].shifter.kind = AARCH64_MOD_NONE;
3186 1.1 christos value <<= inst->operands[1].shifter.amount;
3187 1.1 christos /* As an alias convertor, it has to be clear that the INST->OPCODE
3188 1.1 christos is the opcode of the real instruction. */
3189 1.1 christos if (inst->opcode->op == OP_MOVN)
3190 1.1 christos {
3191 1.6 christos int is32 = inst->operands[0].qualifier == AARCH64_OPND_QLF_W;
3192 1.1 christos value = ~value;
3193 1.1 christos /* A MOVN has an immediate that could be encoded by MOVZ. */
3194 1.1 christos if (aarch64_wide_constant_p (value, is32, NULL))
3195 1.1 christos return 0;
3196 1.1 christos }
3197 1.1 christos inst->operands[1].imm.value = value;
3198 1.1 christos inst->operands[1].shifter.amount = 0;
3199 1.1 christos return 1;
3200 1.1 christos }
3201 1.1 christos
3202 1.1 christos /* MOV <Wd>, #<imm>
3203 1.1 christos is equivalent to:
3204 1.1 christos ORR <Wd>, WZR, #<imm>.
3205 1.1 christos
3206 1.1 christos A disassembler may output ORR, MOVZ and MOVN as a MOV mnemonic, except when
3207 1.1 christos ORR has an immediate that could be generated by a MOVZ or MOVN instruction,
3208 1.1 christos or where a MOVN has an immediate that could be encoded by MOVZ, or where
3209 1.1 christos MOVZ/MOVN #0 have a shift amount other than LSL #0, in which case the
3210 1.1 christos machine-instruction mnemonic must be used. */
3211 1.1 christos
3212 1.1 christos static int
3213 1.1 christos convert_movebitmask_to_mov (aarch64_inst *inst)
3214 1.1 christos {
3215 1.1 christos int is32;
3216 1.1 christos uint64_t value;
3217 1.1 christos
3218 1.1 christos /* Should have been assured by the base opcode value. */
3219 1.1 christos assert (inst->operands[1].reg.regno == 0x1f);
3220 1.1 christos copy_operand_info (inst, 1, 2);
3221 1.1 christos is32 = inst->operands[0].qualifier == AARCH64_OPND_QLF_W;
3222 1.1 christos inst->operands[1].type = AARCH64_OPND_IMM_MOV;
3223 1.1 christos value = inst->operands[1].imm.value;
3224 1.6 christos /* ORR has an immediate that could be generated by a MOVZ or MOVN
3225 1.6 christos instruction. */
3226 1.1 christos if (inst->operands[0].reg.regno != 0x1f
3227 1.1 christos && (aarch64_wide_constant_p (value, is32, NULL)
3228 1.1 christos || aarch64_wide_constant_p (~value, is32, NULL)))
3229 1.1 christos return 0;
3230 1.1 christos
3231 1.1 christos inst->operands[2].type = AARCH64_OPND_NIL;
3232 1.1 christos return 1;
3233 1.1 christos }
3234 1.1 christos
3235 1.1 christos /* Some alias opcodes are disassembled by being converted from their real-form.
3236 1.1 christos N.B. INST->OPCODE is the real opcode rather than the alias. */
3237 1.1 christos
3238 1.1 christos static int
3239 1.1 christos convert_to_alias (aarch64_inst *inst, const aarch64_opcode *alias)
3240 1.1 christos {
3241 1.1 christos switch (alias->op)
3242 1.1 christos {
3243 1.1 christos case OP_ASR_IMM:
3244 1.1 christos case OP_LSR_IMM:
3245 1.1 christos return convert_bfm_to_sr (inst);
3246 1.1 christos case OP_LSL_IMM:
3247 1.1 christos return convert_ubfm_to_lsl (inst);
3248 1.1 christos case OP_CINC:
3249 1.1 christos case OP_CINV:
3250 1.1 christos case OP_CNEG:
3251 1.1 christos return convert_from_csel (inst);
3252 1.1 christos case OP_CSET:
3253 1.1 christos case OP_CSETM:
3254 1.1 christos return convert_csinc_to_cset (inst);
3255 1.1 christos case OP_UBFX:
3256 1.1 christos case OP_BFXIL:
3257 1.1 christos case OP_SBFX:
3258 1.1 christos return convert_bfm_to_bfx (inst);
3259 1.1 christos case OP_SBFIZ:
3260 1.3 christos case OP_BFI:
3261 1.3 christos case OP_UBFIZ:
3262 1.1 christos return convert_bfm_to_bfi (inst);
3263 1.1 christos case OP_BFC:
3264 1.1 christos return convert_bfm_to_bfc (inst);
3265 1.1 christos case OP_MOV_V:
3266 1.1 christos return convert_orr_to_mov (inst);
3267 1.1 christos case OP_MOV_IMM_WIDE:
3268 1.1 christos case OP_MOV_IMM_WIDEN:
3269 1.1 christos return convert_movewide_to_mov (inst);
3270 1.1 christos case OP_MOV_IMM_LOG:
3271 1.1 christos return convert_movebitmask_to_mov (inst);
3272 1.1 christos case OP_ROR_IMM:
3273 1.1 christos return convert_extr_to_ror (inst);
3274 1.1 christos case OP_SXTL:
3275 1.1 christos case OP_SXTL2:
3276 1.1 christos case OP_UXTL:
3277 1.1 christos case OP_UXTL2:
3278 1.1 christos return convert_shll_to_xtl (inst);
3279 1.1 christos default:
3280 1.1 christos return 0;
3281 1.8 christos }
3282 1.6 christos }
3283 1.6 christos
3284 1.1 christos static bool
3285 1.1 christos aarch64_opcode_decode (const aarch64_opcode *, const aarch64_insn,
3286 1.1 christos aarch64_inst *, int, aarch64_operand_error *errors);
3287 1.1 christos
3288 1.1 christos /* Given the instruction information in *INST, check if the instruction has
3289 1.1 christos any alias form that can be used to represent *INST. If the answer is yes,
3290 1.1 christos update *INST to be in the form of the determined alias. */
3291 1.1 christos
3292 1.1 christos /* In the opcode description table, the following flags are used in opcode
3293 1.1 christos entries to help establish the relations between the real and alias opcodes:
3294 1.1 christos
3295 1.1 christos F_ALIAS: opcode is an alias
3296 1.1 christos F_HAS_ALIAS: opcode has alias(es)
3297 1.1 christos F_P1
3298 1.1 christos F_P2
3299 1.1 christos F_P3: Disassembly preference priority 1-3 (the larger the
3300 1.1 christos higher). If nothing is specified, it is the priority
3301 1.1 christos 0 by default, i.e. the lowest priority.
3302 1.1 christos
3303 1.1 christos Although the relation between the machine and the alias instructions are not
3304 1.1 christos explicitly described, it can be easily determined from the base opcode
3305 1.1 christos values, masks and the flags F_ALIAS and F_HAS_ALIAS in their opcode
3306 1.1 christos description entries:
3307 1.1 christos
3308 1.1 christos The mask of an alias opcode must be equal to or a super-set (i.e. more
3309 1.1 christos constrained) of that of the aliased opcode; so is the base opcode value.
3310 1.1 christos
3311 1.1 christos if (opcode_has_alias (real) && alias_opcode_p (opcode)
3312 1.1 christos && (opcode->mask & real->mask) == real->mask
3313 1.1 christos && (real->mask & opcode->opcode) == (real->mask & real->opcode))
3314 1.1 christos then OPCODE is an alias of, and only of, the REAL instruction
3315 1.1 christos
3316 1.1 christos The alias relationship is forced flat-structured to keep related algorithm
3317 1.1 christos simple; an opcode entry cannot be flagged with both F_ALIAS and F_HAS_ALIAS.
3318 1.1 christos
3319 1.1 christos During the disassembling, the decoding decision tree (in
3320 1.1 christos opcodes/aarch64-dis-2.c) always returns an machine instruction opcode entry;
3321 1.1 christos if the decoding of such a machine instruction succeeds (and -Mno-aliases is
3322 1.1 christos not specified), the disassembler will check whether there is any alias
3323 1.1 christos instruction exists for this real instruction. If there is, the disassembler
3324 1.1 christos will try to disassemble the 32-bit binary again using the alias's rule, or
3325 1.1 christos try to convert the IR to the form of the alias. In the case of the multiple
3326 1.1 christos aliases, the aliases are tried one by one from the highest priority
3327 1.1 christos (currently the flag F_P3) to the lowest priority (no priority flag), and the
3328 1.1 christos first succeeds first adopted.
3329 1.1 christos
3330 1.1 christos You may ask why there is a need for the conversion of IR from one form to
3331 1.1 christos another in handling certain aliases. This is because on one hand it avoids
3332 1.1 christos adding more operand code to handle unusual encoding/decoding; on other
3333 1.1 christos hand, during the disassembling, the conversion is an effective approach to
3334 1.1 christos check the condition of an alias (as an alias may be adopted only if certain
3335 1.1 christos conditions are met).
3336 1.1 christos
3337 1.1 christos In order to speed up the alias opcode lookup, aarch64-gen has preprocessed
3338 1.1 christos aarch64_opcode_table and generated aarch64_find_alias_opcode and
3339 1.6 christos aarch64_find_next_alias_opcode (in opcodes/aarch64-dis-2.c) to help. */
3340 1.6 christos
3341 1.1 christos static void
3342 1.1 christos determine_disassembling_preference (struct aarch64_inst *inst,
3343 1.1 christos aarch64_operand_error *errors)
3344 1.1 christos {
3345 1.1 christos const aarch64_opcode *opcode;
3346 1.1 christos const aarch64_opcode *alias;
3347 1.1 christos
3348 1.6 christos opcode = inst->opcode;
3349 1.1 christos
3350 1.1 christos /* This opcode does not have an alias, so use itself. */
3351 1.1 christos if (!opcode_has_alias (opcode))
3352 1.1 christos return;
3353 1.1 christos
3354 1.1 christos alias = aarch64_find_alias_opcode (opcode);
3355 1.1 christos assert (alias);
3356 1.1 christos
3357 1.1 christos #ifdef DEBUG_AARCH64
3358 1.1 christos if (debug_dump)
3359 1.1 christos {
3360 1.1 christos const aarch64_opcode *tmp = alias;
3361 1.1 christos printf ("#### LIST orderd: ");
3362 1.1 christos while (tmp)
3363 1.1 christos {
3364 1.1 christos printf ("%s, ", tmp->name);
3365 1.1 christos tmp = aarch64_find_next_alias_opcode (tmp);
3366 1.1 christos }
3367 1.1 christos printf ("\n");
3368 1.1 christos }
3369 1.1 christos #endif /* DEBUG_AARCH64 */
3370 1.1 christos
3371 1.3 christos for (; alias; alias = aarch64_find_next_alias_opcode (alias))
3372 1.1 christos {
3373 1.1 christos DEBUG_TRACE ("try %s", alias->name);
3374 1.1 christos assert (alias_opcode_p (alias) || opcode_has_alias (opcode));
3375 1.1 christos
3376 1.1 christos /* An alias can be a pseudo opcode which will never be used in the
3377 1.1 christos disassembly, e.g. BIC logical immediate is such a pseudo opcode
3378 1.1 christos aliasing AND. */
3379 1.1 christos if (pseudo_opcode_p (alias))
3380 1.1 christos {
3381 1.1 christos DEBUG_TRACE ("skip pseudo %s", alias->name);
3382 1.1 christos continue;
3383 1.1 christos }
3384 1.1 christos
3385 1.1 christos if ((inst->value & alias->mask) != alias->opcode)
3386 1.1 christos {
3387 1.8 christos DEBUG_TRACE ("skip %s as base opcode not match", alias->name);
3388 1.9 christos continue;
3389 1.8 christos }
3390 1.8 christos
3391 1.8 christos if (!AARCH64_CPU_HAS_ALL_FEATURES (arch_variant, *alias->avariant))
3392 1.8 christos {
3393 1.8 christos DEBUG_TRACE ("skip %s: we're missing features", alias->name);
3394 1.1 christos continue;
3395 1.1 christos }
3396 1.1 christos
3397 1.1 christos /* No need to do any complicated transformation on operands, if the alias
3398 1.1 christos opcode does not have any operand. */
3399 1.1 christos if (aarch64_num_of_operands (alias) == 0 && alias->opcode == inst->value)
3400 1.1 christos {
3401 1.1 christos DEBUG_TRACE ("succeed with 0-operand opcode %s", alias->name);
3402 1.1 christos aarch64_replace_opcode (inst, alias);
3403 1.1 christos return;
3404 1.1 christos }
3405 1.1 christos if (alias->flags & F_CONV)
3406 1.1 christos {
3407 1.1 christos aarch64_inst copy;
3408 1.1 christos memcpy (©, inst, sizeof (aarch64_inst));
3409 1.1 christos /* ALIAS is the preference as long as the instruction can be
3410 1.1 christos successfully converted to the form of ALIAS. */
3411 1.8 christos if (convert_to_alias (©, alias) == 1)
3412 1.8 christos {
3413 1.8 christos aarch64_replace_opcode (©, alias);
3414 1.8 christos if (aarch64_match_operands_constraint (©, NULL) != 1)
3415 1.8 christos {
3416 1.8 christos DEBUG_TRACE ("FAILED with alias %s ", alias->name);
3417 1.8 christos }
3418 1.8 christos else
3419 1.8 christos {
3420 1.1 christos DEBUG_TRACE ("succeed with %s via conversion", alias->name);
3421 1.1 christos memcpy (inst, ©, sizeof (aarch64_inst));
3422 1.1 christos }
3423 1.1 christos return;
3424 1.1 christos }
3425 1.1 christos }
3426 1.1 christos else
3427 1.1 christos {
3428 1.6 christos /* Directly decode the alias opcode. */
3429 1.1 christos aarch64_inst temp;
3430 1.1 christos memset (&temp, '\0', sizeof (aarch64_inst));
3431 1.1 christos if (aarch64_opcode_decode (alias, inst->value, &temp, 1, errors) == 1)
3432 1.1 christos {
3433 1.1 christos DEBUG_TRACE ("succeed with %s via direct decoding", alias->name);
3434 1.1 christos memcpy (inst, &temp, sizeof (aarch64_inst));
3435 1.1 christos return;
3436 1.1 christos }
3437 1.1 christos }
3438 1.6 christos }
3439 1.6 christos }
3440 1.6 christos
3441 1.6 christos /* Some instructions (including all SVE ones) use the instruction class
3442 1.6 christos to describe how a qualifiers_list index is represented in the instruction
3443 1.6 christos encoding. If INST is such an instruction, decode the appropriate fields
3444 1.8 christos and fill in the operand qualifiers accordingly. Return true if no
3445 1.6 christos problems are found. */
3446 1.6 christos
3447 1.6 christos static bool
3448 1.6 christos aarch64_decode_variant_using_iclass (aarch64_inst *inst)
3449 1.6 christos {
3450 1.6 christos int i, variant;
3451 1.6 christos
3452 1.9 christos variant = 0;
3453 1.9 christos switch (inst->opcode->iclass)
3454 1.9 christos {
3455 1.9 christos case sme_mov:
3456 1.9 christos variant = extract_fields (inst->value, 0, 2, FLD_SME_Q, FLD_SME_size_22);
3457 1.9 christos if (variant >= 4 && variant < 7)
3458 1.9 christos return false;
3459 1.9 christos if (variant == 7)
3460 1.9 christos variant = 4;
3461 1.9 christos break;
3462 1.9 christos
3463 1.9 christos case sme_psel:
3464 1.9 christos i = extract_fields (inst->value, 0, 2, FLD_SME_tszh, FLD_SME_tszl);
3465 1.9 christos if (i == 0)
3466 1.9 christos return false;
3467 1.9 christos while ((i & 1) == 0)
3468 1.9 christos {
3469 1.9 christos i >>= 1;
3470 1.9 christos variant += 1;
3471 1.9 christos }
3472 1.9 christos break;
3473 1.9 christos
3474 1.9 christos case sme_shift:
3475 1.10 christos i = extract_field (FLD_SVE_tszh, inst->value, 0);
3476 1.10 christos goto sve_shift;
3477 1.10 christos
3478 1.10 christos case sme_size_12_bh:
3479 1.10 christos variant = extract_field (FLD_S, inst->value, 0);
3480 1.10 christos if (variant > 1)
3481 1.9 christos return false;
3482 1.9 christos break;
3483 1.9 christos
3484 1.9 christos case sme_size_12_bhs:
3485 1.9 christos variant = extract_field (FLD_SME_size_12, inst->value, 0);
3486 1.9 christos if (variant >= 3)
3487 1.9 christos return false;
3488 1.9 christos break;
3489 1.9 christos
3490 1.9 christos case sme_size_12_hs:
3491 1.9 christos variant = extract_field (FLD_SME_size_12, inst->value, 0);
3492 1.9 christos if (variant != 1 && variant != 2)
3493 1.9 christos return false;
3494 1.10 christos variant -= 1;
3495 1.10 christos break;
3496 1.10 christos
3497 1.10 christos case sme_size_12_b:
3498 1.10 christos variant = extract_field (FLD_SME_size_12, inst->value, 0);
3499 1.10 christos if (variant != 0)
3500 1.9 christos return false;
3501 1.9 christos break;
3502 1.9 christos
3503 1.9 christos case sme_size_22:
3504 1.9 christos variant = extract_field (FLD_SME_size_22, inst->value, 0);
3505 1.9 christos break;
3506 1.9 christos
3507 1.9 christos case sme_size_22_hsd:
3508 1.9 christos variant = extract_field (FLD_SME_size_22, inst->value, 0);
3509 1.9 christos if (variant < 1)
3510 1.9 christos return false;
3511 1.9 christos variant -= 1;
3512 1.9 christos break;
3513 1.9 christos
3514 1.9 christos case sme_sz_23:
3515 1.6 christos variant = extract_field (FLD_SME_sz_23, inst->value, 0);
3516 1.6 christos break;
3517 1.6 christos
3518 1.6 christos case sve_cpy:
3519 1.6 christos variant = extract_fields (inst->value, 0, 2, FLD_size, FLD_SVE_M_14);
3520 1.10 christos break;
3521 1.10 christos
3522 1.6 christos case sve_index:
3523 1.8 christos i = extract_field (FLD_imm5, inst->value, 0);
3524 1.6 christos
3525 1.6 christos if ((i & 31) == 0)
3526 1.6 christos return false;
3527 1.6 christos while ((i & 1) == 0)
3528 1.6 christos {
3529 1.6 christos i >>= 1;
3530 1.6 christos variant += 1;
3531 1.6 christos }
3532 1.6 christos break;
3533 1.6 christos
3534 1.6 christos case sve_limm:
3535 1.6 christos /* Pick the smallest applicable element size. */
3536 1.6 christos if ((inst->value & 0x20600) == 0x600)
3537 1.6 christos variant = 0;
3538 1.6 christos else if ((inst->value & 0x20400) == 0x400)
3539 1.6 christos variant = 1;
3540 1.6 christos else if ((inst->value & 0x20000) == 0)
3541 1.6 christos variant = 2;
3542 1.6 christos else
3543 1.9 christos variant = 3;
3544 1.9 christos break;
3545 1.9 christos
3546 1.9 christos case sme2_mov:
3547 1.9 christos /* .D is preferred over the other sizes in disassembly. */
3548 1.9 christos variant = 3;
3549 1.9 christos break;
3550 1.6 christos
3551 1.9 christos case sme2_movaz:
3552 1.6 christos case sme_misc:
3553 1.6 christos case sve_misc:
3554 1.6 christos /* These instructions have only a single variant. */
3555 1.6 christos break;
3556 1.6 christos
3557 1.6 christos case sve_movprfx:
3558 1.6 christos variant = extract_fields (inst->value, 0, 2, FLD_size, FLD_SVE_M_16);
3559 1.6 christos break;
3560 1.6 christos
3561 1.6 christos case sve_pred_zm:
3562 1.6 christos variant = extract_field (FLD_SVE_M_4, inst->value, 0);
3563 1.6 christos break;
3564 1.6 christos
3565 1.6 christos case sve_shift_pred:
3566 1.8 christos i = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_SVE_tszl_8);
3567 1.6 christos sve_shift:
3568 1.6 christos if (i == 0)
3569 1.6 christos return false;
3570 1.6 christos while (i != 1)
3571 1.6 christos {
3572 1.6 christos i >>= 1;
3573 1.6 christos variant += 1;
3574 1.6 christos }
3575 1.6 christos break;
3576 1.6 christos
3577 1.6 christos case sve_shift_unpred:
3578 1.6 christos i = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_SVE_tszl_19);
3579 1.6 christos goto sve_shift;
3580 1.6 christos
3581 1.8 christos case sve_size_bhs:
3582 1.6 christos variant = extract_field (FLD_size, inst->value, 0);
3583 1.6 christos if (variant >= 3)
3584 1.6 christos return false;
3585 1.6 christos break;
3586 1.6 christos
3587 1.6 christos case sve_size_bhsd:
3588 1.6 christos variant = extract_field (FLD_size, inst->value, 0);
3589 1.6 christos break;
3590 1.6 christos
3591 1.8 christos case sve_size_hsd:
3592 1.6 christos i = extract_field (FLD_size, inst->value, 0);
3593 1.6 christos if (i < 1)
3594 1.6 christos return false;
3595 1.9 christos variant = i - 1;
3596 1.9 christos break;
3597 1.7 christos
3598 1.6 christos case sme_fp_sd:
3599 1.6 christos case sme_int_sd:
3600 1.6 christos case sve_size_bh:
3601 1.6 christos case sve_size_sd:
3602 1.7 christos variant = extract_field (FLD_SVE_sz, inst->value, 0);
3603 1.7 christos break;
3604 1.7 christos
3605 1.7 christos case sve_size_sd2:
3606 1.10 christos variant = extract_field (FLD_SVE_sz2, inst->value, 0);
3607 1.10 christos break;
3608 1.10 christos
3609 1.10 christos case sve_size_sd3:
3610 1.10 christos variant = extract_field (FLD_SVE_sz3, inst->value, 0);
3611 1.10 christos break;
3612 1.10 christos
3613 1.10 christos case sve_size_sd4:
3614 1.7 christos variant = extract_field (FLD_SVE_sz4, inst->value, 0);
3615 1.7 christos break;
3616 1.7 christos
3617 1.8 christos case sve_size_hsd2:
3618 1.7 christos i = extract_field (FLD_SVE_size, inst->value, 0);
3619 1.7 christos if (i < 1)
3620 1.7 christos return false;
3621 1.10 christos variant = i - 1;
3622 1.10 christos break;
3623 1.10 christos
3624 1.10 christos case sve_size_hsd3:
3625 1.10 christos i = extract_field (FLD_len, inst->value, 0);
3626 1.10 christos if (i < 1)
3627 1.10 christos return false;
3628 1.7 christos variant = i - 1;
3629 1.7 christos break;
3630 1.7 christos
3631 1.7 christos case sve_size_13:
3632 1.7 christos /* Ignore low bit of this field since that is set in the opcode for
3633 1.7 christos instructions of this iclass. */
3634 1.7 christos i = (extract_field (FLD_size, inst->value, 0) & 2);
3635 1.7 christos variant = (i >> 1);
3636 1.7 christos break;
3637 1.7 christos
3638 1.8 christos case sve_shift_tsz_bhsd:
3639 1.7 christos i = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_SVE_tszl_19);
3640 1.7 christos if (i == 0)
3641 1.7 christos return false;
3642 1.7 christos while (i != 1)
3643 1.7 christos {
3644 1.7 christos i >>= 1;
3645 1.7 christos variant += 1;
3646 1.7 christos }
3647 1.7 christos break;
3648 1.7 christos
3649 1.8 christos case sve_size_tsz_bhs:
3650 1.7 christos i = extract_fields (inst->value, 0, 2, FLD_SVE_sz, FLD_SVE_tszl_19);
3651 1.7 christos if (i == 0)
3652 1.7 christos return false;
3653 1.8 christos while (i != 1)
3654 1.7 christos {
3655 1.7 christos if (i & 1)
3656 1.7 christos return false;
3657 1.7 christos i >>= 1;
3658 1.7 christos variant += 1;
3659 1.7 christos }
3660 1.7 christos break;
3661 1.7 christos
3662 1.8 christos case sve_shift_tsz_hsd:
3663 1.7 christos i = extract_fields (inst->value, 0, 2, FLD_SVE_sz, FLD_SVE_tszl_19);
3664 1.7 christos if (i == 0)
3665 1.7 christos return false;
3666 1.7 christos while (i != 1)
3667 1.7 christos {
3668 1.7 christos i >>= 1;
3669 1.7 christos variant += 1;
3670 1.6 christos }
3671 1.6 christos break;
3672 1.8 christos
3673 1.6 christos default:
3674 1.6 christos /* No mapping between instruction class and qualifiers. */
3675 1.6 christos return true;
3676 1.6 christos }
3677 1.8 christos
3678 1.6 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
3679 1.1 christos inst->operands[i].qualifier = inst->opcode->qualifiers_list[variant][i];
3680 1.1 christos return true;
3681 1.1 christos }
3682 1.1 christos /* Decode the CODE according to OPCODE; fill INST. Return 0 if the decoding
3683 1.1 christos fails, which meanes that CODE is not an instruction of OPCODE; otherwise
3684 1.1 christos return 1.
3685 1.1 christos
3686 1.1 christos If OPCODE has alias(es) and NOALIASES_P is 0, an alias opcode may be
3687 1.8 christos determined and used to disassemble CODE; this is done just before the
3688 1.1 christos return. */
3689 1.6 christos
3690 1.6 christos static bool
3691 1.1 christos aarch64_opcode_decode (const aarch64_opcode *opcode, const aarch64_insn code,
3692 1.1 christos aarch64_inst *inst, int noaliases_p,
3693 1.1 christos aarch64_operand_error *errors)
3694 1.1 christos {
3695 1.1 christos int i;
3696 1.1 christos
3697 1.1 christos DEBUG_TRACE ("enter with %s", opcode->name);
3698 1.6 christos
3699 1.6 christos assert (opcode && inst);
3700 1.6 christos
3701 1.1 christos /* Clear inst. */
3702 1.1 christos memset (inst, '\0', sizeof (aarch64_inst));
3703 1.1 christos
3704 1.1 christos /* Check the base opcode. */
3705 1.1 christos if ((code & opcode->mask) != (opcode->opcode & opcode->mask))
3706 1.1 christos {
3707 1.1 christos DEBUG_TRACE ("base opcode match FAIL");
3708 1.1 christos goto decode_fail;
3709 1.1 christos }
3710 1.1 christos
3711 1.1 christos inst->opcode = opcode;
3712 1.1 christos inst->value = code;
3713 1.1 christos
3714 1.1 christos /* Assign operand codes and indexes. */
3715 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
3716 1.1 christos {
3717 1.1 christos if (opcode->operands[i] == AARCH64_OPND_NIL)
3718 1.1 christos break;
3719 1.1 christos inst->operands[i].type = opcode->operands[i];
3720 1.1 christos inst->operands[i].idx = i;
3721 1.1 christos }
3722 1.1 christos
3723 1.1 christos /* Call the opcode decoder indicated by flags. */
3724 1.1 christos if (opcode_has_special_coder (opcode) && do_special_decoding (inst) == 0)
3725 1.1 christos {
3726 1.1 christos DEBUG_TRACE ("opcode flag-based decoder FAIL");
3727 1.6 christos goto decode_fail;
3728 1.6 christos }
3729 1.6 christos
3730 1.6 christos /* Possibly use the instruction class to determine the correct
3731 1.6 christos qualifier. */
3732 1.6 christos if (!aarch64_decode_variant_using_iclass (inst))
3733 1.6 christos {
3734 1.6 christos DEBUG_TRACE ("iclass-based decoder FAIL");
3735 1.1 christos goto decode_fail;
3736 1.1 christos }
3737 1.1 christos
3738 1.1 christos /* Call operand decoders. */
3739 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
3740 1.5 christos {
3741 1.1 christos const aarch64_operand *opnd;
3742 1.1 christos enum aarch64_opnd type;
3743 1.1 christos
3744 1.1 christos type = opcode->operands[i];
3745 1.1 christos if (type == AARCH64_OPND_NIL)
3746 1.6 christos break;
3747 1.6 christos opnd = &aarch64_operands[type];
3748 1.1 christos if (operand_has_extractor (opnd)
3749 1.1 christos && (! aarch64_extract_operand (opnd, &inst->operands[i], code, inst,
3750 1.1 christos errors)))
3751 1.1 christos {
3752 1.1 christos DEBUG_TRACE ("operand decoder FAIL at operand %d", i);
3753 1.1 christos goto decode_fail;
3754 1.5 christos }
3755 1.7 christos }
3756 1.8 christos
3757 1.5 christos /* If the opcode has a verifier, then check it now. */
3758 1.5 christos if (opcode->verifier
3759 1.5 christos && opcode->verifier (inst, code, 0, false, errors, NULL) != ERR_OK)
3760 1.5 christos {
3761 1.5 christos DEBUG_TRACE ("operand verifier FAIL");
3762 1.1 christos goto decode_fail;
3763 1.1 christos }
3764 1.1 christos
3765 1.1 christos /* Match the qualifiers. */
3766 1.1 christos if (aarch64_match_operands_constraint (inst, NULL) == 1)
3767 1.1 christos {
3768 1.1 christos /* Arriving here, the CODE has been determined as a valid instruction
3769 1.1 christos of OPCODE and *INST has been filled with information of this OPCODE
3770 1.1 christos instruction. Before the return, check if the instruction has any
3771 1.6 christos alias and should be disassembled in the form of its alias instead.
3772 1.1 christos If the answer is yes, *INST will be updated. */
3773 1.8 christos if (!noaliases_p)
3774 1.1 christos determine_disassembling_preference (inst, errors);
3775 1.1 christos DEBUG_TRACE ("SUCCESS");
3776 1.1 christos return true;
3777 1.1 christos }
3778 1.1 christos else
3779 1.1 christos {
3780 1.8 christos DEBUG_TRACE ("constraint matching FAIL");
3781 1.8 christos }
3782 1.1 christos
3783 1.1 christos decode_fail:
3784 1.1 christos return false;
3785 1.1 christos }
3786 1.1 christos
3787 1.1 christos /* This does some user-friendly fix-up to *INST. It is currently focus on
3789 1.1 christos the adjustment of qualifiers to help the printed instruction
3790 1.1 christos recognized/understood more easily. */
3791 1.1 christos
3792 1.1 christos static void
3793 1.1 christos user_friendly_fixup (aarch64_inst *inst)
3794 1.1 christos {
3795 1.1 christos switch (inst->opcode->iclass)
3796 1.1 christos {
3797 1.1 christos case testbranch:
3798 1.1 christos /* TBNZ Xn|Wn, #uimm6, label
3799 1.1 christos Test and Branch Not Zero: conditionally jumps to label if bit number
3800 1.1 christos uimm6 in register Xn is not zero. The bit number implies the width of
3801 1.1 christos the register, which may be written and should be disassembled as Wn if
3802 1.1 christos uimm is less than 32. Limited to a branch offset range of +/- 32KiB.
3803 1.1 christos */
3804 1.1 christos if (inst->operands[1].imm.value < 32)
3805 1.1 christos inst->operands[0].qualifier = AARCH64_OPND_QLF_W;
3806 1.1 christos break;
3807 1.3 christos default: break;
3808 1.3 christos }
3809 1.3 christos }
3810 1.1 christos
3811 1.7 christos /* Decode INSN and fill in *INST the instruction information. An alias
3812 1.3 christos opcode may be filled in *INSN if NOALIASES_P is FALSE. Return zero on
3813 1.8 christos success. */
3814 1.6 christos
3815 1.1 christos enum err_type
3816 1.1 christos aarch64_decode_insn (aarch64_insn insn, aarch64_inst *inst,
3817 1.1 christos bool noaliases_p,
3818 1.1 christos aarch64_operand_error *errors)
3819 1.1 christos {
3820 1.1 christos const aarch64_opcode *opcode = aarch64_opcode_lookup (insn);
3821 1.1 christos
3822 1.1 christos #ifdef DEBUG_AARCH64
3823 1.1 christos if (debug_dump)
3824 1.1 christos {
3825 1.1 christos const aarch64_opcode *tmp = opcode;
3826 1.1 christos printf ("\n");
3827 1.1 christos DEBUG_TRACE ("opcode lookup:");
3828 1.1 christos while (tmp != NULL)
3829 1.1 christos {
3830 1.1 christos aarch64_verbose (" %s", tmp->name);
3831 1.1 christos tmp = aarch64_find_next_opcode (tmp);
3832 1.1 christos }
3833 1.1 christos }
3834 1.1 christos #endif /* DEBUG_AARCH64 */
3835 1.1 christos
3836 1.1 christos /* A list of opcodes may have been found, as aarch64_opcode_lookup cannot
3837 1.1 christos distinguish some opcodes, e.g. SSHR and MOVI, which almost share the same
3838 1.1 christos opcode field and value, apart from the difference that one of them has an
3839 1.1 christos extra field as part of the opcode, but such a field is used for operand
3840 1.1 christos encoding in other opcode(s) ('immh' in the case of the example). */
3841 1.6 christos while (opcode != NULL)
3842 1.1 christos {
3843 1.1 christos /* But only one opcode can be decoded successfully for, as the
3844 1.1 christos decoding routine will check the constraint carefully. */
3845 1.1 christos if (aarch64_opcode_decode (opcode, insn, inst, noaliases_p, errors) == 1)
3846 1.1 christos return ERR_OK;
3847 1.1 christos opcode = aarch64_find_next_opcode (opcode);
3848 1.1 christos }
3849 1.9 christos
3850 1.9 christos return ERR_UND;
3851 1.9 christos }
3852 1.9 christos
3853 1.9 christos /* Return a short string to indicate a switch to STYLE. These strings
3854 1.9 christos will be embedded into the disassembled operand text (as produced by
3855 1.9 christos aarch64_print_operand), and then spotted in the print_operands function
3856 1.9 christos so that the disassembler output can be split by style. */
3857 1.9 christos
3858 1.9 christos static const char *
3859 1.9 christos get_style_text (enum disassembler_style style)
3860 1.9 christos {
3861 1.9 christos static bool init = false;
3862 1.9 christos static char formats[16][4];
3863 1.9 christos unsigned num;
3864 1.9 christos
3865 1.9 christos /* First time through we build a string for every possible format. This
3866 1.9 christos code relies on there being no more than 16 different styles (there's
3867 1.9 christos an assert below for this). */
3868 1.9 christos if (!init)
3869 1.9 christos {
3870 1.9 christos int i;
3871 1.9 christos
3872 1.9 christos for (i = 0; i <= 0xf; ++i)
3873 1.9 christos {
3874 1.9 christos int res ATTRIBUTE_UNUSED
3875 1.9 christos = snprintf (&formats[i][0], sizeof (formats[i]), "%c%x%c",
3876 1.9 christos STYLE_MARKER_CHAR, i, STYLE_MARKER_CHAR);
3877 1.9 christos assert (res == 3);
3878 1.9 christos }
3879 1.9 christos
3880 1.9 christos init = true;
3881 1.9 christos }
3882 1.9 christos
3883 1.9 christos /* Return the string that marks switching to STYLE. */
3884 1.9 christos num = (unsigned) style;
3885 1.9 christos assert (style <= 0xf);
3886 1.9 christos return formats[num];
3887 1.9 christos }
3888 1.9 christos
3889 1.9 christos /* Callback used by aarch64_print_operand to apply STYLE to the
3890 1.9 christos disassembler output created from FMT and ARGS. The STYLER object holds
3891 1.9 christos any required state. Must return a pointer to a string (created from FMT
3892 1.9 christos and ARGS) that will continue to be valid until the complete disassembled
3893 1.9 christos instruction has been printed.
3894 1.9 christos
3895 1.9 christos We return a string that includes two embedded style markers, the first,
3896 1.9 christos places at the start of the string, indicates a switch to STYLE, and the
3897 1.9 christos second, placed at the end of the string, indicates a switch back to the
3898 1.9 christos default text style.
3899 1.9 christos
3900 1.9 christos Later, when we print the operand text we take care to collapse any
3901 1.9 christos adjacent style markers, and to ignore any style markers that appear at
3902 1.9 christos the very end of a complete operand string. */
3903 1.9 christos
3904 1.9 christos static const char *aarch64_apply_style (struct aarch64_styler *styler,
3905 1.9 christos enum disassembler_style style,
3906 1.9 christos const char *fmt,
3907 1.9 christos va_list args)
3908 1.9 christos {
3909 1.9 christos int res;
3910 1.9 christos char *ptr, *tmp;
3911 1.9 christos struct obstack *stack = (struct obstack *) styler->state;
3912 1.9 christos va_list ap;
3913 1.9 christos
3914 1.9 christos /* These are the two strings for switching styles. */
3915 1.9 christos const char *style_on = get_style_text (style);
3916 1.9 christos const char *style_off = get_style_text (dis_style_text);
3917 1.9 christos
3918 1.9 christos /* Calculate space needed once FMT and ARGS are expanded. */
3919 1.9 christos va_copy (ap, args);
3920 1.9 christos res = vsnprintf (NULL, 0, fmt, ap);
3921 1.9 christos va_end (ap);
3922 1.9 christos assert (res >= 0);
3923 1.9 christos
3924 1.9 christos /* Allocate space on the obstack for the expanded FMT and ARGS, as well
3925 1.9 christos as the two strings for switching styles, then write all of these
3926 1.9 christos strings onto the obstack. */
3927 1.9 christos ptr = (char *) obstack_alloc (stack, res + strlen (style_on)
3928 1.9 christos + strlen (style_off) + 1);
3929 1.9 christos tmp = stpcpy (ptr, style_on);
3930 1.9 christos res = vsnprintf (tmp, (res + 1), fmt, args);
3931 1.9 christos assert (res >= 0);
3932 1.9 christos tmp += res;
3933 1.9 christos strcpy (tmp, style_off);
3934 1.1 christos
3935 1.1 christos return ptr;
3936 1.1 christos }
3937 1.1 christos
3938 1.7 christos /* Print operands. */
3939 1.8 christos
3940 1.1 christos static void
3941 1.7 christos print_operands (bfd_vma pc, const aarch64_opcode *opcode,
3942 1.1 christos const aarch64_opnd_info *opnds, struct disassemble_info *info,
3943 1.9 christos bool *has_notes)
3944 1.9 christos {
3945 1.9 christos char *notes = NULL;
3946 1.9 christos int i, pcrel_p, num_printed;
3947 1.9 christos struct aarch64_styler styler;
3948 1.9 christos struct obstack content;
3949 1.9 christos obstack_init (&content);
3950 1.1 christos
3951 1.1 christos styler.apply_style = aarch64_apply_style;
3952 1.5 christos styler.state = (void *) &content;
3953 1.8 christos
3954 1.8 christos for (i = 0, num_printed = 0; i < AARCH64_MAX_OPND_NUM; ++i)
3955 1.1 christos {
3956 1.1 christos char str[128];
3957 1.1 christos char cmt[128];
3958 1.1 christos
3959 1.1 christos /* We regard the opcode operand info more, however we also look into
3960 1.1 christos the inst->operands to support the disassembling of the optional
3961 1.1 christos operand.
3962 1.1 christos The two operand code should be the same in all cases, apart from
3963 1.1 christos when the operand can be optional. */
3964 1.1 christos if (opcode->operands[i] == AARCH64_OPND_NIL
3965 1.5 christos || opnds[i].type == AARCH64_OPND_NIL)
3966 1.8 christos break;
3967 1.9 christos
3968 1.1 christos /* Generate the operand string in STR. */
3969 1.1 christos aarch64_print_operand (str, sizeof (str), pc, opcode, opnds, i, &pcrel_p,
3970 1.1 christos &info->target, ¬es, cmt, sizeof (cmt),
3971 1.9 christos arch_variant, &styler);
3972 1.9 christos
3973 1.1 christos /* Print the delimiter (taking account of omitted operand(s)). */
3974 1.1 christos if (str[0] != '\0')
3975 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "%s",
3976 1.1 christos num_printed++ == 0 ? "\t" : ", ");
3977 1.1 christos
3978 1.8 christos /* Print the operand. */
3979 1.9 christos if (pcrel_p)
3980 1.9 christos (*info->print_address_func) (info->target, info);
3981 1.9 christos else
3982 1.9 christos {
3983 1.9 christos /* This operand came from aarch64_print_operand, and will include
3984 1.9 christos embedded strings indicating which style each character should
3985 1.9 christos have. In the following code we split the text based on
3986 1.9 christos CURR_STYLE, and call the styled print callback to print each
3987 1.9 christos block of text in the appropriate style. */
3988 1.9 christos char *start, *curr;
3989 1.9 christos enum disassembler_style curr_style = dis_style_text;
3990 1.9 christos
3991 1.9 christos start = curr = str;
3992 1.9 christos do
3993 1.9 christos {
3994 1.9 christos if (*curr == '\0'
3995 1.9 christos || (*curr == STYLE_MARKER_CHAR
3996 1.9 christos && ISXDIGIT (*(curr + 1))
3997 1.9 christos && *(curr + 2) == STYLE_MARKER_CHAR))
3998 1.9 christos {
3999 1.9 christos /* Output content between our START position and CURR. */
4000 1.9 christos int len = curr - start;
4001 1.9 christos if (len > 0)
4002 1.9 christos {
4003 1.9 christos if ((*info->fprintf_styled_func) (info->stream,
4004 1.9 christos curr_style,
4005 1.9 christos "%.*s",
4006 1.9 christos len, start) < 0)
4007 1.9 christos break;
4008 1.9 christos }
4009 1.9 christos
4010 1.9 christos if (*curr == '\0')
4011 1.9 christos break;
4012 1.9 christos
4013 1.9 christos /* Skip over the initial STYLE_MARKER_CHAR. */
4014 1.9 christos ++curr;
4015 1.9 christos
4016 1.9 christos /* Update the CURR_STYLE. As there are less than 16
4017 1.9 christos styles, it is possible, that if the input is corrupted
4018 1.9 christos in some way, that we might set CURR_STYLE to an
4019 1.9 christos invalid value. Don't worry though, we check for this
4020 1.9 christos situation. */
4021 1.9 christos if (*curr >= '0' && *curr <= '9')
4022 1.9 christos curr_style = (enum disassembler_style) (*curr - '0');
4023 1.9 christos else if (*curr >= 'a' && *curr <= 'f')
4024 1.9 christos curr_style = (enum disassembler_style) (*curr - 'a' + 10);
4025 1.9 christos else
4026 1.9 christos curr_style = dis_style_text;
4027 1.9 christos
4028 1.9 christos /* Check for an invalid style having been selected. This
4029 1.8 christos should never happen, but it doesn't hurt to be a
4030 1.9 christos little paranoid. */
4031 1.9 christos if (curr_style > dis_style_comment_start)
4032 1.9 christos curr_style = dis_style_text;
4033 1.9 christos
4034 1.9 christos /* Skip the hex character, and the closing STYLE_MARKER_CHAR. */
4035 1.9 christos curr += 2;
4036 1.9 christos
4037 1.9 christos /* Reset the START to after the style marker. */
4038 1.9 christos start = curr;
4039 1.9 christos }
4040 1.8 christos else
4041 1.9 christos ++curr;
4042 1.9 christos }
4043 1.9 christos while (true);
4044 1.9 christos }
4045 1.9 christos
4046 1.9 christos /* Print the comment. This works because only the last operand ever
4047 1.9 christos adds a comment. If that ever changes then we'll need to be
4048 1.1 christos smarter here. */
4049 1.6 christos if (cmt[0] != '\0')
4050 1.6 christos (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
4051 1.7 christos "\t// %s", cmt);
4052 1.8 christos }
4053 1.9 christos
4054 1.9 christos if (notes && !no_notes)
4055 1.7 christos {
4056 1.9 christos *has_notes = true;
4057 1.9 christos (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
4058 1.6 christos " // note: %s", notes);
4059 1.6 christos }
4060 1.6 christos
4061 1.6 christos obstack_free (&content, NULL);
4062 1.6 christos }
4063 1.6 christos
4064 1.6 christos /* Set NAME to a copy of INST's mnemonic with the "." suffix removed. */
4065 1.6 christos
4066 1.6 christos static void
4067 1.6 christos remove_dot_suffix (char *name, const aarch64_inst *inst)
4068 1.6 christos {
4069 1.6 christos char *ptr;
4070 1.6 christos size_t len;
4071 1.6 christos
4072 1.6 christos ptr = strchr (inst->opcode->name, '.');
4073 1.6 christos assert (ptr && inst->cond);
4074 1.1 christos len = ptr - inst->opcode->name;
4075 1.1 christos assert (len < 8);
4076 1.1 christos strncpy (name, inst->opcode->name, len);
4077 1.1 christos name[len] = '\0';
4078 1.1 christos }
4079 1.1 christos
4080 1.1 christos /* Print the instruction mnemonic name. */
4081 1.1 christos
4082 1.1 christos static void
4083 1.1 christos print_mnemonic_name (const aarch64_inst *inst, struct disassemble_info *info)
4084 1.1 christos {
4085 1.1 christos if (inst->opcode->flags & F_COND)
4086 1.6 christos {
4087 1.3 christos /* For instructions that are truly conditionally executed, e.g. b.cond,
4088 1.6 christos prepare the full mnemonic name with the corresponding condition
4089 1.9 christos suffix. */
4090 1.9 christos char name[8];
4091 1.1 christos
4092 1.1 christos remove_dot_suffix (name, inst);
4093 1.9 christos (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
4094 1.9 christos "%s.%s", name, inst->cond->names[0]);
4095 1.1 christos }
4096 1.1 christos else
4097 1.6 christos (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
4098 1.6 christos "%s", inst->opcode->name);
4099 1.6 christos }
4100 1.6 christos
4101 1.6 christos /* Decide whether we need to print a comment after the operands of
4102 1.6 christos instruction INST. */
4103 1.6 christos
4104 1.6 christos static void
4105 1.6 christos print_comment (const aarch64_inst *inst, struct disassemble_info *info)
4106 1.6 christos {
4107 1.6 christos if (inst->opcode->flags & F_COND)
4108 1.6 christos {
4109 1.6 christos char name[8];
4110 1.6 christos unsigned int i, num_conds;
4111 1.9 christos
4112 1.9 christos remove_dot_suffix (name, inst);
4113 1.9 christos num_conds = ARRAY_SIZE (inst->cond->names);
4114 1.9 christos for (i = 1; i < num_conds && inst->cond->names[i]; ++i)
4115 1.6 christos (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
4116 1.6 christos "%s %s.%s",
4117 1.6 christos i == 1 ? " //" : ",",
4118 1.7 christos name, inst->cond->names[i]);
4119 1.7 christos }
4120 1.7 christos }
4121 1.7 christos
4122 1.7 christos /* Build notes from verifiers into a string for printing. */
4123 1.7 christos
4124 1.7 christos static void
4125 1.7 christos print_verifier_notes (aarch64_operand_error *detail,
4126 1.7 christos struct disassemble_info *info)
4127 1.7 christos {
4128 1.7 christos if (no_notes)
4129 1.7 christos return;
4130 1.7 christos
4131 1.9 christos /* The output of the verifier cannot be a fatal error, otherwise the assembly
4132 1.9 christos would not have succeeded. We can safely ignore these. */
4133 1.8 christos assert (detail->non_fatal);
4134 1.8 christos
4135 1.8 christos (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
4136 1.9 christos " // note: ");
4137 1.9 christos switch (detail->kind)
4138 1.9 christos {
4139 1.9 christos case AARCH64_OPDE_A_SHOULD_FOLLOW_B:
4140 1.8 christos (*info->fprintf_styled_func) (info->stream, dis_style_text,
4141 1.8 christos _("this `%s' should have an immediately"
4142 1.8 christos " preceding `%s'"),
4143 1.9 christos detail->data[0].s, detail->data[1].s);
4144 1.9 christos break;
4145 1.9 christos
4146 1.8 christos case AARCH64_OPDE_EXPECTED_A_AFTER_B:
4147 1.8 christos (*info->fprintf_styled_func) (info->stream, dis_style_text,
4148 1.8 christos _("expected `%s' after previous `%s'"),
4149 1.8 christos detail->data[0].s, detail->data[1].s);
4150 1.9 christos break;
4151 1.9 christos
4152 1.8 christos default:
4153 1.9 christos assert (detail->error);
4154 1.9 christos (*info->fprintf_styled_func) (info->stream, dis_style_text,
4155 1.8 christos "%s", detail->error);
4156 1.8 christos if (detail->index >= 0)
4157 1.7 christos (*info->fprintf_styled_func) (info->stream, dis_style_text,
4158 1.7 christos " at operand %d", detail->index + 1);
4159 1.1 christos break;
4160 1.1 christos }
4161 1.1 christos }
4162 1.1 christos
4163 1.7 christos /* Print the instruction according to *INST. */
4164 1.7 christos
4165 1.7 christos static void
4166 1.1 christos print_aarch64_insn (bfd_vma pc, const aarch64_inst *inst,
4167 1.8 christos const aarch64_insn code,
4168 1.7 christos struct disassemble_info *info,
4169 1.1 christos aarch64_operand_error *mismatch_details)
4170 1.7 christos {
4171 1.6 christos bool has_notes = false;
4172 1.7 christos
4173 1.7 christos print_mnemonic_name (inst, info);
4174 1.7 christos print_operands (pc, inst->opcode, inst->operands, info, &has_notes);
4175 1.7 christos print_comment (inst, info);
4176 1.7 christos
4177 1.7 christos /* We've already printed a note, not enough space to print more so exit.
4178 1.7 christos Usually notes shouldn't overlap so it shouldn't happen that we have a note
4179 1.7 christos from a register and instruction at the same time. */
4180 1.7 christos if (has_notes)
4181 1.7 christos return;
4182 1.8 christos
4183 1.7 christos /* Always run constraint verifiers, this is needed because constraints need to
4184 1.7 christos maintain a global state regardless of whether the instruction has the flag
4185 1.7 christos set or not. */
4186 1.8 christos enum err_type result = verify_constraints (inst, code, pc, false,
4187 1.8 christos mismatch_details, &insn_sequence);
4188 1.8 christos switch (result)
4189 1.7 christos {
4190 1.7 christos case ERR_VFI:
4191 1.7 christos print_verifier_notes (mismatch_details, info);
4192 1.7 christos break;
4193 1.7 christos case ERR_UND:
4194 1.7 christos case ERR_UNP:
4195 1.1 christos case ERR_NYI:
4196 1.1 christos default:
4197 1.1 christos break;
4198 1.1 christos }
4199 1.1 christos }
4200 1.1 christos
4201 1.1 christos /* Entry-point of the instruction disassembler and printer. */
4202 1.6 christos
4203 1.6 christos static void
4204 1.1 christos print_insn_aarch64_word (bfd_vma pc,
4205 1.7 christos uint32_t word,
4206 1.1 christos struct disassemble_info *info,
4207 1.7 christos aarch64_operand_error *errors)
4208 1.7 christos {
4209 1.7 christos static const char *err_msg[ERR_NR_ENTRIES+1] =
4210 1.7 christos {
4211 1.1 christos [ERR_OK] = "_",
4212 1.1 christos [ERR_UND] = "undefined",
4213 1.7 christos [ERR_UNP] = "unpredictable",
4214 1.1 christos [ERR_NYI] = "NYI"
4215 1.1 christos };
4216 1.1 christos
4217 1.1 christos enum err_type ret;
4218 1.1 christos aarch64_inst inst;
4219 1.1 christos
4220 1.1 christos info->insn_info_valid = 1;
4221 1.1 christos info->branch_delay_insns = 0;
4222 1.1 christos info->data_size = 0;
4223 1.1 christos info->target = 0;
4224 1.1 christos info->target2 = 0;
4225 1.1 christos
4226 1.1 christos if (info->flags & INSN_HAS_RELOC)
4227 1.1 christos /* If the instruction has a reloc associated with it, then
4228 1.1 christos the offset field in the instruction will actually be the
4229 1.1 christos addend for the reloc. (If we are using REL type relocs).
4230 1.6 christos In such cases, we can ignore the pc when computing
4231 1.1 christos addresses, since the addend is not currently pc-relative. */
4232 1.1 christos pc = 0;
4233 1.1 christos
4234 1.3 christos ret = aarch64_decode_insn (word, &inst, no_aliases, errors);
4235 1.1 christos
4236 1.1 christos if (((word >> 21) & 0x3ff) == 1)
4237 1.1 christos {
4238 1.1 christos /* RESERVED for ALES. */
4239 1.1 christos assert (ret != ERR_OK);
4240 1.1 christos ret = ERR_NYI;
4241 1.1 christos }
4242 1.1 christos
4243 1.1 christos switch (ret)
4244 1.1 christos {
4245 1.1 christos case ERR_UND:
4246 1.9 christos case ERR_UNP:
4247 1.9 christos case ERR_NYI:
4248 1.9 christos /* Handle undefined instructions. */
4249 1.9 christos info->insn_type = dis_noninsn;
4250 1.9 christos (*info->fprintf_styled_func) (info->stream,
4251 1.9 christos dis_style_assembler_directive,
4252 1.9 christos ".inst\t");
4253 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
4254 1.1 christos "0x%08x", word);
4255 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
4256 1.9 christos " ; %s", err_msg[ret]);
4257 1.9 christos break;
4258 1.9 christos case ERR_OK:
4259 1.9 christos user_friendly_fixup (&inst);
4260 1.9 christos if (inst.opcode->iclass == condbranch
4261 1.9 christos || inst.opcode->iclass == testbranch
4262 1.7 christos || inst.opcode->iclass == compbranch)
4263 1.1 christos info->insn_type = dis_condbranch;
4264 1.1 christos else if (inst.opcode->iclass == branch_imm)
4265 1.1 christos info->insn_type = dis_jsr;
4266 1.1 christos print_aarch64_insn (pc, &inst, word, info, errors);
4267 1.1 christos break;
4268 1.1 christos default:
4269 1.1 christos abort ();
4270 1.1 christos }
4271 1.1 christos }
4272 1.8 christos
4273 1.1 christos /* Disallow mapping symbols ($x, $d etc) from
4274 1.1 christos being displayed in symbol relative addresses. */
4275 1.1 christos
4276 1.1 christos bool
4277 1.1 christos aarch64_symbol_is_valid (asymbol * sym,
4278 1.1 christos struct disassemble_info * info ATTRIBUTE_UNUSED)
4279 1.8 christos {
4280 1.1 christos const char * name;
4281 1.1 christos
4282 1.1 christos if (sym == NULL)
4283 1.1 christos return false;
4284 1.1 christos
4285 1.1 christos name = bfd_asymbol_name (sym);
4286 1.1 christos
4287 1.1 christos return name
4288 1.1 christos && (name[0] != '$'
4289 1.1 christos || (name[1] != 'x' && name[1] != 'd')
4290 1.1 christos || (name[2] != '\0' && name[2] != '.'));
4291 1.1 christos }
4292 1.1 christos
4293 1.1 christos /* Print data bytes on INFO->STREAM. */
4294 1.6 christos
4295 1.6 christos static void
4296 1.1 christos print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED,
4297 1.1 christos uint32_t word,
4298 1.1 christos struct disassemble_info *info,
4299 1.1 christos aarch64_operand_error *errors ATTRIBUTE_UNUSED)
4300 1.9 christos {
4301 1.9 christos switch (info->bytes_per_chunk)
4302 1.9 christos {
4303 1.9 christos case 1:
4304 1.1 christos info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
4305 1.1 christos ".byte\t");
4306 1.9 christos info->fprintf_styled_func (info->stream, dis_style_immediate,
4307 1.9 christos "0x%02x", word);
4308 1.9 christos break;
4309 1.9 christos case 2:
4310 1.1 christos info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
4311 1.1 christos ".short\t");
4312 1.9 christos info->fprintf_styled_func (info->stream, dis_style_immediate,
4313 1.9 christos "0x%04x", word);
4314 1.9 christos break;
4315 1.9 christos case 4:
4316 1.1 christos info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
4317 1.1 christos ".word\t");
4318 1.1 christos info->fprintf_styled_func (info->stream, dis_style_immediate,
4319 1.1 christos "0x%08x", word);
4320 1.1 christos break;
4321 1.1 christos default:
4322 1.1 christos abort ();
4323 1.1 christos }
4324 1.1 christos }
4325 1.1 christos
4326 1.1 christos /* Try to infer the code or data type from a symbol.
4327 1.1 christos Returns nonzero if *MAP_TYPE was set. */
4328 1.1 christos
4329 1.8 christos static int
4330 1.1 christos get_sym_code_type (struct disassemble_info *info, int n,
4331 1.1 christos enum map_type *map_type)
4332 1.1 christos {
4333 1.1 christos asymbol * as;
4334 1.6 christos elf_symbol_type *es;
4335 1.6 christos unsigned int type;
4336 1.8 christos const char *name;
4337 1.8 christos
4338 1.8 christos /* If the symbol is in a different section, ignore it. */
4339 1.8 christos if (info->section != NULL && info->section != info->symtab[n]->section)
4340 1.8 christos return false;
4341 1.8 christos
4342 1.8 christos if (n >= info->symtab_size)
4343 1.8 christos return false;
4344 1.8 christos
4345 1.6 christos as = info->symtab[n];
4346 1.1 christos if (bfd_asymbol_flavour (as) != bfd_target_elf_flavour)
4347 1.1 christos return false;
4348 1.1 christos es = (elf_symbol_type *) as;
4349 1.1 christos
4350 1.1 christos type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
4351 1.1 christos
4352 1.8 christos /* If the symbol has function type then use that. */
4353 1.1 christos if (type == STT_FUNC)
4354 1.1 christos {
4355 1.1 christos *map_type = MAP_INSN;
4356 1.1 christos return true;
4357 1.1 christos }
4358 1.1 christos
4359 1.1 christos /* Check for mapping symbols. */
4360 1.1 christos name = bfd_asymbol_name(info->symtab[n]);
4361 1.1 christos if (name[0] == '$'
4362 1.8 christos && (name[1] == 'x' || name[1] == 'd')
4363 1.1 christos && (name[2] == '\0' || name[2] == '.'))
4364 1.1 christos {
4365 1.8 christos *map_type = (name[1] == 'x' ? MAP_INSN : MAP_DATA);
4366 1.8 christos return true;
4367 1.8 christos }
4368 1.8 christos
4369 1.8 christos return false;
4370 1.8 christos }
4371 1.8 christos
4372 1.8 christos /* Set the feature bits in arch_variant in order to get the correct disassembly
4373 1.8 christos for the chosen architecture variant.
4374 1.8 christos
4375 1.8 christos Currently we only restrict disassembly for Armv8-R and otherwise enable all
4376 1.8 christos non-R-profile features. */
4377 1.8 christos static void
4378 1.8 christos select_aarch64_variant (unsigned mach)
4379 1.9 christos {
4380 1.8 christos switch (mach)
4381 1.8 christos {
4382 1.9 christos case bfd_mach_aarch64_8R:
4383 1.9 christos AARCH64_SET_FEATURE (arch_variant, AARCH64_ARCH_V8R);
4384 1.8 christos break;
4385 1.1 christos default:
4386 1.1 christos arch_variant = (aarch64_feature_set) AARCH64_ALL_FEATURES;
4387 1.1 christos AARCH64_CLEAR_FEATURE (arch_variant, arch_variant, V8R);
4388 1.1 christos }
4389 1.1 christos }
4390 1.1 christos
4391 1.1 christos /* Entry-point of the AArch64 disassembler. */
4392 1.1 christos
4393 1.1 christos int
4394 1.1 christos print_insn_aarch64 (bfd_vma pc,
4395 1.6 christos struct disassemble_info *info)
4396 1.6 christos {
4397 1.8 christos bfd_byte buffer[INSNLEN];
4398 1.1 christos int status;
4399 1.1 christos void (*printer) (bfd_vma, uint32_t, struct disassemble_info *,
4400 1.6 christos aarch64_operand_error *);
4401 1.8 christos bool found = false;
4402 1.1 christos unsigned int size = 4;
4403 1.1 christos unsigned long data;
4404 1.1 christos aarch64_operand_error errors;
4405 1.1 christos static bool set_features;
4406 1.1 christos
4407 1.1 christos if (info->disassembler_options)
4408 1.1 christos {
4409 1.1 christos set_default_aarch64_dis_options (info);
4410 1.1 christos
4411 1.1 christos parse_aarch64_dis_options (info->disassembler_options);
4412 1.1 christos
4413 1.8 christos /* To avoid repeated parsing of these options, we remove them here. */
4414 1.8 christos info->disassembler_options = NULL;
4415 1.8 christos }
4416 1.8 christos
4417 1.8 christos if (!set_features)
4418 1.8 christos {
4419 1.1 christos select_aarch64_variant (info->mach);
4420 1.1 christos set_features = true;
4421 1.1 christos }
4422 1.7 christos
4423 1.7 christos /* Aarch64 instructions are always little-endian */
4424 1.7 christos info->endian_code = BFD_ENDIAN_LITTLE;
4425 1.7 christos
4426 1.7 christos /* Default to DATA. A text section is required by the ABI to contain an
4427 1.7 christos INSN mapping symbol at the start. A data section has no such
4428 1.7 christos requirement, hence if no mapping symbol is found the section must
4429 1.7 christos contain only data. This however isn't very useful if the user has
4430 1.7 christos fully stripped the binaries. If this is the case use the section
4431 1.7 christos attributes to determine the default. If we have no section default to
4432 1.7 christos INSN as well, as we may be disassembling some raw bytes on a baremetal
4433 1.7 christos HEX file or similar. */
4434 1.1 christos enum map_type type = MAP_DATA;
4435 1.1 christos if ((info->section && info->section->flags & SEC_CODE) || !info->section)
4436 1.1 christos type = MAP_INSN;
4437 1.1 christos
4438 1.1 christos /* First check the full symtab for a mapping symbol, even if there
4439 1.1 christos are no usable non-mapping symbols for this address. */
4440 1.7 christos if (info->symtab_size != 0
4441 1.8 christos && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour)
4442 1.1 christos {
4443 1.1 christos int last_sym = -1;
4444 1.1 christos bfd_vma addr, section_vma = 0;
4445 1.1 christos bool can_use_search_opt_p;
4446 1.1 christos int n;
4447 1.1 christos
4448 1.1 christos if (pc <= last_mapping_addr)
4449 1.1 christos last_mapping_sym = -1;
4450 1.7 christos
4451 1.7 christos /* Start scanning at the start of the function, or wherever
4452 1.7 christos we finished last time. */
4453 1.7 christos n = info->symtab_pos + 1;
4454 1.7 christos
4455 1.7 christos /* If the last stop offset is different from the current one it means we
4456 1.7 christos are disassembling a different glob of bytes. As such the optimization
4457 1.7 christos would not be safe and we should start over. */
4458 1.1 christos can_use_search_opt_p = last_mapping_sym >= 0
4459 1.1 christos && info->stop_offset == last_stop_offset;
4460 1.7 christos
4461 1.7 christos if (n >= last_mapping_sym && can_use_search_opt_p)
4462 1.7 christos n = last_mapping_sym;
4463 1.7 christos
4464 1.1 christos /* Look down while we haven't passed the location being disassembled.
4465 1.1 christos The reason for this is that there's no defined order between a symbol
4466 1.1 christos and an mapping symbol that may be at the same address. We may have to
4467 1.1 christos look at least one position ahead. */
4468 1.1 christos for (; n < info->symtab_size; n++)
4469 1.6 christos {
4470 1.1 christos addr = bfd_asymbol_value (info->symtab[n]);
4471 1.1 christos if (addr > pc)
4472 1.8 christos break;
4473 1.1 christos if (get_sym_code_type (info, n, &type))
4474 1.1 christos {
4475 1.1 christos last_sym = n;
4476 1.1 christos found = true;
4477 1.1 christos }
4478 1.1 christos }
4479 1.7 christos
4480 1.1 christos if (!found)
4481 1.1 christos {
4482 1.1 christos n = info->symtab_pos;
4483 1.7 christos if (n >= last_mapping_sym && can_use_search_opt_p)
4484 1.7 christos n = last_mapping_sym;
4485 1.7 christos
4486 1.7 christos /* No mapping symbol found at this address. Look backwards
4487 1.7 christos for a preceeding one, but don't go pass the section start
4488 1.7 christos otherwise a data section with no mapping symbol can pick up
4489 1.7 christos a text mapping symbol of a preceeding section. The documentation
4490 1.7 christos says section can be NULL, in which case we will seek up all the
4491 1.1 christos way to the top. */
4492 1.1 christos if (info->section)
4493 1.7 christos section_vma = info->section->vma;
4494 1.7 christos
4495 1.7 christos for (; n >= 0; n--)
4496 1.7 christos {
4497 1.1 christos addr = bfd_asymbol_value (info->symtab[n]);
4498 1.1 christos if (addr < section_vma)
4499 1.1 christos break;
4500 1.8 christos
4501 1.1 christos if (get_sym_code_type (info, n, &type))
4502 1.1 christos {
4503 1.1 christos last_sym = n;
4504 1.1 christos found = true;
4505 1.1 christos break;
4506 1.1 christos }
4507 1.1 christos }
4508 1.7 christos }
4509 1.1 christos
4510 1.1 christos last_mapping_sym = last_sym;
4511 1.1 christos last_type = type;
4512 1.1 christos last_stop_offset = info->stop_offset;
4513 1.1 christos
4514 1.1 christos /* Look a little bit ahead to see if we should print out
4515 1.1 christos less than four bytes of data. If there's a symbol,
4516 1.1 christos mapping or otherwise, after two bytes then don't
4517 1.1 christos print more. */
4518 1.1 christos if (last_type == MAP_DATA)
4519 1.1 christos {
4520 1.1 christos size = 4 - (pc & 3);
4521 1.1 christos for (n = last_sym + 1; n < info->symtab_size; n++)
4522 1.1 christos {
4523 1.1 christos addr = bfd_asymbol_value (info->symtab[n]);
4524 1.1 christos if (addr > pc)
4525 1.1 christos {
4526 1.1 christos if (addr - pc < size)
4527 1.1 christos size = addr - pc;
4528 1.1 christos break;
4529 1.1 christos }
4530 1.1 christos }
4531 1.1 christos /* If the next symbol is after three bytes, we need to
4532 1.1 christos print only part of the data, so that we can use either
4533 1.1 christos .byte or .short. */
4534 1.7 christos if (size == 3)
4535 1.7 christos size = (pc & 1) ? 1 : 2;
4536 1.1 christos }
4537 1.7 christos }
4538 1.7 christos else
4539 1.1 christos last_type = type;
4540 1.1 christos
4541 1.1 christos /* PR 10263: Disassemble data if requested to do so by the user. */
4542 1.1 christos if (last_type == MAP_DATA && ((info->flags & DISASSEMBLE_DATA) == 0))
4543 1.1 christos {
4544 1.1 christos /* size was set above. */
4545 1.1 christos info->bytes_per_chunk = size;
4546 1.1 christos info->display_endian = info->endian;
4547 1.1 christos printer = print_insn_data;
4548 1.1 christos }
4549 1.1 christos else
4550 1.1 christos {
4551 1.1 christos info->bytes_per_chunk = size = INSNLEN;
4552 1.1 christos info->display_endian = info->endian_code;
4553 1.1 christos printer = print_insn_aarch64_word;
4554 1.1 christos }
4555 1.1 christos
4556 1.1 christos status = (*info->read_memory_func) (pc, buffer, size, info);
4557 1.1 christos if (status != 0)
4558 1.1 christos {
4559 1.1 christos (*info->memory_error_func) (status, pc, info);
4560 1.1 christos return -1;
4561 1.1 christos }
4562 1.6 christos
4563 1.1 christos data = bfd_get_bits (buffer, size * 8,
4564 1.1 christos info->display_endian == BFD_ENDIAN_BIG);
4565 1.1 christos
4566 1.1 christos (*printer) (pc, data, info, &errors);
4567 1.1 christos
4568 1.1 christos return size;
4569 1.1 christos }
4570 1.1 christos
4571 1.1 christos void
4573 1.1 christos print_aarch64_disassembler_options (FILE *stream)
4574 1.1 christos {
4575 1.1 christos fprintf (stream, _("\n\
4576 1.1 christos The following AARCH64 specific disassembler options are supported for use\n\
4577 1.1 christos with the -M switch (multiple options should be separated by commas):\n"));
4578 1.1 christos
4579 1.1 christos fprintf (stream, _("\n\
4580 1.6 christos no-aliases Don't print instruction aliases.\n"));
4581 1.6 christos
4582 1.6 christos fprintf (stream, _("\n\
4583 1.6 christos aliases Do print instruction aliases.\n"));
4584 1.6 christos
4585 1.6 christos fprintf (stream, _("\n\
4586 1.1 christos no-notes Don't print instruction notes.\n"));
4587 1.1 christos
4588 1.1 christos fprintf (stream, _("\n\
4589 1.1 christos notes Do print instruction notes.\n"));
4590 1.1 christos
4591 1.1 christos #ifdef DEBUG_AARCH64
4592 1.1 christos fprintf (stream, _("\n\
4593 debug_dump Temp switch for debug trace.\n"));
4594 #endif /* DEBUG_AARCH64 */
4595
4596 fprintf (stream, _("\n"));
4597 }
4598