summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/config/ia64
diff options
context:
space:
mode:
authorkan <kan@FreeBSD.org>2003-07-11 03:40:53 +0000
committerkan <kan@FreeBSD.org>2003-07-11 03:40:53 +0000
commitb2a8872fbe1ec1c49094559ac7b78e6ea4ab7180 (patch)
treef6b0610f4a17fd26aa234354f050080f789861a4 /contrib/gcc/config/ia64
parent52e69d78eee5612ac195e0701a5cebe40d1ab0e1 (diff)
downloadFreeBSD-src-b2a8872fbe1ec1c49094559ac7b78e6ea4ab7180.zip
FreeBSD-src-b2a8872fbe1ec1c49094559ac7b78e6ea4ab7180.tar.gz
Gcc 3.3.1-pre as of 2003-07-11.
Diffstat (limited to 'contrib/gcc/config/ia64')
-rw-r--r--contrib/gcc/config/ia64/aix.h151
-rw-r--r--contrib/gcc/config/ia64/crtbegin.asm15
-rw-r--r--contrib/gcc/config/ia64/crtend.asm12
-rw-r--r--contrib/gcc/config/ia64/elf.h6
-rw-r--r--contrib/gcc/config/ia64/freebsd.h3
-rw-r--r--contrib/gcc/config/ia64/hpux.h160
-rw-r--r--contrib/gcc/config/ia64/hpux_longdouble.h14
-rw-r--r--contrib/gcc/config/ia64/ia64-c.c191
-rw-r--r--contrib/gcc/config/ia64/ia64-modes.def29
-rw-r--r--contrib/gcc/config/ia64/ia64-protos.h22
-rw-r--r--contrib/gcc/config/ia64/ia64.c1427
-rw-r--r--contrib/gcc/config/ia64/ia64.h329
-rw-r--r--contrib/gcc/config/ia64/ia64.md1207
-rw-r--r--contrib/gcc/config/ia64/linux.h13
-rw-r--r--contrib/gcc/config/ia64/quadlib.c19
-rw-r--r--contrib/gcc/config/ia64/sysv4.h162
-rw-r--r--contrib/gcc/config/ia64/t-aix6
-rw-r--r--contrib/gcc/config/ia64/t-hpux33
-rw-r--r--contrib/gcc/config/ia64/t-ia6428
-rw-r--r--contrib/gcc/config/ia64/unwind-ia64.c27
20 files changed, 2346 insertions, 1508 deletions
diff --git a/contrib/gcc/config/ia64/aix.h b/contrib/gcc/config/ia64/aix.h
index fee0732..5eb2334 100644
--- a/contrib/gcc/config/ia64/aix.h
+++ b/contrib/gcc/config/ia64/aix.h
@@ -71,34 +71,36 @@ Boston, MA 02111-1307, USA. */
/* Define this so we can compile MS code for use with WINE. */
#define HANDLE_PRAGMA_PACK_PUSH_POP
+/* Target OS builtins. */
+#define TARGET_OS_CPP_BUILTINS() \
+do { \
+ if (flag_iso) \
+ builtin_define("_ANSI_C_SOURCE"); \
+ builtin_define("_AIX"); \
+ builtin_define("_AIX64"); \
+ builtin_define("unix"); \
+ builtin_assert("system=unix"); \
+ builtin_assert("system=aix"); \
+ builtin_define("__64BIT__"); \
+ builtin_define("_LONG_LONG"); \
+ builtin_define("_IA64"); \
+ builtin_define("__int128=__size128_t"); \
+ if (c_language == clk_cplusplus) \
+ { \
+ builtin_define("_XOPEN_SOURCE=500"); \
+ builtin_define("_XOPEN_SOURCE_EXTENDED=1"); \
+ builtin_define("_LARGE_FILE_API"); \
+ builtin_define("_ALL_SOURCE"); \
+ } \
+} while (0)
+
/* A C string constant that tells the GNU CC driver program options to pass to
CPP. It can also specify how to translate options you give to GNU CC into
options for GNU CC to pass to the CPP. */
-/* If -ansi, we need to define _ANSI_C_SOURCE to get the right headers. */
#undef CPP_SPEC
#define CPP_SPEC "\
-%{mcpu=itanium:-D__itanium__} %{mbig-endian:-D__BIG_ENDIAN__} \
-%{ansi:-D_ANSI_C_SOURCE} \
-%{posix:-D_POSIX_SOURCE} \
-%{cpp_cpu} \
--D__LONG_MAX__=9223372036854775807L"
-
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "\
- -D_AIX -D_AIX64 -D_LONGLONG -Dunix \
- -Asystem=unix -Asystem=aix \
- -D__64BIT__ -D_LONG_LONG -D_IA64 -D__int128=__size128_t"
-
-/* The GNU C++ standard library requires that these macros be defined. */
-#undef CPLUSPLUS_CPP_SPEC
-#define CPLUSPLUS_CPP_SPEC \
- "-D_XOPEN_SOURCE=500 \
- -D_XOPEN_SOURCE_EXTENDED=1 \
- -D_LARGE_FILE_API \
- -D_ALL_SOURCE \
- -D__LONG_MAX__=9223372036854775807L \
- %{cpp_cpu}"
+%{posix:-D_POSIX_SOURCE}"
/* Define this for shared library support. */
@@ -132,103 +134,14 @@ do { \
#define STANDARD_STARTFILE_PREFIX "/usr/lib/ia64l64/"
#endif
-/* Override SELECT_SECTION and SELECT_RTX_SECTION from config/ia64/sysv4.h;
- these definitions ignore flag_pic as if it were always set;
- it is illegal to have relocations in shared segments on AIX. */
-
-/* A C statement or statements to switch to the appropriate
- section for output of DECL. DECL is either a `VAR_DECL' node
- or a constant of some sort. RELOC indicates whether forming
- the initial value of DECL requires link-time relocations. */
-
-#undef SELECT_SECTION
-#define SELECT_SECTION(DECL,RELOC,ALIGN) \
-{ \
- if (TREE_CODE (DECL) == STRING_CST) \
- { \
- if (! flag_writable_strings) \
- const_section (); \
- else \
- data_section (); \
- } \
- else if (TREE_CODE (DECL) == VAR_DECL) \
- { \
- if (XSTR (XEXP (DECL_RTL (DECL), 0), 0)[0] \
- == SDATA_NAME_FLAG_CHAR) \
- sdata_section (); \
- /* ??? We need the extra ! RELOC check, because the default is to \
- only check RELOC if flag_pic is set, and we don't set flag_pic \
- (yet?). */ \
- else if (DECL_READONLY_SECTION (DECL, RELOC) && ! (RELOC)) \
- const_section (); \
- else \
- data_section (); \
- } \
- /* This could be a CONSTRUCTOR containing ADDR_EXPR of a VAR_DECL, \
- in which case we can't put it in a shared library rodata. */ \
- else if (RELOC) \
- data_section (); \
- else \
- const_section (); \
-}
-
-/* Similarly for constant pool data. */
-
-extern unsigned int ia64_section_threshold;
-#undef SELECT_RTX_SECTION
-#define SELECT_RTX_SECTION(MODE, RTX, ALIGN) \
-{ \
- if (GET_MODE_SIZE (MODE) > 0 \
- && GET_MODE_SIZE (MODE) <= ia64_section_threshold) \
- sdata_section (); \
- else if (symbolic_operand ((RTX), (MODE))) \
- data_section (); \
- else \
- const_section (); \
-}
-
-#undef UNIQUE_SECTION
-#define UNIQUE_SECTION(DECL, RELOC) \
- do \
- { \
- int len; \
- int sec; \
- const char *name; \
- char *string; \
- const char *prefix; \
- static const char *const prefixes[/*4*/3][2] = \
- { \
- { ".text.", ".gnu.linkonce.t." }, \
- { ".rodata.", ".gnu.linkonce.r." }, \
- { ".data.", ".gnu.linkonce.d." } \
- /* Do not generate unique sections for uninitialised \
- data since we do not have support for this in the \
- linker scripts yet... \
- ,{ ".bss.", ".gnu.linkonce.b." } */ \
- }; \
- \
- if (TREE_CODE (DECL) == FUNCTION_DECL) \
- sec = 0; \
- /* else if (DECL_INITIAL (DECL) == 0 \
- || DECL_INITIAL (DECL) == error_mark_node) \
- sec = 3; */ \
- else if (DECL_READONLY_SECTION (DECL, RELOC) && ! (RELOC))\
- sec = 1; \
- else \
- sec = 2; \
- \
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
- /* Strip off any encoding in name. */ \
- STRIP_NAME_ENCODING (name, name); \
- prefix = prefixes[sec][DECL_ONE_ONLY(DECL)]; \
- len = strlen (name) + strlen (prefix); \
- string = alloca (len + 1); \
- \
- sprintf (string, "%s%s", prefix, name); \
- \
- DECL_SECTION_NAME (DECL) = build_string (len, string); \
- } \
- while (0)
+/* It is illegal to have relocations in shared segments on AIX.
+ Pretend flag_pic is always set. */
+#undef TARGET_ASM_SELECT_SECTION
+#define TARGET_ASM_SELECT_SECTION ia64_rwreloc_select_section
+#undef TARGET_ASM_UNIQUE_SECTION
+#define TARGET_ASM_UNIQUE_SECTION ia64_rwreloc_unique_section
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION ia64_rwreloc_select_rtx_section
/* Override ia64/sysv4.h setting with that used by AIX5. */
#undef WCHAR_TYPE
diff --git a/contrib/gcc/config/ia64/crtbegin.asm b/contrib/gcc/config/ia64/crtbegin.asm
index 388b24e..cb49e10 100644
--- a/contrib/gcc/config/ia64/crtbegin.asm
+++ b/contrib/gcc/config/ia64/crtbegin.asm
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc.
Contributed by Jes Sorensen, <Jes.Sorensen@cern.ch>
The GNU C Library is free software; you can redistribute it and/or
@@ -16,6 +16,8 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include "auto-host.h"
+
.section .ctors,"aw","progbits"
.align 8
__CTOR_LIST__:
@@ -52,6 +54,16 @@ __dso_handle:
.hidden __dso_handle#
+#ifdef HAVE_INITFINI_ARRAY
+
+.section .fini_array,"a","progbits"
+ data8 @fptr(__do_global_dtors_aux)
+
+.section .init_array,"a","progbits"
+ data8 @fptr(__do_jv_register_classes)
+ data8 @fptr(__do_global_ctors_aux)
+
+#else /* !HAVE_INITFINI_ARRAY */
/*
* Fragment of the ELF _fini routine that invokes our dtor cleanup.
*
@@ -98,6 +110,7 @@ __dso_handle:
br.call.sptk.many b0 = b6
;;
}
+#endif /* !HAVE_INITFINI_ARRAY */
.section .text
.align 16
diff --git a/contrib/gcc/config/ia64/crtend.asm b/contrib/gcc/config/ia64/crtend.asm
index e5d109a..303f30c 100644
--- a/contrib/gcc/config/ia64/crtend.asm
+++ b/contrib/gcc/config/ia64/crtend.asm
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc.
Contributed by Jes Sorensen, <Jes.Sorensen@cern.ch>
The GNU C Library is free software; you can redistribute it and/or
@@ -16,6 +16,8 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include "auto-host.h"
+
.section .ctors,"aw","progbits"
.align 8
__CTOR_END__:
@@ -31,6 +33,7 @@ __DTOR_END__:
__JCR_END__:
data8 0
+#ifndef HAVE_INITFINI_ARRAY
/*
* Fragment of the ELF _init routine that invokes our dtor cleanup.
*
@@ -59,9 +62,16 @@ __JCR_END__:
br.call.sptk.many b0 = b6
;;
}
+#endif /* !HAVE_INITFINI_ARRAY */
.text
.align 16
+#ifdef HAVE_INITFINI_ARRAY
+ /* This is referenced from crtbegin.o. */
+ .globl __do_global_ctors_aux#
+ .type __do_global_ctors_aux#,@function
+ .hidden __do_global_ctors_aux#
+#endif
.proc __do_global_ctors_aux#
__do_global_ctors_aux:
/*
diff --git a/contrib/gcc/config/ia64/elf.h b/contrib/gcc/config/ia64/elf.h
index af6d917..e30090d 100644
--- a/contrib/gcc/config/ia64/elf.h
+++ b/contrib/gcc/config/ia64/elf.h
@@ -5,12 +5,6 @@
#define TARGET_VERSION fprintf (stderr, " (IA-64) ELF");
-/* Define this to be a string constant containing `-D' options to define the
- predefined macros that identify this machine and system. These macros will
- be predefined unless the `-ansi' option is specified. */
-/* ??? This is undefed in svr4.h. */
-#define CPP_PREDEFINES "-Dia64 -Amachine=ia64"
-
/* A C string constant that tells the GNU CC driver program options to pass to
the assembler. It can also specify how to translate options you give to GNU
CC into options for GNU CC to pass to the assembler. */
diff --git a/contrib/gcc/config/ia64/freebsd.h b/contrib/gcc/config/ia64/freebsd.h
index 57bb391..34dc885 100644
--- a/contrib/gcc/config/ia64/freebsd.h
+++ b/contrib/gcc/config/ia64/freebsd.h
@@ -42,9 +42,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
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
diff --git a/contrib/gcc/config/ia64/hpux.h b/contrib/gcc/config/ia64/hpux.h
index d46acf2..56c601b 100644
--- a/contrib/gcc/config/ia64/hpux.h
+++ b/contrib/gcc/config/ia64/hpux.h
@@ -1,5 +1,5 @@
/* Definitions of target machine GNU compiler. IA-64 version.
- Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Steve Ellcey <sje@cup.hp.com> and
Reva Cuthbertson <reva@cup.hp.com>
@@ -25,26 +25,29 @@ Boston, MA 02111-1307, USA. */
#define TARGET_VERSION fprintf (stderr, " (IA-64) HP-UX");
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "\
- -D__IA64__ -D__hpux -D__hpux__ -Dhpux -Dunix \
- -D__BIG_ENDIAN__ -D_LONGLONG \
- -Asystem=hpux -Asystem=posix -Asystem=unix \
- -D_UINT128_T"
-
-/* -D__fpreg=long double is needed to compensate for the lack of __fpreg
- which is a primitive type in HP C but does not exist in GNU C. Same
- for __float80 and __float128. These types appear in HP-UX header
- files and so must have some definition. */
-
-#undef CPP_SPEC
-#define CPP_SPEC "\
- %{mcpu=itanium:-D__itanium__} \
- %{mlp64:-D__LP64__ -D_LP64 -D__LONG_MAX__=9223372036854775807L} \
- %{!ansi:%{!std=c*:%{!std=i*: -D_HPUX_SOURCE -D__STDC_EXT__}}} \
- -D__fpreg=long\\ double \
- -D__float80=long\\ double \
- -D__float128=long\\ double"
+/* Target OS builtins. */
+/* -D__fpreg=long double is needed to compensate for
+ the lack of __fpreg which is a primative type in
+ HP C but does not exist in GNU C. */
+#define TARGET_OS_CPP_BUILTINS() \
+do { \
+ builtin_assert("system=hpux"); \
+ builtin_assert("system=posix"); \
+ builtin_assert("system=unix"); \
+ builtin_define_std("hpux"); \
+ builtin_define_std("unix"); \
+ builtin_define("__IA64__"); \
+ builtin_define("_LONGLONG"); \
+ builtin_define("_UINT128_T"); \
+ builtin_define("__fpreg=long double"); \
+ builtin_define("__float80=long double"); \
+ builtin_define("__float128=long double"); \
+ if (c_language == clk_cplusplus || !flag_iso) \
+ { \
+ builtin_define("_HPUX_SOURCE"); \
+ builtin_define("__STDC_EXT__"); \
+ } \
+} while (0)
#undef ASM_EXTRA_SPEC
#define ASM_EXTRA_SPEC "%{milp32:-milp32} %{mlp64:-mlp64}"
@@ -52,24 +55,31 @@ Boston, MA 02111-1307, USA. */
#undef ENDFILE_SPEC
#undef STARTFILE_SPEC
-#ifdef CROSS_COMPILE
-#define STARTFILE_SPEC "%{!shared:crt0%O%s}"
-#else
-#define STARTFILE_SPEC "/usr/ccs/lib/hpux64/crt0%O"
-#endif
+#define STARTFILE_SPEC "%{!shared:%{static:crt0%O%s}}"
#undef LINK_SPEC
-#define LINK_SPEC "\
- +Accept TypeMismatch \
- %{shared:-b} \
- %{!shared: \
- -u main \
- %{!static: \
- %{rdynamic:-export-dynamic}} \
- %{static:-static}}"
+#define LINK_SPEC \
+ "+Accept TypeMismatch \
+ %{shared:-b} \
+ %{!shared: \
+ -u main \
+ %{static:-noshared}}"
#undef LIB_SPEC
-#define LIB_SPEC "%{!shared:%{!symbolic:-lc}}"
+#define LIB_SPEC \
+ "%{!shared: \
+ %{p:%{!mlp64:-L/usr/lib/hpux32/libp} \
+ %{mlp64:-L/usr/lib/hpux64/libp} -lprof} \
+ %{pg:%{!mlp64:-L/usr/lib/hpux32/libp} \
+ %{mlp64:-L/usr/lib/hpux64/libp} -lgprof} \
+ %{!symbolic:-lc}}"
+
+#ifndef CROSS_COMPILE
+#undef LIBGCC_SPEC
+#define LIBGCC_SPEC \
+ "%{shared-libgcc:%{!mlp64:-lgcc_s_hpux32}%{mlp64:-lgcc_s_hpux64} -lgcc} \
+ %{!shared-libgcc:-lgcc}"
+#endif
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
@@ -85,34 +95,27 @@ Boston, MA 02111-1307, USA. */
#define JMP_BUF_SIZE (8 * 76)
-#undef CONST_SECTION_ASM_OP
-#define CONST_SECTION_ASM_OP "\t.section\t.rodata,\t\"a\",\t\"progbits\""
-
-#undef BITS_BIG_ENDIAN
-#define BITS_BIG_ENDIAN 1
-
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_DWARF2_ASM | MASK_BIG_ENDIAN)
+#define TARGET_DEFAULT (MASK_DWARF2_ASM | MASK_BIG_ENDIAN | MASK_ILP32)
/* This needs to be set to force structure arguments with a single
field to be treated as structures and not as the type of their
field. Without this a structure with a single char will be
returned just like a char variable and that is wrong on HP-UX
- IA64. TARGET_STRUCT_ARG_REG_LITTLE_ENDIAN triggers the special
- structure handling, this macro simply ensures that single field
- structures are always treated like structures. */
+ IA64. */
-#define MEMBER_TYPE_FORCES_BLK(FIELD) 1
+#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) (TREE_CODE (TREE_TYPE (FIELD)) != REAL_TYPE || (MODE == TFmode && !INTEL_EXTENDED_IEEE_FORMAT))
-/* Override the setting of FUNCTION_ARG_REG_LITTLE_ENDIAN in
- defaults.h. Setting this to true means that we are not passing
- structures in registers in the "normal" big-endian way. See
- See section 8.5 of the "Itanium Software Conventions and Runtime
- Architecture", specifically Table 8-1 and the explanation of Byte 0
- alignment and LSB alignment and a description of how structures
- are passed. */
+/* ASM_OUTPUT_EXTERNAL_LIBCALL defaults to just a globalize_label call,
+ but that doesn't put out the @function type information which causes
+ shared library problems. */
-#define FUNCTION_ARG_REG_LITTLE_ENDIAN 1
+#undef ASM_OUTPUT_EXTERNAL_LIBCALL
+#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \
+do { \
+ (*targetm.asm_out.globalize_label) (FILE, XSTR (FUN, 0)); \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, XSTR (FUN, 0), "function"); \
+} while (0)
#undef FUNCTION_ARG_PADDING
#define FUNCTION_ARG_PADDING(MODE, TYPE) \
@@ -120,3 +123,52 @@ Boston, MA 02111-1307, USA. */
#undef PAD_VARARGS_DOWN
#define PAD_VARARGS_DOWN (!AGGREGATE_TYPE_P (type))
+
+#define REGISTER_TARGET_PRAGMAS(PFILE) \
+ cpp_register_pragma (PFILE, 0, "builtin", ia64_hpux_handle_builtin_pragma)
+
+/* Tell ia64.c that we are using the HP linker and we should delay output of
+ function extern declarations so that we don't output them for functions
+ which are never used (and may not be defined). */
+
+#undef TARGET_HPUX_LD
+#define TARGET_HPUX_LD 1
+
+/* Put out the needed function declarations at the end. */
+
+#define ASM_FILE_END(STREAM) ia64_hpux_asm_file_end(STREAM)
+
+#undef CTORS_SECTION_ASM_OP
+#define CTORS_SECTION_ASM_OP "\t.section\t.init_array,\t\"aw\",\"init_array\""
+
+#undef DTORS_SECTION_ASM_OP
+#define DTORS_SECTION_ASM_OP "\t.section\t.fini_array,\t\"aw\",\"fini_array\""
+
+#undef READONLY_DATA_SECTION_ASM_OP
+#define READONLY_DATA_SECTION_ASM_OP "\t.section\t.rodata,\t\"a\",\t\"progbits\""
+
+#undef DATA_SECTION_ASM_OP
+#define DATA_SECTION_ASM_OP "\t.section\t.data,\t\"aw\",\t\"progbits\""
+
+#undef SDATA_SECTION_ASM_OP
+#define SDATA_SECTION_ASM_OP "\t.section\t.sdata,\t\"asw\",\t\"progbits\""
+
+#undef BSS_SECTION_ASM_OP
+#define BSS_SECTION_ASM_OP "\t.section\t.bss,\t\"aw\",\t\"nobits\""
+
+#undef SBSS_SECTION_ASM_OP
+#define SBSS_SECTION_ASM_OP "\t.section\t.sbss,\t\"asw\",\t\"nobits\""
+
+#undef TEXT_SECTION_ASM_OP
+#define TEXT_SECTION_ASM_OP "\t.section\t.text,\t\"ax\",\t\"progbits\""
+
+/* It is illegal to have relocations in shared segments on HPUX.
+ Pretend flag_pic is always set. */
+#undef TARGET_ASM_SELECT_SECTION
+#define TARGET_ASM_SELECT_SECTION ia64_rwreloc_select_section
+#undef TARGET_ASM_UNIQUE_SECTION
+#define TARGET_ASM_UNIQUE_SECTION ia64_rwreloc_unique_section
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION ia64_rwreloc_select_rtx_section
+#undef TARGET_SECTION_TYPE_FLAGS
+#define TARGET_SECTION_TYPE_FLAGS ia64_rwreloc_section_type_flags
diff --git a/contrib/gcc/config/ia64/hpux_longdouble.h b/contrib/gcc/config/ia64/hpux_longdouble.h
index bfc12d4..5333033 100644
--- a/contrib/gcc/config/ia64/hpux_longdouble.h
+++ b/contrib/gcc/config/ia64/hpux_longdouble.h
@@ -18,8 +18,7 @@ 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. */
-/* Tell real.c that we are not using INTEL_EXTENDED_IEEE_FORMAT */
-
+/* We are using IEEE quad precision, not a double-extended with padding. */
#undef INTEL_EXTENDED_IEEE_FORMAT
#define INTEL_EXTENDED_IEEE_FORMAT 0
@@ -42,6 +41,8 @@ Boston, MA 02111-1307, USA. */
#define FLOATDITF2_LIBCALL "_U_Qfcnvxf_dbl_to_quad"
#define FIX_TRUNCTFSI2_LIBCALL "_U_Qfcnvfxt_quad_to_sgl"
#define FIX_TRUNCTFDI2_LIBCALL "_U_Qfcnvfxt_quad_to_dbl"
+#define FIXUNS_TRUNCTFSI2_LIBCALL "_U_Qfcnvfxut_quad_to_sgl"
+#define FIXUNS_TRUNCTFDI2_LIBCALL "_U_Qfcnvfxut_quad_to_dbl"
#define EQTF2_LIBCALL "_U_Qfeq"
#define NETF2_LIBCALL "_U_Qfne"
#define GTTF2_LIBCALL "_U_Qfgt"
@@ -77,8 +78,8 @@ Boston, MA 02111-1307, USA. */
floatditf_libfunc = gen_rtx_SYMBOL_REF (Pmode, FLOATDITF2_LIBCALL); \
fixtfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFSI2_LIBCALL);\
fixtfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFDI2_LIBCALL);\
- fixunstfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFSI2_LIBCALL); \
- fixunstfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFDI2_LIBCALL); \
+ fixunstfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIXUNS_TRUNCTFSI2_LIBCALL); \
+ fixunstfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIXUNS_TRUNCTFDI2_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); \
@@ -86,11 +87,6 @@ Boston, MA 02111-1307, USA. */
lttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, LTTF2_LIBCALL); \
letf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, LETF2_LIBCALL); \
\
- sdiv_optab->handlers[(int) SImode].libfunc = 0; \
- udiv_optab->handlers[(int) SImode].libfunc = 0; \
- smod_optab->handlers[(int) SImode].libfunc = 0; \
- umod_optab->handlers[(int) SImode].libfunc = 0; \
- \
INIT_SUBTARGET_OPTABS; \
} while (0)
diff --git a/contrib/gcc/config/ia64/ia64-c.c b/contrib/gcc/config/ia64/ia64-c.c
new file mode 100644
index 0000000..e44c80b
--- /dev/null
+++ b/contrib/gcc/config/ia64/ia64-c.c
@@ -0,0 +1,191 @@
+/* Definitions of C specific functions for GNU compiler.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by Steve Ellcey <sje@cup.hp.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. */
+
+#include "config.h"
+#include "system.h"
+#include "tree.h"
+#include "cpplib.h"
+#include "c-common.h"
+#include "c-pragma.h"
+#include "toplev.h"
+#include "tm_p.h"
+
+static void ia64_hpux_add_pragma_builtin PARAMS ((tree func));
+
+void
+ia64_hpux_handle_builtin_pragma (pfile)
+ cpp_reader *pfile ATTRIBUTE_UNUSED;
+{
+ /* #pragma builtin name, name, name */
+
+ enum cpp_ttype type;
+ tree x;
+
+ type = c_lex (&x);
+ while (type == CPP_NAME)
+ {
+ ia64_hpux_add_pragma_builtin (x);
+ type = c_lex (&x);
+ if (type == CPP_COMMA)
+ type = c_lex (&x);
+ }
+ if (type != CPP_EOF)
+ warning ("malformed #pragma builtin");
+}
+
+/* List of standard math functions which do not set matherr by default
+ and which have a different version which does set errno and which we
+ want to call *if* we have seen an extern for the routine and we have
+ asked for strict C89 compatibility. */
+
+typedef struct c89_mathlib_names
+{
+ const char *realname; /* User visible function name. */
+ const char *c89name; /* libm special name needed to set errno. */
+} c89_mathlib_names;
+
+static const c89_mathlib_names c89_mathlib_name_list [] =
+{
+ {"acos", "_Acos_e#"},
+ {"acosd", "_Acosd_e#"},
+ {"acosdf", "_Acosdf_e#"},
+ {"acosdl", "_Acosdl_e#"},
+ {"acosdw", "_Acosdw_e#"},
+ {"acosf", "_Acosf_e#"},
+ {"acosh", "_Acosh_e#"},
+ {"acoshf", "_Acoshf_e#"},
+ {"acoshl", "_Acoshl_e#"},
+ {"acoshw", "_Acoshw_e#"},
+ {"acosl", "_Acosl_e#"},
+ {"acosw", "_Acosw_e#"},
+ {"asin", "_Asin_e#"},
+ {"asind", "_Asind_e#"},
+ {"asindf", "_Asindf_e#"},
+ {"asindl", "_Asindl_e#"},
+ {"asindw", "_Asindw_e#"},
+ {"asinf", "_Asinf_e#"},
+ {"asinl", "_Asinl_e#"},
+ {"asinw", "_Asinw_e#"},
+ {"atanh", "_Atanh_e#"},
+ {"atanhf", "_Atanhf_e#"},
+ {"atanhl", "_Atanhl_e#"},
+ {"atanhw", "_Atanhw_e#"},
+ {"cosh", "_Cosh_e#"},
+ {"coshf", "_Coshf_e#"},
+ {"coshl", "_Coshl_e#"},
+ {"coshw", "_Coshw_e#"},
+ {"exp2", "_Exp2_e#"},
+ {"exp2f", "_Exp2f_e#"},
+ {"exp2l", "_Exp2l_e#"},
+ {"exp2w", "_Exp2w_e#"},
+ {"exp", "_Exp_e#"},
+ {"expf", "_Expf_e#"},
+ {"expl", "_Expl_e#"},
+ {"expm1", "_Expm1_e#"},
+ {"expm1f", "_Expm1f_e#"},
+ {"expm1l", "_Expm1l_e#"},
+ {"expm1w", "_Expm1w_e#"},
+ {"expw", "_Expw_e#"},
+ {"fmod", "_Fmod_e#"},
+ {"fmodf", "_Fmodf_e#"},
+ {"fmodl", "_Fmodl_e#"},
+ {"fmodw", "_Fmodw_e#"},
+ {"gamma", "_Gamma_e#"},
+ {"gammaf", "_Gammaf_e#"},
+ {"gammal", "_Gammal_e#"},
+ {"gammaw", "_Gammaw_e#"},
+ {"ldexp", "_Ldexp_e#"},
+ {"ldexpf", "_Ldexpf_e#"},
+ {"ldexpl", "_Ldexpl_e#"},
+ {"ldexpw", "_Ldexpw_e#"},
+ {"lgamma", "_Lgamma_e#"},
+ {"lgammaf", "_Lgammaf_e#"},
+ {"lgammal", "_Lgammal_e#"},
+ {"lgammaw", "_Lgammaw_e#"},
+ {"log10", "_Log10_e#"},
+ {"log10f", "_Log10f_e#"},
+ {"log10l", "_Log10l_e#"},
+ {"log10w", "_Log10w_e#"},
+ {"log1p", "_Log1p_e#"},
+ {"log1pf", "_Log1pf_e#"},
+ {"log1pl", "_Log1pl_e#"},
+ {"log1pw", "_Log1pw_e#"},
+ {"log2", "_Log2_e#"},
+ {"log2f", "_Log2f_e#"},
+ {"log2l", "_Log2l_e#"},
+ {"log2w", "_Log2w_e#"},
+ {"log", "_Log_e#"},
+ {"logb", "_Logb_e#"},
+ {"logbf", "_Logbf_e#"},
+ {"logbl", "_Logbl_e#"},
+ {"logbw", "_Logbw_e#"},
+ {"logf", "_Logf_e#"},
+ {"logl", "_Logl_e#"},
+ {"logw", "_Logw_e#"},
+ {"nextafter", "_Nextafter_e#"},
+ {"nextafterf", "_Nextafterf_e#"},
+ {"nextafterl", "_Nextafterl_e#"},
+ {"nextafterw", "_Nextafterw_e#"},
+ {"pow", "_Pow_e#"},
+ {"powf", "_Powf_e#"},
+ {"powl", "_Powl_e#"},
+ {"poww", "_Poww_e#"},
+ {"remainder", "_Remainder_e#"},
+ {"remainderf", "_Remainderf_e#"},
+ {"remainderl", "_Remainderl_e#"},
+ {"remainderw", "_Remainderw_e#"},
+ {"scalb", "_Scalb_e#"},
+ {"scalbf", "_Scalbf_e#"},
+ {"scalbl", "_Scalbl_e#"},
+ {"scalbw", "_Scalbw_e#"},
+ {"sinh", "_Sinh_e#"},
+ {"sinhf", "_Sinhf_e#"},
+ {"sinhl", "_Sinhl_e#"},
+ {"sinhw", "_Sinhw_e#"},
+ {"sqrt", "_Sqrt_e#"},
+ {"sqrtf", "_Sqrtf_e#"},
+ {"sqrtl", "_Sqrtl_e#"},
+ {"sqrtw", "_Sqrtw_e#"},
+ {"tgamma", "_Tgamma_e#"},
+ {"tgammaf", "_Tgammaf_e#"},
+ {"tgammal", "_Tgammal_e#"},
+ {"tgammaw", "_Tgammaw_e#"}
+};
+
+static void
+ia64_hpux_add_pragma_builtin (func)
+ tree func;
+{
+ size_t i;
+
+ if (!flag_isoc94 && flag_iso)
+ {
+ for (i = 0; i < ARRAY_SIZE (c89_mathlib_name_list); i++)
+ {
+ if (!strcmp(c89_mathlib_name_list[i].realname,
+ IDENTIFIER_POINTER (func)))
+ {
+ add_to_renaming_pragma_list(func,
+ get_identifier(c89_mathlib_name_list[i].c89name));
+ }
+ }
+ }
+}
diff --git a/contrib/gcc/config/ia64/ia64-modes.def b/contrib/gcc/config/ia64/ia64-modes.def
new file mode 100644
index 0000000..0c3eb12
--- /dev/null
+++ b/contrib/gcc/config/ia64/ia64-modes.def
@@ -0,0 +1,29 @@
+/* Definitions of target machine GNU compiler. IA-64 version.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by James E. Wilson <wilson@cygnus.com> and
+ David Mosberger <davidm@hpl.hp.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. */
+
+/* Add any extra modes needed to represent the condition code.
+
+ CCImode is used to mark a single predicate register instead
+ of a register pair. This is currently only used in reg_raw_mode
+ so that flow doesn't do something stupid. */
+
+CC (CCI)
diff --git a/contrib/gcc/config/ia64/ia64-protos.h b/contrib/gcc/config/ia64/ia64-protos.h
index 659adc5..72c2279 100644
--- a/contrib/gcc/config/ia64/ia64-protos.h
+++ b/contrib/gcc/config/ia64/ia64-protos.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler for IA-64.
- Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -21,7 +21,8 @@ Boston, MA 02111-1307, USA. */
/* Variables defined in ia64.c. */
#ifdef RTX_CODE
-extern rtx ia64_compare_op0, ia64_compare_op1;
+extern GTY(()) rtx ia64_compare_op0;
+extern GTY(()) rtx ia64_compare_op1;
#endif
/* Functions defined in ia64.c */
@@ -31,6 +32,7 @@ extern int call_operand PARAMS((rtx, enum machine_mode));
extern int sdata_symbolic_operand PARAMS((rtx, enum machine_mode));
extern int got_symbolic_operand PARAMS((rtx, enum machine_mode));
extern int symbolic_operand PARAMS((rtx, enum machine_mode));
+extern int tls_symbolic_operand PARAMS((rtx, enum machine_mode));
extern int function_operand PARAMS((rtx, enum machine_mode));
extern int setjmp_operand PARAMS((rtx, enum machine_mode));
extern int move_operand PARAMS((rtx, enum machine_mode));
@@ -66,14 +68,18 @@ extern int ar_pfs_reg_operand PARAMS((rtx, enum machine_mode));
extern int general_tfmode_operand PARAMS((rtx, enum machine_mode));
extern int destination_tfmode_operand PARAMS((rtx, enum machine_mode));
extern int tfreg_or_fp01_operand PARAMS((rtx, enum machine_mode));
+extern int basereg_operand PARAMS((rtx, enum machine_mode));
+extern rtx ia64_expand_move PARAMS ((rtx, rtx));
extern int ia64_move_ok PARAMS((rtx, rtx));
+extern int addp4_optimize_ok PARAMS((rtx, rtx));
extern int ia64_depz_field_mask PARAMS((rtx, rtx));
-extern rtx ia64_gp_save_reg PARAMS((int));
extern rtx ia64_split_timode PARAMS((rtx[], rtx, rtx));
extern rtx spill_tfmode_operand PARAMS((rtx, int));
extern rtx ia64_expand_compare PARAMS((enum rtx_code, enum machine_mode));
extern void ia64_expand_call PARAMS((rtx, rtx, rtx, int));
+extern void ia64_split_call PARAMS((rtx, rtx, rtx, rtx, rtx, int, int));
+extern void ia64_reload_gp PARAMS((void));
extern HOST_WIDE_INT ia64_initial_elimination_offset PARAMS((int, int));
extern void ia64_expand_prologue PARAMS((void));
@@ -100,7 +106,6 @@ extern rtx ia64_function_arg PARAMS((CUMULATIVE_ARGS *, enum machine_mode,
tree, int, int));
extern rtx ia64_expand_builtin PARAMS((tree, rtx, rtx,
enum machine_mode, int));
-extern void ia64_va_start PARAMS((int, tree, rtx));
extern rtx ia64_va_arg PARAMS((tree, tree));
extern rtx ia64_function_value PARAMS((tree, tree));
#endif /* RTX_CODE */
@@ -118,8 +123,6 @@ extern int ia64_function_arg_pass_by_reference PARAMS((CUMULATIVE_ARGS *,
tree, int));
extern int ia64_return_in_memory PARAMS((tree));
extern void ia64_asm_output_external PARAMS((FILE *, tree, const char *));
-
-extern void ia64_encode_section_info PARAMS((tree));
#endif /* TREE_CODE */
extern int ia64_register_move_cost PARAMS((enum machine_mode, enum reg_class,
@@ -130,6 +133,7 @@ extern void emit_safe_across_calls PARAMS((FILE *));
extern void ia64_init_builtins PARAMS((void));
extern void ia64_override_options PARAMS((void));
extern int ia64_dbx_register_number PARAMS((int));
+extern bool ia64_function_ok_for_sibcall PARAMS ((tree));
#ifdef SDATA_SECTION_ASM_OP
extern void sdata_section PARAMS ((void));
@@ -143,3 +147,9 @@ extern void sbss_section PARAMS ((void));
/* expr.h defines ARGS_SIZE_RTX and `enum direction'. */
extern enum direction ia64_hpux_function_arg_padding PARAMS ((enum machine_mode, tree));
#endif /* ARGS_SIZE_RTX */
+
+#ifdef GCC_C_PRAGMA_H
+extern void ia64_hpux_handle_builtin_pragma PARAMS ((cpp_reader *));
+#endif
+
+extern void ia64_hpux_asm_file_end PARAMS ((FILE *));
diff --git a/contrib/gcc/config/ia64/ia64.c b/contrib/gcc/config/ia64/ia64.c
index 91dd396..a8b13f9 100644
--- a/contrib/gcc/config/ia64/ia64.c
+++ b/contrib/gcc/config/ia64/ia64.c
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler.
- Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by James E. Wilson <wilson@cygnus.com> and
David Mosberger <davidm@hpl.hp.com>.
@@ -35,7 +35,6 @@ Boston, MA 02111-1307, USA. */
#include "recog.h"
#include "expr.h"
#include "optabs.h"
-#include "obstack.h"
#include "except.h"
#include "function.h"
#include "ggc.h"
@@ -46,6 +45,7 @@ Boston, MA 02111-1307, USA. */
#include "target.h"
#include "target-def.h"
#include "tm_p.h"
+#include "langhooks.h"
/* This is used for communication between ASM_OUTPUT_LABEL and
ASM_OUTPUT_LABELREF. */
@@ -95,6 +95,13 @@ static const char * const ia64_output_reg_names[8] =
/* String used with the -mfixed-range= option. */
const char *ia64_fixed_range_string;
+/* Determines whether we use adds, addl, or movl to generate our
+ TLS immediate offsets. */
+int ia64_tls_size = 22;
+
+/* String used with the -mtls-size= option. */
+const char *ia64_tls_size_string;
+
/* Determines whether we run our final scheduling pass or not. We always
avoid the normal second scheduling pass. */
static int ia64_flag_schedule_insns2;
@@ -103,7 +110,42 @@ static int ia64_flag_schedule_insns2;
sections. */
unsigned int ia64_section_threshold;
+
+/* Structure to be filled in by ia64_compute_frame_size with register
+ save masks and offsets for the current function. */
+
+struct ia64_frame_info
+{
+ HOST_WIDE_INT total_size; /* size of the stack frame, not including
+ the caller's scratch area. */
+ HOST_WIDE_INT spill_cfa_off; /* top of the reg spill area from the cfa. */
+ HOST_WIDE_INT spill_size; /* size of the gr/br/fr spill area. */
+ HOST_WIDE_INT extra_spill_size; /* size of spill area for others. */
+ HARD_REG_SET mask; /* mask of saved registers. */
+ unsigned int gr_used_mask; /* mask of registers in use as gr spill
+ registers or long-term scratches. */
+ int n_spilled; /* number of spilled registers. */
+ int reg_fp; /* register for fp. */
+ int reg_save_b0; /* save register for b0. */
+ int reg_save_pr; /* save register for prs. */
+ int reg_save_ar_pfs; /* save register for ar.pfs. */
+ int reg_save_ar_unat; /* save register for ar.unat. */
+ int reg_save_ar_lc; /* save register for ar.lc. */
+ int reg_save_gp; /* save register for gp. */
+ int n_input_regs; /* number of input registers used. */
+ int n_local_regs; /* number of local registers used. */
+ int n_output_regs; /* number of output registers used. */
+ int n_rotate_regs; /* number of rotating registers used. */
+
+ char need_regstk; /* true if a .regstk directive needed. */
+ char initialized; /* true if the data is finalized. */
+};
+
+/* Current frame information calculated by ia64_compute_frame_size. */
+static struct ia64_frame_info current_frame_info;
+static rtx gen_tls_get_addr PARAMS ((void));
+static rtx gen_thread_pointer PARAMS ((void));
static int find_gr_spill PARAMS ((int));
static int next_scratch_gr_reg PARAMS ((void));
static void mark_reg_gr_used_mask PARAMS ((rtx, void *));
@@ -119,13 +161,13 @@ static rtx gen_fr_restore_x PARAMS ((rtx, rtx, rtx));
static enum machine_mode hfa_element_mode PARAMS ((tree, int));
static void fix_range PARAMS ((const char *));
-static void ia64_add_gc_roots PARAMS ((void));
-static void ia64_init_machine_status PARAMS ((struct function *));
-static void ia64_mark_machine_status PARAMS ((struct function *));
-static void ia64_free_machine_status PARAMS ((struct function *));
+static struct machine_function * ia64_init_machine_status PARAMS ((void));
static void emit_insn_group_barriers PARAMS ((FILE *, rtx));
static void emit_all_insn_group_barriers PARAMS ((FILE *, rtx));
static void emit_predicate_relation_info PARAMS ((void));
+static bool ia64_in_small_data_p PARAMS ((tree));
+static void ia64_encode_section_info PARAMS ((tree, int));
+static const char *ia64_strip_name_encoding PARAMS ((const char *));
static void process_epilogue PARAMS ((void));
static int process_set PARAMS ((FILE *, rtx));
@@ -152,8 +194,26 @@ static int ia64_internal_sched_reorder PARAMS ((FILE *, int, rtx *,
static int ia64_sched_reorder PARAMS ((FILE *, int, rtx *, int *, int));
static int ia64_sched_reorder2 PARAMS ((FILE *, int, rtx *, int *, int));
static int ia64_variable_issue PARAMS ((FILE *, int, rtx, int));
-static rtx ia64_cycle_display PARAMS ((int, rtx));
+static void ia64_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+ HOST_WIDE_INT, tree));
+
+static void ia64_select_rtx_section PARAMS ((enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT));
+static void ia64_rwreloc_select_section PARAMS ((tree, int,
+ unsigned HOST_WIDE_INT))
+ ATTRIBUTE_UNUSED;
+static void ia64_rwreloc_unique_section PARAMS ((tree, int))
+ ATTRIBUTE_UNUSED;
+static void ia64_rwreloc_select_rtx_section PARAMS ((enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT))
+ ATTRIBUTE_UNUSED;
+static unsigned int ia64_rwreloc_section_type_flags
+ PARAMS ((tree, const char *, int))
+ ATTRIBUTE_UNUSED;
+
+static void ia64_hpux_add_extern_decl PARAMS ((const char *name))
+ ATTRIBUTE_UNUSED;
/* Table of valid machine attributes. */
static const struct attribute_spec ia64_attribute_table[] =
@@ -197,6 +257,13 @@ static const struct attribute_spec ia64_attribute_table[] =
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE ia64_output_function_epilogue
+#undef TARGET_IN_SMALL_DATA_P
+#define TARGET_IN_SMALL_DATA_P ia64_in_small_data_p
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO ia64_encode_section_info
+#undef TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING ia64_strip_name_encoding
+
#undef TARGET_SCHED_ADJUST_COST
#define TARGET_SCHED_ADJUST_COST ia64_adjust_cost
#undef TARGET_SCHED_ISSUE_RATE
@@ -211,8 +278,16 @@ static const struct attribute_spec ia64_attribute_table[] =
#define TARGET_SCHED_REORDER ia64_sched_reorder
#undef TARGET_SCHED_REORDER2
#define TARGET_SCHED_REORDER2 ia64_sched_reorder2
-#undef TARGET_SCHED_CYCLE_DISPLAY
-#define TARGET_SCHED_CYCLE_DISPLAY ia64_cycle_display
+
+#ifdef HAVE_AS_TLS
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS true
+#endif
+
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK ia64_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
struct gcc_target targetm = TARGET_INITIALIZER;
@@ -223,7 +298,7 @@ call_operand (op, mode)
rtx op;
enum machine_mode mode;
{
- if (mode != GET_MODE (op))
+ if (mode != GET_MODE (op) && mode != VOIDmode)
return 0;
return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG
@@ -250,7 +325,10 @@ sdata_symbolic_operand (op, mode)
if (CONSTANT_POOL_ADDRESS_P (op))
return GET_MODE_SIZE (get_pool_mode (op)) <= ia64_section_threshold;
else
- return XSTR (op, 0)[0] == SDATA_NAME_FLAG_CHAR;
+ {
+ const char *str = XSTR (op, 0);
+ return (str[0] == ENCODE_SECTION_INFO_CHAR && str[1] == 's');
+ }
default:
break;
@@ -324,6 +402,35 @@ symbolic_operand (op, mode)
return 0;
}
+/* Return tls_model if OP refers to a TLS symbol. */
+
+int
+tls_symbolic_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ const char *str;
+
+ if (GET_CODE (op) != SYMBOL_REF)
+ return 0;
+ str = XSTR (op, 0);
+ if (str[0] != ENCODE_SECTION_INFO_CHAR)
+ return 0;
+ switch (str[1])
+ {
+ case 'G':
+ return TLS_MODEL_GLOBAL_DYNAMIC;
+ case 'L':
+ return TLS_MODEL_LOCAL_DYNAMIC;
+ case 'i':
+ return TLS_MODEL_INITIAL_EXEC;
+ case 'l':
+ return TLS_MODEL_LOCAL_EXEC;
+ }
+ return 0;
+}
+
+
/* Return 1 if OP refers to a function. */
int
@@ -864,6 +971,21 @@ tfreg_or_fp01_operand (op, mode)
return 0;
return fr_reg_or_fp01_operand (op, mode);
}
+
+/* Return 1 if OP is valid as a base register in a reg + offset address. */
+
+int
+basereg_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ /* ??? Should I copy the flag_omit_frame_pointer and cse_not_expected
+ checks from pa.c basereg_operand as well? Seems to be OK without them
+ in test runs. */
+
+ return (register_operand (op, mode) &&
+ REG_POINTER ((GET_CODE (op) == SUBREG) ? SUBREG_REG (op) : op));
+}
/* Return 1 if the operands of a move are ok. */
@@ -889,6 +1011,21 @@ ia64_move_ok (dst, src)
return GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src);
}
+/* Return 0 if we are doing C++ code. This optimization fails with
+ C++ because of GNAT c++/6685. */
+
+int
+addp4_optimize_ok (op1, op2)
+ rtx op1, op2;
+{
+
+ if (!strcmp (lang_hooks.name, "GNU C++"))
+ return 0;
+
+ return (basereg_operand (op1, GET_MODE(op1)) !=
+ basereg_operand (op2, GET_MODE(op2)));
+}
+
/* Check if OP is a mask suitible for use with SHIFT in a dep.z instruction.
Return the length of the field, or <= 0 on failure. */
@@ -918,15 +1055,22 @@ ia64_expand_load_address (dest, src, scratch)
/* The destination could be a MEM during initial rtl generation,
which isn't a valid destination for the PIC load address patterns. */
if (! register_operand (dest, DImode))
- temp = gen_reg_rtx (DImode);
+ if (! scratch || ! register_operand (scratch, DImode))
+ temp = gen_reg_rtx (DImode);
+ else
+ temp = scratch;
else
temp = dest;
+ if (tls_symbolic_operand (src, Pmode))
+ abort ();
+
if (TARGET_AUTO_PIC)
emit_insn (gen_load_gprel64 (temp, src));
else if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_FLAG (src))
emit_insn (gen_load_fptr (temp, src));
- else if (sdata_symbolic_operand (src, DImode))
+ else if ((GET_MODE (src) == Pmode || GET_MODE (src) == ptr_mode)
+ && sdata_symbolic_operand (src, VOIDmode))
emit_insn (gen_load_gprel (temp, src));
else if (GET_CODE (src) == CONST
&& GET_CODE (XEXP (src, 0)) == PLUS
@@ -957,51 +1101,201 @@ ia64_expand_load_address (dest, src, scratch)
scratch = no_new_pseudos ? temp : gen_reg_rtx (DImode);
insn = emit_insn (gen_load_symptr (temp, src, scratch));
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE (temp) != GET_MODE (src))
+ src = convert_memory_address (GET_MODE (temp), src);
+#endif
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, src, REG_NOTES (insn));
}
if (temp != dest)
- emit_move_insn (dest, temp);
+ {
+ if (GET_MODE (dest) != GET_MODE (temp))
+ temp = convert_to_mode (GET_MODE (dest), temp, 0);
+ emit_move_insn (dest, temp);
+ }
}
-rtx
-ia64_gp_save_reg (setjmp_p)
- int setjmp_p;
-{
- rtx save = cfun->machine->ia64_gp_save;
-
- if (save != NULL)
- {
- /* We can't save GP in a pseudo if we are calling setjmp, because
- pseudos won't be restored by longjmp. For now, we save it in r4. */
- /* ??? It would be more efficient to save this directly into a stack
- slot. Unfortunately, the stack slot address gets cse'd across
- the setjmp call because the NOTE_INSN_SETJMP note is in the wrong
- place. */
-
- /* ??? Get the barf bag, Virginia. We've got to replace this thing
- in place, since this rtx is used in exception handling receivers.
- Moreover, we must get this rtx out of regno_reg_rtx or reload
- will do the wrong thing. */
- unsigned int old_regno = REGNO (save);
- if (setjmp_p && old_regno != GR_REG (4))
- {
- REGNO (save) = GR_REG (4);
- regno_reg_rtx[old_regno] = gen_rtx_raw_REG (DImode, old_regno);
- }
+static GTY(()) rtx gen_tls_tga;
+static rtx
+gen_tls_get_addr ()
+{
+ if (!gen_tls_tga)
+ {
+ gen_tls_tga = init_one_libfunc ("__tls_get_addr");
+ }
+ return gen_tls_tga;
+}
+
+static GTY(()) rtx thread_pointer_rtx;
+static rtx
+gen_thread_pointer ()
+{
+ if (!thread_pointer_rtx)
+ {
+ thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
+ RTX_UNCHANGING_P (thread_pointer_rtx) = 1;
}
- else
+ return thread_pointer_rtx;
+}
+
+rtx
+ia64_expand_move (op0, op1)
+ rtx op0, op1;
+{
+ enum machine_mode mode = GET_MODE (op0);
+
+ if (!reload_in_progress && !reload_completed && !ia64_move_ok (op0, op1))
+ op1 = force_reg (mode, op1);
+
+ if (mode == Pmode || mode == ptr_mode)
{
- if (setjmp_p)
- save = gen_rtx_REG (DImode, GR_REG (4));
- else if (! optimize)
- save = gen_rtx_REG (DImode, LOC_REG (0));
- else
- save = gen_reg_rtx (DImode);
- cfun->machine->ia64_gp_save = save;
+ enum tls_model tls_kind;
+ if ((tls_kind = tls_symbolic_operand (op1, Pmode)))
+ {
+ rtx tga_op1, tga_op2, tga_ret, tga_eqv, tmp, insns;
+
+ switch (tls_kind)
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ start_sequence ();
+
+ tga_op1 = gen_reg_rtx (Pmode);
+ emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
+ tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
+ RTX_UNCHANGING_P (tga_op1) = 1;
+
+ tga_op2 = gen_reg_rtx (Pmode);
+ emit_insn (gen_load_ltoff_dtprel (tga_op2, op1));
+ tga_op2 = gen_rtx_MEM (Pmode, tga_op2);
+ RTX_UNCHANGING_P (tga_op2) = 1;
+
+ tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
+ LCT_CONST, Pmode, 2, tga_op1,
+ Pmode, tga_op2, Pmode);
+
+ insns = get_insns ();
+ end_sequence ();
+
+ emit_libcall_block (insns, op0, tga_ret, op1);
+ return NULL_RTX;
+
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ /* ??? This isn't the completely proper way to do local-dynamic
+ If the call to __tls_get_addr is used only by a single symbol,
+ then we should (somehow) move the dtprel to the second arg
+ to avoid the extra add. */
+ start_sequence ();
+
+ tga_op1 = gen_reg_rtx (Pmode);
+ emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
+ tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
+ RTX_UNCHANGING_P (tga_op1) = 1;
+
+ tga_op2 = const0_rtx;
+
+ tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
+ LCT_CONST, Pmode, 2, tga_op1,
+ Pmode, tga_op2, Pmode);
+
+ insns = get_insns ();
+ end_sequence ();
+
+ tga_eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
+ UNSPEC_LD_BASE);
+ tmp = gen_reg_rtx (Pmode);
+ emit_libcall_block (insns, tmp, tga_ret, tga_eqv);
+
+ if (register_operand (op0, Pmode))
+ tga_ret = op0;
+ else
+ tga_ret = gen_reg_rtx (Pmode);
+ if (TARGET_TLS64)
+ {
+ emit_insn (gen_load_dtprel (tga_ret, op1));
+ emit_insn (gen_adddi3 (tga_ret, tmp, tga_ret));
+ }
+ else
+ emit_insn (gen_add_dtprel (tga_ret, tmp, op1));
+ if (tga_ret == op0)
+ return NULL_RTX;
+ op1 = tga_ret;
+ break;
+
+ case TLS_MODEL_INITIAL_EXEC:
+ tmp = gen_reg_rtx (Pmode);
+ emit_insn (gen_load_ltoff_tprel (tmp, op1));
+ tmp = gen_rtx_MEM (Pmode, tmp);
+ RTX_UNCHANGING_P (tmp) = 1;
+ tmp = force_reg (Pmode, tmp);
+
+ if (register_operand (op0, Pmode))
+ op1 = op0;
+ else
+ op1 = gen_reg_rtx (Pmode);
+ emit_insn (gen_adddi3 (op1, tmp, gen_thread_pointer ()));
+ if (op1 == op0)
+ return NULL_RTX;
+ break;
+
+ case TLS_MODEL_LOCAL_EXEC:
+ if (register_operand (op0, Pmode))
+ tmp = op0;
+ else
+ tmp = gen_reg_rtx (Pmode);
+ if (TARGET_TLS64)
+ {
+ emit_insn (gen_load_tprel (tmp, op1));
+ emit_insn (gen_adddi3 (tmp, gen_thread_pointer (), tmp));
+ }
+ else
+ emit_insn (gen_add_tprel (tmp, gen_thread_pointer (), op1));
+ if (tmp == op0)
+ return NULL_RTX;
+ op1 = tmp;
+ break;
+
+ default:
+ abort ();
+ }
+ }
+ else if (!TARGET_NO_PIC &&
+ (symbolic_operand (op1, Pmode) ||
+ symbolic_operand (op1, ptr_mode)))
+ {
+ /* Before optimization starts, delay committing to any particular
+ type of PIC address load. If this function gets deferred, we
+ may acquire information that changes the value of the
+ sdata_symbolic_operand predicate.
+
+ But don't delay for function pointers. Loading a function address
+ actually loads the address of the descriptor not the function.
+ If we represent these as SYMBOL_REFs, then they get cse'd with
+ calls, and we end up with calls to the descriptor address instead
+ of calls to the function address. Functions are not candidates
+ for sdata anyways.
+
+ Don't delay for LABEL_REF because the splitter loses REG_LABEL
+ notes. Don't delay for pool addresses on general principals;
+ they'll never become non-local behind our back. */
+
+ if (rtx_equal_function_value_matters
+ && GET_CODE (op1) != LABEL_REF
+ && ! (GET_CODE (op1) == SYMBOL_REF
+ && (SYMBOL_REF_FLAG (op1)
+ || CONSTANT_POOL_ADDRESS_P (op1)
+ || STRING_POOL_ADDRESS_P (op1))))
+ if (GET_MODE (op1) == DImode)
+ emit_insn (gen_movdi_symbolic (op0, op1));
+ else
+ emit_insn (gen_movsi_symbolic (op0, op1));
+ else
+ ia64_expand_load_address (op0, op1, NULL_RTX);
+ return NULL_RTX;
+ }
}
- return save;
+ return op1;
}
/* Split a post-reload TImode reference into two DImode components. */
@@ -1089,12 +1383,12 @@ spill_tfmode_operand (in, force)
&& GET_MODE (SUBREG_REG (in)) == TImode
&& GET_CODE (SUBREG_REG (in)) == REG)
{
- rtx mem = gen_mem_addressof (SUBREG_REG (in), NULL_TREE);
+ rtx mem = gen_mem_addressof (SUBREG_REG (in), NULL_TREE, true);
return gen_rtx_MEM (TFmode, copy_to_reg (XEXP (mem, 0)));
}
else if (force && GET_CODE (in) == REG)
{
- rtx mem = gen_mem_addressof (in, NULL_TREE);
+ rtx mem = gen_mem_addressof (in, NULL_TREE, true);
return gen_rtx_MEM (TFmode, copy_to_reg (XEXP (mem, 0)));
}
else if (GET_CODE (in) == MEM
@@ -1136,72 +1430,151 @@ ia64_expand_compare (code, mode)
}
/* Emit the appropriate sequence for a call. */
-
void
ia64_expand_call (retval, addr, nextarg, sibcall_p)
rtx retval;
rtx addr;
- rtx nextarg;
+ rtx nextarg ATTRIBUTE_UNUSED;
int sibcall_p;
{
- rtx insn, b0, pfs, gp_save, narg_rtx, dest;
- bool indirect_p;
- int narg;
+ rtx insn, b0;
addr = XEXP (addr, 0);
b0 = gen_rtx_REG (DImode, R_BR (0));
- pfs = gen_rtx_REG (DImode, AR_PFS_REGNUM);
-
- if (! nextarg)
- narg = 0;
- else if (IN_REGNO_P (REGNO (nextarg)))
- narg = REGNO (nextarg) - IN_REG (0);
- else
- narg = REGNO (nextarg) - OUT_REG (0);
- narg_rtx = GEN_INT (narg);
+ /* ??? Should do this for functions known to bind local too. */
if (TARGET_NO_PIC || TARGET_AUTO_PIC)
{
if (sibcall_p)
- insn = gen_sibcall_nopic (addr, narg_rtx, b0, pfs);
+ insn = gen_sibcall_nogp (addr);
else if (! retval)
- insn = gen_call_nopic (addr, narg_rtx, b0);
+ insn = gen_call_nogp (addr, b0);
else
- insn = gen_call_value_nopic (retval, addr, narg_rtx, b0);
- emit_call_insn (insn);
- return;
+ insn = gen_call_value_nogp (retval, addr, b0);
+ insn = emit_call_insn (insn);
}
-
- indirect_p = ! symbolic_operand (addr, VOIDmode);
-
- if (sibcall_p || (TARGET_CONST_GP && !indirect_p))
- gp_save = NULL_RTX;
else
- gp_save = ia64_gp_save_reg (setjmp_operand (addr, VOIDmode));
+ {
+ if (sibcall_p)
+ insn = gen_sibcall_gp (addr);
+ else if (! retval)
+ insn = gen_call_gp (addr, b0);
+ else
+ insn = gen_call_value_gp (retval, addr, b0);
+ insn = emit_call_insn (insn);
- if (gp_save)
- emit_move_insn (gp_save, pic_offset_table_rtx);
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
+ }
- /* If this is an indirect call, then we have the address of a descriptor. */
- if (indirect_p)
+ if (sibcall_p)
{
- dest = force_reg (DImode, gen_rtx_MEM (DImode, addr));
- emit_move_insn (pic_offset_table_rtx,
- gen_rtx_MEM (DImode, plus_constant (addr, 8)));
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), b0);
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn),
+ gen_rtx_REG (DImode, AR_PFS_REGNUM));
}
+}
+void
+ia64_reload_gp ()
+{
+ rtx tmp;
+
+ if (current_frame_info.reg_save_gp)
+ tmp = gen_rtx_REG (DImode, current_frame_info.reg_save_gp);
else
- dest = addr;
+ {
+ HOST_WIDE_INT offset;
+
+ offset = (current_frame_info.spill_cfa_off
+ + current_frame_info.spill_size);
+ if (frame_pointer_needed)
+ {
+ tmp = hard_frame_pointer_rtx;
+ offset = -offset;
+ }
+ else
+ {
+ tmp = stack_pointer_rtx;
+ offset = current_frame_info.total_size - offset;
+ }
+
+ if (CONST_OK_FOR_I (offset))
+ emit_insn (gen_adddi3 (pic_offset_table_rtx,
+ tmp, GEN_INT (offset)));
+ else
+ {
+ emit_move_insn (pic_offset_table_rtx, GEN_INT (offset));
+ emit_insn (gen_adddi3 (pic_offset_table_rtx,
+ pic_offset_table_rtx, tmp));
+ }
+
+ tmp = gen_rtx_MEM (DImode, pic_offset_table_rtx);
+ }
+
+ emit_move_insn (pic_offset_table_rtx, tmp);
+}
+
+void
+ia64_split_call (retval, addr, retaddr, scratch_r, scratch_b,
+ noreturn_p, sibcall_p)
+ rtx retval, addr, retaddr, scratch_r, scratch_b;
+ int noreturn_p, sibcall_p;
+{
+ rtx insn;
+ bool is_desc = false;
+
+ /* If we find we're calling through a register, then we're actually
+ calling through a descriptor, so load up the values. */
+ if (REG_P (addr))
+ {
+ rtx tmp;
+ bool addr_dead_p;
+
+ /* ??? We are currently constrained to *not* use peep2, because
+ we can legitimiately change the global lifetime of the GP
+ (in the form of killing where previously live). This is
+ because a call through a descriptor doesn't use the previous
+ value of the GP, while a direct call does, and we do not
+ commit to either form until the split here.
+
+ That said, this means that we lack precise life info for
+ whether ADDR is dead after this call. This is not terribly
+ important, since we can fix things up essentially for free
+ with the POST_DEC below, but it's nice to not use it when we
+ can immediately tell it's not necessary. */
+ addr_dead_p = ((noreturn_p || sibcall_p
+ || TEST_HARD_REG_BIT (regs_invalidated_by_call,
+ REGNO (addr)))
+ && !FUNCTION_ARG_REGNO_P (REGNO (addr)));
+
+ /* Load the code address into scratch_b. */
+ tmp = gen_rtx_POST_INC (Pmode, addr);
+ tmp = gen_rtx_MEM (Pmode, tmp);
+ emit_move_insn (scratch_r, tmp);
+ emit_move_insn (scratch_b, scratch_r);
+
+ /* Load the GP address. If ADDR is not dead here, then we must
+ revert the change made above via the POST_INCREMENT. */
+ if (!addr_dead_p)
+ tmp = gen_rtx_POST_DEC (Pmode, addr);
+ else
+ tmp = addr;
+ tmp = gen_rtx_MEM (Pmode, tmp);
+ emit_move_insn (pic_offset_table_rtx, tmp);
+
+ is_desc = true;
+ addr = scratch_b;
+ }
if (sibcall_p)
- insn = gen_sibcall_pic (dest, narg_rtx, b0, pfs);
- else if (! retval)
- insn = gen_call_pic (dest, narg_rtx, b0);
+ insn = gen_sibcall_nogp (addr);
+ else if (retval)
+ insn = gen_call_value_nogp (retval, addr, retaddr);
else
- insn = gen_call_value_pic (retval, dest, narg_rtx, b0);
+ insn = gen_call_nogp (addr, retaddr);
emit_call_insn (insn);
- if (gp_save)
- emit_move_insn (pic_offset_table_rtx, gp_save);
+ if ((!TARGET_CONST_GP || is_desc) && !noreturn_p && !sibcall_p)
+ ia64_reload_gp ();
}
/* Begin the assembly file. */
@@ -1240,39 +1613,6 @@ emit_safe_across_calls (f)
fputc ('\n', f);
}
-
-/* Structure to be filled in by ia64_compute_frame_size with register
- save masks and offsets for the current function. */
-
-struct ia64_frame_info
-{
- HOST_WIDE_INT total_size; /* size of the stack frame, not including
- the caller's scratch area. */
- HOST_WIDE_INT spill_cfa_off; /* top of the reg spill area from the cfa. */
- HOST_WIDE_INT spill_size; /* size of the gr/br/fr spill area. */
- HOST_WIDE_INT extra_spill_size; /* size of spill area for others. */
- HARD_REG_SET mask; /* mask of saved registers. */
- unsigned int gr_used_mask; /* mask of registers in use as gr spill
- registers or long-term scratches. */
- int n_spilled; /* number of spilled registers. */
- int reg_fp; /* register for fp. */
- int reg_save_b0; /* save register for b0. */
- int reg_save_pr; /* save register for prs. */
- int reg_save_ar_pfs; /* save register for ar.pfs. */
- int reg_save_ar_unat; /* save register for ar.unat. */
- int reg_save_ar_lc; /* save register for ar.lc. */
- int n_input_regs; /* number of input registers used. */
- int n_local_regs; /* number of local registers used. */
- int n_output_regs; /* number of output registers used. */
- int n_rotate_regs; /* number of rotating registers used. */
-
- char need_regstk; /* true if a .regstk directive needed. */
- char initialized; /* true if the data is finalized. */
-};
-
-/* Current frame information calculated by ia64_compute_frame_size. */
-static struct ia64_frame_info current_frame_info;
-
/* Helper function for ia64_compute_frame_size: find an appropriate general
register to spill some special register to. SPECIAL_SPILL_MASK contains
bits in GR0 to GR31 that have already been allocated by this routine.
@@ -1514,6 +1854,17 @@ ia64_compute_frame_size (size)
extra_spill_size += 8;
n_spilled += 1;
}
+
+ /* Similarly for gp. Note that if we're calling setjmp, the stacked
+ registers are clobbered, so we fall back to the stack. */
+ current_frame_info.reg_save_gp
+ = (current_function_calls_setjmp ? 0 : find_gr_spill (1));
+ if (current_frame_info.reg_save_gp == 0)
+ {
+ SET_HARD_REG_BIT (mask, GR_REG (1));
+ spill_size += 8;
+ n_spilled += 1;
+ }
}
else
{
@@ -1523,6 +1874,17 @@ ia64_compute_frame_size (size)
spill_size += 8;
n_spilled += 1;
}
+
+ if (regs_ever_live[AR_PFS_REGNUM])
+ {
+ SET_HARD_REG_BIT (mask, AR_PFS_REGNUM);
+ current_frame_info.reg_save_ar_pfs = find_gr_spill (1);
+ if (current_frame_info.reg_save_ar_pfs == 0)
+ {
+ extra_spill_size += 8;
+ n_spilled += 1;
+ }
+ }
}
/* Unwind descriptor hackery: things are most efficient if we allocate
@@ -1561,8 +1923,10 @@ ia64_compute_frame_size (size)
}
/* If we're forced to use st8.spill, we're forced to save and restore
- ar.unat as well. */
- if (spilled_gr_p || cfun->machine->n_varargs)
+ ar.unat as well. The check for existing liveness allows inline asm
+ to touch ar.unat. */
+ if (spilled_gr_p || cfun->machine->n_varargs
+ || regs_ever_live[AR_UNAT_REGNUM])
{
regs_ever_live[AR_UNAT_REGNUM] = 1;
SET_HARD_REG_BIT (mask, AR_UNAT_REGNUM);
@@ -1796,7 +2160,7 @@ spill_restore_mem (reg, cfa_off)
spill_fill_data.init_reg[iter],
disp_rtx));
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
}
@@ -2023,7 +2387,8 @@ ia64_expand_prologue ()
/* We don't need an alloc instruction if we've used no outputs or locals. */
if (current_frame_info.n_local_regs == 0
&& current_frame_info.n_output_regs == 0
- && current_frame_info.n_input_regs <= current_function_args_info.int_regs)
+ && current_frame_info.n_input_regs <= current_function_args_info.int_regs
+ && !TEST_HARD_REG_BIT (current_frame_info.mask, AR_PFS_REGNUM))
{
/* If there is no alloc, but there are input registers used, then we
need a .regstk directive. */
@@ -2185,8 +2550,8 @@ ia64_expand_prologue ()
/* The alloc insn already copied ar.pfs into a general register. The
only thing we have to do now is copy that register to a stack slot
if we'd not allocated a local register for the job. */
- if (current_frame_info.reg_save_ar_pfs == 0
- && ! current_function_is_leaf)
+ if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_PFS_REGNUM)
+ && current_frame_info.reg_save_ar_pfs == 0)
{
reg = gen_rtx_REG (DImode, AR_PFS_REGNUM);
do_spill (gen_movdi_x, ar_pfs_save_reg, cfa_off, reg);
@@ -2217,6 +2582,19 @@ ia64_expand_prologue ()
}
}
+ if (current_frame_info.reg_save_gp)
+ {
+ insn = emit_move_insn (gen_rtx_REG (DImode,
+ current_frame_info.reg_save_gp),
+ pic_offset_table_rtx);
+ /* We don't know for sure yet if this is actually needed, since
+ we've not split the PIC call patterns. If all of the calls
+ are indirect, and not followed by any uses of the gp, then
+ this save is dead. Allow it to go away. */
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, REG_NOTES (insn));
+ }
+
/* We should now be at the base of the gr/br/fr spill area. */
if (cfa_off != (current_frame_info.spill_cfa_off
+ current_frame_info.spill_size))
@@ -2398,8 +2776,13 @@ ia64_expand_epilogue (sibcall_p)
+ current_frame_info.spill_size))
abort ();
+ /* The GP may be stored on the stack in the prologue, but it's
+ never restored in the epilogue. Skip the stack slot. */
+ if (TEST_HARD_REG_BIT (current_frame_info.mask, GR_REG (1)))
+ cfa_off -= 8;
+
/* Restore all general registers. */
- for (regno = GR_REG (1); regno <= GR_REG (31); ++regno)
+ for (regno = GR_REG (2); regno <= GR_REG (31); ++regno)
if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
{
reg = gen_rtx_REG (DImode, regno);
@@ -2587,10 +2970,6 @@ ia64_hard_regno_rename_ok (from, to)
if (PR_REGNO_P (from) && PR_REGNO_P (to))
return (from & 1) == (to & 1);
- /* Reg 4 contains the saved gp; we can't reliably rename this. */
- if (from == GR_REG (4) && current_function_calls_setjmp)
- return 0;
-
return 1;
}
@@ -2603,12 +2982,16 @@ ia64_assemble_integer (x, size, aligned_p)
unsigned int size;
int aligned_p;
{
- if (size == UNITS_PER_WORD && aligned_p
+ if (size == (TARGET_ILP32 ? 4 : 8)
+ && aligned_p
&& !(TARGET_NO_PIC || TARGET_AUTO_PIC)
&& GET_CODE (x) == SYMBOL_REF
&& SYMBOL_REF_FLAG (x))
{
- fputs ("\tdata8\t@fptr(", asm_out_file);
+ if (TARGET_ILP32)
+ fputs ("\tdata4\t@fptr(", asm_out_file);
+ else
+ fputs ("\tdata8\t@fptr(", asm_out_file);
output_addr_const (asm_out_file, x);
fputs (")\n", asm_out_file);
return true;
@@ -2796,9 +3179,8 @@ ia64_setup_incoming_varargs (cum, int_mode, type, pretend_size, second_time)
int * pretend_size;
int second_time ATTRIBUTE_UNUSED;
{
- /* If this is a stdarg function, then skip the current argument. */
- if (! current_function_varargs)
- ia64_function_arg_advance (&cum, int_mode, type, 1);
+ /* Skip the current argument. */
+ ia64_function_arg_advance (&cum, int_mode, type, 1);
if (cum.words < MAX_ARGUMENT_SLOTS)
{
@@ -2840,17 +3222,17 @@ hfa_element_mode (type, nested)
gcc's COMPLEX_TYPEs as HFAs. We need to exclude the integral complex
types though. */
case COMPLEX_TYPE:
- if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_FLOAT)
+ if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_FLOAT
+ && (TYPE_MODE (type) != TCmode || INTEL_EXTENDED_IEEE_FORMAT))
return mode_for_size (GET_MODE_UNIT_SIZE (TYPE_MODE (type))
* BITS_PER_UNIT, MODE_FLOAT, 0);
else
return VOIDmode;
case REAL_TYPE:
- /* ??? Should exclude 128-bit long double here. */
/* We want to return VOIDmode for raw REAL_TYPEs, but the actual
mode if this is contained within an aggregate. */
- if (nested)
+ if (nested && (TYPE_MODE (type) != TFmode || INTEL_EXTENDED_IEEE_FORMAT))
return TYPE_MODE (type);
else
return VOIDmode;
@@ -3024,7 +3406,25 @@ ia64_function_arg (cum, mode, type, named, incoming)
happen when we have a SFmode HFA. */
else if (((mode == TFmode) && ! INTEL_EXTENDED_IEEE_FORMAT)
|| (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
- return gen_rtx_REG (mode, basereg + cum->words + offset);
+ {
+ int byte_size = ((mode == BLKmode)
+ ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
+ if (BYTES_BIG_ENDIAN
+ && (mode == BLKmode || (type && AGGREGATE_TYPE_P (type)))
+ && byte_size < UNITS_PER_WORD
+ && byte_size > 0)
+ {
+ rtx gr_reg = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (DImode,
+ (basereg + cum->words
+ + offset)),
+ const0_rtx);
+ return gen_rtx_PARALLEL (mode, gen_rtvec (1, gr_reg));
+ }
+ else
+ return gen_rtx_REG (mode, basereg + cum->words + offset);
+
+ }
/* If there is a prototype, then FP values go in a FR register when
named, and in a GR registeer when unnamed. */
@@ -3199,27 +3599,6 @@ ia64_function_arg_pass_by_reference (cum, mode, type, named)
return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
}
-/* Implement va_start. */
-
-void
-ia64_va_start (stdarg_p, valist, nextarg)
- int stdarg_p;
- tree valist;
- rtx nextarg;
-{
- int arg_words;
- int ofs;
-
- arg_words = current_function_args_info.words;
-
- if (stdarg_p)
- ofs = 0;
- else
- ofs = (arg_words >= MAX_ARGUMENT_SLOTS ? -UNITS_PER_WORD : 0);
-
- nextarg = plus_constant (nextarg, ofs);
- std_expand_builtin_va_start (1, valist, nextarg);
-}
/* Implement va_arg. */
@@ -3332,7 +3711,30 @@ ia64_function_value (valtype, func)
((mode != TFmode) || INTEL_EXTENDED_IEEE_FORMAT))
return gen_rtx_REG (mode, FR_ARG_FIRST);
else
- return gen_rtx_REG (mode, GR_RET_FIRST);
+ {
+ if (BYTES_BIG_ENDIAN
+ && (mode == BLKmode || (valtype && AGGREGATE_TYPE_P (valtype))))
+ {
+ rtx loc[8];
+ int offset;
+ int bytesize;
+ int i;
+
+ offset = 0;
+ bytesize = int_size_in_bytes (valtype);
+ for (i = 0; offset < bytesize; i++)
+ {
+ loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (DImode,
+ GR_RET_FIRST + i),
+ GEN_INT (offset));
+ offset += UNITS_PER_WORD;
+ }
+ return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
+ }
+ else
+ return gen_rtx_REG (mode, GR_RET_FIRST);
+ }
}
/* Print a memory address as an operand to reference that memory location. */
@@ -3777,7 +4179,6 @@ ia64_secondary_reload_class (class, mode, x)
return NO_REGS;
}
-
/* Emit text to declare externally defined variables and functions, because
the Intel assembler does not support undefined externals. */
@@ -3790,8 +4191,13 @@ ia64_asm_output_external (file, decl, name)
{
int save_referenced;
- /* GNU as does not need anything here. */
- if (TARGET_GNU_AS)
+ /* GNU as does not need anything here, but the HP linker does need
+ something for external functions. */
+
+ if (TARGET_GNU_AS
+ && (!TARGET_HPUX_LD
+ || TREE_CODE (decl) != FUNCTION_DECL
+ || strstr(name, "__builtin_") == name))
return;
/* ??? The Intel assembler creates a reference that needs to be satisfied by
@@ -3806,19 +4212,18 @@ ia64_asm_output_external (file, decl, name)
|| ! strcmp (name, "__builtin_args_info"))
return;
- /* assemble_name will set TREE_SYMBOL_REFERENCED, so we must save and
- restore it. */
- save_referenced = TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl));
- if (TREE_CODE (decl) == FUNCTION_DECL)
+ if (TARGET_HPUX_LD)
+ ia64_hpux_add_extern_decl (name);
+ else
{
- fprintf (file, "%s", TYPE_ASM_OP);
- assemble_name (file, name);
- putc (',', file);
- fprintf (file, TYPE_OPERAND_FMT, "function");
- putc ('\n', file);
+ /* assemble_name will set TREE_SYMBOL_REFERENCED, so we must save and
+ restore it. */
+ save_referenced = TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl));
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
+ (*targetm.asm_out.globalize_label) (file, name);
+ TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = save_referenced;
}
- ASM_GLOBALIZE_LABEL (file, name);
- TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = save_referenced;
}
/* Parse the -mfixed-range= option string. */
@@ -3887,44 +4292,10 @@ fix_range (const_str)
}
}
-/* Called to register all of our global variables with the garbage
- collector. */
-
-static void
-ia64_add_gc_roots ()
-{
- ggc_add_rtx_root (&ia64_compare_op0, 1);
- ggc_add_rtx_root (&ia64_compare_op1, 1);
-}
-
-static void
-ia64_init_machine_status (p)
- struct function *p;
-{
- p->machine =
- (struct machine_function *) xcalloc (1, sizeof (struct machine_function));
-}
-
-static void
-ia64_mark_machine_status (p)
- struct function *p;
-{
- struct machine_function *machine = p->machine;
-
- if (machine)
- {
- ggc_mark_rtx (machine->ia64_eh_epilogue_sp);
- ggc_mark_rtx (machine->ia64_eh_epilogue_bsp);
- ggc_mark_rtx (machine->ia64_gp_save);
- }
-}
-
-static void
-ia64_free_machine_status (p)
- struct function *p;
+static struct machine_function *
+ia64_init_machine_status ()
{
- free (p->machine);
- p->machine = NULL;
+ return ggc_alloc_cleared (sizeof (struct machine_function));
}
/* Handle TARGET_OPTIONS switches. */
@@ -3935,25 +4306,41 @@ ia64_override_options ()
if (TARGET_AUTO_PIC)
target_flags |= MASK_CONST_GP;
- if (TARGET_INLINE_DIV_LAT && TARGET_INLINE_DIV_THR)
+ if (TARGET_INLINE_FLOAT_DIV_LAT && TARGET_INLINE_FLOAT_DIV_THR)
+ {
+ warning ("cannot optimize floating point division for both latency and throughput");
+ target_flags &= ~MASK_INLINE_FLOAT_DIV_THR;
+ }
+
+ if (TARGET_INLINE_INT_DIV_LAT && TARGET_INLINE_INT_DIV_THR)
{
- warning ("cannot optimize division for both latency and throughput");
- target_flags &= ~MASK_INLINE_DIV_THR;
+ warning ("cannot optimize integer division for both latency and throughput");
+ target_flags &= ~MASK_INLINE_INT_DIV_THR;
}
if (ia64_fixed_range_string)
fix_range (ia64_fixed_range_string);
+ if (ia64_tls_size_string)
+ {
+ char *end;
+ unsigned long tmp = strtoul (ia64_tls_size_string, &end, 10);
+ if (*end || (tmp != 14 && tmp != 22 && tmp != 64))
+ error ("bad value (%s) for -mtls-size= switch", ia64_tls_size_string);
+ else
+ ia64_tls_size = tmp;
+ }
+
ia64_flag_schedule_insns2 = flag_schedule_insns_after_reload;
flag_schedule_insns_after_reload = 0;
ia64_section_threshold = g_switch_set ? g_switch_value : IA64_DEFAULT_GVALUE;
init_machine_status = ia64_init_machine_status;
- mark_machine_status = ia64_mark_machine_status;
- free_machine_status = ia64_free_machine_status;
- ia64_add_gc_roots ();
+ /* Tell the compiler which flavor of TFmode we're using. */
+ if (INTEL_EXTENDED_IEEE_FORMAT)
+ real_format_for_mode[TFmode - QFmode] = &ieee_extended_intel_128_format;
}
static enum attr_itanium_requires_unit0 ia64_safe_itanium_requires_unit0 PARAMS((rtx));
@@ -4564,8 +4951,22 @@ rtx_needs_barrier (x, flags, pred)
case UNSPEC:
switch (XINT (x, 1))
{
- case 1: /* st8.spill */
- case 2: /* ld8.fill */
+ case UNSPEC_LTOFF_DTPMOD:
+ case UNSPEC_LTOFF_DTPREL:
+ case UNSPEC_DTPREL:
+ case UNSPEC_LTOFF_TPREL:
+ case UNSPEC_TPREL:
+ case UNSPEC_PRED_REL_MUTEX:
+ case UNSPEC_PIC_CALL:
+ case UNSPEC_MF:
+ case UNSPEC_FETCHADD_ACQ:
+ case UNSPEC_BSP_VALUE:
+ case UNSPEC_FLUSHRS:
+ case UNSPEC_BUNDLE_SELECTOR:
+ break;
+
+ case UNSPEC_GR_SPILL:
+ case UNSPEC_GR_RESTORE:
{
HOST_WIDE_INT offset = INTVAL (XVECEXP (x, 0, 1));
HOST_WIDE_INT bit = (offset >> 3) & 63;
@@ -4577,32 +4978,22 @@ rtx_needs_barrier (x, flags, pred)
break;
}
- case 3: /* stf.spill */
- case 4: /* ldf.spill */
- case 8: /* popcnt */
+ case UNSPEC_FR_SPILL:
+ case UNSPEC_FR_RESTORE:
+ case UNSPEC_POPCNT:
need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
break;
- case 7: /* pred_rel_mutex */
- case 9: /* pic call */
- case 12: /* mf */
- case 19: /* fetchadd_acq */
- case 20: /* mov = ar.bsp */
- case 21: /* flushrs */
- case 22: /* bundle selector */
- case 23: /* cycle display */
- break;
-
- case 24: /* addp4 */
+ case UNSPEC_ADDP4:
need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
break;
- case 5: /* recip_approx */
+ case UNSPEC_FR_RECIP_APPROX:
need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
need_barrier |= rtx_needs_barrier (XVECEXP (x, 0, 1), flags, pred);
break;
- case 13: /* cmpxchg_acq */
+ case UNSPEC_CMPXCHG_ACQ:
need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 1), flags, pred);
need_barrier |= rtx_needs_barrier (XVECEXP (x, 0, 2), flags, pred);
break;
@@ -4615,7 +5006,7 @@ rtx_needs_barrier (x, flags, pred)
case UNSPEC_VOLATILE:
switch (XINT (x, 1))
{
- case 0: /* alloc */
+ case UNSPECV_ALLOC:
/* Alloc must always be the first instruction of a group.
We force this by always returning true. */
/* ??? We might get better scheduling if we explicitly check for
@@ -4629,17 +5020,15 @@ rtx_needs_barrier (x, flags, pred)
rws_access_regno (REG_AR_CFM, new_flags, pred);
return 1;
- case 1: /* blockage */
- case 2: /* insn group barrier */
- return 0;
-
- case 5: /* set_bsp */
+ case UNSPECV_SET_BSP:
need_barrier = 1;
break;
- case 7: /* pred.rel.mutex */
- case 8: /* safe_across_calls all */
- case 9: /* safe_across_calls normal */
+ case UNSPECV_BLOCKAGE:
+ case UNSPECV_INSN_GROUP_BARRIER:
+ case UNSPECV_BREAK:
+ case UNSPECV_PSAC_ALL:
+ case UNSPECV_PSAC_NORMAL:
return 0;
default:
@@ -4866,7 +5255,7 @@ emit_insn_group_barriers (dump, insns)
}
else if (GET_CODE (insn) == INSN
&& GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
- && XINT (PATTERN (insn), 1) == 2)
+ && XINT (PATTERN (insn), 1) == UNSPECV_INSN_GROUP_BARRIER)
{
init_insn_group_barriers ();
last_label = 0;
@@ -5328,7 +5717,9 @@ ia64_adjust_cost (insn, link, dep_insn, cost)
addr = XVECEXP (addr, 0, 0);
while (GET_CODE (addr) == SUBREG || GET_CODE (addr) == ZERO_EXTEND)
addr = XEXP (addr, 0);
- if (GET_CODE (addr) == MEM)
+
+ /* Note that LO_SUM is used for GOT loads. */
+ if (GET_CODE (addr) == MEM || GET_CODE (addr) == LO_SUM)
addr = XEXP (addr, 0);
else
addr = 0;
@@ -5470,18 +5861,13 @@ insn_matches_slot (p, itype, slot, insn)
return 0;
}
-/* Like emit_insn_before, but skip cycle_display insns. This makes the
- assembly output a bit prettier. */
+/* Like emit_insn_before, but skip cycle_display notes.
+ ??? When cycle display notes are implemented, update this. */
static void
ia64_emit_insn_before (insn, before)
rtx insn, before;
{
- rtx prev = PREV_INSN (before);
- if (prev && GET_CODE (prev) == INSN
- && GET_CODE (PATTERN (prev)) == UNSPEC
- && XINT (PATTERN (prev), 1) == 23)
- before = prev;
emit_insn_before (insn, before);
}
@@ -6376,9 +6762,11 @@ ia64_sched_reorder2 (dump, sched_verbose, ready, pn_ready, clock_var)
abort ();
insn_code = recog_memoized (stop);
- /* Ignore cycle displays and .pred.rel.mutex. */
- if (insn_code == CODE_FOR_cycle_display
- || insn_code == CODE_FOR_pred_rel_mutex
+ /* Ignore .pred.rel.mutex.
+
+ ??? Update this to ignore cycle display notes too
+ ??? once those are implemented */
+ if (insn_code == CODE_FOR_pred_rel_mutex
|| insn_code == CODE_FOR_prologue_use)
continue;
@@ -6532,17 +6920,6 @@ ia64_sched_finish (dump, sched_verbose)
free (sched_types);
free (sched_ready);
}
-
-static rtx
-ia64_cycle_display (clock, last)
- int clock;
- rtx last;
-{
- if (ia64_final_schedule)
- return emit_insn_after (gen_cycle_display (GEN_INT (clock)), last);
- else
- return last;
-}
/* Emit pseudo-ops for the assembler to describe predicate relations.
At present this assumes that we only consider predicate pairs to
@@ -6552,11 +6929,10 @@ ia64_cycle_display (clock, last)
static void
emit_predicate_relation_info ()
{
- int i;
+ basic_block bb;
- for (i = n_basic_blocks - 1; i >= 0; --i)
+ FOR_EACH_BB_REVERSE (bb)
{
- basic_block bb = BASIC_BLOCK (i);
int r;
rtx head = bb->head;
@@ -6582,9 +6958,8 @@ emit_predicate_relation_info ()
relations around them. Otherwise the assembler will assume the call
returns, and complain about uses of call-clobbered predicates after
the call. */
- for (i = n_basic_blocks - 1; i >= 0; --i)
+ FOR_EACH_BB_REVERSE (bb)
{
- basic_block bb = BASIC_BLOCK (i);
rtx insn = bb->head;
while (1)
@@ -6649,7 +7024,7 @@ ia64_emit_nops ()
pat = INSN_P (insn) ? PATTERN (insn) : const0_rtx;
if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
continue;
- if ((GET_CODE (pat) == UNSPEC && XINT (pat, 1) == 22)
+ if ((GET_CODE (pat) == UNSPEC && XINT (pat, 1) == UNSPEC_BUNDLE_SELECTOR)
|| GET_CODE (insn) == CODE_LABEL)
{
if (b)
@@ -6665,7 +7040,8 @@ ia64_emit_nops ()
bundle_pos = 0;
continue;
}
- else if (GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == 2)
+ else if (GET_CODE (pat) == UNSPEC_VOLATILE
+ && XINT (pat, 1) == UNSPECV_INSN_GROUP_BARRIER)
{
int t = INTVAL (XVECEXP (pat, 0, 0));
if (b)
@@ -6718,14 +7094,17 @@ void
ia64_reorg (insns)
rtx insns;
{
+ /* We are freeing block_for_insn in the toplev to keep compatibility
+ with old MDEP_REORGS that are not CFG based. Recompute it now. */
+ compute_bb_for_insn ();
+
/* If optimizing, we'll have split before scheduling. */
if (optimize == 0)
- split_all_insns_noflow ();
+ split_all_insns (0);
- /* Make sure the CFG and global_live_at_start are correct
- for emit_predicate_relation_info. */
- find_basic_blocks (insns, max_reg_num (), NULL);
- life_analysis (insns, NULL, PROP_DEATH_NOTES);
+ /* ??? update_life_info_in_dirty_blocks fails to terminate during
+ non-optimizing bootstrap. */
+ update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES);
if (ia64_flag_schedule_insns2)
{
@@ -6756,7 +7135,7 @@ ia64_reorg (insns)
insn = prev_active_insn (insn);
if (GET_CODE (insn) == INSN
&& GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
- && XINT (PATTERN (insn), 1) == 2)
+ && XINT (PATTERN (insn), 1) == UNSPECV_INSN_GROUP_BARRIER)
{
saw_stop = 1;
insn = prev_active_insn (insn);
@@ -6861,17 +7240,42 @@ ia64_eh_uses (regno)
code faster because there is one less load. This also includes incomplete
types which can't go in sdata/sbss. */
-/* ??? See select_section. We must put short own readonly variables in
- sdata/sbss instead of the more natural rodata, because we can't perform
- the DECL_READONLY_SECTION test here. */
+static bool
+ia64_in_small_data_p (exp)
+ tree exp;
+{
+ if (TARGET_NO_SDATA)
+ return false;
-extern struct obstack * saveable_obstack;
+ if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
+ {
+ const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
+ if (strcmp (section, ".sdata") == 0
+ || strcmp (section, ".sbss") == 0)
+ return true;
+ }
+ else
+ {
+ HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
-void
-ia64_encode_section_info (decl)
+ /* If this is an incomplete type with size 0, then we can't put it
+ in sdata because it might be too big when completed. */
+ if (size > 0 && size <= ia64_section_threshold)
+ return true;
+ }
+
+ return false;
+}
+
+static void
+ia64_encode_section_info (decl, first)
tree decl;
+ int first ATTRIBUTE_UNUSED;
{
const char *symbol_str;
+ bool is_local;
+ rtx symbol;
+ char encoding = 0;
if (TREE_CODE (decl) == FUNCTION_DECL)
{
@@ -6884,83 +7288,86 @@ ia64_encode_section_info (decl)
|| GET_CODE (DECL_RTL (decl)) != MEM
|| GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
return;
-
- symbol_str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
-
- /* We assume that -fpic is used only to create a shared library (dso).
- With -fpic, no global data can ever be sdata.
- Without -fpic, global common uninitialized data can never be sdata, since
- it can unify with a real definition in a dso. */
- /* ??? Actually, we can put globals in sdata, as long as we don't use gprel
- to access them. The linker may then be able to do linker relaxation to
- optimize references to them. Currently sdata implies use of gprel. */
- /* We need the DECL_EXTERNAL check for C++. static class data members get
- both TREE_STATIC and DECL_EXTERNAL set, to indicate that they are
- statically allocated, but the space is allocated somewhere else. Such
- decls can not be own data. */
- if (! TARGET_NO_SDATA
- && TREE_STATIC (decl) && ! DECL_EXTERNAL (decl)
- && ! (DECL_ONE_ONLY (decl) || DECL_WEAK (decl))
- && ! (TREE_PUBLIC (decl)
- && (flag_pic
- || (DECL_COMMON (decl)
- && (DECL_INITIAL (decl) == 0
- || DECL_INITIAL (decl) == error_mark_node))))
- /* Either the variable must be declared without a section attribute,
- or the section must be sdata or sbss. */
- && (DECL_SECTION_NAME (decl) == 0
- || ! strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
- ".sdata")
- || ! strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
- ".sbss")))
- {
- HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
-
- /* If the variable has already been defined in the output file, then it
- is too late to put it in sdata if it wasn't put there in the first
- place. The test is here rather than above, because if it is already
- in sdata, then it can stay there. */
-
- if (TREE_ASM_WRITTEN (decl))
- ;
-
- /* If this is an incomplete type with size 0, then we can't put it in
- sdata because it might be too big when completed. */
- else if (size > 0
- && size <= (HOST_WIDE_INT) ia64_section_threshold
- && symbol_str[0] != SDATA_NAME_FLAG_CHAR)
- {
- size_t len = strlen (symbol_str);
- char *newstr = alloca (len + 1);
- const char *string;
- *newstr = SDATA_NAME_FLAG_CHAR;
- memcpy (newstr + 1, symbol_str, len + 1);
-
- string = ggc_alloc_string (newstr, len + 1);
- XSTR (XEXP (DECL_RTL (decl), 0), 0) = string;
- }
- }
- /* This decl is marked as being in small data/bss but it shouldn't
- be; one likely explanation for this is that the decl has been
- moved into a different section from the one it was in when
- ENCODE_SECTION_INFO was first called. Remove the '@'. */
- else if (symbol_str[0] == SDATA_NAME_FLAG_CHAR)
+ symbol = XEXP (DECL_RTL (decl), 0);
+ symbol_str = XSTR (symbol, 0);
+
+ is_local = (*targetm.binds_local_p) (decl);
+
+ if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
+ encoding = " GLil"[decl_tls_model (decl)];
+ /* Determine if DECL will wind up in .sdata/.sbss. */
+ else if (is_local && ia64_in_small_data_p (decl))
+ encoding = 's';
+
+ /* Finally, encode this into the symbol string. */
+ if (encoding)
{
- XSTR (XEXP (DECL_RTL (decl), 0), 0)
- = ggc_strdup (symbol_str + 1);
+ char *newstr;
+ size_t len;
+
+ if (symbol_str[0] == ENCODE_SECTION_INFO_CHAR)
+ {
+ if (encoding == symbol_str[1])
+ return;
+ /* ??? Sdata became thread or thread becaome not thread. Lose. */
+ abort ();
+ }
+
+ len = strlen (symbol_str);
+ newstr = alloca (len + 3);
+ newstr[0] = ENCODE_SECTION_INFO_CHAR;
+ newstr[1] = encoding;
+ memcpy (newstr + 2, symbol_str, len + 1);
+
+ XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2);
}
+
+ /* This decl is marked as being in small data/bss but it shouldn't be;
+ one likely explanation for this is that the decl has been moved into
+ a different section from the one it was in when encode_section_info
+ was first called. Remove the encoding. */
+ else if (symbol_str[0] == ENCODE_SECTION_INFO_CHAR)
+ XSTR (symbol, 0) = ggc_strdup (symbol_str + 2);
+}
+
+static const char *
+ia64_strip_name_encoding (str)
+ const char *str;
+{
+ if (str[0] == ENCODE_SECTION_INFO_CHAR)
+ str += 2;
+ if (str[0] == '*')
+ str++;
+ return str;
+}
+
+/* True if it is OK to do sibling call optimization for the specified
+ call expression EXP. DECL will be the called function, or NULL if
+ this is an indirect call. */
+bool
+ia64_function_ok_for_sibcall (decl)
+ tree decl;
+{
+ /* Direct calls are always ok. */
+ if (decl)
+ return true;
+
+ /* If TARGET_CONST_GP is in effect, then our caller expects us to
+ return with our current GP. This means that we'll always have
+ a GP reload after an indirect call. */
+ return !ia64_epilogue_uses (R_GR (1));
}
/* Output assembly directives for prologue regions. */
/* The current basic block number. */
-static int block_num;
+static bool last_block;
/* True if we need a copy_state command at the start of the next block. */
-static int need_copy_state;
+static bool need_copy_state;
/* The function emits unwind directives for the start of an epilogue. */
@@ -6970,10 +7377,10 @@ process_epilogue ()
/* If this isn't the last block of the function, then we need to label the
current state, and copy it back in at the start of the next block. */
- if (block_num != n_basic_blocks - 1)
+ if (!last_block)
{
fprintf (asm_out_file, "\t.label_state 1\n");
- need_copy_state = 1;
+ need_copy_state = true;
}
fprintf (asm_out_file, "\t.restore sp\n");
@@ -6993,7 +7400,7 @@ process_set (asm_out_file, pat)
/* Look for the ALLOC insn. */
if (GET_CODE (src) == UNSPEC_VOLATILE
- && XINT (src, 1) == 0
+ && XINT (src, 1) == UNSPECV_ALLOC
&& GET_CODE (dest) == REG)
{
dest_regno = REGNO (dest);
@@ -7211,18 +7618,18 @@ process_for_unwind_directive (asm_out_file, insn)
if (GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)
{
- block_num = NOTE_BASIC_BLOCK (insn)->index;
+ last_block = NOTE_BASIC_BLOCK (insn)->next_bb == EXIT_BLOCK_PTR;
/* Restore unwind state from immediately before the epilogue. */
if (need_copy_state)
{
fprintf (asm_out_file, "\t.body\n");
fprintf (asm_out_file, "\t.copy_state 1\n");
- need_copy_state = 0;
+ need_copy_state = false;
}
}
- if (! RTX_FRAME_RELATED_P (insn))
+ if (GET_CODE (insn) == NOTE || ! RTX_FRAME_RELATED_P (insn))
return;
pat = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
@@ -7262,55 +7669,43 @@ ia64_init_builtins ()
{
tree psi_type_node = build_pointer_type (integer_type_node);
tree pdi_type_node = build_pointer_type (long_integer_type_node);
- tree endlink = void_list_node;
/* __sync_val_compare_and_swap_si, __sync_bool_compare_and_swap_si */
tree si_ftype_psi_si_si
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, psi_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink))));
+ = build_function_type_list (integer_type_node,
+ psi_type_node, integer_type_node,
+ integer_type_node, NULL_TREE);
/* __sync_val_compare_and_swap_di, __sync_bool_compare_and_swap_di */
tree di_ftype_pdi_di_di
- = build_function_type (long_integer_type_node,
- tree_cons (NULL_TREE, pdi_type_node,
- tree_cons (NULL_TREE,
- long_integer_type_node,
- tree_cons (NULL_TREE,
- long_integer_type_node,
- endlink))));
+ = build_function_type_list (long_integer_type_node,
+ pdi_type_node, long_integer_type_node,
+ long_integer_type_node, NULL_TREE);
/* __sync_synchronize */
tree void_ftype_void
- = build_function_type (void_type_node, endlink);
+ = build_function_type (void_type_node, void_list_node);
/* __sync_lock_test_and_set_si */
tree si_ftype_psi_si
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, psi_type_node,
- tree_cons (NULL_TREE, integer_type_node, endlink)));
+ = build_function_type_list (integer_type_node,
+ psi_type_node, integer_type_node, NULL_TREE);
/* __sync_lock_test_and_set_di */
tree di_ftype_pdi_di
- = build_function_type (long_integer_type_node,
- tree_cons (NULL_TREE, pdi_type_node,
- tree_cons (NULL_TREE, long_integer_type_node,
- endlink)));
+ = build_function_type_list (long_integer_type_node,
+ pdi_type_node, long_integer_type_node,
+ NULL_TREE);
/* __sync_lock_release_si */
tree void_ftype_psi
- = build_function_type (void_type_node, tree_cons (NULL_TREE, psi_type_node,
- endlink));
+ = build_function_type_list (void_type_node, psi_type_node, NULL_TREE);
/* __sync_lock_release_di */
tree void_ftype_pdi
- = build_function_type (void_type_node, tree_cons (NULL_TREE, pdi_type_node,
- endlink));
+ = build_function_type_list (void_type_node, pdi_type_node, NULL_TREE);
#define def_builtin(name, type, code) \
- builtin_function ((name), (type), (code), BUILT_IN_MD, NULL)
+ builtin_function ((name), (type), (code), BUILT_IN_MD, NULL, NULL_TREE)
def_builtin ("__sync_val_compare_and_swap_si", si_ftype_psi_si_si,
IA64_BUILTIN_VAL_COMPARE_AND_SWAP_SI);
@@ -7334,11 +7729,11 @@ ia64_init_builtins ()
IA64_BUILTIN_LOCK_RELEASE_DI);
def_builtin ("__builtin_ia64_bsp",
- build_function_type (ptr_type_node, endlink),
+ build_function_type (ptr_type_node, void_list_node),
IA64_BUILTIN_BSP);
def_builtin ("__builtin_ia64_flushrs",
- build_function_type (void_type_node, endlink),
+ build_function_type (void_type_node, void_list_node),
IA64_BUILTIN_FLUSHRS);
def_builtin ("__sync_fetch_and_add_si", si_ftype_psi_si,
@@ -7421,6 +7816,10 @@ ia64_expand_fetch_and_op (binoptab, mode, arglist, target)
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mem = expand_expr (arg0, NULL_RTX, Pmode, 0);
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE(mem) != Pmode)
+ mem = convert_memory_address (Pmode, mem);
+#endif
value = expand_expr (arg1, NULL_RTX, mode, 0);
mem = gen_rtx_MEM (mode, force_reg (Pmode, mem));
@@ -7480,7 +7879,7 @@ ia64_expand_fetch_and_op (binoptab, mode, arglist, target)
do {
old = tmp;
ar.ccv = tmp;
- ret = tmp + value;
+ ret = tmp <op> value;
cmpxchgsz.acq tmp = [ptr], ret
} while (tmp != old)
*/
@@ -7498,6 +7897,11 @@ ia64_expand_op_and_fetch (binoptab, mode, arglist, target)
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mem = expand_expr (arg0, NULL_RTX, Pmode, 0);
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE(mem) != Pmode)
+ mem = convert_memory_address (Pmode, mem);
+#endif
+
value = expand_expr (arg1, NULL_RTX, mode, 0);
mem = gen_rtx_MEM (mode, force_reg (Pmode, mem));
@@ -7561,11 +7965,11 @@ ia64_expand_compare_and_swap (mode, boolp, arglist, target)
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- mem = expand_expr (arg0, NULL_RTX, Pmode, 0);
+ mem = expand_expr (arg0, NULL_RTX, ptr_mode, 0);
old = expand_expr (arg1, NULL_RTX, mode, 0);
new = expand_expr (arg2, NULL_RTX, mode, 0);
- mem = gen_rtx_MEM (mode, force_reg (Pmode, mem));
+ mem = gen_rtx_MEM (mode, force_reg (ptr_mode, mem));
MEM_VOLATILE_P (mem) = 1;
if (! register_operand (old, mode))
@@ -7578,8 +7982,15 @@ ia64_expand_compare_and_swap (mode, boolp, arglist, target)
else
tmp = gen_reg_rtx (mode);
- ccv = gen_rtx_REG (mode, AR_CCV_REGNUM);
- emit_move_insn (ccv, old);
+ ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
+ if (mode == DImode)
+ emit_move_insn (ccv, old);
+ else
+ {
+ rtx ccvtmp = gen_reg_rtx (DImode);
+ emit_insn (gen_zero_extendsidi2 (ccvtmp, old));
+ emit_move_insn (ccv, ccvtmp);
+ }
emit_insn (gen_mf ());
if (mode == SImode)
insn = gen_cmpxchg_acq_si (tmp, mem, new, ccv);
@@ -7610,10 +8021,10 @@ ia64_expand_lock_test_and_set (mode, arglist, target)
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- mem = expand_expr (arg0, NULL_RTX, Pmode, 0);
+ mem = expand_expr (arg0, NULL_RTX, ptr_mode, 0);
new = expand_expr (arg1, NULL_RTX, mode, 0);
- mem = gen_rtx_MEM (mode, force_reg (Pmode, mem));
+ mem = gen_rtx_MEM (mode, force_reg (ptr_mode, mem));
MEM_VOLATILE_P (mem) = 1;
if (! register_operand (new, mode))
new = copy_to_mode_reg (mode, new);
@@ -7644,9 +8055,9 @@ ia64_expand_lock_release (mode, arglist, target)
rtx mem;
arg0 = TREE_VALUE (arglist);
- mem = expand_expr (arg0, NULL_RTX, Pmode, 0);
+ mem = expand_expr (arg0, NULL_RTX, ptr_mode, 0);
- mem = gen_rtx_MEM (mode, force_reg (Pmode, mem));
+ mem = gen_rtx_MEM (mode, force_reg (ptr_mode, mem));
MEM_VOLATILE_P (mem) = 1;
emit_move_insn (mem, const0_rtx);
@@ -7820,3 +8231,221 @@ ia64_hpux_function_arg_padding (mode, type)
: GET_MODE_BITSIZE (mode) < PARM_BOUNDARY)
? downward : upward);
}
+
+/* Linked list of all external functions that are to be emitted by GCC.
+ We output the name if and only if TREE_SYMBOL_REFERENCED is set in
+ order to avoid putting out names that are never really used. */
+
+struct extern_func_list
+{
+ struct extern_func_list *next; /* next external */
+ char *name; /* name of the external */
+} *extern_func_head = 0;
+
+static void
+ia64_hpux_add_extern_decl (name)
+ const char *name;
+{
+ struct extern_func_list *p;
+
+ p = (struct extern_func_list *) xmalloc (sizeof (struct extern_func_list));
+ p->name = xmalloc (strlen (name) + 1);
+ strcpy(p->name, name);
+ p->next = extern_func_head;
+ extern_func_head = p;
+}
+
+/* Print out the list of used global functions. */
+
+void
+ia64_hpux_asm_file_end (file)
+ FILE *file;
+{
+ while (extern_func_head)
+ {
+ const char *real_name;
+ tree decl;
+
+ real_name = (* targetm.strip_name_encoding) (extern_func_head->name);
+ decl = maybe_get_identifier (real_name);
+
+ if (!decl
+ || (! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (decl)))
+ {
+ if (decl)
+ TREE_ASM_WRITTEN (decl) = 1;
+ (*targetm.asm_out.globalize_label) (file, extern_func_head->name);
+ fprintf (file, "%s", TYPE_ASM_OP);
+ assemble_name (file, extern_func_head->name);
+ putc (',', file);
+ fprintf (file, TYPE_OPERAND_FMT, "function");
+ putc ('\n', file);
+ }
+ extern_func_head = extern_func_head->next;
+ }
+}
+
+
+/* Switch to the section to which we should output X. The only thing
+ special we do here is to honor small data. */
+
+static void
+ia64_select_rtx_section (mode, x, align)
+ enum machine_mode mode;
+ rtx x;
+ unsigned HOST_WIDE_INT align;
+{
+ if (GET_MODE_SIZE (mode) > 0
+ && GET_MODE_SIZE (mode) <= ia64_section_threshold)
+ sdata_section ();
+ else
+ default_elf_select_rtx_section (mode, x, align);
+}
+
+/* It is illegal to have relocations in shared segments on AIX and HPUX.
+ Pretend flag_pic is always set. */
+
+static void
+ia64_rwreloc_select_section (exp, reloc, align)
+ tree exp;
+ int reloc;
+ unsigned HOST_WIDE_INT align;
+{
+ default_elf_select_section_1 (exp, reloc, align, true);
+}
+
+static void
+ia64_rwreloc_unique_section (decl, reloc)
+ tree decl;
+ int reloc;
+{
+ default_unique_section_1 (decl, reloc, true);
+}
+
+static void
+ia64_rwreloc_select_rtx_section (mode, x, align)
+ enum machine_mode mode;
+ rtx x;
+ unsigned HOST_WIDE_INT align;
+{
+ int save_pic = flag_pic;
+ flag_pic = 1;
+ ia64_select_rtx_section (mode, x, align);
+ flag_pic = save_pic;
+}
+
+static unsigned int
+ia64_rwreloc_section_type_flags (decl, name, reloc)
+ tree decl;
+ const char *name;
+ int reloc;
+{
+ return default_section_type_flags_1 (decl, name, reloc, true);
+}
+
+
+/* Output the assembler code for a thunk function. THUNK_DECL is the
+ declaration for the thunk function itself, FUNCTION is the decl for
+ the target function. DELTA is an immediate constant offset to be
+ added to THIS. If VCALL_OFFSET is non-zero, the word at
+ *(*this + vcall_offset) should be added to THIS. */
+
+static void
+ia64_output_mi_thunk (file, thunk, delta, vcall_offset, function)
+ FILE *file;
+ tree thunk ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT delta;
+ HOST_WIDE_INT vcall_offset;
+ tree function;
+{
+ rtx this, insn, funexp;
+
+ reload_completed = 1;
+ no_new_pseudos = 1;
+
+ /* Set things up as ia64_expand_prologue might. */
+ last_scratch_gr_reg = 15;
+
+ memset (&current_frame_info, 0, sizeof (current_frame_info));
+ current_frame_info.spill_cfa_off = -16;
+ current_frame_info.n_input_regs = 1;
+ current_frame_info.need_regstk = (TARGET_REG_NAMES != 0);
+
+ if (!TARGET_REG_NAMES)
+ reg_names[IN_REG (0)] = ia64_reg_numbers[0];
+
+ /* Mark the end of the (empty) prologue. */
+ emit_note (NULL, NOTE_INSN_PROLOGUE_END);
+
+ this = gen_rtx_REG (Pmode, IN_REG (0));
+
+ /* Apply the constant offset, if required. */
+ if (delta)
+ {
+ rtx delta_rtx = GEN_INT (delta);
+
+ if (!CONST_OK_FOR_I (delta))
+ {
+ rtx tmp = gen_rtx_REG (Pmode, 2);
+ emit_move_insn (tmp, delta_rtx);
+ delta_rtx = tmp;
+ }
+ emit_insn (gen_adddi3 (this, this, delta_rtx));
+ }
+
+ /* Apply the offset from the vtable, if required. */
+ if (vcall_offset)
+ {
+ rtx vcall_offset_rtx = GEN_INT (vcall_offset);
+ rtx tmp = gen_rtx_REG (Pmode, 2);
+
+ emit_move_insn (tmp, gen_rtx_MEM (Pmode, this));
+
+ if (!CONST_OK_FOR_J (vcall_offset))
+ {
+ rtx tmp2 = gen_rtx_REG (Pmode, next_scratch_gr_reg ());
+ emit_move_insn (tmp2, vcall_offset_rtx);
+ vcall_offset_rtx = tmp2;
+ }
+ emit_insn (gen_adddi3 (tmp, tmp, vcall_offset_rtx));
+
+ emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
+
+ emit_insn (gen_adddi3 (this, this, tmp));
+ }
+
+ /* Generate a tail call to the target function. */
+ if (! TREE_USED (function))
+ {
+ assemble_external (function);
+ TREE_USED (function) = 1;
+ }
+ funexp = XEXP (DECL_RTL (function), 0);
+ funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
+ ia64_expand_call (NULL_RTX, funexp, NULL_RTX, 1);
+ insn = get_last_insn ();
+ SIBLING_CALL_P (insn) = 1;
+
+ /* Code generation for calls relies on splitting. */
+ reload_completed = 1;
+ try_split (PATTERN (insn), insn, 0);
+
+ emit_barrier ();
+
+ /* Run just enough of rest_of_compilation to get the insns emitted.
+ There's not really enough bulk here to make other passes such as
+ instruction scheduling worth while. Note that use_thunk calls
+ assemble_start_function and assemble_end_function. */
+
+ insn = get_insns ();
+ emit_all_insn_group_barriers (NULL, insn);
+ shorten_branches (insn);
+ final_start_function (insn, file, 1);
+ final (insn, file, 1, 0);
+ final_end_function ();
+
+ reload_completed = 0;
+ no_new_pseudos = 0;
+}
+
+#include "gt-ia64.h"
diff --git a/contrib/gcc/config/ia64/ia64.h b/contrib/gcc/config/ia64/ia64.h
index f69983b..724405a 100644
--- a/contrib/gcc/config/ia64/ia64.h
+++ b/contrib/gcc/config/ia64/ia64.h
@@ -31,14 +31,27 @@ Boston, MA 02111-1307, USA. */
/* Run-time target specifications */
+/* Target CPU builtins. */
+#define TARGET_CPU_CPP_BUILTINS() \
+do { \
+ builtin_assert("cpu=ia64"); \
+ builtin_assert("machine=ia64"); \
+ builtin_define("__ia64"); \
+ builtin_define("__ia64__"); \
+ builtin_define("__itanium__"); \
+ builtin_define("__ELF__"); \
+ if (!TARGET_ILP32) \
+ { \
+ builtin_define("_LP64"); \
+ builtin_define("__LP64__"); \
+ } \
+ if (TARGET_BIG_ENDIAN) \
+ builtin_define("__BIG_ENDIAN__"); \
+} while (0)
+
#define EXTRA_SPECS \
- { "cpp_cpu", CPP_CPU_SPEC }, \
{ "asm_extra", ASM_EXTRA_SPEC },
-#define CPP_CPU_SPEC " \
- -Acpu=ia64 -Amachine=ia64 -D__ia64 -D__ia64__ %{!milp32:-D_LP64 -D__LP64__} \
- -D__ELF__"
-
#define CC1_SPEC "%(cc1_cpu) "
#define ASM_EXTRA_SPEC ""
@@ -72,9 +85,13 @@ extern int target_flags;
#define MASK_AUTO_PIC 0x00000400 /* generate automatically PIC */
-#define MASK_INLINE_DIV_LAT 0x00000800 /* inline div, min latency. */
+#define MASK_INLINE_FLOAT_DIV_LAT 0x00000800 /* inline div, min latency. */
+
+#define MASK_INLINE_FLOAT_DIV_THR 0x00001000 /* inline div, max throughput. */
+
+#define MASK_INLINE_INT_DIV_LAT 0x00000800 /* inline div, min latency. */
-#define MASK_INLINE_DIV_THR 0x00001000 /* inline div, max throughput. */
+#define MASK_INLINE_INT_DIV_THR 0x00001000 /* inline div, max throughput. */
#define MASK_DWARF2_ASM 0x40000000 /* test dwarf2 line info via gas. */
@@ -100,15 +117,33 @@ extern int target_flags;
#define TARGET_AUTO_PIC (target_flags & MASK_AUTO_PIC)
-#define TARGET_INLINE_DIV_LAT (target_flags & MASK_INLINE_DIV_LAT)
+#define TARGET_INLINE_FLOAT_DIV_LAT (target_flags & MASK_INLINE_FLOAT_DIV_LAT)
-#define TARGET_INLINE_DIV_THR (target_flags & MASK_INLINE_DIV_THR)
+#define TARGET_INLINE_FLOAT_DIV_THR (target_flags & MASK_INLINE_FLOAT_DIV_THR)
-#define TARGET_INLINE_DIV \
- (target_flags & (MASK_INLINE_DIV_LAT | MASK_INLINE_DIV_THR))
+#define TARGET_INLINE_INT_DIV_LAT (target_flags & MASK_INLINE_INT_DIV_LAT)
+
+#define TARGET_INLINE_INT_DIV_THR (target_flags & MASK_INLINE_INT_DIV_THR)
+
+#define TARGET_INLINE_FLOAT_DIV \
+ (target_flags & (MASK_INLINE_FLOAT_DIV_LAT | MASK_INLINE_FLOAT_DIV_THR))
+
+#define TARGET_INLINE_INT_DIV \
+ (target_flags & (MASK_INLINE_INT_DIV_LAT | MASK_INLINE_INT_DIV_THR))
#define TARGET_DWARF2_ASM (target_flags & MASK_DWARF2_ASM)
+extern int ia64_tls_size;
+#define TARGET_TLS14 (ia64_tls_size == 14)
+#define TARGET_TLS22 (ia64_tls_size == 22)
+#define TARGET_TLS64 (ia64_tls_size == 64)
+
+#define TARGET_HPUX_LD 0
+
+#ifndef HAVE_AS_LTOFFX_LDXMOV_RELOCS
+#define HAVE_AS_LTOFFX_LDXMOV_RELOCS 0
+#endif
+
/* This macro defines names of command options to set and clear bits in
`target_flags'. Its definition is an initializer with a subgrouping for
each command option. */
@@ -145,10 +180,14 @@ extern int target_flags;
N_("gp is constant (but save/restore gp on indirect calls)") }, \
{ "auto-pic", MASK_AUTO_PIC, \
N_("Generate self-relocatable code") }, \
- { "inline-divide-min-latency", MASK_INLINE_DIV_LAT, \
- N_("Generate inline division, optimize for latency") }, \
- { "inline-divide-max-throughput", MASK_INLINE_DIV_THR, \
- N_("Generate inline division, optimize for throughput") }, \
+ { "inline-float-divide-min-latency", MASK_INLINE_FLOAT_DIV_LAT, \
+ N_("Generate inline floating point division, optimize for latency") },\
+ { "inline-float-divide-max-throughput", MASK_INLINE_FLOAT_DIV_THR, \
+ N_("Generate inline floating point division, optimize for throughput") },\
+ { "inline-int-divide-min-latency", MASK_INLINE_INT_DIV_LAT, \
+ N_("Generate inline integer division, optimize for latency") }, \
+ { "inline-int-divide-max-throughput", MASK_INLINE_INT_DIV_THR, \
+ N_("Generate inline integer division, optimize for throughput") },\
{ "dwarf2-asm", MASK_DWARF2_ASM, \
N_("Enable Dwarf 2 line debug info via GNU as")}, \
{ "no-dwarf2-asm", -MASK_DWARF2_ASM, \
@@ -177,10 +216,13 @@ extern int target_flags;
subgrouping for each command option. */
extern const char *ia64_fixed_range_string;
+extern const char *ia64_tls_size_string;
#define TARGET_OPTIONS \
{ \
{ "fixed-range=", &ia64_fixed_range_string, \
N_("Specify range of registers to make fixed")}, \
+ { "tls-size=", &ia64_tls_size_string, \
+ N_("Specify bit size of immediate TLS offsets")}, \
}
/* Sometimes certain combinations of command options do not make sense on a
@@ -201,25 +243,6 @@ extern const char *ia64_fixed_range_string;
/* Driver configuration */
/* A C string constant that tells the GNU CC driver program options to pass to
- CPP. It can also specify how to translate options you give to GNU CC into
- options for GNU CC to pass to the CPP. */
-
-/* ??? __LONG_MAX__ depends on LP64/ILP32 switch. */
-/* ??? An alternative is to modify glimits.h to check for __LP64__ instead
- of checked for CPU specific defines. We could also get rid of all LONG_MAX
- defines in other tm.h files. */
-#define CPP_SPEC \
- "%{mcpu=itanium:-D__itanium__} %{mbig-endian:-D__BIG_ENDIAN__} \
- %(cpp_cpu) \
- -D__LONG_MAX__=9223372036854775807L"
-
-/* This is always "long" so it doesn't "change" in ILP32 vs. LP64. */
-/* #define NO_BUILTIN_SIZE_TYPE */
-
-/* This is always "long" so it doesn't "change" in ILP32 vs. LP64. */
-/* #define NO_BUILTIN_PTRDIFF_TYPE */
-
-/* A C string constant that tells the GNU CC driver program options to pass to
`cc1'. It can also specify how to translate options you give to GNU CC into
options for GNU CC to pass to the `cc1'. */
@@ -252,10 +275,6 @@ extern const char *ia64_fixed_range_string;
#define LIBGCC2_WORDS_BIG_ENDIAN 0
#endif
-#define BITS_PER_UNIT 8
-
-#define BITS_PER_WORD 64
-
#define UNITS_PER_WORD 8
#define POINTER_SIZE (TARGET_ILP32 ? 32 : 64)
@@ -329,10 +348,10 @@ while (0)
/* Define this if you wish to imitate the way many other C compilers handle
alignment of bitfields and the structures that contain them.
- The behavior is that the type written for a bitfield (`int', `short', or
+ The behavior is that the type written for a bit-field (`int', `short', or
other integer type) imposes an alignment for the entire structure, as if the
structure really did contain an ordinary field of that type. In addition,
- the bitfield is placed within the structure so that it would fit within such
+ the bit-field is placed within the structure so that it would fit within such
a field, not crossing a boundary for it. */
#define PCC_BITFIELD_TYPE_MATTERS 1
@@ -342,16 +361,26 @@ while (0)
/* Allow pairs of registers to be used, which is the intent of the default. */
#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (TImode)
-/* A code distinguishing the floating point format of the target machine. */
-#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-
/* By default, the C++ compiler will use function addresses in the
- vtable entries. Setting this non-zero tells the compiler to use
+ vtable entries. Setting this nonzero tells the compiler to use
function descriptors instead. The value of this macro says how
many words wide the descriptor is (normally 2). It is assumed
that the address of a function descriptor may be treated as a
- pointer to a function. */
-#define TARGET_VTABLE_USES_DESCRIPTORS 2
+ pointer to a function.
+
+ For reasons known only to HP, the vtable entries (as opposed to
+ normal function descriptors) are 16 bytes wide in 32-bit mode as
+ well, even though the 3rd and 4th words are unused. */
+#define TARGET_VTABLE_USES_DESCRIPTORS (TARGET_ILP32 ? 4 : 2)
+
+/* Due to silliness in the HPUX linker, vtable entries must be
+ 8-byte aligned even in 32-bit mode. Rather than create multiple
+ ABIs, force this restriction on everyone else too. */
+#define TARGET_VTABLE_ENTRY_ALIGN 64
+
+/* Due to the above, we need extra padding for the data entries below 0
+ to retain the alignment of the descriptors. */
+#define TARGET_VTABLE_DATA_ENTRY_DISTANCE (TARGET_ILP32 ? 2 : 1)
/* Layout of Source Language Data Types */
@@ -365,17 +394,14 @@ while (0)
#define LONG_LONG_TYPE_SIZE 64
-#define CHAR_TYPE_SIZE 8
-
#define FLOAT_TYPE_SIZE 32
#define DOUBLE_TYPE_SIZE 64
#define LONG_DOUBLE_TYPE_SIZE 128
-/* Tell real.c that this is the 80-bit Intel extended float format
- packaged in a 128-bit entity. */
-
+/* By default we use the 80-bit Intel extended float format packaged
+ in a 128-bit entity. */
#define INTEL_EXTENDED_IEEE_FORMAT 1
#define DEFAULT_SIGNED_CHAR 1
@@ -599,14 +625,6 @@ while (0)
#define LOCAL_REGNO(REGNO) \
(IN_REGNO_P (REGNO) || LOC_REGNO_P (REGNO))
-/* Add any extra modes needed to represent the condition code.
-
- CCImode is used to mark a single predicate register instead
- of a register pair. This is currently only used in reg_raw_mode
- so that flow doesn't do something stupid. */
-
-#define EXTRA_CC_MODES CC(CCImode, "CCI")
-
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. Must be defined if
EXTRA_CC_MODES is defined. */
@@ -970,7 +988,7 @@ enum reg_class
/* Certain machines have the property that some registers cannot be copied to
some other registers without using memory. Define this macro on those
- machines to be a C expression that is non-zero if objects of mode M in
+ machines to be a C expression that is nonzero if objects of mode M in
registers of CLASS1 can only be copied to registers of class CLASS2 by
storing a register of CLASS1 into memory and loading that memory location
into a register of CLASS2. */
@@ -994,17 +1012,12 @@ enum reg_class
: ((CLASS) == FR_REGS && (MODE) == TFmode) ? 1 \
: (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-/* If defined, gives a class of registers that cannot be used as the
- operand of a SUBREG that changes the mode of the object illegally. */
-
-#define CLASS_CANNOT_CHANGE_MODE FR_REGS
-
-/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.
- In FP regs, we can't change FP values to integer values and vice
+/* In FP regs, we can't change FP values to integer values and vice
versa, but we can change e.g. DImode to SImode. */
-#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
- (GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO))
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO) \
+ ? reg_classes_intersect_p (CLASS, FR_REGS) : 0)
/* A C expression that defines the machine-dependent operand constraint
letters (`I', `J', `K', .. 'P') that specify particular ranges of
@@ -1200,7 +1213,7 @@ enum reg_class
{RETURN_ADDRESS_POINTER_REGNUM, BR_REG (0)}, \
}
-/* A C expression that returns non-zero if the compiler is allowed to try to
+/* A C expression that returns nonzero if the compiler is allowed to try to
replace register number FROM with register number TO. The frame pointer
is automatically handled. */
@@ -1344,10 +1357,6 @@ do { \
(((REGNO) >= GR_ARG_FIRST && (REGNO) < (GR_ARG_FIRST + MAX_ARGUMENT_SLOTS)) \
|| ((REGNO) >= FR_ARG_FIRST && (REGNO) < (FR_ARG_FIRST + MAX_ARGUMENT_SLOTS)))
-/* Implement `va_start' for varargs and stdarg. */
-#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
- ia64_va_start (stdarg, valist, nextarg)
-
/* Implement `va_arg'. */
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
ia64_va_arg (valist, type)
@@ -1433,48 +1442,20 @@ do { \
#define ASM_FILE_START(FILE) \
emit_safe_across_calls (FILE)
-/* A C compound statement that outputs the assembler code for a thunk function,
- used to implement C++ virtual function calls with multiple inheritance. */
-
-#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
-do { \
- if (CONST_OK_FOR_I (DELTA)) \
- { \
- fprintf (FILE, "\tadds r32 = "); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA)); \
- fprintf (FILE, ", r32\n"); \
- } \
- else \
- { \
- if (CONST_OK_FOR_J (DELTA)) \
- { \
- fprintf (FILE, "\taddl r2 = "); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA)); \
- fprintf (FILE, ", r0\n"); \
- } \
- else \
- { \
- fprintf (FILE, "\tmovl r2 = "); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA)); \
- fprintf (FILE, "\n"); \
- } \
- fprintf (FILE, "\t;;\n"); \
- fprintf (FILE, "\tadd r32 = r2, r32\n"); \
- } \
- fprintf (FILE, "\tbr "); \
- assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
- fprintf (FILE, "\n"); \
-} while (0)
-
/* Output part N of a function descriptor for DECL. For ia64, both
words are emitted with a single relocation, so ignore N > 0. */
#define ASM_OUTPUT_FDESC(FILE, DECL, PART) \
do { \
if ((PART) == 0) \
{ \
- fputs ("\tdata16.ua @iplt(", FILE); \
+ if (TARGET_ILP32) \
+ fputs ("\tdata8.ua @iplt(", FILE); \
+ else \
+ fputs ("\tdata16.ua @iplt(", FILE); \
assemble_name (FILE, XSTR (XEXP (DECL_RTL (DECL), 0), 0)); \
fputs (")\n", FILE); \
+ if (TARGET_ILP32) \
+ fputs ("\tdata8.ua 0\n", FILE); \
} \
} while (0)
@@ -1786,36 +1767,9 @@ do { \
#define BSS_SECTION_ASM_OP "\t.bss"
-/* Define this macro if references to a symbol must be treated differently
- depending on something about the variable or function named by the symbol
- (such as what section it is in). */
-
-#define ENCODE_SECTION_INFO(DECL) ia64_encode_section_info (DECL)
-
-/* If a variable is weakened, made one only or moved into a different
- section, it may be necessary to redo the section info to move the
- variable out of sdata. */
-
-#define REDO_SECTION_INFO_P(DECL) \
- ((TREE_CODE (DECL) == VAR_DECL) \
- && (DECL_ONE_ONLY (DECL) || DECL_WEAK (DECL) || DECL_COMMON (DECL) \
- || DECL_SECTION_NAME (DECL) != 0))
-
-#define SDATA_NAME_FLAG_CHAR '@'
+#define ENCODE_SECTION_INFO_CHAR '@'
#define IA64_DEFAULT_GVALUE 8
-
-/* Decode SYM_NAME and store the real name part in VAR, sans the characters
- that encode section info. */
-
-#define STRIP_NAME_ENCODING(VAR, SYMBOL_NAME) \
-do { \
- (VAR) = (SYMBOL_NAME); \
- if ((VAR)[0] == SDATA_NAME_FLAG_CHAR) \
- (VAR)++; \
- if ((VAR)[0] == '*') \
- (VAR)++; \
-} while (0)
/* Position Independent Code. */
@@ -1859,61 +1813,6 @@ do { \
#define ASM_APP_OFF "#NO_APP\n"
-/* Output of Data. */
-
-/* This is how to output an assembler line defining a `char' constant
- to an xdata segment. */
-
-#define ASM_OUTPUT_XDATA_CHAR(FILE, SECTION, VALUE) \
-do { \
- fprintf (FILE, "\t.xdata1\t\"%s\", ", SECTION); \
- output_addr_const (FILE, (VALUE)); \
- fprintf (FILE, "\n"); \
-} while (0)
-
-/* This is how to output an assembler line defining a `short' constant
- to an xdata segment. */
-
-#define ASM_OUTPUT_XDATA_SHORT(FILE, SECTION, VALUE) \
-do { \
- fprintf (FILE, "\t.xdata2\t\"%s\", ", SECTION); \
- output_addr_const (FILE, (VALUE)); \
- fprintf (FILE, "\n"); \
-} while (0)
-
-/* This is how to output an assembler line defining an `int' constant
- to an xdata segment. We also handle symbol output here. */
-
-/* ??? For ILP32, also need to handle function addresses here. */
-
-#define ASM_OUTPUT_XDATA_INT(FILE, SECTION, VALUE) \
-do { \
- fprintf (FILE, "\t.xdata4\t\"%s\", ", SECTION); \
- output_addr_const (FILE, (VALUE)); \
- fprintf (FILE, "\n"); \
-} while (0)
-
-/* This is how to output an assembler line defining a `long' constant
- to an xdata segment. We also handle symbol output here. */
-
-#define ASM_OUTPUT_XDATA_DOUBLE_INT(FILE, SECTION, VALUE) \
-do { \
- int need_closing_paren = 0; \
- fprintf (FILE, "\t.xdata8\t\"%s\", ", SECTION); \
- if (!(TARGET_NO_PIC || TARGET_AUTO_PIC) \
- && GET_CODE (VALUE) == SYMBOL_REF) \
- { \
- fprintf (FILE, SYMBOL_REF_FLAG (VALUE) ? "@fptr(" : "@segrel("); \
- need_closing_paren = 1; \
- } \
- output_addr_const (FILE, VALUE); \
- if (need_closing_paren) \
- fprintf (FILE, ")"); \
- fprintf (FILE, "\n"); \
-} while (0)
-
-
-
/* Output of Uninitialized Variables. */
/* This is all handled by svr4.h. */
@@ -1936,16 +1835,8 @@ do { \
ia64_asm_output_label = 0; \
} while (0)
-/* A C statement (sans semicolon) to output to the stdio stream STREAM some
- commands that will make the label NAME global; that is, available for
- reference from other files. */
-
-#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \
-do { \
- fputs ("\t.global ", STREAM); \
- assemble_name (STREAM, NAME); \
- fputs ("\n", STREAM); \
-} while (0)
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\t.global "
/* A C statement (sans semicolon) to output to the stdio stream STREAM any text
necessary for declaring the name of an external symbol named NAME which is
@@ -2191,8 +2082,13 @@ do { \
/* ??? Depends on the pointer size. */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
- fprintf (STREAM, "\tdata8 @pcrel(.L%d)\n", VALUE)
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
+ do { \
+ if (TARGET_ILP32) \
+ fprintf (STREAM, "\tdata4 @pcrel(.L%d)\n", VALUE); \
+ else \
+ fprintf (STREAM, "\tdata8 @pcrel(.L%d)\n", VALUE); \
+ } while (0)
/* This is how to output an element of a case-vector that is absolute.
(Ia64 does not use such vectors, but we must define this macro anyway.) */
@@ -2211,7 +2107,8 @@ do { \
true if the symbol may be affected by dynamic relocations. */
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
(((CODE) == 1 ? DW_EH_PE_textrel : DW_EH_PE_datarel) \
- | ((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_udata8)
+ | ((GLOBAL) ? DW_EH_PE_indirect : 0) \
+ | (TARGET_ILP32 ? DW_EH_PE_udata4 : DW_EH_PE_udata8))
/* Handle special EH pointer encodings. Absolute, pc-relative, and
indirect are handled automatically. */
@@ -2284,7 +2181,7 @@ do { \
/* Define this macro if GNU CC should produce dwarf version 2 format debugging
output in response to the `-g' option. */
-#define DWARF2_DEBUGGING_INFO
+#define DWARF2_DEBUGGING_INFO 1
#define DWARF2_ASM_LINE_DEBUG_INFO (TARGET_DWARF2_ASM)
@@ -2316,12 +2213,6 @@ do { \
fputc (')', FILE); \
} while (0)
-/* Cross Compilation and Floating Point. */
-
-/* Define to enable software floating point emulation. */
-#define REAL_ARITHMETIC
-
-
/* Register Renaming Parameters. */
/* A C expression that is nonzero if hard register number REGNO2 can be
@@ -2381,12 +2272,13 @@ do { \
{ "ar_pfs_reg_operand", {REG}}, \
{ "general_tfmode_operand", {SUBREG, REG, CONST_DOUBLE, MEM}}, \
{ "destination_tfmode_operand", {SUBREG, REG, MEM}}, \
-{ "tfreg_or_fp01_operand", {REG, CONST_DOUBLE}},
+{ "tfreg_or_fp01_operand", {REG, CONST_DOUBLE}}, \
+{ "basereg_operand", {SUBREG, REG}},
/* An alias for a machine mode name. This is the machine mode that elements of
a jump-table should have. */
-#define CASE_VECTOR_MODE Pmode
+#define CASE_VECTOR_MODE ptr_mode
/* Define as C expression which evaluates to nonzero if the tablejump
instruction expects the table to contain offsets from the address of the
@@ -2452,7 +2344,7 @@ do { \
#define PREFETCH_BLOCK 32
-#define HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
/* In rare cases, correct code generation requires extra machine dependent
processing between the second jump optimization pass and delayed branch
@@ -2476,16 +2368,16 @@ extern int ia64_final_schedule;
#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 15 : INVALID_REGNUM)
/* This function contains machine specific function data. */
-struct machine_function
+struct machine_function GTY(())
{
/* The new stack pointer when unwinding from EH. */
- struct rtx_def* ia64_eh_epilogue_sp;
+ rtx ia64_eh_epilogue_sp;
/* The new bsp value when unwinding from EH. */
- struct rtx_def* ia64_eh_epilogue_bsp;
+ rtx ia64_eh_epilogue_bsp;
/* The GP value save register. */
- struct rtx_def* ia64_gp_save;
+ rtx ia64_gp_save;
/* The number of varargs registers to save. */
int n_varargs;
@@ -2558,4 +2450,5 @@ enum fetchop_code {
#undef PROFILE_BEFORE_PROLOGUE
#define PROFILE_BEFORE_PROLOGUE 1
+#define FUNCTION_OK_FOR_SIBCALL(DECL) ia64_function_ok_for_sibcall (DECL)
/* End of ia64.h */
diff --git a/contrib/gcc/config/ia64/ia64.md b/contrib/gcc/config/ia64/ia64.md
index 7b11c06..4d177c2 100644
--- a/contrib/gcc/config/ia64/ia64.md
+++ b/contrib/gcc/config/ia64/ia64.md
@@ -1,5 +1,5 @@
;; IA-64 Machine description template
-;; Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
;; Contributed by James E. Wilson <wilson@cygnus.com> and
;; David Mosberger <davidm@hpl.hp.com>.
@@ -48,35 +48,43 @@
;; ??? Need a better way to describe alternate fp status registers.
-;; Unspec usage:
-;;
-;; unspec:
-;; 1 gr_spill
-;; 2 gr_restore
-;; 3 fr_spill
-;; 4 fr_restore
-;; 5 recip_approx
-;; 7 pred_rel_mutex
-;; 8 popcnt
-;; 9 pic call
-;; 12 mf
-;; 13 cmpxchg_acq
-;; 19 fetchadd_acq
-;; 20 bsp_value
-;; 21 flushrs
-;; 22 bundle selector
-;; 23 cycle display
-;; 24 addp4
-;; 25 prologue_use
-;;
-;; unspec_volatile:
-;; 0 alloc
-;; 1 blockage
-;; 2 insn_group_barrier
-;; 3 break
-;; 5 set_bsp
-;; 8 pred.safe_across_calls all
-;; 9 pred.safe_across_calls normal
+(define_constants
+ [; Relocations
+ (UNSPEC_LTOFF_DTPMOD 0)
+ (UNSPEC_LTOFF_DTPREL 1)
+ (UNSPEC_DTPREL 2)
+ (UNSPEC_LTOFF_TPREL 3)
+ (UNSPEC_TPREL 4)
+
+ (UNSPEC_LD_BASE 9)
+ (UNSPEC_GR_SPILL 10)
+ (UNSPEC_GR_RESTORE 11)
+ (UNSPEC_FR_SPILL 12)
+ (UNSPEC_FR_RESTORE 13)
+ (UNSPEC_FR_RECIP_APPROX 14)
+ (UNSPEC_PRED_REL_MUTEX 15)
+ (UNSPEC_POPCNT 16)
+ (UNSPEC_PIC_CALL 17)
+ (UNSPEC_MF 18)
+ (UNSPEC_CMPXCHG_ACQ 19)
+ (UNSPEC_FETCHADD_ACQ 20)
+ (UNSPEC_BSP_VALUE 21)
+ (UNSPEC_FLUSHRS 22)
+ (UNSPEC_BUNDLE_SELECTOR 23)
+ (UNSPEC_ADDP4 24)
+ (UNSPEC_PROLOGUE_USE 25)
+ ])
+
+(define_constants
+ [(UNSPECV_ALLOC 0)
+ (UNSPECV_BLOCKAGE 1)
+ (UNSPECV_INSN_GROUP_BARRIER 2)
+ (UNSPECV_BREAK 3)
+ (UNSPECV_SET_BSP 4)
+ (UNSPECV_PSAC_ALL 5) ; pred.safe_across_calls
+ (UNSPECV_PSAC_NORMAL 6)
+ (UNSPECV_SETJMP_RECEIVER 7)
+ ])
;; ::::::::::::::::::::
;; ::
@@ -100,8 +108,12 @@
;; multiple instructions, patterns which emit 0 instructions, and patterns
;; which emit instruction that can go in any slot (e.g. nop).
-(define_attr "itanium_class" "unknown,ignore,stop_bit,br,fcmp,fcvtfx,fld,fmac,fmisc,frar_i,frar_m,frbr,frfr,frpr,ialu,icmp,ilog,ishf,ld,chk_s,long_i,mmmul,mmshf,mmshfi,rse_m,scall,sem,stf,st,syst_m0,syst_m,tbit,toar_i,toar_m,tobr,tofr,topr,xmpy,xtd,nop_b,nop_f,nop_i,nop_m,nop_x,lfetch"
- (const_string "unknown"))
+(define_attr "itanium_class" "unknown,ignore,stop_bit,br,fcmp,fcvtfx,fld,
+ fmac,fmisc,frar_i,frar_m,frbr,frfr,frpr,ialu,icmp,ilog,ishf,ld,
+ chk_s,long_i,mmmul,mmshf,mmshfi,rse_m,scall,sem,stf,st,syst_m0,
+ syst_m,tbit,toar_i,toar_m,tobr,tofr,topr,xmpy,xtd,nop_b,nop_f,
+ nop_i,nop_m,nop_x,lfetch"
+ (const_string "unknown"))
;; chk_s has an I and an M form; use type A for convenience.
(define_attr "type" "unknown,A,I,M,F,B,L,X,S"
@@ -262,7 +274,7 @@
&& GET_CODE (operands[1]) == REG && PR_REGNO_P (REGNO (operands[1]))"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))
- (set (match_dup 0) (unspec:BI [(match_dup 0)] 7))]
+ (set (match_dup 0) (unspec:BI [(match_dup 0)] UNSPEC_PRED_REL_MUTEX))]
"operands[2] = gen_rtx_REG (CCImode, REGNO (operands[0]));
operands[3] = gen_rtx_REG (CCImode, REGNO (operands[0]) + 1);
operands[4] = gen_rtx_REG (CCImode, REGNO (operands[1]));
@@ -272,12 +284,12 @@
[(set (match_operand:QI 0 "general_operand" "")
(match_operand:QI 1 "general_operand" ""))]
""
- "
{
- if (! reload_in_progress && ! reload_completed
- && ! ia64_move_ok (operands[0], operands[1]))
- operands[1] = force_reg (QImode, operands[1]);
-}")
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
(define_insn "*movqi_internal"
[(set (match_operand:QI 0 "destination_operand" "=r,r,r, m, r,*f,*f")
@@ -297,12 +309,12 @@
[(set (match_operand:HI 0 "general_operand" "")
(match_operand:HI 1 "general_operand" ""))]
""
- "
{
- if (! reload_in_progress && ! reload_completed
- && ! ia64_move_ok (operands[0], operands[1]))
- operands[1] = force_reg (HImode, operands[1]);
-}")
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
(define_insn "*movhi_internal"
[(set (match_operand:HI 0 "destination_operand" "=r,r,r, m, r,*f,*f")
@@ -322,12 +334,35 @@
[(set (match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" ""))]
""
- "
{
- if (! reload_in_progress && ! reload_completed
- && ! ia64_move_ok (operands[0], operands[1]))
- operands[1] = force_reg (SImode, operands[1]);
-}")
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
+
+;; This is used during early compilation to delay the decision on
+;; how to refer to a variable as long as possible. This is especially
+;; important between initial rtl generation and optimization for
+;; deferred functions, since we may acquire additional information
+;; on the variables used in the meantime.
+
+(define_insn_and_split "movsi_symbolic"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "symbolic_operand" "s"))
+ (clobber (match_scratch:DI 2 "=r"))
+ (use (reg:DI 1))]
+ ""
+ "* abort ();"
+ "!no_new_pseudos || reload_completed"
+ [(const_int 0)]
+{
+ rtx scratch = operands[2];
+ if (!reload_completed)
+ scratch = gen_reg_rtx (Pmode);
+ ia64_expand_load_address (operands[0], operands[1], scratch);
+ DONE;
+})
(define_insn "*movsi_internal"
[(set (match_operand:SI 0 "destination_operand" "=r,r,r,r, m, r,*f,*f, r,*d")
@@ -344,39 +379,19 @@
mov %0 = %1
mov %0 = %1
mov %0 = %r1"
-;; frar_m, toar_m ??? why not frar_i and toar_i
+ ;; frar_m, toar_m ??? why not frar_i and toar_i
[(set_attr "itanium_class" "ialu,ialu,long_i,ld,st,frfr,tofr,fmisc,frar_m,toar_m")])
(define_expand "movdi"
[(set (match_operand:DI 0 "general_operand" "")
(match_operand:DI 1 "general_operand" ""))]
""
- "
{
- if (! reload_in_progress && ! reload_completed
- && ! ia64_move_ok (operands[0], operands[1]))
- operands[1] = force_reg (DImode, operands[1]);
- if (! TARGET_NO_PIC && symbolic_operand (operands[1], DImode))
- {
- /* Before optimization starts, delay committing to any particular
- type of PIC address load. If this function gets deferred, we
- may acquire information that changes the value of the
- sdata_symbolic_operand predicate. */
- /* But don't delay for function pointers. Loading a function address
- actually loads the address of the descriptor not the function.
- If we represent these as SYMBOL_REFs, then they get cse'd with
- calls, and we end up with calls to the descriptor address instead of
- calls to the function address. Functions are not candidates for
- sdata anyways. */
- if (rtx_equal_function_value_matters
- && ! (GET_CODE (operands[1]) == SYMBOL_REF
- && SYMBOL_REF_FLAG (operands[1])))
- emit_insn (gen_movdi_symbolic (operands[0], operands[1], gen_reg_rtx (DImode)));
- else
- ia64_expand_load_address (operands[0], operands[1], NULL_RTX);
- DONE;
- }
-}")
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
;; This is used during early compilation to delay the decision on
;; how to refer to a variable as long as possible. This is especially
@@ -384,19 +399,22 @@
;; deferred functions, since we may acquire additional information
;; on the variables used in the meantime.
-;; ??? This causes us to lose REG_LABEL notes, because the insn splitter
-;; does not attempt to preserve any REG_NOTES on the input instruction.
-
(define_insn_and_split "movdi_symbolic"
[(set (match_operand:DI 0 "register_operand" "=r")
(match_operand:DI 1 "symbolic_operand" "s"))
- (clobber (match_operand:DI 2 "register_operand" "+r"))
+ (clobber (match_scratch:DI 2 "=r"))
(use (reg:DI 1))]
""
"* abort ();"
- ""
+ "!no_new_pseudos || reload_completed"
[(const_int 0)]
- "ia64_expand_load_address (operands[0], operands[1], operands[2]); DONE;")
+{
+ rtx scratch = operands[2];
+ if (!reload_completed)
+ scratch = gen_reg_rtx (Pmode);
+ ia64_expand_load_address (operands[0], operands[1], scratch);
+ DONE;
+})
(define_insn "*movdi_internal"
[(set (match_operand:DI 0 "destination_operand"
@@ -404,27 +422,26 @@
(match_operand:DI 1 "move_operand"
"rO,J,i,m,rO,*f,rO,*f, Q,*f,*b,rO,*e,rK,*d,rK,*c,rO"))]
"ia64_move_ok (operands[0], operands[1])"
- "*
{
static const char * const alt[] = {
- \"%,mov %0 = %r1\",
- \"%,addl %0 = %1, r0\",
- \"%,movl %0 = %1\",
- \"%,ld8%O1 %0 = %1%P1\",
- \"%,st8%Q0 %0 = %r1%P0\",
- \"%,getf.sig %0 = %1\",
- \"%,setf.sig %0 = %r1\",
- \"%,mov %0 = %1\",
- \"%,ldf8 %0 = %1%P1\",
- \"%,stf8 %0 = %1%P0\",
- \"%,mov %0 = %1\",
- \"%,mov %0 = %r1\",
- \"%,mov %0 = %1\",
- \"%,mov %0 = %1\",
- \"%,mov %0 = %1\",
- \"%,mov %0 = %1\",
- \"mov %0 = pr\",
- \"mov pr = %1, -1\"
+ "%,mov %0 = %r1",
+ "%,addl %0 = %1, r0",
+ "%,movl %0 = %1",
+ "%,ld8%O1 %0 = %1%P1",
+ "%,st8%Q0 %0 = %r1%P0",
+ "%,getf.sig %0 = %1",
+ "%,setf.sig %0 = %r1",
+ "%,mov %0 = %1",
+ "%,ldf8 %0 = %1%P1",
+ "%,stf8 %0 = %1%P0",
+ "%,mov %0 = %1",
+ "%,mov %0 = %r1",
+ "%,mov %0 = %1",
+ "%,mov %0 = %1",
+ "%,mov %0 = %1",
+ "%,mov %0 = %1",
+ "mov %0 = pr",
+ "mov pr = %1, -1"
};
if (which_alternative == 2 && ! TARGET_NO_PIC
@@ -432,7 +449,7 @@
abort ();
return alt[which_alternative];
-}"
+}
[(set_attr "itanium_class" "ialu,ialu,long_i,ld,st,frfr,tofr,fmisc,fld,stf,frbr,tobr,frar_i,toar_i,frar_m,toar_m,frpr,topr")])
(define_split
@@ -440,34 +457,32 @@
(match_operand:DI 1 "symbolic_operand" ""))]
"reload_completed && ! TARGET_NO_PIC"
[(const_int 0)]
- "
{
ia64_expand_load_address (operands[0], operands[1], NULL_RTX);
DONE;
-}")
+})
(define_expand "load_fptr"
[(set (match_dup 2)
- (plus:DI (reg:DI 1) (match_operand:DI 1 "function_operand" "")))
+ (plus:DI (reg:DI 1) (match_operand 1 "function_operand" "")))
(set (match_operand:DI 0 "register_operand" "") (match_dup 3))]
""
- "
{
operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
operands[3] = gen_rtx_MEM (DImode, operands[2]);
RTX_UNCHANGING_P (operands[3]) = 1;
-}")
+})
(define_insn "*load_fptr_internal1"
[(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (reg:DI 1) (match_operand:DI 1 "function_operand" "s")))]
+ (plus:DI (reg:DI 1) (match_operand 1 "function_operand" "s")))]
""
"addl %0 = @ltoff(@fptr(%1)), gp"
[(set_attr "itanium_class" "ialu")])
(define_insn "load_gprel"
[(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (reg:DI 1) (match_operand:DI 1 "sdata_symbolic_operand" "s")))]
+ (plus:DI (reg:DI 1) (match_operand 1 "sdata_symbolic_operand" "s")))]
""
"addl %0 = @gprel(%1), gp"
[(set_attr "itanium_class" "ialu")])
@@ -485,29 +500,171 @@
(set (match_operand:DI 0 "register_operand" "")
(plus:DI (match_dup 3) (match_dup 2)))]
""
- "
{
operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
operands[3] = pic_offset_table_rtx;
-}")
+})
(define_expand "load_symptr"
[(set (match_operand:DI 2 "register_operand" "")
- (plus:DI (match_dup 4) (match_operand:DI 1 "got_symbolic_operand" "")))
- (set (match_operand:DI 0 "register_operand" "") (match_dup 3))]
+ (plus:DI (high:DI (match_operand:DI 1 "got_symbolic_operand" ""))
+ (match_dup 3)))
+ (set (match_operand:DI 0 "register_operand" "")
+ (lo_sum:DI (match_dup 2) (match_dup 1)))]
""
- "
{
- operands[3] = gen_rtx_MEM (DImode, operands[2]);
- operands[4] = pic_offset_table_rtx;
- RTX_UNCHANGING_P (operands[3]) = 1;
-}")
+ operands[3] = pic_offset_table_rtx;
+})
+
+(define_insn "*load_symptr_high"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (high:DI (match_operand 1 "got_symbolic_operand" "s"))
+ (match_operand:DI 2 "register_operand" "a")))]
+ ""
+{
+ if (HAVE_AS_LTOFFX_LDXMOV_RELOCS)
+ return "%,addl %0 = @ltoffx(%1), %2";
+ else
+ return "%,addl %0 = @ltoff(%1), %2";
+}
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*load_symptr_low"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand 2 "got_symbolic_operand" "s")))]
+ ""
+{
+ if (HAVE_AS_LTOFFX_LDXMOV_RELOCS)
+ return "%,ld8.mov %0 = [%1], %2";
+ else
+ return "%,ld8 %0 = [%1]";
+}
+ [(set_attr "itanium_class" "ld")])
+
+(define_insn "load_ltoff_dtpmod"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (reg:DI 1)
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_LTOFF_DTPMOD)))]
+ ""
+ "addl %0 = @ltoff(@dtpmod(%1)), gp"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "load_ltoff_dtprel"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (reg:DI 1)
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_LTOFF_DTPREL)))]
+ ""
+ "addl %0 = @ltoff(@dtprel(%1)), gp"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_expand "load_dtprel"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_DTPREL))]
+ ""
+ "")
-(define_insn "*load_symptr_internal1"
+(define_insn "*load_dtprel64"
[(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (reg:DI 1) (match_operand:DI 1 "got_symbolic_operand" "s")))]
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_DTPREL))]
+ "TARGET_TLS64"
+ "movl %0 = @dtprel(%1)"
+ [(set_attr "itanium_class" "long_i")])
+
+(define_insn "*load_dtprel22"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_DTPREL))]
""
- "addl %0 = @ltoff(%1), gp"
+ "addl %0 = @dtprel(%1), r0"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_expand "add_dtprel"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (match_operand:DI 1 "register_operand" "")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+ UNSPEC_DTPREL)))]
+ "!TARGET_TLS64"
+ "")
+
+(define_insn "*add_dtprel14"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+ UNSPEC_DTPREL)))]
+ "TARGET_TLS14"
+ "adds %0 = @dtprel(%2), %1"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*add_dtprel22"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "a")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+ UNSPEC_DTPREL)))]
+ "TARGET_TLS22"
+ "addl %0 = @dtprel(%2), %1"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "load_ltoff_tprel"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (reg:DI 1)
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_LTOFF_TPREL)))]
+ ""
+ "addl %0 = @ltoff(@tprel(%1)), gp"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_expand "load_tprel"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_TPREL))]
+ ""
+ "")
+
+(define_insn "*load_tprel64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_TPREL))]
+ "TARGET_TLS64"
+ "movl %0 = @tprel(%1)"
+ [(set_attr "itanium_class" "long_i")])
+
+(define_insn "*load_tprel22"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_TPREL))]
+ ""
+ "addl %0 = @tprel(%1), r0"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_expand "add_tprel"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (match_operand:DI 1 "register_operand" "")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+ UNSPEC_TPREL)))]
+ "!TARGET_TLS64"
+ "")
+
+(define_insn "*add_tprel14"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+ UNSPEC_TPREL)))]
+ "TARGET_TLS14"
+ "adds %0 = @tprel(%2), %1"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*add_tprel22"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "a")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+ UNSPEC_TPREL)))]
+ "TARGET_TLS22"
+ "addl %0 = @tprel(%2), %1"
[(set_attr "itanium_class" "ialu")])
;; With no offsettable memory references, we've got to have a scratch
@@ -517,12 +674,12 @@
(match_operand:TI 1 "general_operand" ""))
(clobber (match_scratch:DI 2 ""))])]
""
- "
{
- if (! reload_in_progress && ! reload_completed
- && ! ia64_move_ok (operands[0], operands[1]))
- operands[1] = force_reg (TImode, operands[1]);
-}")
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
(define_insn_and_split "*movti_internal"
[(set (match_operand:TI 0 "nonimmediate_operand" "=r,r,m")
@@ -532,7 +689,6 @@
"#"
"reload_completed"
[(const_int 0)]
- "
{
rtx adj1, adj2, in[2], out[2], insn;
int first;
@@ -567,7 +723,7 @@
XEXP (XEXP (out[!first], 0), 0),
REG_NOTES (insn));
DONE;
-}"
+}
[(set_attr "itanium_class" "unknown")
(set_attr "predicable" "no")])
@@ -581,7 +737,6 @@
"#"
"reload_completed"
[(const_int 0)]
- "
{
rtx in[2], out[2];
int first;
@@ -600,7 +755,7 @@
emit_insn (gen_rtx_SET (VOIDmode, out[first], in[first]));
emit_insn (gen_rtx_SET (VOIDmode, out[!first], in[!first]));
DONE;
-}"
+}
[(set_attr "itanium_class" "unknown")
(set_attr "predicable" "no")])
@@ -609,82 +764,80 @@
(match_operand:TI 1 "" "m"))
(clobber (match_operand:TI 2 "register_operand" "=&r"))])]
""
- "
{
unsigned int s_regno = REGNO (operands[2]);
if (s_regno == REGNO (operands[0]))
s_regno += 1;
operands[2] = gen_rtx_REG (DImode, s_regno);
-}")
+})
(define_expand "reload_outti"
[(parallel [(set (match_operand:TI 0 "" "=m")
(match_operand:TI 1 "register_operand" "r"))
(clobber (match_operand:TI 2 "register_operand" "=&r"))])]
""
- "
{
unsigned int s_regno = REGNO (operands[2]);
if (s_regno == REGNO (operands[1]))
s_regno += 1;
operands[2] = gen_rtx_REG (DImode, s_regno);
-}")
+})
;; Floating Point Moves
;;
;; Note - Patterns for SF mode moves are compulsory, but
-;; patterns for DF are optional, as GCC can synthesise them.
+;; patterns for DF are optional, as GCC can synthesize them.
(define_expand "movsf"
[(set (match_operand:SF 0 "general_operand" "")
(match_operand:SF 1 "general_operand" ""))]
""
- "
{
- if (! reload_in_progress && ! reload_completed
- && ! ia64_move_ok (operands[0], operands[1]))
- operands[1] = force_reg (SFmode, operands[1]);
-}")
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
(define_insn "*movsf_internal"
[(set (match_operand:SF 0 "destination_operand" "=f,f, Q,*r, f,*r,*r, m")
(match_operand:SF 1 "general_operand" "fG,Q,fG,fG,*r,*r, m,*r"))]
"ia64_move_ok (operands[0], operands[1])"
"@
- mov %0 = %F1
- ldfs %0 = %1%P1
- stfs %0 = %F1%P0
- getf.s %0 = %F1
- setf.s %0 = %1
- mov %0 = %1
- ld4%O1 %0 = %1%P1
- st4%Q0 %0 = %1%P0"
+ mov %0 = %F1
+ ldfs %0 = %1%P1
+ stfs %0 = %F1%P0
+ getf.s %0 = %F1
+ setf.s %0 = %1
+ mov %0 = %1
+ ld4%O1 %0 = %1%P1
+ st4%Q0 %0 = %1%P0"
[(set_attr "itanium_class" "fmisc,fld,stf,frfr,tofr,ialu,ld,st")])
(define_expand "movdf"
[(set (match_operand:DF 0 "general_operand" "")
(match_operand:DF 1 "general_operand" ""))]
""
- "
{
- if (! reload_in_progress && ! reload_completed
- && ! ia64_move_ok (operands[0], operands[1]))
- operands[1] = force_reg (DFmode, operands[1]);
-}")
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
(define_insn "*movdf_internal"
[(set (match_operand:DF 0 "destination_operand" "=f,f, Q,*r, f,*r,*r, m")
(match_operand:DF 1 "general_operand" "fG,Q,fG,fG,*r,*r, m,*r"))]
"ia64_move_ok (operands[0], operands[1])"
"@
- mov %0 = %F1
- ldfd %0 = %1%P1
- stfd %0 = %F1%P0
- getf.d %0 = %F1
- setf.d %0 = %1
- mov %0 = %1
- ld8%O1 %0 = %1%P1
- st8%Q0 %0 = %1%P0"
+ mov %0 = %F1
+ ldfd %0 = %1%P1
+ stfd %0 = %F1%P0
+ getf.d %0 = %F1
+ setf.d %0 = %1
+ mov %0 = %1
+ ld8%O1 %0 = %1%P1
+ st8%Q0 %0 = %1%P0"
[(set_attr "itanium_class" "fmisc,fld,stf,frfr,tofr,ialu,ld,st")])
;; With no offsettable memory references, we've got to have a scratch
@@ -693,7 +846,6 @@
[(set (match_operand:TF 0 "general_operand" "")
(match_operand:TF 1 "general_operand" ""))]
"INTEL_EXTENDED_IEEE_FORMAT"
- "
{
/* We must support TFmode loads into general registers for stdarg/vararg
and unprototyped calls. We split them into DImode loads for convenience.
@@ -754,7 +906,7 @@
if (! ia64_move_ok (operands[0], operands[1]))
operands[1] = force_reg (TFmode, operands[1]);
}
-}")
+})
;; ??? There's no easy way to mind volatile acquire/release semantics.
@@ -763,9 +915,9 @@
(match_operand:TF 1 "general_tfmode_operand" "fG,m,fG"))]
"INTEL_EXTENDED_IEEE_FORMAT && ia64_move_ok (operands[0], operands[1])"
"@
- mov %0 = %F1
- ldfe %0 = %1%P1
- stfe %0 = %F1%P0"
+ mov %0 = %F1
+ ldfe %0 = %1%P1
+ stfe %0 = %F1%P0"
[(set_attr "itanium_class" "fmisc,fld,stf")])
;; ::::::::::::::::::::
@@ -902,7 +1054,7 @@
[(set (match_operand:DF 0 "register_operand" "=f")
(float:DF (match_operand:DI 1 "register_operand" "f")))]
"!INTEL_EXTENDED_IEEE_FORMAT"
- "fcvt.xf %0 = %1\;;;\;fnorm.d %0 = %0"
+ "fcvt.xf %0 = %1\;;;\;%,fnorm.d %0 = %0"
[(set_attr "itanium_class" "fcvtfx")])
;; ??? Suboptimal. This should be split somehow.
@@ -910,7 +1062,7 @@
[(set (match_operand:SF 0 "register_operand" "=f")
(float:SF (match_operand:DI 1 "register_operand" "f")))]
"!INTEL_EXTENDED_IEEE_FORMAT"
- "fcvt.xf %0 = %1\;;;\;fnorm.s %0 = %0"
+ "fcvt.xf %0 = %1\;;;\;%,fnorm.s %0 = %0"
[(set_attr "itanium_class" "fcvtfx")])
(define_insn "fix_truncsfdi2"
@@ -1033,7 +1185,6 @@
(match_operand:DI 2 "const_int_operand" ""))
(match_operand:DI 3 "nonmemory_operand" ""))]
""
- "
{
int width = INTVAL (operands[1]);
int shift = INTVAL (operands[2]);
@@ -1101,7 +1252,7 @@
operands[2] = GEN_INT (shift);
#endif
}
-}")
+})
(define_insn "*insv_internal"
[(set (zero_extract:DI (match_operand:DI 0 "gr_register_operand" "+r")
@@ -1113,7 +1264,7 @@
"dep %0 = %3, %0, %2, %1"
[(set_attr "itanium_class" "ishf")])
-;; Combine doesn't like to create bitfield insertions into zero.
+;; Combine doesn't like to create bit-field insertions into zero.
(define_insn "*depz_internal"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
(and:DI (ashift:DI (match_operand:DI 1 "gr_register_operand" "r")
@@ -1121,11 +1272,10 @@
(match_operand:DI 3 "const_int_operand" "n")))]
"CONST_OK_FOR_M (INTVAL (operands[2]))
&& ia64_depz_field_mask (operands[3], operands[2]) > 0"
- "*
{
operands[3] = GEN_INT (ia64_depz_field_mask (operands[3], operands[2]));
- return \"%,dep.z %0 = %1, %2, %3\";
-}"
+ return "%,dep.z %0 = %1, %2, %3";
+}
[(set_attr "itanium_class" "ishf")])
(define_insn "shift_mix4left"
@@ -1289,7 +1439,7 @@
(set (match_dup 0) (const_int 1))
(cond_exec (ne (match_dup 2) (const_int 0))
(set (match_dup 0) (const_int 0)))
- (set (match_dup 0) (unspec:BI [(match_dup 0)] 7))]
+ (set (match_dup 0) (unspec:BI [(match_dup 0)] UNSPEC_PRED_REL_MUTEX))]
"operands[3] = gen_rtx_REG (CCImode, REGNO (operands[1]));
operands[4] = gen_rtx_REG (CCImode, REGNO (operands[2]));")
@@ -1305,7 +1455,7 @@
(set (match_dup 0) (const_int 0)))
(cond_exec (eq (match_dup 1) (const_int 0))
(set (match_dup 0) (const_int 1)))
- (set (match_dup 0) (unspec:BI [(match_dup 0)] 7))]
+ (set (match_dup 0) (unspec:BI [(match_dup 0)] UNSPEC_PRED_REL_MUTEX))]
"")
(define_insn "*cmpsi_and_0"
@@ -1693,7 +1843,7 @@
(set (match_operand:CCI 4 "register_operand" "")
(match_operand:CCI 5 "register_operand" ""))
(set (match_operand:BI 6 "register_operand" "")
- (unspec:BI [(match_dup 6)] 7))]
+ (unspec:BI [(match_dup 6)] UNSPEC_PRED_REL_MUTEX))]
"REGNO (operands[3]) == REGNO (operands[0])
&& REGNO (operands[4]) == REGNO (operands[0]) + 1
&& REGNO (operands[4]) == REGNO (operands[2]) + 1
@@ -1729,9 +1879,9 @@
(match_operand:SI 2 "gr_reg_or_22bit_operand" "r,I,J")))]
""
"@
- add %0 = %1, %2
- adds %0 = %2, %1
- addl %0 = %2, %1"
+ add %0 = %1, %2
+ adds %0 = %2, %1
+ addl %0 = %2, %1"
[(set_attr "itanium_class" "ialu")])
(define_insn "*addsi3_plus1"
@@ -1811,10 +1961,7 @@
(neg:SI (match_dup 1))
(match_dup 1)))]
""
- "
-{
- operands[2] = gen_reg_rtx (BImode);
-}")
+ { operands[2] = gen_reg_rtx (BImode); })
(define_expand "sminsi3"
[(set (match_dup 3)
@@ -1824,10 +1971,7 @@
(if_then_else:SI (ne (match_dup 3) (const_int 0))
(match_dup 2) (match_dup 1)))]
""
- "
-{
- operands[3] = gen_reg_rtx (BImode);
-}")
+ { operands[3] = gen_reg_rtx (BImode); })
(define_expand "smaxsi3"
[(set (match_dup 3)
@@ -1837,10 +1981,7 @@
(if_then_else:SI (ne (match_dup 3) (const_int 0))
(match_dup 1) (match_dup 2)))]
""
- "
-{
- operands[3] = gen_reg_rtx (BImode);
-}")
+ { operands[3] = gen_reg_rtx (BImode); })
(define_expand "uminsi3"
[(set (match_dup 3)
@@ -1850,10 +1991,7 @@
(if_then_else:SI (ne (match_dup 3) (const_int 0))
(match_dup 2) (match_dup 1)))]
""
- "
-{
- operands[3] = gen_reg_rtx (BImode);
-}")
+ { operands[3] = gen_reg_rtx (BImode); })
(define_expand "umaxsi3"
[(set (match_dup 3)
@@ -1863,19 +2001,16 @@
(if_then_else:SI (ne (match_dup 3) (const_int 0))
(match_dup 1) (match_dup 2)))]
""
- "
-{
- operands[3] = gen_reg_rtx (BImode);
-}")
+ { operands[3] = gen_reg_rtx (BImode); })
(define_expand "divsi3"
[(set (match_operand:SI 0 "register_operand" "")
(div:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
{
rtx op1_tf, op2_tf, op0_tf, op0_di, twon34;
+ REAL_VALUE_TYPE twon34_r;
op0_tf = gen_reg_rtx (TFmode);
op0_di = gen_reg_rtx (DImode);
@@ -1891,28 +2026,22 @@
expand_float (op2_tf, operands[2], 0);
/* 2^-34 */
-#if 0
- twon34 = (CONST_DOUBLE_FROM_REAL_VALUE
- (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), TFmode));
+ real_2expN (&twon34_r, -34);
+ twon34 = CONST_DOUBLE_FROM_REAL_VALUE (twon34_r, TFmode);
twon34 = force_reg (TFmode, twon34);
-#else
- twon34 = gen_reg_rtx (TFmode);
- convert_move (twon34, force_const_mem (SFmode, CONST_DOUBLE_FROM_REAL_VALUE (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), SFmode)), 0);
-#endif
emit_insn (gen_divsi3_internal (op0_tf, op1_tf, op2_tf, twon34));
emit_insn (gen_fix_trunctfdi2_alts (op0_di, op0_tf, const1_rtx));
emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
DONE;
-}")
+})
(define_expand "modsi3"
[(set (match_operand:SI 0 "register_operand" "")
(mod:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
{
rtx op2_neg, op1_di, div;
@@ -1929,16 +2058,16 @@
emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
gen_lowpart (SImode, op1_di)));
DONE;
-}")
+})
(define_expand "udivsi3"
[(set (match_operand:SI 0 "register_operand" "")
(udiv:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
{
rtx op1_tf, op2_tf, op0_tf, op0_di, twon34;
+ REAL_VALUE_TYPE twon34_r;
op0_tf = gen_reg_rtx (TFmode);
op0_di = gen_reg_rtx (DImode);
@@ -1954,28 +2083,22 @@
expand_float (op2_tf, operands[2], 1);
/* 2^-34 */
-#if 0
- twon34 = (CONST_DOUBLE_FROM_REAL_VALUE
- (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), TFmode));
+ real_2expN (&twon34_r, -34);
+ twon34 = CONST_DOUBLE_FROM_REAL_VALUE (twon34_r, TFmode);
twon34 = force_reg (TFmode, twon34);
-#else
- twon34 = gen_reg_rtx (TFmode);
- convert_move (twon34, force_const_mem (SFmode, CONST_DOUBLE_FROM_REAL_VALUE (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), SFmode)), 0);
-#endif
emit_insn (gen_divsi3_internal (op0_tf, op1_tf, op2_tf, twon34));
emit_insn (gen_fixuns_trunctfdi2_alts (op0_di, op0_tf, const1_rtx));
emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
DONE;
-}")
+})
(define_expand "umodsi3"
[(set (match_operand:SI 0 "register_operand" "")
(umod:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
{
rtx op2_neg, op1_di, div;
@@ -1992,7 +2115,7 @@
emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
gen_lowpart (SImode, op1_di)));
DONE;
-}")
+})
(define_insn_and_split "divsi3_internal"
[(set (match_operand:TF 0 "fr_register_operand" "=&f")
@@ -2002,11 +2125,12 @@
(clobber (match_scratch:TF 5 "=&f"))
(clobber (match_scratch:BI 6 "=c"))
(use (match_operand:TF 3 "fr_register_operand" "f"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:TF (const_int 1) (match_dup 2)))
- (set (match_dup 6) (unspec:BI [(match_dup 1) (match_dup 2)] 5))
+ (set (match_dup 6) (unspec:BI [(match_dup 1) (match_dup 2)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4) (mult:TF (match_dup 1) (match_dup 0)))
@@ -2047,9 +2171,9 @@
(match_operand:DI 2 "gr_reg_or_22bit_operand" "r,I,J")))]
""
"@
- add %0 = %1, %2
- adds %0 = %2, %1
- addl %0 = %2, %1"
+ add %0 = %1, %2
+ adds %0 = %2, %1
+ addl %0 = %2, %1"
[(set_attr "itanium_class" "ialu")])
(define_insn "*adddi3_plus1"
@@ -2198,10 +2322,7 @@
(neg:DI (match_dup 1))
(match_dup 1)))]
""
- "
-{
- operands[2] = gen_reg_rtx (BImode);
-}")
+ { operands[2] = gen_reg_rtx (BImode); })
(define_expand "smindi3"
[(set (match_dup 3)
@@ -2211,10 +2332,7 @@
(if_then_else:DI (ne (match_dup 3) (const_int 0))
(match_dup 2) (match_dup 1)))]
""
- "
-{
- operands[3] = gen_reg_rtx (BImode);
-}")
+ { operands[3] = gen_reg_rtx (BImode); })
(define_expand "smaxdi3"
[(set (match_dup 3)
@@ -2224,10 +2342,7 @@
(if_then_else:DI (ne (match_dup 3) (const_int 0))
(match_dup 1) (match_dup 2)))]
""
- "
-{
- operands[3] = gen_reg_rtx (BImode);
-}")
+ { operands[3] = gen_reg_rtx (BImode); })
(define_expand "umindi3"
[(set (match_dup 3)
@@ -2237,10 +2352,7 @@
(if_then_else:DI (ne (match_dup 3) (const_int 0))
(match_dup 2) (match_dup 1)))]
""
- "
-{
- operands[3] = gen_reg_rtx (BImode);
-}")
+ { operands[3] = gen_reg_rtx (BImode); })
(define_expand "umaxdi3"
[(set (match_dup 3)
@@ -2250,10 +2362,7 @@
(if_then_else:DI (ne (match_dup 3) (const_int 0))
(match_dup 1) (match_dup 2)))]
""
- "
-{
- operands[3] = gen_reg_rtx (BImode);
-}")
+ { operands[3] = gen_reg_rtx (BImode); })
(define_expand "ffsdi2"
[(set (match_dup 6)
@@ -2261,23 +2370,23 @@
(set (match_dup 2) (plus:DI (match_dup 1) (const_int -1)))
(set (match_dup 5) (const_int 0))
(set (match_dup 3) (xor:DI (match_dup 1) (match_dup 2)))
- (set (match_dup 4) (unspec:DI [(match_dup 3)] 8))
+ (set (match_dup 4) (unspec:DI [(match_dup 3)] UNSPEC_POPCNT))
(set (match_operand:DI 0 "gr_register_operand" "")
(if_then_else:DI (ne (match_dup 6) (const_int 0))
(match_dup 5) (match_dup 4)))]
""
- "
{
operands[2] = gen_reg_rtx (DImode);
operands[3] = gen_reg_rtx (DImode);
operands[4] = gen_reg_rtx (DImode);
operands[5] = gen_reg_rtx (DImode);
operands[6] = gen_reg_rtx (BImode);
-}")
+})
(define_insn "*popcnt"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "gr_register_operand" "r")] 8))]
+ (unspec:DI [(match_operand:DI 1 "gr_register_operand" "r")]
+ UNSPEC_POPCNT))]
""
"popcnt %0 = %1"
[(set_attr "itanium_class" "mmmul")])
@@ -2286,8 +2395,7 @@
[(set (match_operand:DI 0 "register_operand" "")
(div:DI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
{
rtx op1_tf, op2_tf, op0_tf;
@@ -2303,21 +2411,20 @@
op2_tf = gen_reg_rtx (TFmode);
expand_float (op2_tf, operands[2], 0);
- if (TARGET_INLINE_DIV_LAT)
+ if (TARGET_INLINE_INT_DIV_LAT)
emit_insn (gen_divdi3_internal_lat (op0_tf, op1_tf, op2_tf));
else
emit_insn (gen_divdi3_internal_thr (op0_tf, op1_tf, op2_tf));
emit_insn (gen_fix_trunctfdi2_alts (operands[0], op0_tf, const1_rtx));
DONE;
-}")
+})
(define_expand "moddi3"
[(set (match_operand:DI 0 "register_operand" "")
(mod:SI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
{
rtx op2_neg, div;
@@ -2328,14 +2435,13 @@
emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
DONE;
-}")
+})
(define_expand "udivdi3"
[(set (match_operand:DI 0 "register_operand" "")
(udiv:DI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
{
rtx op1_tf, op2_tf, op0_tf;
@@ -2351,21 +2457,20 @@
op2_tf = gen_reg_rtx (TFmode);
expand_float (op2_tf, operands[2], 1);
- if (TARGET_INLINE_DIV_LAT)
+ if (TARGET_INLINE_INT_DIV_LAT)
emit_insn (gen_divdi3_internal_lat (op0_tf, op1_tf, op2_tf));
else
emit_insn (gen_divdi3_internal_thr (op0_tf, op1_tf, op2_tf));
emit_insn (gen_fixuns_trunctfdi2_alts (operands[0], op0_tf, const1_rtx));
DONE;
-}")
+})
(define_expand "umoddi3"
[(set (match_operand:DI 0 "register_operand" "")
(umod:DI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
{
rtx op2_neg, div;
@@ -2376,7 +2481,7 @@
emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
DONE;
-}")
+})
(define_insn_and_split "divdi3_internal_lat"
[(set (match_operand:TF 0 "fr_register_operand" "=&f")
@@ -2386,11 +2491,12 @@
(clobber (match_scratch:TF 4 "=&f"))
(clobber (match_scratch:TF 5 "=&f"))
(clobber (match_scratch:BI 6 "=c"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV_LAT"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV_LAT"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:TF (const_int 1) (match_dup 2)))
- (set (match_dup 6) (unspec:BI [(match_dup 1) (match_dup 2)] 5))
+ (set (match_dup 6) (unspec:BI [(match_dup 1) (match_dup 2)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3)
@@ -2444,11 +2550,12 @@
(clobber (match_scratch:TF 3 "=&f"))
(clobber (match_scratch:TF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV_THR"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV_THR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:TF (const_int 1) (match_dup 2)))
- (set (match_dup 5) (unspec:BI [(match_dup 1) (match_dup 2)] 5))
+ (set (match_dup 5) (unspec:BI [(match_dup 1) (match_dup 2)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
@@ -2594,17 +2701,16 @@
[(set (match_operand:SF 0 "fr_register_operand" "")
(div:SF (match_operand:SF 1 "fr_register_operand" "")
(match_operand:SF 2 "fr_register_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV"
{
rtx insn;
- if (TARGET_INLINE_DIV_LAT)
+ if (TARGET_INLINE_FLOAT_DIV_LAT)
insn = gen_divsf3_internal_lat (operands[0], operands[1], operands[2]);
else
insn = gen_divsf3_internal_thr (operands[0], operands[1], operands[2]);
emit_insn (insn);
DONE;
-}")
+})
(define_insn_and_split "divsf3_internal_lat"
[(set (match_operand:SF 0 "fr_register_operand" "=&f")
@@ -2613,11 +2719,12 @@
(clobber (match_scratch:TF 3 "=&f"))
(clobber (match_scratch:TF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV_LAT"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV_LAT"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 6) (div:TF (const_int 1) (match_dup 8)))
- (set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)] 5))
+ (set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3) (mult:TF (match_dup 7) (match_dup 6)))
@@ -2653,11 +2760,13 @@
(set (match_dup 0)
(float_truncate:SF (match_dup 6))))
]
- "operands[6] = gen_rtx_REG (TFmode, REGNO (operands[0]));
- operands[7] = gen_rtx_REG (TFmode, REGNO (operands[1]));
- operands[8] = gen_rtx_REG (TFmode, REGNO (operands[2]));
- operands[9] = gen_rtx_REG (DFmode, REGNO (operands[0]));
- operands[10] = CONST1_RTX (TFmode);"
+{
+ operands[6] = gen_rtx_REG (TFmode, REGNO (operands[0]));
+ operands[7] = gen_rtx_REG (TFmode, REGNO (operands[1]));
+ operands[8] = gen_rtx_REG (TFmode, REGNO (operands[2]));
+ operands[9] = gen_rtx_REG (DFmode, REGNO (operands[0]));
+ operands[10] = CONST1_RTX (TFmode);
+}
[(set_attr "predicable" "no")])
(define_insn_and_split "divsf3_internal_thr"
@@ -2667,11 +2776,12 @@
(clobber (match_scratch:TF 3 "=&f"))
(clobber (match_scratch:TF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV_THR"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV_THR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 6) (div:TF (const_int 1) (match_dup 8)))
- (set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)] 5))
+ (set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
@@ -2704,11 +2814,13 @@
(plus:TF (mult:TF (match_dup 4) (match_dup 6))
(match_dup 3)))))
]
- "operands[6] = gen_rtx_REG (TFmode, REGNO (operands[0]));
- operands[7] = gen_rtx_REG (TFmode, REGNO (operands[1]));
- operands[8] = gen_rtx_REG (TFmode, REGNO (operands[2]));
- operands[9] = gen_rtx_REG (SFmode, REGNO (operands[3]));
- operands[10] = CONST1_RTX (TFmode);"
+{
+ operands[6] = gen_rtx_REG (TFmode, REGNO (operands[0]));
+ operands[7] = gen_rtx_REG (TFmode, REGNO (operands[1]));
+ operands[8] = gen_rtx_REG (TFmode, REGNO (operands[2]));
+ operands[9] = gen_rtx_REG (SFmode, REGNO (operands[3]));
+ operands[10] = CONST1_RTX (TFmode);
+}
[(set_attr "predicable" "no")])
;; ::::::::::::::::::::
@@ -2898,17 +3010,16 @@
[(set (match_operand:DF 0 "fr_register_operand" "")
(div:DF (match_operand:DF 1 "fr_register_operand" "")
(match_operand:DF 2 "fr_register_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV"
{
rtx insn;
- if (TARGET_INLINE_DIV_LAT)
+ if (TARGET_INLINE_FLOAT_DIV_LAT)
insn = gen_divdf3_internal_lat (operands[0], operands[1], operands[2]);
else
insn = gen_divdf3_internal_thr (operands[0], operands[1], operands[2]);
emit_insn (insn);
DONE;
-}")
+})
(define_insn_and_split "divdf3_internal_lat"
[(set (match_operand:DF 0 "fr_register_operand" "=&f")
@@ -2918,11 +3029,12 @@
(clobber (match_scratch:TF 4 "=&f"))
(clobber (match_scratch:TF 5 "=&f"))
(clobber (match_scratch:BI 6 "=c"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV_LAT"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV_LAT"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 7) (div:TF (const_int 1) (match_dup 9)))
- (set (match_dup 6) (unspec:BI [(match_dup 8) (match_dup 9)] 5))
+ (set (match_dup 6) (unspec:BI [(match_dup 8) (match_dup 9)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3) (mult:TF (match_dup 8) (match_dup 7)))
@@ -2980,12 +3092,14 @@
(float_truncate:DF (plus:TF (mult:TF (match_dup 5) (match_dup 7))
(match_dup 3)))))
]
- "operands[7] = gen_rtx_REG (TFmode, REGNO (operands[0]));
- operands[8] = gen_rtx_REG (TFmode, REGNO (operands[1]));
- operands[9] = gen_rtx_REG (TFmode, REGNO (operands[2]));
- operands[10] = gen_rtx_REG (DFmode, REGNO (operands[3]));
- operands[11] = gen_rtx_REG (DFmode, REGNO (operands[5]));
- operands[12] = CONST1_RTX (TFmode);"
+{
+ operands[7] = gen_rtx_REG (TFmode, REGNO (operands[0]));
+ operands[8] = gen_rtx_REG (TFmode, REGNO (operands[1]));
+ operands[9] = gen_rtx_REG (TFmode, REGNO (operands[2]));
+ operands[10] = gen_rtx_REG (DFmode, REGNO (operands[3]));
+ operands[11] = gen_rtx_REG (DFmode, REGNO (operands[5]));
+ operands[12] = CONST1_RTX (TFmode);
+}
[(set_attr "predicable" "no")])
(define_insn_and_split "divdf3_internal_thr"
@@ -2995,11 +3109,12 @@
(clobber (match_scratch:TF 3 "=&f"))
(clobber (match_scratch:DF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV_THR"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV_THR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 6) (div:TF (const_int 1) (match_dup 8)))
- (set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)] 5))
+ (set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
@@ -3044,11 +3159,13 @@
(plus:DF (mult:DF (match_dup 4) (match_dup 0))
(match_dup 9))))
]
- "operands[6] = gen_rtx_REG (TFmode, REGNO (operands[0]));
- operands[7] = gen_rtx_REG (TFmode, REGNO (operands[1]));
- operands[8] = gen_rtx_REG (TFmode, REGNO (operands[2]));
- operands[9] = gen_rtx_REG (DFmode, REGNO (operands[3]));
- operands[10] = CONST1_RTX (TFmode);"
+{
+ operands[6] = gen_rtx_REG (TFmode, REGNO (operands[0]));
+ operands[7] = gen_rtx_REG (TFmode, REGNO (operands[1]));
+ operands[8] = gen_rtx_REG (TFmode, REGNO (operands[2]));
+ operands[9] = gen_rtx_REG (DFmode, REGNO (operands[3]));
+ operands[10] = CONST1_RTX (TFmode);
+}
[(set_attr "predicable" "no")])
;; ::::::::::::::::::::
@@ -3370,17 +3487,16 @@
[(set (match_operand:TF 0 "fr_register_operand" "")
(div:TF (match_operand:TF 1 "fr_register_operand" "")
(match_operand:TF 2 "fr_register_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV"
{
rtx insn;
- if (TARGET_INLINE_DIV_LAT)
+ if (TARGET_INLINE_FLOAT_DIV_LAT)
insn = gen_divtf3_internal_lat (operands[0], operands[1], operands[2]);
else
insn = gen_divtf3_internal_thr (operands[0], operands[1], operands[2]);
emit_insn (insn);
DONE;
-}")
+})
(define_insn_and_split "divtf3_internal_lat"
[(set (match_operand:TF 0 "fr_register_operand" "=&f")
@@ -3391,11 +3507,12 @@
(clobber (match_scratch:TF 5 "=&f"))
(clobber (match_scratch:TF 6 "=&f"))
(clobber (match_scratch:BI 7 "=c"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV_LAT"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV_LAT"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:TF (const_int 1) (match_dup 2)))
- (set (match_dup 7) (unspec:BI [(match_dup 1) (match_dup 2)] 5))
+ (set (match_dup 7) (unspec:BI [(match_dup 1) (match_dup 2)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 3)
@@ -3468,11 +3585,12 @@
(clobber (match_scratch:TF 3 "=&f"))
(clobber (match_scratch:TF 4 "=&f"))
(clobber (match_scratch:BI 5 "=c"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV_THR"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV_THR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:TF (const_int 1) (match_dup 2)))
- (set (match_dup 5) (unspec:BI [(match_dup 1) (match_dup 2)] 5))
+ (set (match_dup 5) (unspec:BI [(match_dup 1) (match_dup 2)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
@@ -3546,7 +3664,7 @@
(match_operand:TF 3 "fr_register_operand" "f")))
(set (match_operand:BI 1 "register_operand" "=c")
(unspec:BI [(match_operand:TF 2 "fr_register_operand" "f")
- (match_dup 3)] 5))
+ (match_dup 3)] UNSPEC_FR_RECIP_APPROX))
(use (match_operand:SI 4 "const_int_operand" ""))]
"INTEL_EXTENDED_IEEE_FORMAT"
"frcpa.s%4 %0, %1 = %2, %3"
@@ -3564,7 +3682,6 @@
(ashift:SI (match_operand:SI 1 "gr_register_operand" "")
(match_operand:SI 2 "gr_reg_or_5bit_operand" "")))]
""
- "
{
if (GET_CODE (operands[2]) != CONST_INT)
{
@@ -3574,7 +3691,7 @@
emit_insn (gen_zero_extendsidi2 (subshift, operands[2]));
operands[2] = subshift;
}
-}")
+})
(define_insn "*ashlsi3_internal"
[(set (match_operand:SI 0 "gr_register_operand" "=r,r,r")
@@ -3592,7 +3709,6 @@
(ashiftrt:SI (match_operand:SI 1 "gr_register_operand" "")
(match_operand:SI 2 "gr_reg_or_5bit_operand" "")))]
""
- "
{
rtx subtarget = gen_reg_rtx (DImode);
if (GET_CODE (operands[2]) == CONST_INT)
@@ -3607,14 +3723,13 @@
}
emit_move_insn (gen_lowpart (DImode, operands[0]), subtarget);
DONE;
-}")
+})
(define_expand "lshrsi3"
[(set (match_operand:SI 0 "gr_register_operand" "")
(lshiftrt:SI (match_operand:SI 1 "gr_register_operand" "")
(match_operand:SI 2 "gr_reg_or_5bit_operand" "")))]
""
- "
{
rtx subtarget = gen_reg_rtx (DImode);
if (GET_CODE (operands[2]) == CONST_INT)
@@ -3629,7 +3744,7 @@
}
emit_move_insn (gen_lowpart (DImode, operands[0]), subtarget);
DONE;
-}")
+})
;; Use mix4.r/shr to implement rotrsi3. We only get 32 bits of valid result
;; here, instead of 64 like the patterns above. Keep the pattern together
@@ -3640,7 +3755,6 @@
(rotatert:SI (match_operand:SI 1 "gr_register_operand" "")
(match_operand:SI 2 "gr_reg_or_5bit_operand" "")))]
""
- "
{
if (GET_MODE (operands[2]) != VOIDmode)
{
@@ -3648,7 +3762,7 @@
emit_insn (gen_zero_extendsidi2 (tmp, operands[2]));
operands[2] = tmp;
}
-}")
+})
(define_insn_and_split "*rotrsi3_internal"
[(set (match_operand:SI 0 "gr_register_operand" "=&r")
@@ -3669,7 +3783,6 @@
(rotate:SI (match_operand:SI 1 "gr_register_operand" "")
(match_operand:SI 2 "gr_reg_or_5bit_operand" "")))]
""
- "
{
if (! shift_32bit_count_operand (operands[2], SImode))
{
@@ -3678,7 +3791,7 @@
emit_insn (gen_rotrsi3 (operands[0], operands[1], tmp));
DONE;
}
-}")
+})
(define_insn_and_split "*rotlsi3_internal"
[(set (match_operand:SI 0 "gr_register_operand" "=r")
@@ -3692,8 +3805,10 @@
(ashift:DI (zero_extend:DI (match_dup 1)) (const_int 32))))
(set (match_dup 3)
(lshiftrt:DI (match_dup 3) (match_dup 2)))]
- "operands[3] = gen_rtx_REG (DImode, REGNO (operands[0]));
- operands[2] = GEN_INT (32 - INTVAL (operands[2]));")
+{
+ operands[3] = gen_rtx_REG (DImode, REGNO (operands[0]));
+ operands[2] = GEN_INT (32 - INTVAL (operands[2]));
+})
;; ::::::::::::::::::::
;; ::
@@ -3776,11 +3891,10 @@
(rotatert:DI (match_operand:DI 1 "gr_register_operand" "")
(match_operand:DI 2 "nonmemory_operand" "")))]
""
- "
{
if (! shift_count_operand (operands[2], DImode))
FAIL;
-}")
+})
(define_insn "*rotrdi3_internal"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
@@ -3795,11 +3909,10 @@
(rotate:DI (match_operand:DI 1 "gr_register_operand" "")
(match_operand:DI 2 "nonmemory_operand" "")))]
""
- "
{
if (! shift_count_operand (operands[2], DImode))
FAIL;
-}")
+})
(define_insn "*rotldi3_internal"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
@@ -3900,72 +4013,66 @@
(compare (match_operand:BI 0 "register_operand" "")
(match_operand:BI 1 "const_int_operand" "")))]
""
- "
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
-}")
+})
(define_expand "cmpsi"
[(set (cc0)
(compare (match_operand:SI 0 "gr_register_operand" "")
(match_operand:SI 1 "gr_reg_or_8bit_and_adjusted_operand" "")))]
""
- "
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
-}")
+})
(define_expand "cmpdi"
[(set (cc0)
(compare (match_operand:DI 0 "gr_register_operand" "")
(match_operand:DI 1 "gr_reg_or_8bit_and_adjusted_operand" "")))]
""
- "
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
-}")
+})
(define_expand "cmpsf"
[(set (cc0)
(compare (match_operand:SF 0 "fr_reg_or_fp01_operand" "")
(match_operand:SF 1 "fr_reg_or_fp01_operand" "")))]
""
- "
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
-}")
+})
(define_expand "cmpdf"
[(set (cc0)
(compare (match_operand:DF 0 "fr_reg_or_fp01_operand" "")
(match_operand:DF 1 "fr_reg_or_fp01_operand" "")))]
""
- "
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
-}")
+})
(define_expand "cmptf"
[(set (cc0)
(compare (match_operand:TF 0 "tfreg_or_fp01_operand" "")
(match_operand:TF 1 "tfreg_or_fp01_operand" "")))]
"INTEL_EXTENDED_IEEE_FORMAT"
- "
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
-}")
+})
(define_insn "*cmpsi_normal"
[(set (match_operand:BI 0 "register_operand" "=c")
@@ -4197,7 +4304,6 @@
(use (match_operand 3 "" "")) ; loop level
(use (match_operand 4 "" ""))] ; label
""
- "
{
/* Only use cloop on innermost loops. */
if (INTVAL (operands[3]) > 1)
@@ -4205,7 +4311,7 @@
emit_jump_insn (gen_doloop_end_internal (gen_rtx_REG (DImode, AR_LC_REGNUM),
operands[4]));
DONE;
-}")
+})
(define_insn "doloop_end_internal"
[(set (pc) (if_then_else (ne (match_operand:DI 0 "ar_lc_reg_operand" "")
@@ -4213,8 +4319,8 @@
(label_ref (match_operand 1 "" ""))
(pc)))
(set (match_dup 0) (if_then_else:DI (ne (match_dup 0) (const_int 0))
- (match_dup 0)
- (plus:DI (match_dup 0) (const_int -1))))]
+ (plus:DI (match_dup 0) (const_int -1))
+ (match_dup 0)))]
""
"br.cloop.sptk.few %l1"
[(set_attr "itanium_class" "br")
@@ -4338,12 +4444,12 @@
"c,c,c,c,c,c,c,c,c,c,c,c,c,c,c")
(const_int 0)])
(match_operand:DI 2 "move_operand"
- "rim, *f, *b,*d*e,rim,rim, rim,*f,*b,*d*e,rO,*f,rOQ,rO, rK")
+ "rnm, *f, *b,*d*e,rnm,rnm, rnm,*f,*b,*d*e,rO,*f,rOQ,rO, rK")
(match_operand:DI 3 "move_operand"
- "rim,rim,rim, rim, *f, *b,*d*e,*f,*b,*d*e,rO,*f,rOQ,rO, rK")))]
+ "rnm,rnm,rnm, rnm, *f, *b,*d*e,*f,*b,*d*e,rO,*f,rOQ,rO, rK")))]
"ia64_move_ok (operands[0], operands[2])
&& ia64_move_ok (operands[0], operands[3])"
- "* abort ();"
+ { abort (); }
[(set_attr "predicable" "no")])
(define_split
@@ -4356,14 +4462,17 @@
(match_operand 3 "move_operand" "")))]
"reload_completed"
[(const_int 0)]
- "
{
rtx tmp;
+ int emitted_something;
+
+ emitted_something = 0;
if (! rtx_equal_p (operands[0], operands[2]))
{
tmp = gen_rtx_SET (VOIDmode, operands[0], operands[2]);
tmp = gen_rtx_COND_EXEC (VOIDmode, operands[4], tmp);
emit_insn (tmp);
+ emitted_something = 1;
}
if (! rtx_equal_p (operands[0], operands[3]))
{
@@ -4373,9 +4482,12 @@
gen_rtx_SET (VOIDmode, operands[0],
operands[3]));
emit_insn (tmp);
+ emitted_something = 1;
}
+ if (! emitted_something)
+ emit_note (NULL, NOTE_INSN_DELETED);
DONE;
-}")
+})
;; Absolute value pattern.
@@ -4422,11 +4534,10 @@
(cond_exec
(match_dup 5)
(set (match_dup 0) (match_dup 3)))]
- "
{
operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? EQ : NE,
VOIDmode, operands[1], const0_rtx);
-}")
+})
;;
;; SImode if_then_else patterns.
@@ -4439,12 +4550,12 @@
[(match_operand:BI 1 "register_operand" "c,c,c,c,c,c,c,c,c")
(const_int 0)])
(match_operand:SI 2 "move_operand"
- "0,0,0,rim*f,rO,rO,rim*f,rO,rO")
+ "0,0,0,rnm*f,rO,rO,rnm*f,rO,rO")
(match_operand:SI 3 "move_operand"
- "rim*f,rO,rO,0,0,0,rim*f,rO,rO")))]
+ "rnm*f,rO,rO,0,0,0,rnm*f,rO,rO")))]
"ia64_move_ok (operands[0], operands[2])
&& ia64_move_ok (operands[0], operands[3])"
- "* abort ();"
+ { abort (); }
[(set_attr "predicable" "no")])
(define_insn "*abssi2_internal"
@@ -4490,11 +4601,10 @@
(cond_exec
(match_dup 5)
(set (match_dup 0) (match_dup 3)))]
- "
{
operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? EQ : NE,
VOIDmode, operands[1], const0_rtx);
-}")
+})
(define_insn_and_split "*cond_opsi2_internal"
[(set (match_operand:SI 0 "gr_register_operand" "=r")
@@ -4515,11 +4625,10 @@
(cond_exec
(match_dup 7)
(set (match_dup 0) (match_op_dup:SI 5 [(match_dup 3) (match_dup 4)])))]
- "
{
operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[6]) == NE ? EQ : NE,
VOIDmode, operands[1], const0_rtx);
-}"
+}
[(set_attr "itanium_class" "ialu")
(set_attr "predicable" "no")])
@@ -4543,11 +4652,10 @@
(cond_exec
(match_dup 7)
(set (match_dup 0) (match_op_dup:SI 5 [(match_dup 4) (match_dup 3)])))]
- "
{
operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[6]) == NE ? EQ : NE,
VOIDmode, operands[1], const0_rtx);
-}"
+}
[(set_attr "itanium_class" "ialu")
(set_attr "predicable" "no")])
@@ -4574,11 +4682,10 @@
(use (match_operand 2 "" ""))
(use (match_operand 3 "" ""))]
""
- "
{
- ia64_expand_call (NULL_RTX, operands[0], operands[2], 0);
+ ia64_expand_call (NULL_RTX, operands[0], operands[2], false);
DONE;
-}")
+})
(define_expand "sibcall"
[(use (match_operand:DI 0 "" ""))
@@ -4586,11 +4693,10 @@
(use (match_operand 2 "" ""))
(use (match_operand 3 "" ""))]
""
- "
{
- ia64_expand_call (NULL_RTX, operands[0], operands[2], 1);
+ ia64_expand_call (NULL_RTX, operands[0], operands[2], true);
DONE;
-}")
+})
;; Subroutine call instruction returning a value. Operand 0 is the hard
;; register in which the value is returned. There are three more operands,
@@ -4606,11 +4712,10 @@
(use (match_operand 3 "" ""))
(use (match_operand 4 "" ""))]
""
- "
{
- ia64_expand_call (operands[0], operands[1], operands[3], 0);
+ ia64_expand_call (operands[0], operands[1], operands[3], false);
DONE;
-}")
+})
(define_expand "sibcall_value"
[(use (match_operand 0 "" ""))
@@ -4619,11 +4724,10 @@
(use (match_operand 3 "" ""))
(use (match_operand 4 "" ""))]
""
- "
{
- ia64_expand_call (operands[0], operands[1], operands[3], 1);
+ ia64_expand_call (operands[0], operands[1], operands[3], true);
DONE;
-}")
+})
;; Call subroutine returning any type.
@@ -4633,7 +4737,6 @@
(match_operand 1 "" "")
(match_operand 2 "" "")])]
""
- "
{
int i;
@@ -4652,61 +4755,127 @@
emit_insn (gen_blockage ());
DONE;
-}")
+})
-(define_insn "call_nopic"
- [(call (mem:DI (match_operand:DI 0 "call_operand" "b,i"))
- (match_operand 1 "" ""))
- (clobber (match_operand:DI 2 "register_operand" "=b,b"))]
+(define_insn "call_nogp"
+ [(call (mem:DI (match_operand:DI 0 "call_operand" "?b,i"))
+ (const_int 0))
+ (clobber (match_operand:DI 1 "register_operand" "=b,b"))]
""
- "br.call%+.many %2 = %0"
+ "br.call%+.many %1 = %0"
[(set_attr "itanium_class" "br,scall")])
-(define_insn "call_value_nopic"
+(define_insn "call_value_nogp"
[(set (match_operand 0 "" "")
- (call (mem:DI (match_operand:DI 1 "call_operand" "b,i"))
- (match_operand 2 "" "")))
- (clobber (match_operand:DI 3 "register_operand" "=b,b"))]
+ (call (mem:DI (match_operand:DI 1 "call_operand" "?b,i"))
+ (const_int 0)))
+ (clobber (match_operand:DI 2 "register_operand" "=b,b"))]
""
- "br.call%+.many %3 = %1"
+ "br.call%+.many %2 = %1"
[(set_attr "itanium_class" "br,scall")])
-(define_insn "sibcall_nopic"
- [(call (mem:DI (match_operand:DI 0 "call_operand" "b,i"))
- (match_operand 1 "" ""))
- (use (match_operand:DI 2 "register_operand" "=b,b"))
- (use (match_operand:DI 3 "ar_pfs_reg_operand" ""))]
+(define_insn "sibcall_nogp"
+ [(call (mem:DI (match_operand:DI 0 "call_operand" "?b,i"))
+ (const_int 0))]
""
"br%+.many %0"
[(set_attr "itanium_class" "br,scall")])
-(define_insn "call_pic"
- [(call (mem:DI (match_operand:DI 0 "call_operand" "b,i"))
- (match_operand 1 "" ""))
- (use (unspec [(reg:DI 1)] 9))
- (clobber (match_operand:DI 2 "register_operand" "=b,b"))]
+(define_insn "call_gp"
+ [(call (mem (match_operand 0 "call_operand" "?r,i"))
+ (const_int 1))
+ (clobber (match_operand:DI 1 "register_operand" "=b,b"))
+ (clobber (match_scratch:DI 2 "=&r,X"))
+ (clobber (match_scratch:DI 3 "=b,X"))]
""
- "br.call%+.many %2 = %0"
+ "#"
[(set_attr "itanium_class" "br,scall")])
-(define_insn "call_value_pic"
+;; Irritatingly, we don't have access to INSN within the split body.
+;; See commentary in ia64_split_call as to why these aren't peep2.
+(define_split
+ [(call (mem (match_operand 0 "call_operand" ""))
+ (const_int 1))
+ (clobber (match_operand:DI 1 "register_operand" ""))
+ (clobber (match_scratch:DI 2 ""))
+ (clobber (match_scratch:DI 3 ""))]
+ "reload_completed && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+ [(const_int 0)]
+{
+ ia64_split_call (NULL_RTX, operands[0], operands[1], operands[2],
+ operands[3], true, false);
+ DONE;
+})
+
+(define_split
+ [(call (mem (match_operand 0 "call_operand" ""))
+ (const_int 1))
+ (clobber (match_operand:DI 1 "register_operand" ""))
+ (clobber (match_scratch:DI 2 ""))
+ (clobber (match_scratch:DI 3 ""))]
+ "reload_completed"
+ [(const_int 0)]
+{
+ ia64_split_call (NULL_RTX, operands[0], operands[1], operands[2],
+ operands[3], false, false);
+ DONE;
+})
+
+(define_insn "call_value_gp"
[(set (match_operand 0 "" "")
- (call (mem:DI (match_operand:DI 1 "call_operand" "b,i"))
- (match_operand 2 "" "")))
- (use (unspec [(reg:DI 1)] 9))
- (clobber (match_operand:DI 3 "register_operand" "=b,b"))]
+ (call (mem:DI (match_operand:DI 1 "call_operand" "?r,i"))
+ (const_int 1)))
+ (clobber (match_operand:DI 2 "register_operand" "=b,b"))
+ (clobber (match_scratch:DI 3 "=&r,X"))
+ (clobber (match_scratch:DI 4 "=b,X"))]
""
- "br.call%+.many %3 = %1"
+ "#"
[(set_attr "itanium_class" "br,scall")])
-(define_insn "sibcall_pic"
- [(call (mem:DI (match_operand:DI 0 "call_operand" "bi"))
- (match_operand 1 "" ""))
- (use (unspec [(reg:DI 1)] 9))
- (use (match_operand:DI 2 "register_operand" "=b"))
- (use (match_operand:DI 3 "ar_pfs_reg_operand" ""))]
+(define_split
+ [(set (match_operand 0 "" "")
+ (call (mem:DI (match_operand:DI 1 "call_operand" ""))
+ (const_int 1)))
+ (clobber (match_operand:DI 2 "register_operand" ""))
+ (clobber (match_scratch:DI 3 ""))
+ (clobber (match_scratch:DI 4 ""))]
+ "reload_completed && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+ [(const_int 0)]
+{
+ ia64_split_call (operands[0], operands[1], operands[2], operands[3],
+ operands[4], true, false);
+ DONE;
+})
+
+(define_split
+ [(set (match_operand 0 "" "")
+ (call (mem:DI (match_operand:DI 1 "call_operand" ""))
+ (const_int 1)))
+ (clobber (match_operand:DI 2 "register_operand" ""))
+ (clobber (match_scratch:DI 3 ""))
+ (clobber (match_scratch:DI 4 ""))]
+ "reload_completed"
+ [(const_int 0)]
+{
+ ia64_split_call (operands[0], operands[1], operands[2], operands[3],
+ operands[4], false, false);
+ DONE;
+})
+
+(define_insn_and_split "sibcall_gp"
+ [(call (mem:DI (match_operand:DI 0 "call_operand" "?r,i"))
+ (const_int 1))
+ (clobber (match_scratch:DI 1 "=&r,X"))
+ (clobber (match_scratch:DI 2 "=b,X"))]
""
- "br%+.many %0"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ ia64_split_call (NULL_RTX, operands[0], NULL_RTX, operands[1],
+ operands[2], true, true);
+ DONE;
+}
[(set_attr "itanium_class" "br")])
(define_insn "return_internal"
@@ -4817,29 +4986,26 @@
(define_expand "prologue"
[(const_int 1)]
""
- "
{
ia64_expand_prologue ();
DONE;
-}")
+})
(define_expand "epilogue"
[(return)]
""
- "
{
ia64_expand_epilogue (0);
DONE;
-}")
+})
(define_expand "sibcall_epilogue"
[(return)]
""
- "
{
ia64_expand_epilogue (1);
DONE;
-}")
+})
;; This prevents the scheduler from moving the SP decrement past FP-relative
;; stack accesses. This is the same as adddi3 plus the extra set.
@@ -4852,9 +5018,9 @@
(match_dup 3))]
""
"@
- add %0 = %1, %2
- adds %0 = %2, %1
- addl %0 = %2, %1"
+ add %0 = %1, %2
+ adds %0 = %2, %1
+ addl %0 = %2, %1"
[(set_attr "itanium_class" "ialu")])
;; This prevents the scheduler from moving the SP restore past FP-relative
@@ -4868,11 +5034,21 @@
"mov %0 = %1"
[(set_attr "itanium_class" "ialu")])
+;; As USE insns aren't meaningful after reload, this is used instead
+;; to prevent deleting instructions setting registers for EH handling
+(define_insn "prologue_use"
+ [(unspec:DI [(match_operand:DI 0 "register_operand" "")]
+ UNSPEC_PROLOGUE_USE)]
+ ""
+ ""
+ [(set_attr "itanium_class" "ignore")
+ (set_attr "predicable" "no")])
+
;; Allocate a new register frame.
(define_insn "alloc"
[(set (match_operand:DI 0 "register_operand" "=r")
- (unspec_volatile:DI [(const_int 0)] 0))
+ (unspec_volatile:DI [(const_int 0)] UNSPECV_ALLOC))
(use (match_operand:DI 1 "const_int_operand" "i"))
(use (match_operand:DI 2 "const_int_operand" "i"))
(use (match_operand:DI 3 "const_int_operand" "i"))
@@ -4886,7 +5062,8 @@
(define_expand "gr_spill"
[(parallel [(set (match_operand:DI 0 "memory_operand" "=m")
(unspec:DI [(match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "const_int_operand" "")] 1))
+ (match_operand:DI 2 "const_int_operand" "")]
+ UNSPEC_GR_SPILL))
(clobber (match_dup 3))])]
""
"operands[3] = gen_rtx_REG (DImode, AR_UNAT_REGNUM);")
@@ -4894,20 +5071,23 @@
(define_insn "gr_spill_internal"
[(set (match_operand:DI 0 "memory_operand" "=m")
(unspec:DI [(match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "const_int_operand" "")] 1))
+ (match_operand:DI 2 "const_int_operand" "")]
+ UNSPEC_GR_SPILL))
(clobber (match_operand:DI 3 "register_operand" ""))]
""
- "*
{
- return \".mem.offset %2, 0\;%,st8.spill %0 = %1%P0\";
-}"
+ /* Note that we use a C output pattern here to avoid the predicate
+ being automatically added before the .mem.offset directive. */
+ return ".mem.offset %2, 0\;%,st8.spill %0 = %1%P0";
+}
[(set_attr "itanium_class" "st")])
;; Reads ar.unat
(define_expand "gr_restore"
[(parallel [(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(match_operand:DI 1 "memory_operand" "m")
- (match_operand:DI 2 "const_int_operand" "")] 2))
+ (match_operand:DI 2 "const_int_operand" "")]
+ UNSPEC_GR_RESTORE))
(use (match_dup 3))])]
""
"operands[3] = gen_rtx_REG (DImode, AR_UNAT_REGNUM);")
@@ -4915,25 +5095,25 @@
(define_insn "gr_restore_internal"
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(match_operand:DI 1 "memory_operand" "m")
- (match_operand:DI 2 "const_int_operand" "")] 2))
+ (match_operand:DI 2 "const_int_operand" "")]
+ UNSPEC_GR_RESTORE))
(use (match_operand:DI 3 "register_operand" ""))]
""
- "*
-{
- return \".mem.offset %2, 0\;%,ld8.fill %0 = %1%P1\";
-}"
+ { return ".mem.offset %2, 0\;%,ld8.fill %0 = %1%P1"; }
[(set_attr "itanium_class" "ld")])
(define_insn "fr_spill"
[(set (match_operand:TF 0 "memory_operand" "=m")
- (unspec:TF [(match_operand:TF 1 "register_operand" "f")] 3))]
+ (unspec:TF [(match_operand:TF 1 "register_operand" "f")]
+ UNSPEC_FR_SPILL))]
""
"stf.spill %0 = %1%P0"
[(set_attr "itanium_class" "stf")])
(define_insn "fr_restore"
[(set (match_operand:TF 0 "register_operand" "=f")
- (unspec:TF [(match_operand:TF 1 "memory_operand" "m")] 4))]
+ (unspec:TF [(match_operand:TF 1 "memory_operand" "m")]
+ UNSPEC_FR_RESTORE))]
""
"ldf.fill %0 = %1%P1"
[(set_attr "itanium_class" "fld")])
@@ -4944,15 +5124,33 @@
(define_insn "bsp_value"
[(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(const_int 0)] 20))]
+ (unspec:DI [(const_int 0)] UNSPEC_BSP_VALUE))]
""
- ";;\;mov %0 = ar.bsp"
+ "*
+{
+ return \";;\;%,mov %0 = ar.bsp\";
+}"
[(set_attr "itanium_class" "frar_i")])
(define_insn "set_bsp"
- [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")] 5)]
- ""
- "flushrs\;mov r19=ar.rsc\;;;\;and r19=0x1c,r19\;;;\;mov ar.rsc=r19\;;;\;mov ar.bspstore=%0\;;;\;or r19=0x3,r19\;;;\;loadrs\;invala\;;;\;mov ar.rsc=r19"
+ [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
+ UNSPECV_SET_BSP)]
+ ""
+ "flushrs
+ mov r19=ar.rsc
+ ;;
+ and r19=0x1c,r19
+ ;;
+ mov ar.rsc=r19
+ ;;
+ mov ar.bspstore=%0
+ ;;
+ or r19=0x3,r19
+ ;;
+ loadrs
+ invala
+ ;;
+ mov ar.rsc=r19"
[(set_attr "itanium_class" "unknown")
(set_attr "predicable" "no")])
@@ -4961,10 +5159,11 @@
;; fixed later. This avoids an RSE DV.
(define_insn "flushrs"
- [(unspec [(const_int 0)] 21)]
+ [(unspec [(const_int 0)] UNSPEC_FLUSHRS)]
""
";;\;flushrs\;;;"
- [(set_attr "itanium_class" "rse_m")])
+ [(set_attr "itanium_class" "rse_m")
+ (set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::
@@ -5012,34 +5211,25 @@
""
[(set_attr "itanium_class" "nop_x")])
-(define_insn "cycle_display"
- [(unspec [(match_operand 0 "const_int_operand" "")] 23)]
- ""
- "// cycle %0"
- [(set_attr "itanium_class" "ignore")
- (set_attr "predicable" "no")])
-
(define_insn "bundle_selector"
- [(unspec [(match_operand 0 "const_int_operand" "")] 22)]
+ [(unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BUNDLE_SELECTOR)]
""
- "*
-{
- return get_bundle_name (INTVAL (operands[0]));
-}"
+ { return get_bundle_name (INTVAL (operands[0])); }
[(set_attr "itanium_class" "ignore")
(set_attr "predicable" "no")])
;; Pseudo instruction that prevents the scheduler from moving code above this
;; point.
(define_insn "blockage"
- [(unspec_volatile [(const_int 0)] 1)]
+ [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
""
""
[(set_attr "itanium_class" "ignore")
(set_attr "predicable" "no")])
(define_insn "insn_group_barrier"
- [(unspec_volatile [(match_operand 0 "const_int_operand" "")] 2)]
+ [(unspec_volatile [(match_operand 0 "const_int_operand" "")]
+ UNSPECV_INSN_GROUP_BARRIER)]
""
";;"
[(set_attr "itanium_class" "stop_bit")
@@ -5077,7 +5267,7 @@
(set_attr "predicable" "no")])
(define_insn "break_f"
- [(unspec_volatile [(const_int 0)] 3)]
+ [(unspec_volatile [(const_int 0)] UNSPECV_BREAK)]
""
"break.f 0"
[(set_attr "itanium_class" "nop_f")])
@@ -5119,14 +5309,13 @@
[(use (match_operand:OI 0 "memory_operand" ""))
(use (match_operand:DI 1 "register_operand" ""))]
""
- "
{
emit_library_call (gen_rtx_SYMBOL_REF (Pmode,
\"__ia64_save_stack_nonlocal\"),
0, VOIDmode, 2, XEXP (operands[0], 0), Pmode,
operands[1], Pmode);
DONE;
-}")
+})
(define_expand "nonlocal_goto"
[(use (match_operand 0 "general_operand" ""))
@@ -5134,7 +5323,6 @@
(use (match_operand 2 "general_operand" ""))
(use (match_operand 3 "general_operand" ""))]
""
- "
{
emit_library_call (gen_rtx_SYMBOL_REF (Pmode, \"__ia64_nonlocal_goto\"),
LCT_NORETURN, VOIDmode, 3,
@@ -5143,34 +5331,24 @@
operands[3], Pmode);
emit_barrier ();
DONE;
-}")
-
-;; The rest of the setjmp processing happens with the nonlocal_goto expander.
-;; ??? This is not tested.
-(define_expand "builtin_setjmp_setup"
- [(use (match_operand:DI 0 "" ""))]
- ""
- "
-{
- emit_move_insn (ia64_gp_save_reg (0), gen_rtx_REG (DImode, GR_REG (1)));
- DONE;
-}")
+})
-(define_expand "builtin_setjmp_receiver"
- [(use (match_operand:DI 0 "" ""))]
+(define_insn_and_split "builtin_setjmp_receiver"
+ [(unspec_volatile [(match_operand:DI 0 "" "")] UNSPECV_SETJMP_RECEIVER)]
""
- "
+ "#"
+ "reload_completed"
+ [(const_int 0)]
{
- emit_move_insn (gen_rtx_REG (DImode, GR_REG (1)), ia64_gp_save_reg (0));
+ ia64_reload_gp ();
DONE;
-}")
+})
(define_expand "eh_epilogue"
[(use (match_operand:DI 0 "register_operand" "r"))
(use (match_operand:DI 1 "register_operand" "r"))
(use (match_operand:DI 2 "register_operand" "r"))]
""
- "
{
rtx bsp = gen_rtx_REG (Pmode, 10);
rtx sp = gen_rtx_REG (Pmode, 9);
@@ -5190,7 +5368,7 @@
cfun->machine->ia64_eh_epilogue_sp = sp;
cfun->machine->ia64_eh_epilogue_bsp = bsp;
-}")
+})
;; Builtin apply support.
@@ -5198,31 +5376,29 @@
[(use (match_operand:DI 0 "register_operand" ""))
(use (match_operand:OI 1 "memory_operand" ""))]
""
- "
{
emit_library_call (gen_rtx_SYMBOL_REF (Pmode,
- \"__ia64_restore_stack_nonlocal\"),
+ "__ia64_restore_stack_nonlocal"),
0, VOIDmode, 1,
copy_to_reg (XEXP (operands[1], 0)), Pmode);
DONE;
-}")
+})
;;; Intrinsics support.
(define_expand "mf"
[(set (mem:BLK (match_dup 0))
- (unspec:BLK [(mem:BLK (match_dup 0))] 12))]
+ (unspec:BLK [(mem:BLK (match_dup 0))] UNSPEC_MF))]
""
- "
{
operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode));
MEM_VOLATILE_P (operands[0]) = 1;
-}")
+})
(define_insn "*mf_internal"
[(set (match_operand:BLK 0 "" "")
- (unspec:BLK [(match_operand:BLK 1 "" "")] 12))]
+ (unspec:BLK [(match_operand:BLK 1 "" "")] UNSPEC_MF))]
""
"mf"
[(set_attr "itanium_class" "syst_m")])
@@ -5232,7 +5408,8 @@
(match_dup 1))
(set (match_operand:SI 1 "not_postinc_memory_operand" "+S")
(unspec:SI [(match_dup 1)
- (match_operand:SI 2 "fetchadd_operand" "n")] 19))]
+ (match_operand:SI 2 "fetchadd_operand" "n")]
+ UNSPEC_FETCHADD_ACQ))]
""
"fetchadd4.acq %0 = %1, %2"
[(set_attr "itanium_class" "sem")])
@@ -5242,7 +5419,8 @@
(match_dup 1))
(set (match_operand:DI 1 "not_postinc_memory_operand" "+S")
(unspec:DI [(match_dup 1)
- (match_operand:DI 2 "fetchadd_operand" "n")] 19))]
+ (match_operand:DI 2 "fetchadd_operand" "n")]
+ UNSPEC_FETCHADD_ACQ))]
""
"fetchadd8.acq %0 = %1, %2"
[(set_attr "itanium_class" "sem")])
@@ -5253,7 +5431,8 @@
(set (match_operand:SI 1 "not_postinc_memory_operand" "+S")
(unspec:SI [(match_dup 1)
(match_operand:SI 2 "gr_register_operand" "r")
- (match_operand:SI 3 "ar_ccv_reg_operand" "")] 13))]
+ (match_operand 3 "ar_ccv_reg_operand" "")]
+ UNSPEC_CMPXCHG_ACQ))]
""
"cmpxchg4.acq %0 = %1, %2, %3"
[(set_attr "itanium_class" "sem")])
@@ -5264,7 +5443,8 @@
(set (match_operand:DI 1 "not_postinc_memory_operand" "+S")
(unspec:DI [(match_dup 1)
(match_operand:DI 2 "gr_register_operand" "r")
- (match_operand:DI 3 "ar_ccv_reg_operand" "")] 13))]
+ (match_operand:DI 3 "ar_ccv_reg_operand" "")]
+ UNSPEC_CMPXCHG_ACQ))]
""
"cmpxchg8.acq %0 = %1, %2, %3"
[(set_attr "itanium_class" "sem")])
@@ -5298,48 +5478,59 @@
(define_insn "pred_rel_mutex"
[(set (match_operand:BI 0 "register_operand" "+c")
- (unspec:BI [(match_dup 0)] 7))]
+ (unspec:BI [(match_dup 0)] UNSPEC_PRED_REL_MUTEX))]
""
".pred.rel.mutex %0, %I0"
[(set_attr "itanium_class" "ignore")
(set_attr "predicable" "no")])
(define_insn "safe_across_calls_all"
- [(unspec_volatile [(const_int 0)] 8)]
+ [(unspec_volatile [(const_int 0)] UNSPECV_PSAC_ALL)]
""
".pred.safe_across_calls p1-p63"
[(set_attr "itanium_class" "ignore")
(set_attr "predicable" "no")])
(define_insn "safe_across_calls_normal"
- [(unspec_volatile [(const_int 0)] 9)]
+ [(unspec_volatile [(const_int 0)] UNSPECV_PSAC_NORMAL)]
""
- "*
{
emit_safe_across_calls (asm_out_file);
- return \"\";
-}"
+ return "";
+}
[(set_attr "itanium_class" "ignore")
(set_attr "predicable" "no")])
-;;
-;;
;; UNSPEC instruction definition to "swizzle" 32 bit pointer into 64 bit
;; pointer. This is used by the HP-UX 32 bit mode.
(define_insn "ptr_extend"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
- (unspec:DI [(match_operand:SI 1 "gr_register_operand" "r")] 24))]
+ (unspec:DI [(match_operand:SI 1 "gr_register_operand" "r")]
+ UNSPEC_ADDP4))]
""
"addp4 %0 = 0,%1"
[(set_attr "itanium_class" "ialu")])
;;
-;; As USE insns aren't meaningful after reload, this is used instead
-;; to prevent deleting instructions setting registers for EH handling
-(define_insn "prologue_use"
- [(unspec:DI [(match_operand:DI 0 "register_operand" "")] 25)]
- ""
- "// %0 needed for EH"
- [(set_attr "itanium_class" "ignore")
- (set_attr "predicable" "no")])
+;; Optimizations for ptr_extend
+
+(define_insn "*ptr_extend_plus_1"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (unspec:DI
+ [(plus:SI (match_operand:SI 1 "basereg_operand" "r")
+ (match_operand:SI 2 "gr_reg_or_14bit_operand" "rI"))]
+ UNSPEC_ADDP4))]
+ "addp4_optimize_ok (operands[1], operands[2])"
+ "addp4 %0 = %2, %1"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*ptr_extend_plus_2"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (unspec:DI
+ [(plus:SI (match_operand:SI 1 "gr_register_operand" "r")
+ (match_operand:SI 2 "basereg_operand" "r"))]
+ UNSPEC_ADDP4))]
+ "addp4_optimize_ok (operands[1], operands[2])"
+ "addp4 %0 = %1, %2"
+ [(set_attr "itanium_class" "ialu")])
diff --git a/contrib/gcc/config/ia64/linux.h b/contrib/gcc/config/ia64/linux.h
index 07882cd..e1d60f7 100644
--- a/contrib/gcc/config/ia64/linux.h
+++ b/contrib/gcc/config/ia64/linux.h
@@ -9,10 +9,15 @@
#undef CC1_SPEC
#define CC1_SPEC "%{profile:-p} %{G*}"
-/* ??? Maybe this should be in sysv4.h? */
-#define CPP_PREDEFINES "\
- -D__gnu_linux__ -D__linux -D__linux__ -D_LONGLONG \
- -Dlinux -Dunix -Asystem=linux"
+/* Target OS builtins. */
+#define TARGET_OS_CPP_BUILTINS() \
+do { \
+ builtin_assert("system=linux"); \
+ builtin_define_std("linux"); \
+ builtin_define_std("unix"); \
+ builtin_define("__gnu_linux__"); \
+ builtin_define("_LONGLONG"); \
+} while (0)
/* Need to override linux.h STARTFILE_SPEC, since it has crtbeginT.o in. */
#undef STARTFILE_SPEC
diff --git a/contrib/gcc/config/ia64/quadlib.c b/contrib/gcc/config/ia64/quadlib.c
index fac3b28..e55c97d 100644
--- a/contrib/gcc/config/ia64/quadlib.c
+++ b/contrib/gcc/config/ia64/quadlib.c
@@ -1,5 +1,5 @@
/* Subroutines for long double support.
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -27,8 +27,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. */
-int _U_Qfcmp (long double a, long double b, int);
-long _U_Qfcnvfxt_quad_to_sgl (long double);
+extern int _U_Qfcmp (long double a, long double b, int);
+
+int _U_Qfeq (long double, long double);
+int _U_Qfne (long double, long double);
+int _U_Qfgt (long double, long double);
+int _U_Qfge (long double, long double);
+int _U_Qflt (long double, long double);
+int _U_Qfle (long double, long double);
+int _U_Qfcomp (long double, long double);
int
_U_Qfeq (long double a, long double b)
@@ -74,9 +81,3 @@ _U_Qfcomp (long double a, long double b)
return (_U_Qfcmp (a, b, 22) != 0 ? 1 : -1);
}
-
-long double
-_U_Qfneg (long double a)
-{
- return (0.0L - a);
-}
diff --git a/contrib/gcc/config/ia64/sysv4.h b/contrib/gcc/config/ia64/sysv4.h
index 840ebdd..3254fa5 100644
--- a/contrib/gcc/config/ia64/sysv4.h
+++ b/contrib/gcc/config/ia64/sysv4.h
@@ -33,8 +33,8 @@
the Intel simulator. So we must explicitly put variables in .bss
instead. This matters only if we care about the Intel assembler. */
-/* This is asm_output_aligned_bss from varasm.c without the ASM_GLOBALIZE_LABEL
- call at the beginning. */
+/* This is asm_output_aligned_bss from varasm.c without the
+ (*targetm.asm_out.globalize_label) call at the beginning. */
/* This is for final.c, because it is used by ASM_DECLARE_OBJECT_NAME. */
extern int size_directive_output;
@@ -42,8 +42,7 @@ extern int size_directive_output;
#undef ASM_OUTPUT_ALIGNED_LOCAL
#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
do { \
- if ((DECL) \
- && XSTR (XEXP (DECL_RTL (DECL), 0), 0)[0] == SDATA_NAME_FLAG_CHAR) \
+ if ((DECL) && sdata_symbolic_operand (XEXP (DECL_RTL (DECL), 0), Pmode)) \
sbss_section (); \
else \
bss_section (); \
@@ -62,8 +61,8 @@ do { \
#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
do { \
const char *name_ = NAME; \
- if (*name_ == SDATA_NAME_FLAG_CHAR) \
- name_++; \
+ if (*name_ == ENCODE_SECTION_INFO_CHAR) \
+ name_ += 2; \
if (*name_ == '*') \
name_++; \
else \
@@ -140,158 +139,15 @@ do { \
emit_safe_across_calls (STREAM); \
} while (0)
-/* A C statement or statements to switch to the appropriate
- section for output of DECL. DECL is either a `VAR_DECL' node
- or a constant of some sort. RELOC indicates whether forming
- the initial value of DECL requires link-time relocations.
-
- Set SECNUM to:
- 0 .text
- 1 .rodata
- 2 .data
- 3 .sdata
- 4 .bss
- 5 .sbss
-*/
-#define DO_SELECT_SECTION(SECNUM, DECL, RELOC) \
- do \
- { \
- if (TREE_CODE (DECL) == FUNCTION_DECL) \
- SECNUM = 0; \
- else if (TREE_CODE (DECL) == STRING_CST) \
- { \
- if (! flag_writable_strings) \
- SECNUM = 0x101; \
- else \
- SECNUM = 2; \
- } \
- else if (TREE_CODE (DECL) == VAR_DECL) \
- { \
- if (XSTR (XEXP (DECL_RTL (DECL), 0), 0)[0] \
- == SDATA_NAME_FLAG_CHAR) \
- SECNUM = 3; \
- /* ??? We need the extra RELOC check, because the default \
- is to only check RELOC if flag_pic is set, and we don't \
- set flag_pic (yet?). */ \
- else if (!DECL_READONLY_SECTION (DECL, RELOC) || (RELOC)) \
- SECNUM = 2; \
- else if (flag_merge_constants < 2) \
- /* C and C++ don't allow different variables to share \
- the same location. -fmerge-all-constants allows \
- even that (at the expense of not conforming). */ \
- SECNUM = 1; \
- else if (TREE_CODE (DECL_INITIAL (DECL)) == STRING_CST) \
- SECNUM = 0x201; \
- else \
- SECNUM = 0x301; \
- } \
- /* This could be a CONSTRUCTOR containing ADDR_EXPR of a VAR_DECL, \
- in which case we can't put it in a shared library rodata. */ \
- else if (flag_pic && (RELOC)) \
- SECNUM = 3; \
- else \
- SECNUM = 2; \
- } \
- while (0)
-
-/* We override svr4.h so that we can support the sdata section. */
-
-#undef SELECT_SECTION
-#define SELECT_SECTION(DECL,RELOC,ALIGN) \
- do \
- { \
- typedef void (*sec_fn) PARAMS ((void)); \
- static sec_fn const sec_functions[6] = \
- { \
- text_section, \
- const_section, \
- data_section, \
- sdata_section, \
- bss_section, \
- sbss_section \
- }; \
- \
- int sec; \
- \
- DO_SELECT_SECTION (sec, DECL, RELOC); \
- \
- switch (sec) \
- { \
- case 0x101: \
- mergeable_string_section (DECL, ALIGN, 0); \
- break; \
- case 0x201: \
- mergeable_string_section (DECL_INITIAL (DECL), \
- ALIGN, 0); \
- break; \
- case 0x301: \
- mergeable_constant_section (DECL_MODE (DECL), \
- ALIGN, 0); \
- break; \
- default: \
- (*sec_functions[sec]) (); \
- break; \
- } \
- } \
- while (0)
-
-#undef UNIQUE_SECTION
-#define UNIQUE_SECTION(DECL, RELOC) \
- do \
- { \
- static const char * const prefixes[6][2] = \
- { \
- { ".text.", ".gnu.linkonce.t." }, \
- { ".rodata.", ".gnu.linkonce.r." }, \
- { ".data.", ".gnu.linkonce.d." }, \
- { ".sdata.", ".gnu.linkonce.s." }, \
- { ".bss.", ".gnu.linkonce.b." }, \
- { ".sbss.", ".gnu.linkonce.sb." } \
- }; \
- \
- int nlen, plen, sec; \
- const char *name, *prefix; \
- char *string; \
- \
- DO_SELECT_SECTION (sec, DECL, RELOC); \
- \
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
- STRIP_NAME_ENCODING (name, name); \
- nlen = strlen (name); \
- \
- prefix = prefixes[sec & 0xff][DECL_ONE_ONLY(DECL)]; \
- plen = strlen (prefix); \
- \
- string = alloca (nlen + plen + 1); \
- \
- memcpy (string, prefix, plen); \
- memcpy (string + plen, name, nlen + 1); \
- \
- DECL_SECTION_NAME (DECL) = build_string (nlen + plen, string); \
- } \
- while (0)
-
-/* Similarly for constant pool data. */
-
-extern unsigned int ia64_section_threshold;
-#undef SELECT_RTX_SECTION
-#define SELECT_RTX_SECTION(MODE, RTX, ALIGN) \
-{ \
- if (GET_MODE_SIZE (MODE) > 0 \
- && GET_MODE_SIZE (MODE) <= ia64_section_threshold) \
- sdata_section (); \
- else if (flag_pic && symbolic_operand ((RTX), (MODE))) \
- data_section (); \
- else \
- mergeable_constant_section ((MODE), (ALIGN), 0); \
-}
+/* Override default elf definition. */
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION ia64_select_rtx_section
#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_const, in_sdata, in_sbss
+#define EXTRA_SECTIONS in_sdata, in_sbss
#undef EXTRA_SECTION_FUNCTIONS
#define EXTRA_SECTION_FUNCTIONS \
- CONST_SECTION_FUNCTION \
SDATA_SECTION_FUNCTION \
SBSS_SECTION_FUNCTION
diff --git a/contrib/gcc/config/ia64/t-aix b/contrib/gcc/config/ia64/t-aix
index 2e738f9..7b6df46 100644
--- a/contrib/gcc/config/ia64/t-aix
+++ b/contrib/gcc/config/ia64/t-aix
@@ -6,11 +6,7 @@ CRTSTUFF_T_CFLAGS_S = -fPIC
TARGET_LIBGCC2_CFLAGS = -fPIC -D__64BIT__ -D_LONG_LONG -D_IA64 -D__int128=__size128_t
LIB2ADDEH += $(srcdir)/config/ia64/unwind-aix.c
-# Add crt[in].o to the list defined in t-ia64. These files provide
-# endpoints for crtbegin/end.
-
-EXTRA_PARTS=crti.o crtn.o crtbegin.o crtend.o crtbeginS.o crtendS.o
-
+# Assemble startup files.
crti.o: $(srcdir)/config/ia64/crti.asm $(GCC_PASSES)
$(GCC_FOR_TARGET) -c -o crti.o -x assembler $(srcdir)/config/ia64/crti.asm
crtn.o: $(srcdir)/config/ia64/crtn.asm $(GCC_PASSES)
diff --git a/contrib/gcc/config/ia64/t-hpux b/contrib/gcc/config/ia64/t-hpux
index 9f8296b..7b42fe5 100644
--- a/contrib/gcc/config/ia64/t-hpux
+++ b/contrib/gcc/config/ia64/t-hpux
@@ -13,3 +13,36 @@ LIB2FUNCS_EXTRA=quadlib.c
quadlib.c: $(srcdir)/config/ia64/quadlib.c
cat $(srcdir)/config/ia64/quadlib.c > quadlib.c
+
+# We get an undefined main when building a cross compiler because our
+# linkspec has "-u main" and we want that for linking but it makes
+# LIBGCC1_TEST fail because it uses -nostdlib -nostartup.
+
+LIBGCC1_TEST =
+
+# Don't run fix-headers. HP-UX headers are standards conformant
+# and don't need to be fixed up in this way.
+# If we remove this (and run fix-headers) we should define FIXPROTO_DEFINES
+# and also fix the definition of putenv in sys-protos.h (const char not char).
+
+STMP_FIXPROTO =
+
+# We do not want to include the EH stuff that linux uses, we want to use
+# the HP-UX libunwind library.
+
+LIB2ADDEH =
+
+SHLIB_EXT = .so
+SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
+ -Wl,+h,@shlib_base_name@.so.0 \
+ -o @shlib_base_name@.so @multilib_flags@ @shlib_objs@ -lc && \
+ rm -f @shlib_base_name@.so.0 && \
+ $(LN_S) @shlib_base_name@.so @shlib_base_name@.so.0
+# $(slibdir) double quoted to protect it from expansion while building
+# libgcc.mk. We want this delayed until actual install time.
+SHLIB_INSTALL = $(INSTALL_DATA) @shlib_base_name@.so $$(DESTDIR)$$(slibdir)/@shlib_base_name@.so.0; \
+ rm -f $$(DESTDIR)$$(slibdir)/@shlib_base_name@.so; \
+ $(LN_S) @shlib_base_name@.so.0 $$(DESTDIR)$$(slibdir)/@shlib_base_name@.so; \
+ chmod +x $$(DESTDIR)$$(slibdir)/@shlib_base_name@.so
+
+SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
diff --git a/contrib/gcc/config/ia64/t-ia64 b/contrib/gcc/config/ia64/t-ia64
index 41c0235..7c63b31 100644
--- a/contrib/gcc/config/ia64/t-ia64
+++ b/contrib/gcc/config/ia64/t-ia64
@@ -19,24 +19,30 @@ LIB1ASMFUNCS = __divtf3 __divdf3 __divsf3 \
SHLIB_MAPFILES += $(srcdir)/config/ia64/libgcc-ia64.ver
-# For svr4 we build crtbegin.o and crtend.o which serve to add begin and
-# end labels to the .ctors and .dtors section when we link using gcc.
-
-EXTRA_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o
-
# Effectively disable the crtbegin/end rules using crtstuff.c
T = disable
# Assemble startup files.
crtbegin.o: $(srcdir)/config/ia64/crtbegin.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -o crtbegin.o -x assembler-with-cpp $(srcdir)/config/ia64/crtbegin.asm
+ $(GCC_FOR_TARGET) -I. -c -o crtbegin.o -x assembler-with-cpp \
+ $(srcdir)/config/ia64/crtbegin.asm
crtend.o: $(srcdir)/config/ia64/crtend.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -o crtend.o -x assembler-with-cpp $(srcdir)/config/ia64/crtend.asm
+ $(GCC_FOR_TARGET) -I. -c -o crtend.o -x assembler-with-cpp \
+ $(srcdir)/config/ia64/crtend.asm
crtbeginS.o: $(srcdir)/config/ia64/crtbegin.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) -DSHARED -c -o crtbeginS.o -x assembler-with-cpp $(srcdir)/config/ia64/crtbegin.asm
+ $(GCC_FOR_TARGET) -I. -DSHARED -c -o crtbeginS.o \
+ -x assembler-with-cpp \
+ $(srcdir)/config/ia64/crtbegin.asm
crtendS.o: $(srcdir)/config/ia64/crtend.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) -DSHARED -c -o crtendS.o -x assembler-with-cpp $(srcdir)/config/ia64/crtend.asm
+ $(GCC_FOR_TARGET) -I. -DSHARED -c -o crtendS.o -x assembler-with-cpp \
+ $(srcdir)/config/ia64/crtend.asm
crtfastmath.o: $(srcdir)/config/ia64/crtfastmath.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -c -o crtfastmath.o $(srcdir)/config/ia64/crtfastmath.c
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -c -o crtfastmath.o \
+ $(srcdir)/config/ia64/crtfastmath.c
+
+LIB2ADDEH = $(srcdir)/config/ia64/unwind-ia64.c $(srcdir)/unwind-sjlj.c \
+ $(srcdir)/unwind-c.c
-LIB2ADDEH = $(srcdir)/config/ia64/unwind-ia64.c $(srcdir)/unwind-sjlj.c
+ia64-c.o: $(srcdir)/config/ia64/ia64-c.c $(CONFIG_H) $(SYSTEM_H) \
+ $(TREE_H) $(CPPLIB_H) $(C_COMMON_H) c-pragma.h toplev.h
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/contrib/gcc/config/ia64/unwind-ia64.c b/contrib/gcc/config/ia64/unwind-ia64.c
index ca91539..12e46ae 100644
--- a/contrib/gcc/config/ia64/unwind-ia64.c
+++ b/contrib/gcc/config/ia64/unwind-ia64.c
@@ -143,7 +143,7 @@ typedef struct unw_state_record
unsigned int any_spills : 1; /* got any register spills? */
unsigned int in_body : 1; /* are we inside a body? */
unsigned int no_reg_stack_frame : 1; /* Don't adjust bsp for i&l regs */
- unsigned char *imask; /* imask of of spill_mask record or NULL */
+ unsigned char *imask; /* imask of spill_mask record or NULL */
unsigned long pr_val; /* predicate values */
unsigned long pr_mask; /* predicate mask */
long spill_offset; /* psp-relative offset for spill base */
@@ -1401,7 +1401,7 @@ unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg)
typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *);
-static unw_decoder unw_decode_table[2][8] =
+static const unw_decoder unw_decode_table[2][8] =
{
/* prologue table: */
{
@@ -1642,6 +1642,29 @@ _Unwind_GetRegionStart (struct _Unwind_Context *context)
return context->region_start;
}
+void *
+_Unwind_FindEnclosingFunction (void *pc)
+{
+ struct unw_table_entry *ent;
+ unsigned long segment_base, gp;
+
+ ent = _Unwind_FindTableEntry (pc, &segment_base, &gp);
+ if (ent == NULL)
+ return NULL;
+ else
+ return (void *)(segment_base + ent->start_offset);
+}
+
+/* Get the value of the CFA as saved in CONTEXT. In GCC/Dwarf2 parlance,
+ the CFA is the value of the stack pointer on entry; In IA-64 unwind
+ parlance, this is the PSP. */
+
+_Unwind_Word
+_Unwind_GetCFA (struct _Unwind_Context *context)
+{
+ return (_Unwind_Ptr) context->psp;
+}
+
static _Unwind_Reason_Code
uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
OpenPOWER on IntegriCloud