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