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