Allow non-fatal errors to be emitted and for disassembly notes be placed on AArch64
[deliverable/binutils-gdb.git] / opcodes / aarch64-asm.c
CommitLineData
a06ea964 1/* aarch64-asm.c -- AArch64 assembler support.
219d1afa 2 Copyright (C) 2012-2018 Free Software Foundation, Inc.
a06ea964
NC
3 Contributed by ARM Ltd.
4
5 This file is part of the GNU opcodes library.
6
7 This library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING3. If not,
19 see <http://www.gnu.org/licenses/>. */
20
21#include "sysdep.h"
22#include <stdarg.h>
b5464a68 23#include "libiberty.h"
a06ea964
NC
24#include "aarch64-asm.h"
25
26/* Utilities. */
27
28/* The unnamed arguments consist of the number of fields and information about
29 these fields where the VALUE will be inserted into CODE. MASK can be zero or
30 the base mask of the opcode.
31
32 N.B. the fields are required to be in such an order than the least signficant
33 field for VALUE comes the first, e.g. the <index> in
34 SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
9aff4b7a 35 is encoded in H:L:M in some cases, the fields H:L:M should be passed in
a06ea964
NC
36 the order of M, L, H. */
37
38static inline void
39insert_fields (aarch64_insn *code, aarch64_insn value, aarch64_insn mask, ...)
40{
41 uint32_t num;
42 const aarch64_field *field;
43 enum aarch64_field_kind kind;
44 va_list va;
45
46 va_start (va, mask);
47 num = va_arg (va, uint32_t);
48 assert (num <= 5);
49 while (num--)
50 {
51 kind = va_arg (va, enum aarch64_field_kind);
52 field = &fields[kind];
53 insert_field (kind, code, value, mask);
54 value >>= field->width;
55 }
56 va_end (va);
57}
58
b5464a68
RS
59/* Insert a raw field value VALUE into all fields in SELF->fields.
60 The least significant bit goes in the final field. */
61
62static void
63insert_all_fields (const aarch64_operand *self, aarch64_insn *code,
64 aarch64_insn value)
65{
66 unsigned int i;
67 enum aarch64_field_kind kind;
68
69 for (i = ARRAY_SIZE (self->fields); i-- > 0; )
70 if (self->fields[i] != FLD_NIL)
71 {
72 kind = self->fields[i];
73 insert_field (kind, code, value, 0);
74 value >>= fields[kind].width;
75 }
76}
77
a06ea964
NC
78/* Operand inserters. */
79
80/* Insert register number. */
561a72d4 81bfd_boolean
a06ea964
NC
82aarch64_ins_regno (const aarch64_operand *self, const aarch64_opnd_info *info,
83 aarch64_insn *code,
561a72d4
TC
84 const aarch64_inst *inst ATTRIBUTE_UNUSED,
85 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
86{
87 insert_field (self->fields[0], code, info->reg.regno, 0);
561a72d4 88 return TRUE;
a06ea964
NC
89}
90
91/* Insert register number, index and/or other data for SIMD register element
92 operand, e.g. the last source operand in
93 SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]. */
561a72d4 94bfd_boolean
a06ea964 95aarch64_ins_reglane (const aarch64_operand *self, const aarch64_opnd_info *info,
561a72d4
TC
96 aarch64_insn *code, const aarch64_inst *inst,
97 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
98{
99 /* regno */
100 insert_field (self->fields[0], code, info->reglane.regno, inst->opcode->mask);
101 /* index and/or type */
102 if (inst->opcode->iclass == asisdone || inst->opcode->iclass == asimdins)
103 {
104 int pos = info->qualifier - AARCH64_OPND_QLF_S_B;
105 if (info->type == AARCH64_OPND_En
106 && inst->opcode->operands[0] == AARCH64_OPND_Ed)
107 {
108 /* index2 for e.g. INS <Vd>.<Ts>[<index1>], <Vn>.<Ts>[<index2>]. */
109 assert (info->idx == 1); /* Vn */
110 aarch64_insn value = info->reglane.index << pos;
111 insert_field (FLD_imm4, code, value, 0);
112 }
113 else
114 {
115 /* index and type for e.g. DUP <V><d>, <Vn>.<T>[<index>].
116 imm5<3:0> <V>
117 0000 RESERVED
118 xxx1 B
119 xx10 H
120 x100 S
121 1000 D */
122 aarch64_insn value = ((info->reglane.index << 1) | 1) << pos;
123 insert_field (FLD_imm5, code, value, 0);
124 }
125 }
65a55fbb
TC
126 else if (inst->opcode->iclass == dotproduct)
127 {
128 unsigned reglane_index = info->reglane.index;
129 switch (info->qualifier)
130 {
00c2093f 131 case AARCH64_OPND_QLF_S_4B:
65a55fbb
TC
132 /* L:H */
133 assert (reglane_index < 4);
134 insert_fields (code, reglane_index, 0, 2, FLD_L, FLD_H);
135 break;
136 default:
137 assert (0);
138 }
139 }
f42f1a1d
TC
140 else if (inst->opcode->iclass == cryptosm3)
141 {
142 /* index for e.g. SM3TT2A <Vd>.4S, <Vn>.4S, <Vm>S[<imm2>]. */
143 unsigned reglane_index = info->reglane.index;
144 assert (reglane_index < 4);
145 insert_field (FLD_SM3_imm2, code, reglane_index, 0);
146 }
a06ea964
NC
147 else
148 {
149 /* index for e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
150 or SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]. */
329d01f7 151 unsigned reglane_index = info->reglane.index;
c2c4ff8d
SN
152
153 if (inst->opcode->op == OP_FCMLA_ELEM)
154 /* Complex operand takes two elements. */
329d01f7 155 reglane_index *= 2;
c2c4ff8d 156
a06ea964
NC
157 switch (info->qualifier)
158 {
159 case AARCH64_OPND_QLF_S_H:
160 /* H:L:M */
329d01f7
MR
161 assert (reglane_index < 8);
162 insert_fields (code, reglane_index, 0, 3, FLD_M, FLD_L, FLD_H);
a06ea964
NC
163 break;
164 case AARCH64_OPND_QLF_S_S:
165 /* H:L */
329d01f7
MR
166 assert (reglane_index < 4);
167 insert_fields (code, reglane_index, 0, 2, FLD_L, FLD_H);
a06ea964
NC
168 break;
169 case AARCH64_OPND_QLF_S_D:
170 /* H */
329d01f7
MR
171 assert (reglane_index < 2);
172 insert_field (FLD_H, code, reglane_index, 0);
a06ea964
NC
173 break;
174 default:
175 assert (0);
176 }
177 }
561a72d4 178 return TRUE;
a06ea964
NC
179}
180
181/* Insert regno and len field of a register list operand, e.g. Vn in TBL. */
561a72d4 182bfd_boolean
a06ea964
NC
183aarch64_ins_reglist (const aarch64_operand *self, const aarch64_opnd_info *info,
184 aarch64_insn *code,
561a72d4
TC
185 const aarch64_inst *inst ATTRIBUTE_UNUSED,
186 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
187{
188 /* R */
189 insert_field (self->fields[0], code, info->reglist.first_regno, 0);
190 /* len */
191 insert_field (FLD_len, code, info->reglist.num_regs - 1, 0);
561a72d4 192 return TRUE;
a06ea964
NC
193}
194
195/* Insert Rt and opcode fields for a register list operand, e.g. Vt
196 in AdvSIMD load/store instructions. */
561a72d4 197bfd_boolean
a06ea964
NC
198aarch64_ins_ldst_reglist (const aarch64_operand *self ATTRIBUTE_UNUSED,
199 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
200 const aarch64_inst *inst,
201 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964 202{
4ad3b7ef 203 aarch64_insn value = 0;
a06ea964
NC
204 /* Number of elements in each structure to be loaded/stored. */
205 unsigned num = get_opcode_dependent_value (inst->opcode);
206
207 /* Rt */
208 insert_field (FLD_Rt, code, info->reglist.first_regno, 0);
209 /* opcode */
210 switch (num)
211 {
212 case 1:
213 switch (info->reglist.num_regs)
214 {
215 case 1: value = 0x7; break;
216 case 2: value = 0xa; break;
217 case 3: value = 0x6; break;
218 case 4: value = 0x2; break;
219 default: assert (0);
220 }
221 break;
222 case 2:
223 value = info->reglist.num_regs == 4 ? 0x3 : 0x8;
224 break;
225 case 3:
226 value = 0x4;
227 break;
228 case 4:
229 value = 0x0;
230 break;
231 default:
232 assert (0);
233 }
234 insert_field (FLD_opcode, code, value, 0);
235
561a72d4 236 return TRUE;
a06ea964
NC
237}
238
239/* Insert Rt and S fields for a register list operand, e.g. Vt in AdvSIMD load
240 single structure to all lanes instructions. */
561a72d4 241bfd_boolean
a06ea964
NC
242aarch64_ins_ldst_reglist_r (const aarch64_operand *self ATTRIBUTE_UNUSED,
243 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
244 const aarch64_inst *inst,
245 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
246{
247 aarch64_insn value;
248 /* The opcode dependent area stores the number of elements in
249 each structure to be loaded/stored. */
250 int is_ld1r = get_opcode_dependent_value (inst->opcode) == 1;
251
252 /* Rt */
253 insert_field (FLD_Rt, code, info->reglist.first_regno, 0);
254 /* S */
255 value = (aarch64_insn) 0;
256 if (is_ld1r && info->reglist.num_regs == 2)
257 /* OP_LD1R does not have alternating variant, but have "two consecutive"
258 instead. */
259 value = (aarch64_insn) 1;
260 insert_field (FLD_S, code, value, 0);
261
561a72d4 262 return TRUE;
a06ea964
NC
263}
264
265/* Insert Q, opcode<2:1>, S, size and Rt fields for a register element list
266 operand e.g. Vt in AdvSIMD load/store single element instructions. */
561a72d4 267bfd_boolean
a06ea964
NC
268aarch64_ins_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED,
269 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
270 const aarch64_inst *inst ATTRIBUTE_UNUSED,
271 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
272{
273 aarch64_field field = {0, 0};
4ad3b7ef
KT
274 aarch64_insn QSsize = 0; /* fields Q:S:size. */
275 aarch64_insn opcodeh2 = 0; /* opcode<2:1> */
a06ea964
NC
276
277 assert (info->reglist.has_index);
278
279 /* Rt */
280 insert_field (FLD_Rt, code, info->reglist.first_regno, 0);
281 /* Encode the index, opcode<2:1> and size. */
282 switch (info->qualifier)
283 {
284 case AARCH64_OPND_QLF_S_B:
285 /* Index encoded in "Q:S:size". */
286 QSsize = info->reglist.index;
287 opcodeh2 = 0x0;
288 break;
289 case AARCH64_OPND_QLF_S_H:
290 /* Index encoded in "Q:S:size<1>". */
291 QSsize = info->reglist.index << 1;
292 opcodeh2 = 0x1;
293 break;
294 case AARCH64_OPND_QLF_S_S:
295 /* Index encoded in "Q:S". */
296 QSsize = info->reglist.index << 2;
297 opcodeh2 = 0x2;
298 break;
299 case AARCH64_OPND_QLF_S_D:
300 /* Index encoded in "Q". */
301 QSsize = info->reglist.index << 3 | 0x1;
302 opcodeh2 = 0x2;
303 break;
304 default:
305 assert (0);
306 }
307 insert_fields (code, QSsize, 0, 3, FLD_vldst_size, FLD_S, FLD_Q);
308 gen_sub_field (FLD_asisdlso_opcode, 1, 2, &field);
309 insert_field_2 (&field, code, opcodeh2, 0);
310
561a72d4 311 return TRUE;
a06ea964
NC
312}
313
314/* Insert fields immh:immb and/or Q for e.g. the shift immediate in
315 SSHR <Vd>.<T>, <Vn>.<T>, #<shift>
316 or SSHR <V><d>, <V><n>, #<shift>. */
561a72d4 317bfd_boolean
a06ea964
NC
318aarch64_ins_advsimd_imm_shift (const aarch64_operand *self ATTRIBUTE_UNUSED,
319 const aarch64_opnd_info *info,
561a72d4
TC
320 aarch64_insn *code, const aarch64_inst *inst,
321 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
322{
323 unsigned val = aarch64_get_qualifier_standard_value (info->qualifier);
324 aarch64_insn Q, imm;
325
326 if (inst->opcode->iclass == asimdshf)
327 {
328 /* Q
329 immh Q <T>
330 0000 x SEE AdvSIMD modified immediate
331 0001 0 8B
332 0001 1 16B
333 001x 0 4H
334 001x 1 8H
335 01xx 0 2S
336 01xx 1 4S
337 1xxx 0 RESERVED
338 1xxx 1 2D */
339 Q = (val & 0x1) ? 1 : 0;
340 insert_field (FLD_Q, code, Q, inst->opcode->mask);
341 val >>= 1;
342 }
343
344 assert (info->type == AARCH64_OPND_IMM_VLSR
345 || info->type == AARCH64_OPND_IMM_VLSL);
346
347 if (info->type == AARCH64_OPND_IMM_VLSR)
348 /* immh:immb
349 immh <shift>
350 0000 SEE AdvSIMD modified immediate
351 0001 (16-UInt(immh:immb))
352 001x (32-UInt(immh:immb))
353 01xx (64-UInt(immh:immb))
354 1xxx (128-UInt(immh:immb)) */
355 imm = (16 << (unsigned)val) - info->imm.value;
356 else
357 /* immh:immb
358 immh <shift>
359 0000 SEE AdvSIMD modified immediate
360 0001 (UInt(immh:immb)-8)
361 001x (UInt(immh:immb)-16)
362 01xx (UInt(immh:immb)-32)
363 1xxx (UInt(immh:immb)-64) */
364 imm = info->imm.value + (8 << (unsigned)val);
365 insert_fields (code, imm, 0, 2, FLD_immb, FLD_immh);
366
561a72d4 367 return TRUE;
a06ea964
NC
368}
369
370/* Insert fields for e.g. the immediate operands in
371 BFM <Wd>, <Wn>, #<immr>, #<imms>. */
561a72d4 372bfd_boolean
a06ea964
NC
373aarch64_ins_imm (const aarch64_operand *self, const aarch64_opnd_info *info,
374 aarch64_insn *code,
561a72d4
TC
375 const aarch64_inst *inst ATTRIBUTE_UNUSED,
376 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
377{
378 int64_t imm;
a06ea964
NC
379
380 imm = info->imm.value;
381 if (operand_need_shift_by_two (self))
382 imm >>= 2;
b5464a68 383 insert_all_fields (self, code, imm);
561a72d4 384 return TRUE;
a06ea964
NC
385}
386
387/* Insert immediate and its shift amount for e.g. the last operand in
388 MOVZ <Wd>, #<imm16>{, LSL #<shift>}. */
561a72d4 389bfd_boolean
a06ea964 390aarch64_ins_imm_half (const aarch64_operand *self, const aarch64_opnd_info *info,
561a72d4
TC
391 aarch64_insn *code, const aarch64_inst *inst,
392 aarch64_operand_error *errors)
a06ea964
NC
393{
394 /* imm16 */
561a72d4 395 aarch64_ins_imm (self, info, code, inst, errors);
a06ea964
NC
396 /* hw */
397 insert_field (FLD_hw, code, info->shifter.amount >> 4, 0);
561a72d4 398 return TRUE;
a06ea964
NC
399}
400
401/* Insert cmode and "a:b:c:d:e:f:g:h" fields for e.g. the last operand in
402 MOVI <Vd>.<T>, #<imm8> {, LSL #<amount>}. */
561a72d4 403bfd_boolean
a06ea964
NC
404aarch64_ins_advsimd_imm_modified (const aarch64_operand *self ATTRIBUTE_UNUSED,
405 const aarch64_opnd_info *info,
406 aarch64_insn *code,
561a72d4
TC
407 const aarch64_inst *inst ATTRIBUTE_UNUSED,
408 aarch64_operand_error *errors
409 ATTRIBUTE_UNUSED)
a06ea964
NC
410{
411 enum aarch64_opnd_qualifier opnd0_qualifier = inst->operands[0].qualifier;
412 uint64_t imm = info->imm.value;
413 enum aarch64_modifier_kind kind = info->shifter.kind;
414 int amount = info->shifter.amount;
415 aarch64_field field = {0, 0};
416
417 /* a:b:c:d:e:f:g:h */
418 if (!info->imm.is_fp && aarch64_get_qualifier_esize (opnd0_qualifier) == 8)
419 {
420 /* Either MOVI <Dd>, #<imm>
421 or MOVI <Vd>.2D, #<imm>.
422 <imm> is a 64-bit immediate
423 "aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh",
424 encoded in "a:b:c:d:e:f:g:h". */
425 imm = aarch64_shrink_expanded_imm8 (imm);
426 assert ((int)imm >= 0);
427 }
a06ea964
NC
428 insert_fields (code, imm, 0, 2, FLD_defgh, FLD_abc);
429
430 if (kind == AARCH64_MOD_NONE)
561a72d4 431 return TRUE;
a06ea964
NC
432
433 /* shift amount partially in cmode */
434 assert (kind == AARCH64_MOD_LSL || kind == AARCH64_MOD_MSL);
435 if (kind == AARCH64_MOD_LSL)
436 {
437 /* AARCH64_MOD_LSL: shift zeros. */
438 int esize = aarch64_get_qualifier_esize (opnd0_qualifier);
f5555712
YZ
439 assert (esize == 4 || esize == 2 || esize == 1);
440 /* For 8-bit move immediate, the optional LSL #0 does not require
441 encoding. */
442 if (esize == 1)
561a72d4 443 return TRUE;
a06ea964
NC
444 amount >>= 3;
445 if (esize == 4)
446 gen_sub_field (FLD_cmode, 1, 2, &field); /* per word */
447 else
448 gen_sub_field (FLD_cmode, 1, 1, &field); /* per halfword */
449 }
450 else
451 {
452 /* AARCH64_MOD_MSL: shift ones. */
453 amount >>= 4;
454 gen_sub_field (FLD_cmode, 0, 1, &field); /* per word */
455 }
456 insert_field_2 (&field, code, amount, 0);
457
561a72d4 458 return TRUE;
aa2aa4c6
RS
459}
460
461/* Insert fields for an 8-bit floating-point immediate. */
561a72d4 462bfd_boolean
aa2aa4c6
RS
463aarch64_ins_fpimm (const aarch64_operand *self, const aarch64_opnd_info *info,
464 aarch64_insn *code,
561a72d4
TC
465 const aarch64_inst *inst ATTRIBUTE_UNUSED,
466 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
aa2aa4c6
RS
467{
468 insert_all_fields (self, code, info->imm.value);
561a72d4 469 return TRUE;
a06ea964
NC
470}
471
582e12bf 472/* Insert 1-bit rotation immediate (#90 or #270). */
561a72d4 473bfd_boolean
582e12bf
RS
474aarch64_ins_imm_rotate1 (const aarch64_operand *self,
475 const aarch64_opnd_info *info,
561a72d4
TC
476 aarch64_insn *code, const aarch64_inst *inst,
477 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
c2c4ff8d 478{
582e12bf
RS
479 uint64_t rot = (info->imm.value - 90) / 180;
480 assert (rot < 2U);
c2c4ff8d 481 insert_field (self->fields[0], code, rot, inst->opcode->mask);
561a72d4 482 return TRUE;
582e12bf 483}
c2c4ff8d 484
582e12bf 485/* Insert 2-bit rotation immediate (#0, #90, #180 or #270). */
561a72d4 486bfd_boolean
582e12bf
RS
487aarch64_ins_imm_rotate2 (const aarch64_operand *self,
488 const aarch64_opnd_info *info,
561a72d4
TC
489 aarch64_insn *code, const aarch64_inst *inst,
490 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
582e12bf
RS
491{
492 uint64_t rot = info->imm.value / 90;
493 assert (rot < 4U);
494 insert_field (self->fields[0], code, rot, inst->opcode->mask);
561a72d4 495 return TRUE;
c2c4ff8d
SN
496}
497
a06ea964
NC
498/* Insert #<fbits> for the immediate operand in fp fix-point instructions,
499 e.g. SCVTF <Dd>, <Wn>, #<fbits>. */
561a72d4 500bfd_boolean
a06ea964
NC
501aarch64_ins_fbits (const aarch64_operand *self, const aarch64_opnd_info *info,
502 aarch64_insn *code,
561a72d4
TC
503 const aarch64_inst *inst ATTRIBUTE_UNUSED,
504 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
505{
506 insert_field (self->fields[0], code, 64 - info->imm.value, 0);
561a72d4 507 return TRUE;
a06ea964
NC
508}
509
510/* Insert arithmetic immediate for e.g. the last operand in
511 SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}. */
561a72d4 512bfd_boolean
a06ea964 513aarch64_ins_aimm (const aarch64_operand *self, const aarch64_opnd_info *info,
561a72d4
TC
514 aarch64_insn *code, const aarch64_inst *inst ATTRIBUTE_UNUSED,
515 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
516{
517 /* shift */
518 aarch64_insn value = info->shifter.amount ? 1 : 0;
519 insert_field (self->fields[0], code, value, 0);
520 /* imm12 (unsigned) */
521 insert_field (self->fields[1], code, info->imm.value, 0);
561a72d4 522 return TRUE;
a06ea964
NC
523}
524
e950b345
RS
525/* Common routine shared by aarch64_ins{,_inv}_limm. INVERT_P says whether
526 the operand should be inverted before encoding. */
561a72d4 527static bfd_boolean
e950b345
RS
528aarch64_ins_limm_1 (const aarch64_operand *self,
529 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
530 const aarch64_inst *inst, bfd_boolean invert_p,
531 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
532{
533 aarch64_insn value;
534 uint64_t imm = info->imm.value;
42408347 535 int esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier);
a06ea964 536
e950b345 537 if (invert_p)
a06ea964 538 imm = ~imm;
535b785f
AM
539 /* The constraint check should have guaranteed this wouldn't happen. */
540 assert (aarch64_logical_immediate_p (imm, esize, &value));
a06ea964
NC
541
542 insert_fields (code, value, 0, 3, self->fields[2], self->fields[1],
543 self->fields[0]);
561a72d4 544 return TRUE;
a06ea964
NC
545}
546
e950b345
RS
547/* Insert logical/bitmask immediate for e.g. the last operand in
548 ORR <Wd|WSP>, <Wn>, #<imm>. */
561a72d4 549bfd_boolean
e950b345 550aarch64_ins_limm (const aarch64_operand *self, const aarch64_opnd_info *info,
561a72d4
TC
551 aarch64_insn *code, const aarch64_inst *inst,
552 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
e950b345
RS
553{
554 return aarch64_ins_limm_1 (self, info, code, inst,
561a72d4 555 inst->opcode->op == OP_BIC, errors);
e950b345
RS
556}
557
558/* Insert a logical/bitmask immediate for the BIC alias of AND (etc.). */
561a72d4 559bfd_boolean
e950b345
RS
560aarch64_ins_inv_limm (const aarch64_operand *self,
561 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
562 const aarch64_inst *inst,
563 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
e950b345 564{
561a72d4 565 return aarch64_ins_limm_1 (self, info, code, inst, TRUE, errors);
e950b345
RS
566}
567
a06ea964
NC
568/* Encode Ft for e.g. STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]
569 or LDP <Qt1>, <Qt2>, [<Xn|SP>], #<imm>. */
561a72d4 570bfd_boolean
a06ea964 571aarch64_ins_ft (const aarch64_operand *self, const aarch64_opnd_info *info,
561a72d4
TC
572 aarch64_insn *code, const aarch64_inst *inst,
573 aarch64_operand_error *errors)
a06ea964 574{
4ad3b7ef 575 aarch64_insn value = 0;
a06ea964
NC
576
577 assert (info->idx == 0);
578
579 /* Rt */
561a72d4 580 aarch64_ins_regno (self, info, code, inst, errors);
a06ea964
NC
581 if (inst->opcode->iclass == ldstpair_indexed
582 || inst->opcode->iclass == ldstnapair_offs
583 || inst->opcode->iclass == ldstpair_off
584 || inst->opcode->iclass == loadlit)
585 {
586 /* size */
587 switch (info->qualifier)
588 {
589 case AARCH64_OPND_QLF_S_S: value = 0; break;
590 case AARCH64_OPND_QLF_S_D: value = 1; break;
591 case AARCH64_OPND_QLF_S_Q: value = 2; break;
592 default: assert (0);
593 }
594 insert_field (FLD_ldst_size, code, value, 0);
595 }
596 else
597 {
598 /* opc[1]:size */
599 value = aarch64_get_qualifier_standard_value (info->qualifier);
600 insert_fields (code, value, 0, 2, FLD_ldst_size, FLD_opc1);
601 }
602
561a72d4 603 return TRUE;
a06ea964
NC
604}
605
606/* Encode the address operand for e.g. STXRB <Ws>, <Wt>, [<Xn|SP>{,#0}]. */
561a72d4 607bfd_boolean
a06ea964
NC
608aarch64_ins_addr_simple (const aarch64_operand *self ATTRIBUTE_UNUSED,
609 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
610 const aarch64_inst *inst ATTRIBUTE_UNUSED,
611 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
612{
613 /* Rn */
614 insert_field (FLD_Rn, code, info->addr.base_regno, 0);
561a72d4 615 return TRUE;
a06ea964
NC
616}
617
618/* Encode the address operand for e.g.
619 STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
561a72d4 620bfd_boolean
a06ea964
NC
621aarch64_ins_addr_regoff (const aarch64_operand *self ATTRIBUTE_UNUSED,
622 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
623 const aarch64_inst *inst ATTRIBUTE_UNUSED,
624 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
625{
626 aarch64_insn S;
627 enum aarch64_modifier_kind kind = info->shifter.kind;
628
629 /* Rn */
630 insert_field (FLD_Rn, code, info->addr.base_regno, 0);
631 /* Rm */
632 insert_field (FLD_Rm, code, info->addr.offset.regno, 0);
633 /* option */
634 if (kind == AARCH64_MOD_LSL)
635 kind = AARCH64_MOD_UXTX; /* Trick to enable the table-driven. */
636 insert_field (FLD_option, code, aarch64_get_operand_modifier_value (kind), 0);
637 /* S */
638 if (info->qualifier != AARCH64_OPND_QLF_S_B)
639 S = info->shifter.amount != 0;
640 else
641 /* For STR <Bt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}},
642 S <amount>
643 0 [absent]
644 1 #0
645 Must be #0 if <extend> is explicitly LSL. */
646 S = info->shifter.operator_present && info->shifter.amount_present;
647 insert_field (FLD_S, code, S, 0);
648
561a72d4 649 return TRUE;
a06ea964
NC
650}
651
f42f1a1d
TC
652/* Encode the address operand for e.g.
653 stlur <Xt>, [<Xn|SP>{, <amount>}]. */
561a72d4 654bfd_boolean
f42f1a1d
TC
655aarch64_ins_addr_offset (const aarch64_operand *self ATTRIBUTE_UNUSED,
656 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
657 const aarch64_inst *inst ATTRIBUTE_UNUSED,
658 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
f42f1a1d
TC
659{
660 /* Rn */
661 insert_field (self->fields[0], code, info->addr.base_regno, 0);
662
663 /* simm9 */
664 int imm = info->addr.offset.imm;
665 insert_field (self->fields[1], code, imm, 0);
666
667 /* writeback */
668 if (info->addr.writeback)
669 {
670 assert (info->addr.preind == 1 && info->addr.postind == 0);
671 insert_field (self->fields[2], code, 1, 0);
672 }
561a72d4 673 return TRUE;
f42f1a1d
TC
674}
675
a06ea964 676/* Encode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>, #<simm>]!. */
561a72d4 677bfd_boolean
a06ea964
NC
678aarch64_ins_addr_simm (const aarch64_operand *self,
679 const aarch64_opnd_info *info,
062f38fa 680 aarch64_insn *code,
561a72d4
TC
681 const aarch64_inst *inst ATTRIBUTE_UNUSED,
682 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
683{
684 int imm;
685
686 /* Rn */
687 insert_field (FLD_Rn, code, info->addr.base_regno, 0);
688 /* simm (imm9 or imm7) */
689 imm = info->addr.offset.imm;
690 if (self->fields[0] == FLD_imm7)
691 /* scaled immediate in ld/st pair instructions.. */
692 imm >>= get_logsz (aarch64_get_qualifier_esize (info->qualifier));
693 insert_field (self->fields[0], code, imm, 0);
694 /* pre/post- index */
695 if (info->addr.writeback)
696 {
697 assert (inst->opcode->iclass != ldst_unscaled
698 && inst->opcode->iclass != ldstnapair_offs
699 && inst->opcode->iclass != ldstpair_off
700 && inst->opcode->iclass != ldst_unpriv);
701 assert (info->addr.preind != info->addr.postind);
702 if (info->addr.preind)
703 insert_field (self->fields[1], code, 1, 0);
704 }
705
561a72d4 706 return TRUE;
a06ea964
NC
707}
708
3f06e550 709/* Encode the address operand for e.g. LDRAA <Xt>, [<Xn|SP>{, #<simm>}]. */
561a72d4 710bfd_boolean
3f06e550
SN
711aarch64_ins_addr_simm10 (const aarch64_operand *self,
712 const aarch64_opnd_info *info,
713 aarch64_insn *code,
561a72d4
TC
714 const aarch64_inst *inst ATTRIBUTE_UNUSED,
715 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
3f06e550
SN
716{
717 int imm;
718
719 /* Rn */
720 insert_field (self->fields[0], code, info->addr.base_regno, 0);
721 /* simm10 */
722 imm = info->addr.offset.imm >> 3;
723 insert_field (self->fields[1], code, imm >> 9, 0);
724 insert_field (self->fields[2], code, imm, 0);
725 /* writeback */
726 if (info->addr.writeback)
727 {
728 assert (info->addr.preind == 1 && info->addr.postind == 0);
729 insert_field (self->fields[3], code, 1, 0);
730 }
561a72d4 731 return TRUE;
3f06e550
SN
732}
733
a06ea964 734/* Encode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>{, #<pimm>}]. */
561a72d4 735bfd_boolean
a06ea964
NC
736aarch64_ins_addr_uimm12 (const aarch64_operand *self,
737 const aarch64_opnd_info *info,
738 aarch64_insn *code,
561a72d4
TC
739 const aarch64_inst *inst ATTRIBUTE_UNUSED,
740 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
741{
742 int shift = get_logsz (aarch64_get_qualifier_esize (info->qualifier));
743
744 /* Rn */
745 insert_field (self->fields[0], code, info->addr.base_regno, 0);
746 /* uimm12 */
747 insert_field (self->fields[1], code,info->addr.offset.imm >> shift, 0);
561a72d4 748 return TRUE;
a06ea964
NC
749}
750
751/* Encode the address operand for e.g.
752 LD1 {<Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>}, [<Xn|SP>], <Xm|#<amount>>. */
561a72d4 753bfd_boolean
a06ea964
NC
754aarch64_ins_simd_addr_post (const aarch64_operand *self ATTRIBUTE_UNUSED,
755 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
756 const aarch64_inst *inst ATTRIBUTE_UNUSED,
757 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
758{
759 /* Rn */
760 insert_field (FLD_Rn, code, info->addr.base_regno, 0);
761 /* Rm | #<amount> */
762 if (info->addr.offset.is_reg)
763 insert_field (FLD_Rm, code, info->addr.offset.regno, 0);
764 else
765 insert_field (FLD_Rm, code, 0x1f, 0);
561a72d4 766 return TRUE;
a06ea964
NC
767}
768
769/* Encode the condition operand for e.g. CSEL <Xd>, <Xn>, <Xm>, <cond>. */
561a72d4 770bfd_boolean
a06ea964
NC
771aarch64_ins_cond (const aarch64_operand *self ATTRIBUTE_UNUSED,
772 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
773 const aarch64_inst *inst ATTRIBUTE_UNUSED,
774 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
775{
776 /* cond */
777 insert_field (FLD_cond, code, info->cond->value, 0);
561a72d4 778 return TRUE;
a06ea964
NC
779}
780
781/* Encode the system register operand for e.g. MRS <Xt>, <systemreg>. */
561a72d4 782bfd_boolean
a06ea964
NC
783aarch64_ins_sysreg (const aarch64_operand *self ATTRIBUTE_UNUSED,
784 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
785 const aarch64_inst *inst,
786 aarch64_operand_error *detail ATTRIBUTE_UNUSED)
a06ea964
NC
787{
788 /* op0:op1:CRn:CRm:op2 */
561a72d4 789 insert_fields (code, info->sysreg.value, inst->opcode->mask, 5,
a06ea964 790 FLD_op2, FLD_CRm, FLD_CRn, FLD_op1, FLD_op0);
561a72d4 791 return TRUE;
a06ea964
NC
792}
793
794/* Encode the PSTATE field operand for e.g. MSR <pstatefield>, #<imm>. */
561a72d4 795bfd_boolean
a06ea964
NC
796aarch64_ins_pstatefield (const aarch64_operand *self ATTRIBUTE_UNUSED,
797 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
798 const aarch64_inst *inst ATTRIBUTE_UNUSED,
799 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
800{
801 /* op1:op2 */
802 insert_fields (code, info->pstatefield, inst->opcode->mask, 2,
803 FLD_op2, FLD_op1);
561a72d4 804 return TRUE;
a06ea964
NC
805}
806
807/* Encode the system instruction op operand for e.g. AT <at_op>, <Xt>. */
561a72d4 808bfd_boolean
a06ea964
NC
809aarch64_ins_sysins_op (const aarch64_operand *self ATTRIBUTE_UNUSED,
810 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
811 const aarch64_inst *inst ATTRIBUTE_UNUSED,
812 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
813{
814 /* op1:CRn:CRm:op2 */
815 insert_fields (code, info->sysins_op->value, inst->opcode->mask, 4,
816 FLD_op2, FLD_CRm, FLD_CRn, FLD_op1);
561a72d4 817 return TRUE;
a06ea964
NC
818}
819
820/* Encode the memory barrier option operand for e.g. DMB <option>|#<imm>. */
821
561a72d4 822bfd_boolean
a06ea964
NC
823aarch64_ins_barrier (const aarch64_operand *self ATTRIBUTE_UNUSED,
824 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
825 const aarch64_inst *inst ATTRIBUTE_UNUSED,
826 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
827{
828 /* CRm */
829 insert_field (FLD_CRm, code, info->barrier->value, 0);
561a72d4 830 return TRUE;
a06ea964
NC
831}
832
833/* Encode the prefetch operation option operand for e.g.
834 PRFM <prfop>, [<Xn|SP>{, #<pimm>}]. */
835
561a72d4 836bfd_boolean
a06ea964
NC
837aarch64_ins_prfop (const aarch64_operand *self ATTRIBUTE_UNUSED,
838 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
839 const aarch64_inst *inst ATTRIBUTE_UNUSED,
840 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
841{
842 /* prfop in Rt */
843 insert_field (FLD_Rt, code, info->prfop->value, 0);
561a72d4 844 return TRUE;
a06ea964
NC
845}
846
9ed608f9
MW
847/* Encode the hint number for instructions that alias HINT but take an
848 operand. */
849
561a72d4 850bfd_boolean
9ed608f9
MW
851aarch64_ins_hint (const aarch64_operand *self ATTRIBUTE_UNUSED,
852 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
853 const aarch64_inst *inst ATTRIBUTE_UNUSED,
854 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
9ed608f9
MW
855{
856 /* CRm:op2. */
857 insert_fields (code, info->hint_option->value, 0, 2, FLD_op2, FLD_CRm);
561a72d4 858 return TRUE;
9ed608f9
MW
859}
860
a06ea964
NC
861/* Encode the extended register operand for e.g.
862 STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
561a72d4 863bfd_boolean
a06ea964
NC
864aarch64_ins_reg_extended (const aarch64_operand *self ATTRIBUTE_UNUSED,
865 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
866 const aarch64_inst *inst ATTRIBUTE_UNUSED,
867 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
868{
869 enum aarch64_modifier_kind kind;
870
871 /* Rm */
872 insert_field (FLD_Rm, code, info->reg.regno, 0);
873 /* option */
874 kind = info->shifter.kind;
875 if (kind == AARCH64_MOD_LSL)
876 kind = info->qualifier == AARCH64_OPND_QLF_W
877 ? AARCH64_MOD_UXTW : AARCH64_MOD_UXTX;
878 insert_field (FLD_option, code, aarch64_get_operand_modifier_value (kind), 0);
879 /* imm3 */
880 insert_field (FLD_imm3, code, info->shifter.amount, 0);
881
561a72d4 882 return TRUE;
a06ea964
NC
883}
884
885/* Encode the shifted register operand for e.g.
886 SUBS <Xd>, <Xn>, <Xm> {, <shift> #<amount>}. */
561a72d4 887bfd_boolean
a06ea964
NC
888aarch64_ins_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED,
889 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
890 const aarch64_inst *inst ATTRIBUTE_UNUSED,
891 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
a06ea964
NC
892{
893 /* Rm */
894 insert_field (FLD_Rm, code, info->reg.regno, 0);
895 /* shift */
896 insert_field (FLD_shift, code,
897 aarch64_get_operand_modifier_value (info->shifter.kind), 0);
898 /* imm6 */
899 insert_field (FLD_imm6, code, info->shifter.amount, 0);
900
561a72d4 901 return TRUE;
a06ea964
NC
902}
903
98907a70
RS
904/* Encode an SVE address [<base>, #<simm4>*<factor>, MUL VL],
905 where <simm4> is a 4-bit signed value and where <factor> is 1 plus
906 SELF's operand-dependent value. fields[0] specifies the field that
907 holds <base>. <simm4> is encoded in the SVE_imm4 field. */
561a72d4 908bfd_boolean
98907a70
RS
909aarch64_ins_sve_addr_ri_s4xvl (const aarch64_operand *self,
910 const aarch64_opnd_info *info,
911 aarch64_insn *code,
561a72d4
TC
912 const aarch64_inst *inst ATTRIBUTE_UNUSED,
913 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
98907a70
RS
914{
915 int factor = 1 + get_operand_specific_data (self);
916 insert_field (self->fields[0], code, info->addr.base_regno, 0);
917 insert_field (FLD_SVE_imm4, code, info->addr.offset.imm / factor, 0);
561a72d4 918 return TRUE;
98907a70
RS
919}
920
921/* Encode an SVE address [<base>, #<simm6>*<factor>, MUL VL],
922 where <simm6> is a 6-bit signed value and where <factor> is 1 plus
923 SELF's operand-dependent value. fields[0] specifies the field that
924 holds <base>. <simm6> is encoded in the SVE_imm6 field. */
561a72d4 925bfd_boolean
98907a70
RS
926aarch64_ins_sve_addr_ri_s6xvl (const aarch64_operand *self,
927 const aarch64_opnd_info *info,
928 aarch64_insn *code,
561a72d4
TC
929 const aarch64_inst *inst ATTRIBUTE_UNUSED,
930 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
98907a70
RS
931{
932 int factor = 1 + get_operand_specific_data (self);
933 insert_field (self->fields[0], code, info->addr.base_regno, 0);
934 insert_field (FLD_SVE_imm6, code, info->addr.offset.imm / factor, 0);
561a72d4 935 return TRUE;
98907a70
RS
936}
937
938/* Encode an SVE address [<base>, #<simm9>*<factor>, MUL VL],
939 where <simm9> is a 9-bit signed value and where <factor> is 1 plus
940 SELF's operand-dependent value. fields[0] specifies the field that
941 holds <base>. <simm9> is encoded in the concatenation of the SVE_imm6
942 and imm3 fields, with imm3 being the less-significant part. */
561a72d4 943bfd_boolean
98907a70
RS
944aarch64_ins_sve_addr_ri_s9xvl (const aarch64_operand *self,
945 const aarch64_opnd_info *info,
946 aarch64_insn *code,
561a72d4
TC
947 const aarch64_inst *inst ATTRIBUTE_UNUSED,
948 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
98907a70
RS
949{
950 int factor = 1 + get_operand_specific_data (self);
951 insert_field (self->fields[0], code, info->addr.base_regno, 0);
952 insert_fields (code, info->addr.offset.imm / factor, 0,
953 2, FLD_imm3, FLD_SVE_imm6);
561a72d4 954 return TRUE;
98907a70
RS
955}
956
582e12bf
RS
957/* Encode an SVE address [X<n>, #<SVE_imm4> << <shift>], where <SVE_imm4>
958 is a 4-bit signed number and where <shift> is SELF's operand-dependent
959 value. fields[0] specifies the base register field. */
561a72d4 960bfd_boolean
582e12bf
RS
961aarch64_ins_sve_addr_ri_s4 (const aarch64_operand *self,
962 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
963 const aarch64_inst *inst ATTRIBUTE_UNUSED,
964 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
582e12bf
RS
965{
966 int factor = 1 << get_operand_specific_data (self);
967 insert_field (self->fields[0], code, info->addr.base_regno, 0);
968 insert_field (FLD_SVE_imm4, code, info->addr.offset.imm / factor, 0);
561a72d4 969 return TRUE;
582e12bf
RS
970}
971
4df068de
RS
972/* Encode an SVE address [X<n>, #<SVE_imm6> << <shift>], where <SVE_imm6>
973 is a 6-bit unsigned number and where <shift> is SELF's operand-dependent
974 value. fields[0] specifies the base register field. */
561a72d4 975bfd_boolean
4df068de
RS
976aarch64_ins_sve_addr_ri_u6 (const aarch64_operand *self,
977 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
978 const aarch64_inst *inst ATTRIBUTE_UNUSED,
979 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
4df068de
RS
980{
981 int factor = 1 << get_operand_specific_data (self);
982 insert_field (self->fields[0], code, info->addr.base_regno, 0);
983 insert_field (FLD_SVE_imm6, code, info->addr.offset.imm / factor, 0);
561a72d4 984 return TRUE;
4df068de
RS
985}
986
987/* Encode an SVE address [X<n>, X<m>{, LSL #<shift>}], where <shift>
988 is SELF's operand-dependent value. fields[0] specifies the base
989 register field and fields[1] specifies the offset register field. */
561a72d4 990bfd_boolean
4df068de
RS
991aarch64_ins_sve_addr_rr_lsl (const aarch64_operand *self,
992 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
993 const aarch64_inst *inst ATTRIBUTE_UNUSED,
994 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
4df068de
RS
995{
996 insert_field (self->fields[0], code, info->addr.base_regno, 0);
997 insert_field (self->fields[1], code, info->addr.offset.regno, 0);
561a72d4 998 return TRUE;
4df068de
RS
999}
1000
1001/* Encode an SVE address [X<n>, Z<m>.<T>, (S|U)XTW {#<shift>}], where
1002 <shift> is SELF's operand-dependent value. fields[0] specifies the
1003 base register field, fields[1] specifies the offset register field and
1004 fields[2] is a single-bit field that selects SXTW over UXTW. */
561a72d4 1005bfd_boolean
4df068de
RS
1006aarch64_ins_sve_addr_rz_xtw (const aarch64_operand *self,
1007 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
1008 const aarch64_inst *inst ATTRIBUTE_UNUSED,
1009 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
4df068de
RS
1010{
1011 insert_field (self->fields[0], code, info->addr.base_regno, 0);
1012 insert_field (self->fields[1], code, info->addr.offset.regno, 0);
1013 if (info->shifter.kind == AARCH64_MOD_UXTW)
1014 insert_field (self->fields[2], code, 0, 0);
1015 else
1016 insert_field (self->fields[2], code, 1, 0);
561a72d4 1017 return TRUE;
4df068de
RS
1018}
1019
1020/* Encode an SVE address [Z<n>.<T>, #<imm5> << <shift>], where <imm5> is a
1021 5-bit unsigned number and where <shift> is SELF's operand-dependent value.
1022 fields[0] specifies the base register field. */
561a72d4 1023bfd_boolean
4df068de
RS
1024aarch64_ins_sve_addr_zi_u5 (const aarch64_operand *self,
1025 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
1026 const aarch64_inst *inst ATTRIBUTE_UNUSED,
1027 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
4df068de
RS
1028{
1029 int factor = 1 << get_operand_specific_data (self);
1030 insert_field (self->fields[0], code, info->addr.base_regno, 0);
1031 insert_field (FLD_imm5, code, info->addr.offset.imm / factor, 0);
561a72d4 1032 return TRUE;
4df068de
RS
1033}
1034
1035/* Encode an SVE address [Z<n>.<T>, Z<m>.<T>{, <modifier> {#<msz>}}],
1036 where <modifier> is fixed by the instruction and where <msz> is a
1037 2-bit unsigned number. fields[0] specifies the base register field
1038 and fields[1] specifies the offset register field. */
561a72d4 1039static bfd_boolean
4df068de 1040aarch64_ext_sve_addr_zz (const aarch64_operand *self,
561a72d4
TC
1041 const aarch64_opnd_info *info, aarch64_insn *code,
1042 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
4df068de
RS
1043{
1044 insert_field (self->fields[0], code, info->addr.base_regno, 0);
1045 insert_field (self->fields[1], code, info->addr.offset.regno, 0);
1046 insert_field (FLD_SVE_msz, code, info->shifter.amount, 0);
561a72d4 1047 return TRUE;
4df068de
RS
1048}
1049
1050/* Encode an SVE address [Z<n>.<T>, Z<m>.<T>{, LSL #<msz>}], where
1051 <msz> is a 2-bit unsigned number. fields[0] specifies the base register
1052 field and fields[1] specifies the offset register field. */
561a72d4 1053bfd_boolean
4df068de
RS
1054aarch64_ins_sve_addr_zz_lsl (const aarch64_operand *self,
1055 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
1056 const aarch64_inst *inst ATTRIBUTE_UNUSED,
1057 aarch64_operand_error *errors)
4df068de 1058{
561a72d4 1059 return aarch64_ext_sve_addr_zz (self, info, code, errors);
4df068de
RS
1060}
1061
1062/* Encode an SVE address [Z<n>.<T>, Z<m>.<T>, SXTW {#<msz>}], where
1063 <msz> is a 2-bit unsigned number. fields[0] specifies the base register
1064 field and fields[1] specifies the offset register field. */
561a72d4 1065bfd_boolean
4df068de
RS
1066aarch64_ins_sve_addr_zz_sxtw (const aarch64_operand *self,
1067 const aarch64_opnd_info *info,
1068 aarch64_insn *code,
561a72d4
TC
1069 const aarch64_inst *inst ATTRIBUTE_UNUSED,
1070 aarch64_operand_error *errors)
4df068de 1071{
561a72d4 1072 return aarch64_ext_sve_addr_zz (self, info, code, errors);
4df068de
RS
1073}
1074
1075/* Encode an SVE address [Z<n>.<T>, Z<m>.<T>, UXTW {#<msz>}], where
1076 <msz> is a 2-bit unsigned number. fields[0] specifies the base register
1077 field and fields[1] specifies the offset register field. */
561a72d4 1078bfd_boolean
4df068de
RS
1079aarch64_ins_sve_addr_zz_uxtw (const aarch64_operand *self,
1080 const aarch64_opnd_info *info,
1081 aarch64_insn *code,
561a72d4
TC
1082 const aarch64_inst *inst ATTRIBUTE_UNUSED,
1083 aarch64_operand_error *errors)
4df068de 1084{
561a72d4 1085 return aarch64_ext_sve_addr_zz (self, info, code, errors);
4df068de
RS
1086}
1087
e950b345 1088/* Encode an SVE ADD/SUB immediate. */
561a72d4 1089bfd_boolean
e950b345
RS
1090aarch64_ins_sve_aimm (const aarch64_operand *self,
1091 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
1092 const aarch64_inst *inst ATTRIBUTE_UNUSED,
1093 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
e950b345
RS
1094{
1095 if (info->shifter.amount == 8)
1096 insert_all_fields (self, code, (info->imm.value & 0xff) | 256);
1097 else if (info->imm.value != 0 && (info->imm.value & 0xff) == 0)
1098 insert_all_fields (self, code, ((info->imm.value / 256) & 0xff) | 256);
1099 else
1100 insert_all_fields (self, code, info->imm.value & 0xff);
561a72d4 1101 return TRUE;
e950b345
RS
1102}
1103
1104/* Encode an SVE CPY/DUP immediate. */
561a72d4 1105bfd_boolean
e950b345
RS
1106aarch64_ins_sve_asimm (const aarch64_operand *self,
1107 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
1108 const aarch64_inst *inst,
1109 aarch64_operand_error *errors)
e950b345 1110{
561a72d4 1111 return aarch64_ins_sve_aimm (self, info, code, inst, errors);
e950b345
RS
1112}
1113
f11ad6bc
RS
1114/* Encode Zn[MM], where MM has a 7-bit triangular encoding. The fields
1115 array specifies which field to use for Zn. MM is encoded in the
1116 concatenation of imm5 and SVE_tszh, with imm5 being the less
1117 significant part. */
561a72d4 1118bfd_boolean
f11ad6bc
RS
1119aarch64_ins_sve_index (const aarch64_operand *self,
1120 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
1121 const aarch64_inst *inst ATTRIBUTE_UNUSED,
1122 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
f11ad6bc
RS
1123{
1124 unsigned int esize = aarch64_get_qualifier_esize (info->qualifier);
1125 insert_field (self->fields[0], code, info->reglane.regno, 0);
1126 insert_fields (code, (info->reglane.index * 2 + 1) * esize, 0,
1127 2, FLD_imm5, FLD_SVE_tszh);
561a72d4 1128 return TRUE;
f11ad6bc
RS
1129}
1130
e950b345 1131/* Encode a logical/bitmask immediate for the MOV alias of SVE DUPM. */
561a72d4 1132bfd_boolean
e950b345
RS
1133aarch64_ins_sve_limm_mov (const aarch64_operand *self,
1134 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
1135 const aarch64_inst *inst,
1136 aarch64_operand_error *errors)
e950b345 1137{
561a72d4 1138 return aarch64_ins_limm (self, info, code, inst, errors);
e950b345
RS
1139}
1140
582e12bf
RS
1141/* Encode Zn[MM], where Zn occupies the least-significant part of the field
1142 and where MM occupies the most-significant part. The operand-dependent
1143 value specifies the number of bits in Zn. */
561a72d4 1144bfd_boolean
582e12bf
RS
1145aarch64_ins_sve_quad_index (const aarch64_operand *self,
1146 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
1147 const aarch64_inst *inst ATTRIBUTE_UNUSED,
1148 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
582e12bf
RS
1149{
1150 unsigned int reg_bits = get_operand_specific_data (self);
1151 assert (info->reglane.regno < (1U << reg_bits));
1152 unsigned int val = (info->reglane.index << reg_bits) + info->reglane.regno;
1153 insert_all_fields (self, code, val);
561a72d4 1154 return TRUE;
582e12bf
RS
1155}
1156
f11ad6bc
RS
1157/* Encode {Zn.<T> - Zm.<T>}. The fields array specifies which field
1158 to use for Zn. */
561a72d4 1159bfd_boolean
f11ad6bc
RS
1160aarch64_ins_sve_reglist (const aarch64_operand *self,
1161 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
1162 const aarch64_inst *inst ATTRIBUTE_UNUSED,
1163 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
f11ad6bc
RS
1164{
1165 insert_field (self->fields[0], code, info->reglist.first_regno, 0);
561a72d4 1166 return TRUE;
f11ad6bc
RS
1167}
1168
2442d846
RS
1169/* Encode <pattern>{, MUL #<amount>}. The fields array specifies which
1170 fields to use for <pattern>. <amount> - 1 is encoded in the SVE_imm4
1171 field. */
561a72d4 1172bfd_boolean
2442d846
RS
1173aarch64_ins_sve_scale (const aarch64_operand *self,
1174 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
1175 const aarch64_inst *inst ATTRIBUTE_UNUSED,
1176 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
2442d846
RS
1177{
1178 insert_all_fields (self, code, info->imm.value);
1179 insert_field (FLD_SVE_imm4, code, info->shifter.amount - 1, 0);
561a72d4 1180 return TRUE;
2442d846
RS
1181}
1182
e950b345 1183/* Encode an SVE shift left immediate. */
561a72d4 1184bfd_boolean
e950b345
RS
1185aarch64_ins_sve_shlimm (const aarch64_operand *self,
1186 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
1187 const aarch64_inst *inst,
1188 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
e950b345
RS
1189{
1190 const aarch64_opnd_info *prev_operand;
1191 unsigned int esize;
1192
1193 assert (info->idx > 0);
1194 prev_operand = &inst->operands[info->idx - 1];
1195 esize = aarch64_get_qualifier_esize (prev_operand->qualifier);
1196 insert_all_fields (self, code, 8 * esize + info->imm.value);
561a72d4 1197 return TRUE;
e950b345
RS
1198}
1199
1200/* Encode an SVE shift right immediate. */
561a72d4 1201bfd_boolean
e950b345
RS
1202aarch64_ins_sve_shrimm (const aarch64_operand *self,
1203 const aarch64_opnd_info *info, aarch64_insn *code,
561a72d4
TC
1204 const aarch64_inst *inst,
1205 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
e950b345
RS
1206{
1207 const aarch64_opnd_info *prev_operand;
1208 unsigned int esize;
1209
1210 assert (info->idx > 0);
1211 prev_operand = &inst->operands[info->idx - 1];
1212 esize = aarch64_get_qualifier_esize (prev_operand->qualifier);
1213 insert_all_fields (self, code, 16 * esize - info->imm.value);
561a72d4 1214 return TRUE;
e950b345
RS
1215}
1216
165d4950
RS
1217/* Encode a single-bit immediate that selects between #0.5 and #1.0.
1218 The fields array specifies which field to use. */
561a72d4 1219bfd_boolean
165d4950
RS
1220aarch64_ins_sve_float_half_one (const aarch64_operand *self,
1221 const aarch64_opnd_info *info,
1222 aarch64_insn *code,
561a72d4
TC
1223 const aarch64_inst *inst ATTRIBUTE_UNUSED,
1224 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
165d4950
RS
1225{
1226 if (info->imm.value == 0x3f000000)
1227 insert_field (self->fields[0], code, 0, 0);
1228 else
1229 insert_field (self->fields[0], code, 1, 0);
561a72d4 1230 return TRUE;
165d4950
RS
1231}
1232
1233/* Encode a single-bit immediate that selects between #0.5 and #2.0.
1234 The fields array specifies which field to use. */
561a72d4 1235bfd_boolean
165d4950
RS
1236aarch64_ins_sve_float_half_two (const aarch64_operand *self,
1237 const aarch64_opnd_info *info,
1238 aarch64_insn *code,
561a72d4
TC
1239 const aarch64_inst *inst ATTRIBUTE_UNUSED,
1240 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
165d4950
RS
1241{
1242 if (info->imm.value == 0x3f000000)
1243 insert_field (self->fields[0], code, 0, 0);
1244 else
1245 insert_field (self->fields[0], code, 1, 0);
561a72d4 1246 return TRUE;
165d4950
RS
1247}
1248
1249/* Encode a single-bit immediate that selects between #0.0 and #1.0.
1250 The fields array specifies which field to use. */
561a72d4 1251bfd_boolean
165d4950
RS
1252aarch64_ins_sve_float_zero_one (const aarch64_operand *self,
1253 const aarch64_opnd_info *info,
1254 aarch64_insn *code,
561a72d4
TC
1255 const aarch64_inst *inst ATTRIBUTE_UNUSED,
1256 aarch64_operand_error *errors ATTRIBUTE_UNUSED)
165d4950
RS
1257{
1258 if (info->imm.value == 0)
1259 insert_field (self->fields[0], code, 0, 0);
1260 else
1261 insert_field (self->fields[0], code, 1, 0);
561a72d4 1262 return TRUE;
165d4950
RS
1263}
1264
a06ea964
NC
1265/* Miscellaneous encoding functions. */
1266
1267/* Encode size[0], i.e. bit 22, for
1268 e.g. FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
1269
1270static void
1271encode_asimd_fcvt (aarch64_inst *inst)
1272{
1273 aarch64_insn value;
1274 aarch64_field field = {0, 0};
1275 enum aarch64_opnd_qualifier qualifier;
1276
1277 switch (inst->opcode->op)
1278 {
1279 case OP_FCVTN:
1280 case OP_FCVTN2:
1281 /* FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
1282 qualifier = inst->operands[1].qualifier;
1283 break;
1284 case OP_FCVTL:
1285 case OP_FCVTL2:
1286 /* FCVTL<Q> <Vd>.<Ta>, <Vn>.<Tb>. */
1287 qualifier = inst->operands[0].qualifier;
1288 break;
1289 default:
1290 assert (0);
1291 }
1292 assert (qualifier == AARCH64_OPND_QLF_V_4S
1293 || qualifier == AARCH64_OPND_QLF_V_2D);
1294 value = (qualifier == AARCH64_OPND_QLF_V_4S) ? 0 : 1;
1295 gen_sub_field (FLD_size, 0, 1, &field);
1296 insert_field_2 (&field, &inst->value, value, 0);
1297}
1298
1299/* Encode size[0], i.e. bit 22, for
1300 e.g. FCVTXN <Vb><d>, <Va><n>. */
1301
1302static void
1303encode_asisd_fcvtxn (aarch64_inst *inst)
1304{
1305 aarch64_insn val = 1;
1306 aarch64_field field = {0, 0};
1307 assert (inst->operands[0].qualifier == AARCH64_OPND_QLF_S_S);
1308 gen_sub_field (FLD_size, 0, 1, &field);
1309 insert_field_2 (&field, &inst->value, val, 0);
1310}
1311
1312/* Encode the 'opc' field for e.g. FCVT <Dd>, <Sn>. */
1313static void
1314encode_fcvt (aarch64_inst *inst)
1315{
1316 aarch64_insn val;
1317 const aarch64_field field = {15, 2};
1318
1319 /* opc dstsize */
1320 switch (inst->operands[0].qualifier)
1321 {
1322 case AARCH64_OPND_QLF_S_S: val = 0; break;
1323 case AARCH64_OPND_QLF_S_D: val = 1; break;
1324 case AARCH64_OPND_QLF_S_H: val = 3; break;
1325 default: abort ();
1326 }
1327 insert_field_2 (&field, &inst->value, val, 0);
1328
1329 return;
1330}
1331
116b6019
RS
1332/* Return the index in qualifiers_list that INST is using. Should only
1333 be called once the qualifiers are known to be valid. */
1334
1335static int
1336aarch64_get_variant (struct aarch64_inst *inst)
1337{
1338 int i, nops, variant;
1339
1340 nops = aarch64_num_of_operands (inst->opcode);
1341 for (variant = 0; variant < AARCH64_MAX_QLF_SEQ_NUM; ++variant)
1342 {
1343 for (i = 0; i < nops; ++i)
1344 if (inst->opcode->qualifiers_list[variant][i]
1345 != inst->operands[i].qualifier)
1346 break;
1347 if (i == nops)
1348 return variant;
1349 }
1350 abort ();
1351}
1352
a06ea964
NC
1353/* Do miscellaneous encodings that are not common enough to be driven by
1354 flags. */
1355
1356static void
1357do_misc_encoding (aarch64_inst *inst)
1358{
c0890d26
RS
1359 unsigned int value;
1360
a06ea964
NC
1361 switch (inst->opcode->op)
1362 {
1363 case OP_FCVT:
1364 encode_fcvt (inst);
1365 break;
1366 case OP_FCVTN:
1367 case OP_FCVTN2:
1368 case OP_FCVTL:
1369 case OP_FCVTL2:
1370 encode_asimd_fcvt (inst);
1371 break;
1372 case OP_FCVTXN_S:
1373 encode_asisd_fcvtxn (inst);
1374 break;
c0890d26
RS
1375 case OP_MOV_P_P:
1376 case OP_MOVS_P_P:
1377 /* Copy Pn to Pm and Pg. */
1378 value = extract_field (FLD_SVE_Pn, inst->value, 0);
1379 insert_field (FLD_SVE_Pm, &inst->value, value, 0);
1380 insert_field (FLD_SVE_Pg4_10, &inst->value, value, 0);
1381 break;
1382 case OP_MOV_Z_P_Z:
1383 /* Copy Zd to Zm. */
1384 value = extract_field (FLD_SVE_Zd, inst->value, 0);
1385 insert_field (FLD_SVE_Zm_16, &inst->value, value, 0);
1386 break;
1387 case OP_MOV_Z_V:
1388 /* Fill in the zero immediate. */
582e12bf
RS
1389 insert_fields (&inst->value, 1 << aarch64_get_variant (inst), 0,
1390 2, FLD_imm5, FLD_SVE_tszh);
c0890d26
RS
1391 break;
1392 case OP_MOV_Z_Z:
1393 /* Copy Zn to Zm. */
1394 value = extract_field (FLD_SVE_Zn, inst->value, 0);
1395 insert_field (FLD_SVE_Zm_16, &inst->value, value, 0);
1396 break;
1397 case OP_MOV_Z_Zi:
1398 break;
1399 case OP_MOVM_P_P_P:
1400 /* Copy Pd to Pm. */
1401 value = extract_field (FLD_SVE_Pd, inst->value, 0);
1402 insert_field (FLD_SVE_Pm, &inst->value, value, 0);
1403 break;
1404 case OP_MOVZS_P_P_P:
1405 case OP_MOVZ_P_P_P:
1406 /* Copy Pn to Pm. */
1407 value = extract_field (FLD_SVE_Pn, inst->value, 0);
1408 insert_field (FLD_SVE_Pm, &inst->value, value, 0);
1409 break;
1410 case OP_NOTS_P_P_P_Z:
1411 case OP_NOT_P_P_P_Z:
1412 /* Copy Pg to Pm. */
1413 value = extract_field (FLD_SVE_Pg4_10, inst->value, 0);
1414 insert_field (FLD_SVE_Pm, &inst->value, value, 0);
1415 break;
a06ea964
NC
1416 default: break;
1417 }
1418}
1419
1420/* Encode the 'size' and 'Q' field for e.g. SHADD. */
1421static void
1422encode_sizeq (aarch64_inst *inst)
1423{
1424 aarch64_insn sizeq;
1425 enum aarch64_field_kind kind;
1426 int idx;
1427
1428 /* Get the index of the operand whose information we are going to use
1429 to encode the size and Q fields.
1430 This is deduced from the possible valid qualifier lists. */
1431 idx = aarch64_select_operand_for_sizeq_field_coding (inst->opcode);
1432 DEBUG_TRACE ("idx: %d; qualifier: %s", idx,
1433 aarch64_get_qualifier_name (inst->operands[idx].qualifier));
1434 sizeq = aarch64_get_qualifier_standard_value (inst->operands[idx].qualifier);
1435 /* Q */
1436 insert_field (FLD_Q, &inst->value, sizeq & 0x1, inst->opcode->mask);
1437 /* size */
1438 if (inst->opcode->iclass == asisdlse
1439 || inst->opcode->iclass == asisdlsep
1440 || inst->opcode->iclass == asisdlso
1441 || inst->opcode->iclass == asisdlsop)
1442 kind = FLD_vldst_size;
1443 else
1444 kind = FLD_size;
1445 insert_field (kind, &inst->value, (sizeq >> 1) & 0x3, inst->opcode->mask);
1446}
1447
1448/* Opcodes that have fields shared by multiple operands are usually flagged
1449 with flags. In this function, we detect such flags and use the
1450 information in one of the related operands to do the encoding. The 'one'
1451 operand is not any operand but one of the operands that has the enough
1452 information for such an encoding. */
1453
1454static void
1455do_special_encoding (struct aarch64_inst *inst)
1456{
1457 int idx;
4ad3b7ef 1458 aarch64_insn value = 0;
a06ea964
NC
1459
1460 DEBUG_TRACE ("enter with coding 0x%x", (uint32_t) inst->value);
1461
1462 /* Condition for truly conditional executed instructions, e.g. b.cond. */
1463 if (inst->opcode->flags & F_COND)
1464 {
1465 insert_field (FLD_cond2, &inst->value, inst->cond->value, 0);
1466 }
1467 if (inst->opcode->flags & F_SF)
1468 {
1469 idx = select_operand_for_sf_field_coding (inst->opcode);
1470 value = (inst->operands[idx].qualifier == AARCH64_OPND_QLF_X
1471 || inst->operands[idx].qualifier == AARCH64_OPND_QLF_SP)
1472 ? 1 : 0;
1473 insert_field (FLD_sf, &inst->value, value, 0);
1474 if (inst->opcode->flags & F_N)
1475 insert_field (FLD_N, &inst->value, value, inst->opcode->mask);
1476 }
ee804238
JW
1477 if (inst->opcode->flags & F_LSE_SZ)
1478 {
1479 idx = select_operand_for_sf_field_coding (inst->opcode);
1480 value = (inst->operands[idx].qualifier == AARCH64_OPND_QLF_X
1481 || inst->operands[idx].qualifier == AARCH64_OPND_QLF_SP)
1482 ? 1 : 0;
1483 insert_field (FLD_lse_sz, &inst->value, value, 0);
1484 }
a06ea964
NC
1485 if (inst->opcode->flags & F_SIZEQ)
1486 encode_sizeq (inst);
1487 if (inst->opcode->flags & F_FPTYPE)
1488 {
1489 idx = select_operand_for_fptype_field_coding (inst->opcode);
1490 switch (inst->operands[idx].qualifier)
1491 {
1492 case AARCH64_OPND_QLF_S_S: value = 0; break;
1493 case AARCH64_OPND_QLF_S_D: value = 1; break;
1494 case AARCH64_OPND_QLF_S_H: value = 3; break;
1495 default: assert (0);
1496 }
1497 insert_field (FLD_type, &inst->value, value, 0);
1498 }
1499 if (inst->opcode->flags & F_SSIZE)
1500 {
1501 enum aarch64_opnd_qualifier qualifier;
1502 idx = select_operand_for_scalar_size_field_coding (inst->opcode);
1503 qualifier = inst->operands[idx].qualifier;
1504 assert (qualifier >= AARCH64_OPND_QLF_S_B
1505 && qualifier <= AARCH64_OPND_QLF_S_Q);
1506 value = aarch64_get_qualifier_standard_value (qualifier);
1507 insert_field (FLD_size, &inst->value, value, inst->opcode->mask);
1508 }
1509 if (inst->opcode->flags & F_T)
1510 {
1511 int num; /* num of consecutive '0's on the right side of imm5<3:0>. */
1512 aarch64_field field = {0, 0};
1513 enum aarch64_opnd_qualifier qualifier;
1514
1515 idx = 0;
1516 qualifier = inst->operands[idx].qualifier;
1517 assert (aarch64_get_operand_class (inst->opcode->operands[0])
1518 == AARCH64_OPND_CLASS_SIMD_REG
1519 && qualifier >= AARCH64_OPND_QLF_V_8B
1520 && qualifier <= AARCH64_OPND_QLF_V_2D);
1521 /* imm5<3:0> q <t>
1522 0000 x reserved
1523 xxx1 0 8b
1524 xxx1 1 16b
1525 xx10 0 4h
1526 xx10 1 8h
1527 x100 0 2s
1528 x100 1 4s
1529 1000 0 reserved
1530 1000 1 2d */
1531 value = aarch64_get_qualifier_standard_value (qualifier);
1532 insert_field (FLD_Q, &inst->value, value & 0x1, inst->opcode->mask);
1533 num = (int) value >> 1;
1534 assert (num >= 0 && num <= 3);
1535 gen_sub_field (FLD_imm5, 0, num + 1, &field);
1536 insert_field_2 (&field, &inst->value, 1 << num, inst->opcode->mask);
1537 }
1538 if (inst->opcode->flags & F_GPRSIZE_IN_Q)
1539 {
1540 /* Use Rt to encode in the case of e.g.
1541 STXP <Ws>, <Xt1>, <Xt2>, [<Xn|SP>{,#0}]. */
1542 enum aarch64_opnd_qualifier qualifier;
1543 idx = aarch64_operand_index (inst->opcode->operands, AARCH64_OPND_Rt);
1544 if (idx == -1)
1545 /* Otherwise use the result operand, which has to be a integer
1546 register. */
1547 idx = 0;
1548 assert (idx == 0 || idx == 1);
1549 assert (aarch64_get_operand_class (inst->opcode->operands[idx])
1550 == AARCH64_OPND_CLASS_INT_REG);
1551 qualifier = inst->operands[idx].qualifier;
1552 insert_field (FLD_Q, &inst->value,
1553 aarch64_get_qualifier_standard_value (qualifier), 0);
1554 }
1555 if (inst->opcode->flags & F_LDS_SIZE)
1556 {
1557 /* e.g. LDRSB <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
1558 enum aarch64_opnd_qualifier qualifier;
1559 aarch64_field field = {0, 0};
1560 assert (aarch64_get_operand_class (inst->opcode->operands[0])
1561 == AARCH64_OPND_CLASS_INT_REG);
1562 gen_sub_field (FLD_opc, 0, 1, &field);
1563 qualifier = inst->operands[0].qualifier;
1564 insert_field_2 (&field, &inst->value,
1565 1 - aarch64_get_qualifier_standard_value (qualifier), 0);
1566 }
1567 /* Miscellaneous encoding as the last step. */
1568 if (inst->opcode->flags & F_MISC)
1569 do_misc_encoding (inst);
1570
1571 DEBUG_TRACE ("exit with coding 0x%x", (uint32_t) inst->value);
1572}
1573
116b6019
RS
1574/* Some instructions (including all SVE ones) use the instruction class
1575 to describe how a qualifiers_list index is represented in the instruction
1576 encoding. If INST is such an instruction, encode the chosen qualifier
1577 variant. */
1578
1579static void
1580aarch64_encode_variant_using_iclass (struct aarch64_inst *inst)
1581{
1582 switch (inst->opcode->iclass)
1583 {
1584 case sve_cpy:
1585 insert_fields (&inst->value, aarch64_get_variant (inst),
1586 0, 2, FLD_SVE_M_14, FLD_size);
1587 break;
1588
1589 case sve_index:
1590 case sve_shift_pred:
1591 case sve_shift_unpred:
1592 /* For indices and shift amounts, the variant is encoded as
1593 part of the immediate. */
1594 break;
1595
1596 case sve_limm:
1597 /* For sve_limm, the .B, .H, and .S forms are just a convenience
1598 and depend on the immediate. They don't have a separate
1599 encoding. */
1600 break;
1601
1602 case sve_misc:
1603 /* sve_misc instructions have only a single variant. */
1604 break;
1605
1606 case sve_movprfx:
1607 insert_fields (&inst->value, aarch64_get_variant (inst),
1608 0, 2, FLD_SVE_M_16, FLD_size);
1609 break;
1610
1611 case sve_pred_zm:
1612 insert_field (FLD_SVE_M_4, &inst->value, aarch64_get_variant (inst), 0);
1613 break;
1614
1615 case sve_size_bhs:
1616 case sve_size_bhsd:
1617 insert_field (FLD_size, &inst->value, aarch64_get_variant (inst), 0);
1618 break;
1619
1620 case sve_size_hsd:
1621 insert_field (FLD_size, &inst->value, aarch64_get_variant (inst) + 1, 0);
1622 break;
1623
1624 case sve_size_sd:
1625 insert_field (FLD_SVE_sz, &inst->value, aarch64_get_variant (inst), 0);
1626 break;
1627
1628 default:
1629 break;
1630 }
1631}
1632
a06ea964
NC
1633/* Converters converting an alias opcode instruction to its real form. */
1634
1635/* ROR <Wd>, <Ws>, #<shift>
1636 is equivalent to:
1637 EXTR <Wd>, <Ws>, <Ws>, #<shift>. */
1638static void
1639convert_ror_to_extr (aarch64_inst *inst)
1640{
1641 copy_operand_info (inst, 3, 2);
1642 copy_operand_info (inst, 2, 1);
1643}
1644
e30181a5
YZ
1645/* UXTL<Q> <Vd>.<Ta>, <Vn>.<Tb>
1646 is equivalent to:
1647 USHLL<Q> <Vd>.<Ta>, <Vn>.<Tb>, #0. */
1648static void
1649convert_xtl_to_shll (aarch64_inst *inst)
1650{
1651 inst->operands[2].qualifier = inst->operands[1].qualifier;
1652 inst->operands[2].imm.value = 0;
1653}
1654
a06ea964
NC
1655/* Convert
1656 LSR <Xd>, <Xn>, #<shift>
1657 to
1658 UBFM <Xd>, <Xn>, #<shift>, #63. */
1659static void
1660convert_sr_to_bfm (aarch64_inst *inst)
1661{
1662 inst->operands[3].imm.value =
1663 inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 31 : 63;
1664}
1665
1666/* Convert MOV to ORR. */
1667static void
1668convert_mov_to_orr (aarch64_inst *inst)
1669{
1670 /* MOV <Vd>.<T>, <Vn>.<T>
1671 is equivalent to:
1672 ORR <Vd>.<T>, <Vn>.<T>, <Vn>.<T>. */
1673 copy_operand_info (inst, 2, 1);
1674}
1675
1676/* When <imms> >= <immr>, the instruction written:
1677 SBFX <Xd>, <Xn>, #<lsb>, #<width>
1678 is equivalent to:
1679 SBFM <Xd>, <Xn>, #<lsb>, #(<lsb>+<width>-1). */
1680
1681static void
1682convert_bfx_to_bfm (aarch64_inst *inst)
1683{
1684 int64_t lsb, width;
1685
1686 /* Convert the operand. */
1687 lsb = inst->operands[2].imm.value;
1688 width = inst->operands[3].imm.value;
1689 inst->operands[2].imm.value = lsb;
1690 inst->operands[3].imm.value = lsb + width - 1;
1691}
1692
1693/* When <imms> < <immr>, the instruction written:
1694 SBFIZ <Xd>, <Xn>, #<lsb>, #<width>
1695 is equivalent to:
1696 SBFM <Xd>, <Xn>, #((64-<lsb>)&0x3f), #(<width>-1). */
1697
1698static void
1699convert_bfi_to_bfm (aarch64_inst *inst)
1700{
1701 int64_t lsb, width;
1702
1703 /* Convert the operand. */
1704 lsb = inst->operands[2].imm.value;
1705 width = inst->operands[3].imm.value;
1706 if (inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31)
1707 {
1708 inst->operands[2].imm.value = (32 - lsb) & 0x1f;
1709 inst->operands[3].imm.value = width - 1;
1710 }
1711 else
1712 {
1713 inst->operands[2].imm.value = (64 - lsb) & 0x3f;
1714 inst->operands[3].imm.value = width - 1;
1715 }
1716}
1717
d685192a
MW
1718/* The instruction written:
1719 BFC <Xd>, #<lsb>, #<width>
1720 is equivalent to:
1721 BFM <Xd>, XZR, #((64-<lsb>)&0x3f), #(<width>-1). */
1722
1723static void
1724convert_bfc_to_bfm (aarch64_inst *inst)
1725{
1726 int64_t lsb, width;
1727
1728 /* Insert XZR. */
1729 copy_operand_info (inst, 3, 2);
1730 copy_operand_info (inst, 2, 1);
11648de5 1731 copy_operand_info (inst, 1, 0);
d685192a
MW
1732 inst->operands[1].reg.regno = 0x1f;
1733
11648de5 1734 /* Convert the immediate operand. */
d685192a
MW
1735 lsb = inst->operands[2].imm.value;
1736 width = inst->operands[3].imm.value;
1737 if (inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31)
1738 {
1739 inst->operands[2].imm.value = (32 - lsb) & 0x1f;
1740 inst->operands[3].imm.value = width - 1;
1741 }
1742 else
1743 {
1744 inst->operands[2].imm.value = (64 - lsb) & 0x3f;
1745 inst->operands[3].imm.value = width - 1;
1746 }
1747}
1748
a06ea964
NC
1749/* The instruction written:
1750 LSL <Xd>, <Xn>, #<shift>
1751 is equivalent to:
1752 UBFM <Xd>, <Xn>, #((64-<shift>)&0x3f), #(63-<shift>). */
1753
1754static void
1755convert_lsl_to_ubfm (aarch64_inst *inst)
1756{
1757 int64_t shift = inst->operands[2].imm.value;
1758
1759 if (inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31)
1760 {
1761 inst->operands[2].imm.value = (32 - shift) & 0x1f;
1762 inst->operands[3].imm.value = 31 - shift;
1763 }
1764 else
1765 {
1766 inst->operands[2].imm.value = (64 - shift) & 0x3f;
1767 inst->operands[3].imm.value = 63 - shift;
1768 }
1769}
1770
1771/* CINC <Wd>, <Wn>, <cond>
1772 is equivalent to:
1773 CSINC <Wd>, <Wn>, <Wn>, invert(<cond>). */
1774
1775static void
1776convert_to_csel (aarch64_inst *inst)
1777{
1778 copy_operand_info (inst, 3, 2);
1779 copy_operand_info (inst, 2, 1);
1780 inst->operands[3].cond = get_inverted_cond (inst->operands[3].cond);
1781}
1782
1783/* CSET <Wd>, <cond>
1784 is equivalent to:
1785 CSINC <Wd>, WZR, WZR, invert(<cond>). */
1786
1787static void
1788convert_cset_to_csinc (aarch64_inst *inst)
1789{
1790 copy_operand_info (inst, 3, 1);
1791 copy_operand_info (inst, 2, 0);
1792 copy_operand_info (inst, 1, 0);
1793 inst->operands[1].reg.regno = 0x1f;
1794 inst->operands[2].reg.regno = 0x1f;
1795 inst->operands[3].cond = get_inverted_cond (inst->operands[3].cond);
1796}
1797
1798/* MOV <Wd>, #<imm>
1799 is equivalent to:
1800 MOVZ <Wd>, #<imm16>, LSL #<shift>. */
1801
1802static void
1803convert_mov_to_movewide (aarch64_inst *inst)
1804{
1805 int is32;
1806 uint32_t shift_amount;
1807 uint64_t value;
1808
1809 switch (inst->opcode->op)
1810 {
1811 case OP_MOV_IMM_WIDE:
1812 value = inst->operands[1].imm.value;
1813 break;
1814 case OP_MOV_IMM_WIDEN:
1815 value = ~inst->operands[1].imm.value;
1816 break;
1817 default:
1818 assert (0);
1819 }
1820 inst->operands[1].type = AARCH64_OPND_HALF;
1821 is32 = inst->operands[0].qualifier == AARCH64_OPND_QLF_W;
062f38fa
RE
1822 if (! aarch64_wide_constant_p (value, is32, &shift_amount))
1823 /* The constraint check should have guaranteed this wouldn't happen. */
1824 assert (0);
a06ea964
NC
1825 value >>= shift_amount;
1826 value &= 0xffff;
1827 inst->operands[1].imm.value = value;
1828 inst->operands[1].shifter.kind = AARCH64_MOD_LSL;
1829 inst->operands[1].shifter.amount = shift_amount;
1830}
1831
1832/* MOV <Wd>, #<imm>
1833 is equivalent to:
1834 ORR <Wd>, WZR, #<imm>. */
1835
1836static void
1837convert_mov_to_movebitmask (aarch64_inst *inst)
1838{
1839 copy_operand_info (inst, 2, 1);
1840 inst->operands[1].reg.regno = 0x1f;
1841 inst->operands[1].skip = 0;
1842}
1843
1844/* Some alias opcodes are assembled by being converted to their real-form. */
1845
1846static void
1847convert_to_real (aarch64_inst *inst, const aarch64_opcode *real)
1848{
1849 const aarch64_opcode *alias = inst->opcode;
1850
1851 if ((alias->flags & F_CONV) == 0)
1852 goto convert_to_real_return;
1853
1854 switch (alias->op)
1855 {
1856 case OP_ASR_IMM:
1857 case OP_LSR_IMM:
1858 convert_sr_to_bfm (inst);
1859 break;
1860 case OP_LSL_IMM:
1861 convert_lsl_to_ubfm (inst);
1862 break;
1863 case OP_CINC:
1864 case OP_CINV:
1865 case OP_CNEG:
1866 convert_to_csel (inst);
1867 break;
1868 case OP_CSET:
1869 case OP_CSETM:
1870 convert_cset_to_csinc (inst);
1871 break;
1872 case OP_UBFX:
1873 case OP_BFXIL:
1874 case OP_SBFX:
1875 convert_bfx_to_bfm (inst);
1876 break;
1877 case OP_SBFIZ:
1878 case OP_BFI:
1879 case OP_UBFIZ:
1880 convert_bfi_to_bfm (inst);
1881 break;
d685192a
MW
1882 case OP_BFC:
1883 convert_bfc_to_bfm (inst);
1884 break;
a06ea964
NC
1885 case OP_MOV_V:
1886 convert_mov_to_orr (inst);
1887 break;
1888 case OP_MOV_IMM_WIDE:
1889 case OP_MOV_IMM_WIDEN:
1890 convert_mov_to_movewide (inst);
1891 break;
1892 case OP_MOV_IMM_LOG:
1893 convert_mov_to_movebitmask (inst);
1894 break;
1895 case OP_ROR_IMM:
1896 convert_ror_to_extr (inst);
1897 break;
e30181a5
YZ
1898 case OP_SXTL:
1899 case OP_SXTL2:
1900 case OP_UXTL:
1901 case OP_UXTL2:
1902 convert_xtl_to_shll (inst);
1903 break;
a06ea964
NC
1904 default:
1905 break;
1906 }
1907
1908convert_to_real_return:
1909 aarch64_replace_opcode (inst, real);
1910}
1911
1912/* Encode *INST_ORI of the opcode code OPCODE.
1913 Return the encoded result in *CODE and if QLF_SEQ is not NULL, return the
1914 matched operand qualifier sequence in *QLF_SEQ. */
1915
561a72d4 1916bfd_boolean
a06ea964
NC
1917aarch64_opcode_encode (const aarch64_opcode *opcode,
1918 const aarch64_inst *inst_ori, aarch64_insn *code,
1919 aarch64_opnd_qualifier_t *qlf_seq,
1920 aarch64_operand_error *mismatch_detail)
1921{
1922 int i;
1923 const aarch64_opcode *aliased;
1924 aarch64_inst copy, *inst;
1925
1926 DEBUG_TRACE ("enter with %s", opcode->name);
1927
1928 /* Create a copy of *INST_ORI, so that we can do any change we want. */
1929 copy = *inst_ori;
1930 inst = &copy;
1931
1932 assert (inst->opcode == NULL || inst->opcode == opcode);
1933 if (inst->opcode == NULL)
1934 inst->opcode = opcode;
1935
1936 /* Constrain the operands.
1937 After passing this, the encoding is guaranteed to succeed. */
1938 if (aarch64_match_operands_constraint (inst, mismatch_detail) == 0)
1939 {
1940 DEBUG_TRACE ("FAIL since operand constraint not met");
1941 return 0;
1942 }
1943
1944 /* Get the base value.
1945 Note: this has to be before the aliasing handling below in order to
1946 get the base value from the alias opcode before we move on to the
1947 aliased opcode for encoding. */
1948 inst->value = opcode->opcode;
1949
1950 /* No need to do anything else if the opcode does not have any operand. */
1951 if (aarch64_num_of_operands (opcode) == 0)
1952 goto encoding_exit;
1953
1954 /* Assign operand indexes and check types. Also put the matched
1955 operand qualifiers in *QLF_SEQ to return. */
1956 for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
1957 {
1958 assert (opcode->operands[i] == inst->operands[i].type);
1959 inst->operands[i].idx = i;
1960 if (qlf_seq != NULL)
1961 *qlf_seq = inst->operands[i].qualifier;
1962 }
1963
1964 aliased = aarch64_find_real_opcode (opcode);
1965 /* If the opcode is an alias and it does not ask for direct encoding by
1966 itself, the instruction will be transformed to the form of real opcode
1967 and the encoding will be carried out using the rules for the aliased
1968 opcode. */
1969 if (aliased != NULL && (opcode->flags & F_CONV))
1970 {
1971 DEBUG_TRACE ("real opcode '%s' has been found for the alias %s",
1972 aliased->name, opcode->name);
1973 /* Convert the operands to the form of the real opcode. */
1974 convert_to_real (inst, aliased);
1975 opcode = aliased;
1976 }
1977
1978 aarch64_opnd_info *info = inst->operands;
1979
1980 /* Call the inserter of each operand. */
1981 for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i, ++info)
1982 {
1983 const aarch64_operand *opnd;
1984 enum aarch64_opnd type = opcode->operands[i];
1985 if (type == AARCH64_OPND_NIL)
1986 break;
1987 if (info->skip)
1988 {
1989 DEBUG_TRACE ("skip the incomplete operand %d", i);
1990 continue;
1991 }
1992 opnd = &aarch64_operands[type];
561a72d4
TC
1993 if (operand_has_inserter (opnd)
1994 && !aarch64_insert_operand (opnd, info, &inst->value, inst,
1995 mismatch_detail))
1996 return FALSE;
a06ea964
NC
1997 }
1998
1999 /* Call opcode encoders indicated by flags. */
2000 if (opcode_has_special_coder (opcode))
2001 do_special_encoding (inst);
2002
116b6019
RS
2003 /* Possibly use the instruction class to encode the chosen qualifier
2004 variant. */
2005 aarch64_encode_variant_using_iclass (inst);
2006
a06ea964
NC
2007encoding_exit:
2008 DEBUG_TRACE ("exit with %s", opcode->name);
2009
2010 *code = inst->value;
2011
561a72d4 2012 return TRUE;
a06ea964 2013}
This page took 0.352516 seconds and 4 git commands to generate.