2007-09-04 H.J. Lu <hongjiu.lu@intel.com>
[deliverable/binutils-gdb.git] / gas / config / tc-i386.c
index cfebda03d06024d92b2904873c674227d0a21e44..9a39d4309b8bdb22ff287a943a9c2642276612b9 100644 (file)
@@ -1,13 +1,13 @@
-/* i386.c -- Assemble code for the Intel 80386
+/* 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
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GAS is distributed in the hope that it will be useful,
@@ -32,7 +32,6 @@
 #include "subsegs.h"
 #include "dwarf2dbg.h"
 #include "dw2gencfi.h"
-#include "opcode/i386.h"
 #include "elf/x86-64.h"
 
 #ifndef REGISTER_WARNINGS
 #endif
 #endif
 
-static INLINE unsigned int mode_from_disp_size PARAMS ((unsigned int));
-static INLINE int fits_in_signed_byte PARAMS ((offsetT));
-static INLINE int fits_in_unsigned_byte PARAMS ((offsetT));
-static INLINE int fits_in_unsigned_word PARAMS ((offsetT));
-static INLINE int fits_in_signed_word PARAMS ((offsetT));
-static INLINE int fits_in_unsigned_long PARAMS ((offsetT));
-static INLINE int fits_in_signed_long PARAMS ((offsetT));
-static int smallest_imm_type PARAMS ((offsetT));
-static offsetT offset_in_range PARAMS ((offsetT, int));
-static int add_prefix PARAMS ((unsigned int));
-static void set_code_flag PARAMS ((int));
-static void set_16bit_gcc_code_flag PARAMS ((int));
-static void set_intel_syntax PARAMS ((int));
-static void set_cpu_arch PARAMS ((int));
+static void set_code_flag (int);
+static void set_16bit_gcc_code_flag (int);
+static void set_intel_syntax (int);
+static void set_cpu_arch (int);
 #ifdef TE_PE
-static void pe_directive_secrel PARAMS ((int));
+static void pe_directive_secrel (int);
 #endif
-static void signed_cons PARAMS ((int));
-static char *output_invalid PARAMS ((int c));
-static int i386_operand PARAMS ((char *operand_string));
-static int i386_intel_operand PARAMS ((char *operand_string, int got_a_float));
-static const reg_entry *parse_register PARAMS ((char *reg_string,
-                                               char **end_op));
-static char *parse_insn PARAMS ((char *, char *));
-static char *parse_operands PARAMS ((char *, const char *));
-static void swap_operands PARAMS ((void));
-static void optimize_imm PARAMS ((void));
-static void optimize_disp PARAMS ((void));
-static int match_template PARAMS ((void));
-static int check_string PARAMS ((void));
-static int process_suffix PARAMS ((void));
-static int check_byte_reg PARAMS ((void));
-static int check_long_reg PARAMS ((void));
-static int check_qword_reg PARAMS ((void));
-static int check_word_reg PARAMS ((void));
-static int finalize_imm PARAMS ((void));
-static int process_operands PARAMS ((void));
-static const seg_entry *build_modrm_byte PARAMS ((void));
-static void output_insn PARAMS ((void));
-static void output_branch PARAMS ((void));
-static void output_jump PARAMS ((void));
-static void output_interseg_jump PARAMS ((void));
-static void output_imm PARAMS ((fragS *insn_start_frag,
-                               offsetT insn_start_off));
-static void output_disp PARAMS ((fragS *insn_start_frag,
-                                offsetT insn_start_off));
+static void signed_cons (int);
+static char *output_invalid (int c);
+static int i386_operand (char *);
+static int i386_intel_operand (char *, int);
+static const reg_entry *parse_register (char *, char **);
+static char *parse_insn (char *, char *);
+static char *parse_operands (char *, const char *);
+static void swap_operands (void);
+static void swap_2_operands (int, int);
+static void optimize_imm (void);
+static void optimize_disp (void);
+static int match_template (void);
+static int check_string (void);
+static int process_suffix (void);
+static int check_byte_reg (void);
+static int check_long_reg (void);
+static int check_qword_reg (void);
+static int check_word_reg (void);
+static int finalize_imm (void);
+static int process_operands (void);
+static const seg_entry *build_modrm_byte (void);
+static void output_insn (void);
+static void output_imm (fragS *, offsetT);
+static void output_disp (fragS *, offsetT);
 #ifndef I386COFF
-static void s_bss PARAMS ((int));
+static void s_bss (int);
 #endif
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
 static void handle_large_common (int small ATTRIBUTE_UNUSED);
@@ -271,8 +255,9 @@ static i386_insn i;
 /* Possible templates for current insn.  */
 static const templates *current_templates;
 
-/* Per instruction expressionS buffers: 2 displacements & 2 immediate max.  */
-static expressionS disp_expressions[2], im_expressions[2];
+/* Per instruction expressionS buffers: max displacements & immediates.  */
+static expressionS disp_expressions[MAX_MEMORY_OPERANDS];
+static expressionS im_expressions[MAX_IMMEDIATE_OPERANDS];
 
 /* Current operand we are working on.  */
 static int this_operand;
@@ -305,6 +290,9 @@ static int intel_syntax = 0;
 /* 1 if register prefix % not required.  */
 static int allow_naked_reg = 0;
 
+/* Register prefix used for error message.  */
+static const char *register_prefix = "%";
+
 /* Used in 16 bit gcc mode to add an l suffix to call, ret, enter,
    leave, push, and pop instructions so that gcc has the same stack
    frame as in 32 bit mode.  */
@@ -323,6 +311,21 @@ static const char *cpu_sub_arch_name = NULL;
 /* CPU feature flags.  */
 static unsigned int cpu_arch_flags = CpuUnknownFlags | CpuNo64;
 
+/* If we have selected a cpu we are generating instructions for.  */
+static int cpu_arch_tune_set = 0;
+
+/* Cpu we are generating instructions for.  */
+static enum processor_type cpu_arch_tune = PROCESSOR_UNKNOWN;
+
+/* CPU feature flags of cpu we are generating instructions for.  */
+static unsigned int cpu_arch_tune_flags = 0;
+
+/* CPU instruction set architecture used.  */
+static enum processor_type cpu_arch_isa = PROCESSOR_UNKNOWN;
+
+/* CPU feature flags of instruction set architecture used.  */
+static unsigned int cpu_arch_isa_flags = 0;
+
 /* If set, conditional jumps are not automatically promoted to handle
    larger than a byte offset.  */
 static unsigned int no_cond_jump_promotion = 0;
@@ -415,35 +418,106 @@ const relax_typeS md_relax_table[] =
   {0, 0, 4, 0}
 };
 
-static const arch_entry cpu_arch[] = {
-  {"i8086",    Cpu086 },
-  {"i186",     Cpu086|Cpu186 },
-  {"i286",     Cpu086|Cpu186|Cpu286 },
-  {"i386",     Cpu086|Cpu186|Cpu286|Cpu386 },
-  {"i486",     Cpu086|Cpu186|Cpu286|Cpu386|Cpu486 },
-  {"i586",     Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586 },
-  {"i686",     Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686 },
-  {"pentium",  Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586 },
-  {"pentiumpro",Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686 },
-  {"pentiumii",        Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX },
-  {"pentiumiii",Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX|CpuMMX2|CpuSSE },
-  {"pentium4", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2 },
-  {"prescott", Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuPNI },
-  {"k6",       Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuK6|CpuMMX },
-  {"k6_2",     Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuK6|CpuMMX|Cpu3dnow },
-  {"athlon",   Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuAthlon|CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA },
-  {"sledgehammer",Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuAthlon|CpuSledgehammer|CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2 },
-  {"opteron",  Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuAthlon|CpuSledgehammer|CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2 },
-  {".mmx",     CpuMMX },
-  {".sse",     CpuMMX|CpuMMX2|CpuSSE },
-  {".sse2",    CpuMMX|CpuMMX2|CpuSSE|CpuSSE2 },
-  {".sse3",    CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3 },
-  {".3dnow",   CpuMMX|Cpu3dnow },
-  {".3dnowa",  CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA },
-  {".padlock", CpuPadLock },
-  {".pacifica",        CpuSVME },
-  {".svme",    CpuSVME },
-  {NULL, 0 }
+static const arch_entry cpu_arch[] =
+{
+  {"generic32", PROCESSOR_GENERIC32,
+   Cpu186|Cpu286|Cpu386},
+  {"generic64", PROCESSOR_GENERIC64,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX
+   |CpuMMX2|CpuSSE|CpuSSE2},
+  {"i8086", PROCESSOR_UNKNOWN,
+   0},
+  {"i186", PROCESSOR_UNKNOWN,
+   Cpu186},
+  {"i286", PROCESSOR_UNKNOWN,
+   Cpu186|Cpu286},
+  {"i386", PROCESSOR_I386,
+   Cpu186|Cpu286|Cpu386},
+  {"i486", PROCESSOR_I486,
+   Cpu186|Cpu286|Cpu386|Cpu486},
+  {"i586", PROCESSOR_PENTIUM,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586},
+  {"i686", PROCESSOR_PENTIUMPRO,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686},
+  {"pentium", PROCESSOR_PENTIUM,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586},
+  {"pentiumpro",PROCESSOR_PENTIUMPRO,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686},
+  {"pentiumii",        PROCESSOR_PENTIUMPRO,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX},
+  {"pentiumiii",PROCESSOR_PENTIUMPRO,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuMMX|CpuMMX2|CpuSSE},
+  {"pentium4", PROCESSOR_PENTIUM4,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX
+   |CpuMMX2|CpuSSE|CpuSSE2},
+  {"prescott", PROCESSOR_NOCONA,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX
+   |CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3},
+  {"nocona", PROCESSOR_NOCONA,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX
+   |CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3},
+  {"yonah", PROCESSOR_CORE,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX
+   |CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3},
+  {"core", PROCESSOR_CORE,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX
+   |CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3},
+  {"merom", PROCESSOR_CORE2,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX
+   |CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3},
+  {"core2", PROCESSOR_CORE2,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuMMX
+   |CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3},
+  {"k6", PROCESSOR_K6,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuK6|CpuMMX},
+  {"k6_2", PROCESSOR_K6,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuK6|CpuMMX|Cpu3dnow},
+  {"athlon", PROCESSOR_ATHLON,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6
+   |CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA},
+  {"sledgehammer", PROCESSOR_K8,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6
+   |CpuSledgehammer|CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2},
+  {"opteron", PROCESSOR_K8,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6
+   |CpuSledgehammer|CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2},
+  {"k8", PROCESSOR_K8,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6
+   |CpuSledgehammer|CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2},
+  {"amdfam10", PROCESSOR_AMDFAM10,
+   Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuK6|CpuSledgehammer
+   |CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a
+   |CpuABM},
+  {".mmx", PROCESSOR_UNKNOWN,
+   CpuMMX},
+  {".sse", PROCESSOR_UNKNOWN,
+   CpuMMX|CpuMMX2|CpuSSE},
+  {".sse2", PROCESSOR_UNKNOWN,
+   CpuMMX|CpuMMX2|CpuSSE|CpuSSE2},
+  {".sse3", PROCESSOR_UNKNOWN,
+   CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3},
+  {".ssse3", PROCESSOR_UNKNOWN,
+   CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3},
+  {".sse4.1", PROCESSOR_UNKNOWN,
+   CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4_1},
+  {".sse4.2", PROCESSOR_UNKNOWN,
+   CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4},
+  {".sse4", PROCESSOR_UNKNOWN,
+   CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSSE3|CpuSSE4},
+  {".3dnow", PROCESSOR_UNKNOWN,
+   CpuMMX|Cpu3dnow},
+  {".3dnowa", PROCESSOR_UNKNOWN,
+   CpuMMX|CpuMMX2|Cpu3dnow|Cpu3dnowA},
+  {".padlock", PROCESSOR_UNKNOWN,
+   CpuPadLock},
+  {".pacifica", PROCESSOR_UNKNOWN,
+   CpuSVME},
+  {".svme", PROCESSOR_UNKNOWN,
+   CpuSVME},
+  {".sse4a", PROCESSOR_UNKNOWN,
+   CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuSSE4a},
+  {".abm", PROCESSOR_UNKNOWN,
+   CpuABM}
 };
 
 const pseudo_typeS md_pseudo_table[] =
@@ -473,7 +547,7 @@ const pseudo_typeS md_pseudo_table[] =
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
   {"largecomm", handle_large_common, 0},
 #else
-  {"file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0},
+  {"file", (void (*) (int)) dwarf2_directive_file, 0},
   {"loc", dwarf2_directive_loc, 0},
   {"loc_mark_labels", dwarf2_directive_loc_mark_labels, 0},
 #endif
@@ -493,9 +567,7 @@ static struct hash_control *op_hash;
 static struct hash_control *reg_hash;
 \f
 void
-i386_align_code (fragP, count)
-     fragS *fragP;
-     int count;
+i386_align_code (fragS *fragP, int count)
 {
   /* Various efficient no-op patterns for aligning code labels.
      Note: Don't try to assemble the instructions in the comments.
@@ -503,7 +575,7 @@ i386_align_code (fragP, count)
   static const char f32_1[] =
     {0x90};                                    /* nop                  */
   static const char f32_2[] =
-    {0x89,0xf6};                               /* movl %esi,%esi       */
+    {0x66,0x90};                               /* xchg %ax,%ax */
   static const char f32_3[] =
     {0x8d,0x76,0x00};                          /* leal 0(%esi),%esi    */
   static const char f32_4[] =
@@ -536,9 +608,6 @@ i386_align_code (fragP, count)
   static const char f32_14[] =
     {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00,       /* leal 0L(%esi,1),%esi */
      0x8d,0xbc,0x27,0x00,0x00,0x00,0x00};      /* leal 0L(%edi,1),%edi */
-  static const char f32_15[] =
-    {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90,       /* jmp .+15; lotsa nops */
-     0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90};
   static const char f16_3[] =
     {0x8d,0x74,0x00};                          /* lea 0(%esi),%esi     */
   static const char f16_4[] =
@@ -555,93 +624,307 @@ i386_align_code (fragP, count)
   static const char f16_8[] =
     {0x8d,0xb4,0x00,0x00,                      /* lea 0w(%si),%si      */
      0x8d,0xbd,0x00,0x00};                     /* lea 0w(%di),%di      */
+  static const char jump_31[] =
+    {0xeb,0x1d,0x90,0x90,0x90,0x90,0x90,       /* jmp .+31; lotsa nops */
+     0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,
+     0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,
+     0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90};
   static const char *const f32_patt[] = {
     f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8,
-    f32_9, f32_10, f32_11, f32_12, f32_13, f32_14, f32_15
+    f32_9, f32_10, f32_11, f32_12, f32_13, f32_14
   };
   static const char *const f16_patt[] = {
-    f32_1, f32_2, f16_3, f16_4, f16_5, f16_6, f16_7, f16_8,
-    f32_15, f32_15, f32_15, f32_15, f32_15, f32_15, f32_15
+    f32_1, f32_2, f16_3, f16_4, f16_5, f16_6, f16_7, f16_8
+  };
+  /* nopl (%[re]ax) */
+  static const char alt_3[] =
+    {0x0f,0x1f,0x00};
+  /* nopl 0(%[re]ax) */
+  static const char alt_4[] =
+    {0x0f,0x1f,0x40,0x00};
+  /* nopl 0(%[re]ax,%[re]ax,1) */
+  static const char alt_5[] =
+    {0x0f,0x1f,0x44,0x00,0x00};
+  /* nopw 0(%[re]ax,%[re]ax,1) */
+  static const char alt_6[] =
+    {0x66,0x0f,0x1f,0x44,0x00,0x00};
+  /* nopl 0L(%[re]ax) */
+  static const char alt_7[] =
+    {0x0f,0x1f,0x80,0x00,0x00,0x00,0x00};
+  /* nopl 0L(%[re]ax,%[re]ax,1) */
+  static const char alt_8[] =
+    {0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
+  /* nopw 0L(%[re]ax,%[re]ax,1) */
+  static const char alt_9[] =
+    {0x66,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
+  /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
+  static const char alt_10[] =
+    {0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
+  /* data16
+     nopw %cs:0L(%[re]ax,%[re]ax,1) */
+  static const char alt_long_11[] =
+    {0x66,
+     0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
+  /* data16
+     data16
+     nopw %cs:0L(%[re]ax,%[re]ax,1) */
+  static const char alt_long_12[] =
+    {0x66,
+     0x66,
+     0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
+  /* data16
+     data16
+     data16
+     nopw %cs:0L(%[re]ax,%[re]ax,1) */
+  static const char alt_long_13[] =
+    {0x66,
+     0x66,
+     0x66,
+     0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
+  /* data16
+     data16
+     data16
+     data16
+     nopw %cs:0L(%[re]ax,%[re]ax,1) */
+  static const char alt_long_14[] =
+    {0x66,
+     0x66,
+     0x66,
+     0x66,
+     0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
+  /* data16
+     data16
+     data16
+     data16
+     data16
+     nopw %cs:0L(%[re]ax,%[re]ax,1) */
+  static const char alt_long_15[] =
+    {0x66,
+     0x66,
+     0x66,
+     0x66,
+     0x66,
+     0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
+  /* nopl 0(%[re]ax,%[re]ax,1)
+     nopw 0(%[re]ax,%[re]ax,1) */
+  static const char alt_short_11[] =
+    {0x0f,0x1f,0x44,0x00,0x00,
+     0x66,0x0f,0x1f,0x44,0x00,0x00};
+  /* nopw 0(%[re]ax,%[re]ax,1)
+     nopw 0(%[re]ax,%[re]ax,1) */
+  static const char alt_short_12[] =
+    {0x66,0x0f,0x1f,0x44,0x00,0x00,
+     0x66,0x0f,0x1f,0x44,0x00,0x00};
+  /* nopw 0(%[re]ax,%[re]ax,1)
+     nopl 0L(%[re]ax) */
+  static const char alt_short_13[] =
+    {0x66,0x0f,0x1f,0x44,0x00,0x00,
+     0x0f,0x1f,0x80,0x00,0x00,0x00,0x00};
+  /* nopl 0L(%[re]ax)
+     nopl 0L(%[re]ax) */
+  static const char alt_short_14[] =
+    {0x0f,0x1f,0x80,0x00,0x00,0x00,0x00,
+     0x0f,0x1f,0x80,0x00,0x00,0x00,0x00};
+  /* nopl 0L(%[re]ax)
+     nopl 0L(%[re]ax,%[re]ax,1) */
+  static const char alt_short_15[] =
+    {0x0f,0x1f,0x80,0x00,0x00,0x00,0x00,
+     0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00};
+  static const char *const alt_short_patt[] = {
+    f32_1, f32_2, alt_3, alt_4, alt_5, alt_6, alt_7, alt_8,
+    alt_9, alt_10, alt_short_11, alt_short_12, alt_short_13,
+    alt_short_14, alt_short_15
+  };
+  static const char *const alt_long_patt[] = {
+    f32_1, f32_2, alt_3, alt_4, alt_5, alt_6, alt_7, alt_8,
+    alt_9, alt_10, alt_long_11, alt_long_12, alt_long_13,
+    alt_long_14, alt_long_15
   };
 
-  if (count <= 0 || count > 15)
+  /* Only align for at least a positive non-zero boundary. */
+  if (count <= 0 || count > MAX_MEM_FOR_RS_ALIGN_CODE)
     return;
 
-  /* The recommended way to pad 64bit code is to use NOPs preceded by
-     maximally four 0x66 prefixes.  Balance the size of nops.  */
-  if (flag_code == CODE_64BIT)
+  /* We need to decide which NOP sequence to use for 32bit and
+     64bit. When -mtune= is used:
+
+     1. For PROCESSOR_I386, PROCESSOR_I486, PROCESSOR_PENTIUM and
+     PROCESSOR_GENERIC32, f32_patt will be used.
+     2. For PROCESSOR_PENTIUMPRO, PROCESSOR_PENTIUM4, PROCESSOR_NOCONA,
+     PROCESSOR_CORE, PROCESSOR_CORE2, and PROCESSOR_GENERIC64,
+     alt_long_patt will be used.
+     3. For PROCESSOR_ATHLON, PROCESSOR_K6, PROCESSOR_K8 and
+     PROCESSOR_AMDFAM10, alt_short_patt will be used.
+
+     When -mtune= isn't used, alt_long_patt will be used if
+     cpu_arch_isa_flags has Cpu686. Otherwise, f32_patt will
+     be used.
+
+     When -march= or .arch is used, we can't use anything beyond
+     cpu_arch_isa_flags.   */
+
+  if (flag_code == CODE_16BIT)
     {
-      int i;
-      int nnops = (count + 3) / 4;
-      int len = count / nnops;
-      int remains = count - nnops * len;
-      int pos = 0;
+      if (count > 8)
+       {
+         memcpy (fragP->fr_literal + fragP->fr_fix,
+                 jump_31, count);
+         /* Adjust jump offset.  */
+         fragP->fr_literal[fragP->fr_fix + 1] = count - 2;
+       }
+      else
+       memcpy (fragP->fr_literal + fragP->fr_fix,
+               f16_patt[count - 1], count);
+    }
+  else
+    {
+      const char *const *patt = NULL;
 
-      for (i = 0; i < remains; i++)
+      if (cpu_arch_isa == PROCESSOR_UNKNOWN)
        {
-         memset (fragP->fr_literal + fragP->fr_fix + pos, 0x66, len);
-         fragP->fr_literal[fragP->fr_fix + pos + len] = 0x90;
-         pos += len + 1;
+         /* PROCESSOR_UNKNOWN means that all ISAs may be used.  */
+         switch (cpu_arch_tune)
+           {
+           case PROCESSOR_UNKNOWN:
+             /* We use cpu_arch_isa_flags to check if we SHOULD
+                optimize for Cpu686.  */
+             if ((cpu_arch_isa_flags & Cpu686) != 0)
+               patt = alt_long_patt;
+             else
+               patt = f32_patt;
+             break;
+           case PROCESSOR_PENTIUMPRO:
+           case PROCESSOR_PENTIUM4:
+           case PROCESSOR_NOCONA:
+           case PROCESSOR_CORE:
+           case PROCESSOR_CORE2:
+           case PROCESSOR_GENERIC64:
+             patt = alt_long_patt;
+             break;
+           case PROCESSOR_K6:
+           case PROCESSOR_ATHLON:
+           case PROCESSOR_K8:
+           case PROCESSOR_AMDFAM10:
+             patt = alt_short_patt;
+             break;
+           case PROCESSOR_I386:
+           case PROCESSOR_I486:
+           case PROCESSOR_PENTIUM:
+           case PROCESSOR_GENERIC32:
+             patt = f32_patt;
+             break;
+           }
        }
-      for (; i < nnops; i++)
+      else
        {
-         memset (fragP->fr_literal + fragP->fr_fix + pos, 0x66, len - 1);
-         fragP->fr_literal[fragP->fr_fix + pos + len - 1] = 0x90;
-         pos += len;
+         switch (cpu_arch_tune)
+           {
+           case PROCESSOR_UNKNOWN:
+             /* When cpu_arch_isa is net, cpu_arch_tune shouldn't be
+                PROCESSOR_UNKNOWN.  */
+             abort ();
+             break;
+
+           case PROCESSOR_I386:
+           case PROCESSOR_I486:
+           case PROCESSOR_PENTIUM:
+           case PROCESSOR_K6:
+           case PROCESSOR_ATHLON:
+           case PROCESSOR_K8:
+           case PROCESSOR_AMDFAM10:
+           case PROCESSOR_GENERIC32:
+             /* We use cpu_arch_isa_flags to check if we CAN optimize
+                for Cpu686.  */
+             if ((cpu_arch_isa_flags & Cpu686) != 0)
+               patt = alt_short_patt;
+             else
+               patt = f32_patt;
+             break;
+           case PROCESSOR_PENTIUMPRO:
+           case PROCESSOR_PENTIUM4:
+           case PROCESSOR_NOCONA:
+           case PROCESSOR_CORE:
+           case PROCESSOR_CORE2:
+             if ((cpu_arch_isa_flags & Cpu686) != 0)
+               patt = alt_long_patt;
+             else
+               patt = f32_patt;
+             break;
+           case PROCESSOR_GENERIC64:
+             patt = alt_long_patt;
+             break;
+           }
+       }
+
+      if (patt == f32_patt)
+       {
+         /* If the padding is less than 15 bytes, we use the normal
+            ones.  Otherwise, we use a jump instruction and adjust
+            its offset.  */
+         if (count < 15)
+           memcpy (fragP->fr_literal + fragP->fr_fix,
+                   patt[count - 1], count);
+         else
+           {
+             memcpy (fragP->fr_literal + fragP->fr_fix,
+                     jump_31, count);
+             /* Adjust jump offset.  */
+             fragP->fr_literal[fragP->fr_fix + 1] = count - 2;
+           }
+       }
+      else
+       {
+         /* Maximum length of an instruction is 15 byte.  If the
+            padding is greater than 15 bytes and we don't use jump,
+            we have to break it into smaller pieces.  */
+         int padding = count;
+         while (padding > 15)
+           {
+             padding -= 15;
+             memcpy (fragP->fr_literal + fragP->fr_fix + padding,
+                     patt [14], 15);
+           }
+
+         if (padding)
+           memcpy (fragP->fr_literal + fragP->fr_fix,
+                   patt [padding - 1], padding);
        }
     }
-  else
-    if (flag_code == CODE_16BIT)
-      {
-       memcpy (fragP->fr_literal + fragP->fr_fix,
-               f16_patt[count - 1], count);
-       if (count > 8)
-         /* Adjust jump offset.  */
-         fragP->fr_literal[fragP->fr_fix + 1] = count - 2;
-      }
-    else
-      memcpy (fragP->fr_literal + fragP->fr_fix,
-             f32_patt[count - 1], count);
   fragP->fr_var = count;
 }
 
 static INLINE unsigned int
-mode_from_disp_size (t)
-     unsigned int t;
+mode_from_disp_size (unsigned int t)
 {
   return (t & Disp8) ? 1 : (t & (Disp16 | Disp32 | Disp32S)) ? 2 : 0;
 }
 
 static INLINE int
-fits_in_signed_byte (num)
-     offsetT num;
+fits_in_signed_byte (offsetT num)
 {
   return (num >= -128) && (num <= 127);
 }
 
 static INLINE int
-fits_in_unsigned_byte (num)
-     offsetT num;
+fits_in_unsigned_byte (offsetT num)
 {
   return (num & 0xff) == num;
 }
 
 static INLINE int
-fits_in_unsigned_word (num)
-     offsetT num;
+fits_in_unsigned_word (offsetT num)
 {
   return (num & 0xffff) == num;
 }
 
 static INLINE int
-fits_in_signed_word (num)
-     offsetT num;
+fits_in_signed_word (offsetT num)
 {
   return (-32768 <= num) && (num <= 32767);
 }
+
 static INLINE int
-fits_in_signed_long (num)
-     offsetT num ATTRIBUTE_UNUSED;
+fits_in_signed_long (offsetT num ATTRIBUTE_UNUSED)
 {
 #ifndef BFD64
   return 1;
@@ -650,9 +933,9 @@ fits_in_signed_long (num)
          || (((offsetT) -1 << 31) & num) == ((offsetT) -1 << 31));
 #endif
 }                              /* fits_in_signed_long() */
+
 static INLINE int
-fits_in_unsigned_long (num)
-     offsetT num ATTRIBUTE_UNUSED;
+fits_in_unsigned_long (offsetT num ATTRIBUTE_UNUSED)
 {
 #ifndef BFD64
   return 1;
@@ -661,11 +944,10 @@ fits_in_unsigned_long (num)
 #endif
 }                              /* fits_in_unsigned_long() */
 
-static int
-smallest_imm_type (num)
-     offsetT num;
+static unsigned int
+smallest_imm_type (offsetT num)
 {
-  if (cpu_arch_flags != (Cpu086 | Cpu186 | Cpu286 | Cpu386 | Cpu486 | CpuNo64))
+  if (cpu_arch_flags != (Cpu186 | Cpu286 | Cpu386 | Cpu486 | CpuNo64))
     {
       /* This code is disabled on the 486 because all the Imm1 forms
         in the opcode table are slower on the i486.  They're the
@@ -689,9 +971,7 @@ smallest_imm_type (num)
 }
 
 static offsetT
-offset_in_range (val, size)
-     offsetT val;
-     int size;
+offset_in_range (offsetT val, int size)
 {
   addressT mask;
 
@@ -726,8 +1006,7 @@ offset_in_range (val, size)
    class already exists, 1 if non rep/repne added, 2 if rep/repne
    added.  */
 static int
-add_prefix (prefix)
-     unsigned int prefix;
+add_prefix (unsigned int prefix)
 {
   int ret = 1;
   unsigned int q;
@@ -735,9 +1014,9 @@ add_prefix (prefix)
   if (prefix >= REX_OPCODE && prefix < REX_OPCODE + 16
       && flag_code == CODE_64BIT)
     {
-      if ((i.prefix[REX_PREFIX] & prefix & REX_MODE64)
-         || ((i.prefix[REX_PREFIX] & (REX_EXTX | REX_EXTY | REX_EXTZ))
-             && (prefix & (REX_EXTX | REX_EXTY | REX_EXTZ))))
+      if ((i.prefix[REX_PREFIX] & prefix & REX_W)
+         || ((i.prefix[REX_PREFIX] & (REX_R | REX_X | REX_B))
+             && (prefix & (REX_R | REX_X | REX_B))))
        ret = 0;
       q = REX_PREFIX;
     }
@@ -794,8 +1073,7 @@ add_prefix (prefix)
 }
 
 static void
-set_code_flag (value)
-     int value;
+set_code_flag (int value)
 {
   flag_code = value;
   cpu_arch_flags &= ~(Cpu64 | CpuNo64);
@@ -812,8 +1090,7 @@ set_code_flag (value)
 }
 
 static void
-set_16bit_gcc_code_flag (new_code_flag)
-     int new_code_flag;
+set_16bit_gcc_code_flag (int new_code_flag)
 {
   flag_code = new_code_flag;
   cpu_arch_flags &= ~(Cpu64 | CpuNo64);
@@ -822,8 +1099,7 @@ set_16bit_gcc_code_flag (new_code_flag)
 }
 
 static void
-set_intel_syntax (syntax_flag)
-     int syntax_flag;
+set_intel_syntax (int syntax_flag)
 {
   /* Find out if register prefixing is specified.  */
   int ask_naked_reg = 0;
@@ -854,11 +1130,11 @@ set_intel_syntax (syntax_flag)
 
   identifier_chars['%'] = intel_syntax && allow_naked_reg ? '%' : 0;
   identifier_chars['$'] = intel_syntax ? '$' : 0;
+  register_prefix = allow_naked_reg ? "" : "%";
 }
 
 static void
-set_cpu_arch (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+set_cpu_arch (int dummy ATTRIBUTE_UNUSED)
 {
   SKIP_WHITESPACE ();
 
@@ -866,9 +1142,9 @@ set_cpu_arch (dummy)
     {
       char *string = input_line_pointer;
       int e = get_symbol_end ();
-      int i;
+      unsigned int i;
 
-      for (i = 0; cpu_arch[i].name; i++)
+      for (i = 0; i < ARRAY_SIZE (cpu_arch); i++)
        {
          if (strcmp (string, cpu_arch[i].name) == 0)
            {
@@ -877,7 +1153,15 @@ set_cpu_arch (dummy)
                  cpu_arch_name = cpu_arch[i].name;
                  cpu_sub_arch_name = NULL;
                  cpu_arch_flags = (cpu_arch[i].flags
-                                   | (flag_code == CODE_64BIT ? Cpu64 : CpuNo64));
+                                   | (flag_code == CODE_64BIT
+                                      ? Cpu64 : CpuNo64));
+                 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;
                }
              if ((cpu_arch_flags | cpu_arch[i].flags) != cpu_arch_flags)
@@ -890,7 +1174,7 @@ set_cpu_arch (dummy)
              return;
            }
        }
-      if (!cpu_arch[i].name)
+      if (i >= ARRAY_SIZE (cpu_arch))
        as_bad (_("no such architecture: `%s'"), string);
 
       *input_line_pointer = e;
@@ -976,10 +1260,9 @@ md_begin ()
   reg_hash = hash_new ();
   {
     const reg_entry *regtab;
+    unsigned int regtab_size = i386_regtab_size;
 
-    for (regtab = i386_regtab;
-        regtab < i386_regtab + sizeof (i386_regtab) / sizeof (i386_regtab[0]);
-        regtab++)
+    for (regtab = i386_regtab; regtab_size--; regtab++)
       {
        hash_err = hash_insert (reg_hash, regtab->reg_name, (PTR) regtab);
        if (hash_err)
@@ -1034,6 +1317,7 @@ md_begin ()
 #endif
     digit_chars['-'] = '-';
     mnemonic_chars['-'] = '-';
+    mnemonic_chars['.'] = '.';
     identifier_chars['_'] = '_';
     identifier_chars['.'] = '.';
 
@@ -1063,8 +1347,7 @@ md_begin ()
 }
 
 void
-i386_print_statistics (file)
-     FILE *file;
+i386_print_statistics (FILE *file)
 {
   hash_print_statistics (file, "i386 opcode", op_hash);
   hash_print_statistics (file, "i386 register", reg_hash);
@@ -1073,16 +1356,13 @@ i386_print_statistics (file)
 #ifdef DEBUG386
 
 /* Debugging routines for md_assemble.  */
-static void pi PARAMS ((char *, i386_insn *));
-static void pte PARAMS ((template *));
-static void pt PARAMS ((unsigned int));
-static void pe PARAMS ((expressionS *));
-static void ps PARAMS ((symbolS *));
+static void pte (template *);
+static void pt (unsigned int);
+static void pe (expressionS *);
+static void ps (symbolS *);
 
 static void
-pi (line, x)
-     char *line;
-     i386_insn *x;
+pi (char *line, i386_insn *x)
 {
   unsigned int i;
 
@@ -1097,10 +1377,10 @@ pi (line, x)
   fprintf (stdout, "  sib:  base %x  index %x  scale %x\n",
           x->sib.base, x->sib.index, x->sib.scale);
   fprintf (stdout, "  rex: 64bit %x  extX %x  extY %x  extZ %x\n",
-          (x->rex & REX_MODE64) != 0,
-          (x->rex & REX_EXTX) != 0,
-          (x->rex & REX_EXTY) != 0,
-          (x->rex & REX_EXTZ) != 0);
+          (x->rex & REX_W) != 0,
+          (x->rex & REX_R) != 0,
+          (x->rex & REX_X) != 0,
+          (x->rex & REX_B) != 0);
   for (i = 0; i < x->operands; i++)
     {
       fprintf (stdout, "    #%d:  ", i + 1);
@@ -1117,8 +1397,7 @@ pi (line, x)
 }
 
 static void
-pte (t)
-     template *t;
+pte (template *t)
 {
   unsigned int i;
   fprintf (stdout, " %d operands ", t->operands);
@@ -1139,8 +1418,7 @@ pte (t)
 }
 
 static void
-pe (e)
-     expressionS *e;
+pe (expressionS *e)
 {
   fprintf (stdout, "    operation     %d\n", e->X_op);
   fprintf (stdout, "    add_number    %ld (%lx)\n",
@@ -1160,8 +1438,7 @@ pe (e)
 }
 
 static void
-ps (s)
-     symbolS *s;
+ps (symbolS *s)
 {
   fprintf (stdout, "%s type %s%s",
           S_GET_NAME (s),
@@ -1324,8 +1601,7 @@ reloc (unsigned int size,
    some cases we force the original symbol to be used.  */
 
 int
-tc_i386_fix_adjustable (fixP)
-     fixS *fixP ATTRIBUTE_UNUSED;
+tc_i386_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED)
 {
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
   if (!IS_ELF)
@@ -1378,11 +1654,8 @@ tc_i386_fix_adjustable (fixP)
   return 1;
 }
 
-static int intel_float_operand PARAMS ((const char *mnemonic));
-
 static int
-intel_float_operand (mnemonic)
-     const char *mnemonic;
+intel_float_operand (const char *mnemonic)
 {
   /* Note that the value returned is meaningful only for opcodes with (memory)
      operands, hence the code here is free to improperly handle opcodes that
@@ -1465,16 +1738,29 @@ md_assemble (line)
   if (line == NULL)
     return;
 
+  /* The order of the immediates should be reversed
+     for 2 immediates extrq and insertq instructions */
+  if ((i.imm_operands == 2)
+      && ((strcmp (mnemonic, "extrq") == 0)
+         || (strcmp (mnemonic, "insertq") == 0)))
+    {
+      swap_2_operands (0, 1);
+      /* "extrq" and insertq" are the only two instructions whose operands
+        have to be reversed even though they have two immediate operands.
+      */
+      if (intel_syntax)
+       swap_operands ();
+    }
+
   /* 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.  "enter" and the
-     intersegment "jmp" and "call" instructions are the only ones that
-     have two immediate operands.  */
-  if (intel_syntax && i.operands > 1
+     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)
       && !((i.types[0] & Imm) && (i.types[1] & Imm)))
@@ -1502,7 +1788,7 @@ md_assemble (line)
       /* Undo SYSV386_COMPAT brokenness when in Intel mode.  See i386.h  */
       if (SYSV386_COMPAT
          && (i.tm.base_opcode & 0xfffffde0) == 0xdce0)
-       i.tm.base_opcode ^= FloatR;
+       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
@@ -1556,9 +1842,9 @@ md_assemble (line)
     {
       expressionS *exp;
 
-      if ((i.tm.cpu_flags & CpuPNI) && i.operands > 0)
+      if ((i.tm.cpu_flags & CpuSSE3) && i.operands > 0)
        {
-         /* These Intel Prescott New Instructions have the fixed
+         /* Streaming SIMD extensions 3 Instructions have the fixed
             operands with an opcode suffix which is coded in the same
             place as an 8-bit immediate field would be. Here we check
             those operands and remove them afterwards.  */
@@ -1566,8 +1852,11 @@ md_assemble (line)
 
          for (x = 0; x < i.operands; x++)
            if (i.op[x].regs->reg_num != x)
-             as_bad (_("can't use register '%%%s' as operand %d in '%s'."),
-                     i.op[x].regs->reg_name, x + 1, i.tm.name);
+             as_bad (_("can't use register '%s%s' as operand %d in '%s'."),
+                     register_prefix,
+                     i.op[x].regs->reg_name,
+                     x + 1,
+                     i.tm.name);
          i.operands = 0;
        }
 
@@ -1616,7 +1905,7 @@ md_assemble (line)
     }
 
   if ((i.tm.opcode_modifier & Rex64) != 0)
-    i.rex |= REX_MODE64;
+    i.rex |= REX_W;
 
   /* For 8 bit registers we need an empty rex prefix.  Also if the
      instruction already has a prefix, we need to convert old
@@ -1640,8 +1929,9 @@ md_assemble (line)
            {
              /* In case it is "hi" register, give up.  */
              if (i.op[x].regs->reg_num > 3)
-               as_bad (_("can't encode register '%%%s' in an instruction requiring REX prefix."),
-                       i.op[x].regs->reg_name);
+               as_bad (_("can't encode register '%s%s' in an "
+                         "instruction requiring REX prefix."),
+                       register_prefix, i.op[x].regs->reg_name);
 
              /* Otherwise it is equivalent to the extended register.
                 Since the encoding doesn't change this is merely
@@ -1660,9 +1950,7 @@ md_assemble (line)
 }
 
 static char *
-parse_insn (line, mnemonic)
-     char *line;
-     char *mnemonic;
+parse_insn (char *line, char *mnemonic)
 {
   char *l = line;
   char *token_start = l;
@@ -1881,9 +2169,7 @@ parse_insn (line, mnemonic)
 }
 
 static char *
-parse_operands (l, mnemonic)
-     char *l;
-     const char *mnemonic;
+parse_operands (char *l, const char *mnemonic)
 {
   char *token_start;
 
@@ -2001,24 +2287,12 @@ parse_operands (l, mnemonic)
 }
 
 static void
-swap_operands ()
+swap_2_operands (int xchg1, int xchg2)
 {
   union i386_op temp_op;
   unsigned int temp_type;
   enum bfd_reloc_code_real temp_reloc;
-  int xchg1 = 0;
-  int xchg2 = 0;
 
-  if (i.operands == 2)
-    {
-      xchg1 = 0;
-      xchg2 = 1;
-    }
-  else if (i.operands == 3)
-    {
-      xchg1 = 0;
-      xchg2 = 2;
-    }
   temp_type = i.types[xchg2];
   i.types[xchg2] = i.types[xchg1];
   i.types[xchg1] = temp_type;
@@ -2028,6 +2302,22 @@ swap_operands ()
   temp_reloc = i.reloc[xchg2];
   i.reloc[xchg2] = i.reloc[xchg1];
   i.reloc[xchg1] = temp_reloc;
+}
+
+static void
+swap_operands (void)
+{
+  switch (i.operands)
+    {
+    case 4:
+      swap_2_operands (1, i.operands - 2);
+    case 3:
+    case 2:
+      swap_2_operands (0, i.operands - 1);
+      break;
+    default:
+      abort ();
+    }
 
   if (i.mem_operands == 2)
     {
@@ -2041,7 +2331,7 @@ swap_operands ()
 /* Try to ensure constant immediates are represented in the smallest
    opcode possible.  */
 static void
-optimize_imm ()
+optimize_imm (void)
 {
   char guess_suffix = 0;
   int op;
@@ -2131,8 +2421,10 @@ optimize_imm ()
              unsigned int mask, allowed = 0;
              const template *t;
 
-             for (t = current_templates->start; t < current_templates->end; ++t)
-               allowed |= t->operand_types[op];
+             for (t = current_templates->start;
+                  t < current_templates->end;
+                  ++t)
+               allowed |= t->operand_types[op];
              switch (guess_suffix)
                {
                case QWORD_MNEM_SUFFIX:
@@ -2161,7 +2453,7 @@ optimize_imm ()
 
 /* Try to use the smallest displacement type too.  */
 static void
-optimize_disp ()
+optimize_disp (void)
 {
   int op;
 
@@ -2225,13 +2517,20 @@ optimize_disp ()
 }
 
 static int
-match_template ()
+match_template (void)
 {
   /* Points to template once we've found it.  */
   const template *t;
-  unsigned int overlap0, overlap1, overlap2;
+  unsigned int overlap0, overlap1, overlap2, overlap3;
   unsigned int found_reverse_match;
   int suffix_check;
+  unsigned int operand_types [MAX_OPERANDS];
+  int addr_prefix_disp;
+  unsigned int j;
+
+#if MAX_OPERANDS != 4
+# error "MAX_OPERANDS must be 4."
+#endif
 
 #define MATCH(overlap, given, template)                                \
   ((overlap & ~JumpAbsolute)                                   \
@@ -2249,7 +2548,11 @@ match_template ()
   overlap0 = 0;
   overlap1 = 0;
   overlap2 = 0;
+  overlap3 = 0;
   found_reverse_match = 0;
+  for (j = 0; j < MAX_OPERANDS; j++)
+    operand_types [j] = 0;
+  addr_prefix_disp = -1;
   suffix_check = (i.suffix == BYTE_MNEM_SUFFIX
                  ? No_bSuf
                  : (i.suffix == WORD_MNEM_SUFFIX
@@ -2265,6 +2568,8 @@ match_template ()
 
   for (t = current_templates->start; t < current_templates->end; t++)
     {
+      addr_prefix_disp = -1;
+
       /* Must have right number of operands.  */
       if (i.operands != t->operands)
        continue;
@@ -2275,6 +2580,9 @@ match_template ()
               && (t->opcode_modifier & IgnoreSize)))
        continue;
 
+      for (j = 0; j < MAX_OPERANDS; 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
          && flag_code != CODE_64BIT
@@ -2282,8 +2590,8 @@ match_template ()
              ? (!(t->opcode_modifier & IgnoreSize)
                 && !intel_float_operand (t->name))
              : intel_float_operand (t->name) != 2)
-         && (!(t->operand_types[0] & (RegMMX | RegXMM))
-             || !(t->operand_types[t->operands > 1] & (RegMMX | RegXMM)))
+         && (!(operand_types[0] & (RegMMX | RegXMM))
+             || !(operand_types[t->operands > 1] & (RegMMX | RegXMM)))
          && (t->base_opcode != 0x0fc7
              || t->extension_opcode != 1 /* cmpxchg8b */))
        continue;
@@ -2297,66 +2605,142 @@ match_template ()
          break;
        }
 
-      overlap0 = i.types[0] & t->operand_types[0];
+      /* Address size prefix will turn Disp64/Disp32/Disp16 operand
+        into Disp32/Disp16/Disp32 operand.  */
+      if (i.prefix[ADDR_PREFIX] != 0)
+         {
+           unsigned int DispOn = 0, DispOff = 0;
+
+           switch (flag_code)
+           {
+           case CODE_16BIT:
+             DispOn = Disp32;
+             DispOff = Disp16;
+             break;
+           case CODE_32BIT:
+             DispOn = Disp16;
+             DispOff = Disp32;
+             break;
+           case CODE_64BIT:
+             DispOn = Disp32;
+             DispOff = Disp64;
+             break;
+           }
+
+           for (j = 0; j < MAX_OPERANDS; j++)
+             {
+               /* There should be only one Disp operand.  */
+               if ((operand_types[j] & DispOff))
+                 {
+                   addr_prefix_disp = j;
+                   operand_types[j] |= DispOn;
+                   operand_types[j] &= ~DispOff;
+                   break;
+                 }
+             }
+         }
+
+      overlap0 = i.types[0] & operand_types[0];
       switch (t->operands)
        {
        case 1:
-         if (!MATCH (overlap0, i.types[0], t->operand_types[0]))
+         if (!MATCH (overlap0, i.types[0], operand_types[0]))
            continue;
          break;
        case 2:
+         /* xchg %eax, %eax is a special case. It is an aliase for nop
+            only in 32bit mode and we can use opcode 0x90.  In 64bit
+            mode, we can't use 0x90 for xchg %eax, %eax since it should
+            zero-extend %eax to %rax.  */
+         if (flag_code == CODE_64BIT
+             && t->base_opcode == 0x90
+             && i.types [0] == (Acc | Reg32)
+             && i.types [1] == (Acc | Reg32))
+           continue;
        case 3:
-         overlap1 = i.types[1] & t->operand_types[1];
-         if (!MATCH (overlap0, i.types[0], t->operand_types[0])
-             || !MATCH (overlap1, i.types[1], t->operand_types[1])
+       case 4:
+         overlap1 = i.types[1] & operand_types[1];
+         if (!MATCH (overlap0, i.types[0], operand_types[0])
+             || !MATCH (overlap1, i.types[1], operand_types[1])
              /* monitor in SSE3 is a very special case.  The first
                 register and the second register may have different
-                sizes.  */
+                sizes.  The same applies to crc32 in SSE4.2.  */
              || !((t->base_opcode == 0x0f01
                    && t->extension_opcode == 0xc8)
+                  || t->base_opcode == 0xf20f38f1
                   || CONSISTENT_REGISTER_MATCH (overlap0, i.types[0],
-                                                t->operand_types[0],
+                                                operand_types[0],
                                                 overlap1, i.types[1],
-                                                t->operand_types[1])))
+                                                operand_types[1])))
            {
              /* Check if other direction is valid ...  */
              if ((t->opcode_modifier & (D | FloatD)) == 0)
                continue;
 
              /* Try reversing direction of operands.  */
-             overlap0 = i.types[0] & t->operand_types[1];
-             overlap1 = i.types[1] & t->operand_types[0];
-             if (!MATCH (overlap0, i.types[0], t->operand_types[1])
-                 || !MATCH (overlap1, i.types[1], t->operand_types[0])
+             overlap0 = i.types[0] & operand_types[1];
+             overlap1 = i.types[1] & operand_types[0];
+             if (!MATCH (overlap0, i.types[0], operand_types[1])
+                 || !MATCH (overlap1, i.types[1], operand_types[0])
                  || !CONSISTENT_REGISTER_MATCH (overlap0, i.types[0],
-                                                t->operand_types[1],
+                                                operand_types[1],
                                                 overlap1, i.types[1],
-                                                t->operand_types[0]))
+                                                operand_types[0]))
                {
                  /* Does not match either direction.  */
                  continue;
                }
              /* found_reverse_match holds which of D or FloatDR
                 we've found.  */
-             found_reverse_match = t->opcode_modifier & (D | FloatDR);
+             if ((t->opcode_modifier & D))
+               found_reverse_match = Opcode_D;
+             else if ((t->opcode_modifier & FloatD))
+               found_reverse_match = Opcode_FloatD;
+             else
+               found_reverse_match = 0;
+             if ((t->opcode_modifier & FloatR))
+               found_reverse_match |= Opcode_FloatR;
            }
-         /* Found a forward 2 operand match here.  */
-         else if (t->operands == 3)
+         else
            {
-             /* Here we make use of the fact that there are no
-                reverse match 3 operand instructions, and all 3
-                operand instructions only need to be checked for
-                register consistency between operands 2 and 3.  */
-             overlap2 = i.types[2] & t->operand_types[2];
-             if (!MATCH (overlap2, i.types[2], t->operand_types[2])
-                 || !CONSISTENT_REGISTER_MATCH (overlap1, i.types[1],
-                                                t->operand_types[1],
-                                                overlap2, i.types[2],
-                                                t->operand_types[2]))
+             /* Found a forward 2 operand match here.  */
+             switch (t->operands)
+               {
+               case 4:
+                 overlap3 = i.types[3] & operand_types[3];
+               case 3:
+                 overlap2 = i.types[2] & operand_types[2];
+                 break;
+               }
 
-               continue;
+             switch (t->operands)
+               {
+               case 4:
+                 if (!MATCH (overlap3, i.types[3], operand_types[3])
+                     || !CONSISTENT_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
+                    reverse match 3 operand instructions, and all 3
+                    operand instructions only need to be checked for
+                    register consistency between operands 2 and 3.  */
+                 if (!MATCH (overlap2, i.types[2], operand_types[2])
+                     || !CONSISTENT_REGISTER_MATCH (overlap1,
+                                                    i.types[1],
+                                                    operand_types[1],
+                                                    overlap2,
+                                                    i.types[2],
+                                                    operand_types[2]))
+                   continue;
+                 break;
+               }
            }
-         /* Found either forward/reverse 2 or 3 operand match here:
+         /* Found either forward/reverse 2, 3 or 4 operand match here:
             slip through to break.  */
        }
       if (t->cpu_flags & ~cpu_arch_flags)
@@ -2380,7 +2764,7 @@ match_template ()
     {
       if (!intel_syntax
          && ((i.types[0] & JumpAbsolute)
-             != (t->operand_types[0] & JumpAbsolute)))
+             != (operand_types[0] & JumpAbsolute)))
        {
          as_warn (_("indirect %s without `*'"), t->name);
        }
@@ -2396,6 +2780,11 @@ match_template ()
 
   /* Copy the template we found.  */
   i.tm = *t;
+
+  if (addr_prefix_disp != -1)
+    i.tm.operand_types[addr_prefix_disp]
+      = operand_types[addr_prefix_disp];
+
   if (found_reverse_match)
     {
       /* If we found a reverse match we must alter the opcode
@@ -2404,15 +2793,15 @@ match_template ()
 
       i.tm.base_opcode ^= found_reverse_match;
 
-      i.tm.operand_types[0] = t->operand_types[1];
-      i.tm.operand_types[1] = t->operand_types[0];
+      i.tm.operand_types[0] = operand_types[1];
+      i.tm.operand_types[1] = operand_types[0];
     }
 
   return 1;
 }
 
 static int
-check_string ()
+check_string (void)
 {
   int mem_op = (i.types[0] & AnyMem) ? 0 : 1;
   if ((i.tm.operand_types[mem_op] & EsSeg) != 0)
@@ -2465,19 +2854,44 @@ process_suffix (void)
        {
          /* We take i.suffix from the last register operand specified,
             Destination register type is more significant than source
-            register type.  */
-         int op;
-
-         for (op = i.operands; --op >= 0;)
-           if ((i.types[op] & Reg)
-               && !(i.tm.operand_types[op] & InOutPortReg))
-             {
-               i.suffix = ((i.types[op] & Reg8) ? BYTE_MNEM_SUFFIX :
-                           (i.types[op] & Reg16) ? WORD_MNEM_SUFFIX :
-                           (i.types[op] & Reg64) ? QWORD_MNEM_SUFFIX :
+            register type.  crc32 in SSE4.2 prefers source register
+            type. */
+         if (i.tm.base_opcode == 0xf20f38f1)
+           {
+             if ((i.types[0] & Reg))
+               i.suffix = ((i.types[0] & Reg16) ? WORD_MNEM_SUFFIX :
                            LONG_MNEM_SUFFIX);
-               break;
-             }
+           }
+         else if (i.tm.base_opcode == 0xf20f38f0)
+           {
+             if ((i.types[0] & Reg8))
+               i.suffix = BYTE_MNEM_SUFFIX;
+           }
+
+         if (!i.suffix)
+           {
+             int op;
+
+             if (i.tm.base_opcode == 0xf20f38f1
+                 || i.tm.base_opcode == 0xf20f38f0)
+               {
+                 /* We have to know the operand size for crc32.  */
+                 as_bad (_("ambiguous memory operand size for `%s`"),
+                         i.tm.name);
+                 return 0;
+               }
+
+             for (op = i.operands; --op >= 0;)
+               if ((i.types[op] & Reg)
+                   && !(i.tm.operand_types[op] & InOutPortReg))
+                 {
+                   i.suffix = ((i.types[op] & Reg8) ? BYTE_MNEM_SUFFIX :
+                               (i.types[op] & Reg16) ? WORD_MNEM_SUFFIX :
+                               (i.types[op] & Reg64) ? QWORD_MNEM_SUFFIX :
+                               LONG_MNEM_SUFFIX);
+                   break;
+                 }
+           }
        }
       else if (i.suffix == BYTE_MNEM_SUFFIX)
        {
@@ -2544,7 +2958,8 @@ process_suffix (void)
        {
          if (i.tm.opcode_modifier & W)
            {
-             as_bad (_("no instruction mnemonic suffix given and no register operands; can't size instruction"));
+             as_bad (_("no instruction mnemonic suffix given and "
+                       "no register operands; can't size instruction"));
              return 0;
            }
        }
@@ -2615,7 +3030,21 @@ process_suffix (void)
       if (i.suffix == QWORD_MNEM_SUFFIX
          && flag_code == CODE_64BIT
          && (i.tm.opcode_modifier & NoRex64) == 0)
-       i.rex |= REX_MODE64;
+       {
+         /* Special case for xchg %rax,%rax.  It is NOP and doesn't
+            need rex64.  cmpxchg8b is also a special case. */
+         if (! (i.operands == 2
+                && i.tm.base_opcode == 0x90
+                && i.tm.extension_opcode == None
+                && i.types [0] == (Acc | Reg64)
+                && i.types [1] == (Acc | Reg64))
+             && ! (i.operands == 1
+                   && i.tm.base_opcode == 0xfc7
+                   && i.tm.extension_opcode == 1
+                   && (i.types [0] & Reg) == 0
+                   && (i.types [0] & AnyMem) != 0))
+           i.rex |= REX_W;
+       }
 
       /* Size floating point instruction.  */
       if (i.suffix == LONG_MNEM_SUFFIX)
@@ -2639,13 +3068,20 @@ check_byte_reg (void)
       if (i.types[op] & Reg8)
        continue;
 
-      /* movzx and movsx should not generate this warning.  */
+      /* 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 == 0xfbf
+             || i.tm.base_opcode == 0x660f3a14
+             || i.tm.base_opcode == 0x660f3a20))
+       continue;
+
+      /* crc32 doesn't generate this warning.  */
+      if (i.tm.base_opcode == 0xf20f38f0)
        continue;
 
       if ((i.types[op] & WordReg) && i.op[op].regs->reg_num < 4)
@@ -2655,18 +3091,20 @@ check_byte_reg (void)
          if (flag_code == CODE_64BIT
              && (i.tm.operand_types[op] & InOutPortReg) == 0)
            {
-             as_bad (_("Incorrect register `%%%s' used with `%c' suffix"),
-                     i.op[op].regs->reg_name,
+             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
          if (!quiet_warnings
              && (i.tm.operand_types[op] & InOutPortReg) == 0)
-           as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"),
+           as_warn (_("using `%s%s' instead of `%s%s' due to `%c' suffix"),
+                    register_prefix,
                     (i.op[op].regs + (i.types[op] & Reg16
                                       ? REGNAM_AL - REGNAM_AX
                                       : REGNAM_AL - REGNAM_EAX))->reg_name,
+                    register_prefix,
                     i.op[op].regs->reg_name,
                     i.suffix);
 #endif
@@ -2678,7 +3116,8 @@ check_byte_reg (void)
                         | Control | Debug | Test
                         | FloatReg | FloatAcc))
        {
-         as_bad (_("`%%%s' not allowed with `%s%c'"),
+         as_bad (_("`%s%s' not allowed with `%s%c'"),
+                 register_prefix,
                  i.op[op].regs->reg_name,
                  i.tm.name,
                  i.suffix);
@@ -2689,7 +3128,7 @@ check_byte_reg (void)
 }
 
 static int
-check_long_reg ()
+check_long_reg (void)
 {
   int op;
 
@@ -2699,7 +3138,8 @@ check_long_reg ()
     if ((i.types[op] & Reg8) != 0
        && (i.tm.operand_types[op] & (Reg16 | Reg32 | Acc)) != 0)
       {
-       as_bad (_("`%%%s' not allowed with `%s%c'"),
+       as_bad (_("`%s%s' not allowed with `%s%c'"),
+               register_prefix,
                i.op[op].regs->reg_name,
                i.tm.name,
                i.suffix);
@@ -2714,15 +3154,17 @@ check_long_reg ()
           lowering is more complicated.  */
        if (flag_code == CODE_64BIT)
          {
-           as_bad (_("Incorrect register `%%%s' used with `%c' suffix"),
-                   i.op[op].regs->reg_name,
+           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
        else
-         as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"),
+         as_warn (_("using `%s%s' instead of `%s%s' due to `%c' suffix"),
+                  register_prefix,
                   (i.op[op].regs + REGNAM_EAX - REGNAM_AX)->reg_name,
+                  register_prefix,
                   i.op[op].regs->reg_name,
                   i.suffix);
 #endif
@@ -2731,16 +3173,27 @@ check_long_reg ()
     else if ((i.types[op] & Reg64) != 0
             && (i.tm.operand_types[op] & (Reg32 | Acc)) != 0)
       {
-       as_bad (_("Incorrect register `%%%s' used with `%c' suffix"),
-               i.op[op].regs->reg_name,
-               i.suffix);
-       return 0;
+       if (intel_syntax
+           && i.tm.base_opcode == 0xf30f2d
+           && (i.types[0] & RegXMM) == 0)
+         {
+           /* cvtss2si converts DWORD memory to Reg64.  We want
+              REX byte. */
+           i.suffix = QWORD_MNEM_SUFFIX;
+         }
+       else
+         {
+           as_bad (_("Incorrect register `%s%s' used with `%c' suffix"),
+                   register_prefix, i.op[op].regs->reg_name,
+                   i.suffix);
+           return 0;
+         }
       }
   return 1;
 }
 
 static int
-check_qword_reg ()
+check_qword_reg (void)
 {
   int op;
 
@@ -2750,29 +3203,40 @@ check_qword_reg ()
     if ((i.types[op] & Reg8) != 0
        && (i.tm.operand_types[op] & (Reg16 | Reg32 | Acc)) != 0)
       {
-       as_bad (_("`%%%s' not allowed with `%s%c'"),
+       as_bad (_("`%s%s' not allowed with `%s%c'"),
+               register_prefix,
                i.op[op].regs->reg_name,
                i.tm.name,
                i.suffix);
        return 0;
       }
   /* Warn if the e prefix on a general reg is missing.  */
-    else if (((i.types[op] & Reg16) != 0
-             || (i.types[op] & Reg32) != 0)
+    else if ((i.types[op] & (Reg16 | Reg32)) != 0
             && (i.tm.operand_types[op] & (Reg32 | Acc)) != 0)
       {
        /* Prohibit these changes in the 64bit mode, since the
           lowering is more complicated.  */
-       as_bad (_("Incorrect register `%%%s' used with `%c' suffix"),
-               i.op[op].regs->reg_name,
-               i.suffix);
-       return 0;
+       if (intel_syntax
+           && i.tm.base_opcode == 0xf20f2d
+           && (i.types[0] & RegXMM) == 0)
+         {
+           /* cvtsd2si converts QWORD memory to Reg32.  We don't want
+              REX byte. */
+           i.suffix = LONG_MNEM_SUFFIX;
+         }
+       else
+         {
+           as_bad (_("Incorrect register `%s%s' used with `%c' suffix"),
+                   register_prefix, i.op[op].regs->reg_name,
+                   i.suffix);
+           return 0;
+         }
       }
   return 1;
 }
 
 static int
-check_word_reg ()
+check_word_reg (void)
 {
   int op;
   for (op = i.operands; --op >= 0;)
@@ -2781,7 +3245,8 @@ check_word_reg ()
     if ((i.types[op] & Reg8) != 0
        && (i.tm.operand_types[op] & (Reg16 | Reg32 | Acc)) != 0)
       {
-       as_bad (_("`%%%s' not allowed with `%s%c'"),
+       as_bad (_("`%s%s' not allowed with `%s%c'"),
+               register_prefix,
                i.op[op].regs->reg_name,
                i.tm.name,
                i.suffix);
@@ -2796,15 +3261,17 @@ check_word_reg ()
           lowering is more complicated.  */
        if (flag_code == CODE_64BIT)
          {
-           as_bad (_("Incorrect register `%%%s' used with `%c' suffix"),
-                   i.op[op].regs->reg_name,
+           as_bad (_("Incorrect register `%s%s' used with `%c' suffix"),
+                   register_prefix, i.op[op].regs->reg_name,
                    i.suffix);
            return 0;
          }
        else
 #if REGISTER_WARNINGS
-         as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"),
+         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
@@ -2813,7 +3280,7 @@ check_word_reg ()
 }
 
 static int
-finalize_imm ()
+finalize_imm (void)
 {
   unsigned int overlap0, overlap1, overlap2;
 
@@ -2844,7 +3311,8 @@ finalize_imm ()
          && overlap0 != Imm16 && overlap0 != Imm32S
          && overlap0 != Imm32 && overlap0 != Imm64)
        {
-         as_bad (_("no instruction mnemonic suffix given; can't determine immediate size"));
+         as_bad (_("no instruction mnemonic suffix given; "
+                   "can't determine immediate size"));
          return 0;
        }
     }
@@ -2877,7 +3345,9 @@ finalize_imm ()
          && overlap1 != Imm16 && overlap1 != Imm32S
          && overlap1 != Imm32 && overlap1 != Imm64)
        {
-         as_bad (_("no instruction mnemonic suffix given; can't determine immediate size %x %c"),overlap1, i.suffix);
+         as_bad (_("no instruction mnemonic suffix given; "
+                   "can't determine immediate size %x %c"),
+                 overlap1, i.suffix);
          return 0;
        }
     }
@@ -2891,7 +3361,7 @@ finalize_imm ()
 }
 
 static int
-process_operands ()
+process_operands (void)
 {
   /* Default segment register this instruction will use for memory
      accesses.  0 means unknown.  This is only for optimizing out
@@ -2901,40 +3371,90 @@ process_operands ()
   /* 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)
-    {
-      unsigned int first_reg_op = (i.types[0] & Reg) ? 0 : 1;
-      /* Pretend we saw the extra register operand.  */
-      assert (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.reg_operands = 2;
+  if (i.tm.opcode_modifier & RegKludge)
+    {
+       if ((i.tm.cpu_flags & 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
+                  && 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 = (i.types[0] & Reg) ? 0 : 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)
     {
-      /* The register or float register operand is in operand 0 or 1.  */
-      unsigned int op = (i.types[0] & (Reg | FloatReg)) ? 0 : 1;
-      /* Register goes in low 3 bits of opcode.  */
-      i.tm.base_opcode |= i.op[op].regs->reg_num;
-      if ((i.op[op].regs->reg_flags & RegRex) != 0)
-       i.rex |= REX_EXTZ;
-      if (!quiet_warnings && (i.tm.opcode_modifier & Ugh) != 0)
+      if (i.types[0] & (SReg2 | SReg3))
        {
-         /* Warn about some common errors, but press on regardless.
-            The first case can be generated by gcc (<= 2.8.1).  */
-         if (i.operands == 2)
+         if (i.tm.base_opcode == POP_SEG_SHORT
+             && i.op[0].regs->reg_num == 1)
            {
-             /* Reversed arguments on faddp, fsubp, etc.  */
-             as_warn (_("translating to `%s %%%s,%%%s'"), i.tm.name,
-                      i.op[1].regs->reg_name,
-                      i.op[0].regs->reg_name);
+             as_bad (_("you can't `pop %%cs'"));
+             return 0;
            }
-         else
+         i.tm.base_opcode |= (i.op[0].regs->reg_num << 3);
+         if ((i.op[0].regs->reg_flags & RegRex) != 0)
+           i.rex |= REX_B;
+       }
+      else
+       {
+         /* The register or float register operand is in operand 0 or 1.  */
+         unsigned int op = (i.types[0] & (Reg | FloatReg)) ? 0 : 1;
+         /* Register goes in low 3 bits of opcode.  */
+         i.tm.base_opcode |= i.op[op].regs->reg_num;
+         if ((i.op[op].regs->reg_flags & RegRex) != 0)
+           i.rex |= REX_B;
+         if (!quiet_warnings && (i.tm.opcode_modifier & Ugh) != 0)
            {
-             /* Extraneous `l' suffix on fp insn.  */
-             as_warn (_("translating to `%s %%%s'"), i.tm.name,
-                      i.op[0].regs->reg_name);
+             /* Warn about some common errors, but press on regardless.
+                The first case can be generated by gcc (<= 2.8.1).  */
+             if (i.operands == 2)
+               {
+                 /* Reversed arguments on faddp, fsubp, etc.  */
+                 as_warn (_("translating to `%s %s%s,%s%s'"), i.tm.name,
+                          register_prefix, i.op[1].regs->reg_name,
+                          register_prefix, i.op[0].regs->reg_name);
+               }
+             else
+               {
+                 /* Extraneous `l' suffix on fp insn.  */
+                 as_warn (_("translating to `%s %s%s'"), i.tm.name,
+                          register_prefix, i.op[0].regs->reg_name);
+               }
            }
        }
     }
@@ -2946,19 +3466,7 @@ process_operands ()
 
       default_seg = build_modrm_byte ();
     }
-  else if (i.tm.opcode_modifier & (Seg2ShortForm | Seg3ShortForm))
-    {
-      if (i.tm.base_opcode == POP_SEG_SHORT
-         && i.op[0].regs->reg_num == 1)
-       {
-         as_bad (_("you can't `pop %%cs'"));
-         return 0;
-       }
-      i.tm.base_opcode |= (i.op[0].regs->reg_num << 3);
-      if ((i.op[0].regs->reg_flags & RegRex) != 0)
-       i.rex |= REX_EXTZ;
-    }
-  else if ((i.tm.base_opcode & ~(D | W)) == MOV_AX_DISP32)
+  else if ((i.tm.base_opcode & ~0x3) == MOV_AX_DISP32)
     {
       default_seg = &ds;
     }
@@ -2969,9 +3477,9 @@ process_operands ()
       default_seg = &ds;
     }
 
-  if ((i.tm.base_opcode == 0x8d /* lea */
-       || (i.tm.cpu_flags & CpuSVME))
-      && i.seg[0] && !quiet_warnings)
+  if (i.tm.base_opcode == 0x8d /* lea */
+      && i.seg[0]
+      && !quiet_warnings)
     as_warn (_("segment override on `%s' is ineffectual"), i.tm.name);
 
   /* If a segment was explicitly specified, and the specified segment
@@ -2988,7 +3496,7 @@ process_operands ()
 }
 
 static const seg_entry *
-build_modrm_byte ()
+build_modrm_byte (void)
 {
   const seg_entry *default_seg = 0;
 
@@ -2997,11 +3505,33 @@ build_modrm_byte ()
   if (i.reg_operands == 2)
     {
       unsigned int source, dest;
-      source = ((i.types[0]
-                & (Reg | RegMMX | RegXMM
-                   | SReg2 | SReg3
-                   | Control | Debug | Test))
-               ? 0 : 1);
+
+      switch (i.operands)
+       {
+       case 2:
+         source = 0;
+         break;
+       case 3:
+         /* When there are 3 operands, one of them may be immediate,
+            which may be the first or the last operand.  Otherwise,
+            the first operand must be shift count register (cl). */
+         assert (i.imm_operands == 1
+                 || (i.imm_operands == 0
+                     && (i.types[0] & ShiftCount)));
+         source = (i.types[0] & (Imm | ShiftCount)) ? 1 : 0;
+         break;
+       case 4:
+         /* When there are 4 operands, the first two must be immediate
+            operands. The source operand will be the 3rd one.  */
+         assert (i.imm_operands == 2
+                 && (i.types[0] & Imm)
+                 && (i.types[1] & Imm));
+         source = 2;
+         break;
+       default:
+         abort ();
+       }
+
       dest = source + 1;
 
       i.rm.mode = 3;
@@ -3011,29 +3541,29 @@ build_modrm_byte ()
         destination operand, then we assume the source operand may
         sometimes be a memory operand and so we need to store the
         destination in the i.rm.reg field.  */
-      if ((i.tm.operand_types[dest] & AnyMem) == 0)
+      if ((i.tm.operand_types[dest] & (AnyMem | RegMem)) == 0)
        {
          i.rm.reg = i.op[dest].regs->reg_num;
          i.rm.regmem = i.op[source].regs->reg_num;
          if ((i.op[dest].regs->reg_flags & RegRex) != 0)
-           i.rex |= REX_EXTX;
+           i.rex |= REX_R;
          if ((i.op[source].regs->reg_flags & RegRex) != 0)
-           i.rex |= REX_EXTZ;
+           i.rex |= REX_B;
        }
       else
        {
          i.rm.reg = i.op[source].regs->reg_num;
          i.rm.regmem = i.op[dest].regs->reg_num;
          if ((i.op[dest].regs->reg_flags & RegRex) != 0)
-           i.rex |= REX_EXTZ;
+           i.rex |= REX_B;
          if ((i.op[source].regs->reg_flags & RegRex) != 0)
-           i.rex |= REX_EXTX;
+           i.rex |= REX_R;
        }
-      if (flag_code != CODE_64BIT && (i.rex & (REX_EXTX | REX_EXTZ)))
+      if (flag_code != CODE_64BIT && (i.rex & (REX_R | REX_B)))
        {
          if (!((i.types[0] | i.types[1]) & Control))
            abort ();
-         i.rex &= ~(REX_EXTX | REX_EXTZ);
+         i.rex &= ~(REX_R | REX_B);
          add_prefix (LOCK_PREFIX_OPCODE);
        }
     }
@@ -3042,9 +3572,12 @@ build_modrm_byte ()
       if (i.mem_operands)
        {
          unsigned int fake_zero_displacement = 0;
-         unsigned int op = ((i.types[0] & AnyMem)
-                            ? 0
-                            : (i.types[1] & AnyMem) ? 1 : 2);
+         unsigned int op;
+
+         for (op = 0; op < i.operands; op++)
+           if ((i.types[op] & AnyMem))
+             break;
+         assert (op < i.operands);
 
          default_seg = &ds;
 
@@ -3065,9 +3598,11 @@ build_modrm_byte ()
                      i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
                      i.sib.base = NO_BASE_REGISTER;
                      i.sib.index = NO_INDEX_REGISTER;
-                     i.types[op] = ((i.prefix[ADDR_PREFIX] == 0) ? Disp32S : Disp32);
+                     i.types[op] = ((i.prefix[ADDR_PREFIX] == 0)
+                                    ? Disp32S : Disp32);
                    }
-                 else if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0))
+                 else if ((flag_code == CODE_16BIT)
+                          ^ (i.prefix[ADDR_PREFIX] != 0))
                    {
                      i.rm.regmem = NO_BASE_REGISTER_16;
                      i.types[op] = Disp16;
@@ -3090,7 +3625,7 @@ build_modrm_byte ()
                  else
                    i.types[op] |= Disp32S;
                  if ((i.index_reg->reg_flags & RegRex) != 0)
-                   i.rex |= REX_EXTY;
+                   i.rex |= REX_X;
                }
            }
          /* RIP addressing for 64bit mode.  */
@@ -3099,7 +3634,7 @@ build_modrm_byte ()
              i.rm.regmem = NO_BASE_REGISTER;
              i.types[op] &= ~ Disp;
              i.types[op] |= Disp32S;
-             i.flags[op] = Operand_PCrel;
+             i.flags[op] |= Operand_PCrel;
              if (! i.disp_operands)
                fake_zero_displacement = 1;
            }
@@ -3137,11 +3672,13 @@ build_modrm_byte ()
            {
              if (flag_code == CODE_64BIT
                  && (i.types[op] & Disp))
-               i.types[op] = (i.types[op] & Disp8) | (i.prefix[ADDR_PREFIX] == 0 ? Disp32S : Disp32);
+               i.types[op] = ((i.types[op] & Disp8)
+                              | (i.prefix[ADDR_PREFIX] == 0
+                                 ? Disp32S : Disp32));
 
              i.rm.regmem = i.base_reg->reg_num;
              if ((i.base_reg->reg_flags & RegRex) != 0)
-               i.rex |= REX_EXTZ;
+               i.rex |= REX_B;
              i.sib.base = i.base_reg->reg_num;
              /* x86-64 ignores REX prefix bit here to avoid decoder
                 complications.  */
@@ -3178,7 +3715,7 @@ build_modrm_byte ()
                  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_EXTY;
+                   i.rex |= REX_X;
                }
 
              if (i.disp_operands
@@ -3211,31 +3748,28 @@ build_modrm_byte ()
         registers are coded into the i.rm.reg field.  */
       if (i.reg_operands)
        {
-         unsigned int op =
-           ((i.types[0]
-             & (Reg | RegMMX | RegXMM
-                | SReg2 | SReg3
-                | Control | Debug | Test))
-            ? 0
-            : ((i.types[1]
-                & (Reg | RegMMX | RegXMM
-                   | SReg2 | SReg3
-                   | Control | Debug | Test))
-               ? 1
-               : 2));
+         unsigned int op;
+
+         for (op = 0; op < i.operands; op++)
+           if ((i.types[op] & (Reg | RegMMX | RegXMM
+                               | SReg2 | SReg3
+                               | Control | Debug | Test)))
+             break;
+         assert (op < i.operands);
+
          /* If there is an extension opcode to put here, the register
             number must be put into the regmem field.  */
          if (i.tm.extension_opcode != None)
            {
              i.rm.regmem = i.op[op].regs->reg_num;
              if ((i.op[op].regs->reg_flags & RegRex) != 0)
-               i.rex |= REX_EXTZ;
+               i.rex |= REX_B;
            }
          else
            {
              i.rm.reg = i.op[op].regs->reg_num;
              if ((i.op[op].regs->reg_flags & RegRex) != 0)
-               i.rex |= REX_EXTX;
+               i.rex |= REX_R;
            }
 
          /* Now, if no memory operand has set i.rm.mode = 0, 1, 2 we
@@ -3253,7 +3787,7 @@ build_modrm_byte ()
 }
 
 static void
-output_branch ()
+output_branch (void)
 {
   char *p;
   int code16;
@@ -3331,7 +3865,7 @@ output_branch ()
 }
 
 static void
-output_jump ()
+output_jump (void)
 {
   char *p;
   int size;
@@ -3397,7 +3931,7 @@ output_jump ()
 }
 
 static void
-output_interseg_jump ()
+output_interseg_jump (void)
 {
   char *p;
   int size;
@@ -3461,7 +3995,7 @@ output_interseg_jump ()
 }
 
 static void
-output_insn ()
+output_insn (void)
 {
   fragS *insn_start_frag;
   offsetT insn_start_off;
@@ -3488,10 +4022,12 @@ output_insn ()
       unsigned char *q;
       unsigned int prefix;
 
-      /* All opcodes on i386 have either 1 or 2 bytes.  Merom New
-        Instructions have 3 bytes.  We may use one more higher byte
-        to specify a prefix the instruction requires.  */
-      if ((i.tm.cpu_flags & CpuMNI) != 0)
+      /* All opcodes on i386 have either 1 or 2 bytes.  SSSE3 and
+        SSE4 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 and ABM.  */
+      if ((i.tm.cpu_flags & (CpuSSSE3 | CpuSSE4)) != 0
+         && (i.tm.cpu_flags & CpuABM) == 0)
        {
          if (i.tm.base_opcode & 0xff000000)
            {
@@ -3532,7 +4068,8 @@ output_insn ()
        }
       else
        {
-         if ((i.tm.cpu_flags & CpuMNI) != 0)
+         if ((i.tm.cpu_flags & (CpuSSSE3 | CpuSSE4)) != 0
+             && (i.tm.cpu_flags & CpuABM) == 0)
            {
              p = frag_more (3);
              *p++ = (i.tm.base_opcode >> 16) & 0xff;
@@ -3586,6 +4123,40 @@ output_insn ()
 #endif /* DEBUG386  */
 }
 
+/* Return the size of the displacement operand N.  */
+
+static int
+disp_size (unsigned int n)
+{
+  int size = 4;
+  if (i.types[n] & (Disp8 | Disp16 | Disp64))
+    {
+      size = 2;
+      if (i.types[n] & Disp8)
+       size = 1;
+      if (i.types[n] & Disp64)
+       size = 8;
+    }
+  return size;
+}
+
+/* Return the size of the immediate operand N.  */
+
+static int
+imm_size (unsigned int n)
+{
+  int size = 4;
+  if (i.types[n] & (Imm8 | Imm8S | Imm16 | Imm64))
+    {
+      size = 2;
+      if (i.types[n] & (Imm8 | Imm8S))
+       size = 1;
+      if (i.types[n] & Imm64)
+       size = 8;
+    }
+  return size;
+}
+
 static void
 output_disp (fragS *insn_start_frag, offsetT insn_start_off)
 {
@@ -3598,18 +4169,9 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off)
        {
          if (i.op[n].disps->X_op == O_constant)
            {
-             int size;
+             int size = disp_size (n);
              offsetT val;
 
-             size = 4;
-             if (i.types[n] & (Disp8 | Disp16 | Disp64))
-               {
-                 size = 2;
-                 if (i.types[n] & Disp8)
-                   size = 1;
-                 if (i.types[n] & Disp64)
-                   size = 8;
-               }
              val = offset_in_range (i.op[n].disps->X_add_number,
                                     size);
              p = frag_more (size);
@@ -3618,45 +4180,32 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off)
          else
            {
              enum bfd_reloc_code_real reloc_type;
-             int size = 4;
-             int sign = 0;
+             int size = disp_size (n);
+             int sign = (i.types[n] & Disp32S) != 0;
              int pcrel = (i.flags[n] & Operand_PCrel) != 0;
 
+             /* We can't have 8 bit displacement here.  */
+             assert ((i.types[n] & Disp8) == 0);
+
              /* The PC relative address is computed relative
                 to the instruction boundary, so in case immediate
                 fields follows, we need to adjust the value.  */
              if (pcrel && i.imm_operands)
                {
-                 int imm_size = 4;
                  unsigned int n1;
+                 int sz = 0;
 
                  for (n1 = 0; n1 < i.operands; n1++)
                    if (i.types[n1] & Imm)
                      {
-                       if (i.types[n1] & (Imm8 | Imm8S | Imm16 | Imm64))
-                         {
-                           imm_size = 2;
-                           if (i.types[n1] & (Imm8 | Imm8S))
-                             imm_size = 1;
-                           if (i.types[n1] & Imm64)
-                             imm_size = 8;
-                         }
-                       break;
+                       /* Only one immediate is allowed for PC
+                          relative address.  */
+                       assert (sz == 0);
+                       sz = imm_size (n1);
+                       i.op[n].disps->X_add_number -= sz;
                      }
                  /* We should find the immediate.  */
-                 if (n1 == i.operands)
-                   abort ();
-                 i.op[n].disps->X_add_number -= imm_size;
-               }
-
-             if (i.types[n] & Disp32S)
-               sign = 1;
-
-             if (i.types[n] & (Disp16 | Disp64))
-               {
-                 size = 2;
-                 if (i.types[n] & Disp64)
-                   size = 8;
+                 assert (sz != 0);
                }
 
              p = frag_more (size);
@@ -3721,18 +4270,9 @@ output_imm (fragS *insn_start_frag, offsetT insn_start_off)
        {
          if (i.op[n].imms->X_op == O_constant)
            {
-             int size;
+             int size = imm_size (n);
              offsetT val;
 
-             size = 4;
-             if (i.types[n] & (Imm8 | Imm8S | Imm16 | Imm64))
-               {
-                 size = 2;
-                 if (i.types[n] & (Imm8 | Imm8S))
-                   size = 1;
-                 else if (i.types[n] & Imm64)
-                   size = 8;
-               }
              val = offset_in_range (i.op[n].imms->X_add_number,
                                     size);
              p = frag_more (size);
@@ -3745,21 +4285,15 @@ output_imm (fragS *insn_start_frag, offsetT insn_start_off)
                 non-absolute imms).  Try to support other
                 sizes ...  */
              enum bfd_reloc_code_real reloc_type;
-             int size = 4;
-             int sign = 0;
+             int size = imm_size (n);
+             int sign;
 
              if ((i.types[n] & (Imm32S))
                  && (i.suffix == QWORD_MNEM_SUFFIX
                      || (!i.suffix && (i.tm.opcode_modifier & No_lSuf))))
                sign = 1;
-             if (i.types[n] & (Imm8 | Imm8S | Imm16 | Imm64))
-               {
-                 size = 2;
-                 if (i.types[n] & (Imm8 | Imm8S))
-                   size = 1;
-                 if (i.types[n] & Imm64)
-                   size = 8;
-               }
+             else
+               sign = 0;
 
              p = frag_more (size);
              reloc_type = reloc (size, 0, sign, i.reloc[n]);
@@ -3853,9 +4387,7 @@ static enum bfd_reloc_code_real got_reloc = NO_RELOC;
 static int cons_sign = -1;
 
 void
-x86_cons_fix_new (fragS *frag,
-                 unsigned int off,
-                 unsigned int len,
+x86_cons_fix_new (fragS *frag, unsigned int off, unsigned int len,
                  expressionS *exp)
 {
   enum bfd_reloc_code_real r = reloc (len, 0, cons_sign, got_reloc);
@@ -3900,23 +4432,57 @@ lex_got (enum bfd_reloc_code_real *reloc,
     const enum bfd_reloc_code_real rel[2];
     const unsigned int types64;
   } gotrel[] = {
-    { "PLTOFF",   { 0,                        BFD_RELOC_X86_64_PLTOFF64 }, Imm64 },
-    { "PLT",      { BFD_RELOC_386_PLT32,      BFD_RELOC_X86_64_PLT32    }, Imm32|Imm32S|Disp32 },
-    { "GOTPLT",   { 0,                        BFD_RELOC_X86_64_GOTPLT64 }, Imm64|Disp64 },
-    { "GOTOFF",   { BFD_RELOC_386_GOTOFF,     BFD_RELOC_X86_64_GOTOFF64 }, Imm64|Disp64 },
-    { "GOTPCREL", { 0,                        BFD_RELOC_X86_64_GOTPCREL }, Imm32|Imm32S|Disp32 },
-    { "TLSGD",    { BFD_RELOC_386_TLS_GD,     BFD_RELOC_X86_64_TLSGD    }, Imm32|Imm32S|Disp32 },
-    { "TLSLDM",   { BFD_RELOC_386_TLS_LDM,    0                         }, 0 },
-    { "TLSLD",    { 0,                        BFD_RELOC_X86_64_TLSLD    }, Imm32|Imm32S|Disp32 },
-    { "GOTTPOFF", { BFD_RELOC_386_TLS_IE_32,  BFD_RELOC_X86_64_GOTTPOFF }, Imm32|Imm32S|Disp32 },
-    { "TPOFF",    { BFD_RELOC_386_TLS_LE_32,  BFD_RELOC_X86_64_TPOFF32  }, Imm32|Imm32S|Imm64|Disp32|Disp64 },
-    { "NTPOFF",   { BFD_RELOC_386_TLS_LE,     0                         }, 0 },
-    { "DTPOFF",   { BFD_RELOC_386_TLS_LDO_32, BFD_RELOC_X86_64_DTPOFF32 }, Imm32|Imm32S|Imm64|Disp32|Disp64 },
-    { "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE,  0                         }, 0 },
-    { "INDNTPOFF",{ BFD_RELOC_386_TLS_IE,     0                         }, 0 },
-    { "GOT",      { BFD_RELOC_386_GOT32,      BFD_RELOC_X86_64_GOT32    }, Imm32|Imm32S|Disp32|Imm64 },
-    { "TLSDESC",  { BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_X86_64_GOTPC32_TLSDESC }, Imm32|Imm32S|Disp32 },
-    { "TLSCALL",  { BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_X86_64_TLSDESC_CALL }, Imm32|Imm32S|Disp32 }
+    { "PLTOFF",   { 0,
+                   BFD_RELOC_X86_64_PLTOFF64 },
+      Imm64 },
+    { "PLT",      { BFD_RELOC_386_PLT32,
+                   BFD_RELOC_X86_64_PLT32    },
+      Imm32 | Imm32S | Disp32 },
+    { "GOTPLT",   { 0,
+                   BFD_RELOC_X86_64_GOTPLT64 },
+      Imm64 | Disp64 },
+    { "GOTOFF",   { BFD_RELOC_386_GOTOFF,
+                   BFD_RELOC_X86_64_GOTOFF64 },
+      Imm64 | Disp64 },
+    { "GOTPCREL", { 0,
+                   BFD_RELOC_X86_64_GOTPCREL },
+      Imm32 | Imm32S | Disp32 },
+    { "TLSGD",    { BFD_RELOC_386_TLS_GD,
+                   BFD_RELOC_X86_64_TLSGD    },
+      Imm32 | Imm32S | Disp32 },
+    { "TLSLDM",   { BFD_RELOC_386_TLS_LDM,
+                   0                         },
+      0 },
+    { "TLSLD",    { 0,
+                   BFD_RELOC_X86_64_TLSLD    },
+      Imm32 | Imm32S | Disp32 },
+    { "GOTTPOFF", { BFD_RELOC_386_TLS_IE_32,
+                   BFD_RELOC_X86_64_GOTTPOFF },
+      Imm32 | Imm32S | Disp32 },
+    { "TPOFF",    { BFD_RELOC_386_TLS_LE_32,
+                   BFD_RELOC_X86_64_TPOFF32  },
+      Imm32 | Imm32S | Imm64 | Disp32 | Disp64 },
+    { "NTPOFF",   { BFD_RELOC_386_TLS_LE,
+                   0                         },
+      0 },
+    { "DTPOFF",   { BFD_RELOC_386_TLS_LDO_32,
+                   BFD_RELOC_X86_64_DTPOFF32 },
+      Imm32 | Imm32S | Imm64 | Disp32 | Disp64 },
+    { "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE,
+                   0                         },
+      0 },
+    { "INDNTPOFF",{ BFD_RELOC_386_TLS_IE,
+                   0                         },
+      0 },
+    { "GOT",      { BFD_RELOC_386_GOT32,
+                   BFD_RELOC_X86_64_GOT32    },
+      Imm32 | Imm32S | Disp32 | Imm64 },
+    { "TLSDESC",  { BFD_RELOC_386_TLS_GOTDESC,
+                   BFD_RELOC_X86_64_GOTPC32_TLSDESC },
+      Imm32 | Imm32S | Disp32 },
+    { "TLSCALL",  { BFD_RELOC_386_TLS_DESC_CALL,
+                   BFD_RELOC_X86_64_TLSDESC_CALL },
+      Imm32 | Imm32S | Disp32 }
   };
   char *cp;
   unsigned int j;
@@ -3925,7 +4491,7 @@ lex_got (enum bfd_reloc_code_real *reloc,
     return NULL;
 
   for (cp = input_line_pointer; *cp != '@'; cp++)
-    if (is_end_of_line[(unsigned char) *cp])
+    if (is_end_of_line[(unsigned char) *cp] || *cp == ',')
       return NULL;
 
   for (j = 0; j < sizeof (gotrel) / sizeof (gotrel[0]); j++)
@@ -3947,7 +4513,7 @@ lex_got (enum bfd_reloc_code_real *reloc,
              if (types)
                {
                  if (flag_code != CODE_64BIT)
-                   *types = Imm32|Disp32;
+                   *types = Imm32 | Disp32;
                  else
                    *types = gotrel[j].types64;
                }
@@ -3955,27 +4521,27 @@ lex_got (enum bfd_reloc_code_real *reloc,
              if (GOT_symbol == NULL)
                GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
 
-             /* Replace the relocation token with ' ', so that
-                errors like foo@GOTOFF1 will be detected.  */
-
              /* The length of the first part of our input line.  */
              first = cp - input_line_pointer;
 
              /* The second part goes from after the reloc token until
-                (and including) an end_of_line char.  Don't use strlen
-                here as the end_of_line char may not be a NUL.  */
+                (and including) an end_of_line char or comma.  */
              past_reloc = cp + 1 + len;
-             for (cp = past_reloc; !is_end_of_line[(unsigned char) *cp++]; )
-               ;
-             second = cp - past_reloc;
+             cp = past_reloc;
+             while (!is_end_of_line[(unsigned char) *cp] && *cp != ',')
+               ++cp;
+             second = cp + 1 - past_reloc;
 
              /* Allocate and copy string.  The trailing NUL shouldn't
                 be necessary, but be safe.  */
              tmpbuf = xmalloc (first + second + 2);
              memcpy (tmpbuf, input_line_pointer, first);
-             tmpbuf[first] = ' ';
-             memcpy (tmpbuf + first + 1, past_reloc, second);
-             tmpbuf[first + second + 1] = '\0';
+             if (second != 0 && *past_reloc != ' ')
+               /* Replace the relocation token with ' ', so that
+                  errors like foo@GOTOFF1 will be detected.  */
+               tmpbuf[first++] = ' ';
+             memcpy (tmpbuf + first, past_reloc, second);
+             tmpbuf[first + second] = '\0';
              return tmpbuf;
            }
 
@@ -3990,9 +4556,7 @@ lex_got (enum bfd_reloc_code_real *reloc,
 }
 
 void
-x86_cons (exp, size)
-     expressionS *exp;
-     int size;
+x86_cons (expressionS *exp, int size)
 {
   if (size == 4 || (object_64bit && size == 8))
     {
@@ -4017,6 +4581,17 @@ x86_cons (exp, size)
                                + (input_line_pointer - gotfree_input_line)
                                + adjust);
          free (gotfree_input_line);
+         if (exp->X_op == O_constant
+             || exp->X_op == O_absent
+             || exp->X_op == O_illegal
+             || exp->X_op == O_register
+             || exp->X_op == O_big)
+           {
+             char c = *input_line_pointer;
+             *input_line_pointer = 0;
+             as_bad (_("missing or invalid expression `%s'"), save);
+             *input_line_pointer = c;
+           }
        }
     }
   else
@@ -4054,11 +4629,8 @@ pe_directive_secrel (dummy)
 }
 #endif
 
-static int i386_immediate PARAMS ((char *));
-
 static int
-i386_immediate (imm_start)
-     char *imm_start;
+i386_immediate (char *imm_start)
 {
   char *save_input_line_pointer;
   char *gotfree_input_line;
@@ -4068,7 +4640,8 @@ i386_immediate (imm_start)
 
   if (i.imm_operands == MAX_IMMEDIATE_OPERANDS)
     {
-      as_bad (_("only 1 or 2 immediate operands are allowed"));
+      as_bad (_("at most %d immediate operands are allowed"),
+             MAX_IMMEDIATE_OPERANDS);
       return 0;
     }
 
@@ -4095,24 +4668,26 @@ i386_immediate (imm_start)
   if (gotfree_input_line)
     free (gotfree_input_line);
 
-  if (exp->X_op == O_absent || exp->X_op == O_big)
+  if (exp->X_op == O_absent
+      || exp->X_op == O_illegal
+      || exp->X_op == O_big
+      || (gotfree_input_line
+         && (exp->X_op == O_constant
+             || exp->X_op == O_register)))
     {
-      /* Missing or bad expr becomes absolute 0.  */
-      as_bad (_("missing or invalid immediate expression `%s' taken as 0"),
+      as_bad (_("missing or invalid immediate expression `%s'"),
              imm_start);
-      exp->X_op = O_constant;
-      exp->X_add_number = 0;
-      exp->X_add_symbol = (symbolS *) 0;
-      exp->X_op_symbol = (symbolS *) 0;
+      return 0;
     }
   else if (exp->X_op == O_constant)
     {
       /* Size it properly later.  */
       i.types[this_operand] |= Imm64;
       /* If BFD64, sign extend val.  */
-      if (!use_rela_relocations)
-       if ((exp->X_add_number & ~(((addressT) 2 << 31) - 1)) == 0)
-         exp->X_add_number = (exp->X_add_number ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31);
+      if (!use_rela_relocations
+         && (exp->X_add_number & ~(((addressT) 2 << 31) - 1)) == 0)
+       exp->X_add_number
+         = (exp->X_add_number ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31);
     }
 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
   else if (OUTPUT_FLAVOR == bfd_target_aout_flavour
@@ -4144,11 +4719,8 @@ i386_immediate (imm_start)
   return 1;
 }
 
-static char *i386_scale PARAMS ((char *));
-
 static char *
-i386_scale (scale)
-     char *scale;
+i386_scale (char *scale)
 {
   offsetT val;
   char *save = input_line_pointer;
@@ -4195,12 +4767,8 @@ i386_scale (scale)
   return scale;
 }
 
-static int i386_displacement PARAMS ((char *, char *));
-
 static int
-i386_displacement (disp_start, disp_end)
-     char *disp_start;
-     char *disp_end;
+i386_displacement (char *disp_start, char *disp_end)
 {
   expressionS *exp;
   segT exp_seg = 0;
@@ -4208,6 +4776,14 @@ i386_displacement (disp_start, disp_end)
   char *gotfree_input_line;
   int bigdisp, override;
   unsigned int types = Disp;
+  int ret;
+
+  if (i.disp_operands == MAX_MEMORY_OPERANDS)
+    {
+      as_bad (_("at most %d displacement operands are allowed"),
+             MAX_MEMORY_OPERANDS);
+      return 0;
+    }
 
   if ((i.types[this_operand] & JumpAbsolute)
       || !(current_templates->start->opcode_modifier & (Jump | JumpDword)))
@@ -4309,10 +4885,10 @@ i386_displacement (disp_start, disp_end)
 #if GCC_ASM_O_HACK
   RESTORE_END_STRING (disp_end + 1);
 #endif
-  RESTORE_END_STRING (disp_end);
   input_line_pointer = save_input_line_pointer;
   if (gotfree_input_line)
     free (gotfree_input_line);
+  ret = 1;
 
   /* We do this to make sure that the section symbol is in
      the symbol table.  We will ultimately change the relocation
@@ -4322,13 +4898,7 @@ i386_displacement (disp_start, disp_end)
       || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTOFF64)
     {
       if (exp->X_op != O_symbol)
-       {
-         as_bad (_("bad expression used with @%s"),
-                 (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL
-                  ? "GOTPCREL"
-                  : "GOTOFF"));
-         return 0;
-       }
+       goto inv_disp;
 
       if (S_IS_LOCAL (exp->X_add_symbol)
          && S_GET_SEGMENT (exp->X_add_symbol) != undefined_section)
@@ -4343,46 +4913,47 @@ i386_displacement (disp_start, disp_end)
        i.reloc[this_operand] = BFD_RELOC_32;
     }
 
-  if (exp->X_op == O_absent || exp->X_op == O_big)
+  else if (exp->X_op == O_absent
+          || exp->X_op == O_illegal
+          || exp->X_op == O_big
+          || (gotfree_input_line
+              && (exp->X_op == O_constant
+                  || exp->X_op == O_register)))
     {
-      /* Missing or bad expr becomes absolute 0.  */
-      as_bad (_("missing or invalid displacement expression `%s' taken as 0"),
+    inv_disp:
+      as_bad (_("missing or invalid displacement expression `%s'"),
              disp_start);
-      exp->X_op = O_constant;
-      exp->X_add_number = 0;
-      exp->X_add_symbol = (symbolS *) 0;
-      exp->X_op_symbol = (symbolS *) 0;
+      ret = 0;
     }
 
 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
-  if (exp->X_op != O_constant
-      && OUTPUT_FLAVOR == bfd_target_aout_flavour
-      && exp_seg != absolute_section
-      && exp_seg != text_section
-      && exp_seg != data_section
-      && exp_seg != bss_section
-      && exp_seg != undefined_section
-      && !bfd_is_com_section (exp_seg))
+  else if (exp->X_op != O_constant
+          && OUTPUT_FLAVOR == bfd_target_aout_flavour
+          && exp_seg != absolute_section
+          && exp_seg != text_section
+          && exp_seg != data_section
+          && exp_seg != bss_section
+          && exp_seg != undefined_section
+          && !bfd_is_com_section (exp_seg))
     {
       as_bad (_("unimplemented segment %s in operand"), exp_seg->name);
-      return 0;
+      ret = 0;
     }
 #endif
 
+  RESTORE_END_STRING (disp_end);
+
   if (!(i.types[this_operand] & ~Disp))
     i.types[this_operand] &= types;
 
-  return 1;
+  return ret;
 }
 
-static int i386_index_check PARAMS ((const char *));
-
 /* Make sure the memory operand we've been dealt is valid.
    Return 1 on success, 0 on a failure.  */
 
 static int
-i386_index_check (operand_string)
-     const char *operand_string;
+i386_index_check (const char *operand_string)
 {
   int ok;
 #if INFER_ADDR_PREFIX
@@ -4391,30 +4962,7 @@ i386_index_check (operand_string)
  tryprefix:
 #endif
   ok = 1;
-  if ((current_templates->start->cpu_flags & CpuSVME)
-      && current_templates->end[-1].operand_types[0] == AnyMem)
-    {
-      /* Memory operands of SVME insns are special in that they only allow
-        rAX as their memory address and ignore any segment override.  */
-      unsigned RegXX;
-
-      /* SKINIT is even more restrictive: it always requires EAX.  */
-      if (strcmp (current_templates->start->name, "skinit") == 0)
-       RegXX = Reg32;
-      else if (flag_code == CODE_64BIT)
-       RegXX = i.prefix[ADDR_PREFIX] == 0 ? Reg64 : Reg32;
-      else
-       RegXX = ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0)
-                ? Reg16
-                : Reg32);
-      if (!i.base_reg
-         || !(i.base_reg->reg_type & Acc)
-         || !(i.base_reg->reg_type & RegXX)
-         || i.index_reg
-         || (i.types[0] & Disp))
-       ok = 0;
-    }
-  else if (flag_code == CODE_64BIT)
+  if (flag_code == CODE_64BIT)
     {
       unsigned RegXX = (i.prefix[ADDR_PREFIX] == 0 ? Reg64 : Reg32);
 
@@ -4467,7 +5015,8 @@ i386_index_check (operand_string)
             FIXME.  There doesn't seem to be any real need for separate
             Disp16 and Disp32 flags.  The same goes for Imm16 and Imm32.
             Removing them would probably clean up the code quite a lot.  */
-         if (flag_code != CODE_64BIT && (i.types[this_operand] & (Disp16 | Disp32)))
+         if (flag_code != CODE_64BIT
+             && (i.types[this_operand] & (Disp16 | Disp32)))
            i.types[this_operand] ^= (Disp16 | Disp32);
          fudged = 1;
          goto tryprefix;
@@ -4488,8 +5037,7 @@ i386_index_check (operand_string)
    on error.  */
 
 static int
-i386_operand (operand_string)
-     char *operand_string;
+i386_operand (char *operand_string)
 {
   const reg_entry *r;
   char *end_op;
@@ -4647,7 +5195,8 @@ i386_operand (operand_string)
            ++base_string;
 
          if (*base_string == ','
-             || ((i.base_reg = parse_register (base_string, &end_op)) != NULL))
+             || ((i.base_reg = parse_register (base_string, &end_op))
+                 != NULL))
            {
              displacement_string_end = temp_string;
 
@@ -4667,7 +5216,8 @@ i386_operand (operand_string)
                  if (is_space_char (*base_string))
                    ++base_string;
 
-                 if ((i.index_reg = parse_register (base_string, &end_op)) != NULL)
+                 if ((i.index_reg = parse_register (base_string, &end_op))
+                     != NULL)
                    {
                      base_string = end_op;
                      if (is_space_char (*base_string))
@@ -4680,7 +5230,8 @@ i386_operand (operand_string)
                        }
                      else if (*base_string != ')')
                        {
-                         as_bad (_("expecting `,' or `)' after index register in `%s'"),
+                         as_bad (_("expecting `,' or `)' "
+                                   "after index register in `%s'"),
                                  operand_string);
                          return 0;
                        }
@@ -4704,21 +5255,24 @@ i386_operand (operand_string)
                        ++base_string;
                      if (*base_string != ')')
                        {
-                         as_bad (_("expecting `)' after scale factor in `%s'"),
+                         as_bad (_("expecting `)' "
+                                   "after scale factor in `%s'"),
                                  operand_string);
                          return 0;
                        }
                    }
                  else if (!i.index_reg)
                    {
-                     as_bad (_("expecting index register or scale factor after `,'; got '%c'"),
+                     as_bad (_("expecting index register or scale factor "
+                               "after `,'; got '%c'"),
                              *base_string);
                      return 0;
                    }
                }
              else if (*base_string != ')')
                {
-                 as_bad (_("expecting `,' or `)' after base register in `%s'"),
+                 as_bad (_("expecting `,' or `)' "
+                           "after base register in `%s'"),
                          operand_string);
                  return 0;
                }
@@ -4934,7 +5488,8 @@ md_convert_frag (abfd, sec, fragP)
     {
       if (no_cond_jump_promotion
          && TYPE_FROM_RELAX_STATE (fragP->fr_subtype) != UNCOND_JUMP)
-       as_warn_where (fragP->fr_file, fragP->fr_line, _("long jump required"));
+       as_warn_where (fragP->fr_file, fragP->fr_line,
+                      _("long jump required"));
 
       switch (fragP->fr_subtype)
        {
@@ -4985,8 +5540,8 @@ md_convert_frag (abfd, sec, fragP)
   if (DISP_SIZE_FROM_RELAX_STATE (fragP->fr_subtype) == 4
       && object_64bit
       && ((addressT) (displacement_from_opcode_start - extension
-                      + ((addressT) 1 << 31))
-          > (((addressT) 2 << 31) - 1)))
+                     + ((addressT) 1 << 31))
+         > (((addressT) 2 << 31) - 1)))
     {
       as_bad_where (fragP->fr_file, fragP->fr_line,
                    _("jump target out of range"));
@@ -5251,18 +5806,17 @@ md_atof (type, litP, sizeP)
   return 0;
 }
 \f
-static char output_invalid_buf[16];
+static char output_invalid_buf[sizeof (unsigned char) * 2 + 6];
 
 static char *
-output_invalid (c)
-     int c;
+output_invalid (int c)
 {
   if (ISPRINT (c))
     snprintf (output_invalid_buf, sizeof (output_invalid_buf),
              "'%c'", c);
   else
     snprintf (output_invalid_buf, sizeof (output_invalid_buf),
-             "(0x%x)", (unsigned) c);
+             "(0x%x)", (unsigned char) c);
   return output_invalid_buf;
 }
 
@@ -5313,14 +5867,16 @@ parse_real_register (char *reg_string, char **end_op)
            ++s;
          if (*s >= '0' && *s <= '7')
            {
-             r = &i386_float_regtab[*s - '0'];
+             int fpr = *s - '0';
              ++s;
              if (is_space_char (*s))
                ++s;
              if (*s == ')')
                {
                  *end_op = s + 1;
-                 return r;
+                 r = hash_find (reg_hash, "st(0)");
+                 know (r);
+                 return r + fpr;
                }
            }
          /* We have "%st(" then garbage.  */
@@ -5362,7 +5918,8 @@ parse_register (char *reg_string, char **end_op)
          const expressionS *e = symbol_get_value_expression (symbolP);
 
          know (e->X_op == O_register);
-         know (e->X_add_number >= 0 && (valueT) e->X_add_number < ARRAY_SIZE (i386_regtab));
+         know (e->X_add_number >= 0
+               && (valueT) e->X_add_number < i386_regtab_size);
          r = i386_regtab + e->X_add_number;
          *end_op = input_line_pointer;
        }
@@ -5420,22 +5977,27 @@ const char *md_shortopts = "qn";
 #define OPTION_32 (OPTION_MD_BASE + 0)
 #define OPTION_64 (OPTION_MD_BASE + 1)
 #define OPTION_DIVIDE (OPTION_MD_BASE + 2)
+#define OPTION_MARCH (OPTION_MD_BASE + 3)
+#define OPTION_MTUNE (OPTION_MD_BASE + 4)
 
-struct option md_longopts[] = {
+struct option md_longopts[] =
+{
   {"32", no_argument, NULL, OPTION_32},
-#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined(TE_PEP)
   {"64", no_argument, NULL, OPTION_64},
 #endif
   {"divide", no_argument, NULL, OPTION_DIVIDE},
+  {"march", required_argument, NULL, OPTION_MARCH},
+  {"mtune", required_argument, NULL, OPTION_MTUNE},
   {NULL, no_argument, NULL, 0}
 };
 size_t md_longopts_size = sizeof (md_longopts);
 
 int
-md_parse_option (c, arg)
-     int c;
-     char *arg ATTRIBUTE_UNUSED;
+md_parse_option (int c, char *arg)
 {
+  unsigned int i;
+
   switch (c)
     {
     case 'n':
@@ -5465,14 +6027,18 @@ md_parse_option (c, arg)
       /* -s: On i386 Solaris, this tells the native assembler to use
         .stab instead of .stab.excl.  We always use .stab anyhow.  */
       break;
-
+#endif
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined(TE_PEP)
     case OPTION_64:
       {
        const char **list, **l;
 
        list = bfd_target_list ();
        for (l = list; *l != NULL; l++)
-         if (strcmp (*l, "elf64-x86-64") == 0)
+         if (CONST_STRNEQ (*l, "elf64-x86-64")
+             || strcmp (*l, "coff-x86-64") == 0
+             || strcmp (*l, "pe-x86-64") == 0
+             || strcmp (*l, "pei-x86-64") == 0)
            {
              default_arch = "x86_64";
              break;
@@ -5505,6 +6071,44 @@ md_parse_option (c, arg)
 #endif
       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)
+           {
+             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;
+           }
+       }
+      if (i >= ARRAY_SIZE (cpu_arch))
+       as_fatal (_("Invalid -march= option: `%s'"), arg);
+      break;
+
+    case OPTION_MTUNE:
+      if (*arg == '.')
+       as_fatal (_("Invalid -mtune= option: `%s'"), arg);
+      for (i = 0; i < ARRAY_SIZE (cpu_arch); i++)
+       {
+         if (strcmp (arg, cpu_arch [i].name) == 0)
+           {
+             cpu_arch_tune_set = 1;
+             cpu_arch_tune = cpu_arch [i].type;
+             cpu_arch_tune_flags = cpu_arch[i].flags;
+             break;
+           }
+       }
+      if (i >= ARRAY_SIZE (cpu_arch))
+       as_fatal (_("Invalid -mtune= option: `%s'"), arg);
+      break;
+
     default:
       return 0;
     }
@@ -5528,6 +6132,10 @@ md_show_usage (stream)
   fprintf (stream, _("\
   -s                      ignored\n"));
 #endif
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined(TE_PEP)
+  fprintf (stream, _("\
+  --32/--64               generate 32bit/64bit code\n"));
+#endif
 #ifdef SVR4_COMMENT_CHARS
   fprintf (stream, _("\
   --divide                do not treat `/' as a comment character\n"));
@@ -5535,24 +6143,50 @@ md_show_usage (stream)
   fprintf (stream, _("\
   --divide                ignored\n"));
 #endif
+  fprintf (stream, _("\
+  -march=CPU/-mtune=CPU   generate code/optimize for CPU, where CPU is one of:\n\
+                           i386, i486, pentium, pentiumpro, pentium4, nocona,\n\
+                           core, core2, k6, athlon, k8, generic32, generic64\n"));
+
 }
 
 #if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \
-     || defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF))
+     || defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined (TE_PEP))
 
 /* Pick the target format to use.  */
 
 const char *
-i386_target_format ()
+i386_target_format (void)
 {
   if (!strcmp (default_arch, "x86_64"))
-    set_code_flag (CODE_64BIT);
+    {
+      set_code_flag (CODE_64BIT);
+      if (cpu_arch_isa_flags == 0)
+       cpu_arch_isa_flags = Cpu186|Cpu286|Cpu386|Cpu486
+                            |Cpu586|Cpu686|CpuP4|CpuMMX|CpuMMX2
+                            |CpuSSE|CpuSSE2;
+      if (cpu_arch_tune_flags == 0)
+       cpu_arch_tune_flags = Cpu186|Cpu286|Cpu386|Cpu486
+                             |Cpu586|Cpu686|CpuP4|CpuMMX|CpuMMX2
+                             |CpuSSE|CpuSSE2;
+    }
   else if (!strcmp (default_arch, "i386"))
-    set_code_flag (CODE_32BIT);
+    {
+      set_code_flag (CODE_32BIT);
+      if (cpu_arch_isa_flags == 0)
+       cpu_arch_isa_flags = Cpu186|Cpu286|Cpu386;
+      if (cpu_arch_tune_flags == 0)
+       cpu_arch_tune_flags = Cpu186|Cpu286|Cpu386;
+    }
   else
     as_fatal (_("Unknown architecture"));
   switch (OUTPUT_FLAVOR)
     {
+#ifdef TE_PEP
+    case bfd_target_coff_flavour:
+      return flag_code == CODE_64BIT ? COFF_TARGET_FORMAT : "coff-i386";
+      break;
+#endif
 #ifdef OBJ_MAYBE_AOUT
     case bfd_target_aout_flavour:
       return AOUT_TARGET_FORMAT;
@@ -5569,7 +6203,7 @@ i386_target_format ()
            object_64bit = 1;
            use_rela_relocations = 1;
          }
-       return flag_code == CODE_64BIT ? "elf64-x86-64" : ELF_TARGET_FORMAT;
+       return flag_code == CODE_64BIT ? ELF_TARGET_FORMAT64 : ELF_TARGET_FORMAT;
       }
 #endif
     default:
@@ -5581,7 +6215,8 @@ i386_target_format ()
 #endif /* OBJ_MAYBE_ more than one  */
 
 #if (defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF))
-void i386_elf_emit_arch_note ()
+void
+i386_elf_emit_arch_note (void)
 {
   if (IS_ELF && cpu_arch_name != NULL)
     {
@@ -5672,8 +6307,7 @@ md_section_align (segment, size)
    size, since the offset is always the last part of the insn.  */
 
 long
-md_pcrel_from (fixP)
-     fixS *fixP;
+md_pcrel_from (fixS *fixP)
 {
   return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
 }
@@ -5681,8 +6315,7 @@ md_pcrel_from (fixP)
 #ifndef I386COFF
 
 static void
-s_bss (ignore)
-     int ignore ATTRIBUTE_UNUSED;
+s_bss (int ignore ATTRIBUTE_UNUSED)
 {
   int temp;
 
@@ -5698,8 +6331,7 @@ s_bss (ignore)
 #endif
 
 void
-i386_validate_fix (fixp)
-     fixS *fixp;
+i386_validate_fix (fixS *fixp)
 {
   if (fixp->fx_subsy && fixp->fx_subsy == GOT_symbol)
     {
@@ -6048,8 +6680,8 @@ struct intel_parser_s
     int got_a_float;           /* Whether the operand is a float.  */
     int op_modifier;           /* Operand modifier.  */
     int is_mem;                        /* 1 if operand is memory reference.  */
-    int in_offset;                     /* >=1 if parsing operand of offset.  */
-    int in_bracket;                    /* >=1 if parsing operand in brackets.  */
+    int in_offset;             /* >=1 if parsing operand of offset.  */
+    int in_bracket;            /* >=1 if parsing operand in brackets.  */
     const reg_entry *reg;      /* Last register reference found.  */
     char *disp;                        /* Displacement string being built.  */
     char *next_operand;                /* Resume point when splitting operands.  */
@@ -6088,22 +6720,19 @@ static struct intel_token cur_token, prev_token;
 #define T_SHR          15
 
 /* Prototypes for intel parser functions.  */
-static int intel_match_token   PARAMS ((int code));
-static void intel_get_token    PARAMS ((void));
-static void intel_putback_token        PARAMS ((void));
-static int intel_expr          PARAMS ((void));
-static int intel_e04           PARAMS ((void));
-static int intel_e05           PARAMS ((void));
-static int intel_e06           PARAMS ((void));
-static int intel_e09           PARAMS ((void));
-static int intel_bracket_expr  PARAMS ((void));
-static int intel_e10           PARAMS ((void));
-static int intel_e11           PARAMS ((void));
+static int intel_match_token (int);
+static void intel_putback_token        (void);
+static void intel_get_token (void);
+static int intel_expr (void);
+static int intel_e04 (void);
+static int intel_e05 (void);
+static int intel_e06 (void);
+static int intel_e09 (void);
+static int intel_e10 (void);
+static int intel_e11 (void);
 
 static int
-i386_intel_operand (operand_string, got_a_float)
-     char *operand_string;
-     int got_a_float;
+i386_intel_operand (char *operand_string, int got_a_float)
 {
   int ret;
   char *p;
@@ -6193,7 +6822,7 @@ i386_intel_operand (operand_string, got_a_float)
        ret = i386_immediate (intel_parser.disp);
 
       if (intel_parser.next_operand && this_operand >= MAX_OPERANDS - 1)
-        ret = 0;
+       ret = 0;
       if (!ret || !intel_parser.next_operand)
        break;
       intel_parser.op_string = intel_parser.next_operand;
@@ -6213,7 +6842,7 @@ i386_intel_operand (operand_string, got_a_float)
    expr'  cmpOp e04 expr'
        | Empty  */
 static int
-intel_expr ()
+intel_expr (void)
 {
   /* XXX Implement the comparison operators.  */
   return intel_e04 ();
@@ -6224,7 +6853,7 @@ intel_expr ()
    e04'        addOp e05 e04'
        | Empty  */
 static int
-intel_e04 ()
+intel_e04 (void)
 {
   int nregs = -1;
 
@@ -6253,7 +6882,7 @@ intel_e04 ()
    e05'        binOp e06 e05'
        | Empty  */
 static int
-intel_e05 ()
+intel_e05 (void)
 {
   int nregs = ~NUM_ADDRESS_REGS;
 
@@ -6262,7 +6891,9 @@ intel_e05 ()
       if (!intel_e06())
        return 0;
 
-      if (cur_token.code == '&' || cur_token.code == '|' || cur_token.code == '^')
+      if (cur_token.code == '&'
+         || cur_token.code == '|'
+         || cur_token.code == '^')
        {
          char str[2];
 
@@ -6288,7 +6919,7 @@ intel_e05 ()
    e06'        mulOp e09 e06'
        | Empty  */
 static int
-intel_e06 ()
+intel_e06 (void)
 {
   int nregs = ~NUM_ADDRESS_REGS;
 
@@ -6297,7 +6928,9 @@ intel_e06 ()
       if (!intel_e09())
        return 0;
 
-      if (cur_token.code == '*' || cur_token.code == '/' || cur_token.code == '%')
+      if (cur_token.code == '*'
+         || cur_token.code == '/'
+         || cur_token.code == '%')
        {
          char str[2];
 
@@ -6334,7 +6967,7 @@ intel_e06 ()
        | : e10 e09'
        | Empty */
 static int
-intel_e09 ()
+intel_e09 (void)
 {
   int nregs = ~NUM_ADDRESS_REGS;
   int in_offset = 0;
@@ -6548,7 +7181,7 @@ intel_e09 ()
 }
 
 static int
-intel_bracket_expr ()
+intel_bracket_expr (void)
 {
   int was_offset = intel_parser.op_modifier & (1 << T_OFFSET);
   const char *start = intel_parser.op_string;
@@ -6609,7 +7242,8 @@ intel_bracket_expr ()
                /* Defer the warning until all of the operand was parsed.  */
                intel_parser.is_mem = -1;
              else if (!quiet_warnings)
-               as_warn (_("`[%.*s]' taken to mean just `%.*s'"), len, start, len, start);
+               as_warn (_("`[%.*s]' taken to mean just `%.*s'"),
+                        len, start, len, start);
            }
        }
       intel_parser.op_modifier |= was_offset;
@@ -6624,7 +7258,7 @@ intel_bracket_expr ()
    e10'        [ expr ] e10'
        | Empty  */
 static int
-intel_e10 ()
+intel_e10 (void)
 {
   if (!intel_e11 ())
     return 0;
@@ -6654,7 +7288,7 @@ intel_e10 ()
        | id
        | constant  */
 static int
-intel_e11 ()
+intel_e11 (void)
 {
   switch (cur_token.code)
     {
@@ -6699,7 +7333,8 @@ intel_e11 ()
          {
            if (!(reg->reg_type & (SReg2 | SReg3)))
              {
-               as_bad (_("`%s' is not a valid segment register"), reg->reg_name);
+               as_bad (_("`%s' is not a valid segment register"),
+                       reg->reg_name);
                return 0;
              }
            else if (i.seg[i.mem_operands])
@@ -6889,7 +7524,8 @@ intel_e11 ()
        /* Get the next token to check for register scaling.  */
        intel_match_token (cur_token.code);
 
-       /* Check if this constant is a scaling factor for an index register.  */
+       /* Check if this constant is a scaling factor for an
+          index register.  */
        if (cur_token.code == '*')
          {
            if (intel_match_token ('*') && cur_token.code == T_REG)
@@ -6898,14 +7534,17 @@ intel_e11 ()
 
                if (!intel_parser.in_bracket)
                  {
-                   as_bad (_("Register scaling only allowed in memory operands"));
+                   as_bad (_("Register scaling only allowed "
+                             "in memory operands"));
                    return 0;
                  }
 
-               if (reg->reg_type & Reg16) /* Disallow things like [1*si]. */
-                 reg = i386_regtab + REGNAM_AX + 4; /* sp is invalid as index */
+                /* Disallow things like [1*si].
+                   sp and esp are invalid as index.  */
+               if (reg->reg_type & Reg16)
+                 reg = i386_regtab + REGNAM_AX + 4;
                else if (i.index_reg)
-                 reg = i386_regtab + REGNAM_EAX + 4; /* esp is invalid as index */
+                 reg = i386_regtab + REGNAM_EAX + 4;
 
                /* The constant is followed by `* reg', so it must be
                   a valid scale.  */
@@ -6955,8 +7594,7 @@ intel_e11 ()
 /* Match the given token against cur_token. If they match, read the next
    token from the operand string.  */
 static int
-intel_match_token (code)
-     int code;
+intel_match_token (int code)
 {
   if (cur_token.code == code)
     {
@@ -6972,7 +7610,7 @@ intel_match_token (code)
 
 /* Read a new token from intel_parser.op_string and store it in cur_token.  */
 static void
-intel_get_token ()
+intel_get_token (void)
 {
   char *end_op;
   const reg_entry *reg;
@@ -7157,7 +7795,7 @@ intel_get_token ()
 /* Put cur_token back into the token stream and make cur_token point to
    prev_token.  */
 static void
-intel_putback_token ()
+intel_putback_token (void)
 {
   if (cur_token.code != T_NIL)
     {
@@ -7173,7 +7811,7 @@ intel_putback_token ()
 }
 
 int
-tc_x86_regname_to_dw2regnum (const char *regname)
+tc_x86_regname_to_dw2regnum (char *regname)
 {
   unsigned int regnum;
   unsigned int regnames_count;
@@ -7293,7 +7931,7 @@ x86_64_section_letter (int letter, char **ptr_msg)
 int
 x86_64_section_word (char *str, size_t len)
 {
-  if (len == 5 && flag_code == CODE_64BIT && strncmp (str, "large", 5) == 0)
+  if (len == 5 && flag_code == CODE_64BIT && CONST_STRNEQ (str, "large"))
     return SHF_X86_64_LARGE;
 
   return -1;
This page took 0.065928 seconds and 4 git commands to generate.