This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [AArch64][SVE 21/32] Add Zn and Pn registers


On 23/08/16 10:18, Richard Sandiford wrote:
> This patch adds the Zn and Pn registers, and associated fields and
> operands.
> 
> OK to install?
> 
> Thanks,
> Richard
> 
> 
> 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.
> 	(aarch64_check_reg_type): Likewise.  Update comment for
> 	REG_TYPE_R_Z_BHSDQ_V.
> 	(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.
> 

OK.

R.


> diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
> index 37f7d26..53e602f 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: any int                    (inc {W}SP inc [WX]ZR) */	\
> @@ -378,6 +381,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);
>      }
> @@ -678,12 +687,15 @@ aarch64_check_reg_type (const reg_entry *reg, aarch64_reg_type type)
>      {
>      case REG_TYPE_R64_SP:	/* 64-bit integer reg (inc SP exc XZR).  */
>      case REG_TYPE_R_Z_SP:	/* Integer reg (inc {X}SP inc [WX]ZR).  */
> -    case REG_TYPE_R_Z_BHSDQ_V:	/* Any register apart from Cn.  */
> +    case REG_TYPE_R_Z_BHSDQ_V:	/* Any register apart from Zn, Pn or Cn.  */
>      case REG_TYPE_BHSDQ:	/* Any [BHSDQ]P FP or SIMD scalar register.  */
>      case REG_TYPE_VN:		/* Vector register.  */
>        gas_assert (reg->type < REG_TYPE_MAX && type < REG_TYPE_MAX);
>        return ((reg_type_masks[reg->type] & reg_type_masks[type])
>  	      == reg_type_masks[reg->type]);
> +    case REG_TYPE_ZN:
> +    case REG_TYPE_PN:
> +      return reg->type == type;
>      default:
>        as_fatal ("unhandled type %d", type);
>        abort ();
> @@ -751,15 +763,16 @@ aarch64_reg_parse_32_64 (char **ccp, bfd_boolean accept_sp,
>    return reg->number;
>  }
>  
> -/* 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;
> @@ -769,7 +782,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;
> @@ -876,15 +889,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.
> @@ -1061,7 +1082,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;
> @@ -4687,7 +4708,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
> @@ -5027,6 +5048,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);
>  
> @@ -5109,22 +5131,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:
> @@ -5149,13 +5203,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))
> @@ -5168,20 +5228,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))
> @@ -5189,8 +5272,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;
> @@ -6185,11 +6277,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), \
> @@ -6229,10 +6323,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/opcode/aarch64.h b/include/opcode/aarch64.h
> index d39f10d..b0eb617 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/aarch64-asm-2.c b/opcodes/aarch64-asm-2.c
> index 439dd3d..9c797b2 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 f291495..c045f9e 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.<T> - Zm.<T>}.  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 3211aff..ede366c 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 a86a84d..6ea010b 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 4c3b521..ab93234 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.<T> - Zm.<T>}.  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 1f10157..5efb904 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 b53bb5c..f8a7079 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 30501fc..56a0169 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 08494c6..cc3dbef 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 8f1c9b2..9dbe0c0 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")
> 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]