1 /* aarch64-asm.c -- AArch64 assembler support.
2 Copyright (C) 2012-2020 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
)
549 uint64_t imm
= info
->imm
.value
;
550 int esize
= aarch64_get_qualifier_esize (inst
->operands
[0].qualifier
);
554 /* The constraint check should have guaranteed this wouldn't happen. */
555 assert (aarch64_logical_immediate_p (imm
, esize
, &value
));
557 insert_fields (code
, value
, 0, 3, self
->fields
[2], self
->fields
[1],
562 /* Insert logical/bitmask immediate for e.g. the last operand in
563 ORR <Wd|WSP>, <Wn>, #<imm>. */
565 aarch64_ins_limm (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
566 aarch64_insn
*code
, const aarch64_inst
*inst
,
567 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
569 return aarch64_ins_limm_1 (self
, info
, code
, inst
,
570 inst
->opcode
->op
== OP_BIC
, errors
);
573 /* Insert a logical/bitmask immediate for the BIC alias of AND (etc.). */
575 aarch64_ins_inv_limm (const aarch64_operand
*self
,
576 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
577 const aarch64_inst
*inst
,
578 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
580 return aarch64_ins_limm_1 (self
, info
, code
, inst
, TRUE
, errors
);
583 /* Encode Ft for e.g. STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]
584 or LDP <Qt1>, <Qt2>, [<Xn|SP>], #<imm>. */
586 aarch64_ins_ft (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
587 aarch64_insn
*code
, const aarch64_inst
*inst
,
588 aarch64_operand_error
*errors
)
590 aarch64_insn value
= 0;
592 assert (info
->idx
== 0);
595 aarch64_ins_regno (self
, info
, code
, inst
, errors
);
596 if (inst
->opcode
->iclass
== ldstpair_indexed
597 || inst
->opcode
->iclass
== ldstnapair_offs
598 || inst
->opcode
->iclass
== ldstpair_off
599 || inst
->opcode
->iclass
== loadlit
)
602 switch (info
->qualifier
)
604 case AARCH64_OPND_QLF_S_S
: value
= 0; break;
605 case AARCH64_OPND_QLF_S_D
: value
= 1; break;
606 case AARCH64_OPND_QLF_S_Q
: value
= 2; break;
609 insert_field (FLD_ldst_size
, code
, value
, 0);
614 value
= aarch64_get_qualifier_standard_value (info
->qualifier
);
615 insert_fields (code
, value
, 0, 2, FLD_ldst_size
, FLD_opc1
);
621 /* Encode the address operand for e.g. STXRB <Ws>, <Wt>, [<Xn|SP>{,#0}]. */
623 aarch64_ins_addr_simple (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
624 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
625 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
626 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
629 insert_field (FLD_Rn
, code
, info
->addr
.base_regno
, 0);
633 /* Encode the address operand for e.g.
634 STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
636 aarch64_ins_addr_regoff (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
637 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
638 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
639 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
642 enum aarch64_modifier_kind kind
= info
->shifter
.kind
;
645 insert_field (FLD_Rn
, code
, info
->addr
.base_regno
, 0);
647 insert_field (FLD_Rm
, code
, info
->addr
.offset
.regno
, 0);
649 if (kind
== AARCH64_MOD_LSL
)
650 kind
= AARCH64_MOD_UXTX
; /* Trick to enable the table-driven. */
651 insert_field (FLD_option
, code
, aarch64_get_operand_modifier_value (kind
), 0);
653 if (info
->qualifier
!= AARCH64_OPND_QLF_S_B
)
654 S
= info
->shifter
.amount
!= 0;
656 /* For STR <Bt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}},
660 Must be #0 if <extend> is explicitly LSL. */
661 S
= info
->shifter
.operator_present
&& info
->shifter
.amount_present
;
662 insert_field (FLD_S
, code
, S
, 0);
667 /* Encode the address operand for e.g.
668 stlur <Xt>, [<Xn|SP>{, <amount>}]. */
670 aarch64_ins_addr_offset (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
671 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
672 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
673 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
676 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
679 int imm
= info
->addr
.offset
.imm
;
680 insert_field (self
->fields
[1], code
, imm
, 0);
683 if (info
->addr
.writeback
)
685 assert (info
->addr
.preind
== 1 && info
->addr
.postind
== 0);
686 insert_field (self
->fields
[2], code
, 1, 0);
691 /* Encode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>, #<simm>]!. */
693 aarch64_ins_addr_simm (const aarch64_operand
*self
,
694 const aarch64_opnd_info
*info
,
696 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
697 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
702 insert_field (FLD_Rn
, code
, info
->addr
.base_regno
, 0);
703 /* simm (imm9 or imm7) */
704 imm
= info
->addr
.offset
.imm
;
705 if (self
->fields
[0] == FLD_imm7
706 || info
->qualifier
== AARCH64_OPND_QLF_imm_tag
)
707 /* scaled immediate in ld/st pair instructions.. */
708 imm
>>= get_logsz (aarch64_get_qualifier_esize (info
->qualifier
));
709 insert_field (self
->fields
[0], code
, imm
, 0);
710 /* pre/post- index */
711 if (info
->addr
.writeback
)
713 assert (inst
->opcode
->iclass
!= ldst_unscaled
714 && inst
->opcode
->iclass
!= ldstnapair_offs
715 && inst
->opcode
->iclass
!= ldstpair_off
716 && inst
->opcode
->iclass
!= ldst_unpriv
);
717 assert (info
->addr
.preind
!= info
->addr
.postind
);
718 if (info
->addr
.preind
)
719 insert_field (self
->fields
[1], code
, 1, 0);
725 /* Encode the address operand for e.g. LDRAA <Xt>, [<Xn|SP>{, #<simm>}]. */
727 aarch64_ins_addr_simm10 (const aarch64_operand
*self
,
728 const aarch64_opnd_info
*info
,
730 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
731 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
736 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
738 imm
= info
->addr
.offset
.imm
>> 3;
739 insert_field (self
->fields
[1], code
, imm
>> 9, 0);
740 insert_field (self
->fields
[2], code
, imm
, 0);
742 if (info
->addr
.writeback
)
744 assert (info
->addr
.preind
== 1 && info
->addr
.postind
== 0);
745 insert_field (self
->fields
[3], code
, 1, 0);
750 /* Encode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>{, #<pimm>}]. */
752 aarch64_ins_addr_uimm12 (const aarch64_operand
*self
,
753 const aarch64_opnd_info
*info
,
755 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
756 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
758 int shift
= get_logsz (aarch64_get_qualifier_esize (info
->qualifier
));
761 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
763 insert_field (self
->fields
[1], code
,info
->addr
.offset
.imm
>> shift
, 0);
767 /* Encode the address operand for e.g.
768 LD1 {<Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>}, [<Xn|SP>], <Xm|#<amount>>. */
770 aarch64_ins_simd_addr_post (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
771 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
772 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
773 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
776 insert_field (FLD_Rn
, code
, info
->addr
.base_regno
, 0);
778 if (info
->addr
.offset
.is_reg
)
779 insert_field (FLD_Rm
, code
, info
->addr
.offset
.regno
, 0);
781 insert_field (FLD_Rm
, code
, 0x1f, 0);
785 /* Encode the condition operand for e.g. CSEL <Xd>, <Xn>, <Xm>, <cond>. */
787 aarch64_ins_cond (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
788 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
789 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
790 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
793 insert_field (FLD_cond
, code
, info
->cond
->value
, 0);
797 /* Encode the system register operand for e.g. MRS <Xt>, <systemreg>. */
799 aarch64_ins_sysreg (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
800 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
801 const aarch64_inst
*inst
,
802 aarch64_operand_error
*detail ATTRIBUTE_UNUSED
)
804 /* If a system instruction check if we have any restrictions on which
805 registers it can use. */
806 if (inst
->opcode
->iclass
== ic_system
)
808 uint64_t opcode_flags
809 = inst
->opcode
->flags
& (F_SYS_READ
| F_SYS_WRITE
);
810 uint32_t sysreg_flags
811 = info
->sysreg
.flags
& (F_REG_READ
| F_REG_WRITE
);
813 /* Check to see if it's read-only, else check if it's write only.
814 if it's both or unspecified don't care. */
815 if (opcode_flags
== F_SYS_READ
817 && sysreg_flags
!= F_REG_READ
)
819 detail
->kind
= AARCH64_OPDE_SYNTAX_ERROR
;
820 detail
->error
= _("specified register cannot be read from");
821 detail
->index
= info
->idx
;
822 detail
->non_fatal
= TRUE
;
824 else if (opcode_flags
== F_SYS_WRITE
826 && sysreg_flags
!= F_REG_WRITE
)
828 detail
->kind
= AARCH64_OPDE_SYNTAX_ERROR
;
829 detail
->error
= _("specified register cannot be written to");
830 detail
->index
= info
->idx
;
831 detail
->non_fatal
= TRUE
;
834 /* op0:op1:CRn:CRm:op2 */
835 insert_fields (code
, info
->sysreg
.value
, inst
->opcode
->mask
, 5,
836 FLD_op2
, FLD_CRm
, FLD_CRn
, FLD_op1
, FLD_op0
);
840 /* Encode the PSTATE field operand for e.g. MSR <pstatefield>, #<imm>. */
842 aarch64_ins_pstatefield (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
843 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
844 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
845 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
848 insert_fields (code
, info
->pstatefield
, inst
->opcode
->mask
, 2,
853 /* Encode the system instruction op operand for e.g. AT <at_op>, <Xt>. */
855 aarch64_ins_sysins_op (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
856 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
857 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
858 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
860 /* op1:CRn:CRm:op2 */
861 insert_fields (code
, info
->sysins_op
->value
, inst
->opcode
->mask
, 4,
862 FLD_op2
, FLD_CRm
, FLD_CRn
, FLD_op1
);
866 /* Encode the memory barrier option operand for e.g. DMB <option>|#<imm>. */
869 aarch64_ins_barrier (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
870 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
871 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
872 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
875 insert_field (FLD_CRm
, code
, info
->barrier
->value
, 0);
879 /* Encode the memory barrier option operand for DSB <option>nXS|#<imm>. */
882 aarch64_ins_barrier_dsb_nxs (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
883 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
884 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
885 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
887 /* For the DSB nXS barrier variant: is a 5-bit unsigned immediate,
888 encoded in CRm<3:2>. */
889 aarch64_insn value
= (info
->barrier
->value
>> 2) - 4;
890 insert_field (FLD_CRm_dsb_nxs
, code
, value
, 0);
894 /* Encode the prefetch operation option operand for e.g.
895 PRFM <prfop>, [<Xn|SP>{, #<pimm>}]. */
898 aarch64_ins_prfop (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
899 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
900 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
901 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
904 insert_field (FLD_Rt
, code
, info
->prfop
->value
, 0);
908 /* Encode the hint number for instructions that alias HINT but take an
912 aarch64_ins_hint (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
913 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
914 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
915 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
918 insert_fields (code
, info
->hint_option
->value
, 0, 2, FLD_op2
, FLD_CRm
);
922 /* Encode the extended register operand for e.g.
923 STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
925 aarch64_ins_reg_extended (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
926 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
927 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
928 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
930 enum aarch64_modifier_kind kind
;
933 insert_field (FLD_Rm
, code
, info
->reg
.regno
, 0);
935 kind
= info
->shifter
.kind
;
936 if (kind
== AARCH64_MOD_LSL
)
937 kind
= info
->qualifier
== AARCH64_OPND_QLF_W
938 ? AARCH64_MOD_UXTW
: AARCH64_MOD_UXTX
;
939 insert_field (FLD_option
, code
, aarch64_get_operand_modifier_value (kind
), 0);
941 insert_field (FLD_imm3
, code
, info
->shifter
.amount
, 0);
946 /* Encode the shifted register operand for e.g.
947 SUBS <Xd>, <Xn>, <Xm> {, <shift> #<amount>}. */
949 aarch64_ins_reg_shifted (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
950 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
951 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
952 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
955 insert_field (FLD_Rm
, code
, info
->reg
.regno
, 0);
957 insert_field (FLD_shift
, code
,
958 aarch64_get_operand_modifier_value (info
->shifter
.kind
), 0);
960 insert_field (FLD_imm6
, code
, info
->shifter
.amount
, 0);
965 /* Encode an SVE address [<base>, #<simm4>*<factor>, MUL VL],
966 where <simm4> is a 4-bit signed value and where <factor> is 1 plus
967 SELF's operand-dependent value. fields[0] specifies the field that
968 holds <base>. <simm4> is encoded in the SVE_imm4 field. */
970 aarch64_ins_sve_addr_ri_s4xvl (const aarch64_operand
*self
,
971 const aarch64_opnd_info
*info
,
973 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
974 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
976 int factor
= 1 + get_operand_specific_data (self
);
977 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
978 insert_field (FLD_SVE_imm4
, code
, info
->addr
.offset
.imm
/ factor
, 0);
982 /* Encode an SVE address [<base>, #<simm6>*<factor>, MUL VL],
983 where <simm6> is a 6-bit signed value and where <factor> is 1 plus
984 SELF's operand-dependent value. fields[0] specifies the field that
985 holds <base>. <simm6> is encoded in the SVE_imm6 field. */
987 aarch64_ins_sve_addr_ri_s6xvl (const aarch64_operand
*self
,
988 const aarch64_opnd_info
*info
,
990 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
991 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
993 int factor
= 1 + get_operand_specific_data (self
);
994 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
995 insert_field (FLD_SVE_imm6
, code
, info
->addr
.offset
.imm
/ factor
, 0);
999 /* Encode an SVE address [<base>, #<simm9>*<factor>, MUL VL],
1000 where <simm9> is a 9-bit signed value and where <factor> is 1 plus
1001 SELF's operand-dependent value. fields[0] specifies the field that
1002 holds <base>. <simm9> is encoded in the concatenation of the SVE_imm6
1003 and imm3 fields, with imm3 being the less-significant part. */
1005 aarch64_ins_sve_addr_ri_s9xvl (const aarch64_operand
*self
,
1006 const aarch64_opnd_info
*info
,
1008 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1009 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1011 int factor
= 1 + get_operand_specific_data (self
);
1012 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1013 insert_fields (code
, info
->addr
.offset
.imm
/ factor
, 0,
1014 2, FLD_imm3
, FLD_SVE_imm6
);
1018 /* Encode an SVE address [X<n>, #<SVE_imm4> << <shift>], where <SVE_imm4>
1019 is a 4-bit signed number and where <shift> is SELF's operand-dependent
1020 value. fields[0] specifies the base register field. */
1022 aarch64_ins_sve_addr_ri_s4 (const aarch64_operand
*self
,
1023 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1024 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1025 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1027 int factor
= 1 << get_operand_specific_data (self
);
1028 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1029 insert_field (FLD_SVE_imm4
, code
, info
->addr
.offset
.imm
/ factor
, 0);
1033 /* Encode an SVE address [X<n>, #<SVE_imm6> << <shift>], where <SVE_imm6>
1034 is a 6-bit unsigned number and where <shift> is SELF's operand-dependent
1035 value. fields[0] specifies the base register field. */
1037 aarch64_ins_sve_addr_ri_u6 (const aarch64_operand
*self
,
1038 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1039 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1040 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1042 int factor
= 1 << get_operand_specific_data (self
);
1043 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1044 insert_field (FLD_SVE_imm6
, code
, info
->addr
.offset
.imm
/ factor
, 0);
1048 /* Encode an SVE address [X<n>, X<m>{, LSL #<shift>}], where <shift>
1049 is SELF's operand-dependent value. fields[0] specifies the base
1050 register field and fields[1] specifies the offset register field. */
1052 aarch64_ins_sve_addr_rr_lsl (const aarch64_operand
*self
,
1053 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1054 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1055 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1057 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1058 insert_field (self
->fields
[1], code
, info
->addr
.offset
.regno
, 0);
1062 /* Encode an SVE address [X<n>, Z<m>.<T>, (S|U)XTW {#<shift>}], where
1063 <shift> is SELF's operand-dependent value. fields[0] specifies the
1064 base register field, fields[1] specifies the offset register field and
1065 fields[2] is a single-bit field that selects SXTW over UXTW. */
1067 aarch64_ins_sve_addr_rz_xtw (const aarch64_operand
*self
,
1068 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1069 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1070 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1072 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1073 insert_field (self
->fields
[1], code
, info
->addr
.offset
.regno
, 0);
1074 if (info
->shifter
.kind
== AARCH64_MOD_UXTW
)
1075 insert_field (self
->fields
[2], code
, 0, 0);
1077 insert_field (self
->fields
[2], code
, 1, 0);
1081 /* Encode an SVE address [Z<n>.<T>, #<imm5> << <shift>], where <imm5> is a
1082 5-bit unsigned number and where <shift> is SELF's operand-dependent value.
1083 fields[0] specifies the base register field. */
1085 aarch64_ins_sve_addr_zi_u5 (const aarch64_operand
*self
,
1086 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1087 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1088 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1090 int factor
= 1 << get_operand_specific_data (self
);
1091 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1092 insert_field (FLD_imm5
, code
, info
->addr
.offset
.imm
/ factor
, 0);
1096 /* Encode an SVE address [Z<n>.<T>, Z<m>.<T>{, <modifier> {#<msz>}}],
1097 where <modifier> is fixed by the instruction and where <msz> is a
1098 2-bit unsigned number. fields[0] specifies the base register field
1099 and fields[1] specifies the offset register field. */
1101 aarch64_ext_sve_addr_zz (const aarch64_operand
*self
,
1102 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1103 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1105 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1106 insert_field (self
->fields
[1], code
, info
->addr
.offset
.regno
, 0);
1107 insert_field (FLD_SVE_msz
, code
, info
->shifter
.amount
, 0);
1111 /* Encode an SVE address [Z<n>.<T>, Z<m>.<T>{, LSL #<msz>}], where
1112 <msz> is a 2-bit unsigned number. fields[0] specifies the base register
1113 field and fields[1] specifies the offset register field. */
1115 aarch64_ins_sve_addr_zz_lsl (const aarch64_operand
*self
,
1116 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1117 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1118 aarch64_operand_error
*errors
)
1120 return aarch64_ext_sve_addr_zz (self
, info
, code
, errors
);
1123 /* Encode an SVE address [Z<n>.<T>, Z<m>.<T>, SXTW {#<msz>}], where
1124 <msz> is a 2-bit unsigned number. fields[0] specifies the base register
1125 field and fields[1] specifies the offset register field. */
1127 aarch64_ins_sve_addr_zz_sxtw (const aarch64_operand
*self
,
1128 const aarch64_opnd_info
*info
,
1130 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1131 aarch64_operand_error
*errors
)
1133 return aarch64_ext_sve_addr_zz (self
, info
, code
, errors
);
1136 /* Encode an SVE address [Z<n>.<T>, Z<m>.<T>, UXTW {#<msz>}], where
1137 <msz> is a 2-bit unsigned number. fields[0] specifies the base register
1138 field and fields[1] specifies the offset register field. */
1140 aarch64_ins_sve_addr_zz_uxtw (const aarch64_operand
*self
,
1141 const aarch64_opnd_info
*info
,
1143 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1144 aarch64_operand_error
*errors
)
1146 return aarch64_ext_sve_addr_zz (self
, info
, code
, errors
);
1149 /* Encode an SVE ADD/SUB immediate. */
1151 aarch64_ins_sve_aimm (const aarch64_operand
*self
,
1152 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1153 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1154 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1156 if (info
->shifter
.amount
== 8)
1157 insert_all_fields (self
, code
, (info
->imm
.value
& 0xff) | 256);
1158 else if (info
->imm
.value
!= 0 && (info
->imm
.value
& 0xff) == 0)
1159 insert_all_fields (self
, code
, ((info
->imm
.value
/ 256) & 0xff) | 256);
1161 insert_all_fields (self
, code
, info
->imm
.value
& 0xff);
1165 /* Encode an SVE CPY/DUP immediate. */
1167 aarch64_ins_sve_asimm (const aarch64_operand
*self
,
1168 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1169 const aarch64_inst
*inst
,
1170 aarch64_operand_error
*errors
)
1172 return aarch64_ins_sve_aimm (self
, info
, code
, inst
, errors
);
1175 /* Encode Zn[MM], where MM has a 7-bit triangular encoding. The fields
1176 array specifies which field to use for Zn. MM is encoded in the
1177 concatenation of imm5 and SVE_tszh, with imm5 being the less
1178 significant part. */
1180 aarch64_ins_sve_index (const aarch64_operand
*self
,
1181 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1182 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1183 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1185 unsigned int esize
= aarch64_get_qualifier_esize (info
->qualifier
);
1186 insert_field (self
->fields
[0], code
, info
->reglane
.regno
, 0);
1187 insert_fields (code
, (info
->reglane
.index
* 2 + 1) * esize
, 0,
1188 2, FLD_imm5
, FLD_SVE_tszh
);
1192 /* Encode a logical/bitmask immediate for the MOV alias of SVE DUPM. */
1194 aarch64_ins_sve_limm_mov (const aarch64_operand
*self
,
1195 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1196 const aarch64_inst
*inst
,
1197 aarch64_operand_error
*errors
)
1199 return aarch64_ins_limm (self
, info
, code
, inst
, errors
);
1202 /* Encode Zn[MM], where Zn occupies the least-significant part of the field
1203 and where MM occupies the most-significant part. The operand-dependent
1204 value specifies the number of bits in Zn. */
1206 aarch64_ins_sve_quad_index (const aarch64_operand
*self
,
1207 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1208 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1209 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1211 unsigned int reg_bits
= get_operand_specific_data (self
);
1212 assert (info
->reglane
.regno
< (1U << reg_bits
));
1213 unsigned int val
= (info
->reglane
.index
<< reg_bits
) + info
->reglane
.regno
;
1214 insert_all_fields (self
, code
, val
);
1218 /* Encode {Zn.<T> - Zm.<T>}. The fields array specifies which field
1221 aarch64_ins_sve_reglist (const aarch64_operand
*self
,
1222 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1223 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1224 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1226 insert_field (self
->fields
[0], code
, info
->reglist
.first_regno
, 0);
1230 /* Encode <pattern>{, MUL #<amount>}. The fields array specifies which
1231 fields to use for <pattern>. <amount> - 1 is encoded in the SVE_imm4
1234 aarch64_ins_sve_scale (const aarch64_operand
*self
,
1235 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1236 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1237 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1239 insert_all_fields (self
, code
, info
->imm
.value
);
1240 insert_field (FLD_SVE_imm4
, code
, info
->shifter
.amount
- 1, 0);
1244 /* Encode an SVE shift left immediate. */
1246 aarch64_ins_sve_shlimm (const aarch64_operand
*self
,
1247 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1248 const aarch64_inst
*inst
,
1249 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1251 const aarch64_opnd_info
*prev_operand
;
1254 assert (info
->idx
> 0);
1255 prev_operand
= &inst
->operands
[info
->idx
- 1];
1256 esize
= aarch64_get_qualifier_esize (prev_operand
->qualifier
);
1257 insert_all_fields (self
, code
, 8 * esize
+ info
->imm
.value
);
1261 /* Encode an SVE shift right immediate. */
1263 aarch64_ins_sve_shrimm (const aarch64_operand
*self
,
1264 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1265 const aarch64_inst
*inst
,
1266 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1268 const aarch64_opnd_info
*prev_operand
;
1271 unsigned int opnd_backshift
= get_operand_specific_data (self
);
1272 assert (info
->idx
>= (int)opnd_backshift
);
1273 prev_operand
= &inst
->operands
[info
->idx
- opnd_backshift
];
1274 esize
= aarch64_get_qualifier_esize (prev_operand
->qualifier
);
1275 insert_all_fields (self
, code
, 16 * esize
- info
->imm
.value
);
1279 /* Encode a single-bit immediate that selects between #0.5 and #1.0.
1280 The fields array specifies which field to use. */
1282 aarch64_ins_sve_float_half_one (const aarch64_operand
*self
,
1283 const aarch64_opnd_info
*info
,
1285 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1286 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1288 if (info
->imm
.value
== 0x3f000000)
1289 insert_field (self
->fields
[0], code
, 0, 0);
1291 insert_field (self
->fields
[0], code
, 1, 0);
1295 /* Encode a single-bit immediate that selects between #0.5 and #2.0.
1296 The fields array specifies which field to use. */
1298 aarch64_ins_sve_float_half_two (const aarch64_operand
*self
,
1299 const aarch64_opnd_info
*info
,
1301 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1302 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1304 if (info
->imm
.value
== 0x3f000000)
1305 insert_field (self
->fields
[0], code
, 0, 0);
1307 insert_field (self
->fields
[0], code
, 1, 0);
1311 /* Encode a single-bit immediate that selects between #0.0 and #1.0.
1312 The fields array specifies which field to use. */
1314 aarch64_ins_sve_float_zero_one (const aarch64_operand
*self
,
1315 const aarch64_opnd_info
*info
,
1317 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1318 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1320 if (info
->imm
.value
== 0)
1321 insert_field (self
->fields
[0], code
, 0, 0);
1323 insert_field (self
->fields
[0], code
, 1, 0);
1327 /* Miscellaneous encoding functions. */
1329 /* Encode size[0], i.e. bit 22, for
1330 e.g. FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
1333 encode_asimd_fcvt (aarch64_inst
*inst
)
1336 aarch64_field field
= {0, 0};
1337 enum aarch64_opnd_qualifier qualifier
;
1339 switch (inst
->opcode
->op
)
1343 /* FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
1344 qualifier
= inst
->operands
[1].qualifier
;
1348 /* FCVTL<Q> <Vd>.<Ta>, <Vn>.<Tb>. */
1349 qualifier
= inst
->operands
[0].qualifier
;
1354 assert (qualifier
== AARCH64_OPND_QLF_V_4S
1355 || qualifier
== AARCH64_OPND_QLF_V_2D
);
1356 value
= (qualifier
== AARCH64_OPND_QLF_V_4S
) ? 0 : 1;
1357 gen_sub_field (FLD_size
, 0, 1, &field
);
1358 insert_field_2 (&field
, &inst
->value
, value
, 0);
1361 /* Encode size[0], i.e. bit 22, for
1362 e.g. FCVTXN <Vb><d>, <Va><n>. */
1365 encode_asisd_fcvtxn (aarch64_inst
*inst
)
1367 aarch64_insn val
= 1;
1368 aarch64_field field
= {0, 0};
1369 assert (inst
->operands
[0].qualifier
== AARCH64_OPND_QLF_S_S
);
1370 gen_sub_field (FLD_size
, 0, 1, &field
);
1371 insert_field_2 (&field
, &inst
->value
, val
, 0);
1374 /* Encode the 'opc' field for e.g. FCVT <Dd>, <Sn>. */
1376 encode_fcvt (aarch64_inst
*inst
)
1379 const aarch64_field field
= {15, 2};
1382 switch (inst
->operands
[0].qualifier
)
1384 case AARCH64_OPND_QLF_S_S
: val
= 0; break;
1385 case AARCH64_OPND_QLF_S_D
: val
= 1; break;
1386 case AARCH64_OPND_QLF_S_H
: val
= 3; break;
1389 insert_field_2 (&field
, &inst
->value
, val
, 0);
1394 /* Return the index in qualifiers_list that INST is using. Should only
1395 be called once the qualifiers are known to be valid. */
1398 aarch64_get_variant (struct aarch64_inst
*inst
)
1400 int i
, nops
, variant
;
1402 nops
= aarch64_num_of_operands (inst
->opcode
);
1403 for (variant
= 0; variant
< AARCH64_MAX_QLF_SEQ_NUM
; ++variant
)
1405 for (i
= 0; i
< nops
; ++i
)
1406 if (inst
->opcode
->qualifiers_list
[variant
][i
]
1407 != inst
->operands
[i
].qualifier
)
1415 /* Do miscellaneous encodings that are not common enough to be driven by
1419 do_misc_encoding (aarch64_inst
*inst
)
1423 switch (inst
->opcode
->op
)
1432 encode_asimd_fcvt (inst
);
1435 encode_asisd_fcvtxn (inst
);
1439 /* Copy Pn to Pm and Pg. */
1440 value
= extract_field (FLD_SVE_Pn
, inst
->value
, 0);
1441 insert_field (FLD_SVE_Pm
, &inst
->value
, value
, 0);
1442 insert_field (FLD_SVE_Pg4_10
, &inst
->value
, value
, 0);
1445 /* Copy Zd to Zm. */
1446 value
= extract_field (FLD_SVE_Zd
, inst
->value
, 0);
1447 insert_field (FLD_SVE_Zm_16
, &inst
->value
, value
, 0);
1450 /* Fill in the zero immediate. */
1451 insert_fields (&inst
->value
, 1 << aarch64_get_variant (inst
), 0,
1452 2, FLD_imm5
, FLD_SVE_tszh
);
1455 /* Copy Zn to Zm. */
1456 value
= extract_field (FLD_SVE_Zn
, inst
->value
, 0);
1457 insert_field (FLD_SVE_Zm_16
, &inst
->value
, value
, 0);
1462 /* Copy Pd to Pm. */
1463 value
= extract_field (FLD_SVE_Pd
, inst
->value
, 0);
1464 insert_field (FLD_SVE_Pm
, &inst
->value
, value
, 0);
1466 case OP_MOVZS_P_P_P
:
1468 /* Copy Pn to Pm. */
1469 value
= extract_field (FLD_SVE_Pn
, inst
->value
, 0);
1470 insert_field (FLD_SVE_Pm
, &inst
->value
, value
, 0);
1472 case OP_NOTS_P_P_P_Z
:
1473 case OP_NOT_P_P_P_Z
:
1474 /* Copy Pg to Pm. */
1475 value
= extract_field (FLD_SVE_Pg4_10
, inst
->value
, 0);
1476 insert_field (FLD_SVE_Pm
, &inst
->value
, value
, 0);
1482 /* Encode the 'size' and 'Q' field for e.g. SHADD. */
1484 encode_sizeq (aarch64_inst
*inst
)
1487 enum aarch64_field_kind kind
;
1490 /* Get the index of the operand whose information we are going to use
1491 to encode the size and Q fields.
1492 This is deduced from the possible valid qualifier lists. */
1493 idx
= aarch64_select_operand_for_sizeq_field_coding (inst
->opcode
);
1494 DEBUG_TRACE ("idx: %d; qualifier: %s", idx
,
1495 aarch64_get_qualifier_name (inst
->operands
[idx
].qualifier
));
1496 sizeq
= aarch64_get_qualifier_standard_value (inst
->operands
[idx
].qualifier
);
1498 insert_field (FLD_Q
, &inst
->value
, sizeq
& 0x1, inst
->opcode
->mask
);
1500 if (inst
->opcode
->iclass
== asisdlse
1501 || inst
->opcode
->iclass
== asisdlsep
1502 || inst
->opcode
->iclass
== asisdlso
1503 || inst
->opcode
->iclass
== asisdlsop
)
1504 kind
= FLD_vldst_size
;
1507 insert_field (kind
, &inst
->value
, (sizeq
>> 1) & 0x3, inst
->opcode
->mask
);
1510 /* Opcodes that have fields shared by multiple operands are usually flagged
1511 with flags. In this function, we detect such flags and use the
1512 information in one of the related operands to do the encoding. The 'one'
1513 operand is not any operand but one of the operands that has the enough
1514 information for such an encoding. */
1517 do_special_encoding (struct aarch64_inst
*inst
)
1520 aarch64_insn value
= 0;
1522 DEBUG_TRACE ("enter with coding 0x%x", (uint32_t) inst
->value
);
1524 /* Condition for truly conditional executed instructions, e.g. b.cond. */
1525 if (inst
->opcode
->flags
& F_COND
)
1527 insert_field (FLD_cond2
, &inst
->value
, inst
->cond
->value
, 0);
1529 if (inst
->opcode
->flags
& F_SF
)
1531 idx
= select_operand_for_sf_field_coding (inst
->opcode
);
1532 value
= (inst
->operands
[idx
].qualifier
== AARCH64_OPND_QLF_X
1533 || inst
->operands
[idx
].qualifier
== AARCH64_OPND_QLF_SP
)
1535 insert_field (FLD_sf
, &inst
->value
, value
, 0);
1536 if (inst
->opcode
->flags
& F_N
)
1537 insert_field (FLD_N
, &inst
->value
, value
, inst
->opcode
->mask
);
1539 if (inst
->opcode
->flags
& F_LSE_SZ
)
1541 idx
= select_operand_for_sf_field_coding (inst
->opcode
);
1542 value
= (inst
->operands
[idx
].qualifier
== AARCH64_OPND_QLF_X
1543 || inst
->operands
[idx
].qualifier
== AARCH64_OPND_QLF_SP
)
1545 insert_field (FLD_lse_sz
, &inst
->value
, value
, 0);
1547 if (inst
->opcode
->flags
& F_SIZEQ
)
1548 encode_sizeq (inst
);
1549 if (inst
->opcode
->flags
& F_FPTYPE
)
1551 idx
= select_operand_for_fptype_field_coding (inst
->opcode
);
1552 switch (inst
->operands
[idx
].qualifier
)
1554 case AARCH64_OPND_QLF_S_S
: value
= 0; break;
1555 case AARCH64_OPND_QLF_S_D
: value
= 1; break;
1556 case AARCH64_OPND_QLF_S_H
: value
= 3; break;
1557 default: assert (0);
1559 insert_field (FLD_type
, &inst
->value
, value
, 0);
1561 if (inst
->opcode
->flags
& F_SSIZE
)
1563 enum aarch64_opnd_qualifier qualifier
;
1564 idx
= select_operand_for_scalar_size_field_coding (inst
->opcode
);
1565 qualifier
= inst
->operands
[idx
].qualifier
;
1566 assert (qualifier
>= AARCH64_OPND_QLF_S_B
1567 && qualifier
<= AARCH64_OPND_QLF_S_Q
);
1568 value
= aarch64_get_qualifier_standard_value (qualifier
);
1569 insert_field (FLD_size
, &inst
->value
, value
, inst
->opcode
->mask
);
1571 if (inst
->opcode
->flags
& F_T
)
1573 int num
; /* num of consecutive '0's on the right side of imm5<3:0>. */
1574 aarch64_field field
= {0, 0};
1575 enum aarch64_opnd_qualifier qualifier
;
1578 qualifier
= inst
->operands
[idx
].qualifier
;
1579 assert (aarch64_get_operand_class (inst
->opcode
->operands
[0])
1580 == AARCH64_OPND_CLASS_SIMD_REG
1581 && qualifier
>= AARCH64_OPND_QLF_V_8B
1582 && qualifier
<= AARCH64_OPND_QLF_V_2D
);
1593 value
= aarch64_get_qualifier_standard_value (qualifier
);
1594 insert_field (FLD_Q
, &inst
->value
, value
& 0x1, inst
->opcode
->mask
);
1595 num
= (int) value
>> 1;
1596 assert (num
>= 0 && num
<= 3);
1597 gen_sub_field (FLD_imm5
, 0, num
+ 1, &field
);
1598 insert_field_2 (&field
, &inst
->value
, 1 << num
, inst
->opcode
->mask
);
1600 if (inst
->opcode
->flags
& F_GPRSIZE_IN_Q
)
1602 /* Use Rt to encode in the case of e.g.
1603 STXP <Ws>, <Xt1>, <Xt2>, [<Xn|SP>{,#0}]. */
1604 enum aarch64_opnd_qualifier qualifier
;
1605 idx
= aarch64_operand_index (inst
->opcode
->operands
, AARCH64_OPND_Rt
);
1607 /* Otherwise use the result operand, which has to be a integer
1610 assert (idx
== 0 || idx
== 1);
1611 assert (aarch64_get_operand_class (inst
->opcode
->operands
[idx
])
1612 == AARCH64_OPND_CLASS_INT_REG
);
1613 qualifier
= inst
->operands
[idx
].qualifier
;
1614 insert_field (FLD_Q
, &inst
->value
,
1615 aarch64_get_qualifier_standard_value (qualifier
), 0);
1617 if (inst
->opcode
->flags
& F_LDS_SIZE
)
1619 /* e.g. LDRSB <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
1620 enum aarch64_opnd_qualifier qualifier
;
1621 aarch64_field field
= {0, 0};
1622 assert (aarch64_get_operand_class (inst
->opcode
->operands
[0])
1623 == AARCH64_OPND_CLASS_INT_REG
);
1624 gen_sub_field (FLD_opc
, 0, 1, &field
);
1625 qualifier
= inst
->operands
[0].qualifier
;
1626 insert_field_2 (&field
, &inst
->value
,
1627 1 - aarch64_get_qualifier_standard_value (qualifier
), 0);
1629 /* Miscellaneous encoding as the last step. */
1630 if (inst
->opcode
->flags
& F_MISC
)
1631 do_misc_encoding (inst
);
1633 DEBUG_TRACE ("exit with coding 0x%x", (uint32_t) inst
->value
);
1636 /* Some instructions (including all SVE ones) use the instruction class
1637 to describe how a qualifiers_list index is represented in the instruction
1638 encoding. If INST is such an instruction, encode the chosen qualifier
1642 aarch64_encode_variant_using_iclass (struct aarch64_inst
*inst
)
1645 switch (inst
->opcode
->iclass
)
1648 insert_fields (&inst
->value
, aarch64_get_variant (inst
),
1649 0, 2, FLD_SVE_M_14
, FLD_size
);
1653 case sve_shift_pred
:
1654 case sve_shift_unpred
:
1655 case sve_shift_tsz_hsd
:
1656 case sve_shift_tsz_bhsd
:
1657 /* For indices and shift amounts, the variant is encoded as
1658 part of the immediate. */
1662 /* For sve_limm, the .B, .H, and .S forms are just a convenience
1663 and depend on the immediate. They don't have a separate
1668 /* sve_misc instructions have only a single variant. */
1672 insert_fields (&inst
->value
, aarch64_get_variant (inst
),
1673 0, 2, FLD_SVE_M_16
, FLD_size
);
1677 insert_field (FLD_SVE_M_4
, &inst
->value
, aarch64_get_variant (inst
), 0);
1682 insert_field (FLD_size
, &inst
->value
, aarch64_get_variant (inst
), 0);
1686 insert_field (FLD_size
, &inst
->value
, aarch64_get_variant (inst
) + 1, 0);
1691 insert_field (FLD_SVE_sz
, &inst
->value
, aarch64_get_variant (inst
), 0);
1695 insert_field (FLD_SVE_sz2
, &inst
->value
, aarch64_get_variant (inst
), 0);
1699 insert_field (FLD_SVE_size
, &inst
->value
,
1700 aarch64_get_variant (inst
) + 1, 0);
1703 case sve_size_tsz_bhs
:
1704 insert_fields (&inst
->value
,
1705 (1 << aarch64_get_variant (inst
)),
1706 0, 2, FLD_SVE_tszl_19
, FLD_SVE_sz
);
1710 variant
= aarch64_get_variant (inst
) + 1;
1713 insert_field (FLD_size
, &inst
->value
, variant
, 0);
1721 /* Converters converting an alias opcode instruction to its real form. */
1723 /* ROR <Wd>, <Ws>, #<shift>
1725 EXTR <Wd>, <Ws>, <Ws>, #<shift>. */
1727 convert_ror_to_extr (aarch64_inst
*inst
)
1729 copy_operand_info (inst
, 3, 2);
1730 copy_operand_info (inst
, 2, 1);
1733 /* UXTL<Q> <Vd>.<Ta>, <Vn>.<Tb>
1735 USHLL<Q> <Vd>.<Ta>, <Vn>.<Tb>, #0. */
1737 convert_xtl_to_shll (aarch64_inst
*inst
)
1739 inst
->operands
[2].qualifier
= inst
->operands
[1].qualifier
;
1740 inst
->operands
[2].imm
.value
= 0;
1744 LSR <Xd>, <Xn>, #<shift>
1746 UBFM <Xd>, <Xn>, #<shift>, #63. */
1748 convert_sr_to_bfm (aarch64_inst
*inst
)
1750 inst
->operands
[3].imm
.value
=
1751 inst
->operands
[2].qualifier
== AARCH64_OPND_QLF_imm_0_31
? 31 : 63;
1754 /* Convert MOV to ORR. */
1756 convert_mov_to_orr (aarch64_inst
*inst
)
1758 /* MOV <Vd>.<T>, <Vn>.<T>
1760 ORR <Vd>.<T>, <Vn>.<T>, <Vn>.<T>. */
1761 copy_operand_info (inst
, 2, 1);
1764 /* When <imms> >= <immr>, the instruction written:
1765 SBFX <Xd>, <Xn>, #<lsb>, #<width>
1767 SBFM <Xd>, <Xn>, #<lsb>, #(<lsb>+<width>-1). */
1770 convert_bfx_to_bfm (aarch64_inst
*inst
)
1774 /* Convert the operand. */
1775 lsb
= inst
->operands
[2].imm
.value
;
1776 width
= inst
->operands
[3].imm
.value
;
1777 inst
->operands
[2].imm
.value
= lsb
;
1778 inst
->operands
[3].imm
.value
= lsb
+ width
- 1;
1781 /* When <imms> < <immr>, the instruction written:
1782 SBFIZ <Xd>, <Xn>, #<lsb>, #<width>
1784 SBFM <Xd>, <Xn>, #((64-<lsb>)&0x3f), #(<width>-1). */
1787 convert_bfi_to_bfm (aarch64_inst
*inst
)
1791 /* Convert the operand. */
1792 lsb
= inst
->operands
[2].imm
.value
;
1793 width
= inst
->operands
[3].imm
.value
;
1794 if (inst
->operands
[2].qualifier
== AARCH64_OPND_QLF_imm_0_31
)
1796 inst
->operands
[2].imm
.value
= (32 - lsb
) & 0x1f;
1797 inst
->operands
[3].imm
.value
= width
- 1;
1801 inst
->operands
[2].imm
.value
= (64 - lsb
) & 0x3f;
1802 inst
->operands
[3].imm
.value
= width
- 1;
1806 /* The instruction written:
1807 BFC <Xd>, #<lsb>, #<width>
1809 BFM <Xd>, XZR, #((64-<lsb>)&0x3f), #(<width>-1). */
1812 convert_bfc_to_bfm (aarch64_inst
*inst
)
1817 copy_operand_info (inst
, 3, 2);
1818 copy_operand_info (inst
, 2, 1);
1819 copy_operand_info (inst
, 1, 0);
1820 inst
->operands
[1].reg
.regno
= 0x1f;
1822 /* Convert the immediate operand. */
1823 lsb
= inst
->operands
[2].imm
.value
;
1824 width
= inst
->operands
[3].imm
.value
;
1825 if (inst
->operands
[2].qualifier
== AARCH64_OPND_QLF_imm_0_31
)
1827 inst
->operands
[2].imm
.value
= (32 - lsb
) & 0x1f;
1828 inst
->operands
[3].imm
.value
= width
- 1;
1832 inst
->operands
[2].imm
.value
= (64 - lsb
) & 0x3f;
1833 inst
->operands
[3].imm
.value
= width
- 1;
1837 /* The instruction written:
1838 LSL <Xd>, <Xn>, #<shift>
1840 UBFM <Xd>, <Xn>, #((64-<shift>)&0x3f), #(63-<shift>). */
1843 convert_lsl_to_ubfm (aarch64_inst
*inst
)
1845 int64_t shift
= inst
->operands
[2].imm
.value
;
1847 if (inst
->operands
[2].qualifier
== AARCH64_OPND_QLF_imm_0_31
)
1849 inst
->operands
[2].imm
.value
= (32 - shift
) & 0x1f;
1850 inst
->operands
[3].imm
.value
= 31 - shift
;
1854 inst
->operands
[2].imm
.value
= (64 - shift
) & 0x3f;
1855 inst
->operands
[3].imm
.value
= 63 - shift
;
1859 /* CINC <Wd>, <Wn>, <cond>
1861 CSINC <Wd>, <Wn>, <Wn>, invert(<cond>). */
1864 convert_to_csel (aarch64_inst
*inst
)
1866 copy_operand_info (inst
, 3, 2);
1867 copy_operand_info (inst
, 2, 1);
1868 inst
->operands
[3].cond
= get_inverted_cond (inst
->operands
[3].cond
);
1871 /* CSET <Wd>, <cond>
1873 CSINC <Wd>, WZR, WZR, invert(<cond>). */
1876 convert_cset_to_csinc (aarch64_inst
*inst
)
1878 copy_operand_info (inst
, 3, 1);
1879 copy_operand_info (inst
, 2, 0);
1880 copy_operand_info (inst
, 1, 0);
1881 inst
->operands
[1].reg
.regno
= 0x1f;
1882 inst
->operands
[2].reg
.regno
= 0x1f;
1883 inst
->operands
[3].cond
= get_inverted_cond (inst
->operands
[3].cond
);
1888 MOVZ <Wd>, #<imm16>, LSL #<shift>. */
1891 convert_mov_to_movewide (aarch64_inst
*inst
)
1894 uint32_t shift_amount
;
1897 switch (inst
->opcode
->op
)
1899 case OP_MOV_IMM_WIDE
:
1900 value
= inst
->operands
[1].imm
.value
;
1902 case OP_MOV_IMM_WIDEN
:
1903 value
= ~inst
->operands
[1].imm
.value
;
1908 inst
->operands
[1].type
= AARCH64_OPND_HALF
;
1909 is32
= inst
->operands
[0].qualifier
== AARCH64_OPND_QLF_W
;
1910 if (! aarch64_wide_constant_p (value
, is32
, &shift_amount
))
1911 /* The constraint check should have guaranteed this wouldn't happen. */
1913 value
>>= shift_amount
;
1915 inst
->operands
[1].imm
.value
= value
;
1916 inst
->operands
[1].shifter
.kind
= AARCH64_MOD_LSL
;
1917 inst
->operands
[1].shifter
.amount
= shift_amount
;
1922 ORR <Wd>, WZR, #<imm>. */
1925 convert_mov_to_movebitmask (aarch64_inst
*inst
)
1927 copy_operand_info (inst
, 2, 1);
1928 inst
->operands
[1].reg
.regno
= 0x1f;
1929 inst
->operands
[1].skip
= 0;
1932 /* Some alias opcodes are assembled by being converted to their real-form. */
1935 convert_to_real (aarch64_inst
*inst
, const aarch64_opcode
*real
)
1937 const aarch64_opcode
*alias
= inst
->opcode
;
1939 if ((alias
->flags
& F_CONV
) == 0)
1940 goto convert_to_real_return
;
1946 convert_sr_to_bfm (inst
);
1949 convert_lsl_to_ubfm (inst
);
1954 convert_to_csel (inst
);
1958 convert_cset_to_csinc (inst
);
1963 convert_bfx_to_bfm (inst
);
1968 convert_bfi_to_bfm (inst
);
1971 convert_bfc_to_bfm (inst
);
1974 convert_mov_to_orr (inst
);
1976 case OP_MOV_IMM_WIDE
:
1977 case OP_MOV_IMM_WIDEN
:
1978 convert_mov_to_movewide (inst
);
1980 case OP_MOV_IMM_LOG
:
1981 convert_mov_to_movebitmask (inst
);
1984 convert_ror_to_extr (inst
);
1990 convert_xtl_to_shll (inst
);
1996 convert_to_real_return
:
1997 aarch64_replace_opcode (inst
, real
);
2000 /* Encode *INST_ORI of the opcode code OPCODE.
2001 Return the encoded result in *CODE and if QLF_SEQ is not NULL, return the
2002 matched operand qualifier sequence in *QLF_SEQ. */
2005 aarch64_opcode_encode (const aarch64_opcode
*opcode
,
2006 const aarch64_inst
*inst_ori
, aarch64_insn
*code
,
2007 aarch64_opnd_qualifier_t
*qlf_seq
,
2008 aarch64_operand_error
*mismatch_detail
,
2009 aarch64_instr_sequence
* insn_sequence
)
2012 const aarch64_opcode
*aliased
;
2013 aarch64_inst copy
, *inst
;
2015 DEBUG_TRACE ("enter with %s", opcode
->name
);
2017 /* Create a copy of *INST_ORI, so that we can do any change we want. */
2021 assert (inst
->opcode
== NULL
|| inst
->opcode
== opcode
);
2022 if (inst
->opcode
== NULL
)
2023 inst
->opcode
= opcode
;
2025 /* Constrain the operands.
2026 After passing this, the encoding is guaranteed to succeed. */
2027 if (aarch64_match_operands_constraint (inst
, mismatch_detail
) == 0)
2029 DEBUG_TRACE ("FAIL since operand constraint not met");
2033 /* Get the base value.
2034 Note: this has to be before the aliasing handling below in order to
2035 get the base value from the alias opcode before we move on to the
2036 aliased opcode for encoding. */
2037 inst
->value
= opcode
->opcode
;
2039 /* No need to do anything else if the opcode does not have any operand. */
2040 if (aarch64_num_of_operands (opcode
) == 0)
2043 /* Assign operand indexes and check types. Also put the matched
2044 operand qualifiers in *QLF_SEQ to return. */
2045 for (i
= 0; i
< AARCH64_MAX_OPND_NUM
; ++i
)
2047 assert (opcode
->operands
[i
] == inst
->operands
[i
].type
);
2048 inst
->operands
[i
].idx
= i
;
2049 if (qlf_seq
!= NULL
)
2050 *qlf_seq
= inst
->operands
[i
].qualifier
;
2053 aliased
= aarch64_find_real_opcode (opcode
);
2054 /* If the opcode is an alias and it does not ask for direct encoding by
2055 itself, the instruction will be transformed to the form of real opcode
2056 and the encoding will be carried out using the rules for the aliased
2058 if (aliased
!= NULL
&& (opcode
->flags
& F_CONV
))
2060 DEBUG_TRACE ("real opcode '%s' has been found for the alias %s",
2061 aliased
->name
, opcode
->name
);
2062 /* Convert the operands to the form of the real opcode. */
2063 convert_to_real (inst
, aliased
);
2067 aarch64_opnd_info
*info
= inst
->operands
;
2069 /* Call the inserter of each operand. */
2070 for (i
= 0; i
< AARCH64_MAX_OPND_NUM
; ++i
, ++info
)
2072 const aarch64_operand
*opnd
;
2073 enum aarch64_opnd type
= opcode
->operands
[i
];
2074 if (type
== AARCH64_OPND_NIL
)
2078 DEBUG_TRACE ("skip the incomplete operand %d", i
);
2081 opnd
= &aarch64_operands
[type
];
2082 if (operand_has_inserter (opnd
)
2083 && !aarch64_insert_operand (opnd
, info
, &inst
->value
, inst
,
2088 /* Call opcode encoders indicated by flags. */
2089 if (opcode_has_special_coder (opcode
))
2090 do_special_encoding (inst
);
2092 /* Possibly use the instruction class to encode the chosen qualifier
2094 aarch64_encode_variant_using_iclass (inst
);
2096 /* Run a verifier if the instruction has one set. */
2097 if (opcode
->verifier
)
2099 enum err_type result
= opcode
->verifier (inst
, *code
, 0, TRUE
,
2100 mismatch_detail
, insn_sequence
);
2112 /* Always run constrain verifiers, this is needed because constrains need to
2113 maintain a global state. Regardless if the instruction has the flag set
2115 enum err_type result
= verify_constraints (inst
, *code
, 0, TRUE
,
2116 mismatch_detail
, insn_sequence
);
2129 DEBUG_TRACE ("exit with %s", opcode
->name
);
2131 *code
= inst
->value
;