x86/Intel: don't swap operands of MONITOR{,X} and MWAIT{,X}
[deliverable/binutils-gdb.git] / gas / config / tc-i386.c
index d7d45de76e0f7af5bb61fbde10292cdce29a4db3..4074a902c83c3bd81b66653f3dd12954b6972aa7 100644 (file)
@@ -983,6 +983,8 @@ static const arch_entry cpu_arch[] =
     CPU_SSE2_FLAGS, 0 },
   { STRING_COMMA_LEN (".sse3"), PROCESSOR_UNKNOWN,
     CPU_SSE3_FLAGS, 0 },
+  { STRING_COMMA_LEN (".sse4a"), PROCESSOR_UNKNOWN,
+    CPU_SSE4A_FLAGS, 0 },
   { STRING_COMMA_LEN (".ssse3"), PROCESSOR_UNKNOWN,
     CPU_SSSE3_FLAGS, 0 },
   { STRING_COMMA_LEN (".sse4.1"), PROCESSOR_UNKNOWN,
@@ -1177,10 +1179,11 @@ static const noarch_entry cpu_noarch[] =
   { STRING_COMMA_LEN ("nosse"),  CPU_ANY_SSE_FLAGS },
   { STRING_COMMA_LEN ("nosse2"),  CPU_ANY_SSE2_FLAGS },
   { STRING_COMMA_LEN ("nosse3"),  CPU_ANY_SSE3_FLAGS },
+  { STRING_COMMA_LEN ("nosse4a"),  CPU_ANY_SSE4A_FLAGS },
   { STRING_COMMA_LEN ("nossse3"),  CPU_ANY_SSSE3_FLAGS },
   { STRING_COMMA_LEN ("nosse4.1"),  CPU_ANY_SSE4_1_FLAGS },
   { STRING_COMMA_LEN ("nosse4.2"),  CPU_ANY_SSE4_2_FLAGS },
-  { STRING_COMMA_LEN ("nosse4"),  CPU_ANY_SSE4_FLAGS },
+  { STRING_COMMA_LEN ("nosse4"),  CPU_ANY_SSE4_1_FLAGS },
   { STRING_COMMA_LEN ("noavx"),  CPU_ANY_AVX_FLAGS },
   { STRING_COMMA_LEN ("noavx2"),  CPU_ANY_AVX2_FLAGS },
   { STRING_COMMA_LEN ("noavx512f"), CPU_ANY_AVX512F_FLAGS },
@@ -4321,14 +4324,16 @@ md_assemble (char *line)
   /* Now we've parsed the mnemonic into a set of templates, and have the
      operands at hand.  */
 
-  /* All intel opcodes have reversed operands except for "bound" and
-     "enter".  We also don't reverse intersegment "jmp" and "call"
-     instructions with 2 immediate operands so that the immediate segment
-     precedes the offset, as it does when in AT&T mode. */
+  /* All Intel opcodes have reversed operands except for "bound", "enter"
+     "monitor*", and "mwait*".  We also don't reverse intersegment "jmp"
+     and "call" instructions with 2 immediate operands so that the immediate
+     segment precedes the offset, as it does when in AT&T mode. */
   if (intel_syntax
       && i.operands > 1
       && (strcmp (mnemonic, "bound") != 0)
       && (strcmp (mnemonic, "invlpga") != 0)
+      && (strncmp (mnemonic, "monitor", 7) != 0)
+      && (strncmp (mnemonic, "mwait", 5) != 0)
       && !(operand_type_check (i.types[0], imm)
           && operand_type_check (i.types[1], imm)))
     swap_operands ();
@@ -4379,22 +4384,6 @@ md_assemble (char *line)
        : as_bad) (_("SSE instruction `%s' is used"), i.tm.name);
     }
 
-  /* Zap movzx and movsx suffix.  The suffix has been set from
-     "word ptr" or "byte ptr" on the source operand in Intel syntax
-     or extracted from mnemonic in AT&T syntax.  But we'll use
-     the destination register to choose the suffix for encoding.  */
-  if ((i.tm.base_opcode & ~9) == 0x0fb6)
-    {
-      /* In Intel syntax, there must be a suffix.  In AT&T syntax, if
-        there is no suffix, the default will be byte extension.  */
-      if (i.reg_operands != 2
-         && !i.suffix
-         && intel_syntax)
-       as_bad (_("ambiguous operand size for `%s'"), i.tm.name);
-
-      i.suffix = 0;
-    }
-
   if (i.tm.opcode_modifier.fwait)
     if (!add_prefix (FWAIT_OPCODE))
       return;
@@ -6311,6 +6300,15 @@ process_suffix (void)
   else if (i.reg_operands
           && (i.operands > 1 || i.types[0].bitfield.class == Reg))
     {
+      unsigned int numop = i.operands;
+
+      /* movsx/movzx want only their source operand considered here, for the
+        ambiguity checking below.  The suffix will be replaced afterwards
+        to represent the destination (register).  */
+      if (((i.tm.base_opcode | 8) == 0xfbe && i.tm.opcode_modifier.w)
+         || (i.tm.base_opcode == 0x63 && i.tm.cpu_flags.bitfield.cpu64))
+       --i.operands;
+
       /* If there's no instruction mnemonic suffix we try to invent one
         based on GPR operands.  */
       if (!i.suffix)
@@ -6339,6 +6337,12 @@ process_suffix (void)
                  continue;
                break;
              }
+
+         /* As an exception, movsx/movzx silently default to a byte source
+            in AT&T mode.  */
+         if ((i.tm.base_opcode | 8) == 0xfbe && i.tm.opcode_modifier.w
+             && !i.suffix && !intel_syntax)
+           i.suffix = BYTE_MNEM_SUFFIX;
        }
       else if (i.suffix == BYTE_MNEM_SUFFIX)
        {
@@ -6385,6 +6389,9 @@ process_suffix (void)
        ;
       else
        abort ();
+
+      /* Undo the movsx/movzx change done above.  */
+      i.operands = numop;
     }
   else if (i.tm.opcode_modifier.defaultsize && !i.suffix)
     {
@@ -6461,53 +6468,50 @@ process_suffix (void)
       /* For [XYZ]MMWORD operands inspect operand sizes.  While generally
         also suitable for AT&T syntax mode, it was requested that this be
         restricted to just Intel syntax.  */
-      if (intel_syntax)
+      if (intel_syntax && is_any_vex_encoding (&i.tm) && !i.broadcast)
        {
-         i386_cpu_flags cpu = cpu_flags_and (i.tm.cpu_flags, avx512);
+         unsigned int op;
 
-         if (!cpu_flags_all_zero (&cpu) && !i.broadcast)
+         for (op = 0; op < i.tm.operands; ++op)
            {
-             unsigned int op;
-
-             for (op = 0; op < i.tm.operands; ++op)
+             if (is_evex_encoding (&i.tm)
+                 && !cpu_arch_flags.bitfield.cpuavx512vl)
                {
-                 if (!cpu_arch_flags.bitfield.cpuavx512vl)
-                   {
-                     if (i.tm.operand_types[op].bitfield.ymmword)
-                       i.tm.operand_types[op].bitfield.xmmword = 0;
-                     if (i.tm.operand_types[op].bitfield.zmmword)
-                       i.tm.operand_types[op].bitfield.ymmword = 0;
-                     if (!i.tm.opcode_modifier.evex
-                         || i.tm.opcode_modifier.evex == EVEXDYN)
-                       i.tm.opcode_modifier.evex = EVEX512;
-                   }
+                 if (i.tm.operand_types[op].bitfield.ymmword)
+                   i.tm.operand_types[op].bitfield.xmmword = 0;
+                 if (i.tm.operand_types[op].bitfield.zmmword)
+                   i.tm.operand_types[op].bitfield.ymmword = 0;
+                 if (!i.tm.opcode_modifier.evex
+                     || i.tm.opcode_modifier.evex == EVEXDYN)
+                   i.tm.opcode_modifier.evex = EVEX512;
+               }
 
-                 if (i.tm.operand_types[op].bitfield.xmmword
-                     + i.tm.operand_types[op].bitfield.ymmword
-                     + i.tm.operand_types[op].bitfield.zmmword < 2)
-                   continue;
+             if (i.tm.operand_types[op].bitfield.xmmword
+                 + i.tm.operand_types[op].bitfield.ymmword
+                 + i.tm.operand_types[op].bitfield.zmmword < 2)
+               continue;
 
-                 /* Any properly sized operand disambiguates the insn.  */
-                 if (i.types[op].bitfield.xmmword
-                     || i.types[op].bitfield.ymmword
-                     || i.types[op].bitfield.zmmword)
-                   {
-                     suffixes &= ~(7 << 6);
-                     evex = 0;
-                     break;
-                   }
+             /* Any properly sized operand disambiguates the insn.  */
+             if (i.types[op].bitfield.xmmword
+                 || i.types[op].bitfield.ymmword
+                 || i.types[op].bitfield.zmmword)
+               {
+                 suffixes &= ~(7 << 6);
+                 evex = 0;
+                 break;
+               }
 
-                 if ((i.flags[op] & Operand_Mem)
-                     && i.tm.operand_types[op].bitfield.unspecified)
-                   {
-                     if (i.tm.operand_types[op].bitfield.xmmword)
-                       suffixes |= 1 << 6;
-                     if (i.tm.operand_types[op].bitfield.ymmword)
-                       suffixes |= 1 << 7;
-                     if (i.tm.operand_types[op].bitfield.zmmword)
-                       suffixes |= 1 << 8;
-                     evex = EVEX512;
-                   }
+             if ((i.flags[op] & Operand_Mem)
+                 && i.tm.operand_types[op].bitfield.unspecified)
+               {
+                 if (i.tm.operand_types[op].bitfield.xmmword)
+                   suffixes |= 1 << 6;
+                 if (i.tm.operand_types[op].bitfield.ymmword)
+                   suffixes |= 1 << 7;
+                 if (i.tm.operand_types[op].bitfield.zmmword)
+                   suffixes |= 1 << 8;
+                 if (is_evex_encoding (&i.tm))
+                   evex = EVEX512;
                }
            }
        }
@@ -6538,6 +6542,10 @@ process_suffix (void)
 
          if (i.tm.opcode_modifier.floatmf)
            i.suffix = SHORT_MNEM_SUFFIX;
+         else if ((i.tm.base_opcode | 8) == 0xfbe
+                  || (i.tm.base_opcode == 0x63
+                      && i.tm.cpu_flags.bitfield.cpu64))
+           /* handled below */;
          else if (evex)
            i.tm.opcode_modifier.evex = evex;
          else if (flag_code == CODE_16BIT)
@@ -6549,6 +6557,32 @@ process_suffix (void)
        }
     }
 
+  if ((i.tm.base_opcode | 8) == 0xfbe
+      || (i.tm.base_opcode == 0x63 && i.tm.cpu_flags.bitfield.cpu64))
+    {
+      /* In Intel syntax, movsx/movzx must have a "suffix" (checked above).
+        In AT&T syntax, if there is no suffix (warned about above), the default
+        will be byte extension.  */
+      if (i.tm.opcode_modifier.w && i.suffix && i.suffix != BYTE_MNEM_SUFFIX)
+       i.tm.base_opcode |= 1;
+
+      /* For further processing, the suffix should represent the destination
+        (register).  This is already the case when one was used with
+        mov[sz][bw]*, but we need to replace it for mov[sz]x, or if there was
+        no suffix to begin with.  */
+      if (i.tm.opcode_modifier.w || i.tm.base_opcode == 0x63 || !i.suffix)
+       {
+         if (i.types[1].bitfield.word)
+           i.suffix = WORD_MNEM_SUFFIX;
+         else if (i.types[1].bitfield.qword)
+           i.suffix = QWORD_MNEM_SUFFIX;
+         else
+           i.suffix = LONG_MNEM_SUFFIX;
+
+         i.tm.opcode_modifier.w = 0;
+       }
+    }
+
   if (!i.tm.opcode_modifier.modrm && i.reg_operands && i.tm.operands < 3)
     i.short_form = (i.tm.operand_types[0].bitfield.class == Reg)
                   != (i.tm.operand_types[1].bitfield.class == Reg);
@@ -6755,9 +6789,7 @@ check_long_reg (void)
             && i.tm.operand_types[op].bitfield.dword)
       {
        if (intel_syntax
-           && (i.tm.opcode_modifier.toqword
-               /* Also convert to QWORD for MOVSXD.  */
-               || i.tm.base_opcode == 0x63)
+           && i.tm.opcode_modifier.toqword
            && i.types[0].bitfield.class != RegSIMD)
          {
            /* Convert to QWORD.  We want REX byte. */
@@ -7178,11 +7210,13 @@ duplicate:
     }
 
   /* If a segment was explicitly specified, and the specified segment
-     is not the default, use an opcode prefix to select it.  If we
-     never figured out what the default segment is, then default_seg
-     will be zero at this point, and the specified segment prefix will
-     always be used.  */
-  if ((i.seg[0]) && (i.seg[0] != default_seg))
+     is neither the default nor the one already recorded from a prefix,
+     use an opcode prefix to select it.  If we never figured out what
+     the default segment is, then default_seg will be zero at this
+     point, and the specified segment prefix will always be used.  */
+  if (i.seg[0]
+      && i.seg[0] != default_seg
+      && i.seg[0]->seg_prefix != i.prefix[SEG_PREFIX])
     {
       if (!add_prefix (i.seg[0]->seg_prefix))
        return 0;
This page took 0.033511 seconds and 4 git commands to generate.