aboutsummaryrefslogtreecommitdiff
path: root/contrib/gcc/config/sparc
diff options
context:
space:
mode:
authorDavid E. O'Brien <obrien@FreeBSD.org>2002-05-09 20:02:13 +0000
committerDavid E. O'Brien <obrien@FreeBSD.org>2002-05-09 20:02:13 +0000
commit909b40107406b30c899ce55c127d8761e8b09ca8 (patch)
tree29a0f0a6c79a69ecc64f612947a0fe5904311713 /contrib/gcc/config/sparc
parent1952e2e1c1be6f107fa3ce8b10025cfd1cd7943b (diff)
Gcc 3.1.0 pre-release from the FSF anoncvs repo on 9-May-2002 15:57:15 EDT.
Notes
Notes: svn path=/vendor/gcc/dist/; revision=96263
Diffstat (limited to 'contrib/gcc/config/sparc')
-rw-r--r--contrib/gcc/config/sparc/aout.h2
-rw-r--r--contrib/gcc/config/sparc/crtfastmath.c54
-rw-r--r--contrib/gcc/config/sparc/elf.h4
-rw-r--r--contrib/gcc/config/sparc/freebsd.h28
-rw-r--r--contrib/gcc/config/sparc/gmon-sol2.c4
-rw-r--r--contrib/gcc/config/sparc/libgcc-sparc-glibc.ver28
-rw-r--r--contrib/gcc/config/sparc/linux-aout.h6
-rw-r--r--contrib/gcc/config/sparc/linux.h84
-rw-r--r--contrib/gcc/config/sparc/linux64.h153
-rw-r--r--contrib/gcc/config/sparc/lite.h2
-rw-r--r--contrib/gcc/config/sparc/litecoff.h2
-rw-r--r--contrib/gcc/config/sparc/liteelf.h2
-rw-r--r--contrib/gcc/config/sparc/netbsd-elf.h344
-rw-r--r--contrib/gcc/config/sparc/netbsd.h9
-rw-r--r--contrib/gcc/config/sparc/pbd.h3
-rw-r--r--contrib/gcc/config/sparc/rtems.h9
-rw-r--r--contrib/gcc/config/sparc/rtemself.h11
-rw-r--r--contrib/gcc/config/sparc/sol2-64.h25
-rw-r--r--contrib/gcc/config/sparc/sol2-bi.h279
-rw-r--r--contrib/gcc/config/sparc/sol2-gas-bi.h5
-rw-r--r--contrib/gcc/config/sparc/sol2-gld-bi.h9
-rw-r--r--contrib/gcc/config/sparc/sol2-gld.h6
-rw-r--r--contrib/gcc/config/sparc/sol2.h36
-rw-r--r--contrib/gcc/config/sparc/sol27-sld.h8
-rw-r--r--contrib/gcc/config/sparc/sp64-aout.h2
-rw-r--r--contrib/gcc/config/sparc/sp64-elf.h6
-rw-r--r--contrib/gcc/config/sparc/sp86x-aout.h2
-rw-r--r--contrib/gcc/config/sparc/sp86x-elf.h2
-rw-r--r--contrib/gcc/config/sparc/sparc-protos.h20
-rw-r--r--contrib/gcc/config/sparc/sparc.c1436
-rw-r--r--contrib/gcc/config/sparc/sparc.h380
-rw-r--r--contrib/gcc/config/sparc/sparc.md912
-rw-r--r--contrib/gcc/config/sparc/splet.h2
-rw-r--r--contrib/gcc/config/sparc/t-crtfm4
-rw-r--r--contrib/gcc/config/sparc/t-elf12
-rw-r--r--contrib/gcc/config/sparc/t-linux648
-rw-r--r--contrib/gcc/config/sparc/t-netbsd646
-rw-r--r--contrib/gcc/config/sparc/t-sol2-642
-rw-r--r--contrib/gcc/config/sparc/vxsim.h3
-rw-r--r--contrib/gcc/config/sparc/vxsparc64.h2
40 files changed, 2588 insertions, 1324 deletions
diff --git a/contrib/gcc/config/sparc/aout.h b/contrib/gcc/config/sparc/aout.h
index fd84d75244b0..3a2273f488bf 100644
--- a/contrib/gcc/config/sparc/aout.h
+++ b/contrib/gcc/config/sparc/aout.h
@@ -88,7 +88,7 @@ do { \
pointer is really %i7. */
#define DBX_REGISTER_NUMBER(REGNO) \
- (TARGET_FLAT && REGNO == FRAME_POINTER_REGNUM ? 31 : REGNO)
+ (TARGET_FLAT && (REGNO) == HARD_FRAME_POINTER_REGNUM ? 31 : REGNO)
/* This is how to output a note to DBX telling it the line number
to which the following sequence of instructions corresponds.
diff --git a/contrib/gcc/config/sparc/crtfastmath.c b/contrib/gcc/config/sparc/crtfastmath.c
new file mode 100644
index 000000000000..df3f907bb336
--- /dev/null
+++ b/contrib/gcc/config/sparc/crtfastmath.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ * Contributed by David S. Miller (davem@redhat.com)
+ *
+ * This file 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 2, or (at your option) any
+ * later version.
+ *
+ * In addition to the permissions in the GNU General Public License, the
+ * Free Software Foundation gives you unlimited permission to link the
+ * compiled version of this file with other programs, and to distribute
+ * those programs without any restriction coming from the use of this
+ * file. (The General Public License restrictions do apply in other
+ * respects; for example, they cover modification of the file, and
+ * distribution when not linked into another program.)
+ *
+ * This file 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 this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * As a special exception, if you link this library with files
+ * compiled with GCC to produce an executable, this does not cause
+ * the resulting executable to be covered by the GNU General Public License.
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ */
+
+#define FPRS_NS (1 << 22) /* Non-Standard fpu results */
+
+static void __attribute__((constructor))
+set_fast_math (void)
+{
+ unsigned int fsr;
+
+ /* This works for the 64-bit case because, even if 32-bit ld/st of
+ the fsr register modified the upper 32-bit, the only thing up there
+ are the 3 other condition codes which are "do not care" at the time
+ that this runs. */
+
+ __asm__("st %%fsr, %0"
+ : "=m" (fsr));
+
+ fsr |= FPRS_NS;
+
+ __asm__("ld %0, %%fsr"
+ : : "m" (fsr));
+}
diff --git a/contrib/gcc/config/sparc/elf.h b/contrib/gcc/config/sparc/elf.h
index 20bea8209517..d2d3a0b74d36 100644
--- a/contrib/gcc/config/sparc/elf.h
+++ b/contrib/gcc/config/sparc/elf.h
@@ -26,7 +26,9 @@ Boston, MA 02111-1307, USA. */
#define STARTFILE_SPEC "crt0.o%s crti.o%s crtbegin.o%s"
#undef ENDFILE_SPEC
-#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
+#define ENDFILE_SPEC \
+ "%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
+ crtend.o%s crtn.o%s"
/* Use the default. */
#undef LINK_SPEC
diff --git a/contrib/gcc/config/sparc/freebsd.h b/contrib/gcc/config/sparc/freebsd.h
index 314b07bc825f..54b5f0ae5c49 100644
--- a/contrib/gcc/config/sparc/freebsd.h
+++ b/contrib/gcc/config/sparc/freebsd.h
@@ -1,5 +1,5 @@
/* Definitions for Sun Sparc64 running FreeBSD using the ELF format
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
Contributed by David E. O'Brien <obrien@FreeBSD.org> and BSDi.
This file is part of GNU CC.
@@ -26,8 +26,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES FBSD_CPP_PREDEFINES
-#define LINK_SPEC "-m elf64_sparc %(link_arch) \
- %{!mno-relax:%{!r:-relax} \
+#define LINK_SPEC "%(link_arch) \
+ %{!mno-relax:%{!r:-relax}} \
%{p:%e`-p' not supported; use `-pg' and gprof(1)} \
%{Wl,*:%*} \
%{assert*} %{R*} %{rpath*} %{defsym*} \
@@ -91,22 +91,19 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
- (MASK_V9 + MASK_64BIT + MASK_PTR64 + MASK_VIS + MASK_FASTER_STRUCTS \
- + MASK_STACK_BIAS + MASK_APP_REGS /* + MASK_EPILOGUE */ + MASK_FPU \
+ (MASK_V9 + MASK_64BIT + MASK_PTR64 /* + MASK_FASTER_STRUCTS */ \
+ + MASK_STACK_BIAS + MASK_APP_REGS + MASK_FPU \
+ MASK_LONG_DOUBLE_128 /* + MASK_HARD_QUAD */)
/* The default code model. */
#undef SPARC_DEFAULT_CMODEL
-#define SPARC_DEFAULT_CMODEL CM_MEDMID
+#define SPARC_DEFAULT_CMODEL CM_MEDLOW
/************************[ Assembler stuff ]********************************/
-/* XXX */
-#if 0
-#undef ASM_CPU_DEFAULT_SPEC
-#define ASM_CPU_DEFAULT_SPEC "-Av9a"
-#endif
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
/* XXX2 */
/* This is how to output a definition of an internal numbered label where
@@ -151,3 +148,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
RELATIVE relocations. */
/* #define DWARF_OFFSET_SIZE PTR_SIZE */
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ "%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s}" \
+ FBSD_ENDFILE_SPEC
+
+/* We use GNU ld so undefine this so that attribute((init_priority)) works. */
+#undef CTORS_SECTION_ASM_OP
+#undef DTORS_SECTION_ASM_OP
diff --git a/contrib/gcc/config/sparc/gmon-sol2.c b/contrib/gcc/config/sparc/gmon-sol2.c
index 6d6696644d91..bcb0c060358a 100644
--- a/contrib/gcc/config/sparc/gmon-sol2.c
+++ b/contrib/gcc/config/sparc/gmon-sol2.c
@@ -291,8 +291,10 @@ static void internal_mcount(selfpc, frompcindex)
if(!already_setup) {
extern char etext[];
+ extern char _start[];
+ extern char _init[];
already_setup = 1;
- monstartup(0, (char *)etext);
+ monstartup(_start < _init ? _start : _init, etext);
#ifdef USE_ONEXIT
on_exit(_mcleanup, 0);
#else
diff --git a/contrib/gcc/config/sparc/libgcc-sparc-glibc.ver b/contrib/gcc/config/sparc/libgcc-sparc-glibc.ver
new file mode 100644
index 000000000000..e3ba0bbdb65b
--- /dev/null
+++ b/contrib/gcc/config/sparc/libgcc-sparc-glibc.ver
@@ -0,0 +1,28 @@
+# In order to work around the very problems that force us to now generally
+# create a libgcc.so, glibc reexported a number of routines from libgcc.a.
+# By now choosing the same version tags for these specific routines, we
+# maintain enough binary compatibility to allow future versions of glibc
+# to defer implementation of these routines to libgcc.so via DT_AUXILIARY.
+
+%ifdef __arch64__
+%define GLIBC_VER GLIBC_2.2
+%else
+%define GLIBC_VER GLIBC_2.0
+%endif
+%inherit GCC_3.0 GLIBC_VER
+GLIBC_VER {
+ # Sampling of DImode arithmetic used by (at least) i386 and m68k.
+ __divdi3
+ __moddi3
+ __udivdi3
+ __umoddi3
+
+ # Exception handling support functions used by most everyone.
+ __register_frame
+ __register_frame_table
+ __deregister_frame
+ __register_frame_info
+ __deregister_frame_info
+ __frame_state_for
+ __register_frame_info_table
+}
diff --git a/contrib/gcc/config/sparc/linux-aout.h b/contrib/gcc/config/sparc/linux-aout.h
index 55c833f24a87..41d38773ecf9 100644
--- a/contrib/gcc/config/sparc/linux-aout.h
+++ b/contrib/gcc/config/sparc/linux-aout.h
@@ -1,5 +1,5 @@
/* Definitions for SPARC running Linux-based GNU systems with a.out.
- Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1999, 2002 Free Software Foundation, Inc.
Contributed by Eddie C. Dost (ecd@skynet.be)
This file is part of GNU CC.
@@ -59,10 +59,8 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
-#undef MAX_WCHAR_TYPE_SIZE
-
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dunix -Dsparc -Dlinux -Asystem=unix -Asystem=posix"
+#define CPP_PREDEFINES "-Dunix -Dsparc -D__gnu_linux__ -Dlinux -Asystem=unix -Asystem=posix"
#undef CPP_SUBTARGET_SPEC
#define CPP_SUBTARGET_SPEC \
diff --git a/contrib/gcc/config/sparc/linux.h b/contrib/gcc/config/sparc/linux.h
index d46413339c1d..b93b46cf46ca 100644
--- a/contrib/gcc/config/sparc/linux.h
+++ b/contrib/gcc/config/sparc/linux.h
@@ -1,5 +1,5 @@
/* Definitions for SPARC running Linux-based GNU systems with ELF.
- Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
Contributed by Eddie C. Dost (ecd@skynet.be)
This file is part of GNU CC.
@@ -62,7 +62,8 @@ Boston, MA 02111-1307, USA. */
#undef ENDFILE_SPEC
#define ENDFILE_SPEC \
- "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
+ "%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
+ %{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
/* This is for -profile to use -lc_p instead of -lc. */
#undef CC1_SPEC
@@ -97,10 +98,8 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
-#undef MAX_WCHAR_TYPE_SIZE
-
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__ELF__ -Dunix -D__sparc__ -Dlinux -Asystem=unix -Asystem=posix"
+#define CPP_PREDEFINES "-D__ELF__ -Dunix -D__sparc__ -D__gnu_linux__ -Dlinux -Asystem=unix -Asystem=posix"
#undef CPP_SUBTARGET_SPEC
#ifdef USE_GNULIBC_1
@@ -186,7 +185,7 @@ Boston, MA 02111-1307, USA. */
#undef ASM_SPEC
#define ASM_SPEC \
"%{V} %{v:%{!V:-V}} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s %{fpic:-K PIC} \
- %{fPIC:-K PIC} %(asm_relax)"
+ %{fPIC:-K PIC} %(asm_cpu) %(asm_relax)"
/* Same as sparc.h */
#undef DBX_REGISTER_NUMBER
@@ -204,6 +203,9 @@ do { \
#undef COMMON_ASM_OP
#define COMMON_ASM_OP "\t.common\t"
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
/* This is how to output a definition of an internal numbered label where
PREFIX is the class of label and NUM is the number within the class. */
@@ -247,3 +249,73 @@ do { \
#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
#endif
+/* Don't be different from other Linux platforms in this regard. */
+#define HANDLE_PRAGMA_PACK_PUSH_POP
+
+/* We use GNU ld so undefine this so that attribute((init_priority)) works. */
+#undef CTORS_SECTION_ASM_OP
+#undef DTORS_SECTION_ASM_OP
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
+ do { \
+ unsigned int *pc_ = (CONTEXT)->ra; \
+ int new_cfa_, i_, oldstyle_; \
+ int regs_off_, fpu_save_off_; \
+ int fpu_save_, this_cfa_; \
+ \
+ if (pc_[1] != 0x91d02010) /* ta 0x10 */ \
+ break; \
+ if (pc_[0] == 0x821020d8) /* mov NR_sigreturn, %g1 */ \
+ oldstyle_ = 1; \
+ else if (pc_[0] == 0x82102065) /* mov NR_rt_sigreturn, %g1 */ \
+ oldstyle_ = 0; \
+ else \
+ break; \
+ if (oldstyle_) \
+ { \
+ regs_off_ = 96; \
+ fpu_save_off_ = regs_off_ + (4 * 4) + (16 * 4); \
+ } \
+ else \
+ { \
+ regs_off_ = 96 + 128; \
+ fpu_save_off_ = regs_off_ + (4 * 4) + (16 * 4) + (2 * 4); \
+ } \
+ this_cfa_ = (int) (CONTEXT)->cfa; \
+ new_cfa_ = *(int *)(((CONTEXT)->cfa) + (regs_off_+(4*4)+(14 * 4))); \
+ fpu_save_ = *(int *)((this_cfa_) + (fpu_save_off_)); \
+ (FS)->cfa_how = CFA_REG_OFFSET; \
+ (FS)->cfa_reg = 14; \
+ (FS)->cfa_offset = new_cfa_ - (int) (CONTEXT)->cfa; \
+ for (i_ = 1; i_ < 16; ++i_) \
+ { \
+ if (i_ == 14) \
+ continue; \
+ (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[i_].loc.offset = \
+ this_cfa_ + (regs_off_+(4 * 4)+(i_ * 4)) - new_cfa_; \
+ } \
+ for (i_ = 0; i_ < 16; ++i_) \
+ { \
+ (FS)->regs.reg[i_ + 16].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[i_ + 16].loc.offset = \
+ this_cfa_ + (i_ * 4) - new_cfa_; \
+ } \
+ if (fpu_save_) \
+ { \
+ for (i_ = 0; i_ < 32; ++i_) \
+ { \
+ (FS)->regs.reg[i_ + 32].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[i_ + 32].loc.offset = \
+ (fpu_save_ + (i_ * 4)) - new_cfa_; \
+ } \
+ } \
+ /* Stick return address into %g0, same trick Alpha uses. */ \
+ (FS)->regs.reg[0].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[0].loc.offset = this_cfa_+(regs_off_+4)-new_cfa_; \
+ (FS)->retaddr_column = 0; \
+ goto SUCCESS; \
+ } while (0)
diff --git a/contrib/gcc/config/sparc/linux64.h b/contrib/gcc/config/sparc/linux64.h
index 31d82042f488..33c3f5438c98 100644
--- a/contrib/gcc/config/sparc/linux64.h
+++ b/contrib/gcc/config/sparc/linux64.h
@@ -34,7 +34,7 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
(MASK_V9 + MASK_PTR64 + MASK_64BIT /* + MASK_HARD_QUAD */ \
- + MASK_STACK_BIAS + MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU + MASK_LONG_DOUBLE_128)
+ + MASK_STACK_BIAS + MASK_APP_REGS + MASK_FPU + MASK_LONG_DOUBLE_128)
#endif
#undef ASM_CPU_DEFAULT_SPEC
@@ -58,8 +58,8 @@ Boston, MA 02111-1307, USA. */
#define STARTFILE_SPEC32 \
"%{!shared: \
- %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\
- crti.o%s %{static:crtbeginT.o%s}\
+ %{pg:/usr/lib/gcrt1.o%s} %{!pg:%{/usr/lib/p:gcrt1.o%s} %{!p:/usr/lib/crt1.o%s}}}\
+ /usr/lib/crti.o%s %{static:crtbeginT.o%s}\
%{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
#define STARTFILE_SPEC64 \
@@ -97,28 +97,33 @@ Boston, MA 02111-1307, USA. */
#undef ENDFILE_SPEC
#define ENDFILE_SPEC32 \
- "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
+ "%{!shared:crtend.o%s} %{shared:crtendS.o%s} /usr/lib/crtn.o%s"
#define ENDFILE_SPEC64 \
"%{!shared:crtend.o%s} %{shared:crtendS.o%s} /usr/lib64/crtn.o%s"
+#define ENDFILE_SPEC_COMMON \
+ "%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s}"
+
#ifdef SPARC_BI_ARCH
#if DEFAULT_ARCH32_P
#define ENDFILE_SPEC "\
%{m32:" ENDFILE_SPEC32 "} \
%{m64:" ENDFILE_SPEC64 "} \
-%{!m32:%{!m64:" ENDFILE_SPEC32 "}}"
+%{!m32:%{!m64:" ENDFILE_SPEC32 "}} " \
+ENDFILE_SPEC_COMMON
#else
#define ENDFILE_SPEC "\
%{m32:" ENDFILE_SPEC32 "} \
%{m64:" ENDFILE_SPEC64 "} \
-%{!m32:%{!m64:" ENDFILE_SPEC64 "}}"
+%{!m32:%{!m64:" ENDFILE_SPEC64 "}} " \
+ENDFILE_SPEC_COMMON
#endif
#else
-#define ENDFILE_SPEC ENDFILE_SPEC64
+#define ENDFILE_SPEC ENDFILE_SPEC64 " " ENDFILE_SPEC_COMMON
#endif
@@ -144,8 +149,6 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
-#undef MAX_WCHAR_TYPE_SIZE
-
/* Define for support of TFmode long double and REAL_ARITHMETIC.
Sparc ABI says that long double is 4 words. */
#undef LONG_DOUBLE_TYPE_SIZE
@@ -164,7 +167,7 @@ Boston, MA 02111-1307, USA. */
#endif
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__ELF__ -Dunix -D_LONGLONG -D__sparc__ -Dlinux -Asystem=unix -Asystem=posix"
+#define CPP_PREDEFINES "-D__ELF__ -Dunix -D_LONGLONG -D__sparc__ -D__gnu_linux__ -Dlinux -Asystem=unix -Asystem=posix"
#undef CPP_SUBTARGET_SPEC
#define CPP_SUBTARGET_SPEC "\
@@ -246,6 +249,7 @@ Boston, MA 02111-1307, USA. */
%{mcypress:-mcpu=cypress} \
%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \
%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
+%{m32:%{m64:%emay not use both -m32 and -m64}} \
%{m64:-mptr64 -mstack-bias -mlong-double-128 \
%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:-mcpu=ultrasparc}}}}}}} \
%{!mno-vis:%{!mcpu=v9:-mvis}}} \
@@ -256,6 +260,7 @@ Boston, MA 02111-1307, USA. */
%{mcypress:-mcpu=cypress} \
%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \
%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
+%{m32:%{m64:%emay not use both -m32 and -m64}} \
%{m32:-mptr32 -mno-stack-bias %{!mlong-double-128:-mlong-double-64} \
%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:-mcpu=cypress}}}}}}}} \
%{!m32:%{!mcpu*:-mcpu=ultrasparc}} \
@@ -325,6 +330,9 @@ do { \
#undef COMMON_ASM_OP
#define COMMON_ASM_OP "\t.common\t"
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
/* This is how to output a definition of an internal numbered label where
PREFIX is the class of label and NUM is the number within the class. */
@@ -361,3 +369,128 @@ do { \
#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
#endif
+/* Don't be different from other Linux platforms in this regard. */
+#define HANDLE_PRAGMA_PACK_PUSH_POP
+
+/* We use GNU ld so undefine this so that attribute((init_priority)) works. */
+#undef CTORS_SECTION_ASM_OP
+#undef DTORS_SECTION_ASM_OP
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+/* Handle multilib correctly. */
+#if defined(__arch64__)
+/* 64-bit Sparc version */
+#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
+ do { \
+ unsigned int *pc_ = (CONTEXT)->ra; \
+ long new_cfa_, i_; \
+ long regs_off_, fpu_save_off_; \
+ long this_cfa_, fpu_save_; \
+ \
+ if (pc_[0] != 0x82102065 /* mov NR_rt_sigreturn, %g1 */ \
+ || pc_[1] != 0x91d0206d) /* ta 0x6d */ \
+ break; \
+ regs_off_ = 192 + 128; \
+ fpu_save_off_ = regs_off_ + (16 * 8) + (3 * 8) + (2 * 4); \
+ this_cfa_ = (long) (CONTEXT)->cfa; \
+ new_cfa_ = *(long *)(((CONTEXT)->cfa) + (regs_off_ + (14 * 8))); \
+ new_cfa_ += 2047; /* Stack bias */ \
+ fpu_save_ = *(long *)((this_cfa_) + (fpu_save_off_)); \
+ (FS)->cfa_how = CFA_REG_OFFSET; \
+ (FS)->cfa_reg = 14; \
+ (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \
+ for (i_ = 1; i_ < 16; ++i_) \
+ { \
+ (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[i_].loc.offset = \
+ this_cfa_ + (regs_off_ + (i_ * 8)) - new_cfa_; \
+ } \
+ for (i_ = 0; i_ < 16; ++i_) \
+ { \
+ (FS)->regs.reg[i_ + 16].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[i_ + 16].loc.offset = \
+ this_cfa_ + (i_ * 8) - new_cfa_; \
+ } \
+ if (fpu_save_) \
+ { \
+ for (i_ = 0; i_ < 64; ++i_) \
+ { \
+ if (i_ > 32 && (i_ & 0x1)) \
+ continue; \
+ (FS)->regs.reg[i_ + 32].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[i_ + 32].loc.offset = \
+ (fpu_save_ + (i_ * 4)) - new_cfa_; \
+ } \
+ } \
+ /* Stick return address into %g0, same trick Alpha uses. */ \
+ (FS)->regs.reg[0].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[0].loc.offset = \
+ this_cfa_ + (regs_off_ + (16 * 8) + 8) - new_cfa_; \
+ (FS)->retaddr_column = 0; \
+ goto SUCCESS; \
+ } while (0)
+#else
+/* 32-bit Sparc version */
+#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
+ do { \
+ unsigned int *pc_ = (CONTEXT)->ra; \
+ int new_cfa_, i_, oldstyle_; \
+ int regs_off_, fpu_save_off_; \
+ int fpu_save_, this_cfa_; \
+ \
+ if (pc_[1] != 0x91d02010) /* ta 0x10 */ \
+ break; \
+ if (pc_[0] == 0x821020d8) /* mov NR_sigreturn, %g1 */ \
+ oldstyle_ = 1; \
+ else if (pc_[0] == 0x82102065) /* mov NR_rt_sigreturn, %g1 */ \
+ oldstyle_ = 0; \
+ else \
+ break; \
+ if (oldstyle_) \
+ { \
+ regs_off_ = 96; \
+ fpu_save_off_ = regs_off_ + (4 * 4) + (16 * 4); \
+ } \
+ else \
+ { \
+ regs_off_ = 96 + 128; \
+ fpu_save_off_ = regs_off_ + (4 * 4) + (16 * 4) + (2 * 4); \
+ } \
+ this_cfa_ = (int) (CONTEXT)->cfa; \
+ new_cfa_ = *(int *)(((CONTEXT)->cfa) + (regs_off_+(4*4)+(14 * 4))); \
+ fpu_save_ = *(int *)((this_cfa_) + (fpu_save_off_)); \
+ (FS)->cfa_how = CFA_REG_OFFSET; \
+ (FS)->cfa_reg = 14; \
+ (FS)->cfa_offset = new_cfa_ - (int) (CONTEXT)->cfa; \
+ for (i_ = 1; i_ < 16; ++i_) \
+ { \
+ if (i_ == 14) \
+ continue; \
+ (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[i_].loc.offset = \
+ this_cfa_ + (regs_off_+(4 * 4)+(i_ * 4)) - new_cfa_; \
+ } \
+ for (i_ = 0; i_ < 16; ++i_) \
+ { \
+ (FS)->regs.reg[i_ + 16].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[i_ + 16].loc.offset = \
+ this_cfa_ + (i_ * 4) - new_cfa_; \
+ } \
+ if (fpu_save_) \
+ { \
+ for (i_ = 0; i_ < 32; ++i_) \
+ { \
+ (FS)->regs.reg[i_ + 32].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[i_ + 32].loc.offset = \
+ (fpu_save_ + (i_ * 4)) - new_cfa_; \
+ } \
+ } \
+ /* Stick return address into %g0, same trick Alpha uses. */ \
+ (FS)->regs.reg[0].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[0].loc.offset = this_cfa_+(regs_off_+4)-new_cfa_; \
+ (FS)->retaddr_column = 0; \
+ goto SUCCESS; \
+ } while (0)
+#endif
diff --git a/contrib/gcc/config/sparc/lite.h b/contrib/gcc/config/sparc/lite.h
index f74044386156..95da781812f9 100644
--- a/contrib/gcc/config/sparc/lite.h
+++ b/contrib/gcc/config/sparc/lite.h
@@ -28,7 +28,7 @@ Boston, MA 02111-1307, USA. */
/* Enable app-regs and epilogue options. Do not enable the fpu. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE)
+#define TARGET_DEFAULT MASK_APP_REGS
/* US Software GOFAST library support. */
#undef INIT_SUBTARGET_OPTABS
diff --git a/contrib/gcc/config/sparc/litecoff.h b/contrib/gcc/config/sparc/litecoff.h
index dede792e69bb..ad0e1225db41 100644
--- a/contrib/gcc/config/sparc/litecoff.h
+++ b/contrib/gcc/config/sparc/litecoff.h
@@ -73,4 +73,4 @@ do { \
pointer is really %i7. */
#define DBX_REGISTER_NUMBER(REGNO) \
- (TARGET_FLAT && REGNO == FRAME_POINTER_REGNUM ? 31 : REGNO)
+ (TARGET_FLAT && (REGNO) == HARD_FRAME_POINTER_REGNUM ? 31 : REGNO)
diff --git a/contrib/gcc/config/sparc/liteelf.h b/contrib/gcc/config/sparc/liteelf.h
index d7c88b5c521e..5c93c2d943a3 100644
--- a/contrib/gcc/config/sparc/liteelf.h
+++ b/contrib/gcc/config/sparc/liteelf.h
@@ -38,7 +38,7 @@ Boston, MA 02111-1307, USA. */
/* Enable app-regs and epilogue options. Do not enable the fpu. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE)
+#define TARGET_DEFAULT MASK_APP_REGS
/* US Software GOFAST library support. */
#undef INIT_SUBTARGET_OPTABS
diff --git a/contrib/gcc/config/sparc/netbsd-elf.h b/contrib/gcc/config/sparc/netbsd-elf.h
new file mode 100644
index 000000000000..b4bbf7124671
--- /dev/null
+++ b/contrib/gcc/config/sparc/netbsd-elf.h
@@ -0,0 +1,344 @@
+/* Definitions of target machine for GNU compiler, for ELF on NetBSD/sparc
+ and NetBSD/sparc64.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by Matthew Green (mrg@eterna.com.au).
+
+This file is part of GNU CC.
+
+GNU CC 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 2, or (at your option)
+any later version.
+
+GNU CC 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 GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Make sure these are undefined. */
+#undef MD_EXEC_PREFIX
+#undef MD_STARTFILE_PREFIX
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-D__sparc__ -D__NetBSD__ -D__ELF__ \
+-Asystem=unix -Asystem=NetBSD"
+
+/* CPP defines used for 64 bit code. */
+#undef CPP_SUBTARGET_SPEC64
+#define CPP_SUBTARGET_SPEC64 \
+ "-D__sparc64__ -D__arch64__ -D__sparc_v9__ %{posix:-D_POSIX_SOURCE}"
+
+/* CPP defines used for 32 bit code. */
+#undef CPP_SUBTARGET_SPEC32
+#define CPP_SUBTARGET_SPEC32 "-D__sparc %{posix:-D_POSIX_SOURCE}"
+
+/* SIZE_TYPE and PTRDIFF_TYPE are wrong from sparc/sparc.h. */
+#undef SIZE_TYPE
+#define SIZE_TYPE "long unsigned int"
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "long int"
+
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+/* This is the char to use for continuation (in case we need to turn
+ continuation back on). */
+#undef DBX_CONTIN_CHAR
+#define DBX_CONTIN_CHAR '?'
+
+#undef DBX_REGISTER_NUMBER
+#define DBX_REGISTER_NUMBER(REGNO) \
+ (TARGET_FLAT && REGNO == HARD_FRAME_POINTER_REGNUM ? 31 : REGNO)
+
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
+/* This is how to output a definition of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#undef ASM_OUTPUT_INTERNAL_LABEL
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, ".L%s%d:\n", PREFIX, NUM)
+
+/* This is how to output a reference to an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#undef ASM_OUTPUT_INTERNAL_LABELREF
+#define ASM_OUTPUT_INTERNAL_LABELREF(FILE,PREFIX,NUM) \
+ fprintf (FILE, ".L%s%d", PREFIX, NUM)
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf ((LABEL), "*.L%s%ld", (PREFIX), (long)(NUM))
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+
+#undef ASM_SPEC
+#define ASM_SPEC "%{fpic:-K PIC} %{fPIC:-K PIC} %{V} %{v:%{!V:-V}} \
+%{mlittle-endian:-EL} \
+%(asm_cpu) %(asm_arch) %(asm_relax)"
+
+#undef STDC_0_IN_SYSTEM_HEADERS
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (%s)", TARGET_NAME);
+
+/*
+ * Clean up afterwards generic SPARC ELF configuration.
+ */
+
+#undef TRANSFER_FROM_TRAMPOLINE
+#define TRANSFER_FROM_TRAMPOLINE
+
+/* FIXME: Aren't these supposed to be available for SPARC ELF? */
+#undef MULDI3_LIBCALL
+#undef DIVDI3_LIBCALL
+#undef UDIVDI3_LIBCALL
+#undef MODDI3_LIBCALL
+#undef UMODDI3_LIBCALL
+#undef INIT_SUBTARGET_OPTABS
+#define INIT_SUBTARGET_OPTABS
+
+/* Below here exists the merged NetBSD/sparc & NetBSD/sparc64 compiler
+ description, allowing one to build 32 bit or 64 bit applications
+ on either. We define the sparc & sparc64 versions of things,
+ occasionally a neutral version (should be the same as "netbsd-elf.h")
+ and then based on SPARC_BI_ARCH, DEFAULT_ARCH32_P, and TARGET_CPU_DEFAULT,
+ we choose the correct version. */
+
+/* We use the default NetBSD ELF STARTFILE_SPEC and ENDFILE_SPEC
+ definitions, even for the SPARC_BI_ARCH compiler, because NetBSD does
+ not have a default place to find these libraries.. */
+
+/* Name the port(s). */
+#define TARGET_NAME64 "NetBSD/sparc64 ELF"
+#define TARGET_NAME32 "NetBSD/sparc ELF"
+
+/* TARGET_CPU_DEFAULT is set in Makefile.in. We test for 64-bit default
+ platform here. */
+
+#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc
+/* A 64 bit v9 compiler with stack-bias,
+ in a Medium/Low code model environment. */
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT \
+ (MASK_V9 + MASK_PTR64 + MASK_64BIT /* + MASK_HARD_QUAD */ \
+ + MASK_STACK_BIAS + MASK_APP_REGS + MASK_FPU + MASK_LONG_DOUBLE_128)
+
+#undef SPARC_DEFAULT_CMODEL
+#define SPARC_DEFAULT_CMODEL CM_MEDANY
+
+#endif
+
+/* CC1_SPEC for NetBSD/sparc. */
+#define CC1_SPEC32 \
+ "%{sun4:} %{target:} \
+ %{mcypress:-mcpu=cypress} \
+ %{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \
+ %{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
+ %{m32:%{m64:%emay not use both -m32 and -m64}} \
+ %{m64: \
+ -mptr64 -mstack-bias -mno-v8plus -mlong-double-128 \
+ %{!mcpu*: \
+ %{!mcypress: \
+ %{!msparclite: \
+ %{!mf930: \
+ %{!mf934: \
+ %{!mv8*: \
+ %{!msupersparc:-mcpu=ultrasparc}}}}}}} \
+ %{!mno-vis:%{!mcpu=v9:-mvis}} \
+ %{p:-mcmodel=medlow} \
+ %{pg:-mcmodel=medlow}}"
+
+#define CC1_SPEC64 \
+ "%{sun4:} %{target:} \
+ %{mcypress:-mcpu=cypress} \
+ %{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \
+ %{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
+ %{m32:%{m64:%emay not use both -m32 and -m64}} \
+ %{m32: \
+ -mptr32 -mno-stack-bias \
+ %{!mlong-double-128:-mlong-double-64} \
+ %{!mcpu*: \
+ %{!mcypress: \
+ %{!msparclite: \
+ %{!mf930: \
+ %{!mf934: \
+ %{!mv8*: \
+ %{!msupersparc:-mcpu=cypress}}}}}}}} \
+ %{!m32: \
+ %{p:-mcmodel=medlow} \
+ %{pg:-mcmodel=medlow}}"
+
+/* Make sure we use the right output format. Pick a default and then
+ make sure -m32/-m64 switch to the right one. */
+
+#define LINK_ARCH32_SPEC \
+ "%-m elf32_sparc \
+ %{assert*} %{R*} %{V} %{v:%{!V:-V}} \
+ %{shared:-shared} \
+ %{!shared: \
+ -dp \
+ %{!nostdlib:%{!r*:%{!e*:-e __start}}} \
+ %{!static: \
+ -dy %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /usr/libexec/ld.elf_so}} \
+ %{static:-static}}"
+
+#define LINK_ARCH64_SPEC \
+ "%-m elf64_sparc \
+ %{assert*} %{R*} %{V} %{v:%{!V:-V}} \
+ %{shared:-shared} \
+ %{!shared: \
+ -dp \
+ %{!nostdlib:%{!r*:%{!e*:-e __start}}} \
+ %{!static: \
+ -dy %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /usr/libexec/ld.elf_so}} \
+ %{static:-static}}"
+
+#define LINK_ARCH_SPEC "\
+%{m32:%(link_arch32)} \
+%{m64:%(link_arch64)} \
+%{!m32:%{!m64:%(link_arch_default)}} \
+"
+
+#if DEFAULT_ARCH32_P
+#define LINK_ARCH_DEFAULT_SPEC LINK_ARCH32_SPEC
+#else
+#define LINK_ARCH_DEFAULT_SPEC LINK_ARCH64_SPEC
+#endif
+
+/* What extra spec entries do we need? */
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "link_arch32", LINK_ARCH32_SPEC }, \
+ { "link_arch64", LINK_ARCH64_SPEC }, \
+ { "link_arch_default", LINK_ARCH_DEFAULT_SPEC }, \
+ { "link_arch", LINK_ARCH_SPEC }, \
+ { "cpp_subtarget_spec32", CPP_SUBTARGET_SPEC32 }, \
+ { "cpp_subtarget_spec64", CPP_SUBTARGET_SPEC64 },
+
+
+/* What extra switches do we need? */
+#undef SUBTARGET_SWITCHES
+#define SUBTARGET_SWITCHES \
+ {"long-double-64", -MASK_LONG_DOUBLE_128, N_("Use 64 bit long doubles") }, \
+ {"long-double-128", MASK_LONG_DOUBLE_128, N_("Use 128 bit long doubles") },
+
+
+/* Build a compiler that supports -m32 and -m64? */
+
+#ifdef SPARC_BI_ARCH
+
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
+
+#undef MAX_LONG_DOUBLE_TYPE_SIZE
+#define MAX_LONG_DOUBLE_TYPE_SIZE 128
+
+#if defined(__arch64__) || defined(__LONG_DOUBLE_128__)
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
+#else
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
+#endif
+
+#undef CC1_SPEC
+#if DEFAULT_ARCH32_P
+#define CC1_SPEC CC1_SPEC32
+#else
+#define CC1_SPEC CC1_SPEC64
+#endif
+
+#if DEFAULT_ARCH32_P
+#define MULTILIB_DEFAULTS { "m32" }
+#else
+#define MULTILIB_DEFAULTS { "m64" }
+#endif
+
+#undef CPP_SUBTARGET_SPEC
+#if DEFAULT_ARCH32_P
+#define CPP_SUBTARGET_SPEC \
+ "%{m64:%(cpp_subtarget_spec64)}%{!m64:%(cpp_subtarget_spec32)}"
+#else
+#define CPP_SUBTARGET_SPEC \
+ "%{!m32:%(cpp_subtarget_spec64)}%{m32:%(cpp_subtarget_spec32)}"
+#endif
+
+/* Restore this from sparc/sparc.h, netbsd.h changes it. */
+#undef CPP_SPEC
+#define CPP_SPEC "%(cpp_cpu) %(cpp_arch) %(cpp_endian) %(cpp_subtarget)"
+
+/* Name the port. */
+#undef TARGET_NAME
+#define TARGET_NAME (DEFAULT_ARCH32_P ? TARGET_NAME32 : TARGET_NAME64)
+
+#else /* SPARC_BI_ARCH */
+
+#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc
+
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 128
+
+#undef MAX_LONG_DOUBLE_TYPE_SIZE
+#define MAX_LONG_DOUBLE_TYPE_SIZE 128
+
+#undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
+
+#undef CC1_SPEC
+#define CC1_SPEC CC1_SPEC64
+
+#undef CPP_SUBTARGET_SPEC
+#define CPP_SUBTARGET_SPEC CPP_SUBTARGET_SPEC64
+
+#undef TARGET_NAME
+#define TARGET_NAME TARGET_NAME64
+
+#else /* TARGET_CPU_DEFAULT == TARGET_CPU_v9 \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc */
+
+/* A 32-bit only compiler. NetBSD don't support 128 bit `long double'
+ for 32-bit code, unlike Solaris. */
+
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+#undef MAX_LONG_DOUBLE_TYPE_SIZE
+#define MAX_LONG_DOUBLE_TYPE_SIZE 64
+
+#undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
+
+#undef CPP_SUBTARGET_SPEC
+#define CPP_SUBTARGET_SPEC CPP_SUBTARGET_SPEC32
+
+#undef CC1_SPEC
+#define CC1_SPEC CC1_SPEC32
+
+#undef TARGET_NAME
+#define TARGET_NAME TARGET_NAME32
+
+#endif /* TARGET_CPU_DEFAULT == TARGET_CPU_v9 \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc */
+
+#endif /* SPARC_BI_ARCH */
+
+/* We use GNU ld so undefine this so that attribute((init_priority)) works. */
+#undef CTORS_SECTION_ASM_OP
+#undef DTORS_SECTION_ASM_OP
diff --git a/contrib/gcc/config/sparc/netbsd.h b/contrib/gcc/config/sparc/netbsd.h
index 4be5b6b8e34e..b7b44409a55c 100644
--- a/contrib/gcc/config/sparc/netbsd.h
+++ b/contrib/gcc/config/sparc/netbsd.h
@@ -11,15 +11,6 @@
#undef PTRDIFF_TYPE
#define PTRDIFF_TYPE "int"
-#undef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-
-#undef WCHAR_UNSIGNED
-#define WCHAR_UNSIGNED 0
-
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE 32
-
/* This is BSD, so it wants DBX format. */
#define DBX_DEBUGGING_INFO
diff --git a/contrib/gcc/config/sparc/pbd.h b/contrib/gcc/config/sparc/pbd.h
index 27dfa9661f9d..9d267a5390ca 100644
--- a/contrib/gcc/config/sparc/pbd.h
+++ b/contrib/gcc/config/sparc/pbd.h
@@ -111,6 +111,9 @@ Boston, MA 02111-1307, USA. */
* Internal labels are prefixed with a period.
*/
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
/* This is how to store into the string LABEL
the symbol_ref name of an internal numbered label where
PREFIX is the class of label and NUM is the number within the class.
diff --git a/contrib/gcc/config/sparc/rtems.h b/contrib/gcc/config/sparc/rtems.h
index 9db8049d4cfb..e537f1ca988f 100644
--- a/contrib/gcc/config/sparc/rtems.h
+++ b/contrib/gcc/config/sparc/rtems.h
@@ -1,5 +1,5 @@
/* Definitions for rtems targeting a SPARC using a.out.
- Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 2000, 2002 Free Software Foundation, Inc.
Contributed by Joel Sherrill (joel@OARcorp.com).
This file is part of GNU CC.
@@ -23,10 +23,5 @@ Boston, MA 02111-1307, USA. */
/* Specify predefined symbols in preprocessor. */
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dsparc -D__GCC_NEW_VARARGS__ -Drtems -D__rtems__ \
+#define CPP_PREDEFINES "-Dsparc -D__GCC_NEW_VARARGS__ -D__rtems__ \
-Asystem=rtems"
-
-/* Generate calls to memcpy, memcmp and memset. */
-#ifndef TARGET_MEM_FUNCTIONS
-#define TARGET_MEM_FUNCTIONS
-#endif
diff --git a/contrib/gcc/config/sparc/rtemself.h b/contrib/gcc/config/sparc/rtemself.h
index 108ff33ca446..4f2cc66bb6cc 100644
--- a/contrib/gcc/config/sparc/rtemself.h
+++ b/contrib/gcc/config/sparc/rtemself.h
@@ -1,5 +1,5 @@
/* Definitions for rtems targeting a SPARC using ELF.
- Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 2000, 2002 Free Software Foundation, Inc.
Contributed by Joel Sherrill (joel@OARcorp.com).
This file is part of GNU CC.
@@ -22,10 +22,5 @@ Boston, MA 02111-1307, USA. */
/* Specify predefined symbols in preprocessor. */
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dsparc -D__GCC_NEW_VARARGS__ -Drtems -D__rtems__ \
- -Asystem=rtems"
-
-/* Generate calls to memcpy, memcmp and memset. */
-#ifndef TARGET_MEM_FUNCTIONS
-#define TARGET_MEM_FUNCTIONS
-#endif
+#define CPP_PREDEFINES "-Dsparc -D__GCC_NEW_VARARGS__ -D__rtems__ \
+ -D__USE_INIT_FINI__ -Asystem=rtems"
diff --git a/contrib/gcc/config/sparc/sol2-64.h b/contrib/gcc/config/sparc/sol2-64.h
index 40db497b4a71..ccdc8f3f800c 100644
--- a/contrib/gcc/config/sparc/sol2-64.h
+++ b/contrib/gcc/config/sparc/sol2-64.h
@@ -1,20 +1,7 @@
-/* Definitions of target machine for GNU compiler, for 64-bit SPARC
- running Solaris 2 using the GNU linker. */
+/* Definitions of target machine for GNU compiler, for bi-arch SPARC
+ running Solaris 2, defaulting to 64-bit code generation. */
-#ifdef LINKER_DOES_NOT_WORK_WITH_DWARF2
-#undef LINKER_DOES_NOT_WORK_WITH_DWARF2
-#endif
-
-#ifdef AS_SPARC64_FLAG
-
-#ifdef LINK_ARCH_SPEC
-#undef LINK_ARCH_SPEC
-#endif
-
-#define LINK_ARCH_SPEC "\
-%{m32:-m elf32_sparc %(link_arch32)} \
-%{m64:-m elf64_sparc %(link_arch64)} \
-%{!m32:%{!m64:%(link_arch_default)}} \
-"
-
-#endif
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT \
+ (MASK_V9 + MASK_PTR64 + MASK_64BIT /* + MASK_HARD_QUAD */ + \
+ MASK_STACK_BIAS + MASK_FPU + MASK_LONG_DOUBLE_128)
diff --git a/contrib/gcc/config/sparc/sol2-bi.h b/contrib/gcc/config/sparc/sol2-bi.h
new file mode 100644
index 000000000000..9828d634c915
--- /dev/null
+++ b/contrib/gcc/config/sparc/sol2-bi.h
@@ -0,0 +1,279 @@
+/* Definitions of target machine for GNU compiler, for bi-arch SPARC
+ running Solaris 2 using the system assembler and linker. */
+
+/* The default code model. */
+#undef SPARC_DEFAULT_CMODEL
+#define SPARC_DEFAULT_CMODEL CM_MEDANY
+
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 128
+
+#define AS_SPARC64_FLAG "-xarch=v9"
+
+#undef ASM_CPU32_DEFAULT_SPEC
+#define ASM_CPU32_DEFAULT_SPEC ""
+#undef ASM_CPU64_DEFAULT_SPEC
+#define ASM_CPU64_DEFAULT_SPEC AS_SPARC64_FLAG
+
+#if TARGET_CPU_DEFAULT == TARGET_CPU_v9
+#undef CPP_CPU64_DEFAULT_SPEC
+#define CPP_CPU64_DEFAULT_SPEC ""
+#undef ASM_CPU32_DEFAULT_SPEC
+#define ASM_CPU32_DEFAULT_SPEC "-xarch=v8plus"
+#endif
+#if TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc
+#undef CPP_CPU64_DEFAULT_SPEC
+#define CPP_CPU64_DEFAULT_SPEC ""
+#undef ASM_CPU32_DEFAULT_SPEC
+#define ASM_CPU32_DEFAULT_SPEC "-xarch=v8plusa"
+#undef ASM_CPU64_DEFAULT_SPEC
+#define ASM_CPU64_DEFAULT_SPEC AS_SPARC64_FLAG "a"
+#endif
+
+/* The sun bundled assembler doesn't accept -Yd, (and neither does gas).
+ It's safe to pass -s always, even if -g is not used. */
+#undef ASM_SPEC
+#define ASM_SPEC "\
+%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s \
+%{fpic:-K PIC} %{fPIC:-K PIC} \
+%(asm_cpu)\
+"
+
+#if DEFAULT_ARCH32_P
+#define DEF_ARCH32_SPEC(__str) "%{!m64:" __str "}"
+#define DEF_ARCH64_SPEC(__str) "%{m64:" __str "}"
+#else
+#define DEF_ARCH32_SPEC(__str) "%{m32:" __str "}"
+#define DEF_ARCH64_SPEC(__str) "%{!m32:" __str "}"
+#endif
+
+#undef CPP_CPU_SPEC
+#define CPP_CPU_SPEC "\
+%{mcypress:} \
+%{msparclite:-D__sparclite__} \
+%{mf930:-D__sparclite__} %{mf934:-D__sparclite__} \
+%{mv8:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
+%{msupersparc:-D__supersparc__ " DEF_ARCH32_SPEC("-D__sparcv8") "} \
+%{mcpu=sparclet:-D__sparclet__} %{mcpu=tsc701:-D__sparclet__} \
+%{mcpu=sparclite:-D__sparclite__} \
+%{mcpu=f930:-D__sparclite__} %{mcpu=f934:-D__sparclite__} \
+%{mcpu=v8:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
+%{mcpu=supersparc:-D__supersparc__ " DEF_ARCH32_SPEC("-D__sparcv8") "} \
+%{mcpu=v9:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
+%{mcpu=ultrasparc:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
+%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_cpu_default)}}}}}}} \
+"
+
+#undef ASM_CPU_SPEC
+#define ASM_CPU_SPEC "\
+%{mcpu=ultrasparc:" DEF_ARCH32_SPEC("-xarch=v8plusa") DEF_ARCH64_SPEC(AS_SPARC64_FLAG "a") "} \
+%{mcpu=v9:" DEF_ARCH32_SPEC("-xarch=v8plus") DEF_ARCH64_SPEC(AS_SPARC64_FLAG) "} \
+%{!mcpu=ultrasparc:%{!mcpu=v9:%{mcpu*:" DEF_ARCH32_SPEC("-xarch=v8") DEF_ARCH64_SPEC(AS_SPARC64_FLAG) "}}} \
+%{!mcpu*:%(asm_cpu_default)} \
+"
+
+#define STARTFILE_SPEC32 "\
+%{ansi:values-Xc.o%s} \
+%{!ansi: \
+ %{traditional:values-Xt.o%s} \
+ %{!traditional:values-Xa.o%s}}"
+
+#define STARTFILE_SPEC64 "\
+%{ansi:/usr/lib/sparcv9/values-Xc.o%s} \
+%{!ansi: \
+ %{traditional:/usr/lib/sparcv9/values-Xt.o%s} \
+ %{!traditional:/usr/lib/sparcv9/values-Xa.o%s}}"
+
+#if DEFAULT_ARCH32_P
+#define STARTFILE_ARCH_SPEC "\
+%{m32:" STARTFILE_SPEC32 "} \
+%{m64:" STARTFILE_SPEC64 "} \
+%{!m32:%{!m64:" STARTFILE_SPEC32 "}}"
+#else
+#define STARTFILE_ARCH_SPEC "\
+%{m32:" STARTFILE_SPEC32 "} \
+%{m64:" STARTFILE_SPEC64 "} \
+%{!m32:%{!m64:" STARTFILE_SPEC64 "}}"
+#endif
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "%{!shared: \
+ %{!symbolic: \
+ %{p:mcrt1.o%s} \
+ %{!p: \
+ %{pg:gcrt1.o%s gmon.o%s} \
+ %{!pg:crt1.o%s}}}} \
+ crti.o%s " STARTFILE_ARCH_SPEC " \
+ crtbegin.o%s"
+
+#undef CPP_CPU_DEFAULT_SPEC
+#define CPP_CPU_DEFAULT_SPEC \
+(DEFAULT_ARCH32_P ? "\
+%{m64:" CPP_CPU64_DEFAULT_SPEC "} \
+%{!m64:" CPP_CPU32_DEFAULT_SPEC "} \
+" : "\
+%{m32:" CPP_CPU32_DEFAULT_SPEC "} \
+%{!m32:" CPP_CPU64_DEFAULT_SPEC "} \
+")
+
+#undef ASM_CPU_DEFAULT_SPEC
+#define ASM_CPU_DEFAULT_SPEC \
+(DEFAULT_ARCH32_P ? "\
+%{m64:" ASM_CPU64_DEFAULT_SPEC "} \
+%{!m64:" ASM_CPU32_DEFAULT_SPEC "} \
+" : "\
+%{m32:" ASM_CPU32_DEFAULT_SPEC "} \
+%{!m32:" ASM_CPU64_DEFAULT_SPEC "} \
+")
+
+/* wchar_t is called differently in <wchar.h> for 32 and 64-bit
+ compilations. This is called for by SCD 2.4.1, p. 6-83, Figure 6-65
+ (32-bit) and p. 6P-10, Figure 6.38 (64-bit). */
+#define NO_BUILTIN_WCHAR_TYPE
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE (TARGET_ARCH64 ? "int" : "long int")
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+/* Same for wint_t. See SCD 2.4.1, p. 6-83, Figure 6-66 (32-bit). There's
+ no corresponding 64-bit definition, but this is what Solaris 8
+ <iso/wchar_iso.h> uses. */
+#define NO_BUILTIN_WINT_TYPE
+
+#undef WINT_TYPE
+#define WINT_TYPE (TARGET_ARCH64 ? "int" : "long int")
+
+#undef WINT_TYPE_SIZE
+#define WINT_TYPE_SIZE 32
+
+#undef CPP_ARCH32_SPEC
+#define CPP_ARCH32_SPEC "-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int \
+-D__WCHAR_TYPE__=long\\ int -D__WINT_TYPE__=long\\ int \
+-D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc"
+#undef CPP_ARCH64_SPEC
+#define CPP_ARCH64_SPEC "-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int \
+-D__WCHAR_TYPE__=int -D__WINT_TYPE__=int \
+-D__arch64__ -Acpu=sparc64 -Amachine=sparcv9 -D__sparcv9"
+
+#undef CPP_ARCH_SPEC
+#define CPP_ARCH_SPEC "\
+%{m32:%(cpp_arch32)} \
+%{m64:%(cpp_arch64)} \
+%{!m32:%{!m64:%(cpp_arch_default)}} \
+"
+
+#undef ASM_ARCH_SPEC
+#define ASM_ARCH_SPEC ""
+
+#undef ASM_ARCH32_SPEC
+#define ASM_ARCH32_SPEC ""
+
+#undef ASM_ARCH64_SPEC
+#define ASM_ARCH64_SPEC ""
+
+#undef ASM_ARCH_DEFAULT_SPEC
+#define ASM_ARCH_DEFAULT_SPEC ""
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "link_arch32", LINK_ARCH32_SPEC }, \
+ { "link_arch64", LINK_ARCH64_SPEC }, \
+ { "link_arch_default", LINK_ARCH_DEFAULT_SPEC }, \
+ { "link_arch", LINK_ARCH_SPEC },
+
+/* This should be the same as in svr4.h, except with -R added. */
+#define LINK_ARCH32_SPEC \
+ "%{G:-G} \
+ %{YP,*} \
+ %{R*} \
+ %{compat-bsd: \
+ %{!YP,*:%{p:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
+ %{pg:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
+ %{!p:%{!pg:-Y P,/usr/ucblib:/usr/ccs/lib:/usr/lib}}} \
+ -R /usr/ucblib} \
+ %{!compat-bsd: \
+ %{!YP,*:%{p:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
+ %{pg:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
+ %{!p:%{!pg:-Y P,/usr/ccs/lib:/usr/lib}}}}"
+
+#define LINK_ARCH64_SPEC \
+ "%{mcmodel=medlow:-M /usr/lib/ld/sparcv9/map.below4G} \
+ %{G:-G} \
+ %{YP,*} \
+ %{R*} \
+ %{compat-bsd: \
+ %{!YP,*:%{p:-Y P,/usr/ucblib/sparcv9:/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
+ %{pg:-Y P,/usr/ucblib/sparcv9:/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
+ %{!p:%{!pg:-Y P,/usr/ucblib/sparcv9:/usr/lib/sparcv9}}} \
+ -R /usr/ucblib} \
+ %{!compat-bsd: \
+ %{!YP,*:%{p:-Y P,/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
+ %{pg:-Y P,/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
+ %{!p:%{!pg:-Y P,/usr/lib/sparcv9}}}}"
+
+#define LINK_ARCH_SPEC "\
+%{m32:%(link_arch32)} \
+%{m64:%(link_arch64)} \
+%{!m32:%{!m64:%(link_arch_default)}} \
+"
+
+#define LINK_ARCH_DEFAULT_SPEC \
+(DEFAULT_ARCH32_P ? LINK_ARCH32_SPEC : LINK_ARCH64_SPEC)
+
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "%{h*} %{v:-V} \
+ %{b} %{Wl,*:%*} \
+ %{static:-dn -Bstatic} \
+ %{shared:-G -dy %{!mimpure-text:-z text}} \
+ %{symbolic:-Bsymbolic -G -dy -z text} \
+ %(link_arch) \
+ %{Qy:} %{!Qn:-Qy}"
+
+#undef CC1_SPEC
+#if DEFAULT_ARCH32_P
+#define CC1_SPEC "\
+%{sun4:} %{target:} \
+%{mcypress:-mcpu=cypress} \
+%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \
+%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
+%{m32:%{m64:%emay not use both -m32 and -m64}} \
+%{m64:-mptr64 -mstack-bias -mno-v8plus \
+ %{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8*:%{!msupersparc:-mcpu=v9}}}}}}}} \
+"
+#else
+#define CC1_SPEC "\
+%{sun4:} %{target:} \
+%{mcypress:-mcpu=cypress} \
+%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \
+%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
+%{m32:%{m64:%emay not use both -m32 and -m64}} \
+%{m32:-mptr32 -mno-stack-bias \
+ %{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8*:%{!msupersparc:-mcpu=cypress}}}}}}}} \
+%{mv8plus:-m32 -mptr32 -mno-stack-bias \
+ %{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:-mcpu=v9}}}}}}}} \
+"
+#endif
+
+#if DEFAULT_ARCH32_P
+#define MULTILIB_DEFAULTS { "m32" }
+#else
+#define MULTILIB_DEFAULTS { "m64" }
+#endif
+
+/* We use stabs-in-elf in 32-bit mode, because that is what the native
+ toolchain uses. But gdb can't handle truncated 32-bit stabs so we
+ use dwarf2 in 64-bit mode. */
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE (TARGET_ARCH32 ? DBX_DEBUG : DWARF2_DEBUG)
+
+/* We can't use the above definition for the purposes of specs. */
+#if defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
+# if DEFAULT_ARCH32_P
+# define ASM_DEBUG_SPEC "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}"
+# else
+# define ASM_DEBUG_SPEC "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}"
+# endif
+#endif
diff --git a/contrib/gcc/config/sparc/sol2-gas-bi.h b/contrib/gcc/config/sparc/sol2-gas-bi.h
new file mode 100644
index 000000000000..0b6cb618d36a
--- /dev/null
+++ b/contrib/gcc/config/sparc/sol2-gas-bi.h
@@ -0,0 +1,5 @@
+/* Definitions of target machine for GNU compiler, for bi-arch SPARC
+ running Solaris 2 using the GNU assembler. */
+
+#undef AS_SPARC64_FLAG
+#define AS_SPARC64_FLAG "-64 -Av9"
diff --git a/contrib/gcc/config/sparc/sol2-gld-bi.h b/contrib/gcc/config/sparc/sol2-gld-bi.h
new file mode 100644
index 000000000000..81a1ff2395d1
--- /dev/null
+++ b/contrib/gcc/config/sparc/sol2-gld-bi.h
@@ -0,0 +1,9 @@
+/* Definitions of target machine for GNU compiler, for bi-arch SPARC
+ running Solaris 2 using the GNU linker. */
+
+#undef LINK_ARCH_SPEC
+#define LINK_ARCH_SPEC "\
+%{m32:-m elf32_sparc %(link_arch32)} \
+%{m64:-m elf64_sparc %(link_arch64)} \
+%{!m32:%{!m64:%(link_arch_default)}} \
+"
diff --git a/contrib/gcc/config/sparc/sol2-gld.h b/contrib/gcc/config/sparc/sol2-gld.h
new file mode 100644
index 000000000000..76e034e46f1e
--- /dev/null
+++ b/contrib/gcc/config/sparc/sol2-gld.h
@@ -0,0 +1,6 @@
+/* Definitions of target machine for GNU compiler, for SPARC running Solaris 2
+ using the GNU linker. */
+
+/* Undefine this so that attribute((init_priority)) works. */
+#undef CTORS_SECTION_ASM_OP
+#undef DTORS_SECTION_ASM_OP
diff --git a/contrib/gcc/config/sparc/sol2.h b/contrib/gcc/config/sparc/sol2.h
index 46e80c121cb7..67e064dd544d 100644
--- a/contrib/gcc/config/sparc/sol2.h
+++ b/contrib/gcc/config/sparc/sol2.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler, for SPARC running Solaris 2
- Copyright 1992, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001 Free Software Foundation, Inc.
+ Copyright 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+ Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@netcom.com).
Additional changes by David V. Henkel-Wallace (gumby@cygnus.com).
@@ -23,17 +23,26 @@ Boston, MA 02111-1307, USA. */
/* Supposedly the same as vanilla sparc svr4, except for the stuff below: */
+/* Solaris 2 (at least as of 2.5.1) uses a 32-bit wchar_t. */
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "long int"
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
/* Solaris 2 uses a wint_t different from the default. This is required
by the SCD 2.4.1, p. 6-83, Figure 6-66. */
#undef WINT_TYPE
#define WINT_TYPE "long int"
#undef WINT_TYPE_SIZE
-#define WINT_TYPE_SIZE BITS_PER_WORD
+#define WINT_TYPE_SIZE 32
+
+#define HANDLE_PRAGMA_REDEFINE_EXTNAME 1
#undef CPP_PREDEFINES
#define CPP_PREDEFINES \
-"-Dsparc -Dsun -Dunix -D__svr4__ -D__SVR4 \
+"-Dsparc -Dsun -Dunix -D__svr4__ -D__SVR4 -D__PRAGMA_REDEFINE_EXTNAME \
-Asystem=unix -Asystem=svr4"
#undef CPP_SUBTARGET_SPEC
@@ -80,12 +89,12 @@ Boston, MA 02111-1307, USA. */
/* However it appears that Solaris 2.0 uses the same reg numbering as
the old BSD-style system did. */
-#undef DBX_REGISTER_NUMBER
/* Same as sparc.h */
+#undef DBX_REGISTER_NUMBER
#define DBX_REGISTER_NUMBER(REGNO) \
- (TARGET_FLAT && REGNO == FRAME_POINTER_REGNUM ? 31 : REGNO)
+ (TARGET_FLAT && (REGNO) == HARD_FRAME_POINTER_REGNUM ? 31 : REGNO)
-/* We use stabs-in-elf for debugging, because that is what the native
+/* We use stabs-in-elf by default, because that is what the native
toolchain uses. */
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
@@ -95,6 +104,9 @@ Boston, MA 02111-1307, USA. */
#define ASM_OUTPUT_SKIP(FILE,SIZE) \
fprintf (FILE, "\t.skip %u\n", (SIZE))
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
/* This is how to output a definition of an internal numbered label where
PREFIX is the class of label and NUM is the number within the class. */
@@ -150,7 +162,9 @@ Boston, MA 02111-1307, USA. */
%{p|pg:-ldl} -lc}}"
#undef ENDFILE_SPEC
-#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
+#define ENDFILE_SPEC \
+ "%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
+ crtend.o%s crtn.o%s"
/* This should be the same as in svr4.h, except with -R added. */
#undef LINK_SPEC
@@ -227,7 +241,7 @@ Boston, MA 02111-1307, USA. */
/* Solaris allows 64 bit out and global registers in 32 bit mode.
sparc_override_options will disable V8+ if not generating V9 code. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_EPILOGUE + MASK_FPU + MASK_V8PLUS + MASK_LONG_DOUBLE_128)
+#define TARGET_DEFAULT (MASK_FPU + MASK_V8PLUS + MASK_LONG_DOUBLE_128)
/*
* Attempt to turn on access permissions for the stack.
@@ -243,7 +257,9 @@ Boston, MA 02111-1307, USA. */
/* This declares mprotect (used in TRANSFER_FROM_TRAMPOLINE) for
libgcc2.c. */
-#ifdef L_trampoline
+/* We don't want to include this because sys/mman.h is not present on
+ some non-Solaris configurations that use sol2.h. */
+#if 0 /* def L_trampoline */
#include <sys/mman.h>
#endif
diff --git a/contrib/gcc/config/sparc/sol27-sld.h b/contrib/gcc/config/sparc/sol27-sld.h
new file mode 100644
index 000000000000..fb47b61f4486
--- /dev/null
+++ b/contrib/gcc/config/sparc/sol27-sld.h
@@ -0,0 +1,8 @@
+/* Up through Solaris 2.7, the system linker does not work with DWARF
+ or DWARF2, since it does not have working support for relocations
+ to unaligned data. */
+
+#undef DWARF_DEBUGGING_INFO
+#undef DWARF2_DEBUGGING_INFO
+#undef PREFERRED_DEBUGGING_TYPE
+#undef ASM_DEBUG_SPEC
diff --git a/contrib/gcc/config/sparc/sp64-aout.h b/contrib/gcc/config/sparc/sp64-aout.h
index 669adc3c45d4..1af9dea39a25 100644
--- a/contrib/gcc/config/sparc/sp64-aout.h
+++ b/contrib/gcc/config/sparc/sp64-aout.h
@@ -26,7 +26,7 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
(MASK_V9 + MASK_PTR64 + MASK_64BIT + MASK_HARD_QUAD \
- + MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU + MASK_STACK_BIAS)
+ + MASK_APP_REGS + MASK_FPU + MASK_STACK_BIAS)
/* The only code model supported is Medium/Low. */
#undef SPARC_DEFAULT_CMODEL
diff --git a/contrib/gcc/config/sparc/sp64-elf.h b/contrib/gcc/config/sparc/sp64-elf.h
index 3bd2a53f562f..caf944b33ff7 100644
--- a/contrib/gcc/config/sparc/sp64-elf.h
+++ b/contrib/gcc/config/sparc/sp64-elf.h
@@ -33,7 +33,7 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
(MASK_V9 + MASK_PTR64 + MASK_64BIT + MASK_HARD_QUAD \
- + MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU + MASK_STACK_BIAS + MASK_LONG_DOUBLE_128)
+ + MASK_APP_REGS + MASK_FPU + MASK_STACK_BIAS + MASK_LONG_DOUBLE_128)
#undef SPARC_DEFAULT_CMODEL
#define SPARC_DEFAULT_CMODEL CM_EMBMEDANY
@@ -71,7 +71,9 @@ crtbegin.o%s \
"
#undef ENDFILE_SPEC
-#define ENDFILE_SPEC "crtend.o%s"
+#define ENDFILE_SPEC \
+ "%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
+ crtend.o%s"
/* Use the default (for now). */
#undef LIB_SPEC
diff --git a/contrib/gcc/config/sparc/sp86x-aout.h b/contrib/gcc/config/sparc/sp86x-aout.h
index ed319253208b..74607d351654 100644
--- a/contrib/gcc/config/sparc/sp86x-aout.h
+++ b/contrib/gcc/config/sparc/sp86x-aout.h
@@ -28,7 +28,7 @@ Boston, MA 02111-1307, USA. */
/* Enable app-regs and epilogue options. Do not enable the fpu. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE)
+#define TARGET_DEFAULT MASK_APP_REGS
#undef ASM_SPEC
#define ASM_SPEC "%{v:-v} %{mlittle-endian-data:--little-endian-data} %(asm_cpu)"
diff --git a/contrib/gcc/config/sparc/sp86x-elf.h b/contrib/gcc/config/sparc/sp86x-elf.h
index 40ecd55ef4d8..42239a945e15 100644
--- a/contrib/gcc/config/sparc/sp86x-elf.h
+++ b/contrib/gcc/config/sparc/sp86x-elf.h
@@ -38,7 +38,7 @@ Boston, MA 02111-1307, USA. */
/* Enable app-regs and epilogue options. Do not enable the fpu. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE)
+#define TARGET_DEFAULT MASK_APP_REGS
#undef ASM_SPEC
#define ASM_SPEC "%{v:-V} %{mlittle-endian-data:--little-endian-data} %(asm_cpu)"
diff --git a/contrib/gcc/config/sparc/sparc-protos.h b/contrib/gcc/config/sparc/sparc-protos.h
index c0f3edce65dc..fd372ded33ca 100644
--- a/contrib/gcc/config/sparc/sparc-protos.h
+++ b/contrib/gcc/config/sparc/sparc-protos.h
@@ -24,6 +24,8 @@ Boston, MA 02111-1307, USA. */
#ifndef __SPARC_PROTOS_H__
#define __SPARC_PROTOS_H__
+extern bool sparc_emitting_epilogue;
+
#ifdef TREE_CODE
extern struct rtx_def *function_value PARAMS ((tree, enum machine_mode, int));
extern void function_arg_advance PARAMS ((CUMULATIVE_ARGS *,
@@ -57,10 +59,7 @@ extern int check_pic PARAMS ((int));
extern int short_branch PARAMS ((int, int));
extern int sparc_flat_epilogue_delay_slots PARAMS ((void));
extern unsigned long sparc_flat_compute_frame_size PARAMS ((int));
-extern void sparc_function_profiler PARAMS ((FILE *, int));
-extern void sparc_function_block_profiler PARAMS ((FILE *, int));
-extern void sparc_block_profiler PARAMS ((FILE *, int));
-extern void sparc_function_block_profiler_exit PARAMS ((FILE *));
+extern void sparc_profile_hook PARAMS ((int));
extern void sparc_override_options PARAMS ((void));
extern int leaf_return_peephole_ok PARAMS ((void));
extern void sparc_output_scratch_registers PARAMS ((FILE *));
@@ -74,6 +73,10 @@ extern enum machine_mode select_cc_mode PARAMS ((enum rtx_code, rtx, rtx));
/* Define the function that build the compare insn for scc and bcc. */
extern rtx gen_compare_reg PARAMS ((enum rtx_code code, rtx, rtx));
extern void sparc_emit_float_lib_cmp PARAMS ((rtx, rtx, enum rtx_code));
+extern void sparc_emit_floatunsdi PARAMS ((rtx [2]));
+extern void emit_tfmode_binop PARAMS ((enum rtx_code, rtx *));
+extern void emit_tfmode_unop PARAMS ((enum rtx_code, rtx *));
+extern void emit_tfmode_cvt PARAMS ((enum rtx_code, rtx *));
/* This function handles all v9 scc insns */
extern int gen_v9_scc PARAMS ((enum rtx_code, rtx *));
extern void sparc_initialize_trampoline PARAMS ((rtx, rtx, rtx));
@@ -85,10 +88,10 @@ extern void sparc_emit_set_const64 PARAMS ((rtx, rtx));
extern void sparc_emit_set_symbolic_const64 PARAMS ((rtx, rtx, rtx));
extern int sparc_splitdi_legitimate PARAMS ((rtx, rtx));
extern int sparc_absnegfloat_split_legitimate PARAMS ((rtx, rtx));
-extern char *output_cbranch PARAMS ((rtx, int, int, int, int, rtx));
-extern const char *output_return PARAMS ((rtx *));
+extern char *output_cbranch PARAMS ((rtx, rtx, int, int, int, int, rtx));
extern const char *output_sibcall PARAMS ((rtx, rtx));
-extern char *output_v9branch PARAMS ((rtx, int, int, int, int, int, rtx));
+extern char *output_v9branch PARAMS ((rtx, rtx, int, int, int, int, int,
+ rtx));
extern void emit_v9_brxx_insn PARAMS ((enum rtx_code, rtx, rtx));
extern void print_operand PARAMS ((FILE *, rtx, int));
extern int mems_ok_for_ldd_peep PARAMS ((rtx, rtx, rtx));
@@ -97,6 +100,7 @@ extern int arith_4096_operand PARAMS ((rtx, enum machine_mode));
extern int zero_operand PARAMS ((rtx, enum machine_mode));
extern int fp_zero_operand PARAMS ((rtx, enum machine_mode));
extern int reg_or_0_operand PARAMS ((rtx, enum machine_mode));
+extern int empty_delay_slot PARAMS ((rtx));
extern int eligible_for_epilogue_delay PARAMS ((rtx, int));
extern int eligible_for_return_delay PARAMS ((rtx));
extern int eligible_for_sibcall_delay PARAMS ((rtx));
@@ -115,8 +119,8 @@ extern char *sparc_v8plus_shift PARAMS ((rtx *, rtx, const char *));
/* Function used for V8+ code generation. Returns 1 if the high
32 bits of REG are 0 before INSN. */
extern int sparc_check_64 PARAMS ((rtx, rtx));
-extern int sparc_return_peephole_ok PARAMS ((rtx, rtx));
extern rtx gen_df_reg PARAMS ((rtx, int));
+extern int sparc_extra_constraint_check PARAMS ((rtx, int, int));
#endif /* RTX_CODE */
#endif /* __SPARC_PROTOS_H__ */
diff --git a/contrib/gcc/config/sparc/sparc.c b/contrib/gcc/config/sparc/sparc.c
index 8cc44490de64..28bbcecc76c5 100644
--- a/contrib/gcc/config/sparc/sparc.c
+++ b/contrib/gcc/config/sparc/sparc.c
@@ -68,26 +68,24 @@ Boston, MA 02111-1307, USA. */
static int apparent_fsize;
static int actual_fsize;
-/* Number of live general or floating point registers needed to be saved
- (as 4-byte quantities). This is only done if TARGET_EPILOGUE. */
+/* Number of live general or floating point registers needed to be
+ saved (as 4-byte quantities). */
static int num_gfregs;
/* Save the operands last given to a compare for use when we
generate a scc or bcc insn. */
-
rtx sparc_compare_op0, sparc_compare_op1;
-/* We may need an epilogue if we spill too many registers.
- If this is non-zero, then we branch here for the epilogue. */
-static rtx leaf_label;
+/* Coordinate with the md file wrt special insns created by
+ sparc_nonflat_function_epilogue. */
+bool sparc_emitting_epilogue;
#ifdef LEAF_REGISTERS
-/* Vector to say how input registers are mapped to output
- registers. FRAME_POINTER_REGNUM cannot be remapped by
- this function to eliminate it. You must use -fomit-frame-pointer
- to get that. */
-const char leaf_reg_remap[] =
+/* Vector to say how input registers are mapped to output registers.
+ HARD_FRAME_POINTER_REGNUM cannot be remapped by this function to
+ eliminate it. You must use -fomit-frame-pointer to get that. */
+char leaf_reg_remap[] =
{ 0, 1, 2, 3, 4, 5, 6, 7,
-1, -1, -1, -1, -1, -1, 14, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -180,6 +178,12 @@ static int sparc_issue_rate PARAMS ((void));
static int sparc_variable_issue PARAMS ((FILE *, int, rtx, int));
static void sparc_sched_init PARAMS ((FILE *, int, int));
static int sparc_sched_reorder PARAMS ((FILE *, int, rtx *, int *, int));
+
+static void emit_soft_tfmode_libcall PARAMS ((const char *, int, rtx *));
+static void emit_soft_tfmode_binop PARAMS ((enum rtx_code, rtx *));
+static void emit_soft_tfmode_unop PARAMS ((enum rtx_code, rtx *));
+static void emit_soft_tfmode_cvt PARAMS ((enum rtx_code, rtx *));
+static void emit_hard_tfmode_operation PARAMS ((enum rtx_code, rtx *));
/* Option handling. */
@@ -433,12 +437,6 @@ sparc_override_options ()
/* Do various machine dependent initializations. */
sparc_init_modes ();
- if ((profile_flag)
- && sparc_cmodel != CM_32 && sparc_cmodel != CM_MEDLOW)
- {
- error ("profiling does not support code models other than medlow");
- }
-
/* Register global variables with the garbage collector. */
sparc_add_gc_roots ();
}
@@ -492,6 +490,20 @@ fp_zero_operand (op, mode)
return op == CONST0_RTX (mode);
}
+/* Nonzero if OP is a register operand in floating point register. */
+
+int
+fp_register_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (! register_operand (op, mode))
+ return 0;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+ return GET_CODE (op) == REG && SPARC_FP_REG_P (REGNO (op));
+}
+
/* Nonzero if OP is a floating point constant which can
be loaded into an integer register using a single
sethi instruction. */
@@ -609,6 +621,27 @@ fcc_reg_operand (op, mode)
#endif
}
+/* Nonzero if OP is a floating point condition code fcc0 register. */
+
+int
+fcc0_reg_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ /* This can happen when recog is called from combine. Op may be a MEM.
+ Fail instead of calling abort in this case. */
+ if (GET_CODE (op) != REG)
+ return 0;
+
+ if (mode != VOIDmode && mode != GET_MODE (op))
+ return 0;
+ if (mode == VOIDmode
+ && (GET_MODE (op) != CCFPmode && GET_MODE (op) != CCFPEmode))
+ return 0;
+
+ return REGNO (op) == SPARC_FCC_REG;
+}
+
/* Nonzero if OP is an integer or floating point condition code register. */
int
@@ -879,12 +912,35 @@ noov_compare_op (op, mode)
if (GET_RTX_CLASS (code) != '<')
return 0;
- if (GET_MODE (XEXP (op, 0)) == CC_NOOVmode)
+ if (GET_MODE (XEXP (op, 0)) == CC_NOOVmode
+ || GET_MODE (XEXP (op, 0)) == CCX_NOOVmode)
/* These are the only branches which work with CC_NOOVmode. */
return (code == EQ || code == NE || code == GE || code == LT);
return 1;
}
+/* Return 1 if this is a 64-bit comparison operator. This allows the use of
+ MATCH_OPERATOR to recognize all the branch insns. */
+
+int
+noov_compare64_op (op, mode)
+ register rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ enum rtx_code code = GET_CODE (op);
+
+ if (! TARGET_V9)
+ return 0;
+
+ if (GET_RTX_CLASS (code) != '<')
+ return 0;
+
+ if (GET_MODE (XEXP (op, 0)) == CCX_NOOVmode)
+ /* These are the only branches which work with CCX_NOOVmode. */
+ return (code == EQ || code == NE || code == GE || code == LT);
+ return (GET_MODE (XEXP (op, 0)) == CCXmode);
+}
+
/* Nonzero if OP is a comparison operator suitable for use in v9
conditional move or branch on register contents instructions. */
@@ -951,13 +1007,11 @@ arith_operand (op, mode)
rtx op;
enum machine_mode mode;
{
- int val;
if (register_operand (op, mode))
return 1;
if (GET_CODE (op) != CONST_INT)
return 0;
- val = INTVAL (op) & 0xffffffff;
- return SPARC_SIMM13_P (val);
+ return SMALL_INT32 (op);
}
/* Return true if OP is a constant 4096 */
@@ -967,11 +1021,10 @@ arith_4096_operand (op, mode)
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
- int val;
if (GET_CODE (op) != CONST_INT)
return 0;
- val = INTVAL (op) & 0xffffffff;
- return val == 4096;
+ else
+ return INTVAL (op) == 4096;
}
/* Return true if OP is suitable as second operand for add/sub */
@@ -999,7 +1052,7 @@ const64_operand (op, mode)
&& SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))
&& (CONST_DOUBLE_HIGH (op) ==
((CONST_DOUBLE_LOW (op) & 0x80000000) != 0 ?
- (HOST_WIDE_INT)0xffffffff : 0)))
+ (HOST_WIDE_INT)-1 : 0)))
#endif
);
}
@@ -1008,21 +1061,15 @@ const64_operand (op, mode)
int
const64_high_operand (op, mode)
rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+ enum machine_mode mode;
{
return ((GET_CODE (op) == CONST_INT
- && (INTVAL (op) & 0xfffffc00) != 0
- && SPARC_SETHI_P (INTVAL (op))
-#if HOST_BITS_PER_WIDE_INT != 64
- /* Must be positive on non-64bit host else the
- optimizer is fooled into thinking that sethi
- sign extends, even though it does not. */
- && INTVAL (op) >= 0
-#endif
+ && (INTVAL (op) & ~(HOST_WIDE_INT)0x3ff) != 0
+ && SPARC_SETHI_P (INTVAL (op) & GET_MODE_MASK (mode))
)
|| (GET_CODE (op) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (op) == 0
- && (CONST_DOUBLE_LOW (op) & 0xfffffc00) != 0
+ && (CONST_DOUBLE_LOW (op) & ~(HOST_WIDE_INT)0x3ff) != 0
&& SPARC_SETHI_P (CONST_DOUBLE_LOW (op))));
}
@@ -1231,12 +1278,7 @@ input_operand (op, mode)
variants when we are working in DImode and !arch64. */
if (GET_MODE_CLASS (mode) == MODE_INT
&& ((GET_CODE (op) == CONST_INT
- && ((SPARC_SETHI_P (INTVAL (op))
- && (! TARGET_ARCH64
- || (INTVAL (op) >= 0)
- || mode == SImode
- || mode == HImode
- || mode == QImode))
+ && (SPARC_SETHI_P (INTVAL (op) & GET_MODE_MASK (mode))
|| SPARC_SIMM13_P (INTVAL (op))
|| (mode == DImode
&& ! TARGET_ARCH64)))
@@ -1315,7 +1357,7 @@ sparc_emit_set_const32 (op0, op1)
{
HOST_WIDE_INT value = INTVAL (op1);
- if (SPARC_SETHI_P (value)
+ if (SPARC_SETHI_P (value & GET_MODE_MASK (mode))
|| SPARC_SIMM13_P (value))
abort ();
}
@@ -1336,11 +1378,13 @@ sparc_emit_set_const32 (op0, op1)
&& (INTVAL (op1) & 0x80000000) != 0)
emit_insn (gen_rtx_SET
(VOIDmode, temp,
- gen_rtx_CONST_DOUBLE (VOIDmode, INTVAL (op1) & 0xfffffc00,
+ gen_rtx_CONST_DOUBLE (VOIDmode,
+ INTVAL (op1) & ~(HOST_WIDE_INT)0x3ff,
0)));
else
emit_insn (gen_rtx_SET (VOIDmode, temp,
- GEN_INT (INTVAL (op1) & 0xfffffc00)));
+ GEN_INT (INTVAL (op1)
+ & ~(HOST_WIDE_INT)0x3ff)));
emit_insn (gen_rtx_SET (VOIDmode,
op0,
@@ -1366,6 +1410,14 @@ sparc_emit_set_symbolic_const64 (op0, op1, temp1)
rtx op1;
rtx temp1;
{
+ rtx ti_temp1 = 0;
+
+ if (temp1 && GET_MODE (temp1) == TImode)
+ {
+ ti_temp1 = temp1;
+ temp1 = gen_rtx_REG (DImode, REGNO (temp1));
+ }
+
switch (sparc_cmodel)
{
case CM_MEDLOW:
@@ -1419,12 +1471,16 @@ sparc_emit_set_symbolic_const64 (op0, op1, temp1)
sllx %temp3, 32, %temp5
or %temp4, %temp5, %reg */
- /* Getting this right wrt. reloading is really tricky.
- We _MUST_ have a separate temporary at this point,
- if we don't barf immediately instead of generating
- incorrect code. */
+ /* It is possible that one of the registers we got for operands[2]
+ might coincide with that of operands[0] (which is why we made
+ it TImode). Pick the other one to use as our scratch. */
if (rtx_equal_p (temp1, op0))
- abort ();
+ {
+ if (ti_temp1)
+ temp1 = gen_rtx_REG (DImode, REGNO (temp1) + 1);
+ else
+ abort();
+ }
emit_insn (gen_sethh (op0, op1));
emit_insn (gen_setlm (temp1, op1));
@@ -1462,12 +1518,16 @@ sparc_emit_set_symbolic_const64 (op0, op1, temp1)
}
else
{
- /* Getting this right wrt. reloading is really tricky.
- We _MUST_ have a separate temporary at this point,
- so we barf immediately instead of generating
- incorrect code. */
- if (temp1 == op0)
- abort ();
+ /* It is possible that one of the registers we got for operands[2]
+ might coincide with that of operands[0] (which is why we made
+ it TImode). Pick the other one to use as our scratch. */
+ if (rtx_equal_p (temp1, op0))
+ {
+ if (ti_temp1)
+ temp1 = gen_rtx_REG (DImode, REGNO (temp1) + 1);
+ else
+ abort();
+ }
emit_insn (gen_embmedany_textuhi (op0, op1));
emit_insn (gen_embmedany_texthi (temp1, op1));
@@ -1494,15 +1554,15 @@ static rtx gen_safe_OR64 PARAMS ((rtx, HOST_WIDE_INT));
static rtx gen_safe_XOR64 PARAMS ((rtx, HOST_WIDE_INT));
#if HOST_BITS_PER_WIDE_INT == 64
-#define GEN_HIGHINT64(__x) GEN_INT ((__x) & 0xfffffc00)
+#define GEN_HIGHINT64(__x) GEN_INT ((__x) & ~(HOST_WIDE_INT)0x3ff)
#define GEN_INT64(__x) GEN_INT (__x)
#else
#define GEN_HIGHINT64(__x) \
- gen_rtx_CONST_DOUBLE (VOIDmode, (__x) & 0xfffffc00, 0)
+ gen_rtx_CONST_DOUBLE (VOIDmode, (__x) & ~(HOST_WIDE_INT)0x3ff, 0)
#define GEN_INT64(__x) \
gen_rtx_CONST_DOUBLE (VOIDmode, (__x) & 0xffffffff, \
((__x) & 0x80000000 \
- ? 0xffffffff : 0))
+ ? -1 : 0))
#endif
/* The optimizer is not to assume anything about exactly
@@ -1587,7 +1647,8 @@ sparc_emit_set_const64_quick1 (op0, temp, low_bits, is_neg)
{
emit_insn (gen_rtx_SET (VOIDmode, op0,
gen_safe_XOR64 (temp,
- (-0x400 | (low_bits & 0x3ff)))));
+ (-(HOST_WIDE_INT)0x400
+ | (low_bits & 0x3ff)))));
}
}
}
@@ -2295,16 +2356,7 @@ gen_v9_scc (compare_code, operands)
|| GET_MODE (operands[0]) == DImode))
return 0;
- /* Handle the case where operands[0] == sparc_compare_op0.
- We "early clobber" the result. */
- if (REGNO (operands[0]) == REGNO (sparc_compare_op0))
- {
- op0 = gen_reg_rtx (GET_MODE (sparc_compare_op0));
- emit_move_insn (op0, sparc_compare_op0);
- }
- else
- op0 = sparc_compare_op0;
- /* For consistency in the following. */
+ op0 = sparc_compare_op0;
op1 = sparc_compare_op1;
/* Try to use the movrCC insns. */
@@ -2314,14 +2366,12 @@ gen_v9_scc (compare_code, operands)
&& v9_regcmp_p (compare_code))
{
/* Special case for op0 != 0. This can be done with one instruction if
- operands[0] == sparc_compare_op0. We don't assume they are equal
- now though. */
+ operands[0] == sparc_compare_op0. */
if (compare_code == NE
&& GET_MODE (operands[0]) == DImode
- && GET_MODE (op0) == DImode)
+ && rtx_equal_p (op0, operands[0]))
{
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], op0));
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_IF_THEN_ELSE (DImode,
gen_rtx_fmt_ee (compare_code, DImode,
@@ -2331,6 +2381,14 @@ gen_v9_scc (compare_code, operands)
return 1;
}
+ if (reg_overlap_mentioned_p (operands[0], op0))
+ {
+ /* Handle the case where operands[0] == sparc_compare_op0.
+ We "early clobber" the result. */
+ op0 = gen_reg_rtx (GET_MODE (sparc_compare_op0));
+ emit_move_insn (op0, sparc_compare_op0);
+ }
+
emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx));
if (GET_MODE (op0) != DImode)
{
@@ -2406,6 +2464,304 @@ gen_df_reg (reg, low)
return gen_rtx_REG (DFmode, regno);
}
+/* Generate a call to FUNC with OPERANDS. Operand 0 is the return value.
+ Unlike normal calls, TFmode operands are passed by reference. It is
+ assumed that no more than 3 operands are required. */
+
+static void
+emit_soft_tfmode_libcall (func_name, nargs, operands)
+ const char *func_name;
+ int nargs;
+ rtx *operands;
+{
+ rtx ret_slot = NULL, arg[3], func_sym;
+ int i;
+
+ /* We only expect to be called for conversions, unary, and binary ops. */
+ if (nargs < 2 || nargs > 3)
+ abort ();
+
+ for (i = 0; i < nargs; ++i)
+ {
+ rtx this_arg = operands[i];
+ rtx this_slot;
+
+ /* TFmode arguments and return values are passed by reference. */
+ if (GET_MODE (this_arg) == TFmode)
+ {
+ if (GET_CODE (this_arg) == MEM)
+ this_arg = XEXP (this_arg, 0);
+ else if (CONSTANT_P (this_arg))
+ {
+ this_slot = force_const_mem (TFmode, this_arg);
+ this_arg = XEXP (this_slot, 0);
+ }
+ else
+ {
+ this_slot = assign_stack_temp (TFmode, GET_MODE_SIZE (TFmode), 0);
+
+ /* Operand 0 is the return value. We'll copy it out later. */
+ if (i > 0)
+ emit_move_insn (this_slot, this_arg);
+ else
+ ret_slot = this_slot;
+
+ this_arg = XEXP (this_slot, 0);
+ }
+ }
+
+ arg[i] = this_arg;
+ }
+
+ func_sym = gen_rtx_SYMBOL_REF (Pmode, func_name);
+
+ if (GET_MODE (operands[0]) == TFmode)
+ {
+ if (nargs == 2)
+ emit_library_call (func_sym, LCT_NORMAL, VOIDmode, 2,
+ arg[0], GET_MODE (arg[0]),
+ arg[1], GET_MODE (arg[1]));
+ else
+ emit_library_call (func_sym, LCT_NORMAL, VOIDmode, 3,
+ arg[0], GET_MODE (arg[0]),
+ arg[1], GET_MODE (arg[1]),
+ arg[2], GET_MODE (arg[2]));
+
+ if (ret_slot)
+ emit_move_insn (operands[0], ret_slot);
+ }
+ else
+ {
+ rtx ret;
+
+ if (nargs != 2)
+ abort ();
+
+ ret = emit_library_call_value (func_sym, operands[0], LCT_NORMAL,
+ GET_MODE (operands[0]), 1,
+ arg[1], GET_MODE (arg[1]));
+
+ if (ret != operands[0])
+ emit_move_insn (operands[0], ret);
+ }
+}
+
+/* Expand soft-float TFmode calls to sparc abi routines. */
+
+static void
+emit_soft_tfmode_binop (code, operands)
+ enum rtx_code code;
+ rtx *operands;
+{
+ const char *func;
+
+ switch (code)
+ {
+ case PLUS:
+ func = "_Qp_add";
+ break;
+ case MINUS:
+ func = "_Qp_sub";
+ break;
+ case MULT:
+ func = "_Qp_mul";
+ break;
+ case DIV:
+ func = "_Qp_div";
+ break;
+ default:
+ abort ();
+ }
+
+ emit_soft_tfmode_libcall (func, 3, operands);
+}
+
+static void
+emit_soft_tfmode_unop (code, operands)
+ enum rtx_code code;
+ rtx *operands;
+{
+ const char *func;
+
+ switch (code)
+ {
+ case SQRT:
+ func = "_Qp_sqrt";
+ break;
+ default:
+ abort ();
+ }
+
+ emit_soft_tfmode_libcall (func, 2, operands);
+}
+
+static void
+emit_soft_tfmode_cvt (code, operands)
+ enum rtx_code code;
+ rtx *operands;
+{
+ const char *func;
+
+ switch (code)
+ {
+ case FLOAT_EXTEND:
+ switch (GET_MODE (operands[1]))
+ {
+ case SFmode:
+ func = "_Qp_stoq";
+ break;
+ case DFmode:
+ func = "_Qp_dtoq";
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case FLOAT_TRUNCATE:
+ switch (GET_MODE (operands[0]))
+ {
+ case SFmode:
+ func = "_Qp_qtos";
+ break;
+ case DFmode:
+ func = "_Qp_qtod";
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case FLOAT:
+ switch (GET_MODE (operands[1]))
+ {
+ case SImode:
+ func = "_Qp_itoq";
+ break;
+ case DImode:
+ func = "_Qp_xtoq";
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case UNSIGNED_FLOAT:
+ switch (GET_MODE (operands[1]))
+ {
+ case SImode:
+ func = "_Qp_uitoq";
+ break;
+ case DImode:
+ func = "_Qp_uxtoq";
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case FIX:
+ switch (GET_MODE (operands[0]))
+ {
+ case SImode:
+ func = "_Qp_qtoi";
+ break;
+ case DImode:
+ func = "_Qp_qtox";
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case UNSIGNED_FIX:
+ switch (GET_MODE (operands[0]))
+ {
+ case SImode:
+ func = "_Qp_qtoui";
+ break;
+ case DImode:
+ func = "_Qp_qtoux";
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ default:
+ abort ();
+ }
+
+ emit_soft_tfmode_libcall (func, 2, operands);
+}
+
+/* Expand a hard-float tfmode operation. All arguments must be in
+ registers. */
+
+static void
+emit_hard_tfmode_operation (code, operands)
+ enum rtx_code code;
+ rtx *operands;
+{
+ rtx op, dest;
+
+ if (GET_RTX_CLASS (code) == '1')
+ {
+ operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
+ op = gen_rtx_fmt_e (code, GET_MODE (operands[0]), operands[1]);
+ }
+ else
+ {
+ operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
+ operands[2] = force_reg (GET_MODE (operands[2]), operands[2]);
+ op = gen_rtx_fmt_ee (code, GET_MODE (operands[0]),
+ operands[1], operands[2]);
+ }
+
+ if (register_operand (operands[0], VOIDmode))
+ dest = operands[0];
+ else
+ dest = gen_reg_rtx (GET_MODE (operands[0]));
+
+ emit_insn (gen_rtx_SET (VOIDmode, dest, op));
+
+ if (dest != operands[0])
+ emit_move_insn (operands[0], dest);
+}
+
+void
+emit_tfmode_binop (code, operands)
+ enum rtx_code code;
+ rtx *operands;
+{
+ if (TARGET_HARD_QUAD)
+ emit_hard_tfmode_operation (code, operands);
+ else
+ emit_soft_tfmode_binop (code, operands);
+}
+
+void
+emit_tfmode_unop (code, operands)
+ enum rtx_code code;
+ rtx *operands;
+{
+ if (TARGET_HARD_QUAD)
+ emit_hard_tfmode_operation (code, operands);
+ else
+ emit_soft_tfmode_unop (code, operands);
+}
+
+void
+emit_tfmode_cvt (code, operands)
+ enum rtx_code code;
+ rtx *operands;
+{
+ if (TARGET_HARD_QUAD)
+ emit_hard_tfmode_operation (code, operands);
+ else
+ emit_soft_tfmode_cvt (code, operands);
+}
+
/* Return nonzero if a return peephole merging return with
setting of output register is ok. */
int
@@ -2414,6 +2770,26 @@ leaf_return_peephole_ok ()
return (actual_fsize == 0);
}
+/* Return nonzero if a branch/jump/call instruction will be emitting
+ nop into its delay slot. */
+
+int
+empty_delay_slot (insn)
+ rtx insn;
+{
+ rtx seq;
+
+ /* If no previous instruction (should not happen), return true. */
+ if (PREV_INSN (insn) == NULL)
+ return 1;
+
+ seq = NEXT_INSN (PREV_INSN (insn));
+ if (GET_CODE (PATTERN (seq)) == SEQUENCE)
+ return 0;
+
+ return 1;
+}
+
/* Return nonzero if TRIAL can go into the function epilogue's
delay slot. SLOT is the slot we are trying to fill. */
@@ -2931,7 +3307,7 @@ load_pic_register ()
}
/* Return 1 if RTX is a MEM which is known to be aligned to at
- least an 8 byte boundary. */
+ least a DESIRED byte boundary. */
int
mem_min_alignment (mem, desired)
@@ -2972,8 +3348,7 @@ mem_min_alignment (mem, desired)
{
int regno = REGNO (base);
- if (regno != FRAME_POINTER_REGNUM
- && regno != STACK_POINTER_REGNUM)
+ if (regno != HARD_FRAME_POINTER_REGNUM && regno != STACK_POINTER_REGNUM)
{
/* Check if the compiler has recorded some information
about the alignment of the base REG. If reload has
@@ -3190,7 +3565,7 @@ sparc_init_modes ()
{
if (i < 16 && TARGET_V8PLUS)
sparc_regno_reg_class[i] = I64_REGS;
- else if (i < 32)
+ else if (i < 32 || i == FRAME_POINTER_REGNUM)
sparc_regno_reg_class[i] = GENERAL_REGS;
else if (i < 64)
sparc_regno_reg_class[i] = FP_REGS;
@@ -3334,31 +3709,28 @@ compute_frame_size (size, leaf_function)
int outgoing_args_size = (current_function_outgoing_args_size
+ REG_PARM_STACK_SPACE (current_function_decl));
- if (TARGET_EPILOGUE)
- {
- /* N_REGS is the number of 4-byte regs saved thus far. This applies
- even to v9 int regs to be consistent with save_regs/restore_regs. */
+ /* N_REGS is the number of 4-byte regs saved thus far. This applies
+ even to v9 int regs to be consistent with save_regs/restore_regs. */
- if (TARGET_ARCH64)
- {
- for (i = 0; i < 8; i++)
- if (regs_ever_live[i] && ! call_used_regs[i])
- n_regs += 2;
- }
- else
- {
- for (i = 0; i < 8; i += 2)
- if ((regs_ever_live[i] && ! call_used_regs[i])
- || (regs_ever_live[i+1] && ! call_used_regs[i+1]))
- n_regs += 2;
- }
-
- for (i = 32; i < (TARGET_V9 ? 96 : 64); i += 2)
+ if (TARGET_ARCH64)
+ {
+ for (i = 0; i < 8; i++)
+ if (regs_ever_live[i] && ! call_used_regs[i])
+ n_regs += 2;
+ }
+ else
+ {
+ for (i = 0; i < 8; i += 2)
if ((regs_ever_live[i] && ! call_used_regs[i])
|| (regs_ever_live[i+1] && ! call_used_regs[i+1]))
n_regs += 2;
}
+ for (i = 32; i < (TARGET_V9 ? 96 : 64); i += 2)
+ if ((regs_ever_live[i] && ! call_used_regs[i])
+ || (regs_ever_live[i+1] && ! call_used_regs[i+1]))
+ n_regs += 2;
+
/* Set up values for use in `function_epilogue'. */
num_gfregs = n_regs;
@@ -3369,9 +3741,8 @@ compute_frame_size (size, leaf_function)
}
else
{
- /* We subtract STARTING_FRAME_OFFSET, remember it's negative.
- The stack bias (if any) is taken out to undo its effects. */
- apparent_fsize = (size - STARTING_FRAME_OFFSET + SPARC_STACK_BIAS + 7) & -8;
+ /* We subtract STARTING_FRAME_OFFSET, remember it's negative. */
+ apparent_fsize = (size - STARTING_FRAME_OFFSET + 7) & -8;
apparent_fsize += n_regs * 4;
actual_fsize = apparent_fsize + ((outgoing_args_size + 7) & -8);
}
@@ -3538,7 +3909,7 @@ sparc_nonflat_function_prologue (file, size, leaf_function)
/* The canonical frame address refers to the top of the frame. */
dwarf2out_def_cfa (label, (leaf_function ? STACK_POINTER_REGNUM
- : FRAME_POINTER_REGNUM),
+ : HARD_FRAME_POINTER_REGNUM),
frame_base_offset);
if (! leaf_function)
@@ -3583,24 +3954,9 @@ sparc_nonflat_function_prologue (file, size, leaf_function)
base = frame_base_name;
}
- n_regs = 0;
- if (TARGET_EPILOGUE && ! leaf_function)
- /* ??? Originally saved regs 0-15 here. */
- n_regs = save_regs (file, 0, 8, base, offset, 0, real_offset);
- else if (leaf_function)
- /* ??? Originally saved regs 0-31 here. */
- n_regs = save_regs (file, 0, 8, base, offset, 0, real_offset);
- if (TARGET_EPILOGUE)
- save_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs,
- real_offset);
- }
-
- leaf_label = 0;
- if (leaf_function && actual_fsize != 0)
- {
- /* warning ("leaf procedure with frame size %d", actual_fsize); */
- if (! TARGET_EPILOGUE)
- leaf_label = gen_label_rtx ();
+ n_regs = save_regs (file, 0, 8, base, offset, 0, real_offset);
+ save_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs,
+ real_offset);
}
}
@@ -3609,7 +3965,7 @@ sparc_nonflat_function_prologue (file, size, leaf_function)
static void
output_restore_regs (file, leaf_function)
FILE *file;
- int leaf_function;
+ int leaf_function ATTRIBUTE_UNUSED;
{
int offset, n_regs;
const char *base;
@@ -3627,15 +3983,8 @@ output_restore_regs (file, leaf_function)
base = frame_base_name;
}
- n_regs = 0;
- if (TARGET_EPILOGUE && ! leaf_function)
- /* ??? Originally saved regs 0-15 here. */
- n_regs = restore_regs (file, 0, 8, base, offset, 0);
- else if (leaf_function)
- /* ??? Originally saved regs 0-31 here. */
- n_regs = restore_regs (file, 0, 8, base, offset, 0);
- if (TARGET_EPILOGUE)
- restore_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs);
+ n_regs = restore_regs (file, 0, 8, base, offset, 0);
+ restore_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs);
}
/* This function generates the assembly code for function exit,
@@ -3668,21 +4017,25 @@ sparc_nonflat_function_epilogue (file, size, leaf_function)
{
const char *ret;
- if (leaf_label)
- {
- emit_label_after (leaf_label, get_last_insn ());
- final_scan_insn (get_last_insn (), file, 0, 0, 1);
- }
-
if (current_function_epilogue_delay_list == 0)
{
/* If code does not drop into the epilogue, we need
- do nothing except output pending case vectors. */
- rtx insn = get_last_insn ();
- if (GET_CODE (insn) == NOTE)
- insn = prev_nonnote_insn (insn);
- if (insn && GET_CODE (insn) == BARRIER)
- goto output_vectors;
+ do nothing except output pending case vectors.
+
+ We have to still output a dummy nop for the sake of
+ sane backtraces. Otherwise, if the last two instructions
+ of a function were call foo; dslot; this can make the return
+ PC of foo (ie. address of call instruction plus 8) point to
+ the first instruction in the next function. */
+ rtx insn;
+
+ fputs("\tnop\n", file);
+
+ insn = get_last_insn ();
+ if (GET_CODE (insn) == NOTE)
+ insn = prev_nonnote_insn (insn);
+ if (insn && GET_CODE (insn) == BARRIER)
+ goto output_vectors;
}
if (num_gfregs)
@@ -3694,95 +4047,93 @@ sparc_nonflat_function_epilogue (file, size, leaf_function)
else
ret = (SKIP_CALLERS_UNIMP_P ? "jmp\t%i7+12" : "ret");
- if (TARGET_EPILOGUE || leaf_label)
+ if (! leaf_function)
{
- int old_target_epilogue = TARGET_EPILOGUE;
- target_flags &= ~old_target_epilogue;
+ if (current_function_calls_eh_return)
+ {
+ if (current_function_epilogue_delay_list)
+ abort ();
+ if (SKIP_CALLERS_UNIMP_P)
+ abort ();
- if (! leaf_function)
+ fputs ("\trestore\n\tretl\n\tadd\t%sp, %g1, %sp\n", file);
+ }
+ /* If we wound up with things in our delay slot, flush them here. */
+ else if (current_function_epilogue_delay_list)
{
- if (current_function_calls_eh_return)
- {
- if (current_function_epilogue_delay_list)
- abort ();
- if (SKIP_CALLERS_UNIMP_P)
- abort ();
+ rtx delay = PATTERN (XEXP (current_function_epilogue_delay_list, 0));
- fputs ("\trestore\n\tretl\n\tadd\t%sp, %g1, %sp\n", file);
+ if (TARGET_V9 && ! epilogue_renumber (&delay, 1))
+ {
+ epilogue_renumber (&delay, 0);
+ fputs (SKIP_CALLERS_UNIMP_P
+ ? "\treturn\t%i7+12\n"
+ : "\treturn\t%i7+8\n", file);
+ final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
+ file, 1, 0, 0);
}
- /* If we wound up with things in our delay slot, flush them here. */
- else if (current_function_epilogue_delay_list)
+ else
{
- rtx delay = PATTERN (XEXP (current_function_epilogue_delay_list, 0));
+ rtx insn, src;
- if (TARGET_V9 && ! epilogue_renumber (&delay, 1))
- {
- epilogue_renumber (&delay, 0);
- fputs (SKIP_CALLERS_UNIMP_P
- ? "\treturn\t%i7+12\n"
- : "\treturn\t%i7+8\n", file);
- final_scan_insn (XEXP (current_function_epilogue_delay_list, 0), file, 1, 0, 0);
- }
- else
- {
- rtx insn = emit_jump_insn_after (gen_rtx_RETURN (VOIDmode),
- get_last_insn ());
- rtx src;
+ if (GET_CODE (delay) != SET)
+ abort();
- if (GET_CODE (delay) != SET)
+ src = SET_SRC (delay);
+ if (GET_CODE (src) == ASHIFT)
+ {
+ if (XEXP (src, 1) != const1_rtx)
abort();
+ SET_SRC (delay)
+ = gen_rtx_PLUS (GET_MODE (src), XEXP (src, 0),
+ XEXP (src, 0));
+ }
- src = SET_SRC (delay);
- if (GET_CODE (src) == ASHIFT)
- {
- if (XEXP (src, 1) != const1_rtx)
- abort();
- SET_SRC (delay) = gen_rtx_PLUS (GET_MODE (src), XEXP (src, 0),
- XEXP (src, 0));
- }
+ insn = gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (2, delay,
+ gen_rtx_RETURN (VOIDmode)));
+ insn = emit_jump_insn (insn);
- PATTERN (insn) = gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, delay, PATTERN (insn)));
- final_scan_insn (insn, file, 1, 0, 1);
- }
+ sparc_emitting_epilogue = true;
+ final_scan_insn (insn, file, 1, 0, 1);
+ sparc_emitting_epilogue = false;
}
- else if (TARGET_V9 && ! SKIP_CALLERS_UNIMP_P)
- fputs ("\treturn\t%i7+8\n\tnop\n", file);
- else
- fprintf (file, "\t%s\n\trestore\n", ret);
}
- else if (current_function_calls_eh_return)
+ else if (TARGET_V9 && ! SKIP_CALLERS_UNIMP_P)
+ fputs ("\treturn\t%i7+8\n\tnop\n", file);
+ else
+ fprintf (file, "\t%s\n\trestore\n", ret);
+ }
+ /* All of the following cases are for leaf functions. */
+ else if (current_function_calls_eh_return)
+ abort ();
+ else if (current_function_epilogue_delay_list)
+ {
+ /* eligible_for_epilogue_delay_slot ensures that if this is a
+ leaf function, then we will only have insn in the delay slot
+ if the frame size is zero, thus no adjust for the stack is
+ needed here. */
+ if (actual_fsize != 0)
abort ();
- /* All of the following cases are for leaf functions. */
- else if (current_function_epilogue_delay_list)
- {
- /* eligible_for_epilogue_delay_slot ensures that if this is a
- leaf function, then we will only have insn in the delay slot
- if the frame size is zero, thus no adjust for the stack is
- needed here. */
- if (actual_fsize != 0)
- abort ();
- fprintf (file, "\t%s\n", ret);
- final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
- file, 1, 0, 1);
- }
- /* Output 'nop' instead of 'sub %sp,-0,%sp' when no frame, so as to
- avoid generating confusing assembly language output. */
- else if (actual_fsize == 0)
- fprintf (file, "\t%s\n\tnop\n", ret);
- else if (actual_fsize <= 4096)
- fprintf (file, "\t%s\n\tsub\t%%sp, -%d, %%sp\n", ret, actual_fsize);
- else if (actual_fsize <= 8192)
- fprintf (file, "\tsub\t%%sp, -4096, %%sp\n\t%s\n\tsub\t%%sp, -%d, %%sp\n",
- ret, actual_fsize - 4096);
- else if ((actual_fsize & 0x3ff) == 0)
- fprintf (file, "\tsethi\t%%hi(%d), %%g1\n\t%s\n\tadd\t%%sp, %%g1, %%sp\n",
- actual_fsize, ret);
- else
- fprintf (file, "\tsethi\t%%hi(%d), %%g1\n\tor\t%%g1, %%lo(%d), %%g1\n\t%s\n\tadd\t%%sp, %%g1, %%sp\n",
- actual_fsize, actual_fsize, ret);
- target_flags |= old_target_epilogue;
+ fprintf (file, "\t%s\n", ret);
+ final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
+ file, 1, 0, 1);
}
+ /* Output 'nop' instead of 'sub %sp,-0,%sp' when no frame, so as to
+ avoid generating confusing assembly language output. */
+ else if (actual_fsize == 0)
+ fprintf (file, "\t%s\n\tnop\n", ret);
+ else if (actual_fsize <= 4096)
+ fprintf (file, "\t%s\n\tsub\t%%sp, -%d, %%sp\n", ret, actual_fsize);
+ else if (actual_fsize <= 8192)
+ fprintf (file, "\tsub\t%%sp, -4096, %%sp\n\t%s\n\tsub\t%%sp, -%d, %%sp\n",
+ ret, actual_fsize - 4096);
+ else if ((actual_fsize & 0x3ff) == 0)
+ fprintf (file, "\tsethi\t%%hi(%d), %%g1\n\t%s\n\tadd\t%%sp, %%g1, %%sp\n",
+ actual_fsize, ret);
+ else
+ fprintf (file, "\tsethi\t%%hi(%d), %%g1\n\tor\t%%g1, %%lo(%d), %%g1\n\t%s\n\tadd\t%%sp, %%g1, %%sp\n",
+ actual_fsize, actual_fsize, ret);
output_vectors:
sparc_output_deferred_case_vectors ();
@@ -4222,7 +4573,10 @@ function_arg_record_value_1 (type, startbitpos, parms)
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
function_arg_record_value_1 (TREE_TYPE (field), bitpos, parms);
- else if (TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
+ else if ((TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
+ || (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE
+ && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
+ == REAL_TYPE)))
&& TARGET_FPU
&& ! packed_p
&& parms->named)
@@ -4245,6 +4599,8 @@ function_arg_record_value_1 (type, startbitpos, parms)
/* There's no need to check this_slotno < SPARC_FP_ARG MAX.
If it wasn't true we wouldn't be here. */
parms->nregs += 1;
+ if (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE)
+ parms->nregs += 1;
}
else
{
@@ -4348,24 +4704,45 @@ function_arg_record_value_2 (type, startbitpos, parms)
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
function_arg_record_value_2 (TREE_TYPE (field), bitpos, parms);
- else if (TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
+ else if ((TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
+ || (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE
+ && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
+ == REAL_TYPE)))
&& TARGET_FPU
&& ! packed_p
&& parms->named)
{
int this_slotno = parms->slotno + bitpos / BITS_PER_WORD;
+ int regno;
+ enum machine_mode mode = DECL_MODE (field);
rtx reg;
function_arg_record_value_3 (bitpos, parms);
-
- reg = gen_rtx_REG (DECL_MODE (field),
- (SPARC_FP_ARG_FIRST + this_slotno * 2
- + (DECL_MODE (field) == SFmode
- && (bitpos & 32) != 0)));
+ regno = SPARC_FP_ARG_FIRST + this_slotno * 2
+ + ((mode == SFmode || mode == SCmode)
+ && (bitpos & 32) != 0);
+ switch (mode)
+ {
+ case SCmode: mode = SFmode; break;
+ case DCmode: mode = DFmode; break;
+ case TCmode: mode = TFmode; break;
+ default: break;
+ }
+ reg = gen_rtx_REG (mode, regno);
XVECEXP (parms->ret, 0, parms->nregs)
= gen_rtx_EXPR_LIST (VOIDmode, reg,
GEN_INT (bitpos / BITS_PER_UNIT));
parms->nregs += 1;
+ if (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE)
+ {
+ regno += GET_MODE_SIZE (mode) / 4;
+ reg = gen_rtx_REG (mode, regno);
+ XVECEXP (parms->ret, 0, parms->nregs)
+ = gen_rtx_EXPR_LIST (VOIDmode, reg,
+ GEN_INT ((bitpos + GET_MODE_BITSIZE (mode))
+ / BITS_PER_UNIT));
+ parms->nregs += 1;
+ }
}
else
{
@@ -4693,8 +5070,9 @@ function_arg_pass_by_reference (cum, mode, type, named)
return ((type && TREE_CODE (type) == ARRAY_TYPE)
/* Consider complex values as aggregates, so care for TCmode. */
|| GET_MODE_SIZE (mode) > 16
- || (type && AGGREGATE_TYPE_P (type)
- && int_size_in_bytes (type) > 16));
+ || (type
+ && AGGREGATE_TYPE_P (type)
+ && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 16));
}
}
@@ -4846,7 +5224,7 @@ sparc_builtin_saveregs ()
emit_move_insn (gen_rtx_MEM (word_mode,
gen_rtx_PLUS (Pmode,
frame_pointer_rtx,
- GEN_INT (STACK_POINTER_OFFSET
+ GEN_INT (FIRST_PARM_OFFSET (0)
+ (UNITS_PER_WORD
* regno)))),
gen_rtx_REG (word_mode,
@@ -4854,7 +5232,7 @@ sparc_builtin_saveregs ()
address = gen_rtx_PLUS (Pmode,
frame_pointer_rtx,
- GEN_INT (STACK_POINTER_OFFSET
+ GEN_INT (FIRST_PARM_OFFSET (0)
+ UNITS_PER_WORD * first_reg));
return address;
@@ -4895,11 +5273,15 @@ sparc_va_arg (valist, type)
if (AGGREGATE_TYPE_P (type))
{
- if (size > 16)
+ if ((unsigned HOST_WIDE_INT) size > 16)
{
indirect = 1;
size = rsize = UNITS_PER_WORD;
}
+ /* SPARC v9 ABI states that structures up to 8 bytes in size are
+ given one 8 byte slot. */
+ else if (size == 0)
+ size = rsize = UNITS_PER_WORD;
else
size = rsize;
}
@@ -4994,25 +5376,43 @@ sparc_va_arg (valist, type)
INSN, if set, is the insn. */
char *
-output_cbranch (op, label, reversed, annul, noop, insn)
- rtx op;
+output_cbranch (op, dest, label, reversed, annul, noop, insn)
+ rtx op, dest;
int label;
int reversed, annul, noop;
rtx insn;
{
- static char string[32];
+ static char string[50];
enum rtx_code code = GET_CODE (op);
rtx cc_reg = XEXP (op, 0);
enum machine_mode mode = GET_MODE (cc_reg);
- static char v8_labelno[] = "%lX";
- static char v9_icc_labelno[] = "%%icc, %lX";
- static char v9_xcc_labelno[] = "%%xcc, %lX";
- static char v9_fcc_labelno[] = "%%fccX, %lY";
- char *labelno;
- const char *branch;
- int labeloff, spaces = 8;
+ const char *labelno, *branch;
+ int spaces = 8, far;
+ char *p;
+
+ /* v9 branches are limited to +-1MB. If it is too far away,
+ change
+
+ bne,pt %xcc, .LC30
+
+ to
+
+ be,pn %xcc, .+12
+ nop
+ ba .LC30
+
+ and
+
+ fbne,a,pn %fcc2, .LC29
+
+ to
- if (reversed)
+ fbe,pt %fcc2, .+16
+ nop
+ ba .LC29 */
+
+ far = get_attr_length (insn) >= 3;
+ if (reversed ^ far)
{
/* Reversal of FP compares takes care -- an ordered compare
becomes an unordered compare and vice versa. */
@@ -5095,7 +5495,7 @@ output_cbranch (op, label, reversed, annul, noop, insn)
branch = "be";
break;
case GE:
- if (mode == CC_NOOVmode)
+ if (mode == CC_NOOVmode || mode == CCX_NOOVmode)
branch = "bpos";
else
branch = "bge";
@@ -5107,7 +5507,7 @@ output_cbranch (op, label, reversed, annul, noop, insn)
branch = "ble";
break;
case LT:
- if (mode == CC_NOOVmode)
+ if (mode == CC_NOOVmode || mode == CCX_NOOVmode)
branch = "bneg";
else
branch = "bl";
@@ -5131,54 +5531,89 @@ output_cbranch (op, label, reversed, annul, noop, insn)
strcpy (string, branch);
}
spaces -= strlen (branch);
+ p = strchr (string, '\0');
/* Now add the annulling, the label, and a possible noop. */
- if (annul)
+ if (annul && ! far)
{
- strcat (string, ",a");
+ strcpy (p, ",a");
+ p += 2;
spaces -= 2;
}
if (! TARGET_V9)
- {
- labeloff = 2;
- labelno = v8_labelno;
- }
+ labelno = "";
else
{
rtx note;
+ int v8 = 0;
- if (insn && (note = find_reg_note (insn, REG_BR_PRED, NULL_RTX)))
+ if (! far && insn && INSN_ADDRESSES_SET_P ())
{
- strcat (string,
- INTVAL (XEXP (note, 0)) & ATTR_FLAG_likely ? ",pt" : ",pn");
- spaces -= 3;
+ int delta = (INSN_ADDRESSES (INSN_UID (dest))
+ - INSN_ADDRESSES (INSN_UID (insn)));
+ /* Leave some instructions for "slop". */
+ if (delta < -260000 || delta >= 260000)
+ v8 = 1;
}
- labeloff = 9;
if (mode == CCFPmode || mode == CCFPEmode)
{
- labeloff = 10;
- labelno = v9_fcc_labelno;
+ static char v9_fcc_labelno[] = "%%fccX, ";
/* Set the char indicating the number of the fcc reg to use. */
- labelno[5] = REGNO (cc_reg) - SPARC_FIRST_V9_FCC_REG + '0';
+ v9_fcc_labelno[5] = REGNO (cc_reg) - SPARC_FIRST_V9_FCC_REG + '0';
+ labelno = v9_fcc_labelno;
+ if (v8)
+ {
+ if (REGNO (cc_reg) == SPARC_FCC_REG)
+ labelno = "";
+ else
+ abort ();
+ }
}
else if (mode == CCXmode || mode == CCX_NOOVmode)
- labelno = v9_xcc_labelno;
+ {
+ labelno = "%%xcc, ";
+ if (v8)
+ abort ();
+ }
else
- labelno = v9_icc_labelno;
+ {
+ labelno = "%%icc, ";
+ if (v8)
+ labelno = "";
+ }
+
+ if (*labelno && insn && (note = find_reg_note (insn, REG_BR_PROB, NULL_RTX)))
+ {
+ strcpy (p,
+ ((INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2) ^ far)
+ ? ",pt" : ",pn");
+ p += 3;
+ spaces -= 3;
+ }
}
- /* Set the char indicating the number of the operand containing the
- label_ref. */
- labelno[labeloff] = label + '0';
if (spaces > 0)
- strcat (string, "\t");
+ *p++ = '\t';
else
- strcat (string, " ");
- strcat (string, labelno);
-
+ *p++ = ' ';
+ strcpy (p, labelno);
+ p = strchr (p, '\0');
+ if (far)
+ {
+ strcpy (p, ".+12\n\tnop\n\tb\t");
+ if (annul || noop)
+ p[3] = '6';
+ p += 13;
+ }
+ *p++ = '%';
+ *p++ = 'l';
+ /* Set the char indicating the number of the operand containing the
+ label_ref. */
+ *p++ = label + '0';
+ *p = '\0';
if (noop)
- strcat (string, "\n\tnop");
+ strcpy (p, "\n\tnop");
return string;
}
@@ -5257,7 +5692,7 @@ sparc_emit_float_lib_cmp (x, y, comparison)
else
slot1 = y;
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), 1,
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), LCT_NORMAL,
DImode, 2,
XEXP (slot0, 0), Pmode,
XEXP (slot1, 0), Pmode);
@@ -5266,7 +5701,7 @@ sparc_emit_float_lib_cmp (x, y, comparison)
}
else
{
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), 1,
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), LCT_NORMAL,
SImode, 2,
x, TFmode, y, TFmode);
@@ -5324,6 +5759,42 @@ sparc_emit_float_lib_cmp (x, y, comparison)
}
}
+/* Generate an unsigned DImode to FP conversion. This is the same code
+ optabs would emit if we didn't have TFmode patterns. */
+
+void
+sparc_emit_floatunsdi (operands)
+ rtx operands[2];
+{
+ rtx neglab, donelab, i0, i1, f0, in, out;
+ enum machine_mode mode;
+
+ out = operands[0];
+ in = force_reg (DImode, operands[1]);
+ mode = GET_MODE (out);
+ neglab = gen_label_rtx ();
+ donelab = gen_label_rtx ();
+ i0 = gen_reg_rtx (DImode);
+ i1 = gen_reg_rtx (DImode);
+ f0 = gen_reg_rtx (mode);
+
+ emit_cmp_and_jump_insns (in, const0_rtx, LT, const0_rtx, DImode, 0, neglab);
+
+ emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_FLOAT (mode, in)));
+ emit_jump_insn (gen_jump (donelab));
+ emit_barrier ();
+
+ emit_label (neglab);
+
+ emit_insn (gen_lshrdi3 (i0, in, const1_rtx));
+ emit_insn (gen_anddi3 (i1, in, const1_rtx));
+ emit_insn (gen_iordi3 (i0, i0, i1));
+ emit_insn (gen_rtx_SET (VOIDmode, f0, gen_rtx_FLOAT (mode, i0)));
+ emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_PLUS (mode, f0, f0)));
+
+ emit_label (donelab);
+}
+
/* Return the string to output a conditional branch to LABEL, testing
register REG. LABEL is the operand number of the label; REG is the
operand number of the reg. OP is the conditional expression. The mode
@@ -5336,22 +5807,45 @@ sparc_emit_float_lib_cmp (x, y, comparison)
NOOP is non-zero if we have to follow this branch by a noop. */
char *
-output_v9branch (op, reg, label, reversed, annul, noop, insn)
- rtx op;
+output_v9branch (op, dest, reg, label, reversed, annul, noop, insn)
+ rtx op, dest;
int reg, label;
int reversed, annul, noop;
rtx insn;
{
- static char string[20];
+ static char string[50];
enum rtx_code code = GET_CODE (op);
enum machine_mode mode = GET_MODE (XEXP (op, 0));
- static char labelno[] = "%X, %lX";
rtx note;
- int spaces = 8;
+ int far;
+ char *p;
+
+ /* branch on register are limited to +-128KB. If it is too far away,
+ change
+
+ brnz,pt %g1, .LC30
+
+ to
+
+ brz,pn %g1, .+12
+ nop
+ ba,pt %xcc, .LC30
+
+ and
+
+ brgez,a,pn %o1, .LC29
+
+ to
+
+ brlz,pt %o1, .+16
+ nop
+ ba,pt %xcc, .LC29 */
+
+ far = get_attr_length (insn) >= 3;
/* If not floating-point or if EQ or NE, we can just reverse the code. */
- if (reversed)
- code = reverse_condition (code), reversed = 0;
+ if (reversed ^ far)
+ code = reverse_condition (code);
/* Only 64 bit versions of these instructions exist. */
if (mode != DImode)
@@ -5363,62 +5857,90 @@ output_v9branch (op, reg, label, reversed, annul, noop, insn)
{
case NE:
strcpy (string, "brnz");
- spaces -= 4;
break;
case EQ:
strcpy (string, "brz");
- spaces -= 3;
break;
case GE:
strcpy (string, "brgez");
- spaces -= 5;
break;
case LT:
strcpy (string, "brlz");
- spaces -= 4;
break;
case LE:
strcpy (string, "brlez");
- spaces -= 5;
break;
case GT:
strcpy (string, "brgz");
- spaces -= 4;
break;
default:
abort ();
}
+ p = strchr (string, '\0');
+
/* Now add the annulling, reg, label, and nop. */
- if (annul)
+ if (annul && ! far)
{
- strcat (string, ",a");
- spaces -= 2;
+ strcpy (p, ",a");
+ p += 2;
}
- if (insn && (note = find_reg_note (insn, REG_BR_PRED, NULL_RTX)))
+ if (insn && (note = find_reg_note (insn, REG_BR_PROB, NULL_RTX)))
{
- strcat (string,
- INTVAL (XEXP (note, 0)) & ATTR_FLAG_likely ? ",pt" : ",pn");
- spaces -= 3;
+ strcpy (p,
+ ((INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2) ^ far)
+ ? ",pt" : ",pn");
+ p += 3;
}
- labelno[1] = reg + '0';
- labelno[6] = label + '0';
- if (spaces > 0)
- strcat (string, "\t");
- else
- strcat (string, " ");
- strcat (string, labelno);
+ *p = p < string + 8 ? '\t' : ' ';
+ p++;
+ *p++ = '%';
+ *p++ = '0' + reg;
+ *p++ = ',';
+ *p++ = ' ';
+ if (far)
+ {
+ int veryfar = 1, delta;
+
+ if (INSN_ADDRESSES_SET_P ())
+ {
+ delta = (INSN_ADDRESSES (INSN_UID (dest))
+ - INSN_ADDRESSES (INSN_UID (insn)));
+ /* Leave some instructions for "slop". */
+ if (delta >= -260000 && delta < 260000)
+ veryfar = 0;
+ }
+
+ strcpy (p, ".+12\n\tnop\n\t");
+ if (annul || noop)
+ p[3] = '6';
+ p += 11;
+ if (veryfar)
+ {
+ strcpy (p, "b\t");
+ p += 2;
+ }
+ else
+ {
+ strcpy (p, "ba,pt\t%%xcc, ");
+ p += 13;
+ }
+ }
+ *p++ = '%';
+ *p++ = 'l';
+ *p++ = '0' + label;
+ *p = '\0';
if (noop)
- strcat (string, "\n\tnop");
+ strcpy (p, "\n\tnop");
return string;
}
@@ -5467,7 +5989,7 @@ epilogue_renumber (where, test)
are in the return delayed slot. */
case PLUS:
if (GET_CODE (XEXP (*where, 0)) == REG
- && REGNO (XEXP (*where, 0)) == FRAME_POINTER_REGNUM
+ && REGNO (XEXP (*where, 0)) == HARD_FRAME_POINTER_REGNUM
&& (GET_CODE (XEXP (*where, 1)) != CONST_INT
|| INTVAL (XEXP (*where, 1)) < SPARC_STACK_BIAS))
return 1;
@@ -5476,7 +5998,7 @@ epilogue_renumber (where, test)
case MEM:
if (SPARC_STACK_BIAS
&& GET_CODE (XEXP (*where, 0)) == REG
- && REGNO (XEXP (*where, 0)) == FRAME_POINTER_REGNUM)
+ && REGNO (XEXP (*where, 0)) == HARD_FRAME_POINTER_REGNUM)
return 1;
break;
@@ -5501,87 +6023,6 @@ epilogue_renumber (where, test)
}
return 0;
}
-
-/* Output assembler code to return from a function. */
-
-const char *
-output_return (operands)
- rtx *operands;
-{
- rtx delay = final_sequence ? XVECEXP (final_sequence, 0, 1) : 0;
-
- if (leaf_label)
- {
- operands[0] = leaf_label;
- return "b%* %l0%(";
- }
- else if (current_function_uses_only_leaf_regs)
- {
- /* No delay slot in a leaf function. */
- if (delay)
- abort ();
-
- /* If we didn't allocate a frame pointer for the current function,
- the stack pointer might have been adjusted. Output code to
- restore it now. */
-
- operands[0] = GEN_INT (actual_fsize);
-
- /* Use sub of negated value in first two cases instead of add to
- allow actual_fsize == 4096. */
-
- if (actual_fsize <= 4096)
- {
- if (SKIP_CALLERS_UNIMP_P)
- return "jmp\t%%o7+12\n\tsub\t%%sp, -%0, %%sp";
- else
- return "retl\n\tsub\t%%sp, -%0, %%sp";
- }
- else if (actual_fsize <= 8192)
- {
- operands[0] = GEN_INT (actual_fsize - 4096);
- if (SKIP_CALLERS_UNIMP_P)
- return "sub\t%%sp, -4096, %%sp\n\tjmp\t%%o7+12\n\tsub\t%%sp, -%0, %%sp";
- else
- return "sub\t%%sp, -4096, %%sp\n\tretl\n\tsub\t%%sp, -%0, %%sp";
- }
- else if (SKIP_CALLERS_UNIMP_P)
- {
- if ((actual_fsize & 0x3ff) != 0)
- return "sethi\t%%hi(%a0), %%g1\n\tor\t%%g1, %%lo(%a0), %%g1\n\tjmp\t%%o7+12\n\tadd\t%%sp, %%g1, %%sp";
- else
- return "sethi\t%%hi(%a0), %%g1\n\tjmp\t%%o7+12\n\tadd\t%%sp, %%g1, %%sp";
- }
- else
- {
- if ((actual_fsize & 0x3ff) != 0)
- return "sethi\t%%hi(%a0), %%g1\n\tor\t%%g1, %%lo(%a0), %%g1\n\tretl\n\tadd\t%%sp, %%g1, %%sp";
- else
- return "sethi\t%%hi(%a0), %%g1\n\tretl\n\tadd\t%%sp, %%g1, %%sp";
- }
- }
- else if (TARGET_V9)
- {
- if (delay)
- {
- epilogue_renumber (&SET_DEST (PATTERN (delay)), 0);
- epilogue_renumber (&SET_SRC (PATTERN (delay)), 0);
- }
- if (SKIP_CALLERS_UNIMP_P)
- return "return\t%%i7+12%#";
- else
- return "return\t%%i7+8%#";
- }
- else
- {
- if (delay)
- abort ();
- if (SKIP_CALLERS_UNIMP_P)
- return "jmp\t%%i7+12\n\trestore";
- else
- return "ret\n\trestore";
- }
-}
/* Leaf functions and non-leaf functions have different needs. */
@@ -5689,6 +6130,20 @@ registers_ok_for_ldd_peep (reg1, reg2)
ld [%o0 + 4], %o1
to
ldd [%o0], %o0
+ nor:
+ ld [%g3 + 4], %g3
+ ld [%g3], %g2
+ to
+ ldd [%g3], %g2
+
+ But, note that the transformation from:
+ ld [%g2 + 4], %g3
+ ld [%g2], %g2
+ to
+ ldd [%g2], %g2
+ is perfectly fine. Thus, the peephole2 patterns always pass us
+ the destination register of the first load, never the second one.
+
For stores we don't have a similar problem, so dependent_reg_rtx is
NULL_RTX. */
@@ -5987,9 +6442,7 @@ print_operand (file, x, code)
case 'b':
{
/* Print a sign-extended character. */
- int i = INTVAL (x) & 0xff;
- if (i & 0x80)
- i |= 0xffffff00;
+ int i = trunc_int_for_mode (INTVAL (x), QImode);
fprintf (file, "%d", i);
return;
}
@@ -6260,38 +6713,42 @@ sparc_initialize_trampoline (tramp, fnaddr, cxt)
*/
#ifdef TRANSFER_FROM_TRAMPOLINE
emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"),
- 0, VOIDmode, 1, tramp, Pmode);
+ LCT_NORMAL, VOIDmode, 1, tramp, Pmode);
#endif
- emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 0)),
- expand_binop (SImode, ior_optab,
- expand_shift (RSHIFT_EXPR, SImode, fnaddr,
- size_int (10), 0, 1),
- GEN_INT (0x03000000),
- NULL_RTX, 1, OPTAB_DIRECT));
-
- emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 4)),
- expand_binop (SImode, ior_optab,
- expand_shift (RSHIFT_EXPR, SImode, cxt,
- size_int (10), 0, 1),
- GEN_INT (0x05000000),
- NULL_RTX, 1, OPTAB_DIRECT));
-
- emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 8)),
- expand_binop (SImode, ior_optab,
- expand_and (fnaddr, GEN_INT (0x3ff), NULL_RTX),
- GEN_INT (0x81c06000),
- NULL_RTX, 1, OPTAB_DIRECT));
-
- emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 12)),
- expand_binop (SImode, ior_optab,
- expand_and (cxt, GEN_INT (0x3ff), NULL_RTX),
- GEN_INT (0x8410a000),
- NULL_RTX, 1, OPTAB_DIRECT));
+ emit_move_insn
+ (gen_rtx_MEM (SImode, plus_constant (tramp, 0)),
+ expand_binop (SImode, ior_optab,
+ expand_shift (RSHIFT_EXPR, SImode, fnaddr,
+ size_int (10), 0, 1),
+ GEN_INT (trunc_int_for_mode (0x03000000, SImode)),
+ NULL_RTX, 1, OPTAB_DIRECT));
+
+ emit_move_insn
+ (gen_rtx_MEM (SImode, plus_constant (tramp, 4)),
+ expand_binop (SImode, ior_optab,
+ expand_shift (RSHIFT_EXPR, SImode, cxt,
+ size_int (10), 0, 1),
+ GEN_INT (trunc_int_for_mode (0x05000000, SImode)),
+ NULL_RTX, 1, OPTAB_DIRECT));
+
+ emit_move_insn
+ (gen_rtx_MEM (SImode, plus_constant (tramp, 8)),
+ expand_binop (SImode, ior_optab,
+ expand_and (SImode, fnaddr, GEN_INT (0x3ff), NULL_RTX),
+ GEN_INT (trunc_int_for_mode (0x81c06000, SImode)),
+ NULL_RTX, 1, OPTAB_DIRECT));
+
+ emit_move_insn
+ (gen_rtx_MEM (SImode, plus_constant (tramp, 12)),
+ expand_binop (SImode, ior_optab,
+ expand_and (SImode, cxt, GEN_INT (0x3ff), NULL_RTX),
+ GEN_INT (trunc_int_for_mode (0x8410a000, SImode)),
+ NULL_RTX, 1, OPTAB_DIRECT));
- emit_insn (gen_flush (validize_mem (gen_rtx_MEM (SImode, tramp))));
/* On UltraSPARC a flush flushes an entire cache line. The trampoline is
aligned on a 16 byte boundary so one flush clears it all. */
+ emit_insn (gen_flush (validize_mem (gen_rtx_MEM (SImode, tramp))));
if (sparc_cpu != PROCESSOR_ULTRASPARC)
emit_insn (gen_flush (validize_mem (gen_rtx_MEM (SImode,
plus_constant (tramp, 8)))));
@@ -6307,7 +6764,7 @@ sparc64_initialize_trampoline (tramp, fnaddr, cxt)
{
#ifdef TRANSFER_FROM_TRAMPOLINE
emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"),
- 0, VOIDmode, 1, tramp, Pmode);
+ LCT_NORMAL, VOIDmode, 1, tramp, Pmode);
#endif
/*
@@ -6319,13 +6776,13 @@ sparc64_initialize_trampoline (tramp, fnaddr, cxt)
*/
emit_move_insn (gen_rtx_MEM (SImode, tramp),
- GEN_INT (0x83414000));
+ GEN_INT (trunc_int_for_mode (0x83414000, SImode)));
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 4)),
- GEN_INT (0xca586018));
+ GEN_INT (trunc_int_for_mode (0xca586018, SImode)));
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 8)),
- GEN_INT (0x81c14000));
+ GEN_INT (trunc_int_for_mode (0x81c14000, SImode)));
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 12)),
- GEN_INT (0xca586010));
+ GEN_INT (trunc_int_for_mode (0xca586010, SImode)));
emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, 16)), cxt);
emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, 24)), fnaddr);
emit_insn (gen_flushdi (validize_mem (gen_rtx_MEM (DImode, tramp))));
@@ -6421,12 +6878,12 @@ struct sparc_frame_info zero_frame_info;
/* Tell prologue and epilogue if register REGNO should be saved / restored. */
#define RETURN_ADDR_REGNUM 15
-#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
+#define HARD_FRAME_POINTER_MASK (1 << (HARD_FRAME_POINTER_REGNUM))
#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
#define MUST_SAVE_REGISTER(regno) \
- ((regs_ever_live[regno] && !call_used_regs[regno]) \
- || (regno == FRAME_POINTER_REGNUM && frame_pointer_needed) \
+ ((regs_ever_live[regno] && !call_used_regs[regno]) \
+ || (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) \
|| (regno == RETURN_ADDR_REGNUM && regs_ever_live[RETURN_ADDR_REGNUM]))
/* Return the bytes needed to compute the frame pointer from the current
@@ -6699,7 +7156,7 @@ sparc_flat_function_prologue (file, size)
if (size > 0)
{
unsigned int reg_offset = current_frame_info.reg_offset;
- const char *const fp_str = reg_names[FRAME_POINTER_REGNUM];
+ const char *const fp_str = reg_names[HARD_FRAME_POINTER_REGNUM];
static const char *const t1_str = "%g1";
/* Things get a little tricky if local variables take up more than ~4096
@@ -6720,7 +7177,7 @@ sparc_flat_function_prologue (file, size)
{
fprintf (file, "\tadd\t%s, %d, %s\n",
sp_str, (int) -size, sp_str);
- if (gmask & FRAME_POINTER_MASK)
+ if (gmask & HARD_FRAME_POINTER_MASK)
{
fprintf (file, "\tst\t%s, [%s+%d]\n",
fp_str, sp_str, reg_offset);
@@ -6735,7 +7192,7 @@ sparc_flat_function_prologue (file, size)
fprintf (file, HOST_WIDE_INT_PRINT_DEC, size);
fprintf (file, ", %s\n\tsub\t%s, %s, %s\n",
t1_str, sp_str, t1_str, sp_str);
- if (gmask & FRAME_POINTER_MASK)
+ if (gmask & HARD_FRAME_POINTER_MASK)
{
fprintf (file, "\tst\t%s, [%s+%d]\n",
fp_str, sp_str, reg_offset);
@@ -6747,11 +7204,11 @@ sparc_flat_function_prologue (file, size)
if (dwarf2out_do_frame ())
{
char *l = dwarf2out_cfi_label ();
- if (gmask & FRAME_POINTER_MASK)
+ if (gmask & HARD_FRAME_POINTER_MASK)
{
- dwarf2out_reg_save (l, FRAME_POINTER_REGNUM,
+ dwarf2out_reg_save (l, HARD_FRAME_POINTER_REGNUM,
reg_offset - 4 - size);
- dwarf2out_def_cfa (l, FRAME_POINTER_REGNUM, 0);
+ dwarf2out_def_cfa (l, HARD_FRAME_POINTER_REGNUM, 0);
}
else
dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, size);
@@ -6765,7 +7222,7 @@ sparc_flat_function_prologue (file, size)
reg_offset += 4;
}
sparc_flat_save_restore (file, sp_str, reg_offset,
- gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),
+ gmask & ~(HARD_FRAME_POINTER_MASK | RETURN_ADDR_MASK),
current_frame_info.fmask,
"st", "std", -size);
}
@@ -6782,7 +7239,7 @@ sparc_flat_function_prologue (file, size)
{
fprintf (file, "\tadd\t%s, %d, %s\n",
sp_str, (int) -size1, sp_str);
- if (gmask & FRAME_POINTER_MASK)
+ if (gmask & HARD_FRAME_POINTER_MASK)
{
fprintf (file, "\tst\t%s, [%s+%d]\n\tsub\t%s, %d, %s\t%s# set up frame pointer\n",
fp_str, sp_str, (int) offset, sp_str, (int) -size1,
@@ -6796,7 +7253,7 @@ sparc_flat_function_prologue (file, size)
fprintf (file, HOST_WIDE_INT_PRINT_DEC, size1);
fprintf (file, ", %s\n\tsub\t%s, %s, %s\n",
t1_str, sp_str, t1_str, sp_str);
- if (gmask & FRAME_POINTER_MASK)
+ if (gmask & HARD_FRAME_POINTER_MASK)
{
fprintf (file, "\tst\t%s, [%s+%d]\n\tadd\t%s, %s, %s\t%s# set up frame pointer\n",
fp_str, sp_str, (int) offset, sp_str, t1_str,
@@ -6807,11 +7264,11 @@ sparc_flat_function_prologue (file, size)
if (dwarf2out_do_frame ())
{
char *l = dwarf2out_cfi_label ();
- if (gmask & FRAME_POINTER_MASK)
+ if (gmask & HARD_FRAME_POINTER_MASK)
{
- dwarf2out_reg_save (l, FRAME_POINTER_REGNUM,
+ dwarf2out_reg_save (l, HARD_FRAME_POINTER_REGNUM,
offset - 4 - size1);
- dwarf2out_def_cfa (l, FRAME_POINTER_REGNUM, 0);
+ dwarf2out_def_cfa (l, HARD_FRAME_POINTER_REGNUM, 0);
}
else
dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, size1);
@@ -6827,7 +7284,7 @@ sparc_flat_function_prologue (file, size)
offset += 4;
}
sparc_flat_save_restore (file, sp_str, offset,
- gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),
+ gmask & ~(HARD_FRAME_POINTER_MASK | RETURN_ADDR_MASK),
current_frame_info.fmask,
"st", "std", -size1);
fprintf (file, "\tset\t");
@@ -6835,7 +7292,7 @@ sparc_flat_function_prologue (file, size)
fprintf (file, ", %s\n\tsub\t%s, %s, %s\n",
t1_str, sp_str, t1_str, sp_str);
if (dwarf2out_do_frame ())
- if (! (gmask & FRAME_POINTER_MASK))
+ if (! (gmask & HARD_FRAME_POINTER_MASK))
dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, size);
}
}
@@ -6884,7 +7341,7 @@ sparc_flat_function_epilogue (file, size)
unsigned HOST_WIDE_INT reg_offset = current_frame_info.reg_offset;
unsigned HOST_WIDE_INT size1;
const char *const sp_str = reg_names[STACK_POINTER_REGNUM];
- const char *const fp_str = reg_names[FRAME_POINTER_REGNUM];
+ const char *const fp_str = reg_names[HARD_FRAME_POINTER_REGNUM];
static const char *const t1_str = "%g1";
/* In the reload sequence, we don't need to fill the load delay
@@ -6930,7 +7387,7 @@ sparc_flat_function_epilogue (file, size)
/* We must restore the frame pointer and return address reg first
because they are treated specially by the prologue output code. */
- if (current_frame_info.gmask & FRAME_POINTER_MASK)
+ if (current_frame_info.gmask & HARD_FRAME_POINTER_MASK)
{
fprintf (file, "\tld\t[%s+%d], %s\n",
sp_str, (int) reg_offset, fp_str);
@@ -6945,7 +7402,7 @@ sparc_flat_function_epilogue (file, size)
/* Restore any remaining saved registers. */
sparc_flat_save_restore (file, sp_str, reg_offset,
- current_frame_info.gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),
+ current_frame_info.gmask & ~(HARD_FRAME_POINTER_MASK | RETURN_ADDR_MASK),
current_frame_info.fmask,
"ld", "ldd", 0);
@@ -8397,60 +8854,24 @@ sparc_v8plus_shift (operands, insn, opcode)
else
return strcat (asm_code, "\t%3, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0");
}
-
-
-/* Return 1 if DEST and SRC reference only global and in registers. */
-
-int
-sparc_return_peephole_ok (dest, src)
- rtx dest, src;
-{
- if (! TARGET_V9)
- return 0;
- if (current_function_uses_only_leaf_regs)
- return 0;
- if (GET_CODE (src) != CONST_INT
- && (GET_CODE (src) != REG || ! IN_OR_GLOBAL_P (src)))
- return 0;
- return IN_OR_GLOBAL_P (dest);
-}
-/* Output assembler code to FILE to increment profiler label # LABELNO
- for profiling a function entry.
-
- 32 bit sparc uses %g2 as the STATIC_CHAIN_REGNUM which gets clobbered
- during profiling so we need to save/restore it around the call to mcount.
- We're guaranteed that a save has just been done, and we use the space
- allocated for intreg/fpreg value passing. */
+/* Output rtl to increment the profiler label LABELNO
+ for profiling a function entry. */
void
-sparc_function_profiler (file, labelno)
- FILE *file;
+sparc_profile_hook (labelno)
int labelno;
{
char buf[32];
- ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
-
- if (! TARGET_ARCH64)
- fputs ("\tst\t%g2, [%fp-4]\n", file);
-
- fputs ("\tsethi\t%hi(", file);
- assemble_name (file, buf);
- fputs ("), %o0\n", file);
+ rtx lab, fun;
- fputs ("\tcall\t", file);
- assemble_name (file, MCOUNT_FUNCTION);
- putc ('\n', file);
-
- fputs ("\t or\t%o0, %lo(", file);
- assemble_name (file, buf);
- fputs ("), %o0\n", file);
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
+ lab = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
+ fun = gen_rtx_SYMBOL_REF (Pmode, MCOUNT_FUNCTION);
- if (! TARGET_ARCH64)
- fputs ("\tld\t[%fp-4], %g2\n", file);
+ emit_library_call (fun, LCT_NORMAL, VOIDmode, 1, lab, Pmode);
}
-
-
+
/* Mark ARG, which is really a struct ultrasparc_pipline_state *, for
GC. */
@@ -8474,7 +8895,6 @@ sparc_add_gc_roots ()
{
ggc_add_rtx_root (&sparc_compare_op0, 1);
ggc_add_rtx_root (&sparc_compare_op1, 1);
- ggc_add_rtx_root (&leaf_label, 1);
ggc_add_rtx_root (&global_offset_table, 1);
ggc_add_rtx_root (&get_pc_symbol, 1);
ggc_add_rtx_root (&sparc_addr_diff_list, 1);
@@ -8511,3 +8931,65 @@ sparc_elf_asm_named_section (name, flags)
fputc ('\n', asm_out_file);
}
#endif /* OBJECT_FORMAT_ELF */
+
+int
+sparc_extra_constraint_check (op, c, strict)
+ rtx op;
+ int c;
+ int strict;
+{
+ int reload_ok_mem;
+
+ if (TARGET_ARCH64
+ && (c == 'T' || c == 'U'))
+ return 0;
+
+ switch (c)
+ {
+ case 'Q':
+ return fp_sethi_p (op);
+
+ case 'R':
+ return fp_mov_p (op);
+
+ case 'S':
+ return fp_high_losum_p (op);
+
+ case 'U':
+ if (! strict
+ || (GET_CODE (op) == REG
+ && (REGNO (op) < FIRST_PSEUDO_REGISTER
+ || reg_renumber[REGNO (op)] >= 0)))
+ return register_ok_for_ldd (op);
+
+ return 0;
+
+ case 'W':
+ case 'T':
+ break;
+
+ default:
+ return 0;
+ }
+
+ /* Our memory extra constraints have to emulate the
+ behavior of 'm' and 'o' in order for reload to work
+ correctly. */
+ if (GET_CODE (op) == MEM)
+ {
+ reload_ok_mem = 0;
+ if ((TARGET_ARCH64 || mem_min_alignment (op, 8))
+ && (! strict
+ || strict_memory_address_p (Pmode, XEXP (op, 0))))
+ reload_ok_mem = 1;
+ }
+ else
+ {
+ reload_ok_mem = (reload_in_progress
+ && GET_CODE (op) == REG
+ && REGNO (op) >= FIRST_PSEUDO_REGISTER
+ && reg_renumber [REGNO (op)] < 0);
+ }
+
+ return reload_ok_mem;
+}
diff --git a/contrib/gcc/config/sparc/sparc.h b/contrib/gcc/config/sparc/sparc.h
index 608b3938d72d..3f2157810b6b 100644
--- a/contrib/gcc/config/sparc/sparc.h
+++ b/contrib/gcc/config/sparc/sparc.h
@@ -358,6 +358,11 @@ Unrecognized value in TARGET_CPU_DEFAULT.
SUBTARGET_EXTRA_SPECS
#define SUBTARGET_EXTRA_SPECS
+
+/* Because libgcc can generate references back to libc (via .umul etc.) we have
+ to list libc again after the second libgcc. */
+#define LINK_GCC_C_SEQUENCE_SPEC "%G %L %G %L"
+
#ifdef SPARC_BI_ARCH
#define NO_BUILTIN_PTRDIFF_TYPE
@@ -369,34 +374,11 @@ Unrecognized value in TARGET_CPU_DEFAULT.
/* ??? This should be 32 bits for v9 but what can we do? */
#define WCHAR_TYPE "short unsigned int"
#define WCHAR_TYPE_SIZE 16
-#define MAX_WCHAR_TYPE_SIZE 16
/* Show we can debug even without a frame pointer. */
#define CAN_DEBUG_WITHOUT_FP
-/* To make profiling work with -f{pic,PIC}, we need to emit the profiling
- code into the rtl. Also, if we are profiling, we cannot eliminate
- the frame pointer (because the return address will get smashed). */
-
-#define OVERRIDE_OPTIONS \
- do { \
- if (profile_flag || profile_arc_flag) \
- { \
- if (flag_pic) \
- { \
- const char *const pic_string = (flag_pic == 1) ? "-fpic" : "-fPIC";\
- warning ("%s and profiling conflict: disabling %s", \
- pic_string, pic_string); \
- flag_pic = 0; \
- } \
- flag_omit_frame_pointer = 0; \
- } \
- sparc_override_options (); \
- SUBTARGET_OVERRIDE_OPTIONS; \
- } while (0)
-
-/* This is meant to be redefined in the host dependent files. */
-#define SUBTARGET_OVERRIDE_OPTIONS
+#define OVERRIDE_OPTIONS sparc_override_options ()
/* Generate DBX debugging information. */
@@ -410,11 +392,6 @@ extern int target_flags;
#define MASK_FPU 1
#define TARGET_FPU (target_flags & MASK_FPU)
-/* Nonzero if we should use function_epilogue(). Otherwise, we
- use fast return insns, but lose some generality. */
-#define MASK_EPILOGUE 2
-#define TARGET_EPILOGUE (target_flags & MASK_EPILOGUE)
-
/* Nonzero if we should assume that double pointers might be unaligned.
This can happen when linking gcc compiled code with other compilers,
because the ABI only guarantees 4 byte alignment. */
@@ -558,10 +535,6 @@ extern int target_flags;
{"soft-float", -MASK_FPU, \
N_("Do not use hardware fp") }, \
{"soft-float", MASK_FPU_SET, NULL }, \
- {"epilogue", MASK_EPILOGUE, \
- N_("Use function_epilogue()") }, \
- {"no-epilogue", -MASK_EPILOGUE, \
- N_("Do not use function_epilogue()") }, \
{"unaligned-doubles", MASK_UNALIGNED_DOUBLES, \
N_("Assume possible double misalignment") }, \
{"no-unaligned-doubles", -MASK_UNALIGNED_DOUBLES, \
@@ -630,7 +603,7 @@ extern int target_flags;
/* MASK_APP_REGS must always be the default because that's what
FIXED_REGISTERS is set to and -ffixed- is processed before
CONDITIONAL_REGISTER_USAGE is called (where we process -mno-app-regs). */
-#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU)
+#define TARGET_DEFAULT (MASK_APP_REGS + MASK_FPU)
/* This is meant to be redefined in target specific files. */
#define SUBTARGET_SWITCHES
@@ -722,7 +695,11 @@ extern struct sparc_cpu_select sparc_select[];
/* Width of a word, in units (bytes). */
#define UNITS_PER_WORD (TARGET_ARCH64 ? 8 : 4)
+#ifdef IN_LIBGCC2
+#define MIN_UNITS_PER_WORD UNITS_PER_WORD
+#else
#define MIN_UNITS_PER_WORD 4
+#endif
/* Now define the sizes of the C data types. */
@@ -894,9 +871,10 @@ if (TARGET_ARCH64 \
accessible. We still account for them to simplify register computations
(eg: in CLASS_MAX_NREGS). There are also 4 fp condition code registers, so
32+32+32+4 == 100.
- Register 100 is used as the integer condition code register. */
+ Register 100 is used as the integer condition code register.
+ Register 101 is used as the soft frame pointer register. */
-#define FIRST_PSEUDO_REGISTER 101
+#define FIRST_PSEUDO_REGISTER 102
#define SPARC_FIRST_FP_REG 32
/* Additional V9 fp regs. */
@@ -962,7 +940,7 @@ if (TARGET_ARCH64 \
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, 1}
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
@@ -987,7 +965,7 @@ if (TARGET_ARCH64 \
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}
/* If !TARGET_FPU, then make the fp registers and fp cc regs fixed so that
they won't be allocated. */
@@ -995,7 +973,7 @@ if (TARGET_ARCH64 \
#define CONDITIONAL_REGISTER_USAGE \
do \
{ \
- if (flag_pic) \
+ if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM) \
{ \
fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
@@ -1039,12 +1017,16 @@ do \
fixed_regs[4] = 0; \
if (TARGET_FLAT) \
{ \
+ int regno; \
/* Let the compiler believe the frame pointer is still \
%fp, but output it as %i7. */ \
fixed_regs[31] = 1; \
- reg_names[FRAME_POINTER_REGNUM] = "%i7"; \
+ reg_names[HARD_FRAME_POINTER_REGNUM] = "%i7"; \
/* Disable leaf functions */ \
memset (sparc_leaf_regs, 0, FIRST_PSEUDO_REGISTER); \
+ /* Make LEAF_REG_REMAP a noop. */ \
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \
+ leaf_reg_remap [regno] = regno; \
} \
} \
while (0)
@@ -1062,9 +1044,9 @@ while (0)
#define HARD_REGNO_NREGS(REGNO, MODE) \
(TARGET_ARCH64 \
- ? ((REGNO) < 32 \
- ? (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD \
- : (GET_MODE_SIZE (MODE) + 3) / 4) \
+ ? ((REGNO) < 32 || (REGNO) == FRAME_POINTER_REGNUM \
+ ? (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD \
+ : (GET_MODE_SIZE (MODE) + 3) / 4) \
: ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
/* Due to the ARCH64 descrepancy above we must override this next
@@ -1107,27 +1089,32 @@ extern int sparc_mode_class[];
/* Register to use for pushing function arguments. */
#define STACK_POINTER_REGNUM 14
+/* The stack bias (amount by which the hardware register is offset by). */
+#define SPARC_STACK_BIAS ((TARGET_ARCH64 && TARGET_STACK_BIAS) ? 2047 : 0)
+
/* Actual top-of-stack address is 92/176 greater than the contents of the
stack pointer register for !v9/v9. That is:
- !v9: 64 bytes for the in and local registers, 4 bytes for structure return
address, and 6*4 bytes for the 6 register parameters.
- v9: 128 bytes for the in and local registers + 6*8 bytes for the integer
parameter regs. */
-#define STACK_POINTER_OFFSET FIRST_PARM_OFFSET(0)
-
-/* The stack bias (amount by which the hardware register is offset by). */
-#define SPARC_STACK_BIAS ((TARGET_ARCH64 && TARGET_STACK_BIAS) ? 2047 : 0)
-
-/* Is stack biased? */
-#define STACK_BIAS SPARC_STACK_BIAS
+#define STACK_POINTER_OFFSET (FIRST_PARM_OFFSET(0) + SPARC_STACK_BIAS)
/* Base register for access to local variables of the function. */
-#define FRAME_POINTER_REGNUM 30
-
-#if 0
-/* Register that is used for the return address for the flat model. */
-#define RETURN_ADDR_REGNUM 15
-#endif
+#define HARD_FRAME_POINTER_REGNUM 30
+
+/* The soft frame pointer does not have the stack bias applied. */
+#define FRAME_POINTER_REGNUM 101
+
+/* Given the stack bias, the stack pointer isn't actually aligned. */
+#define INIT_EXPANDERS \
+ do { \
+ if (cfun && cfun->emit->regno_pointer_align && SPARC_STACK_BIAS) \
+ { \
+ REGNO_POINTER_ALIGN (STACK_POINTER_REGNUM) = BITS_PER_UNIT; \
+ REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = BITS_PER_UNIT; \
+ } \
+ } while (0)
/* Value should be nonzero if functions must have frame pointers.
Zero means the frame pointer need not be set up (and parms
@@ -1138,21 +1125,13 @@ extern int sparc_mode_class[];
Being a non-leaf function does not mean a frame pointer is needed in the
flat window model. However, the debugger won't be able to backtrace through
us with out it. */
-#define FRAME_POINTER_REQUIRED \
- (TARGET_FLAT ? (current_function_calls_alloca || current_function_varargs \
- || !leaf_function_p ()) \
+#define FRAME_POINTER_REQUIRED \
+ (TARGET_FLAT \
+ ? (current_function_calls_alloca \
+ || current_function_varargs \
+ || !leaf_function_p ()) \
: ! (leaf_function_p () && only_leaf_regs_used ()))
-/* C statement to store the difference between the frame pointer
- and the stack pointer values immediately after the function prologue.
-
- Note, we always pretend that this is a leaf function because if
- it's not, there's no point in trying to eliminate the
- frame pointer. If it is a leaf function, we guessed right! */
-#define INITIAL_FRAME_POINTER_OFFSET(VAR) \
- ((VAR) = (TARGET_FLAT ? sparc_flat_compute_frame_size (get_frame_size ()) \
- : compute_frame_size (get_frame_size (), 1)))
-
/* Base register for access to arguments of the function. */
#define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM
@@ -1163,7 +1142,7 @@ extern int sparc_mode_class[];
/* Register which holds offset table for position-independent
data references. */
-#define PIC_OFFSET_TABLE_REGNUM 23
+#define PIC_OFFSET_TABLE_REGNUM (flag_pic ? 23 : INVALID_REGNUM)
/* Pick a default value we can notice from override_options:
!v9: Default is on.
@@ -1275,10 +1254,16 @@ enum reg_class { NO_REGS, FPCC_REGS, I64_REGS, GENERAL_REGS, FP_REGS,
This is an initializer for a vector of HARD_REG_SET
of length N_REG_CLASSES. */
-#define REG_CLASS_CONTENTS \
- {{0, 0, 0, 0}, {0, 0, 0, 0xf}, {0xffff, 0, 0, 0}, \
- {-1, 0, 0, 0}, {0, -1, 0, 0}, {0, -1, -1, 0}, \
- {-1, -1, 0, 0}, {-1, -1, -1, 0}, {-1, -1, -1, 0x1f}}
+#define REG_CLASS_CONTENTS \
+ {{0, 0, 0, 0}, /* NO_REGS */ \
+ {0, 0, 0, 0xf}, /* FPCC_REGS */ \
+ {0xffff, 0, 0, 0}, /* I64_REGS */ \
+ {-1, 0, 0, 0x20}, /* GENERAL_REGS */ \
+ {0, -1, 0, 0}, /* FP_REGS */ \
+ {0, -1, -1, 0}, /* EXTRA_FP_REGS */ \
+ {-1, -1, 0, 0x20}, /* GENERAL_OR_FP_REGS */ \
+ {-1, -1, -1, 0x20}, /* GENERAL_OR_EXTRA_FP_REGS */ \
+ {-1, -1, -1, 0x3f}} /* ALL_REGS */
/* The same information, inverted:
Return the class number of the smallest class containing
@@ -1310,7 +1295,7 @@ extern enum reg_class sparc_regno_reg_class[FIRST_PSEUDO_REGISTER];
88, 89, 90, 91, 92, 93, 94, 95, /* %f56-%f63 */ \
32, 33, /* %f0,%f1 */ \
96, 97, 98, 99, 100, /* %fcc0-3, %icc */ \
- 1, 4, 5, 6, 7, 0, 14, 30}
+ 1, 4, 5, 6, 7, 0, 14, 30, 101}
/* This is the order in which to allocate registers for
leaf functions. If all registers can fit in the "gi" registers,
@@ -1331,14 +1316,14 @@ extern enum reg_class sparc_regno_reg_class[FIRST_PSEUDO_REGISTER];
88, 89, 90, 91, 92, 93, 94, 95, \
32, 33, \
96, 97, 98, 99, 100, \
- 0, 14, 30, 31}
+ 0, 14, 30, 31, 101}
#define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc ()
extern char sparc_leaf_regs[];
#define LEAF_REGISTERS sparc_leaf_regs
-extern const char leaf_reg_remap[];
+extern char leaf_reg_remap[];
#define LEAF_REG_REMAP(REGNO) (leaf_reg_remap[REGNO])
/* The class value for index registers, and the one for base regs. */
@@ -1379,7 +1364,8 @@ extern const char leaf_reg_remap[];
`J' is used for the range which is just zero (since that is R0).
`K' is used for constants which can be loaded with a single sethi insn.
`L' is used for the range of constants supported by the movcc insns.
- `M' is used for the range of constants supported by the movrcc insns. */
+ `M' is used for the range of constants supported by the movrcc insns.
+ `N' is like K, but for constants wider than 32 bits. */
#define SPARC_SIMM10_P(X) ((unsigned HOST_WIDE_INT) (X) + 0x200 < 0x400)
#define SPARC_SIMM11_P(X) ((unsigned HOST_WIDE_INT) (X) + 0x400 < 0x800)
@@ -1388,17 +1374,21 @@ extern const char leaf_reg_remap[];
SMALL_INT is used throughout the port so we continue to use it. */
#define SMALL_INT(X) (SPARC_SIMM13_P (INTVAL (X)))
/* 13 bit immediate, considering only the low 32 bits */
-#define SMALL_INT32(X) (SPARC_SIMM13_P ((int)INTVAL (X) & 0xffffffff))
+#define SMALL_INT32(X) (SPARC_SIMM13_P (trunc_int_for_mode \
+ (INTVAL (X), SImode)))
#define SPARC_SETHI_P(X) \
-(((unsigned HOST_WIDE_INT) (X) & \
- (TARGET_ARCH64 ? ~(unsigned HOST_WIDE_INT) 0xfffffc00 : 0x3ff)) == 0)
+ (((unsigned HOST_WIDE_INT) (X) \
+ & ((unsigned HOST_WIDE_INT) 0x3ff - GET_MODE_MASK (SImode) - 1)) == 0)
+#define SPARC_SETHI32_P(X) \
+ (SPARC_SETHI_P ((unsigned HOST_WIDE_INT) (X) & GET_MODE_MASK (SImode)))
#define CONST_OK_FOR_LETTER_P(VALUE, C) \
((C) == 'I' ? SPARC_SIMM13_P (VALUE) \
: (C) == 'J' ? (VALUE) == 0 \
- : (C) == 'K' ? SPARC_SETHI_P (VALUE) \
+ : (C) == 'K' ? SPARC_SETHI32_P (VALUE) \
: (C) == 'L' ? SPARC_SIMM11_P (VALUE) \
: (C) == 'M' ? SPARC_SIMM10_P (VALUE) \
+ : (C) == 'N' ? SPARC_SETHI_P (VALUE) \
: 0)
/* Similar, but for floating constants, and defining letters G and H.
@@ -1440,7 +1430,10 @@ extern const char leaf_reg_remap[];
We need a temporary when loading/storing a HImode/QImode value
between memory and the FPU registers. This can happen when combine puts
- a paradoxical subreg in a float/fix conversion insn. */
+ a paradoxical subreg in a float/fix conversion insn.
+
+ We need a temporary when loading/storing a DFmode value between
+ unaligned memory and the upper FPU registers. */
#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN) \
((FP_REG_CLASS_P (CLASS) \
@@ -1449,28 +1442,36 @@ extern const char leaf_reg_remap[];
|| ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG) \
&& true_regnum (IN) == -1))) \
? GENERAL_REGS \
- : (((TARGET_CM_MEDANY \
- && symbolic_operand ((IN), (MODE))) \
- || (TARGET_CM_EMBMEDANY \
- && text_segment_operand ((IN), (MODE)))) \
- && !flag_pic) \
- ? GENERAL_REGS \
- : NO_REGS)
+ : ((CLASS) == EXTRA_FP_REGS && (MODE) == DFmode \
+ && GET_CODE (IN) == MEM && TARGET_ARCH32 \
+ && ! mem_min_alignment ((IN), 8)) \
+ ? FP_REGS \
+ : (((TARGET_CM_MEDANY \
+ && symbolic_operand ((IN), (MODE))) \
+ || (TARGET_CM_EMBMEDANY \
+ && text_segment_operand ((IN), (MODE)))) \
+ && !flag_pic) \
+ ? GENERAL_REGS \
+ : NO_REGS)
#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, IN) \
- ((FP_REG_CLASS_P (CLASS) \
+ ((FP_REG_CLASS_P (CLASS) \
&& ((MODE) == HImode || (MODE) == QImode) \
&& (GET_CODE (IN) == MEM \
|| ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG) \
&& true_regnum (IN) == -1))) \
- ? GENERAL_REGS \
- : (((TARGET_CM_MEDANY \
- && symbolic_operand ((IN), (MODE))) \
- || (TARGET_CM_EMBMEDANY \
- && text_segment_operand ((IN), (MODE)))) \
- && !flag_pic) \
- ? GENERAL_REGS \
- : NO_REGS)
+ ? GENERAL_REGS \
+ : ((CLASS) == EXTRA_FP_REGS && (MODE) == DFmode \
+ && GET_CODE (IN) == MEM && TARGET_ARCH32 \
+ && ! mem_min_alignment ((IN), 8)) \
+ ? FP_REGS \
+ : (((TARGET_CM_MEDANY \
+ && symbolic_operand ((IN), (MODE))) \
+ || (TARGET_CM_EMBMEDANY \
+ && text_segment_operand ((IN), (MODE)))) \
+ && !flag_pic) \
+ ? GENERAL_REGS \
+ : NO_REGS)
/* On SPARC it is not possible to directly move data between
GENERAL_REGS and FP_REGS. */
@@ -1535,7 +1536,7 @@ extern const char leaf_reg_remap[];
of the first local allocated. */
/* This allows space for one TFmode floating point value. */
#define STARTING_FRAME_OFFSET \
- (TARGET_ARCH64 ? (SPARC_STACK_BIAS - 16) \
+ (TARGET_ARCH64 ? -16 \
: (-SPARC_STACK_ALIGN (LONG_DOUBLE_TYPE_SIZE / BITS_PER_UNIT)))
/* If we generate an insn to push BYTES bytes,
@@ -1548,14 +1549,12 @@ extern const char leaf_reg_remap[];
even if this function isn't going to use it.
v9: This is 128 for the ins and locals. */
#define FIRST_PARM_OFFSET(FNDECL) \
- (TARGET_ARCH64 ? (SPARC_STACK_BIAS + 16 * UNITS_PER_WORD) \
- : (STRUCT_VALUE_OFFSET + UNITS_PER_WORD))
+ (TARGET_ARCH64 ? 16 * UNITS_PER_WORD : STRUCT_VALUE_OFFSET + UNITS_PER_WORD)
/* Offset from the argument pointer register value to the CFA.
This is different from FIRST_PARM_OFFSET because the register window
comes between the CFA and the arguments. */
-
-#define ARG_POINTER_CFA_OFFSET(FNDECL) SPARC_STACK_BIAS
+#define ARG_POINTER_CFA_OFFSET(FNDECL) 0
/* When a parameter is passed in a register, stack space is still
allocated for it.
@@ -1568,6 +1567,38 @@ extern const char leaf_reg_remap[];
all 6 slots even for v9. */
#define REG_PARM_STACK_SPACE(DECL) (6 * UNITS_PER_WORD)
+/* Definitions for register elimination. */
+/* ??? In TARGET_FLAT mode we needn't have a hard frame pointer. */
+
+#define ELIMINABLE_REGS \
+ {{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM} }
+
+/* The way this is structured, we can't eliminate SFP in favor of SP
+ if the frame pointer is required: we want to use the SFP->HFP elimination
+ in that case. But the test in update_eliminables doesn't know we are
+ assuming below that we only do the former elimination. */
+#define CAN_ELIMINATE(FROM, TO) \
+ ((TO) == HARD_FRAME_POINTER_REGNUM || !FRAME_POINTER_REQUIRED)
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+ do { \
+ (OFFSET) = 0; \
+ if ((TO) == STACK_POINTER_REGNUM) \
+ { \
+ /* Note, we always pretend that this is a leaf function \
+ because if it's not, there's no point in trying to \
+ eliminate the frame pointer. If it is a leaf \
+ function, we guessed right! */ \
+ if (TARGET_FLAT) \
+ (OFFSET) = \
+ sparc_flat_compute_frame_size (get_frame_size ()); \
+ else \
+ (OFFSET) = compute_frame_size (get_frame_size (), 1); \
+ } \
+ (OFFSET) += SPARC_STACK_BIAS; \
+ } while (0)
+
/* Keep the stack pointer constant throughout the function.
This is both an optimization and a necessity: longjmp
doesn't behave itself when the stack pointer moves within
@@ -1828,14 +1859,13 @@ do { \
#endif
-/* Output assembler code to FILE to increment profiler label # LABELNO
- for profiling a function entry. */
+/* Emit rtl for profiling. */
+#define PROFILE_HOOK(LABEL) sparc_profile_hook (LABEL)
-#define FUNCTION_PROFILER(FILE, LABELNO) \
- sparc_function_profiler(FILE, LABELNO)
+/* All the work done in PROFILE_HOOK, but still required. */
+#define FUNCTION_PROFILER(FILE, LABELNO) do { } while (0)
/* Set the name of the mcount function for the system. */
-
#define MCOUNT_FUNCTION "*mcount"
/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
@@ -1899,8 +1929,25 @@ do { \
#define STRICT_ARGUMENT_NAMING TARGET_V9
/* We do not allow sibling calls if -mflat, nor
- we do not allow indirect calls to be optimized into sibling calls. */
-#define FUNCTION_OK_FOR_SIBCALL(DECL) (DECL && ! TARGET_FLAT)
+ we do not allow indirect calls to be optimized into sibling calls.
+
+ Also, on sparc 32-bit we cannot emit a sibling call when the
+ current function returns a structure. This is because the "unimp
+ after call" convention would cause the callee to return to the
+ wrong place. The generic code already disallows cases where the
+ function being called returns a structure.
+
+ It may seem strange how this last case could occur. Usually there
+ is code after the call which jumps to epilogue code which dumps the
+ return value into the struct return area. That ought to invalidate
+ the sibling call right? Well, in the c++ case we can end up passing
+ the pointer to the struct return area to a constructor (which returns
+ void) and then nothing else happens. Such a sibling call would look
+ valid without the added check here. */
+#define FUNCTION_OK_FOR_SIBCALL(DECL) \
+ (DECL \
+ && ! TARGET_FLAT \
+ && (TARGET_ARCH64 || ! current_function_returns_struct))
/* Generate RTL to flush the register windows so as to make arbitrary frames
available. */
@@ -1933,7 +1980,8 @@ do { \
? gen_rtx_REG (Pmode, 31) \
: gen_rtx_MEM (Pmode, \
memory_address (Pmode, plus_constant (frame, \
- 15 * UNITS_PER_WORD))))
+ 15 * UNITS_PER_WORD \
+ + SPARC_STACK_BIAS))))
/* Before the prologue, the return address is %o7 + 8. OK, sometimes it's
+12, but always using +8 is close enough for frame unwind purposes.
@@ -1960,14 +2008,27 @@ do { \
If assembler and linker properly support .uaword %r_disp32(foo),
then use PC relative 32-bit relocations instead of absolute relocs
for shared libraries. On sparc64, use pc relative 32-bit relocs even
- for binaries, to save memory. */
+ for binaries, to save memory.
+
+ binutils 2.12 would emit a R_SPARC_DISP32 dynamic relocation if the
+ symbol %r_disp32() is against was not local, but .hidden. In that
+ case, we have to use DW_EH_PE_absptr for pic personality. */
#ifdef HAVE_AS_SPARC_UA_PCREL
+#ifdef HAVE_AS_SPARC_UA_PCREL_HIDDEN
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
(flag_pic \
? (GLOBAL ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4\
: ((TARGET_ARCH64 && ! GLOBAL) \
? (DW_EH_PE_pcrel | DW_EH_PE_sdata4) \
: DW_EH_PE_absptr))
+#else
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
+ (flag_pic \
+ ? (GLOBAL ? DW_EH_PE_absptr : (DW_EH_PE_pcrel | DW_EH_PE_sdata4)) \
+ : ((TARGET_ARCH64 && ! GLOBAL) \
+ ? (DW_EH_PE_pcrel | DW_EH_PE_sdata4) \
+ : DW_EH_PE_absptr))
+#endif
/* Emit a PC-relative relocation. */
#define ASM_OUTPUT_DWARF_PCREL(FILE, SIZE, LABEL) \
@@ -1996,9 +2057,12 @@ do { \
has been allocated, which happens in local-alloc.c. */
#define REGNO_OK_FOR_INDEX_P(REGNO) \
-((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < (unsigned)32)
-#define REGNO_OK_FOR_BASE_P(REGNO) \
-((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < (unsigned)32)
+((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < (unsigned)32 \
+ || (REGNO) == FRAME_POINTER_REGNUM \
+ || reg_renumber[REGNO] == FRAME_POINTER_REGNUM)
+
+#define REGNO_OK_FOR_BASE_P(REGNO) REGNO_OK_FOR_INDEX_P (REGNO)
+
#define REGNO_OK_FOR_FP_P(REGNO) \
(((unsigned) (REGNO) - 32 < (TARGET_V9 ? (unsigned)64 : (unsigned)32)) \
|| ((unsigned) reg_renumber[REGNO] - 32 < (TARGET_V9 ? (unsigned)64 : (unsigned)32)))
@@ -2079,34 +2143,32 @@ do { \
be at least 8 bytes.
`U' handles all pseudo registers or a hard even numbered
- integer register, needed for ldd/std instructions. */
+ integer register, needed for ldd/std instructions.
-#define EXTRA_CONSTRAINT_BASE(OP, C) \
- ((C) == 'Q' ? fp_sethi_p(OP) \
- : (C) == 'R' ? fp_mov_p(OP) \
- : (C) == 'S' ? fp_high_losum_p(OP) \
- : 0)
+ 'W' handles the memory operand when moving operands in/out
+ of 'e' constraint floating point registers. */
#ifndef REG_OK_STRICT
/* 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) \
- (((unsigned) REGNO (X)) - 32 >= (FIRST_PSEUDO_REGISTER - 32))
+ (REGNO (X) < 32 \
+ || REGNO (X) == FRAME_POINTER_REGNUM \
+ || 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) \
- (((unsigned) REGNO (X)) - 32 >= (FIRST_PSEUDO_REGISTER - 32))
+#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_INDEX_P (X)
+
+/* 'T', 'U' are for aligned memory loads which aren't needed for arch64.
+ 'W' is like 'T' but is assumed true on arch64.
-/* 'T', 'U' are for aligned memory loads which aren't needed for arch64. */
+ Remember to accept pseudo-registers for memory constraints if reload is
+ in progress. */
-#define EXTRA_CONSTRAINT(OP, C) \
- (EXTRA_CONSTRAINT_BASE(OP, C) \
- || ((! TARGET_ARCH64 && (C) == 'T') \
- ? (mem_min_alignment (OP, 8)) \
- : ((! TARGET_ARCH64 && (C) == 'U') \
- ? (register_ok_for_ldd (OP)) \
- : 0)))
+#define EXTRA_CONSTRAINT(OP, C) \
+ sparc_extra_constraint_check(OP, C, 0)
#else
@@ -2115,16 +2177,8 @@ do { \
/* 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))
-#define EXTRA_CONSTRAINT(OP, C) \
- (EXTRA_CONSTRAINT_BASE(OP, C) \
- || ((! TARGET_ARCH64 && (C) == 'T') \
- ? mem_min_alignment (OP, 8) && strict_memory_address_p (Pmode, XEXP (OP, 0)) \
- : ((! TARGET_ARCH64 && (C) == 'U') \
- ? (GET_CODE (OP) == REG \
- && (REGNO (OP) < FIRST_PSEUDO_REGISTER \
- || reg_renumber[REGNO (OP)] >= 0) \
- && register_ok_for_ldd (OP)) \
- : 0)))
+#define EXTRA_CONSTRAINT(OP, C) \
+ sparc_extra_constraint_check(OP, C, 1)
#endif
@@ -2326,12 +2380,13 @@ do { \
/* Decompose SImode constants into hi+lo_sum. We do have to \
rerecognize what we produce, so be careful. */ \
if (CONSTANT_P (X) \
- && (MODE != TFmode || TARGET_V9) \
+ && (MODE != TFmode || TARGET_ARCH64) \
&& GET_MODE (X) == SImode \
&& GET_CODE (X) != LO_SUM && GET_CODE (X) != HIGH \
&& ! (flag_pic \
&& (symbolic_operand (X, Pmode) \
- || pic_address_needs_scratch (X)))) \
+ || pic_address_needs_scratch (X))) \
+ && sparc_cmodel <= CM_MEDLOW) \
{ \
X = gen_rtx_LO_SUM (GET_MODE (X), \
gen_rtx_HIGH (GET_MODE (X), X), X); \
@@ -2596,6 +2651,23 @@ do { \
|| (CLASS1) == FPCC_REGS || (CLASS2) == FPCC_REGS) \
? (sparc_cpu == PROCESSOR_ULTRASPARC ? 12 : 6) : 2)
+/* Provide the cost of a branch. For pre-v9 processors we use
+ a value of 3 to take into account the potential annulling of
+ the delay slot (which ends up being a bubble in the pipeline slot)
+ plus a cycle to take into consideration the instruction cache
+ effects.
+
+ On v9 and later, which have branch prediction facilities, we set
+ it to the depth of the pipeline as that is the cost of a
+ mispredicted branch.
+
+ ??? Set to 9 when PROCESSOR_ULTRASPARC3 is added */
+
+#define BRANCH_COST \
+ ((sparc_cpu == PROCESSOR_V9 \
+ || sparc_cpu == PROCESSOR_ULTRASPARC) \
+ ? 7 : 3)
+
/* Provide the costs of a rtl expression. This is in the body of a
switch on CODE. The purpose for the cost of MULT is to encourage
`synth_mult' to find a synthetic multiply when reasonable.
@@ -2623,13 +2695,12 @@ do { \
case FIX: \
return 19;
-/* Conditional branches with empty delay slots have a length of two. */
-#define ADJUST_INSN_LENGTH(INSN, LENGTH) \
-do { \
- if (GET_CODE (INSN) == CALL_INSN \
- || (GET_CODE (INSN) == JUMP_INSN && ! simplejump_p (insn))) \
- LENGTH += 1; \
-} while (0)
+#define PREFETCH_BLOCK \
+ ((sparc_cpu == PROCESSOR_ULTRASPARC) ? 64 : 32)
+
+/* ??? UltraSPARC-III note: Can set this to 8 for ultra3. */
+#define SIMULTANEOUS_PREFETCHES \
+ ((sparc_cpu == PROCESSOR_ULTRASPARC) ? 2 : 3)
/* Control the assembler format that we output. */
@@ -2675,7 +2746,7 @@ do { \
"%f40", "%f41", "%f42", "%f43", "%f44", "%f45", "%f46", "%f47", \
"%f48", "%f49", "%f50", "%f51", "%f52", "%f53", "%f54", "%f55", \
"%f56", "%f57", "%f58", "%f59", "%f60", "%f61", "%f62", "%f63", \
- "%fcc0", "%fcc1", "%fcc2", "%fcc3", "%icc"}
+ "%fcc0", "%fcc1", "%fcc2", "%fcc3", "%icc", "%sfp" }
/* Define additional names for use in asm clobbers and asm declarations. */
@@ -2944,8 +3015,10 @@ do { \
#define PREDICATE_CODES \
{"reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
{"fp_zero_operand", {CONST_DOUBLE}}, \
+{"fp_register_operand", {SUBREG, REG}}, \
{"intreg_operand", {SUBREG, REG}}, \
{"fcc_reg_operand", {REG}}, \
+{"fcc0_reg_operand", {REG}}, \
{"icc_or_fcc_reg_operand", {REG}}, \
{"restore_operand", {REG}}, \
{"call_operand", {MEM}}, \
@@ -2963,6 +3036,7 @@ do { \
{"eq_or_neq", {EQ, NE}}, \
{"normal_comp_operator", {GE, GT, LE, LT, GTU, LEU}}, \
{"noov_compare_op", {NE, EQ, GE, GT, LE, LT, GEU, GTU, LEU, LTU}}, \
+{"noov_compare64_op", {NE, EQ, GE, GT, LE, LT, GEU, GTU, LEU, LTU}}, \
{"v9_regcmp_op", {EQ, NE, GE, LT, LE, GT}}, \
{"extend_op", {SIGN_EXTEND, ZERO_EXTEND}}, \
{"cc_arithop", {AND, IOR, XOR}}, \
diff --git a/contrib/gcc/config/sparc/sparc.md b/contrib/gcc/config/sparc/sparc.md
index c0b8f6092fa3..ebb6768ef88b 100644
--- a/contrib/gcc/config/sparc/sparc.md
+++ b/contrib/gcc/config/sparc/sparc.md
@@ -1,4 +1,4 @@
-;- Machine description for SPARC chip for GNU C compiler
+;; Machine description for SPARC chip for GNU C compiler
;; Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
;; 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
;; Contributed by Michael Tiemann (tiemann@cygnus.com)
@@ -87,8 +87,78 @@
"ialu,compare,shift,load,sload,store,uncond_branch,branch,call,sibcall,call_no_delay_slot,return,imul,idiv,fpload,fpstore,fp,fpmove,fpcmove,fpcmp,fpmul,fpdivs,fpdivd,fpsqrts,fpsqrtd,cmove,multi,misc"
(const_string "ialu"))
+;; true if branch/call has empty delay slot and will emit a nop in it
+(define_attr "empty_delay_slot" "false,true"
+ (symbol_ref "empty_delay_slot (insn)"))
+
+(define_attr "branch_type" "none,icc,fcc,reg" (const_string "none"))
+
+(define_attr "pic" "false,true"
+ (symbol_ref "flag_pic != 0"))
+
;; Length (in # of insns).
-(define_attr "length" "" (const_int 1))
+(define_attr "length" ""
+ (cond [(eq_attr "type" "uncond_branch,call,sibcall")
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1))
+ (eq_attr "branch_type" "icc")
+ (if_then_else (match_operand 0 "noov_compare64_op" "")
+ (if_then_else (lt (pc) (match_dup 1))
+ (if_then_else (lt (minus (match_dup 1) (pc)) (const_int 260000))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 4)
+ (const_int 3)))
+ (if_then_else (lt (minus (pc) (match_dup 1)) (const_int 260000))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 4)
+ (const_int 3))))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1)))
+ (eq_attr "branch_type" "fcc")
+ (if_then_else (match_operand 0 "fcc0_reg_operand" "")
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1))
+ (if_then_else (lt (pc) (match_dup 2))
+ (if_then_else (lt (minus (match_dup 2) (pc)) (const_int 260000))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 4)
+ (const_int 3)))
+ (if_then_else (lt (minus (pc) (match_dup 2)) (const_int 260000))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 4)
+ (const_int 3)))))
+ (eq_attr "branch_type" "reg")
+ (if_then_else (lt (pc) (match_dup 2))
+ (if_then_else (lt (minus (match_dup 2) (pc)) (const_int 32000))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 4)
+ (const_int 3)))
+ (if_then_else (lt (minus (pc) (match_dup 2)) (const_int 32000))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 4)
+ (const_int 3))))
+ ] (const_int 1)))
;; FP precision.
(define_attr "fptype" "single,double" (const_string "single"))
@@ -1893,11 +1963,12 @@
""
"*
{
- return output_cbranch (operands[0], 1, 0,
+ return output_cbranch (operands[0], operands[1], 1, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
}"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "branch")
+ (set_attr "branch_type" "icc")])
;; XXX fpcmp nop braindamage
(define_insn "*inverted_branch"
@@ -1909,11 +1980,12 @@
""
"*
{
- return output_cbranch (operands[0], 1, 1,
+ return output_cbranch (operands[0], operands[1], 1, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
}"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "branch")
+ (set_attr "branch_type" "icc")])
;; XXX fpcmp nop braindamage
(define_insn "*normal_fp_branch"
@@ -1926,11 +1998,12 @@
""
"*
{
- return output_cbranch (operands[1], 2, 0,
+ return output_cbranch (operands[1], operands[2], 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
}"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "branch")
+ (set_attr "branch_type" "fcc")])
;; XXX fpcmp nop braindamage
(define_insn "*inverted_fp_branch"
@@ -1943,11 +2016,12 @@
""
"*
{
- return output_cbranch (operands[1], 2, 1,
+ return output_cbranch (operands[1], operands[2], 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
}"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "branch")
+ (set_attr "branch_type" "fcc")])
;; XXX fpcmp nop braindamage
(define_insn "*normal_fpe_branch"
@@ -1960,11 +2034,12 @@
""
"*
{
- return output_cbranch (operands[1], 2, 0,
+ return output_cbranch (operands[1], operands[2], 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
}"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "branch")
+ (set_attr "branch_type" "fcc")])
;; XXX fpcmp nop braindamage
(define_insn "*inverted_fpe_branch"
@@ -1977,11 +2052,12 @@
""
"*
{
- return output_cbranch (operands[1], 2, 1,
+ return output_cbranch (operands[1], operands[2], 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
}"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "branch")
+ (set_attr "branch_type" "fcc")])
;; Sparc V9-specific jump insns. None of these are guaranteed to be
;; in the architecture.
@@ -1999,11 +2075,12 @@
"TARGET_ARCH64"
"*
{
- return output_v9branch (operands[0], 1, 2, 0,
+ return output_v9branch (operands[0], operands[2], 1, 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
}"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "branch")
+ (set_attr "branch_type" "reg")])
;; XXX
(define_insn "*inverted_int_branch_sp64"
@@ -2016,11 +2093,12 @@
"TARGET_ARCH64"
"*
{
- return output_v9branch (operands[0], 1, 2, 1,
+ return output_v9branch (operands[0], operands[2], 1, 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
}"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "branch")
+ (set_attr "branch_type" "reg")])
;; Load program counter insns.
@@ -2053,14 +2131,8 @@
a double if needed. */
if (GET_CODE (operands[1]) == CONST_DOUBLE)
{
- operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]) & 0xff);
- }
- else if (GET_CODE (operands[1]) == CONST_INT)
- {
- /* And further, we know for all QI cases that only the
- low byte is significant, which we can always process
- in a single insn. So mask it now. */
- operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff);
+ operands[1] = GEN_INT (trunc_int_for_mode
+ (CONST_DOUBLE_LOW (operands[1]), QImode));
}
/* Handle sets of MEM first. */
@@ -2459,13 +2531,14 @@
(define_insn "*movdi_insn_sp32_v9"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=m,T,U,o,r,r,r,?T,?f,?f,?o,?f")
+ "=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
(match_operand:DI 1 "input_operand"
- " J,U,T,r,o,i,r, f, T, o, f, f"))]
+ " J,J,U,T,r,o,i,r, f, T, o, f, f"))]
"! TARGET_ARCH64 && TARGET_V9
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"@
stx\\t%%g0, %0
+ #
std\\t%1, %0
ldd\\t%1, %0
#
@@ -2477,18 +2550,19 @@
#
#
#"
- [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
- (set_attr "length" "*,*,*,2,2,2,2,*,*,2,2,2")])
+ [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
+ (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,2")])
(define_insn "*movdi_insn_sp32"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=T,U,o,r,r,r,?T,?f,?f,?o,?f")
+ "=o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
(match_operand:DI 1 "input_operand"
- " U,T,r,o,i,r, f, T, o, f, f"))]
+ " J,U,T,r,o,i,r, f, T, o, f, f"))]
"! TARGET_ARCH64
&& (register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode))"
"@
+ #
std\\t%1, %0
ldd\\t%1, %0
#
@@ -2500,8 +2574,8 @@
#
#
#"
- [(set_attr "type" "store,load,*,*,*,*,fpstore,fpload,*,*,*")
- (set_attr "length" "*,*,2,2,2,2,*,*,2,2,2")])
+ [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
+ (set_attr "length" "2,*,*,2,2,2,2,*,*,2,2,2")])
;; The following are generated by sparc_emit_set_const64
(define_insn "*movdi_sp64_dbl"
@@ -2520,8 +2594,8 @@
"sethi\\t%%hi(%a1), %0")
(define_insn "*movdi_insn_sp64_novis"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?m")
- (match_operand:DI 1 "input_operand" "rI,K,J,m,rJ,e,m,e"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?W")
+ (match_operand:DI 1 "input_operand" "rI,N,J,m,rJ,e,W,e"))]
"TARGET_ARCH64 && ! TARGET_VIS
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
@@ -2538,8 +2612,8 @@
(set_attr "fptype" "*,*,*,*,*,double,*,*")])
(define_insn "*movdi_insn_sp64_vis"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?m,b")
- (match_operand:DI 1 "input_operand" "rI,K,J,m,rJ,e,m,e,J"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?W,b")
+ (match_operand:DI 1 "input_operand" "rI,N,J,m,rJ,e,W,e,J"))]
"TARGET_ARCH64 && TARGET_VIS &&
(register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
@@ -2734,8 +2808,7 @@
&& ! flag_pic"
"
{
- sparc_emit_set_symbolic_const64 (operands[0], operands[1],
- gen_rtx_REG (DImode, REGNO (operands[2])));
+ sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
DONE;
}")
@@ -2748,8 +2821,7 @@
&& ! flag_pic"
"
{
- sparc_emit_set_symbolic_const64 (operands[0], operands[1],
- gen_rtx_REG (DImode, REGNO (operands[2])));
+ sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
DONE;
}")
@@ -2771,8 +2843,8 @@
#else
unsigned int low, high;
- low = INTVAL (operands[1]) & 0xffffffff;
- high = (INTVAL (operands[1]) >> 32) & 0xffffffff;
+ low = trunc_int_for_mode (INTVAL (operands[1]), SImode);
+ high = trunc_int_for_mode (INTVAL (operands[1]) >> 32, SImode);
emit_insn (gen_movsi (gen_highpart (SImode, operands[0]), GEN_INT (high)));
/* Slick... but this trick loses if this subreg constant part
@@ -2799,7 +2871,7 @@
/* Slick... but this trick loses if this subreg constant part
can be done in one insn. */
if (CONST_DOUBLE_LOW (operands[1]) == CONST_DOUBLE_HIGH (operands[1])
- && !(SPARC_SETHI_P (CONST_DOUBLE_HIGH (operands[1]))
+ && !(SPARC_SETHI32_P (CONST_DOUBLE_HIGH (operands[1]))
|| SPARC_SIMM13_P (CONST_DOUBLE_HIGH (operands[1]))))
{
emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
@@ -2890,6 +2962,21 @@
DONE;
}")
+(define_split
+ [(set (match_operand:DI 0 "memory_operand" "")
+ (const_int 0))]
+ "reload_completed
+ && (! TARGET_V9
+ || (! TARGET_ARCH64
+ && ! mem_min_alignment (operands[0], 8)))
+ && offsettable_memref_p (operands[0])"
+ [(clobber (const_int 0))]
+ "
+{
+ emit_insn (gen_movsi (adjust_address (operands[0], SImode, 0), const0_rtx));
+ emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4), const0_rtx));
+ DONE;
+}")
;; Floating point move insns
@@ -3202,8 +3289,8 @@
;; Be careful, fmovd does not exist when !v9.
(define_insn "*movdf_insn_sp32"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=e,T,U,T,o,e,*r,o,e,o")
- (match_operand:DF 1 "input_operand" "T#F,e,T,U,G,e,*rFo,*r,o#F,e"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=e,W,U,T,o,e,*r,o,e,o")
+ (match_operand:DF 1 "input_operand" "W#F,e,T,U,G,e,*rFo,*r,o#F,e"))]
"TARGET_FPU
&& ! TARGET_V9
&& (register_operand (operands[0], DFmode)
@@ -3262,8 +3349,8 @@
;; We have available v9 double floats but not 64-bit
;; integer registers and no VIS.
(define_insn "*movdf_insn_v9only_novis"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,T,T,U,T,e,*r,o")
- (match_operand:DF 1 "input_operand" "e,T#F,G,e,T,U,o#F,*roF,*rGe"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,T,W,U,T,f,*r,o")
+ (match_operand:DF 1 "input_operand" "e,W#F,G,e,T,U,o#F,*roF,*rGf"))]
"TARGET_FPU
&& TARGET_V9
&& ! TARGET_VIS
@@ -3288,8 +3375,8 @@
;; We have available v9 double floats but not 64-bit
;; integer registers but we have VIS.
(define_insn "*movdf_insn_v9only_vis"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,T,T,U,T,e,*r,o")
- (match_operand:DF 1 "input_operand" "G,e,T#F,G,e,T,U,o#F,*roGF,*rGe"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,T,W,U,T,f,*r,o")
+ (match_operand:DF 1 "input_operand" "G,e,W#F,G,e,T,U,o#F,*roGF,*rGf"))]
"TARGET_FPU
&& TARGET_VIS
&& ! TARGET_ARCH64
@@ -3314,8 +3401,8 @@
;; We have available both v9 double floats and 64-bit
;; integer registers. No VIS though.
(define_insn "*movdf_insn_sp64_novis"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,m,*r,*r,m,*r")
- (match_operand:DF 1 "input_operand" "e,m#F,e,*rG,m,*rG,F"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,W,*r,*r,m,*r")
+ (match_operand:DF 1 "input_operand" "e,W#F,e,*rG,m,*rG,F"))]
"TARGET_FPU
&& ! TARGET_VIS
&& TARGET_ARCH64
@@ -3337,8 +3424,8 @@
;; We have available both v9 double floats and 64-bit
;; integer registers. And we have VIS.
(define_insn "*movdf_insn_sp64_vis"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,m,*r,*r,m,*r")
- (match_operand:DF 1 "input_operand" "G,e,m#F,e,*rG,m,*rG,F"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,W,*r,*r,m,*r")
+ (match_operand:DF 1 "input_operand" "G,e,W#F,e,*rG,m,*rG,F"))]
"TARGET_FPU
&& TARGET_VIS
&& TARGET_ARCH64
@@ -3411,7 +3498,7 @@
/* Slick... but this trick loses if this subreg constant part
can be done in one insn. */
if (l[1] == l[0]
- && !(SPARC_SETHI_P (l[0])
+ && !(SPARC_SETHI32_P (l[0])
|| SPARC_SIMM13_P (l[0])))
{
emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
@@ -3753,7 +3840,8 @@
"reload_completed
&& (! TARGET_ARCH64
|| (TARGET_FPU
- && ! TARGET_HARD_QUAD))"
+ && ! TARGET_HARD_QUAD)
+ || ! fp_register_operand (operands[0], TFmode))"
[(clobber (const_int 0))]
"
{
@@ -3815,7 +3903,10 @@
[(set (match_operand:TF 0 "register_operand" "")
(match_operand:TF 1 "memory_operand" ""))]
"(reload_completed
- && offsettable_memref_p (operands[1]))"
+ && offsettable_memref_p (operands[1])
+ && (! TARGET_ARCH64
+ || ! TARGET_HARD_QUAD
+ || ! fp_register_operand (operands[0], TFmode)))"
[(clobber (const_int 0))]
"
{
@@ -3848,7 +3939,10 @@
[(set (match_operand:TF 0 "memory_operand" "")
(match_operand:TF 1 "register_operand" ""))]
"(reload_completed
- && offsettable_memref_p (operands[0]))"
+ && offsettable_memref_p (operands[0])
+ && (! TARGET_ARCH64
+ || ! TARGET_HARD_QUAD
+ || ! fp_register_operand (operands[1], TFmode)))"
[(clobber (const_int 0))]
"
{
@@ -4929,31 +5023,11 @@
(set_attr "fptype" "double")])
(define_expand "extendsftf2"
- [(set (match_operand:TF 0 "register_operand" "=e")
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
(float_extend:TF
- (match_operand:SF 1 "register_operand" "f")))]
+ (match_operand:SF 1 "register_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0;
-
- if (GET_CODE (operands[0]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[0];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_stoq\"), 0,
- VOIDmode, 2,
- XEXP (slot0, 0), Pmode,
- operands[1], SFmode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_cvt (FLOAT_EXTEND, operands); DONE;")
(define_insn "*extendsftf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
@@ -4964,31 +5038,11 @@
[(set_attr "type" "fp")])
(define_expand "extenddftf2"
- [(set (match_operand:TF 0 "register_operand" "=e")
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
(float_extend:TF
- (match_operand:DF 1 "register_operand" "e")))]
+ (match_operand:DF 1 "register_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0;
-
- if (GET_CODE (operands[0]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[0];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_dtoq\"), 0,
- VOIDmode, 2,
- XEXP (slot0, 0), Pmode,
- operands[1], DFmode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_cvt (FLOAT_EXTEND, operands); DONE;")
(define_insn "*extenddftf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
@@ -5008,30 +5062,11 @@
(set_attr "fptype" "double")])
(define_expand "trunctfsf2"
- [(set (match_operand:SF 0 "register_operand" "=f")
+ [(set (match_operand:SF 0 "register_operand" "")
(float_truncate:SF
- (match_operand:TF 1 "register_operand" "e")))]
+ (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- {
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
- }
- else
- slot0 = operands[1];
-
- emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtos\"),
- operands[0], 0, SFmode, 1,
- XEXP (slot0, 0), Pmode);
- DONE;
- }
-}")
+ "emit_tfmode_cvt (FLOAT_TRUNCATE, operands); DONE;")
(define_insn "*trunctfsf2_hq"
[(set (match_operand:SF 0 "register_operand" "=f")
@@ -5042,30 +5077,11 @@
[(set_attr "type" "fp")])
(define_expand "trunctfdf2"
- [(set (match_operand:DF 0 "register_operand" "=f")
+ [(set (match_operand:DF 0 "register_operand" "")
(float_truncate:DF
- (match_operand:TF 1 "register_operand" "e")))]
+ (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- {
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
- }
- else
- slot0 = operands[1];
-
- emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtod\"),
- operands[0], 0, DFmode, 1,
- XEXP (slot0, 0), Pmode);
- DONE;
- }
-}")
+ "emit_tfmode_cvt (FLOAT_TRUNCATE, operands); DONE;")
(define_insn "*trunctfdf2_hq"
[(set (match_operand:DF 0 "register_operand" "=e")
@@ -5094,30 +5110,10 @@
(set_attr "fptype" "double")])
(define_expand "floatsitf2"
- [(set (match_operand:TF 0 "register_operand" "=e")
- (float:TF (match_operand:SI 1 "register_operand" "f")))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (float:TF (match_operand:SI 1 "register_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[1];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_itoq\"), 0,
- VOIDmode, 2,
- XEXP (slot0, 0), Pmode,
- operands[1], SImode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_cvt (FLOAT, operands); DONE;")
(define_insn "*floatsitf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
@@ -5127,27 +5123,10 @@
[(set_attr "type" "fp")])
(define_expand "floatunssitf2"
- [(set (match_operand:TF 0 "register_operand" "=e")
- (unsigned_float:TF (match_operand:SI 1 "register_operand" "e")))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (unsigned_float:TF (match_operand:SI 1 "register_operand" "")))]
"TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
- "
-{
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[1];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_uitoq\"), 0,
- VOIDmode, 2,
- XEXP (slot0, 0), Pmode,
- operands[1], SImode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
-}")
+ "emit_tfmode_cvt (UNSIGNED_FLOAT, operands); DONE;")
;; Now the same for 64 bit sources.
@@ -5159,6 +5138,12 @@
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
+(define_expand "floatunsdisf2"
+ [(use (match_operand:SF 0 "register_operand" ""))
+ (use (match_operand:DI 1 "register_operand" ""))]
+ "TARGET_ARCH64 && TARGET_FPU"
+ "sparc_emit_floatunsdi (operands); DONE;")
+
(define_insn "floatdidf2"
[(set (match_operand:DF 0 "register_operand" "=e")
(float:DF (match_operand:DI 1 "register_operand" "e")))]
@@ -5167,31 +5152,17 @@
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
+(define_expand "floatunsdidf2"
+ [(use (match_operand:DF 0 "register_operand" ""))
+ (use (match_operand:DI 1 "register_operand" ""))]
+ "TARGET_ARCH64 && TARGET_FPU"
+ "sparc_emit_floatunsdi (operands); DONE;")
+
(define_expand "floatditf2"
- [(set (match_operand:TF 0 "register_operand" "=e")
- (float:TF (match_operand:DI 1 "register_operand" "e")))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (float:TF (match_operand:DI 1 "register_operand" "")))]
"TARGET_FPU && TARGET_V9 && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[1];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_xtoq\"), 0,
- VOIDmode, 2,
- XEXP (slot0, 0), Pmode,
- operands[1], DImode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_cvt (FLOAT, operands); DONE;")
(define_insn "*floatditf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
@@ -5201,27 +5172,10 @@
[(set_attr "type" "fp")])
(define_expand "floatunsditf2"
- [(set (match_operand:TF 0 "register_operand" "=e")
- (unsigned_float:TF (match_operand:DI 1 "register_operand" "e")))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (unsigned_float:TF (match_operand:DI 1 "register_operand" "")))]
"TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
- "
-{
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[1];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_uxtoq\"), 0,
- VOIDmode, 2,
- XEXP (slot0, 0), Pmode,
- operands[1], DImode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
-}")
+ "emit_tfmode_cvt (UNSIGNED_FLOAT, operands); DONE;")
;; Convert a float to an actual integer.
;; Truncation is performed as part of the conversion.
@@ -5243,58 +5197,23 @@
(set_attr "fptype" "double")])
(define_expand "fix_trunctfsi2"
- [(set (match_operand:SI 0 "register_operand" "=f")
- (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+ [(set (match_operand:SI 0 "register_operand" "")
+ (fix:SI (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- {
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
- }
- else
- slot0 = operands[1];
-
- emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtoi\"),
- operands[0], 0, SImode, 1,
- XEXP (slot0, 0), Pmode);
- DONE;
- }
-}")
+ "emit_tfmode_cvt (FIX, operands); DONE;")
(define_insn "*fix_trunctfsi2_hq"
[(set (match_operand:SI 0 "register_operand" "=f")
- (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+ (fix:SI (match_operand:TF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
"fqtoi\\t%1, %0"
[(set_attr "type" "fp")])
(define_expand "fixuns_trunctfsi2"
- [(set (match_operand:SI 0 "register_operand" "=f")
- (unsigned_fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unsigned_fix:SI (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
- "
-{
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- {
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
- }
- else
- slot0 = operands[1];
-
- emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtoui\"),
- operands[0], 0, SImode, 1,
- XEXP (slot0, 0), Pmode);
- DONE;
-}")
+ "emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
;; Now the same, for V9 targets
@@ -5315,59 +5234,23 @@
(set_attr "fptype" "double")])
(define_expand "fix_trunctfdi2"
- [(set (match_operand:DI 0 "register_operand" "=e")
- (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+ [(set (match_operand:DI 0 "register_operand" "")
+ (fix:DI (match_operand:TF 1 "general_operand" "")))]
"TARGET_V9 && TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- {
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
- }
- else
- slot0 = operands[1];
-
- emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtox\"),
- operands[0], 0, DImode, 1,
- XEXP (slot0, 0), Pmode);
- DONE;
- }
-}")
+ "emit_tfmode_cvt (FIX, operands); DONE;")
(define_insn "*fix_trunctfdi2_hq"
[(set (match_operand:DI 0 "register_operand" "=e")
- (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+ (fix:DI (match_operand:TF 1 "register_operand" "e")))]
"TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
"fqtox\\t%1, %0"
[(set_attr "type" "fp")])
(define_expand "fixuns_trunctfdi2"
- [(set (match_operand:DI 0 "register_operand" "=f")
- (unsigned_fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unsigned_fix:DI (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
- "
-{
- rtx slot0;
-
- if (GET_CODE (operands[1]) != MEM)
- {
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
- }
- else
- slot0 = operands[1];
-
- emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtoux\"),
- operands[0], 0, DImode, 1,
- XEXP (slot0, 0), Pmode);
- DONE;
-}")
-
+ "emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
;;- arithmetic instructions
@@ -5920,6 +5803,13 @@
else
return \"sllx\\t%H1, 32, %3\\n\\tor\\t%L1, %3, %3\\n\\tmulx\\t%3, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0\";
}
+ else if (rtx_equal_p (operands[1], operands[2]))
+ {
+ if (which_alternative == 1)
+ return \"or\\t%L1, %H1, %H1\\n\\tmulx\\t%H1, %H1, %L0\;srlx\\t%L0, 32, %H0\";
+ else
+ return \"sllx\\t%H1, 32, %3\\n\\tor\\t%L1, %3, %3\\n\\tmulx\\t%3, %3, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0\";
+ }
if (sparc_check_64 (operands[2], insn) <= 0)
output_asm_insn (\"srl\\t%L2, 0, %L2\", operands);
if (which_alternative == 1)
@@ -6377,7 +6267,7 @@
[(set_attr "type" "multi")
(set (attr "length")
(if_then_else (eq_attr "isa" "v9")
- (const_int 4) (const_int 7)))])
+ (const_int 4) (const_int 6)))])
(define_insn "divsi3_sp64"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -6576,7 +6466,7 @@
(set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))]
"
{
- operands[4] = GEN_INT (~INTVAL (operands[2]) & 0xffffffff);
+ operands[4] = GEN_INT (~INTVAL (operands[2]));
}")
;; Split DImode logical operations requiring two instructions.
@@ -6719,7 +6609,7 @@
(set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))]
"
{
- operands[4] = GEN_INT (~INTVAL (operands[2]) & 0xffffffff);
+ operands[4] = GEN_INT (~INTVAL (operands[2]));
}")
(define_insn "*or_not_di_sp32"
@@ -6835,7 +6725,7 @@
(set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))]
"
{
- operands[4] = GEN_INT (~INTVAL (operands[2]) & 0xffffffff);
+ operands[4] = GEN_INT (~INTVAL (operands[2]));
}")
(define_split
@@ -6850,7 +6740,7 @@
(set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))]
"
{
- operands[4] = GEN_INT (~INTVAL (operands[2]) & 0xffffffff);
+ operands[4] = GEN_INT (~INTVAL (operands[2]));
}")
;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
@@ -7267,42 +7157,7 @@
(plus:TF (match_operand:TF 1 "general_operand" "")
(match_operand:TF 2 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0, slot1, slot2;
-
- if (GET_CODE (operands[0]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[0];
- if (GET_CODE (operands[1]) != MEM)
- {
- slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
- }
- else
- slot1 = operands[1];
- if (GET_CODE (operands[2]) != MEM)
- {
- slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
- }
- else
- slot2 = operands[2];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_add\"), 0,
- VOIDmode, 3,
- XEXP (slot0, 0), Pmode,
- XEXP (slot1, 0), Pmode,
- XEXP (slot2, 0), Pmode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_binop (PLUS, operands); DONE;")
(define_insn "*addtf3_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
@@ -7334,42 +7189,7 @@
(minus:TF (match_operand:TF 1 "general_operand" "")
(match_operand:TF 2 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0, slot1, slot2;
-
- if (GET_CODE (operands[0]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[0];
- if (GET_CODE (operands[1]) != MEM)
- {
- slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
- }
- else
- slot1 = operands[1];
- if (GET_CODE (operands[2]) != MEM)
- {
- slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
- }
- else
- slot2 = operands[2];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_sub\"), 0,
- VOIDmode, 3,
- XEXP (slot0, 0), Pmode,
- XEXP (slot1, 0), Pmode,
- XEXP (slot2, 0), Pmode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_binop (MINUS, operands); DONE;")
(define_insn "*subtf3_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
@@ -7401,42 +7221,7 @@
(mult:TF (match_operand:TF 1 "general_operand" "")
(match_operand:TF 2 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0, slot1, slot2;
-
- if (GET_CODE (operands[0]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[0];
- if (GET_CODE (operands[1]) != MEM)
- {
- slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
- }
- else
- slot1 = operands[1];
- if (GET_CODE (operands[2]) != MEM)
- {
- slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
- }
- else
- slot2 = operands[2];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_mul\"), 0,
- VOIDmode, 3,
- XEXP (slot0, 0), Pmode,
- XEXP (slot1, 0), Pmode,
- XEXP (slot2, 0), Pmode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_binop (MULT, operands); DONE;")
(define_insn "*multf3_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
@@ -7485,42 +7270,7 @@
(div:TF (match_operand:TF 1 "general_operand" "")
(match_operand:TF 2 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0, slot1, slot2;
-
- if (GET_CODE (operands[0]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[0];
- if (GET_CODE (operands[1]) != MEM)
- {
- slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
- }
- else
- slot1 = operands[1];
- if (GET_CODE (operands[2]) != MEM)
- {
- slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
- }
- else
- slot2 = operands[2];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_div\"), 0,
- VOIDmode, 3,
- XEXP (slot0, 0), Pmode,
- XEXP (slot1, 0), Pmode,
- XEXP (slot2, 0), Pmode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_binop (DIV, operands); DONE;")
;; don't have timing for quad-prec. divide.
(define_insn "*divtf3_hq"
@@ -7769,37 +7519,10 @@
[(set_attr "type" "fpmove")])
(define_expand "sqrttf2"
- [(set (match_operand:TF 0 "register_operand" "=e")
- (sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (sqrt:TF (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
- "
-{
- if (! TARGET_HARD_QUAD)
- {
- rtx slot0, slot1;
-
- if (GET_CODE (operands[0]) != MEM)
- slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- else
- slot0 = operands[0];
- if (GET_CODE (operands[1]) != MEM)
- {
- slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
- }
- else
- slot1 = operands[1];
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_sqrt\"), 0,
- VOIDmode, 2,
- XEXP (slot0, 0), Pmode,
- XEXP (slot1, 0), Pmode);
-
- if (GET_CODE (operands[0]) != MEM)
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
- DONE;
- }
-}")
+ "emit_tfmode_unop (SQRT, operands); DONE;")
(define_insn "*sqrttf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
@@ -8403,7 +8126,7 @@
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
"call\\t%a0, %1\\n\\tnop\\n\\tunimp\\t%2"
[(set_attr "type" "call_no_delay_slot")
- (set_attr "length" "2")])
+ (set_attr "length" "3")])
;; This is a call that wants a structure value.
;; There is no such critter for v9 (??? we may need one anyway).
@@ -8416,7 +8139,7 @@
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
"call\\t%a0, %1\\n\\tnop\\n\\tunimp\\t%2"
[(set_attr "type" "call_no_delay_slot")
- (set_attr "length" "2")])
+ (set_attr "length" "3")])
;; This is a call that may want a structure value. This is used for
;; untyped_calls.
@@ -8429,7 +8152,7 @@
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
"call\\t%a0, %1\\n\\tnop\\n\\tnop"
[(set_attr "type" "call_no_delay_slot")
- (set_attr "length" "2")])
+ (set_attr "length" "3")])
;; This is a call that wants a structure value.
(define_insn "*call_symbolic_untyped_struct_value_sp32"
@@ -8441,7 +8164,7 @@
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
"call\\t%a0, %1\\n\\tnop\\n\\tnop"
[(set_attr "type" "call_no_delay_slot")
- (set_attr "length" "2")])
+ (set_attr "length" "3")])
(define_expand "call_value"
;; Note that this expression is not used for generating RTL.
@@ -8665,21 +8388,6 @@
[(set_attr "type" "multi")
(set_attr "length" "3")])
-(define_insn "return"
- [(return)
- (use (reg:SI 31))]
- "! TARGET_EPILOGUE"
- "* return output_return (operands);"
- [(set_attr "type" "return")])
-
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operand:SI 1 "arith_operand" "rI"))
- (parallel [(return)
- (use (reg:SI 31))])]
- "sparc_return_peephole_ok (operands[0], operands[1])"
- "return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0")
-
(define_insn "nop"
[(const_int 0)]
""
@@ -8737,7 +8445,7 @@
/* Restore %fp from stack pointer value for containing function.
The restore insn that follows will move this to %sp,
and reload the appropriate value into %fp. */
- emit_move_insn (frame_pointer_rtx, stack);
+ emit_move_insn (hard_frame_pointer_rtx, stack);
/* USE of frame_pointer_rtx added for consistency; not clear if
really needed. */
@@ -8813,22 +8521,41 @@
DONE;
}")
-;; ??? Should set length to zero when !current_function_calls_alloca,
-;; ??? but there is no easy way to get at that definition. It would
-;; ??? require including function.h into sparc-protos.h and that is
-;; ??? likely not a good idea. -DaveM
(define_insn "do_builtin_setjmp_setup"
[(unspec_volatile [(const_int 0)] 5)]
""
"*
{
- if (!current_function_calls_alloca)
- return \"\";
- if (TARGET_V9)
- return \"flushw\";
- return \"ta\\t3\";
+ if (! current_function_calls_alloca || ! TARGET_V9 || TARGET_FLAT)
+ return \"#\";
+ fputs (\"\tflushw\n\", asm_out_file);
+ if (flag_pic)
+ fprintf (asm_out_file, \"\tst%c\t%%l7, [%%sp+%d]\n\",
+ TARGET_ARCH64 ? 'x' : 'w',
+ SPARC_STACK_BIAS + 7 * UNITS_PER_WORD);
+ fprintf (asm_out_file, \"\tst%c\t%%fp, [%%sp+%d]\n\",
+ TARGET_ARCH64 ? 'x' : 'w',
+ SPARC_STACK_BIAS + 14 * UNITS_PER_WORD);
+ fprintf (asm_out_file, \"\tst%c\t%%i7, [%%sp+%d]\n\",
+ TARGET_ARCH64 ? 'x' : 'w',
+ SPARC_STACK_BIAS + 15 * UNITS_PER_WORD);
+ return \"\";
}"
- [(set_attr "type" "misc")])
+ [(set_attr "type" "misc")
+ (set (attr "length") (if_then_else (eq_attr "pic" "true")
+ (const_int 4)
+ (const_int 3)))])
+
+(define_split
+ [(unspec_volatile [(const_int 0)] 5)]
+ "! current_function_calls_alloca || ! TARGET_V9 || TARGET_FLAT"
+ [(const_int 0)]
+ "
+{
+ if (current_function_calls_alloca)
+ emit_insn (gen_flush_register_windows ());
+ DONE;
+}")
;; Pattern for use after a setjmp to store FP and the return register
;; into the stack area.
@@ -8998,7 +8725,7 @@
(set (match_operand:SI 2 "register_operand" "")
(match_operand:SI 3 "memory_operand" ""))]
"registers_ok_for_ldd_peep (operands[2], operands[0])
- && mems_ok_for_ldd_peep (operands[3], operands[1], operands[2])"
+ && mems_ok_for_ldd_peep (operands[3], operands[1], operands[0])"
[(set (match_dup 2)
(match_dup 3))]
"operands[3] = change_address (operands[3], DImode, NULL);
@@ -9023,7 +8750,7 @@
(set (match_operand:SF 2 "register_operand" "")
(match_operand:SF 3 "memory_operand" ""))]
"registers_ok_for_ldd_peep (operands[2], operands[0])
- && mems_ok_for_ldd_peep (operands[3], operands[1], operands[2])"
+ && mems_ok_for_ldd_peep (operands[3], operands[1], operands[0])"
[(set (match_dup 2)
(match_dup 3))]
"operands[3] = change_address (operands[3], DFmode, NULL);
@@ -9073,17 +8800,17 @@
&& ! SPARC_FP_REG_P (REGNO (operands[1]))"
[(parallel [(set (match_dup 0) (match_dup 1))
(set (reg:CCX 100)
- (compare:CC (match_dup 1) (const_int 0)))])]
+ (compare:CCX (match_dup 1) (const_int 0)))])]
"")
-;; Return peepholes. First the "normal" ones.
-;; These are necessary to catch insns ending up in the epilogue delay list.
+;; Return peepholes. These are generated by sparc_nonflat_function_epilogue
+;; who then immediately calls final_scan_insn.
(define_insn "*return_qi"
[(set (match_operand:QI 0 "restore_operand" "")
(match_operand:QI 1 "arith_operand" "rI"))
(return)]
- "! TARGET_EPILOGUE"
+ "sparc_emitting_epilogue"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
@@ -9101,7 +8828,7 @@
[(set (match_operand:HI 0 "restore_operand" "")
(match_operand:HI 1 "arith_operand" "rI"))
(return)]
- "! TARGET_EPILOGUE"
+ "sparc_emitting_epilogue"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
@@ -9119,7 +8846,7 @@
[(set (match_operand:SI 0 "restore_operand" "")
(match_operand:SI 1 "arith_operand" "rI"))
(return)]
- "! TARGET_EPILOGUE"
+ "sparc_emitting_epilogue"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
@@ -9133,15 +8860,11 @@
[(set_attr "type" "multi")
(set_attr "length" "2")])
-;; The following pattern is only generated by delayed-branch scheduling,
-;; when the insn winds up in the epilogue. This can happen not only when
-;; ! TARGET_FPU because we move complex types around by parts using
-;; SF mode SUBREGs.
(define_insn "*return_sf_no_fpu"
[(set (match_operand:SF 0 "restore_operand" "=r")
(match_operand:SF 1 "register_operand" "r"))
(return)]
- "! TARGET_EPILOGUE"
+ "sparc_emitting_epilogue"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
@@ -9158,7 +8881,7 @@
[(set (match_operand:DF 0 "restore_operand" "=r")
(match_operand:DF 1 "register_operand" "r"))
(return)]
- "! TARGET_EPILOGUE && TARGET_ARCH64"
+ "sparc_emitting_epilogue && TARGET_ARCH64"
"*
{
if (IN_OR_GLOBAL_P (operands[1]))
@@ -9174,7 +8897,7 @@
(plus:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "rI")))
(return)]
- "! TARGET_EPILOGUE"
+ "sparc_emitting_epilogue"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
@@ -9195,7 +8918,7 @@
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "immediate_operand" "in")))
(return)]
- "! TARGET_EPILOGUE && ! TARGET_CM_MEDMID"
+ "sparc_emitting_epilogue && ! TARGET_CM_MEDMID"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
@@ -9213,7 +8936,7 @@
[(set (match_operand:DI 0 "restore_operand" "")
(match_operand:DI 1 "arith_double_operand" "rHI"))
(return)]
- "TARGET_ARCH64 && ! TARGET_EPILOGUE"
+ "sparc_emitting_epilogue && TARGET_ARCH64"
"ret\;restore %%g0, %1, %Y0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -9223,7 +8946,7 @@
(plus:DI (match_operand:DI 1 "arith_operand" "%r")
(match_operand:DI 2 "arith_double_operand" "rHI")))
(return)]
- "TARGET_ARCH64 && ! TARGET_EPILOGUE"
+ "sparc_emitting_epilogue && TARGET_ARCH64"
"ret\;restore %r1, %2, %Y0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -9233,23 +8956,24 @@
(lo_sum:DI (match_operand:DI 1 "arith_operand" "%r")
(match_operand:DI 2 "immediate_operand" "in")))
(return)]
- "TARGET_ARCH64 && ! TARGET_EPILOGUE && ! TARGET_CM_MEDMID"
+ "sparc_emitting_epilogue && TARGET_ARCH64 && ! TARGET_CM_MEDMID"
"ret\;restore %r1, %%lo(%a2), %Y0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
-;; The following pattern is only generated by delayed-branch scheduling,
-;; when the insn winds up in the epilogue.
(define_insn "*return_sf"
[(set (reg:SF 32)
(match_operand:SF 0 "register_operand" "f"))
(return)]
- "! TARGET_EPILOGUE"
+ "sparc_emitting_epilogue"
"ret\;fmovs\\t%0, %%f0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
;; Now peepholes to do a call followed by a jump.
+;; Do not match this on V9 and later processors, which have a call-return
+;; stack as this corrupts it and causes the code to run slower not faster.
+;; There are not TARGET_ARCH64 patterns because that implies TARGET_V9.
(define_peephole
[(parallel [(set (match_operand 0 "" "")
@@ -9257,7 +8981,8 @@
(match_operand 2 "" "")))
(clobber (reg:SI 15))])
(set (pc) (label_ref (match_operand 3 "" "")))]
- "short_branch (INSN_UID (insn), INSN_UID (operands[3]))
+ "! TARGET_V9
+ && short_branch (INSN_UID (insn), INSN_UID (operands[3]))
&& (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))"
"call\\t%a1, %2\\n\\tadd\\t%%o7, (%l3-.-4), %%o7")
@@ -9266,49 +8991,70 @@
(match_operand 1 "" ""))
(clobber (reg:SI 15))])
(set (pc) (label_ref (match_operand 2 "" "")))]
- "short_branch (INSN_UID (insn), INSN_UID (operands[2]))
- && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))"
- "call\\t%a0, %1\\n\\tadd\\t%%o7, (%l2-.-4), %%o7")
-
-(define_peephole
- [(parallel [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:DI 1 "call_operand_address" "ps"))
- (match_operand 2 "" "")))
- (clobber (reg:DI 15))])
- (set (pc) (label_ref (match_operand 3 "" "")))]
- "TARGET_ARCH64
- && short_branch (INSN_UID (insn), INSN_UID (operands[3]))
- && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))"
- "call\\t%a1, %2\\n\\tadd\\t%%o7, (%l3-.-4), %%o7")
-
-(define_peephole
- [(parallel [(call (mem:SI (match_operand:DI 0 "call_operand_address" "ps"))
- (match_operand 1 "" ""))
- (clobber (reg:DI 15))])
- (set (pc) (label_ref (match_operand 2 "" "")))]
- "TARGET_ARCH64
+ "! TARGET_V9
&& short_branch (INSN_UID (insn), INSN_UID (operands[2]))
&& (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))"
"call\\t%a0, %1\\n\\tadd\\t%%o7, (%l2-.-4), %%o7")
-(define_insn "prefetch"
+;; ??? UltraSPARC-III note: A memory operation loading into the floating point register
+;; ??? file, if it hits the prefetch cache, has a chance to dual-issue with other memory
+;; ??? operations. With DFA we might be able to model this, but it requires a lot of
+;; ??? state.
+(define_expand "prefetch"
+ [(match_operand 0 "address_operand" "")
+ (match_operand 1 "const_int_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_V9"
+ "
+{
+ if (TARGET_ARCH64)
+ emit_insn (gen_prefetch_64 (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_prefetch_32 (operands[0], operands[1], operands[2]));
+ DONE;
+}")
+
+(define_insn "prefetch_64"
[(prefetch (match_operand:DI 0 "address_operand" "p")
(match_operand:DI 1 "const_int_operand" "n")
(match_operand:DI 2 "const_int_operand" "n"))]
- "TARGET_V9"
+ ""
+{
+ static const char * const prefetch_instr[2][2] = {
+ {
+ "prefetch\\t[%a0], 1", /* no locality: prefetch for one read */
+ "prefetch\\t[%a0], 0", /* medium to high locality: prefetch for several reads */
+ },
+ {
+ "prefetch\\t[%a0], 3", /* no locality: prefetch for one write */
+ "prefetch\\t[%a0], 2", /* medium to high locality: prefetch for several writes */
+ }
+ };
+ int read_or_write = INTVAL (operands[1]);
+ int locality = INTVAL (operands[2]);
+
+ if (read_or_write != 0 && read_or_write != 1)
+ abort ();
+ if (locality < 0 || locality > 3)
+ abort ();
+ return prefetch_instr [read_or_write][locality == 0 ? 0 : 1];
+}
+ [(set_attr "type" "load")])
+
+(define_insn "prefetch_32"
+ [(prefetch (match_operand:SI 0 "address_operand" "p")
+ (match_operand:SI 1 "const_int_operand" "n")
+ (match_operand:SI 2 "const_int_operand" "n"))]
+ ""
{
- static const char * const prefetch_instr[2][4] = {
+ static const char * const prefetch_instr[2][2] = {
{
"prefetch\\t[%a0], 1", /* no locality: prefetch for one read */
- "prefetch\\t[%a0], 0", /* medium locality: prefetch for several reads */
- "prefetch\\t[%a0], 0", /* medium locality: prefetch for several reads */
- "prefetch\\t[%a0], 4", /* high locality: prefetch page */
+ "prefetch\\t[%a0], 0", /* medium to high locality: prefetch for several reads */
},
{
"prefetch\\t[%a0], 3", /* no locality: prefetch for one write */
- "prefetch\\t[%a0], 2", /* medium locality: prefetch for several writes */
- "prefetch\\t[%a0], 2", /* medium locality: prefetch for several writes */
- "prefetch\\t[%a0], 4", /* high locality: prefetch page */
+ "prefetch\\t[%a0], 2", /* medium to high locality: prefetch for several writes */
}
};
int read_or_write = INTVAL (operands[1]);
@@ -9318,7 +9064,7 @@
abort ();
if (locality < 0 || locality > 3)
abort ();
- return prefetch_instr [read_or_write][locality];
+ return prefetch_instr [read_or_write][locality == 0 ? 0 : 1];
}
[(set_attr "type" "load")])
diff --git a/contrib/gcc/config/sparc/splet.h b/contrib/gcc/config/sparc/splet.h
index d2ef4fbe35d2..0d3f0546abe2 100644
--- a/contrib/gcc/config/sparc/splet.h
+++ b/contrib/gcc/config/sparc/splet.h
@@ -20,7 +20,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE)
+#define TARGET_DEFAULT MASK_APP_REGS
#define CPP_PREDEFINES "-Dsparc -Acpu=sparc -Amachine=sparc"
diff --git a/contrib/gcc/config/sparc/t-crtfm b/contrib/gcc/config/sparc/t-crtfm
new file mode 100644
index 000000000000..744537db3bd3
--- /dev/null
+++ b/contrib/gcc/config/sparc/t-crtfm
@@ -0,0 +1,4 @@
+EXTRA_PARTS += crtfastmath.o
+
+crtfastmath.o: $(srcdir)/config/sparc/crtfastmath.c $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -c -o crtfastmath.o $(srcdir)/config/sparc/crtfastmath.c
diff --git a/contrib/gcc/config/sparc/t-elf b/contrib/gcc/config/sparc/t-elf
index ead6e25610d0..027940b10e44 100644
--- a/contrib/gcc/config/sparc/t-elf
+++ b/contrib/gcc/config/sparc/t-elf
@@ -1,3 +1,6 @@
+LIB1ASMSRC = sparc/lb1spc.asm
+LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3
+
# We want fine grained libraries, so use the new code to build the
# floating point emulation libraries.
FPBIT = fp-bit.c
@@ -12,12 +15,9 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
# MULTILIB_OPTIONS should have msparclite too, but we'd have to make
# gas build...
-#MULTILIB_OPTIONS = msoft-float mcpu=v8
-MULTILIB_OPTIONS = msoft-float
-#MULTILIB_DIRNAMES = soft v8
-MULTILIB_DIRNAMES = soft
-#MULTILIB_MATCHES = msoft-float=mno-fpu mcpu?v8=mv8
-MULTILIB_MATCHES = msoft-float=mno-fpu
+MULTILIB_OPTIONS = msoft-float mcpu=v8
+MULTILIB_DIRNAMES = soft v8
+MULTILIB_MATCHES = msoft-float=mno-fpu mcpu?v8=mv8
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
diff --git a/contrib/gcc/config/sparc/t-linux64 b/contrib/gcc/config/sparc/t-linux64
index 4f552e07d1e8..c93ff25a3ff1 100644
--- a/contrib/gcc/config/sparc/t-linux64
+++ b/contrib/gcc/config/sparc/t-linux64
@@ -8,3 +8,11 @@ LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
+
+SHLIB_SLIBDIR_SUFFIXES = 64:64 32:
+
+# Override t-slibgcc-elf-ver to export some libgcc symbols with
+# the symbol versions that glibc used.
+# Avoid the t-linux version file.
+SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver \
+ $(srcdir)/config/sparc/libgcc-sparc-glibc.ver
diff --git a/contrib/gcc/config/sparc/t-netbsd64 b/contrib/gcc/config/sparc/t-netbsd64
new file mode 100644
index 000000000000..1292b86367fe
--- /dev/null
+++ b/contrib/gcc/config/sparc/t-netbsd64
@@ -0,0 +1,6 @@
+MULTILIB_OPTIONS = m32/m64
+MULTILIB_DIRNAMES = 32 64
+MULTILIB_MATCHES =
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
diff --git a/contrib/gcc/config/sparc/t-sol2-64 b/contrib/gcc/config/sparc/t-sol2-64
index 8d42c4453542..ef7dee7ecab2 100644
--- a/contrib/gcc/config/sparc/t-sol2-64
+++ b/contrib/gcc/config/sparc/t-sol2-64
@@ -6,3 +6,5 @@ LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o gmon.o crt1.o crti.o crtn.o gcrt1.o
+
+SHLIB_SLIBDIR_SUFFIXES = sparcv9:/sparcv9 sparcv7:
diff --git a/contrib/gcc/config/sparc/vxsim.h b/contrib/gcc/config/sparc/vxsim.h
index 94cfb92df101..c821e82273ed 100644
--- a/contrib/gcc/config/sparc/vxsim.h
+++ b/contrib/gcc/config/sparc/vxsim.h
@@ -71,6 +71,9 @@ do { \
#undef COMMON_ASM_OP
#define COMMON_ASM_OP "\t.common\t"
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
/* This is how to output a definition of an internal numbered label where
PREFIX is the class of label and NUM is the number within the class. */
diff --git a/contrib/gcc/config/sparc/vxsparc64.h b/contrib/gcc/config/sparc/vxsparc64.h
index ecfe25b6c342..358f2c00087a 100644
--- a/contrib/gcc/config/sparc/vxsparc64.h
+++ b/contrib/gcc/config/sparc/vxsparc64.h
@@ -71,7 +71,7 @@ Boston, MA 02111-1307, USA. */
#define CPP_SPEC "%(cpp_cpu) %(cpp_arch) -DCPU=ULTRASPARC -D__CPU__=CPU"
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_APP_REGS | MASK_EPILOGUE | MASK_FPU \
+#define TARGET_DEFAULT (MASK_APP_REGS | MASK_FPU \
| MASK_LONG_DOUBLE_128 | MASK_64BIT)
#undef SPARC_DEFAULT_CMODEL