aarch64-dis.c revision 1.3 1 1.1 christos /* aarch64-dis.c -- AArch64 disassembler.
2 1.3 christos Copyright (C) 2009-2015 Free Software Foundation, Inc.
3 1.1 christos Contributed by ARM Ltd.
4 1.1 christos
5 1.1 christos This file is part of the GNU opcodes library.
6 1.1 christos
7 1.1 christos This library is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3, or (at your option)
10 1.1 christos any later version.
11 1.1 christos
12 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT
13 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 1.1 christos License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program; see the file COPYING3. If not,
19 1.1 christos see <http://www.gnu.org/licenses/>. */
20 1.1 christos
21 1.1 christos #include "sysdep.h"
22 1.1 christos #include "bfd_stdint.h"
23 1.1 christos #include "dis-asm.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.1 christos
29 1.1 christos #define ERR_OK 0
30 1.1 christos #define ERR_UND -1
31 1.1 christos #define ERR_UNP -3
32 1.1 christos #define ERR_NYI -5
33 1.1 christos
34 1.1 christos #define INSNLEN 4
35 1.1 christos
36 1.1 christos /* Cached mapping symbol state. */
37 1.1 christos enum map_type
38 1.1 christos {
39 1.1 christos MAP_INSN,
40 1.1 christos MAP_DATA
41 1.1 christos };
42 1.1 christos
43 1.1 christos static enum map_type last_type;
44 1.1 christos static int last_mapping_sym = -1;
45 1.1 christos static bfd_vma last_mapping_addr = 0;
46 1.1 christos
47 1.1 christos /* Other options */
48 1.1 christos static int no_aliases = 0; /* If set disassemble as most general inst. */
49 1.1 christos
50 1.1 christos
52 1.1 christos static void
53 1.1 christos set_default_aarch64_dis_options (struct disassemble_info *info ATTRIBUTE_UNUSED)
54 1.1 christos {
55 1.1 christos }
56 1.1 christos
57 1.1 christos static void
58 1.1 christos parse_aarch64_dis_option (const char *option, unsigned int len ATTRIBUTE_UNUSED)
59 1.1 christos {
60 1.1 christos /* Try to match options that are simple flags */
61 1.1 christos if (CONST_STRNEQ (option, "no-aliases"))
62 1.1 christos {
63 1.1 christos no_aliases = 1;
64 1.1 christos return;
65 1.1 christos }
66 1.1 christos
67 1.1 christos if (CONST_STRNEQ (option, "aliases"))
68 1.1 christos {
69 1.1 christos no_aliases = 0;
70 1.1 christos return;
71 1.1 christos }
72 1.1 christos
73 1.1 christos #ifdef DEBUG_AARCH64
74 1.1 christos if (CONST_STRNEQ (option, "debug_dump"))
75 1.1 christos {
76 1.1 christos debug_dump = 1;
77 1.1 christos return;
78 1.1 christos }
79 1.1 christos #endif /* DEBUG_AARCH64 */
80 1.1 christos
81 1.1 christos /* Invalid option. */
82 1.1 christos fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
83 1.1 christos }
84 1.1 christos
85 1.1 christos static void
86 1.1 christos parse_aarch64_dis_options (const char *options)
87 1.1 christos {
88 1.1 christos const char *option_end;
89 1.1 christos
90 1.1 christos if (options == NULL)
91 1.1 christos return;
92 1.1 christos
93 1.1 christos while (*options != '\0')
94 1.1 christos {
95 1.1 christos /* Skip empty options. */
96 1.1 christos if (*options == ',')
97 1.1 christos {
98 1.1 christos options++;
99 1.1 christos continue;
100 1.1 christos }
101 1.1 christos
102 1.1 christos /* We know that *options is neither NUL or a comma. */
103 1.1 christos option_end = options + 1;
104 1.1 christos while (*option_end != ',' && *option_end != '\0')
105 1.1 christos option_end++;
106 1.1 christos
107 1.1 christos parse_aarch64_dis_option (options, option_end - options);
108 1.1 christos
109 1.1 christos /* Go on to the next one. If option_end points to a comma, it
110 1.1 christos will be skipped above. */
111 1.1 christos options = option_end;
112 1.1 christos }
113 1.1 christos }
114 1.1 christos
115 1.1 christos /* Functions doing the instruction disassembling. */
117 1.1 christos
118 1.1 christos /* The unnamed arguments consist of the number of fields and information about
119 1.1 christos these fields where the VALUE will be extracted from CODE and returned.
120 1.1 christos MASK can be zero or the base mask of the opcode.
121 1.1 christos
122 1.1 christos N.B. the fields are required to be in such an order than the most signficant
123 1.3 christos field for VALUE comes the first, e.g. the <index> in
124 1.1 christos SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
125 1.1 christos is encoded in H:L:M in some cases, the fields H:L:M should be passed in
126 1.1 christos the order of H, L, M. */
127 1.1 christos
128 1.1 christos static inline aarch64_insn
129 1.1 christos extract_fields (aarch64_insn code, aarch64_insn mask, ...)
130 1.1 christos {
131 1.1 christos uint32_t num;
132 1.1 christos const aarch64_field *field;
133 1.3 christos enum aarch64_field_kind kind;
134 1.1 christos va_list va;
135 1.1 christos
136 1.1 christos va_start (va, mask);
137 1.1 christos num = va_arg (va, uint32_t);
138 1.1 christos assert (num <= 5);
139 1.1 christos aarch64_insn value = 0x0;
140 1.1 christos while (num--)
141 1.1 christos {
142 1.1 christos kind = va_arg (va, enum aarch64_field_kind);
143 1.1 christos field = &fields[kind];
144 1.1 christos value <<= field->width;
145 1.1 christos value |= extract_field (kind, code, mask);
146 1.1 christos }
147 1.1 christos return value;
148 1.1 christos }
149 1.1 christos
150 1.1 christos /* Sign-extend bit I of VALUE. */
151 1.1 christos static inline int32_t
152 1.1 christos sign_extend (aarch64_insn value, unsigned i)
153 1.3 christos {
154 1.1 christos uint32_t ret = value;
155 1.1 christos
156 1.1 christos assert (i < 32);
157 1.1 christos if ((value >> i) & 0x1)
158 1.1 christos {
159 1.1 christos uint32_t val = (uint32_t)(-1) << i;
160 1.1 christos ret = ret | val;
161 1.1 christos }
162 1.1 christos return (int32_t) ret;
163 1.1 christos }
164 1.1 christos
165 1.1 christos /* N.B. the following inline helpfer functions create a dependency on the
166 1.1 christos order of operand qualifier enumerators. */
167 1.1 christos
168 1.1 christos /* Given VALUE, return qualifier for a general purpose register. */
169 1.1 christos static inline enum aarch64_opnd_qualifier
170 1.1 christos get_greg_qualifier_from_value (aarch64_insn value)
171 1.1 christos {
172 1.1 christos enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_W + value;
173 1.1 christos assert (value <= 0x1
174 1.1 christos && aarch64_get_qualifier_standard_value (qualifier) == value);
175 1.1 christos return qualifier;
176 1.3 christos }
177 1.3 christos
178 1.3 christos /* Given VALUE, return qualifier for a vector register. This does not support
179 1.1 christos decoding instructions that accept the 2H vector type. */
180 1.1 christos
181 1.1 christos static inline enum aarch64_opnd_qualifier
182 1.1 christos get_vreg_qualifier_from_value (aarch64_insn value)
183 1.3 christos {
184 1.3 christos enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_V_8B + value;
185 1.3 christos
186 1.3 christos /* Instructions using vector type 2H should not call this function. Skip over
187 1.3 christos the 2H qualifier. */
188 1.3 christos if (qualifier >= AARCH64_OPND_QLF_V_2H)
189 1.1 christos qualifier += 1;
190 1.1 christos
191 1.1 christos assert (value <= 0x8
192 1.1 christos && aarch64_get_qualifier_standard_value (qualifier) == value);
193 1.1 christos return qualifier;
194 1.1 christos }
195 1.1 christos
196 1.1 christos /* Given VALUE, return qualifier for an FP or AdvSIMD scalar register. */
197 1.1 christos static inline enum aarch64_opnd_qualifier
198 1.1 christos get_sreg_qualifier_from_value (aarch64_insn value)
199 1.3 christos {
200 1.1 christos enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_S_B + value;
201 1.1 christos
202 1.1 christos assert (value <= 0x4
203 1.1 christos && aarch64_get_qualifier_standard_value (qualifier) == value);
204 1.1 christos return qualifier;
205 1.1 christos }
206 1.1 christos
207 1.1 christos /* Given the instruction in *INST which is probably half way through the
208 1.1 christos decoding and our caller wants to know the expected qualifier for operand
209 1.1 christos I. Return such a qualifier if we can establish it; otherwise return
210 1.1 christos AARCH64_OPND_QLF_NIL. */
211 1.1 christos
212 1.1 christos static aarch64_opnd_qualifier_t
213 1.1 christos get_expected_qualifier (const aarch64_inst *inst, int i)
214 1.1 christos {
215 1.1 christos aarch64_opnd_qualifier_seq_t qualifiers;
216 1.1 christos /* Should not be called if the qualifier is known. */
217 1.1 christos assert (inst->operands[i].qualifier == AARCH64_OPND_QLF_NIL);
218 1.1 christos if (aarch64_find_best_match (inst, inst->opcode->qualifiers_list,
219 1.1 christos i, qualifiers))
220 1.1 christos return qualifiers[i];
221 1.1 christos else
222 1.1 christos return AARCH64_OPND_QLF_NIL;
223 1.1 christos }
224 1.1 christos
225 1.1 christos /* Operand extractors. */
226 1.1 christos
227 1.1 christos int
228 1.1 christos aarch64_ext_regno (const aarch64_operand *self, aarch64_opnd_info *info,
229 1.1 christos const aarch64_insn code,
230 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
231 1.1 christos {
232 1.1 christos info->reg.regno = extract_field (self->fields[0], code, 0);
233 1.1 christos return 1;
234 1.3 christos }
235 1.3 christos
236 1.3 christos int
237 1.3 christos aarch64_ext_regno_pair (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info,
238 1.3 christos const aarch64_insn code ATTRIBUTE_UNUSED,
239 1.3 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
240 1.3 christos {
241 1.3 christos assert (info->idx == 1
242 1.3 christos || info->idx ==3);
243 1.3 christos info->reg.regno = inst->operands[info->idx - 1].reg.regno + 1;
244 1.3 christos return 1;
245 1.1 christos }
246 1.1 christos
247 1.1 christos /* e.g. IC <ic_op>{, <Xt>}. */
248 1.1 christos int
249 1.1 christos aarch64_ext_regrt_sysins (const aarch64_operand *self, aarch64_opnd_info *info,
250 1.1 christos const aarch64_insn code,
251 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
252 1.1 christos {
253 1.1 christos info->reg.regno = extract_field (self->fields[0], code, 0);
254 1.1 christos assert (info->idx == 1
255 1.1 christos && (aarch64_get_operand_class (inst->operands[0].type)
256 1.1 christos == AARCH64_OPND_CLASS_SYSTEM));
257 1.1 christos /* This will make the constraint checking happy and more importantly will
258 1.3 christos help the disassembler determine whether this operand is optional or
259 1.1 christos not. */
260 1.1 christos info->present = aarch64_sys_ins_reg_has_xt (inst->operands[0].sysins_op);
261 1.1 christos
262 1.1 christos return 1;
263 1.1 christos }
264 1.1 christos
265 1.1 christos /* e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]. */
266 1.1 christos int
267 1.1 christos aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info,
268 1.1 christos const aarch64_insn code,
269 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
270 1.1 christos {
271 1.1 christos /* regno */
272 1.1 christos info->reglane.regno = extract_field (self->fields[0], code,
273 1.3 christos inst->opcode->mask);
274 1.1 christos
275 1.1 christos /* Index and/or type. */
276 1.1 christos if (inst->opcode->iclass == asisdone
277 1.1 christos || inst->opcode->iclass == asimdins)
278 1.1 christos {
279 1.1 christos if (info->type == AARCH64_OPND_En
280 1.1 christos && inst->opcode->operands[0] == AARCH64_OPND_Ed)
281 1.1 christos {
282 1.1 christos unsigned shift;
283 1.1 christos /* index2 for e.g. INS <Vd>.<Ts>[<index1>], <Vn>.<Ts>[<index2>]. */
284 1.1 christos assert (info->idx == 1); /* Vn */
285 1.1 christos aarch64_insn value = extract_field (FLD_imm4, code, 0);
286 1.1 christos /* Depend on AARCH64_OPND_Ed to determine the qualifier. */
287 1.1 christos info->qualifier = get_expected_qualifier (inst, info->idx);
288 1.1 christos shift = get_logsz (aarch64_get_qualifier_esize (info->qualifier));
289 1.1 christos info->reglane.index = value >> shift;
290 1.1 christos }
291 1.1 christos else
292 1.1 christos {
293 1.1 christos /* index and type for e.g. DUP <V><d>, <Vn>.<T>[<index>].
294 1.1 christos imm5<3:0> <V>
295 1.1 christos 0000 RESERVED
296 1.1 christos xxx1 B
297 1.1 christos xx10 H
298 1.1 christos x100 S
299 1.1 christos 1000 D */
300 1.1 christos int pos = -1;
301 1.1 christos aarch64_insn value = extract_field (FLD_imm5, code, 0);
302 1.1 christos while (++pos <= 3 && (value & 0x1) == 0)
303 1.1 christos value >>= 1;
304 1.1 christos if (pos > 3)
305 1.1 christos return 0;
306 1.1 christos info->qualifier = get_sreg_qualifier_from_value (pos);
307 1.1 christos info->reglane.index = (unsigned) (value >> 1);
308 1.1 christos }
309 1.1 christos }
310 1.3 christos else
311 1.1 christos {
312 1.1 christos /* Index only for e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
313 1.1 christos or SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]. */
314 1.1 christos
315 1.1 christos /* Need information in other operand(s) to help decoding. */
316 1.1 christos info->qualifier = get_expected_qualifier (inst, info->idx);
317 1.1 christos switch (info->qualifier)
318 1.1 christos {
319 1.1 christos case AARCH64_OPND_QLF_S_H:
320 1.1 christos /* h:l:m */
321 1.1 christos info->reglane.index = extract_fields (code, 0, 3, FLD_H, FLD_L,
322 1.1 christos FLD_M);
323 1.1 christos info->reglane.regno &= 0xf;
324 1.1 christos break;
325 1.1 christos case AARCH64_OPND_QLF_S_S:
326 1.1 christos /* h:l */
327 1.1 christos info->reglane.index = extract_fields (code, 0, 2, FLD_H, FLD_L);
328 1.1 christos break;
329 1.1 christos case AARCH64_OPND_QLF_S_D:
330 1.1 christos /* H */
331 1.1 christos info->reglane.index = extract_field (FLD_H, code, 0);
332 1.1 christos break;
333 1.1 christos default:
334 1.1 christos return 0;
335 1.1 christos }
336 1.1 christos }
337 1.1 christos
338 1.1 christos return 1;
339 1.1 christos }
340 1.1 christos
341 1.1 christos int
342 1.1 christos aarch64_ext_reglist (const aarch64_operand *self, aarch64_opnd_info *info,
343 1.1 christos const aarch64_insn code,
344 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
345 1.1 christos {
346 1.1 christos /* R */
347 1.1 christos info->reglist.first_regno = extract_field (self->fields[0], code, 0);
348 1.1 christos /* len */
349 1.1 christos info->reglist.num_regs = extract_field (FLD_len, code, 0) + 1;
350 1.1 christos return 1;
351 1.1 christos }
352 1.1 christos
353 1.1 christos /* Decode Rt and opcode fields of Vt in AdvSIMD load/store instructions. */
354 1.1 christos int
355 1.1 christos aarch64_ext_ldst_reglist (const aarch64_operand *self ATTRIBUTE_UNUSED,
356 1.1 christos aarch64_opnd_info *info, const aarch64_insn code,
357 1.1 christos const aarch64_inst *inst)
358 1.1 christos {
359 1.1 christos aarch64_insn value;
360 1.1 christos /* Number of elements in each structure to be loaded/stored. */
361 1.1 christos unsigned expected_num = get_opcode_dependent_value (inst->opcode);
362 1.1 christos
363 1.1 christos struct
364 1.1 christos {
365 1.1 christos unsigned is_reserved;
366 1.1 christos unsigned num_regs;
367 1.1 christos unsigned num_elements;
368 1.1 christos } data [] =
369 1.1 christos { {0, 4, 4},
370 1.1 christos {1, 4, 4},
371 1.1 christos {0, 4, 1},
372 1.1 christos {0, 4, 2},
373 1.1 christos {0, 3, 3},
374 1.1 christos {1, 3, 3},
375 1.1 christos {0, 3, 1},
376 1.1 christos {0, 1, 1},
377 1.1 christos {0, 2, 2},
378 1.1 christos {1, 2, 2},
379 1.1 christos {0, 2, 1},
380 1.1 christos };
381 1.1 christos
382 1.1 christos /* Rt */
383 1.1 christos info->reglist.first_regno = extract_field (FLD_Rt, code, 0);
384 1.1 christos /* opcode */
385 1.1 christos value = extract_field (FLD_opcode, code, 0);
386 1.1 christos if (expected_num != data[value].num_elements || data[value].is_reserved)
387 1.1 christos return 0;
388 1.1 christos info->reglist.num_regs = data[value].num_regs;
389 1.1 christos
390 1.1 christos return 1;
391 1.1 christos }
392 1.1 christos
393 1.1 christos /* Decode Rt and S fields of Vt in AdvSIMD load single structure to all
394 1.1 christos lanes instructions. */
395 1.1 christos int
396 1.1 christos aarch64_ext_ldst_reglist_r (const aarch64_operand *self ATTRIBUTE_UNUSED,
397 1.1 christos aarch64_opnd_info *info, const aarch64_insn code,
398 1.1 christos const aarch64_inst *inst)
399 1.1 christos {
400 1.1 christos aarch64_insn value;
401 1.1 christos
402 1.1 christos /* Rt */
403 1.1 christos info->reglist.first_regno = extract_field (FLD_Rt, code, 0);
404 1.1 christos /* S */
405 1.1 christos value = extract_field (FLD_S, code, 0);
406 1.1 christos
407 1.1 christos /* Number of registers is equal to the number of elements in
408 1.1 christos each structure to be loaded/stored. */
409 1.1 christos info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
410 1.1 christos assert (info->reglist.num_regs >= 1 && info->reglist.num_regs <= 4);
411 1.1 christos
412 1.1 christos /* Except when it is LD1R. */
413 1.1 christos if (info->reglist.num_regs == 1 && value == (aarch64_insn) 1)
414 1.1 christos info->reglist.num_regs = 2;
415 1.1 christos
416 1.1 christos return 1;
417 1.1 christos }
418 1.1 christos
419 1.1 christos /* Decode Q, opcode<2:1>, S, size and Rt fields of Vt in AdvSIMD
420 1.1 christos load/store single element instructions. */
421 1.1 christos int
422 1.1 christos aarch64_ext_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED,
423 1.1 christos aarch64_opnd_info *info, const aarch64_insn code,
424 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
425 1.1 christos {
426 1.1 christos aarch64_field field = {0, 0};
427 1.1 christos aarch64_insn QSsize; /* fields Q:S:size. */
428 1.1 christos aarch64_insn opcodeh2; /* opcode<2:1> */
429 1.1 christos
430 1.1 christos /* Rt */
431 1.1 christos info->reglist.first_regno = extract_field (FLD_Rt, code, 0);
432 1.1 christos
433 1.1 christos /* Decode the index, opcode<2:1> and size. */
434 1.1 christos gen_sub_field (FLD_asisdlso_opcode, 1, 2, &field);
435 1.1 christos opcodeh2 = extract_field_2 (&field, code, 0);
436 1.1 christos QSsize = extract_fields (code, 0, 3, FLD_Q, FLD_S, FLD_vldst_size);
437 1.1 christos switch (opcodeh2)
438 1.1 christos {
439 1.1 christos case 0x0:
440 1.1 christos info->qualifier = AARCH64_OPND_QLF_S_B;
441 1.1 christos /* Index encoded in "Q:S:size". */
442 1.1 christos info->reglist.index = QSsize;
443 1.3 christos break;
444 1.3 christos case 0x1:
445 1.3 christos if (QSsize & 0x1)
446 1.1 christos /* UND. */
447 1.1 christos return 0;
448 1.1 christos info->qualifier = AARCH64_OPND_QLF_S_H;
449 1.1 christos /* Index encoded in "Q:S:size<1>". */
450 1.1 christos info->reglist.index = QSsize >> 1;
451 1.3 christos break;
452 1.3 christos case 0x2:
453 1.3 christos if ((QSsize >> 1) & 0x1)
454 1.1 christos /* UND. */
455 1.1 christos return 0;
456 1.1 christos if ((QSsize & 0x1) == 0)
457 1.1 christos {
458 1.1 christos info->qualifier = AARCH64_OPND_QLF_S_S;
459 1.1 christos /* Index encoded in "Q:S". */
460 1.1 christos info->reglist.index = QSsize >> 2;
461 1.1 christos }
462 1.3 christos else
463 1.3 christos {
464 1.3 christos if (extract_field (FLD_S, code, 0))
465 1.1 christos /* UND */
466 1.1 christos return 0;
467 1.1 christos info->qualifier = AARCH64_OPND_QLF_S_D;
468 1.1 christos /* Index encoded in "Q". */
469 1.1 christos info->reglist.index = QSsize >> 3;
470 1.1 christos }
471 1.1 christos break;
472 1.1 christos default:
473 1.1 christos return 0;
474 1.1 christos }
475 1.1 christos
476 1.1 christos info->reglist.has_index = 1;
477 1.1 christos info->reglist.num_regs = 0;
478 1.1 christos /* Number of registers is equal to the number of elements in
479 1.1 christos each structure to be loaded/stored. */
480 1.1 christos info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
481 1.1 christos assert (info->reglist.num_regs >= 1 && info->reglist.num_regs <= 4);
482 1.1 christos
483 1.1 christos return 1;
484 1.1 christos }
485 1.1 christos
486 1.1 christos /* Decode fields immh:immb and/or Q for e.g.
487 1.1 christos SSHR <Vd>.<T>, <Vn>.<T>, #<shift>
488 1.1 christos or SSHR <V><d>, <V><n>, #<shift>. */
489 1.1 christos
490 1.1 christos int
491 1.1 christos aarch64_ext_advsimd_imm_shift (const aarch64_operand *self ATTRIBUTE_UNUSED,
492 1.1 christos aarch64_opnd_info *info, const aarch64_insn code,
493 1.1 christos const aarch64_inst *inst)
494 1.1 christos {
495 1.1 christos int pos;
496 1.1 christos aarch64_insn Q, imm, immh;
497 1.1 christos enum aarch64_insn_class iclass = inst->opcode->iclass;
498 1.1 christos
499 1.1 christos immh = extract_field (FLD_immh, code, 0);
500 1.1 christos if (immh == 0)
501 1.1 christos return 0;
502 1.1 christos imm = extract_fields (code, 0, 2, FLD_immh, FLD_immb);
503 1.1 christos pos = 4;
504 1.1 christos /* Get highest set bit in immh. */
505 1.1 christos while (--pos >= 0 && (immh & 0x8) == 0)
506 1.1 christos immh <<= 1;
507 1.1 christos
508 1.1 christos assert ((iclass == asimdshf || iclass == asisdshf)
509 1.1 christos && (info->type == AARCH64_OPND_IMM_VLSR
510 1.1 christos || info->type == AARCH64_OPND_IMM_VLSL));
511 1.1 christos
512 1.1 christos if (iclass == asimdshf)
513 1.1 christos {
514 1.1 christos Q = extract_field (FLD_Q, code, 0);
515 1.1 christos /* immh Q <T>
516 1.1 christos 0000 x SEE AdvSIMD modified immediate
517 1.1 christos 0001 0 8B
518 1.1 christos 0001 1 16B
519 1.1 christos 001x 0 4H
520 1.1 christos 001x 1 8H
521 1.1 christos 01xx 0 2S
522 1.1 christos 01xx 1 4S
523 1.1 christos 1xxx 0 RESERVED
524 1.1 christos 1xxx 1 2D */
525 1.1 christos info->qualifier =
526 1.1 christos get_vreg_qualifier_from_value ((pos << 1) | (int) Q);
527 1.1 christos }
528 1.1 christos else
529 1.1 christos info->qualifier = get_sreg_qualifier_from_value (pos);
530 1.1 christos
531 1.1 christos if (info->type == AARCH64_OPND_IMM_VLSR)
532 1.1 christos /* immh <shift>
533 1.1 christos 0000 SEE AdvSIMD modified immediate
534 1.1 christos 0001 (16-UInt(immh:immb))
535 1.1 christos 001x (32-UInt(immh:immb))
536 1.1 christos 01xx (64-UInt(immh:immb))
537 1.1 christos 1xxx (128-UInt(immh:immb)) */
538 1.1 christos info->imm.value = (16 << pos) - imm;
539 1.1 christos else
540 1.1 christos /* immh:immb
541 1.1 christos immh <shift>
542 1.1 christos 0000 SEE AdvSIMD modified immediate
543 1.1 christos 0001 (UInt(immh:immb)-8)
544 1.1 christos 001x (UInt(immh:immb)-16)
545 1.1 christos 01xx (UInt(immh:immb)-32)
546 1.1 christos 1xxx (UInt(immh:immb)-64) */
547 1.1 christos info->imm.value = imm - (8 << pos);
548 1.1 christos
549 1.1 christos return 1;
550 1.1 christos }
551 1.1 christos
552 1.1 christos /* Decode shift immediate for e.g. sshr (imm). */
553 1.1 christos int
554 1.1 christos aarch64_ext_shll_imm (const aarch64_operand *self ATTRIBUTE_UNUSED,
555 1.1 christos aarch64_opnd_info *info, const aarch64_insn code,
556 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
557 1.1 christos {
558 1.1 christos int64_t imm;
559 1.1 christos aarch64_insn val;
560 1.1 christos val = extract_field (FLD_size, code, 0);
561 1.1 christos switch (val)
562 1.1 christos {
563 1.1 christos case 0: imm = 8; break;
564 1.1 christos case 1: imm = 16; break;
565 1.1 christos case 2: imm = 32; break;
566 1.1 christos default: return 0;
567 1.1 christos }
568 1.1 christos info->imm.value = imm;
569 1.1 christos return 1;
570 1.1 christos }
571 1.1 christos
572 1.1 christos /* Decode imm for e.g. BFM <Wd>, <Wn>, #<immr>, #<imms>.
573 1.1 christos value in the field(s) will be extracted as unsigned immediate value. */
574 1.1 christos int
575 1.1 christos aarch64_ext_imm (const aarch64_operand *self, aarch64_opnd_info *info,
576 1.1 christos const aarch64_insn code,
577 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
578 1.1 christos {
579 1.1 christos int64_t imm;
580 1.1 christos /* Maximum of two fields to extract. */
581 1.1 christos assert (self->fields[2] == FLD_NIL);
582 1.1 christos
583 1.1 christos if (self->fields[1] == FLD_NIL)
584 1.1 christos imm = extract_field (self->fields[0], code, 0);
585 1.1 christos else
586 1.1 christos /* e.g. TBZ b5:b40. */
587 1.1 christos imm = extract_fields (code, 0, 2, self->fields[0], self->fields[1]);
588 1.1 christos
589 1.1 christos if (info->type == AARCH64_OPND_FPIMM)
590 1.1 christos info->imm.is_fp = 1;
591 1.1 christos
592 1.1 christos if (operand_need_sign_extension (self))
593 1.1 christos imm = sign_extend (imm, get_operand_fields_width (self) - 1);
594 1.1 christos
595 1.1 christos if (operand_need_shift_by_two (self))
596 1.1 christos imm <<= 2;
597 1.1 christos
598 1.1 christos if (info->type == AARCH64_OPND_ADDR_ADRP)
599 1.1 christos imm <<= 12;
600 1.1 christos
601 1.1 christos info->imm.value = imm;
602 1.1 christos return 1;
603 1.1 christos }
604 1.1 christos
605 1.1 christos /* Decode imm and its shifter for e.g. MOVZ <Wd>, #<imm16>{, LSL #<shift>}. */
606 1.1 christos int
607 1.1 christos aarch64_ext_imm_half (const aarch64_operand *self, aarch64_opnd_info *info,
608 1.1 christos const aarch64_insn code,
609 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
610 1.1 christos {
611 1.1 christos aarch64_ext_imm (self, info, code, inst);
612 1.1 christos info->shifter.kind = AARCH64_MOD_LSL;
613 1.1 christos info->shifter.amount = extract_field (FLD_hw, code, 0) << 4;
614 1.1 christos return 1;
615 1.1 christos }
616 1.1 christos
617 1.1 christos /* Decode cmode and "a:b:c:d:e:f:g:h" for e.g.
618 1.1 christos MOVI <Vd>.<T>, #<imm8> {, LSL #<amount>}. */
619 1.1 christos int
620 1.1 christos aarch64_ext_advsimd_imm_modified (const aarch64_operand *self ATTRIBUTE_UNUSED,
621 1.1 christos aarch64_opnd_info *info,
622 1.1 christos const aarch64_insn code,
623 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
624 1.1 christos {
625 1.1 christos uint64_t imm;
626 1.1 christos enum aarch64_opnd_qualifier opnd0_qualifier = inst->operands[0].qualifier;
627 1.1 christos aarch64_field field = {0, 0};
628 1.1 christos
629 1.1 christos assert (info->idx == 1);
630 1.1 christos
631 1.1 christos if (info->type == AARCH64_OPND_SIMD_FPIMM)
632 1.1 christos info->imm.is_fp = 1;
633 1.1 christos
634 1.1 christos /* a:b:c:d:e:f:g:h */
635 1.1 christos imm = extract_fields (code, 0, 2, FLD_abc, FLD_defgh);
636 1.1 christos if (!info->imm.is_fp && aarch64_get_qualifier_esize (opnd0_qualifier) == 8)
637 1.1 christos {
638 1.1 christos /* Either MOVI <Dd>, #<imm>
639 1.1 christos or MOVI <Vd>.2D, #<imm>.
640 1.1 christos <imm> is a 64-bit immediate
641 1.1 christos 'aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh',
642 1.1 christos encoded in "a:b:c:d:e:f:g:h". */
643 1.1 christos int i;
644 1.1 christos unsigned abcdefgh = imm;
645 1.1 christos for (imm = 0ull, i = 0; i < 8; i++)
646 1.1 christos if (((abcdefgh >> i) & 0x1) != 0)
647 1.1 christos imm |= 0xffull << (8 * i);
648 1.1 christos }
649 1.1 christos info->imm.value = imm;
650 1.1 christos
651 1.1 christos /* cmode */
652 1.1 christos info->qualifier = get_expected_qualifier (inst, info->idx);
653 1.1 christos switch (info->qualifier)
654 1.1 christos {
655 1.1 christos case AARCH64_OPND_QLF_NIL:
656 1.1 christos /* no shift */
657 1.1 christos info->shifter.kind = AARCH64_MOD_NONE;
658 1.1 christos return 1;
659 1.1 christos case AARCH64_OPND_QLF_LSL:
660 1.1 christos /* shift zeros */
661 1.1 christos info->shifter.kind = AARCH64_MOD_LSL;
662 1.1 christos switch (aarch64_get_qualifier_esize (opnd0_qualifier))
663 1.1 christos {
664 1.3 christos case 4: gen_sub_field (FLD_cmode, 1, 2, &field); break; /* per word */
665 1.1 christos case 2: gen_sub_field (FLD_cmode, 1, 1, &field); break; /* per half */
666 1.1 christos case 1: gen_sub_field (FLD_cmode, 1, 0, &field); break; /* per byte */
667 1.1 christos default: assert (0); return 0;
668 1.1 christos }
669 1.1 christos /* 00: 0; 01: 8; 10:16; 11:24. */
670 1.1 christos info->shifter.amount = extract_field_2 (&field, code, 0) << 3;
671 1.1 christos break;
672 1.1 christos case AARCH64_OPND_QLF_MSL:
673 1.1 christos /* shift ones */
674 1.1 christos info->shifter.kind = AARCH64_MOD_MSL;
675 1.1 christos gen_sub_field (FLD_cmode, 0, 1, &field); /* per word */
676 1.1 christos info->shifter.amount = extract_field_2 (&field, code, 0) ? 16 : 8;
677 1.1 christos break;
678 1.1 christos default:
679 1.1 christos assert (0);
680 1.1 christos return 0;
681 1.1 christos }
682 1.1 christos
683 1.1 christos return 1;
684 1.1 christos }
685 1.1 christos
686 1.1 christos /* Decode scale for e.g. SCVTF <Dd>, <Wn>, #<fbits>. */
687 1.1 christos int
688 1.1 christos aarch64_ext_fbits (const aarch64_operand *self ATTRIBUTE_UNUSED,
689 1.1 christos aarch64_opnd_info *info, const aarch64_insn code,
690 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
691 1.1 christos {
692 1.1 christos info->imm.value = 64- extract_field (FLD_scale, code, 0);
693 1.1 christos return 1;
694 1.1 christos }
695 1.1 christos
696 1.1 christos /* Decode arithmetic immediate for e.g.
697 1.1 christos SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}. */
698 1.1 christos int
699 1.1 christos aarch64_ext_aimm (const aarch64_operand *self ATTRIBUTE_UNUSED,
700 1.1 christos aarch64_opnd_info *info, const aarch64_insn code,
701 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
702 1.1 christos {
703 1.1 christos aarch64_insn value;
704 1.1 christos
705 1.1 christos info->shifter.kind = AARCH64_MOD_LSL;
706 1.1 christos /* shift */
707 1.1 christos value = extract_field (FLD_shift, code, 0);
708 1.1 christos if (value >= 2)
709 1.1 christos return 0;
710 1.1 christos info->shifter.amount = value ? 12 : 0;
711 1.1 christos /* imm12 (unsigned) */
712 1.1 christos info->imm.value = extract_field (FLD_imm12, code, 0);
713 1.1 christos
714 1.1 christos return 1;
715 1.1 christos }
716 1.1 christos
717 1.1 christos /* Decode logical immediate for e.g. ORR <Wd|WSP>, <Wn>, #<imm>. */
718 1.1 christos
719 1.1 christos int
720 1.1 christos aarch64_ext_limm (const aarch64_operand *self ATTRIBUTE_UNUSED,
721 1.1 christos aarch64_opnd_info *info, const aarch64_insn code,
722 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
723 1.1 christos {
724 1.1 christos uint64_t imm, mask;
725 1.1 christos uint32_t sf;
726 1.1 christos uint32_t N, R, S;
727 1.1 christos unsigned simd_size;
728 1.1 christos aarch64_insn value;
729 1.1 christos
730 1.1 christos value = extract_fields (code, 0, 3, FLD_N, FLD_immr, FLD_imms);
731 1.1 christos assert (inst->operands[0].qualifier == AARCH64_OPND_QLF_W
732 1.1 christos || inst->operands[0].qualifier == AARCH64_OPND_QLF_X);
733 1.1 christos sf = aarch64_get_qualifier_esize (inst->operands[0].qualifier) != 4;
734 1.1 christos
735 1.1 christos /* value is N:immr:imms. */
736 1.1 christos S = value & 0x3f;
737 1.1 christos R = (value >> 6) & 0x3f;
738 1.1 christos N = (value >> 12) & 0x1;
739 1.1 christos
740 1.1 christos if (sf == 0 && N == 1)
741 1.1 christos return 0;
742 1.3 christos
743 1.1 christos /* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
744 1.1 christos (in other words, right rotated by R), then replicated. */
745 1.1 christos if (N != 0)
746 1.1 christos {
747 1.1 christos simd_size = 64;
748 1.1 christos mask = 0xffffffffffffffffull;
749 1.1 christos }
750 1.1 christos else
751 1.1 christos {
752 1.1 christos switch (S)
753 1.1 christos {
754 1.1 christos case 0x00 ... 0x1f: /* 0xxxxx */ simd_size = 32; break;
755 1.1 christos case 0x20 ... 0x2f: /* 10xxxx */ simd_size = 16; S &= 0xf; break;
756 1.1 christos case 0x30 ... 0x37: /* 110xxx */ simd_size = 8; S &= 0x7; break;
757 1.1 christos case 0x38 ... 0x3b: /* 1110xx */ simd_size = 4; S &= 0x3; break;
758 1.1 christos case 0x3c ... 0x3d: /* 11110x */ simd_size = 2; S &= 0x1; break;
759 1.1 christos default: return 0;
760 1.1 christos }
761 1.1 christos mask = (1ull << simd_size) - 1;
762 1.1 christos /* Top bits are IGNORED. */
763 1.1 christos R &= simd_size - 1;
764 1.1 christos }
765 1.1 christos /* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */
766 1.1 christos if (S == simd_size - 1)
767 1.1 christos return 0;
768 1.1 christos /* S+1 consecutive bits to 1. */
769 1.1 christos /* NOTE: S can't be 63 due to detection above. */
770 1.1 christos imm = (1ull << (S + 1)) - 1;
771 1.1 christos /* Rotate to the left by simd_size - R. */
772 1.1 christos if (R != 0)
773 1.1 christos imm = ((imm << (simd_size - R)) & mask) | (imm >> R);
774 1.1 christos /* Replicate the value according to SIMD size. */
775 1.1 christos switch (simd_size)
776 1.1 christos {
777 1.1 christos case 2: imm = (imm << 2) | imm;
778 1.1 christos case 4: imm = (imm << 4) | imm;
779 1.1 christos case 8: imm = (imm << 8) | imm;
780 1.1 christos case 16: imm = (imm << 16) | imm;
781 1.1 christos case 32: imm = (imm << 32) | imm;
782 1.1 christos case 64: break;
783 1.1 christos default: assert (0); return 0;
784 1.1 christos }
785 1.1 christos
786 1.1 christos info->imm.value = sf ? imm : imm & 0xffffffff;
787 1.1 christos
788 1.1 christos return 1;
789 1.1 christos }
790 1.1 christos
791 1.1 christos /* Decode Ft for e.g. STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]
792 1.1 christos or LDP <Qt1>, <Qt2>, [<Xn|SP>], #<imm>. */
793 1.1 christos int
794 1.1 christos aarch64_ext_ft (const aarch64_operand *self ATTRIBUTE_UNUSED,
795 1.1 christos aarch64_opnd_info *info,
796 1.1 christos const aarch64_insn code, const aarch64_inst *inst)
797 1.1 christos {
798 1.1 christos aarch64_insn value;
799 1.1 christos
800 1.1 christos /* Rt */
801 1.1 christos info->reg.regno = extract_field (FLD_Rt, code, 0);
802 1.1 christos
803 1.1 christos /* size */
804 1.1 christos value = extract_field (FLD_ldst_size, code, 0);
805 1.1 christos if (inst->opcode->iclass == ldstpair_indexed
806 1.1 christos || inst->opcode->iclass == ldstnapair_offs
807 1.1 christos || inst->opcode->iclass == ldstpair_off
808 1.1 christos || inst->opcode->iclass == loadlit)
809 1.1 christos {
810 1.1 christos enum aarch64_opnd_qualifier qualifier;
811 1.1 christos switch (value)
812 1.1 christos {
813 1.1 christos case 0: qualifier = AARCH64_OPND_QLF_S_S; break;
814 1.1 christos case 1: qualifier = AARCH64_OPND_QLF_S_D; break;
815 1.1 christos case 2: qualifier = AARCH64_OPND_QLF_S_Q; break;
816 1.1 christos default: return 0;
817 1.1 christos }
818 1.1 christos info->qualifier = qualifier;
819 1.1 christos }
820 1.1 christos else
821 1.1 christos {
822 1.1 christos /* opc1:size */
823 1.1 christos value = extract_fields (code, 0, 2, FLD_opc1, FLD_ldst_size);
824 1.1 christos if (value > 0x4)
825 1.1 christos return 0;
826 1.1 christos info->qualifier = get_sreg_qualifier_from_value (value);
827 1.1 christos }
828 1.1 christos
829 1.1 christos return 1;
830 1.1 christos }
831 1.1 christos
832 1.1 christos /* Decode the address operand for e.g. STXRB <Ws>, <Wt>, [<Xn|SP>{,#0}]. */
833 1.1 christos int
834 1.1 christos aarch64_ext_addr_simple (const aarch64_operand *self ATTRIBUTE_UNUSED,
835 1.1 christos aarch64_opnd_info *info,
836 1.1 christos aarch64_insn code,
837 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
838 1.1 christos {
839 1.1 christos /* Rn */
840 1.1 christos info->addr.base_regno = extract_field (FLD_Rn, code, 0);
841 1.1 christos return 1;
842 1.1 christos }
843 1.1 christos
844 1.1 christos /* Decode the address operand for e.g.
845 1.1 christos STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
846 1.1 christos int
847 1.1 christos aarch64_ext_addr_regoff (const aarch64_operand *self ATTRIBUTE_UNUSED,
848 1.1 christos aarch64_opnd_info *info,
849 1.1 christos aarch64_insn code, const aarch64_inst *inst)
850 1.1 christos {
851 1.1 christos aarch64_insn S, value;
852 1.1 christos
853 1.1 christos /* Rn */
854 1.1 christos info->addr.base_regno = extract_field (FLD_Rn, code, 0);
855 1.1 christos /* Rm */
856 1.1 christos info->addr.offset.regno = extract_field (FLD_Rm, code, 0);
857 1.1 christos /* option */
858 1.1 christos value = extract_field (FLD_option, code, 0);
859 1.1 christos info->shifter.kind =
860 1.1 christos aarch64_get_operand_modifier_from_value (value, TRUE /* extend_p */);
861 1.1 christos /* Fix-up the shifter kind; although the table-driven approach is
862 1.1 christos efficient, it is slightly inflexible, thus needing this fix-up. */
863 1.1 christos if (info->shifter.kind == AARCH64_MOD_UXTX)
864 1.1 christos info->shifter.kind = AARCH64_MOD_LSL;
865 1.1 christos /* S */
866 1.1 christos S = extract_field (FLD_S, code, 0);
867 1.1 christos if (S == 0)
868 1.1 christos {
869 1.1 christos info->shifter.amount = 0;
870 1.1 christos info->shifter.amount_present = 0;
871 1.1 christos }
872 1.1 christos else
873 1.1 christos {
874 1.1 christos int size;
875 1.1 christos /* Need information in other operand(s) to help achieve the decoding
876 1.1 christos from 'S' field. */
877 1.1 christos info->qualifier = get_expected_qualifier (inst, info->idx);
878 1.1 christos /* Get the size of the data element that is accessed, which may be
879 1.1 christos different from that of the source register size, e.g. in strb/ldrb. */
880 1.1 christos size = aarch64_get_qualifier_esize (info->qualifier);
881 1.1 christos info->shifter.amount = get_logsz (size);
882 1.1 christos info->shifter.amount_present = 1;
883 1.1 christos }
884 1.1 christos
885 1.1 christos return 1;
886 1.1 christos }
887 1.1 christos
888 1.1 christos /* Decode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>], #<simm>. */
889 1.1 christos int
890 1.1 christos aarch64_ext_addr_simm (const aarch64_operand *self, aarch64_opnd_info *info,
891 1.1 christos aarch64_insn code, const aarch64_inst *inst)
892 1.1 christos {
893 1.1 christos aarch64_insn imm;
894 1.1 christos info->qualifier = get_expected_qualifier (inst, info->idx);
895 1.1 christos
896 1.1 christos /* Rn */
897 1.1 christos info->addr.base_regno = extract_field (FLD_Rn, code, 0);
898 1.1 christos /* simm (imm9 or imm7) */
899 1.1 christos imm = extract_field (self->fields[0], code, 0);
900 1.1 christos info->addr.offset.imm = sign_extend (imm, fields[self->fields[0]].width - 1);
901 1.1 christos if (self->fields[0] == FLD_imm7)
902 1.1 christos /* scaled immediate in ld/st pair instructions. */
903 1.1 christos info->addr.offset.imm *= aarch64_get_qualifier_esize (info->qualifier);
904 1.1 christos /* qualifier */
905 1.1 christos if (inst->opcode->iclass == ldst_unscaled
906 1.1 christos || inst->opcode->iclass == ldstnapair_offs
907 1.1 christos || inst->opcode->iclass == ldstpair_off
908 1.1 christos || inst->opcode->iclass == ldst_unpriv)
909 1.1 christos info->addr.writeback = 0;
910 1.1 christos else
911 1.1 christos {
912 1.1 christos /* pre/post- index */
913 1.1 christos info->addr.writeback = 1;
914 1.1 christos if (extract_field (self->fields[1], code, 0) == 1)
915 1.1 christos info->addr.preind = 1;
916 1.1 christos else
917 1.1 christos info->addr.postind = 1;
918 1.1 christos }
919 1.1 christos
920 1.1 christos return 1;
921 1.1 christos }
922 1.1 christos
923 1.1 christos /* Decode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>{, #<simm>}]. */
924 1.1 christos int
925 1.1 christos aarch64_ext_addr_uimm12 (const aarch64_operand *self, aarch64_opnd_info *info,
926 1.1 christos aarch64_insn code,
927 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
928 1.1 christos {
929 1.1 christos int shift;
930 1.1 christos info->qualifier = get_expected_qualifier (inst, info->idx);
931 1.1 christos shift = get_logsz (aarch64_get_qualifier_esize (info->qualifier));
932 1.1 christos /* Rn */
933 1.1 christos info->addr.base_regno = extract_field (self->fields[0], code, 0);
934 1.1 christos /* uimm12 */
935 1.1 christos info->addr.offset.imm = extract_field (self->fields[1], code, 0) << shift;
936 1.1 christos return 1;
937 1.1 christos }
938 1.1 christos
939 1.1 christos /* Decode the address operand for e.g.
940 1.1 christos LD1 {<Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>}, [<Xn|SP>], <Xm|#<amount>>. */
941 1.1 christos int
942 1.1 christos aarch64_ext_simd_addr_post (const aarch64_operand *self ATTRIBUTE_UNUSED,
943 1.1 christos aarch64_opnd_info *info,
944 1.1 christos aarch64_insn code, const aarch64_inst *inst)
945 1.1 christos {
946 1.1 christos /* The opcode dependent area stores the number of elements in
947 1.1 christos each structure to be loaded/stored. */
948 1.1 christos int is_ld1r = get_opcode_dependent_value (inst->opcode) == 1;
949 1.1 christos
950 1.1 christos /* Rn */
951 1.1 christos info->addr.base_regno = extract_field (FLD_Rn, code, 0);
952 1.1 christos /* Rm | #<amount> */
953 1.1 christos info->addr.offset.regno = extract_field (FLD_Rm, code, 0);
954 1.1 christos if (info->addr.offset.regno == 31)
955 1.1 christos {
956 1.1 christos if (inst->opcode->operands[0] == AARCH64_OPND_LVt_AL)
957 1.1 christos /* Special handling of loading single structure to all lane. */
958 1.1 christos info->addr.offset.imm = (is_ld1r ? 1
959 1.1 christos : inst->operands[0].reglist.num_regs)
960 1.1 christos * aarch64_get_qualifier_esize (inst->operands[0].qualifier);
961 1.1 christos else
962 1.1 christos info->addr.offset.imm = inst->operands[0].reglist.num_regs
963 1.1 christos * aarch64_get_qualifier_esize (inst->operands[0].qualifier)
964 1.1 christos * aarch64_get_qualifier_nelem (inst->operands[0].qualifier);
965 1.1 christos }
966 1.1 christos else
967 1.1 christos info->addr.offset.is_reg = 1;
968 1.1 christos info->addr.writeback = 1;
969 1.1 christos
970 1.1 christos return 1;
971 1.1 christos }
972 1.1 christos
973 1.1 christos /* Decode the condition operand for e.g. CSEL <Xd>, <Xn>, <Xm>, <cond>. */
974 1.1 christos int
975 1.1 christos aarch64_ext_cond (const aarch64_operand *self ATTRIBUTE_UNUSED,
976 1.1 christos aarch64_opnd_info *info,
977 1.1 christos aarch64_insn code, const aarch64_inst *inst ATTRIBUTE_UNUSED)
978 1.1 christos {
979 1.1 christos aarch64_insn value;
980 1.1 christos /* cond */
981 1.1 christos value = extract_field (FLD_cond, code, 0);
982 1.1 christos info->cond = get_cond_from_value (value);
983 1.1 christos return 1;
984 1.1 christos }
985 1.1 christos
986 1.1 christos /* Decode the system register operand for e.g. MRS <Xt>, <systemreg>. */
987 1.1 christos int
988 1.1 christos aarch64_ext_sysreg (const aarch64_operand *self ATTRIBUTE_UNUSED,
989 1.1 christos aarch64_opnd_info *info,
990 1.1 christos aarch64_insn code,
991 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
992 1.1 christos {
993 1.1 christos /* op0:op1:CRn:CRm:op2 */
994 1.1 christos info->sysreg = extract_fields (code, 0, 5, FLD_op0, FLD_op1, FLD_CRn,
995 1.1 christos FLD_CRm, FLD_op2);
996 1.1 christos return 1;
997 1.1 christos }
998 1.1 christos
999 1.1 christos /* Decode the PSTATE field operand for e.g. MSR <pstatefield>, #<imm>. */
1000 1.1 christos int
1001 1.1 christos aarch64_ext_pstatefield (const aarch64_operand *self ATTRIBUTE_UNUSED,
1002 1.1 christos aarch64_opnd_info *info, aarch64_insn code,
1003 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
1004 1.1 christos {
1005 1.1 christos int i;
1006 1.1 christos /* op1:op2 */
1007 1.1 christos info->pstatefield = extract_fields (code, 0, 2, FLD_op1, FLD_op2);
1008 1.1 christos for (i = 0; aarch64_pstatefields[i].name != NULL; ++i)
1009 1.1 christos if (aarch64_pstatefields[i].value == (aarch64_insn)info->pstatefield)
1010 1.1 christos return 1;
1011 1.1 christos /* Reserved value in <pstatefield>. */
1012 1.1 christos return 0;
1013 1.1 christos }
1014 1.1 christos
1015 1.1 christos /* Decode the system instruction op operand for e.g. AT <at_op>, <Xt>. */
1016 1.1 christos int
1017 1.1 christos aarch64_ext_sysins_op (const aarch64_operand *self ATTRIBUTE_UNUSED,
1018 1.1 christos aarch64_opnd_info *info,
1019 1.1 christos aarch64_insn code,
1020 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
1021 1.1 christos {
1022 1.1 christos int i;
1023 1.1 christos aarch64_insn value;
1024 1.1 christos const aarch64_sys_ins_reg *sysins_ops;
1025 1.1 christos /* op0:op1:CRn:CRm:op2 */
1026 1.1 christos value = extract_fields (code, 0, 5,
1027 1.1 christos FLD_op0, FLD_op1, FLD_CRn,
1028 1.1 christos FLD_CRm, FLD_op2);
1029 1.1 christos
1030 1.1 christos switch (info->type)
1031 1.1 christos {
1032 1.1 christos case AARCH64_OPND_SYSREG_AT: sysins_ops = aarch64_sys_regs_at; break;
1033 1.1 christos case AARCH64_OPND_SYSREG_DC: sysins_ops = aarch64_sys_regs_dc; break;
1034 1.1 christos case AARCH64_OPND_SYSREG_IC: sysins_ops = aarch64_sys_regs_ic; break;
1035 1.1 christos case AARCH64_OPND_SYSREG_TLBI: sysins_ops = aarch64_sys_regs_tlbi; break;
1036 1.1 christos default: assert (0); return 0;
1037 1.3 christos }
1038 1.1 christos
1039 1.1 christos for (i = 0; sysins_ops[i].name != NULL; ++i)
1040 1.1 christos if (sysins_ops[i].value == value)
1041 1.1 christos {
1042 1.3 christos info->sysins_op = sysins_ops + i;
1043 1.1 christos DEBUG_TRACE ("%s found value: %x, has_xt: %d, i: %d.",
1044 1.3 christos info->sysins_op->name,
1045 1.1 christos (unsigned)info->sysins_op->value,
1046 1.1 christos aarch64_sys_ins_reg_has_xt (info->sysins_op), i);
1047 1.1 christos return 1;
1048 1.1 christos }
1049 1.1 christos
1050 1.1 christos return 0;
1051 1.1 christos }
1052 1.1 christos
1053 1.1 christos /* Decode the memory barrier option operand for e.g. DMB <option>|#<imm>. */
1054 1.1 christos
1055 1.1 christos int
1056 1.1 christos aarch64_ext_barrier (const aarch64_operand *self ATTRIBUTE_UNUSED,
1057 1.1 christos aarch64_opnd_info *info,
1058 1.1 christos aarch64_insn code,
1059 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
1060 1.1 christos {
1061 1.1 christos /* CRm */
1062 1.1 christos info->barrier = aarch64_barrier_options + extract_field (FLD_CRm, code, 0);
1063 1.1 christos return 1;
1064 1.1 christos }
1065 1.1 christos
1066 1.1 christos /* Decode the prefetch operation option operand for e.g.
1067 1.1 christos PRFM <prfop>, [<Xn|SP>{, #<pimm>}]. */
1068 1.1 christos
1069 1.1 christos int
1070 1.1 christos aarch64_ext_prfop (const aarch64_operand *self ATTRIBUTE_UNUSED,
1071 1.1 christos aarch64_opnd_info *info,
1072 1.1 christos aarch64_insn code, const aarch64_inst *inst ATTRIBUTE_UNUSED)
1073 1.1 christos {
1074 1.1 christos /* prfop in Rt */
1075 1.1 christos info->prfop = aarch64_prfops + extract_field (FLD_Rt, code, 0);
1076 1.1 christos return 1;
1077 1.3 christos }
1078 1.3 christos
1079 1.3 christos /* Decode the hint number for an alias taking an operand. Set info->hint_option
1080 1.3 christos to the matching name/value pair in aarch64_hint_options. */
1081 1.3 christos
1082 1.3 christos int
1083 1.3 christos aarch64_ext_hint (const aarch64_operand *self ATTRIBUTE_UNUSED,
1084 1.3 christos aarch64_opnd_info *info,
1085 1.3 christos aarch64_insn code,
1086 1.3 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
1087 1.3 christos {
1088 1.3 christos /* CRm:op2. */
1089 1.3 christos unsigned hint_number;
1090 1.3 christos int i;
1091 1.3 christos
1092 1.3 christos hint_number = extract_fields (code, 0, 2, FLD_CRm, FLD_op2);
1093 1.3 christos
1094 1.3 christos for (i = 0; aarch64_hint_options[i].name != NULL; i++)
1095 1.3 christos {
1096 1.3 christos if (hint_number == aarch64_hint_options[i].value)
1097 1.3 christos {
1098 1.3 christos info->hint_option = &(aarch64_hint_options[i]);
1099 1.3 christos return 1;
1100 1.3 christos }
1101 1.3 christos }
1102 1.3 christos
1103 1.3 christos return 0;
1104 1.1 christos }
1105 1.1 christos
1106 1.1 christos /* Decode the extended register operand for e.g.
1107 1.1 christos STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
1108 1.1 christos int
1109 1.1 christos aarch64_ext_reg_extended (const aarch64_operand *self ATTRIBUTE_UNUSED,
1110 1.1 christos aarch64_opnd_info *info,
1111 1.1 christos aarch64_insn code,
1112 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
1113 1.1 christos {
1114 1.1 christos aarch64_insn value;
1115 1.1 christos
1116 1.1 christos /* Rm */
1117 1.1 christos info->reg.regno = extract_field (FLD_Rm, code, 0);
1118 1.1 christos /* option */
1119 1.1 christos value = extract_field (FLD_option, code, 0);
1120 1.1 christos info->shifter.kind =
1121 1.1 christos aarch64_get_operand_modifier_from_value (value, TRUE /* extend_p */);
1122 1.1 christos /* imm3 */
1123 1.1 christos info->shifter.amount = extract_field (FLD_imm3, code, 0);
1124 1.1 christos
1125 1.1 christos /* This makes the constraint checking happy. */
1126 1.1 christos info->shifter.operator_present = 1;
1127 1.1 christos
1128 1.1 christos /* Assume inst->operands[0].qualifier has been resolved. */
1129 1.1 christos assert (inst->operands[0].qualifier != AARCH64_OPND_QLF_NIL);
1130 1.1 christos info->qualifier = AARCH64_OPND_QLF_W;
1131 1.1 christos if (inst->operands[0].qualifier == AARCH64_OPND_QLF_X
1132 1.1 christos && (info->shifter.kind == AARCH64_MOD_UXTX
1133 1.1 christos || info->shifter.kind == AARCH64_MOD_SXTX))
1134 1.1 christos info->qualifier = AARCH64_OPND_QLF_X;
1135 1.1 christos
1136 1.1 christos return 1;
1137 1.1 christos }
1138 1.1 christos
1139 1.1 christos /* Decode the shifted register operand for e.g.
1140 1.1 christos SUBS <Xd>, <Xn>, <Xm> {, <shift> #<amount>}. */
1141 1.1 christos int
1142 1.1 christos aarch64_ext_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED,
1143 1.1 christos aarch64_opnd_info *info,
1144 1.1 christos aarch64_insn code,
1145 1.1 christos const aarch64_inst *inst ATTRIBUTE_UNUSED)
1146 1.1 christos {
1147 1.1 christos aarch64_insn value;
1148 1.1 christos
1149 1.1 christos /* Rm */
1150 1.1 christos info->reg.regno = extract_field (FLD_Rm, code, 0);
1151 1.1 christos /* shift */
1152 1.1 christos value = extract_field (FLD_shift, code, 0);
1153 1.1 christos info->shifter.kind =
1154 1.1 christos aarch64_get_operand_modifier_from_value (value, FALSE /* extend_p */);
1155 1.1 christos if (info->shifter.kind == AARCH64_MOD_ROR
1156 1.1 christos && inst->opcode->iclass != log_shift)
1157 1.1 christos /* ROR is not available for the shifted register operand in arithmetic
1158 1.1 christos instructions. */
1159 1.1 christos return 0;
1160 1.1 christos /* imm6 */
1161 1.1 christos info->shifter.amount = extract_field (FLD_imm6, code, 0);
1162 1.1 christos
1163 1.1 christos /* This makes the constraint checking happy. */
1164 1.1 christos info->shifter.operator_present = 1;
1165 1.1 christos
1166 1.1 christos return 1;
1167 1.1 christos }
1168 1.1 christos
1169 1.1 christos /* Bitfields that are commonly used to encode certain operands' information
1171 1.1 christos may be partially used as part of the base opcode in some instructions.
1172 1.1 christos For example, the bit 1 of the field 'size' in
1173 1.1 christos FCVTXN <Vb><d>, <Va><n>
1174 1.1 christos is actually part of the base opcode, while only size<0> is available
1175 1.1 christos for encoding the register type. Another example is the AdvSIMD
1176 1.1 christos instruction ORR (register), in which the field 'size' is also used for
1177 1.1 christos the base opcode, leaving only the field 'Q' available to encode the
1178 1.1 christos vector register arrangement specifier '8B' or '16B'.
1179 1.1 christos
1180 1.1 christos This function tries to deduce the qualifier from the value of partially
1181 1.1 christos constrained field(s). Given the VALUE of such a field or fields, the
1182 1.1 christos qualifiers CANDIDATES and the MASK (indicating which bits are valid for
1183 1.1 christos operand encoding), the function returns the matching qualifier or
1184 1.1 christos AARCH64_OPND_QLF_NIL if nothing matches.
1185 1.1 christos
1186 1.1 christos N.B. CANDIDATES is a group of possible qualifiers that are valid for
1187 1.1 christos one operand; it has a maximum of AARCH64_MAX_QLF_SEQ_NUM qualifiers and
1188 1.1 christos may end with AARCH64_OPND_QLF_NIL. */
1189 1.1 christos
1190 1.1 christos static enum aarch64_opnd_qualifier
1191 1.1 christos get_qualifier_from_partial_encoding (aarch64_insn value,
1192 1.1 christos const enum aarch64_opnd_qualifier* \
1193 1.1 christos candidates,
1194 1.1 christos aarch64_insn mask)
1195 1.1 christos {
1196 1.1 christos int i;
1197 1.1 christos DEBUG_TRACE ("enter with value: %d, mask: %d", (int)value, (int)mask);
1198 1.1 christos for (i = 0; i < AARCH64_MAX_QLF_SEQ_NUM; ++i)
1199 1.1 christos {
1200 1.1 christos aarch64_insn standard_value;
1201 1.1 christos if (candidates[i] == AARCH64_OPND_QLF_NIL)
1202 1.1 christos break;
1203 1.1 christos standard_value = aarch64_get_qualifier_standard_value (candidates[i]);
1204 1.1 christos if ((standard_value & mask) == (value & mask))
1205 1.1 christos return candidates[i];
1206 1.1 christos }
1207 1.1 christos return AARCH64_OPND_QLF_NIL;
1208 1.1 christos }
1209 1.1 christos
1210 1.1 christos /* Given a list of qualifier sequences, return all possible valid qualifiers
1211 1.1 christos for operand IDX in QUALIFIERS.
1212 1.1 christos Assume QUALIFIERS is an array whose length is large enough. */
1213 1.1 christos
1214 1.1 christos static void
1215 1.1 christos get_operand_possible_qualifiers (int idx,
1216 1.1 christos const aarch64_opnd_qualifier_seq_t *list,
1217 1.1 christos enum aarch64_opnd_qualifier *qualifiers)
1218 1.1 christos {
1219 1.1 christos int i;
1220 1.1 christos for (i = 0; i < AARCH64_MAX_QLF_SEQ_NUM; ++i)
1221 1.1 christos if ((qualifiers[i] = list[i][idx]) == AARCH64_OPND_QLF_NIL)
1222 1.1 christos break;
1223 1.1 christos }
1224 1.1 christos
1225 1.1 christos /* Decode the size Q field for e.g. SHADD.
1226 1.1 christos We tag one operand with the qualifer according to the code;
1227 1.1 christos whether the qualifier is valid for this opcode or not, it is the
1228 1.1 christos duty of the semantic checking. */
1229 1.1 christos
1230 1.1 christos static int
1231 1.1 christos decode_sizeq (aarch64_inst *inst)
1232 1.1 christos {
1233 1.1 christos int idx;
1234 1.1 christos enum aarch64_opnd_qualifier qualifier;
1235 1.1 christos aarch64_insn code;
1236 1.1 christos aarch64_insn value, mask;
1237 1.1 christos enum aarch64_field_kind fld_sz;
1238 1.1 christos enum aarch64_opnd_qualifier candidates[AARCH64_MAX_QLF_SEQ_NUM];
1239 1.1 christos
1240 1.1 christos if (inst->opcode->iclass == asisdlse
1241 1.1 christos || inst->opcode->iclass == asisdlsep
1242 1.1 christos || inst->opcode->iclass == asisdlso
1243 1.1 christos || inst->opcode->iclass == asisdlsop)
1244 1.1 christos fld_sz = FLD_vldst_size;
1245 1.1 christos else
1246 1.1 christos fld_sz = FLD_size;
1247 1.1 christos
1248 1.1 christos code = inst->value;
1249 1.1 christos value = extract_fields (code, inst->opcode->mask, 2, fld_sz, FLD_Q);
1250 1.1 christos /* Obtain the info that which bits of fields Q and size are actually
1251 1.1 christos available for operand encoding. Opcodes like FMAXNM and FMLA have
1252 1.1 christos size[1] unavailable. */
1253 1.1 christos mask = extract_fields (~inst->opcode->mask, 0, 2, fld_sz, FLD_Q);
1254 1.1 christos
1255 1.1 christos /* The index of the operand we are going to tag a qualifier and the qualifer
1256 1.1 christos itself are reasoned from the value of the size and Q fields and the
1257 1.1 christos possible valid qualifier lists. */
1258 1.1 christos idx = aarch64_select_operand_for_sizeq_field_coding (inst->opcode);
1259 1.1 christos DEBUG_TRACE ("key idx: %d", idx);
1260 1.1 christos
1261 1.1 christos /* For most related instruciton, size:Q are fully available for operand
1262 1.1 christos encoding. */
1263 1.1 christos if (mask == 0x7)
1264 1.1 christos {
1265 1.1 christos inst->operands[idx].qualifier = get_vreg_qualifier_from_value (value);
1266 1.1 christos return 1;
1267 1.1 christos }
1268 1.1 christos
1269 1.1 christos get_operand_possible_qualifiers (idx, inst->opcode->qualifiers_list,
1270 1.1 christos candidates);
1271 1.1 christos #ifdef DEBUG_AARCH64
1272 1.1 christos if (debug_dump)
1273 1.1 christos {
1274 1.1 christos int i;
1275 1.1 christos for (i = 0; candidates[i] != AARCH64_OPND_QLF_NIL
1276 1.1 christos && i < AARCH64_MAX_QLF_SEQ_NUM; ++i)
1277 1.1 christos DEBUG_TRACE ("qualifier %d: %s", i,
1278 1.1 christos aarch64_get_qualifier_name(candidates[i]));
1279 1.1 christos DEBUG_TRACE ("%d, %d", (int)value, (int)mask);
1280 1.1 christos }
1281 1.1 christos #endif /* DEBUG_AARCH64 */
1282 1.1 christos
1283 1.1 christos qualifier = get_qualifier_from_partial_encoding (value, candidates, mask);
1284 1.1 christos
1285 1.1 christos if (qualifier == AARCH64_OPND_QLF_NIL)
1286 1.1 christos return 0;
1287 1.1 christos
1288 1.1 christos inst->operands[idx].qualifier = qualifier;
1289 1.1 christos return 1;
1290 1.1 christos }
1291 1.1 christos
1292 1.1 christos /* Decode size[0]:Q, i.e. bit 22 and bit 30, for
1293 1.1 christos e.g. FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
1294 1.1 christos
1295 1.1 christos static int
1296 1.1 christos decode_asimd_fcvt (aarch64_inst *inst)
1297 1.1 christos {
1298 1.1 christos aarch64_field field = {0, 0};
1299 1.1 christos aarch64_insn value;
1300 1.1 christos enum aarch64_opnd_qualifier qualifier;
1301 1.1 christos
1302 1.1 christos gen_sub_field (FLD_size, 0, 1, &field);
1303 1.1 christos value = extract_field_2 (&field, inst->value, 0);
1304 1.1 christos qualifier = value == 0 ? AARCH64_OPND_QLF_V_4S
1305 1.1 christos : AARCH64_OPND_QLF_V_2D;
1306 1.1 christos switch (inst->opcode->op)
1307 1.1 christos {
1308 1.1 christos case OP_FCVTN:
1309 1.1 christos case OP_FCVTN2:
1310 1.1 christos /* FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
1311 1.1 christos inst->operands[1].qualifier = qualifier;
1312 1.1 christos break;
1313 1.1 christos case OP_FCVTL:
1314 1.1 christos case OP_FCVTL2:
1315 1.1 christos /* FCVTL<Q> <Vd>.<Ta>, <Vn>.<Tb>. */
1316 1.1 christos inst->operands[0].qualifier = qualifier;
1317 1.1 christos break;
1318 1.1 christos default:
1319 1.1 christos assert (0);
1320 1.1 christos return 0;
1321 1.1 christos }
1322 1.1 christos
1323 1.1 christos return 1;
1324 1.1 christos }
1325 1.1 christos
1326 1.1 christos /* Decode size[0], i.e. bit 22, for
1327 1.1 christos e.g. FCVTXN <Vb><d>, <Va><n>. */
1328 1.1 christos
1329 1.1 christos static int
1330 1.1 christos decode_asisd_fcvtxn (aarch64_inst *inst)
1331 1.1 christos {
1332 1.1 christos aarch64_field field = {0, 0};
1333 1.1 christos gen_sub_field (FLD_size, 0, 1, &field);
1334 1.1 christos if (!extract_field_2 (&field, inst->value, 0))
1335 1.1 christos return 0;
1336 1.1 christos inst->operands[0].qualifier = AARCH64_OPND_QLF_S_S;
1337 1.1 christos return 1;
1338 1.1 christos }
1339 1.1 christos
1340 1.1 christos /* Decode the 'opc' field for e.g. FCVT <Dd>, <Sn>. */
1341 1.1 christos static int
1342 1.1 christos decode_fcvt (aarch64_inst *inst)
1343 1.1 christos {
1344 1.1 christos enum aarch64_opnd_qualifier qualifier;
1345 1.1 christos aarch64_insn value;
1346 1.1 christos const aarch64_field field = {15, 2};
1347 1.1 christos
1348 1.1 christos /* opc dstsize */
1349 1.1 christos value = extract_field_2 (&field, inst->value, 0);
1350 1.1 christos switch (value)
1351 1.1 christos {
1352 1.1 christos case 0: qualifier = AARCH64_OPND_QLF_S_S; break;
1353 1.1 christos case 1: qualifier = AARCH64_OPND_QLF_S_D; break;
1354 1.1 christos case 3: qualifier = AARCH64_OPND_QLF_S_H; break;
1355 1.1 christos default: return 0;
1356 1.1 christos }
1357 1.1 christos inst->operands[0].qualifier = qualifier;
1358 1.1 christos
1359 1.1 christos return 1;
1360 1.1 christos }
1361 1.1 christos
1362 1.1 christos /* Do miscellaneous decodings that are not common enough to be driven by
1363 1.1 christos flags. */
1364 1.1 christos
1365 1.1 christos static int
1366 1.1 christos do_misc_decoding (aarch64_inst *inst)
1367 1.1 christos {
1368 1.1 christos switch (inst->opcode->op)
1369 1.1 christos {
1370 1.1 christos case OP_FCVT:
1371 1.1 christos return decode_fcvt (inst);
1372 1.1 christos case OP_FCVTN:
1373 1.1 christos case OP_FCVTN2:
1374 1.1 christos case OP_FCVTL:
1375 1.1 christos case OP_FCVTL2:
1376 1.1 christos return decode_asimd_fcvt (inst);
1377 1.1 christos case OP_FCVTXN_S:
1378 1.1 christos return decode_asisd_fcvtxn (inst);
1379 1.1 christos default:
1380 1.1 christos return 0;
1381 1.1 christos }
1382 1.1 christos }
1383 1.1 christos
1384 1.1 christos /* Opcodes that have fields shared by multiple operands are usually flagged
1385 1.1 christos with flags. In this function, we detect such flags, decode the related
1386 1.1 christos field(s) and store the information in one of the related operands. The
1387 1.1 christos 'one' operand is not any operand but one of the operands that can
1388 1.1 christos accommadate all the information that has been decoded. */
1389 1.1 christos
1390 1.1 christos static int
1391 1.1 christos do_special_decoding (aarch64_inst *inst)
1392 1.1 christos {
1393 1.1 christos int idx;
1394 1.1 christos aarch64_insn value;
1395 1.1 christos /* Condition for truly conditional executed instructions, e.g. b.cond. */
1396 1.1 christos if (inst->opcode->flags & F_COND)
1397 1.1 christos {
1398 1.1 christos value = extract_field (FLD_cond2, inst->value, 0);
1399 1.1 christos inst->cond = get_cond_from_value (value);
1400 1.1 christos }
1401 1.1 christos /* 'sf' field. */
1402 1.1 christos if (inst->opcode->flags & F_SF)
1403 1.1 christos {
1404 1.1 christos idx = select_operand_for_sf_field_coding (inst->opcode);
1405 1.1 christos value = extract_field (FLD_sf, inst->value, 0);
1406 1.1 christos inst->operands[idx].qualifier = get_greg_qualifier_from_value (value);
1407 1.1 christos if ((inst->opcode->flags & F_N)
1408 1.3 christos && extract_field (FLD_N, inst->value, 0) != value)
1409 1.3 christos return 0;
1410 1.3 christos }
1411 1.3 christos /* 'sf' field. */
1412 1.3 christos if (inst->opcode->flags & F_LSE_SZ)
1413 1.3 christos {
1414 1.3 christos idx = select_operand_for_sf_field_coding (inst->opcode);
1415 1.1 christos value = extract_field (FLD_lse_sz, inst->value, 0);
1416 1.1 christos inst->operands[idx].qualifier = get_greg_qualifier_from_value (value);
1417 1.1 christos }
1418 1.1 christos /* size:Q fields. */
1419 1.1 christos if (inst->opcode->flags & F_SIZEQ)
1420 1.1 christos return decode_sizeq (inst);
1421 1.1 christos
1422 1.1 christos if (inst->opcode->flags & F_FPTYPE)
1423 1.1 christos {
1424 1.1 christos idx = select_operand_for_fptype_field_coding (inst->opcode);
1425 1.1 christos value = extract_field (FLD_type, inst->value, 0);
1426 1.1 christos switch (value)
1427 1.1 christos {
1428 1.1 christos case 0: inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_S; break;
1429 1.1 christos case 1: inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_D; break;
1430 1.1 christos case 3: inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_H; break;
1431 1.1 christos default: return 0;
1432 1.1 christos }
1433 1.1 christos }
1434 1.1 christos
1435 1.1 christos if (inst->opcode->flags & F_SSIZE)
1436 1.1 christos {
1437 1.1 christos /* N.B. some opcodes like FCMGT <V><d>, <V><n>, #0 have the size[1] as part
1438 1.1 christos of the base opcode. */
1439 1.1 christos aarch64_insn mask;
1440 1.1 christos enum aarch64_opnd_qualifier candidates[AARCH64_MAX_QLF_SEQ_NUM];
1441 1.1 christos idx = select_operand_for_scalar_size_field_coding (inst->opcode);
1442 1.1 christos value = extract_field (FLD_size, inst->value, inst->opcode->mask);
1443 1.1 christos mask = extract_field (FLD_size, ~inst->opcode->mask, 0);
1444 1.1 christos /* For most related instruciton, the 'size' field is fully available for
1445 1.1 christos operand encoding. */
1446 1.1 christos if (mask == 0x3)
1447 1.1 christos inst->operands[idx].qualifier = get_sreg_qualifier_from_value (value);
1448 1.1 christos else
1449 1.1 christos {
1450 1.1 christos get_operand_possible_qualifiers (idx, inst->opcode->qualifiers_list,
1451 1.1 christos candidates);
1452 1.1 christos inst->operands[idx].qualifier
1453 1.1 christos = get_qualifier_from_partial_encoding (value, candidates, mask);
1454 1.1 christos }
1455 1.1 christos }
1456 1.1 christos
1457 1.1 christos if (inst->opcode->flags & F_T)
1458 1.1 christos {
1459 1.1 christos /* Num of consecutive '0's on the right side of imm5<3:0>. */
1460 1.1 christos int num = 0;
1461 1.1 christos unsigned val, Q;
1462 1.1 christos assert (aarch64_get_operand_class (inst->opcode->operands[0])
1463 1.1 christos == AARCH64_OPND_CLASS_SIMD_REG);
1464 1.1 christos /* imm5<3:0> q <t>
1465 1.1 christos 0000 x reserved
1466 1.1 christos xxx1 0 8b
1467 1.1 christos xxx1 1 16b
1468 1.1 christos xx10 0 4h
1469 1.1 christos xx10 1 8h
1470 1.1 christos x100 0 2s
1471 1.1 christos x100 1 4s
1472 1.1 christos 1000 0 reserved
1473 1.1 christos 1000 1 2d */
1474 1.1 christos val = extract_field (FLD_imm5, inst->value, 0);
1475 1.1 christos while ((val & 0x1) == 0 && ++num <= 3)
1476 1.1 christos val >>= 1;
1477 1.1 christos if (num > 3)
1478 1.1 christos return 0;
1479 1.1 christos Q = (unsigned) extract_field (FLD_Q, inst->value, inst->opcode->mask);
1480 1.1 christos inst->operands[0].qualifier =
1481 1.1 christos get_vreg_qualifier_from_value ((num << 1) | Q);
1482 1.1 christos }
1483 1.1 christos
1484 1.1 christos if (inst->opcode->flags & F_GPRSIZE_IN_Q)
1485 1.1 christos {
1486 1.1 christos /* Use Rt to encode in the case of e.g.
1487 1.1 christos STXP <Ws>, <Xt1>, <Xt2>, [<Xn|SP>{,#0}]. */
1488 1.1 christos idx = aarch64_operand_index (inst->opcode->operands, AARCH64_OPND_Rt);
1489 1.1 christos if (idx == -1)
1490 1.1 christos {
1491 1.1 christos /* Otherwise use the result operand, which has to be a integer
1492 1.1 christos register. */
1493 1.1 christos assert (aarch64_get_operand_class (inst->opcode->operands[0])
1494 1.1 christos == AARCH64_OPND_CLASS_INT_REG);
1495 1.1 christos idx = 0;
1496 1.1 christos }
1497 1.1 christos assert (idx == 0 || idx == 1);
1498 1.1 christos value = extract_field (FLD_Q, inst->value, 0);
1499 1.1 christos inst->operands[idx].qualifier = get_greg_qualifier_from_value (value);
1500 1.1 christos }
1501 1.1 christos
1502 1.1 christos if (inst->opcode->flags & F_LDS_SIZE)
1503 1.1 christos {
1504 1.1 christos aarch64_field field = {0, 0};
1505 1.1 christos assert (aarch64_get_operand_class (inst->opcode->operands[0])
1506 1.1 christos == AARCH64_OPND_CLASS_INT_REG);
1507 1.1 christos gen_sub_field (FLD_opc, 0, 1, &field);
1508 1.1 christos value = extract_field_2 (&field, inst->value, 0);
1509 1.1 christos inst->operands[0].qualifier
1510 1.1 christos = value ? AARCH64_OPND_QLF_W : AARCH64_OPND_QLF_X;
1511 1.1 christos }
1512 1.1 christos
1513 1.1 christos /* Miscellaneous decoding; done as the last step. */
1514 1.1 christos if (inst->opcode->flags & F_MISC)
1515 1.1 christos return do_misc_decoding (inst);
1516 1.1 christos
1517 1.1 christos return 1;
1518 1.1 christos }
1519 1.1 christos
1520 1.1 christos /* Converters converting a real opcode instruction to its alias form. */
1521 1.1 christos
1522 1.1 christos /* ROR <Wd>, <Ws>, #<shift>
1523 1.1 christos is equivalent to:
1524 1.1 christos EXTR <Wd>, <Ws>, <Ws>, #<shift>. */
1525 1.1 christos static int
1526 1.1 christos convert_extr_to_ror (aarch64_inst *inst)
1527 1.1 christos {
1528 1.1 christos if (inst->operands[1].reg.regno == inst->operands[2].reg.regno)
1529 1.1 christos {
1530 1.1 christos copy_operand_info (inst, 2, 3);
1531 1.1 christos inst->operands[3].type = AARCH64_OPND_NIL;
1532 1.1 christos return 1;
1533 1.1 christos }
1534 1.1 christos return 0;
1535 1.1 christos }
1536 1.1 christos
1537 1.1 christos /* UXTL<Q> <Vd>.<Ta>, <Vn>.<Tb>
1538 1.1 christos is equivalent to:
1539 1.1 christos USHLL<Q> <Vd>.<Ta>, <Vn>.<Tb>, #0. */
1540 1.1 christos static int
1541 1.1 christos convert_shll_to_xtl (aarch64_inst *inst)
1542 1.1 christos {
1543 1.1 christos if (inst->operands[2].imm.value == 0)
1544 1.1 christos {
1545 1.1 christos inst->operands[2].type = AARCH64_OPND_NIL;
1546 1.1 christos return 1;
1547 1.1 christos }
1548 1.1 christos return 0;
1549 1.1 christos }
1550 1.1 christos
1551 1.1 christos /* Convert
1552 1.1 christos UBFM <Xd>, <Xn>, #<shift>, #63.
1553 1.1 christos to
1554 1.1 christos LSR <Xd>, <Xn>, #<shift>. */
1555 1.1 christos static int
1556 1.1 christos convert_bfm_to_sr (aarch64_inst *inst)
1557 1.1 christos {
1558 1.1 christos int64_t imms, val;
1559 1.1 christos
1560 1.1 christos imms = inst->operands[3].imm.value;
1561 1.1 christos val = inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 31 : 63;
1562 1.1 christos if (imms == val)
1563 1.1 christos {
1564 1.1 christos inst->operands[3].type = AARCH64_OPND_NIL;
1565 1.1 christos return 1;
1566 1.1 christos }
1567 1.1 christos
1568 1.1 christos return 0;
1569 1.1 christos }
1570 1.1 christos
1571 1.1 christos /* Convert MOV to ORR. */
1572 1.1 christos static int
1573 1.1 christos convert_orr_to_mov (aarch64_inst *inst)
1574 1.1 christos {
1575 1.1 christos /* MOV <Vd>.<T>, <Vn>.<T>
1576 1.1 christos is equivalent to:
1577 1.1 christos ORR <Vd>.<T>, <Vn>.<T>, <Vn>.<T>. */
1578 1.1 christos if (inst->operands[1].reg.regno == inst->operands[2].reg.regno)
1579 1.1 christos {
1580 1.1 christos inst->operands[2].type = AARCH64_OPND_NIL;
1581 1.1 christos return 1;
1582 1.1 christos }
1583 1.1 christos return 0;
1584 1.1 christos }
1585 1.1 christos
1586 1.1 christos /* When <imms> >= <immr>, the instruction written:
1587 1.1 christos SBFX <Xd>, <Xn>, #<lsb>, #<width>
1588 1.1 christos is equivalent to:
1589 1.1 christos SBFM <Xd>, <Xn>, #<lsb>, #(<lsb>+<width>-1). */
1590 1.1 christos
1591 1.1 christos static int
1592 1.1 christos convert_bfm_to_bfx (aarch64_inst *inst)
1593 1.1 christos {
1594 1.1 christos int64_t immr, imms;
1595 1.1 christos
1596 1.1 christos immr = inst->operands[2].imm.value;
1597 1.1 christos imms = inst->operands[3].imm.value;
1598 1.1 christos if (imms >= immr)
1599 1.1 christos {
1600 1.1 christos int64_t lsb = immr;
1601 1.1 christos inst->operands[2].imm.value = lsb;
1602 1.1 christos inst->operands[3].imm.value = imms + 1 - lsb;
1603 1.1 christos /* The two opcodes have different qualifiers for
1604 1.1 christos the immediate operands; reset to help the checking. */
1605 1.1 christos reset_operand_qualifier (inst, 2);
1606 1.1 christos reset_operand_qualifier (inst, 3);
1607 1.1 christos return 1;
1608 1.1 christos }
1609 1.1 christos
1610 1.1 christos return 0;
1611 1.1 christos }
1612 1.1 christos
1613 1.1 christos /* When <imms> < <immr>, the instruction written:
1614 1.1 christos SBFIZ <Xd>, <Xn>, #<lsb>, #<width>
1615 1.1 christos is equivalent to:
1616 1.1 christos SBFM <Xd>, <Xn>, #((64-<lsb>)&0x3f), #(<width>-1). */
1617 1.1 christos
1618 1.1 christos static int
1619 1.1 christos convert_bfm_to_bfi (aarch64_inst *inst)
1620 1.1 christos {
1621 1.1 christos int64_t immr, imms, val;
1622 1.1 christos
1623 1.1 christos immr = inst->operands[2].imm.value;
1624 1.1 christos imms = inst->operands[3].imm.value;
1625 1.1 christos val = inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 32 : 64;
1626 1.1 christos if (imms < immr)
1627 1.1 christos {
1628 1.1 christos inst->operands[2].imm.value = (val - immr) & (val - 1);
1629 1.1 christos inst->operands[3].imm.value = imms + 1;
1630 1.1 christos /* The two opcodes have different qualifiers for
1631 1.1 christos the immediate operands; reset to help the checking. */
1632 1.1 christos reset_operand_qualifier (inst, 2);
1633 1.1 christos reset_operand_qualifier (inst, 3);
1634 1.1 christos return 1;
1635 1.1 christos }
1636 1.1 christos
1637 1.1 christos return 0;
1638 1.3 christos }
1639 1.3 christos
1640 1.3 christos /* The instruction written:
1641 1.3 christos BFC <Xd>, #<lsb>, #<width>
1642 1.3 christos is equivalent to:
1643 1.3 christos BFM <Xd>, XZR, #((64-<lsb>)&0x3f), #(<width>-1). */
1644 1.3 christos
1645 1.3 christos static int
1646 1.3 christos convert_bfm_to_bfc (aarch64_inst *inst)
1647 1.3 christos {
1648 1.3 christos int64_t immr, imms, val;
1649 1.3 christos
1650 1.3 christos /* Should have been assured by the base opcode value. */
1651 1.3 christos assert (inst->operands[1].reg.regno == 0x1f);
1652 1.3 christos
1653 1.3 christos immr = inst->operands[2].imm.value;
1654 1.3 christos imms = inst->operands[3].imm.value;
1655 1.3 christos val = inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 32 : 64;
1656 1.3 christos if (imms < immr)
1657 1.3 christos {
1658 1.3 christos /* Drop XZR from the second operand. */
1659 1.3 christos copy_operand_info (inst, 1, 2);
1660 1.3 christos copy_operand_info (inst, 2, 3);
1661 1.3 christos inst->operands[3].type = AARCH64_OPND_NIL;
1662 1.3 christos
1663 1.3 christos /* Recalculate the immediates. */
1664 1.3 christos inst->operands[1].imm.value = (val - immr) & (val - 1);
1665 1.3 christos inst->operands[2].imm.value = imms + 1;
1666 1.3 christos
1667 1.3 christos /* The two opcodes have different qualifiers for the operands; reset to
1668 1.3 christos help the checking. */
1669 1.3 christos reset_operand_qualifier (inst, 1);
1670 1.3 christos reset_operand_qualifier (inst, 2);
1671 1.3 christos reset_operand_qualifier (inst, 3);
1672 1.3 christos
1673 1.3 christos return 1;
1674 1.3 christos }
1675 1.3 christos
1676 1.3 christos return 0;
1677 1.1 christos }
1678 1.1 christos
1679 1.1 christos /* The instruction written:
1680 1.1 christos LSL <Xd>, <Xn>, #<shift>
1681 1.1 christos is equivalent to:
1682 1.1 christos UBFM <Xd>, <Xn>, #((64-<shift>)&0x3f), #(63-<shift>). */
1683 1.1 christos
1684 1.1 christos static int
1685 1.1 christos convert_ubfm_to_lsl (aarch64_inst *inst)
1686 1.1 christos {
1687 1.1 christos int64_t immr = inst->operands[2].imm.value;
1688 1.1 christos int64_t imms = inst->operands[3].imm.value;
1689 1.1 christos int64_t val
1690 1.1 christos = inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 31 : 63;
1691 1.1 christos
1692 1.1 christos if ((immr == 0 && imms == val) || immr == imms + 1)
1693 1.1 christos {
1694 1.1 christos inst->operands[3].type = AARCH64_OPND_NIL;
1695 1.1 christos inst->operands[2].imm.value = val - imms;
1696 1.1 christos return 1;
1697 1.1 christos }
1698 1.1 christos
1699 1.1 christos return 0;
1700 1.1 christos }
1701 1.3 christos
1702 1.3 christos /* CINC <Wd>, <Wn>, <cond>
1703 1.1 christos is equivalent to:
1704 1.1 christos CSINC <Wd>, <Wn>, <Wn>, invert(<cond>)
1705 1.1 christos where <cond> is not AL or NV. */
1706 1.1 christos
1707 1.3 christos static int
1708 1.3 christos convert_from_csel (aarch64_inst *inst)
1709 1.1 christos {
1710 1.1 christos if (inst->operands[1].reg.regno == inst->operands[2].reg.regno
1711 1.1 christos && (inst->operands[3].cond->value & 0xe) != 0xe)
1712 1.1 christos {
1713 1.1 christos copy_operand_info (inst, 2, 3);
1714 1.1 christos inst->operands[2].cond = get_inverted_cond (inst->operands[3].cond);
1715 1.1 christos inst->operands[3].type = AARCH64_OPND_NIL;
1716 1.1 christos return 1;
1717 1.1 christos }
1718 1.1 christos return 0;
1719 1.1 christos }
1720 1.3 christos
1721 1.3 christos /* CSET <Wd>, <cond>
1722 1.1 christos is equivalent to:
1723 1.1 christos CSINC <Wd>, WZR, WZR, invert(<cond>)
1724 1.1 christos where <cond> is not AL or NV. */
1725 1.1 christos
1726 1.1 christos static int
1727 1.3 christos convert_csinc_to_cset (aarch64_inst *inst)
1728 1.3 christos {
1729 1.1 christos if (inst->operands[1].reg.regno == 0x1f
1730 1.1 christos && inst->operands[2].reg.regno == 0x1f
1731 1.1 christos && (inst->operands[3].cond->value & 0xe) != 0xe)
1732 1.1 christos {
1733 1.1 christos copy_operand_info (inst, 1, 3);
1734 1.1 christos inst->operands[1].cond = get_inverted_cond (inst->operands[3].cond);
1735 1.1 christos inst->operands[3].type = AARCH64_OPND_NIL;
1736 1.1 christos inst->operands[2].type = AARCH64_OPND_NIL;
1737 1.1 christos return 1;
1738 1.1 christos }
1739 1.1 christos return 0;
1740 1.1 christos }
1741 1.1 christos
1742 1.1 christos /* MOV <Wd>, #<imm>
1743 1.1 christos is equivalent to:
1744 1.1 christos MOVZ <Wd>, #<imm16>, LSL #<shift>.
1745 1.1 christos
1746 1.1 christos A disassembler may output ORR, MOVZ and MOVN as a MOV mnemonic, except when
1747 1.1 christos ORR has an immediate that could be generated by a MOVZ or MOVN instruction,
1748 1.1 christos or where a MOVN has an immediate that could be encoded by MOVZ, or where
1749 1.1 christos MOVZ/MOVN #0 have a shift amount other than LSL #0, in which case the
1750 1.1 christos machine-instruction mnemonic must be used. */
1751 1.1 christos
1752 1.1 christos static int
1753 1.1 christos convert_movewide_to_mov (aarch64_inst *inst)
1754 1.1 christos {
1755 1.1 christos uint64_t value = inst->operands[1].imm.value;
1756 1.1 christos /* MOVZ/MOVN #0 have a shift amount other than LSL #0. */
1757 1.1 christos if (value == 0 && inst->operands[1].shifter.amount != 0)
1758 1.1 christos return 0;
1759 1.1 christos inst->operands[1].type = AARCH64_OPND_IMM_MOV;
1760 1.1 christos inst->operands[1].shifter.kind = AARCH64_MOD_NONE;
1761 1.1 christos value <<= inst->operands[1].shifter.amount;
1762 1.1 christos /* As an alias convertor, it has to be clear that the INST->OPCODE
1763 1.1 christos is the opcode of the real instruction. */
1764 1.1 christos if (inst->opcode->op == OP_MOVN)
1765 1.1 christos {
1766 1.1 christos int is32 = inst->operands[0].qualifier == AARCH64_OPND_QLF_W;
1767 1.1 christos value = ~value;
1768 1.1 christos /* A MOVN has an immediate that could be encoded by MOVZ. */
1769 1.1 christos if (aarch64_wide_constant_p (value, is32, NULL) == TRUE)
1770 1.1 christos return 0;
1771 1.1 christos }
1772 1.1 christos inst->operands[1].imm.value = value;
1773 1.1 christos inst->operands[1].shifter.amount = 0;
1774 1.1 christos return 1;
1775 1.1 christos }
1776 1.1 christos
1777 1.1 christos /* MOV <Wd>, #<imm>
1778 1.1 christos is equivalent to:
1779 1.1 christos ORR <Wd>, WZR, #<imm>.
1780 1.1 christos
1781 1.1 christos A disassembler may output ORR, MOVZ and MOVN as a MOV mnemonic, except when
1782 1.1 christos ORR has an immediate that could be generated by a MOVZ or MOVN instruction,
1783 1.1 christos or where a MOVN has an immediate that could be encoded by MOVZ, or where
1784 1.1 christos MOVZ/MOVN #0 have a shift amount other than LSL #0, in which case the
1785 1.1 christos machine-instruction mnemonic must be used. */
1786 1.1 christos
1787 1.1 christos static int
1788 1.1 christos convert_movebitmask_to_mov (aarch64_inst *inst)
1789 1.1 christos {
1790 1.1 christos int is32;
1791 1.1 christos uint64_t value;
1792 1.1 christos
1793 1.1 christos /* Should have been assured by the base opcode value. */
1794 1.1 christos assert (inst->operands[1].reg.regno == 0x1f);
1795 1.1 christos copy_operand_info (inst, 1, 2);
1796 1.1 christos is32 = inst->operands[0].qualifier == AARCH64_OPND_QLF_W;
1797 1.1 christos inst->operands[1].type = AARCH64_OPND_IMM_MOV;
1798 1.1 christos value = inst->operands[1].imm.value;
1799 1.1 christos /* ORR has an immediate that could be generated by a MOVZ or MOVN
1800 1.1 christos instruction. */
1801 1.1 christos if (inst->operands[0].reg.regno != 0x1f
1802 1.1 christos && (aarch64_wide_constant_p (value, is32, NULL) == TRUE
1803 1.1 christos || aarch64_wide_constant_p (~value, is32, NULL) == TRUE))
1804 1.1 christos return 0;
1805 1.1 christos
1806 1.1 christos inst->operands[2].type = AARCH64_OPND_NIL;
1807 1.1 christos return 1;
1808 1.1 christos }
1809 1.1 christos
1810 1.1 christos /* Some alias opcodes are disassembled by being converted from their real-form.
1811 1.1 christos N.B. INST->OPCODE is the real opcode rather than the alias. */
1812 1.1 christos
1813 1.1 christos static int
1814 1.1 christos convert_to_alias (aarch64_inst *inst, const aarch64_opcode *alias)
1815 1.1 christos {
1816 1.1 christos switch (alias->op)
1817 1.1 christos {
1818 1.1 christos case OP_ASR_IMM:
1819 1.1 christos case OP_LSR_IMM:
1820 1.1 christos return convert_bfm_to_sr (inst);
1821 1.1 christos case OP_LSL_IMM:
1822 1.1 christos return convert_ubfm_to_lsl (inst);
1823 1.1 christos case OP_CINC:
1824 1.1 christos case OP_CINV:
1825 1.1 christos case OP_CNEG:
1826 1.1 christos return convert_from_csel (inst);
1827 1.1 christos case OP_CSET:
1828 1.1 christos case OP_CSETM:
1829 1.1 christos return convert_csinc_to_cset (inst);
1830 1.1 christos case OP_UBFX:
1831 1.1 christos case OP_BFXIL:
1832 1.1 christos case OP_SBFX:
1833 1.1 christos return convert_bfm_to_bfx (inst);
1834 1.1 christos case OP_SBFIZ:
1835 1.3 christos case OP_BFI:
1836 1.3 christos case OP_UBFIZ:
1837 1.1 christos return convert_bfm_to_bfi (inst);
1838 1.1 christos case OP_BFC:
1839 1.1 christos return convert_bfm_to_bfc (inst);
1840 1.1 christos case OP_MOV_V:
1841 1.1 christos return convert_orr_to_mov (inst);
1842 1.1 christos case OP_MOV_IMM_WIDE:
1843 1.1 christos case OP_MOV_IMM_WIDEN:
1844 1.1 christos return convert_movewide_to_mov (inst);
1845 1.1 christos case OP_MOV_IMM_LOG:
1846 1.1 christos return convert_movebitmask_to_mov (inst);
1847 1.1 christos case OP_ROR_IMM:
1848 1.1 christos return convert_extr_to_ror (inst);
1849 1.1 christos case OP_SXTL:
1850 1.1 christos case OP_SXTL2:
1851 1.1 christos case OP_UXTL:
1852 1.1 christos case OP_UXTL2:
1853 1.1 christos return convert_shll_to_xtl (inst);
1854 1.1 christos default:
1855 1.1 christos return 0;
1856 1.1 christos }
1857 1.1 christos }
1858 1.1 christos
1859 1.1 christos static int aarch64_opcode_decode (const aarch64_opcode *, const aarch64_insn,
1860 1.1 christos aarch64_inst *, int);
1861 1.1 christos
1862 1.1 christos /* Given the instruction information in *INST, check if the instruction has
1863 1.1 christos any alias form that can be used to represent *INST. If the answer is yes,
1864 1.1 christos update *INST to be in the form of the determined alias. */
1865 1.1 christos
1866 1.1 christos /* In the opcode description table, the following flags are used in opcode
1867 1.1 christos entries to help establish the relations between the real and alias opcodes:
1868 1.1 christos
1869 1.1 christos F_ALIAS: opcode is an alias
1870 1.1 christos F_HAS_ALIAS: opcode has alias(es)
1871 1.1 christos F_P1
1872 1.1 christos F_P2
1873 1.1 christos F_P3: Disassembly preference priority 1-3 (the larger the
1874 1.1 christos higher). If nothing is specified, it is the priority
1875 1.1 christos 0 by default, i.e. the lowest priority.
1876 1.1 christos
1877 1.1 christos Although the relation between the machine and the alias instructions are not
1878 1.1 christos explicitly described, it can be easily determined from the base opcode
1879 1.1 christos values, masks and the flags F_ALIAS and F_HAS_ALIAS in their opcode
1880 1.1 christos description entries:
1881 1.1 christos
1882 1.1 christos The mask of an alias opcode must be equal to or a super-set (i.e. more
1883 1.1 christos constrained) of that of the aliased opcode; so is the base opcode value.
1884 1.1 christos
1885 1.1 christos if (opcode_has_alias (real) && alias_opcode_p (opcode)
1886 1.1 christos && (opcode->mask & real->mask) == real->mask
1887 1.1 christos && (real->mask & opcode->opcode) == (real->mask & real->opcode))
1888 1.1 christos then OPCODE is an alias of, and only of, the REAL instruction
1889 1.1 christos
1890 1.1 christos The alias relationship is forced flat-structured to keep related algorithm
1891 1.1 christos simple; an opcode entry cannot be flagged with both F_ALIAS and F_HAS_ALIAS.
1892 1.1 christos
1893 1.1 christos During the disassembling, the decoding decision tree (in
1894 1.1 christos opcodes/aarch64-dis-2.c) always returns an machine instruction opcode entry;
1895 1.1 christos if the decoding of such a machine instruction succeeds (and -Mno-aliases is
1896 1.1 christos not specified), the disassembler will check whether there is any alias
1897 1.1 christos instruction exists for this real instruction. If there is, the disassembler
1898 1.1 christos will try to disassemble the 32-bit binary again using the alias's rule, or
1899 1.1 christos try to convert the IR to the form of the alias. In the case of the multiple
1900 1.1 christos aliases, the aliases are tried one by one from the highest priority
1901 1.1 christos (currently the flag F_P3) to the lowest priority (no priority flag), and the
1902 1.1 christos first succeeds first adopted.
1903 1.1 christos
1904 1.1 christos You may ask why there is a need for the conversion of IR from one form to
1905 1.1 christos another in handling certain aliases. This is because on one hand it avoids
1906 1.1 christos adding more operand code to handle unusual encoding/decoding; on other
1907 1.1 christos hand, during the disassembling, the conversion is an effective approach to
1908 1.1 christos check the condition of an alias (as an alias may be adopted only if certain
1909 1.1 christos conditions are met).
1910 1.1 christos
1911 1.1 christos In order to speed up the alias opcode lookup, aarch64-gen has preprocessed
1912 1.1 christos aarch64_opcode_table and generated aarch64_find_alias_opcode and
1913 1.1 christos aarch64_find_next_alias_opcode (in opcodes/aarch64-dis-2.c) to help. */
1914 1.1 christos
1915 1.1 christos static void
1916 1.1 christos determine_disassembling_preference (struct aarch64_inst *inst)
1917 1.1 christos {
1918 1.1 christos const aarch64_opcode *opcode;
1919 1.1 christos const aarch64_opcode *alias;
1920 1.1 christos
1921 1.1 christos opcode = inst->opcode;
1922 1.1 christos
1923 1.1 christos /* This opcode does not have an alias, so use itself. */
1924 1.1 christos if (opcode_has_alias (opcode) == FALSE)
1925 1.1 christos return;
1926 1.1 christos
1927 1.1 christos alias = aarch64_find_alias_opcode (opcode);
1928 1.1 christos assert (alias);
1929 1.1 christos
1930 1.1 christos #ifdef DEBUG_AARCH64
1931 1.1 christos if (debug_dump)
1932 1.1 christos {
1933 1.1 christos const aarch64_opcode *tmp = alias;
1934 1.1 christos printf ("#### LIST orderd: ");
1935 1.1 christos while (tmp)
1936 1.1 christos {
1937 1.1 christos printf ("%s, ", tmp->name);
1938 1.1 christos tmp = aarch64_find_next_alias_opcode (tmp);
1939 1.1 christos }
1940 1.1 christos printf ("\n");
1941 1.1 christos }
1942 1.1 christos #endif /* DEBUG_AARCH64 */
1943 1.1 christos
1944 1.3 christos for (; alias; alias = aarch64_find_next_alias_opcode (alias))
1945 1.1 christos {
1946 1.1 christos DEBUG_TRACE ("try %s", alias->name);
1947 1.1 christos assert (alias_opcode_p (alias) || opcode_has_alias (opcode));
1948 1.1 christos
1949 1.1 christos /* An alias can be a pseudo opcode which will never be used in the
1950 1.1 christos disassembly, e.g. BIC logical immediate is such a pseudo opcode
1951 1.1 christos aliasing AND. */
1952 1.1 christos if (pseudo_opcode_p (alias))
1953 1.1 christos {
1954 1.1 christos DEBUG_TRACE ("skip pseudo %s", alias->name);
1955 1.1 christos continue;
1956 1.1 christos }
1957 1.1 christos
1958 1.1 christos if ((inst->value & alias->mask) != alias->opcode)
1959 1.1 christos {
1960 1.1 christos DEBUG_TRACE ("skip %s as base opcode not match", alias->name);
1961 1.1 christos continue;
1962 1.1 christos }
1963 1.1 christos /* No need to do any complicated transformation on operands, if the alias
1964 1.1 christos opcode does not have any operand. */
1965 1.1 christos if (aarch64_num_of_operands (alias) == 0 && alias->opcode == inst->value)
1966 1.1 christos {
1967 1.1 christos DEBUG_TRACE ("succeed with 0-operand opcode %s", alias->name);
1968 1.1 christos aarch64_replace_opcode (inst, alias);
1969 1.1 christos return;
1970 1.1 christos }
1971 1.1 christos if (alias->flags & F_CONV)
1972 1.1 christos {
1973 1.1 christos aarch64_inst copy;
1974 1.1 christos memcpy (©, inst, sizeof (aarch64_inst));
1975 1.1 christos /* ALIAS is the preference as long as the instruction can be
1976 1.1 christos successfully converted to the form of ALIAS. */
1977 1.1 christos if (convert_to_alias (©, alias) == 1)
1978 1.1 christos {
1979 1.1 christos aarch64_replace_opcode (©, alias);
1980 1.1 christos assert (aarch64_match_operands_constraint (©, NULL));
1981 1.1 christos DEBUG_TRACE ("succeed with %s via conversion", alias->name);
1982 1.1 christos memcpy (inst, ©, sizeof (aarch64_inst));
1983 1.1 christos return;
1984 1.1 christos }
1985 1.1 christos }
1986 1.1 christos else
1987 1.1 christos {
1988 1.1 christos /* Directly decode the alias opcode. */
1989 1.1 christos aarch64_inst temp;
1990 1.1 christos memset (&temp, '\0', sizeof (aarch64_inst));
1991 1.1 christos if (aarch64_opcode_decode (alias, inst->value, &temp, 1) == 1)
1992 1.1 christos {
1993 1.1 christos DEBUG_TRACE ("succeed with %s via direct decoding", alias->name);
1994 1.1 christos memcpy (inst, &temp, sizeof (aarch64_inst));
1995 1.1 christos return;
1996 1.1 christos }
1997 1.1 christos }
1998 1.1 christos }
1999 1.1 christos }
2000 1.1 christos
2001 1.1 christos /* Decode the CODE according to OPCODE; fill INST. Return 0 if the decoding
2002 1.1 christos fails, which meanes that CODE is not an instruction of OPCODE; otherwise
2003 1.1 christos return 1.
2004 1.1 christos
2005 1.1 christos If OPCODE has alias(es) and NOALIASES_P is 0, an alias opcode may be
2006 1.1 christos determined and used to disassemble CODE; this is done just before the
2007 1.1 christos return. */
2008 1.1 christos
2009 1.1 christos static int
2010 1.1 christos aarch64_opcode_decode (const aarch64_opcode *opcode, const aarch64_insn code,
2011 1.1 christos aarch64_inst *inst, int noaliases_p)
2012 1.1 christos {
2013 1.1 christos int i;
2014 1.1 christos
2015 1.1 christos DEBUG_TRACE ("enter with %s", opcode->name);
2016 1.1 christos
2017 1.1 christos assert (opcode && inst);
2018 1.1 christos
2019 1.1 christos /* Check the base opcode. */
2020 1.1 christos if ((code & opcode->mask) != (opcode->opcode & opcode->mask))
2021 1.1 christos {
2022 1.1 christos DEBUG_TRACE ("base opcode match FAIL");
2023 1.1 christos goto decode_fail;
2024 1.1 christos }
2025 1.1 christos
2026 1.1 christos /* Clear inst. */
2027 1.1 christos memset (inst, '\0', sizeof (aarch64_inst));
2028 1.1 christos
2029 1.1 christos inst->opcode = opcode;
2030 1.1 christos inst->value = code;
2031 1.1 christos
2032 1.1 christos /* Assign operand codes and indexes. */
2033 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
2034 1.1 christos {
2035 1.1 christos if (opcode->operands[i] == AARCH64_OPND_NIL)
2036 1.1 christos break;
2037 1.1 christos inst->operands[i].type = opcode->operands[i];
2038 1.1 christos inst->operands[i].idx = i;
2039 1.1 christos }
2040 1.1 christos
2041 1.1 christos /* Call the opcode decoder indicated by flags. */
2042 1.1 christos if (opcode_has_special_coder (opcode) && do_special_decoding (inst) == 0)
2043 1.1 christos {
2044 1.1 christos DEBUG_TRACE ("opcode flag-based decoder FAIL");
2045 1.1 christos goto decode_fail;
2046 1.1 christos }
2047 1.1 christos
2048 1.1 christos /* Call operand decoders. */
2049 1.1 christos for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
2050 1.1 christos {
2051 1.1 christos const aarch64_operand *opnd;
2052 1.1 christos enum aarch64_opnd type;
2053 1.1 christos type = opcode->operands[i];
2054 1.1 christos if (type == AARCH64_OPND_NIL)
2055 1.1 christos break;
2056 1.1 christos opnd = &aarch64_operands[type];
2057 1.1 christos if (operand_has_extractor (opnd)
2058 1.1 christos && (! aarch64_extract_operand (opnd, &inst->operands[i], code, inst)))
2059 1.1 christos {
2060 1.1 christos DEBUG_TRACE ("operand decoder FAIL at operand %d", i);
2061 1.1 christos goto decode_fail;
2062 1.1 christos }
2063 1.1 christos }
2064 1.1 christos
2065 1.1 christos /* Match the qualifiers. */
2066 1.1 christos if (aarch64_match_operands_constraint (inst, NULL) == 1)
2067 1.1 christos {
2068 1.1 christos /* Arriving here, the CODE has been determined as a valid instruction
2069 1.1 christos of OPCODE and *INST has been filled with information of this OPCODE
2070 1.1 christos instruction. Before the return, check if the instruction has any
2071 1.1 christos alias and should be disassembled in the form of its alias instead.
2072 1.1 christos If the answer is yes, *INST will be updated. */
2073 1.1 christos if (!noaliases_p)
2074 1.1 christos determine_disassembling_preference (inst);
2075 1.1 christos DEBUG_TRACE ("SUCCESS");
2076 1.1 christos return 1;
2077 1.1 christos }
2078 1.1 christos else
2079 1.1 christos {
2080 1.1 christos DEBUG_TRACE ("constraint matching FAIL");
2081 1.1 christos }
2082 1.1 christos
2083 1.1 christos decode_fail:
2084 1.1 christos return 0;
2085 1.1 christos }
2086 1.1 christos
2087 1.1 christos /* This does some user-friendly fix-up to *INST. It is currently focus on
2089 1.1 christos the adjustment of qualifiers to help the printed instruction
2090 1.1 christos recognized/understood more easily. */
2091 1.1 christos
2092 1.1 christos static void
2093 1.1 christos user_friendly_fixup (aarch64_inst *inst)
2094 1.1 christos {
2095 1.1 christos switch (inst->opcode->iclass)
2096 1.1 christos {
2097 1.1 christos case testbranch:
2098 1.1 christos /* TBNZ Xn|Wn, #uimm6, label
2099 1.1 christos Test and Branch Not Zero: conditionally jumps to label if bit number
2100 1.1 christos uimm6 in register Xn is not zero. The bit number implies the width of
2101 1.1 christos the register, which may be written and should be disassembled as Wn if
2102 1.1 christos uimm is less than 32. Limited to a branch offset range of +/- 32KiB.
2103 1.1 christos */
2104 1.1 christos if (inst->operands[1].imm.value < 32)
2105 1.1 christos inst->operands[0].qualifier = AARCH64_OPND_QLF_W;
2106 1.1 christos break;
2107 1.3 christos default: break;
2108 1.3 christos }
2109 1.3 christos }
2110 1.1 christos
2111 1.3 christos /* Decode INSN and fill in *INST the instruction information. An alias
2112 1.3 christos opcode may be filled in *INSN if NOALIASES_P is FALSE. Return zero on
2113 1.3 christos success. */
2114 1.1 christos
2115 1.1 christos int
2116 1.1 christos aarch64_decode_insn (aarch64_insn insn, aarch64_inst *inst,
2117 1.1 christos bfd_boolean noaliases_p)
2118 1.1 christos {
2119 1.1 christos const aarch64_opcode *opcode = aarch64_opcode_lookup (insn);
2120 1.1 christos
2121 1.1 christos #ifdef DEBUG_AARCH64
2122 1.1 christos if (debug_dump)
2123 1.1 christos {
2124 1.1 christos const aarch64_opcode *tmp = opcode;
2125 1.1 christos printf ("\n");
2126 1.1 christos DEBUG_TRACE ("opcode lookup:");
2127 1.1 christos while (tmp != NULL)
2128 1.1 christos {
2129 1.1 christos aarch64_verbose (" %s", tmp->name);
2130 1.1 christos tmp = aarch64_find_next_opcode (tmp);
2131 1.1 christos }
2132 1.1 christos }
2133 1.1 christos #endif /* DEBUG_AARCH64 */
2134 1.1 christos
2135 1.1 christos /* A list of opcodes may have been found, as aarch64_opcode_lookup cannot
2136 1.1 christos distinguish some opcodes, e.g. SSHR and MOVI, which almost share the same
2137 1.1 christos opcode field and value, apart from the difference that one of them has an
2138 1.1 christos extra field as part of the opcode, but such a field is used for operand
2139 1.1 christos encoding in other opcode(s) ('immh' in the case of the example). */
2140 1.3 christos while (opcode != NULL)
2141 1.1 christos {
2142 1.1 christos /* But only one opcode can be decoded successfully for, as the
2143 1.1 christos decoding routine will check the constraint carefully. */
2144 1.1 christos if (aarch64_opcode_decode (opcode, insn, inst, noaliases_p) == 1)
2145 1.1 christos return ERR_OK;
2146 1.1 christos opcode = aarch64_find_next_opcode (opcode);
2147 1.1 christos }
2148 1.1 christos
2149 1.1 christos return ERR_UND;
2150 1.1 christos }
2151 1.1 christos
2152 1.1 christos /* Print operands. */
2153 1.1 christos
2154 1.1 christos static void
2155 1.1 christos print_operands (bfd_vma pc, const aarch64_opcode *opcode,
2156 1.1 christos const aarch64_opnd_info *opnds, struct disassemble_info *info)
2157 1.1 christos {
2158 1.1 christos int i, pcrel_p, num_printed;
2159 1.1 christos for (i = 0, num_printed = 0; i < AARCH64_MAX_OPND_NUM; ++i)
2160 1.1 christos {
2161 1.1 christos const size_t size = 128;
2162 1.1 christos char str[size];
2163 1.1 christos /* We regard the opcode operand info more, however we also look into
2164 1.1 christos the inst->operands to support the disassembling of the optional
2165 1.1 christos operand.
2166 1.1 christos The two operand code should be the same in all cases, apart from
2167 1.1 christos when the operand can be optional. */
2168 1.1 christos if (opcode->operands[i] == AARCH64_OPND_NIL
2169 1.1 christos || opnds[i].type == AARCH64_OPND_NIL)
2170 1.1 christos break;
2171 1.1 christos
2172 1.1 christos /* Generate the operand string in STR. */
2173 1.1 christos aarch64_print_operand (str, size, pc, opcode, opnds, i, &pcrel_p,
2174 1.1 christos &info->target);
2175 1.1 christos
2176 1.1 christos /* Print the delimiter (taking account of omitted operand(s)). */
2177 1.1 christos if (str[0] != '\0')
2178 1.1 christos (*info->fprintf_func) (info->stream, "%s",
2179 1.1 christos num_printed++ == 0 ? "\t" : ", ");
2180 1.1 christos
2181 1.1 christos /* Print the operand. */
2182 1.1 christos if (pcrel_p)
2183 1.1 christos (*info->print_address_func) (info->target, info);
2184 1.1 christos else
2185 1.1 christos (*info->fprintf_func) (info->stream, "%s", str);
2186 1.1 christos }
2187 1.1 christos }
2188 1.1 christos
2189 1.1 christos /* Print the instruction mnemonic name. */
2190 1.1 christos
2191 1.1 christos static void
2192 1.1 christos print_mnemonic_name (const aarch64_inst *inst, struct disassemble_info *info)
2193 1.1 christos {
2194 1.1 christos if (inst->opcode->flags & F_COND)
2195 1.1 christos {
2196 1.1 christos /* For instructions that are truly conditionally executed, e.g. b.cond,
2197 1.3 christos prepare the full mnemonic name with the corresponding condition
2198 1.1 christos suffix. */
2199 1.1 christos char name[8], *ptr;
2200 1.1 christos size_t len;
2201 1.1 christos
2202 1.1 christos ptr = strchr (inst->opcode->name, '.');
2203 1.1 christos assert (ptr && inst->cond);
2204 1.1 christos len = ptr - inst->opcode->name;
2205 1.1 christos assert (len < 8);
2206 1.1 christos strncpy (name, inst->opcode->name, len);
2207 1.1 christos name [len] = '\0';
2208 1.1 christos (*info->fprintf_func) (info->stream, "%s.%s", name, inst->cond->names[0]);
2209 1.1 christos }
2210 1.1 christos else
2211 1.1 christos (*info->fprintf_func) (info->stream, "%s", inst->opcode->name);
2212 1.1 christos }
2213 1.1 christos
2214 1.1 christos /* Print the instruction according to *INST. */
2215 1.1 christos
2216 1.1 christos static void
2217 1.1 christos print_aarch64_insn (bfd_vma pc, const aarch64_inst *inst,
2218 1.1 christos struct disassemble_info *info)
2219 1.1 christos {
2220 1.1 christos print_mnemonic_name (inst, info);
2221 1.1 christos print_operands (pc, inst->opcode, inst->operands, info);
2222 1.1 christos }
2223 1.1 christos
2224 1.1 christos /* Entry-point of the instruction disassembler and printer. */
2225 1.1 christos
2226 1.1 christos static void
2227 1.1 christos print_insn_aarch64_word (bfd_vma pc,
2228 1.1 christos uint32_t word,
2229 1.1 christos struct disassemble_info *info)
2230 1.1 christos {
2231 1.1 christos static const char *err_msg[6] =
2232 1.1 christos {
2233 1.1 christos [ERR_OK] = "_",
2234 1.1 christos [-ERR_UND] = "undefined",
2235 1.1 christos [-ERR_UNP] = "unpredictable",
2236 1.1 christos [-ERR_NYI] = "NYI"
2237 1.1 christos };
2238 1.1 christos
2239 1.1 christos int ret;
2240 1.1 christos aarch64_inst inst;
2241 1.1 christos
2242 1.1 christos info->insn_info_valid = 1;
2243 1.1 christos info->branch_delay_insns = 0;
2244 1.1 christos info->data_size = 0;
2245 1.1 christos info->target = 0;
2246 1.1 christos info->target2 = 0;
2247 1.1 christos
2248 1.1 christos if (info->flags & INSN_HAS_RELOC)
2249 1.1 christos /* If the instruction has a reloc associated with it, then
2250 1.1 christos the offset field in the instruction will actually be the
2251 1.1 christos addend for the reloc. (If we are using REL type relocs).
2252 1.3 christos In such cases, we can ignore the pc when computing
2253 1.1 christos addresses, since the addend is not currently pc-relative. */
2254 1.1 christos pc = 0;
2255 1.1 christos
2256 1.3 christos ret = aarch64_decode_insn (word, &inst, no_aliases);
2257 1.1 christos
2258 1.1 christos if (((word >> 21) & 0x3ff) == 1)
2259 1.1 christos {
2260 1.1 christos /* RESERVED for ALES. */
2261 1.1 christos assert (ret != ERR_OK);
2262 1.1 christos ret = ERR_NYI;
2263 1.1 christos }
2264 1.1 christos
2265 1.1 christos switch (ret)
2266 1.1 christos {
2267 1.1 christos case ERR_UND:
2268 1.1 christos case ERR_UNP:
2269 1.1 christos case ERR_NYI:
2270 1.1 christos /* Handle undefined instructions. */
2271 1.1 christos info->insn_type = dis_noninsn;
2272 1.1 christos (*info->fprintf_func) (info->stream,".inst\t0x%08x ; %s",
2273 1.1 christos word, err_msg[-ret]);
2274 1.1 christos break;
2275 1.1 christos case ERR_OK:
2276 1.1 christos user_friendly_fixup (&inst);
2277 1.1 christos print_aarch64_insn (pc, &inst, info);
2278 1.1 christos break;
2279 1.1 christos default:
2280 1.1 christos abort ();
2281 1.1 christos }
2282 1.1 christos }
2283 1.1 christos
2284 1.1 christos /* Disallow mapping symbols ($x, $d etc) from
2285 1.1 christos being displayed in symbol relative addresses. */
2286 1.1 christos
2287 1.1 christos bfd_boolean
2288 1.1 christos aarch64_symbol_is_valid (asymbol * sym,
2289 1.1 christos struct disassemble_info * info ATTRIBUTE_UNUSED)
2290 1.1 christos {
2291 1.1 christos const char * name;
2292 1.1 christos
2293 1.1 christos if (sym == NULL)
2294 1.1 christos return FALSE;
2295 1.1 christos
2296 1.1 christos name = bfd_asymbol_name (sym);
2297 1.1 christos
2298 1.1 christos return name
2299 1.1 christos && (name[0] != '$'
2300 1.1 christos || (name[1] != 'x' && name[1] != 'd')
2301 1.1 christos || (name[2] != '\0' && name[2] != '.'));
2302 1.1 christos }
2303 1.1 christos
2304 1.1 christos /* Print data bytes on INFO->STREAM. */
2305 1.1 christos
2306 1.1 christos static void
2307 1.1 christos print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED,
2308 1.1 christos uint32_t word,
2309 1.1 christos struct disassemble_info *info)
2310 1.1 christos {
2311 1.1 christos switch (info->bytes_per_chunk)
2312 1.1 christos {
2313 1.1 christos case 1:
2314 1.1 christos info->fprintf_func (info->stream, ".byte\t0x%02x", word);
2315 1.1 christos break;
2316 1.1 christos case 2:
2317 1.1 christos info->fprintf_func (info->stream, ".short\t0x%04x", word);
2318 1.1 christos break;
2319 1.1 christos case 4:
2320 1.1 christos info->fprintf_func (info->stream, ".word\t0x%08x", word);
2321 1.1 christos break;
2322 1.1 christos default:
2323 1.1 christos abort ();
2324 1.1 christos }
2325 1.1 christos }
2326 1.1 christos
2327 1.1 christos /* Try to infer the code or data type from a symbol.
2328 1.1 christos Returns nonzero if *MAP_TYPE was set. */
2329 1.1 christos
2330 1.1 christos static int
2331 1.1 christos get_sym_code_type (struct disassemble_info *info, int n,
2332 1.1 christos enum map_type *map_type)
2333 1.1 christos {
2334 1.1 christos elf_symbol_type *es;
2335 1.1 christos unsigned int type;
2336 1.1 christos const char *name;
2337 1.1 christos
2338 1.1 christos es = *(elf_symbol_type **)(info->symtab + n);
2339 1.1 christos type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
2340 1.1 christos
2341 1.1 christos /* If the symbol has function type then use that. */
2342 1.1 christos if (type == STT_FUNC)
2343 1.1 christos {
2344 1.1 christos *map_type = MAP_INSN;
2345 1.1 christos return TRUE;
2346 1.1 christos }
2347 1.1 christos
2348 1.1 christos /* Check for mapping symbols. */
2349 1.1 christos name = bfd_asymbol_name(info->symtab[n]);
2350 1.1 christos if (name[0] == '$'
2351 1.1 christos && (name[1] == 'x' || name[1] == 'd')
2352 1.1 christos && (name[2] == '\0' || name[2] == '.'))
2353 1.1 christos {
2354 1.1 christos *map_type = (name[1] == 'x' ? MAP_INSN : MAP_DATA);
2355 1.1 christos return TRUE;
2356 1.1 christos }
2357 1.1 christos
2358 1.1 christos return FALSE;
2359 1.1 christos }
2360 1.1 christos
2361 1.1 christos /* Entry-point of the AArch64 disassembler. */
2362 1.1 christos
2363 1.1 christos int
2364 1.1 christos print_insn_aarch64 (bfd_vma pc,
2365 1.1 christos struct disassemble_info *info)
2366 1.1 christos {
2367 1.1 christos bfd_byte buffer[INSNLEN];
2368 1.1 christos int status;
2369 1.1 christos void (*printer) (bfd_vma, uint32_t, struct disassemble_info *);
2370 1.1 christos bfd_boolean found = FALSE;
2371 1.1 christos unsigned int size = 4;
2372 1.1 christos unsigned long data;
2373 1.1 christos
2374 1.1 christos if (info->disassembler_options)
2375 1.1 christos {
2376 1.1 christos set_default_aarch64_dis_options (info);
2377 1.1 christos
2378 1.1 christos parse_aarch64_dis_options (info->disassembler_options);
2379 1.1 christos
2380 1.1 christos /* To avoid repeated parsing of these options, we remove them here. */
2381 1.1 christos info->disassembler_options = NULL;
2382 1.1 christos }
2383 1.1 christos
2384 1.1 christos /* Aarch64 instructions are always little-endian */
2385 1.1 christos info->endian_code = BFD_ENDIAN_LITTLE;
2386 1.1 christos
2387 1.1 christos /* First check the full symtab for a mapping symbol, even if there
2388 1.1 christos are no usable non-mapping symbols for this address. */
2389 1.1 christos if (info->symtab_size != 0
2390 1.1 christos && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour)
2391 1.1 christos {
2392 1.1 christos enum map_type type = MAP_INSN;
2393 1.1 christos int last_sym = -1;
2394 1.1 christos bfd_vma addr;
2395 1.1 christos int n;
2396 1.1 christos
2397 1.1 christos if (pc <= last_mapping_addr)
2398 1.1 christos last_mapping_sym = -1;
2399 1.1 christos
2400 1.1 christos /* Start scanning at the start of the function, or wherever
2401 1.1 christos we finished last time. */
2402 1.1 christos n = info->symtab_pos + 1;
2403 1.1 christos if (n < last_mapping_sym)
2404 1.1 christos n = last_mapping_sym;
2405 1.1 christos
2406 1.1 christos /* Scan up to the location being disassembled. */
2407 1.1 christos for (; n < info->symtab_size; n++)
2408 1.1 christos {
2409 1.1 christos addr = bfd_asymbol_value (info->symtab[n]);
2410 1.1 christos if (addr > pc)
2411 1.1 christos break;
2412 1.1 christos if ((info->section == NULL
2413 1.1 christos || info->section == info->symtab[n]->section)
2414 1.1 christos && get_sym_code_type (info, n, &type))
2415 1.1 christos {
2416 1.1 christos last_sym = n;
2417 1.1 christos found = TRUE;
2418 1.1 christos }
2419 1.1 christos }
2420 1.1 christos
2421 1.1 christos if (!found)
2422 1.1 christos {
2423 1.1 christos n = info->symtab_pos;
2424 1.1 christos if (n < last_mapping_sym)
2425 1.1 christos n = last_mapping_sym;
2426 1.1 christos
2427 1.1 christos /* No mapping symbol found at this address. Look backwards
2428 1.1 christos for a preceeding one. */
2429 1.1 christos for (; n >= 0; n--)
2430 1.1 christos {
2431 1.1 christos if (get_sym_code_type (info, n, &type))
2432 1.1 christos {
2433 1.1 christos last_sym = n;
2434 1.1 christos found = TRUE;
2435 1.1 christos break;
2436 1.1 christos }
2437 1.1 christos }
2438 1.1 christos }
2439 1.1 christos
2440 1.1 christos last_mapping_sym = last_sym;
2441 1.1 christos last_type = type;
2442 1.1 christos
2443 1.1 christos /* Look a little bit ahead to see if we should print out
2444 1.1 christos less than four bytes of data. If there's a symbol,
2445 1.1 christos mapping or otherwise, after two bytes then don't
2446 1.1 christos print more. */
2447 1.1 christos if (last_type == MAP_DATA)
2448 1.1 christos {
2449 1.1 christos size = 4 - (pc & 3);
2450 1.1 christos for (n = last_sym + 1; n < info->symtab_size; n++)
2451 1.1 christos {
2452 1.1 christos addr = bfd_asymbol_value (info->symtab[n]);
2453 1.1 christos if (addr > pc)
2454 1.1 christos {
2455 1.1 christos if (addr - pc < size)
2456 1.1 christos size = addr - pc;
2457 1.1 christos break;
2458 1.1 christos }
2459 1.1 christos }
2460 1.1 christos /* If the next symbol is after three bytes, we need to
2461 1.1 christos print only part of the data, so that we can use either
2462 1.1 christos .byte or .short. */
2463 1.1 christos if (size == 3)
2464 1.1 christos size = (pc & 1) ? 1 : 2;
2465 1.1 christos }
2466 1.1 christos }
2467 1.1 christos
2468 1.1 christos if (last_type == MAP_DATA)
2469 1.1 christos {
2470 1.1 christos /* size was set above. */
2471 1.1 christos info->bytes_per_chunk = size;
2472 1.1 christos info->display_endian = info->endian;
2473 1.1 christos printer = print_insn_data;
2474 1.1 christos }
2475 1.1 christos else
2476 1.1 christos {
2477 1.1 christos info->bytes_per_chunk = size = INSNLEN;
2478 1.1 christos info->display_endian = info->endian_code;
2479 1.1 christos printer = print_insn_aarch64_word;
2480 1.1 christos }
2481 1.1 christos
2482 1.1 christos status = (*info->read_memory_func) (pc, buffer, size, info);
2483 1.1 christos if (status != 0)
2484 1.1 christos {
2485 1.1 christos (*info->memory_error_func) (status, pc, info);
2486 1.1 christos return -1;
2487 1.1 christos }
2488 1.1 christos
2489 1.1 christos data = bfd_get_bits (buffer, size * 8,
2490 1.1 christos info->display_endian == BFD_ENDIAN_BIG);
2491 1.1 christos
2492 1.1 christos (*printer) (pc, data, info);
2493 1.1 christos
2494 1.1 christos return size;
2495 1.1 christos }
2496 1.1 christos
2497 1.1 christos void
2499 1.1 christos print_aarch64_disassembler_options (FILE *stream)
2500 1.1 christos {
2501 1.1 christos fprintf (stream, _("\n\
2502 1.1 christos The following AARCH64 specific disassembler options are supported for use\n\
2503 1.1 christos with the -M switch (multiple options should be separated by commas):\n"));
2504 1.1 christos
2505 1.1 christos fprintf (stream, _("\n\
2506 1.1 christos no-aliases Don't print instruction aliases.\n"));
2507 1.1 christos
2508 1.1 christos fprintf (stream, _("\n\
2509 1.1 christos aliases Do print instruction aliases.\n"));
2510 1.1 christos
2511 1.1 christos #ifdef DEBUG_AARCH64
2512 1.1 christos fprintf (stream, _("\n\
2513 debug_dump Temp switch for debug trace.\n"));
2514 #endif /* DEBUG_AARCH64 */
2515
2516 fprintf (stream, _("\n"));
2517 }
2518