Index: binutils-2.22/gas/config/tc-ppc.c =================================================================== --- binutils-2.22.orig/gas/config/tc-ppc.c +++ binutils-2.22/gas/config/tc-ppc.c @@ -41,6 +41,10 @@ #include "libxcoff.h" #endif +#if defined(__linux__) && defined(__powerpc64__) +#include <sys/utsname.h> +#endif + /* This is the assembler for the PowerPC or POWER (RS/6000) chips. */ /* Tell the main code what the endianness is. */ @@ -119,6 +123,8 @@ static bfd_boolean reg_names_p = TARGET_ static void ppc_macro (char *, const struct powerpc_macro *); static void ppc_byte (int); +static void ppc_set_obj64 PARAMS ((int)); + #if defined (OBJ_XCOFF) || defined (OBJ_ELF) static void ppc_tc (int); static void ppc_machine (int); @@ -949,7 +955,7 @@ ppc_parse_name (const char *name, expres /* Local variables. */ /* Whether to target xcoff64/elf64. */ -static unsigned int ppc_obj64 = BFD_DEFAULT_TARGET_SIZE == 64; +static int g_ppc_obj64 = -1; /* Opcode hash table. */ static struct hash_control *ppc_hash; @@ -1175,7 +1181,7 @@ md_parse_option (int c, char *arg) if (strcmp (arg, "64") == 0) { #ifdef BFD64 - ppc_obj64 = 1; + ppc_set_obj64 (1); if (ppc_cpu & PPC_OPCODE_VLE) as_bad (_("the use of -mvle requires -a32.")); #else @@ -1366,6 +1372,37 @@ PowerPC options:\n\ -nops=count when aligning, more than COUNT nops uses a branch\n")); } +/* Set ppc_obj64 if it is not already set. */ + +#define ppc_obj64 (ppc_get_obj64 ()) + +static unsigned int +ppc_get_obj64 (void) +{ + if (g_ppc_obj64 < 0) + { + g_ppc_obj64 = BFD_DEFAULT_TARGET_SIZE == 64; + +#if defined(__linux__) && defined(__powerpc64__) + /* Determine if we are running under a 32-bit personality. Don't + use plain personality(0xffffffff) syscall because the kernel lies. */ + { + struct utsname buf; + if (uname(&buf) == 0 && strcmp(buf.machine, "ppc") == 0) + g_ppc_obj64 = 0; + } +#endif + } + + return g_ppc_obj64; +} + +static void +ppc_set_obj64 (int obj64) +{ + g_ppc_obj64 = obj64; +} + /* Set ppc_cpu if it is not already set. */ static void Index: binutils-2.22/gas/config/tc-i386.c =================================================================== --- binutils-2.22.orig/gas/config/tc-i386.c +++ binutils-2.22/gas/config/tc-i386.c @@ -56,6 +56,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. @@ -186,7 +193,18 @@ static void s_bss (int); static void handle_large_common (int small ATTRIBUTE_UNUSED); #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 PARAMS ((void)); +static INLINE void set_default_arch PARAMS ((enum x86_arch arch)); +static INLINE const char *get_default_arch_str PARAMS ((void)); /* VEX prefix. */ typedef struct @@ -2019,7 +2037,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) { @@ -2028,7 +2046,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'; } @@ -2142,7 +2160,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 L1OM, we must enable it. */ @@ -2277,34 +2295,84 @@ 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 () +{ + const char *default_arch_str = DEFAULT_ARCH; + + 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"; + } +} + +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') - 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') - as_fatal (_("Intel K1OM is 64bit ELF only")); - return bfd_mach_k1om; - } - else if (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; - else + case ARCH_x64_32: + if (cpu_arch_isa == PROCESSOR_L1OM) + as_fatal (_("Intel L1OM is 64bit ELF only")); + if (cpu_arch_isa == PROCESSOR_K1OM) + as_fatal (_("Intel K1OM is 64bit ELF only")); return bfd_mach_x64_32; + case ARCH_i386: + return bfd_mach_i386_i386; + default: + as_fatal (_("unknown architecture")); } - else if (!strcmp (default_arch, "i386")) - return bfd_mach_i386_i386; - else - as_fatal (_("unknown architecture")); } void @@ -2433,7 +2501,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 @@ -3522,7 +3590,7 @@ check_suffix: { 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; } @@ -8475,7 +8543,7 @@ md_parse_option (int c, 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) @@ -8495,7 +8563,7 @@ md_parse_option (int c, 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) @@ -8508,7 +8576,7 @@ md_parse_option (int c, char *arg) #endif case OPTION_32: - default_arch = "i386"; + set_default_arch (ARCH_i386); break; case OPTION_DIVIDE: @@ -8819,18 +8887,23 @@ 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') + case ARCH_x86_64: + update_code_flag (CODE_64BIT, 1); x86_elf_abi = X86_64_ABI; - else + 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 if (!strcmp (default_arch, "i386")) - update_code_flag (CODE_32BIT, 1); - 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;