1 /* aarch64-asm.c -- AArch64 assembler support.
2 Copyright (C) 2012-2017 Free Software Foundation, Inc.
3 Contributed by ARM Ltd.
5 This file is part of the GNU opcodes library.
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)
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.
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/>. */
23 #include "libiberty.h"
24 #include "aarch64-asm.h"
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.
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. */
39 insert_fields (aarch64_insn
*code
, aarch64_insn value
, aarch64_insn mask
, ...)
42 const aarch64_field
*field
;
43 enum aarch64_field_kind kind
;
47 num
= va_arg (va
, uint32_t);
51 kind
= va_arg (va
, enum aarch64_field_kind
);
52 field
= &fields
[kind
];
53 insert_field (kind
, code
, value
, mask
);
54 value
>>= field
->width
;
59 /* Insert a raw field value VALUE into all fields in SELF->fields.
60 The least significant bit goes in the final field. */
63 insert_all_fields (const aarch64_operand
*self
, aarch64_insn
*code
,
67 enum aarch64_field_kind kind
;
69 for (i
= ARRAY_SIZE (self
->fields
); i
-- > 0; )
70 if (self
->fields
[i
] != FLD_NIL
)
72 kind
= self
->fields
[i
];
73 insert_field (kind
, code
, value
, 0);
74 value
>>= fields
[kind
].width
;
78 /* Operand inserters. */
80 /* Insert register number. */
82 aarch64_ins_regno (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
84 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
86 insert_field (self
->fields
[0], code
, info
->reg
.regno
, 0);
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>]. */
94 aarch64_ins_reglane (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
95 aarch64_insn
*code
, const aarch64_inst
*inst
)
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
)
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
)
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);
113 /* index and type for e.g. DUP <V><d>, <Vn>.<T>[<index>].
120 aarch64_insn value
= ((info
->reglane
.index
<< 1) | 1) << pos
;
121 insert_field (FLD_imm5
, code
, value
, 0);
124 else if (inst
->opcode
->iclass
== dotproduct
)
126 unsigned reglane_index
= info
->reglane
.index
;
127 switch (info
->qualifier
)
129 case AARCH64_OPND_QLF_S_B
:
131 assert (reglane_index
< 4);
132 insert_fields (code
, reglane_index
, 0, 2, FLD_L
, FLD_H
);
140 /* index for e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
141 or SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]. */
142 unsigned reglane_index
= info
->reglane
.index
;
144 if (inst
->opcode
->op
== OP_FCMLA_ELEM
)
145 /* Complex operand takes two elements. */
148 switch (info
->qualifier
)
150 case AARCH64_OPND_QLF_S_H
:
152 assert (reglane_index
< 8);
153 insert_fields (code
, reglane_index
, 0, 3, FLD_M
, FLD_L
, FLD_H
);
155 case AARCH64_OPND_QLF_S_S
:
157 assert (reglane_index
< 4);
158 insert_fields (code
, reglane_index
, 0, 2, FLD_L
, FLD_H
);
160 case AARCH64_OPND_QLF_S_D
:
162 assert (reglane_index
< 2);
163 insert_field (FLD_H
, code
, reglane_index
, 0);
172 /* Insert regno and len field of a register list operand, e.g. Vn in TBL. */
174 aarch64_ins_reglist (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
176 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
179 insert_field (self
->fields
[0], code
, info
->reglist
.first_regno
, 0);
181 insert_field (FLD_len
, code
, info
->reglist
.num_regs
- 1, 0);
185 /* Insert Rt and opcode fields for a register list operand, e.g. Vt
186 in AdvSIMD load/store instructions. */
188 aarch64_ins_ldst_reglist (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
189 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
190 const aarch64_inst
*inst
)
192 aarch64_insn value
= 0;
193 /* Number of elements in each structure to be loaded/stored. */
194 unsigned num
= get_opcode_dependent_value (inst
->opcode
);
197 insert_field (FLD_Rt
, code
, info
->reglist
.first_regno
, 0);
202 switch (info
->reglist
.num_regs
)
204 case 1: value
= 0x7; break;
205 case 2: value
= 0xa; break;
206 case 3: value
= 0x6; break;
207 case 4: value
= 0x2; break;
212 value
= info
->reglist
.num_regs
== 4 ? 0x3 : 0x8;
223 insert_field (FLD_opcode
, code
, value
, 0);
228 /* Insert Rt and S fields for a register list operand, e.g. Vt in AdvSIMD load
229 single structure to all lanes instructions. */
231 aarch64_ins_ldst_reglist_r (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
232 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
233 const aarch64_inst
*inst
)
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;
241 insert_field (FLD_Rt
, code
, info
->reglist
.first_regno
, 0);
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"
247 value
= (aarch64_insn
) 1;
248 insert_field (FLD_S
, code
, value
, 0);
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. */
256 aarch64_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
)
260 aarch64_field field
= {0, 0};
261 aarch64_insn QSsize
= 0; /* fields Q:S:size. */
262 aarch64_insn opcodeh2
= 0; /* opcode<2:1> */
264 assert (info
->reglist
.has_index
);
267 insert_field (FLD_Rt
, code
, info
->reglist
.first_regno
, 0);
268 /* Encode the index, opcode<2:1> and size. */
269 switch (info
->qualifier
)
271 case AARCH64_OPND_QLF_S_B
:
272 /* Index encoded in "Q:S:size". */
273 QSsize
= info
->reglist
.index
;
276 case AARCH64_OPND_QLF_S_H
:
277 /* Index encoded in "Q:S:size<1>". */
278 QSsize
= info
->reglist
.index
<< 1;
281 case AARCH64_OPND_QLF_S_S
:
282 /* Index encoded in "Q:S". */
283 QSsize
= info
->reglist
.index
<< 2;
286 case AARCH64_OPND_QLF_S_D
:
287 /* Index encoded in "Q". */
288 QSsize
= info
->reglist
.index
<< 3 | 0x1;
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);
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>. */
305 aarch64_ins_advsimd_imm_shift (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
306 const aarch64_opnd_info
*info
,
307 aarch64_insn
*code
, const aarch64_inst
*inst
)
309 unsigned val
= aarch64_get_qualifier_standard_value (info
->qualifier
);
312 if (inst
->opcode
->iclass
== asimdshf
)
316 0000 x SEE AdvSIMD modified immediate
325 Q
= (val
& 0x1) ? 1 : 0;
326 insert_field (FLD_Q
, code
, Q
, inst
->opcode
->mask
);
330 assert (info
->type
== AARCH64_OPND_IMM_VLSR
331 || info
->type
== AARCH64_OPND_IMM_VLSL
);
333 if (info
->type
== AARCH64_OPND_IMM_VLSR
)
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
;
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
);
356 /* Insert fields for e.g. the immediate operands in
357 BFM <Wd>, <Wn>, #<immr>, #<imms>. */
359 aarch64_ins_imm (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
361 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
365 imm
= info
->imm
.value
;
366 if (operand_need_shift_by_two (self
))
368 insert_all_fields (self
, code
, imm
);
372 /* Insert immediate and its shift amount for e.g. the last operand in
373 MOVZ <Wd>, #<imm16>{, LSL #<shift>}. */
375 aarch64_ins_imm_half (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
376 aarch64_insn
*code
, const aarch64_inst
*inst
)
379 aarch64_ins_imm (self
, info
, code
, inst
);
381 insert_field (FLD_hw
, code
, info
->shifter
.amount
>> 4, 0);
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>}. */
388 aarch64_ins_advsimd_imm_modified (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
389 const aarch64_opnd_info
*info
,
391 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
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};
399 /* a:b:c:d:e:f:g:h */
400 if (!info
->imm
.is_fp
&& aarch64_get_qualifier_esize (opnd0_qualifier
) == 8)
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);
410 insert_fields (code
, imm
, 0, 2, FLD_defgh
, FLD_abc
);
412 if (kind
== AARCH64_MOD_NONE
)
415 /* shift amount partially in cmode */
416 assert (kind
== AARCH64_MOD_LSL
|| kind
== AARCH64_MOD_MSL
);
417 if (kind
== AARCH64_MOD_LSL
)
419 /* AARCH64_MOD_LSL: shift zeros. */
420 int esize
= aarch64_get_qualifier_esize (opnd0_qualifier
);
421 assert (esize
== 4 || esize
== 2 || esize
== 1);
422 /* For 8-bit move immediate, the optional LSL #0 does not require
428 gen_sub_field (FLD_cmode
, 1, 2, &field
); /* per word */
430 gen_sub_field (FLD_cmode
, 1, 1, &field
); /* per halfword */
434 /* AARCH64_MOD_MSL: shift ones. */
436 gen_sub_field (FLD_cmode
, 0, 1, &field
); /* per word */
438 insert_field_2 (&field
, code
, amount
, 0);
443 /* Insert fields for an 8-bit floating-point immediate. */
445 aarch64_ins_fpimm (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
447 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
449 insert_all_fields (self
, code
, info
->imm
.value
);
453 /* Insert 1-bit rotation immediate (#90 or #270). */
455 aarch64_ins_imm_rotate1 (const aarch64_operand
*self
,
456 const aarch64_opnd_info
*info
,
457 aarch64_insn
*code
, const aarch64_inst
*inst
)
459 uint64_t rot
= (info
->imm
.value
- 90) / 180;
461 insert_field (self
->fields
[0], code
, rot
, inst
->opcode
->mask
);
465 /* Insert 2-bit rotation immediate (#0, #90, #180 or #270). */
467 aarch64_ins_imm_rotate2 (const aarch64_operand
*self
,
468 const aarch64_opnd_info
*info
,
469 aarch64_insn
*code
, const aarch64_inst
*inst
)
471 uint64_t rot
= info
->imm
.value
/ 90;
473 insert_field (self
->fields
[0], code
, rot
, inst
->opcode
->mask
);
477 /* Insert #<fbits> for the immediate operand in fp fix-point instructions,
478 e.g. SCVTF <Dd>, <Wn>, #<fbits>. */
480 aarch64_ins_fbits (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
482 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
484 insert_field (self
->fields
[0], code
, 64 - info
->imm
.value
, 0);
488 /* Insert arithmetic immediate for e.g. the last operand in
489 SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}. */
491 aarch64_ins_aimm (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
492 aarch64_insn
*code
, const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
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);
502 /* Common routine shared by aarch64_ins{,_inv}_limm. INVERT_P says whether
503 the operand should be inverted before encoding. */
505 aarch64_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
)
510 uint64_t imm
= info
->imm
.value
;
511 int esize
= aarch64_get_qualifier_esize (inst
->operands
[0].qualifier
);
515 /* The constraint check should have guaranteed this wouldn't happen. */
516 assert (aarch64_logical_immediate_p (imm
, esize
, &value
));
518 insert_fields (code
, value
, 0, 3, self
->fields
[2], self
->fields
[1],
523 /* Insert logical/bitmask immediate for e.g. the last operand in
524 ORR <Wd|WSP>, <Wn>, #<imm>. */
526 aarch64_ins_limm (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
527 aarch64_insn
*code
, const aarch64_inst
*inst
)
529 return aarch64_ins_limm_1 (self
, info
, code
, inst
,
530 inst
->opcode
->op
== OP_BIC
);
533 /* Insert a logical/bitmask immediate for the BIC alias of AND (etc.). */
535 aarch64_ins_inv_limm (const aarch64_operand
*self
,
536 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
537 const aarch64_inst
*inst
)
539 return aarch64_ins_limm_1 (self
, info
, code
, inst
, TRUE
);
542 /* Encode Ft for e.g. STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]
543 or LDP <Qt1>, <Qt2>, [<Xn|SP>], #<imm>. */
545 aarch64_ins_ft (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
546 aarch64_insn
*code
, const aarch64_inst
*inst
)
548 aarch64_insn value
= 0;
550 assert (info
->idx
== 0);
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
)
560 switch (info
->qualifier
)
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;
567 insert_field (FLD_ldst_size
, code
, value
, 0);
572 value
= aarch64_get_qualifier_standard_value (info
->qualifier
);
573 insert_fields (code
, value
, 0, 2, FLD_ldst_size
, FLD_opc1
);
579 /* Encode the address operand for e.g. STXRB <Ws>, <Wt>, [<Xn|SP>{,#0}]. */
581 aarch64_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
)
586 insert_field (FLD_Rn
, code
, info
->addr
.base_regno
, 0);
590 /* Encode the address operand for e.g.
591 STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
593 aarch64_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
)
598 enum aarch64_modifier_kind kind
= info
->shifter
.kind
;
601 insert_field (FLD_Rn
, code
, info
->addr
.base_regno
, 0);
603 insert_field (FLD_Rm
, code
, info
->addr
.offset
.regno
, 0);
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);
609 if (info
->qualifier
!= AARCH64_OPND_QLF_S_B
)
610 S
= info
->shifter
.amount
!= 0;
612 /* For STR <Bt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}},
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);
623 /* Encode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>, #<simm>]!. */
625 aarch64_ins_addr_simm (const aarch64_operand
*self
,
626 const aarch64_opnd_info
*info
,
628 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
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
)
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);
655 /* Encode the address operand for e.g. LDRAA <Xt>, [<Xn|SP>{, #<simm>}]. */
657 aarch64_ins_addr_simm10 (const aarch64_operand
*self
,
658 const aarch64_opnd_info
*info
,
660 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
665 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
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);
671 if (info
->addr
.writeback
)
673 assert (info
->addr
.preind
== 1 && info
->addr
.postind
== 0);
674 insert_field (self
->fields
[3], code
, 1, 0);
679 /* Encode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>{, #<pimm>}]. */
681 aarch64_ins_addr_uimm12 (const aarch64_operand
*self
,
682 const aarch64_opnd_info
*info
,
684 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
686 int shift
= get_logsz (aarch64_get_qualifier_esize (info
->qualifier
));
689 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
691 insert_field (self
->fields
[1], code
,info
->addr
.offset
.imm
>> shift
, 0);
695 /* Encode the address operand for e.g.
696 LD1 {<Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>}, [<Xn|SP>], <Xm|#<amount>>. */
698 aarch64_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
)
703 insert_field (FLD_Rn
, code
, info
->addr
.base_regno
, 0);
705 if (info
->addr
.offset
.is_reg
)
706 insert_field (FLD_Rm
, code
, info
->addr
.offset
.regno
, 0);
708 insert_field (FLD_Rm
, code
, 0x1f, 0);
712 /* Encode the condition operand for e.g. CSEL <Xd>, <Xn>, <Xm>, <cond>. */
714 aarch64_ins_cond (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
715 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
716 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
719 insert_field (FLD_cond
, code
, info
->cond
->value
, 0);
723 /* Encode the system register operand for e.g. MRS <Xt>, <systemreg>. */
725 aarch64_ins_sysreg (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
726 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
727 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
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
);
735 /* Encode the PSTATE field operand for e.g. MSR <pstatefield>, #<imm>. */
737 aarch64_ins_pstatefield (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
738 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
739 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
742 insert_fields (code
, info
->pstatefield
, inst
->opcode
->mask
, 2,
747 /* Encode the system instruction op operand for e.g. AT <at_op>, <Xt>. */
749 aarch64_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
)
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
);
759 /* Encode the memory barrier option operand for e.g. DMB <option>|#<imm>. */
762 aarch64_ins_barrier (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
763 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
764 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
767 insert_field (FLD_CRm
, code
, info
->barrier
->value
, 0);
771 /* Encode the prefetch operation option operand for e.g.
772 PRFM <prfop>, [<Xn|SP>{, #<pimm>}]. */
775 aarch64_ins_prfop (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
776 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
777 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
780 insert_field (FLD_Rt
, code
, info
->prfop
->value
, 0);
784 /* Encode the hint number for instructions that alias HINT but take an
788 aarch64_ins_hint (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
789 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
790 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
793 insert_fields (code
, info
->hint_option
->value
, 0, 2, FLD_op2
, FLD_CRm
);
797 /* Encode the extended register operand for e.g.
798 STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
800 aarch64_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
)
804 enum aarch64_modifier_kind kind
;
807 insert_field (FLD_Rm
, code
, info
->reg
.regno
, 0);
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);
815 insert_field (FLD_imm3
, code
, info
->shifter
.amount
, 0);
820 /* Encode the shifted register operand for e.g.
821 SUBS <Xd>, <Xn>, <Xm> {, <shift> #<amount>}. */
823 aarch64_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
)
828 insert_field (FLD_Rm
, code
, info
->reg
.regno
, 0);
830 insert_field (FLD_shift
, code
,
831 aarch64_get_operand_modifier_value (info
->shifter
.kind
), 0);
833 insert_field (FLD_imm6
, code
, info
->shifter
.amount
, 0);
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. */
843 aarch64_ins_sve_addr_ri_s4xvl (const aarch64_operand
*self
,
844 const aarch64_opnd_info
*info
,
846 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
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);
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. */
859 aarch64_ins_sve_addr_ri_s6xvl (const aarch64_operand
*self
,
860 const aarch64_opnd_info
*info
,
862 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
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);
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. */
876 aarch64_ins_sve_addr_ri_s9xvl (const aarch64_operand
*self
,
877 const aarch64_opnd_info
*info
,
879 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
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
);
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. */
892 aarch64_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
)
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);
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. */
906 aarch64_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
)
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);
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. */
920 aarch64_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
)
924 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
925 insert_field (self
->fields
[1], code
, info
->addr
.offset
.regno
, 0);
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. */
934 aarch64_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
)
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);
943 insert_field (self
->fields
[2], code
, 1, 0);
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. */
951 aarch64_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
)
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);
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. */
966 aarch64_ext_sve_addr_zz (const aarch64_operand
*self
,
967 const aarch64_opnd_info
*info
, aarch64_insn
*code
)
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);
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. */
979 aarch64_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
)
983 return aarch64_ext_sve_addr_zz (self
, info
, code
);
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. */
990 aarch64_ins_sve_addr_zz_sxtw (const aarch64_operand
*self
,
991 const aarch64_opnd_info
*info
,
993 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
995 return aarch64_ext_sve_addr_zz (self
, info
, code
);
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. */
1002 aarch64_ins_sve_addr_zz_uxtw (const aarch64_operand
*self
,
1003 const aarch64_opnd_info
*info
,
1005 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
1007 return aarch64_ext_sve_addr_zz (self
, info
, code
);
1010 /* Encode an SVE ADD/SUB immediate. */
1012 aarch64_ins_sve_aimm (const aarch64_operand
*self
,
1013 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1014 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
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);
1021 insert_all_fields (self
, code
, info
->imm
.value
& 0xff);
1025 /* Encode an SVE CPY/DUP immediate. */
1027 aarch64_ins_sve_asimm (const aarch64_operand
*self
,
1028 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1029 const aarch64_inst
*inst
)
1031 return aarch64_ins_sve_aimm (self
, info
, code
, inst
);
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. */
1039 aarch64_ins_sve_index (const aarch64_operand
*self
,
1040 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1041 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
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
);
1050 /* Encode a logical/bitmask immediate for the MOV alias of SVE DUPM. */
1052 aarch64_ins_sve_limm_mov (const aarch64_operand
*self
,
1053 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1054 const aarch64_inst
*inst
)
1056 return aarch64_ins_limm (self
, info
, code
, inst
);
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. */
1063 aarch64_ins_sve_quad_index (const aarch64_operand
*self
,
1064 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1065 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
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
);
1074 /* Encode {Zn.<T> - Zm.<T>}. The fields array specifies which field
1077 aarch64_ins_sve_reglist (const aarch64_operand
*self
,
1078 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1079 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
1081 insert_field (self
->fields
[0], code
, info
->reglist
.first_regno
, 0);
1085 /* Encode <pattern>{, MUL #<amount>}. The fields array specifies which
1086 fields to use for <pattern>. <amount> - 1 is encoded in the SVE_imm4
1089 aarch64_ins_sve_scale (const aarch64_operand
*self
,
1090 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1091 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
1093 insert_all_fields (self
, code
, info
->imm
.value
);
1094 insert_field (FLD_SVE_imm4
, code
, info
->shifter
.amount
- 1, 0);
1098 /* Encode an SVE shift left immediate. */
1100 aarch64_ins_sve_shlimm (const aarch64_operand
*self
,
1101 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1102 const aarch64_inst
*inst
)
1104 const aarch64_opnd_info
*prev_operand
;
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
);
1114 /* Encode an SVE shift right immediate. */
1116 aarch64_ins_sve_shrimm (const aarch64_operand
*self
,
1117 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1118 const aarch64_inst
*inst
)
1120 const aarch64_opnd_info
*prev_operand
;
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
);
1130 /* Encode a single-bit immediate that selects between #0.5 and #1.0.
1131 The fields array specifies which field to use. */
1133 aarch64_ins_sve_float_half_one (const aarch64_operand
*self
,
1134 const aarch64_opnd_info
*info
,
1136 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
1138 if (info
->imm
.value
== 0x3f000000)
1139 insert_field (self
->fields
[0], code
, 0, 0);
1141 insert_field (self
->fields
[0], code
, 1, 0);
1145 /* Encode a single-bit immediate that selects between #0.5 and #2.0.
1146 The fields array specifies which field to use. */
1148 aarch64_ins_sve_float_half_two (const aarch64_operand
*self
,
1149 const aarch64_opnd_info
*info
,
1151 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
1153 if (info
->imm
.value
== 0x3f000000)
1154 insert_field (self
->fields
[0], code
, 0, 0);
1156 insert_field (self
->fields
[0], code
, 1, 0);
1160 /* Encode a single-bit immediate that selects between #0.0 and #1.0.
1161 The fields array specifies which field to use. */
1163 aarch64_ins_sve_float_zero_one (const aarch64_operand
*self
,
1164 const aarch64_opnd_info
*info
,
1166 const aarch64_inst
*inst ATTRIBUTE_UNUSED
)
1168 if (info
->imm
.value
== 0)
1169 insert_field (self
->fields
[0], code
, 0, 0);
1171 insert_field (self
->fields
[0], code
, 1, 0);
1175 /* Miscellaneous encoding functions. */
1177 /* Encode size[0], i.e. bit 22, for
1178 e.g. FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
1181 encode_asimd_fcvt (aarch64_inst
*inst
)
1184 aarch64_field field
= {0, 0};
1185 enum aarch64_opnd_qualifier qualifier
;
1187 switch (inst
->opcode
->op
)
1191 /* FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
1192 qualifier
= inst
->operands
[1].qualifier
;
1196 /* FCVTL<Q> <Vd>.<Ta>, <Vn>.<Tb>. */
1197 qualifier
= inst
->operands
[0].qualifier
;
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);
1209 /* Encode size[0], i.e. bit 22, for
1210 e.g. FCVTXN <Vb><d>, <Va><n>. */
1213 encode_asisd_fcvtxn (aarch64_inst
*inst
)
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);
1222 /* Encode the 'opc' field for e.g. FCVT <Dd>, <Sn>. */
1224 encode_fcvt (aarch64_inst
*inst
)
1227 const aarch64_field field
= {15, 2};
1230 switch (inst
->operands
[0].qualifier
)
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;
1237 insert_field_2 (&field
, &inst
->value
, val
, 0);
1242 /* Return the index in qualifiers_list that INST is using. Should only
1243 be called once the qualifiers are known to be valid. */
1246 aarch64_get_variant (struct aarch64_inst
*inst
)
1248 int i
, nops
, variant
;
1250 nops
= aarch64_num_of_operands (inst
->opcode
);
1251 for (variant
= 0; variant
< AARCH64_MAX_QLF_SEQ_NUM
; ++variant
)
1253 for (i
= 0; i
< nops
; ++i
)
1254 if (inst
->opcode
->qualifiers_list
[variant
][i
]
1255 != inst
->operands
[i
].qualifier
)
1263 /* Do miscellaneous encodings that are not common enough to be driven by
1267 do_misc_encoding (aarch64_inst
*inst
)
1271 switch (inst
->opcode
->op
)
1280 encode_asimd_fcvt (inst
);
1283 encode_asisd_fcvtxn (inst
);
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);
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);
1298 /* Fill in the zero immediate. */
1299 insert_fields (&inst
->value
, 1 << aarch64_get_variant (inst
), 0,
1300 2, FLD_imm5
, FLD_SVE_tszh
);
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);
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);
1314 case OP_MOVZS_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);
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);
1330 /* Encode the 'size' and 'Q' field for e.g. SHADD. */
1332 encode_sizeq (aarch64_inst
*inst
)
1335 enum aarch64_field_kind kind
;
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
);
1346 insert_field (FLD_Q
, &inst
->value
, sizeq
& 0x1, inst
->opcode
->mask
);
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
;
1355 insert_field (kind
, &inst
->value
, (sizeq
>> 1) & 0x3, inst
->opcode
->mask
);
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. */
1365 do_special_encoding (struct aarch64_inst
*inst
)
1368 aarch64_insn value
= 0;
1370 DEBUG_TRACE ("enter with coding 0x%x", (uint32_t) inst
->value
);
1372 /* Condition for truly conditional executed instructions, e.g. b.cond. */
1373 if (inst
->opcode
->flags
& F_COND
)
1375 insert_field (FLD_cond2
, &inst
->value
, inst
->cond
->value
, 0);
1377 if (inst
->opcode
->flags
& F_SF
)
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
)
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
);
1387 if (inst
->opcode
->flags
& F_LSE_SZ
)
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
)
1393 insert_field (FLD_lse_sz
, &inst
->value
, value
, 0);
1395 if (inst
->opcode
->flags
& F_SIZEQ
)
1396 encode_sizeq (inst
);
1397 if (inst
->opcode
->flags
& F_FPTYPE
)
1399 idx
= select_operand_for_fptype_field_coding (inst
->opcode
);
1400 switch (inst
->operands
[idx
].qualifier
)
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);
1407 insert_field (FLD_type
, &inst
->value
, value
, 0);
1409 if (inst
->opcode
->flags
& F_SSIZE
)
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
);
1419 if (inst
->opcode
->flags
& F_T
)
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
;
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
);
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
);
1448 if (inst
->opcode
->flags
& F_GPRSIZE_IN_Q
)
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
);
1455 /* Otherwise use the result operand, which has to be a integer
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);
1465 if (inst
->opcode
->flags
& F_LDS_SIZE
)
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);
1477 /* Miscellaneous encoding as the last step. */
1478 if (inst
->opcode
->flags
& F_MISC
)
1479 do_misc_encoding (inst
);
1481 DEBUG_TRACE ("exit with coding 0x%x", (uint32_t) inst
->value
);
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
1490 aarch64_encode_variant_using_iclass (struct aarch64_inst
*inst
)
1492 switch (inst
->opcode
->iclass
)
1495 insert_fields (&inst
->value
, aarch64_get_variant (inst
),
1496 0, 2, FLD_SVE_M_14
, FLD_size
);
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. */
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
1513 /* sve_misc instructions have only a single variant. */
1517 insert_fields (&inst
->value
, aarch64_get_variant (inst
),
1518 0, 2, FLD_SVE_M_16
, FLD_size
);
1522 insert_field (FLD_SVE_M_4
, &inst
->value
, aarch64_get_variant (inst
), 0);
1527 insert_field (FLD_size
, &inst
->value
, aarch64_get_variant (inst
), 0);
1531 insert_field (FLD_size
, &inst
->value
, aarch64_get_variant (inst
) + 1, 0);
1535 insert_field (FLD_SVE_sz
, &inst
->value
, aarch64_get_variant (inst
), 0);
1543 /* Converters converting an alias opcode instruction to its real form. */
1545 /* ROR <Wd>, <Ws>, #<shift>
1547 EXTR <Wd>, <Ws>, <Ws>, #<shift>. */
1549 convert_ror_to_extr (aarch64_inst
*inst
)
1551 copy_operand_info (inst
, 3, 2);
1552 copy_operand_info (inst
, 2, 1);
1555 /* UXTL<Q> <Vd>.<Ta>, <Vn>.<Tb>
1557 USHLL<Q> <Vd>.<Ta>, <Vn>.<Tb>, #0. */
1559 convert_xtl_to_shll (aarch64_inst
*inst
)
1561 inst
->operands
[2].qualifier
= inst
->operands
[1].qualifier
;
1562 inst
->operands
[2].imm
.value
= 0;
1566 LSR <Xd>, <Xn>, #<shift>
1568 UBFM <Xd>, <Xn>, #<shift>, #63. */
1570 convert_sr_to_bfm (aarch64_inst
*inst
)
1572 inst
->operands
[3].imm
.value
=
1573 inst
->operands
[2].qualifier
== AARCH64_OPND_QLF_imm_0_31
? 31 : 63;
1576 /* Convert MOV to ORR. */
1578 convert_mov_to_orr (aarch64_inst
*inst
)
1580 /* MOV <Vd>.<T>, <Vn>.<T>
1582 ORR <Vd>.<T>, <Vn>.<T>, <Vn>.<T>. */
1583 copy_operand_info (inst
, 2, 1);
1586 /* When <imms> >= <immr>, the instruction written:
1587 SBFX <Xd>, <Xn>, #<lsb>, #<width>
1589 SBFM <Xd>, <Xn>, #<lsb>, #(<lsb>+<width>-1). */
1592 convert_bfx_to_bfm (aarch64_inst
*inst
)
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;
1603 /* When <imms> < <immr>, the instruction written:
1604 SBFIZ <Xd>, <Xn>, #<lsb>, #<width>
1606 SBFM <Xd>, <Xn>, #((64-<lsb>)&0x3f), #(<width>-1). */
1609 convert_bfi_to_bfm (aarch64_inst
*inst
)
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
)
1618 inst
->operands
[2].imm
.value
= (32 - lsb
) & 0x1f;
1619 inst
->operands
[3].imm
.value
= width
- 1;
1623 inst
->operands
[2].imm
.value
= (64 - lsb
) & 0x3f;
1624 inst
->operands
[3].imm
.value
= width
- 1;
1628 /* The instruction written:
1629 BFC <Xd>, #<lsb>, #<width>
1631 BFM <Xd>, XZR, #((64-<lsb>)&0x3f), #(<width>-1). */
1634 convert_bfc_to_bfm (aarch64_inst
*inst
)
1639 copy_operand_info (inst
, 3, 2);
1640 copy_operand_info (inst
, 2, 1);
1641 copy_operand_info (inst
, 1, 0);
1642 inst
->operands
[1].reg
.regno
= 0x1f;
1644 /* Convert the immediate operand. */
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
)
1649 inst
->operands
[2].imm
.value
= (32 - lsb
) & 0x1f;
1650 inst
->operands
[3].imm
.value
= width
- 1;
1654 inst
->operands
[2].imm
.value
= (64 - lsb
) & 0x3f;
1655 inst
->operands
[3].imm
.value
= width
- 1;
1659 /* The instruction written:
1660 LSL <Xd>, <Xn>, #<shift>
1662 UBFM <Xd>, <Xn>, #((64-<shift>)&0x3f), #(63-<shift>). */
1665 convert_lsl_to_ubfm (aarch64_inst
*inst
)
1667 int64_t shift
= inst
->operands
[2].imm
.value
;
1669 if (inst
->operands
[2].qualifier
== AARCH64_OPND_QLF_imm_0_31
)
1671 inst
->operands
[2].imm
.value
= (32 - shift
) & 0x1f;
1672 inst
->operands
[3].imm
.value
= 31 - shift
;
1676 inst
->operands
[2].imm
.value
= (64 - shift
) & 0x3f;
1677 inst
->operands
[3].imm
.value
= 63 - shift
;
1681 /* CINC <Wd>, <Wn>, <cond>
1683 CSINC <Wd>, <Wn>, <Wn>, invert(<cond>). */
1686 convert_to_csel (aarch64_inst
*inst
)
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
);
1693 /* CSET <Wd>, <cond>
1695 CSINC <Wd>, WZR, WZR, invert(<cond>). */
1698 convert_cset_to_csinc (aarch64_inst
*inst
)
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
);
1710 MOVZ <Wd>, #<imm16>, LSL #<shift>. */
1713 convert_mov_to_movewide (aarch64_inst
*inst
)
1716 uint32_t shift_amount
;
1719 switch (inst
->opcode
->op
)
1721 case OP_MOV_IMM_WIDE
:
1722 value
= inst
->operands
[1].imm
.value
;
1724 case OP_MOV_IMM_WIDEN
:
1725 value
= ~inst
->operands
[1].imm
.value
;
1730 inst
->operands
[1].type
= AARCH64_OPND_HALF
;
1731 is32
= inst
->operands
[0].qualifier
== AARCH64_OPND_QLF_W
;
1732 if (! aarch64_wide_constant_p (value
, is32
, &shift_amount
))
1733 /* The constraint check should have guaranteed this wouldn't happen. */
1735 value
>>= shift_amount
;
1737 inst
->operands
[1].imm
.value
= value
;
1738 inst
->operands
[1].shifter
.kind
= AARCH64_MOD_LSL
;
1739 inst
->operands
[1].shifter
.amount
= shift_amount
;
1744 ORR <Wd>, WZR, #<imm>. */
1747 convert_mov_to_movebitmask (aarch64_inst
*inst
)
1749 copy_operand_info (inst
, 2, 1);
1750 inst
->operands
[1].reg
.regno
= 0x1f;
1751 inst
->operands
[1].skip
= 0;
1754 /* Some alias opcodes are assembled by being converted to their real-form. */
1757 convert_to_real (aarch64_inst
*inst
, const aarch64_opcode
*real
)
1759 const aarch64_opcode
*alias
= inst
->opcode
;
1761 if ((alias
->flags
& F_CONV
) == 0)
1762 goto convert_to_real_return
;
1768 convert_sr_to_bfm (inst
);
1771 convert_lsl_to_ubfm (inst
);
1776 convert_to_csel (inst
);
1780 convert_cset_to_csinc (inst
);
1785 convert_bfx_to_bfm (inst
);
1790 convert_bfi_to_bfm (inst
);
1793 convert_bfc_to_bfm (inst
);
1796 convert_mov_to_orr (inst
);
1798 case OP_MOV_IMM_WIDE
:
1799 case OP_MOV_IMM_WIDEN
:
1800 convert_mov_to_movewide (inst
);
1802 case OP_MOV_IMM_LOG
:
1803 convert_mov_to_movebitmask (inst
);
1806 convert_ror_to_extr (inst
);
1812 convert_xtl_to_shll (inst
);
1818 convert_to_real_return
:
1819 aarch64_replace_opcode (inst
, real
);
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. */
1827 aarch64_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
)
1833 const aarch64_opcode
*aliased
;
1834 aarch64_inst copy
, *inst
;
1836 DEBUG_TRACE ("enter with %s", opcode
->name
);
1838 /* Create a copy of *INST_ORI, so that we can do any change we want. */
1842 assert (inst
->opcode
== NULL
|| inst
->opcode
== opcode
);
1843 if (inst
->opcode
== NULL
)
1844 inst
->opcode
= opcode
;
1846 /* Constrain the operands.
1847 After passing this, the encoding is guaranteed to succeed. */
1848 if (aarch64_match_operands_constraint (inst
, mismatch_detail
) == 0)
1850 DEBUG_TRACE ("FAIL since operand constraint not met");
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
;
1860 /* No need to do anything else if the opcode does not have any operand. */
1861 if (aarch64_num_of_operands (opcode
) == 0)
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
)
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
;
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
1879 if (aliased
!= NULL
&& (opcode
->flags
& F_CONV
))
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
);
1888 aarch64_opnd_info
*info
= inst
->operands
;
1890 /* Call the inserter of each operand. */
1891 for (i
= 0; i
< AARCH64_MAX_OPND_NUM
; ++i
, ++info
)
1893 const aarch64_operand
*opnd
;
1894 enum aarch64_opnd type
= opcode
->operands
[i
];
1895 if (type
== AARCH64_OPND_NIL
)
1899 DEBUG_TRACE ("skip the incomplete operand %d", i
);
1902 opnd
= &aarch64_operands
[type
];
1903 if (operand_has_inserter (opnd
))
1904 aarch64_insert_operand (opnd
, info
, &inst
->value
, inst
);
1907 /* Call opcode encoders indicated by flags. */
1908 if (opcode_has_special_coder (opcode
))
1909 do_special_encoding (inst
);
1911 /* Possibly use the instruction class to encode the chosen qualifier
1913 aarch64_encode_variant_using_iclass (inst
);
1916 DEBUG_TRACE ("exit with %s", opcode
->name
);
1918 *code
= inst
->value
;