aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/alpha/alpha.c13
-rw-r--r--gcc/config/arm/rtems-elf.h1
-rw-r--r--gcc/config/avr/avr.c8
-rw-r--r--gcc/config/avr/avr.h13
-rw-r--r--gcc/config/avr/t-avr8
-rw-r--r--gcc/config/fr30/fr30.c48
-rw-r--r--gcc/config/h8300/t-rtems4
-rw-r--r--gcc/config/i386/driver-i386.c4
-rw-r--r--gcc/config/i386/i386.c2
-rw-r--r--gcc/config/i386/i386.md13
-rw-r--r--gcc/config/i386/netware-libgcc.exp1
-rw-r--r--gcc/config/i386/t-crtstuff7
-rw-r--r--gcc/config/i386/t-linux6415
-rw-r--r--gcc/config/ia64/ia64.c13
-rw-r--r--gcc/config/m68k/t-rtems13
-rw-r--r--gcc/config/mips/mips-protos.h4
-rw-r--r--gcc/config/mips/mips.c159
-rw-r--r--gcc/config/mips/mips.h12
-rw-r--r--gcc/config/mips/mips.md122
-rw-r--r--gcc/config/pa/pa-64.h14
-rw-r--r--gcc/config/pa/pa-hpux.h2
-rw-r--r--gcc/config/pa/pa-hpux10.h2
-rw-r--r--gcc/config/pa/pa-hpux11.h16
-rw-r--r--gcc/config/pa/pa-protos.h3
-rw-r--r--gcc/config/pa/pa.c151
-rw-r--r--gcc/config/pa/pa.h79
-rw-r--r--gcc/config/pa/pa.md102
-rw-r--r--gcc/config/pa/pa32-regs.h8
-rw-r--r--gcc/config/pa/pa64-regs.h16
-rw-r--r--gcc/config/pa/som.h4
-rw-r--r--gcc/config/rs6000/aix61.h196
-rw-r--r--gcc/config/rs6000/rs6000-c.c5
-rw-r--r--gcc/config/rs6000/rs6000.md1
-rw-r--r--gcc/config/rs6000/t-linux649
-rw-r--r--gcc/config/s390/constraints.md4
-rw-r--r--gcc/config/s390/fixdfdi.h32
-rw-r--r--gcc/config/s390/s390.c3
-rw-r--r--gcc/config/sh/sh.c4
-rw-r--r--gcc/config/t-freebsd2
-rw-r--r--gcc/config/t-libc-ok2
-rw-r--r--gcc/config/t-lynx2
-rw-r--r--gcc/config/t-netbsd2
-rw-r--r--gcc/config/t-svr42
-rw-r--r--gcc/config/xtensa/xtensa.c26
-rw-r--r--gcc/config/xtensa/xtensa.h8
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