gas/config/tc-i386.c | 186 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 117 insertions(+), 69 deletions(-) diff -Nurp binutils-2.32.orig/gas/config/tc-i386.c binutils-2.32/gas/config/tc-i386.c --- binutils-2.32.orig/gas/config/tc-i386.c 2019-01-19 18:01:33.000000000 +0200 +++ binutils-2.32/gas/config/tc-i386.c 2019-02-05 23:35:55.210609565 +0200 @@ -53,6 +53,13 @@ #endif #endif +#if defined(__linux__) && defined(__x86_64__) +#include <sys/syscall.h> +#include <sys/personality.h> + +#define is_linux32() ((syscall(SYS_personality, 0xffffffff) & PER_MASK) == PER_LINUX32) +#endif + /* Prefixes will be emitted in the order defined below. WAIT_PREFIX must be the first prefix since FWAIT is really is an instruction, and so must come before any prefixes. @@ -197,7 +204,18 @@ static unsigned int x86_feature_2_used; static unsigned int x86_used_note = DEFAULT_X86_USED_NOTE; #endif -static const char *default_arch = DEFAULT_ARCH; +enum x86_arch + { + ARCH_default, + ARCH_i386, + ARCH_x86_64, + ARCH_x64_32, + }; + +static enum x86_arch g_default_arch = ARCH_default; +static enum x86_arch get_default_arch (void); +static INLINE void set_default_arch (enum x86_arch arch); +static INLINE const char *get_default_arch_str (void); /* This struct describes rounding control and SAE in the instruction. */ struct RC_Operation @@ -2462,7 +2480,7 @@ update_code_flag (int value, int check) else as_error = as_bad; (*as_error) (_("64bit mode not supported on `%s'."), - cpu_arch_name ? cpu_arch_name : default_arch); + cpu_arch_name ? cpu_arch_name : get_default_arch_str()); } if (value == CODE_32BIT && !cpu_arch_flags.bitfield.cpui386) { @@ -2471,7 +2489,7 @@ update_code_flag (int value, int check) else as_error = as_bad; (*as_error) (_("32bit mode not supported on `%s'."), - cpu_arch_name ? cpu_arch_name : default_arch); + cpu_arch_name ? cpu_arch_name : get_default_arch_str()); } stackop_size = '\0'; } @@ -2599,7 +2617,7 @@ check_cpu_arch_compatible (const char *n use default_arch. */ arch = cpu_arch_name; if (!arch) - arch = default_arch; + arch = get_default_arch_str(); } /* If we are targeting Intel MCU, we must enable it. */ @@ -2781,44 +2799,87 @@ i386_arch (void) return bfd_arch_i386; } +static enum x86_arch +get_default_arch () +{ + const char *default_arch_str = DEFAULT_ARCH; + + if (g_default_arch != ARCH_default) + return g_default_arch; + +#ifdef is_linux32 + if (is_linux32 ()) + default_arch_str = "i386"; +#endif + + if (!strcmp (default_arch_str, "x86_64")) + g_default_arch = ARCH_x86_64; + else if (!strcmp (default_arch_str, "x86_64:32")) + g_default_arch = ARCH_x64_32; + else if (!strcmp (default_arch_str, "i386")) + g_default_arch = ARCH_i386; + + return g_default_arch; +} + +static INLINE const char +*get_default_arch_str () +{ + switch (g_default_arch) + { + case ARCH_default: + return DEFAULT_ARCH; + case ARCH_x86_64: + return "x86_64"; + case ARCH_x64_32: + return "x86_64:32"; + case ARCH_i386: + return "i386"; + default: + return "noarch"; + } +} + +static INLINE void +set_default_arch (arch) + enum x86_arch arch; +{ + g_default_arch = arch; +} + unsigned long i386_mach (void) { - if (!strncmp (default_arch, "x86_64", 6)) + switch (get_default_arch ()) { - if (cpu_arch_isa == PROCESSOR_L1OM) - { - if (OUTPUT_FLAVOR != bfd_target_elf_flavour - || default_arch[6] != '\0') + case ARCH_x86_64: + if (cpu_arch_isa == PROCESSOR_L1OM) + { + if (OUTPUT_FLAVOR != bfd_target_elf_flavour) + as_fatal (_("Intel L1OM is 64bit ELF only")); + return bfd_mach_l1om; + } + else if (cpu_arch_isa == PROCESSOR_K1OM) + { + if (OUTPUT_FLAVOR != bfd_target_elf_flavour) + as_fatal (_("Intel K1OM is 64bit ELF only")); + return bfd_mach_k1om; + } + return bfd_mach_x86_64; + + case ARCH_x64_32: + if (cpu_arch_isa == PROCESSOR_L1OM) as_fatal (_("Intel L1OM is 64bit ELF only")); - return bfd_mach_l1om; - } - else if (cpu_arch_isa == PROCESSOR_K1OM) - { - if (OUTPUT_FLAVOR != bfd_target_elf_flavour - || default_arch[6] != '\0') + if (cpu_arch_isa == PROCESSOR_K1OM) 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") - || !strcmp (default_arch, "iamcu")) - { - if (cpu_arch_isa == PROCESSOR_IAMCU) - { - if (OUTPUT_FLAVOR != bfd_target_elf_flavour) - as_fatal (_("Intel MCU is 32bit ELF only")); - return bfd_mach_i386_iamcu; - } - else + + case ARCH_i386: return bfd_mach_i386_i386; + + default: + as_fatal (_("unknown architecture")); } - else - as_fatal (_("unknown architecture")); } void @@ -2946,7 +3007,7 @@ md_begin (void) { #if defined (OBJ_COFF) && defined (TE_PE) x86_dwarf2_return_column = (OUTPUT_FLAVOR == bfd_target_coff_flavour - ? 32 : 16); + x86_64:3232 : 16); #else x86_dwarf2_return_column = 16; #endif @@ -4663,7 +4724,7 @@ check_suffix: else as_bad (_("`%s' is not supported on `%s%s'"), current_templates->start->name, - cpu_arch_name ? cpu_arch_name : default_arch, + cpu_arch_name ? cpu_arch_name : get_default_arch_str(), cpu_sub_arch_name ? cpu_sub_arch_name : ""); return NULL; @@ -11004,7 +11065,7 @@ md_parse_option (int c, const char *arg) || strcmp (*l, "pei-x86-64") == 0 || strcmp (*l, "mach-o-x86-64") == 0) { - default_arch = "x86_64"; + set_default_arch (ARCH_x86_64); break; } if (*l == NULL) @@ -11024,7 +11085,7 @@ md_parse_option (int c, const char *arg) for (l = list; *l != NULL; l++) if (CONST_STRNEQ (*l, "elf32-x86-64")) { - default_arch = "x86_64:32"; + set_default_arch (ARCH_x64_32); break; } if (*l == NULL) @@ -11037,7 +11098,7 @@ md_parse_option (int c, const char *arg) #endif case OPTION_32: - default_arch = "i386"; + set_default_arch (ARCH_i386); break; case OPTION_DIVIDE: @@ -11585,39 +11646,26 @@ md_show_usage (FILE *stream) const char * i386_target_format (void) { - if (!strncmp (default_arch, "x86_64", 6)) + switch (get_default_arch ()) { - 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 if (!strcmp (default_arch, "iamcu")) - { - update_code_flag (CODE_32BIT, 1); - if (cpu_arch_isa == PROCESSOR_UNKNOWN) - { - static const i386_cpu_flags iamcu_flags = CPU_IAMCU_FLAGS; - cpu_arch_name = "iamcu"; - cpu_sub_arch_name = NULL; - cpu_arch_flags = iamcu_flags; - cpu_arch_isa = PROCESSOR_IAMCU; - cpu_arch_isa_flags = iamcu_flags; - if (!cpu_arch_tune_set) - { - cpu_arch_tune = cpu_arch_isa; - cpu_arch_tune_flags = cpu_arch_isa_flags; - } - } - else if (cpu_arch_isa != PROCESSOR_IAMCU) - as_fatal (_("Intel MCU doesn't support `%s' architecture"), - cpu_arch_name); + case ARCH_x86_64: + update_code_flag (CODE_64BIT, 1); + x86_elf_abi = X86_64_ABI; + break; + + case ARCH_x64_32: + update_code_flag (CODE_64BIT, 1); + x86_elf_abi = X86_64_X32_ABI; + break; + + case ARCH_i386: + update_code_flag (CODE_32BIT, 1); + break; + + default: + as_fatal (_("Unknown architecture")); + break; } - else - as_fatal (_("unknown architecture")); if (cpu_flags_all_zero (&cpu_arch_isa_flags)) cpu_arch_isa_flags = cpu_arch[flag_code == CODE_64BIT].flags;