gas/
[deliverable/binutils-gdb.git] / gas / config / tc-i386.c
index fd9e0c36bb4f73a8504d89790be943e4a6226f54..28d37a8956c29bdefb4de33508c5660b984320e9 100644 (file)
@@ -1,6 +1,6 @@
 /* tc-i386.c -- Assemble code for the Intel 80386
    Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 #define INFER_ADDR_PREFIX 1
 #endif
 
-#ifndef SCALE1_WHEN_NO_INDEX
-/* Specifying a scale factor besides 1 when there is no index is
-   futile.  eg. `mov (%ebx,2),%al' does exactly the same as
-   `mov (%ebx),%al'.  To slavishly follow what the programmer
-   specified, set SCALE1_WHEN_NO_INDEX to 0.  */
-#define SCALE1_WHEN_NO_INDEX 1
-#endif
-
 #ifndef DEFAULT_ARCH
 #define DEFAULT_ARCH "i386"
 #endif
 #endif
 #endif
 
+/* Prefixes will be emitted in the order defined below.
+   WAIT_PREFIX must be the first prefix since FWAIT is really is an
+   instruction, and so must come before any prefixes.
+   The preferred prefix order is SEG_PREFIX, ADDR_PREFIX, DATA_PREFIX,
+   LOCKREP_PREFIX.  */
+#define WAIT_PREFIX    0
+#define SEG_PREFIX     1
+#define ADDR_PREFIX    2
+#define DATA_PREFIX    3
+#define LOCKREP_PREFIX 4
+#define REX_PREFIX     5       /* must come last.  */
+#define MAX_PREFIXES   6       /* max prefixes per opcode */
+
+/* we define the syntax here (modulo base,index,scale syntax) */
+#define REGISTER_PREFIX '%'
+#define IMMEDIATE_PREFIX '$'
+#define ABSOLUTE_PREFIX '*'
+
+/* these are the instruction mnemonic suffixes in AT&T syntax or
+   memory operand size in Intel syntax.  */
+#define WORD_MNEM_SUFFIX  'w'
+#define BYTE_MNEM_SUFFIX  'b'
+#define SHORT_MNEM_SUFFIX 's'
+#define LONG_MNEM_SUFFIX  'l'
+#define QWORD_MNEM_SUFFIX  'q'
+#define XMMWORD_MNEM_SUFFIX  'x'
+/* Intel Syntax.  Use a non-ascii letter since since it never appears
+   in instructions.  */
+#define LONG_DOUBLE_MNEM_SUFFIX '\1'
+
+#define END_OF_INSN '\0'
+
+/*
+  'templates' is for grouping together 'template' structures for opcodes
+  of the same name.  This is only used for storing the insns in the grand
+  ole hash table of insns.
+  The templates themselves start at START and range up to (but not including)
+  END.
+  */
+typedef struct
+{
+  const template *start;
+  const template *end;
+}
+templates;
+
+/* 386 operand encoding bytes:  see 386 book for details of this.  */
+typedef struct
+{
+  unsigned int regmem; /* codes register or memory operand */
+  unsigned int reg;    /* codes register operand (or extended opcode) */
+  unsigned int mode;   /* how to interpret regmem & reg */
+}
+modrm_byte;
+
+/* x86-64 extension prefix.  */
+typedef int rex_byte;
+
+/* The SSE5 instructions have a two bit instruction modifier (OC) that 
+   is stored in two separate bytes in the instruction.  Pick apart OC 
+   into the 2 separate bits for instruction.  */
+#define DREX_OC0(x)    (((x) & 1) != 0)
+#define DREX_OC1(x)    (((x) & 2) != 0)
+
+#define DREX_OC0_MASK  (1 << 3)        /* set OC0 in byte 4 */
+#define DREX_OC1_MASK  (1 << 2)        /* set OC1 in byte 3 */
+
+/* OC mappings */
+#define DREX_XMEM_X1_X2_X2 0   /* 4 op insn, dest = src3, src1 = reg/mem */
+#define DREX_X1_XMEM_X2_X2 1   /* 4 op insn, dest = src3, src2 = reg/mem */
+#define DREX_X1_XMEM_X2_X1 2   /* 4 op insn, dest = src1, src2 = reg/mem */
+#define DREX_X1_X2_XMEM_X1 3   /* 4 op insn, dest = src1, src3 = reg/mem */
+
+#define DREX_XMEM_X1_X2           0    /* 3 op insn, src1 = reg/mem */
+#define DREX_X1_XMEM_X2           1    /* 3 op insn, src1 = reg/mem */
+
+/* Information needed to create the DREX byte in SSE5 instructions.  */
+typedef struct
+{
+  unsigned int reg;            /* register */
+  unsigned int rex;            /* REX flags */
+  unsigned int modrm_reg;      /* which arg goes in the modrm.reg field */
+  unsigned int modrm_regmem;   /* which arg goes in the modrm.regmem field */
+} drex_byte;
+
+/* 386 opcode byte to code indirect addressing.  */
+typedef struct
+{
+  unsigned base;
+  unsigned index;
+  unsigned scale;
+}
+sib_byte;
+
+enum processor_type
+{
+  PROCESSOR_UNKNOWN,
+  PROCESSOR_I386,
+  PROCESSOR_I486,
+  PROCESSOR_PENTIUM,
+  PROCESSOR_PENTIUMPRO,
+  PROCESSOR_PENTIUM4,
+  PROCESSOR_NOCONA,
+  PROCESSOR_CORE,
+  PROCESSOR_CORE2,
+  PROCESSOR_K6,
+  PROCESSOR_ATHLON,
+  PROCESSOR_K8,
+  PROCESSOR_GENERIC32,
+  PROCESSOR_GENERIC64,
+  PROCESSOR_AMDFAM10
+};
+
+/* x86 arch names, types and features */
+typedef struct
+{
+  const char *name;            /* arch name */
+  enum processor_type type;    /* arch type */
+  i386_cpu_flags flags;                /* cpu feature flags */
+}
+arch_entry;
+
 static void set_code_flag (int);
 static void set_16bit_gcc_code_flag (int);
 static void set_intel_syntax (int);
+static void set_intel_mnemonic (int);
+static void set_allow_index_reg (int);
 static void set_cpu_arch (int);
 #ifdef TE_PE
 static void pe_directive_secrel (int);
 #endif
 static void signed_cons (int);
 static char *output_invalid (int c);
-static int i386_operand (char *);
+static int i386_att_operand (char *);
 static int i386_intel_operand (char *, int);
 static const reg_entry *parse_register (char *, char **);
 static char *parse_insn (char *, char *);
@@ -119,8 +235,8 @@ struct _i386_insn
     /* TM holds the template for the insn were currently assembling.  */
     template tm;
 
-    /* SUFFIX holds the instruction mnemonic suffix if given.
-       (e.g. 'l' for 'movl')  */
+    /* SUFFIX holds the instruction size suffix for byte, word, dword
+       or qword, if given.  */
     char suffix;
 
     /* OPERANDS gives the number of given operands.  */
@@ -273,7 +389,6 @@ enum flag_code {
        CODE_32BIT,
        CODE_16BIT,
        CODE_64BIT };
-#define NUM_FLAG_CODE ((int) CODE_64BIT + 1)
 
 static enum flag_code flag_code;
 static unsigned int object_64bit;
@@ -291,9 +406,19 @@ static const char *flag_code_names[] =
    0 if att syntax.  */
 static int intel_syntax = 0;
 
+/* 1 for intel mnemonic,
+   0 if att mnemonic.  */
+static int intel_mnemonic = !SYSV386_COMPAT;
+
+/* 1 if support old (<= 2.8.1) versions of gcc.  */
+static int old_gcc = OLDGCC_COMPAT;
+
 /* 1 if register prefix % not required.  */
 static int allow_naked_reg = 0;
 
+/* 1 if pseudo index register, eiz/riz, is allowed .  */
+static int allow_index_reg = 0;
+
 /* Register prefix used for error message.  */
 static const char *register_prefix = "%";
 
@@ -310,14 +435,11 @@ static int quiet_warnings = 0;
 
 /* CPU name.  */
 static const char *cpu_arch_name = NULL;
-static const char *cpu_sub_arch_name = NULL;
+static char *cpu_sub_arch_name = NULL;
 
 /* CPU feature flags.  */
 static i386_cpu_flags cpu_arch_flags = CPU_UNKNOWN_FLAGS;
 
-/* Bitwise NOT of cpu_arch_flags.  */
-static i386_cpu_flags cpu_arch_flags_not;
-
 /* If we have selected a cpu we are generating instructions for.  */
 static int cpu_arch_tune_set = 0;
 
@@ -427,92 +549,96 @@ const relax_typeS md_relax_table[] =
 
 static const arch_entry cpu_arch[] =
 {
-  {"generic32", PROCESSOR_GENERIC32,
-   CPU_GENERIC32_FLAGS },
-  {"generic64", PROCESSOR_GENERIC64,
-   CPU_GENERIC64_FLAGS },
-  {"i8086", PROCESSOR_UNKNOWN,
-   CPU_NONE_FLAGS },
-  {"i186", PROCESSOR_UNKNOWN,
-   CPU_I186_FLAGS },
-  {"i286", PROCESSOR_UNKNOWN,
-   CPU_I286_FLAGS },
-  {"i386", PROCESSOR_I386,
-   CPU_I386_FLAGS },
-  {"i486", PROCESSOR_I486,
-   CPU_I486_FLAGS },
-  {"i586", PROCESSOR_PENTIUM,
-   CPU_I586_FLAGS },
-  {"i686", PROCESSOR_PENTIUMPRO,
-   CPU_I686_FLAGS },
-  {"pentium", PROCESSOR_PENTIUM,
-   CPU_I586_FLAGS },
-  {"pentiumpro",PROCESSOR_PENTIUMPRO,
-   CPU_I686_FLAGS },
-  {"pentiumii",        PROCESSOR_PENTIUMPRO,
-   CPU_P2_FLAGS },
-  {"pentiumiii",PROCESSOR_PENTIUMPRO,
-   CPU_P3_FLAGS },
-  {"pentium4", PROCESSOR_PENTIUM4,
-   CPU_P4_FLAGS },
-  {"prescott", PROCESSOR_NOCONA,
-   CPU_CORE_FLAGS },
-  {"nocona", PROCESSOR_NOCONA,
-   CPU_NOCONA_FLAGS },
-  {"yonah", PROCESSOR_CORE,
-   CPU_CORE_FLAGS },
-  {"core", PROCESSOR_CORE,
-   CPU_CORE_FLAGS },
-  {"merom", PROCESSOR_CORE2,
-   CPU_CORE2_FLAGS },
-  {"core2", PROCESSOR_CORE2,
-   CPU_CORE2_FLAGS },
-  {"k6", PROCESSOR_K6,
-   CPU_K6_FLAGS },
-  {"k6_2", PROCESSOR_K6,
-   CPU_K6_2_FLAGS },
-  {"athlon", PROCESSOR_ATHLON,
-   CPU_ATHLON_FLAGS },
-  {"sledgehammer", PROCESSOR_K8,
-   CPU_K8_FLAGS },
-  {"opteron", PROCESSOR_K8,
-   CPU_K8_FLAGS },
-  {"k8", PROCESSOR_K8,
-   CPU_K8_FLAGS },
-  {"amdfam10", PROCESSOR_AMDFAM10,
-   CPU_AMDFAM10_FLAGS },
-  {".mmx", PROCESSOR_UNKNOWN,
-   CPU_MMX_FLAGS },
-  {".sse", PROCESSOR_UNKNOWN,
-   CPU_SSE_FLAGS },
-  {".sse2", PROCESSOR_UNKNOWN,
-   CPU_SSE2_FLAGS },
-  {".sse3", PROCESSOR_UNKNOWN,
-   CPU_SSE3_FLAGS },
-  {".ssse3", PROCESSOR_UNKNOWN,
-   CPU_SSSE3_FLAGS },
-  {".sse4.1", PROCESSOR_UNKNOWN,
-   CPU_SSE4_1_FLAGS },
-  {".sse4.2", PROCESSOR_UNKNOWN,
-   CPU_SSE4_2_FLAGS },
-  {".sse4", PROCESSOR_UNKNOWN,
-   CPU_SSE4_2_FLAGS },
-  {".3dnow", PROCESSOR_UNKNOWN,
-   CPU_3DNOW_FLAGS },
-  {".3dnowa", PROCESSOR_UNKNOWN,
-   CPU_3DNOWA_FLAGS },
-  {".padlock", PROCESSOR_UNKNOWN,
-   CPU_PADLOCK_FLAGS },
-  {".pacifica", PROCESSOR_UNKNOWN,
-   CPU_SVME_FLAGS },
-  {".svme", PROCESSOR_UNKNOWN,
-   CPU_SVME_FLAGS },
-  {".sse4a", PROCESSOR_UNKNOWN,
-   CPU_SSE4A_FLAGS },
-  {".abm", PROCESSOR_UNKNOWN,
-   CPU_ABM_FLAGS },
-  {".sse5", PROCESSOR_UNKNOWN,
-   CPU_SSE5_FLAGS },
+  { "generic32", PROCESSOR_GENERIC32,
+    CPU_GENERIC32_FLAGS },
+  { "generic64", PROCESSOR_GENERIC64,
+    CPU_GENERIC64_FLAGS },
+  { "i8086", PROCESSOR_UNKNOWN,
+    CPU_NONE_FLAGS },
+  { "i186", PROCESSOR_UNKNOWN,
+    CPU_I186_FLAGS },
+  { "i286", PROCESSOR_UNKNOWN,
+    CPU_I286_FLAGS },
+  { "i386", PROCESSOR_I386,
+    CPU_I386_FLAGS },
+  { "i486", PROCESSOR_I486,
+    CPU_I486_FLAGS },
+  { "i586", PROCESSOR_PENTIUM,
+    CPU_I586_FLAGS },
+  { "i686", PROCESSOR_PENTIUMPRO,
+    CPU_I686_FLAGS },
+  { "pentium", PROCESSOR_PENTIUM,
+    CPU_I586_FLAGS },
+  { "pentiumpro", PROCESSOR_PENTIUMPRO,
+    CPU_I686_FLAGS },
+  { "pentiumii", PROCESSOR_PENTIUMPRO,
+    CPU_P2_FLAGS },
+  { "pentiumiii",PROCESSOR_PENTIUMPRO,
+    CPU_P3_FLAGS },
+  { "pentium4", PROCESSOR_PENTIUM4,
+    CPU_P4_FLAGS },
+  { "prescott", PROCESSOR_NOCONA,
+    CPU_CORE_FLAGS },
+  { "nocona", PROCESSOR_NOCONA,
+    CPU_NOCONA_FLAGS },
+  { "yonah", PROCESSOR_CORE,
+    CPU_CORE_FLAGS },
+  { "core", PROCESSOR_CORE,
+    CPU_CORE_FLAGS },
+  { "merom", PROCESSOR_CORE2,
+    CPU_CORE2_FLAGS },
+  { "core2", PROCESSOR_CORE2,
+    CPU_CORE2_FLAGS },
+  { "k6", PROCESSOR_K6,
+    CPU_K6_FLAGS },
+  { "k6_2", PROCESSOR_K6,
+    CPU_K6_2_FLAGS },
+  { "athlon", PROCESSOR_ATHLON,
+    CPU_ATHLON_FLAGS },
+  { "sledgehammer", PROCESSOR_K8,
+    CPU_K8_FLAGS },
+  { "opteron", PROCESSOR_K8,
+    CPU_K8_FLAGS },
+  { "k8", PROCESSOR_K8,
+    CPU_K8_FLAGS },
+  { "amdfam10", PROCESSOR_AMDFAM10,
+    CPU_AMDFAM10_FLAGS },
+  { ".mmx", PROCESSOR_UNKNOWN,
+    CPU_MMX_FLAGS },
+  { ".sse", PROCESSOR_UNKNOWN,
+    CPU_SSE_FLAGS },
+  { ".sse2", PROCESSOR_UNKNOWN,
+    CPU_SSE2_FLAGS },
+  { ".sse3", PROCESSOR_UNKNOWN,
+    CPU_SSE3_FLAGS },
+  { ".ssse3", PROCESSOR_UNKNOWN,
+    CPU_SSSE3_FLAGS },
+  { ".sse4.1", PROCESSOR_UNKNOWN,
+    CPU_SSE4_1_FLAGS },
+  { ".sse4.2", PROCESSOR_UNKNOWN,
+    CPU_SSE4_2_FLAGS },
+  { ".sse4", PROCESSOR_UNKNOWN,
+    CPU_SSE4_2_FLAGS },
+  { ".vmx", PROCESSOR_UNKNOWN,
+    CPU_VMX_FLAGS },
+  { ".smx", PROCESSOR_UNKNOWN,
+    CPU_SMX_FLAGS },
+  { ".3dnow", PROCESSOR_UNKNOWN,
+    CPU_3DNOW_FLAGS },
+  { ".3dnowa", PROCESSOR_UNKNOWN,
+    CPU_3DNOWA_FLAGS },
+  { ".padlock", PROCESSOR_UNKNOWN,
+    CPU_PADLOCK_FLAGS },
+  { ".pacifica", PROCESSOR_UNKNOWN,
+    CPU_SVME_FLAGS },
+  { ".svme", PROCESSOR_UNKNOWN,
+    CPU_SVME_FLAGS },
+  { ".sse4a", PROCESSOR_UNKNOWN,
+    CPU_SSE4A_FLAGS },
+  { ".abm", PROCESSOR_UNKNOWN,
+    CPU_ABM_FLAGS },
+  { ".sse5", PROCESSOR_UNKNOWN,
+    CPU_SSE5_FLAGS },
 };
 
 const pseudo_typeS md_pseudo_table[] =
@@ -539,6 +665,10 @@ const pseudo_typeS md_pseudo_table[] =
   {"code64", set_code_flag, CODE_64BIT},
   {"intel_syntax", set_intel_syntax, 1},
   {"att_syntax", set_intel_syntax, 0},
+  {"intel_mnemonic", set_intel_mnemonic, 1},
+  {"att_mnemonic", set_intel_mnemonic, 0},
+  {"allow_index_reg", set_allow_index_reg, 1},
+  {"disallow_index_reg", set_allow_index_reg, 0},
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
   {"largecomm", handle_large_common, 0},
 #else
@@ -959,29 +1089,6 @@ cpu_flags_check_cpu64 (i386_cpu_flags f)
           || (flag_code != CODE_64BIT && f.bitfield.cpu64));
 }
 
-static INLINE i386_cpu_flags
-cpu_flags_not (i386_cpu_flags x)
-{
-  switch (ARRAY_SIZE (x.array))
-    {
-    case 3:
-      x.array [2] = ~x.array [2];
-    case 2:
-      x.array [1] = ~x.array [1];
-    case 1:
-      x.array [0] = ~x.array [0];
-      break;
-    default:
-      abort ();
-    }
-
-#ifdef CpuUnused
-  x.bitfield.unused = 0;
-#endif
-
-  return x;
-}
-
 static INLINE i386_cpu_flags
 cpu_flags_and (i386_cpu_flags x, i386_cpu_flags y)
 {
@@ -1018,19 +1125,29 @@ cpu_flags_or (i386_cpu_flags x, i386_cpu_flags y)
   return x;
 }
 
+/* Return 3 if there is a perfect match, 2 if compatible with 64bit,
+   1 if compatible with arch, 0 if there is no match.  */
+
 static int
 cpu_flags_match (i386_cpu_flags x)
 {
-  i386_cpu_flags not = cpu_arch_flags_not;
-
-  not.bitfield.cpu64 = 1;
-  not.bitfield.cpuno64 = 1;
+  int overlap = cpu_flags_check_cpu64 (x) ? 2 : 0;
 
   x.bitfield.cpu64 = 0;
   x.bitfield.cpuno64 = 0;
 
-  not = cpu_flags_and (x, not);
-  return UINTS_ALL_ZERO (not);
+  if (UINTS_ALL_ZERO (x))
+    overlap |= 1;
+  else
+    {
+      i386_cpu_flags cpu = cpu_arch_flags;
+
+      cpu.bitfield.cpu64 = 0;
+      cpu.bitfield.cpuno64 = 0;
+      cpu = cpu_flags_and (x, cpu);
+      overlap |= UINTS_ALL_ZERO (cpu) ? 0 : 1;
+    }
+  return overlap;
 }
 
 static INLINE i386_operand_type
@@ -1098,7 +1215,6 @@ static const i386_operand_type disp32s = OPERAND_TYPE_DISP32S;
 static const i386_operand_type disp16_32 = OPERAND_TYPE_DISP16_32;
 static const i386_operand_type anydisp
   = OPERAND_TYPE_ANYDISP;
-static const i386_operand_type baseindex = OPERAND_TYPE_BASEINDEX;
 static const i386_operand_type regxmm = OPERAND_TYPE_REGXMM;
 static const i386_operand_type imm8 = OPERAND_TYPE_IMM8;
 static const i386_operand_type imm8s = OPERAND_TYPE_IMM8S;
@@ -1157,6 +1273,102 @@ operand_type_check (i386_operand_type t, enum operand_type c)
     }
 }
 
+/* Return 1 if there is no conflict in 8bit/16bit/32bit/64bit on
+   operand J for instruction template T.  */
+
+static INLINE int
+match_reg_size (const template *t, unsigned int j)
+{
+  return !((i.types[j].bitfield.byte
+           && !t->operand_types[j].bitfield.byte)
+          || (i.types[j].bitfield.word
+              && !t->operand_types[j].bitfield.word)
+          || (i.types[j].bitfield.dword
+              && !t->operand_types[j].bitfield.dword)
+          || (i.types[j].bitfield.qword
+              && !t->operand_types[j].bitfield.qword));
+}
+
+/* Return 1 if there is no conflict in any size on operand J for
+   instruction template T.  */
+
+static INLINE int
+match_mem_size (const template *t, unsigned int j)
+{
+  return (match_reg_size (t, j)
+         && !((i.types[j].bitfield.unspecified
+               && !t->operand_types[j].bitfield.unspecified)
+              || (i.types[j].bitfield.fword
+                  && !t->operand_types[j].bitfield.fword)
+              || (i.types[j].bitfield.tbyte
+                  && !t->operand_types[j].bitfield.tbyte)
+              || (i.types[j].bitfield.xmmword
+                  && !t->operand_types[j].bitfield.xmmword)));
+}
+
+/* Return 1 if there is no size conflict on any operands for
+   instruction template T.  */
+
+static INLINE int
+operand_size_match (const template *t)
+{
+  unsigned int j;
+  int match = 1;
+
+  /* Don't check jump instructions.  */
+  if (t->opcode_modifier.jump
+      || t->opcode_modifier.jumpbyte
+      || t->opcode_modifier.jumpdword
+      || t->opcode_modifier.jumpintersegment)
+    return match;
+
+  /* Check memory and accumulator operand size.  */
+  for (j = 0; j < i.operands; j++)
+    {
+      if (t->operand_types[j].bitfield.anysize)
+       continue;
+
+      if (t->operand_types[j].bitfield.acc && !match_reg_size (t, j))
+       {
+         match = 0;
+         break;
+       }
+
+      if (i.types[j].bitfield.mem && !match_mem_size (t, j))
+       {
+         match = 0;
+         break;
+       }
+    }
+
+  if (match
+      || (!t->opcode_modifier.d && !t->opcode_modifier.floatd))
+    return match;
+
+  /* Check reverse.  */
+  assert (i.operands == 2);
+
+  match = 1;
+  for (j = 0; j < 2; j++)
+    {
+      if (t->operand_types[j].bitfield.acc
+         && !match_reg_size (t, j ? 0 : 1))
+       {
+         match = 0;
+         break;
+       }
+
+      if (i.types[j].bitfield.mem
+         && !match_mem_size (t, j ? 0 : 1))
+       {
+         match = 0;
+         break;
+       }
+    }
+
+  return match;
+}
+
 static INLINE int
 operand_type_match (i386_operand_type overlap,
                    i386_operand_type given)
@@ -1164,6 +1376,14 @@ operand_type_match (i386_operand_type overlap,
   i386_operand_type temp = overlap;
 
   temp.bitfield.jumpabsolute = 0;
+  temp.bitfield.unspecified = 0;
+  temp.bitfield.byte = 0;
+  temp.bitfield.word = 0;
+  temp.bitfield.dword = 0;
+  temp.bitfield.fword = 0;
+  temp.bitfield.qword = 0;
+  temp.bitfield.tbyte = 0;
+  temp.bitfield.xmmword = 0;
   if (UINTS_ALL_ZERO (temp))
     return 0;
 
@@ -1171,7 +1391,7 @@ operand_type_match (i386_operand_type overlap,
          && given.bitfield.jumpabsolute == overlap.bitfield.jumpabsolute);
 }
 
-/* If given types r0 and r1 are registers they must be of the same type
+/* If given types g0 and g1 are registers they must be of the same type
    unless the expected operand type register overlap is null.
    Note that Acc in a template matches every size of reg.  */
 
@@ -1439,15 +1659,11 @@ set_code_flag (int value)
     {
       cpu_arch_flags.bitfield.cpu64 = 1;
       cpu_arch_flags.bitfield.cpuno64 = 0;
-      cpu_arch_flags_not.bitfield.cpu64 = 0;
-      cpu_arch_flags_not.bitfield.cpuno64 = 1;
     }
   else
     {
       cpu_arch_flags.bitfield.cpu64 = 0;
       cpu_arch_flags.bitfield.cpuno64 = 1;
-      cpu_arch_flags_not.bitfield.cpu64 = 1;
-      cpu_arch_flags_not.bitfield.cpuno64 = 0;
     }
   if (value == CODE_64BIT && !cpu_arch_flags.bitfield.cpulm )
     {
@@ -1468,8 +1684,6 @@ set_16bit_gcc_code_flag (int new_code_flag)
     abort ();
   cpu_arch_flags.bitfield.cpu64 = 0;
   cpu_arch_flags.bitfield.cpuno64 = 1;
-  cpu_arch_flags_not.bitfield.cpu64 = 1;
-  cpu_arch_flags_not.bitfield.cpuno64 = 0;
   stackop_size = LONG_MNEM_SUFFIX;
 }
 
@@ -1508,6 +1722,18 @@ set_intel_syntax (int syntax_flag)
   register_prefix = allow_naked_reg ? "" : "%";
 }
 
+static void
+set_intel_mnemonic (int mnemonic_flag)
+{
+  intel_mnemonic = mnemonic_flag;
+}
+
+static void
+set_allow_index_reg (int flag)
+{
+  allow_index_reg = flag;
+}
+
 static void
 set_cpu_arch (int dummy ATTRIBUTE_UNUSED)
 {
@@ -1539,7 +1765,6 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED)
                      cpu_arch_flags.bitfield.cpu64 = 0;
                      cpu_arch_flags.bitfield.cpuno64 = 1;
                    }
-                 cpu_arch_flags_not = cpu_flags_not (cpu_arch_flags);
                  cpu_arch_isa = cpu_arch[i].type;
                  cpu_arch_isa_flags = cpu_arch[i].flags;
                  if (!cpu_arch_tune_set)
@@ -1554,9 +1779,17 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED)
                                    cpu_arch[i].flags);
              if (!UINTS_EQUAL (flags, cpu_arch_flags))
                {
-                 cpu_sub_arch_name = cpu_arch[i].name;
+                 if (cpu_sub_arch_name)
+                   {
+                     char *name = cpu_sub_arch_name;
+                     cpu_sub_arch_name = concat (name,
+                                                 cpu_arch[i].name,
+                                                 NULL);
+                     free (name);
+                   }
+                 else
+                   cpu_sub_arch_name = xstrdup (cpu_arch[i].name);
                  cpu_arch_flags = flags;
-                 cpu_arch_flags_not = cpu_flags_not (cpu_arch_flags);
                }
              *input_line_pointer = e;
              demand_empty_rest_of_line ();
@@ -1607,8 +1840,6 @@ md_begin ()
 {
   const char *hash_err;
 
-  cpu_arch_flags_not = cpu_flags_not (cpu_arch_flags);
-
   /* Initialize op_hash hash table.  */
   op_hash = hash_new ();
 
@@ -2181,30 +2412,20 @@ md_assemble (line)
   if (!match_template ())
     return;
 
-  if (intel_syntax)
+  /* 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)
     {
-      /* Undo SYSV386_COMPAT brokenness when in Intel mode.  See i386.h  */
-      if (SYSV386_COMPAT
-         && (i.tm.base_opcode & 0xfffffde0) == 0xdce0)
-       i.tm.base_opcode ^= Opcode_FloatR;
-
-      /* Zap movzx and movsx suffix.  The suffix may have been set from
-        "word ptr" or "byte ptr" on the source operand, but we'll use
-        the suffix later to choose the destination register.  */
-      if ((i.tm.base_opcode & ~9) == 0x0fb6)
-       {
-         if (i.reg_operands < 2
-             && !i.suffix
-             && (!i.tm.opcode_modifier.no_bsuf
-                 || !i.tm.opcode_modifier.no_wsuf
-                 || !i.tm.opcode_modifier.no_lsuf
-                 || !i.tm.opcode_modifier.no_ssuf
-                 || !i.tm.opcode_modifier.no_xsuf
-                 || !i.tm.opcode_modifier.no_qsuf))
-           as_bad (_("ambiguous operand size for `%s'"), i.tm.name);
+      /* 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;
-       }
+      i.suffix = 0;
     }
 
   if (i.tm.opcode_modifier.fwait)
@@ -2534,11 +2755,11 @@ parse_insn (char *line, char *mnemonic)
   supported = 0;
   for (t = current_templates->start; t < current_templates->end; ++t)
     {
-      if (cpu_flags_match (t->cpu_flags))
-       supported |= 1;
-      if (cpu_flags_check_cpu64 (t->cpu_flags))
-       supported |= 2;
+      supported |= cpu_flags_match (t->cpu_flags);
+      if (supported == 3)
+       goto skip;
     }
+
   if (!(supported & 2))
     {
       as_bad (flag_code == CODE_64BIT
@@ -2549,12 +2770,14 @@ parse_insn (char *line, char *mnemonic)
     }
   if (!(supported & 1))
     {
-      as_warn (_("`%s' is not supported on `%s%s'"),
-              current_templates->start->name,
-              cpu_arch_name,
-              cpu_sub_arch_name ? cpu_sub_arch_name : "");
+      as_bad (_("`%s' is not supported on `%s%s'"),
+             current_templates->start->name, cpu_arch_name,
+             cpu_sub_arch_name ? cpu_sub_arch_name : "");
+      return NULL;
     }
-  else if (!cpu_arch_flags.bitfield.cpui386
+
+skip:
+  if (!cpu_arch_flags.bitfield.cpui386
           && (flag_code != CODE_16BIT))
     {
       as_warn (_("use .code16 to ensure correct addressing mode"));
@@ -2653,6 +2876,7 @@ parse_operands (char *l, const char *mnemonic)
        {                       /* Yes, we've read in another operand.  */
          unsigned int operand_ok;
          this_operand = i.operands++;
+         i.types[this_operand].bitfield.unspecified = 1;
          if (i.operands > MAX_OPERANDS)
            {
              as_bad (_("spurious operands; (%d operands/instruction max)"),
@@ -2667,7 +2891,7 @@ parse_operands (char *l, const char *mnemonic)
              i386_intel_operand (token_start,
                                  intel_float_operand (mnemonic));
          else
-           operand_ok = i386_operand (token_start);
+           operand_ok = i386_att_operand (token_start);
 
          RESTORE_END_STRING (l);
          if (!operand_ok)
@@ -2977,7 +3201,8 @@ match_template (void)
   i386_operand_type operand_types [MAX_OPERANDS];
   int addr_prefix_disp;
   unsigned int j;
-  i386_cpu_flags overlap;
+  unsigned int found_cpu_match;
+  unsigned int check_register;
 
 #if MAX_OPERANDS != 4
 # error "MAX_OPERANDS must be 4."
@@ -2998,7 +3223,7 @@ match_template (void)
   else if (i.suffix == QWORD_MNEM_SUFFIX)
     suffix_check.no_qsuf = 1;
   else if (i.suffix == LONG_DOUBLE_MNEM_SUFFIX)
-    suffix_check.no_xsuf = 1;
+    suffix_check.no_ldsuf = 1;
 
   for (t = current_templates->start; t < current_templates->end; t++)
     {
@@ -3008,18 +3233,39 @@ match_template (void)
       if (i.operands != t->operands)
        continue;
 
+      /* Check processor support.  */
+      found_cpu_match = cpu_flags_match (t->cpu_flags) == 3;
+      if (!found_cpu_match)
+       continue;
+
+      /* Check old gcc support. */
+      if (!old_gcc && t->opcode_modifier.oldgcc)
+       continue;
+
+      /* Check AT&T mnemonic.   */
+      if (intel_mnemonic && t->opcode_modifier.attmnemonic)
+       continue;
+
+      /* Check AT&T syntax Intel syntax.   */
+      if ((intel_syntax && t->opcode_modifier.attsyntax)
+         || (!intel_syntax && t->opcode_modifier.intelsyntax))
+       continue;
+
       /* Check the suffix, except for some instructions in intel mode.  */
-      if (((t->opcode_modifier.no_bsuf & suffix_check.no_bsuf)
-          || (t->opcode_modifier.no_wsuf & suffix_check.no_wsuf)
-          || (t->opcode_modifier.no_lsuf & suffix_check.no_lsuf)
-          || (t->opcode_modifier.no_ssuf & suffix_check.no_ssuf)
-          || (t->opcode_modifier.no_qsuf & suffix_check.no_qsuf)
-          || (t->opcode_modifier.no_xsuf & suffix_check.no_xsuf))
-         && !(intel_syntax && t->opcode_modifier.ignoresize))
+      if ((!intel_syntax || !t->opcode_modifier.ignoresize)
+         && ((t->opcode_modifier.no_bsuf && suffix_check.no_bsuf)
+             || (t->opcode_modifier.no_wsuf && suffix_check.no_wsuf)
+             || (t->opcode_modifier.no_lsuf && suffix_check.no_lsuf)
+             || (t->opcode_modifier.no_ssuf && suffix_check.no_ssuf)
+             || (t->opcode_modifier.no_qsuf && suffix_check.no_qsuf)
+             || (t->opcode_modifier.no_ldsuf && suffix_check.no_ldsuf)))
+       continue;
+
+      if (!operand_size_match (t))
        continue;
 
       for (j = 0; j < MAX_OPERANDS; j++)
-       operand_types [j] = t->operand_types [j];
+       operand_types[j] = t->operand_types[j];
 
       /* In general, don't allow 64-bit operands in 32-bit mode.  */
       if (i.suffix == QWORD_MNEM_SUFFIX
@@ -3037,16 +3283,11 @@ match_template (void)
        continue;
 
       /* Do not verify operands when there are none.  */
-      else 
+      else
        {
-         overlap = cpu_flags_and (t->cpu_flags, cpu_arch_flags_not);
          if (!t->operands)
-           {
-             if (!UINTS_ALL_ZERO (overlap))
-               continue;
-             /* We've found a match; break out of loop.  */
-             break;
-           }
+           /* We've found a match; break out of loop.  */
+           break;
        }
 
       /* Address size prefix will turn Disp64/Disp32/Disp16 operand
@@ -3095,6 +3336,9 @@ match_template (void)
            }
          }
 
+      /* We check register size only if size of operands can be
+        encoded the canonical way.  */
+      check_register = t->opcode_modifier.w;
       overlap0 = operand_type_and (i.types[0], operand_types[0]);
       switch (t->operands)
        {
@@ -3117,19 +3361,8 @@ match_template (void)
          overlap1 = operand_type_and (i.types[1], operand_types[1]);
          if (!operand_type_match (overlap0, i.types[0])
              || !operand_type_match (overlap1, i.types[1])
-             /* monitor in SSE3 is a very special case.  The first
-                register and the second register may have different
-                sizes.  The same applies to crc32 in SSE4.2.  It is
-                also true for invlpga, vmload, vmrun and vmsave in
-                SVME.  */
-             || !((t->base_opcode == 0x0f01
-                   && (t->extension_opcode == 0xc8
-                       || t->extension_opcode == 0xd8
-                       || t->extension_opcode == 0xda
-                       || t->extension_opcode == 0xdb
-                       || t->extension_opcode == 0xdf))
-                  || t->base_opcode == 0xf20f38f1
-                  || operand_type_register_match (overlap0, i.types[0],
+             || (check_register
+                 && !operand_type_register_match (overlap0, i.types[0],
                                                   operand_types[0],
                                                   overlap1, i.types[1],
                                                   operand_types[1])))
@@ -3143,10 +3376,13 @@ match_template (void)
              overlap1 = operand_type_and (i.types[1], operand_types[0]);
              if (!operand_type_match (overlap0, i.types[0])
                  || !operand_type_match (overlap1, i.types[1])
-                 || !operand_type_register_match (overlap0, i.types[0],
-                                                  operand_types[1],
-                                                  overlap1, i.types[1],
-                                                  operand_types[0]))
+                 || (check_register
+                     && !operand_type_register_match (overlap0,
+                                                      i.types[0],
+                                                      operand_types[1],
+                                                      overlap1,
+                                                      i.types[1],
+                                                      operand_types[0])))
                {
                  /* Does not match either direction.  */
                  continue;
@@ -3180,12 +3416,13 @@ match_template (void)
                {
                case 4:
                  if (!operand_type_match (overlap3, i.types[3])
-                     || !operand_type_register_match (overlap2,
-                                                      i.types[2],
-                                                      operand_types[2],
-                                                      overlap3,
-                                                      i.types[3],
-                                                      operand_types[3]))
+                     || (check_register
+                         && !operand_type_register_match (overlap2,
+                                                          i.types[2],
+                                                          operand_types[2],
+                                                          overlap3,
+                                                          i.types[3],
+                                                          operand_types[3])))
                    continue;
                case 3:
                  /* Here we make use of the fact that there are no
@@ -3193,12 +3430,13 @@ match_template (void)
                     operand instructions only need to be checked for
                     register consistency between operands 2 and 3.  */
                  if (!operand_type_match (overlap2, i.types[2])
-                     || !operand_type_register_match (overlap1,
-                                                      i.types[1],
-                                                      operand_types[1],
-                                                      overlap2,
-                                                      i.types[2],
-                                                      operand_types[2]))
+                     || (check_register
+                         && !operand_type_register_match (overlap1,
+                                                          i.types[1],
+                                                          operand_types[1],
+                                                          overlap2,
+                                                          i.types[2],
+                                                          operand_types[2])))
                    continue;
                  break;
                }
@@ -3206,7 +3444,7 @@ match_template (void)
          /* Found either forward/reverse 2, 3 or 4 operand match here:
             slip through to break.  */
        }
-      if (!UINTS_ALL_ZERO (overlap))
+      if (!found_cpu_match)
        {
          found_reverse_match = 0;
          continue;
@@ -3382,7 +3620,11 @@ process_suffix (void)
        }
       else if (i.suffix == QWORD_MNEM_SUFFIX)
        {
-         if (!check_qword_reg ())
+         if (intel_syntax
+             && i.tm.opcode_modifier.ignoresize
+             && i.tm.opcode_modifier.no_qsuf)
+           i.suffix = 0;
+         else if (!check_qword_reg ())
            return 0;
        }
       else if (i.suffix == WORD_MNEM_SUFFIX)
@@ -3390,6 +3632,11 @@ process_suffix (void)
          if (!check_word_reg ())
            return 0;
        }
+      else if (i.suffix == XMMWORD_MNEM_SUFFIX)
+       {
+         /* Skip if the instruction has x suffix.  match_template
+            should check if it is a valid suffix.  */
+       }
       else if (intel_syntax && i.tm.opcode_modifier.ignoresize)
        /* Do nothing if the instruction is going to ignore the prefix.  */
        ;
@@ -3450,7 +3697,7 @@ process_suffix (void)
            suffixes |= 1 << 1;
          if (!i.tm.opcode_modifier.no_lsuf)
            suffixes |= 1 << 2;
-         if (!i.tm.opcode_modifier.no_lsuf)
+         if (!i.tm.opcode_modifier.no_ldsuf)
            suffixes |= 1 << 3;
          if (!i.tm.opcode_modifier.no_ssuf)
            suffixes |= 1 << 4;
@@ -3472,7 +3719,9 @@ process_suffix (void)
   /* Change the opcode based on the operand size given by i.suffix;
      We don't need to change things for byte insns.  */
 
-  if (i.suffix && i.suffix != BYTE_MNEM_SUFFIX)
+  if (i.suffix
+      && i.suffix != BYTE_MNEM_SUFFIX
+      && i.suffix != XMMWORD_MNEM_SUFFIX)
     {
       /* It's not a byte, select word/dword operation.  */
       if (i.tm.opcode_modifier.w)
@@ -3486,17 +3735,10 @@ process_suffix (void)
       /* Now select between word & dword operations via the operand
         size prefix, except for instructions that will ignore this
         prefix anyway.  */
-      if (i.tm.base_opcode == 0x0f01
-          && (i.tm.extension_opcode == 0xc8
-              || i.tm.extension_opcode == 0xd8
-              || i.tm.extension_opcode == 0xda
-              || i.tm.extension_opcode == 0xdb
-              || i.tm.extension_opcode == 0xdf))
-       {
-         /* monitor in SSE3 is a very special case. The default size
-            of AX is the size of mode. The address size override
-            prefix will change the size of AX.  It is also true for
-            invlpga, vmload, vmrun and vmsave in SVME.  */
+      if (i.tm.opcode_modifier.addrprefixop0)
+       {
+         /* The address size override prefix changes the size of the
+            first operand.  */
          if ((flag_code == CODE_32BIT
               && i.op->regs[0].reg_type.bitfield.reg16)
              || (flag_code != CODE_32BIT
@@ -3563,16 +3805,8 @@ check_byte_reg (void)
       if (i.types[op].bitfield.reg8)
        continue;
 
-      /* movzx, movsx, pextrb and pinsrb should not generate this
-        warning.  */
-      if (intel_syntax
-         && (i.tm.base_opcode == 0xfb7
-             || i.tm.base_opcode == 0xfb6
-             || i.tm.base_opcode == 0x63
-             || i.tm.base_opcode == 0xfbe
-             || i.tm.base_opcode == 0xfbf
-             || i.tm.base_opcode == 0x660f3a14
-             || i.tm.base_opcode == 0x660f3a20))
+      /* Don't generate this warning if not needed.  */
+      if (intel_syntax && i.tm.opcode_modifier.byteokintel)
        continue;
 
       /* crc32 doesn't generate this warning.  */
@@ -3684,11 +3918,10 @@ check_long_reg (void)
                 || i.tm.operand_types[op].bitfield.acc))
       {
        if (intel_syntax
-           && i.tm.base_opcode == 0xf30f2d
+           && i.tm.opcode_modifier.toqword
            && !i.types[0].bitfield.regxmm)
          {
-           /* cvtss2si converts DWORD memory to Reg64.  We want
-              REX byte. */
+           /* Convert to QWORD.  We want REX byte. */
            i.suffix = QWORD_MNEM_SUFFIX;
          }
        else
@@ -3731,11 +3964,10 @@ check_qword_reg (void)
        /* Prohibit these changes in the 64bit mode, since the
           lowering is more complicated.  */
        if (intel_syntax
-           && i.tm.base_opcode == 0xf20f2d
+           && i.tm.opcode_modifier.todword
            && !i.types[0].bitfield.regxmm)
          {
-           /* cvtsd2si converts QWORD memory to Reg32.  We don't want
-              REX byte. */
+           /* Convert to DWORD.  We don't want REX byte. */
            i.suffix = LONG_MNEM_SUFFIX;
          }
        else
@@ -3881,8 +4113,8 @@ finalize_imm (void)
 static void
 process_drex (void)
 {
-  i.drex.modrm_reg = None;
-  i.drex.modrm_regmem = None;
+  i.drex.modrm_reg = 0;
+  i.drex.modrm_regmem = 0;
 
   /* SSE5 4 operand instructions must have the destination the same as 
      one of the inputs.  Figure out the destination register and cache
@@ -4222,57 +4454,56 @@ process_operands (void)
       || i.tm.opcode_modifier.drexc)
     process_drex ();
 
-  /* The imul $imm, %reg instruction is converted into
-     imul $imm, %reg, %reg, and the clr %reg instruction
-     is converted into xor %reg, %reg.  */
-  if (i.tm.opcode_modifier.regkludge)
-    {
-       if (i.tm.cpu_flags.bitfield.cpusse4_1)
-        {
-          /* The first operand in instruction blendvpd, blendvps and
-             pblendvb in SSE4.1 is implicit and must be xmm0.  */
-          assert (i.operands == 3
-                  && i.reg_operands >= 2
-                  && UINTS_EQUAL (i.types[0], regxmm));
-          if (i.op[0].regs->reg_num != 0)
-            {
-              if (intel_syntax)
-                as_bad (_("the last operand of `%s' must be `%sxmm0'"),
-                        i.tm.name, register_prefix);
-              else
-                as_bad (_("the first operand of `%s' must be `%sxmm0'"),
-                        i.tm.name, register_prefix);
-              return 0;
-            }
-          i.op[0] = i.op[1];
-          i.op[1] = i.op[2];
-          i.types[0] = i.types[1];
-          i.types[1] = i.types[2];
-          i.operands--;
-          i.reg_operands--;
-
-          /* We need to adjust fields in i.tm since they are used by
-             build_modrm_byte.  */
-          i.tm.operand_types [0] = i.tm.operand_types [1];
-          i.tm.operand_types [1] = i.tm.operand_types [2];
-          i.tm.operands--;
-        }
-       else
-        {
-          unsigned int first_reg_op;
-          
-          if (operand_type_check (i.types[0], reg))
-            first_reg_op = 0;
-          else
-            first_reg_op = 1;
-          /* Pretend we saw the extra register operand.  */
-          assert (i.reg_operands == 1
-                  && i.op[first_reg_op + 1].regs == 0);
-          i.op[first_reg_op + 1].regs = i.op[first_reg_op].regs;
-          i.types[first_reg_op + 1] = i.types[first_reg_op];
-          i.operands++;
-          i.reg_operands++;
-        }
+  if (i.tm.opcode_modifier.firstxmm0)
+    {
+      unsigned int j;
+
+      /* The first operand is implicit and must be xmm0.  */
+      assert (i.reg_operands && UINTS_EQUAL (i.types[0], regxmm));
+      if (i.op[0].regs->reg_num != 0)
+       {
+         if (intel_syntax)
+           as_bad (_("the last operand of `%s' must be `%sxmm0'"),
+                   i.tm.name, register_prefix);
+         else
+           as_bad (_("the first operand of `%s' must be `%sxmm0'"),
+                   i.tm.name, register_prefix);
+         return 0;
+       }
+
+      for (j = 1; j < i.operands; j++)
+       {
+         i.op[j - 1] = i.op[j];
+         i.types[j - 1] = i.types[j];
+
+         /* We need to adjust fields in i.tm since they are used by
+            build_modrm_byte.  */
+         i.tm.operand_types [j - 1] = i.tm.operand_types [j];
+       }
+
+      i.operands--;
+      i.reg_operands--;
+      i.tm.operands--;
+    }
+  else if (i.tm.opcode_modifier.regkludge)
+    {
+      /* The imul $imm, %reg instruction is converted into
+        imul $imm, %reg, %reg, and the clr %reg instruction
+        is converted into xor %reg, %reg.  */
+
+      unsigned int first_reg_op;
+
+      if (operand_type_check (i.types[0], reg))
+       first_reg_op = 0;
+      else
+       first_reg_op = 1;
+      /* Pretend we saw the extra register operand.  */
+      assert (i.reg_operands == 1
+             && i.op[first_reg_op + 1].regs == 0);
+      i.op[first_reg_op + 1].regs = i.op[first_reg_op].regs;
+      i.types[first_reg_op + 1] = i.types[first_reg_op];
+      i.operands++;
+      i.reg_operands++;
     }
 
   if (i.tm.opcode_modifier.shortform)
@@ -4413,11 +4644,12 @@ build_modrm_byte (void)
            source = 0;
          break;
        case 4:
-         /* When there are 4 operands, the first two must be immediate
-            operands. The source operand will be the 3rd one.  */
+         /* When there are 4 operands, the first two must be 8bit
+            immediate operands. The source operand will be the 3rd
+            one.  */
          assert (i.imm_operands == 2
-                 && operand_type_check (i.types[0], imm)
-                 && operand_type_check (i.types[1], imm));
+                 && i.types[0].bitfield.imm8
+                 && i.types[1].bitfield.imm8);
          source = 2;
          break;
        default:
@@ -4518,7 +4750,11 @@ build_modrm_byte (void)
                }
              else /* !i.base_reg && i.index_reg  */
                {
-                 i.sib.index = i.index_reg->reg_num;
+                 if (i.index_reg->reg_num == RegEiz
+                     || i.index_reg->reg_num == RegRiz)
+                   i.sib.index = NO_INDEX_REGISTER;
+                 else
+                   i.sib.index = i.index_reg->reg_num;
                  i.sib.base = NO_BASE_REGISTER;
                  i.sib.scale = i.log2_scale_factor;
                  i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
@@ -4541,7 +4777,8 @@ build_modrm_byte (void)
                }
            }
          /* RIP addressing for 64bit mode.  */
-         else if (UINTS_EQUAL (i.base_reg->reg_type, baseindex))
+         else if (i.base_reg->reg_num == RegRip ||
+                  i.base_reg->reg_num == RegEip)
            {
              i.rm.regmem = NO_BASE_REGISTER;
              i.types[op].bitfield.disp8 = 0;
@@ -4626,16 +4863,14 @@ build_modrm_byte (void)
                     Any base register besides %esp will not use the
                     extra modrm byte.  */
                  i.sib.index = NO_INDEX_REGISTER;
-#if !SCALE1_WHEN_NO_INDEX
-                 /* Another case where we force the second 
-                    modrm byte.  */
-                 if (i.log2_scale_factor)
-                   i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
-#endif
                }
              else
                {
-                 i.sib.index = i.index_reg->reg_num;
+                 if (i.index_reg->reg_num == RegEiz
+                     || i.index_reg->reg_num == RegRiz)
+                   i.sib.index = NO_INDEX_REGISTER;
+                 else
+                   i.sib.index = i.index_reg->reg_num;
                  i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
                  if ((i.index_reg->reg_flags & RegRex) != 0)
                    i.rex |= REX_X;
@@ -4970,67 +5205,64 @@ output_insn (void)
       /* Output normal instructions here.  */
       char *p;
       unsigned char *q;
+      unsigned int j;
       unsigned int prefix;
-      int opc_3b;
-
-      /* All opcodes on i386 have either 1 or 2 bytes.  SSSE3 and
-        SSE4 and SSE5 instructions have 3 bytes.  We may use one 
-        more higher byte to specify a prefix the instruction 
-        requires. Exclude instructions which are in both SSE4.2 
-        and ABM.  */
-      opc_3b = (i.tm.cpu_flags.bitfield.cpussse3
-               || i.tm.cpu_flags.bitfield.cpusse5
-               || i.tm.cpu_flags.bitfield.cpusse4_1
-               || (i.tm.cpu_flags.bitfield.cpusse4_2
-                   && !i.tm.cpu_flags.bitfield.cpuabm));
-      if (opc_3b)
+
+      switch (i.tm.opcode_length)
        {
+       case 3:
          if (i.tm.base_opcode & 0xff000000)
            {
              prefix = (i.tm.base_opcode >> 24) & 0xff;
              goto check_prefix;
            }
-       }
-      else if ((i.tm.base_opcode & 0xff0000) != 0)
-       {
-         prefix = (i.tm.base_opcode >> 16) & 0xff;
-         if (i.tm.cpu_flags.bitfield.cpupadlock)
+         break;
+       case 2:
+         if ((i.tm.base_opcode & 0xff0000) != 0)
            {
-           check_prefix:
-             if (prefix != REPE_PREFIX_OPCODE
-                 || i.prefix[LOCKREP_PREFIX] != REPE_PREFIX_OPCODE)
+             prefix = (i.tm.base_opcode >> 16) & 0xff;
+             if (i.tm.cpu_flags.bitfield.cpupadlock)
+               {
+check_prefix:
+                 if (prefix != REPE_PREFIX_OPCODE
+                     || i.prefix[LOCKREP_PREFIX] != REPE_PREFIX_OPCODE)
+                   add_prefix (prefix);
+               }
+             else
                add_prefix (prefix);
            }
-         else
-           add_prefix (prefix);
+         break;
+       case 1:
+         break;
+       default:
+         abort ();
        }
 
       /* The prefix bytes.  */
-      for (q = i.prefix;
-          q < i.prefix + sizeof (i.prefix) / sizeof (i.prefix[0]);
-          q++)
-       {
-         if (*q)
-           {
-             p = frag_more (1);
-             md_number_to_chars (p, (valueT) *q, 1);
-           }
-       }
+      for (j = ARRAY_SIZE (i.prefix), q = i.prefix; j > 0; j--, q++)
+       if (*q)
+         FRAG_APPEND_1_CHAR (*q);
 
       /* Now the opcode; be careful about word order here!  */
-      if (fits_in_unsigned_byte (i.tm.base_opcode))
+      if (i.tm.opcode_length == 1)
        {
          FRAG_APPEND_1_CHAR (i.tm.base_opcode);
        }
       else
        {
-         if (opc_3b)
+         switch (i.tm.opcode_length)
            {
+           case 3:
              p = frag_more (3);
              *p++ = (i.tm.base_opcode >> 16) & 0xff;
+             break;
+           case 2:
+             p = frag_more (2);
+             break;
+           default:
+             abort ();
+             break;
            }
-         else
-           p = frag_more (2);
 
          /* Put out high byte first: can't use md_number_to_chars!  */
          *p++ = (i.tm.base_opcode >> 8) & 0xff;
@@ -5047,12 +5279,9 @@ output_insn (void)
       /* Now the modrm byte and sib byte (if present).  */
       if (i.tm.opcode_modifier.modrm)
        {
-         p = frag_more (1);
-         md_number_to_chars (p,
-                             (valueT) (i.rm.regmem << 0
-                                       | i.rm.reg << 3
-                                       | i.rm.mode << 6),
-                             1);
+         FRAG_APPEND_1_CHAR ((i.rm.regmem << 0
+                              | i.rm.reg << 3
+                              | i.rm.mode << 6));
          /* If i.rm.regmem == ESP (4)
             && i.rm.mode != (Register mode)
             && not 16 bit
@@ -5060,14 +5289,9 @@ output_insn (void)
          if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING
              && i.rm.mode != 3
              && !(i.base_reg && i.base_reg->reg_type.bitfield.reg16))
-           {
-             p = frag_more (1);
-             md_number_to_chars (p,
-                                 (valueT) (i.sib.base << 0
-                                           | i.sib.index << 3
-                                           | i.sib.scale << 6),
-                                 1);
-           }
+           FRAG_APPEND_1_CHAR ((i.sib.base << 0
+                                | i.sib.index << 3
+                                | i.sib.scale << 6));
        }
 
       /* Write the DREX byte if needed.  */
@@ -5467,7 +5691,7 @@ lex_got (enum bfd_reloc_code_real *reloc,
     if (is_end_of_line[(unsigned char) *cp] || *cp == ',')
       return NULL;
 
-  for (j = 0; j < sizeof (gotrel) / sizeof (gotrel[0]); j++)
+  for (j = 0; j < ARRAY_SIZE (gotrel); j++)
     {
       int len;
 
@@ -5741,9 +5965,7 @@ i386_scale (char *scale)
     {
       as_warn (_("scale factor of %d without an index register"),
               1 << i.log2_scale_factor);
-#if SCALE1_WHEN_NO_INDEX
       i.log2_scale_factor = 0;
-#endif
     }
   scale = input_line_pointer;
   input_line_pointer = save;
@@ -5977,12 +6199,16 @@ i386_index_check (const char *operand_string)
               || (i.prefix[ADDR_PREFIX]
                   && !i.base_reg->reg_type.bitfield.reg32))
           && (i.index_reg
-              || !UINTS_EQUAL (i.base_reg->reg_type, baseindex)))
+              || i.base_reg->reg_num !=
+                 (i.prefix[ADDR_PREFIX] == 0 ? RegRip : RegEip)))
          || (i.index_reg
              && (!i.index_reg->reg_type.bitfield.baseindex
                  || (i.prefix[ADDR_PREFIX] == 0
-                     && !i.index_reg->reg_type.bitfield.reg64)
+                     && i.index_reg->reg_num != RegRiz
+                     && !i.index_reg->reg_type.bitfield.reg64
+                     )
                  || (i.prefix[ADDR_PREFIX]
+                     && i.index_reg->reg_num != RegEiz
                      && !i.index_reg->reg_type.bitfield.reg32))))
        ok = 0;
     }
@@ -6009,7 +6235,8 @@ i386_index_check (const char *operand_string)
          if ((i.base_reg
               && !i.base_reg->reg_type.bitfield.reg32)
              || (i.index_reg
-                 && (!i.index_reg->reg_type.bitfield.reg32
+                 && ((!i.index_reg->reg_type.bitfield.reg32
+                      && i.index_reg->reg_num != RegEiz)
                      || !i.index_reg->reg_type.bitfield.baseindex)))
            ok = 0;
        }
@@ -6050,7 +6277,7 @@ i386_index_check (const char *operand_string)
    on error.  */
 
 static int
-i386_operand (char *operand_string)
+i386_att_operand (char *operand_string)
 {
   const reg_entry *r;
   char *end_op;
@@ -6137,6 +6364,7 @@ i386_operand (char *operand_string)
       temp.bitfield.baseindex = 0;
       i.types[this_operand] = operand_type_or (i.types[this_operand],
                                               temp);
+      i.types[this_operand].bitfield.unspecified = 0;
       i.op[this_operand].regs = r;
       i.reg_operands++;
     }
@@ -6329,6 +6557,7 @@ i386_operand (char *operand_string)
 
       if (i386_index_check (operand_string) == 0)
        return 0;
+      i.types[this_operand].bitfield.mem = 1;
       i.mem_operands++;
     }
   else
@@ -6576,41 +6805,6 @@ md_convert_frag (abfd, sec, fragP)
   fragP->fr_fix += extension;
 }
 \f
-/* Size of byte displacement jmp.  */
-int md_short_jump_size = 2;
-
-/* Size of dword displacement jmp.  */
-int md_long_jump_size = 5;
-
-void
-md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
-     char *ptr;
-     addressT from_addr, to_addr;
-     fragS *frag ATTRIBUTE_UNUSED;
-     symbolS *to_symbol ATTRIBUTE_UNUSED;
-{
-  offsetT offset;
-
-  offset = to_addr - (from_addr + 2);
-  /* Opcode for byte-disp jump.  */
-  md_number_to_chars (ptr, (valueT) 0xeb, 1);
-  md_number_to_chars (ptr + 1, (valueT) offset, 1);
-}
-
-void
-md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
-     char *ptr;
-     addressT from_addr, to_addr;
-     fragS *frag ATTRIBUTE_UNUSED;
-     symbolS *to_symbol ATTRIBUTE_UNUSED;
-{
-  offsetT offset;
-
-  offset = to_addr - (from_addr + 5);
-  md_number_to_chars (ptr, (valueT) 0xe9, 1);
-  md_number_to_chars (ptr + 1, (valueT) offset, 4);
-}
-\f
 /* Apply a fixup (fixS) to segment data, once it has been determined
    by our caller that we have all the info we need to fix it up.
 
@@ -6773,58 +6967,12 @@ md_apply_fix (fixP, valP, seg)
   md_number_to_chars (p, value, fixP->fx_size);
 }
 \f
-#define MAX_LITTLENUMS 6
-
-/* Turn the string pointed to by litP into a floating point constant
-   of type TYPE, and emit the appropriate bytes.  The number of
-   LITTLENUMS emitted is stored in *SIZEP.  An error message is
-   returned, or NULL on OK.  */
-
 char *
-md_atof (type, litP, sizeP)
-     int type;
-     char *litP;
-     int *sizeP;
+md_atof (int type, char *litP, int *sizeP)
 {
-  int prec;
-  LITTLENUM_TYPE words[MAX_LITTLENUMS];
-  LITTLENUM_TYPE *wordP;
-  char *t;
-
-  switch (type)
-    {
-    case 'f':
-    case 'F':
-      prec = 2;
-      break;
-
-    case 'd':
-    case 'D':
-      prec = 4;
-      break;
-
-    case 'x':
-    case 'X':
-      prec = 5;
-      break;
-
-    default:
-      *sizeP = 0;
-      return _("Bad call to md_atof ()");
-    }
-  t = atof_ieee (input_line_pointer, type, words);
-  if (t)
-    input_line_pointer = t;
-
-  *sizeP = prec * sizeof (LITTLENUM_TYPE);
-  /* This loops outputs the LITTLENUMs in REVERSE order; in accord with
-     the bigendian 386.  */
-  for (wordP = words + prec - 1; prec--;)
-    {
-      md_number_to_chars (litP, (valueT) (*wordP--), sizeof (LITTLENUM_TYPE));
-      litP += sizeof (LITTLENUM_TYPE);
-    }
-  return 0;
+  /* This outputs the LITTLENUMs in REVERSE order;
+     in accord with the bigendian 386.  */
+  return ieee_md_atof (type, litP, sizeP, FALSE);
 }
 \f
 static char output_invalid_buf[sizeof (unsigned char) * 2 + 6];
@@ -6905,6 +7053,12 @@ parse_real_register (char *reg_string, char **end_op)
        }
     }
 
+  /* Don't allow fake index register unless allow_index_reg isn't 0. */
+  if (r != NULL
+      && !allow_index_reg
+      && (r->reg_num == RegEiz || r->reg_num == RegRiz))
+    return (const reg_entry *) NULL;
+
   if (r != NULL
       && ((r->reg_flags & (RegRex64 | RegRex))
          || r->reg_type.bitfield.reg64)
@@ -7002,6 +7156,11 @@ const char *md_shortopts = "qn";
 #define OPTION_DIVIDE (OPTION_MD_BASE + 2)
 #define OPTION_MARCH (OPTION_MD_BASE + 3)
 #define OPTION_MTUNE (OPTION_MD_BASE + 4)
+#define OPTION_MMNEMONIC (OPTION_MD_BASE + 5)
+#define OPTION_MSYNTAX (OPTION_MD_BASE + 6)
+#define OPTION_MINDEX_REG (OPTION_MD_BASE + 7)
+#define OPTION_MNAKED_REG (OPTION_MD_BASE + 8)
+#define OPTION_MOLD_GCC (OPTION_MD_BASE + 9)
 
 struct option md_longopts[] =
 {
@@ -7012,6 +7171,11 @@ struct option md_longopts[] =
   {"divide", no_argument, NULL, OPTION_DIVIDE},
   {"march", required_argument, NULL, OPTION_MARCH},
   {"mtune", required_argument, NULL, OPTION_MTUNE},
+  {"mmnemonic", required_argument, NULL, OPTION_MMNEMONIC},
+  {"msyntax", required_argument, NULL, OPTION_MSYNTAX},
+  {"mindex-reg", no_argument, NULL, OPTION_MINDEX_REG},
+  {"mnaked-reg", no_argument, NULL, OPTION_MNAKED_REG},
+  {"mold-gcc", no_argument, NULL, OPTION_MOLD_GCC},
   {NULL, no_argument, NULL, 0}
 };
 size_t md_longopts_size = sizeof (md_longopts);
@@ -7020,6 +7184,7 @@ int
 md_parse_option (int c, char *arg)
 {
   unsigned int i;
+  char *arch, *next;
 
   switch (c)
     {
@@ -7095,24 +7260,62 @@ md_parse_option (int c, char *arg)
       break;
 
     case OPTION_MARCH:
-      if (*arg == '.')
-       as_fatal (_("Invalid -march= option: `%s'"), arg);
-      for (i = 0; i < ARRAY_SIZE (cpu_arch); i++)
-       {
-         if (strcmp (arg, cpu_arch [i].name) == 0)
+      arch = xstrdup (arg);
+      do
+       {
+         if (*arch == '.')
+           as_fatal (_("Invalid -march= option: `%s'"), arg);
+         next = strchr (arch, '+');
+         if (next)
+           *next++ = '\0';
+         for (i = 0; i < ARRAY_SIZE (cpu_arch); i++)
            {
-             cpu_arch_isa = cpu_arch[i].type;
-             cpu_arch_isa_flags = cpu_arch[i].flags;
-             if (!cpu_arch_tune_set)
+             if (strcmp (arch, cpu_arch [i].name) == 0)
                {
-                 cpu_arch_tune = cpu_arch_isa;
-                 cpu_arch_tune_flags = cpu_arch_isa_flags;
+                 /* Processor.  */
+                 cpu_arch_name = cpu_arch[i].name;
+                 cpu_sub_arch_name = NULL;
+                 cpu_arch_flags = cpu_arch[i].flags;
+                 cpu_arch_isa = cpu_arch[i].type;
+                 cpu_arch_isa_flags = cpu_arch[i].flags;
+                 if (!cpu_arch_tune_set)
+                   {
+                     cpu_arch_tune = cpu_arch_isa;
+                     cpu_arch_tune_flags = cpu_arch_isa_flags;
+                   }
+                 break;
+               }
+             else if (*cpu_arch [i].name == '.'
+                      && strcmp (arch, cpu_arch [i].name + 1) == 0)
+               {
+                 /* ISA entension.  */
+                 i386_cpu_flags flags;
+                 flags = cpu_flags_or (cpu_arch_flags,
+                                       cpu_arch[i].flags);
+                 if (!UINTS_EQUAL (flags, cpu_arch_flags))
+                   {
+                     if (cpu_sub_arch_name)
+                       {
+                         char *name = cpu_sub_arch_name;
+                         cpu_sub_arch_name = concat (name,
+                                                     cpu_arch[i].name,
+                                                     NULL);
+                         free (name);
+                       }
+                     else
+                       cpu_sub_arch_name = xstrdup (cpu_arch[i].name);
+                     cpu_arch_flags = flags;
+                   }
+                 break;
                }
-             break;
            }
+
+         if (i >= ARRAY_SIZE (cpu_arch))
+           as_fatal (_("Invalid -march= option: `%s'"), arg);
+
+         arch = next;
        }
-      if (i >= ARRAY_SIZE (cpu_arch))
-       as_fatal (_("Invalid -march= option: `%s'"), arg);
+      while (next != NULL );
       break;
 
     case OPTION_MTUNE:
@@ -7132,6 +7335,36 @@ md_parse_option (int c, char *arg)
        as_fatal (_("Invalid -mtune= option: `%s'"), arg);
       break;
 
+    case OPTION_MMNEMONIC:
+      if (strcasecmp (arg, "att") == 0)
+       intel_mnemonic = 0;
+      else if (strcasecmp (arg, "intel") == 0)
+       intel_mnemonic = 1;
+      else
+       as_fatal (_("Invalid -mmnemonic= option: `%s'"), arg);
+      break;
+
+    case OPTION_MSYNTAX:
+      if (strcasecmp (arg, "att") == 0)
+       intel_syntax = 0;
+      else if (strcasecmp (arg, "intel") == 0)
+       intel_syntax = 1;
+      else
+       as_fatal (_("Invalid -msyntax= option: `%s'"), arg);
+      break;
+
+    case OPTION_MINDEX_REG:
+      allow_index_reg = 1;
+      break;
+
+    case OPTION_MNAKED_REG:
+      allow_naked_reg = 1;
+      break;
+
+    case OPTION_MOLD_GCC:
+      old_gcc = 1;
+      break;
+
     default:
       return 0;
     }
@@ -7167,10 +7400,28 @@ md_show_usage (stream)
   --divide                ignored\n"));
 #endif
   fprintf (stream, _("\
-  -march=CPU/-mtune=CPU   generate code/optimize for CPU, where CPU is one of:\n\
+  -march=CPU[,+EXTENSION...]\n\
+                          generate code for CPU and EXTENSION, CPU is one of:\n\
+                           i386, i486, pentium, pentiumpro, pentium4, nocona,\n\
+                           core, core2, k6, athlon, k8, generic32, generic64\n\
+                         EXTENSION is combination of:\n\
+                          mmx, sse, sse2, sse3, ssse3, sse4.1, sse4.2, sse4,\n\
+                          vmx, smx, 3dnow, 3dnowa, sse4a, sse5, svme, abm,\n\
+                          padlock\n"));
+  fprintf (stream, _("\
+  -mtune=CPU              optimize for CPU, where CPU is one of:\n\
                            i386, i486, pentium, pentiumpro, pentium4, nocona,\n\
                            core, core2, k6, athlon, k8, generic32, generic64\n"));
-
+  fprintf (stream, _("\
+  -mmnemonic=[att|intel]  use AT&T/Intel mnemonic\n"));
+  fprintf (stream, _("\
+  -msyntax=[att|intel]    use AT&T/Intel syntax\n"));
+  fprintf (stream, _("\
+  -mindex-reg             support pseudo index registers\n"));
+  fprintf (stream, _("\
+  -mnaked-reg             don't require `%%' prefix for registers\n"));
+  fprintf (stream, _("\
+  -mold-gcc               support old (<= 2.8.1) versions of gcc\n"));
 }
 
 #if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \
@@ -7836,6 +8087,7 @@ i386_intel_operand (char *operand_string, int got_a_float)
          else
            {
              char *s = intel_parser.disp;
+             i.types[this_operand].bitfield.mem = 1;
              i.mem_operands++;
 
              if (!quiet_warnings && intel_parser.is_mem < 0)
@@ -7878,6 +8130,7 @@ i386_intel_operand (char *operand_string, int got_a_float)
        break;
       intel_parser.op_string = intel_parser.next_operand;
       this_operand = i.operands++;
+      i.types[this_operand].bitfield.unspecified = 1;
     }
 
   free (p);
@@ -8086,7 +8339,10 @@ intel_e09 (void)
          char suffix;
 
          if (prev_token.code == T_BYTE)
-           suffix = BYTE_MNEM_SUFFIX;
+           {
+             suffix = BYTE_MNEM_SUFFIX;
+             i.types[this_operand].bitfield.byte = 1;
+           }
 
          else if (prev_token.code == T_WORD)
            {
@@ -8098,6 +8354,7 @@ intel_e09 (void)
                suffix = SHORT_MNEM_SUFFIX;
              else
                suffix = WORD_MNEM_SUFFIX;
+             i.types[this_operand].bitfield.word = 1;
            }
 
          else if (prev_token.code == T_DWORD)
@@ -8114,6 +8371,7 @@ intel_e09 (void)
                suffix = SHORT_MNEM_SUFFIX;
              else
                suffix = LONG_MNEM_SUFFIX;
+             i.types[this_operand].bitfield.dword = 1;
            }
 
          else if (prev_token.code == T_FWORD)
@@ -8130,6 +8388,7 @@ intel_e09 (void)
                }
              else
                suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */
+             i.types[this_operand].bitfield.fword = 1;
            }
 
          else if (prev_token.code == T_QWORD)
@@ -8137,7 +8396,8 @@ intel_e09 (void)
              if (intel_parser.got_a_float == 1)        /* "f..." */
                suffix = LONG_MNEM_SUFFIX;
              else
-               suffix = QWORD_MNEM_SUFFIX;
+                 suffix = QWORD_MNEM_SUFFIX;
+             i.types[this_operand].bitfield.qword = 1;
            }
 
          else if (prev_token.code == T_TBYTE)
@@ -8150,8 +8410,8 @@ intel_e09 (void)
 
          else if (prev_token.code == T_XMMWORD)
            {
-             /* XXX ignored for now, but accepted since gcc uses it */
-             suffix = 0;
+             suffix = XMMWORD_MNEM_SUFFIX;
+             i.types[this_operand].bitfield.xmmword = 1;
            }
 
          else
@@ -8160,6 +8420,8 @@ intel_e09 (void)
              return 0;
            }
 
+         i.types[this_operand].bitfield.unspecified = 0;
+
          /* Operands for jump/call using 'ptr' notation denote absolute
             addresses.  */
          if (current_templates->start->opcode_modifier.jump
@@ -8490,6 +8752,7 @@ intel_e11 (void)
            temp.bitfield.baseindex = 0;
            i.types[this_operand] = operand_type_or (i.types[this_operand],
                                                     temp);
+           i.types[this_operand].bitfield.unspecified = 0;
            i.op[this_operand].regs = reg;
            i.reg_operands++;
          }
This page took 0.044447 seconds and 4 git commands to generate.