summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/config/ia64
diff options
context:
space:
mode:
authorkan <kan@FreeBSD.org>2007-05-19 01:19:51 +0000
committerkan <kan@FreeBSD.org>2007-05-19 01:19:51 +0000
commit1f9ea4d0a40cca64d60cf4dab152349da7b9dddf (patch)
tree0cb530c9c38af219e6dda2994c078b6b2b9ad853 /contrib/gcc/config/ia64
parent4895159b2b4f648051c1f139faa7b6dc50c2bfcb (diff)
downloadFreeBSD-src-1f9ea4d0a40cca64d60cf4dab152349da7b9dddf.zip
FreeBSD-src-1f9ea4d0a40cca64d60cf4dab152349da7b9dddf.tar.gz
GCC 4.2.0 release.
Diffstat (limited to 'contrib/gcc/config/ia64')
-rw-r--r--contrib/gcc/config/ia64/crtbegin.asm35
-rw-r--r--contrib/gcc/config/ia64/crtend.asm35
-rw-r--r--contrib/gcc/config/ia64/crtfastmath.c40
-rw-r--r--contrib/gcc/config/ia64/crti.asm4
-rw-r--r--contrib/gcc/config/ia64/crtn.asm4
-rw-r--r--contrib/gcc/config/ia64/fde-glibc.c4
-rw-r--r--contrib/gcc/config/ia64/freebsd.h4
-rw-r--r--contrib/gcc/config/ia64/hpux.h80
-rw-r--r--contrib/gcc/config/ia64/ia64-c.c16
-rw-r--r--contrib/gcc/config/ia64/ia64-modes.def43
-rw-r--r--contrib/gcc/config/ia64/ia64-protos.h84
-rw-r--r--contrib/gcc/config/ia64/ia64.c4934
-rw-r--r--contrib/gcc/config/ia64/ia64.h594
-rw-r--r--contrib/gcc/config/ia64/ia64.md1524
-rw-r--r--contrib/gcc/config/ia64/ia64.opt147
-rw-r--r--contrib/gcc/config/ia64/ia64intrin.h132
-rw-r--r--contrib/gcc/config/ia64/ilp32.opt7
-rw-r--r--contrib/gcc/config/ia64/itanium1.md144
-rw-r--r--contrib/gcc/config/ia64/itanium2.md179
-rw-r--r--contrib/gcc/config/ia64/lib1funcs.asm61
-rw-r--r--contrib/gcc/config/ia64/linux-unwind.h193
-rw-r--r--contrib/gcc/config/ia64/linux.h164
-rw-r--r--contrib/gcc/config/ia64/predicates.md591
-rw-r--r--contrib/gcc/config/ia64/quadlib.c4
-rw-r--r--contrib/gcc/config/ia64/sync.md178
-rw-r--r--contrib/gcc/config/ia64/sysv4.h40
-rw-r--r--contrib/gcc/config/ia64/t-hpux27
-rw-r--r--contrib/gcc/config/ia64/t-ia647
-rw-r--r--contrib/gcc/config/ia64/unwind-ia64.c42
-rw-r--r--contrib/gcc/config/ia64/unwind-ia64.h4
-rw-r--r--contrib/gcc/config/ia64/vect.md1304
31 files changed, 7040 insertions, 3585 deletions
diff --git a/contrib/gcc/config/ia64/crtbegin.asm b/contrib/gcc/config/ia64/crtbegin.asm
index 494def7..e040916 100644
--- a/contrib/gcc/config/ia64/crtbegin.asm
+++ b/contrib/gcc/config/ia64/crtbegin.asm
@@ -1,20 +1,29 @@
-/* Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2003, 2005 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
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ This file is part of GCC.
- The GNU C Library 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
- Library General Public License for more details.
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
#include "auto-host.h"
diff --git a/contrib/gcc/config/ia64/crtend.asm b/contrib/gcc/config/ia64/crtend.asm
index 8984d88..66eaa01 100644
--- a/contrib/gcc/config/ia64/crtend.asm
+++ b/contrib/gcc/config/ia64/crtend.asm
@@ -1,20 +1,29 @@
-/* Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2003, 2005 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
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ This file is part of GCC.
- The GNU C Library 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
- Library General Public License for more details.
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
#include "auto-host.h"
diff --git a/contrib/gcc/config/ia64/crtfastmath.c b/contrib/gcc/config/ia64/crtfastmath.c
index aa0d120..e5b32cb 100644
--- a/contrib/gcc/config/ia64/crtfastmath.c
+++ b/contrib/gcc/config/ia64/crtfastmath.c
@@ -1,29 +1,29 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2005 Free Software Foundation, Inc.
Contributed by David Mosberger <davidm@hpl.hp.com>.
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ This file is part of GCC.
- The GNU C Library is distributed in the hope that it will be useful,
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
+ 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 Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
-/* In addition to the permissions in the GNU General Public License, the
- Free Software Foundation gives you unlimited permission to link the
- compiled version of this file into combinations with other programs,
- and to distribute those combinations without any restriction coming
- from the use of this file. (The General Public License restrictions
- do apply in other respects; for example, they cover modification of
- the file, and distribution when not linked into a combine
- executable.) */
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
/* We could call fesetenv() here but that would create a confusing
dependency on libm (since that is where fesetenv() gets defined.
diff --git a/contrib/gcc/config/ia64/crti.asm b/contrib/gcc/config/ia64/crti.asm
index 4b48e3d..a2d1e12 100644
--- a/contrib/gcc/config/ia64/crti.asm
+++ b/contrib/gcc/config/ia64/crti.asm
@@ -21,8 +21,8 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to
-# the Free Software Foundation, 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
+# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
#
# As a special exception, if you link this library with files
# compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/ia64/crtn.asm b/contrib/gcc/config/ia64/crtn.asm
index 48a9a03..52ec47c 100644
--- a/contrib/gcc/config/ia64/crtn.asm
+++ b/contrib/gcc/config/ia64/crtn.asm
@@ -21,8 +21,8 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to
-# the Free Software Foundation, 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
+# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
#
# As a special exception, if you link this library with files
# compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/ia64/fde-glibc.c b/contrib/gcc/config/ia64/fde-glibc.c
index 15e1927..7506c17 100644
--- a/contrib/gcc/config/ia64/fde-glibc.c
+++ b/contrib/gcc/config/ia64/fde-glibc.c
@@ -15,8 +15,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* As a special exception, if you link this library with other files,
some of which are compiled with GCC, to produce an executable,
diff --git a/contrib/gcc/config/ia64/freebsd.h b/contrib/gcc/config/ia64/freebsd.h
index d5977ff..2373910 100644
--- a/contrib/gcc/config/ia64/freebsd.h
+++ b/contrib/gcc/config/ia64/freebsd.h
@@ -16,7 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#undef SUBTARGET_EXTRA_SPECS
#define SUBTARGET_EXTRA_SPECS \
@@ -24,7 +25,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define LINK_SPEC " \
%{p:%nconsider using `-pg' instead of `-p' with gprof(1)} \
- %{Wl,*:%*} \
%{assert*} %{R*} %{rpath*} %{defsym*} \
%{shared:-Bshareable %{h*} %{soname*}} \
%{symbolic:-Bsymbolic} \
diff --git a/contrib/gcc/config/ia64/hpux.h b/contrib/gcc/config/ia64/hpux.h
index 09fb53f..996b7d2 100644
--- a/contrib/gcc/config/ia64/hpux.h
+++ b/contrib/gcc/config/ia64/hpux.h
@@ -1,5 +1,6 @@
/* Definitions of target machine GNU compiler. IA-64 version.
- Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
+ Free Software Foundation, Inc.
Contributed by Steve Ellcey <sje@cup.hp.com> and
Reva Cuthbertson <reva@cup.hp.com>
@@ -17,8 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* This macro is a C statement to print on `stderr' a string describing the
particular machine description choice. */
@@ -29,6 +30,12 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_HPUX
#define TARGET_HPUX 1
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "unsigned int"
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
/* Target OS builtins. */
#define TARGET_OS_CPP_BUILTINS() \
do { \
@@ -46,6 +53,7 @@ do { \
builtin_define("_HPUX_SOURCE"); \
builtin_define("__STDC_EXT__"); \
builtin_define("__STDCPP__"); \
+ builtin_define("_INCLUDE__STDC_A1_SOURCE"); \
} \
if (TARGET_ILP32) \
builtin_define("_ILP32"); \
@@ -64,11 +72,13 @@ do { \
#undef ENDFILE_SPEC
#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "%{!shared:%{static:crt0%O%s}}"
+#define STARTFILE_SPEC "%{!shared:%{static:crt0%O%s} \
+ %{mlp64:/usr/lib/hpux64/unix98%O%s} \
+ %{!mlp64:/usr/lib/hpux32/unix98%O%s}}"
#undef LINK_SPEC
#define LINK_SPEC \
- "+Accept TypeMismatch \
+ "-z +Accept TypeMismatch \
%{shared:-b} \
%{!shared: \
-u main \
@@ -84,11 +94,6 @@ do { \
%{mlp64:-L/usr/lib/hpux64/libp} -lgprof} \
%{!symbolic:-lc}}"
-#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES \
- { "ilp32", MASK_ILP32, "Generate ILP32 code" }, \
- { "lp64", -MASK_ILP32, "Generate LP64 code" },
-
#define MULTILIB_DEFAULTS { "milp32" }
/* A C expression whose value is zero if pointers that need to be extended
@@ -101,16 +106,11 @@ do { \
#define JMP_BUF_SIZE (8 * 76)
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_DWARF2_ASM | MASK_BIG_ENDIAN | MASK_ILP32)
-
-/* This needs to be set to force structure arguments with a single
- integer 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, instead of being returned at the
- top of the register as specified for big-endian IA64. */
+#define TARGET_DEFAULT \
+ (MASK_DWARF2_ASM | MASK_BIG_ENDIAN | MASK_ILP32)
-#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) \
- (!FLOAT_MODE_P (MODE) || (MODE) == TFmode)
+/* ??? Might not be needed anymore. */
+#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) ((MODE) == TFmode)
/* ASM_OUTPUT_EXTERNAL_LIBCALL defaults to just a globalize_label call,
but that doesn't put out the @function type information which causes
@@ -178,19 +178,45 @@ do { \
/* 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
+#undef TARGET_ASM_RELOC_RW_MASK
+#define TARGET_ASM_RELOC_RW_MASK ia64_hpux_reloc_rw_mask
/* ia64 HPUX has the float and long double forms of math functions. */
#undef TARGET_C99_FUNCTIONS
#define TARGET_C99_FUNCTIONS 1
+#undef TARGET_INIT_LIBFUNCS
#define TARGET_INIT_LIBFUNCS ia64_hpux_init_libfuncs
#define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) ((MODE) == TFmode)
+
+/* Put all *xf routines in libgcc, regardless of long double size. */
+#undef LIBGCC2_HAS_XF_MODE
+#define LIBGCC2_HAS_XF_MODE 1
+#define XF_SIZE 64
+
+/* Put all *tf routines in libgcc, regardless of long double size. */
+#undef LIBGCC2_HAS_TF_MODE
+#define LIBGCC2_HAS_TF_MODE 1
+#define TF_SIZE 113
+
+/* HP-UX headers are C++-compatible. */
+#define NO_IMPLICIT_EXTERN_C
+
+/* HP-UX uses PROFILE_HOOK instead of FUNCTION_PROFILER but we need a
+ FUNCTION_PROFILER defined because its use is not ifdefed. When using
+ PROFILE_HOOK, the profile call comes after the prologue. */
+
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(FILE, LABELNO) do { } while (0)
+
+#undef PROFILE_HOOK
+#define PROFILE_HOOK(LABEL) ia64_profile_hook (LABEL)
+
+#undef PROFILE_BEFORE_PROLOGUE
+
+#undef NO_PROFILE_COUNTERS
+#define NO_PROFILE_COUNTERS 0
+
+#undef HANDLE_PRAGMA_PACK_PUSH_POP
+#define HANDLE_PRAGMA_PACK_PUSH_POP
diff --git a/contrib/gcc/config/ia64/ia64-c.c b/contrib/gcc/config/ia64/ia64-c.c
index 422fc86..9bb2a80 100644
--- a/contrib/gcc/config/ia64/ia64-c.c
+++ b/contrib/gcc/config/ia64/ia64-c.c
@@ -1,5 +1,5 @@
/* Definitions of C specific functions for GNU compiler.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Steve Ellcey <sje@cup.hp.com>
This file is part of GCC.
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
@@ -40,16 +40,16 @@ ia64_hpux_handle_builtin_pragma (cpp_reader *pfile ATTRIBUTE_UNUSED)
enum cpp_ttype type;
tree x;
- type = c_lex (&x);
+ type = pragma_lex (&x);
while (type == CPP_NAME)
{
ia64_hpux_add_pragma_builtin (x);
- type = c_lex (&x);
+ type = pragma_lex (&x);
if (type == CPP_COMMA)
- type = c_lex (&x);
+ type = pragma_lex (&x);
}
if (type != CPP_EOF)
- warning ("malformed #pragma builtin");
+ warning (OPT_Wpragmas, "malformed #pragma builtin");
}
/* List of standard math functions which do not set matherr by default
@@ -60,7 +60,7 @@ ia64_hpux_handle_builtin_pragma (cpp_reader *pfile ATTRIBUTE_UNUSED)
typedef struct c89_mathlib_names
{
const char *realname; /* User visible function name. */
- const char *c89name; /* libm special name needed to set errno. */
+ const char *c89name; /* libm special name needed to set errno. */
} c89_mathlib_names;
static const c89_mathlib_names c89_mathlib_name_list [] =
diff --git a/contrib/gcc/config/ia64/ia64-modes.def b/contrib/gcc/config/ia64/ia64-modes.def
index 17688bd..c7e9927 100644
--- a/contrib/gcc/config/ia64/ia64-modes.def
+++ b/contrib/gcc/config/ia64/ia64-modes.def
@@ -1,5 +1,5 @@
/* Definitions of target machine GNU compiler. IA-64 version.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by James E. Wilson <wilson@cygnus.com> and
David Mosberger <davidm@hpl.hp.com>.
@@ -17,43 +17,52 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* IA64 requires both XF and TF modes.
XFmode is __float80 is IEEE extended; TFmode is __float128
- is IEEE quad.
+ is IEEE quad. Both these modes occupy 16 bytes, but XFmode
+ only has 80 significant bits. RFmode is __fpreg is IA64 internal
+ register format with 82 significant bits but otherwise handled like
+ XFmode. */
- IEEE extended is 128 bits wide, except in ILP32 mode, but we
- have to say it's 12 bytes so that the bitsize and wider_mode
- tables are correctly set up. We correct its size below. */
-
-FLOAT_MODE (XF, 12, ieee_extended_intel_128_format);
+FRACTIONAL_FLOAT_MODE (XF, 80, 16, ieee_extended_intel_128_format);
+FRACTIONAL_FLOAT_MODE (RF, 82, 16, ieee_extended_intel_128_format);
FLOAT_MODE (TF, 16, ieee_quad_format);
/* The above produces:
mode ILP32 size/align LP64 size/align
- XF 12/4 12/4
+ XF 16/16 16/16
TF 16/16 16/16
psABI expectations:
mode ILP32 size/align LP64 size/align
- XF - 16/16
+ XF 12/4 -
TF - -
HPUX expectations:
mode ILP32 size/align LP64 size/align
- XF 16/16 16/16
+ XF - -
TF 16/8 -
We fix this up here. */
+ADJUST_FLOAT_FORMAT (XF, (TARGET_ILP32 && !TARGET_HPUX)
+ ? &ieee_extended_intel_96_format
+ : &ieee_extended_intel_128_format);
ADJUST_BYTESIZE (XF, (TARGET_ILP32 && !TARGET_HPUX) ? 12 : 16);
ADJUST_ALIGNMENT (XF, (TARGET_ILP32 && !TARGET_HPUX) ? 4 : 16);
+ADJUST_FLOAT_FORMAT (RF, (TARGET_ILP32 && !TARGET_HPUX)
+ ? &ieee_extended_intel_96_format
+ : &ieee_extended_intel_128_format);
+ADJUST_BYTESIZE (RF, (TARGET_ILP32 && !TARGET_HPUX) ? 12 : 16);
+ADJUST_ALIGNMENT (RF, (TARGET_ILP32 && !TARGET_HPUX) ? 4 : 16);
+
ADJUST_ALIGNMENT (TF, (TARGET_ILP32 && TARGET_HPUX) ? 8 : 16);
/* 256-bit integer mode is needed for STACK_SAVEAREA_MODE. */
@@ -66,3 +75,13 @@ INT_MODE (OI, 32);
so that flow doesn't do something stupid. */
CC_MODE (CCI);
+
+/* Vector modes. */
+VECTOR_MODES (INT, 4); /* V4QI V2HI */
+VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */
+VECTOR_MODE (INT, QI, 16);
+VECTOR_MODE (INT, HI, 8);
+VECTOR_MODE (INT, SI, 4);
+VECTOR_MODE (FLOAT, SF, 2);
+VECTOR_MODE (FLOAT, SF, 4);
+
diff --git a/contrib/gcc/config/ia64/ia64-protos.h b/contrib/gcc/config/ia64/ia64-protos.h
index 7825616..c4bf61d 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, 2002, 2003, 2004
+ Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Variables defined in ia64.c. */
@@ -33,74 +33,44 @@ extern int bundling_p;
extern int ia64_st_address_bypass_p (rtx, rtx);
extern int ia64_ld_address_bypass_p (rtx, rtx);
extern int ia64_produce_address_p (rtx);
-extern int call_operand (rtx, enum machine_mode);
-extern int sdata_symbolic_operand (rtx, enum machine_mode);
-extern int got_symbolic_operand (rtx, enum machine_mode);
-extern int symbolic_operand (rtx, enum machine_mode);
-extern int tls_symbolic_operand (rtx, enum machine_mode);
-extern int function_operand (rtx, enum machine_mode);
-extern int setjmp_operand (rtx, enum machine_mode);
-extern int move_operand (rtx, enum machine_mode);
-extern int gr_register_operand (rtx, enum machine_mode);
-extern int fr_register_operand (rtx, enum machine_mode);
-extern int grfr_register_operand (rtx, enum machine_mode);
-extern int gr_nonimmediate_operand (rtx, enum machine_mode);
-extern int fr_nonimmediate_operand (rtx, enum machine_mode);
-extern int grfr_nonimmediate_operand (rtx, enum machine_mode);
-extern int gr_reg_or_0_operand (rtx, enum machine_mode);
-extern int gr_reg_or_5bit_operand (rtx, enum machine_mode);
-extern int gr_reg_or_6bit_operand (rtx, enum machine_mode);
-extern int gr_reg_or_8bit_operand (rtx, enum machine_mode);
-extern int grfr_reg_or_8bit_operand (rtx, enum machine_mode);
-extern int gr_reg_or_8bit_adjusted_operand (rtx, enum machine_mode);
-extern int gr_reg_or_8bit_and_adjusted_operand (rtx, enum machine_mode);
-extern int gr_reg_or_14bit_operand (rtx, enum machine_mode);
-extern int gr_reg_or_22bit_operand (rtx, enum machine_mode);
-extern int shift_count_operand (rtx, enum machine_mode);
-extern int shift_32bit_count_operand (rtx, enum machine_mode);
-extern int shladd_operand (rtx, enum machine_mode);
-extern int fetchadd_operand (rtx, enum machine_mode);
-extern int fr_reg_or_fp01_operand (rtx, enum machine_mode);
-extern int normal_comparison_operator (rtx, enum machine_mode);
-extern int adjusted_comparison_operator (rtx, enum machine_mode);
-extern int signed_inequality_operator (rtx, enum machine_mode);
-extern int destination_operand (rtx, enum machine_mode);
-extern int not_postinc_memory_operand (rtx, enum machine_mode);
-extern int predicate_operator (rtx, enum machine_mode);
-extern int ar_lc_reg_operand (rtx, enum machine_mode);
-extern int ar_ccv_reg_operand (rtx, enum machine_mode);
-extern int ar_pfs_reg_operand (rtx, enum machine_mode);
-extern int general_xfmode_operand (rtx, enum machine_mode);
-extern int destination_xfmode_operand (rtx, enum machine_mode);
-extern int xfreg_or_fp01_operand (rtx, enum machine_mode);
-extern int basereg_operand (rtx, enum machine_mode);
+
+extern bool ia64_const_ok_for_letter_p (HOST_WIDE_INT, char);
+extern bool ia64_const_double_ok_for_letter_p (rtx, char);
+extern bool ia64_extra_constraint (rtx, char);
+extern bool ia64_legitimate_constant_p (rtx);
extern rtx ia64_expand_move (rtx, rtx);
extern int ia64_move_ok (rtx, rtx);
+extern int ia64_load_pair_ok (rtx, rtx);
extern int addp4_optimize_ok (rtx, rtx);
extern void ia64_emit_cond_move (rtx, rtx, rtx);
extern int ia64_depz_field_mask (rtx, rtx);
extern void ia64_split_tmode_move (rtx[]);
-extern rtx spill_xfmode_operand (rtx, int);
+extern bool ia64_expand_movxf_movrf (enum machine_mode, rtx[]);
extern rtx ia64_expand_compare (enum rtx_code, enum machine_mode);
+extern void ia64_expand_vecint_cmov (rtx[]);
+extern bool ia64_expand_vecint_minmax (enum rtx_code, enum machine_mode, rtx[]);
+extern void ia64_expand_widen_sum (rtx[], bool);
+extern void ia64_expand_dot_prod_v8qi (rtx[], bool);
extern void ia64_expand_call (rtx, rtx, rtx, int);
extern void ia64_split_call (rtx, rtx, rtx, rtx, rtx, int, int);
extern void ia64_reload_gp (void);
+extern void ia64_expand_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx);
extern HOST_WIDE_INT ia64_initial_elimination_offset (int, int);
extern void ia64_expand_prologue (void);
extern void ia64_expand_epilogue (int);
extern int ia64_direct_return (void);
-extern void ia64_expand_load_address (rtx, rtx);
+extern bool ia64_expand_load_address (rtx, rtx);
extern int ia64_hard_regno_rename_ok (int, int);
extern void ia64_initialize_trampoline (rtx, rtx, rtx);
extern void ia64_print_operand_address (FILE *, rtx);
extern void ia64_print_operand (FILE *, rtx, int);
+extern enum reg_class ia64_preferred_reload_class (rtx, enum reg_class);
extern enum reg_class ia64_secondary_reload_class (enum reg_class,
enum machine_mode, rtx);
-extern void ia64_output_dwarf_dtprel (FILE*, int, rtx);
extern void process_for_unwind_directive (FILE *, rtx);
extern const char *get_bundle_name (int);
#endif /* RTX_CODE */
@@ -114,15 +84,9 @@ extern rtx ia64_va_arg (tree, tree);
extern rtx ia64_function_value (tree, tree);
#endif /* RTX_CODE */
-extern void ia64_setup_incoming_varargs (CUMULATIVE_ARGS, int, tree,
- int *, int);
-extern int ia64_function_arg_partial_nregs (CUMULATIVE_ARGS *,
- enum machine_mode, tree, int);
extern void ia64_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
tree, int);
-extern int ia64_function_arg_pass_by_reference (CUMULATIVE_ARGS *,
- enum machine_mode, tree, int);
-extern int ia64_return_in_memory (tree);
+extern int ia64_function_arg_boundary (enum machine_mode, tree);
extern void ia64_asm_output_external (FILE *, tree, const char *);
#endif /* TREE_CODE */
@@ -138,17 +102,13 @@ extern int ia64_dbx_register_number (int);
extern rtx ia64_return_addr_rtx (HOST_WIDE_INT, rtx);
extern void ia64_split_return_addr_rtx (rtx);
-#ifdef SDATA_SECTION_ASM_OP
-extern void sdata_section (void);
-#endif
-
-#ifdef SBSS_SECTION_ASM_OP
-extern void sbss_section (void);
-#endif
-
#ifdef ARGS_SIZE_RTX
/* expr.h defines ARGS_SIZE_RTX and `enum direction'. */
extern enum direction ia64_hpux_function_arg_padding (enum machine_mode, tree);
#endif /* ARGS_SIZE_RTX */
extern void ia64_hpux_handle_builtin_pragma (struct cpp_reader *);
+extern void ia64_output_function_profiler (FILE *, int);
+extern void ia64_profile_hook (int);
+
+extern void ia64_optimization_options (int, int);
diff --git a/contrib/gcc/config/ia64/ia64.c b/contrib/gcc/config/ia64/ia64.c
index c215b19..6ddff32 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, 2003, 2004
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
Contributed by James E. Wilson <wilson@cygnus.com> and
David Mosberger <davidm@hpl.hp.com>.
@@ -18,8 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
@@ -51,6 +51,10 @@ Boston, MA 02111-1307, USA. */
#include "hashtab.h"
#include "langhooks.h"
#include "cfglayout.h"
+#include "tree-gimple.h"
+#include "intl.h"
+#include "debug.h"
+#include "params.h"
/* This is used for communication between ASM_OUTPUT_LABEL and
ASM_OUTPUT_LABELREF. */
@@ -97,26 +101,17 @@ static const char * const ia64_local_reg_names[80] =
static const char * const ia64_output_reg_names[8] =
{ "out0", "out1", "out2", "out3", "out4", "out5", "out6", "out7" };
-/* 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;
-
/* Which cpu are we scheduling for. */
-enum processor_type ia64_tune;
-
-/* String used with the -tune= option. */
-const char *ia64_tune_string;
+enum processor_type ia64_tune = PROCESSOR_ITANIUM2;
/* Determines whether we run our final scheduling pass or not. We always
avoid the normal second scheduling pass. */
static int ia64_flag_schedule_insns2;
+/* Determines whether we run variable tracking in machine dependent
+ reorganization. */
+static int ia64_flag_var_tracking;
+
/* Variables which are this size or smaller are put in the sdata/sbss
sections. */
@@ -159,16 +154,24 @@ struct ia64_frame_info
/* Current frame information calculated by ia64_compute_frame_size. */
static struct ia64_frame_info current_frame_info;
-static int ia64_use_dfa_pipeline_interface (void);
static int ia64_first_cycle_multipass_dfa_lookahead (void);
static void ia64_dependencies_evaluation_hook (rtx, rtx);
static void ia64_init_dfa_pre_cycle_insn (void);
static rtx ia64_dfa_pre_cycle_insn (void);
static int ia64_first_cycle_multipass_dfa_lookahead_guard (rtx);
+static bool ia64_first_cycle_multipass_dfa_lookahead_guard_spec (rtx);
static int ia64_dfa_new_cycle (FILE *, int, rtx, int, int, int *);
+static void ia64_h_i_d_extended (void);
+static int ia64_mode_to_int (enum machine_mode);
+static void ia64_set_sched_flags (spec_info_t);
+static int ia64_speculate_insn (rtx, ds_t, rtx *);
+static rtx ia64_gen_spec_insn (rtx, ds_t, int, bool, bool);
+static bool ia64_needs_block_p (rtx);
+static rtx ia64_gen_check (rtx, rtx, bool);
+static int ia64_spec_check_p (rtx);
+static int ia64_spec_check_src_p (rtx);
static rtx gen_tls_get_addr (void);
static rtx gen_thread_pointer (void);
-static rtx ia64_expand_tls_address (enum tls_model, rtx, rtx);
static int find_gr_spill (int);
static int next_scratch_gr_reg (void);
static void mark_reg_gr_used_mask (rtx, void *);
@@ -182,10 +185,16 @@ static rtx gen_movdi_x (rtx, rtx, rtx);
static rtx gen_fr_spill_x (rtx, rtx, rtx);
static rtx gen_fr_restore_x (rtx, rtx, rtx);
-static enum machine_mode hfa_element_mode (tree, int);
+static enum machine_mode hfa_element_mode (tree, bool);
+static void ia64_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
+ tree, int *, int);
+static int ia64_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
+ tree, bool);
static bool ia64_function_ok_for_sibcall (tree, tree);
+static bool ia64_return_in_memory (tree, tree);
static bool ia64_rtx_costs (rtx, int, int, int *);
static void fix_range (const char *);
+static bool ia64_handle_option (size_t, const char *, int);
static struct machine_function * ia64_init_machine_status (void);
static void emit_insn_group_barriers (FILE *);
static void emit_all_insn_group_barriers (FILE *);
@@ -193,23 +202,19 @@ static void final_emit_insn_group_barriers (FILE *);
static void emit_predicate_relation_info (void);
static void ia64_reorg (void);
static bool ia64_in_small_data_p (tree);
-static void process_epilogue (void);
-static int process_set (FILE *, rtx);
-
-static rtx ia64_expand_fetch_and_op (optab, enum machine_mode, tree, rtx);
-static rtx ia64_expand_op_and_fetch (optab, enum machine_mode, tree, rtx);
-static rtx ia64_expand_compare_and_swap (enum machine_mode, enum machine_mode,
- int, tree, rtx);
-static rtx ia64_expand_lock_test_and_set (enum machine_mode, tree, rtx);
-static rtx ia64_expand_lock_release (enum machine_mode, tree, rtx);
+static void process_epilogue (FILE *, rtx, bool, bool);
+static int process_set (FILE *, rtx, rtx, bool, bool);
+
static bool ia64_assemble_integer (rtx, unsigned int, int);
static void ia64_output_function_prologue (FILE *, HOST_WIDE_INT);
static void ia64_output_function_epilogue (FILE *, HOST_WIDE_INT);
static void ia64_output_function_end_prologue (FILE *);
static int ia64_issue_rate (void);
-static int ia64_adjust_cost (rtx, rtx, rtx, int);
+static int ia64_adjust_cost_2 (rtx, int, rtx, int);
static void ia64_sched_init (FILE *, int, int);
+static void ia64_sched_init_global (FILE *, int, int);
+static void ia64_sched_finish_global (FILE *, int);
static void ia64_sched_finish (FILE *, int);
static int ia64_dfa_sched_reorder (FILE *, int, rtx *, int *, int, int);
static int ia64_sched_reorder (FILE *, int, rtx *, int *, int);
@@ -238,31 +243,37 @@ static void ia64_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
HOST_WIDE_INT, tree);
static void ia64_file_start (void);
-static void ia64_select_rtx_section (enum machine_mode, rtx,
- unsigned HOST_WIDE_INT);
-static void ia64_rwreloc_select_section (tree, int, unsigned HOST_WIDE_INT)
- ATTRIBUTE_UNUSED;
-static void ia64_rwreloc_unique_section (tree, int)
+static int ia64_hpux_reloc_rw_mask (void) ATTRIBUTE_UNUSED;
+static int ia64_reloc_rw_mask (void) ATTRIBUTE_UNUSED;
+static section *ia64_select_rtx_section (enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT);
+static void ia64_output_dwarf_dtprel (FILE *, int, rtx)
ATTRIBUTE_UNUSED;
-static void ia64_rwreloc_select_rtx_section (enum machine_mode, rtx,
- unsigned HOST_WIDE_INT)
- ATTRIBUTE_UNUSED;
-static unsigned int ia64_rwreloc_section_type_flags (tree, const char *, int)
- ATTRIBUTE_UNUSED;
-
+static unsigned int ia64_section_type_flags (tree, const char *, int);
static void ia64_hpux_add_extern_decl (tree decl)
ATTRIBUTE_UNUSED;
static void ia64_hpux_file_end (void)
ATTRIBUTE_UNUSED;
+static void ia64_init_libfuncs (void)
+ ATTRIBUTE_UNUSED;
static void ia64_hpux_init_libfuncs (void)
ATTRIBUTE_UNUSED;
+static void ia64_sysv4_init_libfuncs (void)
+ ATTRIBUTE_UNUSED;
static void ia64_vms_init_libfuncs (void)
ATTRIBUTE_UNUSED;
static tree ia64_handle_model_attribute (tree *, tree, tree, int, bool *);
static void ia64_encode_section_info (tree, rtx, int);
static rtx ia64_struct_value_rtx (tree, int);
-
+static tree ia64_gimplify_va_arg (tree, tree, tree *, tree *);
+static bool ia64_scalar_mode_supported_p (enum machine_mode mode);
+static bool ia64_vector_mode_supported_p (enum machine_mode mode);
+static bool ia64_cannot_force_const_mem (rtx);
+static const char *ia64_mangle_fundamental_type (tree);
+static const char *ia64_invalid_conversion (tree, tree);
+static const char *ia64_invalid_unary_op (int, tree);
+static const char *ia64_invalid_binary_op (int, tree, tree);
/* Table of valid machine attributes. */
static const struct attribute_spec ia64_attribute_table[] =
@@ -310,8 +321,8 @@ static const struct attribute_spec ia64_attribute_table[] =
#undef TARGET_IN_SMALL_DATA_P
#define TARGET_IN_SMALL_DATA_P ia64_in_small_data_p
-#undef TARGET_SCHED_ADJUST_COST
-#define TARGET_SCHED_ADJUST_COST ia64_adjust_cost
+#undef TARGET_SCHED_ADJUST_COST_2
+#define TARGET_SCHED_ADJUST_COST_2 ia64_adjust_cost_2
#undef TARGET_SCHED_ISSUE_RATE
#define TARGET_SCHED_ISSUE_RATE ia64_issue_rate
#undef TARGET_SCHED_VARIABLE_ISSUE
@@ -320,6 +331,10 @@ static const struct attribute_spec ia64_attribute_table[] =
#define TARGET_SCHED_INIT ia64_sched_init
#undef TARGET_SCHED_FINISH
#define TARGET_SCHED_FINISH ia64_sched_finish
+#undef TARGET_SCHED_INIT_GLOBAL
+#define TARGET_SCHED_INIT_GLOBAL ia64_sched_init_global
+#undef TARGET_SCHED_FINISH_GLOBAL
+#define TARGET_SCHED_FINISH_GLOBAL ia64_sched_finish_global
#undef TARGET_SCHED_REORDER
#define TARGET_SCHED_REORDER ia64_sched_reorder
#undef TARGET_SCHED_REORDER2
@@ -328,9 +343,6 @@ static const struct attribute_spec ia64_attribute_table[] =
#undef TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK
#define TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK ia64_dependencies_evaluation_hook
-#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
-#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE ia64_use_dfa_pipeline_interface
-
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD ia64_first_cycle_multipass_dfa_lookahead
@@ -346,8 +358,29 @@ static const struct attribute_spec ia64_attribute_table[] =
#undef TARGET_SCHED_DFA_NEW_CYCLE
#define TARGET_SCHED_DFA_NEW_CYCLE ia64_dfa_new_cycle
+#undef TARGET_SCHED_H_I_D_EXTENDED
+#define TARGET_SCHED_H_I_D_EXTENDED ia64_h_i_d_extended
+
+#undef TARGET_SCHED_SET_SCHED_FLAGS
+#define TARGET_SCHED_SET_SCHED_FLAGS ia64_set_sched_flags
+
+#undef TARGET_SCHED_SPECULATE_INSN
+#define TARGET_SCHED_SPECULATE_INSN ia64_speculate_insn
+
+#undef TARGET_SCHED_NEEDS_BLOCK_P
+#define TARGET_SCHED_NEEDS_BLOCK_P ia64_needs_block_p
+
+#undef TARGET_SCHED_GEN_CHECK
+#define TARGET_SCHED_GEN_CHECK ia64_gen_check
+
+#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC
+#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC\
+ ia64_first_cycle_multipass_dfa_lookahead_guard_spec
+
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL ia64_function_ok_for_sibcall
+#undef TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES ia64_arg_partial_bytes
#undef TARGET_ASM_OUTPUT_MI_THUNK
#define TARGET_ASM_OUTPUT_MI_THUNK ia64_output_mi_thunk
@@ -368,639 +401,78 @@ static const struct attribute_spec ia64_attribute_table[] =
#undef TARGET_ENCODE_SECTION_INFO
#define TARGET_ENCODE_SECTION_INFO ia64_encode_section_info
-#undef TARGET_STRUCT_VALUE_RTX
-#define TARGET_STRUCT_VALUE_RTX ia64_struct_value_rtx
-
-struct gcc_target targetm = TARGET_INITIALIZER;
-
-/* Return 1 if OP is a valid operand for the MEM of a CALL insn. */
-
-int
-call_operand (rtx op, enum machine_mode mode)
-{
- if (mode != GET_MODE (op) && mode != VOIDmode)
- return 0;
-
- return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG
- || (GET_CODE (op) == SUBREG && GET_CODE (XEXP (op, 0)) == REG));
-}
-
-/* Return 1 if OP refers to a symbol in the sdata section. */
-
-int
-sdata_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- HOST_WIDE_INT offset = 0, size = 0;
-
- switch (GET_CODE (op))
- {
- case CONST:
- op = XEXP (op, 0);
- if (GET_CODE (op) != PLUS
- || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
- || GET_CODE (XEXP (op, 1)) != CONST_INT)
- break;
- offset = INTVAL (XEXP (op, 1));
- op = XEXP (op, 0);
- /* FALLTHRU */
-
- case SYMBOL_REF:
- if (CONSTANT_POOL_ADDRESS_P (op))
- {
- size = GET_MODE_SIZE (get_pool_mode (op));
- if (size > ia64_section_threshold)
- return false;
- }
- else
- {
- tree t;
-
- if (!SYMBOL_REF_LOCAL_P (op) || !SYMBOL_REF_SMALL_P (op))
- return false;
-
- /* Note that in addition to DECLs, we can get various forms
- of constants here. */
- t = SYMBOL_REF_DECL (op);
- if (DECL_P (t))
- t = DECL_SIZE_UNIT (t);
- else
- t = TYPE_SIZE_UNIT (TREE_TYPE (t));
- if (t && host_integerp (t, 0))
- {
- size = tree_low_cst (t, 0);
- if (size < 0)
- size = 0;
- }
- }
-
- /* Deny the stupid user trick of addressing outside the object. Such
- things quickly result in GPREL22 relocation overflows. Of course,
- they're also highly undefined. From a pure pedant's point of view
- they deserve a slap on the wrist (such as provided by a relocation
- overflow), but that just leads to bugzilla noise. */
- return (offset >= 0 && offset <= size);
-
- default:
- break;
- }
-
- return 0;
-}
-
-int
-small_addr_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return SYMBOL_REF_SMALL_ADDR_P (op);
-}
-
-/* Return 1 if OP refers to a symbol, and is appropriate for a GOT load. */
-
-int
-got_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case CONST:
- op = XEXP (op, 0);
- if (GET_CODE (op) != PLUS)
- return 0;
- if (GET_CODE (XEXP (op, 0)) != SYMBOL_REF)
- return 0;
- op = XEXP (op, 1);
- if (GET_CODE (op) != CONST_INT)
- return 0;
-
- return 1;
-
- /* Ok if we're not using GOT entries at all. */
- if (TARGET_NO_PIC || TARGET_AUTO_PIC)
- return 1;
-
- /* "Ok" while emitting rtl, since otherwise we won't be provided
- with the entire offset during emission, which makes it very
- hard to split the offset into high and low parts. */
- if (rtx_equal_function_value_matters)
- return 1;
-
- /* Force the low 14 bits of the constant to zero so that we do not
- use up so many GOT entries. */
- return (INTVAL (op) & 0x3fff) == 0;
-
- case SYMBOL_REF:
- if (SYMBOL_REF_SMALL_ADDR_P (op))
- return 0;
- case LABEL_REF:
- return 1;
-
- default:
- break;
- }
- return 0;
-}
-
-/* Return 1 if OP refers to a symbol. */
-
-int
-symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case CONST:
- case SYMBOL_REF:
- case LABEL_REF:
- return 1;
-
- default:
- break;
- }
- return 0;
-}
-
-/* Return tls_model if OP refers to a TLS symbol. */
-
-int
-tls_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != SYMBOL_REF)
- return 0;
- return SYMBOL_REF_TLS_MODEL (op);
-}
-
-
-/* Return 1 if OP refers to a function. */
-
-int
-function_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (op))
- return 1;
- else
- return 0;
-}
-
-/* Return 1 if OP is setjmp or a similar function. */
-
-/* ??? This is an unsatisfying solution. Should rethink. */
-
-int
-setjmp_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- const char *name;
- int retval = 0;
-
- if (GET_CODE (op) != SYMBOL_REF)
- return 0;
-
- name = XSTR (op, 0);
-
- /* The following code is borrowed from special_function_p in calls.c. */
-
- /* Disregard prefix _, __ or __x. */
- if (name[0] == '_')
- {
- if (name[1] == '_' && name[2] == 'x')
- name += 3;
- else if (name[1] == '_')
- name += 2;
- else
- name += 1;
- }
-
- if (name[0] == 's')
- {
- retval
- = ((name[1] == 'e'
- && (! strcmp (name, "setjmp")
- || ! strcmp (name, "setjmp_syscall")))
- || (name[1] == 'i'
- && ! strcmp (name, "sigsetjmp"))
- || (name[1] == 'a'
- && ! strcmp (name, "savectx")));
- }
- else if ((name[0] == 'q' && name[1] == 's'
- && ! strcmp (name, "qsetjmp"))
- || (name[0] == 'v' && name[1] == 'f'
- && ! strcmp (name, "vfork")))
- retval = 1;
-
- return retval;
-}
-
-/* Return 1 if OP is a general operand, excluding tls symbolic operands. */
-
-int
-move_operand (rtx op, enum machine_mode mode)
-{
- return general_operand (op, mode) && !tls_symbolic_operand (op, mode);
-}
-
-/* Return 1 if OP is a register operand that is (or could be) a GR reg. */
-
-int
-gr_register_operand (rtx op, enum machine_mode mode)
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return GENERAL_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a register operand that is (or could be) an FR reg. */
-
-int
-fr_register_operand (rtx op, enum machine_mode mode)
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return FR_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a register operand that is (or could be) a GR/FR reg. */
-
-int
-grfr_register_operand (rtx op, enum machine_mode mode)
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return GENERAL_REGNO_P (regno) || FR_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a nonimmediate operand that is (or could be) a GR reg. */
-
-int
-gr_nonimmediate_operand (rtx op, enum machine_mode mode)
-{
- if (! nonimmediate_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return GENERAL_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a nonimmediate operand that is (or could be) a FR reg. */
-
-int
-fr_nonimmediate_operand (rtx op, enum machine_mode mode)
-{
- if (! nonimmediate_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return FR_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a nonimmediate operand that is a GR/FR reg. */
-
-int
-grfr_nonimmediate_operand (rtx op, enum machine_mode mode)
-{
- if (! nonimmediate_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return GENERAL_REGNO_P (regno) || FR_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a GR register operand, or zero. */
-
-int
-gr_reg_or_0_operand (rtx op, enum machine_mode mode)
-{
- return (op == const0_rtx || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR register operand, or a 5 bit immediate operand. */
-
-int
-gr_reg_or_5bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) < 32)
- || GET_CODE (op) == CONSTANT_P_RTX
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR register operand, or a 6 bit immediate operand. */
-
-int
-gr_reg_or_6bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op)))
- || GET_CODE (op) == CONSTANT_P_RTX
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR register operand, or an 8 bit immediate operand. */
-
-int
-gr_reg_or_8bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)))
- || GET_CODE (op) == CONSTANT_P_RTX
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR/FR register operand, or an 8 bit immediate. */
-
-int
-grfr_reg_or_8bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)))
- || GET_CODE (op) == CONSTANT_P_RTX
- || grfr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or an 8 bit adjusted immediate
- operand. */
-
-int
-gr_reg_or_8bit_adjusted_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_L (INTVAL (op)))
- || GET_CODE (op) == CONSTANT_P_RTX
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or is valid for both an 8 bit
- immediate and an 8 bit adjusted immediate operand. This is necessary
- because when we emit a compare, we don't know what the condition will be,
- so we need the union of the immediates accepted by GT and LT. */
-
-int
-gr_reg_or_8bit_and_adjusted_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op))
- && CONST_OK_FOR_L (INTVAL (op)))
- || GET_CODE (op) == CONSTANT_P_RTX
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or a 14 bit immediate operand. */
-
-int
-gr_reg_or_14bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_I (INTVAL (op)))
- || GET_CODE (op) == CONSTANT_P_RTX
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or a 22 bit immediate operand. */
-
-int
-gr_reg_or_22bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_J (INTVAL (op)))
- || GET_CODE (op) == CONSTANT_P_RTX
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a 6 bit immediate operand. */
-
-int
-shift_count_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op)))
- || GET_CODE (op) == CONSTANT_P_RTX);
-}
-
-/* Return 1 if OP is a 5 bit immediate operand. */
-
-int
-shift_32bit_count_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return ((GET_CODE (op) == CONST_INT
- && (INTVAL (op) >= 0 && INTVAL (op) < 32))
- || GET_CODE (op) == CONSTANT_P_RTX);
-}
-
-/* Return 1 if OP is a 2, 4, 8, or 16 immediate operand. */
-
-int
-shladd_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && (INTVAL (op) == 2 || INTVAL (op) == 4
- || INTVAL (op) == 8 || INTVAL (op) == 16));
-}
-
-/* Return 1 if OP is a -16, -8, -4, -1, 1, 4, 8, or 16 immediate operand. */
-
-int
-fetchadd_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && (INTVAL (op) == -16 || INTVAL (op) == -8 ||
- INTVAL (op) == -4 || INTVAL (op) == -1 ||
- INTVAL (op) == 1 || INTVAL (op) == 4 ||
- INTVAL (op) == 8 || INTVAL (op) == 16));
-}
-
-/* Return 1 if OP is a floating-point constant zero, one, or a register. */
-
-int
-fr_reg_or_fp01_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (op))
- || fr_register_operand (op, mode));
-}
-
-/* Like nonimmediate_operand, but don't allow MEMs that try to use a
- POST_MODIFY with a REG as displacement. */
-
-int
-destination_operand (rtx op, enum machine_mode mode)
-{
- if (! nonimmediate_operand (op, mode))
- return 0;
- if (GET_CODE (op) == MEM
- && GET_CODE (XEXP (op, 0)) == POST_MODIFY
- && GET_CODE (XEXP (XEXP (XEXP (op, 0), 1), 1)) == REG)
- return 0;
- return 1;
-}
-
-/* Like memory_operand, but don't allow post-increments. */
-
-int
-not_postinc_memory_operand (rtx op, enum machine_mode mode)
-{
- return (memory_operand (op, mode)
- && GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != 'a');
-}
-
-/* Return 1 if this is a comparison operator, which accepts a normal 8-bit
- signed immediate operand. */
-
-int
-normal_comparison_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((mode == VOIDmode || GET_MODE (op) == mode)
- && (code == EQ || code == NE
- || code == GT || code == LE || code == GTU || code == LEU));
-}
-
-/* Return 1 if this is a comparison operator, which accepts an adjusted 8-bit
- signed immediate operand. */
-
-int
-adjusted_comparison_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((mode == VOIDmode || GET_MODE (op) == mode)
- && (code == LT || code == GE || code == LTU || code == GEU));
-}
-
-/* Return 1 if this is a signed inequality operator. */
-
-int
-signed_inequality_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((mode == VOIDmode || GET_MODE (op) == mode)
- && (code == GE || code == GT
- || code == LE || code == LT));
-}
-
-/* Return 1 if this operator is valid for predication. */
+#undef TARGET_SECTION_TYPE_FLAGS
+#define TARGET_SECTION_TYPE_FLAGS ia64_section_type_flags
-int
-predicate_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((GET_MODE (op) == mode || mode == VOIDmode)
- && (code == EQ || code == NE));
-}
-
-/* Return 1 if this operator can be used in a conditional operation. */
-
-int
-condop_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((GET_MODE (op) == mode || mode == VOIDmode)
- && (code == PLUS || code == MINUS || code == AND
- || code == IOR || code == XOR));
-}
-
-/* Return 1 if this is the ar.lc register. */
-
-int
-ar_lc_reg_operand (register rtx op, enum machine_mode mode)
-{
- return (GET_MODE (op) == DImode
- && (mode == DImode || mode == VOIDmode)
- && GET_CODE (op) == REG
- && REGNO (op) == AR_LC_REGNUM);
-}
-
-/* Return 1 if this is the ar.ccv register. */
-
-int
-ar_ccv_reg_operand (register rtx op, enum machine_mode mode)
-{
- return ((GET_MODE (op) == mode || mode == VOIDmode)
- && GET_CODE (op) == REG
- && REGNO (op) == AR_CCV_REGNUM);
-}
-
-/* Return 1 if this is the ar.pfs register. */
-
-int
-ar_pfs_reg_operand (register rtx op, enum machine_mode mode)
-{
- return ((GET_MODE (op) == mode || mode == VOIDmode)
- && GET_CODE (op) == REG
- && REGNO (op) == AR_PFS_REGNUM);
-}
-
-/* Like general_operand, but don't allow (mem (addressof)). */
-
-int
-general_xfmode_operand (rtx op, enum machine_mode mode)
-{
- if (! general_operand (op, mode))
- return 0;
- if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == ADDRESSOF)
- return 0;
- return 1;
-}
-
-/* Similarly. */
-
-int
-destination_xfmode_operand (rtx op, enum machine_mode mode)
-{
- if (! destination_operand (op, mode))
- return 0;
- if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == ADDRESSOF)
- return 0;
- return 1;
-}
+#ifdef HAVE_AS_TLS
+#undef TARGET_ASM_OUTPUT_DWARF_DTPREL
+#define TARGET_ASM_OUTPUT_DWARF_DTPREL ia64_output_dwarf_dtprel
+#endif
-/* Similarly. */
+/* ??? ABI doesn't allow us to define this. */
+#if 0
+#undef TARGET_PROMOTE_FUNCTION_ARGS
+#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
+#endif
-int
-xfreg_or_fp01_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == SUBREG)
- return 0;
- return fr_reg_or_fp01_operand (op, mode);
-}
+/* ??? ABI doesn't allow us to define this. */
+#if 0
+#undef TARGET_PROMOTE_FUNCTION_RETURN
+#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
+#endif
-/* Return 1 if OP is valid as a base register in a reg + offset address. */
+/* ??? Investigate. */
+#if 0
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
+#endif
-int
-basereg_operand (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. */
+#undef TARGET_STRUCT_VALUE_RTX
+#define TARGET_STRUCT_VALUE_RTX ia64_struct_value_rtx
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY ia64_return_in_memory
+#undef TARGET_SETUP_INCOMING_VARARGS
+#define TARGET_SETUP_INCOMING_VARARGS ia64_setup_incoming_varargs
+#undef TARGET_STRICT_ARGUMENT_NAMING
+#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
+#undef TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
+
+#undef TARGET_GIMPLIFY_VA_ARG_EXPR
+#define TARGET_GIMPLIFY_VA_ARG_EXPR ia64_gimplify_va_arg
+
+#undef TARGET_UNWIND_EMIT
+#define TARGET_UNWIND_EMIT process_for_unwind_directive
+
+#undef TARGET_SCALAR_MODE_SUPPORTED_P
+#define TARGET_SCALAR_MODE_SUPPORTED_P ia64_scalar_mode_supported_p
+#undef TARGET_VECTOR_MODE_SUPPORTED_P
+#define TARGET_VECTOR_MODE_SUPPORTED_P ia64_vector_mode_supported_p
+
+/* ia64 architecture manual 4.4.7: ... reads, writes, and flushes may occur
+ in an order different from the specified program order. */
+#undef TARGET_RELAXED_ORDERING
+#define TARGET_RELAXED_ORDERING true
+
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | TARGET_CPU_DEFAULT)
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION ia64_handle_option
+
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM ia64_cannot_force_const_mem
+
+#undef TARGET_MANGLE_FUNDAMENTAL_TYPE
+#define TARGET_MANGLE_FUNDAMENTAL_TYPE ia64_mangle_fundamental_type
+
+#undef TARGET_INVALID_CONVERSION
+#define TARGET_INVALID_CONVERSION ia64_invalid_conversion
+#undef TARGET_INVALID_UNARY_OP
+#define TARGET_INVALID_UNARY_OP ia64_invalid_unary_op
+#undef TARGET_INVALID_BINARY_OP
+#define TARGET_INVALID_BINARY_OP ia64_invalid_binary_op
- return (register_operand (op, mode) &&
- REG_POINTER ((GET_CODE (op) == SUBREG) ? SUBREG_REG (op) : op));
-}
+struct gcc_target targetm = TARGET_INITIALIZER;
typedef enum
{
@@ -1043,7 +515,8 @@ ia64_get_addr_area (tree decl)
}
static tree
-ia64_handle_model_attribute (tree *node, tree name, tree args, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+ia64_handle_model_attribute (tree *node, tree name, tree args,
+ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
{
ia64_addr_area addr_area = ADDR_AREA_NORMAL;
ia64_addr_area area;
@@ -1057,7 +530,7 @@ ia64_handle_model_attribute (tree *node, tree name, tree args, int flags ATTRIBU
}
else
{
- warning ("invalid argument of `%s' attribute",
+ warning (OPT_Wattributes, "invalid argument of %qs attribute",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
@@ -1070,26 +543,27 @@ ia64_handle_model_attribute (tree *node, tree name, tree args, int flags ATTRIBU
&& !TREE_STATIC (decl))
{
error ("%Jan address area attribute cannot be specified for "
- "local variables", decl, decl);
+ "local variables", decl);
*no_add_attrs = true;
}
area = ia64_get_addr_area (decl);
if (area != ADDR_AREA_NORMAL && addr_area != area)
{
- error ("%Jaddress area of '%s' conflicts with previous "
- "declaration", decl, decl);
+ error ("address area of %q+D conflicts with previous "
+ "declaration", decl);
*no_add_attrs = true;
}
break;
case FUNCTION_DECL:
error ("%Jaddress area attribute cannot be specified for functions",
- decl, decl);
+ decl);
*no_add_attrs = true;
break;
default:
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qs attribute ignored",
+ IDENTIFIER_POINTER (name));
*no_add_attrs = true;
break;
}
@@ -1107,7 +581,7 @@ ia64_encode_addr_area (tree decl, rtx symbol)
{
case ADDR_AREA_NORMAL: break;
case ADDR_AREA_SMALL: flags |= SYMBOL_FLAG_SMALL_ADDR; break;
- default: abort ();
+ default: gcc_unreachable ();
}
SYMBOL_REF_FLAGS (symbol) = flags;
}
@@ -1125,6 +599,102 @@ ia64_encode_section_info (tree decl, rtx rtl, int first)
ia64_encode_addr_area (decl, XEXP (rtl, 0));
}
+/* Implement CONST_OK_FOR_LETTER_P. */
+
+bool
+ia64_const_ok_for_letter_p (HOST_WIDE_INT value, char c)
+{
+ switch (c)
+ {
+ case 'I':
+ return CONST_OK_FOR_I (value);
+ case 'J':
+ return CONST_OK_FOR_J (value);
+ case 'K':
+ return CONST_OK_FOR_K (value);
+ case 'L':
+ return CONST_OK_FOR_L (value);
+ case 'M':
+ return CONST_OK_FOR_M (value);
+ case 'N':
+ return CONST_OK_FOR_N (value);
+ case 'O':
+ return CONST_OK_FOR_O (value);
+ case 'P':
+ return CONST_OK_FOR_P (value);
+ default:
+ return false;
+ }
+}
+
+/* Implement CONST_DOUBLE_OK_FOR_LETTER_P. */
+
+bool
+ia64_const_double_ok_for_letter_p (rtx value, char c)
+{
+ switch (c)
+ {
+ case 'G':
+ return CONST_DOUBLE_OK_FOR_G (value);
+ default:
+ return false;
+ }
+}
+
+/* Implement EXTRA_CONSTRAINT. */
+
+bool
+ia64_extra_constraint (rtx value, char c)
+{
+ switch (c)
+ {
+ case 'Q':
+ /* Non-volatile memory for FP_REG loads/stores. */
+ return memory_operand(value, VOIDmode) && !MEM_VOLATILE_P (value);
+
+ case 'R':
+ /* 1..4 for shladd arguments. */
+ return (GET_CODE (value) == CONST_INT
+ && INTVAL (value) >= 1 && INTVAL (value) <= 4);
+
+ case 'S':
+ /* Non-post-inc memory for asms and other unsavory creatures. */
+ return (GET_CODE (value) == MEM
+ && GET_RTX_CLASS (GET_CODE (XEXP (value, 0))) != RTX_AUTOINC
+ && (reload_in_progress || memory_operand (value, VOIDmode)));
+
+ case 'T':
+ /* Symbol ref to small-address-area. */
+ return small_addr_symbolic_operand (value, VOIDmode);
+
+ case 'U':
+ /* Vector zero. */
+ return value == CONST0_RTX (GET_MODE (value));
+
+ case 'W':
+ /* An integer vector, such that conversion to an integer yields a
+ value appropriate for an integer 'J' constraint. */
+ if (GET_CODE (value) == CONST_VECTOR
+ && GET_MODE_CLASS (GET_MODE (value)) == MODE_VECTOR_INT)
+ {
+ value = simplify_subreg (DImode, value, GET_MODE (value), 0);
+ return ia64_const_ok_for_letter_p (INTVAL (value), 'J');
+ }
+ return false;
+
+ case 'Y':
+ /* A V2SF vector containing elements that satisfy 'G'. */
+ return
+ (GET_CODE (value) == CONST_VECTOR
+ && GET_MODE (value) == V2SFmode
+ && ia64_const_double_ok_for_letter_p (XVECEXP (value, 0, 0), 'G')
+ && ia64_const_double_ok_for_letter_p (XVECEXP (value, 0, 1), 'G'));
+
+ default:
+ return false;
+ }
+}
+
/* Return 1 if the operands of a move are ok. */
int
@@ -1148,6 +718,37 @@ ia64_move_ok (rtx dst, rtx src)
return GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src);
}
+/* Return 1 if the operands are ok for a floating point load pair. */
+
+int
+ia64_load_pair_ok (rtx dst, rtx src)
+{
+ if (GET_CODE (dst) != REG || !FP_REGNO_P (REGNO (dst)))
+ return 0;
+ if (GET_CODE (src) != MEM || MEM_VOLATILE_P (src))
+ return 0;
+ switch (GET_CODE (XEXP (src, 0)))
+ {
+ case REG:
+ case POST_INC:
+ break;
+ case POST_DEC:
+ return 0;
+ case POST_MODIFY:
+ {
+ rtx adjust = XEXP (XEXP (XEXP (src, 0), 1), 1);
+
+ if (GET_CODE (adjust) != CONST_INT
+ || INTVAL (adjust) != GET_MODE_SIZE (GET_MODE (src)))
+ return 0;
+ }
+ break;
+ default:
+ abort ();
+ }
+ return 1;
+}
+
int
addp4_optimize_ok (rtx op1, rtx op2)
{
@@ -1171,72 +772,158 @@ ia64_depz_field_mask (rtx rop, rtx rshift)
return exact_log2 (op + 1);
}
+/* Return the TLS model to use for ADDR. */
+
+static enum tls_model
+tls_symbolic_operand_type (rtx addr)
+{
+ enum tls_model tls_kind = 0;
+
+ if (GET_CODE (addr) == CONST)
+ {
+ if (GET_CODE (XEXP (addr, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF)
+ tls_kind = SYMBOL_REF_TLS_MODEL (XEXP (XEXP (addr, 0), 0));
+ }
+ else if (GET_CODE (addr) == SYMBOL_REF)
+ tls_kind = SYMBOL_REF_TLS_MODEL (addr);
+
+ return tls_kind;
+}
+
+/* Return true if X is a constant that is valid for some immediate
+ field in an instruction. */
+
+bool
+ia64_legitimate_constant_p (rtx x)
+{
+ switch (GET_CODE (x))
+ {
+ case CONST_INT:
+ case LABEL_REF:
+ return true;
+
+ case CONST_DOUBLE:
+ if (GET_MODE (x) == VOIDmode)
+ return true;
+ return CONST_DOUBLE_OK_FOR_G (x);
+
+ case CONST:
+ case SYMBOL_REF:
+ /* ??? Short term workaround for PR 28490. We must make the code here
+ match the code in ia64_expand_move and move_operand, even though they
+ are both technically wrong. */
+ if (tls_symbolic_operand_type (x) == 0)
+ {
+ HOST_WIDE_INT addend = 0;
+ rtx op = x;
+
+ if (GET_CODE (op) == CONST
+ && GET_CODE (XEXP (op, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
+ {
+ addend = INTVAL (XEXP (XEXP (op, 0), 1));
+ op = XEXP (XEXP (op, 0), 0);
+ }
+
+ if (any_offset_symbol_operand (op, GET_MODE (op))
+ || function_operand (op, GET_MODE (op)))
+ return true;
+ if (aligned_offset_symbol_operand (op, GET_MODE (op)))
+ return (addend & 0x3fff) == 0;
+ return false;
+ }
+ return false;
+
+ case CONST_VECTOR:
+ {
+ enum machine_mode mode = GET_MODE (x);
+
+ if (mode == V2SFmode)
+ return ia64_extra_constraint (x, 'Y');
+
+ return (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
+ && GET_MODE_SIZE (mode) <= 8);
+ }
+
+ default:
+ return false;
+ }
+}
+
+/* Don't allow TLS addresses to get spilled to memory. */
+
+static bool
+ia64_cannot_force_const_mem (rtx x)
+{
+ return tls_symbolic_operand_type (x) != 0;
+}
+
/* Expand a symbolic constant load. */
-void
+bool
ia64_expand_load_address (rtx dest, rtx src)
{
- if (tls_symbolic_operand (src, VOIDmode))
- abort ();
- if (GET_CODE (dest) != REG)
- abort ();
+ gcc_assert (GET_CODE (dest) == REG);
/* ILP32 mode still loads 64-bits of data from the GOT. This avoids
having to pointer-extend the value afterward. Other forms of address
computation below are also more natural to compute as 64-bit quantities.
If we've been given an SImode destination register, change it. */
if (GET_MODE (dest) != Pmode)
- dest = gen_rtx_REG (Pmode, REGNO (dest));
+ dest = gen_rtx_REG_offset (dest, Pmode, REGNO (dest), 0);
- if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_SMALL_ADDR_P (src))
- {
- emit_insn (gen_rtx_SET (VOIDmode, dest, src));
- return;
- }
- else if (TARGET_AUTO_PIC)
- {
- emit_insn (gen_load_gprel64 (dest, src));
- return;
- }
+ if (TARGET_NO_PIC)
+ return false;
+ if (small_addr_symbolic_operand (src, VOIDmode))
+ return false;
+
+ if (TARGET_AUTO_PIC)
+ emit_insn (gen_load_gprel64 (dest, src));
else if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (src))
- {
- emit_insn (gen_load_fptr (dest, src));
- return;
- }
+ emit_insn (gen_load_fptr (dest, src));
else if (sdata_symbolic_operand (src, VOIDmode))
+ emit_insn (gen_load_gprel (dest, src));
+ else
{
- emit_insn (gen_load_gprel (dest, src));
- return;
- }
+ HOST_WIDE_INT addend = 0;
+ rtx tmp;
- if (GET_CODE (src) == CONST
- && GET_CODE (XEXP (src, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (src, 0), 1)) == CONST_INT
- && (INTVAL (XEXP (XEXP (src, 0), 1)) & 0x1fff) != 0)
- {
- rtx sym = XEXP (XEXP (src, 0), 0);
- HOST_WIDE_INT ofs, hi, lo;
+ /* We did split constant offsets in ia64_expand_move, and we did try
+ to keep them split in move_operand, but we also allowed reload to
+ rematerialize arbitrary constants rather than spill the value to
+ the stack and reload it. So we have to be prepared here to split
+ them apart again. */
+ if (GET_CODE (src) == CONST)
+ {
+ HOST_WIDE_INT hi, lo;
- /* Split the offset into a sign extended 14-bit low part
- and a complementary high part. */
- ofs = INTVAL (XEXP (XEXP (src, 0), 1));
- lo = ((ofs & 0x3fff) ^ 0x2000) - 0x2000;
- hi = ofs - lo;
+ hi = INTVAL (XEXP (XEXP (src, 0), 1));
+ lo = ((hi & 0x3fff) ^ 0x2000) - 0x2000;
+ hi = hi - lo;
- ia64_expand_load_address (dest, plus_constant (sym, hi));
- emit_insn (gen_adddi3 (dest, dest, GEN_INT (lo)));
- }
- else
- {
- rtx tmp;
+ if (lo != 0)
+ {
+ addend = lo;
+ src = plus_constant (XEXP (XEXP (src, 0), 0), hi);
+ }
+ }
tmp = gen_rtx_HIGH (Pmode, src);
tmp = gen_rtx_PLUS (Pmode, tmp, pic_offset_table_rtx);
emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
- tmp = gen_rtx_LO_SUM (GET_MODE (dest), dest, src);
+ tmp = gen_rtx_LO_SUM (Pmode, dest, src);
emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
+
+ if (addend)
+ {
+ tmp = gen_rtx_PLUS (Pmode, dest, GEN_INT (addend));
+ emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
+ }
}
+
+ return true;
}
static GTY(()) rtx gen_tls_tga;
@@ -1253,18 +940,17 @@ static rtx
gen_thread_pointer (void)
{
if (!thread_pointer_rtx)
- {
- thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
- RTX_UNCHANGING_P (thread_pointer_rtx) = 1;
- }
+ thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
return thread_pointer_rtx;
}
static rtx
-ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
+ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1,
+ rtx orig_op1, HOST_WIDE_INT addend)
{
rtx tga_op1, tga_op2, tga_ret, tga_eqv, tmp, insns;
rtx orig_op0 = op0;
+ HOST_WIDE_INT addend_lo, addend_hi;
switch (tls_kind)
{
@@ -1272,14 +958,10 @@ ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
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;
+ emit_insn (gen_load_dtpmod (tga_op1, op1));
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;
+ emit_insn (gen_load_dtprel (tga_op2, op1));
tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
LCT_CONST, Pmode, 2, tga_op1,
@@ -1301,9 +983,7 @@ ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
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;
+ emit_insn (gen_load_dtpmod (tga_op1, op1));
tga_op2 = const0_rtx;
@@ -1327,15 +1007,18 @@ ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
emit_insn (gen_adddi3 (op0, tmp, op0));
}
else
- emit_insn (gen_add_dtprel (op0, tmp, op1));
+ emit_insn (gen_add_dtprel (op0, op1, tmp));
break;
case TLS_MODEL_INITIAL_EXEC:
+ addend_lo = ((addend & 0x3fff) ^ 0x2000) - 0x2000;
+ addend_hi = addend - addend_lo;
+
+ op1 = plus_constant (op1, addend_hi);
+ addend = addend_lo;
+
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);
+ emit_insn (gen_load_tprel (tmp, op1));
if (!register_operand (op0, Pmode))
op0 = gen_reg_rtx (Pmode);
@@ -1345,19 +1028,25 @@ ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
case TLS_MODEL_LOCAL_EXEC:
if (!register_operand (op0, Pmode))
op0 = gen_reg_rtx (Pmode);
+
+ op1 = orig_op1;
+ addend = 0;
if (TARGET_TLS64)
{
emit_insn (gen_load_tprel (op0, op1));
- emit_insn (gen_adddi3 (op0, gen_thread_pointer (), op0));
+ emit_insn (gen_adddi3 (op0, op0, gen_thread_pointer ()));
}
else
- emit_insn (gen_add_tprel (op0, gen_thread_pointer (), op1));
+ emit_insn (gen_add_tprel (op0, op1, gen_thread_pointer ()));
break;
default:
- abort ();
+ gcc_unreachable ();
}
+ if (addend)
+ op0 = expand_simple_binop (Pmode, PLUS, op0, GEN_INT (addend),
+ orig_op0, 1, OPTAB_DIRECT);
if (orig_op0 == op0)
return NULL_RTX;
if (GET_MODE (orig_op0) == Pmode)
@@ -1375,14 +1064,60 @@ ia64_expand_move (rtx op0, rtx op1)
if ((mode == Pmode || mode == ptr_mode) && symbolic_operand (op1, VOIDmode))
{
+ HOST_WIDE_INT addend = 0;
enum tls_model tls_kind;
- if ((tls_kind = tls_symbolic_operand (op1, VOIDmode)))
- return ia64_expand_tls_address (tls_kind, op0, op1);
+ rtx sym = op1;
- if (!TARGET_NO_PIC && reload_completed)
+ if (GET_CODE (op1) == CONST
+ && GET_CODE (XEXP (op1, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (op1, 0), 1)) == CONST_INT)
{
- ia64_expand_load_address (op0, op1);
- return NULL_RTX;
+ addend = INTVAL (XEXP (XEXP (op1, 0), 1));
+ sym = XEXP (XEXP (op1, 0), 0);
+ }
+
+ tls_kind = tls_symbolic_operand_type (sym);
+ if (tls_kind)
+ return ia64_expand_tls_address (tls_kind, op0, sym, op1, addend);
+
+ if (any_offset_symbol_operand (sym, mode))
+ addend = 0;
+ else if (aligned_offset_symbol_operand (sym, mode))
+ {
+ HOST_WIDE_INT addend_lo, addend_hi;
+
+ addend_lo = ((addend & 0x3fff) ^ 0x2000) - 0x2000;
+ addend_hi = addend - addend_lo;
+
+ if (addend_lo != 0)
+ {
+ op1 = plus_constant (sym, addend_hi);
+ addend = addend_lo;
+ }
+ else
+ addend = 0;
+ }
+ else
+ op1 = sym;
+
+ if (reload_completed)
+ {
+ /* We really should have taken care of this offset earlier. */
+ gcc_assert (addend == 0);
+ if (ia64_expand_load_address (op0, op1))
+ return NULL_RTX;
+ }
+
+ if (addend)
+ {
+ rtx subtarget = no_new_pseudos ? op0 : gen_reg_rtx (mode);
+
+ emit_insn (gen_rtx_SET (VOIDmode, subtarget, op1));
+
+ op1 = expand_simple_binop (mode, PLUS, subtarget,
+ GEN_INT (addend), op0, 1, OPTAB_DIRECT);
+ if (op0 == op1)
+ return NULL_RTX;
}
}
@@ -1434,7 +1169,7 @@ ia64_split_tmode (rtx out[2], rtx in, bool reversed, bool dead)
case CONST_INT:
case CONST_DOUBLE:
/* Cannot occur reversed. */
- if (reversed) abort ();
+ gcc_assert (!reversed);
if (GET_MODE (in) != TFmode)
split_double (in, &out[0], &out[1]);
@@ -1491,14 +1226,16 @@ ia64_split_tmode (rtx out[2], rtx in, bool reversed, bool dead)
break;
case POST_INC:
- if (reversed || dead) abort ();
+ gcc_assert (!reversed && !dead);
+
/* Just do the increment in two steps. */
out[0] = adjust_automodify_address (in, DImode, 0, 0);
out[1] = adjust_automodify_address (in, DImode, 0, 8);
break;
case POST_DEC:
- if (reversed || dead) abort ();
+ gcc_assert (!reversed && !dead);
+
/* Add 8, subtract 24. */
base = XEXP (base, 0);
out[0] = adjust_automodify_address
@@ -1510,7 +1247,8 @@ ia64_split_tmode (rtx out[2], rtx in, bool reversed, bool dead)
break;
case POST_MODIFY:
- if (reversed || dead) abort ();
+ gcc_assert (!reversed && !dead);
+
/* Extract and adjust the modification. This case is
trickier than the others, because we might have an
index register, or we might have a combined offset that
@@ -1529,38 +1267,41 @@ ia64_split_tmode (rtx out[2], rtx in, bool reversed, bool dead)
out[1] = adjust_automodify_address (in, DImode, 0, 8);
fixup = gen_adddi3 (base, base, GEN_INT (-8));
}
- else if (GET_CODE (XEXP (offset, 1)) != CONST_INT)
- abort ();
- else if (INTVAL (XEXP (offset, 1)) < -256 + 8)
- {
- /* Again the postmodify cannot be made to match, but
- in this case it's more efficient to get rid of the
- postmodify entirely and fix up with an add insn. */
- out[1] = adjust_automodify_address (in, DImode, base, 8);
- fixup = gen_adddi3 (base, base,
- GEN_INT (INTVAL (XEXP (offset, 1)) - 8));
- }
else
{
- /* Combined offset still fits in the displacement field.
- (We cannot overflow it at the high end.) */
- out[1] = adjust_automodify_address
- (in, DImode,
- gen_rtx_POST_MODIFY (Pmode, base,
- gen_rtx_PLUS (Pmode, base,
- GEN_INT (INTVAL (XEXP (offset, 1)) - 8))),
- 8);
+ gcc_assert (GET_CODE (XEXP (offset, 1)) == CONST_INT);
+ if (INTVAL (XEXP (offset, 1)) < -256 + 8)
+ {
+ /* Again the postmodify cannot be made to match,
+ but in this case it's more efficient to get rid
+ of the postmodify entirely and fix up with an
+ add insn. */
+ out[1] = adjust_automodify_address (in, DImode, base, 8);
+ fixup = gen_adddi3
+ (base, base, GEN_INT (INTVAL (XEXP (offset, 1)) - 8));
+ }
+ else
+ {
+ /* Combined offset still fits in the displacement field.
+ (We cannot overflow it at the high end.) */
+ out[1] = adjust_automodify_address
+ (in, DImode, gen_rtx_POST_MODIFY
+ (Pmode, base, gen_rtx_PLUS
+ (Pmode, base,
+ GEN_INT (INTVAL (XEXP (offset, 1)) - 8))),
+ 8);
+ }
}
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
}
default:
- abort ();
+ gcc_unreachable ();
}
return fixup;
@@ -1580,7 +1321,7 @@ ia64_split_tmode_move (rtx operands[])
the value it points to. In that case we have to do the loads in
the appropriate order so that the pointer is not destroyed too
early. Also we must not generate a postmodify for that second
- load, or rws_access_regno will abort. */
+ load, or rws_access_regno will die. */
if (GET_CODE (operands[1]) == MEM
&& reg_overlap_mentioned_p (operands[0], operands[1]))
{
@@ -1637,28 +1378,159 @@ ia64_split_tmode_move (rtx operands[])
This solution attempts to prevent this situation from occurring. When
we see something like the above, we spill the inner register to memory. */
-rtx
-spill_xfmode_operand (rtx in, int force)
+static rtx
+spill_xfmode_rfmode_operand (rtx in, int force, enum machine_mode mode)
{
if (GET_CODE (in) == SUBREG
&& GET_MODE (SUBREG_REG (in)) == TImode
&& GET_CODE (SUBREG_REG (in)) == REG)
{
- rtx mem = gen_mem_addressof (SUBREG_REG (in), NULL_TREE, /*rescan=*/true);
- return gen_rtx_MEM (XFmode, copy_to_reg (XEXP (mem, 0)));
+ rtx memt = assign_stack_temp (TImode, 16, 0);
+ emit_move_insn (memt, SUBREG_REG (in));
+ return adjust_address (memt, mode, 0);
}
else if (force && GET_CODE (in) == REG)
{
- rtx mem = gen_mem_addressof (in, NULL_TREE, /*rescan=*/true);
- return gen_rtx_MEM (XFmode, copy_to_reg (XEXP (mem, 0)));
+ rtx memx = assign_stack_temp (mode, 16, 0);
+ emit_move_insn (memx, in);
+ return memx;
}
- else if (GET_CODE (in) == MEM
- && GET_CODE (XEXP (in, 0)) == ADDRESSOF)
- return change_address (in, XFmode, copy_to_reg (XEXP (in, 0)));
else
return in;
}
+/* Expand the movxf or movrf pattern (MODE says which) with the given
+ OPERANDS, returning true if the pattern should then invoke
+ DONE. */
+
+bool
+ia64_expand_movxf_movrf (enum machine_mode mode, rtx operands[])
+{
+ rtx op0 = operands[0];
+
+ if (GET_CODE (op0) == SUBREG)
+ op0 = SUBREG_REG (op0);
+
+ /* We must support XFmode loads into general registers for stdarg/vararg,
+ unprototyped calls, and a rare case where a long double is passed as
+ an argument after a float HFA fills the FP registers. We split them into
+ DImode loads for convenience. We also need to support XFmode stores
+ for the last case. This case does not happen for stdarg/vararg routines,
+ because we do a block store to memory of unnamed arguments. */
+
+ if (GET_CODE (op0) == REG && GR_REGNO_P (REGNO (op0)))
+ {
+ rtx out[2];
+
+ /* We're hoping to transform everything that deals with XFmode
+ quantities and GR registers early in the compiler. */
+ gcc_assert (!no_new_pseudos);
+
+ /* Struct to register can just use TImode instead. */
+ if ((GET_CODE (operands[1]) == SUBREG
+ && GET_MODE (SUBREG_REG (operands[1])) == TImode)
+ || (GET_CODE (operands[1]) == REG
+ && GR_REGNO_P (REGNO (operands[1]))))
+ {
+ rtx op1 = operands[1];
+
+ if (GET_CODE (op1) == SUBREG)
+ op1 = SUBREG_REG (op1);
+ else
+ op1 = gen_rtx_REG (TImode, REGNO (op1));
+
+ emit_move_insn (gen_rtx_REG (TImode, REGNO (op0)), op1);
+ return true;
+ }
+
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ /* Don't word-swap when reading in the constant. */
+ emit_move_insn (gen_rtx_REG (DImode, REGNO (op0)),
+ operand_subword (operands[1], WORDS_BIG_ENDIAN,
+ 0, mode));
+ emit_move_insn (gen_rtx_REG (DImode, REGNO (op0) + 1),
+ operand_subword (operands[1], !WORDS_BIG_ENDIAN,
+ 0, mode));
+ return true;
+ }
+
+ /* If the quantity is in a register not known to be GR, spill it. */
+ if (register_operand (operands[1], mode))
+ operands[1] = spill_xfmode_rfmode_operand (operands[1], 1, mode);
+
+ gcc_assert (GET_CODE (operands[1]) == MEM);
+
+ /* Don't word-swap when reading in the value. */
+ out[0] = gen_rtx_REG (DImode, REGNO (op0));
+ out[1] = gen_rtx_REG (DImode, REGNO (op0) + 1);
+
+ emit_move_insn (out[0], adjust_address (operands[1], DImode, 0));
+ emit_move_insn (out[1], adjust_address (operands[1], DImode, 8));
+ return true;
+ }
+
+ if (GET_CODE (operands[1]) == REG && GR_REGNO_P (REGNO (operands[1])))
+ {
+ /* We're hoping to transform everything that deals with XFmode
+ quantities and GR registers early in the compiler. */
+ gcc_assert (!no_new_pseudos);
+
+ /* Op0 can't be a GR_REG here, as that case is handled above.
+ If op0 is a register, then we spill op1, so that we now have a
+ MEM operand. This requires creating an XFmode subreg of a TImode reg
+ to force the spill. */
+ if (register_operand (operands[0], mode))
+ {
+ rtx op1 = gen_rtx_REG (TImode, REGNO (operands[1]));
+ op1 = gen_rtx_SUBREG (mode, op1, 0);
+ operands[1] = spill_xfmode_rfmode_operand (op1, 0, mode);
+ }
+
+ else
+ {
+ rtx in[2];
+
+ gcc_assert (GET_CODE (operands[0]) == MEM);
+
+ /* Don't word-swap when writing out the value. */
+ in[0] = gen_rtx_REG (DImode, REGNO (operands[1]));
+ in[1] = gen_rtx_REG (DImode, REGNO (operands[1]) + 1);
+
+ emit_move_insn (adjust_address (operands[0], DImode, 0), in[0]);
+ emit_move_insn (adjust_address (operands[0], DImode, 8), in[1]);
+ return true;
+ }
+ }
+
+ if (!reload_in_progress && !reload_completed)
+ {
+ operands[1] = spill_xfmode_rfmode_operand (operands[1], 0, mode);
+
+ if (GET_MODE (op0) == TImode && GET_CODE (op0) == REG)
+ {
+ rtx memt, memx, in = operands[1];
+ if (CONSTANT_P (in))
+ in = validize_mem (force_const_mem (mode, in));
+ if (GET_CODE (in) == MEM)
+ memt = adjust_address (in, TImode, 0);
+ else
+ {
+ memt = assign_stack_temp (TImode, 16, 0);
+ memx = adjust_address (memt, mode, 0);
+ emit_move_insn (memx, in);
+ }
+ emit_move_insn (op0, memt);
+ return true;
+ }
+
+ if (!ia64_move_ok (operands[0], operands[1]))
+ operands[1] = force_reg (mode, operands[1]);
+ }
+
+ return false;
+}
+
/* Emit comparison instruction if necessary, returning the expression
that holds the compare result in the proper mode. */
@@ -1674,15 +1546,13 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
do not need to emit another comparison. */
if (GET_MODE (op0) == BImode)
{
- if ((code == NE || code == EQ) && op1 == const0_rtx)
- cmp = op0;
- else
- abort ();
+ gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
+ cmp = op0;
}
/* HPUX TFmode compare requires a library call to _U_Qfcmp, which takes a
magic number as its third argument, that indicates what to do.
The return value is an integer to be compared against zero. */
- else if (TARGET_HPUX && GET_MODE (op0) == TFmode)
+ else if (GET_MODE (op0) == TFmode)
{
enum qfcmp_magic {
QCMP_INV = 1, /* Raise FP_INVALID on SNaN as a side effect. */
@@ -1693,8 +1563,8 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
} magic;
enum rtx_code ncode;
rtx ret, insns;
- if (GET_MODE (op1) != TFmode)
- abort ();
+
+ gcc_assert (cmptf_libfunc && GET_MODE (op1) == TFmode);
switch (code)
{
/* 1 = equal, 0 = not equal. Equality operators do
@@ -1703,6 +1573,7 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
case NE: magic = QCMP_EQ; ncode = EQ; break;
/* isunordered() from C99. */
case UNORDERED: magic = QCMP_UNORD; ncode = NE; break;
+ case ORDERED: magic = QCMP_UNORD; ncode = EQ; break;
/* Relational operators raise FP_INVALID when given
an SNaN operand. */
case LT: magic = QCMP_LT |QCMP_INV; ncode = NE; break;
@@ -1712,7 +1583,7 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
/* FUTURE: Implement UNEQ, UNLT, UNLE, UNGT, UNGE, LTGT.
Expanders for buneq etc. weuld have to be added to ia64.md
for this to be useful. */
- default: abort ();
+ default: gcc_unreachable ();
}
start_sequence ();
@@ -1743,6 +1614,316 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
return gen_rtx_fmt_ee (code, mode, cmp, const0_rtx);
}
+/* Generate an integral vector comparison. Return true if the condition has
+ been reversed, and so the sense of the comparison should be inverted. */
+
+static bool
+ia64_expand_vecint_compare (enum rtx_code code, enum machine_mode mode,
+ rtx dest, rtx op0, rtx op1)
+{
+ bool negate = false;
+ rtx x;
+
+ /* Canonicalize the comparison to EQ, GT, GTU. */
+ switch (code)
+ {
+ case EQ:
+ case GT:
+ case GTU:
+ break;
+
+ case NE:
+ case LE:
+ case LEU:
+ code = reverse_condition (code);
+ negate = true;
+ break;
+
+ case GE:
+ case GEU:
+ code = reverse_condition (code);
+ negate = true;
+ /* FALLTHRU */
+
+ case LT:
+ case LTU:
+ code = swap_condition (code);
+ x = op0, op0 = op1, op1 = x;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Unsigned parallel compare is not supported by the hardware. Play some
+ tricks to turn this into a signed comparison against 0. */
+ if (code == GTU)
+ {
+ switch (mode)
+ {
+ case V2SImode:
+ {
+ rtx t1, t2, mask;
+
+ /* Perform a parallel modulo subtraction. */
+ t1 = gen_reg_rtx (V2SImode);
+ emit_insn (gen_subv2si3 (t1, op0, op1));
+
+ /* Extract the original sign bit of op0. */
+ mask = GEN_INT (-0x80000000);
+ mask = gen_rtx_CONST_VECTOR (V2SImode, gen_rtvec (2, mask, mask));
+ mask = force_reg (V2SImode, mask);
+ t2 = gen_reg_rtx (V2SImode);
+ emit_insn (gen_andv2si3 (t2, op0, mask));
+
+ /* XOR it back into the result of the subtraction. This results
+ in the sign bit set iff we saw unsigned underflow. */
+ x = gen_reg_rtx (V2SImode);
+ emit_insn (gen_xorv2si3 (x, t1, t2));
+
+ code = GT;
+ op0 = x;
+ op1 = CONST0_RTX (mode);
+ }
+ break;
+
+ case V8QImode:
+ case V4HImode:
+ /* Perform a parallel unsigned saturating subtraction. */
+ x = gen_reg_rtx (mode);
+ emit_insn (gen_rtx_SET (VOIDmode, x,
+ gen_rtx_US_MINUS (mode, op0, op1)));
+
+ code = EQ;
+ op0 = x;
+ op1 = CONST0_RTX (mode);
+ negate = !negate;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ x = gen_rtx_fmt_ee (code, mode, op0, op1);
+ emit_insn (gen_rtx_SET (VOIDmode, dest, x));
+
+ return negate;
+}
+
+/* Emit an integral vector conditional move. */
+
+void
+ia64_expand_vecint_cmov (rtx operands[])
+{
+ enum machine_mode mode = GET_MODE (operands[0]);
+ enum rtx_code code = GET_CODE (operands[3]);
+ bool negate;
+ rtx cmp, x, ot, of;
+
+ cmp = gen_reg_rtx (mode);
+ negate = ia64_expand_vecint_compare (code, mode, cmp,
+ operands[4], operands[5]);
+
+ ot = operands[1+negate];
+ of = operands[2-negate];
+
+ if (ot == CONST0_RTX (mode))
+ {
+ if (of == CONST0_RTX (mode))
+ {
+ emit_move_insn (operands[0], ot);
+ return;
+ }
+
+ x = gen_rtx_NOT (mode, cmp);
+ x = gen_rtx_AND (mode, x, of);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ }
+ else if (of == CONST0_RTX (mode))
+ {
+ x = gen_rtx_AND (mode, cmp, ot);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ }
+ else
+ {
+ rtx t, f;
+
+ t = gen_reg_rtx (mode);
+ x = gen_rtx_AND (mode, cmp, operands[1+negate]);
+ emit_insn (gen_rtx_SET (VOIDmode, t, x));
+
+ f = gen_reg_rtx (mode);
+ x = gen_rtx_NOT (mode, cmp);
+ x = gen_rtx_AND (mode, x, operands[2-negate]);
+ emit_insn (gen_rtx_SET (VOIDmode, f, x));
+
+ x = gen_rtx_IOR (mode, t, f);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ }
+}
+
+/* Emit an integral vector min or max operation. Return true if all done. */
+
+bool
+ia64_expand_vecint_minmax (enum rtx_code code, enum machine_mode mode,
+ rtx operands[])
+{
+ rtx xops[6];
+
+ /* These four combinations are supported directly. */
+ if (mode == V8QImode && (code == UMIN || code == UMAX))
+ return false;
+ if (mode == V4HImode && (code == SMIN || code == SMAX))
+ return false;
+
+ /* This combination can be implemented with only saturating subtraction. */
+ if (mode == V4HImode && code == UMAX)
+ {
+ rtx x, tmp = gen_reg_rtx (mode);
+
+ x = gen_rtx_US_MINUS (mode, operands[1], operands[2]);
+ emit_insn (gen_rtx_SET (VOIDmode, tmp, x));
+
+ emit_insn (gen_addv4hi3 (operands[0], tmp, operands[2]));
+ return true;
+ }
+
+ /* Everything else implemented via vector comparisons. */
+ xops[0] = operands[0];
+ xops[4] = xops[1] = operands[1];
+ xops[5] = xops[2] = operands[2];
+
+ switch (code)
+ {
+ case UMIN:
+ code = LTU;
+ break;
+ case UMAX:
+ code = GTU;
+ break;
+ case SMIN:
+ code = LT;
+ break;
+ case SMAX:
+ code = GT;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ xops[3] = gen_rtx_fmt_ee (code, VOIDmode, operands[1], operands[2]);
+
+ ia64_expand_vecint_cmov (xops);
+ return true;
+}
+
+/* Emit an integral vector widening sum operations. */
+
+void
+ia64_expand_widen_sum (rtx operands[3], bool unsignedp)
+{
+ rtx l, h, x, s;
+ enum machine_mode wmode, mode;
+ rtx (*unpack_l) (rtx, rtx, rtx);
+ rtx (*unpack_h) (rtx, rtx, rtx);
+ rtx (*plus) (rtx, rtx, rtx);
+
+ wmode = GET_MODE (operands[0]);
+ mode = GET_MODE (operands[1]);
+
+ switch (mode)
+ {
+ case V8QImode:
+ unpack_l = gen_unpack1_l;
+ unpack_h = gen_unpack1_h;
+ plus = gen_addv4hi3;
+ break;
+ case V4HImode:
+ unpack_l = gen_unpack2_l;
+ unpack_h = gen_unpack2_h;
+ plus = gen_addv2si3;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Fill in x with the sign extension of each element in op1. */
+ if (unsignedp)
+ x = CONST0_RTX (mode);
+ else
+ {
+ bool neg;
+
+ x = gen_reg_rtx (mode);
+
+ neg = ia64_expand_vecint_compare (LT, mode, x, operands[1],
+ CONST0_RTX (mode));
+ gcc_assert (!neg);
+ }
+
+ l = gen_reg_rtx (wmode);
+ h = gen_reg_rtx (wmode);
+ s = gen_reg_rtx (wmode);
+
+ emit_insn (unpack_l (gen_lowpart (mode, l), operands[1], x));
+ emit_insn (unpack_h (gen_lowpart (mode, h), operands[1], x));
+ emit_insn (plus (s, l, operands[2]));
+ emit_insn (plus (operands[0], h, s));
+}
+
+/* Emit a signed or unsigned V8QI dot product operation. */
+
+void
+ia64_expand_dot_prod_v8qi (rtx operands[4], bool unsignedp)
+{
+ rtx l1, l2, h1, h2, x1, x2, p1, p2, p3, p4, s1, s2, s3;
+
+ /* Fill in x1 and x2 with the sign extension of each element. */
+ if (unsignedp)
+ x1 = x2 = CONST0_RTX (V8QImode);
+ else
+ {
+ bool neg;
+
+ x1 = gen_reg_rtx (V8QImode);
+ x2 = gen_reg_rtx (V8QImode);
+
+ neg = ia64_expand_vecint_compare (LT, V8QImode, x1, operands[1],
+ CONST0_RTX (V8QImode));
+ gcc_assert (!neg);
+ neg = ia64_expand_vecint_compare (LT, V8QImode, x2, operands[2],
+ CONST0_RTX (V8QImode));
+ gcc_assert (!neg);
+ }
+
+ l1 = gen_reg_rtx (V4HImode);
+ l2 = gen_reg_rtx (V4HImode);
+ h1 = gen_reg_rtx (V4HImode);
+ h2 = gen_reg_rtx (V4HImode);
+
+ emit_insn (gen_unpack1_l (gen_lowpart (V8QImode, l1), operands[1], x1));
+ emit_insn (gen_unpack1_l (gen_lowpart (V8QImode, l2), operands[2], x2));
+ emit_insn (gen_unpack1_h (gen_lowpart (V8QImode, h1), operands[1], x1));
+ emit_insn (gen_unpack1_h (gen_lowpart (V8QImode, h2), operands[2], x2));
+
+ p1 = gen_reg_rtx (V2SImode);
+ p2 = gen_reg_rtx (V2SImode);
+ p3 = gen_reg_rtx (V2SImode);
+ p4 = gen_reg_rtx (V2SImode);
+ emit_insn (gen_pmpy2_r (p1, l1, l2));
+ emit_insn (gen_pmpy2_l (p2, l1, l2));
+ emit_insn (gen_pmpy2_r (p3, h1, h2));
+ emit_insn (gen_pmpy2_l (p4, h1, h2));
+
+ s1 = gen_reg_rtx (V2SImode);
+ s2 = gen_reg_rtx (V2SImode);
+ s3 = gen_reg_rtx (V2SImode);
+ emit_insn (gen_addv2si3 (s1, p1, p2));
+ emit_insn (gen_addv2si3 (s2, p3, p4));
+ emit_insn (gen_addv2si3 (s3, s1, operands[3]));
+ emit_insn (gen_addv2si3 (operands[0], s2, s3));
+}
+
/* Emit the appropriate sequence for a call. */
void
@@ -1884,12 +2065,129 @@ ia64_split_call (rtx retval, rtx addr, rtx retaddr, rtx scratch_r,
if ((!TARGET_CONST_GP || is_desc) && !noreturn_p && !sibcall_p)
ia64_reload_gp ();
}
+
+/* Expand an atomic operation. We want to perform MEM <CODE>= VAL atomically.
+
+ This differs from the generic code in that we know about the zero-extending
+ properties of cmpxchg, and the zero-extending requirements of ar.ccv. We
+ also know that ld.acq+cmpxchg.rel equals a full barrier.
+
+ The loop we want to generate looks like
+
+ cmp_reg = mem;
+ label:
+ old_reg = cmp_reg;
+ new_reg = cmp_reg op val;
+ cmp_reg = compare-and-swap(mem, old_reg, new_reg)
+ if (cmp_reg != old_reg)
+ goto label;
+
+ Note that we only do the plain load from memory once. Subsequent
+ iterations use the value loaded by the compare-and-swap pattern. */
+
+void
+ia64_expand_atomic_op (enum rtx_code code, rtx mem, rtx val,
+ rtx old_dst, rtx new_dst)
+{
+ enum machine_mode mode = GET_MODE (mem);
+ rtx old_reg, new_reg, cmp_reg, ar_ccv, label;
+ enum insn_code icode;
+
+ /* Special case for using fetchadd. */
+ if ((mode == SImode || mode == DImode)
+ && (code == PLUS || code == MINUS)
+ && fetchadd_operand (val, mode))
+ {
+ if (code == MINUS)
+ val = GEN_INT (-INTVAL (val));
+
+ if (!old_dst)
+ old_dst = gen_reg_rtx (mode);
+
+ emit_insn (gen_memory_barrier ());
+
+ if (mode == SImode)
+ icode = CODE_FOR_fetchadd_acq_si;
+ else
+ icode = CODE_FOR_fetchadd_acq_di;
+ emit_insn (GEN_FCN (icode) (old_dst, mem, val));
+
+ if (new_dst)
+ {
+ new_reg = expand_simple_binop (mode, PLUS, old_dst, val, new_dst,
+ true, OPTAB_WIDEN);
+ if (new_reg != new_dst)
+ emit_move_insn (new_dst, new_reg);
+ }
+ return;
+ }
+
+ /* Because of the volatile mem read, we get an ld.acq, which is the
+ front half of the full barrier. The end half is the cmpxchg.rel. */
+ gcc_assert (MEM_VOLATILE_P (mem));
+
+ old_reg = gen_reg_rtx (DImode);
+ cmp_reg = gen_reg_rtx (DImode);
+ label = gen_label_rtx ();
+
+ if (mode != DImode)
+ {
+ val = simplify_gen_subreg (DImode, val, mode, 0);
+ emit_insn (gen_extend_insn (cmp_reg, mem, DImode, mode, 1));
+ }
+ else
+ emit_move_insn (cmp_reg, mem);
+
+ emit_label (label);
+
+ ar_ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
+ emit_move_insn (old_reg, cmp_reg);
+ emit_move_insn (ar_ccv, cmp_reg);
+
+ if (old_dst)
+ emit_move_insn (old_dst, gen_lowpart (mode, cmp_reg));
+
+ new_reg = cmp_reg;
+ if (code == NOT)
+ {
+ new_reg = expand_simple_unop (DImode, NOT, new_reg, NULL_RTX, true);
+ code = AND;
+ }
+ new_reg = expand_simple_binop (DImode, code, new_reg, val, NULL_RTX,
+ true, OPTAB_DIRECT);
+
+ if (mode != DImode)
+ new_reg = gen_lowpart (mode, new_reg);
+ if (new_dst)
+ emit_move_insn (new_dst, new_reg);
+
+ switch (mode)
+ {
+ case QImode: icode = CODE_FOR_cmpxchg_rel_qi; break;
+ case HImode: icode = CODE_FOR_cmpxchg_rel_hi; break;
+ case SImode: icode = CODE_FOR_cmpxchg_rel_si; break;
+ case DImode: icode = CODE_FOR_cmpxchg_rel_di; break;
+ default:
+ gcc_unreachable ();
+ }
+
+ emit_insn (GEN_FCN (icode) (cmp_reg, mem, ar_ccv, new_reg));
+
+ emit_cmp_and_jump_insns (cmp_reg, old_reg, NE, NULL, DImode, true, label);
+}
/* Begin the assembly file. */
static void
ia64_file_start (void)
{
+ /* Variable tracking should be run after all optimizations which change order
+ of insns. It also needs a valid CFG. This can't be done in
+ ia64_override_options, because flag_var_tracking is finalized after
+ that. */
+ ia64_flag_var_tracking = flag_var_tracking;
+ flag_var_tracking = 0;
+
default_file_start ();
emit_safe_across_calls ();
}
@@ -2000,7 +2298,7 @@ next_scratch_gr_reg (void)
}
/* There must be _something_ available. */
- abort ();
+ gcc_unreachable ();
}
/* Helper function for ia64_compute_frame_size, called through
@@ -2012,7 +2310,7 @@ mark_reg_gr_used_mask (rtx reg, void *data ATTRIBUTE_UNUSED)
unsigned int regno = REGNO (reg);
if (regno < 32)
{
- unsigned int i, n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+ unsigned int i, n = hard_regno_nregs[regno][GET_MODE (reg)];
for (i = 0; i < n; ++i)
current_frame_info.gr_used_mask |= 1 << (regno + i);
}
@@ -2084,12 +2382,14 @@ ia64_compute_frame_size (HOST_WIDE_INT size)
break;
i = regno - OUT_REG (0) + 1;
+#ifndef PROFILE_HOOK
/* When -p profiling, we need one output register for the mcount argument.
Likewise for -a profiling for the bb_init_func argument. For -ax
profiling, we need two output registers for the two bb_init_trace_func
arguments. */
if (current_function_profile)
i = MAX (i, 1);
+#endif
current_frame_info.n_output_regs = i;
/* ??? No rotating register support yet. */
@@ -2152,7 +2452,7 @@ ia64_compute_frame_size (HOST_WIDE_INT size)
current_frame_info.reg_save_b0 = find_gr_spill (1);
if (current_frame_info.reg_save_b0 == 0)
{
- spill_size += 8;
+ extra_spill_size += 8;
n_spilled += 1;
}
@@ -2181,7 +2481,7 @@ ia64_compute_frame_size (HOST_WIDE_INT size)
if (regs_ever_live[BR_REG (0)] && ! call_used_regs[BR_REG (0)])
{
SET_HARD_REG_BIT (mask, BR_REG (0));
- spill_size += 8;
+ extra_spill_size += 8;
n_spilled += 1;
}
@@ -2297,39 +2597,49 @@ ia64_initial_elimination_offset (int from, int to)
switch (from)
{
case FRAME_POINTER_REGNUM:
- if (to == HARD_FRAME_POINTER_REGNUM)
+ switch (to)
{
+ case HARD_FRAME_POINTER_REGNUM:
if (current_function_is_leaf)
offset = -current_frame_info.total_size;
else
offset = -(current_frame_info.total_size
- current_function_outgoing_args_size - 16);
- }
- else if (to == STACK_POINTER_REGNUM)
- {
+ break;
+
+ case STACK_POINTER_REGNUM:
if (current_function_is_leaf)
offset = 0;
else
offset = 16 + current_function_outgoing_args_size;
+ break;
+
+ default:
+ gcc_unreachable ();
}
- else
- abort ();
break;
case ARG_POINTER_REGNUM:
/* Arguments start above the 16 byte save area, unless stdarg
in which case we store through the 16 byte save area. */
- if (to == HARD_FRAME_POINTER_REGNUM)
- offset = 16 - current_function_pretend_args_size;
- else if (to == STACK_POINTER_REGNUM)
- offset = (current_frame_info.total_size
- + 16 - current_function_pretend_args_size);
- else
- abort ();
+ switch (to)
+ {
+ case HARD_FRAME_POINTER_REGNUM:
+ offset = 16 - current_function_pretend_args_size;
+ break;
+
+ case STACK_POINTER_REGNUM:
+ offset = (current_frame_info.total_size
+ + 16 - current_function_pretend_args_size);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
break;
default:
- abort ();
+ gcc_unreachable ();
}
return offset;
@@ -2619,8 +2929,9 @@ ia64_expand_prologue (void)
if (optimize)
{
edge e;
+ edge_iterator ei;
- for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
+ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
if ((e->flags & EDGE_FAKE) == 0
&& (e->flags & EDGE_FALLTHRU) != 0)
break;
@@ -2860,35 +3171,7 @@ ia64_expand_prologue (void)
}
}
- 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))
- abort ();
-
- /* Spill all general registers. */
- for (regno = GR_REG (1); regno <= GR_REG (31); ++regno)
- if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
- {
- reg = gen_rtx_REG (DImode, regno);
- do_spill (gen_gr_spill, reg, cfa_off, reg);
- cfa_off -= 8;
- }
-
- /* Handle BR0 specially -- it may be getting stored permanently in
- some GR register. */
+ /* Save the return pointer. */
if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
{
reg = gen_rtx_REG (DImode, BR_REG (0));
@@ -2913,6 +3196,32 @@ ia64_expand_prologue (void)
}
}
+ 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. */
+ gcc_assert (cfa_off == (current_frame_info.spill_cfa_off
+ + current_frame_info.spill_size));
+
+ /* Spill all general registers. */
+ for (regno = GR_REG (1); regno <= GR_REG (31); ++regno)
+ if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
+ {
+ reg = gen_rtx_REG (DImode, regno);
+ do_spill (gen_gr_spill, reg, cfa_off, reg);
+ cfa_off -= 8;
+ }
+
/* Spill the rest of the BR registers. */
for (regno = BR_REG (1); regno <= BR_REG (7); ++regno)
if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
@@ -2929,15 +3238,13 @@ ia64_expand_prologue (void)
for (regno = FR_REG (2); regno <= FR_REG (127); ++regno)
if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
{
- if (cfa_off & 15)
- abort ();
+ gcc_assert (!(cfa_off & 15));
reg = gen_rtx_REG (XFmode, regno);
do_spill (gen_fr_spill_x, reg, cfa_off, reg);
cfa_off -= 16;
}
- if (cfa_off != current_frame_info.spill_cfa_off)
- abort ();
+ gcc_assert (cfa_off == current_frame_info.spill_cfa_off);
finish_spill_pointers ();
}
@@ -3048,10 +3355,25 @@ ia64_expand_epilogue (int sibcall_p)
emit_move_insn (reg, alt_reg);
}
+ /* Restore the return pointer. */
+ if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
+ {
+ if (current_frame_info.reg_save_b0 != 0)
+ alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_b0);
+ else
+ {
+ alt_regno = next_scratch_gr_reg ();
+ alt_reg = gen_rtx_REG (DImode, alt_regno);
+ do_restore (gen_movdi_x, alt_reg, cfa_off);
+ cfa_off -= 8;
+ }
+ reg = gen_rtx_REG (DImode, BR_REG (0));
+ emit_move_insn (reg, alt_reg);
+ }
+
/* 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))
- abort ();
+ gcc_assert (cfa_off == (current_frame_info.spill_cfa_off
+ + current_frame_info.spill_size));
/* The GP may be stored on the stack in the prologue, but it's
never restored in the epilogue. Skip the stack slot. */
@@ -3067,23 +3389,7 @@ ia64_expand_epilogue (int sibcall_p)
cfa_off -= 8;
}
- /* Restore the branch registers. Handle B0 specially, as it may
- have gotten stored in some GR register. */
- if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
- {
- if (current_frame_info.reg_save_b0 != 0)
- alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_b0);
- else
- {
- alt_regno = next_scratch_gr_reg ();
- alt_reg = gen_rtx_REG (DImode, alt_regno);
- do_restore (gen_movdi_x, alt_reg, cfa_off);
- cfa_off -= 8;
- }
- reg = gen_rtx_REG (DImode, BR_REG (0));
- emit_move_insn (reg, alt_reg);
- }
-
+ /* Restore the branch registers. */
for (regno = BR_REG (1); regno <= BR_REG (7); ++regno)
if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
{
@@ -3099,8 +3405,7 @@ ia64_expand_epilogue (int sibcall_p)
for (regno = FR_REG (2); regno <= FR_REG (127); ++regno)
if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
{
- if (cfa_off & 15)
- abort ();
+ gcc_assert (!(cfa_off & 15));
reg = gen_rtx_REG (XFmode, regno);
do_restore (gen_fr_restore_x, reg, cfa_off);
cfa_off -= 16;
@@ -3113,8 +3418,7 @@ ia64_expand_epilogue (int sibcall_p)
emit_move_insn (reg, ar_unat_save_reg);
}
- if (cfa_off != current_frame_info.spill_cfa_off)
- abort ();
+ gcc_assert (cfa_off == current_frame_info.spill_cfa_off);
finish_spill_pointers ();
@@ -3488,6 +3792,11 @@ ia64_initialize_trampoline (rtx addr, rtx fnaddr, rtx static_chain)
}
}
+ /* Make sure addresses are Pmode even if we are in ILP32 mode. */
+ addr = convert_memory_address (Pmode, addr);
+ fnaddr = convert_memory_address (Pmode, fnaddr);
+ static_chain = convert_memory_address (Pmode, static_chain);
+
/* Load up our iterator. */
addr_reg = gen_reg_rtx (Pmode);
emit_move_insn (addr_reg, addr);
@@ -3515,17 +3824,19 @@ ia64_initialize_trampoline (rtx addr, rtx fnaddr, rtx static_chain)
We generate the actual spill instructions during prologue generation. */
-void
-ia64_setup_incoming_varargs (CUMULATIVE_ARGS cum, int int_mode, tree type,
- int * pretend_size,
+static void
+ia64_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, int * pretend_size,
int second_time ATTRIBUTE_UNUSED)
{
+ CUMULATIVE_ARGS next_cum = *cum;
+
/* Skip the current argument. */
- ia64_function_arg_advance (&cum, int_mode, type, 1);
+ ia64_function_arg_advance (&next_cum, mode, type, 1);
- if (cum.words < MAX_ARGUMENT_SLOTS)
+ if (next_cum.words < MAX_ARGUMENT_SLOTS)
{
- int n = MAX_ARGUMENT_SLOTS - cum.words;
+ int n = MAX_ARGUMENT_SLOTS - next_cum.words;
*pretend_size = n * UNITS_PER_WORD;
cfun->machine->n_varargs = n;
}
@@ -3537,10 +3848,14 @@ ia64_setup_incoming_varargs (CUMULATIVE_ARGS cum, int int_mode, tree type,
An aggregate is a homogeneous floating point aggregate is if all
fields/elements in it have the same floating point type (e.g,
- SFmode). 128-bit quad-precision floats are excluded. */
+ SFmode). 128-bit quad-precision floats are excluded.
+
+ Variable sized aggregates should never arrive here, since we should
+ have already decided to pass them by reference. Top-level zero-sized
+ aggregates are excluded because our parallels crash the middle-end. */
static enum machine_mode
-hfa_element_mode (tree type, int nested)
+hfa_element_mode (tree type, bool nested)
{
enum machine_mode element_mode = VOIDmode;
enum machine_mode mode;
@@ -3548,13 +3863,15 @@ hfa_element_mode (tree type, int nested)
int know_element_mode = 0;
tree t;
+ if (!nested && (!TYPE_SIZE (type) || integer_zerop (TYPE_SIZE (type))))
+ return VOIDmode;
+
switch (code)
{
case VOID_TYPE: case INTEGER_TYPE: case ENUMERAL_TYPE:
- case BOOLEAN_TYPE: case CHAR_TYPE: case POINTER_TYPE:
+ case BOOLEAN_TYPE: case POINTER_TYPE:
case OFFSET_TYPE: case REFERENCE_TYPE: case METHOD_TYPE:
- case FILE_TYPE: case SET_TYPE: case LANG_TYPE:
- case FUNCTION_TYPE:
+ case LANG_TYPE: case FUNCTION_TYPE:
return VOIDmode;
/* Fortran complex types are supposed to be HFAs, so we need to handle
@@ -3756,13 +4073,7 @@ ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
else if (gr_size > UNITS_PER_WORD)
int_regs += gr_size / UNITS_PER_WORD;
}
-
- /* If we ended up using just one location, just return that one loc, but
- change the mode back to the argument mode. */
- if (i == 1)
- return gen_rtx_REG (mode, REGNO (XEXP (loc[0], 0)));
- else
- return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
+ return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
}
/* Integral and aggregates go in general registers. If we have run out of
@@ -3830,13 +4141,13 @@ ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
}
}
-/* Return number of words, at the beginning of the argument, that must be
+/* Return number of bytes, at the beginning of the argument, that must be
put in registers. 0 is the argument is entirely in registers or entirely
in memory. */
-int
-ia64_function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- tree type, int named ATTRIBUTE_UNUSED)
+static int
+ia64_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, bool named ATTRIBUTE_UNUSED)
{
int words = ia64_function_arg_words (type, mode);
int offset = ia64_function_arg_offset (cum, type, words);
@@ -3853,7 +4164,7 @@ ia64_function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
if (words + cum->words + offset <= MAX_ARGUMENT_SLOTS)
return 0;
- return MAX_ARGUMENT_SLOTS - cum->words - offset;
+ return (MAX_ARGUMENT_SLOTS - cum->words - offset) * UNITS_PER_WORD;
}
/* Update CUM to point after this argument. This is patterned after
@@ -3913,10 +4224,11 @@ ia64_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
cum->fp_regs = fp_regs;
}
- /* Integral and aggregates go in general registers. If we have run out of
- FR registers, then FP values must also go in general registers. This can
- happen when we have a SFmode HFA. */
- else if (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS)
+ /* Integral and aggregates go in general registers. So do TFmode FP values.
+ If we have run out of FR registers, then other FP values must also go in
+ general registers. This can happen when we have a SFmode HFA. */
+ else if (mode == TFmode || mode == TCmode
+ || (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
cum->int_regs = cum->words;
/* If there is a prototype, then FP values go in a FR register when
@@ -3939,15 +4251,29 @@ ia64_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
}
}
-/* Variable sized types are passed by reference. */
-/* ??? At present this is a GCC extension to the IA-64 ABI. */
+/* Arguments with alignment larger than 8 bytes start at the next even
+ boundary. On ILP32 HPUX, TFmode arguments start on next even boundary
+ even though their normal alignment is 8 bytes. See ia64_function_arg. */
int
-ia64_function_arg_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- tree type, int named ATTRIBUTE_UNUSED)
+ia64_function_arg_boundary (enum machine_mode mode, tree type)
{
- return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
+
+ if (mode == TFmode && TARGET_HPUX && TARGET_ILP32)
+ return PARM_BOUNDARY * 2;
+
+ if (type)
+ {
+ if (TYPE_ALIGN (type) > PARM_BOUNDARY)
+ return PARM_BOUNDARY * 2;
+ else
+ return PARM_BOUNDARY;
+ }
+
+ if (GET_MODE_BITSIZE (mode) > PARM_BOUNDARY)
+ return PARM_BOUNDARY * 2;
+ else
+ return PARM_BOUNDARY;
}
/* True if it is OK to do sibling call optimization for the specified
@@ -3970,20 +4296,15 @@ ia64_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
/* Implement va_arg. */
-rtx
-ia64_va_arg (tree valist, tree type)
+static tree
+ia64_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
{
- tree t;
-
/* Variable sized types are passed by reference. */
- if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+ if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
{
- rtx addr = force_reg (ptr_mode,
- std_expand_builtin_va_arg (valist, build_pointer_type (type)));
-#ifdef POINTERS_EXTEND_UNSIGNED
- addr = convert_memory_address (Pmode, addr);
-#endif
- return gen_rtx_MEM (ptr_mode, addr);
+ tree ptrtype = build_pointer_type (type);
+ tree addr = std_gimplify_va_arg_expr (valist, ptrtype, pre_p, post_p);
+ return build_va_arg_indirect_ref (addr);
}
/* Aggregate arguments with alignment larger than 8 bytes start at
@@ -3993,23 +4314,22 @@ ia64_va_arg (tree valist, tree type)
if ((TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == INTEGER_TYPE)
? int_size_in_bytes (type) > 8 : TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
{
- t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
- build_int_2 (2 * UNITS_PER_WORD - 1, 0));
- t = build (BIT_AND_EXPR, TREE_TYPE (t), t,
- build_int_2 (-2 * UNITS_PER_WORD, -1));
- t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ tree t = build2 (PLUS_EXPR, TREE_TYPE (valist), valist,
+ build_int_cst (NULL_TREE, 2 * UNITS_PER_WORD - 1));
+ t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
+ build_int_cst (NULL_TREE, -2 * UNITS_PER_WORD));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
+ gimplify_and_add (t, pre_p);
}
- return std_expand_builtin_va_arg (valist, type);
+ return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
}
/* Return 1 if function return value returned in memory. Return 0 if it is
in a register. */
-int
-ia64_return_in_memory (tree valtype)
+static bool
+ia64_return_in_memory (tree valtype, tree fntype ATTRIBUTE_UNUSED)
{
enum machine_mode mode;
enum machine_mode hfa_mode;
@@ -4021,7 +4341,7 @@ ia64_return_in_memory (tree valtype)
{
byte_size = int_size_in_bytes (valtype);
if (byte_size < 0)
- return 1;
+ return true;
}
/* Hfa's with up to 8 elements are returned in the FP argument registers. */
@@ -4032,14 +4352,14 @@ ia64_return_in_memory (tree valtype)
int hfa_size = GET_MODE_SIZE (hfa_mode);
if (byte_size / hfa_size > MAX_ARGUMENT_SLOTS)
- return 1;
+ return true;
else
- return 0;
+ return false;
}
else if (byte_size > UNITS_PER_WORD * MAX_INT_RETURN_SLOTS)
- return 1;
+ return true;
else
- return 0;
+ return false;
}
/* Return rtx for register that holds the function return value. */
@@ -4072,18 +4392,30 @@ ia64_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
GEN_INT (offset));
offset += hfa_size;
}
-
- if (i == 1)
- return XEXP (loc[0], 0);
- else
- return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
+ return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
}
else if (FLOAT_TYPE_P (valtype) && mode != TFmode && mode != TCmode)
return gen_rtx_REG (mode, FR_ARG_FIRST);
else
{
+ bool need_parallel = false;
+
+ /* In big-endian mode, we need to manage the layout of aggregates
+ in the registers so that we get the bits properly aligned in
+ the highpart of the registers. */
if (BYTES_BIG_ENDIAN
&& (mode == BLKmode || (valtype && AGGREGATE_TYPE_P (valtype))))
+ need_parallel = true;
+
+ /* Something like struct S { long double x; char a[0] } is not an
+ HFA structure, and therefore doesn't go in fp registers. But
+ the middle-end will give it XFmode anyway, and XFmode values
+ don't normally fit in integer registers. So we need to smuggle
+ the value inside a parallel. */
+ else if (mode == XFmode || mode == XCmode || mode == RFmode)
+ need_parallel = true;
+
+ if (need_parallel)
{
rtx loc[8];
int offset;
@@ -4092,6 +4424,10 @@ ia64_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
offset = 0;
bytesize = int_size_in_bytes (valtype);
+ /* An empty PARALLEL is invalid here, but the return value
+ doesn't matter for empty structs. */
+ if (bytesize == 0)
+ return gen_rtx_REG (mode, GR_RET_FIRST);
for (i = 0; offset < bytesize; i++)
{
loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
@@ -4102,20 +4438,22 @@ ia64_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
}
return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
}
- else
- return gen_rtx_REG (mode, GR_RET_FIRST);
+
+ return gen_rtx_REG (mode, GR_RET_FIRST);
}
}
-/* This is called from dwarf2out.c via ASM_OUTPUT_DWARF_DTPREL.
+/* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
We need to emit DTP-relative relocations. */
-void
+static void
ia64_output_dwarf_dtprel (FILE *file, int size, rtx x)
{
- if (size != 8)
- abort ();
- fputs ("\tdata8.ua\t@dtprel(", file);
+ gcc_assert (size == 4 || size == 8);
+ if (size == 4)
+ fputs ("\tdata4.ua\t@dtprel(", file);
+ else
+ fputs ("\tdata8.ua\t@dtprel(", file);
output_addr_const (file, x);
fputs (")", file);
}
@@ -4149,8 +4487,11 @@ ia64_print_operand_address (FILE * stream ATTRIBUTE_UNUSED,
for Intel assembler.
U Print an 8-bit sign extended number (K) as a 64-bit unsigned number
for Intel assembler.
+ X A pair of floating point registers.
r Print register name, or constant 0 as r0. HP compatibility for
- Linux kernel. */
+ Linux kernel.
+ v Print vector constant value as an 8-byte integer value. */
+
void
ia64_print_operand (FILE * file, rtx x, int code)
{
@@ -4201,10 +4542,11 @@ ia64_print_operand (FILE * file, rtx x, int code)
str = reg_names [FR_REG (0)];
else if (x == CONST1_RTX (GET_MODE (x)))
str = reg_names [FR_REG (1)];
- else if (GET_CODE (x) == REG)
- str = reg_names [REGNO (x)];
else
- abort ();
+ {
+ gcc_assert (GET_CODE (x) == REG);
+ str = reg_names [REGNO (x)];
+ }
fputs (str, file);
return;
@@ -4242,13 +4584,12 @@ ia64_print_operand (FILE * file, rtx x, int code)
x = XEXP (XEXP (XEXP (x, 0), 1), 1);
if (GET_CODE (x) == CONST_INT)
value = INTVAL (x);
- else if (GET_CODE (x) == REG)
+ else
{
+ gcc_assert (GET_CODE (x) == REG);
fprintf (file, ", %s", reg_names[REGNO (x)]);
return;
}
- else
- abort ();
break;
case POST_INC:
@@ -4295,6 +4636,13 @@ ia64_print_operand (FILE * file, rtx x, int code)
}
break;
+ case 'X':
+ {
+ unsigned int regno = REGNO (x);
+ fprintf (file, "%s, %s", reg_names [regno], reg_names [regno + 1]);
+ }
+ return;
+
case 'r':
/* If this operand is the constant zero, write it as register zero.
Any register, zero, or CONST_INT value is OK here. */
@@ -4308,6 +4656,11 @@ ia64_print_operand (FILE * file, rtx x, int code)
output_operand_lossage ("invalid %%r value");
return;
+ case 'v':
+ gcc_assert (GET_CODE (x) == CONST_VECTOR);
+ x = simplify_subreg (DImode, x, GET_MODE (x), 0);
+ break;
+
case '+':
{
const char *which;
@@ -4320,11 +4673,13 @@ ia64_print_operand (FILE * file, rtx x, int code)
int pred_val = INTVAL (XEXP (x, 0));
/* Guess top and bottom 10% statically predicted. */
- if (pred_val < REG_BR_PROB_BASE / 50)
+ if (pred_val < REG_BR_PROB_BASE / 50
+ && br_prob_note_reliable_p (x))
which = ".spnt";
else if (pred_val < REG_BR_PROB_BASE / 2)
which = ".dpnt";
- else if (pred_val < REG_BR_PROB_BASE / 100 * 98)
+ else if (pred_val < REG_BR_PROB_BASE / 100 * 98
+ || !br_prob_note_reliable_p (x))
which = ".dptk";
else
which = ".sptk";
@@ -4370,7 +4725,7 @@ ia64_print_operand (FILE * file, rtx x, int code)
case MEM:
{
rtx addr = XEXP (x, 0);
- if (GET_RTX_CLASS (GET_CODE (addr)) == 'a')
+ if (GET_RTX_CLASS (GET_CODE (addr)) == RTX_AUTOINC)
addr = XEXP (addr, 0);
fprintf (file, "[%s]", reg_names [REGNO (addr)]);
break;
@@ -4485,7 +4840,7 @@ ia64_register_move_cost (enum machine_mode mode, enum reg_class from,
so that we get secondary memory reloads. Between FR_REGS,
we have to make this at least as expensive as MEMORY_MOVE_COST
to avoid spectacularly poor register class preferencing. */
- if (mode == XFmode)
+ if (mode == XFmode || mode == RFmode)
{
if (to != GR_REGS || from != GR_REGS)
return MEMORY_MOVE_COST (mode, to, 0);
@@ -4519,18 +4874,53 @@ ia64_register_move_cost (enum machine_mode mode, enum reg_class from,
case GR_REGS:
case FR_REGS:
+ case FP_REGS:
case GR_AND_FR_REGS:
case GR_AND_BR_REGS:
case ALL_REGS:
break;
default:
- abort ();
+ gcc_unreachable ();
}
return 2;
}
+/* Implement PREFERRED_RELOAD_CLASS. Place additional restrictions on CLASS
+ to use when copying X into that class. */
+
+enum reg_class
+ia64_preferred_reload_class (rtx x, enum reg_class class)
+{
+ switch (class)
+ {
+ case FR_REGS:
+ case FP_REGS:
+ /* Don't allow volatile mem reloads into floating point registers.
+ This is defined to force reload to choose the r/m case instead
+ of the f/f case when reloading (set (reg fX) (mem/v)). */
+ if (MEM_P (x) && MEM_VOLATILE_P (x))
+ return NO_REGS;
+
+ /* Force all unrecognized constants into the constant pool. */
+ if (CONSTANT_P (x))
+ return NO_REGS;
+ break;
+
+ case AR_M_REGS:
+ case AR_I_REGS:
+ if (!OBJECT_P (x))
+ return NO_REGS;
+ break;
+
+ default:
+ break;
+ }
+
+ return class;
+}
+
/* This function returns the register class required for a secondary
register when copying between one of the registers in CLASS, and X,
using MODE. A return value of NO_REGS means that no secondary register
@@ -4572,6 +4962,7 @@ ia64_secondary_reload_class (enum reg_class class,
break;
case FR_REGS:
+ case FP_REGS:
/* Need to go through general registers to get to other class regs. */
if (regno >= 0 && ! (FR_REGNO_P (regno) || GENERAL_REGNO_P (regno)))
return GR_REGS;
@@ -4690,7 +5081,7 @@ fix_range (const char *const_str)
dash = strchr (str, '-');
if (!dash)
{
- warning ("value of -mfixed-range must have form REG1-REG2");
+ warning (0, "value of -mfixed-range must have form REG1-REG2");
return;
}
*dash = '\0';
@@ -4702,14 +5093,14 @@ fix_range (const char *const_str)
first = decode_reg_name (str);
if (first < 0)
{
- warning ("unknown register name: %s", str);
+ warning (0, "unknown register name: %s", str);
return;
}
last = decode_reg_name (dash + 1);
if (last < 0)
{
- warning ("unknown register name: %s", dash + 1);
+ warning (0, "unknown register name: %s", dash + 1);
return;
}
@@ -4717,7 +5108,7 @@ fix_range (const char *const_str)
if (first > last)
{
- warning ("%s-%s is an empty range", str, dash + 1);
+ warning (0, "%s-%s is an empty range", str, dash + 1);
return;
}
@@ -4732,87 +5123,70 @@ fix_range (const char *const_str)
}
}
-static struct machine_function *
-ia64_init_machine_status (void)
-{
- return ggc_alloc_cleared (sizeof (struct machine_function));
-}
-
-/* Handle TARGET_OPTIONS switches. */
+/* Implement TARGET_HANDLE_OPTION. */
-void
-ia64_override_options (void)
+static bool
+ia64_handle_option (size_t code, const char *arg, int value)
{
- static struct pta
- {
- const char *const name; /* processor name or nickname. */
- const enum processor_type processor;
- }
- const processor_alias_table[] =
+ switch (code)
{
- {"itanium", PROCESSOR_ITANIUM},
- {"itanium1", PROCESSOR_ITANIUM},
- {"merced", PROCESSOR_ITANIUM},
- {"itanium2", PROCESSOR_ITANIUM2},
- {"mckinley", PROCESSOR_ITANIUM2},
- };
-
- int const pta_size = ARRAY_SIZE (processor_alias_table);
- int i;
+ case OPT_mfixed_range_:
+ fix_range (arg);
+ return true;
- if (TARGET_AUTO_PIC)
- target_flags |= MASK_CONST_GP;
+ case OPT_mtls_size_:
+ if (value != 14 && value != 22 && value != 64)
+ error ("bad value %<%s%> for -mtls-size= switch", arg);
+ return true;
- 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;
- }
+ case OPT_mtune_:
+ {
+ static struct pta
+ {
+ const char *name; /* processor name or nickname. */
+ enum processor_type processor;
+ }
+ const processor_alias_table[] =
+ {
+ {"itanium", PROCESSOR_ITANIUM},
+ {"itanium1", PROCESSOR_ITANIUM},
+ {"merced", PROCESSOR_ITANIUM},
+ {"itanium2", PROCESSOR_ITANIUM2},
+ {"mckinley", PROCESSOR_ITANIUM2},
+ };
+ int const pta_size = ARRAY_SIZE (processor_alias_table);
+ int i;
- if (TARGET_INLINE_INT_DIV_LAT && TARGET_INLINE_INT_DIV_THR)
- {
- warning ("cannot optimize integer division for both latency and throughput");
- target_flags &= ~MASK_INLINE_INT_DIV_THR;
- }
+ for (i = 0; i < pta_size; i++)
+ if (!strcmp (arg, processor_alias_table[i].name))
+ {
+ ia64_tune = processor_alias_table[i].processor;
+ break;
+ }
+ if (i == pta_size)
+ error ("bad value %<%s%> for -mtune= switch", arg);
+ return true;
+ }
- if (TARGET_INLINE_SQRT_LAT && TARGET_INLINE_SQRT_THR)
- {
- warning ("cannot optimize square root for both latency and throughput");
- target_flags &= ~MASK_INLINE_SQRT_THR;
+ default:
+ return true;
}
+}
- if (TARGET_INLINE_SQRT_LAT)
- {
- warning ("not yet implemented: latency-optimized inline square root");
- target_flags &= ~MASK_INLINE_SQRT_LAT;
- }
+/* Implement OVERRIDE_OPTIONS. */
- if (ia64_fixed_range_string)
- fix_range (ia64_fixed_range_string);
+void
+ia64_override_options (void)
+{
+ if (TARGET_AUTO_PIC)
+ target_flags |= MASK_CONST_GP;
- if (ia64_tls_size_string)
+ if (TARGET_INLINE_SQRT == INL_MIN_LAT)
{
- 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;
+ warning (0, "not yet implemented: latency-optimized inline square root");
+ TARGET_INLINE_SQRT = INL_MAX_THR;
}
- if (!ia64_tune_string)
- ia64_tune_string = "itanium2";
-
- for (i = 0; i < pta_size; i++)
- if (! strcmp (ia64_tune_string, processor_alias_table[i].name))
- {
- ia64_tune = processor_alias_table[i].processor;
- break;
- }
-
- if (i == pta_size)
- error ("bad value (%s) for -tune= switch", ia64_tune_string);
-
ia64_flag_schedule_insns2 = flag_schedule_insns_after_reload;
flag_schedule_insns_after_reload = 0;
@@ -4820,6 +5194,12 @@ ia64_override_options (void)
init_machine_status = ia64_init_machine_status;
}
+
+static struct machine_function *
+ia64_init_machine_status (void)
+{
+ return ggc_alloc_cleared (sizeof (struct machine_function));
+}
static enum attr_itanium_class ia64_safe_itanium_class (rtx);
static enum attr_type ia64_safe_type (rtx);
@@ -4851,7 +5231,6 @@ ia64_safe_type (rtx insn)
never explicitly used in gcc generated code, it seems wasteful to
do so (plus it would make the call and return patterns needlessly
complex). */
-#define REG_GP (GR_REG (1))
#define REG_RP (BR_REG (0))
#define REG_AR_CFM (FIRST_PSEUDO_REGISTER + 1)
/* This is used for volatile asms which may require a stop bit immediately
@@ -4896,8 +5275,8 @@ struct reg_write_state rws_sum[NUM_REGS];
struct reg_write_state rws_insn[NUM_REGS];
/* Indicates whether this is the first instruction after a stop bit,
- in which case we don't need another stop bit. Without this, we hit
- the abort in ia64_variable_issue when scheduling an alloc. */
+ in which case we don't need another stop bit. Without this,
+ ia64_variable_issue will die when scheduling an alloc. */
static int first_instruction;
/* Misc flags needed to compute RAW/WAW dependencies while we are traversing
@@ -4915,12 +5294,12 @@ struct reg_flags
static void rws_update (struct reg_write_state *, int, struct reg_flags, int);
static int rws_access_regno (int, struct reg_flags, int);
static int rws_access_reg (rtx, struct reg_flags, int);
-static void update_set_flags (rtx, struct reg_flags *, int *, rtx *);
-static int set_src_needs_barrier (rtx, struct reg_flags, int, rtx);
+static void update_set_flags (rtx, struct reg_flags *);
+static int set_src_needs_barrier (rtx, struct reg_flags, int);
static int rtx_needs_barrier (rtx, struct reg_flags, int);
static void init_insn_group_barriers (void);
-static int group_barrier_needed_p (rtx);
-static int safe_group_barrier_needed_p (rtx);
+static int group_barrier_needed (rtx);
+static int safe_group_barrier_needed (rtx);
/* Update *RWS for REGNO, which is being written by the current instruction,
with predicate PRED, and associated register flags in FLAGS. */
@@ -4948,8 +5327,7 @@ rws_access_regno (int regno, struct reg_flags flags, int pred)
{
int need_barrier = 0;
- if (regno >= NUM_REGS)
- abort ();
+ gcc_assert (regno < NUM_REGS);
if (! PR_REGNO_P (regno))
flags.is_and = flags.is_or = 0;
@@ -4959,8 +5337,7 @@ rws_access_regno (int regno, struct reg_flags flags, int pred)
int write_count;
/* One insn writes same reg multiple times? */
- if (rws_insn[regno].write_count > 0)
- abort ();
+ gcc_assert (!rws_insn[regno].write_count);
/* Update info for current instruction. */
rws_update (rws_insn, regno, flags, pred);
@@ -5001,7 +5378,7 @@ rws_access_regno (int regno, struct reg_flags flags, int pred)
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
else
@@ -5054,7 +5431,7 @@ rws_access_regno (int regno, struct reg_flags flags, int pred)
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
@@ -5082,62 +5459,31 @@ rws_access_reg (rtx reg, struct reg_flags flags, int pred)
the condition, stored in *PFLAGS, *PPRED and *PCOND. */
static void
-update_set_flags (rtx x, struct reg_flags *pflags, int *ppred, rtx *pcond)
+update_set_flags (rtx x, struct reg_flags *pflags)
{
rtx src = SET_SRC (x);
- *pcond = 0;
-
switch (GET_CODE (src))
{
case CALL:
return;
case IF_THEN_ELSE:
- if (SET_DEST (x) == pc_rtx)
- /* X is a conditional branch. */
- return;
- else
- {
- int is_complemented = 0;
-
- /* X is a conditional move. */
- rtx cond = XEXP (src, 0);
- if (GET_CODE (cond) == EQ)
- is_complemented = 1;
- cond = XEXP (cond, 0);
- if (GET_CODE (cond) != REG
- && REGNO_REG_CLASS (REGNO (cond)) != PR_REGS)
- abort ();
- *pcond = cond;
- if (XEXP (src, 1) == SET_DEST (x)
- || XEXP (src, 2) == SET_DEST (x))
- {
- /* X is a conditional move that conditionally writes the
- destination. */
-
- /* We need another complement in this case. */
- if (XEXP (src, 1) == SET_DEST (x))
- is_complemented = ! is_complemented;
-
- *ppred = REGNO (cond);
- if (is_complemented)
- ++*ppred;
- }
-
- /* ??? If this is a conditional write to the dest, then this
- instruction does not actually read one source. This probably
- doesn't matter, because that source is also the dest. */
- /* ??? Multiple writes to predicate registers are allowed
- if they are all AND type compares, or if they are all OR
- type compares. We do not generate such instructions
- currently. */
- }
- /* ... fall through ... */
+ /* There are four cases here:
+ (1) The destination is (pc), in which case this is a branch,
+ nothing here applies.
+ (2) The destination is ar.lc, in which case this is a
+ doloop_end_internal,
+ (3) The destination is an fp register, in which case this is
+ an fselect instruction.
+ (4) The condition has (unspec [(reg)] UNSPEC_LDC), in which case
+ this is a check load.
+ In all cases, nothing we do in this function applies. */
+ return;
default:
- if (GET_RTX_CLASS (GET_CODE (src)) == '<'
- && GET_MODE_CLASS (GET_MODE (XEXP (src, 0))) == MODE_FLOAT)
+ if (COMPARISON_P (src)
+ && SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (src, 0))))
/* Set pflags->is_fp to 1 so that we know we're dealing
with a floating point comparison when processing the
destination of the SET. */
@@ -5161,7 +5507,7 @@ update_set_flags (rtx x, struct reg_flags *pflags, int *ppred, rtx *pcond)
for this insn. */
static int
-set_src_needs_barrier (rtx x, struct reg_flags flags, int pred, rtx cond)
+set_src_needs_barrier (rtx x, struct reg_flags flags, int pred)
{
int need_barrier = 0;
rtx dst;
@@ -5176,22 +5522,29 @@ set_src_needs_barrier (rtx x, struct reg_flags flags, int pred, rtx cond)
/* X is a conditional branch. */
/* ??? This seems redundant, as the caller sets this bit for
all JUMP_INSNs. */
- flags.is_branch = 1;
+ if (!ia64_spec_check_src_p (src))
+ flags.is_branch = 1;
return rtx_needs_barrier (src, flags, pred);
}
- need_barrier = rtx_needs_barrier (src, flags, pred);
+ if (ia64_spec_check_src_p (src))
+ /* Avoid checking one register twice (in condition
+ and in 'then' section) for ldc pattern. */
+ {
+ gcc_assert (REG_P (XEXP (src, 2)));
+ need_barrier = rtx_needs_barrier (XEXP (src, 2), flags, pred);
+
+ /* We process MEM below. */
+ src = XEXP (src, 1);
+ }
- /* This instruction unconditionally uses a predicate register. */
- if (cond)
- need_barrier |= rws_access_reg (cond, flags, 0);
+ need_barrier |= rtx_needs_barrier (src, flags, pred);
dst = SET_DEST (x);
if (GET_CODE (dst) == ZERO_EXTRACT)
{
need_barrier |= rtx_needs_barrier (XEXP (dst, 1), flags, pred);
need_barrier |= rtx_needs_barrier (XEXP (dst, 2), flags, pred);
- dst = XEXP (dst, 0);
}
return need_barrier;
}
@@ -5208,7 +5561,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
int need_barrier = 0;
const char *format_ptr;
struct reg_flags new_flags;
- rtx cond = 0;
+ rtx cond;
if (! x)
return 0;
@@ -5218,8 +5571,8 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
switch (GET_CODE (x))
{
case SET:
- update_set_flags (x, &new_flags, &pred, &cond);
- need_barrier = set_src_needs_barrier (x, new_flags, pred, cond);
+ update_set_flags (x, &new_flags);
+ need_barrier = set_src_needs_barrier (x, new_flags, pred);
if (GET_CODE (SET_SRC (x)) != CALL)
{
new_flags.is_write = 1;
@@ -5232,7 +5585,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
need_barrier |= rws_access_regno (AR_EC_REGNUM, new_flags, pred);
/* Avoid multiple register writes, in case this is a pattern with
- multiple CALL rtx. This avoids an abort in rws_access_reg. */
+ multiple CALL rtx. This avoids a failure in rws_access_reg. */
if (! flags.is_sibcall && ! rws_insn[REG_AR_CFM].write_count)
{
new_flags.is_write = 1;
@@ -5246,16 +5599,14 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
/* X is a predicated instruction. */
cond = COND_EXEC_TEST (x);
- if (pred)
- abort ();
+ gcc_assert (!pred);
need_barrier = rtx_needs_barrier (cond, flags, 0);
if (GET_CODE (cond) == EQ)
is_complemented = 1;
cond = XEXP (cond, 0);
- if (GET_CODE (cond) != REG
- && REGNO_REG_CLASS (REGNO (cond)) != PR_REGS)
- abort ();
+ gcc_assert (GET_CODE (cond) == REG
+ && REGNO_REG_CLASS (REGNO (cond)) == PR_REGS);
pred = REGNO (cond);
if (is_complemented)
++pred;
@@ -5276,7 +5627,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
|| (MEM_VOLATILE_P (x) && TARGET_VOL_ASM_STOP))
{
/* Avoid writing the register multiple times if we have multiple
- asm outputs. This avoids an abort in rws_access_reg. */
+ asm outputs. This avoids a failure in rws_access_reg. */
if (! rws_insn[REG_VOLATILE].write_count)
{
new_flags.is_write = 1;
@@ -5286,7 +5637,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
}
/* For all ASM_OPERANDS, we must traverse the vector of input operands.
- We can not just fall through here since then we would be confused
+ We cannot just fall through here since then we would be confused
by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate
traditional asms unlike their normal usage. */
@@ -5299,17 +5650,26 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
for (i = XVECLEN (x, 0) - 1; i >= 0; --i)
{
rtx pat = XVECEXP (x, 0, i);
- if (GET_CODE (pat) == SET)
+ switch (GET_CODE (pat))
{
- update_set_flags (pat, &new_flags, &pred, &cond);
- need_barrier |= set_src_needs_barrier (pat, new_flags, pred, cond);
+ case SET:
+ update_set_flags (pat, &new_flags);
+ need_barrier |= set_src_needs_barrier (pat, new_flags, pred);
+ break;
+
+ case USE:
+ case CALL:
+ case ASM_OPERANDS:
+ need_barrier |= rtx_needs_barrier (pat, flags, pred);
+ break;
+
+ case CLOBBER:
+ case RETURN:
+ break;
+
+ default:
+ gcc_unreachable ();
}
- else if (GET_CODE (pat) == USE
- || GET_CODE (pat) == CALL
- || GET_CODE (pat) == ASM_OPERANDS)
- need_barrier |= rtx_needs_barrier (pat, flags, pred);
- else if (GET_CODE (pat) != CLOBBER && GET_CODE (pat) != RETURN)
- abort ();
}
for (i = XVECLEN (x, 0) - 1; i >= 0; --i)
{
@@ -5329,8 +5689,8 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
break;
case SUBREG:
- x = SUBREG_REG (x);
- /* FALLTHRU */
+ need_barrier |= rtx_needs_barrier (SUBREG_REG (x), flags, pred);
+ break;
case REG:
if (REGNO (x) == AR_UNAT_REGNUM)
{
@@ -5347,14 +5707,13 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
need_barrier = rtx_needs_barrier (XEXP (x, 0), new_flags, pred);
break;
- case CONST_INT: case CONST_DOUBLE:
+ case CONST_INT: case CONST_DOUBLE: case CONST_VECTOR:
case SYMBOL_REF: case LABEL_REF: case CONST:
break;
/* Operators with side-effects. */
case POST_INC: case POST_DEC:
- if (GET_CODE (XEXP (x, 0)) != REG)
- abort ();
+ gcc_assert (GET_CODE (XEXP (x, 0)) == REG);
new_flags.is_write = 0;
need_barrier = rws_access_reg (XEXP (x, 0), new_flags, pred);
@@ -5363,8 +5722,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
break;
case POST_MODIFY:
- if (GET_CODE (XEXP (x, 0)) != REG)
- abort ();
+ gcc_assert (GET_CODE (XEXP (x, 0)) == REG);
new_flags.is_write = 0;
need_barrier = rws_access_reg (XEXP (x, 0), new_flags, pred);
@@ -5391,6 +5749,14 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
need_barrier = rtx_needs_barrier (XEXP (x, 0), flags, pred);
break;
+ case VEC_SELECT:
+ /* VEC_SELECT's second argument is a PARALLEL with integers that
+ describe the elements selected. On ia64, those integers are
+ always constants. Avoid walking the PARALLEL so that we don't
+ get confused with "normal" parallels and then die. */
+ need_barrier = rtx_needs_barrier (XEXP (x, 0), flags, pred);
+ break;
+
case UNSPEC:
switch (XINT (x, 1))
{
@@ -5415,7 +5781,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
HOST_WIDE_INT bit = (offset >> 3) & 63;
need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
- new_flags.is_write = (XINT (x, 1) == 1);
+ new_flags.is_write = (XINT (x, 1) == UNSPEC_GR_SPILL);
need_barrier |= rws_access_regno (AR_UNAT_BIT_0 + bit,
new_flags, pred);
break;
@@ -5427,10 +5793,17 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
case UNSPEC_SETF_EXP:
case UNSPEC_ADDP4:
case UNSPEC_FR_SQRT_RECIP_APPROX:
+ case UNSPEC_LDA:
+ case UNSPEC_LDS:
+ case UNSPEC_LDSA:
+ case UNSPEC_CHKACLR:
+ case UNSPEC_CHKS:
need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
break;
case UNSPEC_FR_RECIP_APPROX:
+ case UNSPEC_SHRP:
+ case UNSPEC_COPYSIGN:
need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
need_barrier |= rtx_needs_barrier (XVECEXP (x, 0, 1), flags, pred);
break;
@@ -5441,7 +5814,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
@@ -5474,7 +5847,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
return 0;
default:
- abort ();
+ gcc_unreachable ();
}
break;
@@ -5513,14 +5886,14 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
}
return need_barrier;
}
-/* Clear out the state for group_barrier_needed_p at the start of a
+/* Clear out the state for group_barrier_needed at the start of a
sequence of insns. */
static void
@@ -5530,12 +5903,12 @@ init_insn_group_barriers (void)
first_instruction = 1;
}
-/* Given the current state, recorded by previous calls to this function,
- determine whether a group barrier (a stop bit) is necessary before INSN.
- Return nonzero if so. */
+/* Given the current state, determine whether a group barrier (a stop bit) is
+ necessary before INSN. Return nonzero if so. This modifies the state to
+ include the effects of INSN as a side-effect. */
static int
-group_barrier_needed_p (rtx insn)
+group_barrier_needed (rtx insn)
{
rtx pat;
int need_barrier = 0;
@@ -5572,7 +5945,8 @@ group_barrier_needed_p (rtx insn)
break;
case JUMP_INSN:
- flags.is_branch = 1;
+ if (!ia64_spec_check_p (insn))
+ flags.is_branch = 1;
/* Don't bundle a jump following a call. */
if ((pat = prev_active_insn (insn))
@@ -5628,7 +6002,7 @@ group_barrier_needed_p (rtx insn)
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (first_instruction && INSN_P (insn)
@@ -5643,10 +6017,10 @@ group_barrier_needed_p (rtx insn)
return need_barrier;
}
-/* Like group_barrier_needed_p, but do not clobber the current state. */
+/* Like group_barrier_needed, but do not clobber the current state. */
static int
-safe_group_barrier_needed_p (rtx insn)
+safe_group_barrier_needed (rtx insn)
{
struct reg_write_state rws_saved[NUM_REGS];
int saved_first_instruction;
@@ -5655,7 +6029,7 @@ safe_group_barrier_needed_p (rtx insn)
memcpy (rws_saved, rws_sum, NUM_REGS * sizeof *rws_saved);
saved_first_instruction = first_instruction;
- t = group_barrier_needed_p (insn);
+ t = group_barrier_needed (insn);
memcpy (rws_sum, rws_saved, NUM_REGS * sizeof *rws_saved);
first_instruction = saved_first_instruction;
@@ -5705,7 +6079,7 @@ emit_insn_group_barriers (FILE *dump)
{
insns_since_last_label = 1;
- if (group_barrier_needed_p (insn))
+ if (group_barrier_needed (insn))
{
if (last_label)
{
@@ -5753,158 +6127,17 @@ emit_all_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
{
if (recog_memoized (insn) == CODE_FOR_insn_group_barrier)
init_insn_group_barriers ();
- else if (group_barrier_needed_p (insn))
+ else if (group_barrier_needed (insn))
{
emit_insn_before (gen_insn_group_barrier (GEN_INT (3)), insn);
init_insn_group_barriers ();
- group_barrier_needed_p (insn);
+ group_barrier_needed (insn);
}
}
}
}
-static int errata_find_address_regs (rtx *, void *);
-static void errata_emit_nops (rtx);
-static void fixup_errata (void);
-
-/* This structure is used to track some details about the previous insns
- groups so we can determine if it may be necessary to insert NOPs to
- workaround hardware errata. */
-static struct group
-{
- HARD_REG_SET p_reg_set;
- HARD_REG_SET gr_reg_conditionally_set;
-} last_group[2];
-
-/* Index into the last_group array. */
-static int group_idx;
-
-/* Called through for_each_rtx; determines if a hard register that was
- conditionally set in the previous group is used as an address register.
- It ensures that for_each_rtx returns 1 in that case. */
-static int
-errata_find_address_regs (rtx *xp, void *data ATTRIBUTE_UNUSED)
-{
- rtx x = *xp;
- if (GET_CODE (x) != MEM)
- return 0;
- x = XEXP (x, 0);
- if (GET_CODE (x) == POST_MODIFY)
- x = XEXP (x, 0);
- if (GET_CODE (x) == REG)
- {
- struct group *prev_group = last_group + (group_idx ^ 1);
- if (TEST_HARD_REG_BIT (prev_group->gr_reg_conditionally_set,
- REGNO (x)))
- return 1;
- return -1;
- }
- return 0;
-}
-
-/* Called for each insn; this function keeps track of the state in
- last_group and emits additional NOPs if necessary to work around
- an Itanium A/B step erratum. */
-static void
-errata_emit_nops (rtx insn)
-{
- struct group *this_group = last_group + group_idx;
- struct group *prev_group = last_group + (group_idx ^ 1);
- rtx pat = PATTERN (insn);
- rtx cond = GET_CODE (pat) == COND_EXEC ? COND_EXEC_TEST (pat) : 0;
- rtx real_pat = cond ? COND_EXEC_CODE (pat) : pat;
- enum attr_type type;
- rtx set = real_pat;
-
- if (GET_CODE (real_pat) == USE
- || GET_CODE (real_pat) == CLOBBER
- || GET_CODE (real_pat) == ASM_INPUT
- || GET_CODE (real_pat) == ADDR_VEC
- || GET_CODE (real_pat) == ADDR_DIFF_VEC
- || asm_noperands (PATTERN (insn)) >= 0)
- return;
-
- /* single_set doesn't work for COND_EXEC insns, so we have to duplicate
- parts of it. */
-
- if (GET_CODE (set) == PARALLEL)
- {
- int i;
- set = XVECEXP (real_pat, 0, 0);
- for (i = 1; i < XVECLEN (real_pat, 0); i++)
- if (GET_CODE (XVECEXP (real_pat, 0, i)) != USE
- && GET_CODE (XVECEXP (real_pat, 0, i)) != CLOBBER)
- {
- set = 0;
- break;
- }
- }
-
- if (set && GET_CODE (set) != SET)
- set = 0;
-
- type = get_attr_type (insn);
-
- if (type == TYPE_F
- && set && REG_P (SET_DEST (set)) && PR_REGNO_P (REGNO (SET_DEST (set))))
- SET_HARD_REG_BIT (this_group->p_reg_set, REGNO (SET_DEST (set)));
-
- if ((type == TYPE_M || type == TYPE_A) && cond && set
- && REG_P (SET_DEST (set))
- && GET_CODE (SET_SRC (set)) != PLUS
- && GET_CODE (SET_SRC (set)) != MINUS
- && (GET_CODE (SET_SRC (set)) != ASHIFT
- || !shladd_operand (XEXP (SET_SRC (set), 1), VOIDmode))
- && (GET_CODE (SET_SRC (set)) != MEM
- || GET_CODE (XEXP (SET_SRC (set), 0)) != POST_MODIFY)
- && GENERAL_REGNO_P (REGNO (SET_DEST (set))))
- {
- if (GET_RTX_CLASS (GET_CODE (cond)) != '<'
- || ! REG_P (XEXP (cond, 0)))
- abort ();
-
- if (TEST_HARD_REG_BIT (prev_group->p_reg_set, REGNO (XEXP (cond, 0))))
- SET_HARD_REG_BIT (this_group->gr_reg_conditionally_set, REGNO (SET_DEST (set)));
- }
- if (for_each_rtx (&real_pat, errata_find_address_regs, NULL))
- {
- emit_insn_before (gen_insn_group_barrier (GEN_INT (3)), insn);
- emit_insn_before (gen_nop (), insn);
- emit_insn_before (gen_insn_group_barrier (GEN_INT (3)), insn);
- group_idx = 0;
- memset (last_group, 0, sizeof last_group);
- }
-}
-
-/* Emit extra nops if they are required to work around hardware errata. */
-
-static void
-fixup_errata (void)
-{
- rtx insn;
-
- if (! TARGET_B_STEP)
- return;
-
- group_idx = 0;
- memset (last_group, 0, sizeof last_group);
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- if (!INSN_P (insn))
- continue;
-
- if (ia64_safe_type (insn) == TYPE_S)
- {
- group_idx ^= 1;
- memset (last_group + group_idx, 0, sizeof last_group[group_idx]);
- }
- else
- errata_emit_nops (insn);
- }
-}
-
/* Instruction scheduling support. */
@@ -5932,7 +6165,7 @@ static const char *bundle_name [NR_BUNDLES] =
int ia64_final_schedule = 0;
-/* Codes of the corresponding quieryied units: */
+/* Codes of the corresponding queried units: */
static int _0mii_, _0mmi_, _0mfi_, _0mmf_;
static int _0bbb_, _0mbb_, _0mib_, _0mmb_, _0mfb_, _0mlx_;
@@ -5967,7 +6200,15 @@ static state_t prev_cycle_state = NULL;
/* The following array element values are TRUE if the corresponding
insn requires to add stop bits before it. */
-static char *stops_p;
+static char *stops_p = NULL;
+
+/* The following array element values are ZERO for non-speculative
+ instructions and hold corresponding speculation check number for
+ speculative instructions. */
+static int *spec_check_no = NULL;
+
+/* Size of spec_check_no array. */
+static int max_uid = 0;
/* The following variable is used to set up the mentioned above array. */
@@ -5989,6 +6230,9 @@ static int *clocks;
static int *add_cycles;
+/* The following variable value is number of data speculations in progress. */
+static int pending_data_specs = 0;
+
static rtx ia64_single_set (rtx);
static void ia64_emit_insn_before (rtx, rtx);
@@ -6038,16 +6282,18 @@ ia64_single_set (rtx insn)
return ret;
}
-/* Adjust the cost of a scheduling dependency. Return the new cost of
- a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
+/* Adjust the cost of a scheduling dependency.
+ Return the new cost of a dependency of type DEP_TYPE or INSN on DEP_INSN.
+ COST is the current cost. */
static int
-ia64_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
+ia64_adjust_cost_2 (rtx insn, int dep_type1, rtx dep_insn, int cost)
{
+ enum reg_note dep_type = (enum reg_note) dep_type1;
enum attr_itanium_class dep_class;
enum attr_itanium_class insn_class;
- if (REG_NOTE_KIND (link) != REG_DEP_OUTPUT)
+ if (dep_type != REG_DEP_OUTPUT)
return cost;
insn_class = ia64_safe_itanium_class (insn);
@@ -6078,6 +6324,12 @@ ia64_dependencies_evaluation_hook (rtx head, rtx tail)
{
rtx insn, link, next, next_tail;
+ /* Before reload, which_alternative is not set, which means that
+ ia64_safe_itanium_class will produce wrong results for (at least)
+ move instructions. */
+ if (!reload_completed)
+ return;
+
next_tail = NEXT_INSN (tail);
for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
if (INSN_P (insn))
@@ -6088,14 +6340,19 @@ ia64_dependencies_evaluation_hook (rtx head, rtx tail)
{
for (link = INSN_DEPEND (insn); link != 0; link = XEXP (link, 1))
{
+ enum attr_itanium_class c;
+
+ if (REG_NOTE_KIND (link) != REG_DEP_TRUE)
+ continue;
next = XEXP (link, 0);
- if ((ia64_safe_itanium_class (next) == ITANIUM_CLASS_ST
- || ia64_safe_itanium_class (next) == ITANIUM_CLASS_STF)
+ c = ia64_safe_itanium_class (next);
+ if ((c == ITANIUM_CLASS_ST
+ || c == ITANIUM_CLASS_STF)
&& ia64_st_address_bypass_p (insn, next))
break;
- else if ((ia64_safe_itanium_class (next) == ITANIUM_CLASS_LD
- || ia64_safe_itanium_class (next)
- == ITANIUM_CLASS_FLD)
+ else if ((c == ITANIUM_CLASS_LD
+ || c == ITANIUM_CLASS_FLD
+ || c == ITANIUM_CLASS_FLDP)
&& ia64_ld_address_bypass_p (insn, next))
break;
}
@@ -6117,13 +6374,32 @@ ia64_sched_init (FILE *dump ATTRIBUTE_UNUSED,
for (insn = NEXT_INSN (current_sched_info->prev_head);
insn != current_sched_info->next_tail;
insn = NEXT_INSN (insn))
- if (SCHED_GROUP_P (insn))
- abort ();
+ gcc_assert (!SCHED_GROUP_P (insn));
#endif
last_scheduled_insn = NULL_RTX;
init_insn_group_barriers ();
}
+/* We're beginning a scheduling pass. Check assertion. */
+
+static void
+ia64_sched_init_global (FILE *dump ATTRIBUTE_UNUSED,
+ int sched_verbose ATTRIBUTE_UNUSED,
+ int max_ready ATTRIBUTE_UNUSED)
+{
+ gcc_assert (!pending_data_specs);
+}
+
+/* Scheduling pass is now finished. Free/reset static variable. */
+static void
+ia64_sched_finish_global (FILE *dump ATTRIBUTE_UNUSED,
+ int sched_verbose ATTRIBUTE_UNUSED)
+{
+ free (spec_check_no);
+ spec_check_no = 0;
+ max_uid = 0;
+}
+
/* We are about to being issuing insns for this clock cycle.
Override the default sort algorithm to better slot instructions. */
@@ -6185,7 +6461,7 @@ ia64_dfa_sched_reorder (FILE *dump, int sched_verbose, rtx *ready,
int nr_need_stop = 0;
for (insnp = ready; insnp < e_ready; insnp++)
- if (safe_group_barrier_needed_p (*insnp))
+ if (safe_group_barrier_needed (*insnp))
nr_need_stop++;
if (reorder_type == 1 && n_ready == nr_need_stop)
@@ -6199,7 +6475,7 @@ ia64_dfa_sched_reorder (FILE *dump, int sched_verbose, rtx *ready,
while (insnp >= ready + deleted)
{
rtx insn = *insnp;
- if (! safe_group_barrier_needed_p (insn))
+ if (! safe_group_barrier_needed (insn))
break;
memmove (ready + 1, ready, (insnp - ready) * sizeof (rtx));
*ready = insn;
@@ -6246,12 +6522,23 @@ ia64_variable_issue (FILE *dump ATTRIBUTE_UNUSED,
rtx insn ATTRIBUTE_UNUSED,
int can_issue_more ATTRIBUTE_UNUSED)
{
+ if (current_sched_info->flags & DO_SPECULATION)
+ /* Modulo scheduling does not extend h_i_d when emitting
+ new instructions. Deal with it. */
+ {
+ if (DONE_SPEC (insn) & BEGIN_DATA)
+ pending_data_specs++;
+ if (CHECK_SPEC (insn) & BEGIN_DATA)
+ pending_data_specs--;
+ }
+
last_scheduled_insn = insn;
memcpy (prev_cycle_state, curr_state, dfa_state_size);
if (reload_completed)
{
- if (group_barrier_needed_p (insn))
- abort ();
+ int needed = group_barrier_needed (insn);
+
+ gcc_assert (!needed);
if (GET_CODE (insn) == CALL_INSN)
init_insn_group_barriers ();
stops_p [INSN_UID (insn)] = stop_before_p;
@@ -6266,10 +6553,23 @@ ia64_variable_issue (FILE *dump ATTRIBUTE_UNUSED,
static int
ia64_first_cycle_multipass_dfa_lookahead_guard (rtx insn)
{
- if (insn == NULL_RTX || !INSN_P (insn))
- abort ();
- return (!reload_completed
- || !safe_group_barrier_needed_p (insn));
+ gcc_assert (insn && INSN_P (insn));
+ return ((!reload_completed
+ || !safe_group_barrier_needed (insn))
+ && ia64_first_cycle_multipass_dfa_lookahead_guard_spec (insn));
+}
+
+/* We are choosing insn from the ready queue. Return nonzero if INSN
+ can be chosen. */
+
+static bool
+ia64_first_cycle_multipass_dfa_lookahead_guard_spec (rtx insn)
+{
+ gcc_assert (insn && INSN_P (insn));
+ /* Size of ALAT is 32. As far as we perform conservative data speculation,
+ we keep ALAT half-empty. */
+ return (pending_data_specs < 16
+ || !(TODO_SPEC (insn) & BEGIN_DATA));
}
/* The following variable value is pseudo-insn used by the DFA insn
@@ -6278,7 +6578,7 @@ ia64_first_cycle_multipass_dfa_lookahead_guard (rtx insn)
static rtx dfa_pre_cycle_insn;
-/* We are about to being issuing INSN. Return nonzero if we can not
+/* We are about to being issuing INSN. Return nonzero if we cannot
issue it on given cycle CLOCK and return zero if we should not sort
the ready queue on the next clock start. */
@@ -6288,9 +6588,8 @@ ia64_dfa_new_cycle (FILE *dump, int verbose, rtx insn, int last_clock,
{
int setup_clocks_p = FALSE;
- if (insn == NULL_RTX || !INSN_P (insn))
- abort ();
- if ((reload_completed && safe_group_barrier_needed_p (insn))
+ gcc_assert (insn && INSN_P (insn));
+ if ((reload_completed && safe_group_barrier_needed (insn))
|| (last_scheduled_insn
&& (GET_CODE (last_scheduled_insn) == CALL_INSN
|| GET_CODE (PATTERN (last_scheduled_insn)) == ASM_INPUT
@@ -6358,6 +6657,590 @@ ia64_dfa_new_cycle (FILE *dump, int verbose, rtx insn, int last_clock,
return 0;
}
+/* Implement targetm.sched.h_i_d_extended hook.
+ Extend internal data structures. */
+static void
+ia64_h_i_d_extended (void)
+{
+ if (current_sched_info->flags & DO_SPECULATION)
+ {
+ int new_max_uid = get_max_uid () + 1;
+
+ spec_check_no = xrecalloc (spec_check_no, new_max_uid,
+ max_uid, sizeof (*spec_check_no));
+ max_uid = new_max_uid;
+ }
+
+ if (stops_p != NULL)
+ {
+ int new_clocks_length = get_max_uid () + 1;
+
+ stops_p = xrecalloc (stops_p, new_clocks_length, clocks_length, 1);
+
+ if (ia64_tune == PROCESSOR_ITANIUM)
+ {
+ clocks = xrecalloc (clocks, new_clocks_length, clocks_length,
+ sizeof (int));
+ add_cycles = xrecalloc (add_cycles, new_clocks_length, clocks_length,
+ sizeof (int));
+ }
+
+ clocks_length = new_clocks_length;
+ }
+}
+
+/* Constants that help mapping 'enum machine_mode' to int. */
+enum SPEC_MODES
+ {
+ SPEC_MODE_INVALID = -1,
+ SPEC_MODE_FIRST = 0,
+ SPEC_MODE_FOR_EXTEND_FIRST = 1,
+ SPEC_MODE_FOR_EXTEND_LAST = 3,
+ SPEC_MODE_LAST = 8
+ };
+
+/* Return index of the MODE. */
+static int
+ia64_mode_to_int (enum machine_mode mode)
+{
+ switch (mode)
+ {
+ case BImode: return 0; /* SPEC_MODE_FIRST */
+ case QImode: return 1; /* SPEC_MODE_FOR_EXTEND_FIRST */
+ case HImode: return 2;
+ case SImode: return 3; /* SPEC_MODE_FOR_EXTEND_LAST */
+ case DImode: return 4;
+ case SFmode: return 5;
+ case DFmode: return 6;
+ case XFmode: return 7;
+ case TImode:
+ /* ??? This mode needs testing. Bypasses for ldfp8 instruction are not
+ mentioned in itanium[12].md. Predicate fp_register_operand also
+ needs to be defined. Bottom line: better disable for now. */
+ return SPEC_MODE_INVALID;
+ default: return SPEC_MODE_INVALID;
+ }
+}
+
+/* Provide information about speculation capabilities. */
+static void
+ia64_set_sched_flags (spec_info_t spec_info)
+{
+ unsigned int *flags = &(current_sched_info->flags);
+
+ if (*flags & SCHED_RGN
+ || *flags & SCHED_EBB)
+ {
+ int mask = 0;
+
+ if ((mflag_sched_br_data_spec && !reload_completed && optimize > 0)
+ || (mflag_sched_ar_data_spec && reload_completed))
+ {
+ mask |= BEGIN_DATA;
+
+ if ((mflag_sched_br_in_data_spec && !reload_completed)
+ || (mflag_sched_ar_in_data_spec && reload_completed))
+ mask |= BE_IN_DATA;
+ }
+
+ if (mflag_sched_control_spec)
+ {
+ mask |= BEGIN_CONTROL;
+
+ if (mflag_sched_in_control_spec)
+ mask |= BE_IN_CONTROL;
+ }
+
+ gcc_assert (*flags & USE_GLAT);
+
+ if (mask)
+ {
+ *flags |= USE_DEPS_LIST | DETACH_LIFE_INFO | DO_SPECULATION;
+
+ spec_info->mask = mask;
+ spec_info->flags = 0;
+
+ if ((mask & DATA_SPEC) && mflag_sched_prefer_non_data_spec_insns)
+ spec_info->flags |= PREFER_NON_DATA_SPEC;
+
+ if ((mask & CONTROL_SPEC)
+ && mflag_sched_prefer_non_control_spec_insns)
+ spec_info->flags |= PREFER_NON_CONTROL_SPEC;
+
+ if (mflag_sched_spec_verbose)
+ {
+ if (sched_verbose >= 1)
+ spec_info->dump = sched_dump;
+ else
+ spec_info->dump = stderr;
+ }
+ else
+ spec_info->dump = 0;
+
+ if (mflag_sched_count_spec_in_critical_path)
+ spec_info->flags |= COUNT_SPEC_IN_CRITICAL_PATH;
+ }
+ }
+}
+
+/* Implement targetm.sched.speculate_insn hook.
+ Check if the INSN can be TS speculative.
+ If 'no' - return -1.
+ If 'yes' - generate speculative pattern in the NEW_PAT and return 1.
+ If current pattern of the INSN already provides TS speculation, return 0. */
+static int
+ia64_speculate_insn (rtx insn, ds_t ts, rtx *new_pat)
+{
+ rtx pat, reg, mem, mem_reg;
+ int mode_no, gen_p = 1;
+ bool extend_p;
+
+ gcc_assert (!(ts & ~BEGIN_SPEC) && ts);
+
+ pat = PATTERN (insn);
+
+ if (GET_CODE (pat) == COND_EXEC)
+ pat = COND_EXEC_CODE (pat);
+
+ /* This should be a SET ... */
+ if (GET_CODE (pat) != SET)
+ return -1;
+
+ reg = SET_DEST (pat);
+ /* ... to the general/fp register ... */
+ if (!REG_P (reg) || !(GR_REGNO_P (REGNO (reg)) || FP_REGNO_P (REGNO (reg))))
+ return -1;
+
+ /* ... from the mem ... */
+ mem = SET_SRC (pat);
+
+ /* ... that can, possibly, be a zero_extend ... */
+ if (GET_CODE (mem) == ZERO_EXTEND)
+ {
+ mem = XEXP (mem, 0);
+ extend_p = true;
+ }
+ else
+ extend_p = false;
+
+ /* ... or a speculative load. */
+ if (GET_CODE (mem) == UNSPEC)
+ {
+ int code;
+
+ code = XINT (mem, 1);
+ if (code != UNSPEC_LDA && code != UNSPEC_LDS && code != UNSPEC_LDSA)
+ return -1;
+
+ if ((code == UNSPEC_LDA && !(ts & BEGIN_CONTROL))
+ || (code == UNSPEC_LDS && !(ts & BEGIN_DATA))
+ || code == UNSPEC_LDSA)
+ gen_p = 0;
+
+ mem = XVECEXP (mem, 0, 0);
+ gcc_assert (MEM_P (mem));
+ }
+
+ /* Source should be a mem ... */
+ if (!MEM_P (mem))
+ return -1;
+
+ /* ... addressed by a register. */
+ mem_reg = XEXP (mem, 0);
+ if (!REG_P (mem_reg))
+ return -1;
+
+ /* We should use MEM's mode since REG's mode in presence of ZERO_EXTEND
+ will always be DImode. */
+ mode_no = ia64_mode_to_int (GET_MODE (mem));
+
+ if (mode_no == SPEC_MODE_INVALID
+ || (extend_p
+ && !(SPEC_MODE_FOR_EXTEND_FIRST <= mode_no
+ && mode_no <= SPEC_MODE_FOR_EXTEND_LAST)))
+ return -1;
+
+ extract_insn_cached (insn);
+ gcc_assert (reg == recog_data.operand[0] && mem == recog_data.operand[1]);
+
+ *new_pat = ia64_gen_spec_insn (insn, ts, mode_no, gen_p != 0, extend_p);
+
+ return gen_p;
+}
+
+enum
+ {
+ /* Offset to reach ZERO_EXTEND patterns. */
+ SPEC_GEN_EXTEND_OFFSET = SPEC_MODE_LAST - SPEC_MODE_FOR_EXTEND_FIRST + 1,
+ /* Number of patterns for each speculation mode. */
+ SPEC_N = (SPEC_MODE_LAST
+ + SPEC_MODE_FOR_EXTEND_LAST - SPEC_MODE_FOR_EXTEND_FIRST + 2)
+ };
+
+enum SPEC_GEN_LD_MAP
+ {
+ /* Offset to ld.a patterns. */
+ SPEC_GEN_A = 0 * SPEC_N,
+ /* Offset to ld.s patterns. */
+ SPEC_GEN_S = 1 * SPEC_N,
+ /* Offset to ld.sa patterns. */
+ SPEC_GEN_SA = 2 * SPEC_N,
+ /* Offset to ld.sa patterns. For this patterns corresponding ld.c will
+ mutate to chk.s. */
+ SPEC_GEN_SA_FOR_S = 3 * SPEC_N
+ };
+
+/* These offsets are used to get (4 * SPEC_N). */
+enum SPEC_GEN_CHECK_OFFSET
+ {
+ SPEC_GEN_CHKA_FOR_A_OFFSET = 4 * SPEC_N - SPEC_GEN_A,
+ SPEC_GEN_CHKA_FOR_SA_OFFSET = 4 * SPEC_N - SPEC_GEN_SA
+ };
+
+/* If GEN_P is true, calculate the index of needed speculation check and return
+ speculative pattern for INSN with speculative mode TS, machine mode
+ MODE_NO and with ZERO_EXTEND (if EXTEND_P is true).
+ If GEN_P is false, just calculate the index of needed speculation check. */
+static rtx
+ia64_gen_spec_insn (rtx insn, ds_t ts, int mode_no, bool gen_p, bool extend_p)
+{
+ rtx pat, new_pat;
+ int load_no;
+ int shift = 0;
+
+ static rtx (* const gen_load[]) (rtx, rtx) = {
+ gen_movbi_advanced,
+ gen_movqi_advanced,
+ gen_movhi_advanced,
+ gen_movsi_advanced,
+ gen_movdi_advanced,
+ gen_movsf_advanced,
+ gen_movdf_advanced,
+ gen_movxf_advanced,
+ gen_movti_advanced,
+ gen_zero_extendqidi2_advanced,
+ gen_zero_extendhidi2_advanced,
+ gen_zero_extendsidi2_advanced,
+
+ gen_movbi_speculative,
+ gen_movqi_speculative,
+ gen_movhi_speculative,
+ gen_movsi_speculative,
+ gen_movdi_speculative,
+ gen_movsf_speculative,
+ gen_movdf_speculative,
+ gen_movxf_speculative,
+ gen_movti_speculative,
+ gen_zero_extendqidi2_speculative,
+ gen_zero_extendhidi2_speculative,
+ gen_zero_extendsidi2_speculative,
+
+ gen_movbi_speculative_advanced,
+ gen_movqi_speculative_advanced,
+ gen_movhi_speculative_advanced,
+ gen_movsi_speculative_advanced,
+ gen_movdi_speculative_advanced,
+ gen_movsf_speculative_advanced,
+ gen_movdf_speculative_advanced,
+ gen_movxf_speculative_advanced,
+ gen_movti_speculative_advanced,
+ gen_zero_extendqidi2_speculative_advanced,
+ gen_zero_extendhidi2_speculative_advanced,
+ gen_zero_extendsidi2_speculative_advanced,
+
+ gen_movbi_speculative_advanced,
+ gen_movqi_speculative_advanced,
+ gen_movhi_speculative_advanced,
+ gen_movsi_speculative_advanced,
+ gen_movdi_speculative_advanced,
+ gen_movsf_speculative_advanced,
+ gen_movdf_speculative_advanced,
+ gen_movxf_speculative_advanced,
+ gen_movti_speculative_advanced,
+ gen_zero_extendqidi2_speculative_advanced,
+ gen_zero_extendhidi2_speculative_advanced,
+ gen_zero_extendsidi2_speculative_advanced
+ };
+
+ load_no = extend_p ? mode_no + SPEC_GEN_EXTEND_OFFSET : mode_no;
+
+ if (ts & BEGIN_DATA)
+ {
+ /* We don't need recovery because even if this is ld.sa
+ ALAT entry will be allocated only if NAT bit is set to zero.
+ So it is enough to use ld.c here. */
+
+ if (ts & BEGIN_CONTROL)
+ {
+ load_no += SPEC_GEN_SA;
+
+ if (!mflag_sched_ldc)
+ shift = SPEC_GEN_CHKA_FOR_SA_OFFSET;
+ }
+ else
+ {
+ load_no += SPEC_GEN_A;
+
+ if (!mflag_sched_ldc)
+ shift = SPEC_GEN_CHKA_FOR_A_OFFSET;
+ }
+ }
+ else if (ts & BEGIN_CONTROL)
+ {
+ /* ld.sa can be used instead of ld.s to avoid basic block splitting. */
+ if (!mflag_control_ldc)
+ load_no += SPEC_GEN_S;
+ else
+ {
+ gcc_assert (mflag_sched_ldc);
+ load_no += SPEC_GEN_SA_FOR_S;
+ }
+ }
+ else
+ gcc_unreachable ();
+
+ /* Set the desired check index. We add '1', because zero element in this
+ array means, that instruction with such uid is non-speculative. */
+ spec_check_no[INSN_UID (insn)] = load_no + shift + 1;
+
+ if (!gen_p)
+ return 0;
+
+ new_pat = gen_load[load_no] (copy_rtx (recog_data.operand[0]),
+ copy_rtx (recog_data.operand[1]));
+
+ pat = PATTERN (insn);
+ if (GET_CODE (pat) == COND_EXEC)
+ new_pat = gen_rtx_COND_EXEC (VOIDmode, copy_rtx
+ (COND_EXEC_TEST (pat)), new_pat);
+
+ return new_pat;
+}
+
+/* Offset to branchy checks. */
+enum { SPEC_GEN_CHECK_MUTATION_OFFSET = 5 * SPEC_N };
+
+/* Return nonzero, if INSN needs branchy recovery check. */
+static bool
+ia64_needs_block_p (rtx insn)
+{
+ int check_no;
+
+ check_no = spec_check_no[INSN_UID(insn)] - 1;
+ gcc_assert (0 <= check_no && check_no < SPEC_GEN_CHECK_MUTATION_OFFSET);
+
+ return ((SPEC_GEN_S <= check_no && check_no < SPEC_GEN_S + SPEC_N)
+ || (4 * SPEC_N <= check_no && check_no < 4 * SPEC_N + SPEC_N));
+}
+
+/* Generate (or regenerate, if (MUTATE_P)) recovery check for INSN.
+ If (LABEL != 0 || MUTATE_P), generate branchy recovery check.
+ Otherwise, generate a simple check. */
+static rtx
+ia64_gen_check (rtx insn, rtx label, bool mutate_p)
+{
+ rtx op1, pat, check_pat;
+
+ static rtx (* const gen_check[]) (rtx, rtx) = {
+ gen_movbi_clr,
+ gen_movqi_clr,
+ gen_movhi_clr,
+ gen_movsi_clr,
+ gen_movdi_clr,
+ gen_movsf_clr,
+ gen_movdf_clr,
+ gen_movxf_clr,
+ gen_movti_clr,
+ gen_zero_extendqidi2_clr,
+ gen_zero_extendhidi2_clr,
+ gen_zero_extendsidi2_clr,
+
+ gen_speculation_check_bi,
+ gen_speculation_check_qi,
+ gen_speculation_check_hi,
+ gen_speculation_check_si,
+ gen_speculation_check_di,
+ gen_speculation_check_sf,
+ gen_speculation_check_df,
+ gen_speculation_check_xf,
+ gen_speculation_check_ti,
+ gen_speculation_check_di,
+ gen_speculation_check_di,
+ gen_speculation_check_di,
+
+ gen_movbi_clr,
+ gen_movqi_clr,
+ gen_movhi_clr,
+ gen_movsi_clr,
+ gen_movdi_clr,
+ gen_movsf_clr,
+ gen_movdf_clr,
+ gen_movxf_clr,
+ gen_movti_clr,
+ gen_zero_extendqidi2_clr,
+ gen_zero_extendhidi2_clr,
+ gen_zero_extendsidi2_clr,
+
+ gen_movbi_clr,
+ gen_movqi_clr,
+ gen_movhi_clr,
+ gen_movsi_clr,
+ gen_movdi_clr,
+ gen_movsf_clr,
+ gen_movdf_clr,
+ gen_movxf_clr,
+ gen_movti_clr,
+ gen_zero_extendqidi2_clr,
+ gen_zero_extendhidi2_clr,
+ gen_zero_extendsidi2_clr,
+
+ gen_advanced_load_check_clr_bi,
+ gen_advanced_load_check_clr_qi,
+ gen_advanced_load_check_clr_hi,
+ gen_advanced_load_check_clr_si,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_sf,
+ gen_advanced_load_check_clr_df,
+ gen_advanced_load_check_clr_xf,
+ gen_advanced_load_check_clr_ti,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_di,
+
+ /* Following checks are generated during mutation. */
+ gen_advanced_load_check_clr_bi,
+ gen_advanced_load_check_clr_qi,
+ gen_advanced_load_check_clr_hi,
+ gen_advanced_load_check_clr_si,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_sf,
+ gen_advanced_load_check_clr_df,
+ gen_advanced_load_check_clr_xf,
+ gen_advanced_load_check_clr_ti,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_di,
+
+ 0,0,0,0,0,0,0,0,0,0,0,0,
+
+ gen_advanced_load_check_clr_bi,
+ gen_advanced_load_check_clr_qi,
+ gen_advanced_load_check_clr_hi,
+ gen_advanced_load_check_clr_si,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_sf,
+ gen_advanced_load_check_clr_df,
+ gen_advanced_load_check_clr_xf,
+ gen_advanced_load_check_clr_ti,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_di,
+
+ gen_speculation_check_bi,
+ gen_speculation_check_qi,
+ gen_speculation_check_hi,
+ gen_speculation_check_si,
+ gen_speculation_check_di,
+ gen_speculation_check_sf,
+ gen_speculation_check_df,
+ gen_speculation_check_xf,
+ gen_speculation_check_ti,
+ gen_speculation_check_di,
+ gen_speculation_check_di,
+ gen_speculation_check_di
+ };
+
+ extract_insn_cached (insn);
+
+ if (label)
+ {
+ gcc_assert (mutate_p || ia64_needs_block_p (insn));
+ op1 = label;
+ }
+ else
+ {
+ gcc_assert (!mutate_p && !ia64_needs_block_p (insn));
+ op1 = copy_rtx (recog_data.operand[1]);
+ }
+
+ if (mutate_p)
+ /* INSN is ld.c.
+ Find the speculation check number by searching for original
+ speculative load in the RESOLVED_DEPS list of INSN.
+ As long as patterns are unique for each instruction, this can be
+ accomplished by matching ORIG_PAT fields. */
+ {
+ rtx link;
+ int check_no = 0;
+ rtx orig_pat = ORIG_PAT (insn);
+
+ for (link = RESOLVED_DEPS (insn); link; link = XEXP (link, 1))
+ {
+ rtx x = XEXP (link, 0);
+
+ if (ORIG_PAT (x) == orig_pat)
+ check_no = spec_check_no[INSN_UID (x)];
+ }
+ gcc_assert (check_no);
+
+ spec_check_no[INSN_UID (insn)] = (check_no
+ + SPEC_GEN_CHECK_MUTATION_OFFSET);
+ }
+
+ check_pat = (gen_check[spec_check_no[INSN_UID (insn)] - 1]
+ (copy_rtx (recog_data.operand[0]), op1));
+
+ pat = PATTERN (insn);
+ if (GET_CODE (pat) == COND_EXEC)
+ check_pat = gen_rtx_COND_EXEC (VOIDmode, copy_rtx (COND_EXEC_TEST (pat)),
+ check_pat);
+
+ return check_pat;
+}
+
+/* Return nonzero, if X is branchy recovery check. */
+static int
+ia64_spec_check_p (rtx x)
+{
+ x = PATTERN (x);
+ if (GET_CODE (x) == COND_EXEC)
+ x = COND_EXEC_CODE (x);
+ if (GET_CODE (x) == SET)
+ return ia64_spec_check_src_p (SET_SRC (x));
+ return 0;
+}
+
+/* Return nonzero, if SRC belongs to recovery check. */
+static int
+ia64_spec_check_src_p (rtx src)
+{
+ if (GET_CODE (src) == IF_THEN_ELSE)
+ {
+ rtx t;
+
+ t = XEXP (src, 0);
+ if (GET_CODE (t) == NE)
+ {
+ t = XEXP (t, 0);
+
+ if (GET_CODE (t) == UNSPEC)
+ {
+ int code;
+
+ code = XINT (t, 1);
+
+ if (code == UNSPEC_CHKACLR
+ || code == UNSPEC_CHKS
+ || code == UNSPEC_LDCCLR)
+ {
+ gcc_assert (code != 0);
+ return code;
+ }
+ }
+ }
+ }
+ return 0;
+}
/* The following page contains abstract data `bundle states' which are
@@ -6617,12 +7500,10 @@ issue_nops_and_insn (struct bundle_state *originator, int before_nops_num,
curr_state->accumulated_insns_num
= originator->accumulated_insns_num + before_nops_num;
curr_state->branch_deviation = originator->branch_deviation;
- if (insn == NULL_RTX)
- abort ();
- else if (INSN_CODE (insn) == CODE_FOR_insn_group_barrier)
+ gcc_assert (insn);
+ if (INSN_CODE (insn) == CODE_FOR_insn_group_barrier)
{
- if (GET_MODE (insn) == TImode)
- abort ();
+ gcc_assert (GET_MODE (insn) != TImode);
if (!try_issue_nops (curr_state, before_nops_num))
return;
if (!try_issue_insn (curr_state, insn))
@@ -6642,14 +7523,25 @@ issue_nops_and_insn (struct bundle_state *originator, int before_nops_num,
if (!try_issue_insn (curr_state, insn))
return;
curr_state->accumulated_insns_num++;
- if (GET_CODE (PATTERN (insn)) == ASM_INPUT
- || asm_noperands (PATTERN (insn)) >= 0)
- abort ();
+ gcc_assert (GET_CODE (PATTERN (insn)) != ASM_INPUT
+ && asm_noperands (PATTERN (insn)) < 0);
+
if (ia64_safe_type (insn) == TYPE_L)
curr_state->accumulated_insns_num++;
}
else
{
+ /* If this is an insn that must be first in a group, then don't allow
+ nops to be emitted before it. Currently, alloc is the only such
+ supported instruction. */
+ /* ??? The bundling automatons should handle this for us, but they do
+ not yet have support for the first_insn attribute. */
+ if (before_nops_num > 0 && get_attr_first_insn (insn) == FIRST_INSN_YES)
+ {
+ free_bundle_state (curr_state);
+ return;
+ }
+
state_transition (curr_state->dfa_state, dfa_pre_cycle_insn);
state_transition (curr_state->dfa_state, NULL);
curr_state->cost++;
@@ -6728,7 +7620,13 @@ get_max_pos (state_t state)
/* The function returns code of a possible template for given position
and state. The function should be called only with 2 values of
- position equal to 3 or 6. */
+ position equal to 3 or 6. We avoid generating F NOPs by putting
+ templates containing F insns at the end of the template search
+ because undocumented anomaly in McKinley derived cores which can
+ cause stalls if an F-unit insn (including a NOP) is issued within a
+ six-cycle window after reading certain application registers (such
+ as ar.bsp). Furthermore, power-considerations also argue against
+ the use of F-unit instructions unless they're really needed. */
static int
get_template (state_t state, int pos)
@@ -6736,53 +7634,53 @@ get_template (state_t state, int pos)
switch (pos)
{
case 3:
- if (cpu_unit_reservation_p (state, _0mii_))
- return 0;
- else if (cpu_unit_reservation_p (state, _0mmi_))
+ if (cpu_unit_reservation_p (state, _0mmi_))
return 1;
- else if (cpu_unit_reservation_p (state, _0mfi_))
- return 2;
- else if (cpu_unit_reservation_p (state, _0mmf_))
- return 3;
- else if (cpu_unit_reservation_p (state, _0bbb_))
- return 4;
- else if (cpu_unit_reservation_p (state, _0mbb_))
- return 5;
- else if (cpu_unit_reservation_p (state, _0mib_))
- return 6;
+ else if (cpu_unit_reservation_p (state, _0mii_))
+ return 0;
else if (cpu_unit_reservation_p (state, _0mmb_))
return 7;
+ else if (cpu_unit_reservation_p (state, _0mib_))
+ return 6;
+ else if (cpu_unit_reservation_p (state, _0mbb_))
+ return 5;
+ else if (cpu_unit_reservation_p (state, _0bbb_))
+ return 4;
+ else if (cpu_unit_reservation_p (state, _0mmf_))
+ return 3;
+ else if (cpu_unit_reservation_p (state, _0mfi_))
+ return 2;
else if (cpu_unit_reservation_p (state, _0mfb_))
return 8;
else if (cpu_unit_reservation_p (state, _0mlx_))
return 9;
else
- abort ();
+ gcc_unreachable ();
case 6:
- if (cpu_unit_reservation_p (state, _1mii_))
- return 0;
- else if (cpu_unit_reservation_p (state, _1mmi_))
+ if (cpu_unit_reservation_p (state, _1mmi_))
return 1;
- else if (cpu_unit_reservation_p (state, _1mfi_))
- return 2;
- else if (_1mmf_ >= 0 && cpu_unit_reservation_p (state, _1mmf_))
- return 3;
- else if (cpu_unit_reservation_p (state, _1bbb_))
- return 4;
- else if (cpu_unit_reservation_p (state, _1mbb_))
- return 5;
- else if (cpu_unit_reservation_p (state, _1mib_))
- return 6;
+ else if (cpu_unit_reservation_p (state, _1mii_))
+ return 0;
else if (cpu_unit_reservation_p (state, _1mmb_))
return 7;
+ else if (cpu_unit_reservation_p (state, _1mib_))
+ return 6;
+ else if (cpu_unit_reservation_p (state, _1mbb_))
+ return 5;
+ else if (cpu_unit_reservation_p (state, _1bbb_))
+ return 4;
+ else if (_1mmf_ >= 0 && cpu_unit_reservation_p (state, _1mmf_))
+ return 3;
+ else if (cpu_unit_reservation_p (state, _1mfi_))
+ return 2;
else if (cpu_unit_reservation_p (state, _1mfb_))
return 8;
else if (cpu_unit_reservation_p (state, _1mlx_))
return 9;
else
- abort ();
+ gcc_unreachable ();
default:
- abort ();
+ gcc_unreachable ();
}
}
@@ -6801,6 +7699,53 @@ get_next_important_insn (rtx insn, rtx tail)
return NULL_RTX;
}
+/* Add a bundle selector TEMPLATE0 before INSN. */
+
+static void
+ia64_add_bundle_selector_before (int template0, rtx insn)
+{
+ rtx b = gen_bundle_selector (GEN_INT (template0));
+
+ ia64_emit_insn_before (b, insn);
+#if NR_BUNDLES == 10
+ if ((template0 == 4 || template0 == 5)
+ && (flag_unwind_tables || (flag_exceptions && !USING_SJLJ_EXCEPTIONS)))
+ {
+ int i;
+ rtx note = NULL_RTX;
+
+ /* In .mbb and .bbb bundles, check if CALL_INSN isn't in the
+ first or second slot. If it is and has REG_EH_NOTE set, copy it
+ to following nops, as br.call sets rp to the address of following
+ bundle and therefore an EH region end must be on a bundle
+ boundary. */
+ insn = PREV_INSN (insn);
+ for (i = 0; i < 3; i++)
+ {
+ do
+ insn = next_active_insn (insn);
+ while (GET_CODE (insn) == INSN
+ && get_attr_empty (insn) == EMPTY_YES);
+ if (GET_CODE (insn) == CALL_INSN)
+ note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+ else if (note)
+ {
+ int code;
+
+ gcc_assert ((code = recog_memoized (insn)) == CODE_FOR_nop
+ || code == CODE_FOR_nop_b);
+ if (find_reg_note (insn, REG_EH_REGION, NULL_RTX))
+ note = NULL_RTX;
+ else
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (note, 0),
+ REG_NOTES (insn));
+ }
+ }
+ }
+#endif
+}
+
/* The following function does insn bundling. Bundling means
inserting templates and nop insns to fit insn groups into permitted
templates. Instruction scheduling uses NDFA (non-deterministic
@@ -6813,7 +7758,7 @@ get_next_important_insn (rtx insn, rtx tail)
automata only says that we can issue an insn possibly inserting
some nops before it and using some template. Therefore insn
bundling in this function is implemented by using DFA
- (deterministic finite automata). We follows all possible insn
+ (deterministic finite automata). We follow all possible insn
sequences by inserting 0-2 nops (that is what the NDFA describe for
insn scheduling) before/after each insn being bundled. We know the
start of simulated processor cycle from insn scheduling (insn
@@ -6827,7 +7772,7 @@ get_next_important_insn (rtx insn, rtx tail)
by structure bundle_state (see above). If we generate the same
bundle state (key is automaton state after issuing the insns and
nops for it), we reuse already generated one. As consequence we
- reject some decisions which can not improve the solution and
+ reject some decisions which cannot improve the solution and
reduce memory for the algorithm.
When we reach the end of EBB (extended basic block), we choose the
@@ -6866,7 +7811,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
initiate_bundle_state_table ();
index_to_bundle_states = xmalloc ((insn_num + 2)
* sizeof (struct bundle_state *));
- /* First (forward) pass -- generation of bundle states. */
+ /* First (forward) pass -- generation of bundle states. */
curr_state = get_free_bundle_state ();
curr_state->insn = NULL;
curr_state->before_nops_num = 0;
@@ -6903,16 +7848,15 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
break;
}
}
- /* Froward pass: generation of bundle states. */
+ /* Forward pass: generation of bundle states. */
for (insn = get_next_important_insn (NEXT_INSN (prev_head_insn), tail);
insn != NULL_RTX;
insn = next_insn)
{
- if (!INSN_P (insn)
- || ia64_safe_itanium_class (insn) == ITANIUM_CLASS_IGNORE
- || GET_CODE (PATTERN (insn)) == USE
- || GET_CODE (PATTERN (insn)) == CLOBBER)
- abort ();
+ gcc_assert (INSN_P (insn)
+ && ia64_safe_itanium_class (insn) != ITANIUM_CLASS_IGNORE
+ && GET_CODE (PATTERN (insn)) != USE
+ && GET_CODE (PATTERN (insn)) != CLOBBER);
type = ia64_safe_type (insn);
next_insn = get_next_important_insn (NEXT_INSN (insn), tail);
insn_num++;
@@ -6952,8 +7896,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
issue_nops_and_insn (curr_state, 0, insn, bundle_end_p,
only_bundle_end_p);
}
- if (index_to_bundle_states [insn_num] == NULL)
- abort ();
+ gcc_assert (index_to_bundle_states [insn_num]);
for (curr_state = index_to_bundle_states [insn_num];
curr_state != NULL;
curr_state = curr_state->next)
@@ -6986,10 +7929,10 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
INSN_UID (insn));
}
}
- if (index_to_bundle_states [insn_num] == NULL)
- /* We should find a solution because the 2nd insn scheduling has
- found one. */
- abort ();
+
+ /* We should find a solution because the 2nd insn scheduling has
+ found one. */
+ gcc_assert (index_to_bundle_states [insn_num]);
/* Find a state corresponding to the best insn sequence. */
best_state = NULL;
for (curr_state = index_to_bundle_states [insn_num];
@@ -7067,8 +8010,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
if (max_pos > 3 && template1 < 0)
/* It may happen when we have the stop inside a bundle. */
{
- if (pos > 3)
- abort ();
+ gcc_assert (pos <= 3);
template1 = get_template (curr_state->dfa_state, 3);
pos += 3;
}
@@ -7079,16 +8021,13 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
nop = gen_nop ();
emit_insn_after (nop, insn);
pos--;
- if (pos < 0)
- abort ();
+ gcc_assert (pos >= 0);
if (pos % 3 == 0)
{
/* We are at the start of a bundle: emit the template
(it should be defined). */
- if (template0 < 0)
- abort ();
- b = gen_bundle_selector (GEN_INT (template0));
- ia64_emit_insn_before (b, nop);
+ gcc_assert (template0 >= 0);
+ ia64_add_bundle_selector_before (template0, nop);
/* If we have two bundle window, we make one bundle
rotation. Otherwise template0 will be undefined
(negative value). */
@@ -7105,8 +8044,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
/* Long insn takes 2 slots. */
if (ia64_safe_type (insn) == TYPE_L)
pos--;
- if (pos < 0)
- abort ();
+ gcc_assert (pos >= 0);
if (pos % 3 == 0
&& INSN_CODE (insn) != CODE_FOR_insn_group_barrier
&& GET_CODE (PATTERN (insn)) != ASM_INPUT
@@ -7114,13 +8052,11 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
{
/* The current insn is at the bundle start: emit the
template. */
- if (template0 < 0)
- abort ();
- b = gen_bundle_selector (GEN_INT (template0));
- ia64_emit_insn_before (b, insn);
+ gcc_assert (template0 >= 0);
+ ia64_add_bundle_selector_before (template0, insn);
b = PREV_INSN (insn);
insn = b;
- /* See comment above in analogous place for emiting nops
+ /* See comment above in analogous place for emitting nops
after the insn. */
template0 = template1;
template1 = -1;
@@ -7133,16 +8069,13 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
nop = PREV_INSN (insn);
insn = nop;
pos--;
- if (pos < 0)
- abort ();
+ gcc_assert (pos >= 0);
if (pos % 3 == 0)
{
- /* See comment above in analogous place for emiting nops
+ /* See comment above in analogous place for emitting nops
after the insn. */
- if (template0 < 0)
- abort ();
- b = gen_bundle_selector (GEN_INT (template0));
- ia64_emit_insn_before (b, insn);
+ gcc_assert (template0 >= 0);
+ ia64_add_bundle_selector_before (template0, insn);
b = PREV_INSN (insn);
insn = b;
template0 = template1;
@@ -7160,11 +8093,10 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
insn != NULL_RTX;
insn = next_insn)
{
- if (!INSN_P (insn)
- || ia64_safe_itanium_class (insn) == ITANIUM_CLASS_IGNORE
- || GET_CODE (PATTERN (insn)) == USE
- || GET_CODE (PATTERN (insn)) == CLOBBER)
- abort ();
+ gcc_assert (INSN_P (insn)
+ && ia64_safe_itanium_class (insn) != ITANIUM_CLASS_IGNORE
+ && GET_CODE (PATTERN (insn)) != USE
+ && GET_CODE (PATTERN (insn)) != CLOBBER);
next_insn = get_next_important_insn (NEXT_INSN (insn), tail);
if (INSN_UID (insn) < clocks_length && add_cycles [INSN_UID (insn)])
/* We found a MM-insn which needs additional cycles. */
@@ -7191,7 +8123,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
onto MFI because we will add nops before the
insn. It simplifies subsequent code a lot. */
PATTERN (last)
- = gen_bundle_selector (GEN_INT (2)); /* -> MFI */
+ = gen_bundle_selector (const2_rtx); /* -> MFI */
break;
}
else if (recog_memoized (last) != CODE_FOR_insn_group_barrier
@@ -7202,9 +8134,9 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
bundle start, there are no more 3 insns in the bundle,
and the MM-insn is not at the start of bundle with
template MLX. */
- if ((pred_stop_p && n == 0) || n > 2
- || (template0 == 9 && n != 0))
- abort ();
+ gcc_assert ((!pred_stop_p || n)
+ && n <= 2
+ && (template0 != 9 || !n));
/* Put nops after the insn in the bundle. */
for (j = 3 - n; j > 0; j --)
ia64_emit_insn_before (gen_nop (), insn);
@@ -7219,7 +8151,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
for (i = add_cycles [INSN_UID (insn)]; i > 0; i--)
{
/* Insert "MII;" template. */
- ia64_emit_insn_before (gen_bundle_selector (GEN_INT (0)),
+ ia64_emit_insn_before (gen_bundle_selector (const0_rtx),
insn);
ia64_emit_insn_before (gen_nop (), insn);
ia64_emit_insn_before (gen_nop (), insn);
@@ -7237,8 +8169,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
}
/* Put the MM-insn in the same slot of a bundle with the
same template as the original one. */
- ia64_emit_insn_before (gen_bundle_selector (GEN_INT (template0)),
- insn);
+ ia64_add_bundle_selector_before (template0, insn);
/* To put the insn in the same slot, add necessary number
of nops. */
for (j = n; j > 0; j --)
@@ -7318,7 +8249,7 @@ final_emit_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
need_barrier_p = 0;
prev_insn = NULL_RTX;
}
- else if (need_barrier_p || group_barrier_needed_p (insn))
+ else if (need_barrier_p || group_barrier_needed (insn))
{
if (TARGET_EARLY_STOP_BITS)
{
@@ -7342,7 +8273,7 @@ final_emit_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
last != insn;
last = NEXT_INSN (last))
if (INSN_P (last))
- group_barrier_needed_p (last);
+ group_barrier_needed (last);
}
else
{
@@ -7350,7 +8281,7 @@ final_emit_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
insn);
init_insn_group_barriers ();
}
- group_barrier_needed_p (insn);
+ group_barrier_needed (insn);
prev_insn = NULL_RTX;
}
else if (recog_memoized (insn) >= 0)
@@ -7364,16 +8295,7 @@ final_emit_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
-/* If the following function returns TRUE, we will use the the DFA
- insn scheduler. */
-
-static int
-ia64_use_dfa_pipeline_interface (void)
-{
- return 1;
-}
-
-/* If the following function returns TRUE, we will use the the DFA
+/* If the following function returns TRUE, we will use the DFA
insn scheduler. */
static int
@@ -7418,18 +8340,19 @@ ia64_st_address_bypass_p (rtx producer, rtx consumer)
{
rtx dest, reg, mem;
- if (producer == NULL_RTX || consumer == NULL_RTX)
- abort ();
+ gcc_assert (producer && consumer);
dest = ia64_single_set (producer);
- if (dest == NULL_RTX || (reg = SET_DEST (dest)) == NULL_RTX
- || (GET_CODE (reg) != REG && GET_CODE (reg) != SUBREG))
- abort ();
+ gcc_assert (dest);
+ reg = SET_DEST (dest);
+ gcc_assert (reg);
if (GET_CODE (reg) == SUBREG)
reg = SUBREG_REG (reg);
+ gcc_assert (GET_CODE (reg) == REG);
+
dest = ia64_single_set (consumer);
- if (dest == NULL_RTX || (mem = SET_DEST (dest)) == NULL_RTX
- || GET_CODE (mem) != MEM)
- abort ();
+ gcc_assert (dest);
+ mem = SET_DEST (dest);
+ gcc_assert (mem && GET_CODE (mem) == MEM);
return reg_mentioned_p (reg, mem);
}
@@ -7441,32 +8364,49 @@ ia64_ld_address_bypass_p (rtx producer, rtx consumer)
{
rtx dest, src, reg, mem;
- if (producer == NULL_RTX || consumer == NULL_RTX)
- abort ();
+ gcc_assert (producer && consumer);
dest = ia64_single_set (producer);
- if (dest == NULL_RTX || (reg = SET_DEST (dest)) == NULL_RTX
- || (GET_CODE (reg) != REG && GET_CODE (reg) != SUBREG))
- abort ();
+ gcc_assert (dest);
+ reg = SET_DEST (dest);
+ gcc_assert (reg);
if (GET_CODE (reg) == SUBREG)
reg = SUBREG_REG (reg);
+ gcc_assert (GET_CODE (reg) == REG);
+
src = ia64_single_set (consumer);
- if (src == NULL_RTX || (mem = SET_SRC (src)) == NULL_RTX)
- abort ();
+ gcc_assert (src);
+ mem = SET_SRC (src);
+ gcc_assert (mem);
+
if (GET_CODE (mem) == UNSPEC && XVECLEN (mem, 0) > 0)
mem = XVECEXP (mem, 0, 0);
+ else if (GET_CODE (mem) == IF_THEN_ELSE)
+ /* ??? Is this bypass necessary for ld.c? */
+ {
+ gcc_assert (XINT (XEXP (XEXP (mem, 0), 0), 1) == UNSPEC_LDCCLR);
+ mem = XEXP (mem, 1);
+ }
+
while (GET_CODE (mem) == SUBREG || GET_CODE (mem) == ZERO_EXTEND)
mem = XEXP (mem, 0);
+ if (GET_CODE (mem) == UNSPEC)
+ {
+ int c = XINT (mem, 1);
+
+ gcc_assert (c == UNSPEC_LDA || c == UNSPEC_LDS || c == UNSPEC_LDSA);
+ mem = XVECEXP (mem, 0, 0);
+ }
+
/* Note that LO_SUM is used for GOT loads. */
- if (GET_CODE (mem) != LO_SUM && GET_CODE (mem) != MEM)
- abort ();
+ gcc_assert (GET_CODE (mem) == LO_SUM || GET_CODE (mem) == MEM);
return reg_mentioned_p (reg, mem);
}
/* The following function returns TRUE if INSN produces address for a
load/store insn. We will place such insns into M slot because it
- decreases its latency time. */
+ decreases its latency time. */
int
ia64_produce_address_p (rtx insn)
@@ -7497,8 +8437,10 @@ emit_predicate_relation_info (void)
&& NOTE_LINE_NUMBER (NEXT_INSN (head)) == NOTE_INSN_BASIC_BLOCK)
head = NEXT_INSN (head);
- for (r = PR_REG (0); r < PR_REG (64); r += 2)
- if (REGNO_REG_SET_P (bb->global_live_at_start, r))
+ /* Skip p0, which may be thought to be live due to (reg:DI p0)
+ grabbing the entire block of predicate registers. */
+ for (r = PR_REG (2); r < PR_REG (64); r += 2)
+ if (REGNO_REG_SET_P (bb->il.rtl->global_live_at_start, r))
{
rtx p = gen_rtx_REG (BImode, r);
rtx n = emit_insn_after (gen_pred_rel_mutex (p), head);
@@ -7554,7 +8496,7 @@ ia64_reorg (void)
non-optimizing bootstrap. */
update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES);
- if (ia64_flag_schedule_insns2)
+ if (optimize && ia64_flag_schedule_insns2)
{
timevar_push (TV_SCHED2);
ia64_final_schedule = 1;
@@ -7628,7 +8570,7 @@ ia64_reorg (void)
_1mfb_ = get_cpu_unit_code ("1b_1mfb.");
_1mlx_ = get_cpu_unit_code ("1b_1mlx.");
}
- schedule_ebbs (rtl_dump_file);
+ schedule_ebbs ();
finish_bundle_states ();
if (ia64_tune == PROCESSOR_ITANIUM)
{
@@ -7636,13 +8578,14 @@ ia64_reorg (void)
free (clocks);
}
free (stops_p);
- emit_insn_group_barriers (rtl_dump_file);
+ stops_p = NULL;
+ emit_insn_group_barriers (dump_file);
ia64_final_schedule = 0;
timevar_pop (TV_SCHED2);
}
else
- emit_all_insn_group_barriers (rtl_dump_file);
+ emit_all_insn_group_barriers (dump_file);
/* A call must not be the last instruction in a function, so that the
return address is still within the function, so that unwinding works
@@ -7672,8 +8615,14 @@ ia64_reorg (void)
}
}
- fixup_errata ();
emit_predicate_relation_info ();
+
+ if (ia64_flag_var_tracking)
+ {
+ timevar_push (TV_VAR_TRACKING);
+ variable_tracking_main ();
+ timevar_pop (TV_VAR_TRACKING);
+ }
}
/* Return true if REGNO is used by the epilogue. */
@@ -7766,8 +8715,13 @@ ia64_in_small_data_p (tree exp)
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)
+ || strncmp (section, ".sdata.", 7) == 0
+ || strncmp (section, ".gnu.linkonce.s.", 16) == 0
+ || strcmp (section, ".sbss") == 0
+ || strncmp (section, ".sbss.", 6) == 0
+ || strncmp (section, ".gnu.linkonce.sb.", 17) == 0)
return true;
}
else
@@ -7793,28 +8747,84 @@ static bool last_block;
static bool need_copy_state;
+#ifndef MAX_ARTIFICIAL_LABEL_BYTES
+# define MAX_ARTIFICIAL_LABEL_BYTES 30
+#endif
+
+/* Emit a debugging label after a call-frame-related insn. We'd
+ rather output the label right away, but we'd have to output it
+ after, not before, the instruction, and the instruction has not
+ been output yet. So we emit the label after the insn, delete it to
+ avoid introducing basic blocks, and mark it as preserved, such that
+ it is still output, given that it is referenced in debug info. */
+
+static const char *
+ia64_emit_deleted_label_after_insn (rtx insn)
+{
+ char label[MAX_ARTIFICIAL_LABEL_BYTES];
+ rtx lb = gen_label_rtx ();
+ rtx label_insn = emit_label_after (lb, insn);
+
+ LABEL_PRESERVE_P (lb) = 1;
+
+ delete_insn (label_insn);
+
+ ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (label_insn));
+
+ return xstrdup (label);
+}
+
+/* Define the CFA after INSN with the steady-state definition. */
+
+static void
+ia64_dwarf2out_def_steady_cfa (rtx insn)
+{
+ rtx fp = frame_pointer_needed
+ ? hard_frame_pointer_rtx
+ : stack_pointer_rtx;
+
+ dwarf2out_def_cfa
+ (ia64_emit_deleted_label_after_insn (insn),
+ REGNO (fp),
+ ia64_initial_elimination_offset
+ (REGNO (arg_pointer_rtx), REGNO (fp))
+ + ARG_POINTER_CFA_OFFSET (current_function_decl));
+}
+
+/* The generic dwarf2 frame debug info generator does not define a
+ separate region for the very end of the epilogue, so refrain from
+ doing so in the IA64-specific code as well. */
+
+#define IA64_CHANGE_CFA_IN_EPILOGUE 0
+
/* The function emits unwind directives for the start of an epilogue. */
static void
-process_epilogue (void)
+process_epilogue (FILE *asm_out_file, rtx insn, bool unwind, bool frame)
{
/* 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 (!last_block)
{
- fprintf (asm_out_file, "\t.label_state 1\n");
+ if (unwind)
+ fprintf (asm_out_file, "\t.label_state %d\n",
+ ++cfun->machine->state_num);
need_copy_state = true;
}
- fprintf (asm_out_file, "\t.restore sp\n");
+ if (unwind)
+ fprintf (asm_out_file, "\t.restore sp\n");
+ if (IA64_CHANGE_CFA_IN_EPILOGUE && frame)
+ dwarf2out_def_cfa (ia64_emit_deleted_label_after_insn (insn),
+ STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET);
}
/* This function processes a SET pattern looking for specific patterns
which result in emitting an assembly directive required for unwinding. */
static int
-process_set (FILE *asm_out_file, rtx pat)
+process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame)
{
rtx src = SET_SRC (pat);
rtx dest = SET_DEST (pat);
@@ -7830,8 +8840,11 @@ process_set (FILE *asm_out_file, rtx pat)
/* If this is the final destination for ar.pfs, then this must
be the alloc in the prologue. */
if (dest_regno == current_frame_info.reg_save_ar_pfs)
- fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
- ia64_dbx_register_number (dest_regno));
+ {
+ if (unwind)
+ fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
+ ia64_dbx_register_number (dest_regno));
+ }
else
{
/* This must be an alloc before a sibcall. We must drop the
@@ -7842,8 +8855,9 @@ process_set (FILE *asm_out_file, rtx pat)
sp" now. */
if (current_frame_info.total_size == 0 && !frame_pointer_needed)
/* if haven't done process_epilogue() yet, do it now */
- process_epilogue ();
- fprintf (asm_out_file, "\t.prologue\n");
+ process_epilogue (asm_out_file, insn, unwind, frame);
+ if (unwind)
+ fprintf (asm_out_file, "\t.prologue\n");
}
return 1;
}
@@ -7855,22 +8869,27 @@ process_set (FILE *asm_out_file, rtx pat)
{
rtx op0 = XEXP (src, 0);
rtx op1 = XEXP (src, 1);
- if (op0 == dest && GET_CODE (op1) == CONST_INT)
+
+ gcc_assert (op0 == dest && GET_CODE (op1) == CONST_INT);
+
+ if (INTVAL (op1) < 0)
{
- if (INTVAL (op1) < 0)
+ gcc_assert (!frame_pointer_needed);
+ if (unwind)
fprintf (asm_out_file, "\t.fframe "HOST_WIDE_INT_PRINT_DEC"\n",
-INTVAL (op1));
- else
- process_epilogue ();
+ if (frame)
+ ia64_dwarf2out_def_steady_cfa (insn);
}
else
- abort ();
+ process_epilogue (asm_out_file, insn, unwind, frame);
}
- else if (GET_CODE (src) == REG
- && REGNO (src) == HARD_FRAME_POINTER_REGNUM)
- process_epilogue ();
else
- abort ();
+ {
+ gcc_assert (GET_CODE (src) == REG
+ && REGNO (src) == HARD_FRAME_POINTER_REGNUM);
+ process_epilogue (asm_out_file, insn, unwind, frame);
+ }
return 1;
}
@@ -7885,44 +8904,46 @@ process_set (FILE *asm_out_file, rtx pat)
{
case BR_REG (0):
/* Saving return address pointer. */
- if (dest_regno != current_frame_info.reg_save_b0)
- abort ();
- fprintf (asm_out_file, "\t.save rp, r%d\n",
- ia64_dbx_register_number (dest_regno));
+ gcc_assert (dest_regno == current_frame_info.reg_save_b0);
+ if (unwind)
+ fprintf (asm_out_file, "\t.save rp, r%d\n",
+ ia64_dbx_register_number (dest_regno));
return 1;
case PR_REG (0):
- if (dest_regno != current_frame_info.reg_save_pr)
- abort ();
- fprintf (asm_out_file, "\t.save pr, r%d\n",
- ia64_dbx_register_number (dest_regno));
+ gcc_assert (dest_regno == current_frame_info.reg_save_pr);
+ if (unwind)
+ fprintf (asm_out_file, "\t.save pr, r%d\n",
+ ia64_dbx_register_number (dest_regno));
return 1;
case AR_UNAT_REGNUM:
- if (dest_regno != current_frame_info.reg_save_ar_unat)
- abort ();
- fprintf (asm_out_file, "\t.save ar.unat, r%d\n",
- ia64_dbx_register_number (dest_regno));
+ gcc_assert (dest_regno == current_frame_info.reg_save_ar_unat);
+ if (unwind)
+ fprintf (asm_out_file, "\t.save ar.unat, r%d\n",
+ ia64_dbx_register_number (dest_regno));
return 1;
case AR_LC_REGNUM:
- if (dest_regno != current_frame_info.reg_save_ar_lc)
- abort ();
- fprintf (asm_out_file, "\t.save ar.lc, r%d\n",
- ia64_dbx_register_number (dest_regno));
+ gcc_assert (dest_regno == current_frame_info.reg_save_ar_lc);
+ if (unwind)
+ fprintf (asm_out_file, "\t.save ar.lc, r%d\n",
+ ia64_dbx_register_number (dest_regno));
return 1;
case STACK_POINTER_REGNUM:
- if (dest_regno != HARD_FRAME_POINTER_REGNUM
- || ! frame_pointer_needed)
- abort ();
- fprintf (asm_out_file, "\t.vframe r%d\n",
- ia64_dbx_register_number (dest_regno));
+ gcc_assert (dest_regno == HARD_FRAME_POINTER_REGNUM
+ && frame_pointer_needed);
+ if (unwind)
+ fprintf (asm_out_file, "\t.vframe r%d\n",
+ ia64_dbx_register_number (dest_regno));
+ if (frame)
+ ia64_dwarf2out_def_steady_cfa (insn);
return 1;
default:
/* Everything else should indicate being stored to memory. */
- abort ();
+ gcc_unreachable ();
}
}
@@ -7938,64 +8959,65 @@ process_set (FILE *asm_out_file, rtx pat)
base = XEXP (dest, 0);
off = 0;
}
- else if (GET_CODE (XEXP (dest, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT)
+ else
{
+ gcc_assert (GET_CODE (XEXP (dest, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT);
base = XEXP (XEXP (dest, 0), 0);
off = INTVAL (XEXP (XEXP (dest, 0), 1));
}
- else
- abort ();
if (base == hard_frame_pointer_rtx)
{
saveop = ".savepsp";
off = - off;
}
- else if (base == stack_pointer_rtx)
- saveop = ".savesp";
else
- abort ();
+ {
+ gcc_assert (base == stack_pointer_rtx);
+ saveop = ".savesp";
+ }
src_regno = REGNO (src);
switch (src_regno)
{
case BR_REG (0):
- if (current_frame_info.reg_save_b0 != 0)
- abort ();
- fprintf (asm_out_file, "\t%s rp, %ld\n", saveop, off);
+ gcc_assert (!current_frame_info.reg_save_b0);
+ if (unwind)
+ fprintf (asm_out_file, "\t%s rp, %ld\n", saveop, off);
return 1;
case PR_REG (0):
- if (current_frame_info.reg_save_pr != 0)
- abort ();
- fprintf (asm_out_file, "\t%s pr, %ld\n", saveop, off);
+ gcc_assert (!current_frame_info.reg_save_pr);
+ if (unwind)
+ fprintf (asm_out_file, "\t%s pr, %ld\n", saveop, off);
return 1;
case AR_LC_REGNUM:
- if (current_frame_info.reg_save_ar_lc != 0)
- abort ();
- fprintf (asm_out_file, "\t%s ar.lc, %ld\n", saveop, off);
+ gcc_assert (!current_frame_info.reg_save_ar_lc);
+ if (unwind)
+ fprintf (asm_out_file, "\t%s ar.lc, %ld\n", saveop, off);
return 1;
case AR_PFS_REGNUM:
- if (current_frame_info.reg_save_ar_pfs != 0)
- abort ();
- fprintf (asm_out_file, "\t%s ar.pfs, %ld\n", saveop, off);
+ gcc_assert (!current_frame_info.reg_save_ar_pfs);
+ if (unwind)
+ fprintf (asm_out_file, "\t%s ar.pfs, %ld\n", saveop, off);
return 1;
case AR_UNAT_REGNUM:
- if (current_frame_info.reg_save_ar_unat != 0)
- abort ();
- fprintf (asm_out_file, "\t%s ar.unat, %ld\n", saveop, off);
+ gcc_assert (!current_frame_info.reg_save_ar_unat);
+ if (unwind)
+ fprintf (asm_out_file, "\t%s ar.unat, %ld\n", saveop, off);
return 1;
case GR_REG (4):
case GR_REG (5):
case GR_REG (6):
case GR_REG (7):
- fprintf (asm_out_file, "\t.save.g 0x%x\n",
- 1 << (src_regno - GR_REG (4)));
+ if (unwind)
+ fprintf (asm_out_file, "\t.save.g 0x%x\n",
+ 1 << (src_regno - GR_REG (4)));
return 1;
case BR_REG (1):
@@ -8003,24 +9025,27 @@ process_set (FILE *asm_out_file, rtx pat)
case BR_REG (3):
case BR_REG (4):
case BR_REG (5):
- fprintf (asm_out_file, "\t.save.b 0x%x\n",
- 1 << (src_regno - BR_REG (1)));
+ if (unwind)
+ fprintf (asm_out_file, "\t.save.b 0x%x\n",
+ 1 << (src_regno - BR_REG (1)));
return 1;
case FR_REG (2):
case FR_REG (3):
case FR_REG (4):
case FR_REG (5):
- fprintf (asm_out_file, "\t.save.f 0x%x\n",
- 1 << (src_regno - FR_REG (2)));
+ if (unwind)
+ fprintf (asm_out_file, "\t.save.f 0x%x\n",
+ 1 << (src_regno - FR_REG (2)));
return 1;
case FR_REG (16): case FR_REG (17): case FR_REG (18): case FR_REG (19):
case FR_REG (20): case FR_REG (21): case FR_REG (22): case FR_REG (23):
case FR_REG (24): case FR_REG (25): case FR_REG (26): case FR_REG (27):
case FR_REG (28): case FR_REG (29): case FR_REG (30): case FR_REG (31):
- fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n",
- 1 << (src_regno - FR_REG (12)));
+ if (unwind)
+ fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n",
+ 1 << (src_regno - FR_REG (12)));
return 1;
default:
@@ -8037,8 +9062,11 @@ process_set (FILE *asm_out_file, rtx pat)
void
process_for_unwind_directive (FILE *asm_out_file, rtx insn)
{
- if (flag_unwind_tables
- || (flag_exceptions && !USING_SJLJ_EXCEPTIONS))
+ bool unwind = (flag_unwind_tables
+ || (flag_exceptions && !USING_SJLJ_EXCEPTIONS));
+ bool frame = dwarf2out_do_frame ();
+
+ if (unwind || frame)
{
rtx pat;
@@ -8050,8 +9078,14 @@ process_for_unwind_directive (FILE *asm_out_file, rtx insn)
/* 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");
+ if (unwind)
+ {
+ fprintf (asm_out_file, "\t.body\n");
+ fprintf (asm_out_file, "\t.copy_state %d\n",
+ cfun->machine->state_num);
+ }
+ if (IA64_CHANGE_CFA_IN_EPILOGUE && frame)
+ ia64_dwarf2out_def_steady_cfa (insn);
need_copy_state = false;
}
}
@@ -8068,7 +9102,7 @@ process_for_unwind_directive (FILE *asm_out_file, rtx insn)
switch (GET_CODE (pat))
{
case SET:
- process_set (asm_out_file, pat);
+ process_set (asm_out_file, pat, insn, unwind, frame);
break;
case PARALLEL:
@@ -8079,77 +9113,39 @@ process_for_unwind_directive (FILE *asm_out_file, rtx insn)
{
rtx x = XVECEXP (pat, 0, par_index);
if (GET_CODE (x) == SET)
- process_set (asm_out_file, x);
+ process_set (asm_out_file, x, insn, unwind, frame);
}
break;
}
default:
- abort ();
+ gcc_unreachable ();
}
}
}
+enum ia64_builtins
+{
+ IA64_BUILTIN_BSP,
+ IA64_BUILTIN_FLUSHRS
+};
+
void
ia64_init_builtins (void)
{
- tree psi_type_node = build_pointer_type (integer_type_node);
- tree pdi_type_node = build_pointer_type (long_integer_type_node);
-
- /* __sync_val_compare_and_swap_si, __sync_bool_compare_and_swap_si */
- tree si_ftype_psi_si_si
- = build_function_type_list (integer_type_node,
- psi_type_node, integer_type_node,
- integer_type_node, NULL_TREE);
-
- /* __sync_val_compare_and_swap_di */
- tree di_ftype_pdi_di_di
- = build_function_type_list (long_integer_type_node,
- pdi_type_node, long_integer_type_node,
- long_integer_type_node, NULL_TREE);
- /* __sync_bool_compare_and_swap_di */
- tree si_ftype_pdi_di_di
- = build_function_type_list (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, void_list_node);
-
- /* __sync_lock_test_and_set_si */
- tree si_ftype_psi_si
- = 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_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_list (void_type_node, psi_type_node, NULL_TREE);
-
- /* __sync_lock_release_di */
- tree void_ftype_pdi
- = build_function_type_list (void_type_node, pdi_type_node, NULL_TREE);
-
tree fpreg_type;
tree float80_type;
/* The __fpreg type. */
fpreg_type = make_node (REAL_TYPE);
- /* ??? The back end should know to load/save __fpreg variables using
- the ldf.fill and stf.spill instructions. */
- TYPE_PRECISION (fpreg_type) = 96;
+ TYPE_PRECISION (fpreg_type) = 82;
layout_type (fpreg_type);
(*lang_hooks.types.register_builtin_type) (fpreg_type, "__fpreg");
/* The __float80 type. */
float80_type = make_node (REAL_TYPE);
- TYPE_PRECISION (float80_type) = 96;
+ TYPE_PRECISION (float80_type) = 80;
layout_type (float80_type);
(*lang_hooks.types.register_builtin_type) (float80_type, "__float80");
@@ -8166,29 +9162,9 @@ ia64_init_builtins (void)
(*lang_hooks.types.register_builtin_type) (long_double_type_node,
"__float128");
-#define def_builtin(name, type, code) \
- 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);
- def_builtin ("__sync_val_compare_and_swap_di", di_ftype_pdi_di_di,
- IA64_BUILTIN_VAL_COMPARE_AND_SWAP_DI);
- def_builtin ("__sync_bool_compare_and_swap_si", si_ftype_psi_si_si,
- IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_SI);
- def_builtin ("__sync_bool_compare_and_swap_di", si_ftype_pdi_di_di,
- IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_DI);
-
- def_builtin ("__sync_synchronize", void_ftype_void,
- IA64_BUILTIN_SYNCHRONIZE);
-
- def_builtin ("__sync_lock_test_and_set_si", si_ftype_psi_si,
- IA64_BUILTIN_LOCK_TEST_AND_SET_SI);
- def_builtin ("__sync_lock_test_and_set_di", di_ftype_pdi_di,
- IA64_BUILTIN_LOCK_TEST_AND_SET_DI);
- def_builtin ("__sync_lock_release_si", void_ftype_psi,
- IA64_BUILTIN_LOCK_RELEASE_SI);
- def_builtin ("__sync_lock_release_di", void_ftype_pdi,
- IA64_BUILTIN_LOCK_RELEASE_DI);
+#define def_builtin(name, type, code) \
+ lang_hooks.builtin_function ((name), (type), (code), BUILT_IN_MD, \
+ NULL, NULL_TREE)
def_builtin ("__builtin_ia64_bsp",
build_function_type (ptr_type_node, void_list_node),
@@ -8198,322 +9174,9 @@ ia64_init_builtins (void)
build_function_type (void_type_node, void_list_node),
IA64_BUILTIN_FLUSHRS);
- def_builtin ("__sync_fetch_and_add_si", si_ftype_psi_si,
- IA64_BUILTIN_FETCH_AND_ADD_SI);
- def_builtin ("__sync_fetch_and_sub_si", si_ftype_psi_si,
- IA64_BUILTIN_FETCH_AND_SUB_SI);
- def_builtin ("__sync_fetch_and_or_si", si_ftype_psi_si,
- IA64_BUILTIN_FETCH_AND_OR_SI);
- def_builtin ("__sync_fetch_and_and_si", si_ftype_psi_si,
- IA64_BUILTIN_FETCH_AND_AND_SI);
- def_builtin ("__sync_fetch_and_xor_si", si_ftype_psi_si,
- IA64_BUILTIN_FETCH_AND_XOR_SI);
- def_builtin ("__sync_fetch_and_nand_si", si_ftype_psi_si,
- IA64_BUILTIN_FETCH_AND_NAND_SI);
-
- def_builtin ("__sync_add_and_fetch_si", si_ftype_psi_si,
- IA64_BUILTIN_ADD_AND_FETCH_SI);
- def_builtin ("__sync_sub_and_fetch_si", si_ftype_psi_si,
- IA64_BUILTIN_SUB_AND_FETCH_SI);
- def_builtin ("__sync_or_and_fetch_si", si_ftype_psi_si,
- IA64_BUILTIN_OR_AND_FETCH_SI);
- def_builtin ("__sync_and_and_fetch_si", si_ftype_psi_si,
- IA64_BUILTIN_AND_AND_FETCH_SI);
- def_builtin ("__sync_xor_and_fetch_si", si_ftype_psi_si,
- IA64_BUILTIN_XOR_AND_FETCH_SI);
- def_builtin ("__sync_nand_and_fetch_si", si_ftype_psi_si,
- IA64_BUILTIN_NAND_AND_FETCH_SI);
-
- def_builtin ("__sync_fetch_and_add_di", di_ftype_pdi_di,
- IA64_BUILTIN_FETCH_AND_ADD_DI);
- def_builtin ("__sync_fetch_and_sub_di", di_ftype_pdi_di,
- IA64_BUILTIN_FETCH_AND_SUB_DI);
- def_builtin ("__sync_fetch_and_or_di", di_ftype_pdi_di,
- IA64_BUILTIN_FETCH_AND_OR_DI);
- def_builtin ("__sync_fetch_and_and_di", di_ftype_pdi_di,
- IA64_BUILTIN_FETCH_AND_AND_DI);
- def_builtin ("__sync_fetch_and_xor_di", di_ftype_pdi_di,
- IA64_BUILTIN_FETCH_AND_XOR_DI);
- def_builtin ("__sync_fetch_and_nand_di", di_ftype_pdi_di,
- IA64_BUILTIN_FETCH_AND_NAND_DI);
-
- def_builtin ("__sync_add_and_fetch_di", di_ftype_pdi_di,
- IA64_BUILTIN_ADD_AND_FETCH_DI);
- def_builtin ("__sync_sub_and_fetch_di", di_ftype_pdi_di,
- IA64_BUILTIN_SUB_AND_FETCH_DI);
- def_builtin ("__sync_or_and_fetch_di", di_ftype_pdi_di,
- IA64_BUILTIN_OR_AND_FETCH_DI);
- def_builtin ("__sync_and_and_fetch_di", di_ftype_pdi_di,
- IA64_BUILTIN_AND_AND_FETCH_DI);
- def_builtin ("__sync_xor_and_fetch_di", di_ftype_pdi_di,
- IA64_BUILTIN_XOR_AND_FETCH_DI);
- def_builtin ("__sync_nand_and_fetch_di", di_ftype_pdi_di,
- IA64_BUILTIN_NAND_AND_FETCH_DI);
-
#undef def_builtin
}
-/* Expand fetch_and_op intrinsics. The basic code sequence is:
-
- mf
- tmp = [ptr];
- do {
- ret = tmp;
- ar.ccv = tmp;
- tmp <op>= value;
- cmpxchgsz.acq tmp = [ptr], tmp
- } while (tmp != ret)
-*/
-
-static rtx
-ia64_expand_fetch_and_op (optab binoptab, enum machine_mode mode,
- tree arglist, rtx target)
-{
- rtx ret, label, tmp, ccv, insn, mem, value;
- tree arg0, arg1;
-
- 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));
- MEM_VOLATILE_P (mem) = 1;
-
- if (target && register_operand (target, mode))
- ret = target;
- else
- ret = gen_reg_rtx (mode);
-
- emit_insn (gen_mf ());
-
- /* Special case for fetchadd instructions. */
- if (binoptab == add_optab && fetchadd_operand (value, VOIDmode))
- {
- if (mode == SImode)
- insn = gen_fetchadd_acq_si (ret, mem, value);
- else
- insn = gen_fetchadd_acq_di (ret, mem, value);
- emit_insn (insn);
- return ret;
- }
-
- tmp = gen_reg_rtx (mode);
- /* ar.ccv must always be loaded with a zero-extended DImode value. */
- ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
- emit_move_insn (tmp, mem);
-
- label = gen_label_rtx ();
- emit_label (label);
- emit_move_insn (ret, tmp);
- convert_move (ccv, tmp, /*unsignedp=*/1);
-
- /* Perform the specific operation. Special case NAND by noticing
- one_cmpl_optab instead. */
- if (binoptab == one_cmpl_optab)
- {
- tmp = expand_unop (mode, binoptab, tmp, NULL, OPTAB_WIDEN);
- binoptab = and_optab;
- }
- tmp = expand_binop (mode, binoptab, tmp, value, tmp, 1, OPTAB_WIDEN);
-
- if (mode == SImode)
- insn = gen_cmpxchg_acq_si (tmp, mem, tmp, ccv);
- else
- insn = gen_cmpxchg_acq_di (tmp, mem, tmp, ccv);
- emit_insn (insn);
-
- emit_cmp_and_jump_insns (tmp, ret, NE, 0, mode, 1, label);
-
- return ret;
-}
-
-/* Expand op_and_fetch intrinsics. The basic code sequence is:
-
- mf
- tmp = [ptr];
- do {
- old = tmp;
- ar.ccv = tmp;
- ret = tmp <op> value;
- cmpxchgsz.acq tmp = [ptr], ret
- } while (tmp != old)
-*/
-
-static rtx
-ia64_expand_op_and_fetch (optab binoptab, enum machine_mode mode,
- tree arglist, rtx target)
-{
- rtx old, label, tmp, ret, ccv, insn, mem, value;
- tree arg0, arg1;
-
- 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));
- MEM_VOLATILE_P (mem) = 1;
-
- if (target && ! register_operand (target, mode))
- target = NULL_RTX;
-
- emit_insn (gen_mf ());
- tmp = gen_reg_rtx (mode);
- old = gen_reg_rtx (mode);
- /* ar.ccv must always be loaded with a zero-extended DImode value. */
- ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
-
- emit_move_insn (tmp, mem);
-
- label = gen_label_rtx ();
- emit_label (label);
- emit_move_insn (old, tmp);
- convert_move (ccv, tmp, /*unsignedp=*/1);
-
- /* Perform the specific operation. Special case NAND by noticing
- one_cmpl_optab instead. */
- if (binoptab == one_cmpl_optab)
- {
- tmp = expand_unop (mode, binoptab, tmp, NULL, OPTAB_WIDEN);
- binoptab = and_optab;
- }
- ret = expand_binop (mode, binoptab, tmp, value, target, 1, OPTAB_WIDEN);
-
- if (mode == SImode)
- insn = gen_cmpxchg_acq_si (tmp, mem, ret, ccv);
- else
- insn = gen_cmpxchg_acq_di (tmp, mem, ret, ccv);
- emit_insn (insn);
-
- emit_cmp_and_jump_insns (tmp, old, NE, 0, mode, 1, label);
-
- return ret;
-}
-
-/* Expand val_ and bool_compare_and_swap. For val_ we want:
-
- ar.ccv = oldval
- mf
- cmpxchgsz.acq ret = [ptr], newval, ar.ccv
- return ret
-
- For bool_ it's the same except return ret == oldval.
-*/
-
-static rtx
-ia64_expand_compare_and_swap (enum machine_mode rmode, enum machine_mode mode,
- int boolp, tree arglist, rtx target)
-{
- tree arg0, arg1, arg2;
- rtx mem, old, new, ccv, tmp, insn;
-
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- 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 (ptr_mode, mem));
- MEM_VOLATILE_P (mem) = 1;
-
- if (GET_MODE (old) != mode)
- old = convert_to_mode (mode, old, /*unsignedp=*/1);
- if (GET_MODE (new) != mode)
- new = convert_to_mode (mode, new, /*unsignedp=*/1);
-
- if (! register_operand (old, mode))
- old = copy_to_mode_reg (mode, old);
- if (! register_operand (new, mode))
- new = copy_to_mode_reg (mode, new);
-
- if (! boolp && target && register_operand (target, mode))
- tmp = target;
- else
- tmp = gen_reg_rtx (mode);
-
- ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
- convert_move (ccv, old, /*unsignedp=*/1);
- emit_insn (gen_mf ());
- if (mode == SImode)
- insn = gen_cmpxchg_acq_si (tmp, mem, new, ccv);
- else
- insn = gen_cmpxchg_acq_di (tmp, mem, new, ccv);
- emit_insn (insn);
-
- if (boolp)
- {
- if (! target)
- target = gen_reg_rtx (rmode);
- return emit_store_flag_force (target, EQ, tmp, old, mode, 1, 1);
- }
- else
- return tmp;
-}
-
-/* Expand lock_test_and_set. I.e. `xchgsz ret = [ptr], new'. */
-
-static rtx
-ia64_expand_lock_test_and_set (enum machine_mode mode, tree arglist,
- rtx target)
-{
- tree arg0, arg1;
- rtx mem, new, ret, insn;
-
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- mem = expand_expr (arg0, NULL_RTX, ptr_mode, 0);
- new = expand_expr (arg1, NULL_RTX, mode, 0);
-
- 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);
-
- if (target && register_operand (target, mode))
- ret = target;
- else
- ret = gen_reg_rtx (mode);
-
- if (mode == SImode)
- insn = gen_xchgsi (ret, mem, new);
- else
- insn = gen_xchgdi (ret, mem, new);
- emit_insn (insn);
-
- return ret;
-}
-
-/* Expand lock_release. I.e. `stsz.rel [ptr] = r0'. */
-
-static rtx
-ia64_expand_lock_release (enum machine_mode mode, tree arglist,
- rtx target ATTRIBUTE_UNUSED)
-{
- tree arg0;
- rtx mem;
-
- arg0 = TREE_VALUE (arglist);
- mem = expand_expr (arg0, NULL_RTX, ptr_mode, 0);
-
- mem = gen_rtx_MEM (mode, force_reg (ptr_mode, mem));
- MEM_VOLATILE_P (mem) = 1;
-
- emit_move_insn (mem, const0_rtx);
-
- return const0_rtx;
-}
-
rtx
ia64_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
enum machine_mode mode ATTRIBUTE_UNUSED,
@@ -8521,89 +9184,9 @@ ia64_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
{
tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
- tree arglist = TREE_OPERAND (exp, 1);
- enum machine_mode rmode = VOIDmode;
switch (fcode)
{
- case IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_SI:
- case IA64_BUILTIN_VAL_COMPARE_AND_SWAP_SI:
- mode = SImode;
- rmode = SImode;
- break;
-
- case IA64_BUILTIN_LOCK_TEST_AND_SET_SI:
- case IA64_BUILTIN_LOCK_RELEASE_SI:
- case IA64_BUILTIN_FETCH_AND_ADD_SI:
- case IA64_BUILTIN_FETCH_AND_SUB_SI:
- case IA64_BUILTIN_FETCH_AND_OR_SI:
- case IA64_BUILTIN_FETCH_AND_AND_SI:
- case IA64_BUILTIN_FETCH_AND_XOR_SI:
- case IA64_BUILTIN_FETCH_AND_NAND_SI:
- case IA64_BUILTIN_ADD_AND_FETCH_SI:
- case IA64_BUILTIN_SUB_AND_FETCH_SI:
- case IA64_BUILTIN_OR_AND_FETCH_SI:
- case IA64_BUILTIN_AND_AND_FETCH_SI:
- case IA64_BUILTIN_XOR_AND_FETCH_SI:
- case IA64_BUILTIN_NAND_AND_FETCH_SI:
- mode = SImode;
- break;
-
- case IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_DI:
- mode = DImode;
- rmode = SImode;
- break;
-
- case IA64_BUILTIN_VAL_COMPARE_AND_SWAP_DI:
- mode = DImode;
- rmode = DImode;
- break;
-
- case IA64_BUILTIN_LOCK_TEST_AND_SET_DI:
- case IA64_BUILTIN_LOCK_RELEASE_DI:
- case IA64_BUILTIN_FETCH_AND_ADD_DI:
- case IA64_BUILTIN_FETCH_AND_SUB_DI:
- case IA64_BUILTIN_FETCH_AND_OR_DI:
- case IA64_BUILTIN_FETCH_AND_AND_DI:
- case IA64_BUILTIN_FETCH_AND_XOR_DI:
- case IA64_BUILTIN_FETCH_AND_NAND_DI:
- case IA64_BUILTIN_ADD_AND_FETCH_DI:
- case IA64_BUILTIN_SUB_AND_FETCH_DI:
- case IA64_BUILTIN_OR_AND_FETCH_DI:
- case IA64_BUILTIN_AND_AND_FETCH_DI:
- case IA64_BUILTIN_XOR_AND_FETCH_DI:
- case IA64_BUILTIN_NAND_AND_FETCH_DI:
- mode = DImode;
- break;
-
- default:
- break;
- }
-
- switch (fcode)
- {
- case IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_SI:
- case IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_DI:
- return ia64_expand_compare_and_swap (rmode, mode, 1, arglist,
- target);
-
- case IA64_BUILTIN_VAL_COMPARE_AND_SWAP_SI:
- case IA64_BUILTIN_VAL_COMPARE_AND_SWAP_DI:
- return ia64_expand_compare_and_swap (rmode, mode, 0, arglist,
- target);
-
- case IA64_BUILTIN_SYNCHRONIZE:
- emit_insn (gen_mf ());
- return const0_rtx;
-
- case IA64_BUILTIN_LOCK_TEST_AND_SET_SI:
- case IA64_BUILTIN_LOCK_TEST_AND_SET_DI:
- return ia64_expand_lock_test_and_set (mode, arglist, target);
-
- case IA64_BUILTIN_LOCK_RELEASE_SI:
- case IA64_BUILTIN_LOCK_RELEASE_DI:
- return ia64_expand_lock_release (mode, arglist, target);
-
case IA64_BUILTIN_BSP:
if (! target || ! register_operand (target, DImode))
target = gen_reg_rtx (DImode);
@@ -8617,54 +9200,6 @@ ia64_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
emit_insn (gen_flushrs ());
return const0_rtx;
- case IA64_BUILTIN_FETCH_AND_ADD_SI:
- case IA64_BUILTIN_FETCH_AND_ADD_DI:
- return ia64_expand_fetch_and_op (add_optab, mode, arglist, target);
-
- case IA64_BUILTIN_FETCH_AND_SUB_SI:
- case IA64_BUILTIN_FETCH_AND_SUB_DI:
- return ia64_expand_fetch_and_op (sub_optab, mode, arglist, target);
-
- case IA64_BUILTIN_FETCH_AND_OR_SI:
- case IA64_BUILTIN_FETCH_AND_OR_DI:
- return ia64_expand_fetch_and_op (ior_optab, mode, arglist, target);
-
- case IA64_BUILTIN_FETCH_AND_AND_SI:
- case IA64_BUILTIN_FETCH_AND_AND_DI:
- return ia64_expand_fetch_and_op (and_optab, mode, arglist, target);
-
- case IA64_BUILTIN_FETCH_AND_XOR_SI:
- case IA64_BUILTIN_FETCH_AND_XOR_DI:
- return ia64_expand_fetch_and_op (xor_optab, mode, arglist, target);
-
- case IA64_BUILTIN_FETCH_AND_NAND_SI:
- case IA64_BUILTIN_FETCH_AND_NAND_DI:
- return ia64_expand_fetch_and_op (one_cmpl_optab, mode, arglist, target);
-
- case IA64_BUILTIN_ADD_AND_FETCH_SI:
- case IA64_BUILTIN_ADD_AND_FETCH_DI:
- return ia64_expand_op_and_fetch (add_optab, mode, arglist, target);
-
- case IA64_BUILTIN_SUB_AND_FETCH_SI:
- case IA64_BUILTIN_SUB_AND_FETCH_DI:
- return ia64_expand_op_and_fetch (sub_optab, mode, arglist, target);
-
- case IA64_BUILTIN_OR_AND_FETCH_SI:
- case IA64_BUILTIN_OR_AND_FETCH_DI:
- return ia64_expand_op_and_fetch (ior_optab, mode, arglist, target);
-
- case IA64_BUILTIN_AND_AND_FETCH_SI:
- case IA64_BUILTIN_AND_AND_FETCH_DI:
- return ia64_expand_op_and_fetch (and_optab, mode, arglist, target);
-
- case IA64_BUILTIN_XOR_AND_FETCH_SI:
- case IA64_BUILTIN_XOR_AND_FETCH_DI:
- return ia64_expand_op_and_fetch (xor_optab, mode, arglist, target);
-
- case IA64_BUILTIN_NAND_AND_FETCH_SI:
- case IA64_BUILTIN_NAND_AND_FETCH_DI:
- return ia64_expand_op_and_fetch (one_cmpl_optab, mode, arglist, target);
-
default:
break;
}
@@ -8722,8 +9257,7 @@ ia64_hpux_file_end (void)
tree decl = p->decl;
tree id = DECL_ASSEMBLER_NAME (decl);
- if (!id)
- abort ();
+ gcc_assert (id);
if (!TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (id))
{
@@ -8740,19 +9274,72 @@ ia64_hpux_file_end (void)
extern_func_head = 0;
}
-/* Rename all the TFmode libfuncs using the HPUX conventions. */
+/* Set SImode div/mod functions, init_integral_libfuncs only initializes
+ modes of word_mode and larger. Rename the TFmode libfuncs using the
+ HPUX conventions. __divtf3 is used for XFmode. We need to keep it for
+ backward compatibility. */
static void
-ia64_hpux_init_libfuncs (void)
+ia64_init_libfuncs (void)
{
+ set_optab_libfunc (sdiv_optab, SImode, "__divsi3");
+ set_optab_libfunc (udiv_optab, SImode, "__udivsi3");
+ set_optab_libfunc (smod_optab, SImode, "__modsi3");
+ set_optab_libfunc (umod_optab, SImode, "__umodsi3");
+
set_optab_libfunc (add_optab, TFmode, "_U_Qfadd");
set_optab_libfunc (sub_optab, TFmode, "_U_Qfsub");
set_optab_libfunc (smul_optab, TFmode, "_U_Qfmpy");
set_optab_libfunc (sdiv_optab, TFmode, "_U_Qfdiv");
+ set_optab_libfunc (neg_optab, TFmode, "_U_Qfneg");
+
+ set_conv_libfunc (sext_optab, TFmode, SFmode, "_U_Qfcnvff_sgl_to_quad");
+ set_conv_libfunc (sext_optab, TFmode, DFmode, "_U_Qfcnvff_dbl_to_quad");
+ set_conv_libfunc (sext_optab, TFmode, XFmode, "_U_Qfcnvff_f80_to_quad");
+ set_conv_libfunc (trunc_optab, SFmode, TFmode, "_U_Qfcnvff_quad_to_sgl");
+ set_conv_libfunc (trunc_optab, DFmode, TFmode, "_U_Qfcnvff_quad_to_dbl");
+ set_conv_libfunc (trunc_optab, XFmode, TFmode, "_U_Qfcnvff_quad_to_f80");
+
+ set_conv_libfunc (sfix_optab, SImode, TFmode, "_U_Qfcnvfxt_quad_to_sgl");
+ set_conv_libfunc (sfix_optab, DImode, TFmode, "_U_Qfcnvfxt_quad_to_dbl");
+ set_conv_libfunc (sfix_optab, TImode, TFmode, "_U_Qfcnvfxt_quad_to_quad");
+ set_conv_libfunc (ufix_optab, SImode, TFmode, "_U_Qfcnvfxut_quad_to_sgl");
+ set_conv_libfunc (ufix_optab, DImode, TFmode, "_U_Qfcnvfxut_quad_to_dbl");
+
+ set_conv_libfunc (sfloat_optab, TFmode, SImode, "_U_Qfcnvxf_sgl_to_quad");
+ set_conv_libfunc (sfloat_optab, TFmode, DImode, "_U_Qfcnvxf_dbl_to_quad");
+ set_conv_libfunc (sfloat_optab, TFmode, TImode, "_U_Qfcnvxf_quad_to_quad");
+ /* HP-UX 11.23 libc does not have a function for unsigned
+ SImode-to-TFmode conversion. */
+ set_conv_libfunc (ufloat_optab, TFmode, DImode, "_U_Qfcnvxuf_dbl_to_quad");
+}
+
+/* Rename all the TFmode libfuncs using the HPUX conventions. */
+
+static void
+ia64_hpux_init_libfuncs (void)
+{
+ ia64_init_libfuncs ();
+
+ /* The HP SI millicode division and mod functions expect DI arguments.
+ By turning them off completely we avoid using both libgcc and the
+ non-standard millicode routines and use the HP DI millicode routines
+ instead. */
+
+ set_optab_libfunc (sdiv_optab, SImode, 0);
+ set_optab_libfunc (udiv_optab, SImode, 0);
+ set_optab_libfunc (smod_optab, SImode, 0);
+ set_optab_libfunc (umod_optab, SImode, 0);
+
+ set_optab_libfunc (sdiv_optab, DImode, "__milli_divI");
+ set_optab_libfunc (udiv_optab, DImode, "__milli_divU");
+ set_optab_libfunc (smod_optab, DImode, "__milli_remI");
+ set_optab_libfunc (umod_optab, DImode, "__milli_remU");
+
+ /* HP-UX libc has TF min/max/abs routines in it. */
set_optab_libfunc (smin_optab, TFmode, "_U_Qfmin");
set_optab_libfunc (smax_optab, TFmode, "_U_Qfmax");
set_optab_libfunc (abs_optab, TFmode, "_U_Qfabs");
- set_optab_libfunc (neg_optab, TFmode, "_U_Qfneg");
/* ia64_expand_compare uses this. */
cmptf_libfunc = init_one_libfunc ("_U_Qfcmp");
@@ -8764,21 +9351,6 @@ ia64_hpux_init_libfuncs (void)
set_optab_libfunc (ge_optab, TFmode, 0);
set_optab_libfunc (lt_optab, TFmode, 0);
set_optab_libfunc (le_optab, TFmode, 0);
-
- set_conv_libfunc (sext_optab, TFmode, SFmode, "_U_Qfcnvff_sgl_to_quad");
- set_conv_libfunc (sext_optab, TFmode, DFmode, "_U_Qfcnvff_dbl_to_quad");
- set_conv_libfunc (sext_optab, TFmode, XFmode, "_U_Qfcnvff_f80_to_quad");
- set_conv_libfunc (trunc_optab, SFmode, TFmode, "_U_Qfcnvff_quad_to_sgl");
- set_conv_libfunc (trunc_optab, DFmode, TFmode, "_U_Qfcnvff_quad_to_dbl");
- set_conv_libfunc (trunc_optab, XFmode, TFmode, "_U_Qfcnvff_quad_to_f80");
-
- set_conv_libfunc (sfix_optab, SImode, TFmode, "_U_Qfcnvfxt_quad_to_sgl");
- set_conv_libfunc (sfix_optab, DImode, TFmode, "_U_Qfcnvfxt_quad_to_dbl");
- set_conv_libfunc (ufix_optab, SImode, TFmode, "_U_Qfcnvfxut_quad_to_sgl");
- set_conv_libfunc (ufix_optab, DImode, TFmode, "_U_Qfcnvfxut_quad_to_dbl");
-
- set_conv_libfunc (sfloat_optab, TFmode, SImode, "_U_Qfcnvxf_sgl_to_quad");
- set_conv_libfunc (sfloat_optab, TFmode, DImode, "_U_Qfcnvxf_dbl_to_quad");
}
/* Rename the division and modulus functions in VMS. */
@@ -8795,50 +9367,79 @@ ia64_vms_init_libfuncs (void)
set_optab_libfunc (umod_optab, SImode, "OTS$REM_UI");
set_optab_libfunc (umod_optab, DImode, "OTS$REM_UL");
}
-
-/* Switch to the section to which we should output X. The only thing
- special we do here is to honor small data. */
+
+/* Rename the TFmode libfuncs available from soft-fp in glibc using
+ the HPUX conventions. */
static void
-ia64_select_rtx_section (enum machine_mode mode, rtx x,
- unsigned HOST_WIDE_INT align)
+ia64_sysv4_init_libfuncs (void)
{
- if (GET_MODE_SIZE (mode) > 0
- && GET_MODE_SIZE (mode) <= ia64_section_threshold)
- sdata_section ();
- else
- default_elf_select_rtx_section (mode, x, align);
-}
+ ia64_init_libfuncs ();
-/* It is illegal to have relocations in shared segments on AIX and HPUX.
- Pretend flag_pic is always set. */
+ /* These functions are not part of the HPUX TFmode interface. We
+ use them instead of _U_Qfcmp, which doesn't work the way we
+ expect. */
+ set_optab_libfunc (eq_optab, TFmode, "_U_Qfeq");
+ set_optab_libfunc (ne_optab, TFmode, "_U_Qfne");
+ set_optab_libfunc (gt_optab, TFmode, "_U_Qfgt");
+ set_optab_libfunc (ge_optab, TFmode, "_U_Qfge");
+ set_optab_libfunc (lt_optab, TFmode, "_U_Qflt");
+ set_optab_libfunc (le_optab, TFmode, "_U_Qfle");
-static void
-ia64_rwreloc_select_section (tree exp, int reloc, unsigned HOST_WIDE_INT align)
+ /* We leave out _U_Qfmin, _U_Qfmax and _U_Qfabs since soft-fp in
+ glibc doesn't have them. */
+}
+
+/* For HPUX, it is illegal to have relocations in shared segments. */
+
+static int
+ia64_hpux_reloc_rw_mask (void)
{
- default_elf_select_section_1 (exp, reloc, align, true);
+ return 3;
}
-static void
-ia64_rwreloc_unique_section (tree decl, int reloc)
+/* For others, relax this so that relocations to local data goes in
+ read-only segments, but we still cannot allow global relocations
+ in read-only segments. */
+
+static int
+ia64_reloc_rw_mask (void)
{
- default_unique_section_1 (decl, reloc, true);
+ return flag_pic ? 3 : 2;
}
-static void
-ia64_rwreloc_select_rtx_section (enum machine_mode mode, rtx x,
- unsigned HOST_WIDE_INT align)
+/* Return the section to use for X. The only special thing we do here
+ is to honor small data. */
+
+static section *
+ia64_select_rtx_section (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;
+ if (GET_MODE_SIZE (mode) > 0
+ && GET_MODE_SIZE (mode) <= ia64_section_threshold
+ && !TARGET_NO_SDATA)
+ return sdata_section;
+ else
+ return default_elf_select_rtx_section (mode, x, align);
}
static unsigned int
-ia64_rwreloc_section_type_flags (tree decl, const char *name, int reloc)
+ia64_section_type_flags (tree decl, const char *name, int reloc)
{
- return default_section_type_flags_1 (decl, name, reloc, true);
+ unsigned int flags = 0;
+
+ if (strcmp (name, ".sdata") == 0
+ || strncmp (name, ".sdata.", 7) == 0
+ || strncmp (name, ".gnu.linkonce.s.", 16) == 0
+ || strncmp (name, ".sdata2.", 8) == 0
+ || strncmp (name, ".gnu.linkonce.s2.", 17) == 0
+ || strcmp (name, ".sbss") == 0
+ || strncmp (name, ".sbss.", 6) == 0
+ || strncmp (name, ".gnu.linkonce.sb.", 17) == 0)
+ flags = SECTION_SMALL;
+
+ flags |= default_section_type_flags (decl, name, reloc);
+ return flags;
}
/* Returns true if FNTYPE (a FUNCTION_TYPE or a METHOD_TYPE) returns a
@@ -8881,6 +9482,7 @@ ia64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
reload_completed = 1;
epilogue_completed = 1;
no_new_pseudos = 1;
+ reset_block_changes ();
/* Set things up as ia64_expand_prologue might. */
last_scratch_gr_reg = 15;
@@ -9003,7 +9605,7 @@ ia64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
insn = get_insns ();
shorten_branches (insn);
final_start_function (insn, file, 1);
- final (insn, file, 1, 0);
+ final (insn, file, 1);
final_end_function ();
reload_completed = 0;
@@ -9022,4 +9624,216 @@ ia64_struct_value_rtx (tree fntype,
return gen_rtx_REG (Pmode, GR_REG (8));
}
+static bool
+ia64_scalar_mode_supported_p (enum machine_mode mode)
+{
+ switch (mode)
+ {
+ case QImode:
+ case HImode:
+ case SImode:
+ case DImode:
+ case TImode:
+ return true;
+
+ case SFmode:
+ case DFmode:
+ case XFmode:
+ case RFmode:
+ return true;
+
+ case TFmode:
+ return TARGET_HPUX;
+
+ default:
+ return false;
+ }
+}
+
+static bool
+ia64_vector_mode_supported_p (enum machine_mode mode)
+{
+ switch (mode)
+ {
+ case V8QImode:
+ case V4HImode:
+ case V2SImode:
+ return true;
+
+ case V2SFmode:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* Implement the FUNCTION_PROFILER macro. */
+
+void
+ia64_output_function_profiler (FILE *file, int labelno)
+{
+ bool indirect_call;
+
+ /* If the function needs a static chain and the static chain
+ register is r15, we use an indirect call so as to bypass
+ the PLT stub in case the executable is dynamically linked,
+ because the stub clobbers r15 as per 5.3.6 of the psABI.
+ We don't need to do that in non canonical PIC mode. */
+
+ if (cfun->static_chain_decl && !TARGET_NO_PIC && !TARGET_AUTO_PIC)
+ {
+ gcc_assert (STATIC_CHAIN_REGNUM == 15);
+ indirect_call = true;
+ }
+ else
+ indirect_call = false;
+
+ if (TARGET_GNU_AS)
+ fputs ("\t.prologue 4, r40\n", file);
+ else
+ fputs ("\t.prologue\n\t.save ar.pfs, r40\n", file);
+ fputs ("\talloc out0 = ar.pfs, 8, 0, 4, 0\n", file);
+
+ if (NO_PROFILE_COUNTERS)
+ fputs ("\tmov out3 = r0\n", file);
+ else
+ {
+ char buf[20];
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
+
+ if (TARGET_AUTO_PIC)
+ fputs ("\tmovl out3 = @gprel(", file);
+ else
+ fputs ("\taddl out3 = @ltoff(", file);
+ assemble_name (file, buf);
+ if (TARGET_AUTO_PIC)
+ fputs (")\n", file);
+ else
+ fputs ("), r1\n", file);
+ }
+
+ if (indirect_call)
+ fputs ("\taddl r14 = @ltoff(@fptr(_mcount)), r1\n", file);
+ fputs ("\t;;\n", file);
+
+ fputs ("\t.save rp, r42\n", file);
+ fputs ("\tmov out2 = b0\n", file);
+ if (indirect_call)
+ fputs ("\tld8 r14 = [r14]\n\t;;\n", file);
+ fputs ("\t.body\n", file);
+ fputs ("\tmov out1 = r1\n", file);
+ if (indirect_call)
+ {
+ fputs ("\tld8 r16 = [r14], 8\n\t;;\n", file);
+ fputs ("\tmov b6 = r16\n", file);
+ fputs ("\tld8 r1 = [r14]\n", file);
+ fputs ("\tbr.call.sptk.many b0 = b6\n\t;;\n", file);
+ }
+ else
+ fputs ("\tbr.call.sptk.many b0 = _mcount\n\t;;\n", file);
+}
+
+static GTY(()) rtx mcount_func_rtx;
+static rtx
+gen_mcount_func_rtx (void)
+{
+ if (!mcount_func_rtx)
+ mcount_func_rtx = init_one_libfunc ("_mcount");
+ return mcount_func_rtx;
+}
+
+void
+ia64_profile_hook (int labelno)
+{
+ rtx label, ip;
+
+ if (NO_PROFILE_COUNTERS)
+ label = const0_rtx;
+ else
+ {
+ char buf[30];
+ const char *label_name;
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
+ label_name = (*targetm.strip_name_encoding) (ggc_strdup (buf));
+ label = gen_rtx_SYMBOL_REF (Pmode, label_name);
+ SYMBOL_REF_FLAGS (label) = SYMBOL_FLAG_LOCAL;
+ }
+ ip = gen_reg_rtx (Pmode);
+ emit_insn (gen_ip_value (ip));
+ emit_library_call (gen_mcount_func_rtx (), LCT_NORMAL,
+ VOIDmode, 3,
+ gen_rtx_REG (Pmode, BR_REG (0)), Pmode,
+ ip, Pmode,
+ label, Pmode);
+}
+
+/* Return the mangling of TYPE if it is an extended fundamental type. */
+
+static const char *
+ia64_mangle_fundamental_type (tree type)
+{
+ /* On HP-UX, "long double" is mangled as "e" so __float128 is
+ mangled as "e". */
+ if (!TARGET_HPUX && TYPE_MODE (type) == TFmode)
+ return "g";
+ /* On HP-UX, "e" is not available as a mangling of __float80 so use
+ an extended mangling. Elsewhere, "e" is available since long
+ double is 80 bits. */
+ if (TYPE_MODE (type) == XFmode)
+ return TARGET_HPUX ? "u9__float80" : "e";
+ if (TYPE_MODE (type) == RFmode)
+ return "u7__fpreg";
+ return NULL;
+}
+
+/* Return the diagnostic message string if conversion from FROMTYPE to
+ TOTYPE is not allowed, NULL otherwise. */
+static const char *
+ia64_invalid_conversion (tree fromtype, tree totype)
+{
+ /* Reject nontrivial conversion to or from __fpreg. */
+ if (TYPE_MODE (fromtype) == RFmode
+ && TYPE_MODE (totype) != RFmode
+ && TYPE_MODE (totype) != VOIDmode)
+ return N_("invalid conversion from %<__fpreg%>");
+ if (TYPE_MODE (totype) == RFmode
+ && TYPE_MODE (fromtype) != RFmode)
+ return N_("invalid conversion to %<__fpreg%>");
+ return NULL;
+}
+
+/* Return the diagnostic message string if the unary operation OP is
+ not permitted on TYPE, NULL otherwise. */
+static const char *
+ia64_invalid_unary_op (int op, tree type)
+{
+ /* Reject operations on __fpreg other than unary + or &. */
+ if (TYPE_MODE (type) == RFmode
+ && op != CONVERT_EXPR
+ && op != ADDR_EXPR)
+ return N_("invalid operation on %<__fpreg%>");
+ return NULL;
+}
+
+/* Return the diagnostic message string if the binary operation OP is
+ not permitted on TYPE1 and TYPE2, NULL otherwise. */
+static const char *
+ia64_invalid_binary_op (int op ATTRIBUTE_UNUSED, tree type1, tree type2)
+{
+ /* Reject operations on __fpreg. */
+ if (TYPE_MODE (type1) == RFmode || TYPE_MODE (type2) == RFmode)
+ return N_("invalid operation on %<__fpreg%>");
+ return NULL;
+}
+
+/* Implement overriding of the optimization options. */
+void
+ia64_optimization_options (int level ATTRIBUTE_UNUSED,
+ int size ATTRIBUTE_UNUSED)
+{
+ /* Let the scheduler form additional regions. */
+ set_param_value ("max-sched-extend-regions-iters", 2);
+}
+
#include "gt-ia64.h"
diff --git a/contrib/gcc/config/ia64/ia64.h b/contrib/gcc/config/ia64/ia64.h
index 9f7dd05..c9bb417 100644
--- a/contrib/gcc/config/ia64/ia64.h
+++ b/contrib/gcc/config/ia64/ia64.h
@@ -1,5 +1,6 @@
/* Definitions of target machine GNU compiler. IA-64 version.
- Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
Contributed by James E. Wilson <wilson@cygnus.com> and
David Mosberger <davidm@hpl.hp.com>.
@@ -17,8 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* ??? Look at ABI group documents for list of preprocessor macros and
other features required for ABI compliance. */
@@ -26,8 +27,6 @@ Boston, MA 02111-1307, USA. */
/* ??? Functions containing a non-local goto target save many registers. Why?
See for instance execute/920428-2.c. */
-/* ??? Add support for short data/bss sections. */
-
/* Run-time target specifications */
@@ -55,95 +54,9 @@ do { \
#define ASM_EXTRA_SPEC ""
-
-/* This declaration should be present. */
-extern int target_flags;
-
-/* This series of macros is to allow compiler command arguments to enable or
- disable the use of optional features of the target machine. */
-
-#define MASK_BIG_ENDIAN 0x00000001 /* Generate big endian code. */
-
-#define MASK_GNU_AS 0x00000002 /* Generate code for GNU as. */
-
-#define MASK_GNU_LD 0x00000004 /* Generate code for GNU ld. */
-
-#define MASK_NO_PIC 0x00000008 /* Generate code without GP reg. */
-
-#define MASK_VOL_ASM_STOP 0x00000010 /* Emit stop bits for vol ext asm. */
-
-#define MASK_ILP32 0x00000020 /* Generate ILP32 code. */
-
-#define MASK_B_STEP 0x00000040 /* Emit code for Itanium B step. */
-
-#define MASK_REG_NAMES 0x00000080 /* Use in/loc/out register names. */
-
-#define MASK_NO_SDATA 0x00000100 /* Disable sdata/scommon/sbss. */
-
-#define MASK_CONST_GP 0x00000200 /* treat gp as program-wide constant */
-
-#define MASK_AUTO_PIC 0x00000400 /* generate automatically PIC */
-
-#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_INT_DIV_THR 0x00001000 /* inline div, max throughput. */
-
-#define MASK_INLINE_SQRT_LAT 0x00002000 /* inline sqrt, min latency. */
-
-#define MASK_INLINE_SQRT_THR 0x00004000 /* inline sqrt, max throughput. */
-
-#define MASK_DWARF2_ASM 0x40000000 /* test dwarf2 line info via gas. */
-
-#define MASK_EARLY_STOP_BITS 0x00002000 /* tune stop bits for the model. */
-
-#define TARGET_BIG_ENDIAN (target_flags & MASK_BIG_ENDIAN)
-
-#define TARGET_GNU_AS (target_flags & MASK_GNU_AS)
-
-#define TARGET_GNU_LD (target_flags & MASK_GNU_LD)
-
-#define TARGET_NO_PIC (target_flags & MASK_NO_PIC)
-
-#define TARGET_VOL_ASM_STOP (target_flags & MASK_VOL_ASM_STOP)
-
-#define TARGET_ILP32 (target_flags & MASK_ILP32)
-
-#define TARGET_B_STEP (target_flags & MASK_B_STEP)
-
-#define TARGET_REG_NAMES (target_flags & MASK_REG_NAMES)
-
-#define TARGET_NO_SDATA (target_flags & MASK_NO_SDATA)
-
-#define TARGET_CONST_GP (target_flags & MASK_CONST_GP)
-
-#define TARGET_AUTO_PIC (target_flags & MASK_AUTO_PIC)
-
-#define TARGET_INLINE_FLOAT_DIV_LAT (target_flags & MASK_INLINE_FLOAT_DIV_LAT)
-
-#define TARGET_INLINE_FLOAT_DIV_THR (target_flags & MASK_INLINE_FLOAT_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_INLINE_SQRT_LAT (target_flags & MASK_INLINE_SQRT_LAT)
-
-#define TARGET_INLINE_SQRT_THR (target_flags & MASK_INLINE_SQRT_THR)
-
-#define TARGET_INLINE_SQRT \
- (target_flags & (MASK_INLINE_SQRT_LAT | MASK_INLINE_SQRT_THR))
-
-#define TARGET_DWARF2_ASM (target_flags & MASK_DWARF2_ASM)
+/* Variables which are this size or smaller are put in the sdata/sbss
+ sections. */
+extern unsigned int ia64_section_threshold;
/* If the assembler supports thread-local storage, assume that the
system does as well. If a particular target system has an
@@ -154,126 +67,54 @@ extern int target_flags;
#define TARGET_HAVE_TLS true
#endif
-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_EARLY_STOP_BITS (target_flags & MASK_EARLY_STOP_BITS)
#define TARGET_HPUX 0
#define TARGET_HPUX_LD 0
+#ifndef TARGET_ILP32
+#define TARGET_ILP32 0
+#endif
+
#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. */
+/* Values for TARGET_INLINE_FLOAT_DIV, TARGET_INLINE_INT_DIV, and
+ TARGET_INLINE_SQRT. */
-#define TARGET_SWITCHES \
-{ \
- { "big-endian", MASK_BIG_ENDIAN, \
- N_("Generate big endian code") }, \
- { "little-endian", -MASK_BIG_ENDIAN, \
- N_("Generate little endian code") }, \
- { "gnu-as", MASK_GNU_AS, \
- N_("Generate code for GNU as") }, \
- { "no-gnu-as", -MASK_GNU_AS, \
- N_("Generate code for Intel as") }, \
- { "gnu-ld", MASK_GNU_LD, \
- N_("Generate code for GNU ld") }, \
- { "no-gnu-ld", -MASK_GNU_LD, \
- N_("Generate code for Intel ld") }, \
- { "no-pic", MASK_NO_PIC, \
- N_("Generate code without GP reg") }, \
- { "volatile-asm-stop", MASK_VOL_ASM_STOP, \
- N_("Emit stop bits before and after volatile extended asms") }, \
- { "no-volatile-asm-stop", -MASK_VOL_ASM_STOP, \
- N_("Don't emit stop bits before and after volatile extended asms") }, \
- { "b-step", MASK_B_STEP, \
- N_("Emit code for Itanium (TM) processor B step")}, \
- { "register-names", MASK_REG_NAMES, \
- N_("Use in/loc/out register names")}, \
- { "no-sdata", MASK_NO_SDATA, \
- N_("Disable use of sdata/scommon/sbss")}, \
- { "sdata", -MASK_NO_SDATA, \
- N_("Enable use of sdata/scommon/sbss")}, \
- { "constant-gp", MASK_CONST_GP, \
- N_("gp is constant (but save/restore gp on indirect calls)") }, \
- { "auto-pic", MASK_AUTO_PIC, \
- N_("Generate self-relocatable code") }, \
- { "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") },\
- { "inline-sqrt-min-latency", MASK_INLINE_SQRT_LAT, \
- N_("Generate inline square root, optimize for latency") }, \
- { "inline-sqrt-max-throughput", MASK_INLINE_SQRT_THR, \
- N_("Generate inline square root, optimize for throughput") }, \
- { "dwarf2-asm", MASK_DWARF2_ASM, \
- N_("Enable Dwarf 2 line debug info via GNU as")}, \
- { "no-dwarf2-asm", -MASK_DWARF2_ASM, \
- N_("Disable Dwarf 2 line debug info via GNU as")}, \
- { "early-stop-bits", MASK_EARLY_STOP_BITS, \
- N_("Enable earlier placing stop bits for better scheduling")}, \
- { "no-early-stop-bits", -MASK_EARLY_STOP_BITS, \
- N_("Disable earlier placing stop bits")}, \
- SUBTARGET_SWITCHES \
- { "", TARGET_DEFAULT | TARGET_CPU_DEFAULT, \
- NULL } \
-}
+enum ia64_inline_type
+{
+ INL_NO = 0,
+ INL_MIN_LAT = 1,
+ INL_MAX_THR = 2
+};
/* Default target_flags if no switches are specified */
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT MASK_DWARF2_ASM
+#define TARGET_DEFAULT (MASK_DWARF2_ASM)
#endif
#ifndef TARGET_CPU_DEFAULT
#define TARGET_CPU_DEFAULT 0
#endif
-#ifndef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES
-#endif
-
-/* This macro is similar to `TARGET_SWITCHES' but defines names of command
- options that have values. Its definition is an initializer with a
- subgrouping for each command option. */
-
-extern const char *ia64_fixed_range_string;
-extern const char *ia64_tls_size_string;
-
/* Which processor to schedule for. The cpu attribute defines a list
- that mirrors this list, so changes to i64.md must be made at the
+ that mirrors this list, so changes to ia64.md must be made at the
same time. */
enum processor_type
{
- PROCESSOR_ITANIUM, /* Original Itanium. */
+ PROCESSOR_ITANIUM, /* Original Itanium. */
PROCESSOR_ITANIUM2,
PROCESSOR_max
};
extern enum processor_type ia64_tune;
-extern const char *ia64_tune_string;
-
-#define TARGET_OPTIONS \
-{ \
- { "fixed-range=", &ia64_fixed_range_string, \
- N_("Specify range of registers to make fixed"), 0}, \
- { "tls-size=", &ia64_tls_size_string, \
- N_("Specify bit size of immediate TLS offsets"), 0}, \
- { "tune=", &ia64_tune_string, \
- N_("Schedule code for given CPU"), 0}, \
-}
-
/* Sometimes certain combinations of command options do not make sense on a
particular target machine. You can define a macro `OVERRIDE_OPTIONS' to
take account of this. This macro, if defined, is executed once just after
@@ -349,12 +190,6 @@ do \
} \
while (0)
-/* ??? ABI doesn't allow us to define this. */
-/* #define PROMOTE_FUNCTION_ARGS */
-
-/* ??? ABI doesn't allow us to define this. */
-/* #define PROMOTE_FUNCTION_RETURN */
-
#define PARM_BOUNDARY 64
/* Define this macro if you wish to preserve a certain alignment for the stack
@@ -439,8 +274,6 @@ while (0)
#define LONG_TYPE_SIZE (TARGET_ILP32 ? 32 : 64)
-#define MAX_LONG_TYPE_SIZE 64
-
#define LONG_LONG_TYPE_SIZE 64
#define FLOAT_TYPE_SIZE 32
@@ -448,10 +281,10 @@ while (0)
#define DOUBLE_TYPE_SIZE 64
/* long double is XFmode normally, TFmode for HPUX. */
-#define LONG_DOUBLE_TYPE_SIZE (TARGET_HPUX ? 128 : 96)
+#define LONG_DOUBLE_TYPE_SIZE (TARGET_HPUX ? 128 : 80)
/* We always want the XFmode operations from libgcc2.c. */
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 96
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 80
#define DEFAULT_SIGNED_CHAR 1
@@ -491,6 +324,7 @@ while (0)
#define ADDL_REGNO_P(REGNO) ((unsigned HOST_WIDE_INT) (REGNO) <= 3)
#define GR_REGNO_P(REGNO) ((unsigned HOST_WIDE_INT) (REGNO) <= 127)
#define FR_REGNO_P(REGNO) ((REGNO) >= 128 && (REGNO) <= 255)
+#define FP_REGNO_P(REGNO) ((REGNO) >= 128 && (REGNO) <= 254 && (REGNO) != 159)
#define PR_REGNO_P(REGNO) ((REGNO) >= 256 && (REGNO) <= 319)
#define BR_REGNO_P(REGNO) ((REGNO) >= 320 && (REGNO) <= 327)
#define GENERAL_REGNO_P(REGNO) \
@@ -620,7 +454,7 @@ while (0)
#define CALL_REALLY_USED_REGISTERS \
{ /* General registers. */ \
- 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, \
+ 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
@@ -629,7 +463,7 @@ while (0)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, \
/* Floating-point registers. */ \
- 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
@@ -638,7 +472,7 @@ while (0)
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
/* Predicate registers. */ \
- 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
@@ -672,9 +506,7 @@ while (0)
#define LOCAL_REGNO(REGNO) \
(IN_REGNO_P (REGNO) || LOC_REGNO_P (REGNO))
-/* 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. */
+/* We define CCImode in ia64-modes.def so we need a selector. */
#define SELECT_CC_MODE(OP,X,Y) CCmode
@@ -810,6 +642,7 @@ while (0)
: PR_REGNO_P (REGNO) && (MODE) == BImode ? 2 \
: PR_REGNO_P (REGNO) && (MODE) == CCImode ? 1 \
: FR_REGNO_P (REGNO) && (MODE) == XFmode ? 1 \
+ : FR_REGNO_P (REGNO) && (MODE) == XCmode ? 2 \
: (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* A C expression that is nonzero if it is permissible to store a value of mode
@@ -819,12 +652,12 @@ while (0)
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
(FR_REGNO_P (REGNO) ? \
GET_MODE_CLASS (MODE) != MODE_CC && \
- (MODE) != TImode && \
(MODE) != BImode && \
(MODE) != TFmode \
: PR_REGNO_P (REGNO) ? \
(MODE) == BImode || GET_MODE_CLASS (MODE) == MODE_CC \
- : GR_REGNO_P (REGNO) ? (MODE) != CCImode && (MODE) != XFmode \
+ : GR_REGNO_P (REGNO) ? \
+ (MODE) != CCImode && (MODE) != XFmode && (MODE) != XCmode \
: AR_REGNO_P (REGNO) ? (MODE) == DImode \
: BR_REGNO_P (REGNO) ? (MODE) == DImode \
: 0)
@@ -841,7 +674,8 @@ while (0)
we can't tie it with any other modes. */
#define MODES_TIEABLE_P(MODE1, MODE2) \
(GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2) \
- && (((MODE1) == XFmode) == ((MODE2) == XFmode)) \
+ && ((((MODE1) == XFmode) || ((MODE1) == XCmode)) \
+ == (((MODE2) == XFmode) || ((MODE2) == XCmode))) \
&& (((MODE1) == BImode) == ((MODE2) == BImode)))
/* Specify the modes required to caller save a given hard regno.
@@ -887,6 +721,7 @@ enum reg_class
AR_I_REGS,
ADDL_REGS,
GR_REGS,
+ FP_REGS,
FR_REGS,
GR_AND_BR_REGS,
GR_AND_FR_REGS,
@@ -903,7 +738,7 @@ enum reg_class
constants. These names are used in writing some of the debugging dumps. */
#define REG_CLASS_NAMES \
{ "NO_REGS", "PR_REGS", "BR_REGS", "AR_M_REGS", "AR_I_REGS", \
- "ADDL_REGS", "GR_REGS", "FR_REGS", \
+ "ADDL_REGS", "GR_REGS", "FP_REGS", "FR_REGS", \
"GR_AND_BR_REGS", "GR_AND_FR_REGS", "ALL_REGS" }
/* An initializer containing the contents of the register classes, as integers
@@ -940,6 +775,10 @@ enum reg_class
{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x0100 }, \
+ /* FP_REGS. */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+ 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, \
+ 0x00000000, 0x00000000, 0x0000 }, \
/* FR_REGS. */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
@@ -967,7 +806,8 @@ enum reg_class
#define REGNO_REG_CLASS(REGNO) \
(ADDL_REGNO_P (REGNO) ? ADDL_REGS \
: GENERAL_REGNO_P (REGNO) ? GR_REGS \
- : FR_REGNO_P (REGNO) ? FR_REGS \
+ : FR_REGNO_P (REGNO) ? (REGNO) != R_FR (31) \
+ && (REGNO) != R_FR(127) ? FP_REGS : FR_REGS \
: PR_REGNO_P (REGNO) ? PR_REGS \
: BR_REGNO_P (REGNO) ? BR_REGS \
: AR_M_REGNO_P (REGNO) ? AR_M_REGS \
@@ -998,6 +838,7 @@ enum reg_class
: (CHAR) == 'c' ? PR_REGS \
: (CHAR) == 'd' ? AR_M_REGS \
: (CHAR) == 'e' ? AR_I_REGS \
+ : (CHAR) == 'x' ? FP_REGS \
: NO_REGS)
/* A C expression which is nonzero if register number NUM is suitable for use
@@ -1017,18 +858,8 @@ enum reg_class
The value is a register class; perhaps CLASS, or perhaps another, smaller
class. */
-/* Don't allow volatile mem reloads into floating point registers. This
- is defined to force reload to choose the r/m case instead of the f/f case
- when reloading (set (reg fX) (mem/v)).
-
- Do not reload expressions into AR regs. */
-
#define PREFERRED_RELOAD_CLASS(X, CLASS) \
- (CLASS == FR_REGS && GET_CODE (X) == MEM && MEM_VOLATILE_P (X) ? NO_REGS \
- : CLASS == FR_REGS && GET_CODE (X) == CONST_DOUBLE ? NO_REGS \
- : GET_RTX_CLASS (GET_CODE (X)) != 'o' \
- && (CLASS == AR_M_REGS || CLASS == AR_I_REGS) ? NO_REGS \
- : CLASS)
+ ia64_preferred_reload_class (X, CLASS)
/* You should define this macro to indicate to the reload phase that it may
need to allocate at least one register for a reload in addition to the
@@ -1053,8 +884,9 @@ enum reg_class
with unions should be solved with the addressof fiddling done by
movxf and friends. */
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
- ((MODE) == XFmode && (((CLASS1) == GR_REGS && (CLASS2) == FR_REGS) \
- || ((CLASS1) == FR_REGS && (CLASS2) == GR_REGS)))
+ (((MODE) == XFmode || (MODE) == XCmode) \
+ && (((CLASS1) == GR_REGS && (CLASS2) == FR_REGS) \
+ || ((CLASS1) == FR_REGS && (CLASS2) == GR_REGS)))
#endif
/* A C expression for the maximum number of consecutive registers of
@@ -1063,14 +895,15 @@ enum reg_class
#define CLASS_MAX_NREGS(CLASS, MODE) \
((MODE) == BImode && (CLASS) == PR_REGS ? 2 \
- : ((CLASS) == FR_REGS && (MODE) == XFmode) ? 1 \
+ : (((CLASS) == FR_REGS || (CLASS) == FP_REGS) && (MODE) == XFmode) ? 1 \
+ : (((CLASS) == FR_REGS || (CLASS) == FP_REGS) && (MODE) == XCmode) ? 2 \
: (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-/* In FP regs, we can't change FP values to integer values and vice
- versa, but we can change e.g. DImode to SImode. */
+/* In FP regs, we can't change FP values to integer values and vice versa,
+ but we can change e.g. DImode to SImode, and V2SFmode into DImode. */
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
- (GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO) \
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (SCALAR_FLOAT_MODE_P (FROM) != SCALAR_FLOAT_MODE_P (TO) \
? reg_classes_intersect_p (CLASS, FR_REGS) : 0)
/* A C expression that defines the machine-dependent operand constraint
@@ -1097,15 +930,7 @@ enum reg_class
#define CONST_OK_FOR_P(VALUE) ((VALUE) == 0 || (VALUE) == -1)
#define CONST_OK_FOR_LETTER_P(VALUE, C) \
-((C) == 'I' ? CONST_OK_FOR_I (VALUE) \
- : (C) == 'J' ? CONST_OK_FOR_J (VALUE) \
- : (C) == 'K' ? CONST_OK_FOR_K (VALUE) \
- : (C) == 'L' ? CONST_OK_FOR_L (VALUE) \
- : (C) == 'M' ? CONST_OK_FOR_M (VALUE) \
- : (C) == 'N' ? CONST_OK_FOR_N (VALUE) \
- : (C) == 'O' ? CONST_OK_FOR_O (VALUE) \
- : (C) == 'P' ? CONST_OK_FOR_P (VALUE) \
- : 0)
+ ia64_const_ok_for_letter_p (VALUE, C)
/* A C expression that defines the machine-dependent operand constraint letters
(`G', `H') that specify particular ranges of `const_double' values. */
@@ -1116,33 +941,21 @@ enum reg_class
|| (VALUE) == CONST1_RTX (GET_MODE (VALUE)))
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
- ((C) == 'G' ? CONST_DOUBLE_OK_FOR_G (VALUE) : 0)
+ ia64_const_double_ok_for_letter_p (VALUE, C)
/* A C expression that defines the optional machine-dependent constraint
letters (`Q', `R', `S', `T', `U') that can be used to segregate specific
types of operands, usually memory references, for the target machine. */
-/* Non-volatile memory for FP_REG loads/stores. */
-#define CONSTRAINT_OK_FOR_Q(VALUE) \
- (memory_operand((VALUE), VOIDmode) && ! MEM_VOLATILE_P (VALUE))
-/* 1..4 for shladd arguments. */
-#define CONSTRAINT_OK_FOR_R(VALUE) \
- (GET_CODE (VALUE) == CONST_INT && INTVAL (VALUE) >= 1 && INTVAL (VALUE) <= 4)
-/* Non-post-inc memory for asms and other unsavory creatures. */
-#define CONSTRAINT_OK_FOR_S(VALUE) \
- (GET_CODE (VALUE) == MEM \
- && GET_RTX_CLASS (GET_CODE (XEXP ((VALUE), 0))) != 'a' \
- && (reload_in_progress || memory_operand ((VALUE), VOIDmode)))
-/* Symbol ref to small-address-area: */
-#define CONSTRAINT_OK_FOR_T(VALUE) \
- (GET_CODE (VALUE) == SYMBOL_REF && SYMBOL_REF_SMALL_ADDR_P (VALUE))
-
#define EXTRA_CONSTRAINT(VALUE, C) \
- ((C) == 'Q' ? CONSTRAINT_OK_FOR_Q (VALUE) \
- : (C) == 'R' ? CONSTRAINT_OK_FOR_R (VALUE) \
- : (C) == 'S' ? CONSTRAINT_OK_FOR_S (VALUE) \
- : (C) == 'T' ? CONSTRAINT_OK_FOR_T (VALUE) \
- : 0)
+ ia64_extra_constraint (VALUE, C)
+
+/* Document the constraints that can accept reloaded memory operands. This is
+ needed by the extended asm support, and by reload. 'Q' accepts mem, but
+ only non-volatile mem. Since we can't reload a volatile mem into a
+ non-volatile mem, it can not be listed here. */
+
+#define EXTRA_MEMORY_CONSTRAINT(C, STR) ((C) == 'S')
/* Basic Stack Layout */
@@ -1150,9 +963,9 @@ enum reg_class
to a smaller address. */
#define STACK_GROWS_DOWNWARD 1
-/* Define this macro if the addresses of local variable slots are at negative
- offsets from the frame pointer. */
-/* #define FRAME_GROWS_DOWNWARD */
+/* Define this macro to nonzero if the addresses of local variable slots
+ are at negative offsets from the frame pointer. */
+#define FRAME_GROWS_DOWNWARD 0
/* Offset from the frame pointer to the first local variable slot to
be allocated. */
@@ -1203,7 +1016,12 @@ enum reg_class
beginning of any function, before the prologue. The top of the frame is
defined to be the value of the stack pointer in the previous frame, just
before the call instruction. */
-#define INCOMING_FRAME_SP_OFFSET 0
+/* The CFA is past the red zone, not at the entry-point stack
+ pointer. */
+#define INCOMING_FRAME_SP_OFFSET STACK_POINTER_OFFSET
+
+/* We shorten debug info by using CFA-16 as DW_AT_frame_base. */
+#define CFA_FRAME_BASE_OFFSET(FUNDECL) (-INCOMING_FRAME_SP_OFFSET)
/* Register That Address the Stack Frame. */
@@ -1279,13 +1097,6 @@ enum reg_class
/* Passing Function Arguments on the Stack */
-/* Define this macro if an argument declared in a prototype as an integral type
- smaller than `int' should actually be passed as an `int'. In addition to
- avoiding errors in certain cases of mismatch, it also makes for better code
- on certain machines. */
-/* ??? Investigate. */
-/* #define PROMOTE_PROTOTYPES */
-
/* If defined, the maximum amount of space required for outgoing arguments will
be computed and placed into the variable
`current_function_outgoing_args_size'. */
@@ -1324,29 +1135,6 @@ enum reg_class
#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
ia64_function_arg (&CUM, MODE, TYPE, NAMED, 1)
-/* A C expression for the number of words, at the beginning of an argument,
- must be put in registers. The value must be zero for arguments that are
- passed entirely in registers or that are entirely pushed on the stack. */
-
-#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
- ia64_function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED)
-
-/* A C expression that indicates when an argument must be passed by reference.
- If nonzero for an argument, a copy of that argument is made in memory and a
- pointer to the argument is passed instead of the argument itself. The
- pointer is passed in whatever way is appropriate for passing a pointer to
- that type. */
-
-#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
- ia64_function_arg_pass_by_reference (&CUM, MODE, TYPE, NAMED)
-
-/* Nonzero if we do not know how to pass TYPE solely in registers. */
-
-#define MUST_PASS_IN_STACK(MODE, TYPE) \
- ((TYPE) != 0 \
- && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \
- || TREE_ADDRESSABLE (TYPE)))
-
/* A C type for declaring a variable that is used as the first argument of
`FUNCTION_ARG' and other related values. For some target machines, the type
`int' suffices and can hold the number of bytes of argument so far. */
@@ -1395,15 +1183,11 @@ do { \
/* If defined, a C expression that gives the alignment boundary, in bits, of an
argument with the specified mode and type. */
-/* Arguments with alignment larger than 8 bytes start at the next even
- boundary. See ia64_function_arg. */
+/* Return the alignment boundary in bits for an argument with a specified
+ mode and type. */
#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
- (((TYPE) ? (TYPE_ALIGN (TYPE) > 8 * BITS_PER_UNIT) \
- : (((((MODE) == BLKmode \
- ? int_size_in_bytes (TYPE) : GET_MODE_SIZE (MODE)) \
- + UNITS_PER_WORD - 1) / UNITS_PER_WORD) > 1)) \
- ? 128 : PARM_BOUNDARY)
+ ia64_function_arg_boundary (MODE, TYPE)
/* A C expression that is nonzero if REGNO is the number of a hard register in
which function arguments are sometimes passed. This does *not* include
@@ -1414,10 +1198,6 @@ do { \
(((REGNO) >= AR_ARG_FIRST && (REGNO) < (AR_ARG_FIRST + MAX_ARGUMENT_SLOTS)) \
|| ((REGNO) >= FR_ARG_FIRST && (REGNO) < (FR_ARG_FIRST + MAX_ARGUMENT_SLOTS)))
-/* Implement `va_arg'. */
-#define EXPAND_BUILTIN_VA_ARG(valist, type) \
- ia64_va_arg (valist, type)
-
/* How Scalar Function Values are Returned */
/* A C expression to create an RTX representing the place where a function
@@ -1446,15 +1226,6 @@ do { \
/* How Large Values are Returned */
-/* A nonzero value says to return the function value in memory, just as large
- structures are always returned. */
-
-#define RETURN_IN_MEMORY(TYPE) \
- ia64_return_in_memory (TYPE)
-
-/* If you define this macro to be 0, then the conventions used for structure
- and union return values are decided by the `RETURN_IN_MEMORY' macro. */
-
#define DEFAULT_PCC_STRUCT_RETURN 0
@@ -1499,6 +1270,7 @@ do { \
fputs ("\tdata8.ua @iplt(", FILE); \
else \
fputs ("\tdata16.ua @iplt(", FILE); \
+ mark_decl_referenced (DECL); \
assemble_name (FILE, XSTR (XEXP (DECL_RTL (DECL), 0), 0)); \
fputs (")\n", FILE); \
if (TARGET_ILP32) \
@@ -1512,39 +1284,11 @@ do { \
call the profiling subroutine `mcount'. */
#undef FUNCTION_PROFILER
-#define FUNCTION_PROFILER(FILE, LABELNO) \
-do { \
- char buf[20]; \
- ASM_GENERATE_INTERNAL_LABEL (buf, "LP", LABELNO); \
- fputs ("\talloc out0 = ar.pfs, 8, 0, 4, 0\n", FILE); \
- if (TARGET_AUTO_PIC) \
- fputs ("\tmovl out3 = @gprel(", FILE); \
- else \
- fputs ("\taddl out3 = @ltoff(", FILE); \
- assemble_name (FILE, buf); \
- if (TARGET_AUTO_PIC) \
- fputs (");;\n", FILE); \
- else \
- fputs ("), r1;;\n", FILE); \
- fputs ("\tmov out1 = r1\n", FILE); \
- fputs ("\tmov out2 = b0\n", FILE); \
- fputs ("\tbr.call.sptk.many b0 = _mcount;;\n", FILE); \
-} while (0)
-
-/* Implementing the Varargs Macros. */
-
-/* Define this macro to store the anonymous register arguments into the stack
- so that all the arguments appear to have been passed consecutively on the
- stack. */
-
-#define SETUP_INCOMING_VARARGS(ARGS_SO_FAR, MODE, TYPE, PRETEND_ARGS_SIZE, SECOND_TIME) \
- ia64_setup_incoming_varargs (ARGS_SO_FAR, MODE, TYPE, & PRETEND_ARGS_SIZE, SECOND_TIME)
-
-/* Define this macro if the location where a function argument is passed
- depends on whether or not it is a named argument. */
-
-#define STRICT_ARGUMENT_NAMING 1
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ ia64_output_function_profiler(FILE, LABELNO)
+/* Neither hpux nor linux use profile counters. */
+#define NO_PROFILE_COUNTERS 1
/* Trampolines for Nested Functions. */
@@ -1592,15 +1336,6 @@ do { \
#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, STATIC_CHAIN) \
ia64_initialize_trampoline((ADDR), (FNADDR), (STATIC_CHAIN))
-/* Implicit Calls to Library Routines */
-
-/* Define this macro if GCC should generate calls to the System V (and ANSI
- C) library functions `memcpy' and `memset' rather than the BSD functions
- `bcopy' and `bzero'. */
-
-#define TARGET_MEM_FUNCTIONS
-
-
/* Addressing Modes */
/* Define this macro if the machine supports post-increment addressing. */
@@ -1666,13 +1401,6 @@ do { \
#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X)
-/* A C compound statement that attempts to replace X with a valid memory
- address for an operand of mode MODE.
-
- This must be present, but there is nothing useful to be done here. */
-
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)
-
/* A C statement or compound statement with a conditional `goto LABEL;'
executed if memory address X (an RTX) can have different meanings depending
on the machine mode of the memory reference it is used for or if the address
@@ -1685,10 +1413,7 @@ do { \
/* A C expression that is nonzero if X is a legitimate constant for an
immediate operand on the target machine. */
-#define LEGITIMATE_CONSTANT_P(X) \
- (GET_CODE (X) != CONST_DOUBLE || GET_MODE (X) == VOIDmode \
- || GET_MODE (X) == DImode || CONST_DOUBLE_OK_FOR_G (X)) \
-
+#define LEGITIMATE_CONSTANT_P(X) ia64_legitimate_constant_p (X)
/* Condition Code Status */
@@ -1708,7 +1433,7 @@ do { \
/* A C expression for the cost of moving data of mode M between a
register and memory. */
#define MEMORY_MOVE_COST(MODE,CLASS,IN) \
- ((CLASS) == GENERAL_REGS || (CLASS) == FR_REGS \
+ ((CLASS) == GENERAL_REGS || (CLASS) == FR_REGS || (CLASS) == FP_REGS \
|| (CLASS) == GR_AND_FR_REGS ? 4 : 10)
/* A C expression for the cost of a branch instruction. A value of 1 is the
@@ -2014,13 +1739,6 @@ do { \
{ "loc79", LOC_REG (79) }, \
}
-/* Emit a dtp-relative reference to a TLS variable. */
-
-#ifdef HAVE_AS_TLS
-#define ASM_OUTPUT_DWARF_DTPREL(FILE, SIZE, X) \
- ia64_output_dwarf_dtprel (FILE, SIZE, X)
-#endif
-
/* A C compound statement to output to stdio stream STREAM the assembler syntax
for an instruction operand X. X is an RTL expression. */
@@ -2066,11 +1784,6 @@ do { \
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.) */
-
-#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) abort ()
-
/* Jump tables only need 8 byte alignment. */
#define ADDR_VEC_ALIGN(ADDR_VEC) 3
@@ -2159,6 +1872,12 @@ do { \
#define DWARF2_DEBUGGING_INFO 1
+/* We do not want call-frame info to be output, since debuggers are
+ supposed to use the target unwind info. Leave this undefined it
+ TARGET_UNWIND_INFO might ever be false. */
+
+#define DWARF2_FRAME_INFO 0
+
#define DWARF2_ASM_LINE_DEBUG_INFO (TARGET_DWARF2_ASM)
/* Use tags for debug info labels, so that they don't break instruction
@@ -2172,12 +1891,12 @@ do { \
/* Use section-relative relocations for debugging offsets. Unlike other
targets that fake this by putting the section VMA at 0, IA-64 has
proper relocations for them. */
-#define ASM_OUTPUT_DWARF_OFFSET(FILE, SIZE, LABEL) \
- do { \
- fputs (integer_asm_op (SIZE, FALSE), FILE); \
- fputs ("@secrel(", FILE); \
- assemble_name (FILE, LABEL); \
- fputc (')', FILE); \
+#define ASM_OUTPUT_DWARF_OFFSET(FILE, SIZE, LABEL, SECTION) \
+ do { \
+ fputs (integer_asm_op (SIZE, FALSE), FILE); \
+ fputs ("@secrel(", FILE); \
+ assemble_name (FILE, LABEL); \
+ fputc (')', FILE); \
} while (0)
/* Emit a PC-relative relocation. */
@@ -2206,58 +1925,6 @@ do { \
#define SYMBOL_REF_SMALL_ADDR_P(X) \
((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_SMALL_ADDR) != 0)
-/* Define this if you have defined special-purpose predicates in the file
- `MACHINE.c'. For each predicate, list all rtl codes that can be in
- expressions matched by the predicate. */
-
-#define PREDICATE_CODES \
-{ "call_operand", {SUBREG, REG, SYMBOL_REF}}, \
-{ "got_symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \
-{ "sdata_symbolic_operand", {SYMBOL_REF, CONST}}, \
-{ "small_addr_symbolic_operand", {SYMBOL_REF}}, \
-{ "symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \
-{ "function_operand", {SYMBOL_REF}}, \
-{ "setjmp_operand", {SYMBOL_REF}}, \
-{ "destination_operand", {SUBREG, REG, MEM}}, \
-{ "not_postinc_memory_operand", {MEM}}, \
-{ "move_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \
- CONSTANT_P_RTX, SYMBOL_REF, CONST, LABEL_REF}}, \
-{ "gr_register_operand", {SUBREG, REG}}, \
-{ "fr_register_operand", {SUBREG, REG}}, \
-{ "grfr_register_operand", {SUBREG, REG}}, \
-{ "gr_nonimmediate_operand", {SUBREG, REG, MEM}}, \
-{ "fr_nonimmediate_operand", {SUBREG, REG, MEM}}, \
-{ "grfr_nonimmediate_operand", {SUBREG, REG, MEM}}, \
-{ "gr_reg_or_0_operand", {SUBREG, REG, CONST_INT}}, \
-{ "gr_reg_or_5bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
-{ "gr_reg_or_6bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
-{ "gr_reg_or_8bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
-{ "grfr_reg_or_8bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
-{ "gr_reg_or_8bit_adjusted_operand", {SUBREG, REG, CONST_INT, \
- CONSTANT_P_RTX}}, \
-{ "gr_reg_or_8bit_and_adjusted_operand", {SUBREG, REG, CONST_INT, \
- CONSTANT_P_RTX}}, \
-{ "gr_reg_or_14bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
-{ "gr_reg_or_22bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
-{ "shift_count_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
-{ "shift_32bit_count_operand", {SUBREG, REG, CONST_INT, \
- CONSTANT_P_RTX}}, \
-{ "shladd_operand", {CONST_INT}}, \
-{ "fetchadd_operand", {CONST_INT}}, \
-{ "fr_reg_or_fp01_operand", {SUBREG, REG, CONST_DOUBLE}}, \
-{ "normal_comparison_operator", {EQ, NE, GT, LE, GTU, LEU}}, \
-{ "adjusted_comparison_operator", {LT, GE, LTU, GEU}}, \
-{ "signed_inequality_operator", {GE, GT, LE, LT}}, \
-{ "predicate_operator", {NE, EQ}}, \
-{ "condop_operator", {PLUS, MINUS, IOR, XOR, AND}}, \
-{ "ar_lc_reg_operand", {REG}}, \
-{ "ar_ccv_reg_operand", {REG}}, \
-{ "ar_pfs_reg_operand", {REG}}, \
-{ "general_xfmode_operand", {SUBREG, REG, CONST_DOUBLE, MEM}}, \
-{ "destination_xfmode_operand", {SUBREG, REG, MEM}}, \
-{ "xfreg_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. */
@@ -2336,8 +2003,9 @@ do { \
extern int ia64_final_schedule;
-#define IA64_UNWIND_INFO 1
-#define IA64_UNWIND_EMIT(f,i) process_for_unwind_directive (f,i)
+#define TARGET_UNWIND_INFO 1
+
+#define TARGET_UNWIND_TABLES_DEFAULT true
#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 15 : INVALID_REGNUM)
@@ -2355,66 +2023,9 @@ struct machine_function GTY(())
/* The number of varargs registers to save. */
int n_varargs;
-};
-
-
-enum ia64_builtins
-{
- IA64_BUILTIN_SYNCHRONIZE,
-
- IA64_BUILTIN_FETCH_AND_ADD_SI,
- IA64_BUILTIN_FETCH_AND_SUB_SI,
- IA64_BUILTIN_FETCH_AND_OR_SI,
- IA64_BUILTIN_FETCH_AND_AND_SI,
- IA64_BUILTIN_FETCH_AND_XOR_SI,
- IA64_BUILTIN_FETCH_AND_NAND_SI,
-
- IA64_BUILTIN_ADD_AND_FETCH_SI,
- IA64_BUILTIN_SUB_AND_FETCH_SI,
- IA64_BUILTIN_OR_AND_FETCH_SI,
- IA64_BUILTIN_AND_AND_FETCH_SI,
- IA64_BUILTIN_XOR_AND_FETCH_SI,
- IA64_BUILTIN_NAND_AND_FETCH_SI,
-
- IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_SI,
- IA64_BUILTIN_VAL_COMPARE_AND_SWAP_SI,
-
- IA64_BUILTIN_SYNCHRONIZE_SI,
-
- IA64_BUILTIN_LOCK_TEST_AND_SET_SI,
-
- IA64_BUILTIN_LOCK_RELEASE_SI,
-
- IA64_BUILTIN_FETCH_AND_ADD_DI,
- IA64_BUILTIN_FETCH_AND_SUB_DI,
- IA64_BUILTIN_FETCH_AND_OR_DI,
- IA64_BUILTIN_FETCH_AND_AND_DI,
- IA64_BUILTIN_FETCH_AND_XOR_DI,
- IA64_BUILTIN_FETCH_AND_NAND_DI,
- IA64_BUILTIN_ADD_AND_FETCH_DI,
- IA64_BUILTIN_SUB_AND_FETCH_DI,
- IA64_BUILTIN_OR_AND_FETCH_DI,
- IA64_BUILTIN_AND_AND_FETCH_DI,
- IA64_BUILTIN_XOR_AND_FETCH_DI,
- IA64_BUILTIN_NAND_AND_FETCH_DI,
-
- IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_DI,
- IA64_BUILTIN_VAL_COMPARE_AND_SWAP_DI,
-
- IA64_BUILTIN_SYNCHRONIZE_DI,
-
- IA64_BUILTIN_LOCK_TEST_AND_SET_DI,
-
- IA64_BUILTIN_LOCK_RELEASE_DI,
-
- IA64_BUILTIN_BSP,
- IA64_BUILTIN_FLUSHRS
-};
-
-/* Codes for expand_compare_and_swap and expand_swap_and_compare. */
-enum fetchop_code {
- IA64_ADD_OP, IA64_SUB_OP, IA64_OR_OP, IA64_AND_OP, IA64_XOR_OP, IA64_NAND_OP
+ /* The number of the next unwind state to copy. */
+ int state_num;
};
#define DONT_USE_BUILTIN_SETJMP
@@ -2424,9 +2035,16 @@ enum fetchop_code {
#undef PROFILE_BEFORE_PROLOGUE
#define PROFILE_BEFORE_PROLOGUE 1
+/* Initialize library function table. */
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS ia64_init_libfuncs
/* Switch on code for querying unit reservations. */
#define CPU_UNITS_QUERY 1
+/* Define this to change the optimizations performed by default. */
+#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) \
+ ia64_optimization_options ((LEVEL), (SIZE))
+
/* End of ia64.h */
diff --git a/contrib/gcc/config/ia64/ia64.md b/contrib/gcc/config/ia64/ia64.md
index 4bda8f4..e573c55 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, 2002, 2003, 2004
+;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
;; Free Software Foundation, Inc.
;; Contributed by James E. Wilson <wilson@cygnus.com> and
;; David Mosberger <davidm@hpl.hp.com>.
@@ -18,8 +18,8 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
@@ -56,6 +56,7 @@
(UNSPEC_DTPREL 2)
(UNSPEC_LTOFF_TPREL 3)
(UNSPEC_TPREL 4)
+ (UNSPEC_DTPMOD 5)
(UNSPEC_LD_BASE 9)
(UNSPEC_GR_SPILL 10)
@@ -77,6 +78,15 @@
(UNSPEC_RET_ADDR 26)
(UNSPEC_SETF_EXP 27)
(UNSPEC_FR_SQRT_RECIP_APPROX 28)
+ (UNSPEC_SHRP 29)
+ (UNSPEC_COPYSIGN 30)
+ (UNSPEC_VECT_EXTR 31)
+ (UNSPEC_LDA 40)
+ (UNSPEC_LDS 41)
+ (UNSPEC_LDSA 42)
+ (UNSPEC_LDCCLR 43)
+ (UNSPEC_CHKACLR 45)
+ (UNSPEC_CHKS 47)
])
(define_constants
@@ -89,6 +99,8 @@
(UNSPECV_PSAC_NORMAL 6)
(UNSPECV_SETJMP_RECEIVER 7)
])
+
+(include "predicates.md")
;; ::::::::::::::::::::
;; ::
@@ -117,19 +129,21 @@
;; 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,nop_b,nop_f,
- nop_i,nop_m,nop_x,lfetch,pre_cycle"
+ fldp,fmac,fmisc,frar_i,frar_m,frbr,frfr,frpr,ialu,icmp,ilog,ishf,
+ ld,chk_s_i,chk_s_f,chk_a,long_i,mmalua,mmmul,mmshf,mmshfi,rse_m,scall,sem,stf,
+ st,syst_m0, syst_m,tbit,toar_i,toar_m,tobr,tofr,topr,xmpy,xtd,nop,
+ nop_b,nop_f,nop_i,nop_m,nop_x,lfetch,pre_cycle"
(const_string "unknown"))
-;; chk_s has an I and an M form; use type A for convenience.
+;; chk_s_i has an I and an M form; use type A for convenience.
(define_attr "type" "unknown,A,I,M,F,B,L,X,S"
- (cond [(eq_attr "itanium_class" "ld,st,fld,stf,sem,nop_m") (const_string "M")
+ (cond [(eq_attr "itanium_class" "ld,st,fld,fldp,stf,sem,nop_m") (const_string "M")
(eq_attr "itanium_class" "rse_m,syst_m,syst_m0") (const_string "M")
(eq_attr "itanium_class" "frar_m,toar_m,frfr,tofr") (const_string "M")
(eq_attr "itanium_class" "lfetch") (const_string "M")
- (eq_attr "itanium_class" "chk_s,ialu,icmp,ilog") (const_string "A")
+ (eq_attr "itanium_class" "chk_s_f,chk_a") (const_string "M")
+ (eq_attr "itanium_class" "chk_s_i,ialu,icmp,ilog,mmalua")
+ (const_string "A")
(eq_attr "itanium_class" "fmisc,fmac,fcmp,xmpy") (const_string "F")
(eq_attr "itanium_class" "fcvtfx,nop_f") (const_string "F")
(eq_attr "itanium_class" "frar_i,toar_i,frbr,tobr") (const_string "I")
@@ -158,8 +172,18 @@
(define_attr "empty" "no,yes" (const_string "no"))
-
+;; True iff this insn must be the first insn of an instruction group.
+;; This is true for the alloc instruction, and will also be true of others
+;; when we have full intrinsics support.
+
+(define_attr "first_insn" "no,yes" (const_string "no"))
+
+(define_attr "data_speculative" "no,yes" (const_string "no"))
+(define_attr "control_speculative" "no,yes" (const_string "no"))
+
+(define_attr "check_load" "no,yes" (const_string "no"))
+
;; DFA descriptions of ia64 processors used for insn scheduling and
;; bundling.
@@ -170,9 +194,6 @@
(automata_option "w")
-;;(automata_option "no-minimization")
-
-
(include "itanium1.md")
(include "itanium2.md")
@@ -198,8 +219,8 @@
(set_attr "predicable" "no")])
(define_insn "movbi"
- [(set (match_operand:BI 0 "nonimmediate_operand" "=c,c,?c,?*r, c,*r,*r,*m,*r")
- (match_operand:BI 1 "move_operand" " O,n, c, c,*r, n,*m,*r,*r"))]
+ [(set (match_operand:BI 0 "destination_operand" "=c,c,?c,?*r, c,*r,*r,*m,*r")
+ (match_operand:BI 1 "move_operand" " O,n, c, c,*r, n,*m,*r,*r"))]
""
"@
cmp.ne %0, %I0 = r0, r0
@@ -357,65 +378,252 @@
"mov pr = %1, -1"
};
- if (which_alternative == 2 && ! TARGET_NO_PIC
- && symbolic_operand (operands[1], VOIDmode))
- abort ();
+ gcc_assert (which_alternative != 2 || TARGET_NO_PIC
+ || !symbolic_operand (operands[1], VOIDmode));
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_mode_macro MODE [BI QI HI SI DI SF DF XF TI])
+(define_mode_macro MODE_FOR_EXTEND [QI HI SI])
+
+(define_mode_attr output_a [
+ (BI "ld1.a %0 = %1%P1")
+ (QI "ld1.a %0 = %1%P1")
+ (HI "ld2.a %0 = %1%P1")
+ (SI "ld4.a %0 = %1%P1")
+ (DI
+ "@
+ ld8.a %0 = %1%P1
+ ldf8.a %0 = %1%P1")
+ (SF
+ "@
+ ldfs.a %0 = %1%P1
+ ld4.a %0 = %1%P1")
+ (DF
+ "@
+ ldfd.a %0 = %1%P1
+ ld8.a %0 = %1%P1")
+ (XF "ldfe.a %0 = %1%P1")
+ (TI "ldfp8.a %X0 = %1%P1")])
+
+(define_mode_attr output_s [
+ (BI "ld1.s %0 = %1%P1")
+ (QI "ld1.s %0 = %1%P1")
+ (HI "ld2.s %0 = %1%P1")
+ (SI "ld4.s %0 = %1%P1")
+ (DI
+ "@
+ ld8.s %0 = %1%P1
+ ldf8.s %0 = %1%P1")
+ (SF
+ "@
+ ldfs.s %0 = %1%P1
+ ld4.s %0 = %1%P1")
+ (DF
+ "@
+ ldfd.s %0 = %1%P1
+ ld8.s %0 = %1%P1")
+ (XF "ldfe.s %0 = %1%P1")
+ (TI "ldfp8.s %X0 = %1%P1")])
+
+(define_mode_attr output_sa [
+ (BI "ld1.sa %0 = %1%P1")
+ (QI "ld1.sa %0 = %1%P1")
+ (HI "ld2.sa %0 = %1%P1")
+ (SI "ld4.sa %0 = %1%P1")
+ (DI
+ "@
+ ld8.sa %0 = %1%P1
+ ldf8.sa %0 = %1%P1")
+ (SF
+ "@
+ ldfs.sa %0 = %1%P1
+ ld4.sa %0 = %1%P1")
+ (DF
+ "@
+ ldfd.sa %0 = %1%P1
+ ld8.sa %0 = %1%P1")
+ (XF "ldfe.sa %0 = %1%P1")
+ (TI "ldfp8.sa %X0 = %1%P1")])
+
+(define_mode_attr output_c_clr [
+ (BI "ld1.c.clr%O1 %0 = %1%P1")
+ (QI "ld1.c.clr%O1 %0 = %1%P1")
+ (HI "ld2.c.clr%O1 %0 = %1%P1")
+ (SI "ld4.c.clr%O1 %0 = %1%P1")
+ (DI
+ "@
+ ld8.c.clr%O1 %0 = %1%P1
+ ldf8.c.clr %0 = %1%P1")
+ (SF
+ "@
+ ldfs.c.clr %0 = %1%P1
+ ld4.c.clr%O1 %0 = %1%P1")
+ (DF
+ "@
+ ldfd.c.clr %0 = %1%P1
+ ld8.c.clr%O1 %0 = %1%P1")
+ (XF "ldfe.c.clr %0 = %1%P1")
+ (TI "ldfp8.c.clr %X0 = %1%P1")])
+
+(define_mode_attr ld_reg_constr [(BI "=*r") (QI "=r") (HI "=r") (SI "=r") (DI "=r,*f") (SF "=f,*r") (DF "=f,*r") (XF "=f") (TI "=*x")])
+(define_mode_attr ldc_reg_constr [(BI "+*r") (QI "+r") (HI "+r") (SI "+r") (DI "+r,*f") (SF "+f,*r") (DF "+f,*r") (XF "+f") (TI "+*x")])
+(define_mode_attr chk_reg_constr [(BI "*r") (QI "r") (HI "r") (SI "r") (DI "r,*f") (SF "f,*r") (DF "f,*r") (XF "f") (TI "*x")])
+
+(define_mode_attr mem_constr [(BI "*m") (QI "m") (HI "m") (SI "m") (DI "m,Q") (SF "Q,m") (DF "Q,m") (XF "m") (TI "Q")])
+
+;; Define register predicate prefix.
+;; We can generate speculative loads only for general and fp registers - this
+;; is constrainted in ia64.c: ia64_speculate_insn ().
+(define_mode_attr reg_pred_prefix [(BI "gr") (QI "gr") (HI "gr") (SI "gr") (DI "grfr") (SF "grfr") (DF "grfr") (XF "fr") (TI "fr")])
+
+(define_mode_attr ld_class [(BI "ld") (QI "ld") (HI "ld") (SI "ld") (DI "ld,fld") (SF "fld,ld") (DF "fld,ld") (XF "fld") (TI "fldp")])
+(define_mode_attr chka_class [(BI "chk_a") (QI "chk_a") (HI "chk_a") (SI "chk_a") (DI "chk_a,chk_a") (SF "chk_a,chk_a") (DF "chk_a,chk_a") (XF "chk_a") (TI "chk_a")])
+(define_mode_attr chks_class [(BI "chk_s_i") (QI "chk_s_i") (HI "chk_s_i") (SI "chk_s_i") (DI "chk_s_i,chk_s_f") (SF "chk_s_f,chk_s_i") (DF "chk_s_f,chk_s_i") (XF "chk_s_f") (TI "chk_s_i")])
+
+(define_mode_attr attr_yes [(BI "yes") (QI "yes") (HI "yes") (SI "yes") (DI "yes,yes") (SF "yes,yes") (DF "yes,yes") (XF "yes") (TI "yes")])
+
+(define_insn "mov<mode>_advanced"
+ [(set (match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<ld_reg_constr>")
+ (unspec:MODE [(match_operand:MODE 1 "memory_operand" "<mem_constr>")] UNSPEC_LDA))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "<output_a>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "data_speculative" "<attr_yes>")])
+
+(define_insn "zero_extend<mode>di2_advanced"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (zero_extend:DI (unspec:MODE_FOR_EXTEND [(match_operand:MODE_FOR_EXTEND 1 "memory_operand" "<mem_constr>")] UNSPEC_LDA)))]
+ ""
+ "<output_a>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "data_speculative" "<attr_yes>")])
+
+(define_insn "mov<mode>_speculative"
+ [(set (match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<ld_reg_constr>")
+ (unspec:MODE [(match_operand:MODE 1 "memory_operand" "<mem_constr>")] UNSPEC_LDS))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "<output_s>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "control_speculative" "<attr_yes>")])
+
+(define_insn "zero_extend<mode>di2_speculative"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (zero_extend:DI (unspec:MODE_FOR_EXTEND [(match_operand:MODE_FOR_EXTEND 1 "memory_operand" "<mem_constr>")] UNSPEC_LDS)))]
+ ""
+ "<output_s>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "control_speculative" "<attr_yes>")])
+
+(define_insn "mov<mode>_speculative_advanced"
+ [(set (match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<ld_reg_constr>")
+ (unspec:MODE [(match_operand:MODE 1 "memory_operand" "<mem_constr>")] UNSPEC_LDSA))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "<output_sa>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "data_speculative" "<attr_yes>")
+ (set_attr "control_speculative" "<attr_yes>")])
+
+(define_insn "zero_extend<mode>di2_speculative_advanced"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (zero_extend:DI (unspec:MODE_FOR_EXTEND [(match_operand:MODE_FOR_EXTEND 1 "memory_operand" "<mem_constr>")] UNSPEC_LDSA)))]
+ ""
+ "<output_sa>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "data_speculative" "<attr_yes>")
+ (set_attr "control_speculative" "<attr_yes>")])
+
+(define_insn "mov<mode>_clr"
+ [(set (match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<ldc_reg_constr>")
+ (if_then_else:MODE (ne (unspec [(match_dup 0)] UNSPEC_LDCCLR) (const_int 0))
+ (match_operand:MODE 1 "memory_operand" "<mem_constr>")
+ (match_dup 0)))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "<output_c_clr>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "check_load" "<attr_yes>")])
+
+(define_insn "zero_extend<mode>di2_clr"
+ [(set (match_operand:DI 0 "gr_register_operand" "+r")
+ (if_then_else:DI (ne (unspec [(match_dup 0)] UNSPEC_LDCCLR) (const_int 0))
+ (zero_extend:DI (match_operand:MODE_FOR_EXTEND 1 "memory_operand" "<mem_constr>"))
+ (match_dup 0)))]
+ ""
+ "<output_c_clr>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "check_load" "<attr_yes>")])
+
+(define_insn "advanced_load_check_clr_<mode>"
+ [(set (pc)
+ (if_then_else (ne (unspec [(match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<chk_reg_constr>")] UNSPEC_CHKACLR) (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ ""
+ "chk.a.clr %0, %l1"
+ [(set_attr "itanium_class" "<chka_class>")])
+
+(define_insn "speculation_check_<mode>"
+ [(set (pc)
+ (if_then_else (ne (unspec [(match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<chk_reg_constr>")] UNSPEC_CHKS) (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ ""
+ "chk.s %0, %l1"
+ [(set_attr "itanium_class" "<chks_class>")])
+
(define_split
[(set (match_operand 0 "register_operand" "")
(match_operand 1 "symbolic_operand" ""))]
- "reload_completed && ! TARGET_NO_PIC"
+ "reload_completed"
[(const_int 0)]
{
- ia64_expand_load_address (operands[0], operands[1]);
- DONE;
+ if (ia64_expand_load_address (operands[0], operands[1]))
+ DONE;
+ else
+ FAIL;
})
(define_expand "load_fptr"
- [(set (match_dup 2)
- (plus:DI (reg:DI 1) (match_operand 1 "function_operand" "")))
- (set (match_operand:DI 0 "register_operand" "") (match_dup 3))]
- ""
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (match_dup 2) (match_operand 1 "function_operand" "")))
+ (set (match_dup 0) (match_dup 3))]
+ "reload_completed"
{
- 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;
+ operands[2] = pic_offset_table_rtx;
+ operands[3] = gen_const_mem (DImode, operands[0]);
})
(define_insn "*load_fptr_internal1"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (reg:DI 1) (match_operand 1 "function_operand" "s")))]
- ""
+ "reload_completed"
"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 1 "sdata_symbolic_operand" "s")))]
- ""
+ "reload_completed"
"addl %0 = @gprel(%1), gp"
[(set_attr "itanium_class" "ialu")])
-(define_insn "gprel64_offset"
+(define_insn "*gprel64_offset"
[(set (match_operand:DI 0 "register_operand" "=r")
(minus:DI (match_operand:DI 1 "symbolic_operand" "") (reg:DI 1)))]
- ""
+ "reload_completed"
"movl %0 = @gprel(%1)"
[(set_attr "itanium_class" "long_i")])
(define_expand "load_gprel64"
- [(set (match_dup 2)
- (minus:DI (match_operand:DI 1 "symbolic_operand" "") (match_dup 3)))
- (set (match_operand:DI 0 "register_operand" "")
- (plus:DI (match_dup 3) (match_dup 2)))]
- ""
+ [(set (match_operand:DI 0 "register_operand" "")
+ (minus:DI (match_operand:DI 1 "symbolic_operand" "") (match_dup 2)))
+ (set (match_dup 0)
+ (plus:DI (match_dup 2) (match_dup 0)))]
+ "reload_completed"
{
- operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
- operands[3] = pic_offset_table_rtx;
+ operands[2] = pic_offset_table_rtx;
})
;; This is used as a placeholder for the return address during early
@@ -441,7 +649,7 @@
[(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")))]
- ""
+ "reload_completed"
{
if (HAVE_AS_LTOFFX_LDXMOV_RELOCS)
return "%,addl %0 = @ltoffx(%1), %2";
@@ -454,7 +662,7 @@
[(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")))]
- ""
+ "reload_completed"
{
if (HAVE_AS_LTOFFX_LDXMOV_RELOCS)
return "%,ld8.mov %0 = [%1], %2";
@@ -463,34 +671,41 @@
}
[(set_attr "itanium_class" "ld")])
-(define_insn "load_ltoff_dtpmod"
+(define_insn_and_split "load_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)))]
+ (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
+ UNSPEC_DTPMOD))]
""
- "addl %0 = @ltoff(@dtpmod(%1)), gp"
- [(set_attr "itanium_class" "ialu")])
+ "#"
+ "reload_completed"
+ [(set (match_dup 0)
+ (plus:DI (unspec:DI [(match_dup 1)] UNSPEC_LTOFF_DTPMOD)
+ (match_dup 2)))
+ (set (match_dup 0) (match_dup 3))]
+{
+ operands[2] = pic_offset_table_rtx;
+ operands[3] = gen_const_mem (DImode, operands[0]);
+})
-(define_insn "load_ltoff_dtprel"
+(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_DTPREL)))]
- ""
- "addl %0 = @ltoff(@dtprel(%1)), gp"
+ (plus:DI (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
+ UNSPEC_LTOFF_DTPMOD)
+ (match_operand:DI 2 "register_operand" "a")))]
+ "reload_completed"
+ "addl %0 = @ltoff(@dtpmod(%1)), %2"
[(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:DI [(match_operand 1 "tls_symbolic_operand" "")]
UNSPEC_DTPREL))]
""
"")
(define_insn "*load_dtprel64"
[(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ (unspec:DI [(match_operand 1 "ld_tls_symbolic_operand" "")]
UNSPEC_DTPREL))]
"TARGET_TLS64"
"movl %0 = @dtprel(%1)"
@@ -498,57 +713,73 @@
(define_insn "*load_dtprel22"
[(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ (unspec:DI [(match_operand 1 "ld_tls_symbolic_operand" "")]
UNSPEC_DTPREL))]
""
"addl %0 = @dtprel(%1), r0"
[(set_attr "itanium_class" "ialu")])
+(define_insn_and_split "*load_dtprel_gd"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
+ UNSPEC_DTPREL))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0)
+ (plus:DI (unspec:DI [(match_dup 1)] UNSPEC_LTOFF_DTPREL)
+ (match_dup 2)))
+ (set (match_dup 0) (match_dup 3))]
+{
+ operands[2] = pic_offset_table_rtx;
+ operands[3] = gen_const_mem (DImode, operands[0]);
+})
+
+(define_insn "*load_ltoff_dtprel"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
+ UNSPEC_LTOFF_DTPREL)
+ (match_operand:DI 2 "register_operand" "a")))]
+ ""
+ "addl %0 = @ltoff(@dtprel(%1)), %2"
+ [(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)))]
+ (plus:DI (unspec:DI [(match_operand 1 "ld_tls_symbolic_operand" "")]
+ UNSPEC_DTPREL)
+ (match_operand:DI 2 "register_operand" "")))]
"!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)))]
+ (plus:DI (unspec:DI [(match_operand 1 "ld_tls_symbolic_operand" "")]
+ UNSPEC_DTPREL)
+ (match_operand:DI 2 "register_operand" "r")))]
"TARGET_TLS14"
- "adds %0 = @dtprel(%2), %1"
+ "adds %0 = @dtprel(%1), %2"
[(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)))]
+ (plus:DI (unspec:DI [(match_operand 1 "ld_tls_symbolic_operand" "")]
+ UNSPEC_DTPREL)
+ (match_operand:DI 2 "register_operand" "a")))]
"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"
+ "addl %0 = @dtprel(%1), %2"
[(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:DI [(match_operand 1 "tls_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:DI [(match_operand 1 "le_tls_symbolic_operand" "")]
UNSPEC_TPREL))]
"TARGET_TLS64"
"movl %0 = @tprel(%1)"
@@ -556,36 +787,61 @@
(define_insn "*load_tprel22"
[(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ (unspec:DI [(match_operand 1 "le_tls_symbolic_operand" "")]
UNSPEC_TPREL))]
""
"addl %0 = @tprel(%1), r0"
[(set_attr "itanium_class" "ialu")])
+(define_insn_and_split "*load_tprel_ie"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand 1 "ie_tls_symbolic_operand" "")]
+ UNSPEC_TPREL))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0)
+ (plus:DI (unspec:DI [(match_dup 1)] UNSPEC_LTOFF_TPREL)
+ (match_dup 2)))
+ (set (match_dup 0) (match_dup 3))]
+{
+ operands[2] = pic_offset_table_rtx;
+ operands[3] = gen_const_mem (DImode, operands[0]);
+})
+
+(define_insn "*load_ltoff_tprel"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (unspec:DI [(match_operand 1 "ie_tls_symbolic_operand" "")]
+ UNSPEC_LTOFF_TPREL)
+ (match_operand:DI 2 "register_operand" "a")))]
+ ""
+ "addl %0 = @ltoff(@tprel(%1)), %2"
+ [(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)))]
+ (plus:DI (unspec:DI [(match_operand 1 "le_tls_symbolic_operand" "")]
+ UNSPEC_TPREL)
+ (match_operand:DI 2 "register_operand" "")))]
"!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)))]
+ (plus:DI (unspec:DI [(match_operand 1 "le_tls_symbolic_operand" "")]
+ UNSPEC_TPREL)
+ (match_operand:DI 2 "register_operand" "r")))]
"TARGET_TLS14"
- "adds %0 = @tprel(%2), %1"
+ "adds %0 = @tprel(%1), %2"
[(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)))]
+ (plus:DI (unspec:DI [(match_operand 1 "le_tls_symbolic_operand" "")]
+ UNSPEC_TPREL)
+ (match_operand:DI 2 "register_operand" "a")))]
"TARGET_TLS22"
- "addl %0 = @tprel(%2), %1"
+ "addl %0 = @tprel(%1), %2"
[(set_attr "itanium_class" "ialu")])
;; With no offsettable memory references, we've got to have a scratch
@@ -604,18 +860,22 @@
})
(define_insn_and_split "*movti_internal"
- [(set (match_operand:TI 0 "nonimmediate_operand" "=r,r,m")
- (match_operand:TI 1 "general_operand" "ri,m,r"))]
+ [(set (match_operand:TI 0 "destination_operand" "=r, *fm,*x,*f, Q")
+ (match_operand:TI 1 "general_operand" "r*fim,r, Q, *fOQ,*f"))]
"ia64_move_ok (operands[0], operands[1])"
- "#"
- "reload_completed"
+ "@
+ #
+ #
+ ldfp8 %X0 = %1%P1
+ #
+ #"
+ "reload_completed && !ia64_load_pair_ok(operands[0], operands[1])"
[(const_int 0)]
{
ia64_split_tmode_move (operands);
DONE;
}
- [(set_attr "itanium_class" "unknown")
- (set_attr "predicable" "no")])
+ [(set_attr "itanium_class" "unknown,unknown,fldp,unknown,unknown")])
;; Floating Point Moves
;;
@@ -681,72 +941,15 @@
(match_operand:XF 1 "general_operand" ""))]
""
{
- /* We must support XFmode loads into general registers for stdarg/vararg
- and unprototyped calls. We split them into DImode loads for convenience.
- We don't need XFmode stores from general regs, because a stdarg/vararg
- routine does a block store to memory of unnamed arguments. */
- if (GET_CODE (operands[0]) == REG
- && GR_REGNO_P (REGNO (operands[0])))
- {
- /* We're hoping to transform everything that deals with XFmode
- quantities and GR registers early in the compiler. */
- if (no_new_pseudos)
- abort ();
-
- /* Struct to register can just use TImode instead. */
- if ((GET_CODE (operands[1]) == SUBREG
- && GET_MODE (SUBREG_REG (operands[1])) == TImode)
- || (GET_CODE (operands[1]) == REG
- && GR_REGNO_P (REGNO (operands[1]))))
- {
- emit_move_insn (gen_rtx_REG (TImode, REGNO (operands[0])),
- SUBREG_REG (operands[1]));
- DONE;
- }
-
- if (GET_CODE (operands[1]) == CONST_DOUBLE)
- {
- emit_move_insn (gen_rtx_REG (DImode, REGNO (operands[0])),
- operand_subword (operands[1], 0, 0, XFmode));
- emit_move_insn (gen_rtx_REG (DImode, REGNO (operands[0]) + 1),
- operand_subword (operands[1], 1, 0, XFmode));
- DONE;
- }
-
- /* If the quantity is in a register not known to be GR, spill it. */
- if (register_operand (operands[1], XFmode))
- operands[1] = spill_xfmode_operand (operands[1], 1);
-
- if (GET_CODE (operands[1]) == MEM)
- {
- rtx out[2];
-
- out[WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[0]));
- out[!WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[0])+1);
-
- emit_move_insn (out[0], adjust_address (operands[1], DImode, 0));
- emit_move_insn (out[1], adjust_address (operands[1], DImode, 8));
- DONE;
- }
-
- abort ();
- }
-
- if (! reload_in_progress && ! reload_completed)
- {
- operands[0] = spill_xfmode_operand (operands[0], 0);
- operands[1] = spill_xfmode_operand (operands[1], 0);
-
- if (! ia64_move_ok (operands[0], operands[1]))
- operands[1] = force_reg (XFmode, operands[1]);
- }
+ if (ia64_expand_movxf_movrf (XFmode, operands))
+ DONE;
})
;; ??? There's no easy way to mind volatile acquire/release semantics.
(define_insn "*movxf_internal"
- [(set (match_operand:XF 0 "destination_xfmode_operand" "=f,f, m")
- (match_operand:XF 1 "general_xfmode_operand" "fG,m,fG"))]
+ [(set (match_operand:XF 0 "destination_operand" "=f,f, m")
+ (match_operand:XF 1 "general_operand" "fG,m,fG"))]
"ia64_move_ok (operands[0], operands[1])"
"@
mov %0 = %F1
@@ -754,6 +957,26 @@
stfe %0 = %F1%P0"
[(set_attr "itanium_class" "fmisc,fld,stf")])
+;; Same as for movxf, but for RFmode.
+(define_expand "movrf"
+ [(set (match_operand:RF 0 "general_operand" "")
+ (match_operand:RF 1 "general_operand" ""))]
+ ""
+{
+ if (ia64_expand_movxf_movrf (RFmode, operands))
+ DONE;
+})
+
+(define_insn "*movrf_internal"
+ [(set (match_operand:RF 0 "destination_operand" "=f,f, m")
+ (match_operand:RF 1 "general_operand" "fG,m,fG"))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "@
+ mov %0 = %F1
+ ldf.fill %0 = %1%P1
+ stf.spill %0 = %F1%P0"
+ [(set_attr "itanium_class" "fmisc,fld,stf")])
+
;; Better code generation via insns that deal with TFmode register pairs
;; directly. Same concerns apply as for TImode.
(define_expand "movtf"
@@ -768,7 +991,7 @@
})
(define_insn_and_split "*movtf_internal"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=r,r,m")
+ [(set (match_operand:TF 0 "destination_operand" "=r,r,m")
(match_operand:TF 1 "general_operand" "ri,m,r"))]
"ia64_move_ok (operands[0], operands[1])"
"#"
@@ -839,10 +1062,10 @@
(match_operand:SI 1 "grfr_nonimmediate_operand" "r,m,f")))]
""
"@
- zxt4 %0 = %1
+ addp4 %0 = %1, r0
ld4%O1 %0 = %1%P1
fmix.r %0 = f0, %1"
- [(set_attr "itanium_class" "xtd,ld,fmisc")])
+ [(set_attr "itanium_class" "ialu,ld,fmisc")])
;; Convert between floating point types of different sizes.
@@ -1001,8 +1224,8 @@
(define_insn "extv"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
(sign_extract:DI (match_operand:DI 1 "gr_register_operand" "r")
- (match_operand:DI 2 "const_int_operand" "n")
- (match_operand:DI 3 "const_int_operand" "n")))]
+ (match_operand:DI 2 "extr_len_operand" "n")
+ (match_operand:DI 3 "shift_count_operand" "M")))]
""
"extr %0 = %1, %3, %2"
[(set_attr "itanium_class" "ishf")])
@@ -1010,8 +1233,8 @@
(define_insn "extzv"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
(zero_extract:DI (match_operand:DI 1 "gr_register_operand" "r")
- (match_operand:DI 2 "const_int_operand" "n")
- (match_operand:DI 3 "const_int_operand" "n")))]
+ (match_operand:DI 2 "extr_len_operand" "n")
+ (match_operand:DI 3 "shift_count_operand" "M")))]
""
"extr.u %0 = %1, %3, %2"
[(set_attr "itanium_class" "ishf")])
@@ -1111,6 +1334,15 @@
[(set_attr "itanium_class" "ishf")])
;; Combine doesn't like to create bit-field insertions into zero.
+(define_insn "*shladdp4_internal"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (and:DI (ashift:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "shladd_log2_operand" "n"))
+ (match_operand:DI 3 "const_int_operand" "n")))]
+ "ia64_depz_field_mask (operands[3], operands[2]) + INTVAL (operands[2]) == 32"
+ "shladdp4 %0 = %1, %2, r0"
+ [(set_attr "itanium_class" "ialu")])
+
(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")
@@ -1138,18 +1370,7 @@
(const_int 32) (const_int 0))
(match_operand:DI 1 "register_operand" ""))
(clobber (match_operand:DI 2 "register_operand" ""))]
- "reload_completed"
- [(set (match_dup 3) (ashift:DI (match_dup 1) (const_int 32)))
- (set (zero_extract:DI (match_dup 0) (const_int 32) (const_int 0))
- (lshiftrt:DI (match_dup 3) (const_int 32)))]
- "operands[3] = operands[2];")
-
-(define_split
- [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "")
- (const_int 32) (const_int 0))
- (match_operand:DI 1 "register_operand" ""))
- (clobber (match_operand:DI 2 "register_operand" ""))]
- "! reload_completed"
+ ""
[(set (match_dup 3) (ashift:DI (match_dup 1) (const_int 32)))
(set (zero_extract:DI (match_dup 0) (const_int 32) (const_int 0))
(lshiftrt:DI (match_dup 3) (const_int 32)))]
@@ -1409,7 +1630,7 @@
(and:BI (ne:BI (zero_extract:DI
(match_operand:DI 1 "gr_register_operand" "r")
(const_int 1)
- (match_operand:DI 2 "const_int_operand" "n"))
+ (match_operand:DI 2 "shift_count_operand" "M"))
(const_int 0))
(match_operand:BI 3 "register_operand" "0")))]
""
@@ -1421,7 +1642,7 @@
(and:BI (eq:BI (zero_extract:DI
(match_operand:DI 1 "gr_register_operand" "r")
(const_int 1)
- (match_operand:DI 2 "const_int_operand" "n"))
+ (match_operand:DI 2 "shift_count_operand" "M"))
(const_int 0))
(match_operand:BI 3 "register_operand" "0")))]
""
@@ -1533,7 +1754,7 @@
(ior:BI (ne:BI (zero_extract:DI
(match_operand:DI 1 "gr_register_operand" "r")
(const_int 1)
- (match_operand:DI 2 "const_int_operand" "n"))
+ (match_operand:DI 2 "shift_count_operand" "M"))
(const_int 0))
(match_operand:BI 3 "register_operand" "0")))]
""
@@ -1545,7 +1766,7 @@
(ior:BI (eq:BI (zero_extract:DI
(match_operand:DI 1 "gr_register_operand" "r")
(const_int 1)
- (match_operand:DI 2 "const_int_operand" "n"))
+ (match_operand:DI 2 "shift_count_operand" "M"))
(const_int 0))
(match_operand:BI 3 "register_operand" "0")))]
""
@@ -1855,8 +2076,7 @@
(match_operand:SI 2 "general_operand" "")))]
"TARGET_INLINE_INT_DIV"
{
- rtx op1_xf, op2_xf, op0_xf, op0_di, twon34;
- REAL_VALUE_TYPE twon34_r;
+ rtx op1_xf, op2_xf, op0_xf, op0_di, twon34, twon34_exp;
op0_xf = gen_reg_rtx (XFmode);
op0_di = gen_reg_rtx (DImode);
@@ -1872,10 +2092,14 @@
expand_float (op2_xf, operands[2], 0);
/* 2^-34 */
- real_2expN (&twon34_r, -34);
- twon34 = CONST_DOUBLE_FROM_REAL_VALUE (twon34_r, XFmode);
- twon34 = force_reg (XFmode, twon34);
-
+ twon34_exp = gen_reg_rtx (DImode);
+ emit_move_insn (twon34_exp, GEN_INT (65501));
+ twon34 = gen_reg_rtx (XFmode);
+ emit_insn (gen_setf_exp_xf (twon34, twon34_exp));
+
+ emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (SImode),
+ CONST1_RTX (SImode)));
+
emit_insn (gen_divsi3_internal (op0_xf, op1_xf, op2_xf, twon34));
emit_insn (gen_fix_truncxfdi2_alts (op0_di, op0_xf, const1_rtx));
@@ -1912,8 +2136,7 @@
(match_operand:SI 2 "general_operand" "")))]
"TARGET_INLINE_INT_DIV"
{
- rtx op1_xf, op2_xf, op0_xf, op0_di, twon34;
- REAL_VALUE_TYPE twon34_r;
+ rtx op1_xf, op2_xf, op0_xf, op0_di, twon34, twon34_exp;
op0_xf = gen_reg_rtx (XFmode);
op0_di = gen_reg_rtx (DImode);
@@ -1929,10 +2152,14 @@
expand_float (op2_xf, operands[2], 1);
/* 2^-34 */
- real_2expN (&twon34_r, -34);
- twon34 = CONST_DOUBLE_FROM_REAL_VALUE (twon34_r, XFmode);
- twon34 = force_reg (XFmode, twon34);
-
+ twon34_exp = gen_reg_rtx (DImode);
+ emit_move_insn (twon34_exp, GEN_INT (65501));
+ twon34 = gen_reg_rtx (XFmode);
+ emit_insn (gen_setf_exp_xf (twon34, twon34_exp));
+
+ emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (SImode),
+ CONST1_RTX (SImode)));
+
emit_insn (gen_divsi3_internal (op0_xf, op1_xf, op2_xf, twon34));
emit_insn (gen_fixuns_truncxfdi2_alts (op0_di, op0_xf, const1_rtx));
@@ -1983,8 +2210,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 5)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
- (match_dup 7)))
+ (minus:XF (match_dup 7)
+ (mult:XF (match_dup 2) (match_dup 0))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
@@ -2124,9 +2351,6 @@
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))]
"")
-;; ??? There are highpart multiply and add instructions, but we have no way
-;; to generate them.
-
(define_insn "smuldi3_highpart"
[(set (match_operand:DI 0 "fr_register_operand" "=f")
(truncate:DI
@@ -2294,7 +2518,10 @@
op2_xf = gen_reg_rtx (XFmode);
expand_float (op2_xf, operands[2], 0);
- if (TARGET_INLINE_INT_DIV_LAT)
+ emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (DImode),
+ CONST1_RTX (DImode)));
+
+ if (TARGET_INLINE_INT_DIV == INL_MIN_LAT)
emit_insn (gen_divdi3_internal_lat (op0_xf, op1_xf, op2_xf));
else
emit_insn (gen_divdi3_internal_thr (op0_xf, op1_xf, op2_xf));
@@ -2340,7 +2567,10 @@
op2_xf = gen_reg_rtx (XFmode);
expand_float (op2_xf, operands[2], 1);
- if (TARGET_INLINE_INT_DIV_LAT)
+ emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (DImode),
+ CONST1_RTX (DImode)));
+
+ if (TARGET_INLINE_INT_DIV == INL_MIN_LAT)
emit_insn (gen_divdi3_internal_lat (op0_xf, op1_xf, op2_xf));
else
emit_insn (gen_divdi3_internal_thr (op0_xf, op1_xf, op2_xf));
@@ -2374,7 +2604,7 @@
(clobber (match_scratch:XF 4 "=&f"))
(clobber (match_scratch:XF 5 "=&f"))
(clobber (match_scratch:BI 6 "=c"))]
- "TARGET_INLINE_INT_DIV_LAT"
+ "TARGET_INLINE_INT_DIV == INL_MIN_LAT"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2)))
@@ -2383,8 +2613,8 @@
(use (const_int 1))])
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
- (match_dup 7)))
+ (minus:XF (match_dup 7)
+ (mult:XF (match_dup 2) (match_dup 0))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4) (mult:XF (match_dup 1) (match_dup 0)))
@@ -2414,8 +2644,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 3)))
- (match_dup 1)))
+ (minus:XF (match_dup 1)
+ (mult:XF (match_dup 2) (match_dup 3))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 0)
@@ -2433,7 +2663,7 @@
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:XF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
- "TARGET_INLINE_INT_DIV_THR"
+ "TARGET_INLINE_INT_DIV == INL_MAX_THR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2)))
@@ -2442,8 +2672,8 @@
(use (const_int 1))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
- (match_dup 6)))
+ (minus:XF (match_dup 6)
+ (mult:XF (match_dup 2) (match_dup 0))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 0)
@@ -2463,8 +2693,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 3)))
- (match_dup 1)))
+ (minus:XF (match_dup 1)
+ (mult:XF (match_dup 2) (match_dup 3))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 0)
@@ -2477,6 +2707,200 @@
;; ::::::::::::::::::::
;; ::
+;; :: 128 bit Integer arithmetic
+;; ::
+;; ::::::::::::::::::::
+
+(define_insn "addti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (plus:TI (match_operand:TI 1 "gr_register_operand" "%r")
+ (match_operand:TI 2 "gr_reg_or_14bit_operand" "rI")))
+ (clobber (match_scratch:BI 3 "=&c"))]
+ ""
+ "#"
+ [(set_attr "itanium_class" "unknown")])
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (plus:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:TI 2 "register_operand" "")))
+ (clobber (match_scratch:BI 3 ""))]
+ "reload_completed"
+ [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (ltu:BI (match_dup 0) (match_dup 1)))
+ (cond_exec (eq (match_dup 3) (const_int 0))
+ (set (match_dup 4) (plus:DI (match_dup 5) (match_dup 6))))
+ (cond_exec (ne (match_dup 3) (const_int 0))
+ (set (match_dup 4)
+ (plus:DI (plus:DI (match_dup 5) (match_dup 6))
+ (const_int 1))))]
+{
+ operands[4] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[5] = gen_highpart (DImode, operands[1]);
+ operands[1] = gen_lowpart (DImode, operands[1]);
+ operands[6] = gen_highpart (DImode, operands[2]);
+ operands[2] = gen_lowpart (DImode, operands[2]);
+})
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (plus:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:TI 2 "immediate_operand" "")))
+ (clobber (match_scratch:BI 3 ""))]
+ "reload_completed"
+ [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (ltu:BI (match_dup 0) (match_dup 1)))
+ (cond_exec (eq (match_dup 3) (const_int 0))
+ (set (match_dup 4)
+ (plus:DI (match_dup 5) (match_dup 6))))
+ (cond_exec (ne (match_dup 3) (const_int 0))
+ (set (match_dup 4)
+ (plus:DI (match_dup 5) (match_dup 7))))]
+{
+ operands[4] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[5] = gen_highpart (DImode, operands[1]);
+ operands[1] = gen_lowpart (DImode, operands[1]);
+ operands[6] = INTVAL (operands[2]) < 0 ? constm1_rtx : const0_rtx;
+ operands[7] = INTVAL (operands[2]) < 0 ? const0_rtx : const1_rtx;
+})
+
+(define_insn "subti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (minus:TI (match_operand:TI 1 "gr_reg_or_8bit_operand" "rK")
+ (match_operand:TI 2 "gr_register_operand" "r")))
+ (clobber (match_scratch:BI 3 "=&c"))]
+ ""
+ "#"
+ [(set_attr "itanium_class" "unknown")])
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (minus:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:TI 2 "register_operand" "")))
+ (clobber (match_scratch:BI 3 "=&c"))]
+ "reload_completed"
+ [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (ltu:BI (match_dup 1) (match_dup 0)))
+ (cond_exec (eq (match_dup 3) (const_int 0))
+ (set (match_dup 4) (minus:DI (match_dup 5) (match_dup 6))))
+ (cond_exec (ne (match_dup 3) (const_int 0))
+ (set (match_dup 4)
+ (plus:DI (not:DI (match_dup 6)) (match_dup 5))))]
+{
+ operands[4] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[5] = gen_highpart (DImode, operands[1]);
+ operands[1] = gen_lowpart (DImode, operands[1]);
+ operands[6] = gen_highpart (DImode, operands[2]);
+ operands[2] = gen_lowpart (DImode, operands[2]);
+})
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (minus:TI (match_operand:TI 1 "immediate_operand" "")
+ (match_operand:TI 2 "register_operand" "")))
+ (clobber (match_scratch:BI 3 "=&c"))]
+ "reload_completed && CONST_OK_FOR_K (INTVAL (operands[1]))"
+ [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (gtu:BI (match_dup 0) (match_dup 1)))
+ (cond_exec (ne (match_dup 3) (const_int 0))
+ (set (match_dup 4) (minus:DI (match_dup 6) (match_dup 5))))
+ (cond_exec (eq (match_dup 3) (const_int 0))
+ (set (match_dup 4) (minus:DI (match_dup 7) (match_dup 5))))]
+{
+ operands[4] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[5] = gen_highpart (DImode, operands[2]);
+ operands[2] = gen_lowpart (DImode, operands[2]);
+ operands[6] = INTVAL (operands[1]) < 0 ? GEN_INT (-2) : constm1_rtx;
+ operands[7] = INTVAL (operands[1]) < 0 ? constm1_rtx : const0_rtx;
+})
+
+(define_expand "mulditi3"
+ [(set (match_operand:TI 0 "fr_register_operand" "")
+ (mult:TI (sign_extend:TI
+ (match_operand:DI 1 "fr_register_operand" ""))
+ (sign_extend:TI
+ (match_operand:DI 2 "fr_register_operand" ""))))]
+ ""
+ "")
+
+(define_insn_and_split "*mulditi3_internal"
+ [(set (match_operand:TI 0 "fr_register_operand" "=&f")
+ (mult:TI (sign_extend:TI
+ (match_operand:DI 1 "fr_register_operand" "%f"))
+ (sign_extend:TI
+ (match_operand:DI 2 "fr_register_operand" "f"))))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0) (mult:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (sign_extend:TI (match_dup 1))
+ (sign_extend:TI (match_dup 2)))
+ (const_int 64))))]
+{
+ operands[3] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+}
+ [(set_attr "itanium_class" "unknown")])
+
+(define_expand "umulditi3"
+ [(set (match_operand:TI 0 "fr_register_operand" "")
+ (mult:TI (zero_extend:TI
+ (match_operand:DI 1 "fr_register_operand" ""))
+ (zero_extend:TI
+ (match_operand:DI 2 "fr_register_operand" ""))))]
+ ""
+ "")
+
+(define_insn_and_split "*umulditi3_internal"
+ [(set (match_operand:TI 0 "fr_register_operand" "=&f")
+ (mult:TI (zero_extend:TI
+ (match_operand:DI 1 "fr_register_operand" "%f"))
+ (zero_extend:TI
+ (match_operand:DI 2 "fr_register_operand" "f"))))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0) (mult:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (zero_extend:TI (match_dup 1))
+ (zero_extend:TI (match_dup 2)))
+ (const_int 64))))]
+{
+ operands[3] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+}
+ [(set_attr "itanium_class" "unknown")])
+
+(define_insn_and_split "negti2"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (neg:TI (match_operand:TI 1 "gr_register_operand" "r")))
+ (clobber (match_scratch:BI 2 "=&c"))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 2) (eq:BI (match_dup 1) (const_int 0)))
+ (set (match_dup 0) (minus:DI (const_int 0) (match_dup 1)))
+ (cond_exec (eq (match_dup 2) (const_int 0))
+ (set (match_dup 3) (minus:DI (const_int -1) (match_dup 4))))
+ (cond_exec (ne (match_dup 2) (const_int 0))
+ (set (match_dup 3) (minus:DI (const_int 0) (match_dup 4))))]
+{
+ operands[3] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[4] = gen_highpart (DImode, operands[1]);
+ operands[1] = gen_lowpart (DImode, operands[1]);
+}
+ [(set_attr "itanium_class" "unknown")])
+
+;; ::::::::::::::::::::
+;; ::
;; :: 32 bit floating point arithmetic
;; ::
;; ::::::::::::::::::::
@@ -2526,7 +2950,25 @@
"fnegabs %0 = %1"
[(set_attr "itanium_class" "fmisc")])
-(define_insn "minsf3"
+(define_insn "copysignsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (unspec:SF [(match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN))]
+ ""
+ "fmerge.s %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*ncopysignsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (neg:SF (unspec:SF [(match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN)))]
+ ""
+ "fmerge.ns %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "sminsf3"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(smin:SF (match_operand:SF 1 "fr_register_operand" "f")
(match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))]
@@ -2534,7 +2976,7 @@
"fmin %0 = %1, %F2"
[(set_attr "itanium_class" "fmisc")])
-(define_insn "maxsf3"
+(define_insn "smaxsf3"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(smax:SF (match_operand:SF 1 "fr_register_operand" "f")
(match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))]
@@ -2568,18 +3010,25 @@
"fnmpy.s %0 = %1, %2"
[(set_attr "itanium_class" "fmac")])
-;; ??? Is it possible to canonicalize this as (minus (reg) (mult))?
-
(define_insn "*nmaddsf4"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
- (plus:SF (neg:SF (mult:SF
- (match_operand:SF 1 "fr_register_operand" "f")
- (match_operand:SF 2 "fr_register_operand" "f")))
- (match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")))]
+ (minus:SF (match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")
+ (mult:SF (match_operand:SF 1 "fr_register_operand" "f")
+ (match_operand:SF 2 "fr_register_operand" "f"))))]
""
"fnma.s %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
+(define_insn "*nmaddsf4_alts"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (minus:SF (match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")
+ (mult:SF (match_operand:SF 1 "fr_register_operand" "f")
+ (match_operand:SF 2 "fr_register_operand" "f"))))
+ (use (match_operand:SI 4 "const_int_operand" ""))]
+ ""
+ "fnma.s.s%4 %0 = %1, %2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
(define_expand "divsf3"
[(set (match_operand:SF 0 "fr_register_operand" "")
(div:SF (match_operand:SF 1 "fr_register_operand" "")
@@ -2587,7 +3036,7 @@
"TARGET_INLINE_FLOAT_DIV"
{
rtx insn;
- if (TARGET_INLINE_FLOAT_DIV_LAT)
+ if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT)
insn = gen_divsf3_internal_lat (operands[0], operands[1], operands[2]);
else
insn = gen_divsf3_internal_thr (operands[0], operands[1], operands[2]);
@@ -2602,20 +3051,20 @@
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:XF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
- "TARGET_INLINE_FLOAT_DIV_LAT"
+ "TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 6) (div:XF (const_int 1) (match_dup 8)))
(set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)]
UNSPEC_FR_RECIP_APPROX))
- (use (const_int 1))])
+ (use (const_int 0))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3) (mult:XF (match_dup 7) (match_dup 6)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 6)))
- (match_dup 10)))
+ (minus:XF (match_dup 10)
+ (mult:XF (match_dup 8) (match_dup 6))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
@@ -2659,17 +3108,17 @@
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:XF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
- "TARGET_INLINE_FLOAT_DIV_THR"
+ "TARGET_INLINE_FLOAT_DIV == INL_MAX_THR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 6) (div:XF (const_int 1) (match_dup 8)))
(set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)]
UNSPEC_FR_RECIP_APPROX))
- (use (const_int 1))])
+ (use (const_int 0))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 6)))
- (match_dup 10)))
+ (minus:XF (match_dup 10)
+ (mult:XF (match_dup 8) (match_dup 6))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
@@ -2688,8 +3137,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 3)))
- (match_dup 7)))
+ (minus:XF (match_dup 7)
+ (mult:XF (match_dup 8) (match_dup 3))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(set (match_dup 0)
@@ -2720,7 +3169,7 @@
[(set_attr "itanium_class" "fmisc")
(set_attr "predicable" "no")])
-(define_insn "*setf_exp_xf"
+(define_insn "setf_exp_xf"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(unspec:XF [(match_operand:DI 1 "register_operand" "r")]
UNSPEC_SETF_EXP))]
@@ -2734,14 +3183,14 @@
"TARGET_INLINE_SQRT"
{
rtx insn;
- if (TARGET_INLINE_SQRT_LAT)
#if 0
+ if (TARGET_INLINE_SQRT == INL_MIN_LAT)
insn = gen_sqrtsf2_internal_lat (operands[0], operands[1]);
+ else
#else
- abort ();
+ gcc_assert (TARGET_INLINE_SQRT != INL_MIN_LAT);
#endif
- else
- insn = gen_sqrtsf2_internal_thr (operands[0], operands[1]);
+ insn = gen_sqrtsf2_internal_thr (operands[0], operands[1]);
emit_insn (insn);
DONE;
})
@@ -2764,7 +3213,7 @@
(clobber (match_scratch:XF 5 "=&f"))
;; Register p6 in optimization guide.
(clobber (match_scratch:BI 6 "=c"))]
- "TARGET_INLINE_SQRT_THR"
+ "TARGET_INLINE_SQRT == INL_MAX_THR"
"#"
"&& reload_completed"
[ ;; exponent of +1/2 in r2
@@ -2799,8 +3248,8 @@
;; d = 1/2 - S0 * H0 in f10
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 5)
- (plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 4)))
- (match_dup 3)))
+ (minus:XF (match_dup 3)
+ (mult:XF (match_dup 7) (match_dup 4))))
(use (const_int 1))]))
;; Step 5
;; d' = d + 1/2 * d in f8
@@ -2835,8 +3284,8 @@
;; d1 = a - S1 * S1 in f9
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 7)))
- (match_dup 8)))
+ (minus:XF (match_dup 8)
+ (mult:XF (match_dup 7) (match_dup 7))))
(use (const_int 1))]))
;; Step 10
;; S = S1 + d1 * H1 in f7
@@ -2933,7 +3382,25 @@
"fnegabs %0 = %1"
[(set_attr "itanium_class" "fmisc")])
-(define_insn "mindf3"
+(define_insn "copysigndf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN))]
+ ""
+ "fmerge.s %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*ncopysigndf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (neg:DF (unspec:DF [(match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN)))]
+ ""
+ "fmerge.ns %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "smindf3"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(smin:DF (match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))]
@@ -2941,7 +3408,7 @@
"fmin %0 = %1, %F2"
[(set_attr "itanium_class" "fmisc")])
-(define_insn "maxdf3"
+(define_insn "smaxdf3"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(smax:DF (match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))]
@@ -3004,40 +3471,46 @@
"fnmpy.s %0 = %1, %2"
[(set_attr "itanium_class" "fmac")])
-;; ??? Is it possible to canonicalize this as (minus (reg) (mult))?
-
(define_insn "*nmadddf4"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
- (plus:DF (neg:DF (mult:DF
- (match_operand:DF 1 "fr_register_operand" "f")
- (match_operand:DF 2 "fr_register_operand" "f")))
- (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))]
+ (minus:DF (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")
+ (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
+ (match_operand:DF 2 "fr_register_operand" "f"))))]
""
"fnma.d %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
(define_insn "*nmadddf4_alts"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
- (plus:DF (neg:DF (mult:DF
- (match_operand:DF 1 "fr_register_operand" "f")
- (match_operand:DF 2 "fr_register_operand" "f")))
- (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))
+ (minus:DF (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")
+ (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
+ (match_operand:DF 2 "fr_register_operand" "f"))))
(use (match_operand:SI 4 "const_int_operand" ""))]
""
"fnma.d.s%4 %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
-(define_insn "*nmadddf4_trunc"
+(define_insn "*nmadddf4_truncsf"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
- (plus:DF (neg:DF (mult:DF
- (match_operand:DF 1 "fr_register_operand" "f")
- (match_operand:DF 2 "fr_register_operand" "f")))
- (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG"))))]
+ (minus:DF (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")
+ (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
+ (match_operand:DF 2 "fr_register_operand" "f")))))]
""
"fnma.s %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
+(define_insn "*nmadddf4_truncsf_alts"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (minus:DF (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")
+ (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
+ (match_operand:DF 2 "fr_register_operand" "f")))))
+ (use (match_operand:SI 4 "const_int_operand" ""))]
+ ""
+ "fnma.s.s%4 %0 = %1, %2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
(define_expand "divdf3"
[(set (match_operand:DF 0 "fr_register_operand" "")
(div:DF (match_operand:DF 1 "fr_register_operand" "")
@@ -3045,7 +3518,7 @@
"TARGET_INLINE_FLOAT_DIV"
{
rtx insn;
- if (TARGET_INLINE_FLOAT_DIV_LAT)
+ if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT)
insn = gen_divdf3_internal_lat (operands[0], operands[1], operands[2]);
else
insn = gen_divdf3_internal_thr (operands[0], operands[1], operands[2]);
@@ -3061,20 +3534,20 @@
(clobber (match_scratch:XF 4 "=&f"))
(clobber (match_scratch:XF 5 "=&f"))
(clobber (match_scratch:BI 6 "=c"))]
- "TARGET_INLINE_FLOAT_DIV_LAT"
+ "TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 7) (div:XF (const_int 1) (match_dup 9)))
(set (match_dup 6) (unspec:BI [(match_dup 8) (match_dup 9)]
UNSPEC_FR_RECIP_APPROX))
- (use (const_int 1))])
+ (use (const_int 0))])
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3) (mult:XF (match_dup 8) (match_dup 7)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 9) (match_dup 7)))
- (match_dup 12)))
+ (minus:XF (match_dup 12)
+ (mult:XF (match_dup 9) (match_dup 7))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3)
@@ -3116,8 +3589,8 @@
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 11)
(float_truncate:DF
- (plus:XF (neg:XF (mult:XF (match_dup 9) (match_dup 3)))
- (match_dup 8))))
+ (minus:XF (match_dup 8)
+ (mult:XF (match_dup 9) (match_dup 3)))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(set (match_dup 0)
@@ -3141,17 +3614,17 @@
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:DF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
- "TARGET_INLINE_FLOAT_DIV_THR"
+ "TARGET_INLINE_FLOAT_DIV == INL_MAX_THR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 6) (div:XF (const_int 1) (match_dup 8)))
(set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)]
UNSPEC_FR_RECIP_APPROX))
- (use (const_int 1))])
+ (use (const_int 0))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 6)))
- (match_dup 10)))
+ (minus:XF (match_dup 10)
+ (mult:XF (match_dup 8) (match_dup 6))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 6)
@@ -3179,12 +3652,12 @@
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 9)
(float_truncate:DF
- (mult:XF (match_dup 7) (match_dup 3))))
+ (mult:XF (match_dup 7) (match_dup 6))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:DF (neg:DF (mult:DF (match_dup 2) (match_dup 9)))
- (match_dup 1)))
+ (minus:DF (match_dup 1)
+ (mult:DF (match_dup 2) (match_dup 9))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(set (match_dup 0)
@@ -3208,14 +3681,14 @@
"TARGET_INLINE_SQRT"
{
rtx insn;
- if (TARGET_INLINE_SQRT_LAT)
#if 0
+ if (TARGET_INLINE_SQRT == INL_MIN_LAT)
insn = gen_sqrtdf2_internal_lat (operands[0], operands[1]);
+ else
#else
- abort ();
+ gcc_assert (TARGET_INLINE_SQRT != INL_MIN_LAT);
#endif
- else
- insn = gen_sqrtdf2_internal_thr (operands[0], operands[1]);
+ insn = gen_sqrtdf2_internal_thr (operands[0], operands[1]);
emit_insn (insn);
DONE;
})
@@ -3238,7 +3711,7 @@
(clobber (match_scratch:XF 5 "=&f"))
;; Register p6 in optimization guide.
(clobber (match_scratch:BI 6 "=c"))]
- "TARGET_INLINE_SQRT_THR"
+ "TARGET_INLINE_SQRT == INL_MAX_THR"
"#"
"&& reload_completed"
[ ;; exponent of +1/2 in r2
@@ -3273,8 +3746,8 @@
;; r0 = 1/2 - G0 * H0 in f9
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 3)))
- (match_dup 5)))
+ (minus:XF (match_dup 5)
+ (mult:XF (match_dup 7) (match_dup 3))))
(use (const_int 1))]))
;; Step 5
;; H1 = H0 + r0 * H0 in f8
@@ -3294,8 +3767,8 @@
;; r1 = 1/2 - G1 * H1 in f9
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 3)))
- (match_dup 5)))
+ (minus:XF (match_dup 5)
+ (mult:XF (match_dup 7) (match_dup 3))))
(use (const_int 1))]))
;; Step 8
;; H2 = H1 + r1 * H1 in f8
@@ -3315,8 +3788,8 @@
;; d2 = a - G2 * G2 in f9
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 7)))
- (match_dup 8)))
+ (minus:XF (match_dup 8)
+ (mult:XF (match_dup 7) (match_dup 7))))
(use (const_int 1))]))
;; Step 11
;; G3 = G2 + d2 * H2 in f7
@@ -3329,8 +3802,8 @@
;; d3 = a - G3 * G3 in f9
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 7)))
- (match_dup 8)))
+ (minus:XF (match_dup 8)
+ (mult:XF (match_dup 7) (match_dup 7))))
(use (const_int 1))]))
;; Step 13
;; S = G3 + d3 * H2 in f7
@@ -3483,7 +3956,25 @@
"fnegabs %0 = %F1"
[(set_attr "itanium_class" "fmisc")])
-(define_insn "minxf3"
+(define_insn "copysignxf3"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN))]
+ ""
+ "fmerge.s %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*ncopysignxf3"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (neg:XF (unspec:XF [(match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN)))]
+ ""
+ "fmerge.ns %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "sminxf3"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(smin:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))]
@@ -3491,7 +3982,7 @@
"fmin %0 = %F1, %F2"
[(set_attr "itanium_class" "fmisc")])
-(define_insn "maxxf3"
+(define_insn "smaxxf3"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(smax:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))]
@@ -3617,14 +4108,12 @@
"fnmpy.d %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
-;; ??? Is it possible to canonicalize this as (minus (reg) (mult))?
-
(define_insn "*nmaddxf4"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
- (plus:XF (neg:XF (mult:XF
- (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")))]
+ (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")
+ (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
+ )))]
""
"fnma %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3632,10 +4121,10 @@
(define_insn "*nmaddxf4_truncsf"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
- (plus:XF (neg:XF (mult:XF
- (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))]
+ (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")
+ (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
+ ))))]
""
"fnma.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3643,33 +4132,44 @@
(define_insn "*nmaddxf4_truncdf"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(float_truncate:DF
- (plus:XF (neg:XF (mult:XF
- (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))]
+ (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")
+ (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
+ ))))]
""
"fnma.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
(define_insn "*nmaddxf4_alts"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
- (plus:XF (neg:XF (mult:XF
- (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")))
+ (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")
+ (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
+ )))
(use (match_operand:SI 4 "const_int_operand" ""))]
""
"fnma.s%4 %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
+(define_insn "*nmaddxf4_truncsf_alts"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")
+ (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
+ ))))
+ (use (match_operand:SI 4 "const_int_operand" ""))]
+ ""
+ "fnma.s.s%4 %0 = %F1, %F2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
(define_insn "*nmaddxf4_truncdf_alts"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(float_truncate:DF
- (plus:XF (neg:XF
- (mult:XF
- (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))
+ (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")
+ (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
+ ))))
(use (match_operand:SI 4 "const_int_operand" ""))]
""
"fnma.d.s%4 %0 = %F1, %F2, %F3"
@@ -3682,7 +4182,7 @@
"TARGET_INLINE_FLOAT_DIV"
{
rtx insn;
- if (TARGET_INLINE_FLOAT_DIV_LAT)
+ if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT)
insn = gen_divxf3_internal_lat (operands[0], operands[1], operands[2]);
else
insn = gen_divxf3_internal_thr (operands[0], operands[1], operands[2]);
@@ -3699,17 +4199,17 @@
(clobber (match_scratch:XF 5 "=&f"))
(clobber (match_scratch:XF 6 "=&f"))
(clobber (match_scratch:BI 7 "=c"))]
- "TARGET_INLINE_FLOAT_DIV_LAT"
+ "TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2)))
(set (match_dup 7) (unspec:BI [(match_dup 1) (match_dup 2)]
UNSPEC_FR_RECIP_APPROX))
- (use (const_int 1))])
+ (use (const_int 0))])
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
- (match_dup 8)))
+ (minus:XF (match_dup 8)
+ (mult:XF (match_dup 2) (match_dup 0))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 4) (mult:XF (match_dup 1) (match_dup 0)))
@@ -3739,8 +4239,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 4)))
- (match_dup 1)))
+ (minus:XF (match_dup 1)
+ (mult:XF (match_dup 2) (match_dup 4))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 3)
@@ -3749,8 +4249,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 5)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
- (match_dup 8)))
+ (minus:XF (match_dup 8)
+ (mult:XF (match_dup 2) (match_dup 0))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 0)
@@ -3759,8 +4259,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 3)))
- (match_dup 1)))
+ (minus:XF (match_dup 1)
+ (mult:XF (match_dup 2) (match_dup 3))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(set (match_dup 0)
@@ -3777,17 +4277,17 @@
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:XF 4 "=&f"))
(clobber (match_scratch:BI 5 "=c"))]
- "TARGET_INLINE_FLOAT_DIV_THR"
+ "TARGET_INLINE_FLOAT_DIV == INL_MAX_THR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2)))
(set (match_dup 5) (unspec:BI [(match_dup 1) (match_dup 2)]
UNSPEC_FR_RECIP_APPROX))
- (use (const_int 1))])
+ (use (const_int 0))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
- (match_dup 6)))
+ (minus:XF (match_dup 6)
+ (mult:XF (match_dup 2) (match_dup 0))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
@@ -3807,8 +4307,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 0)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 3)))
- (match_dup 6)))
+ (minus:XF (match_dup 6)
+ (mult:XF (match_dup 2) (match_dup 3))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 0)
@@ -3817,8 +4317,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 4)))
- (match_dup 1)))
+ (minus:XF (match_dup 1)
+ (mult:XF (match_dup 2) (match_dup 4))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
@@ -3827,8 +4327,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
- (match_dup 6)))
+ (minus:XF (match_dup 6)
+ (mult:XF (match_dup 2) (match_dup 0))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 0)
@@ -3837,8 +4337,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 3)))
- (match_dup 1)))
+ (minus:XF (match_dup 1)
+ (mult:XF (match_dup 2) (match_dup 3))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(set (match_dup 0)
@@ -3856,14 +4356,14 @@
"TARGET_INLINE_SQRT"
{
rtx insn;
- if (TARGET_INLINE_SQRT_LAT)
#if 0
+ if (TARGET_INLINE_SQRT == INL_MIN_LAT)
insn = gen_sqrtxf2_internal_lat (operands[0], operands[1]);
+ else
#else
- abort ();
+ gcc_assert (TARGET_INLINE_SQRT != INL_MIN_LAT);
#endif
- else
- insn = gen_sqrtxf2_internal_thr (operands[0], operands[1]);
+ insn = gen_sqrtxf2_internal_thr (operands[0], operands[1]);
emit_insn (insn);
DONE;
})
@@ -3888,7 +4388,7 @@
(clobber (match_scratch:XF 6 "=&f"))
;; Register p6 in optimization guide.
(clobber (match_scratch:BI 7 "=c"))]
- "TARGET_INLINE_SQRT_THR"
+ "TARGET_INLINE_SQRT == INL_MAX_THR"
"#"
"&& reload_completed"
[ ;; exponent of +1/2 in r2
@@ -3923,8 +4423,8 @@
;; d0 = 1/2 - S0 * H0 in f10
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 5)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 4)))
- (match_dup 3)))
+ (minus:XF (match_dup 3)
+ (mult:XF (match_dup 8) (match_dup 4))))
(use (const_int 1))]))
;; Step 5
;; H1 = H0 + d0 * H0 in f9
@@ -3944,8 +4444,8 @@
;; d1 = 1/2 - S1 * H1 in f10
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 5)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 4)))
- (match_dup 3)))
+ (minus:XF (match_dup 3)
+ (mult:XF (match_dup 8) (match_dup 4))))
(use (const_int 1))]))
;; Step 8
;; H2 = H1 + d1 * H1 in f9
@@ -3965,15 +4465,15 @@
;; d2 = 1/2 - S2 * H2 in f10
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 5)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 4)))
- (match_dup 3)))
+ (minus:XF (match_dup 3)
+ (mult:XF (match_dup 8) (match_dup 4))))
(use (const_int 1))]))
;; Step 11
;; e2 = a - S2 * S2 in f8
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 8)))
- (match_dup 9)))
+ (minus:XF (match_dup 9)
+ (mult:XF (match_dup 8) (match_dup 8))))
(use (const_int 1))]))
;; Step 12
;; S3 = S2 + e2 * H2 in f7
@@ -3993,8 +4493,8 @@
;; e3 = a - S3 * S3 in f8
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 8)))
- (match_dup 9)))
+ (minus:XF (match_dup 9)
+ (mult:XF (match_dup 8) (match_dup 8))))
(use (const_int 1))]))
;; Step 15
;; S = S3 + e3 * H3 in f7
@@ -4154,8 +4654,8 @@
(rotate:SI (match_operand:SI 1 "gr_register_operand" "r")
(match_operand:SI 2 "shift_32bit_count_operand" "n")))]
""
- "#"
- "reload_completed"
+ "mux2 %0 = %1, 0xe1"
+ "reload_completed && INTVAL (operands[2]) != 16"
[(set (match_dup 3)
(ior:DI (zero_extend:DI (match_dup 1))
(ashift:DI (zero_extend:DI (match_dup 1)) (const_int 32))))
@@ -4164,7 +4664,8 @@
{
operands[3] = gen_rtx_REG (DImode, REGNO (operands[0]));
operands[2] = GEN_INT (32 - INTVAL (operands[2]));
-})
+}
+ [(set_attr "itanium_class" "mmshf")])
;; ::::::::::::::::::::
;; ::
@@ -4209,7 +4710,7 @@
(match_operand:DI 3 "nonmemory_operand" "r"))
(match_operand:DI 4 "nonmemory_operand" "rI")))]
"reload_in_progress"
- "* abort ();"
+ "* gcc_unreachable ();"
"reload_completed"
[(set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (match_dup 2))
(match_dup 3)))
@@ -4280,6 +4781,199 @@
;; ::::::::::::::::::::
;; ::
+;; :: 128 bit Integer Shifts and Rotates
+;; ::
+;; ::::::::::::::::::::
+
+(define_expand "ashlti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "")
+ (ashift:TI (match_operand:TI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))]
+ ""
+{
+ if (!dshift_count_operand (operands[2], DImode))
+ FAIL;
+})
+
+(define_insn_and_split "*ashlti3_internal"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (ashift:TI (match_operand:TI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "dshift_count_operand" "n")))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ HOST_WIDE_INT shift = INTVAL (operands[2]);
+ rtx rl = gen_lowpart (DImode, operands[0]);
+ rtx rh = gen_highpart (DImode, operands[0]);
+ rtx lo = gen_lowpart (DImode, operands[1]);
+ rtx shiftlo = GEN_INT (shift & 63);
+
+ if (shift & 64)
+ {
+ emit_move_insn (rl, const0_rtx);
+ if (shift & 63)
+ emit_insn (gen_ashldi3 (rh, lo, shiftlo));
+ else
+ emit_move_insn (rh, lo);
+ }
+ else
+ {
+ rtx hi = gen_highpart (DImode, operands[1]);
+
+ emit_insn (gen_shrp (rh, hi, lo, GEN_INT (-shift & 63)));
+ emit_insn (gen_ashldi3 (rl, lo, shiftlo));
+ }
+ DONE;
+})
+
+(define_expand "ashrti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "")
+ (ashiftrt:TI (match_operand:TI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))]
+ ""
+{
+ if (!dshift_count_operand (operands[2], DImode))
+ FAIL;
+})
+
+(define_insn_and_split "*ashrti3_internal"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (ashiftrt:TI (match_operand:TI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "dshift_count_operand" "n")))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ HOST_WIDE_INT shift = INTVAL (operands[2]);
+ rtx rl = gen_lowpart (DImode, operands[0]);
+ rtx rh = gen_highpart (DImode, operands[0]);
+ rtx hi = gen_highpart (DImode, operands[1]);
+ rtx shiftlo = GEN_INT (shift & 63);
+
+ if (shift & 64)
+ {
+ if (shift & 63)
+ emit_insn (gen_ashrdi3 (rl, hi, shiftlo));
+ else
+ emit_move_insn (rl, hi);
+ emit_insn (gen_ashrdi3 (rh, hi, GEN_INT (63)));
+ }
+ else
+ {
+ rtx lo = gen_lowpart (DImode, operands[1]);
+
+ emit_insn (gen_shrp (rl, hi, lo, shiftlo));
+ emit_insn (gen_ashrdi3 (rh, hi, shiftlo));
+ }
+ DONE;
+})
+
+(define_expand "lshrti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "")
+ (lshiftrt:TI (match_operand:TI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))]
+ ""
+{
+ if (!dshift_count_operand (operands[2], DImode))
+ FAIL;
+})
+
+(define_insn_and_split "*lshrti3_internal"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (lshiftrt:TI (match_operand:TI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "dshift_count_operand" "n")))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ HOST_WIDE_INT shift = INTVAL (operands[2]);
+ rtx rl = gen_lowpart (DImode, operands[0]);
+ rtx rh = gen_highpart (DImode, operands[0]);
+ rtx hi = gen_highpart (DImode, operands[1]);
+ rtx shiftlo = GEN_INT (shift & 63);
+
+ if (shift & 64)
+ {
+ if (shift & 63)
+ emit_insn (gen_lshrdi3 (rl, hi, shiftlo));
+ else
+ emit_move_insn (rl, hi);
+ emit_move_insn (rh, const0_rtx);
+ }
+ else
+ {
+ rtx lo = gen_lowpart (DImode, operands[1]);
+
+ emit_insn (gen_shrp (rl, hi, lo, shiftlo));
+ emit_insn (gen_lshrdi3 (rh, hi, shiftlo));
+ }
+ DONE;
+})
+
+(define_expand "rotlti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "")
+ (rotate:TI (match_operand:TI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))]
+ ""
+{
+ if (! dshift_count_operand (operands[2], DImode))
+ FAIL;
+})
+
+(define_insn_and_split "*rotlti3_internal"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (rotate:TI (match_operand:TI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "dshift_count_operand" "n")))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ HOST_WIDE_INT count = INTVAL (operands[2]);
+ rtx rl = gen_lowpart (DImode, operands[0]);
+ rtx rh = gen_highpart (DImode, operands[0]);
+ rtx lo = gen_lowpart (DImode, operands[1]);
+ rtx hi = gen_highpart (DImode, operands[1]);
+ rtx countlo = GEN_INT (-count & 63);
+
+ if (count & 64)
+ {
+ if (count & 63)
+ {
+ emit_insn (gen_shrp (rl, hi, lo, countlo));
+ emit_insn (gen_shrp (rh, lo, hi, countlo));
+ }
+ else
+ {
+ emit_move_insn (rl, hi);
+ emit_move_insn (rh, lo);
+ }
+ }
+ else
+ {
+ emit_insn (gen_shrp (rl, lo, hi, countlo));
+ emit_insn (gen_shrp (rh, hi, lo, countlo));
+ }
+ DONE;
+}
+ [(set_attr "itanium_class" "unknown")])
+
+(define_insn "shrp"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "gr_register_operand" "r")
+ (match_operand:DI 3 "shift_count_operand" "M")]
+ UNSPEC_SHRP))]
+ ""
+ "shrp %0 = %1, %2, %3"
+ [(set_attr "itanium_class" "ishf")])
+
+;; ::::::::::::::::::::
+;; ::
;; :: 32 bit Integer Logical operations
;; ::
;; ::::::::::::::::::::
@@ -4516,7 +5210,7 @@
[(set (match_operand:BI 0 "register_operand" "=c")
(eq:BI (zero_extract:DI (match_operand:DI 1 "gr_register_operand" "r")
(const_int 1)
- (match_operand:DI 2 "immediate_operand" "n"))
+ (match_operand:DI 2 "shift_count_operand" "M"))
(const_int 0)))]
""
"tbit.z %0, %I0 = %1, %2"
@@ -4526,7 +5220,7 @@
[(set (match_operand:BI 0 "register_operand" "=c")
(ne:BI (zero_extract:DI (match_operand:DI 1 "gr_register_operand" "r")
(const_int 1)
- (match_operand:DI 2 "immediate_operand" "n"))
+ (match_operand:DI 2 "shift_count_operand" "M"))
(const_int 0)))]
""
"tbit.nz %0, %I0 = %1, %2"
@@ -4816,7 +5510,7 @@
"rim,rim,rim, rim, *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 (); }
+ { gcc_unreachable (); }
[(set_attr "predicable" "no")])
(define_split
@@ -4919,7 +5613,7 @@
"rim*f,rO,rO,0,0,0,rim*f,rO,rO")))]
"ia64_move_ok (operands[0], operands[2])
&& ia64_move_ok (operands[0], operands[3])"
- { abort (); }
+ { gcc_unreachable (); }
[(set_attr "predicable" "no")])
(define_insn "*abssi2_internal"
@@ -5318,12 +6012,10 @@
start_sequence ();
set = single_set (last);
- if (! rtx_equal_p (SET_DEST (set), op0)
- || GET_CODE (SET_SRC (set)) != MEM)
- abort ();
+ gcc_assert (rtx_equal_p (SET_DEST (set), op0)
+ && GET_CODE (SET_SRC (set)) == MEM);
addr = XEXP (SET_SRC (set), 0);
- if (rtx_equal_p (addr, op0))
- abort ();
+ gcc_assert (!rtx_equal_p (addr, op0));
}
/* Jump table elements are stored pc-relative. That is, a displacement
@@ -5421,7 +6113,8 @@
""
"alloc %0 = ar.pfs, %1, %2, %3, %4"
[(set_attr "itanium_class" "syst_m0")
- (set_attr "predicable" "no")])
+ (set_attr "predicable" "no")
+ (set_attr "first_insn" "yes")])
;; Modifies ar.unat
(define_expand "gr_spill"
@@ -5434,7 +6127,7 @@
"operands[3] = gen_rtx_REG (DImode, AR_UNAT_REGNUM);")
(define_insn "gr_spill_internal"
- [(set (match_operand:DI 0 "memory_operand" "=m")
+ [(set (match_operand:DI 0 "destination_operand" "=m")
(unspec:DI [(match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "const_int_operand" "")]
UNSPEC_GR_SPILL))
@@ -5468,7 +6161,7 @@
[(set_attr "itanium_class" "ld")])
(define_insn "fr_spill"
- [(set (match_operand:XF 0 "memory_operand" "=m")
+ [(set (match_operand:XF 0 "destination_operand" "=m")
(unspec:XF [(match_operand:XF 1 "register_operand" "f")]
UNSPEC_FR_SPILL))]
""
@@ -5622,7 +6315,7 @@
[(trap_if (const_int 1) (match_operand 0 "const_int_operand" ""))]
""
"break %0"
- [(set_attr "itanium_class" "chk_s")])
+ [(set_attr "itanium_class" "chk_s_i")])
(define_expand "conditional_trap"
[(trap_if (match_operand 0 "" "") (match_operand 1 "" ""))]
@@ -5638,7 +6331,7 @@
(match_operand 2 "const_int_operand" ""))]
""
"(%J0) break %2"
- [(set_attr "itanium_class" "chk_s")
+ [(set_attr "itanium_class" "chk_s_i")
(set_attr "predicable" "no")])
(define_insn "break_f"
@@ -5670,10 +6363,8 @@
int i = (INTVAL (operands[1]));
int j = (INTVAL (operands[2]));
- if (i != 0 && i != 1)
- abort ();
- if (j < 0 || j > 3)
- abort ();
+ gcc_assert (i == 0 || i == 1);
+ gcc_assert (j >= 0 && j <= 3);
return alt[i][j];
}
[(set_attr "itanium_class" "lfetch")])
@@ -5760,88 +6451,6 @@
})
-;;; Intrinsics support.
-
-(define_expand "mf"
- [(set (mem:BLK (match_dup 0))
- (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 "" "")] UNSPEC_MF))]
- ""
- "mf"
- [(set_attr "itanium_class" "syst_m")])
-
-(define_insn "fetchadd_acq_si"
- [(set (match_operand:SI 0 "gr_register_operand" "=r")
- (match_operand:SI 1 "not_postinc_memory_operand" "+S"))
- (set (match_dup 1)
- (unspec:SI [(match_dup 1)
- (match_operand:SI 2 "fetchadd_operand" "n")]
- UNSPEC_FETCHADD_ACQ))]
- ""
- "fetchadd4.acq %0 = %1, %2"
- [(set_attr "itanium_class" "sem")])
-
-(define_insn "fetchadd_acq_di"
- [(set (match_operand:DI 0 "gr_register_operand" "=r")
- (match_operand:DI 1 "not_postinc_memory_operand" "+S"))
- (set (match_dup 1)
- (unspec:DI [(match_dup 1)
- (match_operand:DI 2 "fetchadd_operand" "n")]
- UNSPEC_FETCHADD_ACQ))]
- ""
- "fetchadd8.acq %0 = %1, %2"
- [(set_attr "itanium_class" "sem")])
-
-(define_insn "cmpxchg_acq_si"
- [(set (match_operand:SI 0 "gr_register_operand" "=r")
- (match_operand:SI 1 "not_postinc_memory_operand" "+S"))
- (set (match_dup 1)
- (unspec:SI [(match_dup 1)
- (match_operand:SI 2 "gr_register_operand" "r")
- (match_operand:DI 3 "ar_ccv_reg_operand" "")]
- UNSPEC_CMPXCHG_ACQ))]
- ""
- "cmpxchg4.acq %0 = %1, %2, %3"
- [(set_attr "itanium_class" "sem")])
-
-(define_insn "cmpxchg_acq_di"
- [(set (match_operand:DI 0 "gr_register_operand" "=r")
- (match_operand:DI 1 "not_postinc_memory_operand" "+S"))
- (set (match_dup 1)
- (unspec:DI [(match_dup 1)
- (match_operand:DI 2 "gr_register_operand" "r")
- (match_operand:DI 3 "ar_ccv_reg_operand" "")]
- UNSPEC_CMPXCHG_ACQ))]
- ""
- "cmpxchg8.acq %0 = %1, %2, %3"
- [(set_attr "itanium_class" "sem")])
-
-(define_insn "xchgsi"
- [(set (match_operand:SI 0 "gr_register_operand" "=r")
- (match_operand:SI 1 "not_postinc_memory_operand" "+S"))
- (set (match_dup 1)
- (match_operand:SI 2 "gr_register_operand" "r"))]
- ""
- "xchg4 %0 = %1, %2"
- [(set_attr "itanium_class" "sem")])
-
-(define_insn "xchgdi"
- [(set (match_operand:DI 0 "gr_register_operand" "=r")
- (match_operand:DI 1 "not_postinc_memory_operand" "+S"))
- (set (match_dup 1)
- (match_operand:DI 2 "gr_register_operand" "r"))]
- ""
- "xchg8 %0 = %1, %2"
- [(set_attr "itanium_class" "sem")])
-
;; Predication.
(define_cond_exec
@@ -5909,3 +6518,18 @@
"addp4_optimize_ok (operands[1], operands[2])"
"addp4 %0 = %1, %2"
[(set_attr "itanium_class" "ialu")])
+
+;;
+;; Get instruction pointer
+
+(define_insn "ip_value"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (pc))]
+ ""
+ "mov %0 = ip"
+ [(set_attr "itanium_class" "ialu")])
+
+;; Vector operations
+(include "vect.md")
+;; Atomic operations
+(include "sync.md")
diff --git a/contrib/gcc/config/ia64/ia64.opt b/contrib/gcc/config/ia64/ia64.opt
new file mode 100644
index 0000000..2ff3d59
--- /dev/null
+++ b/contrib/gcc/config/ia64/ia64.opt
@@ -0,0 +1,147 @@
+mbig-endian
+Target Report RejectNegative Mask(BIG_ENDIAN)
+Generate big endian code
+
+mlittle-endian
+Target Report RejectNegative InverseMask(BIG_ENDIAN)
+Generate little endian code
+
+mgnu-as
+Target Report Mask(GNU_AS)
+Generate code for GNU as
+
+mgnu-ld
+Target Report Mask(GNU_LD)
+Generate code for GNU ld
+
+mvolatile-asm-stop
+Target Report Mask(VOL_ASM_STOP)
+Emit stop bits before and after volatile extended asms
+
+mregister-names
+Target Mask(REG_NAMES)
+Use in/loc/out register names
+
+mno-sdata
+Target Report RejectNegative Mask(NO_SDATA)
+
+msdata
+Target Report RejectNegative InverseMask(NO_SDATA)
+Enable use of sdata/scommon/sbss
+
+mno-pic
+Target Report RejectNegative Mask(NO_PIC)
+Generate code without GP reg
+
+mconstant-gp
+Target Report RejectNegative Mask(CONST_GP)
+gp is constant (but save/restore gp on indirect calls)
+
+mauto-pic
+Target Report RejectNegative Mask(AUTO_PIC)
+Generate self-relocatable code
+
+minline-float-divide-min-latency
+Target Report RejectNegative Var(TARGET_INLINE_FLOAT_DIV, 1)
+Generate inline floating point division, optimize for latency
+
+minline-float-divide-max-throughput
+Target Report RejectNegative Var(TARGET_INLINE_FLOAT_DIV, 2) Init(2)
+Generate inline floating point division, optimize for throughput
+
+mno-inline-float-divide
+Target Report RejectNegative Var(TARGET_INLINE_FLOAT_DIV, 0)
+
+minline-int-divide-min-latency
+Target Report RejectNegative Var(TARGET_INLINE_INT_DIV, 1)
+Generate inline integer division, optimize for latency
+
+minline-int-divide-max-throughput
+Target Report RejectNegative Var(TARGET_INLINE_INT_DIV, 2)
+Generate inline integer division, optimize for throughput
+
+mno-inline-int-divide
+Target Report RejectNegative Var(TARGET_INLINE_INT_DIV, 0)
+Do not inline integer division
+
+minline-sqrt-min-latency
+Target Report RejectNegative Var(TARGET_INLINE_SQRT, 1)
+Generate inline square root, optimize for latency
+
+minline-sqrt-max-throughput
+Target Report RejectNegative Var(TARGET_INLINE_SQRT, 2)
+Generate inline square root, optimize for throughput
+
+mno-inline-sqrt
+Target Report RejectNegative Var(TARGET_INLINE_SQRT, 0)
+Do not inline square root
+
+mdwarf2-asm
+Target Report Mask(DWARF2_ASM)
+Enable Dwarf 2 line debug info via GNU as
+
+mearly-stop-bits
+Target Report Mask(EARLY_STOP_BITS)
+Enable earlier placing stop bits for better scheduling
+
+mfixed-range=
+Target RejectNegative Joined
+Specify range of registers to make fixed
+
+mtls-size=
+Target RejectNegative Joined UInteger Var(ia64_tls_size) Init(22)
+Specify bit size of immediate TLS offsets
+
+mtune=
+Target RejectNegative Joined
+Schedule code for given CPU
+
+msched-br-data-spec
+Target Report Var(mflag_sched_br_data_spec) Init(0)
+Use data speculation before reload
+
+msched-ar-data-spec
+Target Report Var(mflag_sched_ar_data_spec) Init(1)
+Use data speculation after reload
+
+msched-control-spec
+Target Report Var(mflag_sched_control_spec) Init(0)
+Use control speculation
+
+msched-br-in-data-spec
+Target Report Var(mflag_sched_br_in_data_spec) Init(1)
+Use in block data speculation before reload
+
+msched-ar-in-data-spec
+Target Report Var(mflag_sched_ar_in_data_spec) Init(1)
+Use in block data speculation after reload
+
+msched-in-control-spec
+Target Report Var(mflag_sched_in_control_spec) Init(1)
+Use in block control speculation
+
+msched-ldc
+Target Report Var(mflag_sched_ldc) Init(1)
+Use simple data speculation check
+
+msched-control-ldc
+Target Report Var(mflag_control_ldc) Init(0)
+Use simple data speculation check for control speculation
+
+msched-spec-verbose
+Common Report Var(mflag_sched_spec_verbose) Init(0)
+Print information about speculative motions.
+
+msched-prefer-non-data-spec-insns
+Common Report Var(mflag_sched_prefer_non_data_spec_insns) Init(0)
+If set, data speculative instructions will be chosen for schedule only if there are no other choices at the moment
+
+msched-prefer-non-control-spec-insns
+Common Report Var(mflag_sched_prefer_non_control_spec_insns) Init(0)
+If set, control speculative instructions will be chosen for schedule only if there are no other choices at the moment
+
+msched-count-spec-in-critical-path
+Common Report Var(mflag_sched_count_spec_in_critical_path) Init(0)
+Count speculative dependencies while calculating priority of instructions
+
+; This comment is to ensure we retain the blank line above.
diff --git a/contrib/gcc/config/ia64/ia64intrin.h b/contrib/gcc/config/ia64/ia64intrin.h
index 262dc20..fba7296 100644
--- a/contrib/gcc/config/ia64/ia64intrin.h
+++ b/contrib/gcc/config/ia64/ia64intrin.h
@@ -1,130 +1,2 @@
-#ifndef _IA64INTRIN_H_INCLUDED
-#define _IA64INTRIN_H_INCLUDED
-
-/* Actually, everything is a compiler builtin, but just so
- there's no confusion... */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern void __sync_synchronize (void);
-
-extern int __sync_val_compare_and_swap_si (int *, int, int);
-extern long __sync_val_compare_and_swap_di (long *, long, long);
-#define __sync_val_compare_and_swap(PTR, OLD, NEW) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) \
- __sync_val_compare_and_swap_si((int *)(PTR),(int)(OLD),(int)(NEW)) \
- : (__typeof__(*(PTR))) \
- __sync_val_compare_and_swap_di((long *)(PTR),(long)(OLD),(long)(NEW)))
-
-extern int __sync_bool_compare_and_swap_si (int *, int, int);
-extern int __sync_bool_compare_and_swap_di (long *, long, long);
-#define __sync_bool_compare_and_swap(PTR, OLD, NEW) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? __sync_bool_compare_and_swap_si((int *)(PTR),(int)(OLD),(int)(NEW)) \
- : __sync_bool_compare_and_swap_di((long *)(PTR),(long)(OLD),(long)(NEW)))
-
-extern void __sync_lock_release_si (int *);
-extern void __sync_lock_release_di (long *);
-#define __sync_lock_release(PTR) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? __sync_lock_release_si((int *)(PTR)) \
- : __sync_lock_release_di((long *)(PTR)))
-
-extern int __sync_lock_test_and_set_si (int *, int);
-extern long __sync_lock_test_and_set_di (long *, long);
-#define __sync_lock_test_and_set(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_lock_test_and_set_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_lock_test_and_set_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_fetch_and_add_si (int *, int);
-extern long __sync_fetch_and_add_di (long *, long);
-#define __sync_fetch_and_add(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_fetch_and_add_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_fetch_and_add_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_fetch_and_sub_si (int *, int);
-extern long __sync_fetch_and_sub_di (long *, long);
-#define __sync_fetch_and_sub(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_fetch_and_sub_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_fetch_and_sub_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_fetch_and_and_si (int *, int);
-extern long __sync_fetch_and_and_di (long *, long);
-#define __sync_fetch_and_and(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_fetch_and_and_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_fetch_and_and_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_fetch_and_or_si (int *, int);
-extern long __sync_fetch_and_or_di (long *, long);
-#define __sync_fetch_and_or(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_fetch_and_or_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_fetch_and_or_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_fetch_and_xor_si (int *, int);
-extern long __sync_fetch_and_xor_di (long *, long);
-#define __sync_fetch_and_xor(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_fetch_and_xor_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_fetch_and_xor_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_fetch_and_nand_si (int *, int);
-extern long __sync_fetch_and_nand_di (long *, long);
-#define __sync_fetch_and_nand(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_fetch_and_nand_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_fetch_and_nand_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_add_and_fetch_si (int *, int);
-extern long __sync_add_and_fetch_di (long *, long);
-#define __sync_add_and_fetch(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_add_and_fetch_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_add_and_fetch_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_sub_and_fetch_si (int *, int);
-extern long __sync_sub_and_fetch_di (long *, long);
-#define __sync_sub_and_fetch(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_sub_and_fetch_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_sub_and_fetch_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_and_and_fetch_si (int *, int);
-extern long __sync_and_and_fetch_di (long *, long);
-#define __sync_and_and_fetch(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_and_and_fetch_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_and_and_fetch_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_or_and_fetch_si (int *, int);
-extern long __sync_or_and_fetch_di (long *, long);
-#define __sync_or_and_fetch(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_or_and_fetch_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_or_and_fetch_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_xor_and_fetch_si (int *, int);
-extern long __sync_xor_and_fetch_di (long *, long);
-#define __sync_xor_and_fetch(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_xor_and_fetch_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_xor_and_fetch_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_nand_and_fetch_si (int *, int);
-extern long __sync_nand_and_fetch_di (long *, long);
-#define __sync_nand_and_fetch(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_nand_and_fetch_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_nand_and_fetch_di((long *)(PTR),(long)(VAL)))
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/* Overloaded builtins have been ported to C++: nothing is needed
+ in the header anymore. This file intentionally left void. */
diff --git a/contrib/gcc/config/ia64/ilp32.opt b/contrib/gcc/config/ia64/ilp32.opt
new file mode 100644
index 0000000..bcb6473
--- /dev/null
+++ b/contrib/gcc/config/ia64/ilp32.opt
@@ -0,0 +1,7 @@
+milp32
+Target Report RejectNegative Mask(ILP32)
+Generate ILP32 code
+
+mlp64
+Target Report RejectNegative InverseMask(ILP32)
+Generate LP64 code
diff --git a/contrib/gcc/config/ia64/itanium1.md b/contrib/gcc/config/ia64/itanium1.md
index 2b84411..f9b7f91 100644
--- a/contrib/gcc/config/ia64/itanium1.md
+++ b/contrib/gcc/config/ia64/itanium1.md
@@ -1,6 +1,6 @@
;; Itanium1 (original Itanium) DFA descriptions for insn scheduling
;; and bundling.
-;; Copyright (C) 2002 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
;; Contributed by Vladimir Makarov <vmakarov@redhat.com>.
;;
;; This file is part of GCC.
@@ -17,8 +17,8 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA. */
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA. */
;;
@@ -33,10 +33,10 @@
DEFINE_AUTOMATON).
All define_reservations and define_cpu_units should have unique
- names which can not be "nothing".
+ names which cannot be "nothing".
o (exclusion_set string string) means that each CPU function unit
- in the first string can not be reserved simultaneously with each
+ in the first string cannot be reserved simultaneously with each
unit whose name is in the second string and vise versa. CPU
units in the string are separated by commas. For example, it is
useful for description CPU with fully pipelined floating point
@@ -44,7 +44,7 @@
floating point insns or only double floating point insns.
o (presence_set string string) means that each CPU function unit in
- the first string can not be reserved unless at least one of
+ the first string cannot be reserved unless at least one of
pattern of units whose names are in the second string is
reserved. This is an asymmetric relation. CPU units or unit
patterns in the strings are separated by commas. Pattern is one
@@ -92,13 +92,13 @@
string are separated by commas. Pattern is one unit name or unit
names separated by white-spaces.
- For example, it is useful for description that slot0 can not be
+ For example, it is useful for description that slot0 cannot be
reserved after slot1 or slot2 reservation for a VLIW processor.
We could describe it by the following construction
(absence_set "slot2" "slot0, slot1")
- Or slot2 can not be reserved if slot0 and unit b0 are reserved or
+ Or slot2 cannot be reserved if slot0 and unit b0 are reserved or
slot1 and unit b1 are reserved . In this case we could write
(absence_set "slot2" "slot0 b0, slot1 b1")
@@ -140,7 +140,7 @@
case, you describe common part and use one its name (the 1st
parameter) in regular expression in define_insn_reservation. All
define_reservations, define results and define_cpu_units should
- have unique names which can not be "nothing".
+ have unique names which cannot be "nothing".
o (define_insn_reservation name default_latency condition regexpr)
describes reservation of cpu functional units (the 3nd operand)
@@ -525,10 +525,29 @@
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "fcvtfx"))
(eq (symbol_ref "bundling_p") (const_int 0))) "1_F")
+
(define_insn_reservation "1_fld" 9
- (and (and (eq_attr "cpu" "itanium")
- (eq_attr "itanium_class" "fld"))
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "check_load" "no"))
+ (eq (symbol_ref "bundling_p") (const_int 0))) "1_M")
+(define_insn_reservation "1_fldc" 0
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "check_load" "yes"))
+ (eq (symbol_ref "bundling_p") (const_int 0))) "1_M")
+
+(define_insn_reservation "1_fldp" 9
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "fldp"))
+ (eq_attr "check_load" "no"))
(eq (symbol_ref "bundling_p") (const_int 0))) "1_M")
+(define_insn_reservation "1_fldpc" 0
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "fldp"))
+ (eq_attr "check_load" "yes"))
+ (eq (symbol_ref "bundling_p") (const_int 0))) "1_M")
+
(define_insn_reservation "1_fmac" 5
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "fmac"))
@@ -589,14 +608,25 @@
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "ilog"))
(eq (symbol_ref "bundling_p") (const_int 0))) "1_A")
+(define_insn_reservation "1_mmalua" 2
+ (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "mmalua"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "1_A")
(define_insn_reservation "1_ishf" 1
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "ishf"))
(eq (symbol_ref "bundling_p") (const_int 0)))
"1_I+1_not_ui1")
(define_insn_reservation "1_ld" 2
- (and (and (eq_attr "cpu" "itanium")
- (eq_attr "itanium_class" "ld"))
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "ld"))
+ (eq_attr "check_load" "no"))
+ (eq (symbol_ref "bundling_p") (const_int 0))) "1_M")
+(define_insn_reservation "1_ldc" 0
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "ld"))
+ (eq_attr "check_load" "yes"))
(eq (symbol_ref "bundling_p") (const_int 0))) "1_M")
(define_insn_reservation "1_long_i" 1
(and (and (eq_attr "cpu" "itanium")
@@ -687,10 +717,19 @@
(eq_attr "itanium_class" "xtd"))
(eq (symbol_ref "bundling_p") (const_int 0))) "1_I")
-(define_insn_reservation "1_chk_s" 0
+(define_insn_reservation "1_chk_s_i" 0
(and (and (eq_attr "cpu" "itanium")
- (eq_attr "itanium_class" "chk_s"))
+ (eq_attr "itanium_class" "chk_s_i"))
(eq (symbol_ref "bundling_p") (const_int 0))) "1_A")
+(define_insn_reservation "1_chk_s_f" 0
+ (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "chk_s_f"))
+ (eq (symbol_ref "bundling_p") (const_int 0))) "1_M")
+(define_insn_reservation "1_chk_a" 0
+ (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "chk_a"))
+ (eq (symbol_ref "bundling_p") (const_int 0))) "1_M")
+
(define_insn_reservation "1_lfetch" 0
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "lfetch"))
@@ -920,7 +959,7 @@
;; There is only one insn `mov ar.pfs =' for toar_i.
(define_bypass 0 "1_tobr,1_topr,1_toar_i" "1_br,1_scall")
-(define_bypass 3 "1_ialu,1_ialu_addr" "1_mmmul,1_mmshf")
+(define_bypass 3 "1_ialu,1_ialu_addr" "1_mmmul,1_mmshf,1_mmalua")
;; ??? howto describe ialu for I slot only. We use ialu_addr for that
;;(define_bypass 2 "1_ialu" "1_ld" "ia64_ld_address_bypass_p")
;; ??? howto describe ialu st/address for I slot only. We use ialu_addr
@@ -934,15 +973,15 @@
(define_bypass 2 "1_ilog,1_xtd" "1_ld" "ia64_ld_address_bypass_p")
(define_bypass 2 "1_ilog,1_xtd" "1_st" "ia64_st_address_bypass_p")
-(define_bypass 3 "1_ld" "1_mmmul,1_mmshf")
+(define_bypass 3 "1_ld,1_ldc" "1_mmmul,1_mmshf")
(define_bypass 3 "1_ld" "1_ld" "ia64_ld_address_bypass_p")
(define_bypass 3 "1_ld" "1_st" "ia64_st_address_bypass_p")
;; Intel docs say only LD, ST, IALU, ILOG, ISHF consumers have latency 4,
;; but HP engineers say any non-MM operation.
-(define_bypass 4 "1_mmmul,1_mmshf"
- "1_br,1_fcmp,1_fcvtfx,1_fld,1_fmac,1_fmisc,1_frar_i,1_frar_m,\
- 1_frbr,1_frfr,1_frpr,1_ialu,1_icmp,1_ilog,1_ishf,1_ld,1_chk_s,\
+(define_bypass 4 "1_mmmul,1_mmshf,1_mmalua"
+ "1_br,1_fcmp,1_fcvtfx,1_fld,1_fldc,1_fmac,1_fmisc,1_frar_i,1_frar_m,\
+ 1_frbr,1_frfr,1_frpr,1_ialu,1_icmp,1_ilog,1_ishf,1_ld,1_ldc,1_chk_s_i,1_chk_s_f,1_chk_a,\
1_long_i,1_rse_m,1_sem,1_stf,1_st,1_syst_m0,1_syst_m,\
1_tbit,1_toar_i,1_toar_m,1_tobr,1_tofr,1_topr,1_xmpy,1_xtd")
@@ -956,15 +995,15 @@
(define_bypass 8 "1_fmisc,1_fcvtfx,1_fmac,1_xmpy" "1_stf")
;; We don't use here fcmp because scall may be predicated.
-(define_bypass 0 "1_fcvtfx,1_fld,1_fmac,1_fmisc,1_frar_i,1_frar_m,\
+(define_bypass 0 "1_fcvtfx,1_fld,1_fldc,1_fmac,1_fmisc,1_frar_i,1_frar_m,\
1_frbr,1_frfr,1_frpr,1_ialu,1_ialu_addr,1_ilog,1_ishf,\
- 1_ld,1_long_i,1_mmmul,1_mmshf,1_mmshfi,1_toar_m,1_tofr,\
- 1_xmpy,1_xtd" "1_scall")
+ 1_ld,1_ldc,1_long_i,1_mmalua,1_mmmul,1_mmshf,1_mmshfi,\
+ 1_toar_m,1_tofr,1_xmpy,1_xtd" "1_scall")
(define_bypass 0 "1_unknown,1_ignore,1_stop_bit,1_br,1_fcmp,1_fcvtfx,\
- 1_fld,1_fmac,1_fmisc,1_frar_i,1_frar_m,1_frbr,1_frfr,\
- 1_frpr,1_ialu,1_ialu_addr,1_icmp,1_ilog,1_ishf,1_ld,\
- 1_chk_s,1_long_i,1_mmmul,1_mmshf,1_mmshfi,1_nop,\
+ 1_fld,1_fldc,1_fmac,1_fmisc,1_frar_i,1_frar_m,1_frbr,1_frfr,\
+ 1_frpr,1_ialu,1_ialu_addr,1_icmp,1_ilog,1_ishf,1_ld,1_ldc,\
+ 1_chk_s_i,1_chk_s_f,1_chk_a,1_long_i,1_mmalua,1_mmmul,1_mmshf,1_mmshfi,1_nop,\
1_nop_b,1_nop_f,1_nop_i,1_nop_m,1_nop_x,1_rse_m,1_scall,\
1_sem,1_stf,1_st,1_syst_m0,1_syst_m,1_tbit,1_toar_i,\
1_toar_m,1_tobr,1_tofr,1_topr,1_xmpy,1_xtd,1_lfetch"
@@ -1398,10 +1437,29 @@
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "fcvtfx"))
(ne (symbol_ref "bundling_p") (const_int 0))) "1b_F")
+
(define_insn_reservation "1b_fld" 9
- (and (and (eq_attr "cpu" "itanium")
- (eq_attr "itanium_class" "fld"))
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "check_load" "no"))
(ne (symbol_ref "bundling_p") (const_int 0))) "1b_M")
+(define_insn_reservation "1b_fldc" 0
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "check_load" "yes"))
+ (ne (symbol_ref "bundling_p") (const_int 0))) "1b_M")
+
+(define_insn_reservation "1b_fldp" 9
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "fldp"))
+ (eq_attr "check_load" "no"))
+ (ne (symbol_ref "bundling_p") (const_int 0))) "1b_M")
+(define_insn_reservation "1b_fldpc" 0
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "fldp"))
+ (eq_attr "check_load" "yes"))
+ (ne (symbol_ref "bundling_p") (const_int 0))) "1b_M")
+
(define_insn_reservation "1b_fmac" 5
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "fmac"))
@@ -1458,15 +1516,27 @@
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "ilog"))
(ne (symbol_ref "bundling_p") (const_int 0))) "1b_A")
+(define_insn_reservation "1b_mmalua" 2
+ (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "mmalua"))
+ (ne (symbol_ref "bundling_p") (const_int 0))) "1b_A")
(define_insn_reservation "1b_ishf" 1
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "ishf"))
(ne (symbol_ref "bundling_p") (const_int 0)))
"1b_I+1b_not_ui1")
+
(define_insn_reservation "1b_ld" 2
- (and (and (eq_attr "cpu" "itanium")
- (eq_attr "itanium_class" "ld"))
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "ld"))
+ (eq_attr "check_load" "no"))
(ne (symbol_ref "bundling_p") (const_int 0))) "1b_M")
+(define_insn_reservation "1b_ldc" 0
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "ld"))
+ (eq_attr "check_load" "yes"))
+ (ne (symbol_ref "bundling_p") (const_int 0))) "1b_M")
+
(define_insn_reservation "1b_long_i" 1
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "long_i"))
@@ -1549,10 +1619,20 @@
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "xtd"))
(ne (symbol_ref "bundling_p") (const_int 0))) "1b_I")
-(define_insn_reservation "1b_chk_s" 0
+
+(define_insn_reservation "1b_chk_s_i" 0
(and (and (eq_attr "cpu" "itanium")
- (eq_attr "itanium_class" "chk_s"))
+ (eq_attr "itanium_class" "chk_s_i"))
(ne (symbol_ref "bundling_p") (const_int 0))) "1b_A")
+(define_insn_reservation "1b_chk_s_f" 0
+ (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "chk_s_f"))
+ (ne (symbol_ref "bundling_p") (const_int 0))) "1b_M")
+(define_insn_reservation "1b_chk_a" 0
+ (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "chk_a"))
+ (ne (symbol_ref "bundling_p") (const_int 0))) "1b_M")
+
(define_insn_reservation "1b_lfetch" 0
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "lfetch"))
diff --git a/contrib/gcc/config/ia64/itanium2.md b/contrib/gcc/config/ia64/itanium2.md
index 0cdb070..a10971d 100644
--- a/contrib/gcc/config/ia64/itanium2.md
+++ b/contrib/gcc/config/ia64/itanium2.md
@@ -1,5 +1,5 @@
;; Itanium2 DFA descriptions for insn scheduling and bundling.
-;; Copyright (C) 2002 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
;; Contributed by Vladimir Makarov <vmakarov@redhat.com>.
;;
;; This file is part of GCC.
@@ -16,8 +16,8 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA. */
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA. */
;;
/* This is description of pipeline hazards based on DFA. The
@@ -31,10 +31,10 @@
DEFINE_AUTOMATON).
All define_reservations and define_cpu_units should have unique
- names which can not be "nothing".
+ names which cannot be "nothing".
o (exclusion_set string string) means that each CPU function unit
- in the first string can not be reserved simultaneously with each
+ in the first string cannot be reserved simultaneously with each
unit whose name is in the second string and vise versa. CPU
units in the string are separated by commas. For example, it is
useful for description CPU with fully pipelined floating point
@@ -42,7 +42,7 @@
floating point insns or only double floating point insns.
o (presence_set string string) means that each CPU function unit in
- the first string can not be reserved unless at least one of
+ the first string cannot be reserved unless at least one of
pattern of units whose names are in the second string is
reserved. This is an asymmetric relation. CPU units or unit
patterns in the strings are separated by commas. Pattern is one
@@ -90,13 +90,13 @@
string are separated by commas. Pattern is one unit name or unit
names separated by white-spaces.
- For example, it is useful for description that slot0 can not be
+ For example, it is useful for description that slot0 cannot be
reserved after slot1 or slot2 reservation for a VLIW processor.
We could describe it by the following construction
(absence_set "slot2" "slot0, slot1")
- Or slot2 can not be reserved if slot0 and unit b0 are reserved or
+ Or slot2 cannot be reserved if slot0 and unit b0 are reserved or
slot1 and unit b1 are reserved . In this case we could write
(absence_set "slot2" "slot0 b0, slot1 b1")
@@ -138,7 +138,7 @@
case, you describe common part and use one its name (the 1st
parameter) in regular expression in define_insn_reservation. All
define_reservations, define results and define_cpu_units should
- have unique names which can not be "nothing".
+ have unique names which cannot be "nothing".
o (define_insn_reservation name default_latency condition regexpr)
describes reservation of cpu functional units (the 3nd operand)
@@ -398,7 +398,7 @@
"2_stop")
;; The issue logic can reorder M slot insns between different subtypes
-;; but can not reorder insn within the same subtypes. The following
+;; but cannot reorder insn within the same subtypes. The following
;; constraint is enough to describe this.
(final_presence_set "2_um1" "2_um0")
(final_presence_set "2_um3" "2_um2")
@@ -484,7 +484,7 @@
(define_reservation "2_M_only_um01" "2_M0_only_um01|2_M1_only_um01")
;; I instruction is dispersed to the lowest numbered I unit
-;; not already in use. Remeber about possible splitting.
+;; not already in use. Remember about possible splitting.
(define_reservation "2_I0"
"2_0mi.i+2_ui0|2_0mii.+(2_ui0|2_ui1)|2_0mmi.+2_ui0\
|2_0mfi.+2_ui0|2_0mi.b+2_ui0|(2_1mi.i|2_1mi.b)+(2_ui0|2_ui1)\
@@ -731,9 +731,38 @@
(eq_attr "itanium_class" "fcvtfx"))
(eq (symbol_ref "bundling_p") (const_int 0))) "2_F")
(define_insn_reservation "2_fld" 6
- (and (and (eq_attr "cpu" "itanium2")
- (eq_attr "itanium_class" "fld"))
- (eq (symbol_ref "bundling_p") (const_int 0))) "2_M")
+ (and (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "data_speculative" "no"))
+ (eq_attr "check_load" "no"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "2_M")
+(define_insn_reservation "2_flda" 6
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "data_speculative" "yes"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "2_M_only_um01")
+(define_insn_reservation "2_fldc" 0
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "check_load" "yes"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "2_M_only_um01")
+
+(define_insn_reservation "2_fldp" 6
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fldp"))
+ (eq_attr "check_load" "no"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "2_M_only_um01")
+(define_insn_reservation "2_fldpc" 0
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fldp"))
+ (eq_attr "check_load" "yes"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "2_M_only_um01")
+
(define_insn_reservation "2_fmac" 4
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "fmac"))
@@ -786,17 +815,29 @@
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "ilog"))
(eq (symbol_ref "bundling_p") (const_int 0))) "2_A")
+(define_insn_reservation "2_mmalua" 2
+ (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "mmalua"))
+ (eq (symbol_ref "bundling_p") (const_int 0))) "2_A")
;; Latency time ???
(define_insn_reservation "2_ishf" 1
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "ishf"))
(eq (symbol_ref "bundling_p") (const_int 0)))
"2_I+2_only_ui0")
+
(define_insn_reservation "2_ld" 1
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "ld"))
+ (eq_attr "check_load" "no"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "2_M_only_um01")
+(define_insn_reservation "2_ldc" 0
(and (and (eq_attr "cpu" "itanium2")
- (eq_attr "itanium_class" "ld"))
+ (eq_attr "check_load" "yes"))
(eq (symbol_ref "bundling_p") (const_int 0)))
"2_M_only_um01")
+
(define_insn_reservation "2_long_i" 1
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "long_i"))
@@ -900,11 +941,22 @@
(eq_attr "itanium_class" "xtd"))
(eq (symbol_ref "bundling_p") (const_int 0))) "2_I")
-(define_insn_reservation "2_chk_s" 0
+(define_insn_reservation "2_chk_s_i" 0
(and (and (eq_attr "cpu" "itanium2")
- (eq_attr "itanium_class" "chk_s"))
+ (eq_attr "itanium_class" "chk_s_i"))
(eq (symbol_ref "bundling_p") (const_int 0)))
"2_I|2_M_only_um23")
+(define_insn_reservation "2_chk_s_f" 0
+ (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "chk_s_f"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "2_M_only_um23")
+(define_insn_reservation "2_chk_a" 0
+ (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "chk_a"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "2_M_only_um01")
+
(define_insn_reservation "2_lfetch" 0
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "lfetch"))
@@ -1016,23 +1068,24 @@
(define_bypass 0 "2_tbit" "2_br,2_scall")
(define_bypass 2 "2_ld" "2_ld" "ia64_ld_address_bypass_p")
(define_bypass 2 "2_ld" "2_st" "ia64_st_address_bypass_p")
-(define_bypass 2 "2_ld" "2_mmmul,2_mmshf")
-(define_bypass 3 "2_ilog" "2_mmmul,2_mmshf")
-(define_bypass 3 "2_ialu" "2_mmmul,2_mmshf")
-(define_bypass 3 "2_mmmul,2_mmshf" "2_ialu,2_ilog,2_ishf,2_st,2_ld")
+(define_bypass 2 "2_ld,2_ldc" "2_mmalua,2_mmmul,2_mmshf")
+(define_bypass 3 "2_ilog" "2_mmalua,2_mmmul,2_mmshf")
+(define_bypass 3 "2_ialu" "2_mmalua,2_mmmul,2_mmshf")
+(define_bypass 3 "2_mmalua,2_mmmul,2_mmshf" "2_ialu,2_ilog,2_ishf,2_st,2_ld,2_ldc")
(define_bypass 6 "2_tofr" "2_frfr,2_stf")
(define_bypass 7 "2_fmac" "2_frfr,2_stf")
;; We don't use here fcmp because scall may be predicated.
-(define_bypass 0 "2_fcvtfx,2_fld,2_fmac,2_fmisc,2_frar_i,2_frar_m,\
- 2_frbr,2_frfr,2_frpr,2_ialu,2_ilog,2_ishf,2_ld,2_long_i,\
- 2_mmmul,2_mmshf,2_mmshfi,2_toar_m,2_tofr,2_xmpy,2_xtd"
+(define_bypass 0 "2_fcvtfx,2_fld,2_flda,2_fldc,2_fmac,2_fmisc,2_frar_i,2_frar_m,\
+ 2_frbr,2_frfr,2_frpr,2_ialu,2_ilog,2_ishf,2_ld,2_ldc,2_long_i,\
+ 2_mmalua,2_mmmul,2_mmshf,2_mmshfi,2_toar_m,2_tofr,\
+ 2_xmpy,2_xtd"
"2_scall")
-(define_bypass 0 "2_unknown,2_ignore,2_stop_bit,2_br,2_fcmp,2_fcvtfx,2_fld,\
+(define_bypass 0 "2_unknown,2_ignore,2_stop_bit,2_br,2_fcmp,2_fcvtfx,2_fld,2_flda,2_fldc,\
2_fmac,2_fmisc,2_frar_i,2_frar_m,2_frbr,2_frfr,2_frpr,\
- 2_ialu,2_icmp,2_ilog,2_ishf,2_ld,2_chk_s,\
- 2_long_i,2_mmmul,2_mmshf,2_mmshfi,2_nop,2_nop_b,2_nop_f,\
+ 2_ialu,2_icmp,2_ilog,2_ishf,2_ld,2_ldc,2_chk_s_i,2_chk_s_f,2_chk_a,2_long_i,\
+ 2_mmalua,2_mmmul,2_mmshf,2_mmshfi,2_nop,2_nop_b,2_nop_f,\
2_nop_i,2_nop_m,2_nop_x,2_rse_m,2_scall,2_sem,2_stf,2_st,\
2_syst_m0,2_syst_m,2_tbit,2_toar_i,2_toar_m,2_tobr,2_tofr,\
2_topr,2_xmpy,2_xtd,2_lfetch" "2_ignore")
@@ -1274,7 +1327,7 @@
"2b_stop")
;; The issue logic can reorder M slot insns between different subtypes
-;; but can not reorder insn within the same subtypes. The following
+;; but cannot reorder insn within the same subtypes. The following
;; constraint is enough to describe this.
(final_presence_set "2b_um1" "2b_um0")
(final_presence_set "2b_um3" "2b_um2")
@@ -1335,7 +1388,7 @@
+(2b_um2|2b_um3)")
;; I instruction is dispersed to the lowest numbered I unit
-;; not already in use. Remeber about possible splitting.
+;; not already in use. Remember about possible splitting.
(define_reservation "2b_I"
"2b_0mi.i+2_2+2b_ui0|2b_0mii.+2_3+(2b_ui0|2b_ui1)|2b_0mmi.+2_3+2b_ui0\
|2b_0mfi.+2_3+2b_ui0|2b_0mi.b+2_2+2b_ui0\
@@ -1533,9 +1586,38 @@
(eq_attr "itanium_class" "fcvtfx"))
(ne (symbol_ref "bundling_p") (const_int 0))) "2b_F")
(define_insn_reservation "2b_fld" 6
- (and (and (eq_attr "cpu" "itanium2")
- (eq_attr "itanium_class" "fld"))
- (ne (symbol_ref "bundling_p") (const_int 0))) "2b_M")
+ (and (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "data_speculative" "no"))
+ (eq_attr "check_load" "no"))
+ (ne (symbol_ref "bundling_p") (const_int 0)))
+ "2b_M")
+(define_insn_reservation "2b_flda" 6
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "data_speculative" "yes"))
+ (ne (symbol_ref "bundling_p") (const_int 0)))
+ "2b_M_only_um01")
+(define_insn_reservation "2b_fldc" 0
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "check_load" "yes"))
+ (ne (symbol_ref "bundling_p") (const_int 0)))
+ "2b_M_only_um01")
+
+(define_insn_reservation "2b_fldp" 6
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fldp"))
+ (eq_attr "check_load" "no"))
+ (ne (symbol_ref "bundling_p") (const_int 0)))
+ "2b_M_only_um01")
+(define_insn_reservation "2b_fldpc" 0
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fldp"))
+ (eq_attr "check_load" "yes"))
+ (ne (symbol_ref "bundling_p") (const_int 0)))
+ "2b_M_only_um01")
+
(define_insn_reservation "2b_fmac" 4
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "fmac"))
@@ -1586,17 +1668,30 @@
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "ilog"))
(ne (symbol_ref "bundling_p") (const_int 0))) "2b_A")
+(define_insn_reservation "2b_mmalua" 2
+ (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "mmalua"))
+ (ne (symbol_ref "bundling_p") (const_int 0))) "2b_A")
;; Latency time ???
(define_insn_reservation "2b_ishf" 1
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "ishf"))
(ne (symbol_ref "bundling_p") (const_int 0)))
"2b_I+2b_only_ui0")
+
(define_insn_reservation "2b_ld" 1
- (and (and (eq_attr "cpu" "itanium2")
- (eq_attr "itanium_class" "ld"))
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "ld"))
+ (eq_attr "check_load" "no"))
+ (ne (symbol_ref "bundling_p") (const_int 0)))
+ "2b_M_only_um01")
+(define_insn_reservation "2b_ldc" 0
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "ld"))
+ (eq_attr "check_load" "yes"))
(ne (symbol_ref "bundling_p") (const_int 0)))
"2b_M_only_um01")
+
(define_insn_reservation "2b_long_i" 1
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "long_i"))
@@ -1695,11 +1790,23 @@
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "xtd"))
(ne (symbol_ref "bundling_p") (const_int 0))) "2b_I")
-(define_insn_reservation "2b_chk_s" 0
+
+(define_insn_reservation "2b_chk_s_i" 0
(and (and (eq_attr "cpu" "itanium2")
- (eq_attr "itanium_class" "chk_s"))
+ (eq_attr "itanium_class" "chk_s_i"))
(ne (symbol_ref "bundling_p") (const_int 0)))
"2b_I|2b_M_only_um23")
+(define_insn_reservation "2b_chk_s_f" 0
+ (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "chk_s_f"))
+ (ne (symbol_ref "bundling_p") (const_int 0)))
+ "2b_M_only_um23")
+(define_insn_reservation "2b_chk_a" 0
+ (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "chk_a"))
+ (ne (symbol_ref "bundling_p") (const_int 0)))
+ "2b_M_only_um01")
+
(define_insn_reservation "2b_lfetch" 0
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "lfetch"))
diff --git a/contrib/gcc/config/ia64/lib1funcs.asm b/contrib/gcc/config/ia64/lib1funcs.asm
index e3d348b..245a8bb 100644
--- a/contrib/gcc/config/ia64/lib1funcs.asm
+++ b/contrib/gcc/config/ia64/lib1funcs.asm
@@ -1,3 +1,30 @@
+/* Copyright (C) 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
+ Contributed by James E. Wilson <wilson@cygnus.com>.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
+
#ifdef L__divxf3
// Compute a 80-bit IEEE double-extended quotient.
//
@@ -139,10 +166,13 @@ __divdi3:
// Transfer inputs to FP registers.
setf.sig f8 = in0
setf.sig f9 = in1
+ // Check divide by zero.
+ cmp.ne.unc p0,p7=0,in1
;;
// Convert the inputs to FP, so that they won't be treated as unsigned.
fcvt.xf f8 = f8
fcvt.xf f9 = f9
+(p7) break 1
;;
// Compute the reciprocal approximation.
frcpa.s1 f10, p6 = f8, f9
@@ -189,10 +219,13 @@ __moddi3:
// Transfer inputs to FP registers.
setf.sig f14 = in0
setf.sig f9 = in1
+ // Check divide by zero.
+ cmp.ne.unc p0,p7=0,in1
;;
// Convert the inputs to FP, so that they won't be treated as unsigned.
fcvt.xf f8 = f14
fcvt.xf f9 = f9
+(p7) break 1
;;
// Compute the reciprocal approximation.
frcpa.s1 f10, p6 = f8, f9
@@ -243,10 +276,13 @@ __udivdi3:
// Transfer inputs to FP registers.
setf.sig f8 = in0
setf.sig f9 = in1
+ // Check divide by zero.
+ cmp.ne.unc p0,p7=0,in1
;;
// Convert the inputs to FP, to avoid FP software-assist faults.
fcvt.xuf.s1 f8 = f8
fcvt.xuf.s1 f9 = f9
+(p7) break 1
;;
// Compute the reciprocal approximation.
frcpa.s1 f10, p6 = f8, f9
@@ -293,10 +329,13 @@ __umoddi3:
// Transfer inputs to FP registers.
setf.sig f14 = in0
setf.sig f9 = in1
+ // Check divide by zero.
+ cmp.ne.unc p0,p7=0,in1
;;
// Convert the inputs to FP, to avoid FP software assist faults.
fcvt.xuf.s1 f8 = f14
fcvt.xuf.s1 f9 = f9
+(p7) break 1;
;;
// Compute the reciprocal approximation.
frcpa.s1 f10, p6 = f8, f9
@@ -345,11 +384,14 @@ __umoddi3:
.proc __divsi3
__divsi3:
.regstk 2,0,0,0
+ // Check divide by zero.
+ cmp.ne.unc p0,p7=0,in1
sxt4 in0 = in0
sxt4 in1 = in1
;;
setf.sig f8 = in0
setf.sig f9 = in1
+(p7) break 1
;;
mov r2 = 0x0ffdd
fcvt.xf f8 = f8
@@ -394,6 +436,8 @@ __modsi3:
;;
setf.sig f13 = r32
setf.sig f9 = r33
+ // Check divide by zero.
+ cmp.ne.unc p0,p7=0,in1
;;
sub in1 = r0, in1
fcvt.xf f8 = f13
@@ -401,6 +445,7 @@ __modsi3:
;;
setf.exp f11 = r2
frcpa.s1 f10, p6 = f8, f9
+(p7) break 1
;;
(p6) fmpy.s1 f12 = f8, f10
(p6) fnma.s1 f10 = f9, f10, f1
@@ -441,9 +486,12 @@ __udivsi3:
;;
setf.sig f8 = in0
setf.sig f9 = in1
+ // Check divide by zero.
+ cmp.ne.unc p0,p7=0,in1
;;
fcvt.xf f8 = f8
fcvt.xf f9 = f9
+(p7) break 1
;;
setf.exp f11 = r2
frcpa.s1 f10, p6 = f8, f9
@@ -484,6 +532,8 @@ __umodsi3:
;;
setf.sig f13 = in0
setf.sig f9 = in1
+ // Check divide by zero.
+ cmp.ne.unc p0,p7=0,in1
;;
sub in1 = r0, in1
fcvt.xf f8 = f13
@@ -491,6 +541,7 @@ __umodsi3:
;;
setf.exp f11 = r2
frcpa.s1 f10, p6 = f8, f9
+(p7) break 1;
;;
(p6) fmpy.s1 f12 = f8, f10
(p6) fnma.s1 f10 = f9, f10, f1
@@ -706,9 +757,8 @@ __ia64_trampoline:
.endp __ia64_trampoline
#endif
-#ifdef L__compat
// Thunks for backward compatibility.
-
+#ifdef L_fixtfdi
.text
.align 16
.global __fixtfti
@@ -719,7 +769,8 @@ __fixtfti:
;;
}
.endp __fixtfti
-
+#endif
+#ifdef L_fixunstfdi
.align 16
.global __fixunstfti
.proc __fixunstfti
@@ -729,7 +780,8 @@ __fixunstfti:
;;
}
.endp __fixunstfti
-
+#endif
+#if L_floatditf
.align 16
.global __floattitf
.proc __floattitf
@@ -739,5 +791,4 @@ __floattitf:
;;
}
.endp __floattitf
-
#endif
diff --git a/contrib/gcc/config/ia64/linux-unwind.h b/contrib/gcc/config/ia64/linux-unwind.h
new file mode 100644
index 0000000..8b2878e
--- /dev/null
+++ b/contrib/gcc/config/ia64/linux-unwind.h
@@ -0,0 +1,193 @@
+/* DWARF2 EH unwinding support for IA64 Linux.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ In addition to the permissions in the GNU General Public License,
+ the Free Software Foundation gives you unlimited permission to link
+ the compiled version of this file with other programs, and to
+ distribute those programs without any restriction coming from the
+ use of this file. (The General Public License restrictions do
+ apply in other respects; for example, they cover modification of
+ the file, and distribution when not linked into another program.)
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+/* This works only for glibc-2.3 and later, because sigcontext is different
+ in glibc-2.2.4. */
+
+#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)
+#include <signal.h>
+#include <sys/ucontext.h>
+
+#define IA64_GATE_AREA_START 0xa000000000000100LL
+#define IA64_GATE_AREA_END 0xa000000000030000LL
+
+#define MD_FALLBACK_FRAME_STATE_FOR ia64_fallback_frame_state
+
+static _Unwind_Reason_Code
+ia64_fallback_frame_state (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+{
+ if (context->rp >= IA64_GATE_AREA_START
+ && context->rp < IA64_GATE_AREA_END)
+ {
+ struct sigframe {
+ char scratch[16];
+ unsigned long sig_number;
+ struct siginfo *info;
+ struct sigcontext *sc;
+ } *frame_ = (struct sigframe *)context->psp;
+ struct sigcontext *sc = frame_->sc;
+
+ /* Restore scratch registers in case the unwinder needs to
+ refer to a value stored in one of them. */
+ {
+ int i;
+
+ for (i = 2; i < 4; i++)
+ context->ireg[i - 2].loc = &sc->sc_gr[i];
+ for (i = 8; i < 12; i++)
+ context->ireg[i - 2].loc = &sc->sc_gr[i];
+ for (i = 14; i < 32; i++)
+ context->ireg[i - 2].loc = &sc->sc_gr[i];
+ }
+
+ context->fpsr_loc = &(sc->sc_ar_fpsr);
+ context->pfs_loc = &(sc->sc_ar_pfs);
+ context->lc_loc = &(sc->sc_ar_lc);
+ context->unat_loc = &(sc->sc_ar_unat);
+ context->br_loc[0] = &(sc->sc_br[0]);
+ context->br_loc[6] = &(sc->sc_br[6]);
+ context->br_loc[7] = &(sc->sc_br[7]);
+ context->pr = sc->sc_pr;
+ context->psp = sc->sc_gr[12];
+ context->gp = sc->sc_gr[1];
+ /* Signal frame doesn't have an associated reg. stack frame
+ other than what we adjust for below. */
+ fs -> no_reg_stack_frame = 1;
+
+ if (sc->sc_rbs_base)
+ {
+ /* Need to switch from alternate register backing store. */
+ long ndirty, loadrs = sc->sc_loadrs >> 16;
+ unsigned long alt_bspstore = context->bsp - loadrs;
+ unsigned long bspstore;
+ unsigned long *ar_bsp = (unsigned long *)(sc->sc_ar_bsp);
+
+ ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore,
+ (unsigned long *) context->bsp);
+ bspstore = (unsigned long)
+ ia64_rse_skip_regs (ar_bsp, -ndirty);
+ ia64_copy_rbs (context, bspstore, alt_bspstore, loadrs,
+ sc->sc_ar_rnat);
+ }
+
+ /* Don't touch the branch registers o.t. b0, b6 and b7.
+ The kernel doesn't pass the preserved branch registers
+ in the sigcontext but leaves them intact, so there's no
+ need to do anything with them here. */
+ {
+ unsigned long sof = sc->sc_cfm & 0x7f;
+ context->bsp = (unsigned long)
+ ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof);
+ }
+
+ fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_SPREL;
+ fs->curr.reg[UNW_REG_RP].val
+ = (unsigned long)&(sc->sc_ip) - context->psp;
+ fs->curr.reg[UNW_REG_RP].when = -1;
+
+ return _URC_NO_REASON;
+ }
+ return _URC_END_OF_STACK;
+}
+
+#define MD_HANDLE_UNWABI ia64_handle_unwabi
+
+static void
+ia64_handle_unwabi (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+ if (fs->unwabi == ((3 << 8) | 's')
+ || fs->unwabi == ((0 << 8) | 's'))
+ {
+ struct sigframe {
+ char scratch[16];
+ unsigned long sig_number;
+ struct siginfo *info;
+ struct sigcontext *sc;
+ } *frame = (struct sigframe *)context->psp;
+ struct sigcontext *sc = frame->sc;
+
+ /* Restore scratch registers in case the unwinder needs to
+ refer to a value stored in one of them. */
+ {
+ int i;
+
+ for (i = 2; i < 4; i++)
+ context->ireg[i - 2].loc = &sc->sc_gr[i];
+ for (i = 8; i < 12; i++)
+ context->ireg[i - 2].loc = &sc->sc_gr[i];
+ for (i = 14; i < 32; i++)
+ context->ireg[i - 2].loc = &sc->sc_gr[i];
+ }
+
+ context->pfs_loc = &(sc->sc_ar_pfs);
+ context->lc_loc = &(sc->sc_ar_lc);
+ context->unat_loc = &(sc->sc_ar_unat);
+ context->br_loc[0] = &(sc->sc_br[0]);
+ context->br_loc[6] = &(sc->sc_br[6]);
+ context->br_loc[7] = &(sc->sc_br[7]);
+ context->pr = sc->sc_pr;
+ context->gp = sc->sc_gr[1];
+ /* Signal frame doesn't have an associated reg. stack frame
+ other than what we adjust for below. */
+ fs -> no_reg_stack_frame = 1;
+
+ if (sc->sc_rbs_base)
+ {
+ /* Need to switch from alternate register backing store. */
+ long ndirty, loadrs = sc->sc_loadrs >> 16;
+ unsigned long alt_bspstore = context->bsp - loadrs;
+ unsigned long bspstore;
+ unsigned long *ar_bsp = (unsigned long *)(sc->sc_ar_bsp);
+
+ ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore,
+ (unsigned long *) context->bsp);
+ bspstore = (unsigned long) ia64_rse_skip_regs (ar_bsp, -ndirty);
+ ia64_copy_rbs (context, bspstore, alt_bspstore, loadrs,
+ sc->sc_ar_rnat);
+ }
+
+ /* Don't touch the branch registers o.t. b0, b6 and b7.
+ The kernel doesn't pass the preserved branch registers
+ in the sigcontext but leaves them intact, so there's no
+ need to do anything with them here. */
+ {
+ unsigned long sof = sc->sc_cfm & 0x7f;
+ context->bsp = (unsigned long)
+ ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof);
+ }
+
+ /* pfs_loc already set above. Without this pfs_loc would point
+ incorrectly to sc_cfm instead of sc_ar_pfs. */
+ fs->curr.reg[UNW_REG_PFS].where = UNW_WHERE_NONE;
+ }
+}
+#endif /* glibc-2.3 or better */
diff --git a/contrib/gcc/config/ia64/linux.h b/contrib/gcc/config/ia64/linux.h
index 5c73b0c..cecae0d 100644
--- a/contrib/gcc/config/ia64/linux.h
+++ b/contrib/gcc/config/ia64/linux.h
@@ -37,15 +37,18 @@ do { \
/* Define this for shared library support because it isn't in the main
linux.h file. */
+#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux-ia64.so.2"
+
#undef LINK_SPEC
#define LINK_SPEC "\
%{shared:-shared} \
%{!shared: \
%{!static: \
%{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /lib/ld-linux-ia64.so.2}} \
+ %{!dynamic-linker:-dynamic-linker " LINUX_DYNAMIC_LINKER "}} \
%{static:-static}}"
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
#define JMP_BUF_SIZE 76
@@ -55,161 +58,4 @@ do { \
#undef LINK_EH_SPEC
#define LINK_EH_SPEC ""
-/* Do code reading to identify a signal frame, and set the frame
- state data appropriately. See unwind-dw2.c for the structs. */
-
-/* This works only for glibc-2.3 and later, because sigcontext is different
- in glibc-2.2.4. */
-
-#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)
-
-#ifdef IN_LIBGCC2
-#include <signal.h>
-#include <sys/ucontext.h>
-
-#define IA64_GATE_AREA_START 0xa000000000000100LL
-#define IA64_GATE_AREA_END 0xa000000000030000LL
-
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- if ((CONTEXT)->rp >= IA64_GATE_AREA_START \
- && (CONTEXT)->rp < IA64_GATE_AREA_END) \
- { \
- struct sigframe { \
- char scratch[16]; \
- unsigned long sig_number; \
- struct siginfo *info; \
- struct sigcontext *sc; \
- } *frame_ = (struct sigframe *)(CONTEXT)->psp; \
- struct sigcontext *sc_ = frame_->sc; \
- \
- /* Restore scratch registers in case the unwinder needs to \
- refer to a value stored in one of them. */ \
- { \
- int i_; \
- \
- for (i_ = 2; i_ < 4; i_++) \
- (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
- for (i_ = 8; i_ < 12; i_++) \
- (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
- for (i_ = 14; i_ < 32; i_++) \
- (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
- } \
- \
- (CONTEXT)->fpsr_loc = &(sc_->sc_ar_fpsr); \
- (CONTEXT)->pfs_loc = &(sc_->sc_ar_pfs); \
- (CONTEXT)->lc_loc = &(sc_->sc_ar_lc); \
- (CONTEXT)->unat_loc = &(sc_->sc_ar_unat); \
- (CONTEXT)->br_loc[0] = &(sc_->sc_br[0]); \
- (CONTEXT)->br_loc[6] = &(sc_->sc_br[6]); \
- (CONTEXT)->br_loc[7] = &(sc_->sc_br[7]); \
- (CONTEXT)->pr = sc_->sc_pr; \
- (CONTEXT)->psp = sc_->sc_gr[12]; \
- (CONTEXT)->gp = sc_->sc_gr[1]; \
- /* Signal frame doesn't have an associated reg. stack frame \
- other than what we adjust for below. */ \
- (FS) -> no_reg_stack_frame = 1; \
- \
- if (sc_->sc_rbs_base) \
- { \
- /* Need to switch from alternate register backing store. */ \
- long ndirty, loadrs = sc_->sc_loadrs >> 16; \
- unsigned long alt_bspstore = (CONTEXT)->bsp - loadrs; \
- unsigned long bspstore; \
- unsigned long *ar_bsp = (unsigned long *)(sc_->sc_ar_bsp); \
- \
- ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore, \
- (unsigned long *) (CONTEXT)->bsp);\
- bspstore = (unsigned long) \
- ia64_rse_skip_regs (ar_bsp, -ndirty); \
- ia64_copy_rbs ((CONTEXT), bspstore, alt_bspstore, loadrs, \
- sc_->sc_ar_rnat); \
- } \
- \
- /* Don't touch the branch registers o.t. b0, b6 and b7. \
- The kernel doesn't pass the preserved branch registers \
- in the sigcontext but leaves them intact, so there's no \
- need to do anything with them here. */ \
- { \
- unsigned long sof = sc_->sc_cfm & 0x7f; \
- (CONTEXT)->bsp = (unsigned long) \
- ia64_rse_skip_regs ((unsigned long *)(sc_->sc_ar_bsp), -sof); \
- } \
- \
- (FS)->curr.reg[UNW_REG_RP].where = UNW_WHERE_SPREL; \
- (FS)->curr.reg[UNW_REG_RP].val \
- = (unsigned long)&(sc_->sc_ip) - (CONTEXT)->psp; \
- (FS)->curr.reg[UNW_REG_RP].when = -1; \
- \
- goto SUCCESS; \
- }
-
-#define MD_HANDLE_UNWABI(CONTEXT, FS) \
- if ((FS)->unwabi == ((3 << 8) | 's') \
- || (FS)->unwabi == ((0 << 8) | 's')) \
- { \
- struct sigframe { \
- char scratch[16]; \
- unsigned long sig_number; \
- struct siginfo *info; \
- struct sigcontext *sc; \
- } *frame_ = (struct sigframe *)(CONTEXT)->psp; \
- struct sigcontext *sc_ = frame_->sc; \
- \
- /* Restore scratch registers in case the unwinder needs to \
- refer to a value stored in one of them. */ \
- { \
- int i_; \
- \
- for (i_ = 2; i_ < 4; i_++) \
- (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
- for (i_ = 8; i_ < 12; i_++) \
- (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
- for (i_ = 14; i_ < 32; i_++) \
- (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
- } \
- \
- (CONTEXT)->pfs_loc = &(sc_->sc_ar_pfs); \
- (CONTEXT)->lc_loc = &(sc_->sc_ar_lc); \
- (CONTEXT)->unat_loc = &(sc_->sc_ar_unat); \
- (CONTEXT)->br_loc[0] = &(sc_->sc_br[0]); \
- (CONTEXT)->br_loc[6] = &(sc_->sc_br[6]); \
- (CONTEXT)->br_loc[7] = &(sc_->sc_br[7]); \
- (CONTEXT)->pr = sc_->sc_pr; \
- (CONTEXT)->gp = sc_->sc_gr[1]; \
- /* Signal frame doesn't have an associated reg. stack frame \
- other than what we adjust for below. */ \
- (FS) -> no_reg_stack_frame = 1; \
- \
- if (sc_->sc_rbs_base) \
- { \
- /* Need to switch from alternate register backing store. */ \
- long ndirty, loadrs = sc_->sc_loadrs >> 16; \
- unsigned long alt_bspstore = (CONTEXT)->bsp - loadrs; \
- unsigned long bspstore; \
- unsigned long *ar_bsp = (unsigned long *)(sc_->sc_ar_bsp); \
- \
- ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore, \
- (unsigned long *) (CONTEXT)->bsp);\
- bspstore = (unsigned long) \
- ia64_rse_skip_regs (ar_bsp, -ndirty); \
- ia64_copy_rbs ((CONTEXT), bspstore, alt_bspstore, loadrs, \
- sc_->sc_ar_rnat); \
- } \
- \
- /* Don't touch the branch registers o.t. b0, b6 and b7. \
- The kernel doesn't pass the preserved branch registers \
- in the sigcontext but leaves them intact, so there's no \
- need to do anything with them here. */ \
- { \
- unsigned long sof = sc_->sc_cfm & 0x7f; \
- (CONTEXT)->bsp = (unsigned long) \
- ia64_rse_skip_regs ((unsigned long *)(sc_->sc_ar_bsp), -sof); \
- } \
- \
- /* pfs_loc already set above. Without this pfs_loc would point \
- incorrectly to sc_cfm instead of sc_ar_pfs. */ \
- (FS)->curr.reg[UNW_REG_PFS].where = UNW_WHERE_NONE; \
- }
-
-#endif /* IN_LIBGCC2 */
-#endif /* glibc-2.3 or better */
+#define MD_UNWIND_SUPPORT "config/ia64/linux-unwind.h"
diff --git a/contrib/gcc/config/ia64/predicates.md b/contrib/gcc/config/ia64/predicates.md
new file mode 100644
index 0000000..657c150
--- /dev/null
+++ b/contrib/gcc/config/ia64/predicates.md
@@ -0,0 +1,591 @@
+;; Predicate definitions for IA-64.
+;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;; True if OP is a valid operand for the MEM of a CALL insn.
+(define_predicate "call_operand"
+ (ior (match_code "symbol_ref")
+ (match_operand 0 "register_operand")))
+
+;; True if OP refers to any kind of symbol.
+;; For roughly the same reasons that pmode_register_operand exists, this
+;; predicate ignores its mode argument.
+(define_special_predicate "symbolic_operand"
+ (match_code "symbol_ref,const,label_ref"))
+
+;; True if OP is a SYMBOL_REF which refers to a function.
+(define_predicate "function_operand"
+ (and (match_code "symbol_ref")
+ (match_test "SYMBOL_REF_FUNCTION_P (op)")))
+
+;; True if OP refers to a symbol in the sdata section.
+(define_predicate "sdata_symbolic_operand"
+ (match_code "symbol_ref,const")
+{
+ HOST_WIDE_INT offset = 0, size = 0;
+
+ switch (GET_CODE (op))
+ {
+ case CONST:
+ op = XEXP (op, 0);
+ if (GET_CODE (op) != PLUS
+ || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+ || GET_CODE (XEXP (op, 1)) != CONST_INT)
+ return false;
+ offset = INTVAL (XEXP (op, 1));
+ op = XEXP (op, 0);
+ /* FALLTHRU */
+
+ case SYMBOL_REF:
+ if (CONSTANT_POOL_ADDRESS_P (op))
+ {
+ size = GET_MODE_SIZE (get_pool_mode (op));
+ if (size > ia64_section_threshold)
+ return false;
+ }
+ else
+ {
+ tree t;
+
+ if (!SYMBOL_REF_LOCAL_P (op) || !SYMBOL_REF_SMALL_P (op))
+ return false;
+
+ /* Note that in addition to DECLs, we can get various forms
+ of constants here. */
+ t = SYMBOL_REF_DECL (op);
+ if (DECL_P (t))
+ t = DECL_SIZE_UNIT (t);
+ else
+ t = TYPE_SIZE_UNIT (TREE_TYPE (t));
+ if (t && host_integerp (t, 0))
+ {
+ size = tree_low_cst (t, 0);
+ if (size < 0)
+ size = 0;
+ }
+ }
+
+ /* Deny the stupid user trick of addressing outside the object. Such
+ things quickly result in GPREL22 relocation overflows. Of course,
+ they're also highly undefined. From a pure pedant's point of view
+ they deserve a slap on the wrist (such as provided by a relocation
+ overflow), but that just leads to bugzilla noise. */
+ return (offset >= 0 && offset <= size);
+
+ default:
+ gcc_unreachable ();
+ }
+})
+
+;; True if OP refers to a symbol in the small address area.
+(define_predicate "small_addr_symbolic_operand"
+ (match_code "symbol_ref,const")
+{
+ switch (GET_CODE (op))
+ {
+ case CONST:
+ op = XEXP (op, 0);
+ if (GET_CODE (op) != PLUS
+ || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+ || GET_CODE (XEXP (op, 1)) != CONST_INT)
+ return false;
+ op = XEXP (op, 0);
+ /* FALLTHRU */
+
+ case SYMBOL_REF:
+ return SYMBOL_REF_SMALL_ADDR_P (op);
+
+ default:
+ gcc_unreachable ();
+ }
+})
+
+;; True if OP refers to a symbol with which we may use any offset.
+(define_predicate "any_offset_symbol_operand"
+ (match_code "symbol_ref")
+{
+ if (TARGET_NO_PIC || TARGET_AUTO_PIC)
+ return true;
+ if (SYMBOL_REF_SMALL_ADDR_P (op))
+ return true;
+ if (SYMBOL_REF_FUNCTION_P (op))
+ return false;
+ if (sdata_symbolic_operand (op, mode))
+ return true;
+ return false;
+})
+
+;; True if OP refers to a symbol with which we may use 14-bit aligned offsets.
+;; False if OP refers to a symbol with which we may not use any offset at any
+;; time.
+(define_predicate "aligned_offset_symbol_operand"
+ (and (match_code "symbol_ref")
+ (match_test "! SYMBOL_REF_FUNCTION_P (op)")))
+
+;; True if OP refers to a symbol, and is appropriate for a GOT load.
+(define_predicate "got_symbolic_operand"
+ (match_operand 0 "symbolic_operand" "")
+{
+ HOST_WIDE_INT addend = 0;
+
+ switch (GET_CODE (op))
+ {
+ case LABEL_REF:
+ return true;
+
+ case CONST:
+ /* Accept only (plus (symbol_ref) (const_int)). */
+ op = XEXP (op, 0);
+ if (GET_CODE (op) != PLUS
+ || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+ || GET_CODE (XEXP (op, 1)) != CONST_INT)
+ return false;
+
+ addend = INTVAL (XEXP (op, 1));
+ op = XEXP (op, 0);
+ /* FALLTHRU */
+
+ case SYMBOL_REF:
+ /* These symbols shouldn't be used with got loads. */
+ if (SYMBOL_REF_SMALL_ADDR_P (op))
+ return false;
+ if (SYMBOL_REF_TLS_MODEL (op) != 0)
+ return false;
+
+ if (any_offset_symbol_operand (op, mode))
+ return true;
+
+ /* The low 14 bits of the constant have been forced to zero
+ so that we do not use up so many GOT entries. Prevent cse
+ from undoing this. */
+ if (aligned_offset_symbol_operand (op, mode))
+ return (addend & 0x3fff) == 0;
+
+ return addend == 0;
+
+ default:
+ gcc_unreachable ();
+ }
+})
+
+;; Return true if OP is a valid thread local storage symbolic operand.
+(define_predicate "tls_symbolic_operand"
+ (match_code "symbol_ref,const")
+{
+ switch (GET_CODE (op))
+ {
+ case SYMBOL_REF:
+ return SYMBOL_REF_TLS_MODEL (op) != 0;
+
+ case CONST:
+ op = XEXP (op, 0);
+ if (GET_CODE (op) != PLUS
+ || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+ || GET_CODE (XEXP (op, 1)) != CONST_INT)
+ return false;
+
+ /* We only allow certain offsets for certain tls models. */
+ switch (SYMBOL_REF_TLS_MODEL (XEXP (op, 0)))
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ return false;
+
+ case TLS_MODEL_INITIAL_EXEC:
+ return (INTVAL (XEXP (op, 1)) & 0x3fff) == 0;
+
+ case TLS_MODEL_LOCAL_EXEC:
+ return true;
+
+ default:
+ return false;
+ }
+
+ default:
+ gcc_unreachable ();
+ }
+})
+
+;; Return true if OP is a local-dynamic thread local storage symbolic operand.
+(define_predicate "ld_tls_symbolic_operand"
+ (and (match_code "symbol_ref")
+ (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_DYNAMIC")))
+
+;; Return true if OP is an initial-exec thread local storage symbolic operand.
+(define_predicate "ie_tls_symbolic_operand"
+ (match_code "symbol_ref,const")
+{
+ switch (GET_CODE (op))
+ {
+ case CONST:
+ op = XEXP (op, 0);
+ if (GET_CODE (op) != PLUS
+ || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+ || GET_CODE (XEXP (op, 1)) != CONST_INT
+ || (INTVAL (XEXP (op, 1)) & 0x3fff) != 0)
+ return false;
+ op = XEXP (op, 0);
+ /* FALLTHRU */
+
+ case SYMBOL_REF:
+ return SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_INITIAL_EXEC;
+
+ default:
+ gcc_unreachable ();
+ }
+})
+
+;; Return true if OP is a local-exec thread local storage symbolic operand.
+(define_predicate "le_tls_symbolic_operand"
+ (match_code "symbol_ref,const")
+{
+ switch (GET_CODE (op))
+ {
+ case CONST:
+ op = XEXP (op, 0);
+ if (GET_CODE (op) != PLUS
+ || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+ || GET_CODE (XEXP (op, 1)) != CONST_INT)
+ return false;
+ op = XEXP (op, 0);
+ /* FALLTHRU */
+
+ case SYMBOL_REF:
+ return SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_EXEC;
+
+ default:
+ gcc_unreachable ();
+ }
+})
+
+;; Like nonimmediate_operand, but don't allow MEMs that try to use a
+;; POST_MODIFY with a REG as displacement.
+(define_predicate "destination_operand"
+ (and (match_operand 0 "nonimmediate_operand")
+ (match_test "GET_CODE (op) != MEM
+ || GET_CODE (XEXP (op, 0)) != POST_MODIFY
+ || GET_CODE (XEXP (XEXP (XEXP (op, 0), 1), 1)) != REG")))
+
+;; Like memory_operand, but don't allow post-increments.
+(define_predicate "not_postinc_memory_operand"
+ (and (match_operand 0 "memory_operand")
+ (match_test "GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != RTX_AUTOINC")))
+
+;; True if OP is a general operand, with some restrictions on symbols.
+(define_predicate "move_operand"
+ (match_operand 0 "general_operand")
+{
+ switch (GET_CODE (op))
+ {
+ case CONST:
+ {
+ HOST_WIDE_INT addend;
+
+ /* Accept only (plus (symbol_ref) (const_int)). */
+ op = XEXP (op, 0);
+ if (GET_CODE (op) != PLUS
+ || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+ || GET_CODE (XEXP (op, 1)) != CONST_INT)
+ return false;
+
+ addend = INTVAL (XEXP (op, 1));
+ op = XEXP (op, 0);
+
+ /* After reload, we want to allow any offset whatsoever. This
+ allows reload the opportunity to avoid spilling addresses to
+ the stack, and instead simply substitute in the value from a
+ REG_EQUIV. We'll split this up again when splitting the insn. */
+ if (reload_in_progress || reload_completed)
+ return true;
+
+ /* Some symbol types we allow to use with any offset. */
+ if (any_offset_symbol_operand (op, mode))
+ return true;
+
+ /* Some symbol types we allow offsets with the low 14 bits of the
+ constant forced to zero so that we do not use up so many GOT
+ entries. We want to prevent cse from undoing this. */
+ if (aligned_offset_symbol_operand (op, mode))
+ return (addend & 0x3fff) == 0;
+
+ /* The remaining symbol types may never be used with an offset. */
+ return false;
+ }
+
+ default:
+ return true;
+ }
+})
+
+;; True if OP is a register operand that is (or could be) a GR reg.
+(define_predicate "gr_register_operand"
+ (match_operand 0 "register_operand")
+{
+ unsigned int regno;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ regno = REGNO (op);
+ return (regno >= FIRST_PSEUDO_REGISTER || GENERAL_REGNO_P (regno));
+})
+
+;; True if OP is a register operand that is (or could be) an FR reg.
+(define_predicate "fr_register_operand"
+ (match_operand 0 "register_operand")
+{
+ unsigned int regno;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ regno = REGNO (op);
+ return (regno >= FIRST_PSEUDO_REGISTER || FR_REGNO_P (regno));
+})
+
+;; True if OP is a register operand that is (or could be) a GR/FR reg.
+(define_predicate "grfr_register_operand"
+ (match_operand 0 "register_operand")
+{
+ unsigned int regno;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ regno = REGNO (op);
+ return (regno >= FIRST_PSEUDO_REGISTER
+ || GENERAL_REGNO_P (regno)
+ || FR_REGNO_P (regno));
+})
+
+;; True if OP is a nonimmediate operand that is (or could be) a GR reg.
+(define_predicate "gr_nonimmediate_operand"
+ (match_operand 0 "nonimmediate_operand")
+{
+ unsigned int regno;
+
+ if (GET_CODE (op) == MEM)
+ return true;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ regno = REGNO (op);
+ return (regno >= FIRST_PSEUDO_REGISTER || GENERAL_REGNO_P (regno));
+})
+
+;; True if OP is a nonimmediate operand that is (or could be) a FR reg.
+(define_predicate "fr_nonimmediate_operand"
+ (match_operand 0 "nonimmediate_operand")
+{
+ unsigned int regno;
+
+ if (GET_CODE (op) == MEM)
+ return true;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ regno = REGNO (op);
+ return (regno >= FIRST_PSEUDO_REGISTER || FR_REGNO_P (regno));
+})
+
+;; True if OP is a nonimmediate operand that is (or could be) a GR/FR reg.
+(define_predicate "grfr_nonimmediate_operand"
+ (match_operand 0 "nonimmediate_operand")
+{
+ unsigned int regno;
+
+ if (GET_CODE (op) == MEM)
+ return true;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ regno = REGNO (op);
+ return (regno >= FIRST_PSEUDO_REGISTER
+ || GENERAL_REGNO_P (regno)
+ || FR_REGNO_P (regno));
+})
+
+;; True if OP is a GR register operand, or zero.
+(define_predicate "gr_reg_or_0_operand"
+ (ior (match_operand 0 "gr_register_operand")
+ (and (match_code "const_int,const_double,const_vector")
+ (match_test "op == CONST0_RTX (GET_MODE (op))"))))
+
+;; True if OP is a GR register operand, or a 5 bit immediate operand.
+(define_predicate "gr_reg_or_5bit_operand"
+ (ior (match_operand 0 "gr_register_operand")
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) < 32"))))
+
+;; True if OP is a GR register operand, or a 6 bit immediate operand.
+(define_predicate "gr_reg_or_6bit_operand"
+ (ior (match_operand 0 "gr_register_operand")
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_M (INTVAL (op))"))))
+
+;; True if OP is a GR register operand, or an 8 bit immediate operand.
+(define_predicate "gr_reg_or_8bit_operand"
+ (ior (match_operand 0 "gr_register_operand")
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_K (INTVAL (op))"))))
+
+;; True if OP is a GR/FR register operand, or an 8 bit immediate operand.
+(define_predicate "grfr_reg_or_8bit_operand"
+ (ior (match_operand 0 "grfr_register_operand")
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_K (INTVAL (op))"))))
+
+;; True if OP is a register operand, or an 8 bit adjusted immediate operand.
+(define_predicate "gr_reg_or_8bit_adjusted_operand"
+ (ior (match_operand 0 "gr_register_operand")
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_L (INTVAL (op))"))))
+
+;; True if OP is a register operand, or is valid for both an 8 bit
+;; immediate and an 8 bit adjusted immediate operand. This is necessary
+;; because when we emit a compare, we don't know what the condition will be,
+;; so we need the union of the immediates accepted by GT and LT.
+(define_predicate "gr_reg_or_8bit_and_adjusted_operand"
+ (ior (match_operand 0 "gr_register_operand")
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_K (INTVAL (op))
+ && CONST_OK_FOR_L (INTVAL (op))"))))
+
+;; True if OP is a register operand, or a 14 bit immediate operand.
+(define_predicate "gr_reg_or_14bit_operand"
+ (ior (match_operand 0 "gr_register_operand")
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_I (INTVAL (op))"))))
+
+;; True if OP is a register operand, or a 22 bit immediate operand.
+(define_predicate "gr_reg_or_22bit_operand"
+ (ior (match_operand 0 "gr_register_operand")
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_J (INTVAL (op))"))))
+
+;; True if OP is a 7 bit immediate operand.
+(define_predicate "dshift_count_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) < 128")))
+
+;; True if OP is a 6 bit immediate operand.
+(define_predicate "shift_count_operand"
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_M (INTVAL (op))")))
+
+;; True if OP-1 is a 6 bit immediate operand, used in extr instruction.
+(define_predicate "extr_len_operand"
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_M (INTVAL (op) - 1)")))
+
+;; True if OP is a 5 bit immediate operand.
+(define_predicate "shift_32bit_count_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) < 32")))
+
+;; True if OP is one of the immediate values 2, 4, 8, or 16.
+(define_predicate "shladd_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) == 2 || INTVAL (op) == 4 ||
+ INTVAL (op) == 8 || INTVAL (op) == 16")))
+
+;; True if OP is one of the immediate values 1, 2, 3, or 4.
+(define_predicate "shladd_log2_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 1 && INTVAL (op) <= 4")))
+
+;; True if OP is one of the immediate values -16, -8, -4, -1, 1, 4, 8, 16.
+(define_predicate "fetchadd_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) == -16 || INTVAL (op) == -8 ||
+ INTVAL (op) == -4 || INTVAL (op) == -1 ||
+ INTVAL (op) == 1 || INTVAL (op) == 4 ||
+ INTVAL (op) == 8 || INTVAL (op) == 16")))
+
+;; True if OP is 0..3.
+(define_predicate "const_int_2bit_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 3")))
+
+;; True if OP is a floating-point constant zero, one, or a register.
+(define_predicate "fr_reg_or_fp01_operand"
+ (ior (match_operand 0 "fr_register_operand")
+ (and (match_code "const_double")
+ (match_test "CONST_DOUBLE_OK_FOR_G (op)"))))
+
+;; Like fr_reg_or_fp01_operand, but don't allow any SUBREGs.
+(define_predicate "xfreg_or_fp01_operand"
+ (and (match_operand 0 "fr_reg_or_fp01_operand")
+ (not (match_code "subreg"))))
+
+;; True if OP is a constant zero, or a register.
+(define_predicate "fr_reg_or_0_operand"
+ (ior (match_operand 0 "fr_register_operand")
+ (and (match_code "const_double,const_vector")
+ (match_test "op == CONST0_RTX (GET_MODE (op))"))))
+
+;; True if this is a comparison operator, which accepts a normal 8-bit
+;; signed immediate operand.
+(define_predicate "normal_comparison_operator"
+ (match_code "eq,ne,gt,le,gtu,leu"))
+
+;; True if this is a comparison operator, which accepts an adjusted 8-bit
+;; signed immediate operand.
+(define_predicate "adjusted_comparison_operator"
+ (match_code "lt,ge,ltu,geu"))
+
+;; True if this is a signed inequality operator.
+(define_predicate "signed_inequality_operator"
+ (match_code "ge,gt,le,lt"))
+
+;; True if this operator is valid for predication.
+(define_predicate "predicate_operator"
+ (match_code "eq,ne"))
+
+;; True if this operator can be used in a conditional operation.
+(define_predicate "condop_operator"
+ (match_code "plus,minus,ior,xor,and"))
+
+;; These three are hardware registers that can only be addressed in
+;; DImode. It's not strictly necessary to test mode == DImode here,
+;; but it makes decent insurance against someone writing a
+;; match_operand wrong.
+
+;; True if this is the ar.lc register.
+(define_predicate "ar_lc_reg_operand"
+ (and (match_code "reg")
+ (match_test "mode == DImode && REGNO (op) == AR_LC_REGNUM")))
+
+;; True if this is the ar.ccv register.
+(define_predicate "ar_ccv_reg_operand"
+ (and (match_code "reg")
+ (match_test "mode == DImode && REGNO (op) == AR_CCV_REGNUM")))
+
+;; True if this is the ar.pfs register.
+(define_predicate "ar_pfs_reg_operand"
+ (and (match_code "reg")
+ (match_test "mode == DImode && REGNO (op) == AR_PFS_REGNUM")))
+
+;; True if OP is valid as a base register in a reg + offset address.
+;; ??? 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.
+(define_predicate "basereg_operand"
+ (match_operand 0 "register_operand")
+{
+ return REG_P (op) && REG_POINTER (op);
+})
+
diff --git a/contrib/gcc/config/ia64/quadlib.c b/contrib/gcc/config/ia64/quadlib.c
index cc367ea..e4bff78 100644
--- a/contrib/gcc/config/ia64/quadlib.c
+++ b/contrib/gcc/config/ia64/quadlib.c
@@ -24,8 +24,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
extern int _U_Qfcmp (long double a, long double b, int);
diff --git a/contrib/gcc/config/ia64/sync.md b/contrib/gcc/config/ia64/sync.md
new file mode 100644
index 0000000..43ad28b
--- /dev/null
+++ b/contrib/gcc/config/ia64/sync.md
@@ -0,0 +1,178 @@
+;; GCC machine description for IA-64 synchronization instructions.
+;; Copyright (C) 2005
+;; Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+(define_mode_macro IMODE [QI HI SI DI])
+(define_mode_macro I124MODE [QI HI SI])
+(define_mode_macro I48MODE [SI DI])
+(define_mode_attr modesuffix [(QI "1") (HI "2") (SI "4") (DI "8")])
+
+(define_code_macro FETCHOP [plus minus ior xor and])
+(define_code_attr fetchop_name
+ [(plus "add") (minus "sub") (ior "ior") (xor "xor") (and "and")])
+
+(define_insn "memory_barrier"
+ [(set (mem:BLK (match_scratch:DI 0 "X"))
+ (unspec:BLK [(mem:BLK (match_scratch:DI 1 "X"))] UNSPEC_MF))]
+ ""
+ "mf"
+ [(set_attr "itanium_class" "syst_m")])
+
+(define_insn "fetchadd_acq_<mode>"
+ [(set (match_operand:I48MODE 0 "gr_register_operand" "=r")
+ (match_operand:I48MODE 1 "not_postinc_memory_operand" "+S"))
+ (set (match_dup 1)
+ (unspec:I48MODE [(match_dup 1)
+ (match_operand:I48MODE 2 "fetchadd_operand" "n")]
+ UNSPEC_FETCHADD_ACQ))]
+ ""
+ "fetchadd<modesuffix>.acq %0 = %1, %2"
+ [(set_attr "itanium_class" "sem")])
+
+(define_expand "sync_<fetchop_name><mode>"
+ [(set (match_operand:IMODE 0 "memory_operand" "")
+ (FETCHOP:IMODE (match_dup 0)
+ (match_operand:IMODE 1 "general_operand" "")))]
+ ""
+{
+ ia64_expand_atomic_op (<CODE>, operands[0], operands[1], NULL, NULL);
+ DONE;
+})
+
+(define_expand "sync_nand<mode>"
+ [(set (match_operand:IMODE 0 "memory_operand" "")
+ (and:IMODE (not:IMODE (match_dup 0))
+ (match_operand:IMODE 1 "general_operand" "")))]
+ ""
+{
+ ia64_expand_atomic_op (NOT, operands[0], operands[1], NULL, NULL);
+ DONE;
+})
+
+(define_expand "sync_old_<fetchop_name><mode>"
+ [(set (match_operand:IMODE 0 "gr_register_operand" "")
+ (FETCHOP:IMODE
+ (match_operand:IMODE 1 "memory_operand" "")
+ (match_operand:IMODE 2 "general_operand" "")))]
+ ""
+{
+ ia64_expand_atomic_op (<CODE>, operands[1], operands[2], operands[0], NULL);
+ DONE;
+})
+
+(define_expand "sync_old_nand<mode>"
+ [(set (match_operand:IMODE 0 "gr_register_operand" "")
+ (and:IMODE
+ (not:IMODE (match_operand:IMODE 1 "memory_operand" ""))
+ (match_operand:IMODE 2 "general_operand" "")))]
+ ""
+{
+ ia64_expand_atomic_op (NOT, operands[1], operands[2], operands[0], NULL);
+ DONE;
+})
+
+(define_expand "sync_new_<fetchop_name><mode>"
+ [(set (match_operand:IMODE 0 "gr_register_operand" "")
+ (FETCHOP:IMODE
+ (match_operand:IMODE 1 "memory_operand" "")
+ (match_operand:IMODE 2 "general_operand" "")))]
+ ""
+{
+ ia64_expand_atomic_op (<CODE>, operands[1], operands[2], NULL, operands[0]);
+ DONE;
+})
+
+(define_expand "sync_new_nand<mode>"
+ [(set (match_operand:IMODE 0 "gr_register_operand" "")
+ (and:IMODE
+ (not:IMODE (match_operand:IMODE 1 "memory_operand" ""))
+ (match_operand:IMODE 2 "general_operand" "")))]
+ ""
+{
+ ia64_expand_atomic_op (NOT, operands[1], operands[2], NULL, operands[0]);
+ DONE;
+})
+
+(define_expand "sync_compare_and_swap<mode>"
+ [(match_operand:IMODE 0 "gr_register_operand" "")
+ (match_operand:IMODE 1 "memory_operand" "")
+ (match_operand:IMODE 2 "gr_register_operand" "")
+ (match_operand:IMODE 3 "gr_register_operand" "")]
+ ""
+{
+ rtx ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
+ rtx dst;
+
+ convert_move (ccv, operands[2], 1);
+
+ dst = operands[0];
+ if (GET_MODE (dst) != DImode)
+ dst = gen_reg_rtx (DImode);
+
+ emit_insn (gen_memory_barrier ());
+ emit_insn (gen_cmpxchg_rel_<mode> (dst, operands[1], ccv, operands[3]));
+
+ if (dst != operands[0])
+ emit_move_insn (operands[0], gen_lowpart (<MODE>mode, dst));
+ DONE;
+})
+
+(define_insn "cmpxchg_rel_<mode>"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (zero_extend:DI
+ (match_operand:I124MODE 1 "not_postinc_memory_operand" "+S")))
+ (set (match_dup 1)
+ (unspec:I124MODE
+ [(match_dup 1)
+ (match_operand:DI 2 "ar_ccv_reg_operand" "")
+ (match_operand:I124MODE 3 "gr_register_operand" "r")]
+ UNSPEC_CMPXCHG_ACQ))]
+ ""
+ "cmpxchg<modesuffix>.rel %0 = %1, %3, %2"
+ [(set_attr "itanium_class" "sem")])
+
+(define_insn "cmpxchg_rel_di"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (match_operand:DI 1 "not_postinc_memory_operand" "+S"))
+ (set (match_dup 1)
+ (unspec:DI [(match_dup 1)
+ (match_operand:DI 2 "ar_ccv_reg_operand" "")
+ (match_operand:DI 3 "gr_register_operand" "r")]
+ UNSPEC_CMPXCHG_ACQ))]
+ ""
+ "cmpxchg8.rel %0 = %1, %3, %2"
+ [(set_attr "itanium_class" "sem")])
+
+(define_insn "sync_lock_test_and_set<mode>"
+ [(set (match_operand:IMODE 0 "gr_register_operand" "=r")
+ (match_operand:IMODE 1 "not_postinc_memory_operand" "+S"))
+ (set (match_dup 1)
+ (match_operand:IMODE 2 "gr_register_operand" "r"))]
+ ""
+ "xchg<modesuffix> %0 = %1, %2"
+ [(set_attr "itanium_class" "sem")])
+
+(define_expand "sync_lock_release<mode>"
+ [(set (match_operand:IMODE 0 "memory_operand" "")
+ (match_operand:IMODE 1 "gr_reg_or_0_operand" ""))]
+ ""
+{
+ gcc_assert (MEM_VOLATILE_P (operands[0]));
+})
diff --git a/contrib/gcc/config/ia64/sysv4.h b/contrib/gcc/config/ia64/sysv4.h
index 15a57d9..795b6ea 100644
--- a/contrib/gcc/config/ia64/sysv4.h
+++ b/contrib/gcc/config/ia64/sysv4.h
@@ -1,5 +1,8 @@
/* Override definitions in elfos.h/svr4.h to be correct for IA64. */
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS ia64_sysv4_init_libfuncs
+
/* We want DWARF2 as specified by the IA64 ABI. */
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
@@ -43,9 +46,9 @@ extern int size_directive_output;
#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
do { \
if ((DECL) && sdata_symbolic_operand (XEXP (DECL_RTL (DECL), 0), Pmode)) \
- sbss_section (); \
+ switch_to_section (sbss_section); \
else \
- bss_section (); \
+ switch_to_section (bss_section); \
ASM_OUTPUT_ALIGN (FILE, floor_log2 ((ALIGN) / BITS_PER_UNIT)); \
ASM_DECLARE_OBJECT_NAME (FILE, NAME, DECL); \
ASM_OUTPUT_SKIP (FILE, SIZE ? SIZE : 1); \
@@ -118,39 +121,10 @@ do { \
} while (0)
/* Override default elf definition. */
+#undef TARGET_ASM_RELOC_RW_MASK
+#define TARGET_ASM_RELOC_RW_MASK ia64_reloc_rw_mask
#undef TARGET_ASM_SELECT_RTX_SECTION
#define TARGET_ASM_SELECT_RTX_SECTION ia64_select_rtx_section
-#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_sdata, in_sbss
-
-#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
- SDATA_SECTION_FUNCTION \
- SBSS_SECTION_FUNCTION
-
#define SDATA_SECTION_ASM_OP "\t.sdata"
-
-#define SDATA_SECTION_FUNCTION \
-void \
-sdata_section (void) \
-{ \
- if (in_section != in_sdata) \
- { \
- fprintf (asm_out_file, "%s\n", SDATA_SECTION_ASM_OP); \
- in_section = in_sdata; \
- } \
-}
-
#define SBSS_SECTION_ASM_OP "\t.sbss"
-
-#define SBSS_SECTION_FUNCTION \
-void \
-sbss_section (void) \
-{ \
- if (in_section != in_sbss) \
- { \
- fprintf (asm_out_file, "%s\n", SBSS_SECTION_ASM_OP); \
- in_section = in_sbss; \
- } \
-}
diff --git a/contrib/gcc/config/ia64/t-hpux b/contrib/gcc/config/ia64/t-hpux
index d89f174..b925c73 100644
--- a/contrib/gcc/config/ia64/t-hpux
+++ b/contrib/gcc/config/ia64/t-hpux
@@ -7,9 +7,15 @@ MULTILIB_OPTIONS = milp32/mlp64
MULTILIB_DIRNAMES = hpux32 hpux64
MULTILIB_MATCHES =
+# On HP-UX we do not want _fixtfdi, _fixunstfdi, or _floatditf from
+# LIB1ASMSRC. These functions map the 128 bit conversion function names
+# to 80 bit conversions and were done for Linux backwards compatibility.
+
+LIB1ASMFUNCS := $(filter-out _fixtfdi _fixunstfdi _floatditf,$(LIB1ASMFUNCS))
+
# Support routines for HP-UX 128 bit floats.
-LIB2FUNCS_EXTRA=quadlib.c
+LIB2FUNCS_EXTRA=quadlib.c $(srcdir)/config/floatunsitf.c
quadlib.c: $(srcdir)/config/ia64/quadlib.c
cat $(srcdir)/config/ia64/quadlib.c > quadlib.c
@@ -32,14 +38,19 @@ SHLIB_EXT = .so
# DT_NEEDED entry for libunwind.
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@ -lunwind -lc && \
- rm -f @shlib_base_name@.so.0 && \
- $(LN_S) @shlib_base_name@.so @shlib_base_name@.so.0
+ -o @multilib_dir@/@shlib_base_name@.so @multilib_flags@ \
+ @shlib_objs@ -lunwind -lc && \
+ rm -f @multilib_dir@/@shlib_base_name@.so.0 && \
+ $(LN_S) @shlib_base_name@.so @multilib_dir@/@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_INSTALL = \
+ $$(mkinstalldirs) $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@; \
+ $(INSTALL_DATA) @multilib_dir@/@shlib_base_name@.so \
+ $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so.0; \
+ rm -f $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so; \
+ $(LN_S) @shlib_base_name@.so.0 \
+ $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so; \
+ chmod +x $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@/@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 21d37a7..6053588 100644
--- a/contrib/gcc/config/ia64/t-ia64
+++ b/contrib/gcc/config/ia64/t-ia64
@@ -8,7 +8,8 @@ LIB1ASMSRC = ia64/lib1funcs.asm
LIB1ASMFUNCS = __divxf3 __divdf3 __divsf3 \
__divdi3 __moddi3 __udivdi3 __umoddi3 \
__divsi3 __modsi3 __udivsi3 __umodsi3 __save_stack_nonlocal \
- __nonlocal_goto __restore_stack_nonlocal __trampoline __compat
+ __nonlocal_goto __restore_stack_nonlocal __trampoline \
+ _fixtfdi _fixunstfdi _floatditf
# ??? Hack to get -P option used when compiling lib1funcs.asm, because Intel
# assembler does not accept # line number as a comment.
@@ -41,7 +42,7 @@ crtfastmath.o: $(srcdir)/config/ia64/crtfastmath.c $(GCC_PASSES)
$(srcdir)/config/ia64/crtfastmath.c
LIB2ADDEH = $(srcdir)/config/ia64/unwind-ia64.c $(srcdir)/unwind-sjlj.c \
- $(srcdir)/unwind-c.c $(srcdir)/gthr-gnat.c
+ $(srcdir)/unwind-c.c
ia64-c.o: $(srcdir)/config/ia64/ia64-c.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(TREE_H) $(CPPLIB_H) $(C_COMMON_H) c-pragma.h toplev.h
@@ -49,3 +50,5 @@ ia64-c.o: $(srcdir)/config/ia64/ia64-c.c $(CONFIG_H) $(SYSTEM_H) \
# genattrtab generates very long string literals.
insn-attrtab.o-warn = -Wno-error
+
+ia64.o: debug.h $(PARAMS_H)
diff --git a/contrib/gcc/config/ia64/unwind-ia64.c b/contrib/gcc/config/ia64/unwind-ia64.c
index a49652e..fc7b207 100644
--- a/contrib/gcc/config/ia64/unwind-ia64.c
+++ b/contrib/gcc/config/ia64/unwind-ia64.c
@@ -1,6 +1,6 @@
/* Subroutines needed for unwinding IA-64 standard format stack frame
info for exception handling.
- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006
Free Software Foundation, Inc.
Contributed by Andrew MacLeod <amacleod@cygnus.com>
Andrew Haley <aph@cygnus.com>
@@ -20,8 +20,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* As a special exception, if you link this library with other files,
some of which are compiled with GCC, to produce an executable,
@@ -44,6 +44,7 @@
#undef ENABLE_MALLOC_CHECKING
#ifndef __USING_SJLJ_EXCEPTIONS__
+
#define UNW_VER(x) ((x) >> 48)
#define UNW_FLAG_MASK 0x0000ffff00000000
#define UNW_FLAG_OSMASK 0x0000f00000000000
@@ -284,10 +285,10 @@ atomic_free (unsigned int *mask, int bit)
#define PTR_IN(X, P) ((P) >= (X) && (P) < (X) + SIZE (X))
static struct unw_reg_state emergency_reg_state[32];
-static int emergency_reg_state_free = MASK_FOR (emergency_reg_state);
+static unsigned int emergency_reg_state_free = MASK_FOR (emergency_reg_state);
static struct unw_labeled_state emergency_labeled_state[8];
-static int emergency_labeled_state_free = MASK_FOR (emergency_labeled_state);
+static unsigned int emergency_labeled_state_free = MASK_FOR (emergency_labeled_state);
#ifdef ENABLE_MALLOC_CHECKING
static int reg_state_alloced;
@@ -1703,6 +1704,13 @@ _Unwind_GetIP (struct _Unwind_Context *context)
return context->rp;
}
+inline _Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+ *ip_before_insn = 0;
+ return context->rp;
+}
+
/* Overwrite the return address for CONTEXT with VAL. */
inline void
@@ -1754,6 +1762,9 @@ _Unwind_GetBSP (struct _Unwind_Context *context)
return (_Unwind_Ptr) context->bsp;
}
+#ifdef MD_UNWIND_SUPPORT
+#include MD_UNWIND_SUPPORT
+#endif
static _Unwind_Reason_Code
uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
@@ -1777,7 +1788,8 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
os-specific fallback mechanism. This will necessarily
not provide a personality routine or LSDA. */
#ifdef MD_FALLBACK_FRAME_STATE_FOR
- MD_FALLBACK_FRAME_STATE_FOR (context, fs, success);
+ if (MD_FALLBACK_FRAME_STATE_FOR (context, fs) == _URC_NO_REASON)
+ return _URC_NO_REASON;
/* [SCRA 11.4.1] A leaf function with no memory stack, no exception
handlers, and which keeps the return value in B0 does not need
@@ -1792,15 +1804,10 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
fs->curr.reg[UNW_REG_RP].when = -1;
fs->curr.reg[UNW_REG_RP].val = 0;
- goto success;
+ return _URC_NO_REASON;
}
-
- return _URC_END_OF_STACK;
- success:
- return _URC_NO_REASON;
-#else
- return _URC_END_OF_STACK;
#endif
+ return _URC_END_OF_STACK;
}
context->region_start = ent->start_offset + segment_base;
@@ -2060,6 +2067,12 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
}
}
+static void
+uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+ uw_update_context (context, fs);
+}
+
/* Fill in CONTEXT for top-of-stack. The only valid registers at this
level will be the return address and the CFA. Note that CFA = SP+16. */
@@ -2111,7 +2124,7 @@ uw_init_context_1 (struct _Unwind_Context *context, void *bsp)
uw_update_context (context, &fs);
}
-/* Install (ie longjmp to) the contents of TARGET. */
+/* Install (i.e. longjmp to) the contents of TARGET. */
static void __attribute__((noreturn))
uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
@@ -2389,7 +2402,6 @@ uw_identify_context (struct _Unwind_Context *context)
alias (_Unwind_Backtrace);
alias (_Unwind_DeleteException);
alias (_Unwind_FindEnclosingFunction);
-alias (_Unwind_FindTableEntry);
alias (_Unwind_ForcedUnwind);
alias (_Unwind_GetBSP);
alias (_Unwind_GetCFA);
diff --git a/contrib/gcc/config/ia64/unwind-ia64.h b/contrib/gcc/config/ia64/unwind-ia64.h
index 053829f..09b4a98 100644
--- a/contrib/gcc/config/ia64/unwind-ia64.h
+++ b/contrib/gcc/config/ia64/unwind-ia64.h
@@ -16,8 +16,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
struct unw_table_entry
{
diff --git a/contrib/gcc/config/ia64/vect.md b/contrib/gcc/config/ia64/vect.md
new file mode 100644
index 0000000..94380bf
--- /dev/null
+++ b/contrib/gcc/config/ia64/vect.md
@@ -0,0 +1,1304 @@
+;; IA-64 machine description for vector operations.
+;; Copyright (C) 2004, 2005
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+
+;; Integer vector operations
+
+(define_mode_macro VECINT [V8QI V4HI V2SI])
+(define_mode_macro VECINT12 [V8QI V4HI])
+(define_mode_macro VECINT24 [V4HI V2SI])
+(define_mode_attr vecsize [(V8QI "1") (V4HI "2") (V2SI "4")])
+
+(define_expand "mov<mode>"
+ [(set (match_operand:VECINT 0 "general_operand" "")
+ (match_operand:VECINT 1 "general_operand" ""))]
+ ""
+{
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
+
+(define_insn "*mov<mode>_internal"
+ [(set (match_operand:VECINT 0 "destination_operand"
+ "=r,r,r,r,m ,*f ,*f,Q ,r ,*f")
+ (match_operand:VECINT 1 "move_operand"
+ "rU,W,i,m,rU,U*f,Q ,*f,*f,r "))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "@
+ mov %0 = %r1
+ addl %0 = %v1, r0
+ movl %0 = %v1
+ ld8%O1 %0 = %1%P1
+ st8%Q0 %0 = %r1%P0
+ mov %0 = %F1
+ ldf8 %0 = %1%P1
+ stf8 %0 = %1%P0
+ getf.sig %0 = %1
+ setf.sig %0 = %1"
+ [(set_attr "itanium_class" "ialu,ialu,long_i,ld,st,fmisc,fld,stf,frfr,tofr")])
+
+(define_insn "one_cmpl<mode>2"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "=r")
+ (not:VECINT (match_operand:VECINT 1 "gr_register_operand" "r")))]
+ ""
+ "andcm %0 = -1, %1"
+ [(set_attr "itanium_class" "ilog")])
+
+(define_insn "and<mode>3"
+ [(set (match_operand:VECINT 0 "grfr_register_operand" "=r,*f")
+ (and:VECINT
+ (match_operand:VECINT 1 "grfr_register_operand" "r,*f")
+ (match_operand:VECINT 2 "grfr_reg_or_8bit_operand" "r,*f")))]
+ ""
+ "@
+ and %0 = %2, %1
+ fand %0 = %2, %1"
+ [(set_attr "itanium_class" "ilog,fmisc")])
+
+(define_insn "*andnot<mode>"
+ [(set (match_operand:VECINT 0 "grfr_register_operand" "=r,*f")
+ (and:VECINT
+ (not:VECINT (match_operand:VECINT 1 "grfr_register_operand" "r,*f"))
+ (match_operand:VECINT 2 "grfr_reg_or_8bit_operand" "r,*f")))]
+ ""
+ "@
+ andcm %0 = %2, %1
+ fandcm %0 = %2, %1"
+ [(set_attr "itanium_class" "ilog,fmisc")])
+
+(define_insn "ior<mode>3"
+ [(set (match_operand:VECINT 0 "grfr_register_operand" "=r,*f")
+ (ior:VECINT
+ (match_operand:VECINT 1 "grfr_register_operand" "r,*f")
+ (match_operand:VECINT 2 "grfr_reg_or_8bit_operand" "r,*f")))]
+ ""
+ "@
+ or %0 = %2, %1
+ for %0 = %2, %1"
+ [(set_attr "itanium_class" "ilog,fmisc")])
+
+(define_insn "xor<mode>3"
+ [(set (match_operand:VECINT 0 "grfr_register_operand" "=r,*f")
+ (xor:VECINT
+ (match_operand:VECINT 1 "grfr_register_operand" "r,*f")
+ (match_operand:VECINT 2 "grfr_reg_or_8bit_operand" "r,*f")))]
+ ""
+ "@
+ xor %0 = %2, %1
+ fxor %0 = %2, %1"
+ [(set_attr "itanium_class" "ilog,fmisc")])
+
+(define_insn "neg<mode>2"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "=r")
+ (neg:VECINT (match_operand:VECINT 1 "gr_register_operand" "r")))]
+ ""
+ "psub<vecsize> %0 = r0, %1"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_insn "add<mode>3"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "=r")
+ (plus:VECINT (match_operand:VECINT 1 "gr_register_operand" "r")
+ (match_operand:VECINT 2 "gr_register_operand" "r")))]
+ ""
+ "padd<vecsize> %0 = %1, %2"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_insn "*ssadd<mode>3"
+ [(set (match_operand:VECINT12 0 "gr_register_operand" "=r")
+ (ss_plus:VECINT12
+ (match_operand:VECINT12 1 "gr_register_operand" "r")
+ (match_operand:VECINT12 2 "gr_register_operand" "r")))]
+ ""
+ "padd<vecsize>.sss %0 = %1, %2"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_insn "*usadd<mode>3"
+ [(set (match_operand:VECINT12 0 "gr_register_operand" "=r")
+ (us_plus:VECINT12
+ (match_operand:VECINT12 1 "gr_register_operand" "r")
+ (match_operand:VECINT12 2 "gr_register_operand" "r")))]
+ ""
+ "padd<vecsize>.uuu %0 = %1, %2"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_insn "sub<mode>3"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "=r")
+ (minus:VECINT (match_operand:VECINT 1 "gr_register_operand" "r")
+ (match_operand:VECINT 2 "gr_register_operand" "r")))]
+ ""
+ "psub<vecsize> %0 = %1, %2"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_insn "*sssub<mode>3"
+ [(set (match_operand:VECINT12 0 "gr_register_operand" "=r")
+ (ss_minus:VECINT12
+ (match_operand:VECINT12 1 "gr_register_operand" "r")
+ (match_operand:VECINT12 2 "gr_register_operand" "r")))]
+ ""
+ "psub<vecsize>.sss %0 = %1, %2"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_insn "*ussub<mode>3"
+ [(set (match_operand:VECINT12 0 "gr_register_operand" "=r")
+ (us_minus:VECINT12
+ (match_operand:VECINT12 1 "gr_register_operand" "r")
+ (match_operand:VECINT12 2 "gr_register_operand" "r")))]
+ ""
+ "psub<vecsize>.uuu %0 = %1, %2"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_expand "mulv8qi3"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "")
+ (mult:V8QI (match_operand:V8QI 1 "gr_register_operand" "r")
+ (match_operand:V8QI 2 "gr_register_operand" "r")))]
+ ""
+{
+ rtx r1, l1, r2, l2, rm, lm;
+
+ r1 = gen_reg_rtx (V4HImode);
+ l1 = gen_reg_rtx (V4HImode);
+ r2 = gen_reg_rtx (V4HImode);
+ l2 = gen_reg_rtx (V4HImode);
+
+ /* Zero-extend the QImode elements into two words of HImode elements
+ by interleaving them with zero bytes. */
+ emit_insn (gen_mix1_r (gen_lowpart (V8QImode, r1),
+ operands[1], CONST0_RTX (V8QImode)));
+ emit_insn (gen_mix1_r (gen_lowpart (V8QImode, r2),
+ operands[2], CONST0_RTX (V8QImode)));
+ emit_insn (gen_mix1_l (gen_lowpart (V8QImode, l1),
+ operands[1], CONST0_RTX (V8QImode)));
+ emit_insn (gen_mix1_l (gen_lowpart (V8QImode, l2),
+ operands[2], CONST0_RTX (V8QImode)));
+
+ /* Multiply. */
+ rm = gen_reg_rtx (V4HImode);
+ lm = gen_reg_rtx (V4HImode);
+ emit_insn (gen_mulv4hi3 (rm, r1, r2));
+ emit_insn (gen_mulv4hi3 (lm, l1, l2));
+
+ /* Zap the high order bytes of the HImode elements by overwriting those
+ in one part with the low order bytes of the other. */
+ emit_insn (gen_mix1_r (operands[0],
+ gen_lowpart (V8QImode, rm),
+ gen_lowpart (V8QImode, lm)));
+ DONE;
+})
+
+(define_insn "mulv4hi3"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (mult:V4HI (match_operand:V4HI 1 "gr_register_operand" "r")
+ (match_operand:V4HI 2 "gr_register_operand" "r")))]
+ ""
+ "pmpyshr2 %0 = %1, %2, 0"
+ [(set_attr "itanium_class" "mmmul")])
+
+(define_insn "pmpy2_r"
+ [(set (match_operand:V2SI 0 "gr_register_operand" "=r")
+ (mult:V2SI
+ (vec_select:V2SI
+ (sign_extend:V4SI
+ (match_operand:V4HI 1 "gr_register_operand" "r"))
+ (parallel [(const_int 0) (const_int 2)]))
+ (vec_select:V2SI
+ (sign_extend:V4SI
+ (match_operand:V4HI 2 "gr_register_operand" "r"))
+ (parallel [(const_int 0) (const_int 2)]))))]
+ ""
+ "pmpy2.r %0 = %1, %2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "pmpy2_l"
+ [(set (match_operand:V2SI 0 "gr_register_operand" "=r")
+ (mult:V2SI
+ (vec_select:V2SI
+ (sign_extend:V4SI
+ (match_operand:V4HI 1 "gr_register_operand" "r"))
+ (parallel [(const_int 1) (const_int 3)]))
+ (vec_select:V2SI
+ (sign_extend:V4SI
+ (match_operand:V4HI 2 "gr_register_operand" "r"))
+ (parallel [(const_int 1) (const_int 3)]))))]
+ ""
+ "pmpy2.l %0 = %1, %2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_expand "umax<mode>3"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "")
+ (umax:VECINT (match_operand:VECINT 1 "gr_register_operand" "")
+ (match_operand:VECINT 2 "gr_register_operand" "")))]
+ ""
+{
+ if (ia64_expand_vecint_minmax (UMAX, <MODE>mode, operands))
+ DONE;
+})
+
+(define_expand "smax<mode>3"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "")
+ (smax:VECINT (match_operand:VECINT 1 "gr_reg_or_0_operand" "")
+ (match_operand:VECINT 2 "gr_reg_or_0_operand" "")))]
+ ""
+{
+ if (ia64_expand_vecint_minmax (SMAX, <MODE>mode, operands))
+ DONE;
+})
+
+(define_expand "umin<mode>3"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "")
+ (umin:VECINT (match_operand:VECINT 1 "gr_register_operand" "")
+ (match_operand:VECINT 2 "gr_register_operand" "")))]
+ ""
+{
+ if (ia64_expand_vecint_minmax (UMIN, <MODE>mode, operands))
+ DONE;
+})
+
+(define_expand "smin<mode>3"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "")
+ (smin:VECINT (match_operand:VECINT 1 "gr_reg_or_0_operand" "")
+ (match_operand:VECINT 2 "gr_reg_or_0_operand" "")))]
+ ""
+{
+ if (ia64_expand_vecint_minmax (SMIN, <MODE>mode, operands))
+ DONE;
+})
+
+(define_insn "*umaxv8qi3"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (umax:V8QI (match_operand:V8QI 1 "gr_register_operand" "r")
+ (match_operand:V8QI 2 "gr_register_operand" "r")))]
+ ""
+ "pmax1.u %0 = %1, %2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*smaxv4hi3"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (smax:V4HI (match_operand:V4HI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V4HI 2 "gr_reg_or_0_operand" "rU")))]
+ ""
+ "pmax2 %0 = %r1, %r2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*uminv8qi3"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (umin:V8QI (match_operand:V8QI 1 "gr_register_operand" "r")
+ (match_operand:V8QI 2 "gr_register_operand" "r")))]
+ ""
+ "pmin1.u %0 = %1, %2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*sminv4hi3"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (smin:V4HI (match_operand:V4HI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V4HI 2 "gr_reg_or_0_operand" "rU")))]
+ ""
+ "pmin2 %0 = %r1, %r2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "ashl<mode>3"
+ [(set (match_operand:VECINT24 0 "gr_register_operand" "=r")
+ (ashift:VECINT24
+ (match_operand:VECINT24 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "gr_reg_or_5bit_operand" "rn")))]
+ ""
+ "pshl<vecsize> %0 = %1, %2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "ashr<mode>3"
+ [(set (match_operand:VECINT24 0 "gr_register_operand" "=r")
+ (ashiftrt:VECINT24
+ (match_operand:VECINT24 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "gr_reg_or_5bit_operand" "rn")))]
+ ""
+ "pshr<vecsize> %0 = %1, %2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "lshr<mode>3"
+ [(set (match_operand:VECINT24 0 "gr_register_operand" "=r")
+ (lshiftrt:VECINT24
+ (match_operand:VECINT24 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "gr_reg_or_5bit_operand" "rn")))]
+ ""
+ "pshr<vecsize>.u %0 = %1, %2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_expand "vec_shl_<mode>"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "")
+ (ashift:DI (match_operand:VECINT 1 "gr_register_operand" "")
+ (match_operand:DI 2 "gr_reg_or_6bit_operand" "")))]
+ ""
+{
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[1] = gen_lowpart (DImode, operands[1]);
+})
+
+(define_expand "vec_shr_<mode>"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "")
+ (lshiftrt:DI (match_operand:VECINT 1 "gr_register_operand" "")
+ (match_operand:DI 2 "gr_reg_or_6bit_operand" "")))]
+ ""
+{
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[1] = gen_lowpart (DImode, operands[1]);
+})
+
+(define_expand "widen_usumv8qi3"
+ [(match_operand:V4HI 0 "gr_register_operand" "")
+ (match_operand:V8QI 1 "gr_register_operand" "")
+ (match_operand:V4HI 2 "gr_register_operand" "")]
+ ""
+{
+ ia64_expand_widen_sum (operands, true);
+ DONE;
+})
+
+(define_expand "widen_usumv4hi3"
+ [(match_operand:V2SI 0 "gr_register_operand" "")
+ (match_operand:V4HI 1 "gr_register_operand" "")
+ (match_operand:V2SI 2 "gr_register_operand" "")]
+ ""
+{
+ ia64_expand_widen_sum (operands, true);
+ DONE;
+})
+
+(define_expand "widen_ssumv8qi3"
+ [(match_operand:V4HI 0 "gr_register_operand" "")
+ (match_operand:V8QI 1 "gr_register_operand" "")
+ (match_operand:V4HI 2 "gr_register_operand" "")]
+ ""
+{
+ ia64_expand_widen_sum (operands, false);
+ DONE;
+})
+
+(define_expand "widen_ssumv4hi3"
+ [(match_operand:V2SI 0 "gr_register_operand" "")
+ (match_operand:V4HI 1 "gr_register_operand" "")
+ (match_operand:V2SI 2 "gr_register_operand" "")]
+ ""
+{
+ ia64_expand_widen_sum (operands, false);
+ DONE;
+})
+
+(define_expand "udot_prodv8qi"
+ [(match_operand:V2SI 0 "gr_register_operand" "")
+ (match_operand:V8QI 1 "gr_register_operand" "")
+ (match_operand:V8QI 2 "gr_register_operand" "")
+ (match_operand:V2SI 3 "gr_register_operand" "")]
+ ""
+{
+ ia64_expand_dot_prod_v8qi (operands, true);
+ DONE;
+})
+
+(define_expand "sdot_prodv8qi"
+ [(match_operand:V2SI 0 "gr_register_operand" "")
+ (match_operand:V8QI 1 "gr_register_operand" "")
+ (match_operand:V8QI 2 "gr_register_operand" "")
+ (match_operand:V2SI 3 "gr_register_operand" "")]
+ ""
+{
+ ia64_expand_dot_prod_v8qi (operands, false);
+ DONE;
+})
+
+(define_expand "sdot_prodv4hi"
+ [(match_operand:V2SI 0 "gr_register_operand" "")
+ (match_operand:V4HI 1 "gr_register_operand" "")
+ (match_operand:V4HI 2 "gr_register_operand" "")
+ (match_operand:V2SI 3 "gr_register_operand" "")]
+ ""
+{
+ rtx l, r, t;
+
+ r = gen_reg_rtx (V2SImode);
+ l = gen_reg_rtx (V2SImode);
+ t = gen_reg_rtx (V2SImode);
+
+ emit_insn (gen_pmpy2_r (r, operands[1], operands[2]));
+ emit_insn (gen_pmpy2_l (l, operands[1], operands[2]));
+ emit_insn (gen_addv2si3 (t, r, operands[3]));
+ emit_insn (gen_addv2si3 (operands[0], t, l));
+ DONE;
+})
+
+(define_expand "vcond<mode>"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "")
+ (if_then_else:VECINT
+ (match_operator 3 ""
+ [(match_operand:VECINT 4 "gr_reg_or_0_operand" "")
+ (match_operand:VECINT 5 "gr_reg_or_0_operand" "")])
+ (match_operand:VECINT 1 "gr_reg_or_0_operand" "")
+ (match_operand:VECINT 2 "gr_reg_or_0_operand" "")))]
+ ""
+{
+ ia64_expand_vecint_cmov (operands);
+ DONE;
+})
+
+(define_expand "vcondu<mode>"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "")
+ (if_then_else:VECINT
+ (match_operator 3 ""
+ [(match_operand:VECINT 4 "gr_reg_or_0_operand" "")
+ (match_operand:VECINT 5 "gr_reg_or_0_operand" "")])
+ (match_operand:VECINT 1 "gr_reg_or_0_operand" "")
+ (match_operand:VECINT 2 "gr_reg_or_0_operand" "")))]
+ ""
+{
+ ia64_expand_vecint_cmov (operands);
+ DONE;
+})
+
+(define_insn "*cmpeq_<mode>"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "=r")
+ (eq:VECINT (match_operand:VECINT 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:VECINT 2 "gr_reg_or_0_operand" "rU")))]
+ ""
+ "pcmp<vecsize>.eq %0 = %r1, %r2"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_insn "*cmpgt_<mode>"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "=r")
+ (gt:VECINT (match_operand:VECINT 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:VECINT 2 "gr_reg_or_0_operand" "rU")))]
+ ""
+ "pcmp<vecsize>.gt %0 = %r1, %r2"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_insn "pack2_sss"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_concat:V8QI
+ (ss_truncate:V4QI
+ (match_operand:V4HI 1 "gr_reg_or_0_operand" "rU"))
+ (ss_truncate:V4QI
+ (match_operand:V4HI 2 "gr_reg_or_0_operand" "rU"))))]
+ ""
+ "pack2.sss %0 = %r1, %r2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*pack2_uss"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_concat:V8QI
+ (us_truncate:V4QI
+ (match_operand:V4HI 1 "gr_reg_or_0_operand" "rU"))
+ (us_truncate:V4QI
+ (match_operand:V4HI 2 "gr_reg_or_0_operand" "rU"))))]
+ ""
+ "pack2.uss %0 = %r1, %r2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "pack4_sss"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (vec_concat:V4HI
+ (ss_truncate:V2HI
+ (match_operand:V2SI 1 "gr_reg_or_0_operand" "rU"))
+ (ss_truncate:V2HI
+ (match_operand:V2SI 2 "gr_reg_or_0_operand" "rU"))))]
+ ""
+ "pack4.sss %0 = %r1, %r2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "unpack1_l"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (vec_concat:V16QI
+ (match_operand:V8QI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V8QI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 0)
+ (const_int 1)
+ (const_int 2)
+ (const_int 3)
+ (const_int 8)
+ (const_int 9)
+ (const_int 10)
+ (const_int 11)])))]
+ ""
+ "unpack1.l %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "unpack1_h"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (vec_concat:V16QI
+ (match_operand:V8QI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V8QI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 4)
+ (const_int 5)
+ (const_int 6)
+ (const_int 7)
+ (const_int 12)
+ (const_int 13)
+ (const_int 14)
+ (const_int 15)])))]
+ ""
+ "unpack1.h %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "mix1_r"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (vec_concat:V16QI
+ (match_operand:V8QI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V8QI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 0)
+ (const_int 8)
+ (const_int 2)
+ (const_int 10)
+ (const_int 4)
+ (const_int 12)
+ (const_int 6)
+ (const_int 14)])))]
+ ""
+ "mix1.r %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "mix1_l"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (vec_concat:V16QI
+ (match_operand:V8QI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V8QI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 1)
+ (const_int 9)
+ (const_int 3)
+ (const_int 11)
+ (const_int 5)
+ (const_int 13)
+ (const_int 7)
+ (const_int 15)])))]
+ ""
+ "mix1.l %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mux1_rev"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (match_operand:V8QI 1 "gr_register_operand" "r")
+ (parallel [(const_int 7)
+ (const_int 6)
+ (const_int 5)
+ (const_int 4)
+ (const_int 3)
+ (const_int 2)
+ (const_int 1)
+ (const_int 0)])))]
+ ""
+ "mux1 %0 = %1, @rev"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mux1_mix"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (match_operand:V8QI 1 "gr_register_operand" "r")
+ (parallel [(const_int 0)
+ (const_int 4)
+ (const_int 2)
+ (const_int 6)
+ (const_int 1)
+ (const_int 5)
+ (const_int 3)
+ (const_int 7)])))]
+ ""
+ "mux1 %0 = %1, @mix"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mux1_shuf"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (match_operand:V8QI 1 "gr_register_operand" "r")
+ (parallel [(const_int 0)
+ (const_int 4)
+ (const_int 1)
+ (const_int 5)
+ (const_int 2)
+ (const_int 6)
+ (const_int 3)
+ (const_int 7)])))]
+ ""
+ "mux1 %0 = %1, @shuf"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mux1_alt"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (match_operand:V8QI 1 "gr_register_operand" "r")
+ (parallel [(const_int 0)
+ (const_int 2)
+ (const_int 4)
+ (const_int 6)
+ (const_int 1)
+ (const_int 3)
+ (const_int 5)
+ (const_int 7)])))]
+ ""
+ "mux1 %0 = %1, @alt"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mux1_brcst_v8qi"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (match_operand:V8QI 1 "gr_register_operand" "r")
+ (parallel [(const_int 0)
+ (const_int 0)
+ (const_int 0)
+ (const_int 0)
+ (const_int 0)
+ (const_int 0)
+ (const_int 0)
+ (const_int 0)])))]
+ ""
+ "mux1 %0 = %1, @brcst"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mux1_brcst_qi"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_duplicate:V8QI
+ (match_operand:QI 1 "gr_register_operand" "r")))]
+ ""
+ "mux1 %0 = %1, @brcst"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "unpack2_l"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (vec_select:V4HI
+ (vec_concat:V8HI
+ (match_operand:V4HI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V4HI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 0)
+ (const_int 4)
+ (const_int 1)
+ (const_int 5)])))]
+ ""
+ "unpack2.l %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "unpack2_h"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (vec_select:V4HI
+ (vec_concat:V8HI
+ (match_operand:V4HI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V4HI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 2)
+ (const_int 6)
+ (const_int 3)
+ (const_int 7)])))]
+ ""
+ "unpack2.h %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mix2_r"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (vec_select:V4HI
+ (vec_concat:V8HI
+ (match_operand:V4HI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V4HI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 0)
+ (const_int 4)
+ (const_int 2)
+ (const_int 6)])))]
+ ""
+ "mix2.r %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mix2_l"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (vec_select:V4HI
+ (vec_concat:V8HI
+ (match_operand:V4HI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V4HI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 1)
+ (const_int 5)
+ (const_int 3)
+ (const_int 7)])))]
+ ""
+ "mix2.l %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mux2"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (vec_select:V4HI
+ (match_operand:V4HI 1 "gr_register_operand" "r")
+ (parallel [(match_operand 2 "const_int_2bit_operand" "")
+ (match_operand 3 "const_int_2bit_operand" "")
+ (match_operand 4 "const_int_2bit_operand" "")
+ (match_operand 5 "const_int_2bit_operand" "")])))]
+ ""
+{
+ int mask;
+ mask = INTVAL (operands[2]);
+ mask |= INTVAL (operands[3]) << 2;
+ mask |= INTVAL (operands[4]) << 4;
+ mask |= INTVAL (operands[5]) << 6;
+ operands[2] = GEN_INT (mask);
+ return "%,mux2 %0 = %1, %2";
+}
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mux2_brcst_hi"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (vec_duplicate:V4HI
+ (match_operand:HI 1 "gr_register_operand" "r")))]
+ ""
+ "mux2 %0 = %1, 0"
+ [(set_attr "itanium_class" "mmshf")])
+
+;; Note that mix4.r performs the exact same operation.
+(define_insn "*unpack4_l"
+ [(set (match_operand:V2SI 0 "gr_register_operand" "=r")
+ (vec_select:V2SI
+ (vec_concat:V4SI
+ (match_operand:V2SI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V2SI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 0)
+ (const_int 2)])))]
+ ""
+ "unpack4.l %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+;; Note that mix4.l performs the exact same operation.
+(define_insn "*unpack4_h"
+ [(set (match_operand:V2SI 0 "gr_register_operand" "=r")
+ (vec_select:V2SI
+ (vec_concat:V4SI
+ (match_operand:V2SI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V2SI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 1)
+ (const_int 3)])))]
+ ""
+ "unpack4.h %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_expand "vec_initv2si"
+ [(match_operand:V2SI 0 "gr_register_operand" "")
+ (match_operand 1 "" "")]
+ ""
+{
+ rtx op1 = XVECEXP (operands[1], 0, 0);
+ rtx op2 = XVECEXP (operands[1], 0, 1);
+ rtx x;
+
+ if (GET_CODE (op1) == CONST_INT && GET_CODE (op2) == CONST_INT)
+ {
+ rtvec v = rtvec_alloc (2);
+ RTVEC_ELT (v, 0) = TARGET_BIG_ENDIAN ? op2 : op1;
+ RTVEC_ELT (v, 1) = TARGET_BIG_ENDIAN ? op1 : op2;;
+ x = gen_rtx_CONST_VECTOR (V2SImode, v);
+ emit_move_insn (operands[0], x);
+ DONE;
+ }
+
+ if (!gr_reg_or_0_operand (op1, SImode))
+ op1 = force_reg (SImode, op1);
+ if (!gr_reg_or_0_operand (op2, SImode))
+ op2 = force_reg (SImode, op2);
+
+ if (TARGET_BIG_ENDIAN)
+ x = gen_rtx_VEC_CONCAT (V2SImode, op2, op1);
+ else
+ x = gen_rtx_VEC_CONCAT (V2SImode, op1, op2);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ DONE;
+})
+
+(define_insn "*vecinit_v2si"
+ [(set (match_operand:V2SI 0 "gr_register_operand" "=r")
+ (vec_concat:V2SI
+ (match_operand:SI 1 "gr_reg_or_0_operand" "rO")
+ (match_operand:SI 2 "gr_reg_or_0_operand" "rO")))]
+ ""
+ "unpack4.l %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+;; Missing operations
+;; padd.uus
+;; pavg
+;; pavgsub
+;; pmpyshr, general form
+;; psad
+;; pshladd
+;; pshradd
+;; psub.uus
+
+;; Floating point vector operations
+
+(define_expand "movv2sf"
+ [(set (match_operand:V2SF 0 "general_operand" "")
+ (match_operand:V2SF 1 "general_operand" ""))]
+ ""
+{
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
+
+(define_insn "*movv2sf_internal"
+ [(set (match_operand:V2SF 0 "destination_operand"
+ "=f,f,f,Q,*r ,*r,*r,*r,m ,f ,*r")
+ (match_operand:V2SF 1 "move_operand"
+ "fU,Y,Q,f,U*r,W ,i ,m ,*r,*r,f "))]
+ "ia64_move_ok (operands[0], operands[1])"
+{
+ static const char * const alt[] = {
+ "%,mov %0 = %F1",
+ "%,fpack %0 = %F2, %F1",
+ "%,ldf8 %0 = %1%P1",
+ "%,stf8 %0 = %1%P0",
+ "%,mov %0 = %r1",
+ "%,addl %0 = %v1, r0",
+ "%,movl %0 = %v1",
+ "%,ld8%O1 %0 = %1%P1",
+ "%,st8%Q0 %0 = %r1%P0",
+ "%,setf.sig %0 = %1",
+ "%,getf.sig %0 = %1"
+ };
+
+ if (which_alternative == 1)
+ {
+ operands[2] = XVECEXP (operands[1], 0, 1);
+ operands[1] = XVECEXP (operands[1], 0, 0);
+ }
+
+ return alt[which_alternative];
+}
+ [(set_attr "itanium_class" "fmisc,fmisc,fld,stf,ialu,ialu,long_i,ld,st,tofr,frfr")])
+
+(define_insn "absv2sf2"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (abs:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")))]
+ ""
+ "fpabs %0 = %1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "negv2sf2"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (neg:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")))]
+ ""
+ "fpneg %0 = %1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*negabsv2sf2"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (neg:V2SF
+ (abs:V2SF (match_operand:V2SF 1 "fr_register_operand" "f"))))]
+ ""
+ "fpnegabs %0 = %1"
+ [(set_attr "itanium_class" "fmisc")])
+
+;; In order to convince combine to merge plus and mult to a useful fpma,
+;; we need a couple of extra patterns.
+(define_expand "addv2sf3"
+ [(parallel
+ [(set (match_operand:V2SF 0 "fr_register_operand" "")
+ (plus:V2SF (match_operand:V2SF 1 "fr_register_operand" "")
+ (match_operand:V2SF 2 "fr_register_operand" "")))
+ (use (match_dup 3))])]
+ ""
+{
+ rtvec v = gen_rtvec (2, CONST1_RTX (SFmode), CONST1_RTX (SFmode));
+ operands[3] = force_reg (V2SFmode, gen_rtx_CONST_VECTOR (V2SFmode, v));
+})
+
+;; The split condition here could be combine_completed, if we had such.
+(define_insn_and_split "*addv2sf3_1"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (plus:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f")))
+ (use (match_operand:V2SF 3 "fr_register_operand" "f"))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0)
+ (plus:V2SF
+ (mult:V2SF (match_dup 1) (match_dup 3))
+ (match_dup 2)))]
+ "")
+
+(define_insn_and_split "*addv2sf3_2"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (plus:V2SF
+ (mult:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f"))
+ (match_operand:V2SF 3 "fr_register_operand" "f")))
+ (use (match_operand:V2SF 4 "" "X"))]
+ ""
+ "#"
+ ""
+ [(set (match_dup 0)
+ (plus:V2SF
+ (mult:V2SF (match_dup 1) (match_dup 2))
+ (match_dup 3)))]
+ "")
+
+;; In order to convince combine to merge minus and mult to a useful fpms,
+;; we need a couple of extra patterns.
+(define_expand "subv2sf3"
+ [(parallel
+ [(set (match_operand:V2SF 0 "fr_register_operand" "")
+ (minus:V2SF (match_operand:V2SF 1 "fr_register_operand" "")
+ (match_operand:V2SF 2 "fr_register_operand" "")))
+ (use (match_dup 3))])]
+ ""
+{
+ rtvec v = gen_rtvec (2, CONST1_RTX (SFmode), CONST1_RTX (SFmode));
+ operands[3] = force_reg (V2SFmode, gen_rtx_CONST_VECTOR (V2SFmode, v));
+})
+
+;; The split condition here could be combine_completed, if we had such.
+(define_insn_and_split "*subv2sf3_1"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (minus:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f")))
+ (use (match_operand:V2SF 3 "fr_register_operand" "f"))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0)
+ (minus:V2SF
+ (mult:V2SF (match_dup 1) (match_dup 3))
+ (match_dup 2)))]
+ "")
+
+(define_insn_and_split "*subv2sf3_2"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (minus:V2SF
+ (mult:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f"))
+ (match_operand:V2SF 3 "fr_register_operand" "f")))
+ (use (match_operand:V2SF 4 "" "X"))]
+ ""
+ "#"
+ ""
+ [(set (match_dup 0)
+ (minus:V2SF
+ (mult:V2SF (match_dup 1) (match_dup 2))
+ (match_dup 3)))]
+ "")
+
+(define_insn "mulv2sf3"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (mult:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f")))]
+ ""
+ "fpmpy %0 = %1, %2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*fpma"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (plus:V2SF
+ (mult:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f"))
+ (match_operand:V2SF 3 "fr_register_operand" "f")))]
+ ""
+ "fpma %0 = %1, %2, %3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*fpms"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (minus:V2SF
+ (mult:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f"))
+ (match_operand:V2SF 3 "fr_register_operand" "f")))]
+ ""
+ "fpms %0 = %1, %2, %3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*fpnmpy"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (neg:V2SF
+ (mult:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f"))))]
+ ""
+ "fpnmpy %0 = %1, %2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*fpnma"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (plus:V2SF
+ (neg:V2SF
+ (mult:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f")))
+ (match_operand:V2SF 3 "fr_register_operand" "f")))]
+ ""
+ "fpnma %0 = %1, %2, %3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "smaxv2sf3"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (smax:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f")))]
+ ""
+ "fpmax %0 = %1, %2"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "sminv2sf3"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (smin:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f")))]
+ ""
+ "fpmin %0 = %1, %2"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_expand "reduc_splus_v2sf"
+ [(match_operand:V2SF 0 "fr_register_operand" "")
+ (match_operand:V2SF 1 "fr_register_operand" "")]
+ ""
+{
+ rtx tmp = gen_reg_rtx (V2SFmode);
+ emit_insn (gen_fswap (tmp, operands[1], CONST0_RTX (V2SFmode)));
+ emit_insn (gen_addv2sf3 (operands[0], operands[1], tmp));
+ DONE;
+})
+
+(define_expand "reduc_smax_v2sf"
+ [(match_operand:V2SF 0 "fr_register_operand" "")
+ (match_operand:V2SF 1 "fr_register_operand" "")]
+ ""
+{
+ rtx tmp = gen_reg_rtx (V2SFmode);
+ emit_insn (gen_fswap (tmp, operands[1], CONST0_RTX (V2SFmode)));
+ emit_insn (gen_smaxv2sf3 (operands[0], operands[1], tmp));
+ DONE;
+})
+
+(define_expand "reduc_smin_v2sf"
+ [(match_operand:V2SF 0 "fr_register_operand" "")
+ (match_operand:V2SF 1 "fr_register_operand" "")]
+ ""
+{
+ rtx tmp = gen_reg_rtx (V2SFmode);
+ emit_insn (gen_fswap (tmp, operands[1], CONST0_RTX (V2SFmode)));
+ emit_insn (gen_sminv2sf3 (operands[0], operands[1], tmp));
+ DONE;
+})
+
+(define_expand "vcondv2sf"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "")
+ (if_then_else:V2SF
+ (match_operator 3 ""
+ [(match_operand:V2SF 4 "fr_reg_or_0_operand" "")
+ (match_operand:V2SF 5 "fr_reg_or_0_operand" "")])
+ (match_operand:V2SF 1 "fr_reg_or_0_operand" "")
+ (match_operand:V2SF 2 "fr_reg_or_0_operand" "")))]
+ ""
+{
+ rtx x, cmp;
+
+ cmp = gen_reg_rtx (V2SFmode);
+ PUT_MODE (operands[3], V2SFmode);
+ emit_insn (gen_rtx_SET (VOIDmode, cmp, operands[3]));
+
+ x = gen_rtx_IF_THEN_ELSE (V2SFmode, cmp, operands[1], operands[2]);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ DONE;
+})
+
+(define_insn "*fpcmp"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (match_operator:V2SF 3 "comparison_operator"
+ [(match_operand:V2SF 1 "fr_reg_or_0_operand" "fU")
+ (match_operand:V2SF 2 "fr_reg_or_0_operand" "fU")]))]
+ ""
+ "fpcmp.%D3 %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*fselect"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (if_then_else:V2SF
+ (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_reg_or_0_operand" "fU")
+ (match_operand:V2SF 3 "fr_reg_or_0_operand" "fU")))]
+ ""
+ "fselect %0 = %F2, %F3, %1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_expand "vec_initv2sf"
+ [(match_operand:V2SF 0 "fr_register_operand" "")
+ (match_operand 1 "" "")]
+ ""
+{
+ rtx op1 = XVECEXP (operands[1], 0, 0);
+ rtx op2 = XVECEXP (operands[1], 0, 1);
+ rtx x;
+
+ if (GET_CODE (op1) == CONST_DOUBLE && GET_CODE (op2) == CONST_DOUBLE)
+ {
+ x = gen_rtx_CONST_VECTOR (V2SFmode, XVEC (operands[1], 0));
+ emit_move_insn (operands[0], x);
+ DONE;
+ }
+
+ if (!fr_reg_or_fp01_operand (op1, SFmode))
+ op1 = force_reg (SFmode, op1);
+ if (!fr_reg_or_fp01_operand (op2, SFmode))
+ op2 = force_reg (SFmode, op2);
+
+ if (TARGET_BIG_ENDIAN)
+ emit_insn (gen_fpack (operands[0], op2, op1));
+ else
+ emit_insn (gen_fpack (operands[0], op1, op2));
+ DONE;
+})
+
+(define_insn "fpack"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (vec_concat:V2SF
+ (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fpack %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "fswap"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (vec_select:V2SF
+ (vec_concat:V4SF
+ (match_operand:V2SF 1 "fr_reg_or_0_operand" "fU")
+ (match_operand:V2SF 2 "fr_reg_or_0_operand" "fU"))
+ (parallel [(const_int 1) (const_int 2)])))]
+ ""
+ "fswap %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*fmix_l"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (vec_select:V2SF
+ (vec_concat:V4SF
+ (match_operand:V2SF 1 "fr_reg_or_0_operand" "fU")
+ (match_operand:V2SF 2 "fr_reg_or_0_operand" "fU"))
+ (parallel [(const_int 1) (const_int 3)])))]
+ ""
+ "fmix.l %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "fmix_r"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (vec_select:V2SF
+ (vec_concat:V4SF
+ (match_operand:V2SF 1 "fr_reg_or_0_operand" "fU")
+ (match_operand:V2SF 2 "fr_reg_or_0_operand" "fU"))
+ (parallel [(const_int 0) (const_int 2)])))]
+ ""
+ "fmix.r %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "fmix_lr"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (vec_select:V2SF
+ (vec_concat:V4SF
+ (match_operand:V2SF 1 "fr_reg_or_0_operand" "fU")
+ (match_operand:V2SF 2 "fr_reg_or_0_operand" "fU"))
+ (parallel [(const_int 0) (const_int 3)])))]
+ ""
+ "fmix.lr %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_expand "vec_setv2sf"
+ [(match_operand:V2SF 0 "fr_register_operand" "")
+ (match_operand:SF 1 "fr_register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ ""
+{
+ rtx tmp = gen_reg_rtx (V2SFmode);
+ emit_insn (gen_fpack (tmp, operands[1], CONST0_RTX (SFmode)));
+
+ switch (INTVAL (operands[2]))
+ {
+ case 0:
+ emit_insn (gen_fmix_lr (operands[0], tmp, operands[0]));
+ break;
+ case 1:
+ emit_insn (gen_fmix_r (operands[0], operands[0], tmp));
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ DONE;
+})
+
+(define_insn_and_split "*vec_extractv2sf_0_le"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=r,f,m")
+ (unspec:SF [(match_operand:V2SF 1 "nonimmediate_operand" "rfm,rm,r")
+ (const_int 0)]
+ UNSPEC_VECT_EXTR))]
+ "!TARGET_BIG_ENDIAN"
+ "#"
+ "reload_completed"
+ [(set (match_dup 0) (match_dup 1))]
+{
+ if (REG_P (operands[1]) && FR_REGNO_P (REGNO (operands[1])))
+ operands[0] = gen_rtx_REG (V2SFmode, REGNO (operands[0]));
+ else if (MEM_P (operands[1]))
+ operands[1] = adjust_address (operands[1], SFmode, 0);
+ else
+ operands[1] = gen_rtx_REG (SFmode, REGNO (operands[1]));
+})
+
+(define_insn_and_split "*vec_extractv2sf_0_be"
+ [(set (match_operand:SF 0 "register_operand" "=r,f")
+ (unspec:SF [(match_operand:V2SF 1 "register_operand" "rf,r")
+ (const_int 0)]
+ UNSPEC_VECT_EXTR))]
+ "TARGET_BIG_ENDIAN"
+ "#"
+ "reload_completed"
+ [(set (match_dup 0) (match_dup 1))]
+{
+ if (REG_P (operands[1]) && FR_REGNO_P (REGNO (operands[1])))
+ operands[0] = gen_rtx_REG (V2SFmode, REGNO (operands[0]));
+ else
+ operands[1] = gen_rtx_REG (SFmode, REGNO (operands[1]));
+})
+
+(define_insn_and_split "*vec_extractv2sf_1"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (unspec:SF [(match_operand:V2SF 1 "register_operand" "r")
+ (const_int 1)]
+ UNSPEC_VECT_EXTR))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
+ operands[1] = gen_rtx_REG (DImode, REGNO (operands[1]));
+ if (TARGET_BIG_ENDIAN)
+ emit_move_insn (operands[0], operands[1]);
+ else
+ emit_insn (gen_lshrdi3 (operands[0], operands[1], GEN_INT (32)));
+ DONE;
+})
+
+(define_expand "vec_extractv2sf"
+ [(set (match_operand:SF 0 "register_operand" "")
+ (unspec:SF [(match_operand:V2SF 1 "register_operand" "")
+ (match_operand:DI 2 "const_int_operand" "")]
+ UNSPEC_VECT_EXTR))]
+ ""
+ "")
+
+;; Missing operations
+;; fprcpa
+;; fpsqrta
OpenPOWER on IntegriCloud