1 /* aarch64-asm.c -- AArch64 assembler support.
2 Copyright (C) 2012-2021 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"
29 /* The unnamed arguments consist of the number of fields and information about
30 these fields where the VALUE will be inserted into CODE. MASK can be zero or
31 the base mask of the opcode.
33 N.B. the fields are required to be in such an order than the least signficant
34 field for VALUE comes the first, e.g. the <index> in
35 SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
36 is encoded in H:L:M in some cases, the fields H:L:M should be passed in
37 the order of M, L, H. */
40 insert_fields (aarch64_insn
*code
, aarch64_insn value
, aarch64_insn mask
, ...)
43 const aarch64_field
*field
;
44 enum aarch64_field_kind kind
;
48 num
= va_arg (va
, uint32_t);
52 kind
= va_arg (va
, enum aarch64_field_kind
);
53 field
= &fields
[kind
];
54 insert_field (kind
, code
, value
, mask
);
55 value
>>= field
->width
;
60 /* Insert a raw field value VALUE into all fields in SELF->fields.
61 The least significant bit goes in the final field. */
64 insert_all_fields (const aarch64_operand
*self
, aarch64_insn
*code
,
68 enum aarch64_field_kind kind
;
70 for (i
= ARRAY_SIZE (self
->fields
); i
-- > 0; )
71 if (self
->fields
[i
] != FLD_NIL
)
73 kind
= self
->fields
[i
];
74 insert_field (kind
, code
, value
, 0);
75 value
>>= fields
[kind
].width
;
79 /* Operand inserters. */
83 aarch64_ins_none (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
84 const aarch64_opnd_info
*info ATTRIBUTE_UNUSED
,
85 aarch64_insn
*code ATTRIBUTE_UNUSED
,
86 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
87 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
92 /* Insert register number. */
94 aarch64_ins_regno (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
96 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
97 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
99 insert_field (self
->fields
[0], code
, info
->reg
.regno
, 0);
103 /* Insert register number, index and/or other data for SIMD register element
104 operand, e.g. the last source operand in
105 SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]. */
107 aarch64_ins_reglane (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
108 aarch64_insn
*code
, const aarch64_inst
*inst
,
109 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
112 insert_field (self
->fields
[0], code
, info
->reglane
.regno
, inst
->opcode
->mask
);
113 /* index and/or type */
114 if (inst
->opcode
->iclass
== asisdone
|| inst
->opcode
->iclass
== asimdins
)
116 int pos
= info
->qualifier
- AARCH64_OPND_QLF_S_B
;
117 if (info
->type
== AARCH64_OPND_En
118 && inst
->opcode
->operands
[0] == AARCH64_OPND_Ed
)
120 /* index2 for e.g. INS <Vd>.<Ts>[<index1>], <Vn>.<Ts>[<index2>]. */
121 assert (info
->idx
== 1); /* Vn */
122 aarch64_insn value
= info
->reglane
.index
<< pos
;
123 insert_field (FLD_imm4
, code
, value
, 0);
127 /* index and type for e.g. DUP <V><d>, <Vn>.<T>[<index>].
134 aarch64_insn value
= ((info
->reglane
.index
<< 1) | 1) << pos
;
135 insert_field (FLD_imm5
, code
, value
, 0);
138 else if (inst
->opcode
->iclass
== dotproduct
)
140 unsigned reglane_index
= info
->reglane
.index
;
141 switch (info
->qualifier
)
143 case AARCH64_OPND_QLF_S_4B
:
144 case AARCH64_OPND_QLF_S_2H
:
146 assert (reglane_index
< 4);
147 insert_fields (code
, reglane_index
, 0, 2, FLD_L
, FLD_H
);
153 else if (inst
->opcode
->iclass
== cryptosm3
)
155 /* index for e.g. SM3TT2A <Vd>.4S, <Vn>.4S, <Vm>S[<imm2>]. */
156 unsigned reglane_index
= info
->reglane
.index
;
157 assert (reglane_index
< 4);
158 insert_field (FLD_SM3_imm2
, code
, reglane_index
, 0);
162 /* index for e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
163 or SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]. */
164 unsigned reglane_index
= info
->reglane
.index
;
166 if (inst
->opcode
->op
== OP_FCMLA_ELEM
)
167 /* Complex operand takes two elements. */
170 switch (info
->qualifier
)
172 case AARCH64_OPND_QLF_S_H
:
174 assert (reglane_index
< 8);
175 insert_fields (code
, reglane_index
, 0, 3, FLD_M
, FLD_L
, FLD_H
);
177 case AARCH64_OPND_QLF_S_S
:
179 assert (reglane_index
< 4);
180 insert_fields (code
, reglane_index
, 0, 2, FLD_L
, FLD_H
);
182 case AARCH64_OPND_QLF_S_D
:
184 assert (reglane_index
< 2);
185 insert_field (FLD_H
, code
, reglane_index
, 0);
194 /* Insert regno and len field of a register list operand, e.g. Vn in TBL. */
196 aarch64_ins_reglist (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
198 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
199 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
202 insert_field (self
->fields
[0], code
, info
->reglist
.first_regno
, 0);
204 insert_field (FLD_len
, code
, info
->reglist
.num_regs
- 1, 0);
208 /* Insert Rt and opcode fields for a register list operand, e.g. Vt
209 in AdvSIMD load/store instructions. */
211 aarch64_ins_ldst_reglist (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
212 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
213 const aarch64_inst
*inst
,
214 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
216 aarch64_insn value
= 0;
217 /* Number of elements in each structure to be loaded/stored. */
218 unsigned num
= get_opcode_dependent_value (inst
->opcode
);
221 insert_field (FLD_Rt
, code
, info
->reglist
.first_regno
, 0);
226 switch (info
->reglist
.num_regs
)
228 case 1: value
= 0x7; break;
229 case 2: value
= 0xa; break;
230 case 3: value
= 0x6; break;
231 case 4: value
= 0x2; break;
236 value
= info
->reglist
.num_regs
== 4 ? 0x3 : 0x8;
247 insert_field (FLD_opcode
, code
, value
, 0);
252 /* Insert Rt and S fields for a register list operand, e.g. Vt in AdvSIMD load
253 single structure to all lanes instructions. */
255 aarch64_ins_ldst_reglist_r (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
256 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
257 const aarch64_inst
*inst
,
258 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
261 /* The opcode dependent area stores the number of elements in
262 each structure to be loaded/stored. */
263 int is_ld1r
= get_opcode_dependent_value (inst
->opcode
) == 1;
266 insert_field (FLD_Rt
, code
, info
->reglist
.first_regno
, 0);
268 value
= (aarch64_insn
) 0;
269 if (is_ld1r
&& info
->reglist
.num_regs
== 2)
270 /* OP_LD1R does not have alternating variant, but have "two consecutive"
272 value
= (aarch64_insn
) 1;
273 insert_field (FLD_S
, code
, value
, 0);
278 /* Insert Q, opcode<2:1>, S, size and Rt fields for a register element list
279 operand e.g. Vt in AdvSIMD load/store single element instructions. */
281 aarch64_ins_ldst_elemlist (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
282 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
283 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
284 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
286 aarch64_field field
= {0, 0};
287 aarch64_insn QSsize
= 0; /* fields Q:S:size. */
288 aarch64_insn opcodeh2
= 0; /* opcode<2:1> */
290 assert (info
->reglist
.has_index
);
293 insert_field (FLD_Rt
, code
, info
->reglist
.first_regno
, 0);
294 /* Encode the index, opcode<2:1> and size. */
295 switch (info
->qualifier
)
297 case AARCH64_OPND_QLF_S_B
:
298 /* Index encoded in "Q:S:size". */
299 QSsize
= info
->reglist
.index
;
302 case AARCH64_OPND_QLF_S_H
:
303 /* Index encoded in "Q:S:size<1>". */
304 QSsize
= info
->reglist
.index
<< 1;
307 case AARCH64_OPND_QLF_S_S
:
308 /* Index encoded in "Q:S". */
309 QSsize
= info
->reglist
.index
<< 2;
312 case AARCH64_OPND_QLF_S_D
:
313 /* Index encoded in "Q". */
314 QSsize
= info
->reglist
.index
<< 3 | 0x1;
320 insert_fields (code
, QSsize
, 0, 3, FLD_vldst_size
, FLD_S
, FLD_Q
);
321 gen_sub_field (FLD_asisdlso_opcode
, 1, 2, &field
);
322 insert_field_2 (&field
, code
, opcodeh2
, 0);
327 /* Insert fields immh:immb and/or Q for e.g. the shift immediate in
328 SSHR <Vd>.<T>, <Vn>.<T>, #<shift>
329 or SSHR <V><d>, <V><n>, #<shift>. */
331 aarch64_ins_advsimd_imm_shift (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
332 const aarch64_opnd_info
*info
,
333 aarch64_insn
*code
, const aarch64_inst
*inst
,
334 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
336 unsigned val
= aarch64_get_qualifier_standard_value (info
->qualifier
);
339 if (inst
->opcode
->iclass
== asimdshf
)
343 0000 x SEE AdvSIMD modified immediate
352 Q
= (val
& 0x1) ? 1 : 0;
353 insert_field (FLD_Q
, code
, Q
, inst
->opcode
->mask
);
357 assert (info
->type
== AARCH64_OPND_IMM_VLSR
358 || info
->type
== AARCH64_OPND_IMM_VLSL
);
360 if (info
->type
== AARCH64_OPND_IMM_VLSR
)
363 0000 SEE AdvSIMD modified immediate
364 0001 (16-UInt(immh:immb))
365 001x (32-UInt(immh:immb))
366 01xx (64-UInt(immh:immb))
367 1xxx (128-UInt(immh:immb)) */
368 imm
= (16 << (unsigned)val
) - info
->imm
.value
;
372 0000 SEE AdvSIMD modified immediate
373 0001 (UInt(immh:immb)-8)
374 001x (UInt(immh:immb)-16)
375 01xx (UInt(immh:immb)-32)
376 1xxx (UInt(immh:immb)-64) */
377 imm
= info
->imm
.value
+ (8 << (unsigned)val
);
378 insert_fields (code
, imm
, 0, 2, FLD_immb
, FLD_immh
);
383 /* Insert fields for e.g. the immediate operands in
384 BFM <Wd>, <Wn>, #<immr>, #<imms>. */
386 aarch64_ins_imm (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
388 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
389 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
393 imm
= info
->imm
.value
;
394 if (operand_need_shift_by_two (self
))
396 if (operand_need_shift_by_four (self
))
398 insert_all_fields (self
, code
, imm
);
402 /* Insert immediate and its shift amount for e.g. the last operand in
403 MOVZ <Wd>, #<imm16>{, LSL #<shift>}. */
405 aarch64_ins_imm_half (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
406 aarch64_insn
*code
, const aarch64_inst
*inst
,
407 aarch64_operand_error
*errors
)
410 aarch64_ins_imm (self
, info
, code
, inst
, errors
);
412 insert_field (FLD_hw
, code
, info
->shifter
.amount
>> 4, 0);
416 /* Insert cmode and "a:b:c:d:e:f:g:h" fields for e.g. the last operand in
417 MOVI <Vd>.<T>, #<imm8> {, LSL #<amount>}. */
419 aarch64_ins_advsimd_imm_modified (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
420 const aarch64_opnd_info
*info
,
422 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
423 aarch64_operand_error
*errors
426 enum aarch64_opnd_qualifier opnd0_qualifier
= inst
->operands
[0].qualifier
;
427 uint64_t imm
= info
->imm
.value
;
428 enum aarch64_modifier_kind kind
= info
->shifter
.kind
;
429 int amount
= info
->shifter
.amount
;
430 aarch64_field field
= {0, 0};
432 /* a:b:c:d:e:f:g:h */
433 if (!info
->imm
.is_fp
&& aarch64_get_qualifier_esize (opnd0_qualifier
) == 8)
435 /* Either MOVI <Dd>, #<imm>
436 or MOVI <Vd>.2D, #<imm>.
437 <imm> is a 64-bit immediate
438 "aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh",
439 encoded in "a:b:c:d:e:f:g:h". */
440 imm
= aarch64_shrink_expanded_imm8 (imm
);
441 assert ((int)imm
>= 0);
443 insert_fields (code
, imm
, 0, 2, FLD_defgh
, FLD_abc
);
445 if (kind
== AARCH64_MOD_NONE
)
448 /* shift amount partially in cmode */
449 assert (kind
== AARCH64_MOD_LSL
|| kind
== AARCH64_MOD_MSL
);
450 if (kind
== AARCH64_MOD_LSL
)
452 /* AARCH64_MOD_LSL: shift zeros. */
453 int esize
= aarch64_get_qualifier_esize (opnd0_qualifier
);
454 assert (esize
== 4 || esize
== 2 || esize
== 1);
455 /* For 8-bit move immediate, the optional LSL #0 does not require
461 gen_sub_field (FLD_cmode
, 1, 2, &field
); /* per word */
463 gen_sub_field (FLD_cmode
, 1, 1, &field
); /* per halfword */
467 /* AARCH64_MOD_MSL: shift ones. */
469 gen_sub_field (FLD_cmode
, 0, 1, &field
); /* per word */
471 insert_field_2 (&field
, code
, amount
, 0);
476 /* Insert fields for an 8-bit floating-point immediate. */
478 aarch64_ins_fpimm (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
480 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
481 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
483 insert_all_fields (self
, code
, info
->imm
.value
);
487 /* Insert 1-bit rotation immediate (#90 or #270). */
489 aarch64_ins_imm_rotate1 (const aarch64_operand
*self
,
490 const aarch64_opnd_info
*info
,
491 aarch64_insn
*code
, const aarch64_inst
*inst
,
492 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
494 uint64_t rot
= (info
->imm
.value
- 90) / 180;
496 insert_field (self
->fields
[0], code
, rot
, inst
->opcode
->mask
);
500 /* Insert 2-bit rotation immediate (#0, #90, #180 or #270). */
502 aarch64_ins_imm_rotate2 (const aarch64_operand
*self
,
503 const aarch64_opnd_info
*info
,
504 aarch64_insn
*code
, const aarch64_inst
*inst
,
505 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
507 uint64_t rot
= info
->imm
.value
/ 90;
509 insert_field (self
->fields
[0], code
, rot
, inst
->opcode
->mask
);
513 /* Insert #<fbits> for the immediate operand in fp fix-point instructions,
514 e.g. SCVTF <Dd>, <Wn>, #<fbits>. */
516 aarch64_ins_fbits (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
518 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
519 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
521 insert_field (self
->fields
[0], code
, 64 - info
->imm
.value
, 0);
525 /* Insert arithmetic immediate for e.g. the last operand in
526 SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}. */
528 aarch64_ins_aimm (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
529 aarch64_insn
*code
, const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
530 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
533 aarch64_insn value
= info
->shifter
.amount
? 1 : 0;
534 insert_field (self
->fields
[0], code
, value
, 0);
535 /* imm12 (unsigned) */
536 insert_field (self
->fields
[1], code
, info
->imm
.value
, 0);
540 /* Common routine shared by aarch64_ins{,_inv}_limm. INVERT_P says whether
541 the operand should be inverted before encoding. */
543 aarch64_ins_limm_1 (const aarch64_operand
*self
,
544 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
545 const aarch64_inst
*inst
, bfd_boolean invert_p
,
546 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
550 uint64_t imm
= info
->imm
.value
;
551 int esize
= aarch64_get_qualifier_esize (inst
->operands
[0].qualifier
);
555 /* The constraint check should guarantee that this will work. */
556 res
= aarch64_logical_immediate_p (imm
, esize
, &value
);
558 insert_fields (code
, value
, 0, 3, self
->fields
[2], self
->fields
[1],
563 /* Insert logical/bitmask immediate for e.g. the last operand in
564 ORR <Wd|WSP>, <Wn>, #<imm>. */
566 aarch64_ins_limm (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
567 aarch64_insn
*code
, const aarch64_inst
*inst
,
568 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
570 return aarch64_ins_limm_1 (self
, info
, code
, inst
,
571 inst
->opcode
->op
== OP_BIC
, errors
);
574 /* Insert a logical/bitmask immediate for the BIC alias of AND (etc.). */
576 aarch64_ins_inv_limm (const aarch64_operand
*self
,
577 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
578 const aarch64_inst
*inst
,
579 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
581 return aarch64_ins_limm_1 (self
, info
, code
, inst
, TRUE
, errors
);
584 /* Encode Ft for e.g. STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]
585 or LDP <Qt1>, <Qt2>, [<Xn|SP>], #<imm>. */
587 aarch64_ins_ft (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
588 aarch64_insn
*code
, const aarch64_inst
*inst
,
589 aarch64_operand_error
*errors
)
591 aarch64_insn value
= 0;
593 assert (info
->idx
== 0);
596 aarch64_ins_regno (self
, info
, code
, inst
, errors
);
597 if (inst
->opcode
->iclass
== ldstpair_indexed
598 || inst
->opcode
->iclass
== ldstnapair_offs
599 || inst
->opcode
->iclass
== ldstpair_off
600 || inst
->opcode
->iclass
== loadlit
)
603 switch (info
->qualifier
)
605 case AARCH64_OPND_QLF_S_S
: value
= 0; break;
606 case AARCH64_OPND_QLF_S_D
: value
= 1; break;
607 case AARCH64_OPND_QLF_S_Q
: value
= 2; break;
610 insert_field (FLD_ldst_size
, code
, value
, 0);
615 value
= aarch64_get_qualifier_standard_value (info
->qualifier
);
616 insert_fields (code
, value
, 0, 2, FLD_ldst_size
, FLD_opc1
);
622 /* Encode the address operand for e.g. STXRB <Ws>, <Wt>, [<Xn|SP>{,#0}]. */
624 aarch64_ins_addr_simple (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
625 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
626 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
627 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
630 insert_field (FLD_Rn
, code
, info
->addr
.base_regno
, 0);
634 /* Encode the address operand for e.g.
635 STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
637 aarch64_ins_addr_regoff (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
638 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
639 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
640 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
643 enum aarch64_modifier_kind kind
= info
->shifter
.kind
;
646 insert_field (FLD_Rn
, code
, info
->addr
.base_regno
, 0);
648 insert_field (FLD_Rm
, code
, info
->addr
.offset
.regno
, 0);
650 if (kind
== AARCH64_MOD_LSL
)
651 kind
= AARCH64_MOD_UXTX
; /* Trick to enable the table-driven. */
652 insert_field (FLD_option
, code
, aarch64_get_operand_modifier_value (kind
), 0);
654 if (info
->qualifier
!= AARCH64_OPND_QLF_S_B
)
655 S
= info
->shifter
.amount
!= 0;
657 /* For STR <Bt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}},
661 Must be #0 if <extend> is explicitly LSL. */
662 S
= info
->shifter
.operator_present
&& info
->shifter
.amount_present
;
663 insert_field (FLD_S
, code
, S
, 0);
668 /* Encode the address operand for e.g.
669 stlur <Xt>, [<Xn|SP>{, <amount>}]. */
671 aarch64_ins_addr_offset (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
672 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
673 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
674 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
677 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
680 int imm
= info
->addr
.offset
.imm
;
681 insert_field (self
->fields
[1], code
, imm
, 0);
684 if (info
->addr
.writeback
)
686 assert (info
->addr
.preind
== 1 && info
->addr
.postind
== 0);
687 insert_field (self
->fields
[2], code
, 1, 0);
692 /* Encode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>, #<simm>]!. */
694 aarch64_ins_addr_simm (const aarch64_operand
*self
,
695 const aarch64_opnd_info
*info
,
697 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
698 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
703 insert_field (FLD_Rn
, code
, info
->addr
.base_regno
, 0);
704 /* simm (imm9 or imm7) */
705 imm
= info
->addr
.offset
.imm
;
706 if (self
->fields
[0] == FLD_imm7
707 || info
->qualifier
== AARCH64_OPND_QLF_imm_tag
)
708 /* scaled immediate in ld/st pair instructions.. */
709 imm
>>= get_logsz (aarch64_get_qualifier_esize (info
->qualifier
));
710 insert_field (self
->fields
[0], code
, imm
, 0);
711 /* pre/post- index */
712 if (info
->addr
.writeback
)
714 assert (inst
->opcode
->iclass
!= ldst_unscaled
715 && inst
->opcode
->iclass
!= ldstnapair_offs
716 && inst
->opcode
->iclass
!= ldstpair_off
717 && inst
->opcode
->iclass
!= ldst_unpriv
);
718 assert (info
->addr
.preind
!= info
->addr
.postind
);
719 if (info
->addr
.preind
)
720 insert_field (self
->fields
[1], code
, 1, 0);
726 /* Encode the address operand for e.g. LDRAA <Xt>, [<Xn|SP>{, #<simm>}]. */
728 aarch64_ins_addr_simm10 (const aarch64_operand
*self
,
729 const aarch64_opnd_info
*info
,
731 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
732 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
737 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
739 imm
= info
->addr
.offset
.imm
>> 3;
740 insert_field (self
->fields
[1], code
, imm
>> 9, 0);
741 insert_field (self
->fields
[2], code
, imm
, 0);
743 if (info
->addr
.writeback
)
745 assert (info
->addr
.preind
== 1 && info
->addr
.postind
== 0);
746 insert_field (self
->fields
[3], code
, 1, 0);
751 /* Encode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>{, #<pimm>}]. */
753 aarch64_ins_addr_uimm12 (const aarch64_operand
*self
,
754 const aarch64_opnd_info
*info
,
756 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
757 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
759 int shift
= get_logsz (aarch64_get_qualifier_esize (info
->qualifier
));
762 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
764 insert_field (self
->fields
[1], code
,info
->addr
.offset
.imm
>> shift
, 0);
768 /* Encode the address operand for e.g.
769 LD1 {<Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>}, [<Xn|SP>], <Xm|#<amount>>. */
771 aarch64_ins_simd_addr_post (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
772 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
773 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
774 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
777 insert_field (FLD_Rn
, code
, info
->addr
.base_regno
, 0);
779 if (info
->addr
.offset
.is_reg
)
780 insert_field (FLD_Rm
, code
, info
->addr
.offset
.regno
, 0);
782 insert_field (FLD_Rm
, code
, 0x1f, 0);
786 /* Encode the condition operand for e.g. CSEL <Xd>, <Xn>, <Xm>, <cond>. */
788 aarch64_ins_cond (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
789 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
790 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
791 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
794 insert_field (FLD_cond
, code
, info
->cond
->value
, 0);
798 /* Encode the system register operand for e.g. MRS <Xt>, <systemreg>. */
800 aarch64_ins_sysreg (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
801 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
802 const aarch64_inst
*inst
,
803 aarch64_operand_error
*detail ATTRIBUTE_UNUSED
)
805 /* If a system instruction check if we have any restrictions on which
806 registers it can use. */
807 if (inst
->opcode
->iclass
== ic_system
)
809 uint64_t opcode_flags
810 = inst
->opcode
->flags
& (F_SYS_READ
| F_SYS_WRITE
);
811 uint32_t sysreg_flags
812 = info
->sysreg
.flags
& (F_REG_READ
| F_REG_WRITE
);
814 /* Check to see if it's read-only, else check if it's write only.
815 if it's both or unspecified don't care. */
816 if (opcode_flags
== F_SYS_READ
818 && sysreg_flags
!= F_REG_READ
)
820 detail
->kind
= AARCH64_OPDE_SYNTAX_ERROR
;
821 detail
->error
= _("specified register cannot be read from");
822 detail
->index
= info
->idx
;
823 detail
->non_fatal
= TRUE
;
825 else if (opcode_flags
== F_SYS_WRITE
827 && sysreg_flags
!= F_REG_WRITE
)
829 detail
->kind
= AARCH64_OPDE_SYNTAX_ERROR
;
830 detail
->error
= _("specified register cannot be written to");
831 detail
->index
= info
->idx
;
832 detail
->non_fatal
= TRUE
;
835 /* op0:op1:CRn:CRm:op2 */
836 insert_fields (code
, info
->sysreg
.value
, inst
->opcode
->mask
, 5,
837 FLD_op2
, FLD_CRm
, FLD_CRn
, FLD_op1
, FLD_op0
);
841 /* Encode the PSTATE field operand for e.g. MSR <pstatefield>, #<imm>. */
843 aarch64_ins_pstatefield (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
844 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
845 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
846 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
849 insert_fields (code
, info
->pstatefield
, inst
->opcode
->mask
, 2,
854 /* Encode the system instruction op operand for e.g. AT <at_op>, <Xt>. */
856 aarch64_ins_sysins_op (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
857 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
858 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
859 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
861 /* op1:CRn:CRm:op2 */
862 insert_fields (code
, info
->sysins_op
->value
, inst
->opcode
->mask
, 4,
863 FLD_op2
, FLD_CRm
, FLD_CRn
, FLD_op1
);
867 /* Encode the memory barrier option operand for e.g. DMB <option>|#<imm>. */
870 aarch64_ins_barrier (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
871 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
872 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
873 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
876 insert_field (FLD_CRm
, code
, info
->barrier
->value
, 0);
880 /* Encode the memory barrier option operand for DSB <option>nXS|#<imm>. */
883 aarch64_ins_barrier_dsb_nxs (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
884 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
885 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
886 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
888 /* For the DSB nXS barrier variant: is a 5-bit unsigned immediate,
889 encoded in CRm<3:2>. */
890 aarch64_insn value
= (info
->barrier
->value
>> 2) - 4;
891 insert_field (FLD_CRm_dsb_nxs
, code
, value
, 0);
895 /* Encode the prefetch operation option operand for e.g.
896 PRFM <prfop>, [<Xn|SP>{, #<pimm>}]. */
899 aarch64_ins_prfop (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
900 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
901 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
902 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
905 insert_field (FLD_Rt
, code
, info
->prfop
->value
, 0);
909 /* Encode the hint number for instructions that alias HINT but take an
913 aarch64_ins_hint (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
914 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
915 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
916 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
919 insert_fields (code
, info
->hint_option
->value
, 0, 2, FLD_op2
, FLD_CRm
);
923 /* Encode the extended register operand for e.g.
924 STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
926 aarch64_ins_reg_extended (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
927 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
928 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
929 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
931 enum aarch64_modifier_kind kind
;
934 insert_field (FLD_Rm
, code
, info
->reg
.regno
, 0);
936 kind
= info
->shifter
.kind
;
937 if (kind
== AARCH64_MOD_LSL
)
938 kind
= info
->qualifier
== AARCH64_OPND_QLF_W
939 ? AARCH64_MOD_UXTW
: AARCH64_MOD_UXTX
;
940 insert_field (FLD_option
, code
, aarch64_get_operand_modifier_value (kind
), 0);
942 insert_field (FLD_imm3
, code
, info
->shifter
.amount
, 0);
947 /* Encode the shifted register operand for e.g.
948 SUBS <Xd>, <Xn>, <Xm> {, <shift> #<amount>}. */
950 aarch64_ins_reg_shifted (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
951 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
952 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
953 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
956 insert_field (FLD_Rm
, code
, info
->reg
.regno
, 0);
958 insert_field (FLD_shift
, code
,
959 aarch64_get_operand_modifier_value (info
->shifter
.kind
), 0);
961 insert_field (FLD_imm6
, code
, info
->shifter
.amount
, 0);
966 /* Encode an SVE address [<base>, #<simm4>*<factor>, MUL VL],
967 where <simm4> is a 4-bit signed value and where <factor> is 1 plus
968 SELF's operand-dependent value. fields[0] specifies the field that
969 holds <base>. <simm4> is encoded in the SVE_imm4 field. */
971 aarch64_ins_sve_addr_ri_s4xvl (const aarch64_operand
*self
,
972 const aarch64_opnd_info
*info
,
974 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
975 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
977 int factor
= 1 + get_operand_specific_data (self
);
978 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
979 insert_field (FLD_SVE_imm4
, code
, info
->addr
.offset
.imm
/ factor
, 0);
983 /* Encode an SVE address [<base>, #<simm6>*<factor>, MUL VL],
984 where <simm6> is a 6-bit signed value and where <factor> is 1 plus
985 SELF's operand-dependent value. fields[0] specifies the field that
986 holds <base>. <simm6> is encoded in the SVE_imm6 field. */
988 aarch64_ins_sve_addr_ri_s6xvl (const aarch64_operand
*self
,
989 const aarch64_opnd_info
*info
,
991 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
992 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
994 int factor
= 1 + get_operand_specific_data (self
);
995 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
996 insert_field (FLD_SVE_imm6
, code
, info
->addr
.offset
.imm
/ factor
, 0);
1000 /* Encode an SVE address [<base>, #<simm9>*<factor>, MUL VL],
1001 where <simm9> is a 9-bit signed value and where <factor> is 1 plus
1002 SELF's operand-dependent value. fields[0] specifies the field that
1003 holds <base>. <simm9> is encoded in the concatenation of the SVE_imm6
1004 and imm3 fields, with imm3 being the less-significant part. */
1006 aarch64_ins_sve_addr_ri_s9xvl (const aarch64_operand
*self
,
1007 const aarch64_opnd_info
*info
,
1009 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1010 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1012 int factor
= 1 + get_operand_specific_data (self
);
1013 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1014 insert_fields (code
, info
->addr
.offset
.imm
/ factor
, 0,
1015 2, FLD_imm3
, FLD_SVE_imm6
);
1019 /* Encode an SVE address [X<n>, #<SVE_imm4> << <shift>], where <SVE_imm4>
1020 is a 4-bit signed number and where <shift> is SELF's operand-dependent
1021 value. fields[0] specifies the base register field. */
1023 aarch64_ins_sve_addr_ri_s4 (const aarch64_operand
*self
,
1024 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1025 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1026 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1028 int factor
= 1 << get_operand_specific_data (self
);
1029 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1030 insert_field (FLD_SVE_imm4
, code
, info
->addr
.offset
.imm
/ factor
, 0);
1034 /* Encode an SVE address [X<n>, #<SVE_imm6> << <shift>], where <SVE_imm6>
1035 is a 6-bit unsigned number and where <shift> is SELF's operand-dependent
1036 value. fields[0] specifies the base register field. */
1038 aarch64_ins_sve_addr_ri_u6 (const aarch64_operand
*self
,
1039 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1040 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1041 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1043 int factor
= 1 << get_operand_specific_data (self
);
1044 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1045 insert_field (FLD_SVE_imm6
, code
, info
->addr
.offset
.imm
/ factor
, 0);
1049 /* Encode an SVE address [X<n>, X<m>{, LSL #<shift>}], where <shift>
1050 is SELF's operand-dependent value. fields[0] specifies the base
1051 register field and fields[1] specifies the offset register field. */
1053 aarch64_ins_sve_addr_rr_lsl (const aarch64_operand
*self
,
1054 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1055 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1056 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1058 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1059 insert_field (self
->fields
[1], code
, info
->addr
.offset
.regno
, 0);
1063 /* Encode an SVE address [X<n>, Z<m>.<T>, (S|U)XTW {#<shift>}], where
1064 <shift> is SELF's operand-dependent value. fields[0] specifies the
1065 base register field, fields[1] specifies the offset register field and
1066 fields[2] is a single-bit field that selects SXTW over UXTW. */
1068 aarch64_ins_sve_addr_rz_xtw (const aarch64_operand
*self
,
1069 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1070 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1071 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1073 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1074 insert_field (self
->fields
[1], code
, info
->addr
.offset
.regno
, 0);
1075 if (info
->shifter
.kind
== AARCH64_MOD_UXTW
)
1076 insert_field (self
->fields
[2], code
, 0, 0);
1078 insert_field (self
->fields
[2], code
, 1, 0);
1082 /* Encode an SVE address [Z<n>.<T>, #<imm5> << <shift>], where <imm5> is a
1083 5-bit unsigned number and where <shift> is SELF's operand-dependent value.
1084 fields[0] specifies the base register field. */
1086 aarch64_ins_sve_addr_zi_u5 (const aarch64_operand
*self
,
1087 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1088 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1089 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1091 int factor
= 1 << get_operand_specific_data (self
);
1092 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1093 insert_field (FLD_imm5
, code
, info
->addr
.offset
.imm
/ factor
, 0);
1097 /* Encode an SVE address [Z<n>.<T>, Z<m>.<T>{, <modifier> {#<msz>}}],
1098 where <modifier> is fixed by the instruction and where <msz> is a
1099 2-bit unsigned number. fields[0] specifies the base register field
1100 and fields[1] specifies the offset register field. */
1102 aarch64_ext_sve_addr_zz (const aarch64_operand
*self
,
1103 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1104 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1106 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1107 insert_field (self
->fields
[1], code
, info
->addr
.offset
.regno
, 0);
1108 insert_field (FLD_SVE_msz
, code
, info
->shifter
.amount
, 0);
1112 /* Encode an SVE address [Z<n>.<T>, Z<m>.<T>{, LSL #<msz>}], where
1113 <msz> is a 2-bit unsigned number. fields[0] specifies the base register
1114 field and fields[1] specifies the offset register field. */
1116 aarch64_ins_sve_addr_zz_lsl (const aarch64_operand
*self
,
1117 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1118 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1119 aarch64_operand_error
*errors
)
1121 return aarch64_ext_sve_addr_zz (self
, info
, code
, errors
);
1124 /* Encode an SVE address [Z<n>.<T>, Z<m>.<T>, SXTW {#<msz>}], where
1125 <msz> is a 2-bit unsigned number. fields[0] specifies the base register
1126 field and fields[1] specifies the offset register field. */
1128 aarch64_ins_sve_addr_zz_sxtw (const aarch64_operand
*self
,
1129 const aarch64_opnd_info
*info
,
1131 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1132 aarch64_operand_error
*errors
)
1134 return aarch64_ext_sve_addr_zz (self
, info
, code
, errors
);
1137 /* Encode an SVE address [Z<n>.<T>, Z<m>.<T>, UXTW {#<msz>}], where
1138 <msz> is a 2-bit unsigned number. fields[0] specifies the base register
1139 field and fields[1] specifies the offset register field. */
1141 aarch64_ins_sve_addr_zz_uxtw (const aarch64_operand
*self
,
1142 const aarch64_opnd_info
*info
,
1144 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1145 aarch64_operand_error
*errors
)
1147 return aarch64_ext_sve_addr_zz (self
, info
, code
, errors
);
1150 /* Encode an SVE ADD/SUB immediate. */
1152 aarch64_ins_sve_aimm (const aarch64_operand
*self
,
1153 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1154 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1155 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1157 if (info
->shifter
.amount
== 8)
1158 insert_all_fields (self
, code
, (info
->imm
.value
& 0xff) | 256);
1159 else if (info
->imm
.value
!= 0 && (info
->imm
.value
& 0xff) == 0)
1160 insert_all_fields (self
, code
, ((info
->imm
.value
/ 256) & 0xff) | 256);
1162 insert_all_fields (self
, code
, info
->imm
.value
& 0xff);
1166 /* Encode an SVE CPY/DUP immediate. */
1168 aarch64_ins_sve_asimm (const aarch64_operand
*self
,
1169 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1170 const aarch64_inst
*inst
,
1171 aarch64_operand_error
*errors
)
1173 return aarch64_ins_sve_aimm (self
, info
, code
, inst
, errors
);
1176 /* Encode Zn[MM], where MM has a 7-bit triangular encoding. The fields
1177 array specifies which field to use for Zn. MM is encoded in the
1178 concatenation of imm5 and SVE_tszh, with imm5 being the less
1179 significant part. */
1181 aarch64_ins_sve_index (const aarch64_operand
*self
,
1182 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1183 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1184 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1186 unsigned int esize
= aarch64_get_qualifier_esize (info
->qualifier
);
1187 insert_field (self
->fields
[0], code
, info
->reglane
.regno
, 0);
1188 insert_fields (code
, (info
->reglane
.index
* 2 + 1) * esize
, 0,
1189 2, FLD_imm5
, FLD_SVE_tszh
);
1193 /* Encode a logical/bitmask immediate for the MOV alias of SVE DUPM. */
1195 aarch64_ins_sve_limm_mov (const aarch64_operand
*self
,
1196 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1197 const aarch64_inst
*inst
,
1198 aarch64_operand_error
*errors
)
1200 return aarch64_ins_limm (self
, info
, code
, inst
, errors
);
1203 /* Encode Zn[MM], where Zn occupies the least-significant part of the field
1204 and where MM occupies the most-significant part. The operand-dependent
1205 value specifies the number of bits in Zn. */
1207 aarch64_ins_sve_quad_index (const aarch64_operand
*self
,
1208 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1209 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1210 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1212 unsigned int reg_bits
= get_operand_specific_data (self
);
1213 assert (info
->reglane
.regno
< (1U << reg_bits
));
1214 unsigned int val
= (info
->reglane
.index
<< reg_bits
) + info
->reglane
.regno
;
1215 insert_all_fields (self
, code
, val
);
1219 /* Encode {Zn.<T> - Zm.<T>}. The fields array specifies which field
1222 aarch64_ins_sve_reglist (const aarch64_operand
*self
,
1223 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1224 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1225 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1227 insert_field (self
->fields
[0], code
, info
->reglist
.first_regno
, 0);
1231 /* Encode <pattern>{, MUL #<amount>}. The fields array specifies which
1232 fields to use for <pattern>. <amount> - 1 is encoded in the SVE_imm4
1235 aarch64_ins_sve_scale (const aarch64_operand
*self
,
1236 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1237 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1238 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1240 insert_all_fields (self
, code
, info
->imm
.value
);
1241 insert_field (FLD_SVE_imm4
, code
, info
->shifter
.amount
- 1, 0);
1245 /* Encode an SVE shift left immediate. */
1247 aarch64_ins_sve_shlimm (const aarch64_operand
*self
,
1248 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1249 const aarch64_inst
*inst
,
1250 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1252 const aarch64_opnd_info
*prev_operand
;
1255 assert (info
->idx
> 0);
1256 prev_operand
= &inst
->operands
[info
->idx
- 1];
1257 esize
= aarch64_get_qualifier_esize (prev_operand
->qualifier
);
1258 insert_all_fields (self
, code
, 8 * esize
+ info
->imm
.value
);
1262 /* Encode an SVE shift right immediate. */
1264 aarch64_ins_sve_shrimm (const aarch64_operand
*self
,
1265 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1266 const aarch64_inst
*inst
,
1267 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1269 const aarch64_opnd_info
*prev_operand
;
1272 unsigned int opnd_backshift
= get_operand_specific_data (self
);
1273 assert (info
->idx
>= (int)opnd_backshift
);
1274 prev_operand
= &inst
->operands
[info
->idx
- opnd_backshift
];
1275 esize
= aarch64_get_qualifier_esize (prev_operand
->qualifier
);
1276 insert_all_fields (self
, code
, 16 * esize
- info
->imm
.value
);
1280 /* Encode a single-bit immediate that selects between #0.5 and #1.0.
1281 The fields array specifies which field to use. */
1283 aarch64_ins_sve_float_half_one (const aarch64_operand
*self
,
1284 const aarch64_opnd_info
*info
,
1286 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1287 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1289 if (info
->imm
.value
== 0x3f000000)
1290 insert_field (self
->fields
[0], code
, 0, 0);
1292 insert_field (self
->fields
[0], code
, 1, 0);
1296 /* Encode a single-bit immediate that selects between #0.5 and #2.0.
1297 The fields array specifies which field to use. */
1299 aarch64_ins_sve_float_half_two (const aarch64_operand
*self
,
1300 const aarch64_opnd_info
*info
,
1302 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1303 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1305 if (info
->imm
.value
== 0x3f000000)
1306 insert_field (self
->fields
[0], code
, 0, 0);
1308 insert_field (self
->fields
[0], code
, 1, 0);
1312 /* Encode a single-bit immediate that selects between #0.0 and #1.0.
1313 The fields array specifies which field to use. */
1315 aarch64_ins_sve_float_zero_one (const aarch64_operand
*self
,
1316 const aarch64_opnd_info
*info
,
1318 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1319 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1321 if (info
->imm
.value
== 0)
1322 insert_field (self
->fields
[0], code
, 0, 0);
1324 insert_field (self
->fields
[0], code
, 1, 0);
1328 /* Miscellaneous encoding functions. */
1330 /* Encode size[0], i.e. bit 22, for
1331 e.g. FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
1334 encode_asimd_fcvt (aarch64_inst
*inst
)
1337 aarch64_field field
= {0, 0};
1338 enum aarch64_opnd_qualifier qualifier
;
1340 switch (inst
->opcode
->op
)
1344 /* FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
1345 qualifier
= inst
->operands
[1].qualifier
;
1349 /* FCVTL<Q> <Vd>.<Ta>, <Vn>.<Tb>. */
1350 qualifier
= inst
->operands
[0].qualifier
;
1355 assert (qualifier
== AARCH64_OPND_QLF_V_4S
1356 || qualifier
== AARCH64_OPND_QLF_V_2D
);
1357 value
= (qualifier
== AARCH64_OPND_QLF_V_4S
) ? 0 : 1;
1358 gen_sub_field (FLD_size
, 0, 1, &field
);
1359 insert_field_2 (&field
, &inst
->value
, value
, 0);
1362 /* Encode size[0], i.e. bit 22, for
1363 e.g. FCVTXN <Vb><d>, <Va><n>. */
1366 encode_asisd_fcvtxn (aarch64_inst
*inst
)
1368 aarch64_insn val
= 1;
1369 aarch64_field field
= {0, 0};
1370 assert (inst
->operands
[0].qualifier
== AARCH64_OPND_QLF_S_S
);
1371 gen_sub_field (FLD_size
, 0, 1, &field
);
1372 insert_field_2 (&field
, &inst
->value
, val
, 0);
1375 /* Encode the 'opc' field for e.g. FCVT <Dd>, <Sn>. */
1377 encode_fcvt (aarch64_inst
*inst
)
1380 const aarch64_field field
= {15, 2};
1383 switch (inst
->operands
[0].qualifier
)
1385 case AARCH64_OPND_QLF_S_S
: val
= 0; break;
1386 case AARCH64_OPND_QLF_S_D
: val
= 1; break;
1387 case AARCH64_OPND_QLF_S_H
: val
= 3; break;
1390 insert_field_2 (&field
, &inst
->value
, val
, 0);
1395 /* Return the index in qualifiers_list that INST is using. Should only
1396 be called once the qualifiers are known to be valid. */
1399 aarch64_get_variant (struct aarch64_inst
*inst
)
1401 int i
, nops
, variant
;
1403 nops
= aarch64_num_of_operands (inst
->opcode
);
1404 for (variant
= 0; variant
< AARCH64_MAX_QLF_SEQ_NUM
; ++variant
)
1406 for (i
= 0; i
< nops
; ++i
)
1407 if (inst
->opcode
->qualifiers_list
[variant
][i
]
1408 != inst
->operands
[i
].qualifier
)
1416 /* Do miscellaneous encodings that are not common enough to be driven by
1420 do_misc_encoding (aarch64_inst
*inst
)
1424 switch (inst
->opcode
->op
)
1433 encode_asimd_fcvt (inst
);
1436 encode_asisd_fcvtxn (inst
);
1440 /* Copy Pn to Pm and Pg. */
1441 value
= extract_field (FLD_SVE_Pn
, inst
->value
, 0);
1442 insert_field (FLD_SVE_Pm
, &inst
->value
, value
, 0);
1443 insert_field (FLD_SVE_Pg4_10
, &inst
->value
, value
, 0);
1446 /* Copy Zd to Zm. */
1447 value
= extract_field (FLD_SVE_Zd
, inst
->value
, 0);
1448 insert_field (FLD_SVE_Zm_16
, &inst
->value
, value
, 0);
1451 /* Fill in the zero immediate. */
1452 insert_fields (&inst
->value
, 1 << aarch64_get_variant (inst
), 0,
1453 2, FLD_imm5
, FLD_SVE_tszh
);
1456 /* Copy Zn to Zm. */
1457 value
= extract_field (FLD_SVE_Zn
, inst
->value
, 0);
1458 insert_field (FLD_SVE_Zm_16
, &inst
->value
, value
, 0);
1463 /* Copy Pd to Pm. */
1464 value
= extract_field (FLD_SVE_Pd
, inst
->value
, 0);
1465 insert_field (FLD_SVE_Pm
, &inst
->value
, value
, 0);
1467 case OP_MOVZS_P_P_P
:
1469 /* Copy Pn to Pm. */
1470 value
= extract_field (FLD_SVE_Pn
, inst
->value
, 0);
1471 insert_field (FLD_SVE_Pm
, &inst
->value
, value
, 0);
1473 case OP_NOTS_P_P_P_Z
:
1474 case OP_NOT_P_P_P_Z
:
1475 /* Copy Pg to Pm. */
1476 value
= extract_field (FLD_SVE_Pg4_10
, inst
->value
, 0);
1477 insert_field (FLD_SVE_Pm
, &inst
->value
, value
, 0);
1483 /* Encode the 'size' and 'Q' field for e.g. SHADD. */
1485 encode_sizeq (aarch64_inst
*inst
)
1488 enum aarch64_field_kind kind
;
1491 /* Get the index of the operand whose information we are going to use
1492 to encode the size and Q fields.
1493 This is deduced from the possible valid qualifier lists. */
1494 idx
= aarch64_select_operand_for_sizeq_field_coding (inst
->opcode
);
1495 DEBUG_TRACE ("idx: %d; qualifier: %s", idx
,
1496 aarch64_get_qualifier_name (inst
->operands
[idx
].qualifier
));
1497 sizeq
= aarch64_get_qualifier_standard_value (inst
->operands
[idx
].qualifier
);
1499 insert_field (FLD_Q
, &inst
->value
, sizeq
& 0x1, inst
->opcode
->mask
);
1501 if (inst
->opcode
->iclass
== asisdlse
1502 || inst
->opcode
->iclass
== asisdlsep
1503 || inst
->opcode
->iclass
== asisdlso
1504 || inst
->opcode
->iclass
== asisdlsop
)
1505 kind
= FLD_vldst_size
;
1508 insert_field (kind
, &inst
->value
, (sizeq
>> 1) & 0x3, inst
->opcode
->mask
);
1511 /* Opcodes that have fields shared by multiple operands are usually flagged
1512 with flags. In this function, we detect such flags and use the
1513 information in one of the related operands to do the encoding. The 'one'
1514 operand is not any operand but one of the operands that has the enough
1515 information for such an encoding. */
1518 do_special_encoding (struct aarch64_inst
*inst
)
1521 aarch64_insn value
= 0;
1523 DEBUG_TRACE ("enter with coding 0x%x", (uint32_t) inst
->value
);
1525 /* Condition for truly conditional executed instructions, e.g. b.cond. */
1526 if (inst
->opcode
->flags
& F_COND
)
1528 insert_field (FLD_cond2
, &inst
->value
, inst
->cond
->value
, 0);
1530 if (inst
->opcode
->flags
& F_SF
)
1532 idx
= select_operand_for_sf_field_coding (inst
->opcode
);
1533 value
= (inst
->operands
[idx
].qualifier
== AARCH64_OPND_QLF_X
1534 || inst
->operands
[idx
].qualifier
== AARCH64_OPND_QLF_SP
)
1536 insert_field (FLD_sf
, &inst
->value
, value
, 0);
1537 if (inst
->opcode
->flags
& F_N
)
1538 insert_field (FLD_N
, &inst
->value
, value
, inst
->opcode
->mask
);
1540 if (inst
->opcode
->flags
& F_LSE_SZ
)
1542 idx
= select_operand_for_sf_field_coding (inst
->opcode
);
1543 value
= (inst
->operands
[idx
].qualifier
== AARCH64_OPND_QLF_X
1544 || inst
->operands
[idx
].qualifier
== AARCH64_OPND_QLF_SP
)
1546 insert_field (FLD_lse_sz
, &inst
->value
, value
, 0);
1548 if (inst
->opcode
->flags
& F_SIZEQ
)
1549 encode_sizeq (inst
);
1550 if (inst
->opcode
->flags
& F_FPTYPE
)
1552 idx
= select_operand_for_fptype_field_coding (inst
->opcode
);
1553 switch (inst
->operands
[idx
].qualifier
)
1555 case AARCH64_OPND_QLF_S_S
: value
= 0; break;
1556 case AARCH64_OPND_QLF_S_D
: value
= 1; break;
1557 case AARCH64_OPND_QLF_S_H
: value
= 3; break;
1558 default: assert (0);
1560 insert_field (FLD_type
, &inst
->value
, value
, 0);
1562 if (inst
->opcode
->flags
& F_SSIZE
)
1564 enum aarch64_opnd_qualifier qualifier
;
1565 idx
= select_operand_for_scalar_size_field_coding (inst
->opcode
);
1566 qualifier
= inst
->operands
[idx
].qualifier
;
1567 assert (qualifier
>= AARCH64_OPND_QLF_S_B
1568 && qualifier
<= AARCH64_OPND_QLF_S_Q
);
1569 value
= aarch64_get_qualifier_standard_value (qualifier
);
1570 insert_field (FLD_size
, &inst
->value
, value
, inst
->opcode
->mask
);
1572 if (inst
->opcode
->flags
& F_T
)
1574 int num
; /* num of consecutive '0's on the right side of imm5<3:0>. */
1575 aarch64_field field
= {0, 0};
1576 enum aarch64_opnd_qualifier qualifier
;
1579 qualifier
= inst
->operands
[idx
].qualifier
;
1580 assert (aarch64_get_operand_class (inst
->opcode
->operands
[0])
1581 == AARCH64_OPND_CLASS_SIMD_REG
1582 && qualifier
>= AARCH64_OPND_QLF_V_8B
1583 && qualifier
<= AARCH64_OPND_QLF_V_2D
);
1594 value
= aarch64_get_qualifier_standard_value (qualifier
);
1595 insert_field (FLD_Q
, &inst
->value
, value
& 0x1, inst
->opcode
->mask
);
1596 num
= (int) value
>> 1;
1597 assert (num
>= 0 && num
<= 3);
1598 gen_sub_field (FLD_imm5
, 0, num
+ 1, &field
);
1599 insert_field_2 (&field
, &inst
->value
, 1 << num
, inst
->opcode
->mask
);
1601 if (inst
->opcode
->flags
& F_GPRSIZE_IN_Q
)
1603 /* Use Rt to encode in the case of e.g.
1604 STXP <Ws>, <Xt1>, <Xt2>, [<Xn|SP>{,#0}]. */
1605 enum aarch64_opnd_qualifier qualifier
;
1606 idx
= aarch64_operand_index (inst
->opcode
->operands
, AARCH64_OPND_Rt
);
1608 /* Otherwise use the result operand, which has to be a integer
1611 assert (idx
== 0 || idx
== 1);
1612 assert (aarch64_get_operand_class (inst
->opcode
->operands
[idx
])
1613 == AARCH64_OPND_CLASS_INT_REG
);
1614 qualifier
= inst
->operands
[idx
].qualifier
;
1615 insert_field (FLD_Q
, &inst
->value
,
1616 aarch64_get_qualifier_standard_value (qualifier
), 0);
1618 if (inst
->opcode
->flags
& F_LDS_SIZE
)
1620 /* e.g. LDRSB <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
1621 enum aarch64_opnd_qualifier qualifier
;
1622 aarch64_field field
= {0, 0};
1623 assert (aarch64_get_operand_class (inst
->opcode
->operands
[0])
1624 == AARCH64_OPND_CLASS_INT_REG
);
1625 gen_sub_field (FLD_opc
, 0, 1, &field
);
1626 qualifier
= inst
->operands
[0].qualifier
;
1627 insert_field_2 (&field
, &inst
->value
,
1628 1 - aarch64_get_qualifier_standard_value (qualifier
), 0);
1630 /* Miscellaneous encoding as the last step. */
1631 if (inst
->opcode
->flags
& F_MISC
)
1632 do_misc_encoding (inst
);
1634 DEBUG_TRACE ("exit with coding 0x%x", (uint32_t) inst
->value
);
1637 /* Some instructions (including all SVE ones) use the instruction class
1638 to describe how a qualifiers_list index is represented in the instruction
1639 encoding. If INST is such an instruction, encode the chosen qualifier
1643 aarch64_encode_variant_using_iclass (struct aarch64_inst
*inst
)
1646 switch (inst
->opcode
->iclass
)
1649 insert_fields (&inst
->value
, aarch64_get_variant (inst
),
1650 0, 2, FLD_SVE_M_14
, FLD_size
);
1654 case sve_shift_pred
:
1655 case sve_shift_unpred
:
1656 case sve_shift_tsz_hsd
:
1657 case sve_shift_tsz_bhsd
:
1658 /* For indices and shift amounts, the variant is encoded as
1659 part of the immediate. */
1663 /* For sve_limm, the .B, .H, and .S forms are just a convenience
1664 and depend on the immediate. They don't have a separate
1669 /* sve_misc instructions have only a single variant. */
1673 insert_fields (&inst
->value
, aarch64_get_variant (inst
),
1674 0, 2, FLD_SVE_M_16
, FLD_size
);
1678 insert_field (FLD_SVE_M_4
, &inst
->value
, aarch64_get_variant (inst
), 0);
1683 insert_field (FLD_size
, &inst
->value
, aarch64_get_variant (inst
), 0);
1687 insert_field (FLD_size
, &inst
->value
, aarch64_get_variant (inst
) + 1, 0);
1692 insert_field (FLD_SVE_sz
, &inst
->value
, aarch64_get_variant (inst
), 0);
1696 insert_field (FLD_SVE_sz2
, &inst
->value
, aarch64_get_variant (inst
), 0);
1700 insert_field (FLD_SVE_size
, &inst
->value
,
1701 aarch64_get_variant (inst
) + 1, 0);
1704 case sve_size_tsz_bhs
:
1705 insert_fields (&inst
->value
,
1706 (1 << aarch64_get_variant (inst
)),
1707 0, 2, FLD_SVE_tszl_19
, FLD_SVE_sz
);
1711 variant
= aarch64_get_variant (inst
) + 1;
1714 insert_field (FLD_size
, &inst
->value
, variant
, 0);
1722 /* Converters converting an alias opcode instruction to its real form. */
1724 /* ROR <Wd>, <Ws>, #<shift>
1726 EXTR <Wd>, <Ws>, <Ws>, #<shift>. */
1728 convert_ror_to_extr (aarch64_inst
*inst
)
1730 copy_operand_info (inst
, 3, 2);
1731 copy_operand_info (inst
, 2, 1);
1734 /* UXTL<Q> <Vd>.<Ta>, <Vn>.<Tb>
1736 USHLL<Q> <Vd>.<Ta>, <Vn>.<Tb>, #0. */
1738 convert_xtl_to_shll (aarch64_inst
*inst
)
1740 inst
->operands
[2].qualifier
= inst
->operands
[1].qualifier
;
1741 inst
->operands
[2].imm
.value
= 0;
1745 LSR <Xd>, <Xn>, #<shift>
1747 UBFM <Xd>, <Xn>, #<shift>, #63. */
1749 convert_sr_to_bfm (aarch64_inst
*inst
)
1751 inst
->operands
[3].imm
.value
=
1752 inst
->operands
[2].qualifier
== AARCH64_OPND_QLF_imm_0_31
? 31 : 63;
1755 /* Convert MOV to ORR. */
1757 convert_mov_to_orr (aarch64_inst
*inst
)
1759 /* MOV <Vd>.<T>, <Vn>.<T>
1761 ORR <Vd>.<T>, <Vn>.<T>, <Vn>.<T>. */
1762 copy_operand_info (inst
, 2, 1);
1765 /* When <imms> >= <immr>, the instruction written:
1766 SBFX <Xd>, <Xn>, #<lsb>, #<width>
1768 SBFM <Xd>, <Xn>, #<lsb>, #(<lsb>+<width>-1). */
1771 convert_bfx_to_bfm (aarch64_inst
*inst
)
1775 /* Convert the operand. */
1776 lsb
= inst
->operands
[2].imm
.value
;
1777 width
= inst
->operands
[3].imm
.value
;
1778 inst
->operands
[2].imm
.value
= lsb
;
1779 inst
->operands
[3].imm
.value
= lsb
+ width
- 1;
1782 /* When <imms> < <immr>, the instruction written:
1783 SBFIZ <Xd>, <Xn>, #<lsb>, #<width>
1785 SBFM <Xd>, <Xn>, #((64-<lsb>)&0x3f), #(<width>-1). */
1788 convert_bfi_to_bfm (aarch64_inst
*inst
)
1792 /* Convert the operand. */
1793 lsb
= inst
->operands
[2].imm
.value
;
1794 width
= inst
->operands
[3].imm
.value
;
1795 if (inst
->operands
[2].qualifier
== AARCH64_OPND_QLF_imm_0_31
)
1797 inst
->operands
[2].imm
.value
= (32 - lsb
) & 0x1f;
1798 inst
->operands
[3].imm
.value
= width
- 1;
1802 inst
->operands
[2].imm
.value
= (64 - lsb
) & 0x3f;
1803 inst
->operands
[3].imm
.value
= width
- 1;
1807 /* The instruction written:
1808 BFC <Xd>, #<lsb>, #<width>
1810 BFM <Xd>, XZR, #((64-<lsb>)&0x3f), #(<width>-1). */
1813 convert_bfc_to_bfm (aarch64_inst
*inst
)
1818 copy_operand_info (inst
, 3, 2);
1819 copy_operand_info (inst
, 2, 1);
1820 copy_operand_info (inst
, 1, 0);
1821 inst
->operands
[1].reg
.regno
= 0x1f;
1823 /* Convert the immediate operand. */
1824 lsb
= inst
->operands
[2].imm
.value
;
1825 width
= inst
->operands
[3].imm
.value
;
1826 if (inst
->operands
[2].qualifier
== AARCH64_OPND_QLF_imm_0_31
)
1828 inst
->operands
[2].imm
.value
= (32 - lsb
) & 0x1f;
1829 inst
->operands
[3].imm
.value
= width
- 1;
1833 inst
->operands
[2].imm
.value
= (64 - lsb
) & 0x3f;
1834 inst
->operands
[3].imm
.value
= width
- 1;
1838 /* The instruction written:
1839 LSL <Xd>, <Xn>, #<shift>
1841 UBFM <Xd>, <Xn>, #((64-<shift>)&0x3f), #(63-<shift>). */
1844 convert_lsl_to_ubfm (aarch64_inst
*inst
)
1846 int64_t shift
= inst
->operands
[2].imm
.value
;
1848 if (inst
->operands
[2].qualifier
== AARCH64_OPND_QLF_imm_0_31
)
1850 inst
->operands
[2].imm
.value
= (32 - shift
) & 0x1f;
1851 inst
->operands
[3].imm
.value
= 31 - shift
;
1855 inst
->operands
[2].imm
.value
= (64 - shift
) & 0x3f;
1856 inst
->operands
[3].imm
.value
= 63 - shift
;
1860 /* CINC <Wd>, <Wn>, <cond>
1862 CSINC <Wd>, <Wn>, <Wn>, invert(<cond>). */
1865 convert_to_csel (aarch64_inst
*inst
)
1867 copy_operand_info (inst
, 3, 2);
1868 copy_operand_info (inst
, 2, 1);
1869 inst
->operands
[3].cond
= get_inverted_cond (inst
->operands
[3].cond
);
1872 /* CSET <Wd>, <cond>
1874 CSINC <Wd>, WZR, WZR, invert(<cond>). */
1877 convert_cset_to_csinc (aarch64_inst
*inst
)
1879 copy_operand_info (inst
, 3, 1);
1880 copy_operand_info (inst
, 2, 0);
1881 copy_operand_info (inst
, 1, 0);
1882 inst
->operands
[1].reg
.regno
= 0x1f;
1883 inst
->operands
[2].reg
.regno
= 0x1f;
1884 inst
->operands
[3].cond
= get_inverted_cond (inst
->operands
[3].cond
);
1889 MOVZ <Wd>, #<imm16>, LSL #<shift>. */
1892 convert_mov_to_movewide (aarch64_inst
*inst
)
1895 uint32_t shift_amount
;
1898 switch (inst
->opcode
->op
)
1900 case OP_MOV_IMM_WIDE
:
1901 value
= inst
->operands
[1].imm
.value
;
1903 case OP_MOV_IMM_WIDEN
:
1904 value
= ~inst
->operands
[1].imm
.value
;
1909 inst
->operands
[1].type
= AARCH64_OPND_HALF
;
1910 is32
= inst
->operands
[0].qualifier
== AARCH64_OPND_QLF_W
;
1911 if (! aarch64_wide_constant_p (value
, is32
, &shift_amount
))
1912 /* The constraint check should have guaranteed this wouldn't happen. */
1914 value
>>= shift_amount
;
1916 inst
->operands
[1].imm
.value
= value
;
1917 inst
->operands
[1].shifter
.kind
= AARCH64_MOD_LSL
;
1918 inst
->operands
[1].shifter
.amount
= shift_amount
;
1923 ORR <Wd>, WZR, #<imm>. */
1926 convert_mov_to_movebitmask (aarch64_inst
*inst
)
1928 copy_operand_info (inst
, 2, 1);
1929 inst
->operands
[1].reg
.regno
= 0x1f;
1930 inst
->operands
[1].skip
= 0;
1933 /* Some alias opcodes are assembled by being converted to their real-form. */
1936 convert_to_real (aarch64_inst
*inst
, const aarch64_opcode
*real
)
1938 const aarch64_opcode
*alias
= inst
->opcode
;
1940 if ((alias
->flags
& F_CONV
) == 0)
1941 goto convert_to_real_return
;
1947 convert_sr_to_bfm (inst
);
1950 convert_lsl_to_ubfm (inst
);
1955 convert_to_csel (inst
);
1959 convert_cset_to_csinc (inst
);
1964 convert_bfx_to_bfm (inst
);
1969 convert_bfi_to_bfm (inst
);
1972 convert_bfc_to_bfm (inst
);
1975 convert_mov_to_orr (inst
);
1977 case OP_MOV_IMM_WIDE
:
1978 case OP_MOV_IMM_WIDEN
:
1979 convert_mov_to_movewide (inst
);
1981 case OP_MOV_IMM_LOG
:
1982 convert_mov_to_movebitmask (inst
);
1985 convert_ror_to_extr (inst
);
1991 convert_xtl_to_shll (inst
);
1997 convert_to_real_return
:
1998 aarch64_replace_opcode (inst
, real
);
2001 /* Encode *INST_ORI of the opcode code OPCODE.
2002 Return the encoded result in *CODE and if QLF_SEQ is not NULL, return the
2003 matched operand qualifier sequence in *QLF_SEQ. */
2006 aarch64_opcode_encode (const aarch64_opcode
*opcode
,
2007 const aarch64_inst
*inst_ori
, aarch64_insn
*code
,
2008 aarch64_opnd_qualifier_t
*qlf_seq
,
2009 aarch64_operand_error
*mismatch_detail
,
2010 aarch64_instr_sequence
* insn_sequence
)
2013 const aarch64_opcode
*aliased
;
2014 aarch64_inst copy
, *inst
;
2016 DEBUG_TRACE ("enter with %s", opcode
->name
);
2018 /* Create a copy of *INST_ORI, so that we can do any change we want. */
2022 assert (inst
->opcode
== NULL
|| inst
->opcode
== opcode
);
2023 if (inst
->opcode
== NULL
)
2024 inst
->opcode
= opcode
;
2026 /* Constrain the operands.
2027 After passing this, the encoding is guaranteed to succeed. */
2028 if (aarch64_match_operands_constraint (inst
, mismatch_detail
) == 0)
2030 DEBUG_TRACE ("FAIL since operand constraint not met");
2034 /* Get the base value.
2035 Note: this has to be before the aliasing handling below in order to
2036 get the base value from the alias opcode before we move on to the
2037 aliased opcode for encoding. */
2038 inst
->value
= opcode
->opcode
;
2040 /* No need to do anything else if the opcode does not have any operand. */
2041 if (aarch64_num_of_operands (opcode
) == 0)
2044 /* Assign operand indexes and check types. Also put the matched
2045 operand qualifiers in *QLF_SEQ to return. */
2046 for (i
= 0; i
< AARCH64_MAX_OPND_NUM
; ++i
)
2048 assert (opcode
->operands
[i
] == inst
->operands
[i
].type
);
2049 inst
->operands
[i
].idx
= i
;
2050 if (qlf_seq
!= NULL
)
2051 *qlf_seq
= inst
->operands
[i
].qualifier
;
2054 aliased
= aarch64_find_real_opcode (opcode
);
2055 /* If the opcode is an alias and it does not ask for direct encoding by
2056 itself, the instruction will be transformed to the form of real opcode
2057 and the encoding will be carried out using the rules for the aliased
2059 if (aliased
!= NULL
&& (opcode
->flags
& F_CONV
))
2061 DEBUG_TRACE ("real opcode '%s' has been found for the alias %s",
2062 aliased
->name
, opcode
->name
);
2063 /* Convert the operands to the form of the real opcode. */
2064 convert_to_real (inst
, aliased
);
2068 aarch64_opnd_info
*info
= inst
->operands
;
2070 /* Call the inserter of each operand. */
2071 for (i
= 0; i
< AARCH64_MAX_OPND_NUM
; ++i
, ++info
)
2073 const aarch64_operand
*opnd
;
2074 enum aarch64_opnd type
= opcode
->operands
[i
];
2075 if (type
== AARCH64_OPND_NIL
)
2079 DEBUG_TRACE ("skip the incomplete operand %d", i
);
2082 opnd
= &aarch64_operands
[type
];
2083 if (operand_has_inserter (opnd
)
2084 && !aarch64_insert_operand (opnd
, info
, &inst
->value
, inst
,
2089 /* Call opcode encoders indicated by flags. */
2090 if (opcode_has_special_coder (opcode
))
2091 do_special_encoding (inst
);
2093 /* Possibly use the instruction class to encode the chosen qualifier
2095 aarch64_encode_variant_using_iclass (inst
);
2097 /* Run a verifier if the instruction has one set. */
2098 if (opcode
->verifier
)
2100 enum err_type result
= opcode
->verifier (inst
, *code
, 0, TRUE
,
2101 mismatch_detail
, insn_sequence
);
2113 /* Always run constrain verifiers, this is needed because constrains need to
2114 maintain a global state. Regardless if the instruction has the flag set
2116 enum err_type result
= verify_constraints (inst
, *code
, 0, TRUE
,
2117 mismatch_detail
, insn_sequence
);
2130 DEBUG_TRACE ("exit with %s", opcode
->name
);
2132 *code
= inst
->value
;