[AArch64][SVE 24/32] Add AARCH64_OPND_SVE_PATTERN_SCALED

Some SVE instructions count the number of elements in a given vector
pattern and allow a scale factor of [1, 16] to be applied to the result.
This scale factor is written ", MUL #n", where "MUL" is a new operator.
E.g.:

	UQINCD	X0, POW2, MUL #2

This patch adds support for this kind of operand.

All existing operators were shifts of some kind, so there was a natural
range of [0, 63] regardless of context.  This was then narrowered further
by later checks (e.g. to [0, 31] when used for 32-bit values).

In contrast, MUL doesn't really have a natural context-independent range.
Rather than pick one arbitrarily, it seemed better to make the "shift"
amount a full 64-bit value and leave the range test to the usual
operand-checking code.  I've rearranged the fields of aarch64_opnd_info
so that this doesn't increase the size of the structure (although I don't
think its size is critical anyway).

include/
	* opcode/aarch64.h (AARCH64_OPND_SVE_PATTERN_SCALED): New
	aarch64_opnd.
	(AARCH64_MOD_MUL): New aarch64_modifier_kind.
	(aarch64_opnd_info): Make shifter.amount an int64_t and
	rearrange the fields.

opcodes/
	* aarch64-tbl.h (AARCH64_OPERANDS): Add an entry for
	AARCH64_OPND_SVE_PATTERN_SCALED.
	* aarch64-opc.h (FLD_SVE_imm4): New aarch64_field_kind.
	* aarch64-opc.c (fields): Add a corresponding entry.
	(set_multiplier_out_of_range_error): New function.
	(aarch64_operand_modifiers): Add entry for AARCH64_MOD_MUL.
	(operand_general_constraint_met_p): Handle
	AARCH64_OPND_SVE_PATTERN_SCALED.
	(print_register_offset_address): Use PRIi64 to print the
	shift amount.
	(aarch64_print_operand): Likewise.  Handle
	AARCH64_OPND_SVE_PATTERN_SCALED.
	* aarch64-opc-2.c: Regenerate.
	* aarch64-asm.h (ins_sve_scale): New inserter.
	* aarch64-asm.c (aarch64_ins_sve_scale): New function.
	* aarch64-asm-2.c: Regenerate.
	* aarch64-dis.h (ext_sve_scale): New inserter.
	* aarch64-dis.c (aarch64_ext_sve_scale): New function.
	* aarch64-dis-2.c: Regenerate.

gas/
	* config/tc-aarch64.c (SHIFTED_MUL): New parse_shift_mode.
	(parse_shift): Handle it.  Reject AARCH64_MOD_MUL for all other
	shift modes.  Skip range tests for AARCH64_MOD_MUL.
	(process_omitted_operand): Handle AARCH64_OPND_SVE_PATTERN_SCALED.
	(parse_operands): Likewise.
This commit is contained in:
Richard Sandiford 2016-09-21 16:55:22 +01:00
parent 245d2e3fe8
commit 2442d8466e
15 changed files with 186 additions and 19 deletions

View file

@ -1,3 +1,11 @@
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
* config/tc-aarch64.c (SHIFTED_MUL): New parse_shift_mode.
(parse_shift): Handle it. Reject AARCH64_MOD_MUL for all other
shift modes. Skip range tests for AARCH64_MOD_MUL.
(process_omitted_operand): Handle AARCH64_OPND_SVE_PATTERN_SCALED.
(parse_operands): Likewise.
2016-09-21 Richard Sandiford <richard.sandiford@arm.com> 2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
* config/tc-aarch64.c (parse_enum_string): New function. * config/tc-aarch64.c (parse_enum_string): New function.

View file

@ -2882,6 +2882,7 @@ enum parse_shift_mode
SHIFTED_LOGIC_IMM, /* "rn{,lsl|lsr|asl|asr|ror #n}" or SHIFTED_LOGIC_IMM, /* "rn{,lsl|lsr|asl|asr|ror #n}" or
"#imm" */ "#imm" */
SHIFTED_LSL, /* bare "lsl #n" */ SHIFTED_LSL, /* bare "lsl #n" */
SHIFTED_MUL, /* bare "mul #n" */
SHIFTED_LSL_MSL, /* "lsl|msl #n" */ SHIFTED_LSL_MSL, /* "lsl|msl #n" */
SHIFTED_REG_OFFSET /* [su]xtw|sxtx {#n} or lsl #n */ SHIFTED_REG_OFFSET /* [su]xtw|sxtx {#n} or lsl #n */
}; };
@ -2923,6 +2924,13 @@ parse_shift (char **str, aarch64_opnd_info *operand, enum parse_shift_mode mode)
return FALSE; return FALSE;
} }
if (kind == AARCH64_MOD_MUL
&& mode != SHIFTED_MUL)
{
set_syntax_error (_("invalid use of 'MUL'"));
return FALSE;
}
switch (mode) switch (mode)
{ {
case SHIFTED_LOGIC_IMM: case SHIFTED_LOGIC_IMM:
@ -2949,6 +2957,14 @@ parse_shift (char **str, aarch64_opnd_info *operand, enum parse_shift_mode mode)
} }
break; break;
case SHIFTED_MUL:
if (kind != AARCH64_MOD_MUL)
{
set_syntax_error (_("only 'MUL' is permitted"));
return FALSE;
}
break;
case SHIFTED_REG_OFFSET: case SHIFTED_REG_OFFSET:
if (kind != AARCH64_MOD_UXTW && kind != AARCH64_MOD_LSL if (kind != AARCH64_MOD_UXTW && kind != AARCH64_MOD_LSL
&& kind != AARCH64_MOD_SXTW && kind != AARCH64_MOD_SXTX) && kind != AARCH64_MOD_SXTW && kind != AARCH64_MOD_SXTX)
@ -3001,7 +3017,11 @@ parse_shift (char **str, aarch64_opnd_info *operand, enum parse_shift_mode mode)
set_syntax_error (_("constant shift amount required")); set_syntax_error (_("constant shift amount required"));
return FALSE; return FALSE;
} }
else if (exp.X_add_number < 0 || exp.X_add_number > 63) /* For parsing purposes, MUL #n has no inherent range. The range
depends on the operand and will be checked by operand-specific
routines. */
else if (kind != AARCH64_MOD_MUL
&& (exp.X_add_number < 0 || exp.X_add_number > 63))
{ {
set_fatal_syntax_error (_("shift amount out of range 0 to 63")); set_fatal_syntax_error (_("shift amount out of range 0 to 63"));
return FALSE; return FALSE;
@ -4863,6 +4883,12 @@ process_omitted_operand (enum aarch64_opnd type, const aarch64_opcode *opcode,
operand->imm.value = default_value; operand->imm.value = default_value;
break; break;
case AARCH64_OPND_SVE_PATTERN_SCALED:
operand->imm.value = default_value;
operand->shifter.kind = AARCH64_MOD_MUL;
operand->shifter.amount = 1;
break;
case AARCH64_OPND_EXCEPTION: case AARCH64_OPND_EXCEPTION:
inst.reloc.type = BFD_RELOC_UNUSED; inst.reloc.type = BFD_RELOC_UNUSED;
break; break;
@ -5373,6 +5399,20 @@ parse_operands (char *str, const aarch64_opcode *opcode)
info->imm.value = val; info->imm.value = val;
break; break;
case AARCH64_OPND_SVE_PATTERN_SCALED:
po_enum_or_fail (aarch64_sve_pattern_array);
info->imm.value = val;
if (skip_past_comma (&str)
&& !parse_shift (&str, info, SHIFTED_MUL))
goto failure;
if (!info->shifter.operator_present)
{
gas_assert (info->shifter.kind == AARCH64_MOD_NONE);
info->shifter.kind = AARCH64_MOD_MUL;
info->shifter.amount = 1;
}
break;
case AARCH64_OPND_SVE_PRFOP: case AARCH64_OPND_SVE_PRFOP:
po_enum_or_fail (aarch64_sve_prfop_array); po_enum_or_fail (aarch64_sve_prfop_array);
info->imm.value = val; info->imm.value = val;

View file

@ -1,3 +1,11 @@
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
* opcode/aarch64.h (AARCH64_OPND_SVE_PATTERN_SCALED): New
aarch64_opnd.
(AARCH64_MOD_MUL): New aarch64_modifier_kind.
(aarch64_opnd_info): Make shifter.amount an int64_t and
rearrange the fields.
2016-09-21 Richard Sandiford <richard.sandiford@arm.com> 2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
* opcode/aarch64.h (AARCH64_OPND_SVE_PATTERN): New aarch64_opnd. * opcode/aarch64.h (AARCH64_OPND_SVE_PATTERN): New aarch64_opnd.

View file

@ -245,6 +245,7 @@ enum aarch64_opnd
AARCH64_OPND_BARRIER_PSB, /* Barrier operand for PSB. */ AARCH64_OPND_BARRIER_PSB, /* Barrier operand for PSB. */
AARCH64_OPND_SVE_PATTERN, /* SVE vector pattern enumeration. */ 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. */ AARCH64_OPND_SVE_PRFOP, /* SVE prefetch operation. */
AARCH64_OPND_SVE_Pd, /* SVE p0-p15 in Pd. */ AARCH64_OPND_SVE_Pd, /* SVE p0-p15 in Pd. */
AARCH64_OPND_SVE_Pg3, /* SVE p0-p7 in Pg. */ AARCH64_OPND_SVE_Pg3, /* SVE p0-p7 in Pg. */
@ -745,6 +746,7 @@ enum aarch64_modifier_kind
AARCH64_MOD_SXTH, AARCH64_MOD_SXTH,
AARCH64_MOD_SXTW, AARCH64_MOD_SXTW,
AARCH64_MOD_SXTX, AARCH64_MOD_SXTX,
AARCH64_MOD_MUL,
}; };
bfd_boolean bfd_boolean
@ -836,10 +838,10 @@ struct aarch64_opnd_info
struct struct
{ {
enum aarch64_modifier_kind kind; enum aarch64_modifier_kind kind;
int amount;
unsigned operator_present: 1; /* Only valid during encoding. */ unsigned operator_present: 1; /* Only valid during encoding. */
/* Value of the 'S' field in ld/st reg offset; used only in decoding. */ /* Value of the 'S' field in ld/st reg offset; used only in decoding. */
unsigned amount_present: 1; unsigned amount_present: 1;
int64_t amount;
} shifter; } shifter;
unsigned skip:1; /* Operand is not completed if there is a fixup needed unsigned skip:1; /* Operand is not completed if there is a fixup needed

View file

@ -1,3 +1,25 @@
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
* aarch64-tbl.h (AARCH64_OPERANDS): Add an entry for
AARCH64_OPND_SVE_PATTERN_SCALED.
* aarch64-opc.h (FLD_SVE_imm4): New aarch64_field_kind.
* aarch64-opc.c (fields): Add a corresponding entry.
(set_multiplier_out_of_range_error): New function.
(aarch64_operand_modifiers): Add entry for AARCH64_MOD_MUL.
(operand_general_constraint_met_p): Handle
AARCH64_OPND_SVE_PATTERN_SCALED.
(print_register_offset_address): Use PRIi64 to print the
shift amount.
(aarch64_print_operand): Likewise. Handle
AARCH64_OPND_SVE_PATTERN_SCALED.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_scale): New inserter.
* aarch64-asm.c (aarch64_ins_sve_scale): New function.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_scale): New inserter.
* aarch64-dis.c (aarch64_ext_sve_scale): New function.
* aarch64-dis-2.c: Regenerate.
2016-09-21 Richard Sandiford <richard.sandiford@arm.com> 2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for * aarch64-tbl.h (AARCH64_OPERANDS): Add entries for

View file

@ -480,7 +480,6 @@ aarch64_insert_operand (const aarch64_operand *self,
case 27: case 27:
case 35: case 35:
case 36: case 36:
case 91:
case 92: case 92:
case 93: case 93:
case 94: case 94:
@ -494,7 +493,8 @@ aarch64_insert_operand (const aarch64_operand *self,
case 102: case 102:
case 103: case 103:
case 104: case 104:
case 107: case 105:
case 108:
return aarch64_ins_regno (self, info, code, inst); return aarch64_ins_regno (self, info, code, inst);
case 12: case 12:
return aarch64_ins_reg_extended (self, info, code, inst); return aarch64_ins_reg_extended (self, info, code, inst);
@ -532,7 +532,7 @@ aarch64_insert_operand (const aarch64_operand *self,
case 69: case 69:
case 70: case 70:
case 89: case 89:
case 90: case 91:
return aarch64_ins_imm (self, info, code, inst); return aarch64_ins_imm (self, info, code, inst);
case 38: case 38:
case 39: case 39:
@ -583,10 +583,12 @@ aarch64_insert_operand (const aarch64_operand *self,
return aarch64_ins_prfop (self, info, code, inst); return aarch64_ins_prfop (self, info, code, inst);
case 88: case 88:
return aarch64_ins_hint (self, info, code, inst); return aarch64_ins_hint (self, info, code, inst);
case 105: case 90:
return aarch64_ins_sve_index (self, info, code, inst); return aarch64_ins_sve_scale (self, info, code, inst);
case 106: case 106:
case 108: return aarch64_ins_sve_index (self, info, code, inst);
case 107:
case 109:
return aarch64_ins_sve_reglist (self, info, code, inst); return aarch64_ins_sve_reglist (self, info, code, inst);
default: assert (0); abort (); default: assert (0); abort ();
} }

View file

@ -772,6 +772,19 @@ aarch64_ins_sve_reglist (const aarch64_operand *self,
return NULL; return NULL;
} }
/* Encode <pattern>{, MUL #<amount>}. The fields array specifies which
fields to use for <pattern>. <amount> - 1 is encoded in the SVE_imm4
field. */
const char *
aarch64_ins_sve_scale (const aarch64_operand *self,
const aarch64_opnd_info *info, aarch64_insn *code,
const aarch64_inst *inst ATTRIBUTE_UNUSED)
{
insert_all_fields (self, code, info->imm.value);
insert_field (FLD_SVE_imm4, code, info->shifter.amount - 1, 0);
return NULL;
}
/* Miscellaneous encoding functions. */ /* Miscellaneous encoding functions. */
/* Encode size[0], i.e. bit 22, for /* Encode size[0], i.e. bit 22, for

View file

@ -71,6 +71,7 @@ AARCH64_DECL_OPD_INSERTER (ins_reg_extended);
AARCH64_DECL_OPD_INSERTER (ins_reg_shifted); AARCH64_DECL_OPD_INSERTER (ins_reg_shifted);
AARCH64_DECL_OPD_INSERTER (ins_sve_index); AARCH64_DECL_OPD_INSERTER (ins_sve_index);
AARCH64_DECL_OPD_INSERTER (ins_sve_reglist); AARCH64_DECL_OPD_INSERTER (ins_sve_reglist);
AARCH64_DECL_OPD_INSERTER (ins_sve_scale);
#undef AARCH64_DECL_OPD_INSERTER #undef AARCH64_DECL_OPD_INSERTER

View file

@ -10426,7 +10426,6 @@ aarch64_extract_operand (const aarch64_operand *self,
case 27: case 27:
case 35: case 35:
case 36: case 36:
case 91:
case 92: case 92:
case 93: case 93:
case 94: case 94:
@ -10440,7 +10439,8 @@ aarch64_extract_operand (const aarch64_operand *self,
case 102: case 102:
case 103: case 103:
case 104: case 104:
case 107: case 105:
case 108:
return aarch64_ext_regno (self, info, code, inst); return aarch64_ext_regno (self, info, code, inst);
case 8: case 8:
return aarch64_ext_regrt_sysins (self, info, code, inst); return aarch64_ext_regrt_sysins (self, info, code, inst);
@ -10483,7 +10483,7 @@ aarch64_extract_operand (const aarch64_operand *self,
case 69: case 69:
case 70: case 70:
case 89: case 89:
case 90: case 91:
return aarch64_ext_imm (self, info, code, inst); return aarch64_ext_imm (self, info, code, inst);
case 38: case 38:
case 39: case 39:
@ -10536,10 +10536,12 @@ aarch64_extract_operand (const aarch64_operand *self,
return aarch64_ext_prfop (self, info, code, inst); return aarch64_ext_prfop (self, info, code, inst);
case 88: case 88:
return aarch64_ext_hint (self, info, code, inst); return aarch64_ext_hint (self, info, code, inst);
case 105: case 90:
return aarch64_ext_sve_index (self, info, code, inst); return aarch64_ext_sve_scale (self, info, code, inst);
case 106: case 106:
case 108: return aarch64_ext_sve_index (self, info, code, inst);
case 107:
case 109:
return aarch64_ext_sve_reglist (self, info, code, inst); return aarch64_ext_sve_reglist (self, info, code, inst);
default: assert (0); abort (); default: assert (0); abort ();
} }

View file

@ -1219,6 +1219,26 @@ aarch64_ext_sve_reglist (const aarch64_operand *self,
info->reglist.num_regs = get_opcode_dependent_value (inst->opcode); info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
return 1; return 1;
} }
/* Decode <pattern>{, MUL #<amount>}. The fields array specifies which
fields to use for <pattern>. <amount> - 1 is encoded in the SVE_imm4
field. */
int
aarch64_ext_sve_scale (const aarch64_operand *self,
aarch64_opnd_info *info, aarch64_insn code,
const aarch64_inst *inst)
{
int val;
if (!aarch64_ext_imm (self, info, code, inst))
return 0;
val = extract_field (FLD_SVE_imm4, code, 0);
info->shifter.kind = AARCH64_MOD_MUL;
info->shifter.amount = val + 1;
info->shifter.operator_present = (val != 0);
info->shifter.amount_present = (val != 0);
return 1;
}
/* Bitfields that are commonly used to encode certain operands' information /* Bitfields that are commonly used to encode certain operands' information
may be partially used as part of the base opcode in some instructions. may be partially used as part of the base opcode in some instructions.

View file

@ -93,6 +93,7 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_reg_extended);
AARCH64_DECL_OPD_EXTRACTOR (ext_reg_shifted); AARCH64_DECL_OPD_EXTRACTOR (ext_reg_shifted);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_index); AARCH64_DECL_OPD_EXTRACTOR (ext_sve_index);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_reglist); AARCH64_DECL_OPD_EXTRACTOR (ext_sve_reglist);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_scale);
#undef AARCH64_DECL_OPD_EXTRACTOR #undef AARCH64_DECL_OPD_EXTRACTOR

View file

@ -114,6 +114,7 @@ const struct aarch64_operand aarch64_operands[] =
{AARCH64_OPND_CLASS_SYSTEM, "PRFOP", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a prefetch operation specifier"}, {AARCH64_OPND_CLASS_SYSTEM, "PRFOP", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a prefetch operation specifier"},
{AARCH64_OPND_CLASS_SYSTEM, "BARRIER_PSB", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "the PSB option name CSYNC"}, {AARCH64_OPND_CLASS_SYSTEM, "BARRIER_PSB", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "the PSB option name CSYNC"},
{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", 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"}, {AARCH64_OPND_CLASS_IMMEDIATE, "SVE_PRFOP", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_prfop}, "an enumeration value such as PLDL1KEEP"},
{AARCH64_OPND_CLASS_PRED_REG, "SVE_Pd", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pd}, "an SVE predicate register"}, {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pd", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pd}, "an SVE predicate register"},
{AARCH64_OPND_CLASS_PRED_REG, "SVE_Pg3", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pg3}, "an SVE predicate register"}, {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pg3", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pg3}, "an SVE predicate register"},

View file

@ -279,6 +279,7 @@ const aarch64_field fields[] =
{ 16, 5 }, /* SVE_Zm_16: SVE vector register, bits [20,16]. */ { 16, 5 }, /* SVE_Zm_16: SVE vector register, bits [20,16]. */
{ 5, 5 }, /* SVE_Zn: SVE vector register, bits [9,5]. */ { 5, 5 }, /* SVE_Zn: SVE vector register, bits [9,5]. */
{ 0, 5 }, /* SVE_Zt: SVE vector register, bits [4,0]. */ { 0, 5 }, /* SVE_Zt: SVE vector register, bits [4,0]. */
{ 16, 4 }, /* SVE_imm4: 4-bit immediate field. */
{ 5, 5 }, /* SVE_pattern: vector pattern enumeration. */ { 5, 5 }, /* SVE_pattern: vector pattern enumeration. */
{ 0, 4 }, /* SVE_prfop: prefetch operation for SVE PRF[BHWD]. */ { 0, 4 }, /* SVE_prfop: prefetch operation for SVE PRF[BHWD]. */
{ 22, 2 }, /* SVE_tszh: triangular size select high, bits [23,22]. */ { 22, 2 }, /* SVE_tszh: triangular size select high, bits [23,22]. */
@ -359,6 +360,7 @@ const struct aarch64_name_value_pair aarch64_operand_modifiers [] =
{"sxth", 0x5}, {"sxth", 0x5},
{"sxtw", 0x6}, {"sxtw", 0x6},
{"sxtx", 0x7}, {"sxtx", 0x7},
{"mul", 0x0},
{NULL, 0}, {NULL, 0},
}; };
@ -1303,6 +1305,18 @@ set_sft_amount_out_of_range_error (aarch64_operand_error *mismatch_detail,
_("shift amount")); _("shift amount"));
} }
/* Report that the MUL modifier in operand IDX should be in the range
[LOWER_BOUND, UPPER_BOUND]. */
static inline void
set_multiplier_out_of_range_error (aarch64_operand_error *mismatch_detail,
int idx, int lower_bound, int upper_bound)
{
if (mismatch_detail == NULL)
return;
set_out_of_range_error (mismatch_detail, idx, lower_bound, upper_bound,
_("multiplier"));
}
static inline void static inline void
set_unaligned_error (aarch64_operand_error *mismatch_detail, int idx, set_unaligned_error (aarch64_operand_error *mismatch_detail, int idx,
int alignment) int alignment)
@ -2001,6 +2015,15 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
} }
break; break;
case AARCH64_OPND_SVE_PATTERN_SCALED:
assert (opnd->shifter.kind == AARCH64_MOD_MUL);
if (!value_in_range_p (opnd->shifter.amount, 1, 16))
{
set_multiplier_out_of_range_error (mismatch_detail, idx, 1, 16);
return 0;
}
break;
default: default:
break; break;
} }
@ -2525,7 +2548,8 @@ print_register_offset_address (char *buf, size_t size,
if (print_extend_p) if (print_extend_p)
{ {
if (print_amount_p) if (print_amount_p)
snprintf (tb, sizeof (tb), ",%s #%d", shift_name, opnd->shifter.amount); snprintf (tb, sizeof (tb), ",%s #%" PRIi64, shift_name,
opnd->shifter.amount);
else else
snprintf (tb, sizeof (tb), ",%s", shift_name); snprintf (tb, sizeof (tb), ",%s", shift_name);
} }
@ -2620,7 +2644,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
} }
} }
if (opnd->shifter.amount) if (opnd->shifter.amount)
snprintf (buf, size, "%s, %s #%d", snprintf (buf, size, "%s, %s #%" PRIi64,
get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0), get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
aarch64_operand_modifiers[kind].name, aarch64_operand_modifiers[kind].name,
opnd->shifter.amount); opnd->shifter.amount);
@ -2637,7 +2661,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
snprintf (buf, size, "%s", snprintf (buf, size, "%s",
get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0)); get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
else else
snprintf (buf, size, "%s, %s #%d", snprintf (buf, size, "%s, %s #%" PRIi64,
get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0), get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
aarch64_operand_modifiers[opnd->shifter.kind].name, aarch64_operand_modifiers[opnd->shifter.kind].name,
opnd->shifter.amount); opnd->shifter.amount);
@ -2760,6 +2784,26 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
snprintf (buf, size, "#%" PRIi64, opnd->imm.value); snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
break; break;
case AARCH64_OPND_SVE_PATTERN_SCALED:
if (optional_operand_p (opcode, idx)
&& !opnd->shifter.operator_present
&& opnd->imm.value == get_optional_operand_default_value (opcode))
break;
enum_value = opnd->imm.value;
assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
if (aarch64_sve_pattern_array[opnd->imm.value])
snprintf (buf, size, "%s", aarch64_sve_pattern_array[opnd->imm.value]);
else
snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
if (opnd->shifter.operator_present)
{
size_t len = strlen (buf);
snprintf (buf + len, size - len, ", %s #%" PRIi64,
aarch64_operand_modifiers[opnd->shifter.kind].name,
opnd->shifter.amount);
}
break;
case AARCH64_OPND_SVE_PRFOP: case AARCH64_OPND_SVE_PRFOP:
enum_value = opnd->imm.value; enum_value = opnd->imm.value;
assert (enum_value < ARRAY_SIZE (aarch64_sve_prfop_array)); assert (enum_value < ARRAY_SIZE (aarch64_sve_prfop_array));
@ -2794,7 +2838,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
case AARCH64_OPND_AIMM: case AARCH64_OPND_AIMM:
case AARCH64_OPND_HALF: case AARCH64_OPND_HALF:
if (opnd->shifter.amount) if (opnd->shifter.amount)
snprintf (buf, size, "#0x%" PRIx64 ", lsl #%d", opnd->imm.value, snprintf (buf, size, "#0x%" PRIx64 ", lsl #%" PRIi64, opnd->imm.value,
opnd->shifter.amount); opnd->shifter.amount);
else else
snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value); snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
@ -2806,7 +2850,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
|| opnd->shifter.kind == AARCH64_MOD_NONE) || opnd->shifter.kind == AARCH64_MOD_NONE)
snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value); snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
else else
snprintf (buf, size, "#0x%" PRIx64 ", %s #%d", opnd->imm.value, snprintf (buf, size, "#0x%" PRIx64 ", %s #%" PRIi64, opnd->imm.value,
aarch64_operand_modifiers[opnd->shifter.kind].name, aarch64_operand_modifiers[opnd->shifter.kind].name,
opnd->shifter.amount); opnd->shifter.amount);
break; break;

View file

@ -106,6 +106,7 @@ enum aarch64_field_kind
FLD_SVE_Zm_16, FLD_SVE_Zm_16,
FLD_SVE_Zn, FLD_SVE_Zn,
FLD_SVE_Zt, FLD_SVE_Zt,
FLD_SVE_imm4,
FLD_SVE_pattern, FLD_SVE_pattern,
FLD_SVE_prfop, FLD_SVE_prfop,
FLD_SVE_tszh, FLD_SVE_tszh,

View file

@ -2822,6 +2822,8 @@ struct aarch64_opcode aarch64_opcode_table[] =
"the PSB option name CSYNC") \ "the PSB option name CSYNC") \
Y(IMMEDIATE, imm, "SVE_PATTERN", 0, F(FLD_SVE_pattern), \ Y(IMMEDIATE, imm, "SVE_PATTERN", 0, F(FLD_SVE_pattern), \
"an enumeration value such as POW2") \ "an enumeration value such as POW2") \
Y(IMMEDIATE, sve_scale, "SVE_PATTERN_SCALED", 0, \
F(FLD_SVE_pattern), "an enumeration value such as POW2") \
Y(IMMEDIATE, imm, "SVE_PRFOP", 0, F(FLD_SVE_prfop), \ Y(IMMEDIATE, imm, "SVE_PRFOP", 0, F(FLD_SVE_prfop), \
"an enumeration value such as PLDL1KEEP") \ "an enumeration value such as PLDL1KEEP") \
Y(PRED_REG, regno, "SVE_Pd", 0, F(FLD_SVE_Pd), \ Y(PRED_REG, regno, "SVE_Pd", 0, F(FLD_SVE_Pd), \