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