x86-64: Intel64 adjustments for insns dealing with far pointers
[deliverable/binutils-gdb.git] / gas / config / tc-i386.c
index 543fe25b4d4939d78028da7041361d0e7c453657..ac141b84d0b6ee914ab5ed67bdf094da367efeac 100644 (file)
 #endif
 #endif
 
-#ifndef REGISTER_WARNINGS
-#define REGISTER_WARNINGS 1
-#endif
-
 #ifndef INFER_ADDR_PREFIX
 #define INFER_ADDR_PREFIX 1
 #endif
@@ -354,6 +350,9 @@ struct _i386_insn
     unsigned int prefixes;
     unsigned char prefix[MAX_PREFIXES];
 
+    /* Register is in low 3 bits of opcode.  */
+    bfd_boolean short_form;
+
     /* The operand to a branch insn indicates an absolute branch.  */
     bfd_boolean jumpabsolute;
 
@@ -2245,8 +2244,7 @@ mismatch:
 
 /* If given types g0 and g1 are registers they must be of the same type
    unless the expected operand type register overlap is null.
-   Memory operand size of certain SIMD instructions is also being checked
-   here.  */
+   Some Intel syntax memory operand size checking also happens here.  */
 
 static INLINE int
 operand_type_register_match (i386_operand_type g0,
@@ -2258,14 +2256,16 @@ operand_type_register_match (i386_operand_type g0,
       && g0.bitfield.class != RegSIMD
       && (!operand_type_check (g0, anymem)
          || g0.bitfield.unspecified
-         || t0.bitfield.class != RegSIMD))
+         || (t0.bitfield.class != Reg
+             && t0.bitfield.class != RegSIMD)))
     return 1;
 
   if (g1.bitfield.class != Reg
       && g1.bitfield.class != RegSIMD
       && (!operand_type_check (g1, anymem)
          || g1.bitfield.unspecified
-         || t1.bitfield.class != RegSIMD))
+         || (t1.bitfield.class != Reg
+             && t1.bitfield.class != RegSIMD)))
     return 1;
 
   if (g0.bitfield.byte == g1.bitfield.byte
@@ -4084,7 +4084,6 @@ optimize_encoding (void)
              i.tm.base_opcode = 0xb8;
              i.tm.extension_opcode = None;
              i.tm.opcode_modifier.w = 0;
-             i.tm.opcode_modifier.shortform = 1;
              i.tm.opcode_modifier.modrm = 0;
            }
        }
@@ -5828,7 +5827,7 @@ match_template (char mnem_suffix)
          break;
        case intel64:
          /* -mintel64: Don't accept AMD64.  */
-         if (t->opcode_modifier.isa64 == AMD64)
+         if (t->opcode_modifier.isa64 == AMD64 && flag_code == CODE_64BIT)
            continue;
          break;
        }
@@ -6495,6 +6494,10 @@ process_suffix (void)
        }
     }
 
+  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);
+
   /* Change the opcode based on the operand size given by i.suffix.  */
   switch (i.suffix)
     {
@@ -6511,7 +6514,7 @@ process_suffix (void)
       /* It's not a byte, select word/dword operation.  */
       if (i.tm.opcode_modifier.w)
        {
-         if (i.tm.opcode_modifier.shortform)
+         if (i.short_form)
            i.tm.base_opcode |= 8;
          else
            i.tm.base_opcode |= 1;
@@ -6631,31 +6634,10 @@ check_byte_reg (void)
          && i.tm.operand_types[op].bitfield.word)
        continue;
 
-      /* crc32 doesn't generate this warning.  */
-      if (i.tm.base_opcode == 0xf20f38f0)
+      /* crc32 only wants its source operand checked here.  */
+      if (i.tm.base_opcode == 0xf20f38f0 && op)
        continue;
 
-      if ((i.types[op].bitfield.word
-          || i.types[op].bitfield.dword
-          || i.types[op].bitfield.qword)
-         && i.op[op].regs->reg_num < 4
-         /* Prohibit these changes in 64bit mode, since the lowering
-            would be more complicated.  */
-         && flag_code != CODE_64BIT)
-       {
-#if REGISTER_WARNINGS
-         if (!quiet_warnings)
-           as_warn (_("using `%s%s' instead of `%s%s' due to `%c' suffix"),
-                    register_prefix,
-                    (i.op[op].regs + (i.types[op].bitfield.word
-                                      ? REGNAM_AL - REGNAM_AX
-                                      : REGNAM_AL - REGNAM_EAX))->reg_name,
-                    register_prefix,
-                    i.op[op].regs->reg_name,
-                    i.suffix);
-#endif
-         continue;
-       }
       /* Any other register is bad.  */
       if (i.types[op].bitfield.class == Reg
          || i.types[op].bitfield.class == RegMMX
@@ -6811,29 +6793,17 @@ check_word_reg (void)
                i.suffix);
        return 0;
       }
-    /* Warn if the e or r prefix on a general reg is present.  */
-    else if ((!quiet_warnings || flag_code == CODE_64BIT)
-            && (i.types[op].bitfield.dword
+    /* Error if the e or r prefix on a general reg is present.  */
+    else if ((i.types[op].bitfield.dword
                 || i.types[op].bitfield.qword)
             && (i.tm.operand_types[op].bitfield.class == Reg
                 || i.tm.operand_types[op].bitfield.instance == Accum)
             && i.tm.operand_types[op].bitfield.word)
       {
-       /* Prohibit these changes in the 64bit mode, since the
-          lowering is more complicated.  */
-       if (flag_code == CODE_64BIT)
-         {
-           as_bad (_("incorrect register `%s%s' used with `%c' suffix"),
-                   register_prefix, i.op[op].regs->reg_name,
-                   i.suffix);
-           return 0;
-         }
-#if REGISTER_WARNINGS
-       as_warn (_("using `%s%s' instead of `%s%s' due to `%c' suffix"),
-                register_prefix,
-                (i.op[op].regs + REGNAM_AX - REGNAM_EAX)->reg_name,
-                register_prefix, i.op[op].regs->reg_name, i.suffix);
-#endif
+       as_bad (_("incorrect register `%s%s' used with `%c' suffix"),
+               register_prefix, i.op[op].regs->reg_name,
+               i.suffix);
+       return 0;
       }
   return 1;
 }
@@ -7109,7 +7079,7 @@ duplicate:
         on one of their operands, the default segment is ds.  */
       default_seg = &ds;
     }
-  else if (i.tm.opcode_modifier.shortform)
+  else if (i.short_form)
     {
       /* The register or float register operand is in operand
         0 or 1.  */
This page took 0.040883 seconds and 4 git commands to generate.