mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-25 11:04:18 +08:00
[AArch64][SVE 27/32] Add SVE integer immediate operands
This patch adds the new SVE integer immediate operands. There are three kinds: - simple signed and unsigned ranges, but with new widths and positions. - 13-bit logical immediates. These have the same form as in base AArch64, but at a different bit position. In the case of the "MOV Zn.<T>, #<limm>" alias of DUPM, the logical immediate <limm> is not allowed to be a valid DUP immediate, since DUP is preferred over DUPM for constants that both instructions can handle. - a new 9-bit arithmetic immediate, of the form "<imm8>{, LSL #8}". In some contexts the operand is signed and in others it's unsigned. As an extension, we allow shifted immediates to be written as a single integer, e.g. "#256" is equivalent to "#1, LSL #8". We also use the shiftless form as the preferred disassembly, except for the special case of "#0, LSL #8" (a redundant encoding of 0). include/ * opcode/aarch64.h (AARCH64_OPND_SIMM5): New aarch64_opnd. (AARCH64_OPND_SVE_AIMM, AARCH64_OPND_SVE_ASIMM) (AARCH64_OPND_SVE_INV_LIMM, AARCH64_OPND_SVE_LIMM) (AARCH64_OPND_SVE_LIMM_MOV, AARCH64_OPND_SVE_SHLIMM_PRED) (AARCH64_OPND_SVE_SHLIMM_UNPRED, AARCH64_OPND_SVE_SHRIMM_PRED) (AARCH64_OPND_SVE_SHRIMM_UNPRED, AARCH64_OPND_SVE_SIMM5) (AARCH64_OPND_SVE_SIMM5B, AARCH64_OPND_SVE_SIMM6) (AARCH64_OPND_SVE_SIMM8, AARCH64_OPND_SVE_UIMM3) (AARCH64_OPND_SVE_UIMM7, AARCH64_OPND_SVE_UIMM8) (AARCH64_OPND_SVE_UIMM8_53): Likewise. (aarch64_sve_dupm_mov_immediate_p): Declare. opcodes/ * aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE integer immediate operands. * aarch64-opc.h (FLD_SVE_immN, FLD_SVE_imm3, FLD_SVE_imm5) (FLD_SVE_imm5b, FLD_SVE_imm7, FLD_SVE_imm8, FLD_SVE_imm9) (FLD_SVE_immr, FLD_SVE_imms, FLD_SVE_tszh): New aarch64_field_kinds. * aarch64-opc.c (fields): Add corresponding entries. (operand_general_constraint_met_p): Handle the new SVE integer immediate operands. (aarch64_print_operand): Likewise. (aarch64_sve_dupm_mov_immediate_p): New function. * aarch64-opc-2.c: Regenerate. * aarch64-asm.h (ins_inv_limm, ins_sve_aimm, ins_sve_asimm) (ins_sve_limm_mov, ins_sve_shlimm, ins_sve_shrimm): New inserters. * aarch64-asm.c (aarch64_ins_limm_1): New function, split out from... (aarch64_ins_limm): ...here. (aarch64_ins_inv_limm): New function. (aarch64_ins_sve_aimm): Likewise. (aarch64_ins_sve_asimm): Likewise. (aarch64_ins_sve_limm_mov): Likewise. (aarch64_ins_sve_shlimm): Likewise. (aarch64_ins_sve_shrimm): Likewise. * aarch64-asm-2.c: Regenerate. * aarch64-dis.h (ext_inv_limm, ext_sve_aimm, ext_sve_asimm) (ext_sve_limm_mov, ext_sve_shlimm, ext_sve_shrimm): New extractors. * aarch64-dis.c (decode_limm): New function, split out from... (aarch64_ext_limm): ...here. (aarch64_ext_inv_limm): New function. (decode_sve_aimm): Likewise. (aarch64_ext_sve_aimm): Likewise. (aarch64_ext_sve_asimm): Likewise. (aarch64_ext_sve_limm_mov): Likewise. (aarch64_top_bit): Likewise. (aarch64_ext_sve_shlimm): Likewise. (aarch64_ext_sve_shrimm): Likewise. * aarch64-dis-2.c: Regenerate. gas/ * config/tc-aarch64.c (parse_operands): Handle the new SVE integer immediate operands.
This commit is contained in:
parent
98907a7049
commit
e950b34539
@ -1,3 +1,8 @@
|
||||
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* config/tc-aarch64.c (parse_operands): Handle the new SVE integer
|
||||
immediate operands.
|
||||
|
||||
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
|
||||
|
@ -5501,6 +5501,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
|
||||
break;
|
||||
|
||||
case AARCH64_OPND_CCMP_IMM:
|
||||
case AARCH64_OPND_SIMM5:
|
||||
case AARCH64_OPND_FBITS:
|
||||
case AARCH64_OPND_UIMM4:
|
||||
case AARCH64_OPND_UIMM3_OP1:
|
||||
@ -5508,10 +5509,36 @@ parse_operands (char *str, const aarch64_opcode *opcode)
|
||||
case AARCH64_OPND_IMM_VLSL:
|
||||
case AARCH64_OPND_IMM:
|
||||
case AARCH64_OPND_WIDTH:
|
||||
case AARCH64_OPND_SVE_INV_LIMM:
|
||||
case AARCH64_OPND_SVE_LIMM:
|
||||
case AARCH64_OPND_SVE_LIMM_MOV:
|
||||
case AARCH64_OPND_SVE_SHLIMM_PRED:
|
||||
case AARCH64_OPND_SVE_SHLIMM_UNPRED:
|
||||
case AARCH64_OPND_SVE_SHRIMM_PRED:
|
||||
case AARCH64_OPND_SVE_SHRIMM_UNPRED:
|
||||
case AARCH64_OPND_SVE_SIMM5:
|
||||
case AARCH64_OPND_SVE_SIMM5B:
|
||||
case AARCH64_OPND_SVE_SIMM6:
|
||||
case AARCH64_OPND_SVE_SIMM8:
|
||||
case AARCH64_OPND_SVE_UIMM3:
|
||||
case AARCH64_OPND_SVE_UIMM7:
|
||||
case AARCH64_OPND_SVE_UIMM8:
|
||||
case AARCH64_OPND_SVE_UIMM8_53:
|
||||
po_imm_nc_or_fail ();
|
||||
info->imm.value = val;
|
||||
break;
|
||||
|
||||
case AARCH64_OPND_SVE_AIMM:
|
||||
case AARCH64_OPND_SVE_ASIMM:
|
||||
po_imm_nc_or_fail ();
|
||||
info->imm.value = val;
|
||||
skip_whitespace (str);
|
||||
if (skip_past_comma (&str))
|
||||
po_misc_or_fail (parse_shift (&str, info, SHIFTED_LSL));
|
||||
else
|
||||
inst.base.operands[i].shifter.kind = AARCH64_MOD_LSL;
|
||||
break;
|
||||
|
||||
case AARCH64_OPND_SVE_PATTERN:
|
||||
po_enum_or_fail (aarch64_sve_pattern_array);
|
||||
info->imm.value = val;
|
||||
|
@ -1,3 +1,17 @@
|
||||
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* opcode/aarch64.h (AARCH64_OPND_SIMM5): New aarch64_opnd.
|
||||
(AARCH64_OPND_SVE_AIMM, AARCH64_OPND_SVE_ASIMM)
|
||||
(AARCH64_OPND_SVE_INV_LIMM, AARCH64_OPND_SVE_LIMM)
|
||||
(AARCH64_OPND_SVE_LIMM_MOV, AARCH64_OPND_SVE_SHLIMM_PRED)
|
||||
(AARCH64_OPND_SVE_SHLIMM_UNPRED, AARCH64_OPND_SVE_SHRIMM_PRED)
|
||||
(AARCH64_OPND_SVE_SHRIMM_UNPRED, AARCH64_OPND_SVE_SIMM5)
|
||||
(AARCH64_OPND_SVE_SIMM5B, AARCH64_OPND_SVE_SIMM6)
|
||||
(AARCH64_OPND_SVE_SIMM8, AARCH64_OPND_SVE_UIMM3)
|
||||
(AARCH64_OPND_SVE_UIMM7, AARCH64_OPND_SVE_UIMM8)
|
||||
(AARCH64_OPND_SVE_UIMM8_53): Likewise.
|
||||
(aarch64_sve_dupm_mov_immediate_p): Declare.
|
||||
|
||||
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
|
||||
|
@ -200,6 +200,7 @@ enum aarch64_opnd
|
||||
AARCH64_OPND_BIT_NUM, /* Immediate. */
|
||||
AARCH64_OPND_EXCEPTION,/* imm16 operand in exception instructions. */
|
||||
AARCH64_OPND_CCMP_IMM,/* Immediate in conditional compare instructions. */
|
||||
AARCH64_OPND_SIMM5, /* 5-bit signed immediate in the imm5 field. */
|
||||
AARCH64_OPND_NZCV, /* Flag bit specifier giving an alternative value for
|
||||
each condition flag. */
|
||||
|
||||
@ -289,6 +290,11 @@ enum aarch64_opnd
|
||||
AARCH64_OPND_SVE_ADDR_ZZ_LSL, /* SVE [Zn.<T>, Zm,<T>, LSL #<msz>]. */
|
||||
AARCH64_OPND_SVE_ADDR_ZZ_SXTW, /* SVE [Zn.<T>, Zm,<T>, SXTW #<msz>]. */
|
||||
AARCH64_OPND_SVE_ADDR_ZZ_UXTW, /* SVE [Zn.<T>, Zm,<T>, UXTW #<msz>]. */
|
||||
AARCH64_OPND_SVE_AIMM, /* SVE unsigned arithmetic immediate. */
|
||||
AARCH64_OPND_SVE_ASIMM, /* SVE signed arithmetic immediate. */
|
||||
AARCH64_OPND_SVE_INV_LIMM, /* SVE inverted logical immediate. */
|
||||
AARCH64_OPND_SVE_LIMM, /* SVE logical immediate. */
|
||||
AARCH64_OPND_SVE_LIMM_MOV, /* SVE logical immediate for MOV. */
|
||||
AARCH64_OPND_SVE_PATTERN, /* SVE vector pattern enumeration. */
|
||||
AARCH64_OPND_SVE_PATTERN_SCALED, /* Likewise, with additional MUL factor. */
|
||||
AARCH64_OPND_SVE_PRFOP, /* SVE prefetch operation. */
|
||||
@ -300,6 +306,18 @@ enum aarch64_opnd
|
||||
AARCH64_OPND_SVE_Pm, /* SVE p0-p15 in Pm. */
|
||||
AARCH64_OPND_SVE_Pn, /* SVE p0-p15 in Pn. */
|
||||
AARCH64_OPND_SVE_Pt, /* SVE p0-p15 in Pt. */
|
||||
AARCH64_OPND_SVE_SHLIMM_PRED, /* SVE shift left amount (predicated). */
|
||||
AARCH64_OPND_SVE_SHLIMM_UNPRED, /* SVE shift left amount (unpredicated). */
|
||||
AARCH64_OPND_SVE_SHRIMM_PRED, /* SVE shift right amount (predicated). */
|
||||
AARCH64_OPND_SVE_SHRIMM_UNPRED, /* SVE shift right amount (unpredicated). */
|
||||
AARCH64_OPND_SVE_SIMM5, /* SVE signed 5-bit immediate. */
|
||||
AARCH64_OPND_SVE_SIMM5B, /* SVE secondary signed 5-bit immediate. */
|
||||
AARCH64_OPND_SVE_SIMM6, /* SVE signed 6-bit immediate. */
|
||||
AARCH64_OPND_SVE_SIMM8, /* SVE signed 8-bit immediate. */
|
||||
AARCH64_OPND_SVE_UIMM3, /* SVE unsigned 3-bit immediate. */
|
||||
AARCH64_OPND_SVE_UIMM7, /* SVE unsigned 7-bit immediate. */
|
||||
AARCH64_OPND_SVE_UIMM8, /* SVE unsigned 8-bit immediate. */
|
||||
AARCH64_OPND_SVE_UIMM8_53, /* SVE split unsigned 8-bit immediate. */
|
||||
AARCH64_OPND_SVE_Za_5, /* SVE vector register in Za, bits [9,5]. */
|
||||
AARCH64_OPND_SVE_Za_16, /* SVE vector register in Za, bits [20,16]. */
|
||||
AARCH64_OPND_SVE_Zd, /* SVE vector register in Zd. */
|
||||
@ -1065,6 +1083,9 @@ aarch64_get_operand_name (enum aarch64_opnd);
|
||||
extern const char *
|
||||
aarch64_get_operand_desc (enum aarch64_opnd);
|
||||
|
||||
extern bfd_boolean
|
||||
aarch64_sve_dupm_mov_immediate_p (uint64_t, int);
|
||||
|
||||
#ifdef DEBUG_AARCH64
|
||||
extern int debug_dump;
|
||||
|
||||
|
@ -1,3 +1,41 @@
|
||||
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
|
||||
integer immediate operands.
|
||||
* aarch64-opc.h (FLD_SVE_immN, FLD_SVE_imm3, FLD_SVE_imm5)
|
||||
(FLD_SVE_imm5b, FLD_SVE_imm7, FLD_SVE_imm8, FLD_SVE_imm9)
|
||||
(FLD_SVE_immr, FLD_SVE_imms, FLD_SVE_tszh): New aarch64_field_kinds.
|
||||
* aarch64-opc.c (fields): Add corresponding entries.
|
||||
(operand_general_constraint_met_p): Handle the new SVE integer
|
||||
immediate operands.
|
||||
(aarch64_print_operand): Likewise.
|
||||
(aarch64_sve_dupm_mov_immediate_p): New function.
|
||||
* aarch64-opc-2.c: Regenerate.
|
||||
* aarch64-asm.h (ins_inv_limm, ins_sve_aimm, ins_sve_asimm)
|
||||
(ins_sve_limm_mov, ins_sve_shlimm, ins_sve_shrimm): New inserters.
|
||||
* aarch64-asm.c (aarch64_ins_limm_1): New function, split out from...
|
||||
(aarch64_ins_limm): ...here.
|
||||
(aarch64_ins_inv_limm): New function.
|
||||
(aarch64_ins_sve_aimm): Likewise.
|
||||
(aarch64_ins_sve_asimm): Likewise.
|
||||
(aarch64_ins_sve_limm_mov): Likewise.
|
||||
(aarch64_ins_sve_shlimm): Likewise.
|
||||
(aarch64_ins_sve_shrimm): Likewise.
|
||||
* aarch64-asm-2.c: Regenerate.
|
||||
* aarch64-dis.h (ext_inv_limm, ext_sve_aimm, ext_sve_asimm)
|
||||
(ext_sve_limm_mov, ext_sve_shlimm, ext_sve_shrimm): New extractors.
|
||||
* aarch64-dis.c (decode_limm): New function, split out from...
|
||||
(aarch64_ext_limm): ...here.
|
||||
(aarch64_ext_inv_limm): New function.
|
||||
(decode_sve_aimm): Likewise.
|
||||
(aarch64_ext_sve_aimm): Likewise.
|
||||
(aarch64_ext_sve_asimm): Likewise.
|
||||
(aarch64_ext_sve_limm_mov): Likewise.
|
||||
(aarch64_top_bit): Likewise.
|
||||
(aarch64_ext_sve_shlimm): Likewise.
|
||||
(aarch64_ext_sve_shrimm): Likewise.
|
||||
* aarch64-dis-2.c: Regenerate.
|
||||
|
||||
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
|
||||
|
@ -480,12 +480,6 @@ aarch64_insert_operand (const aarch64_operand *self,
|
||||
case 27:
|
||||
case 35:
|
||||
case 36:
|
||||
case 129:
|
||||
case 130:
|
||||
case 131:
|
||||
case 132:
|
||||
case 133:
|
||||
case 134:
|
||||
case 135:
|
||||
case 136:
|
||||
case 137:
|
||||
@ -494,7 +488,13 @@ aarch64_insert_operand (const aarch64_operand *self,
|
||||
case 140:
|
||||
case 141:
|
||||
case 142:
|
||||
case 145:
|
||||
case 155:
|
||||
case 156:
|
||||
case 157:
|
||||
case 158:
|
||||
case 159:
|
||||
case 160:
|
||||
case 163:
|
||||
return aarch64_ins_regno (self, info, code, inst);
|
||||
case 12:
|
||||
return aarch64_ins_reg_extended (self, info, code, inst);
|
||||
@ -527,12 +527,21 @@ aarch64_insert_operand (const aarch64_operand *self,
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 67:
|
||||
case 59:
|
||||
case 68:
|
||||
case 69:
|
||||
case 70:
|
||||
case 126:
|
||||
case 128:
|
||||
case 71:
|
||||
case 132:
|
||||
case 134:
|
||||
case 147:
|
||||
case 148:
|
||||
case 149:
|
||||
case 150:
|
||||
case 151:
|
||||
case 152:
|
||||
case 153:
|
||||
case 154:
|
||||
return aarch64_ins_imm (self, info, code, inst);
|
||||
case 38:
|
||||
case 39:
|
||||
@ -543,61 +552,61 @@ aarch64_insert_operand (const aarch64_operand *self,
|
||||
return aarch64_ins_advsimd_imm_modified (self, info, code, inst);
|
||||
case 46:
|
||||
return aarch64_ins_fpimm (self, info, code, inst);
|
||||
case 59:
|
||||
return aarch64_ins_limm (self, info, code, inst);
|
||||
case 60:
|
||||
return aarch64_ins_aimm (self, info, code, inst);
|
||||
case 130:
|
||||
return aarch64_ins_limm (self, info, code, inst);
|
||||
case 61:
|
||||
return aarch64_ins_imm_half (self, info, code, inst);
|
||||
return aarch64_ins_aimm (self, info, code, inst);
|
||||
case 62:
|
||||
return aarch64_ins_imm_half (self, info, code, inst);
|
||||
case 63:
|
||||
return aarch64_ins_fbits (self, info, code, inst);
|
||||
case 64:
|
||||
case 65:
|
||||
case 66:
|
||||
return aarch64_ins_cond (self, info, code, inst);
|
||||
case 71:
|
||||
case 77:
|
||||
return aarch64_ins_addr_simple (self, info, code, inst);
|
||||
case 72:
|
||||
return aarch64_ins_addr_regoff (self, info, code, inst);
|
||||
case 78:
|
||||
return aarch64_ins_addr_simple (self, info, code, inst);
|
||||
case 73:
|
||||
return aarch64_ins_addr_regoff (self, info, code, inst);
|
||||
case 74:
|
||||
case 75:
|
||||
return aarch64_ins_addr_simm (self, info, code, inst);
|
||||
case 76:
|
||||
return aarch64_ins_addr_simm (self, info, code, inst);
|
||||
case 77:
|
||||
return aarch64_ins_addr_uimm12 (self, info, code, inst);
|
||||
case 78:
|
||||
return aarch64_ins_simd_addr_post (self, info, code, inst);
|
||||
case 79:
|
||||
return aarch64_ins_sysreg (self, info, code, inst);
|
||||
return aarch64_ins_simd_addr_post (self, info, code, inst);
|
||||
case 80:
|
||||
return aarch64_ins_pstatefield (self, info, code, inst);
|
||||
return aarch64_ins_sysreg (self, info, code, inst);
|
||||
case 81:
|
||||
return aarch64_ins_pstatefield (self, info, code, inst);
|
||||
case 82:
|
||||
case 83:
|
||||
case 84:
|
||||
return aarch64_ins_sysins_op (self, info, code, inst);
|
||||
case 85:
|
||||
return aarch64_ins_sysins_op (self, info, code, inst);
|
||||
case 86:
|
||||
return aarch64_ins_barrier (self, info, code, inst);
|
||||
case 87:
|
||||
return aarch64_ins_prfop (self, info, code, inst);
|
||||
return aarch64_ins_barrier (self, info, code, inst);
|
||||
case 88:
|
||||
return aarch64_ins_hint (self, info, code, inst);
|
||||
return aarch64_ins_prfop (self, info, code, inst);
|
||||
case 89:
|
||||
return aarch64_ins_hint (self, info, code, inst);
|
||||
case 90:
|
||||
case 91:
|
||||
case 92:
|
||||
return aarch64_ins_sve_addr_ri_s4xvl (self, info, code, inst);
|
||||
case 93:
|
||||
return aarch64_ins_sve_addr_ri_s6xvl (self, info, code, inst);
|
||||
return aarch64_ins_sve_addr_ri_s4xvl (self, info, code, inst);
|
||||
case 94:
|
||||
return aarch64_ins_sve_addr_ri_s9xvl (self, info, code, inst);
|
||||
return aarch64_ins_sve_addr_ri_s6xvl (self, info, code, inst);
|
||||
case 95:
|
||||
return aarch64_ins_sve_addr_ri_s9xvl (self, info, code, inst);
|
||||
case 96:
|
||||
case 97:
|
||||
case 98:
|
||||
return aarch64_ins_sve_addr_ri_u6 (self, info, code, inst);
|
||||
case 99:
|
||||
return aarch64_ins_sve_addr_ri_u6 (self, info, code, inst);
|
||||
case 100:
|
||||
case 101:
|
||||
case 102:
|
||||
@ -609,8 +618,8 @@ aarch64_insert_operand (const aarch64_operand *self,
|
||||
case 108:
|
||||
case 109:
|
||||
case 110:
|
||||
return aarch64_ins_sve_addr_rr_lsl (self, info, code, inst);
|
||||
case 111:
|
||||
return aarch64_ins_sve_addr_rr_lsl (self, info, code, inst);
|
||||
case 112:
|
||||
case 113:
|
||||
case 114:
|
||||
@ -618,24 +627,39 @@ aarch64_insert_operand (const aarch64_operand *self,
|
||||
case 116:
|
||||
case 117:
|
||||
case 118:
|
||||
return aarch64_ins_sve_addr_rz_xtw (self, info, code, inst);
|
||||
case 119:
|
||||
return aarch64_ins_sve_addr_rz_xtw (self, info, code, inst);
|
||||
case 120:
|
||||
case 121:
|
||||
case 122:
|
||||
return aarch64_ins_sve_addr_zi_u5 (self, info, code, inst);
|
||||
case 123:
|
||||
return aarch64_ins_sve_addr_zz_lsl (self, info, code, inst);
|
||||
return aarch64_ins_sve_addr_zi_u5 (self, info, code, inst);
|
||||
case 124:
|
||||
return aarch64_ins_sve_addr_zz_sxtw (self, info, code, inst);
|
||||
return aarch64_ins_sve_addr_zz_lsl (self, info, code, inst);
|
||||
case 125:
|
||||
return aarch64_ins_sve_addr_zz_sxtw (self, info, code, inst);
|
||||
case 126:
|
||||
return aarch64_ins_sve_addr_zz_uxtw (self, info, code, inst);
|
||||
case 127:
|
||||
return aarch64_ins_sve_aimm (self, info, code, inst);
|
||||
case 128:
|
||||
return aarch64_ins_sve_asimm (self, info, code, inst);
|
||||
case 129:
|
||||
return aarch64_ins_inv_limm (self, info, code, inst);
|
||||
case 131:
|
||||
return aarch64_ins_sve_limm_mov (self, info, code, inst);
|
||||
case 133:
|
||||
return aarch64_ins_sve_scale (self, info, code, inst);
|
||||
case 143:
|
||||
return aarch64_ins_sve_index (self, info, code, inst);
|
||||
case 144:
|
||||
return aarch64_ins_sve_shlimm (self, info, code, inst);
|
||||
case 145:
|
||||
case 146:
|
||||
return aarch64_ins_sve_shrimm (self, info, code, inst);
|
||||
case 161:
|
||||
return aarch64_ins_sve_index (self, info, code, inst);
|
||||
case 162:
|
||||
case 164:
|
||||
return aarch64_ins_sve_reglist (self, info, code, inst);
|
||||
default: assert (0); abort ();
|
||||
}
|
||||
|
@ -452,17 +452,18 @@ aarch64_ins_aimm (const aarch64_operand *self, const aarch64_opnd_info *info,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Insert logical/bitmask immediate for e.g. the last operand in
|
||||
ORR <Wd|WSP>, <Wn>, #<imm>. */
|
||||
const char *
|
||||
aarch64_ins_limm (const aarch64_operand *self, const aarch64_opnd_info *info,
|
||||
aarch64_insn *code, const aarch64_inst *inst ATTRIBUTE_UNUSED)
|
||||
/* Common routine shared by aarch64_ins{,_inv}_limm. INVERT_P says whether
|
||||
the operand should be inverted before encoding. */
|
||||
static const char *
|
||||
aarch64_ins_limm_1 (const aarch64_operand *self,
|
||||
const aarch64_opnd_info *info, aarch64_insn *code,
|
||||
const aarch64_inst *inst, bfd_boolean invert_p)
|
||||
{
|
||||
aarch64_insn value;
|
||||
uint64_t imm = info->imm.value;
|
||||
int esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier);
|
||||
|
||||
if (inst->opcode->op == OP_BIC)
|
||||
if (invert_p)
|
||||
imm = ~imm;
|
||||
if (aarch64_logical_immediate_p (imm, esize, &value) == FALSE)
|
||||
/* The constraint check should have guaranteed this wouldn't happen. */
|
||||
@ -473,6 +474,25 @@ aarch64_ins_limm (const aarch64_operand *self, const aarch64_opnd_info *info,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Insert logical/bitmask immediate for e.g. the last operand in
|
||||
ORR <Wd|WSP>, <Wn>, #<imm>. */
|
||||
const char *
|
||||
aarch64_ins_limm (const aarch64_operand *self, const aarch64_opnd_info *info,
|
||||
aarch64_insn *code, const aarch64_inst *inst)
|
||||
{
|
||||
return aarch64_ins_limm_1 (self, info, code, inst,
|
||||
inst->opcode->op == OP_BIC);
|
||||
}
|
||||
|
||||
/* Insert a logical/bitmask immediate for the BIC alias of AND (etc.). */
|
||||
const char *
|
||||
aarch64_ins_inv_limm (const aarch64_operand *self,
|
||||
const aarch64_opnd_info *info, aarch64_insn *code,
|
||||
const aarch64_inst *inst)
|
||||
{
|
||||
return aarch64_ins_limm_1 (self, info, code, inst, TRUE);
|
||||
}
|
||||
|
||||
/* Encode Ft for e.g. STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]
|
||||
or LDP <Qt1>, <Qt2>, [<Xn|SP>], #<imm>. */
|
||||
const char *
|
||||
@ -903,6 +923,30 @@ aarch64_ins_sve_addr_zz_uxtw (const aarch64_operand *self,
|
||||
return aarch64_ext_sve_addr_zz (self, info, code);
|
||||
}
|
||||
|
||||
/* Encode an SVE ADD/SUB immediate. */
|
||||
const char *
|
||||
aarch64_ins_sve_aimm (const aarch64_operand *self,
|
||||
const aarch64_opnd_info *info, aarch64_insn *code,
|
||||
const aarch64_inst *inst ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (info->shifter.amount == 8)
|
||||
insert_all_fields (self, code, (info->imm.value & 0xff) | 256);
|
||||
else if (info->imm.value != 0 && (info->imm.value & 0xff) == 0)
|
||||
insert_all_fields (self, code, ((info->imm.value / 256) & 0xff) | 256);
|
||||
else
|
||||
insert_all_fields (self, code, info->imm.value & 0xff);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Encode an SVE CPY/DUP immediate. */
|
||||
const char *
|
||||
aarch64_ins_sve_asimm (const aarch64_operand *self,
|
||||
const aarch64_opnd_info *info, aarch64_insn *code,
|
||||
const aarch64_inst *inst)
|
||||
{
|
||||
return aarch64_ins_sve_aimm (self, info, code, inst);
|
||||
}
|
||||
|
||||
/* Encode Zn[MM], where MM has a 7-bit triangular encoding. The fields
|
||||
array specifies which field to use for Zn. MM is encoded in the
|
||||
concatenation of imm5 and SVE_tszh, with imm5 being the less
|
||||
@ -919,6 +963,15 @@ aarch64_ins_sve_index (const aarch64_operand *self,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Encode a logical/bitmask immediate for the MOV alias of SVE DUPM. */
|
||||
const char *
|
||||
aarch64_ins_sve_limm_mov (const aarch64_operand *self,
|
||||
const aarch64_opnd_info *info, aarch64_insn *code,
|
||||
const aarch64_inst *inst)
|
||||
{
|
||||
return aarch64_ins_limm (self, info, code, inst);
|
||||
}
|
||||
|
||||
/* Encode {Zn.<T> - Zm.<T>}. The fields array specifies which field
|
||||
to use for Zn. */
|
||||
const char *
|
||||
@ -943,6 +996,38 @@ aarch64_ins_sve_scale (const aarch64_operand *self,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Encode an SVE shift left immediate. */
|
||||
const char *
|
||||
aarch64_ins_sve_shlimm (const aarch64_operand *self,
|
||||
const aarch64_opnd_info *info, aarch64_insn *code,
|
||||
const aarch64_inst *inst)
|
||||
{
|
||||
const aarch64_opnd_info *prev_operand;
|
||||
unsigned int esize;
|
||||
|
||||
assert (info->idx > 0);
|
||||
prev_operand = &inst->operands[info->idx - 1];
|
||||
esize = aarch64_get_qualifier_esize (prev_operand->qualifier);
|
||||
insert_all_fields (self, code, 8 * esize + info->imm.value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Encode an SVE shift right immediate. */
|
||||
const char *
|
||||
aarch64_ins_sve_shrimm (const aarch64_operand *self,
|
||||
const aarch64_opnd_info *info, aarch64_insn *code,
|
||||
const aarch64_inst *inst)
|
||||
{
|
||||
const aarch64_opnd_info *prev_operand;
|
||||
unsigned int esize;
|
||||
|
||||
assert (info->idx > 0);
|
||||
prev_operand = &inst->operands[info->idx - 1];
|
||||
esize = aarch64_get_qualifier_esize (prev_operand->qualifier);
|
||||
insert_all_fields (self, code, 16 * esize - info->imm.value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Miscellaneous encoding functions. */
|
||||
|
||||
/* Encode size[0], i.e. bit 22, for
|
||||
|
@ -54,6 +54,7 @@ AARCH64_DECL_OPD_INSERTER (ins_fpimm);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_fbits);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_aimm);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_limm);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_inv_limm);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_ft);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_addr_simple);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_addr_regoff);
|
||||
@ -79,9 +80,14 @@ AARCH64_DECL_OPD_INSERTER (ins_sve_addr_zi_u5);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_sve_addr_zz_lsl);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_sve_addr_zz_sxtw);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_sve_addr_zz_uxtw);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_sve_aimm);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_sve_asimm);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_sve_index);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_sve_limm_mov);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_sve_reglist);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_sve_scale);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_sve_shlimm);
|
||||
AARCH64_DECL_OPD_INSERTER (ins_sve_shrimm);
|
||||
|
||||
#undef AARCH64_DECL_OPD_INSERTER
|
||||
|
||||
|
@ -10426,12 +10426,6 @@ aarch64_extract_operand (const aarch64_operand *self,
|
||||
case 27:
|
||||
case 35:
|
||||
case 36:
|
||||
case 129:
|
||||
case 130:
|
||||
case 131:
|
||||
case 132:
|
||||
case 133:
|
||||
case 134:
|
||||
case 135:
|
||||
case 136:
|
||||
case 137:
|
||||
@ -10440,7 +10434,13 @@ aarch64_extract_operand (const aarch64_operand *self,
|
||||
case 140:
|
||||
case 141:
|
||||
case 142:
|
||||
case 145:
|
||||
case 155:
|
||||
case 156:
|
||||
case 157:
|
||||
case 158:
|
||||
case 159:
|
||||
case 160:
|
||||
case 163:
|
||||
return aarch64_ext_regno (self, info, code, inst);
|
||||
case 8:
|
||||
return aarch64_ext_regrt_sysins (self, info, code, inst);
|
||||
@ -10477,13 +10477,22 @@ aarch64_extract_operand (const aarch64_operand *self,
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 66:
|
||||
case 59:
|
||||
case 67:
|
||||
case 68:
|
||||
case 69:
|
||||
case 70:
|
||||
case 126:
|
||||
case 128:
|
||||
case 71:
|
||||
case 132:
|
||||
case 134:
|
||||
case 147:
|
||||
case 148:
|
||||
case 149:
|
||||
case 150:
|
||||
case 151:
|
||||
case 152:
|
||||
case 153:
|
||||
case 154:
|
||||
return aarch64_ext_imm (self, info, code, inst);
|
||||
case 38:
|
||||
case 39:
|
||||
@ -10496,61 +10505,61 @@ aarch64_extract_operand (const aarch64_operand *self,
|
||||
return aarch64_ext_shll_imm (self, info, code, inst);
|
||||
case 46:
|
||||
return aarch64_ext_fpimm (self, info, code, inst);
|
||||
case 59:
|
||||
return aarch64_ext_limm (self, info, code, inst);
|
||||
case 60:
|
||||
return aarch64_ext_aimm (self, info, code, inst);
|
||||
case 130:
|
||||
return aarch64_ext_limm (self, info, code, inst);
|
||||
case 61:
|
||||
return aarch64_ext_imm_half (self, info, code, inst);
|
||||
return aarch64_ext_aimm (self, info, code, inst);
|
||||
case 62:
|
||||
return aarch64_ext_imm_half (self, info, code, inst);
|
||||
case 63:
|
||||
return aarch64_ext_fbits (self, info, code, inst);
|
||||
case 64:
|
||||
case 65:
|
||||
case 66:
|
||||
return aarch64_ext_cond (self, info, code, inst);
|
||||
case 71:
|
||||
case 77:
|
||||
return aarch64_ext_addr_simple (self, info, code, inst);
|
||||
case 72:
|
||||
return aarch64_ext_addr_regoff (self, info, code, inst);
|
||||
case 78:
|
||||
return aarch64_ext_addr_simple (self, info, code, inst);
|
||||
case 73:
|
||||
return aarch64_ext_addr_regoff (self, info, code, inst);
|
||||
case 74:
|
||||
case 75:
|
||||
return aarch64_ext_addr_simm (self, info, code, inst);
|
||||
case 76:
|
||||
return aarch64_ext_addr_simm (self, info, code, inst);
|
||||
case 77:
|
||||
return aarch64_ext_addr_uimm12 (self, info, code, inst);
|
||||
case 78:
|
||||
return aarch64_ext_simd_addr_post (self, info, code, inst);
|
||||
case 79:
|
||||
return aarch64_ext_sysreg (self, info, code, inst);
|
||||
return aarch64_ext_simd_addr_post (self, info, code, inst);
|
||||
case 80:
|
||||
return aarch64_ext_pstatefield (self, info, code, inst);
|
||||
return aarch64_ext_sysreg (self, info, code, inst);
|
||||
case 81:
|
||||
return aarch64_ext_pstatefield (self, info, code, inst);
|
||||
case 82:
|
||||
case 83:
|
||||
case 84:
|
||||
return aarch64_ext_sysins_op (self, info, code, inst);
|
||||
case 85:
|
||||
return aarch64_ext_sysins_op (self, info, code, inst);
|
||||
case 86:
|
||||
return aarch64_ext_barrier (self, info, code, inst);
|
||||
case 87:
|
||||
return aarch64_ext_prfop (self, info, code, inst);
|
||||
return aarch64_ext_barrier (self, info, code, inst);
|
||||
case 88:
|
||||
return aarch64_ext_hint (self, info, code, inst);
|
||||
return aarch64_ext_prfop (self, info, code, inst);
|
||||
case 89:
|
||||
return aarch64_ext_hint (self, info, code, inst);
|
||||
case 90:
|
||||
case 91:
|
||||
case 92:
|
||||
return aarch64_ext_sve_addr_ri_s4xvl (self, info, code, inst);
|
||||
case 93:
|
||||
return aarch64_ext_sve_addr_ri_s6xvl (self, info, code, inst);
|
||||
return aarch64_ext_sve_addr_ri_s4xvl (self, info, code, inst);
|
||||
case 94:
|
||||
return aarch64_ext_sve_addr_ri_s9xvl (self, info, code, inst);
|
||||
return aarch64_ext_sve_addr_ri_s6xvl (self, info, code, inst);
|
||||
case 95:
|
||||
return aarch64_ext_sve_addr_ri_s9xvl (self, info, code, inst);
|
||||
case 96:
|
||||
case 97:
|
||||
case 98:
|
||||
return aarch64_ext_sve_addr_ri_u6 (self, info, code, inst);
|
||||
case 99:
|
||||
return aarch64_ext_sve_addr_ri_u6 (self, info, code, inst);
|
||||
case 100:
|
||||
case 101:
|
||||
case 102:
|
||||
@ -10562,8 +10571,8 @@ aarch64_extract_operand (const aarch64_operand *self,
|
||||
case 108:
|
||||
case 109:
|
||||
case 110:
|
||||
return aarch64_ext_sve_addr_rr_lsl (self, info, code, inst);
|
||||
case 111:
|
||||
return aarch64_ext_sve_addr_rr_lsl (self, info, code, inst);
|
||||
case 112:
|
||||
case 113:
|
||||
case 114:
|
||||
@ -10571,24 +10580,39 @@ aarch64_extract_operand (const aarch64_operand *self,
|
||||
case 116:
|
||||
case 117:
|
||||
case 118:
|
||||
return aarch64_ext_sve_addr_rz_xtw (self, info, code, inst);
|
||||
case 119:
|
||||
return aarch64_ext_sve_addr_rz_xtw (self, info, code, inst);
|
||||
case 120:
|
||||
case 121:
|
||||
case 122:
|
||||
return aarch64_ext_sve_addr_zi_u5 (self, info, code, inst);
|
||||
case 123:
|
||||
return aarch64_ext_sve_addr_zz_lsl (self, info, code, inst);
|
||||
return aarch64_ext_sve_addr_zi_u5 (self, info, code, inst);
|
||||
case 124:
|
||||
return aarch64_ext_sve_addr_zz_sxtw (self, info, code, inst);
|
||||
return aarch64_ext_sve_addr_zz_lsl (self, info, code, inst);
|
||||
case 125:
|
||||
return aarch64_ext_sve_addr_zz_sxtw (self, info, code, inst);
|
||||
case 126:
|
||||
return aarch64_ext_sve_addr_zz_uxtw (self, info, code, inst);
|
||||
case 127:
|
||||
return aarch64_ext_sve_aimm (self, info, code, inst);
|
||||
case 128:
|
||||
return aarch64_ext_sve_asimm (self, info, code, inst);
|
||||
case 129:
|
||||
return aarch64_ext_inv_limm (self, info, code, inst);
|
||||
case 131:
|
||||
return aarch64_ext_sve_limm_mov (self, info, code, inst);
|
||||
case 133:
|
||||
return aarch64_ext_sve_scale (self, info, code, inst);
|
||||
case 143:
|
||||
return aarch64_ext_sve_index (self, info, code, inst);
|
||||
case 144:
|
||||
return aarch64_ext_sve_shlimm (self, info, code, inst);
|
||||
case 145:
|
||||
case 146:
|
||||
return aarch64_ext_sve_shrimm (self, info, code, inst);
|
||||
case 161:
|
||||
return aarch64_ext_sve_index (self, info, code, inst);
|
||||
case 162:
|
||||
case 164:
|
||||
return aarch64_ext_sve_reglist (self, info, code, inst);
|
||||
default: assert (0); abort ();
|
||||
}
|
||||
|
@ -734,32 +734,21 @@ aarch64_ext_aimm (const aarch64_operand *self ATTRIBUTE_UNUSED,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Decode logical immediate for e.g. ORR <Wd|WSP>, <Wn>, #<imm>. */
|
||||
|
||||
int
|
||||
aarch64_ext_limm (const aarch64_operand *self ATTRIBUTE_UNUSED,
|
||||
aarch64_opnd_info *info, const aarch64_insn code,
|
||||
const aarch64_inst *inst ATTRIBUTE_UNUSED)
|
||||
/* Return true if VALUE is a valid logical immediate encoding, storing the
|
||||
decoded value in *RESULT if so. ESIZE is the number of bytes in the
|
||||
decoded immediate. */
|
||||
static int
|
||||
decode_limm (uint32_t esize, aarch64_insn value, int64_t *result)
|
||||
{
|
||||
uint64_t imm, mask;
|
||||
uint32_t sf;
|
||||
uint32_t N, R, S;
|
||||
unsigned simd_size;
|
||||
aarch64_insn value;
|
||||
|
||||
value = extract_fields (code, 0, 3, FLD_N, FLD_immr, FLD_imms);
|
||||
assert (inst->operands[0].qualifier == AARCH64_OPND_QLF_W
|
||||
|| inst->operands[0].qualifier == AARCH64_OPND_QLF_X);
|
||||
sf = aarch64_get_qualifier_esize (inst->operands[0].qualifier) != 4;
|
||||
|
||||
/* value is N:immr:imms. */
|
||||
S = value & 0x3f;
|
||||
R = (value >> 6) & 0x3f;
|
||||
N = (value >> 12) & 0x1;
|
||||
|
||||
if (sf == 0 && N == 1)
|
||||
return 0;
|
||||
|
||||
/* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
|
||||
(in other words, right rotated by R), then replicated. */
|
||||
if (N != 0)
|
||||
@ -782,6 +771,10 @@ aarch64_ext_limm (const aarch64_operand *self ATTRIBUTE_UNUSED,
|
||||
/* Top bits are IGNORED. */
|
||||
R &= simd_size - 1;
|
||||
}
|
||||
|
||||
if (simd_size > esize * 8)
|
||||
return 0;
|
||||
|
||||
/* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */
|
||||
if (S == simd_size - 1)
|
||||
return 0;
|
||||
@ -803,11 +796,38 @@ aarch64_ext_limm (const aarch64_operand *self ATTRIBUTE_UNUSED,
|
||||
default: assert (0); return 0;
|
||||
}
|
||||
|
||||
info->imm.value = sf ? imm : imm & 0xffffffff;
|
||||
*result = imm & ~((uint64_t) -1 << (esize * 4) << (esize * 4));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Decode a logical immediate for e.g. ORR <Wd|WSP>, <Wn>, #<imm>. */
|
||||
int
|
||||
aarch64_ext_limm (const aarch64_operand *self,
|
||||
aarch64_opnd_info *info, const aarch64_insn code,
|
||||
const aarch64_inst *inst)
|
||||
{
|
||||
uint32_t esize;
|
||||
aarch64_insn value;
|
||||
|
||||
value = extract_fields (code, 0, 3, self->fields[0], self->fields[1],
|
||||
self->fields[2]);
|
||||
esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier);
|
||||
return decode_limm (esize, value, &info->imm.value);
|
||||
}
|
||||
|
||||
/* Decode a logical immediate for the BIC alias of AND (etc.). */
|
||||
int
|
||||
aarch64_ext_inv_limm (const aarch64_operand *self,
|
||||
aarch64_opnd_info *info, const aarch64_insn code,
|
||||
const aarch64_inst *inst)
|
||||
{
|
||||
if (!aarch64_ext_limm (self, info, code, inst))
|
||||
return 0;
|
||||
info->imm.value = ~info->imm.value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Decode Ft for e.g. STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]
|
||||
or LDP <Qt1>, <Qt2>, [<Xn|SP>], #<imm>. */
|
||||
int
|
||||
@ -1404,6 +1424,47 @@ aarch64_ext_sve_addr_zz_uxtw (const aarch64_operand *self,
|
||||
return aarch64_ext_sve_addr_zz (self, info, code, AARCH64_MOD_UXTW);
|
||||
}
|
||||
|
||||
/* Finish decoding an SVE arithmetic immediate, given that INFO already
|
||||
has the raw field value and that the low 8 bits decode to VALUE. */
|
||||
static int
|
||||
decode_sve_aimm (aarch64_opnd_info *info, int64_t value)
|
||||
{
|
||||
info->shifter.kind = AARCH64_MOD_LSL;
|
||||
info->shifter.amount = 0;
|
||||
if (info->imm.value & 0x100)
|
||||
{
|
||||
if (value == 0)
|
||||
/* Decode 0x100 as #0, LSL #8. */
|
||||
info->shifter.amount = 8;
|
||||
else
|
||||
value *= 256;
|
||||
}
|
||||
info->shifter.operator_present = (info->shifter.amount != 0);
|
||||
info->shifter.amount_present = (info->shifter.amount != 0);
|
||||
info->imm.value = value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Decode an SVE ADD/SUB immediate. */
|
||||
int
|
||||
aarch64_ext_sve_aimm (const aarch64_operand *self,
|
||||
aarch64_opnd_info *info, const aarch64_insn code,
|
||||
const aarch64_inst *inst)
|
||||
{
|
||||
return (aarch64_ext_imm (self, info, code, inst)
|
||||
&& decode_sve_aimm (info, (uint8_t) info->imm.value));
|
||||
}
|
||||
|
||||
/* Decode an SVE CPY/DUP immediate. */
|
||||
int
|
||||
aarch64_ext_sve_asimm (const aarch64_operand *self,
|
||||
aarch64_opnd_info *info, const aarch64_insn code,
|
||||
const aarch64_inst *inst)
|
||||
{
|
||||
return (aarch64_ext_imm (self, info, code, inst)
|
||||
&& decode_sve_aimm (info, (int8_t) info->imm.value));
|
||||
}
|
||||
|
||||
/* Decode Zn[MM], where MM has a 7-bit triangular encoding. The fields
|
||||
array specifies which field to use for Zn. MM is encoded in the
|
||||
concatenation of imm5 and SVE_tszh, with imm5 being the less
|
||||
@ -1425,6 +1486,17 @@ aarch64_ext_sve_index (const aarch64_operand *self,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Decode a logical immediate for the MOV alias of SVE DUPM. */
|
||||
int
|
||||
aarch64_ext_sve_limm_mov (const aarch64_operand *self,
|
||||
aarch64_opnd_info *info, const aarch64_insn code,
|
||||
const aarch64_inst *inst)
|
||||
{
|
||||
int esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier);
|
||||
return (aarch64_ext_limm (self, info, code, inst)
|
||||
&& aarch64_sve_dupm_mov_immediate_p (info->imm.value, esize));
|
||||
}
|
||||
|
||||
/* Decode {Zn.<T> - Zm.<T>}. The fields array specifies which field
|
||||
to use for Zn. The opcode-dependent value specifies the number
|
||||
of registers in the list. */
|
||||
@ -1457,6 +1529,44 @@ aarch64_ext_sve_scale (const aarch64_operand *self,
|
||||
info->shifter.amount_present = (val != 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return the top set bit in VALUE, which is expected to be relatively
|
||||
small. */
|
||||
static uint64_t
|
||||
get_top_bit (uint64_t value)
|
||||
{
|
||||
while ((value & -value) != value)
|
||||
value -= value & -value;
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Decode an SVE shift-left immediate. */
|
||||
int
|
||||
aarch64_ext_sve_shlimm (const aarch64_operand *self,
|
||||
aarch64_opnd_info *info, const aarch64_insn code,
|
||||
const aarch64_inst *inst)
|
||||
{
|
||||
if (!aarch64_ext_imm (self, info, code, inst)
|
||||
|| info->imm.value == 0)
|
||||
return 0;
|
||||
|
||||
info->imm.value -= get_top_bit (info->imm.value);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Decode an SVE shift-right immediate. */
|
||||
int
|
||||
aarch64_ext_sve_shrimm (const aarch64_operand *self,
|
||||
aarch64_opnd_info *info, const aarch64_insn code,
|
||||
const aarch64_inst *inst)
|
||||
{
|
||||
if (!aarch64_ext_imm (self, info, code, inst)
|
||||
|| info->imm.value == 0)
|
||||
return 0;
|
||||
|
||||
info->imm.value = get_top_bit (info->imm.value) * 2 - info->imm.value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Bitfields that are commonly used to encode certain operands' information
|
||||
may be partially used as part of the base opcode in some instructions.
|
||||
|
@ -76,6 +76,7 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_fpimm);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_fbits);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_aimm);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_limm);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_inv_limm);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_ft);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_addr_simple);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_addr_regoff);
|
||||
@ -101,9 +102,14 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_zi_u5);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_zz_lsl);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_zz_sxtw);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_zz_uxtw);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_aimm);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_asimm);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_index);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_limm_mov);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_reglist);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_scale);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_shlimm);
|
||||
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_shrimm);
|
||||
|
||||
#undef AARCH64_DECL_OPD_EXTRACTOR
|
||||
|
||||
|
@ -82,6 +82,7 @@ const struct aarch64_operand aarch64_operands[] =
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "BIT_NUM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_b5, FLD_b40}, "the bit number to be tested"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "EXCEPTION", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm16}, "a 16-bit unsigned immediate"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "CCMP_IMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm5}, "a 5-bit unsigned immediate"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SIMM5", OPD_F_SEXT | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm5}, "a 5-bit signed immediate"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "NZCV", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_nzcv}, "a flag bit specifier giving an alternative value for each flag"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "LIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_N,FLD_immr,FLD_imms}, "Logical immediate"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "AIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_shift,FLD_imm12}, "a 12-bit unsigned immediate with optional left shift of 12 bits"},
|
||||
@ -150,6 +151,11 @@ const struct aarch64_operand aarch64_operands[] =
|
||||
{AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_ZZ_LSL", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn,FLD_SVE_Zm_16}, "an address with a vector register offset"},
|
||||
{AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_ZZ_SXTW", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn,FLD_SVE_Zm_16}, "an address with a vector register offset"},
|
||||
{AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_ZZ_UXTW", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn,FLD_SVE_Zm_16}, "an address with a vector register offset"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_AIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm9}, "a 9-bit unsigned arithmetic operand"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_ASIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm9}, "a 9-bit signed arithmetic operand"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_INV_LIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms}, "an inverted 13-bit logical immediate"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_LIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms}, "a 13-bit logical immediate"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_LIMM_MOV", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms}, "a 13-bit logical move immediate"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_PATTERN", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_pattern}, "an enumeration value such as POW2"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_PATTERN_SCALED", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_pattern}, "an enumeration value such as POW2"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_PRFOP", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_prfop}, "an enumeration value such as PLDL1KEEP"},
|
||||
@ -161,6 +167,18 @@ const struct aarch64_operand aarch64_operands[] =
|
||||
{AARCH64_OPND_CLASS_PRED_REG, "SVE_Pm", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pm}, "an SVE predicate register"},
|
||||
{AARCH64_OPND_CLASS_PRED_REG, "SVE_Pn", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pn}, "an SVE predicate register"},
|
||||
{AARCH64_OPND_CLASS_PRED_REG, "SVE_Pt", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pt}, "an SVE predicate register"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SHLIMM_PRED", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_tszh,FLD_SVE_imm5}, "a shift-left immediate operand"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SHLIMM_UNPRED", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_tszh,FLD_imm5}, "a shift-left immediate operand"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SHRIMM_PRED", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_tszh,FLD_SVE_imm5}, "a shift-right immediate operand"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SHRIMM_UNPRED", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_tszh,FLD_imm5}, "a shift-right immediate operand"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SIMM5", OPD_F_SEXT | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm5}, "a 5-bit signed immediate"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SIMM5B", OPD_F_SEXT | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm5b}, "a 5-bit signed immediate"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SIMM6", OPD_F_SEXT | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imms}, "a 6-bit signed immediate"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SIMM8", OPD_F_SEXT | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm8}, "an 8-bit signed immediate"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_UIMM3", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm3}, "a 3-bit unsigned immediate"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_UIMM7", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm7}, "a 7-bit unsigned immediate"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_UIMM8", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm8}, "an 8-bit unsigned immediate"},
|
||||
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_UIMM8_53", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm5,FLD_imm3}, "an 8-bit unsigned immediate"},
|
||||
{AARCH64_OPND_CLASS_SVE_REG, "SVE_Za_5", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Za_5}, "an SVE vector register"},
|
||||
{AARCH64_OPND_CLASS_SVE_REG, "SVE_Za_16", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Za_16}, "an SVE vector register"},
|
||||
{AARCH64_OPND_CLASS_SVE_REG, "SVE_Zd", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zd}, "an SVE vector register"},
|
||||
|
@ -264,6 +264,7 @@ const aarch64_field fields[] =
|
||||
{ 31, 1 }, /* b5: in the test bit and branch instructions. */
|
||||
{ 19, 5 }, /* b40: in the test bit and branch instructions. */
|
||||
{ 10, 6 }, /* scale: in the fixed-point scalar to fp converting inst. */
|
||||
{ 17, 1 }, /* SVE_N: SVE equivalent of N. */
|
||||
{ 0, 4 }, /* SVE_Pd: p0-p15, bits [3,0]. */
|
||||
{ 10, 3 }, /* SVE_Pg3: p0-p7, bits [12,10]. */
|
||||
{ 5, 4 }, /* SVE_Pg4_5: p0-p15, bits [8,5]. */
|
||||
@ -279,8 +280,16 @@ const aarch64_field fields[] =
|
||||
{ 16, 5 }, /* SVE_Zm_16: SVE vector register, bits [20,16]. */
|
||||
{ 5, 5 }, /* SVE_Zn: SVE vector register, bits [9,5]. */
|
||||
{ 0, 5 }, /* SVE_Zt: SVE vector register, bits [4,0]. */
|
||||
{ 16, 3 }, /* SVE_imm3: 3-bit immediate field. */
|
||||
{ 16, 4 }, /* SVE_imm4: 4-bit immediate field. */
|
||||
{ 5, 5 }, /* SVE_imm5: 5-bit immediate field. */
|
||||
{ 16, 5 }, /* SVE_imm5b: secondary 5-bit immediate field. */
|
||||
{ 16, 6 }, /* SVE_imm6: 6-bit immediate field. */
|
||||
{ 14, 7 }, /* SVE_imm7: 7-bit immediate field. */
|
||||
{ 5, 8 }, /* SVE_imm8: 8-bit immediate field. */
|
||||
{ 5, 9 }, /* SVE_imm9: 9-bit immediate field. */
|
||||
{ 11, 6 }, /* SVE_immr: SVE equivalent of immr. */
|
||||
{ 5, 6 }, /* SVE_imms: SVE equivalent of imms. */
|
||||
{ 10, 2 }, /* SVE_msz: 2-bit shift amount for ADR. */
|
||||
{ 5, 5 }, /* SVE_pattern: vector pattern enumeration. */
|
||||
{ 0, 4 }, /* SVE_prfop: prefetch operation for SVE PRF[BHWD]. */
|
||||
@ -1374,9 +1383,10 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
|
||||
const aarch64_opcode *opcode,
|
||||
aarch64_operand_error *mismatch_detail)
|
||||
{
|
||||
unsigned num, modifiers;
|
||||
unsigned num, modifiers, shift;
|
||||
unsigned char size;
|
||||
int64_t imm, min_value, max_value;
|
||||
uint64_t uvalue, mask;
|
||||
const aarch64_opnd_info *opnd = opnds + idx;
|
||||
aarch64_opnd_qualifier_t qualifier = opnd->qualifier;
|
||||
|
||||
@ -1977,6 +1987,10 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
|
||||
case AARCH64_OPND_UIMM7:
|
||||
case AARCH64_OPND_UIMM3_OP1:
|
||||
case AARCH64_OPND_UIMM3_OP2:
|
||||
case AARCH64_OPND_SVE_UIMM3:
|
||||
case AARCH64_OPND_SVE_UIMM7:
|
||||
case AARCH64_OPND_SVE_UIMM8:
|
||||
case AARCH64_OPND_SVE_UIMM8_53:
|
||||
size = get_operand_fields_width (get_operand_from_code (type));
|
||||
assert (size < 32);
|
||||
if (!value_fit_unsigned_field_p (opnd->imm.value, size))
|
||||
@ -1987,6 +2001,22 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
|
||||
}
|
||||
break;
|
||||
|
||||
case AARCH64_OPND_SIMM5:
|
||||
case AARCH64_OPND_SVE_SIMM5:
|
||||
case AARCH64_OPND_SVE_SIMM5B:
|
||||
case AARCH64_OPND_SVE_SIMM6:
|
||||
case AARCH64_OPND_SVE_SIMM8:
|
||||
size = get_operand_fields_width (get_operand_from_code (type));
|
||||
assert (size < 32);
|
||||
if (!value_fit_signed_field_p (opnd->imm.value, size))
|
||||
{
|
||||
set_imm_out_of_range_error (mismatch_detail, idx,
|
||||
-(1 << (size - 1)),
|
||||
(1 << (size - 1)) - 1);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case AARCH64_OPND_WIDTH:
|
||||
assert (idx > 1 && opnds[idx-1].type == AARCH64_OPND_IMM
|
||||
&& opnds[0].type == AARCH64_OPND_Rd);
|
||||
@ -2001,6 +2031,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
|
||||
break;
|
||||
|
||||
case AARCH64_OPND_LIMM:
|
||||
case AARCH64_OPND_SVE_LIMM:
|
||||
{
|
||||
int esize = aarch64_get_qualifier_esize (opnds[0].qualifier);
|
||||
uint64_t uimm = opnd->imm.value;
|
||||
@ -2171,6 +2202,90 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
|
||||
}
|
||||
break;
|
||||
|
||||
case AARCH64_OPND_SVE_AIMM:
|
||||
min_value = 0;
|
||||
sve_aimm:
|
||||
assert (opnd->shifter.kind == AARCH64_MOD_LSL);
|
||||
size = aarch64_get_qualifier_esize (opnds[0].qualifier);
|
||||
mask = ~((uint64_t) -1 << (size * 4) << (size * 4));
|
||||
uvalue = opnd->imm.value;
|
||||
shift = opnd->shifter.amount;
|
||||
if (size == 1)
|
||||
{
|
||||
if (shift != 0)
|
||||
{
|
||||
set_other_error (mismatch_detail, idx,
|
||||
_("no shift amount allowed for"
|
||||
" 8-bit constants"));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (shift != 0 && shift != 8)
|
||||
{
|
||||
set_other_error (mismatch_detail, idx,
|
||||
_("shift amount must be 0 or 8"));
|
||||
return 0;
|
||||
}
|
||||
if (shift == 0 && (uvalue & 0xff) == 0)
|
||||
{
|
||||
shift = 8;
|
||||
uvalue = (int64_t) uvalue / 256;
|
||||
}
|
||||
}
|
||||
mask >>= shift;
|
||||
if ((uvalue & mask) != uvalue && (uvalue | ~mask) != uvalue)
|
||||
{
|
||||
set_other_error (mismatch_detail, idx,
|
||||
_("immediate too big for element size"));
|
||||
return 0;
|
||||
}
|
||||
uvalue = (uvalue - min_value) & mask;
|
||||
if (uvalue > 0xff)
|
||||
{
|
||||
set_other_error (mismatch_detail, idx,
|
||||
_("invalid arithmetic immediate"));
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case AARCH64_OPND_SVE_ASIMM:
|
||||
min_value = -128;
|
||||
goto sve_aimm;
|
||||
|
||||
case AARCH64_OPND_SVE_INV_LIMM:
|
||||
{
|
||||
int esize = aarch64_get_qualifier_esize (opnds[0].qualifier);
|
||||
uint64_t uimm = ~opnd->imm.value;
|
||||
if (!aarch64_logical_immediate_p (uimm, esize, NULL))
|
||||
{
|
||||
set_other_error (mismatch_detail, idx,
|
||||
_("immediate out of range"));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AARCH64_OPND_SVE_LIMM_MOV:
|
||||
{
|
||||
int esize = aarch64_get_qualifier_esize (opnds[0].qualifier);
|
||||
uint64_t uimm = opnd->imm.value;
|
||||
if (!aarch64_logical_immediate_p (uimm, esize, NULL))
|
||||
{
|
||||
set_other_error (mismatch_detail, idx,
|
||||
_("immediate out of range"));
|
||||
return 0;
|
||||
}
|
||||
if (!aarch64_sve_dupm_mov_immediate_p (uimm, esize))
|
||||
{
|
||||
set_other_error (mismatch_detail, idx,
|
||||
_("invalid replicated MOV immediate"));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AARCH64_OPND_SVE_PATTERN_SCALED:
|
||||
assert (opnd->shifter.kind == AARCH64_MOD_MUL);
|
||||
if (!value_in_range_p (opnd->shifter.amount, 1, 16))
|
||||
@ -2180,6 +2295,27 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
|
||||
}
|
||||
break;
|
||||
|
||||
case AARCH64_OPND_SVE_SHLIMM_PRED:
|
||||
case AARCH64_OPND_SVE_SHLIMM_UNPRED:
|
||||
size = aarch64_get_qualifier_esize (opnds[idx - 1].qualifier);
|
||||
if (!value_in_range_p (opnd->imm.value, 0, 8 * size - 1))
|
||||
{
|
||||
set_imm_out_of_range_error (mismatch_detail, idx,
|
||||
0, 8 * size - 1);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case AARCH64_OPND_SVE_SHRIMM_PRED:
|
||||
case AARCH64_OPND_SVE_SHRIMM_UNPRED:
|
||||
size = aarch64_get_qualifier_esize (opnds[idx - 1].qualifier);
|
||||
if (!value_in_range_p (opnd->imm.value, 1, 8 * size))
|
||||
{
|
||||
set_imm_out_of_range_error (mismatch_detail, idx, 1, 8 * size);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2953,6 +3089,19 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
|
||||
case AARCH64_OPND_IMMR:
|
||||
case AARCH64_OPND_IMMS:
|
||||
case AARCH64_OPND_FBITS:
|
||||
case AARCH64_OPND_SIMM5:
|
||||
case AARCH64_OPND_SVE_SHLIMM_PRED:
|
||||
case AARCH64_OPND_SVE_SHLIMM_UNPRED:
|
||||
case AARCH64_OPND_SVE_SHRIMM_PRED:
|
||||
case AARCH64_OPND_SVE_SHRIMM_UNPRED:
|
||||
case AARCH64_OPND_SVE_SIMM5:
|
||||
case AARCH64_OPND_SVE_SIMM5B:
|
||||
case AARCH64_OPND_SVE_SIMM6:
|
||||
case AARCH64_OPND_SVE_SIMM8:
|
||||
case AARCH64_OPND_SVE_UIMM3:
|
||||
case AARCH64_OPND_SVE_UIMM7:
|
||||
case AARCH64_OPND_SVE_UIMM8:
|
||||
case AARCH64_OPND_SVE_UIMM8_53:
|
||||
snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
|
||||
break;
|
||||
|
||||
@ -3021,6 +3170,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
|
||||
case AARCH64_OPND_LIMM:
|
||||
case AARCH64_OPND_AIMM:
|
||||
case AARCH64_OPND_HALF:
|
||||
case AARCH64_OPND_SVE_INV_LIMM:
|
||||
case AARCH64_OPND_SVE_LIMM:
|
||||
case AARCH64_OPND_SVE_LIMM_MOV:
|
||||
if (opnd->shifter.amount)
|
||||
snprintf (buf, size, "#0x%" PRIx64 ", lsl #%" PRIi64, opnd->imm.value,
|
||||
opnd->shifter.amount);
|
||||
@ -3039,6 +3191,15 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
|
||||
opnd->shifter.amount);
|
||||
break;
|
||||
|
||||
case AARCH64_OPND_SVE_AIMM:
|
||||
case AARCH64_OPND_SVE_ASIMM:
|
||||
if (opnd->shifter.amount)
|
||||
snprintf (buf, size, "#%" PRIi64 ", lsl #%" PRIi64, opnd->imm.value,
|
||||
opnd->shifter.amount);
|
||||
else
|
||||
snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
|
||||
break;
|
||||
|
||||
case AARCH64_OPND_FPIMM:
|
||||
case AARCH64_OPND_SIMD_FPIMM:
|
||||
switch (aarch64_get_qualifier_esize (opnds[0].qualifier))
|
||||
@ -3967,6 +4128,33 @@ verify_ldpsw (const struct aarch64_opcode * opcode ATTRIBUTE_UNUSED,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Return true if VALUE cannot be moved into an SVE register using DUP
|
||||
(with any element size, not just ESIZE) and if using DUPM would
|
||||
therefore be OK. ESIZE is the number of bytes in the immediate. */
|
||||
|
||||
bfd_boolean
|
||||
aarch64_sve_dupm_mov_immediate_p (uint64_t uvalue, int esize)
|
||||
{
|
||||
int64_t svalue = uvalue;
|
||||
uint64_t upper = (uint64_t) -1 << (esize * 4) << (esize * 4);
|
||||
|
||||
if ((uvalue & ~upper) != uvalue && (uvalue | upper) != uvalue)
|
||||
return FALSE;
|
||||
if (esize <= 4 || (uint32_t) uvalue == (uint32_t) (uvalue >> 32))
|
||||
{
|
||||
svalue = (int32_t) uvalue;
|
||||
if (esize <= 2 || (uint16_t) uvalue == (uint16_t) (uvalue >> 16))
|
||||
{
|
||||
svalue = (int16_t) uvalue;
|
||||
if (esize == 1 || (uint8_t) uvalue == (uint8_t) (uvalue >> 8))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if ((svalue & 0xff) == 0)
|
||||
svalue /= 256;
|
||||
return svalue < -128 || svalue >= 128;
|
||||
}
|
||||
|
||||
/* Include the opcode description table as well as the operand description
|
||||
table. */
|
||||
#define VERIFIER(x) verify_##x
|
||||
|
@ -91,6 +91,7 @@ enum aarch64_field_kind
|
||||
FLD_b5,
|
||||
FLD_b40,
|
||||
FLD_scale,
|
||||
FLD_SVE_N,
|
||||
FLD_SVE_Pd,
|
||||
FLD_SVE_Pg3,
|
||||
FLD_SVE_Pg4_5,
|
||||
@ -106,8 +107,16 @@ enum aarch64_field_kind
|
||||
FLD_SVE_Zm_16,
|
||||
FLD_SVE_Zn,
|
||||
FLD_SVE_Zt,
|
||||
FLD_SVE_imm3,
|
||||
FLD_SVE_imm4,
|
||||
FLD_SVE_imm5,
|
||||
FLD_SVE_imm5b,
|
||||
FLD_SVE_imm6,
|
||||
FLD_SVE_imm7,
|
||||
FLD_SVE_imm8,
|
||||
FLD_SVE_imm9,
|
||||
FLD_SVE_immr,
|
||||
FLD_SVE_imms,
|
||||
FLD_SVE_msz,
|
||||
FLD_SVE_pattern,
|
||||
FLD_SVE_prfop,
|
||||
|
@ -2761,6 +2761,8 @@ struct aarch64_opcode aarch64_opcode_table[] =
|
||||
"a 16-bit unsigned immediate") \
|
||||
Y(IMMEDIATE, imm, "CCMP_IMM", 0, F(FLD_imm5), \
|
||||
"a 5-bit unsigned immediate") \
|
||||
Y(IMMEDIATE, imm, "SIMM5", OPD_F_SEXT, F(FLD_imm5), \
|
||||
"a 5-bit signed immediate") \
|
||||
Y(IMMEDIATE, imm, "NZCV", 0, F(FLD_nzcv), \
|
||||
"a flag bit specifier giving an alternative value for each flag") \
|
||||
Y(IMMEDIATE, limm, "LIMM", 0, F(FLD_N,FLD_immr,FLD_imms), \
|
||||
@ -2925,6 +2927,19 @@ struct aarch64_opcode aarch64_opcode_table[] =
|
||||
Y(ADDRESS, sve_addr_zz_uxtw, "SVE_ADDR_ZZ_UXTW", 0, \
|
||||
F(FLD_SVE_Zn,FLD_SVE_Zm_16), \
|
||||
"an address with a vector register offset") \
|
||||
Y(IMMEDIATE, sve_aimm, "SVE_AIMM", 0, F(FLD_SVE_imm9), \
|
||||
"a 9-bit unsigned arithmetic operand") \
|
||||
Y(IMMEDIATE, sve_asimm, "SVE_ASIMM", 0, F(FLD_SVE_imm9), \
|
||||
"a 9-bit signed arithmetic operand") \
|
||||
Y(IMMEDIATE, inv_limm, "SVE_INV_LIMM", 0, \
|
||||
F(FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms), \
|
||||
"an inverted 13-bit logical immediate") \
|
||||
Y(IMMEDIATE, limm, "SVE_LIMM", 0, \
|
||||
F(FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms), \
|
||||
"a 13-bit logical immediate") \
|
||||
Y(IMMEDIATE, sve_limm_mov, "SVE_LIMM_MOV", 0, \
|
||||
F(FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms), \
|
||||
"a 13-bit logical move immediate") \
|
||||
Y(IMMEDIATE, imm, "SVE_PATTERN", 0, F(FLD_SVE_pattern), \
|
||||
"an enumeration value such as POW2") \
|
||||
Y(IMMEDIATE, sve_scale, "SVE_PATTERN_SCALED", 0, \
|
||||
@ -2947,6 +2962,30 @@ struct aarch64_opcode aarch64_opcode_table[] =
|
||||
"an SVE predicate register") \
|
||||
Y(PRED_REG, regno, "SVE_Pt", 0, F(FLD_SVE_Pt), \
|
||||
"an SVE predicate register") \
|
||||
Y(IMMEDIATE, sve_shlimm, "SVE_SHLIMM_PRED", 0, \
|
||||
F(FLD_SVE_tszh,FLD_SVE_imm5), "a shift-left immediate operand") \
|
||||
Y(IMMEDIATE, sve_shlimm, "SVE_SHLIMM_UNPRED", 0, \
|
||||
F(FLD_SVE_tszh,FLD_imm5), "a shift-left immediate operand") \
|
||||
Y(IMMEDIATE, sve_shrimm, "SVE_SHRIMM_PRED", 0, \
|
||||
F(FLD_SVE_tszh,FLD_SVE_imm5), "a shift-right immediate operand") \
|
||||
Y(IMMEDIATE, sve_shrimm, "SVE_SHRIMM_UNPRED", 0, \
|
||||
F(FLD_SVE_tszh,FLD_imm5), "a shift-right immediate operand") \
|
||||
Y(IMMEDIATE, imm, "SVE_SIMM5", OPD_F_SEXT, F(FLD_SVE_imm5), \
|
||||
"a 5-bit signed immediate") \
|
||||
Y(IMMEDIATE, imm, "SVE_SIMM5B", OPD_F_SEXT, F(FLD_SVE_imm5b), \
|
||||
"a 5-bit signed immediate") \
|
||||
Y(IMMEDIATE, imm, "SVE_SIMM6", OPD_F_SEXT, F(FLD_SVE_imms), \
|
||||
"a 6-bit signed immediate") \
|
||||
Y(IMMEDIATE, imm, "SVE_SIMM8", OPD_F_SEXT, F(FLD_SVE_imm8), \
|
||||
"an 8-bit signed immediate") \
|
||||
Y(IMMEDIATE, imm, "SVE_UIMM3", 0, F(FLD_SVE_imm3), \
|
||||
"a 3-bit unsigned immediate") \
|
||||
Y(IMMEDIATE, imm, "SVE_UIMM7", 0, F(FLD_SVE_imm7), \
|
||||
"a 7-bit unsigned immediate") \
|
||||
Y(IMMEDIATE, imm, "SVE_UIMM8", 0, F(FLD_SVE_imm8), \
|
||||
"an 8-bit unsigned immediate") \
|
||||
Y(IMMEDIATE, imm, "SVE_UIMM8_53", 0, F(FLD_imm5,FLD_imm3), \
|
||||
"an 8-bit unsigned immediate") \
|
||||
Y(SVE_REG, regno, "SVE_Za_5", 0, F(FLD_SVE_Za_5), \
|
||||
"an SVE vector register") \
|
||||
Y(SVE_REG, regno, "SVE_Za_16", 0, F(FLD_SVE_Za_16), \
|
||||
|
Loading…
Reference in New Issue
Block a user