summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/config/sparc
diff options
context:
space:
mode:
authorkan <kan@FreeBSD.org>2004-07-28 03:11:36 +0000
committerkan <kan@FreeBSD.org>2004-07-28 03:11:36 +0000
commite0020c9fe3d2c91658ad0f59cb6a55c44f909db3 (patch)
treeb406472295ae0b130894cc19f02f43b36157fec6 /contrib/gcc/config/sparc
parentb754d213ab76dee1e7bcd5acb4becd5658c0ca99 (diff)
parent5e00ec74d8ce58f99801200d4d3d0412c7cc1b28 (diff)
downloadFreeBSD-src-e0020c9fe3d2c91658ad0f59cb6a55c44f909db3.zip
FreeBSD-src-e0020c9fe3d2c91658ad0f59cb6a55c44f909db3.tar.gz
This commit was generated by cvs2svn to compensate for changes in r132718,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'contrib/gcc/config/sparc')
-rw-r--r--contrib/gcc/config/sparc/aout.h26
-rw-r--r--contrib/gcc/config/sparc/biarch64.h10
-rw-r--r--contrib/gcc/config/sparc/cypress.md8
-rw-r--r--contrib/gcc/config/sparc/elf.h30
-rw-r--r--contrib/gcc/config/sparc/gmon-sol2.c29
-rw-r--r--contrib/gcc/config/sparc/hypersparc.md8
-rw-r--r--contrib/gcc/config/sparc/linux.h89
-rw-r--r--contrib/gcc/config/sparc/linux64.h102
-rw-r--r--contrib/gcc/config/sparc/lite.h18
-rw-r--r--contrib/gcc/config/sparc/litecoff.h19
-rw-r--r--contrib/gcc/config/sparc/liteelf.h25
-rw-r--r--contrib/gcc/config/sparc/netbsd-elf.h41
-rw-r--r--contrib/gcc/config/sparc/openbsd.h29
-rw-r--r--contrib/gcc/config/sparc/openbsd64.h19
-rw-r--r--contrib/gcc/config/sparc/pbd.h39
-rw-r--r--contrib/gcc/config/sparc/rtemself.h23
-rw-r--r--contrib/gcc/config/sparc/sol2-64.h11
-rw-r--r--contrib/gcc/config/sparc/sol2-bi.h80
-rw-r--r--contrib/gcc/config/sparc/sol2-gas-bi.h6
-rw-r--r--contrib/gcc/config/sparc/sol2-gld-bi.h27
-rw-r--r--contrib/gcc/config/sparc/sol2-gld.h5
-rw-r--r--contrib/gcc/config/sparc/sol2.h86
-rw-r--r--contrib/gcc/config/sparc/sol26-sld.h7
-rw-r--r--contrib/gcc/config/sparc/sp64-aout.h10
-rw-r--r--contrib/gcc/config/sparc/sp64-elf.h22
-rw-r--r--contrib/gcc/config/sparc/sp86x-elf.h25
-rw-r--r--contrib/gcc/config/sparc/sparc-modes.def24
-rw-r--r--contrib/gcc/config/sparc/sparc-protos.h177
-rw-r--r--contrib/gcc/config/sparc/sparc.c2926
-rw-r--r--contrib/gcc/config/sparc/sparc.h525
-rw-r--r--contrib/gcc/config/sparc/sparc.md729
-rw-r--r--contrib/gcc/config/sparc/sparclet.md8
-rw-r--r--contrib/gcc/config/sparc/supersparc.md8
-rw-r--r--contrib/gcc/config/sparc/sysv4-only.h35
-rw-r--r--contrib/gcc/config/sparc/sysv4.h24
-rw-r--r--contrib/gcc/config/sparc/t-sol23
-rw-r--r--contrib/gcc/config/sparc/ultra1_2.md58
-rw-r--r--contrib/gcc/config/sparc/ultra3.md29
38 files changed, 3373 insertions, 1967 deletions
diff --git a/contrib/gcc/config/sparc/aout.h b/contrib/gcc/config/sparc/aout.h
index 7532281..1031048 100644
--- a/contrib/gcc/config/sparc/aout.h
+++ b/contrib/gcc/config/sparc/aout.h
@@ -1,21 +1,21 @@
-/* Definitions of target machine for GNU compiler, for SPARC using a.out.
+/* Definitions of target machine for GCC, for SPARC using a.out.
Copyright (C) 1994, 1996, 2002 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com).
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
@@ -23,14 +23,6 @@ Boston, MA 02111-1307, USA. */
#define TARGET_VERSION fprintf (stderr, " (sparc)");
-/* Names to predefine in the preprocessor for this target machine.
- ??? It would be nice to not include any subtarget specific values here,
- however there's no way to portably provide subtarget values to
- CPP_PREFINES. Also, -D values in CPP_SUBTARGET_SPEC don't get turned into
- foo, __foo and __foo__. */
-
-#define CPP_PREDEFINES "-Dsparc -Acpu=sparc -Amachine=sparc"
-
/* These compiler options take an argument. We ignore -target for now. */
#define WORD_SWITCH_TAKES_ARG(STR) \
@@ -67,8 +59,6 @@ do { \
This is needed for SunOS 4.0, and should not hurt for 3.2
versions either. */
-#define ASM_OUTPUT_SOURCE_LINE(file, line) \
- { static int sym_lineno = 1; \
- fprintf (file, ".stabn 68,0,%d,LM%d\nLM%d:\n", \
- line, sym_lineno, sym_lineno); \
- sym_lineno += 1; }
+#define ASM_OUTPUT_SOURCE_LINE(file, line, counter) \
+ fprintf (file, ".stabn 68,0,%d,LM%d\nLM%d:\n", \
+ line, counter, counter)
diff --git a/contrib/gcc/config/sparc/biarch64.h b/contrib/gcc/config/sparc/biarch64.h
index f85111ab..b825f4f 100644
--- a/contrib/gcc/config/sparc/biarch64.h
+++ b/contrib/gcc/config/sparc/biarch64.h
@@ -1,21 +1,21 @@
-/* Definitions of target machine for GNU compiler, for Sun SPARC.
+/* Definitions of target machine for GCC, for Sun SPARC.
Copyright (C) 2001 Free Software Foundation, Inc.
Contributed by David E. O'Brien <obrien@FreeBSD.org>.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
diff --git a/contrib/gcc/config/sparc/cypress.md b/contrib/gcc/config/sparc/cypress.md
index e9bff6d..c234594 100644
--- a/contrib/gcc/config/sparc/cypress.md
+++ b/contrib/gcc/config/sparc/cypress.md
@@ -1,20 +1,20 @@
;; Scheduling description for SPARC Cypress.
;; Copyright (C) 2002 Free Software Foundation, Inc.
;;
-;; This file is part of GNU CC.
+;; This file is part of GCC.
;;
-;; GNU CC is free software; you can redistribute it and/or modify
+;; GCC is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;;
-;; GNU CC is distributed in the hope that it will be useful,
+;; GCC is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with GNU CC; see the file COPYING. If not, write to
+;; along with GCC; see the file COPYING. If not, write to
;; the Free Software Foundation, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
diff --git a/contrib/gcc/config/sparc/elf.h b/contrib/gcc/config/sparc/elf.h
index d2d3a0b..5f01a34 100644
--- a/contrib/gcc/config/sparc/elf.h
+++ b/contrib/gcc/config/sparc/elf.h
@@ -1,27 +1,24 @@
-/* Definitions of target machine for GNU compiler,
+/* Definitions of target machine for GCC,
for SPARC running in an embedded environment using the ELF file format.
Copyright (C) 1997 Free Software Foundation, Inc.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dsparc -D__elf__"
-
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "crt0.o%s crti.o%s crtbegin.o%s"
@@ -45,14 +42,9 @@ Boston, MA 02111-1307, USA. */
#undef STDC_0_IN_SYSTEM_HEADERS
/* We don't want to use the Solaris2 specific long long int conversion
- routines. */
-#undef INIT_SUBTARGET_OPTABS
-#define INIT_SUBTARGET_OPTABS
-
-/* ??? We haven't added Solaris2 equivalent 64 bit library routines to
- lb1sp*.asm, so we need to avoid using them. */
-#undef MULDI3_LIBCALL
-#undef DIVDI3_LIBCALL
-#undef UDIVDI3_LIBCALL
-#undef MODDI3_LIBCALL
-#undef UMODDI3_LIBCALL
+ routines or 64-bit integer multiply and divide routines. */
+#undef SUN_CONVERSION_LIBFUNCS
+#define SUN_CONVERSION_LIBFUNCS 0
+
+#undef SUN_INTEGER_MULTIPLY_64
+#define SUN_INTEGER_MULTIPLY_64 0
diff --git a/contrib/gcc/config/sparc/gmon-sol2.c b/contrib/gcc/config/sparc/gmon-sol2.c
index c577666..9f9f019 100644
--- a/contrib/gcc/config/sparc/gmon-sol2.c
+++ b/contrib/gcc/config/sparc/gmon-sol2.c
@@ -32,8 +32,11 @@
* for Cygnus Support, July 1992.
*/
-#include "config.h"
-#include "system.h"
+#include "tconfig.h"
+#include "tsystem.h"
+#include <fcntl.h> /* for creat() */
+#include "coretypes.h"
+#include "tm.h"
#if 0
#include "sparc/gmon.h"
@@ -85,13 +88,11 @@ static int s_scale;
#define MSG "No space for profiling buffer(s)\n"
-static void moncontrol PARAMS ((int));
-extern void monstartup PARAMS ((char *, char *));
-extern void _mcleanup PARAMS ((void));
+static void moncontrol (int);
+extern void monstartup (char *, char *);
+extern void _mcleanup (void);
-void monstartup(lowpc, highpc)
- char *lowpc;
- char *highpc;
+void monstartup(char *lowpc, char *highpc)
{
int monsize;
char *buffer;
@@ -167,7 +168,7 @@ void monstartup(lowpc, highpc)
}
void
-_mcleanup()
+_mcleanup(void)
{
int fd;
int fromindex;
@@ -266,7 +267,8 @@ _mcleanup()
* -- [eichin:19920702.1107EST]
*/
-static void internal_mcount PARAMS ((char *, unsigned short *)) ATTRIBUTE_UNUSED;
+static void internal_mcount (char *, unsigned short *)
+ __attribute__ ((__unused__));
/* i7 == last ret, -> frompcindex */
/* o7 == current ret, -> selfpc */
@@ -275,9 +277,7 @@ asm(".global _mcount; _mcount: mov %i7,%o1; mov %o7,%o0;b,a internal_mcount");
/* This is for compatibility with old versions of gcc which used mcount. */
asm(".global mcount; mcount: mov %i7,%o1; mov %o7,%o0;b,a internal_mcount");
-static void internal_mcount(selfpc, frompcindex)
- register char *selfpc;
- register unsigned short *frompcindex;
+static void internal_mcount(char *selfpc, unsigned short *frompcindex)
{
register struct tostruct *top;
register struct tostruct *prevtop;
@@ -407,8 +407,7 @@ overflow:
* profiling is what mcount checks to see if
* all the data structures are ready.
*/
-static void moncontrol(mode)
- int mode;
+static void moncontrol(int mode)
{
if (mode) {
/* start */
diff --git a/contrib/gcc/config/sparc/hypersparc.md b/contrib/gcc/config/sparc/hypersparc.md
index d80e51e..d617efd 100644
--- a/contrib/gcc/config/sparc/hypersparc.md
+++ b/contrib/gcc/config/sparc/hypersparc.md
@@ -1,20 +1,20 @@
;; Scheduling description for HyperSPARC.
;; Copyright (C) 2002 Free Software Foundation, Inc.
;;
-;; This file is part of GNU CC.
+;; This file is part of GCC.
;;
-;; GNU CC is free software; you can redistribute it and/or modify
+;; GCC is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;;
-;; GNU CC is distributed in the hope that it will be useful,
+;; GCC is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with GNU CC; see the file COPYING. If not, write to
+;; along with GCC; see the file COPYING. If not, write to
;; the Free Software Foundation, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
diff --git a/contrib/gcc/config/sparc/linux.h b/contrib/gcc/config/sparc/linux.h
index e4bd7bb..7ddf2a3 100644
--- a/contrib/gcc/config/sparc/linux.h
+++ b/contrib/gcc/config/sparc/linux.h
@@ -1,37 +1,40 @@
/* Definitions for SPARC running Linux-based GNU systems with ELF.
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004
+ Free Software Foundation, Inc.
Contributed by Eddie C. Dost (ecd@skynet.be)
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#define LINUX_DEFAULT_ELF
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("unix"); \
+ builtin_define_std ("linux"); \
+ builtin_define ("__gnu_linux__"); \
+ builtin_assert ("system=linux"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=posix"); \
+ } \
+ while (0)
/* Don't assume anything about the header files. */
#define NO_IMPLICIT_EXTERN_C
-/* GNU/Linux uses ctype from glibc.a. I am not sure how complete it is.
- For now, we play safe. It may change later. */
-
-#if 0
-#undef MULTIBYTE_CHARS
-#define MULTIBYTE_CHARS 1
-#endif
-
#undef MD_EXEC_PREFIX
#undef MD_STARTFILE_PREFIX
@@ -46,12 +49,14 @@ Boston, MA 02111-1307, USA. */
"%{!shared: \
%{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\
crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
+#elif defined HAVE_LD_PIE
+#define STARTFILE_SPEC \
+ "%{!shared: %{pg|p:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}}\
+ crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}"
#else
#define STARTFILE_SPEC \
- "%{!shared: \
- %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\
- crti.o%s %{static:crtbeginT.o%s}\
- %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
+ "%{!shared: %{pg|p:gcrt1.o%s;:crt1.o%s}}\
+ crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}"
#endif
/* Provide a ENDFILE_SPEC appropriate for GNU/Linux. Here we tack on
@@ -63,7 +68,7 @@ Boston, MA 02111-1307, USA. */
#undef ENDFILE_SPEC
#define ENDFILE_SPEC \
"%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
- %{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
+ %{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s"
/* This is for -profile to use -lc_p instead of -lc. */
#undef CC1_SPEC
@@ -98,17 +103,14 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__ELF__ -Dunix -D__sparc__ -D__gnu_linux__ -Dlinux -Asystem=unix -Asystem=posix"
-
#undef CPP_SUBTARGET_SPEC
#ifdef USE_GNULIBC_1
#define CPP_SUBTARGET_SPEC \
-"%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} \
+"%{fPIC|fPIE|fpic|fpie:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} \
%{mlong-double-128:-D__LONG_DOUBLE_128__}"
#else
#define CPP_SUBTARGET_SPEC \
-"%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} \
+"%{fPIC|fPIE|fpic|fpie:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} \
%{pthread:-D_REENTRANT} %{mlong-double-128:-D__LONG_DOUBLE_128__}"
#endif
@@ -152,15 +154,6 @@ Boston, MA 02111-1307, USA. */
#undef LINK_SPEC
#ifdef USE_GNULIBC_1
-#ifndef LINUX_DEFAULT_ELF
-#define LINK_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \
- %{!shared: \
- %{!ibcs: \
- %{!static: \
- %{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /lib/elf/ld-linux.so.1} \
- %{!rpath:-rpath /lib/elf/}} %{static:-static}}}"
-#else
#define LINK_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \
%{!shared: \
%{!ibcs: \
@@ -168,7 +161,6 @@ Boston, MA 02111-1307, USA. */
%{rdynamic:-export-dynamic} \
%{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \
%{static:-static}}}"
-#endif
#else
#define LINK_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \
%{!mno-relax:%{!r:-relax}} \
@@ -184,8 +176,8 @@ Boston, MA 02111-1307, USA. */
It's safe to pass -s always, even if -g is not used. */
#undef ASM_SPEC
#define ASM_SPEC \
- "%{V} %{v:%{!V:-V}} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s %{fpic:-K PIC} \
- %{fPIC:-K PIC} %(asm_cpu) %(asm_relax)"
+ "%{V} %{v:%{!V:-V}} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s \
+ %{fpic|fPIC|fpie|fPIE:-K PIC} %(asm_cpu) %(asm_relax)"
/* Same as sparc.h */
#undef DBX_REGISTER_NUMBER
@@ -206,13 +198,6 @@ do { \
#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. */
@@ -245,10 +230,20 @@ do { \
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
#endif
+#undef DITF_CONVERSION_LIBFUNCS
+#define DITF_CONVERSION_LIBFUNCS 1
+
#if !defined(USE_GNULIBC_1) && defined(HAVE_LD_EH_FRAME_HDR)
#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
#endif
+#ifdef HAVE_AS_TLS
+#undef TARGET_SUN_TLS
+#undef TARGET_GNU_TLS
+#define TARGET_SUN_TLS 0
+#define TARGET_GNU_TLS 1
+#endif
+
/* Don't be different from other Linux platforms in this regard. */
#define HANDLE_PRAGMA_PACK_PUSH_POP
@@ -256,6 +251,14 @@ do { \
#undef CTORS_SECTION_ASM_OP
#undef DTORS_SECTION_ASM_OP
+#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
+
+/* Determine whether the the entire c99 runtime is present in the
+ runtime library. */
+#define TARGET_C99_FUNCTIONS 1
+
+#define TARGET_HAS_F_SETLKW
+
#undef LINK_GCC_C_SEQUENCE_SPEC
#define LINK_GCC_C_SEQUENCE_SPEC \
"%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}"
diff --git a/contrib/gcc/config/sparc/linux64.h b/contrib/gcc/config/sparc/linux64.h
index 27be1d1..bb1c591 100644
--- a/contrib/gcc/config/sparc/linux64.h
+++ b/contrib/gcc/config/sparc/linux64.h
@@ -1,25 +1,37 @@
/* Definitions for 64-bit SPARC running Linux-based GNU systems with ELF.
- Copyright 1996, 1997, 1998, 2000, 2002 Free Software Foundation, Inc.
+ Copyright 1996, 1997, 1998, 2000, 2002, 2003, 2004
+ Free Software Foundation, Inc.
Contributed by David S. Miller (davem@caip.rutgers.edu)
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#define LINUX_DEFAULT_ELF
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("unix"); \
+ builtin_define_std ("linux"); \
+ builtin_define ("_LONGLONG"); \
+ builtin_define ("__gnu_linux__"); \
+ builtin_assert ("system=linux"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=posix"); \
+ } \
+ while (0)
/* Don't assume anything about the header files. */
#define NO_IMPLICIT_EXTERN_C
@@ -27,7 +39,9 @@ Boston, MA 02111-1307, USA. */
#undef MD_EXEC_PREFIX
#undef MD_STARTFILE_PREFIX
-#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc
+#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc3
/* A 64 bit v9 compiler with stack-bias,
in a Medium/Low code model environment. */
@@ -43,8 +57,7 @@ Boston, MA 02111-1307, USA. */
#ifdef SPARC_BI_ARCH
#undef CPP_ARCH32_SPEC
-#define CPP_ARCH32_SPEC "%{mlong-double-128:-D__LONG_DOUBLE_128__} \
--D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc"
+#define CPP_ARCH32_SPEC "%{mlong-double-128:-D__LONG_DOUBLE_128__}"
#endif
@@ -55,10 +68,15 @@ Boston, MA 02111-1307, USA. */
#undef STARTFILE_SPEC
+#ifdef HAVE_LD_PIE
#define STARTFILE_SPEC \
- "%{!shared:%{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\
- crti.o%s %{static:crtbeginT.o%s}\
- %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
+ "%{!shared:%{pg|p:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}}\
+ crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbeginS.o%s}"
+#else
+#define STARTFILE_SPEC \
+ "%{!shared:%{pg|p:gcrt1.o%s;:crt1.o%s}}\
+ crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbeginS.o%s}"
+#endif
/* Provide a ENDFILE_SPEC appropriate for GNU/Linux. Here we tack on
the GNU/Linux magical crtend.o file (see crtstuff.c) which
@@ -69,7 +87,7 @@ Boston, MA 02111-1307, USA. */
#undef ENDFILE_SPEC
#define ENDFILE_SPEC \
- "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s\
+ "%{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s\
%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s}"
/* The GNU C++ standard library requires that these macros be defined. */
@@ -111,13 +129,9 @@ Boston, MA 02111-1307, USA. */
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
#endif
-#undef CPP_PREDEFINES
-#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 "\
-%{fPIC:-D__PIC__ -D__pic__} \
-%{fpic:-D__PIC__ -D__pic__} \
+%{fPIC|fpic|fPIE|fpie:-D__PIC__ -D__pic__} \
%{posix:-D_POSIX_SOURCE} \
%{pthread:-D_REENTRANT} \
"
@@ -213,6 +227,27 @@ Boston, MA 02111-1307, USA. */
"
#endif
+/* Support for a compile-time default CPU, et cetera. The rules are:
+ --with-cpu is ignored if -mcpu is specified.
+ --with-tune is ignored if -mtune is specified.
+ --with-float is ignored if -mhard-float, -msoft-float, -mfpu, or -mno-fpu
+ are specified.
+ In the SPARC_BI_ARCH compiler we cannot pass %{!mcpu=*:-mcpu=%(VALUE)}
+ here, otherwise say -mcpu=v7 would be passed even when -m64.
+ CC1_SPEC above takes care of this instead. */
+#undef OPTION_DEFAULT_SPECS
+#if DEFAULT_ARCH32_P
+#define OPTION_DEFAULT_SPECS \
+ {"cpu", "%{!m64:%{!mcpu=*:-mcpu=%(VALUE)}}" }, \
+ {"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \
+ {"float", "%{!msoft-float:%{!mhard-float:%{!fpu:%{!no-fpu:-m%(VALUE)-float}}}}" }
+#else
+#define OPTION_DEFAULT_SPECS \
+ {"cpu", "%{!m32:%{!mcpu=*:-mcpu=%(VALUE)}}" }, \
+ {"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \
+ {"float", "%{!msoft-float:%{!mhard-float:%{!fpu:%{!no-fpu:-m%(VALUE)-float}}}}" }
+#endif
+
#if DEFAULT_ARCH32_P
#define MULTILIB_DEFAULTS { "m32" }
#else
@@ -246,7 +281,7 @@ Boston, MA 02111-1307, USA. */
%{T} \
%{Ym,*} \
%{Wa,*:%*} \
--s %{fpic:-K PIC} %{fPIC:-K PIC} \
+-s %{fpic|fPIC|fpie|fPIE:-K PIC} \
%{mlittle-endian:-EL} \
%(asm_cpu) %(asm_arch) %(asm_relax)"
@@ -254,10 +289,6 @@ Boston, MA 02111-1307, USA. */
#undef DBX_REGISTER_NUMBER
#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
-/* System V Release 4 uses DWARF debugging info. Buf DWARF1 doesn't do
- 64-bit anything, so we use DWARF2. */
-
-#undef DWARF_DEBUGGING_INFO
#define DWARF2_DEBUGGING_INFO 1
#define DBX_DEBUGGING_INFO 1
@@ -276,13 +307,6 @@ do { \
#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. */
@@ -308,10 +332,20 @@ do { \
/* #define DWARF_OFFSET_SIZE PTR_SIZE */
+#undef DITF_CONVERSION_LIBFUNCS
+#define DITF_CONVERSION_LIBFUNCS 1
+
#if defined(HAVE_LD_EH_FRAME_HDR)
#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
#endif
+#ifdef HAVE_AS_TLS
+#undef TARGET_SUN_TLS
+#undef TARGET_GNU_TLS
+#define TARGET_SUN_TLS 0
+#define TARGET_GNU_TLS 1
+#endif
+
/* Don't be different from other Linux platforms in this regard. */
#define HANDLE_PRAGMA_PACK_PUSH_POP
@@ -319,6 +353,14 @@ do { \
#undef CTORS_SECTION_ASM_OP
#undef DTORS_SECTION_ASM_OP
+#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
+
+/* Determine whether the the entire c99 runtime is present in the
+ runtime library. */
+#define TARGET_C99_FUNCTIONS 1
+
+#define TARGET_HAS_F_SETLKW
+
#undef LINK_GCC_C_SEQUENCE_SPEC
#define LINK_GCC_C_SEQUENCE_SPEC \
"%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}"
diff --git a/contrib/gcc/config/sparc/lite.h b/contrib/gcc/config/sparc/lite.h
index 95da781..cac67ec 100644
--- a/contrib/gcc/config/sparc/lite.h
+++ b/contrib/gcc/config/sparc/lite.h
@@ -1,27 +1,24 @@
-/* Definitions of target machine for GNU compiler, for SPARClite w/o FPU.
+/* Definitions of target machine for GCC, for SPARClite w/o FPU.
Copyright (C) 1993, 1996 Free Software Foundation, Inc.
Contributed by Jim Wilson (wilson@cygnus.com).
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dsparc -Dsparclite -Acpu=sparc -Amachine=sparc"
-
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (sparclite)");
@@ -30,6 +27,5 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT MASK_APP_REGS
-/* US Software GOFAST library support. */
-#undef INIT_SUBTARGET_OPTABS
-#define INIT_SUBTARGET_OPTABS INIT_GOFAST_OPTABS
+/* Enable US Software GOFAST library support. */
+#define US_SOFTWARE_GOFAST
diff --git a/contrib/gcc/config/sparc/litecoff.h b/contrib/gcc/config/sparc/litecoff.h
index 91808f5..e31a0b4 100644
--- a/contrib/gcc/config/sparc/litecoff.h
+++ b/contrib/gcc/config/sparc/litecoff.h
@@ -1,28 +1,33 @@
-/* Definitions of target machine for GNU compiler, for SPARClite w/o FPU, COFF.
+/* Definitions of target machine for GCC, for SPARClite w/o FPU, COFF.
Copyright (C) 1994, 1996, 2000, 2002 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com).
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define BSS_SECTION_ASM_OP "\t.section\t\".bss\""
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dsparc -Dsparclite -Acpu=sparc -Amachine=sparc"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("sparc"); \
+ builtin_define_std ("sparclite"); \
+ } \
+ while (0)
/* Default to stabs in COFF. */
diff --git a/contrib/gcc/config/sparc/liteelf.h b/contrib/gcc/config/sparc/liteelf.h
index 9b6cbaa..49a2089 100644
--- a/contrib/gcc/config/sparc/liteelf.h
+++ b/contrib/gcc/config/sparc/liteelf.h
@@ -1,30 +1,34 @@
-/* Definitions of target machine for GNU compiler, for SPARClite w/o FPU.
+/* Definitions of target machine for GCC, for SPARClite w/o FPU, ELF.
Copyright (C) 1998, 1999 Free Software Foundation, Inc.
Contributed by Stan Cox (scox@cygnus.com).
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__sparc__ -D__sparclite__ -Acpu=sparc -Amachine=sparc"
+#undef TARGET_SUB_OS_CPP_BUILTINS
+#define TARGET_SUB_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__sparclite__"); \
+ } \
+ while (0)
/* Default to dwarf2 in ELF. */
-#define DWARF_DEBUGGING_INFO 1
#define DWARF2_DEBUGGING_INFO 1
#undef PREFERRED_DEBUGGING_TYPE
@@ -38,9 +42,8 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT MASK_APP_REGS
-/* US Software GOFAST library support. */
-#undef INIT_SUBTARGET_OPTABS
-#define INIT_SUBTARGET_OPTABS INIT_GOFAST_OPTABS
+/* Enable US Software GOFAST library support. */
+#define US_SOFTWARE_GOFAST
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "crti.o%s crtbegin.o%s"
diff --git a/contrib/gcc/config/sparc/netbsd-elf.h b/contrib/gcc/config/sparc/netbsd-elf.h
index 10788f2..bc92eb2 100644
--- a/contrib/gcc/config/sparc/netbsd-elf.h
+++ b/contrib/gcc/config/sparc/netbsd-elf.h
@@ -1,22 +1,22 @@
-/* Definitions of target machine for GNU compiler, for ELF on NetBSD/sparc
+/* Definitions of target machine for GCC, for ELF on NetBSD/sparc
and NetBSD/sparc64.
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
Contributed by Matthew Green (mrg@eterna.com.au).
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
@@ -26,9 +26,9 @@ Boston, MA 02111-1307, USA. */
NETBSD_OS_CPP_BUILTINS_ELF(); \
if (TARGET_ARCH64) \
{ \
- NETBSD_OS_CPP_BUILTINS_LP64(); \
builtin_define ("__sparc64__"); \
builtin_define ("__sparc_v9__"); \
+ builtin_define ("__sparcv9"); \
} \
else \
builtin_define ("__sparc"); \
@@ -40,9 +40,6 @@ Boston, MA 02111-1307, USA. */
#undef MD_EXEC_PREFIX
#undef MD_STARTFILE_PREFIX
-/* Make sure this is undefined. */
-#undef CPP_PREDEFINES
-
/* CPP defines used by all NetBSD targets. */
#undef CPP_SUBTARGET_SPEC
#define CPP_SUBTARGET_SPEC "%(netbsd_cpp_spec)"
@@ -69,13 +66,6 @@ Boston, MA 02111-1307, USA. */
#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. */
@@ -96,31 +86,18 @@ Boston, MA 02111-1307, USA. */
#define USER_LABEL_PREFIX ""
#undef ASM_SPEC
-#define ASM_SPEC "%{fpic:-K PIC} %{fPIC:-K PIC} %{V} %{v:%{!V:-V}} \
+#define ASM_SPEC "%{fpic|fPIC|fpie|fPIE:-K PIC} %{V} %{v:%{!V:-V}} \
%{mlittle-endian:-EL} \
%(asm_cpu) %(asm_arch) %(asm_relax)"
#undef STDC_0_IN_SYSTEM_HEADERS
/* Attempt to enable execute permissions on the stack. */
-#define TRANSFER_FROM_TRAMPOLINE NETBSD_ENABLE_EXECUTE_STACK
+#define ENABLE_EXECUTE_STACK NETBSD_ENABLE_EXECUTE_STACK
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (%s)", TARGET_NAME);
-/*
- * Clean up afterwards generic SPARC ELF configuration.
- */
-
-/* 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,
diff --git a/contrib/gcc/config/sparc/openbsd.h b/contrib/gcc/config/sparc/openbsd.h
index a4333df..e36f51e 100644
--- a/contrib/gcc/config/sparc/openbsd.h
+++ b/contrib/gcc/config/sparc/openbsd.h
@@ -1,29 +1,33 @@
/* Configuration file for sparc OpenBSD target.
- Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Get generic OpenBSD definitions. */
-#define OBSD_OLD_GAS
-#include <openbsd.h>
-
-/* Run-time target specifications. */
-#define CPP_PREDEFINES "-D__unix__ -D__sparc__ -D__OpenBSD__ -Asystem=unix -Asystem=OpenBSD -Acpu=sparc -Amachine=sparc"
+/* Target OS builtins. */
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__unix__"); \
+ builtin_define ("__OpenBSD__"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=OpenBSD"); \
+ } \
+ while (0)
/* Layout of source language data types */
@@ -58,8 +62,7 @@ Boston, MA 02111-1307, USA. */
/* Assembler format: exception region output. */
/* All configurations that don't use elf must be explicit about not using
- dwarf unwind information. egcs doesn't try too hard to check internal
- configuration files... */
+ dwarf unwind information. */
#define DWARF2_UNWIND_INFO 0
#undef ASM_PREFERRED_EH_DATA_FORMAT
diff --git a/contrib/gcc/config/sparc/openbsd64.h b/contrib/gcc/config/sparc/openbsd64.h
index 4dfe381..e13c886 100644
--- a/contrib/gcc/config/sparc/openbsd64.h
+++ b/contrib/gcc/config/sparc/openbsd64.h
@@ -30,9 +30,20 @@ Boston, MA 02111-1307, USA. */
#undef SPARC_DEFAULT_CMODEL
#define SPARC_DEFAULT_CMODEL CM_MEDMID
-/* Run-time target specifications. */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__unix__ -D__sparc__ -D__sparc64__ -D__sparcv9__ -D__sparc_v9__ -D__arch64__ -D__ELF__ -D__OpenBSD__ -Asystem(unix) -Asystem(OpenBSD) -Acpu(sparc) -Amachine(sparc)"
+/* Target OS builtins. */
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__unix__"); \
+ builtin_define ("__OpenBSD__"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=OpenBSD"); \
+ builtin_define ("__sparc64__"); \
+ builtin_define ("__sparcv9__"); \
+ builtin_define ("__sparc_v9__"); \
+ builtin_define ("__arch64__"); \
+ } \
+ while (0)
#undef CPP_SUBTARGET_SPEC
#define CPP_SUBTARGET_SPEC ""
@@ -42,7 +53,7 @@ Boston, MA 02111-1307, USA. */
#undef ASM_SPEC
#define ASM_SPEC "\
-%{v:-V} -s %{fpic:-K PIC} %{fPIC:-K PIC} \
+%{v:-V} -s %{fpic|fPIC|fpie|fPIE:-K PIC} \
%{mlittle-endian:-EL} \
%(asm_cpu) %(asm_arch) \
"
diff --git a/contrib/gcc/config/sparc/pbd.h b/contrib/gcc/config/sparc/pbd.h
index e7c01c0..e9344a0 100644
--- a/contrib/gcc/config/sparc/pbd.h
+++ b/contrib/gcc/config/sparc/pbd.h
@@ -2,28 +2,32 @@
version (using GAS and COFF (encapsulated is unacceptable) )
Copyright (C) 1990, 1996, 2000 Free Software Foundation, Inc.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
-/* Names to predefine in the preprocessor for this target machine. */
-
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dsparc -DUnicomPBD -Dunix -D__GCC_NEW_VARARGS__ -Asystem=unix -Acpu=sparc -Amachine=sparc"
+/* Target OS builtins. */
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("unix"); \
+ builtin_define_std ("UnicomPBD"); \
+ builtin_assert ("system=unix"); \
+ } \
+ while (0)
/* We want DBX format for use with gdb under COFF. */
@@ -116,18 +120,9 @@ Boston, MA 02111-1307, USA. */
This is suitable for output with `assemble_name'. */
#undef ASM_GENERATE_INTERNAL_LABEL
-
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
sprintf (LABEL, "*.%s%ld", PREFIX, (long)(NUM))
-
-/* This is how to output 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, ".%s%d:\n", PREFIX, NUM)
-
/* This is how to output an element of a case-vector that is relative. */
#undef ASM_OUTPUT_ADDR_DIFF_ELT
@@ -145,10 +140,8 @@ Boston, MA 02111-1307, USA. */
/* This is needed for SunOS 4.0, and should not hurt for 3.2
versions either. */
#undef ASM_OUTPUT_SOURCE_LINE
-#define ASM_OUTPUT_SOURCE_LINE(file, line) \
- { static int sym_lineno = 1; \
- fprintf (file, ".stabn 68,0,%d,.LM%d\n.LM%d:\n", \
- line, sym_lineno, sym_lineno); \
- sym_lineno += 1; }
+#define ASM_OUTPUT_SOURCE_LINE(file, line, counter) \
+ fprintf (file, ".stabn 68,0,%d,.LM%d\n.LM%d:\n", \
+ line, counter, counter)
#define ASM_INT_OP "\t.long "
diff --git a/contrib/gcc/config/sparc/rtemself.h b/contrib/gcc/config/sparc/rtemself.h
index 4f2cc66..ffb2a72 100644
--- a/contrib/gcc/config/sparc/rtemself.h
+++ b/contrib/gcc/config/sparc/rtemself.h
@@ -2,25 +2,30 @@
Copyright (C) 1996, 1997, 2000, 2002 Free Software Foundation, Inc.
Contributed by Joel Sherrill (joel@OARcorp.com).
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Specify predefined symbols in preprocessor. */
-
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dsparc -D__GCC_NEW_VARARGS__ -D__rtems__ \
- -D__USE_INIT_FINI__ -Asystem=rtems"
+/* Target OS builtins. */
+#define TARGET_SUB_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("sparc"); \
+ builtin_define ("__rtems__"); \
+ builtin_define ("__USE_INIT_FINI__"); \
+ builtin_assert ("system=rtems"); \
+ } \
+ while (0)
diff --git a/contrib/gcc/config/sparc/sol2-64.h b/contrib/gcc/config/sparc/sol2-64.h
index ccdc8f3..d53747a 100644
--- a/contrib/gcc/config/sparc/sol2-64.h
+++ b/contrib/gcc/config/sparc/sol2-64.h
@@ -1,7 +1,16 @@
-/* Definitions of target machine for GNU compiler, for bi-arch SPARC
+/* Definitions of target machine for GCC, for bi-arch SPARC
running Solaris 2, defaulting to 64-bit code generation. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
(MASK_V9 + MASK_PTR64 + MASK_64BIT /* + MASK_HARD_QUAD */ + \
MASK_STACK_BIAS + MASK_FPU + MASK_LONG_DOUBLE_128)
+
+/* Target OS builtins. */
+#undef TARGET_SUB_OS_CPP_BUILTINS
+#define TARGET_SUB_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("sparc"); \
+ } \
+ while (0)
diff --git a/contrib/gcc/config/sparc/sol2-bi.h b/contrib/gcc/config/sparc/sol2-bi.h
index 3f9416d..80ec1da 100644
--- a/contrib/gcc/config/sparc/sol2-bi.h
+++ b/contrib/gcc/config/sparc/sol2-bi.h
@@ -1,4 +1,4 @@
-/* Definitions of target machine for GNU compiler, for bi-arch SPARC
+/* Definitions of target machine for GCC, for bi-arch SPARC
running Solaris 2 using the system assembler and linker. */
/* The default code model. */
@@ -18,6 +18,7 @@
#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 ""
@@ -27,6 +28,15 @@
#define ASM_CPU64_DEFAULT_SPEC AS_SPARC64_FLAG "a"
#endif
+#if TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc3
+#undef CPP_CPU64_DEFAULT_SPEC
+#define CPP_CPU64_DEFAULT_SPEC ""
+#undef ASM_CPU32_DEFAULT_SPEC
+#define ASM_CPU32_DEFAULT_SPEC "-xarch=v8plusb"
+#undef ASM_CPU64_DEFAULT_SPEC
+#define ASM_CPU64_DEFAULT_SPEC AS_SPARC64_FLAG "b"
+#endif
+
#if DEFAULT_ARCH32_P
#define DEF_ARCH32_SPEC(__str) "%{!m64:" __str "}"
#define DEF_ARCH64_SPEC(__str) "%{m64:" __str "}"
@@ -45,15 +55,16 @@
%{mcpu=sparclite|mcpu-f930|mcpu=f934:-D__sparclite__} \
%{mcpu=v8:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
%{mcpu=supersparc:-D__supersparc__ " DEF_ARCH32_SPEC("-D__sparcv8") "} \
-%{mcpu=v9|mcpu=ultrasparc:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
+%{mcpu=v9|mcpu=ultrasparc|mcpu=ultrasparc3:" 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=ultrasparc:" DEF_ARCH32_SPEC("-xarch=v8plusa") DEF_ARCH64_SPEC(AS_SPARC64_FLAG "a") "} \
+%{mcpu=ultrasparc3:" DEF_ARCH32_SPEC("-xarch=v8plusb") DEF_ARCH64_SPEC(AS_SPARC64_FLAG "b") "} \
+%{!mcpu=ultrasparc3:%{!mcpu=ultrasparc:%{!mcpu=v9:%{mcpu*:" DEF_ARCH32_SPEC("-xarch=v8") DEF_ARCH64_SPEC(AS_SPARC64_FLAG) "}}}} \
%{!mcpu*:%(asm_cpu_default)} \
"
@@ -98,11 +109,9 @@
#define WINT_TYPE_SIZE 32
#undef CPP_ARCH32_SPEC
-#define CPP_ARCH32_SPEC "\
--D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc"
+#define CPP_ARCH32_SPEC ""
#undef CPP_ARCH64_SPEC
-#define CPP_ARCH64_SPEC "\
--D__arch64__ -Acpu=sparc64 -Amachine=sparcv9 -D__sparcv9"
+#define CPP_ARCH64_SPEC "-D__arch64__ -D__sparcv9"
#undef CPP_ARCH_SPEC
#define CPP_ARCH_SPEC "\
@@ -135,7 +144,7 @@
* This should be the same as in sol2.h, except with "/sparcv9"
* appended to the paths and /usr/ccs/lib is no longer necessary
*/
-#define LINK_ARCH64_SPEC \
+#define LINK_ARCH64_SPEC_BASE \
"%{mcmodel=medlow:-M /usr/lib/ld/sparcv9/map.below4G} \
%{G:-G} \
%{YP,*} \
@@ -143,17 +152,35 @@
%{compat-bsd: \
%{!YP,*:%{p|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} \
+ -R /usr/ucblib/sparcv9} \
%{!compat-bsd: \
%{!YP,*:%{p|pg:-Y P,/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
%{!p:%{!pg:-Y P,/usr/lib/sparcv9}}}}"
+#define LINK_ARCH64_SPEC LINK_ARCH64_SPEC_BASE
+
#undef LINK_ARCH_SPEC
+#if DISABLE_MULTILIB
+#if DEFAULT_ARCH32_P
#define LINK_ARCH_SPEC "\
%{m32:%(link_arch32)} \
+%{m64:%edoes not support multilib} \
+%{!m32:%{!m64:%(link_arch_default)}} \
+"
+#else
+#define LINK_ARCH_SPEC "\
+%{m32:%edoes not support multilib} \
%{m64:%(link_arch64)} \
%{!m32:%{!m64:%(link_arch_default)}} \
"
+#endif
+#else
+#define LINK_ARCH_SPEC "\
+%{m32:%(link_arch32)} \
+%{m64:%(link_arch64)} \
+%{!m32:%{!m64:%(link_arch_default)}} \
+"
+#endif
#define LINK_ARCH_DEFAULT_SPEC \
(DEFAULT_ARCH32_P ? LINK_ARCH32_SPEC : LINK_ARCH64_SPEC)
@@ -183,23 +210,36 @@
"
#endif
+/* Support for a compile-time default CPU, et cetera. The rules are:
+ --with-cpu is ignored if -mcpu is specified.
+ --with-tune is ignored if -mtune is specified.
+ --with-float is ignored if -mhard-float, -msoft-float, -mfpu, or -mno-fpu
+ are specified.
+ In the SPARC_BI_ARCH compiler we cannot pass %{!mcpu=*:-mcpu=%(VALUE)}
+ here, otherwise say -mcpu=v7 would be passed even when -m64.
+ CC1_SPEC above takes care of this instead. */
+#undef OPTION_DEFAULT_SPECS
+#if DEFAULT_ARCH32_P
+#define OPTION_DEFAULT_SPECS \
+ {"cpu", "%{!m64:%{!mcpu=*:-mcpu=%(VALUE)}}" }, \
+ {"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \
+ {"float", "%{!msoft-float:%{!mhard-float:%{!fpu:%{!no-fpu:-m%(VALUE)-float}}}}" }
+#else
+#define OPTION_DEFAULT_SPECS \
+ {"cpu", "%{!m32:%{!mcpu=*:-mcpu=%(VALUE)}}" }, \
+ {"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \
+ {"float", "%{!msoft-float:%{!mhard-float:%{!fpu:%{!no-fpu:-m%(VALUE)-float}}}}" }
+#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)
+#define PREFERRED_DEBUGGING_TYPE 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
+# define ASM_DEBUG_SPEC "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}"
#endif
diff --git a/contrib/gcc/config/sparc/sol2-gas-bi.h b/contrib/gcc/config/sparc/sol2-gas-bi.h
index 0b6cb61..88b3954 100644
--- a/contrib/gcc/config/sparc/sol2-gas-bi.h
+++ b/contrib/gcc/config/sparc/sol2-gas-bi.h
@@ -1,5 +1,5 @@
-/* Definitions of target machine for GNU compiler, for bi-arch SPARC
+/* Definitions of target machine for GCC, for bi-arch SPARC
running Solaris 2 using the GNU assembler. */
-#undef AS_SPARC64_FLAG
-#define AS_SPARC64_FLAG "-64 -Av9"
+#undef AS_SPARC64_FLAG
+#define AS_SPARC64_FLAG "-TSO -64 -Av9"
diff --git a/contrib/gcc/config/sparc/sol2-gld-bi.h b/contrib/gcc/config/sparc/sol2-gld-bi.h
index 81a1ff2..aa9a40b 100644
--- a/contrib/gcc/config/sparc/sol2-gld-bi.h
+++ b/contrib/gcc/config/sparc/sol2-gld-bi.h
@@ -1,9 +1,34 @@
-/* Definitions of target machine for GNU compiler, for bi-arch SPARC
+/* Definitions of target machine for GCC, for bi-arch SPARC
running Solaris 2 using the GNU linker. */
+#undef LINK_ARCH32_SPEC
+#define LINK_ARCH32_SPEC \
+ LINK_ARCH32_SPEC_BASE "%{!static: -rpath-link %R/usr/lib}"
+
+#undef LINK_ARCH64_SPEC
+#define LINK_ARCH64_SPEC \
+ LINK_ARCH64_SPEC_BASE "%{!static: -rpath-link %R/usr/lib/sparcv9}"
+
#undef LINK_ARCH_SPEC
+#if DISABLE_MULTILIB
+#if DEFAULT_ARCH32_P
#define LINK_ARCH_SPEC "\
%{m32:-m elf32_sparc %(link_arch32)} \
+%{m64:%edoes not support multilib} \
+%{!m32:%{!m64:%(link_arch_default)}} \
+"
+#else
+#define LINK_ARCH_SPEC "\
+%{m32:%edoes not support multilib} \
%{m64:-m elf64_sparc %(link_arch64)} \
%{!m32:%{!m64:%(link_arch_default)}} \
"
+#endif
+#else
+#define LINK_ARCH_SPEC "\
+%{m32:-m elf32_sparc %(link_arch32)} \
+%{m64:-m elf64_sparc %(link_arch64)} \
+%{!m32:%{!m64:%(link_arch_default)}} \
+"
+#endif
+
diff --git a/contrib/gcc/config/sparc/sol2-gld.h b/contrib/gcc/config/sparc/sol2-gld.h
index 76e034e..eb422cb 100644
--- a/contrib/gcc/config/sparc/sol2-gld.h
+++ b/contrib/gcc/config/sparc/sol2-gld.h
@@ -1,6 +1,9 @@
-/* Definitions of target machine for GNU compiler, for SPARC running Solaris 2
+/* Definitions of target machine for GCC, 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
+
+#undef SUPPORTS_INIT_PRIORITY
+#define SUPPORTS_INIT_PRIORITY 1
diff --git a/contrib/gcc/config/sparc/sol2.h b/contrib/gcc/config/sparc/sol2.h
index 3026e40..cbf914e 100644
--- a/contrib/gcc/config/sparc/sol2.h
+++ b/contrib/gcc/config/sparc/sol2.h
@@ -1,31 +1,28 @@
-/* Definitions of target machine for GNU compiler, for SPARC running Solaris 2
- Copyright 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+/* Definitions of target machine for GCC, for SPARC running Solaris 2
+ Copyright 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004
Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@netcom.com).
Additional changes by David V. Henkel-Wallace (gumby@cygnus.com).
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Supposedly the same as vanilla sparc svr4, except for the stuff below: */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dsparc"
-
/* This is here rather than in sparc.h because it's not known what
other assemblers will accept. */
@@ -39,11 +36,16 @@ Boston, MA 02111-1307, USA. */
#define ASM_CPU_DEFAULT_SPEC "-xarch=v8plusa"
#endif
+#if TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc3
+#undef ASM_CPU_DEFAULT_SPEC
+#define ASM_CPU_DEFAULT_SPEC "-xarch=v8plusb"
+#endif
+
#undef ASM_CPU_SPEC
#define ASM_CPU_SPEC "\
-%{mcpu=v8plus:-xarch=v8plus} \
%{mcpu=v9:-xarch=v8plus} \
%{mcpu=ultrasparc:-xarch=v8plusa} \
+%{mcpu=ultrasparc3:-xarch=v8plusb} \
%{!mcpu*:%(asm_cpu_default)} \
"
@@ -63,18 +65,11 @@ Boston, MA 02111-1307, USA. */
/* The Solaris 2 assembler uses .skip, not .zero, so put this back. */
#undef ASM_OUTPUT_SKIP
#define ASM_OUTPUT_SKIP(FILE,SIZE) \
- fprintf (FILE, "\t.skip %u\n", (SIZE))
+ fprintf (FILE, "\t.skip %u\n", (int)(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. */
-
-#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. */
@@ -91,6 +86,33 @@ Boston, MA 02111-1307, USA. */
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
sprintf ((LABEL), "*.L%s%ld", (PREFIX), (long)(NUM))
+/* The native TLS-enabled assembler requires the directive #tls_object
+ to be put on objects in TLS sections (as of v7.1). This is not
+ required by the GNU assembler but supported on SPARC. */
+#undef ASM_DECLARE_OBJECT_NAME
+#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
+ do \
+ { \
+ HOST_WIDE_INT size; \
+ \
+ if (DECL_THREAD_LOCAL (DECL)) \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "tls_object"); \
+ else \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
+ \
+ size_directive_output = 0; \
+ if (!flag_inhibit_size_directive \
+ && (DECL) && DECL_SIZE (DECL)) \
+ { \
+ size_directive_output = 1; \
+ size = int_size_in_bytes (TREE_TYPE (DECL)); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size); \
+ } \
+ \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
+ } \
+ while (0)
+
#undef ENDFILE_SPEC
@@ -108,6 +130,10 @@ Boston, MA 02111-1307, USA. */
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
((flag_pic || GLOBAL) ? DW_EH_PE_aligned : DW_EH_PE_absptr)
#endif
+
+/* The Solaris linker doesn't understand constructor priorities. */
+#undef SUPPORTS_INIT_PRIORITY
+#define SUPPORTS_INIT_PRIORITY 0
/* ??? This does not work in SunOS 4.x, so it is not enabled in sparc.h.
Instead, it is enabled here, because it does work under Solaris. */
@@ -118,28 +144,20 @@ Boston, MA 02111-1307, USA. */
/* But indicate that it isn't supported by the hardware. */
#define WIDEST_HARDWARE_FP_SIZE 64
-#define MULDI3_LIBCALL "__mul64"
-#define DIVDI3_LIBCALL "__div64"
-#define UDIVDI3_LIBCALL "__udiv64"
-#define MODDI3_LIBCALL "__rem64"
-#define UMODDI3_LIBCALL "__urem64"
-
/* Solaris's _Qp_* library routine implementation clobbers the output
memory before the inputs are fully consumed. */
#undef TARGET_BUGGY_QP_LIB
#define TARGET_BUGGY_QP_LIB 1
-#undef INIT_SUBTARGET_OPTABS
-#define INIT_SUBTARGET_OPTABS \
- fixsfdi_libfunc \
- = init_one_libfunc (TARGET_ARCH64 ? "__ftol" : "__ftoll"); \
- fixunssfdi_libfunc \
- = init_one_libfunc (TARGET_ARCH64 ? "__ftoul" : "__ftoull"); \
- fixdfdi_libfunc \
- = init_one_libfunc (TARGET_ARCH64 ? "__dtol" : "__dtoll"); \
- fixunsdfdi_libfunc \
- = init_one_libfunc (TARGET_ARCH64 ? "__dtoul" : "__dtoull")
+#undef SUN_CONVERSION_LIBFUNCS
+#define SUN_CONVERSION_LIBFUNCS 1
+
+#undef DITF_CONVERSION_LIBFUNCS
+#define DITF_CONVERSION_LIBFUNCS 1
+
+#undef SUN_INTEGER_MULTIPLY_64
+#define SUN_INTEGER_MULTIPLY_64 1
/* Solaris allows 64 bit out and global registers in 32 bit mode.
sparc_override_options will disable V8+ if not generating V9 code. */
diff --git a/contrib/gcc/config/sparc/sol26-sld.h b/contrib/gcc/config/sparc/sol26-sld.h
index 74b5433..2e7fed9 100644
--- a/contrib/gcc/config/sparc/sol26-sld.h
+++ b/contrib/gcc/config/sparc/sol26-sld.h
@@ -1,6 +1,5 @@
-/* Up through Solaris 2.6, the system linker does not work with DWARF
- or DWARF2, since it does not have working support for relocations
- to unaligned data. */
+/* Up through Solaris 2.6, the system linker does not work with DWARF2
+ since it does not have working support for relocations to unaligned
+ data. */
-#undef DWARF_DEBUGGING_INFO
#undef DWARF2_DEBUGGING_INFO
diff --git a/contrib/gcc/config/sparc/sp64-aout.h b/contrib/gcc/config/sparc/sp64-aout.h
index 1af9dea..376cfa8 100644
--- a/contrib/gcc/config/sparc/sp64-aout.h
+++ b/contrib/gcc/config/sparc/sp64-aout.h
@@ -1,21 +1,21 @@
-/* Definitions of target machine for GNU compiler, for SPARC64, a.out.
+/* Definitions of target machine for GCC, for SPARC64, a.out.
Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc.
Contributed by Doug Evans, dje@cygnus.com.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
diff --git a/contrib/gcc/config/sparc/sp64-elf.h b/contrib/gcc/config/sparc/sp64-elf.h
index 18187dc..650c3ff 100644
--- a/contrib/gcc/config/sparc/sp64-elf.h
+++ b/contrib/gcc/config/sparc/sp64-elf.h
@@ -1,22 +1,22 @@
-/* Definitions of target machine for GNU compiler, for SPARC64, ELF.
+/* Definitions of target machine for GCC, for SPARC64, ELF.
Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000
Free Software Foundation, Inc.
Contributed by Doug Evans, dje@cygnus.com.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
@@ -38,8 +38,14 @@ Boston, MA 02111-1307, USA. */
#undef SPARC_DEFAULT_CMODEL
#define SPARC_DEFAULT_CMODEL CM_EMBMEDANY
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dsparc -D__ELF__ -Acpu=sparc -Amachine=sparc"
+/* Target OS builtins for config/sol.h. */
+#undef TARGET_SUB_OS_CPP_BUILTINS
+#define TARGET_SUB_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("sparc"); \
+ } \
+ while (0)
/* __svr4__ is used by the C library (FIXME) */
#undef CPP_SUBTARGET_SPEC
@@ -50,7 +56,7 @@ Boston, MA 02111-1307, USA. */
#undef ASM_SPEC
#define ASM_SPEC "\
-%{v:-V} -s %{fpic:-K PIC} %{fPIC:-K PIC} \
+%{v:-V} -s %{fpic|fPIC|fpie|fPIE:-K PIC} \
%{mlittle-endian:-EL} \
%(asm_cpu) %(asm_arch) \
"
diff --git a/contrib/gcc/config/sparc/sp86x-elf.h b/contrib/gcc/config/sparc/sp86x-elf.h
index cb7e8c3..593400d 100644
--- a/contrib/gcc/config/sparc/sp86x-elf.h
+++ b/contrib/gcc/config/sparc/sp86x-elf.h
@@ -1,30 +1,34 @@
-/* Definitions of target machine for GNU compiler, for sparclite 86x w/o FPU.
+/* Definitions of target machine for GCC, for sparclite 86x w/o FPU.
Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
Contributed by Stan Cox (scox@cygnus.com).
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__sparc__ -D__sparclite86x__ -Acpu=sparc -Amachine=sparc"
+#undef TARGET_SUB_OS_CPP_BUILTINS
+#define TARGET_SUB_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__sparclite86x__"); \
+ } \
+ while (0)
/* Default to dwarf2 in ELF. */
-#define DWARF_DEBUGGING_INFO 1
#define DWARF2_DEBUGGING_INFO 1
#undef PREFERRED_DEBUGGING_TYPE
@@ -41,9 +45,8 @@ Boston, MA 02111-1307, USA. */
#undef ASM_SPEC
#define ASM_SPEC "%{v:-V} %{mlittle-endian-data:--little-endian-data} %(asm_cpu)"
-/* US Software GOFAST library support. */
-#undef INIT_SUBTARGET_OPTABS
-#define INIT_SUBTARGET_OPTABS INIT_GOFAST_OPTABS
+/* Enable US Software GOFAST library support. */
+#define US_SOFTWARE_GOFAST
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "crti.o%s crtbegin.o%s"
diff --git a/contrib/gcc/config/sparc/sparc-modes.def b/contrib/gcc/config/sparc/sparc-modes.def
index 3ebf9c8..ea2a99d 100644
--- a/contrib/gcc/config/sparc/sparc-modes.def
+++ b/contrib/gcc/config/sparc/sparc-modes.def
@@ -1,26 +1,29 @@
-/* Definitions of target machine for GNU compiler, for Sun SPARC.
+/* Definitions of target machine for GCC, for Sun SPARC.
Copyright (C) 2002 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com).
64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
at Cygnus Support.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+/* 128-bit floating point */
+FLOAT_MODE (TF, 16, ieee_quad_format);
+
/* Add any extra modes needed to represent the condition code.
On the SPARC, we have a "no-overflow" mode which is used when an add or
@@ -34,9 +37,8 @@ Boston, MA 02111-1307, USA. */
CCXmode and CCX_NOOVmode are only used by v9. */
-CC (CCX)
-CC (CC_NOOV)
-CC (CCX_NOOV)
-CC (CCFP)
-CC (CCFPE)
-
+CC_MODE (CCX);
+CC_MODE (CC_NOOV);
+CC_MODE (CCX_NOOV);
+CC_MODE (CCFP);
+CC_MODE (CCFPE);
diff --git a/contrib/gcc/config/sparc/sparc-protos.h b/contrib/gcc/config/sparc/sparc-protos.h
index 0aa6e58..3216f38 100644
--- a/contrib/gcc/config/sparc/sparc-protos.h
+++ b/contrib/gcc/config/sparc/sparc-protos.h
@@ -1,23 +1,23 @@
-/* Prototypes of target machine for GNU compiler, for Sun SPARC.
- Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+/* Prototypes of target machine for SPARC.
+ Copyright (C) 1999, 2000, 2003 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com).
- 64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
+ 64-bit SPARC-V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
at Cygnus Support.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
@@ -27,100 +27,101 @@ Boston, MA 02111-1307, USA. */
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 *,
- enum machine_mode, tree, int));
-extern struct rtx_def *function_arg PARAMS ((const CUMULATIVE_ARGS *,
- enum machine_mode,
- tree, int, int));
-extern int function_arg_partial_nregs PARAMS ((const CUMULATIVE_ARGS *,
- enum machine_mode,
- tree, int));
-extern int function_arg_pass_by_reference PARAMS ((const CUMULATIVE_ARGS *,
- enum machine_mode,
- tree, int));
-extern struct rtx_def *sparc_builtin_saveregs PARAMS ((void));
+extern struct rtx_def *function_value (tree, enum machine_mode, int);
+extern void function_arg_advance (CUMULATIVE_ARGS *,
+ enum machine_mode, tree, int);
+extern struct rtx_def *function_arg (const CUMULATIVE_ARGS *,
+ enum machine_mode, tree, int, int);
+extern int function_arg_partial_nregs (const CUMULATIVE_ARGS *,
+ enum machine_mode, tree, int);
+extern int function_arg_pass_by_reference (const CUMULATIVE_ARGS *,
+ enum machine_mode, tree, int);
+extern struct rtx_def *sparc_builtin_saveregs (void);
#ifdef RTX_CODE
-extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx, int));
-extern void sparc_va_start PARAMS ((tree, rtx));
+extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
+extern void sparc_va_start (tree, rtx);
#endif
-extern struct rtx_def *sparc_va_arg PARAMS ((tree, tree));
-extern unsigned long sparc_type_code PARAMS ((tree));
+extern struct rtx_def *sparc_va_arg (tree, tree);
+extern unsigned long sparc_type_code (tree);
#ifdef ARGS_SIZE_RTX
/* expr.h defines ARGS_SIZE_RTX and `enum direction' */
-extern enum direction function_arg_padding PARAMS ((enum machine_mode, tree));
+extern enum direction function_arg_padding (enum machine_mode, tree);
#endif /* ARGS_SIZE_RTX */
#endif /* TREE_CODE */
-extern void load_pic_register PARAMS ((void));
-extern void order_regs_for_local_alloc PARAMS ((void));
-extern int compute_frame_size PARAMS ((int, int));
-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_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 *));
-extern void sparc_flat_save_restore PARAMS ((FILE *, const char *,
- unsigned int, unsigned long,
- unsigned long, const char *,
- const char *, unsigned long));
+extern void load_pic_register (void);
+extern void order_regs_for_local_alloc (void);
+extern HOST_WIDE_INT compute_frame_size (HOST_WIDE_INT, int);
+extern int check_pic (int);
+extern int short_branch (int, int);
+extern int sparc_flat_epilogue_delay_slots (void);
+extern HOST_WIDE_INT sparc_flat_compute_frame_size (HOST_WIDE_INT);
+extern void sparc_profile_hook (int);
+extern void sparc_override_options (void);
+extern int leaf_return_peephole_ok (void);
+extern void sparc_output_scratch_registers (FILE *);
#ifdef RTX_CODE
-extern enum machine_mode select_cc_mode PARAMS ((enum rtx_code, rtx, rtx));
+extern enum machine_mode select_cc_mode (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 *));
+extern rtx gen_compare_reg (enum rtx_code code, rtx, rtx);
+extern void sparc_emit_float_lib_cmp (rtx, rtx, enum rtx_code);
+extern void sparc_emit_floatunsdi (rtx [2]);
+extern void emit_tfmode_binop (enum rtx_code, rtx *);
+extern void emit_tfmode_unop (enum rtx_code, rtx *);
+extern void emit_tfmode_cvt (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));
-extern void sparc64_initialize_trampoline PARAMS ((rtx, rtx, rtx));
-extern rtx legitimize_pic_address PARAMS ((rtx, enum machine_mode, rtx));
-extern void sparc_defer_case_vector PARAMS ((rtx, rtx, int));
-extern void sparc_emit_set_const32 PARAMS ((rtx, rtx));
-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, rtx, int, int, int, int, rtx));
-extern const char *output_sibcall PARAMS ((rtx, 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));
-extern int arith_double_4096_operand PARAMS ((rtx, enum machine_mode));
-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_sibcall_delay PARAMS ((rtx));
-extern int emit_move_sequence PARAMS ((rtx, enum machine_mode));
-extern int fp_sethi_p PARAMS ((rtx));
-extern int fp_mov_p PARAMS ((rtx));
-extern int fp_high_losum_p PARAMS ((rtx));
-extern int mem_min_alignment PARAMS ((rtx, int));
-extern int pic_address_needs_scratch PARAMS ((rtx));
-extern int reg_unused_after PARAMS ((rtx, rtx));
-extern int register_ok_for_ldd PARAMS ((rtx));
-extern int registers_ok_for_ldd_peep PARAMS ((rtx, rtx));
-extern int sparc_flat_eligible_for_epilogue_delay PARAMS ((rtx, int));
-extern int v9_regcmp_p PARAMS ((enum rtx_code));
-extern char *sparc_v8plus_shift PARAMS ((rtx *, rtx, const char *));
+extern int gen_v9_scc (enum rtx_code, rtx *);
+extern void sparc_initialize_trampoline (rtx, rtx, rtx);
+extern void sparc64_initialize_trampoline (rtx, rtx, rtx);
+extern bool legitimate_constant_p (rtx);
+extern bool constant_address_p (rtx);
+extern bool legitimate_pic_operand_p (rtx);
+extern int legitimate_address_p (enum machine_mode, rtx, int);
+extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
+extern rtx legitimize_tls_address (rtx);
+extern rtx legitimize_address (rtx, rtx, enum machine_mode);
+extern void sparc_defer_case_vector (rtx, rtx, int);
+extern void sparc_emit_set_const32 (rtx, rtx);
+extern void sparc_emit_set_const64 (rtx, rtx);
+extern void sparc_emit_set_symbolic_const64 (rtx, rtx, rtx);
+extern int sparc_splitdi_legitimate (rtx, rtx);
+extern int sparc_absnegfloat_split_legitimate (rtx, rtx);
+extern const char *output_ubranch (rtx, int, rtx);
+extern char *output_cbranch (rtx, rtx, int, int, int, int, rtx);
+extern const char *output_sibcall (rtx, rtx);
+extern char *output_v9branch (rtx, rtx, int, int, int, int, int, rtx);
+extern void emit_v9_brxx_insn (enum rtx_code, rtx, rtx);
+extern void print_operand (FILE *, rtx, int);
+extern int mems_ok_for_ldd_peep (rtx, rtx, rtx);
+extern int arith_double_4096_operand (rtx, enum machine_mode);
+extern int arith_4096_operand (rtx, enum machine_mode);
+extern int zero_operand (rtx, enum machine_mode);
+extern int fp_zero_operand (rtx, enum machine_mode);
+extern int reg_or_0_operand (rtx, enum machine_mode);
+extern int tls_symbolic_operand (rtx);
+extern int empty_delay_slot (rtx);
+extern int eligible_for_epilogue_delay (rtx, int);
+extern int eligible_for_sibcall_delay (rtx);
+extern int tls_call_delay (rtx);
+extern int emit_move_sequence (rtx, enum machine_mode);
+extern int fp_sethi_p (rtx);
+extern int fp_mov_p (rtx);
+extern int fp_high_losum_p (rtx);
+extern int mem_min_alignment (rtx, int);
+extern int pic_address_needs_scratch (rtx);
+extern int reg_unused_after (rtx, rtx);
+extern int register_ok_for_ldd (rtx);
+extern int registers_ok_for_ldd_peep (rtx, rtx);
+extern int sparc_flat_eligible_for_epilogue_delay (rtx, int);
+extern int v9_regcmp_p (enum rtx_code);
+extern char *sparc_v8plus_shift (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 rtx gen_df_reg PARAMS ((rtx, int));
-extern int sparc_extra_constraint_check PARAMS ((rtx, int, int));
-extern int sparc_rtx_costs PARAMS ((rtx, enum rtx_code, enum rtx_code));
+extern int sparc_check_64 (rtx, rtx);
+extern rtx gen_df_reg (rtx, int);
+extern int sparc_extra_constraint_check (rtx, int, int);
+extern void sparc_output_dwarf_dtprel (FILE*, int, rtx);
#endif /* RTX_CODE */
#endif /* __SPARC_PROTOS_H__ */
diff --git a/contrib/gcc/config/sparc/sparc.c b/contrib/gcc/config/sparc/sparc.c
index 79022b4..c959370 100644
--- a/contrib/gcc/config/sparc/sparc.c
+++ b/contrib/gcc/config/sparc/sparc.c
@@ -1,29 +1,31 @@
-/* Subroutines for insn-output.c for Sun SPARC.
+/* Subroutines for insn-output.c for SPARC.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
- 64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
+ 64-bit SPARC-V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
at Cygnus Support.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "regs.h"
@@ -37,7 +39,6 @@ Boston, MA 02111-1307, USA. */
#include "function.h"
#include "expr.h"
#include "optabs.h"
-#include "libfuncs.h"
#include "recog.h"
#include "toplev.h"
#include "ggc.h"
@@ -45,6 +46,7 @@ Boston, MA 02111-1307, USA. */
#include "debug.h"
#include "target.h"
#include "target-def.h"
+#include "cfglayout.h"
/* 1 if the caller has placed an "unimp" insn immediately after the call.
This is used in v8 code when calling a function that returns a structure.
@@ -65,8 +67,8 @@ Boston, MA 02111-1307, USA. */
scheduling (to see what can go in a delay slot).
APPARENT_FSIZE is the size of the stack less the register save area and less
the outgoing argument area. It is used when saving call preserved regs. */
-static int apparent_fsize;
-static int actual_fsize;
+static HOST_WIDE_INT apparent_fsize;
+static HOST_WIDE_INT actual_fsize;
/* Number of live general or floating point registers needed to be
saved (as 4-byte quantities). */
@@ -117,67 +119,81 @@ char sparc_leaf_regs[] =
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1};
+struct machine_function GTY(())
+{
+ /* Some local-dynamic TLS symbol name. */
+ const char *some_ld_name;
+};
+
/* Name of where we pretend to think the frame pointer points.
Normally, this is "%fp", but if we are in a leaf procedure,
this is "%sp+something". We record "something" separately as it may be
too big for reg+constant addressing. */
static const char *frame_base_name;
-static int frame_base_offset;
-
-static void sparc_init_modes PARAMS ((void));
-static int save_regs PARAMS ((FILE *, int, int, const char *,
- int, int, int));
-static int restore_regs PARAMS ((FILE *, int, int, const char *, int, int));
-static void build_big_number PARAMS ((FILE *, int, const char *));
-static int function_arg_slotno PARAMS ((const CUMULATIVE_ARGS *,
- enum machine_mode, tree, int, int,
- int *, int *));
-
-static int supersparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));
-static int hypersparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));
-
-static void sparc_output_addr_vec PARAMS ((rtx));
-static void sparc_output_addr_diff_vec PARAMS ((rtx));
-static void sparc_output_deferred_case_vectors PARAMS ((void));
-static int check_return_regs PARAMS ((rtx));
-static int epilogue_renumber PARAMS ((rtx *, int));
-static bool sparc_assemble_integer PARAMS ((rtx, unsigned int, int));
-static int set_extends PARAMS ((rtx));
-static void output_restore_regs PARAMS ((FILE *, int));
-static void sparc_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
-static void sparc_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
-static void sparc_flat_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
-static void sparc_flat_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
-static void sparc_nonflat_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT,
- int));
-static void sparc_nonflat_function_prologue PARAMS ((FILE *, HOST_WIDE_INT,
- int));
+static HOST_WIDE_INT frame_base_offset;
+
+static void sparc_init_modes (void);
+static int save_regs (FILE *, int, int, const char *, int, int, HOST_WIDE_INT);
+static int restore_regs (FILE *, int, int, const char *, int, int);
+static void build_big_number (FILE *, HOST_WIDE_INT, const char *);
+static void scan_record_type (tree, int *, int *, int *);
+static int function_arg_slotno (const CUMULATIVE_ARGS *, enum machine_mode,
+ tree, int, int, int *, int *);
+
+static int supersparc_adjust_cost (rtx, rtx, rtx, int);
+static int hypersparc_adjust_cost (rtx, rtx, rtx, int);
+
+static void sparc_output_addr_vec (rtx);
+static void sparc_output_addr_diff_vec (rtx);
+static void sparc_output_deferred_case_vectors (void);
+static int check_return_regs (rtx);
+static int epilogue_renumber (rtx *, int);
+static bool sparc_assemble_integer (rtx, unsigned int, int);
+static int set_extends (rtx);
+static void output_restore_regs (FILE *, int);
+static void sparc_output_function_prologue (FILE *, HOST_WIDE_INT);
+static void sparc_output_function_epilogue (FILE *, HOST_WIDE_INT);
+static void sparc_flat_function_epilogue (FILE *, HOST_WIDE_INT);
+static void sparc_flat_function_prologue (FILE *, HOST_WIDE_INT);
+static void sparc_flat_save_restore (FILE *, const char *, int,
+ unsigned long, unsigned long,
+ const char *, const char *,
+ HOST_WIDE_INT);
+static void sparc_nonflat_function_epilogue (FILE *, HOST_WIDE_INT, int);
+static void sparc_nonflat_function_prologue (FILE *, HOST_WIDE_INT, int);
#ifdef OBJECT_FORMAT_ELF
-static void sparc_elf_asm_named_section PARAMS ((const char *, unsigned int));
+static void sparc_elf_asm_named_section (const char *, unsigned int);
#endif
-static void sparc_aout_select_section PARAMS ((tree, int,
- unsigned HOST_WIDE_INT))
+static void sparc_aout_select_section (tree, int, unsigned HOST_WIDE_INT)
ATTRIBUTE_UNUSED;
-static void sparc_aout_select_rtx_section PARAMS ((enum machine_mode, rtx,
- unsigned HOST_WIDE_INT))
+static void sparc_aout_select_rtx_section (enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT)
ATTRIBUTE_UNUSED;
-static int sparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));
-static int sparc_issue_rate PARAMS ((void));
-static void sparc_sched_init PARAMS ((FILE *, int, int));
-static int sparc_use_dfa_pipeline_interface PARAMS ((void));
-static int sparc_use_sched_lookahead PARAMS ((void));
-
-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 *));
-
-static void sparc_encode_section_info PARAMS ((tree, int));
-static void sparc_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
- HOST_WIDE_INT, tree));
+static int sparc_adjust_cost (rtx, rtx, rtx, int);
+static int sparc_issue_rate (void);
+static void sparc_sched_init (FILE *, int, int);
+static int sparc_use_dfa_pipeline_interface (void);
+static int sparc_use_sched_lookahead (void);
+
+static void emit_soft_tfmode_libcall (const char *, int, rtx *);
+static void emit_soft_tfmode_binop (enum rtx_code, rtx *);
+static void emit_soft_tfmode_unop (enum rtx_code, rtx *);
+static void emit_soft_tfmode_cvt (enum rtx_code, rtx *);
+static void emit_hard_tfmode_operation (enum rtx_code, rtx *);
+
+static bool sparc_function_ok_for_sibcall (tree, tree);
+static void sparc_init_libfuncs (void);
+static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
+ HOST_WIDE_INT, tree);
+static struct machine_function * sparc_init_machine_status (void);
+static bool sparc_cannot_force_const_mem (rtx);
+static rtx sparc_tls_get_addr (void);
+static rtx sparc_tls_got (void);
+static const char *get_some_local_dynamic_name (void);
+static int get_some_local_dynamic_name_1 (rtx *, void *);
+static bool sparc_rtx_costs (rtx, int, int, int *);
/* Option handling. */
@@ -238,21 +254,36 @@ enum processor_type sparc_cpu;
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD sparc_use_sched_lookahead
-#undef TARGET_ENCODE_SECTION_INFO
-#define TARGET_ENCODE_SECTION_INFO sparc_encode_section_info
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL sparc_function_ok_for_sibcall
+
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS sparc_init_libfuncs
+
+#ifdef HAVE_AS_TLS
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS true
+#endif
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM sparc_cannot_force_const_mem
#undef TARGET_ASM_OUTPUT_MI_THUNK
#define TARGET_ASM_OUTPUT_MI_THUNK sparc_output_mi_thunk
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS sparc_rtx_costs
+#undef TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST hook_int_rtx_0
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Validate and override various options, and do some machine dependent
initialization. */
void
-sparc_override_options ()
+sparc_override_options (void)
{
static struct code_model {
const char *const name;
@@ -444,6 +475,9 @@ sparc_override_options ()
/* Do various machine dependent initializations. */
sparc_init_modes ();
+
+ /* Set up function hooks. */
+ init_machine_status = sparc_init_machine_status;
}
/* Miscellaneous utilities. */
@@ -452,8 +486,7 @@ sparc_override_options ()
or branch on register contents instructions. */
int
-v9_regcmp_p (code)
- enum rtx_code code;
+v9_regcmp_p (enum rtx_code code)
{
return (code == EQ || code == NE || code == GE || code == LT
|| code == LE || code == GT);
@@ -466,9 +499,7 @@ v9_regcmp_p (code)
or const0_rtx. */
int
-reg_or_0_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+reg_or_0_operand (rtx op, enum machine_mode mode)
{
if (register_operand (op, mode))
return 1;
@@ -486,9 +517,7 @@ reg_or_0_operand (op, mode)
/* Return nonzero only if OP is const1_rtx. */
int
-const1_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+const1_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return op == const1_rtx;
}
@@ -496,9 +525,7 @@ const1_operand (op, mode)
/* Nonzero if OP is a floating point value with value 0.0. */
int
-fp_zero_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+fp_zero_operand (rtx op, enum machine_mode mode)
{
if (GET_MODE_CLASS (GET_MODE (op)) != MODE_FLOAT)
return 0;
@@ -508,9 +535,7 @@ fp_zero_operand (op, mode)
/* Nonzero if OP is a register operand in floating point register. */
int
-fp_register_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+fp_register_operand (rtx op, enum machine_mode mode)
{
if (! register_operand (op, mode))
return 0;
@@ -524,8 +549,7 @@ fp_register_operand (op, mode)
sethi instruction. */
int
-fp_sethi_p (op)
- rtx op;
+fp_sethi_p (rtx op)
{
if (GET_CODE (op) == CONST_DOUBLE)
{
@@ -549,8 +573,7 @@ fp_sethi_p (op)
mov instruction. */
int
-fp_mov_p (op)
- rtx op;
+fp_mov_p (rtx op)
{
if (GET_CODE (op) == CONST_DOUBLE)
{
@@ -574,8 +597,7 @@ fp_mov_p (op)
instruction sequence. */
int
-fp_high_losum_p (op)
- rtx op;
+fp_high_losum_p (rtx op)
{
/* The constraints calling this should only be in
SFmode move insns, so any constant which cannot
@@ -601,9 +623,7 @@ fp_high_losum_p (op)
/* Nonzero if OP is an integer register. */
int
-intreg_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+intreg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return (register_operand (op, SImode)
|| (TARGET_ARCH64 && register_operand (op, DImode)));
@@ -612,9 +632,7 @@ intreg_operand (op, mode)
/* Nonzero if OP is a floating point condition code register. */
int
-fcc_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+fcc_reg_operand (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. */
@@ -639,9 +657,7 @@ fcc_reg_operand (op, mode)
/* Nonzero if OP is a floating point condition code fcc0 register. */
int
-fcc0_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+fcc0_reg_operand (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. */
@@ -660,9 +676,7 @@ fcc0_reg_operand (op, mode)
/* Nonzero if OP is an integer or floating point condition code register. */
int
-icc_or_fcc_reg_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+icc_or_fcc_reg_operand (rtx op, enum machine_mode mode)
{
if (GET_CODE (op) == REG && REGNO (op) == SPARC_ICC_REG)
{
@@ -679,9 +693,7 @@ icc_or_fcc_reg_operand (op, mode)
/* Nonzero if OP can appear as the dest of a RESTORE insn. */
int
-restore_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+restore_operand (rtx op, enum machine_mode mode)
{
return (GET_CODE (op) == REG && GET_MODE (op) == mode
&& (REGNO (op) < 8 || (REGNO (op) >= 24 && REGNO (op) < 32)));
@@ -691,9 +703,7 @@ restore_operand (op, mode)
memory address. */
int
-call_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+call_operand (rtx op, enum machine_mode mode)
{
if (GET_CODE (op) != MEM)
abort ();
@@ -702,20 +712,51 @@ call_operand (op, mode)
}
int
-call_operand_address (op, mode)
- rtx op;
- enum machine_mode mode;
+call_operand_address (rtx op, enum machine_mode mode)
{
return (symbolic_operand (op, mode) || memory_address_p (Pmode, op));
}
+/* If OP is a SYMBOL_REF of a thread-local symbol, return its TLS mode,
+ otherwise return 0. */
+
+int
+tls_symbolic_operand (rtx op)
+{
+ if (GET_CODE (op) != SYMBOL_REF)
+ return 0;
+ return SYMBOL_REF_TLS_MODEL (op);
+}
+
+int
+tgd_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return tls_symbolic_operand (op) == TLS_MODEL_GLOBAL_DYNAMIC;
+}
+
+int
+tld_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return tls_symbolic_operand (op) == TLS_MODEL_LOCAL_DYNAMIC;
+}
+
+int
+tie_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return tls_symbolic_operand (op) == TLS_MODEL_INITIAL_EXEC;
+}
+
+int
+tle_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return tls_symbolic_operand (op) == TLS_MODEL_LOCAL_EXEC;
+}
+
/* Returns 1 if OP is either a symbol reference or a sum of a symbol
reference and a constant. */
int
-symbolic_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
+symbolic_operand (register rtx op, enum machine_mode mode)
{
enum machine_mode omode = GET_MODE (op);
@@ -725,12 +766,15 @@ symbolic_operand (op, mode)
switch (GET_CODE (op))
{
case SYMBOL_REF:
+ return !SYMBOL_REF_TLS_MODEL (op);
+
case LABEL_REF:
return 1;
case CONST:
op = XEXP (op, 0);
- return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+ return (((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+ && !SYMBOL_REF_TLS_MODEL (XEXP (op, 0)))
|| GET_CODE (XEXP (op, 0)) == LABEL_REF)
&& GET_CODE (XEXP (op, 1)) == CONST_INT);
@@ -743,25 +787,22 @@ symbolic_operand (op, mode)
operand of mode MODE. */
int
-symbolic_memory_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+symbolic_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
if (GET_CODE (op) != MEM)
return 0;
op = XEXP (op, 0);
- return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST
- || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF);
+ return ((GET_CODE (op) == SYMBOL_REF && !SYMBOL_REF_TLS_MODEL (op))
+ || GET_CODE (op) == CONST || GET_CODE (op) == HIGH
+ || GET_CODE (op) == LABEL_REF);
}
/* Return truth value of statement that OP is a LABEL_REF of mode MODE. */
int
-label_ref_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+label_ref_operand (rtx op, enum machine_mode mode)
{
if (GET_CODE (op) != LABEL_REF)
return 0;
@@ -774,9 +815,7 @@ label_ref_operand (op, mode)
in either the medium/low or medium/anywhere code models of sparc64. */
int
-sp64_medium_pic_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+sp64_medium_pic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
/* Check for (const (minus (symbol_ref:GOT)
(const (minus (label) (pc))))). */
@@ -801,14 +840,12 @@ sp64_medium_pic_operand (op, mode)
are accessed with EMBMEDANY_BASE_REG. */
int
-data_segment_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+data_segment_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
switch (GET_CODE (op))
{
case SYMBOL_REF :
- return ! SYMBOL_REF_FLAG (op);
+ return ! SYMBOL_REF_FUNCTION_P (op);
case PLUS :
/* Assume canonical format of symbol + constant.
Fall through. */
@@ -823,16 +860,14 @@ data_segment_operand (op, mode)
This is needed in the medium/anywhere code model on v9. */
int
-text_segment_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+text_segment_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
switch (GET_CODE (op))
{
case LABEL_REF :
return 1;
case SYMBOL_REF :
- return SYMBOL_REF_FLAG (op);
+ return SYMBOL_REF_FUNCTION_P (op);
case PLUS :
/* Assume canonical format of symbol + constant.
Fall through. */
@@ -847,9 +882,7 @@ text_segment_operand (op, mode)
not symbolic. */
int
-reg_or_nonsymb_mem_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
+reg_or_nonsymb_mem_operand (register rtx op, enum machine_mode mode)
{
if (register_operand (op, mode))
return 1;
@@ -861,9 +894,8 @@ reg_or_nonsymb_mem_operand (op, mode)
}
int
-splittable_symbolic_memory_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+splittable_symbolic_memory_operand (rtx op,
+ enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (GET_CODE (op) != MEM)
return 0;
@@ -873,9 +905,8 @@ splittable_symbolic_memory_operand (op, mode)
}
int
-splittable_immediate_memory_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+splittable_immediate_memory_operand (rtx op,
+ enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (GET_CODE (op) != MEM)
return 0;
@@ -887,9 +918,7 @@ splittable_immediate_memory_operand (op, mode)
/* Return truth value of whether OP is EQ or NE. */
int
-eq_or_neq (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+eq_or_neq (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
}
@@ -898,9 +927,7 @@ eq_or_neq (op, mode)
or LTU for non-floating-point. We handle those specially. */
int
-normal_comp_operator (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+normal_comp_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
enum rtx_code code = GET_CODE (op);
@@ -918,9 +945,7 @@ normal_comp_operator (op, mode)
MATCH_OPERATOR to recognize all the branch insns. */
int
-noov_compare_op (op, mode)
- register rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+noov_compare_op (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
enum rtx_code code = GET_CODE (op);
@@ -938,9 +963,7 @@ noov_compare_op (op, mode)
MATCH_OPERATOR to recognize all the branch insns. */
int
-noov_compare64_op (op, mode)
- register rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+noov_compare64_op (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
enum rtx_code code = GET_CODE (op);
@@ -960,9 +983,7 @@ noov_compare64_op (op, mode)
conditional move or branch on register contents instructions. */
int
-v9_regcmp_op (op, mode)
- register rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+v9_regcmp_op (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
enum rtx_code code = GET_CODE (op);
@@ -975,9 +996,7 @@ v9_regcmp_op (op, mode)
/* Return 1 if this is a SIGN_EXTEND or ZERO_EXTEND operation. */
int
-extend_op (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+extend_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND;
}
@@ -987,9 +1006,7 @@ extend_op (op, mode)
because these require CC_NOOVmode, which we handle explicitly. */
int
-cc_arithop (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+cc_arithop (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (GET_CODE (op) == AND
|| GET_CODE (op) == IOR
@@ -1003,9 +1020,7 @@ cc_arithop (op, mode)
complement its second operand and set the condition codes explicitly. */
int
-cc_arithopn (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+cc_arithopn (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
/* XOR is not here because combine canonicalizes (xor (not ...) ...)
and (xor ... (not ...)) to (not (xor ...)). */
@@ -1018,9 +1033,7 @@ cc_arithopn (op, mode)
most 3 address instructions. */
int
-arith_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+arith_operand (rtx op, enum machine_mode mode)
{
if (register_operand (op, mode))
return 1;
@@ -1032,9 +1045,7 @@ arith_operand (op, mode)
/* Return true if OP is a constant 4096 */
int
-arith_4096_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+arith_4096_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
if (GET_CODE (op) != CONST_INT)
return 0;
@@ -1045,9 +1056,7 @@ arith_4096_operand (op, mode)
/* Return true if OP is suitable as second operand for add/sub */
int
-arith_add_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+arith_add_operand (rtx op, enum machine_mode mode)
{
return arith_operand (op, mode) || arith_4096_operand (op, mode);
}
@@ -1056,9 +1065,7 @@ arith_add_operand (op, mode)
immediate field of OR and XOR instructions. Used for 64-bit
constant formation patterns. */
int
-const64_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+const64_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return ((GET_CODE (op) == CONST_INT
&& SPARC_SIMM13_P (INTVAL (op)))
@@ -1074,9 +1081,7 @@ const64_operand (op, mode)
/* The same, but only for sethi instructions. */
int
-const64_high_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+const64_high_operand (rtx op, enum machine_mode mode)
{
return ((GET_CODE (op) == CONST_INT
&& (INTVAL (op) & ~(HOST_WIDE_INT)0x3ff) != 0
@@ -1093,9 +1098,7 @@ const64_high_operand (op, mode)
the movcc instructions. */
int
-arith11_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+arith11_operand (rtx op, enum machine_mode mode)
{
return (register_operand (op, mode)
|| (GET_CODE (op) == CONST_INT && SPARC_SIMM11_P (INTVAL (op))));
@@ -1106,9 +1109,7 @@ arith11_operand (op, mode)
the movrcc instructions. */
int
-arith10_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+arith10_operand (rtx op, enum machine_mode mode)
{
return (register_operand (op, mode)
|| (GET_CODE (op) == CONST_INT && SPARC_SIMM10_P (INTVAL (op))));
@@ -1122,9 +1123,7 @@ arith10_operand (op, mode)
for most 3 address instructions. */
int
-arith_double_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+arith_double_operand (rtx op, enum machine_mode mode)
{
return (register_operand (op, mode)
|| (GET_CODE (op) == CONST_INT && SMALL_INT (op))
@@ -1144,9 +1143,7 @@ arith_double_operand (op, mode)
/* Return true if OP is a constant 4096 for DImode on ARCH64 */
int
-arith_double_4096_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+arith_double_4096_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return (TARGET_ARCH64 &&
((GET_CODE (op) == CONST_INT && INTVAL (op) == 4096) ||
@@ -1158,9 +1155,7 @@ arith_double_4096_operand (op, mode)
/* Return true if OP is suitable as second operand for add/sub in DImode */
int
-arith_double_add_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+arith_double_add_operand (rtx op, enum machine_mode mode)
{
return arith_double_operand (op, mode) || arith_double_4096_operand (op, mode);
}
@@ -1171,9 +1166,7 @@ arith_double_add_operand (op, mode)
/* ??? Replace with arith11_operand? */
int
-arith11_double_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+arith11_double_operand (rtx op, enum machine_mode mode)
{
return (register_operand (op, mode)
|| (GET_CODE (op) == CONST_DOUBLE
@@ -1194,9 +1187,7 @@ arith11_double_operand (op, mode)
/* ??? Replace with arith10_operand? */
int
-arith10_double_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+arith10_double_operand (rtx op, enum machine_mode mode)
{
return (register_operand (op, mode)
|| (GET_CODE (op) == CONST_DOUBLE
@@ -1216,17 +1207,13 @@ arith10_double_operand (op, mode)
which have a 13 bit immediate field. */
int
-small_int (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+small_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
}
int
-small_int_or_double (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+small_int_or_double (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return ((GET_CODE (op) == CONST_INT && SMALL_INT (op))
|| (GET_CODE (op) == CONST_DOUBLE
@@ -1239,9 +1226,7 @@ small_int_or_double (op, mode)
interprets the extended result as an unsigned number. */
int
-uns_small_int (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+uns_small_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
#if HOST_BITS_PER_WIDE_INT > 32
/* All allowed constants will fit a CONST_INT. */
@@ -1258,18 +1243,14 @@ uns_small_int (op, mode)
}
int
-uns_arith_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+uns_arith_operand (rtx op, enum machine_mode mode)
{
return register_operand (op, mode) || uns_small_int (op, mode);
}
/* Return truth value of statement that OP is a call-clobbered register. */
int
-clobbered_register (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+clobbered_register (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]);
}
@@ -1277,16 +1258,14 @@ clobbered_register (op, mode)
/* Return 1 if OP is a valid operand for the source of a move insn. */
int
-input_operand (op, mode)
- rtx op;
- enum machine_mode mode;
+input_operand (rtx op, enum machine_mode mode)
{
/* If both modes are non-void they must be the same. */
if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
return 0;
- /* Only a tiny bit of handling for CONSTANT_P_RTX is necessary. */
- if (GET_CODE (op) == CONST && GET_CODE (XEXP (op, 0)) == CONSTANT_P_RTX)
+ /* Accept CONSTANT_P_RTX, since it will be gone by CSE1 and result in 0/1. */
+ if (GET_CODE (op) == CONSTANT_P_RTX)
return 1;
/* Allow any one instruction integer constant, and all CONST_INT
@@ -1357,13 +1336,37 @@ input_operand (op, mode)
return 0;
}
+/* Return 1 if OP is valid for the lhs of a compare insn. */
+
+int
+compare_operand (rtx op, enum machine_mode mode)
+{
+ if (GET_CODE (op) == ZERO_EXTRACT)
+ return (register_operand (XEXP (op, 0), mode)
+ && small_int_or_double (XEXP (op, 1), mode)
+ && small_int_or_double (XEXP (op, 2), mode)
+ /* This matches cmp_zero_extract. */
+ && ((mode == SImode
+ && ((GET_CODE (XEXP (op, 2)) == CONST_INT
+ && INTVAL (XEXP (op, 2)) > 19)
+ || (GET_CODE (XEXP (op, 2)) == CONST_DOUBLE
+ && CONST_DOUBLE_LOW (XEXP (op, 2)) > 19)))
+ /* This matches cmp_zero_extract_sp64. */
+ || (mode == DImode
+ && TARGET_ARCH64
+ && ((GET_CODE (XEXP (op, 2)) == CONST_INT
+ && INTVAL (XEXP (op, 2)) > 51)
+ || (GET_CODE (XEXP (op, 2)) == CONST_DOUBLE
+ && CONST_DOUBLE_LOW (XEXP (op, 2)) > 51)))));
+ else
+ return register_operand (op, mode);
+}
+
/* We know it can't be done in one insn when we get here,
- the movsi expander guarentees this. */
+ the movsi expander guarantees this. */
void
-sparc_emit_set_const32 (op0, op1)
- rtx op0;
- rtx op1;
+sparc_emit_set_const32 (rtx op0, rtx op1)
{
enum machine_mode mode = GET_MODE (op0);
rtx temp;
@@ -1417,21 +1420,25 @@ sparc_emit_set_const32 (op0, op1)
}
-/* SPARC-v9 code-model support. */
+/* Load OP1, a symbolic 64-bit constant, into OP0, a DImode register.
+ If TEMP is non-zero, we are forbidden to use any other scratch
+ registers. Otherwise, we are allowed to generate them as needed.
+
+ Note that TEMP may have TImode if the code model is TARGET_CM_MEDANY
+ or TARGET_CM_EMBMEDANY (see the reload_indi and reload_outdi patterns). */
void
-sparc_emit_set_symbolic_const64 (op0, op1, temp1)
- rtx op0;
- rtx op1;
- rtx temp1;
+sparc_emit_set_symbolic_const64 (rtx op0, rtx op1, rtx temp)
{
- rtx ti_temp1 = 0;
+ rtx temp1, temp2, temp3, temp4, temp5;
+ rtx ti_temp = 0;
- if (temp1 && GET_MODE (temp1) == TImode)
+ if (temp && GET_MODE (temp) == TImode)
{
- ti_temp1 = temp1;
- temp1 = gen_rtx_REG (DImode, REGNO (temp1));
+ ti_temp = temp;
+ temp = gen_rtx_REG (DImode, REGNO (temp));
}
+ /* SPARC-V9 code-model support. */
switch (sparc_cmodel)
{
case CM_MEDLOW:
@@ -1443,8 +1450,13 @@ sparc_emit_set_symbolic_const64 (op0, op1, temp1)
The executable must be in the low 4TB of the virtual address
space.
- sethi %hi(symbol), %temp
- or %temp, %lo(symbol), %reg */
+ sethi %hi(symbol), %temp1
+ or %temp1, %lo(symbol), %reg */
+ if (temp)
+ temp1 = temp; /* op0 is allowed. */
+ else
+ temp1 = gen_reg_rtx (DImode);
+
emit_insn (gen_rtx_SET (VOIDmode, temp1, gen_rtx_HIGH (DImode, op1)));
emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_LO_SUM (DImode, temp1, op1)));
break;
@@ -1462,11 +1474,24 @@ sparc_emit_set_symbolic_const64 (op0, op1, temp1)
or %temp1, %m44(symbol), %temp2
sllx %temp2, 12, %temp3
or %temp3, %l44(symbol), %reg */
- emit_insn (gen_seth44 (op0, op1));
- emit_insn (gen_setm44 (op0, op0, op1));
- emit_insn (gen_rtx_SET (VOIDmode, temp1,
- gen_rtx_ASHIFT (DImode, op0, GEN_INT (12))));
- emit_insn (gen_setl44 (op0, temp1, op1));
+ if (temp)
+ {
+ temp1 = op0;
+ temp2 = op0;
+ temp3 = temp; /* op0 is allowed. */
+ }
+ else
+ {
+ temp1 = gen_reg_rtx (DImode);
+ temp2 = gen_reg_rtx (DImode);
+ temp3 = gen_reg_rtx (DImode);
+ }
+
+ emit_insn (gen_seth44 (temp1, op1));
+ emit_insn (gen_setm44 (temp2, temp1, op1));
+ emit_insn (gen_rtx_SET (VOIDmode, temp3,
+ gen_rtx_ASHIFT (DImode, temp2, GEN_INT (12))));
+ emit_insn (gen_setl44 (op0, temp3, op1));
break;
case CM_MEDANY:
@@ -1481,29 +1506,44 @@ sparc_emit_set_symbolic_const64 (op0, op1, temp1)
sethi %hh(symbol), %temp1
sethi %lm(symbol), %temp2
or %temp1, %hm(symbol), %temp3
- or %temp2, %lo(symbol), %temp4
- sllx %temp3, 32, %temp5
- or %temp4, %temp5, %reg */
-
- /* 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))
+ sllx %temp3, 32, %temp4
+ or %temp4, %temp2, %temp5
+ or %temp5, %lo(symbol), %reg */
+ if (temp)
{
- if (ti_temp1)
- temp1 = gen_rtx_REG (DImode, REGNO (temp1) + 1);
- else
- 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 (temp, op0))
+ {
+ if (ti_temp)
+ temp = gen_rtx_REG (DImode, REGNO (temp) + 1);
+ else
+ abort();
+ }
+ temp1 = op0;
+ temp2 = temp; /* op0 is _not_ allowed, see above. */
+ temp3 = op0;
+ temp4 = op0;
+ temp5 = op0;
+ }
+ else
+ {
+ temp1 = gen_reg_rtx (DImode);
+ temp2 = gen_reg_rtx (DImode);
+ temp3 = gen_reg_rtx (DImode);
+ temp4 = gen_reg_rtx (DImode);
+ temp5 = gen_reg_rtx (DImode);
}
- emit_insn (gen_sethh (op0, op1));
- emit_insn (gen_setlm (temp1, op1));
- emit_insn (gen_sethm (op0, op0, op1));
- emit_insn (gen_rtx_SET (VOIDmode, op0,
- gen_rtx_ASHIFT (DImode, op0, GEN_INT (32))));
- emit_insn (gen_rtx_SET (VOIDmode, op0,
- gen_rtx_PLUS (DImode, op0, temp1)));
- emit_insn (gen_setlo (op0, op0, op1));
+ emit_insn (gen_sethh (temp1, op1));
+ emit_insn (gen_setlm (temp2, op1));
+ emit_insn (gen_sethm (temp3, temp1, op1));
+ emit_insn (gen_rtx_SET (VOIDmode, temp4,
+ gen_rtx_ASHIFT (DImode, temp3, GEN_INT (32))));
+ emit_insn (gen_rtx_SET (VOIDmode, temp5,
+ gen_rtx_PLUS (DImode, temp4, temp2)));
+ emit_insn (gen_setlo (op0, temp5, op1));
break;
case CM_EMBMEDANY:
@@ -1515,42 +1555,69 @@ sparc_emit_set_symbolic_const64 (op0, op1, temp1)
look different.
Data segment: sethi %hi(symbol), %temp1
- or %temp1, %lo(symbol), %temp2
- add %temp2, EMBMEDANY_BASE_REG, %reg
-
- Text segment: sethi %uhi(symbol), %temp1
- sethi %hi(symbol), %temp2
- or %temp1, %ulo(symbol), %temp3
- or %temp2, %lo(symbol), %temp4
- sllx %temp3, 32, %temp5
- or %temp4, %temp5, %reg */
+ add %temp1, EMBMEDANY_BASE_REG, %temp2
+ or %temp2, %lo(symbol), %reg */
if (data_segment_operand (op1, GET_MODE (op1)))
{
+ if (temp)
+ {
+ temp1 = temp; /* op0 is allowed. */
+ temp2 = op0;
+ }
+ else
+ {
+ temp1 = gen_reg_rtx (DImode);
+ temp2 = gen_reg_rtx (DImode);
+ }
+
emit_insn (gen_embmedany_sethi (temp1, op1));
- emit_insn (gen_embmedany_brsum (op0, temp1));
- emit_insn (gen_embmedany_losum (op0, op0, op1));
+ emit_insn (gen_embmedany_brsum (temp2, temp1));
+ emit_insn (gen_embmedany_losum (op0, temp2, op1));
}
+
+ /* Text segment: sethi %uhi(symbol), %temp1
+ sethi %hi(symbol), %temp2
+ or %temp1, %ulo(symbol), %temp3
+ sllx %temp3, 32, %temp4
+ or %temp4, %temp2, %temp5
+ or %temp5, %lo(symbol), %reg */
else
{
- /* 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 (temp)
{
- if (ti_temp1)
- temp1 = gen_rtx_REG (DImode, REGNO (temp1) + 1);
- else
- 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 (temp, op0))
+ {
+ if (ti_temp)
+ temp = gen_rtx_REG (DImode, REGNO (temp) + 1);
+ else
+ abort();
+ }
+ temp1 = op0;
+ temp2 = temp; /* op0 is _not_ allowed, see above. */
+ temp3 = op0;
+ temp4 = op0;
+ temp5 = op0;
+ }
+ else
+ {
+ temp1 = gen_reg_rtx (DImode);
+ temp2 = gen_reg_rtx (DImode);
+ temp3 = gen_reg_rtx (DImode);
+ temp4 = gen_reg_rtx (DImode);
+ temp5 = gen_reg_rtx (DImode);
}
- emit_insn (gen_embmedany_textuhi (op0, op1));
- emit_insn (gen_embmedany_texthi (temp1, op1));
- emit_insn (gen_embmedany_textulo (op0, op0, op1));
- emit_insn (gen_rtx_SET (VOIDmode, op0,
- gen_rtx_ASHIFT (DImode, op0, GEN_INT (32))));
- emit_insn (gen_rtx_SET (VOIDmode, op0,
- gen_rtx_PLUS (DImode, op0, temp1)));
- emit_insn (gen_embmedany_textlo (op0, op0, op1));
+ emit_insn (gen_embmedany_textuhi (temp1, op1));
+ emit_insn (gen_embmedany_texthi (temp2, op1));
+ emit_insn (gen_embmedany_textulo (temp3, temp1, op1));
+ emit_insn (gen_rtx_SET (VOIDmode, temp4,
+ gen_rtx_ASHIFT (DImode, temp3, GEN_INT (32))));
+ emit_insn (gen_rtx_SET (VOIDmode, temp5,
+ gen_rtx_PLUS (DImode, temp4, temp2)));
+ emit_insn (gen_embmedany_textlo (op0, temp5, op1));
}
break;
@@ -1562,10 +1629,10 @@ sparc_emit_set_symbolic_const64 (op0, op1, temp1)
/* These avoid problems when cross compiling. If we do not
go through all this hair then the optimizer will see
invalid REG_EQUAL notes or in some cases none at all. */
-static void sparc_emit_set_safe_HIGH64 PARAMS ((rtx, HOST_WIDE_INT));
-static rtx gen_safe_SET64 PARAMS ((rtx, HOST_WIDE_INT));
-static rtx gen_safe_OR64 PARAMS ((rtx, HOST_WIDE_INT));
-static rtx gen_safe_XOR64 PARAMS ((rtx, HOST_WIDE_INT));
+static void sparc_emit_set_safe_HIGH64 (rtx, HOST_WIDE_INT);
+static rtx gen_safe_SET64 (rtx, HOST_WIDE_INT);
+static rtx gen_safe_OR64 (rtx, HOST_WIDE_INT);
+static rtx gen_safe_XOR64 (rtx, HOST_WIDE_INT);
#if HOST_BITS_PER_WIDE_INT == 64
#define GEN_HIGHINT64(__x) GEN_INT ((__x) & ~(HOST_WIDE_INT)0x3ff)
@@ -1584,33 +1651,25 @@ static rtx gen_safe_XOR64 PARAMS ((rtx, HOST_WIDE_INT));
during CSE. We mask out the non-HIGH bits, and matches
a plain movdi, to alleviate this problem. */
static void
-sparc_emit_set_safe_HIGH64 (dest, val)
- rtx dest;
- HOST_WIDE_INT val;
+sparc_emit_set_safe_HIGH64 (rtx dest, HOST_WIDE_INT val)
{
emit_insn (gen_rtx_SET (VOIDmode, dest, GEN_HIGHINT64 (val)));
}
static rtx
-gen_safe_SET64 (dest, val)
- rtx dest;
- HOST_WIDE_INT val;
+gen_safe_SET64 (rtx dest, HOST_WIDE_INT val)
{
return gen_rtx_SET (VOIDmode, dest, GEN_INT64 (val));
}
static rtx
-gen_safe_OR64 (src, val)
- rtx src;
- HOST_WIDE_INT val;
+gen_safe_OR64 (rtx src, HOST_WIDE_INT val)
{
return gen_rtx_IOR (DImode, src, GEN_INT64 (val));
}
static rtx
-gen_safe_XOR64 (src, val)
- rtx src;
- HOST_WIDE_INT val;
+gen_safe_XOR64 (rtx src, HOST_WIDE_INT val)
{
return gen_rtx_XOR (DImode, src, GEN_INT64 (val));
}
@@ -1623,15 +1682,12 @@ gen_safe_XOR64 (src, val)
Without doing this, the optimizer cannot see such
opportunities. */
-static void sparc_emit_set_const64_quick1
- PARAMS ((rtx, rtx, unsigned HOST_WIDE_INT, int));
+static void sparc_emit_set_const64_quick1 (rtx, rtx,
+ unsigned HOST_WIDE_INT, int);
static void
-sparc_emit_set_const64_quick1 (op0, temp, low_bits, is_neg)
- rtx op0;
- rtx temp;
- unsigned HOST_WIDE_INT low_bits;
- int is_neg;
+sparc_emit_set_const64_quick1 (rtx op0, rtx temp,
+ unsigned HOST_WIDE_INT low_bits, int is_neg)
{
unsigned HOST_WIDE_INT high_bits;
@@ -1666,17 +1722,14 @@ sparc_emit_set_const64_quick1 (op0, temp, low_bits, is_neg)
}
}
-static void sparc_emit_set_const64_quick2
- PARAMS ((rtx, rtx, unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT, int));
+static void sparc_emit_set_const64_quick2 (rtx, rtx, unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT, int);
static void
-sparc_emit_set_const64_quick2 (op0, temp, high_bits, low_immediate, shift_count)
- rtx op0;
- rtx temp;
- unsigned HOST_WIDE_INT high_bits;
- unsigned HOST_WIDE_INT low_immediate;
- int shift_count;
+sparc_emit_set_const64_quick2 (rtx op0, rtx temp,
+ unsigned HOST_WIDE_INT high_bits,
+ unsigned HOST_WIDE_INT low_immediate,
+ int shift_count)
{
rtx temp2 = op0;
@@ -1707,17 +1760,15 @@ sparc_emit_set_const64_quick2 (op0, temp, high_bits, low_immediate, shift_count)
gen_safe_OR64 (op0, low_immediate)));
}
-static void sparc_emit_set_const64_longway
- PARAMS ((rtx, rtx, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT));
+static void sparc_emit_set_const64_longway (rtx, rtx, unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT);
/* Full 64-bit constant decomposition. Even though this is the
'worst' case, we still optimize a few things away. */
static void
-sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits)
- rtx op0;
- rtx temp;
- unsigned HOST_WIDE_INT high_bits;
- unsigned HOST_WIDE_INT low_bits;
+sparc_emit_set_const64_longway (rtx op0, rtx temp,
+ unsigned HOST_WIDE_INT high_bits,
+ unsigned HOST_WIDE_INT low_bits)
{
rtx sub_temp;
@@ -1815,15 +1866,14 @@ sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits)
}
/* Analyze a 64-bit constant for certain properties. */
-static void analyze_64bit_constant
- PARAMS ((unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT,
- int *, int *, int *));
+static void analyze_64bit_constant (unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT,
+ int *, int *, int *);
static void
-analyze_64bit_constant (high_bits, low_bits, hbsp, lbsp, abbasp)
- unsigned HOST_WIDE_INT high_bits, low_bits;
- int *hbsp, *lbsp, *abbasp;
+analyze_64bit_constant (unsigned HOST_WIDE_INT high_bits,
+ unsigned HOST_WIDE_INT low_bits,
+ int *hbsp, int *lbsp, int *abbasp)
{
int lowest_bit_set, highest_bit_set, all_bits_between_are_set;
int i;
@@ -1884,12 +1934,11 @@ analyze_64bit_constant (high_bits, low_bits, hbsp, lbsp, abbasp)
*abbasp = all_bits_between_are_set;
}
-static int const64_is_2insns
- PARAMS ((unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT));
+static int const64_is_2insns (unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT);
static int
-const64_is_2insns (high_bits, low_bits)
- unsigned HOST_WIDE_INT high_bits, low_bits;
+const64_is_2insns (unsigned HOST_WIDE_INT high_bits,
+ unsigned HOST_WIDE_INT low_bits)
{
int highest_bit_set, lowest_bit_set, all_bits_between_are_set;
@@ -1912,14 +1961,14 @@ const64_is_2insns (high_bits, low_bits)
return 0;
}
-static unsigned HOST_WIDE_INT create_simple_focus_bits
- PARAMS ((unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
- int, int));
+static unsigned HOST_WIDE_INT create_simple_focus_bits (unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT,
+ int, int);
static unsigned HOST_WIDE_INT
-create_simple_focus_bits (high_bits, low_bits, lowest_bit_set, shift)
- unsigned HOST_WIDE_INT high_bits, low_bits;
- int lowest_bit_set, shift;
+create_simple_focus_bits (unsigned HOST_WIDE_INT high_bits,
+ unsigned HOST_WIDE_INT low_bits,
+ int lowest_bit_set, int shift)
{
HOST_WIDE_INT hi, lo;
@@ -1943,14 +1992,12 @@ create_simple_focus_bits (high_bits, low_bits, lowest_bit_set, shift)
insn sequence possible. Detection of all the 1-insn cases
has been done already. */
void
-sparc_emit_set_const64 (op0, op1)
- rtx op0;
- rtx op1;
+sparc_emit_set_const64 (rtx op0, rtx op1)
{
unsigned HOST_WIDE_INT high_bits, low_bits;
int lowest_bit_set, highest_bit_set;
int all_bits_between_are_set;
- rtx temp;
+ rtx temp = 0;
/* Sanity check that we know what we are working with. */
if (! TARGET_ARCH64)
@@ -1966,8 +2013,6 @@ sparc_emit_set_const64 (op0, op1)
if (reload_in_progress || reload_completed)
temp = op0;
- else
- temp = gen_reg_rtx (DImode);
if (GET_CODE (op1) != CONST_DOUBLE
&& GET_CODE (op1) != CONST_INT)
@@ -1976,6 +2021,9 @@ sparc_emit_set_const64 (op0, op1)
return;
}
+ if (! temp)
+ temp = gen_reg_rtx (DImode);
+
if (GET_CODE (op1) == CONST_DOUBLE)
{
#if HOST_BITS_PER_WIDE_INT == 64
@@ -2223,10 +2271,7 @@ sparc_emit_set_const64 (op0, op1)
processing is needed. */
enum machine_mode
-select_cc_mode (op, x, y)
- enum rtx_code op;
- rtx x;
- rtx y ATTRIBUTE_UNUSED;
+select_cc_mode (enum rtx_code op, rtx x, rtx y ATTRIBUTE_UNUSED)
{
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
{
@@ -2275,9 +2320,7 @@ select_cc_mode (op, x, y)
return the rtx for the cc reg in the proper mode. */
rtx
-gen_compare_reg (code, x, y)
- enum rtx_code code;
- rtx x, y;
+gen_compare_reg (enum rtx_code code, rtx x, rtx y)
{
enum machine_mode mode = SELECT_CC_MODE (code, x, y);
rtx cc_reg;
@@ -2358,9 +2401,7 @@ gen_compare_reg (code, x, y)
sparc_compare_op1. */
int
-gen_v9_scc (compare_code, operands)
- enum rtx_code compare_code;
- register rtx *operands;
+gen_v9_scc (enum rtx_code compare_code, register rtx *operands)
{
rtx temp, op0, op1;
@@ -2448,9 +2489,7 @@ gen_v9_scc (compare_code, operands)
This function exists to take advantage of the v9 brxx insns. */
void
-emit_v9_brxx_insn (code, op0, label)
- enum rtx_code code;
- rtx op0, label;
+emit_v9_brxx_insn (enum rtx_code code, rtx op0, rtx label)
{
emit_jump_insn (gen_rtx_SET (VOIDmode,
pc_rtx,
@@ -2466,9 +2505,7 @@ emit_v9_brxx_insn (code, op0, label)
low 64bit of the register and 0 otherwise.
*/
rtx
-gen_df_reg (reg, low)
- rtx reg;
- int low;
+gen_df_reg (rtx reg, int low)
{
int regno = REGNO (reg);
@@ -2482,10 +2519,7 @@ gen_df_reg (reg, low)
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;
+emit_soft_tfmode_libcall (const char *func_name, int nargs, rtx *operands)
{
rtx ret_slot = NULL, arg[3], func_sym;
int i;
@@ -2570,9 +2604,7 @@ emit_soft_tfmode_libcall (func_name, nargs, operands)
/* Expand soft-float TFmode calls to sparc abi routines. */
static void
-emit_soft_tfmode_binop (code, operands)
- enum rtx_code code;
- rtx *operands;
+emit_soft_tfmode_binop (enum rtx_code code, rtx *operands)
{
const char *func;
@@ -2598,9 +2630,7 @@ emit_soft_tfmode_binop (code, operands)
}
static void
-emit_soft_tfmode_unop (code, operands)
- enum rtx_code code;
- rtx *operands;
+emit_soft_tfmode_unop (enum rtx_code code, rtx *operands)
{
const char *func;
@@ -2617,9 +2647,7 @@ emit_soft_tfmode_unop (code, operands)
}
static void
-emit_soft_tfmode_cvt (code, operands)
- enum rtx_code code;
- rtx *operands;
+emit_soft_tfmode_cvt (enum rtx_code code, rtx *operands)
{
const char *func;
@@ -2720,9 +2748,7 @@ emit_soft_tfmode_cvt (code, operands)
registers. */
static void
-emit_hard_tfmode_operation (code, operands)
- enum rtx_code code;
- rtx *operands;
+emit_hard_tfmode_operation (enum rtx_code code, rtx *operands)
{
rtx op, dest;
@@ -2751,9 +2777,7 @@ emit_hard_tfmode_operation (code, operands)
}
void
-emit_tfmode_binop (code, operands)
- enum rtx_code code;
- rtx *operands;
+emit_tfmode_binop (enum rtx_code code, rtx *operands)
{
if (TARGET_HARD_QUAD)
emit_hard_tfmode_operation (code, operands);
@@ -2762,9 +2786,7 @@ emit_tfmode_binop (code, operands)
}
void
-emit_tfmode_unop (code, operands)
- enum rtx_code code;
- rtx *operands;
+emit_tfmode_unop (enum rtx_code code, rtx *operands)
{
if (TARGET_HARD_QUAD)
emit_hard_tfmode_operation (code, operands);
@@ -2773,9 +2795,7 @@ emit_tfmode_unop (code, operands)
}
void
-emit_tfmode_cvt (code, operands)
- enum rtx_code code;
- rtx *operands;
+emit_tfmode_cvt (enum rtx_code code, rtx *operands)
{
if (TARGET_HARD_QUAD)
emit_hard_tfmode_operation (code, operands);
@@ -2786,7 +2806,7 @@ emit_tfmode_cvt (code, operands)
/* Return nonzero if a return peephole merging return with
setting of output register is ok. */
int
-leaf_return_peephole_ok ()
+leaf_return_peephole_ok (void)
{
return (actual_fsize == 0);
}
@@ -2795,8 +2815,7 @@ leaf_return_peephole_ok ()
nop into its delay slot. */
int
-empty_delay_slot (insn)
- rtx insn;
+empty_delay_slot (rtx insn)
{
rtx seq;
@@ -2815,9 +2834,7 @@ empty_delay_slot (insn)
delay slot. SLOT is the slot we are trying to fill. */
int
-eligible_for_epilogue_delay (trial, slot)
- rtx trial;
- int slot;
+eligible_for_epilogue_delay (rtx trial, int slot)
{
rtx pat, src;
@@ -2939,12 +2956,37 @@ eligible_for_epilogue_delay (trial, slot)
return 0;
}
+/* Return nonzero if TRIAL can go into the call delay slot. */
+int
+tls_call_delay (rtx trial)
+{
+ rtx pat, unspec;
+
+ /* Binutils allows
+ call __tls_get_addr, %tgd_call (foo)
+ add %l7, %o0, %o0, %tgd_add (foo)
+ while Sun as/ld does not. */
+ if (TARGET_GNU_TLS || !TARGET_TLS)
+ return 1;
+
+ pat = PATTERN (trial);
+ if (GET_CODE (pat) != SET || GET_CODE (SET_DEST (pat)) != PLUS)
+ return 1;
+
+ unspec = XEXP (SET_DEST (pat), 1);
+ if (GET_CODE (unspec) != UNSPEC
+ || (XINT (unspec, 1) != UNSPEC_TLSGD
+ && XINT (unspec, 1) != UNSPEC_TLSLDM))
+ return 1;
+
+ return 0;
+}
+
/* Return nonzero if TRIAL can go into the sibling call
delay slot. */
int
-eligible_for_sibcall_delay (trial)
- rtx trial;
+eligible_for_sibcall_delay (rtx trial)
{
rtx pat, src;
@@ -3034,8 +3076,7 @@ eligible_for_sibcall_delay (trial)
}
static int
-check_return_regs (x)
- rtx x;
+check_return_regs (rtx x)
{
switch (GET_CODE (x))
{
@@ -3069,8 +3110,7 @@ check_return_regs (x)
}
int
-short_branch (uid1, uid2)
- int uid1, uid2;
+short_branch (int uid1, int uid2)
{
int delta = INSN_ADDRESSES (uid1) - INSN_ADDRESSES (uid2);
@@ -3085,9 +3125,7 @@ short_branch (uid1, uid2)
We assume REG is a reload reg, and therefore does
not live past labels or calls or jumps. */
int
-reg_unused_after (reg, insn)
- rtx reg;
- rtx insn;
+reg_unused_after (rtx reg, rtx insn)
{
enum rtx_code code, prev_code = UNKNOWN;
@@ -3116,18 +3154,56 @@ reg_unused_after (reg, insn)
return 1;
}
+/* Determine if it's legal to put X into the constant pool. This
+ is not possible if X contains the address of a symbol that is
+ not constant (TLS) or not known at final link time (PIC). */
+
+static bool
+sparc_cannot_force_const_mem (rtx x)
+{
+ switch (GET_CODE (x))
+ {
+ case CONST_INT:
+ case CONST_DOUBLE:
+ /* Accept all non-symbolic constants. */
+ return false;
+
+ case LABEL_REF:
+ /* Labels are OK iff we are non-PIC. */
+ return flag_pic != 0;
+
+ case SYMBOL_REF:
+ /* 'Naked' TLS symbol references are never OK,
+ non-TLS symbols are OK iff we are non-PIC. */
+ if (SYMBOL_REF_TLS_MODEL (x))
+ return true;
+ else
+ return flag_pic != 0;
+
+ case CONST:
+ return sparc_cannot_force_const_mem (XEXP (x, 0));
+ case PLUS:
+ case MINUS:
+ return sparc_cannot_force_const_mem (XEXP (x, 0))
+ || sparc_cannot_force_const_mem (XEXP (x, 1));
+ case UNSPEC:
+ return true;
+ default:
+ abort ();
+ }
+}
+
/* The table we use to reference PIC data. */
static GTY(()) rtx global_offset_table;
/* The function we use to get at it. */
static GTY(()) rtx get_pc_symbol;
-static char get_pc_symbol_name[256];
+static GTY(()) char get_pc_symbol_name[256];
/* Ensure that we are not using patterns that are not OK with PIC. */
int
-check_pic (i)
- int i;
+check_pic (int i)
{
switch (flag_pic)
{
@@ -3150,8 +3226,7 @@ check_pic (i)
reloaded while generating PIC code. */
int
-pic_address_needs_scratch (x)
- rtx x;
+pic_address_needs_scratch (rtx x)
{
/* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
@@ -3163,16 +3238,399 @@ pic_address_needs_scratch (x)
return 0;
}
+/* Determine if a given RTX is a valid constant. We already know this
+ satisfies CONSTANT_P. */
+
+bool
+legitimate_constant_p (rtx x)
+{
+ rtx inner;
+
+ switch (GET_CODE (x))
+ {
+ case SYMBOL_REF:
+ /* TLS symbols are not constant. */
+ if (SYMBOL_REF_TLS_MODEL (x))
+ return false;
+ break;
+
+ case CONST:
+ inner = XEXP (x, 0);
+
+ /* Offsets of TLS symbols are never valid.
+ Discourage CSE from creating them. */
+ if (GET_CODE (inner) == PLUS
+ && tls_symbolic_operand (XEXP (inner, 0)))
+ return false;
+ break;
+
+ case CONST_DOUBLE:
+ if (GET_MODE (x) == VOIDmode)
+ return true;
+
+ /* Floating point constants are generally not ok.
+ The only exception is 0.0 in VIS. */
+ if (TARGET_VIS
+ && (GET_MODE (x) == SFmode
+ || GET_MODE (x) == DFmode
+ || GET_MODE (x) == TFmode)
+ && fp_zero_operand (x, GET_MODE (x)))
+ return true;
+
+ return false;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+/* Determine if a given RTX is a valid constant address. */
+
+bool
+constant_address_p (rtx x)
+{
+ switch (GET_CODE (x))
+ {
+ case LABEL_REF:
+ case CONST_INT:
+ case HIGH:
+ return true;
+
+ case CONST:
+ if (flag_pic && pic_address_needs_scratch (x))
+ return false;
+ return legitimate_constant_p (x);
+
+ case SYMBOL_REF:
+ return !flag_pic && legitimate_constant_p (x);
+
+ default:
+ return false;
+ }
+}
+
+/* Nonzero if the constant value X is a legitimate general operand
+ when generating PIC code. It is given that flag_pic is on and
+ that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
+
+bool
+legitimate_pic_operand_p (rtx x)
+{
+ if (pic_address_needs_scratch (x))
+ return false;
+ if (tls_symbolic_operand (x)
+ || (GET_CODE (x) == CONST
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && tls_symbolic_operand (XEXP (XEXP (x, 0), 0))))
+ return false;
+ return true;
+}
+
+/* Return nonzero if ADDR is a valid memory address.
+ STRICT specifies whether strict register checking applies. */
+
+int
+legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
+{
+ rtx rs1 = NULL, rs2 = NULL, imm1 = NULL, imm2;
+
+ if (REG_P (addr) || GET_CODE (addr) == SUBREG)
+ rs1 = addr;
+ else if (GET_CODE (addr) == PLUS)
+ {
+ rs1 = XEXP (addr, 0);
+ rs2 = XEXP (addr, 1);
+
+ /* Canonicalize. REG comes first, if there are no regs,
+ LO_SUM comes first. */
+ if (!REG_P (rs1)
+ && GET_CODE (rs1) != SUBREG
+ && (REG_P (rs2)
+ || GET_CODE (rs2) == SUBREG
+ || (GET_CODE (rs2) == LO_SUM && GET_CODE (rs1) != LO_SUM)))
+ {
+ rs1 = XEXP (addr, 1);
+ rs2 = XEXP (addr, 0);
+ }
+
+ if ((flag_pic == 1
+ && rs1 == pic_offset_table_rtx
+ && !REG_P (rs2)
+ && GET_CODE (rs2) != SUBREG
+ && GET_CODE (rs2) != LO_SUM
+ && GET_CODE (rs2) != MEM
+ && !tls_symbolic_operand (rs2)
+ && (! symbolic_operand (rs2, VOIDmode) || mode == Pmode)
+ && (GET_CODE (rs2) != CONST_INT || SMALL_INT (rs2)))
+ || ((REG_P (rs1)
+ || GET_CODE (rs1) == SUBREG)
+ && RTX_OK_FOR_OFFSET_P (rs2)))
+ {
+ imm1 = rs2;
+ rs2 = NULL;
+ }
+ else if ((REG_P (rs1) || GET_CODE (rs1) == SUBREG)
+ && (REG_P (rs2) || GET_CODE (rs2) == SUBREG))
+ {
+ /* We prohibit REG + REG for TFmode when there are no instructions
+ which accept REG+REG instructions. We do this because REG+REG
+ is not an offsetable address. If we get the situation in reload
+ where source and destination of a movtf pattern are both MEMs with
+ REG+REG address, then only one of them gets converted to an
+ offsetable address. */
+ if (mode == TFmode
+ && !(TARGET_FPU && TARGET_ARCH64 && TARGET_V9
+ && TARGET_HARD_QUAD))
+ return 0;
+
+ /* We prohibit REG + REG on ARCH32 if not optimizing for
+ DFmode/DImode because then mem_min_alignment is likely to be zero
+ after reload and the forced split would lack a matching splitter
+ pattern. */
+ if (TARGET_ARCH32 && !optimize
+ && (mode == DFmode || mode == DImode))
+ return 0;
+ }
+ else if (USE_AS_OFFSETABLE_LO10
+ && GET_CODE (rs1) == LO_SUM
+ && TARGET_ARCH64
+ && ! TARGET_CM_MEDMID
+ && RTX_OK_FOR_OLO10_P (rs2))
+ {
+ imm2 = rs2;
+ rs2 = NULL;
+ imm1 = XEXP (rs1, 1);
+ rs1 = XEXP (rs1, 0);
+ if (! CONSTANT_P (imm1) || tls_symbolic_operand (rs1))
+ return 0;
+ }
+ }
+ else if (GET_CODE (addr) == LO_SUM)
+ {
+ rs1 = XEXP (addr, 0);
+ imm1 = XEXP (addr, 1);
+
+ if (! CONSTANT_P (imm1) || tls_symbolic_operand (rs1))
+ return 0;
+
+ /* We can't allow TFmode, because an offset greater than or equal to the
+ alignment (8) may cause the LO_SUM to overflow if !v9. */
+ if (mode == TFmode && !TARGET_V9)
+ return 0;
+ }
+ else if (GET_CODE (addr) == CONST_INT && SMALL_INT (addr))
+ return 1;
+ else
+ return 0;
+
+ if (GET_CODE (rs1) == SUBREG)
+ rs1 = SUBREG_REG (rs1);
+ if (!REG_P (rs1))
+ return 0;
+
+ if (rs2)
+ {
+ if (GET_CODE (rs2) == SUBREG)
+ rs2 = SUBREG_REG (rs2);
+ if (!REG_P (rs2))
+ return 0;
+ }
+
+ if (strict)
+ {
+ if (!REGNO_OK_FOR_BASE_P (REGNO (rs1))
+ || (rs2 && !REGNO_OK_FOR_BASE_P (REGNO (rs2))))
+ return 0;
+ }
+ else
+ {
+ if ((REGNO (rs1) >= 32
+ && REGNO (rs1) != FRAME_POINTER_REGNUM
+ && REGNO (rs1) < FIRST_PSEUDO_REGISTER)
+ || (rs2
+ && (REGNO (rs2) >= 32
+ && REGNO (rs2) != FRAME_POINTER_REGNUM
+ && REGNO (rs2) < FIRST_PSEUDO_REGISTER)))
+ return 0;
+ }
+ return 1;
+}
+
+/* Construct the SYMBOL_REF for the tls_get_offset function. */
+
+static GTY(()) rtx sparc_tls_symbol;
+static rtx
+sparc_tls_get_addr (void)
+{
+ if (!sparc_tls_symbol)
+ sparc_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr");
+
+ return sparc_tls_symbol;
+}
+
+static rtx
+sparc_tls_got (void)
+{
+ rtx temp;
+ if (flag_pic)
+ {
+ current_function_uses_pic_offset_table = 1;
+ return pic_offset_table_rtx;
+ }
+
+ if (!global_offset_table)
+ global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
+ temp = gen_reg_rtx (Pmode);
+ emit_move_insn (temp, global_offset_table);
+ return temp;
+}
+
+
+/* ADDR contains a thread-local SYMBOL_REF. Generate code to compute
+ this (thread-local) address. */
+
+rtx
+legitimize_tls_address (rtx addr)
+{
+ rtx temp1, temp2, temp3, ret, o0, got, insn;
+
+ if (no_new_pseudos)
+ abort ();
+
+ if (GET_CODE (addr) == SYMBOL_REF)
+ switch (SYMBOL_REF_TLS_MODEL (addr))
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ start_sequence ();
+ temp1 = gen_reg_rtx (SImode);
+ temp2 = gen_reg_rtx (SImode);
+ ret = gen_reg_rtx (Pmode);
+ o0 = gen_rtx_REG (Pmode, 8);
+ got = sparc_tls_got ();
+ emit_insn (gen_tgd_hi22 (temp1, addr));
+ emit_insn (gen_tgd_lo10 (temp2, temp1, addr));
+ if (TARGET_ARCH32)
+ {
+ emit_insn (gen_tgd_add32 (o0, got, temp2, addr));
+ insn = emit_call_insn (gen_tgd_call32 (o0, sparc_tls_get_addr (),
+ addr, const1_rtx));
+ }
+ else
+ {
+ emit_insn (gen_tgd_add64 (o0, got, temp2, addr));
+ insn = emit_call_insn (gen_tgd_call64 (o0, sparc_tls_get_addr (),
+ addr, const1_rtx));
+ }
+ CALL_INSN_FUNCTION_USAGE (insn)
+ = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_USE (VOIDmode, o0),
+ CALL_INSN_FUNCTION_USAGE (insn));
+ insn = get_insns ();
+ end_sequence ();
+ emit_libcall_block (insn, ret, o0, addr);
+ break;
+
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ start_sequence ();
+ temp1 = gen_reg_rtx (SImode);
+ temp2 = gen_reg_rtx (SImode);
+ temp3 = gen_reg_rtx (Pmode);
+ ret = gen_reg_rtx (Pmode);
+ o0 = gen_rtx_REG (Pmode, 8);
+ got = sparc_tls_got ();
+ emit_insn (gen_tldm_hi22 (temp1));
+ emit_insn (gen_tldm_lo10 (temp2, temp1));
+ if (TARGET_ARCH32)
+ {
+ emit_insn (gen_tldm_add32 (o0, got, temp2));
+ insn = emit_call_insn (gen_tldm_call32 (o0, sparc_tls_get_addr (),
+ const1_rtx));
+ }
+ else
+ {
+ emit_insn (gen_tldm_add64 (o0, got, temp2));
+ insn = emit_call_insn (gen_tldm_call64 (o0, sparc_tls_get_addr (),
+ const1_rtx));
+ }
+ CALL_INSN_FUNCTION_USAGE (insn)
+ = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_USE (VOIDmode, o0),
+ CALL_INSN_FUNCTION_USAGE (insn));
+ insn = get_insns ();
+ end_sequence ();
+ emit_libcall_block (insn, temp3, o0,
+ gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
+ UNSPEC_TLSLD_BASE));
+ temp1 = gen_reg_rtx (SImode);
+ temp2 = gen_reg_rtx (SImode);
+ emit_insn (gen_tldo_hix22 (temp1, addr));
+ emit_insn (gen_tldo_lox10 (temp2, temp1, addr));
+ if (TARGET_ARCH32)
+ emit_insn (gen_tldo_add32 (ret, temp3, temp2, addr));
+ else
+ emit_insn (gen_tldo_add64 (ret, temp3, temp2, addr));
+ break;
+
+ case TLS_MODEL_INITIAL_EXEC:
+ temp1 = gen_reg_rtx (SImode);
+ temp2 = gen_reg_rtx (SImode);
+ temp3 = gen_reg_rtx (Pmode);
+ got = sparc_tls_got ();
+ emit_insn (gen_tie_hi22 (temp1, addr));
+ emit_insn (gen_tie_lo10 (temp2, temp1, addr));
+ if (TARGET_ARCH32)
+ emit_insn (gen_tie_ld32 (temp3, got, temp2, addr));
+ else
+ emit_insn (gen_tie_ld64 (temp3, got, temp2, addr));
+ if (TARGET_SUN_TLS)
+ {
+ ret = gen_reg_rtx (Pmode);
+ if (TARGET_ARCH32)
+ emit_insn (gen_tie_add32 (ret, gen_rtx_REG (Pmode, 7),
+ temp3, addr));
+ else
+ emit_insn (gen_tie_add64 (ret, gen_rtx_REG (Pmode, 7),
+ temp3, addr));
+ }
+ else
+ ret = gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, 7), temp3);
+ break;
+
+ case TLS_MODEL_LOCAL_EXEC:
+ temp1 = gen_reg_rtx (Pmode);
+ temp2 = gen_reg_rtx (Pmode);
+ if (TARGET_ARCH32)
+ {
+ emit_insn (gen_tle_hix22_sp32 (temp1, addr));
+ emit_insn (gen_tle_lox10_sp32 (temp2, temp1, addr));
+ }
+ else
+ {
+ emit_insn (gen_tle_hix22_sp64 (temp1, addr));
+ emit_insn (gen_tle_lox10_sp64 (temp2, temp1, addr));
+ }
+ ret = gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, 7), temp2);
+ break;
+
+ default:
+ abort ();
+ }
+
+ else
+ abort (); /* for now ... */
+
+ return ret;
+}
+
+
/* Legitimize PIC addresses. If the address is already position-independent,
we return ORIG. Newly generated position-independent addresses go into a
reg. This is REG if nonzero, otherwise we allocate register(s) as
necessary. */
rtx
-legitimize_pic_address (orig, mode, reg)
- rtx orig;
- enum machine_mode mode ATTRIBUTE_UNUSED;
- rtx reg;
+legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
+ rtx reg)
{
if (GET_CODE (orig) == SYMBOL_REF)
{
@@ -3272,10 +3730,56 @@ legitimize_pic_address (orig, mode, reg)
return orig;
}
+/* Try machine-dependent ways of modifying an illegitimate address X
+ to be legitimate. If we find one, return the new, valid address.
+
+ OLDX is the address as it was before break_out_memory_refs was called.
+ In some cases it is useful to look at this to decide what needs to be done.
+
+ MODE is the mode of the operand pointed to by X. */
+
+rtx
+legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, enum machine_mode mode)
+{
+ rtx orig_x = x;
+
+ if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT)
+ x = gen_rtx_PLUS (Pmode, XEXP (x, 1),
+ force_operand (XEXP (x, 0), NULL_RTX));
+ if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == MULT)
+ x = gen_rtx_PLUS (Pmode, XEXP (x, 0),
+ force_operand (XEXP (x, 1), NULL_RTX));
+ if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS)
+ x = gen_rtx_PLUS (Pmode, force_operand (XEXP (x, 0), NULL_RTX),
+ XEXP (x, 1));
+ if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == PLUS)
+ x = gen_rtx_PLUS (Pmode, XEXP (x, 0),
+ force_operand (XEXP (x, 1), NULL_RTX));
+
+ if (x != orig_x && legitimate_address_p (mode, x, FALSE))
+ return x;
+
+ if (tls_symbolic_operand (x))
+ x = legitimize_tls_address (x);
+ else if (flag_pic)
+ x = legitimize_pic_address (x, mode, 0);
+ else if (GET_CODE (x) == PLUS && CONSTANT_ADDRESS_P (XEXP (x, 1)))
+ x = gen_rtx_PLUS (Pmode, XEXP (x, 0),
+ copy_to_mode_reg (Pmode, XEXP (x, 1)));
+ else if (GET_CODE (x) == PLUS && CONSTANT_ADDRESS_P (XEXP (x, 0)))
+ x = gen_rtx_PLUS (Pmode, XEXP (x, 1),
+ copy_to_mode_reg (Pmode, XEXP (x, 0)));
+ else if (GET_CODE (x) == SYMBOL_REF
+ || GET_CODE (x) == CONST
+ || GET_CODE (x) == LABEL_REF)
+ x = copy_to_suggested_reg (x, NULL_RTX, Pmode);
+ return x;
+}
+
/* Emit special PIC prologues. */
void
-load_pic_register ()
+load_pic_register (void)
{
/* Labels to get the PC in the prologue of this function. */
int orig_flag_pic = flag_pic;
@@ -3294,7 +3798,7 @@ load_pic_register ()
align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
if (align > 0)
ASM_OUTPUT_ALIGN (asm_out_file, align);
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LGETPC", 0);
+ (*targetm.asm_out.internal_label) (asm_out_file, "LGETPC", 0);
fputs ("\tretl\n\tadd\t%o7, %l7, %l7\n", asm_out_file);
}
@@ -3320,9 +3824,7 @@ load_pic_register ()
least a DESIRED byte boundary. */
int
-mem_min_alignment (mem, desired)
- rtx mem;
- int desired;
+mem_min_alignment (rtx mem, int desired)
{
rtx addr, base, offset;
@@ -3515,7 +4017,7 @@ int sparc_mode_class [NUM_MACHINE_MODES];
enum reg_class sparc_regno_reg_class[FIRST_PSEUDO_REGISTER];
static void
-sparc_init_modes ()
+sparc_init_modes (void)
{
int i;
@@ -3551,16 +4053,13 @@ sparc_init_modes ()
sparc_mode_class[i] = 0;
break;
case MODE_CC:
- default:
- /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
- we must explicitly check for them here. */
if (i == (int) CCFPmode || i == (int) CCFPEmode)
sparc_mode_class[i] = 1 << (int) CCFP_MODE;
- else if (i == (int) CCmode || i == (int) CC_NOOVmode
- || i == (int) CCXmode || i == (int) CCX_NOOVmode)
- sparc_mode_class[i] = 1 << (int) CC_MODE;
else
- sparc_mode_class[i] = 0;
+ sparc_mode_class[i] = 1 << (int) CC_MODE;
+ break;
+ default:
+ sparc_mode_class[i] = 0;
break;
}
}
@@ -3593,13 +4092,8 @@ sparc_init_modes ()
v9 int regs as it simplifies the code. */
static int
-save_regs (file, low, high, base, offset, n_regs, real_offset)
- FILE *file;
- int low, high;
- const char *base;
- int offset;
- int n_regs;
- int real_offset;
+save_regs (FILE *file, int low, int high, const char *base,
+ int offset, int n_regs, HOST_WIDE_INT real_offset)
{
int i;
@@ -3666,12 +4160,8 @@ save_regs (file, low, high, base, offset, n_regs, real_offset)
v9 int regs as it simplifies the code. */
static int
-restore_regs (file, low, high, base, offset, n_regs)
- FILE *file;
- int low, high;
- const char *base;
- int offset;
- int n_regs;
+restore_regs (FILE *file, int low, int high, const char *base,
+ int offset, int n_regs)
{
int i;
@@ -3710,10 +4200,8 @@ restore_regs (file, low, high, base, offset, n_regs)
/* Compute the frame size required by the function. This function is called
during the reload pass and also by output_function_prologue(). */
-int
-compute_frame_size (size, leaf_function)
- int size;
- int leaf_function;
+HOST_WIDE_INT
+compute_frame_size (HOST_WIDE_INT size, int leaf_function)
{
int n_regs = 0, i;
int outgoing_args_size = (current_function_outgoing_args_size
@@ -3767,41 +4255,102 @@ compute_frame_size (size, leaf_function)
return SPARC_STACK_ALIGN (actual_fsize);
}
-/* Build a (32 bit) big number in a register. */
-/* ??? We may be able to use the set macro here too. */
+/* Build big number NUM in register REG and output the result to FILE.
+ REG is guaranteed to be the only clobbered register. The function
+ will very likely emit several instructions, so it must not be called
+ from within a delay slot. */
static void
-build_big_number (file, num, reg)
- FILE *file;
- int num;
- const char *reg;
+build_big_number (FILE *file, HOST_WIDE_INT num, const char *reg)
{
- if (num >= 0 || ! TARGET_ARCH64)
+#if HOST_BITS_PER_WIDE_INT == 64
+ HOST_WIDE_INT high_bits = (num >> 32) & 0xffffffff;
+
+ if (high_bits == 0
+#else
+ if (num >= 0
+#endif
+ || ! TARGET_ARCH64)
{
- fprintf (file, "\tsethi\t%%hi(%d), %s\n", num, reg);
+ /* We don't use the 'set' macro because it appears to be broken
+ in the Solaris 7 assembler. */
+ fprintf (file, "\tsethi\t%%hi("HOST_WIDE_INT_PRINT_DEC"), %s\n",
+ num, reg);
if ((num & 0x3ff) != 0)
- fprintf (file, "\tor\t%s, %%lo(%d), %s\n", reg, num, reg);
+ fprintf (file, "\tor\t%s, %%lo("HOST_WIDE_INT_PRINT_DEC"), %s\n",
+ reg, num, reg);
}
+#if HOST_BITS_PER_WIDE_INT == 64
+ else if (high_bits == 0xffffffff) /* && TARGET_ARCH64 */
+#else
else /* num < 0 && TARGET_ARCH64 */
+#endif
{
/* Sethi does not sign extend, so we must use a little trickery
to use it for negative numbers. Invert the constant before
loading it in, then use xor immediate to invert the loaded bits
(along with the upper 32 bits) to the desired constant. This
works because the sethi and immediate fields overlap. */
- int asize = num;
- int inv = ~asize;
- int low = -0x400 + (asize & 0x3FF);
+ HOST_WIDE_INT inv = ~num;
+ HOST_WIDE_INT low = -0x400 + (num & 0x3ff);
- fprintf (file, "\tsethi\t%%hi(%d), %s\n\txor\t%s, %d, %s\n",
- inv, reg, reg, low, reg);
+ fprintf (file, "\tsethi\t%%hi("HOST_WIDE_INT_PRINT_DEC"), %s\n",
+ inv, reg);
+ fprintf (file, "\txor\t%s, "HOST_WIDE_INT_PRINT_DEC", %s\n",
+ reg, low, reg);
}
+#if HOST_BITS_PER_WIDE_INT == 64
+ else /* TARGET_ARCH64 */
+ {
+ /* We don't use the 'setx' macro because if requires a scratch register.
+ This is the translation of sparc_emit_set_const64_longway into asm.
+ Hopefully we will soon have prologue/epilogue emitted as RTL. */
+ HOST_WIDE_INT low1 = (num >> (32 - 12)) & 0xfff;
+ HOST_WIDE_INT low2 = (num >> (32 - 12 - 12)) & 0xfff;
+ HOST_WIDE_INT low3 = (num >> (32 - 12 - 12 - 8)) & 0x0ff;
+ int to_shift = 12;
+
+ /* We don't use the 'set' macro because it appears to be broken
+ in the Solaris 7 assembler. */
+ fprintf (file, "\tsethi\t%%hi("HOST_WIDE_INT_PRINT_DEC"), %s\n",
+ high_bits, reg);
+ if ((high_bits & 0x3ff) != 0)
+ fprintf (file, "\tor\t%s, %%lo("HOST_WIDE_INT_PRINT_DEC"), %s\n",
+ reg, high_bits, reg);
+
+ if (low1 != 0)
+ {
+ fprintf (file, "\tsllx\t%s, %d, %s\n", reg, to_shift, reg);
+ fprintf (file, "\tor\t%s, "HOST_WIDE_INT_PRINT_DEC", %s\n",
+ reg, low1, reg);
+ to_shift = 12;
+ }
+ else
+ {
+ to_shift += 12;
+ }
+ if (low2 != 0)
+ {
+ fprintf (file, "\tsllx\t%s, %d, %s\n", reg, to_shift, reg);
+ fprintf (file, "\tor\t%s, "HOST_WIDE_INT_PRINT_DEC", %s\n",
+ reg, low2, reg);
+ to_shift = 8;
+ }
+ else
+ {
+ to_shift += 8;
+ }
+ fprintf (file, "\tsllx\t%s, %d, %s\n", reg, to_shift, reg);
+ if (low3 != 0)
+ fprintf (file, "\tor\t%s, "HOST_WIDE_INT_PRINT_DEC", %s\n",
+ reg, low3, reg);
+ }
+#endif
}
/* Output any necessary .register pseudo-ops. */
void
-sparc_output_scratch_registers (file)
- FILE *file ATTRIBUTE_UNUSED;
+sparc_output_scratch_registers (FILE *file ATTRIBUTE_UNUSED)
{
#ifdef HAVE_AS_REGISTER_PSEUDO_OP
int i;
@@ -3841,9 +4390,7 @@ sparc_output_scratch_registers (file)
to do this is made in regclass.c. */
static void
-sparc_output_function_prologue (file, size)
- FILE *file;
- HOST_WIDE_INT size;
+sparc_output_function_prologue (FILE *file, HOST_WIDE_INT size)
{
if (TARGET_FLAT)
sparc_flat_function_prologue (file, size);
@@ -3855,10 +4402,8 @@ sparc_output_function_prologue (file, size)
/* Output code for the function prologue. */
static void
-sparc_nonflat_function_prologue (file, size, leaf_function)
- FILE *file;
- HOST_WIDE_INT size;
- int leaf_function;
+sparc_nonflat_function_prologue (FILE *file, HOST_WIDE_INT size,
+ int leaf_function)
{
sparc_output_scratch_registers (file);
@@ -3885,11 +4430,13 @@ sparc_nonflat_function_prologue (file, size, leaf_function)
else if (! leaf_function)
{
if (actual_fsize <= 4096)
- fprintf (file, "\tsave\t%%sp, -%d, %%sp\n", actual_fsize);
+ fprintf (file, "\tsave\t%%sp, -"HOST_WIDE_INT_PRINT_DEC", %%sp\n",
+ actual_fsize);
else if (actual_fsize <= 8192)
{
fprintf (file, "\tsave\t%%sp, -4096, %%sp\n");
- fprintf (file, "\tadd\t%%sp, -%d, %%sp\n", actual_fsize - 4096);
+ fprintf (file, "\tadd\t%%sp, -"HOST_WIDE_INT_PRINT_DEC", %%sp\n",
+ actual_fsize - 4096);
}
else
{
@@ -3900,11 +4447,13 @@ sparc_nonflat_function_prologue (file, size, leaf_function)
else /* leaf function */
{
if (actual_fsize <= 4096)
- fprintf (file, "\tadd\t%%sp, -%d, %%sp\n", actual_fsize);
+ fprintf (file, "\tadd\t%%sp, -"HOST_WIDE_INT_PRINT_DEC", %%sp\n",
+ actual_fsize);
else if (actual_fsize <= 8192)
{
fprintf (file, "\tadd\t%%sp, -4096, %%sp\n");
- fprintf (file, "\tadd\t%%sp, -%d, %%sp\n", actual_fsize - 4096);
+ fprintf (file, "\tadd\t%%sp, -"HOST_WIDE_INT_PRINT_DEC", %%sp\n",
+ actual_fsize - 4096);
}
else
{
@@ -3941,7 +4490,8 @@ sparc_nonflat_function_prologue (file, size, leaf_function)
/* Call saved registers are saved just above the outgoing argument area. */
if (num_gfregs)
{
- int offset, real_offset, n_regs;
+ HOST_WIDE_INT offset, real_offset;
+ int n_regs;
const char *base;
real_offset = -apparent_fsize;
@@ -3973,11 +4523,10 @@ sparc_nonflat_function_prologue (file, size, leaf_function)
/* Output code to restore any call saved registers. */
static void
-output_restore_regs (file, leaf_function)
- FILE *file;
- int leaf_function ATTRIBUTE_UNUSED;
+output_restore_regs (FILE *file, int leaf_function ATTRIBUTE_UNUSED)
{
- int offset, n_regs;
+ HOST_WIDE_INT offset;
+ int n_regs;
const char *base;
offset = -apparent_fsize + frame_base_offset;
@@ -4006,9 +4555,7 @@ output_restore_regs (file, leaf_function)
before returning. */
static void
-sparc_output_function_epilogue (file, size)
- FILE *file;
- HOST_WIDE_INT size;
+sparc_output_function_epilogue (FILE *file, HOST_WIDE_INT size)
{
if (TARGET_FLAT)
sparc_flat_function_epilogue (file, size);
@@ -4020,10 +4567,9 @@ sparc_output_function_epilogue (file, size)
/* Output code for the function epilogue. */
static void
-sparc_nonflat_function_epilogue (file, size, leaf_function)
- FILE *file;
- HOST_WIDE_INT size ATTRIBUTE_UNUSED;
- int leaf_function;
+sparc_nonflat_function_epilogue (FILE *file,
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED,
+ int leaf_function)
{
const char *ret;
@@ -4088,7 +4634,7 @@ sparc_nonflat_function_epilogue (file, size, leaf_function)
? "\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);
+ file, 1, 0, 0, NULL);
}
else
{
@@ -4113,7 +4659,7 @@ sparc_nonflat_function_epilogue (file, size, leaf_function)
insn = emit_jump_insn (insn);
sparc_emitting_epilogue = true;
- final_scan_insn (insn, file, 1, 0, 1);
+ final_scan_insn (insn, file, 1, 0, 1, NULL);
sparc_emitting_epilogue = false;
}
}
@@ -4135,23 +4681,23 @@ sparc_nonflat_function_epilogue (file, size, leaf_function)
abort ();
fprintf (file, "\t%s\n", ret);
final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
- file, 1, 0, 1);
+ file, 1, 0, 1, NULL);
}
/* 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);
+ fprintf (file, "\t%s\n\tsub\t%%sp, -"HOST_WIDE_INT_PRINT_DEC", %%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",
+ fprintf (file, "\tsub\t%%sp, -4096, %%sp\n\t%s\n\tsub\t%%sp, -"HOST_WIDE_INT_PRINT_DEC", %%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);
+ else
+ {
+ build_big_number (file, actual_fsize, "%g1");
+ fprintf (file, "\t%s\n\tadd\t%%sp, %%g1, %%sp\n", ret);
+ }
output_vectors:
sparc_output_deferred_case_vectors ();
@@ -4160,8 +4706,7 @@ sparc_nonflat_function_epilogue (file, size, leaf_function)
/* Output a sibling call. */
const char *
-output_sibcall (insn, call_operand)
- rtx insn, call_operand;
+output_sibcall (rtx insn, rtx call_operand)
{
int leaf_regs = current_function_uses_only_leaf_regs;
rtx operands[3];
@@ -4179,7 +4724,7 @@ output_sibcall (insn, call_operand)
if (! delay)
abort ();
- final_scan_insn (delay, asm_out_file, 1, 0, 1);
+ final_scan_insn (delay, asm_out_file, 1, 0, 1, NULL);
PATTERN (delay) = gen_blockage ();
INSN_CODE (delay) = -1;
delay_slot = 0;
@@ -4200,7 +4745,7 @@ output_sibcall (insn, call_operand)
#else
int spare_slot = ((TARGET_ARCH32 || TARGET_CM_MEDLOW) && ! flag_pic);
#endif
- int size = 0;
+ HOST_WIDE_INT size = 0;
if ((actual_fsize || ! spare_slot) && delay_slot)
{
@@ -4209,7 +4754,7 @@ output_sibcall (insn, call_operand)
if (! delay)
abort ();
- final_scan_insn (delay, asm_out_file, 1, 0, 1);
+ final_scan_insn (delay, asm_out_file, 1, 0, 1, NULL);
PATTERN (delay) = gen_blockage ();
INSN_CODE (delay) = -1;
delay_slot = 0;
@@ -4223,15 +4768,9 @@ output_sibcall (insn, call_operand)
fputs ("\tsub\t%sp, -4096, %sp\n", asm_out_file);
size = actual_fsize - 4096;
}
- else if ((actual_fsize & 0x3ff) == 0)
- fprintf (asm_out_file,
- "\tsethi\t%%hi(%d), %%g1\n\tadd\t%%sp, %%g1, %%sp\n",
- actual_fsize);
else
{
- fprintf (asm_out_file,
- "\tsethi\t%%hi(%d), %%g1\n\tor\t%%g1, %%lo(%d), %%g1\n",
- actual_fsize, actual_fsize);
+ build_big_number (asm_out_file, actual_fsize, "%g1");
fputs ("\tadd\t%%sp, %%g1, %%sp\n", asm_out_file);
}
}
@@ -4240,14 +4779,14 @@ output_sibcall (insn, call_operand)
output_asm_insn ("sethi\t%%hi(%a0), %%g1", operands);
output_asm_insn ("jmpl\t%%g1 + %%lo(%a0), %%g0", operands);
if (size)
- fprintf (asm_out_file, "\t sub\t%%sp, -%d, %%sp\n", size);
+ fprintf (asm_out_file, "\t sub\t%%sp, -"HOST_WIDE_INT_PRINT_DEC", %%sp\n", size);
else if (! delay_slot)
fputs ("\t nop\n", asm_out_file);
}
else
{
if (size)
- fprintf (asm_out_file, "\tsub\t%%sp, -%d, %%sp\n", size);
+ fprintf (asm_out_file, "\tsub\t%%sp, -"HOST_WIDE_INT_PRINT_DEC", %%sp\n", size);
/* Use or with rs2 %%g0 instead of mov, so that as/ld can optimize
it into branch if possible. */
output_asm_insn ("or\t%%o7, %%g0, %%g1", operands);
@@ -4363,19 +4902,48 @@ output_sibcall (insn, call_operand)
For a library call, FNTYPE is 0. */
void
-init_cumulative_args (cum, fntype, libname, indirect)
- CUMULATIVE_ARGS *cum;
- tree fntype;
- rtx libname ATTRIBUTE_UNUSED;
- int indirect ATTRIBUTE_UNUSED;
+init_cumulative_args (struct sparc_args *cum, tree fntype,
+ rtx libname ATTRIBUTE_UNUSED,
+ tree fndecl ATTRIBUTE_UNUSED)
{
cum->words = 0;
cum->prototype_p = fntype && TYPE_ARG_TYPES (fntype);
cum->libcall_p = fntype == 0;
}
+/* Scan the record type TYPE and return the following predicates:
+ - INTREGS_P: the record contains at least one field or sub-field
+ that is eligible for promotion in integer registers.
+ - FP_REGS_P: the record contains at least one field or sub-field
+ that is eligible for promotion in floating-point registers.
+ - PACKED_P: the record contains at least one field that is packed.
+
+ Sub-fields are not taken into account for the PACKED_P predicate. */
+
+static void
+scan_record_type (tree type, int *intregs_p, int *fpregs_p, int *packed_p)
+{
+ tree field;
+
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ if (TREE_CODE (field) == FIELD_DECL)
+ {
+ if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
+ scan_record_type (TREE_TYPE (field), intregs_p, fpregs_p, 0);
+ else if (FLOAT_TYPE_P (TREE_TYPE (field)) && TARGET_FPU)
+ *fpregs_p = 1;
+ else
+ *intregs_p = 1;
+
+ if (packed_p && DECL_PACKED (field))
+ *packed_p = 1;
+ }
+ }
+}
+
/* Compute the slot number to pass an argument in.
- Returns the slot number or -1 if passing on the stack.
+ Return the slot number or -1 if passing on the stack.
CUM is a variable of type CUMULATIVE_ARGS which gives info about
the preceding args and about the function being called.
@@ -4390,14 +4958,9 @@ init_cumulative_args (cum, fntype, libname, indirect)
*PPADDING records the amount of padding needed in words. */
static int
-function_arg_slotno (cum, mode, type, named, incoming_p, pregno, ppadding)
- const CUMULATIVE_ARGS *cum;
- enum machine_mode mode;
- tree type;
- int named;
- int incoming_p;
- int *pregno;
- int *ppadding;
+function_arg_slotno (const struct sparc_args *cum, enum machine_mode mode,
+ tree type, int named, int incoming_p,
+ int *pregno, int *ppadding)
{
int regbase = (incoming_p
? SPARC_INCOMING_INT_ARG_FIRST
@@ -4421,19 +4984,27 @@ function_arg_slotno (cum, mode, type, named, incoming_p, pregno, ppadding)
See emit_call_1. */
return -1;
+ case TImode : case CTImode :
+ if (TARGET_ARCH64 && (slotno & 1) != 0)
+ slotno++, *ppadding = 1;
+ /* fallthrough */
+
case QImode : case CQImode :
case HImode : case CHImode :
case SImode : case CSImode :
case DImode : case CDImode :
- case TImode : case CTImode :
if (slotno >= SPARC_INT_ARG_MAX)
return -1;
regno = regbase + slotno;
break;
+ case TFmode : case TCmode :
+ if (TARGET_ARCH64 && (slotno & 1) != 0)
+ slotno++, *ppadding = 1;
+ /* fallthrough */
+
case SFmode : case SCmode :
case DFmode : case DCmode :
- case TFmode : case TCmode :
if (TARGET_ARCH32)
{
if (slotno >= SPARC_INT_ARG_MAX)
@@ -4442,9 +5013,6 @@ function_arg_slotno (cum, mode, type, named, incoming_p, pregno, ppadding)
}
else
{
- if ((mode == TFmode || mode == TCmode)
- && (slotno & 1) != 0)
- slotno++, *ppadding = 1;
if (TARGET_FPU && named)
{
if (slotno >= SPARC_FP_ARG_MAX)
@@ -4479,27 +5047,14 @@ function_arg_slotno (cum, mode, type, named, incoming_p, pregno, ppadding)
}
else
{
- tree field;
- int intregs_p = 0, fpregs_p = 0;
- /* The ABI obviously doesn't specify how packed
- structures are passed. These are defined to be passed
- in int regs if possible, otherwise memory. */
- int packed_p = 0;
+ int intregs_p = 0, fpregs_p = 0, packed_p = 0;
- /* First see what kinds of registers we need. */
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- {
- if (TREE_CODE (field) == FIELD_DECL)
- {
- if (TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
- && TARGET_FPU)
- fpregs_p = 1;
- else
- intregs_p = 1;
- if (DECL_PACKED (field))
- packed_p = 1;
- }
- }
+ /* First see what kinds of registers we would need. */
+ scan_record_type (type, &intregs_p, &fpregs_p, &packed_p);
+
+ /* The ABI obviously doesn't specify how packed structures
+ are passed. These are defined to be passed in int regs
+ if possible, otherwise memory. */
if (packed_p || !named)
fpregs_p = 0, intregs_p = 1;
@@ -4535,49 +5090,45 @@ struct function_arg_record_value_parms
int named; /* whether the argument is named. */
int regbase; /* regno of the base register. */
int stack; /* 1 if part of the argument is on the stack. */
- int intoffset; /* offset of the pending integer field. */
+ int intoffset; /* offset of the first pending integer field. */
unsigned int nregs; /* number of words passed in registers. */
};
static void function_arg_record_value_3
- PARAMS ((HOST_WIDE_INT, struct function_arg_record_value_parms *));
+ (HOST_WIDE_INT, struct function_arg_record_value_parms *);
static void function_arg_record_value_2
- PARAMS ((tree, HOST_WIDE_INT,
- struct function_arg_record_value_parms *));
+ (tree, HOST_WIDE_INT, struct function_arg_record_value_parms *, bool);
static void function_arg_record_value_1
- PARAMS ((tree, HOST_WIDE_INT,
- struct function_arg_record_value_parms *));
-static rtx function_arg_record_value
- PARAMS ((tree, enum machine_mode, int, int, int));
+ (tree, HOST_WIDE_INT, struct function_arg_record_value_parms *, bool);
+static rtx function_arg_record_value (tree, enum machine_mode, int, int, int);
+static rtx function_arg_union_value (int, enum machine_mode, int);
/* A subroutine of function_arg_record_value. Traverse the structure
- recusively and determine how many registers will be required. */
+ recursively and determine how many registers will be required. */
static void
-function_arg_record_value_1 (type, startbitpos, parms)
- tree type;
- HOST_WIDE_INT startbitpos;
- struct function_arg_record_value_parms *parms;
+function_arg_record_value_1 (tree type, HOST_WIDE_INT startbitpos,
+ struct function_arg_record_value_parms *parms,
+ bool packed_p)
{
tree field;
- /* The ABI obviously doesn't specify how packed structures are
- passed. These are defined to be passed in int regs if possible,
- otherwise memory. */
- int packed_p = 0;
-
/* We need to compute how many registers are needed so we can
allocate the PARALLEL but before we can do that we need to know
- whether there are any packed fields. If there are, int regs are
- used regardless of whether there are fp values present. */
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- {
- if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
- {
- packed_p = 1;
- break;
- }
- }
+ whether there are any packed fields. The ABI obviously doesn't
+ specify how structures are passed in this case, so they are
+ defined to be passed in int regs if possible, otherwise memory,
+ regardless of whether there are fp values present. */
+
+ if (! packed_p)
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
+ {
+ packed_p = true;
+ break;
+ }
+ }
/* Compute how many registers we need. */
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
@@ -4593,21 +5144,24 @@ function_arg_record_value_1 (type, startbitpos, parms)
/* ??? FIXME: else assume zero offset. */
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
- || (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE
- && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
- == REAL_TYPE)))
- && TARGET_FPU
- && ! packed_p
- && parms->named)
+ function_arg_record_value_1 (TREE_TYPE (field),
+ bitpos,
+ parms,
+ packed_p);
+ else if (FLOAT_TYPE_P (TREE_TYPE (field))
+ && TARGET_FPU
+ && parms->named
+ && ! packed_p)
{
if (parms->intoffset != -1)
{
+ unsigned int startbit, endbit;
int intslots, this_slotno;
- intslots = (bitpos - parms->intoffset + BITS_PER_WORD - 1)
- / BITS_PER_WORD;
+ startbit = parms->intoffset & -BITS_PER_WORD;
+ endbit = (bitpos + BITS_PER_WORD - 1) & -BITS_PER_WORD;
+
+ intslots = (endbit - startbit) / BITS_PER_WORD;
this_slotno = parms->slotno + parms->intoffset
/ BITS_PER_WORD;
@@ -4641,9 +5195,8 @@ function_arg_record_value_1 (type, startbitpos, parms)
structure between parms->intoffset and bitpos to integer registers. */
static void
-function_arg_record_value_3 (bitpos, parms)
- HOST_WIDE_INT bitpos;
- struct function_arg_record_value_parms *parms;
+function_arg_record_value_3 (HOST_WIDE_INT bitpos,
+ struct function_arg_record_value_parms *parms)
{
enum machine_mode mode;
unsigned int regno;
@@ -4687,6 +5240,7 @@ function_arg_record_value_3 (bitpos, parms)
this_slotno += 1;
intoffset = (intoffset | (UNITS_PER_WORD-1)) + 1;
+ mode = word_mode;
parms->nregs += 1;
intslots -= 1;
}
@@ -4699,22 +5253,21 @@ function_arg_record_value_3 (bitpos, parms)
to make that happen. */
static void
-function_arg_record_value_2 (type, startbitpos, parms)
- tree type;
- HOST_WIDE_INT startbitpos;
- struct function_arg_record_value_parms *parms;
+function_arg_record_value_2 (tree type, HOST_WIDE_INT startbitpos,
+ struct function_arg_record_value_parms *parms,
+ bool packed_p)
{
tree field;
- int packed_p = 0;
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- {
- if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
- {
- packed_p = 1;
- break;
- }
- }
+ if (! packed_p)
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
+ {
+ packed_p = true;
+ break;
+ }
+ }
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
@@ -4729,14 +5282,14 @@ function_arg_record_value_2 (type, startbitpos, parms)
/* ??? FIXME: else assume zero offset. */
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
- || (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE
- && (TREE_CODE (TREE_TYPE (TREE_TYPE (field)))
- == REAL_TYPE)))
- && TARGET_FPU
- && ! packed_p
- && parms->named)
+ function_arg_record_value_2 (TREE_TYPE (field),
+ bitpos,
+ parms,
+ packed_p);
+ else if (FLOAT_TYPE_P (TREE_TYPE (field))
+ && TARGET_FPU
+ && parms->named
+ && ! packed_p)
{
int this_slotno = parms->slotno + bitpos / BITS_PER_WORD;
int regno;
@@ -4794,10 +5347,8 @@ function_arg_record_value_2 (type, startbitpos, parms)
REGBASE is the regno of the base register for the parameter array. */
static rtx
-function_arg_record_value (type, mode, slotno, named, regbase)
- tree type;
- enum machine_mode mode;
- int slotno, named, regbase;
+function_arg_record_value (tree type, enum machine_mode mode,
+ int slotno, int named, int regbase)
{
HOST_WIDE_INT typesize = int_size_in_bytes (type);
struct function_arg_record_value_parms parms;
@@ -4812,8 +5363,9 @@ function_arg_record_value (type, mode, slotno, named, regbase)
/* Compute how many registers we need. */
parms.nregs = 0;
parms.intoffset = 0;
- function_arg_record_value_1 (type, 0, &parms);
+ function_arg_record_value_1 (type, 0, &parms, false);
+ /* Take into account pending integer fields. */
if (parms.intoffset != -1)
{
unsigned int startbit, endbit;
@@ -4874,7 +5426,7 @@ function_arg_record_value (type, mode, slotno, named, regbase)
/* Fill in the entries. */
parms.nregs = 0;
parms.intoffset = 0;
- function_arg_record_value_2 (type, 0, &parms);
+ function_arg_record_value_2 (type, 0, &parms, false);
function_arg_record_value_3 (typesize * BITS_PER_UNIT, &parms);
if (parms.nregs != nregs)
@@ -4883,6 +5435,33 @@ function_arg_record_value (type, mode, slotno, named, regbase)
return parms.ret;
}
+/* Used by function_arg and function_value to implement the conventions
+ of the 64-bit ABI for passing and returning unions.
+ Return an expression valid as a return value for the two macros
+ FUNCTION_ARG and FUNCTION_VALUE.
+
+ SIZE is the size in bytes of the union.
+ MODE is the argument's machine mode.
+ REGNO is the hard register the union will be passed in. */
+
+static rtx
+function_arg_union_value (int size, enum machine_mode mode, int regno)
+{
+ int nwords = ROUND_ADVANCE (size), i;
+ rtx regs;
+
+ /* Unions are passed left-justified. */
+ regs = gen_rtx_PARALLEL (mode, rtvec_alloc (nwords));
+
+ for (i = 0; i < nwords; i++)
+ XVECEXP (regs, 0, i)
+ = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (word_mode, regno + i),
+ GEN_INT (UNITS_PER_WORD * i));
+
+ return regs;
+}
+
/* Handle the FUNCTION_ARG macro.
Determine where to put an argument to a function.
Value is zero to push the argument on the stack,
@@ -4899,12 +5478,8 @@ function_arg_record_value (type, mode, slotno, named, regbase)
INCOMING_P is zero for FUNCTION_ARG, nonzero for FUNCTION_INCOMING_ARG. */
rtx
-function_arg (cum, mode, type, named, incoming_p)
- const CUMULATIVE_ARGS *cum;
- enum machine_mode mode;
- tree type;
- int named;
- int incoming_p;
+function_arg (const struct sparc_args *cum, enum machine_mode mode,
+ tree type, int named, int incoming_p)
{
int regbase = (incoming_p
? SPARC_INCOMING_INT_ARG_FIRST
@@ -4923,13 +5498,32 @@ function_arg (cum, mode, type, named, incoming_p)
reg = gen_rtx_REG (mode, regno);
return reg;
}
+
+ if (type && TREE_CODE (type) == RECORD_TYPE)
+ {
+ /* Structures up to 16 bytes in size are passed in arg slots on the
+ stack and are promoted to registers where possible. */
+ if (int_size_in_bytes (type) > 16)
+ abort (); /* shouldn't get here */
+
+ return function_arg_record_value (type, mode, slotno, named, regbase);
+ }
+ else if (type && TREE_CODE (type) == UNION_TYPE)
+ {
+ HOST_WIDE_INT size = int_size_in_bytes (type);
+
+ if (size > 16)
+ abort (); /* shouldn't get here */
+
+ return function_arg_union_value (size, mode, regno);
+ }
/* v9 fp args in reg slots beyond the int reg slots get passed in regs
but also have the slot allocated for them.
If no prototype is in scope fp values in register slots get passed
in two places, either fp regs and int regs or fp regs and memory. */
- if ((GET_MODE_CLASS (mode) == MODE_FLOAT
- || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
+ else if ((GET_MODE_CLASS (mode) == MODE_FLOAT
+ || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
&& SPARC_FP_REG_P (regno))
{
reg = gen_rtx_REG (mode, regno);
@@ -4958,7 +5552,7 @@ function_arg (cum, mode, type, named, incoming_p)
This is due to locate_and_pad_parm being called in
expand_call whenever reg_parm_stack_space > 0, which
- while benefical to our example here, would seem to be
+ while beneficial to our example here, would seem to be
in error from what had been intended. Ho hum... -- r~ */
#endif
return reg;
@@ -4993,27 +5587,6 @@ function_arg (cum, mode, type, named, incoming_p)
}
}
}
- else if (type && TREE_CODE (type) == RECORD_TYPE)
- {
- /* Structures up to 16 bytes in size are passed in arg slots on the
- stack and are promoted to registers where possible. */
-
- if (int_size_in_bytes (type) > 16)
- abort (); /* shouldn't get here */
-
- return function_arg_record_value (type, mode, slotno, named, regbase);
- }
- else if (type && TREE_CODE (type) == UNION_TYPE)
- {
- enum machine_mode mode;
- int bytes = int_size_in_bytes (type);
-
- if (bytes > 16)
- abort ();
-
- mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 0);
- reg = gen_rtx_REG (mode, regno);
- }
else
{
/* Scalar or complex int. */
@@ -5035,11 +5608,8 @@ function_arg (cum, mode, type, named, incoming_p)
mode] will be split between that reg and memory. */
int
-function_arg_partial_nregs (cum, mode, type, named)
- const CUMULATIVE_ARGS *cum;
- enum machine_mode mode;
- tree type;
- int named;
+function_arg_partial_nregs (const struct sparc_args *cum,
+ enum machine_mode mode, tree type, int named)
{
int slotno, regno, padding;
@@ -5073,11 +5643,17 @@ function_arg_partial_nregs (cum, mode, type, named)
}
else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
|| (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
- && ! TARGET_FPU))
+ && ! (TARGET_FPU && named)))
{
+ /* The complex types are passed as packed types. */
+ if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
+ return 0;
+
if (GET_MODE_ALIGNMENT (mode) == 128)
{
slotno += slotno & 1;
+
+ /* ??? The mode needs 3 slots? */
if (slotno == SPARC_INT_ARG_MAX - 2)
return 1;
}
@@ -5106,21 +5682,21 @@ function_arg_partial_nregs (cum, mode, type, named)
For Pascal, also pass arrays by reference. */
int
-function_arg_pass_by_reference (cum, mode, type, named)
- const CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
- enum machine_mode mode;
- tree type;
- int named ATTRIBUTE_UNUSED;
+function_arg_pass_by_reference (const struct sparc_args *cum ATTRIBUTE_UNUSED,
+ enum machine_mode mode, tree type,
+ int named ATTRIBUTE_UNUSED)
{
if (TARGET_ARCH32)
{
return ((type && AGGREGATE_TYPE_P (type))
- || mode == TFmode || mode == TCmode);
+ || mode == SCmode
+ || GET_MODE_SIZE (mode) > 8);
}
else
{
return ((type && TREE_CODE (type) == ARRAY_TYPE)
- /* Consider complex values as aggregates, so care for TCmode. */
+ /* Consider complex values as aggregates, so care
+ for CTImode and TCmode. */
|| GET_MODE_SIZE (mode) > 16
|| (type
&& AGGREGATE_TYPE_P (type)
@@ -5134,11 +5710,8 @@ function_arg_pass_by_reference (cum, mode, type, named)
TYPE is null for libcalls where that information may not be available. */
void
-function_arg_advance (cum, mode, type, named)
- CUMULATIVE_ARGS *cum;
- enum machine_mode mode;
- tree type;
- int named;
+function_arg_advance (struct sparc_args *cum, enum machine_mode mode,
+ tree type, int named)
{
int slotno, regno, padding;
@@ -5168,14 +5741,6 @@ function_arg_advance (cum, mode, type, named)
else /* passed by reference */
++cum->words;
}
- else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
- {
- cum->words += 2;
- }
- else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
- {
- cum->words += GET_MODE_SIZE (mode) / UNITS_PER_WORD;
- }
else
{
cum->words += (mode != BLKmode
@@ -5190,21 +5755,13 @@ function_arg_advance (cum, mode, type, named)
argument slot. */
enum direction
-function_arg_padding (mode, type)
- enum machine_mode mode;
- tree type;
+function_arg_padding (enum machine_mode mode, tree type)
{
if (TARGET_ARCH64 && type != 0 && AGGREGATE_TYPE_P (type))
return upward;
- /* This is the default definition. */
- return (! BYTES_BIG_ENDIAN
- ? upward
- : ((mode == BLKmode
- ? (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
- && int_size_in_bytes (type) < (PARM_BOUNDARY / BITS_PER_UNIT))
- : GET_MODE_BITSIZE (mode) < PARM_BOUNDARY)
- ? downward : upward));
+ /* Fall back to the default. */
+ return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
}
/* Handle FUNCTION_VALUE, FUNCTION_OUTGOING_VALUE, and LIBCALL_VALUE macros.
@@ -5212,18 +5769,16 @@ function_arg_padding (mode, type)
except that up to 32-bytes may be returned in registers. */
rtx
-function_value (type, mode, incoming_p)
- tree type;
- enum machine_mode mode;
- int incoming_p;
+function_value (tree type, enum machine_mode mode, int incoming_p)
{
int regno;
- int regbase = (incoming_p
- ? SPARC_OUTGOING_INT_ARG_FIRST
- : SPARC_INCOMING_INT_ARG_FIRST);
if (TARGET_ARCH64 && type)
{
+ int regbase = (incoming_p
+ ? SPARC_OUTGOING_INT_ARG_FIRST
+ : SPARC_INCOMING_INT_ARG_FIRST);
+
if (TREE_CODE (type) == RECORD_TYPE)
{
/* Structures up to 32 bytes in size are passed in registers,
@@ -5234,6 +5789,15 @@ function_value (type, mode, incoming_p)
return function_arg_record_value (type, mode, 0, 1, regbase);
}
+ else if (TREE_CODE (type) == UNION_TYPE)
+ {
+ HOST_WIDE_INT size = int_size_in_bytes (type);
+
+ if (size > 32)
+ abort (); /* shouldn't get here */
+
+ return function_arg_union_value (size, mode, regbase);
+ }
else if (AGGREGATE_TYPE_P (type))
{
/* All other aggregate types are passed in an integer register
@@ -5244,14 +5808,23 @@ function_value (type, mode, incoming_p)
abort ();
mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 0);
+
+ /* ??? We probably should have made the same ABI change in
+ 3.4.0 as the one we made for unions. The latter was
+ required by the SCD though, while the former is not
+ specified, so we favored compatibility and efficiency.
+
+ Now we're stuck for aggregates larger than 16 bytes,
+ because OImode vanished in the meantime. Let's not
+ try to be unduly clever, and simply follow the ABI
+ for unions in that case. */
+ if (mode == BLKmode)
+ return function_arg_union_value (bytes, mode, regbase);
}
+ else if (GET_MODE_CLASS (mode) == MODE_INT
+ && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+ mode = word_mode;
}
-
- if (TARGET_ARCH64
- && GET_MODE_CLASS (mode) == MODE_INT
- && GET_MODE_SIZE (mode) < UNITS_PER_WORD
- && type && ! AGGREGATE_TYPE_P (type))
- mode = DImode;
if (incoming_p)
regno = BASE_RETURN_VALUE_REG (mode);
@@ -5266,7 +5839,7 @@ function_value (type, mode, incoming_p)
the first unnamed parameter. */
rtx
-sparc_builtin_saveregs ()
+sparc_builtin_saveregs (void)
{
int first_reg = current_function_args_info.words;
rtx address;
@@ -5293,9 +5866,7 @@ sparc_builtin_saveregs ()
/* Implement `va_start' for varargs and stdarg. */
void
-sparc_va_start (valist, nextarg)
- tree valist;
- rtx nextarg;
+sparc_va_start (tree valist, rtx nextarg)
{
nextarg = expand_builtin_saveregs ();
std_expand_builtin_va_start (valist, nextarg);
@@ -5304,8 +5875,7 @@ sparc_va_start (valist, nextarg)
/* Implement `va_arg'. */
rtx
-sparc_va_arg (valist, type)
- tree valist, type;
+sparc_va_arg (tree valist, tree type)
{
HOST_WIDE_INT size, rsize, align;
tree addr, incr;
@@ -5322,16 +5892,19 @@ sparc_va_arg (valist, type)
if (TYPE_ALIGN (type) >= 2 * (unsigned) BITS_PER_WORD)
align = 2 * UNITS_PER_WORD;
- if (AGGREGATE_TYPE_P (type))
+ /* Consider complex values as aggregates, so care
+ for CTImode and TCmode. */
+ if ((unsigned HOST_WIDE_INT) 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)
+ indirect = 1;
+ size = rsize = UNITS_PER_WORD;
+ align = 0;
+ }
+ else if (AGGREGATE_TYPE_P (type))
+ {
+ /* SPARC-V9 ABI states that structures up to 16 bytes in size
+ are given whole slots as needed. */
+ if (size == 0)
size = rsize = UNITS_PER_WORD;
else
size = rsize;
@@ -5340,8 +5913,8 @@ sparc_va_arg (valist, type)
else
{
if (AGGREGATE_TYPE_P (type)
- || TYPE_MODE (type) == TFmode
- || TYPE_MODE (type) == TCmode)
+ || TYPE_MODE (type) == SCmode
+ || GET_MODE_SIZE (TYPE_MODE (type)) > 8)
{
indirect = 1;
size = rsize = UNITS_PER_WORD;
@@ -5414,25 +5987,81 @@ sparc_va_arg (valist, type)
return addr_rtx;
}
+/* Return the string to output an unconditional branch to LABEL, which is
+ the operand number of the label.
+
+ DEST is the destination insn (i.e. the label), INSN is the source. */
+
+const char *
+output_ubranch (rtx dest, int label, rtx insn)
+{
+ static char string[64];
+ bool noop = false;
+ char *p;
+
+ /* TurboSPARC is reported to have problems with
+ with
+ foo: b,a foo
+ i.e. an empty loop with the annul bit set. The workaround is to use
+ foo: b foo; nop
+ instead. */
+
+ if (! TARGET_V9 && flag_delayed_branch
+ && (INSN_ADDRESSES (INSN_UID (dest))
+ == INSN_ADDRESSES (INSN_UID (insn))))
+ {
+ strcpy (string, "b\t");
+ noop = true;
+ }
+ else
+ {
+ bool v9_form = false;
+
+ if (TARGET_V9 && INSN_ADDRESSES_SET_P ())
+ {
+ int delta = (INSN_ADDRESSES (INSN_UID (dest))
+ - INSN_ADDRESSES (INSN_UID (insn)));
+ /* Leave some instructions for "slop". */
+ if (delta >= -260000 && delta < 260000)
+ v9_form = true;
+ }
+
+ if (v9_form)
+ strcpy (string, "ba%*,pt\t%%xcc, ");
+ else
+ strcpy (string, "b%*\t");
+ }
+
+ p = strchr (string, '\0');
+ *p++ = '%';
+ *p++ = 'l';
+ *p++ = '0' + label;
+ *p++ = '%';
+ if (noop)
+ *p++ = '#';
+ else
+ *p++ = '(';
+ *p = '\0';
+
+ return string;
+}
+
/* Return the string to output a conditional branch to LABEL, which is
the operand number of the label. OP is the conditional expression.
XEXP (OP, 0) is assumed to be a condition code register (integer or
floating point) and its mode specifies what kind of comparison we made.
+ DEST is the destination insn (i.e. the label), INSN is the source.
+
REVERSED is nonzero if we should reverse the sense of the comparison.
ANNUL is nonzero if we should generate an annulling branch.
- NOOP is nonzero if we have to follow this branch by a noop.
-
- INSN, if set, is the insn. */
+ NOOP is nonzero if we have to follow this branch by a noop. */
char *
-output_cbranch (op, dest, label, reversed, annul, noop, insn)
- rtx op, dest;
- int label;
- int reversed, annul, noop;
- rtx insn;
+output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
+ int noop, rtx insn)
{
static char string[50];
enum rtx_code code = GET_CODE (op);
@@ -5463,7 +6092,7 @@ output_cbranch (op, dest, label, reversed, annul, noop, insn)
nop
ba .LC29 */
- far = get_attr_length (insn) >= 3;
+ far = TARGET_V9 && (get_attr_length (insn) >= 3);
if (reversed ^ far)
{
/* Reversal of FP compares takes care -- an ordered compare
@@ -5593,9 +6222,7 @@ output_cbranch (op, dest, label, reversed, annul, noop, insn)
spaces -= 2;
}
- if (! TARGET_V9)
- labelno = "";
- else
+ if (TARGET_V9)
{
rtx note;
int v8 = 0;
@@ -5645,6 +6272,9 @@ output_cbranch (op, dest, label, reversed, annul, noop, insn)
spaces -= 3;
}
}
+ else
+ labelno = "";
+
if (spaces > 0)
*p++ = '\t';
else
@@ -5676,9 +6306,7 @@ output_cbranch (op, dest, label, reversed, annul, noop, insn)
values as arguments instead of the TFmode registers themselves,
that's why we cannot call emit_float_lib_cmp. */
void
-sparc_emit_float_lib_cmp (x, y, comparison)
- rtx x, y;
- enum rtx_code comparison;
+sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison)
{
const char *qpfunc;
rtx slot0, slot1, result, tem, tem2;
@@ -5815,8 +6443,7 @@ sparc_emit_float_lib_cmp (x, y, comparison)
optabs would emit if we didn't have TFmode patterns. */
void
-sparc_emit_floatunsdi (operands)
- rtx operands[2];
+sparc_emit_floatunsdi (rtx *operands)
{
rtx neglab, donelab, i0, i1, f0, in, out;
enum machine_mode mode;
@@ -5852,6 +6479,8 @@ sparc_emit_floatunsdi (operands)
operand number of the reg. OP is the conditional expression. The mode
of REG says what kind of comparison we made.
+ DEST is the destination insn (i.e. the label), INSN is the source.
+
REVERSED is nonzero if we should reverse the sense of the comparison.
ANNUL is nonzero if we should generate an annulling branch.
@@ -5859,11 +6488,8 @@ sparc_emit_floatunsdi (operands)
NOOP is nonzero if we have to follow this branch by a noop. */
char *
-output_v9branch (op, dest, reg, label, reversed, annul, noop, insn)
- rtx op, dest;
- int reg, label;
- int reversed, annul, noop;
- rtx insn;
+output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
+ int annul, int noop, rtx insn)
{
static char string[50];
enum rtx_code code = GET_CODE (op);
@@ -6003,9 +6629,7 @@ output_v9branch (op, dest, reg, label, reversed, annul, noop, insn)
*/
static int
-epilogue_renumber (where, test)
- register rtx *where;
- int test;
+epilogue_renumber (register rtx *where, int test)
{
register const char *fmt;
register int i;
@@ -6089,7 +6713,7 @@ static const int *const reg_alloc_orders[] = {
reg_nonleaf_alloc_order};
void
-order_regs_for_local_alloc ()
+order_regs_for_local_alloc (void)
{
static int last_order_nonleaf = 1;
@@ -6106,9 +6730,7 @@ order_regs_for_local_alloc ()
mem<-->reg splits to be run. */
int
-sparc_splitdi_legitimate (reg, mem)
- rtx reg;
- rtx mem;
+sparc_splitdi_legitimate (rtx reg, rtx mem)
{
/* Punt if we are here by mistake. */
if (! reload_completed)
@@ -6129,12 +6751,11 @@ sparc_splitdi_legitimate (reg, mem)
}
/* Return 1 if x and y are some kind of REG and they refer to
- different hard registers. This test is guarenteed to be
+ different hard registers. This test is guaranteed to be
run after reload. */
int
-sparc_absnegfloat_split_legitimate (x, y)
- rtx x, y;
+sparc_absnegfloat_split_legitimate (rtx x, rtx y)
{
if (GET_CODE (x) != REG)
return 0;
@@ -6151,8 +6772,7 @@ sparc_absnegfloat_split_legitimate (x, y)
Note reg1 and reg2 *must* be hard registers. */
int
-registers_ok_for_ldd_peep (reg1, reg2)
- rtx reg1, reg2;
+registers_ok_for_ldd_peep (rtx reg1, rtx reg2)
{
/* We might have been passed a SUBREG. */
if (GET_CODE (reg1) != REG || GET_CODE (reg2) != REG)
@@ -6200,12 +6820,11 @@ registers_ok_for_ldd_peep (reg1, reg2)
NULL_RTX. */
int
-mems_ok_for_ldd_peep (mem1, mem2, dependent_reg_rtx)
- rtx mem1, mem2, dependent_reg_rtx;
+mems_ok_for_ldd_peep (rtx mem1, rtx mem2, rtx dependent_reg_rtx)
{
rtx addr1, addr2;
unsigned int reg1;
- int offset1;
+ HOST_WIDE_INT offset1;
/* The mems cannot be volatile. */
if (MEM_VOLATILE_P (mem1) || MEM_VOLATILE_P (mem2))
@@ -6275,8 +6894,7 @@ mems_ok_for_ldd_peep (mem1, mem2, dependent_reg_rtx)
ldd and std insns. */
int
-register_ok_for_ldd (reg)
- rtx reg;
+register_ok_for_ldd (rtx reg)
{
/* We might have been passed a SUBREG. */
if (GET_CODE (reg) != REG)
@@ -6293,10 +6911,7 @@ register_ok_for_ldd (reg)
For `%' followed by punctuation, CODE is the punctuation and X is null. */
void
-print_operand (file, x, code)
- FILE *file;
- rtx x;
- int code;
+print_operand (FILE *file, rtx x, int code)
{
switch (code)
{
@@ -6331,7 +6946,11 @@ print_operand (file, x, code)
/* Print out what we are using as the frame pointer. This might
be %fp, or might be %sp+offset. */
/* ??? What if offset is too big? Perhaps the caller knows it isn't? */
- fprintf (file, "%s+%d", frame_base_name, frame_base_offset);
+ fprintf (file, "%s+"HOST_WIDE_INT_PRINT_DEC, frame_base_name, frame_base_offset);
+ return;
+ case '&':
+ /* Print some local dynamic TLS name. */
+ assemble_name (file, get_some_local_dynamic_name ());
return;
case 'Y':
/* Adjust the operand to take into account a RESTORE operation. */
@@ -6581,10 +7200,7 @@ print_operand (file, x, code)
special handling for aligned DI-mode objects. */
static bool
-sparc_assemble_integer (x, size, aligned_p)
- rtx x;
- unsigned int size;
- int aligned_p;
+sparc_assemble_integer (rtx x, unsigned int size, int aligned_p)
{
/* ??? We only output .xword's for symbols and only then in environments
where the assembler can handle them. */
@@ -6639,8 +7255,7 @@ sparc_assemble_integer (x, size, aligned_p)
#endif
unsigned long
-sparc_type_code (type)
- register tree type;
+sparc_type_code (register tree type)
{
register unsigned long qualifiers = 0;
register unsigned shift;
@@ -6764,10 +7379,9 @@ sparc_type_code (type)
Emit enough FLUSH insns to synchronize the data and instruction caches. */
void
-sparc_initialize_trampoline (tramp, fnaddr, cxt)
- rtx tramp, fnaddr, cxt;
+sparc_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
{
- /* SPARC 32 bit trampoline:
+ /* SPARC 32-bit trampoline:
sethi %hi(fn), %g1
sethi %hi(static), %g2
@@ -6777,10 +7391,6 @@ sparc_initialize_trampoline (tramp, fnaddr, cxt)
SETHI i,r = 00rr rrr1 00ii iiii iiii iiii iiii iiii
JMPL r+i,d = 10dd ddd1 1100 0rrr rr1i iiii iiii iiii
*/
-#ifdef TRANSFER_FROM_TRAMPOLINE
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"),
- LCT_NORMAL, VOIDmode, 1, tramp, Pmode);
-#endif
emit_move_insn
(gen_rtx_MEM (SImode, plus_constant (tramp, 0)),
@@ -6819,22 +7429,25 @@ sparc_initialize_trampoline (tramp, fnaddr, cxt)
&& sparc_cpu != PROCESSOR_ULTRASPARC3)
emit_insn (gen_flush (validize_mem (gen_rtx_MEM (SImode,
plus_constant (tramp, 8)))));
+
+ /* Call __enable_execute_stack after writing onto the stack to make sure
+ the stack address is accessible. */
+#ifdef ENABLE_EXECUTE_STACK
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"),
+ LCT_NORMAL, VOIDmode, 1, tramp, Pmode);
+#endif
+
}
-/* The 64 bit version is simpler because it makes more sense to load the
+/* The 64-bit version is simpler because it makes more sense to load the
values as "immediate" data out of the trampoline. It's also easier since
we can read the PC without clobbering a register. */
void
-sparc64_initialize_trampoline (tramp, fnaddr, cxt)
- rtx tramp, fnaddr, cxt;
+sparc64_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
{
-#ifdef TRANSFER_FROM_TRAMPOLINE
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"),
- LCT_NORMAL, VOIDmode, 1, tramp, Pmode);
-#endif
+ /* SPARC 64-bit trampoline:
- /*
rd %pc, %g1
ldx [%g1+24], %g5
jmp %g5
@@ -6857,6 +7470,13 @@ sparc64_initialize_trampoline (tramp, fnaddr, cxt)
if (sparc_cpu != PROCESSOR_ULTRASPARC
&& sparc_cpu != PROCESSOR_ULTRASPARC3)
emit_insn (gen_flushdi (validize_mem (gen_rtx_MEM (DImode, plus_constant (tramp, 8)))));
+
+ /* Call __enable_execute_stack after writing onto the stack to make sure
+ the stack address is accessible. */
+#ifdef ENABLE_EXECUTE_STACK
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"),
+ LCT_NORMAL, VOIDmode, 1, tramp, Pmode);
+#endif
}
/* Subroutines to support a flat (single) register window calling
@@ -6925,16 +7545,16 @@ sparc64_initialize_trampoline (tramp, fnaddr, cxt)
struct sparc_frame_info
{
- unsigned long total_size; /* # bytes that the entire frame takes up. */
- unsigned long var_size; /* # bytes that variables take up. */
- unsigned long args_size; /* # bytes that outgoing arguments take up. */
- unsigned long extra_size; /* # bytes of extra gunk. */
- unsigned int gp_reg_size; /* # bytes needed to store gp regs. */
- unsigned int fp_reg_size; /* # bytes needed to store fp regs. */
+ HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up. */
+ HOST_WIDE_INT var_size; /* # bytes that variables take up. */
+ int args_size; /* # bytes that outgoing arguments take up. */
+ int extra_size; /* # bytes of extra gunk. */
+ int gp_reg_size; /* # bytes needed to store gp regs. */
+ int fp_reg_size; /* # bytes needed to store fp regs. */
unsigned long gmask; /* Mask of saved gp registers. */
unsigned long fmask; /* Mask of saved fp registers. */
- unsigned long reg_offset; /* Offset from new sp to store regs. */
- int initialized; /* Nonzero if frame size already calculated. */
+ int reg_offset; /* Offset from new sp to store regs. */
+ int initialized; /* Nonzero if frame size already calculated. */
};
/* Current frame information calculated by sparc_flat_compute_frame_size. */
@@ -6943,34 +7563,56 @@ struct sparc_frame_info current_frame_info;
/* Zero structure to initialize current_frame_info. */
struct sparc_frame_info zero_frame_info;
-/* Tell prologue and epilogue if register REGNO should be saved / restored. */
-
#define RETURN_ADDR_REGNUM 15
#define HARD_FRAME_POINTER_MASK (1 << (HARD_FRAME_POINTER_REGNUM))
#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
+
+/* Tell prologue and epilogue if register REGNO should be saved / restored. */
+
+static bool
+sparc_flat_must_save_register_p (int regno)
+{
+ /* General case: call-saved registers live at some point. */
+ if (!call_used_regs[regno] && regs_ever_live[regno])
+ return true;
+
+ /* Frame pointer register (%i7) if needed. */
+ if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
+ return true;
-#define MUST_SAVE_REGISTER(regno) \
- ((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]))
+ /* PIC register (%l7) if needed. */
+ if (regno == (int) PIC_OFFSET_TABLE_REGNUM
+ && flag_pic && current_function_uses_pic_offset_table)
+ return true;
+ /* Return address register (%o7) if needed. */
+ if (regno == RETURN_ADDR_REGNUM
+ && (regs_ever_live[RETURN_ADDR_REGNUM]
+ /* When the PIC offset table is used, the PIC register
+ is set by using a bare call that clobbers %o7. */
+ || (flag_pic && current_function_uses_pic_offset_table)))
+ return true;
+
+ return false;
+}
+
/* Return the bytes needed to compute the frame pointer from the current
stack pointer. */
-unsigned long
-sparc_flat_compute_frame_size (size)
- int size; /* # of var. bytes allocated. */
+HOST_WIDE_INT
+sparc_flat_compute_frame_size (HOST_WIDE_INT size)
+ /* # of var. bytes allocated. */
{
int regno;
- unsigned long total_size; /* # bytes that the entire frame takes up. */
- unsigned long var_size; /* # bytes that variables take up. */
- unsigned long args_size; /* # bytes that outgoing arguments take up. */
- unsigned long extra_size; /* # extra bytes. */
- unsigned int gp_reg_size; /* # bytes needed to store gp regs. */
- unsigned int fp_reg_size; /* # bytes needed to store fp regs. */
+ HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up. */
+ HOST_WIDE_INT var_size; /* # bytes that variables take up. */
+ int args_size; /* # bytes that outgoing arguments take up. */
+ int extra_size; /* # extra bytes. */
+ int gp_reg_size; /* # bytes needed to store gp regs. */
+ int fp_reg_size; /* # bytes needed to store fp regs. */
unsigned long gmask; /* Mask of saved gp registers. */
unsigned long fmask; /* Mask of saved fp registers. */
- unsigned long reg_offset; /* Offset to register save area. */
+ int reg_offset; /* Offset to register save area. */
int need_aligned_p; /* 1 if need the save area 8 byte aligned. */
/* This is the size of the 16 word reg save area, 1 word struct addr
@@ -6995,11 +7637,11 @@ sparc_flat_compute_frame_size (size)
/* Calculate space needed for gp registers. */
for (regno = 1; regno <= 31; regno++)
{
- if (MUST_SAVE_REGISTER (regno))
+ if (sparc_flat_must_save_register_p (regno))
{
/* If we need to save two regs in a row, ensure there's room to bump
up the address to align it to a doubleword boundary. */
- if ((regno & 0x1) == 0 && MUST_SAVE_REGISTER (regno+1))
+ if ((regno & 0x1) == 0 && sparc_flat_must_save_register_p (regno+1))
{
if (gp_reg_size % 8 != 0)
gp_reg_size += 4;
@@ -7076,17 +7718,11 @@ sparc_flat_compute_frame_size (size)
WORD_OP is either "st" for save, "ld" for restore.
DOUBLEWORD_OP is either "std" for save, "ldd" for restore. */
-void
-sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op,
- doubleword_op, base_offset)
- FILE *file;
- const char *base_reg;
- unsigned int offset;
- unsigned long gmask;
- unsigned long fmask;
- const char *word_op;
- const char *doubleword_op;
- unsigned long base_offset;
+static void
+sparc_flat_save_restore (FILE *file, const char *base_reg, int offset,
+ unsigned long gmask, unsigned long fmask,
+ const char *word_op, const char *doubleword_op,
+ HOST_WIDE_INT base_offset)
{
int regno;
@@ -7181,9 +7817,7 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op,
/* Set up the stack and frame (if desired) for the function. */
static void
-sparc_flat_function_prologue (file, size)
- FILE *file;
- HOST_WIDE_INT size;
+sparc_flat_function_prologue (FILE *file, HOST_WIDE_INT size)
{
const char *sp_str = reg_names[STACK_POINTER_REGNUM];
unsigned long gmask = current_frame_info.gmask;
@@ -7192,7 +7826,8 @@ sparc_flat_function_prologue (file, size)
/* This is only for the human reader. */
fprintf (file, "\t%s#PROLOGUE# 0\n", ASM_COMMENT_START);
- fprintf (file, "\t%s# vars= %ld, regs= %d/%d, args= %d, extra= %ld\n",
+ fprintf (file, "\t%s# vars= "HOST_WIDE_INT_PRINT_DEC", "
+ "regs= %d/%d, args= %d, extra= %d\n",
ASM_COMMENT_START,
current_frame_info.var_size,
current_frame_info.gp_reg_size / 4,
@@ -7223,7 +7858,7 @@ sparc_flat_function_prologue (file, size)
after %i7 so gdb won't have to look too far to find it. */
if (size > 0)
{
- unsigned int reg_offset = current_frame_info.reg_offset;
+ int reg_offset = current_frame_info.reg_offset;
const char *const fp_str = reg_names[HARD_FRAME_POINTER_REGNUM];
static const char *const t1_str = "%g1";
@@ -7239,27 +7874,26 @@ sparc_flat_function_prologue (file, size)
the gdb folk first. */
/* Is the entire register save area offsettable from %sp? */
- if (reg_offset < 4096 - 64 * (unsigned) UNITS_PER_WORD)
+ if (reg_offset < 4096 - 64 * UNITS_PER_WORD)
{
if (size <= 4096)
{
- fprintf (file, "\tadd\t%s, %d, %s\n",
- sp_str, (int) -size, sp_str);
+ fprintf (file, "\tadd\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s\n",
+ sp_str, size, sp_str);
if (gmask & HARD_FRAME_POINTER_MASK)
{
fprintf (file, "\tst\t%s, [%s+%d]\n",
fp_str, sp_str, reg_offset);
- fprintf (file, "\tsub\t%s, %d, %s\t%s# set up frame pointer\n",
- sp_str, (int) -size, fp_str, ASM_COMMENT_START);
+ fprintf (file, "\tsub\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s"
+ "\t%s# set up frame pointer\n",
+ sp_str, size, fp_str, ASM_COMMENT_START);
reg_offset += 4;
}
}
else
{
- fprintf (file, "\tset\t");
- 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);
+ build_big_number (file, size, t1_str);
+ fprintf (file, "\tsub\t%s, %s, %s\n", sp_str, t1_str, sp_str);
if (gmask & HARD_FRAME_POINTER_MASK)
{
fprintf (file, "\tst\t%s, [%s+%d]\n",
@@ -7297,34 +7931,40 @@ sparc_flat_function_prologue (file, size)
else
{
/* Subtract %sp in two steps, but make sure there is always a
- 64 byte register save area, and %sp is properly aligned. */
+ 64-byte register save area, and %sp is properly aligned. */
+
/* Amount to decrement %sp by, the first time. */
- unsigned HOST_WIDE_INT size1 = ((size - reg_offset + 64) + 15) & -16;
- /* Offset to register save area from %sp. */
- unsigned HOST_WIDE_INT offset = size1 - (size - reg_offset);
+ HOST_WIDE_INT size1 = ((size - reg_offset + 64) + 15) & -16;
+
+ /* Amount to decrement %sp by, the second time. */
+ HOST_WIDE_INT size2 = size - size1;
+
+ /* Offset to register save area from %sp after first decrement. */
+ int offset = (int)(size1 - (size - reg_offset));
if (size1 <= 4096)
{
- fprintf (file, "\tadd\t%s, %d, %s\n",
- sp_str, (int) -size1, sp_str);
+ fprintf (file, "\tadd\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s\n",
+ sp_str, size1, sp_str);
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,
+ fprintf (file, "\tst\t%s, [%s+%d]\n"
+ "\tsub\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s"
+ "\t%s# set up frame pointer\n",
+ fp_str, sp_str, offset, sp_str, size1,
fp_str, ASM_COMMENT_START);
offset += 4;
}
}
else
{
- fprintf (file, "\tset\t");
- 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);
+ build_big_number (file, size1, t1_str);
+ fprintf (file, "\tsub\t%s, %s, %s\n", sp_str, t1_str, sp_str);
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,
+ fprintf (file, "\tst\t%s, [%s+%d]\n"
+ "\tadd\t%s, %s, %s\t%s# set up frame pointer\n",
+ fp_str, sp_str, offset, sp_str, t1_str,
fp_str, ASM_COMMENT_START);
offset += 4;
}
@@ -7344,7 +7984,7 @@ sparc_flat_function_prologue (file, size)
if (gmask & RETURN_ADDR_MASK)
{
fprintf (file, "\tst\t%s, [%s+%d]\n",
- reg_names[RETURN_ADDR_REGNUM], sp_str, (int) offset);
+ reg_names[RETURN_ADDR_REGNUM], sp_str, offset);
if (dwarf2out_do_frame ())
/* offset - size1 == reg_offset - size
if reg_offset were updated above like offset. */
@@ -7355,10 +7995,14 @@ sparc_flat_function_prologue (file, size)
gmask & ~(HARD_FRAME_POINTER_MASK | RETURN_ADDR_MASK),
current_frame_info.fmask,
"st", "std", -size1);
- fprintf (file, "\tset\t");
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, size - size1);
- fprintf (file, ", %s\n\tsub\t%s, %s, %s\n",
- t1_str, sp_str, t1_str, sp_str);
+ if (size2 <= 4096)
+ fprintf (file, "\tadd\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s\n",
+ sp_str, size2, sp_str);
+ else
+ {
+ build_big_number (file, size2, t1_str);
+ fprintf (file, "\tsub\t%s, %s, %s\n", sp_str, t1_str, sp_str);
+ }
if (dwarf2out_do_frame ())
if (! (gmask & HARD_FRAME_POINTER_MASK))
dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, size);
@@ -7372,9 +8016,7 @@ sparc_flat_function_prologue (file, size)
and regs. */
static void
-sparc_flat_function_epilogue (file, size)
- FILE *file;
- HOST_WIDE_INT size;
+sparc_flat_function_epilogue (FILE *file, HOST_WIDE_INT size)
{
rtx epilogue_delay = current_function_epilogue_delay_list;
int noepilogue = FALSE;
@@ -7406,8 +8048,8 @@ sparc_flat_function_epilogue (file, size)
if (!noepilogue)
{
- unsigned HOST_WIDE_INT reg_offset = current_frame_info.reg_offset;
- unsigned HOST_WIDE_INT size1;
+ int reg_offset = current_frame_info.reg_offset;
+ int reg_offset1;
const char *const sp_str = reg_names[STACK_POINTER_REGNUM];
const char *const fp_str = reg_names[HARD_FRAME_POINTER_REGNUM];
static const char *const t1_str = "%g1";
@@ -7416,41 +8058,43 @@ sparc_flat_function_epilogue (file, size)
slots for most of the loads, also see if we can fill the final
delay slot if not otherwise filled by the reload sequence. */
- if (size > 4095)
- {
- fprintf (file, "\tset\t");
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, size);
- fprintf (file, ", %s\n", t1_str);
- }
+ if (size > 4096)
+ build_big_number (file, size, t1_str);
if (frame_pointer_needed)
{
- if (size > 4095)
+ if (size > 4096)
fprintf (file,"\tsub\t%s, %s, %s\t\t%s# sp not trusted here\n",
fp_str, t1_str, sp_str, ASM_COMMENT_START);
else
- fprintf (file,"\tsub\t%s, %d, %s\t\t%s# sp not trusted here\n",
- fp_str, (int) size, sp_str, ASM_COMMENT_START);
+ fprintf (file,"\tadd\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s"
+ "\t\t%s# sp not trusted here\n",
+ fp_str, size, sp_str, ASM_COMMENT_START);
}
/* Is the entire register save area offsettable from %sp? */
- if (reg_offset < 4096 - 64 * (unsigned) UNITS_PER_WORD)
+ if (reg_offset < 4096 - 64 * UNITS_PER_WORD)
{
- size1 = 0;
+ reg_offset1 = 0;
}
else
{
/* Restore %sp in two steps, but make sure there is always a
- 64 byte register save area, and %sp is properly aligned. */
+ 64-byte register save area, and %sp is properly aligned. */
+
/* Amount to increment %sp by, the first time. */
- size1 = ((reg_offset - 64 - 16) + 15) & -16;
+ reg_offset1 = ((reg_offset - 64 - 16) + 15) & -16;
+
/* Offset to register save area from %sp. */
- reg_offset = size1 - reg_offset;
+ reg_offset = reg_offset1 - reg_offset;
- fprintf (file, "\tset\t");
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, size1);
- fprintf (file, ", %s\n\tadd\t%s, %s, %s\n",
- t1_str, sp_str, t1_str, sp_str);
+ if (reg_offset1 > 4096)
+ {
+ build_big_number (file, reg_offset1, t1_str);
+ fprintf (file, "\tadd\t%s, %s, %s\n", sp_str, t1_str, sp_str);
+ }
+ else
+ fprintf (file, "\tsub\t%s, -%d, %s\n", sp_str, reg_offset1, sp_str);
}
/* We must restore the frame pointer and return address reg first
@@ -7458,13 +8102,13 @@ sparc_flat_function_epilogue (file, size)
if (current_frame_info.gmask & HARD_FRAME_POINTER_MASK)
{
fprintf (file, "\tld\t[%s+%d], %s\n",
- sp_str, (int) reg_offset, fp_str);
+ sp_str, reg_offset, fp_str);
reg_offset += 4;
}
if (current_frame_info.gmask & RETURN_ADDR_MASK)
{
fprintf (file, "\tld\t[%s+%d], %s\n",
- sp_str, (int) reg_offset, reg_names[RETURN_ADDR_REGNUM]);
+ sp_str, reg_offset, reg_names[RETURN_ADDR_REGNUM]);
reg_offset += 4;
}
@@ -7476,15 +8120,11 @@ sparc_flat_function_epilogue (file, size)
/* If we had to increment %sp in two steps, record it so the second
restoration in the epilogue finishes up. */
- if (size1 > 0)
+ if (reg_offset1 > 0)
{
- size -= size1;
- if (size > 4095)
- {
- fprintf (file, "\tset\t");
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, size);
- fprintf (file, ", %s\n", t1_str);
- }
+ size -= reg_offset1;
+ if (size > 4096)
+ build_big_number (file, size, t1_str);
}
if (current_function_returns_struct)
@@ -7501,14 +8141,15 @@ sparc_flat_function_epilogue (file, size)
{
if (size)
abort ();
- final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1);
+ final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1, NULL);
}
- else if (size > 4095)
+ else if (size > 4096)
fprintf (file, "\tadd\t%s, %s, %s\n", sp_str, t1_str, sp_str);
else if (size > 0)
- fprintf (file, "\tadd\t%s, %d, %s\n", sp_str, (int) size, sp_str);
+ fprintf (file, "\tsub\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s\n",
+ sp_str, size, sp_str);
else
fprintf (file, "\tnop\n");
@@ -7526,7 +8167,7 @@ sparc_flat_function_epilogue (file, size)
or the only register saved is the return register. */
int
-sparc_flat_epilogue_delay_slots ()
+sparc_flat_epilogue_delay_slots (void)
{
if (!current_frame_info.initialized)
(void) sparc_flat_compute_frame_size (get_frame_size ());
@@ -7542,9 +8183,7 @@ sparc_flat_epilogue_delay_slots ()
pointer is OK. */
int
-sparc_flat_eligible_for_epilogue_delay (trial, slot)
- rtx trial;
- int slot ATTRIBUTE_UNUSED;
+sparc_flat_eligible_for_epilogue_delay (rtx trial, int slot ATTRIBUTE_UNUSED)
{
rtx pat = PATTERN (trial);
@@ -7562,11 +8201,7 @@ sparc_flat_eligible_for_epilogue_delay (trial, slot)
a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
static int
-supersparc_adjust_cost (insn, link, dep_insn, cost)
- rtx insn;
- rtx link;
- rtx dep_insn;
- int cost;
+supersparc_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
{
enum attr_type insn_type;
@@ -7627,11 +8262,7 @@ supersparc_adjust_cost (insn, link, dep_insn, cost)
}
static int
-hypersparc_adjust_cost (insn, link, dep_insn, cost)
- rtx insn;
- rtx link;
- rtx dep_insn;
- int cost;
+hypersparc_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
{
enum attr_type insn_type, dep_type;
rtx pat = PATTERN(insn);
@@ -7708,11 +8339,7 @@ hypersparc_adjust_cost (insn, link, dep_insn, cost)
}
static int
-sparc_adjust_cost(insn, link, dep, cost)
- rtx insn;
- rtx link;
- rtx dep;
- int cost;
+sparc_adjust_cost(rtx insn, rtx link, rtx dep, int cost)
{
switch (sparc_cpu)
{
@@ -7730,15 +8357,14 @@ sparc_adjust_cost(insn, link, dep, cost)
}
static void
-sparc_sched_init (dump, sched_verbose, max_ready)
- FILE *dump ATTRIBUTE_UNUSED;
- int sched_verbose ATTRIBUTE_UNUSED;
- int max_ready ATTRIBUTE_UNUSED;
+sparc_sched_init (FILE *dump ATTRIBUTE_UNUSED,
+ int sched_verbose ATTRIBUTE_UNUSED,
+ int max_ready ATTRIBUTE_UNUSED)
{
}
static int
-sparc_use_dfa_pipeline_interface ()
+sparc_use_dfa_pipeline_interface (void)
{
if ((1 << sparc_cpu) &
((1 << PROCESSOR_ULTRASPARC) | (1 << PROCESSOR_CYPRESS) |
@@ -7750,7 +8376,7 @@ sparc_use_dfa_pipeline_interface ()
}
static int
-sparc_use_sched_lookahead ()
+sparc_use_sched_lookahead (void)
{
if (sparc_cpu == PROCESSOR_ULTRASPARC
|| sparc_cpu == PROCESSOR_ULTRASPARC3)
@@ -7763,7 +8389,7 @@ sparc_use_sched_lookahead ()
}
static int
-sparc_issue_rate ()
+sparc_issue_rate (void)
{
switch (sparc_cpu)
{
@@ -7784,8 +8410,7 @@ sparc_issue_rate ()
}
static int
-set_extends (insn)
- rtx insn;
+set_extends (rtx insn)
{
register rtx pat = PATTERN (insn);
@@ -7852,9 +8477,7 @@ static GTY(()) rtx sparc_addr_diff_list;
static GTY(()) rtx sparc_addr_list;
void
-sparc_defer_case_vector (lab, vec, diff)
- rtx lab, vec;
- int diff;
+sparc_defer_case_vector (rtx lab, rtx vec, int diff)
{
vec = gen_rtx_EXPR_LIST (VOIDmode, lab, vec);
if (diff)
@@ -7865,8 +8488,7 @@ sparc_defer_case_vector (lab, vec, diff)
}
static void
-sparc_output_addr_vec (vec)
- rtx vec;
+sparc_output_addr_vec (rtx vec)
{
rtx lab = XEXP (vec, 0), body = XEXP (vec, 1);
int idx, vlen = XVECLEN (body, 0);
@@ -7879,7 +8501,7 @@ sparc_output_addr_vec (vec)
ASM_OUTPUT_CASE_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab),
NEXT_INSN (lab));
#else
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab));
+ (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (lab));
#endif
for (idx = 0; idx < vlen; idx++)
@@ -7894,8 +8516,7 @@ sparc_output_addr_vec (vec)
}
static void
-sparc_output_addr_diff_vec (vec)
- rtx vec;
+sparc_output_addr_diff_vec (rtx vec)
{
rtx lab = XEXP (vec, 0), body = XEXP (vec, 1);
rtx base = XEXP (XEXP (body, 0), 0);
@@ -7909,7 +8530,7 @@ sparc_output_addr_diff_vec (vec)
ASM_OUTPUT_CASE_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab),
NEXT_INSN (lab));
#else
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab));
+ (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (lab));
#endif
for (idx = 0; idx < vlen; idx++)
@@ -7927,7 +8548,7 @@ sparc_output_addr_diff_vec (vec)
}
static void
-sparc_output_deferred_case_vectors ()
+sparc_output_deferred_case_vectors (void)
{
rtx t;
int align;
@@ -7955,8 +8576,7 @@ sparc_output_deferred_case_vectors ()
unknown. Return 1 if the high bits are zero, -1 if the register is
sign extended. */
int
-sparc_check_64 (x, insn)
- rtx x, insn;
+sparc_check_64 (rtx x, rtx insn)
{
/* If a register is set only once it is safe to ignore insns this
code does not know how to handle. The loop will either recognize
@@ -8016,10 +8636,7 @@ sparc_check_64 (x, insn)
/* Returns assembly code to perform a DImode shift using
a 64-bit global or out register on SPARC-V8+. */
char *
-sparc_v8plus_shift (operands, insn, opcode)
- rtx *operands;
- rtx insn;
- const char *opcode;
+sparc_v8plus_shift (rtx *operands, rtx insn, const char *opcode)
{
static char asm_code[60];
@@ -8056,8 +8673,7 @@ sparc_v8plus_shift (operands, insn, opcode)
for profiling a function entry. */
void
-sparc_profile_hook (labelno)
- int labelno;
+sparc_profile_hook (int labelno)
{
char buf[32];
rtx lab, fun;
@@ -8071,9 +8687,7 @@ sparc_profile_hook (labelno)
#ifdef OBJECT_FORMAT_ELF
static void
-sparc_elf_asm_named_section (name, flags)
- const char *name;
- unsigned int flags;
+sparc_elf_asm_named_section (const char *name, unsigned int flags)
{
if (flags & SECTION_MERGE)
{
@@ -8089,6 +8703,8 @@ sparc_elf_asm_named_section (name, flags)
fputs (",#alloc", asm_out_file);
if (flags & SECTION_WRITE)
fputs (",#write", asm_out_file);
+ if (flags & SECTION_TLS)
+ fputs (",#tls", asm_out_file);
if (flags & SECTION_CODE)
fputs (",#execinstr", asm_out_file);
@@ -8098,15 +8714,133 @@ sparc_elf_asm_named_section (name, flags)
}
#endif /* OBJECT_FORMAT_ELF */
+/* We do not allow sibling calls if -mflat, nor
+ 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. */
+static bool
+sparc_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
+{
+ return (decl
+ && ! TARGET_FLAT
+ && (TARGET_ARCH64 || ! current_function_returns_struct));
+}
+
+/* libfunc renaming. */
+#include "config/gofast.h"
+
+static void
+sparc_init_libfuncs (void)
+{
+ if (TARGET_ARCH32)
+ {
+ /* Use the subroutines that Sun's library provides for integer
+ multiply and divide. The `*' prevents an underscore from
+ being prepended by the compiler. .umul is a little faster
+ than .mul. */
+ set_optab_libfunc (smul_optab, SImode, "*.umul");
+ set_optab_libfunc (sdiv_optab, SImode, "*.div");
+ set_optab_libfunc (udiv_optab, SImode, "*.udiv");
+ set_optab_libfunc (smod_optab, SImode, "*.rem");
+ set_optab_libfunc (umod_optab, SImode, "*.urem");
+
+ /* TFmode arithmetic. These names are part of the SPARC 32bit ABI. */
+ set_optab_libfunc (add_optab, TFmode, "_Q_add");
+ set_optab_libfunc (sub_optab, TFmode, "_Q_sub");
+ set_optab_libfunc (neg_optab, TFmode, "_Q_neg");
+ set_optab_libfunc (smul_optab, TFmode, "_Q_mul");
+ set_optab_libfunc (sdiv_optab, TFmode, "_Q_div");
+
+ /* We can define the TFmode sqrt optab only if TARGET_FPU. This
+ is because with soft-float, the SFmode and DFmode sqrt
+ instructions will be absent, and the compiler will notice and
+ try to use the TFmode sqrt instruction for calls to the
+ builtin function sqrt, but this fails. */
+ if (TARGET_FPU)
+ set_optab_libfunc (sqrt_optab, TFmode, "_Q_sqrt");
+
+ set_optab_libfunc (eq_optab, TFmode, "_Q_feq");
+ set_optab_libfunc (ne_optab, TFmode, "_Q_fne");
+ set_optab_libfunc (gt_optab, TFmode, "_Q_fgt");
+ set_optab_libfunc (ge_optab, TFmode, "_Q_fge");
+ set_optab_libfunc (lt_optab, TFmode, "_Q_flt");
+ set_optab_libfunc (le_optab, TFmode, "_Q_fle");
+
+ set_conv_libfunc (sext_optab, TFmode, SFmode, "_Q_stoq");
+ set_conv_libfunc (sext_optab, TFmode, DFmode, "_Q_dtoq");
+ set_conv_libfunc (trunc_optab, SFmode, TFmode, "_Q_qtos");
+ set_conv_libfunc (trunc_optab, DFmode, TFmode, "_Q_qtod");
+
+ set_conv_libfunc (sfix_optab, SImode, TFmode, "_Q_qtoi");
+ set_conv_libfunc (ufix_optab, SImode, TFmode, "_Q_qtou");
+ set_conv_libfunc (sfloat_optab, TFmode, SImode, "_Q_itoq");
+
+ if (DITF_CONVERSION_LIBFUNCS)
+ {
+ set_conv_libfunc (sfix_optab, DImode, TFmode, "_Q_qtoll");
+ set_conv_libfunc (ufix_optab, DImode, TFmode, "_Q_qtoull");
+ set_conv_libfunc (sfloat_optab, TFmode, DImode, "_Q_lltoq");
+ }
+
+ if (SUN_CONVERSION_LIBFUNCS)
+ {
+ set_conv_libfunc (sfix_optab, DImode, SFmode, "__ftoll");
+ set_conv_libfunc (ufix_optab, DImode, SFmode, "__ftoull");
+ set_conv_libfunc (sfix_optab, DImode, DFmode, "__dtoll");
+ set_conv_libfunc (ufix_optab, DImode, DFmode, "__dtoull");
+ }
+ }
+ if (TARGET_ARCH64)
+ {
+ /* In the SPARC 64bit ABI, SImode multiply and divide functions
+ do not exist in the library. Make sure the compiler does not
+ emit calls to them by accident. (It should always use the
+ hardware instructions.) */
+ set_optab_libfunc (smul_optab, SImode, 0);
+ set_optab_libfunc (sdiv_optab, SImode, 0);
+ set_optab_libfunc (udiv_optab, SImode, 0);
+ set_optab_libfunc (smod_optab, SImode, 0);
+ set_optab_libfunc (umod_optab, SImode, 0);
+
+ if (SUN_INTEGER_MULTIPLY_64)
+ {
+ set_optab_libfunc (smul_optab, DImode, "__mul64");
+ set_optab_libfunc (sdiv_optab, DImode, "__div64");
+ set_optab_libfunc (udiv_optab, DImode, "__udiv64");
+ set_optab_libfunc (smod_optab, DImode, "__rem64");
+ set_optab_libfunc (umod_optab, DImode, "__urem64");
+ }
+
+ if (SUN_CONVERSION_LIBFUNCS)
+ {
+ set_conv_libfunc (sfix_optab, DImode, SFmode, "__ftol");
+ set_conv_libfunc (ufix_optab, DImode, SFmode, "__ftoul");
+ set_conv_libfunc (sfix_optab, DImode, DFmode, "__dtol");
+ set_conv_libfunc (ufix_optab, DImode, DFmode, "__dtoul");
+ }
+ }
+
+ gofast_maybe_init_libfuncs ();
+}
+
/* ??? Similar to the standard section selection, but force reloc-y-ness
if SUNOS4_SHARED_LIBRARIES. Unclear why this helps (as opposed to
pretending PIC always on), but that's what the old code did. */
static void
-sparc_aout_select_section (t, reloc, align)
- tree t;
- int reloc;
- unsigned HOST_WIDE_INT align;
+sparc_aout_select_section (tree t, int reloc, unsigned HOST_WIDE_INT align)
{
default_select_section (t, reloc | SUNOS4_SHARED_LIBRARIES, align);
}
@@ -8115,10 +8849,8 @@ sparc_aout_select_section (t, reloc, align)
that offers. */
static void
-sparc_aout_select_rtx_section (mode, x, align)
- enum machine_mode mode;
- rtx x;
- unsigned HOST_WIDE_INT align;
+sparc_aout_select_rtx_section (enum machine_mode mode, rtx x,
+ unsigned HOST_WIDE_INT align)
{
if (align <= MAX_TEXT_ALIGN
&& ! (flag_pic && (symbolic_operand (x, mode)
@@ -8129,10 +8861,7 @@ sparc_aout_select_rtx_section (mode, x, align)
}
int
-sparc_extra_constraint_check (op, c, strict)
- rtx op;
- int c;
- int strict;
+sparc_extra_constraint_check (rtx op, int c, int strict)
{
int reload_ok_mem;
@@ -8194,10 +8923,8 @@ sparc_extra_constraint_check (op, c, strict)
??? scheduler description. Some day, teach genautomata to output
??? the latencies and then CSE will just use that. */
-int
-sparc_rtx_costs (x, code, outer_code)
- rtx x;
- enum rtx_code code, outer_code;
+static bool
+sparc_rtx_costs (rtx x, int code, int outer_code, int *total)
{
switch (code)
{
@@ -8211,50 +8938,61 @@ sparc_rtx_costs (x, code, outer_code)
{
case PROCESSOR_ULTRASPARC:
case PROCESSOR_ULTRASPARC3:
- return COSTS_N_INSNS (4);
+ *total = COSTS_N_INSNS (4);
+ return true;
case PROCESSOR_SUPERSPARC:
- return COSTS_N_INSNS (3);
+ *total = COSTS_N_INSNS (3);
+ return true;
case PROCESSOR_CYPRESS:
- return COSTS_N_INSNS (5);
+ *total = COSTS_N_INSNS (5);
+ return true;
case PROCESSOR_HYPERSPARC:
case PROCESSOR_SPARCLITE86X:
default:
- return COSTS_N_INSNS (1);
+ *total = COSTS_N_INSNS (1);
+ return true;
}
}
- return COSTS_N_INSNS (1);
+ *total = COSTS_N_INSNS (1);
+ return true;
case SQRT:
switch (sparc_cpu)
{
case PROCESSOR_ULTRASPARC:
if (GET_MODE (x) == SFmode)
- return COSTS_N_INSNS (13);
+ *total = COSTS_N_INSNS (13);
else
- return COSTS_N_INSNS (23);
+ *total = COSTS_N_INSNS (23);
+ return true;
case PROCESSOR_ULTRASPARC3:
if (GET_MODE (x) == SFmode)
- return COSTS_N_INSNS (20);
+ *total = COSTS_N_INSNS (20);
else
- return COSTS_N_INSNS (29);
+ *total = COSTS_N_INSNS (29);
+ return true;
case PROCESSOR_SUPERSPARC:
- return COSTS_N_INSNS (12);
+ *total = COSTS_N_INSNS (12);
+ return true;
case PROCESSOR_CYPRESS:
- return COSTS_N_INSNS (63);
+ *total = COSTS_N_INSNS (63);
+ return true;
case PROCESSOR_HYPERSPARC:
case PROCESSOR_SPARCLITE86X:
- return COSTS_N_INSNS (17);
+ *total = COSTS_N_INSNS (17);
+ return true;
default:
- return COSTS_N_INSNS (30);
+ *total = COSTS_N_INSNS (30);
+ return true;
}
case COMPARE:
@@ -8264,18 +9002,22 @@ sparc_rtx_costs (x, code, outer_code)
{
case PROCESSOR_ULTRASPARC:
case PROCESSOR_ULTRASPARC3:
- return COSTS_N_INSNS (1);
+ *total = COSTS_N_INSNS (1);
+ return true;
case PROCESSOR_SUPERSPARC:
- return COSTS_N_INSNS (3);
+ *total = COSTS_N_INSNS (3);
+ return true;
case PROCESSOR_CYPRESS:
- return COSTS_N_INSNS (5);
+ *total = COSTS_N_INSNS (5);
+ return true;
case PROCESSOR_HYPERSPARC:
case PROCESSOR_SPARCLITE86X:
default:
- return COSTS_N_INSNS (1);
+ *total = COSTS_N_INSNS (1);
+ return true;
}
}
@@ -8283,7 +9025,8 @@ sparc_rtx_costs (x, code, outer_code)
??? all UltraSPARC processors because the result
??? can be bypassed to a branch in the same group. */
- return COSTS_N_INSNS (1);
+ *total = COSTS_N_INSNS (1);
+ return true;
case MULT:
if (FLOAT_MODE_P (GET_MODE (x)))
@@ -8292,20 +9035,25 @@ sparc_rtx_costs (x, code, outer_code)
{
case PROCESSOR_ULTRASPARC:
case PROCESSOR_ULTRASPARC3:
- return COSTS_N_INSNS (4);
+ *total = COSTS_N_INSNS (4);
+ return true;
case PROCESSOR_SUPERSPARC:
- return COSTS_N_INSNS (3);
+ *total = COSTS_N_INSNS (3);
+ return true;
case PROCESSOR_CYPRESS:
- return COSTS_N_INSNS (7);
+ *total = COSTS_N_INSNS (7);
+ return true;
case PROCESSOR_HYPERSPARC:
case PROCESSOR_SPARCLITE86X:
- return COSTS_N_INSNS (1);
+ *total = COSTS_N_INSNS (1);
+ return true;
default:
- return COSTS_N_INSNS (5);
+ *total = COSTS_N_INSNS (5);
+ return true;
}
}
@@ -8342,20 +9090,28 @@ sparc_rtx_costs (x, code, outer_code)
Since we do not play any such tricks currently the
safest thing to do is report the worst case latency. */
if (sparc_cpu == PROCESSOR_ULTRASPARC)
- return (GET_MODE (x) == DImode ?
- COSTS_N_INSNS (34) : COSTS_N_INSNS (19));
+ {
+ *total = (GET_MODE (x) == DImode
+ ? COSTS_N_INSNS (34) : COSTS_N_INSNS (19));
+ return true;
+ }
/* Multiply latency on Ultra-III, fortunately, is constant. */
if (sparc_cpu == PROCESSOR_ULTRASPARC3)
- return COSTS_N_INSNS (6);
+ {
+ *total = COSTS_N_INSNS (6);
+ return true;
+ }
if (sparc_cpu == PROCESSOR_HYPERSPARC
|| sparc_cpu == PROCESSOR_SPARCLITE86X)
- return COSTS_N_INSNS (17);
+ {
+ *total = COSTS_N_INSNS (17);
+ return true;
+ }
- return (TARGET_HARD_MUL
- ? COSTS_N_INSNS (5)
- : COSTS_N_INSNS (25));
+ *total = (TARGET_HARD_MUL ? COSTS_N_INSNS (5) : COSTS_N_INSNS (25));
+ return true;
case DIV:
case UDIV:
@@ -8367,57 +9123,67 @@ sparc_rtx_costs (x, code, outer_code)
{
case PROCESSOR_ULTRASPARC:
if (GET_MODE (x) == SFmode)
- return COSTS_N_INSNS (13);
+ *total = COSTS_N_INSNS (13);
else
- return COSTS_N_INSNS (23);
+ *total = COSTS_N_INSNS (23);
+ return true;
case PROCESSOR_ULTRASPARC3:
if (GET_MODE (x) == SFmode)
- return COSTS_N_INSNS (17);
+ *total = COSTS_N_INSNS (17);
else
- return COSTS_N_INSNS (20);
+ *total = COSTS_N_INSNS (20);
+ return true;
case PROCESSOR_SUPERSPARC:
if (GET_MODE (x) == SFmode)
- return COSTS_N_INSNS (6);
+ *total = COSTS_N_INSNS (6);
else
- return COSTS_N_INSNS (9);
+ *total = COSTS_N_INSNS (9);
+ return true;
case PROCESSOR_HYPERSPARC:
case PROCESSOR_SPARCLITE86X:
if (GET_MODE (x) == SFmode)
- return COSTS_N_INSNS (8);
+ *total = COSTS_N_INSNS (8);
else
- return COSTS_N_INSNS (12);
+ *total = COSTS_N_INSNS (12);
+ return true;
default:
- return COSTS_N_INSNS (7);
+ *total = COSTS_N_INSNS (7);
+ return true;
}
}
if (sparc_cpu == PROCESSOR_ULTRASPARC)
- return (GET_MODE (x) == DImode ?
- COSTS_N_INSNS (68) : COSTS_N_INSNS (37));
- if (sparc_cpu == PROCESSOR_ULTRASPARC3)
- return (GET_MODE (x) == DImode ?
- COSTS_N_INSNS (71) : COSTS_N_INSNS (40));
- return COSTS_N_INSNS (25);
+ *total = (GET_MODE (x) == DImode
+ ? COSTS_N_INSNS (68) : COSTS_N_INSNS (37));
+ else if (sparc_cpu == PROCESSOR_ULTRASPARC3)
+ *total = (GET_MODE (x) == DImode
+ ? COSTS_N_INSNS (71) : COSTS_N_INSNS (40));
+ else
+ *total = COSTS_N_INSNS (25);
+ return true;
case IF_THEN_ELSE:
/* Conditional moves. */
switch (sparc_cpu)
{
case PROCESSOR_ULTRASPARC:
- return COSTS_N_INSNS (2);
+ *total = COSTS_N_INSNS (2);
+ return true;
case PROCESSOR_ULTRASPARC3:
if (FLOAT_MODE_P (GET_MODE (x)))
- return COSTS_N_INSNS (3);
+ *total = COSTS_N_INSNS (3);
else
- return COSTS_N_INSNS (2);
+ *total = COSTS_N_INSNS (2);
+ return true;
default:
- return COSTS_N_INSNS (1);
+ *total = COSTS_N_INSNS (1);
+ return true;
}
case MEM:
@@ -8428,9 +9194,10 @@ sparc_rtx_costs (x, code, outer_code)
{
case PROCESSOR_ULTRASPARC:
if (outer_code == ZERO_EXTEND)
- return COSTS_N_INSNS (1);
+ *total = COSTS_N_INSNS (1);
else
- return COSTS_N_INSNS (2);
+ *total = COSTS_N_INSNS (2);
+ return true;
case PROCESSOR_ULTRASPARC3:
if (outer_code == ZERO_EXTEND)
@@ -8438,112 +9205,110 @@ sparc_rtx_costs (x, code, outer_code)
if (GET_MODE (x) == QImode
|| GET_MODE (x) == HImode
|| outer_code == SIGN_EXTEND)
- return COSTS_N_INSNS (2);
+ *total = COSTS_N_INSNS (2);
else
- return COSTS_N_INSNS (1);
+ *total = COSTS_N_INSNS (1);
}
else
{
/* This handles sign extension (3 cycles)
and everything else (2 cycles). */
- return COSTS_N_INSNS (2);
+ *total = COSTS_N_INSNS (2);
}
+ return true;
case PROCESSOR_SUPERSPARC:
if (FLOAT_MODE_P (GET_MODE (x))
|| outer_code == ZERO_EXTEND
|| outer_code == SIGN_EXTEND)
- return COSTS_N_INSNS (0);
+ *total = COSTS_N_INSNS (0);
else
- return COSTS_N_INSNS (1);
+ *total = COSTS_N_INSNS (1);
+ return true;
case PROCESSOR_TSC701:
if (outer_code == ZERO_EXTEND
|| outer_code == SIGN_EXTEND)
- return COSTS_N_INSNS (2);
+ *total = COSTS_N_INSNS (2);
else
- return COSTS_N_INSNS (3);
+ *total = COSTS_N_INSNS (3);
+ return true;
case PROCESSOR_CYPRESS:
if (outer_code == ZERO_EXTEND
|| outer_code == SIGN_EXTEND)
- return COSTS_N_INSNS (1);
+ *total = COSTS_N_INSNS (1);
else
- return COSTS_N_INSNS (2);
+ *total = COSTS_N_INSNS (2);
+ return true;
case PROCESSOR_HYPERSPARC:
case PROCESSOR_SPARCLITE86X:
default:
if (outer_code == ZERO_EXTEND
|| outer_code == SIGN_EXTEND)
- return COSTS_N_INSNS (0);
+ *total = COSTS_N_INSNS (0);
else
- return COSTS_N_INSNS (1);
+ *total = COSTS_N_INSNS (1);
+ return true;
}
case CONST_INT:
if (INTVAL (x) < 0x1000 && INTVAL (x) >= -0x1000)
- return 0;
+ {
+ *total = 0;
+ return true;
+ }
+ /* FALLTHRU */
- /* fallthru */
case HIGH:
- return 2;
+ *total = 2;
+ return true;
case CONST:
case LABEL_REF:
case SYMBOL_REF:
- return 4;
+ *total = 4;
+ return true;
case CONST_DOUBLE:
- if (GET_MODE (x) == DImode)
- if ((XINT (x, 3) == 0
- && (unsigned) XINT (x, 2) < 0x1000)
- || (XINT (x, 3) == -1
- && XINT (x, 2) < 0
- && XINT (x, 2) >= -0x1000))
- return 0;
- return 8;
+ if (GET_MODE (x) == DImode
+ && ((XINT (x, 3) == 0
+ && (unsigned HOST_WIDE_INT) XINT (x, 2) < 0x1000)
+ || (XINT (x, 3) == -1
+ && XINT (x, 2) < 0
+ && XINT (x, 2) >= -0x1000)))
+ *total = 0;
+ else
+ *total = 8;
+ return true;
default:
- abort();
- };
-}
-
-/* If we are referencing a function make the SYMBOL_REF special. In
- the Embedded Medium/Anywhere code model, %g4 points to the data
- segment so we must not add it to function addresses. */
-
-static void
-sparc_encode_section_info (decl, first)
- tree decl;
- int first ATTRIBUTE_UNUSED;
-{
- if (TARGET_CM_EMBMEDANY && TREE_CODE (decl) == FUNCTION_DECL)
- SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
+ return false;
+ }
}
/* Output code to add DELTA to the first argument, and then jump to FUNCTION.
Used for C++ multiple inheritance. */
static void
-sparc_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
- FILE *file;
- tree thunk_fndecl ATTRIBUTE_UNUSED;
- HOST_WIDE_INT delta;
- HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
- tree function;
+sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
+ HOST_WIDE_INT delta,
+ HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
+ tree function)
{
rtx this, insn, funexp, delta_rtx, tmp;
reload_completed = 1;
+ epilogue_completed = 1;
no_new_pseudos = 1;
current_function_uses_only_leaf_regs = 1;
- emit_note (NULL, NOTE_INSN_PROLOGUE_END);
+ emit_note (NOTE_INSN_PROLOGUE_END);
/* Find the "this" pointer. Normally in %o0, but in ARCH64 if the function
returns a structure, the structure return pointer is there instead. */
- if (TARGET_ARCH64 && aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
+ if (TARGET_ARCH64 && aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
this = gen_rtx_REG (Pmode, SPARC_INCOMING_INT_ARG_FIRST + 1);
else
this = gen_rtx_REG (Pmode, SPARC_INCOMING_INT_ARG_FIRST);
@@ -8554,10 +9319,17 @@ sparc_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
if (!SPARC_SIMM13_P (delta))
{
rtx scratch = gen_rtx_REG (Pmode, 1);
- if (TARGET_ARCH64)
- sparc_emit_set_const64 (scratch, delta_rtx);
+
+ if (input_operand (delta_rtx, GET_MODE (scratch)))
+ emit_insn (gen_rtx_SET (VOIDmode, scratch, delta_rtx));
else
- sparc_emit_set_const32 (scratch, delta_rtx);
+ {
+ if (TARGET_ARCH64)
+ sparc_emit_set_const64 (scratch, delta_rtx);
+ else
+ sparc_emit_set_const32 (scratch, delta_rtx);
+ }
+
delta_rtx = scratch;
}
@@ -8581,13 +9353,79 @@ sparc_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
instruction scheduling worth while. Note that use_thunk calls
assemble_start_function and assemble_end_function. */
insn = get_insns ();
+ insn_locators_initialize ();
shorten_branches (insn);
final_start_function (insn, file, 1);
final (insn, file, 1, 0);
final_end_function ();
reload_completed = 0;
+ epilogue_completed = 0;
no_new_pseudos = 0;
}
+/* How to allocate a 'struct machine_function'. */
+
+static struct machine_function *
+sparc_init_machine_status (void)
+{
+ return ggc_alloc_cleared (sizeof (struct machine_function));
+}
+
+/* Locate some local-dynamic symbol still in use by this function
+ so that we can print its name in local-dynamic base patterns. */
+
+static const char *
+get_some_local_dynamic_name (void)
+{
+ rtx insn;
+
+ if (cfun->machine->some_ld_name)
+ return cfun->machine->some_ld_name;
+
+ for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
+ if (INSN_P (insn)
+ && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
+ return cfun->machine->some_ld_name;
+
+ abort ();
+}
+
+static int
+get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
+{
+ rtx x = *px;
+
+ if (x
+ && GET_CODE (x) == SYMBOL_REF
+ && SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC)
+ {
+ cfun->machine->some_ld_name = XSTR (x, 0);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* This is called from dwarf2out.c via ASM_OUTPUT_DWARF_DTPREL.
+ We need to emit DTP-relative relocations. */
+
+void
+sparc_output_dwarf_dtprel (FILE *file, int size, rtx x)
+{
+ switch (size)
+ {
+ case 4:
+ fputs ("\t.word\t%r_tls_dtpoff32(", file);
+ break;
+ case 8:
+ fputs ("\t.xword\t%r_tls_dtpoff64(", file);
+ break;
+ default:
+ abort ();
+ }
+ output_addr_const (file, x);
+ fputs (")", file);
+}
+
#include "gt-sparc.h"
diff --git a/contrib/gcc/config/sparc/sparc.h b/contrib/gcc/config/sparc/sparc.h
index 7c6a7fd..3202359 100644
--- a/contrib/gcc/config/sparc/sparc.h
+++ b/contrib/gcc/config/sparc/sparc.h
@@ -1,30 +1,50 @@
/* Definitions of target machine for GNU compiler, for Sun SPARC.
Copyright (C) 1987, 1988, 1989, 1992, 1994, 1995, 1996, 1997, 1998, 1999
- 2000, 2001, 2002 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com).
- 64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
+ 64-bit SPARC-V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
at Cygnus Support.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Note that some other tm.h files include this one and then override
whatever definitions are necessary. */
+/* Target CPU builtins. FIXME: Defining sparc is for the benefit of
+ Solaris only; otherwise just define __sparc__. Sadly the headers
+ are such a mess there is no Solaris-specific header. */
+#define TARGET_CPU_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("sparc"); \
+ if (TARGET_64BIT) \
+ { \
+ builtin_assert ("cpu=sparc64"); \
+ builtin_assert ("machine=sparc64"); \
+ } \
+ else \
+ { \
+ builtin_assert ("cpu=sparc"); \
+ builtin_assert ("machine=sparc"); \
+ } \
+ } \
+ while (0)
+
/* Specify this in a cover file to provide bi-architecture (32/64) support. */
/* #define SPARC_BI_ARCH */
@@ -49,35 +69,41 @@ Boston, MA 02111-1307, USA. */
#endif /* IN_LIBGCC2 */
#define TARGET_ARCH64 (! TARGET_ARCH32)
-/* Code model selection.
- -mcmodel is used to select the v9 code model.
- Different code models aren't supported for v7/8 code.
-
- TARGET_CM_32: 32 bit address space, top 32 bits = 0,
- pointers are 32 bits. Note that this isn't intended
- to imply a v7/8 abi.
-
- TARGET_CM_MEDLOW: 32 bit address space, top 32 bits = 0,
- avoid generating %uhi and %ulo terms,
- pointers are 64 bits.
-
- TARGET_CM_MEDMID: 64 bit address space.
- The executable must be in the low 16 TB of memory.
- This corresponds to the low 44 bits, and the %[hml]44
- relocs are used. The text segment has a maximum size
- of 31 bits.
-
- TARGET_CM_MEDANY: 64 bit address space.
- The text and data segments have a maximum size of 31
- bits and may be located anywhere. The maximum offset
- from any instruction to the label _GLOBAL_OFFSET_TABLE_
- is 31 bits.
-
- TARGET_CM_EMBMEDANY: 64 bit address space.
- The text and data segments have a maximum size of 31 bits
- and may be located anywhere. Register %g4 contains
- the start address of the data segment.
-*/
+/* Code model selection in 64-bit environment.
+
+ The machine mode used for addresses is 32-bit wide:
+
+ TARGET_CM_32: 32-bit address space.
+ It is the code model used when generating 32-bit code.
+
+ The machine mode used for addresses is 64-bit wide:
+
+ TARGET_CM_MEDLOW: 32-bit address space.
+ The executable must be in the low 32 bits of memory.
+ This avoids generating %uhi and %ulo terms. Programs
+ can be statically or dynamically linked.
+
+ TARGET_CM_MEDMID: 44-bit address space.
+ The executable must be in the low 44 bits of memory,
+ and the %[hml]44 terms are used. The text and data
+ segments have a maximum size of 2GB (31-bit span).
+ The maximum offset from any instruction to the label
+ _GLOBAL_OFFSET_TABLE_ is 2GB (31-bit span).
+
+ TARGET_CM_MEDANY: 64-bit address space.
+ The text and data segments have a maximum size of 2GB
+ (31-bit span) and may be located anywhere in memory.
+ The maximum offset from any instruction to the label
+ _GLOBAL_OFFSET_TABLE_ is 2GB (31-bit span).
+
+ TARGET_CM_EMBMEDANY: 64-bit address space.
+ The text and data segments have a maximum size of 2GB
+ (31-bit span) and may be located anywhere in memory.
+ The global register %g4 contains the start address of
+ the data segment. Programs are statically linked and
+ PIC is not supported.
+
+ Different code models are not supported in 32-bit environment. */
enum cmodel {
CM_32,
@@ -239,15 +265,8 @@ extern enum cmodel sparc_cmodel;
%{mcpu=ultrasparc3:-D__sparc_v9__} \
%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_cpu_default)}}}}}}} \
"
-
-/* ??? The GCC_NEW_VARARGS macro is now obsolete, because gcc always uses
- the right varags.h file when bootstrapping. */
-/* ??? It's not clear what value we want to use for -Acpu/machine for
- sparc64 in 32 bit environments, so for now we only use `sparc64' in
- 64 bit environments. */
-
-#define CPP_ARCH32_SPEC "-D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc"
-#define CPP_ARCH64_SPEC "-D__arch64__ -Acpu=sparc64 -Amachine=sparc64"
+#define CPP_ARCH32_SPEC ""
+#define CPP_ARCH64_SPEC "-D__arch64__"
#define CPP_ARCH_DEFAULT_SPEC \
(DEFAULT_ARCH32_P ? CPP_ARCH32_SPEC : CPP_ARCH64_SPEC)
@@ -323,15 +342,17 @@ extern enum cmodel sparc_cmodel;
/* Special flags to the Sun-4 assembler when using pipe for input. */
#define ASM_SPEC "\
-%| %{R} %{!pg:%{!p:%{fpic:-k} %{fPIC:-k}}} %{keep-local-as-symbols:-L} \
+%{R} %{!pg:%{!p:%{fpic|fPIC|fpie|fPIE:-k}}} %{keep-local-as-symbols:-L} \
%(asm_cpu) %(asm_relax)"
+#define AS_NEEDS_DASH_FOR_PIPED_INPUT
+
/* This macro defines names of additional specifications to put in the specs
that can be used in various specifications like CC1_SPEC. Its definition
is an initializer with a subgrouping for each command option.
Each subgrouping contains a string constant, that defines the
- specification name, and a string constant that used by the GNU CC driver
+ specification name, and a string constant that used by the GCC driver
program.
Do not define this macro if it does not need to do anything. */
@@ -630,17 +651,27 @@ extern enum processor_type sparc_cpu;
#define TARGET_OPTIONS \
{ \
{ "cpu=", &sparc_select[1].string, \
- N_("Use features of and schedule code for given CPU") }, \
+ N_("Use features of and schedule code for given CPU"), 0}, \
{ "tune=", &sparc_select[2].string, \
- N_("Schedule code for given CPU") }, \
+ N_("Schedule code for given CPU"), 0}, \
{ "cmodel=", &sparc_cmodel_string, \
- N_("Use given SPARC code model") }, \
+ N_("Use given SPARC code model"), 0}, \
SUBTARGET_OPTIONS \
}
/* This is meant to be redefined in target specific files. */
#define SUBTARGET_OPTIONS
+/* Support for a compile-time default CPU, et cetera. The rules are:
+ --with-cpu is ignored if -mcpu is specified.
+ --with-tune is ignored if -mtune is specified.
+ --with-float is ignored if -mhard-float, -msoft-float, -mfpu, or -mno-fpu
+ are specified. */
+#define OPTION_DEFAULT_SPECS \
+ {"cpu", "%{!mcpu=*:-mcpu=%(VALUE)}" }, \
+ {"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \
+ {"float", "%{!msoft-float:%{!mhard-float:%{!fpu:%{!no-fpu:-m%(VALUE)-float}}}}" }
+
/* sparc_select[0] is reserved for the default cpu. */
struct sparc_cpu_select
{
@@ -755,7 +786,13 @@ if (TARGET_ARCH64 \
#define PARM_BOUNDARY (TARGET_ARCH64 ? 64 : 32)
/* Boundary (in *bits*) on which stack pointer should be aligned. */
+/* FIXME, this is wrong when TARGET_ARCH64 and TARGET_STACK_BIAS, because
+ then sp+2047 is 128-bit aligned so sp is really only byte-aligned. */
#define STACK_BOUNDARY (TARGET_ARCH64 ? 128 : 64)
+/* Temporary hack until the FIXME above is fixed. This macro is used
+ only in pad_to_arg_alignment in function.c; see the comment there
+ for details about what it does. */
+#define SPARC_STACK_BOUNDARY_HACK (TARGET_ARCH64 && TARGET_STACK_BIAS)
/* ALIGN FRAMES on double word boundaries */
@@ -1018,7 +1055,7 @@ while (0)
: (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
+/* Due to the ARCH64 discrepancy above we must override this next
macro too. */
#define REGMODE_NATURAL_SIZE(MODE) \
((TARGET_ARCH64 && FLOAT_MODE_P (MODE)) ? 4 : UNITS_PER_WORD)
@@ -1126,8 +1163,7 @@ extern int sparc_mode_class[];
#define RETURN_IN_MEMORY(TYPE) \
(TARGET_ARCH32 \
? (TYPE_MODE (TYPE) == BLKmode \
- || TYPE_MODE (TYPE) == TFmode \
- || TYPE_MODE (TYPE) == TCmode) \
+ || TYPE_MODE (TYPE) == TFmode) \
: (TYPE_MODE (TYPE) == BLKmode \
&& (unsigned HOST_WIDE_INT) int_size_in_bytes (TYPE) > 32))
@@ -1233,6 +1269,20 @@ enum reg_class { NO_REGS, FPCC_REGS, I64_REGS, GENERAL_REGS, FP_REGS,
{-1, -1, -1, 0x20}, /* GENERAL_OR_EXTRA_FP_REGS */ \
{-1, -1, -1, 0x3f}} /* ALL_REGS */
+/* Defines invalid mode changes. Borrowed from pa64-regs.h.
+
+ SImode loads to floating-point registers are not zero-extended.
+ The definition for LOAD_EXTEND_OP specifies that integer loads
+ narrower than BITS_PER_WORD will be zero-extended. As a result,
+ we inhibit changes from SImode unless they are to a mode that is
+ identical in size. */
+
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (TARGET_ARCH64 \
+ && (FROM) == SImode \
+ && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+ ? reg_classes_intersect_p (CLASS, FP_REGS) : 0)
+
/* The same information, inverted:
Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression
@@ -1253,7 +1303,7 @@ extern enum reg_class sparc_regno_reg_class[FIRST_PSEUDO_REGISTER];
We know in this case that we will not end up with a leaf function.
- The register allocater is given the global and out registers first
+ The register allocator is given the global and out registers first
because these registers are call clobbered and thus less useful to
global register allocation.
@@ -1626,13 +1676,13 @@ extern char leaf_reg_remap[];
#define BASE_RETURN_VALUE_REG(MODE) \
(TARGET_ARCH64 \
? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 8) \
- : (((MODE) == SFmode || (MODE) == DFmode) && TARGET_FPU ? 32 : 8))
+ : (TARGET_FPU && FLOAT_MODE_P (MODE) && (MODE) != TFmode ? 32 : 8))
#define BASE_OUTGOING_VALUE_REG(MODE) \
(TARGET_ARCH64 \
? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 \
: TARGET_FLAT ? 8 : 24) \
- : (((MODE) == SFmode || (MODE) == DFmode) && TARGET_FPU ? 32 \
+ : (TARGET_FPU && FLOAT_MODE_P (MODE) && (MODE) != TFmode ? 32\
: (TARGET_FLAT ? 8 : 24)))
#define BASE_PASSING_ARG_REG(MODE) \
@@ -1735,8 +1785,8 @@ struct sparc_args {
for a call to a function whose data type is FNTYPE.
For a library call, FNTYPE is 0. */
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
-init_cumulative_args (& (CUM), (FNTYPE), (LIBNAME), (INDIRECT));
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
+init_cumulative_args (& (CUM), (FNTYPE), (LIBNAME), (FNDECL));
/* Update the data in CUM to advance over an argument
of mode MODE and data type TYPE.
@@ -1935,27 +1985,6 @@ 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.
-
- 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. */
#define SETUP_FRAME_ADDRESSES() \
@@ -2050,12 +2079,6 @@ do { \
/* Addressing modes, and classification of registers for them. */
-/* #define HAVE_POST_INCREMENT 0 */
-/* #define HAVE_POST_DECREMENT 0 */
-
-/* #define HAVE_PRE_DECREMENT 0 */
-/* #define HAVE_PRE_INCREMENT 0 */
-
/* Macros to check register numbers against specific register classes. */
/* These assume that REGNO is a hard or pseudo reg number.
@@ -2101,27 +2124,18 @@ do { \
When PIC, we do not accept an address that would require a scratch reg
to load into a register. */
-#define CONSTANT_ADDRESS_P(X) \
- (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
- || GET_CODE (X) == CONST_INT || GET_CODE (X) == HIGH \
- || (GET_CODE (X) == CONST \
- && ! (flag_pic && pic_address_needs_scratch (X))))
+#define CONSTANT_ADDRESS_P(X) constant_address_p (X)
/* Define this, so that when PIC, reload won't try to reload invalid
addresses which require two reload registers. */
-#define LEGITIMATE_PIC_OPERAND_P(X) (! pic_address_needs_scratch (X))
+#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X)
/* Nonzero if the constant value X is a legitimate general operand.
Anything can be made to work except floating point constants.
If TARGET_VIS, 0.0 can be made to work as well. */
-#define LEGITIMATE_CONSTANT_P(X) \
- (GET_CODE (X) != CONST_DOUBLE || GET_MODE (X) == VOIDmode || \
- (TARGET_VIS && \
- (GET_MODE (X) == SFmode || GET_MODE (X) == DFmode || \
- GET_MODE (X) == TFmode) && \
- fp_zero_operand (X, GET_MODE (X))))
+#define LEGITIMATE_CONSTANT_P(X) legitimate_constant_p (X)
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class.
@@ -2228,110 +2242,19 @@ do { \
#define RTX_OK_FOR_OLO10_P(X) \
(GET_CODE (X) == CONST_INT && INTVAL (X) >= -0x1000 && INTVAL (X) < 0xc00 - 8)
+#ifdef REG_OK_STRICT
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
-{ if (RTX_OK_FOR_BASE_P (X)) \
+{ \
+ if (legitimate_address_p (MODE, X, 1)) \
goto ADDR; \
- else if (GET_CODE (X) == PLUS) \
- { \
- register rtx op0 = XEXP (X, 0); \
- register rtx op1 = XEXP (X, 1); \
- if (flag_pic && op0 == pic_offset_table_rtx) \
- { \
- if (RTX_OK_FOR_BASE_P (op1)) \
- goto ADDR; \
- else if (flag_pic == 1 \
- && GET_CODE (op1) != REG \
- && GET_CODE (op1) != LO_SUM \
- && GET_CODE (op1) != MEM \
- && (! SYMBOLIC_CONST (op1) \
- || MODE == Pmode) \
- && (GET_CODE (op1) != CONST_INT \
- || SMALL_INT (op1))) \
- goto ADDR; \
- } \
- else if (RTX_OK_FOR_BASE_P (op0)) \
- { \
- if ((RTX_OK_FOR_INDEX_P (op1) \
- /* We prohibit REG + REG for TFmode when \
- there are no instructions which accept \
- REG+REG instructions. We do this \
- because REG+REG is not an offsetable \
- address. If we get the situation \
- in reload where source and destination \
- of a movtf pattern are both MEMs with \
- REG+REG address, then only one of them \
- gets converted to an offsetable \
- address. */ \
- && (MODE != TFmode \
- || (TARGET_FPU && TARGET_ARCH64 \
- && TARGET_V9 \
- && TARGET_HARD_QUAD)) \
- /* We prohibit REG + REG on ARCH32 if \
- not optimizing for DFmode/DImode \
- because then mem_min_alignment is \
- likely to be zero after reload and the \
- forced split would lack a matching \
- splitter pattern. */ \
- && (TARGET_ARCH64 || optimize \
- || (MODE != DFmode \
- && MODE != DImode))) \
- || RTX_OK_FOR_OFFSET_P (op1)) \
- goto ADDR; \
- } \
- else if (RTX_OK_FOR_BASE_P (op1)) \
- { \
- if ((RTX_OK_FOR_INDEX_P (op0) \
- /* See the previous comment. */ \
- && (MODE != TFmode \
- || (TARGET_FPU && TARGET_ARCH64 \
- && TARGET_V9 \
- && TARGET_HARD_QUAD)) \
- && (TARGET_ARCH64 || optimize \
- || (MODE != DFmode \
- && MODE != DImode))) \
- || RTX_OK_FOR_OFFSET_P (op0)) \
- goto ADDR; \
- } \
- else if (USE_AS_OFFSETABLE_LO10 \
- && GET_CODE (op0) == LO_SUM \
- && TARGET_ARCH64 \
- && ! TARGET_CM_MEDMID \
- && RTX_OK_FOR_OLO10_P (op1)) \
- { \
- register rtx op00 = XEXP (op0, 0); \
- register rtx op01 = XEXP (op0, 1); \
- if (RTX_OK_FOR_BASE_P (op00) \
- && CONSTANT_P (op01)) \
- goto ADDR; \
- } \
- else if (USE_AS_OFFSETABLE_LO10 \
- && GET_CODE (op1) == LO_SUM \
- && TARGET_ARCH64 \
- && ! TARGET_CM_MEDMID \
- && RTX_OK_FOR_OLO10_P (op0)) \
- { \
- register rtx op10 = XEXP (op1, 0); \
- register rtx op11 = XEXP (op1, 1); \
- if (RTX_OK_FOR_BASE_P (op10) \
- && CONSTANT_P (op11)) \
- goto ADDR; \
- } \
- } \
- else if (GET_CODE (X) == LO_SUM) \
- { \
- register rtx op0 = XEXP (X, 0); \
- register rtx op1 = XEXP (X, 1); \
- if (RTX_OK_FOR_BASE_P (op0) \
- && CONSTANT_P (op1) \
- /* We can't allow TFmode, because an offset \
- greater than or equal to the alignment (8) \
- may cause the LO_SUM to overflow if !v9. */\
- && (MODE != TFmode || TARGET_V9)) \
- goto ADDR; \
- } \
- else if (GET_CODE (X) == CONST_INT && SMALL_INT (X)) \
+}
+#else
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ \
+ if (legitimate_address_p (MODE, X, 0)) \
goto ADDR; \
}
+#endif
/* Go to LABEL if ADDR (a legitimate address expression)
has an effect that depends on the machine mode it is used for.
@@ -2376,33 +2299,11 @@ do { \
/* On SPARC, change REG+N into REG+REG, and REG+(X*Y) into REG+REG. */
#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
-{ rtx sparc_x = (X); \
- if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == MULT) \
- (X) = gen_rtx_PLUS (Pmode, XEXP (X, 1), \
- force_operand (XEXP (X, 0), NULL_RTX)); \
- if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == MULT) \
- (X) = gen_rtx_PLUS (Pmode, XEXP (X, 0), \
- force_operand (XEXP (X, 1), NULL_RTX)); \
- if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == PLUS) \
- (X) = gen_rtx_PLUS (Pmode, force_operand (XEXP (X, 0), NULL_RTX),\
- XEXP (X, 1)); \
- if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == PLUS) \
- (X) = gen_rtx_PLUS (Pmode, XEXP (X, 0), \
- force_operand (XEXP (X, 1), NULL_RTX)); \
- if (sparc_x != (X) && memory_address_p (MODE, X)) \
- goto WIN; \
- if (flag_pic) (X) = legitimize_pic_address (X, MODE, 0); \
- else if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 1))) \
- (X) = gen_rtx_PLUS (Pmode, XEXP (X, 0), \
- copy_to_mode_reg (Pmode, XEXP (X, 1))); \
- else if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 0))) \
- (X) = gen_rtx_PLUS (Pmode, XEXP (X, 1), \
- copy_to_mode_reg (Pmode, XEXP (X, 0))); \
- else if (GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == CONST \
- || GET_CODE (X) == LABEL_REF) \
- (X) = copy_to_suggested_reg (X, NULL_RTX, Pmode); \
- if (memory_address_p (MODE, X)) \
- goto WIN; }
+{ \
+ (X) = legitimize_address (X, OLDX, MODE); \
+ if (memory_address_p (MODE, X)) \
+ goto WIN; \
+}
/* Try a machine-dependent way of reloading an illegitimate address
operand. If we find one, push the reload and jump to WIN. This
@@ -2491,11 +2392,6 @@ do { \
and maybe make use of that. */
#define SLOW_BYTE_ACCESS 1
-/* We assume that the store-condition-codes instructions store 0 for false
- and some other value for true. This is the value stored for true. */
-
-#define STORE_FLAG_VALUE 1
-
/* When a prototype says `char' or `short', really pass an `int'. */
#define PROMOTE_PROTOTYPES (TARGET_ARCH32)
@@ -2507,9 +2403,7 @@ do { \
is done just by pretending it is already truncated. */
#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-/* Specify the machine mode that pointers have.
- After generation of rtl, the compiler makes no further distinction
- between pointers and any other objects of this machine mode. */
+/* Specify the machine mode used for addresses. */
#define Pmode (TARGET_ARCH64 ? DImode : SImode)
/* Generate calls to memcpy, memcmp and memset. */
@@ -2540,100 +2434,20 @@ do { \
/* alloca should avoid clobbering the old register save area. */
#define SETJMP_VIA_SAVE_AREA
-/* Define subroutines to call to handle multiply and divide.
- Use the subroutines that Sun's library provides.
- The `*' prevents an underscore from being prepended by the compiler. */
-
-#define DIVSI3_LIBCALL "*.div"
-#define UDIVSI3_LIBCALL "*.udiv"
-#define MODSI3_LIBCALL "*.rem"
-#define UMODSI3_LIBCALL "*.urem"
-/* .umul is a little faster than .mul. */
-#define MULSI3_LIBCALL "*.umul"
-
-/* Define library calls for quad FP operations. These are all part of the
- SPARC 32bit ABI. */
-#define ADDTF3_LIBCALL "_Q_add"
-#define SUBTF3_LIBCALL "_Q_sub"
-#define NEGTF2_LIBCALL "_Q_neg"
-#define MULTF3_LIBCALL "_Q_mul"
-#define DIVTF3_LIBCALL "_Q_div"
-#define FLOATSITF2_LIBCALL "_Q_itoq"
-#define FIX_TRUNCTFSI2_LIBCALL "_Q_qtoi"
-#define FIXUNS_TRUNCTFSI2_LIBCALL "_Q_qtou"
-#define EXTENDSFTF2_LIBCALL "_Q_stoq"
-#define TRUNCTFSF2_LIBCALL "_Q_qtos"
-#define EXTENDDFTF2_LIBCALL "_Q_dtoq"
-#define TRUNCTFDF2_LIBCALL "_Q_qtod"
-#define EQTF2_LIBCALL "_Q_feq"
-#define NETF2_LIBCALL "_Q_fne"
-#define GTTF2_LIBCALL "_Q_fgt"
-#define GETF2_LIBCALL "_Q_fge"
-#define LTTF2_LIBCALL "_Q_flt"
-#define LETF2_LIBCALL "_Q_fle"
+/* The _Q_* comparison libcalls return booleans. */
+#define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) ((MODE) == TFmode)
/* Assume by default that the _Qp_* 64-bit libcalls are implemented such
that the inputs are fully consumed before the output memory is clobbered. */
#define TARGET_BUGGY_QP_LIB 0
-/* We can define the TFmode sqrt optab only if TARGET_FPU. This is because
- with soft-float, the SFmode and DFmode sqrt instructions will be absent,
- and the compiler will notice and try to use the TFmode sqrt instruction
- for calls to the builtin function sqrt, but this fails. */
-#define INIT_TARGET_OPTABS \
- do { \
- if (TARGET_ARCH32) \
- { \
- add_optab->handlers[(int) TFmode].libfunc \
- = init_one_libfunc (ADDTF3_LIBCALL); \
- sub_optab->handlers[(int) TFmode].libfunc \
- = init_one_libfunc (SUBTF3_LIBCALL); \
- neg_optab->handlers[(int) TFmode].libfunc \
- = init_one_libfunc (NEGTF2_LIBCALL); \
- smul_optab->handlers[(int) TFmode].libfunc \
- = init_one_libfunc (MULTF3_LIBCALL); \
- sdiv_optab->handlers[(int) TFmode].libfunc \
- = init_one_libfunc (DIVTF3_LIBCALL); \
- eqtf2_libfunc = init_one_libfunc (EQTF2_LIBCALL); \
- netf2_libfunc = init_one_libfunc (NETF2_LIBCALL); \
- gttf2_libfunc = init_one_libfunc (GTTF2_LIBCALL); \
- getf2_libfunc = init_one_libfunc (GETF2_LIBCALL); \
- lttf2_libfunc = init_one_libfunc (LTTF2_LIBCALL); \
- letf2_libfunc = init_one_libfunc (LETF2_LIBCALL); \
- trunctfsf2_libfunc = init_one_libfunc (TRUNCTFSF2_LIBCALL); \
- trunctfdf2_libfunc = init_one_libfunc (TRUNCTFDF2_LIBCALL); \
- extendsftf2_libfunc = init_one_libfunc (EXTENDSFTF2_LIBCALL); \
- extenddftf2_libfunc = init_one_libfunc (EXTENDDFTF2_LIBCALL); \
- floatsitf_libfunc = init_one_libfunc (FLOATSITF2_LIBCALL); \
- fixtfsi_libfunc = init_one_libfunc (FIX_TRUNCTFSI2_LIBCALL); \
- fixunstfsi_libfunc \
- = init_one_libfunc (FIXUNS_TRUNCTFSI2_LIBCALL); \
- if (TARGET_FPU) \
- sqrt_optab->handlers[(int) TFmode].libfunc \
- = init_one_libfunc ("_Q_sqrt"); \
- } \
- if (TARGET_ARCH64) \
- { \
- /* In the SPARC 64bit ABI, these libfuncs do not exist in the \
- library. Make sure the compiler does not emit calls to them \
- by accident. */ \
- sdiv_optab->handlers[(int) SImode].libfunc = NULL; \
- udiv_optab->handlers[(int) SImode].libfunc = NULL; \
- smod_optab->handlers[(int) SImode].libfunc = NULL; \
- umod_optab->handlers[(int) SImode].libfunc = NULL; \
- smul_optab->handlers[(int) SImode].libfunc = NULL; \
- } \
- INIT_SUBTARGET_OPTABS; \
- } while (0)
-
-/* This is meant to be redefined in the host dependent files */
-#define INIT_SUBTARGET_OPTABS
+/* Assume by default that we do not have the Solaris-specific conversion
+ routines nor 64-bit integer multiply and divide routines. */
-/* Nonzero if a floating point comparison library call for
- mode MODE that will return a boolean value. Zero if one
- of the libgcc2 functions is used. */
-#define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) ((MODE) == TFmode)
+#define SUN_CONVERSION_LIBFUNCS 0
+#define DITF_CONVERSION_LIBFUNCS 0
+#define SUN_INTEGER_MULTIPLY_64 0
/* Compute extra cost of moving data between one register class
and another. */
@@ -2662,29 +2476,6 @@ do { \
: (sparc_cpu == PROCESSOR_ULTRASPARC3 \
? 9 : 3))
-/* The cases that RTX_COSTS handles. */
-
-#define RTX_COSTS_CASES \
-case PLUS: case MINUS: case ABS: case NEG: \
-case FLOAT: case UNSIGNED_FLOAT: \
-case FIX: case UNSIGNED_FIX: \
-case FLOAT_EXTEND: case FLOAT_TRUNCATE: \
-case SQRT: \
-case COMPARE: case IF_THEN_ELSE: \
-case MEM: \
-case MULT: case DIV: case UDIV: case MOD: case UMOD: \
-case CONST_INT: case HIGH: case CONST: \
-case LABEL_REF: case SYMBOL_REF: case CONST_DOUBLE:
-
-/* Provide the costs of a rtl expression. This is in the body of a
- switch on CODE. */
-
-#define RTX_COSTS(X,CODE,OUTER_CODE) \
- RTX_COSTS_CASES \
- return sparc_rtx_costs(X,CODE,OUTER_CODE);
-
-#define ADDRESS_COST(RTX) 1
-
#define PREFETCH_BLOCK \
((sparc_cpu == PROCESSOR_ULTRASPARC \
|| sparc_cpu == PROCESSOR_ULTRASPARC3) \
@@ -2698,10 +2489,6 @@ case LABEL_REF: case SYMBOL_REF: case CONST_DOUBLE:
/* Control the assembler format that we output. */
-/* Output at beginning of assembler file. */
-
-#define ASM_FILE_START(file)
-
/* A C string constant describing how to begin a comment in the target
assembler language. The compiler assumes that the comment will end at
the end of the line. */
@@ -2765,12 +2552,6 @@ case LABEL_REF: case SYMBOL_REF: case CONST_DOUBLE:
#define USER_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. */
-
-#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
- fprintf (FILE, "%s%d:\n", 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.
@@ -2849,7 +2630,7 @@ do { \
fprintf (FILE, "\t.align %d,0x1000000\n", (1<<(LOG)))
#define ASM_OUTPUT_SKIP(FILE,SIZE) \
- fprintf (FILE, "\t.skip %u\n", (SIZE))
+ fprintf (FILE, "\t.skip "HOST_WIDE_INT_PRINT_UNSIGNED"\n", (SIZE))
/* This says how to output an assembler line
to define a global common symbol. */
@@ -2857,7 +2638,7 @@ do { \
#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
( fputs ("\t.common ", (FILE)), \
assemble_name ((FILE), (NAME)), \
- fprintf ((FILE), ",%u,\"bss\"\n", (SIZE)))
+ fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",\"bss\"\n", (SIZE)))
/* This says how to output an assembler line to define a local common
symbol. */
@@ -2865,7 +2646,7 @@ do { \
#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGNED) \
( fputs ("\t.reserve ", (FILE)), \
assemble_name ((FILE), (NAME)), \
- fprintf ((FILE), ",%u,\"bss\",%u\n", \
+ fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",\"bss\",%u\n", \
(SIZE), ((ALIGNED) / BITS_PER_UNIT)))
/* A C statement (sans semicolon) to output to the stdio stream
@@ -2875,20 +2656,9 @@ do { \
#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
do { \
- fputs (".globl ", (FILE)); \
- assemble_name ((FILE), (NAME)); \
- fputs ("\n", (FILE)); \
ASM_OUTPUT_ALIGNED_LOCAL (FILE, NAME, SIZE, ALIGN); \
} while (0)
-/* Store in OUTPUT a string (made with alloca) containing
- an assembler-name for a local static variable named NAME.
- LABELNO is an integer which is different for each call. */
-
-#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
-( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
- sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
-
#define IDENT_ASM_OP "\t.ident\t"
/* Output #ident as a .ident. */
@@ -2896,8 +2666,16 @@ do { \
#define ASM_OUTPUT_IDENT(FILE, NAME) \
fprintf (FILE, "%s\"%s\"\n", IDENT_ASM_OP, NAME);
+/* Emit a dtp-relative reference to a TLS variable. */
+
+#ifdef HAVE_AS_TLS
+#define ASM_OUTPUT_DWARF_DTPREL(FILE, SIZE, X) \
+ sparc_output_dwarf_dtprel (FILE, SIZE, X)
+#endif
+
#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
- ((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' || (CHAR) == '(' || (CHAR) == '_')
+ ((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' \
+ || (CHAR) == '(' || (CHAR) == '_' || (CHAR) == '&')
/* Print operand X (an rtx) in assembler syntax to file FILE.
CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
@@ -2984,6 +2762,14 @@ do { \
} \
}
+#ifdef HAVE_AS_TLS
+#define TARGET_TLS 1
+#else
+#define TARGET_TLS 0
+#endif
+#define TARGET_SUN_TLS TARGET_TLS
+#define TARGET_GNU_TLS 0
+
/* Define the codes that are matched by predicates in sparc.c. */
#define PREDICATE_CODES \
@@ -3030,8 +2816,13 @@ do { \
{"uns_arith_operand", {SUBREG, REG, CONST_INT}}, \
{"clobbered_register", {REG}}, \
{"input_operand", {SUBREG, REG, CONST_INT, MEM, CONST}}, \
+{"compare_operand", {SUBREG, REG, ZERO_EXTRACT}}, \
{"const64_operand", {CONST_INT, CONST_DOUBLE}}, \
-{"const64_high_operand", {CONST_INT, CONST_DOUBLE}},
+{"const64_high_operand", {CONST_INT, CONST_DOUBLE}}, \
+{"tgd_symbolic_operand", {SYMBOL_REF}}, \
+{"tld_symbolic_operand", {SYMBOL_REF}}, \
+{"tie_symbolic_operand", {SYMBOL_REF}}, \
+{"tle_symbolic_operand", {SYMBOL_REF}},
/* The number of Pmode words for the setjmp buffer. */
#define JMP_BUF_SIZE 12
diff --git a/contrib/gcc/config/sparc/sparc.md b/contrib/gcc/config/sparc/sparc.md
index b53013e..c7da780 100644
--- a/contrib/gcc/config/sparc/sparc.md
+++ b/contrib/gcc/config/sparc/sparc.md
@@ -1,24 +1,24 @@
-;; Machine description for SPARC chip for GNU C compiler
+;; Machine description for SPARC chip for GCC
;; Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-;; 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+;; 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
;; Contributed by Michael Tiemann (tiemann@cygnus.com)
-;; 64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
+;; 64-bit SPARC-V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
;; at Cygnus Support.
-;; This file is part of GNU CC.
+;; This file is part of GCC.
-;; GNU CC is free software; you can redistribute it and/or modify
+;; GCC is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
-;; GNU CC is distributed in the hope that it will be useful,
+;; GCC is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU CC; see the file COPYING. If not, write to
+;; along with GCC; see the file COPYING. If not, write to
;; the Free Software Foundation, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
@@ -38,6 +38,13 @@
(UNSPEC_EMB_TEXTHI 14)
(UNSPEC_EMB_TEXTULO 15)
(UNSPEC_EMB_SETHM 18)
+
+ (UNSPEC_TLSGD 30)
+ (UNSPEC_TLSLDM 31)
+ (UNSPEC_TLSLDO 32)
+ (UNSPEC_TLSIE 33)
+ (UNSPEC_TLSLE 34)
+ (UNSPEC_TLSLD_BASE 35)
])
(define_constants
@@ -99,6 +106,7 @@
fpcmp,
fpmul,fpdivs,fpdivd,
fpsqrts,fpsqrtd,
+ fga,fgm_pack,fgm_mul,fgm_pdist,fgm_cmp,
cmove,
ialuX,
multi,flushw,iflush,trap"
@@ -120,6 +128,8 @@
(symbol_ref "TARGET_FLAT != 0"))
;; Length (in # of insns).
+;; Beware that setting a length greater or equal to 3 for conditional branches
+;; has a side-effect (see output_cbranch and output_v9branch).
(define_attr "length" ""
(cond [(eq_attr "type" "uncond_branch,call,sibcall")
(if_then_else (eq_attr "empty_delay_slot" "true")
@@ -199,6 +209,9 @@
;; Attributes for instruction and branch scheduling
+(define_attr "tls_call_delay" "false,true"
+ (symbol_ref "tls_call_delay (insn)"))
+
(define_attr "in_call_delay" "false,true"
(cond [(eq_attr "type" "uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
(const_string "false")
@@ -206,7 +219,8 @@
(if_then_else (eq_attr "length" "1")
(const_string "true")
(const_string "false"))]
- (if_then_else (eq_attr "length" "1")
+ (if_then_else (and (eq_attr "length" "1")
+ (eq_attr "tls_call_delay" "true"))
(const_string "true")
(const_string "false"))))
@@ -290,10 +304,13 @@
(define_expand "cmpsi"
[(set (reg:CC 100)
- (compare:CC (match_operand:SI 0 "register_operand" "")
+ (compare:CC (match_operand:SI 0 "compare_operand" "")
(match_operand:SI 1 "arith_operand" "")))]
""
{
+ if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx)
+ operands[0] = force_reg (SImode, operands[0]);
+
sparc_compare_op0 = operands[0];
sparc_compare_op1 = operands[1];
DONE;
@@ -301,10 +318,13 @@
(define_expand "cmpdi"
[(set (reg:CCX 100)
- (compare:CCX (match_operand:DI 0 "register_operand" "")
+ (compare:CCX (match_operand:DI 0 "compare_operand" "")
(match_operand:DI 1 "arith_double_operand" "")))]
"TARGET_ARCH64"
{
+ if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx)
+ operands[0] = force_reg (DImode, operands[0]);
+
sparc_compare_op0 = operands[0];
sparc_compare_op1 = operands[1];
DONE;
@@ -1685,6 +1705,10 @@
}
}
+ /* Fixup TLS cases. */
+ if (tls_symbolic_operand (operands [1]))
+ operands[1] = legitimize_tls_address (operands[1]);
+
/* Fixup PIC cases. */
if (flag_pic)
{
@@ -1744,6 +1768,10 @@
}
}
+ /* Fixup TLS cases. */
+ if (tls_symbolic_operand (operands [1]))
+ operands[1] = legitimize_tls_address (operands[1]);
+
/* Fixup PIC cases. */
if (flag_pic)
{
@@ -1798,8 +1826,8 @@
;; We always work with constants here.
(define_insn "*movhi_lo_sum"
[(set (match_operand:HI 0 "register_operand" "=r")
- (ior:HI (match_operand:HI 1 "arith_operand" "%r")
- (match_operand:HI 2 "arith_operand" "I")))]
+ (ior:HI (match_operand:HI 1 "register_operand" "%r")
+ (match_operand:HI 2 "small_int" "I")))]
""
"or\t%1, %2, %0")
@@ -1826,6 +1854,10 @@
}
}
+ /* Fixup TLS cases. */
+ if (tls_symbolic_operand (operands [1]))
+ operands[1] = legitimize_tls_address (operands[1]);
+
/* Fixup PIC cases. */
if (flag_pic)
{
@@ -1897,7 +1929,7 @@
st\t%r1, %0
st\t%1, %0
fzeros\t%0"
- [(set_attr "type" "*,fpmove,*,*,load,fpload,store,fpstore,fpmove")])
+ [(set_attr "type" "*,fpmove,*,*,load,fpload,store,fpstore,fga")])
(define_insn "*movsi_lo_sum"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -2002,6 +2034,10 @@
}
}
+ /* Fixup TLS cases. */
+ if (tls_symbolic_operand (operands [1]))
+ operands[1] = legitimize_tls_address (operands[1]);
+
if (flag_pic)
{
if (CONSTANT_P (operands[1])
@@ -2165,7 +2201,7 @@
ldd\t%1, %0
std\t%1, %0
fzero\t%0"
- [(set_attr "type" "*,*,*,load,store,fpmove,fpload,fpstore,fpmove")
+ [(set_attr "type" "*,*,*,load,store,fpmove,fpload,fpstore,fga")
(set_attr "fptype" "*,*,*,*,*,double,*,*,double")])
(define_expand "movdi_pic_label_ref"
@@ -2613,7 +2649,7 @@
abort();
}
}
- [(set_attr "type" "fpmove,fpmove,*,*,*,*,load,fpload,fpstore,store")])
+ [(set_attr "type" "fpmove,fga,*,*,*,*,load,fpload,fpstore,store")])
;; Exactly the same as above, except that all `f' cases are deleted.
;; This is necessary to prevent reload from ever trying to use a `f' reg
@@ -2930,7 +2966,7 @@
#
#
#"
- [(set_attr "type" "fpmove,fpmove,load,store,store,load,store,*,*,*")
+ [(set_attr "type" "fga,fpmove,load,store,store,load,store,*,*,*")
(set_attr "length" "*,*,*,*,*,*,*,2,2,2")
(set_attr "fptype" "double,double,*,*,*,*,*,*,*,*")])
@@ -2977,7 +3013,7 @@
ldx\t%1, %0
stx\t%r1, %0
#"
- [(set_attr "type" "fpmove,fpmove,load,store,*,load,store,*")
+ [(set_attr "type" "fga,fpmove,load,store,*,load,store,*")
(set_attr "length" "*,*,*,*,*,*,*,2")
(set_attr "fptype" "double,double,*,*,*,*,*,*")])
@@ -3205,7 +3241,7 @@
operands[1]));
}
- /* Handle MEM cases first, note that only v9 guarentees
+ /* Handle MEM cases first, note that only v9 guarantees
full 16-byte alignment for quads. */
if (GET_CODE (operands[0]) == MEM)
{
@@ -4949,7 +4985,7 @@
add\t%1, %2, %0
sub\t%1, -%2, %0
fpadd32s\t%1, %2, %0"
- [(set_attr "type" "*,*,fp")])
+ [(set_attr "type" "*,*,fga")])
(define_insn "*cmp_cc_plus"
[(set (reg:CC_NOOV 100)
@@ -5105,7 +5141,7 @@
sub\t%1, %2, %0
add\t%1, -%2, %0
fpsub32s\t%1, %2, %0"
- [(set_attr "type" "*,*,fp")])
+ [(set_attr "type" "*,*,fga")])
(define_insn "*cmp_minus_cc"
[(set (reg:CC_NOOV 100)
@@ -5829,7 +5865,7 @@
"@
#
fand\t%1, %2, %0"
- [(set_attr "type" "*,fp")
+ [(set_attr "type" "*,fga")
(set_attr "length" "2,*")
(set_attr "fptype" "double")])
@@ -5841,7 +5877,7 @@
"@
and\t%1, %2, %0
fand\t%1, %2, %0"
- [(set_attr "type" "*,fp")
+ [(set_attr "type" "*,fga")
(set_attr "fptype" "double")])
(define_insn "andsi3"
@@ -5852,7 +5888,7 @@
"@
and\t%1, %2, %0
fands\t%1, %2, %0"
- [(set_attr "type" "*,fp")])
+ [(set_attr "type" "*,fga")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -5924,7 +5960,7 @@
operands[6] = gen_lowpart (SImode, operands[0]);
operands[7] = gen_lowpart (SImode, operands[1]);
operands[8] = gen_lowpart (SImode, operands[2]);"
- [(set_attr "type" "*,fp")
+ [(set_attr "type" "*,fga")
(set_attr "length" "2,*")
(set_attr "fptype" "double")])
@@ -5936,7 +5972,7 @@
"@
andn\t%2, %1, %0
fandnot1\t%1, %2, %0"
- [(set_attr "type" "*,fp")
+ [(set_attr "type" "*,fga")
(set_attr "fptype" "double")])
(define_insn "*and_not_si"
@@ -5947,7 +5983,7 @@
"@
andn\t%2, %1, %0
fandnot1s\t%1, %2, %0"
- [(set_attr "type" "*,fp")])
+ [(set_attr "type" "*,fga")])
(define_expand "iordi3"
[(set (match_operand:DI 0 "register_operand" "")
@@ -5964,7 +6000,7 @@
"@
#
for\t%1, %2, %0"
- [(set_attr "type" "*,fp")
+ [(set_attr "type" "*,fga")
(set_attr "length" "2,*")
(set_attr "fptype" "double")])
@@ -5976,7 +6012,7 @@
"@
or\t%1, %2, %0
for\t%1, %2, %0"
- [(set_attr "type" "*,fp")
+ [(set_attr "type" "*,fga")
(set_attr "fptype" "double")])
(define_insn "iorsi3"
@@ -5987,7 +6023,7 @@
"@
or\t%1, %2, %0
fors\t%1, %2, %0"
- [(set_attr "type" "*,fp")])
+ [(set_attr "type" "*,fga")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -6025,7 +6061,7 @@
operands[6] = gen_lowpart (SImode, operands[0]);
operands[7] = gen_lowpart (SImode, operands[1]);
operands[8] = gen_lowpart (SImode, operands[2]);"
- [(set_attr "type" "*,fp")
+ [(set_attr "type" "*,fga")
(set_attr "length" "2,*")
(set_attr "fptype" "double")])
@@ -6037,7 +6073,7 @@
"@
orn\t%2, %1, %0
fornot1\t%1, %2, %0"
- [(set_attr "type" "*,fp")
+ [(set_attr "type" "*,fga")
(set_attr "fptype" "double")])
(define_insn "*or_not_si"
@@ -6048,7 +6084,7 @@
"@
orn\t%2, %1, %0
fornot1s\t%1, %2, %0"
- [(set_attr "type" "*,fp")])
+ [(set_attr "type" "*,fga")])
(define_expand "xordi3"
[(set (match_operand:DI 0 "register_operand" "")
@@ -6065,7 +6101,7 @@
"@
#
fxor\t%1, %2, %0"
- [(set_attr "type" "*,fp")
+ [(set_attr "type" "*,fga")
(set_attr "length" "2,*")
(set_attr "fptype" "double")])
@@ -6077,7 +6113,7 @@
"@
xor\t%r1, %2, %0
fxor\t%1, %2, %0"
- [(set_attr "type" "*,fp")
+ [(set_attr "type" "*,fga")
(set_attr "fptype" "double")])
(define_insn "*xordi3_sp64_dbl"
@@ -6096,7 +6132,7 @@
"@
xor\t%r1, %2, %0
fxors\t%1, %2, %0"
- [(set_attr "type" "*,fp")])
+ [(set_attr "type" "*,fga")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -6150,7 +6186,7 @@
operands[6] = gen_lowpart (SImode, operands[0]);
operands[7] = gen_lowpart (SImode, operands[1]);
operands[8] = gen_lowpart (SImode, operands[2]);"
- [(set_attr "type" "*,fp")
+ [(set_attr "type" "*,fga")
(set_attr "length" "2,*")
(set_attr "fptype" "double")])
@@ -6162,7 +6198,7 @@
"@
xnor\t%r1, %2, %0
fxnor\t%1, %2, %0"
- [(set_attr "type" "*,fp")
+ [(set_attr "type" "*,fga")
(set_attr "fptype" "double")])
(define_insn "*xor_not_si"
@@ -6173,7 +6209,7 @@
"@
xnor\t%r1, %2, %0
fxnors\t%1, %2, %0"
- [(set_attr "type" "*,fp")])
+ [(set_attr "type" "*,fga")])
;; These correspond to the above in the case where we also (or only)
;; want to set the condition code.
@@ -6436,7 +6472,7 @@
operands[3] = gen_highpart (SImode, operands[1]);
operands[4] = gen_lowpart (SImode, operands[0]);
operands[5] = gen_lowpart (SImode, operands[1]);"
- [(set_attr "type" "*,fp")
+ [(set_attr "type" "*,fga")
(set_attr "length" "2,*")
(set_attr "fptype" "double")])
@@ -6447,7 +6483,7 @@
"@
xnor\t%%g0, %1, %0
fnot1\t%1, %0"
- [(set_attr "type" "*,fp")
+ [(set_attr "type" "*,fga")
(set_attr "fptype" "double")])
(define_insn "one_cmplsi2"
@@ -6457,7 +6493,7 @@
"@
xnor\t%%g0, %1, %0
fnot1s\t%1, %0"
- [(set_attr "type" "*,fp")])
+ [(set_attr "type" "*,fga")])
(define_insn "*cmp_cc_not"
[(set (reg:CC 100)
@@ -7212,27 +7248,10 @@
[(set_attr "type" "shift")])
;; Unconditional and other jump instructions
-;; On the SPARC, by setting the annul bit on an unconditional branch, the
-;; following insn is never executed. This saves us a nop. Dbx does not
-;; handle such branches though, so we only use them when optimizing.
(define_insn "jump"
[(set (pc) (label_ref (match_operand 0 "" "")))]
""
-{
- /* TurboSPARC is reported to have problems with
- with
- foo: b,a foo
- i.e. an empty loop with the annul bit set. The workaround is to use
- foo: b foo; nop
- instead. */
-
- if (! TARGET_V9 && flag_delayed_branch
- && (INSN_ADDRESSES (INSN_UID (operands[0]))
- == INSN_ADDRESSES (INSN_UID (insn))))
- return "b\t%l0%#";
- else
- return TARGET_V9 ? "ba%*,pt\t%%xcc, %l0%(" : "b%*\t%l0%(";
-}
+ "* return output_ubranch (operands[0], 0, insn);"
[(set_attr "type" "uncond_branch")])
(define_expand "tablejump"
@@ -7658,7 +7677,7 @@
emit_insn (gen_rtx_USE (VOIDmode, valreg2));
/* Construct the return. */
- expand_null_return ();
+ expand_naked_return ();
DONE;
})
@@ -7796,7 +7815,7 @@
;; For __builtin_setjmp we need to flush register windows iff the function
;; calls alloca as well, because otherwise the register window might be
-;; saved after %sp adjustement and thus setjmp would crash
+;; saved after %sp adjustment and thus setjmp would crash
(define_expand "builtin_setjmp_setup"
[(match_operand 0 "register_operand" "r")]
""
@@ -8239,31 +8258,6 @@
[(set_attr "type" "multi")
(set_attr "length" "2")])
-;; Now peepholes to do a call followed by a jump.
-
-(define_peephole
- [(parallel [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "call_operand_address" "ps"))
- (match_operand 2 "" "")))
- (clobber (reg:SI 15))])
- (set (pc) (label_ref (match_operand 3 "" "")))]
- "short_branch (INSN_UID (insn), INSN_UID (operands[3]))
- && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))
- && sparc_cpu != PROCESSOR_ULTRASPARC
- && sparc_cpu != PROCESSOR_ULTRASPARC3"
- "call\t%a1, %2\n\tadd\t%%o7, (%l3-.-4), %%o7")
-
-(define_peephole
- [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "ps"))
- (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))
- && sparc_cpu != PROCESSOR_ULTRASPARC
- && sparc_cpu != PROCESSOR_ULTRASPARC3"
- "call\t%a0, %1\n\tadd\t%%o7, (%l2-.-4), %%o7")
-
;; ??? 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
@@ -8391,3 +8385,566 @@
"TARGET_V9"
"t%C0\t%%xcc, %1"
[(set_attr "type" "trap")])
+
+;; TLS support
+(define_insn "tgd_hi22"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI (unspec:SI [(match_operand 1 "tgd_symbolic_operand" "")]
+ UNSPEC_TLSGD)))]
+ "TARGET_TLS"
+ "sethi\\t%%tgd_hi22(%a1), %0")
+
+(define_insn "tgd_lo10"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand 2 "tgd_symbolic_operand" "")]
+ UNSPEC_TLSGD)))]
+ "TARGET_TLS"
+ "add\\t%1, %%tgd_lo10(%a2), %0")
+
+(define_insn "tgd_add32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tgd_symbolic_operand" "")]
+ UNSPEC_TLSGD)))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "add\\t%1, %2, %0, %%tgd_add(%a3)")
+
+(define_insn "tgd_add64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tgd_symbolic_operand" "")]
+ UNSPEC_TLSGD)))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "add\\t%1, %2, %0, %%tgd_add(%a3)")
+
+(define_insn "tgd_call32"
+ [(set (match_operand 0 "register_operand" "=r")
+ (call (mem:SI (unspec:SI [(match_operand:SI 1 "symbolic_operand" "s")
+ (match_operand 2 "tgd_symbolic_operand" "")]
+ UNSPEC_TLSGD))
+ (match_operand 3 "" "")))
+ (clobber (reg:SI 15))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "call\t%a1, %%tgd_call(%a2)%#"
+ [(set_attr "type" "call")])
+
+(define_insn "tgd_call64"
+ [(set (match_operand 0 "register_operand" "=r")
+ (call (mem:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "s")
+ (match_operand 2 "tgd_symbolic_operand" "")]
+ UNSPEC_TLSGD))
+ (match_operand 3 "" "")))
+ (clobber (reg:DI 15))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "call\t%a1, %%tgd_call(%a2)%#"
+ [(set_attr "type" "call")])
+
+(define_insn "tldm_hi22"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI (unspec:SI [(const_int 0)] UNSPEC_TLSLDM)))]
+ "TARGET_TLS"
+ "sethi\\t%%tldm_hi22(%&), %0")
+
+(define_insn "tldm_lo10"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(const_int 0)] UNSPEC_TLSLDM)))]
+ "TARGET_TLS"
+ "add\\t%1, %%tldm_lo10(%&), %0")
+
+(define_insn "tldm_add32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand:SI 2 "register_operand" "r")]
+ UNSPEC_TLSLDM)))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "add\\t%1, %2, %0, %%tldm_add(%&)")
+
+(define_insn "tldm_add64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:SI 2 "register_operand" "r")]
+ UNSPEC_TLSLDM)))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "add\\t%1, %2, %0, %%tldm_add(%&)")
+
+(define_insn "tldm_call32"
+ [(set (match_operand 0 "register_operand" "=r")
+ (call (mem:SI (unspec:SI [(match_operand:SI 1 "symbolic_operand" "s")]
+ UNSPEC_TLSLDM))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI 15))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "call\t%a1, %%tldm_call(%&)%#"
+ [(set_attr "type" "call")])
+
+(define_insn "tldm_call64"
+ [(set (match_operand 0 "register_operand" "=r")
+ (call (mem:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "s")]
+ UNSPEC_TLSLDM))
+ (match_operand 2 "" "")))
+ (clobber (reg:DI 15))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "call\t%a1, %%tldm_call(%&)%#"
+ [(set_attr "type" "call")])
+
+(define_insn "tldo_hix22"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI (unspec:SI [(match_operand 1 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)))]
+ "TARGET_TLS"
+ "sethi\\t%%tldo_hix22(%a1), %0")
+
+(define_insn "tldo_lox10"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand 2 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)))]
+ "TARGET_TLS"
+ "xor\\t%1, %%tldo_lox10(%a2), %0")
+
+(define_insn "tldo_add32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "add\\t%1, %2, %0, %%tldo_add(%a3)")
+
+(define_insn "tldo_add64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "add\\t%1, %2, %0, %%tldo_add(%a3)")
+
+(define_insn "tie_hi22"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI (unspec:SI [(match_operand 1 "tie_symbolic_operand" "")]
+ UNSPEC_TLSIE)))]
+ "TARGET_TLS"
+ "sethi\\t%%tie_hi22(%a1), %0")
+
+(define_insn "tie_lo10"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand 2 "tie_symbolic_operand" "")]
+ UNSPEC_TLSIE)))]
+ "TARGET_TLS"
+ "add\\t%1, %%tie_lo10(%a2), %0")
+
+(define_insn "tie_ld32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tie_symbolic_operand" "")]
+ UNSPEC_TLSIE))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "ld\\t[%1 + %2], %0, %%tie_ld(%a3)"
+ [(set_attr "type" "load")])
+
+(define_insn "tie_ld64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tie_symbolic_operand" "")]
+ UNSPEC_TLSIE))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldx\\t[%1 + %2], %0, %%tie_ldx(%a3)"
+ [(set_attr "type" "load")])
+
+(define_insn "tie_add32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tie_symbolic_operand" "")]
+ UNSPEC_TLSIE)))]
+ "TARGET_SUN_TLS && TARGET_ARCH32"
+ "add\\t%1, %2, %0, %%tie_add(%a3)")
+
+(define_insn "tie_add64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:DI 2 "register_operand" "r")
+ (match_operand 3 "tie_symbolic_operand" "")]
+ UNSPEC_TLSIE)))]
+ "TARGET_SUN_TLS && TARGET_ARCH64"
+ "add\\t%1, %2, %0, %%tie_add(%a3)")
+
+(define_insn "tle_hix22_sp32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI (unspec:SI [(match_operand 1 "tle_symbolic_operand" "")]
+ UNSPEC_TLSLE)))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "sethi\\t%%tle_hix22(%a1), %0")
+
+(define_insn "tle_lox10_sp32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand 2 "tle_symbolic_operand" "")]
+ UNSPEC_TLSLE)))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "xor\\t%1, %%tle_lox10(%a2), %0")
+
+(define_insn "tle_hix22_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (high:DI (unspec:DI [(match_operand 1 "tle_symbolic_operand" "")]
+ UNSPEC_TLSLE)))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "sethi\\t%%tle_hix22(%a1), %0")
+
+(define_insn "tle_lox10_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand 2 "tle_symbolic_operand" "")]
+ UNSPEC_TLSLE)))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "xor\\t%1, %%tle_lox10(%a2), %0")
+
+;; Now patterns combining tldo_add{32,64} with some integer loads or stores
+(define_insn "*tldo_ldub_sp32"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r"))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldub1_sp32"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldub2_sp32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldsb1_sp32"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldsb2_sp32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldub_sp64"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r"))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldub1_sp64"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldub2_sp64"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldub3_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldsb1_sp64"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldsb2_sp64"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldsb3_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_lduh_sp32"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (mem:HI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r"))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "lduh\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_lduh1_sp32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (mem:HI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "lduh\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldsh1_sp32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (mem:HI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "ldsh\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_lduh_sp64"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r"))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "lduh\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_lduh1_sp64"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "lduh\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_lduh2_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "lduh\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldsh1_sp64"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldsh\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldsh2_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI (mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldsh\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_lduw_sp32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mem:SI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r"))))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "ld\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")])
+
+(define_insn "*tldo_lduw_sp64"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mem:SI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r"))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "lduw\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")])
+
+(define_insn "*tldo_lduw1_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (mem:SI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "lduw\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")])
+
+(define_insn "*tldo_ldsw1_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI (mem:SI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldsw\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
+
+(define_insn "*tldo_ldx_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (mem:DI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r"))))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "ldx\t[%1 + %2], %0, %%tldo_add(%3)"
+ [(set_attr "type" "load")])
+
+(define_insn "*tldo_stb_sp32"
+ [(set (mem:QI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))
+ (match_operand:QI 0 "register_operand" "=r"))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "stb\t%0, [%1 + %2], %%tldo_add(%3)"
+ [(set_attr "type" "store")])
+
+(define_insn "*tldo_stb_sp64"
+ [(set (mem:QI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))
+ (match_operand:QI 0 "register_operand" "=r"))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "stb\t%0, [%1 + %2], %%tldo_add(%3)"
+ [(set_attr "type" "store")])
+
+(define_insn "*tldo_sth_sp32"
+ [(set (mem:HI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))
+ (match_operand:HI 0 "register_operand" "=r"))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "sth\t%0, [%1 + %2], %%tldo_add(%3)"
+ [(set_attr "type" "store")])
+
+(define_insn "*tldo_sth_sp64"
+ [(set (mem:HI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))
+ (match_operand:HI 0 "register_operand" "=r"))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "sth\t%0, [%1 + %2], %%tldo_add(%3)"
+ [(set_attr "type" "store")])
+
+(define_insn "*tldo_stw_sp32"
+ [(set (mem:SI (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:SI 1 "register_operand" "r")))
+ (match_operand:SI 0 "register_operand" "=r"))]
+ "TARGET_TLS && TARGET_ARCH32"
+ "st\t%0, [%1 + %2], %%tldo_add(%3)"
+ [(set_attr "type" "store")])
+
+(define_insn "*tldo_stw_sp64"
+ [(set (mem:SI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))
+ (match_operand:SI 0 "register_operand" "=r"))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "stw\t%0, [%1 + %2], %%tldo_add(%3)"
+ [(set_attr "type" "store")])
+
+(define_insn "*tldo_stx_sp64"
+ [(set (mem:DI (plus:DI (unspec:DI [(match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "tld_symbolic_operand" "")]
+ UNSPEC_TLSLDO)
+ (match_operand:DI 1 "register_operand" "r")))
+ (match_operand:DI 0 "register_operand" "=r"))]
+ "TARGET_TLS && TARGET_ARCH64"
+ "stx\t%0, [%1 + %2], %%tldo_add(%3)"
+ [(set_attr "type" "store")])
diff --git a/contrib/gcc/config/sparc/sparclet.md b/contrib/gcc/config/sparc/sparclet.md
index 080090c..15020ba 100644
--- a/contrib/gcc/config/sparc/sparclet.md
+++ b/contrib/gcc/config/sparc/sparclet.md
@@ -1,20 +1,20 @@
;; Scheduling description for SPARClet.
;; Copyright (C) 2002 Free Software Foundation, Inc.
;;
-;; This file is part of GNU CC.
+;; This file is part of GCC.
;;
-;; GNU CC is free software; you can redistribute it and/or modify
+;; GCC is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;;
-;; GNU CC is distributed in the hope that it will be useful,
+;; GCC is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with GNU CC; see the file COPYING. If not, write to
+;; along with GCC; see the file COPYING. If not, write to
;; the Free Software Foundation, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
diff --git a/contrib/gcc/config/sparc/supersparc.md b/contrib/gcc/config/sparc/supersparc.md
index ea32886..93e4cf7 100644
--- a/contrib/gcc/config/sparc/supersparc.md
+++ b/contrib/gcc/config/sparc/supersparc.md
@@ -1,20 +1,20 @@
;; Scheduling description for SuperSPARC.
;; Copyright (C) 2002 Free Software Foundation, Inc.
;;
-;; This file is part of GNU CC.
+;; This file is part of GCC.
;;
-;; GNU CC is free software; you can redistribute it and/or modify
+;; GCC is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;;
-;; GNU CC is distributed in the hope that it will be useful,
+;; GCC is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with GNU CC; see the file COPYING. If not, write to
+;; along with GCC; see the file COPYING. If not, write to
;; the Free Software Foundation, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
diff --git a/contrib/gcc/config/sparc/sysv4-only.h b/contrib/gcc/config/sparc/sysv4-only.h
new file mode 100644
index 0000000..da265a0
--- /dev/null
+++ b/contrib/gcc/config/sparc/sysv4-only.h
@@ -0,0 +1,35 @@
+/* Target macros for GCC for SPARC running System V.4
+ Copyright (C) 2003
+ Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Provide a set of pre-definitions and pre-assertions appropriate for
+ the SPARC running svr4. __svr4__ is our extension. */
+
+/* Target OS builtins. */ \
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("sparc"); \
+ builtin_define_std ("unix"); \
+ builtin_define ("__svr4__"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=svr4"); \
+ } \
+ while (0)
diff --git a/contrib/gcc/config/sparc/sysv4.h b/contrib/gcc/config/sparc/sysv4.h
index f304d6b..776debc 100644
--- a/contrib/gcc/config/sparc/sysv4.h
+++ b/contrib/gcc/config/sparc/sysv4.h
@@ -3,20 +3,20 @@
Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@monkeys.com).
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
@@ -48,13 +48,6 @@ Boston, MA 02111-1307, USA. */
#undef SKIP_ASM_OP
#undef SET_ASM_OP /* Has no equivalent. See ASM_OUTPUT_DEF below. */
-/* Provide a set of pre-definitions and pre-assertions appropriate for
- the SPARC running svr4. __svr4__ is our extension. */
-
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES \
-"-Dsparc -Dunix -D__svr4__ -Asystem=unix -Asystem=svr4"
-
/* The native assembler can't compute differences between symbols in different
sections when generating pic code, so we must put jump tables in the
text section. */
@@ -66,7 +59,7 @@ Boston, MA 02111-1307, USA. */
#undef ASM_SPEC
#define ASM_SPEC \
"%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
- %{fpic:-K PIC} %{fPIC:-K PIC} %(asm_cpu)"
+ %{fpic|fPIC|fpie|fPIE:-K PIC} %(asm_cpu)"
/* Define the names of various pseudo-op used by the SPARC/svr4 assembler.
Note that many of these are different from the typical pseudo-ops used
@@ -93,7 +86,7 @@ Boston, MA 02111-1307, USA. */
#undef ASM_OUTPUT_CASE_LABEL
#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, JUMPTABLE) \
do { ASM_OUTPUT_ALIGN ((FILE), Pmode == SImode ? 2 : 3); \
- ASM_OUTPUT_INTERNAL_LABEL ((FILE), PREFIX, NUM); \
+ (*targetm.asm_out.internal_label) ((FILE), PREFIX, NUM); \
} while (0)
/* This is how to equate one symbol to another symbol. The syntax used is
@@ -161,11 +154,6 @@ do { ASM_OUTPUT_ALIGN ((FILE), Pmode == SImode ? 2 : 3); \
#undef TARGET_ASM_NAMED_SECTION
#define TARGET_ASM_NAMED_SECTION sparc_elf_asm_named_section
-/* A C statement (sans semicolon) to output to the stdio stream
- FILE the assembler definition of uninitialized global DECL named
- NAME whose size is SIZE bytes and alignment is ALIGN bytes.
- Try to use asm_output_aligned_bss to implement this macro. */
-
#undef ASM_OUTPUT_ALIGNED_BSS
#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
diff --git a/contrib/gcc/config/sparc/t-sol2 b/contrib/gcc/config/sparc/t-sol2
index 4a5a13b..f32765f 100644
--- a/contrib/gcc/config/sparc/t-sol2
+++ b/contrib/gcc/config/sparc/t-sol2
@@ -1,5 +1,6 @@
# gmon build rule:
-$(T)gmon.o: $(srcdir)/config/sparc/gmon-sol2.c $(GCC_PASSES) $(CONFIG_H) stmp-int-hdrs
+$(T)gmon.o: $(srcdir)/config/sparc/gmon-sol2.c $(GCC_PASSES) \
+ $(TCONFIG_H) tsystem.h coretypes.h $(TM_H) stmp-int-hdrs
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) \
-c $(srcdir)/config/sparc/gmon-sol2.c -o $(T)gmon.o
diff --git a/contrib/gcc/config/sparc/ultra1_2.md b/contrib/gcc/config/sparc/ultra1_2.md
index 2194be7..e58c624 100644
--- a/contrib/gcc/config/sparc/ultra1_2.md
+++ b/contrib/gcc/config/sparc/ultra1_2.md
@@ -1,20 +1,20 @@
;; Scheduling description for UltraSPARC-I/II.
;; Copyright (C) 2002 Free Software Foundation, Inc.
;;
-;; This file is part of GNU CC.
+;; This file is part of GCC.
;;
-;; GNU CC is free software; you can redistribute it and/or modify
+;; GCC is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;;
-;; GNU CC is distributed in the hope that it will be useful,
+;; GCC is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with GNU CC; see the file COPYING. If not, write to
+;; along with GCC; see the file COPYING. If not, write to
;; the Free Software Foundation, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
@@ -250,3 +250,53 @@
;; An integer branch may execute in the same cycle as the compare
;; creating the condition codes.
(define_bypass 0 "us1_simple_ieu1" "us1_branch")
+
+;; VIS scheduling
+(define_insn_reservation "us1_fga_single"
+ 2
+ (and (and
+ (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fga"))
+ (eq_attr "fptype" "single"))
+ "us1_fpa + us1_fp_single + us1_slotany, nothing")
+
+(define_bypass 1 "us1_fga_single" "us1_fga_single")
+
+(define_insn_reservation "us1_fga_double"
+ 2
+ (and (and
+ (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fga"))
+ (eq_attr "fptype" "double"))
+ "us1_fpa + us1_fp_double + us1_slotany, nothing")
+
+(define_bypass 1 "us1_fga_double" "us1_fga_double")
+
+(define_insn_reservation "us1_fgm_single"
+ 4
+ (and (and
+ (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fgm_pack,fgm_mul,fgm_cmp"))
+ (eq_attr "fptype" "single"))
+ "us1_fpm + us1_fp_single + us1_slotany, nothing*3")
+
+(define_bypass 3 "us1_fgm_single" "us1_fga_single")
+
+(define_insn_reservation "us1_fgm_double"
+ 4
+ (and (and
+ (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fgm_pack,fgm_mul,fgm_cmp"))
+ (eq_attr "fptype" "double"))
+ "us1_fpm + us1_fp_double + us1_slotany, nothing*3")
+
+(define_bypass 3 "us1_fgm_double" "us1_fga_double")
+
+(define_insn_reservation "us1_pdist"
+ 4
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fgm_pdist"))
+ "us1_fpm + us1_fp_double + us1_slotany, nothing*3")
+
+(define_bypass 3 "us1_pdist" "us1_fga_double,us1_fga_single")
+(define_bypass 1 "us1_pdist" "us1_pdist")
diff --git a/contrib/gcc/config/sparc/ultra3.md b/contrib/gcc/config/sparc/ultra3.md
index cebc9f2..238beab 100644
--- a/contrib/gcc/config/sparc/ultra3.md
+++ b/contrib/gcc/config/sparc/ultra3.md
@@ -1,20 +1,20 @@
;; Scheduling description for UltraSPARC-III.
;; Copyright (C) 2002 Free Software Foundation, Inc.
;;
-;; This file is part of GNU CC.
+;; This file is part of GCC.
;;
-;; GNU CC is free software; you can redistribute it and/or modify
+;; GCC is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;;
-;; GNU CC is distributed in the hope that it will be useful,
+;; GCC is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with GNU CC; see the file COPYING. If not, write to
+;; along with GCC; see the file COPYING. If not, write to
;; the Free Software Foundation, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
@@ -167,3 +167,24 @@
;; If FMOVfcc is user of FPCMP, latency is only 1 cycle.
(define_bypass 1 "us3_fpcmp" "us3_fcmov")
+
+;; VIS scheduling
+(define_insn_reservation "us3_fga"
+ 3
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "fga"))
+ "us3_fpa + us3_slotany, nothing*2")
+
+(define_insn_reservation "us3_fgm"
+ 4
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "fgm_pack,fgm_mul,fgm_cmp"))
+ "us3_fpm + us3_slotany, nothing*3")
+
+(define_insn_reservation "us3_pdist"
+ 4
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "fgm_pdist"))
+ "us3_fpm + us3_slotany, nothing*3")
+
+(define_bypass 1 "us3_pdist" "us3_pdist")
OpenPOWER on IntegriCloud