diff options
Diffstat (limited to 'gcc/config')
45 files changed, 779 insertions, 376 deletions
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 807aa4c62a8..e0a7d695973 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -3149,7 +3149,7 @@ static rtx alpha_emit_xfloating_compare (enum rtx_code *pcode, rtx op0, rtx op1) { enum rtx_code cmp_code, res_code; - rtx func, out, operands[2]; + rtx func, out, operands[2], note; /* X_floating library comparison functions return -1 unordered @@ -3189,10 +3189,13 @@ alpha_emit_xfloating_compare (enum rtx_code *pcode, rtx op0, rtx op1) operands[1] = op1; out = gen_reg_rtx (DImode); - /* ??? Strange mode for equiv because what's actually returned - is -1,0,1, not a proper boolean value. */ - alpha_emit_xfloating_libcall (func, out, operands, 2, - gen_rtx_fmt_ee (cmp_code, CCmode, op0, op1)); + /* What's actually returned is -1,0,1, not a proper boolean value, + so use an EXPR_LIST as with a generic libcall instead of a + comparison type expression. */ + note = gen_rtx_EXPR_LIST (VOIDmode, op1, NULL_RTX); + note = gen_rtx_EXPR_LIST (VOIDmode, op0, note); + note = gen_rtx_EXPR_LIST (VOIDmode, func, note); + alpha_emit_xfloating_libcall (func, out, operands, 2, note); return out; } diff --git a/gcc/config/arm/rtems-elf.h b/gcc/config/arm/rtems-elf.h index ca14a5b43aa..ebeeed36a90 100644 --- a/gcc/config/arm/rtems-elf.h +++ b/gcc/config/arm/rtems-elf.h @@ -26,6 +26,7 @@ #define TARGET_OS_CPP_BUILTINS() \ do { \ builtin_define ("__rtems__"); \ + builtin_define ("__USE_INIT_FINI__"); \ builtin_assert ("system=rtems"); \ } while (0) diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 9be1d0ac362..02acb22c5aa 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -143,6 +143,7 @@ static const struct base_arch_s avr_arch_types[] = { { 0, 0, 0, 0, "__AVR_ARCH__=2" }, { 0, 0, 0, 1, "__AVR_ARCH__=25"}, { 0, 0, 1, 0, "__AVR_ARCH__=3" }, + { 0, 0, 1, 1, "__AVR_ARCH__=35"}, { 0, 1, 0, 1, "__AVR_ARCH__=4" }, { 0, 1, 1, 1, "__AVR_ARCH__=5" } }; @@ -157,6 +158,7 @@ enum avr_arch ARCH_AVR2, ARCH_AVR25, ARCH_AVR3, + ARCH_AVR35, ARCH_AVR4, ARCH_AVR5 }; @@ -212,6 +214,10 @@ static const struct mcu_type_s avr_mcu_types[] = { { "at43usb320", ARCH_AVR3, "__AVR_AT43USB320__" }, { "at43usb355", ARCH_AVR3, "__AVR_AT43USB355__" }, { "at76c711", ARCH_AVR3, "__AVR_AT76C711__" }, + /* Classic + MOVW + JMP/CALL. */ + { "avr35", ARCH_AVR35, NULL }, + { "at90usb82", ARCH_AVR35, "__AVR_AT90USB82__" }, + { "at90usb162", ARCH_AVR35, "__AVR_AT90USB162__" }, /* Enhanced, <= 8K. */ { "avr4", ARCH_AVR4, NULL }, { "atmega8", ARCH_AVR4, "__AVR_ATmega8__" }, @@ -262,8 +268,6 @@ static const struct mcu_type_s avr_mcu_types[] = { { "at90can32", ARCH_AVR5, "__AVR_AT90CAN32__" }, { "at90can64", ARCH_AVR5, "__AVR_AT90CAN64__" }, { "at90can128", ARCH_AVR5, "__AVR_AT90CAN128__" }, - { "at90usb82", ARCH_AVR5, "__AVR_AT90USB82__" }, - { "at90usb162", ARCH_AVR5, "__AVR_AT90USB162__" }, { "at90usb646", ARCH_AVR5, "__AVR_AT90USB646__" }, { "at90usb647", ARCH_AVR5, "__AVR_AT90USB647__" }, { "at90usb1286", ARCH_AVR5, "__AVR_AT90USB1286__" }, diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h index df5bf3e7d82..04b12963931 100644 --- a/gcc/config/avr/avr.h +++ b/gcc/config/avr/avr.h @@ -733,7 +733,7 @@ extern int avr_case_values_threshold; /* A C string constant that tells the GCC drvier program options to pass to `cc1plus'. */ -#define ASM_SPEC "%{mmcu=avr25:-mmcu=avr2;\ +#define ASM_SPEC "%{mmcu=avr25:-mmcu=avr2;mmcu=avr35:-mmcu=avr3;\ mmcu=*:-mmcu=%*}" #define LINK_SPEC " %{!mmcu*:-m avr2}\ @@ -759,7 +759,9 @@ mmcu=*:-mmcu=%*}" %{mmcu=atmega103|\ mmcu=atmega603|\ mmcu=at43*|\ - mmcu=at76*:-m avr3}\ + mmcu=at76*|\ + mmcu=at90usb82|\ + mmcu=at90usb162:-m avr3}\ %{mmcu=atmega8*|\ mmcu=atmega48|\ mmcu=at90pwm*:-m avr4}\ @@ -769,7 +771,8 @@ mmcu=*:-mmcu=%*}" mmcu=atmega64*|\ mmcu=atmega128*|\ mmcu=at90can*|\ - mmcu=at90usb*|\ + mmcu=at90usb64*|\ + mmcu=at90usb128*|\ mmcu=at94k:-m avr5}\ %{mmcu=atmega324*|\ mmcu=atmega325*|\ @@ -844,6 +847,8 @@ mmcu=*:-mmcu=%*}" %{mmcu=at43usb320:crt43320.o%s} \ %{mmcu=at43usb355:crt43355.o%s} \ %{mmcu=at76c711:crt76711.o%s} \ +%{mmcu=at90usb162|mmcu=avr35:crtusb162.o%s} \ +%{mmcu=at90usb82:crtusb82.o%s} \ %{mmcu=atmega8|mmcu=avr4:crtm8.o%s} \ %{mmcu=atmega48:crtm48.o%s} \ %{mmcu=atmega88:crtm88.o%s} \ @@ -890,8 +895,6 @@ mmcu=*:-mmcu=%*}" %{mmcu=at90can32:crtcan32.o%s} \ %{mmcu=at90can64:crtcan64.o%s} \ %{mmcu=at90can128:crtcan128.o%s} \ -%{mmcu=at90usb82:crtusb82.o%s} \ -%{mmcu=at90usb162:crtusb162.o%s} \ %{mmcu=at90usb646:crtusb646.o%s} \ %{mmcu=at90usb647:crtusb647.o%s} \ %{mmcu=at90usb1286:crtusb1286.o%s} \ diff --git a/gcc/config/avr/t-avr b/gcc/config/avr/t-avr index e582b6cf7d6..3ceed822ff5 100644 --- a/gcc/config/avr/t-avr +++ b/gcc/config/avr/t-avr @@ -37,8 +37,8 @@ fp-bit.c: $(srcdir)/config/fp-bit.c $(srcdir)/config/avr/t-avr FPBIT = fp-bit.c -MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr4/mmcu=avr5 -MULTILIB_DIRNAMES = avr2 avr25 avr3 avr4 avr5 +MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr35/mmcu=avr4/mmcu=avr5 +MULTILIB_DIRNAMES = avr2 avr25 avr3 avr35 avr4 avr5 # The many avr2 matches are not listed here - this is the default. MULTILIB_MATCHES = \ @@ -59,6 +59,8 @@ MULTILIB_MATCHES = \ mmcu?avr3=mmcu?at43usb320 \ mmcu?avr3=mmcu?at43usb355 \ mmcu?avr3=mmcu?at76c711 \ + mmcu?avr35=mmcu?at90usb82 \ + mmcu?avr35=mmcu?at90usb162 \ mmcu?avr4=mmcu?atmega48 \ mmcu?avr4=mmcu?atmega8 \ mmcu?avr4=mmcu?atmega8515 \ @@ -105,8 +107,6 @@ MULTILIB_MATCHES = \ mmcu?avr5=mmcu?at90can32 \ mmcu?avr5=mmcu?at90can64 \ mmcu?avr5=mmcu?at90can128 \ - mmcu?avr5=mmcu?at90usb82 \ - mmcu?avr5=mmcu?at90usb162 \ mmcu?avr5=mmcu?at90usb646 \ mmcu?avr5=mmcu?at90usb647 \ mmcu?avr5=mmcu?at90usb1286 \ diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c index c910ab83ced..3d01d3e4f66 100644 --- a/gcc/config/fr30/fr30.c +++ b/gcc/config/fr30/fr30.c @@ -827,47 +827,23 @@ fr30_move_double (rtx * operands) { rtx addr = XEXP (src, 0); int dregno = REGNO (dest); - rtx dest0; - rtx dest1; + rtx dest0 = operand_subword (dest, 0, TRUE, mode);; + rtx dest1 = operand_subword (dest, 1, TRUE, mode);; rtx new_mem; - /* If the high-address word is used in the address, we - must load it last. Otherwise, load it first. */ - int reverse = (refers_to_regno_p (dregno, dregno + 1, addr, 0) != 0); - gcc_assert (GET_CODE (addr) == REG); - dest0 = operand_subword (dest, reverse, TRUE, mode); - dest1 = operand_subword (dest, !reverse, TRUE, mode); - - if (reverse) - { - emit_insn (gen_rtx_SET (VOIDmode, dest1, - adjust_address (src, SImode, 0))); - emit_insn (gen_rtx_SET (SImode, dest0, - gen_rtx_REG (SImode, REGNO (addr)))); - emit_insn (gen_rtx_SET (SImode, dest0, - plus_constant (dest0, UNITS_PER_WORD))); - - new_mem = gen_rtx_MEM (SImode, dest0); - MEM_COPY_ATTRIBUTES (new_mem, src); - - emit_insn (gen_rtx_SET (VOIDmode, dest0, new_mem)); - } - else - { - emit_insn (gen_rtx_SET (VOIDmode, dest0, - adjust_address (src, SImode, 0))); - emit_insn (gen_rtx_SET (SImode, dest1, - gen_rtx_REG (SImode, REGNO (addr)))); - emit_insn (gen_rtx_SET (SImode, dest1, - plus_constant (dest1, UNITS_PER_WORD))); - - new_mem = gen_rtx_MEM (SImode, dest1); - MEM_COPY_ATTRIBUTES (new_mem, src); + /* Copy the address before clobbering it. See PR 34174. */ + emit_insn (gen_rtx_SET (SImode, dest1, addr)); + emit_insn (gen_rtx_SET (VOIDmode, dest0, + adjust_address (src, SImode, 0))); + emit_insn (gen_rtx_SET (SImode, dest1, + plus_constant (dest1, UNITS_PER_WORD))); + + new_mem = gen_rtx_MEM (SImode, dest1); + MEM_COPY_ATTRIBUTES (new_mem, src); - emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem)); - } + emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem)); } else if (src_code == CONST_INT || src_code == CONST_DOUBLE) { diff --git a/gcc/config/h8300/t-rtems b/gcc/config/h8300/t-rtems index 104ee2366f1..0d76437f8cf 100644 --- a/gcc/config/h8300/t-rtems +++ b/gcc/config/h8300/t-rtems @@ -2,6 +2,6 @@ # -mn is not applicable to RTEMS (-mn implies 16bit void*) -MULTILIB_OPTIONS = mh/ms mint32 -MULTILIB_DIRNAMES = h8300h h8300s int32 +MULTILIB_OPTIONS = mh/ms/msx mint32 +MULTILIB_DIRNAMES = h8300h h8300s h8sx int32 MULTILIB_EXCEPTIONS = mint32 diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c index aca450de26c..42ccea44ef9 100644 --- a/gcc/config/i386/driver-i386.c +++ b/gcc/config/i386/driver-i386.c @@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. If not see const char *host_detect_local_cpu (int argc, const char **argv); -#ifdef GCC_VERSION +#ifdef __GNUC__ #define cpuid(num,a,b,c,d) \ asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \ : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ @@ -296,4 +296,4 @@ const char *host_detect_local_cpu (int argc, const char **argv) return concat ("-m", argv[0], "=", cpu, NULL); } -#endif /* GCC_VERSION */ +#endif /* __GNUC__ */ diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 00b80863693..81765e53e57 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -17192,7 +17192,7 @@ ix86_rtx_costs (rtx x, int code, int outer_code, int *total) nbits = 7; /* Compute costs correctly for widening multiplication. */ - if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op1) == ZERO_EXTEND) + if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND) && GET_MODE_SIZE (GET_MODE (XEXP (op0, 0))) * 2 == GET_MODE_SIZE (mode)) { diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index eb1cf73bf87..8debac1174e 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -3715,7 +3715,8 @@ ; else { - rtx temp = assign_386_stack_local (SFmode, SLOT_VIRTUAL); + int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL; + rtx temp = assign_386_stack_local (SFmode, slot); emit_insn (gen_truncdfsf2_with_temp (operands[0], operands[1], temp)); DONE; } @@ -3867,7 +3868,10 @@ DONE; } else - operands[2] = assign_386_stack_local (SFmode, SLOT_VIRTUAL); + { + int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL; + operands[2] = assign_386_stack_local (SFmode, slot); + } }) (define_insn "*truncxfsf2_mixed" @@ -3965,7 +3969,10 @@ DONE; } else - operands[2] = assign_386_stack_local (DFmode, SLOT_VIRTUAL); + { + int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL; + operands[2] = assign_386_stack_local (DFmode, slot); + } }) (define_insn "*truncxfdf2_mixed" diff --git a/gcc/config/i386/netware-libgcc.exp b/gcc/config/i386/netware-libgcc.exp index a3498c0e720..8579bd5d228 100644 --- a/gcc/config/i386/netware-libgcc.exp +++ b/gcc/config/i386/netware-libgcc.exp @@ -64,6 +64,7 @@ _Unwind_GetDataRelBase, _Unwind_GetGR, _Unwind_GetIP, + _Unwind_GetIPInfo, _Unwind_GetLanguageSpecificData, _Unwind_GetRegionStart, _Unwind_GetTextRelBase, diff --git a/gcc/config/i386/t-crtstuff b/gcc/config/i386/t-crtstuff index a202df6653f..c14dd9411ae 100644 --- a/gcc/config/i386/t-crtstuff +++ b/gcc/config/i386/t-crtstuff @@ -1,2 +1,7 @@ # The pushl in CTOR initialization interferes with frame pointer elimination. -CRTSTUFF_T_CFLAGS = -fno-omit-frame-pointer +# crtend*.o cannot be compiled without -fno-asynchronous-unwind-tables, +# because then __FRAME_END__ might not be the last thing in .eh_frame +# section. -fno-asynchronous-unwind-tables is off by default for i386 +# and is on by default for x86-64. We turn it off for both i386 and +# x86-64. +CRTSTUFF_T_CFLAGS += -fno-omit-frame-pointer -fno-asynchronous-unwind-tables diff --git a/gcc/config/i386/t-linux64 b/gcc/config/i386/t-linux64 index aac59a08e36..8cb029f5063 100644 --- a/gcc/config/i386/t-linux64 +++ b/gcc/config/i386/t-linux64 @@ -4,18 +4,19 @@ SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver \ $(srcdir)/config/i386/libgcc-x86_64-glibc.ver +# On Debian, Ubuntu and other derivative distributions, the 32bit libraries +# are found in /lib32 and /usr/lib32, /lib64 and /usr/lib64 are symlinks to +# /lib and /usr/lib, while other distributions install libraries into /lib64 +# and /usr/lib64. The LSB does not enforce the use of /lib64 and /usr/lib64, +# it doesn't tell anything about the 32bit libraries on those systems. Set +# MULTILIB_OSDIRNAMES according to what is found on the target. + MULTILIB_OPTIONS = m64/m32 MULTILIB_DIRNAMES = 64 32 -MULTILIB_OSDIRNAMES = ../lib64 ../lib +MULTILIB_OSDIRNAMES = ../lib64 $(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib) LIBGCC = stmp-multilib INSTALL_LIBGCC = install-multilib EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o \ crtbeginT.o crtfastmath.o - -# The pushl in CTOR initialization interferes with frame pointer elimination. -# crtend*.o cannot be compiled without -fno-asynchronous-unwind-tables, -# because then __FRAME_END__ might not be the last thing in .eh_frame -# section. -CRTSTUFF_T_CFLAGS = -fno-omit-frame-pointer -fno-asynchronous-unwind-tables diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 20412685316..082a2315bed 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -9174,6 +9174,19 @@ ia64_init_builtins (void) IA64_BUILTIN_FLUSHRS); #undef def_builtin + + if (TARGET_HPUX) + { + if (built_in_decls [BUILT_IN_FINITE]) + set_user_assembler_name (built_in_decls [BUILT_IN_FINITE], + "_Isfinite"); + if (built_in_decls [BUILT_IN_FINITEF]) + set_user_assembler_name (built_in_decls [BUILT_IN_FINITEF], + "_Isfinitef"); + if (built_in_decls [BUILT_IN_FINITEL]) + set_user_assembler_name (built_in_decls [BUILT_IN_FINITEL], + "_Isfinitef128"); + } } rtx diff --git a/gcc/config/m68k/t-rtems b/gcc/config/m68k/t-rtems index e660da2d637..2597bcae505 100644 --- a/gcc/config/m68k/t-rtems +++ b/gcc/config/m68k/t-rtems @@ -1,7 +1,14 @@ # Custom multilibs for RTEMS -MULTILIB_OPTIONS = m68000/m68020/m5200/mcpu32/m68030/m68040/m68060 m68881/msoft-float +MULTILIB_OPTIONS = m68000/m68020/m5200/m528x/mcpu32/m68030/m68040/m68060/m5307/m5407/mcfv4e +MULTILIB_OPTIONS += m68881/msoft-float MULTILIB_DIRNAMES = MULTILIB_MATCHES = m68000=mc68000 m68000=m68302 mcpu32=m68332 m68020=mc68020 m68030=mc68030 -MULTILIB_MATCHES += m5200=m528x -MULTILIB_EXCEPTIONS = m68000/msoft-float m5200/m68881 m5200/msoft-float mcpu32/m68881 mcpu32/msoft-float m68040/m68881 m68060/m68881 +MULTILIB_MATCHES += m5200=m5206e +MULTILIB_EXCEPTIONS = m68000/msoft-float m68040/m68881 m68060/m68881 +MULTILIB_EXCEPTIONS += mcpu32/m68881 mcpu32/msoft-float +MULTILIB_EXCEPTIONS += m5200/m68881 m5200/msoft-float +MULTILIB_EXCEPTIONS += m528x/m68881 m528x/msoft-float +MULTILIB_EXCEPTIONS += m5307/m68881 m5307/msoft-float +MULTILIB_EXCEPTIONS += m5407/m68881 m5407/msoft-float +MULTILIB_EXCEPTIONS += mcfv4e/m68881 mcfv4e/msoft-float diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 0cfe76756d5..737cc176a6a 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -171,7 +171,7 @@ extern void mips_expand_vcondv2sf (rtx, rtx, rtx, enum rtx_code, rtx, rtx); #endif extern void gen_conditional_move (rtx *); extern void mips_gen_conditional_trap (rtx *); -extern void mips_expand_call (rtx, rtx, rtx, rtx, int); +extern rtx mips_expand_call (rtx, rtx, rtx, rtx, int); extern void mips_emit_fcc_reload (rtx, rtx, rtx); extern void mips_set_return_address (rtx, rtx); extern bool mips_expand_block_move (rtx, rtx, rtx); @@ -231,7 +231,7 @@ extern enum reg_class mips_secondary_reload_class (enum reg_class, enum machine_mode, rtx, int); extern int mips_class_max_nregs (enum reg_class, enum machine_mode); -extern int build_mips16_call_stub (rtx, rtx, rtx, int); +extern rtx build_mips16_call_stub (rtx, rtx, rtx, int); extern int mips_register_move_cost (enum machine_mode, enum reg_class, enum reg_class); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index da2fb255b8a..ff020bf9349 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -1904,6 +1904,31 @@ mips_idiv_insns (void) count++; return count; } + +/* Emit a call sequence with call pattern PATTERN and return the call + instruction itself (which is not necessarily the last instruction + emitted). LAZY_P is true if the call address is lazily-bound. */ + +static rtx +mips_emit_call_insn (rtx pattern, bool lazy_p) +{ + rtx insn; + + insn = emit_call_insn (pattern); + + /* Lazy-binding stubs require $gp to be valid on entry. */ + if (lazy_p) + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); + + if (TARGET_ABICALLS) + { + /* See the comment above load_call<mode> for details. */ + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), + gen_rtx_REG (Pmode, GOT_VERSION_REGNUM)); + emit_insn (gen_update_got_version ()); + } + return insn; +} /* This function is used to implement GO_IF_LEGITIMATE_ADDRESS. It returns a nonzero value if X is a legitimate address for a memory @@ -1935,6 +1960,19 @@ mips_force_temporary (rtx dest, rtx value) } +/* Return an instruction that copies $gp into register REG. We want + GCC to treat the register's value as constant, so that its value + can be rematerialized on demand. */ + +static rtx +gen_load_const_gp (rtx reg) +{ + return (Pmode == SImode + ? gen_load_const_gp_si (reg) + : gen_load_const_gp_di (reg)); +} + + /* Return a LO_SUM expression for ADDR. TEMP is as for mips_force_temporary and is used to load the high part into a register. */ @@ -1943,10 +1981,15 @@ mips_split_symbol (rtx temp, rtx addr) { rtx high; - if (TARGET_MIPS16) - high = mips16_gp_pseudo_reg (); - else + if (!TARGET_MIPS16) high = mips_force_temporary (temp, gen_rtx_HIGH (Pmode, copy_rtx (addr))); + else if (no_new_pseudos) + { + emit_insn (gen_load_const_gp (copy_rtx (temp))); + high = temp; + } + else + high = mips16_gp_pseudo_reg (); return gen_rtx_LO_SUM (Pmode, high, addr); } @@ -2026,7 +2069,7 @@ static GTY(()) rtx mips_tls_symbol; static rtx mips_call_tls_get_addr (rtx sym, enum mips_symbol_type type, rtx v0) { - rtx insn, loc, tga, a0; + rtx insn, loc, a0; a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST); @@ -2039,8 +2082,7 @@ mips_call_tls_get_addr (rtx sym, enum mips_symbol_type type, rtx v0) emit_insn (gen_rtx_SET (Pmode, a0, gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, loc))); - tga = gen_rtx_MEM (Pmode, mips_tls_symbol); - insn = emit_call_insn (gen_call_value (v0, tga, const0_rtx, const0_rtx)); + insn = mips_expand_call (v0, mips_tls_symbol, const0_rtx, const0_rtx, false); CONST_OR_PURE_CALL_P (insn) = 1; use_reg (&CALL_INSN_FUNCTION_USAGE (insn), v0); use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0); @@ -3415,9 +3457,11 @@ mips_load_call_address (rtx dest, rtx addr, int sibcall_p) function, ARGS_SIZE is the size of the arguments and AUX is the value passed to us by mips_function_arg. SIBCALL_P is true if we are expanding a sibling call, false if we're expanding - a normal call. */ + a normal call. -void + Return the call itself. */ + +rtx mips_expand_call (rtx result, rtx addr, rtx args_size, rtx aux, int sibcall_p) { rtx orig_addr, pattern, insn; @@ -3431,11 +3475,13 @@ mips_expand_call (rtx result, rtx addr, rtx args_size, rtx aux, int sibcall_p) lazy_p = mips_load_call_address (addr, orig_addr, sibcall_p); } - if (TARGET_MIPS16 - && mips16_hard_float - && build_mips16_call_stub (result, addr, args_size, - aux == 0 ? 0 : (int) GET_MODE (aux))) - return; + insn = build_mips16_call_stub (result, addr, args_size, + aux == 0 ? 0 : (int) GET_MODE (aux)); + if (insn) + { + gcc_assert (!sibcall_p && !lazy_p); + return insn; + } if (result == 0) pattern = (sibcall_p @@ -3457,17 +3503,7 @@ mips_expand_call (rtx result, rtx addr, rtx args_size, rtx aux, int sibcall_p) ? gen_sibcall_value_internal (result, addr, args_size) : gen_call_value_internal (result, addr, args_size)); - insn = emit_call_insn (pattern); - - /* Lazy-binding stubs require $gp to be valid on entry. We also pretend - that they use FAKE_CALL_REGNO; see the load_call<mode> patterns for - details. */ - if (lazy_p) - { - use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); - use_reg (&CALL_INSN_FUNCTION_USAGE (insn), - gen_rtx_REG (Pmode, FAKE_CALL_REGNO)); - } + return mips_emit_call_insn (pattern, lazy_p); } @@ -5077,6 +5113,10 @@ override_options (void) else if (ALL_COP_REG_P (regno)) temp = (class == MODE_INT && size <= UNITS_PER_WORD); + + else if (regno == GOT_VERSION_REGNUM) + temp = (mode == SImode); + else temp = 0; @@ -6669,13 +6709,16 @@ mips_emit_loadgp (void) offset = mips_unspec_address (addr, SYMBOL_GOTOFF_LOADGP); incoming_address = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM); emit_insn (gen_loadgp (offset, incoming_address)); - if (!TARGET_EXPLICIT_RELOCS) - emit_insn (gen_loadgp_blockage ()); break; default: - break; + return; } + /* Emit a blockage if there are implicit uses of the GP register. + This includes profiled functions, because FUNCTION_PROFILE uses + a jal macro. */ + if (!TARGET_EXPLICIT_RELOCS || current_function_profile) + emit_insn (gen_loadgp_blockage ()); } /* Set up the stack and frame (if desired) for the function. */ @@ -7882,19 +7925,11 @@ mips16_gp_pseudo_reg (void) { if (cfun->machine->mips16_gp_pseudo_rtx == NULL_RTX) { - rtx unspec; rtx insn, scan; cfun->machine->mips16_gp_pseudo_rtx = gen_reg_rtx (Pmode); - /* We want to initialize this to a value which gcc will believe - is constant. */ - start_sequence (); - unspec = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, const0_rtx), UNSPEC_GP); - emit_move_insn (cfun->machine->mips16_gp_pseudo_rtx, - gen_rtx_CONST (Pmode, unspec)); - insn = get_insns (); - end_sequence (); + insn = gen_load_const_gp (cfun->machine->mips16_gp_pseudo_rtx); push_topmost_sequence (); /* We need to emit the initialization after the FUNCTION_BEG @@ -8083,10 +8118,12 @@ static struct mips16_stub *mips16_stubs; RETVAL is the location of the return value, or null if this is a call rather than a call_value. FN is the address of the function and ARG_SIZE is the size of the arguments. FP_CODE - is the code built by function_arg. This function returns a nonzero - value if it builds the call instruction itself. */ + is the code built by function_arg. -int + If a stub was needed, emit the call and return the call insn itself. + Return null otherwise. */ + +rtx build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code) { int fpret; @@ -8100,7 +8137,7 @@ build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code) /* We don't need to do anything if we aren't in mips16 mode, or if we were invoked with the -msoft-float option. */ if (! TARGET_MIPS16 || ! mips16_hard_float) - return 0; + return NULL_RTX; /* Figure out whether the value might come back in a floating point register. */ @@ -8112,13 +8149,13 @@ build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code) arguments and the value will not be returned in a floating point register. */ if (fp_code == 0 && ! fpret) - return 0; + return NULL_RTX; /* We don't need to do anything if this is a call to a special mips16 support function. */ if (GET_CODE (fn) == SYMBOL_REF && strncmp (XSTR (fn, 0), "__mips16_", 9) == 0) - return 0; + return NULL_RTX; /* This code will only work for o32 and o64 abis. The other ABI's require more sophisticated support. */ @@ -8157,7 +8194,7 @@ build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code) insn = gen_call_internal (stub_fn, arg_size); else insn = gen_call_value_internal (retval, stub_fn, arg_size); - insn = emit_call_insn (insn); + insn = mips_emit_call_insn (insn, false); /* Put the register usage information on the CALL. */ CALL_INSN_FUNCTION_USAGE (insn) = @@ -8179,7 +8216,7 @@ build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code) /* Return 1 to tell the caller that we've generated the call insn. */ - return 1; + return insn; } /* We know the function we are going to call. If we have already @@ -8358,7 +8395,7 @@ build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code) insn = gen_call_internal (fn, arg_size); else insn = gen_call_value_internal (retval, fn, arg_size); - insn = emit_call_insn (insn); + insn = mips_emit_call_insn (insn, false); CALL_INSN_FUNCTION_USAGE (insn) = gen_rtx_EXPR_LIST (VOIDmode, @@ -8367,11 +8404,11 @@ build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code) /* Return 1 to tell the caller that we've generated the call insn. */ - return 1; + return insn; } /* Return 0 to let the caller generate the call insn. */ - return 0; + return NULL_RTX; } /* An entry in the mips16 constant pool. VALUE is the pool constant, @@ -9102,7 +9139,7 @@ mips_avoid_hazard (rtx after, rtx insn, int *hilo_delay, rtx *delayed_reg, rtx lo_reg) { rtx pattern, set; - int nops, ninsns, hazard_set; + int nops, ninsns; pattern = PATTERN (insn); @@ -9148,15 +9185,8 @@ mips_avoid_hazard (rtx after, rtx insn, int *hilo_delay, break; case HAZARD_DELAY: - hazard_set = (int) get_attr_hazard_set (insn); - if (hazard_set == 0) - set = single_set (insn); - else - { - gcc_assert (GET_CODE (PATTERN (insn)) == PARALLEL); - set = XVECEXP (PATTERN (insn), 0, hazard_set - 1); - } - gcc_assert (set && GET_CODE (set) == SET); + set = single_set (insn); + gcc_assert (set); *delayed_reg = SET_DEST (set); break; } @@ -11014,14 +11044,21 @@ mips_encode_section_info (tree decl, rtx rtl, int first) } } -/* Implement TARGET_EXTRA_LIVE_ON_ENTRY. PIC_FUNCTION_ADDR_REGNUM is live - on entry to a function when generating -mshared abicalls code. */ +/* Implement TARGET_EXTRA_LIVE_ON_ENTRY. */ static void mips_extra_live_on_entry (bitmap regs) { - if (TARGET_ABICALLS && !TARGET_ABSOLUTE_ABICALLS) - bitmap_set_bit (regs, PIC_FUNCTION_ADDR_REGNUM); + if (TARGET_ABICALLS) + { + /* PIC_FUNCTION_ADDR_REGNUM is live if we need it to set up + the global pointer. */ + if (!TARGET_ABSOLUTE_ABICALLS) + bitmap_set_bit (regs, PIC_FUNCTION_ADDR_REGNUM); + + /* See the comment above load_call<mode> for details. */ + bitmap_set_bit (regs, GOT_VERSION_REGNUM); + } } /* SImode values are represented as sign-extended to DImode. */ diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index d34cad46006..e857c1d706d 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -1175,7 +1175,7 @@ extern const struct mips_rtx_cost_data *mips_cost; - 3 fake registers: - ARG_POINTER_REGNUM - FRAME_POINTER_REGNUM - - FAKE_CALL_REGNO (see the comment above load_callsi for details) + - GOT_VERSION_REGNUM (see the comment above load_call<mode> for details) - 3 dummy entries that were used at various times in the past. - 6 DSP accumulator registers (3 hi-lo pairs) for MIPS DSP ASE - 6 DSP control registers */ @@ -1255,7 +1255,7 @@ extern const struct mips_rtx_cost_data *mips_cost; 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ /* Others. */ \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, \ /* COP0 registers */ \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ @@ -1966,8 +1966,12 @@ typedef struct mips_args { /* Say that the epilogue uses the return address register. Note that in the case of sibcalls, the values "used by the epilogue" are - considered live at the start of the called function. */ -#define EPILOGUE_USES(REGNO) ((REGNO) == 31) + considered live at the start of the called function. + + If using a GOT, say that the epilogue also uses GOT_VERSION_REGNUM. + See the comment above load_call<mode> for details. */ +#define EPILOGUE_USES(REGNO) \ + ((REGNO) == 31 || (TARGET_ABICALLS && (REGNO) == GOT_VERSION_REGNUM)) /* Treat LOC as a byte offset from the stack pointer and round it up to the next fully-aligned offset. */ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index ccb75cbf312..6a940d53ad1 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -29,7 +29,7 @@ (UNSPEC_GET_FNADDR 3) (UNSPEC_BLOCKAGE 4) (UNSPEC_CPRESTORE 5) - (UNSPEC_EH_RECEIVER 6) + (UNSPEC_RESTORE_GP 6) (UNSPEC_EH_RETURN 7) (UNSPEC_CONSTTABLE_INT 8) (UNSPEC_CONSTTABLE_FLOAT 9) @@ -46,10 +46,12 @@ (UNSPEC_MFHILO 26) (UNSPEC_TLS_LDM 27) (UNSPEC_TLS_GET_TP 28) + (UNSPEC_SET_GOT_VERSION 29) + (UNSPEC_UPDATE_GOT_VERSION 30) (UNSPEC_ADDRESS_FIRST 100) - (FAKE_CALL_REGNO 79) + (GOT_VERSION_REGNUM 79) ;; For MIPS Paired-Singled Floating Point Instructions. @@ -222,8 +224,9 @@ ;; frsqrt2 floating point reciprocal square root step2 ;; multi multiword sequence (or user asm statements) ;; nop no operation +;; ghost an instruction that produces no real code (define_attr "type" - "unknown,branch,jump,call,load,fpload,fpidxload,store,fpstore,fpidxstore,prefetch,prefetchx,condmove,xfer,mthilo,mfhilo,const,arith,shift,slt,clz,trap,imul,imul3,imadd,idiv,fmove,fadd,fmul,fmadd,fdiv,frdiv,frdiv1,frdiv2,fabs,fneg,fcmp,fcvt,fsqrt,frsqrt,frsqrt1,frsqrt2,multi,nop" + "unknown,branch,jump,call,load,fpload,fpidxload,store,fpstore,fpidxstore,prefetch,prefetchx,condmove,xfer,mthilo,mfhilo,const,arith,shift,slt,clz,trap,imul,imul3,imadd,idiv,fmove,fadd,fmul,fmadd,fdiv,frdiv,frdiv1,frdiv2,fabs,fneg,fcmp,fcvt,fsqrt,frsqrt,frsqrt1,frsqrt2,multi,nop,ghost" (cond [(eq_attr "jal" "!unset") (const_string "call") (eq_attr "got" "load") (const_string "load")] (const_string "unknown"))) @@ -370,17 +373,6 @@ (const_string "hilo")] (const_string "none"))) -;; Indicates which SET in an instruction pattern induces a hazard. -;; Only meaningful when "hazard" is not "none". SINGLE means that -;; the pattern has only one set while the other values are indexes -;; into a PARALLEL vector. -;; -;; Hazardous instructions with multiple sets should generally put the -;; hazardous set first. The only purpose of this attribute is to force -;; each multi-set pattern to explicitly assert that this condition holds. -(define_attr "hazard_set" "single,0" - (const_string "single")) - ;; Is it a single instruction? (define_attr "single_insn" "no,yes" (symbol_ref "get_attr_length (insn) == (TARGET_MIPS16 ? 2 : 4)")) @@ -585,6 +577,12 @@ (define_cpu_unit "alu" "alu") (define_cpu_unit "imuldiv" "imuldiv") +;; Ghost instructions produce no real code and introduce no hazards. +;; They exist purely to express an effect on dataflow. +(define_insn_reservation "ghost" 0 + (eq_attr "type" "ghost") + "nothing") + (include "4k.md") (include "5k.md") (include "24k.md") @@ -4001,6 +3999,11 @@ [(set_attr "type" "xfer,fpstore") (set_attr "mode" "SF")]) +;; Move a constant that satisfies CONST_GP_P into operand 0. +(define_expand "load_const_gp_<mode>" + [(set (match_operand:P 0 "register_operand" "=d") + (const:P (unspec:P [(const_int 0)] UNSPEC_GP)))]) + ;; Insn to initialize $gp for n32/n64 abicalls. Operand 0 is the offset ;; of _gp from the start of this function. Operand 1 is the incoming ;; function address. @@ -4034,12 +4037,11 @@ } [(set_attr "length" "8")]) -;; The use of gp is hidden when not using explicit relocations. ;; This blockage instruction prevents the gp load from being ;; scheduled after an implicit use of gp. It also prevents ;; the load from being deleted as dead. (define_insn "loadgp_blockage" - [(unspec_volatile [(reg:DI 28)] UNSPEC_BLOCKAGE)] + [(unspec_volatile [(reg:SI 28)] UNSPEC_BLOCKAGE)] "" "" [(set_attr "type" "unknown") @@ -5024,9 +5026,33 @@ DONE; }) -(define_insn_and_split "exception_receiver" +(define_expand "exception_receiver" + [(const_int 0)] + "TARGET_ABICALLS" +{ + /* See the comment above load_call<mode> for details. */ + emit_insn (gen_set_got_version ()); + + /* If we have a call-clobbered $gp, restore it from its save slot. */ + if (HAVE_restore_gp) + emit_insn (gen_restore_gp ()); + DONE; +}) + +(define_expand "nonlocal_goto_receiver" + [(const_int 0)] + "TARGET_ABICALLS" +{ + /* See the comment above load_call<mode> for details. */ + emit_insn (gen_set_got_version ()); + DONE; +}) + +;; Restore $gp from its .cprestore stack slot. The instruction remains +;; volatile until all uses of $28 are exposed. +(define_insn_and_split "restore_gp" [(set (reg:SI 28) - (unspec_volatile:SI [(const_int 0)] UNSPEC_EH_RECEIVER))] + (unspec_volatile:SI [(const_int 0)] UNSPEC_RESTORE_GP))] "TARGET_ABICALLS && TARGET_OLDABI" "#" "&& reload_completed" @@ -5055,24 +5081,66 @@ ;; potentially modify the GOT entry. And once a stub has been called, ;; we must not call it again. ;; -;; We represent this restriction using an imaginary fixed register that -;; is set by the GOT load and used by the call. By making this register -;; call-clobbered, and by making the GOT load the only way of setting -;; the register, we ensure that the load cannot be moved past a call. +;; We represent this restriction using an imaginary, fixed, call-saved +;; register called GOT_VERSION_REGNUM. The idea is to make the register +;; live throughout the function and to change its value after every +;; potential call site. This stops any rtx value that uses the register +;; from being computed before an earlier call. To do this, we: +;; +;; - Ensure that the register is live on entry to the function, +;; so that it is never thought to be used uninitalized. +;; +;; - Ensure that the register is live on exit from the function, +;; so that it is live throughout. +;; +;; - Make each call (lazily-bound or not) use the current value +;; of GOT_VERSION_REGNUM, so that updates of the register are +;; not moved across call boundaries. +;; +;; - Add "ghost" definitions of the register to the beginning of +;; blocks reached by EH and ABNORMAL_CALL edges, because those +;; edges may involve calls that normal paths don't. (E.g. the +;; unwinding code that handles a non-call exception may change +;; lazily-bound GOT entries.) We do this by making the +;; exception_receiver and nonlocal_goto_receiver expanders emit +;; a set_got_version instruction. +;; +;; - After each call (lazily-bound or not), use a "ghost" +;; update_got_version instruction to change the register's value. +;; This instruction mimics the _possible_ effect of the dynamic +;; resolver during the call and it remains live even if the call +;; itself becomes dead. +;; +;; - Leave GOT_VERSION_REGNUM out of all register classes. +;; The register is therefore not a valid register_operand +;; and cannot be moved to or from other registers. (define_insn "load_call<mode>" [(set (match_operand:P 0 "register_operand" "=c") (unspec:P [(match_operand:P 1 "register_operand" "r") - (match_operand:P 2 "immediate_operand" "")] - UNSPEC_LOAD_CALL)) - (set (reg:P FAKE_CALL_REGNO) - (unspec:P [(match_dup 2)] UNSPEC_LOAD_CALL))] + (match_operand:P 2 "immediate_operand" "") + (reg:SI GOT_VERSION_REGNUM)] UNSPEC_LOAD_CALL))] "TARGET_ABICALLS" "<load>\t%0,%R2(%1)" [(set_attr "type" "load") (set_attr "mode" "<MODE>") - (set_attr "hazard_set" "0") (set_attr "length" "4")]) +(define_insn "set_got_version" + [(set (reg:SI GOT_VERSION_REGNUM) + (unspec_volatile:SI [(const_int 0)] UNSPEC_SET_GOT_VERSION))] + "TARGET_ABICALLS" + "" + [(set_attr "length" "0") + (set_attr "type" "ghost")]) + +(define_insn "update_got_version" + [(set (reg:SI GOT_VERSION_REGNUM) + (unspec:SI [(reg:SI GOT_VERSION_REGNUM)] UNSPEC_UPDATE_GOT_VERSION))] + "TARGET_ABICALLS" + "" + [(set_attr "length" "0") + (set_attr "type" "ghost")]) + ;; Sibling calls. All these patterns use jump instructions. ;; If TARGET_SIBCALLS, call_insn_operand will only accept constant diff --git a/gcc/config/pa/pa-64.h b/gcc/config/pa/pa-64.h index e3adcf3ec28..67c8179c573 100644 --- a/gcc/config/pa/pa-64.h +++ b/gcc/config/pa/pa-64.h @@ -84,3 +84,17 @@ along with GCC; see the file COPYING3. If not see want aggregates padded down. */ #define PAD_VARARGS_DOWN (!AGGREGATE_TYPE_P (type)) + +/* In the PA architecture, it is not possible to directly move data + between GENERAL_REGS and FP_REGS. On the 32-bit port, we use the + location at SP-16 because PA 1.X only supports 5-bit immediates for + floating-point loads and stores. We don't expose this location in + the RTL to avoid scheduling related problems. For example, the + store and load could be separated by a call to a pure or const + function which has no frame and this function might also use SP-16. + We have 14-bit immediates on the 64-bit port, so we use secondary + memory for the copies. */ +#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \ + (MAYBE_FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2) \ + || MAYBE_FP_REG_CLASS_P (CLASS2) != FP_REG_CLASS_P (CLASS1)) + diff --git a/gcc/config/pa/pa-hpux.h b/gcc/config/pa/pa-hpux.h index 2a96835c558..cd85cdc2d27 100644 --- a/gcc/config/pa/pa-hpux.h +++ b/gcc/config/pa/pa-hpux.h @@ -97,7 +97,7 @@ along with GCC; see the file COPYING3. If not see #undef LINK_SPEC #if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_PA_11) #define LINK_SPEC \ - "%{!mpa-risc-1-0:%{!march=1.0:%{!shared:-L/lib/pa1.1 -L/usr/lib/pa1.1 }}}%{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{g*:-a archive} %{shared:-b}" + "%{!mpa-risc-1-0:%{!march=1.0:%{static:-L/lib/pa1.1 -L/usr/lib/pa1.1 }}}%{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{g*:-a archive} %{shared:-b}" #else #define LINK_SPEC \ "%{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{g*:-a archive} %{shared:-b}" diff --git a/gcc/config/pa/pa-hpux10.h b/gcc/config/pa/pa-hpux10.h index e48e43a398c..679689c3a52 100644 --- a/gcc/config/pa/pa-hpux10.h +++ b/gcc/config/pa/pa-hpux10.h @@ -84,7 +84,7 @@ along with GCC; see the file COPYING3. If not see #undef LINK_SPEC #if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_PA_11) #define LINK_SPEC \ - "%{!mpa-risc-1-0:%{!march=1.0:%{!shared:-L/lib/pa1.1 -L/usr/lib/pa1.1 }}}\ + "%{!mpa-risc-1-0:%{!march=1.0:%{static:-L/lib/pa1.1 -L/usr/lib/pa1.1 }}}\ %{!shared:%{p:-L/lib/libp %{!static:\ %nWarning: consider linking with `-static' as system libraries with\n\ %n profiling support are only provided in archive format}}}\ diff --git a/gcc/config/pa/pa-hpux11.h b/gcc/config/pa/pa-hpux11.h index cb4ff9317a3..4c64447f4d2 100644 --- a/gcc/config/pa/pa-hpux11.h +++ b/gcc/config/pa/pa-hpux11.h @@ -105,18 +105,6 @@ along with GCC; see the file COPYING3. If not see /* We can debug dynamically linked executables on hpux11; we also want dereferencing of a NULL pointer to cause a SEGV. */ #undef LINK_SPEC -#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_PA_11) -#define LINK_SPEC \ - "%{!mpa-risc-1-0:%{!march=1.0:%{!shared:-L/lib/pa1.1 -L/usr/lib/pa1.1 }}}\ - %{!shared:%{p:-L/lib/libp -L/usr/lib/libp %{!static:\ - %nWarning: consider linking with `-static' as system libraries with\n\ - %n profiling support are only provided in archive format}}}\ - %{!shared:%{pg:-L/lib/libp -L/usr/lib/libp %{!static:\ - %nWarning: consider linking with `-static' as system libraries with\n\ - %n profiling support are only provided in archive format}}}\ - -z %{mlinker-opt:-O} %{!shared:-u main -u __gcc_plt_call}\ - %{static:-a archive} %{shared:-b}" -#else #define LINK_SPEC \ "%{!shared:%{p:-L/lib/libp -L/usr/lib/libp %{!static:\ %nWarning: consider linking with `-static' as system libraries with\n\ @@ -126,7 +114,6 @@ along with GCC; see the file COPYING3. If not see %n profiling support are only provided in archive format}}}\ -z %{mlinker-opt:-O} %{!shared:-u main -u __gcc_plt_call}\ %{static:-a archive} %{shared:-b}" -#endif /* HP-UX 11 has posix threads. HP libc contains pthread stubs so that non-threaded applications can be linked with a thread-safe libc @@ -190,3 +177,6 @@ along with GCC; see the file COPYING3. If not see with secondary definition (weak) symbols. */ #undef TARGET_SOM_SDEF #define TARGET_SOM_SDEF 1 + +#undef TARGET_HPUX_11 +#define TARGET_HPUX_11 1 diff --git a/gcc/config/pa/pa-protos.h b/gcc/config/pa/pa-protos.h index 0f0b960e40e..14386436c57 100644 --- a/gcc/config/pa/pa-protos.h +++ b/gcc/config/pa/pa-protos.h @@ -174,6 +174,9 @@ extern void pa_asm_output_aligned_local (FILE *, const char *, unsigned HOST_WIDE_INT, unsigned int); extern void pa_hpux_asm_output_external (FILE *, tree, const char *); +extern bool pa_cannot_change_mode_class (enum machine_mode, enum machine_mode, + enum reg_class); +extern bool pa_modes_tieable_p (enum machine_mode, enum machine_mode); extern const int magic_milli[]; extern int shadd_constant_p (int); diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 4b5efb50c51..5d3689cad3c 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -511,6 +511,12 @@ pa_init_builtins (void) implicit_built_in_decls[(int) BUILT_IN_FPUTC_UNLOCKED] = implicit_built_in_decls[(int) BUILT_IN_PUTC_UNLOCKED]; #endif +#if TARGET_HPUX_11 + if (built_in_decls [BUILT_IN_FINITE]) + set_user_assembler_name (built_in_decls [BUILT_IN_FINITE], "_Isfinite"); + if (built_in_decls [BUILT_IN_FINITEF]) + set_user_assembler_name (built_in_decls [BUILT_IN_FINITEF], "_Isfinitef"); +#endif } /* Function to init struct machine_function. @@ -620,6 +626,8 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) /* Labels need special handling. */ if (pic_label_operand (orig, mode)) { + rtx insn; + /* We do not want to go through the movXX expanders here since that would create recursion. @@ -630,7 +638,24 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) So instead we just emit the raw set, which avoids the movXX expanders completely. */ mark_reg_pointer (reg, BITS_PER_UNIT); - emit_insn (gen_rtx_SET (VOIDmode, reg, orig)); + insn = emit_insn (gen_rtx_SET (VOIDmode, reg, orig)); + + /* Put a REG_EQUAL note on this insn, so that it can be optimized. */ + REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig, REG_NOTES (insn)); + + /* During and after reload, we need to generate a REG_LABEL note and + update LABEL_NUSES because this is not done automatically. */ + if (reload_in_progress || reload_completed) + { + /* Extract LABEL_REF. */ + if (GET_CODE (orig) == CONST) + orig = XEXP (XEXP (orig, 0), 0); + /* Extract CODE_LABEL. */ + orig = XEXP (orig, 0); + REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, orig, + REG_NOTES (insn)); + LABEL_NUSES (orig)++; + } current_function_uses_pic_offset_table = 1; return reg; } @@ -878,7 +903,7 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, int mask; mask = (GET_MODE_CLASS (mode) == MODE_FLOAT - ? (TARGET_PA_20 ? 0x3fff : 0x1f) : 0x3fff); + ? (INT14_OK_STRICT ? 0x3fff : 0x1f) : 0x3fff); /* Choose which way to round the offset. Round up if we are >= halfway to the next boundary. */ @@ -5652,12 +5677,49 @@ pa_secondary_reload (bool in_p, rtx x, enum reg_class class, if (regno >= FIRST_PSEUDO_REGISTER || GET_CODE (x) == SUBREG) regno = true_regnum (x); - /* Handle out of range displacement for integer mode loads/stores of - FP registers. */ - if (((regno >= FIRST_PSEUDO_REGISTER || regno == -1) - && GET_MODE_CLASS (mode) == MODE_INT - && FP_REG_CLASS_P (class)) - || (class == SHIFT_REGS && (regno <= 0 || regno >= 32))) + /* In order to allow 14-bit displacements in integer loads and stores, + we need to prevent reload from generating out of range integer mode + loads and stores to the floating point registers. Previously, we + used to call for a secondary reload and have emit_move_sequence() + fix the instruction sequence. However, reload occasionally wouldn't + generate the reload and we would end up with an invalid REG+D memory + address. So, now we use an intermediate general register for most + memory loads and stores. */ + if ((regno >= FIRST_PSEUDO_REGISTER || regno == -1) + && GET_MODE_CLASS (mode) == MODE_INT + && FP_REG_CLASS_P (class)) + { + /* Reload passes (mem:SI (reg/f:DI 30 %r30) when it wants to check + the secondary reload needed for a pseudo. It never passes a + REG+D address. */ + if (GET_CODE (x) == MEM) + { + x = XEXP (x, 0); + + /* We don't need an intermediate for indexed and LO_SUM DLT + memory addresses. When INT14_OK_STRICT is true, it might + appear that we could directly allow register indirect + memory addresses. However, this doesn't work because we + don't support SUBREGs in floating-point register copies + and reload doesn't tell us when it's going to use a SUBREG. */ + if (IS_INDEX_ADDR_P (x) + || IS_LO_SUM_DLT_ADDR_P (x)) + return NO_REGS; + + /* Otherwise, we need an intermediate general register. */ + return GENERAL_REGS; + } + + /* Request a secondary reload with a general scratch register + for everthing else. ??? Could symbolic operands be handled + directly when generating non-pic PA 2.0 code? */ + sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode]; + return NO_REGS; + } + + /* We need a secondary register (GPR) for copies between the SAR + and anything other than a general register. */ + if (class == SHIFT_REGS && (regno <= 0 || regno >= 32)) { sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode]; return NO_REGS; @@ -5666,16 +5728,15 @@ pa_secondary_reload (bool in_p, rtx x, enum reg_class class, /* A SAR<->FP register copy requires a secondary register (GPR) as well as secondary memory. */ if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER - && ((REGNO_REG_CLASS (regno) == SHIFT_REGS && FP_REG_CLASS_P (class)) - || (class == SHIFT_REGS - && FP_REG_CLASS_P (REGNO_REG_CLASS (regno))))) + && (REGNO_REG_CLASS (regno) == SHIFT_REGS + && FP_REG_CLASS_P (class))) { sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode]; return NO_REGS; } /* Secondary reloads of symbolic operands require %r1 as a scratch - register when we're generating PIC code and the operand isn't + register when we're generating PIC code and when the operand isn't readonly. */ if (GET_CODE (x) == HIGH) x = XEXP (x, 0); @@ -7743,6 +7804,12 @@ hppa_encode_label (rtx sym) static void pa_encode_section_info (tree decl, rtx rtl, int first) { + int old_referenced = 0; + + if (!first && MEM_P (rtl) && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF) + old_referenced + = SYMBOL_REF_FLAGS (XEXP (rtl, 0)) & SYMBOL_FLAG_REFERENCED; + default_encode_section_info (decl, rtl, first); if (first && TEXT_SPACE_P (decl)) @@ -7751,6 +7818,8 @@ pa_encode_section_info (tree decl, rtx rtl, int first) if (TREE_CODE (decl) == FUNCTION_DECL) hppa_encode_label (XEXP (rtl, 0)); } + else if (old_referenced) + SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= old_referenced; } /* This is sort of inverse to pa_encode_section_info. */ @@ -9519,4 +9588,62 @@ pa_hpux_file_end (void) } #endif +/* Return true if a change from mode FROM to mode TO for a register + in register class CLASS is invalid. */ + +bool +pa_cannot_change_mode_class (enum machine_mode from, enum machine_mode to, + enum reg_class class) +{ + if (from == to) + return false; + + /* Reject changes to/from complex and vector modes. */ + if (COMPLEX_MODE_P (from) || VECTOR_MODE_P (from) + || COMPLEX_MODE_P (to) || VECTOR_MODE_P (to)) + return true; + + if (GET_MODE_SIZE (from) == GET_MODE_SIZE (to)) + return false; + + /* There is no way to load QImode or HImode values directly from + memory. SImode loads to the FP registers are not zero extended. + On the 64-bit target, this conflicts with the definition of + LOAD_EXTEND_OP. Thus, we can't allow changing between modes + with different sizes in the floating-point registers. */ + if (MAYBE_FP_REG_CLASS_P (class)) + return true; + + /* HARD_REGNO_MODE_OK places modes with sizes larger than a word + in specific sets of registers. Thus, we cannot allow changing + to a larger mode when it's larger than a word. */ + if (GET_MODE_SIZE (to) > UNITS_PER_WORD + && GET_MODE_SIZE (to) > GET_MODE_SIZE (from)) + return true; + + return false; +} + +/* Returns TRUE if it is a good idea to tie two pseudo registers + when one has mode MODE1 and one has mode MODE2. + If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, + for any hard reg, then this must be FALSE for correct output. + + We should return FALSE for QImode and HImode because these modes + are not ok in the floating-point registers. However, this prevents + tieing these modes to SImode and DImode in the general registers. + So, this isn't a good idea. We rely on HARD_REGNO_MODE_OK and + CANNOT_CHANGE_MODE_CLASS to prevent these modes from being used + in the floating-point registers. */ + +bool +pa_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2) +{ + /* Don't tie modes in different classes. */ + if (GET_MODE_CLASS (mode1) != GET_MODE_CLASS (mode2)) + return false; + + return true; +} + #include "gt-pa.h" diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index 3a305e54903..d814bc646fa 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -83,6 +83,11 @@ extern int flag_pa_unix; #define TARGET_HPUX_10_10 0 #endif +/* HP-UX 11.* features (11.00, 11.11, 11.23, etc.) */ +#ifndef TARGET_HPUX_11 +#define TARGET_HPUX_11 0 +#endif + /* HP-UX 11i multibyte and UNIX 98 extensions. */ #ifndef TARGET_HPUX_11_11 #define TARGET_HPUX_11_11 0 @@ -344,7 +349,7 @@ typedef struct machine_function GTY(()) If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, for any hard reg, then this must be 0 for correct output. */ #define MODES_TIEABLE_P(MODE1, MODE2) \ - (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2)) + pa_modes_tieable_p (MODE1, MODE2) /* Specify the registers used for certain standard purposes. The values of these macros are register numbers. */ @@ -534,17 +539,6 @@ extern struct rtx_def *hppa_pic_save_rtx (void); #define MAYBE_FP_REG_CLASS_P(CLASS) \ reg_classes_intersect_p ((CLASS), FP_REGS) -/* On the PA it is not possible to directly move data between - GENERAL_REGS and FP_REGS. On the 32-bit port, we use the - location at SP-16. We don't expose this location in the RTL to - avoid scheduling related problems. For example, the store and - load could be separated by a call to a pure or const function - which has no frame and uses SP-16. */ -#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \ - (TARGET_64BIT \ - && (MAYBE_FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2) \ - || MAYBE_FP_REG_CLASS_P (CLASS2) != FP_REG_CLASS_P (CLASS1))) - /* Stack layout; function entry, exit and calling. */ @@ -1229,6 +1223,24 @@ extern int may_call_alloca; (GET_CODE (OP) == CONST_INT && INTVAL (OP) == 63) : 0))))))) +/* Nonzero if 14-bit offsets can be used for all loads and stores. + This is not possible when generating PA 1.x code as floating point + loads and stores only support 5-bit offsets. Note that we do not + forbid the use of 14-bit offsets in GO_IF_LEGITIMATE_ADDRESS. + Instead, we use pa_secondary_reload() to reload integer mode + REG+D memory addresses used in floating point loads and stores. + + FIXME: the ELF32 linker clobbers the LSB of the FP register number + in PA 2.0 floating-point insns with long displacements. This is + because R_PARISC_DPREL14WR and other relocations like it are not + yet supported by GNU ld. For now, we reject long displacements + on this target. */ + +#define INT14_OK_STRICT \ + (TARGET_SOFT_FLOAT \ + || TARGET_DISABLE_FPREGS \ + || (TARGET_PA_20 && !TARGET_ELF32)) + /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx and check its validity for a certain class. We have two alternate definitions for each of them. @@ -1247,16 +1259,18 @@ extern int may_call_alloca; /* Nonzero if X is a hard reg that can be used as an index or if it is a pseudo reg. */ #define REG_OK_FOR_INDEX_P(X) \ -(REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER)) + (REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER)) + /* Nonzero if X is a hard reg that can be used as a base reg or if it is a pseudo reg. */ #define REG_OK_FOR_BASE_P(X) \ -(REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER)) + (REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER)) #else /* Nonzero if X is a hard reg that can be used as an index. */ #define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) + /* Nonzero if X is a hard reg that can be used as a base reg. */ #define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) @@ -1308,11 +1322,7 @@ extern int may_call_alloca; We treat a SYMBOL_REF as legitimate if it is part of the current function's constant-pool, because such addresses can actually be - output as REG+SMALLINT. - - Note we only allow 5 bit immediates for access to a constant address; - doing so avoids losing for loading/storing a FP register at an address - which will not fit in 5 bits. */ + output as REG+SMALLINT. */ #define VAL_5_BITS_P(X) ((unsigned HOST_WIDE_INT)(X) + 0x10 < 0x20) #define INT_5_BITS(X) VAL_5_BITS_P (INTVAL (X)) @@ -1340,7 +1350,8 @@ extern int may_call_alloca; ((TARGET_64BIT && (MODE) == DImode) \ || (MODE) == SImode \ || (MODE) == HImode \ - || (!TARGET_SOFT_FLOAT && ((MODE) == DFmode || (MODE) == SFmode))) + || (MODE) == SFmode \ + || (MODE) == DFmode) /* These are the modes that we allow for unscaled indexing. */ #define MODE_OK_FOR_UNSCALED_INDEXING_P(MODE) \ @@ -1348,7 +1359,8 @@ extern int may_call_alloca; || (MODE) == SImode \ || (MODE) == HImode \ || (MODE) == QImode \ - || (!TARGET_SOFT_FLOAT && ((MODE) == DFmode || (MODE) == SFmode))) + || (MODE) == SFmode \ + || (MODE) == DFmode) #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ { \ @@ -1382,20 +1394,10 @@ extern int may_call_alloca; || (INTVAL (index) % 8) == 0)) \ /* Similarly, the base register for SFmode/DFmode \ loads and stores with long displacements must \ - be aligned. \ - \ - FIXME: the ELF32 linker clobbers the LSB of \ - the FP register number in PA 2.0 floating-point \ - insns with long displacements. This is because \ - R_PARISC_DPREL14WR and other relocations like \ - it are not supported. For now, we reject long \ - displacements on this target. */ \ + be aligned. */ \ || (((MODE) == SFmode || (MODE) == DFmode) \ - && (TARGET_SOFT_FLOAT \ - || (TARGET_PA_20 \ - && !TARGET_ELF32 \ - && (INTVAL (index) \ - % GET_MODE_SIZE (MODE)) == 0))))) \ + && INT14_OK_STRICT \ + && (INTVAL (index) % GET_MODE_SIZE (MODE)) == 0))) \ || INT_5_BITS (index))) \ goto ADDR; \ if (!TARGET_DISABLE_INDEXING \ @@ -1495,7 +1497,7 @@ do { \ rtx new, temp = NULL_RTX; \ \ mask = (GET_MODE_CLASS (MODE) == MODE_FLOAT \ - ? (TARGET_PA_20 && !TARGET_ELF32 ? 0x3fff : 0x1f) : 0x3fff); \ + ? (INT14_OK_STRICT ? 0x3fff : 0x1f) : 0x3fff); \ \ if (optimize && GET_CODE (AD) == PLUS) \ temp = simplify_binary_operation (PLUS, Pmode, \ @@ -1517,9 +1519,10 @@ do { \ newoffset = offset & ~mask; \ \ /* Ensure that long displacements are aligned. */ \ - if (!VAL_5_BITS_P (newoffset) \ - && GET_MODE_CLASS (MODE) == MODE_FLOAT) \ - newoffset &= ~(GET_MODE_SIZE (MODE) -1); \ + if (mask == 0x3fff \ + && (GET_MODE_CLASS (MODE) == MODE_FLOAT \ + || (TARGET_64BIT && (MODE) == DImode))) \ + newoffset &= ~(GET_MODE_SIZE (MODE) - 1); \ \ if (newoffset != 0 && VAL_14_BITS_P (newoffset)) \ { \ diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index 2fca3e69dc8..e1004d04ae4 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -3125,60 +3125,11 @@ (define_insn "" [(set (match_operand:HI 0 "move_dest_operand" - "=r,r,r,r,r,Q,!*q,!r,!*f,?r,?*f") - (match_operand:HI 1 "move_src_operand" - "r,J,N,K,RQ,rM,!rM,!*q,!*fM,*f,r"))] - "(register_operand (operands[0], HImode) - || reg_or_0_operand (operands[1], HImode)) - && !TARGET_SOFT_FLOAT - && !TARGET_64BIT" - "@ - copy %1,%0 - ldi %1,%0 - ldil L'%1,%0 - {zdepi|depwi,z} %Z1,%0 - ldh%M1 %1,%0 - sth%M0 %r1,%0 - mtsar %r1 - {mfctl|mfctl,w} %sar,%0 - fcpy,sgl %f1,%0 - {fstws|fstw} %1,-16(%%sp)\n\t{ldws|ldw} -16(%%sp),%0 - {stws|stw} %1,-16(%%sp)\n\t{fldws|fldw} -16(%%sp),%0" - [(set_attr "type" "move,move,move,shift,load,store,move,move,move,move,move") - (set_attr "pa_combine_type" "addmove") - (set_attr "length" "4,4,4,4,4,4,4,4,4,8,8")]) - -(define_insn "" - [(set (match_operand:HI 0 "move_dest_operand" - "=r,r,r,r,r,Q,!*q,!r,!*f") - (match_operand:HI 1 "move_src_operand" - "r,J,N,K,RQ,rM,!rM,!*q,!*fM"))] - "(register_operand (operands[0], HImode) - || reg_or_0_operand (operands[1], HImode)) - && !TARGET_SOFT_FLOAT - && TARGET_64BIT" - "@ - copy %1,%0 - ldi %1,%0 - ldil L'%1,%0 - {zdepi|depwi,z} %Z1,%0 - ldh%M1 %1,%0 - sth%M0 %r1,%0 - mtsar %r1 - {mfctl|mfctl,w} %sar,%0 - fcpy,sgl %f1,%0" - [(set_attr "type" "move,move,move,shift,load,store,move,move,move") - (set_attr "pa_combine_type" "addmove") - (set_attr "length" "4,4,4,4,4,4,4,4,4")]) - -(define_insn "" - [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,r,r,Q,!*q,!r") (match_operand:HI 1 "move_src_operand" "r,J,N,K,RQ,rM,!rM,!*q"))] "(register_operand (operands[0], HImode) - || reg_or_0_operand (operands[1], HImode)) - && TARGET_SOFT_FLOAT" + || reg_or_0_operand (operands[1], HImode))" "@ copy %1,%0 ldi %1,%0 @@ -3298,60 +3249,11 @@ (define_insn "" [(set (match_operand:QI 0 "move_dest_operand" - "=r,r,r,r,r,Q,!*q,!r,!*f,?r,?*f") - (match_operand:QI 1 "move_src_operand" - "r,J,N,K,RQ,rM,!rM,!*q,!*fM,*f,r"))] - "(register_operand (operands[0], QImode) - || reg_or_0_operand (operands[1], QImode)) - && !TARGET_SOFT_FLOAT - && !TARGET_64BIT" - "@ - copy %1,%0 - ldi %1,%0 - ldil L'%1,%0 - {zdepi|depwi,z} %Z1,%0 - ldb%M1 %1,%0 - stb%M0 %r1,%0 - mtsar %r1 - {mfctl|mfctl,w} %%sar,%0 - fcpy,sgl %f1,%0 - {fstws|fstw} %1,-16(%%sp)\n\t{ldws|ldw} -16(%%sp),%0 - {stws|stw} %1,-16(%%sp)\n\t{fldws|fldw} -16(%%sp),%0" - [(set_attr "type" "move,move,move,shift,load,store,move,move,move,move,move") - (set_attr "pa_combine_type" "addmove") - (set_attr "length" "4,4,4,4,4,4,4,4,4,8,8")]) - -(define_insn "" - [(set (match_operand:QI 0 "move_dest_operand" - "=r,r,r,r,r,Q,!*q,!r,!*f") - (match_operand:QI 1 "move_src_operand" - "r,J,N,K,RQ,rM,!rM,!*q,!*fM"))] - "(register_operand (operands[0], QImode) - || reg_or_0_operand (operands[1], QImode)) - && !TARGET_SOFT_FLOAT - && TARGET_64BIT" - "@ - copy %1,%0 - ldi %1,%0 - ldil L'%1,%0 - {zdepi|depwi,z} %Z1,%0 - ldb%M1 %1,%0 - stb%M0 %r1,%0 - mtsar %r1 - {mfctl|mfctl,w} %%sar,%0 - fcpy,sgl %f1,%0" - [(set_attr "type" "move,move,move,shift,load,store,move,move,move") - (set_attr "pa_combine_type" "addmove") - (set_attr "length" "4,4,4,4,4,4,4,4,4")]) - -(define_insn "" - [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,r,r,Q,!*q,!r") (match_operand:QI 1 "move_src_operand" "r,J,N,K,RQ,rM,!rM,!*q"))] "(register_operand (operands[0], QImode) - || reg_or_0_operand (operands[1], QImode)) - && TARGET_SOFT_FLOAT" + || reg_or_0_operand (operands[1], QImode))" "@ copy %1,%0 ldi %1,%0 diff --git a/gcc/config/pa/pa32-regs.h b/gcc/config/pa/pa32-regs.h index a17c117726a..97f48c768b6 100644 --- a/gcc/config/pa/pa32-regs.h +++ b/gcc/config/pa/pa32-regs.h @@ -172,8 +172,7 @@ #define VALID_FP_MODE_P(MODE) \ ((MODE) == SFmode || (MODE) == DFmode \ || (MODE) == SCmode || (MODE) == DCmode \ - || (MODE) == QImode || (MODE) == HImode || (MODE) == SImode \ - || (TARGET_PA_11 && (MODE) == DImode)) + || (MODE) == SImode || (TARGET_PA_11 && (MODE) == DImode)) /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. @@ -288,6 +287,11 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS, {0x00000000, 0x00000000, 0x01000000}, /* SHIFT_REGS */ \ {0xfffffffe, 0xffffffff, 0x01ffffff}} /* ALL_REGS */ +/* Defines invalid mode changes. */ + +#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ + pa_cannot_change_mode_class (FROM, TO, CLASS) + /* Return the class number of the smallest class containing reg number REGNO. This could be a conditional expression or could index an array. */ diff --git a/gcc/config/pa/pa64-regs.h b/gcc/config/pa/pa64-regs.h index a9ad8b60e8f..b79dbc98e42 100644 --- a/gcc/config/pa/pa64-regs.h +++ b/gcc/config/pa/pa64-regs.h @@ -156,8 +156,7 @@ along with GCC; see the file COPYING3. If not see #define VALID_FP_MODE_P(MODE) \ ((MODE) == SFmode || (MODE) == DFmode \ || (MODE) == SCmode || (MODE) == DCmode \ - || (MODE) == QImode || (MODE) == HImode || (MODE) == SImode \ - || (MODE) == DImode) + || (MODE) == SImode || (MODE) == DImode) /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. On the HP-PA, the cpu registers can hold any mode. We @@ -242,17 +241,10 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS, {0x00000000, 0x10000000}, /* SHIFT_REGS */ \ {0xfffffffe, 0x1fffffff}} /* ALL_REGS */ -/* Defines invalid mode changes. +/* Defines invalid mode changes. */ - SImode loads to floating-point registers are not zero-extended. - The definition for LOAD_EXTEND_OP specifies that integer loads - narrower than BITS_PER_WORD will be zero-extended. As a result, - we inhibit changes from SImode unless they are to a mode that is - identical in size. */ - -#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ - ((FROM) == SImode && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \ - ? reg_classes_intersect_p (CLASS, FP_REGS) : 0) +#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ + pa_cannot_change_mode_class (FROM, TO, CLASS) /* Return the class number of the smallest class containing reg number REGNO. This could be a conditional expression diff --git a/gcc/config/pa/som.h b/gcc/config/pa/som.h index 22bda046912..5d1c054a3eb 100644 --- a/gcc/config/pa/som.h +++ b/gcc/config/pa/som.h @@ -335,3 +335,7 @@ do { \ /* We can't handle weak aliases, and therefore can't support pragma weak. Suppress the use of pragma weak in gthr-dce.h and gthr-posix.h. */ #define GTHREAD_USE_WEAK 0 + +/* Shared library suffix. Collect2 strips the version string after + this suffix when generating constructor/destructor names. */ +#define SHLIB_SUFFIX ".sl" diff --git a/gcc/config/rs6000/aix61.h b/gcc/config/rs6000/aix61.h new file mode 100644 index 00000000000..64064074fea --- /dev/null +++ b/gcc/config/rs6000/aix61.h @@ -0,0 +1,196 @@ +/* Definitions of target machine for GNU compiler, + for IBM RS/6000 POWER running AIX V6.1. + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + Free Software Foundation, Inc. + Contributed by David Edelsohn (edelsohn@gnu.org). + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +/* Sometimes certain combinations of command options do not make sense + on a particular target machine. You can define a macro + `OVERRIDE_OPTIONS' to take account of this. This macro, if + defined, is executed once just after all the command options have + been parsed. + + The macro SUBTARGET_OVERRIDE_OPTIONS is provided for subtargets, to + get control. */ + +#define NON_POWERPC_MASKS (MASK_POWER | MASK_POWER2) +#define SUBTARGET_OVERRIDE_OPTIONS \ +do { \ + if (TARGET_64BIT && (target_flags & NON_POWERPC_MASKS)) \ + { \ + target_flags &= ~NON_POWERPC_MASKS; \ + warning (0, "-maix64 and POWER architecture are incompatible"); \ + } \ + if (TARGET_64BIT && ! TARGET_POWERPC64) \ + { \ + target_flags |= MASK_POWERPC64; \ + warning (0, "-maix64 requires PowerPC64 architecture remain enabled"); \ + } \ + if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128) \ + { \ + rs6000_long_double_type_size = 64; \ + if (rs6000_explicit_options.long_double) \ + warning (0, "soft-float and long-double-128 are incompatible"); \ + } \ + if (TARGET_POWERPC64 && ! TARGET_64BIT) \ + { \ + error ("-maix64 required: 64-bit computation with 32-bit addressing not yet supported"); \ + } \ +} while (0); + +#undef ASM_SPEC +#define ASM_SPEC "-u %{maix64:-a64 %{!mcpu*:-mppc64}} %(asm_cpu)" + +/* Common ASM definitions used by ASM_SPEC amongst the various targets + for handling -mcpu=xxx switches. */ +#undef ASM_CPU_SPEC +#define ASM_CPU_SPEC \ +"%{!mcpu*: %{!maix64: \ + %{mpowerpc64: -mppc64} \ + %{!mpower64: %(asm_default)}}} \ +%{mcpu=power3: -m620} \ +%{mcpu=power4: -mpwr4} \ +%{mcpu=power5: -mpwr5} \ +%{mcpu=power5+: -mpwr5x} \ +%{mcpu=power6: -mpwr6} \ +%{mcpu=power6x: -mpwr6} \ +%{mcpu=powerpc: -mppc} \ +%{mcpu=rs64a: -mppc} \ +%{mcpu=603: -m603} \ +%{mcpu=603e: -m603} \ +%{mcpu=604: -m604} \ +%{mcpu=604e: -m604} \ +%{mcpu=620: -m620} \ +%{mcpu=630: -m620} \ +%{mcpu=970: -m970} \ +%{mcpu=G5: -m970}" + +#undef ASM_DEFAULT_SPEC +#define ASM_DEFAULT_SPEC "-mppc" + +#undef TARGET_OS_CPP_BUILTINS +#define TARGET_OS_CPP_BUILTINS() \ + do \ + { \ + builtin_define ("_AIX43"); \ + builtin_define ("_AIX51"); \ + builtin_define ("_AIX52"); \ + builtin_define ("_AIX53"); \ + builtin_define ("_AIX61"); \ + TARGET_OS_AIX_CPP_BUILTINS (); \ + } \ + while (0) + +#undef CPP_SPEC +#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} \ + %{ansi: -D_ANSI_C_SOURCE} \ + %{maix64: -D__64BIT__} \ + %{mpe: -I/usr/lpp/ppe.poe/include} \ + %{pthread: -D_THREAD_SAFE}" + +/* The GNU C++ standard library requires that these macros be + defined. Synchronize with libstdc++ os_defines.h. */ +#undef CPLUSPLUS_CPP_SPEC +#define CPLUSPLUS_CPP_SPEC \ + "-D_ALL_SOURCE -D__COMPATMATH__ \ + %{maix64: -D__64BIT__} \ + %{mpe: -I/usr/lpp/ppe.poe/include} \ + %{pthread: -D_THREAD_SAFE}" + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS) + +#undef PROCESSOR_DEFAULT +#define PROCESSOR_DEFAULT PROCESSOR_POWER5 +#undef PROCESSOR_DEFAULT64 +#define PROCESSOR_DEFAULT64 PROCESSOR_POWER5 + +#undef TARGET_POWER +#define TARGET_POWER 0 + +/* Define this macro as a C expression for the initializer of an + array of string to tell the driver program which options are + defaults for this target and thus do not need to be handled + specially when using `MULTILIB_OPTIONS'. + + Do not define this macro if `MULTILIB_OPTIONS' is not defined in + the target makefile fragment or if none of the options listed in + `MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */ + +#undef MULTILIB_DEFAULTS + +#undef LIB_SPEC +#define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\ + %{p:-L/lib/profiled -L/usr/lib/profiled}\ + %{!maix64:%{!shared:%{g*:-lg}}}\ + %{mpe:-L/usr/lpp/ppe.poe/lib -lmpi -lvtd}\ + %{pthread:-lpthreads} -lc" + +#undef LINK_SPEC +#define LINK_SPEC "-bpT:0x10000000 -bpD:0x20000000 %{!r:-btextro} -bnodelcsect\ + %{static:-bnso %(link_syscalls) } %{shared:-bM:SRE %{!e:-bnoentry}}\ + %{!maix64:%{!shared:%{g*: %(link_libg) }}} %{maix64:-b64}\ + %{mpe:-binitfini:poe_remote_main}" + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{!shared:\ + %{maix64:%{pg:gcrt0_64%O%s}%{!pg:%{p:mcrt0_64%O%s}%{!p:crt0_64%O%s}}}\ + %{!maix64:\ + %{pthread:%{pg:gcrt0_r%O%s}%{!pg:%{p:mcrt0_r%O%s}%{!p:crt0_r%O%s}}}\ + %{!pthread:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}}}" + +/* AIX V5 typedefs ptrdiff_t as "long" while earlier releases used "int". */ + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "long int" + +/* Type used for wchar_t, as a string used in a declaration. */ +#undef WCHAR_TYPE +#define WCHAR_TYPE (!TARGET_64BIT ? "short unsigned int" : "unsigned int") + +/* Width of wchar_t in bits. */ +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE (!TARGET_64BIT ? 16 : 32) + +/* AIX V5 uses PowerPC nop (ori 0,0,0) instruction as call glue for PowerPC + and "cror 31,31,31" for POWER architecture. */ + +#undef RS6000_CALL_GLUE +#define RS6000_CALL_GLUE "{cror 31,31,31|nop}" + +/* AIX 4.2 and above provides initialization and finalization function + support from linker command line. */ +#undef HAS_INIT_SECTION +#define HAS_INIT_SECTION + +#undef LD_INIT_SWITCH +#define LD_INIT_SWITCH "-binitfini" + +/* AIX 5.2 has the float and long double forms of math functions. */ +#undef TARGET_C99_FUNCTIONS +#define TARGET_C99_FUNCTIONS 1 + +#ifndef _AIX52 +extern long long int atoll(const char *); +#endif + +/* This target uses the aix64.opt file. */ +#define TARGET_USES_AIX64_OPT 1 + +#define RS6000_DEFAULT_LONG_DOUBLE_SIZE 128 diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c index ebdb7a338b5..bd1cd54d2fd 100644 --- a/gcc/config/rs6000/rs6000-c.c +++ b/gcc/config/rs6000/rs6000-c.c @@ -131,7 +131,10 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile) RS6000_CPU_CPP_ENDIAN_BUILTINS(); if (TARGET_LONG_DOUBLE_128) - builtin_define ("__LONG_DOUBLE_128__"); + { + builtin_define ("__LONG_DOUBLE_128__"); + builtin_define ("__LONGDOUBLE128"); + } switch (rs6000_current_abi) { diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 58a31396638..865690d10ab 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -10074,6 +10074,7 @@ "" " { + operands[1] = force_reg (Pmode, operands[1]); operands[2] = gen_reg_rtx (Pmode); operands[3] = gen_frame_mem (Pmode, operands[0]); operands[4] = gen_frame_mem (Pmode, operands[1]); diff --git a/gcc/config/rs6000/t-linux64 b/gcc/config/rs6000/t-linux64 index a2c04f928e6..2a2e7b0cdc0 100644 --- a/gcc/config/rs6000/t-linux64 +++ b/gcc/config/rs6000/t-linux64 @@ -7,12 +7,19 @@ LIB2FUNCS_EXTRA := $(sort $(LIB2FUNCS_EXTRA)) TARGET_LIBGCC2_CFLAGS += -mno-minimal-toc +# On Debian, Ubuntu and other derivative distributions, the 32bit libraries +# are found in /lib32 and /usr/lib32, /lib64 and /usr/lib64 are symlinks to +# /lib and /usr/lib, while other distributions install libraries into /lib64 +# and /usr/lib64. The LSB does not enforce the use of /lib64 and /usr/lib64, +# it doesn't tell anything about the 32bit libraries on those systems. Set +# MULTILIB_OSDIRNAMES according to what is found on the target. + MULTILIB_OPTIONS = m64/m32 msoft-float MULTILIB_DIRNAMES = 64 32 nof MULTILIB_EXTRA_OPTS = fPIC mstrict-align MULTILIB_EXCEPTIONS = m64/msoft-float MULTILIB_EXCLUSIONS = m64/!m32/msoft-float -MULTILIB_OSDIRNAMES = ../lib64 ../lib nof +MULTILIB_OSDIRNAMES = ../lib64 $(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib) nof MULTILIB_MATCHES = $(MULTILIB_MATCHES_FLOAT) softfp_wrap_start := '\#ifndef __powerpc64__' diff --git a/gcc/config/s390/constraints.md b/gcc/config/s390/constraints.md index cdafa2fad31..92fd3254ca5 100644 --- a/gcc/config/s390/constraints.md +++ b/gcc/config/s390/constraints.md @@ -49,7 +49,7 @@ ;; O -- Multiple letter constraint followed by 1 parameter. ;; s: Signed extended immediate value (-2G .. 2G-1). ;; p: Positive extended immediate value (0 .. 4G-1). -;; n: Negative extended immediate value (-4G .. -1). +;; n: Negative extended immediate value (-4G+1 .. -1). ;; These constraints do not accept any operand if the machine does ;; not provide the extended-immediate facility. ;; P -- Any integer constant that can be loaded without literal pool. @@ -337,7 +337,7 @@ (define_constraint "On" "@internal - Negative extended immediate value (-4G .. -1). + Negative extended immediate value (-4G+1 .. -1). This constraint will only match if the machine provides the extended-immediate facility." (and (match_code "const_int") diff --git a/gcc/config/s390/fixdfdi.h b/gcc/config/s390/fixdfdi.h index f3e48ac8f9d..04aa4ed738b 100644 --- a/gcc/config/s390/fixdfdi.h +++ b/gcc/config/s390/fixdfdi.h @@ -77,13 +77,15 @@ __fixunstfdi (long double a1) if ((EXPD(dl1) == 0x7fff) && !FRACD_ZERO_P (dl1)) return 0x0ULL; - /* If the upper ll part of the mantissa isn't - zeroed out after shifting the number would be to large. */ - if (exp >= -HIGH_LL_FRAC_BITS) - return 0xFFFFFFFFFFFFFFFFULL; - + /* One extra bit is needed for the unit bit which is appended by + MANTD_HIGH_LL on the left of the matissa. */ exp += HIGH_LL_FRAC_BITS + 1; + /* If the result would still need a left shift it will be to large + to be represented. */ + if (exp > 0) + return 0xFFFFFFFFFFFFFFFFULL; + l = MANTD_LOW_LL (dl1) >> (HIGH_LL_FRAC_BITS + 1) | MANTD_HIGH_LL (dl1) << (64 - (HIGH_LL_FRAC_BITS + 1)); @@ -117,7 +119,7 @@ union double_long { struct { SItype_x i[4]; /* 32 bit parts: 0 upper ... 3 lowest */ } l; - DItype_x ll[2]; /* 64 bit parts: 0 upper, 1 lower */ + UDItype_x ll[2]; /* 64 bit parts: 0 upper, 1 lower */ }; DItype_x __fixtfdi (long double a1); @@ -149,17 +151,21 @@ __fixtfdi (long double a1) if ((EXPD(dl1) == 0x7fff) && !FRACD_ZERO_P (dl1)) return 0x8000000000000000ULL; - /* If the upper ll part of the mantissa isn't - zeroed out after shifting the number would be to large. */ - if (exp >= -HIGH_LL_FRAC_BITS) + /* One extra bit is needed for the unit bit which is appended by + MANTD_HIGH_LL on the left of the matissa. */ + exp += HIGH_LL_FRAC_BITS + 1; + + /* If the result would still need a left shift it will be to large + to be represented. Compared to the unsigned variant we have to + take care that there is still space for the sign bit to be + applied. So we can only go on if there is a right-shift by one + or more. */ + if (exp >= 0) { - l = (long long)1 << 63; /* long int min */ + l = (long long)1 << 63; /* long long int min */ return SIGND (dl1) ? l : l - 1; } - /* The extra bit is needed for the sign bit. */ - exp += HIGH_LL_FRAC_BITS + 1; - l = MANTD_LOW_LL (dl1) >> (HIGH_LL_FRAC_BITS + 1) | MANTD_HIGH_LL (dl1) << (64 - (HIGH_LL_FRAC_BITS + 1)); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 10246e238db..355f257a919 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -2009,8 +2009,7 @@ s390_O_constraint_str (const char c, HOST_WIDE_INT value) || s390_single_part (GEN_INT (value), DImode, SImode, 0) == 1; case 'n': - return value == -1 - || s390_single_part (GEN_INT (value), DImode, SImode, -1) == 1; + return s390_single_part (GEN_INT (value - 1), DImode, SImode, -1) == 1; default: gcc_unreachable (); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index f567afbef69..43efeb3f744 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -3530,6 +3530,7 @@ find_barrier (int num_mova, rtx mova, rtx from) rtx barrier_before_mova = 0, found_barrier = 0, good_barrier = 0; int si_limit; int hi_limit; + rtx orig = from; /* For HImode: range is 510, add 4 because pc counts from address of second instruction after this one, subtract 2 for the jump instruction @@ -3753,7 +3754,8 @@ find_barrier (int num_mova, rtx mova, rtx from) /* If we exceeded the range, then we must back up over the last instruction we looked at. Otherwise, we just need to undo the NEXT_INSN at the end of the loop. */ - if (count_hi > hi_limit || count_si > si_limit) + if (PREV_INSN (from) != orig + && (count_hi > hi_limit || count_si > si_limit)) from = PREV_INSN (PREV_INSN (from)); else from = PREV_INSN (from); diff --git a/gcc/config/t-freebsd b/gcc/config/t-freebsd index 211dbdf6b71..0680618a6ec 100644 --- a/gcc/config/t-freebsd +++ b/gcc/config/t-freebsd @@ -1,5 +1,5 @@ # Compile crtbeginS.o and crtendS.o with pic. -CRTSTUFF_T_CFLAGS_S = -fPIC +CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC # Compile libgcc.a with pic. TARGET_LIBGCC2_CFLAGS += -fPIC diff --git a/gcc/config/t-libc-ok b/gcc/config/t-libc-ok index 4dae812ae31..561ee0b31d1 100644 --- a/gcc/config/t-libc-ok +++ b/gcc/config/t-libc-ok @@ -1 +1 @@ -CRTSTUFF_T_CFLAGS_S=-fPIC +CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC diff --git a/gcc/config/t-lynx b/gcc/config/t-lynx index a14a53c614e..3a6a5d871e4 100644 --- a/gcc/config/t-lynx +++ b/gcc/config/t-lynx @@ -1,5 +1,5 @@ # Compile crtbeginS.o and crtendS.o with pic. -CRTSTUFF_T_CFLAGS_S = -fPIC +CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC # Compile libgcc2.a with pic. TARGET_LIBGCC2_CFLAGS = -fPIC diff --git a/gcc/config/t-netbsd b/gcc/config/t-netbsd index 843e4100df7..34949e12858 100644 --- a/gcc/config/t-netbsd +++ b/gcc/config/t-netbsd @@ -1,2 +1,2 @@ # Always build crtstuff with PIC. -CRTSTUFF_T_CFLAGS = -fPIC +CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC diff --git a/gcc/config/t-svr4 b/gcc/config/t-svr4 index 52c9b28fc9a..3ea1174580d 100644 --- a/gcc/config/t-svr4 +++ b/gcc/config/t-svr4 @@ -4,7 +4,7 @@ # we will be doing that, we just always use -fPIC when compiling the # routines in crtstuff.c. Likewise for libgcc2.c. -CRTSTUFF_T_CFLAGS = -fPIC +CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC TARGET_LIBGCC2_CFLAGS = -fPIC # See all the declarations. diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index 91ff1096451..f9a90c3b1f1 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -1579,6 +1579,8 @@ override_options (void) /* There's no need for -fPIC (as opposed to -fpic) on Xtensa. */ if (flag_pic > 1) flag_pic = 1; + if (flag_pic && !flag_pie) + flag_shlib = 1; /* Hot/cold partitioning does not work on this architecture, because of constant pools (the load instruction cannot necessarily reach that far). @@ -1954,12 +1956,13 @@ xtensa_expand_prologue (void) { HOST_WIDE_INT total_size; rtx size_rtx; + rtx insn, note_rtx; total_size = compute_frame_size (get_frame_size ()); size_rtx = GEN_INT (total_size); if (total_size < (1 << (12+3))) - emit_insn (gen_entry (size_rtx, size_rtx)); + insn = emit_insn (gen_entry (size_rtx, size_rtx)); else { /* Use a8 as a temporary since a0-a7 may be live. */ @@ -1967,14 +1970,14 @@ xtensa_expand_prologue (void) emit_insn (gen_entry (size_rtx, GEN_INT (MIN_FRAME_SIZE))); emit_move_insn (tmp_reg, GEN_INT (total_size - MIN_FRAME_SIZE)); emit_insn (gen_subsi3 (tmp_reg, stack_pointer_rtx, tmp_reg)); - emit_move_insn (stack_pointer_rtx, tmp_reg); + insn = emit_insn (gen_movsi (stack_pointer_rtx, tmp_reg)); } if (frame_pointer_needed) { if (cfun->machine->set_frame_ptr_insn) { - rtx first, insn; + rtx first; push_topmost_sequence (); first = get_insns (); @@ -1993,8 +1996,20 @@ xtensa_expand_prologue (void) } } else - emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); + insn = emit_insn (gen_movsi (hard_frame_pointer_rtx, + stack_pointer_rtx)); } + + /* Create a note to describe the CFA. Because this is only used to set + DW_AT_frame_base for debug info, don't bother tracking changes through + each instruction in the prologue. It just takes up space. */ + note_rtx = gen_rtx_SET (VOIDmode, (frame_pointer_needed + ? hard_frame_pointer_rtx + : stack_pointer_rtx), + plus_constant (stack_pointer_rtx, -total_size)); + RTX_FRAME_RELATED_P (insn) = 1; + REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, + note_rtx, REG_NOTES (insn)); } @@ -2371,7 +2386,8 @@ xtensa_secondary_reload_class (enum reg_class class, if (!isoutput) { - if (class == FP_REGS && constantpool_mem_p (x)) + if ((class == FP_REGS || GET_MODE_SIZE (mode) < UNITS_PER_WORD) + && constantpool_mem_p (x)) return RL_REGS; } diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h index 3c019a8fd23..48c6f8386ad 100644 --- a/gcc/config/xtensa/xtensa.h +++ b/gcc/config/xtensa/xtensa.h @@ -1208,8 +1208,12 @@ typedef struct xtensa_args /* How to start an assembler comment. */ #define ASM_COMMENT_START "#" -/* Exception handling TODO!! */ -#define DWARF_UNWIND_INFO 0 +/* Generate DWARF2 unwind info to get the DW_AT_frame_base set correctly, + even though we don't yet use it for unwinding. */ +#define MUST_USE_SJLJ_EXCEPTIONS 1 +#define DWARF2_UNWIND_INFO 1 +#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, 0) +#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (0) /* Xtensa constant pool breaks the devices in crtstuff.c to control section in where code resides. We have to write it as asm code. Use |