x86: limit ImmExt abuse
[deliverable/binutils-gdb.git] / gas / config / tc-i386.c
index fe50566d86b2b2fe45c56da3fce616ff0b150994..1741c0e2de36bf7ba38eb5f5a9e6dbfddfe8d691 100644 (file)
@@ -98,6 +98,9 @@
 
 #define END_OF_INSN '\0'
 
+/* This matches the C -> StaticRounding alias in the opcode table.  */
+#define commutative staticrounding
+
 /*
   'templates' is for grouping together 'template' structures for opcodes
   of the same name.  This is only used for storing the insns in the grand
@@ -3438,6 +3441,43 @@ build_vex_prefix (const insn_template *t)
        i.tm = t[1];
     }
 
+  /* Use 2-byte VEX prefix by swapping commutative source operands if there
+     are no memory operands and at least 3 register ones.  */
+  if (i.reg_operands >= 3
+      && i.vec_encoding != vex_encoding_vex3
+      && i.reg_operands == i.operands - i.imm_operands
+      && i.tm.opcode_modifier.vex
+      && i.tm.opcode_modifier.commutative
+      && (i.tm.opcode_modifier.sse2avx || optimize > 1)
+      && i.rex == REX_B
+      && i.vex.register_specifier
+      && !(i.vex.register_specifier->reg_flags & RegRex))
+    {
+      unsigned int xchg = i.operands - i.reg_operands;
+      union i386_op temp_op;
+      i386_operand_type temp_type;
+
+      gas_assert (i.tm.opcode_modifier.vexopcode == VEX0F);
+      gas_assert (!i.tm.opcode_modifier.sae);
+      gas_assert (operand_type_equal (&i.types[i.operands - 2],
+                                      &i.types[i.operands - 3]));
+      gas_assert (i.rm.mode == 3);
+
+      temp_type = i.types[xchg];
+      i.types[xchg] = i.types[xchg + 1];
+      i.types[xchg + 1] = temp_type;
+      temp_op = i.op[xchg];
+      i.op[xchg] = i.op[xchg + 1];
+      i.op[xchg + 1] = temp_op;
+
+      i.rex = 0;
+      xchg = i.rm.regmem | 8;
+      i.rm.regmem = ~register_specifier & 0xf;
+      gas_assert (!(i.rm.regmem & 8));
+      i.vex.register_specifier += xchg - i.rm.regmem;
+      register_specifier = ~xchg & 0xf;
+    }
+
   if (i.tm.opcode_modifier.vex == VEXScalar)
     vector_length = avxscalar;
   else if (i.tm.opcode_modifier.vex == VEX256)
@@ -4000,6 +4040,29 @@ optimize_encoding (void)
            }
        }
     }
+  else if (optimize > 1
+          && !optimize_for_space
+          && i.reg_operands == 2
+          && i.op[0].regs == i.op[1].regs
+          && ((i.tm.base_opcode & ~(Opcode_D | 1)) == 0x8
+              || (i.tm.base_opcode & ~(Opcode_D | 1)) == 0x20)
+          && (flag_code != CODE_64BIT || !i.types[0].bitfield.dword))
+    {
+      /* Optimize: -O2:
+          andb %rN, %rN  -> testb %rN, %rN
+          andw %rN, %rN  -> testw %rN, %rN
+          andq %rN, %rN  -> testq %rN, %rN
+          orb %rN, %rN   -> testb %rN, %rN
+          orw %rN, %rN   -> testw %rN, %rN
+          orq %rN, %rN   -> testq %rN, %rN
+
+          and outside of 64-bit mode
+
+          andl %rN, %rN  -> testl %rN, %rN
+          orl %rN, %rN   -> testl %rN, %rN
+       */
+      i.tm.base_opcode = 0x84 | (i.tm.base_opcode & 1);
+    }
   else if (i.reg_operands == 3
           && i.op[0].regs == i.op[1].regs
           && !i.types[2].bitfield.xmmword
@@ -4157,6 +4220,9 @@ optimize_encoding (void)
       i.tm.opcode_modifier.vex
        = i.types[0].bitfield.ymmword ? VEX256 : VEX128;
       i.tm.opcode_modifier.vexw = VEXW0;
+      /* VPAND, VPOR, and VPXOR are commutative.  */
+      if (i.reg_operands == 3 && i.tm.base_opcode != 0x66df)
+       i.tm.opcode_modifier.commutative = 1;
       i.tm.opcode_modifier.evex = 0;
       i.tm.opcode_modifier.masking = 0;
       i.tm.opcode_modifier.broadcast = 0;
@@ -8217,7 +8283,7 @@ output_insn (void)
         Xfence instructions.  */
       if (i.tm.base_opcode != 0xf18
          && i.tm.base_opcode != 0xf0d
-         && i.tm.base_opcode != 0xfae
+         && i.tm.base_opcode != 0xfaef8
          && (i.has_regmmx
              || i.tm.cpu_flags.bitfield.cpummx
              || i.tm.cpu_flags.bitfield.cpua3dnow
@@ -8265,12 +8331,9 @@ output_insn (void)
       unsigned int prefix;
 
       if (avoid_fence
-         && i.tm.base_opcode == 0xfae
-         && i.operands == 1
-         && i.imm_operands == 1
-         && (i.op[0].imms->X_add_number == 0xe8
-             || i.op[0].imms->X_add_number == 0xf0
-             || i.op[0].imms->X_add_number == 0xf8))
+         && (i.tm.base_opcode == 0xfaee8
+             || i.tm.base_opcode == 0xfaef0
+             || i.tm.base_opcode == 0xfaef8))
         {
           /* Encode lfence, mfence, and sfence as
              f0 83 04 24 00   lock addl $0x0, (%{re}sp).  */
@@ -8299,17 +8362,17 @@ output_insn (void)
              if (i.tm.base_opcode & 0xff000000)
                {
                  prefix = (i.tm.base_opcode >> 24) & 0xff;
-                 add_prefix (prefix);
+                 if (!i.tm.cpu_flags.bitfield.cpupadlock
+                     || prefix != REPE_PREFIX_OPCODE
+                     || (i.prefix[REP_PREFIX] != REPE_PREFIX_OPCODE))
+                   add_prefix (prefix);
                }
              break;
            case 2:
              if ((i.tm.base_opcode & 0xff0000) != 0)
                {
                  prefix = (i.tm.base_opcode >> 16) & 0xff;
-                 if (!i.tm.cpu_flags.bitfield.cpupadlock
-                     || prefix != REPE_PREFIX_OPCODE
-                     || (i.prefix[REP_PREFIX] != REPE_PREFIX_OPCODE))
-                   add_prefix (prefix);
+                 add_prefix (prefix);
                }
              break;
            case 1:
@@ -9722,7 +9785,7 @@ i386_index_check (const char *operand_string)
   enum flag_code addr_mode = i386_addressing_mode ();
 
   if (current_templates->start->opcode_modifier.isstring
-      && !current_templates->start->opcode_modifier.immext
+      && !current_templates->start->cpu_flags.bitfield.cpupadlock
       && (current_templates->end[-1].opcode_modifier.isstring
          || i.mem_operands))
     {
This page took 0.026516 seconds and 4 git commands to generate.