Skip to content

Commit

Permalink
[AArch64][SVE 24/32] Add AARCH64_OPND_SVE_PATTERN_SCALED
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rsandifo-arm committed Sep 21, 2016
1 parent 245d2e3 commit 2442d84
Show file tree
Hide file tree
Showing 15 changed files with 186 additions and 19 deletions.
8 changes: 8 additions & 0 deletions gas/ChangeLog
Original file line number Diff line number Diff line change
@@ -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>

* config/tc-aarch64.c (parse_enum_string): New function.
Expand Down
42 changes: 41 additions & 1 deletion gas/config/tc-aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -2882,6 +2882,7 @@ enum parse_shift_mode
SHIFTED_LOGIC_IMM, /* "rn{,lsl|lsr|asl|asr|ror #n}" or
"#imm" */
SHIFTED_LSL, /* bare "lsl #n" */
SHIFTED_MUL, /* bare "mul #n" */
SHIFTED_LSL_MSL, /* "lsl|msl #n" */
SHIFTED_REG_OFFSET /* [su]xtw|sxtx {#n} or lsl #n */
};
Expand Down Expand Up @@ -2923,6 +2924,13 @@ parse_shift (char **str, aarch64_opnd_info *operand, enum parse_shift_mode mode)
return FALSE;
}

if (kind == AARCH64_MOD_MUL
&& mode != SHIFTED_MUL)
{
set_syntax_error (_("invalid use of 'MUL'"));
return FALSE;
}

switch (mode)
{
case SHIFTED_LOGIC_IMM:
Expand All @@ -2949,6 +2957,14 @@ parse_shift (char **str, aarch64_opnd_info *operand, enum parse_shift_mode mode)
}
break;

case SHIFTED_MUL:
if (kind != AARCH64_MOD_MUL)
{
set_syntax_error (_("only 'MUL' is permitted"));
return FALSE;
}
break;

case SHIFTED_REG_OFFSET:
if (kind != AARCH64_MOD_UXTW && kind != AARCH64_MOD_LSL
&& kind != AARCH64_MOD_SXTW && kind != AARCH64_MOD_SXTX)
Expand Down Expand Up @@ -3001,7 +3017,11 @@ parse_shift (char **str, aarch64_opnd_info *operand, enum parse_shift_mode mode)
set_syntax_error (_("constant shift amount required"));
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"));
return FALSE;
Expand Down Expand Up @@ -4863,6 +4883,12 @@ process_omitted_operand (enum aarch64_opnd type, const aarch64_opcode *opcode,
operand->imm.value = default_value;
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:
inst.reloc.type = BFD_RELOC_UNUSED;
break;
Expand Down Expand Up @@ -5373,6 +5399,20 @@ parse_operands (char *str, const aarch64_opcode *opcode)
info->imm.value = val;
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:
po_enum_or_fail (aarch64_sve_prfop_array);
info->imm.value = val;
Expand Down
8 changes: 8 additions & 0 deletions include/ChangeLog
Original file line number Diff line number Diff line change
@@ -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>

* opcode/aarch64.h (AARCH64_OPND_SVE_PATTERN): New aarch64_opnd.
Expand Down
4 changes: 3 additions & 1 deletion include/opcode/aarch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ enum aarch64_opnd
AARCH64_OPND_BARRIER_PSB, /* Barrier operand for PSB. */

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_Pd, /* SVE p0-p15 in Pd. */
AARCH64_OPND_SVE_Pg3, /* SVE p0-p7 in Pg. */
Expand Down Expand Up @@ -745,6 +746,7 @@ enum aarch64_modifier_kind
AARCH64_MOD_SXTH,
AARCH64_MOD_SXTW,
AARCH64_MOD_SXTX,
AARCH64_MOD_MUL,
};

bfd_boolean
Expand Down Expand Up @@ -836,10 +838,10 @@ struct aarch64_opnd_info
struct
{
enum aarch64_modifier_kind kind;
int amount;
unsigned operator_present: 1; /* Only valid during encoding. */
/* Value of the 'S' field in ld/st reg offset; used only in decoding. */
unsigned amount_present: 1;
int64_t amount;
} shifter;

unsigned skip:1; /* Operand is not completed if there is a fixup needed
Expand Down
22 changes: 22 additions & 0 deletions opcodes/ChangeLog
Original file line number Diff line number Diff line change
@@ -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>

* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for
Expand Down
14 changes: 8 additions & 6 deletions opcodes/aarch64-asm-2.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,6 @@ aarch64_insert_operand (const aarch64_operand *self,
case 27:
case 35:
case 36:
case 91:
case 92:
case 93:
case 94:
Expand All @@ -494,7 +493,8 @@ aarch64_insert_operand (const aarch64_operand *self,
case 102:
case 103:
case 104:
case 107:
case 105:
case 108:
return aarch64_ins_regno (self, info, code, inst);
case 12:
return aarch64_ins_reg_extended (self, info, code, inst);
Expand Down Expand Up @@ -532,7 +532,7 @@ aarch64_insert_operand (const aarch64_operand *self,
case 69:
case 70:
case 89:
case 90:
case 91:
return aarch64_ins_imm (self, info, code, inst);
case 38:
case 39:
Expand Down Expand Up @@ -583,10 +583,12 @@ aarch64_insert_operand (const aarch64_operand *self,
return aarch64_ins_prfop (self, info, code, inst);
case 88:
return aarch64_ins_hint (self, info, code, inst);
case 105:
return aarch64_ins_sve_index (self, info, code, inst);
case 90:
return aarch64_ins_sve_scale (self, info, code, inst);
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);
default: assert (0); abort ();
}
Expand Down
13 changes: 13 additions & 0 deletions opcodes/aarch64-asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,19 @@ aarch64_ins_sve_reglist (const aarch64_operand *self,
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. */

/* Encode size[0], i.e. bit 22, for
Expand Down
1 change: 1 addition & 0 deletions opcodes/aarch64-asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ AARCH64_DECL_OPD_INSERTER (ins_reg_extended);
AARCH64_DECL_OPD_INSERTER (ins_reg_shifted);
AARCH64_DECL_OPD_INSERTER (ins_sve_index);
AARCH64_DECL_OPD_INSERTER (ins_sve_reglist);
AARCH64_DECL_OPD_INSERTER (ins_sve_scale);

#undef AARCH64_DECL_OPD_INSERTER

Expand Down
14 changes: 8 additions & 6 deletions opcodes/aarch64-dis-2.c
Original file line number Diff line number Diff line change
Expand Up @@ -10426,7 +10426,6 @@ aarch64_extract_operand (const aarch64_operand *self,
case 27:
case 35:
case 36:
case 91:
case 92:
case 93:
case 94:
Expand All @@ -10440,7 +10439,8 @@ aarch64_extract_operand (const aarch64_operand *self,
case 102:
case 103:
case 104:
case 107:
case 105:
case 108:
return aarch64_ext_regno (self, info, code, inst);
case 8:
return aarch64_ext_regrt_sysins (self, info, code, inst);
Expand Down Expand Up @@ -10483,7 +10483,7 @@ aarch64_extract_operand (const aarch64_operand *self,
case 69:
case 70:
case 89:
case 90:
case 91:
return aarch64_ext_imm (self, info, code, inst);
case 38:
case 39:
Expand Down Expand Up @@ -10536,10 +10536,12 @@ aarch64_extract_operand (const aarch64_operand *self,
return aarch64_ext_prfop (self, info, code, inst);
case 88:
return aarch64_ext_hint (self, info, code, inst);
case 105:
return aarch64_ext_sve_index (self, info, code, inst);
case 90:
return aarch64_ext_sve_scale (self, info, code, inst);
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);
default: assert (0); abort ();
}
Expand Down
20 changes: 20 additions & 0 deletions opcodes/aarch64-dis.c
Original file line number Diff line number Diff line change
Expand Up @@ -1219,6 +1219,26 @@ aarch64_ext_sve_reglist (const aarch64_operand *self,
info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
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
may be partially used as part of the base opcode in some instructions.
Expand Down
1 change: 1 addition & 0 deletions opcodes/aarch64-dis.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_reg_extended);
AARCH64_DECL_OPD_EXTRACTOR (ext_reg_shifted);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_index);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_reglist);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_scale);

#undef AARCH64_DECL_OPD_EXTRACTOR

Expand Down
1 change: 1 addition & 0 deletions opcodes/aarch64-opc-2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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, "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_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_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"},
Expand Down
Loading

0 comments on commit 2442d84

Please sign in to comment.