From 5d21d768b2c9f3601cbb00aa36a5ec22bacf93df Mon Sep 17 00:00:00 2001 From: nwhitehorn Date: Sat, 10 Jul 2010 02:29:22 +0000 Subject: Teach our toolchain how to generate 64-bit PowerPC binaries. This fixes a variety of bugs in binutils related to handling of 64-bit PPC ELF, provides a GCC configuration for 64-bit PowerPC on FreeBSD, and associated build systems tweaks. Obtained from: projects/ppc64 --- contrib/gcc/config/rs6000/freebsd.h | 182 ++++++++++++++++++++++++++++++++++-- 1 file changed, 175 insertions(+), 7 deletions(-) (limited to 'contrib/gcc') diff --git a/contrib/gcc/config/rs6000/freebsd.h b/contrib/gcc/config/rs6000/freebsd.h index 1fb4b25..2ce115d 100644 --- a/contrib/gcc/config/rs6000/freebsd.h +++ b/contrib/gcc/config/rs6000/freebsd.h @@ -21,13 +21,86 @@ /* Override the defaults, which exist to force the proper definition. */ -#undef CPP_OS_DEFAULT_SPEC -#define CPP_OS_DEFAULT_SPEC "%(cpp_os_freebsd)" +#ifdef IN_LIBGCC2 +#undef TARGET_64BIT +#ifdef __powerpc64__ +#define TARGET_64BIT 1 +#else +#define TARGET_64BIT 0 +#endif +#endif + +/* On 64-bit systems, use the AIX ABI like Linux and NetBSD */ + +#undef DEFAULT_ABI +#define DEFAULT_ABI (TARGET_64BIT ? ABI_AIX : ABI_V4) +#undef TARGET_AIX +#define TARGET_AIX TARGET_64BIT + +#undef FBSD_TARGET_CPU_CPP_BUILTINS +#define FBSD_TARGET_CPU_CPP_BUILTINS() \ + do \ + { \ + builtin_define ("__PPC__"); \ + builtin_define ("__ppc__"); \ + builtin_define ("__PowerPC__"); \ + builtin_define ("__powerpc__"); \ + if (TARGET_64BIT) \ + { \ + builtin_define ("__LP64__"); \ + builtin_define ("__ppc64__"); \ + builtin_define ("__powerpc64__"); \ + builtin_define ("__arch64__"); \ + builtin_assert ("cpu=powerpc64"); \ + builtin_assert ("machine=powerpc64"); \ + } else { \ + builtin_assert ("cpu=powerpc"); \ + builtin_assert ("machine=powerpc"); \ + } \ + } \ + while (0) + +#define INVALID_64BIT "-m%s not supported in this configuration" +#define INVALID_32BIT INVALID_64BIT + +#undef SUBSUBTARGET_OVERRIDE_OPTIONS +#define SUBSUBTARGET_OVERRIDE_OPTIONS \ + do \ + { \ + if (!rs6000_explicit_options.alignment) \ + rs6000_alignment_flags = MASK_ALIGN_NATURAL; \ + if (TARGET_64BIT) \ + { \ + if (DEFAULT_ABI != ABI_AIX) \ + { \ + rs6000_current_abi = ABI_AIX; \ + error (INVALID_64BIT, "call"); \ + } \ + dot_symbols = !strcmp (rs6000_abi_name, "aixdesc"); \ + if (target_flags & MASK_RELOCATABLE) \ + { \ + target_flags &= ~MASK_RELOCATABLE; \ + error (INVALID_64BIT, "relocatable"); \ + } \ + if (target_flags & MASK_EABI) \ + { \ + target_flags &= ~MASK_EABI; \ + error (INVALID_64BIT, "eabi"); \ + } \ + if (target_flags & MASK_PROTOTYPE) \ + { \ + target_flags &= ~MASK_PROTOTYPE; \ + error (INVALID_64BIT, "prototype"); \ + } \ + if ((target_flags & MASK_POWERPC64) == 0) \ + { \ + target_flags |= MASK_POWERPC64; \ + error ("64 bit CPU required"); \ + } \ + } \ + } \ + while (0) -#undef CPP_OS_FREEBSD_SPEC -#define CPP_OS_FREEBSD_SPEC "\ - -D__PPC__ -D__ppc__ -D__PowerPC__ -D__powerpc__ \ - -Acpu=powerpc -Amachine=powerpc " #undef STARTFILE_DEFAULT_SPEC #define STARTFILE_DEFAULT_SPEC "%(startfile_freebsd)" @@ -57,7 +130,10 @@ c-common.c, and config//.h. */ #undef SIZE_TYPE -#define SIZE_TYPE "unsigned int" +#define SIZE_TYPE (TARGET_64BIT ? "long unsigned int" : "unsigned int") + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE (TARGET_64BIT ? "long int" : "int") /* rs6000.h gets this wrong for FreeBSD. We use the GCC defaults instead. */ #undef WCHAR_TYPE @@ -75,3 +151,95 @@ /* Override rs6000.h definition. */ #undef ASM_APP_OFF #define ASM_APP_OFF "#NO_APP\n" + +/* Tell the assembler we want 32/64-bit binaries if -m32 or -m64 is passed */ +#if (TARGET_DEFAULT & MASK_64BIT) +#define SVR4_ASM_SPEC "%(asm_cpu) \ +%{.s: %{mregnames} %{mno-regnames}} %{.S: %{mregnames} %{mno-regnames}} \ +%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \ +%{mrelocatable} %{mrelocatable-lib} %{fpic|fpie|fPIC|fPIE:-K PIC} \ +%{memb|msdata|msdata=eabi: -memb} \ +%{mlittle|mlittle-endian:-mlittle; \ + mbig|mbig-endian :-mbig; \ + mcall-aixdesc | \ + mcall-freebsd | \ + mcall-netbsd | \ + mcall-openbsd | \ + mcall-linux | \ + mcall-gnu :-mbig; \ + mcall-i960-old :-mlittle}" +#define LINK_OS_FREEBSD_SPEC_DEF "\ + %{p:%nconsider using `-pg' instead of `-p' with gprof(1)} \ + %{v:-V} \ + %{assert*} %{R*} %{rpath*} %{defsym*} \ + %{shared:-Bshareable %{h*} %{soname*}} \ + %{!shared: \ + %{!static: \ + %{rdynamic: -export-dynamic} \ + %{!dynamic-linker:-dynamic-linker %(fbsd_dynamic_linker) }} \ + %{static:-Bstatic}} \ + %{symbolic:-Bsymbolic}" + + +#undef ASM_DEFAULT_SPEC +#undef ASM_SPEC +#undef LINK_OS_FREEBSD_SPEC +#define ASM_DEFAULT_SPEC "-mppc%{!m32:64}" +#define ASM_SPEC "%{m32:-a32}%{!m32:-a64} " SVR4_ASM_SPEC +#define LINK_OS_FREEBSD_SPEC "%{m32:-melf32ppc}%{!m32:-melf64ppc} " LINK_OS_FREEBSD_SPEC_DEF +#endif + +/* _init and _fini functions are built from bits spread across many + object files, each potentially with a different TOC pointer. For + that reason, place a nop after the call so that the linker can + restore the TOC pointer if a TOC adjusting call stub is needed. */ +#ifdef __powerpc64__ +#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \ + asm (SECTION_OP "\n" \ +" bl ." #FUNC "\n" \ +" nop\n" \ +" .previous"); +#endif + +/* __throw will restore its own return address to be the same as the + return address of the function that the throw is being made to. + This is unfortunate, because we want to check the original + return address to see if we need to restore the TOC. + So we have to squirrel it away with this. */ +#define SETUP_FRAME_ADDRESSES() \ + do { if (TARGET_64BIT) rs6000_aix_emit_builtin_unwind_init (); } while (0) + +/* Select a format to encode pointers in exception handling data. CODE + is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is + true if the symbol may be affected by dynamic relocations. */ +#undef ASM_PREFERRED_EH_DATA_FORMAT +#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \ + ((TARGET_64BIT || flag_pic || TARGET_RELOCATABLE) \ + ? (((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel \ + | (TARGET_64BIT ? DW_EH_PE_udata8 : DW_EH_PE_sdata4)) \ + : DW_EH_PE_absptr) + +#define MD_FROB_UPDATE_CONTEXT(CTX, FS) \ + if (TARGET_64BIT) { \ + if ((FS)->regs.reg[2].how == REG_UNSAVED) \ + { \ + unsigned int *insn \ + = (unsigned int *) \ + _Unwind_GetGR ((CTX), LINK_REGISTER_REGNUM); \ + if (*insn == 0xE8410028) \ + _Unwind_SetGRPtr ((CTX), 2, (CTX)->cfa + 40); \ + } \ + } + +/* FreeBSD doesn't support saving and restoring 64-bit regs with a 32-bit + kernel. This is supported when running on a 64-bit kernel with + COMPAT_FREEBSD32, but tell GCC it isn't so that our 32-bit binaries + are compatible. */ +#define OS_MISSING_POWERPC64 !TARGET_64BIT + +/* Function profiling bits */ +#undef RS6000_MCOUNT +#define RS6000_MCOUNT ((TARGET_64BIT) ? "._mcount" : "_mcount") +#define PROFILE_HOOK(LABEL) \ + do { if (TARGET_64BIT) output_profile_hook (LABEL); } while (0) + -- cgit v1.1