diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2016-09-21 16:54:53 +0100 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@arm.com> | 2016-09-21 16:54:53 +0100 |
commit | 245d2e3fe8d9ff35c65ed1329609fb7e59034877 (patch) | |
tree | b35423d664e70149dadbee4992d77506f8a8787c /gas/config | |
parent | d50c751e00b5336b4604b92271ab84615fdb0d27 (diff) | |
download | gdb-245d2e3fe8d9ff35c65ed1329609fb7e59034877.zip gdb-245d2e3fe8d9ff35c65ed1329609fb7e59034877.tar.gz gdb-245d2e3fe8d9ff35c65ed1329609fb7e59034877.tar.bz2 |
[AArch64][SVE 23/32] Add SVE pattern and prfop operands
The SVE instructions have two enumerated operands: one to select a
vector pattern and another to select a prefetch operation. The latter
is a cut-down version of the base AArch64 prefetch operation.
Both types of operand can also be specified as raw enum values such as #31.
Reserved values can only be specified this way.
If it hadn't been for the pattern operand, I would have been tempted
to use the existing parsing for prefetch operations and add extra
checks for SVE. However, since the patterns needed new enum parsing
code anyway, it seeemed cleaner to reuse it for the prefetches too.
Because of the small number of enum values, I don't think we'd gain
anything by using hash tables.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_PATTERN): New aarch64_opnd.
(AARCH64_OPND_SVE_PRFOP): Likewise.
(aarch64_sve_pattern_array): Declare.
(aarch64_sve_prfop_array): Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for
AARCH64_OPND_SVE_PATTERN and AARCH64_OPND_SVE_PRFOP.
* aarch64-opc.h (FLD_SVE_pattern): New aarch64_field_kind.
(FLD_SVE_prfop): Likewise.
* aarch64-opc.c: Include libiberty.h.
(aarch64_sve_pattern_array): New variable.
(aarch64_sve_prfop_array): Likewise.
(fields): Add entries for FLD_SVE_pattern and FLD_SVE_prfop.
(aarch64_print_operand): Handle AARCH64_OPND_SVE_PATTERN and
AARCH64_OPND_SVE_PRFOP.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis-2.c: Likewise.
* aarch64-opc-2.c: Likewise.
gas/
* config/tc-aarch64.c (parse_enum_string): New function.
(po_enum_or_fail): New macro.
(parse_operands): Handle AARCH64_OPND_SVE_PATTERN and
AARCH64_OPND_SVE_PRFOP.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-aarch64.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index f877262..7a3a39d 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -3584,6 +3584,52 @@ parse_adrp (char **str) /* Miscellaneous. */ +/* Parse a symbolic operand such as "pow2" at *STR. ARRAY is an array + of SIZE tokens in which index I gives the token for field value I, + or is null if field value I is invalid. REG_TYPE says which register + names should be treated as registers rather than as symbolic immediates. + + Return true on success, moving *STR past the operand and storing the + field value in *VAL. */ + +static int +parse_enum_string (char **str, int64_t *val, const char *const *array, + size_t size, aarch64_reg_type reg_type) +{ + expressionS exp; + char *p, *q; + size_t i; + + /* Match C-like tokens. */ + p = q = *str; + while (ISALNUM (*q)) + q++; + + for (i = 0; i < size; ++i) + if (array[i] + && strncasecmp (array[i], p, q - p) == 0 + && array[i][q - p] == 0) + { + *val = i; + *str = q; + return TRUE; + } + + if (!parse_immediate_expression (&p, &exp, reg_type)) + return FALSE; + + if (exp.X_op == O_constant + && (uint64_t) exp.X_add_number < size) + { + *val = exp.X_add_number; + *str = p; + return TRUE; + } + + /* Use the default error for this operand. */ + return FALSE; +} + /* Parse an option for a preload instruction. Returns the encoding for the option, or PARSE_FAIL. */ @@ -3793,6 +3839,12 @@ parse_sys_ins_reg (char **str, struct hash_control *sys_ins_regs) } \ } while (0) +#define po_enum_or_fail(array) do { \ + if (!parse_enum_string (&str, &val, array, \ + ARRAY_SIZE (array), imm_reg_type)) \ + goto failure; \ + } while (0) + #define po_misc_or_fail(expr) do { \ if (!expr) \ goto failure; \ @@ -4806,6 +4858,8 @@ process_omitted_operand (enum aarch64_opnd type, const aarch64_opcode *opcode, case AARCH64_OPND_WIDTH: case AARCH64_OPND_UIMM7: case AARCH64_OPND_NZCV: + case AARCH64_OPND_SVE_PATTERN: + case AARCH64_OPND_SVE_PRFOP: operand->imm.value = default_value; break; @@ -5314,6 +5368,16 @@ parse_operands (char *str, const aarch64_opcode *opcode) info->imm.value = val; break; + case AARCH64_OPND_SVE_PATTERN: + po_enum_or_fail (aarch64_sve_pattern_array); + info->imm.value = val; + break; + + case AARCH64_OPND_SVE_PRFOP: + po_enum_or_fail (aarch64_sve_prfop_array); + info->imm.value = val; + break; + case AARCH64_OPND_UIMM7: po_imm_or_fail (0, 127); info->imm.value = val; |