Add vmfunc
[deliverable/binutils-gdb.git] / gas / config / tc-i386.c
index 03ea5625d2c877579be3d8069f1f0dd443575098..9e83a4d0a469f8fdf3252b5c9a22cb01b0eb1db3 100644 (file)
@@ -1,6 +1,7 @@
 /* tc-i386.c -- Assemble code for the Intel 80386
    Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
+   2012
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -132,6 +133,7 @@ typedef struct
   enum processor_type type;    /* arch type */
   i386_cpu_flags flags;                /* cpu feature flags */
   unsigned int skip;           /* show_arch should skip this. */
+  unsigned int negated;                /* turn off indicated flags.  */
 }
 arch_entry;
 
@@ -216,7 +218,9 @@ enum i386_error
     old_gcc_only,
     unsupported_with_intel_mnemonic,
     unsupported_syntax,
-    unsupported
+    unsupported,
+    invalid_vsib_address,
+    unsupported_vector_index_register
   };
 
 struct _i386_insn
@@ -276,6 +280,9 @@ struct _i386_insn
     /* Swap operand in encoding.  */
     unsigned int swap_operand;
 
+    /* Force 32bit displacement in encoding.  */
+    unsigned int disp32_encoding;
+
     /* Error message.  */
     enum i386_error error;
   };
@@ -299,6 +306,7 @@ const char extra_symbol_chars[] = "*%-(["
         && !defined (TE_LINUX)                         \
         && !defined (TE_NETWARE)                       \
         && !defined (TE_FreeBSD)                       \
+        && !defined (TE_DragonFly)                     \
         && !defined (TE_NetBSD)))
 /* This array holds the chars that always start a comment.  If the
    pre-processor is disabled, these aren't very useful.  The option
@@ -385,8 +393,24 @@ enum flag_code {
 
 static enum flag_code flag_code;
 static unsigned int object_64bit;
+static unsigned int disallow_64bit_reloc;
 static int use_rela_relocations = 0;
 
+#if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \
+     || defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) \
+     || defined (TE_PE) || defined (TE_PEP) || defined (OBJ_MACH_O))
+
+/* The ELF ABI to use.  */
+enum x86_elf_abi
+{
+  I386_ABI,
+  X86_64_ABI,
+  X86_64_X32_ABI
+};
+
+static enum x86_elf_abi x86_elf_abi = I386_ABI;
+#endif
+
 /* The names used to print error messages.  */
 static const char *flag_code_names[] =
   {
@@ -566,149 +590,169 @@ static const arch_entry cpu_arch[] =
   /* Do not replace the first two entries - i386_target_format()
      relies on them being there in this order.  */
   { STRING_COMMA_LEN ("generic32"), PROCESSOR_GENERIC32,
-    CPU_GENERIC32_FLAGS, 0 },
+    CPU_GENERIC32_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("generic64"), PROCESSOR_GENERIC64,
-    CPU_GENERIC64_FLAGS, 0 },
+    CPU_GENERIC64_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("i8086"), PROCESSOR_UNKNOWN,
-    CPU_NONE_FLAGS, 0 },
+    CPU_NONE_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("i186"), PROCESSOR_UNKNOWN,
-    CPU_I186_FLAGS, 0 },
+    CPU_I186_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("i286"), PROCESSOR_UNKNOWN,
-    CPU_I286_FLAGS, 0 },
+    CPU_I286_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("i386"), PROCESSOR_I386,
-    CPU_I386_FLAGS, 0 },
+    CPU_I386_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("i486"), PROCESSOR_I486,
-    CPU_I486_FLAGS, 0 },
+    CPU_I486_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("i586"), PROCESSOR_PENTIUM,
-    CPU_I586_FLAGS, 0 },
+    CPU_I586_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("i686"), PROCESSOR_PENTIUMPRO,
-    CPU_I686_FLAGS, 0 },
+    CPU_I686_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("pentium"), PROCESSOR_PENTIUM,
-    CPU_I586_FLAGS, 0 },
+    CPU_I586_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("pentiumpro"), PROCESSOR_PENTIUMPRO,
-    CPU_I686_FLAGS, 0 },
+    CPU_PENTIUMPRO_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("pentiumii"), PROCESSOR_PENTIUMPRO,
-    CPU_P2_FLAGS, 0 },
+    CPU_P2_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("pentiumiii"),PROCESSOR_PENTIUMPRO,
-    CPU_P3_FLAGS, 0 },
+    CPU_P3_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("pentium4"), PROCESSOR_PENTIUM4,
-    CPU_P4_FLAGS, 0 },
+    CPU_P4_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("prescott"), PROCESSOR_NOCONA,
-    CPU_CORE_FLAGS, 0 },
+    CPU_CORE_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("nocona"), PROCESSOR_NOCONA,
-    CPU_NOCONA_FLAGS, 0 },
+    CPU_NOCONA_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("yonah"), PROCESSOR_CORE,
-    CPU_CORE_FLAGS, 1 },
+    CPU_CORE_FLAGS, 1, 0 },
   { STRING_COMMA_LEN ("core"), PROCESSOR_CORE,
-    CPU_CORE_FLAGS, 0 },
+    CPU_CORE_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("merom"), PROCESSOR_CORE2,
-    CPU_CORE2_FLAGS, 1 },
+    CPU_CORE2_FLAGS, 1, 0 },
   { STRING_COMMA_LEN ("core2"), PROCESSOR_CORE2,
-    CPU_CORE2_FLAGS, 0 },
+    CPU_CORE2_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("corei7"), PROCESSOR_COREI7,
-    CPU_COREI7_FLAGS, 0 },
+    CPU_COREI7_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("l1om"), PROCESSOR_L1OM,
-    CPU_L1OM_FLAGS, 0 },
+    CPU_L1OM_FLAGS, 0, 0 },
+  { STRING_COMMA_LEN ("k1om"), PROCESSOR_K1OM,
+    CPU_K1OM_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("k6"), PROCESSOR_K6,
-    CPU_K6_FLAGS, 0 },
+    CPU_K6_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("k6_2"), PROCESSOR_K6,
-    CPU_K6_2_FLAGS, 0 },
+    CPU_K6_2_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("athlon"), PROCESSOR_ATHLON,
-    CPU_ATHLON_FLAGS, 0 },
+    CPU_ATHLON_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("sledgehammer"), PROCESSOR_K8,
-    CPU_K8_FLAGS, 1 },
+    CPU_K8_FLAGS, 1, 0 },
   { STRING_COMMA_LEN ("opteron"), PROCESSOR_K8,
-    CPU_K8_FLAGS, 0 },
+    CPU_K8_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("k8"), PROCESSOR_K8,
-    CPU_K8_FLAGS, 0 },
+    CPU_K8_FLAGS, 0, 0 },
   { STRING_COMMA_LEN ("amdfam10"), PROCESSOR_AMDFAM10,
-    CPU_AMDFAM10_FLAGS, 0 },
-  { STRING_COMMA_LEN ("bdver1"), PROCESSOR_BDVER1,
-    CPU_BDVER1_FLAGS, 0 },
+    CPU_AMDFAM10_FLAGS, 0, 0 },
+  { STRING_COMMA_LEN ("bdver1"), PROCESSOR_BD,
+    CPU_BDVER1_FLAGS, 0, 0 },
+  { STRING_COMMA_LEN ("bdver2"), PROCESSOR_BD,
+    CPU_BDVER2_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".8087"), PROCESSOR_UNKNOWN,
-    CPU_8087_FLAGS, 0 },
+    CPU_8087_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".287"), PROCESSOR_UNKNOWN,
-    CPU_287_FLAGS, 0 },
+    CPU_287_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".387"), PROCESSOR_UNKNOWN,
-    CPU_387_FLAGS, 0 },
+    CPU_387_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".no87"), PROCESSOR_UNKNOWN,
-    CPU_ANY87_FLAGS, 0 },
+    CPU_ANY87_FLAGS, 0, 1 },
   { STRING_COMMA_LEN (".mmx"), PROCESSOR_UNKNOWN,
-    CPU_MMX_FLAGS, 0 },
+    CPU_MMX_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".nommx"), PROCESSOR_UNKNOWN,
-    CPU_3DNOWA_FLAGS, 0 },
+    CPU_3DNOWA_FLAGS, 0, 1 },
   { STRING_COMMA_LEN (".sse"), PROCESSOR_UNKNOWN,
-    CPU_SSE_FLAGS, 0 },
+    CPU_SSE_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".sse2"), PROCESSOR_UNKNOWN,
-    CPU_SSE2_FLAGS, 0 },
+    CPU_SSE2_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".sse3"), PROCESSOR_UNKNOWN,
-    CPU_SSE3_FLAGS, 0 },
+    CPU_SSE3_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".ssse3"), PROCESSOR_UNKNOWN,
-    CPU_SSSE3_FLAGS, 0 },
+    CPU_SSSE3_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".sse4.1"), PROCESSOR_UNKNOWN,
-    CPU_SSE4_1_FLAGS, 0 },
+    CPU_SSE4_1_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".sse4.2"), PROCESSOR_UNKNOWN,
-    CPU_SSE4_2_FLAGS, 0 },
+    CPU_SSE4_2_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".sse4"), PROCESSOR_UNKNOWN,
-    CPU_SSE4_2_FLAGS, 0 },
+    CPU_SSE4_2_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".nosse"), PROCESSOR_UNKNOWN,
-    CPU_ANY_SSE_FLAGS, 0 },
+    CPU_ANY_SSE_FLAGS, 0, 1 },
   { STRING_COMMA_LEN (".avx"), PROCESSOR_UNKNOWN,
-    CPU_AVX_FLAGS, 0 },
+    CPU_AVX_FLAGS, 0, 0 },
+  { STRING_COMMA_LEN (".avx2"), PROCESSOR_UNKNOWN,
+    CPU_AVX2_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".noavx"), PROCESSOR_UNKNOWN,
-    CPU_ANY_AVX_FLAGS, 0 },
+    CPU_ANY_AVX_FLAGS, 0, 1 },
   { STRING_COMMA_LEN (".vmx"), PROCESSOR_UNKNOWN,
-    CPU_VMX_FLAGS, 0 },
+    CPU_VMX_FLAGS, 0, 0 },
+  { STRING_COMMA_LEN (".vmfunc"), PROCESSOR_UNKNOWN,
+    CPU_VMFUNC_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".smx"), PROCESSOR_UNKNOWN,
-    CPU_SMX_FLAGS, 0 },
+    CPU_SMX_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".xsave"), PROCESSOR_UNKNOWN,
-    CPU_XSAVE_FLAGS, 0 },
+    CPU_XSAVE_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".xsaveopt"), PROCESSOR_UNKNOWN,
-    CPU_XSAVEOPT_FLAGS, 0 },
+    CPU_XSAVEOPT_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".aes"), PROCESSOR_UNKNOWN,
-    CPU_AES_FLAGS, 0 },
+    CPU_AES_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".pclmul"), PROCESSOR_UNKNOWN,
-    CPU_PCLMUL_FLAGS, 0 },
+    CPU_PCLMUL_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".clmul"), PROCESSOR_UNKNOWN,
-    CPU_PCLMUL_FLAGS, 1 },
+    CPU_PCLMUL_FLAGS, 1, 0 },
   { STRING_COMMA_LEN (".fsgsbase"), PROCESSOR_UNKNOWN,
-    CPU_FSGSBASE_FLAGS, 0 },
+    CPU_FSGSBASE_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".rdrnd"), PROCESSOR_UNKNOWN,
-    CPU_RDRND_FLAGS, 0 },
+    CPU_RDRND_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".f16c"), PROCESSOR_UNKNOWN,
-    CPU_F16C_FLAGS, 0 },
+    CPU_F16C_FLAGS, 0, 0 },
+  { STRING_COMMA_LEN (".bmi2"), PROCESSOR_UNKNOWN,
+    CPU_BMI2_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".fma"), PROCESSOR_UNKNOWN,
-    CPU_FMA_FLAGS, 0 },
+    CPU_FMA_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".fma4"), PROCESSOR_UNKNOWN,
-    CPU_FMA4_FLAGS, 0 },
+    CPU_FMA4_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".xop"), PROCESSOR_UNKNOWN,
-    CPU_XOP_FLAGS, 0 },
+    CPU_XOP_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".lwp"), PROCESSOR_UNKNOWN,
-    CPU_LWP_FLAGS, 0 },
+    CPU_LWP_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".movbe"), PROCESSOR_UNKNOWN,
-    CPU_MOVBE_FLAGS, 0 },
+    CPU_MOVBE_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".ept"), PROCESSOR_UNKNOWN,
-    CPU_EPT_FLAGS, 0 },
+    CPU_EPT_FLAGS, 0, 0 },
+  { STRING_COMMA_LEN (".lzcnt"), PROCESSOR_UNKNOWN,
+    CPU_LZCNT_FLAGS, 0, 0 },
+  { STRING_COMMA_LEN (".invpcid"), PROCESSOR_UNKNOWN,
+    CPU_INVPCID_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".clflush"), PROCESSOR_UNKNOWN,
-    CPU_CLFLUSH_FLAGS, 0 },
+    CPU_CLFLUSH_FLAGS, 0, 0 },
+  { STRING_COMMA_LEN (".nop"), PROCESSOR_UNKNOWN,
+    CPU_NOP_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".syscall"), PROCESSOR_UNKNOWN,
-    CPU_SYSCALL_FLAGS, 0 },
+    CPU_SYSCALL_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".rdtscp"), PROCESSOR_UNKNOWN,
-    CPU_RDTSCP_FLAGS, 0 },
+    CPU_RDTSCP_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".3dnow"), PROCESSOR_UNKNOWN,
-    CPU_3DNOW_FLAGS, 0 },
+    CPU_3DNOW_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".3dnowa"), PROCESSOR_UNKNOWN,
-    CPU_3DNOWA_FLAGS, 0 },
+    CPU_3DNOWA_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".padlock"), PROCESSOR_UNKNOWN,
-    CPU_PADLOCK_FLAGS, 0 },
+    CPU_PADLOCK_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".pacifica"), PROCESSOR_UNKNOWN,
-    CPU_SVME_FLAGS, 1 },
+    CPU_SVME_FLAGS, 1, 0 },
   { STRING_COMMA_LEN (".svme"), PROCESSOR_UNKNOWN,
-    CPU_SVME_FLAGS, 0 },
+    CPU_SVME_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".sse4a"), PROCESSOR_UNKNOWN,
-    CPU_SSE4A_FLAGS, 0 },
+    CPU_SSE4A_FLAGS, 0, 0 },
   { STRING_COMMA_LEN (".abm"), PROCESSOR_UNKNOWN,
-    CPU_ABM_FLAGS, 0 },
+    CPU_ABM_FLAGS, 0, 0 },
+  { STRING_COMMA_LEN (".bmi"), PROCESSOR_UNKNOWN,
+    CPU_BMI_FLAGS, 0, 0 },
+  { STRING_COMMA_LEN (".tbm"), PROCESSOR_UNKNOWN,
+    CPU_TBM_FLAGS, 0, 0 },
 };
 
 #ifdef I386COFF
@@ -994,11 +1038,11 @@ i386_align_code (fragS *fragP, int count)
      PROCESSOR_CORE, PROCESSOR_CORE2, PROCESSOR_COREI7, and
      PROCESSOR_GENERIC64, alt_long_patt will be used.
      3. For PROCESSOR_ATHLON, PROCESSOR_K6, PROCESSOR_K8 and
-     PROCESSOR_AMDFAM10, and PROCESSOR_BDVER1, alt_short_patt
+     PROCESSOR_AMDFAM10, and PROCESSOR_BD, 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
+     cpu_arch_isa_flags has CpuNop.  Otherwise, f32_patt will
      be used.
 
      When -march= or .arch is used, we can't use anything beyond
@@ -1028,19 +1072,19 @@ i386_align_code (fragS *fragP, int count)
            {
            case PROCESSOR_UNKNOWN:
              /* We use cpu_arch_isa_flags to check if we SHOULD
-                optimize for Cpu686.  */
-             if (fragP->tc_frag_data.isa_flags.bitfield.cpui686)
+                optimize with nops.  */
+             if (fragP->tc_frag_data.isa_flags.bitfield.cpunop)
                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_COREI7:
            case PROCESSOR_L1OM:
+           case PROCESSOR_K1OM:
            case PROCESSOR_GENERIC64:
              patt = alt_long_patt;
              break;
@@ -1048,12 +1092,13 @@ i386_align_code (fragS *fragP, int count)
            case PROCESSOR_ATHLON:
            case PROCESSOR_K8:
            case PROCESSOR_AMDFAM10:
-           case PROCESSOR_BDVER1:
+           case PROCESSOR_BD:
              patt = alt_short_patt;
              break;
            case PROCESSOR_I386:
            case PROCESSOR_I486:
            case PROCESSOR_PENTIUM:
+           case PROCESSOR_PENTIUMPRO:
            case PROCESSOR_GENERIC32:
              patt = f32_patt;
              break;
@@ -1076,11 +1121,11 @@ i386_align_code (fragS *fragP, int count)
            case PROCESSOR_ATHLON:
            case PROCESSOR_K8:
            case PROCESSOR_AMDFAM10:
-           case PROCESSOR_BDVER1:
+           case PROCESSOR_BD:
            case PROCESSOR_GENERIC32:
              /* We use cpu_arch_isa_flags to check if we CAN optimize
-                for Cpu686.  */
-             if (fragP->tc_frag_data.isa_flags.bitfield.cpui686)
+                with nops.  */
+             if (fragP->tc_frag_data.isa_flags.bitfield.cpunop)
                patt = alt_short_patt;
              else
                patt = f32_patt;
@@ -1092,7 +1137,8 @@ i386_align_code (fragS *fragP, int count)
            case PROCESSOR_CORE2:
            case PROCESSOR_COREI7:
            case PROCESSOR_L1OM:
-             if (fragP->tc_frag_data.isa_flags.bitfield.cpui686)
+           case PROCESSOR_K1OM:
+             if (fragP->tc_frag_data.isa_flags.bitfield.cpunop)
                patt = alt_long_patt;
              else
                patt = f32_patt;
@@ -2084,6 +2130,11 @@ check_cpu_arch_compatible (const char *name ATTRIBUTE_UNUSED,
       || new_flag.bitfield.cpul1om)
     return;
 
+  /* If we are targeting Intel K1OM, we must enable it.  */
+  if (get_elf_backend_data (stdoutput)->elf_machine_code != EM_K1OM
+      || new_flag.bitfield.cpuk1om)
+    return;
+
   as_bad (_("`%s' is not supported on `%s'"), name, arch);
 #endif
 }
@@ -2131,7 +2182,7 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED)
                  break;
                }
 
-             if (strncmp (string + 1, "no", 2))
+             if (!cpu_arch[j].negated)
                flags = cpu_flags_or (cpu_arch_flags,
                                      cpu_arch[j].flags);
              else
@@ -2150,6 +2201,7 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED)
                  else
                    cpu_sub_arch_name = xstrdup (cpu_arch[j].name);
                  cpu_arch_flags = flags;
+                 cpu_arch_isa_flags = flags;
                }
              *input_line_pointer = e;
              demand_empty_rest_of_line ();
@@ -2194,32 +2246,49 @@ i386_arch (void)
        as_fatal (_("Intel L1OM is 64bit ELF only"));
       return bfd_arch_l1om;
     }
+  else if (cpu_arch_isa == PROCESSOR_K1OM)
+    {
+      if (OUTPUT_FLAVOR != bfd_target_elf_flavour
+         || flag_code != CODE_64BIT)
+       as_fatal (_("Intel K1OM is 64bit ELF only"));
+      return bfd_arch_k1om;
+    }
   else
     return bfd_arch_i386;
 }
 
 unsigned long
-i386_mach ()
+i386_mach (void)
 {
-  if (!strcmp (default_arch, "x86_64"))
+  if (!strncmp (default_arch, "x86_64", 6))
     {
       if (cpu_arch_isa == PROCESSOR_L1OM)
        {
-         if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
+         if (OUTPUT_FLAVOR != bfd_target_elf_flavour
+             || default_arch[6] != '\0')
            as_fatal (_("Intel L1OM is 64bit ELF only"));
          return bfd_mach_l1om;
        }
-      else
+      else if (cpu_arch_isa == PROCESSOR_K1OM)
+       {
+         if (OUTPUT_FLAVOR != bfd_target_elf_flavour
+             || default_arch[6] != '\0')
+           as_fatal (_("Intel K1OM is 64bit ELF only"));
+         return bfd_mach_k1om;
+       }
+      else if (default_arch[6] == '\0')
        return bfd_mach_x86_64;
+      else
+       return bfd_mach_x64_32;
     }
   else if (!strcmp (default_arch, "i386"))
     return bfd_mach_i386_i386;
   else
-    as_fatal (_("Unknown architecture"));
+    as_fatal (_("unknown architecture"));
 }
 \f
 void
-md_begin ()
+md_begin (void)
 {
   const char *hash_err;
 
@@ -2249,7 +2318,7 @@ md_begin ()
                                    (void *) core_optab);
            if (hash_err)
              {
-               as_fatal (_("Internal Error:  Can't hash %s: %s"),
+               as_fatal (_("internal Error:  Can't hash %s: %s"),
                          (optab - 1)->name,
                          hash_err);
              }
@@ -2271,7 +2340,7 @@ md_begin ()
       {
        hash_err = hash_insert (reg_hash, regtab->reg_name, (void *) regtab);
        if (hash_err)
-         as_fatal (_("Internal Error:  Can't hash %s: %s"),
+         as_fatal (_("internal Error:  Can't hash %s: %s"),
                    regtab->reg_name,
                    hash_err);
       }
@@ -2342,7 +2411,12 @@ md_begin ()
 
   if (flag_code == CODE_64BIT)
     {
+#if defined (OBJ_COFF) && defined (TE_PE)
+      x86_dwarf2_return_column = (OUTPUT_FLAVOR == bfd_target_coff_flavour
+                                 ? 32 : 16);
+#else
       x86_dwarf2_return_column = 16;
+#endif
       x86_cie_data_alignment = -8;
     }
   else
@@ -2556,7 +2630,7 @@ reloc (unsigned int size,
          }
 
       /* Sign-checking 4-byte relocations in 16-/32-bit code is pointless.  */
-      if (size == 4 && flag_code != CODE_64BIT)
+      if (size == 4 && (flag_code != CODE_64BIT || disallow_64bit_reloc))
        sign = -1;
 
       rel = bfd_reloc_type_lookup (stdoutput, other);
@@ -2800,6 +2874,7 @@ build_vex_prefix (const insn_template *t)
 
   /* Use 2-byte VEX prefix if possible.  */
   if (i.tm.opcode_modifier.vexopcode == VEX0F
+      && i.tm.opcode_modifier.vexw != VEXW1
       && (i.rex & (REX_W | REX_X | REX_B)) == 0)
     {
       /* 2-byte VEX prefix.  */
@@ -2978,6 +3053,7 @@ md_assemble (char *line)
   /* Don't optimize displacement for movabs since it only takes 64bit
      displacement.  */
   if (i.disp_operands
+      && !i.disp32_encoding
       && (flag_code != CODE_64BIT
          || strcmp (mnemonic, "movabs") != 0))
     optimize_disp ();
@@ -3252,9 +3328,15 @@ parse_insn (char *line, char *mnemonic)
 
   if (!current_templates)
     {
-      /* Check if we should swap operand in encoding.  */
+      /* Check if we should swap operand or force 32bit displacement in
+        encoding.  */
       if (mnem_p - 2 == dot_p && dot_p[1] == 's')
        i.swap_operand = 1;
+      else if (mnem_p - 4 == dot_p 
+              && dot_p[1] == 'd'
+              && dot_p[2] == '3'
+              && dot_p[3] == '2')
+       i.disp32_encoding = 1;
       else
        goto check_suffix;
       mnem_p = dot_p;
@@ -3786,7 +3868,39 @@ optimize_disp (void)
       }
 }
 
-/* Check if operands are valid for the instrucrtion.  Update VEX
+/* Check if operands are valid for the instruction.  */
+
+static int
+check_VecOperands (const insn_template *t)
+{
+  /* Without VSIB byte, we can't have a vector register for index.  */
+  if (!t->opcode_modifier.vecsib
+      && i.index_reg
+      && (i.index_reg->reg_type.bitfield.regxmm
+         || i.index_reg->reg_type.bitfield.regymm))
+    {
+      i.error = unsupported_vector_index_register;
+      return 1;
+    }
+
+  /* For VSIB byte, we need a vector register for index and no PC
+     relative addressing is allowed.  */
+  if (t->opcode_modifier.vecsib
+      && (!i.index_reg
+         || !((t->opcode_modifier.vecsib == VecSIB128
+               && i.index_reg->reg_type.bitfield.regxmm)
+              || (t->opcode_modifier.vecsib == VecSIB256
+                  && i.index_reg->reg_type.bitfield.regymm))
+         || (i.base_reg && i.base_reg->reg_num == RegRip)))
+    {
+      i.error = invalid_vsib_address;
+      return 1;
+    }
+
+  return 0;
+}
+
+/* Check if operands are valid for the instruction.  Update VEX
    operand types.  */
 
 static int
@@ -3982,9 +4096,8 @@ match_template (void)
            }
          }
 
-      /* We check register size only if size of operands can be
-        encoded the canonical way.  */
-      check_register = t->opcode_modifier.w;
+      /* We check register size if needed.  */
+      check_register = t->opcode_modifier.checkregsize;
       overlap0 = operand_type_and (i.types[0], operand_types[0]);
       switch (t->operands)
        {
@@ -4123,6 +4236,10 @@ check_reverse:
          continue;
        }
 
+      /* Check if vector operands are valid.  */
+      if (check_VecOperands (t))
+       continue;
+
       /* Check if VEX operands are valid.  */
       if (VEX_check_operands (t))
        continue;
@@ -4169,6 +4286,12 @@ check_reverse:
        case unsupported:
          err_msg = _("unsupported");
          break;
+       case invalid_vsib_address:
+         err_msg = _("invalid VSIB address");
+         break;
+       case unsupported_vector_index_register:
+         err_msg = _("unsupported vector index register");
+         break;
        }
       as_bad (_("%s for `%s'"), err_msg,
              current_templates->start->name);
@@ -4549,7 +4672,7 @@ check_byte_reg (void)
          if (flag_code == CODE_64BIT
              && !i.tm.operand_types[op].bitfield.inoutportreg)
            {
-             as_bad (_("Incorrect register `%s%s' used with `%c' suffix"),
+             as_bad (_("incorrect register `%s%s' used with `%c' suffix"),
                      register_prefix, i.op[op].regs->reg_name,
                      i.suffix);
              return 0;
@@ -4624,7 +4747,7 @@ check_long_reg (void)
           lowering is more complicated.  */
        if (flag_code == CODE_64BIT)
          {
-           as_bad (_("Incorrect register `%s%s' used with `%c' suffix"),
+           as_bad (_("incorrect register `%s%s' used with `%c' suffix"),
                    register_prefix, i.op[op].regs->reg_name,
                    i.suffix);
            return 0;
@@ -4653,7 +4776,7 @@ check_long_reg (void)
          }
        else
          {
-           as_bad (_("Incorrect register `%s%s' used with `%c' suffix"),
+           as_bad (_("incorrect register `%s%s' used with `%c' suffix"),
                    register_prefix, i.op[op].regs->reg_name,
                    i.suffix);
            return 0;
@@ -4699,7 +4822,7 @@ check_qword_reg (void)
          }
        else
          {
-           as_bad (_("Incorrect register `%s%s' used with `%c' suffix"),
+           as_bad (_("incorrect register `%s%s' used with `%c' suffix"),
                    register_prefix, i.op[op].regs->reg_name,
                    i.suffix);
            return 0;
@@ -4737,7 +4860,7 @@ check_word_reg (void)
           lowering is more complicated.  */
        if (flag_code == CODE_64BIT)
          {
-           as_bad (_("Incorrect register `%s%s' used with `%c' suffix"),
+           as_bad (_("incorrect register `%s%s' used with `%c' suffix"),
                    register_prefix, i.op[op].regs->reg_name,
                    i.suffix);
            return 0;
@@ -5261,15 +5384,15 @@ build_modrm_byte (void)
                          && i.imm_operands == 1
                          && (i.types[0].bitfield.imm8
                              || i.types[i.operands - 1].bitfield.imm8)));
-         if (i.tm.opcode_modifier.vexvvvv == VEXXDS)
+         if (i.imm_operands == 2)
+           source = 2;
+         else
            {
              if (i.types[0].bitfield.imm8)
                source = 1;
              else
                source = 0;
            }
-         else
-           source = 2;
          break;
        case 5:
          break;
@@ -5284,16 +5407,34 @@ build_modrm_byte (void)
          if (i.tm.opcode_modifier.vexvvvv == VEXXDS)
            {
              /* For instructions with VexNDS, the register-only
-                source operand must be XMM or YMM register. It is
-                encoded in VEX prefix.  We need to clear RegMem bit
-                before calling operand_type_equal.  */
-             i386_operand_type op = i.tm.operand_types[dest];
+                source operand must be 32/64bit integer, XMM or
+                YMM register.  It is encoded in VEX prefix.  We
+                need to clear RegMem bit before calling
+                operand_type_equal.  */
+
+             i386_operand_type op;
+             unsigned int vvvv;
+
+             /* Check register-only source operand when two source
+                operands are swapped.  */
+             if (!i.tm.operand_types[source].bitfield.baseindex
+                 && i.tm.operand_types[dest].bitfield.baseindex)
+               {
+                 vvvv = source;
+                 source = dest;
+               }
+             else
+               vvvv = dest;
+
+             op = i.tm.operand_types[vvvv];
              op.bitfield.regmem = 0;
              if ((dest + 1) >= i.operands
-                 || (!operand_type_equal (&op, &regxmm)
+                 || (op.bitfield.reg32 != 1
+                     && !op.bitfield.reg64 != 1
+                     && !operand_type_equal (&op, &regxmm)
                      && !operand_type_equal (&op, &regymm)))
                abort ();
-             i.vex.register_specifier = i.op[dest].regs;
+             i.vex.register_specifier = i.op[vvvv].regs;
              dest++;
            }
        }
@@ -5347,15 +5488,53 @@ build_modrm_byte (void)
              break;
          gas_assert (op < i.operands);
 
+         if (i.tm.opcode_modifier.vecsib)
+           {
+             if (i.index_reg->reg_num == RegEiz
+                 || i.index_reg->reg_num == RegRiz)
+               abort ();
+
+             i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
+             if (!i.base_reg)
+               {
+                 i.sib.base = NO_BASE_REGISTER;
+                 i.sib.scale = i.log2_scale_factor;
+                 i.types[op].bitfield.disp8 = 0;
+                 i.types[op].bitfield.disp16 = 0;
+                 i.types[op].bitfield.disp64 = 0;
+                 if (flag_code != CODE_64BIT)
+                   {
+                     /* Must be 32 bit */
+                     i.types[op].bitfield.disp32 = 1;
+                     i.types[op].bitfield.disp32s = 0;
+                   }
+                 else
+                   {
+                     i.types[op].bitfield.disp32 = 0;
+                     i.types[op].bitfield.disp32s = 1;
+                   }
+               }
+             i.sib.index = i.index_reg->reg_num;
+             if ((i.index_reg->reg_flags & RegRex) != 0)
+               i.rex |= REX_X;
+           }
+
          default_seg = &ds;
 
          if (i.base_reg == 0)
            {
              i.rm.mode = 0;
              if (!i.disp_operands)
-               fake_zero_displacement = 1;
+               {
+                 fake_zero_displacement = 1;
+                 /* Instructions with VSIB byte need 32bit displacement
+                    if there is no base register.  */
+                 if (i.tm.opcode_modifier.vecsib)
+                   i.types[op].bitfield.disp32 = 1;
+               }
              if (i.index_reg == 0)
                {
+                 gas_assert (!i.tm.opcode_modifier.vecsib);
                  /* Operand is just <disp>  */
                  if (flag_code == CODE_64BIT)
                    {
@@ -5381,8 +5560,9 @@ build_modrm_byte (void)
                      i.types[op] = disp32;
                    }
                }
-             else /* !i.base_reg && i.index_reg  */
+             else if (!i.tm.opcode_modifier.vecsib)
                {
+                 /* !i.base_reg && i.index_reg  */
                  if (i.index_reg->reg_num == RegEiz
                      || i.index_reg->reg_num == RegRiz)
                    i.sib.index = NO_INDEX_REGISTER;
@@ -5413,6 +5593,7 @@ build_modrm_byte (void)
          else if (i.base_reg->reg_num == RegRip ||
                   i.base_reg->reg_num == RegEip)
            {
+             gas_assert (!i.tm.opcode_modifier.vecsib);
              i.rm.regmem = NO_BASE_REGISTER;
              i.types[op].bitfield.disp8 = 0;
              i.types[op].bitfield.disp16 = 0;
@@ -5425,6 +5606,7 @@ build_modrm_byte (void)
            }
          else if (i.base_reg->reg_type.bitfield.reg16)
            {
+             gas_assert (!i.tm.opcode_modifier.vecsib);
              switch (i.base_reg->reg_num)
                {
                case 3: /* (%bx)  */
@@ -5468,7 +5650,8 @@ build_modrm_byte (void)
                    i.types[op].bitfield.disp32 = 1;
                }
 
-             i.rm.regmem = i.base_reg->reg_num;
+             if (!i.tm.opcode_modifier.vecsib)
+               i.rm.regmem = i.base_reg->reg_num;
              if ((i.base_reg->reg_flags & RegRex) != 0)
                i.rex |= REX_B;
              i.sib.base = i.base_reg->reg_num;
@@ -5490,6 +5673,7 @@ build_modrm_byte (void)
              i.sib.scale = i.log2_scale_factor;
              if (i.index_reg == 0)
                {
+                 gas_assert (!i.tm.opcode_modifier.vecsib);
                  /* <disp>(%esp) becomes two byte modrm with no index
                     register.  We've already stored the code for esp
                     in i.rm.regmem ie. ESCAPE_TO_TWO_BYTE_ADDRESSING.
@@ -5497,7 +5681,7 @@ build_modrm_byte (void)
                     extra modrm byte.  */
                  i.sib.index = NO_INDEX_REGISTER;
                }
-             else
+             else if (!i.tm.opcode_modifier.vecsib)
                {
                  if (i.index_reg->reg_num == RegEiz
                      || i.index_reg->reg_num == RegRiz)
@@ -5621,30 +5805,51 @@ build_modrm_byte (void)
                }
              else
                {
-                 vex_reg = op + 1;
-                 gas_assert (vex_reg < i.operands);
+                 /* Check register-only source operand when two source
+                    operands are swapped.  */
+                 if (!i.tm.operand_types[op].bitfield.baseindex
+                     && i.tm.operand_types[op + 1].bitfield.baseindex)
+                   {
+                     vex_reg = op;
+                     op += 2;
+                     gas_assert (mem == (vex_reg + 1)
+                                 && op < i.operands);
+                   }
+                 else
+                   {
+                     vex_reg = op + 1;
+                     gas_assert (vex_reg < i.operands);
+                   }
                }
            }
          else if (i.tm.opcode_modifier.vexvvvv == VEXNDD)
            {
-             /* For instructions with VexNDD, there should be
-                no memory operand and the register destination
+             /* For instructions with VexNDD, the register destination
                 is encoded in VEX prefix.  */
-             gas_assert (i.mem_operands == 0
-                         && (op + 2) == i.operands);
-             vex_reg = op + 1;
+             if (i.mem_operands == 0)
+               {
+                 /* There is no memory operand.  */
+                 gas_assert ((op + 2) == i.operands);
+                 vex_reg = op + 1;
+               }
+             else
+               { 
+                 /* There are only 2 operands.  */
+                 gas_assert (op < 2 && i.operands == 2);
+                 vex_reg = 1;
+               }
            }
          else
            gas_assert (op < i.operands);
 
          if (vex_reg != (unsigned int) ~0)
            {
-             gas_assert (i.reg_operands == 2);
+             i386_operand_type *type = &i.tm.operand_types[vex_reg];
 
-             if (!operand_type_equal (&i.tm.operand_types[vex_reg],
-                                      &regxmm)
-                 && !operand_type_equal (&i.tm.operand_types[vex_reg],
-                                         &regymm))
+             if (type->bitfield.reg32 != 1
+                 && type->bitfield.reg64 != 1
+                 && !operand_type_equal (type, &regxmm)
+                 && !operand_type_equal (type, &regymm))
                abort ();
 
              i.vex.register_specifier = i.op[vex_reg].regs;
@@ -5687,15 +5892,15 @@ static void
 output_branch (void)
 {
   char *p;
+  int size;
   int code16;
   int prefix;
   relax_substateT subtype;
   symbolS *sym;
   offsetT off;
 
-  code16 = 0;
-  if (flag_code == CODE_16BIT)
-    code16 = CODE16;
+  code16 = flag_code == CODE_16BIT ? CODE16 : 0;
+  size = i.disp32_encoding ? BIG : SMALL;
 
   prefix = 0;
   if (i.prefix[DATA_PREFIX] != 0)
@@ -5738,11 +5943,11 @@ output_branch (void)
   *p = i.tm.base_opcode;
 
   if ((unsigned char) *p == JUMP_PC_RELATIVE)
-    subtype = ENCODE_RELAX_STATE (UNCOND_JUMP, SMALL);
+    subtype = ENCODE_RELAX_STATE (UNCOND_JUMP, size);
   else if (cpu_arch_flags.bitfield.cpui386)
-    subtype = ENCODE_RELAX_STATE (COND_JUMP, SMALL);
+    subtype = ENCODE_RELAX_STATE (COND_JUMP, size);
   else
-    subtype = ENCODE_RELAX_STATE (COND_JUMP86, SMALL);
+    subtype = ENCODE_RELAX_STATE (COND_JUMP86, size);
   subtype |= code16;
 
   sym = i.op[0].disps->X_add_symbol;
@@ -6324,7 +6529,8 @@ x86_cons_fix_new (fragS *frag, unsigned int off, unsigned int len,
   fix_new_exp (frag, off, len, exp, 0, r);
 }
 
-#if (!defined (OBJ_ELF) && !defined (OBJ_MAYBE_ELF)) || defined (LEX_AT)
+#if !(defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined (OBJ_MACH_O)) \
+    || defined (LEX_AT)
 # define lex_got(reloc, adjust, types) NULL
 #else
 /* Parse operands of the form
@@ -6407,8 +6613,10 @@ lex_got (enum bfd_reloc_code_real *rel,
   char *cp;
   unsigned int j;
 
+#if defined (OBJ_MAYBE_ELF)
   if (!IS_ELF)
     return NULL;
+#endif
 
   for (cp = input_line_pointer; *cp != '@'; cp++)
     if (is_end_of_line[(unsigned char) *cp] || *cp == ',')
@@ -6475,6 +6683,7 @@ lex_got (enum bfd_reloc_code_real *rel,
   /* Might be a symbol version string.  Don't as_bad here.  */
   return NULL;
 }
+#endif
 
 void
 x86_cons (expressionS *exp, int size)
@@ -6487,7 +6696,7 @@ x86_cons (expressionS *exp, int size)
       /* Handle @GOTOFF and the like in an expression.  */
       char *save;
       char *gotfree_input_line;
-      int adjust;
+      int adjust = 0;
 
       save = input_line_pointer;
       gotfree_input_line = lex_got (&got_reloc, &adjust, NULL);
@@ -6526,7 +6735,6 @@ x86_cons (expressionS *exp, int size)
   if (intel_syntax)
     i386_intel_simplify (exp);
 }
-#endif
 
 static void
 signed_cons (int size)
@@ -6539,8 +6747,7 @@ signed_cons (int size)
 
 #ifdef TE_PE
 static void
-pe_directive_secrel (dummy)
-     int dummy ATTRIBUTE_UNUSED;
+pe_directive_secrel (int dummy ATTRIBUTE_UNUSED)
 {
   expressionS exp;
 
@@ -6623,8 +6830,8 @@ i386_finalize_immediate (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp,
     {
       /* Size it properly later.  */
       i.types[this_operand].bitfield.imm64 = 1;
-      /* If BFD64, sign extend val.  */
-      if (!use_rela_relocations
+      /* If not 64bit, sign extend val.  */
+      if (flag_code != CODE_64BIT
          && (exp->X_add_number & ~(((addressT) 2 << 31) - 1)) == 0)
        exp->X_add_number
          = (exp->X_add_number ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31);
@@ -7038,6 +7245,8 @@ i386_index_check (const char *operand_string)
               || i.base_reg->reg_num !=
                  (i.prefix[ADDR_PREFIX] == 0 ? RegRip : RegEip)))
          || (i.index_reg
+             && !(i.index_reg->reg_type.bitfield.regxmm
+                  || i.index_reg->reg_type.bitfield.regymm)
              && (!i.index_reg->reg_type.bitfield.baseindex
                  || (i.prefix[ADDR_PREFIX] == 0
                      && i.index_reg->reg_num != RegRiz
@@ -7071,6 +7280,8 @@ i386_index_check (const char *operand_string)
          if ((i.base_reg
               && !i.base_reg->reg_type.bitfield.reg32)
              || (i.index_reg
+                 && !i.index_reg->reg_type.bitfield.regxmm
+                 && !i.index_reg->reg_type.bitfield.regymm
                  && ((!i.index_reg->reg_type.bitfield.reg32
                       && i.index_reg->reg_num != RegEiz)
                      || !i.index_reg->reg_type.bitfield.baseindex)))
@@ -7428,9 +7639,7 @@ i386_att_operand (char *operand_string)
    returned value.  */
 
 int
-md_estimate_size_before_relax (fragP, segment)
-     fragS *fragP;
-     segT segment;
+md_estimate_size_before_relax (fragS *fragP, segT segment)
 {
   /* We've already got fragP->fr_subtype right;  all we have to do is
      check for un-relaxable symbols.  On an ELF system, we can't relax
@@ -7553,10 +7762,8 @@ md_estimate_size_before_relax (fragP, segment)
        Caller will turn frag into a ".space 0".  */
 
 void
-md_convert_frag (abfd, sec, fragP)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     segT sec ATTRIBUTE_UNUSED;
-     fragS *fragP;
+md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED,
+                 fragS *fragP)
 {
   unsigned char *opcode;
   unsigned char *where_to_put_displacement = NULL;
@@ -7653,21 +7860,17 @@ md_convert_frag (abfd, sec, fragP)
   fragP->fr_fix += extension;
 }
 \f
-/* Apply a fixup (fixS) to segment data, once it has been determined
+/* Apply a fixup (fixP) to segment data, once it has been determined
    by our caller that we have all the info we need to fix it up.
 
+   Parameter valP is the pointer to the value of the bits.
+
    On the 386, immediates, displacements, and data pointers are all in
    the same (little-endian) format, so we don't need to care about which
    we are handling.  */
 
 void
-md_apply_fix (fixP, valP, seg)
-     /* The fix we're to put in.  */
-     fixS *fixP;
-     /* Pointer to the value of the bits.  */
-     valueT *valP;
-     /* Segment fix is from.  */
-     segT seg ATTRIBUTE_UNUSED;
+md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 {
   char *p = fixP->fx_where + fixP->fx_frag->fr_literal;
   valueT value = *valP;
@@ -8080,13 +8283,17 @@ const char *md_shortopts = "qn";
 #define OPTION_MSSE2AVX (OPTION_MD_BASE + 10)
 #define OPTION_MSSE_CHECK (OPTION_MD_BASE + 11)
 #define OPTION_MAVXSCALAR (OPTION_MD_BASE + 12)
+#define OPTION_X32 (OPTION_MD_BASE + 13)
 
 struct option md_longopts[] =
 {
   {"32", no_argument, NULL, OPTION_32},
 #if (defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) \
-     || defined (TE_PE) || defined (TE_PEP))
+     || defined (TE_PE) || defined (TE_PEP) || defined (OBJ_MACH_O))
   {"64", no_argument, NULL, OPTION_64},
+#endif
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+  {"x32", no_argument, NULL, OPTION_X32},
 #endif
   {"divide", no_argument, NULL, OPTION_DIVIDE},
   {"march", required_argument, NULL, OPTION_MARCH},
@@ -8140,7 +8347,7 @@ md_parse_option (int c, char *arg)
       break;
 #endif
 #if (defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) \
-     || defined (TE_PE) || defined (TE_PEP))
+     || defined (TE_PE) || defined (TE_PEP) || defined (OBJ_MACH_O))
     case OPTION_64:
       {
        const char **list, **l;
@@ -8150,18 +8357,41 @@ md_parse_option (int c, char *arg)
          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)
+             || strcmp (*l, "pei-x86-64") == 0
+             || strcmp (*l, "mach-o-x86-64") == 0)
            {
              default_arch = "x86_64";
              break;
            }
        if (*l == NULL)
-         as_fatal (_("No compiled in support for x86_64"));
+         as_fatal (_("no compiled in support for x86_64"));
        free (list);
       }
       break;
 #endif
 
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+    case OPTION_X32:
+      if (IS_ELF)
+       {
+         const char **list, **l;
+
+         list = bfd_target_list ();
+         for (l = list; *l != NULL; l++)
+           if (CONST_STRNEQ (*l, "elf32-x86-64"))
+             {
+               default_arch = "x86_64:32";
+               break;
+             }
+         if (*l == NULL)
+           as_fatal (_("no compiled in support for 32bit x86_64"));
+         free (list);
+       }
+      else
+       as_fatal (_("32bit x86_64 is only supported for ELF"));
+      break;
+#endif
+
     case OPTION_32:
       default_arch = "i386";
       break;
@@ -8188,7 +8418,7 @@ md_parse_option (int c, char *arg)
       do
        {
          if (*arch == '.')
-           as_fatal (_("Invalid -march= option: `%s'"), arg);
+           as_fatal (_("invalid -march= option: `%s'"), arg);
          next = strchr (arch, '+');
          if (next)
            *next++ = '\0';
@@ -8218,7 +8448,7 @@ md_parse_option (int c, char *arg)
                  /* ISA entension.  */
                  i386_cpu_flags flags;
 
-                 if (strncmp (arch, "no", 2))
+                 if (!cpu_arch[j].negated)
                    flags = cpu_flags_or (cpu_arch_flags,
                                          cpu_arch[j].flags);
                  else
@@ -8237,13 +8467,14 @@ md_parse_option (int c, char *arg)
                      else
                        cpu_sub_arch_name = xstrdup (cpu_arch[j].name);
                      cpu_arch_flags = flags;
+                     cpu_arch_isa_flags = flags;
                    }
                  break;
                }
            }
 
          if (j >= ARRAY_SIZE (cpu_arch))
-           as_fatal (_("Invalid -march= option: `%s'"), arg);
+           as_fatal (_("invalid -march= option: `%s'"), arg);
 
          arch = next;
        }
@@ -8252,7 +8483,7 @@ md_parse_option (int c, char *arg)
 
     case OPTION_MTUNE:
       if (*arg == '.')
-       as_fatal (_("Invalid -mtune= option: `%s'"), arg);
+       as_fatal (_("invalid -mtune= option: `%s'"), arg);
       for (j = 0; j < ARRAY_SIZE (cpu_arch); j++)
        {
          if (strcmp (arg, cpu_arch [j].name) == 0)
@@ -8264,7 +8495,7 @@ md_parse_option (int c, char *arg)
            }
        }
       if (j >= ARRAY_SIZE (cpu_arch))
-       as_fatal (_("Invalid -mtune= option: `%s'"), arg);
+       as_fatal (_("invalid -mtune= option: `%s'"), arg);
       break;
 
     case OPTION_MMNEMONIC:
@@ -8273,7 +8504,7 @@ md_parse_option (int c, char *arg)
       else if (strcasecmp (arg, "intel") == 0)
        intel_mnemonic = 1;
       else
-       as_fatal (_("Invalid -mmnemonic= option: `%s'"), arg);
+       as_fatal (_("invalid -mmnemonic= option: `%s'"), arg);
       break;
 
     case OPTION_MSYNTAX:
@@ -8282,7 +8513,7 @@ md_parse_option (int c, char *arg)
       else if (strcasecmp (arg, "intel") == 0)
        intel_syntax = 1;
       else
-       as_fatal (_("Invalid -msyntax= option: `%s'"), arg);
+       as_fatal (_("invalid -msyntax= option: `%s'"), arg);
       break;
 
     case OPTION_MINDEX_REG:
@@ -8309,7 +8540,7 @@ md_parse_option (int c, char *arg)
       else if (strcasecmp (arg, "none") == 0)
        sse_check = sse_check_none;
       else
-       as_fatal (_("Invalid -msse-check= option: `%s'"), arg);
+       as_fatal (_("invalid -msse-check= option: `%s'"), arg);
       break;
 
     case OPTION_MAVXSCALAR:
@@ -8318,7 +8549,7 @@ md_parse_option (int c, char *arg)
       else if (strcasecmp (arg, "256") == 0)
        avxscalar = vex256;
       else
-       as_fatal (_("Invalid -mavxscalar= option: `%s'"), arg);
+       as_fatal (_("invalid -mavxscalar= option: `%s'"), arg);
       break;
 
     default:
@@ -8425,7 +8656,7 @@ md_show_usage (FILE *stream)
 #if (defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) \
      || defined (TE_PE) || defined (TE_PEP))
   fprintf (stream, _("\
-  --32/--64               generate 32bit/64bit code\n"));
+  --32/--64/--x32         generate 32bit/64bit/x32 code\n"));
 #endif
 #ifdef SVR4_COMMENT_CHARS
   fprintf (stream, _("\
@@ -8473,12 +8704,18 @@ md_show_usage (FILE *stream)
 const char *
 i386_target_format (void)
 {
-  if (!strcmp (default_arch, "x86_64"))
-    update_code_flag (CODE_64BIT, 1);
+  if (!strncmp (default_arch, "x86_64", 6))
+    {
+      update_code_flag (CODE_64BIT, 1);
+      if (default_arch[6] == '\0')
+       x86_elf_abi = X86_64_ABI;
+      else
+       x86_elf_abi = X86_64_X32_ABI;
+    }
   else if (!strcmp (default_arch, "i386"))
     update_code_flag (CODE_32BIT, 1);
   else
-    as_fatal (_("Unknown architecture"));
+    as_fatal (_("unknown architecture"));
 
   if (cpu_flags_all_zero (&cpu_arch_isa_flags))
     cpu_arch_isa_flags = cpu_arch[flag_code == CODE_64BIT].flags;
@@ -8506,25 +8743,51 @@ i386_target_format (void)
 #if defined (OBJ_MAYBE_ELF) || defined (OBJ_ELF)
     case bfd_target_elf_flavour:
       {
-       if (flag_code == CODE_64BIT)
+       const char *format;
+
+       switch (x86_elf_abi)
          {
+         default:
+           format = ELF_TARGET_FORMAT;
+           break;
+         case X86_64_ABI:
+           use_rela_relocations = 1;
            object_64bit = 1;
+           format = ELF_TARGET_FORMAT64;
+           break;
+         case X86_64_X32_ABI:
            use_rela_relocations = 1;
+           object_64bit = 1;
+           disallow_64bit_reloc = 1;
+           format = ELF_TARGET_FORMAT32;
+           break;
          }
        if (cpu_arch_isa == PROCESSOR_L1OM)
          {
-           if (flag_code != CODE_64BIT)
+           if (x86_elf_abi != X86_64_ABI)
              as_fatal (_("Intel L1OM is 64bit only"));
            return ELF_TARGET_L1OM_FORMAT;
          }
+       if (cpu_arch_isa == PROCESSOR_K1OM)
+         {
+           if (x86_elf_abi != X86_64_ABI)
+             as_fatal (_("Intel K1OM is 64bit only"));
+           return ELF_TARGET_K1OM_FORMAT;
+         }
        else
-         return (flag_code == CODE_64BIT
-                 ? ELF_TARGET_FORMAT64 : ELF_TARGET_FORMAT);
+         return format;
       }
 #endif
 #if defined (OBJ_MACH_O)
     case bfd_target_mach_o_flavour:
-      return flag_code == CODE_64BIT ? "mach-o-x86-64" : "mach-o-i386";
+      if (flag_code == CODE_64BIT)
+       {
+         use_rela_relocations = 1;
+         object_64bit = 1;
+         return "mach-o-x86-64";
+       }
+      else
+       return "mach-o-i386";
 #endif
     default:
       abort ();
@@ -8577,8 +8840,7 @@ i386_elf_emit_arch_note (void)
 #endif
 \f
 symbolS *
-md_undefined_symbol (name)
-     char *name;
+md_undefined_symbol (char *name)
 {
   if (name[0] == GLOBAL_OFFSET_TABLE_NAME[0]
       && name[1] == GLOBAL_OFFSET_TABLE_NAME[1]
@@ -8600,9 +8862,7 @@ md_undefined_symbol (name)
 /* Round up a section size to the appropriate boundary.  */
 
 valueT
-md_section_align (segment, size)
-     segT segment ATTRIBUTE_UNUSED;
-     valueT size;
+md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
 {
 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
   if (OUTPUT_FLAVOR == bfd_target_aout_flavour)
@@ -8673,9 +8933,7 @@ i386_validate_fix (fixS *fixp)
 }
 
 arelent *
-tc_gen_reloc (section, fixp)
-     asection *section ATTRIBUTE_UNUSED;
-     fixS *fixp;
+tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
 {
   arelent *rel;
   bfd_reloc_code_real_type code;
@@ -8810,6 +9068,26 @@ tc_gen_reloc (section, fixp)
   /* Use the rela in 64bit mode.  */
   else
     {
+      if (disallow_64bit_reloc)
+       switch (code)
+         {
+         case BFD_RELOC_X86_64_DTPOFF64:
+         case BFD_RELOC_X86_64_TPOFF64:
+         case BFD_RELOC_64_PCREL:
+         case BFD_RELOC_X86_64_GOTOFF64:
+         case BFD_RELOC_X86_64_GOT64:
+         case BFD_RELOC_X86_64_GOTPCREL64:
+         case BFD_RELOC_X86_64_GOTPC64:
+         case BFD_RELOC_X86_64_GOTPLT64:
+         case BFD_RELOC_X86_64_PLTOFF64:
+           as_bad_where (fixp->fx_file, fixp->fx_line,
+                         _("cannot represent relocation type %s in x32 mode"),
+                         bfd_get_reloc_code_name (code));
+           break;
+         default:
+           break;
+         }
+
       if (!fixp->fx_pcrel)
        rel->addend = fixp->fx_offset;
       else
@@ -8901,6 +9179,16 @@ tc_x86_frame_initial_instructions (void)
   cfi_add_CFA_offset (x86_dwarf2_return_column, x86_cie_data_alignment);
 }
 
+int
+x86_dwarf2_addr_size (void)
+{
+#if defined (OBJ_MAYBE_ELF) || defined (OBJ_ELF)
+  if (x86_elf_abi == X86_64_X32_ABI)
+    return 4;
+#endif
+  return bfd_arch_bits_per_address (stdoutput) / 8;
+}
+
 int
 i386_elf_section_type (const char *str, size_t len)
 {
@@ -8945,10 +9233,10 @@ x86_64_section_letter (int letter, char **ptr_msg)
       if (letter == 'l')
        return SHF_X86_64_LARGE;
 
-      *ptr_msg = _("Bad .section directive: want a,l,w,x,M,S,G,T in string");
+      *ptr_msg = _("bad .section directive: want a,l,w,x,M,S,G,T in string");
     }
   else
-    *ptr_msg = _("Bad .section directive: want a,w,x,M,S,G,T in string");
+    *ptr_msg = _("bad .section directive: want a,w,x,M,S,G,T in string");
   return -1;
 }
 
This page took 0.043865 seconds and 4 git commands to generate.