diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2016-09-21 16:55:22 +0100 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@arm.com> | 2016-09-21 16:55:22 +0100 |
commit | 2442d8466e221ba6cf4ec4bd2a819fdcb1e5ea7e (patch) | |
tree | 3cf11472e060354947af66613dd1b4a6361f9b02 /gas | |
parent | 245d2e3fe8d9ff35c65ed1329609fb7e59034877 (diff) | |
download | gdb-2442d8466e221ba6cf4ec4bd2a819fdcb1e5ea7e.zip gdb-2442d8466e221ba6cf4ec4bd2a819fdcb1e5ea7e.tar.gz gdb-2442d8466e221ba6cf4ec4bd2a819fdcb1e5ea7e.tar.bz2 |
[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.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 8 | ||||
-rw-r--r-- | gas/config/tc-aarch64.c | 42 |
2 files changed, 49 insertions, 1 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index d532bb1..97f1a61 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,13 @@ 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. (po_enum_or_fail): New macro. (parse_operands): Handle AARCH64_OPND_SVE_PATTERN and diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index 7a3a39d..79ee054 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -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 */ }; @@ -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: @@ -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) @@ -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; @@ -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; @@ -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; |