This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [AArch64][SVE 23/32] Add SVE pattern and prfop operands
On 23/08/16 10:19, Richard Sandiford wrote:
> 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.
>
> OK to install?
>
> Thanks,
> Richard
>
>
> 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.
>
OK.
R.
> diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
> index ed4933b..9d1e3ec 100644
> --- a/gas/config/tc-aarch64.c
> +++ b/gas/config/tc-aarch64.c
> @@ -3634,6 +3634,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. */
>
> @@ -3844,6 +3890,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; \
> @@ -4857,6 +4909,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;
>
> @@ -5365,6 +5419,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;
> diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
> index 8eae0b9..dd191cf 100644
> --- a/include/opcode/aarch64.h
> +++ b/include/opcode/aarch64.h
> @@ -244,6 +244,8 @@ enum aarch64_opnd
> AARCH64_OPND_PRFOP, /* Prefetch operation. */
> AARCH64_OPND_BARRIER_PSB, /* Barrier operand for PSB. */
>
> + AARCH64_OPND_SVE_PATTERN, /* SVE vector pattern enumeration. */
> + 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. */
> AARCH64_OPND_SVE_Pg4_5, /* SVE p0-p15 in Pg, bits [8,5]. */
> @@ -1037,6 +1039,9 @@ aarch64_verbose (const char *, ...) __attribute__ ((format (printf, 1, 2)));
> #define DEBUG_TRACE_IF(C, M, ...) ;
> #endif /* DEBUG_AARCH64 */
>
> +extern const char *const aarch64_sve_pattern_array[32];
> +extern const char *const aarch64_sve_prfop_array[16];
> +
> #ifdef __cplusplus
> }
> #endif
> diff --git a/opcodes/aarch64-asm-2.c b/opcodes/aarch64-asm-2.c
> index 9c797b2..0a6e476 100644
> --- a/opcodes/aarch64-asm-2.c
> +++ b/opcodes/aarch64-asm-2.c
> @@ -480,8 +480,6 @@ aarch64_insert_operand (const aarch64_operand *self,
> case 27:
> case 35:
> case 36:
> - case 89:
> - case 90:
> case 91:
> case 92:
> case 93:
> @@ -494,7 +492,9 @@ aarch64_insert_operand (const aarch64_operand *self,
> case 100:
> case 101:
> case 102:
> - case 105:
> + case 103:
> + case 104:
> + case 107:
> return aarch64_ins_regno (self, info, code, inst);
> case 12:
> return aarch64_ins_reg_extended (self, info, code, inst);
> @@ -531,6 +531,8 @@ aarch64_insert_operand (const aarch64_operand *self,
> case 68:
> case 69:
> case 70:
> + case 89:
> + case 90:
> return aarch64_ins_imm (self, info, code, inst);
> case 38:
> case 39:
> @@ -581,10 +583,10 @@ 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 103:
> + case 105:
> return aarch64_ins_sve_index (self, info, code, inst);
> - case 104:
> case 106:
> + case 108:
> return aarch64_ins_sve_reglist (self, info, code, inst);
> default: assert (0); abort ();
> }
> diff --git a/opcodes/aarch64-dis-2.c b/opcodes/aarch64-dis-2.c
> index 6ea010b..9f936f0 100644
> --- a/opcodes/aarch64-dis-2.c
> +++ b/opcodes/aarch64-dis-2.c
> @@ -10426,8 +10426,6 @@ aarch64_extract_operand (const aarch64_operand *self,
> case 27:
> case 35:
> case 36:
> - case 89:
> - case 90:
> case 91:
> case 92:
> case 93:
> @@ -10440,7 +10438,9 @@ aarch64_extract_operand (const aarch64_operand *self,
> case 100:
> case 101:
> case 102:
> - case 105:
> + case 103:
> + case 104:
> + case 107:
> return aarch64_ext_regno (self, info, code, inst);
> case 8:
> return aarch64_ext_regrt_sysins (self, info, code, inst);
> @@ -10482,6 +10482,8 @@ aarch64_extract_operand (const aarch64_operand *self,
> case 68:
> case 69:
> case 70:
> + case 89:
> + case 90:
> return aarch64_ext_imm (self, info, code, inst);
> case 38:
> case 39:
> @@ -10534,10 +10536,10 @@ 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 103:
> + case 105:
> return aarch64_ext_sve_index (self, info, code, inst);
> - case 104:
> case 106:
> + case 108:
> return aarch64_ext_sve_reglist (self, info, code, inst);
> default: assert (0); abort ();
> }
> diff --git a/opcodes/aarch64-opc-2.c b/opcodes/aarch64-opc-2.c
> index f8a7079..3905053 100644
> --- a/opcodes/aarch64-opc-2.c
> +++ b/opcodes/aarch64-opc-2.c
> @@ -113,6 +113,8 @@ const struct aarch64_operand aarch64_operands[] =
> {AARCH64_OPND_CLASS_SYSTEM, "BARRIER_ISB", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "the ISB option name SY or an optional 4-bit unsigned immediate"},
> {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_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"},
> {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pg4_5", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pg4_5}, "an SVE predicate register"},
> diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
> index 41c058f..934c14d 100644
> --- a/opcodes/aarch64-opc.c
> +++ b/opcodes/aarch64-opc.c
> @@ -27,6 +27,7 @@
> #include <inttypes.h>
>
> #include "opintl.h"
> +#include "libiberty.h"
>
> #include "aarch64-opc.h"
>
> @@ -34,6 +35,70 @@
> int debug_dump = FALSE;
> #endif /* DEBUG_AARCH64 */
>
> +/* The enumeration strings associated with each value of a 5-bit SVE
> + pattern operand. A null entry indicates a reserved meaning. */
> +const char *const aarch64_sve_pattern_array[32] = {
> + /* 0-7. */
> + "pow2",
> + "vl1",
> + "vl2",
> + "vl3",
> + "vl4",
> + "vl5",
> + "vl6",
> + "vl7",
> + /* 8-15. */
> + "vl8",
> + "vl16",
> + "vl32",
> + "vl64",
> + "vl128",
> + "vl256",
> + 0,
> + 0,
> + /* 16-23. */
> + 0,
> + 0,
> + 0,
> + 0,
> + 0,
> + 0,
> + 0,
> + 0,
> + /* 24-31. */
> + 0,
> + 0,
> + 0,
> + 0,
> + 0,
> + "mul4",
> + "mul3",
> + "all"
> +};
> +
> +/* The enumeration strings associated with each value of a 4-bit SVE
> + prefetch operand. A null entry indicates a reserved meaning. */
> +const char *const aarch64_sve_prfop_array[16] = {
> + /* 0-7. */
> + "pldl1keep",
> + "pldl1strm",
> + "pldl2keep",
> + "pldl2strm",
> + "pldl3keep",
> + "pldl3strm",
> + 0,
> + 0,
> + /* 8-15. */
> + "pstl1keep",
> + "pstl1strm",
> + "pstl2keep",
> + "pstl2strm",
> + "pstl3keep",
> + "pstl3strm",
> + 0,
> + 0
> +};
> +
> /* Helper functions to determine which operand to be used to encode/decode
> the size:Q fields for AdvSIMD instructions. */
>
> @@ -214,6 +279,8 @@ 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]. */
> + { 5, 5 }, /* SVE_pattern: vector pattern enumeration. */
> + { 0, 4 }, /* SVE_prfop: prefetch operation for SVE PRF[BHWD]. */
> { 22, 2 }, /* SVE_tszh: triangular size select high, bits [23,22]. */
> };
>
> @@ -2489,7 +2556,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
> const char *name = NULL;
> const aarch64_opnd_info *opnd = opnds + idx;
> enum aarch64_modifier_kind kind;
> - uint64_t addr;
> + uint64_t addr, enum_value;
>
> buf[0] = '\0';
> if (pcrel_p)
> @@ -2681,6 +2748,27 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
> snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
> break;
>
> + case AARCH64_OPND_SVE_PATTERN:
> + if (optional_operand_p (opcode, idx)
> + && 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[enum_value])
> + snprintf (buf, size, "%s", aarch64_sve_pattern_array[enum_value]);
> + else
> + snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
> + break;
> +
> + case AARCH64_OPND_SVE_PRFOP:
> + enum_value = opnd->imm.value;
> + assert (enum_value < ARRAY_SIZE (aarch64_sve_prfop_array));
> + if (aarch64_sve_prfop_array[enum_value])
> + snprintf (buf, size, "%s", aarch64_sve_prfop_array[enum_value]);
> + else
> + snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
> + break;
> +
> case AARCH64_OPND_IMM_MOV:
> switch (aarch64_get_qualifier_esize (opnds[0].qualifier))
> {
> diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h
> index cc3dbef..b54f35e 100644
> --- a/opcodes/aarch64-opc.h
> +++ b/opcodes/aarch64-opc.h
> @@ -106,6 +106,8 @@ enum aarch64_field_kind
> FLD_SVE_Zm_16,
> FLD_SVE_Zn,
> FLD_SVE_Zt,
> + FLD_SVE_pattern,
> + FLD_SVE_prfop,
> FLD_SVE_tszh,
> };
>
> diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
> index 9dbe0c0..73415f7 100644
> --- a/opcodes/aarch64-tbl.h
> +++ b/opcodes/aarch64-tbl.h
> @@ -2820,6 +2820,10 @@ struct aarch64_opcode aarch64_opcode_table[] =
> "a prefetch operation specifier") \
> Y (SYSTEM, hint, "BARRIER_PSB", 0, F (), \
> "the PSB option name CSYNC") \
> + Y(IMMEDIATE, imm, "SVE_PATTERN", 0, F(FLD_SVE_pattern), \
> + "an enumeration value such as POW2") \
> + Y(IMMEDIATE, imm, "SVE_PRFOP", 0, F(FLD_SVE_prfop), \
> + "an enumeration value such as PLDL1KEEP") \
> Y(PRED_REG, regno, "SVE_Pd", 0, F(FLD_SVE_Pd), \
> "an SVE predicate register") \
> Y(PRED_REG, regno, "SVE_Pg3", 0, F(FLD_SVE_Pg3), \
>