diff --git a/Makefile b/Makefile index ae2423f..cf63971 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ SOURCES = sources CONFIG_SUB_REV = 3d5db9ebe860 BINUTILS_VER = 2.25.1 -GCC_VER = 5.2.0 +GCC_VER = 5.3.0 MUSL_VER = 1.1.14 GMP_VER = 6.1.0 MPC_VER = 1.0.3 diff --git a/hashes/gcc-5.3.0.tar.bz2.sha1 b/hashes/gcc-5.3.0.tar.bz2.sha1 new file mode 100644 index 0000000..a066444 --- /dev/null +++ b/hashes/gcc-5.3.0.tar.bz2.sha1 @@ -0,0 +1 @@ +0612270b103941da08376df4d0ef4e5662a2e9eb gcc-5.3.0.tar.bz2 diff --git a/patches/gcc-5.3.0/0001-musl.diff b/patches/gcc-5.3.0/0001-musl.diff new file mode 100644 index 0000000..5675aab --- /dev/null +++ b/patches/gcc-5.3.0/0001-musl.diff @@ -0,0 +1,892 @@ +diff --git a/fixincludes/mkfixinc.sh b/fixincludes/mkfixinc.sh +index 6653fed..0d96c8c 100755 +--- a/fixincludes/mkfixinc.sh ++++ b/fixincludes/mkfixinc.sh +@@ -19,7 +19,8 @@ case $machine in + powerpc-*-eabi* | \ + powerpc-*-rtems* | \ + powerpcle-*-eabisim* | \ +- powerpcle-*-eabi* ) ++ powerpcle-*-eabi* | \ ++ *-musl* ) + # IF there is no include fixing, + # THEN create a no-op fixer and exit + (echo "#! /bin/sh" ; echo "exit 0" ) > ${target} +diff --git a/gcc/config.gcc b/gcc/config.gcc +index 3ede69b..d9eb8cf 100644 +--- a/gcc/config.gcc ++++ b/gcc/config.gcc +@@ -575,7 +575,7 @@ case ${target} in + esac + + # Common C libraries. +-tm_defines="$tm_defines LIBC_GLIBC=1 LIBC_UCLIBC=2 LIBC_BIONIC=3" ++tm_defines="$tm_defines LIBC_GLIBC=1 LIBC_UCLIBC=2 LIBC_BIONIC=3 LIBC_MUSL=4" + + # 32-bit x86 processors supported by --with-arch=. Each processor + # MUST be separated by exactly one space. +@@ -720,6 +720,9 @@ case ${target} in + *-*-*uclibc*) + tm_defines="$tm_defines DEFAULT_LIBC=LIBC_UCLIBC" + ;; ++ *-*-*musl*) ++ tm_defines="$tm_defines DEFAULT_LIBC=LIBC_MUSL" ++ ;; + *) + tm_defines="$tm_defines DEFAULT_LIBC=LIBC_GLIBC" + ;; +diff --git a/gcc/config/aarch64/aarch64-linux.h b/gcc/config/aarch64/aarch64-linux.h +index ba7fc3b..1600a32 100644 +--- a/gcc/config/aarch64/aarch64-linux.h ++++ b/gcc/config/aarch64/aarch64-linux.h +@@ -23,6 +23,9 @@ + + #define GLIBC_DYNAMIC_LINKER "/lib/ld-linux-aarch64%{mbig-endian:_be}%{mabi=ilp32:_ilp32}.so.1" + ++#undef MUSL_DYNAMIC_LINKER ++#define MUSL_DYNAMIC_LINKER "/lib/ld-musl-aarch64%{mbig-endian:_be}%{mabi=ilp32:_ilp32}.so.1" ++ + #undef ASAN_CC1_SPEC + #define ASAN_CC1_SPEC "%{%:sanitize(address):-funwind-tables}" + +diff --git a/gcc/config/alpha/linux.h b/gcc/config/alpha/linux.h +index c567f43..475ea06 100644 +--- a/gcc/config/alpha/linux.h ++++ b/gcc/config/alpha/linux.h +@@ -61,10 +61,14 @@ along with GCC; see the file COPYING3. If not see + #define OPTION_GLIBC (DEFAULT_LIBC == LIBC_GLIBC) + #define OPTION_UCLIBC (DEFAULT_LIBC == LIBC_UCLIBC) + #define OPTION_BIONIC (DEFAULT_LIBC == LIBC_BIONIC) ++#undef OPTION_MUSL ++#define OPTION_MUSL (DEFAULT_LIBC == LIBC_MUSL) + #else + #define OPTION_GLIBC (linux_libc == LIBC_GLIBC) + #define OPTION_UCLIBC (linux_libc == LIBC_UCLIBC) + #define OPTION_BIONIC (linux_libc == LIBC_BIONIC) ++#undef OPTION_MUSL ++#define OPTION_MUSL (linux_libc == LIBC_MUSL) + #endif + + /* Determine what functions are present at the runtime; +diff --git a/gcc/config/arm/linux-eabi.h b/gcc/config/arm/linux-eabi.h +index e9d65dc..f12e6bd 100644 +--- a/gcc/config/arm/linux-eabi.h ++++ b/gcc/config/arm/linux-eabi.h +@@ -77,6 +77,23 @@ + %{mfloat-abi=soft*:" GLIBC_DYNAMIC_LINKER_SOFT_FLOAT "} \ + %{!mfloat-abi=*:" GLIBC_DYNAMIC_LINKER_DEFAULT "}" + ++/* For ARM musl currently supports four dynamic linkers: ++ - ld-musl-arm.so.1 - for the EABI-derived soft-float ABI ++ - ld-musl-armhf.so.1 - for the EABI-derived hard-float ABI ++ - ld-musl-armeb.so.1 - for the EABI-derived soft-float ABI, EB ++ - ld-musl-armebhf.so.1 - for the EABI-derived hard-float ABI, EB ++ musl does not support the legacy OABI mode. ++ All the dynamic linkers live in /lib. ++ We default to soft-float, EL. */ ++#undef MUSL_DYNAMIC_LINKER ++#if TARGET_BIG_ENDIAN_DEFAULT ++#define MUSL_DYNAMIC_LINKER_E "%{mlittle-endian:;:eb}" ++#else ++#define MUSL_DYNAMIC_LINKER_E "%{mbig-endian:eb}" ++#endif ++#define MUSL_DYNAMIC_LINKER \ ++ "/lib/ld-musl-arm" MUSL_DYNAMIC_LINKER_E "%{mfloat-abi=hard:hf}.so.1" ++ + /* At this point, bpabi.h will have clobbered LINK_SPEC. We want to + use the GNU/Linux version, not the generic BPABI version. */ + #undef LINK_SPEC +diff --git a/gcc/config/glibc-stdint.h b/gcc/config/glibc-stdint.h +index 3fc67dc..98f4f04 100644 +--- a/gcc/config/glibc-stdint.h ++++ b/gcc/config/glibc-stdint.h +@@ -22,6 +22,12 @@ a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + ++/* Systems using musl libc should use this header and make sure ++ OPTION_MUSL is defined correctly before using the TYPE macros. */ ++#ifndef OPTION_MUSL ++#define OPTION_MUSL 0 ++#endif ++ + #define SIG_ATOMIC_TYPE "int" + + #define INT8_TYPE "signed char" +@@ -43,12 +49,12 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + #define UINT_LEAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int") + + #define INT_FAST8_TYPE "signed char" +-#define INT_FAST16_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "int") +-#define INT_FAST32_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "int") ++#define INT_FAST16_TYPE (LONG_TYPE_SIZE == 64 && !OPTION_MUSL ? "long int" : "int") ++#define INT_FAST32_TYPE (LONG_TYPE_SIZE == 64 && !OPTION_MUSL ? "long int" : "int") + #define INT_FAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int") + #define UINT_FAST8_TYPE "unsigned char" +-#define UINT_FAST16_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "unsigned int") +-#define UINT_FAST32_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "unsigned int") ++#define UINT_FAST16_TYPE (LONG_TYPE_SIZE == 64 && !OPTION_MUSL ? "long unsigned int" : "unsigned int") ++#define UINT_FAST32_TYPE (LONG_TYPE_SIZE == 64 && !OPTION_MUSL ? "long unsigned int" : "unsigned int") + #define UINT_FAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int") + + #define INTPTR_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "int") +diff --git a/gcc/config/i386/linux.h b/gcc/config/i386/linux.h +index a100963..385aefd 100644 +--- a/gcc/config/i386/linux.h ++++ b/gcc/config/i386/linux.h +@@ -21,3 +21,6 @@ along with GCC; see the file COPYING3. If not see + + #define GNU_USER_LINK_EMULATION "elf_i386" + #define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2" ++ ++#undef MUSL_DYNAMIC_LINKER ++#define MUSL_DYNAMIC_LINKER "/lib/ld-musl-i386.so.1" +diff --git a/gcc/config/i386/linux64.h b/gcc/config/i386/linux64.h +index a27d3be..e300480 100644 +--- a/gcc/config/i386/linux64.h ++++ b/gcc/config/i386/linux64.h +@@ -30,3 +30,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + #define GLIBC_DYNAMIC_LINKER32 "/lib/ld-linux.so.2" + #define GLIBC_DYNAMIC_LINKER64 "/lib64/ld-linux-x86-64.so.2" + #define GLIBC_DYNAMIC_LINKERX32 "/libx32/ld-linux-x32.so.2" ++ ++#undef MUSL_DYNAMIC_LINKER32 ++#define MUSL_DYNAMIC_LINKER32 "/lib/ld-musl-i386.so.1" ++#undef MUSL_DYNAMIC_LINKER64 ++#define MUSL_DYNAMIC_LINKER64 "/lib/ld-musl-x86_64.so.1" ++#undef MUSL_DYNAMIC_LINKERX32 ++#define MUSL_DYNAMIC_LINKERX32 "/lib/ld-musl-x32.so.1" +diff --git a/gcc/config/linux.h b/gcc/config/linux.h +index 857389a..7bc87ab 100644 +--- a/gcc/config/linux.h ++++ b/gcc/config/linux.h +@@ -32,10 +32,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + #define OPTION_GLIBC (DEFAULT_LIBC == LIBC_GLIBC) + #define OPTION_UCLIBC (DEFAULT_LIBC == LIBC_UCLIBC) + #define OPTION_BIONIC (DEFAULT_LIBC == LIBC_BIONIC) ++#undef OPTION_MUSL ++#define OPTION_MUSL (DEFAULT_LIBC == LIBC_MUSL) + #else + #define OPTION_GLIBC (linux_libc == LIBC_GLIBC) + #define OPTION_UCLIBC (linux_libc == LIBC_UCLIBC) + #define OPTION_BIONIC (linux_libc == LIBC_BIONIC) ++#undef OPTION_MUSL ++#define OPTION_MUSL (linux_libc == LIBC_MUSL) + #endif + + #define GNU_USER_TARGET_OS_CPP_BUILTINS() \ +@@ -50,21 +54,25 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + } while (0) + + /* Determine which dynamic linker to use depending on whether GLIBC or +- uClibc or Bionic is the default C library and whether +- -muclibc or -mglibc or -mbionic has been passed to change the default. */ ++ uClibc or Bionic or musl is the default C library and whether ++ -muclibc or -mglibc or -mbionic or -mmusl has been passed to change ++ the default. */ + +-#define CHOOSE_DYNAMIC_LINKER1(LIBC1, LIBC2, LIBC3, LD1, LD2, LD3) \ +- "%{" LIBC2 ":" LD2 ";:%{" LIBC3 ":" LD3 ";:" LD1 "}}" ++#define CHOOSE_DYNAMIC_LINKER1(LIBC1, LIBC2, LIBC3, LIBC4, LD1, LD2, LD3, LD4) \ ++ "%{" LIBC2 ":" LD2 ";:%{" LIBC3 ":" LD3 ";:%{" LIBC4 ":" LD4 ";:" LD1 "}}}" + + #if DEFAULT_LIBC == LIBC_GLIBC +-#define CHOOSE_DYNAMIC_LINKER(G, U, B) \ +- CHOOSE_DYNAMIC_LINKER1 ("mglibc", "muclibc", "mbionic", G, U, B) ++#define CHOOSE_DYNAMIC_LINKER(G, U, B, M) \ ++ CHOOSE_DYNAMIC_LINKER1 ("mglibc", "muclibc", "mbionic", "mmusl", G, U, B, M) + #elif DEFAULT_LIBC == LIBC_UCLIBC +-#define CHOOSE_DYNAMIC_LINKER(G, U, B) \ +- CHOOSE_DYNAMIC_LINKER1 ("muclibc", "mglibc", "mbionic", U, G, B) ++#define CHOOSE_DYNAMIC_LINKER(G, U, B, M) \ ++ CHOOSE_DYNAMIC_LINKER1 ("muclibc", "mglibc", "mbionic", "mmusl", U, G, B, M) + #elif DEFAULT_LIBC == LIBC_BIONIC +-#define CHOOSE_DYNAMIC_LINKER(G, U, B) \ +- CHOOSE_DYNAMIC_LINKER1 ("mbionic", "mglibc", "muclibc", B, G, U) ++#define CHOOSE_DYNAMIC_LINKER(G, U, B, M) \ ++ CHOOSE_DYNAMIC_LINKER1 ("mbionic", "mglibc", "muclibc", "mmusl", B, G, U, M) ++#elif DEFAULT_LIBC == LIBC_MUSL ++#define CHOOSE_DYNAMIC_LINKER(G, U, B, M) \ ++ CHOOSE_DYNAMIC_LINKER1 ("mmusl", "mglibc", "muclibc", "mbionic", M, G, U, B) + #else + #error "Unsupported DEFAULT_LIBC" + #endif /* DEFAULT_LIBC */ +@@ -81,24 +89,100 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + #define BIONIC_DYNAMIC_LINKER32 "/system/bin/linker" + #define BIONIC_DYNAMIC_LINKER64 "/system/bin/linker64" + #define BIONIC_DYNAMIC_LINKERX32 "/system/bin/linkerx32" ++/* Should be redefined for each target that supports musl. */ ++#define MUSL_DYNAMIC_LINKER "/dev/null" ++#define MUSL_DYNAMIC_LINKER32 "/dev/null" ++#define MUSL_DYNAMIC_LINKER64 "/dev/null" ++#define MUSL_DYNAMIC_LINKERX32 "/dev/null" + + #define GNU_USER_DYNAMIC_LINKER \ + CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER, UCLIBC_DYNAMIC_LINKER, \ +- BIONIC_DYNAMIC_LINKER) ++ BIONIC_DYNAMIC_LINKER, MUSL_DYNAMIC_LINKER) + #define GNU_USER_DYNAMIC_LINKER32 \ + CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER32, UCLIBC_DYNAMIC_LINKER32, \ +- BIONIC_DYNAMIC_LINKER32) ++ BIONIC_DYNAMIC_LINKER32, MUSL_DYNAMIC_LINKER32) + #define GNU_USER_DYNAMIC_LINKER64 \ + CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER64, UCLIBC_DYNAMIC_LINKER64, \ +- BIONIC_DYNAMIC_LINKER64) ++ BIONIC_DYNAMIC_LINKER64, MUSL_DYNAMIC_LINKER64) + #define GNU_USER_DYNAMIC_LINKERX32 \ + CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKERX32, UCLIBC_DYNAMIC_LINKERX32, \ +- BIONIC_DYNAMIC_LINKERX32) ++ BIONIC_DYNAMIC_LINKERX32, MUSL_DYNAMIC_LINKERX32) + + /* Whether we have Bionic libc runtime */ + #undef TARGET_HAS_BIONIC + #define TARGET_HAS_BIONIC (OPTION_BIONIC) + ++/* musl avoids problematic includes by rearranging the include directories. ++ * Unfortunately, this is mostly duplicated from cppdefault.c */ ++#if DEFAULT_LIBC == LIBC_MUSL ++#define INCLUDE_DEFAULTS_MUSL_GPP \ ++ { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, \ ++ GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 }, \ ++ { GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1, \ ++ GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 1 }, \ ++ { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1, \ ++ GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 }, ++ ++#ifdef LOCAL_INCLUDE_DIR ++#define INCLUDE_DEFAULTS_MUSL_LOCAL \ ++ { LOCAL_INCLUDE_DIR, 0, 0, 1, 1, 2 }, \ ++ { LOCAL_INCLUDE_DIR, 0, 0, 1, 1, 0 }, ++#else ++#define INCLUDE_DEFAULTS_MUSL_LOCAL ++#endif ++ ++#ifdef PREFIX_INCLUDE_DIR ++#define INCLUDE_DEFAULTS_MUSL_PREFIX \ ++ { PREFIX_INCLUDE_DIR, 0, 0, 1, 0, 0}, ++#else ++#define INCLUDE_DEFAULTS_MUSL_PREFIX ++#endif ++ ++#ifdef CROSS_INCLUDE_DIR ++#define INCLUDE_DEFAULTS_MUSL_CROSS \ ++ { CROSS_INCLUDE_DIR, "GCC", 0, 0, 0, 0}, ++#else ++#define INCLUDE_DEFAULTS_MUSL_CROSS ++#endif ++ ++#ifdef TOOL_INCLUDE_DIR ++#define INCLUDE_DEFAULTS_MUSL_TOOL \ ++ { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1, 0, 0}, ++#else ++#define INCLUDE_DEFAULTS_MUSL_TOOL ++#endif ++ ++#ifdef NATIVE_SYSTEM_HEADER_DIR ++#define INCLUDE_DEFAULTS_MUSL_NATIVE \ ++ { NATIVE_SYSTEM_HEADER_DIR, 0, 0, 0, 1, 2 }, \ ++ { NATIVE_SYSTEM_HEADER_DIR, 0, 0, 0, 1, 0 }, ++#else ++#define INCLUDE_DEFAULTS_MUSL_NATIVE ++#endif ++ ++#if defined (CROSS_DIRECTORY_STRUCTURE) && !defined (TARGET_SYSTEM_ROOT) ++# undef INCLUDE_DEFAULTS_MUSL_LOCAL ++# define INCLUDE_DEFAULTS_MUSL_LOCAL ++# undef INCLUDE_DEFAULTS_MUSL_NATIVE ++# define INCLUDE_DEFAULTS_MUSL_NATIVE ++#else ++# undef INCLUDE_DEFAULTS_MUSL_CROSS ++# define INCLUDE_DEFAULTS_MUSL_CROSS ++#endif ++ ++#undef INCLUDE_DEFAULTS ++#define INCLUDE_DEFAULTS \ ++ { \ ++ INCLUDE_DEFAULTS_MUSL_GPP \ ++ INCLUDE_DEFAULTS_MUSL_PREFIX \ ++ INCLUDE_DEFAULTS_MUSL_CROSS \ ++ INCLUDE_DEFAULTS_MUSL_TOOL \ ++ INCLUDE_DEFAULTS_MUSL_NATIVE \ ++ { GCC_INCLUDE_DIR, "GCC", 0, 1, 0, 0 }, \ ++ { 0, 0, 0, 0, 0, 0 } \ ++ } ++#endif ++ + #if (DEFAULT_LIBC == LIBC_UCLIBC) && defined (SINGLE_LIBC) /* uClinux */ + /* This is a *uclinux* target. We don't define below macros to normal linux + versions, because doing so would require *uclinux* targets to include +diff --git a/gcc/config/linux.opt b/gcc/config/linux.opt +index c054338..ef055a7 100644 +--- a/gcc/config/linux.opt ++++ b/gcc/config/linux.opt +@@ -28,5 +28,9 @@ Target Report RejectNegative Var(linux_libc,LIBC_GLIBC) Negative(muclibc) + Use GNU C library + + muclibc +-Target Report RejectNegative Var(linux_libc,LIBC_UCLIBC) Negative(mbionic) ++Target Report RejectNegative Var(linux_libc,LIBC_UCLIBC) Negative(mmusl) + Use uClibc C library ++ ++mmusl ++Target Report RejectNegative Var(linux_libc,LIBC_MUSL) Negative(mbionic) ++Use musl C library +diff --git a/gcc/config/microblaze/linux.h b/gcc/config/microblaze/linux.h +index 655a70f..a8a3f3e 100644 +--- a/gcc/config/microblaze/linux.h ++++ b/gcc/config/microblaze/linux.h +@@ -28,10 +28,20 @@ + #undef TLS_NEEDS_GOT + #define TLS_NEEDS_GOT 1 + +-#define DYNAMIC_LINKER "/lib/ld.so.1" ++#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1" ++ ++#if TARGET_BIG_ENDIAN_DEFAULT == 0 /* LE */ ++#define MUSL_DYNAMIC_LINKER_E "%{mbig-endian:;:el}" ++#else ++#define MUSL_DYNAMIC_LINKER_E "%{mlittle-endian:el}" ++#endif ++ ++#undef MUSL_DYNAMIC_LINKER ++#define MUSL_DYNAMIC_LINKER "/lib/ld-musl-microblaze" MUSL_DYNAMIC_LINKER_E ".so.1" ++ + #undef SUBTARGET_EXTRA_SPECS + #define SUBTARGET_EXTRA_SPECS \ +- { "dynamic_linker", DYNAMIC_LINKER } ++ { "dynamic_linker", GNU_USER_DYNAMIC_LINKER } + + #undef LINK_SPEC + #define LINK_SPEC "%{shared:-shared} \ +diff --git a/gcc/config/mips/linux.h b/gcc/config/mips/linux.h +index 91df261..fb358e2 100644 +--- a/gcc/config/mips/linux.h ++++ b/gcc/config/mips/linux.h +@@ -37,7 +37,13 @@ along with GCC; see the file COPYING3. If not see + #define UCLIBC_DYNAMIC_LINKERN32 \ + "%{mnan=2008:/lib32/ld-uClibc-mipsn8.so.0;:/lib32/ld-uClibc.so.0}" + ++#undef MUSL_DYNAMIC_LINKER32 ++#define MUSL_DYNAMIC_LINKER32 "/lib/ld-musl-mips%{EL:el}%{msoft-float:-sf}.so.1" ++#undef MUSL_DYNAMIC_LINKER64 ++#define MUSL_DYNAMIC_LINKER64 "/lib/ld-musl-mips64%{EL:el}%{msoft-float:-sf}.so.1" ++#define MUSL_DYNAMIC_LINKERN32 "/lib/ld-musl-mipsn32%{EL:el}%{msoft-float:-sf}.so.1" ++ + #define BIONIC_DYNAMIC_LINKERN32 "/system/bin/linker32" + #define GNU_USER_DYNAMIC_LINKERN32 \ + CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKERN32, UCLIBC_DYNAMIC_LINKERN32, \ +- BIONIC_DYNAMIC_LINKERN32) ++ BIONIC_DYNAMIC_LINKERN32, MUSL_DYNAMIC_LINKERN32) +diff --git a/gcc/config/rs6000/linux.h b/gcc/config/rs6000/linux.h +index fe0ebd6..a68ff69 100644 +--- a/gcc/config/rs6000/linux.h ++++ b/gcc/config/rs6000/linux.h +@@ -30,10 +30,14 @@ + #define OPTION_GLIBC (DEFAULT_LIBC == LIBC_GLIBC) + #define OPTION_UCLIBC (DEFAULT_LIBC == LIBC_UCLIBC) + #define OPTION_BIONIC (DEFAULT_LIBC == LIBC_BIONIC) ++#undef OPTION_MUSL ++#define OPTION_MUSL (DEFAULT_LIBC == LIBC_MUSL) + #else + #define OPTION_GLIBC (linux_libc == LIBC_GLIBC) + #define OPTION_UCLIBC (linux_libc == LIBC_UCLIBC) + #define OPTION_BIONIC (linux_libc == LIBC_BIONIC) ++#undef OPTION_MUSL ++#define OPTION_MUSL (linux_libc == LIBC_MUSL) + #endif + + /* Determine what functions are present at the runtime; +diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h +index 0879e7e..6a7d435 100644 +--- a/gcc/config/rs6000/linux64.h ++++ b/gcc/config/rs6000/linux64.h +@@ -299,10 +299,14 @@ extern int dot_symbols; + #define OPTION_GLIBC (DEFAULT_LIBC == LIBC_GLIBC) + #define OPTION_UCLIBC (DEFAULT_LIBC == LIBC_UCLIBC) + #define OPTION_BIONIC (DEFAULT_LIBC == LIBC_BIONIC) ++#undef OPTION_MUSL ++#define OPTION_MUSL (DEFAULT_LIBC == LIBC_MUSL) + #else + #define OPTION_GLIBC (linux_libc == LIBC_GLIBC) + #define OPTION_UCLIBC (linux_libc == LIBC_UCLIBC) + #define OPTION_BIONIC (linux_libc == LIBC_BIONIC) ++#undef OPTION_MUSL ++#define OPTION_MUSL (linux_libc == LIBC_MUSL) + #endif + + /* Determine what functions are present at the runtime; +@@ -365,17 +369,23 @@ extern int dot_symbols; + #endif + #define UCLIBC_DYNAMIC_LINKER32 "/lib/ld-uClibc.so.0" + #define UCLIBC_DYNAMIC_LINKER64 "/lib/ld64-uClibc.so.0" ++#define MUSL_DYNAMIC_LINKER32 \ ++ "/lib/ld-musl-powerpc" MUSL_DYNAMIC_LINKER_E "%{msoft-float:-sf}.so.1" ++#define MUSL_DYNAMIC_LINKER64 \ ++ "/lib/ld-musl-powerpc64" MUSL_DYNAMIC_LINKER_E "%{msoft-float:-sf}.so.1" + #if DEFAULT_LIBC == LIBC_UCLIBC +-#define CHOOSE_DYNAMIC_LINKER(G, U) "%{mglibc:" G ";:" U "}" ++#define CHOOSE_DYNAMIC_LINKER(G, U, M) "%{mglibc:" G ";:%{mmusl:" M ";:" U "}}" + #elif DEFAULT_LIBC == LIBC_GLIBC +-#define CHOOSE_DYNAMIC_LINKER(G, U) "%{muclibc:" U ";:" G "}" ++#define CHOOSE_DYNAMIC_LINKER(G, U, M) "%{muclibc:" U ";:%{mmusl:" M ";:" G "}}" ++#elif DEFAULT_LIBC == LIBC_MUSL ++#define CHOOSE_DYNAMIC_LINKER(G, U, M) "%{mglibc:" G ";:%{muclibc:" U ";:" M "}}" + #else + #error "Unsupported DEFAULT_LIBC" + #endif + #define GNU_USER_DYNAMIC_LINKER32 \ +- CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER32, UCLIBC_DYNAMIC_LINKER32) ++ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER32, UCLIBC_DYNAMIC_LINKER32, MUSL_DYNAMIC_LINKER32) + #define GNU_USER_DYNAMIC_LINKER64 \ +- CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER64, UCLIBC_DYNAMIC_LINKER64) ++ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER64, UCLIBC_DYNAMIC_LINKER64, MUSL_DYNAMIC_LINKER64) + + #undef DEFAULT_ASM_ENDIAN + #if (TARGET_DEFAULT & MASK_LITTLE_ENDIAN) +diff --git a/gcc/config/rs6000/secureplt.h b/gcc/config/rs6000/secureplt.h +index b463463..77edf2a 100644 +--- a/gcc/config/rs6000/secureplt.h ++++ b/gcc/config/rs6000/secureplt.h +@@ -18,3 +18,4 @@ along with GCC; see the file COPYING3. If not see + . */ + + #define CC1_SECURE_PLT_DEFAULT_SPEC "-msecure-plt" ++#define LINK_SECURE_PLT_DEFAULT_SPEC "--secure-plt" +diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h +index 9917c2f..68365de 100644 +--- a/gcc/config/rs6000/sysv4.h ++++ b/gcc/config/rs6000/sysv4.h +@@ -537,6 +537,9 @@ ENDIAN_SELECT(" -mbig", " -mlittle", DEFAULT_ASM_ENDIAN) + #ifndef CC1_SECURE_PLT_DEFAULT_SPEC + #define CC1_SECURE_PLT_DEFAULT_SPEC "" + #endif ++#ifndef LINK_SECURE_PLT_DEFAULT_SPEC ++#define LINK_SECURE_PLT_DEFAULT_SPEC "" ++#endif + + /* Pass -G xxx to the compiler. */ + #undef CC1_SPEC +@@ -574,7 +577,8 @@ + %{R*} \ + %(link_shlib) \ + %{!T*: %(link_start) } \ +-%(link_os)" ++%(link_os) \ ++%{!mbss-plt: %{!msecure-plt: %(link_secure_plt_default)}}" + + /* Shared libraries are not default. */ + #define LINK_SHLIB_SPEC "\ +@@ -762,17 +766,23 @@ ENDIAN_SELECT(" -mbig", " -mlittle", DEFAULT_ASM_ENDIAN) + + #define LINK_START_LINUX_SPEC "" + ++#define MUSL_DYNAMIC_LINKER_E ENDIAN_SELECT("","le","") ++ + #define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1" + #define UCLIBC_DYNAMIC_LINKER "/lib/ld-uClibc.so.0" ++#define MUSL_DYNAMIC_LINKER \ ++ "/lib/ld-musl-powerpc" MUSL_DYNAMIC_LINKER_E "%{msoft-float:-sf}.so.1" + #if DEFAULT_LIBC == LIBC_UCLIBC +-#define CHOOSE_DYNAMIC_LINKER(G, U) "%{mglibc:" G ";:" U "}" ++#define CHOOSE_DYNAMIC_LINKER(G, U, M) "%{mglibc:" G ";:%{mmusl:" M ";:" U "}}" ++#elif DEFAULT_LIBC == LIBC_MUSL ++#define CHOOSE_DYNAMIC_LINKER(G, U, M) "%{mglibc:" G ";:%{muclibc:" U ";:" M "}}" + #elif !defined (DEFAULT_LIBC) || DEFAULT_LIBC == LIBC_GLIBC +-#define CHOOSE_DYNAMIC_LINKER(G, U) "%{muclibc:" U ";:" G "}" ++#define CHOOSE_DYNAMIC_LINKER(G, U, M) "%{muclibc:" U ";:%{mmusl:" M ";:" G "}}" + #else + #error "Unsupported DEFAULT_LIBC" + #endif + #define GNU_USER_DYNAMIC_LINKER \ +- CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER, UCLIBC_DYNAMIC_LINKER) ++ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER, UCLIBC_DYNAMIC_LINKER, MUSL_DYNAMIC_LINKER) + + #define LINK_OS_LINUX_SPEC "-m elf32ppclinux %{!shared: %{!static: \ + %{rdynamic:-export-dynamic} \ +@@ -895,6 +905,7 @@ ncrtn.o%s" + { "link_os_openbsd", LINK_OS_OPENBSD_SPEC }, \ + { "link_os_default", LINK_OS_DEFAULT_SPEC }, \ + { "cc1_secure_plt_default", CC1_SECURE_PLT_DEFAULT_SPEC }, \ ++ { "link_secure_plt_default", LINK_SECURE_PLT_DEFAULT_SPEC }, \ + { "cpp_os_ads", CPP_OS_ADS_SPEC }, \ + { "cpp_os_yellowknife", CPP_OS_YELLOWKNIFE_SPEC }, \ + { "cpp_os_mvme", CPP_OS_MVME_SPEC }, \ +@@ -949,3 +960,72 @@ ncrtn.o%s" + /* This target uses the sysv4.opt file. */ + #define TARGET_USES_SYSV4_OPT 1 + ++/* Include order changes for musl, same as in generic linux.h. */ ++#if DEFAULT_LIBC == LIBC_MUSL ++#define INCLUDE_DEFAULTS_MUSL_GPP \ ++ { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, \ ++ GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 }, \ ++ { GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1, \ ++ GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 1 }, \ ++ { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1, \ ++ GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 }, ++ ++#ifdef LOCAL_INCLUDE_DIR ++#define INCLUDE_DEFAULTS_MUSL_LOCAL \ ++ { LOCAL_INCLUDE_DIR, 0, 0, 1, 1, 2 }, \ ++ { LOCAL_INCLUDE_DIR, 0, 0, 1, 1, 0 }, ++#else ++#define INCLUDE_DEFAULTS_MUSL_LOCAL ++#endif ++ ++#ifdef PREFIX_INCLUDE_DIR ++#define INCLUDE_DEFAULTS_MUSL_PREFIX \ ++ { PREFIX_INCLUDE_DIR, 0, 0, 1, 0, 0}, ++#else ++#define INCLUDE_DEFAULTS_MUSL_PREFIX ++#endif ++ ++#ifdef CROSS_INCLUDE_DIR ++#define INCLUDE_DEFAULTS_MUSL_CROSS \ ++ { CROSS_INCLUDE_DIR, "GCC", 0, 0, 0, 0}, ++#else ++#define INCLUDE_DEFAULTS_MUSL_CROSS ++#endif ++ ++#ifdef TOOL_INCLUDE_DIR ++#define INCLUDE_DEFAULTS_MUSL_TOOL \ ++ { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1, 0, 0}, ++#else ++#define INCLUDE_DEFAULTS_MUSL_TOOL ++#endif ++ ++#ifdef NATIVE_SYSTEM_HEADER_DIR ++#define INCLUDE_DEFAULTS_MUSL_NATIVE \ ++ { NATIVE_SYSTEM_HEADER_DIR, 0, 0, 0, 1, 2 }, \ ++ { NATIVE_SYSTEM_HEADER_DIR, 0, 0, 0, 1, 0 }, ++#else ++#define INCLUDE_DEFAULTS_MUSL_NATIVE ++#endif ++ ++#if defined (CROSS_DIRECTORY_STRUCTURE) && !defined (TARGET_SYSTEM_ROOT) ++# undef INCLUDE_DEFAULTS_MUSL_LOCAL ++# define INCLUDE_DEFAULTS_MUSL_LOCAL ++# undef INCLUDE_DEFAULTS_MUSL_NATIVE ++# define INCLUDE_DEFAULTS_MUSL_NATIVE ++#else ++# undef INCLUDE_DEFAULTS_MUSL_CROSS ++# define INCLUDE_DEFAULTS_MUSL_CROSS ++#endif ++ ++#undef INCLUDE_DEFAULTS ++#define INCLUDE_DEFAULTS \ ++ { \ ++ INCLUDE_DEFAULTS_MUSL_GPP \ ++ INCLUDE_DEFAULTS_MUSL_PREFIX \ ++ INCLUDE_DEFAULTS_MUSL_CROSS \ ++ INCLUDE_DEFAULTS_MUSL_TOOL \ ++ INCLUDE_DEFAULTS_MUSL_NATIVE \ ++ { GCC_INCLUDE_DIR, "GCC", 0, 1, 0, 0 }, \ ++ { 0, 0, 0, 0, 0, 0 } \ ++ } ++#endif +diff --git a/gcc/config/rs6000/sysv4le.h b/gcc/config/rs6000/sysv4le.h +index 7b1d6a1..064323c 100644 +--- a/gcc/config/rs6000/sysv4le.h ++++ b/gcc/config/rs6000/sysv4le.h +@@ -35,3 +35,5 @@ + /* Little-endian PowerPC64 Linux uses the ELF v2 ABI by default. */ + #define LINUX64_DEFAULT_ABI_ELFv2 + ++#undef MUSL_DYNAMIC_LINKER_E ++#define MUSL_DYNAMIC_LINKER_E ENDIAN_SELECT("","le","le") +diff --git a/gcc/config/sh/linux.h b/gcc/config/sh/linux.h +index 0f5d614..4c167c6 100644 +--- a/gcc/config/sh/linux.h ++++ b/gcc/config/sh/linux.h +@@ -43,6 +43,29 @@ along with GCC; see the file COPYING3. If not see + + #define TARGET_ASM_FILE_END file_end_indicate_exec_stack + ++#if TARGET_ENDIAN_DEFAULT == MASK_LITTLE_ENDIAN ++#define MUSL_DYNAMIC_LINKER_E "%{mb:eb}" ++#else ++#define MUSL_DYNAMIC_LINKER_E "%{!ml:eb}" ++#endif ++ ++#if TARGET_CPU_DEFAULT & ( MASK_HARD_SH2A_DOUBLE | MASK_SH4 ) ++/* "-nofpu" if any nofpu option is specified */ ++#define MUSL_DYNAMIC_LINKER_FP \ ++ "%{m1|m2|m2a-nofpu|m3|m4-nofpu|m4-100-nofpu|m4-200-nofpu|m4-300-nofpu|" \ ++ "m4-340|m4-400|m4-500|m4al|m5-32media-nofpu|m5-64media-nofpu|" \ ++ "m5-compact-nofpu:-nofpu}" ++#else ++/* "-nofpu" if none of the hard fpu options are specified */ ++#define MUSL_DYNAMIC_LINKER_FP \ ++ "%{m2a|m4|m4-100|m4-200|m4-300|m4a|m5-32media|m5-64media|m5-compact:;:-nofpu}" ++#endif ++ ++#undef MUSL_DYNAMIC_LINKER ++#define MUSL_DYNAMIC_LINKER \ ++ "/lib/ld-musl-sh" MUSL_DYNAMIC_LINKER_E MUSL_DYNAMIC_LINKER_FP \ ++ "%{mfdpic:-fdpic}.so.1" ++ + #define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2" + + #undef SUBTARGET_LINK_EMUL_SUFFIX +diff --git a/gcc/configure b/gcc/configure +index 0037240..66aab9f 100755 +--- a/gcc/configure ++++ b/gcc/configure +@@ -27742,6 +27742,9 @@ if test "${gcc_cv_libc_provides_ssp+set}" = set; then : + else + gcc_cv_libc_provides_ssp=no + case "$target" in ++ *-*-musl*) ++ # All versions of musl provide stack protector ++ gcc_cv_libc_provides_ssp=yes;; + *-*-linux* | *-*-kfreebsd*-gnu | *-*-knetbsd*-gnu) + # glibc 2.4 and later provides __stack_chk_fail and + # either __stack_chk_guard, or TLS access to stack guard canary. +@@ -27774,6 +27777,7 @@ fi + # ) and for now + # simply assert that glibc does provide this, which is true for all + # realistically usable GNU/Hurd configurations. ++ # All supported versions of musl provide it as well + gcc_cv_libc_provides_ssp=yes;; + *-*-darwin* | *-*-freebsd*) + ac_fn_c_check_func "$LINENO" "__stack_chk_fail" "ac_cv_func___stack_chk_fail" +@@ -27870,6 +27874,9 @@ case "$target" in + gcc_cv_target_dl_iterate_phdr=no + fi + ;; ++ *-linux-musl*) ++ gcc_cv_target_dl_iterate_phdr=yes ++ ;; + esac + + if test x$gcc_cv_target_dl_iterate_phdr = xyes; then +diff --git a/gcc/configure.ac b/gcc/configure.ac +index 6f38ba1..b81960c 100644 +--- a/gcc/configure.ac ++++ b/gcc/configure.ac +@@ -5229,6 +5229,9 @@ AC_CACHE_CHECK(__stack_chk_fail in target C library, + gcc_cv_libc_provides_ssp, + [gcc_cv_libc_provides_ssp=no + case "$target" in ++ *-*-musl*) ++ # All versions of musl provide stack protector ++ gcc_cv_libc_provides_ssp=yes;; + *-*-linux* | *-*-kfreebsd*-gnu | *-*-knetbsd*-gnu) + # glibc 2.4 and later provides __stack_chk_fail and + # either __stack_chk_guard, or TLS access to stack guard canary. +@@ -5255,6 +5258,7 @@ AC_CACHE_CHECK(__stack_chk_fail in target C library, + # ) and for now + # simply assert that glibc does provide this, which is true for all + # realistically usable GNU/Hurd configurations. ++ # All supported versions of musl provide it as well + gcc_cv_libc_provides_ssp=yes;; + *-*-darwin* | *-*-freebsd*) + AC_CHECK_FUNC(__stack_chk_fail,[gcc_cv_libc_provides_ssp=yes], +@@ -5328,6 +5332,9 @@ case "$target" in + gcc_cv_target_dl_iterate_phdr=no + fi + ;; ++ *-linux-musl*) ++ gcc_cv_target_dl_iterate_phdr=yes ++ ;; + esac + GCC_TARGET_TEMPLATE([TARGET_DL_ITERATE_PHDR]) + if test x$gcc_cv_target_dl_iterate_phdr = xyes; then +diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi +index f84a199..ee9765b 100644 +--- a/gcc/doc/invoke.texi ++++ b/gcc/doc/invoke.texi +@@ -667,7 +667,7 @@ Objective-C and Objective-C++ Dialects}. + -mcpu=@var{cpu}} + + @emph{GNU/Linux Options} +-@gccoptlist{-mglibc -muclibc -mbionic -mandroid @gol ++@gccoptlist{-mglibc -muclibc -mmusl -mbionic -mandroid @gol + -tno-android-cc -tno-android-ld} + + @emph{H8/300 Options} +@@ -15324,13 +15324,19 @@ These @samp{-m} options are defined for GNU/Linux targets: + @item -mglibc + @opindex mglibc + Use the GNU C library. This is the default except +-on @samp{*-*-linux-*uclibc*} and @samp{*-*-linux-*android*} targets. ++on @samp{*-*-linux-*uclibc*}, @samp{*-*-linux-*musl*} and ++@samp{*-*-linux-*android*} targets. + + @item -muclibc + @opindex muclibc + Use uClibc C library. This is the default on + @samp{*-*-linux-*uclibc*} targets. + ++@item -mmusl ++@opindex mmusl ++Use the musl C library. This is the default on ++@samp{*-*-linux-*musl*} targets. ++ + @item -mbionic + @opindex mbionic + Use Bionic C library. This is the default on +diff --git a/libcilkrts/runtime/os-unix.c b/libcilkrts/runtime/os-unix.c +index cb582dd..e43d7d5 100644 +--- a/libcilkrts/runtime/os-unix.c ++++ b/libcilkrts/runtime/os-unix.c +@@ -51,6 +51,7 @@ + #if defined __linux__ + # include + # include ++# include + #elif defined __APPLE__ + # include + // Uses sysconf(_SC_NPROCESSORS_ONLN) in verbose output +@@ -400,28 +401,19 @@ COMMON_SYSDEP void __cilkrts_sleep(void) + + COMMON_SYSDEP void __cilkrts_yield(void) + { +-#if __APPLE__ || __FreeBSD__ || __VXWORKS__ +- // On MacOS, call sched_yield to yield quantum. I'm not sure why we +- // don't do this on Linux also. +- sched_yield(); +-#elif defined(__DragonFly__) +- // On DragonFly BSD, call sched_yield to yield quantum. +- sched_yield(); +-#elif defined(__MIC__) ++#if defined(__MIC__) + // On MIC, pthread_yield() really trashes things. Arch's measurements + // showed that calling _mm_delay_32() (or doing nothing) was a better + // option. Delaying 1024 clock cycles is a reasonable compromise between + // giving up the processor and latency starting up when work becomes + // available + _mm_delay_32(1024); +-#elif defined(__ANDROID__) || (defined(__sun__) && defined(__svr4__)) +- // On Android and Solaris, call sched_yield to yield quantum. I'm not +- // sure why we don't do this on Linux also. +- sched_yield(); +-#else +- // On Linux, call pthread_yield (which in turn will call sched_yield) +- // to yield quantum. ++#elif defined(__sun__) && !defined(__svr4__) ++ // On old SunOS call pthread_yield to yield a quantum. + pthread_yield(); ++#else ++ // On other platforms call sched_yield to yield a quantum. ++ sched_yield(); + #endif + } + +diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c +index e1e566b..137dced 100644 +--- a/libgcc/unwind-dw2-fde-dip.c ++++ b/libgcc/unwind-dw2-fde-dip.c +@@ -59,6 +59,12 @@ + + #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \ + && defined(TARGET_DL_ITERATE_PHDR) \ ++ && defined(__linux__) ++# define USE_PT_GNU_EH_FRAME ++#endif ++ ++#if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \ ++ && defined(TARGET_DL_ITERATE_PHDR) \ + && (defined(__DragonFly__) || defined(__FreeBSD__)) + # define ElfW __ElfN + # define USE_PT_GNU_EH_FRAME +diff --git a/libgfortran/acinclude.m4 b/libgfortran/acinclude.m4 +index ba890f9..30b8b1a6 100644 +--- a/libgfortran/acinclude.m4 ++++ b/libgfortran/acinclude.m4 +@@ -100,7 +100,7 @@ void foo (void); + [Define to 1 if the target supports #pragma weak]) + fi + case "$host" in +- *-*-darwin* | *-*-hpux* | *-*-cygwin* | *-*-mingw* ) ++ *-*-darwin* | *-*-hpux* | *-*-cygwin* | *-*-mingw* | *-*-musl* ) + AC_DEFINE(GTHREAD_USE_WEAK, 0, + [Define to 0 if the target shouldn't use #pragma weak]) + ;; +diff --git a/libgfortran/configure b/libgfortran/configure +index e1592f7..07542e1 100755 +--- a/libgfortran/configure ++++ b/libgfortran/configure +@@ -26447,7 +26447,7 @@ $as_echo "#define SUPPORTS_WEAK 1" >>confdefs.h + + fi + case "$host" in +- *-*-darwin* | *-*-hpux* | *-*-cygwin* | *-*-mingw* ) ++ *-*-darwin* | *-*-hpux* | *-*-cygwin* | *-*-mingw* | *-*-musl* ) + + $as_echo "#define GTHREAD_USE_WEAK 0" >>confdefs.h + +diff --git a/libitm/config/arm/hwcap.cc b/libitm/config/arm/hwcap.cc +index a1c2cfd..ea8f023 100644 +--- a/libitm/config/arm/hwcap.cc ++++ b/libitm/config/arm/hwcap.cc +@@ -40,7 +40,7 @@ int GTM_hwcap HIDDEN = 0 + + #ifdef __linux__ + #include +-#include ++#include + #include + + static void __attribute__((constructor)) +diff --git a/libitm/config/linux/x86/tls.h b/libitm/config/linux/x86/tls.h +index e731ab7..54ad8b6 100644 +--- a/libitm/config/linux/x86/tls.h ++++ b/libitm/config/linux/x86/tls.h +@@ -25,16 +25,19 @@ + #ifndef LIBITM_X86_TLS_H + #define LIBITM_X86_TLS_H 1 + +-#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 10) ++#if defined(__GLIBC_PREREQ) ++#if __GLIBC_PREREQ(2, 10) + /* Use slots in the TCB head rather than __thread lookups. + GLIBC has reserved words 10 through 13 for TM. */ + #define HAVE_ARCH_GTM_THREAD 1 + #define HAVE_ARCH_GTM_THREAD_DISP 1 + #endif ++#endif + + #include "config/generic/tls.h" + +-#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 10) ++#if defined(__GLIBC_PREREQ) ++#if __GLIBC_PREREQ(2, 10) + namespace GTM HIDDEN { + + #ifdef __x86_64__ +@@ -101,5 +104,6 @@ static inline void set_abi_disp(struct abi_dispatch *x) + + } // namespace GTM + #endif /* >= GLIBC 2.10 */ ++#endif + + #endif // LIBITM_X86_TLS_H +diff --git a/libstdc++-v3/config/os/generic/os_defines.h b/libstdc++-v3/config/os/generic/os_defines.h +index 45bf52a..103ec0e 100644 +--- a/libstdc++-v3/config/os/generic/os_defines.h ++++ b/libstdc++-v3/config/os/generic/os_defines.h +@@ -33,4 +33,9 @@ + // System-specific #define, typedefs, corrections, etc, go here. This + // file will come before all others. + ++// Disable the weak reference logic in gthr.h for os/generic because it ++// is broken on every platform unless there is implementation specific ++// workaround in gthr-posix.h and at link-time for static linking. ++#define _GLIBCXX_GTHREAD_USE_WEAK 0 ++ + #endif +diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host +index 640199c..106134e 100644 +--- a/libstdc++-v3/configure.host ++++ b/libstdc++-v3/configure.host +@@ -273,6 +273,9 @@ case "${host_os}" in + freebsd*) + os_include_dir="os/bsd/freebsd" + ;; ++ linux-musl*) ++ os_include_dir="os/generic" ++ ;; + gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu) + if [ "$uclibc" = "yes" ]; then + os_include_dir="os/uclibc" diff --git a/patches/gcc-5.3.0/0002-pr66609.diff b/patches/gcc-5.3.0/0002-pr66609.diff new file mode 100644 index 0000000..5c3bd31 --- /dev/null +++ b/patches/gcc-5.3.0/0002-pr66609.diff @@ -0,0 +1,138 @@ +--- a/gcc/config/sh/sh-protos.h ++++ a/gcc/config/sh/sh-protos.h +@@ -159,6 +159,7 @@ extern int sh_eval_treg_value (rtx op); + extern HOST_WIDE_INT sh_disp_addr_displacement (rtx mem_op); + extern int sh_max_mov_insn_displacement (machine_mode mode, bool consider_sh2a); + extern bool sh_movsf_ie_ra_split_p (rtx, rtx, rtx); ++extern void sh_expand_sym_label2reg (rtx, rtx, rtx, bool); + + /* Result value of sh_find_set_of_reg. */ + struct set_of_reg +--- a/gcc/config/sh/sh.c ++++ a/gcc/config/sh/sh.c +@@ -1604,6 +1604,10 @@ sh_asm_output_addr_const_extra (FILE *file, rtx x) + output_addr_const (file, XVECEXP (x, 0, 0)); + fputs ("@GOTPLT", file); + break; ++ case UNSPEC_PCREL: ++ output_addr_const (file, XVECEXP (x, 0, 0)); ++ fputs ("@PCREL", file); ++ break; + case UNSPEC_DTPOFF: + output_addr_const (file, XVECEXP (x, 0, 0)); + fputs ("@DTPOFF", file); +@@ -10441,6 +10445,7 @@ nonpic_symbol_mentioned_p (rtx x) + || XINT (x, 1) == UNSPEC_DTPOFF + || XINT (x, 1) == UNSPEC_TPOFF + || XINT (x, 1) == UNSPEC_PLT ++ || XINT (x, 1) == UNSPEC_PCREL + || XINT (x, 1) == UNSPEC_SYMOFF + || XINT (x, 1) == UNSPEC_PCREL_SYMOFF)) + return false; +@@ -10714,7 +10719,8 @@ sh_delegitimize_address (rtx orig_x) + rtx symplt = XEXP (XVECEXP (y, 0, 0), 0); + + if (GET_CODE (symplt) == UNSPEC +- && XINT (symplt, 1) == UNSPEC_PLT) ++ && (XINT (symplt, 1) == UNSPEC_PLT ++ || XINT (symplt, 1) == UNSPEC_PCREL)) + return XVECEXP (symplt, 0, 0); + } + } +@@ -11702,9 +11708,24 @@ sh_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) + || crtl->args.info.stack_regs == 0) + && ! sh_cfun_interrupt_handler_p () + && (! flag_pic +- || (decl && ! TREE_PUBLIC (decl)) ++ || (decl && ! (TREE_PUBLIC (decl) || DECL_WEAK (decl))) + || (decl && DECL_VISIBILITY (decl) != VISIBILITY_DEFAULT))); + } ++ ++/* Expand to appropriate sym*_label2reg for SYM and SIBCALL_P. */ ++void ++sh_expand_sym_label2reg (rtx reg, rtx sym, rtx lab, bool sibcall_p) ++{ ++ const_tree decl = SYMBOL_REF_DECL (sym); ++ bool is_weak = (decl && DECL_P (decl) && DECL_WEAK (decl)); ++ ++ if (!is_weak && SYMBOL_REF_LOCAL_P (sym)) ++ emit_insn (gen_sym_label2reg (reg, sym, lab)); ++ else if (sibcall_p) ++ emit_insn (gen_symPCREL_label2reg (reg, sym, lab)); ++ else ++ emit_insn (gen_symPLT_label2reg (reg, sym, lab)); ++} + + /* Machine specific built-in functions. */ + +--- a/gcc/config/sh/sh.md ++++ a/gcc/config/sh/sh.md +@@ -135,6 +135,7 @@ + UNSPEC_PLT + UNSPEC_CALLER + UNSPEC_GOTPLT ++ UNSPEC_PCREL + UNSPEC_ICACHE + UNSPEC_INIT_TRAMP + UNSPEC_FCOSA +@@ -9470,11 +9471,8 @@ label: + [(const_int 0)] + { + rtx lab = PATTERN (gen_call_site ()); +- +- if (SYMBOL_REF_LOCAL_P (operands[0])) +- emit_insn (gen_sym_label2reg (operands[2], operands[0], lab)); +- else +- emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab)); ++ ++ sh_expand_sym_label2reg (operands[2], operands[0], lab, false); + emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab))); + DONE; + } +@@ -9605,10 +9603,7 @@ label: + { + rtx lab = PATTERN (gen_call_site ()); + +- if (SYMBOL_REF_LOCAL_P (operands[1])) +- emit_insn (gen_sym_label2reg (operands[3], operands[1], lab)); +- else +- emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab)); ++ sh_expand_sym_label2reg (operands[3], operands[1], lab, false); + emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3], + operands[2], copy_rtx (lab))); + DONE; +@@ -10008,7 +10003,7 @@ label: + rtx lab = PATTERN (gen_call_site ()); + rtx call_insn; + +- emit_insn (gen_sym_label2reg (operands[2], operands[0], lab)); ++ sh_expand_sym_label2reg (operands[2], operands[0], lab, true); + call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1], + copy_rtx (lab))); + SIBLING_CALL_P (call_insn) = 1; +@@ -10200,7 +10195,7 @@ label: + rtx lab = PATTERN (gen_call_site ()); + rtx call_insn; + +- emit_insn (gen_sym_label2reg (operands[3], operands[1], lab)); ++ sh_expand_sym_label2reg (operands[3], operands[1], lab, true); + call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0], + operands[3], + operands[2], +@@ -10748,6 +10743,16 @@ label: + UNSPEC_SYMOFF)))] + "TARGET_SH1" "") + ++(define_expand "symPCREL_label2reg" ++ [(set (match_operand:SI 0 "" "") ++ (const:SI ++ (unspec:SI ++ [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PCREL)) ++ (const:SI (plus:SI (match_operand:SI 2 "" "") ++ (const_int 2)))] UNSPEC_PCREL_SYMOFF)))] ++ "TARGET_SH1" ++ "") ++ + (define_expand "symGOT_load" + [(set (match_dup 2) (match_operand 1 "" "")) + (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG))) diff --git a/patches/gcc-5.3.0/0003-shbitrot.diff b/patches/gcc-5.3.0/0003-shbitrot.diff new file mode 100644 index 0000000..27cbd68 --- /dev/null +++ b/patches/gcc-5.3.0/0003-shbitrot.diff @@ -0,0 +1,33 @@ +--- gcc-5.2.0.orig/gcc/config.gcc ++++ gcc-5.2.0/gcc/config.gcc +@@ -4096,7 +4099,7 @@ + esac + ;; + +- sh[123456ble]-*-* | sh-*-*) ++ sh[123456ble]*-*-* | sh-*-*) + supported_defaults="cpu" + case "`echo $with_cpu | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ_ abcdefghijklmnopqrstuvwxyz- | sed s/sh/m/`" in + "" | m1 | m2 | m2e | m3 | m3e | m4 | m4-single | m4-single-only | m4-nofpu ) +--- gcc-5.2.0.base/gcc/configure.ac 2015-08-11 16:23:36.000000000 +0000 ++++ gcc-5.2.0/gcc/configure.ac 2015-09-13 08:17:31.714972082 +0000 +@@ -3300,7 +3300,7 @@ + tls_first_minor=14 + tls_as_opt="-m64 -Aesame --fatal-warnings" + ;; +- sh-*-* | sh[34]-*-*) ++ sh-*-* | sh[123456789lbe]*-*-*) + conftest_s=' + .section ".tdata","awT",@progbits + foo: .long 25 +--- gcc-5.2.0.base/gcc/configure 2015-08-11 16:23:35.000000000 +0000 ++++ gcc-5.2.0/gcc/configure 2015-09-13 08:17:42.608304751 +0000 +@@ -23754,7 +23754,7 @@ + tls_first_minor=14 + tls_as_opt="-m64 -Aesame --fatal-warnings" + ;; +- sh-*-* | sh[34]-*-*) ++ sh-*-* | sh[123456789lbe]*-*-*) + conftest_s=' + .section ".tdata","awT",@progbits + foo: .long 25 diff --git a/patches/gcc-5.3.0/0004-j2.diff b/patches/gcc-5.3.0/0004-j2.diff new file mode 100644 index 0000000..8f69236 --- /dev/null +++ b/patches/gcc-5.3.0/0004-j2.diff @@ -0,0 +1,349 @@ +diff --git a/gcc/config.gcc b/gcc/config.gcc +index 0f2dc32..a3d0d45 100644 +--- a/gcc/config.gcc ++++ b/gcc/config.gcc +@@ -467,7 +467,7 @@ s390*-*-*) + extra_headers="s390intrin.h htmintrin.h htmxlintrin.h vecintrin.h" + ;; + # Note the 'l'; we need to be able to match e.g. "shle" or "shl". +-sh[123456789lbe]*-*-* | sh-*-*) ++sh[123456789lbej]*-*-* | sh-*-*) + cpu_type=sh + extra_options="${extra_options} fused-madd.opt" + extra_objs="${extra_objs} sh_treg_combine.o sh-mem.o sh_optimize_sett_clrt.o" +@@ -2601,19 +2601,19 @@ s390x-ibm-tpf*) + extra_options="${extra_options} s390/tpf.opt" + tmake_file="${tmake_file} s390/t-s390" + ;; +-sh-*-elf* | sh[12346l]*-*-elf* | \ +- sh-*-linux* | sh[2346lbe]*-*-linux* | \ ++sh-*-elf* | sh[12346lj]*-*-elf* | \ ++ sh-*-linux* | sh[2346lbej]*-*-linux* | \ + sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \ + sh64-*-netbsd* | sh64l*-*-netbsd*) + tmake_file="${tmake_file} sh/t-sh sh/t-elf" + if test x${with_endian} = x; then + case ${target} in +- sh[1234]*be-*-* | sh[1234]*eb-*-*) with_endian=big ;; ++ sh[j1234]*be-*-* | sh[j1234]*eb-*-*) with_endian=big ;; + shbe-*-* | sheb-*-*) with_endian=big,little ;; + sh[1234]l* | sh[34]*-*-linux*) with_endian=little ;; + shl* | sh64l* | sh*-*-linux* | \ + sh5l* | sh-superh-elf) with_endian=little,big ;; +- sh[1234]*-*-*) with_endian=big ;; ++ sh[j1234]*-*-*) with_endian=big ;; + *) with_endian=big,little ;; + esac + fi +@@ -2703,6 +2703,7 @@ sh-*-elf* | sh[12346l]*-*-elf* | \ + sh2a_nofpu*) sh_cpu_target=sh2a-nofpu ;; + sh2a*) sh_cpu_target=sh2a ;; + sh2e*) sh_cpu_target=sh2e ;; ++ shj2*) sh_cpu_target=shj2;; + sh2*) sh_cpu_target=sh2 ;; + *) sh_cpu_target=sh1 ;; + esac +@@ -2727,7 +2728,7 @@ sh-*-elf* | sh[12346l]*-*-elf* | \ + sh2a-single-only | sh2a-single | sh2a-nofpu | sh2a | \ + sh4a-single-only | sh4a-single | sh4a-nofpu | sh4a | sh4al | \ + sh4-single-only | sh4-single | sh4-nofpu | sh4 | sh4-300 | \ +- sh3e | sh3 | sh2e | sh2 | sh1) ;; ++ sh3e | sh3 | sh2e | sh2 | sh1 | shj2) ;; + "") sh_cpu_default=${sh_cpu_target} ;; + *) echo "with_cpu=$with_cpu not supported"; exit 1 ;; + esac +@@ -2738,9 +2739,9 @@ sh-*-elf* | sh[12346l]*-*-elf* | \ + sh[1234]*) sh_multilibs=${sh_cpu_target} ;; + sh64* | sh5*) sh_multilibs=m5-32media,m5-32media-nofpu,m5-compact,m5-compact-nofpu,m5-64media,m5-64media-nofpu ;; + sh-superh-*) sh_multilibs=m4,m4-single,m4-single-only,m4-nofpu ;; +- sh*-*-linux*) sh_multilibs=m1,m2,m2a,m3e,m4 ;; ++ sh*-*-linux*) sh_multilibs=m1,m2,m2a,m3e,m4,mj2 ;; + sh*-*-netbsd*) sh_multilibs=m3,m3e,m4 ;; +- *) sh_multilibs=m1,m2,m2e,m4,m4-single,m4-single-only,m2a,m2a-single ;; ++ *) sh_multilibs=m1,m2,m2e,m4,m4-single,m4-single-only,m2a,m2a-single,mj2 ;; + esac + if test x$with_fp = xno; then + sh_multilibs="`echo $sh_multilibs|sed -e s/m4/sh4-nofpu/ -e s/,m4-[^,]*//g -e s/,m[23]e// -e s/m2a,m2a-single/m2a-nofpu/ -e s/m5-..m....,//g`" +@@ -2758,7 +2759,8 @@ sh-*-elf* | sh[12346l]*-*-elf* | \ + m2a | m2a-single | m2a-single-only | m2a-nofpu | \ + m5-64media | m5-64media-nofpu | \ + m5-32media | m5-32media-nofpu | \ +- m5-compact | m5-compact-nofpu) ++ m5-compact | m5-compact-nofpu | \ ++ mj2) + # TM_MULTILIB_CONFIG is used by t-sh for the non-endian multilib definition + # It is passed to MULTIILIB_OPTIONS verbatim. + TM_MULTILIB_CONFIG="${TM_MULTILIB_CONFIG}/${sh_multilib}" +@@ -2775,7 +2777,7 @@ sh-*-elf* | sh[12346l]*-*-elf* | \ + done + TM_MULTILIB_CONFIG=`echo $TM_MULTILIB_CONFIG | sed 's:^/::'` + if test x${enable_incomplete_targets} = xyes ; then +- tm_defines="$tm_defines SUPPORT_SH1=1 SUPPORT_SH2E=1 SUPPORT_SH4=1 SUPPORT_SH4_SINGLE=1 SUPPORT_SH2A=1 SUPPORT_SH2A_SINGLE=1 SUPPORT_SH5_32MEDIA=1 SUPPORT_SH5_32MEDIA_NOFPU=1 SUPPORT_SH5_64MEDIA=1 SUPPORT_SH5_64MEDIA_NOFPU=1" ++ tm_defines="$tm_defines SUPPORT_SH1=1 SUPPORT_SH2E=1 SUPPORT_SH4=1 SUPPORT_SH4_SINGLE=1 SUPPORT_SH2A=1 SUPPORT_SH2A_SINGLE=1 SUPPORT_SH5_32MEDIA=1 SUPPORT_SH5_32MEDIA_NOFPU=1 SUPPORT_SH5_64MEDIA=1 SUPPORT_SH5_64MEDIA_NOFPU=1 SUPPORT_SHJ2=1" + fi + tm_file="$tm_file ./sysroot-suffix.h" + tmake_file="$tmake_file t-sysroot-suffix" +@@ -4106,6 +4109,8 @@ + ;; + m4a | m4a-single | m4a-single-only | m4a-nofpu | m4al) + ;; ++ mj2) ++ ;; + *) + echo "Unknown CPU used in --with-cpu=$with_cpu, known values:" 1>&2 + echo "m1 m2 m2e m3 m3e m4 m4-single m4-single-only m4-nofpu" 1>&2 +@@ -4456,7 +4458,7 @@ case ${target} in + tmake_file="rs6000/t-rs6000 ${tmake_file}" + ;; + +- sh[123456ble]*-*-* | sh-*-*) ++ sh[123456blej]*-*-* | sh-*-*) + c_target_objs="${c_target_objs} sh-c.o" + cxx_target_objs="${cxx_target_objs} sh-c.o" + ;; +diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h +index b08120d..63b77fa 100644 +--- a/gcc/config/sh/sh-protos.h ++++ b/gcc/config/sh/sh-protos.h +@@ -45,6 +45,7 @@ struct sh_atomic_model + hard_llcs, + soft_tcb, + soft_imask, ++ hard_cas, + + num_models + }; +@@ -88,6 +89,9 @@ extern const sh_atomic_model& selected_atomic_model (void); + #define TARGET_ATOMIC_SOFT_IMASK \ + (selected_atomic_model ().type == sh_atomic_model::soft_imask) + ++#define TARGET_ATOMIC_HARD_CAS \ ++ (selected_atomic_model ().type == sh_atomic_model::hard_cas) ++ + #ifdef RTX_CODE + extern rtx sh_fsca_sf2int (void); + extern rtx sh_fsca_int2sf (void); +diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c +index 0b18ce5..bdf96e2 100644 +--- a/gcc/config/sh/sh.c ++++ b/gcc/config/sh/sh.c +@@ -692,6 +692,7 @@ parse_validate_atomic_model_option (const char* str) + model_names[sh_atomic_model::hard_llcs] = "hard-llcs"; + model_names[sh_atomic_model::soft_tcb] = "soft-tcb"; + model_names[sh_atomic_model::soft_imask] = "soft-imask"; ++ model_names[sh_atomic_model::hard_cas] = "hard-cas"; + + const char* model_cdef_names[sh_atomic_model::num_models]; + model_cdef_names[sh_atomic_model::none] = "NONE"; +@@ -699,6 +700,7 @@ parse_validate_atomic_model_option (const char* str) + model_cdef_names[sh_atomic_model::hard_llcs] = "HARD_LLCS"; + model_cdef_names[sh_atomic_model::soft_tcb] = "SOFT_TCB"; + model_cdef_names[sh_atomic_model::soft_imask] = "SOFT_IMASK"; ++ model_cdef_names[sh_atomic_model::hard_cas] = "HARD_CAS"; + + sh_atomic_model ret; + ret.type = sh_atomic_model::none; +@@ -780,6 +782,9 @@ got_mode_name:; + if (ret.type == sh_atomic_model::soft_imask && TARGET_USERMODE) + err_ret ("cannot use atomic model %s in user mode", ret.name); + ++ if (ret.type == sh_atomic_model::hard_cas && !TARGET_SHJ2) ++ err_ret ("atomic model %s is only available J2 targets", ret.name); ++ + return ret; + + #undef err_ret +@@ -845,6 +850,8 @@ sh_option_override (void) + sh_cpu = PROCESSOR_SH2E; + if (TARGET_SH2A) + sh_cpu = PROCESSOR_SH2A; ++ if (TARGET_SHJ2) ++ sh_cpu = PROCESSOR_SHJ2; + if (TARGET_SH3) + sh_cpu = PROCESSOR_SH3; + if (TARGET_SH3E) +diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h +index 7187c23..9d0d1d0 100644 +--- a/gcc/config/sh/sh.h ++++ b/gcc/config/sh/sh.h +@@ -106,6 +106,7 @@ extern int code_for_indirect_jump_scratch; + #define SUPPORT_SH4_SINGLE 1 + #define SUPPORT_SH2A 1 + #define SUPPORT_SH2A_SINGLE 1 ++#define SUPPORT_SHJ2 1 + #endif + + #define TARGET_DIVIDE_INV \ +@@ -157,6 +158,7 @@ extern int code_for_indirect_jump_scratch; + #define SELECT_SH5_32MEDIA_NOFPU (MASK_SH5 | MASK_SH_E) + #define SELECT_SH5_COMPACT (MASK_SH5 | MASK_SH4 | SELECT_SH3E) + #define SELECT_SH5_COMPACT_NOFPU (MASK_SH5 | SELECT_SH3) ++#define SELECT_SHJ2 (MASK_SHJ2 | SELECT_SH2) + + #if SUPPORT_SH1 + #define SUPPORT_SH2 1 +@@ -164,6 +166,7 @@ extern int code_for_indirect_jump_scratch; + #if SUPPORT_SH2 + #define SUPPORT_SH3 1 + #define SUPPORT_SH2A_NOFPU 1 ++#define SUPPORT_SHJ2 1 + #endif + #if SUPPORT_SH3 + #define SUPPORT_SH4_NOFPU 1 +@@ -211,7 +214,7 @@ extern int code_for_indirect_jump_scratch; + #define MASK_ARCH (MASK_SH1 | MASK_SH2 | MASK_SH3 | MASK_SH_E | MASK_SH4 \ + | MASK_HARD_SH2A | MASK_HARD_SH2A_DOUBLE | MASK_SH4A \ + | MASK_HARD_SH4 | MASK_FPU_SINGLE | MASK_SH5 \ +- | MASK_FPU_SINGLE_ONLY) ++ | MASK_FPU_SINGLE_ONLY | MASK_SHJ2) + + /* This defaults us to big-endian. */ + #ifndef TARGET_ENDIAN_DEFAULT +@@ -289,8 +292,8 @@ extern int code_for_indirect_jump_scratch; + %{m5-compact*:--isa=SHcompact} \ + %{m5-32media*:--isa=SHmedia --abi=32} \ + %{m5-64media*:--isa=SHmedia --abi=64} \ +-%{m4al:-dsp} %{mcut2-workaround:-cut2-workaround}" +- ++%{m4al:-dsp} %{mcut2-workaround:-cut2-workaround} \ ++%{mj2:-isa=j2}" + #define ASM_SPEC SH_ASM_SPEC + + #ifndef SUBTARGET_ASM_ENDIAN_SPEC +@@ -1853,7 +1856,7 @@ struct sh_args { + + /* Nonzero if the target supports dynamic shift instructions + like shad and shld. */ +-#define TARGET_DYNSHIFT (TARGET_SH3 || TARGET_SH2A) ++#define TARGET_DYNSHIFT (TARGET_SH3 || TARGET_SH2A || TARGET_SHJ2) + + /* The cost of using the dynamic shift insns (shad, shld) are the same + if they are available. If they are not available a library function will +@@ -2185,6 +2188,7 @@ enum processor_type { + PROCESSOR_SH2, + PROCESSOR_SH2E, + PROCESSOR_SH2A, ++ PROCESSOR_SHJ2, + PROCESSOR_SH3, + PROCESSOR_SH3E, + PROCESSOR_SH4, +diff --git a/gcc/config/sh/sh.opt b/gcc/config/sh/sh.opt +index 1026c73..bac47ed 100644 +--- a/gcc/config/sh/sh.opt ++++ b/gcc/config/sh/sh.opt +@@ -71,6 +71,10 @@ m2e + Target RejectNegative Condition(SUPPORT_SH2E) + Generate SH2e code. + ++mj2 ++Target RejectNegative Mask(SHJ2) Condition(SUPPORT_SHJ2) ++Generate J2 code. ++ + m3 + Target RejectNegative Mask(SH3) Condition(SUPPORT_SH3) + Generate SH3 code. +diff --git a/gcc/config/sh/sync.md b/gcc/config/sh/sync.md +index 6f1337b..cff57b8 100644 +--- a/gcc/config/sh/sync.md ++++ b/gcc/config/sh/sync.md +@@ -240,6 +240,9 @@ + || (TARGET_SH4A && mode == SImode && !TARGET_ATOMIC_STRICT)) + atomic_insn = gen_atomic_compare_and_swap_hard (old_val, mem, + exp_val, new_val); ++ else if (TARGET_ATOMIC_HARD_CAS && mode == SImode) ++ atomic_insn = gen_atomic_compare_and_swap_cas (old_val, mem, ++ exp_val, new_val); + else if (TARGET_ATOMIC_SOFT_GUSA) + atomic_insn = gen_atomic_compare_and_swap_soft_gusa (old_val, mem, + exp_val, new_val); +@@ -306,6 +309,57 @@ + } + [(set_attr "length" "14")]) + ++(define_expand "atomic_compare_and_swapsi_cas" ++ [(set (match_operand:SI 0 "register_operand" "=r") ++ (unspec_volatile:SI ++ [(match_operand:SI 1 "atomic_mem_operand_0" "=Sra") ++ (match_operand:SI 2 "register_operand" "r") ++ (match_operand:SI 3 "register_operand" "r")] ++ UNSPECV_CMPXCHG_1))] ++ "TARGET_ATOMIC_HARD_CAS" ++{ ++ rtx mem = gen_rtx_REG (SImode, 0); ++ emit_move_insn (mem, force_reg (SImode, XEXP (operands[1], 0))); ++ emit_insn (gen_shj2_cas (operands[0], mem, operands[2], operands[3])); ++ DONE; ++}) ++ ++(define_insn "shj2_cas" ++ [(set (match_operand:SI 0 "register_operand" "=&r") ++ (unspec_volatile:SI ++ [(match_operand:SI 1 "register_operand" "=r") ++ (match_operand:SI 2 "register_operand" "r") ++ (match_operand:SI 3 "register_operand" "0")] ++ UNSPECV_CMPXCHG_1)) ++ (set (reg:SI T_REG) ++ (unspec_volatile:SI [(const_int 0)] UNSPECV_CMPXCHG_3))] ++ "TARGET_ATOMIC_HARD_CAS" ++ "cas.l %2,%0,@%1" ++ [(set_attr "length" "2")] ++) ++ ++(define_expand "atomic_compare_and_swapqi_cas" ++ [(set (match_operand:SI 0 "arith_reg_dest" "=&r") ++ (unspec_volatile:SI ++ [(match_operand:SI 1 "atomic_mem_operand_0" "=Sra") ++ (match_operand:SI 2 "arith_operand" "rI08") ++ (match_operand:SI 3 "arith_operand" "rI08")] ++ UNSPECV_CMPXCHG_1))] ++ "TARGET_ATOMIC_HARD_CAS" ++{FAIL;} ++) ++ ++(define_expand "atomic_compare_and_swaphi_cas" ++ [(set (match_operand:SI 0 "arith_reg_dest" "=&r") ++ (unspec_volatile:SI ++ [(match_operand:SI 1 "atomic_mem_operand_0" "=Sra") ++ (match_operand:SI 2 "arith_operand" "rI08") ++ (match_operand:SI 3 "arith_operand" "rI08")] ++ UNSPECV_CMPXCHG_1))] ++ "TARGET_ATOMIC_HARD_CAS" ++{FAIL;} ++) ++ + ;; The QIHImode llcs patterns modify the address register of the memory + ;; operand. In order to express that, we have to open code the memory + ;; operand. Initially the insn is expanded like every other atomic insn +diff --git a/gcc/config/sh/t-sh b/gcc/config/sh/t-sh +index 348cc0b..8e6bdaf 100644 +--- a/gcc/config/sh/t-sh ++++ b/gcc/config/sh/t-sh +@@ -52,7 +52,7 @@ MULTILIB_MATCHES = $(shell \ + m4-single,m4-100-single,m4-200-single,m4-300-single,m4a-single \ + m4,m4-100,m4-200,m4-300,m4a \ + m5-32media,m5-compact,m5-32media \ +- m5-32media-nofpu,m5-compact-nofpu,m5-32media-nofpu; do \ ++ m5-32media-nofpu,m5-compact-nofpu,m5-32media-nofpu,mj2; do \ + subst= ; \ + for lib in `echo $$abi|tr , ' '` ; do \ + if test "`echo $$multilibs|sed s/$$lib//`" != "$$multilibs"; then \ +@@ -65,9 +65,9 @@ MULTILIB_MATCHES = $(shell \ + + # SH1 and SH2A support big endian only. + ifeq ($(DEFAULT_ENDIAN),ml) +-MULTILIB_EXCEPTIONS = m1 ml/m1 m2a* ml/m2a* $(TM_MULTILIB_EXCEPTIONS_CONFIG) ++MULTILIB_EXCEPTIONS = m1 ml/m1 m2a* ml/m2a* ml/mj2 $(TM_MULTILIB_EXCEPTIONS_CONFIG) + else +-MULTILIB_EXCEPTIONS = ml/m1 ml/m2a* $(TM_MULTILIB_EXCEPTIONS_CONFIG) ++MULTILIB_EXCEPTIONS = ml/m1 ml/m2a* ml/mj2 $(TM_MULTILIB_EXCEPTIONS_CONFIG) + endif + + MULTILIB_OSDIRNAMES = \ +@@ -96,6 +96,7 @@ MULTILIB_OSDIRNAMES = \ + m5-compact-nofpu=!m5-compact-nofpu $(OTHER_ENDIAN)/m5-compact-nofpu=!$(OTHER_ENDIAN)/m5-compact-nofpu \ + m5-64media=!m5-64media $(OTHER_ENDIAN)/m5-64media=!$(OTHER_ENDIAN)/m5-64media \ + m5-64media-nofpu=!m5-64media-nofpu $(OTHER_ENDIAN)/m5-64media-nofpu=!$(OTHER_ENDIAN)/m5-64media-nofpu ++ mj2=!j2 + + $(out_object_file): gt-sh.h + gt-sh.h : s-gtype ; @true diff --git a/patches/gcc-5.3.0/0005-staticpie.diff b/patches/gcc-5.3.0/0005-staticpie.diff new file mode 100644 index 0000000..2668462 --- /dev/null +++ b/patches/gcc-5.3.0/0005-staticpie.diff @@ -0,0 +1,24 @@ +--- gcc-5.2.0.orig/gcc/config/gnu-user.h 2015-01-05 12:33:28.000000000 +0000 ++++ gcc-5.2.0/gcc/config/gnu-user.h 2015-08-25 08:15:18.354957759 +0000 +@@ -42,8 +42,8 @@ + + #if defined HAVE_LD_PIE + #define GNU_USER_TARGET_STARTFILE_SPEC \ +- "%{!shared: %{pg|p|profile:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}} \ +- crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s} \ ++ "%{!shared: %{pg|p|profile:gcrt1.o%s;pie:%{static:rcrt1.o%s;:Scrt1.o%s};:crt1.o%s}} \ ++ crti.o%s %{shared|pie:crtbeginS.o%s;static:crtbeginT.o%s;:crtbegin.o%s} \ + %{fvtable-verify=none:%s; \ + fvtable-verify=preinit:vtv_start_preinit.o%s; \ + fvtable-verify=std:vtv_start.o%s}" +--- gcc-5.2.0.orig/gcc/gcc.c 2015-03-10 09:37:41.000000000 +0000 ++++ gcc-5.2.0/gcc/gcc.c 2015-09-30 00:25:33.225927941 +0000 +@@ -739,7 +739,7 @@ + + #ifndef LINK_PIE_SPEC + #ifdef HAVE_LD_PIE +-#define LINK_PIE_SPEC "%{pie:-pie} " ++#define LINK_PIE_SPEC "%{pie:-pie %{static:--no-dynamic-linker}} " + #else + #define LINK_PIE_SPEC "%{pie:} " + #endif diff --git a/patches/gcc-5.3.0/0006-defaultpie.diff b/patches/gcc-5.3.0/0006-defaultpie.diff new file mode 100644 index 0000000..b040441 --- /dev/null +++ b/patches/gcc-5.3.0/0006-defaultpie.diff @@ -0,0 +1,40 @@ +diff --git a/gcc/config.gcc b/gcc/config.gcc +index 3779369..a6d95ca 100644 +--- a/gcc/config.gcc ++++ b/gcc/config.gcc +@@ -3101,6 +3101,12 @@ case ${target} in + ;; + esac + ++case "x${enable_default_pie}" in ++xyes) ++ tm_defines="${tm_defines} ENABLE_DEFAULT_PIE=1" ++ ;; ++esac ++ + t= + all_defaults="abi cpu arch tune schedule float mode fpu divide" + for option in $all_defaults +--- gcc-5.2.0.orig/gcc/gcc.c 2015-03-10 09:37:41.000000000 +0000 ++++ gcc-5.2.0/gcc/gcc.c 2015-08-25 07:47:12.895060530 +0000 +@@ -1012,10 +1012,19 @@ + #define CILK_SELF_SPECS "%{fcilkplus: -pthread}" + #endif + ++/* Default to PIE */ ++#ifndef PIE_SELF_SPECS ++#ifdef ENABLE_DEFAULT_PIE ++#define PIE_SELF_SPECS "%{shared|pie|r|nostdlib|nopie|no-pie:;:-pie} %{fpic|fPIC|fpie|fPIE|fno-pic|fno-PIC|fno-pie|fno-PIE|D__KERNEL__:;:-fPIE}" ++#else ++#define PIE_SELF_SPECS "" ++#endif ++#endif ++ + static const char *const driver_self_specs[] = { + "%{fdump-final-insns:-fdump-final-insns=.} %> 3; ++ int dwords = bytes >> 3; + emit_insn (gen_move_insn (r6, GEN_INT (dwords - 1))); +- emit_insn (gen_block_lump_real_i4 (func_addr_rtx)); ++ emit_insn (gen_block_lump_real_i4 (func_addr_rtx, lab)); + return true; + } + else +@@ -159,10 +160,10 @@ expand_block_move (rtx *operands) + rtx r5 = gen_rtx_REG (SImode, 5); + + sprintf (entry, "__movmemSI%d", bytes); +- function_symbol (func_addr_rtx, entry, SFUNC_STATIC); ++ rtx lab = function_symbol (func_addr_rtx, entry, SFUNC_STATIC).lab; + force_into (XEXP (operands[0], 0), r4); + force_into (XEXP (operands[1], 0), r5); +- emit_insn (gen_block_move_real (func_addr_rtx)); ++ emit_insn (gen_block_move_real (func_addr_rtx, lab)); + return true; + } + +@@ -176,7 +177,7 @@ expand_block_move (rtx *operands) + rtx r5 = gen_rtx_REG (SImode, 5); + rtx r6 = gen_rtx_REG (SImode, 6); + +- function_symbol (func_addr_rtx, "__movmem", SFUNC_STATIC); ++ rtx lab = function_symbol (func_addr_rtx, "__movmem", SFUNC_STATIC).lab; + force_into (XEXP (operands[0], 0), r4); + force_into (XEXP (operands[1], 0), r5); + +@@ -189,7 +190,7 @@ expand_block_move (rtx *operands) + final_switch = 16 - ((bytes / 4) % 16); + while_loop = ((bytes / 4) / 16 - 1) * 16; + emit_insn (gen_move_insn (r6, GEN_INT (while_loop + final_switch))); +- emit_insn (gen_block_lump_real (func_addr_rtx)); ++ emit_insn (gen_block_lump_real (func_addr_rtx, lab)); + return true; + } + +diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h +index f94459f..c64a948 100644 +--- a/gcc/config/sh/sh-protos.h ++++ b/gcc/config/sh/sh-protos.h +@@ -377,7 +377,19 @@ extern void fpscr_set_from_mem (int, HARD_REG_SET); + extern void sh_pr_interrupt (struct cpp_reader *); + extern void sh_pr_trapa (struct cpp_reader *); + extern void sh_pr_nosave_low_regs (struct cpp_reader *); +-extern rtx function_symbol (rtx, const char *, enum sh_function_kind); ++ ++struct function_symbol_result ++{ ++ function_symbol_result (void) : sym (NULL), lab (NULL) { } ++ function_symbol_result (rtx s, rtx l) : sym (s), lab (l) { } ++ ++ rtx sym; ++ rtx lab; ++}; ++ ++extern function_symbol_result function_symbol (rtx, const char *, ++ sh_function_kind); ++extern rtx sh_get_fdpic_reg_initial_val (void); + extern rtx sh_get_pr_initial_val (void); + + extern void sh_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, +@@ -396,4 +408,5 @@ extern bool sh_hard_regno_mode_ok (unsigned int, machine_mode); + extern machine_mode sh_hard_regno_caller_save_mode (unsigned int, unsigned int, + machine_mode); + extern bool sh_can_use_simple_return_p (void); ++extern rtx sh_load_function_descriptor (rtx); + #endif /* ! GCC_SH_PROTOS_H */ +diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c +index 904201b..e6a0b1e 100644 +--- a/gcc/config/sh/sh.c ++++ b/gcc/config/sh/sh.c +@@ -268,6 +268,7 @@ static rtx sh_expand_builtin (tree, rtx, rtx, machine_mode, int); + static void sh_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, + HOST_WIDE_INT, tree); + static void sh_file_start (void); ++static bool sh_assemble_integer (rtx, unsigned int, int); + static bool flow_dependent_p (rtx, rtx); + static void flow_dependent_p_1 (rtx, const_rtx, void *); + static int shiftcosts (rtx); +@@ -276,6 +277,7 @@ static int addsubcosts (rtx); + static int multcosts (rtx); + static bool unspec_caller_rtx_p (rtx); + static bool sh_cannot_copy_insn_p (rtx_insn *); ++static bool sh_cannot_force_const_mem_p (machine_mode, rtx); + static bool sh_rtx_costs (rtx, int, int, int, int *, bool); + static int sh_address_cost (rtx, machine_mode, addr_space_t, bool); + static int sh_pr_n_sets (void); +@@ -421,6 +423,9 @@ static const struct attribute_spec sh_attribute_table[] = + #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE + #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true + ++#undef TARGET_ASM_INTEGER ++#define TARGET_ASM_INTEGER sh_assemble_integer ++ + #undef TARGET_REGISTER_MOVE_COST + #define TARGET_REGISTER_MOVE_COST sh_register_move_cost + +@@ -679,6 +684,9 @@ static const struct attribute_spec sh_attribute_table[] = + #undef TARGET_ATOMIC_TEST_AND_SET_TRUEVAL + #define TARGET_ATOMIC_TEST_AND_SET_TRUEVAL 0x80 + ++#undef TARGET_CANNOT_FORCE_CONST_MEM ++#define TARGET_CANNOT_FORCE_CONST_MEM sh_cannot_force_const_mem_p ++ + struct gcc_target targetm = TARGET_INITIALIZER; + + +@@ -996,6 +1004,13 @@ sh_option_override (void) + if (! global_options_set.x_TARGET_ZDCBRANCH && TARGET_HARD_SH4) + TARGET_ZDCBRANCH = 1; + ++ /* FDPIC code is a special form of PIC, and the vast majority of code ++ generation constraints that apply to PIC also apply to FDPIC, so we ++ set flag_pic to avoid the need to check TARGET_FDPIC everywhere ++ flag_pic is checked. */ ++ if (TARGET_FDPIC && !flag_pic) ++ flag_pic = 2; ++ + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) + if (! VALID_REGISTER_P (regno)) + sh_register_names[regno][0] = '\0'; +@@ -1687,6 +1702,14 @@ sh_asm_output_addr_const_extra (FILE *file, rtx x) + output_addr_const (file, XVECEXP (x, 0, 1)); + fputs ("-.)", file); + break; ++ case UNSPEC_GOTFUNCDESC: ++ output_addr_const (file, XVECEXP (x, 0, 0)); ++ fputs ("@GOTFUNCDESC", file); ++ break; ++ case UNSPEC_GOTOFFFUNCDESC: ++ output_addr_const (file, XVECEXP (x, 0, 0)); ++ fputs ("@GOTOFFFUNCDESC", file); ++ break; + default: + return false; + } +@@ -1871,6 +1894,9 @@ prepare_move_operands (rtx operands[], machine_mode mode) + { + case TLS_MODEL_GLOBAL_DYNAMIC: + tga_ret = gen_rtx_REG (Pmode, R0_REG); ++ if (TARGET_FDPIC) ++ emit_move_insn (gen_rtx_REG (Pmode, PIC_REG), ++ sh_get_fdpic_reg_initial_val ()); + emit_call_insn (gen_tls_global_dynamic (tga_ret, op1)); + tmp = gen_reg_rtx (Pmode); + emit_move_insn (tmp, tga_ret); +@@ -1879,6 +1905,9 @@ prepare_move_operands (rtx operands[], machine_mode mode) + + case TLS_MODEL_LOCAL_DYNAMIC: + tga_ret = gen_rtx_REG (Pmode, R0_REG); ++ if (TARGET_FDPIC) ++ emit_move_insn (gen_rtx_REG (Pmode, PIC_REG), ++ sh_get_fdpic_reg_initial_val ()); + emit_call_insn (gen_tls_local_dynamic (tga_ret, op1)); + + tmp = gen_reg_rtx (Pmode); +@@ -1896,6 +1925,9 @@ prepare_move_operands (rtx operands[], machine_mode mode) + case TLS_MODEL_INITIAL_EXEC: + tga_op1 = !can_create_pseudo_p () ? op0 : gen_reg_rtx (Pmode); + tmp = gen_sym2GOTTPOFF (op1); ++ if (TARGET_FDPIC) ++ emit_move_insn (gen_rtx_REG (Pmode, PIC_REG), ++ sh_get_fdpic_reg_initial_val ()); + emit_insn (gen_tls_initial_exec (tga_op1, tmp)); + op1 = tga_op1; + break; +@@ -1922,6 +1954,22 @@ prepare_move_operands (rtx operands[], machine_mode mode) + operands[1] = op1; + } + } ++ ++ if (SH_OFFSETS_MUST_BE_WITHIN_SECTIONS_P) ++ { ++ rtx base, offset; ++ split_const (operands[1], &base, &offset); ++ ++ if (GET_CODE (base) == SYMBOL_REF ++ && !offset_within_block_p (base, INTVAL (offset))) ++ { ++ rtx tmp = can_create_pseudo_p () ? gen_reg_rtx (mode) : operands[0]; ++ emit_move_insn (tmp, base); ++ if (!arith_operand (offset, mode)) ++ offset = force_reg (mode, offset); ++ emit_insn (gen_add3_insn (operands[0], tmp, offset)); ++ } ++ } + } + + /* Implement the canonicalize_comparison target hook for the combine +@@ -3026,6 +3074,24 @@ sh_file_start (void) + } + } + ++/* Implementation of TARGET_ASM_INTEGER for SH. Pointers to functions ++ need to be output as pointers to function descriptors for ++ FDPIC. */ ++ ++static bool ++sh_assemble_integer (rtx value, unsigned int size, int aligned_p) ++{ ++ if (TARGET_FDPIC && size == UNITS_PER_WORD ++ && GET_CODE (value) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (value)) ++ { ++ fputs ("\t.long\t", asm_out_file); ++ output_addr_const (asm_out_file, value); ++ fputs ("@FUNCDESC\n", asm_out_file); ++ return true; ++ } ++ return default_assemble_integer (value, size, aligned_p); ++} ++ + /* Check if PAT includes UNSPEC_CALLER unspec pattern. */ + static bool + unspec_caller_rtx_p (rtx pat) +@@ -3061,6 +3127,17 @@ sh_cannot_copy_insn_p (rtx_insn *insn) + return false; + + pat = PATTERN (insn); ++ ++ if (GET_CODE (pat) == CLOBBER || GET_CODE (pat) == USE) ++ return false; ++ ++ if (TARGET_FDPIC && GET_CODE (pat) == PARALLEL) ++ { ++ rtx t = XVECEXP (pat, 0, XVECLEN (pat, 0) - 1); ++ if (GET_CODE (t) == USE && unspec_caller_rtx_p (XEXP (t, 0))) ++ return true; ++ } ++ + if (GET_CODE (pat) != SET) + return false; + pat = SET_SRC (pat); +@@ -4102,8 +4179,8 @@ expand_ashiftrt (rtx *operands) + /* Load the value into an arg reg and call a helper. */ + emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]); + sprintf (func, "__ashiftrt_r4_%d", value); +- function_symbol (wrk, func, SFUNC_STATIC); +- emit_insn (gen_ashrsi3_n (GEN_INT (value), wrk)); ++ rtx lab = function_symbol (wrk, func, SFUNC_STATIC).lab; ++ emit_insn (gen_ashrsi3_n (GEN_INT (value), wrk, lab)); + emit_move_insn (operands[0], gen_rtx_REG (SImode, 4)); + return true; + } +@@ -7954,7 +8031,8 @@ sh_expand_prologue (void) + stack_usage += d; + } + +- if (flag_pic && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM)) ++ if (flag_pic && !TARGET_FDPIC ++ && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM)) + emit_insn (gen_GOTaddr2picreg (const0_rtx)); + + if (SHMEDIA_REGS_STACK_ADJUST ()) +@@ -10458,7 +10536,9 @@ nonpic_symbol_mentioned_p (rtx x) + || XINT (x, 1) == UNSPEC_PLT + || XINT (x, 1) == UNSPEC_PCREL + || XINT (x, 1) == UNSPEC_SYMOFF +- || XINT (x, 1) == UNSPEC_PCREL_SYMOFF)) ++ || XINT (x, 1) == UNSPEC_PCREL_SYMOFF ++ || XINT (x, 1) == UNSPEC_GOTFUNCDESC ++ || XINT (x, 1) == UNSPEC_GOTOFFFUNCDESC)) + return false; + + fmt = GET_RTX_FORMAT (GET_CODE (x)); +@@ -10493,7 +10573,26 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED, + if (reg == NULL_RTX) + reg = gen_reg_rtx (Pmode); + +- emit_insn (gen_symGOTOFF2reg (reg, orig)); ++ if (TARGET_FDPIC ++ && GET_CODE (orig) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (orig)) ++ { ++ /* Weak functions may be NULL which doesn't work with ++ GOTOFFFUNCDESC because the runtime offset is not known. */ ++ if (SYMBOL_REF_WEAK (orig)) ++ emit_insn (gen_symGOTFUNCDESC2reg (reg, orig)); ++ else ++ emit_insn (gen_symGOTOFFFUNCDESC2reg (reg, orig)); ++ } ++ else if (TARGET_FDPIC ++ && (GET_CODE (orig) == LABEL_REF ++ || (GET_CODE (orig) == SYMBOL_REF && SYMBOL_REF_DECL (orig) ++ && (TREE_READONLY (SYMBOL_REF_DECL (orig)) ++ || SYMBOL_REF_EXTERNAL_P (orig) ++ || DECL_SECTION_NAME(SYMBOL_REF_DECL (orig)))))) ++ /* In FDPIC, GOTOFF can only be used for writable data. */ ++ emit_insn (gen_symGOT2reg (reg, orig)); ++ else ++ emit_insn (gen_symGOTOFF2reg (reg, orig)); + return reg; + } + else if (GET_CODE (orig) == SYMBOL_REF) +@@ -10501,7 +10600,10 @@ legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED, + if (reg == NULL_RTX) + reg = gen_reg_rtx (Pmode); + +- emit_insn (gen_symGOT2reg (reg, orig)); ++ if (TARGET_FDPIC && SYMBOL_REF_FUNCTION_P (orig)) ++ emit_insn (gen_symGOTFUNCDESC2reg (reg, orig)); ++ else ++ emit_insn (gen_symGOT2reg (reg, orig)); + return reg; + } + return orig; +@@ -11539,8 +11641,39 @@ sh_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED) + 5 0008 00000000 l1: .long area + 6 000c 00000000 l2: .long function + ++ FDPIC needs a form that includes a function descriptor and ++ code to load the GOT register: ++ 0 0000 00000000 .long l0 ++ 1 0004 00000000 .long gotval ++ 2 0008 D302 l0: mov.l l1,r3 ++ 3 000a D203 mov.l l2,r2 ++ 4 000c 6122 mov.l @r2,r1 ++ 5 000e 5C21 mov.l @(4,r2),r12 ++ 6 0010 412B jmp @r1 ++ 7 0012 0009 nop ++ 8 0014 00000000 l1: .long area ++ 9 0018 00000000 l2: .long function ++ + SH5 (compact) uses r1 instead of r3 for the static chain. */ + ++/* Emit insns to store a value at memory address + offset. */ ++static void ++sh_emit_storesi (rtx addr, HOST_WIDE_INT offset, rtx value) ++{ ++ gcc_assert ((offset & 3) == 0); ++ emit_move_insn (offset == 0 ++ ? change_address (addr, SImode, NULL_RTX) ++ : adjust_address (addr, SImode, offset), value); ++} ++ ++/* Emit insns to store w0 at addr + offset and w1 at addr + offset + 2. */ ++static void ++sh_emit_storehi (rtx addr, HOST_WIDE_INT offset, uint16_t w0, uint16_t w1) ++{ ++ sh_emit_storesi (addr, offset, gen_int_mode (TARGET_LITTLE_ENDIAN ++ ? (w0 | (w1 << 16)) ++ : (w1 | (w0 << 16)), SImode)); ++} + + /* Emit RTL insns to initialize the variable parts of a trampoline. + FNADDR is an RTX for the address of the function's pure code. +@@ -11675,20 +11808,34 @@ sh_trampoline_init (rtx tramp_mem, tree fndecl, rtx cxt) + emit_insn (gen_initialize_trampoline (tramp, cxt, fnaddr)); + return; + } +- emit_move_insn (change_address (tramp_mem, SImode, NULL_RTX), +- gen_int_mode (TARGET_LITTLE_ENDIAN ? 0xd301d202 : 0xd202d301, +- SImode)); +- emit_move_insn (adjust_address (tramp_mem, SImode, 4), +- gen_int_mode (TARGET_LITTLE_ENDIAN ? 0x0009422b : 0x422b0009, +- SImode)); +- emit_move_insn (adjust_address (tramp_mem, SImode, 8), cxt); +- emit_move_insn (adjust_address (tramp_mem, SImode, 12), fnaddr); ++ if (TARGET_FDPIC) ++ { ++ rtx a = force_reg (Pmode, plus_constant (Pmode, XEXP (tramp_mem, 0), 8)); ++ ++ sh_emit_storesi (tramp_mem, 0, a); ++ sh_emit_storesi (tramp_mem, 4, sh_get_fdpic_reg_initial_val ()); ++ ++ sh_emit_storehi (tramp_mem, 8, 0xd302, 0xd203); ++ sh_emit_storehi (tramp_mem, 12, 0x6122, 0x5c21); ++ sh_emit_storehi (tramp_mem, 16, 0x412b, 0x0009); ++ ++ sh_emit_storesi (tramp_mem, 20, cxt); ++ sh_emit_storesi (tramp_mem, 24, fnaddr); ++ } ++ else ++ { ++ sh_emit_storehi (tramp_mem, 0, 0xd202, 0xd301); ++ sh_emit_storehi (tramp_mem, 4, 0x422b, 0x0009); ++ ++ sh_emit_storesi (tramp_mem, 8, cxt); ++ sh_emit_storesi (tramp_mem, 12, fnaddr); ++ } + if (TARGET_HARD_SH4 || TARGET_SH5) + { + if (!TARGET_INLINE_IC_INVALIDATE + || (!(TARGET_SH4A || TARGET_SH4_300) && TARGET_USERMODE)) + emit_library_call (function_symbol (NULL, "__ic_invalidate", +- FUNCTION_ORDINARY), ++ FUNCTION_ORDINARY).sym, + LCT_NORMAL, VOIDmode, 1, tramp, SImode); + else + emit_insn (gen_ic_invalidate_line (tramp)); +@@ -11718,7 +11865,7 @@ sh_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) + && (! TARGET_SHCOMPACT + || crtl->args.info.stack_regs == 0) + && ! sh_cfun_interrupt_handler_p () +- && (! flag_pic ++ && (! flag_pic || TARGET_FDPIC + || (decl && ! (TREE_PUBLIC (decl) || DECL_WEAK (decl))) + || (decl && DECL_VISIBILITY (decl) != VISIBILITY_DEFAULT))); + } +@@ -11732,7 +11879,7 @@ sh_expand_sym_label2reg (rtx reg, rtx sym, rtx lab, bool sibcall_p) + + if (!is_weak && SYMBOL_REF_LOCAL_P (sym)) + emit_insn (gen_sym_label2reg (reg, sym, lab)); +- else if (sibcall_p) ++ else if (sibcall_p && SYMBOL_REF_LOCAL_P (sym)) + emit_insn (gen_symPCREL_label2reg (reg, sym, lab)); + else + emit_insn (gen_symPLT_label2reg (reg, sym, lab)); +@@ -12733,8 +12880,16 @@ sh_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, + #endif + if (TARGET_SH2 && flag_pic) + { +- sibcall = gen_sibcall_pcrel (funexp, const0_rtx); +- XEXP (XVECEXP (sibcall, 0, 2), 0) = scratch2; ++ if (TARGET_FDPIC) ++ { ++ sibcall = gen_sibcall_pcrel_fdpic (funexp, const0_rtx); ++ XEXP (XVECEXP (sibcall, 0, 3), 0) = scratch2; ++ } ++ else ++ { ++ sibcall = gen_sibcall_pcrel (funexp, const0_rtx); ++ XEXP (XVECEXP (sibcall, 0, 2), 0) = scratch2; ++ } + } + else + { +@@ -12775,17 +12930,25 @@ sh_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, + epilogue_completed = 0; + } + +-rtx +-function_symbol (rtx target, const char *name, enum sh_function_kind kind) +-{ +- rtx sym; ++/* Return an RTX pair for the address and call site label of a function ++ NAME of kind KIND, placing the result in TARGET if not NULL. For ++ SFUNC_STATIC, if FDPIC, the LAB member of result will be set to ++ (const_int 0) if jsr should be used, or a label_ref if bsrf should ++ be used. For FDPIC, both SFUNC_GOT and SFUNC_STATIC will return the ++ address of the function itself, not a function descriptor, so they ++ can only be used with functions not using the FDPIC register that ++ are known to be called directory without a PLT entry. */ + ++function_symbol_result ++function_symbol (rtx target, const char *name, sh_function_kind kind) ++{ + /* If this is not an ordinary function, the name usually comes from a + string literal or an sprintf buffer. Make sure we use the same + string consistently, so that cse will be able to unify address loads. */ + if (kind != FUNCTION_ORDINARY) + name = IDENTIFIER_POINTER (get_identifier (name)); +- sym = gen_rtx_SYMBOL_REF (Pmode, name); ++ rtx sym = gen_rtx_SYMBOL_REF (Pmode, name); ++ rtx lab = const0_rtx; + SYMBOL_REF_FLAGS (sym) = SYMBOL_FLAG_FUNCTION; + if (flag_pic) + switch (kind) +@@ -12802,14 +12965,25 @@ function_symbol (rtx target, const char *name, enum sh_function_kind kind) + } + case SFUNC_STATIC: + { +- /* ??? To allow cse to work, we use GOTOFF relocations. +- We could add combiner patterns to transform this into +- straight pc-relative calls with sym2PIC / bsrf when +- label load and function call are still 1:1 and in the +- same basic block during combine. */ + rtx reg = target ? target : gen_reg_rtx (Pmode); + +- emit_insn (gen_symGOTOFF2reg (reg, sym)); ++ if (TARGET_FDPIC) ++ { ++ /* We use PC-relative calls, since GOTOFF can only refer ++ to writable data. This works along with sh_sfunc_call. */ ++ lab = PATTERN (gen_call_site ()); ++ emit_insn (gen_sym_label2reg (reg, sym, lab)); ++ } ++ else ++ { ++ /* ??? To allow cse to work, we use GOTOFF relocations. ++ we could add combiner patterns to transform this into ++ straight pc-relative calls with sym2PIC / bsrf when ++ label load and function call are still 1:1 and in the ++ same basic block during combine. */ ++ emit_insn (gen_symGOTOFF2reg (reg, sym)); ++ } ++ + sym = reg; + break; + } +@@ -12817,9 +12991,9 @@ function_symbol (rtx target, const char *name, enum sh_function_kind kind) + if (target && sym != target) + { + emit_move_insn (target, sym); +- return target; ++ return function_symbol_result (target, lab); + } +- return sym; ++ return function_symbol_result (sym, lab); + } + + /* Find the number of a general purpose register in S. */ +@@ -13432,6 +13606,12 @@ sh_conditional_register_usage (void) + fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; + call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; + } ++ if (TARGET_FDPIC) ++ { ++ fixed_regs[PIC_REG] = 1; ++ call_used_regs[PIC_REG] = 1; ++ call_really_used_regs[PIC_REG] = 1; ++ } + /* Renesas saves and restores mac registers on call. */ + if (TARGET_HITACHI && ! TARGET_NOMACSAVE) + { +@@ -13460,14 +13640,32 @@ sh_conditional_register_usage (void) + static bool + sh_legitimate_constant_p (machine_mode mode, rtx x) + { +- return (TARGET_SHMEDIA +- ? ((mode != DFmode && GET_MODE_CLASS (mode) != MODE_VECTOR_FLOAT) +- || x == CONST0_RTX (mode) +- || !TARGET_SHMEDIA_FPU +- || TARGET_SHMEDIA64) +- : (GET_CODE (x) != CONST_DOUBLE +- || mode == DFmode || mode == SFmode +- || mode == DImode || GET_MODE (x) == VOIDmode)); ++ if (SH_OFFSETS_MUST_BE_WITHIN_SECTIONS_P) ++ { ++ rtx base, offset; ++ split_const (x, &base, &offset); ++ ++ if (GET_CODE (base) == SYMBOL_REF ++ && !offset_within_block_p (base, INTVAL (offset))) ++ return false; ++ } ++ ++ if (TARGET_FDPIC ++ && (SYMBOLIC_CONST_P (x) ++ || (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS ++ && SYMBOLIC_CONST_P (XEXP (XEXP (x, 0), 0))))) ++ return false; ++ ++ if (TARGET_SHMEDIA ++ && ((mode != DFmode && GET_MODE_CLASS (mode) != MODE_VECTOR_FLOAT) ++ || x == CONST0_RTX (mode) ++ || !TARGET_SHMEDIA_FPU ++ || TARGET_SHMEDIA64)) ++ return false; ++ ++ return GET_CODE (x) != CONST_DOUBLE ++ || mode == DFmode || mode == SFmode ++ || mode == DImode || GET_MODE (x) == VOIDmode; + } + + enum sh_divide_strategy_e sh_div_strategy = SH_DIV_STRATEGY_DEFAULT; +@@ -14558,4 +14756,41 @@ sh_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size, + } + } + ++bool ++sh_cannot_force_const_mem_p (machine_mode mode ATTRIBUTE_UNUSED, ++ rtx x ATTRIBUTE_UNUSED) ++{ ++ return TARGET_FDPIC; ++} ++ ++/* Emit insns to load the function address from FUNCDESC (an FDPIC ++ function descriptor) into r1 and the GOT address into r12, ++ returning an rtx for r1. */ ++ ++rtx ++sh_load_function_descriptor (rtx funcdesc) ++{ ++ rtx r1 = gen_rtx_REG (Pmode, R1_REG); ++ rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG); ++ rtx fnaddr = gen_rtx_MEM (Pmode, funcdesc); ++ rtx gotaddr = gen_rtx_MEM (Pmode, plus_constant (Pmode, funcdesc, 4)); ++ ++ emit_move_insn (r1, fnaddr); ++ /* The ABI requires the entry point address to be loaded first, so ++ prevent the load from being moved after that of the GOT ++ address. */ ++ emit_insn (gen_blockage ()); ++ emit_move_insn (pic_reg, gotaddr); ++ return r1; ++} ++ ++/* Return an rtx holding the initial value of the FDPIC register (the ++ FDPIC pointer passed in from the caller). */ ++ ++rtx ++sh_get_fdpic_reg_initial_val (void) ++{ ++ return get_hard_reg_initial_val (Pmode, PIC_REG); ++} ++ + #include "gt-sh.h" +diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h +index aafcf28..e232179 100644 +--- a/gcc/config/sh/sh.h ++++ b/gcc/config/sh/sh.h +@@ -321,7 +321,7 @@ extern int code_for_indirect_jump_scratch; + #endif + + #ifndef SUBTARGET_ASM_SPEC +-#define SUBTARGET_ASM_SPEC "" ++#define SUBTARGET_ASM_SPEC "%{mfdpic:--fdpic}" + #endif + + #if TARGET_ENDIAN_DEFAULT == MASK_LITTLE_ENDIAN +@@ -349,7 +349,7 @@ extern int code_for_indirect_jump_scratch; + #define ASM_ISA_DEFAULT_SPEC "" + #endif /* MASK_SH5 */ + +-#define SUBTARGET_LINK_EMUL_SUFFIX "" ++#define SUBTARGET_LINK_EMUL_SUFFIX "%{mfdpic:_fd}" + #define SUBTARGET_LINK_SPEC "" + + /* Go via SH_LINK_SPEC to avoid code replication. */ +@@ -383,8 +383,18 @@ extern int code_for_indirect_jump_scratch; + "%{m2a*:%eSH2a does not support little-endian}}" + #endif + ++#ifdef FDPIC_DEFAULT ++#define FDPIC_SELF_SPECS "%{!mno-fdpic:-mfdpic}" ++#else ++#define FDPIC_SELF_SPECS ++#endif ++ + #undef DRIVER_SELF_SPECS +-#define DRIVER_SELF_SPECS UNSUPPORTED_SH2A ++#define DRIVER_SELF_SPECS UNSUPPORTED_SH2A SUBTARGET_DRIVER_SELF_SPECS \ ++ FDPIC_SELF_SPECS ++ ++#undef SUBTARGET_DRIVER_SELF_SPECS ++#define SUBTARGET_DRIVER_SELF_SPECS + + #define ASSEMBLER_DIALECT assembler_dialect + +@@ -942,6 +952,10 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \ + code access to data items. */ + #define PIC_OFFSET_TABLE_REGNUM (flag_pic ? PIC_REG : INVALID_REGNUM) + ++/* For FDPIC, the FDPIC register is call-clobbered (otherwise PLT ++ entries would need to handle saving and restoring it). */ ++#define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED TARGET_FDPIC ++ + #define GOT_SYMBOL_NAME "*_GLOBAL_OFFSET_TABLE_" + + /* Definitions for register eliminations. +@@ -1566,7 +1580,8 @@ struct sh_args { + 6 000c 00000000 l2: .long function */ + + /* Length in units of the trampoline for entering a nested function. */ +-#define TRAMPOLINE_SIZE (TARGET_SHMEDIA64 ? 40 : TARGET_SH5 ? 24 : 16) ++#define TRAMPOLINE_SIZE \ ++ (TARGET_SHMEDIA64 ? 40 : TARGET_SH5 ? 24 : TARGET_FDPIC ? 32 : 16) + + /* Alignment required for a trampoline in bits. */ + #define TRAMPOLINE_ALIGNMENT \ +@@ -1622,6 +1637,10 @@ struct sh_args { + || GENERAL_REGISTER_P ((unsigned) reg_renumber[(REGNO)])) \ + : (REGNO) == R0_REG || (unsigned) reg_renumber[(REGNO)] == R0_REG) + ++/* True if SYMBOL + OFFSET constants must refer to something within ++ SYMBOL's section. */ ++#define SH_OFFSETS_MUST_BE_WITHIN_SECTIONS_P TARGET_FDPIC ++ + /* Maximum number of registers that can appear in a valid memory + address. */ + #define MAX_REGS_PER_ADDRESS 2 +@@ -2262,9 +2281,11 @@ extern int current_function_interrupt; + /* We have to distinguish between code and data, so that we apply + datalabel where and only where appropriate. Use sdataN for data. */ + #define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \ +- ((flag_pic && (GLOBAL) ? DW_EH_PE_indirect : 0) \ +- | (flag_pic ? DW_EH_PE_pcrel : DW_EH_PE_absptr) \ +- | ((CODE) ? 0 : (TARGET_SHMEDIA64 ? DW_EH_PE_sdata8 : DW_EH_PE_sdata4))) ++ ((TARGET_FDPIC \ ++ ? ((GLOBAL) ? DW_EH_PE_indirect | DW_EH_PE_datarel : DW_EH_PE_pcrel) \ ++ : ((flag_pic && (GLOBAL) ? DW_EH_PE_indirect : 0) \ ++ | (flag_pic ? DW_EH_PE_pcrel : DW_EH_PE_absptr))) \ ++ | ((CODE) ? 0 : (TARGET_SHMEDIA64 ? DW_EH_PE_sdata8 : DW_EH_PE_sdata4))) + + /* Handle special EH pointer encodings. Absolute, pc-relative, and + indirect are handled automatically. */ +@@ -2277,6 +2298,17 @@ extern int current_function_interrupt; + SYMBOL_REF_FLAGS (ADDR) |= SYMBOL_FLAG_FUNCTION; \ + if (0) goto DONE; \ + } \ ++ if (TARGET_FDPIC \ ++ && ((ENCODING) & 0xf0) == (DW_EH_PE_indirect | DW_EH_PE_datarel)) \ ++ { \ ++ fputs ("\t.ualong ", FILE); \ ++ output_addr_const (FILE, ADDR); \ ++ if (GET_CODE (ADDR) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (ADDR)) \ ++ fputs ("@GOTFUNCDESC", FILE); \ ++ else \ ++ fputs ("@GOT", FILE); \ ++ goto DONE; \ ++ } \ + } while (0) + + #if (defined CRT_BEGIN || defined CRT_END) && ! __SHMEDIA__ +diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md +index d758e3b..45c9995 100644 +--- a/gcc/config/sh/sh.md ++++ b/gcc/config/sh/sh.md +@@ -170,6 +170,9 @@ (define_c_enum "unspec" [ + UNSPEC_SYMOFF + ;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .). + UNSPEC_PCREL_SYMOFF ++ ;; For FDPIC ++ UNSPEC_GOTFUNCDESC ++ UNSPEC_GOTOFFFUNCDESC + ;; Misc builtins + UNSPEC_BUILTIN_STRLEN + ]) +@@ -2591,15 +2594,18 @@ (define_insn "udivsi3_sh2a" + ;; This reload would clobber the value in r0 we are trying to store. + ;; If we let reload allocate r0, then this problem can never happen. + (define_insn "udivsi3_i1" +- [(set (match_operand:SI 0 "register_operand" "=z") ++ [(set (match_operand:SI 0 "register_operand" "=z,z") + (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) + (clobber (reg:SI T_REG)) + (clobber (reg:SI PR_REG)) + (clobber (reg:SI R1_REG)) + (clobber (reg:SI R4_REG)) +- (use (match_operand:SI 1 "arith_reg_operand" "r"))] ++ (use (match_operand:SI 1 "arith_reg_operand" "r,r")) ++ (use (match_operand 2 "" "Z,Ccl"))] + "TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1" +- "jsr @%1%#" ++ "@ ++ jsr @%1%# ++ bsrf %1\n%O2:%#" + [(set_attr "type" "sfunc") + (set_attr "needs_delay_slot" "yes")]) + +@@ -2648,7 +2654,7 @@ (define_expand "udivsi3_i4_media" + }) + + (define_insn "udivsi3_i4" +- [(set (match_operand:SI 0 "register_operand" "=y") ++ [(set (match_operand:SI 0 "register_operand" "=y,y") + (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) + (clobber (reg:SI T_REG)) + (clobber (reg:SI PR_REG)) +@@ -2660,16 +2666,19 @@ (define_insn "udivsi3_i4" + (clobber (reg:SI R4_REG)) + (clobber (reg:SI R5_REG)) + (clobber (reg:SI FPSCR_STAT_REG)) +- (use (match_operand:SI 1 "arith_reg_operand" "r")) ++ (use (match_operand:SI 1 "arith_reg_operand" "r,r")) ++ (use (match_operand 2 "" "Z,Ccl")) + (use (reg:SI FPSCR_MODES_REG))] + "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE" +- "jsr @%1%#" ++ "@ ++ jsr @%1%# ++ bsrf %1\n%O2:%#" + [(set_attr "type" "sfunc") + (set_attr "fp_mode" "double") + (set_attr "needs_delay_slot" "yes")]) + + (define_insn "udivsi3_i4_single" +- [(set (match_operand:SI 0 "register_operand" "=y") ++ [(set (match_operand:SI 0 "register_operand" "=y,y") + (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG))) + (clobber (reg:SI T_REG)) + (clobber (reg:SI PR_REG)) +@@ -2680,10 +2689,13 @@ (define_insn "udivsi3_i4_single" + (clobber (reg:SI R1_REG)) + (clobber (reg:SI R4_REG)) + (clobber (reg:SI R5_REG)) +- (use (match_operand:SI 1 "arith_reg_operand" "r"))] ++ (use (match_operand:SI 1 "arith_reg_operand" "r,r")) ++ (use (match_operand 2 "" "Z,Ccl"))] + "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT) + && TARGET_FPU_SINGLE" +- "jsr @%1%#" ++ "@ ++ jsr @%1%# ++ bsrf %1\n%O2:%#" + [(set_attr "type" "sfunc") + (set_attr "needs_delay_slot" "yes")]) + +@@ -2742,11 +2754,11 @@ (define_expand "udivsi3" + } + else if (TARGET_DIVIDE_CALL_FP) + { +- function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC); ++ rtx lab = function_symbol (operands[3], "__udivsi3_i4", SFUNC_STATIC).lab; + if (TARGET_FPU_SINGLE) +- last = gen_udivsi3_i4_single (operands[0], operands[3]); ++ last = gen_udivsi3_i4_single (operands[0], operands[3], lab); + else +- last = gen_udivsi3_i4 (operands[0], operands[3]); ++ last = gen_udivsi3_i4 (operands[0], operands[3], lab); + } + else if (TARGET_SHMEDIA_FPU) + { +@@ -2771,14 +2783,14 @@ (define_expand "udivsi3" + if (TARGET_SHMEDIA) + last = gen_udivsi3_i1_media (operands[0], operands[3]); + else if (TARGET_FPU_ANY) +- last = gen_udivsi3_i4_single (operands[0], operands[3]); ++ last = gen_udivsi3_i4_single (operands[0], operands[3], const0_rtx); + else +- last = gen_udivsi3_i1 (operands[0], operands[3]); ++ last = gen_udivsi3_i1 (operands[0], operands[3], const0_rtx); + } + else + { +- function_symbol (operands[3], "__udivsi3", SFUNC_STATIC); +- last = gen_udivsi3_i1 (operands[0], operands[3]); ++ rtx lab = function_symbol (operands[3], "__udivsi3", SFUNC_STATIC).lab; ++ last = gen_udivsi3_i1 (operands[0], operands[3], lab); + } + emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]); + emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]); +@@ -2906,7 +2918,7 @@ (define_insn_and_split "*divsi_inv_call_combine" + emit_move_insn (gen_rtx_REG (DImode, R20_REG), x); + break; + } +- sym = function_symbol (NULL, name, kind); ++ sym = function_symbol (NULL, name, kind).sym; + emit_insn (gen_divsi3_media_2 (operands[0], sym)); + DONE; + } +@@ -2926,31 +2938,37 @@ (define_expand "divsi3_i4_media" + }) + + (define_insn "divsi3_i4" +- [(set (match_operand:SI 0 "register_operand" "=y") ++ [(set (match_operand:SI 0 "register_operand" "=y,y") + (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) + (clobber (reg:SI PR_REG)) + (clobber (reg:DF DR0_REG)) + (clobber (reg:DF DR2_REG)) + (clobber (reg:SI FPSCR_STAT_REG)) +- (use (match_operand:SI 1 "arith_reg_operand" "r")) ++ (use (match_operand:SI 1 "arith_reg_operand" "r,r")) ++ (use (match_operand 2 "" "Z,Ccl")) + (use (reg:SI FPSCR_MODES_REG))] + "TARGET_FPU_DOUBLE && ! TARGET_FPU_SINGLE" +- "jsr @%1%#" ++ "@ ++ jsr @%1%# ++ bsrf %1\n%O2:%#" + [(set_attr "type" "sfunc") + (set_attr "fp_mode" "double") + (set_attr "needs_delay_slot" "yes")]) + + (define_insn "divsi3_i4_single" +- [(set (match_operand:SI 0 "register_operand" "=y") ++ [(set (match_operand:SI 0 "register_operand" "=y,y") + (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) + (clobber (reg:SI PR_REG)) + (clobber (reg:DF DR0_REG)) + (clobber (reg:DF DR2_REG)) + (clobber (reg:SI R2_REG)) +- (use (match_operand:SI 1 "arith_reg_operand" "r"))] ++ (use (match_operand:SI 1 "arith_reg_operand" "r,r")) ++ (use (match_operand 2 "" "Z,Ccl"))] + "(TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE || TARGET_SHCOMPACT) + && TARGET_FPU_SINGLE" +- "jsr @%1%#" ++ "@ ++ jsr @%1%# ++ bsrf %1\n%O2:%#" + [(set_attr "type" "sfunc") + (set_attr "needs_delay_slot" "yes")]) + +@@ -2994,11 +3012,12 @@ (define_expand "divsi3" + } + else if (TARGET_DIVIDE_CALL_FP) + { +- function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC); ++ rtx lab = function_symbol (operands[3], sh_divsi3_libfunc, ++ SFUNC_STATIC).lab; + if (TARGET_FPU_SINGLE) +- last = gen_divsi3_i4_single (operands[0], operands[3]); ++ last = gen_divsi3_i4_single (operands[0], operands[3], lab); + else +- last = gen_divsi3_i4 (operands[0], operands[3]); ++ last = gen_divsi3_i4 (operands[0], operands[3], lab); + } + else if (TARGET_SH2A) + { +@@ -3113,7 +3132,7 @@ (define_expand "divsi3" + last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media) + (operands[0], operands[3])); + else if (TARGET_FPU_ANY) +- last = gen_divsi3_i4_single (operands[0], operands[3]); ++ last = gen_divsi3_i4_single (operands[0], operands[3], const0_rtx); + else + last = gen_divsi3_i1 (operands[0], operands[3]); + } +@@ -3713,7 +3732,7 @@ (define_expand "mulsi3" + { + /* The address must be set outside the libcall, + since it goes into a pseudo. */ +- rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC); ++ rtx sym = function_symbol (NULL, "__mulsi3", SFUNC_STATIC).sym; + rtx addr = force_reg (SImode, sym); + rtx insns = gen_mulsi3_call (operands[0], operands[1], + operands[2], addr); +@@ -4970,8 +4989,8 @@ (define_expand "ashlsi3" + { + emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]); + rtx funcaddr = gen_reg_rtx (Pmode); +- function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC); +- emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr)); ++ rtx lab = function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC).lab; ++ emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr, lab)); + + DONE; + } +@@ -5024,15 +5043,18 @@ (define_insn_and_split "ashlsi3_d" + ;; In order to make combine understand the truncation of the shift amount + ;; operand we have to allow it to use pseudo regs for the shift operands. + (define_insn "ashlsi3_d_call" +- [(set (match_operand:SI 0 "arith_reg_dest" "=z") ++ [(set (match_operand:SI 0 "arith_reg_dest" "=z,z") + (ashift:SI (reg:SI R4_REG) +- (and:SI (match_operand:SI 1 "arith_reg_operand" "z") ++ (and:SI (match_operand:SI 1 "arith_reg_operand" "z,z") + (const_int 31)))) +- (use (match_operand:SI 2 "arith_reg_operand" "r")) ++ (use (match_operand:SI 2 "arith_reg_operand" "r,r")) ++ (use (match_operand 3 "" "Z,Ccl")) + (clobber (reg:SI T_REG)) + (clobber (reg:SI PR_REG))] + "TARGET_SH1 && !TARGET_DYNSHIFT" +- "jsr @%2%#" ++ "@ ++ jsr @%2%# ++ bsrf %2\n%O3:%#" + [(set_attr "type" "sfunc") + (set_attr "needs_delay_slot" "yes")]) + +@@ -5374,12 +5396,15 @@ (define_insn "ashrsi3_d" + (define_insn "ashrsi3_n" + [(set (reg:SI R4_REG) + (ashiftrt:SI (reg:SI R4_REG) +- (match_operand:SI 0 "const_int_operand" "i"))) ++ (match_operand:SI 0 "const_int_operand" "i,i"))) + (clobber (reg:SI T_REG)) + (clobber (reg:SI PR_REG)) +- (use (match_operand:SI 1 "arith_reg_operand" "r"))] ++ (use (match_operand:SI 1 "arith_reg_operand" "r,r")) ++ (use (match_operand 2 "" "Z,Ccl"))] + "TARGET_SH1" +- "jsr @%1%#" ++ "@ ++ jsr @%1%# ++ bsrf %1\n%O2:%#" + [(set_attr "type" "sfunc") + (set_attr "needs_delay_slot" "yes")]) + +@@ -5532,8 +5557,8 @@ (define_expand "lshrsi3" + { + emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]); + rtx funcaddr = gen_reg_rtx (Pmode); +- function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC); +- emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr)); ++ rtx lab = function_symbol (funcaddr, "__lshrsi3_r0", SFUNC_STATIC).lab; ++ emit_insn (gen_lshrsi3_d_call (operands[0], operands[2], funcaddr, lab)); + DONE; + } + }) +@@ -5585,15 +5610,18 @@ (define_insn_and_split "lshrsi3_d" + ;; In order to make combine understand the truncation of the shift amount + ;; operand we have to allow it to use pseudo regs for the shift operands. + (define_insn "lshrsi3_d_call" +- [(set (match_operand:SI 0 "arith_reg_dest" "=z") ++ [(set (match_operand:SI 0 "arith_reg_dest" "=z,z") + (lshiftrt:SI (reg:SI R4_REG) +- (and:SI (match_operand:SI 1 "arith_reg_operand" "z") ++ (and:SI (match_operand:SI 1 "arith_reg_operand" "z,z") + (const_int 31)))) +- (use (match_operand:SI 2 "arith_reg_operand" "r")) ++ (use (match_operand:SI 2 "arith_reg_operand" "r,r")) ++ (use (match_operand 3 "" "Z,Ccl")) + (clobber (reg:SI T_REG)) + (clobber (reg:SI PR_REG))] + "TARGET_SH1 && !TARGET_DYNSHIFT" +- "jsr @%2%#" ++ "@ ++ jsr @%2%# ++ bsrf %2\n%O3:%#" + [(set_attr "type" "sfunc") + (set_attr "needs_delay_slot" "yes")]) + +@@ -7315,7 +7343,7 @@ (define_expand "ic_invalidate_line" + } + else if (TARGET_SHCOMPACT) + { +- operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC); ++ operands[1] = function_symbol (NULL, "__ic_invalidate", SFUNC_STATIC).sym; + operands[1] = force_reg (Pmode, operands[1]); + emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1])); + DONE; +@@ -7397,7 +7425,7 @@ (define_expand "initialize_trampoline" + + tramp = force_reg (Pmode, operands[0]); + sfun = force_reg (Pmode, function_symbol (NULL, "__init_trampoline", +- SFUNC_STATIC)); ++ SFUNC_STATIC).sym); + emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]); + emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]); + +@@ -9459,9 +9487,29 @@ (define_insn "calli" + (match_operand 1 "" "")) + (use (reg:SI FPSCR_MODES_REG)) + (clobber (reg:SI PR_REG))] +- "TARGET_SH1" ++ "TARGET_SH1 && !TARGET_FDPIC" + { +- if (TARGET_SH2A && (dbr_sequence_length () == 0)) ++ if (TARGET_SH2A && dbr_sequence_length () == 0) ++ return "jsr/n @%0"; ++ else ++ return "jsr @%0%#"; ++} ++ [(set_attr "type" "call") ++ (set (attr "fp_mode") ++ (if_then_else (eq_attr "fpu_single" "yes") ++ (const_string "single") (const_string "double"))) ++ (set_attr "needs_delay_slot" "yes") ++ (set_attr "fp_set" "unknown")]) ++ ++(define_insn "calli_fdpic" ++ [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) ++ (match_operand 1)) ++ (use (reg:SI FPSCR_MODES_REG)) ++ (use (reg:SI PIC_REG)) ++ (clobber (reg:SI PR_REG))] ++ "TARGET_FDPIC" ++{ ++ if (TARGET_SH2A && dbr_sequence_length () == 0) + return "jsr/n @%0"; + else + return "jsr @%0%#"; +@@ -9588,9 +9636,30 @@ (define_insn "call_valuei" + (match_operand 2 "" ""))) + (use (reg:SI FPSCR_MODES_REG)) + (clobber (reg:SI PR_REG))] +- "TARGET_SH1" ++ "TARGET_SH1 && !TARGET_FDPIC" ++{ ++ if (TARGET_SH2A && dbr_sequence_length () == 0) ++ return "jsr/n @%1"; ++ else ++ return "jsr @%1%#"; ++} ++ [(set_attr "type" "call") ++ (set (attr "fp_mode") ++ (if_then_else (eq_attr "fpu_single" "yes") ++ (const_string "single") (const_string "double"))) ++ (set_attr "needs_delay_slot" "yes") ++ (set_attr "fp_set" "unknown")]) ++ ++(define_insn "call_valuei_fdpic" ++ [(set (match_operand 0 "" "=rf") ++ (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) ++ (match_operand 2))) ++ (use (reg:SI FPSCR_REG)) ++ (use (reg:SI PIC_REG)) ++ (clobber (reg:SI PR_REG))] ++ "TARGET_FDPIC" + { +- if (TARGET_SH2A && (dbr_sequence_length () == 0)) ++ if (TARGET_SH2A && dbr_sequence_length () == 0) + return "jsr/n @%1"; + else + return "jsr @%1%#"; +@@ -9725,6 +9794,12 @@ (define_expand "call" + (clobber (reg:SI PR_REG))])] + "" + { ++ if (TARGET_FDPIC) ++ { ++ rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG); ++ emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ()); ++ } ++ + if (TARGET_SHMEDIA) + { + operands[0] = shmedia_prepare_call_address (operands[0], 0); +@@ -9759,8 +9834,8 @@ (define_expand "call" + run out of registers when adjusting fpscr for the call. */ + emit_insn (gen_force_mode_for_call ()); + +- operands[0] +- = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT); ++ operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", ++ SFUNC_GOT).sym; + operands[0] = force_reg (SImode, operands[0]); + + emit_move_insn (r0, func); +@@ -9808,7 +9883,13 @@ (define_expand "call" + operands[1] = operands[2]; + } + +- emit_call_insn (gen_calli (operands[0], operands[1])); ++ if (TARGET_FDPIC) ++ { ++ operands[0] = sh_load_function_descriptor (operands[0]); ++ emit_call_insn (gen_calli_fdpic (operands[0], operands[1])); ++ } ++ else ++ emit_call_insn (gen_calli (operands[0], operands[1])); + DONE; + }) + +@@ -9888,7 +9969,7 @@ (define_expand "call_pop" + emit_insn (gen_force_mode_for_call ()); + + operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", +- SFUNC_GOT); ++ SFUNC_GOT).sym; + operands[0] = force_reg (SImode, operands[0]); + + emit_move_insn (r0, func); +@@ -9913,6 +9994,12 @@ (define_expand "call_value" + (clobber (reg:SI PR_REG))])] + "" + { ++ if (TARGET_FDPIC) ++ { ++ rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG); ++ emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ()); ++ } ++ + if (TARGET_SHMEDIA) + { + operands[1] = shmedia_prepare_call_address (operands[1], 0); +@@ -9948,8 +10035,8 @@ (define_expand "call_value" + run out of registers when adjusting fpscr for the call. */ + emit_insn (gen_force_mode_for_call ()); + +- operands[1] +- = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT); ++ operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", ++ SFUNC_GOT).sym; + operands[1] = force_reg (SImode, operands[1]); + + emit_move_insn (r0, func); +@@ -9997,7 +10084,14 @@ (define_expand "call_value" + else + operands[1] = force_reg (SImode, XEXP (operands[1], 0)); + +- emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2])); ++ if (TARGET_FDPIC) ++ { ++ operands[1] = sh_load_function_descriptor (operands[1]); ++ emit_call_insn (gen_call_valuei_fdpic (operands[0], operands[1], ++ operands[2])); ++ } ++ else ++ emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2])); + DONE; + }) + +@@ -10006,7 +10100,21 @@ (define_insn "sibcalli" + (match_operand 1 "" "")) + (use (reg:SI FPSCR_MODES_REG)) + (return)] +- "TARGET_SH1" ++ "TARGET_SH1 && !TARGET_FDPIC" ++ "jmp @%0%#" ++ [(set_attr "needs_delay_slot" "yes") ++ (set (attr "fp_mode") ++ (if_then_else (eq_attr "fpu_single" "yes") ++ (const_string "single") (const_string "double"))) ++ (set_attr "type" "jump_ind")]) ++ ++(define_insn "sibcalli_fdpic" ++ [(call (mem:SI (match_operand:SI 0 "register_operand" "k")) ++ (match_operand 1)) ++ (use (reg:SI FPSCR_MODES_REG)) ++ (use (reg:SI PIC_REG)) ++ (return)] ++ "TARGET_FDPIC" + "jmp @%0%#" + [(set_attr "needs_delay_slot" "yes") + (set (attr "fp_mode") +@@ -10020,7 +10128,25 @@ (define_insn "sibcalli_pcrel" + (use (match_operand 2 "" "")) + (use (reg:SI FPSCR_MODES_REG)) + (return)] +- "TARGET_SH2" ++ "TARGET_SH2 && !TARGET_FDPIC" ++{ ++ return "braf %0" "\n" ++ "%O2:%#"; ++} ++ [(set_attr "needs_delay_slot" "yes") ++ (set (attr "fp_mode") ++ (if_then_else (eq_attr "fpu_single" "yes") ++ (const_string "single") (const_string "double"))) ++ (set_attr "type" "jump_ind")]) ++ ++(define_insn "sibcalli_pcrel_fdpic" ++ [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "k")) ++ (match_operand 1)) ++ (use (match_operand 2)) ++ (use (reg:SI FPSCR_MODES_REG)) ++ (use (reg:SI PIC_REG)) ++ (return)] ++ "TARGET_SH2 && TARGET_FDPIC" + { + return "braf %0" "\n" + "%O2:%#"; +@@ -10053,7 +10179,7 @@ (define_insn_and_split "sibcall_pcrel" + (use (reg:SI FPSCR_MODES_REG)) + (clobber (match_scratch:SI 2 "=&k")) + (return)] +- "TARGET_SH2" ++ "TARGET_SH2 && !TARGET_FDPIC" + "#" + "reload_completed" + [(const_int 0)] +@@ -10073,6 +10199,32 @@ (define_insn_and_split "sibcall_pcrel" + (const_string "single") (const_string "double"))) + (set_attr "type" "jump_ind")]) + ++(define_insn_and_split "sibcall_pcrel_fdpic" ++ [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand")) ++ (match_operand 1)) ++ (use (reg:SI FPSCR_MODES_REG)) ++ (use (reg:SI PIC_REG)) ++ (clobber (match_scratch:SI 2 "=k")) ++ (return)] ++ "TARGET_SH2 && TARGET_FDPIC" ++ "#" ++ "&& reload_completed" ++ [(const_int 0)] ++{ ++ rtx lab = PATTERN (gen_call_site ()); ++ ++ sh_expand_sym_label2reg (operands[2], operands[0], lab, true); ++ rtx i = emit_call_insn (gen_sibcalli_pcrel_fdpic (operands[2], operands[1], ++ copy_rtx (lab))); ++ SIBLING_CALL_P (i) = 1; ++ DONE; ++} ++ [(set_attr "needs_delay_slot" "yes") ++ (set (attr "fp_mode") ++ (if_then_else (eq_attr "fpu_single" "yes") ++ (const_string "single") (const_string "double"))) ++ (set_attr "type" "jump_ind")]) ++ + (define_insn "sibcall_compact" + [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k")) + (match_operand 1 "" "")) +@@ -10117,6 +10269,12 @@ (define_expand "sibcall" + (return)])] + "" + { ++ if (TARGET_FDPIC) ++ { ++ rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG); ++ emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ()); ++ } ++ + if (TARGET_SHMEDIA) + { + operands[0] = shmedia_prepare_call_address (operands[0], 1); +@@ -10161,8 +10319,8 @@ (define_expand "sibcall" + run out of registers when adjusting fpscr for the call. */ + emit_insn (gen_force_mode_for_call ()); + +- operands[0] +- = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT); ++ operands[0] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", ++ SFUNC_GOT).sym; + operands[0] = force_reg (SImode, operands[0]); + + /* We don't need a return trampoline, since the callee will +@@ -10196,13 +10354,23 @@ (define_expand "sibcall" + static functions. */ + && SYMBOL_REF_LOCAL_P (XEXP (operands[0], 0))) + { +- emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1])); ++ if (TARGET_FDPIC) ++ emit_call_insn (gen_sibcall_pcrel_fdpic (XEXP (operands[0], 0), ++ operands[1])); ++ else ++ emit_call_insn (gen_sibcall_pcrel (XEXP (operands[0], 0), operands[1])); + DONE; + } + else + operands[0] = force_reg (SImode, XEXP (operands[0], 0)); + +- emit_call_insn (gen_sibcalli (operands[0], operands[1])); ++ if (TARGET_FDPIC) ++ { ++ operands[0] = sh_load_function_descriptor (operands[0]); ++ emit_call_insn (gen_sibcalli_fdpic (operands[0], operands[1])); ++ } ++ else ++ emit_call_insn (gen_sibcalli (operands[0], operands[1])); + DONE; + }) + +@@ -10212,7 +10380,22 @@ (define_insn "sibcall_valuei" + (match_operand 2 "" ""))) + (use (reg:SI FPSCR_MODES_REG)) + (return)] +- "TARGET_SH1" ++ "TARGET_SH1 && !TARGET_FDPIC" ++ "jmp @%1%#" ++ [(set_attr "needs_delay_slot" "yes") ++ (set (attr "fp_mode") ++ (if_then_else (eq_attr "fpu_single" "yes") ++ (const_string "single") (const_string "double"))) ++ (set_attr "type" "jump_ind")]) ++ ++(define_insn "sibcall_valuei_fdpic" ++ [(set (match_operand 0 "" "=rf") ++ (call (mem:SI (match_operand:SI 1 "register_operand" "k")) ++ (match_operand 2))) ++ (use (reg:SI FPSCR_MODES_REG)) ++ (use (reg:SI PIC_REG)) ++ (return)] ++ "TARGET_FDPIC" + "jmp @%1%#" + [(set_attr "needs_delay_slot" "yes") + (set (attr "fp_mode") +@@ -10227,7 +10410,26 @@ (define_insn "sibcall_valuei_pcrel" + (use (match_operand 3 "" "")) + (use (reg:SI FPSCR_MODES_REG)) + (return)] +- "TARGET_SH2" ++ "TARGET_SH2 && !TARGET_FDPIC" ++{ ++ return "braf %1" "\n" ++ "%O3:%#"; ++} ++ [(set_attr "needs_delay_slot" "yes") ++ (set (attr "fp_mode") ++ (if_then_else (eq_attr "fpu_single" "yes") ++ (const_string "single") (const_string "double"))) ++ (set_attr "type" "jump_ind")]) ++ ++(define_insn "sibcall_valuei_pcrel_fdpic" ++ [(set (match_operand 0 "" "=rf") ++ (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "k")) ++ (match_operand 2))) ++ (use (match_operand 3)) ++ (use (reg:SI FPSCR_MODES_REG)) ++ (use (reg:SI PIC_REG)) ++ (return)] ++ "TARGET_SH2 && TARGET_FDPIC" + { + return "braf %1" "\n" + "%O3:%#"; +@@ -10245,7 +10447,7 @@ (define_insn_and_split "sibcall_value_pcrel" + (use (reg:SI FPSCR_MODES_REG)) + (clobber (match_scratch:SI 3 "=&k")) + (return)] +- "TARGET_SH2" ++ "TARGET_SH2 && !TARGET_FDPIC" + "#" + "reload_completed" + [(const_int 0)] +@@ -10267,6 +10469,35 @@ (define_insn_and_split "sibcall_value_pcrel" + (const_string "single") (const_string "double"))) + (set_attr "type" "jump_ind")]) + ++(define_insn_and_split "sibcall_value_pcrel_fdpic" ++ [(set (match_operand 0 "" "=rf") ++ (call (mem:SI (match_operand:SI 1 "symbol_ref_operand")) ++ (match_operand 2))) ++ (use (reg:SI FPSCR_MODES_REG)) ++ (use (reg:SI PIC_REG)) ++ (clobber (match_scratch:SI 3 "=k")) ++ (return)] ++ "TARGET_SH2 && TARGET_FDPIC" ++ "#" ++ "&& reload_completed" ++ [(const_int 0)] ++{ ++ rtx lab = PATTERN (gen_call_site ()); ++ ++ sh_expand_sym_label2reg (operands[3], operands[1], lab, true); ++ rtx i = emit_call_insn (gen_sibcall_valuei_pcrel_fdpic (operands[0], ++ operands[3], ++ operands[2], ++ copy_rtx (lab))); ++ SIBLING_CALL_P (i) = 1; ++ DONE; ++} ++ [(set_attr "needs_delay_slot" "yes") ++ (set (attr "fp_mode") ++ (if_then_else (eq_attr "fpu_single" "yes") ++ (const_string "single") (const_string "double"))) ++ (set_attr "type" "jump_ind")]) ++ + (define_insn "sibcall_value_compact" + [(set (match_operand 0 "" "=rf,rf") + (call (mem:SI (match_operand:SI 1 "register_operand" "k,k")) +@@ -10314,6 +10545,12 @@ (define_expand "sibcall_value" + (return)])] + "" + { ++ if (TARGET_FDPIC) ++ { ++ rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG); ++ emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ()); ++ } ++ + if (TARGET_SHMEDIA) + { + operands[1] = shmedia_prepare_call_address (operands[1], 1); +@@ -10359,8 +10596,8 @@ (define_expand "sibcall_value" + run out of registers when adjusting fpscr for the call. */ + emit_insn (gen_force_mode_for_call ()); + +- operands[1] +- = function_symbol (NULL, "__GCC_shcompact_call_trampoline", SFUNC_GOT); ++ operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", ++ SFUNC_GOT).sym; + operands[1] = force_reg (SImode, operands[1]); + + /* We don't need a return trampoline, since the callee will +@@ -10395,15 +10632,27 @@ (define_expand "sibcall_value" + static functions. */ + && SYMBOL_REF_LOCAL_P (XEXP (operands[1], 0))) + { +- emit_call_insn (gen_sibcall_value_pcrel (operands[0], +- XEXP (operands[1], 0), +- operands[2])); ++ if (TARGET_FDPIC) ++ emit_call_insn (gen_sibcall_value_pcrel_fdpic (operands[0], ++ XEXP (operands[1], 0), ++ operands[2])); ++ else ++ emit_call_insn (gen_sibcall_value_pcrel (operands[0], ++ XEXP (operands[1], 0), ++ operands[2])); + DONE; + } + else + operands[1] = force_reg (SImode, XEXP (operands[1], 0)); + +- emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2])); ++ if (TARGET_FDPIC) ++ { ++ operands[1] = sh_load_function_descriptor (operands[1]); ++ emit_call_insn (gen_sibcall_valuei_fdpic (operands[0], operands[1], ++ operands[2])); ++ } ++ else ++ emit_call_insn (gen_sibcall_valuei (operands[0], operands[1], operands[2])); + DONE; + }) + +@@ -10487,7 +10736,7 @@ (define_expand "call_value_pop" + emit_insn (gen_force_mode_for_call ()); + + operands[1] = function_symbol (NULL, "__GCC_shcompact_call_trampoline", +- SFUNC_GOT); ++ SFUNC_GOT).sym; + operands[1] = force_reg (SImode, operands[1]); + + emit_move_insn (r0, func); +@@ -10685,6 +10934,13 @@ (define_expand "GOTaddr2picreg" + DONE; + } + ++ if (TARGET_FDPIC) ++ { ++ rtx pic_reg = gen_rtx_REG (Pmode, PIC_REG); ++ emit_move_insn (pic_reg, sh_get_fdpic_reg_initial_val ()); ++ DONE; ++ } ++ + operands[1] = gen_rtx_REG (Pmode, PIC_REG); + operands[2] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME); + +@@ -10820,10 +11076,13 @@ (define_expand "symGOT_load" + rtx mem; + bool stack_chk_guard_p = false; + ++ rtx picreg = TARGET_FDPIC ? sh_get_fdpic_reg_initial_val () ++ : gen_rtx_REG (Pmode, PIC_REG); ++ + operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode); + operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode); + +- if (!TARGET_SHMEDIA ++ if (!TARGET_SHMEDIA && !TARGET_FDPIC + && flag_stack_protect + && GET_CODE (operands[1]) == CONST + && GET_CODE (XEXP (operands[1], 0)) == UNSPEC +@@ -10862,8 +11121,7 @@ (define_expand "symGOT_load" + if (stack_chk_guard_p) + emit_insn (gen_chk_guard_add (operands[3], operands[2])); + else +- emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2], +- gen_rtx_REG (Pmode, PIC_REG))); ++ emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2], picreg)); + + /* N.B. This is not constant for a GOTPLT relocation. */ + mem = gen_rtx_MEM (Pmode, operands[3]); +@@ -10894,6 +11152,23 @@ (define_expand "symGOT2reg" + DONE; + }) + ++(define_expand "sym2GOTFUNCDESC" ++ [(const (unspec [(match_operand 0)] UNSPEC_GOTFUNCDESC))] ++ "TARGET_FDPIC") ++ ++(define_expand "symGOTFUNCDESC2reg" ++ [(match_operand 0) (match_operand 1)] ++ "TARGET_FDPIC" ++{ ++ rtx gotsym = gen_sym2GOTFUNCDESC (operands[1]); ++ PUT_MODE (gotsym, Pmode); ++ rtx insn = emit_insn (gen_symGOT_load (operands[0], gotsym)); ++ ++ MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1; ++ ++ DONE; ++}) ++ + (define_expand "symGOTPLT2reg" + [(match_operand 0 "" "") (match_operand 1 "" "")] + "" +@@ -10920,18 +11195,39 @@ (define_expand "symGOTOFF2reg" + ? operands[0] + : gen_reg_rtx (GET_MODE (operands[0]))); + ++ rtx picreg = TARGET_FDPIC ? sh_get_fdpic_reg_initial_val () ++ : gen_rtx_REG (Pmode, PIC_REG); ++ + gotoffsym = gen_sym2GOTOFF (operands[1]); + PUT_MODE (gotoffsym, Pmode); + emit_move_insn (t, gotoffsym); +- insn = emit_move_insn (operands[0], +- gen_rtx_PLUS (Pmode, t, +- gen_rtx_REG (Pmode, PIC_REG))); ++ insn = emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, picreg)); + + set_unique_reg_note (insn, REG_EQUAL, operands[1]); + + DONE; + }) + ++(define_expand "sym2GOTOFFFUNCDESC" ++ [(const (unspec [(match_operand 0)] UNSPEC_GOTOFFFUNCDESC))] ++ "TARGET_FDPIC") ++ ++(define_expand "symGOTOFFFUNCDESC2reg" ++ [(match_operand 0) (match_operand 1)] ++ "TARGET_FDPIC" ++{ ++ rtx picreg = sh_get_fdpic_reg_initial_val (); ++ rtx t = !can_create_pseudo_p () ++ ? operands[0] ++ : gen_reg_rtx (GET_MODE (operands[0])); ++ ++ rtx gotoffsym = gen_sym2GOTOFFFUNCDESC (operands[1]); ++ PUT_MODE (gotoffsym, Pmode); ++ emit_move_insn (t, gotoffsym); ++ emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, picreg)); ++ DONE; ++}) ++ + (define_expand "symPLT_label2reg" + [(set (match_operand:SI 0 "" "") + (const:SI +@@ -12688,18 +12984,22 @@ (define_expand "movmemsi" + (define_insn "block_move_real" + [(parallel [(set (mem:BLK (reg:SI R4_REG)) + (mem:BLK (reg:SI R5_REG))) +- (use (match_operand:SI 0 "arith_reg_operand" "r")) ++ (use (match_operand:SI 0 "arith_reg_operand" "r,r")) ++ (use (match_operand 1 "" "Z,Ccl")) + (clobber (reg:SI PR_REG)) + (clobber (reg:SI R0_REG))])] + "TARGET_SH1 && ! TARGET_HARD_SH4" +- "jsr @%0%#" ++ "@ ++ jsr @%0%# ++ bsrf %0\n%O1:%#" + [(set_attr "type" "sfunc") + (set_attr "needs_delay_slot" "yes")]) + + (define_insn "block_lump_real" + [(parallel [(set (mem:BLK (reg:SI R4_REG)) + (mem:BLK (reg:SI R5_REG))) +- (use (match_operand:SI 0 "arith_reg_operand" "r")) ++ (use (match_operand:SI 0 "arith_reg_operand" "r,r")) ++ (use (match_operand 1 "" "Z,Ccl")) + (use (reg:SI R6_REG)) + (clobber (reg:SI PR_REG)) + (clobber (reg:SI T_REG)) +@@ -12708,27 +13008,33 @@ (define_insn "block_lump_real" + (clobber (reg:SI R6_REG)) + (clobber (reg:SI R0_REG))])] + "TARGET_SH1 && ! TARGET_HARD_SH4" +- "jsr @%0%#" ++ "@ ++ jsr @%0%# ++ bsrf %0\n%O1:%#" + [(set_attr "type" "sfunc") + (set_attr "needs_delay_slot" "yes")]) + + (define_insn "block_move_real_i4" + [(parallel [(set (mem:BLK (reg:SI R4_REG)) + (mem:BLK (reg:SI R5_REG))) +- (use (match_operand:SI 0 "arith_reg_operand" "r")) ++ (use (match_operand:SI 0 "arith_reg_operand" "r,r")) ++ (use (match_operand 1 "" "Z,Ccl")) + (clobber (reg:SI PR_REG)) + (clobber (reg:SI R0_REG)) + (clobber (reg:SI R1_REG)) + (clobber (reg:SI R2_REG))])] + "TARGET_HARD_SH4" +- "jsr @%0%#" ++ "@ ++ jsr @%0%# ++ bsrf %0\n%O1:%#" + [(set_attr "type" "sfunc") + (set_attr "needs_delay_slot" "yes")]) + + (define_insn "block_lump_real_i4" + [(parallel [(set (mem:BLK (reg:SI R4_REG)) + (mem:BLK (reg:SI R5_REG))) +- (use (match_operand:SI 0 "arith_reg_operand" "r")) ++ (use (match_operand:SI 0 "arith_reg_operand" "r,r")) ++ (use (match_operand 1 "" "Z,Ccl")) + (use (reg:SI R6_REG)) + (clobber (reg:SI PR_REG)) + (clobber (reg:SI T_REG)) +@@ -12740,7 +13046,9 @@ (define_insn "block_lump_real_i4" + (clobber (reg:SI R2_REG)) + (clobber (reg:SI R3_REG))])] + "TARGET_HARD_SH4" +- "jsr @%0%#" ++ "@ ++ jsr @%0%# ++ bsrf %0\n%O1:%#" + [(set_attr "type" "sfunc") + (set_attr "needs_delay_slot" "yes")]) + +diff --git a/gcc/config/sh/sh.opt b/gcc/config/sh/sh.opt +index 8875b5d..c2e8aca 100644 +--- a/gcc/config/sh/sh.opt ++++ b/gcc/config/sh/sh.opt +@@ -264,6 +264,10 @@ mdivsi3_libfunc= + Target RejectNegative Joined Var(sh_divsi3_libfunc) Init("") + Specify name for 32 bit signed division function + ++mfdpic ++Target Report Var(TARGET_FDPIC) Init(0) ++Generate ELF FDPIC code ++ + mfmovd + Target RejectNegative Mask(FMOVD) + Enable the use of 64-bit floating point registers in fmov instructions. See -mdalign if 64-bit alignment is required. +diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi +index 1fd773e..fe57b97 100644 +--- a/gcc/doc/install.texi ++++ b/gcc/doc/install.texi +@@ -1810,6 +1810,9 @@ When neither of these configure options are used, the default will be + 128-bit @code{long double} when built against GNU C Library 2.4 and later, + 64-bit @code{long double} otherwise. + ++@item --enable-fdpic ++On SH Linux systems, generate ELF FDPIC code. ++ + @item --with-gmp=@var{pathname} + @itemx --with-gmp-include=@var{pathname} + @itemx --with-gmp-lib=@var{pathname} +diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi +index ebfaaa1..8b26eac 100644 +--- a/gcc/doc/invoke.texi ++++ b/gcc/doc/invoke.texi +@@ -21178,6 +21178,10 @@ in effect. + Prefer zero-displacement conditional branches for conditional move instruction + patterns. This can result in faster code on the SH4 processor. + ++@item -mfdpic ++@opindex fdpic ++Generate code using the FDPIC ABI. ++ + @end table + + @node Solaris 2 Options +diff --git a/include/longlong.h b/include/longlong.h +index a0b2ce1..d7ef671 100644 +--- a/include/longlong.h ++++ b/include/longlong.h +@@ -1102,6 +1102,33 @@ extern UDItype __umulsidi3 (USItype, USItype); + /* This is the same algorithm as __udiv_qrnnd_c. */ + #define UDIV_NEEDS_NORMALIZATION 1 + ++#ifdef __FDPIC__ ++/* FDPIC needs a special version of the asm fragment to extract the ++ code address from the function descriptor. __udiv_qrnnd_16 is ++ assumed to be local and not to use the GOT, so loading r12 is ++ not needed. */ ++#define udiv_qrnnd(q, r, n1, n0, d) \ ++ do { \ ++ extern UWtype __udiv_qrnnd_16 (UWtype, UWtype) \ ++ __attribute__ ((visibility ("hidden"))); \ ++ /* r0: rn r1: qn */ /* r0: n1 r4: n0 r5: d r6: d1 */ /* r2: __m */ \ ++ __asm__ ( \ ++ "mov%M4 %4,r5\n" \ ++" swap.w %3,r4\n" \ ++" swap.w r5,r6\n" \ ++" mov.l @%5,r2\n" \ ++" jsr @r2\n" \ ++" shll16 r6\n" \ ++" swap.w r4,r4\n" \ ++" mov.l @%5,r2\n" \ ++" jsr @r2\n" \ ++" swap.w r1,%0\n" \ ++" or r1,%0" \ ++ : "=r" (q), "=&z" (r) \ ++ : "1" (n1), "r" (n0), "rm" (d), "r" (&__udiv_qrnnd_16) \ ++ : "r1", "r2", "r4", "r5", "r6", "pr", "t"); \ ++ } while (0) ++#else + #define udiv_qrnnd(q, r, n1, n0, d) \ + do { \ + extern UWtype __udiv_qrnnd_16 (UWtype, UWtype) \ +@@ -1121,6 +1148,7 @@ extern UDItype __umulsidi3 (USItype, USItype); + : "1" (n1), "r" (n0), "rm" (d), "r" (&__udiv_qrnnd_16) \ + : "r1", "r2", "r4", "r5", "r6", "pr", "t"); \ + } while (0) ++#endif /* __FDPIC__ */ + + #define UDIV_TIME 80 + +diff --git a/libitm/config/sh/sjlj.S b/libitm/config/sh/sjlj.S +index 410cef6..8c83fce 100644 +--- a/libitm/config/sh/sjlj.S ++++ b/libitm/config/sh/sjlj.S +@@ -58,9 +58,6 @@ _ITM_beginTransaction: + jsr @r1 + mov r15, r5 + #else +- mova .Lgot, r0 +- mov.l .Lgot, r12 +- add r0, r12 + mov.l .Lbegin, r1 + bsrf r1 + mov r15, r5 +@@ -79,14 +76,12 @@ _ITM_beginTransaction: + nop + cfi_endproc + +- .align 2 +-.Lgot: +- .long _GLOBAL_OFFSET_TABLE_ ++ .align 2 + .Lbegin: + #if defined HAVE_ATTRIBUTE_VISIBILITY || !defined __PIC__ + .long GTM_begin_transaction + #else +- .long GTM_begin_transaction@PLT-(.Lbegin0-.) ++ .long GTM_begin_transaction@PCREL-(.Lbegin0-.) + #endif + .size _ITM_beginTransaction, . - _ITM_beginTransaction + diff --git a/patches/gcc-5.3.0/0008-shsibcall.diff b/patches/gcc-5.3.0/0008-shsibcall.diff new file mode 100644 index 0000000..48a165f --- /dev/null +++ b/patches/gcc-5.3.0/0008-shsibcall.diff @@ -0,0 +1,39 @@ +--- a/gcc/config/sh/sh.md (revision 233324) ++++ b/gcc/config/sh/sh.md (working copy) +@@ -10476,7 +10476,7 @@ + (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "")) + (match_operand 2 "" ""))) + (use (reg:SI FPSCR_MODES_REG)) +- (clobber (match_scratch:SI 3 "=&k")) ++ (clobber (reg:SI R1_REG)) + (return)] + "TARGET_SH2 && !TARGET_FDPIC" + "#" +@@ -10491,6 +10495,8 @@ + rtx lab = PATTERN (gen_call_site ()); + rtx call_insn; + ++ operands[3] = gen_rtx_REG (SImode, R1_REG); ++ + sh_expand_sym_label2reg (operands[3], operands[1], lab, true); + call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0], + operands[3], +@@ -10511,7 +10519,7 @@ + (match_operand 2))) + (use (reg:SI FPSCR_MODES_REG)) + (use (reg:SI PIC_REG)) +- (clobber (match_scratch:SI 3 "=k")) ++ (clobber (reg:SI R1_REG)) + (return)] + "TARGET_SH2 && TARGET_FDPIC" + "#" +@@ -10520,6 +10528,8 @@ + { + rtx lab = PATTERN (gen_call_site ()); + ++ operands[3] = gen_rtx_REG (SImode, R1_REG); ++ + sh_expand_sym_label2reg (operands[3], operands[1], lab, true); + rtx i = emit_call_insn (gen_sibcall_valuei_pcrel_fdpic (operands[0], + operands[3], + diff --git a/patches/gcc-5.3.0/0009-mipsdw.diff b/patches/gcc-5.3.0/0009-mipsdw.diff new file mode 100644 index 0000000..de1144a --- /dev/null +++ b/patches/gcc-5.3.0/0009-mipsdw.diff @@ -0,0 +1,11 @@ +--- a/libgcc/config/mips/linux-unwind.h 2016-04-07 23:08:58.088577977 +0000 ++++ b/libgcc/config/mips/linux-unwind.h 2016-04-07 23:04:34.016523639 +0000 +@@ -27,7 +27,7 @@ + state data appropriately. See unwind-dw2.c for the structs. */ + + #include +-#include ++#include + + /* The third parameter to the signal handler points to something with + * this structure defined in asm/ucontext.h, but the name clashes with