From f11ad6bc0fc44b94c6970115bb6984b497b967e7 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Wed, 21 Sep 2016 16:53:54 +0100 Subject: [PATCH] [AArch64][SVE 21/32] Add Zn and Pn registers This patch adds the Zn and Pn registers, and associated fields and operands. include/ * opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New aarch64_operand_class. (AARCH64_OPND_CLASS_PRED_REG): Likewise. (AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5) (AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16) (AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt) (AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd) (AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn) (AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN) (AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds. opcodes/ * aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands. * aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5) (FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt) (FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16) (FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds. * aarch64-opc.c (fields): Add corresponding entries here. (operand_general_constraint_met_p): Check that SVE register lists have the correct length. Check the ranges of SVE index registers. Check for cases where p8-p15 are used in 3-bit predicate fields. (aarch64_print_operand): Handle the new SVE operands. * aarch64-opc-2.c: Regenerate. * aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters. * aarch64-asm.c (aarch64_ins_sve_index): New function. (aarch64_ins_sve_reglist): Likewise. * aarch64-asm-2.c: Regenerate. * aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors. * aarch64-dis.c (aarch64_ext_sve_index): New function. (aarch64_ext_sve_reglist): Likewise. * aarch64-dis-2.c: Regenerate. gas/ * config/tc-aarch64.c (NTA_HASVARWIDTH): New macro. (AARCH64_REG_TYPES): Add ZN and PN. (get_reg_expected_msg): Handle them. (parse_vector_type_for_operand): Add a reg_type parameter. Skip the width for Zn and Pn registers. (parse_typed_reg): Extend vector handling to Zn and Pn. Update the call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn, expecting the width to be 0. (parse_vector_reg_list): Restrict error about [BHSD]nn operands to REG_TYPE_VN. (vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH. (parse_operands): Handle the new Zn and Pn operands. (REGSET16): New macro, split out from... (REGSET31): ...here. (reg_names): Add Zn and Pn entries. --- gas/ChangeLog | 18 +++++ gas/config/tc-aarch64.c | 161 +++++++++++++++++++++++++++++++-------- include/ChangeLog | 13 ++++ include/opcode/aarch64.h | 21 +++++ opcodes/ChangeLog | 22 ++++++ opcodes/aarch64-asm-2.c | 20 +++++ opcodes/aarch64-asm.c | 27 +++++++ opcodes/aarch64-asm.h | 2 + opcodes/aarch64-dis-2.c | 20 +++++ opcodes/aarch64-dis.c | 34 +++++++++ opcodes/aarch64-dis.h | 2 + opcodes/aarch64-opc-2.c | 18 +++++ opcodes/aarch64-opc.c | 93 ++++++++++++++++++++++ opcodes/aarch64-opc.h | 16 ++++ opcodes/aarch64-tbl.h | 38 ++++++++- 15 files changed, 473 insertions(+), 32 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 425c37a7dde..ac1bb548b63 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,21 @@ +2016-09-21 Richard Sandiford + + * config/tc-aarch64.c (NTA_HASVARWIDTH): New macro. + (AARCH64_REG_TYPES): Add ZN and PN. + (get_reg_expected_msg): Handle them. + (parse_vector_type_for_operand): Add a reg_type parameter. + Skip the width for Zn and Pn registers. + (parse_typed_reg): Extend vector handling to Zn and Pn. Update the + call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn, + expecting the width to be 0. + (parse_vector_reg_list): Restrict error about [BHSD]nn operands to + REG_TYPE_VN. + (vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH. + (parse_operands): Handle the new Zn and Pn operands. + (REGSET16): New macro, split out from... + (REGSET31): ...here. + (reg_names): Add Zn and Pn entries. + 2016-09-21 Richard Sandiford * config/tc-aarch64.c (output_operand_error_record): Handle diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index 83352303cf0..be88d29da89 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -87,8 +87,9 @@ enum vector_el_type }; /* Bits for DEFINED field in vector_type_el. */ -#define NTA_HASTYPE 1 -#define NTA_HASINDEX 2 +#define NTA_HASTYPE 1 +#define NTA_HASINDEX 2 +#define NTA_HASVARWIDTH 4 struct vector_type_el { @@ -265,6 +266,8 @@ struct reloc_entry BASIC_REG_TYPE(FP_Q) /* q[0-31] */ \ BASIC_REG_TYPE(CN) /* c[0-7] */ \ BASIC_REG_TYPE(VN) /* v[0-31] */ \ + BASIC_REG_TYPE(ZN) /* z[0-31] */ \ + BASIC_REG_TYPE(PN) /* p[0-15] */ \ /* Typecheck: any 64-bit int reg (inc SP exc XZR). */ \ MULTI_REG_TYPE(R64_SP, REG_TYPE(R_64) | REG_TYPE(SP_64)) \ /* Typecheck: x[0-30], w[0-30] or [xw]zr. */ \ @@ -393,6 +396,12 @@ get_reg_expected_msg (aarch64_reg_type reg_type) case REG_TYPE_VN: /* any V reg */ msg = N_("vector register expected"); break; + case REG_TYPE_ZN: + msg = N_("SVE vector register expected"); + break; + case REG_TYPE_PN: + msg = N_("SVE predicate register expected"); + break; default: as_fatal (_("invalid register type %d"), reg_type); } @@ -724,15 +733,16 @@ aarch64_reg_parse_32_64 (char **ccp, aarch64_opnd_qualifier_t *qualifier) return reg; } -/* Parse the qualifier of a SIMD vector register or a SIMD vector element. - Fill in *PARSED_TYPE and return TRUE if the parsing succeeds; - otherwise return FALSE. +/* Parse the qualifier of a vector register or vector element of type + REG_TYPE. Fill in *PARSED_TYPE and return TRUE if the parsing + succeeds; otherwise return FALSE. Accept only one occurrence of: 8b 16b 2h 4h 8h 2s 4s 1d 2d b h s d q */ static bfd_boolean -parse_vector_type_for_operand (struct vector_type_el *parsed_type, char **str) +parse_vector_type_for_operand (aarch64_reg_type reg_type, + struct vector_type_el *parsed_type, char **str) { char *ptr = *str; unsigned width; @@ -742,7 +752,7 @@ parse_vector_type_for_operand (struct vector_type_el *parsed_type, char **str) /* skip '.' */ ptr++; - if (!ISDIGIT (*ptr)) + if (reg_type == REG_TYPE_ZN || reg_type == REG_TYPE_PN || !ISDIGIT (*ptr)) { width = 0; goto elt_size; @@ -849,15 +859,23 @@ parse_typed_reg (char **ccp, aarch64_reg_type type, aarch64_reg_type *rtype, } type = reg->type; - if (type == REG_TYPE_VN && *str == '.') + if ((type == REG_TYPE_VN || type == REG_TYPE_ZN || type == REG_TYPE_PN) + && *str == '.') { - if (!parse_vector_type_for_operand (&parsetype, &str)) + if (!parse_vector_type_for_operand (type, &parsetype, &str)) return PARSE_FAIL; /* Register if of the form Vn.[bhsdq]. */ is_typed_vecreg = TRUE; - if (parsetype.width == 0) + if (type == REG_TYPE_ZN || type == REG_TYPE_PN) + { + /* The width is always variable; we don't allow an integer width + to be specified. */ + gas_assert (parsetype.width == 0); + atype.defined |= NTA_HASVARWIDTH | NTA_HASTYPE; + } + else if (parsetype.width == 0) /* Expect index. In the new scheme we cannot have Vn.[bhsdq] represent a scalar. Therefore any Vn.[bhsdq] should have an index following it. @@ -1034,7 +1052,7 @@ parse_vector_reg_list (char **ccp, aarch64_reg_type type, continue; } /* reject [bhsd]n */ - if (typeinfo.defined == 0) + if (type == REG_TYPE_VN && typeinfo.defined == 0) { set_first_syntax_error (_("invalid scalar register in list")); error = TRUE; @@ -4639,7 +4657,7 @@ vectype_to_qualifier (const struct vector_type_el *vectype) gas_assert (vectype->type >= NT_b && vectype->type <= NT_q); - if (vectype->defined & NTA_HASINDEX) + if (vectype->defined & (NTA_HASINDEX | NTA_HASVARWIDTH)) /* Vector element register. */ return AARCH64_OPND_QLF_S_B + vectype->type; else @@ -4979,6 +4997,7 @@ parse_operands (char *str, const aarch64_opcode *opcode) struct vector_type_el vectype; aarch64_opnd_qualifier_t qualifier; aarch64_opnd_info *info = &inst.base.operands[i]; + aarch64_reg_type reg_type; DEBUG_TRACE ("parse operand %d", i); @@ -5061,22 +5080,54 @@ parse_operands (char *str, const aarch64_opcode *opcode) info->qualifier = AARCH64_OPND_QLF_S_B + (rtype - REG_TYPE_FP_B); break; + case AARCH64_OPND_SVE_Pd: + case AARCH64_OPND_SVE_Pg3: + case AARCH64_OPND_SVE_Pg4_5: + case AARCH64_OPND_SVE_Pg4_10: + case AARCH64_OPND_SVE_Pg4_16: + case AARCH64_OPND_SVE_Pm: + case AARCH64_OPND_SVE_Pn: + case AARCH64_OPND_SVE_Pt: + reg_type = REG_TYPE_PN; + goto vector_reg; + + case AARCH64_OPND_SVE_Za_5: + case AARCH64_OPND_SVE_Za_16: + case AARCH64_OPND_SVE_Zd: + case AARCH64_OPND_SVE_Zm_5: + case AARCH64_OPND_SVE_Zm_16: + case AARCH64_OPND_SVE_Zn: + case AARCH64_OPND_SVE_Zt: + reg_type = REG_TYPE_ZN; + goto vector_reg; + case AARCH64_OPND_Vd: case AARCH64_OPND_Vn: case AARCH64_OPND_Vm: - val = aarch64_reg_parse (&str, REG_TYPE_VN, NULL, &vectype); + reg_type = REG_TYPE_VN; + vector_reg: + val = aarch64_reg_parse (&str, reg_type, NULL, &vectype); if (val == PARSE_FAIL) { - first_error (_(get_reg_expected_msg (REG_TYPE_VN))); + first_error (_(get_reg_expected_msg (reg_type))); goto failure; } if (vectype.defined & NTA_HASINDEX) goto failure; info->reg.regno = val; - info->qualifier = vectype_to_qualifier (&vectype); - if (info->qualifier == AARCH64_OPND_QLF_NIL) - goto failure; + if ((reg_type == REG_TYPE_PN || reg_type == REG_TYPE_ZN) + && vectype.type == NT_invtype) + /* Unqualified Pn and Zn registers are allowed in certain + contexts. Rely on F_STRICT qualifier checking to catch + invalid uses. */ + info->qualifier = AARCH64_OPND_QLF_NIL; + else + { + info->qualifier = vectype_to_qualifier (&vectype); + if (info->qualifier == AARCH64_OPND_QLF_NIL) + goto failure; + } break; case AARCH64_OPND_VdD1: @@ -5101,13 +5152,19 @@ parse_operands (char *str, const aarch64_opcode *opcode) info->qualifier = AARCH64_OPND_QLF_S_D; break; + case AARCH64_OPND_SVE_Zn_INDEX: + reg_type = REG_TYPE_ZN; + goto vector_reg_index; + case AARCH64_OPND_Ed: case AARCH64_OPND_En: case AARCH64_OPND_Em: - val = aarch64_reg_parse (&str, REG_TYPE_VN, NULL, &vectype); + reg_type = REG_TYPE_VN; + vector_reg_index: + val = aarch64_reg_parse (&str, reg_type, NULL, &vectype); if (val == PARSE_FAIL) { - first_error (_(get_reg_expected_msg (REG_TYPE_VN))); + first_error (_(get_reg_expected_msg (reg_type))); goto failure; } if (vectype.type == NT_invtype || !(vectype.defined & NTA_HASINDEX)) @@ -5120,20 +5177,43 @@ parse_operands (char *str, const aarch64_opcode *opcode) goto failure; break; + case AARCH64_OPND_SVE_ZnxN: + case AARCH64_OPND_SVE_ZtxN: + reg_type = REG_TYPE_ZN; + goto vector_reg_list; + case AARCH64_OPND_LVn: case AARCH64_OPND_LVt: case AARCH64_OPND_LVt_AL: case AARCH64_OPND_LEt: - if ((val = parse_vector_reg_list (&str, REG_TYPE_VN, - &vectype)) == PARSE_FAIL) - goto failure; - if (! reg_list_valid_p (val, /* accept_alternate */ 0)) + reg_type = REG_TYPE_VN; + vector_reg_list: + if (reg_type == REG_TYPE_ZN + && get_opcode_dependent_value (opcode) == 1 + && *str != '{') { - set_fatal_syntax_error (_("invalid register list")); - goto failure; + val = aarch64_reg_parse (&str, reg_type, NULL, &vectype); + if (val == PARSE_FAIL) + { + first_error (_(get_reg_expected_msg (reg_type))); + goto failure; + } + info->reglist.first_regno = val; + info->reglist.num_regs = 1; + } + else + { + val = parse_vector_reg_list (&str, reg_type, &vectype); + if (val == PARSE_FAIL) + goto failure; + if (! reg_list_valid_p (val, /* accept_alternate */ 0)) + { + set_fatal_syntax_error (_("invalid register list")); + goto failure; + } + info->reglist.first_regno = (val >> 2) & 0x1f; + info->reglist.num_regs = (val & 0x3) + 1; } - info->reglist.first_regno = (val >> 2) & 0x1f; - info->reglist.num_regs = (val & 0x3) + 1; if (operands[i] == AARCH64_OPND_LEt) { if (!(vectype.defined & NTA_HASINDEX)) @@ -5141,8 +5221,17 @@ parse_operands (char *str, const aarch64_opcode *opcode) info->reglist.has_index = 1; info->reglist.index = vectype.index; } - else if (!(vectype.defined & NTA_HASTYPE)) - goto failure; + else + { + if (vectype.defined & NTA_HASINDEX) + goto failure; + if (!(vectype.defined & NTA_HASTYPE)) + { + if (reg_type == REG_TYPE_ZN) + set_fatal_syntax_error (_("missing type suffix")); + goto failure; + } + } info->qualifier = vectype_to_qualifier (&vectype); if (info->qualifier == AARCH64_OPND_QLF_NIL) goto failure; @@ -6157,11 +6246,13 @@ aarch64_canonicalize_symbol_name (char *name) #define REGDEF(s,n,t) { #s, n, REG_TYPE_##t, TRUE } #define REGNUM(p,n,t) REGDEF(p##n, n, t) -#define REGSET31(p,t) \ +#define REGSET16(p,t) \ REGNUM(p, 0,t), REGNUM(p, 1,t), REGNUM(p, 2,t), REGNUM(p, 3,t), \ REGNUM(p, 4,t), REGNUM(p, 5,t), REGNUM(p, 6,t), REGNUM(p, 7,t), \ REGNUM(p, 8,t), REGNUM(p, 9,t), REGNUM(p,10,t), REGNUM(p,11,t), \ - REGNUM(p,12,t), REGNUM(p,13,t), REGNUM(p,14,t), REGNUM(p,15,t), \ + REGNUM(p,12,t), REGNUM(p,13,t), REGNUM(p,14,t), REGNUM(p,15,t) +#define REGSET31(p,t) \ + REGSET16(p, t), \ REGNUM(p,16,t), REGNUM(p,17,t), REGNUM(p,18,t), REGNUM(p,19,t), \ REGNUM(p,20,t), REGNUM(p,21,t), REGNUM(p,22,t), REGNUM(p,23,t), \ REGNUM(p,24,t), REGNUM(p,25,t), REGNUM(p,26,t), REGNUM(p,27,t), \ @@ -6201,10 +6292,18 @@ static const reg_entry reg_names[] = { /* FP/SIMD registers. */ REGSET (v, VN), REGSET (V, VN), + + /* SVE vector registers. */ + REGSET (z, ZN), REGSET (Z, ZN), + + /* SVE predicate registers. */ + REGSET16 (p, PN), REGSET16 (P, PN) }; #undef REGDEF #undef REGNUM +#undef REGSET16 +#undef REGSET31 #undef REGSET #define N 1 diff --git a/include/ChangeLog b/include/ChangeLog index e6c3dbdf508..53d0ba0b176 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,16 @@ +2016-09-21 Richard Sandiford + + * opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New + aarch64_operand_class. + (AARCH64_OPND_CLASS_PRED_REG): Likewise. + (AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5) + (AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16) + (AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt) + (AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd) + (AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn) + (AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN) + (AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds. + 2016-09-21 Richard Sandiford * opcode/aarch64.h (aarch64_opcode): Add a tied_operand field. diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h index d39f10d0cfc..b0eb6175d07 100644 --- a/include/opcode/aarch64.h +++ b/include/opcode/aarch64.h @@ -120,6 +120,8 @@ enum aarch64_operand_class AARCH64_OPND_CLASS_SISD_REG, AARCH64_OPND_CLASS_SIMD_REGLIST, AARCH64_OPND_CLASS_CP_REG, + AARCH64_OPND_CLASS_SVE_REG, + AARCH64_OPND_CLASS_PRED_REG, AARCH64_OPND_CLASS_ADDRESS, AARCH64_OPND_CLASS_IMMEDIATE, AARCH64_OPND_CLASS_SYSTEM, @@ -241,6 +243,25 @@ enum aarch64_opnd AARCH64_OPND_BARRIER_ISB, /* Barrier operand for ISB. */ AARCH64_OPND_PRFOP, /* Prefetch operation. */ AARCH64_OPND_BARRIER_PSB, /* Barrier operand for PSB. */ + + 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]. */ + AARCH64_OPND_SVE_Pg4_10, /* SVE p0-p15 in Pg, bits [13,10]. */ + AARCH64_OPND_SVE_Pg4_16, /* SVE p0-p15 in Pg, bits [19,16]. */ + AARCH64_OPND_SVE_Pm, /* SVE p0-p15 in Pm. */ + AARCH64_OPND_SVE_Pn, /* SVE p0-p15 in Pn. */ + AARCH64_OPND_SVE_Pt, /* SVE p0-p15 in Pt. */ + AARCH64_OPND_SVE_Za_5, /* SVE vector register in Za, bits [9,5]. */ + AARCH64_OPND_SVE_Za_16, /* SVE vector register in Za, bits [20,16]. */ + AARCH64_OPND_SVE_Zd, /* SVE vector register in Zd. */ + AARCH64_OPND_SVE_Zm_5, /* SVE vector register in Zm, bits [9,5]. */ + AARCH64_OPND_SVE_Zm_16, /* SVE vector register in Zm, bits [20,16]. */ + AARCH64_OPND_SVE_Zn, /* SVE vector register in Zn. */ + AARCH64_OPND_SVE_Zn_INDEX, /* Indexed SVE vector register, for DUP. */ + AARCH64_OPND_SVE_ZnxN, /* SVE vector register list in Zn. */ + AARCH64_OPND_SVE_Zt, /* SVE vector register in Zt. */ + AARCH64_OPND_SVE_ZtxN, /* SVE vector register list in Zt. */ }; /* Qualifier constrains an operand. It either specifies a variant of an diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 925ea1eb101..463837baa43 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,25 @@ +2016-09-21 Richard Sandiford + + * aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands. + * aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5) + (FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt) + (FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16) + (FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds. + * aarch64-opc.c (fields): Add corresponding entries here. + (operand_general_constraint_met_p): Check that SVE register lists + have the correct length. Check the ranges of SVE index registers. + Check for cases where p8-p15 are used in 3-bit predicate fields. + (aarch64_print_operand): Handle the new SVE operands. + * aarch64-opc-2.c: Regenerate. + * aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters. + * aarch64-asm.c (aarch64_ins_sve_index): New function. + (aarch64_ins_sve_reglist): Likewise. + * aarch64-asm-2.c: Regenerate. + * aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors. + * aarch64-dis.c (aarch64_ext_sve_index): New function. + (aarch64_ext_sve_reglist): Likewise. + * aarch64-dis-2.c: Regenerate. + 2016-09-21 Richard Sandiford * aarch64-tbl.h (CORE_INSN, __FP_INSN, SIMD_INSN, CRYP_INSN) diff --git a/opcodes/aarch64-asm-2.c b/opcodes/aarch64-asm-2.c index 439dd3d0e80..9c797b2ea5a 100644 --- a/opcodes/aarch64-asm-2.c +++ b/opcodes/aarch64-asm-2.c @@ -480,6 +480,21 @@ aarch64_insert_operand (const aarch64_operand *self, case 27: case 35: case 36: + case 89: + case 90: + case 91: + case 92: + case 93: + case 94: + case 95: + case 96: + case 97: + case 98: + case 99: + case 100: + case 101: + case 102: + case 105: return aarch64_ins_regno (self, info, code, inst); case 12: return aarch64_ins_reg_extended (self, info, code, inst); @@ -566,6 +581,11 @@ 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: + return aarch64_ins_sve_index (self, info, code, inst); + case 104: + case 106: + return aarch64_ins_sve_reglist (self, info, code, inst); default: assert (0); abort (); } } diff --git a/opcodes/aarch64-asm.c b/opcodes/aarch64-asm.c index f291495992e..c045f9e4b41 100644 --- a/opcodes/aarch64-asm.c +++ b/opcodes/aarch64-asm.c @@ -745,6 +745,33 @@ aarch64_ins_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED, return NULL; } +/* Encode Zn[MM], where MM has a 7-bit triangular encoding. The fields + array specifies which field to use for Zn. MM is encoded in the + concatenation of imm5 and SVE_tszh, with imm5 being the less + significant part. */ +const char * +aarch64_ins_sve_index (const aarch64_operand *self, + const aarch64_opnd_info *info, aarch64_insn *code, + const aarch64_inst *inst ATTRIBUTE_UNUSED) +{ + unsigned int esize = aarch64_get_qualifier_esize (info->qualifier); + insert_field (self->fields[0], code, info->reglane.regno, 0); + insert_fields (code, (info->reglane.index * 2 + 1) * esize, 0, + 2, FLD_imm5, FLD_SVE_tszh); + return NULL; +} + +/* Encode {Zn. - Zm.}. The fields array specifies which field + to use for Zn. */ +const char * +aarch64_ins_sve_reglist (const aarch64_operand *self, + const aarch64_opnd_info *info, aarch64_insn *code, + const aarch64_inst *inst ATTRIBUTE_UNUSED) +{ + insert_field (self->fields[0], code, info->reglist.first_regno, 0); + return NULL; +} + /* Miscellaneous encoding functions. */ /* Encode size[0], i.e. bit 22, for diff --git a/opcodes/aarch64-asm.h b/opcodes/aarch64-asm.h index 3211aff99b4..ede366c00f2 100644 --- a/opcodes/aarch64-asm.h +++ b/opcodes/aarch64-asm.h @@ -69,6 +69,8 @@ AARCH64_DECL_OPD_INSERTER (ins_hint); AARCH64_DECL_OPD_INSERTER (ins_prfop); 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); #undef AARCH64_DECL_OPD_INSERTER diff --git a/opcodes/aarch64-dis-2.c b/opcodes/aarch64-dis-2.c index a86a84ddd59..6ea010b3573 100644 --- a/opcodes/aarch64-dis-2.c +++ b/opcodes/aarch64-dis-2.c @@ -10426,6 +10426,21 @@ aarch64_extract_operand (const aarch64_operand *self, case 27: case 35: case 36: + case 89: + case 90: + case 91: + case 92: + case 93: + case 94: + case 95: + case 96: + case 97: + case 98: + case 99: + case 100: + case 101: + case 102: + case 105: return aarch64_ext_regno (self, info, code, inst); case 8: return aarch64_ext_regrt_sysins (self, info, code, inst); @@ -10519,6 +10534,11 @@ 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: + return aarch64_ext_sve_index (self, info, code, inst); + case 104: + case 106: + return aarch64_ext_sve_reglist (self, info, code, inst); default: assert (0); abort (); } } diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c index 4c3b521d0de..ab93234e28a 100644 --- a/opcodes/aarch64-dis.c +++ b/opcodes/aarch64-dis.c @@ -1185,6 +1185,40 @@ aarch64_ext_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED, return 1; } + +/* Decode Zn[MM], where MM has a 7-bit triangular encoding. The fields + array specifies which field to use for Zn. MM is encoded in the + concatenation of imm5 and SVE_tszh, with imm5 being the less + significant part. */ +int +aarch64_ext_sve_index (const aarch64_operand *self, + aarch64_opnd_info *info, aarch64_insn code, + const aarch64_inst *inst ATTRIBUTE_UNUSED) +{ + int val; + + info->reglane.regno = extract_field (self->fields[0], code, 0); + val = extract_fields (code, 0, 2, FLD_SVE_tszh, FLD_imm5); + if ((val & 15) == 0) + return 0; + while ((val & 1) == 0) + val /= 2; + info->reglane.index = val / 2; + return 1; +} + +/* Decode {Zn. - Zm.}. The fields array specifies which field + to use for Zn. The opcode-dependent value specifies the number + of registers in the list. */ +int +aarch64_ext_sve_reglist (const aarch64_operand *self, + aarch64_opnd_info *info, aarch64_insn code, + const aarch64_inst *inst ATTRIBUTE_UNUSED) +{ + info->reglist.first_regno = extract_field (self->fields[0], code, 0); + info->reglist.num_regs = get_opcode_dependent_value (inst->opcode); + 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. diff --git a/opcodes/aarch64-dis.h b/opcodes/aarch64-dis.h index 1f101571b6f..5efb9044ba9 100644 --- a/opcodes/aarch64-dis.h +++ b/opcodes/aarch64-dis.h @@ -91,6 +91,8 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_hint); AARCH64_DECL_OPD_EXTRACTOR (ext_prfop); 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); #undef AARCH64_DECL_OPD_EXTRACTOR diff --git a/opcodes/aarch64-opc-2.c b/opcodes/aarch64-opc-2.c index b53bb5c3370..f8a7079c690 100644 --- a/opcodes/aarch64-opc-2.c +++ b/opcodes/aarch64-opc-2.c @@ -113,6 +113,24 @@ 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_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"}, + {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pg4_10", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pg4_10}, "an SVE predicate register"}, + {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pg4_16", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pg4_16}, "an SVE predicate register"}, + {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pm", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pm}, "an SVE predicate register"}, + {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pn", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pn}, "an SVE predicate register"}, + {AARCH64_OPND_CLASS_PRED_REG, "SVE_Pt", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pt}, "an SVE predicate register"}, + {AARCH64_OPND_CLASS_SVE_REG, "SVE_Za_5", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Za_5}, "an SVE vector register"}, + {AARCH64_OPND_CLASS_SVE_REG, "SVE_Za_16", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Za_16}, "an SVE vector register"}, + {AARCH64_OPND_CLASS_SVE_REG, "SVE_Zd", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zd}, "an SVE vector register"}, + {AARCH64_OPND_CLASS_SVE_REG, "SVE_Zm_5", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zm_5}, "an SVE vector register"}, + {AARCH64_OPND_CLASS_SVE_REG, "SVE_Zm_16", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zm_16}, "an SVE vector register"}, + {AARCH64_OPND_CLASS_SVE_REG, "SVE_Zn", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn}, "an SVE vector register"}, + {AARCH64_OPND_CLASS_SVE_REG, "SVE_Zn_INDEX", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn}, "an indexed SVE vector register"}, + {AARCH64_OPND_CLASS_SVE_REG, "SVE_ZnxN", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn}, "a list of SVE vector registers"}, + {AARCH64_OPND_CLASS_SVE_REG, "SVE_Zt", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zt}, "an SVE vector register"}, + {AARCH64_OPND_CLASS_SVE_REG, "SVE_ZtxN", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zt}, "a list of SVE vector registers"}, {AARCH64_OPND_CLASS_NIL, "", 0, {0}, "DUMMY"}, }; diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c index 30501fcc47e..56a01693dc9 100644 --- a/opcodes/aarch64-opc.c +++ b/opcodes/aarch64-opc.c @@ -199,6 +199,22 @@ const aarch64_field fields[] = { 31, 1 }, /* b5: in the test bit and branch instructions. */ { 19, 5 }, /* b40: in the test bit and branch instructions. */ { 10, 6 }, /* scale: in the fixed-point scalar to fp converting inst. */ + { 0, 4 }, /* SVE_Pd: p0-p15, bits [3,0]. */ + { 10, 3 }, /* SVE_Pg3: p0-p7, bits [12,10]. */ + { 5, 4 }, /* SVE_Pg4_5: p0-p15, bits [8,5]. */ + { 10, 4 }, /* SVE_Pg4_10: p0-p15, bits [13,10]. */ + { 16, 4 }, /* SVE_Pg4_16: p0-p15, bits [19,16]. */ + { 16, 4 }, /* SVE_Pm: p0-p15, bits [19,16]. */ + { 5, 4 }, /* SVE_Pn: p0-p15, bits [8,5]. */ + { 0, 4 }, /* SVE_Pt: p0-p15, bits [3,0]. */ + { 5, 5 }, /* SVE_Za_5: SVE vector register, bits [9,5]. */ + { 16, 5 }, /* SVE_Za_16: SVE vector register, bits [20,16]. */ + { 0, 5 }, /* SVE_Zd: SVE vector register. bits [4,0]. */ + { 5, 5 }, /* SVE_Zm_5: SVE vector register, bits [9,5]. */ + { 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]. */ + { 22, 2 }, /* SVE_tszh: triangular size select high, bits [23,22]. */ }; enum aarch64_operand_class @@ -1332,6 +1348,43 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx, } break; + case AARCH64_OPND_CLASS_SVE_REG: + switch (type) + { + case AARCH64_OPND_SVE_Zn_INDEX: + size = aarch64_get_qualifier_esize (opnd->qualifier); + if (!value_in_range_p (opnd->reglane.index, 0, 64 / size - 1)) + { + set_elem_idx_out_of_range_error (mismatch_detail, idx, + 0, 64 / size - 1); + return 0; + } + break; + + case AARCH64_OPND_SVE_ZnxN: + case AARCH64_OPND_SVE_ZtxN: + if (opnd->reglist.num_regs != get_opcode_dependent_value (opcode)) + { + set_other_error (mismatch_detail, idx, + _("invalid register list")); + return 0; + } + break; + + default: + break; + } + break; + + case AARCH64_OPND_CLASS_PRED_REG: + if (opnd->reg.regno >= 8 + && get_operand_fields_width (get_operand_from_code (type)) == 3) + { + set_other_error (mismatch_detail, idx, _("p0-p7 expected")); + return 0; + } + break; + case AARCH64_OPND_CLASS_COND: if (type == AARCH64_OPND_COND1 && (opnds[idx].cond->value & 0xe) == 0xe) @@ -2560,6 +2613,46 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc, print_register_list (buf, size, opnd, "v"); break; + case AARCH64_OPND_SVE_Pd: + case AARCH64_OPND_SVE_Pg3: + case AARCH64_OPND_SVE_Pg4_5: + case AARCH64_OPND_SVE_Pg4_10: + case AARCH64_OPND_SVE_Pg4_16: + case AARCH64_OPND_SVE_Pm: + case AARCH64_OPND_SVE_Pn: + case AARCH64_OPND_SVE_Pt: + if (opnd->qualifier == AARCH64_OPND_QLF_NIL) + snprintf (buf, size, "p%d", opnd->reg.regno); + else + snprintf (buf, size, "p%d.%s", opnd->reg.regno, + aarch64_get_qualifier_name (opnd->qualifier)); + break; + + case AARCH64_OPND_SVE_Za_5: + case AARCH64_OPND_SVE_Za_16: + case AARCH64_OPND_SVE_Zd: + case AARCH64_OPND_SVE_Zm_5: + case AARCH64_OPND_SVE_Zm_16: + case AARCH64_OPND_SVE_Zn: + case AARCH64_OPND_SVE_Zt: + if (opnd->qualifier == AARCH64_OPND_QLF_NIL) + snprintf (buf, size, "z%d", opnd->reg.regno); + else + snprintf (buf, size, "z%d.%s", opnd->reg.regno, + aarch64_get_qualifier_name (opnd->qualifier)); + break; + + case AARCH64_OPND_SVE_ZnxN: + case AARCH64_OPND_SVE_ZtxN: + print_register_list (buf, size, opnd, "z"); + break; + + case AARCH64_OPND_SVE_Zn_INDEX: + snprintf (buf, size, "z%d.%s[%" PRIi64 "]", opnd->reglane.regno, + aarch64_get_qualifier_name (opnd->qualifier), + opnd->reglane.index); + break; + case AARCH64_OPND_Cn: case AARCH64_OPND_Cm: snprintf (buf, size, "C%d", opnd->reg.regno); diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h index 08494c678a5..cc3dbefd631 100644 --- a/opcodes/aarch64-opc.h +++ b/opcodes/aarch64-opc.h @@ -91,6 +91,22 @@ enum aarch64_field_kind FLD_b5, FLD_b40, FLD_scale, + FLD_SVE_Pd, + FLD_SVE_Pg3, + FLD_SVE_Pg4_5, + FLD_SVE_Pg4_10, + FLD_SVE_Pg4_16, + FLD_SVE_Pm, + FLD_SVE_Pn, + FLD_SVE_Pt, + FLD_SVE_Za_5, + FLD_SVE_Za_16, + FLD_SVE_Zd, + FLD_SVE_Zm_5, + FLD_SVE_Zm_16, + FLD_SVE_Zn, + FLD_SVE_Zt, + FLD_SVE_tszh, }; /* Field description. */ diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h index 8f1c9b237d9..9dbe0c0ec5d 100644 --- a/opcodes/aarch64-tbl.h +++ b/opcodes/aarch64-tbl.h @@ -2819,4 +2819,40 @@ struct aarch64_opcode aarch64_opcode_table[] = Y(SYSTEM, prfop, "PRFOP", 0, F(), \ "a prefetch operation specifier") \ Y (SYSTEM, hint, "BARRIER_PSB", 0, F (), \ - "the PSB option name CSYNC") + "the PSB option name CSYNC") \ + 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), \ + "an SVE predicate register") \ + Y(PRED_REG, regno, "SVE_Pg4_5", 0, F(FLD_SVE_Pg4_5), \ + "an SVE predicate register") \ + Y(PRED_REG, regno, "SVE_Pg4_10", 0, F(FLD_SVE_Pg4_10), \ + "an SVE predicate register") \ + Y(PRED_REG, regno, "SVE_Pg4_16", 0, F(FLD_SVE_Pg4_16), \ + "an SVE predicate register") \ + Y(PRED_REG, regno, "SVE_Pm", 0, F(FLD_SVE_Pm), \ + "an SVE predicate register") \ + Y(PRED_REG, regno, "SVE_Pn", 0, F(FLD_SVE_Pn), \ + "an SVE predicate register") \ + Y(PRED_REG, regno, "SVE_Pt", 0, F(FLD_SVE_Pt), \ + "an SVE predicate register") \ + Y(SVE_REG, regno, "SVE_Za_5", 0, F(FLD_SVE_Za_5), \ + "an SVE vector register") \ + Y(SVE_REG, regno, "SVE_Za_16", 0, F(FLD_SVE_Za_16), \ + "an SVE vector register") \ + Y(SVE_REG, regno, "SVE_Zd", 0, F(FLD_SVE_Zd), \ + "an SVE vector register") \ + Y(SVE_REG, regno, "SVE_Zm_5", 0, F(FLD_SVE_Zm_5), \ + "an SVE vector register") \ + Y(SVE_REG, regno, "SVE_Zm_16", 0, F(FLD_SVE_Zm_16), \ + "an SVE vector register") \ + Y(SVE_REG, regno, "SVE_Zn", 0, F(FLD_SVE_Zn), \ + "an SVE vector register") \ + Y(SVE_REG, sve_index, "SVE_Zn_INDEX", 0, F(FLD_SVE_Zn), \ + "an indexed SVE vector register") \ + Y(SVE_REG, sve_reglist, "SVE_ZnxN", 0, F(FLD_SVE_Zn), \ + "a list of SVE vector registers") \ + Y(SVE_REG, regno, "SVE_Zt", 0, F(FLD_SVE_Zt), \ + "an SVE vector register") \ + Y(SVE_REG, sve_reglist, "SVE_ZtxN", 0, F(FLD_SVE_Zt), \ + "a list of SVE vector registers") -- 2.30.2