x86: drop "mem" operand type attribute
[deliverable/binutils-gdb.git] / gas / config / tc-i386.c
index c4ccffc75fa65348d02f66f7059c443c06efdfa0..e9e55f43a0d059fb077002e48a433886e03513e1 100644 (file)
@@ -230,6 +230,9 @@ struct Broadcast_Operation
 
   /* Index of broadcasted operand.  */
   int operand;
+
+  /* Number of bytes to broadcast.  */
+  int bytes;
 };
 
 static struct Broadcast_Operation broadcast_op;
@@ -269,7 +272,6 @@ enum i386_error
     invalid_vector_register_set,
     unsupported_vector_index_register,
     unsupported_broadcast,
-    broadcast_not_on_src_operand,
     broadcast_needed,
     unsupported_masking,
     mask_not_on_destination,
@@ -307,6 +309,7 @@ struct _i386_insn
     /* Flags for operands.  */
     unsigned int flags[MAX_OPERANDS];
 #define Operand_PCrel 1
+#define Operand_Mem   2
 
     /* Relocation type for operand */
     enum bfd_reloc_code_real reloc[MAX_OPERANDS];
@@ -2008,7 +2011,7 @@ operand_size_match (const insn_template *t)
          break;
        }
 
-      if (i.types[j].bitfield.mem && !match_mem_size (t, j, j))
+      if ((i.flags[j] & Operand_Mem) && !match_mem_size (t, j, j))
        {
          match = 0;
          break;
@@ -2033,8 +2036,7 @@ mismatch:
          && !match_operand_size (t, j, !j))
        goto mismatch;
 
-      if (i.types[!j].bitfield.mem
-         && !match_mem_size (t, j, !j))
+      if ((i.flags[!j] & Operand_Mem) && !match_mem_size (t, j, !j))
        goto mismatch;
     }
 
@@ -3365,8 +3367,10 @@ build_vex_prefix (const insn_template *t)
     {
       unsigned int op;
 
+      /* Determine vector length from the last multi-length vector
+        operand.  */
       vector_length = 0;
-      for (op = 0; op < t->operands; ++op)
+      for (op = t->operands; op--;)
        if (t->operand_types[op].bitfield.xmmword
            && t->operand_types[op].bitfield.ymmword
            && i.types[op].bitfield.ymmword)
@@ -3474,6 +3478,13 @@ is_evex_encoding (const insn_template *t)
         || t->opcode_modifier.staticrounding || t->opcode_modifier.sae;
 }
 
+static INLINE bfd_boolean
+is_any_vex_encoding (const insn_template *t)
+{
+  return t->opcode_modifier.vex || t->opcode_modifier.vexopcode
+        || is_evex_encoding (t);
+}
+
 /* Build the EVEX prefix.  */
 
 static void
@@ -3613,22 +3624,32 @@ build_evex_prefix (void)
        {
          unsigned int op;
 
+         /* Determine vector length from the last multi-length vector
+            operand.  */
          vec_length = 0;
-         for (op = 0; op < i.tm.operands; ++op)
+         for (op = i.operands; op--;)
            if (i.tm.operand_types[op].bitfield.xmmword
                + i.tm.operand_types[op].bitfield.ymmword
                + i.tm.operand_types[op].bitfield.zmmword > 1)
              {
                if (i.types[op].bitfield.zmmword)
-                 i.tm.opcode_modifier.evex = EVEX512;
+                 {
+                   i.tm.opcode_modifier.evex = EVEX512;
+                   break;
+                 }
                else if (i.types[op].bitfield.ymmword)
-                 i.tm.opcode_modifier.evex = EVEX256;
+                 {
+                   i.tm.opcode_modifier.evex = EVEX256;
+                   break;
+                 }
                else if (i.types[op].bitfield.xmmword)
-                 i.tm.opcode_modifier.evex = EVEX128;
+                 {
+                   i.tm.opcode_modifier.evex = EVEX128;
+                   break;
+                 }
                else if (i.broadcast && (int) op == i.broadcast->operand)
                  {
-                   switch ((i.tm.operand_types[op].bitfield.dword ? 4 : 8)
-                           * i.broadcast->type)
+                   switch (i.broadcast->bytes)
                      {
                        case 64:
                          i.tm.opcode_modifier.evex = EVEX512;
@@ -3640,12 +3661,14 @@ build_evex_prefix (void)
                          i.tm.opcode_modifier.evex = EVEX128;
                          break;
                        default:
-                         continue;
+                         abort ();
                      }
+                   break;
                  }
-                 continue;
-               break;
              }
+
+         if (op >= MAX_OPERANDS)
+           abort ();
        }
 
       switch (i.tm.opcode_modifier.evex)
@@ -3744,9 +3767,7 @@ bad_register_operand:
 
   gas_assert (i.imm_operands <= 1
              && (i.operands <= 2
-                 || ((i.tm.opcode_modifier.vex
-                      || i.tm.opcode_modifier.vexopcode
-                      || is_evex_encoding (&i.tm))
+                 || (is_any_vex_encoding (&i.tm)
                      && i.operands <= 4)));
 
   exp = &im_expressions[i.imm_operands++];
@@ -3921,7 +3942,11 @@ optimize_encoding (void)
                || i.tm.base_opcode == 0x66f8
                || i.tm.base_opcode == 0x66f9
                || i.tm.base_opcode == 0x66fa
-               || i.tm.base_opcode == 0x66fb)
+               || i.tm.base_opcode == 0x66fb
+               || i.tm.base_opcode == 0x42
+               || i.tm.base_opcode == 0x6642
+               || i.tm.base_opcode == 0x47
+               || i.tm.base_opcode == 0x6647)
               && i.tm.extension_opcode == None))
     {
       /* Optimize: -O2:
@@ -3952,6 +3977,12 @@ optimize_encoding (void)
             EVEX VOP %ymmM, %ymmM, %ymmN
               -> VEX vpxor %xmmM, %xmmM, %xmmN (M and N < 16)
               -> EVEX VOP %xmmM, %xmmM, %xmmN (M || N >= 16)
+          VOP, one of kxord and kxorq:
+            VEX VOP %kM, %kM, %kN
+              -> VEX kxorw %kM, %kM, %kN
+          VOP, one of kandnd and kandnq:
+            VEX VOP %kM, %kM, %kN
+              -> VEX kandnw %kM, %kM, %kN
        */
       if (is_evex_encoding (&i.tm))
        {
@@ -3964,6 +3995,11 @@ optimize_encoding (void)
              i.tm.opcode_modifier.evex = 0;
            }
        }
+      else if (i.tm.operand_types[0].bitfield.regmask)
+       {
+         i.tm.base_opcode &= 0xff;
+         i.tm.opcode_modifier.vexw = VEXW0;
+       }
       else
        i.tm.opcode_modifier.vex = VEX128;
 
@@ -4109,6 +4145,13 @@ md_assemble (char *line)
       return;
     }
 
+  /* Check for data size prefix on VEX/XOP/EVEX encoded insns.  */
+  if (i.prefix[DATA_PREFIX] && is_any_vex_encoding (&i.tm))
+    {
+      as_bad (_("data size prefix invalid with `%s'"), i.tm.name);
+      return;
+    }
+
   /* Check if HLE prefix is OK.  */
   if (i.hle_prefix && !check_hle ())
     return;
@@ -4195,8 +4238,7 @@ md_assemble (char *line)
       as_warn (_("translating to `%sp'"), i.tm.name);
     }
 
-  if (i.tm.opcode_modifier.vex || i.tm.opcode_modifier.vexopcode
-      || is_evex_encoding (&i.tm))
+  if (is_any_vex_encoding (&i.tm))
     {
       if (flag_code == CODE_16BIT)
        {
@@ -4659,6 +4701,13 @@ parse_operands (char *l, const char *mnemonic)
          /* Now parse operand adding info to 'i' as we go along.  */
          END_STRING_AND_SAVE (l);
 
+         if (i.mem_operands > 1)
+           {
+             as_bad (_("too many memory references for `%s'"),
+                     mnemonic);
+             return 0;
+           }
+
          if (intel_syntax)
            operand_ok =
              i386_intel_operand (token_start,
@@ -4704,14 +4753,21 @@ swap_2_operands (int xchg1, int xchg2)
 {
   union i386_op temp_op;
   i386_operand_type temp_type;
+  unsigned int temp_flags;
   enum bfd_reloc_code_real temp_reloc;
 
   temp_type = i.types[xchg2];
   i.types[xchg2] = i.types[xchg1];
   i.types[xchg1] = temp_type;
+
+  temp_flags = i.flags[xchg2];
+  i.flags[xchg2] = i.flags[xchg1];
+  i.flags[xchg1] = temp_flags;
+
   temp_op = i.op[xchg2];
   i.op[xchg2] = i.op[xchg1];
   i.op[xchg1] = temp_op;
+
   temp_reloc = i.reloc[xchg2];
   i.reloc[xchg2] = i.reloc[xchg1];
   i.reloc[xchg1] = temp_reloc;
@@ -4994,6 +5050,22 @@ optimize_disp (void)
       }
 }
 
+/* Return 1 if there is a match in broadcast bytes between operand
+   GIVEN and instruction template T.   */
+
+static INLINE int
+match_broadcast_size (const insn_template *t, unsigned int given)
+{
+  return ((t->opcode_modifier.broadcast == BYTE_BROADCAST
+          && i.types[given].bitfield.byte)
+         || (t->opcode_modifier.broadcast == WORD_BROADCAST
+             && i.types[given].bitfield.word)
+         || (t->opcode_modifier.broadcast == DWORD_BROADCAST
+             && i.types[given].bitfield.dword)
+         || (t->opcode_modifier.broadcast == QWORD_BROADCAST
+             && i.types[given].bitfield.qword));
+}
+
 /* Check if operands are valid for the instruction.  */
 
 static int
@@ -5112,23 +5184,29 @@ check_VecOperands (const insn_template *t)
       i386_operand_type type, overlap;
 
       /* Check if specified broadcast is supported in this instruction,
-        and it's applied to memory operand of DWORD or QWORD type.  */
+        and its broadcast bytes match the memory operand.  */
       op = i.broadcast->operand;
       if (!t->opcode_modifier.broadcast
-         || !i.types[op].bitfield.mem
+         || !(i.flags[op] & Operand_Mem)
          || (!i.types[op].bitfield.unspecified
-             && (t->operand_types[op].bitfield.dword
-                 ? !i.types[op].bitfield.dword
-                 : !i.types[op].bitfield.qword)))
+             && !match_broadcast_size (t, op)))
        {
        bad_broadcast:
          i.error = unsupported_broadcast;
          return 1;
        }
 
+      i.broadcast->bytes = ((1 << (t->opcode_modifier.broadcast - 1))
+                           * i.broadcast->type);
       operand_type_set (&type, 0);
-      switch ((t->operand_types[op].bitfield.dword ? 4 : 8) * i.broadcast->type)
+      switch (i.broadcast->bytes)
        {
+       case 2:
+         type.bitfield.word = 1;
+         break;
+       case 4:
+         type.bitfield.dword = 1;
+         break;
        case 8:
          type.bitfield.qword = 1;
          break;
@@ -5175,9 +5253,7 @@ check_VecOperands (const insn_template *t)
          break;
       gas_assert (op < i.operands);
       /* Check size of the memory operand.  */
-      if (t->operand_types[op].bitfield.dword
-         ? i.types[op].bitfield.dword
-         : i.types[op].bitfield.qword)
+      if (match_broadcast_size (t, op))
        {
          i.error = broadcast_needed;
          return 1;
@@ -5187,13 +5263,39 @@ check_VecOperands (const insn_template *t)
     op = MAX_OPERANDS - 1; /* Avoid uninitialized variable warning.  */
 
   /* Check if requested masking is supported.  */
-  if (i.mask
-      && (!t->opcode_modifier.masking
-         || (i.mask->zeroing
-             && t->opcode_modifier.masking == MERGING_MASKING)))
+  if (i.mask)
     {
-      i.error = unsupported_masking;
-      return 1;
+      switch (t->opcode_modifier.masking)
+       {
+       case BOTH_MASKING:
+         break;
+       case MERGING_MASKING:
+         if (i.mask->zeroing)
+           {
+       case 0:
+             i.error = unsupported_masking;
+             return 1;
+           }
+         break;
+       case DYNAMIC_MASKING:
+         /* Memory destinations allow only merging masking.  */
+         if (i.mask->zeroing && i.mem_operands)
+           {
+             /* Find memory operand.  */
+             for (op = 0; op < i.operands; op++)
+               if (i.flags[op] & Operand_Mem)
+                 break;
+             gas_assert (op < i.operands);
+             if (op == i.operands - 1)
+               {
+                 i.error = unsupported_masking;
+                 return 1;
+               }
+           }
+         break;
+       default:
+         abort ();
+       }
     }
 
   /* Check if masking is applied to dest operand.  */
@@ -5231,7 +5333,7 @@ check_VecOperands (const insn_template *t)
       && i.disp_encoding != disp_encoding_32bit)
     {
       if (i.broadcast)
-       i.memshift = t->operand_types[op].bitfield.dword ? 2 : 3;
+       i.memshift = t->opcode_modifier.broadcast - 1;
       else if (t->opcode_modifier.disp8memshift != DISP8_SHIFT_VL)
        i.memshift = t->opcode_modifier.disp8memshift;
       else
@@ -5242,14 +5344,17 @@ check_VecOperands (const insn_template *t)
          for (op = 0; op < i.operands; op++)
            if (operand_type_check (i.types[op], anymem))
              {
-               if (t->operand_types[op].bitfield.xmmword
-                   + t->operand_types[op].bitfield.ymmword
-                   + t->operand_types[op].bitfield.zmmword <= 1)
+               if (t->opcode_modifier.evex == EVEXLIG)
+                 i.memshift = 2 + (i.suffix == QWORD_MNEM_SUFFIX);
+               else if (t->operand_types[op].bitfield.xmmword
+                        + t->operand_types[op].bitfield.ymmword
+                        + t->operand_types[op].bitfield.zmmword <= 1)
                  type = &t->operand_types[op];
                else if (!i.types[op].bitfield.unspecified)
                  type = &i.types[op];
              }
-           else if (i.types[op].bitfield.regsimd)
+           else if (i.types[op].bitfield.regsimd
+                    && t->opcode_modifier.evex != EVEXLIG)
              {
                if (i.types[op].bitfield.zmmword)
                  i.memshift = 6;
@@ -5754,9 +5859,6 @@ check_reverse:
        case unsupported_broadcast:
          err_msg = _("unsupported broadcast");
          break;
-       case broadcast_not_on_src_operand:
-         err_msg = _("broadcast not on source memory operand");
-         break;
        case broadcast_needed:
          err_msg = _("broadcast is needed for operand of such type");
          break;
@@ -6094,6 +6196,9 @@ process_suffix (void)
       else if (i.suffix != QWORD_MNEM_SUFFIX
               && !i.tm.opcode_modifier.ignoresize
               && !i.tm.opcode_modifier.floatmf
+              && !i.tm.opcode_modifier.vex
+              && !i.tm.opcode_modifier.vexopcode
+              && !is_evex_encoding (&i.tm)
               && ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT)
                   || (flag_code == CODE_64BIT
                       && i.tm.opcode_modifier.jumpbyte)))
@@ -7922,7 +8027,8 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off)
              int size = disp_size (n);
              offsetT val = i.op[n].disps->X_add_number;
 
-             val = offset_in_range (val >> i.memshift, size);
+             val = offset_in_range (val >> (size == 1 ? i.memshift : 0),
+                                    size);
              p = frag_more (size);
              md_number_to_chars (p, val, size);
            }
@@ -8598,6 +8704,7 @@ check_VecOperations (char *op_string, char *op_end)
 
              broadcast_op.type = bcst_type;
              broadcast_op.operand = this_operand;
+             broadcast_op.bytes = 0;
              i.broadcast = &broadcast_op;
            }
          /* Check masking operation.  */
@@ -9714,7 +9821,7 @@ i386_att_operand (char *operand_string)
 
       if (i386_index_check (operand_string) == 0)
        return 0;
-      i.types[this_operand].bitfield.mem = 1;
+      i.flags[this_operand] |= Operand_Mem;
       if (i.mem_operands == 0)
        i.memop1_string = xstrdup (operand_string);
       i.mem_operands++;
@@ -10331,7 +10438,7 @@ parse_real_register (char *reg_string, char **end_op)
      mode, and require EVEX encoding.  */
   if (r->reg_flags & RegVRex)
     {
-      if (!cpu_arch_flags.bitfield.cpuvrex
+      if (!cpu_arch_flags.bitfield.cpuavx512f
          || flag_code != CODE_64BIT)
        return (const reg_entry *) NULL;
 
This page took 0.031551 seconds and 4 git commands to generate.