x86: Add support for Intel AMX instructions

Jan Beulich jbeulich@suse.com
Thu Jul 9 09:06:19 GMT 2020


On 09.07.2020 07:29, Cui, Lili wrote:
> Here is the updated patch.

Actually, besides a comment about the new operand checking further
down, based on work that I've bee recently doing to shrink the
disassembler table sizes, one more remark:

> @@ -6901,6 +7016,78 @@ static const struct dis386 x86_64_table[][2] = {
>      { "lidt{Q|Q}", { M }, 0 },
>      { "lidt", { M }, 0 },
>    },
> +
> +  /* X86_64_VEX_0F3849_P_0_W_0_M_0_L_0 */
> +  {
> +    { Bad_Opcode },
> +    { "ldtilecfg", { M }, 0 },
> +  },
> +
> +  /* X86_64_VEX_0F3849_P_0_W_0_M_1_REG_0_RM_0_L_0 */
> +  {
> +    { Bad_Opcode },
> +    { "tilerelease", { Skip_MODRM }, 0 },
> +  },
> +
> +  /* X86_64_VEX_0F3849_P_2_W_0_M_0_L_0 */
> +  {
> +    { Bad_Opcode },
> +    { "sttilecfg", { M }, 0 },
> +  },
> +
> +  /* X86_64_VEX_0F3849_P_3_W_0_M_0_L_0 */
> +  {
> +    { Bad_Opcode },
> +    { "tilezero", { TMM, Skip_MODRM }, 0 },
> +  },
> +
> +  /* X86_64_VEX_0F384B_P_1_W_0_M_0_L_0 */
> +  {
> +    { Bad_Opcode },
> +    { "tilestored", { MVexSIBMEM, TMM }, 0 },
> +  },
> +
> +  /* X86_64_VEX_0F384B_P_2_W_0_M_0_L_0 */
> +  {
> +    { Bad_Opcode },
> +    { "tileloaddt1", { TMM, MVexSIBMEM }, 0 },
> +  },
> +
> +  /* X86_64_VEX_0F384B_P_3_W_0_M_0_L_0 */
> +  {
> +    { Bad_Opcode },
> +    { "tileloadd", { TMM, MVexSIBMEM }, 0 },
> +  },
> +
> +  /* X86_64_VEX_0F385C_P_1_W_0_M_0_L_0 */
> +  {
> +    { Bad_Opcode },
> +    { "tdpbf16ps", { TMM, EXtmm, VexTmm }, 0 },
> +  },
> +
> +  /* X86_64_VEX_0F385E_P_0_W_0_M_0_L_0 */
> +  {
> +    { Bad_Opcode },
> +    { "tdpbuud", { TMM, EXtmm, VexTmm }, 0 },
> +  },
> +
> +  /* X86_64_VEX_0F385E_P_1_W_0_M_0_L_0 */
> +  {
> +    { Bad_Opcode },
> +    { "tdpbsud", { TMM, EXtmm, VexTmm }, 0 },
> +  },
> +
> +  /* X86_64_VEX_0F385E_P_2_W_0_M_0_L_0 */
> +  {
> +    { Bad_Opcode },
> +    { "tdpbusd", { TMM, EXtmm, VexTmm }, 0 },
> +  },
> +
> +  /* X86_64_VEX_0F385E_P_3_W_0_M_0_L_0 */
> +  {
> +    { Bad_Opcode },
> +    { "tdpbssd", { TMM, EXtmm, VexTmm }, 0 },
> +  },
>  };

There are quite a few entries here. Going through x86_64_table[] as
the very first decode step would shrink the number of entries here
to just 4, without - afaict - affecting the number of other table
entries. Question of course is whether this is going to conflict
with perhaps already existing future uses of other encoding
variants of these major opcodes - I'm pretty sure you could check
internally, and I'd also assume that if for anything they'd be used
for further tile operations, and hence also all be 64-bit only.

> @@ -16290,6 +16684,41 @@ OP_VEX (int bytemode, int sizeflag ATTRIBUTE_UNUSED)
>    oappend (names[reg]);
>  }
>  
> +static void
> +OP_VEX_TMM_Fixup (int bytemode, int sizeflag)
> +{
> +  OP_VEX (bytemode, sizeflag);
> +
> +  if (amx_operands.tmm0!=-1
> +      && amx_operands.tmm1!=-1
> +      && amx_operands.tmm2!=-1)

Hmm, another ugly (sorry, I dislike most of them and hence try to
make progress to drop at least some) fixup routine, and another
global variable. It looks quite feasible to integrate this into
your addition to OP_VEX(), and I think you could get away without
any new global variable as well, at least as long as you don't
permit %tmm8 and up (recovering the low 3 bits from modrm's fields
is straightforward).

Also you would want blanks around != if this code was to stay.

> +  {
> +    /* All 3 TMM registers must be distinct.  */
> +    if (amx_operands.tmm1 == amx_operands.tmm0
> +	&& amx_operands.tmm2 == amx_operands.tmm0)
> +      {
> +	strcpy (op_out[0], "(bad)");
> +	strcpy (op_out[1], "(bad)");
> +	strcpy (op_out[2], "(bad)");
> +      }
> +    else if (amx_operands.tmm1 == amx_operands.tmm0)
> +      {
> +	strcpy (op_out[0], "(bad)");
> +	strcpy (op_out[1], "(bad)");
> +      }
> +    else if (amx_operands.tmm2 == amx_operands.tmm0)
> +      {
> +	strcpy (op_out[0], "(bad)");
> +	strcpy (op_out[2], "(bad)");
> +      }
> +    else if (amx_operands.tmm2 == amx_operands.tmm1)
> +      {
> +	strcpy (op_out[1], "(bad)");
> +	strcpy (op_out[2], "(bad)");
> +      }

I've meanwhile checked - unfortunately the gather insns don't have
correct operands checked, so there's nothing to compare against to
determine desirable behavior here. Generally I'd recommend against
replacing all (affected) operands by "(bad)". How about you zap only
the first (or last) violator? Or you append "(bad)" rather than
replacing the operands? H.J. - do you have any opinion here?

Jan


More information about the Binutils mailing list