1 /* aarch64-asm.c -- AArch64 assembler support.
2 Copyright (C) 2012-2018 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. */
81 /* Insert register number. */
83 aarch64_ins_regno (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
85 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
86 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
88 insert_field (self
->fields
[0], code
, info
->reg
.regno
, 0);
92 /* Insert register number, index and/or other data for SIMD register element
93 operand, e.g. the last source operand in
94 SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]. */
96 aarch64_ins_reglane (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
97 aarch64_insn
*code
, const aarch64_inst
*inst
,
98 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
101 insert_field (self
->fields
[0], code
, info
->reglane
.regno
, inst
->opcode
->mask
);
102 /* index and/or type */
103 if (inst
->opcode
->iclass
== asisdone
|| inst
->opcode
->iclass
== asimdins
)
105 int pos
= info
->qualifier
- AARCH64_OPND_QLF_S_B
;
106 if (info
->type
== AARCH64_OPND_En
107 && inst
->opcode
->operands
[0] == AARCH64_OPND_Ed
)
109 /* index2 for e.g. INS <Vd>.<Ts>[<index1>], <Vn>.<Ts>[<index2>]. */
110 assert (info
->idx
== 1); /* Vn */
111 aarch64_insn value
= info
->reglane
.index
<< pos
;
112 insert_field (FLD_imm4
, code
, value
, 0);
116 /* index and type for e.g. DUP <V><d>, <Vn>.<T>[<index>].
123 aarch64_insn value
= ((info
->reglane
.index
<< 1) | 1) << pos
;
124 insert_field (FLD_imm5
, code
, value
, 0);
127 else if (inst
->opcode
->iclass
== dotproduct
)
129 unsigned reglane_index
= info
->reglane
.index
;
130 switch (info
->qualifier
)
132 case AARCH64_OPND_QLF_S_4B
:
134 assert (reglane_index
< 4);
135 insert_fields (code
, reglane_index
, 0, 2, FLD_L
, FLD_H
);
141 else if (inst
->opcode
->iclass
== cryptosm3
)
143 /* index for e.g. SM3TT2A <Vd>.4S, <Vn>.4S, <Vm>S[<imm2>]. */
144 unsigned reglane_index
= info
->reglane
.index
;
145 assert (reglane_index
< 4);
146 insert_field (FLD_SM3_imm2
, code
, reglane_index
, 0);
150 /* index for e.g. SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
151 or SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]. */
152 unsigned reglane_index
= info
->reglane
.index
;
154 if (inst
->opcode
->op
== OP_FCMLA_ELEM
)
155 /* Complex operand takes two elements. */
158 switch (info
->qualifier
)
160 case AARCH64_OPND_QLF_S_H
:
162 assert (reglane_index
< 8);
163 insert_fields (code
, reglane_index
, 0, 3, FLD_M
, FLD_L
, FLD_H
);
165 case AARCH64_OPND_QLF_S_S
:
167 assert (reglane_index
< 4);
168 insert_fields (code
, reglane_index
, 0, 2, FLD_L
, FLD_H
);
170 case AARCH64_OPND_QLF_S_D
:
172 assert (reglane_index
< 2);
173 insert_field (FLD_H
, code
, reglane_index
, 0);
182 /* Insert regno and len field of a register list operand, e.g. Vn in TBL. */
184 aarch64_ins_reglist (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
186 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
187 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
190 insert_field (self
->fields
[0], code
, info
->reglist
.first_regno
, 0);
192 insert_field (FLD_len
, code
, info
->reglist
.num_regs
- 1, 0);
196 /* Insert Rt and opcode fields for a register list operand, e.g. Vt
197 in AdvSIMD load/store instructions. */
199 aarch64_ins_ldst_reglist (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
200 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
201 const aarch64_inst
*inst
,
202 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
204 aarch64_insn value
= 0;
205 /* Number of elements in each structure to be loaded/stored. */
206 unsigned num
= get_opcode_dependent_value (inst
->opcode
);
209 insert_field (FLD_Rt
, code
, info
->reglist
.first_regno
, 0);
214 switch (info
->reglist
.num_regs
)
216 case 1: value
= 0x7; break;
217 case 2: value
= 0xa; break;
218 case 3: value
= 0x6; break;
219 case 4: value
= 0x2; break;
224 value
= info
->reglist
.num_regs
== 4 ? 0x3 : 0x8;
235 insert_field (FLD_opcode
, code
, value
, 0);
240 /* Insert Rt and S fields for a register list operand, e.g. Vt in AdvSIMD load
241 single structure to all lanes instructions. */
243 aarch64_ins_ldst_reglist_r (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
244 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
245 const aarch64_inst
*inst
,
246 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
249 /* The opcode dependent area stores the number of elements in
250 each structure to be loaded/stored. */
251 int is_ld1r
= get_opcode_dependent_value (inst
->opcode
) == 1;
254 insert_field (FLD_Rt
, code
, info
->reglist
.first_regno
, 0);
256 value
= (aarch64_insn
) 0;
257 if (is_ld1r
&& info
->reglist
.num_regs
== 2)
258 /* OP_LD1R does not have alternating variant, but have "two consecutive"
260 value
= (aarch64_insn
) 1;
261 insert_field (FLD_S
, code
, value
, 0);
266 /* Insert Q, opcode<2:1>, S, size and Rt fields for a register element list
267 operand e.g. Vt in AdvSIMD load/store single element instructions. */
269 aarch64_ins_ldst_elemlist (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
270 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
271 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
272 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
274 aarch64_field field
= {0, 0};
275 aarch64_insn QSsize
= 0; /* fields Q:S:size. */
276 aarch64_insn opcodeh2
= 0; /* opcode<2:1> */
278 assert (info
->reglist
.has_index
);
281 insert_field (FLD_Rt
, code
, info
->reglist
.first_regno
, 0);
282 /* Encode the index, opcode<2:1> and size. */
283 switch (info
->qualifier
)
285 case AARCH64_OPND_QLF_S_B
:
286 /* Index encoded in "Q:S:size". */
287 QSsize
= info
->reglist
.index
;
290 case AARCH64_OPND_QLF_S_H
:
291 /* Index encoded in "Q:S:size<1>". */
292 QSsize
= info
->reglist
.index
<< 1;
295 case AARCH64_OPND_QLF_S_S
:
296 /* Index encoded in "Q:S". */
297 QSsize
= info
->reglist
.index
<< 2;
300 case AARCH64_OPND_QLF_S_D
:
301 /* Index encoded in "Q". */
302 QSsize
= info
->reglist
.index
<< 3 | 0x1;
308 insert_fields (code
, QSsize
, 0, 3, FLD_vldst_size
, FLD_S
, FLD_Q
);
309 gen_sub_field (FLD_asisdlso_opcode
, 1, 2, &field
);
310 insert_field_2 (&field
, code
, opcodeh2
, 0);
315 /* Insert fields immh:immb and/or Q for e.g. the shift immediate in
316 SSHR <Vd>.<T>, <Vn>.<T>, #<shift>
317 or SSHR <V><d>, <V><n>, #<shift>. */
319 aarch64_ins_advsimd_imm_shift (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
320 const aarch64_opnd_info
*info
,
321 aarch64_insn
*code
, const aarch64_inst
*inst
,
322 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
324 unsigned val
= aarch64_get_qualifier_standard_value (info
->qualifier
);
327 if (inst
->opcode
->iclass
== asimdshf
)
331 0000 x SEE AdvSIMD modified immediate
340 Q
= (val
& 0x1) ? 1 : 0;
341 insert_field (FLD_Q
, code
, Q
, inst
->opcode
->mask
);
345 assert (info
->type
== AARCH64_OPND_IMM_VLSR
346 || info
->type
== AARCH64_OPND_IMM_VLSL
);
348 if (info
->type
== AARCH64_OPND_IMM_VLSR
)
351 0000 SEE AdvSIMD modified immediate
352 0001 (16-UInt(immh:immb))
353 001x (32-UInt(immh:immb))
354 01xx (64-UInt(immh:immb))
355 1xxx (128-UInt(immh:immb)) */
356 imm
= (16 << (unsigned)val
) - info
->imm
.value
;
360 0000 SEE AdvSIMD modified immediate
361 0001 (UInt(immh:immb)-8)
362 001x (UInt(immh:immb)-16)
363 01xx (UInt(immh:immb)-32)
364 1xxx (UInt(immh:immb)-64) */
365 imm
= info
->imm
.value
+ (8 << (unsigned)val
);
366 insert_fields (code
, imm
, 0, 2, FLD_immb
, FLD_immh
);
371 /* Insert fields for e.g. the immediate operands in
372 BFM <Wd>, <Wn>, #<immr>, #<imms>. */
374 aarch64_ins_imm (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
376 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
377 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
381 imm
= info
->imm
.value
;
382 if (operand_need_shift_by_two (self
))
384 insert_all_fields (self
, code
, imm
);
388 /* Insert immediate and its shift amount for e.g. the last operand in
389 MOVZ <Wd>, #<imm16>{, LSL #<shift>}. */
391 aarch64_ins_imm_half (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
392 aarch64_insn
*code
, const aarch64_inst
*inst
,
393 aarch64_operand_error
*errors
)
396 aarch64_ins_imm (self
, info
, code
, inst
, errors
);
398 insert_field (FLD_hw
, code
, info
->shifter
.amount
>> 4, 0);
402 /* Insert cmode and "a:b:c:d:e:f:g:h" fields for e.g. the last operand in
403 MOVI <Vd>.<T>, #<imm8> {, LSL #<amount>}. */
405 aarch64_ins_advsimd_imm_modified (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
406 const aarch64_opnd_info
*info
,
408 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
409 aarch64_operand_error
*errors
412 enum aarch64_opnd_qualifier opnd0_qualifier
= inst
->operands
[0].qualifier
;
413 uint64_t imm
= info
->imm
.value
;
414 enum aarch64_modifier_kind kind
= info
->shifter
.kind
;
415 int amount
= info
->shifter
.amount
;
416 aarch64_field field
= {0, 0};
418 /* a:b:c:d:e:f:g:h */
419 if (!info
->imm
.is_fp
&& aarch64_get_qualifier_esize (opnd0_qualifier
) == 8)
421 /* Either MOVI <Dd>, #<imm>
422 or MOVI <Vd>.2D, #<imm>.
423 <imm> is a 64-bit immediate
424 "aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh",
425 encoded in "a:b:c:d:e:f:g:h". */
426 imm
= aarch64_shrink_expanded_imm8 (imm
);
427 assert ((int)imm
>= 0);
429 insert_fields (code
, imm
, 0, 2, FLD_defgh
, FLD_abc
);
431 if (kind
== AARCH64_MOD_NONE
)
434 /* shift amount partially in cmode */
435 assert (kind
== AARCH64_MOD_LSL
|| kind
== AARCH64_MOD_MSL
);
436 if (kind
== AARCH64_MOD_LSL
)
438 /* AARCH64_MOD_LSL: shift zeros. */
439 int esize
= aarch64_get_qualifier_esize (opnd0_qualifier
);
440 assert (esize
== 4 || esize
== 2 || esize
== 1);
441 /* For 8-bit move immediate, the optional LSL #0 does not require
447 gen_sub_field (FLD_cmode
, 1, 2, &field
); /* per word */
449 gen_sub_field (FLD_cmode
, 1, 1, &field
); /* per halfword */
453 /* AARCH64_MOD_MSL: shift ones. */
455 gen_sub_field (FLD_cmode
, 0, 1, &field
); /* per word */
457 insert_field_2 (&field
, code
, amount
, 0);
462 /* Insert fields for an 8-bit floating-point immediate. */
464 aarch64_ins_fpimm (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
466 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
467 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
469 insert_all_fields (self
, code
, info
->imm
.value
);
473 /* Insert 1-bit rotation immediate (#90 or #270). */
475 aarch64_ins_imm_rotate1 (const aarch64_operand
*self
,
476 const aarch64_opnd_info
*info
,
477 aarch64_insn
*code
, const aarch64_inst
*inst
,
478 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
480 uint64_t rot
= (info
->imm
.value
- 90) / 180;
482 insert_field (self
->fields
[0], code
, rot
, inst
->opcode
->mask
);
486 /* Insert 2-bit rotation immediate (#0, #90, #180 or #270). */
488 aarch64_ins_imm_rotate2 (const aarch64_operand
*self
,
489 const aarch64_opnd_info
*info
,
490 aarch64_insn
*code
, const aarch64_inst
*inst
,
491 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
493 uint64_t rot
= info
->imm
.value
/ 90;
495 insert_field (self
->fields
[0], code
, rot
, inst
->opcode
->mask
);
499 /* Insert #<fbits> for the immediate operand in fp fix-point instructions,
500 e.g. SCVTF <Dd>, <Wn>, #<fbits>. */
502 aarch64_ins_fbits (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
504 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
505 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
507 insert_field (self
->fields
[0], code
, 64 - info
->imm
.value
, 0);
511 /* Insert arithmetic immediate for e.g. the last operand in
512 SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}. */
514 aarch64_ins_aimm (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
515 aarch64_insn
*code
, const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
516 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
519 aarch64_insn value
= info
->shifter
.amount
? 1 : 0;
520 insert_field (self
->fields
[0], code
, value
, 0);
521 /* imm12 (unsigned) */
522 insert_field (self
->fields
[1], code
, info
->imm
.value
, 0);
526 /* Common routine shared by aarch64_ins{,_inv}_limm. INVERT_P says whether
527 the operand should be inverted before encoding. */
529 aarch64_ins_limm_1 (const aarch64_operand
*self
,
530 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
531 const aarch64_inst
*inst
, bfd_boolean invert_p
,
532 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
535 uint64_t imm
= info
->imm
.value
;
536 int esize
= aarch64_get_qualifier_esize (inst
->operands
[0].qualifier
);
540 /* The constraint check should have guaranteed this wouldn't happen. */
541 assert (aarch64_logical_immediate_p (imm
, esize
, &value
));
543 insert_fields (code
, value
, 0, 3, self
->fields
[2], self
->fields
[1],
548 /* Insert logical/bitmask immediate for e.g. the last operand in
549 ORR <Wd|WSP>, <Wn>, #<imm>. */
551 aarch64_ins_limm (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
552 aarch64_insn
*code
, const aarch64_inst
*inst
,
553 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
555 return aarch64_ins_limm_1 (self
, info
, code
, inst
,
556 inst
->opcode
->op
== OP_BIC
, errors
);
559 /* Insert a logical/bitmask immediate for the BIC alias of AND (etc.). */
561 aarch64_ins_inv_limm (const aarch64_operand
*self
,
562 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
563 const aarch64_inst
*inst
,
564 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
566 return aarch64_ins_limm_1 (self
, info
, code
, inst
, TRUE
, errors
);
569 /* Encode Ft for e.g. STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]
570 or LDP <Qt1>, <Qt2>, [<Xn|SP>], #<imm>. */
572 aarch64_ins_ft (const aarch64_operand
*self
, const aarch64_opnd_info
*info
,
573 aarch64_insn
*code
, const aarch64_inst
*inst
,
574 aarch64_operand_error
*errors
)
576 aarch64_insn value
= 0;
578 assert (info
->idx
== 0);
581 aarch64_ins_regno (self
, info
, code
, inst
, errors
);
582 if (inst
->opcode
->iclass
== ldstpair_indexed
583 || inst
->opcode
->iclass
== ldstnapair_offs
584 || inst
->opcode
->iclass
== ldstpair_off
585 || inst
->opcode
->iclass
== loadlit
)
588 switch (info
->qualifier
)
590 case AARCH64_OPND_QLF_S_S
: value
= 0; break;
591 case AARCH64_OPND_QLF_S_D
: value
= 1; break;
592 case AARCH64_OPND_QLF_S_Q
: value
= 2; break;
595 insert_field (FLD_ldst_size
, code
, value
, 0);
600 value
= aarch64_get_qualifier_standard_value (info
->qualifier
);
601 insert_fields (code
, value
, 0, 2, FLD_ldst_size
, FLD_opc1
);
607 /* Encode the address operand for e.g. STXRB <Ws>, <Wt>, [<Xn|SP>{,#0}]. */
609 aarch64_ins_addr_simple (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
610 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
611 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
612 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
615 insert_field (FLD_Rn
, code
, info
->addr
.base_regno
, 0);
619 /* Encode the address operand for e.g.
620 STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
622 aarch64_ins_addr_regoff (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
623 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
624 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
625 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
628 enum aarch64_modifier_kind kind
= info
->shifter
.kind
;
631 insert_field (FLD_Rn
, code
, info
->addr
.base_regno
, 0);
633 insert_field (FLD_Rm
, code
, info
->addr
.offset
.regno
, 0);
635 if (kind
== AARCH64_MOD_LSL
)
636 kind
= AARCH64_MOD_UXTX
; /* Trick to enable the table-driven. */
637 insert_field (FLD_option
, code
, aarch64_get_operand_modifier_value (kind
), 0);
639 if (info
->qualifier
!= AARCH64_OPND_QLF_S_B
)
640 S
= info
->shifter
.amount
!= 0;
642 /* For STR <Bt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}},
646 Must be #0 if <extend> is explicitly LSL. */
647 S
= info
->shifter
.operator_present
&& info
->shifter
.amount_present
;
648 insert_field (FLD_S
, code
, S
, 0);
653 /* Encode the address operand for e.g.
654 stlur <Xt>, [<Xn|SP>{, <amount>}]. */
656 aarch64_ins_addr_offset (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
657 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
658 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
659 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
662 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
665 int imm
= info
->addr
.offset
.imm
;
666 insert_field (self
->fields
[1], code
, imm
, 0);
669 if (info
->addr
.writeback
)
671 assert (info
->addr
.preind
== 1 && info
->addr
.postind
== 0);
672 insert_field (self
->fields
[2], code
, 1, 0);
677 /* Encode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>, #<simm>]!. */
679 aarch64_ins_addr_simm (const aarch64_operand
*self
,
680 const aarch64_opnd_info
*info
,
682 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
683 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
688 insert_field (FLD_Rn
, code
, info
->addr
.base_regno
, 0);
689 /* simm (imm9 or imm7) */
690 imm
= info
->addr
.offset
.imm
;
691 if (self
->fields
[0] == FLD_imm7
)
692 /* scaled immediate in ld/st pair instructions.. */
693 imm
>>= get_logsz (aarch64_get_qualifier_esize (info
->qualifier
));
694 insert_field (self
->fields
[0], code
, imm
, 0);
695 /* pre/post- index */
696 if (info
->addr
.writeback
)
698 assert (inst
->opcode
->iclass
!= ldst_unscaled
699 && inst
->opcode
->iclass
!= ldstnapair_offs
700 && inst
->opcode
->iclass
!= ldstpair_off
701 && inst
->opcode
->iclass
!= ldst_unpriv
);
702 assert (info
->addr
.preind
!= info
->addr
.postind
);
703 if (info
->addr
.preind
)
704 insert_field (self
->fields
[1], code
, 1, 0);
710 /* Encode the address operand for e.g. LDRAA <Xt>, [<Xn|SP>{, #<simm>}]. */
712 aarch64_ins_addr_simm10 (const aarch64_operand
*self
,
713 const aarch64_opnd_info
*info
,
715 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
716 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
721 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
723 imm
= info
->addr
.offset
.imm
>> 3;
724 insert_field (self
->fields
[1], code
, imm
>> 9, 0);
725 insert_field (self
->fields
[2], code
, imm
, 0);
727 if (info
->addr
.writeback
)
729 assert (info
->addr
.preind
== 1 && info
->addr
.postind
== 0);
730 insert_field (self
->fields
[3], code
, 1, 0);
735 /* Encode the address operand for e.g. LDRSW <Xt>, [<Xn|SP>{, #<pimm>}]. */
737 aarch64_ins_addr_uimm12 (const aarch64_operand
*self
,
738 const aarch64_opnd_info
*info
,
740 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
741 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
743 int shift
= get_logsz (aarch64_get_qualifier_esize (info
->qualifier
));
746 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
748 insert_field (self
->fields
[1], code
,info
->addr
.offset
.imm
>> shift
, 0);
752 /* Encode the address operand for e.g.
753 LD1 {<Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>}, [<Xn|SP>], <Xm|#<amount>>. */
755 aarch64_ins_simd_addr_post (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
756 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
757 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
758 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
761 insert_field (FLD_Rn
, code
, info
->addr
.base_regno
, 0);
763 if (info
->addr
.offset
.is_reg
)
764 insert_field (FLD_Rm
, code
, info
->addr
.offset
.regno
, 0);
766 insert_field (FLD_Rm
, code
, 0x1f, 0);
770 /* Encode the condition operand for e.g. CSEL <Xd>, <Xn>, <Xm>, <cond>. */
772 aarch64_ins_cond (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
773 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
774 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
775 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
778 insert_field (FLD_cond
, code
, info
->cond
->value
, 0);
782 /* Encode the system register operand for e.g. MRS <Xt>, <systemreg>. */
784 aarch64_ins_sysreg (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
785 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
786 const aarch64_inst
*inst
,
787 aarch64_operand_error
*detail ATTRIBUTE_UNUSED
)
789 /* If a system instruction check if we have any restrictions on which
790 registers it can use. */
791 if (inst
->opcode
->iclass
== ic_system
)
793 uint64_t opcode_flags
794 = inst
->opcode
->flags
& (F_SYS_READ
| F_SYS_WRITE
);
795 uint32_t sysreg_flags
796 = info
->sysreg
.flags
& (F_REG_READ
| F_REG_WRITE
);
798 /* Check to see if it's read-only, else check if it's write only.
799 if it's both or unspecified don't care. */
800 if (opcode_flags
== F_SYS_READ
802 && sysreg_flags
!= F_REG_READ
)
804 detail
->kind
= AARCH64_OPDE_SYNTAX_ERROR
;
805 detail
->error
= _("specified register cannot be read from");
806 detail
->index
= info
->idx
;
807 detail
->non_fatal
= TRUE
;
809 else if (opcode_flags
== F_SYS_WRITE
811 && sysreg_flags
!= F_REG_WRITE
)
813 detail
->kind
= AARCH64_OPDE_SYNTAX_ERROR
;
814 detail
->error
= _("specified register cannot be written to");
815 detail
->index
= info
->idx
;
816 detail
->non_fatal
= TRUE
;
819 /* op0:op1:CRn:CRm:op2 */
820 insert_fields (code
, info
->sysreg
.value
, inst
->opcode
->mask
, 5,
821 FLD_op2
, FLD_CRm
, FLD_CRn
, FLD_op1
, FLD_op0
);
825 /* Encode the PSTATE field operand for e.g. MSR <pstatefield>, #<imm>. */
827 aarch64_ins_pstatefield (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
828 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
829 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
830 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
833 insert_fields (code
, info
->pstatefield
, inst
->opcode
->mask
, 2,
838 /* Encode the system instruction op operand for e.g. AT <at_op>, <Xt>. */
840 aarch64_ins_sysins_op (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
841 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
842 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
843 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
845 /* op1:CRn:CRm:op2 */
846 insert_fields (code
, info
->sysins_op
->value
, inst
->opcode
->mask
, 4,
847 FLD_op2
, FLD_CRm
, FLD_CRn
, FLD_op1
);
851 /* Encode the memory barrier option operand for e.g. DMB <option>|#<imm>. */
854 aarch64_ins_barrier (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
855 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
856 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
857 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
860 insert_field (FLD_CRm
, code
, info
->barrier
->value
, 0);
864 /* Encode the prefetch operation option operand for e.g.
865 PRFM <prfop>, [<Xn|SP>{, #<pimm>}]. */
868 aarch64_ins_prfop (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
869 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
870 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
871 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
874 insert_field (FLD_Rt
, code
, info
->prfop
->value
, 0);
878 /* Encode the hint number for instructions that alias HINT but take an
882 aarch64_ins_hint (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
)
888 insert_fields (code
, info
->hint_option
->value
, 0, 2, FLD_op2
, FLD_CRm
);
892 /* Encode the extended register operand for e.g.
893 STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
895 aarch64_ins_reg_extended (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
896 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
897 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
898 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
900 enum aarch64_modifier_kind kind
;
903 insert_field (FLD_Rm
, code
, info
->reg
.regno
, 0);
905 kind
= info
->shifter
.kind
;
906 if (kind
== AARCH64_MOD_LSL
)
907 kind
= info
->qualifier
== AARCH64_OPND_QLF_W
908 ? AARCH64_MOD_UXTW
: AARCH64_MOD_UXTX
;
909 insert_field (FLD_option
, code
, aarch64_get_operand_modifier_value (kind
), 0);
911 insert_field (FLD_imm3
, code
, info
->shifter
.amount
, 0);
916 /* Encode the shifted register operand for e.g.
917 SUBS <Xd>, <Xn>, <Xm> {, <shift> #<amount>}. */
919 aarch64_ins_reg_shifted (const aarch64_operand
*self ATTRIBUTE_UNUSED
,
920 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
921 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
922 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
925 insert_field (FLD_Rm
, code
, info
->reg
.regno
, 0);
927 insert_field (FLD_shift
, code
,
928 aarch64_get_operand_modifier_value (info
->shifter
.kind
), 0);
930 insert_field (FLD_imm6
, code
, info
->shifter
.amount
, 0);
935 /* Encode an SVE address [<base>, #<simm4>*<factor>, MUL VL],
936 where <simm4> is a 4-bit signed value and where <factor> is 1 plus
937 SELF's operand-dependent value. fields[0] specifies the field that
938 holds <base>. <simm4> is encoded in the SVE_imm4 field. */
940 aarch64_ins_sve_addr_ri_s4xvl (const aarch64_operand
*self
,
941 const aarch64_opnd_info
*info
,
943 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
944 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
946 int factor
= 1 + get_operand_specific_data (self
);
947 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
948 insert_field (FLD_SVE_imm4
, code
, info
->addr
.offset
.imm
/ factor
, 0);
952 /* Encode an SVE address [<base>, #<simm6>*<factor>, MUL VL],
953 where <simm6> is a 6-bit signed value and where <factor> is 1 plus
954 SELF's operand-dependent value. fields[0] specifies the field that
955 holds <base>. <simm6> is encoded in the SVE_imm6 field. */
957 aarch64_ins_sve_addr_ri_s6xvl (const aarch64_operand
*self
,
958 const aarch64_opnd_info
*info
,
960 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
961 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
963 int factor
= 1 + get_operand_specific_data (self
);
964 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
965 insert_field (FLD_SVE_imm6
, code
, info
->addr
.offset
.imm
/ factor
, 0);
969 /* Encode an SVE address [<base>, #<simm9>*<factor>, MUL VL],
970 where <simm9> is a 9-bit signed value and where <factor> is 1 plus
971 SELF's operand-dependent value. fields[0] specifies the field that
972 holds <base>. <simm9> is encoded in the concatenation of the SVE_imm6
973 and imm3 fields, with imm3 being the less-significant part. */
975 aarch64_ins_sve_addr_ri_s9xvl (const aarch64_operand
*self
,
976 const aarch64_opnd_info
*info
,
978 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
979 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
981 int factor
= 1 + get_operand_specific_data (self
);
982 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
983 insert_fields (code
, info
->addr
.offset
.imm
/ factor
, 0,
984 2, FLD_imm3
, FLD_SVE_imm6
);
988 /* Encode an SVE address [X<n>, #<SVE_imm4> << <shift>], where <SVE_imm4>
989 is a 4-bit signed number and where <shift> is SELF's operand-dependent
990 value. fields[0] specifies the base register field. */
992 aarch64_ins_sve_addr_ri_s4 (const aarch64_operand
*self
,
993 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
994 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
995 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
997 int factor
= 1 << get_operand_specific_data (self
);
998 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
999 insert_field (FLD_SVE_imm4
, code
, info
->addr
.offset
.imm
/ factor
, 0);
1003 /* Encode an SVE address [X<n>, #<SVE_imm6> << <shift>], where <SVE_imm6>
1004 is a 6-bit unsigned number and where <shift> is SELF's operand-dependent
1005 value. fields[0] specifies the base register field. */
1007 aarch64_ins_sve_addr_ri_u6 (const aarch64_operand
*self
,
1008 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
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_field (FLD_SVE_imm6
, code
, info
->addr
.offset
.imm
/ factor
, 0);
1018 /* Encode an SVE address [X<n>, X<m>{, LSL #<shift>}], where <shift>
1019 is SELF's operand-dependent value. fields[0] specifies the base
1020 register field and fields[1] specifies the offset register field. */
1022 aarch64_ins_sve_addr_rr_lsl (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 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1028 insert_field (self
->fields
[1], code
, info
->addr
.offset
.regno
, 0);
1032 /* Encode an SVE address [X<n>, Z<m>.<T>, (S|U)XTW {#<shift>}], where
1033 <shift> is SELF's operand-dependent value. fields[0] specifies the
1034 base register field, fields[1] specifies the offset register field and
1035 fields[2] is a single-bit field that selects SXTW over UXTW. */
1037 aarch64_ins_sve_addr_rz_xtw (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 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1043 insert_field (self
->fields
[1], code
, info
->addr
.offset
.regno
, 0);
1044 if (info
->shifter
.kind
== AARCH64_MOD_UXTW
)
1045 insert_field (self
->fields
[2], code
, 0, 0);
1047 insert_field (self
->fields
[2], code
, 1, 0);
1051 /* Encode an SVE address [Z<n>.<T>, #<imm5> << <shift>], where <imm5> is a
1052 5-bit unsigned number and where <shift> is SELF's operand-dependent value.
1053 fields[0] specifies the base register field. */
1055 aarch64_ins_sve_addr_zi_u5 (const aarch64_operand
*self
,
1056 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1057 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1058 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1060 int factor
= 1 << get_operand_specific_data (self
);
1061 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1062 insert_field (FLD_imm5
, code
, info
->addr
.offset
.imm
/ factor
, 0);
1066 /* Encode an SVE address [Z<n>.<T>, Z<m>.<T>{, <modifier> {#<msz>}}],
1067 where <modifier> is fixed by the instruction and where <msz> is a
1068 2-bit unsigned number. fields[0] specifies the base register field
1069 and fields[1] specifies the offset register field. */
1071 aarch64_ext_sve_addr_zz (const aarch64_operand
*self
,
1072 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1073 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1075 insert_field (self
->fields
[0], code
, info
->addr
.base_regno
, 0);
1076 insert_field (self
->fields
[1], code
, info
->addr
.offset
.regno
, 0);
1077 insert_field (FLD_SVE_msz
, code
, info
->shifter
.amount
, 0);
1081 /* Encode an SVE address [Z<n>.<T>, Z<m>.<T>{, LSL #<msz>}], where
1082 <msz> is a 2-bit unsigned number. fields[0] specifies the base register
1083 field and fields[1] specifies the offset register field. */
1085 aarch64_ins_sve_addr_zz_lsl (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
)
1090 return aarch64_ext_sve_addr_zz (self
, info
, code
, errors
);
1093 /* Encode an SVE address [Z<n>.<T>, Z<m>.<T>, SXTW {#<msz>}], where
1094 <msz> is a 2-bit unsigned number. fields[0] specifies the base register
1095 field and fields[1] specifies the offset register field. */
1097 aarch64_ins_sve_addr_zz_sxtw (const aarch64_operand
*self
,
1098 const aarch64_opnd_info
*info
,
1100 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1101 aarch64_operand_error
*errors
)
1103 return aarch64_ext_sve_addr_zz (self
, info
, code
, errors
);
1106 /* Encode an SVE address [Z<n>.<T>, Z<m>.<T>, UXTW {#<msz>}], where
1107 <msz> is a 2-bit unsigned number. fields[0] specifies the base register
1108 field and fields[1] specifies the offset register field. */
1110 aarch64_ins_sve_addr_zz_uxtw (const aarch64_operand
*self
,
1111 const aarch64_opnd_info
*info
,
1113 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1114 aarch64_operand_error
*errors
)
1116 return aarch64_ext_sve_addr_zz (self
, info
, code
, errors
);
1119 /* Encode an SVE ADD/SUB immediate. */
1121 aarch64_ins_sve_aimm (const aarch64_operand
*self
,
1122 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1123 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1124 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1126 if (info
->shifter
.amount
== 8)
1127 insert_all_fields (self
, code
, (info
->imm
.value
& 0xff) | 256);
1128 else if (info
->imm
.value
!= 0 && (info
->imm
.value
& 0xff) == 0)
1129 insert_all_fields (self
, code
, ((info
->imm
.value
/ 256) & 0xff) | 256);
1131 insert_all_fields (self
, code
, info
->imm
.value
& 0xff);
1135 /* Encode an SVE CPY/DUP immediate. */
1137 aarch64_ins_sve_asimm (const aarch64_operand
*self
,
1138 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1139 const aarch64_inst
*inst
,
1140 aarch64_operand_error
*errors
)
1142 return aarch64_ins_sve_aimm (self
, info
, code
, inst
, errors
);
1145 /* Encode Zn[MM], where MM has a 7-bit triangular encoding. The fields
1146 array specifies which field to use for Zn. MM is encoded in the
1147 concatenation of imm5 and SVE_tszh, with imm5 being the less
1148 significant part. */
1150 aarch64_ins_sve_index (const aarch64_operand
*self
,
1151 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1152 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1153 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1155 unsigned int esize
= aarch64_get_qualifier_esize (info
->qualifier
);
1156 insert_field (self
->fields
[0], code
, info
->reglane
.regno
, 0);
1157 insert_fields (code
, (info
->reglane
.index
* 2 + 1) * esize
, 0,
1158 2, FLD_imm5
, FLD_SVE_tszh
);
1162 /* Encode a logical/bitmask immediate for the MOV alias of SVE DUPM. */
1164 aarch64_ins_sve_limm_mov (const aarch64_operand
*self
,
1165 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1166 const aarch64_inst
*inst
,
1167 aarch64_operand_error
*errors
)
1169 return aarch64_ins_limm (self
, info
, code
, inst
, errors
);
1172 /* Encode Zn[MM], where Zn occupies the least-significant part of the field
1173 and where MM occupies the most-significant part. The operand-dependent
1174 value specifies the number of bits in Zn. */
1176 aarch64_ins_sve_quad_index (const aarch64_operand
*self
,
1177 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1178 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1179 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1181 unsigned int reg_bits
= get_operand_specific_data (self
);
1182 assert (info
->reglane
.regno
< (1U << reg_bits
));
1183 unsigned int val
= (info
->reglane
.index
<< reg_bits
) + info
->reglane
.regno
;
1184 insert_all_fields (self
, code
, val
);
1188 /* Encode {Zn.<T> - Zm.<T>}. The fields array specifies which field
1191 aarch64_ins_sve_reglist (const aarch64_operand
*self
,
1192 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1193 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1194 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1196 insert_field (self
->fields
[0], code
, info
->reglist
.first_regno
, 0);
1200 /* Encode <pattern>{, MUL #<amount>}. The fields array specifies which
1201 fields to use for <pattern>. <amount> - 1 is encoded in the SVE_imm4
1204 aarch64_ins_sve_scale (const aarch64_operand
*self
,
1205 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1206 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1207 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1209 insert_all_fields (self
, code
, info
->imm
.value
);
1210 insert_field (FLD_SVE_imm4
, code
, info
->shifter
.amount
- 1, 0);
1214 /* Encode an SVE shift left immediate. */
1216 aarch64_ins_sve_shlimm (const aarch64_operand
*self
,
1217 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1218 const aarch64_inst
*inst
,
1219 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1221 const aarch64_opnd_info
*prev_operand
;
1224 assert (info
->idx
> 0);
1225 prev_operand
= &inst
->operands
[info
->idx
- 1];
1226 esize
= aarch64_get_qualifier_esize (prev_operand
->qualifier
);
1227 insert_all_fields (self
, code
, 8 * esize
+ info
->imm
.value
);
1231 /* Encode an SVE shift right immediate. */
1233 aarch64_ins_sve_shrimm (const aarch64_operand
*self
,
1234 const aarch64_opnd_info
*info
, aarch64_insn
*code
,
1235 const aarch64_inst
*inst
,
1236 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1238 const aarch64_opnd_info
*prev_operand
;
1241 assert (info
->idx
> 0);
1242 prev_operand
= &inst
->operands
[info
->idx
- 1];
1243 esize
= aarch64_get_qualifier_esize (prev_operand
->qualifier
);
1244 insert_all_fields (self
, code
, 16 * esize
- info
->imm
.value
);
1248 /* Encode a single-bit immediate that selects between #0.5 and #1.0.
1249 The fields array specifies which field to use. */
1251 aarch64_ins_sve_float_half_one (const aarch64_operand
*self
,
1252 const aarch64_opnd_info
*info
,
1254 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1255 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1257 if (info
->imm
.value
== 0x3f000000)
1258 insert_field (self
->fields
[0], code
, 0, 0);
1260 insert_field (self
->fields
[0], code
, 1, 0);
1264 /* Encode a single-bit immediate that selects between #0.5 and #2.0.
1265 The fields array specifies which field to use. */
1267 aarch64_ins_sve_float_half_two (const aarch64_operand
*self
,
1268 const aarch64_opnd_info
*info
,
1270 const aarch64_inst
*inst ATTRIBUTE_UNUSED
,
1271 aarch64_operand_error
*errors ATTRIBUTE_UNUSED
)
1273 if (info
->imm
.value
== 0x3f000000)
1274 insert_field (self
->fields
[0], code
, 0, 0);
1276 insert_field (self
->fields
[0], code
, 1, 0);
1280 /* Encode a single-bit immediate that selects between #0.0 and #1.0.
1281 The fields array specifies which field to use. */
1283 aarch64_ins_sve_float_zero_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
== 0)
1290 insert_field (self
->fields
[0], code
, 0, 0);
1292 insert_field (self
->fields
[0], code
, 1, 0);
1296 /* Miscellaneous encoding functions. */
1298 /* Encode size[0], i.e. bit 22, for
1299 e.g. FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
1302 encode_asimd_fcvt (aarch64_inst
*inst
)
1305 aarch64_field field
= {0, 0};
1306 enum aarch64_opnd_qualifier qualifier
;
1308 switch (inst
->opcode
->op
)
1312 /* FCVTN<Q> <Vd>.<Tb>, <Vn>.<Ta>. */
1313 qualifier
= inst
->operands
[1].qualifier
;
1317 /* FCVTL<Q> <Vd>.<Ta>, <Vn>.<Tb>. */
1318 qualifier
= inst
->operands
[0].qualifier
;
1323 assert (qualifier
== AARCH64_OPND_QLF_V_4S
1324 || qualifier
== AARCH64_OPND_QLF_V_2D
);
1325 value
= (qualifier
== AARCH64_OPND_QLF_V_4S
) ? 0 : 1;
1326 gen_sub_field (FLD_size
, 0, 1, &field
);
1327 insert_field_2 (&field
, &inst
->value
, value
, 0);
1330 /* Encode size[0], i.e. bit 22, for
1331 e.g. FCVTXN <Vb><d>, <Va><n>. */
1334 encode_asisd_fcvtxn (aarch64_inst
*inst
)
1336 aarch64_insn val
= 1;
1337 aarch64_field field
= {0, 0};
1338 assert (inst
->operands
[0].qualifier
== AARCH64_OPND_QLF_S_S
);
1339 gen_sub_field (FLD_size
, 0, 1, &field
);
1340 insert_field_2 (&field
, &inst
->value
, val
, 0);
1343 /* Encode the 'opc' field for e.g. FCVT <Dd>, <Sn>. */
1345 encode_fcvt (aarch64_inst
*inst
)
1348 const aarch64_field field
= {15, 2};
1351 switch (inst
->operands
[0].qualifier
)
1353 case AARCH64_OPND_QLF_S_S
: val
= 0; break;
1354 case AARCH64_OPND_QLF_S_D
: val
= 1; break;
1355 case AARCH64_OPND_QLF_S_H
: val
= 3; break;
1358 insert_field_2 (&field
, &inst
->value
, val
, 0);
1363 /* Return the index in qualifiers_list that INST is using. Should only
1364 be called once the qualifiers are known to be valid. */
1367 aarch64_get_variant (struct aarch64_inst
*inst
)
1369 int i
, nops
, variant
;
1371 nops
= aarch64_num_of_operands (inst
->opcode
);
1372 for (variant
= 0; variant
< AARCH64_MAX_QLF_SEQ_NUM
; ++variant
)
1374 for (i
= 0; i
< nops
; ++i
)
1375 if (inst
->opcode
->qualifiers_list
[variant
][i
]
1376 != inst
->operands
[i
].qualifier
)
1384 /* Do miscellaneous encodings that are not common enough to be driven by
1388 do_misc_encoding (aarch64_inst
*inst
)
1392 switch (inst
->opcode
->op
)
1401 encode_asimd_fcvt (inst
);
1404 encode_asisd_fcvtxn (inst
);
1408 /* Copy Pn to Pm and Pg. */
1409 value
= extract_field (FLD_SVE_Pn
, inst
->value
, 0);
1410 insert_field (FLD_SVE_Pm
, &inst
->value
, value
, 0);
1411 insert_field (FLD_SVE_Pg4_10
, &inst
->value
, value
, 0);
1414 /* Copy Zd to Zm. */
1415 value
= extract_field (FLD_SVE_Zd
, inst
->value
, 0);
1416 insert_field (FLD_SVE_Zm_16
, &inst
->value
, value
, 0);
1419 /* Fill in the zero immediate. */
1420 insert_fields (&inst
->value
, 1 << aarch64_get_variant (inst
), 0,
1421 2, FLD_imm5
, FLD_SVE_tszh
);
1424 /* Copy Zn to Zm. */
1425 value
= extract_field (FLD_SVE_Zn
, inst
->value
, 0);
1426 insert_field (FLD_SVE_Zm_16
, &inst
->value
, value
, 0);
1431 /* Copy Pd to Pm. */
1432 value
= extract_field (FLD_SVE_Pd
, inst
->value
, 0);
1433 insert_field (FLD_SVE_Pm
, &inst
->value
, value
, 0);
1435 case OP_MOVZS_P_P_P
:
1437 /* Copy Pn to Pm. */
1438 value
= extract_field (FLD_SVE_Pn
, inst
->value
, 0);
1439 insert_field (FLD_SVE_Pm
, &inst
->value
, value
, 0);
1441 case OP_NOTS_P_P_P_Z
:
1442 case OP_NOT_P_P_P_Z
:
1443 /* Copy Pg to Pm. */
1444 value
= extract_field (FLD_SVE_Pg4_10
, inst
->value
, 0);
1445 insert_field (FLD_SVE_Pm
, &inst
->value
, value
, 0);
1451 /* Encode the 'size' and 'Q' field for e.g. SHADD. */
1453 encode_sizeq (aarch64_inst
*inst
)
1456 enum aarch64_field_kind kind
;
1459 /* Get the index of the operand whose information we are going to use
1460 to encode the size and Q fields.
1461 This is deduced from the possible valid qualifier lists. */
1462 idx
= aarch64_select_operand_for_sizeq_field_coding (inst
->opcode
);
1463 DEBUG_TRACE ("idx: %d; qualifier: %s", idx
,
1464 aarch64_get_qualifier_name (inst
->operands
[idx
].qualifier
));
1465 sizeq
= aarch64_get_qualifier_standard_value (inst
->operands
[idx
].qualifier
);
1467 insert_field (FLD_Q
, &inst
->value
, sizeq
& 0x1, inst
->opcode
->mask
);
1469 if (inst
->opcode
->iclass
== asisdlse
1470 || inst
->opcode
->iclass
== asisdlsep
1471 || inst
->opcode
->iclass
== asisdlso
1472 || inst
->opcode
->iclass
== asisdlsop
)
1473 kind
= FLD_vldst_size
;
1476 insert_field (kind
, &inst
->value
, (sizeq
>> 1) & 0x3, inst
->opcode
->mask
);
1479 /* Opcodes that have fields shared by multiple operands are usually flagged
1480 with flags. In this function, we detect such flags and use the
1481 information in one of the related operands to do the encoding. The 'one'
1482 operand is not any operand but one of the operands that has the enough
1483 information for such an encoding. */
1486 do_special_encoding (struct aarch64_inst
*inst
)
1489 aarch64_insn value
= 0;
1491 DEBUG_TRACE ("enter with coding 0x%x", (uint32_t) inst
->value
);
1493 /* Condition for truly conditional executed instructions, e.g. b.cond. */
1494 if (inst
->opcode
->flags
& F_COND
)
1496 insert_field (FLD_cond2
, &inst
->value
, inst
->cond
->value
, 0);
1498 if (inst
->opcode
->flags
& F_SF
)
1500 idx
= select_operand_for_sf_field_coding (inst
->opcode
);
1501 value
= (inst
->operands
[idx
].qualifier
== AARCH64_OPND_QLF_X
1502 || inst
->operands
[idx
].qualifier
== AARCH64_OPND_QLF_SP
)
1504 insert_field (FLD_sf
, &inst
->value
, value
, 0);
1505 if (inst
->opcode
->flags
& F_N
)
1506 insert_field (FLD_N
, &inst
->value
, value
, inst
->opcode
->mask
);
1508 if (inst
->opcode
->flags
& F_LSE_SZ
)
1510 idx
= select_operand_for_sf_field_coding (inst
->opcode
);
1511 value
= (inst
->operands
[idx
].qualifier
== AARCH64_OPND_QLF_X
1512 || inst
->operands
[idx
].qualifier
== AARCH64_OPND_QLF_SP
)
1514 insert_field (FLD_lse_sz
, &inst
->value
, value
, 0);
1516 if (inst
->opcode
->flags
& F_SIZEQ
)
1517 encode_sizeq (inst
);
1518 if (inst
->opcode
->flags
& F_FPTYPE
)
1520 idx
= select_operand_for_fptype_field_coding (inst
->opcode
);
1521 switch (inst
->operands
[idx
].qualifier
)
1523 case AARCH64_OPND_QLF_S_S
: value
= 0; break;
1524 case AARCH64_OPND_QLF_S_D
: value
= 1; break;
1525 case AARCH64_OPND_QLF_S_H
: value
= 3; break;
1526 default: assert (0);
1528 insert_field (FLD_type
, &inst
->value
, value
, 0);
1530 if (inst
->opcode
->flags
& F_SSIZE
)
1532 enum aarch64_opnd_qualifier qualifier
;
1533 idx
= select_operand_for_scalar_size_field_coding (inst
->opcode
);
1534 qualifier
= inst
->operands
[idx
].qualifier
;
1535 assert (qualifier
>= AARCH64_OPND_QLF_S_B
1536 && qualifier
<= AARCH64_OPND_QLF_S_Q
);
1537 value
= aarch64_get_qualifier_standard_value (qualifier
);
1538 insert_field (FLD_size
, &inst
->value
, value
, inst
->opcode
->mask
);
1540 if (inst
->opcode
->flags
& F_T
)
1542 int num
; /* num of consecutive '0's on the right side of imm5<3:0>. */
1543 aarch64_field field
= {0, 0};
1544 enum aarch64_opnd_qualifier qualifier
;
1547 qualifier
= inst
->operands
[idx
].qualifier
;
1548 assert (aarch64_get_operand_class (inst
->opcode
->operands
[0])
1549 == AARCH64_OPND_CLASS_SIMD_REG
1550 && qualifier
>= AARCH64_OPND_QLF_V_8B
1551 && qualifier
<= AARCH64_OPND_QLF_V_2D
);
1562 value
= aarch64_get_qualifier_standard_value (qualifier
);
1563 insert_field (FLD_Q
, &inst
->value
, value
& 0x1, inst
->opcode
->mask
);
1564 num
= (int) value
>> 1;
1565 assert (num
>= 0 && num
<= 3);
1566 gen_sub_field (FLD_imm5
, 0, num
+ 1, &field
);
1567 insert_field_2 (&field
, &inst
->value
, 1 << num
, inst
->opcode
->mask
);
1569 if (inst
->opcode
->flags
& F_GPRSIZE_IN_Q
)
1571 /* Use Rt to encode in the case of e.g.
1572 STXP <Ws>, <Xt1>, <Xt2>, [<Xn|SP>{,#0}]. */
1573 enum aarch64_opnd_qualifier qualifier
;
1574 idx
= aarch64_operand_index (inst
->opcode
->operands
, AARCH64_OPND_Rt
);
1576 /* Otherwise use the result operand, which has to be a integer
1579 assert (idx
== 0 || idx
== 1);
1580 assert (aarch64_get_operand_class (inst
->opcode
->operands
[idx
])
1581 == AARCH64_OPND_CLASS_INT_REG
);
1582 qualifier
= inst
->operands
[idx
].qualifier
;
1583 insert_field (FLD_Q
, &inst
->value
,
1584 aarch64_get_qualifier_standard_value (qualifier
), 0);
1586 if (inst
->opcode
->flags
& F_LDS_SIZE
)
1588 /* e.g. LDRSB <Wt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
1589 enum aarch64_opnd_qualifier qualifier
;
1590 aarch64_field field
= {0, 0};
1591 assert (aarch64_get_operand_class (inst
->opcode
->operands
[0])
1592 == AARCH64_OPND_CLASS_INT_REG
);
1593 gen_sub_field (FLD_opc
, 0, 1, &field
);
1594 qualifier
= inst
->operands
[0].qualifier
;
1595 insert_field_2 (&field
, &inst
->value
,
1596 1 - aarch64_get_qualifier_standard_value (qualifier
), 0);
1598 /* Miscellaneous encoding as the last step. */
1599 if (inst
->opcode
->flags
& F_MISC
)
1600 do_misc_encoding (inst
);
1602 DEBUG_TRACE ("exit with coding 0x%x", (uint32_t) inst
->value
);
1605 /* Some instructions (including all SVE ones) use the instruction class
1606 to describe how a qualifiers_list index is represented in the instruction
1607 encoding. If INST is such an instruction, encode the chosen qualifier
1611 aarch64_encode_variant_using_iclass (struct aarch64_inst
*inst
)
1613 switch (inst
->opcode
->iclass
)
1616 insert_fields (&inst
->value
, aarch64_get_variant (inst
),
1617 0, 2, FLD_SVE_M_14
, FLD_size
);
1621 case sve_shift_pred
:
1622 case sve_shift_unpred
:
1623 /* For indices and shift amounts, the variant is encoded as
1624 part of the immediate. */
1628 /* For sve_limm, the .B, .H, and .S forms are just a convenience
1629 and depend on the immediate. They don't have a separate
1634 /* sve_misc instructions have only a single variant. */
1638 insert_fields (&inst
->value
, aarch64_get_variant (inst
),
1639 0, 2, FLD_SVE_M_16
, FLD_size
);
1643 insert_field (FLD_SVE_M_4
, &inst
->value
, aarch64_get_variant (inst
), 0);
1648 insert_field (FLD_size
, &inst
->value
, aarch64_get_variant (inst
), 0);
1652 insert_field (FLD_size
, &inst
->value
, aarch64_get_variant (inst
) + 1, 0);
1656 insert_field (FLD_SVE_sz
, &inst
->value
, aarch64_get_variant (inst
), 0);
1664 /* Converters converting an alias opcode instruction to its real form. */
1666 /* ROR <Wd>, <Ws>, #<shift>
1668 EXTR <Wd>, <Ws>, <Ws>, #<shift>. */
1670 convert_ror_to_extr (aarch64_inst
*inst
)
1672 copy_operand_info (inst
, 3, 2);
1673 copy_operand_info (inst
, 2, 1);
1676 /* UXTL<Q> <Vd>.<Ta>, <Vn>.<Tb>
1678 USHLL<Q> <Vd>.<Ta>, <Vn>.<Tb>, #0. */
1680 convert_xtl_to_shll (aarch64_inst
*inst
)
1682 inst
->operands
[2].qualifier
= inst
->operands
[1].qualifier
;
1683 inst
->operands
[2].imm
.value
= 0;
1687 LSR <Xd>, <Xn>, #<shift>
1689 UBFM <Xd>, <Xn>, #<shift>, #63. */
1691 convert_sr_to_bfm (aarch64_inst
*inst
)
1693 inst
->operands
[3].imm
.value
=
1694 inst
->operands
[2].qualifier
== AARCH64_OPND_QLF_imm_0_31
? 31 : 63;
1697 /* Convert MOV to ORR. */
1699 convert_mov_to_orr (aarch64_inst
*inst
)
1701 /* MOV <Vd>.<T>, <Vn>.<T>
1703 ORR <Vd>.<T>, <Vn>.<T>, <Vn>.<T>. */
1704 copy_operand_info (inst
, 2, 1);
1707 /* When <imms> >= <immr>, the instruction written:
1708 SBFX <Xd>, <Xn>, #<lsb>, #<width>
1710 SBFM <Xd>, <Xn>, #<lsb>, #(<lsb>+<width>-1). */
1713 convert_bfx_to_bfm (aarch64_inst
*inst
)
1717 /* Convert the operand. */
1718 lsb
= inst
->operands
[2].imm
.value
;
1719 width
= inst
->operands
[3].imm
.value
;
1720 inst
->operands
[2].imm
.value
= lsb
;
1721 inst
->operands
[3].imm
.value
= lsb
+ width
- 1;
1724 /* When <imms> < <immr>, the instruction written:
1725 SBFIZ <Xd>, <Xn>, #<lsb>, #<width>
1727 SBFM <Xd>, <Xn>, #((64-<lsb>)&0x3f), #(<width>-1). */
1730 convert_bfi_to_bfm (aarch64_inst
*inst
)
1734 /* Convert the operand. */
1735 lsb
= inst
->operands
[2].imm
.value
;
1736 width
= inst
->operands
[3].imm
.value
;
1737 if (inst
->operands
[2].qualifier
== AARCH64_OPND_QLF_imm_0_31
)
1739 inst
->operands
[2].imm
.value
= (32 - lsb
) & 0x1f;
1740 inst
->operands
[3].imm
.value
= width
- 1;
1744 inst
->operands
[2].imm
.value
= (64 - lsb
) & 0x3f;
1745 inst
->operands
[3].imm
.value
= width
- 1;
1749 /* The instruction written:
1750 BFC <Xd>, #<lsb>, #<width>
1752 BFM <Xd>, XZR, #((64-<lsb>)&0x3f), #(<width>-1). */
1755 convert_bfc_to_bfm (aarch64_inst
*inst
)
1760 copy_operand_info (inst
, 3, 2);
1761 copy_operand_info (inst
, 2, 1);
1762 copy_operand_info (inst
, 1, 0);
1763 inst
->operands
[1].reg
.regno
= 0x1f;
1765 /* Convert the immediate operand. */
1766 lsb
= inst
->operands
[2].imm
.value
;
1767 width
= inst
->operands
[3].imm
.value
;
1768 if (inst
->operands
[2].qualifier
== AARCH64_OPND_QLF_imm_0_31
)
1770 inst
->operands
[2].imm
.value
= (32 - lsb
) & 0x1f;
1771 inst
->operands
[3].imm
.value
= width
- 1;
1775 inst
->operands
[2].imm
.value
= (64 - lsb
) & 0x3f;
1776 inst
->operands
[3].imm
.value
= width
- 1;
1780 /* The instruction written:
1781 LSL <Xd>, <Xn>, #<shift>
1783 UBFM <Xd>, <Xn>, #((64-<shift>)&0x3f), #(63-<shift>). */
1786 convert_lsl_to_ubfm (aarch64_inst
*inst
)
1788 int64_t shift
= inst
->operands
[2].imm
.value
;
1790 if (inst
->operands
[2].qualifier
== AARCH64_OPND_QLF_imm_0_31
)
1792 inst
->operands
[2].imm
.value
= (32 - shift
) & 0x1f;
1793 inst
->operands
[3].imm
.value
= 31 - shift
;
1797 inst
->operands
[2].imm
.value
= (64 - shift
) & 0x3f;
1798 inst
->operands
[3].imm
.value
= 63 - shift
;
1802 /* CINC <Wd>, <Wn>, <cond>
1804 CSINC <Wd>, <Wn>, <Wn>, invert(<cond>). */
1807 convert_to_csel (aarch64_inst
*inst
)
1809 copy_operand_info (inst
, 3, 2);
1810 copy_operand_info (inst
, 2, 1);
1811 inst
->operands
[3].cond
= get_inverted_cond (inst
->operands
[3].cond
);
1814 /* CSET <Wd>, <cond>
1816 CSINC <Wd>, WZR, WZR, invert(<cond>). */
1819 convert_cset_to_csinc (aarch64_inst
*inst
)
1821 copy_operand_info (inst
, 3, 1);
1822 copy_operand_info (inst
, 2, 0);
1823 copy_operand_info (inst
, 1, 0);
1824 inst
->operands
[1].reg
.regno
= 0x1f;
1825 inst
->operands
[2].reg
.regno
= 0x1f;
1826 inst
->operands
[3].cond
= get_inverted_cond (inst
->operands
[3].cond
);
1831 MOVZ <Wd>, #<imm16>, LSL #<shift>. */
1834 convert_mov_to_movewide (aarch64_inst
*inst
)
1837 uint32_t shift_amount
;
1840 switch (inst
->opcode
->op
)
1842 case OP_MOV_IMM_WIDE
:
1843 value
= inst
->operands
[1].imm
.value
;
1845 case OP_MOV_IMM_WIDEN
:
1846 value
= ~inst
->operands
[1].imm
.value
;
1851 inst
->operands
[1].type
= AARCH64_OPND_HALF
;
1852 is32
= inst
->operands
[0].qualifier
== AARCH64_OPND_QLF_W
;
1853 if (! aarch64_wide_constant_p (value
, is32
, &shift_amount
))
1854 /* The constraint check should have guaranteed this wouldn't happen. */
1856 value
>>= shift_amount
;
1858 inst
->operands
[1].imm
.value
= value
;
1859 inst
->operands
[1].shifter
.kind
= AARCH64_MOD_LSL
;
1860 inst
->operands
[1].shifter
.amount
= shift_amount
;
1865 ORR <Wd>, WZR, #<imm>. */
1868 convert_mov_to_movebitmask (aarch64_inst
*inst
)
1870 copy_operand_info (inst
, 2, 1);
1871 inst
->operands
[1].reg
.regno
= 0x1f;
1872 inst
->operands
[1].skip
= 0;
1875 /* Some alias opcodes are assembled by being converted to their real-form. */
1878 convert_to_real (aarch64_inst
*inst
, const aarch64_opcode
*real
)
1880 const aarch64_opcode
*alias
= inst
->opcode
;
1882 if ((alias
->flags
& F_CONV
) == 0)
1883 goto convert_to_real_return
;
1889 convert_sr_to_bfm (inst
);
1892 convert_lsl_to_ubfm (inst
);
1897 convert_to_csel (inst
);
1901 convert_cset_to_csinc (inst
);
1906 convert_bfx_to_bfm (inst
);
1911 convert_bfi_to_bfm (inst
);
1914 convert_bfc_to_bfm (inst
);
1917 convert_mov_to_orr (inst
);
1919 case OP_MOV_IMM_WIDE
:
1920 case OP_MOV_IMM_WIDEN
:
1921 convert_mov_to_movewide (inst
);
1923 case OP_MOV_IMM_LOG
:
1924 convert_mov_to_movebitmask (inst
);
1927 convert_ror_to_extr (inst
);
1933 convert_xtl_to_shll (inst
);
1939 convert_to_real_return
:
1940 aarch64_replace_opcode (inst
, real
);
1943 /* Encode *INST_ORI of the opcode code OPCODE.
1944 Return the encoded result in *CODE and if QLF_SEQ is not NULL, return the
1945 matched operand qualifier sequence in *QLF_SEQ. */
1948 aarch64_opcode_encode (const aarch64_opcode
*opcode
,
1949 const aarch64_inst
*inst_ori
, aarch64_insn
*code
,
1950 aarch64_opnd_qualifier_t
*qlf_seq
,
1951 aarch64_operand_error
*mismatch_detail
)
1954 const aarch64_opcode
*aliased
;
1955 aarch64_inst copy
, *inst
;
1957 DEBUG_TRACE ("enter with %s", opcode
->name
);
1959 /* Create a copy of *INST_ORI, so that we can do any change we want. */
1963 assert (inst
->opcode
== NULL
|| inst
->opcode
== opcode
);
1964 if (inst
->opcode
== NULL
)
1965 inst
->opcode
= opcode
;
1967 /* Constrain the operands.
1968 After passing this, the encoding is guaranteed to succeed. */
1969 if (aarch64_match_operands_constraint (inst
, mismatch_detail
) == 0)
1971 DEBUG_TRACE ("FAIL since operand constraint not met");
1975 /* Get the base value.
1976 Note: this has to be before the aliasing handling below in order to
1977 get the base value from the alias opcode before we move on to the
1978 aliased opcode for encoding. */
1979 inst
->value
= opcode
->opcode
;
1981 /* No need to do anything else if the opcode does not have any operand. */
1982 if (aarch64_num_of_operands (opcode
) == 0)
1985 /* Assign operand indexes and check types. Also put the matched
1986 operand qualifiers in *QLF_SEQ to return. */
1987 for (i
= 0; i
< AARCH64_MAX_OPND_NUM
; ++i
)
1989 assert (opcode
->operands
[i
] == inst
->operands
[i
].type
);
1990 inst
->operands
[i
].idx
= i
;
1991 if (qlf_seq
!= NULL
)
1992 *qlf_seq
= inst
->operands
[i
].qualifier
;
1995 aliased
= aarch64_find_real_opcode (opcode
);
1996 /* If the opcode is an alias and it does not ask for direct encoding by
1997 itself, the instruction will be transformed to the form of real opcode
1998 and the encoding will be carried out using the rules for the aliased
2000 if (aliased
!= NULL
&& (opcode
->flags
& F_CONV
))
2002 DEBUG_TRACE ("real opcode '%s' has been found for the alias %s",
2003 aliased
->name
, opcode
->name
);
2004 /* Convert the operands to the form of the real opcode. */
2005 convert_to_real (inst
, aliased
);
2009 aarch64_opnd_info
*info
= inst
->operands
;
2011 /* Call the inserter of each operand. */
2012 for (i
= 0; i
< AARCH64_MAX_OPND_NUM
; ++i
, ++info
)
2014 const aarch64_operand
*opnd
;
2015 enum aarch64_opnd type
= opcode
->operands
[i
];
2016 if (type
== AARCH64_OPND_NIL
)
2020 DEBUG_TRACE ("skip the incomplete operand %d", i
);
2023 opnd
= &aarch64_operands
[type
];
2024 if (operand_has_inserter (opnd
)
2025 && !aarch64_insert_operand (opnd
, info
, &inst
->value
, inst
,
2030 /* Call opcode encoders indicated by flags. */
2031 if (opcode_has_special_coder (opcode
))
2032 do_special_encoding (inst
);
2034 /* Possibly use the instruction class to encode the chosen qualifier
2036 aarch64_encode_variant_using_iclass (inst
);
2039 DEBUG_TRACE ("exit with %s", opcode
->name
);
2041 *code
= inst
->value
;