summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/config/sparc
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2002-02-01 18:16:02 +0000
committerobrien <obrien@FreeBSD.org>2002-02-01 18:16:02 +0000
commitc9ab9ae440a8066b2c2b85b157b1fdadcf09916a (patch)
tree086d9d6c8fbd4fc8fe4495059332f66bc0f8d12b /contrib/gcc/config/sparc
parent2ecfd8bd04b63f335c1ec6295740a4bfd97a4fa6 (diff)
downloadFreeBSD-src-c9ab9ae440a8066b2c2b85b157b1fdadcf09916a.zip
FreeBSD-src-c9ab9ae440a8066b2c2b85b157b1fdadcf09916a.tar.gz
Enlist the FreeBSD-CURRENT users as testers of what is to become Gcc 3.1.0.
These bits are taken from the FSF anoncvs repo on 1-Feb-2002 08:20 PST.
Diffstat (limited to 'contrib/gcc/config/sparc')
-rw-r--r--contrib/gcc/config/sparc/aout.h84
-rw-r--r--contrib/gcc/config/sparc/biarch64.h24
-rw-r--r--contrib/gcc/config/sparc/bsd.h2
-rw-r--r--contrib/gcc/config/sparc/elf.h4
-rw-r--r--contrib/gcc/config/sparc/freebsd.h153
-rw-r--r--contrib/gcc/config/sparc/gmon-sol2.c25
-rw-r--r--contrib/gcc/config/sparc/lb1spc.asm4
-rw-r--r--contrib/gcc/config/sparc/lb1spl.asm4
-rw-r--r--contrib/gcc/config/sparc/linux-aout.h56
-rw-r--r--contrib/gcc/config/sparc/linux.h118
-rw-r--r--contrib/gcc/config/sparc/linux64.h139
-rw-r--r--contrib/gcc/config/sparc/lite.h5
-rw-r--r--contrib/gcc/config/sparc/litecoff.h103
-rw-r--r--contrib/gcc/config/sparc/liteelf.h52
-rw-r--r--contrib/gcc/config/sparc/lynx-ng.h5
-rw-r--r--contrib/gcc/config/sparc/lynx.h13
-rw-r--r--contrib/gcc/config/sparc/netbsd.h9
-rw-r--r--contrib/gcc/config/sparc/openbsd.h7
-rw-r--r--contrib/gcc/config/sparc/pbd.h15
-rw-r--r--contrib/gcc/config/sparc/rtems.h7
-rw-r--r--contrib/gcc/config/sparc/rtemself.h31
-rw-r--r--contrib/gcc/config/sparc/sol2-64.h20
-rw-r--r--contrib/gcc/config/sparc/sol2-sld-64.h130
-rw-r--r--contrib/gcc/config/sparc/sol2-sld.h2
-rw-r--r--contrib/gcc/config/sparc/sol2.h156
-rw-r--r--contrib/gcc/config/sparc/sp64-aout.h5
-rw-r--r--contrib/gcc/config/sparc/sp64-elf.h54
-rw-r--r--contrib/gcc/config/sparc/sp86x-aout.h51
-rw-r--r--contrib/gcc/config/sparc/sp86x-elf.h67
-rw-r--r--contrib/gcc/config/sparc/sparc-protos.h122
-rw-r--r--contrib/gcc/config/sparc/sparc.c2824
-rw-r--r--contrib/gcc/config/sparc/sparc.h1440
-rw-r--r--contrib/gcc/config/sparc/sparc.md4208
-rw-r--r--contrib/gcc/config/sparc/splet.h35
-rw-r--r--contrib/gcc/config/sparc/sun4gas.h7
-rw-r--r--contrib/gcc/config/sparc/sun4o3.h22
-rw-r--r--contrib/gcc/config/sparc/sunos4.h39
-rw-r--r--contrib/gcc/config/sparc/sysv4.h84
-rw-r--r--contrib/gcc/config/sparc/t-chorus-elf29
-rw-r--r--contrib/gcc/config/sparc/t-elf18
-rw-r--r--contrib/gcc/config/sparc/t-linux6423
-rw-r--r--contrib/gcc/config/sparc/t-openbsd5
-rw-r--r--contrib/gcc/config/sparc/t-sol27
-rw-r--r--contrib/gcc/config/sparc/t-sp86x23
-rw-r--r--contrib/gcc/config/sparc/t-sparcbare9
-rw-r--r--contrib/gcc/config/sparc/t-sparclite9
-rw-r--r--contrib/gcc/config/sparc/t-splet9
-rw-r--r--contrib/gcc/config/sparc/t-sunos414
-rw-r--r--contrib/gcc/config/sparc/t-vxsparc7
-rw-r--r--contrib/gcc/config/sparc/t-vxsparc6423
-rw-r--r--contrib/gcc/config/sparc/vxsim.h16
-rw-r--r--contrib/gcc/config/sparc/vxsparc.h6
-rw-r--r--contrib/gcc/config/sparc/vxsparc64.h92
53 files changed, 6201 insertions, 4205 deletions
diff --git a/contrib/gcc/config/sparc/aout.h b/contrib/gcc/config/sparc/aout.h
index 478d710..fd84d75 100644
--- a/contrib/gcc/config/sparc/aout.h
+++ b/contrib/gcc/config/sparc/aout.h
@@ -19,8 +19,84 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "sparc/sparc.h" /* SPARC definitions */
-#include "aoutos.h" /* A.out definitions */
+/* Print subsidiary information on the compiler version in use. */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dsparc -Acpu(sparc) -Amachine(sparc)"
+#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) \
+ (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \
+ || !strcmp (STR, "target") || !strcmp (STR, "assert"))
+
+/* This is defined differently for v9 in a cover file. */
+#define SELECT_SECTION(T,RELOC,ALIGN) \
+{ \
+ if (TREE_CODE (T) == VAR_DECL) \
+ { \
+ if (TREE_READONLY (T) && ! TREE_SIDE_EFFECTS (T) \
+ && DECL_INITIAL (T) \
+ && (DECL_INITIAL (T) == error_mark_node \
+ || TREE_CONSTANT (DECL_INITIAL (T))) \
+ && DECL_ALIGN (T) <= MAX_TEXT_ALIGN \
+ && ! (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES))) \
+ text_section (); \
+ else \
+ data_section (); \
+ } \
+ else if (TREE_CODE (T) == CONSTRUCTOR) \
+ { \
+ if (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES)) \
+ data_section (); \
+ } \
+ else if (TREE_CODE_CLASS (TREE_CODE (T)) == 'c') \
+ { \
+ if ((TREE_CODE (T) == STRING_CST && flag_writable_strings) \
+ || TYPE_ALIGN (TREE_TYPE (T)) > MAX_TEXT_ALIGN \
+ || (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES))) \
+ data_section (); \
+ else \
+ text_section (); \
+ } \
+}
+
+/* Output the label for a function definition. */
+
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+do { \
+ ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
+} while (0)
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP "\t.text"
+
+/* Output before writable data. */
+
+#define DATA_SECTION_ASM_OP "\t.data"
+
+/* How to renumber registers for dbx and gdb. In the flat model, the frame
+ pointer is really %i7. */
+
+#define DBX_REGISTER_NUMBER(REGNO) \
+ (TARGET_FLAT && REGNO == FRAME_POINTER_REGNUM ? 31 : REGNO)
+
+/* This is how to output a note to DBX telling it the line number
+ to which the following sequence of instructions corresponds.
+
+ 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; }
diff --git a/contrib/gcc/config/sparc/biarch64.h b/contrib/gcc/config/sparc/biarch64.h
new file mode 100644
index 0000000..f85111ab
--- /dev/null
+++ b/contrib/gcc/config/sparc/biarch64.h
@@ -0,0 +1,24 @@
+/* Definitions of target machine for GNU compiler, 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.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Specify this in a cover file to provide bi-architecture (32/64) support. */
+
+#define SPARC_BI_ARCH
diff --git a/contrib/gcc/config/sparc/bsd.h b/contrib/gcc/config/sparc/bsd.h
index 761abe2..41f8308 100644
--- a/contrib/gcc/config/sparc/bsd.h
+++ b/contrib/gcc/config/sparc/bsd.h
@@ -1,5 +1,3 @@
-#include "sparc/sparc.h"
-
#undef LIB_SPEC
#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}"
diff --git a/contrib/gcc/config/sparc/elf.h b/contrib/gcc/config/sparc/elf.h
index 635238f..20bea82 100644
--- a/contrib/gcc/config/sparc/elf.h
+++ b/contrib/gcc/config/sparc/elf.h
@@ -19,10 +19,8 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "sol2.h"
-
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dsparc -D__elf__ -Acpu(sparc) -Amachine(sparc)"
+#define CPP_PREDEFINES "-Dsparc -D__elf__"
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "crt0.o%s crti.o%s crtbegin.o%s"
diff --git a/contrib/gcc/config/sparc/freebsd.h b/contrib/gcc/config/sparc/freebsd.h
new file mode 100644
index 0000000..314b07b
--- /dev/null
+++ b/contrib/gcc/config/sparc/freebsd.h
@@ -0,0 +1,153 @@
+/* Definitions for Sun Sparc64 running FreeBSD using the ELF format
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Contributed by David E. O'Brien <obrien@FreeBSD.org> and BSDi.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* FreeBSD needs's the platform name (sparc64) defined. */
+
+#undef CPP_CPU64_DEFAULT_SPEC
+#define CPP_CPU64_DEFAULT_SPEC "-D__sparc64__ -D__sparc_v9__"
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES FBSD_CPP_PREDEFINES
+
+#define LINK_SPEC "-m elf64_sparc %(link_arch) \
+ %{!mno-relax:%{!r:-relax} \
+ %{p:%e`-p' not supported; use `-pg' and gprof(1)} \
+ %{Wl,*:%*} \
+ %{assert*} %{R*} %{rpath*} %{defsym*} \
+ %{shared:-Bshareable %{h*} %{soname*}} \
+ %{symbolic:-Bsymbolic} \
+ %{!shared: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /usr/libexec/ld-elf.so.1}} \
+ %{static:-Bstatic}}"
+
+
+/************************[ Target stuff ]***********************************/
+
+/* Define the actual types of some ANSI-mandated types.
+ Needs to agree with <machine/ansi.h>. GCC defaults come from c-decl.c,
+ c-common.c, and config/<arch>/<arch>.h. */
+
+/* Earlier headers may get this wrong for FreeBSD.
+ We use the GCC defaults instead. */
+#undef WCHAR_TYPE
+
+#undef WCHAR_UNSIGNED
+#define WCHAR_UNSIGNED 0
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+/* Define for support of TFmode long double and REAL_ARITHMETIC.
+ Sparc ABI says that long double is 4 words. */
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
+
+/* Constant which presents upper bound of the above value. */
+#undef MAX_LONG_DOUBLE_TYPE_SIZE
+#define MAX_LONG_DOUBLE_TYPE_SIZE 128
+
+/* Define this to set long double type size to use in libgcc2.c, which can
+ not depend on target_flags. */
+#if defined(__arch64__) || defined(__LONG_DOUBLE_128__)
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
+#else
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
+#endif
+
+/* Definitions for 64-bit SPARC running systems with ELF. */
+
+#undef SUBTARGET_SWITCHES
+#define SUBTARGET_SWITCHES \
+ {"long-double-64", -MASK_LONG_DOUBLE_128, N_("Use 64 bit long doubles") }, \
+ {"long-double-128", MASK_LONG_DOUBLE_128, N_("Use 128 bit long doubles") },
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (FreeBSD/sparc64 ELF)");
+
+#define TARGET_ELF 1
+
+/* XXX */
+/* A 64 bit v9 compiler with stack-bias,
+ in a Medium/mid code model environment. */
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT \
+ (MASK_V9 + MASK_64BIT + MASK_PTR64 + MASK_VIS + MASK_FASTER_STRUCTS \
+ + MASK_STACK_BIAS + MASK_APP_REGS /* + MASK_EPILOGUE */ + MASK_FPU \
+ + MASK_LONG_DOUBLE_128 /* + MASK_HARD_QUAD */)
+
+/* The default code model. */
+#undef SPARC_DEFAULT_CMODEL
+#define SPARC_DEFAULT_CMODEL CM_MEDMID
+
+
+/************************[ Assembler stuff ]********************************/
+
+/* XXX */
+#if 0
+#undef ASM_CPU_DEFAULT_SPEC
+#define ASM_CPU_DEFAULT_SPEC "-Av9a"
+#endif
+
+/* XXX2 */
+/* 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)
+
+/* XXX2 */
+/* This is how to output a reference to an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#undef ASM_OUTPUT_INTERNAL_LABELREF
+#define ASM_OUTPUT_INTERNAL_LABELREF(FILE,PREFIX,NUM) \
+ fprintf (FILE, ".L%s%d", PREFIX, NUM)
+
+/* XXX2 */
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf (LABEL, "*.L%s%d", PREFIX, NUM)
+
+
+/************************[ Debugger stuff ]*********************************/
+
+/* This is the char to use for continuation (in case we need to turn
+ continuation back on). */
+
+#undef DBX_CONTIN_CHAR
+#define DBX_CONTIN_CHAR '?'
+
+/* DWARF bits. */
+
+/* Follow Irix 6 and not the Dwarf2 draft in using 64-bit offsets.
+ Obviously the Dwarf2 folks havn't tried to actually build systems
+ with their spec. On a 64-bit system, only 64-bit relocs become
+ RELATIVE relocations. */
+
+/* #define DWARF_OFFSET_SIZE PTR_SIZE */
diff --git a/contrib/gcc/config/sparc/gmon-sol2.c b/contrib/gcc/config/sparc/gmon-sol2.c
index a6abcab..6d66966 100644
--- a/contrib/gcc/config/sparc/gmon-sol2.c
+++ b/contrib/gcc/config/sparc/gmon-sol2.c
@@ -10,10 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
+ * 3. [rescinded 22 July 1999]
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@@ -88,9 +85,9 @@ static int s_scale;
#define MSG "No space for profiling buffer(s)\n"
-static void moncontrol PROTO ((int));
-extern void monstartup PROTO ((char *, char *));
-extern void _mcleanup PROTO ((void));
+static void moncontrol PARAMS ((int));
+extern void monstartup PARAMS ((char *, char *));
+extern void _mcleanup PARAMS ((void));
void monstartup(lowpc, highpc)
char *lowpc;
@@ -105,10 +102,10 @@ void monstartup(lowpc, highpc)
* so the rest of the scaling (here and in gprof) stays in ints.
*/
lowpc = (char *)
- ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
+ ROUNDDOWN((unsigned long)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
s_lowpc = lowpc;
highpc = (char *)
- ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
+ ROUNDUP((unsigned long)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
s_highpc = highpc;
s_textsize = highpc - lowpc;
monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
@@ -198,7 +195,7 @@ _mcleanup()
else
progname++;
- sprintf(buf, "%s/%ld.%s", profdir, getpid(), progname);
+ sprintf(buf, "%s/%ld.%s", profdir, (long) getpid(), progname);
proffile = buf;
} else {
proffile = "gmon.out";
@@ -211,7 +208,7 @@ _mcleanup()
}
# ifdef DEBUG
fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
-# endif DEBUG
+# endif /* DEBUG */
write( fd , sbuf , ssiz );
endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) {
@@ -224,7 +221,7 @@ _mcleanup()
fprintf( stderr ,
"[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
frompc , tos[toindex].selfpc , tos[toindex].count );
-# endif DEBUG
+# endif /* DEBUG */
rawarc.raw_frompc = (unsigned long) frompc;
rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
rawarc.raw_count = tos[toindex].count;
@@ -269,7 +266,7 @@ _mcleanup()
* -- [eichin:19920702.1107EST]
*/
-static void internal_mcount PROTO((char *, unsigned short *)) ATTRIBUTE_UNUSED;
+static void internal_mcount PARAMS ((char *, unsigned short *)) ATTRIBUTE_UNUSED;
/* i7 == last ret, -> frompcindex */
/* o7 == current ret, -> selfpc */
@@ -415,7 +412,7 @@ static void moncontrol(mode)
/* start */
profil((unsigned short *)(sbuf + sizeof(struct phdr)),
ssiz - sizeof(struct phdr),
- (int)s_lowpc, s_scale);
+ (long)s_lowpc, s_scale);
profiling = 0;
} else {
/* stop */
diff --git a/contrib/gcc/config/sparc/lb1spc.asm b/contrib/gcc/config/sparc/lb1spc.asm
index 831f33a..b31f82c 100644
--- a/contrib/gcc/config/sparc/lb1spc.asm
+++ b/contrib/gcc/config/sparc/lb1spc.asm
@@ -1,5 +1,5 @@
-/* This is an assembly language implementation of libgcc1.c for the sparc
- processor.
+/* This is an assembly language implementation of mulsi3, divsi3, and modsi3
+ for the sparc processor.
These routines are derived from the Sparc Architecture Manual, version 8,
slightly edited to match the desired calling convention, and also to
diff --git a/contrib/gcc/config/sparc/lb1spl.asm b/contrib/gcc/config/sparc/lb1spl.asm
index 4c8bc30..9dda675 100644
--- a/contrib/gcc/config/sparc/lb1spl.asm
+++ b/contrib/gcc/config/sparc/lb1spl.asm
@@ -1,5 +1,5 @@
-/* This is an assembly language implementation of libgcc1.c for the sparclite
- processor.
+/* This is an assembly language implementation of mulsi3, divsi3, and modsi3
+ for the sparclite processor.
These routines are all from the Sparclite User's Guide, slightly edited
to match the desired calling convention, and also to optimize them. */
diff --git a/contrib/gcc/config/sparc/linux-aout.h b/contrib/gcc/config/sparc/linux-aout.h
index 76d7653..55c833f 100644
--- a/contrib/gcc/config/sparc/linux-aout.h
+++ b/contrib/gcc/config/sparc/linux-aout.h
@@ -1,5 +1,5 @@
/* Definitions for SPARC running Linux-based GNU systems with a.out.
- Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
Contributed by Eddie C. Dost (ecd@skynet.be)
This file is part of GNU CC.
@@ -19,24 +19,18 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include <aoutos.h>
-#include <sparc/sparc.h>
-
-/* Don't assume anything about the header files. */
+/* Don't assume anything about the header files. */
#define NO_IMPLICIT_EXTERN_C
-#undef HAVE_ATEXIT
-#define HAVE_ATEXIT
-
/* GNU/Linux uses ctype from glibc.a. I am not sure how complete it is.
- For now, we play safe. It may change later. */
+ For now, we play safe. It may change later. */
#if 0
#undef MULTIBYTE_CHARS
#define MULTIBYTE_CHARS 1
#endif
-/* We need that too. */
+/* We need that too. */
#define HANDLE_SYSV_PRAGMA
#undef MD_EXEC_PREFIX
@@ -45,11 +39,7 @@ Boston, MA 02111-1307, USA. */
/* Output at beginning of assembler file. */
/* The .file command should always begin the output. */
#undef ASM_FILE_START
-#define ASM_FILE_START(FILE) \
- do { \
- output_file_directive (FILE, main_input_filename); \
- fprintf (FILE, "\t.version\t\"01.01\"\n"); \
- } while (0)
+#define ASM_FILE_START(FILE) output_file_directive (FILE, main_input_filename)
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "%{pg:gcrt0.o%s} %{!pg:%{p:gcrt0.o%s} %{!p:crt0.o%s}} %{static:-static}"
@@ -64,13 +54,15 @@ Boston, MA 02111-1307, USA. */
#define PTRDIFF_TYPE "int"
#undef WCHAR_TYPE
-#define WCHAR_TYPE "long int"
+#define WCHAR_TYPE "int"
#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE BITS_PER_WORD
+#define WCHAR_TYPE_SIZE 32
+
+#undef MAX_WCHAR_TYPE_SIZE
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dunix -Dsparc -Dlinux -Asystem(unix) -Asystem(posix)"
+#define CPP_PREDEFINES "-Dunix -Dsparc -Dlinux -Asystem=unix -Asystem=posix"
#undef CPP_SUBTARGET_SPEC
#define CPP_SUBTARGET_SPEC \
@@ -78,6 +70,7 @@ Boston, MA 02111-1307, USA. */
/* Don't default to pcc-struct-return, because gcc is the only compiler,
and we want to retain compatibility with older gcc versions. */
+#undef DEFAULT_PCC_STRUCT_RETURN
#define DEFAULT_PCC_STRUCT_RETURN 0
#undef LIB_SPEC
@@ -98,33 +91,8 @@ Boston, MA 02111-1307, USA. */
#define LINK_SPEC "-m sparclinux"
/* The sun bundled assembler doesn't accept -Yd, (and neither does gas).
- It's safe to pass -s always, even if -g is not used. */
+ It's safe to pass -s always, even if -g is not used. */
#undef ASM_SPEC
#define ASM_SPEC \
"%{V} %{v:%{!V:-V}} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s %{fpic:-K PIC} %{fPIC:-K PIC}"
-
-#if 0
-/* Define for support of TFmode long double and REAL_ARITHMETIC.
- Sparc ABI says that long double is 4 words. GNU/Linux does not support
- long double yet. */
-#define LONG_DOUBLE_TYPE_SIZE 128
-#endif
-/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special
- traps available which can get and set the condition codes
- reliably. */
-#undef MACHINE_STATE_SAVE
-#define MACHINE_STATE_SAVE(ID) \
- unsigned long int ms_flags, ms_saveret; \
- asm volatile("ta 0x20\n\t" \
- "mov %%g1, %0\n\t" \
- "mov %%g2, %1\n\t" \
- : "=r" (ms_flags), "=r" (ms_saveret));
-
-#undef MACHINE_STATE_RESTORE
-#define MACHINE_STATE_RESTORE(ID) \
- asm volatile("mov %0, %%g1\n\t" \
- "mov %1, %%g2\n\t" \
- "ta 0x21\n\t" \
- : /* no outputs */ \
- : "r" (ms_flags), "r" (ms_saveret));
diff --git a/contrib/gcc/config/sparc/linux.h b/contrib/gcc/config/sparc/linux.h
index d967b01..d464133 100644
--- a/contrib/gcc/config/sparc/linux.h
+++ b/contrib/gcc/config/sparc/linux.h
@@ -1,5 +1,5 @@
/* Definitions for SPARC running Linux-based GNU systems with ELF.
- Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
Contributed by Eddie C. Dost (ecd@skynet.be)
This file is part of GNU CC.
@@ -21,52 +21,38 @@ Boston, MA 02111-1307, USA. */
#define LINUX_DEFAULT_ELF
-/* Don't assume anything about the header files. */
+/* Don't assume anything about the header files. */
#define NO_IMPLICIT_EXTERN_C
-#undef HAVE_ATEXIT
-#define HAVE_ATEXIT
-
/* GNU/Linux uses ctype from glibc.a. I am not sure how complete it is.
- For now, we play safe. It may change later. */
+ For now, we play safe. It may change later. */
#if 0
#undef MULTIBYTE_CHARS
#define MULTIBYTE_CHARS 1
#endif
-#ifndef USE_GNULIBC_1
-#undef DEFAULT_VTABLE_THUNKS
-#define DEFAULT_VTABLE_THUNKS 1
-#endif
-
-/* Use stabs instead of DWARF debug format. */
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-
-#include <sparc/sysv4.h>
-
#undef MD_EXEC_PREFIX
#undef MD_STARTFILE_PREFIX
-/* Output at beginning of assembler file. */
-/* The .file command should always begin the output. */
-#undef ASM_FILE_START
-#define ASM_FILE_START(FILE) \
- do { \
- output_file_directive (FILE, main_input_filename); \
- fprintf (FILE, "\t.version\t\"01.01\"\n"); \
- } while (0)
-
/* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add
the GNU/Linux magical crtbegin.o file (see crtstuff.c) which
provides part of the support for getting C++ file-scope static
- object constructed before entering `main'. */
+ object constructed before entering `main'. */
#undef STARTFILE_SPEC
+#ifdef USE_GNULIBC_1
#define STARTFILE_SPEC \
"%{!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}"
+#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}}"
+#endif
/* Provide a ENDFILE_SPEC appropriate for GNU/Linux. Here we tack on
the GNU/Linux magical crtend.o file (see crtstuff.c) which
@@ -78,7 +64,7 @@ Boston, MA 02111-1307, USA. */
#define ENDFILE_SPEC \
"%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
-/* This is for -profile to use -lc_p instead of -lc. */
+/* This is for -profile to use -lc_p instead of -lc. */
#undef CC1_SPEC
#define CC1_SPEC "%{profile:-p} \
%{sun4:} %{target:} \
@@ -87,9 +73,18 @@ Boston, MA 02111-1307, USA. */
%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
"
+/* The GNU C++ standard library requires that these macros be defined. */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (sparc GNU/Linux with ELF)");
+#undef SUBTARGET_SWITCHES
+#define SUBTARGET_SWITCHES \
+{"long-double-64", -MASK_LONG_DOUBLE_128, N_("Use 64 bit long doubles") }, \
+{"long-double-128", MASK_LONG_DOUBLE_128, N_("Use 128 bit long doubles") },
+
#undef SIZE_TYPE
#define SIZE_TYPE "unsigned int"
@@ -97,21 +92,25 @@ Boston, MA 02111-1307, USA. */
#define PTRDIFF_TYPE "int"
#undef WCHAR_TYPE
-#define WCHAR_TYPE "long int"
+#define WCHAR_TYPE "int"
#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE BITS_PER_WORD
+#define WCHAR_TYPE_SIZE 32
+
+#undef MAX_WCHAR_TYPE_SIZE
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__ELF__ -Dunix -D__sparc__ -Dlinux -Asystem(unix) -Asystem(posix)"
+#define CPP_PREDEFINES "-D__ELF__ -Dunix -D__sparc__ -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:-D__PIC__ -D__pic__} %{fpic:-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} %{pthread:-D_REENTRANT}"
+"%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} \
+%{pthread:-D_REENTRANT} %{mlong-double-128:-D__LONG_DOUBLE_128__}"
#endif
#undef LIB_SPEC
@@ -150,7 +149,7 @@ Boston, MA 02111-1307, USA. */
When the -shared link option is used a final link is not being
done. */
-/* If ELF is the default format, we should not use /lib/elf. */
+/* If ELF is the default format, we should not use /lib/elf. */
#undef LINK_SPEC
#ifdef USE_GNULIBC_1
@@ -173,6 +172,7 @@ Boston, MA 02111-1307, USA. */
#endif
#else
#define LINK_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \
+ %{!mno-relax:%{!r:-relax}} \
%{!shared: \
%{!ibcs: \
%{!static: \
@@ -182,20 +182,16 @@ Boston, MA 02111-1307, USA. */
#endif
/* The sun bundled assembler doesn't accept -Yd, (and neither does gas).
- It's safe to pass -s always, even if -g is not used. */
+ 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}"
+ "%{V} %{v:%{!V:-V}} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s %{fpic:-K PIC} \
+ %{fPIC:-K PIC} %(asm_relax)"
/* Same as sparc.h */
#undef DBX_REGISTER_NUMBER
#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
-/* We use stabs-in-elf for debugging, because that is what the native
- toolchain uses. XXX */
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-
#undef ASM_OUTPUT_ALIGNED_LOCAL
#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
do { \
@@ -206,7 +202,7 @@ do { \
} while (0)
#undef COMMON_ASM_OP
-#define COMMON_ASM_OP "\t.common"
+#define COMMON_ASM_OP "\t.common\t"
/* 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. */
@@ -229,31 +225,25 @@ do { \
#undef ASM_GENERATE_INTERNAL_LABEL
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
- sprintf (LABEL, "*.L%s%d", PREFIX, NUM)
+ sprintf (LABEL, "*.L%s%ld", PREFIX, (long)(NUM))
-#if 0
/* Define for support of TFmode long double and REAL_ARITHMETIC.
- Sparc ABI says that long double is 4 words. GNU/Linux does not support
- long double yet. */
-#define LONG_DOUBLE_TYPE_SIZE 128
+ Sparc ABI says that long double is 4 words. */
+#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
+
+/* Constant which presents upper bound of the above value. */
+#define MAX_LONG_DOUBLE_TYPE_SIZE 128
+
+/* Define this to set long double type size to use in libgcc2.c, which can
+ not depend on target_flags. */
+#ifdef __LONG_DOUBLE_128__
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
+#else
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
+#endif
+
+#if !defined(USE_GNULIBC_1) && defined(HAVE_LD_EH_FRAME_HDR)
+#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
#endif
-/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special
- traps available which can get and set the condition codes
- reliably. */
-#undef MACHINE_STATE_SAVE
-#define MACHINE_STATE_SAVE(ID) \
- unsigned long int ms_flags, ms_saveret; \
- asm volatile("ta 0x20\n\t" \
- "mov %%g1, %0\n\t" \
- "mov %%g2, %1\n\t" \
- : "=r" (ms_flags), "=r" (ms_saveret));
-
-#undef MACHINE_STATE_RESTORE
-#define MACHINE_STATE_RESTORE(ID) \
- asm volatile("mov %0, %%g1\n\t" \
- "mov %1, %%g2\n\t" \
- "ta 0x21\n\t" \
- : /* no outputs */ \
- : "r" (ms_flags), "r" (ms_saveret));
diff --git a/contrib/gcc/config/sparc/linux64.h b/contrib/gcc/config/sparc/linux64.h
index 705b5ca..31d8204 100644
--- a/contrib/gcc/config/sparc/linux64.h
+++ b/contrib/gcc/config/sparc/linux64.h
@@ -1,5 +1,5 @@
/* Definitions for 64-bit SPARC running Linux-based GNU systems with ELF.
- Copyright 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
Contributed by David S. Miller (davem@caip.rutgers.edu)
This file is part of GNU CC.
@@ -19,18 +19,11 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#define SPARC_BI_ARCH
-
#define LINUX_DEFAULT_ELF
-/* Don't assume anything about the header files. */
+/* Don't assume anything about the header files. */
#define NO_IMPLICIT_EXTERN_C
-#undef HAVE_ATEXIT
-#define HAVE_ATEXIT
-
-#include <sparc/sysv4.h>
-
#undef MD_EXEC_PREFIX
#undef MD_STARTFILE_PREFIX
@@ -41,38 +34,40 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
(MASK_V9 + MASK_PTR64 + MASK_64BIT /* + MASK_HARD_QUAD */ \
- + MASK_STACK_BIAS + MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU)
+ + MASK_STACK_BIAS + MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU + MASK_LONG_DOUBLE_128)
#endif
-/* Output at beginning of assembler file. */
-/* The .file command should always begin the output. */
-#undef ASM_FILE_START
-#define ASM_FILE_START(FILE) \
- do { \
- output_file_directive (FILE, main_input_filename); \
- fprintf (FILE, "\t.version\t\"01.01\"\n"); \
- } while (0)
-
#undef ASM_CPU_DEFAULT_SPEC
#define ASM_CPU_DEFAULT_SPEC "-Av9a"
+#ifdef SPARC_BI_ARCH
+
+#undef CPP_ARCH32_SPEC
+#define CPP_ARCH32_SPEC "%{mlong-double-128:-D__LONG_DOUBLE_128__} \
+-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int \
+-D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc"
+
+#endif
+
/* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add
the GNU/Linux magical crtbegin.o file (see crtstuff.c) which
provides part of the support for getting C++ file-scope static
- object constructed before entering `main'. */
+ object constructed before entering `main'. */
#undef STARTFILE_SPEC
#define STARTFILE_SPEC32 \
"%{!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}"
+ crti.o%s %{static:crtbeginT.o%s}\
+ %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
#define STARTFILE_SPEC64 \
"%{!shared: \
%{pg:/usr/lib64/gcrt1.o%s} %{!pg:%{p:/usr/lib64/gcrt1.o%s} %{!p:/usr/lib64/crt1.o%s}}}\
- /usr/lib64/crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
-
+ /usr/lib64/crti.o%s %{static:crtbeginT.o%s}\
+ %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
+
#ifdef SPARC_BI_ARCH
#if DEFAULT_ARCH32_P
@@ -127,6 +122,10 @@ Boston, MA 02111-1307, USA. */
#endif
+/* The GNU C++ standard library requires that these macros be defined. */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (sparc64 GNU/Linux with ELF)");
@@ -134,17 +133,38 @@ Boston, MA 02111-1307, USA. */
#undef SPARC_DEFAULT_CMODEL
#define SPARC_DEFAULT_CMODEL CM_MEDLOW
+#undef SUBTARGET_SWITCHES
+#define SUBTARGET_SWITCHES \
+{"long-double-64", -MASK_LONG_DOUBLE_128, N_("Use 64 bit long doubles") }, \
+{"long-double-128", MASK_LONG_DOUBLE_128, N_("Use 128 bit long doubles") },
+
#undef WCHAR_TYPE
-#define WCHAR_TYPE "long int"
-
+#define WCHAR_TYPE "int"
+
#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE BITS_PER_WORD
+#define WCHAR_TYPE_SIZE 32
+
+#undef MAX_WCHAR_TYPE_SIZE
+/* Define for support of TFmode long double and REAL_ARITHMETIC.
+ Sparc ABI says that long double is 4 words. */
#undef LONG_DOUBLE_TYPE_SIZE
-#define LONG_DOUBLE_TYPE_SIZE 128
+#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
+
+/* Constant which presents upper bound of the above value. */
+#undef MAX_LONG_DOUBLE_TYPE_SIZE
+#define MAX_LONG_DOUBLE_TYPE_SIZE 128
+
+/* Define this to set long double type size to use in libgcc2.c, which can
+ not depend on target_flags. */
+#if defined(__arch64__) || defined(__LONG_DOUBLE_128__)
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
+#else
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
+#endif
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__ELF__ -Dunix -D_LONGLONG -D__sparc__ -Dlinux -Asystem(unix) -Asystem(posix)"
+#define CPP_PREDEFINES "-D__ELF__ -Dunix -D_LONGLONG -D__sparc__ -Dlinux -Asystem=unix -Asystem=posix"
#undef CPP_SUBTARGET_SPEC
#define CPP_SUBTARGET_SPEC "\
@@ -174,7 +194,7 @@ Boston, MA 02111-1307, USA. */
When the -shared link option is used a final link is not being
done. */
-/* If ELF is the default format, we should not use /lib/elf. */
+/* If ELF is the default format, we should not use /lib/elf. */
#ifdef SPARC_BI_ARCH
@@ -216,6 +236,7 @@ Boston, MA 02111-1307, USA. */
#define LINK_SPEC "\
%(link_arch) \
%{mlittle-endian:-EL} \
+%{!mno-relax:%{!r:-relax}} \
"
#undef CC1_SPEC
@@ -225,7 +246,9 @@ Boston, MA 02111-1307, USA. */
%{mcypress:-mcpu=cypress} \
%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \
%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
-%{m64:-mptr64 -mcpu=ultrasparc -mstack-bias} \
+%{m64:-mptr64 -mstack-bias -mlong-double-128 \
+ %{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:-mcpu=ultrasparc}}}}}}} \
+ %{!mno-vis:%{!mcpu=v9:-mvis}}} \
"
#else
#define CC1_SPEC "\
@@ -233,7 +256,10 @@ Boston, MA 02111-1307, USA. */
%{mcypress:-mcpu=cypress} \
%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \
%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
-%{m32:-mptr32 -mcpu=cypress -mno-stack-bias} \
+%{m32:-mptr32 -mno-stack-bias %{!mlong-double-128:-mlong-double-64} \
+ %{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:-mcpu=cypress}}}}}}}} \
+%{!m32:%{!mcpu*:-mcpu=ultrasparc}} \
+%{!mno-vis:%{!m32:%{!mcpu=v9:-mvis}}} \
"
#endif
@@ -246,7 +272,7 @@ Boston, MA 02111-1307, USA. */
#else /* !SPARC_BI_ARCH */
#undef LINK_SPEC
-#define LINK_ARCH_SPEC "-m elf64_sparc -Y P,/usr/lib64 %{shared:-shared} \
+#define LINK_SPEC "-m elf64_sparc -Y P,/usr/lib64 %{shared:-shared} \
%{!shared: \
%{!ibcs: \
%{!static: \
@@ -254,12 +280,13 @@ Boston, MA 02111-1307, USA. */
%{!dynamic-linker:-dynamic-linker /lib64/ld-linux.so.2}} \
%{static:-static}}} \
%{mlittle-endian:-EL} \
+%{!mno-relax:%{!r:-relax}} \
"
#endif /* !SPARC_BI_ARCH */
/* The sun bundled assembler doesn't accept -Yd, (and neither does gas).
- It's safe to pass -s always, even if -g is not used. */
+ It's safe to pass -s always, even if -g is not used. */
#undef ASM_SPEC
#define ASM_SPEC "\
%{V} \
@@ -271,8 +298,7 @@ Boston, MA 02111-1307, USA. */
%{Wa,*:%*} \
-s %{fpic:-K PIC} %{fPIC:-K PIC} \
%{mlittle-endian:-EL} \
-%(asm_cpu) %(asm_arch) \
-"
+%(asm_cpu) %(asm_arch) %(asm_relax)"
/* Same as sparc.h */
#undef DBX_REGISTER_NUMBER
@@ -287,9 +313,6 @@ Boston, MA 02111-1307, USA. */
#define DWARF2_DEBUGGING_INFO
#define DBX_DEBUGGING_INFO
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-
#undef ASM_OUTPUT_ALIGNED_LOCAL
#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
do { \
@@ -300,7 +323,7 @@ do { \
} while (0)
#undef COMMON_ASM_OP
-#define COMMON_ASM_OP "\t.common"
+#define COMMON_ASM_OP "\t.common\t"
/* 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. */
@@ -323,44 +346,18 @@ do { \
#undef ASM_GENERATE_INTERNAL_LABEL
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
- sprintf (LABEL, "*.L%s%d", PREFIX, NUM)
-
-/* Stabs doesn't use this, and it confuses a simulator. */
-/* ??? Need to see what DWARF needs, if anything. */
-#undef ASM_IDENTIFY_GCC
-#define ASM_IDENTIFY_GCC(FILE)
-
-/* Define the names of various pseudo-ops used by the Sparc/svr4 assembler.
- ??? If ints are 64 bits then UNALIGNED_INT_ASM_OP (defined elsewhere) is
- misnamed. These should all refer to explicit sizes (half/word/xword?),
- anything other than short/int/long/etc. */
-
-#define UNALIGNED_DOUBLE_INT_ASM_OP ".uaxword"
+ sprintf (LABEL, "*.L%s%ld", PREFIX, (long)(NUM))
/* DWARF bits. */
/* Follow Irix 6 and not the Dwarf2 draft in using 64-bit offsets.
- Obviously the Dwarf2 folks havn't tried to actually build systems
+ Obviously the Dwarf2 folks haven't tried to actually build systems
with their spec. On a 64-bit system, only 64-bit relocs become
RELATIVE relocations. */
/* #define DWARF_OFFSET_SIZE PTR_SIZE */
+
+#if defined(HAVE_LD_EH_FRAME_HDR)
+#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
+#endif
-/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special
- traps available which can get and set the condition codes
- reliably. */
-#undef MACHINE_STATE_SAVE
-#define MACHINE_STATE_SAVE(ID) \
- unsigned long int ms_flags, ms_saveret; \
- asm volatile("ta 0x20\n\t" \
- "mov %%g1, %0\n\t" \
- "mov %%g2, %1\n\t" \
- : "=r" (ms_flags), "=r" (ms_saveret));
-
-#undef MACHINE_STATE_RESTORE
-#define MACHINE_STATE_RESTORE(ID) \
- asm volatile("mov %0, %%g1\n\t" \
- "mov %1, %%g2\n\t" \
- "ta 0x21\n\t" \
- : /* no outputs */ \
- : "r" (ms_flags), "r" (ms_saveret));
diff --git a/contrib/gcc/config/sparc/lite.h b/contrib/gcc/config/sparc/lite.h
index 55c232a..f740443 100644
--- a/contrib/gcc/config/sparc/lite.h
+++ b/contrib/gcc/config/sparc/lite.h
@@ -19,10 +19,8 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "sparc/sparc.h"
-
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dsparc -Dsparclite -Acpu(sparc) -Amachine(sparc)"
+#define CPP_PREDEFINES "-Dsparc -Dsparclite -Acpu=sparc -Amachine=sparc"
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (sparclite)");
@@ -33,6 +31,5 @@ Boston, MA 02111-1307, USA. */
#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE)
/* US Software GOFAST library support. */
-#include "gofast.h"
#undef INIT_SUBTARGET_OPTABS
#define INIT_SUBTARGET_OPTABS INIT_GOFAST_OPTABS
diff --git a/contrib/gcc/config/sparc/litecoff.h b/contrib/gcc/config/sparc/litecoff.h
index bd89e1b..dede792 100644
--- a/contrib/gcc/config/sparc/litecoff.h
+++ b/contrib/gcc/config/sparc/litecoff.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for SPARClite w/o FPU, COFF.
- Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1996, 2000 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com).
This file is part of GNU CC.
@@ -19,95 +19,58 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "sparc/lite.h"
-
-#undef ASM_OUTPUT_IDENT
-
-#undef SELECT_SECTION
-#undef SELECT_RTX_SECTION
-#define BSS_SECTION_ASM_OP ".section\t\".bss\""
-
-#include "svr3.h"
+#define BSS_SECTION_ASM_OP "\t.section\t\".bss\""
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dsparc -Dsparclite -Acpu(sparc) -Amachine(sparc)"
+#define CPP_PREDEFINES "-Dsparc -Dsparclite -Acpu=sparc -Amachine=sparc"
/* Default to stabs in COFF. */
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-#include "dbxcoff.h"
-
/* Support the ctors and dtors sections for g++. */
#undef INIT_SECTION_ASM_OP
-/* Support the ctors and dtors sections for g++. */
-
-#undef CTORS_SECTION_ASM_OP
-#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"x\""
-#undef DTORS_SECTION_ASM_OP
-#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"x\""
-
/* A list of other sections which the compiler might be "in" at any
given time. */
#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_const, in_ctors, in_dtors
+#define EXTRA_SECTIONS in_const
/* A list of extra section function definitions. */
#undef EXTRA_SECTION_FUNCTIONS
#define EXTRA_SECTION_FUNCTIONS \
- CONST_SECTION_FUNCTION \
- CTORS_SECTION_FUNCTION \
- DTORS_SECTION_FUNCTION
-
-#define CTORS_SECTION_FUNCTION \
-void \
-ctors_section () \
-{ \
- if (in_section != in_ctors) \
- { \
- fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \
- in_section = in_ctors; \
- } \
-}
-
-#define DTORS_SECTION_FUNCTION \
-void \
-dtors_section () \
-{ \
- if (in_section != in_dtors) \
- { \
- fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \
- in_section = in_dtors; \
- } \
-}
-
-#define INT_ASM_OP ".long"
-
-/* A C statement (sans semicolon) to output an element in the table of
- global constructors. */
-#undef ASM_OUTPUT_CONSTRUCTOR
-#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
- do { \
- ctors_section (); \
- fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
- assemble_name (FILE, NAME); \
- fprintf (FILE, "\n"); \
- } while (0)
-
-/* A C statement (sans semicolon) to output an element in the table of
- global destructors. */
-#undef ASM_OUTPUT_DESTRUCTOR
-#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
- do { \
- dtors_section (); \
- fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
- assemble_name (FILE, NAME); \
- fprintf (FILE, "\n"); \
- } while (0)
+ CONST_SECTION_FUNCTION
#undef DO_GLOBAL_CTORS_BODY
#undef DO_GLOBAL_DTORS_BODY
+
+/* These compiler options take an argument. We ignore -target for now. */
+
+#define WORD_SWITCH_TAKES_ARG(STR) \
+ (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \
+ || !strcmp (STR, "target") || !strcmp (STR, "assert"))
+
+/* Output the label for a function definition. */
+
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+do { \
+ ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
+} while (0)
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP "\t.text"
+
+/* Output before writable data. */
+
+#define DATA_SECTION_ASM_OP "\t.data"
+
+/* How to renumber registers for dbx and gdb. In the flat model, the frame
+ pointer is really %i7. */
+
+#define DBX_REGISTER_NUMBER(REGNO) \
+ (TARGET_FLAT && REGNO == FRAME_POINTER_REGNUM ? 31 : REGNO)
diff --git a/contrib/gcc/config/sparc/liteelf.h b/contrib/gcc/config/sparc/liteelf.h
new file mode 100644
index 0000000..d7c88b5
--- /dev/null
+++ b/contrib/gcc/config/sparc/liteelf.h
@@ -0,0 +1,52 @@
+/* Definitions of target machine for GNU compiler, for SPARClite w/o FPU.
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ Contributed by Stan Cox (scox@cygnus.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-D__sparc__ -D__sparclite__ -Acpu=sparc -Amachine=sparc"
+
+/* Default to dwarf2 in ELF. */
+
+#undef DWARF_DEBUGGING_INFO
+#define DWARF_DEBUGGING_INFO
+#undef DWARF2_DEBUGGING_INFO
+#define DWARF2_DEBUGGING_INFO
+
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (sparclite)");
+
+/* Enable app-regs and epilogue options. Do not enable the fpu. */
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE)
+
+/* US Software GOFAST library support. */
+#undef INIT_SUBTARGET_OPTABS
+#define INIT_SUBTARGET_OPTABS INIT_GOFAST_OPTABS
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "crti.o%s crtbegin.o%s"
+
+/* Use __main method of constructor invocation. */
+#undef INIT_SECTION_ASM_OP
+#undef FINI_SECTION_ASM_OP
diff --git a/contrib/gcc/config/sparc/lynx-ng.h b/contrib/gcc/config/sparc/lynx-ng.h
index 9e9f82c..b1a6ef5 100644
--- a/contrib/gcc/config/sparc/lynx-ng.h
+++ b/contrib/gcc/config/sparc/lynx-ng.h
@@ -18,9 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include <sparc/sparc.h>
-#include <lynx-ng.h>
-
/* ??? Must redefine to get sparclite and v8 defines. Can this be done
differently? */
@@ -33,7 +30,7 @@ Boston, MA 02111-1307, USA. */
/* Names to predefine in the preprocessor for this target machine. */
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dunix -Dsparc -DLynx -DIBITS32 -Asystem(unix) -Asystem(lynx) -Acpu(sparc) -Amachine(sparc)"
+#define CPP_PREDEFINES "-Dunix -Dsparc -DLynx -DIBITS32 -Asystem=unix -Asystem=lynx -Acpu=sparc -Amachine=sparc"
/* Provide required defaults for linker switches. */
diff --git a/contrib/gcc/config/sparc/lynx.h b/contrib/gcc/config/sparc/lynx.h
index 99b319a..866612d 100644
--- a/contrib/gcc/config/sparc/lynx.h
+++ b/contrib/gcc/config/sparc/lynx.h
@@ -1,5 +1,5 @@
/* Definitions for SPARC running LynxOS.
- Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,15 +18,10 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include <sparc/sparc.h>
-
#undef ASM_OUTPUT_IDENT
-#undef SELECT_SECTION
#undef SELECT_RTX_SECTION
-#define BSS_SECTION_ASM_OP ".section\t\".bss\""
-
-#include <lynx.h>
+#define BSS_SECTION_ASM_OP "\t.section\t\".bss\""
/* ??? Must redefine to get sparclite and v8 defines. Can this be done
differently? */
@@ -40,12 +35,12 @@ Boston, MA 02111-1307, USA. */
/* Names to predefine in the preprocessor for this target machine. */
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dunix -Dsparc -DSPARC -DLynx -DLYNX -DIBITS32 -Asystem(unix) -Asystem(lynx) -Acpu(sparc) -Amachine(sparc)"
+#define CPP_PREDEFINES "-Dunix -Dsparc -DSPARC -DLynx -DLYNX -DIBITS32 -Asystem=unix -Asystem=lynx -Acpu=sparc -Amachine=sparc"
#undef LINK_SPEC
/* Sparc version of libc.a has references to libm.a (printf calls pow for
- instance), so we must always link both. */
+ instance), so we must always link both. */
#undef LIB_SPEC
#define LIB_SPEC "%{mthreads:-L/lib/thread/} \
diff --git a/contrib/gcc/config/sparc/netbsd.h b/contrib/gcc/config/sparc/netbsd.h
index a512f41..4be5b6b 100644
--- a/contrib/gcc/config/sparc/netbsd.h
+++ b/contrib/gcc/config/sparc/netbsd.h
@@ -1,13 +1,7 @@
-#include <sparc/sparc.h>
-
-/* Get generic NetBSD definitions. */
-
-#include <netbsd.h>
-
/* Names to predefine in the preprocessor for this target machine. */
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dunix -Dsparc -D__NetBSD__ -Asystem(unix) -Asystem(NetBSD) -Acpu(sparc) -Amachine(sparc)"
+#define CPP_PREDEFINES "-Dunix -Dsparc -D__NetBSD__ -Asystem=unix -Asystem=NetBSD -Acpu=sparc -Amachine=sparc"
/* Make gcc agree with <machine/ansi.h> */
@@ -43,4 +37,3 @@
/* Until they use ELF or something that handles dwarf2 unwinds
and initialization stuff better. */
#define DWARF2_UNWIND_INFO 0
-
diff --git a/contrib/gcc/config/sparc/openbsd.h b/contrib/gcc/config/sparc/openbsd.h
index 19ece97..dc37284 100644
--- a/contrib/gcc/config/sparc/openbsd.h
+++ b/contrib/gcc/config/sparc/openbsd.h
@@ -18,14 +18,12 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include <sparc/sparc.h>
-
/* 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)"
+#define CPP_PREDEFINES "-D__unix__ -D__sparc__ -D__OpenBSD__ -Asystem=unix -Asystem=OpenBSD -Acpu=sparc -Amachine=sparc"
/* Layout of source language data types */
@@ -64,5 +62,6 @@ Boston, MA 02111-1307, USA. */
configuration files... */
#define DWARF2_UNWIND_INFO 0
-/* Default sparc.h does already define ASM_OUTPUT_MI_THUNK */
+#undef ASM_PREFERRED_EH_DATA_FORMAT
+/* Default sparc.h does already define ASM_OUTPUT_MI_THUNK */
diff --git a/contrib/gcc/config/sparc/pbd.h b/contrib/gcc/config/sparc/pbd.h
index b70fdcb..27dfa96 100644
--- a/contrib/gcc/config/sparc/pbd.h
+++ b/contrib/gcc/config/sparc/pbd.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler, Citicorp/TTI Unicom PBD
version (using GAS and COFF (encapsulated is unacceptable) )
- Copyright (C) 1990, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1996, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -19,12 +19,11 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "sparc/sparc.h"
/* 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)"
+#define CPP_PREDEFINES "-Dsparc -DUnicomPBD -Dunix -D__GCC_NEW_VARARGS__ -Asystem=unix -Acpu=sparc -Amachine=sparc"
/* We want DBX format for use with gdb under COFF. */
@@ -77,7 +76,7 @@ Boston, MA 02111-1307, USA. */
/* similar to default, but allows for the table defined by ld with gcc.ifile.
nptrs is always 0. So we need to instead check that __DTOR_LIST__[1] != 0.
The old check is left in so that the same macro can be used if and when
- a future version of gas does support section directives. */
+ a future version of gas does support section directives. */
#define DO_GLOBAL_DTORS_BODY {int nptrs = *(int *)__DTOR_LIST__; int i; \
if (nptrs == -1 || (__DTOR_LIST__[0] == 0 && __DTOR_LIST__[1] != 0)) \
@@ -102,7 +101,7 @@ Boston, MA 02111-1307, USA. */
}
*/
-/* The prefix to add to user-visible assembler symbols. */
+/* The prefix to add to user-visible assembler symbols. */
#undef USER_LABEL_PREFIX
#define USER_LABEL_PREFIX ""
@@ -120,7 +119,7 @@ Boston, MA 02111-1307, USA. */
#undef ASM_GENERATE_INTERNAL_LABEL
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
- sprintf (LABEL, "*.%s%d", PREFIX, NUM)
+ sprintf (LABEL, "*.%s%ld", PREFIX, (long)(NUM))
/* This is how to output an internal numbered label where
@@ -146,11 +145,11 @@ 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(file, line)
+#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_INT_OP ".long "
+#define ASM_INT_OP "\t.long "
diff --git a/contrib/gcc/config/sparc/rtems.h b/contrib/gcc/config/sparc/rtems.h
index 1ab0a42..9db8049 100644
--- a/contrib/gcc/config/sparc/rtems.h
+++ b/contrib/gcc/config/sparc/rtems.h
@@ -1,5 +1,5 @@
/* Definitions for rtems targeting a SPARC using a.out.
- Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc.
Contributed by Joel Sherrill (joel@OARcorp.com).
This file is part of GNU CC.
@@ -19,17 +19,14 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "sparc/aout.h"
/* Specify predefined symbols in preprocessor. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Dsparc -D__GCC_NEW_VARARGS__ -Drtems -D__rtems__ \
- -Asystem(rtems) -Acpu(sparc) -Amachine(sparc)"
+ -Asystem=rtems"
/* Generate calls to memcpy, memcmp and memset. */
#ifndef TARGET_MEM_FUNCTIONS
#define TARGET_MEM_FUNCTIONS
#endif
-
-/* end of sparc/rtems.h */
diff --git a/contrib/gcc/config/sparc/rtemself.h b/contrib/gcc/config/sparc/rtemself.h
new file mode 100644
index 0000000..108ff33
--- /dev/null
+++ b/contrib/gcc/config/sparc/rtemself.h
@@ -0,0 +1,31 @@
+/* Definitions for rtems targeting a SPARC using ELF.
+ Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc.
+ Contributed by Joel Sherrill (joel@OARcorp.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Specify predefined symbols in preprocessor. */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dsparc -D__GCC_NEW_VARARGS__ -Drtems -D__rtems__ \
+ -Asystem=rtems"
+
+/* Generate calls to memcpy, memcmp and memset. */
+#ifndef TARGET_MEM_FUNCTIONS
+#define TARGET_MEM_FUNCTIONS
+#endif
diff --git a/contrib/gcc/config/sparc/sol2-64.h b/contrib/gcc/config/sparc/sol2-64.h
new file mode 100644
index 0000000..40db497
--- /dev/null
+++ b/contrib/gcc/config/sparc/sol2-64.h
@@ -0,0 +1,20 @@
+/* Definitions of target machine for GNU compiler, for 64-bit SPARC
+ running Solaris 2 using the GNU linker. */
+
+#ifdef LINKER_DOES_NOT_WORK_WITH_DWARF2
+#undef LINKER_DOES_NOT_WORK_WITH_DWARF2
+#endif
+
+#ifdef AS_SPARC64_FLAG
+
+#ifdef LINK_ARCH_SPEC
+#undef LINK_ARCH_SPEC
+#endif
+
+#define LINK_ARCH_SPEC "\
+%{m32:-m elf32_sparc %(link_arch32)} \
+%{m64:-m elf64_sparc %(link_arch64)} \
+%{!m32:%{!m64:%(link_arch_default)}} \
+"
+
+#endif
diff --git a/contrib/gcc/config/sparc/sol2-sld-64.h b/contrib/gcc/config/sparc/sol2-sld-64.h
index c2518d8..161026b 100644
--- a/contrib/gcc/config/sparc/sol2-sld-64.h
+++ b/contrib/gcc/config/sparc/sol2-sld-64.h
@@ -1,10 +1,19 @@
/* Definitions of target machine for GNU compiler, for 64-bit SPARC
running Solaris 2 using the system linker. */
-#define SPARC_BI_ARCH
+#ifdef AS_SPARC64_FLAG
+#include "sparc/sparc_bi.h"
+#endif
+#include "sparc/sparc.h"
+#include "dbxelf.h"
+#include "elfos.h"
+#include "svr4.h"
+#include "sparc/sysv4.h"
#include "sparc/sol2.h"
+#ifdef AS_SPARC64_FLAG
+
/* At least up through Solaris 2.6,
the system linker does not work with DWARF or DWARF2,
since it does not have working support for relocations
@@ -18,7 +27,7 @@
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
(MASK_V9 + MASK_PTR64 + MASK_64BIT /* + MASK_HARD_QUAD */ + \
- MASK_STACK_BIAS + MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU)
+ MASK_STACK_BIAS + MASK_EPILOGUE + MASK_FPU + MASK_LONG_DOUBLE_128)
#endif
/* The default code model. */
@@ -31,7 +40,7 @@
#undef ASM_CPU32_DEFAULT_SPEC
#define ASM_CPU32_DEFAULT_SPEC ""
#undef ASM_CPU64_DEFAULT_SPEC
-#define ASM_CPU64_DEFAULT_SPEC "-xarch=v9"
+#define ASM_CPU64_DEFAULT_SPEC AS_SPARC64_FLAG
#if TARGET_CPU_DEFAULT == TARGET_CPU_v9
#undef CPP_CPU64_DEFAULT_SPEC
@@ -45,11 +54,11 @@
#undef ASM_CPU32_DEFAULT_SPEC
#define ASM_CPU32_DEFAULT_SPEC "-xarch=v8plusa"
#undef ASM_CPU64_DEFAULT_SPEC
-#define ASM_CPU64_DEFAULT_SPEC "-xarch=v9a"
+#define ASM_CPU64_DEFAULT_SPEC AS_SPARC64_FLAG "a"
#endif
/* The sun bundled assembler doesn't accept -Yd, (and neither does gas).
- It's safe to pass -s always, even if -g is not used. */
+ It's safe to pass -s always, even if -g is not used. */
#undef ASM_SPEC
#define ASM_SPEC "\
%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s \
@@ -84,9 +93,9 @@
#undef ASM_CPU_SPEC
#define ASM_CPU_SPEC "\
-%{mcpu=ultrasparc:" DEF_ARCH32_SPEC("-xarch=v8plusa") DEF_ARCH64_SPEC("-xarch=v9a") "} \
-%{mcpu=v9:" DEF_ARCH32_SPEC("-xarch=v8plus") DEF_ARCH64_SPEC("-xarch=v9") "} \
-%{!mcpu=ultrasparc:%{!mcpu=v9:%{mcpu*:" DEF_ARCH32_SPEC("-xarch=v8") DEF_ARCH64_SPEC("-xarch=v9") "}}} \
+%{mcpu=ultrasparc:" DEF_ARCH32_SPEC("-xarch=v8plusa") DEF_ARCH64_SPEC(AS_SPARC64_FLAG "a") "} \
+%{mcpu=v9:" DEF_ARCH32_SPEC("-xarch=v8plus") DEF_ARCH64_SPEC(AS_SPARC64_FLAG) "} \
+%{!mcpu=ultrasparc:%{!mcpu=v9:%{mcpu*:" DEF_ARCH32_SPEC("-xarch=v8") DEF_ARCH64_SPEC(AS_SPARC64_FLAG) "}}} \
%{!mcpu*:%(asm_cpu_default)} \
"
@@ -130,7 +139,7 @@
%{!p: \
%{pg:gcrt1.o%s gmon.o%s} \
%{!pg:crt1.o%s}}}} \
- crti.o%s" STARTFILE_ARCH_SPEC " \
+ crti.o%s " STARTFILE_ARCH_SPEC " \
crtbegin.o%s"
#ifdef SPARC_BI_ARCH
@@ -155,12 +164,36 @@
%{!m32:" ASM_CPU64_DEFAULT_SPEC "} \
")
+/* wchar_t is called differently in <wchar.h> for 32 and 64-bit
+ compilations. This is called for by SCD 2.4.1, p. 6-83, Figure 6-65
+ (32-bit) and p. 6P-10, Figure 6.38 (64-bit). */
+#define NO_BUILTIN_WCHAR_TYPE
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE (TARGET_ARCH64 ? "int" : "long int")
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+/* Same for wint_t. See SCD 2.4.1, p. 6-83, Figure 6-66 (32-bit). There's
+ no corresponding 64-bit definition, but this is what Solaris 8
+ <iso/wchar_iso.h> uses. */
+#define NO_BUILTIN_WINT_TYPE
+
+#undef WINT_TYPE
+#define WINT_TYPE (TARGET_ARCH64 ? "int" : "long int")
+
+#undef WINT_TYPE_SIZE
+#define WINT_TYPE_SIZE 32
+
#undef CPP_ARCH32_SPEC
#define CPP_ARCH32_SPEC "-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int \
--D__GCC_NEW_VARARGS__ -Acpu(sparc) -Amachine(sparc)"
+-D__WCHAR_TYPE__=long\\ int -D__WINT_TYPE__=long\\ int \
+-D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc"
#undef CPP_ARCH64_SPEC
#define CPP_ARCH64_SPEC "-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int \
--D__arch64__ -Acpu(sparc64) -Amachine(sparcv9) -D__sparcv9"
+-D__WCHAR_TYPE__=int -D__WINT_TYPE__=int \
+-D__arch64__ -Acpu=sparc64 -Amachine=sparcv9 -D__sparcv9"
#undef CPP_ARCH_SPEC
#define CPP_ARCH_SPEC "\
@@ -244,7 +277,8 @@
%{mcypress:-mcpu=cypress} \
%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \
%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
-%{m64:-mptr64 -mcpu=v9 -mstack-bias -mno-v8plus} \
+%{m64:-mptr64 -mstack-bias -mno-v8plus \
+ %{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8*:%{!msupersparc:-mcpu=v9}}}}}}}} \
"
#else
#define CC1_SPEC "\
@@ -252,8 +286,10 @@
%{mcypress:-mcpu=cypress} \
%{msparclite:-mcpu=sparclite} %{mf930:-mcpu=f930} %{mf934:-mcpu=f934} \
%{mv8:-mcpu=v8} %{msupersparc:-mcpu=supersparc} \
-%{m32:-mptr32 -mcpu=cypress -mno-stack-bias} \
-%{mv8plus:-m32 -mptr32 -mcpu=cypress -mno-stack-bias} \
+%{m32:-mptr32 -mno-stack-bias \
+ %{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8*:%{!msupersparc:-mcpu=cypress}}}}}}}} \
+%{mv8plus:-m32 -mptr32 -mno-stack-bias \
+ %{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:-mcpu=v9}}}}}}}} \
"
#endif
@@ -296,68 +332,4 @@
#endif /* ! SPARC_BI_ARCH */
-/*
- * Attempt to turn on access permissions for the stack.
- *
- * This code must be defined when compiling gcc but not when compiling
- * libgcc2.a, unless we're generating code for 64 bits SPARC
- *
- * _SC_STACK_PROT is only defined for post 2.6, but we want this code
- * to run always. 2.6 can change the stack protection but has no way to
- * query it.
- *
- */
-
-#define TRANSFER_FROM_TRAMPOLINE \
-static int need_enable_exec_stack; \
- \
-static void check_enabling(void) __attribute__ ((constructor)); \
-static void check_enabling(void) \
-{ \
- extern long sysconf(int); \
- \
- int prot = (int) sysconf(515 /*_SC_STACK_PROT */); \
- if (prot != 7) \
- need_enable_exec_stack = 1; \
-} \
- \
-void \
-__enable_execute_stack (addr) \
- void *addr; \
-{ \
- if (!need_enable_exec_stack) \
- return; \
- else { \
- long size = getpagesize (); \
- long mask = ~(size-1); \
- char *page = (char *) (((long) addr) & mask); \
- char *end = (char *) ((((long) (addr + TRAMPOLINE_SIZE)) & mask) + size); \
- \
- /* 7 is PROT_READ | PROT_WRITE | PROT_EXEC */ \
- if (mprotect (page, end - page, 7) < 0) \
- perror ("mprotect of trampoline code"); \
- } \
-}
-
-/* A C statement (sans semicolon) to output an element in the table of
- global constructors. */
-#undef ASM_OUTPUT_CONSTRUCTOR
-#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
- do { \
- ctors_section (); \
- fprintf (FILE, "\t%s\t ", TARGET_ARCH64 ? ASM_LONGLONG : INT_ASM_OP); \
- assemble_name (FILE, NAME); \
- fprintf (FILE, "\n"); \
- } while (0)
-
-/* A C statement (sans semicolon) to output an element in the table of
- global destructors. */
-#undef ASM_OUTPUT_DESTRUCTOR
-#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
- do { \
- dtors_section (); \
- fprintf (FILE, "\t%s\t ", TARGET_ARCH64 ? ASM_LONGLONG : INT_ASM_OP); \
- assemble_name (FILE, NAME); \
- fprintf (FILE, "\n"); \
- } while (0)
-
+#endif
diff --git a/contrib/gcc/config/sparc/sol2-sld.h b/contrib/gcc/config/sparc/sol2-sld.h
index a824987..3847fae 100644
--- a/contrib/gcc/config/sparc/sol2-sld.h
+++ b/contrib/gcc/config/sparc/sol2-sld.h
@@ -1,8 +1,6 @@
/* Definitions of target machine for GNU compiler, for SPARC running Solaris 2
using the system linker. */
-#include "sparc/sol2.h"
-
/* At least up through Solaris 2.6,
the system linker does not work with DWARF or DWARF2,
since it does not have working support for relocations
diff --git a/contrib/gcc/config/sparc/sol2.h b/contrib/gcc/config/sparc/sol2.h
index 9274f9d..46e80c1 100644
--- a/contrib/gcc/config/sparc/sol2.h
+++ b/contrib/gcc/config/sparc/sol2.h
@@ -1,5 +1,6 @@
/* Definitions of target machine for GNU compiler, for SPARC running Solaris 2
- Copyright 1992, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright 1992, 1995, 1996, 1997, 1998, 1999, 2000,
+ 2001 Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@netcom.com).
Additional changes by David V. Henkel-Wallace (gumby@cygnus.com).
@@ -21,12 +22,19 @@ 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: */
-#include "sparc/sysv4.h"
+
+/* Solaris 2 uses a wint_t different from the default. This is required
+ by the SCD 2.4.1, p. 6-83, Figure 6-66. */
+#undef WINT_TYPE
+#define WINT_TYPE "long int"
+
+#undef WINT_TYPE_SIZE
+#define WINT_TYPE_SIZE BITS_PER_WORD
#undef CPP_PREDEFINES
#define CPP_PREDEFINES \
"-Dsparc -Dsun -Dunix -D__svr4__ -D__SVR4 \
--Asystem(unix) -Asystem(svr4)"
+-Asystem=unix -Asystem=svr4"
#undef CPP_SUBTARGET_SPEC
#define CPP_SUBTARGET_SPEC "\
@@ -35,8 +43,16 @@ Boston, MA 02111-1307, USA. */
%{compat-bsd:-iwithprefixbefore ucbinclude -I/usr/ucbinclude} \
"
+/* For C++ we need to add some additional macro definitions required
+ by the C++ standard library. */
+#define CPLUSPLUS_CPP_SPEC "\
+-D_XOPEN_SOURCE=500 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE=1 \
+-D__EXTENSIONS__ \
+%(cpp) \
+"
+
/* The sun bundled assembler doesn't accept -Yd, (and neither does gas).
- It's safe to pass -s always, even if -g is not used. */
+ It's safe to pass -s always, even if -g is not used. */
#undef ASM_SPEC
#define ASM_SPEC "\
%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s \
@@ -62,7 +78,7 @@ Boston, MA 02111-1307, USA. */
"
/* However it appears that Solaris 2.0 uses the same reg numbering as
- the old BSD-style system did. */
+ the old BSD-style system did. */
#undef DBX_REGISTER_NUMBER
/* Same as sparc.h */
@@ -74,18 +90,11 @@ Boston, MA 02111-1307, USA. */
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-/* The Solaris 2 assembler uses .skip, not .zero, so put this back. */
+/* 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))
-/* Use .uahalf/.uaword so packed structure members don't generate
- assembler errors when using the native assembler. */
-#undef ASM_SHORT
-#define ASM_SHORT ".uahalf"
-#undef ASM_LONG
-#define ASM_LONG ".uaword"
-
/* 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. */
@@ -138,7 +147,7 @@ Boston, MA 02111-1307, USA. */
%{!symbolic:\
%{pthreads:-lpthread} \
%{!pthreads:%{threads:-lthread}} \
- -lc}}"
+ %{p|pg:-ldl} -lc}}"
#undef ENDFILE_SPEC
#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
@@ -155,14 +164,14 @@ Boston, MA 02111-1307, USA. */
%{YP,*} \
%{R*} \
%{compat-bsd: \
- %{!YP,*:%{p:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
- %{pg:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
- %{!p:%{!pg:-Y P,/usr/ucblib:/usr/ccs/lib:/usr/lib}}} \
- -R /usr/ucblib} \
+ %{!YP,*:%{pg:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
+ %{!pg:%{p:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
+ %{!p:-Y P,/usr/ucblib:/usr/ccs/lib:/usr/lib}}} \
+ -R /usr/ucblib} \
%{!compat-bsd: \
- %{!YP,*:%{p:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
- %{pg:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
- %{!p:%{!pg:-Y P,/usr/ccs/lib:/usr/lib}}}} \
+ %{!YP,*:%{pg:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
+ %{!pg:%{p:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
+ %{!p:-Y P,/usr/ccs/lib:/usr/lib}}}} \
%{Qy:} %{!Qn:-Qy}"
/* This defines which switch letters take arguments.
@@ -175,6 +184,17 @@ Boston, MA 02111-1307, USA. */
|| (CHAR) == 'h' \
|| (CHAR) == 'x' \
|| (CHAR) == 'z')
+
+/* Select a format to encode pointers in exception handling data. CODE
+ is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
+ true if the symbol may be affected by dynamic relocations.
+
+ Some Solaris dynamic linkers don't handle unaligned section relative
+ relocs properly, so force them to be aligned. */
+#ifndef HAVE_AS_SPARC_UA_PCREL
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
+ ((flag_pic || GLOBAL) ? DW_EH_PE_aligned : DW_EH_PE_absptr)
+#endif
/* ??? 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. */
@@ -185,7 +205,7 @@ Boston, MA 02111-1307, USA. */
/* But indicate that it isn't supported by the hardware. */
#define WIDEST_HARDWARE_FP_SIZE 64
-#define STDC_0_IN_SYSTEM_HEADERS
+#define STDC_0_IN_SYSTEM_HEADERS 1
#define MULDI3_LIBCALL "__mul64"
#define DIVDI3_LIBCALL "__div64"
@@ -194,43 +214,67 @@ Boston, MA 02111-1307, USA. */
#define UMODDI3_LIBCALL "__urem64"
#undef INIT_SUBTARGET_OPTABS
-#define INIT_SUBTARGET_OPTABS \
- fixsfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, \
- TARGET_ARCH64 ? "__ftol" : "__ftoll"); \
- fixunssfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, \
- TARGET_ARCH64 ? "__ftoul" : "__ftoull"); \
- fixdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, \
- TARGET_ARCH64 ? "__dtol" : "__dtoll"); \
- fixunsdfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, \
- TARGET_ARCH64 ? "__dtoul" : "__dtoull")
-
-/* No weird SPARC variants on Solaris */
-#undef TARGET_LIVE_G0
-#define TARGET_LIVE_G0 0
-#undef TARGET_BROKEN_SAVERESTORE
-#define TARGET_BROKEN_SAVERESTORE 0
+#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")
/* Solaris allows 64 bit out and global registers in 32 bit mode.
sparc_override_options will disable V8+ if not generating V9 code. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU + MASK_V8PLUS)
+#define TARGET_DEFAULT (MASK_EPILOGUE + MASK_FPU + MASK_V8PLUS + MASK_LONG_DOUBLE_128)
-/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special
- traps available which can get and set the condition codes
- reliably. */
-#undef MACHINE_STATE_SAVE
-#define MACHINE_STATE_SAVE(ID) \
- unsigned long int ms_flags, ms_saveret; \
- asm volatile("ta 0x20\n\t" \
- "mov %%g1, %0\n\t" \
- "mov %%g2, %1\n\t" \
- : "=r" (ms_flags), "=r" (ms_saveret));
-
-#undef MACHINE_STATE_RESTORE
-#define MACHINE_STATE_RESTORE(ID) \
- asm volatile("mov %0, %%g1\n\t" \
- "mov %1, %%g2\n\t" \
- "ta 0x21\n\t" \
- : /* no outputs */ \
- : "r" (ms_flags), "r" (ms_saveret));
+/*
+ * Attempt to turn on access permissions for the stack.
+ *
+ * This code must be defined when compiling gcc but not when compiling
+ * libgcc2.a, unless we're generating code for 64 bits SPARC
+ *
+ * _SC_STACK_PROT is only defined for post 2.6, but we want this code
+ * to run always. 2.6 can change the stack protection but has no way to
+ * query it.
+ *
+ */
+
+/* This declares mprotect (used in TRANSFER_FROM_TRAMPOLINE) for
+ libgcc2.c. */
+#ifdef L_trampoline
+#include <sys/mman.h>
+#endif
+#define TRANSFER_FROM_TRAMPOLINE \
+static int need_enable_exec_stack; \
+ \
+static void check_enabling(void) __attribute__ ((constructor)); \
+static void check_enabling(void) \
+{ \
+ extern long sysconf(int); \
+ \
+ int prot = (int) sysconf(515 /*_SC_STACK_PROT */); \
+ if (prot != 7) \
+ need_enable_exec_stack = 1; \
+} \
+ \
+extern void __enable_execute_stack (void *); \
+void \
+__enable_execute_stack (addr) \
+ void *addr; \
+{ \
+ if (!need_enable_exec_stack) \
+ return; \
+ else { \
+ long size = getpagesize (); \
+ long mask = ~(size-1); \
+ char *page = (char *) (((long) addr) & mask); \
+ char *end = (char *) ((((long) (addr + TRAMPOLINE_SIZE)) & mask) + size); \
+ \
+ /* 7 is PROT_READ | PROT_WRITE | PROT_EXEC */ \
+ if (mprotect (page, end - page, 7) < 0) \
+ perror ("mprotect of trampoline code"); \
+ } \
+}
diff --git a/contrib/gcc/config/sparc/sp64-aout.h b/contrib/gcc/config/sparc/sp64-aout.h
index e3056df..669adc3 100644
--- a/contrib/gcc/config/sparc/sp64-aout.h
+++ b/contrib/gcc/config/sparc/sp64-aout.h
@@ -19,8 +19,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "sparc/sparc.h"
-#include "aoutos.h"
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (sparc64-aout)")
@@ -33,6 +31,3 @@ Boston, MA 02111-1307, USA. */
/* The only code model supported is Medium/Low. */
#undef SPARC_DEFAULT_CMODEL
#define SPARC_DEFAULT_CMODEL CM_MEDLOW
-
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dsparc -Acpu(sparc) -Amachine(sparc)"
diff --git a/contrib/gcc/config/sparc/sp64-elf.h b/contrib/gcc/config/sparc/sp64-elf.h
index 4fd81c5..3bd2a53 100644
--- a/contrib/gcc/config/sparc/sp64-elf.h
+++ b/contrib/gcc/config/sparc/sp64-elf.h
@@ -1,5 +1,6 @@
/* Definitions of target machine for GNU compiler, for SPARC64, ELF.
- Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+ 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.
@@ -24,8 +25,6 @@ Boston, MA 02111-1307, USA. */
less duplicate all of svr4.h, sparc/sysv4.h, and sparc/sol2.h here
(suitably cleaned up). */
-#include "sparc/sol2.h"
-
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (sparc64-elf)")
@@ -34,13 +33,13 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
(MASK_V9 + MASK_PTR64 + MASK_64BIT + MASK_HARD_QUAD \
- + MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU + MASK_STACK_BIAS)
+ + MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU + MASK_STACK_BIAS + MASK_LONG_DOUBLE_128)
#undef SPARC_DEFAULT_CMODEL
#define SPARC_DEFAULT_CMODEL CM_EMBMEDANY
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dsparc -D__ELF__ -Acpu(sparc) -Amachine(sparc)"
+#define CPP_PREDEFINES "-Dsparc -D__ELF__ -Acpu=sparc -Amachine=sparc"
/* __svr4__ is used by the C library (FIXME) */
#undef CPP_SUBTARGET_SPEC
@@ -80,8 +79,8 @@ crtbegin.o%s \
/* V9 chips can handle either endianness. */
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
-{"big-endian", -MASK_LITTLE_ENDIAN, "Generate code for big endian" }, \
-{"little-endian", MASK_LITTLE_ENDIAN, "Generate code for little endian" },
+{"big-endian", -MASK_LITTLE_ENDIAN, N_("Generate code for big endian") }, \
+{"little-endian", MASK_LITTLE_ENDIAN, N_("Generate code for little endian") },
#undef BYTES_BIG_ENDIAN
#define BYTES_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN)
@@ -111,48 +110,7 @@ crtbegin.o%s \
GDB doesn't support 64 bit stabs yet and the desired debug format is DWARF
anyway so it is the default. */
-#define DWARF_DEBUGGING_INFO
-#define DWARF2_DEBUGGING_INFO
#define DBX_DEBUGGING_INFO
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-
-/* Stabs doesn't use this, and it confuses a simulator. */
-/* ??? Need to see what DWARF needs, if anything. */
-#undef ASM_IDENTIFY_GCC
-#define ASM_IDENTIFY_GCC(FILE)
-
-/* Define the names of various pseudo-ops used by the Sparc/svr4 assembler.
- ??? If ints are 64 bits then UNALIGNED_INT_ASM_OP (defined elsewhere) is
- misnamed. These should all refer to explicit sizes (half/word/xword?),
- anything other than short/int/long/etc. */
-
-#define UNALIGNED_LONGLONG_ASM_OP ".uaxword"
-
-/* DWARF stuff. */
-
-#define ASM_OUTPUT_DWARF_ADDR(FILE, LABEL) \
-do { \
- fprintf ((FILE), "\t%s\t", UNALIGNED_LONGLONG_ASM_OP); \
- assemble_name ((FILE), (LABEL)); \
- fprintf ((FILE), "\n"); \
-} while (0)
-
-#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE, RTX) \
-do { \
- fprintf ((FILE), "\t%s\t", UNALIGNED_LONGLONG_ASM_OP); \
- output_addr_const ((FILE), (RTX)); \
- fputc ('\n', (FILE)); \
-} while (0)
-
-#define ASM_OUTPUT_DWARF2_ADDR_CONST(FILE, ADDR) \
- fprintf ((FILE), "\t%s\t%s", UNALIGNED_LONGLONG_ASM_OP, (ADDR))
-
-/* ??? Not sure if this should be 4 or 8 bytes. 4 works for now. */
-#define ASM_OUTPUT_DWARF_REF(FILE, LABEL) \
-do { \
- fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \
- assemble_name ((FILE), (LABEL)); \
- fprintf ((FILE), "\n"); \
-} while (0)
diff --git a/contrib/gcc/config/sparc/sp86x-aout.h b/contrib/gcc/config/sparc/sp86x-aout.h
new file mode 100644
index 0000000..ed31925
--- /dev/null
+++ b/contrib/gcc/config/sparc/sp86x-aout.h
@@ -0,0 +1,51 @@
+/* Definitions of target machine for GNU compiler, for sparclite 86x w/o FPU.
+ Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-D__sparc__ -D__sparclite86x__ -Acpu=sparc -Amachine=sparc"
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (sparclite 86x)");
+
+/* Enable app-regs and epilogue options. Do not enable the fpu. */
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE)
+
+#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
+
+#undef LINK_SPEC
+#define LINK_SPEC "%{v:-V}"
+
+#undef BYTES_BIG_ENDIAN
+#define BYTES_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN_DATA)
+#undef WORDS_BIG_ENDIAN
+#define WORDS_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN_DATA)
+
+#define TARGET_LITTLE_ENDIAN_DATA (target_flags & MASK_LITTLE_ENDIAN)
+#undef SUBTARGET_SWITCHES
+#define SUBTARGET_SWITCHES \
+ { "little-endian-data", MASK_LITTLE_ENDIAN, N_("Use little-endian byte order for data")},
diff --git a/contrib/gcc/config/sparc/sp86x-elf.h b/contrib/gcc/config/sparc/sp86x-elf.h
new file mode 100644
index 0000000..40ecd55
--- /dev/null
+++ b/contrib/gcc/config/sparc/sp86x-elf.h
@@ -0,0 +1,67 @@
+/* Definitions of target machine for GNU compiler, 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.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-D__sparc__ -D__sparclite86x__ -Acpu=sparc -Amachine=sparc"
+
+/* Default to dwarf2 in ELF. */
+
+#undef DWARF_DEBUGGING_INFO
+#define DWARF_DEBUGGING_INFO
+#undef DWARF2_DEBUGGING_INFO
+#define DWARF2_DEBUGGING_INFO
+
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (sparclite 86x)");
+
+/* Enable app-regs and epilogue options. Do not enable the fpu. */
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE)
+
+#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
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "crti.o%s crtbegin.o%s"
+
+#undef LINK_SPEC
+#define LINK_SPEC "%{v:-V} %{mlittle-endian-data:-EL}"
+
+#undef BYTES_BIG_ENDIAN
+#define BYTES_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN_DATA)
+#undef WORDS_BIG_ENDIAN
+#define WORDS_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN_DATA)
+
+/* Use __main method of constructor invocation */
+#undef INIT_SECTION_ASM_OP
+
+#define TARGET_LITTLE_ENDIAN_DATA (target_flags & MASK_LITTLE_ENDIAN)
+#undef SUBTARGET_SWITCHES
+#define SUBTARGET_SWITCHES \
+ { "little-endian-data", MASK_LITTLE_ENDIAN, N_("Use little-endian byte order for data")},
diff --git a/contrib/gcc/config/sparc/sparc-protos.h b/contrib/gcc/config/sparc/sparc-protos.h
new file mode 100644
index 0000000..c0f3edc
--- /dev/null
+++ b/contrib/gcc/config/sparc/sparc-protos.h
@@ -0,0 +1,122 @@
+/* Prototypes of target machine for GNU compiler, for Sun SPARC.
+ Copyright (C) 1999, 2000 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.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifndef __SPARC_PROTOS_H__
+#define __SPARC_PROTOS_H__
+
+#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));
+#ifdef RTX_CODE
+extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx, int));
+extern void sparc_va_start PARAMS ((int, tree, rtx));
+#endif
+extern struct rtx_def *sparc_va_arg PARAMS ((tree, tree));
+extern unsigned long sparc_type_code PARAMS ((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));
+#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_function_profiler PARAMS ((FILE *, int));
+extern void sparc_function_block_profiler PARAMS ((FILE *, int));
+extern void sparc_block_profiler PARAMS ((FILE *, int));
+extern void sparc_function_block_profiler_exit PARAMS ((FILE *));
+extern void sparc_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));
+
+#ifdef RTX_CODE
+extern enum machine_mode select_cc_mode PARAMS ((enum rtx_code, rtx, rtx));
+/* Define the function that build the compare insn for scc and bcc. */
+extern rtx gen_compare_reg PARAMS ((enum rtx_code code, rtx, rtx));
+extern void sparc_emit_float_lib_cmp PARAMS ((rtx, rtx, enum rtx_code));
+/* 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, int, int, int, int, rtx));
+extern const char *output_return PARAMS ((rtx *));
+extern const char *output_sibcall PARAMS ((rtx, rtx));
+extern char *output_v9branch PARAMS ((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 eligible_for_epilogue_delay PARAMS ((rtx, int));
+extern int eligible_for_return_delay PARAMS ((rtx));
+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 *));
+/* Function used for V8+ code generation. Returns 1 if the high
+ 32 bits of REG are 0 before INSN. */
+extern int sparc_check_64 PARAMS ((rtx, rtx));
+extern int sparc_return_peephole_ok PARAMS ((rtx, rtx));
+extern rtx gen_df_reg PARAMS ((rtx, int));
+#endif /* RTX_CODE */
+
+#endif /* __SPARC_PROTOS_H__ */
diff --git a/contrib/gcc/config/sparc/sparc.c b/contrib/gcc/config/sparc/sparc.c
index 6ec392b..8cc4449 100644
--- a/contrib/gcc/config/sparc/sparc.c
+++ b/contrib/gcc/config/sparc/sparc.c
@@ -1,6 +1,6 @@
/* Subroutines for insn-output.c for Sun SPARC.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000 Free Software Foundation, Inc.
+ 1999, 2000, 2001 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.
@@ -31,13 +31,20 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
+#include "function.h"
#include "expr.h"
+#include "optabs.h"
+#include "libfuncs.h"
#include "recog.h"
#include "toplev.h"
+#include "ggc.h"
+#include "tm_p.h"
+#include "debug.h"
+#include "target.h"
+#include "target-def.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.
@@ -61,6 +68,10 @@ Boston, MA 02111-1307, USA. */
static int apparent_fsize;
static int actual_fsize;
+/* Number of live general or floating point registers needed to be saved
+ (as 4-byte quantities). This is only done if TARGET_EPILOGUE. */
+static int num_gfregs;
+
/* Save the operands last given to a compare for use when we
generate a scc or bcc insn. */
@@ -76,7 +87,7 @@ static rtx leaf_label;
registers. FRAME_POINTER_REGNUM cannot be remapped by
this function to eliminate it. You must use -fomit-frame-pointer
to get that. */
-char leaf_reg_remap[] =
+const char leaf_reg_remap[] =
{ 0, 1, 2, 3, 4, 5, 6, 7,
-1, -1, -1, -1, -1, -1, 14, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -92,6 +103,24 @@ char leaf_reg_remap[] =
88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100};
+/* Vector, indexed by hard register number, which contains 1
+ for a register that is allowable in a candidate for leaf
+ function treatment. */
+char sparc_leaf_regs[] =
+{ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1};
+
#endif
/* Name of where we pretend to think the frame pointer points.
@@ -102,28 +131,55 @@ char leaf_reg_remap[] =
static const char *frame_base_name;
static int frame_base_offset;
-static rtx pic_setup_code PROTO((void));
-static void sparc_init_modes PROTO((void));
-static int save_regs PROTO((FILE *, int, int, const char *,
+static void sparc_init_modes PARAMS ((void));
+static int save_regs PARAMS ((FILE *, int, int, const char *,
int, int, int));
-static int restore_regs PROTO((FILE *, int, int, const char *, int, int));
-static void build_big_number PROTO((FILE *, int, const char *));
-static int function_arg_slotno PROTO((const CUMULATIVE_ARGS *,
+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 PROTO((rtx, rtx, rtx, int));
-static int hypersparc_adjust_cost PROTO((rtx, rtx, rtx, int));
-static int ultrasparc_adjust_cost PROTO((rtx, rtx, rtx, int));
-
-static void sparc_output_addr_vec PROTO((rtx));
-static void sparc_output_addr_diff_vec PROTO((rtx));
-static void sparc_output_deferred_case_vectors PROTO((void));
-
-
-#ifdef DWARF2_DEBUGGING_INFO
-extern char *dwarf2out_cfi_label ();
+static int supersparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));
+static int hypersparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));
+static int ultrasparc_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 void sparc_add_gc_roots PARAMS ((void));
+static void mark_ultrasparc_pipeline_state 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 ultra_cmove_results_ready_p PARAMS ((rtx));
+static int ultra_fpmode_conflict_exists PARAMS ((enum machine_mode));
+static rtx *ultra_find_type PARAMS ((int, rtx *, int));
+static void ultra_build_types_avail PARAMS ((rtx *, int));
+static void ultra_flush_pipeline PARAMS ((void));
+static void ultra_rescan_pipeline_state PARAMS ((rtx *, 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));
+#ifdef OBJECT_FORMAT_ELF
+static void sparc_elf_asm_named_section PARAMS ((const char *, unsigned int));
#endif
+static void ultrasparc_sched_reorder PARAMS ((FILE *, int, rtx *, int));
+static int ultrasparc_variable_issue PARAMS ((rtx));
+static void ultrasparc_sched_init PARAMS ((void));
+
+static int sparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));
+static int sparc_issue_rate PARAMS ((void));
+static int sparc_variable_issue PARAMS ((FILE *, int, rtx, int));
+static void sparc_sched_init PARAMS ((FILE *, int, int));
+static int sparc_sched_reorder PARAMS ((FILE *, int, rtx *, int *, int));
/* Option handling. */
@@ -132,15 +188,7 @@ const char *sparc_cmodel_string;
/* Parsed value. */
enum cmodel sparc_cmodel;
-/* Record alignment options as passed by user. */
-const char *sparc_align_loops_string;
-const char *sparc_align_jumps_string;
-const char *sparc_align_funcs_string;
-
-/* Parsed values, as a power of two. */
-int sparc_align_loops;
-int sparc_align_jumps;
-int sparc_align_funcs;
+char sparc_hard_reg_printed[8];
struct sparc_cpu_select sparc_select[] =
{
@@ -153,7 +201,47 @@ struct sparc_cpu_select sparc_select[] =
/* CPU type. This is set from TARGET_CPU_DEFAULT and -m{cpu,tune}=xxx. */
enum processor_type sparc_cpu;
+
+/* Initialize the GCC target structure. */
+
+/* The sparc default is to use .half rather than .short for aligned
+ HI objects. Use .word instead of .long on non-ELF systems. */
+#undef TARGET_ASM_ALIGNED_HI_OP
+#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
+#ifndef OBJECT_FORMAT_ELF
+#undef TARGET_ASM_ALIGNED_SI_OP
+#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
+#endif
+#undef TARGET_ASM_UNALIGNED_HI_OP
+#define TARGET_ASM_UNALIGNED_HI_OP "\t.uahalf\t"
+#undef TARGET_ASM_UNALIGNED_SI_OP
+#define TARGET_ASM_UNALIGNED_SI_OP "\t.uaword\t"
+#undef TARGET_ASM_UNALIGNED_DI_OP
+#define TARGET_ASM_UNALIGNED_DI_OP "\t.uaxword\t"
+
+/* The target hook has to handle DI-mode values. */
+#undef TARGET_ASM_INTEGER
+#define TARGET_ASM_INTEGER sparc_assemble_integer
+
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE sparc_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE sparc_output_function_epilogue
+
+#undef TARGET_SCHED_ADJUST_COST
+#define TARGET_SCHED_ADJUST_COST sparc_adjust_cost
+#undef TARGET_SCHED_ISSUE_RATE
+#define TARGET_SCHED_ISSUE_RATE sparc_issue_rate
+#undef TARGET_SCHED_VARIABLE_ISSUE
+#define TARGET_SCHED_VARIABLE_ISSUE sparc_variable_issue
+#undef TARGET_SCHED_INIT
+#define TARGET_SCHED_INIT sparc_sched_init
+#undef TARGET_SCHED_REORDER
+#define TARGET_SCHED_REORDER sparc_sched_reorder
+
+struct gcc_target targetm = TARGET_INITIALIZER;
+
/* Validate and override various options, and do some machine dependent
initialization. */
@@ -161,9 +249,9 @@ void
sparc_override_options ()
{
static struct code_model {
- const char *name;
- int value;
- } cmodels[] = {
+ const char *const name;
+ const int value;
+ } const cmodels[] = {
{ "32", CM_32 },
{ "medlow", CM_MEDLOW },
{ "medmid", CM_MEDMID },
@@ -171,12 +259,12 @@ sparc_override_options ()
{ "embmedany", CM_EMBMEDANY },
{ 0, 0 }
};
- struct code_model *cmodel;
+ const struct code_model *cmodel;
/* Map TARGET_CPU_DEFAULT to value for -m{arch,tune}=. */
static struct cpu_default {
- int cpu;
- const char *name;
- } cpu_default[] = {
+ const int cpu;
+ const char *const name;
+ } const cpu_default[] = {
/* There must be one entry here for each TARGET_CPU value. */
{ TARGET_CPU_sparc, "cypress" },
{ TARGET_CPU_sparclet, "tsc701" },
@@ -189,14 +277,14 @@ sparc_override_options ()
{ TARGET_CPU_ultrasparc, "ultrasparc" },
{ 0, 0 }
};
- struct cpu_default *def;
+ const struct cpu_default *def;
/* Table of values for -m{cpu,tune}=. */
static struct cpu_table {
- const char *name;
- enum processor_type processor;
- int disable;
- int enable;
- } cpu_table[] = {
+ const char *const name;
+ const enum processor_type processor;
+ const int disable;
+ const int enable;
+ } const cpu_table[] = {
{ "v7", PROCESSOR_V7, MASK_ISA, 0 },
{ "cypress", PROCESSOR_CYPRESS, MASK_ISA, 0 },
{ "v8", PROCESSOR_V8, MASK_ISA, MASK_V8 },
@@ -208,37 +296,35 @@ sparc_override_options ()
{ "f930", PROCESSOR_F930, MASK_ISA|MASK_FPU, MASK_SPARCLITE },
{ "f934", PROCESSOR_F934, MASK_ISA, MASK_SPARCLITE|MASK_FPU },
{ "hypersparc", PROCESSOR_HYPERSPARC, MASK_ISA, MASK_V8|MASK_FPU },
- { "sparclite86x", PROCESSOR_SPARCLITE86X, MASK_ISA|MASK_FPU, MASK_V8 },
+ { "sparclite86x", PROCESSOR_SPARCLITE86X, MASK_ISA|MASK_FPU,
+ MASK_SPARCLITE },
{ "sparclet", PROCESSOR_SPARCLET, MASK_ISA, MASK_SPARCLET },
/* TEMIC sparclet */
{ "tsc701", PROCESSOR_TSC701, MASK_ISA, MASK_SPARCLET },
{ "v9", PROCESSOR_V9, MASK_ISA, MASK_V9 },
- /* TI ultrasparc */
- { "ultrasparc", PROCESSOR_ULTRASPARC, MASK_ISA, MASK_V9 },
+ /* TI ultrasparc I, II, IIi */
+ { "ultrasparc", PROCESSOR_ULTRASPARC, MASK_ISA, MASK_V9
+ /* Although insns using %y are deprecated, it is a clear win on current
+ ultrasparcs. */
+ |MASK_DEPRECATED_V8_INSNS},
{ 0, 0, 0, 0 }
};
- struct cpu_table *cpu;
- struct sparc_cpu_select *sel;
+ const struct cpu_table *cpu;
+ const struct sparc_cpu_select *sel;
int fpu;
#ifndef SPARC_BI_ARCH
/* Check for unsupported architecture size. */
if (! TARGET_64BIT != DEFAULT_ARCH32_P)
- {
- error ("%s is not supported by this configuration",
- DEFAULT_ARCH32_P ? "-m64" : "-m32");
- }
+ error ("%s is not supported by this configuration",
+ DEFAULT_ARCH32_P ? "-m64" : "-m32");
#endif
- /* At the moment we don't allow different pointer size and architecture */
- if (! TARGET_64BIT != ! TARGET_PTR64)
+ /* We force all 64bit archs to use 128 bit long double */
+ if (TARGET_64BIT && ! TARGET_LONG_DOUBLE_128)
{
- error ("-mptr%d not allowed on -m%d",
- TARGET_PTR64 ? 64 : 32, TARGET_64BIT ? 64 : 32);
- if (TARGET_64BIT)
- target_flags |= MASK_PTR64;
- else
- target_flags &= ~MASK_PTR64;
+ error ("-mlong-double-64 not allowed with -m64");
+ target_flags |= MASK_LONG_DOUBLE_128;
}
/* Code model selection. */
@@ -299,9 +385,26 @@ sparc_override_options ()
}
/* If -mfpu or -mno-fpu was explicitly used, don't override with
- the processor default. */
+ the processor default. Clear MASK_FPU_SET to avoid confusing
+ the reverse mapping from switch values to names. */
if (TARGET_FPU_SET)
- target_flags = (target_flags & ~MASK_FPU) | fpu;
+ {
+ target_flags = (target_flags & ~MASK_FPU) | fpu;
+ target_flags &= ~MASK_FPU_SET;
+ }
+
+ /* Don't allow -mvis if FPU is disabled. */
+ if (! TARGET_FPU)
+ target_flags &= ~MASK_VIS;
+
+ /* -mvis assumes UltraSPARC+, so we are sure v9 instructions
+ are available.
+ -m64 also implies v9. */
+ if (TARGET_VIS || TARGET_ARCH64)
+ {
+ target_flags |= MASK_V9;
+ target_flags &= ~(MASK_V8 | MASK_SPARCLET | MASK_SPARCLITE);
+ }
/* Use the deprecated v8 insns for sparc64 in 32 bit mode. */
if (TARGET_V9 && TARGET_ARCH32)
@@ -315,63 +418,29 @@ sparc_override_options ()
if (TARGET_ARCH32)
target_flags &= ~MASK_STACK_BIAS;
- /* Don't allow -mvis if FPU is disabled. */
- if (! TARGET_FPU)
- target_flags &= ~MASK_VIS;
-
- /* Validate -malign-loops= value, or provide default. */
- if (sparc_align_loops_string)
- {
- sparc_align_loops = exact_log2 (atoi (sparc_align_loops_string));
- if (sparc_align_loops < 2 || sparc_align_loops > 7)
- fatal ("-malign-loops=%s is not between 4 and 128 or is not a power of two",
- sparc_align_loops_string);
- }
- else
- {
- /* ??? This relies on ASM_OUTPUT_ALIGN to not emit the alignment if
- its 0. This sounds a bit kludgey. */
- sparc_align_loops = 0;
- }
-
- /* Validate -malign-jumps= value, or provide default. */
- if (sparc_align_jumps_string)
- {
- sparc_align_jumps = exact_log2 (atoi (sparc_align_jumps_string));
- if (sparc_align_jumps < 2 || sparc_align_loops > 7)
- fatal ("-malign-jumps=%s is not between 4 and 128 or is not a power of two",
- sparc_align_jumps_string);
- }
- else
- {
- /* ??? This relies on ASM_OUTPUT_ALIGN to not emit the alignment if
- its 0. This sounds a bit kludgey. */
- sparc_align_jumps = 0;
- }
-
- /* Validate -malign-functions= value, or provide default. */
- if (sparc_align_funcs_string)
- {
- sparc_align_funcs = exact_log2 (atoi (sparc_align_funcs_string));
- if (sparc_align_funcs < 2 || sparc_align_loops > 7)
- fatal ("-malign-functions=%s is not between 4 and 128 or is not a power of two",
- sparc_align_funcs_string);
- }
- else
- sparc_align_funcs = DEFAULT_SPARC_ALIGN_FUNCS;
+ /* Supply a default value for align_functions. */
+ if (align_functions == 0 && sparc_cpu == PROCESSOR_ULTRASPARC)
+ align_functions = 32;
/* Validate PCC_STRUCT_RETURN. */
if (flag_pcc_struct_return == DEFAULT_PCC_STRUCT_RETURN)
flag_pcc_struct_return = (TARGET_ARCH64 ? 0 : 1);
+ /* Only use .uaxword when compiling for a 64-bit target. */
+ if (!TARGET_ARCH64)
+ targetm.asm_out.unaligned_op.di = NULL;
+
/* Do various machine dependent initializations. */
sparc_init_modes ();
- if ((profile_flag || profile_block_flag)
- && sparc_cmodel != CM_MEDLOW)
+ if ((profile_flag)
+ && sparc_cmodel != CM_32 && sparc_cmodel != CM_MEDLOW)
{
error ("profiling does not support code models other than medlow");
}
+
+ /* Register global variables with the garbage collector. */
+ sparc_add_gc_roots ();
}
/* Miscellaneous utilities. */
@@ -391,8 +460,7 @@ v9_regcmp_p (code)
/* Operand constraints. */
/* Return non-zero only if OP is a register of mode MODE,
- or const0_rtx. Don't allow const0_rtx if TARGET_LIVE_G0 because
- %g0 may contain anything. */
+ or const0_rtx. */
int
reg_or_0_operand (op, mode)
@@ -401,17 +469,13 @@ reg_or_0_operand (op, mode)
{
if (register_operand (op, mode))
return 1;
- if (TARGET_LIVE_G0)
- return 0;
if (op == const0_rtx)
return 1;
if (GET_MODE (op) == VOIDmode && GET_CODE (op) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (op) == 0
&& CONST_DOUBLE_LOW (op) == 0)
return 1;
- if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
- && GET_CODE (op) == CONST_DOUBLE
- && fp_zero_operand (op))
+ if (fp_zero_operand (op, mode))
return 1;
return 0;
}
@@ -419,13 +483,92 @@ reg_or_0_operand (op, mode)
/* Nonzero if OP is a floating point value with value 0.0. */
int
-fp_zero_operand (op)
+fp_zero_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_MODE_CLASS (GET_MODE (op)) != MODE_FLOAT)
+ return 0;
+ return op == CONST0_RTX (mode);
+}
+
+/* Nonzero if OP is a floating point constant which can
+ be loaded into an integer register using a single
+ sethi instruction. */
+
+int
+fp_sethi_p (op)
rtx op;
{
- REAL_VALUE_TYPE r;
+ if (GET_CODE (op) == CONST_DOUBLE)
+ {
+ REAL_VALUE_TYPE r;
+ long i;
- REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- return (REAL_VALUES_EQUAL (r, dconst0) && ! REAL_VALUE_MINUS_ZERO (r));
+ REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+ if (REAL_VALUES_EQUAL (r, dconst0) &&
+ ! REAL_VALUE_MINUS_ZERO (r))
+ return 0;
+ REAL_VALUE_TO_TARGET_SINGLE (r, i);
+ if (SPARC_SETHI_P (i))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Nonzero if OP is a floating point constant which can
+ be loaded into an integer register using a single
+ mov instruction. */
+
+int
+fp_mov_p (op)
+ rtx op;
+{
+ if (GET_CODE (op) == CONST_DOUBLE)
+ {
+ REAL_VALUE_TYPE r;
+ long i;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+ if (REAL_VALUES_EQUAL (r, dconst0) &&
+ ! REAL_VALUE_MINUS_ZERO (r))
+ return 0;
+ REAL_VALUE_TO_TARGET_SINGLE (r, i);
+ if (SPARC_SIMM13_P (i))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Nonzero if OP is a floating point constant which can
+ be loaded into an integer register using a high/losum
+ instruction sequence. */
+
+int
+fp_high_losum_p (op)
+ rtx op;
+{
+ /* The constraints calling this should only be in
+ SFmode move insns, so any constant which cannot
+ be moved using a single insn will do. */
+ if (GET_CODE (op) == CONST_DOUBLE)
+ {
+ REAL_VALUE_TYPE r;
+ long i;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+ if (REAL_VALUES_EQUAL (r, dconst0) &&
+ ! REAL_VALUE_MINUS_ZERO (r))
+ return 0;
+ REAL_VALUE_TO_TARGET_SINGLE (r, i);
+ if (! SPARC_SETHI_P (i)
+ && ! SPARC_SIMM13_P (i))
+ return 1;
+ }
+
+ return 0;
}
/* Nonzero if OP is an integer register. */
@@ -526,6 +669,11 @@ symbolic_operand (op, mode)
register rtx op;
enum machine_mode mode;
{
+ enum machine_mode omode = GET_MODE (op);
+
+ if (omode != mode && omode != VOIDmode && mode != VOIDmode)
+ return 0;
+
switch (GET_CODE (op))
{
case SYMBOL_REF:
@@ -538,10 +686,6 @@ symbolic_operand (op, mode)
|| GET_CODE (XEXP (op, 0)) == LABEL_REF)
&& GET_CODE (XEXP (op, 1)) == CONST_INT);
- /* ??? This clause seems to be irrelevant. */
- case CONST_DOUBLE:
- return GET_MODE (op) == mode;
-
default:
return 0;
}
@@ -621,7 +765,7 @@ data_segment_operand (op, mode)
/* Assume canonical format of symbol + constant.
Fall through. */
case CONST :
- return data_segment_operand (XEXP (op, 0));
+ return data_segment_operand (XEXP (op, 0), VOIDmode);
default :
return 0;
}
@@ -645,7 +789,7 @@ text_segment_operand (op, mode)
/* Assume canonical format of symbol + constant.
Fall through. */
case CONST :
- return text_segment_operand (XEXP (op, 0));
+ return text_segment_operand (XEXP (op, 0), VOIDmode);
default :
return 0;
}
@@ -793,7 +937,7 @@ cc_arithopn (op, mode)
enum machine_mode mode ATTRIBUTE_UNUSED;
{
/* XOR is not here because combine canonicalizes (xor (not ...) ...)
- and (xor ... (not ...)) to (not (xor ...)). */
+ and (xor ... (not ...)) to (not (xor ...)). */
return (GET_CODE (op) == AND
|| GET_CODE (op) == IOR);
}
@@ -1005,7 +1149,7 @@ arith10_double_operand (op, mode)
&& (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x200) < 0x400));
}
-/* Return truth value of whether OP is a integer which fits the
+/* Return truth value of whether OP is an integer which fits the
range constraining immediate operands in most three-address insns,
which have a 13 bit immediate field. */
@@ -1042,7 +1186,7 @@ uns_small_int (op, mode)
return (GET_CODE (op) == CONST_INT
&& ((INTVAL (op) >= 0 && INTVAL (op) < 0x1000)
|| (INTVAL (op) >= 0xFFFFF000
- && INTVAL (op) < 0x100000000)));
+ && INTVAL (op) <= 0xFFFFFFFF)));
#else
return ((GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 0x1000)
|| (GET_CODE (op) == CONST_DOUBLE
@@ -1068,16 +1212,6 @@ clobbered_register (op, mode)
return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]);
}
-/* Return 1 if OP is const0_rtx, used for TARGET_LIVE_G0 insns. */
-
-int
-zero_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- return op == const0_rtx;
-}
-
/* Return 1 if OP is a valid operand for the source of a move insn. */
int
@@ -1100,7 +1234,9 @@ input_operand (op, mode)
&& ((SPARC_SETHI_P (INTVAL (op))
&& (! TARGET_ARCH64
|| (INTVAL (op) >= 0)
- || mode == SImode))
+ || mode == SImode
+ || mode == HImode
+ || mode == QImode))
|| SPARC_SIMM13_P (INTVAL (op))
|| (mode == DImode
&& ! TARGET_ARCH64)))
@@ -1116,7 +1252,8 @@ input_operand (op, mode)
(SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))
&& (((CONST_DOUBLE_LOW (op) & 0x80000000) == 0
&& CONST_DOUBLE_HIGH (op) == 0)
- || (CONST_DOUBLE_HIGH (op) == -1)))
+ || (CONST_DOUBLE_HIGH (op) == -1
+ && CONST_DOUBLE_LOW (op) & 0x80000000) != 0))
#endif
))))
return 1;
@@ -1131,6 +1268,10 @@ input_operand (op, mode)
if (register_operand (op, mode))
return 1;
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT
+ && GET_CODE (op) == CONST_DOUBLE)
+ return 1;
+
/* If this is a SUBREG, look inside so that we handle
paradoxical ones. */
if (GET_CODE (op) == SUBREG)
@@ -1193,42 +1334,32 @@ sparc_emit_set_const32 (op0, op1)
if (TARGET_ARCH64
&& HOST_BITS_PER_WIDE_INT != 64
&& (INTVAL (op1) & 0x80000000) != 0)
- {
- emit_insn (gen_rtx_SET (VOIDmode,
- temp,
- gen_rtx_CONST_DOUBLE (VOIDmode, const0_rtx,
- INTVAL (op1) & 0xfffffc00, 0)));
- }
+ emit_insn (gen_rtx_SET
+ (VOIDmode, temp,
+ gen_rtx_CONST_DOUBLE (VOIDmode, INTVAL (op1) & 0xfffffc00,
+ 0)));
else
- {
- emit_insn (gen_rtx_SET (VOIDmode,
- temp,
- GEN_INT (INTVAL (op1) & 0xfffffc00)));
- }
+ emit_insn (gen_rtx_SET (VOIDmode, temp,
+ GEN_INT (INTVAL (op1) & 0xfffffc00)));
+
emit_insn (gen_rtx_SET (VOIDmode,
op0,
- gen_rtx_IOR (mode,
- temp,
+ gen_rtx_IOR (mode, temp,
GEN_INT (INTVAL (op1) & 0x3ff))));
}
else
{
/* A symbol, emit in the traditional way. */
+ emit_insn (gen_rtx_SET (VOIDmode, temp,
+ gen_rtx_HIGH (mode, op1)));
emit_insn (gen_rtx_SET (VOIDmode,
- temp,
- gen_rtx_HIGH (mode,
- op1)));
- emit_insn (gen_rtx_SET (VOIDmode,
- op0,
- gen_rtx_LO_SUM (mode,
- temp,
- op1)));
+ op0, gen_rtx_LO_SUM (mode, temp, op1)));
}
}
-/* Sparc-v9 code-model support. */
+/* Sparc-v9 code-model support. */
void
sparc_emit_set_symbolic_const64 (op0, op1, temp1)
rtx op0;
@@ -1289,10 +1420,10 @@ sparc_emit_set_symbolic_const64 (op0, op1, temp1)
or %temp4, %temp5, %reg */
/* Getting this right wrt. reloading is really tricky.
- We _MUST_ have a seperate temporary at this point,
+ We _MUST_ have a separate temporary at this point,
if we don't barf immediately instead of generating
incorrect code. */
- if (temp1 == op0)
+ if (rtx_equal_p (temp1, op0))
abort ();
emit_insn (gen_sethh (op0, op1));
@@ -1332,7 +1463,7 @@ sparc_emit_set_symbolic_const64 (op0, op1, temp1)
else
{
/* Getting this right wrt. reloading is really tricky.
- We _MUST_ have a seperate temporary at this point,
+ We _MUST_ have a separate temporary at this point,
so we barf immediately instead of generating
incorrect code. */
if (temp1 == op0)
@@ -1357,21 +1488,19 @@ 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 PROTO ((rtx, HOST_WIDE_INT));
-static rtx gen_safe_SET64 PROTO ((rtx, HOST_WIDE_INT));
-static rtx gen_safe_OR64 PROTO ((rtx, HOST_WIDE_INT));
-static rtx gen_safe_XOR64 PROTO ((rtx, HOST_WIDE_INT));
+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));
#if HOST_BITS_PER_WIDE_INT == 64
#define GEN_HIGHINT64(__x) GEN_INT ((__x) & 0xfffffc00)
#define GEN_INT64(__x) GEN_INT (__x)
#else
#define GEN_HIGHINT64(__x) \
- gen_rtx_CONST_DOUBLE (VOIDmode, const0_rtx, \
- (__x) & 0xfffffc00, 0)
+ gen_rtx_CONST_DOUBLE (VOIDmode, (__x) & 0xfffffc00, 0)
#define GEN_INT64(__x) \
- gen_rtx_CONST_DOUBLE (VOIDmode, const0_rtx, \
- (__x) & 0xffffffff, \
+ gen_rtx_CONST_DOUBLE (VOIDmode, (__x) & 0xffffffff, \
((__x) & 0x80000000 \
? 0xffffffff : 0))
#endif
@@ -1422,7 +1551,7 @@ gen_safe_XOR64 (src, val)
opportunities. */
static void sparc_emit_set_const64_quick1
- PROTO((rtx, rtx, unsigned HOST_WIDE_INT, int));
+ PARAMS ((rtx, rtx, unsigned HOST_WIDE_INT, int));
static void
sparc_emit_set_const64_quick1 (op0, temp, low_bits, is_neg)
@@ -1464,7 +1593,7 @@ sparc_emit_set_const64_quick1 (op0, temp, low_bits, is_neg)
}
static void sparc_emit_set_const64_quick2
- PROTO((rtx, rtx, unsigned HOST_WIDE_INT,
+ PARAMS ((rtx, rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT, int));
static void
@@ -1492,7 +1621,7 @@ sparc_emit_set_const64_quick2 (op0, temp, high_bits, low_immediate, shift_count)
temp2 = temp;
}
- /* Now shift it up into place. */
+ /* Now shift it up into place. */
emit_insn (gen_rtx_SET (VOIDmode, op0,
gen_rtx_ASHIFT (DImode, temp2,
GEN_INT (shift_count))));
@@ -1505,7 +1634,7 @@ sparc_emit_set_const64_quick2 (op0, temp, high_bits, low_immediate, shift_count)
}
static void sparc_emit_set_const64_longway
- PROTO((rtx, rtx, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT));
+ PARAMS ((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. */
@@ -1607,13 +1736,13 @@ sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits)
if (low3 != const0_rtx)
emit_insn (gen_rtx_SET (VOIDmode, op0,
gen_rtx_IOR (DImode, op0, low3)));
- /* phew... */
+ /* phew... */
}
}
-/* Analyze a 64-bit constant for certain properties. */
+/* Analyze a 64-bit constant for certain properties. */
static void analyze_64bit_constant
- PROTO((unsigned HOST_WIDE_INT,
+ PARAMS ((unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
int *, int *, int *));
@@ -1682,7 +1811,7 @@ analyze_64bit_constant (high_bits, low_bits, hbsp, lbsp, abbasp)
}
static int const64_is_2insns
- PROTO((unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT));
+ PARAMS ((unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT));
static int
const64_is_2insns (high_bits, low_bits)
@@ -1710,7 +1839,7 @@ const64_is_2insns (high_bits, low_bits)
}
static unsigned HOST_WIDE_INT create_simple_focus_bits
- PROTO((unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
+ PARAMS ((unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
int, int));
static unsigned HOST_WIDE_INT
@@ -1750,12 +1879,17 @@ sparc_emit_set_const64 (op0, op1)
rtx temp;
/* Sanity check that we know what we are working with. */
- if (! TARGET_ARCH64
- || GET_CODE (op0) != REG
- || (REGNO (op0) >= SPARC_FIRST_FP_REG
- && REGNO (op0) <= SPARC_LAST_V9_FP_REG))
+ if (! TARGET_ARCH64)
abort ();
+ if (GET_CODE (op0) != SUBREG)
+ {
+ if (GET_CODE (op0) != REG
+ || (REGNO (op0) >= SPARC_FIRST_FP_REG
+ && REGNO (op0) <= SPARC_LAST_V9_FP_REG))
+ abort ();
+ }
+
if (reload_in_progress || reload_completed)
temp = op0;
else
@@ -1937,7 +2071,7 @@ sparc_emit_set_const64 (op0, op1)
negated_const = GEN_INT (((~low_bits) & 0xfffffc00) |
(((HOST_WIDE_INT)((~high_bits) & 0xffffffff))<<32));
#else
- negated_const = gen_rtx_CONST_DOUBLE (DImode, const0_rtx,
+ negated_const = gen_rtx_CONST_DOUBLE (DImode,
(~low_bits) & 0xfffffc00,
(~high_bits) & 0xffffffff);
#endif
@@ -2000,7 +2134,7 @@ sparc_emit_set_const64 (op0, op1)
return;
}
- /* The easiest way when all else fails, is full decomposition. */
+ /* The easiest way when all else fails, is full decomposition. */
#if 0
printf ("sparc_emit_set_const64: Hard constant [%08lx%08lx] neg[%08lx%08lx]\n",
high_bits, low_bits, ~high_bits, ~low_bits);
@@ -2008,6 +2142,61 @@ sparc_emit_set_const64 (op0, op1)
sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits);
}
+/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
+ return the mode to be used for the comparison. For floating-point,
+ CCFP[E]mode is used. CC_NOOVmode should be used when the first operand
+ is a PLUS, MINUS, NEG, or ASHIFT. CCmode should be used when no special
+ processing is needed. */
+
+enum machine_mode
+select_cc_mode (op, x, y)
+ enum rtx_code op;
+ rtx x;
+ rtx y ATTRIBUTE_UNUSED;
+{
+ if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+ {
+ switch (op)
+ {
+ case EQ:
+ case NE:
+ case UNORDERED:
+ case ORDERED:
+ case UNLT:
+ case UNLE:
+ case UNGT:
+ case UNGE:
+ case UNEQ:
+ case LTGT:
+ return CCFPmode;
+
+ case LT:
+ case LE:
+ case GT:
+ case GE:
+ return CCFPEmode;
+
+ default:
+ abort ();
+ }
+ }
+ else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
+ || GET_CODE (x) == NEG || GET_CODE (x) == ASHIFT)
+ {
+ if (TARGET_ARCH64 && GET_MODE (x) == DImode)
+ return CCX_NOOVmode;
+ else
+ return CC_NOOVmode;
+ }
+ else
+ {
+ if (TARGET_ARCH64 && GET_MODE (x) == DImode)
+ return CCXmode;
+ else
+ return CCmode;
+ }
+}
+
/* X and Y are two things to compare using CODE. Emit the compare insn and
return the rtx for the cc reg in the proper mode. */
@@ -2200,6 +2389,22 @@ emit_v9_brxx_insn (code, op0, label)
gen_rtx_LABEL_REF (VOIDmode, label),
pc_rtx)));
}
+
+/* Generate a DFmode part of a hard TFmode register.
+ REG is the TFmode hard register, LOW is 1 for the
+ low 64bit of the register and 0 otherwise.
+ */
+rtx
+gen_df_reg (reg, low)
+ rtx reg;
+ int low;
+{
+ int regno = REGNO (reg);
+
+ if ((WORDS_BIG_ENDIAN == 0) ^ (low != 0))
+ regno += (TARGET_ARCH64 && regno < 32) ? 1 : 2;
+ return gen_rtx_REG (DFmode, regno);
+}
/* Return nonzero if a return peephole merging return with
setting of output register is ok. */
@@ -2228,10 +2433,14 @@ eligible_for_epilogue_delay (trial, slot)
if (get_attr_length (trial) != 1)
return 0;
- /* If %g0 is live, there are lots of things we can't handle.
- Rather than trying to find them all now, let's punt and only
- optimize things as necessary. */
- if (TARGET_LIVE_G0)
+ /* If there are any call-saved registers, we should scan TRIAL if it
+ does not reference them. For now just make it easy. */
+ if (num_gfregs)
+ return 0;
+
+ /* If the function uses __builtin_eh_return, the eh_return machinery
+ occupies the delay slot. */
+ if (current_function_calls_eh_return)
return 0;
/* In the case of a true leaf function, anything can go into the delay slot.
@@ -2245,36 +2454,43 @@ eligible_for_epilogue_delay (trial, slot)
return 0;
}
- /* If only trivial `restore' insns work, nothing can go in the
- delay slot. */
- else if (TARGET_BROKEN_SAVERESTORE)
- return 0;
-
pat = PATTERN (trial);
/* Otherwise, only operations which can be done in tandem with
- a `restore' insn can go into the delay slot. */
+ a `restore' or `return' insn can go into the delay slot. */
if (GET_CODE (SET_DEST (pat)) != REG
- || REGNO (SET_DEST (pat)) >= 32
|| REGNO (SET_DEST (pat)) < 24)
return 0;
+ /* If this instruction sets up floating point register and we have a return
+ instruction, it can probably go in. But restore will not work
+ with FP_REGS. */
+ if (REGNO (SET_DEST (pat)) >= 32)
+ {
+ if (TARGET_V9 && ! epilogue_renumber (&pat, 1)
+ && (get_attr_in_uncond_branch_delay (trial) == IN_BRANCH_DELAY_TRUE))
+ return 1;
+ return 0;
+ }
+
/* The set of insns matched here must agree precisely with the set of
patterns paired with a RETURN in sparc.md. */
src = SET_SRC (pat);
/* This matches "*return_[qhs]i" or even "*return_di" on TARGET_ARCH64. */
- if (arith_operand (src, GET_MODE (src)))
+ if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
+ && arith_operand (src, GET_MODE (src)))
{
if (TARGET_ARCH64)
return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
else
return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
}
-
+
/* This matches "*return_di". */
- else if (arith_double_operand (src, GET_MODE (src)))
+ else if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
+ && arith_double_operand (src, GET_MODE (src)))
return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
/* This matches "*return_sf_no_fpu". */
@@ -2282,6 +2498,12 @@ eligible_for_epilogue_delay (trial, slot)
&& register_operand (src, SFmode))
return 1;
+ /* If we have return instruction, anything that does not use
+ local or output registers and can go into a delay slot wins. */
+ else if (TARGET_V9 && ! epilogue_renumber (&pat, 1)
+ && (get_attr_in_uncond_branch_delay (trial) == IN_BRANCH_DELAY_TRUE))
+ return 1;
+
/* This matches "*return_addsi". */
else if (GET_CODE (src) == PLUS
&& arith_operand (XEXP (src, 0), SImode)
@@ -2298,6 +2520,119 @@ eligible_for_epilogue_delay (trial, slot)
|| register_operand (XEXP (src, 1), DImode)))
return 1;
+ /* This can match "*return_losum_[sd]i".
+ Catch only some cases, so that return_losum* don't have
+ to be too big. */
+ else if (GET_CODE (src) == LO_SUM
+ && ! TARGET_CM_MEDMID
+ && ((register_operand (XEXP (src, 0), SImode)
+ && immediate_operand (XEXP (src, 1), SImode))
+ || (TARGET_ARCH64
+ && register_operand (XEXP (src, 0), DImode)
+ && immediate_operand (XEXP (src, 1), DImode))))
+ return 1;
+
+ /* sll{,x} reg,1,reg2 is add reg,reg,reg2 as well. */
+ else if (GET_CODE (src) == ASHIFT
+ && (register_operand (XEXP (src, 0), SImode)
+ || register_operand (XEXP (src, 0), DImode))
+ && XEXP (src, 1) == const1_rtx)
+ return 1;
+
+ return 0;
+}
+
+/* Return nonzero if TRIAL can go into the sibling call
+ delay slot. */
+
+int
+eligible_for_sibcall_delay (trial)
+ rtx trial;
+{
+ rtx pat, src;
+
+ if (GET_CODE (trial) != INSN || GET_CODE (PATTERN (trial)) != SET)
+ return 0;
+
+ if (get_attr_length (trial) != 1)
+ return 0;
+
+ pat = PATTERN (trial);
+
+ if (current_function_uses_only_leaf_regs)
+ {
+ /* If the tail call is done using the call instruction,
+ we have to restore %o7 in the delay slot. */
+ if ((TARGET_ARCH64 && ! TARGET_CM_MEDLOW) || flag_pic)
+ return 0;
+
+ /* %g1 is used to build the function address */
+ if (reg_mentioned_p (gen_rtx_REG (Pmode, 1), pat))
+ return 0;
+
+ return 1;
+ }
+
+ /* Otherwise, only operations which can be done in tandem with
+ a `restore' insn can go into the delay slot. */
+ if (GET_CODE (SET_DEST (pat)) != REG
+ || REGNO (SET_DEST (pat)) < 24
+ || REGNO (SET_DEST (pat)) >= 32)
+ return 0;
+
+ /* If it mentions %o7, it can't go in, because sibcall will clobber it
+ in most cases. */
+ if (reg_mentioned_p (gen_rtx_REG (Pmode, 15), pat))
+ return 0;
+
+ src = SET_SRC (pat);
+
+ if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
+ && arith_operand (src, GET_MODE (src)))
+ {
+ if (TARGET_ARCH64)
+ return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
+ else
+ return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
+ }
+
+ else if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
+ && arith_double_operand (src, GET_MODE (src)))
+ return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
+
+ else if (! TARGET_FPU && restore_operand (SET_DEST (pat), SFmode)
+ && register_operand (src, SFmode))
+ return 1;
+
+ else if (GET_CODE (src) == PLUS
+ && arith_operand (XEXP (src, 0), SImode)
+ && arith_operand (XEXP (src, 1), SImode)
+ && (register_operand (XEXP (src, 0), SImode)
+ || register_operand (XEXP (src, 1), SImode)))
+ return 1;
+
+ else if (GET_CODE (src) == PLUS
+ && arith_double_operand (XEXP (src, 0), DImode)
+ && arith_double_operand (XEXP (src, 1), DImode)
+ && (register_operand (XEXP (src, 0), DImode)
+ || register_operand (XEXP (src, 1), DImode)))
+ return 1;
+
+ else if (GET_CODE (src) == LO_SUM
+ && ! TARGET_CM_MEDMID
+ && ((register_operand (XEXP (src, 0), SImode)
+ && immediate_operand (XEXP (src, 1), SImode))
+ || (TARGET_ARCH64
+ && register_operand (XEXP (src, 0), DImode)
+ && immediate_operand (XEXP (src, 1), DImode))))
+ return 1;
+
+ else if (GET_CODE (src) == ASHIFT
+ && (register_operand (XEXP (src, 0), SImode)
+ || register_operand (XEXP (src, 0), DImode))
+ && XEXP (src, 1) == const1_rtx)
+ return 1;
+
return 0;
}
@@ -2351,10 +2686,12 @@ int
short_branch (uid1, uid2)
int uid1, uid2;
{
- unsigned int delta = insn_addresses[uid1] - insn_addresses[uid2];
- if (delta + 1024 < 2048)
+ int delta = INSN_ADDRESSES (uid1) - INSN_ADDRESSES (uid2);
+
+ /* Leave a few words of "slop". */
+ if (delta >= -1023 && delta <= 1022)
return 1;
- /* warning ("long branch, distance %d", delta); */
+
return 0;
}
@@ -2409,12 +2746,12 @@ check_pic (i)
switch (flag_pic)
{
case 1:
- if (GET_CODE (recog_operand[i]) == SYMBOL_REF
- || (GET_CODE (recog_operand[i]) == CONST
- && ! (GET_CODE (XEXP (recog_operand[i], 0)) == MINUS
- && (XEXP (XEXP (recog_operand[i], 0), 0)
+ if (GET_CODE (recog_data.operand[i]) == SYMBOL_REF
+ || (GET_CODE (recog_data.operand[i]) == CONST
+ && ! (GET_CODE (XEXP (recog_data.operand[i], 0)) == MINUS
+ && (XEXP (XEXP (recog_data.operand[i], 0), 0)
== global_offset_table)
- && (GET_CODE (XEXP (XEXP (recog_operand[i], 0), 1))
+ && (GET_CODE (XEXP (XEXP (recog_data.operand[i], 0), 1))
== CONST))))
abort ();
case 2:
@@ -2430,9 +2767,6 @@ int
pic_address_needs_scratch (x)
rtx x;
{
- if (GET_CODE (x) == LABEL_REF)
- return 1;
-
/* 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
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
@@ -2495,8 +2829,8 @@ legitimize_pic_address (orig, mode, reg)
address = orig;
pic_ref = gen_rtx_MEM (Pmode,
- gen_rtx_PLUS (Pmode,
- pic_offset_table_rtx, address));
+ gen_rtx_PLUS (Pmode,
+ pic_offset_table_rtx, address));
current_function_uses_pic_offset_table = 1;
RTX_UNCHANGING_P (pic_ref) = 1;
insn = emit_move_insn (reg, pic_ref);
@@ -2534,7 +2868,7 @@ legitimize_pic_address (orig, mode, reg)
if (GET_CODE (offset) == CONST_INT)
{
if (SMALL_INT (offset))
- return plus_constant_for_output (base, INTVAL (offset));
+ return plus_constant (base, INTVAL (offset));
else if (! reload_in_progress && ! reload_completed)
offset = force_reg (Pmode, offset);
else
@@ -2552,38 +2886,18 @@ legitimize_pic_address (orig, mode, reg)
return orig;
}
-/* Return the RTX for insns to set the PIC register. */
-
-static rtx
-pic_setup_code ()
-{
- rtx seq;
-
- start_sequence ();
- emit_insn (gen_get_pc (pic_offset_table_rtx, global_offset_table,
- get_pc_symbol));
- seq = gen_sequence ();
- end_sequence ();
-
- return seq;
-}
-
-/* Emit special PIC prologues and epilogues. */
+/* Emit special PIC prologues. */
void
-finalize_pic ()
+load_pic_register ()
{
/* Labels to get the PC in the prologue of this function. */
int orig_flag_pic = flag_pic;
- rtx insn;
-
- if (current_function_uses_pic_offset_table == 0)
- return;
if (! flag_pic)
abort ();
- /* If we havn't emitted the special get_pc helper function, do so now. */
+ /* If we haven't emitted the special get_pc helper function, do so now. */
if (get_pc_symbol_name[0] == 0)
{
int align;
@@ -2595,7 +2909,7 @@ finalize_pic ()
if (align > 0)
ASM_OUTPUT_ALIGN (asm_out_file, align);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LGETPC", 0);
- fputs ("\tretl\n\tadd %o7,%l7,%l7\n", asm_out_file);
+ fputs ("\tretl\n\tadd\t%o7, %l7, %l7\n", asm_out_file);
}
/* Initialize every time through, since we can't easily
@@ -2604,16 +2918,8 @@ finalize_pic ()
get_pc_symbol = gen_rtx_SYMBOL_REF (Pmode, get_pc_symbol_name);
flag_pic = 0;
- emit_insn_after (pic_setup_code (), get_insns ());
-
- /* Insert the code in each nonlocal goto receiver.
- If you make changes here or to the nonlocal_goto_receiver
- pattern, make sure the unspec_volatile numbers still
- match. */
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
- && XINT (PATTERN (insn), 1) == 5)
- emit_insn_after (pic_setup_code (), insn);
+ emit_insn (gen_get_pc (pic_offset_table_rtx, global_offset_table,
+ get_pc_symbol));
flag_pic = orig_flag_pic;
@@ -2671,11 +2977,13 @@ mem_min_alignment (mem, desired)
{
/* Check if the compiler has recorded some information
about the alignment of the base REG. If reload has
- completed, we already matched with proper alignments. */
- if (((regno_pointer_align != NULL
- && REGNO_POINTER_ALIGN (regno) >= desired)
- || reload_completed)
- && ((INTVAL (offset) & (desired - 1)) == 0))
+ completed, we already matched with proper alignments.
+ If not running global_alloc, reload might give us
+ unaligned pointer to local stack though. */
+ if (((cfun != 0
+ && REGNO_POINTER_ALIGN (regno) >= desired * BITS_PER_UNIT)
+ || (optimize && reload_completed))
+ && (INTVAL (offset) & (desired - 1)) == 0)
return 1;
}
else
@@ -2723,6 +3031,9 @@ enum sparc_mode_class {
/* Modes for quad-word and smaller quantities. */
#define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
+/* Modes for 8-word and smaller quantities. */
+#define O_MODES (T_MODES | (1 << (int) O_MODE) | (1 << (int) OF_MODE))
+
/* Modes for single-float quantities. We must allow any single word or
smaller quantity. This is because the fix/float conversion instructions
take integer inputs/outputs from the float registers. */
@@ -2731,13 +3042,8 @@ enum sparc_mode_class {
/* Modes for double-float and smaller quantities. */
#define DF_MODES (S_MODES | D_MODES)
-#define DF_MODES64 DF_MODES
-
/* Modes for double-float only quantities. */
-#define DF_ONLY_MODES ((1 << (int) DF_MODE) | (1 << (int) D_MODE))
-
-/* Modes for double-float and larger quantities. */
-#define DF_UP_MODES (DF_ONLY_MODES | TF_ONLY_MODES)
+#define DF_MODES_NO_S ((1 << (int) D_MODE) | (1 << (int) DF_MODE))
/* Modes for quad-float only quantities. */
#define TF_ONLY_MODES (1 << (int) TF_MODE)
@@ -2745,7 +3051,16 @@ enum sparc_mode_class {
/* Modes for quad-float and smaller quantities. */
#define TF_MODES (DF_MODES | TF_ONLY_MODES)
-#define TF_MODES64 (DF_MODES64 | TF_ONLY_MODES)
+/* Modes for quad-float and double-float quantities. */
+#define TF_MODES_NO_S (DF_MODES_NO_S | TF_ONLY_MODES)
+
+/* Modes for quad-float pair only quantities. */
+#define OF_ONLY_MODES (1 << (int) OF_MODE)
+
+/* Modes for quad-float pairs and smaller quantities. */
+#define OF_MODES (TF_MODES | OF_ONLY_MODES)
+
+#define OF_MODES_NO_S (TF_MODES_NO_S | OF_ONLY_MODES)
/* Modes for condition codes. */
#define CC_MODES (1 << (int) CC_MODE)
@@ -2758,25 +3073,25 @@ enum sparc_mode_class {
they cross fixed registers). */
/* This points to either the 32 bit or the 64 bit version. */
-int *hard_regno_mode_classes;
+const int *hard_regno_mode_classes;
-static int hard_32bit_mode_classes[] = {
+static const int hard_32bit_mode_classes[] = {
S_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
T_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
- TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
- TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
- TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
- TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
+ OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
+ OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
+ OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
+ OF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
/* FP regs f32 to f63. Only the even numbered registers actually exist,
and none can hold SFmode/SImode values. */
- DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0,
- DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0,
- DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0,
- DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0,
+ OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
+ OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
+ OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
+ OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, TF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
/* %fcc[0123] */
CCFP_MODES, CCFP_MODES, CCFP_MODES, CCFP_MODES,
@@ -2785,23 +3100,23 @@ static int hard_32bit_mode_classes[] = {
CC_MODES
};
-static int hard_64bit_mode_classes[] = {
+static const int hard_64bit_mode_classes[] = {
D_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
+ O_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
- T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
- T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
+ O_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
- TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, TF_MODES64, SF_MODES, DF_MODES64, SF_MODES,
- TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, TF_MODES64, SF_MODES, DF_MODES64, SF_MODES,
- TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, TF_MODES64, SF_MODES, DF_MODES64, SF_MODES,
- TF_MODES64, SF_MODES, DF_MODES64, SF_MODES, TF_MODES64, SF_MODES, DF_MODES64, SF_MODES,
+ OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
+ OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
+ OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
+ OF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
/* FP regs f32 to f63. Only the even numbered registers actually exist,
and none can hold SFmode/SImode values. */
- DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0,
- DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0,
- DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0,
- DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0,
+ OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
+ OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
+ OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
+ OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, TF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
/* %fcc[0123] */
CCFP_MODES, CCFP_MODES, CCFP_MODES, CCFP_MODES,
@@ -2995,11 +3310,11 @@ restore_regs (file, low, high, base, offset, n_regs)
base, offset + 4 * n_regs, reg_names[i]),
n_regs += 2;
else
- fprintf (file, "\tld\t[%s+%d],%s\n",
+ fprintf (file, "\tld\t[%s+%d], %s\n",
base, offset + 4 * n_regs, reg_names[i]),
n_regs += 2;
else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
- fprintf (file, "\tld\t[%s+%d],%s\n",
+ fprintf (file, "\tld\t[%s+%d], %s\n",
base, offset + 4 * n_regs + 4, reg_names[i+1]),
n_regs += 2;
}
@@ -3007,12 +3322,6 @@ restore_regs (file, low, high, base, offset, n_regs)
return n_regs;
}
-/* Static variables we want to share between prologue and epilogue. */
-
-/* Number of live general or floating point registers needed to be saved
- (as 4-byte quantities). This is only done if TARGET_EPILOGUE. */
-static int num_gfregs;
-
/* Compute the frame size required by the function. This function is called
during the reload pass and also by output_function_prologue(). */
@@ -3108,14 +3417,70 @@ build_big_number (file, num, reg)
}
}
+/* Output any necessary .register pseudo-ops. */
+void
+sparc_output_scratch_registers (file)
+ FILE *file ATTRIBUTE_UNUSED;
+{
+#ifdef HAVE_AS_REGISTER_PSEUDO_OP
+ int i;
+
+ if (TARGET_ARCH32)
+ return;
+
+ /* Check if %g[2367] were used without
+ .register being printed for them already. */
+ for (i = 2; i < 8; i++)
+ {
+ if (regs_ever_live [i]
+ && ! sparc_hard_reg_printed [i])
+ {
+ sparc_hard_reg_printed [i] = 1;
+ fprintf (file, "\t.register\t%%g%d, #scratch\n", i);
+ }
+ if (i == 3) i = 5;
+ }
+#endif
+}
+
+/* This function generates the assembly code for function entry.
+ FILE is a stdio stream to output the code to.
+ SIZE is an int: how many units of temporary storage to allocate.
+ Refer to the array `regs_ever_live' to determine which registers
+ to save; `regs_ever_live[I]' is nonzero if register number I
+ is ever used in the function. This macro is responsible for
+ knowing which registers should not be saved even if used. */
+
+/* On SPARC, move-double insns between fpu and cpu need an 8-byte block
+ of memory. If any fpu reg is used in the function, we allocate
+ such a block here, at the bottom of the frame, just in case it's needed.
+
+ If this function is a leaf procedure, then we may choose not
+ to do a "save" insn. The decision about whether or not
+ to do this is made in regclass.c. */
+
+static void
+sparc_output_function_prologue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size;
+{
+ if (TARGET_FLAT)
+ sparc_flat_function_prologue (file, size);
+ else
+ sparc_nonflat_function_prologue (file, size,
+ current_function_uses_only_leaf_regs);
+}
+
/* Output code for the function prologue. */
-void
-output_function_prologue (file, size, leaf_function)
+static void
+sparc_nonflat_function_prologue (file, size, leaf_function)
FILE *file;
- int size;
+ HOST_WIDE_INT size;
int leaf_function;
{
+ sparc_output_scratch_registers (file);
+
/* Need to use actual_fsize, since we are also allocating
space for our callee (and our own register save area). */
actual_fsize = compute_frame_size (size, leaf_function);
@@ -3136,7 +3501,7 @@ output_function_prologue (file, size, leaf_function)
if (actual_fsize == 0)
/* do nothing. */ ;
- else if (! leaf_function && ! TARGET_BROKEN_SAVERESTORE)
+ else if (! leaf_function)
{
if (actual_fsize <= 4096)
fprintf (file, "\tsave\t%%sp, -%d, %%sp\n", actual_fsize);
@@ -3151,26 +3516,6 @@ output_function_prologue (file, size, leaf_function)
fprintf (file, "\tsave\t%%sp, %%g1, %%sp\n");
}
}
- else if (! leaf_function && TARGET_BROKEN_SAVERESTORE)
- {
- /* We assume the environment will properly handle or otherwise avoid
- trouble associated with an interrupt occurring after the `save' or
- trap occurring during it. */
- fprintf (file, "\tsave\n");
-
- if (actual_fsize <= 4096)
- fprintf (file, "\tadd\t%%fp, -%d, %%sp\n", actual_fsize);
- else if (actual_fsize <= 8192)
- {
- fprintf (file, "\tadd\t%%fp, -4096, %%sp\n");
- fprintf (file, "\tadd\t%%fp, -%d, %%sp\n", actual_fsize - 4096);
- }
- else
- {
- build_big_number (file, -actual_fsize, "%g1");
- fprintf (file, "\tadd\t%%fp, %%g1, %%sp\n");
- }
- }
else /* leaf function */
{
if (actual_fsize <= 4096)
@@ -3259,12 +3604,66 @@ output_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;
+{
+ int offset, n_regs;
+ const char *base;
+
+ offset = -apparent_fsize + frame_base_offset;
+ if (offset < -4096 || offset + num_gfregs * 4 > 4096 - 8 /*double*/)
+ {
+ build_big_number (file, offset, "%g1");
+ fprintf (file, "\tadd\t%s, %%g1, %%g1\n", frame_base_name);
+ base = "%g1";
+ offset = 0;
+ }
+ else
+ {
+ base = frame_base_name;
+ }
+
+ n_regs = 0;
+ if (TARGET_EPILOGUE && ! leaf_function)
+ /* ??? Originally saved regs 0-15 here. */
+ n_regs = restore_regs (file, 0, 8, base, offset, 0);
+ else if (leaf_function)
+ /* ??? Originally saved regs 0-31 here. */
+ n_regs = restore_regs (file, 0, 8, base, offset, 0);
+ if (TARGET_EPILOGUE)
+ restore_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs);
+}
+
+/* This function generates the assembly code for function exit,
+ on machines that need it.
+
+ The function epilogue should not depend on the current stack pointer!
+ It should use the frame pointer only. This is mandatory because
+ of alloca; we also take advantage of it to omit stack adjustments
+ before returning. */
+
+static void
+sparc_output_function_epilogue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size;
+{
+ if (TARGET_FLAT)
+ sparc_flat_function_epilogue (file, size);
+ else
+ sparc_nonflat_function_epilogue (file, size,
+ current_function_uses_only_leaf_regs);
+}
+
/* Output code for the function epilogue. */
-void
-output_function_epilogue (file, size, leaf_function)
+static void
+sparc_nonflat_function_epilogue (file, size, leaf_function)
FILE *file;
- int size ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
int leaf_function;
{
const char *ret;
@@ -3275,15 +3674,8 @@ output_function_epilogue (file, size, leaf_function)
final_scan_insn (get_last_insn (), file, 0, 0, 1);
}
-#ifdef FUNCTION_BLOCK_PROFILER_EXIT
- else if (profile_block_flag == 2)
+ if (current_function_epilogue_delay_list == 0)
{
- FUNCTION_BLOCK_PROFILER_EXIT(file);
- }
-#endif
-
- else if (current_function_epilogue_delay_list == 0)
- {
/* If code does not drop into the epilogue, we need
do nothing except output pending case vectors. */
rtx insn = get_last_insn ();
@@ -3293,35 +3685,8 @@ output_function_epilogue (file, size, leaf_function)
goto output_vectors;
}
- /* Restore any call saved registers. */
if (num_gfregs)
- {
- int offset, n_regs;
- const char *base;
-
- offset = -apparent_fsize + frame_base_offset;
- if (offset < -4096 || offset + num_gfregs * 4 > 4096 - 8 /*double*/)
- {
- build_big_number (file, offset, "%g1");
- fprintf (file, "\tadd\t%s, %%g1, %%g1\n", frame_base_name);
- base = "%g1";
- offset = 0;
- }
- else
- {
- base = frame_base_name;
- }
-
- n_regs = 0;
- if (TARGET_EPILOGUE && ! leaf_function)
- /* ??? Originally saved regs 0-15 here. */
- n_regs = restore_regs (file, 0, 8, base, offset, 0);
- else if (leaf_function)
- /* ??? Originally saved regs 0-31 here. */
- n_regs = restore_regs (file, 0, 8, base, offset, 0);
- if (TARGET_EPILOGUE)
- restore_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs);
- }
+ output_restore_regs (file, leaf_function);
/* Work out how to skip the caller's unimp instruction if required. */
if (leaf_function)
@@ -3336,22 +3701,58 @@ output_function_epilogue (file, size, leaf_function)
if (! leaf_function)
{
+ if (current_function_calls_eh_return)
+ {
+ if (current_function_epilogue_delay_list)
+ abort ();
+ if (SKIP_CALLERS_UNIMP_P)
+ abort ();
+
+ fputs ("\trestore\n\tretl\n\tadd\t%sp, %g1, %sp\n", file);
+ }
/* If we wound up with things in our delay slot, flush them here. */
- if (current_function_epilogue_delay_list)
+ else if (current_function_epilogue_delay_list)
{
- rtx insn = emit_jump_insn_after (gen_rtx_RETURN (VOIDmode),
- get_last_insn ());
- PATTERN (insn) = gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2,
- PATTERN (XEXP (current_function_epilogue_delay_list, 0)),
- PATTERN (insn)));
- final_scan_insn (insn, file, 1, 0, 1);
+ rtx delay = PATTERN (XEXP (current_function_epilogue_delay_list, 0));
+
+ if (TARGET_V9 && ! epilogue_renumber (&delay, 1))
+ {
+ epilogue_renumber (&delay, 0);
+ fputs (SKIP_CALLERS_UNIMP_P
+ ? "\treturn\t%i7+12\n"
+ : "\treturn\t%i7+8\n", file);
+ final_scan_insn (XEXP (current_function_epilogue_delay_list, 0), file, 1, 0, 0);
+ }
+ else
+ {
+ rtx insn = emit_jump_insn_after (gen_rtx_RETURN (VOIDmode),
+ get_last_insn ());
+ rtx src;
+
+ if (GET_CODE (delay) != SET)
+ abort();
+
+ src = SET_SRC (delay);
+ if (GET_CODE (src) == ASHIFT)
+ {
+ if (XEXP (src, 1) != const1_rtx)
+ abort();
+ SET_SRC (delay) = gen_rtx_PLUS (GET_MODE (src), XEXP (src, 0),
+ XEXP (src, 0));
+ }
+
+ PATTERN (insn) = gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (2, delay, PATTERN (insn)));
+ final_scan_insn (insn, file, 1, 0, 1);
+ }
}
else if (TARGET_V9 && ! SKIP_CALLERS_UNIMP_P)
fputs ("\treturn\t%i7+8\n\tnop\n", file);
else
fprintf (file, "\t%s\n\trestore\n", ret);
}
+ else if (current_function_calls_eh_return)
+ abort ();
/* All of the following cases are for leaf functions. */
else if (current_function_epilogue_delay_list)
{
@@ -3386,6 +3787,149 @@ output_function_epilogue (file, size, leaf_function)
output_vectors:
sparc_output_deferred_case_vectors ();
}
+
+/* Output a sibling call. */
+
+const char *
+output_sibcall (insn, call_operand)
+ rtx insn, call_operand;
+{
+ int leaf_regs = current_function_uses_only_leaf_regs;
+ rtx operands[3];
+ int delay_slot = dbr_sequence_length () > 0;
+
+ if (num_gfregs)
+ {
+ /* Call to restore global regs might clobber
+ the delay slot. Instead of checking for this
+ output the delay slot now. */
+ if (delay_slot)
+ {
+ rtx delay = NEXT_INSN (insn);
+
+ if (! delay)
+ abort ();
+
+ final_scan_insn (delay, asm_out_file, 1, 0, 1);
+ PATTERN (delay) = gen_blockage ();
+ INSN_CODE (delay) = -1;
+ delay_slot = 0;
+ }
+ output_restore_regs (asm_out_file, leaf_regs);
+ }
+
+ operands[0] = call_operand;
+
+ if (leaf_regs)
+ {
+#ifdef HAVE_AS_RELAX_OPTION
+ /* If as and ld are relaxing tail call insns into branch always,
+ use or %o7,%g0,X; call Y; or X,%g0,%o7 always, so that it can
+ be optimized. With sethi/jmpl as nor ld has no easy way how to
+ find out if somebody does not branch between the sethi and jmpl. */
+ int spare_slot = 0;
+#else
+ int spare_slot = ((TARGET_ARCH32 || TARGET_CM_MEDLOW) && ! flag_pic);
+#endif
+ int size = 0;
+
+ if ((actual_fsize || ! spare_slot) && delay_slot)
+ {
+ rtx delay = NEXT_INSN (insn);
+
+ if (! delay)
+ abort ();
+
+ final_scan_insn (delay, asm_out_file, 1, 0, 1);
+ PATTERN (delay) = gen_blockage ();
+ INSN_CODE (delay) = -1;
+ delay_slot = 0;
+ }
+ if (actual_fsize)
+ {
+ if (actual_fsize <= 4096)
+ size = actual_fsize;
+ else if (actual_fsize <= 8192)
+ {
+ 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);
+ fputs ("\tadd\t%%sp, %%g1, %%sp\n", asm_out_file);
+ }
+ }
+ if (spare_slot)
+ {
+ 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);
+ 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);
+ /* 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);
+ output_asm_insn ("call\t%a0, 0", operands);
+ output_asm_insn (" or\t%%g1, %%g0, %%o7", operands);
+ }
+ return "";
+ }
+
+ output_asm_insn ("call\t%a0, 0", operands);
+ if (delay_slot)
+ {
+ rtx delay = NEXT_INSN (insn), pat;
+
+ if (! delay)
+ abort ();
+
+ pat = PATTERN (delay);
+ if (GET_CODE (pat) != SET)
+ abort ();
+
+ operands[0] = SET_DEST (pat);
+ pat = SET_SRC (pat);
+ switch (GET_CODE (pat))
+ {
+ case PLUS:
+ operands[1] = XEXP (pat, 0);
+ operands[2] = XEXP (pat, 1);
+ output_asm_insn (" restore %r1, %2, %Y0", operands);
+ break;
+ case LO_SUM:
+ operands[1] = XEXP (pat, 0);
+ operands[2] = XEXP (pat, 1);
+ output_asm_insn (" restore %r1, %%lo(%a2), %Y0", operands);
+ break;
+ case ASHIFT:
+ operands[1] = XEXP (pat, 0);
+ output_asm_insn (" restore %r1, %r1, %Y0", operands);
+ break;
+ default:
+ operands[1] = pat;
+ output_asm_insn (" restore %%g0, %1, %Y0", operands);
+ break;
+ }
+ PATTERN (delay) = gen_blockage ();
+ INSN_CODE (delay) = -1;
+ }
+ else
+ fputs ("\t restore\n", asm_out_file);
+ return "";
+}
/* Functions for handling argument passing.
@@ -3453,7 +3997,7 @@ void
init_cumulative_args (cum, fntype, libname, indirect)
CUMULATIVE_ARGS *cum;
tree fntype;
- tree libname ATTRIBUTE_UNUSED;
+ rtx libname ATTRIBUTE_UNUSED;
int indirect ATTRIBUTE_UNUSED;
{
cum->words = 0;
@@ -3512,6 +4056,7 @@ function_arg_slotno (cum, mode, type, named, incoming_p, pregno, ppadding)
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;
@@ -3618,20 +4163,28 @@ struct function_arg_record_value_parms
{
rtx ret;
int slotno, named, regbase;
- int nregs, intoffset;
+ unsigned int nregs;
+ int intoffset;
};
static void function_arg_record_value_3
- PROTO((int, struct function_arg_record_value_parms *));
+ PARAMS ((HOST_WIDE_INT, struct function_arg_record_value_parms *));
static void function_arg_record_value_2
- PROTO((tree, int, struct function_arg_record_value_parms *));
+ PARAMS ((tree, HOST_WIDE_INT,
+ struct function_arg_record_value_parms *));
+static void function_arg_record_value_1
+ PARAMS ((tree, HOST_WIDE_INT,
+ struct function_arg_record_value_parms *));
static rtx function_arg_record_value
- PROTO((tree, enum machine_mode, int, int, int));
+ PARAMS ((tree, enum machine_mode, int, int, int));
+
+/* A subroutine of function_arg_record_value. Traverse the structure
+ recusively and determine how many registers will be required. */
static void
function_arg_record_value_1 (type, startbitpos, parms)
tree type;
- int startbitpos;
+ HOST_WIDE_INT startbitpos;
struct function_arg_record_value_parms *parms;
{
tree field;
@@ -3659,15 +4212,16 @@ function_arg_record_value_1 (type, startbitpos, parms)
{
if (TREE_CODE (field) == FIELD_DECL)
{
- int bitpos = startbitpos;
- if (DECL_FIELD_BITPOS (field))
- bitpos += TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field));
+ HOST_WIDE_INT bitpos = startbitpos;
+
+ if (DECL_SIZE (field) != 0
+ && host_integerp (bit_position (field), 1))
+ bitpos += int_bit_position (field);
+
/* ??? FIXME: else assume zero offset. */
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
- {
- function_arg_record_value_1 (TREE_TYPE (field), bitpos, parms);
- }
+ function_arg_record_value_1 (TREE_TYPE (field), bitpos, parms);
else if (TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
&& TARGET_FPU
&& ! packed_p
@@ -3701,23 +4255,29 @@ function_arg_record_value_1 (type, startbitpos, parms)
}
}
-/* Handle recursive structure field register assignment. */
+/* A subroutine of function_arg_record_value. Assign the bits of the
+ structure between parms->intoffset and bitpos to integer registers. */
static void
function_arg_record_value_3 (bitpos, parms)
- int bitpos;
+ HOST_WIDE_INT bitpos;
struct function_arg_record_value_parms *parms;
{
enum machine_mode mode;
- int regno, this_slotno, intslots, intoffset;
+ unsigned int regno;
+ unsigned int startbit, endbit;
+ int this_slotno, intslots, intoffset;
rtx reg;
if (parms->intoffset == -1)
return;
+
intoffset = parms->intoffset;
parms->intoffset = -1;
- intslots = (bitpos - intoffset + BITS_PER_WORD - 1) / BITS_PER_WORD;
+ startbit = intoffset & -BITS_PER_WORD;
+ endbit = (bitpos + BITS_PER_WORD - 1) & -BITS_PER_WORD;
+ intslots = (endbit - startbit) / BITS_PER_WORD;
this_slotno = parms->slotno + intoffset / BITS_PER_WORD;
intslots = MIN (intslots, SPARC_INT_ARG_MAX - this_slotno);
@@ -3730,10 +4290,8 @@ function_arg_record_value_3 (bitpos, parms)
at the moment but may wish to revisit. */
if (intoffset % BITS_PER_WORD != 0)
- {
- mode = mode_for_size (BITS_PER_WORD - intoffset%BITS_PER_WORD,
- MODE_INT, 0);
- }
+ mode = mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
+ MODE_INT, 0);
else
mode = word_mode;
@@ -3753,10 +4311,15 @@ function_arg_record_value_3 (bitpos, parms)
while (intslots > 0);
}
+/* A subroutine of function_arg_record_value. Traverse the structure
+ recursively and assign bits to floating point registers. Track which
+ bits in between need integer registers; invoke function_arg_record_value_3
+ to make that happen. */
+
static void
function_arg_record_value_2 (type, startbitpos, parms)
tree type;
- int startbitpos;
+ HOST_WIDE_INT startbitpos;
struct function_arg_record_value_parms *parms;
{
tree field;
@@ -3775,15 +4338,16 @@ function_arg_record_value_2 (type, startbitpos, parms)
{
if (TREE_CODE (field) == FIELD_DECL)
{
- int bitpos = startbitpos;
- if (DECL_FIELD_BITPOS (field))
- bitpos += TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field));
+ HOST_WIDE_INT bitpos = startbitpos;
+
+ if (DECL_SIZE (field) != 0
+ && host_integerp (bit_position (field), 1))
+ bitpos += int_bit_position (field);
+
/* ??? FIXME: else assume zero offset. */
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
- {
- function_arg_record_value_2 (TREE_TYPE (field), bitpos, parms);
- }
+ function_arg_record_value_2 (TREE_TYPE (field), bitpos, parms);
else if (TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
&& TARGET_FPU
&& ! packed_p
@@ -3812,6 +4376,9 @@ function_arg_record_value_2 (type, startbitpos, parms)
}
}
+/* Used by function_arg and function_value to implement the complex
+ Sparc64 structure calling conventions. */
+
static rtx
function_arg_record_value (type, mode, slotno, named, regbase)
tree type;
@@ -3820,7 +4387,7 @@ function_arg_record_value (type, mode, slotno, named, regbase)
{
HOST_WIDE_INT typesize = int_size_in_bytes (type);
struct function_arg_record_value_parms parms;
- int nregs;
+ unsigned int nregs;
parms.ret = NULL_RTX;
parms.slotno = slotno;
@@ -3834,10 +4401,12 @@ function_arg_record_value (type, mode, slotno, named, regbase)
if (parms.intoffset != -1)
{
+ unsigned int startbit, endbit;
int intslots, this_slotno;
- intslots = (typesize*BITS_PER_UNIT - parms.intoffset + BITS_PER_WORD - 1)
- / BITS_PER_WORD;
+ startbit = parms.intoffset & -BITS_PER_WORD;
+ endbit = (typesize*BITS_PER_UNIT + BITS_PER_WORD - 1) & -BITS_PER_WORD;
+ intslots = (endbit - startbit) / BITS_PER_WORD;
this_slotno = slotno + parms.intoffset / BITS_PER_WORD;
intslots = MIN (intslots, SPARC_INT_ARG_MAX - this_slotno);
@@ -4122,7 +4691,7 @@ function_arg_pass_by_reference (cum, mode, type, named)
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 TCmode. */
|| GET_MODE_SIZE (mode) > 16
|| (type && AGGREGATE_TYPE_P (type)
&& int_size_in_bytes (type) > 16));
@@ -4235,9 +4804,11 @@ function_value (type, mode, incoming_p)
return function_arg_record_value (type, mode, 0, 1, regbase);
}
- else if (TREE_CODE (type) == UNION_TYPE)
+ else if (AGGREGATE_TYPE_P (type))
{
- int bytes = int_size_in_bytes (type);
+ /* All other aggregate types are passed in an integer register
+ in a mode corresponding to the size of the type. */
+ HOST_WIDE_INT bytes = int_size_in_bytes (type);
if (bytes > 32)
abort ();
@@ -4249,7 +4820,7 @@ function_value (type, mode, incoming_p)
if (TARGET_ARCH64
&& GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) < UNITS_PER_WORD
- && type && TREE_CODE (type) != UNION_TYPE)
+ && type && ! AGGREGATE_TYPE_P (type))
mode = DImode;
if (incoming_p)
@@ -4260,14 +4831,12 @@ function_value (type, mode, incoming_p)
return gen_rtx_REG (mode, regno);
}
-/* Do what is necessary for `va_start'. The argument is ignored.
-
- We look at the current function to determine if stdarg or varargs
- is used and return the address of the first unnamed parameter. */
+/* Do what is necessary for `va_start'. We look at the current function
+ to determine if stdarg or varargs is used and return the address of
+ the first unnamed parameter. */
rtx
-sparc_builtin_saveregs (arglist)
- tree arglist ATTRIBUTE_UNUSED;
+sparc_builtin_saveregs ()
{
int first_reg = current_function_args_info.words;
rtx address;
@@ -4275,29 +4844,141 @@ sparc_builtin_saveregs (arglist)
for (regno = first_reg; regno < NPARM_REGS (word_mode); regno++)
emit_move_insn (gen_rtx_MEM (word_mode,
- gen_rtx_PLUS (Pmode,
- frame_pointer_rtx,
- GEN_INT (STACK_POINTER_OFFSET
- + UNITS_PER_WORD * regno))),
+ gen_rtx_PLUS (Pmode,
+ frame_pointer_rtx,
+ GEN_INT (STACK_POINTER_OFFSET
+ + (UNITS_PER_WORD
+ * regno)))),
gen_rtx_REG (word_mode,
- BASE_INCOMING_ARG_REG (word_mode) + regno));
+ BASE_INCOMING_ARG_REG (word_mode) + regno));
address = gen_rtx_PLUS (Pmode,
- frame_pointer_rtx,
- GEN_INT (STACK_POINTER_OFFSET
- + UNITS_PER_WORD * first_reg));
-
- if (current_function_check_memory_usage
- && first_reg < NPARM_REGS (word_mode))
- emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
- address, ptr_mode,
- GEN_INT (UNITS_PER_WORD
- * (NPARM_REGS (word_mode) - first_reg)),
- TYPE_MODE (sizetype), GEN_INT (MEMORY_USE_RW),
- TYPE_MODE (integer_type_node));
+ frame_pointer_rtx,
+ GEN_INT (STACK_POINTER_OFFSET
+ + UNITS_PER_WORD * first_reg));
return address;
}
+
+/* Implement `va_start' for varargs and stdarg. */
+
+void
+sparc_va_start (stdarg_p, valist, nextarg)
+ int stdarg_p ATTRIBUTE_UNUSED;
+ tree valist;
+ rtx nextarg;
+{
+ nextarg = expand_builtin_saveregs ();
+ std_expand_builtin_va_start (1, valist, nextarg);
+}
+
+/* Implement `va_arg'. */
+
+rtx
+sparc_va_arg (valist, type)
+ tree valist, type;
+{
+ HOST_WIDE_INT size, rsize, align;
+ tree addr, incr;
+ rtx addr_rtx;
+ int indirect = 0;
+
+ /* Round up sizeof(type) to a word. */
+ size = int_size_in_bytes (type);
+ rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
+ align = 0;
+
+ if (TARGET_ARCH64)
+ {
+ if (TYPE_ALIGN (type) >= 2 * (unsigned) BITS_PER_WORD)
+ align = 2 * UNITS_PER_WORD;
+
+ if (AGGREGATE_TYPE_P (type))
+ {
+ if (size > 16)
+ {
+ indirect = 1;
+ size = rsize = UNITS_PER_WORD;
+ }
+ else
+ size = rsize;
+ }
+ }
+ else
+ {
+ if (AGGREGATE_TYPE_P (type)
+ || TYPE_MODE (type) == TFmode
+ || TYPE_MODE (type) == TCmode)
+ {
+ indirect = 1;
+ size = rsize = UNITS_PER_WORD;
+ }
+ }
+
+ incr = valist;
+ if (align)
+ {
+ incr = fold (build (PLUS_EXPR, ptr_type_node, incr,
+ build_int_2 (align - 1, 0)));
+ incr = fold (build (BIT_AND_EXPR, ptr_type_node, incr,
+ build_int_2 (-align, -1)));
+ }
+
+ addr = incr = save_expr (incr);
+ if (BYTES_BIG_ENDIAN && size < rsize)
+ {
+ addr = fold (build (PLUS_EXPR, ptr_type_node, incr,
+ build_int_2 (rsize - size, 0)));
+ }
+ incr = fold (build (PLUS_EXPR, ptr_type_node, incr,
+ build_int_2 (rsize, 0)));
+
+ incr = build (MODIFY_EXPR, ptr_type_node, valist, incr);
+ TREE_SIDE_EFFECTS (incr) = 1;
+ expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ addr_rtx = expand_expr (addr, NULL, Pmode, EXPAND_NORMAL);
+
+ /* If the address isn't aligned properly for the type,
+ we may need to copy to a temporary.
+ FIXME: This is inefficient. Usually we can do this
+ in registers. */
+ if (align == 0
+ && TYPE_ALIGN (type) > BITS_PER_WORD
+ && !indirect)
+ {
+ /* FIXME: We really need to specify that the temporary is live
+ for the whole function because expand_builtin_va_arg wants
+ the alias set to be get_varargs_alias_set (), but in this
+ case the alias set is that for TYPE and if the memory gets
+ reused it will be reused with alias set TYPE. */
+ rtx tmp = assign_temp (type, 0, 1, 0);
+ rtx dest_addr;
+
+ addr_rtx = force_reg (Pmode, addr_rtx);
+ addr_rtx = gen_rtx_MEM (BLKmode, addr_rtx);
+ set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
+ set_mem_align (addr_rtx, BITS_PER_WORD);
+ tmp = shallow_copy_rtx (tmp);
+ PUT_MODE (tmp, BLKmode);
+ set_mem_alias_set (tmp, 0);
+
+ dest_addr = emit_block_move (tmp, addr_rtx, GEN_INT (rsize));
+ if (dest_addr != NULL_RTX)
+ addr_rtx = dest_addr;
+ else
+ addr_rtx = XCEXP (tmp, 0, MEM);
+ }
+
+ if (indirect)
+ {
+ addr_rtx = force_reg (Pmode, addr_rtx);
+ addr_rtx = gen_rtx_MEM (Pmode, addr_rtx);
+ set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
+ }
+
+ return addr_rtx;
+}
/* Return the string to output a conditional branch to LABEL, which is
the operand number of the label. OP is the conditional expression.
@@ -4328,158 +5009,128 @@ output_cbranch (op, label, reversed, annul, noop, insn)
static char v9_xcc_labelno[] = "%%xcc, %lX";
static char v9_fcc_labelno[] = "%%fccX, %lY";
char *labelno;
+ const char *branch;
int labeloff, spaces = 8;
- /* ??? !v9: FP branches cannot be preceded by another floating point insn.
- Because there is currently no concept of pre-delay slots, we can fix
- this only by always emitting a nop before a floating point branch. */
-
- if ((mode == CCFPmode || mode == CCFPEmode) && ! TARGET_V9)
- strcpy (string, "nop\n\t");
- else
- string[0] = '\0';
-
- /* If not floating-point or if EQ or NE, we can just reverse the code. */
- if (reversed
- && ((mode != CCFPmode && mode != CCFPEmode) || code == EQ || code == NE))
- code = reverse_condition (code), reversed = 0;
-
- /* Start by writing the branch condition. */
- switch (code)
+ if (reversed)
{
- case NE:
+ /* Reversal of FP compares takes care -- an ordered compare
+ becomes an unordered compare and vice versa. */
if (mode == CCFPmode || mode == CCFPEmode)
- {
- strcat (string, "fbne");
- spaces -= 4;
- }
+ code = reverse_condition_maybe_unordered (code);
else
- {
- strcpy (string, "bne");
- spaces -= 3;
- }
- break;
+ code = reverse_condition (code);
+ }
- case EQ:
- if (mode == CCFPmode || mode == CCFPEmode)
- {
- strcat (string, "fbe");
- spaces -= 3;
- }
- else
+ /* Start by writing the branch condition. */
+ if (mode == CCFPmode || mode == CCFPEmode)
+ {
+ switch (code)
{
- strcpy (string, "be");
- spaces -= 2;
- }
- break;
+ case NE:
+ branch = "fbne";
+ break;
+ case EQ:
+ branch = "fbe";
+ break;
+ case GE:
+ branch = "fbge";
+ break;
+ case GT:
+ branch = "fbg";
+ break;
+ case LE:
+ branch = "fble";
+ break;
+ case LT:
+ branch = "fbl";
+ break;
+ case UNORDERED:
+ branch = "fbu";
+ break;
+ case ORDERED:
+ branch = "fbo";
+ break;
+ case UNGT:
+ branch = "fbug";
+ break;
+ case UNLT:
+ branch = "fbul";
+ break;
+ case UNEQ:
+ branch = "fbue";
+ break;
+ case UNGE:
+ branch = "fbuge";
+ break;
+ case UNLE:
+ branch = "fbule";
+ break;
+ case LTGT:
+ branch = "fblg";
+ break;
- case GE:
- if (mode == CCFPmode || mode == CCFPEmode)
- {
- if (reversed)
- strcat (string, "fbul");
- else
- strcat (string, "fbge");
- spaces -= 4;
- }
- else if (mode == CC_NOOVmode)
- {
- strcpy (string, "bpos");
- spaces -= 4;
- }
- else
- {
- strcpy (string, "bge");
- spaces -= 3;
+ default:
+ abort ();
}
- break;
- case GT:
- if (mode == CCFPmode || mode == CCFPEmode)
- {
- if (reversed)
- {
- strcat (string, "fbule");
- spaces -= 5;
- }
- else
- {
- strcat (string, "fbg");
- spaces -= 3;
- }
- }
- else
- {
- strcpy (string, "bg");
- spaces -= 2;
- }
- break;
+ /* ??? !v9: FP branches cannot be preceded by another floating point
+ insn. Because there is currently no concept of pre-delay slots,
+ we can fix this only by always emitting a nop before a floating
+ point branch. */
- case LE:
- if (mode == CCFPmode || mode == CCFPEmode)
+ string[0] = '\0';
+ if (! TARGET_V9)
+ strcpy (string, "nop\n\t");
+ strcat (string, branch);
+ }
+ else
+ {
+ switch (code)
{
- if (reversed)
- strcat (string, "fbug");
+ case NE:
+ branch = "bne";
+ break;
+ case EQ:
+ branch = "be";
+ break;
+ case GE:
+ if (mode == CC_NOOVmode)
+ branch = "bpos";
else
- strcat (string, "fble");
- spaces -= 4;
- }
- else
- {
- strcpy (string, "ble");
- spaces -= 3;
- }
- break;
-
- case LT:
- if (mode == CCFPmode || mode == CCFPEmode)
- {
- if (reversed)
- {
- strcat (string, "fbuge");
- spaces -= 5;
- }
+ branch = "bge";
+ break;
+ case GT:
+ branch = "bg";
+ break;
+ case LE:
+ branch = "ble";
+ break;
+ case LT:
+ if (mode == CC_NOOVmode)
+ branch = "bneg";
else
- {
- strcat (string, "fbl");
- spaces -= 3;
- }
- }
- else if (mode == CC_NOOVmode)
- {
- strcpy (string, "bneg");
- spaces -= 4;
- }
- else
- {
- strcpy (string, "bl");
- spaces -= 2;
- }
- break;
-
- case GEU:
- strcpy (string, "bgeu");
- spaces -= 4;
- break;
-
- case GTU:
- strcpy (string, "bgu");
- spaces -= 3;
- break;
-
- case LEU:
- strcpy (string, "bleu");
- spaces -= 4;
- break;
-
- case LTU:
- strcpy (string, "blu");
- spaces -= 3;
- break;
+ branch = "bl";
+ break;
+ case GEU:
+ branch = "bgeu";
+ break;
+ case GTU:
+ branch = "bgu";
+ break;
+ case LEU:
+ branch = "bleu";
+ break;
+ case LTU:
+ branch = "blu";
+ break;
- default:
- abort ();
+ default:
+ abort ();
+ }
+ strcpy (string, branch);
}
+ spaces -= strlen (branch);
/* Now add the annulling, the label, and a possible noop. */
if (annul)
@@ -4532,6 +5183,147 @@ output_cbranch (op, label, reversed, annul, noop, insn)
return string;
}
+/* Emit a library call comparison between floating point X and Y.
+ COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).
+ TARGET_ARCH64 uses _Qp_* functions, which use pointers to TFmode
+ 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;
+{
+ const char *qpfunc;
+ rtx slot0, slot1, result, tem, tem2;
+ enum machine_mode mode;
+
+ switch (comparison)
+ {
+ case EQ:
+ qpfunc = (TARGET_ARCH64) ? "_Qp_feq" : "_Q_feq";
+ break;
+
+ case NE:
+ qpfunc = (TARGET_ARCH64) ? "_Qp_fne" : "_Q_fne";
+ break;
+
+ case GT:
+ qpfunc = (TARGET_ARCH64) ? "_Qp_fgt" : "_Q_fgt";
+ break;
+
+ case GE:
+ qpfunc = (TARGET_ARCH64) ? "_Qp_fge" : "_Q_fge";
+ break;
+
+ case LT:
+ qpfunc = (TARGET_ARCH64) ? "_Qp_flt" : "_Q_flt";
+ break;
+
+ case LE:
+ qpfunc = (TARGET_ARCH64) ? "_Qp_fle" : "_Q_fle";
+ break;
+
+ case ORDERED:
+ case UNORDERED:
+ case UNGT:
+ case UNLT:
+ case UNEQ:
+ case UNGE:
+ case UNLE:
+ case LTGT:
+ qpfunc = (TARGET_ARCH64) ? "_Qp_cmp" : "_Q_cmp";
+ break;
+
+ default:
+ abort();
+ break;
+ }
+
+ if (TARGET_ARCH64)
+ {
+ if (GET_CODE (x) != MEM)
+ {
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ emit_insn (gen_rtx_SET (VOIDmode, slot0, x));
+ }
+ else
+ slot0 = x;
+
+ if (GET_CODE (y) != MEM)
+ {
+ slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ emit_insn (gen_rtx_SET (VOIDmode, slot1, y));
+ }
+ else
+ slot1 = y;
+
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), 1,
+ DImode, 2,
+ XEXP (slot0, 0), Pmode,
+ XEXP (slot1, 0), Pmode);
+
+ mode = DImode;
+ }
+ else
+ {
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), 1,
+ SImode, 2,
+ x, TFmode, y, TFmode);
+
+ mode = SImode;
+ }
+
+
+ /* Immediately move the result of the libcall into a pseudo
+ register so reload doesn't clobber the value if it needs
+ the return register for a spill reg. */
+ result = gen_reg_rtx (mode);
+ emit_move_insn (result, hard_libcall_value (mode));
+
+ switch (comparison)
+ {
+ default:
+ emit_cmp_insn (result, const0_rtx, NE, NULL_RTX, mode, 0);
+ break;
+ case ORDERED:
+ case UNORDERED:
+ emit_cmp_insn (result, GEN_INT(3), comparison == UNORDERED ? EQ : NE,
+ NULL_RTX, mode, 0);
+ break;
+ case UNGT:
+ case UNGE:
+ emit_cmp_insn (result, const1_rtx,
+ comparison == UNGT ? GT : NE, NULL_RTX, mode, 0);
+ break;
+ case UNLE:
+ emit_cmp_insn (result, const2_rtx, NE, NULL_RTX, mode, 0);
+ break;
+ case UNLT:
+ tem = gen_reg_rtx (mode);
+ if (TARGET_ARCH32)
+ emit_insn (gen_andsi3 (tem, result, const1_rtx));
+ else
+ emit_insn (gen_anddi3 (tem, result, const1_rtx));
+ emit_cmp_insn (tem, const0_rtx, NE, NULL_RTX, mode, 0);
+ break;
+ case UNEQ:
+ case LTGT:
+ tem = gen_reg_rtx (mode);
+ if (TARGET_ARCH32)
+ emit_insn (gen_addsi3 (tem, result, const1_rtx));
+ else
+ emit_insn (gen_adddi3 (tem, result, const1_rtx));
+ tem2 = gen_reg_rtx (mode);
+ if (TARGET_ARCH32)
+ emit_insn (gen_andsi3 (tem2, tem, const2_rtx));
+ else
+ emit_insn (gen_anddi3 (tem2, tem, const2_rtx));
+ emit_cmp_insn (tem2, const0_rtx, comparison == UNEQ ? EQ : NE,
+ NULL_RTX, mode, 0);
+ break;
+ }
+}
+
/* Return the string to output a conditional branch to LABEL, testing
register REG. LABEL is the operand number of the label; REG is the
operand number of the reg. OP is the conditional expression. The mode
@@ -4631,56 +5423,83 @@ output_v9branch (op, reg, label, reversed, annul, noop, insn)
return string;
}
-/* Renumber registers in delay slot. Replace registers instead of
- renumbering because they may be shared.
-
- This does not handle instructions other than move. */
+/* Return 1, if any of the registers of the instruction are %l[0-7] or %o[0-7].
+ Such instructions cannot be used in the delay slot of return insn on v9.
+ If TEST is 0, also rename all %i[0-7] registers to their %o[0-7] counterparts.
+ */
-static void
-epilogue_renumber (where)
- rtx *where;
+static int
+epilogue_renumber (where, test)
+ register rtx *where;
+ int test;
{
- rtx x = *where;
- enum rtx_code code = GET_CODE (x);
+ register const char *fmt;
+ register int i;
+ register enum rtx_code code;
+
+ if (*where == 0)
+ return 0;
+
+ code = GET_CODE (*where);
switch (code)
{
- case MEM:
- *where = x = copy_rtx (x);
- epilogue_renumber (&XEXP (x, 0));
- return;
-
case REG:
- {
- int regno = REGNO (x);
- if (regno > 8 && regno < 24)
- abort ();
- if (regno >= 24 && regno < 32)
- *where = gen_rtx_REG (GET_MODE (x), regno - 16);
- return;
- }
+ if (REGNO (*where) >= 8 && REGNO (*where) < 24) /* oX or lX */
+ return 1;
+ if (! test && REGNO (*where) >= 24 && REGNO (*where) < 32)
+ *where = gen_rtx (REG, GET_MODE (*where), OUTGOING_REGNO (REGNO(*where)));
+ case SCRATCH:
+ case CC0:
+ case PC:
case CONST_INT:
case CONST_DOUBLE:
- case CONST:
- case SYMBOL_REF:
- case LABEL_REF:
- return;
+ return 0;
- case IOR:
- case AND:
- case XOR:
+ /* Do not replace the frame pointer with the stack pointer because
+ it can cause the delayed instruction to load below the stack.
+ This occurs when instructions like:
+
+ (set (reg/i:SI 24 %i0)
+ (mem/f:SI (plus:SI (reg/f:SI 30 %fp)
+ (const_int -20 [0xffffffec])) 0))
+
+ are in the return delayed slot. */
case PLUS:
- case MINUS:
- epilogue_renumber (&XEXP (x, 1));
- case NEG:
- case NOT:
- epilogue_renumber (&XEXP (x, 0));
- return;
+ if (GET_CODE (XEXP (*where, 0)) == REG
+ && REGNO (XEXP (*where, 0)) == FRAME_POINTER_REGNUM
+ && (GET_CODE (XEXP (*where, 1)) != CONST_INT
+ || INTVAL (XEXP (*where, 1)) < SPARC_STACK_BIAS))
+ return 1;
+ break;
+
+ case MEM:
+ if (SPARC_STACK_BIAS
+ && GET_CODE (XEXP (*where, 0)) == REG
+ && REGNO (XEXP (*where, 0)) == FRAME_POINTER_REGNUM)
+ return 1;
+ break;
default:
- debug_rtx (*where);
- abort ();
+ break;
+ }
+
+ fmt = GET_RTX_FORMAT (code);
+
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'E')
+ {
+ register int j;
+ for (j = XVECLEN (*where, i) - 1; j >= 0; j--)
+ if (epilogue_renumber (&(XVECEXP (*where, i, j)), test))
+ return 1;
+ }
+ else if (fmt[i] == 'e'
+ && epilogue_renumber (&(XEXP (*where, i)), test))
+ return 1;
}
+ return 0;
}
/* Output assembler code to return from a function. */
@@ -4736,17 +5555,17 @@ output_return (operands)
else
{
if ((actual_fsize & 0x3ff) != 0)
- return "sethi %%hi(%a0),%%g1\n\tor %%g1,%%lo(%a0),%%g1\n\tretl\n\tadd %%sp,%%g1,%%sp";
+ return "sethi\t%%hi(%a0), %%g1\n\tor\t%%g1, %%lo(%a0), %%g1\n\tretl\n\tadd\t%%sp, %%g1, %%sp";
else
- return "sethi %%hi(%a0),%%g1\n\tretl\n\tadd %%sp,%%g1,%%sp";
+ return "sethi\t%%hi(%a0), %%g1\n\tretl\n\tadd\t%%sp, %%g1, %%sp";
}
}
else if (TARGET_V9)
{
if (delay)
{
- epilogue_renumber (&SET_DEST (PATTERN (delay)));
- epilogue_renumber (&SET_SRC (PATTERN (delay)));
+ epilogue_renumber (&SET_DEST (PATTERN (delay)), 0);
+ epilogue_renumber (&SET_SRC (PATTERN (delay)), 0);
}
if (SKIP_CALLERS_UNIMP_P)
return "return\t%%i7+12%#";
@@ -4766,13 +5585,13 @@ output_return (operands)
/* Leaf functions and non-leaf functions have different needs. */
-static int
+static const int
reg_leaf_alloc_order[] = REG_LEAF_ALLOC_ORDER;
-static int
+static const int
reg_nonleaf_alloc_order[] = REG_ALLOC_ORDER;
-static int *reg_alloc_orders[] = {
+static const int *const reg_alloc_orders[] = {
reg_leaf_alloc_order,
reg_nonleaf_alloc_order};
@@ -4784,8 +5603,9 @@ order_regs_for_local_alloc ()
if (regs_ever_live[15] != last_order_nonleaf)
{
last_order_nonleaf = !last_order_nonleaf;
- bcopy ((char *) reg_alloc_orders[last_order_nonleaf],
- (char *) reg_alloc_order, FIRST_PSEUDO_REGISTER * sizeof (int));
+ memcpy ((char *) reg_alloc_order,
+ (const char *) reg_alloc_orders[last_order_nonleaf],
+ FIRST_PSEUDO_REGISTER * sizeof (int));
}
}
@@ -4823,12 +5643,8 @@ int
sparc_absnegfloat_split_legitimate (x, y)
rtx x, y;
{
- if (GET_CODE (x) == SUBREG)
- x = alter_subreg (x);
if (GET_CODE (x) != REG)
return 0;
- if (GET_CODE (y) == SUBREG)
- y = alter_subreg (y);
if (GET_CODE (y) != REG)
return 0;
if (REGNO (x) == REGNO (y))
@@ -4859,26 +5675,42 @@ registers_ok_for_ldd_peep (reg1, reg2)
return (REGNO (reg1) == REGNO (reg2) - 1);
}
-/* Return 1 if addr1 and addr2 are suitable for use in an ldd or
- std insn.
-
- This can only happen when addr1 and addr2 are consecutive memory
- locations (addr1 + 4 == addr2). addr1 must also be aligned on a
- 64 bit boundary (addr1 % 8 == 0).
-
- We know %sp and %fp are kept aligned on a 64 bit boundary. Other
- registers are assumed to *never* be properly aligned and are
- rejected.
+/* Return 1 if the addresses in mem1 and mem2 are suitable for use in
+ an ldd or std insn.
+
+ This can only happen when addr1 and addr2, the addresses in mem1
+ and mem2, are consecutive memory locations (addr1 + 4 == addr2).
+ addr1 must also be aligned on a 64-bit boundary.
- Knowing %sp and %fp are kept aligned on a 64 bit boundary, we
- need only check that the offset for addr1 % 8 == 0. */
+ Also iff dependent_reg_rtx is not null it should not be used to
+ compute the address for mem1, i.e. we cannot optimize a sequence
+ like:
+ ld [%o0], %o0
+ ld [%o0 + 4], %o1
+ to
+ ldd [%o0], %o0
+ For stores we don't have a similar problem, so dependent_reg_rtx is
+ NULL_RTX. */
int
-addrs_ok_for_ldd_peep (addr1, addr2)
- rtx addr1, addr2;
+mems_ok_for_ldd_peep (mem1, mem2, dependent_reg_rtx)
+ rtx mem1, mem2, dependent_reg_rtx;
{
- int reg1, offset1;
+ rtx addr1, addr2;
+ unsigned int reg1;
+ int offset1;
+ /* The mems cannot be volatile. */
+ if (MEM_VOLATILE_P (mem1) || MEM_VOLATILE_P (mem2))
+ return 0;
+
+ /* MEM1 should be aligned on a 64-bit boundary. */
+ if (MEM_ALIGN (mem1) < 64)
+ return 0;
+
+ addr1 = XEXP (mem1, 0);
+ addr2 = XEXP (mem2, 0);
+
/* Extract a register number and offset (if used) from the first addr. */
if (GET_CODE (addr1) == PLUS)
{
@@ -4911,14 +5743,12 @@ addrs_ok_for_ldd_peep (addr1, addr2)
|| GET_CODE (XEXP (addr2, 1)) != CONST_INT)
return 0;
- /* Only %fp and %sp are allowed. Additionally both addresses must
- use the same register. */
- if (reg1 != FRAME_POINTER_REGNUM && reg1 != STACK_POINTER_REGNUM)
- return 0;
-
if (reg1 != REGNO (XEXP (addr2, 0)))
return 0;
+ if (dependent_reg_rtx != NULL_RTX && reg1 == REGNO (dependent_reg_rtx))
+ return 0;
+
/* The first offset must be evenly divisible by 8 to ensure the
address is 64 bit aligned. */
if (offset1 % 8 != 0)
@@ -5001,13 +5831,13 @@ print_operand (file, x, code)
if (GET_CODE (x) == CONST_INT)
break;
else if (GET_CODE (x) != REG)
- output_operand_lossage ("Invalid %%Y operand");
+ output_operand_lossage ("invalid %%Y operand");
else if (REGNO (x) < 8)
fputs (reg_names[REGNO (x)], file);
else if (REGNO (x) >= 24 && REGNO (x) < 32)
fputs (reg_names[REGNO (x)-16], file);
else
- output_operand_lossage ("Invalid %%Y operand");
+ output_operand_lossage ("invalid %%Y operand");
return;
case 'L':
/* Print out the low order register name of a register pair. */
@@ -5077,7 +5907,7 @@ print_operand (file, x, code)
case IOR: fputs ("or", file); break;
case AND: fputs ("and", file); break;
case XOR: fputs ("xor", file); break;
- default: output_operand_lossage ("Invalid %%A operand");
+ default: output_operand_lossage ("invalid %%A operand");
}
return;
@@ -5087,7 +5917,7 @@ print_operand (file, x, code)
case IOR: fputs ("orn", file); break;
case AND: fputs ("andn", file); break;
case XOR: fputs ("xnor", file); break;
- default: output_operand_lossage ("Invalid %%B operand");
+ default: output_operand_lossage ("invalid %%B operand");
}
return;
@@ -5095,9 +5925,16 @@ print_operand (file, x, code)
case 'c' :
case 'C':
{
- enum rtx_code rc = (code == 'c'
- ? reverse_condition (GET_CODE (x))
- : GET_CODE (x));
+ enum rtx_code rc = GET_CODE (x);
+
+ if (code == 'c')
+ {
+ enum machine_mode mode = GET_MODE (XEXP (x, 0));
+ if (mode == CCFPmode || mode == CCFPEmode)
+ rc = reverse_condition_maybe_unordered (GET_CODE (x));
+ else
+ rc = reverse_condition (GET_CODE (x));
+ }
switch (rc)
{
case NE: fputs ("ne", file); break;
@@ -5110,9 +5947,17 @@ print_operand (file, x, code)
case GTU: fputs ("gu", file); break;
case LEU: fputs ("leu", file); break;
case LTU: fputs ("lu", file); break;
+ case LTGT: fputs ("lg", file); break;
+ case UNORDERED: fputs ("u", file); break;
+ case ORDERED: fputs ("o", file); break;
+ case UNLT: fputs ("ul", file); break;
+ case UNLE: fputs ("ule", file); break;
+ case UNGT: fputs ("ug", file); break;
+ case UNGE: fputs ("uge", file); break;
+ case UNEQ: fputs ("ue", file); break;
default: output_operand_lossage (code == 'c'
- ? "Invalid %%c operand"
- : "Invalid %%C operand");
+ ? "invalid %%c operand"
+ : "invalid %%C operand");
}
return;
}
@@ -5133,8 +5978,8 @@ print_operand (file, x, code)
case LE: fputs ("lez", file); break;
case GT: fputs ("gz", file); break;
default: output_operand_lossage (code == 'd'
- ? "Invalid %%d operand"
- : "Invalid %%D operand");
+ ? "invalid %%d operand"
+ : "invalid %%D operand");
}
return;
}
@@ -5152,7 +5997,7 @@ print_operand (file, x, code)
case 'f':
/* Operand must be a MEM; write its address. */
if (GET_CODE (x) != MEM)
- output_operand_lossage ("Invalid %%f operand");
+ output_operand_lossage ("invalid %%f operand");
output_address (XEXP (x, 0));
return;
@@ -5171,8 +6016,7 @@ print_operand (file, x, code)
{
fputc ('[', file);
/* Poor Sun assembler doesn't understand absolute addressing. */
- if (CONSTANT_P (XEXP (x, 0))
- && ! TARGET_LIVE_G0)
+ if (CONSTANT_P (XEXP (x, 0)))
fputs ("%g0+", file);
output_address (XEXP (x, 0));
fputc (']', file);
@@ -5198,10 +6042,10 @@ print_operand (file, x, code)
|| GET_MODE_CLASS (GET_MODE (x)) == MODE_INT))
{
if (CONST_DOUBLE_HIGH (x) == 0)
- fprintf (file, "%u", CONST_DOUBLE_LOW (x));
+ fprintf (file, "%u", (unsigned int) CONST_DOUBLE_LOW (x));
else if (CONST_DOUBLE_HIGH (x) == -1
&& CONST_DOUBLE_LOW (x) < 0)
- fprintf (file, "%d", CONST_DOUBLE_LOW (x));
+ fprintf (file, "%d", (int) CONST_DOUBLE_LOW (x));
else
output_operand_lossage ("long long constant not a valid immediate operand");
}
@@ -5210,65 +6054,33 @@ print_operand (file, x, code)
else { output_addr_const (file, x); }
}
-/* This function outputs assembler code for VALUE to FILE, where VALUE is
- a 64 bit (DImode) value. */
-
-/* ??? If there is a 64 bit counterpart to .word that the assembler
- understands, then using that would simply this code greatly. */
-/* ??? We only output .xword's for symbols and only then in environments
- where the assembler can handle them. */
+/* Target hook for assembling integer objects. The sparc version has
+ special handling for aligned DI-mode objects. */
-void
-output_double_int (file, value)
- FILE *file;
- rtx value;
+static bool
+sparc_assemble_integer (x, size, aligned_p)
+ rtx x;
+ unsigned int size;
+ int aligned_p;
{
- if (GET_CODE (value) == CONST_INT)
- {
- /* ??? This has endianness issues. */
-#if HOST_BITS_PER_WIDE_INT == 64
- HOST_WIDE_INT xword = INTVAL (value);
- HOST_WIDE_INT high, low;
-
- high = (xword >> 32) & 0xffffffff;
- low = xword & 0xffffffff;
- ASM_OUTPUT_INT (file, GEN_INT (high));
- ASM_OUTPUT_INT (file, GEN_INT (low));
-#else
- if (INTVAL (value) < 0)
- ASM_OUTPUT_INT (file, constm1_rtx);
- else
- ASM_OUTPUT_INT (file, const0_rtx);
- ASM_OUTPUT_INT (file, value);
-#endif
- }
- else if (GET_CODE (value) == CONST_DOUBLE)
- {
- ASM_OUTPUT_INT (file, GEN_INT (CONST_DOUBLE_HIGH (value)));
- ASM_OUTPUT_INT (file, GEN_INT (CONST_DOUBLE_LOW (value)));
- }
- else if (GET_CODE (value) == SYMBOL_REF
- || GET_CODE (value) == CONST
- || GET_CODE (value) == PLUS
- || (TARGET_ARCH64 &&
- (GET_CODE (value) == LABEL_REF
- || GET_CODE (value) == CODE_LABEL
- || GET_CODE (value) == MINUS)))
+ /* ??? We only output .xword's for symbols and only then in environments
+ where the assembler can handle them. */
+ if (aligned_p && size == 8
+ && (GET_CODE (x) != CONST_INT && GET_CODE (x) != CONST_DOUBLE))
{
- if (! TARGET_V9)
+ if (TARGET_V9)
{
- ASM_OUTPUT_INT (file, const0_rtx);
- ASM_OUTPUT_INT (file, value);
+ assemble_integer_with_op ("\t.xword\t", x);
+ return true;
}
else
{
- fprintf (file, "\t%s\t", ASM_LONGLONG);
- output_addr_const (file, value);
- fprintf (file, "\n");
+ assemble_aligned_integer (4, const0_rtx);
+ assemble_aligned_integer (4, x);
+ return true;
}
}
- else
- abort ();
+ return default_assemble_integer (x, size, aligned_p);
}
/* Return the value of a code used in the .proc pseudo-op that says
@@ -5516,10 +6328,10 @@ sparc64_initialize_trampoline (tramp, fnaddr, cxt)
GEN_INT (0xca586010));
emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, 16)), cxt);
emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, 24)), fnaddr);
- emit_insn (gen_flush (validize_mem (gen_rtx_MEM (DImode, tramp))));
+ emit_insn (gen_flushdi (validize_mem (gen_rtx_MEM (DImode, tramp))));
if (sparc_cpu != PROCESSOR_ULTRASPARC)
- emit_insn (gen_flush (validize_mem (gen_rtx_MEM (DImode, plus_constant (tramp, 8)))));
+ emit_insn (gen_flushdi (validize_mem (gen_rtx_MEM (DImode, plus_constant (tramp, 8)))));
}
/* Subroutines to support a flat (single) register window calling
@@ -5743,12 +6555,12 @@ void
sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op,
doubleword_op, base_offset)
FILE *file;
- char *base_reg;
+ const char *base_reg;
unsigned int offset;
unsigned long gmask;
unsigned long fmask;
- char *word_op;
- char *doubleword_op;
+ const char *word_op;
+ const char *doubleword_op;
unsigned long base_offset;
{
int regno;
@@ -5843,14 +6655,16 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op,
/* Set up the stack and frame (if desired) for the function. */
-void
-sparc_flat_output_function_prologue (file, size)
+static void
+sparc_flat_function_prologue (file, size)
FILE *file;
- int size;
+ HOST_WIDE_INT size;
{
- char *sp_str = reg_names[STACK_POINTER_REGNUM];
+ const char *sp_str = reg_names[STACK_POINTER_REGNUM];
unsigned long gmask = current_frame_info.gmask;
+ sparc_output_scratch_registers (file);
+
/* 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",
@@ -5885,8 +6699,8 @@ sparc_flat_output_function_prologue (file, size)
if (size > 0)
{
unsigned int reg_offset = current_frame_info.reg_offset;
- char *fp_str = reg_names[FRAME_POINTER_REGNUM];
- const char *t1_str = "%g1";
+ const char *const fp_str = reg_names[FRAME_POINTER_REGNUM];
+ static const char *const t1_str = "%g1";
/* Things get a little tricky if local variables take up more than ~4096
bytes and outgoing arguments take up more than ~4096 bytes. When that
@@ -5900,25 +6714,27 @@ sparc_flat_output_function_prologue (file, size)
the gdb folk first. */
/* Is the entire register save area offsettable from %sp? */
- if (reg_offset < 4096 - 64 * UNITS_PER_WORD)
+ if (reg_offset < 4096 - 64 * (unsigned) UNITS_PER_WORD)
{
if (size <= 4096)
{
fprintf (file, "\tadd\t%s, %d, %s\n",
- sp_str, -size, sp_str);
+ sp_str, (int) -size, sp_str);
if (gmask & 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, -size, fp_str, ASM_COMMENT_START);
+ sp_str, (int) -size, fp_str, ASM_COMMENT_START);
reg_offset += 4;
}
}
else
{
- fprintf (file, "\tset\t%d, %s\n\tsub\t%s, %s, %s\n",
- size, t1_str, sp_str, t1_str, sp_str);
+ 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);
if (gmask & FRAME_POINTER_MASK)
{
fprintf (file, "\tst\t%s, [%s+%d]\n",
@@ -5958,31 +6774,33 @@ sparc_flat_output_function_prologue (file, size)
/* Subtract %sp in two steps, but make sure there is always a
64 byte register save area, and %sp is properly aligned. */
/* Amount to decrement %sp by, the first time. */
- unsigned int size1 = ((size - reg_offset + 64) + 15) & -16;
+ unsigned HOST_WIDE_INT size1 = ((size - reg_offset + 64) + 15) & -16;
/* Offset to register save area from %sp. */
- unsigned int offset = size1 - (size - reg_offset);
+ unsigned HOST_WIDE_INT offset = size1 - (size - reg_offset);
if (size1 <= 4096)
{
fprintf (file, "\tadd\t%s, %d, %s\n",
- sp_str, -size1, sp_str);
+ sp_str, (int) -size1, sp_str);
if (gmask & 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, offset, sp_str, -size1, fp_str,
- ASM_COMMENT_START);
+ fp_str, sp_str, (int) offset, sp_str, (int) -size1,
+ fp_str, ASM_COMMENT_START);
offset += 4;
}
}
else
{
- fprintf (file, "\tset\t%d, %s\n\tsub\t%s, %s, %s\n",
- size1, t1_str, sp_str, t1_str, sp_str);
+ 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);
if (gmask & 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, offset, sp_str, t1_str, fp_str,
- ASM_COMMENT_START);
+ fp_str, sp_str, (int) offset, sp_str, t1_str,
+ fp_str, ASM_COMMENT_START);
offset += 4;
}
}
@@ -6001,7 +6819,7 @@ sparc_flat_output_function_prologue (file, size)
if (gmask & RETURN_ADDR_MASK)
{
fprintf (file, "\tst\t%s, [%s+%d]\n",
- reg_names[RETURN_ADDR_REGNUM], sp_str, offset);
+ reg_names[RETURN_ADDR_REGNUM], sp_str, (int) offset);
if (dwarf2out_do_frame ())
/* offset - size1 == reg_offset - size
if reg_offset were updated above like offset. */
@@ -6012,8 +6830,10 @@ sparc_flat_output_function_prologue (file, size)
gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),
current_frame_info.fmask,
"st", "std", -size1);
- fprintf (file, "\tset\t%d, %s\n\tsub\t%s, %s, %s\n",
- size - size1, t1_str, sp_str, t1_str, sp_str);
+ 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 (dwarf2out_do_frame ())
if (! (gmask & FRAME_POINTER_MASK))
dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, size);
@@ -6024,12 +6844,12 @@ sparc_flat_output_function_prologue (file, size)
}
/* Do any necessary cleanup after a function to restore stack, frame,
- and regs. */
+ and regs. */
-void
-sparc_flat_output_function_epilogue (file, size)
+static void
+sparc_flat_function_epilogue (file, size)
FILE *file;
- int size;
+ HOST_WIDE_INT size;
{
rtx epilogue_delay = current_function_epilogue_delay_list;
int noepilogue = FALSE;
@@ -6061,18 +6881,22 @@ sparc_flat_output_function_epilogue (file, size)
if (!noepilogue)
{
- unsigned int reg_offset = current_frame_info.reg_offset;
- unsigned int size1;
- char *sp_str = reg_names[STACK_POINTER_REGNUM];
- char *fp_str = reg_names[FRAME_POINTER_REGNUM];
- const char *t1_str = "%g1";
+ unsigned HOST_WIDE_INT reg_offset = current_frame_info.reg_offset;
+ unsigned HOST_WIDE_INT size1;
+ const char *const sp_str = reg_names[STACK_POINTER_REGNUM];
+ const char *const fp_str = reg_names[FRAME_POINTER_REGNUM];
+ static const char *const t1_str = "%g1";
/* In the reload sequence, we don't need to fill the load delay
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%d, %s\n", size, t1_str);
+ {
+ fprintf (file, "\tset\t");
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, size);
+ fprintf (file, ", %s\n", t1_str);
+ }
if (frame_pointer_needed)
{
@@ -6081,11 +6905,11 @@ sparc_flat_output_function_epilogue (file, size)
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, size, sp_str, ASM_COMMENT_START);
+ fp_str, (int) size, sp_str, ASM_COMMENT_START);
}
/* Is the entire register save area offsettable from %sp? */
- if (reg_offset < 4096 - 64 * UNITS_PER_WORD)
+ if (reg_offset < 4096 - 64 * (unsigned) UNITS_PER_WORD)
{
size1 = 0;
}
@@ -6098,8 +6922,10 @@ sparc_flat_output_function_epilogue (file, size)
/* Offset to register save area from %sp. */
reg_offset = size1 - reg_offset;
- fprintf (file, "\tset\t%d, %s\n\tadd\t%s, %s, %s\n",
- size1, t1_str, sp_str, t1_str, sp_str);
+ 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);
}
/* We must restore the frame pointer and return address reg first
@@ -6107,13 +6933,13 @@ sparc_flat_output_function_epilogue (file, size)
if (current_frame_info.gmask & FRAME_POINTER_MASK)
{
fprintf (file, "\tld\t[%s+%d], %s\n",
- sp_str, reg_offset, fp_str);
+ sp_str, (int) 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, reg_offset, reg_names[RETURN_ADDR_REGNUM]);
+ sp_str, (int) reg_offset, reg_names[RETURN_ADDR_REGNUM]);
reg_offset += 4;
}
@@ -6129,8 +6955,11 @@ sparc_flat_output_function_epilogue (file, size)
{
size -= size1;
if (size > 4095)
- fprintf (file, "\tset\t%d, %s\n",
- size, t1_str);
+ {
+ fprintf (file, "\tset\t");
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, size);
+ fprintf (file, ", %s\n", t1_str);
+ }
}
if (current_function_returns_struct)
@@ -6154,7 +6983,7 @@ sparc_flat_output_function_epilogue (file, size)
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, size, sp_str);
+ fprintf (file, "\tadd\t%s, %d, %s\n", sp_str, (int) size, sp_str);
else
fprintf (file, "\tnop\n");
@@ -6183,7 +7012,7 @@ sparc_flat_epilogue_delay_slots ()
return 0;
}
-/* Return true is TRIAL is a valid insn for the epilogue delay slot.
+/* Return true if TRIAL is a valid insn for the epilogue delay slot.
Any single length instruction which doesn't reference the stack or frame
pointer is OK. */
@@ -6197,12 +7026,6 @@ sparc_flat_eligible_for_epilogue_delay (trial, slot)
if (get_attr_length (trial) != 1)
return 0;
- /* If %g0 is live, there are lots of things we can't handle.
- Rather than trying to find them all now, let's punt and only
- optimize things as necessary. */
- if (TARGET_LIVE_G0)
- return 0;
-
if (! reg_mentioned_p (stack_pointer_rtx, pat)
&& ! reg_mentioned_p (frame_pointer_rtx, pat))
return 1;
@@ -6305,7 +7128,7 @@ hypersparc_adjust_cost (insn, link, dep_insn, cost)
{
case TYPE_STORE:
case TYPE_FPSTORE:
- /* Get the delay iff the address of the store is the dependence. */
+ /* Get the delay iff the address of the store is the dependence. */
if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
return cost;
@@ -6347,7 +7170,7 @@ hypersparc_adjust_cost (insn, link, dep_insn, cost)
break;
case REG_DEP_ANTI:
- /* Anti-dependencies only penalize the fpu unit. */
+ /* Anti-dependencies only penalize the fpu unit. */
if (insn_type == TYPE_IALU || insn_type == TYPE_SHIFT)
return 0;
break;
@@ -6379,11 +7202,12 @@ ultrasparc_adjust_cost (insn, link, dep_insn, cost)
/* Nothing issues in parallel with integer multiplies, so
mark as zero cost since the scheduler can not do anything
about it. */
- if (insn_type == TYPE_IMUL)
+ if (insn_type == TYPE_IMUL || insn_type == TYPE_IDIV)
return 0;
#define SLOW_FP(dep_type) \
-(dep_type == TYPE_FPSQRT || dep_type == TYPE_FPDIVS || dep_type == TYPE_FPDIVD)
+(dep_type == TYPE_FPSQRTS || dep_type == TYPE_FPSQRTD || \
+ dep_type == TYPE_FPDIVS || dep_type == TYPE_FPDIVD)
switch (REG_NOTE_KIND (link))
{
@@ -6460,11 +7284,10 @@ ultrasparc_adjust_cost (insn, link, dep_insn, cost)
or the cycle after an instruction which writes any
integer register. Model this as cost 2 for dependent
instructions. */
- if ((dep_type == TYPE_IALU || dep_type == TYPE_UNARY
- || dep_type == TYPE_BINARY)
+ if (dep_type == TYPE_IALU
&& cost < 2)
return 2;
- /* Otherwise check as for integer conditional moves. */
+ /* Otherwise check as for integer conditional moves. */
case TYPE_CMOVE:
/* Conditional moves involving integer registers wait until
@@ -6481,7 +7304,7 @@ ultrasparc_adjust_cost (insn, link, dep_insn, cost)
break;
case REG_DEP_ANTI:
- /* Divide and square root lock destination registers for full latency. */
+ /* Divide and square root lock destination registers for full latency. */
if (! SLOW_FP (dep_type))
return 0;
break;
@@ -6510,7 +7333,7 @@ ultrasparc_adjust_cost (insn, link, dep_insn, cost)
#undef SLOW_FP
}
-int
+static int
sparc_adjust_cost(insn, link, dep, cost)
rtx insn;
rtx link;
@@ -6552,7 +7375,10 @@ enum ultra_code { NONE=0, /* no insn at all */
SINGLE, /* single issue instructions */
NUM_ULTRA_CODES };
-static const char *ultra_code_names[NUM_ULTRA_CODES] = {
+static enum ultra_code ultra_code_from_mask PARAMS ((int));
+static void ultra_schedule_insn PARAMS ((rtx *, rtx *, int, enum ultra_code));
+
+static const char *const ultra_code_names[NUM_ULTRA_CODES] = {
"NONE", "IEU0", "IEU1", "IEUN", "LSU", "CTI",
"FPM", "FPA", "SINGLE" };
@@ -6596,17 +7422,18 @@ ultra_code_from_mask (type_mask)
return IEU0;
else if (type_mask & (TMASK (TYPE_COMPARE) |
TMASK (TYPE_CALL) |
+ TMASK (TYPE_SIBCALL) |
TMASK (TYPE_UNCOND_BRANCH)))
return IEU1;
- else if (type_mask & (TMASK (TYPE_IALU) | TMASK (TYPE_BINARY) |
- TMASK (TYPE_MOVE) | TMASK (TYPE_UNARY)))
+ else if (type_mask & TMASK (TYPE_IALU))
return IEUN;
else if (type_mask & (TMASK (TYPE_LOAD) | TMASK (TYPE_SLOAD) |
TMASK (TYPE_STORE) | TMASK (TYPE_FPLOAD) |
TMASK (TYPE_FPSTORE)))
return LSU;
else if (type_mask & (TMASK (TYPE_FPMUL) | TMASK (TYPE_FPDIVS) |
- TMASK (TYPE_FPDIVD) | TMASK (TYPE_FPSQRT)))
+ TMASK (TYPE_FPDIVD) | TMASK (TYPE_FPSQRTS) |
+ TMASK (TYPE_FPSQRTD)))
return FPM;
else if (type_mask & (TMASK (TYPE_FPMOVE) | TMASK (TYPE_FPCMOVE) |
TMASK (TYPE_FP) | TMASK (TYPE_FPCMP)))
@@ -6629,7 +7456,7 @@ ultra_cmove_results_ready_p (insn)
/* If this got dispatched in the previous
group, the results are not ready. */
- entry = (ultra_cur_hist - 1) % (ULTRA_NUM_HIST - 1);
+ entry = (ultra_cur_hist - 1) & (ULTRA_NUM_HIST - 1);
up = &ultra_pipe_hist[entry];
slot = 4;
while (--slot >= 0)
@@ -6650,7 +7477,7 @@ ultra_fpmode_conflict_exists (fpmode)
int hist_ent;
int hist_lim;
- hist_ent = (ultra_cur_hist - 1) % (ULTRA_NUM_HIST - 1);
+ hist_ent = (ultra_cur_hist - 1) & (ULTRA_NUM_HIST - 1);
if (ultra_cycles_elapsed < 4)
hist_lim = ultra_cycles_elapsed;
else
@@ -6679,18 +7506,19 @@ ultra_fpmode_conflict_exists (fpmode)
continue;
/* If it is not FMOV, FABS, FNEG, FDIV, or FSQRT then
- we will get a stall. Loads and stores are independant
+ we will get a stall. Loads and stores are independent
of these rules. */
if (GET_CODE (SET_SRC (pat)) != ABS
&& GET_CODE (SET_SRC (pat)) != NEG
&& ((TMASK (get_attr_type (insn)) &
(TMASK (TYPE_FPDIVS) | TMASK (TYPE_FPDIVD) |
- TMASK (TYPE_FPMOVE) | TMASK (TYPE_FPSQRT) |
+ TMASK (TYPE_FPMOVE) | TMASK (TYPE_FPSQRTS) |
+ TMASK (TYPE_FPSQRTD) |
TMASK (TYPE_LOAD) | TMASK (TYPE_STORE))) == 0))
return 1;
}
hist_lim--;
- hist_ent = (hist_ent - 1) % (ULTRA_NUM_HIST - 1);
+ hist_ent = (hist_ent - 1) & (ULTRA_NUM_HIST - 1);
}
/* No conflicts, safe to dispatch. */
@@ -6769,8 +7597,8 @@ ultra_find_type (type_mask, list, start)
&& GET_CODE (SET_SRC (pat)) == SUBREG
&& REGNO (SUBREG_REG (SET_DEST (slot_pat))) ==
REGNO (SUBREG_REG (SET_SRC (pat)))
- && SUBREG_WORD (SET_DEST (slot_pat)) ==
- SUBREG_WORD (SET_SRC (pat)))))
+ && SUBREG_BYTE (SET_DEST (slot_pat)) ==
+ SUBREG_BYTE (SET_SRC (pat)))))
|| (check_fpmode_conflict == 1
&& GET_CODE (slot_insn) == INSN
&& GET_CODE (slot_pat) == SET
@@ -6843,6 +7671,7 @@ ultra_schedule_insn (ip, ready, this, type)
{
int pipe_slot;
char mask = ultra_pipe.free_slot_mask;
+ rtx temp;
/* Obtain free slot. */
for (pipe_slot = 0; pipe_slot < 4; pipe_slot++)
@@ -6864,44 +7693,49 @@ ultra_schedule_insn (ip, ready, this, type)
ultra_pipe.commit[pipe_slot] = 0;
/* Update ready list. */
- if (ip != &ready[this])
+ temp = *ip;
+ while (ip != &ready[this])
{
- rtx temp = *ip;
-
- *ip = ready[this];
- ready[this] = temp;
+ ip[0] = ip[1];
+ ++ip;
}
+ *ip = temp;
}
/* Advance to the next pipeline group. */
static void
ultra_flush_pipeline ()
{
- ultra_cur_hist = (ultra_cur_hist + 1) % (ULTRA_NUM_HIST - 1);
+ ultra_cur_hist = (ultra_cur_hist + 1) & (ULTRA_NUM_HIST - 1);
ultra_cycles_elapsed += 1;
- bzero ((char *) &ultra_pipe, sizeof ultra_pipe);
+ memset ((char *) &ultra_pipe, 0, sizeof ultra_pipe);
ultra_pipe.free_slot_mask = 0xf;
}
-static int ultra_reorder_called_this_block;
-
/* Init our data structures for this current block. */
-void
-ultrasparc_sched_init (dump, sched_verbose)
- FILE *dump ATTRIBUTE_UNUSED;
- int sched_verbose ATTRIBUTE_UNUSED;
+static void
+ultrasparc_sched_init ()
{
- bzero ((char *) ultra_pipe_hist, sizeof ultra_pipe_hist);
+ memset ((char *) ultra_pipe_hist, 0, sizeof ultra_pipe_hist);
ultra_cur_hist = 0;
ultra_cycles_elapsed = 0;
- ultra_reorder_called_this_block = 0;
ultra_pipe.free_slot_mask = 0xf;
}
+static void
+sparc_sched_init (dump, sched_verbose, max_ready)
+ FILE *dump ATTRIBUTE_UNUSED;
+ int sched_verbose ATTRIBUTE_UNUSED;
+ int max_ready ATTRIBUTE_UNUSED;
+{
+ if (sparc_cpu == PROCESSOR_ULTRASPARC)
+ ultrasparc_sched_init ();
+}
+
/* INSN has been scheduled, update pipeline commit state
and return how many instructions are still to be
scheduled in this group. */
-int
+static int
ultrasparc_variable_issue (insn)
rtx insn;
{
@@ -6925,6 +7759,19 @@ ultrasparc_variable_issue (insn)
return left_to_fire;
}
+static int
+sparc_variable_issue (dump, sched_verbose, insn, cim)
+ FILE *dump ATTRIBUTE_UNUSED;
+ int sched_verbose ATTRIBUTE_UNUSED;
+ rtx insn;
+ int cim;
+{
+ if (sparc_cpu == PROCESSOR_ULTRASPARC)
+ return ultrasparc_variable_issue (insn);
+ else
+ return cim - 1;
+}
+
/* In actual_hazard_this_instance, we may have yanked some
instructions from the ready list due to conflict cost
adjustments. If so, and such an insn was in our pipeline
@@ -6974,7 +7821,7 @@ ultra_rescan_pipeline_state (ready, n_ready)
}
}
-void
+static void
ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
FILE *dump;
int sched_verbose;
@@ -6984,14 +7831,6 @@ ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
struct ultrasparc_pipeline_state *up = &ultra_pipe;
int i, this_insn;
- /* We get called once unnecessarily per block of insns
- scheduled. */
- if (ultra_reorder_called_this_block == 0)
- {
- ultra_reorder_called_this_block = 1;
- return;
- }
-
if (sched_verbose)
{
int n;
@@ -7063,7 +7902,7 @@ ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
{
/* If the pipeline is (still) empty and we have any single
group insns, get them out now as this is a good time. */
- rtx *ip = ultra_find_type ((TMASK (TYPE_RETURN) | TMASK (TYPE_ADDRESS) |
+ rtx *ip = ultra_find_type ((TMASK (TYPE_RETURN) | TMASK (TYPE_IDIV) |
TMASK (TYPE_IMUL) | TMASK (TYPE_CMOVE) |
TMASK (TYPE_MULTI) | TMASK (TYPE_MISC)),
ready, this_insn);
@@ -7076,6 +7915,7 @@ ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
/* If we are not in the process of emptying out the pipe, try to
obtain an instruction which must be the first in it's group. */
ip = ultra_find_type ((TMASK (TYPE_CALL) |
+ TMASK (TYPE_SIBCALL) |
TMASK (TYPE_CALL_NO_DELAY_SLOT) |
TMASK (TYPE_UNCOND_BRANCH)),
ready, this_insn);
@@ -7086,7 +7926,8 @@ ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
}
else if ((ip = ultra_find_type ((TMASK (TYPE_FPDIVS) |
TMASK (TYPE_FPDIVD) |
- TMASK (TYPE_FPSQRT)),
+ TMASK (TYPE_FPSQRTS) |
+ TMASK (TYPE_FPSQRTD)),
ready, this_insn)) != 0)
{
ultra_schedule_insn (ip, ready, this_insn, FPM);
@@ -7115,8 +7956,7 @@ ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
if ((up->free_slot_mask & 0x7) != 0
&& up->num_ieu_insns < 2)
{
- rtx *ip = ultra_find_type ((TMASK (TYPE_IALU) | TMASK (TYPE_BINARY) |
- TMASK (TYPE_MOVE) | TMASK (TYPE_UNARY) |
+ rtx *ip = ultra_find_type ((TMASK (TYPE_IALU) |
(up->contents[IEU1] == 0 ? TMASK (TYPE_COMPARE) : 0)),
ready, this_insn);
if (ip)
@@ -7137,8 +7977,7 @@ ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
&& up->num_ieu_insns < 2)
{
rtx *ip;
- int tmask = (TMASK (TYPE_IALU) | TMASK (TYPE_BINARY) |
- TMASK (TYPE_MOVE) | TMASK (TYPE_UNARY));
+ int tmask = TMASK (TYPE_IALU);
if (!up->contents[IEU1])
tmask |= TMASK (TYPE_COMPARE);
@@ -7234,7 +8073,7 @@ ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
}
else
{
- bzero ((char *) &ultra_pipe, sizeof ultra_pipe);
+ memset ((char *) &ultra_pipe, 0, sizeof ultra_pipe);
ultra_pipe.free_slot_mask = 0xf;
}
}
@@ -7266,7 +8105,20 @@ ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
}
}
-int
+static int
+sparc_sched_reorder (dump, sched_verbose, ready, n_readyp, clock)
+ FILE *dump;
+ int sched_verbose;
+ rtx *ready;
+ int *n_readyp;
+ int clock ATTRIBUTE_UNUSED;
+{
+ if (sparc_cpu == PROCESSOR_ULTRASPARC)
+ ultrasparc_sched_reorder (dump, sched_verbose, ready, *n_readyp);
+ return sparc_issue_rate ();
+}
+
+static int
sparc_issue_rate ()
{
switch (sparc_cpu)
@@ -7287,14 +8139,14 @@ sparc_issue_rate ()
}
static int
-set_extends(x, insn)
- rtx x, insn;
+set_extends (insn)
+ rtx insn;
{
register rtx pat = PATTERN (insn);
switch (GET_CODE (SET_SRC (pat)))
{
- /* Load and some shift instructions zero extend. */
+ /* Load and some shift instructions zero extend. */
case MEM:
case ZERO_EXTEND:
/* sethi clears the high bits */
@@ -7312,33 +8164,46 @@ set_extends(x, insn)
return 1;
case AND:
{
+ rtx op0 = XEXP (SET_SRC (pat), 0);
rtx op1 = XEXP (SET_SRC (pat), 1);
if (GET_CODE (op1) == CONST_INT)
return INTVAL (op1) >= 0;
- if (GET_CODE (XEXP (SET_SRC (pat), 0)) == REG
- && sparc_check_64 (XEXP (SET_SRC (pat), 0), insn) == 1)
- return 1;
- if (GET_CODE (op1) == REG
- && sparc_check_64 ((op1), insn) == 1)
+ if (GET_CODE (op0) != REG)
+ return 0;
+ if (sparc_check_64 (op0, insn) == 1)
return 1;
+ return (GET_CODE (op1) == REG && sparc_check_64 (op1, insn) == 1);
+ }
+ case IOR:
+ case XOR:
+ {
+ rtx op0 = XEXP (SET_SRC (pat), 0);
+ rtx op1 = XEXP (SET_SRC (pat), 1);
+ if (GET_CODE (op0) != REG || sparc_check_64 (op0, insn) <= 0)
+ return 0;
+ if (GET_CODE (op1) == CONST_INT)
+ return INTVAL (op1) >= 0;
+ return (GET_CODE (op1) == REG && sparc_check_64 (op1, insn) == 1);
}
case ASHIFT:
case LSHIFTRT:
return GET_MODE (SET_SRC (pat)) == SImode;
- /* Positive integers leave the high bits zero. */
+ /* Positive integers leave the high bits zero. */
case CONST_DOUBLE:
- return ! (CONST_DOUBLE_LOW (x) & 0x80000000);
+ return ! (CONST_DOUBLE_LOW (SET_SRC (pat)) & 0x80000000);
case CONST_INT:
- return ! (INTVAL (x) & 0x80000000);
+ return ! (INTVAL (SET_SRC (pat)) & 0x80000000);
case ASHIFTRT:
case SIGN_EXTEND:
return - (GET_MODE (SET_SRC (pat)) == SImode);
+ case REG:
+ return sparc_check_64 (SET_SRC (pat), insn);
default:
return 0;
}
}
-/* We _ought_ to have only one kind per function, but... */
+/* We _ought_ to have only one kind per function, but... */
static rtx sparc_addr_diff_list;
static rtx sparc_addr_list;
@@ -7454,10 +8319,16 @@ sparc_check_64 (x, insn)
the single set and return the correct value or fail to recognize
it and return 0. */
int set_once = 0;
+ rtx y = x;
+
+ if (GET_CODE (x) != REG)
+ abort ();
- if (GET_CODE (x) == REG
- && flag_expensive_optimizations
- && REG_N_SETS (REGNO (x)) == 1)
+ if (GET_MODE (x) == DImode)
+ y = gen_rtx_REG (SImode, REGNO (x) + WORDS_BIG_ENDIAN);
+
+ if (flag_expensive_optimizations
+ && REG_N_SETS (REGNO (y)) == 1)
set_once = 1;
if (insn == 0)
@@ -7487,8 +8358,10 @@ sparc_check_64 (x, insn)
if (GET_CODE (pat) != SET)
return 0;
if (rtx_equal_p (x, SET_DEST (pat)))
- return set_extends (x, insn);
- if (reg_overlap_mentioned_p (SET_DEST (pat), x))
+ return set_extends (insn);
+ if (y && rtx_equal_p (y, SET_DEST (pat)))
+ return set_extends (insn);
+ if (reg_overlap_mentioned_p (SET_DEST (pat), y))
return 0;
}
}
@@ -7500,7 +8373,7 @@ char *
sparc_v8plus_shift (operands, insn, opcode)
rtx *operands;
rtx insn;
- char *opcode;
+ const char *opcode;
{
static char asm_code[60];
@@ -7508,25 +8381,25 @@ sparc_v8plus_shift (operands, insn, opcode)
operands[3] = operands[0];
if (GET_CODE (operands[1]) == CONST_INT)
{
- output_asm_insn ("mov %1,%3", operands);
+ output_asm_insn ("mov\t%1, %3", operands);
}
else
{
- output_asm_insn ("sllx %H1,32,%3", operands);
+ output_asm_insn ("sllx\t%H1, 32, %3", operands);
if (sparc_check_64 (operands[1], insn) <= 0)
- output_asm_insn ("srl %L1,0,%L1", operands);
- output_asm_insn ("or %L1,%3,%3", operands);
+ output_asm_insn ("srl\t%L1, 0, %L1", operands);
+ output_asm_insn ("or\t%L1, %3, %3", operands);
}
strcpy(asm_code, opcode);
if (which_alternative != 2)
- return strcat (asm_code, " %0,%2,%L0\n\tsrlx %L0,32,%H0");
+ return strcat (asm_code, "\t%0, %2, %L0\n\tsrlx\t%L0, 32, %H0");
else
- return strcat (asm_code, " %3,%2,%3\n\tsrlx %3,32,%H0\n\tmov %3,%L0");
+ return strcat (asm_code, "\t%3, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0");
}
-/* Return 1 if DEST and SRC reference only global and in registers. */
+/* Return 1 if DEST and SRC reference only global and in registers. */
int
sparc_return_peephole_ok (dest, src)
@@ -7559,289 +8432,82 @@ sparc_function_profiler (file, labelno)
ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
if (! TARGET_ARCH64)
- fputs ("\tst\t%g2,[%fp-4]\n", file);
+ fputs ("\tst\t%g2, [%fp-4]\n", file);
fputs ("\tsethi\t%hi(", file);
assemble_name (file, buf);
- fputs ("),%o0\n", file);
+ fputs ("), %o0\n", file);
fputs ("\tcall\t", file);
assemble_name (file, MCOUNT_FUNCTION);
putc ('\n', file);
- fputs ("\t or\t%o0,%lo(", file);
+ fputs ("\t or\t%o0, %lo(", file);
assemble_name (file, buf);
- fputs ("),%o0\n", file);
+ fputs ("), %o0\n", file);
if (! TARGET_ARCH64)
- fputs ("\tld\t[%fp-4],%g2\n", file);
+ fputs ("\tld\t[%fp-4], %g2\n", file);
}
-/* The following macro shall output assembler code to FILE
- to initialize basic-block profiling.
-
- If profile_block_flag == 2
-
- Output code to call the subroutine `__bb_init_trace_func'
- and pass two parameters to it. The first parameter is
- the address of a block allocated in the object module.
- The second parameter is the number of the first basic block
- of the function.
+/* Mark ARG, which is really a struct ultrasparc_pipline_state *, for
+ GC. */
- The name of the block is a local symbol made with this statement:
-
- ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0);
-
- Of course, since you are writing the definition of
- `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you
- can take a short cut in the definition of this macro and use the
- name that you know will result.
-
- The number of the first basic block of the function is
- passed to the macro in BLOCK_OR_LABEL.
-
- If described in a virtual assembler language the code to be
- output looks like:
-
- parameter1 <- LPBX0
- parameter2 <- BLOCK_OR_LABEL
- call __bb_init_trace_func
-
- else if profile_block_flag != 0
-
- Output code to call the subroutine `__bb_init_func'
- and pass one single parameter to it, which is the same
- as the first parameter to `__bb_init_trace_func'.
-
- The first word of this parameter is a flag which will be nonzero if
- the object module has already been initialized. So test this word
- first, and do not call `__bb_init_func' if the flag is nonzero.
- Note: When profile_block_flag == 2 the test need not be done
- but `__bb_init_trace_func' *must* be called.
-
- BLOCK_OR_LABEL may be used to generate a label number as a
- branch destination in case `__bb_init_func' will not be called.
-
- If described in a virtual assembler language the code to be
- output looks like:
-
- cmp (LPBX0),0
- jne local_label
- parameter1 <- LPBX0
- call __bb_init_func
- local_label:
-
-*/
-
-void
-sparc_function_block_profiler(file, block_or_label)
- FILE *file;
- int block_or_label;
+static void
+mark_ultrasparc_pipeline_state (arg)
+ void *arg;
{
- char LPBX[32];
- ASM_GENERATE_INTERNAL_LABEL (LPBX, "LPBX", 0);
-
- if (profile_block_flag == 2)
- {
- fputs ("\tsethi\t%hi(", file);
- assemble_name (file, LPBX);
- fputs ("),%o0\n", file);
-
- fprintf (file, "\tsethi\t%%hi(%d),%%o1\n", block_or_label);
-
- fputs ("\tor\t%o0,%lo(", file);
- assemble_name (file, LPBX);
- fputs ("),%o0\n", file);
-
- fprintf (file, "\tcall\t%s__bb_init_trace_func\n", user_label_prefix);
-
- fprintf (file, "\t or\t%%o1,%%lo(%d),%%o1\n", block_or_label);
- }
- else if (profile_block_flag != 0)
- {
- char LPBY[32];
- ASM_GENERATE_INTERNAL_LABEL (LPBY, "LPBY", block_or_label);
-
- fputs ("\tsethi\t%hi(", file);
- assemble_name (file, LPBX);
- fputs ("),%o0\n", file);
-
- fputs ("\tld\t[%lo(", file);
- assemble_name (file, LPBX);
- fputs (")+%o0],%o1\n", file);
-
- fputs ("\ttst\t%o1\n", file);
-
- if (TARGET_V9)
- {
- fputs ("\tbne,pn\t%icc,", file);
- assemble_name (file, LPBY);
- putc ('\n', file);
- }
- else
- {
- fputs ("\tbne\t", file);
- assemble_name (file, LPBY);
- putc ('\n', file);
- }
-
- fputs ("\t or\t%o0,%lo(", file);
- assemble_name (file, LPBX);
- fputs ("),%o0\n", file);
+ struct ultrasparc_pipeline_state *ups;
+ size_t i;
- fprintf (file, "\tcall\t%s__bb_init_func\n\t nop\n", user_label_prefix);
-
- ASM_OUTPUT_INTERNAL_LABEL (file, "LPBY", block_or_label);
- }
+ ups = (struct ultrasparc_pipeline_state *) arg;
+ for (i = 0; i < sizeof (ups->group) / sizeof (rtx); ++i)
+ ggc_mark_rtx (ups->group[i]);
}
-/* The following macro shall output assembler code to FILE
- to increment a counter associated with basic block number BLOCKNO.
-
- If profile_block_flag == 2
-
- Output code to initialize the global structure `__bb' and
- call the function `__bb_trace_func' which will increment the
- counter.
-
- `__bb' consists of two words. In the first word the number
- of the basic block has to be stored. In the second word
- the address of a block allocated in the object module
- has to be stored.
-
- The basic block number is given by BLOCKNO.
-
- The address of the block is given by the label created with
+/* Called to register all of our global variables with the garbage
+ collector. */
- ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0);
-
- by FUNCTION_BLOCK_PROFILER.
-
- Of course, since you are writing the definition of
- `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you
- can take a short cut in the definition of this macro and use the
- name that you know will result.
-
- If described in a virtual assembler language the code to be
- output looks like:
-
- move BLOCKNO -> (__bb)
- move LPBX0 -> (__bb+4)
- call __bb_trace_func
-
- Note that function `__bb_trace_func' must not change the
- machine state, especially the flag register. To grant
- this, you must output code to save and restore registers
- either in this macro or in the macros MACHINE_STATE_SAVE
- and MACHINE_STATE_RESTORE. The last two macros will be
- used in the function `__bb_trace_func', so you must make
- sure that the function prologue does not change any
- register prior to saving it with MACHINE_STATE_SAVE.
-
- else if profile_block_flag != 0
-
- Output code to increment the counter directly.
- Basic blocks are numbered separately from zero within each
- compiled object module. The count associated with block number
- BLOCKNO is at index BLOCKNO in an array of words; the name of
- this array is a local symbol made with this statement:
-
- ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 2);
-
- Of course, since you are writing the definition of
- `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you
- can take a short cut in the definition of this macro and use the
- name that you know will result.
-
- If described in a virtual assembler language, the code to be
- output looks like:
-
- inc (LPBX2+4*BLOCKNO)
-
-*/
-
-void
-sparc_block_profiler(file, blockno)
- FILE *file;
- int blockno;
+static void
+sparc_add_gc_roots ()
{
- char LPBX[32];
-
- if (profile_block_flag == 2)
- {
- ASM_GENERATE_INTERNAL_LABEL (LPBX, "LPBX", 0);
-
- fprintf (file, "\tsethi\t%%hi(%s__bb),%%g1\n", user_label_prefix);
- fprintf (file, "\tsethi\t%%hi(%d),%%g2\n", blockno);
- fprintf (file, "\tor\t%%g1,%%lo(%s__bb),%%g1\n", user_label_prefix);
- fprintf (file, "\tor\t%%g2,%%lo(%d),%%g2\n", blockno);
-
- fputs ("\tst\t%g2,[%g1]\n", file);
-
- fputs ("\tsethi\t%hi(", file);
- assemble_name (file, LPBX);
- fputs ("),%g2\n", file);
-
- fputs ("\tor\t%g2,%lo(", file);
- assemble_name (file, LPBX);
- fputs ("),%g2\n", file);
-
- fputs ("\tst\t%g2,[%g1+4]\n", file);
- fputs ("\tmov\t%o7,%g2\n", file);
-
- fprintf (file, "\tcall\t%s__bb_trace_func\n\t nop\n", user_label_prefix);
+ ggc_add_rtx_root (&sparc_compare_op0, 1);
+ ggc_add_rtx_root (&sparc_compare_op1, 1);
+ ggc_add_rtx_root (&leaf_label, 1);
+ ggc_add_rtx_root (&global_offset_table, 1);
+ ggc_add_rtx_root (&get_pc_symbol, 1);
+ ggc_add_rtx_root (&sparc_addr_diff_list, 1);
+ ggc_add_rtx_root (&sparc_addr_list, 1);
+ ggc_add_root (ultra_pipe_hist, ARRAY_SIZE (ultra_pipe_hist),
+ sizeof (ultra_pipe_hist[0]), &mark_ultrasparc_pipeline_state);
+}
- fputs ("\tmov\t%g2,%o7\n", file);
- }
- else if (profile_block_flag != 0)
+#ifdef OBJECT_FORMAT_ELF
+static void
+sparc_elf_asm_named_section (name, flags)
+ const char *name;
+ unsigned int flags;
+{
+ if (flags & SECTION_MERGE)
{
- ASM_GENERATE_INTERNAL_LABEL (LPBX, "LPBX", 2);
-
- fputs ("\tsethi\t%hi(", file);
- assemble_name (file, LPBX);
- fprintf (file, "+%d),%%g1\n", blockno*4);
-
- fputs ("\tld\t[%g1+%lo(", file);
- assemble_name (file, LPBX);
- fprintf (file, "+%d)],%%g2\n", blockno*4);
-
- fputs ("\tadd\t%g2,1,%g2\n", file);
-
- fputs ("\tst\t%g2,[%g1+%lo(", file);
- assemble_name (file, LPBX);
- fprintf (file, "+%d)]\n", blockno*4);
+ /* entsize cannot be expressed in this section attributes
+ encoding style. */
+ default_elf_asm_named_section (name, flags);
+ return;
}
-}
-
-/* The following macro shall output assembler code to FILE
- to indicate a return from function during basic-block profiling.
- If profile_block_flag == 2:
+ fprintf (asm_out_file, "\t.section\t\"%s\"", name);
- Output assembler code to call function `__bb_trace_ret'.
+ if (!(flags & SECTION_DEBUG))
+ fputs (",#alloc", asm_out_file);
+ if (flags & SECTION_WRITE)
+ fputs (",#write", asm_out_file);
+ if (flags & SECTION_CODE)
+ fputs (",#execinstr", asm_out_file);
- Note that function `__bb_trace_ret' must not change the
- machine state, especially the flag register. To grant
- this, you must output code to save and restore registers
- either in this macro or in the macros MACHINE_STATE_SAVE_RET
- and MACHINE_STATE_RESTORE_RET. The last two macros will be
- used in the function `__bb_trace_ret', so you must make
- sure that the function prologue does not change any
- register prior to saving it with MACHINE_STATE_SAVE_RET.
+ /* ??? Handle SECTION_BSS. */
- else if profile_block_flag != 0:
-
- The macro will not be used, so it need not distinguish
- these cases.
-*/
-
-void
-sparc_function_block_profiler_exit(file)
- FILE *file;
-{
- if (profile_block_flag == 2)
- fprintf (file, "\tcall\t%s__bb_trace_ret\n\t nop\n", user_label_prefix);
- else
- abort ();
+ fputc ('\n', asm_out_file);
}
+#endif /* OBJECT_FORMAT_ELF */
diff --git a/contrib/gcc/config/sparc/sparc.h b/contrib/gcc/config/sparc/sparc.h
index ad11d74..608b393 100644
--- a/contrib/gcc/config/sparc/sparc.h
+++ b/contrib/gcc/config/sparc/sparc.h
@@ -1,5 +1,6 @@
/* Definitions of target machine for GNU compiler, for Sun SPARC.
- Copyright (C) 1987, 88, 89, 92, 94-98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1989, 1992, 1994, 1995, 1996, 1997, 1998, 1999
+ 2000, 2001, 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.
@@ -33,28 +34,28 @@ Boston, MA 02111-1307, USA. */
/* TARGET_ARCH{32,64} are the main macros to decide which of the two
architectures to compile for. We allow targets to choose compile time or
runtime selection. */
-#ifdef SPARC_BI_ARCH
#ifdef IN_LIBGCC2
-#if defined(__sparcv9) || defined(__sparcv_v9) || defined(__arch64__)
+#if defined(__sparcv9) || defined(__arch64__)
#define TARGET_ARCH32 0
#else
#define TARGET_ARCH32 1
-#endif /* V9 sparc */
+#endif /* sparc64 */
#else
+#ifdef SPARC_BI_ARCH
#define TARGET_ARCH32 (! TARGET_64BIT)
-#endif /* IN_LIBGCC2 */
#else
#define TARGET_ARCH32 (DEFAULT_ARCH32_P)
#endif /* SPARC_BI_ARCH */
+#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 v8 code.
+ 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 v8 abi.
+ to imply a v7/8 abi.
TARGET_CM_MEDLOW: 32 bit address space, top 32 bits = 0,
avoid generating %uhi and %ulo terms,
@@ -97,7 +98,7 @@ extern enum cmodel sparc_cmodel;
#define TARGET_CM_MEDANY (sparc_cmodel == CM_MEDANY)
#define TARGET_CM_EMBMEDANY (sparc_cmodel == CM_EMBMEDANY)
-#define SPARC_DEFAULT_CMODEL CM_MEDLOW
+#define SPARC_DEFAULT_CMODEL CM_32
/* This is call-clobbered in the normal ABI, but is reserved in the
home grown (aka upward compatible) embedded ABI. */
@@ -173,8 +174,8 @@ extern enum cmodel sparc_cmodel;
#endif
#if TARGET_CPU_DEFAULT == TARGET_CPU_sparclite86x
-#define CPP_CPU32_DEFAULT_SPEC "-D__sparclite86x__ -D__sparc_v8__"
-#define ASM_CPU32_DEFAULT_SPEC "-Av8"
+#define CPP_CPU32_DEFAULT_SPEC "-D__sparclite86x__"
+#define ASM_CPU32_DEFAULT_SPEC "-Asparclite"
#endif
#endif
@@ -209,19 +210,12 @@ Unrecognized value in TARGET_CPU_DEFAULT.
#endif /* !SPARC_BI_ARCH */
-/* 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 -Dsun -Dunix -Asystem(unix) -Asystem(bsd)"
-
/* Define macros to distinguish architectures. */
/* Common CPP definitions used by CPP_SPEC amongst the various targets
for handling -mcpu=xxx switches. */
#define CPP_CPU_SPEC "\
+%{msoft-float:-D_SOFT_FLOAT} \
%{mcypress:} \
%{msparclite:-D__sparclite__} \
%{mf930:-D__sparclite__} %{mf934:-D__sparclite__} \
@@ -233,7 +227,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
%{mcpu=v8:-D__sparc_v8__} \
%{mcpu=supersparc:-D__supersparc__ -D__sparc_v8__} \
%{mcpu=hypersparc:-D__hypersparc__ -D__sparc_v8__} \
-%{mcpu=sparclite86x:-D__sparclite86x__ -D__sparc_v8__} \
+%{mcpu=sparclite86x:-D__sparclite86x__} \
%{mcpu=v9:-D__sparc_v9__} \
%{mcpu=ultrasparc:-D__sparc_v9__} \
%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_cpu_default)}}}}}}} \
@@ -248,14 +242,14 @@ Unrecognized value in TARGET_CPU_DEFAULT.
#ifdef SPARC_BI_ARCH
#define CPP_ARCH32_SPEC "-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int \
--D__GCC_NEW_VARARGS__ -Acpu(sparc) -Amachine(sparc)"
+-D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc"
#define CPP_ARCH64_SPEC "-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int \
--D__arch64__ -Acpu(sparc64) -Amachine(sparc64)"
+-D__arch64__ -Acpu=sparc64 -Amachine=sparc64"
#else
-#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 "-D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc"
+#define CPP_ARCH64_SPEC "-D__arch64__ -Acpu=sparc64 -Amachine=sparc64"
#endif
@@ -297,6 +291,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
%{msparclite:-Asparclite} \
%{mf930:-Asparclite} %{mf934:-Asparclite} \
%{mcpu=sparclite:-Asparclite} \
+%{mcpu=sparclite86x:-Asparclite} \
%{mcpu=f930:-Asparclite} %{mcpu=f934:-Asparclite} \
%{mv8plus:-Av8plus} \
%{mcpu=v9:-Av9} \
@@ -308,7 +303,11 @@ Unrecognized value in TARGET_CPU_DEFAULT.
This is what GAS uses. Add %(asm_arch) to ASM_SPEC to enable. */
#define ASM_ARCH32_SPEC "-32"
+#ifdef HAVE_AS_REGISTER_PSEUDO_OP
+#define ASM_ARCH64_SPEC "-64 -no-undeclared-regs"
+#else
#define ASM_ARCH64_SPEC "-64"
+#endif
#define ASM_ARCH_DEFAULT_SPEC \
(DEFAULT_ARCH32_P ? ASM_ARCH32_SPEC : ASM_ARCH64_SPEC)
@@ -318,20 +317,17 @@ Unrecognized value in TARGET_CPU_DEFAULT.
%{!m32:%{!m64:%(asm_arch_default)}} \
"
+#ifdef HAVE_AS_RELAX_OPTION
+#define ASM_RELAX_SPEC "%{!mno-relax:-relax}"
+#else
+#define ASM_RELAX_SPEC ""
+#endif
+
/* 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} \
-%(asm_cpu) \
-"
-
-#define LIB_SPEC "%{!shared:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} %{g:-lg}}"
-
-/* Provide required defaults for linker -e and -d switches. */
-
-#define LINK_SPEC \
- "%{!shared:%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp} %{static:-Bstatic} \
- %{assert*} %{shared:%{!mimpure-text:-assert pure-text}}"
+%(asm_cpu) %(asm_relax)"
/* This macro defines names of additional specifications to put in the specs
that can be used in various specifications like CC1_SPEC. Its definition
@@ -356,6 +352,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
{ "asm_cpu_default", ASM_CPU_DEFAULT_SPEC }, \
{ "asm_arch32", ASM_ARCH32_SPEC }, \
{ "asm_arch64", ASM_ARCH64_SPEC }, \
+ { "asm_relax", ASM_RELAX_SPEC }, \
{ "asm_arch_default", ASM_ARCH_DEFAULT_SPEC },\
{ "asm_arch", ASM_ARCH_SPEC }, \
SUBTARGET_EXTRA_SPECS
@@ -381,15 +378,13 @@ Unrecognized value in TARGET_CPU_DEFAULT.
code into the rtl. Also, if we are profiling, we cannot eliminate
the frame pointer (because the return address will get smashed). */
-void sparc_override_options ();
-
#define OVERRIDE_OPTIONS \
do { \
- if (profile_flag || profile_block_flag || profile_arc_flag) \
+ if (profile_flag || profile_arc_flag) \
{ \
if (flag_pic) \
{ \
- const char *pic_string = (flag_pic == 1) ? "-fpic" : "-fPIC";\
+ const char *const pic_string = (flag_pic == 1) ? "-fpic" : "-fPIC";\
warning ("%s and profiling conflict: disabling %s", \
pic_string, pic_string); \
flag_pic = 0; \
@@ -403,16 +398,6 @@ void sparc_override_options ();
/* This is meant to be redefined in the host dependent files. */
#define SUBTARGET_OVERRIDE_OPTIONS
-/* These compiler options take an argument. We ignore -target for now. */
-
-#define WORD_SWITCH_TAKES_ARG(STR) \
- (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \
- || !strcmp (STR, "target") || !strcmp (STR, "assert"))
-
-/* Print subsidiary information on the compiler version in use. */
-
-#define TARGET_VERSION fprintf (stderr, " (sparc)");
-
/* Generate DBX debugging information. */
#define DBX_DEBUGGING_INFO
@@ -425,7 +410,7 @@ extern int target_flags;
#define MASK_FPU 1
#define TARGET_FPU (target_flags & MASK_FPU)
-/* Nonzero if we should use FUNCTION_EPILOGUE. Otherwise, we
+/* Nonzero if we should use function_epilogue(). Otherwise, we
use fast return insns, but lose some generality. */
#define MASK_EPILOGUE 2
#define TARGET_EPILOGUE (target_flags & MASK_EPILOGUE)
@@ -500,8 +485,7 @@ extern int target_flags;
/* 0x2000, 0x4000 are unused */
-/* Nonzero if pointers are 64 bits.
- At the moment it must follow architecture size flag. */
+/* Nonzero if pointers are 64 bits. */
#define MASK_PTR64 0x8000
#define TARGET_PTR64 (target_flags & MASK_PTR64)
@@ -518,20 +502,7 @@ extern int target_flags;
#define MASK_STACK_BIAS 0x80000
#define TARGET_STACK_BIAS (target_flags & MASK_STACK_BIAS)
-/* Non-zero means %g0 is a normal register.
- We still clobber it as necessary, but we can't rely on it always having
- a zero value.
- We don't bother to support this in true 64 bit mode. */
-#define MASK_LIVE_G0 0x100000
-#define TARGET_LIVE_G0 (target_flags & MASK_LIVE_G0)
-
-/* Non-zero means the cpu has broken `save' and `restore' insns, only
- the trivial versions work (save %g0,%g0,%g0; restore %g0,%g0,%g0).
- We assume the environment will properly handle or otherwise avoid
- trouble associated with an interrupt occurring after the `save' or trap
- occurring during it. */
-#define MASK_BROKEN_SAVERESTORE 0x200000
-#define TARGET_BROKEN_SAVERESTORE (target_flags & MASK_BROKEN_SAVERESTORE)
+/* 0x100000,0x200000 unused */
/* Non-zero means -m{,no-}fpu was passed on the command line. */
#define MASK_FPU_SET 0x400000
@@ -542,11 +513,19 @@ extern int target_flags;
#define TARGET_VIS (target_flags & MASK_VIS)
/* Compile for Solaris V8+. 32 bit Solaris preserves the high bits of
- the current out and global registers. Linux saves the high bits on
- context switches but not signals. */
-#define MASK_V8PLUS 0x2000000
+ the current out and global registers and Linux 2.2+ as well. */
+#define MASK_V8PLUS 0x2000000
#define TARGET_V8PLUS (target_flags & MASK_V8PLUS)
+/* Force a the fastest alignment on structures to take advantage of
+ faster copies. */
+#define MASK_FASTER_STRUCTS 0x4000000
+#define TARGET_FASTER_STRUCTS (target_flags & MASK_FASTER_STRUCTS)
+
+/* Use IEEE quad long double. */
+#define MASK_LONG_DOUBLE_128 0x8000000
+#define TARGET_LONG_DOUBLE_128 (target_flags & MASK_LONG_DOUBLE_128)
+
/* TARGET_HARD_MUL: Use hardware multiply instructions but not %y.
TARGET_HARD_MUL32: Use hardware multiply instructions with rd %y
to get high 32 bits. False in V8+ or V9 because multiply stores
@@ -555,7 +534,7 @@ extern int target_flags;
#define TARGET_HARD_MUL32 \
((TARGET_V8 || TARGET_SPARCLITE \
|| TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS) \
- && ! TARGET_V8PLUS)
+ && ! TARGET_V8PLUS && TARGET_ARCH32)
#define TARGET_HARD_MUL \
(TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET \
@@ -569,42 +548,82 @@ extern int target_flags;
An empty string NAME is used to identify the default VALUE. */
#define TARGET_SWITCHES \
- { {"fpu", MASK_FPU | MASK_FPU_SET, "Use hardware fp" }, \
- {"no-fpu", -MASK_FPU, "Do not use hardware fp" }, \
- {"no-fpu", MASK_FPU_SET, "Do not use hardware fp" }, \
- {"hard-float", MASK_FPU | MASK_FPU_SET, "Use hardware fp" }, \
- {"soft-float", -MASK_FPU, "Do not use hardware fp" }, \
- {"soft-float", MASK_FPU_SET, "Do not use hardware fp" }, \
- {"epilogue", MASK_EPILOGUE, "Use FUNCTION_EPILOGUE" }, \
- {"no-epilogue", -MASK_EPILOGUE, "Do not use FUNCTION_EPILOGUE" }, \
- {"unaligned-doubles", MASK_UNALIGNED_DOUBLES, "Assume possible double misalignment" },\
- {"no-unaligned-doubles", -MASK_UNALIGNED_DOUBLES, "Assume all doubles are aligned" }, \
- {"impure-text", MASK_IMPURE_TEXT, "Pass -assert pure-text to linker" }, \
- {"no-impure-text", -MASK_IMPURE_TEXT, "Do not pass -assert pure-text to linker" }, \
- {"flat", MASK_FLAT, "Use flat register window model" }, \
- {"no-flat", -MASK_FLAT, "Do not use flat register window model" }, \
- {"app-regs", MASK_APP_REGS, "Use ABI reserved registers" }, \
- {"no-app-regs", -MASK_APP_REGS, "Do not use ABI reserved registers" }, \
- {"hard-quad-float", MASK_HARD_QUAD, "Use hardware quad fp instructions" }, \
- {"soft-quad-float", -MASK_HARD_QUAD, "Do not use hardware quad fp instructions" }, \
- {"v8plus", MASK_V8PLUS, "Compile for v8plus ABI" }, \
- {"no-v8plus", -MASK_V8PLUS, "Do not compile for v8plus ABI" }, \
- {"vis", MASK_VIS, "Utilize Visual Instruction Set" }, \
- {"no-vis", -MASK_VIS, "Do not utilize Visual Instruction Set" }, \
+ { {"fpu", MASK_FPU | MASK_FPU_SET, \
+ N_("Use hardware fp") }, \
+ {"no-fpu", -MASK_FPU, \
+ N_("Do not use hardware fp") }, \
+ {"no-fpu", MASK_FPU_SET, NULL, }, \
+ {"hard-float", MASK_FPU | MASK_FPU_SET, \
+ N_("Use hardware fp") }, \
+ {"soft-float", -MASK_FPU, \
+ N_("Do not use hardware fp") }, \
+ {"soft-float", MASK_FPU_SET, NULL }, \
+ {"epilogue", MASK_EPILOGUE, \
+ N_("Use function_epilogue()") }, \
+ {"no-epilogue", -MASK_EPILOGUE, \
+ N_("Do not use function_epilogue()") }, \
+ {"unaligned-doubles", MASK_UNALIGNED_DOUBLES, \
+ N_("Assume possible double misalignment") }, \
+ {"no-unaligned-doubles", -MASK_UNALIGNED_DOUBLES, \
+ N_("Assume all doubles are aligned") }, \
+ {"impure-text", MASK_IMPURE_TEXT, \
+ N_("Pass -assert pure-text to linker") }, \
+ {"no-impure-text", -MASK_IMPURE_TEXT, \
+ N_("Do not pass -assert pure-text to linker") }, \
+ {"flat", MASK_FLAT, \
+ N_("Use flat register window model") }, \
+ {"no-flat", -MASK_FLAT, \
+ N_("Do not use flat register window model") }, \
+ {"app-regs", MASK_APP_REGS, \
+ N_("Use ABI reserved registers") }, \
+ {"no-app-regs", -MASK_APP_REGS, \
+ N_("Do not use ABI reserved registers") }, \
+ {"hard-quad-float", MASK_HARD_QUAD, \
+ N_("Use hardware quad fp instructions") }, \
+ {"soft-quad-float", -MASK_HARD_QUAD, \
+ N_("Do not use hardware quad fp instructions") }, \
+ {"v8plus", MASK_V8PLUS, \
+ N_("Compile for v8plus ABI") }, \
+ {"no-v8plus", -MASK_V8PLUS, \
+ N_("Do not compile for v8plus ABI") }, \
+ {"vis", MASK_VIS, \
+ N_("Utilize Visual Instruction Set") }, \
+ {"no-vis", -MASK_VIS, \
+ N_("Do not utilize Visual Instruction Set") }, \
/* ??? These are deprecated, coerced to -mcpu=. Delete in 2.9. */ \
- {"cypress", 0, "Optimize for Cypress processors" }, \
- {"sparclite", 0, "Optimize for SparcLite processors" }, \
- {"f930", 0, "Optimize for F930 processors" }, \
- {"f934", 0, "Optimize for F934 processors" }, \
- {"v8", 0, "Use V8 Sparc ISA" }, \
- {"supersparc", 0, "Optimize for SuperSparc processors" }, \
- /* End of deprecated options. */ \
- {"ptr64", MASK_PTR64, "Pointers are 64-bit" }, \
- {"ptr32", -MASK_PTR64, "Pointers are 32-bit" }, \
- {"32", -MASK_64BIT, "Use 32-bit ABI" }, \
- {"64", MASK_64BIT, "Use 64-bit ABI" }, \
- {"stack-bias", MASK_STACK_BIAS, "Use stack bias" }, \
- {"no-stack-bias", -MASK_STACK_BIAS, "Do not use stack bias" }, \
+ {"cypress", 0, \
+ N_("Optimize for Cypress processors") }, \
+ {"sparclite", 0, \
+ N_("Optimize for SparcLite processors") }, \
+ {"f930", 0, \
+ N_("Optimize for F930 processors") }, \
+ {"f934", 0, \
+ N_("Optimize for F934 processors") }, \
+ {"v8", 0, \
+ N_("Use V8 Sparc ISA") }, \
+ {"supersparc", 0, \
+ N_("Optimize for SuperSparc processors") }, \
+ /* End of deprecated options. */ \
+ {"ptr64", MASK_PTR64, \
+ N_("Pointers are 64-bit") }, \
+ {"ptr32", -MASK_PTR64, \
+ N_("Pointers are 32-bit") }, \
+ {"32", -MASK_64BIT, \
+ N_("Use 32-bit ABI") }, \
+ {"64", MASK_64BIT, \
+ N_("Use 64-bit ABI") }, \
+ {"stack-bias", MASK_STACK_BIAS, \
+ N_("Use stack bias") }, \
+ {"no-stack-bias", -MASK_STACK_BIAS, \
+ N_("Do not use stack bias") }, \
+ {"faster-structs", MASK_FASTER_STRUCTS, \
+ N_("Use structs on stronger alignment for double-word copies") }, \
+ {"no-faster-structs", -MASK_FASTER_STRUCTS, \
+ N_("Do not use structs on stronger alignment for double-word copies") }, \
+ {"relax", 0, \
+ N_("Optimize tail call instructions in assembler and linker") }, \
+ {"no-relax", 0, \
+ N_("Do not optimize tail call instructions in assembler or linker") }, \
SUBTARGET_SWITCHES \
{ "", TARGET_DEFAULT, ""}}
@@ -641,32 +660,15 @@ extern enum processor_type sparc_cpu;
Every file includes us, but not every file includes insn-attr.h. */
#define sparc_cpu_attr ((enum attr_cpu) sparc_cpu)
-/* This macro is similar to `TARGET_SWITCHES' but defines names of
- command options that have values. Its definition is an
- initializer with a subgrouping for each command option.
-
- Each subgrouping contains a string constant, that defines the
- fixed part of the option name, and the address of a variable.
- The variable, type `char *', is set to the variable part of the
- given option if the fixed part matches. The actual option name
- is made by appending `-m' to the specified name.
-
- Here is an example which defines `-mshort-data-NUMBER'. If the
- given option is `-mshort-data-512', the variable `m88k_short_data'
- will be set to the string `"512"'.
-
- extern char *m88k_short_data;
- #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } */
-
#define TARGET_OPTIONS \
-{ \
- { "cpu=", &sparc_select[1].string, "Use features of and schedule code for given CPU" }, \
- { "tune=", &sparc_select[2].string, "Schedule code for given CPU" }, \
- { "cmodel=", &sparc_cmodel_string, "Use given Sparc code model" }, \
- { "align-loops=", &sparc_align_loops_string, "Loop code aligned to this power of 2" }, \
- { "align-jumps=", &sparc_align_jumps_string, "Jump targets are aligned to this power of 2" }, \
- { "align-functions=", &sparc_align_funcs_string, "Function starts are aligned to this power of 2" }, \
- SUBTARGET_OPTIONS \
+{ \
+ { "cpu=", &sparc_select[1].string, \
+ N_("Use features of and schedule code for given CPU") }, \
+ { "tune=", &sparc_select[2].string, \
+ N_("Schedule code for given CPU") }, \
+ { "cmodel=", &sparc_cmodel_string, \
+ N_("Use given Sparc code model") }, \
+ SUBTARGET_OPTIONS \
}
/* This is meant to be redefined in target specific files. */
@@ -676,24 +678,12 @@ extern enum processor_type sparc_cpu;
struct sparc_cpu_select
{
const char *string;
- const char *name;
- int set_tune_p;
- int set_arch_p;
+ const char *const name;
+ const int set_tune_p;
+ const int set_arch_p;
};
extern struct sparc_cpu_select sparc_select[];
-
-/* Variables to record values the user passes. */
-extern const char *sparc_align_loops_string;
-extern const char *sparc_align_jumps_string;
-extern const char *sparc_align_funcs_string;
-/* Parsed values as a power of two. */
-extern int sparc_align_loops;
-extern int sparc_align_jumps;
-extern int sparc_align_funcs;
-
-#define DEFAULT_SPARC_ALIGN_FUNCS \
-(sparc_cpu == PROCESSOR_ULTRASPARC ? 5 : 2)
/* target machine storage layout */
@@ -743,7 +733,7 @@ extern int sparc_align_funcs;
#define FLOAT_TYPE_SIZE 32
#define DOUBLE_TYPE_SIZE 64
-#if defined (SPARC_BI_ARCH)
+#ifdef SPARC_BI_ARCH
#define MAX_LONG_TYPE_SIZE 64
#endif
@@ -759,6 +749,11 @@ extern int sparc_align_funcs;
See also the macro `Pmode' defined below. */
#define POINTER_SIZE (TARGET_PTR64 ? 64 : 32)
+/* If we have to extend pointers (only when TARGET_ARCH64 and not
+ TARGET_PTR64), we want to do it unsigned. This macro does nothing
+ if ptr_mode and Pmode are the same. */
+#define POINTERS_EXTEND_UNSIGNED 1
+
/* A macro to update MODE and UNSIGNEDP when an object whose type
is TYPE and which has the specified mode and signedness is to be
stored in a register. This macro is only called when TYPE is a
@@ -767,9 +762,7 @@ extern int sparc_align_funcs;
if (TARGET_ARCH64 \
&& GET_MODE_CLASS (MODE) == MODE_INT \
&& GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \
-{ \
- (MODE) = DImode; \
-}
+ (MODE) = DImode;
/* Define this macro if the promotion described by PROMOTE_MODE
should also be done for outgoing function arguments. */
@@ -787,6 +780,18 @@ if (TARGET_ARCH64 \
for this value. */
#define PROMOTE_FUNCTION_RETURN
+/* Define this macro if the promotion described by PROMOTE_MODE
+ should _only_ be performed for outgoing function arguments or
+ function return values, as specified by PROMOTE_FUNCTION_ARGS
+ and PROMOTE_FUNCTION_RETURN, respectively. */
+/* This is only needed for TARGET_ARCH64, but since PROMOTE_MODE is a no-op
+ for TARGET_ARCH32 this is ok. Otherwise we'd need to add a runtime test
+ for this value. For TARGET_ARCH64 we need it, as we don't have instructions
+ for arithmetic operations which do zero/sign extension at the same time,
+ so without this we end up with a srl/sra after every assignment to an
+ user variable, which means very very bad code. */
+#define PROMOTE_FOR_CALL_ONLY
+
/* Allocation boundary (in *bits*) for storing arguments in argument list. */
#define PARM_BOUNDARY (TARGET_ARCH64 ? 64 : 32)
@@ -799,7 +804,7 @@ if (TARGET_ARCH64 \
(TARGET_ARCH64 ? (((LOC)+15) & ~15) : (((LOC)+7) & ~7))
/* Allocation boundary (in *bits*) for the code of a function. */
-#define FUNCTION_BOUNDARY (1 << (sparc_align_funcs + 3))
+#define FUNCTION_BOUNDARY 32
/* Alignment of field after `int : 0' in a structure. */
#define EMPTY_FIELD_BOUNDARY (TARGET_ARCH64 ? 64 : 32)
@@ -816,6 +821,23 @@ if (TARGET_ARCH64 \
/* The best alignment to use in cases where we have a choice. */
#define FASTEST_ALIGNMENT 64
+/* Define this macro as an expression for the alignment of a structure
+ (given by STRUCT as a tree node) if the alignment computed in the
+ usual way is COMPUTED and the alignment explicitly specified was
+ SPECIFIED.
+
+ The default is to use SPECIFIED if it is larger; otherwise, use
+ the smaller of COMPUTED and `BIGGEST_ALIGNMENT' */
+#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED) \
+ (TARGET_FASTER_STRUCTS ? \
+ ((TREE_CODE (STRUCT) == RECORD_TYPE \
+ || TREE_CODE (STRUCT) == UNION_TYPE \
+ || TREE_CODE (STRUCT) == QUAL_UNION_TYPE) \
+ && TYPE_FIELDS (STRUCT) != 0 \
+ ? MAX (MAX ((COMPUTED), (SPECIFIED)), BIGGEST_ALIGNMENT) \
+ : MAX ((COMPUTED), (SPECIFIED))) \
+ : MAX ((COMPUTED), (SPECIFIED)))
+
/* Make strings word-aligned so strcpy from constants will be faster. */
#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
((TREE_CODE (EXP) == STRING_CST \
@@ -846,44 +868,14 @@ if (TARGET_ARCH64 \
#define SUNOS4_SHARED_LIBRARIES 0
#endif
-/* This is defined differently for v9 in a cover file. */
-#define SELECT_SECTION(T,RELOC) \
-{ \
- if (TREE_CODE (T) == VAR_DECL) \
- { \
- if (TREE_READONLY (T) && ! TREE_SIDE_EFFECTS (T) \
- && DECL_INITIAL (T) \
- && (DECL_INITIAL (T) == error_mark_node \
- || TREE_CONSTANT (DECL_INITIAL (T))) \
- && DECL_ALIGN (T) <= MAX_TEXT_ALIGN \
- && ! (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES))) \
- text_section (); \
- else \
- data_section (); \
- } \
- else if (TREE_CODE (T) == CONSTRUCTOR) \
- { \
- if (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES)) \
- data_section (); \
- } \
- else if (TREE_CODE_CLASS (TREE_CODE (T)) == 'c') \
- { \
- if ((TREE_CODE (T) == STRING_CST && flag_writable_strings) \
- || TYPE_ALIGN (TREE_TYPE (T)) > MAX_TEXT_ALIGN \
- || (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES))) \
- data_section (); \
- else \
- text_section (); \
- } \
-}
/* Use text section for a constant
unless we need more alignment than that offers. */
/* This is defined differently for v9 in a cover file. */
-#define SELECT_RTX_SECTION(MODE, X) \
+#define SELECT_RTX_SECTION(MODE, X, ALIGN) \
{ \
if (GET_MODE_BITSIZE (MODE) <= MAX_TEXT_ALIGN \
- && ! (flag_pic && (symbolic_operand (X) || SUNOS4_SHARED_LIBRARIES))) \
+ && ! (flag_pic && (symbolic_operand ((X), (MODE)) || SUNOS4_SHARED_LIBRARIES))) \
text_section (); \
else \
data_section (); \
@@ -955,7 +947,7 @@ if (TARGET_ARCH64 \
*/
#define FIXED_REGISTERS \
- {1, 0, 0, 0, 0, 0, 1, 1, \
+ {1, 0, 2, 2, 2, 2, 1, 1, \
0, 0, 0, 0, 0, 0, 1, 0, \
0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 1, 1, \
@@ -1008,12 +1000,12 @@ do \
fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
} \
- if (TARGET_ARCH32) \
- { \
- fixed_regs[5] = 1; \
- } \
- if (TARGET_LIVE_G0) \
- fixed_regs[0] = 0; \
+ /* If the user has passed -f{fixed,call-{used,saved}}-g5 */ \
+ /* then honour it. */ \
+ if (TARGET_ARCH32 && fixed_regs[5]) \
+ fixed_regs[5] = 1; \
+ else if (TARGET_ARCH64 && fixed_regs[5] == 2) \
+ fixed_regs[5] = 0; \
if (! TARGET_V9) \
{ \
int regno; \
@@ -1033,25 +1025,26 @@ do \
for (regno = 32; regno < SPARC_LAST_V9_FCC_REG; regno++) \
fixed_regs[regno] = 1; \
} \
- /* Don't unfix g2-g4 if they were fixed with -ffixed-. */ \
- fixed_regs[2] |= ! TARGET_APP_REGS; \
- fixed_regs[3] |= ! TARGET_APP_REGS; \
- fixed_regs[4] |= ! TARGET_APP_REGS || TARGET_CM_EMBMEDANY; \
+ /* If the user has passed -f{fixed,call-{used,saved}}-g2 */ \
+ /* then honour it. Likewise with g3 and g4. */ \
+ if (fixed_regs[2] == 2) \
+ fixed_regs[2] = ! TARGET_APP_REGS; \
+ if (fixed_regs[3] == 2) \
+ fixed_regs[3] = ! TARGET_APP_REGS; \
+ if (TARGET_ARCH32 && fixed_regs[4] == 2) \
+ fixed_regs[4] = ! TARGET_APP_REGS; \
+ else if (TARGET_CM_EMBMEDANY) \
+ fixed_regs[4] = 1; \
+ else if (fixed_regs[4] == 2) \
+ fixed_regs[4] = 0; \
if (TARGET_FLAT) \
{ \
/* Let the compiler believe the frame pointer is still \
%fp, but output it as %i7. */ \
fixed_regs[31] = 1; \
reg_names[FRAME_POINTER_REGNUM] = "%i7"; \
- /* ??? This is a hack to disable leaf functions. */ \
- global_regs[7] = 1; \
- } \
- if (profile_block_flag) \
- { \
- /* %g1 and %g2 must be fixed, because BLOCK_PROFILER \
- uses them. */ \
- fixed_regs[1] = 1; \
- fixed_regs[2] = 1; \
+ /* Disable leaf functions */ \
+ memset (sparc_leaf_regs, 0, FIRST_PSEUDO_REGISTER); \
} \
} \
while (0)
@@ -1074,25 +1067,19 @@ while (0)
: (GET_MODE_SIZE (MODE) + 3) / 4) \
: ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
-/* A subreg in 64 bit mode will have the wrong offset for a floating point
- register. The least significant part is at offset 1, compared to 0 for
- integer registers. This only applies when FMODE is a larger mode.
- We also need to handle a special case of TF-->DF conversions. */
-#define ALTER_HARD_SUBREG(TMODE, WORD, FMODE, REGNO) \
- (TARGET_ARCH64 \
- && (REGNO) >= SPARC_FIRST_FP_REG \
- && (REGNO) <= SPARC_LAST_V9_FP_REG \
- && (TMODE) == SImode \
- && !((FMODE) == QImode || (FMODE) == HImode) \
- ? ((REGNO) + 1) \
- : ((TMODE) == DFmode && (FMODE) == TFmode) \
- ? ((REGNO) + ((WORD) * 2)) \
- : ((REGNO) + (WORD)))
+/* Due to the ARCH64 descrepancy above we must override this next
+ macro too. */
+#define REGMODE_NATURAL_SIZE(MODE) \
+ ((TARGET_ARCH64 && FLOAT_MODE_P (MODE)) ? 4 : UNITS_PER_WORD)
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
See sparc.c for how we initialize this. */
-extern int *hard_regno_mode_classes;
+extern const int *hard_regno_mode_classes;
extern int sparc_mode_class[];
+
+/* ??? Because of the funny way we pass parameters we should allow certain
+ ??? types of float/complex values to be in integer registers during
+ ??? RTL generation. This only matters on arch32. */
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
((hard_regno_mode_classes[REGNO] & sparc_mode_class[MODE]) != 0)
@@ -1178,8 +1165,6 @@ extern int sparc_mode_class[];
#define PIC_OFFSET_TABLE_REGNUM 23
-#define FINALIZE_PIC finalize_pic ()
-
/* Pick a default value we can notice from override_options:
!v9: Default is on.
v9: Default is off. */
@@ -1197,7 +1182,7 @@ extern int sparc_mode_class[];
|| TYPE_MODE (TYPE) == TFmode \
|| TYPE_MODE (TYPE) == TCmode) \
: (TYPE_MODE (TYPE) == BLKmode \
- && int_size_in_bytes (TYPE) > 32))
+ && (unsigned HOST_WIDE_INT) int_size_in_bytes (TYPE) > 32))
/* Functions which return large structures get the address
to place the wanted value at offset 64 from the frame.
@@ -1210,15 +1195,14 @@ extern int sparc_mode_class[];
#define STRUCT_VALUE \
(TARGET_ARCH64 \
? 0 \
- : gen_rtx_MEM (Pmode, \
- gen_rtx_PLUS (Pmode, stack_pointer_rtx, \
- GEN_INT (STRUCT_VALUE_OFFSET))))
+ : gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx, \
+ STRUCT_VALUE_OFFSET)))
+
#define STRUCT_VALUE_INCOMING \
- (TARGET_ARCH64 \
- ? 0 \
- : gen_rtx_MEM (Pmode, \
- gen_rtx_PLUS (Pmode, frame_pointer_rtx, \
- GEN_INT (STRUCT_VALUE_OFFSET))))
+ (TARGET_ARCH64 \
+ ? 0 \
+ : gen_rtx_MEM (Pmode, plus_constant (frame_pointer_rtx, \
+ STRUCT_VALUE_OFFSET)))
/* Define the classes of registers for register constraints in the
machine description. Also define ranges of constants.
@@ -1280,7 +1264,7 @@ enum reg_class { NO_REGS, FPCC_REGS, I64_REGS, GENERAL_REGS, FP_REGS,
#define N_REG_CLASSES (int) LIM_REG_CLASSES
-/* Give names of register classes as strings for dump file. */
+/* Give names of register classes as strings for dump file. */
#define REG_CLASS_NAMES \
{ "NO_REGS", "FPCC_REGS", "I64_REGS", "GENERAL_REGS", "FP_REGS", \
@@ -1301,7 +1285,7 @@ enum reg_class { NO_REGS, FPCC_REGS, I64_REGS, GENERAL_REGS, FP_REGS,
reg number REGNO. This could be a conditional expression
or could index an array. */
-extern enum reg_class sparc_regno_reg_class[];
+extern enum reg_class sparc_regno_reg_class[FIRST_PSEUDO_REGISTER];
#define REGNO_REG_CLASS(REGNO) sparc_regno_reg_class[(REGNO)]
@@ -1329,11 +1313,12 @@ extern enum reg_class sparc_regno_reg_class[];
1, 4, 5, 6, 7, 0, 14, 30}
/* This is the order in which to allocate registers for
- leaf functions. If all registers can fit in the "i" registers,
+ leaf functions. If all registers can fit in the "gi" registers,
then we have the possibility of having a leaf function. */
#define REG_LEAF_ALLOC_ORDER \
{ 2, 3, 24, 25, 26, 27, 28, 29, \
+ 4, 5, 6, 7, 1, \
15, 8, 9, 10, 11, 12, 13, \
16, 17, 18, 19, 20, 21, 22, 23, \
34, 35, 36, 37, 38, 39, \
@@ -1346,32 +1331,14 @@ extern enum reg_class sparc_regno_reg_class[];
88, 89, 90, 91, 92, 93, 94, 95, \
32, 33, \
96, 97, 98, 99, 100, \
- 1, 4, 5, 6, 7, 0, 14, 30, 31}
-
+ 0, 14, 30, 31}
+
#define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc ()
-/* ??? %g7 is not a leaf register to effectively #undef LEAF_REGISTERS when
- -mflat is used. Function only_leaf_regs_used will return 0 if a global
- register is used and is not permitted in a leaf function. We make %g7
- a global reg if -mflat and voila. Since %g7 is a system register and is
- fixed it won't be used by gcc anyway. */
+extern char sparc_leaf_regs[];
+#define LEAF_REGISTERS sparc_leaf_regs
-#define LEAF_REGISTERS \
-{ 1, 1, 1, 1, 1, 1, 1, 0, \
- 0, 0, 0, 0, 0, 0, 1, 0, \
- 0, 0, 0, 0, 0, 0, 0, 0, \
- 1, 1, 1, 1, 1, 1, 0, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1}
-
-extern char leaf_reg_remap[];
+extern const char leaf_reg_remap[];
#define LEAF_REG_REMAP(REGNO) (leaf_reg_remap[REGNO])
/* The class value for index registers, and the one for base regs. */
@@ -1386,7 +1353,7 @@ extern char leaf_reg_remap[];
.md file for v8 and v9.
'd' and 'b' are used for single and double precision VIS operations,
if TARGET_VIS.
- 'h' is used for V8+ 64 bit global and out registers. */
+ 'h' is used for V8+ 64 bit global and out registers. */
#define REG_CLASS_FROM_LETTER(C) \
(TARGET_V9 \
@@ -1423,7 +1390,8 @@ extern char leaf_reg_remap[];
/* 13 bit immediate, considering only the low 32 bits */
#define SMALL_INT32(X) (SPARC_SIMM13_P ((int)INTVAL (X) & 0xffffffff))
#define SPARC_SETHI_P(X) \
-(((unsigned HOST_WIDE_INT) (X) & ~(unsigned HOST_WIDE_INT) 0xfffffc00) == 0)
+(((unsigned HOST_WIDE_INT) (X) & \
+ (TARGET_ARCH64 ? ~(unsigned HOST_WIDE_INT) 0xfffffc00 : 0x3ff)) == 0)
#define CONST_OK_FOR_LETTER_P(VALUE, C) \
((C) == 'I' ? SPARC_SIMM13_P (VALUE) \
@@ -1437,16 +1405,19 @@ extern char leaf_reg_remap[];
Here VALUE is the CONST_DOUBLE rtx itself. */
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
- ((C) == 'G' ? fp_zero_operand (VALUE) \
- : (C) == 'H' ? arith_double_operand (VALUE, DImode) \
+ ((C) == 'G' ? fp_zero_operand (VALUE, GET_MODE (VALUE)) \
+ : (C) == 'H' ? arith_double_operand (VALUE, DImode) \
: 0)
/* Given an rtx X being reloaded into a reg required to be
in class CLASS, return the class of reg to actually use.
In general this is just CLASS; but on some machines
in some cases it is preferable to use a more restrictive class. */
-/* - We can't load constants into FP registers. We can't load any FP
- constant if an 'E' constraint fails to match it.
+/* - We can't load constants into FP registers.
+ - We can't load FP constants into integer registers when soft-float,
+ because there is no soft-float pattern with a r/F constraint.
+ - We can't load FP constants into integer registers for TFmode unless
+ it is 0.0L, because there is no movtf pattern with a r/F constraint.
- Try and reload integer constants (symbolic or otherwise) back into
registers directly, rather than having them dumped to memory. */
@@ -1454,8 +1425,9 @@ extern char leaf_reg_remap[];
(CONSTANT_P (X) \
? ((FP_REG_CLASS_P (CLASS) \
|| (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
- && (HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT \
- || HOST_BITS_PER_INT != BITS_PER_WORD))) \
+ && ! TARGET_FPU) \
+ || (GET_MODE (X) == TFmode \
+ && ! fp_zero_operand (X, TFmode))) \
? NO_REGS \
: (!FP_REG_CLASS_P (CLASS) \
&& GET_MODE_CLASS (GET_MODE (X)) == MODE_INT) \
@@ -1512,8 +1484,8 @@ extern char leaf_reg_remap[];
#define SECONDARY_MEMORY_NEEDED_RTX(MODE) \
(get_frame_size () == 0 \
? assign_stack_local (MODE, GET_MODE_SIZE (MODE), 0) \
- : gen_rtx_MEM (MODE, gen_rtx_PLUS (Pmode, frame_pointer_rtx, \
- GEN_INT (STARTING_FRAME_OFFSET))))
+ : gen_rtx_MEM (MODE, plus_constant (frame_pointer_rtx, \
+ STARTING_FRAME_OFFSET)))
/* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on v9
because the movsi and movsf patterns don't handle r/f moves.
@@ -1579,14 +1551,16 @@ extern char leaf_reg_remap[];
(TARGET_ARCH64 ? (SPARC_STACK_BIAS + 16 * UNITS_PER_WORD) \
: (STRUCT_VALUE_OFFSET + UNITS_PER_WORD))
-/* Offset from the argument pointer register value to the CFA. */
+/* Offset from the argument pointer register value to the CFA.
+ This is different from FIRST_PARM_OFFSET because the register window
+ comes between the CFA and the arguments. */
-#define ARG_POINTER_CFA_OFFSET SPARC_STACK_BIAS
+#define ARG_POINTER_CFA_OFFSET(FNDECL) SPARC_STACK_BIAS
/* When a parameter is passed in a register, stack space is still
allocated for it.
!v9: All 6 possible integer registers have backing store allocated.
- v9: Only space for the arguments passed is allocated. */
+ v9: Only space for the arguments passed is allocated. */
/* ??? Ideally, we'd use zero here (as the minimum), but zero has special
meaning to the backend. Further, we need to be able to detect if a
varargs/unprototyped function is called, as they may want to spill more
@@ -1598,7 +1572,7 @@ extern char leaf_reg_remap[];
This is both an optimization and a necessity: longjmp
doesn't behave itself when the stack pointer moves within
the function! */
-#define ACCUMULATE_OUTGOING_ARGS
+#define ACCUMULATE_OUTGOING_ARGS 1
/* Value is the number of bytes of arguments automatically
popped when returning from a subroutine call.
@@ -1629,7 +1603,7 @@ extern char leaf_reg_remap[];
? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 8) \
: 8)
-/* ??? FIXME -- seems wrong for v9 structure passing... */
+/* ??? FIXME -- seems wrong for v9 structure passing... */
#define BASE_INCOMING_ARG_REG(MODE) \
(TARGET_ARCH64 \
? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 \
@@ -1652,6 +1626,13 @@ extern char leaf_reg_remap[];
#define OUTGOING_REGNO(IN) \
((TARGET_FLAT || (IN) < 24 || (IN) > 31) ? (IN) : (IN) - 16)
+/* Define this macro if the target machine has register windows. This
+ C expression returns true if the register is call-saved but is in the
+ register window. */
+
+#define LOCAL_REGNO(REGNO) \
+ (TARGET_FLAT ? 0 : (REGNO) >= 16 && (REGNO) <= 31)
+
/* Define how to find the value returned by a function.
VALTYPE is the data type of the value (as a tree).
If the precise function being called is known, FUNC is its FUNCTION_DECL;
@@ -1659,7 +1640,6 @@ extern char leaf_reg_remap[];
/* On SPARC the value is found in the first "output" register. */
-extern struct rtx_def *function_value ();
#define FUNCTION_VALUE(VALTYPE, FUNC) \
function_value ((VALTYPE), TYPE_MODE (VALTYPE), 1)
@@ -1718,7 +1698,6 @@ struct sparc_args {
for a call to a function whose data type is FNTYPE.
For a library call, FNTYPE is 0. */
-extern void init_cumulative_args ();
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
init_cumulative_args (& (CUM), (FNTYPE), (LIBNAME), (INDIRECT));
@@ -1726,10 +1705,16 @@ init_cumulative_args (& (CUM), (FNTYPE), (LIBNAME), (INDIRECT));
of mode MODE and data type TYPE.
TYPE is null for libcalls where that information may not be available. */
-extern void function_arg_advance ();
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
function_arg_advance (& (CUM), (MODE), (TYPE), (NAMED))
+/* Nonzero if we do not know how to pass TYPE solely in registers. */
+
+#define MUST_PASS_IN_STACK(MODE,TYPE) \
+ ((TYPE) != 0 \
+ && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \
+ || TREE_ADDRESSABLE (TYPE)))
+
/* Determine where to put an argument to a function.
Value is zero to push the argument on the stack,
or a hard register in which to store the argument.
@@ -1743,7 +1728,6 @@ function_arg_advance (& (CUM), (MODE), (TYPE), (NAMED))
NAMED is nonzero if this argument is a named parameter
(otherwise it is an extra parameter matching an ellipsis). */
-extern struct rtx_def *function_arg ();
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
function_arg (& (CUM), (MODE), (TYPE), (NAMED), 0)
@@ -1757,7 +1741,6 @@ function_arg (& (CUM), (MODE), (TYPE), (NAMED), 1)
this is the number of registers used.
For args passed entirely in registers or entirely in memory, zero. */
-extern int function_arg_partial_nregs ();
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
function_arg_partial_nregs (& (CUM), (MODE), (TYPE), (NAMED))
@@ -1767,7 +1750,6 @@ function_arg_partial_nregs (& (CUM), (MODE), (TYPE), (NAMED))
The pointer is passed in whatever way is appropriate for passing a pointer
to that type. */
-extern int function_arg_pass_by_reference ();
#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
function_arg_pass_by_reference (& (CUM), (MODE), (TYPE), (NAMED))
@@ -1796,13 +1778,6 @@ function_arg_padding ((MODE), (TYPE))
extern struct rtx_def *sparc_compare_op0, *sparc_compare_op1;
-/* Define the function that build the compare insn for scc and bcc. */
-
-extern struct rtx_def *gen_compare_reg ();
-
-/* This function handles all v9 scc insns */
-
-extern int gen_v9_scc ();
/* Generate the special assembly code needed to tell the assembler whatever
it might need to know about the return value of a function.
@@ -1814,34 +1789,44 @@ extern int gen_v9_scc ();
#define ASM_DECLARE_RESULT(FILE, RESULT) \
fprintf ((FILE), "\t.proc\t0%lo\n", sparc_type_code (TREE_TYPE (RESULT)))
-/* Output the label for a function definition. */
+/* Output the special assembly code needed to tell the assembler some
+ register is used as global register variable.
-#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+ SPARC 64bit psABI declares registers %g2 and %g3 as application
+ registers and %g6 and %g7 as OS registers. Any object using them
+ should declare (for %g2/%g3 has to, for %g6/%g7 can) that it uses them
+ and how they are used (scratch or some global variable).
+ Linker will then refuse to link together objects which use those
+ registers incompatibly.
+
+ Unless the registers are used for scratch, two different global
+ registers cannot be declared to the same name, so in the unlikely
+ case of a global register variable occupying more than one register
+ we prefix the second and following registers with .gnu.part1. etc. */
+
+extern char sparc_hard_reg_printed[8];
+
+#ifdef HAVE_AS_REGISTER_PSEUDO_OP
+#define ASM_DECLARE_REGISTER_GLOBAL(FILE, DECL, REGNO, NAME) \
do { \
- ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
- ASM_OUTPUT_LABEL (FILE, NAME); \
+ if (TARGET_ARCH64) \
+ { \
+ int end = HARD_REGNO_NREGS ((REGNO), DECL_MODE (decl)) + (REGNO); \
+ int reg; \
+ for (reg = (REGNO); reg < 8 && reg < end; reg++) \
+ if ((reg & ~1) == 2 || (reg & ~1) == 6) \
+ { \
+ if (reg == (REGNO)) \
+ fprintf ((FILE), "\t.register\t%%g%d, %s\n", reg, (NAME)); \
+ else \
+ fprintf ((FILE), "\t.register\t%%g%d, .gnu.part%d.%s\n", \
+ reg, reg - (REGNO), (NAME)); \
+ sparc_hard_reg_printed[reg] = 1; \
+ } \
+ } \
} while (0)
+#endif
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-/* On SPARC, move-double insns between fpu and cpu need an 8-byte block
- of memory. If any fpu reg is used in the function, we allocate
- such a block here, at the bottom of the frame, just in case it's needed.
-
- If this function is a leaf procedure, then we may choose not
- to do a "save" insn. The decision about whether or not
- to do this is made in regclass.c. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
- (TARGET_FLAT ? sparc_flat_output_function_prologue (FILE, (int)SIZE) \
- : output_function_prologue (FILE, (int)SIZE, \
- current_function_uses_only_leaf_regs))
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
@@ -1852,165 +1837,16 @@ do { \
/* Set the name of the mcount function for the system. */
#define MCOUNT_FUNCTION "*mcount"
-
-/* The following macro shall output assembler code to FILE
- to initialize basic-block profiling. */
-
-#define FUNCTION_BLOCK_PROFILER(FILE, BLOCK_OR_LABEL) \
- sparc_function_block_profiler(FILE, BLOCK_OR_LABEL)
-
-/* The following macro shall output assembler code to FILE
- to increment a counter associated with basic block number BLOCKNO. */
-
-#define BLOCK_PROFILER(FILE, BLOCKNO) \
- sparc_block_profiler (FILE, BLOCKNO)
-
-/* The following macro shall output assembler code to FILE
- to indicate a return from function during basic-block profiling. */
-
-#define FUNCTION_BLOCK_PROFILER_EXIT(FILE) \
- sparc_function_block_profiler_exit(FILE)
-
-/* The function `__bb_trace_func' is called in every basic block
- and is not allowed to change the machine state. Saving (restoring)
- the state can either be done in the BLOCK_PROFILER macro,
- before calling function (rsp. after returning from function)
- `__bb_trace_func', or it can be done inside the function by
- defining the macros:
-
- MACHINE_STATE_SAVE(ID)
- MACHINE_STATE_RESTORE(ID)
-
- In the latter case care must be taken, that the prologue code
- of function `__bb_trace_func' does not already change the
- state prior to saving it with MACHINE_STATE_SAVE.
-
- The parameter `ID' is a string identifying a unique macro use.
-
- On sparc it is sufficient to save the psw register to memory.
- Unfortunately the psw register can be read in supervisor mode only,
- so we read only the condition codes by using branch instructions
- and hope that this is enough. */
-
-#define MACHINE_STATE_SAVE(ID) \
- int ms_flags, ms_saveret; \
- asm volatile( \
- "mov %%g0,%0\n\
- be,a LFLGNZ"ID"\n\
- or %0,4,%0\n\
-LFLGNZ"ID":\n\
- bcs,a LFLGNC"ID"\n\
- or %0,1,%0\n\
-LFLGNC"ID":\n\
- bvs,a LFLGNV"ID"\n\
- or %0,2,%0\n\
-LFLGNV"ID":\n\
- bneg,a LFLGNN"ID"\n\
- or %0,8,%0\n\
-LFLGNN"ID":\n\
- mov %%g2,%1" \
- : "=r"(ms_flags), "=r"(ms_saveret));
-
-/* On sparc MACHINE_STATE_RESTORE restores the psw register from memory.
- The psw register can be written in supervisor mode only,
- which is true even for simple condition codes.
- We use some combination of instructions to produce the
- proper condition codes, but some flag combinations can not
- be generated in this way. If this happens an unimplemented
- instruction will be executed to abort the program. */
-
-#define MACHINE_STATE_RESTORE(ID) \
-{ extern char flgtab[] __asm__("LFLGTAB"ID); \
- int scratch; \
- asm volatile ( \
- "jmpl %2+%1,%%g0\n\
- ! Do part of VC in the delay slot here, as it needs 3 insns.\n\
- addcc 2,%3,%%g0\n\
-LFLGTAB" ID ":\n\
- ! 0\n\
- ba LFLGRET"ID"\n\
- orcc 1,%%g0,%%g0\n\
- ! C\n\
- ba LFLGRET"ID"\n\
- addcc 2,%3,%%g0\n\
- ! V\n\
- unimp\n\
- nop\n\
- ! VC\n\
- ba LFLGRET"ID"\n\
- addxcc %4,%4,%0\n\
- ! Z\n\
- ba LFLGRET"ID"\n\
- subcc %%g0,%%g0,%%g0\n\
- ! ZC\n\
- ba LFLGRET"ID"\n\
- addcc 1,%3,%0\n\
- ! ZVC\n\
- ba LFLGRET"ID"\n\
- addcc %4,%4,%0\n\
- ! N\n\
- ba LFLGRET"ID"\n\
- orcc %%g0,-1,%%g0\n\
- ! NC\n\
- ba LFLGRET"ID"\n\
- addcc %%g0,%3,%%g0\n\
- ! NV\n\
- unimp\n\
- nop\n\
- ! NVC\n\
- unimp\n\
- nop\n\
- ! NZ\n\
- unimp\n\
- nop\n\
- ! NZC\n\
- unimp\n\
- nop\n\
- ! NZV\n\
- unimp\n\
- nop\n\
- ! NZVC\n\
- unimp\n\
- nop\n\
-LFLGRET"ID":\n\
- mov %5,%%g2" \
- : "=r"(scratch) \
- : "r"(ms_flags*8), "r"(flgtab), "r"(-1), \
- "r"(0x80000000), "r"(ms_saveret) \
- : "cc", "%g2"); }
/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
the stack pointer does not matter. The value is tested only in
functions that have frame pointers.
No definition is equivalent to always zero. */
-extern int current_function_calls_alloca;
-extern int current_function_outgoing_args_size;
-
#define EXIT_IGNORE_STACK \
(get_frame_size () != 0 \
|| current_function_calls_alloca || current_function_outgoing_args_size)
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning. */
-
-/* This declaration is needed due to traditional/ANSI
- incompatibilities which cannot be #ifdefed away
- because they occur inside of macros. Sigh. */
-extern union tree_node *current_function_decl;
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) \
- (TARGET_FLAT ? sparc_flat_output_function_epilogue (FILE, (int)SIZE) \
- : output_function_epilogue (FILE, (int)SIZE, \
- current_function_uses_only_leaf_regs))
-
#define DELAY_SLOTS_FOR_EPILOGUE \
(TARGET_FLAT ? sparc_flat_epilogue_delay_slots () : 1)
#define ELIGIBLE_FOR_EPILOGUE_DELAY(trial, slots_filled) \
@@ -2031,19 +1867,23 @@ extern union tree_node *current_function_decl;
FNADDR is an RTX for the address of the function's pure code.
CXT is an RTX for the static chain value for the function. */
-void sparc_initialize_trampoline ();
-void sparc64_initialize_trampoline ();
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
if (TARGET_ARCH64) \
sparc64_initialize_trampoline (TRAMP, FNADDR, CXT); \
else \
sparc_initialize_trampoline (TRAMP, FNADDR, CXT)
-/* Generate necessary RTL for __builtin_saveregs().
- ARGLIST is the argument list; see expr.c. */
+/* Generate necessary RTL for __builtin_saveregs(). */
+
+#define EXPAND_BUILTIN_SAVEREGS() sparc_builtin_saveregs ()
+
+/* Implement `va_start' for varargs and stdarg. */
+#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
+ sparc_va_start (stdarg, valist, nextarg)
-extern struct rtx_def *sparc_builtin_saveregs ();
-#define EXPAND_BUILTIN_SAVEREGS(ARGLIST) sparc_builtin_saveregs (ARGLIST)
+/* Implement `va_arg'. */
+#define EXPAND_BUILTIN_VA_ARG(valist, type) \
+ sparc_va_arg (valist, type)
/* Define this macro if the location where a function argument is passed
depends on whether or not it is a named argument.
@@ -2058,6 +1898,10 @@ extern struct rtx_def *sparc_builtin_saveregs ();
#define STRICT_ARGUMENT_NAMING TARGET_V9
+/* We do not allow sibling calls if -mflat, nor
+ we do not allow indirect calls to be optimized into sibling calls. */
+#define FUNCTION_OK_FOR_SIBCALL(DECL) (DECL && ! TARGET_FLAT)
+
/* Generate RTL to flush the register windows so as to make arbitrary frames
available. */
#define SETUP_FRAME_ADDRESSES() \
@@ -2067,8 +1911,7 @@ extern struct rtx_def *sparc_builtin_saveregs ();
return an rtx for the address of the word in the frame
that holds the dynamic chain--the previous frame's address.
??? -mflat support? */
-#define DYNAMIC_CHAIN_ADDRESS(frame) \
- gen_rtx_PLUS (Pmode, frame, GEN_INT (14 * UNITS_PER_WORD))
+#define DYNAMIC_CHAIN_ADDRESS(frame) plus_constant (frame, 14 * UNITS_PER_WORD)
/* The return address isn't on the stack, it is in a register, so we can't
access it from the current frame pointer. We can access it from the
@@ -2077,7 +1920,7 @@ extern struct rtx_def *sparc_builtin_saveregs ();
#define RETURN_ADDR_IN_PREVIOUS_FRAME
/* This is the offset of the return address to the true next instruction to be
- executed for the current function. */
+ executed for the current function. */
#define RETURN_ADDR_OFFSET \
(8 + 4 * (! TARGET_ARCH64 && current_function_returns_struct))
@@ -2089,21 +1932,52 @@ extern struct rtx_def *sparc_builtin_saveregs ();
((count == -1) \
? gen_rtx_REG (Pmode, 31) \
: gen_rtx_MEM (Pmode, \
- memory_address (Pmode, plus_constant (frame, 15 * UNITS_PER_WORD))))
+ memory_address (Pmode, plus_constant (frame, \
+ 15 * UNITS_PER_WORD))))
/* Before the prologue, the return address is %o7 + 8. OK, sometimes it's
+12, but always using +8 is close enough for frame unwind purposes.
Actually, just using %o7 is close enough for unwinding, but %o7+8
is something you can return to. */
#define INCOMING_RETURN_ADDR_RTX \
- gen_rtx_PLUS (word_mode, gen_rtx_REG (word_mode, 15), GEN_INT (8))
+ plus_constant (gen_rtx_REG (word_mode, 15), 8)
+#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (15)
/* The offset from the incoming value of %sp to the top of the stack frame
for the current function. On sparc64, we have to account for the stack
bias if present. */
#define INCOMING_FRAME_SP_OFFSET SPARC_STACK_BIAS
-#define DOESNT_NEED_UNWINDER (! TARGET_FLAT)
+/* Describe how we implement __builtin_eh_return. */
+#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 24 : INVALID_REGNUM)
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, 1) /* %g1 */
+#define EH_RETURN_HANDLER_RTX gen_rtx_REG (Pmode, 31) /* %i7 */
+
+/* Select a format to encode pointers in exception handling data. CODE
+ is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
+ true if the symbol may be affected by dynamic relocations.
+
+ If assembler and linker properly support .uaword %r_disp32(foo),
+ then use PC relative 32-bit relocations instead of absolute relocs
+ for shared libraries. On sparc64, use pc relative 32-bit relocs even
+ for binaries, to save memory. */
+#ifdef HAVE_AS_SPARC_UA_PCREL
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
+ (flag_pic \
+ ? (GLOBAL ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4\
+ : ((TARGET_ARCH64 && ! GLOBAL) \
+ ? (DW_EH_PE_pcrel | DW_EH_PE_sdata4) \
+ : DW_EH_PE_absptr))
+
+/* Emit a PC-relative relocation. */
+#define ASM_OUTPUT_DWARF_PCREL(FILE, SIZE, LABEL) \
+ do { \
+ fputs (integer_asm_op (SIZE, FALSE), FILE); \
+ fprintf (FILE, "%%r_disp%d(", SIZE * 8); \
+ assemble_name (FILE, LABEL); \
+ fputc (')', FILE); \
+ } while (0)
+#endif
/* Addressing modes, and classification of registers for them. */
@@ -2172,8 +2046,10 @@ extern struct rtx_def *sparc_builtin_saveregs ();
#define LEGITIMATE_CONSTANT_P(X) \
(GET_CODE (X) != CONST_DOUBLE || GET_MODE (X) == VOIDmode || \
- (TARGET_VIS && (GET_MODE (X) == SFmode || GET_MODE (X) == DFmode) && \
- fp_zero_operand (X)))
+ (TARGET_VIS && \
+ (GET_MODE (X) == SFmode || GET_MODE (X) == DFmode || \
+ GET_MODE (X) == TFmode) && \
+ fp_zero_operand (X, GET_MODE (X))))
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class.
@@ -2190,12 +2066,27 @@ extern struct rtx_def *sparc_builtin_saveregs ();
/* Optional extra constraints for this machine.
+ 'Q' handles floating point constants which can be moved into
+ an integer register with a single sethi instruction.
+
+ 'R' handles floating point constants which can be moved into
+ an integer register with a single mov instruction.
+
+ 'S' handles floating point constants which can be moved into
+ an integer register using a high/lo_sum sequence.
+
'T' handles memory addresses where the alignment is known to
be at least 8 bytes.
`U' handles all pseudo registers or a hard even numbered
integer register, needed for ldd/std instructions. */
+#define EXTRA_CONSTRAINT_BASE(OP, C) \
+ ((C) == 'Q' ? fp_sethi_p(OP) \
+ : (C) == 'R' ? fp_mov_p(OP) \
+ : (C) == 'S' ? fp_high_losum_p(OP) \
+ : 0)
+
#ifndef REG_OK_STRICT
/* Nonzero if X is a hard reg that can be used as an index
@@ -2207,15 +2098,16 @@ extern struct rtx_def *sparc_builtin_saveregs ();
#define REG_OK_FOR_BASE_P(X) \
(((unsigned) REGNO (X)) - 32 >= (FIRST_PSEUDO_REGISTER - 32))
-/* 'T', 'U' are for aligned memory loads which aren't needed for v9. */
+/* 'T', 'U' are for aligned memory loads which aren't needed for arch64. */
#define EXTRA_CONSTRAINT(OP, C) \
- ((! TARGET_ARCH64 && (C) == 'T') \
- ? (mem_min_alignment (OP, 8)) \
- : ((! TARGET_ARCH64 && (C) == 'U') \
- ? (register_ok_for_ldd (OP)) \
- : 0))
-
+ (EXTRA_CONSTRAINT_BASE(OP, C) \
+ || ((! TARGET_ARCH64 && (C) == 'T') \
+ ? (mem_min_alignment (OP, 8)) \
+ : ((! TARGET_ARCH64 && (C) == 'U') \
+ ? (register_ok_for_ldd (OP)) \
+ : 0)))
+
#else
/* Nonzero if X is a hard reg that can be used as an index. */
@@ -2224,14 +2116,24 @@ extern struct rtx_def *sparc_builtin_saveregs ();
#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
#define EXTRA_CONSTRAINT(OP, C) \
- ((! TARGET_ARCH64 && (C) == 'T') \
- ? mem_min_alignment (OP, 8) && strict_memory_address_p (Pmode, XEXP (OP, 0)) \
- : ((! TARGET_ARCH64 && (C) == 'U') \
- ? (GET_CODE (OP) == REG \
- && (REGNO (OP) < FIRST_PSEUDO_REGISTER \
- || reg_renumber[REGNO (OP)] >= 0) \
- && register_ok_for_ldd (OP)) \
- : 0))
+ (EXTRA_CONSTRAINT_BASE(OP, C) \
+ || ((! TARGET_ARCH64 && (C) == 'T') \
+ ? mem_min_alignment (OP, 8) && strict_memory_address_p (Pmode, XEXP (OP, 0)) \
+ : ((! TARGET_ARCH64 && (C) == 'U') \
+ ? (GET_CODE (OP) == REG \
+ && (REGNO (OP) < FIRST_PSEUDO_REGISTER \
+ || reg_renumber[REGNO (OP)] >= 0) \
+ && register_ok_for_ldd (OP)) \
+ : 0)))
+
+#endif
+
+/* Should gcc use [%reg+%lo(xx)+offset] addresses? */
+
+#ifdef HAVE_AS_OFFSETABLE_LO10
+#define USE_AS_OFFSETABLE_LO10 1
+#else
+#define USE_AS_OFFSETABLE_LO10 0
#endif
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
@@ -2257,7 +2159,10 @@ extern struct rtx_def *sparc_builtin_saveregs ();
&& REG_OK_FOR_INDEX_P (SUBREG_REG (X))))
#define RTX_OK_FOR_OFFSET_P(X) \
- (GET_CODE (X) == CONST_INT && INTVAL (X) >= -0x1000 && INTVAL (X) < 0x1000)
+ (GET_CODE (X) == CONST_INT && INTVAL (X) >= -0x1000 && INTVAL (X) < 0x1000 - 8)
+
+#define RTX_OK_FOR_OLO10_P(X) \
+ (GET_CODE (X) == CONST_INT && INTVAL (X) >= -0x1000 && INTVAL (X) < 0xc00 - 8)
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
{ if (RTX_OK_FOR_BASE_P (X)) \
@@ -2290,25 +2195,61 @@ extern struct rtx_def *sparc_builtin_saveregs ();
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))) \
+ 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 \
+ /* See the previous comment. */ \
+ && (MODE != TFmode \
|| (TARGET_FPU && TARGET_ARCH64 \
&& TARGET_V9 \
- && TARGET_HARD_QUAD))) \
+ && 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) \
{ \
@@ -2318,7 +2259,7 @@ extern struct rtx_def *sparc_builtin_saveregs ();
&& 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. */\
+ may cause the LO_SUM to overflow if !v9. */\
&& (MODE != TFmode || TARGET_V9)) \
goto ADDR; \
} \
@@ -2340,30 +2281,29 @@ extern struct rtx_def *sparc_builtin_saveregs ();
opportunities to optimize the output. */
/* On SPARC, change REG+N into REG+REG, and REG+(X*Y) into REG+REG. */
-extern struct rtx_def *legitimize_pic_address ();
#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)); \
+ 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)); \
+ 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)); \
+ 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)); \
+ 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))); \
+ 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))); \
+ 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); \
@@ -2395,7 +2335,7 @@ do { \
{ \
X = gen_rtx_LO_SUM (GET_MODE (X), \
gen_rtx_HIGH (GET_MODE (X), X), X); \
- push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR, \
+ push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL, \
BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \
OPNUM, TYPE); \
goto WIN; \
@@ -2428,7 +2368,7 @@ do { \
(! TARGET_PTR64 ? SImode : flag_pic ? SImode : TARGET_CM_MEDLOW ? SImode : DImode)
#else
/* If assembler does not have working .subsection -1, we use DImode for pic, as otherwise
- we have to sign extend which slows things down. */
+ we have to sign extend which slows things down. */
#define CASE_VECTOR_MODE \
(! TARGET_PTR64 ? SImode : flag_pic ? DImode : TARGET_CM_MEDLOW ? SImode : DImode)
#endif
@@ -2436,15 +2376,9 @@ do { \
/* Define as C expression which evaluates to nonzero if the tablejump
instruction expects the table to contain offsets from the address of the
table.
- Do not define this if the table should contain absolute addresses. */
+ Do not define this if the table should contain absolute addresses. */
/* #define CASE_VECTOR_PC_RELATIVE 1 */
-/* Specify the tree operation to be used to convert reals to integers. */
-#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
-
-/* This is the kind of divide that is easiest to do in the general case. */
-#define EASY_DIV_EXPR TRUNC_DIV_EXPR
-
/* Define this as 1 if `char' should by default be signed; else as 0. */
#define DEFAULT_SIGNED_CHAR 1
@@ -2484,10 +2418,10 @@ do { \
#define STORE_FLAG_VALUE 1
/* When a prototype says `char' or `short', really pass an `int'. */
-#define PROMOTE_PROTOTYPES
+#define PROMOTE_PROTOTYPES (TARGET_ARCH32)
/* Define this to be nonzero if shift instructions ignore all but the low-order
- few bits. */
+ few bits. */
#define SHIFT_COUNT_TRUNCATED 1
/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
@@ -2497,7 +2431,7 @@ do { \
/* 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. */
-#define Pmode (TARGET_PTR64 ? DImode : SImode)
+#define Pmode (TARGET_ARCH64 ? DImode : SImode)
/* Generate calls to memcpy, memcmp and memset. */
#define TARGET_MEM_FUNCTIONS
@@ -2515,34 +2449,28 @@ do { \
CCXmode and CCX_NOOVmode are only used by v9. */
-#define EXTRA_CC_MODES CCXmode, CC_NOOVmode, CCX_NOOVmode, CCFPmode, CCFPEmode
-
-/* Define the names for the modes specified above. */
-
-#define EXTRA_CC_NAMES "CCX", "CC_NOOV", "CCX_NOOV", "CCFP", "CCFPE"
+#define EXTRA_CC_MODES \
+ CC(CCXmode, "CCX") \
+ CC(CC_NOOVmode, "CC_NOOV") \
+ CC(CCX_NOOVmode, "CCX_NOOV") \
+ CC(CCFPmode, "CCFP") \
+ CC(CCFPEmode, "CCFPE")
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. For floating-point,
- CCFP[E]mode is used. CC_NOOVmode should be used when the first operand is a
- PLUS, MINUS, NEG, or ASHIFT. CCmode should be used when no special
+ CCFP[E]mode is used. CC_NOOVmode should be used when the first operand
+ is a PLUS, MINUS, NEG, or ASHIFT. CCmode should be used when no special
processing is needed. */
-#define SELECT_CC_MODE(OP,X,Y) \
- (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
- ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \
- : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \
- || GET_CODE (X) == NEG || GET_CODE (X) == ASHIFT) \
- ? (TARGET_ARCH64 && GET_MODE (X) == DImode ? CCX_NOOVmode : CC_NOOVmode) \
- : ((TARGET_ARCH64 || TARGET_V8PLUS) && GET_MODE (X) == DImode ? CCXmode : CCmode)))
-
-/* Return non-zero if SELECT_CC_MODE will never return MODE for a
- floating point inequality comparison. */
+#define SELECT_CC_MODE(OP,X,Y) select_cc_mode ((OP), (X), (Y))
-#define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode)
+/* Return non-zero if MODE implies a floating point inequality can be
+ reversed. For Sparc this is always true because we have a full
+ compliment of ordered and unordered comparisons, but until generic
+ code knows how to reverse it correctly we keep the old definition. */
+#define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode && (MODE) != CCFPmode)
-/* A function address in a call instruction
- is a byte address (for indexing purposes)
- so give the MEM rtx a byte's mode. */
-#define FUNCTION_MODE SImode
+/* A function address in a call instruction for indexing purposes. */
+#define FUNCTION_MODE Pmode
/* Define this if addresses of constant functions
shouldn't be put through pseudo regs where they can be cse'd.
@@ -2565,26 +2493,25 @@ do { \
#define MULSI3_LIBCALL "*.umul"
/* Define library calls for quad FP operations. These are all part of the
- SPARC ABI.
- ??? ARCH64 still does not work as the _Qp_* routines take pointers. */
-#define ADDTF3_LIBCALL (TARGET_ARCH64 ? "_Qp_add" : "_Q_add")
-#define SUBTF3_LIBCALL (TARGET_ARCH64 ? "_Qp_sub" : "_Q_sub")
-#define NEGTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_neg" : "_Q_neg")
-#define MULTF3_LIBCALL (TARGET_ARCH64 ? "_Qp_mul" : "_Q_mul")
-#define DIVTF3_LIBCALL (TARGET_ARCH64 ? "_Qp_div" : "_Q_div")
-#define FLOATSITF2_LIBCALL (TARGET_ARCH64 ? "_Qp_itoq" : "_Q_itoq")
-#define FIX_TRUNCTFSI2_LIBCALL (TARGET_ARCH64 ? "_Qp_qtoi" : "_Q_qtoi")
-#define FIXUNS_TRUNCTFSI2_LIBCALL (TARGET_ARCH64 ? "_Qp_qtoui" : "_Q_qtou")
-#define EXTENDSFTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_stoq" : "_Q_stoq")
-#define TRUNCTFSF2_LIBCALL (TARGET_ARCH64 ? "_Qp_qtos" : "_Q_qtos")
-#define EXTENDDFTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_dtoq" : "_Q_dtoq")
-#define TRUNCTFDF2_LIBCALL (TARGET_ARCH64 ? "_Qp_qtod" : "_Q_qtod")
-#define EQTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_feq" : "_Q_feq")
-#define NETF2_LIBCALL (TARGET_ARCH64 ? "_Qp_fne" : "_Q_fne")
-#define GTTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_fgt" : "_Q_fgt")
-#define GETF2_LIBCALL (TARGET_ARCH64 ? "_Qp_fge" : "_Q_fge")
-#define LTTF2_LIBCALL (TARGET_ARCH64 ? "_Qp_flt" : "_Q_flt")
-#define LETF2_LIBCALL (TARGET_ARCH64 ? "_Qp_fle" : "_Q_fle")
+ 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"
/* 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,
@@ -2592,39 +2519,47 @@ do { \
for calls to the builtin function sqrt, but this fails. */
#define INIT_TARGET_OPTABS \
do { \
- add_optab->handlers[(int) TFmode].libfunc \
- = gen_rtx_SYMBOL_REF (Pmode, ADDTF3_LIBCALL); \
- sub_optab->handlers[(int) TFmode].libfunc \
- = gen_rtx_SYMBOL_REF (Pmode, SUBTF3_LIBCALL); \
- neg_optab->handlers[(int) TFmode].libfunc \
- = gen_rtx_SYMBOL_REF (Pmode, NEGTF2_LIBCALL); \
- smul_optab->handlers[(int) TFmode].libfunc \
- = gen_rtx_SYMBOL_REF (Pmode, MULTF3_LIBCALL); \
- flodiv_optab->handlers[(int) TFmode].libfunc \
- = gen_rtx_SYMBOL_REF (Pmode, DIVTF3_LIBCALL); \
- eqtf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, EQTF2_LIBCALL); \
- netf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, NETF2_LIBCALL); \
- gttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, GTTF2_LIBCALL); \
- getf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, GETF2_LIBCALL); \
- lttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, LTTF2_LIBCALL); \
- letf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, LETF2_LIBCALL); \
- trunctfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, TRUNCTFSF2_LIBCALL); \
- trunctfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, TRUNCTFDF2_LIBCALL); \
- extendsftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, EXTENDSFTF2_LIBCALL); \
- extenddftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, EXTENDDFTF2_LIBCALL); \
- floatsitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, FLOATSITF2_LIBCALL); \
- fixtfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFSI2_LIBCALL); \
- fixunstfsi_libfunc \
- = gen_rtx_SYMBOL_REF (Pmode, FIXUNS_TRUNCTFSI2_LIBCALL); \
- if (TARGET_FPU) \
- sqrt_optab->handlers[(int) TFmode].libfunc \
- = gen_rtx_SYMBOL_REF (Pmode, "_Q_sqrt"); \
+ 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"); \
+ } \
INIT_SUBTARGET_OPTABS; \
} while (0)
/* This is meant to be redefined in the host dependent files */
#define INIT_SUBTARGET_OPTABS
+/* 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)
+
/* Compute the cost of computing a constant rtl expression RTX
whose rtx-code is CODE. The body of this macro is a portion
of a switch statement. If the code is computed here,
@@ -2655,7 +2590,7 @@ do { \
/* Compute extra cost of moving data between one register class
and another. */
#define GENERAL_OR_I64(C) ((C) == GENERAL_REGS || (C) == I64_REGS)
-#define REGISTER_MOVE_COST(CLASS1, CLASS2) \
+#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
(((FP_REG_CLASS_P (CLASS1) && GENERAL_OR_I64 (CLASS2)) \
|| (GENERAL_OR_I64 (CLASS1) && FP_REG_CLASS_P (CLASS2)) \
|| (CLASS1) == FPCC_REGS || (CLASS2) == FPCC_REGS) \
@@ -2688,35 +2623,13 @@ do { \
case FIX: \
return 19;
-#define ISSUE_RATE sparc_issue_rate()
-
-/* Adjust the cost of dependencies. */
-#define ADJUST_COST(INSN,LINK,DEP,COST) \
- sparc_adjust_cost(INSN, LINK, DEP, COST)
-
-extern void ultrasparc_sched_reorder ();
-extern void ultrasparc_sched_init ();
-extern int ultrasparc_variable_issue ();
-
-#define MD_SCHED_INIT(DUMP, SCHED_VERBOSE) \
- if (sparc_cpu == PROCESSOR_ULTRASPARC) \
- ultrasparc_sched_init (DUMP, SCHED_VERBOSE)
-
-#define MD_SCHED_REORDER(DUMP, SCHED_VERBOSE, READY, N_READY) \
- if (sparc_cpu == PROCESSOR_ULTRASPARC) \
- ultrasparc_sched_reorder (DUMP, SCHED_VERBOSE, READY, N_READY)
-
-#define MD_SCHED_VARIABLE_ISSUE(DUMP, SCHED_VERBOSE, INSN, CAN_ISSUE_MORE) \
- if (sparc_cpu == PROCESSOR_ULTRASPARC) \
- (CAN_ISSUE_MORE) = ultrasparc_variable_issue (INSN); \
- else \
- (CAN_ISSUE_MORE)--
-
/* Conditional branches with empty delay slots have a length of two. */
#define ADJUST_INSN_LENGTH(INSN, LENGTH) \
+do { \
if (GET_CODE (INSN) == CALL_INSN \
|| (GET_CODE (INSN) == JUMP_INSN && ! simplejump_p (insn))) \
- LENGTH += 1; else
+ LENGTH += 1; \
+} while (0)
/* Control the assembler format that we output. */
@@ -2742,21 +2655,9 @@ extern int ultrasparc_variable_issue ();
/* ??? Try to make the style consistent here (_OP?). */
-#define ASM_LONGLONG ".xword"
-#define ASM_LONG ".word"
-#define ASM_SHORT ".half"
-#define ASM_BYTE_OP ".byte"
#define ASM_FLOAT ".single"
#define ASM_DOUBLE ".double"
-#define ASM_LONGDOUBLE ".xxx" /* ??? Not known (or used yet). */
-
-/* Output before read-only data. */
-
-#define TEXT_SECTION_ASM_OP ".text"
-
-/* Output before writable data. */
-
-#define DATA_SECTION_ASM_OP ".data"
+#define ASM_LONGDOUBLE ".xxx" /* ??? Not known (or used yet). */
/* How to refer to registers in assembler output.
This sequence is indexed by compiler's hard-register-number (see above). */
@@ -2781,12 +2682,6 @@ extern int ultrasparc_variable_issue ();
#define ADDITIONAL_REGISTER_NAMES \
{{"ccr", SPARC_ICC_REG}, {"cc", SPARC_ICC_REG}}
-/* How to renumber registers for dbx and gdb. In the flat model, the frame
- pointer is really %i7. */
-
-#define DBX_REGISTER_NUMBER(REGNO) \
- (TARGET_FLAT && REGNO == FRAME_POINTER_REGNUM ? 31 : REGNO)
-
/* On Sun 4, this limit is 2048. We use 1000 to be safe, since the length
can run past this up to a continuation point. Once we used 1500, but
a single entry in C++ can run more than 500 bytes, due to the length of
@@ -2795,17 +2690,6 @@ extern int ultrasparc_variable_issue ();
guess... */
#define DBX_CONTIN_LENGTH 1000
-/* This is how to output a note to DBX telling it the line number
- to which the following sequence of instructions corresponds.
-
- 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; }
-
/* This is how to output the definition of a user-level label named NAME,
such as the label on a static function or variable NAME. */
@@ -2818,7 +2702,7 @@ extern int ultrasparc_variable_issue ();
#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
do { fputs ("\t.global ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
-/* The prefix to add to user-visible assembler symbols. */
+/* The prefix to add to user-visible assembler symbols. */
#define USER_LABEL_PREFIX "_"
@@ -2836,85 +2720,8 @@ extern int ultrasparc_variable_issue ();
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
sprintf ((LABEL), "*%s%ld", (PREFIX), (long)(NUM))
-/* This is how to output an assembler line defining a `float' constant.
- We always have to use a .long pseudo-op to do this because the native
- SVR4 ELF assembler is buggy and it generates incorrect values when we
- try to use the .float pseudo-op instead. */
-
-#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
- { \
- long t; \
- char str[30]; \
- REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \
- REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \
- fprintf (FILE, "\t%s\t0x%lx %s ~%s\n", ASM_LONG, t, \
- ASM_COMMENT_START, str); \
- } \
-
-/* This is how to output an assembler line defining a `double' constant.
- We always have to use a .long pseudo-op to do this because the native
- SVR4 ELF assembler is buggy and it generates incorrect values when we
- try to use the .float pseudo-op instead. */
-
-#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
- { \
- long t[2]; \
- char str[30]; \
- REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \
- REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \
- fprintf (FILE, "\t%s\t0x%lx %s ~%s\n", ASM_LONG, t[0], \
- ASM_COMMENT_START, str); \
- fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t[1]); \
- }
-
-/* This is how to output an assembler line defining a `long double'
- constant. */
-
-#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
- { \
- long t[4]; \
- char str[30]; \
- REAL_VALUE_TO_TARGET_LONG_DOUBLE ((VALUE), t); \
- REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \
- fprintf (FILE, "\t%s\t0x%lx %s ~%s\n", ASM_LONG, t[0], \
- ASM_COMMENT_START, str); \
- fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t[1]); \
- fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t[2]); \
- fprintf (FILE, "\t%s\t0x%lx\n", ASM_LONG, t[3]); \
- }
-
-/* This is how to output an assembler line defining an `int' constant. */
-
-#define ASM_OUTPUT_INT(FILE,VALUE) \
-( fprintf (FILE, "\t%s\t", ASM_LONG), \
- output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
-
-/* This is how to output an assembler line defining a DImode constant. */
-#define ASM_OUTPUT_DOUBLE_INT(FILE,VALUE) \
- output_double_int (FILE, VALUE)
-
-/* Likewise for `char' and `short' constants. */
-
-#define ASM_OUTPUT_SHORT(FILE,VALUE) \
-( fprintf (FILE, "\t%s\t", ASM_SHORT), \
- output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
-
-#define ASM_OUTPUT_CHAR(FILE,VALUE) \
-( fprintf (FILE, "\t%s\t", ASM_BYTE_OP), \
- output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
-
-/* This is how to output an assembler line for a numeric constant byte. */
-
-#define ASM_OUTPUT_BYTE(FILE,VALUE) \
- fprintf (FILE, "\t%s\t0x%x\n", ASM_BYTE_OP, (VALUE))
-
/* This is how we hook in and defer the case-vector until the end of
the function. */
-extern void sparc_defer_case_vector ();
-
#define ASM_OUTPUT_ADDR_VEC(LAB,VEC) \
sparc_defer_case_vector ((LAB),(VEC), 0)
@@ -2975,10 +2782,6 @@ do { \
if ((LOG) != 0) \
fprintf (FILE, "\t.align %d\n", (1<<(LOG)))
-#define LABEL_ALIGN_AFTER_BARRIER(LABEL) (sparc_align_jumps)
-
-#define LOOP_ALIGN(LABEL) (sparc_align_loops)
-
#define ASM_OUTPUT_SKIP(FILE,SIZE) \
fprintf (FILE, "\t.skip %u\n", (SIZE))
@@ -3020,70 +2823,34 @@ do { \
( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
-#define IDENT_ASM_OP ".ident"
+#define IDENT_ASM_OP "\t.ident\t"
/* Output #ident as a .ident. */
#define ASM_OUTPUT_IDENT(FILE, NAME) \
- fprintf (FILE, "\t%s\t\"%s\"\n", IDENT_ASM_OP, NAME);
+ fprintf (FILE, "%s\"%s\"\n", IDENT_ASM_OP, NAME);
/* Output code to add DELTA to the first argument, and then jump to FUNCTION.
Used for C++ multiple inheritance. */
#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
do { \
- int big_delta = (DELTA) >= 4096 || (DELTA) < -4096; \
- if (big_delta) \
- fprintf (FILE, "\tset %d,%%g1\n\tadd %%o0,%%g1,%%o0\n", (DELTA)); \
- /* Don't use the jmp solution unless we know the target is local to \
- the application or shared object. \
- XXX: Wimp out and don't actually check anything except if this is \
- an embedded target where we assume there are no shared libs. */ \
- if (!TARGET_CM_EMBMEDANY || flag_pic) \
- { \
- if (! big_delta) \
- fprintf (FILE, "\tadd %%o0,%d,%%o0\n", DELTA); \
- fprintf (FILE, "\tmov %%o7,%%g1\n"); \
- fprintf (FILE, "\tcall "); \
- assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
- fprintf (FILE, ",0\n"); \
- } \
- else if (TARGET_CM_EMBMEDANY) \
- { \
- fprintf (FILE, "\tsetx "); \
- assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
- fprintf (FILE, ",%%g5,%%g1\n\tjmp %%g1\n"); \
- } \
+ int reg = 0; \
+ \
+ if (TARGET_ARCH64 \
+ && aggregate_value_p (TREE_TYPE (TREE_TYPE (FUNCTION)))) \
+ reg = 1; \
+ if ((DELTA) >= 4096 || (DELTA) < -4096) \
+ fprintf (FILE, "\tset\t%d, %%g1\n\tadd\t%%o%d, %%g1, %%o%d\n", \
+ (int)(DELTA), reg, reg); \
else \
- { \
- fprintf (FILE, "\tsethi %%hi("); \
- assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
- fprintf (FILE, "),%%g1\n\tjmp %%g1+%%lo("); \
- assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
- fprintf (FILE, ")\n"); \
- } \
- if (!TARGET_CM_EMBMEDANY || flag_pic) \
- fprintf (FILE, "\tmov %%g1,%%o7\n"); \
- else if (big_delta) \
- fprintf (FILE, "\tnop\n"); \
- else \
- fprintf (FILE, "\tadd %%o0,%d,%%o0\n", DELTA); \
+ fprintf (FILE, "\tadd\t%%o%d, %d, %%o%d\n", reg, (int)(DELTA), reg);\
+ fprintf (FILE, "\tor\t%%o7, %%g0, %%g1\n"); \
+ fprintf (FILE, "\tcall\t"); \
+ assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
+ fprintf (FILE, ", 0\n"); \
+ fprintf (FILE, "\t or\t%%g1, %%g0, %%o7\n"); \
} while (0)
-/* Define the parentheses used to group arithmetic operations
- in assembler code. */
-
-#define ASM_OPEN_PAREN "("
-#define ASM_CLOSE_PAREN ")"
-
-/* Define results of standard character escape sequences. */
-#define TARGET_BELL 007
-#define TARGET_BS 010
-#define TARGET_TAB 011
-#define TARGET_NEWLINE 012
-#define TARGET_VT 013
-#define TARGET_FF 014
-#define TARGET_CR 015
-
#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' || (CHAR) == '(' || (CHAR) == '_')
@@ -3109,15 +2876,29 @@ do { \
offset = INTVAL (XEXP (addr, 1)), base = XEXP (addr, 0);\
else \
base = XEXP (addr, 0), index = XEXP (addr, 1); \
- fputs (reg_names[REGNO (base)], FILE); \
- if (index == 0) \
- fprintf (FILE, "%+d", offset); \
- else if (GET_CODE (index) == REG) \
- fprintf (FILE, "+%s", reg_names[REGNO (index)]); \
- else if (GET_CODE (index) == SYMBOL_REF \
- || GET_CODE (index) == CONST) \
- fputc ('+', FILE), output_addr_const (FILE, index); \
- else abort (); \
+ if (GET_CODE (base) == LO_SUM) \
+ { \
+ if (! USE_AS_OFFSETABLE_LO10 \
+ || TARGET_ARCH32 \
+ || TARGET_CM_MEDMID) \
+ abort (); \
+ output_operand (XEXP (base, 0), 0); \
+ fputs ("+%lo(", FILE); \
+ output_address (XEXP (base, 1)); \
+ fprintf (FILE, ")+%d", offset); \
+ } \
+ else \
+ { \
+ fputs (reg_names[REGNO (base)], FILE); \
+ if (index == 0) \
+ fprintf (FILE, "%+d", offset); \
+ else if (GET_CODE (index) == REG) \
+ fprintf (FILE, "+%s", reg_names[REGNO (index)]); \
+ else if (GET_CODE (index) == SYMBOL_REF \
+ || GET_CODE (index) == CONST) \
+ fputc ('+', FILE), output_addr_const (FILE, index); \
+ else abort (); \
+ } \
} \
else if (GET_CODE (addr) == MINUS \
&& GET_CODE (XEXP (addr, 1)) == LABEL_REF) \
@@ -3170,7 +2951,7 @@ do { \
{"call_operand", {MEM}}, \
{"call_operand_address", {SYMBOL_REF, LABEL_REF, CONST, CONST_DOUBLE, \
ADDRESSOF, SUBREG, REG, PLUS, LO_SUM, CONST_INT}}, \
-{"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST, CONST_DOUBLE}}, \
+{"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}}, \
{"symbolic_memory_operand", {SUBREG, MEM}}, \
{"label_ref_operand", {LABEL_REF}}, \
{"sp64_medium_pic_operand", {CONST}}, \
@@ -3200,7 +2981,6 @@ do { \
{"uns_arith_operand", {SUBREG, REG, CONST_INT}}, \
{"clobbered_register", {REG}}, \
{"input_operand", {SUBREG, REG, CONST_INT, MEM, CONST}}, \
-{"zero_operand", {CONST_INT}}, \
{"const64_operand", {CONST_INT, CONST_DOUBLE}}, \
{"const64_high_operand", {CONST_INT, CONST_DOUBLE}},
@@ -3209,101 +2989,3 @@ do { \
#define DONT_ACCESS_GBLS_AFTER_EPILOGUE (flag_pic)
-/* Declare functions defined in sparc.c and used in templates. */
-
-extern void sparc_emit_set_const32 ();
-extern void sparc_emit_set_const64 ();
-extern void sparc_emit_set_symbolic_const64 ();
-extern int sparc_splitdi_legitimate ();
-extern int sparc_absnegfloat_split_legitimate ();
-
-extern char *output_cbranch ();
-extern const char *output_return ();
-extern char *output_v9branch ();
-
-extern void emit_v9_brxx_insn ();
-extern void finalize_pic ();
-extern void order_regs_for_local_alloc ();
-extern void output_double_int ();
-extern void output_function_epilogue ();
-extern void output_function_prologue ();
-extern void print_operand ();
-extern void sparc_flat_output_function_epilogue ();
-extern void sparc_flat_output_function_prologue ();
-
-extern int addrs_ok_for_ldd_peep ();
-extern int arith10_double_operand ();
-extern int arith10_operand ();
-extern int arith11_double_operand ();
-extern int arith11_operand ();
-extern int arith_double_operand ();
-extern int arith_double_4096_operand ();
-extern int arith_double_add_operand ();
-extern int arith_operand ();
-extern int arith_4096_operand ();
-extern int arith_add_operand ();
-extern int call_operand_address ();
-extern int input_operand ();
-extern int zero_operand ();
-extern int const64_operand ();
-extern int const64_high_operand ();
-extern int cc_arithop ();
-extern int cc_arithopn ();
-extern int check_pic ();
-extern int compute_frame_size ();
-extern int data_segment_operand ();
-extern int eligible_for_epilogue_delay ();
-extern int eligible_for_return_delay ();
-extern int emit_move_sequence ();
-extern int extend_op ();
-extern int fcc_reg_operand ();
-extern int fp_zero_operand ();
-extern int icc_or_fcc_reg_operand ();
-extern int label_ref_operand ();
-extern int mem_min_alignment ();
-extern int noov_compare_op ();
-extern int pic_address_needs_scratch ();
-extern int reg_or_0_operand ();
-extern int reg_or_nonsymb_mem_operand ();
-extern int reg_unused_after ();
-extern int register_ok_for_ldd ();
-extern int registers_ok_for_ldd_peep ();
-extern int restore_operand ();
-extern int short_branch ();
-extern int small_int ();
-extern int small_int_or_double ();
-extern int sp64_medium_pic_operand ();
-extern int sparc_flat_eligible_for_epilogue_delay ();
-extern int sparc_flat_epilogue_delay_slots ();
-extern int sparc_issue_rate ();
-extern int splittable_immediate_memory_operand ();
-extern int splittable_symbolic_memory_operand ();
-extern int sparc_adjust_cost ();
-extern int symbolic_memory_operand ();
-extern int symbolic_operand ();
-extern int text_segment_operand ();
-extern int uns_small_int ();
-extern int v9_regcmp_op ();
-extern int v9_regcmp_p ();
-
-extern unsigned long sparc_flat_compute_frame_size ();
-extern unsigned long sparc_type_code ();
-
-extern void sparc_function_profiler ();
-extern void sparc_function_block_profiler ();
-extern void sparc_block_profiler ();
-extern void sparc_function_block_profiler_exit ();
-
-extern char *sparc_v8plus_shift ();
-
-#ifdef __STDC__
-/* Function used for V8+ code generation. Returns 1 if the high
- 32 bits of REG are 0 before INSN. */
-extern int sparc_check_64 (struct rtx_def *, struct rtx_def *);
-extern int sparc_return_peephole_ok (struct rtx_def *, struct rtx_def *);
-extern int compute_frame_size (int, int);
-#endif
-
-/* Defined in flags.h, but insn-emit.c does not include flags.h. */
-
-extern int flag_pic;
diff --git a/contrib/gcc/config/sparc/sparc.md b/contrib/gcc/config/sparc/sparc.md
index 58e882c..c0b8f60 100644
--- a/contrib/gcc/config/sparc/sparc.md
+++ b/contrib/gcc/config/sparc/sparc.md
@@ -1,6 +1,6 @@
-;;- Machine description for SPARC chip for GNU C compiler
+;- Machine description for SPARC chip for GNU C compiler
;; Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-;; 1999 Free Software Foundation, Inc.
+;; 1999, 2000, 2001, 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.
@@ -38,12 +38,10 @@
;; 9 sethh
;; 10 setlm
;; 11 embmedany_sethi, embmedany_brsum
-;; 12 movsf_const_high
;; 13 embmedany_textuhi
;; 14 embmedany_texthi
;; 15 embmedany_textulo
;; 16 embmedany_textlo
-;; 17 movsf_const_lo
;; 18 sethm
;; 19 setlo
;;
@@ -52,7 +50,7 @@
;; 2 goto_handler_and_restore
;; 3 goto_handler_and_restore_v9*
;; 4 flush
-;; 5 nonlocal_goto_receiver
+;; 5 do_builtin_setjmp_setup
;;
;; The upper 32 fp regs on the v9 can't hold SFmode values. To deal with this
@@ -60,9 +58,6 @@
;; is a bit of a misnomer as it covers all 64 fp regs. The corresponding
;; constraint letter is 'e'. To avoid any confusion, 'e' is used instead of
;; 'f' for all DF/TFmode values, including those that are specific to the v8.
-;;
-;; -mlive-g0 is *not* supported for TARGET_ARCH64, so we don't bother to
-;; test TARGET_LIVE_G0 if we have TARGET_ARCH64.
;; Attribute for cpu type.
;; These must match the values for enum processor_type in sparc.h.
@@ -85,72 +80,31 @@
(cond [(symbol_ref "TARGET_ARCH64") (const_string "arch64bit")]
(const_string "arch32bit"))))
-;; Whether -mlive-g0 is in effect.
-(define_attr "live_g0" "no,yes"
- (const
- (cond [(symbol_ref "TARGET_LIVE_G0") (const_string "yes")]
- (const_string "no"))))
-
-;; Insn type. Used to default other attribute values.
-
-;; type "unary" insns have one input operand (1) and one output operand (0)
-;; type "binary" insns have two input operands (1,2) and one output (0)
-;; type "compare" insns have one or two input operands (0,1) and no output
-;; type "call_no_delay_slot" is a call followed by an unimp instruction.
+;; Insn type.
+;; If you add any new type here, please update ultrasparc_sched_reorder too.
(define_attr "type"
- "move,unary,binary,compare,load,sload,store,ialu,shift,uncond_branch,branch,call,call_no_delay_slot,return,address,imul,fpload,fpstore,fp,fpmove,fpcmove,fpcmp,fpmul,fpdivs,fpdivd,fpsqrt,cmove,multi,misc"
- (const_string "binary"))
-
-;; Set true if insn uses call-clobbered intermediate register.
-(define_attr "use_clobbered" "false,true"
- (if_then_else (and (eq_attr "type" "address")
- (match_operand 0 "clobbered_register" ""))
- (const_string "true")
- (const_string "false")))
+ "ialu,compare,shift,load,sload,store,uncond_branch,branch,call,sibcall,call_no_delay_slot,return,imul,idiv,fpload,fpstore,fp,fpmove,fpcmove,fpcmp,fpmul,fpdivs,fpdivd,fpsqrts,fpsqrtd,cmove,multi,misc"
+ (const_string "ialu"))
;; Length (in # of insns).
-(define_attr "length" ""
- (cond [(eq_attr "type" "load,sload,fpload")
- (if_then_else (match_operand 1 "symbolic_memory_operand" "")
- (const_int 2) (const_int 1))
-
- (eq_attr "type" "store,fpstore")
- (if_then_else (match_operand 0 "symbolic_memory_operand" "")
- (const_int 2) (const_int 1))
+(define_attr "length" "" (const_int 1))
- (eq_attr "type" "address") (const_int 2)
-
- (eq_attr "type" "binary")
- (if_then_else (ior (match_operand 2 "arith_operand" "")
- (match_operand 2 "arith_double_operand" ""))
- (const_int 1) (const_int 3))
-
- (eq_attr "type" "multi") (const_int 2)
-
- (eq_attr "type" "move,unary")
- (if_then_else (ior (match_operand 1 "arith_operand" "")
- (match_operand 1 "arith_double_operand" ""))
- (const_int 1) (const_int 2))]
-
- (const_int 1)))
+;; FP precision.
+(define_attr "fptype" "single,double" (const_string "single"))
(define_asm_attributes
- [(set_attr "length" "1")
+ [(set_attr "length" "2")
(set_attr "type" "multi")])
;; Attributes for instruction and branch scheduling
(define_attr "in_call_delay" "false,true"
- (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,return,multi")
+ (cond [(eq_attr "type" "uncond_branch,branch,call,sibcall,call_no_delay_slot,return,multi")
(const_string "false")
(eq_attr "type" "load,fpload,store,fpstore")
(if_then_else (eq_attr "length" "1")
(const_string "true")
- (const_string "false"))
- (eq_attr "type" "address")
- (if_then_else (eq_attr "use_clobbered" "false")
- (const_string "true")
(const_string "false"))]
(if_then_else (eq_attr "length" "1")
(const_string "true")
@@ -159,14 +113,23 @@
(define_delay (eq_attr "type" "call")
[(eq_attr "in_call_delay" "true") (nil) (nil)])
+(define_attr "eligible_for_sibcall_delay" "false,true"
+ (symbol_ref "eligible_for_sibcall_delay (insn)"))
+
+(define_delay (eq_attr "type" "sibcall")
+ [(eq_attr "eligible_for_sibcall_delay" "true") (nil) (nil)])
+
(define_attr "leaf_function" "false,true"
(const (symbol_ref "current_function_uses_only_leaf_regs")))
+(define_attr "eligible_for_return_delay" "false,true"
+ (symbol_ref "eligible_for_return_delay (insn)"))
+
(define_attr "in_return_delay" "false,true"
- (if_then_else (and (and (and (eq_attr "type" "move,load,sload,store,binary,ialu")
+ (if_then_else (and (and (and (eq_attr "type" "ialu,load,sload,store")
(eq_attr "length" "1"))
(eq_attr "leaf_function" "false"))
- (match_insn "eligible_for_return_delay"))
+ (eq_attr "eligible_for_return_delay" "false"))
(const_string "true")
(const_string "false")))
@@ -187,19 +150,19 @@
;; because it prevents us from moving back the final store of inner loops.
(define_attr "in_branch_delay" "false,true"
- (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
+ (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
(eq_attr "length" "1"))
(const_string "true")
(const_string "false")))
(define_attr "in_uncond_branch_delay" "false,true"
- (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
+ (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
(eq_attr "length" "1"))
(const_string "true")
(const_string "false")))
(define_attr "in_annul_branch_delay" "false,true"
- (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
+ (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
(eq_attr "length" "1"))
(const_string "true")
(const_string "false")))
@@ -224,9 +187,6 @@
;; On the sparclite, integer multiply takes 1, 3, or 5 cycles depending on
;; the inputs.
-;; (define_function_unit "alu" 1 0
-;; (eq_attr "type" "unary,binary,move,address") 1 0)
-
;; ---- cypress CY7C602 scheduling:
;; Memory with load-delay of 1 (i.e., 2 cycle load).
@@ -271,7 +231,7 @@
(define_function_unit "fp_mds" 1 0
(and (eq_attr "cpu" "cypress")
- (eq_attr "type" "fpsqrt"))
+ (eq_attr "type" "fpsqrts,fpsqrtd"))
63 63)
;; ----- The TMS390Z55 scheduling
@@ -338,7 +298,7 @@
(define_function_unit "fp_mds" 1 0
(and (eq_attr "cpu" "supersparc")
- (eq_attr "type" "fpsqrt"))
+ (eq_attr "type" "fpsqrts,fpsqrtd"))
12 10)
(define_function_unit "fp_mds" 1 0
@@ -363,6 +323,17 @@
(eq_attr "type" "store,fpstore"))
2 1)
+(define_function_unit "sparclite86x_branch" 1 0
+ (and (eq_attr "cpu" "sparclite86x")
+ (eq_attr "type" "branch"))
+ 1 1)
+
+;; integer multiply insns
+(define_function_unit "sparclite86x_shift" 1 0
+ (and (eq_attr "cpu" "sparclite86x")
+ (eq_attr "type" "shift"))
+ 1 1)
+
(define_function_unit "fp_alu" 1 0
(and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
(eq_attr "type" "fp,fpmove,fpcmp"))
@@ -385,7 +356,7 @@
(define_function_unit "fp_mds" 1 0
(and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
- (eq_attr "type" "fpsqrt"))
+ (eq_attr "type" "fpsqrts,fpsqrtd"))
17 15)
(define_function_unit "fp_mds" 1 0
@@ -450,7 +421,7 @@
(define_function_unit "ieuN" 2 0
(and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "ialu,binary,move,unary,shift,compare,call,call_no_delay_slot,uncond_branch"))
+ (eq_attr "type" "ialu,shift,compare,call,sibcall,call_no_delay_slot,uncond_branch"))
1 1)
(define_function_unit "ieu0" 1 0
@@ -465,7 +436,7 @@
(define_function_unit "ieu1" 1 0
(and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "compare,call,call_no_delay_slot,uncond_branch"))
+ (eq_attr "type" "compare,call,sibcall,call_no_delay_slot,uncond_branch"))
1 1)
(define_function_unit "cti" 1 0
@@ -476,14 +447,18 @@
;; Timings; throughput/latency
;; FMOV 1/1 fmov, fabs, fneg
;; FMOVcc 1/2
-;; FADD 1/4 add/sub, format conv, compar
-;; FMUL 1/4
+;; FADD 1/3 add/sub, format conv, compar
+;; FMUL 1/3
;; FDIVs 12/12
;; FDIVd 22/22
;; FSQRTs 12/12
;; FSQRTd 22/22
;; FCMP takes 1 cycle to branch, 2 cycles to conditional move.
;;
+;; FDIV{s,d}/FSQRT{s,d} are given their own unit since they only
+;; use the FPM multiplier for final rounding 3 cycles before the
+;; end of their latency and we have no real way to model that.
+;;
;; ??? This is really bogus because the timings really depend upon
;; who uses the result. We should record who the user is with
;; more descriptive 'type' attribute names and account for these
@@ -502,7 +477,7 @@
(define_function_unit "fadd" 1 0
(and (eq_attr "cpu" "ultrasparc")
(eq_attr "type" "fp"))
- 4 1)
+ 3 1)
(define_function_unit "fadd" 1 0
(and (eq_attr "cpu" "ultrasparc")
@@ -512,27 +487,32 @@
(define_function_unit "fmul" 1 0
(and (eq_attr "cpu" "ultrasparc")
(eq_attr "type" "fpmul"))
- 4 1)
+ 3 1)
(define_function_unit "fadd" 1 0
(and (eq_attr "cpu" "ultrasparc")
(eq_attr "type" "fpcmove"))
2 1)
-(define_function_unit "fmul" 1 0
+(define_function_unit "fdiv" 1 0
(and (eq_attr "cpu" "ultrasparc")
(eq_attr "type" "fpdivs"))
12 12)
-(define_function_unit "fmul" 1 0
+(define_function_unit "fdiv" 1 0
(and (eq_attr "cpu" "ultrasparc")
(eq_attr "type" "fpdivd"))
22 22)
-(define_function_unit "fmul" 1 0
+(define_function_unit "fdiv" 1 0
(and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "fpsqrt"))
+ (eq_attr "type" "fpsqrts"))
12 12)
+
+(define_function_unit "fdiv" 1 0
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fpsqrtd"))
+ 22 22)
;; Compare instructions.
;; This controls RTL generation and register allocation.
@@ -657,7 +637,8 @@
return \"fcmped\\t%0, %1, %2\";
return \"fcmped\\t%1, %2\";
}"
- [(set_attr "type" "fpcmp")])
+ [(set_attr "type" "fpcmp")
+ (set_attr "fptype" "double")])
(define_insn "*cmptf_fpe"
[(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
@@ -696,7 +677,8 @@
return \"fcmpd\\t%0, %1, %2\";
return \"fcmpd\\t%1, %2\";
}"
- [(set_attr "type" "fpcmp")])
+ [(set_attr "type" "fpcmp")
+ (set_attr "fptype" "double")])
(define_insn "*cmptf_fp"
[(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
@@ -728,7 +710,7 @@
(parallel [(set (match_operand:SI 0 "register_operand" "")
(eq:SI (match_dup 3) (const_int 0)))
(clobber (reg:CC 100))])]
- "! TARGET_LIVE_G0"
+ ""
"{ operands[3] = gen_reg_rtx (SImode); }")
(define_expand "seqdi_special"
@@ -747,7 +729,7 @@
(parallel [(set (match_operand:SI 0 "register_operand" "")
(ne:SI (match_dup 3) (const_int 0)))
(clobber (reg:CC 100))])]
- "! TARGET_LIVE_G0"
+ ""
"{ operands[3] = gen_reg_rtx (SImode); }")
(define_expand "snedi_special"
@@ -802,7 +784,7 @@
(define_expand "seq"
[(set (match_operand:SI 0 "intreg_operand" "")
(eq:SI (match_dup 1) (const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"
{
if (GET_MODE (sparc_compare_op0) == SImode)
@@ -837,10 +819,10 @@
}
else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
- emit_insn (gen_sne (operands[0]));
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
+ emit_jump_insn (gen_sne (operands[0]));
DONE;
- }
+ }
else if (TARGET_V9)
{
if (gen_v9_scc (EQ, operands))
@@ -855,7 +837,7 @@
(define_expand "sne"
[(set (match_operand:SI 0 "intreg_operand" "")
(ne:SI (match_dup 1) (const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"
{
if (GET_MODE (sparc_compare_op0) == SImode)
@@ -890,10 +872,10 @@
}
else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
- emit_insn (gen_sne (operands[0]));
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
+ emit_jump_insn (gen_sne (operands[0]));
DONE;
- }
+ }
else if (TARGET_V9)
{
if (gen_v9_scc (NE, operands))
@@ -906,13 +888,13 @@
(define_expand "sgt"
[(set (match_operand:SI 0 "intreg_operand" "")
(gt:SI (match_dup 1) (const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
- emit_insn (gen_sne (operands[0]));
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
+ emit_jump_insn (gen_sne (operands[0]));
DONE;
}
else if (TARGET_V9)
@@ -927,13 +909,13 @@
(define_expand "slt"
[(set (match_operand:SI 0 "intreg_operand" "")
(lt:SI (match_dup 1) (const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
- emit_insn (gen_sne (operands[0]));
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
+ emit_jump_insn (gen_sne (operands[0]));
DONE;
}
else if (TARGET_V9)
@@ -948,13 +930,13 @@
(define_expand "sge"
[(set (match_operand:SI 0 "intreg_operand" "")
(ge:SI (match_dup 1) (const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
- emit_insn (gen_sne (operands[0]));
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
+ emit_jump_insn (gen_sne (operands[0]));
DONE;
}
else if (TARGET_V9)
@@ -969,13 +951,13 @@
(define_expand "sle"
[(set (match_operand:SI 0 "intreg_operand" "")
(le:SI (match_dup 1) (const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
- emit_insn (gen_sne (operands[0]));
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
+ emit_jump_insn (gen_sne (operands[0]));
DONE;
}
else if (TARGET_V9)
@@ -990,7 +972,7 @@
(define_expand "sgtu"
[(set (match_operand:SI 0 "intreg_operand" "")
(gtu:SI (match_dup 1) (const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"
{
if (! TARGET_V9)
@@ -1025,7 +1007,7 @@
(define_expand "sltu"
[(set (match_operand:SI 0 "intreg_operand" "")
(ltu:SI (match_dup 1) (const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"
{
if (TARGET_V9)
@@ -1039,7 +1021,7 @@
(define_expand "sgeu"
[(set (match_operand:SI 0 "intreg_operand" "")
(geu:SI (match_dup 1) (const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"
{
if (TARGET_V9)
@@ -1053,7 +1035,7 @@
(define_expand "sleu"
[(set (match_operand:SI 0 "intreg_operand" "")
(leu:SI (match_dup 1) (const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"
{
if (! TARGET_V9)
@@ -1097,7 +1079,7 @@
(ne:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0)))
(clobber (reg:CC 100))]
- "! TARGET_LIVE_G0"
+ ""
"#"
[(set_attr "length" "2")])
@@ -1117,7 +1099,7 @@
(neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0))))
(clobber (reg:CC 100))]
- "! TARGET_LIVE_G0"
+ ""
"#"
[(set_attr "length" "2")])
@@ -1139,8 +1121,7 @@
(clobber (reg:CC 100))]
"TARGET_ARCH64"
"#"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
+ [(set_attr "length" "2")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -1162,14 +1143,14 @@
(const_int 0)))]
"TARGET_ARCH64"
"#"
- [(set_attr "type" "cmove")
- (set_attr "length" "2")])
+ [(set_attr "length" "2")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(ne:DI (match_operand:DI 1 "register_operand" "")
(const_int 0)))]
- "TARGET_ARCH64"
+ "TARGET_ARCH64
+ && ! reg_overlap_mentioned_p (operands[1], operands[0])"
[(set (match_dup 0) (const_int 0))
(set (match_dup 0) (if_then_else:DI (ne:DI (match_dup 1)
(const_int 0))
@@ -1183,14 +1164,14 @@
(const_int 0))))]
"TARGET_ARCH64"
"#"
- [(set_attr "type" "cmove")
- (set_attr "length" "2")])
+ [(set_attr "length" "2")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(neg:DI (ne:DI (match_operand:DI 1 "register_operand" "")
(const_int 0))))]
- "TARGET_ARCH64"
+ "TARGET_ARCH64
+ && ! reg_overlap_mentioned_p (operands[1], operands[0])"
[(set (match_dup 0) (const_int 0))
(set (match_dup 0) (if_then_else:DI (ne:DI (match_dup 1)
(const_int 0))
@@ -1204,14 +1185,14 @@
(const_int 0)))]
"TARGET_ARCH64"
"#"
- [(set_attr "type" "cmove")
- (set_attr "length" "2")])
+ [(set_attr "length" "2")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(ne:SI (match_operand:DI 1 "register_operand" "")
(const_int 0)))]
- "TARGET_ARCH64"
+ "TARGET_ARCH64
+ && ! reg_overlap_mentioned_p (operands[1], operands[0])"
[(set (match_dup 0) (const_int 0))
(set (match_dup 0) (if_then_else:SI (ne:DI (match_dup 1)
(const_int 0))
@@ -1224,7 +1205,7 @@
(eq:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0)))
(clobber (reg:CC 100))]
- "! TARGET_LIVE_G0"
+ ""
"#"
[(set_attr "length" "2")])
@@ -1244,7 +1225,7 @@
(neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0))))
(clobber (reg:CC 100))]
- "! TARGET_LIVE_G0"
+ ""
"#"
[(set_attr "length" "2")])
@@ -1266,8 +1247,7 @@
(clobber (reg:CC 100))]
"TARGET_ARCH64"
"#"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
+ [(set_attr "length" "2")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -1289,14 +1269,14 @@
(const_int 0)))]
"TARGET_ARCH64"
"#"
- [(set_attr "type" "cmove")
- (set_attr "length" "2")])
+ [(set_attr "length" "2")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(eq:DI (match_operand:DI 1 "register_operand" "")
(const_int 0)))]
- "TARGET_ARCH64"
+ "TARGET_ARCH64
+ && ! reg_overlap_mentioned_p (operands[1], operands[0])"
[(set (match_dup 0) (const_int 0))
(set (match_dup 0) (if_then_else:DI (eq:DI (match_dup 1)
(const_int 0))
@@ -1310,14 +1290,14 @@
(const_int 0))))]
"TARGET_ARCH64"
"#"
- [(set_attr "type" "cmove")
- (set_attr "length" "2")])
+ [(set_attr "length" "2")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(neg:DI (eq:DI (match_operand:DI 1 "register_operand" "")
(const_int 0))))]
- "TARGET_ARCH64"
+ "TARGET_ARCH64
+ && ! reg_overlap_mentioned_p (operands[1], operands[0])"
[(set (match_dup 0) (const_int 0))
(set (match_dup 0) (if_then_else:DI (eq:DI (match_dup 1)
(const_int 0))
@@ -1331,14 +1311,14 @@
(const_int 0)))]
"TARGET_ARCH64"
"#"
- [(set_attr "type" "cmove")
- (set_attr "length" "2")])
+ [(set_attr "length" "2")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(eq:SI (match_operand:DI 1 "register_operand" "")
(const_int 0)))]
- "TARGET_ARCH64"
+ "TARGET_ARCH64
+ && ! reg_overlap_mentioned_p (operands[1], operands[0])"
[(set (match_dup 0) (const_int 0))
(set (match_dup 0) (if_then_else:SI (eq:DI (match_dup 1)
(const_int 0))
@@ -1356,7 +1336,7 @@
(const_int 0))
(match_operand:SI 2 "register_operand" "r")))
(clobber (reg:CC 100))]
- "! TARGET_LIVE_G0"
+ ""
"#"
[(set_attr "length" "2")])
@@ -1366,7 +1346,7 @@
(const_int 0))
(match_operand:SI 2 "register_operand" "")))
(clobber (reg:CC 100))]
- "! TARGET_LIVE_G0"
+ ""
[(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
(const_int 0)))
(set (match_dup 0) (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
@@ -1379,7 +1359,7 @@
(ne:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0))))
(clobber (reg:CC 100))]
- "! TARGET_LIVE_G0"
+ ""
"#"
[(set_attr "length" "2")])
@@ -1389,7 +1369,7 @@
(ne:SI (match_operand:SI 1 "register_operand" "")
(const_int 0))))
(clobber (reg:CC 100))]
- "! TARGET_LIVE_G0"
+ ""
[(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
(const_int 0)))
(set (match_dup 0) (minus:SI (match_dup 2)
@@ -1402,7 +1382,7 @@
(const_int 0))
(match_operand:SI 2 "register_operand" "r")))
(clobber (reg:CC 100))]
- "! TARGET_LIVE_G0"
+ ""
"#"
[(set_attr "length" "2")])
@@ -1412,7 +1392,7 @@
(const_int 0))
(match_operand:SI 2 "register_operand" "")))
(clobber (reg:CC 100))]
- "! TARGET_LIVE_G0"
+ ""
[(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
(const_int 0)))
(set (match_dup 0) (plus:SI (geu:SI (reg:CC 100) (const_int 0))
@@ -1425,7 +1405,7 @@
(eq:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0))))
(clobber (reg:CC 100))]
- "! TARGET_LIVE_G0"
+ ""
"#"
[(set_attr "length" "2")])
@@ -1435,7 +1415,7 @@
(eq:SI (match_operand:SI 1 "register_operand" "")
(const_int 0))))
(clobber (reg:CC 100))]
- "! TARGET_LIVE_G0"
+ ""
[(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
(const_int 0)))
(set (match_dup 0) (minus:SI (match_dup 2)
@@ -1449,53 +1429,47 @@
(define_insn "*sltu_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(ltu:SI (reg:CC 100) (const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"addx\\t%%g0, 0, %0"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
(define_insn "*neg_sltu_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
- "! TARGET_LIVE_G0"
+ ""
"subx\\t%%g0, 0, %0"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
;; ??? Combine should canonicalize these next two to the same pattern.
(define_insn "*neg_sltu_minus_x"
[(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (neg:SI (ltu:SI (reg:CC 100) (const_int 0)))
(match_operand:SI 1 "arith_operand" "rI")))]
- "! TARGET_LIVE_G0"
+ ""
"subx\\t%%g0, %1, %0"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
(define_insn "*neg_sltu_plus_x"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
(match_operand:SI 1 "arith_operand" "rI"))))]
- "! TARGET_LIVE_G0"
+ ""
"subx\\t%%g0, %1, %0"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
(define_insn "*sgeu_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(geu:SI (reg:CC 100) (const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"subx\\t%%g0, -1, %0"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
(define_insn "*neg_sgeu_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
- "! TARGET_LIVE_G0"
+ ""
"addx\\t%%g0, -1, %0"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in.
;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
@@ -1505,10 +1479,9 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (ltu:SI (reg:CC 100) (const_int 0))
(match_operand:SI 1 "arith_operand" "rI")))]
- "! TARGET_LIVE_G0"
+ ""
"addx\\t%%g0, %1, %0"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
(define_insn "*sltu_plus_x_plus_y"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -1517,8 +1490,7 @@
(match_operand:SI 2 "arith_operand" "rI"))))]
""
"addx\\t%1, %2, %0"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
(define_insn "*x_minus_sltu"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -1526,8 +1498,7 @@
(ltu:SI (reg:CC 100) (const_int 0))))]
""
"subx\\t%1, 0, %0"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
;; ??? Combine should canonicalize these next two to the same pattern.
(define_insn "*x_minus_y_minus_sltu"
@@ -1537,8 +1508,7 @@
(ltu:SI (reg:CC 100) (const_int 0))))]
""
"subx\\t%r1, %2, %0"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
(define_insn "*x_minus_sltu_plus_y"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -1547,8 +1517,7 @@
(match_operand:SI 2 "arith_operand" "rI"))))]
""
"subx\\t%r1, %2, %0"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
(define_insn "*sgeu_plus_x"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -1556,8 +1525,7 @@
(match_operand:SI 1 "register_operand" "r")))]
""
"subx\\t%1, -1, %0"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
(define_insn "*x_minus_sgeu"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -1565,11 +1533,10 @@
(geu:SI (reg:CC 100) (const_int 0))))]
""
"addx\\t%1, -1, %0"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
(define_split
- [(set (match_operand:SI 0 "register_operand" "=r")
+ [(set (match_operand:SI 0 "register_operand" "")
(match_operator:SI 2 "noov_compare_op"
[(match_operand 1 "icc_or_fcc_reg_operand" "")
(const_int 0)]))]
@@ -1608,10 +1575,10 @@
}
else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
emit_jump_insn (gen_bne (operands[0]));
DONE;
- }
+ }
operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
}")
@@ -1632,10 +1599,10 @@
}
else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
emit_jump_insn (gen_bne (operands[0]));
DONE;
- }
+ }
operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
}")
@@ -1656,10 +1623,10 @@
}
else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
emit_jump_insn (gen_bne (operands[0]));
DONE;
- }
+ }
operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);
}")
@@ -1690,10 +1657,10 @@
}
else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
emit_jump_insn (gen_bne (operands[0]));
DONE;
- }
+ }
operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1);
}")
@@ -1724,10 +1691,10 @@
}
else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
emit_jump_insn (gen_bne (operands[0]));
DONE;
- }
+ }
operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1);
}")
@@ -1758,10 +1725,10 @@
}
else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
- emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
emit_jump_insn (gen_bne (operands[0]));
DONE;
- }
+ }
operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1);
}")
@@ -1774,6 +1741,145 @@
"
{ operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
}")
+
+(define_expand "bunordered"
+ [(set (pc)
+ (if_then_else (unordered (match_dup 1) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
+ {
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1,
+ UNORDERED);
+ emit_jump_insn (gen_beq (operands[0]));
+ DONE;
+ }
+ operands[1] = gen_compare_reg (UNORDERED, sparc_compare_op0,
+ sparc_compare_op1);
+}")
+
+(define_expand "bordered"
+ [(set (pc)
+ (if_then_else (ordered (match_dup 1) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
+ {
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, ORDERED);
+ emit_jump_insn (gen_bne (operands[0]));
+ DONE;
+ }
+ operands[1] = gen_compare_reg (ORDERED, sparc_compare_op0,
+ sparc_compare_op1);
+}")
+
+(define_expand "bungt"
+ [(set (pc)
+ (if_then_else (ungt (match_dup 1) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
+ {
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGT);
+ emit_jump_insn (gen_bgt (operands[0]));
+ DONE;
+ }
+ operands[1] = gen_compare_reg (UNGT, sparc_compare_op0, sparc_compare_op1);
+}")
+
+(define_expand "bunlt"
+ [(set (pc)
+ (if_then_else (unlt (match_dup 1) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
+ {
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLT);
+ emit_jump_insn (gen_bne (operands[0]));
+ DONE;
+ }
+ operands[1] = gen_compare_reg (UNLT, sparc_compare_op0, sparc_compare_op1);
+}")
+
+(define_expand "buneq"
+ [(set (pc)
+ (if_then_else (uneq (match_dup 1) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
+ {
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNEQ);
+ emit_jump_insn (gen_beq (operands[0]));
+ DONE;
+ }
+ operands[1] = gen_compare_reg (UNEQ, sparc_compare_op0, sparc_compare_op1);
+}")
+
+(define_expand "bunge"
+ [(set (pc)
+ (if_then_else (unge (match_dup 1) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
+ {
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGE);
+ emit_jump_insn (gen_bne (operands[0]));
+ DONE;
+ }
+ operands[1] = gen_compare_reg (UNGE, sparc_compare_op0, sparc_compare_op1);
+}")
+
+(define_expand "bunle"
+ [(set (pc)
+ (if_then_else (unle (match_dup 1) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
+ {
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLE);
+ emit_jump_insn (gen_bne (operands[0]));
+ DONE;
+ }
+ operands[1] = gen_compare_reg (UNLE, sparc_compare_op0, sparc_compare_op1);
+}")
+
+(define_expand "bltgt"
+ [(set (pc)
+ (if_then_else (ltgt (match_dup 1) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
+ {
+ sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LTGT);
+ emit_jump_insn (gen_bne (operands[0]));
+ DONE;
+ }
+ operands[1] = gen_compare_reg (LTGT, sparc_compare_op0, sparc_compare_op1);
+}")
;; Now match both normal and inverted jump.
@@ -1924,14 +2030,15 @@
(unspec [(match_operand 1 "" "") (match_operand 2 "" "")] 2))]
"flag_pic && REGNO (operands[0]) == 23"
"sethi\\t%%hi(%a1-4), %0\\n\\tcall\\t%a2\\n\\tadd\\t%0, %%lo(%a1+4), %0"
- [(set_attr "length" "3")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "3")])
;; Currently unused...
;; (define_insn "get_pc_via_rdpc"
;; [(set (match_operand 0 "register_operand" "=r") (pc))]
;; "TARGET_V9"
;; "rd\\t%%pc, %0"
-;; [(set_attr "type" "move")])
+;; [(set_attr "type" "misc")])
;; Move instructions
@@ -1959,7 +2066,6 @@
/* Handle sets of MEM first. */
if (GET_CODE (operands[0]) == MEM)
{
- /* This checks TARGET_LIVE_G0 for us. */
if (reg_or_0_operand (operands[1], QImode))
goto movqi_is_ok;
@@ -1995,7 +2101,7 @@
}")
(define_insn "*movqi_insn"
- [(set (match_operand:QI 0 "general_operand" "=r,r,m")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m")
(match_operand:QI 1 "input_operand" "rI,m,rJ"))]
"(register_operand (operands[0], QImode)
|| reg_or_0_operand (operands[1], QImode))"
@@ -2003,8 +2109,7 @@
mov\\t%1, %0
ldub\\t%1, %0
stb\\t%r1, %0"
- [(set_attr "type" "move,load,store")
- (set_attr "length" "1")])
+ [(set_attr "type" "*,load,store")])
(define_expand "movhi"
[(set (match_operand:HI 0 "general_operand" "")
@@ -2020,7 +2125,6 @@
/* Handle sets of MEM first. */
if (GET_CODE (operands[0]) == MEM)
{
- /* This checks TARGET_LIVE_G0 for us. */
if (reg_or_0_operand (operands[1], HImode))
goto movhi_is_ok;
@@ -2049,7 +2153,7 @@
}
}
- /* This makes sure we will not get rematched due to splittage. */
+ /* This makes sure we will not get rematched due to splittage. */
if (! CONSTANT_P (operands[1]) || input_operand (operands[1], HImode))
;
else if (CONSTANT_P (operands[1])
@@ -2067,12 +2171,10 @@
[(set (match_operand:HI 0 "register_operand" "=r")
(match_operand:HI 1 "const64_high_operand" ""))]
"TARGET_ARCH64"
- "sethi\\t%%hi(%a1), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "sethi\\t%%hi(%a1), %0")
(define_insn "*movhi_insn"
- [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
(match_operand:HI 1 "input_operand" "rI,K,m,rJ"))]
"(register_operand (operands[0], HImode)
|| reg_or_0_operand (operands[1], HImode))"
@@ -2081,8 +2183,7 @@
sethi\\t%%hi(%a1), %0
lduh\\t%1, %0
sth\\t%r1, %0"
- [(set_attr "type" "move,move,load,store")
- (set_attr "length" "1")])
+ [(set_attr "type" "*,*,load,store")])
;; We always work with constants here.
(define_insn "*movhi_lo_sum"
@@ -2090,9 +2191,7 @@
(ior:HI (match_operand:HI 1 "arith_operand" "%r")
(match_operand:HI 2 "arith_operand" "I")))]
""
- "or\\t%1, %2, %0"
- [(set_attr "type" "ialu")
- (set_attr "length" "1")])
+ "or\\t%1, %2, %0")
(define_expand "movsi"
[(set (match_operand:SI 0 "general_operand" "")
@@ -2108,7 +2207,6 @@
/* Handle sets of MEM first. */
if (GET_CODE (operands[0]) == MEM)
{
- /* This checks TARGET_LIVE_G0 for us. */
if (reg_or_0_operand (operands[1], SImode))
goto movsi_is_ok;
@@ -2153,7 +2251,7 @@
operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
operands[1]));
- /* This makes sure we will not get rematched due to splittage. */
+ /* This makes sure we will not get rematched due to splittage. */
if (! CONSTANT_P (operands[1]) || input_operand (operands[1], SImode))
;
else if (CONSTANT_P (operands[1])
@@ -2167,27 +2265,16 @@
;
}")
-;; Special LIVE_G0 pattern to obtain zero in a register.
-(define_insn "*movsi_zero_liveg0"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operand:SI 1 "zero_operand" "J"))]
- "TARGET_LIVE_G0"
- "and\\t%0, 0, %0"
- [(set_attr "type" "binary")
- (set_attr "length" "1")])
-
;; This is needed to show CSE exactly which bits are set
;; in a 64-bit register by sethi instructions.
(define_insn "*movsi_const64_special"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operand:SI 1 "const64_high_operand" ""))]
"TARGET_ARCH64"
- "sethi\\t%%hi(%a1), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "sethi\\t%%hi(%a1), %0")
(define_insn "*movsi_insn"
- [(set (match_operand:SI 0 "general_operand" "=r,f,r,r,r,f,m,m,d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,f,r,r,r,f,m,m,d")
(match_operand:SI 1 "input_operand" "rI,!f,K,J,m,!m,rJ,!f,J"))]
"(register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))"
@@ -2201,25 +2288,20 @@
st\\t%r1, %0
st\\t%1, %0
fzeros\\t%0"
- [(set_attr "type" "move,fpmove,move,move,load,fpload,store,fpstore,fpmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "*,fpmove,*,*,load,fpload,store,fpstore,fpmove")])
(define_insn "*movsi_lo_sum"
[(set (match_operand:SI 0 "register_operand" "=r")
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "immediate_operand" "in")))]
""
- "or\\t%1, %%lo(%a2), %0"
- [(set_attr "type" "ialu")
- (set_attr "length" "1")])
+ "or\\t%1, %%lo(%a2), %0")
(define_insn "*movsi_high"
[(set (match_operand:SI 0 "register_operand" "=r")
(high:SI (match_operand:SI 1 "immediate_operand" "in")))]
""
- "sethi\\t%%hi(%a1), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "sethi\\t%%hi(%a1), %0")
;; The next two patterns must wrap the SYMBOL_REF in an UNSPEC
;; so that CSE won't optimize the address computation away.
@@ -2228,17 +2310,13 @@
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
(unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))]
"flag_pic"
- "or\\t%1, %%lo(%a2), %0"
- [(set_attr "type" "ialu")
- (set_attr "length" "1")])
+ "or\\t%1, %%lo(%a2), %0")
(define_insn "movsi_high_pic"
[(set (match_operand:SI 0 "register_operand" "=r")
(high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
"flag_pic && check_pic (1)"
- "sethi\\t%%hi(%a1), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "sethi\\t%%hi(%a1), %0")
(define_expand "movsi_pic_label_ref"
[(set (match_dup 3) (high:SI
@@ -2253,8 +2331,16 @@
{
current_function_uses_pic_offset_table = 1;
operands[2] = gen_rtx_SYMBOL_REF (Pmode, \"_GLOBAL_OFFSET_TABLE_\");
- operands[3] = gen_reg_rtx (SImode);
- operands[4] = gen_reg_rtx (SImode);
+ if (no_new_pseudos)
+ {
+ operands[3] = operands[0];
+ operands[4] = operands[0];
+ }
+ else
+ {
+ operands[3] = gen_reg_rtx (SImode);
+ operands[4] = gen_reg_rtx (SImode);
+ }
operands[5] = pic_offset_table_rtx;
}")
@@ -2264,9 +2350,7 @@
(unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
(match_operand:SI 2 "" "")] 5)))]
"flag_pic"
- "sethi\\t%%hi(%a2-(%a1-.)), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "sethi\\t%%hi(%a2-(%a1-.)), %0")
(define_insn "*movsi_lo_sum_pic_label_ref"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -2274,9 +2358,7 @@
(unspec:SI [(match_operand:SI 2 "label_ref_operand" "")
(match_operand:SI 3 "" "")] 5)))]
"flag_pic"
- "or\\t%1, %%lo(%a3-(%a2-.)), %0"
- [(set_attr "type" "ialu")
- (set_attr "length" "1")])
+ "or\\t%1, %%lo(%a3-(%a2-.)), %0")
(define_expand "movdi"
[(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
@@ -2302,7 +2384,7 @@
The const zero case is more complex, on v9
we can always perform it. */
if (register_operand (operands[1], DImode)
- || (TARGET_ARCH64
+ || (TARGET_V9
&& (operands[1] == const0_rtx)))
goto movdi_is_ok;
@@ -2347,7 +2429,7 @@
operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
operands[1]));
- /* This makes sure we will not get rematched due to splittage. */
+ /* This makes sure we will not get rematched due to splittage. */
if (! CONSTANT_P (operands[1]) || input_operand (operands[1], DImode))
;
else if (TARGET_ARCH64
@@ -2374,12 +2456,38 @@
;; (const_int -5016)))
;; (reg:DI 2 %g2))
;;
+
+(define_insn "*movdi_insn_sp32_v9"
+ [(set (match_operand:DI 0 "nonimmediate_operand"
+ "=m,T,U,o,r,r,r,?T,?f,?f,?o,?f")
+ (match_operand:DI 1 "input_operand"
+ " J,U,T,r,o,i,r, f, T, o, f, f"))]
+ "! TARGET_ARCH64 && TARGET_V9
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "@
+ stx\\t%%g0, %0
+ std\\t%1, %0
+ ldd\\t%1, %0
+ #
+ #
+ #
+ #
+ std\\t%1, %0
+ ldd\\t%1, %0
+ #
+ #
+ #"
+ [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
+ (set_attr "length" "*,*,*,2,2,2,2,*,*,2,2,2")])
+
(define_insn "*movdi_insn_sp32"
- [(set (match_operand:DI 0 "general_operand" "=T,U,o,r,r,r,?T,?f,?f,?o,?f")
- (match_operand:DI 1 "input_operand" "U,T,r,o,i,r,f,T,o,f,f"))]
- "! TARGET_ARCH64 &&
- (register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode))"
+ [(set (match_operand:DI 0 "nonimmediate_operand"
+ "=T,U,o,r,r,r,?T,?f,?f,?o,?f")
+ (match_operand:DI 1 "input_operand"
+ " U,T,r,o,i,r, f, T, o, f, f"))]
+ "! TARGET_ARCH64
+ && (register_operand (operands[0], DImode)
+ || register_operand (operands[1], DImode))"
"@
std\\t%1, %0
ldd\\t%1, %0
@@ -2393,7 +2501,7 @@
#
#"
[(set_attr "type" "store,load,*,*,*,*,fpstore,fpload,*,*,*")
- (set_attr "length" "1,1,2,2,2,2,1,1,2,2,2")])
+ (set_attr "length" "*,*,2,2,2,2,*,*,2,2,2")])
;; The following are generated by sparc_emit_set_const64
(define_insn "*movdi_sp64_dbl"
@@ -2401,9 +2509,7 @@
(match_operand:DI 1 "const64_operand" ""))]
"(TARGET_ARCH64
&& HOST_BITS_PER_WIDE_INT != 64)"
- "mov\\t%1, %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "mov\\t%1, %0")
;; This is needed to show CSE exactly which bits are set
;; in a 64-bit register by sethi instructions.
@@ -2411,14 +2517,30 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(match_operand:DI 1 "const64_high_operand" ""))]
"TARGET_ARCH64"
- "sethi\\t%%hi(%a1), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "sethi\\t%%hi(%a1), %0")
+
+(define_insn "*movdi_insn_sp64_novis"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?m")
+ (match_operand:DI 1 "input_operand" "rI,K,J,m,rJ,e,m,e"))]
+ "TARGET_ARCH64 && ! TARGET_VIS
+ && (register_operand (operands[0], DImode)
+ || reg_or_0_operand (operands[1], DImode))"
+ "@
+ mov\\t%1, %0
+ sethi\\t%%hi(%a1), %0
+ clr\\t%0
+ ldx\\t%1, %0
+ stx\\t%r1, %0
+ fmovd\\t%1, %0
+ ldd\\t%1, %0
+ std\\t%1, %0"
+ [(set_attr "type" "*,*,*,load,store,fpmove,fpload,fpstore")
+ (set_attr "fptype" "*,*,*,*,*,double,*,*")])
-(define_insn "*movdi_insn_sp64"
- [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,m,?e,?e,?m,b")
+(define_insn "*movdi_insn_sp64_vis"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?m,b")
(match_operand:DI 1 "input_operand" "rI,K,J,m,rJ,e,m,e,J"))]
- "TARGET_ARCH64 &&
+ "TARGET_ARCH64 && TARGET_VIS &&
(register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
"@
@@ -2431,8 +2553,8 @@
ldd\\t%1, %0
std\\t%1, %0
fzero\\t%0"
- [(set_attr "type" "move,move,move,load,store,fpmove,fpload,fpstore,fpmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "*,*,*,load,store,fpmove,fpload,fpstore,fpmove")
+ (set_attr "fptype" "*,*,*,*,*,double,*,*,double")])
(define_expand "movdi_pic_label_ref"
[(set (match_dup 3) (high:DI
@@ -2447,8 +2569,16 @@
{
current_function_uses_pic_offset_table = 1;
operands[2] = gen_rtx_SYMBOL_REF (Pmode, \"_GLOBAL_OFFSET_TABLE_\");
- operands[3] = gen_reg_rtx (DImode);
- operands[4] = gen_reg_rtx (DImode);
+ if (no_new_pseudos)
+ {
+ operands[3] = operands[0];
+ operands[4] = operands[0];
+ }
+ else
+ {
+ operands[3] = gen_reg_rtx (DImode);
+ operands[4] = gen_reg_rtx (DImode);
+ }
operands[5] = pic_offset_table_rtx;
}")
@@ -2458,9 +2588,7 @@
(unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
(match_operand:DI 2 "" "")] 5)))]
"TARGET_ARCH64 && flag_pic"
- "sethi\\t%%hi(%a2-(%a1-.)), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "sethi\\t%%hi(%a2-(%a1-.)), %0")
(define_insn "*movdi_lo_sum_pic_label_ref"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -2468,9 +2596,7 @@
(unspec:DI [(match_operand:DI 2 "label_ref_operand" "")
(match_operand:DI 3 "" "")] 5)))]
"TARGET_ARCH64 && flag_pic"
- "or\\t%1, %%lo(%a3-(%a2-.)), %0"
- [(set_attr "type" "ialu")
- (set_attr "length" "1")])
+ "or\\t%1, %%lo(%a3-(%a2-.)), %0")
;; Sparc-v9 code model support insns. See sparc_emit_set_symbolic_const64
;; in sparc.c to see what is going on here... PIC stuff comes first.
@@ -2480,160 +2606,123 @@
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(unspec:DI [(match_operand:DI 2 "immediate_operand" "in")] 0)))]
"TARGET_ARCH64 && flag_pic"
- "or\\t%1, %%lo(%a2), %0"
- [(set_attr "type" "ialu")
- (set_attr "length" "1")])
+ "or\\t%1, %%lo(%a2), %0")
(define_insn "movdi_high_pic"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (unspec:DI [(match_operand 1 "" "")] 0)))]
"TARGET_ARCH64 && flag_pic && check_pic (1)"
- "sethi\\t%%hi(%a1), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "sethi\\t%%hi(%a1), %0")
(define_insn "*sethi_di_medlow_embmedany_pic"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (match_operand:DI 1 "sp64_medium_pic_operand" "")))]
"(TARGET_CM_MEDLOW || TARGET_CM_EMBMEDANY) && check_pic (1)"
- "sethi\\t%%lo(%a1), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "sethi\\t%%hi(%a1), %0")
(define_insn "*sethi_di_medlow"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (match_operand:DI 1 "symbolic_operand" "")))]
"TARGET_CM_MEDLOW && check_pic (1)"
- "sethi\\t%%hi(%a1), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "sethi\\t%%hi(%a1), %0")
(define_insn "*losum_di_medlow"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "symbolic_operand" "")))]
"TARGET_CM_MEDLOW"
- "or\\t%1, %%lo(%a2), %0"
- [(set_attr "type" "ialu")
- (set_attr "length" "1")])
+ "or\\t%1, %%lo(%a2), %0")
(define_insn "seth44"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] 6)))]
"TARGET_CM_MEDMID"
- "sethi\\t%%h44(%a1), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "sethi\\t%%h44(%a1), %0")
(define_insn "setm44"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] 7)))]
"TARGET_CM_MEDMID"
- "or\\t%1, %%m44(%a2), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "or\\t%1, %%m44(%a2), %0")
(define_insn "setl44"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "symbolic_operand" "")))]
"TARGET_CM_MEDMID"
- "or\\t%1, %%l44(%a2), %0"
- [(set_attr "type" "ialu")
- (set_attr "length" "1")])
+ "or\\t%1, %%l44(%a2), %0")
(define_insn "sethh"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] 9)))]
"TARGET_CM_MEDANY"
- "sethi\\t%%hh(%a1), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "sethi\\t%%hh(%a1), %0")
(define_insn "setlm"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] 10)))]
"TARGET_CM_MEDANY"
- "sethi\\t%%lm(%a1), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "sethi\\t%%lm(%a1), %0")
(define_insn "sethm"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] 18)))]
"TARGET_CM_MEDANY"
- "or\\t%1, %%hm(%a2), %0"
- [(set_attr "type" "ialu")
- (set_attr "length" "1")])
+ "or\\t%1, %%hm(%a2), %0")
(define_insn "setlo"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "symbolic_operand" "")))]
"TARGET_CM_MEDANY"
- "or\\t%1, %%lo(%a2), %0"
- [(set_attr "type" "ialu")
- (set_attr "length" "1")])
+ "or\\t%1, %%lo(%a2), %0")
(define_insn "embmedany_sethi"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (unspec:DI [(match_operand:DI 1 "data_segment_operand" "")] 11)))]
"TARGET_CM_EMBMEDANY && check_pic (1)"
- "sethi\\t%%hi(%a1), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "sethi\\t%%hi(%a1), %0")
(define_insn "embmedany_losum"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "data_segment_operand" "")))]
"TARGET_CM_EMBMEDANY"
- "add\\t%1, %%lo(%a2), %0"
- [(set_attr "type" "ialu")
- (set_attr "length" "1")])
+ "add\\t%1, %%lo(%a2), %0")
(define_insn "embmedany_brsum"
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(match_operand:DI 1 "register_operand" "r")] 11))]
"TARGET_CM_EMBMEDANY"
- "add\\t%1, %_, %0"
- [(set_attr "length" "1")])
+ "add\\t%1, %_, %0")
(define_insn "embmedany_textuhi"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] 13)))]
"TARGET_CM_EMBMEDANY && check_pic (1)"
- "sethi\\t%%uhi(%a1), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "sethi\\t%%uhi(%a1), %0")
(define_insn "embmedany_texthi"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] 14)))]
"TARGET_CM_EMBMEDANY && check_pic (1)"
- "sethi\\t%%hi(%a1), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ "sethi\\t%%hi(%a1), %0")
(define_insn "embmedany_textulo"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(unspec:DI [(match_operand:DI 2 "text_segment_operand" "")] 15)))]
"TARGET_CM_EMBMEDANY"
- "or\\t%1, %%ulo(%a2), %0"
- [(set_attr "type" "ialu")
- (set_attr "length" "1")])
+ "or\\t%1, %%ulo(%a2), %0")
(define_insn "embmedany_textlo"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "text_segment_operand" "")))]
"TARGET_CM_EMBMEDANY"
- "or\\t%1, %%lo(%a2), %0"
- [(set_attr "type" "ialu")
- (set_attr "length" "1")])
+ "or\\t%1, %%lo(%a2), %0")
;; Now some patterns to help reload out a bit.
(define_expand "reload_indi"
@@ -2672,12 +2761,28 @@
[(clobber (const_int 0))]
"
{
+#if HOST_BITS_PER_WIDE_INT == 32
emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
(INTVAL (operands[1]) < 0) ?
constm1_rtx :
const0_rtx));
emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
operands[1]));
+#else
+ unsigned int low, high;
+
+ low = INTVAL (operands[1]) & 0xffffffff;
+ high = (INTVAL (operands[1]) >> 32) & 0xffffffff;
+ emit_insn (gen_movsi (gen_highpart (SImode, operands[0]), GEN_INT (high)));
+
+ /* Slick... but this trick loses if this subreg constant part
+ can be done in one insn. */
+ if (low == high && (low & 0x3ff) != 0 && low + 0x1000 >= 0x2000)
+ emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
+ gen_highpart (SImode, operands[0])));
+ else
+ emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]), GEN_INT (low)));
+#endif
DONE;
}")
@@ -2720,11 +2825,6 @@
rtx dest1, dest2;
rtx src1, src2;
- if (GET_CODE (set_dest) == SUBREG)
- set_dest = alter_subreg (set_dest);
- if (GET_CODE (set_src) == SUBREG)
- set_src = alter_subreg (set_src);
-
dest1 = gen_highpart (SImode, set_dest);
dest2 = gen_lowpart (SImode, set_dest);
src1 = gen_highpart (SImode, set_src);
@@ -2756,9 +2856,8 @@
[(clobber (const_int 0))]
"
{
- rtx word0 = change_address (operands[1], SImode, NULL_RTX);
- rtx word1 = change_address (operands[1], SImode,
- plus_constant_for_output (XEXP (word0, 0), 4));
+ rtx word0 = adjust_address (operands[1], SImode, 0);
+ rtx word1 = adjust_address (operands[1], SImode, 4);
rtx high_part = gen_highpart (SImode, operands[0]);
rtx low_part = gen_lowpart (SImode, operands[0]);
@@ -2784,92 +2883,177 @@
[(clobber (const_int 0))]
"
{
- rtx word0 = change_address (operands[0], SImode, NULL_RTX);
- rtx word1 = change_address (operands[0], SImode,
- plus_constant_for_output (XEXP (word0, 0), 4));
- rtx high_part = gen_highpart (SImode, operands[1]);
- rtx low_part = gen_lowpart (SImode, operands[1]);
-
- emit_insn (gen_movsi (word0, high_part));
- emit_insn (gen_movsi (word1, low_part));
+ emit_insn (gen_movsi (adjust_address (operands[0], SImode, 0),
+ gen_highpart (SImode, operands[1])));
+ emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4),
+ gen_lowpart (SImode, operands[1])));
DONE;
}")
;; Floating point move insns
-(define_insn "*clear_sf"
- [(set (match_operand:SF 0 "general_operand" "=f")
- (match_operand:SF 1 "" ""))]
- "TARGET_VIS
- && GET_CODE (operands[1]) == CONST_DOUBLE
- && GET_CODE (operands[0]) == REG
- && fp_zero_operand (operands[1])"
- "fzeros\\t%0"
- [(set_attr "type" "fpmove")
- (set_attr "length" "1")])
+(define_insn "*movsf_insn_novis"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,*r,*r,*r,*r,*r,f,m,m")
+ (match_operand:SF 1 "input_operand" "f,G,Q,*rR,S,m,m,f,*rG"))]
+ "(TARGET_FPU && ! TARGET_VIS)
+ && (register_operand (operands[0], SFmode)
+ || register_operand (operands[1], SFmode)
+ || fp_zero_operand (operands[1], SFmode))"
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_DOUBLE
+ && (which_alternative == 2
+ || which_alternative == 3
+ || which_alternative == 4))
+ {
+ REAL_VALUE_TYPE r;
+ long i;
-(define_insn "*movsf_const_intreg"
- [(set (match_operand:SF 0 "general_operand" "=f,r")
- (match_operand:SF 1 "" "m,F"))]
- "TARGET_FPU
- && GET_CODE (operands[1]) == CONST_DOUBLE
- && GET_CODE (operands[0]) == REG"
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+ REAL_VALUE_TO_TARGET_SINGLE (r, i);
+ operands[1] = GEN_INT (i);
+ }
+
+ switch (which_alternative)
+ {
+ case 0:
+ return \"fmovs\\t%1, %0\";
+ case 1:
+ return \"clr\\t%0\";
+ case 2:
+ return \"sethi\\t%%hi(%a1), %0\";
+ case 3:
+ return \"mov\\t%1, %0\";
+ case 4:
+ return \"#\";
+ case 5:
+ case 6:
+ return \"ld\\t%1, %0\";
+ case 7:
+ case 8:
+ return \"st\\t%r1, %0\";
+ default:
+ abort();
+ }
+}"
+ [(set_attr "type" "fpmove,*,*,*,*,load,fpload,fpstore,store")])
+
+(define_insn "*movsf_insn_vis"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,*r,*r,*r,*r,*r,f,m,m")
+ (match_operand:SF 1 "input_operand" "f,G,G,Q,*rR,S,m,m,f,*rG"))]
+ "(TARGET_FPU && TARGET_VIS)
+ && (register_operand (operands[0], SFmode)
+ || register_operand (operands[1], SFmode)
+ || fp_zero_operand (operands[1], SFmode))"
"*
{
- REAL_VALUE_TYPE r;
- long i;
+ if (GET_CODE (operands[1]) == CONST_DOUBLE
+ && (which_alternative == 3
+ || which_alternative == 4
+ || which_alternative == 5))
+ {
+ REAL_VALUE_TYPE r;
+ long i;
- if (which_alternative == 0)
- return \"ld\\t%1, %0\";
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+ REAL_VALUE_TO_TARGET_SINGLE (r, i);
+ operands[1] = GEN_INT (i);
+ }
- REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
- REAL_VALUE_TO_TARGET_SINGLE (r, i);
- if (SPARC_SIMM13_P (i) || SPARC_SETHI_P (i))
+ switch (which_alternative)
{
+ case 0:
+ return \"fmovs\\t%1, %0\";
+ case 1:
+ return \"fzeros\\t%0\";
+ case 2:
+ return \"clr\\t%0\";
+ case 3:
+ return \"sethi\\t%%hi(%a1), %0\";
+ case 4:
+ return \"mov\\t%1, %0\";
+ case 5:
+ return \"#\";
+ case 6:
+ case 7:
+ return \"ld\\t%1, %0\";
+ case 8:
+ case 9:
+ return \"st\\t%r1, %0\";
+ default:
+ abort();
+ }
+}"
+ [(set_attr "type" "fpmove,fpmove,*,*,*,*,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
+;; when -mno-fpu.
+
+(define_insn "*movsf_no_f_insn"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,r,r,m")
+ (match_operand:SF 1 "input_operand" "G,Q,rR,S,m,rG"))]
+ "! TARGET_FPU
+ && (register_operand (operands[0], SFmode)
+ || register_operand (operands[1], SFmode)
+ || fp_zero_operand (operands[1], SFmode))"
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_DOUBLE
+ && (which_alternative == 1
+ || which_alternative == 2
+ || which_alternative == 3))
+ {
+ REAL_VALUE_TYPE r;
+ long i;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+ REAL_VALUE_TO_TARGET_SINGLE (r, i);
operands[1] = GEN_INT (i);
- if (SPARC_SIMM13_P (INTVAL (operands[1])))
- return \"mov\\t%1, %0\";
- else if (SPARC_SETHI_P (INTVAL (operands[1])))
- return \"sethi\\t%%hi(%a1), %0\";
- else
- abort ();
}
- else
- return \"#\";
+
+ switch (which_alternative)
+ {
+ case 0:
+ return \"clr\\t%0\";
+ case 1:
+ return \"sethi\\t%%hi(%a1), %0\";
+ case 2:
+ return \"mov\\t%1, %0\";
+ case 3:
+ return \"#\";
+ case 4:
+ return \"ld\\t%1, %0\";
+ case 5:
+ return \"st\\t%r1, %0\";
+ default:
+ abort();
+ }
}"
- [(set_attr "type" "move")
- (set_attr "length" "1,2")])
+ [(set_attr "type" "*,*,*,*,load,store")])
-;; There isn't much I can do about this, if I change the
-;; mode then flow info gets really confused because the
-;; destination no longer looks the same. Ho hum...
-(define_insn "*movsf_const_high"
+(define_insn "*movsf_lo_sum"
[(set (match_operand:SF 0 "register_operand" "=r")
- (unspec:SF [(match_operand 1 "const_int_operand" "")] 12))]
- ""
- "sethi\\t%%hi(%a1), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ (lo_sum:SF (match_operand:SF 1 "register_operand" "r")
+ (match_operand:SF 2 "const_double_operand" "S")))]
+ "fp_high_losum_p (operands[2])"
+ "*
+{
+ REAL_VALUE_TYPE r;
+ long i;
-(define_insn "*movsf_const_lo"
- [(set (match_operand:SF 0 "register_operand" "=r")
- (unspec:SF [(match_operand 1 "register_operand" "r")
- (match_operand 2 "const_int_operand" "")] 17))]
- ""
- "or\\t%1, %%lo(%a2), %0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
+ REAL_VALUE_TO_TARGET_SINGLE (r, i);
+ operands[2] = GEN_INT (i);
+ return \"or\\t%1, %%lo(%a2), %0\";
+}")
-(define_split
- [(set (match_operand:SF 0 "register_operand" "")
- (match_operand:SF 1 "const_double_operand" ""))]
- "TARGET_FPU
- && (GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)"
- [(set (match_dup 0) (unspec:SF [(match_dup 1)] 12))
- (set (match_dup 0) (unspec:SF [(match_dup 0) (match_dup 1)] 17))]
- "
+(define_insn "*movsf_high"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (high:SF (match_operand:SF 1 "const_double_operand" "S")))]
+ "fp_high_losum_p (operands[1])"
+ "*
{
REAL_VALUE_TYPE r;
long i;
@@ -2877,8 +3061,18 @@
REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
REAL_VALUE_TO_TARGET_SINGLE (r, i);
operands[1] = GEN_INT (i);
+ return \"sethi\\t%%hi(%1), %0\";
}")
+(define_split
+ [(set (match_operand:SF 0 "register_operand" "")
+ (match_operand:SF 1 "const_double_operand" ""))]
+ "fp_high_losum_p (operands[1])
+ && (GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) < 32)"
+ [(set (match_dup 0) (high:SF (match_dup 1)))
+ (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
+
(define_expand "movsf"
[(set (match_operand:SF 0 "general_operand" "")
(match_operand:SF 1 "general_operand" ""))]
@@ -2889,16 +3083,20 @@
if (GET_CODE (operands[0]) == REG
&& CONSTANT_P (operands[1]))
{
- if (TARGET_VIS
- && GET_CODE (operands[1]) == CONST_DOUBLE
- && fp_zero_operand (operands[1]))
- goto movsf_is_ok;
-
/* emit_group_store will send such bogosity to us when it is
not storing directly into memory. So fix this up to avoid
crashes in output_constant_pool. */
if (operands [1] == const0_rtx)
operands[1] = CONST0_RTX (SFmode);
+
+ if (TARGET_VIS && fp_zero_operand (operands[1], SFmode))
+ goto movsf_is_ok;
+
+ /* We are able to build any SF constant in integer registers
+ with at most 2 instructions. */
+ if (REGNO (operands[0]) < 32)
+ goto movsf_is_ok;
+
operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
operands[1]));
}
@@ -2906,7 +3104,8 @@
/* Handle sets of MEM first. */
if (GET_CODE (operands[0]) == MEM)
{
- if (register_operand (operands[1], SFmode))
+ if (register_operand (operands[1], SFmode)
+ || fp_zero_operand (operands[1], SFmode))
goto movsf_is_ok;
if (! reload_in_progress)
@@ -2937,142 +3136,6 @@
;
}")
-(define_insn "*movsf_insn"
- [(set (match_operand:SF 0 "general_operand" "=f,f,m,r,r,m")
- (match_operand:SF 1 "input_operand" "f,m,f,r,m,r"))]
- "TARGET_FPU
- && (register_operand (operands[0], SFmode)
- || register_operand (operands[1], SFmode))"
- "@
- fmovs\\t%1, %0
- ld\\t%1, %0
- st\\t%1, %0
- mov\\t%1, %0
- ld\\t%1, %0
- st\\t%1, %0"
- [(set_attr "type" "fpmove,fpload,fpstore,move,load,store")
- (set_attr "length" "1")])
-
-;; 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
-;; when -mno-fpu.
-
-(define_insn "*movsf_no_f_insn"
- [(set (match_operand:SF 0 "general_operand" "=r,r,m")
- (match_operand:SF 1 "input_operand" "r,m,r"))]
- "! TARGET_FPU
- && (register_operand (operands[0], SFmode)
- || register_operand (operands[1], SFmode))"
- "@
- mov\\t%1, %0
- ld\\t%1, %0
- st\\t%1, %0"
- [(set_attr "type" "move,load,store")
- (set_attr "length" "1")])
-
-(define_insn "*clear_df"
- [(set (match_operand:DF 0 "general_operand" "=e")
- (match_operand:DF 1 "" ""))]
- "TARGET_VIS
- && GET_CODE (operands[1]) == CONST_DOUBLE
- && GET_CODE (operands[0]) == REG
- && fp_zero_operand (operands[1])"
- "fzero\\t%0"
- [(set_attr "type" "fpmove")
- (set_attr "length" "1")])
-
-(define_insn "*movdf_const_intreg_sp32"
- [(set (match_operand:DF 0 "general_operand" "=e,e,r")
- (match_operand:DF 1 "" "T,o,F"))]
- "TARGET_FPU && ! TARGET_ARCH64
- && GET_CODE (operands[1]) == CONST_DOUBLE
- && GET_CODE (operands[0]) == REG"
- "*
-{
- if (which_alternative == 0)
- return \"ldd\\t%1, %0\";
- else
- return \"#\";
-}"
- [(set_attr "type" "move")
- (set_attr "length" "1,2,2")])
-
-;; Now that we redo life analysis with a clean slate after
-;; instruction splitting for sched2 this can work.
-(define_insn "*movdf_const_intreg_sp64"
- [(set (match_operand:DF 0 "general_operand" "=e,e,r")
- (match_operand:DF 1 "" "m,o,F"))]
- "TARGET_FPU
- && TARGET_ARCH64
- && GET_CODE (operands[1]) == CONST_DOUBLE
- && GET_CODE (operands[0]) == REG"
- "*
-{
- if (which_alternative == 0)
- return \"ldd\\t%1, %0\";
- else
- return \"#\";
-}"
- [(set_attr "type" "move")
- (set_attr "length" "1,2,2")])
-
-(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (match_operand:DF 1 "const_double_operand" ""))]
- "TARGET_FPU
- && GET_CODE (operands[1]) == CONST_DOUBLE
- && (GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
- && reload_completed"
- [(clobber (const_int 0))]
- "
-{
- REAL_VALUE_TYPE r;
- long l[2];
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
- REAL_VALUE_TO_TARGET_DOUBLE (r, l);
- if (GET_CODE (operands[0]) == SUBREG)
- operands[0] = alter_subreg (operands[0]);
- operands[0] = gen_rtx_raw_REG (DImode, REGNO (operands[0]));
-
- if (TARGET_ARCH64)
- {
-#if HOST_BITS_PER_WIDE_INT == 64
- HOST_WIDE_INT val;
-
- val = ((HOST_WIDE_INT)l[1] |
- ((HOST_WIDE_INT)l[0] << 32));
- emit_insn (gen_movdi (operands[0], GEN_INT (val)));
-#else
- emit_insn (gen_movdi (operands[0],
- gen_rtx_CONST_DOUBLE (VOIDmode, const0_rtx,
- l[1], l[0])));
-#endif
- }
- else
- {
- emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
- GEN_INT (l[0])));
-
- /* Slick... but this trick loses if this subreg constant part
- can be done in one insn. */
- if (l[1] == l[0]
- && !(SPARC_SETHI_P (l[0])
- || SPARC_SIMM13_P (l[0])))
- {
- emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
- gen_highpart (SImode, operands[0])));
- }
- else
- {
- emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
- GEN_INT (l[1])));
- }
- }
- DONE;
-}")
-
(define_expand "movdf"
[(set (match_operand:DF 0 "general_operand" "")
(match_operand:DF 1 "general_operand" ""))]
@@ -3083,16 +3146,21 @@
if (GET_CODE (operands[0]) == REG
&& CONSTANT_P (operands[1]))
{
- if (TARGET_VIS
- && GET_CODE (operands[1]) == CONST_DOUBLE
- && fp_zero_operand (operands[1]))
- goto movdf_is_ok;
-
/* emit_group_store will send such bogosity to us when it is
not storing directly into memory. So fix this up to avoid
crashes in output_constant_pool. */
if (operands [1] == const0_rtx)
operands[1] = CONST0_RTX (DFmode);
+
+ if ((TARGET_VIS || REGNO (operands[0]) < 32)
+ && fp_zero_operand (operands[1], DFmode))
+ goto movdf_is_ok;
+
+ /* We are able to build any DF constant in integer registers. */
+ if (REGNO (operands[0]) < 32
+ && (reload_completed || reload_in_progress))
+ goto movdf_is_ok;
+
operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
operands[1]));
}
@@ -3100,7 +3168,8 @@
/* Handle MEM cases first. */
if (GET_CODE (operands[0]) == MEM)
{
- if (register_operand (operands[1], DFmode))
+ if (register_operand (operands[1], DFmode)
+ || fp_zero_operand (operands[1], DFmode))
goto movdf_is_ok;
if (! reload_in_progress)
@@ -3133,12 +3202,13 @@
;; Be careful, fmovd does not exist when !v9.
(define_insn "*movdf_insn_sp32"
- [(set (match_operand:DF 0 "general_operand" "=e,T,U,T,e,r,r,o,e,o")
- (match_operand:DF 1 "input_operand" "T,e,T,U,e,r,o,r,o,e"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=e,T,U,T,o,e,*r,o,e,o")
+ (match_operand:DF 1 "input_operand" "T#F,e,T,U,G,e,*rFo,*r,o#F,e"))]
"TARGET_FPU
&& ! TARGET_V9
&& (register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode))"
+ || register_operand (operands[1], DFmode)
+ || fp_zero_operand (operands[1], DFmode))"
"@
ldd\\t%1, %0
std\\t%1, %0
@@ -3151,15 +3221,17 @@
#
#"
[(set_attr "type" "fpload,fpstore,load,store,*,*,*,*,*,*")
- (set_attr "length" "1,1,1,1,2,2,2,2,2,2")])
+ (set_attr "length" "*,*,*,*,2,2,2,2,2,2")])
(define_insn "*movdf_no_e_insn_sp32"
- [(set (match_operand:DF 0 "general_operand" "=U,T,r,r,o")
- (match_operand:DF 1 "input_operand" "T,U,r,o,r"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,o,r,o")
+ (match_operand:DF 1 "input_operand" "T,U,G,ro,r"))]
"! TARGET_FPU
+ && ! TARGET_V9
&& ! TARGET_ARCH64
&& (register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode))"
+ || register_operand (operands[1], DFmode)
+ || fp_zero_operand (operands[1], DFmode))"
"@
ldd\\t%1, %0
std\\t%1, %0
@@ -3167,63 +3239,192 @@
#
#"
[(set_attr "type" "load,store,*,*,*")
- (set_attr "length" "1,1,2,2,2")])
+ (set_attr "length" "*,*,2,2,2")])
+
+(define_insn "*movdf_no_e_insn_v9_sp32"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,T,r,o")
+ (match_operand:DF 1 "input_operand" "T,U,G,ro,rG"))]
+ "! TARGET_FPU
+ && TARGET_V9
+ && ! TARGET_ARCH64
+ && (register_operand (operands[0], DFmode)
+ || register_operand (operands[1], DFmode)
+ || fp_zero_operand (operands[1], DFmode))"
+ "@
+ ldd\\t%1, %0
+ std\\t%1, %0
+ stx\\t%r1, %0
+ #
+ #"
+ [(set_attr "type" "load,store,store,*,*")
+ (set_attr "length" "*,*,*,2,2")])
;; We have available v9 double floats but not 64-bit
-;; integer registers.
-(define_insn "*movdf_insn_v9only"
- [(set (match_operand:DF 0 "general_operand" "=e,e,m,U,T,r,r,o")
- (match_operand:DF 1 "input_operand" "e,m,e,T,U,r,o,r"))]
+;; integer registers and no VIS.
+(define_insn "*movdf_insn_v9only_novis"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,T,T,U,T,e,*r,o")
+ (match_operand:DF 1 "input_operand" "e,T#F,G,e,T,U,o#F,*roF,*rGe"))]
"TARGET_FPU
&& TARGET_V9
+ && ! TARGET_VIS
+ && ! TARGET_ARCH64
+ && (register_operand (operands[0], DFmode)
+ || register_operand (operands[1], DFmode)
+ || fp_zero_operand (operands[1], DFmode))"
+ "@
+ fmovd\\t%1, %0
+ ldd\\t%1, %0
+ stx\\t%r1, %0
+ std\\t%1, %0
+ ldd\\t%1, %0
+ std\\t%1, %0
+ #
+ #
+ #"
+ [(set_attr "type" "fpmove,load,store,store,load,store,*,*,*")
+ (set_attr "length" "*,*,*,*,*,*,2,2,2")
+ (set_attr "fptype" "double,*,*,*,*,*,*,*,*")])
+
+;; We have available v9 double floats but not 64-bit
+;; integer registers but we have VIS.
+(define_insn "*movdf_insn_v9only_vis"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,T,T,U,T,e,*r,o")
+ (match_operand:DF 1 "input_operand" "G,e,T#F,G,e,T,U,o#F,*roGF,*rGe"))]
+ "TARGET_FPU
+ && TARGET_VIS
&& ! TARGET_ARCH64
&& (register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode))"
+ || register_operand (operands[1], DFmode)
+ || fp_zero_operand (operands[1], DFmode))"
"@
+ fzero\\t%0
fmovd\\t%1, %0
ldd\\t%1, %0
+ stx\\t%r1, %0
std\\t%1, %0
ldd\\t%1, %0
std\\t%1, %0
#
#
#"
- [(set_attr "type" "fpmove,load,store,load,store,*,*,*")
- (set_attr "length" "1,1,1,1,1,2,2,2")])
+ [(set_attr "type" "fpmove,fpmove,load,store,store,load,store,*,*,*")
+ (set_attr "length" "*,*,*,*,*,*,*,2,2,2")
+ (set_attr "fptype" "double,double,*,*,*,*,*,*,*,*")])
;; We have available both v9 double floats and 64-bit
-;; integer registers.
-(define_insn "*movdf_insn_sp64"
- [(set (match_operand:DF 0 "general_operand" "=e,e,m,r,r,m")
- (match_operand:DF 1 "input_operand" "e,m,e,r,m,r"))]
+;; integer registers. No VIS though.
+(define_insn "*movdf_insn_sp64_novis"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,m,*r,*r,m,*r")
+ (match_operand:DF 1 "input_operand" "e,m#F,e,*rG,m,*rG,F"))]
"TARGET_FPU
- && TARGET_V9
+ && ! TARGET_VIS
&& TARGET_ARCH64
&& (register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode))"
+ || register_operand (operands[1], DFmode)
+ || fp_zero_operand (operands[1], DFmode))"
"@
fmovd\\t%1, %0
ldd\\t%1, %0
std\\t%1, %0
- mov\\t%1, %0
+ mov\\t%r1, %0
ldx\\t%1, %0
- stx\\t%1, %0"
- [(set_attr "type" "fpmove,load,store,move,load,store")
- (set_attr "length" "1")])
+ stx\\t%r1, %0
+ #"
+ [(set_attr "type" "fpmove,load,store,*,load,store,*")
+ (set_attr "length" "*,*,*,*,*,*,2")
+ (set_attr "fptype" "double,*,*,*,*,*,*")])
+
+;; We have available both v9 double floats and 64-bit
+;; integer registers. And we have VIS.
+(define_insn "*movdf_insn_sp64_vis"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,m,*r,*r,m,*r")
+ (match_operand:DF 1 "input_operand" "G,e,m#F,e,*rG,m,*rG,F"))]
+ "TARGET_FPU
+ && TARGET_VIS
+ && TARGET_ARCH64
+ && (register_operand (operands[0], DFmode)
+ || register_operand (operands[1], DFmode)
+ || fp_zero_operand (operands[1], DFmode))"
+ "@
+ fzero\\t%0
+ fmovd\\t%1, %0
+ ldd\\t%1, %0
+ std\\t%1, %0
+ mov\\t%r1, %0
+ ldx\\t%1, %0
+ stx\\t%r1, %0
+ #"
+ [(set_attr "type" "fpmove,fpmove,load,store,*,load,store,*")
+ (set_attr "length" "*,*,*,*,*,*,*,2")
+ (set_attr "fptype" "double,double,*,*,*,*,*,*")])
(define_insn "*movdf_no_e_insn_sp64"
- [(set (match_operand:DF 0 "general_operand" "=r,r,m")
- (match_operand:DF 1 "input_operand" "r,m,r"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
+ (match_operand:DF 1 "input_operand" "r,m,rG"))]
"! TARGET_FPU
&& TARGET_ARCH64
&& (register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode))"
+ || register_operand (operands[1], DFmode)
+ || fp_zero_operand (operands[1], DFmode))"
"@
mov\\t%1, %0
ldx\\t%1, %0
- stx\\t%1, %0"
- [(set_attr "type" "move,load,store")
- (set_attr "length" "1")])
+ stx\\t%r1, %0"
+ [(set_attr "type" "*,load,store")])
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "const_double_operand" ""))]
+ "TARGET_FPU
+ && (GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) < 32)
+ && ! fp_zero_operand(operands[1], DFmode)
+ && reload_completed"
+ [(clobber (const_int 0))]
+ "
+{
+ REAL_VALUE_TYPE r;
+ long l[2];
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+ REAL_VALUE_TO_TARGET_DOUBLE (r, l);
+ operands[0] = gen_rtx_raw_REG (DImode, REGNO (operands[0]));
+
+ if (TARGET_ARCH64)
+ {
+#if HOST_BITS_PER_WIDE_INT == 64
+ HOST_WIDE_INT val;
+
+ val = ((HOST_WIDE_INT)(unsigned long)l[1] |
+ ((HOST_WIDE_INT)(unsigned long)l[0] << 32));
+ emit_insn (gen_movdi (operands[0], GEN_INT (val)));
+#else
+ emit_insn (gen_movdi (operands[0],
+ gen_rtx_CONST_DOUBLE (VOIDmode, l[1], l[0])));
+#endif
+ }
+ else
+ {
+ emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
+ GEN_INT (l[0])));
+
+ /* Slick... but this trick loses if this subreg constant part
+ can be done in one insn. */
+ if (l[1] == l[0]
+ && !(SPARC_SETHI_P (l[0])
+ || SPARC_SIMM13_P (l[0])))
+ {
+ emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
+ gen_highpart (SImode, operands[0])));
+ }
+ else
+ {
+ emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
+ GEN_INT (l[1])));
+ }
+ }
+ DONE;
+}")
;; Ok, now the splits to handle all the multi insn and
;; mis-aligned memory address cases.
@@ -3249,11 +3450,6 @@
rtx dest1, dest2;
rtx src1, src2;
- if (GET_CODE (set_dest) == SUBREG)
- set_dest = alter_subreg (set_dest);
- if (GET_CODE (set_src) == SUBREG)
- set_src = alter_subreg (set_src);
-
dest1 = gen_highpart (SFmode, set_dest);
dest2 = gen_lowpart (SFmode, set_dest);
src1 = gen_highpart (SFmode, set_src);
@@ -3277,26 +3473,16 @@
(define_split
[(set (match_operand:DF 0 "register_operand" "")
(match_operand:DF 1 "memory_operand" ""))]
- "((! TARGET_V9
- || (! TARGET_ARCH64
- && ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
- || (GET_CODE (operands[0]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))))
- && (reload_completed
- && (((REGNO (operands[0])) % 2) != 0
- || ! mem_min_alignment (operands[1], 8))
- && offsettable_memref_p (operands[1])))"
+ "reload_completed
+ && ! TARGET_ARCH64
+ && (((REGNO (operands[0]) % 2) != 0)
+ || ! mem_min_alignment (operands[1], 8))
+ && offsettable_memref_p (operands[1])"
[(clobber (const_int 0))]
"
{
- rtx word0 = change_address (operands[1], SFmode, NULL_RTX);
- rtx word1 = change_address (operands[1], SFmode,
- plus_constant_for_output (XEXP (word0, 0), 4));
-
- if (GET_CODE (operands[0]) == SUBREG)
- operands[0] = alter_subreg (operands[0]);
+ rtx word0 = adjust_address (operands[1], SFmode, 0);
+ rtx word1 = adjust_address (operands[1], SFmode, 4);
if (reg_overlap_mentioned_p (gen_highpart (SFmode, operands[0]), word1))
{
@@ -3318,26 +3504,17 @@
(define_split
[(set (match_operand:DF 0 "memory_operand" "")
(match_operand:DF 1 "register_operand" ""))]
- "((! TARGET_V9
- || (! TARGET_ARCH64
- && ((GET_CODE (operands[1]) == REG
- && REGNO (operands[1]) < 32)
- || (GET_CODE (operands[1]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[1])) == REG
- && REGNO (SUBREG_REG (operands[1])) < 32))))
- && (reload_completed
- && (((REGNO (operands[1])) % 2) != 0
- || ! mem_min_alignment (operands[0], 8))
- && offsettable_memref_p (operands[0])))"
+ "reload_completed
+ && ! TARGET_ARCH64
+ && (((REGNO (operands[1]) % 2) != 0)
+ || ! mem_min_alignment (operands[0], 8))
+ && offsettable_memref_p (operands[0])"
[(clobber (const_int 0))]
"
{
- rtx word0 = change_address (operands[0], SFmode, NULL_RTX);
- rtx word1 = change_address (operands[0], SFmode,
- plus_constant_for_output (XEXP (word0, 0), 4));
+ rtx word0 = adjust_address (operands[0], SFmode, 0);
+ rtx word1 = adjust_address (operands[0], SFmode, 4);
- if (GET_CODE (operands[1]) == SUBREG)
- operands[1] = alter_subreg (operands[1]);
emit_insn (gen_movsf (word0,
gen_highpart (SFmode, operands[1])));
emit_insn (gen_movsf (word1,
@@ -3345,13 +3522,57 @@
DONE;
}")
+(define_split
+ [(set (match_operand:DF 0 "memory_operand" "")
+ (match_operand:DF 1 "fp_zero_operand" ""))]
+ "reload_completed
+ && (! TARGET_V9
+ || (! TARGET_ARCH64
+ && ! mem_min_alignment (operands[0], 8)))
+ && offsettable_memref_p (operands[0])"
+ [(clobber (const_int 0))]
+ "
+{
+ rtx dest1, dest2;
+
+ dest1 = adjust_address (operands[0], SFmode, 0);
+ dest2 = adjust_address (operands[0], SFmode, 4);
+
+ emit_insn (gen_movsf (dest1, CONST0_RTX (SFmode)));
+ emit_insn (gen_movsf (dest2, CONST0_RTX (SFmode)));
+ DONE;
+}")
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "fp_zero_operand" ""))]
+ "reload_completed
+ && ! TARGET_ARCH64
+ && ((GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) < 32)
+ || (GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == REG
+ && REGNO (SUBREG_REG (operands[0])) < 32))"
+ [(clobber (const_int 0))]
+ "
+{
+ rtx set_dest = operands[0];
+ rtx dest1, dest2;
+
+ dest1 = gen_highpart (SFmode, set_dest);
+ dest2 = gen_lowpart (SFmode, set_dest);
+ emit_insn (gen_movsf (dest1, CONST0_RTX (SFmode)));
+ emit_insn (gen_movsf (dest2, CONST0_RTX (SFmode)));
+ DONE;
+}")
+
(define_expand "movtf"
[(set (match_operand:TF 0 "general_operand" "")
(match_operand:TF 1 "general_operand" ""))]
""
"
{
- /* Force TFmode constants into memory. */
+ /* Force TFmode constants into memory. */
if (GET_CODE (operands[0]) == REG
&& CONSTANT_P (operands[1]))
{
@@ -3360,16 +3581,21 @@
crashes in output_constant_pool. */
if (operands [1] == const0_rtx)
operands[1] = CONST0_RTX (TFmode);
+
+ if (TARGET_VIS && fp_zero_operand (operands[1], TFmode))
+ goto movtf_is_ok;
+
operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
operands[1]));
}
/* Handle MEM cases first, note that only v9 guarentees
- full 16-byte alignment for quads. */
+ full 16-byte alignment for quads. */
if (GET_CODE (operands[0]) == MEM)
{
- if (register_operand (operands[1], TFmode))
- goto movtf_is_ok;
+ if (register_operand (operands[1], TFmode)
+ || fp_zero_operand (operands[1], TFmode))
+ goto movtf_is_ok;
if (! reload_in_progress)
{
@@ -3402,12 +3628,26 @@
;; Be careful, fmovq and {st,ld}{x,q} do not exist when !arch64 so
;; we must split them all. :-(
(define_insn "*movtf_insn_sp32"
- [(set (match_operand:TF 0 "general_operand" "=e,o,U,o,e,r,r,o")
- (match_operand:TF 1 "input_operand" "o,e,o,U,e,r,o,r"))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,U,r")
+ (match_operand:TF 1 "input_operand" "oe,GeUr,o,roG"))]
+ "TARGET_FPU
+ && ! TARGET_VIS
+ && ! TARGET_ARCH64
+ && (register_operand (operands[0], TFmode)
+ || register_operand (operands[1], TFmode)
+ || fp_zero_operand (operands[1], TFmode))"
+ "#"
+ [(set_attr "length" "4")])
+
+(define_insn "*movtf_insn_vis_sp32"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,U,r")
+ (match_operand:TF 1 "input_operand" "Goe,GeUr,o,roG"))]
"TARGET_FPU
+ && TARGET_VIS
&& ! TARGET_ARCH64
&& (register_operand (operands[0], TFmode)
- || register_operand (operands[1], TFmode))"
+ || register_operand (operands[1], TFmode)
+ || fp_zero_operand (operands[1], TFmode))"
"#"
[(set_attr "length" "4")])
@@ -3416,26 +3656,47 @@
;; when -mno-fpu.
(define_insn "*movtf_no_e_insn_sp32"
- [(set (match_operand:TF 0 "general_operand" "=U,o,r,r,o")
- (match_operand:TF 1 "input_operand" "o,U,r,o,r"))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=o,U,o,r,o")
+ (match_operand:TF 1 "input_operand" "G,o,U,roG,r"))]
"! TARGET_FPU
&& ! TARGET_ARCH64
&& (register_operand (operands[0], TFmode)
- || register_operand (operands[1], TFmode))"
+ || register_operand (operands[1], TFmode)
+ || fp_zero_operand (operands[1], TFmode))"
"#"
[(set_attr "length" "4")])
;; Now handle the float reg cases directly when arch64,
;; hard_quad, and proper reg number alignment are all true.
(define_insn "*movtf_insn_hq_sp64"
- [(set (match_operand:TF 0 "general_operand" "=e,e,m,r,r,o")
- (match_operand:TF 1 "input_operand" "e,m,e,r,o,r"))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=e,e,m,o,r")
+ (match_operand:TF 1 "input_operand" "e,m,e,Gr,roG"))]
"TARGET_FPU
+ && ! TARGET_VIS
+ && TARGET_ARCH64
+ && TARGET_HARD_QUAD
+ && (register_operand (operands[0], TFmode)
+ || register_operand (operands[1], TFmode)
+ || fp_zero_operand (operands[1], TFmode))"
+ "@
+ fmovq\\t%1, %0
+ ldq\\t%1, %0
+ stq\\t%1, %0
+ #
+ #"
+ [(set_attr "type" "fpmove,fpload,fpstore,*,*")
+ (set_attr "length" "*,*,*,2,2")])
+
+(define_insn "*movtf_insn_hq_vis_sp64"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=e,e,m,eo,r,o")
+ (match_operand:TF 1 "input_operand" "e,m,e,G,roG,r"))]
+ "TARGET_FPU
+ && TARGET_VIS
&& TARGET_ARCH64
- && TARGET_V9
&& TARGET_HARD_QUAD
&& (register_operand (operands[0], TFmode)
- || register_operand (operands[1], TFmode))"
+ || register_operand (operands[1], TFmode)
+ || fp_zero_operand (operands[1], TFmode))"
"@
fmovq\\t%1, %0
ldq\\t%1, %0
@@ -3444,28 +3705,44 @@
#
#"
[(set_attr "type" "fpmove,fpload,fpstore,*,*,*")
- (set_attr "length" "1,1,1,2,2,2")])
+ (set_attr "length" "*,*,*,2,2,2")])
;; Now we allow the integer register cases even when
;; only arch64 is true.
(define_insn "*movtf_insn_sp64"
- [(set (match_operand:TF 0 "general_operand" "=e,o,r,o,e,r")
- (match_operand:TF 1 "input_operand" "o,e,o,r,e,r"))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,r")
+ (match_operand:TF 1 "input_operand" "oe,Ger,orG"))]
+ "TARGET_FPU
+ && ! TARGET_VIS
+ && TARGET_ARCH64
+ && ! TARGET_HARD_QUAD
+ && (register_operand (operands[0], TFmode)
+ || register_operand (operands[1], TFmode)
+ || fp_zero_operand (operands[1], TFmode))"
+ "#"
+ [(set_attr "length" "2")])
+
+(define_insn "*movtf_insn_vis_sp64"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,r")
+ (match_operand:TF 1 "input_operand" "Goe,Ger,orG"))]
"TARGET_FPU
+ && TARGET_VIS
&& TARGET_ARCH64
&& ! TARGET_HARD_QUAD
&& (register_operand (operands[0], TFmode)
- || register_operand (operands[1], TFmode))"
+ || register_operand (operands[1], TFmode)
+ || fp_zero_operand (operands[1], TFmode))"
"#"
[(set_attr "length" "2")])
(define_insn "*movtf_no_e_insn_sp64"
- [(set (match_operand:TF 0 "general_operand" "=r,o,r")
- (match_operand:TF 1 "input_operand" "o,r,r"))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o")
+ (match_operand:TF 1 "input_operand" "orG,rG"))]
"! TARGET_FPU
&& TARGET_ARCH64
&& (register_operand (operands[0], TFmode)
- || register_operand (operands[1], TFmode))"
+ || register_operand (operands[1], TFmode)
+ || fp_zero_operand (operands[1], TFmode))"
"#"
[(set_attr "length" "2")])
@@ -3485,16 +3762,10 @@
rtx dest1, dest2;
rtx src1, src2;
- if (GET_CODE (set_dest) == SUBREG)
- set_dest = alter_subreg (set_dest);
- if (GET_CODE (set_src) == SUBREG)
- set_src = alter_subreg (set_src);
-
- /* Ugly, but gen_highpart will crap out here for 32-bit targets. */
- dest1 = gen_rtx_SUBREG (DFmode, set_dest, WORDS_BIG_ENDIAN == 0);
- dest2 = gen_rtx_SUBREG (DFmode, set_dest, WORDS_BIG_ENDIAN != 0);
- src1 = gen_rtx_SUBREG (DFmode, set_src, WORDS_BIG_ENDIAN == 0);
- src2 = gen_rtx_SUBREG (DFmode, set_src, WORDS_BIG_ENDIAN != 0);
+ dest1 = gen_df_reg (set_dest, 0);
+ dest2 = gen_df_reg (set_dest, 1);
+ src1 = gen_df_reg (set_src, 0);
+ src2 = gen_df_reg (set_src, 1);
/* Now emit using the real source and destination we found, swapping
the order if we detect overlap. */
@@ -3512,6 +3783,35 @@
}")
(define_split
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (match_operand:TF 1 "fp_zero_operand" ""))]
+ "reload_completed"
+ [(clobber (const_int 0))]
+ "
+{
+ rtx set_dest = operands[0];
+ rtx dest1, dest2;
+
+ switch (GET_CODE (set_dest))
+ {
+ case REG:
+ dest1 = gen_df_reg (set_dest, 0);
+ dest2 = gen_df_reg (set_dest, 1);
+ break;
+ case MEM:
+ dest1 = adjust_address (set_dest, DFmode, 0);
+ dest2 = adjust_address (set_dest, DFmode, 8);
+ break;
+ default:
+ abort ();
+ }
+
+ emit_insn (gen_movdf (dest1, CONST0_RTX (DFmode)));
+ emit_insn (gen_movdf (dest2, CONST0_RTX (DFmode)));
+ DONE;
+}")
+
+(define_split
[(set (match_operand:TF 0 "register_operand" "")
(match_operand:TF 1 "memory_operand" ""))]
"(reload_completed
@@ -3519,14 +3819,14 @@
[(clobber (const_int 0))]
"
{
- rtx word0 = change_address (operands[1], DFmode, NULL_RTX);
- rtx word1 = change_address (operands[1], DFmode,
- plus_constant_for_output (XEXP (word0, 0), 8));
- rtx dest1, dest2;
+ rtx word0 = adjust_address (operands[1], DFmode, 0);
+ rtx word1 = adjust_address (operands[1], DFmode, 8);
+ rtx set_dest, dest1, dest2;
- /* Ugly, but gen_highpart will crap out here for 32-bit targets. */
- dest1 = gen_rtx_SUBREG (DFmode, operands[0], WORDS_BIG_ENDIAN == 0);
- dest2 = gen_rtx_SUBREG (DFmode, operands[0], WORDS_BIG_ENDIAN != 0);
+ set_dest = operands[0];
+
+ dest1 = gen_df_reg (set_dest, 0);
+ dest2 = gen_df_reg (set_dest, 1);
/* Now output, ordering such that we don't clobber any registers
mentioned in the address. */
@@ -3552,16 +3852,12 @@
[(clobber (const_int 0))]
"
{
- rtx word0 = change_address (operands[0], DFmode, NULL_RTX);
- rtx word1 = change_address (operands[0], DFmode,
- plus_constant_for_output (XEXP (word0, 0), 8));
- rtx src1, src2;
+ rtx set_src = operands[1];
- /* Ugly, but gen_highpart will crap out here for 32-bit targets. */
- src1 = gen_rtx_SUBREG (DFmode, operands[1], WORDS_BIG_ENDIAN == 0);
- src2 = gen_rtx_SUBREG (DFmode, operands[1], WORDS_BIG_ENDIAN != 0);
- emit_insn (gen_movdf (word0, src1));
- emit_insn (gen_movdf (word1, src2));
+ emit_insn (gen_movdf (adjust_address (operands[0], DFmode, 0),
+ gen_df_reg (set_src, 0)));
+ emit_insn (gen_movdf (adjust_address (operands[0], DFmode, 8),
+ gen_df_reg (set_src, 1)));
DONE;
}")
@@ -3790,8 +4086,7 @@
"@
mov%C1\\t%x2, %3, %0
mov%c1\\t%x2, %4, %0"
- [(set_attr "type" "cmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "cmove")])
(define_insn "*movhi_cc_sp64"
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -3804,8 +4099,7 @@
"@
mov%C1\\t%x2, %3, %0
mov%c1\\t%x2, %4, %0"
- [(set_attr "type" "cmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "cmove")])
(define_insn "*movsi_cc_sp64"
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -3818,8 +4112,7 @@
"@
mov%C1\\t%x2, %3, %0
mov%c1\\t%x2, %4, %0"
- [(set_attr "type" "cmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "cmove")])
;; ??? The constraints of operands 3,4 need work.
(define_insn "*movdi_cc_sp64"
@@ -3833,8 +4126,7 @@
"@
mov%C1\\t%x2, %3, %0
mov%c1\\t%x2, %4, %0"
- [(set_attr "type" "cmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "cmove")])
(define_insn "*movdi_cc_sp64_trunc"
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -3847,8 +4139,7 @@
"@
mov%C1\\t%x2, %3, %0
mov%c1\\t%x2, %4, %0"
- [(set_attr "type" "cmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "cmove")])
(define_insn "*movsf_cc_sp64"
[(set (match_operand:SF 0 "register_operand" "=f,f")
@@ -3861,10 +4152,9 @@
"@
fmovs%C1\\t%x2, %3, %0
fmovs%c1\\t%x2, %4, %0"
- [(set_attr "type" "fpcmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "fpcmove")])
-(define_insn "*movdf_cc_sp64"
+(define_insn "movdf_cc_sp64"
[(set (match_operand:DF 0 "register_operand" "=e,e")
(if_then_else:DF (match_operator 1 "comparison_operator"
[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
@@ -3876,9 +4166,9 @@
fmovd%C1\\t%x2, %3, %0
fmovd%c1\\t%x2, %4, %0"
[(set_attr "type" "fpcmove")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
-(define_insn "*movtf_cc_sp64"
+(define_insn "*movtf_cc_hq_sp64"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(if_then_else:TF (match_operator 1 "comparison_operator"
[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
@@ -3889,8 +4179,59 @@
"@
fmovq%C1\\t%x2, %3, %0
fmovq%c1\\t%x2, %4, %0"
- [(set_attr "type" "fpcmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "fpcmove")])
+
+(define_insn "*movtf_cc_sp64"
+ [(set (match_operand:TF 0 "register_operand" "=e,e")
+ (if_then_else:TF (match_operator 1 "comparison_operator"
+ [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
+ (const_int 0)])
+ (match_operand:TF 3 "register_operand" "e,0")
+ (match_operand:TF 4 "register_operand" "0,e")))]
+ "TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
+ "#"
+ [(set_attr "length" "2")])
+
+(define_split
+ [(set (match_operand:TF 0 "register_operand" "")
+ (if_then_else:TF (match_operator 1 "comparison_operator"
+ [(match_operand 2 "icc_or_fcc_reg_operand" "")
+ (const_int 0)])
+ (match_operand:TF 3 "register_operand" "")
+ (match_operand:TF 4 "register_operand" "")))]
+ "reload_completed && TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
+ [(clobber (const_int 0))]
+ "
+{
+ rtx set_dest = operands[0];
+ rtx set_srca = operands[3];
+ rtx set_srcb = operands[4];
+ int third = rtx_equal_p (set_dest, set_srca);
+ rtx dest1, dest2;
+ rtx srca1, srca2, srcb1, srcb2;
+
+ dest1 = gen_df_reg (set_dest, 0);
+ dest2 = gen_df_reg (set_dest, 1);
+ srca1 = gen_df_reg (set_srca, 0);
+ srca2 = gen_df_reg (set_srca, 1);
+ srcb1 = gen_df_reg (set_srcb, 0);
+ srcb2 = gen_df_reg (set_srcb, 1);
+
+ /* Now emit using the real source and destination we found, swapping
+ the order if we detect overlap. */
+ if ((third && reg_overlap_mentioned_p (dest1, srcb2))
+ || (!third && reg_overlap_mentioned_p (dest1, srca2)))
+ {
+ emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
+ emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
+ }
+ else
+ {
+ emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
+ emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
+ }
+ DONE;
+}")
(define_insn "*movqi_cc_reg_sp64"
[(set (match_operand:QI 0 "register_operand" "=r,r")
@@ -3903,8 +4244,7 @@
"@
movr%D1\\t%2, %r3, %0
movr%d1\\t%2, %r4, %0"
- [(set_attr "type" "cmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "cmove")])
(define_insn "*movhi_cc_reg_sp64"
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -3917,8 +4257,7 @@
"@
movr%D1\\t%2, %r3, %0
movr%d1\\t%2, %r4, %0"
- [(set_attr "type" "cmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "cmove")])
(define_insn "*movsi_cc_reg_sp64"
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -3931,8 +4270,7 @@
"@
movr%D1\\t%2, %r3, %0
movr%d1\\t%2, %r4, %0"
- [(set_attr "type" "cmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "cmove")])
;; ??? The constraints of operands 3,4 need work.
(define_insn "*movdi_cc_reg_sp64"
@@ -3946,8 +4284,7 @@
"@
movr%D1\\t%2, %r3, %0
movr%d1\\t%2, %r4, %0"
- [(set_attr "type" "cmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "cmove")])
(define_insn "*movdi_cc_reg_sp64_trunc"
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -3960,8 +4297,7 @@
"@
movr%D1\\t%2, %r3, %0
movr%d1\\t%2, %r4, %0"
- [(set_attr "type" "cmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "cmove")])
(define_insn "*movsf_cc_reg_sp64"
[(set (match_operand:SF 0 "register_operand" "=f,f")
@@ -3974,10 +4310,9 @@
"@
fmovrs%D1\\t%2, %3, %0
fmovrs%d1\\t%2, %4, %0"
- [(set_attr "type" "fpcmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "fpcmove")])
-(define_insn "*movdf_cc_reg_sp64"
+(define_insn "movdf_cc_reg_sp64"
[(set (match_operand:DF 0 "register_operand" "=e,e")
(if_then_else:DF (match_operator 1 "v9_regcmp_op"
[(match_operand:DI 2 "register_operand" "r,r")
@@ -3989,21 +4324,73 @@
fmovrd%D1\\t%2, %3, %0
fmovrd%d1\\t%2, %4, %0"
[(set_attr "type" "fpcmove")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
-(define_insn "*movtf_cc_reg_sp64"
+(define_insn "*movtf_cc_reg_hq_sp64"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(if_then_else:TF (match_operator 1 "v9_regcmp_op"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
(match_operand:TF 3 "register_operand" "e,0")
(match_operand:TF 4 "register_operand" "0,e")))]
- "TARGET_ARCH64 && TARGET_FPU"
+ "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
"@
fmovrq%D1\\t%2, %3, %0
fmovrq%d1\\t%2, %4, %0"
- [(set_attr "type" "fpcmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "fpcmove")])
+
+(define_insn "*movtf_cc_reg_sp64"
+ [(set (match_operand:TF 0 "register_operand" "=e,e")
+ (if_then_else:TF (match_operator 1 "v9_regcmp_op"
+ [(match_operand:DI 2 "register_operand" "r,r")
+ (const_int 0)])
+ (match_operand:TF 3 "register_operand" "e,0")
+ (match_operand:TF 4 "register_operand" "0,e")))]
+ "TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD"
+ "#"
+ [(set_attr "length" "2")])
+
+(define_split
+ [(set (match_operand:TF 0 "register_operand" "")
+ (if_then_else:TF (match_operator 1 "v9_regcmp_op"
+ [(match_operand:DI 2 "register_operand" "")
+ (const_int 0)])
+ (match_operand:TF 3 "register_operand" "")
+ (match_operand:TF 4 "register_operand" "")))]
+ "reload_completed && TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD"
+ [(clobber (const_int 0))]
+ "
+{
+ rtx set_dest = operands[0];
+ rtx set_srca = operands[3];
+ rtx set_srcb = operands[4];
+ int third = rtx_equal_p (set_dest, set_srca);
+ rtx dest1, dest2;
+ rtx srca1, srca2, srcb1, srcb2;
+
+ dest1 = gen_df_reg (set_dest, 0);
+ dest2 = gen_df_reg (set_dest, 1);
+ srca1 = gen_df_reg (set_srca, 0);
+ srca2 = gen_df_reg (set_srca, 1);
+ srcb1 = gen_df_reg (set_srcb, 0);
+ srcb2 = gen_df_reg (set_srcb, 1);
+
+ /* Now emit using the real source and destination we found, swapping
+ the order if we detect overlap. */
+ if ((third && reg_overlap_mentioned_p (dest1, srcb2))
+ || (!third && reg_overlap_mentioned_p (dest1, srca2)))
+ {
+ emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
+ emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
+ }
+ else
+ {
+ emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
+ emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
+ }
+ DONE;
+}")
+
;;- zero extension instructions
@@ -4019,16 +4406,17 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_16 = GEN_INT (16);
- int op1_subword = 0;
+ int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subword = SUBREG_WORD (operand1);
+ op1_subbyte = SUBREG_BYTE (operand1);
+ op1_subbyte /= GET_MODE_SIZE (SImode);
+ op1_subbyte *= GET_MODE_SIZE (SImode);
operand1 = XEXP (operand1, 0);
}
- emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1,
- op1_subword),
+ emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
shift_16));
emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
DONE;
@@ -4039,8 +4427,7 @@
(zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
""
"lduh\\t%1, %0"
- [(set_attr "type" "load")
- (set_attr "length" "1")])
+ [(set_attr "type" "load")])
(define_expand "zero_extendqihi2"
[(set (match_operand:HI 0 "register_operand" "")
@@ -4055,8 +4442,7 @@
"@
and\\t%1, 0xff, %0
ldub\\t%1, %0"
- [(set_attr "type" "unary,load")
- (set_attr "length" "1")])
+ [(set_attr "type" "*,load")])
(define_expand "zero_extendqisi2"
[(set (match_operand:SI 0 "register_operand" "")
@@ -4071,8 +4457,7 @@
"@
and\\t%1, 0xff, %0
ldub\\t%1, %0"
- [(set_attr "type" "unary,load")
- (set_attr "length" "1")])
+ [(set_attr "type" "*,load")])
(define_expand "zero_extendqidi2"
[(set (match_operand:DI 0 "register_operand" "")
@@ -4087,8 +4472,7 @@
"@
and\\t%1, 0xff, %0
ldub\\t%1, %0"
- [(set_attr "type" "unary,load")
- (set_attr "length" "1")])
+ [(set_attr "type" "*,load")])
(define_expand "zero_extendhidi2"
[(set (match_operand:DI 0 "register_operand" "")
@@ -4098,16 +4482,17 @@
{
rtx temp = gen_reg_rtx (DImode);
rtx shift_48 = GEN_INT (48);
- int op1_subword = 0;
+ int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subword = SUBREG_WORD (operand1);
+ op1_subbyte = SUBREG_BYTE (operand1);
+ op1_subbyte /= GET_MODE_SIZE (DImode);
+ op1_subbyte *= GET_MODE_SIZE (DImode);
operand1 = XEXP (operand1, 0);
}
- emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1,
- op1_subword),
+ emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
shift_48));
emit_insn (gen_lshrdi3 (operand0, temp, shift_48));
DONE;
@@ -4118,8 +4503,7 @@
(zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
"TARGET_ARCH64"
"lduh\\t%1, %0"
- [(set_attr "type" "load")
- (set_attr "length" "1")])
+ [(set_attr "type" "load")])
;; ??? Write truncdisi pattern using sra?
@@ -4137,16 +4521,14 @@
"@
srl\\t%1, 0, %0
lduw\\t%1, %0"
- [(set_attr "type" "shift,load")
- (set_attr "length" "1")])
+ [(set_attr "type" "shift,load")])
(define_insn "*zero_extendsidi2_insn_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
"! TARGET_ARCH64"
"#"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
+ [(set_attr "length" "2")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -4158,9 +4540,6 @@
{
rtx dest1, dest2;
- if (GET_CODE (operands[0]) == SUBREG)
- operands[0] = alter_subreg (operands[0]);
-
dest1 = gen_highpart (SImode, operands[0]);
dest2 = gen_lowpart (SImode, operands[0]);
@@ -4187,10 +4566,17 @@
[(set (reg:CC 100)
(compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
(const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
+ "andcc\\t%0, 0xff, %%g0"
+ [(set_attr "type" "compare")])
+
+(define_insn "*cmp_zero_qi"
+ [(set (reg:CC 100)
+ (compare:CC (match_operand:QI 0 "register_operand" "r")
+ (const_int 0)))]
+ ""
"andcc\\t%0, 0xff, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_zero_extendqisi2_set"
[(set (reg:CC 100)
@@ -4200,8 +4586,18 @@
(zero_extend:SI (match_dup 1)))]
""
"andcc\\t%1, 0xff, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
+
+(define_insn "*cmp_zero_extendqisi2_andcc_set"
+ [(set (reg:CC 100)
+ (compare:CC (and:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 255))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (subreg:QI (match_dup 1) 0)))]
+ ""
+ "andcc\\t%1, 0xff, %0"
+ [(set_attr "type" "compare")])
(define_insn "*cmp_zero_extendqidi2"
[(set (reg:CCX 100)
@@ -4209,8 +4605,15 @@
(const_int 0)))]
"TARGET_ARCH64"
"andcc\\t%0, 0xff, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
+
+(define_insn "*cmp_zero_qi_sp64"
+ [(set (reg:CCX 100)
+ (compare:CCX (match_operand:QI 0 "register_operand" "r")
+ (const_int 0)))]
+ "TARGET_ARCH64"
+ "andcc\\t%0, 0xff, %%g0"
+ [(set_attr "type" "compare")])
(define_insn "*cmp_zero_extendqidi2_set"
[(set (reg:CCX 100)
@@ -4220,50 +4623,56 @@
(zero_extend:DI (match_dup 1)))]
"TARGET_ARCH64"
"andcc\\t%1, 0xff, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
+
+(define_insn "*cmp_zero_extendqidi2_andcc_set"
+ [(set (reg:CCX 100)
+ (compare:CCX (and:DI (match_operand:DI 1 "register_operand" "r")
+ (const_int 255))
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (subreg:QI (match_dup 1) 0)))]
+ "TARGET_ARCH64"
+ "andcc\\t%1, 0xff, %0"
+ [(set_attr "type" "compare")])
;; Similarly, handle {SI,DI}->QI mode truncation followed by a compare.
(define_insn "*cmp_siqi_trunc"
[(set (reg:CC 100)
- (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0)
+ (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 3)
(const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"andcc\\t%0, 0xff, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_siqi_trunc_set"
[(set (reg:CC 100)
- (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 0)
+ (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 3)
(const_int 0)))
(set (match_operand:QI 0 "register_operand" "=r")
- (subreg:QI (match_dup 1) 0))]
+ (subreg:QI (match_dup 1) 3))]
""
"andcc\\t%1, 0xff, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_diqi_trunc"
[(set (reg:CC 100)
- (compare:CC (subreg:QI (match_operand:DI 0 "register_operand" "r") 0)
+ (compare:CC (subreg:QI (match_operand:DI 0 "register_operand" "r") 7)
(const_int 0)))]
"TARGET_ARCH64"
"andcc\\t%0, 0xff, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_diqi_trunc_set"
[(set (reg:CC 100)
- (compare:CC (subreg:QI (match_operand:DI 1 "register_operand" "r") 0)
+ (compare:CC (subreg:QI (match_operand:DI 1 "register_operand" "r") 7)
(const_int 0)))
(set (match_operand:QI 0 "register_operand" "=r")
- (subreg:QI (match_dup 1) 0))]
+ (subreg:QI (match_dup 1) 7))]
"TARGET_ARCH64"
"andcc\\t%1, 0xff, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
;;- sign extension instructions
@@ -4279,16 +4688,17 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_16 = GEN_INT (16);
- int op1_subword = 0;
+ int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subword = SUBREG_WORD (operand1);
+ op1_subbyte = SUBREG_BYTE (operand1);
+ op1_subbyte /= GET_MODE_SIZE (SImode);
+ op1_subbyte *= GET_MODE_SIZE (SImode);
operand1 = XEXP (operand1, 0);
}
- emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1,
- op1_subword),
+ emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
shift_16));
emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
DONE;
@@ -4299,8 +4709,7 @@
(sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
""
"ldsh\\t%1, %0"
- [(set_attr "type" "sload")
- (set_attr "length" "1")])
+ [(set_attr "type" "sload")])
(define_expand "extendqihi2"
[(set (match_operand:HI 0 "register_operand" "")
@@ -4310,24 +4719,27 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_24 = GEN_INT (24);
- int op1_subword = 0;
- int op0_subword = 0;
+ int op1_subbyte = 0;
+ int op0_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subword = SUBREG_WORD (operand1);
+ op1_subbyte = SUBREG_BYTE (operand1);
+ op1_subbyte /= GET_MODE_SIZE (SImode);
+ op1_subbyte *= GET_MODE_SIZE (SImode);
operand1 = XEXP (operand1, 0);
}
if (GET_CODE (operand0) == SUBREG)
{
- op0_subword = SUBREG_WORD (operand0);
+ op0_subbyte = SUBREG_BYTE (operand0);
+ op0_subbyte /= GET_MODE_SIZE (SImode);
+ op0_subbyte *= GET_MODE_SIZE (SImode);
operand0 = XEXP (operand0, 0);
}
- emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1,
- op1_subword),
+ emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
shift_24));
if (GET_MODE (operand0) != SImode)
- operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subword);
+ operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subbyte);
emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
DONE;
}")
@@ -4337,8 +4749,7 @@
(sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
""
"ldsb\\t%1, %0"
- [(set_attr "type" "sload")
- (set_attr "length" "1")])
+ [(set_attr "type" "sload")])
(define_expand "extendqisi2"
[(set (match_operand:SI 0 "register_operand" "")
@@ -4348,16 +4759,17 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_24 = GEN_INT (24);
- int op1_subword = 0;
+ int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subword = SUBREG_WORD (operand1);
+ op1_subbyte = SUBREG_BYTE (operand1);
+ op1_subbyte /= GET_MODE_SIZE (SImode);
+ op1_subbyte *= GET_MODE_SIZE (SImode);
operand1 = XEXP (operand1, 0);
}
- emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1,
- op1_subword),
+ emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
shift_24));
emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
DONE;
@@ -4368,8 +4780,7 @@
(sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
""
"ldsb\\t%1, %0"
- [(set_attr "type" "sload")
- (set_attr "length" "1")])
+ [(set_attr "type" "sload")])
(define_expand "extendqidi2"
[(set (match_operand:DI 0 "register_operand" "")
@@ -4379,16 +4790,17 @@
{
rtx temp = gen_reg_rtx (DImode);
rtx shift_56 = GEN_INT (56);
- int op1_subword = 0;
+ int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subword = SUBREG_WORD (operand1);
+ op1_subbyte = SUBREG_BYTE (operand1);
+ op1_subbyte /= GET_MODE_SIZE (DImode);
+ op1_subbyte *= GET_MODE_SIZE (DImode);
operand1 = XEXP (operand1, 0);
}
- emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1,
- op1_subword),
+ emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
shift_56));
emit_insn (gen_ashrdi3 (operand0, temp, shift_56));
DONE;
@@ -4399,8 +4811,7 @@
(sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
"TARGET_ARCH64"
"ldsb\\t%1, %0"
- [(set_attr "type" "sload")
- (set_attr "length" "1")])
+ [(set_attr "type" "sload")])
(define_expand "extendhidi2"
[(set (match_operand:DI 0 "register_operand" "")
@@ -4410,16 +4821,17 @@
{
rtx temp = gen_reg_rtx (DImode);
rtx shift_48 = GEN_INT (48);
- int op1_subword = 0;
+ int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subword = SUBREG_WORD (operand1);
+ op1_subbyte = SUBREG_BYTE (operand1);
+ op1_subbyte /= GET_MODE_SIZE (DImode);
+ op1_subbyte *= GET_MODE_SIZE (DImode);
operand1 = XEXP (operand1, 0);
}
- emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1,
- op1_subword),
+ emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
shift_48));
emit_insn (gen_ashrdi3 (operand0, temp, shift_48));
DONE;
@@ -4430,8 +4842,7 @@
(sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
"TARGET_ARCH64"
"ldsh\\t%1, %0"
- [(set_attr "type" "sload")
- (set_attr "length" "1")])
+ [(set_attr "type" "sload")])
(define_expand "extendsidi2"
[(set (match_operand:DI 0 "register_operand" "")
@@ -4446,8 +4857,7 @@
"@
sra\\t%1, 0, %0
ldsw\\t%1, %0"
- [(set_attr "type" "shift,sload")
- (set_attr "length" "1")])
+ [(set_attr "type" "shift,sload")])
;; Special pattern for optimizing bit-field compares. This is needed
;; because combine uses this as a canonical form.
@@ -4459,11 +4869,10 @@
(match_operand:SI 1 "small_int_or_double" "n")
(match_operand:SI 2 "small_int_or_double" "n"))
(const_int 0)))]
- "! TARGET_LIVE_G0
- && ((GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) > 19)
- || (GET_CODE (operands[2]) == CONST_DOUBLE
- && CONST_DOUBLE_LOW (operands[2]) > 19))"
+ "(GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) > 19)
+ || (GET_CODE (operands[2]) == CONST_DOUBLE
+ && CONST_DOUBLE_LOW (operands[2]) > 19)"
"*
{
int len = (GET_CODE (operands[1]) == CONST_INT
@@ -4478,8 +4887,7 @@
operands[1] = GEN_INT (mask);
return \"andcc\\t%0, %1, %%g0\";
}"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_zero_extract_sp64"
[(set (reg:CCX 100)
@@ -4507,8 +4915,7 @@
operands[1] = GEN_INT (mask);
return \"andcc\\t%0, %1, %%g0\";
}"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
;; Conversions between float, double and long double.
@@ -4519,25 +4926,77 @@
"TARGET_FPU"
"fstod\\t%1, %0"
[(set_attr "type" "fp")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
+
+(define_expand "extendsftf2"
+ [(set (match_operand:TF 0 "register_operand" "=e")
+ (float_extend:TF
+ (match_operand:SF 1 "register_operand" "f")))]
+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
+ "
+{
+ if (! TARGET_HARD_QUAD)
+ {
+ rtx slot0;
-(define_insn "extendsftf2"
+ if (GET_CODE (operands[0]) != MEM)
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ else
+ slot0 = operands[0];
+
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_stoq\"), 0,
+ VOIDmode, 2,
+ XEXP (slot0, 0), Pmode,
+ operands[1], SFmode);
+
+ if (GET_CODE (operands[0]) != MEM)
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
+ DONE;
+ }
+}")
+
+(define_insn "*extendsftf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
(float_extend:TF
(match_operand:SF 1 "register_operand" "f")))]
"TARGET_FPU && TARGET_HARD_QUAD"
"fstoq\\t%1, %0"
- [(set_attr "type" "fp")
- (set_attr "length" "1")])
+ [(set_attr "type" "fp")])
-(define_insn "extenddftf2"
+(define_expand "extenddftf2"
+ [(set (match_operand:TF 0 "register_operand" "=e")
+ (float_extend:TF
+ (match_operand:DF 1 "register_operand" "e")))]
+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
+ "
+{
+ if (! TARGET_HARD_QUAD)
+ {
+ rtx slot0;
+
+ if (GET_CODE (operands[0]) != MEM)
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ else
+ slot0 = operands[0];
+
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_dtoq\"), 0,
+ VOIDmode, 2,
+ XEXP (slot0, 0), Pmode,
+ operands[1], DFmode);
+
+ if (GET_CODE (operands[0]) != MEM)
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
+ DONE;
+ }
+}")
+
+(define_insn "*extenddftf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
(float_extend:TF
(match_operand:DF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
"fdtoq\\t%1, %0"
- [(set_attr "type" "fp")
- (set_attr "length" "1")])
+ [(set_attr "type" "fp")])
(define_insn "truncdfsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
@@ -4546,25 +5005,75 @@
"TARGET_FPU"
"fdtos\\t%1, %0"
[(set_attr "type" "fp")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
-(define_insn "trunctfsf2"
+(define_expand "trunctfsf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float_truncate:SF
+ (match_operand:TF 1 "register_operand" "e")))]
+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
+ "
+{
+ if (! TARGET_HARD_QUAD)
+ {
+ rtx slot0;
+
+ if (GET_CODE (operands[1]) != MEM)
+ {
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
+ }
+ else
+ slot0 = operands[1];
+
+ emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtos\"),
+ operands[0], 0, SFmode, 1,
+ XEXP (slot0, 0), Pmode);
+ DONE;
+ }
+}")
+
+(define_insn "*trunctfsf2_hq"
[(set (match_operand:SF 0 "register_operand" "=f")
(float_truncate:SF
(match_operand:TF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
"fqtos\\t%1, %0"
- [(set_attr "type" "fp")
- (set_attr "length" "1")])
+ [(set_attr "type" "fp")])
+
+(define_expand "trunctfdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float_truncate:DF
+ (match_operand:TF 1 "register_operand" "e")))]
+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
+ "
+{
+ if (! TARGET_HARD_QUAD)
+ {
+ rtx slot0;
-(define_insn "trunctfdf2"
+ if (GET_CODE (operands[1]) != MEM)
+ {
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
+ }
+ else
+ slot0 = operands[1];
+
+ emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtod\"),
+ operands[0], 0, DFmode, 1,
+ XEXP (slot0, 0), Pmode);
+ DONE;
+ }
+}")
+
+(define_insn "*trunctfdf2_hq"
[(set (match_operand:DF 0 "register_operand" "=e")
(float_truncate:DF
(match_operand:TF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
"fqtod\\t%1, %0"
- [(set_attr "type" "fp")
- (set_attr "length" "1")])
+ [(set_attr "type" "fp")])
;; Conversion between fixed point and floating point.
@@ -4574,7 +5083,7 @@
"TARGET_FPU"
"fitos\\t%1, %0"
[(set_attr "type" "fp")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
(define_insn "floatsidf2"
[(set (match_operand:DF 0 "register_operand" "=e")
@@ -4582,15 +5091,63 @@
"TARGET_FPU"
"fitod\\t%1, %0"
[(set_attr "type" "fp")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
-(define_insn "floatsitf2"
+(define_expand "floatsitf2"
+ [(set (match_operand:TF 0 "register_operand" "=e")
+ (float:TF (match_operand:SI 1 "register_operand" "f")))]
+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
+ "
+{
+ if (! TARGET_HARD_QUAD)
+ {
+ rtx slot0;
+
+ if (GET_CODE (operands[1]) != MEM)
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ else
+ slot0 = operands[1];
+
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_itoq\"), 0,
+ VOIDmode, 2,
+ XEXP (slot0, 0), Pmode,
+ operands[1], SImode);
+
+ if (GET_CODE (operands[0]) != MEM)
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
+ DONE;
+ }
+}")
+
+(define_insn "*floatsitf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
(float:TF (match_operand:SI 1 "register_operand" "f")))]
"TARGET_FPU && TARGET_HARD_QUAD"
"fitoq\\t%1, %0"
- [(set_attr "type" "fp")
- (set_attr "length" "1")])
+ [(set_attr "type" "fp")])
+
+(define_expand "floatunssitf2"
+ [(set (match_operand:TF 0 "register_operand" "=e")
+ (unsigned_float:TF (match_operand:SI 1 "register_operand" "e")))]
+ "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
+ "
+{
+ rtx slot0;
+
+ if (GET_CODE (operands[1]) != MEM)
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ else
+ slot0 = operands[1];
+
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_uitoq\"), 0,
+ VOIDmode, 2,
+ XEXP (slot0, 0), Pmode,
+ operands[1], SImode);
+
+ if (GET_CODE (operands[0]) != MEM)
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
+ DONE;
+}")
;; Now the same for 64 bit sources.
@@ -4600,7 +5157,7 @@
"TARGET_V9 && TARGET_FPU"
"fxtos\\t%1, %0"
[(set_attr "type" "fp")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
(define_insn "floatdidf2"
[(set (match_operand:DF 0 "register_operand" "=e")
@@ -4608,15 +5165,63 @@
"TARGET_V9 && TARGET_FPU"
"fxtod\\t%1, %0"
[(set_attr "type" "fp")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
-(define_insn "floatditf2"
+(define_expand "floatditf2"
+ [(set (match_operand:TF 0 "register_operand" "=e")
+ (float:TF (match_operand:DI 1 "register_operand" "e")))]
+ "TARGET_FPU && TARGET_V9 && (TARGET_HARD_QUAD || TARGET_ARCH64)"
+ "
+{
+ if (! TARGET_HARD_QUAD)
+ {
+ rtx slot0;
+
+ if (GET_CODE (operands[1]) != MEM)
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ else
+ slot0 = operands[1];
+
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_xtoq\"), 0,
+ VOIDmode, 2,
+ XEXP (slot0, 0), Pmode,
+ operands[1], DImode);
+
+ if (GET_CODE (operands[0]) != MEM)
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
+ DONE;
+ }
+}")
+
+(define_insn "*floatditf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
(float:TF (match_operand:DI 1 "register_operand" "e")))]
"TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
"fxtoq\\t%1, %0"
- [(set_attr "type" "fp")
- (set_attr "length" "1")])
+ [(set_attr "type" "fp")])
+
+(define_expand "floatunsditf2"
+ [(set (match_operand:TF 0 "register_operand" "=e")
+ (unsigned_float:TF (match_operand:DI 1 "register_operand" "e")))]
+ "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
+ "
+{
+ rtx slot0;
+
+ if (GET_CODE (operands[1]) != MEM)
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ else
+ slot0 = operands[1];
+
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_uxtoq\"), 0,
+ VOIDmode, 2,
+ XEXP (slot0, 0), Pmode,
+ operands[1], DImode);
+
+ if (GET_CODE (operands[0]) != MEM)
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
+ DONE;
+}")
;; Convert a float to an actual integer.
;; Truncation is performed as part of the conversion.
@@ -4627,7 +5232,7 @@
"TARGET_FPU"
"fstoi\\t%1, %0"
[(set_attr "type" "fp")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
(define_insn "fix_truncdfsi2"
[(set (match_operand:SI 0 "register_operand" "=f")
@@ -4635,15 +5240,61 @@
"TARGET_FPU"
"fdtoi\\t%1, %0"
[(set_attr "type" "fp")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
+
+(define_expand "fix_trunctfsi2"
+ [(set (match_operand:SI 0 "register_operand" "=f")
+ (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
+ "
+{
+ if (! TARGET_HARD_QUAD)
+ {
+ rtx slot0;
+
+ if (GET_CODE (operands[1]) != MEM)
+ {
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
+ }
+ else
+ slot0 = operands[1];
+
+ emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtoi\"),
+ operands[0], 0, SImode, 1,
+ XEXP (slot0, 0), Pmode);
+ DONE;
+ }
+}")
-(define_insn "fix_trunctfsi2"
+(define_insn "*fix_trunctfsi2_hq"
[(set (match_operand:SI 0 "register_operand" "=f")
(fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
"TARGET_FPU && TARGET_HARD_QUAD"
"fqtoi\\t%1, %0"
- [(set_attr "type" "fp")
- (set_attr "length" "1")])
+ [(set_attr "type" "fp")])
+
+(define_expand "fixuns_trunctfsi2"
+ [(set (match_operand:SI 0 "register_operand" "=f")
+ (unsigned_fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+ "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
+ "
+{
+ rtx slot0;
+
+ if (GET_CODE (operands[1]) != MEM)
+ {
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
+ }
+ else
+ slot0 = operands[1];
+
+ emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtoui\"),
+ operands[0], 0, SImode, 1,
+ XEXP (slot0, 0), Pmode);
+ DONE;
+}")
;; Now the same, for V9 targets
@@ -4653,7 +5304,7 @@
"TARGET_V9 && TARGET_FPU"
"fstox\\t%1, %0"
[(set_attr "type" "fp")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
(define_insn "fix_truncdfdi2"
[(set (match_operand:DI 0 "register_operand" "=e")
@@ -4661,15 +5312,62 @@
"TARGET_V9 && TARGET_FPU"
"fdtox\\t%1, %0"
[(set_attr "type" "fp")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
+
+(define_expand "fix_trunctfdi2"
+ [(set (match_operand:DI 0 "register_operand" "=e")
+ (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+ "TARGET_V9 && TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
+ "
+{
+ if (! TARGET_HARD_QUAD)
+ {
+ rtx slot0;
+
+ if (GET_CODE (operands[1]) != MEM)
+ {
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
+ }
+ else
+ slot0 = operands[1];
+
+ emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtox\"),
+ operands[0], 0, DImode, 1,
+ XEXP (slot0, 0), Pmode);
+ DONE;
+ }
+}")
-(define_insn "fix_trunctfdi2"
+(define_insn "*fix_trunctfdi2_hq"
[(set (match_operand:DI 0 "register_operand" "=e")
(fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
"TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
"fqtox\\t%1, %0"
- [(set_attr "type" "fp")
- (set_attr "length" "1")])
+ [(set_attr "type" "fp")])
+
+(define_expand "fixuns_trunctfdi2"
+ [(set (match_operand:DI 0 "register_operand" "=f")
+ (unsigned_fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
+ "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
+ "
+{
+ rtx slot0;
+
+ if (GET_CODE (operands[1]) != MEM)
+ {
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ emit_insn (gen_rtx_SET (VOIDmode, slot0, operands[1]));
+ }
+ else
+ slot0 = operands[1];
+
+ emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_qtoux\"),
+ operands[0], 0, DImode, 1,
+ XEXP (slot0, 0), Pmode);
+ DONE;
+}")
+
;;- arithmetic instructions
@@ -4680,6 +5378,8 @@
""
"
{
+ HOST_WIDE_INT i;
+
if (! TARGET_ARCH64)
{
emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
@@ -4692,9 +5392,17 @@
}
if (arith_double_4096_operand(operands[2], DImode))
{
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_MINUS (DImode, operands[1],
- GEN_INT(-4096))));
+ switch (GET_CODE (operands[1]))
+ {
+ case CONST_INT: i = INTVAL (operands[1]); break;
+ case CONST_DOUBLE: i = CONST_DOUBLE_LOW (operands[1]); break;
+ default:
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_MINUS (DImode, operands[1],
+ GEN_INT(-4096))));
+ DONE;
+ }
+ emit_insn (gen_movdi (operands[0], GEN_INT (i + 4096)));
DONE;
}
}")
@@ -4709,9 +5417,9 @@
[(set_attr "length" "2")])
(define_split
- [(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
- (match_operand:DI 2 "arith_double_operand" "rHI")))
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (match_operand:DI 1 "arith_double_operand" "")
+ (match_operand:DI 2 "arith_double_operand" "")))
(clobber (reg:CC 100))]
"! TARGET_ARCH64 && reload_completed"
[(parallel [(set (reg:CC_NOOV 100)
@@ -4730,7 +5438,8 @@
operands[4] = gen_lowpart (SImode, operands[1]);
operands[5] = gen_lowpart (SImode, operands[2]);
operands[6] = gen_highpart (SImode, operands[0]);
- operands[7] = gen_highpart (SImode, operands[1]);
+ operands[7] = gen_highpart_mode (SImode, DImode, operands[1]);
+#if HOST_BITS_PER_WIDE_INT == 32
if (GET_CODE (operands[2]) == CONST_INT)
{
if (INTVAL (operands[2]) < 0)
@@ -4739,13 +5448,14 @@
operands[8] = const0_rtx;
}
else
- operands[8] = gen_highpart (SImode, operands[2]);
+#endif
+ operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
}")
(define_split
- [(set (match_operand:DI 0 "register_operand" "=r")
- (minus:DI (match_operand:DI 1 "arith_double_operand" "r")
- (match_operand:DI 2 "arith_double_operand" "rHI")))
+ [(set (match_operand:DI 0 "register_operand" "")
+ (minus:DI (match_operand:DI 1 "arith_double_operand" "")
+ (match_operand:DI 2 "arith_double_operand" "")))
(clobber (reg:CC 100))]
"! TARGET_ARCH64 && reload_completed"
[(parallel [(set (reg:CC_NOOV 100)
@@ -4765,6 +5475,7 @@
operands[5] = gen_lowpart (SImode, operands[2]);
operands[6] = gen_highpart (SImode, operands[0]);
operands[7] = gen_highpart (SImode, operands[1]);
+#if HOST_BITS_PER_WIDE_INT == 32
if (GET_CODE (operands[2]) == CONST_INT)
{
if (INTVAL (operands[2]) < 0)
@@ -4773,7 +5484,8 @@
operands[8] = const0_rtx;
}
else
- operands[8] = gen_highpart (SImode, operands[2]);
+#endif
+ operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
}")
;; LTU here means "carry set"
@@ -4784,8 +5496,7 @@
(ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
""
"addx\\t%1, %2, %0"
- [(set_attr "type" "unary")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
(define_insn "*addx_extend_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -4794,8 +5505,7 @@
(ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
"! TARGET_ARCH64"
"#"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
+ [(set_attr "length" "2")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -4807,7 +5517,7 @@
(ltu:SI (reg:CC_NOOV 100) (const_int 0))))
(set (match_dup 4) (const_int 0))]
"operands[3] = gen_lowpart (SImode, operands[0]);
- operands[4] = gen_highpart (SImode, operands[1]);")
+ operands[4] = gen_highpart_mode (SImode, DImode, operands[1]);")
(define_insn "*addx_extend_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -4816,8 +5526,7 @@
(ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
"TARGET_ARCH64"
"addx\\t%r1, %2, %0"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
(define_insn "subx"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -4826,8 +5535,7 @@
(ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
""
"subx\\t%r1, %2, %0"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
(define_insn "*subx_extend_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -4836,8 +5544,7 @@
(ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
"TARGET_ARCH64"
"subx\\t%r1, %2, %0"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
(define_insn "*subx_extend"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -4846,13 +5553,12 @@
(ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
"! TARGET_ARCH64"
"#"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
+ [(set_attr "length" "2")])
(define_split
- [(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
- (match_operand:SI 2 "arith_operand" "rI"))
+ [(set (match_operand:DI 0 "register_operand" "")
+ (zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "")
+ (match_operand:SI 2 "arith_operand" ""))
(ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
"! TARGET_ARCH64 && reload_completed"
[(set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 2))
@@ -4868,8 +5574,7 @@
(clobber (reg:CC 100))]
"! TARGET_ARCH64"
"#"
- [(set_attr "type" "multi")
- (set_attr "length" "2")])
+ [(set_attr "length" "2")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -4894,9 +5599,7 @@
(plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
(match_operand:DI 2 "arith_double_operand" "rHI")))]
"TARGET_ARCH64"
- "add\\t%1, %2, %0"
- [(set_attr "type" "binary")
- (set_attr "length" "1")])
+ "add\\t%1, %2, %0")
(define_expand "addsi3"
[(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -4905,11 +5608,15 @@
""
"
{
- if (arith_4096_operand(operands[2], DImode))
+ if (arith_4096_operand(operands[2], SImode))
{
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_MINUS (SImode, operands[1],
- GEN_INT(-4096))));
+ if (GET_CODE (operands[1]) == CONST_INT)
+ emit_insn (gen_movsi (operands[0],
+ GEN_INT (INTVAL (operands[1]) + 4096)));
+ else
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_MINUS (SImode, operands[1],
+ GEN_INT(-4096))));
DONE;
}
}")
@@ -4922,18 +5629,16 @@
"@
add\\t%1, %2, %0
fpadd32s\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "1")])
+ [(set_attr "type" "*,fp")])
(define_insn "*cmp_cc_plus"
[(set (reg:CC_NOOV 100)
(compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r")
(match_operand:SI 1 "arith_operand" "rI"))
(const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"addcc\\t%0, %1, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_ccx_plus"
[(set (reg:CCX_NOOV 100)
@@ -4942,8 +5647,7 @@
(const_int 0)))]
"TARGET_ARCH64"
"addcc\\t%0, %1, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_cc_plus_set"
[(set (reg:CC_NOOV 100)
@@ -4954,8 +5658,7 @@
(plus:SI (match_dup 1) (match_dup 2)))]
""
"addcc\\t%1, %2, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_ccx_plus_set"
[(set (reg:CCX_NOOV 100)
@@ -4966,8 +5669,7 @@
(plus:DI (match_dup 1) (match_dup 2)))]
"TARGET_ARCH64"
"addcc\\t%1, %2, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_expand "subdi3"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -5018,7 +5720,7 @@
{
rtx highp, lowp;
- highp = gen_highpart (SImode, operands[2]);
+ highp = gen_highpart_mode (SImode, DImode, operands[2]);
lowp = gen_lowpart (SImode, operands[2]);
if ((lowp == const0_rtx)
&& (operands[0] == operands[1]))
@@ -5026,7 +5728,8 @@
emit_insn (gen_rtx_SET (VOIDmode,
gen_highpart (SImode, operands[0]),
gen_rtx_MINUS (SImode,
- gen_highpart (SImode, operands[1]),
+ gen_highpart_mode (SImode, DImode,
+ operands[1]),
highp)));
}
else
@@ -5035,7 +5738,7 @@
gen_lowpart (SImode, operands[1]),
lowp));
emit_insn (gen_subx (gen_highpart (SImode, operands[0]),
- gen_highpart (SImode, operands[1]),
+ gen_highpart_mode (SImode, DImode, operands[1]),
highp));
}
DONE;
@@ -5067,8 +5770,7 @@
(clobber (reg:CC 100))]
"! TARGET_ARCH64"
"#"
- [(set_attr "type" "multi")
- (set_attr "length" "2")])
+ [(set_attr "length" "2")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -5093,9 +5795,7 @@
(minus:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "arith_double_operand" "rHI")))]
"TARGET_ARCH64"
- "sub\\t%1, %2, %0"
- [(set_attr "type" "binary")
- (set_attr "length" "1")])
+ "sub\\t%1, %2, %0")
(define_expand "subsi3"
[(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -5104,7 +5804,7 @@
""
"
{
- if (arith_4096_operand(operands[2], DImode))
+ if (arith_4096_operand(operands[2], SImode))
{
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_PLUS (SImode, operands[1],
@@ -5121,18 +5821,16 @@
"@
sub\\t%1, %2, %0
fpsub32s\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "1")])
+ [(set_attr "type" "*,fp")])
(define_insn "*cmp_minus_cc"
[(set (reg:CC_NOOV 100)
(compare:CC_NOOV (minus:SI (match_operand:SI 0 "reg_or_0_operand" "rJ")
(match_operand:SI 1 "arith_operand" "rI"))
(const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"subcc\\t%r0, %1, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_minus_ccx"
[(set (reg:CCX_NOOV 100)
@@ -5141,8 +5839,7 @@
(const_int 0)))]
"TARGET_ARCH64"
"subcc\\t%0, %1, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "cmp_minus_cc_set"
[(set (reg:CC_NOOV 100)
@@ -5153,8 +5850,7 @@
(minus:SI (match_dup 1) (match_dup 2)))]
""
"subcc\\t%r1, %2, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_minus_ccx_set"
[(set (reg:CCX_NOOV 100)
@@ -5165,14 +5861,12 @@
(minus:DI (match_dup 1) (match_dup 2)))]
"TARGET_ARCH64"
"subcc\\t%1, %2, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
;; Integer Multiply/Divide.
-;; The 32 bit multiply/divide instructions are deprecated on v9 and shouldn't
-;; we used. We still use them in 32 bit v9 compilers.
-;; The 64 bit v9 compiler will (/should) widen the args and use muldi3.
+;; The 32 bit multiply/divide instructions are deprecated on v9, but at
+;; least in UltraSPARC I, II and IIi it is a win tick-wise.
(define_insn "mulsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -5180,8 +5874,7 @@
(match_operand:SI 2 "arith_operand" "rI")))]
"TARGET_HARD_MUL"
"smul\\t%1, %2, %0"
- [(set_attr "type" "imul")
- (set_attr "length" "1")])
+ [(set_attr "type" "imul")])
(define_expand "muldi3"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -5203,15 +5896,14 @@
(match_operand:DI 2 "arith_double_operand" "rHI")))]
"TARGET_ARCH64"
"mulx\\t%1, %2, %0"
- [(set_attr "type" "imul")
- (set_attr "length" "1")])
+ [(set_attr "type" "imul")])
;; V8plus wide multiply.
;; XXX
(define_insn "muldi3_v8plus"
[(set (match_operand:DI 0 "register_operand" "=r,h")
(mult:DI (match_operand:DI 1 "arith_double_operand" "%r,0")
- (match_operand:DI 2 "arith_double_operand" "rHI,rHI")))
+ (match_operand:DI 2 "arith_double_operand" "rI,rI")))
(clobber (match_scratch:SI 3 "=&h,X"))
(clobber (match_scratch:SI 4 "=&h,X"))]
"TARGET_V8PLUS"
@@ -5221,6 +5913,13 @@
output_asm_insn (\"srl\\t%L1, 0, %L1\", operands);
if (which_alternative == 1)
output_asm_insn (\"sllx\\t%H1, 32, %H1\", operands);
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (which_alternative == 1)
+ return \"or\\t%L1, %H1, %H1\\n\\tmulx\\t%H1, %2, %L0\;srlx\\t%L0, 32, %H0\";
+ else
+ return \"sllx\\t%H1, 32, %3\\n\\tor\\t%L1, %3, %3\\n\\tmulx\\t%3, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0\";
+ }
if (sparc_check_64 (operands[2], insn) <= 0)
output_asm_insn (\"srl\\t%L2, 0, %L2\", operands);
if (which_alternative == 1)
@@ -5228,21 +5927,19 @@
else
return \"sllx\\t%H1, 32, %3\\n\\tsllx\\t%H2, 32, %4\\n\\tor\\t%L1, %3, %3\\n\\tor\\t%L2, %4, %4\\n\\tmulx\\t%3, %4, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0\";
}"
- [(set_attr "length" "9,8")])
-
-;; It is not known whether this will match.
+ [(set_attr "type" "multi")
+ (set_attr "length" "9,8")])
(define_insn "*cmp_mul_set"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (mult:SI (match_operand:SI 1 "arith_operand" "%r")
- (match_operand:SI 2 "arith_operand" "rI")))
- (set (reg:CC_NOOV 100)
- (compare:CC_NOOV (mult:SI (match_dup 1) (match_dup 2))
- (const_int 0)))]
+ [(set (reg:CC 100)
+ (compare:CC (mult:SI (match_operand:SI 1 "arith_operand" "%r")
+ (match_operand:SI 2 "arith_operand" "rI"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI (match_dup 1) (match_dup 2)))]
"TARGET_V8 || TARGET_SPARCLITE || TARGET_DEPRECATED_V8_INSNS"
"smulcc\\t%1, %2, %0"
- [(set_attr "type" "imul")
- (set_attr "length" "1")])
+ [(set_attr "type" "imul")])
(define_expand "mulsidi3"
[(set (match_operand:DI 0 "register_operand" "")
@@ -5254,12 +5951,11 @@
if (CONSTANT_P (operands[2]))
{
if (TARGET_V8PLUS)
- {
- emit_insn (gen_const_mulsidi3_v8plus (operands[0], operands[1],
- operands[2]));
- DONE;
- }
- emit_insn (gen_const_mulsidi3 (operands[0], operands[1], operands[2]));
+ emit_insn (gen_const_mulsidi3_v8plus (operands[0], operands[1],
+ operands[2]));
+ else
+ emit_insn (gen_const_mulsidi3_sp32 (operands[0], operands[1],
+ operands[2]));
DONE;
}
if (TARGET_V8PLUS)
@@ -5281,7 +5977,8 @@
"@
smul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
smul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
- [(set_attr "length" "2,3")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2,3")])
;; XXX
(define_insn "const_mulsidi3_v8plus"
@@ -5293,7 +5990,8 @@
"@
smul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
smul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
- [(set_attr "length" "2,3")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2,3")])
;; XXX
(define_insn "*mulsidi3_sp32"
@@ -5305,33 +6003,55 @@
{
return TARGET_SPARCLET ? \"smuld\\t%1, %2, %L0\" : \"smul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
}"
- [(set (attr "length")
+ [(set (attr "type")
+ (if_then_else (eq_attr "isa" "sparclet")
+ (const_string "imul") (const_string "multi")))
+ (set (attr "length")
(if_then_else (eq_attr "isa" "sparclet")
(const_int 1) (const_int 2)))])
+(define_insn "*mulsidi3_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
+ (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
+ "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
+ "smul\\t%1, %2, %0"
+ [(set_attr "type" "imul")])
+
;; Extra pattern, because sign_extend of a constant isn't valid.
;; XXX
-(define_insn "const_mulsidi3"
+(define_insn "const_mulsidi3_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
(match_operand:SI 2 "small_int" "I")))]
- "TARGET_HARD_MUL"
+ "TARGET_HARD_MUL32"
"*
{
return TARGET_SPARCLET ? \"smuld\\t%1, %2, %L0\" : \"smul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
}"
- [(set (attr "length")
+ [(set (attr "type")
+ (if_then_else (eq_attr "isa" "sparclet")
+ (const_string "imul") (const_string "multi")))
+ (set (attr "length")
(if_then_else (eq_attr "isa" "sparclet")
(const_int 1) (const_int 2)))])
+(define_insn "const_mulsidi3_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "small_int" "I")))]
+ "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
+ "smul\\t%1, %2, %0"
+ [(set_attr "type" "imul")])
+
(define_expand "smulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "")
(truncate:SI
(lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
(sign_extend:DI (match_operand:SI 2 "arith_operand" "")))
(const_int 32))))]
- "TARGET_HARD_MUL"
+ "TARGET_HARD_MUL && TARGET_ARCH32"
"
{
if (CONSTANT_P (operands[2]))
@@ -5365,9 +6085,10 @@
(clobber (match_scratch:SI 4 "=X,&h"))]
"TARGET_V8PLUS"
"@
- smul %1,%2,%0\;srlx %0,%3,%0
- smul %1,%2,%4\;srlx %4,%3,%0"
- [(set_attr "length" "2")])
+ smul\\t%1, %2, %0\;srlx\\t%0, %3, %0
+ smul\\t%1, %2, %4\;srlx\\t%4, %3, %0"
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
;; The combiner changes TRUNCATE in the previous pattern to SUBREG.
;; XXX
@@ -5378,13 +6099,14 @@
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
(sign_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
(match_operand:SI 3 "const_int_operand" "i,i"))
- 1))
+ 4))
(clobber (match_scratch:SI 4 "=X,&h"))]
"TARGET_V8PLUS"
"@
smul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
smul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
- [(set_attr "length" "2")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
;; XXX
(define_insn "const_smulsi3_highpart_v8plus"
@@ -5398,7 +6120,8 @@
"@
smul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
smul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
- [(set_attr "length" "2")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
;; XXX
(define_insn "*smulsi3_highpart_sp32"
@@ -5407,10 +6130,10 @@
(lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
(sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
(const_int 32))))]
- "TARGET_HARD_MUL32
- && ! TARGET_LIVE_G0"
+ "TARGET_HARD_MUL32"
"smul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
- [(set_attr "length" "2")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
;; XXX
(define_insn "const_smulsi3_highpart"
@@ -5419,10 +6142,10 @@
(lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
(match_operand:SI 2 "register_operand" "r"))
(const_int 32))))]
- "TARGET_HARD_MUL32
- && ! TARGET_LIVE_G0"
+ "TARGET_HARD_MUL32"
"smul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
- [(set_attr "length" "2")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
(define_expand "umulsidi3"
[(set (match_operand:DI 0 "register_operand" "")
@@ -5434,12 +6157,11 @@
if (CONSTANT_P (operands[2]))
{
if (TARGET_V8PLUS)
- {
- emit_insn (gen_const_umulsidi3_v8plus (operands[0], operands[1],
- operands[2]));
- DONE;
- }
- emit_insn (gen_const_umulsidi3 (operands[0], operands[1], operands[2]));
+ emit_insn (gen_const_umulsidi3_v8plus (operands[0], operands[1],
+ operands[2]));
+ else
+ emit_insn (gen_const_umulsidi3_sp32 (operands[0], operands[1],
+ operands[2]));
DONE;
}
if (TARGET_V8PLUS)
@@ -5459,7 +6181,8 @@
"@
umul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
umul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
- [(set_attr "length" "2,3")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2,3")])
;; XXX
(define_insn "*umulsidi3_sp32"
@@ -5471,14 +6194,25 @@
{
return TARGET_SPARCLET ? \"umuld\\t%1, %2, %L0\" : \"umul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
}"
- [(set (attr "length")
+ [(set (attr "type")
+ (if_then_else (eq_attr "isa" "sparclet")
+ (const_string "imul") (const_string "multi")))
+ (set (attr "length")
(if_then_else (eq_attr "isa" "sparclet")
(const_int 1) (const_int 2)))])
+(define_insn "*umulsidi3_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
+ (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
+ "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
+ "umul\\t%1, %2, %0"
+ [(set_attr "type" "imul")])
+
;; Extra pattern, because sign_extend of a constant isn't valid.
;; XXX
-(define_insn "const_umulsidi3"
+(define_insn "const_umulsidi3_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
(match_operand:SI 2 "uns_small_int" "")))]
@@ -5487,10 +6221,21 @@
{
return TARGET_SPARCLET ? \"umuld\\t%1, %2, %L0\" : \"umul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
}"
- [(set (attr "length")
+ [(set (attr "type")
+ (if_then_else (eq_attr "isa" "sparclet")
+ (const_string "imul") (const_string "multi")))
+ (set (attr "length")
(if_then_else (eq_attr "isa" "sparclet")
(const_int 1) (const_int 2)))])
+(define_insn "const_umulsidi3_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "uns_small_int" "")))]
+ "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
+ "umul\\t%1, %2, %0"
+ [(set_attr "type" "imul")])
+
;; XXX
(define_insn "const_umulsidi3_v8plus"
[(set (match_operand:DI 0 "register_operand" "=h,r")
@@ -5501,7 +6246,8 @@
"@
umul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
umul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
- [(set_attr "length" "2,3")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2,3")])
(define_expand "umulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "")
@@ -5509,7 +6255,7 @@
(lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
(zero_extend:DI (match_operand:SI 2 "uns_arith_operand" "")))
(const_int 32))))]
- "TARGET_HARD_MUL"
+ "TARGET_HARD_MUL && TARGET_ARCH32"
"
{
if (CONSTANT_P (operands[2]))
@@ -5545,7 +6291,8 @@
"@
umul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
umul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
- [(set_attr "length" "2")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
;; XXX
(define_insn "const_umulsi3_highpart_v8plus"
@@ -5559,7 +6306,8 @@
"@
umul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
umul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
- [(set_attr "length" "2")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
;; XXX
(define_insn "*umulsi3_highpart_sp32"
@@ -5568,10 +6316,10 @@
(lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
(zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
(const_int 32))))]
- "TARGET_HARD_MUL32
- && ! TARGET_LIVE_G0"
+ "TARGET_HARD_MUL32"
"umul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
- [(set_attr "length" "2")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
;; XXX
(define_insn "const_umulsi3_highpart"
@@ -5580,88 +6328,117 @@
(lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
(match_operand:SI 2 "uns_small_int" ""))
(const_int 32))))]
- "TARGET_HARD_MUL32
- && ! TARGET_LIVE_G0"
+ "TARGET_HARD_MUL32"
"umul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
- [(set_attr "length" "2")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
;; The v8 architecture specifies that there must be 3 instructions between
;; a y register write and a use of it for correct results.
-;; XXX SHEESH
-(define_insn "divsi3"
+(define_expand "divsi3"
+ [(parallel [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (div:SI (match_operand:SI 1 "register_operand" "r,r")
+ (match_operand:SI 2 "input_operand" "rI,m")))
+ (clobber (match_scratch:SI 3 "=&r,&r"))])]
+ "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
+ "
+{
+ if (TARGET_ARCH64)
+ {
+ operands[3] = gen_reg_rtx(SImode);
+ emit_insn (gen_ashrsi3 (operands[3], operands[1], GEN_INT (31)));
+ emit_insn (gen_divsi3_sp64 (operands[0], operands[1], operands[2],
+ operands[3]));
+ DONE;
+ }
+}")
+
+(define_insn "divsi3_sp32"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(div:SI (match_operand:SI 1 "register_operand" "r,r")
(match_operand:SI 2 "input_operand" "rI,m")))
(clobber (match_scratch:SI 3 "=&r,&r"))]
- "(TARGET_V8
- || TARGET_DEPRECATED_V8_INSNS)
- && ! TARGET_LIVE_G0"
+ "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS)
+ && TARGET_ARCH32"
"*
{
if (which_alternative == 0)
- if (TARGET_V9)
- return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tsdiv\\t%1, %2, %0\";
- else
- return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tnop\\n\\tnop\\n\\tnop\\n\\tsdiv\\t%1, %2, %0\";
+ if (TARGET_V9)
+ return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tsdiv\\t%1, %2, %0\";
+ else
+ return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tnop\\n\\tnop\\n\\tnop\\n\\tsdiv\\t%1, %2, %0\";
else
if (TARGET_V9)
- return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tld\\t%2, %3\\n\\tsdiv\\t%1, %3, %0\";
+ return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tld\\t%2, %3\\n\\tsdiv\\t%1, %3, %0\";
else
- return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tld\\t%2, %3\\n\\tnop\\n\\tnop\\n\\tsdiv\\t%1, %3, %0\";
+ return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tld\\t%2, %3\\n\\tnop\\n\\tnop\\n\\tsdiv\\t%1, %3, %0\";
}"
- [(set (attr "length")
+ [(set_attr "type" "multi")
+ (set (attr "length")
(if_then_else (eq_attr "isa" "v9")
(const_int 4) (const_int 7)))])
+(define_insn "divsi3_sp64"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (div:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "input_operand" "rI")))
+ (use (match_operand:SI 3 "register_operand" "r"))]
+ "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
+ "wr\\t%%g0, %3, %%y\\n\\tsdiv\\t%1, %2, %0"
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
+
(define_insn "divdi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(div:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "arith_double_operand" "rHI")))]
"TARGET_ARCH64"
- "sdivx\\t%1, %2, %0")
-
-;; It is not known whether this will match.
+ "sdivx\\t%1, %2, %0"
+ [(set_attr "type" "idiv")])
-;; XXX I hope it doesn't fucking match...
(define_insn "*cmp_sdiv_cc_set"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (div:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "arith_operand" "rI")))
- (set (reg:CC 100)
- (compare:CC (div:SI (match_dup 1) (match_dup 2))
+ [(set (reg:CC 100)
+ (compare:CC (div:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI"))
(const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=r")
+ (div:SI (match_dup 1) (match_dup 2)))
(clobber (match_scratch:SI 3 "=&r"))]
- "(TARGET_V8
- || TARGET_DEPRECATED_V8_INSNS)
- && ! TARGET_LIVE_G0"
+ "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
"*
{
if (TARGET_V9)
- return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tsdivcc\\t%1, %2, %0\";
+ return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tsdivcc\\t%1, %2, %0\";
else
- return \"sra\\t%1, 31, %3\\n\\twr\\t%%g0, %3, %%y\\n\\tnop\\n\\tnop\\n\\tnop\\n\\tsdivcc\\t%1, %2, %0\";
+ return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tnop\\n\\tnop\\n\\tnop\\n\\tsdivcc\\t%1, %2, %0\";
}"
- [(set (attr "length")
+ [(set_attr "type" "multi")
+ (set (attr "length")
(if_then_else (eq_attr "isa" "v9")
(const_int 3) (const_int 6)))])
;; XXX
-(define_insn "udivsi3"
+(define_expand "udivsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "")
+ (match_operand:SI 2 "input_operand" "")))]
+ "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
+ "")
+
+(define_insn "udivsi3_sp32"
[(set (match_operand:SI 0 "register_operand" "=r,&r,&r")
(udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "r,r,m")
(match_operand:SI 2 "input_operand" "rI,m,r")))]
"(TARGET_V8
|| TARGET_DEPRECATED_V8_INSNS)
- && ! TARGET_LIVE_G0"
+ && TARGET_ARCH32"
"*
{
output_asm_insn (\"wr\\t%%g0, %%g0, %%y\", operands);
switch (which_alternative)
{
default:
- if (TARGET_V9)
- return \"udiv\\t%1, %2, %0\";
return \"nop\\n\\tnop\\n\\tnop\\n\\tudiv\\t%1, %2, %0\";
case 1:
return \"ld\\t%2, %0\\n\\tnop\\n\\tnop\\n\\tudiv\\t%1, %0, %0\";
@@ -5669,31 +6446,35 @@
return \"ld\\t%1, %0\\n\\tnop\\n\\tnop\\n\\tudiv\\t%0, %2, %0\";
}
}"
- [(set (attr "length")
- (if_then_else (and (eq_attr "isa" "v9")
- (eq_attr "alternative" "0"))
- (const_int 2) (const_int 5)))])
+ [(set_attr "type" "multi")
+ (set_attr "length" "5")])
+
+(define_insn "udivsi3_sp64"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "r")
+ (match_operand:SI 2 "input_operand" "rI")))]
+ "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
+ "wr\\t%%g0, 0, %%y\\n\\tudiv\\t%1, %2, %0"
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
(define_insn "udivdi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(udiv:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "arith_double_operand" "rHI")))]
"TARGET_ARCH64"
- "udivx\\t%1, %2, %0")
-
-;; It is not known whether this will match.
+ "udivx\\t%1, %2, %0"
+ [(set_attr "type" "idiv")])
-;; XXX I hope it doesn't fucking match...
(define_insn "*cmp_udiv_cc_set"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (udiv:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "arith_operand" "rI")))
- (set (reg:CC 100)
- (compare:CC (udiv:SI (match_dup 1) (match_dup 2))
- (const_int 0)))]
- "(TARGET_V8
- || TARGET_DEPRECATED_V8_INSNS)
- && ! TARGET_LIVE_G0"
+ [(set (reg:CC 100)
+ (compare:CC (udiv:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=r")
+ (udiv:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_V8
+ || TARGET_DEPRECATED_V8_INSNS"
"*
{
if (TARGET_V9)
@@ -5701,7 +6482,8 @@
else
return \"wr\\t%%g0, %%g0, %%y\\n\\tnop\\n\\tnop\\n\\tnop\\n\\tudivcc\\t%1, %2, %0\";
}"
- [(set (attr "length")
+ [(set_attr "type" "multi")
+ (set (attr "length")
(if_then_else (eq_attr "isa" "v9")
(const_int 2) (const_int 5)))])
@@ -5714,8 +6496,7 @@
(match_operand:SI 3 "register_operand" "0")))]
"TARGET_SPARCLET"
"smac\\t%1, %2, %0"
- [(set_attr "type" "imul")
- (set_attr "length" "1")])
+ [(set_attr "type" "imul")])
(define_insn "*smacdi"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -5726,8 +6507,7 @@
(match_operand:DI 3 "register_operand" "0")))]
"TARGET_SPARCLET"
"smacd\\t%1, %2, %L0"
- [(set_attr "type" "imul")
- (set_attr "length" "1")])
+ [(set_attr "type" "imul")])
(define_insn "*umacdi"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -5738,8 +6518,7 @@
(match_operand:DI 3 "register_operand" "0")))]
"TARGET_SPARCLET"
"umacd\\t%1, %2, %L0"
- [(set_attr "type" "imul")
- (set_attr "length" "1")])
+ [(set_attr "type" "imul")])
;;- Boolean instructions
;; We define DImode `and' so with DImode `not' we can get
@@ -5760,8 +6539,9 @@
"@
#
fand\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "2,1")])
+ [(set_attr "type" "*,fp")
+ (set_attr "length" "2,*")
+ (set_attr "fptype" "double")])
(define_insn "*anddi3_sp64"
[(set (match_operand:DI 0 "register_operand" "=r,b")
@@ -5771,8 +6551,8 @@
"@
and\\t%1, %2, %0
fand\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "1,1")])
+ [(set_attr "type" "*,fp")
+ (set_attr "fptype" "double")])
(define_insn "andsi3"
[(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -5782,8 +6562,7 @@
"@
and\\t%1, %2, %0
fands\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "1,1")])
+ [(set_attr "type" "*,fp")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -5817,12 +6596,11 @@
(set (match_dup 5) (match_op_dup:SI 1 [(match_dup 7) (match_dup 9)]))]
"
{
- if (GET_CODE (operands[0]) == SUBREG)
- operands[0] = alter_subreg (operands[0]);
operands[4] = gen_highpart (SImode, operands[0]);
operands[5] = gen_lowpart (SImode, operands[0]);
operands[6] = gen_highpart (SImode, operands[2]);
operands[7] = gen_lowpart (SImode, operands[2]);
+#if HOST_BITS_PER_WIDE_INT == 32
if (GET_CODE (operands[3]) == CONST_INT)
{
if (INTVAL (operands[3]) < 0)
@@ -5831,7 +6609,8 @@
operands[8] = const0_rtx;
}
else
- operands[8] = gen_highpart (SImode, operands[3]);
+#endif
+ operands[8] = gen_highpart_mode (SImode, DImode, operands[3]);
operands[9] = gen_lowpart (SImode, operands[3]);
}")
@@ -5843,8 +6622,9 @@
"@
#
fandnot1\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "2,1")])
+ [(set_attr "type" "*,fp")
+ (set_attr "length" "2,*")
+ (set_attr "fptype" "double")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -5859,9 +6639,7 @@
&& REGNO (SUBREG_REG (operands[0])) < 32))"
[(set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))
(set (match_dup 6) (and:SI (not:SI (match_dup 7)) (match_dup 8)))]
- "if (GET_CODE (operands[0]) == SUBREG)
- operands[0] = alter_subreg (operands[0]);
- operands[3] = gen_highpart (SImode, operands[0]);
+ "operands[3] = gen_highpart (SImode, operands[0]);
operands[4] = gen_highpart (SImode, operands[1]);
operands[5] = gen_highpart (SImode, operands[2]);
operands[6] = gen_lowpart (SImode, operands[0]);
@@ -5876,8 +6654,8 @@
"@
andn\\t%2, %1, %0
fandnot1\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "1,1")])
+ [(set_attr "type" "*,fp")
+ (set_attr "fptype" "double")])
(define_insn "*and_not_si"
[(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -5887,8 +6665,7 @@
"@
andn\\t%2, %1, %0
fandnot1s\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "1,1")])
+ [(set_attr "type" "*,fp")])
(define_expand "iordi3"
[(set (match_operand:DI 0 "register_operand" "")
@@ -5905,8 +6682,9 @@
"@
#
for\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "2,1")])
+ [(set_attr "type" "*,fp")
+ (set_attr "length" "2,*")
+ (set_attr "fptype" "double")])
(define_insn "*iordi3_sp64"
[(set (match_operand:DI 0 "register_operand" "=r,b")
@@ -5916,8 +6694,8 @@
"@
or\\t%1, %2, %0
for\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "1,1")])
+ [(set_attr "type" "*,fp")
+ (set_attr "fptype" "double")])
(define_insn "iorsi3"
[(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -5927,8 +6705,7 @@
"@
or\\t%1, %2, %0
fors\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "1,1")])
+ [(set_attr "type" "*,fp")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -5953,8 +6730,9 @@
"@
#
fornot1\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "2,1")])
+ [(set_attr "type" "*,fp")
+ (set_attr "length" "2,*")
+ (set_attr "fptype" "double")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -5969,9 +6747,7 @@
&& REGNO (SUBREG_REG (operands[0])) < 32))"
[(set (match_dup 3) (ior:SI (not:SI (match_dup 4)) (match_dup 5)))
(set (match_dup 6) (ior:SI (not:SI (match_dup 7)) (match_dup 8)))]
- "if (GET_CODE (operands[0]) == SUBREG)
- operands[0] = alter_subreg (operands[0]);
- operands[3] = gen_highpart (SImode, operands[0]);
+ "operands[3] = gen_highpart (SImode, operands[0]);
operands[4] = gen_highpart (SImode, operands[1]);
operands[5] = gen_highpart (SImode, operands[2]);
operands[6] = gen_lowpart (SImode, operands[0]);
@@ -5986,8 +6762,8 @@
"@
orn\\t%2, %1, %0
fornot1\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "1,1")])
+ [(set_attr "type" "*,fp")
+ (set_attr "fptype" "double")])
(define_insn "*or_not_si"
[(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -5997,8 +6773,7 @@
"@
orn\\t%2, %1, %0
fornot1s\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "1,1")])
+ [(set_attr "type" "*,fp")])
(define_expand "xordi3"
[(set (match_operand:DI 0 "register_operand" "")
@@ -6015,8 +6790,9 @@
"@
#
fxor\\t%1, %2, %0"
- [(set_attr "length" "2,1")
- (set_attr "type" "ialu,fp")])
+ [(set_attr "type" "*,fp")
+ (set_attr "length" "2,*")
+ (set_attr "fptype" "double")])
(define_insn "*xordi3_sp64"
[(set (match_operand:DI 0 "register_operand" "=r,b")
@@ -6026,8 +6802,8 @@
"@
xor\\t%r1, %2, %0
fxor\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "1,1")])
+ [(set_attr "type" "*,fp")
+ (set_attr "fptype" "double")])
(define_insn "*xordi3_sp64_dbl"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -6035,9 +6811,7 @@
(match_operand:DI 2 "const64_operand" "")))]
"(TARGET_ARCH64
&& HOST_BITS_PER_WIDE_INT != 64)"
- "xor\\t%1, %2, %0"
- [(set_attr "type" "ialu")
- (set_attr "length" "1")])
+ "xor\\t%1, %2, %0")
(define_insn "xorsi3"
[(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -6047,8 +6821,7 @@
"@
xor\\t%r1, %2, %0
fxors\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "1,1")])
+ [(set_attr "type" "*,fp")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -6090,8 +6863,9 @@
"@
#
fxnor\\t%1, %2, %0"
- [(set_attr "length" "2,1")
- (set_attr "type" "ialu,fp")])
+ [(set_attr "type" "*,fp")
+ (set_attr "length" "2,*")
+ (set_attr "fptype" "double")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -6106,9 +6880,7 @@
&& REGNO (SUBREG_REG (operands[0])) < 32))"
[(set (match_dup 3) (not:SI (xor:SI (match_dup 4) (match_dup 5))))
(set (match_dup 6) (not:SI (xor:SI (match_dup 7) (match_dup 8))))]
- "if (GET_CODE (operands[0]) == SUBREG)
- operands[0] = alter_subreg (operands[0]);
- operands[3] = gen_highpart (SImode, operands[0]);
+ "operands[3] = gen_highpart (SImode, operands[0]);
operands[4] = gen_highpart (SImode, operands[1]);
operands[5] = gen_highpart (SImode, operands[2]);
operands[6] = gen_lowpart (SImode, operands[0]);
@@ -6123,8 +6895,8 @@
"@
xnor\\t%r1, %2, %0
fxnor\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "1,1")])
+ [(set_attr "type" "*,fp")
+ (set_attr "fptype" "double")])
(define_insn "*xor_not_si"
[(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -6134,8 +6906,7 @@
"@
xnor\\t%r1, %2, %0
fxnors\\t%1, %2, %0"
- [(set_attr "type" "ialu,fp")
- (set_attr "length" "1,1")])
+ [(set_attr "type" "*,fp")])
;; These correspond to the above in the case where we also (or only)
;; want to set the condition code.
@@ -6147,10 +6918,9 @@
[(match_operand:SI 0 "arith_operand" "%r")
(match_operand:SI 1 "arith_operand" "rI")])
(const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"%A2cc\\t%0, %1, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_ccx_arith_op"
[(set (reg:CCX 100)
@@ -6161,8 +6931,7 @@
(const_int 0)))]
"TARGET_ARCH64"
"%A2cc\\t%0, %1, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_cc_arith_op_set"
[(set (reg:CC 100)
@@ -6172,11 +6941,10 @@
(match_operand:SI 2 "arith_operand" "rI")])
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
- (match_dup 3))]
- ""
+ (match_operator:SI 4 "cc_arithop" [(match_dup 1) (match_dup 2)]))]
+ "GET_CODE (operands[3]) == GET_CODE (operands[4])"
"%A3cc\\t%1, %2, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_ccx_arith_op_set"
[(set (reg:CCX 100)
@@ -6186,11 +6954,10 @@
(match_operand:DI 2 "arith_double_operand" "rHI")])
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
- (match_dup 3))]
- "TARGET_ARCH64"
+ (match_operator:DI 4 "cc_arithop" [(match_dup 1) (match_dup 2)]))]
+ "TARGET_ARCH64 && GET_CODE (operands[3]) == GET_CODE (operands[4])"
"%A3cc\\t%1, %2, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_cc_xor_not"
[(set (reg:CC 100)
@@ -6198,10 +6965,9 @@
(not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ")
(match_operand:SI 1 "arith_operand" "rI")))
(const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"xnorcc\\t%r0, %1, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_ccx_xor_not"
[(set (reg:CCX 100)
@@ -6211,8 +6977,7 @@
(const_int 0)))]
"TARGET_ARCH64"
"xnorcc\\t%r0, %1, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_cc_xor_not_set"
[(set (reg:CC 100)
@@ -6224,8 +6989,7 @@
(not:SI (xor:SI (match_dup 1) (match_dup 2))))]
""
"xnorcc\\t%r1, %2, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_ccx_xor_not_set"
[(set (reg:CCX 100)
@@ -6237,8 +7001,7 @@
(not:DI (xor:DI (match_dup 1) (match_dup 2))))]
"TARGET_ARCH64"
"xnorcc\\t%r1, %2, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_cc_arith_op_not"
[(set (reg:CC 100)
@@ -6247,10 +7010,9 @@
[(not:SI (match_operand:SI 0 "arith_operand" "rI"))
(match_operand:SI 1 "reg_or_0_operand" "rJ")])
(const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"%B2cc\\t%r1, %0, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_ccx_arith_op_not"
[(set (reg:CCX 100)
@@ -6261,8 +7023,7 @@
(const_int 0)))]
"TARGET_ARCH64"
"%B2cc\\t%r1, %0, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_cc_arith_op_not_set"
[(set (reg:CC 100)
@@ -6272,11 +7033,11 @@
(match_operand:SI 2 "reg_or_0_operand" "rJ")])
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
- (match_dup 3))]
- ""
+ (match_operator:SI 4 "cc_arithopn"
+ [(not:SI (match_dup 1)) (match_dup 2)]))]
+ "GET_CODE (operands[3]) == GET_CODE (operands[4])"
"%B3cc\\t%r2, %1, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_ccx_arith_op_not_set"
[(set (reg:CCX 100)
@@ -6286,11 +7047,11 @@
(match_operand:DI 2 "reg_or_0_operand" "rJ")])
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
- (match_dup 3))]
- "TARGET_ARCH64"
+ (match_operator:DI 4 "cc_arithopn"
+ [(not:DI (match_dup 1)) (match_dup 2)]))]
+ "TARGET_ARCH64 && GET_CODE (operands[3]) == GET_CODE (operands[4])"
"%B3cc\\t%r2, %1, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
;; We cannot use the "neg" pseudo insn because the Sun assembler
;; does not know how to make it work for constants.
@@ -6303,11 +7064,14 @@
{
if (! TARGET_ARCH64)
{
- emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
- gen_rtx_SET (VOIDmode, operand0,
- gen_rtx_NEG (DImode, operand1)),
- gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_REG (CCmode, SPARC_ICC_REG)))));
+ emit_insn (gen_rtx_PARALLEL
+ (VOIDmode,
+ gen_rtvec (2,
+ gen_rtx_SET (VOIDmode, operand0,
+ gen_rtx_NEG (DImode, operand1)),
+ gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_REG (CCmode,
+ SPARC_ICC_REG)))));
DONE;
}
}")
@@ -6316,18 +7080,15 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(neg:DI (match_operand:DI 1 "register_operand" "r")))
(clobber (reg:CC 100))]
- "! TARGET_ARCH64
- && ! TARGET_LIVE_G0"
+ "TARGET_ARCH32"
"#"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
+ [(set_attr "length" "2")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(neg:DI (match_operand:DI 1 "register_operand" "")))
(clobber (reg:CC 100))]
- "! TARGET_ARCH64
- && ! TARGET_LIVE_G0
+ "TARGET_ARCH32
&& reload_completed"
[(parallel [(set (reg:CC_NOOV 100)
(compare:CC_NOOV (minus:SI (const_int 0) (match_dup 5))
@@ -6344,44 +7105,21 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(neg:DI (match_operand:DI 1 "register_operand" "r")))]
"TARGET_ARCH64"
- "sub\\t%%g0, %1, %0"
- [(set_attr "type" "unary")
- (set_attr "length" "1")])
-
-(define_expand "negsi2"
- [(set (match_operand:SI 0 "register_operand" "")
- (neg:SI (match_operand:SI 1 "arith_operand" "")))]
- ""
- "
-{
- if (TARGET_LIVE_G0)
- {
- rtx zero_reg = gen_reg_rtx (SImode);
-
- emit_insn (gen_rtx_SET (VOIDmode, zero_reg, const0_rtx));
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_MINUS (SImode, zero_reg,
- operands[1])));
- DONE;
- }
-}")
+ "sub\\t%%g0, %1, %0")
-(define_insn "*negsi2_not_liveg0"
+(define_insn "negsi2"
[(set (match_operand:SI 0 "register_operand" "=r")
- (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
- "! TARGET_LIVE_G0"
- "sub\\t%%g0, %1, %0"
- [(set_attr "type" "unary")
- (set_attr "length" "1")])
+ (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
+ ""
+ "sub\\t%%g0, %1, %0")
(define_insn "*cmp_cc_neg"
[(set (reg:CC_NOOV 100)
(compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI"))
(const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"subcc\\t%%g0, %0, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_ccx_neg"
[(set (reg:CCX_NOOV 100)
@@ -6389,8 +7127,7 @@
(const_int 0)))]
"TARGET_ARCH64"
"subcc\\t%%g0, %0, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_cc_set_neg"
[(set (reg:CC_NOOV 100)
@@ -6398,10 +7135,9 @@
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_dup 1)))]
- "! TARGET_LIVE_G0"
+ ""
"subcc\\t%%g0, %1, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_ccx_set_neg"
[(set (reg:CCX_NOOV 100)
@@ -6411,8 +7147,7 @@
(neg:DI (match_dup 1)))]
"TARGET_ARCH64"
"subcc\\t%%g0, %1, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
;; We cannot use the "not" pseudo insn because the Sun assembler
;; does not know how to make it work for constants.
@@ -6429,8 +7164,9 @@
"@
#
fnot1\\t%1, %0"
- [(set_attr "type" "unary,fp")
- (set_attr "length" "2,1")])
+ [(set_attr "type" "*,fp")
+ (set_attr "length" "2,*")
+ (set_attr "fptype" "double")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -6444,9 +7180,7 @@
&& REGNO (SUBREG_REG (operands[0])) < 32))"
[(set (match_dup 2) (not:SI (xor:SI (match_dup 3) (const_int 0))))
(set (match_dup 4) (not:SI (xor:SI (match_dup 5) (const_int 0))))]
- "if (GET_CODE (operands[0]) == SUBREG)
- operands[0] = alter_subreg (operands[0]);
- operands[2] = gen_highpart (SImode, operands[0]);
+ "operands[2] = gen_highpart (SImode, operands[0]);
operands[3] = gen_highpart (SImode, operands[1]);
operands[4] = gen_lowpart (SImode, operands[0]);
operands[5] = gen_lowpart (SImode, operands[1]);")
@@ -6458,59 +7192,25 @@
"@
xnor\\t%%g0, %1, %0
fnot1\\t%1, %0"
- [(set_attr "type" "unary,fp")
- (set_attr "length" "1")])
+ [(set_attr "type" "*,fp")
+ (set_attr "fptype" "double")])
-(define_expand "one_cmplsi2"
- [(set (match_operand:SI 0 "register_operand" "")
- (not:SI (match_operand:SI 1 "arith_operand" "")))]
- ""
- "
-{
- if (TARGET_LIVE_G0
- && GET_CODE (operands[1]) == CONST_INT)
- {
- rtx zero_reg = gen_reg_rtx (SImode);
-
- emit_insn (gen_rtx_SET (VOIDmode, zero_reg, const0_rtx));
- emit_insn (gen_rtx_SET (VOIDmode,
- operands[0],
- gen_rtx_NOT (SImode,
- gen_rtx_XOR (SImode,
- zero_reg,
- operands[1]))));
- DONE;
- }
-}")
-
-(define_insn "*one_cmplsi2_not_liveg0"
+(define_insn "one_cmplsi2"
[(set (match_operand:SI 0 "register_operand" "=r,d")
(not:SI (match_operand:SI 1 "arith_operand" "rI,d")))]
- "! TARGET_LIVE_G0"
+ ""
"@
xnor\\t%%g0, %1, %0
fnot1s\\t%1, %0"
- [(set_attr "type" "unary,fp")
- (set_attr "length" "1,1")])
-
-(define_insn "*one_cmplsi2_liveg0"
- [(set (match_operand:SI 0 "register_operand" "=r,d")
- (not:SI (match_operand:SI 1 "arith_operand" "r,d")))]
- "TARGET_LIVE_G0"
- "@
- xnor\\t%1, 0, %0
- fnot1s\\t%1, %0"
- [(set_attr "type" "unary,fp")
- (set_attr "length" "1,1")])
+ [(set_attr "type" "*,fp")])
(define_insn "*cmp_cc_not"
[(set (reg:CC 100)
(compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI"))
(const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"xnorcc\\t%%g0, %0, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_ccx_not"
[(set (reg:CCX 100)
@@ -6518,8 +7218,7 @@
(const_int 0)))]
"TARGET_ARCH64"
"xnorcc\\t%%g0, %0, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_cc_set_not"
[(set (reg:CC 100)
@@ -6527,10 +7226,9 @@
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
(not:SI (match_dup 1)))]
- "! TARGET_LIVE_G0"
+ ""
"xnorcc\\t%%g0, %1, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_ccx_set_not"
[(set (reg:CCX 100)
@@ -6540,19 +7238,79 @@
(not:DI (match_dup 1)))]
"TARGET_ARCH64"
"xnorcc\\t%%g0, %1, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
+
+(define_insn "*cmp_cc_set"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "register_operand" "r"))
+ (set (reg:CC 100)
+ (compare:CC (match_dup 1)
+ (const_int 0)))]
+ ""
+ "orcc\\t%1, 0, %0"
+ [(set_attr "type" "compare")])
+
+(define_insn "*cmp_ccx_set64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (match_operand:DI 1 "register_operand" "r"))
+ (set (reg:CCX 100)
+ (compare:CCX (match_dup 1)
+ (const_int 0)))]
+ "TARGET_ARCH64"
+ "orcc\\t%1, 0, %0"
+ [(set_attr "type" "compare")])
;; Floating point arithmetic instructions.
-(define_insn "addtf3"
+(define_expand "addtf3"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (plus:TF (match_operand:TF 1 "general_operand" "")
+ (match_operand:TF 2 "general_operand" "")))]
+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
+ "
+{
+ if (! TARGET_HARD_QUAD)
+ {
+ rtx slot0, slot1, slot2;
+
+ if (GET_CODE (operands[0]) != MEM)
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ else
+ slot0 = operands[0];
+ if (GET_CODE (operands[1]) != MEM)
+ {
+ slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
+ }
+ else
+ slot1 = operands[1];
+ if (GET_CODE (operands[2]) != MEM)
+ {
+ slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
+ }
+ else
+ slot2 = operands[2];
+
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_add\"), 0,
+ VOIDmode, 3,
+ XEXP (slot0, 0), Pmode,
+ XEXP (slot1, 0), Pmode,
+ XEXP (slot2, 0), Pmode);
+
+ if (GET_CODE (operands[0]) != MEM)
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
+ DONE;
+ }
+}")
+
+(define_insn "*addtf3_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
(plus:TF (match_operand:TF 1 "register_operand" "e")
(match_operand:TF 2 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
"faddq\\t%1, %2, %0"
- [(set_attr "type" "fp")
- (set_attr "length" "1")])
+ [(set_attr "type" "fp")])
(define_insn "adddf3"
[(set (match_operand:DF 0 "register_operand" "=e")
@@ -6561,7 +7319,7 @@
"TARGET_FPU"
"faddd\\t%1, %2, %0"
[(set_attr "type" "fp")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
(define_insn "addsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
@@ -6569,17 +7327,57 @@
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU"
"fadds\\t%1, %2, %0"
- [(set_attr "type" "fp")
- (set_attr "length" "1")])
+ [(set_attr "type" "fp")])
-(define_insn "subtf3"
+(define_expand "subtf3"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (minus:TF (match_operand:TF 1 "general_operand" "")
+ (match_operand:TF 2 "general_operand" "")))]
+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
+ "
+{
+ if (! TARGET_HARD_QUAD)
+ {
+ rtx slot0, slot1, slot2;
+
+ if (GET_CODE (operands[0]) != MEM)
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ else
+ slot0 = operands[0];
+ if (GET_CODE (operands[1]) != MEM)
+ {
+ slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
+ }
+ else
+ slot1 = operands[1];
+ if (GET_CODE (operands[2]) != MEM)
+ {
+ slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
+ }
+ else
+ slot2 = operands[2];
+
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_sub\"), 0,
+ VOIDmode, 3,
+ XEXP (slot0, 0), Pmode,
+ XEXP (slot1, 0), Pmode,
+ XEXP (slot2, 0), Pmode);
+
+ if (GET_CODE (operands[0]) != MEM)
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
+ DONE;
+ }
+}")
+
+(define_insn "*subtf3_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
(minus:TF (match_operand:TF 1 "register_operand" "e")
(match_operand:TF 2 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
"fsubq\\t%1, %2, %0"
- [(set_attr "type" "fp")
- (set_attr "length" "1")])
+ [(set_attr "type" "fp")])
(define_insn "subdf3"
[(set (match_operand:DF 0 "register_operand" "=e")
@@ -6588,7 +7386,7 @@
"TARGET_FPU"
"fsubd\\t%1, %2, %0"
[(set_attr "type" "fp")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
(define_insn "subsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
@@ -6596,17 +7394,57 @@
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU"
"fsubs\\t%1, %2, %0"
- [(set_attr "type" "fp")
- (set_attr "length" "1")])
+ [(set_attr "type" "fp")])
+
+(define_expand "multf3"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (mult:TF (match_operand:TF 1 "general_operand" "")
+ (match_operand:TF 2 "general_operand" "")))]
+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
+ "
+{
+ if (! TARGET_HARD_QUAD)
+ {
+ rtx slot0, slot1, slot2;
+
+ if (GET_CODE (operands[0]) != MEM)
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ else
+ slot0 = operands[0];
+ if (GET_CODE (operands[1]) != MEM)
+ {
+ slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
+ }
+ else
+ slot1 = operands[1];
+ if (GET_CODE (operands[2]) != MEM)
+ {
+ slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
+ }
+ else
+ slot2 = operands[2];
+
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_mul\"), 0,
+ VOIDmode, 3,
+ XEXP (slot0, 0), Pmode,
+ XEXP (slot1, 0), Pmode,
+ XEXP (slot2, 0), Pmode);
+
+ if (GET_CODE (operands[0]) != MEM)
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
+ DONE;
+ }
+}")
-(define_insn "multf3"
+(define_insn "*multf3_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
(mult:TF (match_operand:TF 1 "register_operand" "e")
(match_operand:TF 2 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
"fmulq\\t%1, %2, %0"
- [(set_attr "type" "fpmul")
- (set_attr "length" "1")])
+ [(set_attr "type" "fpmul")])
(define_insn "muldf3"
[(set (match_operand:DF 0 "register_operand" "=e")
@@ -6615,7 +7453,7 @@
"TARGET_FPU"
"fmuld\\t%1, %2, %0"
[(set_attr "type" "fpmul")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
(define_insn "mulsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
@@ -6623,8 +7461,7 @@
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU"
"fmuls\\t%1, %2, %0"
- [(set_attr "type" "fpmul")
- (set_attr "length" "1")])
+ [(set_attr "type" "fpmul")])
(define_insn "*muldf3_extend"
[(set (match_operand:DF 0 "register_operand" "=e")
@@ -6633,7 +7470,7 @@
"(TARGET_V8 || TARGET_V9) && TARGET_FPU"
"fsmuld\\t%1, %2, %0"
[(set_attr "type" "fpmul")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
(define_insn "*multf3_extend"
[(set (match_operand:TF 0 "register_operand" "=e")
@@ -6641,18 +7478,58 @@
(float_extend:TF (match_operand:DF 2 "register_operand" "e"))))]
"(TARGET_V8 || TARGET_V9) && TARGET_FPU && TARGET_HARD_QUAD"
"fdmulq\\t%1, %2, %0"
- [(set_attr "type" "fpmul")
- (set_attr "length" "1")])
+ [(set_attr "type" "fpmul")])
+
+(define_expand "divtf3"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (div:TF (match_operand:TF 1 "general_operand" "")
+ (match_operand:TF 2 "general_operand" "")))]
+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
+ "
+{
+ if (! TARGET_HARD_QUAD)
+ {
+ rtx slot0, slot1, slot2;
+
+ if (GET_CODE (operands[0]) != MEM)
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ else
+ slot0 = operands[0];
+ if (GET_CODE (operands[1]) != MEM)
+ {
+ slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
+ }
+ else
+ slot1 = operands[1];
+ if (GET_CODE (operands[2]) != MEM)
+ {
+ slot2 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ emit_insn (gen_rtx_SET (VOIDmode, slot2, operands[2]));
+ }
+ else
+ slot2 = operands[2];
+
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_div\"), 0,
+ VOIDmode, 3,
+ XEXP (slot0, 0), Pmode,
+ XEXP (slot1, 0), Pmode,
+ XEXP (slot2, 0), Pmode);
+
+ if (GET_CODE (operands[0]) != MEM)
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
+ DONE;
+ }
+}")
;; don't have timing for quad-prec. divide.
-(define_insn "divtf3"
+(define_insn "*divtf3_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
(div:TF (match_operand:TF 1 "register_operand" "e")
(match_operand:TF 2 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
"fdivq\\t%1, %2, %0"
- [(set_attr "type" "fpdivd")
- (set_attr "length" "1")])
+ [(set_attr "type" "fpdivd")])
(define_insn "divdf3"
[(set (match_operand:DF 0 "register_operand" "=e")
@@ -6661,7 +7538,7 @@
"TARGET_FPU"
"fdivd\\t%1, %2, %0"
[(set_attr "type" "fpdivd")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
(define_insn "divsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
@@ -6669,8 +7546,7 @@
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU"
"fdivs\\t%1, %2, %0"
- [(set_attr "type" "fpdivs")
- (set_attr "length" "1")])
+ [(set_attr "type" "fpdivs")])
(define_expand "negtf2"
[(set (match_operand:TF 0 "register_operand" "=e,e")
@@ -6687,8 +7563,8 @@
"@
fnegs\\t%0, %0
#"
- [(set_attr "type" "fpmove")
- (set_attr "length" "1,2")])
+ [(set_attr "type" "fpmove,*")
+ (set_attr "length" "*,2")])
(define_split
[(set (match_operand:TF 0 "register_operand" "")
@@ -6700,11 +7576,7 @@
[(set (match_dup 2) (neg:SF (match_dup 3)))
(set (match_dup 4) (match_dup 5))
(set (match_dup 6) (match_dup 7))]
- "if (GET_CODE (operands[0]) == SUBREG)
- operands[0] = alter_subreg (operands[0]);
- if (GET_CODE (operands[1]) == SUBREG)
- operands[1] = alter_subreg (operands[1]);
- operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
+ "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);
@@ -6719,8 +7591,9 @@
"@
fnegd\\t%0, %0
#"
- [(set_attr "type" "fpmove")
- (set_attr "length" "1,2")])
+ [(set_attr "type" "fpmove,*")
+ (set_attr "length" "*,2")
+ (set_attr "fptype" "double")])
(define_split
[(set (match_operand:TF 0 "register_operand" "")
@@ -6731,11 +7604,7 @@
&& sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
[(set (match_dup 2) (neg:DF (match_dup 3)))
(set (match_dup 4) (match_dup 5))]
- "if (GET_CODE (operands[0]) == SUBREG)
- operands[0] = alter_subreg (operands[0]);
- if (GET_CODE (operands[1]) == SUBREG)
- operands[1] = alter_subreg (operands[1]);
- operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
+ "operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
operands[3] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]));
operands[4] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);")
@@ -6753,8 +7622,8 @@
"@
fnegs\\t%0, %0
#"
- [(set_attr "type" "fpmove")
- (set_attr "length" "1,2")])
+ [(set_attr "type" "fpmove,*")
+ (set_attr "length" "*,2")])
(define_split
[(set (match_operand:DF 0 "register_operand" "")
@@ -6765,11 +7634,7 @@
&& sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
[(set (match_dup 2) (neg:SF (match_dup 3)))
(set (match_dup 4) (match_dup 5))]
- "if (GET_CODE (operands[0]) == SUBREG)
- operands[0] = alter_subreg (operands[0]);
- if (GET_CODE (operands[1]) == SUBREG)
- operands[1] = alter_subreg (operands[1]);
- operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
+ "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);")
@@ -6780,15 +7645,14 @@
"TARGET_FPU && TARGET_V9"
"fnegd\\t%1, %0"
[(set_attr "type" "fpmove")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
(define_insn "negsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(neg:SF (match_operand:SF 1 "register_operand" "f")))]
"TARGET_FPU"
"fnegs\\t%1, %0"
- [(set_attr "type" "fpmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "fpmove")])
(define_expand "abstf2"
[(set (match_operand:TF 0 "register_operand" "")
@@ -6804,12 +7668,12 @@
"@
fabss\\t%0, %0
#"
- [(set_attr "type" "fpmove")
- (set_attr "length" "1,2")])
+ [(set_attr "type" "fpmove,*")
+ (set_attr "length" "*,2")])
(define_split
- [(set (match_operand:TF 0 "register_operand" "=e,e")
- (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
+ [(set (match_operand:TF 0 "register_operand" "")
+ (abs:TF (match_operand:TF 1 "register_operand" "")))]
"TARGET_FPU
&& ! TARGET_V9
&& reload_completed
@@ -6817,11 +7681,7 @@
[(set (match_dup 2) (abs:SF (match_dup 3)))
(set (match_dup 4) (match_dup 5))
(set (match_dup 6) (match_dup 7))]
- "if (GET_CODE (operands[0]) == SUBREG)
- operands[0] = alter_subreg (operands[0]);
- if (GET_CODE (operands[1]) == SUBREG)
- operands[1] = alter_subreg (operands[1]);
- operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
+ "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);
@@ -6836,7 +7696,7 @@
fabsd\\t%0, %0
fabsq\\t%1, %0"
[(set_attr "type" "fpmove")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double,*")])
(define_insn "*abstf2_v9"
[(set (match_operand:TF 0 "register_operand" "=e,e")
@@ -6845,23 +7705,20 @@
"@
fabsd\\t%0, %0
#"
- [(set_attr "type" "fpmove")
- (set_attr "length" "1,2")])
+ [(set_attr "type" "fpmove,*")
+ (set_attr "length" "*,2")
+ (set_attr "fptype" "double,*")])
(define_split
- [(set (match_operand:TF 0 "register_operand" "=e,e")
- (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
+ [(set (match_operand:TF 0 "register_operand" "")
+ (abs:TF (match_operand:TF 1 "register_operand" "")))]
"TARGET_FPU
&& TARGET_V9
&& reload_completed
&& sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
[(set (match_dup 2) (abs:DF (match_dup 3)))
(set (match_dup 4) (match_dup 5))]
- "if (GET_CODE (operands[0]) == SUBREG)
- operands[0] = alter_subreg (operands[0]);
- if (GET_CODE (operands[1]) == SUBREG)
- operands[1] = alter_subreg (operands[1]);
- operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
+ "operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
operands[3] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]));
operands[4] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);")
@@ -6879,23 +7736,19 @@
"@
fabss\\t%0, %0
#"
- [(set_attr "type" "fpmove")
- (set_attr "length" "1,2")])
+ [(set_attr "type" "fpmove,*")
+ (set_attr "length" "*,2")])
(define_split
- [(set (match_operand:DF 0 "register_operand" "=e,e")
- (abs:DF (match_operand:DF 1 "register_operand" "0,e")))]
+ [(set (match_operand:DF 0 "register_operand" "")
+ (abs:DF (match_operand:DF 1 "register_operand" "")))]
"TARGET_FPU
&& ! TARGET_V9
&& reload_completed
&& sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
[(set (match_dup 2) (abs:SF (match_dup 3)))
(set (match_dup 4) (match_dup 5))]
- "if (GET_CODE (operands[0]) == SUBREG)
- operands[0] = alter_subreg (operands[0]);
- if (GET_CODE (operands[1]) == SUBREG)
- operands[1] = alter_subreg (operands[1]);
- operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
+ "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);")
@@ -6906,39 +7759,69 @@
"TARGET_FPU && TARGET_V9"
"fabsd\\t%1, %0"
[(set_attr "type" "fpmove")
- (set_attr "length" "1")])
+ (set_attr "fptype" "double")])
(define_insn "abssf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(abs:SF (match_operand:SF 1 "register_operand" "f")))]
"TARGET_FPU"
"fabss\\t%1, %0"
- [(set_attr "type" "fpmove")
- (set_attr "length" "1")])
+ [(set_attr "type" "fpmove")])
-(define_insn "sqrttf2"
+(define_expand "sqrttf2"
+ [(set (match_operand:TF 0 "register_operand" "=e")
+ (sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
+ "
+{
+ if (! TARGET_HARD_QUAD)
+ {
+ rtx slot0, slot1;
+
+ if (GET_CODE (operands[0]) != MEM)
+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ else
+ slot0 = operands[0];
+ if (GET_CODE (operands[1]) != MEM)
+ {
+ slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+ emit_insn (gen_rtx_SET (VOIDmode, slot1, operands[1]));
+ }
+ else
+ slot1 = operands[1];
+
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, \"_Qp_sqrt\"), 0,
+ VOIDmode, 2,
+ XEXP (slot0, 0), Pmode,
+ XEXP (slot1, 0), Pmode);
+
+ if (GET_CODE (operands[0]) != MEM)
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], slot0));
+ DONE;
+ }
+}")
+
+(define_insn "*sqrttf2_hq"
[(set (match_operand:TF 0 "register_operand" "=e")
(sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
"fsqrtq\\t%1, %0"
- [(set_attr "type" "fpsqrt")
- (set_attr "length" "1")])
+ [(set_attr "type" "fpsqrtd")])
(define_insn "sqrtdf2"
[(set (match_operand:DF 0 "register_operand" "=e")
(sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
"TARGET_FPU"
"fsqrtd\\t%1, %0"
- [(set_attr "type" "fpsqrt")
- (set_attr "length" "1")])
+ [(set_attr "type" "fpsqrtd")
+ (set_attr "fptype" "double")])
(define_insn "sqrtsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
"TARGET_FPU"
"fsqrts\\t%1, %0"
- [(set_attr "type" "fpsqrt")
- (set_attr "length" "1")])
+ [(set_attr "type" "fpsqrts")])
;;- arithmetic shift instructions
@@ -6955,8 +7838,7 @@
return \"sll\\t%1, %2, %0\";
}"
- [(set_attr "type" "shift")
- (set_attr "length" "1")])
+ [(set_attr "type" "shift")])
;; We special case multiplication by two, as add can be done
;; in both ALUs, while shift only in IEU0 on UltraSPARC.
@@ -6965,9 +7847,7 @@
(ashift:SI (match_operand:SI 1 "register_operand" "r")
(const_int 1)))]
""
- "add\\t%1, %1, %0"
- [(set_attr "type" "binary")
- (set_attr "length" "1")])
+ "add\\t%1, %1, %0")
(define_expand "ashldi3"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -6992,9 +7872,7 @@
(ashift:DI (match_operand:DI 1 "register_operand" "r")
(const_int 1)))]
"TARGET_ARCH64"
- "add\\t%1, %1, %0"
- [(set_attr "type" "binary")
- (set_attr "length" "1")])
+ "add\\t%1, %1, %0")
(define_insn "*ashldi3_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -7009,8 +7887,7 @@
return \"sllx\\t%1, %2, %0\";
}"
- [(set_attr "type" "shift")
- (set_attr "length" "1")])
+ [(set_attr "type" "shift")])
;; XXX UGH!
(define_insn "ashldi3_v8plus"
@@ -7020,34 +7897,35 @@
(clobber (match_scratch:SI 3 "=X,X,&h"))]
"TARGET_V8PLUS"
"*return sparc_v8plus_shift (operands, insn, \"sllx\");"
- [(set_attr "length" "5,5,6")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "5,5,6")])
;; Optimize (1LL<<x)-1
;; XXX this also needs to be fixed to handle equal subregs
;; XXX first before we could re-enable it.
-(define_insn ""
- [(set (match_operand:DI 0 "register_operand" "=h")
- (plus:DI (ashift:DI (const_int 1)
- (match_operand:SI 2 "arith_operand" "rI"))
- (const_int -1)))]
- "0 && TARGET_V8PLUS"
- "*
-{
- if (GET_CODE (operands[2]) == REG && REGNO (operands[2]) == REGNO (operands[0]))
- return \"mov 1,%L0\;sllx %L0,%2,%L0\;sub %L0,1,%L0\;srlx %L0,32,%H0\";
- return \"mov 1,%H0\;sllx %H0,%2,%L0\;sub %L0,1,%L0\;srlx %L0,32,%H0\";
-}"
- [(set_attr "length" "4")])
+;(define_insn ""
+; [(set (match_operand:DI 0 "register_operand" "=h")
+; (plus:DI (ashift:DI (const_int 1)
+; (match_operand:SI 1 "arith_operand" "rI"))
+; (const_int -1)))]
+; "0 && TARGET_V8PLUS"
+; "*
+;{
+; if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == REGNO (operands[0]))
+; return \"mov\\t1, %L0\;sllx\\t%L0, %1, %L0\;sub\\t%L0, 1, %L0\;srlx\\t%L0, 32, %H0\";
+; return \"mov\\t1, %H0\;sllx\\t%H0, %1, %L0\;sub\\t%L0, 1, %L0\;srlx\\t%L0, 32, %H0\";
+;}"
+; [(set_attr "type" "multi")
+; (set_attr "length" "4")])
(define_insn "*cmp_cc_ashift_1"
[(set (reg:CC_NOOV 100)
(compare:CC_NOOV (ashift:SI (match_operand:SI 0 "register_operand" "r")
(const_int 1))
(const_int 0)))]
- "! TARGET_LIVE_G0"
+ ""
"addcc\\t%0, %0, %%g0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "*cmp_cc_set_ashift_1"
[(set (reg:CC_NOOV 100)
@@ -7058,8 +7936,7 @@
(ashift:SI (match_dup 1) (const_int 1)))]
""
"addcc\\t%1, %1, %0"
- [(set_attr "type" "compare")
- (set_attr "length" "1")])
+ [(set_attr "type" "compare")])
(define_insn "ashrsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -7074,8 +7951,7 @@
return \"sra\\t%1, %2, %0\";
}"
- [(set_attr "type" "shift")
- (set_attr "length" "1")])
+ [(set_attr "type" "shift")])
(define_insn "*ashrsi3_extend"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -7083,8 +7959,7 @@
(match_operand:SI 2 "arith_operand" "r"))))]
"TARGET_ARCH64"
"sra\\t%1, %2, %0"
- [(set_attr "type" "shift")
- (set_attr "length" "1")])
+ [(set_attr "type" "shift")])
;; This handles the case as above, but with constant shift instead of
;; register. Combiner "simplifies" it for us a little bit though.
@@ -7106,8 +7981,7 @@
return \"sra\\t%1, %2, %0\";
}"
- [(set_attr "type" "shift")
- (set_attr "length" "1")])
+ [(set_attr "type" "shift")])
(define_expand "ashrdi3"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -7138,8 +8012,7 @@
return \"srax\\t%1, %2, %0\";
}"
- [(set_attr "type" "shift")
- (set_attr "length" "1")])
+ [(set_attr "type" "shift")])
;; XXX
(define_insn "ashrdi3_v8plus"
@@ -7149,7 +8022,8 @@
(clobber (match_scratch:SI 3 "=X,X,&h"))]
"TARGET_V8PLUS"
"*return sparc_v8plus_shift (operands, insn, \"srax\");"
- [(set_attr "length" "5,5,6")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "5,5,6")])
(define_insn "lshrsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -7164,8 +8038,7 @@
return \"srl\\t%1, %2, %0\";
}"
- [(set_attr "type" "shift")
- (set_attr "length" "1")])
+ [(set_attr "type" "shift")])
;; This handles the case where
;; (zero_extend:DI (lshiftrt:SI (match_operand:SI) (match_operand:SI))),
@@ -7179,14 +8052,11 @@
&& ((GET_CODE (operands[3]) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (operands[3]) == 0
&& CONST_DOUBLE_LOW (operands[3]) == 0xffffffff)
-#if HOST_BITS_PER_WIDE_INT >= 64
- || (GET_CODE (operands[3]) == CONST_INT
- && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) == 0xffffffff)
-#endif
- )"
+ || (HOST_BITS_PER_WIDE_INT >= 64
+ && GET_CODE (operands[3]) == CONST_INT
+ && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) == 0xffffffff))"
"srl\\t%1, %2, %0"
- [(set_attr "type" "shift")
- (set_attr "length" "1")])
+ [(set_attr "type" "shift")])
;; This handles the case where
;; (lshiftrt:DI (zero_extend:DI (match_operand:SI)) (const_int >=0 < 32))
@@ -7208,8 +8078,7 @@
return \"srl\\t%1, %2, %0\";
}"
- [(set_attr "type" "shift")
- (set_attr "length" "1")])
+ [(set_attr "type" "shift")])
(define_expand "lshrdi3"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -7240,8 +8109,7 @@
return \"srlx\\t%1, %2, %0\";
}"
- [(set_attr "type" "shift")
- (set_attr "length" "1")])
+ [(set_attr "type" "shift")])
;; XXX
(define_insn "lshrdi3_v8plus"
@@ -7251,7 +8119,82 @@
(clobber (match_scratch:SI 3 "=X,X,&h"))]
"TARGET_V8PLUS"
"*return sparc_v8plus_shift (operands, insn, \"srlx\");"
- [(set_attr "length" "5,5,6")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "5,5,6")])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
+ (const_int 32)) 4)
+ (match_operand:SI 2 "small_int_or_double" "n")))]
+ "TARGET_ARCH64
+ && ((GET_CODE (operands[2]) == CONST_INT
+ && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
+ || (GET_CODE (operands[2]) == CONST_DOUBLE
+ && !CONST_DOUBLE_HIGH (operands[2])
+ && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
+ "*
+{
+ operands[2] = GEN_INT (INTVAL (operands[2]) + 32);
+
+ return \"srax\\t%1, %2, %0\";
+}"
+ [(set_attr "type" "shift")])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lshiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
+ (const_int 32)) 4)
+ (match_operand:SI 2 "small_int_or_double" "n")))]
+ "TARGET_ARCH64
+ && ((GET_CODE (operands[2]) == CONST_INT
+ && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
+ || (GET_CODE (operands[2]) == CONST_DOUBLE
+ && !CONST_DOUBLE_HIGH (operands[2])
+ && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
+ "*
+{
+ operands[2] = GEN_INT (INTVAL (operands[2]) + 32);
+
+ return \"srlx\\t%1, %2, %0\";
+}"
+ [(set_attr "type" "shift")])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:SI 2 "small_int_or_double" "n")) 4)
+ (match_operand:SI 3 "small_int_or_double" "n")))]
+ "TARGET_ARCH64
+ && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
+ && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 32
+ && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) < 32
+ && (unsigned HOST_WIDE_INT) (INTVAL (operands[2]) + INTVAL (operands[3])) < 64"
+ "*
+{
+ operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]));
+
+ return \"srax\\t%1, %2, %0\";
+}"
+ [(set_attr "type" "shift")])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lshiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:SI 2 "small_int_or_double" "n")) 4)
+ (match_operand:SI 3 "small_int_or_double" "n")))]
+ "TARGET_ARCH64
+ && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
+ && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 32
+ && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) < 32
+ && (unsigned HOST_WIDE_INT) (INTVAL (operands[2]) + INTVAL (operands[3])) < 64"
+ "*
+{
+ operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]));
+
+ return \"srlx\\t%1, %2, %0\";
+}"
+ [(set_attr "type" "shift")])
;; Unconditional and other jump instructions
;; On the Sparc, by setting the annul bit on an unconditional branch, the
@@ -7270,8 +8213,8 @@
instead. */
if (! TARGET_V9 && flag_delayed_branch
- && (insn_addresses[INSN_UID (operands[0])]
- == insn_addresses[INSN_UID (insn)]))
+ && (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%(\";
@@ -7305,14 +8248,14 @@
(define_insn "*tablejump_sp32"
[(set (pc) (match_operand:SI 0 "address_operand" "p"))
(use (label_ref (match_operand 1 "" "")))]
- "! TARGET_PTR64"
+ "! TARGET_ARCH64"
"jmp\\t%a0%#"
[(set_attr "type" "uncond_branch")])
(define_insn "*tablejump_sp64"
[(set (pc) (match_operand:DI 0 "address_operand" "p"))
(use (label_ref (match_operand 1 "" "")))]
- "TARGET_PTR64"
+ "TARGET_ARCH64"
"jmp\\t%a0%#"
[(set_attr "type" "uncond_branch")])
@@ -7352,21 +8295,19 @@
if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
emit_jump_insn
- (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (3,
- gen_rtx_SET (VOIDmode, pc_rtx,
- XEXP (operands[0], 0)),
- operands[3],
- gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_REG (Pmode, 15)))));
+ (gen_rtx_PARALLEL
+ (VOIDmode,
+ gen_rtvec (3,
+ gen_rtx_SET (VOIDmode, pc_rtx, XEXP (operands[0], 0)),
+ operands[3],
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
else
emit_jump_insn
- (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2,
- gen_rtx_SET (VOIDmode, pc_rtx,
- XEXP (operands[0], 0)),
- gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_REG (Pmode, 15)))));
+ (gen_rtx_PARALLEL
+ (VOIDmode,
+ gen_rtvec (2,
+ gen_rtx_SET (VOIDmode, pc_rtx, XEXP (operands[0], 0)),
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
goto finish_call;
}
@@ -7386,17 +8327,17 @@
if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
emit_call_insn
- (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (3, gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx),
- operands[3],
- gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_REG (Pmode, 15)))));
+ (gen_rtx_PARALLEL
+ (VOIDmode,
+ gen_rtvec (3, gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx),
+ operands[3],
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
else
emit_call_insn
- (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx),
- gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_REG (Pmode, 15)))));
+ (gen_rtx_PARALLEL
+ (VOIDmode,
+ gen_rtvec (2, gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx),
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
finish_call:
#if 0
@@ -7420,7 +8361,7 @@
(match_operand 1 "" ""))
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
- "! TARGET_PTR64"
+ "! TARGET_ARCH64"
"call\\t%a0, %1%#"
[(set_attr "type" "call")])
@@ -7429,25 +8370,25 @@
(match_operand 1 "" ""))
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
- "! TARGET_PTR64"
+ "! TARGET_ARCH64"
"call\\t%a0, %1%#"
[(set_attr "type" "call")])
(define_insn "*call_address_sp64"
- [(call (mem:SI (match_operand:DI 0 "address_operand" "p"))
+ [(call (mem:DI (match_operand:DI 0 "address_operand" "p"))
(match_operand 1 "" ""))
(clobber (reg:DI 15))]
;;- Do not use operand 1 for most machines.
- "TARGET_PTR64"
+ "TARGET_ARCH64"
"call\\t%a0, %1%#"
[(set_attr "type" "call")])
(define_insn "*call_symbolic_sp64"
- [(call (mem:SI (match_operand:DI 0 "symbolic_operand" "s"))
+ [(call (mem:DI (match_operand:DI 0 "symbolic_operand" "s"))
(match_operand 1 "" ""))
(clobber (reg:DI 15))]
;;- Do not use operand 1 for most machines.
- "TARGET_PTR64"
+ "TARGET_ARCH64"
"call\\t%a0, %1%#"
[(set_attr "type" "call")])
@@ -7461,7 +8402,8 @@
;;- Do not use operand 1 for most machines.
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
"call\\t%a0, %1\\n\\tnop\\n\\tunimp\\t%2"
- [(set_attr "type" "call_no_delay_slot")])
+ [(set_attr "type" "call_no_delay_slot")
+ (set_attr "length" "2")])
;; This is a call that wants a structure value.
;; There is no such critter for v9 (??? we may need one anyway).
@@ -7473,7 +8415,8 @@
;;- Do not use operand 1 for most machines.
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
"call\\t%a0, %1\\n\\tnop\\n\\tunimp\\t%2"
- [(set_attr "type" "call_no_delay_slot")])
+ [(set_attr "type" "call_no_delay_slot")
+ (set_attr "length" "2")])
;; This is a call that may want a structure value. This is used for
;; untyped_calls.
@@ -7485,7 +8428,8 @@
;;- Do not use operand 1 for most machines.
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
"call\\t%a0, %1\\n\\tnop\\n\\tnop"
- [(set_attr "type" "call_no_delay_slot")])
+ [(set_attr "type" "call_no_delay_slot")
+ (set_attr "length" "2")])
;; This is a call that wants a structure value.
(define_insn "*call_symbolic_untyped_struct_value_sp32"
@@ -7496,13 +8440,14 @@
;;- Do not use operand 1 for most machines.
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
"call\\t%a0, %1\\n\\tnop\\n\\tnop"
- [(set_attr "type" "call_no_delay_slot")])
+ [(set_attr "type" "call_no_delay_slot")
+ (set_attr "length" "2")])
(define_expand "call_value"
;; Note that this expression is not used for generating RTL.
;; All the RTL is generated explicitly below.
[(set (match_operand 0 "register_operand" "=rf")
- (call (match_operand:SI 1 "" "")
+ (call (match_operand 1 "" "")
(match_operand 4 "" "")))]
;; operand 2 is stack_size_rtx
;; operand 3 is next_arg_register
@@ -7528,7 +8473,7 @@
vec = gen_rtvec (2,
gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx)),
+ gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx)),
gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)));
emit_call_insn (gen_rtx_PARALLEL (VOIDmode, vec));
@@ -7542,7 +8487,7 @@
(match_operand 2 "" "")))
(clobber (reg:SI 15))]
;;- Do not use operand 2 for most machines.
- "! TARGET_PTR64"
+ "! TARGET_ARCH64"
"call\\t%a1, %2%#"
[(set_attr "type" "call")])
@@ -7552,27 +8497,27 @@
(match_operand 2 "" "")))
(clobber (reg:SI 15))]
;;- Do not use operand 2 for most machines.
- "! TARGET_PTR64"
+ "! TARGET_ARCH64"
"call\\t%a1, %2%#"
[(set_attr "type" "call")])
(define_insn "*call_value_address_sp64"
[(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:DI 1 "address_operand" "p"))
+ (call (mem:DI (match_operand:DI 1 "address_operand" "p"))
(match_operand 2 "" "")))
(clobber (reg:DI 15))]
;;- Do not use operand 2 for most machines.
- "TARGET_PTR64"
+ "TARGET_ARCH64"
"call\\t%a1, %2%#"
[(set_attr "type" "call")])
(define_insn "*call_value_symbolic_sp64"
[(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:DI 1 "symbolic_operand" "s"))
+ (call (mem:DI (match_operand:DI 1 "symbolic_operand" "s"))
(match_operand 2 "" "")))
(clobber (reg:DI 15))]
;;- Do not use operand 2 for most machines.
- "TARGET_PTR64"
+ "TARGET_ARCH64"
"call\\t%a1, %2%#"
[(set_attr "type" "call")])
@@ -7588,7 +8533,7 @@
/* Pass constm1 to indicate that it may expect a structure value, but
we don't know what size it is. */
- emit_call_insn (gen_call (operands[0], const0_rtx, NULL, constm1_rtx));
+ emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, constm1_rtx));
for (i = 0; i < XVECLEN (operands[2], 0); i++)
{
@@ -7605,6 +8550,59 @@
DONE;
}")
+;;- tail calls
+(define_expand "sibcall"
+ [(parallel [(call (match_operand 0 "call_operand" "") (const_int 0))
+ (return)])]
+ ""
+ "")
+
+(define_insn "*sibcall_symbolic_sp32"
+ [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
+ (match_operand 1 "" ""))
+ (return)]
+ "! TARGET_ARCH64"
+ "* return output_sibcall(insn, operands[0]);"
+ [(set_attr "type" "sibcall")])
+
+(define_insn "*sibcall_symbolic_sp64"
+ [(call (mem:DI (match_operand:DI 0 "symbolic_operand" "s"))
+ (match_operand 1 "" ""))
+ (return)]
+ "TARGET_ARCH64"
+ "* return output_sibcall(insn, operands[0]);"
+ [(set_attr "type" "sibcall")])
+
+(define_expand "sibcall_value"
+ [(parallel [(set (match_operand 0 "register_operand" "=rf")
+ (call (match_operand 1 "" "") (const_int 0)))
+ (return)])]
+ ""
+ "")
+
+(define_insn "*sibcall_value_symbolic_sp32"
+ [(set (match_operand 0 "" "=rf")
+ (call (mem:SI (match_operand:SI 1 "symbolic_operand" "s"))
+ (match_operand 2 "" "")))
+ (return)]
+ "! TARGET_ARCH64"
+ "* return output_sibcall(insn, operands[1]);"
+ [(set_attr "type" "sibcall")])
+
+(define_insn "*sibcall_value_symbolic_sp64"
+ [(set (match_operand 0 "" "")
+ (call (mem:DI (match_operand:DI 1 "symbolic_operand" "s"))
+ (match_operand 2 "" "")))
+ (return)]
+ "TARGET_ARCH64"
+ "* return output_sibcall(insn, operands[1]);"
+ [(set_attr "type" "sibcall")])
+
+(define_expand "sibcall_epilogue"
+ [(const_int 0)]
+ ""
+ "DONE;")
+
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
;; all of memory. This blocks insns from being moved across this point.
@@ -7642,10 +8640,9 @@
}
/* Reload the function value registers. */
- emit_move_insn (valreg1, change_address (result, DImode, XEXP (result, 0)));
+ emit_move_insn (valreg1, adjust_address (result, DImode, 0));
emit_move_insn (valreg2,
- change_address (result, TARGET_ARCH64 ? TFmode : DFmode,
- plus_constant (XEXP (result, 0), 8)));
+ adjust_address (result, TARGET_ARCH64 ? TFmode : DFmode, 8));
/* Put USE insns before the return. */
emit_insn (gen_rtx_USE (VOIDmode, valreg1));
@@ -7664,8 +8661,9 @@
[(unspec:SI [(match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "register_operand" "r")] 1)]
"! TARGET_ARCH64"
- "cmp %1,0\;be,a .+8\;add %0,4,%0"
- [(set_attr "type" "multi")])
+ "cmp\\t%1, 0\;be,a\\t.+8\;add\\t%0, 4, %0"
+ [(set_attr "type" "multi")
+ (set_attr "length" "3")])
(define_insn "return"
[(return)
@@ -7685,9 +8683,7 @@
(define_insn "nop"
[(const_int 0)]
""
- "nop"
- [(set_attr "type" "ialu")
- (set_attr "length" "1")])
+ "nop")
(define_expand "indirect_jump"
[(set (pc) (match_operand 0 "address_operand" "p"))]
@@ -7696,13 +8692,13 @@
(define_insn "*branch_sp32"
[(set (pc) (match_operand:SI 0 "address_operand" "p"))]
- "! TARGET_PTR64"
+ "! TARGET_ARCH64"
"jmp\\t%a0%#"
[(set_attr "type" "uncond_branch")])
(define_insn "*branch_sp64"
[(set (pc) (match_operand:DI 0 "address_operand" "p"))]
- "TARGET_PTR64"
+ "TARGET_ARCH64"
"jmp\\t%a0%#"
[(set_attr "type" "uncond_branch")])
@@ -7718,9 +8714,9 @@
#if 0
rtx chain = operands[0];
#endif
- rtx fp = operands[1];
+ rtx lab = operands[1];
rtx stack = operands[2];
- rtx lab = operands[3];
+ rtx fp = operands[3];
rtx labreg;
/* Trap instruction to flush all the register windows. */
@@ -7753,8 +8749,9 @@
if (TARGET_V9 && GET_CODE (chain) == CONST_INT
&& ! (INTVAL (chain) & ~(HOST_WIDE_INT)0xffffffff))
{
- emit_insn (gen_goto_handler_and_restore_v9 (labreg, static_chain_rtx,
- chain));
+ emit_jump_insn (gen_goto_handler_and_restore_v9 (labreg,
+ static_chain_rtx,
+ chain));
emit_barrier ();
DONE;
}
@@ -7763,7 +8760,7 @@
#endif
emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx));
- emit_insn (gen_goto_handler_and_restore (labreg));
+ emit_jump_insn (gen_goto_handler_and_restore (labreg));
emit_barrier ();
DONE;
}")
@@ -7773,14 +8770,13 @@
[(unspec_volatile [(const_int 0)] 1)]
""
"* return TARGET_V9 ? \"flushw\" : \"ta\\t3\";"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
(define_insn "goto_handler_and_restore"
[(unspec_volatile [(match_operand 0 "register_operand" "=r")] 2)]
- ""
+ "GET_MODE (operands[0]) == Pmode"
"jmp\\t%0+0\\n\\trestore"
- [(set_attr "type" "misc")
+ [(set_attr "type" "multi")
(set_attr "length" "2")])
;;(define_insn "goto_handler_and_restore_v9"
@@ -7791,7 +8787,7 @@
;; "@
;; return\\t%0+0\\n\\tmov\\t%2, %Y1
;; sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1"
-;; [(set_attr "type" "misc")
+;; [(set_attr "type" "multi")
;; (set_attr "length" "2,3")])
;;
;;(define_insn "*goto_handler_and_restore_v9_sp64"
@@ -7802,9 +8798,38 @@
;; "@
;; return\\t%0+0\\n\\tmov\\t%2, %Y1
;; sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1"
-;; [(set_attr "type" "misc")
+;; [(set_attr "type" "multi")
;; (set_attr "length" "2,3")])
+;; 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
+(define_expand "builtin_setjmp_setup"
+ [(match_operand 0 "register_operand" "r")]
+ ""
+ "
+{
+ emit_insn (gen_do_builtin_setjmp_setup ());
+ DONE;
+}")
+
+;; ??? Should set length to zero when !current_function_calls_alloca,
+;; ??? but there is no easy way to get at that definition. It would
+;; ??? require including function.h into sparc-protos.h and that is
+;; ??? likely not a good idea. -DaveM
+(define_insn "do_builtin_setjmp_setup"
+ [(unspec_volatile [(const_int 0)] 5)]
+ ""
+ "*
+{
+ if (!current_function_calls_alloca)
+ return \"\";
+ if (TARGET_V9)
+ return \"flushw\";
+ return \"ta\\t3\";
+}"
+ [(set_attr "type" "misc")])
+
;; Pattern for use after a setjmp to store FP and the return register
;; into the stack area.
@@ -7836,12 +8861,23 @@
;; Special pattern for the FLUSH instruction.
+; We do SImode and DImode versions of this to quiet down genrecog's complaints
+; of the define_insn otherwise missing a mode. We make "flush", aka
+; gen_flush, the default one since sparc_initialize_trampoline uses
+; it on SImode mem values.
+
(define_insn "flush"
- [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 4)]
+ [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] 3)]
+ ""
+ "* return TARGET_V9 ? \"flush\\t%f0\" : \"iflush\\t%f0\";"
+ [(set_attr "type" "misc")])
+
+(define_insn "flushdi"
+ [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m")] 3)]
""
"* return TARGET_V9 ? \"flush\\t%f0\" : \"iflush\\t%f0\";"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
+
;; find first set.
@@ -7858,9 +8894,7 @@
"TARGET_SPARCLITE || TARGET_SPARCLET"
"*
{
- if (TARGET_LIVE_G0)
- output_asm_insn (\"and %%g0,0,%%g0\", operands);
- return \"sub %%g0,%1,%0\;and %0,%1,%0\;scan %0,0,%0\;mov 32,%2\;sub %2,%0,%0\;sra %0,31,%2\;and %2,31,%2\;add %2,%0,%0\";
+ return \"sub\\t%%g0, %1, %0\;and\\t%0, %1, %0\;scan\\t%0, 0, %0\;mov\\t32, %2\;sub\\t%2, %0, %0\;sra\\t%0, 31, %2\;and\\t%2, 31, %2\;add\\t%2, %0, %0\";
}"
[(set_attr "type" "multi")
(set_attr "length" "8")])
@@ -7876,10 +8910,11 @@
; (ffs:DI (match_operand:DI 1 "register_operand" "r")))
; (clobber (match_scratch:DI 2 "=&r"))]
; "TARGET_ARCH64"
-; "neg %1,%2\;xnor %1,%2,%2\;popc %2,%0\;movzr %1,0,%0"
+; "neg\\t%1, %2\;xnor\\t%1, %2, %2\;popc\\t%2, %0\;movzr\\t%1, 0, %0"
; [(set_attr "type" "multi")
; (set_attr "length" "4")])
+
;; Peepholes go at the end.
@@ -7887,144 +8922,159 @@
;; The conditions in which we do this are very restricted and are
;; explained in the code for {registers,memory}_ok_for_ldd functions.
-(define_peephole
+(define_peephole2
[(set (match_operand:SI 0 "memory_operand" "")
(const_int 0))
(set (match_operand:SI 1 "memory_operand" "")
(const_int 0))]
"TARGET_V9
- && ! MEM_VOLATILE_P (operands[0])
- && ! MEM_VOLATILE_P (operands[1])
- && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[1], 0))"
- "stx\\t%%g0, %0")
+ && mems_ok_for_ldd_peep (operands[0], operands[1], NULL_RTX)"
+ [(set (match_dup 0)
+ (const_int 0))]
+ "operands[0] = change_address (operands[0], DImode, NULL);")
-(define_peephole
+(define_peephole2
[(set (match_operand:SI 0 "memory_operand" "")
(const_int 0))
(set (match_operand:SI 1 "memory_operand" "")
(const_int 0))]
"TARGET_V9
- && ! MEM_VOLATILE_P (operands[0])
- && ! MEM_VOLATILE_P (operands[1])
- && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[0], 0))"
- "stx\\t%%g0, %1")
+ && mems_ok_for_ldd_peep (operands[1], operands[0], NULL_RTX)"
+ [(set (match_dup 1)
+ (const_int 0))]
+ "operands[1] = change_address (operands[1], DImode, NULL);")
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=rf")
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "memory_operand" ""))
- (set (match_operand:SI 2 "register_operand" "=rf")
+ (set (match_operand:SI 2 "register_operand" "")
(match_operand:SI 3 "memory_operand" ""))]
"registers_ok_for_ldd_peep (operands[0], operands[2])
- && ! MEM_VOLATILE_P (operands[1])
- && ! MEM_VOLATILE_P (operands[3])
- && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))"
- "ldd\\t%1, %0")
+ && mems_ok_for_ldd_peep (operands[1], operands[3], operands[0])"
+ [(set (match_dup 0)
+ (match_dup 1))]
+ "operands[1] = change_address (operands[1], DImode, NULL);
+ operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));")
-(define_peephole
+(define_peephole2
[(set (match_operand:SI 0 "memory_operand" "")
- (match_operand:SI 1 "register_operand" "rf"))
+ (match_operand:SI 1 "register_operand" ""))
(set (match_operand:SI 2 "memory_operand" "")
- (match_operand:SI 3 "register_operand" "rf"))]
+ (match_operand:SI 3 "register_operand" ""))]
"registers_ok_for_ldd_peep (operands[1], operands[3])
- && ! MEM_VOLATILE_P (operands[0])
- && ! MEM_VOLATILE_P (operands[2])
- && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
- "std\\t%1, %0")
-
-(define_peephole
- [(set (match_operand:SF 0 "register_operand" "=fr")
+ && mems_ok_for_ldd_peep (operands[0], operands[2], NULL_RTX)"
+ [(set (match_dup 0)
+ (match_dup 1))]
+ "operands[0] = change_address (operands[0], DImode, NULL);
+ operands[1] = gen_rtx_REG (DImode, REGNO (operands[1]));")
+
+(define_peephole2
+ [(set (match_operand:SF 0 "register_operand" "")
(match_operand:SF 1 "memory_operand" ""))
- (set (match_operand:SF 2 "register_operand" "=fr")
+ (set (match_operand:SF 2 "register_operand" "")
(match_operand:SF 3 "memory_operand" ""))]
"registers_ok_for_ldd_peep (operands[0], operands[2])
- && ! MEM_VOLATILE_P (operands[1])
- && ! MEM_VOLATILE_P (operands[3])
- && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))"
- "ldd\\t%1, %0")
+ && mems_ok_for_ldd_peep (operands[1], operands[3], operands[0])"
+ [(set (match_dup 0)
+ (match_dup 1))]
+ "operands[1] = change_address (operands[1], DFmode, NULL);
+ operands[0] = gen_rtx_REG (DFmode, REGNO (operands[0]));")
-(define_peephole
+(define_peephole2
[(set (match_operand:SF 0 "memory_operand" "")
- (match_operand:SF 1 "register_operand" "fr"))
+ (match_operand:SF 1 "register_operand" ""))
(set (match_operand:SF 2 "memory_operand" "")
- (match_operand:SF 3 "register_operand" "fr"))]
+ (match_operand:SF 3 "register_operand" ""))]
"registers_ok_for_ldd_peep (operands[1], operands[3])
- && ! MEM_VOLATILE_P (operands[0])
- && ! MEM_VOLATILE_P (operands[2])
- && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
- "std\\t%1, %0")
+ && mems_ok_for_ldd_peep (operands[0], operands[2], NULL_RTX)"
+ [(set (match_dup 0)
+ (match_dup 1))]
+ "operands[0] = change_address (operands[0], DFmode, NULL);
+ operands[1] = gen_rtx_REG (DFmode, REGNO (operands[1]));")
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=rf")
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "memory_operand" ""))
- (set (match_operand:SI 2 "register_operand" "=rf")
+ (set (match_operand:SI 2 "register_operand" "")
(match_operand:SI 3 "memory_operand" ""))]
"registers_ok_for_ldd_peep (operands[2], operands[0])
- && ! MEM_VOLATILE_P (operands[3])
- && ! MEM_VOLATILE_P (operands[1])
- && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
- "ldd\\t%3, %2")
+ && mems_ok_for_ldd_peep (operands[3], operands[1], operands[2])"
+ [(set (match_dup 2)
+ (match_dup 3))]
+ "operands[3] = change_address (operands[3], DImode, NULL);
+ operands[2] = gen_rtx_REG (DImode, REGNO (operands[2]));")
-(define_peephole
+(define_peephole2
[(set (match_operand:SI 0 "memory_operand" "")
- (match_operand:SI 1 "register_operand" "rf"))
+ (match_operand:SI 1 "register_operand" ""))
(set (match_operand:SI 2 "memory_operand" "")
- (match_operand:SI 3 "register_operand" "rf"))]
+ (match_operand:SI 3 "register_operand" ""))]
"registers_ok_for_ldd_peep (operands[3], operands[1])
- && ! MEM_VOLATILE_P (operands[2])
- && ! MEM_VOLATILE_P (operands[0])
- && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))"
- "std\\t%3, %2")
+ && mems_ok_for_ldd_peep (operands[2], operands[0], NULL_RTX)"
+ [(set (match_dup 2)
+ (match_dup 3))]
+ "operands[2] = change_address (operands[2], DImode, NULL);
+ operands[3] = gen_rtx_REG (DImode, REGNO (operands[3]));
+ ")
-(define_peephole
- [(set (match_operand:SF 0 "register_operand" "=fr")
+(define_peephole2
+ [(set (match_operand:SF 0 "register_operand" "")
(match_operand:SF 1 "memory_operand" ""))
- (set (match_operand:SF 2 "register_operand" "=fr")
+ (set (match_operand:SF 2 "register_operand" "")
(match_operand:SF 3 "memory_operand" ""))]
"registers_ok_for_ldd_peep (operands[2], operands[0])
- && ! MEM_VOLATILE_P (operands[3])
- && ! MEM_VOLATILE_P (operands[1])
- && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
- "ldd\\t%3, %2")
+ && mems_ok_for_ldd_peep (operands[3], operands[1], operands[2])"
+ [(set (match_dup 2)
+ (match_dup 3))]
+ "operands[3] = change_address (operands[3], DFmode, NULL);
+ operands[2] = gen_rtx_REG (DFmode, REGNO (operands[2]));")
-(define_peephole
+(define_peephole2
[(set (match_operand:SF 0 "memory_operand" "")
- (match_operand:SF 1 "register_operand" "fr"))
+ (match_operand:SF 1 "register_operand" ""))
(set (match_operand:SF 2 "memory_operand" "")
- (match_operand:SF 3 "register_operand" "fr"))]
+ (match_operand:SF 3 "register_operand" ""))]
"registers_ok_for_ldd_peep (operands[3], operands[1])
- && ! MEM_VOLATILE_P (operands[2])
- && ! MEM_VOLATILE_P (operands[0])
- && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))"
- "std\\t%3, %2")
+ && mems_ok_for_ldd_peep (operands[2], operands[0], NULL_RTX)"
+ [(set (match_dup 2)
+ (match_dup 3))]
+ "operands[2] = change_address (operands[2], DFmode, NULL);
+ operands[3] = gen_rtx_REG (DFmode, REGNO (operands[3]));")
;; Optimize the case of following a reg-reg move with a test
;; of reg just moved. Don't allow floating point regs for operand 0 or 1.
;; This can result from a float to fix conversion.
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operand:SI 1 "register_operand" "r"))
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "register_operand" ""))
(set (reg:CC 100)
- (compare:CC (match_operand:SI 2 "register_operand" "r")
+ (compare:CC (match_operand:SI 2 "register_operand" "")
(const_int 0)))]
"(rtx_equal_p (operands[2], operands[0])
|| rtx_equal_p (operands[2], operands[1]))
- && ! FP_REG_P (operands[0])
- && ! FP_REG_P (operands[1])"
- "orcc\\t%1, 0, %0")
+ && ! SPARC_FP_REG_P (REGNO (operands[0]))
+ && ! SPARC_FP_REG_P (REGNO (operands[1]))"
+ [(parallel [(set (match_dup 0) (match_dup 1))
+ (set (reg:CC 100)
+ (compare:CC (match_dup 1) (const_int 0)))])]
+ "")
-(define_peephole
- [(set (match_operand:DI 0 "register_operand" "=r")
- (match_operand:DI 1 "register_operand" "r"))
+(define_peephole2
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "register_operand" ""))
(set (reg:CCX 100)
- (compare:CCX (match_operand:DI 2 "register_operand" "r")
+ (compare:CCX (match_operand:DI 2 "register_operand" "")
(const_int 0)))]
"TARGET_ARCH64
&& (rtx_equal_p (operands[2], operands[0])
|| rtx_equal_p (operands[2], operands[1]))
- && ! FP_REG_P (operands[0])
- && ! FP_REG_P (operands[1])"
- "orcc\\t%1, 0, %0")
+ && ! SPARC_FP_REG_P (REGNO (operands[0]))
+ && ! SPARC_FP_REG_P (REGNO (operands[1]))"
+ [(parallel [(set (match_dup 0) (match_dup 1))
+ (set (reg:CCX 100)
+ (compare:CC (match_dup 1) (const_int 0)))])]
+ "")
;; Return peepholes. First the "normal" ones.
;; These are necessary to catch insns ending up in the epilogue delay list.
@@ -8033,7 +9083,7 @@
[(set (match_operand:QI 0 "restore_operand" "")
(match_operand:QI 1 "arith_operand" "rI"))
(return)]
- "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
+ "! TARGET_EPILOGUE"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
@@ -8044,13 +9094,14 @@
else
return \"ret\\n\\trestore %%g0, %1, %Y0\";
}"
- [(set_attr "type" "multi")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
(define_insn "*return_hi"
[(set (match_operand:HI 0 "restore_operand" "")
(match_operand:HI 1 "arith_operand" "rI"))
(return)]
- "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
+ "! TARGET_EPILOGUE"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
@@ -8061,13 +9112,14 @@
else
return \"ret\;restore %%g0, %1, %Y0\";
}"
- [(set_attr "type" "multi")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
(define_insn "*return_si"
[(set (match_operand:SI 0 "restore_operand" "")
(match_operand:SI 1 "arith_operand" "rI"))
(return)]
- "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
+ "! TARGET_EPILOGUE"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
@@ -8078,17 +9130,18 @@
else
return \"ret\;restore %%g0, %1, %Y0\";
}"
- [(set_attr "type" "multi")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
;; The following pattern is only generated by delayed-branch scheduling,
;; when the insn winds up in the epilogue. This can happen not only when
;; ! TARGET_FPU because we move complex types around by parts using
;; SF mode SUBREGs.
(define_insn "*return_sf_no_fpu"
- [(set (match_operand:SF 0 "restore_operand" "r")
+ [(set (match_operand:SF 0 "restore_operand" "=r")
(match_operand:SF 1 "register_operand" "r"))
(return)]
- "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
+ "! TARGET_EPILOGUE"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
@@ -8098,14 +9151,30 @@
else
return \"ret\;restore %%g0, %1, %Y0\";
}"
- [(set_attr "type" "multi")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
+
+(define_insn "*return_df_no_fpu"
+ [(set (match_operand:DF 0 "restore_operand" "=r")
+ (match_operand:DF 1 "register_operand" "r"))
+ (return)]
+ "! TARGET_EPILOGUE && TARGET_ARCH64"
+ "*
+{
+ if (IN_OR_GLOBAL_P (operands[1]))
+ return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
+ else
+ return \"ret\;restore %%g0, %1, %Y0\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
(define_insn "*return_addsi"
[(set (match_operand:SI 0 "restore_operand" "")
(plus:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "rI")))
(return)]
- "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
+ "! TARGET_EPILOGUE"
"*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
@@ -8118,7 +9187,27 @@
else
return \"ret\;restore %r1, %2, %Y0\";
}"
- [(set_attr "type" "multi")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
+
+(define_insn "*return_losum_si"
+ [(set (match_operand:SI 0 "restore_operand" "")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "immediate_operand" "in")))
+ (return)]
+ "! TARGET_EPILOGUE && ! TARGET_CM_MEDMID"
+ "*
+{
+ if (! TARGET_ARCH64 && current_function_returns_struct)
+ return \"jmp\\t%%i7+12\\n\\trestore %r1, %%lo(%a2), %Y0\";
+ /* If operands are global or in registers, can use return */
+ else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
+ return \"return\\t%%i7+8\\n\\tor\\t%Y1, %%lo(%a2), %Y0\";
+ else
+ return \"ret\;restore %r1, %%lo(%a2), %Y0\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
(define_insn "*return_di"
[(set (match_operand:DI 0 "restore_operand" "")
@@ -8126,7 +9215,8 @@
(return)]
"TARGET_ARCH64 && ! TARGET_EPILOGUE"
"ret\;restore %%g0, %1, %Y0"
- [(set_attr "type" "multi")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
(define_insn "*return_adddi"
[(set (match_operand:DI 0 "restore_operand" "")
@@ -8135,7 +9225,18 @@
(return)]
"TARGET_ARCH64 && ! TARGET_EPILOGUE"
"ret\;restore %r1, %2, %Y0"
- [(set_attr "type" "multi")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
+
+(define_insn "*return_losum_di"
+ [(set (match_operand:DI 0 "restore_operand" "")
+ (lo_sum:DI (match_operand:DI 1 "arith_operand" "%r")
+ (match_operand:DI 2 "immediate_operand" "in")))
+ (return)]
+ "TARGET_ARCH64 && ! TARGET_EPILOGUE && ! TARGET_CM_MEDMID"
+ "ret\;restore %r1, %%lo(%a2), %Y0"
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
;; The following pattern is only generated by delayed-branch scheduling,
;; when the insn winds up in the epilogue.
@@ -8145,7 +9246,8 @@
(return)]
"! TARGET_EPILOGUE"
"ret\;fmovs\\t%0, %%f0"
- [(set_attr "type" "multi")])
+ [(set_attr "type" "multi")
+ (set_attr "length" "2")])
;; Now peepholes to do a call followed by a jump.
@@ -8156,8 +9258,7 @@
(clobber (reg:SI 15))])
(set (pc) (label_ref (match_operand 3 "" "")))]
"short_branch (INSN_UID (insn), INSN_UID (operands[3]))
- && in_same_eh_region (insn, operands[3])
- && in_same_eh_region (insn, ins1)"
+ && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))"
"call\\t%a1, %2\\n\\tadd\\t%%o7, (%l3-.-4), %%o7")
(define_peephole
@@ -8166,8 +9267,7 @@
(clobber (reg:SI 15))])
(set (pc) (label_ref (match_operand 2 "" "")))]
"short_branch (INSN_UID (insn), INSN_UID (operands[2]))
- && in_same_eh_region (insn, operands[2])
- && in_same_eh_region (insn, ins1)"
+ && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))"
"call\\t%a0, %1\\n\\tadd\\t%%o7, (%l2-.-4), %%o7")
(define_peephole
@@ -8178,8 +9278,7 @@
(set (pc) (label_ref (match_operand 3 "" "")))]
"TARGET_ARCH64
&& short_branch (INSN_UID (insn), INSN_UID (operands[3]))
- && in_same_eh_region (insn, operands[3])
- && in_same_eh_region (insn, ins1)"
+ && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))"
"call\\t%a1, %2\\n\\tadd\\t%%o7, (%l3-.-4), %%o7")
(define_peephole
@@ -8189,27 +9288,76 @@
(set (pc) (label_ref (match_operand 2 "" "")))]
"TARGET_ARCH64
&& short_branch (INSN_UID (insn), INSN_UID (operands[2]))
- && in_same_eh_region (insn, operands[2])
- && in_same_eh_region (insn, ins1)"
+ && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))"
"call\\t%a0, %1\\n\\tadd\\t%%o7, (%l2-.-4), %%o7")
-;; After a nonlocal goto, we need to restore the PIC register, but only
-;; if we need it. So do nothing much here, but we'll check for this in
-;; finalize_pic.
+(define_insn "prefetch"
+ [(prefetch (match_operand:DI 0 "address_operand" "p")
+ (match_operand:DI 1 "const_int_operand" "n")
+ (match_operand:DI 2 "const_int_operand" "n"))]
+ "TARGET_V9"
+{
+ static const char * const prefetch_instr[2][4] = {
+ {
+ "prefetch\\t[%a0], 1", /* no locality: prefetch for one read */
+ "prefetch\\t[%a0], 0", /* medium locality: prefetch for several reads */
+ "prefetch\\t[%a0], 0", /* medium locality: prefetch for several reads */
+ "prefetch\\t[%a0], 4", /* high locality: prefetch page */
+ },
+ {
+ "prefetch\\t[%a0], 3", /* no locality: prefetch for one write */
+ "prefetch\\t[%a0], 2", /* medium locality: prefetch for several writes */
+ "prefetch\\t[%a0], 2", /* medium locality: prefetch for several writes */
+ "prefetch\\t[%a0], 4", /* high locality: prefetch page */
+ }
+ };
+ int read_or_write = INTVAL (operands[1]);
+ int locality = INTVAL (operands[2]);
+
+ if (read_or_write != 0 && read_or_write != 1)
+ abort ();
+ if (locality < 0 || locality > 3)
+ abort ();
+ return prefetch_instr [read_or_write][locality];
+}
+ [(set_attr "type" "load")])
+
+(define_expand "prologue"
+ [(const_int 1)]
+ "flag_pic && current_function_uses_pic_offset_table"
+ "
+{
+ load_pic_register ();
+ DONE;
+}")
-;; Make sure this unspec_volatile number agrees with finalize_pic.
-(define_insn "nonlocal_goto_receiver"
- [(unspec_volatile [(const_int 0)] 5)]
- "flag_pic"
- ""
- [(set_attr "length" "0")])
+;; We need to reload %l7 for -mflat -fpic,
+;; otherwise %l7 should be preserved simply
+;; by loading the function's register window
+(define_expand "exception_receiver"
+ [(const_int 0)]
+ "TARGET_FLAT && flag_pic"
+ "
+{
+ load_pic_register ();
+ DONE;
+}")
+
+;; Likewise
+(define_expand "builtin_setjmp_receiver"
+ [(label_ref (match_operand 0 "" ""))]
+ "TARGET_FLAT && flag_pic"
+ "
+{
+ load_pic_register ();
+ DONE;
+}")
(define_insn "trap"
[(trap_if (const_int 1) (const_int 5))]
""
"ta\\t5"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
(define_expand "conditional_trap"
[(trap_if (match_operator 0 "noov_compare_op"
@@ -8225,13 +9373,11 @@
(match_operand:SI 1 "arith_operand" "rM"))]
""
"t%C0\\t%1"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
(define_insn ""
[(trap_if (match_operator 0 "noov_compare_op" [(reg:CCX 100) (const_int 0)])
(match_operand:SI 1 "arith_operand" "rM"))]
"TARGET_V9"
"t%C0\\t%%xcc, %1"
- [(set_attr "type" "misc")
- (set_attr "length" "1")])
+ [(set_attr "type" "misc")])
diff --git a/contrib/gcc/config/sparc/splet.h b/contrib/gcc/config/sparc/splet.h
index d924e70..d2ef4fb 100644
--- a/contrib/gcc/config/sparc/splet.h
+++ b/contrib/gcc/config/sparc/splet.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for SPARClet.
- Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc.
Contributed by Doug Evans (dje@cygnus.com).
This file is part of GNU CC.
@@ -19,22 +19,15 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "sparc/aout.h"
-
-/* -mbroken-saverestore is not included here because the long term
- default is -mno-broken-saverestore. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE)
-/* -mlive-g0 is only supported on the sparclet. */
+#define CPP_PREDEFINES "-Dsparc -Acpu=sparc -Amachine=sparc"
+
#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES \
-{"big-endian", -MASK_LITTLE_ENDIAN, "Generate code for big endian" }, \
-{"little-endian", MASK_LITTLE_ENDIAN, "Generate code for little endian" }, \
-{"live-g0", MASK_LIVE_G0, "Use g0 as a normal register" }, \
-{"no-live-g0", -MASK_LIVE_G0, "Register g0 is fixed with a zero value" }, \
-{"broken-saverestore", MASK_BROKEN_SAVERESTORE, "Enable save/restore bug workarounds" }, \
-{"no-broken-saverestore", -MASK_BROKEN_SAVERESTORE, "Disable save/restore bug workarouns" },
+#define SUBTARGET_SWITCHES \
+{"big-endian", -MASK_LITTLE_ENDIAN, N_("Generate code for big endian") }, \
+{"little-endian", MASK_LITTLE_ENDIAN, N_("Generate code for little endian") },
#undef ASM_SPEC
#define ASM_SPEC "%{mlittle-endian:-EL} %(asm_cpu)"
@@ -51,19 +44,3 @@ Boston, MA 02111-1307, USA. */
#define BYTES_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN)
#undef WORDS_BIG_ENDIAN
#define WORDS_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN)
-
-#undef SUBTARGET_OVERRIDE_OPTIONS
-#define SUBTARGET_OVERRIDE_OPTIONS \
- do { \
- if (TARGET_LIVE_G0) \
- { \
- warning ("Option '-mlive-g0' deprecated."); \
- target_flags &= ~MASK_LIVE_G0; \
- } \
- else if (TARGET_BROKEN_SAVERESTORE) \
- { \
- warning ("Option '-mbroken-saverestore' deprecated."); \
- target_flags &= ~MASK_BROKEN_SAVERESTORE; \
- } \
- } while (0)
-
diff --git a/contrib/gcc/config/sparc/sun4gas.h b/contrib/gcc/config/sparc/sun4gas.h
index 3cea956..7f4f7db 100644
--- a/contrib/gcc/config/sparc/sun4gas.h
+++ b/contrib/gcc/config/sparc/sun4gas.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for SunOS 4.x with gas
- Copyright (C) 1997 Free Software Foundation, Inc.
+ Copyright (C) 1997, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,10 +18,5 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* gas supports unaligned data. */
-#define UNALIGNED_DOUBLE_INT_ASM_OP ".uaxword"
-#define UNALIGNED_INT_ASM_OP ".uaword"
-#define UNALIGNED_SHORT_ASM_OP ".uahalf"
-
/* defaults.h will define DWARF2_UNWIND_INFO for us. */
#undef DWARF2_UNWIND_INFO
diff --git a/contrib/gcc/config/sparc/sun4o3.h b/contrib/gcc/config/sparc/sun4o3.h
index d2a53c1..e79a4c8 100644
--- a/contrib/gcc/config/sparc/sun4o3.h
+++ b/contrib/gcc/config/sparc/sun4o3.h
@@ -1,4 +1,5 @@
-#include "sparc/sparc.h"
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dsparc -Dsun -Dunix -Asystem=unix -Asystem=bsd"
/* Override the name of the mcount profiling function. */
@@ -8,22 +9,3 @@
/* LINK_SPEC is needed only for SunOS 4. */
#undef LINK_SPEC
-
-/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special
- traps available which can get and set the condition codes
- reliably. */
-#undef MACHINE_STATE_SAVE
-#define MACHINE_STATE_SAVE(ID) \
- unsigned long int ms_flags, ms_saveret; \
- asm volatile("ta 0x20\n\t" \
- "mov %%g1, %0\n\t" \
- "mov %%g2, %1\n\t" \
- : "=r" (ms_flags), "=r" (ms_saveret));
-
-#undef MACHINE_STATE_RESTORE
-#define MACHINE_STATE_RESTORE(ID) \
- asm volatile("mov %0, %%g1\n\t" \
- "mov %1, %%g2\n\t" \
- "ta 0x21\n\t" \
- : /* no outputs */ \
- : "r" (ms_flags), "r" (ms_saveret));
diff --git a/contrib/gcc/config/sparc/sunos4.h b/contrib/gcc/config/sparc/sunos4.h
index 14c7a43..e5b2dcc 100644
--- a/contrib/gcc/config/sparc/sunos4.h
+++ b/contrib/gcc/config/sparc/sunos4.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for SunOS 4.x
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,32 +18,29 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#undef SUNOS4_SHARED_LIBRARIES
#define SUNOS4_SHARED_LIBRARIES 1
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dsparc -Dsun -Dunix -Asystem=unix -Asystem=bsd"
+
+#define LIB_SPEC "%{!shared:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} %{g:-lg}}"
+
+/* Provide required defaults for linker -e and -d switches. */
+
+#define LINK_SPEC \
+ "%{!shared:%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp} %{static:-Bstatic} \
+ %{assert*} %{shared:%{!mimpure-text:-assert pure-text}}"
+
/* Use N_BINCL stabs. */
#define DBX_USE_BINCL
-#include "sparc/sparc.h"
-
/* The Sun as doesn't like unaligned data. */
#define DWARF2_UNWIND_INFO 0
-/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special
- traps available which can get and set the condition codes
- reliably. */
-#undef MACHINE_STATE_SAVE
-#define MACHINE_STATE_SAVE(ID) \
- unsigned long int ms_flags, ms_saveret; \
- asm volatile("ta 0x20\n\t" \
- "mov %%g1, %0\n\t" \
- "mov %%g2, %1\n\t" \
- : "=r" (ms_flags), "=r" (ms_saveret));
-
-#undef MACHINE_STATE_RESTORE
-#define MACHINE_STATE_RESTORE(ID) \
- asm volatile("mov %0, %%g1\n\t" \
- "mov %1, %%g2\n\t" \
- "ta 0x21\n\t" \
- : /* no outputs */ \
- : "r" (ms_flags), "r" (ms_saveret));
+/* SunOS has on_exit instead of atexit. */
+/* The man page says it returns int. */
+extern int on_exit PARAMS ((void *, void *));
+#define ON_EXIT(FUNC) on_exit ((FUNC), 0)
+#define NEED_ATEXIT
diff --git a/contrib/gcc/config/sparc/sysv4.h b/contrib/gcc/config/sparc/sysv4.h
index 5f9bba9..a4c7f91 100644
--- a/contrib/gcc/config/sparc/sysv4.h
+++ b/contrib/gcc/config/sparc/sysv4.h
@@ -1,5 +1,6 @@
/* Target definitions for GNU compiler for Sparc running System V.4
- Copyright (C) 1991, 92, 95, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1992, 1995, 1996, 1997, 1998, 2000
+ Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@monkeys.com).
This file is part of GNU CC.
@@ -19,19 +20,9 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "sparc/sparc.h"
-
-/* Undefine some symbols which are defined in "sparc.h" but which are
- appropriate only for SunOS 4.x, and not for svr4. */
-
-#undef WORD_SWITCH_TAKES_ARG
-#undef ASM_OUTPUT_SOURCE_LINE
-#undef SELECT_SECTION
-#undef ASM_DECLARE_FUNCTION_NAME
-#undef TEXT_SECTION_ASM_OP
-#undef DATA_SECTION_ASM_OP
-
-#include "svr4.h"
+#ifndef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (sparc ELF)");
+#endif
/* ??? Put back the SIZE_TYPE/PTRDIFF_TYPE definitions set by sparc.h.
Why, exactly, is svr4.h messing with this? Seems like the chip
@@ -60,8 +51,9 @@ Boston, MA 02111-1307, USA. */
/* 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)"
+"-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
@@ -78,9 +70,9 @@ Boston, MA 02111-1307, USA. */
/* Must use data section for relocatable constants when pic. */
#undef SELECT_RTX_SECTION
-#define SELECT_RTX_SECTION(MODE,RTX) \
+#define SELECT_RTX_SECTION(MODE,RTX,ALIGN) \
{ \
- if (flag_pic && symbolic_operand (RTX)) \
+ if (flag_pic && symbolic_operand ((RTX), (MODE))) \
data_section (); \
else \
const_section (); \
@@ -92,18 +84,11 @@ Boston, MA 02111-1307, USA. */
to keep the Sparc/svr4 assembler somewhat compatible with the Sparc/SunOS
assembler. */
-#define STRING_ASM_OP ".asciz"
-#define COMMON_ASM_OP ".common"
-#define SKIP_ASM_OP ".skip"
-#define UNALIGNED_DOUBLE_INT_ASM_OP ".uaxword"
-#define UNALIGNED_INT_ASM_OP ".uaword"
-#define UNALIGNED_SHORT_ASM_OP ".uahalf"
-#define PUSHSECTION_ASM_OP ".pushsection"
-#define POPSECTION_ASM_OP ".popsection"
-
-/* This is defined in sparc.h but is not used by svr4.h. */
-#undef ASM_LONG
-#define ASM_LONG ".long"
+#define STRING_ASM_OP "\t.asciz\t"
+#define COMMON_ASM_OP "\t.common\t"
+#define SKIP_ASM_OP "\t.skip\t"
+#define PUSHSECTION_ASM_OP "\t.pushsection\t"
+#define POPSECTION_ASM_OP "\t.popsection"
/* This is the format used to print the second operand of a .type pseudo-op
for the Sparc/svr4 assembler. */
@@ -113,7 +98,7 @@ Boston, MA 02111-1307, USA. */
/* This is the format used to print a .pushsection pseudo-op (and its operand)
for the Sparc/svr4 assembler. */
-#define PUSHSECTION_FORMAT "\t%s\t\"%s\"\n"
+#define PUSHSECTION_FORMAT "%s\"%s\"\n"
#undef ASM_OUTPUT_CASE_LABEL
#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, JUMPTABLE) \
@@ -155,12 +140,12 @@ do { ASM_OUTPUT_ALIGN ((FILE), Pmode == SImode ? 2 : 3); \
*not* to push the previous section name onto the assembler's
section names stack (as we do often in dwarfout.c). */
-#define TEXT_SECTION_ASM_OP ".section\t\".text\""
-#define DATA_SECTION_ASM_OP ".section\t\".data\""
-#define BSS_SECTION_ASM_OP ".section\t\".bss\""
-#define CONST_SECTION_ASM_OP ".section\t\".rodata\""
-#define INIT_SECTION_ASM_OP ".section\t\".init\""
-#define FINI_SECTION_ASM_OP ".section\t\".fini\""
+#define TEXT_SECTION_ASM_OP "\t.section\t\".text\""
+#define DATA_SECTION_ASM_OP "\t.section\t\".data\""
+#define BSS_SECTION_ASM_OP "\t.section\t\".bss\""
+#define CONST_SECTION_ASM_OP "\t.section\t\".rodata\""
+#define INIT_SECTION_ASM_OP "\t.section\t\".init\""
+#define FINI_SECTION_ASM_OP "\t.section\t\".fini\""
/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
@@ -178,28 +163,13 @@ do { ASM_OUTPUT_ALIGN ((FILE), Pmode == SImode ? 2 : 3); \
via the SHF_WRITE attribute.) */
#undef CTORS_SECTION_ASM_OP
-#define CTORS_SECTION_ASM_OP ".section\t\".ctors\",#alloc,#write"
+#define CTORS_SECTION_ASM_OP "\t.section\t\".ctors\",#alloc,#write"
#undef DTORS_SECTION_ASM_OP
-#define DTORS_SECTION_ASM_OP ".section\t\".dtors\",#alloc,#write"
-#undef EH_FRAME_SECTION_ASM_OP
-#define EH_FRAME_SECTION_ASM_OP ".section\t\".eh_frame\",#alloc,#write"
-
-/* A C statement to output something to the assembler file to switch to section
- NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or
- NULL_TREE. Some target formats do not support arbitrary sections. Do not
- define this macro in such cases. */
-
-#undef ASM_OUTPUT_SECTION_NAME /* Override svr4.h's definition. */
-#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
-do { \
- if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL) \
- fprintf (FILE, ".section\t\"%s\",#alloc,#execinstr\n", \
- (NAME)); \
- else if ((DECL) && DECL_READONLY_SECTION (DECL, RELOC)) \
- fprintf (FILE, ".section\t\"%s\",#alloc\n", (NAME)); \
- else \
- fprintf (FILE, ".section\t\"%s\",#alloc,#write\n", (NAME)); \
-} while (0)
+#define DTORS_SECTION_ASM_OP "\t.section\t\".dtors\",#alloc,#write"
+
+/* Switch into a generic section. */
+#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
diff --git a/contrib/gcc/config/sparc/t-chorus-elf b/contrib/gcc/config/sparc/t-chorus-elf
new file mode 100644
index 0000000..5fc405b
--- /dev/null
+++ b/contrib/gcc/config/sparc/t-chorus-elf
@@ -0,0 +1,29 @@
+LIB1ASMSRC = sparc/lb1spc.asm
+LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3
+
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+ cat $(srcdir)/config/fp-bit.c > dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#define FLOAT' > fp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+# MULTILIB_OPTIONS should have msparclite too, but we'd have to make
+# gas build...
+MULTILIB_OPTIONS =
+MULTILIB_DIRNAMES =
+MULTILIB_MATCHES =
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+# Assemble startup files.
+crti.o: $(srcdir)/config/sparc/sol2-ci.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) -c -o crti.o -x assembler $(srcdir)/config/sparc/sol2-ci.asm
+crtn.o: $(srcdir)/config/sparc/sol2-cn.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) -c -o crtn.o -x assembler $(srcdir)/config/sparc/sol2-cn.asm
diff --git a/contrib/gcc/config/sparc/t-elf b/contrib/gcc/config/sparc/t-elf
index da9df38..ead6e25 100644
--- a/contrib/gcc/config/sparc/t-elf
+++ b/contrib/gcc/config/sparc/t-elf
@@ -1,17 +1,7 @@
-# we need to supply our own assembly versions of libgcc1.c files,
-# since the user may not have native 'cc' available
-
-CROSS_LIBGCC1 = libgcc1-asm.a
-LIB1ASMSRC = sparc/lb1spc.asm
-LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3
-
-# crt0 is built elsewhere
-LIBGCC1_TEST =
-
-# These are really part of libgcc1, but this will cause them to be
-# built correctly, so...
-
-LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
dp-bit.c: $(srcdir)/config/fp-bit.c
cat $(srcdir)/config/fp-bit.c > dp-bit.c
diff --git a/contrib/gcc/config/sparc/t-linux64 b/contrib/gcc/config/sparc/t-linux64
index 077cf69..4f552e0 100644
--- a/contrib/gcc/config/sparc/t-linux64
+++ b/contrib/gcc/config/sparc/t-linux64
@@ -1,21 +1,10 @@
-MULTILIB_OPTIONS = m64/m32
-MULTILIB_DIRNAMES = 64 32
-MULTILIB_MATCHES =
+MULTILIB_OPTIONS = m64/m32 mno-app-regs|mcmodel=medany
+MULTILIB_DIRNAMES = 64 32 alt
+MULTILIB_MATCHES = mcmodel?medany=mcmodel?medmid
+MULTILIB_EXCEPTIONS = m32/mno-app-regs* m32/mcmodel=*
+MULTILIB_EXCLUSIONS = m32/!m64/mno-app-regs m32/!m64/mcmodel=medany
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
-EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o
-
-tcrtbeginS.o: crtstuff.c $(GCC_PASSES) $(CONFIG_H) \
- defaults.h frame.h gbl-ctors.h
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
- -finhibit-size-directive -fno-inline-functions -fno-exceptions $(CRTSTUFF_T_CFLAGS_S) \
- -c $(srcdir)/crtstuff.c -DCRT_BEGIN -o tcrtbeginS$(objext)
-
-tcrtendS.o: crtstuff.c $(GCC_PASSES) $(CONFIG_H) \
- defaults.h frame.h gbl-ctors.h
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
- -finhibit-size-directive -fno-inline-functions -fno-exceptions $(CRTSTUFF_T_CFLAGS_S) \
- -c $(srcdir)/crtstuff.c -DCRT_END -o tcrtendS$(objext)
-
+EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
diff --git a/contrib/gcc/config/sparc/t-openbsd b/contrib/gcc/config/sparc/t-openbsd
new file mode 100644
index 0000000..898a24e
--- /dev/null
+++ b/contrib/gcc/config/sparc/t-openbsd
@@ -0,0 +1,5 @@
+# The native linker doesn't handle linking -fpic code with -fPIC code. Ugh.
+# We cope by building both variants of libgcc.
+MULTILIB_OPTIONS = fpic/fPIC
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
diff --git a/contrib/gcc/config/sparc/t-sol2 b/contrib/gcc/config/sparc/t-sol2
index a9b6ee1..4a5a13b 100644
--- a/contrib/gcc/config/sparc/t-sol2
+++ b/contrib/gcc/config/sparc/t-sol2
@@ -1,10 +1,3 @@
-# we need to supply our own assembly versions of libgcc1.c files,
-# since the user may not have native 'cc' available
-
-LIBGCC1 =
-CROSS_LIBGCC1 =
-LIBGCC1_TEST =
-
# gmon build rule:
$(T)gmon.o: $(srcdir)/config/sparc/gmon-sol2.c $(GCC_PASSES) $(CONFIG_H) stmp-int-hdrs
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) \
diff --git a/contrib/gcc/config/sparc/t-sp86x b/contrib/gcc/config/sparc/t-sp86x
new file mode 100644
index 0000000..6dd5c03
--- /dev/null
+++ b/contrib/gcc/config/sparc/t-sp86x
@@ -0,0 +1,23 @@
+LIB1ASMSRC = sparc/lb1spc.asm
+LIB1ASMFUNCS = _divsi3 _modsi3
+
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#define US_SOFTWARE_GOFAST' > dp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#define FLOAT' > fp-bit.c
+ echo '#define US_SOFTWARE_GOFAST' >> fp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+MULTILIB_OPTIONS = mlittle-endian-data
+MULTILIB_DIRNAMES = little
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
diff --git a/contrib/gcc/config/sparc/t-sparcbare b/contrib/gcc/config/sparc/t-sparcbare
index 8bd978b..bac38de 100644
--- a/contrib/gcc/config/sparc/t-sparcbare
+++ b/contrib/gcc/config/sparc/t-sparcbare
@@ -1,13 +1,12 @@
# configuration file for a bare sparc cpu
-CROSS_LIBGCC1 = libgcc1-asm.a
LIB1ASMSRC = sparc/lb1spc.asm
LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3
-# These are really part of libgcc1, but this will cause them to be
-# built correctly, so...
-
-LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
dp-bit.c: $(srcdir)/config/fp-bit.c
cat $(srcdir)/config/fp-bit.c > dp-bit.c
diff --git a/contrib/gcc/config/sparc/t-sparclite b/contrib/gcc/config/sparc/t-sparclite
index 7cdfbb0..03c44b5 100644
--- a/contrib/gcc/config/sparc/t-sparclite
+++ b/contrib/gcc/config/sparc/t-sparclite
@@ -1,11 +1,10 @@
-CROSS_LIBGCC1 = libgcc1-asm.a
LIB1ASMSRC = sparc/lb1spl.asm
LIB1ASMFUNCS = _divsi3 _udivsi3 _modsi3 _umodsi3
-# These are really part of libgcc1, but this will cause them to be
-# built correctly, so...
-
-LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
dp-bit.c: $(srcdir)/config/fp-bit.c
echo '#define US_SOFTWARE_GOFAST' > dp-bit.c
diff --git a/contrib/gcc/config/sparc/t-splet b/contrib/gcc/config/sparc/t-splet
index 3329e0b..3334200 100644
--- a/contrib/gcc/config/sparc/t-splet
+++ b/contrib/gcc/config/sparc/t-splet
@@ -1,13 +1,12 @@
# configuration file for a bare sparclet cpu, aout format files
-CROSS_LIBGCC1 = libgcc1-asm.a
LIB1ASMSRC = sparc/lb1spc.asm
LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3
-# These are really part of libgcc1, but this will cause them to be
-# built correctly, so...
-
-LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
dp-bit.c: $(srcdir)/config/fp-bit.c
cat $(srcdir)/config/fp-bit.c > dp-bit.c
diff --git a/contrib/gcc/config/sparc/t-sunos41 b/contrib/gcc/config/sparc/t-sunos41
index 5783d6a..1056d93 100644
--- a/contrib/gcc/config/sparc/t-sunos41
+++ b/contrib/gcc/config/sparc/t-sunos41
@@ -1,9 +1,5 @@
# SunOS 4.1.*
-LIBGCC1 =
-CROSS_LIBGCC1 =
-LIBGCC1_TEST =
-
MULTILIB_OPTIONS = fpic/fPIC mcpu=v8
MULTILIB_DIRNAMES = pic ucpic v8
MULTILIB_MATCHES = mcpu?v8=mv8
diff --git a/contrib/gcc/config/sparc/t-vxsparc b/contrib/gcc/config/sparc/t-vxsparc
index 0c7a14a..5a47341 100644
--- a/contrib/gcc/config/sparc/t-vxsparc
+++ b/contrib/gcc/config/sparc/t-vxsparc
@@ -1,10 +1,3 @@
-LIBGCC1 =
-CROSS_LIBGCC1 =
-
-# We don't want to build .umul, etc., because VxWorks provides them,
-# which means that libgcc1-test will fail.
-LIBGCC1_TEST =
-
# We don't want to put exit in libgcc.a for VxWorks, because VxWorks
# does not have _exit.
TARGET_LIBGCC2_CFLAGS = -Dexit=unused_exit
diff --git a/contrib/gcc/config/sparc/t-vxsparc64 b/contrib/gcc/config/sparc/t-vxsparc64
new file mode 100644
index 0000000..ee779ee
--- /dev/null
+++ b/contrib/gcc/config/sparc/t-vxsparc64
@@ -0,0 +1,23 @@
+# We don't want to put exit in libgcc.a for VxWorks, because VxWorks
+# does not have _exit.
+TARGET_LIBGCC2_CFLAGS = -Dexit=unused_exit
+
+LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#define US_SOFTWARE_GOFAST' > dp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#define FLOAT' > fp-bit.c
+ echo '#define US_SOFTWARE_GOFAST' >> fp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+MULTILIB_OPTIONS=O0
+MULTILIB_DIRNAMES=O0
+MULTILIB_MATCHES=
+MULTILIB_EXCEPTIONS=
+MULTILIB_EXTRA_OPTS=m64 mcpu=ultrasparc
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
diff --git a/contrib/gcc/config/sparc/vxsim.h b/contrib/gcc/config/sparc/vxsim.h
index 6c80375..94cfb92 100644
--- a/contrib/gcc/config/sparc/vxsim.h
+++ b/contrib/gcc/config/sparc/vxsim.h
@@ -18,13 +18,15 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (sparc VxSim)");
+
/* Supposedly the same as vanilla sparc svr4, except for the stuff below: */
-#include "sparc/sysv4.h"
#undef CPP_PREDEFINES
#define CPP_PREDEFINES \
"-DCPU=SIMSPARCSOLARIS -D__vxworks -D__vxworks__ -Dsparc -D__svr4__ -D__SVR4 \
- -Asystem(embedded) -Asystem(svr4) -Acpu(sparc) -Amachine(sparc)\
+ -Asystem=embedded -Asystem=svr4 -Acpu=sparc -Amachine=sparc\
-D__GCC_NEW_VARARGS__"
#undef CPP_SPEC
@@ -34,14 +36,14 @@ Boston, MA 02111-1307, USA. */
#define CC1_SPEC "-fno-builtin %{sun4:} %{target:}"
/* The sun bundled assembler doesn't accept -Yd, (and neither does gas).
- It's safe to pass -s always, even if -g is not used. */
+ It's safe to pass -s always, even if -g is not used. */
#undef ASM_SPEC
#define ASM_SPEC \
"%{V} %{v:%{!V:-V}} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s \
%{fpic:-K PIC} %{fPIC:-K PIC}"
/* However it appears that Solaris 2.0 uses the same reg numbering as
- the old BSD-style system did. */
+ the old BSD-style system did. */
#undef DBX_REGISTER_NUMBER
/* Same as sparc.h */
@@ -52,7 +54,7 @@ Boston, MA 02111-1307, USA. */
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-/* The Solaris 2 assembler uses .skip, not .zero, so put this back. */
+/* 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))
@@ -67,7 +69,7 @@ do { \
} while (0)
#undef COMMON_ASM_OP
-#define COMMON_ASM_OP "\t.common"
+#define COMMON_ASM_OP "\t.common\t"
/* 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. */
@@ -90,7 +92,7 @@ do { \
#undef ASM_GENERATE_INTERNAL_LABEL
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
- sprintf (LABEL, "*.L%s%d", PREFIX, NUM)
+ sprintf (LABEL, "*.L%s%ld", PREFIX, (long)(NUM))
diff --git a/contrib/gcc/config/sparc/vxsparc.h b/contrib/gcc/config/sparc/vxsparc.h
index 18ce6ed..da3e591 100644
--- a/contrib/gcc/config/sparc/vxsparc.h
+++ b/contrib/gcc/config/sparc/vxsparc.h
@@ -19,7 +19,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "sparc/aout.h"
/* Specify what to link with. */
/* VxWorks does all the library stuff itself. */
@@ -27,7 +26,7 @@ Boston, MA 02111-1307, USA. */
#undef LIB_SPEC
#define LIB_SPEC ""
-/* Provide required defaults for linker -e. */
+/* Provide required defaults for linker -e. */
#undef LINK_SPEC
#define LINK_SPEC "%{!nostdlib:%{!r*:%{!e*:-e start}}}"
@@ -36,7 +35,7 @@ Boston, MA 02111-1307, USA. */
#define STARTFILE_SPEC ""
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dsparc -Acpu(sparc) -Amachine(sparc)"
+#define CPP_PREDEFINES "-Dsparc -Acpu=sparc -Amachine=sparc"
/* Note that we define CPU here even if the user has specified -ansi.
This violates user namespace, but the VxWorks headers, and potentially
@@ -56,6 +55,5 @@ Boston, MA 02111-1307, USA. */
#define WCHAR_TYPE_SIZE 8
/* US Software GOFAST library support. */
-#include "gofast.h"
#undef INIT_SUBTARGET_OPTABS
#define INIT_SUBTARGET_OPTABS INIT_GOFAST_OPTABS
diff --git a/contrib/gcc/config/sparc/vxsparc64.h b/contrib/gcc/config/sparc/vxsparc64.h
new file mode 100644
index 0000000..ecfe25b
--- /dev/null
+++ b/contrib/gcc/config/sparc/vxsparc64.h
@@ -0,0 +1,92 @@
+/* Definitions of target machine for GNU compiler.
+ 64-bit VxWorks Sparc version.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+/* Specify what to link with. */
+/* VxWorks does all the library stuff itself. */
+#undef LIB_SPEC
+#define LIB_SPEC "-r"
+
+/* VxWorks provides the functionality of crt0.o and friends itself. */
+#undef STARTFILE_SPEC
+#undef ENDFILE_SPEC
+#define STARTFILE_SPEC ""
+#define ENDFILE_SPEC ""
+
+#undef LINK_SPEC
+#define LINK_SPEC ""
+
+/* We need to prohibit dots in constructor labels so that we can build a
+ table of { string, address } entries for each non-static name in a
+ program. The address, being of the form &name, it cannot contain a dot or
+ C will try to parse it as a &struct.field phrase. */
+#undef NO_DOLLAR_IN_LABEL
+#undef DOLLARS_IN_IDENTIFIERS
+#define DOLLARS_IN_IDENTIFIERS 1
+#define NO_DOT_IN_LABEL
+
+/* Enable #pragma pack(n) */
+#define HANDLE_SYSV_PRAGMA
+
+/* We use stabs for debugging */
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+
+/* Longs are still only 32bits for vxWorks, even for UltraSPARC */
+#undef LONG_TYPE_SIZE
+#define LONG_TYPE_SIZE 32
+
+#undef CPP_ARCH32_SPEC
+#define CPP_ARCH32_SPEC "-Acpu(sparc) -Amachine(sparc)"
+#undef CPP_ARCH64_SPEC
+#define CPP_ARCH64_SPEC \
+"-Dsparc64 -D__arch64__ -Acpu(sparc64) -Amachine(sparc64)"
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-D__vxworks -D__sparc__ -Dsparc -D__GCC_NEW_VARARGS__"
+
+/* Note that we define CPU here even if the user has specified -ansi.
+ This violates user namespace, but the VxWorks headers, and potentially
+ user code, all explicitly rely upon the definition of CPU in order to get
+ the proper processor information. */
+#undef CPP_SPEC
+#define CPP_SPEC "%(cpp_cpu) %(cpp_arch) -DCPU=ULTRASPARC -D__CPU__=CPU"
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_APP_REGS | MASK_EPILOGUE | MASK_FPU \
+ | MASK_LONG_DOUBLE_128 | MASK_64BIT)
+
+#undef SPARC_DEFAULT_CMODEL
+#define SPARC_DEFAULT_CMODEL CM_MEDLOW
+
+#undef PTRDIFF_TYPE
+#undef SIZE_TYPE
+#undef WCHAR_TYPE
+#undef WCHAR_TYPE_SIZE
+
+#define PTRDIFF_TYPE "long int"
+#define SIZE_TYPE "unsigned int"
+#define WCHAR_TYPE "char"
+#define WCHAR_TYPE_SIZE 8
+
+/* US Software GOFAST library support. */
+#undef INIT_SUBTARGET_OPTABS
+#define INIT_SUBTARGET_OPTABS INIT_GOFAST_OPTABS
OpenPOWER on IntegriCloud