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: [PATCH 3/4] x86: fold RegXMM/RegYMM/RegZMM into RegSIMD


On Fri, Dec 15, 2017 at 2:34 AM, Jan Beulich <JBeulich@suse.com> wrote:
> ... qualified by their respective sizes, allowing to drop FirstXmm0 at
> the same time.
>
> gas/
> 2017-12-15  Jan Beulich  <jbeulich@suse.com>
>
>         * config/tc-i386.c (match_simd_size): New.
>         (match_mem_size): Use it.
>         (operand_size_match): Likewise. Split .reg and .acc checks.
>         (pi, check_VecOperands, match_template, check_byte_reg,
>         check_long_reg, check_qword_reg, build_modrm_byte,
>         parse_real_register): Replace .regxmm, .regymm, and .regzmm
>         checks.
>         (md_assemble): Qualify .acc check with .xmmword one.
>         (bad_implicit_operand): Delete.
>         (process_operands): Replace .firstxmm0 checks with .acc plus
>         .xmmword ones. Drop now pointless assertions. Convert .acc to
>         .regsimd.
>         * config/tc-i386-intel.c (i386_intel_simplify_register): Replace
>         .regxmm, .regymm, and .regzmm checks.
>         * testsuite/gas/i386/x86-64-specific-reg.l: Adjust expectations.
>
> opcodes/
> 2017-12-15  Jan Beulich  <jbeulich@suse.com>
>
>         * i386-gen.c (operand_type_shorthands): Add RegXMM, RegYMM, and
>         RegZMM.
>         (opcode_modifiers): Drop FirstXmm0.
>         (operand_types): Replace RegXMM, RegYMM, and RegZMM with just
>         RegSIMD.
>         * i386-opc.h (enum of opcode modifiers): Drop FirstXmm0.
>         (struct i386_opcode_modifier): Drop firstxmm0.
>         (enum of operand types): Replace RegXMM, RegYMM, and RegZMM with
>         just RegSIMD. Extend comment.
>         (union i386_operand_type): Replace regxmm, regymm, and regzmm
>         with just regsimd.
>         * i386-opc.tbl (blendvpd, blendvps, pblendvb, sha256rnds2): Use
>         Acc|Xmmword.
>         * i386-reg.tbl (xmm0): Add Acc.
>         * i386-init.h, i386-tbl.h: Re-generate.
>
> --- a/gas/config/tc-i386-intel.c
> +++ b/gas/config/tc-i386-intel.c
> @@ -286,9 +286,9 @@ i386_intel_simplify_register (expression
>        i.op[this_operand].regs = i386_regtab + reg_num;
>      }
>    else if (!intel_state.index
> -          && (i386_regtab[reg_num].reg_type.bitfield.regxmm
> -              || i386_regtab[reg_num].reg_type.bitfield.regymm
> -              || i386_regtab[reg_num].reg_type.bitfield.regzmm
> +          && (i386_regtab[reg_num].reg_type.bitfield.xmmword
> +              || i386_regtab[reg_num].reg_type.bitfield.ymmword
> +              || i386_regtab[reg_num].reg_type.bitfield.zmmword
>                || i386_regtab[reg_num].reg_num == RegRiz
>                || i386_regtab[reg_num].reg_num == RegEiz))
>      intel_state.index = i386_regtab + reg_num;
> --- a/gas/config/tc-i386.c
> +++ b/gas/config/tc-i386.c
> @@ -1825,6 +1825,20 @@ match_reg_size (const insn_template *t,
>                && !t->operand_types[j].bitfield.tbyte));
>  }
>
> +/* Return 1 if there is no conflict in SIMD register on
> +   operand J for instruction template T.  */
> +
> +static INLINE int
> +match_simd_size (const insn_template *t, unsigned int j)
> +{
> +  return !((i.types[j].bitfield.xmmword
> +           && !t->operand_types[j].bitfield.xmmword)
> +          || (i.types[j].bitfield.ymmword
> +              && !t->operand_types[j].bitfield.ymmword)
> +          || (i.types[j].bitfield.zmmword
> +              && !t->operand_types[j].bitfield.zmmword));
> +}
> +
>  /* Return 1 if there is no conflict in any size on operand J for
>     instruction template T.  */
>
> @@ -1837,12 +1851,17 @@ match_mem_size (const insn_template *t,
>                 && !t->operand_types[j].bitfield.unspecified)
>                || (i.types[j].bitfield.fword
>                    && !t->operand_types[j].bitfield.fword)
> -              || (i.types[j].bitfield.xmmword
> -                  && !t->operand_types[j].bitfield.xmmword)
> -              || (i.types[j].bitfield.ymmword
> -                  && !t->operand_types[j].bitfield.ymmword)
> -              || (i.types[j].bitfield.zmmword
> -                  && !t->operand_types[j].bitfield.zmmword)));
> +              /* For scalar opcode templates to allow register and memory
> +                 operands at the same time, some special casing is needed
> +                 here.  */
> +              || ((t->operand_types[j].bitfield.regsimd
> +                   && !t->opcode_modifier.broadcast
> +                   && (t->operand_types[j].bitfield.dword
> +                       || t->operand_types[j].bitfield.qword))
> +                  ? (i.types[j].bitfield.xmmword
> +                     || i.types[j].bitfield.ymmword
> +                     || i.types[j].bitfield.zmmword)
> +                  : !match_simd_size(t, j))));
>  }
>
>  /* Return 1 if there is no size conflict on any operands for
> @@ -1864,17 +1883,31 @@ operand_size_match (const insn_template
>    /* Check memory and accumulator operand size.  */
>    for (j = 0; j < i.operands; j++)
>      {
> -      if (!i.types[j].bitfield.reg && t->operand_types[j].bitfield.anysize)
> +      if (!i.types[j].bitfield.reg && !i.types[j].bitfield.regsimd
> +         && t->operand_types[j].bitfield.anysize)
>         continue;
>
> -      if ((t->operand_types[j].bitfield.reg
> -          || t->operand_types[j].bitfield.acc)
> +      if (t->operand_types[j].bitfield.reg
>           && !match_reg_size (t, j))
>         {
>           match = 0;
>           break;
>         }
>
> +      if (t->operand_types[j].bitfield.regsimd
> +         && !match_simd_size (t, j))
> +       {
> +         match = 0;
> +         break;
> +       }
> +
> +      if (t->operand_types[j].bitfield.acc
> +         && (!match_reg_size (t, j) || !match_simd_size (t, j)))
> +       {
> +         match = 0;
> +         break;
> +       }
> +
>        if (i.types[j].bitfield.mem && !match_mem_size (t, j))
>         {
>           match = 0;
> @@ -2804,9 +2837,7 @@ pi (char *line, i386_insn *x)
>        fprintf (stdout, "\n");
>        if (x->types[j].bitfield.reg
>           || x->types[j].bitfield.regmmx
> -         || x->types[j].bitfield.regxmm
> -         || x->types[j].bitfield.regymm
> -         || x->types[j].bitfield.regzmm
> +         || x->types[j].bitfield.regsimd
>           || x->types[j].bitfield.sreg2
>           || x->types[j].bitfield.sreg3
>           || x->types[j].bitfield.control
> @@ -3768,7 +3799,7 @@ md_assemble (char *line)
>      for (j = 0; j < i.operands; j++)
>        if (i.types[j].bitfield.inoutportreg
>           || i.types[j].bitfield.shiftcount
> -         || i.types[j].bitfield.acc)
> +         || (i.types[j].bitfield.acc && !i.types[j].bitfield.xmmword))
>         i.reg_operands--;
>
>    /* ImmExt should be processed after SSE2AVX.  */
> @@ -4576,9 +4607,9 @@ check_VecOperands (const insn_template *
>    /* Without VSIB byte, we can't have a vector register for index.  */
>    if (!t->opcode_modifier.vecsib
>        && i.index_reg
> -      && (i.index_reg->reg_type.bitfield.regxmm
> -         || i.index_reg->reg_type.bitfield.regymm
> -         || i.index_reg->reg_type.bitfield.regzmm))
> +      && (i.index_reg->reg_type.bitfield.xmmword
> +         || i.index_reg->reg_type.bitfield.ymmword
> +         || i.index_reg->reg_type.bitfield.zmmword))
>      {
>        i.error = unsupported_vector_index_register;
>        return 1;
> @@ -4598,11 +4629,11 @@ check_VecOperands (const insn_template *
>      {
>        if (!i.index_reg
>           || !((t->opcode_modifier.vecsib == VecSIB128
> -               && i.index_reg->reg_type.bitfield.regxmm)
> +               && i.index_reg->reg_type.bitfield.xmmword)
>                || (t->opcode_modifier.vecsib == VecSIB256
> -                  && i.index_reg->reg_type.bitfield.regymm)
> +                  && i.index_reg->reg_type.bitfield.ymmword)
>                || (t->opcode_modifier.vecsib == VecSIB512
> -                  && i.index_reg->reg_type.bitfield.regzmm)))
> +                  && i.index_reg->reg_type.bitfield.zmmword)))
>        {
>         i.error = invalid_vsib_address;
>         return 1;
> @@ -4611,10 +4642,12 @@ check_VecOperands (const insn_template *
>        gas_assert (i.reg_operands == 2 || i.mask);
>        if (i.reg_operands == 2 && !i.mask)
>         {
> -         gas_assert (i.types[0].bitfield.regxmm
> -                     || i.types[0].bitfield.regymm);
> -         gas_assert (i.types[2].bitfield.regxmm
> -                     || i.types[2].bitfield.regymm);
> +         gas_assert (i.types[0].bitfield.regsimd);
> +         gas_assert (i.types[0].bitfield.xmmword
> +                     || i.types[0].bitfield.ymmword);
> +         gas_assert (i.types[2].bitfield.regsimd);
> +         gas_assert (i.types[2].bitfield.xmmword
> +                     || i.types[2].bitfield.ymmword);
>           if (operand_check == check_none)
>             return 0;
>           if (register_number (i.op[0].regs)
> @@ -4633,9 +4666,10 @@ check_VecOperands (const insn_template *
>         }
>        else if (i.reg_operands == 1 && i.mask)
>         {
> -         if ((i.types[1].bitfield.regxmm
> -              || i.types[1].bitfield.regymm
> -              || i.types[1].bitfield.regzmm)
> +         if (i.types[1].bitfield.regsimd
> +             && (i.types[1].bitfield.xmmword
> +                 || i.types[1].bitfield.ymmword
> +                 || i.types[1].bitfield.zmmword)
>               && (register_number (i.op[1].regs)
>                   == register_number (i.index_reg)))
>             {
> @@ -4941,13 +4975,9 @@ match_template (char mnem_suffix)
>                  && !intel_float_operand (t->name))
>               : intel_float_operand (t->name) != 2)
>           && ((!operand_types[0].bitfield.regmmx
> -              && !operand_types[0].bitfield.regxmm
> -              && !operand_types[0].bitfield.regymm
> -              && !operand_types[0].bitfield.regzmm)
> +              && !operand_types[0].bitfield.regsimd)
>               || (!operand_types[t->operands > 1].bitfield.regmmx
> -                 && !operand_types[t->operands > 1].bitfield.regxmm
> -                 && !operand_types[t->operands > 1].bitfield.regymm
> -                 && !operand_types[t->operands > 1].bitfield.regzmm))
> +                 && !operand_types[t->operands > 1].bitfield.regsimd))
>           && (t->base_opcode != 0x0fc7
>               || t->extension_opcode != 1 /* cmpxchg8b */))
>         continue;
> @@ -4960,9 +4990,9 @@ match_template (char mnem_suffix)
>                       && !intel_float_operand (t->name))
>                    : intel_float_operand (t->name) != 2)
>                && ((!operand_types[0].bitfield.regmmx
> -                   && !operand_types[0].bitfield.regxmm)
> +                   && !operand_types[0].bitfield.regsimd)
>                    || (!operand_types[t->operands > 1].bitfield.regmmx
> -                      && !operand_types[t->operands > 1].bitfield.regxmm)))
> +                      && !operand_types[t->operands > 1].bitfield.regsimd)))
>         continue;
>
>        /* Do not verify operands when there are none.  */
> @@ -5653,9 +5683,7 @@ check_byte_reg (void)
>        /* Any other register is bad.  */
>        if (i.types[op].bitfield.reg
>           || i.types[op].bitfield.regmmx
> -         || i.types[op].bitfield.regxmm
> -         || i.types[op].bitfield.regymm
> -         || i.types[op].bitfield.regzmm
> +         || i.types[op].bitfield.regsimd
>           || i.types[op].bitfield.sreg2
>           || i.types[op].bitfield.sreg3
>           || i.types[op].bitfield.control
> @@ -5728,7 +5756,7 @@ check_long_reg (void)
>        {
>         if (intel_syntax
>             && i.tm.opcode_modifier.toqword
> -           && !i.types[0].bitfield.regxmm)
> +           && !i.types[0].bitfield.regsimd)
>           {
>             /* Convert to QWORD.  We want REX byte. */
>             i.suffix = QWORD_MNEM_SUFFIX;
> @@ -5779,7 +5807,7 @@ check_qword_reg (void)
>            lowering is more complicated.  */
>         if (intel_syntax
>             && i.tm.opcode_modifier.todword
> -           && !i.types[0].bitfield.regxmm)
> +           && !i.types[0].bitfield.regsimd)
>           {
>             /* Convert to DWORD.  We don't want REX byte. */
>             i.suffix = LONG_MNEM_SUFFIX;
> @@ -5930,20 +5958,6 @@ finalize_imm (void)
>  }
>
>  static int
> -bad_implicit_operand (int xmm)
> -{
> -  const char *ireg = xmm ? "xmm0" : "ymm0";
> -
> -  if (intel_syntax)
> -    as_bad (_("the last operand of `%s' must be `%s%s'"),
> -           i.tm.name, register_prefix, ireg);
> -  else
> -    as_bad (_("the first operand of `%s' must be `%s%s'"),
> -           i.tm.name, register_prefix, ireg);
> -  return 0;
> -}
> -

Will we miss the assembly operand error checking?

-- 
H.J.


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