diff options
-rw-r--r-- | gas/ChangeLog | 7 | ||||
-rw-r--r-- | gas/config/tc-aarch64.c | 64 | ||||
-rw-r--r-- | include/ChangeLog | 7 | ||||
-rw-r--r-- | include/opcode/aarch64.h | 5 | ||||
-rw-r--r-- | opcodes/ChangeLog | 16 | ||||
-rw-r--r-- | opcodes/aarch64-asm-2.c | 12 | ||||
-rw-r--r-- | opcodes/aarch64-dis-2.c | 12 | ||||
-rw-r--r-- | opcodes/aarch64-opc-2.c | 2 | ||||
-rw-r--r-- | opcodes/aarch64-opc.c | 90 | ||||
-rw-r--r-- | opcodes/aarch64-opc.h | 2 | ||||
-rw-r--r-- | opcodes/aarch64-tbl.h | 4 |
11 files changed, 210 insertions, 11 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 589b2cf..d532bb1 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,12 @@ 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 + AARCH64_OPND_SVE_PRFOP. + +2016-09-21 Richard Sandiford <richard.sandiford@arm.com> + * config/tc-aarch64.c (vector_el_type): Add NT_zero and NT_merge. (parse_vector_type_for_operand): Assert that the skipped character is a '.'. 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; diff --git a/include/ChangeLog b/include/ChangeLog index 175d1d5..96da0a3 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,5 +1,12 @@ 2016-09-21 Richard Sandiford <richard.sandiford@arm.com> + * 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. + +2016-09-21 Richard Sandiford <richard.sandiford@arm.com> + * opcode/aarch64.h (AARCH64_OPND_QLF_P_Z): New aarch64_opnd_qualifier. (AARCH64_OPND_QLF_P_M): Likewise. 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/ChangeLog b/opcodes/ChangeLog index 5d2ddb1..a2afc0d 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,5 +1,21 @@ 2016-09-21 Richard Sandiford <richard.sandiford@arm.com> + * 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. + +2016-09-21 Richard Sandiford <richard.sandiford@arm.com> + * aarch64-opc.c (aarch64_opnd_qualifiers): Add entries for AARCH64_OPND_QLF_P_[ZM]. (aarch64_print_operand): Print /z and /m where appropriate. 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), \ |