]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
x86: integrate mask_op into struct _i386_insn
authorJan Beulich <jbeulich@suse.com>
Tue, 30 Mar 2021 12:05:42 +0000 (14:05 +0200)
committerJan Beulich <jbeulich@suse.com>
Tue, 30 Mar 2021 12:05:42 +0000 (14:05 +0200)
There's no need for the extra level of indirection and the extra storage
needed for the pointer, pointing from one piece of static data to
another. Key checking of masking being in effect off of the register
field of the structure instead.

gas/ChangeLog
gas/config/tc-i386.c

index 49cbc6b433d4bb267b16c073af0f3c64736a38d9..94c7cc4271dddcb6c573ff1c6a4aa4bdeb2f959e 100644 (file)
@@ -1,3 +1,17 @@
+2021-03-30  Jan Beulich  <jbeulich@suse.com>
+
+       * config/tc-i386.c (reg_k0): New.
+       (mask_op): Delete.
+       (struct Mask_Operation): Move ...
+       (struct _i386_insn): ... here. Change field "mask".
+       (md_begin): Initialize reg_k0.
+       (build_evex_prefix): Adjust mask processing.
+       (swap_2_operands): Likewise.
+       (check_VecOperands): Likewise.
+       (check_VecOperations): Likewise.
+       (optimize_encoding): Adjust checks for masking.
+       (output_insn): Likewise.
+
 2021-03-30  Jan Beulich  <jbeulich@suse.com>
 
        * config/tc-i386.c (swap_2_operands): Switch parameters to
index 03bd7b6d3142baf3b0cee307d09845d14aad7717..d5baf95da95424f0a5bb5ebd8c6d0d63d770e327 100644 (file)
@@ -214,6 +214,8 @@ static const char *default_arch = DEFAULT_ARCH;
 static const reg_entry bad_reg = { "<bad>", OPERAND_TYPE_NONE, 0, 0,
                                   { Dw2Inval, Dw2Inval } };
 
+static const reg_entry *reg_k0;
+
 /* This struct describes rounding control and SAE in the instruction.  */
 struct RC_Operation
 {
@@ -230,19 +232,6 @@ struct RC_Operation
 
 static struct RC_Operation rc_op;
 
-/* The struct describes masking, applied to OPERAND in the instruction.
-   MASK is a pointer to the corresponding mask register.  ZEROING tells
-   whether merging or zeroing mask is used.  */
-struct Mask_Operation
-{
-  const reg_entry *mask;
-  unsigned int zeroing;
-  /* The operand where this operation is associated.  */
-  unsigned int operand;
-};
-
-static struct Mask_Operation mask_op;
-
 /* The struct describes broadcasting, applied to OPERAND.  FACTOR is
    broadcast factor.  */
 struct Broadcast_Operation
@@ -393,8 +382,18 @@ struct _i386_insn
     sib_byte sib;
     vex_prefix vex;
 
-    /* Masking attributes.  */
-    struct Mask_Operation *mask;
+    /* Masking attributes.
+
+       The struct describes masking, applied to OPERAND in the instruction.
+       REG is a pointer to the corresponding mask register.  ZEROING tells
+       whether merging or zeroing mask is used.  */
+    struct Mask_Operation
+    {
+      const reg_entry *reg;
+      unsigned int zeroing;
+      /* The operand where this operation is associated.  */
+      unsigned int operand;
+    } mask;
 
     /* Rounding control and SAE attributes.  */
     struct RC_Operation *rounding;
@@ -3093,8 +3092,13 @@ md_begin (void)
     unsigned int regtab_size = i386_regtab_size;
 
     for (regtab = i386_regtab; regtab_size--; regtab++)
-      if (str_hash_insert (reg_hash, regtab->reg_name, regtab, 0) != NULL)
-       as_fatal (_("duplicate %s"), regtab->reg_name);
+      {
+       if (str_hash_insert (reg_hash, regtab->reg_name, regtab, 0) != NULL)
+         as_fatal (_("duplicate %s"), regtab->reg_name);
+
+       if (regtab->reg_type.bitfield.class == RegMask && !regtab->reg_num)
+         reg_k0 = regtab;
+      }
   }
 
   /* Fill in lexical tables:  mnemonic_chars, operand_chars.  */
@@ -3871,7 +3875,7 @@ build_evex_prefix (void)
 
   /* The fourth byte of the EVEX prefix.  */
   /* The zeroing-masking bit.  */
-  if (i.mask && i.mask->zeroing)
+  if (i.mask.reg && i.mask.zeroing)
     i.vex.bytes[3] |= 0x80;
 
   /* Don't always set the broadcast bit if there is no RC.  */
@@ -3962,8 +3966,8 @@ build_evex_prefix (void)
        i.vex.bytes[3] |= 0x10 | (evexrcig << 5);
     }
 
-  if (i.mask && i.mask->mask)
-    i.vex.bytes[3] |= i.mask->mask->reg_num;
+  if (i.mask.reg)
+    i.vex.bytes[3] |= i.mask.reg->reg_num;
 }
 
 static void
@@ -4164,7 +4168,7 @@ optimize_encoding (void)
           && i.op[0].regs == i.op[1].regs
           && !i.types[2].bitfield.xmmword
           && (i.tm.opcode_modifier.vex
-              || ((!i.mask || i.mask->zeroing)
+              || ((!i.mask.reg || i.mask.zeroing)
                   && !i.rounding
                   && is_evex_encoding (&i.tm)
                   && (i.vec_encoding != vex_encoding_evex
@@ -4250,7 +4254,7 @@ optimize_encoding (void)
   else if (i.vec_encoding != vex_encoding_evex
           && !i.types[0].bitfield.zmmword
           && !i.types[1].bitfield.zmmword
-          && !i.mask
+          && !i.mask.reg
           && !i.broadcast
           && is_evex_encoding (&i.tm)
           && ((i.tm.base_opcode & ~Opcode_SIMD_IntD) == 0x6f
@@ -5461,12 +5465,12 @@ swap_2_operands (unsigned int xchg1, unsigned int xchg2)
   i.reloc[xchg2] = i.reloc[xchg1];
   i.reloc[xchg1] = temp_reloc;
 
-  if (i.mask)
+  if (i.mask.reg)
     {
-      if (i.mask->operand == xchg1)
-       i.mask->operand = xchg2;
-      else if (i.mask->operand == xchg2)
-       i.mask->operand = xchg1;
+      if (i.mask.operand == xchg1)
+       i.mask.operand = xchg2;
+      else if (i.mask.operand == xchg2)
+       i.mask.operand = xchg1;
     }
   if (i.broadcast)
     {
@@ -5802,7 +5806,7 @@ check_VecOperands (const insn_template *t)
 
   /* Check if default mask is allowed.  */
   if (t->opcode_modifier.nodefmask
-      && (!i.mask || i.mask->mask->reg_num == 0))
+      && (!i.mask.reg || i.mask.reg->reg_num == 0))
     {
       i.error = no_default_mask;
       return 1;
@@ -5824,8 +5828,8 @@ check_VecOperands (const insn_template *t)
        return 1;
       }
 
-      gas_assert (i.reg_operands == 2 || i.mask);
-      if (i.reg_operands == 2 && !i.mask)
+      gas_assert (i.reg_operands == 2 || i.mask.reg);
+      if (i.reg_operands == 2 && !i.mask.reg)
        {
          gas_assert (i.types[0].bitfield.class == RegSIMD);
          gas_assert (i.types[0].bitfield.xmmword
@@ -5849,7 +5853,7 @@ check_VecOperands (const insn_template *t)
            }
          as_warn (_("mask, index, and destination registers should be distinct"));
        }
-      else if (i.reg_operands == 1 && i.mask)
+      else if (i.reg_operands == 1 && i.mask.reg)
        {
          if (i.types[1].bitfield.class == RegSIMD
              && (i.types[1].bitfield.xmmword
@@ -5982,14 +5986,14 @@ check_VecOperands (const insn_template *t)
     op = MAX_OPERANDS - 1; /* Avoid uninitialized variable warning.  */
 
   /* Check if requested masking is supported.  */
-  if (i.mask)
+  if (i.mask.reg)
     {
       switch (t->opcode_modifier.masking)
        {
        case BOTH_MASKING:
          break;
        case MERGING_MASKING:
-         if (i.mask->zeroing)
+         if (i.mask.zeroing)
            {
        case 0:
              i.error = unsupported_masking;
@@ -5998,7 +6002,7 @@ check_VecOperands (const insn_template *t)
          break;
        case DYNAMIC_MASKING:
          /* Memory destinations allow only merging masking.  */
-         if (i.mask->zeroing && i.mem_operands)
+         if (i.mask.zeroing && i.mem_operands)
            {
              /* Find memory operand.  */
              for (op = 0; op < i.operands; op++)
@@ -6018,7 +6022,7 @@ check_VecOperands (const insn_template *t)
     }
 
   /* Check if masking is applied to dest operand.  */
-  if (i.mask && (i.mask->operand != i.operands - 1))
+  if (i.mask.reg && (i.mask.operand != i.operands - 1))
     {
       i.error = mask_not_on_destination;
       return 1;
@@ -9230,7 +9234,7 @@ output_insn (void)
        x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_YMM;
       if ((i.xstate & xstate_zmm) == xstate_zmm)
        x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_ZMM;
-      if (i.mask || (i.xstate & xstate_mask) == xstate_mask)
+      if (i.mask.reg || (i.xstate & xstate_mask) == xstate_mask)
        x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_MASK;
       if (i.tm.cpu_flags.bitfield.cpufxsr)
        x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_FXSR;
@@ -10431,23 +10435,20 @@ check_VecOperations (char *op_string, char *op_end)
                  return NULL;
                }
 
-             if (!i.mask)
+             if (!i.mask.reg)
                {
-                 mask_op.mask = mask;
-                 mask_op.zeroing = 0;
-                 mask_op.operand = this_operand;
-                 i.mask = &mask_op;
+                 i.mask.reg = mask;
+                 i.mask.operand = this_operand;
                }
+             else if (i.mask.reg->reg_num)
+               goto duplicated_vec_op;
              else
                {
-                 if (i.mask->mask)
-                   goto duplicated_vec_op;
-
-                 i.mask->mask = mask;
+                 i.mask.reg = mask;
 
                  /* Only "{z}" is allowed here.  No need to check
                     zeroing mask explicitly.  */
-                 if (i.mask->operand != (unsigned int) this_operand)
+                 if (i.mask.operand != (unsigned int) this_operand)
                    {
                      as_bad (_("invalid write mask `%s'"), saved);
                      return NULL;
@@ -10459,27 +10460,26 @@ check_VecOperations (char *op_string, char *op_end)
          /* Check zeroing-flag for masking operation.  */
          else if (*op_string == 'z')
            {
-             if (!i.mask)
+             if (!i.mask.reg)
                {
-                 mask_op.mask = NULL;
-                 mask_op.zeroing = 1;
-                 mask_op.operand = this_operand;
-                 i.mask = &mask_op;
+                 i.mask.reg = reg_k0;
+                 i.mask.zeroing = 1;
+                 i.mask.operand = this_operand;
                }
              else
                {
-                 if (i.mask->zeroing)
+                 if (i.mask.zeroing)
                    {
                    duplicated_vec_op:
                      as_bad (_("duplicated `%s'"), saved);
                      return NULL;
                    }
 
-                 i.mask->zeroing = 1;
+                 i.mask.zeroing = 1;
 
                  /* Only "{%k}" is allowed here.  No need to check mask
                     register explicitly.  */
-                 if (i.mask->operand != (unsigned int) this_operand)
+                 if (i.mask.operand != (unsigned int) this_operand)
                    {
                      as_bad (_("invalid zeroing-masking `%s'"),
                              saved);
@@ -10512,7 +10512,7 @@ check_VecOperations (char *op_string, char *op_end)
       return NULL;
     }
 
-  if (i.mask && i.mask->zeroing && !i.mask->mask)
+  if (i.mask.reg && i.mask.zeroing && !i.mask.reg->reg_num)
     {
       as_bad (_("zeroing-masking only allowed with write mask"));
       return NULL;