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 30/32] Add SVE instruction classes


On 23/08/16 10:25, Richard Sandiford wrote:
> The main purpose of the SVE aarch64_insn_classes is to describe how
> an index into an aarch64_opnd_qualifier_seq_t is represented in the
> instruction encoding.  Other instructions usually use flags for this
> information, but (a) we're running out of those and (b) the iclass
> would otherwise be unused for SVE.
> 
> OK to install?
> 
> Thanks,
> Richard
> 
> 
> include/opcode/
> 	* aarch64.h (sve_cpy, sve_index, sve_limm, sve_misc, sve_movprfx)
> 	(sve_pred_zm, sve_shift_pred, sve_shift_unpred, sve_size_bhs)
> 	(sve_size_bhsd, sve_size_hsd, sve_size_sd): New aarch64_insn_classes.
> 
> opcodes/
> 	* aarch64-opc.h (FLD_SVE_M_4, FLD_SVE_M_14, FLD_SVE_M_16)
> 	(FLD_SVE_sz, FLD_SVE_tsz, FLD_SVE_tszl_8, FLD_SVE_tszl_19): New
> 	aarch64_field_kinds.
> 	* aarch64-opc.c (fields): Add corresponding entries.
> 	* aarch64-asm.c (aarch64_get_variant): New function.
> 	(aarch64_encode_variant_using_iclass): Likewise.
> 	(aarch64_opcode_encode): Call it.
> 	* aarch64-dis.c (aarch64_decode_variant_using_iclass): New function.
> 	(aarch64_opcode_decode): Call it.
> 

OK

R.

> diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
> index 8d3fb21..01e6b2c 100644
> --- a/include/opcode/aarch64.h
> +++ b/include/opcode/aarch64.h
> @@ -485,6 +485,18 @@ enum aarch64_insn_class
>    movewide,
>    pcreladdr,
>    ic_system,
> +  sve_cpy,
> +  sve_index,
> +  sve_limm,
> +  sve_misc,
> +  sve_movprfx,
> +  sve_pred_zm,
> +  sve_shift_pred,
> +  sve_shift_unpred,
> +  sve_size_bhs,
> +  sve_size_bhsd,
> +  sve_size_hsd,
> +  sve_size_sd,
>    testbranch,
>  };
>  
> diff --git a/opcodes/aarch64-asm.c b/opcodes/aarch64-asm.c
> index fd356f4..78fd272 100644
> --- a/opcodes/aarch64-asm.c
> +++ b/opcodes/aarch64-asm.c
> @@ -1140,6 +1140,27 @@ encode_fcvt (aarch64_inst *inst)
>    return;
>  }
>  
> +/* Return the index in qualifiers_list that INST is using.  Should only
> +   be called once the qualifiers are known to be valid.  */
> +
> +static int
> +aarch64_get_variant (struct aarch64_inst *inst)
> +{
> +  int i, nops, variant;
> +
> +  nops = aarch64_num_of_operands (inst->opcode);
> +  for (variant = 0; variant < AARCH64_MAX_QLF_SEQ_NUM; ++variant)
> +    {
> +      for (i = 0; i < nops; ++i)
> +	if (inst->opcode->qualifiers_list[variant][i]
> +	    != inst->operands[i].qualifier)
> +	  break;
> +      if (i == nops)
> +	return variant;
> +    }
> +  abort ();
> +}
> +
>  /* Do miscellaneous encodings that are not common enough to be driven by
>     flags.  */
>  
> @@ -1318,6 +1339,65 @@ do_special_encoding (struct aarch64_inst *inst)
>    DEBUG_TRACE ("exit with coding 0x%x", (uint32_t) inst->value);
>  }
>  
> +/* Some instructions (including all SVE ones) use the instruction class
> +   to describe how a qualifiers_list index is represented in the instruction
> +   encoding.  If INST is such an instruction, encode the chosen qualifier
> +   variant.  */
> +
> +static void
> +aarch64_encode_variant_using_iclass (struct aarch64_inst *inst)
> +{
> +  switch (inst->opcode->iclass)
> +    {
> +    case sve_cpy:
> +      insert_fields (&inst->value, aarch64_get_variant (inst),
> +		     0, 2, FLD_SVE_M_14, FLD_size);
> +      break;
> +
> +    case sve_index:
> +    case sve_shift_pred:
> +    case sve_shift_unpred:
> +      /* For indices and shift amounts, the variant is encoded as
> +	 part of the immediate.  */
> +      break;
> +
> +    case sve_limm:
> +      /* For sve_limm, the .B, .H, and .S forms are just a convenience
> +	 and depend on the immediate.  They don't have a separate
> +	 encoding.  */
> +      break;
> +
> +    case sve_misc:
> +      /* sve_misc instructions have only a single variant.  */
> +      break;
> +
> +    case sve_movprfx:
> +      insert_fields (&inst->value, aarch64_get_variant (inst),
> +		     0, 2, FLD_SVE_M_16, FLD_size);
> +      break;
> +
> +    case sve_pred_zm:
> +      insert_field (FLD_SVE_M_4, &inst->value, aarch64_get_variant (inst), 0);
> +      break;
> +
> +    case sve_size_bhs:
> +    case sve_size_bhsd:
> +      insert_field (FLD_size, &inst->value, aarch64_get_variant (inst), 0);
> +      break;
> +
> +    case sve_size_hsd:
> +      insert_field (FLD_size, &inst->value, aarch64_get_variant (inst) + 1, 0);
> +      break;
> +
> +    case sve_size_sd:
> +      insert_field (FLD_SVE_sz, &inst->value, aarch64_get_variant (inst), 0);
> +      break;
> +
> +    default:
> +      break;
> +    }
> +}
> +
>  /* Converters converting an alias opcode instruction to its real form.  */
>  
>  /* ROR <Wd>, <Ws>, #<shift>
> @@ -1686,6 +1766,10 @@ aarch64_opcode_encode (const aarch64_opcode *opcode,
>    if (opcode_has_special_coder (opcode))
>      do_special_encoding (inst);
>  
> +  /* Possibly use the instruction class to encode the chosen qualifier
> +     variant.  */
> +  aarch64_encode_variant_using_iclass (inst);
> +
>  encoding_exit:
>    DEBUG_TRACE ("exit with %s", opcode->name);
>  
> diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
> index 385286c..f84f216 100644
> --- a/opcodes/aarch64-dis.c
> +++ b/opcodes/aarch64-dis.c
> @@ -2444,6 +2444,105 @@ determine_disassembling_preference (struct aarch64_inst *inst)
>      }
>  }
>  
> +/* Some instructions (including all SVE ones) use the instruction class
> +   to describe how a qualifiers_list index is represented in the instruction
> +   encoding.  If INST is such an instruction, decode the appropriate fields
> +   and fill in the operand qualifiers accordingly.  Return true if no
> +   problems are found.  */
> +
> +static bfd_boolean
> +aarch64_decode_variant_using_iclass (aarch64_inst *inst)
> +{
> +  int i, variant;
> +
> +  variant = 0;
> +  switch (inst->opcode->iclass)
> +    {
> +    case sve_cpy:
> +      variant = extract_fields (inst->value, 0, 2, FLD_size, FLD_SVE_M_14);
> +      break;
> +
> +    case sve_index:
> +      i = extract_field (FLD_SVE_tsz, inst->value, 0);
> +      if (i == 0)
> +	return FALSE;
> +      while ((i & 1) == 0)
> +	{
> +	  i >>= 1;
> +	  variant += 1;
> +	}
> +      break;
> +
> +    case sve_limm:
> +      /* Pick the smallest applicable element size.  */
> +      if ((inst->value & 0x20600) == 0x600)
> +	variant = 0;
> +      else if ((inst->value & 0x20400) == 0x400)
> +	variant = 1;
> +      else if ((inst->value & 0x20000) == 0)
> +	variant = 2;
> +      else
> +	variant = 3;
> +      break;
> +
> +    case sve_misc:
> +      /* sve_misc instructions have only a single variant.  */
> +      break;
> +
> +    case sve_movprfx:
> +      variant = extract_fields (inst->value, 0, 2, FLD_size, FLD_SVE_M_16);
> +      break;
> +
> +    case sve_pred_zm:
> +      variant = extract_field (FLD_SVE_M_4, inst->value, 0);
> +      break;
> +
> +    case sve_shift_pred:
> +      i = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_SVE_tszl_8);
> +    sve_shift:
> +      if (i == 0)
> +	return FALSE;
> +      while (i != 1)
> +	{
> +	  i >>= 1;
> +	  variant += 1;
> +	}
> +      break;
> +
> +    case sve_shift_unpred:
> +      i = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_SVE_tszl_19);
> +      goto sve_shift;
> +
> +    case sve_size_bhs:
> +      variant = extract_field (FLD_size, inst->value, 0);
> +      if (variant >= 3)
> +	return FALSE;
> +      break;
> +
> +    case sve_size_bhsd:
> +      variant = extract_field (FLD_size, inst->value, 0);
> +      break;
> +
> +    case sve_size_hsd:
> +      i = extract_field (FLD_size, inst->value, 0);
> +      if (i < 1)
> +	return FALSE;
> +      variant = i - 1;
> +      break;
> +
> +    case sve_size_sd:
> +      variant = extract_field (FLD_SVE_sz, inst->value, 0);
> +      break;
> +
> +    default:
> +      /* No mapping between instruction class and qualifiers.  */
> +      return TRUE;
> +    }
> +
> +  for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
> +    inst->operands[i].qualifier = inst->opcode->qualifiers_list[variant][i];
> +  return TRUE;
> +}
>  /* Decode the CODE according to OPCODE; fill INST.  Return 0 if the decoding
>     fails, which meanes that CODE is not an instruction of OPCODE; otherwise
>     return 1.
> @@ -2491,6 +2590,14 @@ aarch64_opcode_decode (const aarch64_opcode *opcode, const aarch64_insn code,
>        goto decode_fail;
>      }
>  
> +  /* Possibly use the instruction class to determine the correct
> +     qualifier.  */
> +  if (!aarch64_decode_variant_using_iclass (inst))
> +    {
> +      DEBUG_TRACE ("iclass-based decoder FAIL");
> +      goto decode_fail;
> +    }
> +
>    /* Call operand decoders.  */
>    for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
>      {
> diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
> index 1ad4ccf..2eb2a81 100644
> --- a/opcodes/aarch64-opc.c
> +++ b/opcodes/aarch64-opc.c
> @@ -264,6 +264,9 @@ 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.  */
> +    {  4,  1 }, /* SVE_M_4: Merge/zero select, bit 4.  */
> +    { 14,  1 }, /* SVE_M_14: Merge/zero select, bit 14.  */
> +    { 16,  1 }, /* SVE_M_16: Merge/zero select, bit 16.  */
>      { 17,  1 }, /* SVE_N: SVE equivalent of N.  */
>      {  0,  4 }, /* SVE_Pd: p0-p15, bits [3,0].  */
>      { 10,  3 }, /* SVE_Pg3: p0-p7, bits [12,10].  */
> @@ -299,7 +302,11 @@ const aarch64_field fields[] =
>      { 10,  2 }, /* SVE_msz: 2-bit shift amount for ADR.  */
>      {  5,  5 }, /* SVE_pattern: vector pattern enumeration.  */
>      {  0,  4 }, /* SVE_prfop: prefetch operation for SVE PRF[BHWD].  */
> +    { 22,  1 }, /* SVE_sz: 1-bit element size select.  */
> +    { 16,  4 }, /* SVE_tsz: triangular size select.  */
>      { 22,  2 }, /* SVE_tszh: triangular size select high, bits [23,22].  */
> +    {  8,  2 }, /* SVE_tszl_8: triangular size select low, bits [9,8].  */
> +    { 19,  2 }, /* SVE_tszl_19: triangular size select low, bits [20,19].  */
>      { 14,  1 }, /* SVE_xs_14: UXTW/SXTW select (bit 14).  */
>      { 22,  1 }  /* SVE_xs_22: UXTW/SXTW select (bit 22).  */
>  };
> diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h
> index a7654d0..0c3d90e 100644
> --- a/opcodes/aarch64-opc.h
> +++ b/opcodes/aarch64-opc.h
> @@ -91,6 +91,9 @@ enum aarch64_field_kind
>    FLD_b5,
>    FLD_b40,
>    FLD_scale,
> +  FLD_SVE_M_4,
> +  FLD_SVE_M_14,
> +  FLD_SVE_M_16,
>    FLD_SVE_N,
>    FLD_SVE_Pd,
>    FLD_SVE_Pg3,
> @@ -126,7 +129,11 @@ enum aarch64_field_kind
>    FLD_SVE_msz,
>    FLD_SVE_pattern,
>    FLD_SVE_prfop,
> +  FLD_SVE_sz,
> +  FLD_SVE_tsz,
>    FLD_SVE_tszh,
> +  FLD_SVE_tszl_8,
> +  FLD_SVE_tszl_19,
>    FLD_SVE_xs_14,
>    FLD_SVE_xs_22,
>  };
> 


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