summaryrefslogtreecommitdiff
path: root/toolchain
diff options
context:
space:
mode:
Diffstat (limited to 'toolchain')
-rw-r--r--toolchain/Makefile2
-rw-r--r--toolchain/binutils/Makefile8
-rw-r--r--toolchain/binutils/Makefile.inc63
-rw-r--r--toolchain/binutils/patches/2.20.1/newer-gcc.patch24
-rw-r--r--toolchain/binutils/patches/2.28/lm32.patch24
-rw-r--r--toolchain/binutils/patches/2.37/0001-i386-Allow-GOT32-relocations-against-ABS-symbols.patch47
-rw-r--r--toolchain/binutils/patches/2.37/nds32-uclibc.patch15
-rw-r--r--toolchain/binutils/patches/2.38/0001-binutils-2.38-vs.-ppc32-linux-kernel.patch55
-rw-r--r--toolchain/binutils/patches/2.38/nds32-uclibc.patch15
-rw-r--r--toolchain/binutils/patches/2.41/lm32.patch24
-rw-r--r--toolchain/binutils/patches/2.42/j2.patch584
-rw-r--r--toolchain/binutils/patches/2.42/kvx.patch29
-rw-r--r--toolchain/elf2flt/Makefile23
-rw-r--r--toolchain/elf2flt/Makefile.inc9
-rw-r--r--toolchain/elf2flt/patches/26dfb54a59c8c0106418a0c46ccb4288d9e066fd/0001-riscv32.patch42
-rw-r--r--toolchain/elf2flt/patches/26dfb54a59c8c0106418a0c46ccb4288d9e066fd/0002-lm32.patch167
-rw-r--r--toolchain/elf2flt/patches/26dfb54a59c8c0106418a0c46ccb4288d9e066fd/0003-sh2.patch52
-rw-r--r--toolchain/elf2flt/patches/3051fec89bbd30de6f952dc3100712feff3ca076/0001-.rofixup-fix.patch33
-rw-r--r--toolchain/elf2flt/patches/453398f917d167f8c308c8f997270c48ae8f8b12/0005-elf2flt-add-riscv-64-bits-support.patch137
-rw-r--r--toolchain/elf2flt/patches/453398f917d167f8c308c8f997270c48ae8f8b12/0008-remove_BFD_VMA_FMT.patch125
-rw-r--r--toolchain/elf2flt/patches/v2021.08/0001-elf2flt-handle-binutils-2.34.patch377
-rw-r--r--toolchain/elf2flt/patches/v2021.08/0002-elf2flt.ld-reinstate-32-byte-alignment-for-.data-sec.patch81
-rw-r--r--toolchain/elf2flt/patches/v2021.08/0003-elf2flt-add-riscv-64-bits-support.patch103
-rw-r--r--toolchain/elf2flt/patches/v2021.08/0004-elf2flt-create-a-common-helper-function.patch76
-rw-r--r--toolchain/elf2flt/patches/v2021.08/0005-elf2flt-fix-fatal-error-regression-on-m68k-xtensa-ri.patch74
-rw-r--r--toolchain/elf2flt/patches/v2021.08/0006-elf2flt-xtensa-fix-text-relocations.patch25
-rw-r--r--toolchain/elf2flt/patches/v2021.08/0007-riscv32.patch56
-rw-r--r--toolchain/elf2flt/patches/v2021.08/0008-remove_BFD_VMA_FMT.patch97
-rw-r--r--toolchain/elf2flt/patches/v2021.08/0009-riscv.patch11
-rw-r--r--toolchain/elf2flt/patches/v2024.02/0001-sh2.patch43
-rw-r--r--toolchain/elf2flt/patches/v2024.02/0002-h8300.patch20
-rw-r--r--toolchain/elf2flt/patches/v2024.02/0003-riscv64-alignment.patch12
-rw-r--r--toolchain/gcc/Makefile32
-rw-r--r--toolchain/gcc/Makefile.inc78
-rw-r--r--toolchain/gcc/patches/10.3.0/revert-sparc.patch23628
-rw-r--r--toolchain/gcc/patches/10.5.0/add-crtreloc.frv (renamed from toolchain/gcc/patches/10.3.0/add-crtreloc.frv)0
-rw-r--r--toolchain/gcc/patches/10.5.0/c6x-disable-multilib.patch (renamed from toolchain/gcc/patches/10.3.0/c6x-disable-multilib.patch)0
-rw-r--r--toolchain/gcc/patches/10.5.0/ia64-fix-libgcc.patch (renamed from toolchain/gcc/patches/10.3.0/ia64-fix-libgcc.patch)0
-rw-r--r--toolchain/gcc/patches/10.5.0/j2.patch346
-rw-r--r--toolchain/gcc/patches/10.5.0/nios2-softfp.patch (renamed from toolchain/gcc/patches/10.3.0/nios2-softfp.patch)0
-rw-r--r--toolchain/gcc/patches/10.5.0/revert-sparc.patch283
-rw-r--r--toolchain/gcc/patches/11.4.0/add-crtreloc.frv12
-rw-r--r--toolchain/gcc/patches/11.4.0/c6x-disable-multilib.patch10
-rw-r--r--toolchain/gcc/patches/11.4.0/csky.patch12
-rw-r--r--toolchain/gcc/patches/11.4.0/ia64-fix-libgcc.patch17
-rw-r--r--toolchain/gcc/patches/11.4.0/nios2-softfp.patch14
-rw-r--r--toolchain/gcc/patches/11.4.0/revert.sparc283
-rw-r--r--toolchain/gcc/patches/12.3.0/csky.patch12
-rw-r--r--toolchain/gcc/patches/12.3.0/nios2-softfp.patch14
-rw-r--r--toolchain/gcc/patches/13.2.0/csky.patch12
-rw-r--r--toolchain/gcc/patches/13.2.0/nios2-softfp.patch14
-rw-r--r--toolchain/gcc/patches/4.5.4/gcc.lm322
-rw-r--r--toolchain/gdb/Makefile.inc26
-rw-r--r--toolchain/glibc/Makefile12
-rw-r--r--toolchain/glibc/Makefile.inc14
-rw-r--r--toolchain/glibc/patches/2.26/0001-Do-not-use-__builtin_types_compatible_p-in-C-mode-bu.patch50
-rw-r--r--toolchain/glibc/patches/2.26/0002-Do-not-use-generic-selection-in-C-mode.patch56
-rw-r--r--toolchain/glibc/patches/2.26/0003-Provide-a-C-version-of-issignaling-that-does-not-use.patch225
-rw-r--r--toolchain/glibc/patches/2.26/0004-Fix-the-C-version-of-issignaling-when-__NO_LONG_DOUB.patch47
-rw-r--r--toolchain/glibc/patches/2.26/0005-Provide-a-C-version-of-iszero-that-does-not-use-__MA.patch210
-rw-r--r--toolchain/glibc/patches/2.26/0006-Let-fpclassify-use-the-builtin-when-optimizing-for-s.patch63
-rw-r--r--toolchain/glibc/patches/2.38/0001-m68k-fix-__mpn_lshift-and-__mpn_rshift-for-non-68020.patch46
-rw-r--r--toolchain/glibc/patches/2.38/0004-ARC-Add-support-for-ARCv3-processors.patch4036
-rw-r--r--toolchain/glibc/patches/2.38/m68k-m68040.patch59
-rw-r--r--toolchain/gmp/Makefile.inc4
-rw-r--r--toolchain/mpfr/Makefile.inc4
-rw-r--r--toolchain/musl/Makefile.inc6
-rw-r--r--toolchain/newlib/Makefile.inc13
-rw-r--r--toolchain/newlib/patches/3.1.0/fix-tooldir.patch12
-rw-r--r--toolchain/newlib/patches/git/fix-tooldir.patch12
-rw-r--r--toolchain/newlib/patches/newlib-xtensa/fix-tooldir.patch12
-rw-r--r--toolchain/uclibc-ng/Makefile32
-rw-r--r--toolchain/uclibc-ng/Makefile.inc12
73 files changed, 7747 insertions, 24426 deletions
diff --git a/toolchain/Makefile b/toolchain/Makefile
index a7302bdb2..55e3ccce5 100644
--- a/toolchain/Makefile
+++ b/toolchain/Makefile
@@ -41,7 +41,7 @@ endif
ifeq ($(ADK_TOOLCHAIN_WITH_GDB),y)
# disable gdb for some architectures
-ifeq ($(ADK_TARGET_ARCH_ARC)$(ADK_TARGET_ARCH_CR16)$(ADK_TARGET_ARCH_EPIPHANY)$(ADK_TARGET_ARCH_METAG)$(ADK_TARGET_ARCH_NDS32)$(ADK_TARGET_ARCH_OR1K),)
+ifeq ($(ADK_TARGET_ARCH_CR16)$(ADK_TARGET_ARCH_EPIPHANY)$(ADK_TARGET_ARCH_METAG)$(ADK_TARGET_ARCH_NDS32),)
TARGETS+=gdb
GDB:=gdb-install
endif
diff --git a/toolchain/binutils/Makefile b/toolchain/binutils/Makefile
index 7136cf66e..63b1080fb 100644
--- a/toolchain/binutils/Makefile
+++ b/toolchain/binutils/Makefile
@@ -28,6 +28,10 @@ else
CONFOPTS+= --disable-gold
endif
+ifeq ($(ADK_TARGET_ARCH_ARC),y)
+CONFOPTS+= --enable-lto --enable-plugins
+endif
+
ifeq ($(ADK_TARGET_ARCH_X86_64)$(ADK_TARGET_CPU_CF),)
CONFOPTS+= --disable-multilib
else
@@ -44,7 +48,6 @@ ifeq ($(ADK_TARGET_ARCH_XTENSA),y)
--strip-components=1 -C $(WRKSRC) binutils
endif
(cd $(WRKBUILD); PATH='$(HOST_PATH)' \
- LDFLAGS=-ldl \
MAKEINFO=true \
M4='${STAGING_HOST_DIR}/usr/bin/m4' \
$(WRKBUILD)/configure \
@@ -58,6 +61,7 @@ endif
--disable-gdb \
--enable-obsolete \
--disable-werror \
+ --disable-gprof \
--disable-install-libiberty \
${CONFOPTS} \
);
@@ -70,7 +74,7 @@ $(WRKBUILD)/.compiled: $(WRKBUILD)/.configured
$(WRKBUILD)/.installed: $(WRKBUILD)/.compiled
PATH='$(HOST_PATH)' $(MAKE) MAKEINFO=true -C $(WRKBUILD) install
-ifeq ($(ADK_TARGET_ARCH_H8300)$(ADK_TARGET_ARCH_NDS32)$(ADK_TARGET_ARCH_SH),y)
+ifeq ($(ADK_TARGET_ARCH_KVX)$(ADK_TARGET_ARCH_H8300)$(ADK_TARGET_ARCH_NDS32)$(ADK_TARGET_ARCH_SH),y)
$(INSTALL_DIR) $(STAGING_TARGET_DIR)/usr/lib/ldscripts
$(CP) $(WRKBUILD)/ld/ldscripts/* $(STAGING_TARGET_DIR)/usr/lib/ldscripts/
endif
diff --git a/toolchain/binutils/Makefile.inc b/toolchain/binutils/Makefile.inc
index ac252de32..758539cf0 100644
--- a/toolchain/binutils/Makefile.inc
+++ b/toolchain/binutils/Makefile.inc
@@ -2,40 +2,61 @@
# material, please see the LICENCE file in the top-level directory.
PKG_NAME:= binutils
-ifeq ($(ADK_TOOLCHAIN_BINUTILS_2_37),y)
-PKG_VERSION:= 2.37
+ifeq ($(ADK_TOOLCHAIN_BINUTILS_2_42),y)
+PKG_VERSION:= 2.42
PKG_RELEASE:= 1
-PKG_HASH:= 820d9724f020a3e69cb337893a0b63c2db161dadcb0e06fc11dc29eb1e84a32c
+PKG_HASH:= 5d2a6c1d49686a557869caae08b6c2e83699775efd27505e01b2f4db1a024ffc
PKG_SITES:= ${MASTER_SITE_GNU:=binutils/}
-DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
endif
-ifeq ($(ADK_TOOLCHAIN_BINUTILS_2_28),y)
-PKG_VERSION:= 2.28
+ifeq ($(ADK_TOOLCHAIN_BINUTILS_2_41),y)
+PKG_VERSION:= 2.41
PKG_RELEASE:= 1
-PKG_HASH:= cd717966fc761d840d451dbd58d44e1e5b92949d2073d75b73fccb476d772fcf
+PKG_HASH:= 48d00a8dc73aa7d2394a7dc069b96191d95e8de8f0da6dc91da5cce655c20e45
PKG_SITES:= ${MASTER_SITE_GNU:=binutils/}
DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
endif
-ifeq ($(ADK_TOOLCHAIN_BINUTILS_ARC),y)
-PKG_VERSION:= arc-2020.09
-PKG_GIT:= tag
-PKG_RELEASE:= 1
-PKG_SITES:= https://github.com/foss-for-synopsys-dwc-arc-processors/binutils-gdb.git
-DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
+ifeq ($(ADK_TOOLCHAIN_BINUTILS_2_40),y)
+PKG_VERSION:= 2.40
+PKG_RELEASE:= 1
+PKG_HASH:= d7f82c4047decf43a6f769ac32456a92ddb6932409a585c633cdd4e9df23d956
+PKG_SITES:= ${MASTER_SITE_GNU:=binutils/}
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
+endif
+ifeq ($(ADK_TOOLCHAIN_BINUTILS_2_39),y)
+PKG_VERSION:= 2.39
+PKG_RELEASE:= 1
+PKG_HASH:= d12ea6f239f1ffe3533ea11ad6e224ffcb89eb5d01bbea589e9158780fa11f10
+PKG_SITES:= ${MASTER_SITE_GNU:=binutils/}
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
+endif
+ifeq ($(ADK_TOOLCHAIN_BINUTILS_2_38),y)
+PKG_VERSION:= 2.38
+PKG_RELEASE:= 1
+PKG_HASH:= b3f1dc5b17e75328f19bd88250bee2ef9f91fc8cbb7bd48bdb31390338636052
+PKG_SITES:= ${MASTER_SITE_GNU:=binutils/}
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
+endif
+ifeq ($(ADK_TOOLCHAIN_BINUTILS_2_37),y)
+PKG_VERSION:= 2.37
+PKG_RELEASE:= 1
+PKG_HASH:= c44968b97cd86499efbc4b4ab7d98471f673e5414c554ef54afa930062dbbfcb
+PKG_SITES:= ${MASTER_SITE_GNU:=binutils/}
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
endif
ifeq ($(ADK_TOOLCHAIN_BINUTILS_KVX),y)
-PKG_VERSION:= c5e8437af055869c8666a1c1e5a391d9af5be0c0
+PKG_VERSION:= 782547a4e2bdf1308728032853678ca69bb154ea
PKG_GIT:= hash
PKG_RELEASE:= 1
PKG_SITES:= https://github.com/kalray/gdb-binutils.git
-DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
endif
-ifeq ($(ADK_TOOLCHAIN_BINUTILS_NDS32),y)
-PKG_VERSION:= nds32-binutils-2.30-branch-open
-PKG_GIT:= branch
+ifeq ($(ADK_TOOLCHAIN_BINUTILS_ARC),y)
+PKG_VERSION:= arc-2023.09
+PKG_GIT:= tag
PKG_RELEASE:= 1
-PKG_SITES:= https://github.com/andestech/binutils.git
-DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
+PKG_SITES:= https://github.com/foss-for-synopsys-dwc-arc-processors/binutils-gdb.git
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
endif
ifeq ($(ADK_TOOLCHAIN_BINUTILS_AVR32),y)
PKG_VERSION:= 2.20.1
@@ -48,5 +69,5 @@ ifeq ($(ADK_TOOLCHAIN_BINUTILS_GIT),y)
PKG_VERSION:= git
PKG_RELEASE:= 1
PKG_SITES:= git://sourceware.org/git/binutils-gdb.git
-DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
endif
diff --git a/toolchain/binutils/patches/2.20.1/newer-gcc.patch b/toolchain/binutils/patches/2.20.1/newer-gcc.patch
new file mode 100644
index 000000000..b7f42e447
--- /dev/null
+++ b/toolchain/binutils/patches/2.20.1/newer-gcc.patch
@@ -0,0 +1,24 @@
+diff -Nur binutils-2.20.1.orig/binutils/readelf.c binutils-2.20.1/binutils/readelf.c
+--- binutils-2.20.1.orig/binutils/readelf.c 2023-02-03 11:04:53.722082738 +0100
++++ binutils-2.20.1/binutils/readelf.c 2023-02-03 11:05:27.049296372 +0100
+@@ -150,7 +150,7 @@
+ #include "filenames.h"
+
+ char * program_name = "readelf";
+-int do_wide;
++extern int do_wide;
+ static long archive_file_offset;
+ static unsigned long archive_file_size;
+ static unsigned long dynamic_addr;
+diff -Nur binutils-2.20.1.orig/gas/config/tc-avr32.c binutils-2.20.1/gas/config/tc-avr32.c
+--- binutils-2.20.1.orig/gas/config/tc-avr32.c 2023-02-03 11:04:53.726082644 +0100
++++ binutils-2.20.1/gas/config/tc-avr32.c 2023-02-03 11:06:12.164234434 +0100
+@@ -47,7 +47,7 @@
+
+ /* Flags given on the command line */
+ static int avr32_pic = FALSE;
+-int linkrelax = FALSE;
++//extern int linkrelax = FALSE;
+ int avr32_iarcompat = FALSE;
+
+ /* This array holds the chars that always start a comment. */
diff --git a/toolchain/binutils/patches/2.28/lm32.patch b/toolchain/binutils/patches/2.28/lm32.patch
new file mode 100644
index 000000000..962281625
--- /dev/null
+++ b/toolchain/binutils/patches/2.28/lm32.patch
@@ -0,0 +1,24 @@
+diff -Nur binutils-2.28.orig/bfd/config.bfd binutils-2.28/bfd/config.bfd
+--- binutils-2.28.orig/bfd/config.bfd 2017-03-02 09:23:53.000000000 +0100
++++ binutils-2.28/bfd/config.bfd 2023-08-27 11:54:08.526040118 +0200
+@@ -924,7 +924,7 @@
+ ;;
+
+ lm32-*-*linux*)
+- targ_defvec=lm32_elf32_fdpic_vec
++ targ_defvec=lm32_elf32_vec
+ targ_selvecs=lm32_elf32_vec
+ ;;
+
+diff -Nur binutils-2.28.orig/ld/configure.tgt binutils-2.28/ld/configure.tgt
+--- binutils-2.28.orig/ld/configure.tgt 2017-03-02 09:23:54.000000000 +0100
++++ binutils-2.28/ld/configure.tgt 2023-08-27 11:54:43.882874903 +0200
+@@ -416,7 +416,7 @@
+ ;;
+ iq2000-*-elf) targ_emul=elf32iq2000 ; targ_extra_emuls="elf32iq10"
+ ;;
+-lm32-*-*linux*) targ_emul=elf32lm32fd ;;
++lm32-*-*linux*) targ_emul=elf32lm32 ;;
+ lm32-*-*) targ_emul=elf32lm32 ; targ_extra_emuls="elf32lm32fd"
+ ;;
+ m32c-*-elf | m32c-*-rtems*)
diff --git a/toolchain/binutils/patches/2.37/0001-i386-Allow-GOT32-relocations-against-ABS-symbols.patch b/toolchain/binutils/patches/2.37/0001-i386-Allow-GOT32-relocations-against-ABS-symbols.patch
new file mode 100644
index 000000000..3e2928226
--- /dev/null
+++ b/toolchain/binutils/patches/2.37/0001-i386-Allow-GOT32-relocations-against-ABS-symbols.patch
@@ -0,0 +1,47 @@
+From 30a954525f4e53a9cd50a1a8a6f201c7cf6595c7 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Mon, 7 Feb 2022 15:22:19 -0800
+Subject: [PATCH] i386: Allow GOT32 relocations against ABS symbols
+
+GOT32 relocations are allowed since absolute value + addend is stored in
+the GOT slot.
+
+Tested on glibc 2.35 build with GCC 11.2 and -Os.
+
+bfd/
+
+ PR ld/28870
+ * elfxx-x86.c (_bfd_elf_x86_valid_reloc_p): Also allow GOT32
+ relocations.
+
+
+Signed-off-by: Waldemar Brodkorb <wbx@openadk.org>
+
+diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
+index 7ac2411fc80..d00dc45677b 100644
+--- a/bfd/elfxx-x86.c
++++ b/bfd/elfxx-x86.c
+@@ -1942,9 +1942,9 @@ _bfd_elf_x86_valid_reloc_p (asection *input_section,
+ irel = *rel;
+
+ /* Only allow relocations against absolute symbol, which can be
+- resolved as absolute value + addend. GOTPCREL relocations
+- are allowed since absolute value + addend is stored in the
+- GOT slot. */
++ resolved as absolute value + addend. GOTPCREL and GOT32
++ relocations are allowed since absolute value + addend is
++ stored in the GOT slot. */
+ if (bed->target_id == X86_64_ELF_DATA)
+ {
+ r_type &= ~R_X86_64_converted_reloc_bit;
+@@ -1965,7 +1965,9 @@ _bfd_elf_x86_valid_reloc_p (asection *input_section,
+ else
+ valid_p = (r_type == R_386_32
+ || r_type == R_386_16
+- || r_type == R_386_8);
++ || r_type == R_386_8
++ || r_type == R_386_GOT32
++ || r_type == R_386_GOT32X);
+
+ if (valid_p)
+ *no_dynreloc_p = true;
diff --git a/toolchain/binutils/patches/2.37/nds32-uclibc.patch b/toolchain/binutils/patches/2.37/nds32-uclibc.patch
new file mode 100644
index 000000000..b14e98511
--- /dev/null
+++ b/toolchain/binutils/patches/2.37/nds32-uclibc.patch
@@ -0,0 +1,15 @@
+diff -Nur binutils-2.37.orig/ld/configure.tgt binutils-2.37/ld/configure.tgt
+--- binutils-2.37.orig/ld/configure.tgt 2021-07-08 13:37:20.000000000 +0200
++++ binutils-2.37/ld/configure.tgt 2022-01-21 03:23:49.296011413 +0100
+@@ -594,9 +594,9 @@
+ nds32*be-*-elf*) targ_emul=nds32belf
+ targ_extra_emuls="nds32elf nds32elf16m nds32belf16m"
+ ;;
+-nds32*le-*-linux-gnu*) targ_emul=nds32elf_linux
++nds32*le-*-linux-*) targ_emul=nds32elf_linux
+ ;;
+-nds32*be-*-linux-gnu*) targ_emul=nds32belf_linux
++nds32*be-*-linux-*) targ_emul=nds32belf_linux
+ ;;
+ nios2*-*-linux*) targ_emul=nios2linux
+ ;;
diff --git a/toolchain/binutils/patches/2.38/0001-binutils-2.38-vs.-ppc32-linux-kernel.patch b/toolchain/binutils/patches/2.38/0001-binutils-2.38-vs.-ppc32-linux-kernel.patch
new file mode 100644
index 000000000..c62652c95
--- /dev/null
+++ b/toolchain/binutils/patches/2.38/0001-binutils-2.38-vs.-ppc32-linux-kernel.patch
@@ -0,0 +1,55 @@
+From ed9b2e40ebffec835d63473367da8dd8f80d7d5b Mon Sep 17 00:00:00 2001
+From: Alan Modra <amodra@gmail.com>
+Date: Mon, 21 Feb 2022 10:58:57 +1030
+Subject: [PATCH] binutils 2.38 vs. ppc32 linux kernel
+
+Commit b25f942e18d6 made .machine more strict. Weaken it again.
+
+ * config/tc-ppc.c (ppc_machine): Treat an early .machine specially,
+ keeping sticky options to work around gcc bugs.
+
+(cherry picked from commit cebc89b9328eab994f6b0314c263f94e7949a553)
+Signed-off-by: Waldemar Brodkorb <wbx@openadk.org>
+---
+ gas/config/tc-ppc.c | 25 ++++++++++++++++++++++++-
+ 1 file changed, 24 insertions(+), 1 deletion(-)
+
+diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c
+index 054f9c72161..89bc7d3f9b9 100644
+--- a/gas/config/tc-ppc.c
++++ b/gas/config/tc-ppc.c
+@@ -5965,7 +5965,30 @@ ppc_machine (int ignore ATTRIBUTE_UNUSED)
+ options do not count as a new machine, instead they add
+ to currently selected opcodes. */
+ ppc_cpu_t machine_sticky = 0;
+- new_cpu = ppc_parse_cpu (ppc_cpu, &machine_sticky, cpu_string);
++ /* Unfortunately, some versions of gcc emit a .machine
++ directive very near the start of the compiler's assembly
++ output file. This is bad because it overrides user -Wa
++ cpu selection. Worse, there are versions of gcc that
++ emit the *wrong* cpu, not even respecting the -mcpu given
++ to gcc. See gcc pr101393. And to compound the problem,
++ as of 20220222 gcc doesn't pass the correct cpu option to
++ gas on the command line. See gcc pr59828. Hack around
++ this by keeping sticky options for an early .machine. */
++ asection *sec;
++ for (sec = stdoutput->sections; sec != NULL; sec = sec->next)
++ {
++ segment_info_type *info = seg_info (sec);
++ /* Are the frags for this section perturbed from their
++ initial state? Even .align will count here. */
++ if (info != NULL
++ && (info->frchainP->frch_root != info->frchainP->frch_last
++ || info->frchainP->frch_root->fr_type != rs_fill
++ || info->frchainP->frch_root->fr_fix != 0))
++ break;
++ }
++ new_cpu = ppc_parse_cpu (ppc_cpu,
++ sec == NULL ? &sticky : &machine_sticky,
++ cpu_string);
+ if (new_cpu != 0)
+ ppc_cpu = new_cpu;
+ else
+--
+2.30.2
+
diff --git a/toolchain/binutils/patches/2.38/nds32-uclibc.patch b/toolchain/binutils/patches/2.38/nds32-uclibc.patch
new file mode 100644
index 000000000..b14e98511
--- /dev/null
+++ b/toolchain/binutils/patches/2.38/nds32-uclibc.patch
@@ -0,0 +1,15 @@
+diff -Nur binutils-2.37.orig/ld/configure.tgt binutils-2.37/ld/configure.tgt
+--- binutils-2.37.orig/ld/configure.tgt 2021-07-08 13:37:20.000000000 +0200
++++ binutils-2.37/ld/configure.tgt 2022-01-21 03:23:49.296011413 +0100
+@@ -594,9 +594,9 @@
+ nds32*be-*-elf*) targ_emul=nds32belf
+ targ_extra_emuls="nds32elf nds32elf16m nds32belf16m"
+ ;;
+-nds32*le-*-linux-gnu*) targ_emul=nds32elf_linux
++nds32*le-*-linux-*) targ_emul=nds32elf_linux
+ ;;
+-nds32*be-*-linux-gnu*) targ_emul=nds32belf_linux
++nds32*be-*-linux-*) targ_emul=nds32belf_linux
+ ;;
+ nios2*-*-linux*) targ_emul=nios2linux
+ ;;
diff --git a/toolchain/binutils/patches/2.41/lm32.patch b/toolchain/binutils/patches/2.41/lm32.patch
new file mode 100644
index 000000000..dcbb0d541
--- /dev/null
+++ b/toolchain/binutils/patches/2.41/lm32.patch
@@ -0,0 +1,24 @@
+diff -Nur binutils-2.41.orig/bfd/config.bfd binutils-2.41/bfd/config.bfd
+--- binutils-2.41.orig/bfd/config.bfd 2023-07-03 01:00:00.000000000 +0200
++++ binutils-2.41/bfd/config.bfd 2023-09-07 17:03:12.853045008 +0200
+@@ -803,7 +803,7 @@
+ ;;
+
+ lm32-*-*linux*)
+- targ_defvec=lm32_elf32_fdpic_vec
++ targ_defvec=lm32_elf32_vec
+ targ_selvecs=lm32_elf32_vec
+ ;;
+
+diff -Nur binutils-2.41.orig/ld/configure.tgt binutils-2.41/ld/configure.tgt
+--- binutils-2.41.orig/ld/configure.tgt 2023-07-03 01:00:00.000000000 +0200
++++ binutils-2.41/ld/configure.tgt 2023-09-07 17:03:44.364298973 +0200
+@@ -468,7 +468,7 @@
+ targ_extra_emuls="elf32iq10"
+ targ_extra_ofiles=ldelfgen.o
+ ;;
+-lm32-*-*linux*) targ_emul=elf32lm32fd
++lm32-*-*linux*) targ_emul=elf32lm32
+ ;;
+ lm32-*-*) targ_emul=elf32lm32
+ targ_extra_emuls="elf32lm32fd"
diff --git a/toolchain/binutils/patches/2.42/j2.patch b/toolchain/binutils/patches/2.42/j2.patch
new file mode 100644
index 000000000..42c7274aa
--- /dev/null
+++ b/toolchain/binutils/patches/2.42/j2.patch
@@ -0,0 +1,584 @@
+diff -Nur binutils-2.42.orig/bfd/archures.c binutils-2.42/bfd/archures.c
+--- binutils-2.42.orig/bfd/archures.c 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/bfd/archures.c 2024-02-22 16:50:03.657904349 +0100
+@@ -284,10 +284,12 @@
+ .#define bfd_mach_sh_dsp 0x2d
+ .#define bfd_mach_sh2a 0x2a
+ .#define bfd_mach_sh2a_nofpu 0x2b
++.#define bfd_mach_shj2 0x2c
+ .#define bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu 0x2a1
+ .#define bfd_mach_sh2a_nofpu_or_sh3_nommu 0x2a2
+ .#define bfd_mach_sh2a_or_sh4 0x2a3
+ .#define bfd_mach_sh2a_or_sh3e 0x2a4
++.#define bfd_mach_sh2a_nofpu_or_sh3_nommu_or_shj2_nofpu 0x2a5
+ .#define bfd_mach_sh2e 0x2e
+ .#define bfd_mach_sh3 0x30
+ .#define bfd_mach_sh3_nommu 0x31
+diff -Nur binutils-2.42.orig/bfd/bfd-in2.h binutils-2.42/bfd/bfd-in2.h
+--- binutils-2.42.orig/bfd/bfd-in2.h 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/bfd/bfd-in2.h 2024-02-22 16:50:03.661904381 +0100
+@@ -1540,10 +1540,12 @@
+ #define bfd_mach_sh_dsp 0x2d
+ #define bfd_mach_sh2a 0x2a
+ #define bfd_mach_sh2a_nofpu 0x2b
++#define bfd_mach_shj2 0x2c
+ #define bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu 0x2a1
+ #define bfd_mach_sh2a_nofpu_or_sh3_nommu 0x2a2
+ #define bfd_mach_sh2a_or_sh4 0x2a3
+ #define bfd_mach_sh2a_or_sh3e 0x2a4
++#define bfd_mach_sh2a_nofpu_or_sh3_nommu_or_shj2_nofpu 0x2a5
+ #define bfd_mach_sh2e 0x2e
+ #define bfd_mach_sh3 0x30
+ #define bfd_mach_sh3_nommu 0x31
+diff -Nur binutils-2.42.orig/bfd/cpu-sh.c binutils-2.42/bfd/cpu-sh.c
+--- binutils-2.42.orig/bfd/cpu-sh.c 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/bfd/cpu-sh.c 2024-02-22 16:50:03.661904381 +0100
+@@ -63,7 +63,9 @@
+ N (bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu, "sh2a-nofpu-or-sh4-nommu-nofpu", false, arch_info_struct + 16),
+ N (bfd_mach_sh2a_nofpu_or_sh3_nommu, "sh2a-nofpu-or-sh3-nommu", false, arch_info_struct + 17),
+ N (bfd_mach_sh2a_or_sh4, "sh2a-or-sh4", false, arch_info_struct + 18),
+- N (bfd_mach_sh2a_or_sh3e, "sh2a-or-sh3e", false, NULL)
++ N (bfd_mach_sh2a_or_sh3e, "sh2a-or-sh3e", false, arch_info_struct + 19),
++ N (bfd_mach_shj2, "j2", false, arch_info_struct + 20),
++ N (bfd_mach_sh2a_nofpu_or_sh3_nommu_or_shj2_nofpu, "sh2a-nofpu-or-sh3-nommu-or-j2-nofpu", false, NULL)
+ };
+
+ const bfd_arch_info_type bfd_sh_arch =
+@@ -99,6 +101,8 @@
+ { bfd_mach_sh4_nofpu, arch_sh4_nofpu, arch_sh4_nofpu_up },
+ { bfd_mach_sh4_nommu_nofpu, arch_sh4_nommu_nofpu, arch_sh4_nommu_nofpu_up },
+ { bfd_mach_sh4a_nofpu, arch_sh4a_nofpu, arch_sh4a_nofpu_up },
++ { bfd_mach_shj2, arch_shj2, arch_shj2_up },
++ { bfd_mach_sh2a_nofpu_or_sh3_nommu_or_shj2_nofpu, arch_sh2a_nofpu_or_sh3_nommu_or_shj2_nofpu, arch_sh2a_nofpu_or_sh3_nommu_or_shj2_nofpu_up },
+ { 0, 0, 0 } /* Terminator. */
+ };
+
+diff -Nur binutils-2.42.orig/binutils/readelf.c binutils-2.42/binutils/readelf.c
+--- binutils-2.42.orig/binutils/readelf.c 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/binutils/readelf.c 2024-02-22 16:53:19.799614987 +0100
+@@ -4326,6 +4326,12 @@
+ case EF_SH2A_SH3E:
+ out = stpcpy (out, ", sh2a-or-sh3e");
+ break;
++ case EF_SHJ2:
++ out = stpcpy (out, ", j2");
++ break;
++ case EF_SH2A_SH3_SHJ2:
++ out = stpcpy (out, ", sh2a-nofpu-or-sh3-nommu-or-shj2 -nofpu");
++ break;
+ default:
+ out = stpcpy (out, _(", unknown ISA"));
+ break;
+diff -Nur binutils-2.42.orig/gas/config/tc-sh.c binutils-2.42/gas/config/tc-sh.c
+--- binutils-2.42.orig/gas/config/tc-sh.c 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/gas/config/tc-sh.c 2024-02-22 16:50:03.685904574 +0100
+@@ -1251,6 +1251,8 @@
+ if (*ptr == ',')
+ ptr++;
+ get_operand (&ptr, operand + 2);
++ if (strcmp (info->name,"cas") == 0)
++ operand[2].type = A_IND_0;
+ }
+ }
+ }
+@@ -1775,7 +1777,10 @@
+ goto fail;
+ reg_m = 4;
+ break;
+-
++ case A_IND_0:
++ if (user->reg != 0)
++ goto fail;
++ break;
+ default:
+ printf (_("unhandled %d\n"), arg);
+ goto fail;
+diff -Nur binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh2a-nofpu-or-sh3-nommu.s binutils-2.42/gas/testsuite/gas/sh/arch/sh2a-nofpu-or-sh3-nommu.s
+--- binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh2a-nofpu-or-sh3-nommu.s 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/gas/testsuite/gas/sh/arch/sh2a-nofpu-or-sh3-nommu.s 2024-02-22 16:50:03.685904574 +0100
+@@ -12,8 +12,6 @@
+ sh2a_nofpu_or_sh3_nommu:
+ ! Instructions introduced into sh2a-nofpu-or-sh3-nommu
+ pref @r4 ;!/* 0000nnnn10000011 pref @<REG_N> */{"pref",{A_IND_N},{HEX_0,REG_N,HEX_8,HEX_3}, arch_sh2a_nofpu_or_sh3_nommu_up}
+- shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_up}
+- shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_up}
+
+ ! Instructions inherited from ancestors: sh sh2
+ add #4,r4 ;!/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM0_8}, arch_sh_up}
+diff -Nur binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh2a-nofpu-or-sh4-nommu-nofpu.s binutils-2.42/gas/testsuite/gas/sh/arch/sh2a-nofpu-or-sh4-nommu-nofpu.s
+--- binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh2a-nofpu-or-sh4-nommu-nofpu.s 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/gas/testsuite/gas/sh/arch/sh2a-nofpu-or-sh4-nommu-nofpu.s 2024-02-22 16:50:03.685904574 +0100
+@@ -12,7 +12,7 @@
+ sh2a_nofpu_or_sh4_nommu_nofpu:
+ ! Instructions introduced into sh2a-nofpu-or-sh4-nommu-nofpu
+
+-! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu
++! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh3-nommu-or-sh2j-nofpu
+ add #4,r4 ;!/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM0_8}, arch_sh_up}
+ add r5,r4 ;!/* 0011nnnnmmmm1100 add <REG_M>,<REG_N> */{"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}, arch_sh_up}
+ addc r5,r4 ;!/* 0011nnnnmmmm1110 addc <REG_M>,<REG_N>*/{"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}, arch_sh_up}
+@@ -119,8 +119,8 @@
+ rte ;!/* 0000000000101011 rte */{"rte",{0},{HEX_0,HEX_0,HEX_2,HEX_B}, arch_sh_up}
+ rts ;!/* 0000000000001011 rts */{"rts",{0},{HEX_0,HEX_0,HEX_0,HEX_B}, arch_sh_up}
+ sett ;!/* 0000000000011000 sett */{"sett",{0},{HEX_0,HEX_0,HEX_1,HEX_8}, arch_sh_up}
+- shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_up}
+- shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_up}
++ shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
++ shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
+ shal r4 ;!/* 0100nnnn00100000 shal <REG_N> */{"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}, arch_sh_up}
+ shar r4 ;!/* 0100nnnn00100001 shar <REG_N> */{"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}, arch_sh_up}
+ shll r4 ;!/* 0100nnnn00000000 shll <REG_N> */{"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}, arch_sh_up}
+diff -Nur binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh2a-nofpu.s binutils-2.42/gas/testsuite/gas/sh/arch/sh2a-nofpu.s
+--- binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh2a-nofpu.s 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/gas/testsuite/gas/sh/arch/sh2a-nofpu.s 2024-02-22 16:50:03.685904574 +0100
+@@ -64,7 +64,7 @@
+ movu.b @(2048,r5),r4 ;!/* 0011nnnnmmmm0001 1000dddddddddddd movu.b @(<DISP12>,<REG_M>),<REG_N> */ {"movu.b",{A_DISP_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_1,HEX_8,DISP0_12}, arch_sh2a_nofpu_up | arch_op32}
+ movu.w @(2048,r5),r4 ;!/* 0011nnnnmmmm0001 1001dddddddddddd movu.w @(<DISP12>,<REG_M>),<REG_N> */ {"movu.w",{A_DISP_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_1,HEX_9,DISP0_12BY2}, arch_sh2a_nofpu_up | arch_op32}
+
+-! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh4-nommu-nofpu
++! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh3-nommu-or-sh2j-nofpu sh2a-nofpu-or-sh4-nommu-nofpu
+ add #4,r4 ;!/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM0_8}, arch_sh_up}
+ add r5,r4 ;!/* 0011nnnnmmmm1100 add <REG_M>,<REG_N> */{"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}, arch_sh_up}
+ addc r5,r4 ;!/* 0011nnnnmmmm1110 addc <REG_M>,<REG_N>*/{"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}, arch_sh_up}
+@@ -171,8 +171,8 @@
+ rte ;!/* 0000000000101011 rte */{"rte",{0},{HEX_0,HEX_0,HEX_2,HEX_B}, arch_sh_up}
+ rts ;!/* 0000000000001011 rts */{"rts",{0},{HEX_0,HEX_0,HEX_0,HEX_B}, arch_sh_up}
+ sett ;!/* 0000000000011000 sett */{"sett",{0},{HEX_0,HEX_0,HEX_1,HEX_8}, arch_sh_up}
+- shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_up}
+- shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_up}
++ shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
++ shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
+ shal r4 ;!/* 0100nnnn00100000 shal <REG_N> */{"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}, arch_sh_up}
+ shar r4 ;!/* 0100nnnn00100001 shar <REG_N> */{"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}, arch_sh_up}
+ shll r4 ;!/* 0100nnnn00000000 shll <REG_N> */{"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}, arch_sh_up}
+diff -Nur binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh2a-or-sh3e.s binutils-2.42/gas/testsuite/gas/sh/arch/sh2a-or-sh3e.s
+--- binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh2a-or-sh3e.s 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/gas/testsuite/gas/sh/arch/sh2a-or-sh3e.s 2024-02-22 16:50:03.689904606 +0100
+@@ -13,7 +13,7 @@
+ ! Instructions introduced into sh2a-or-sh3e
+ fsqrt fr1 ;!/* 1111nnnn01101101 fsqrt <F_REG_N> */{"fsqrt",{F_REG_N},{HEX_F,REG_N,HEX_6,HEX_D}, arch_sh2a_or_sh3e_up}
+
+-! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2e
++! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh3-nommu-or-sh2j-nofpu sh2e
+ add #4,r4 ;!/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM0_8}, arch_sh_up}
+ add r5,r4 ;!/* 0011nnnnmmmm1100 add <REG_M>,<REG_N> */{"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}, arch_sh_up}
+ addc r5,r4 ;!/* 0011nnnnmmmm1110 addc <REG_M>,<REG_N>*/{"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}, arch_sh_up}
+@@ -124,8 +124,8 @@
+ rte ;!/* 0000000000101011 rte */{"rte",{0},{HEX_0,HEX_0,HEX_2,HEX_B}, arch_sh_up}
+ rts ;!/* 0000000000001011 rts */{"rts",{0},{HEX_0,HEX_0,HEX_0,HEX_B}, arch_sh_up}
+ sett ;!/* 0000000000011000 sett */{"sett",{0},{HEX_0,HEX_0,HEX_1,HEX_8}, arch_sh_up}
+- shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_up}
+- shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_up}
++ shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
++ shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
+ shal r4 ;!/* 0100nnnn00100000 shal <REG_N> */{"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}, arch_sh_up}
+ shar r4 ;!/* 0100nnnn00100001 shar <REG_N> */{"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}, arch_sh_up}
+ shll r4 ;!/* 0100nnnn00000000 shll <REG_N> */{"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}, arch_sh_up}
+diff -Nur binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh2a-or-sh4.s binutils-2.42/gas/testsuite/gas/sh/arch/sh2a-or-sh4.s
+--- binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh2a-or-sh4.s 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/gas/testsuite/gas/sh/arch/sh2a-or-sh4.s 2024-02-22 16:50:03.689904606 +0100
+@@ -39,7 +39,7 @@
+ fsub dr4,dr2 ;!/* 1111nnn0mmm00001 fsub <D_REG_M>,<D_REG_N>*/{"fsub",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_1}, arch_sh2a_or_sh4_up}
+ ftrc dr2,FPUL ;!/* 1111nnnn00111101 ftrc <D_REG_N>,FPUL*/{"ftrc",{D_REG_N,FPUL_M},{HEX_F,REG_N,HEX_3,HEX_D}, arch_sh2a_or_sh4_up}
+
+-! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh4-nommu-nofpu sh2a-or-sh3e sh2e
++! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh3-nommu-or-sh2j-nofpu sh2a-nofpu-or-sh4-nommu-nofpu sh2a-or-sh3e sh2e
+ add #4,r4 ;!/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM0_8}, arch_sh_up}
+ add r5,r4 ;!/* 0011nnnnmmmm1100 add <REG_M>,<REG_N> */{"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}, arch_sh_up}
+ addc r5,r4 ;!/* 0011nnnnmmmm1110 addc <REG_M>,<REG_N>*/{"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}, arch_sh_up}
+@@ -150,8 +150,8 @@
+ rte ;!/* 0000000000101011 rte */{"rte",{0},{HEX_0,HEX_0,HEX_2,HEX_B}, arch_sh_up}
+ rts ;!/* 0000000000001011 rts */{"rts",{0},{HEX_0,HEX_0,HEX_0,HEX_B}, arch_sh_up}
+ sett ;!/* 0000000000011000 sett */{"sett",{0},{HEX_0,HEX_0,HEX_1,HEX_8}, arch_sh_up}
+- shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_up}
+- shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_up}
++ shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
++ shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
+ shal r4 ;!/* 0100nnnn00100000 shal <REG_N> */{"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}, arch_sh_up}
+ shar r4 ;!/* 0100nnnn00100001 shar <REG_N> */{"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}, arch_sh_up}
+ shll r4 ;!/* 0100nnnn00000000 shll <REG_N> */{"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}, arch_sh_up}
+diff -Nur binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh2a.s binutils-2.42/gas/testsuite/gas/sh/arch/sh2a.s
+--- binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh2a.s 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/gas/testsuite/gas/sh/arch/sh2a.s 2024-02-22 16:50:03.689904606 +0100
+@@ -16,7 +16,7 @@
+ fmov.s fr2,@(2048,r4) ;!/* 0011nnnnmmmm0001 0011dddddddddddd fmov.s <F_REG_M>,@(<DISP12>,<REG_N>) */ {"fmov.s",{F_REG_M,A_DISP_REG_N},{HEX_3,REG_N,REG_M,HEX_1,HEX_3,DISP1_12BY4}, arch_sh2a_up | arch_op32}
+ fmov.s @(2048,r5),fr1 ;!/* 0011nnnnmmmm0001 0111dddddddddddd fmov.s @(<DISP12>,<REG_M>),<F_REG_N> */ {"fmov.s",{A_DISP_REG_M,F_REG_N},{HEX_3,REG_N,REG_M,HEX_1,HEX_7,DISP0_12BY4}, arch_sh2a_up | arch_op32}
+
+-! Instructions inherited from ancestors: sh sh2 sh2a-nofpu sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh4-nommu-nofpu sh2a-or-sh3e sh2a-or-sh4 sh2e
++! Instructions inherited from ancestors: sh sh2 sh2a-nofpu sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh3-nommu-or-sh2j-nofpu sh2a-nofpu-or-sh4-nommu-nofpu sh2a-or-sh3e sh2a-or-sh4 sh2e
+ add #4,r4 ;!/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM0_8}, arch_sh_up}
+ add r5,r4 ;!/* 0011nnnnmmmm1100 add <REG_M>,<REG_N> */{"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}, arch_sh_up}
+ addc r5,r4 ;!/* 0011nnnnmmmm1110 addc <REG_M>,<REG_N>*/{"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}, arch_sh_up}
+@@ -140,8 +140,8 @@
+ rte ;!/* 0000000000101011 rte */{"rte",{0},{HEX_0,HEX_0,HEX_2,HEX_B}, arch_sh_up}
+ rts ;!/* 0000000000001011 rts */{"rts",{0},{HEX_0,HEX_0,HEX_0,HEX_B}, arch_sh_up}
+ sett ;!/* 0000000000011000 sett */{"sett",{0},{HEX_0,HEX_0,HEX_1,HEX_8}, arch_sh_up}
+- shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_up}
+- shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_up}
++ shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
++ shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
+ shal r4 ;!/* 0100nnnn00100000 shal <REG_N> */{"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}, arch_sh_up}
+ shar r4 ;!/* 0100nnnn00100001 shar <REG_N> */{"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}, arch_sh_up}
+ shll r4 ;!/* 0100nnnn00000000 shll <REG_N> */{"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}, arch_sh_up}
+diff -Nur binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh3-dsp.s binutils-2.42/gas/testsuite/gas/sh/arch/sh3-dsp.s
+--- binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh3-dsp.s 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/gas/testsuite/gas/sh/arch/sh3-dsp.s 2024-02-22 16:50:03.689904606 +0100
+@@ -12,7 +12,7 @@
+ sh3_dsp:
+ ! Instructions introduced into sh3-dsp
+
+-! Instructions inherited from ancestors: sh sh-dsp sh2 sh2a-nofpu-or-sh3-nommu sh3 sh3-nommu
++! Instructions inherited from ancestors: sh sh-dsp sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh3-nommu-or-sh2j-nofpu sh3 sh3-nommu
+ add #4,r4 ;!/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM0_8}, arch_sh_up}
+ add r5,r4 ;!/* 0011nnnnmmmm1100 add <REG_M>,<REG_N> */{"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}, arch_sh_up}
+ addc r5,r4 ;!/* 0011nnnnmmmm1110 addc <REG_M>,<REG_N>*/{"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}, arch_sh_up}
+@@ -152,8 +152,8 @@
+ setrc #4 ;!/* 10000010i8*1.... setrc #<imm> */{"setrc",{A_IMM},{HEX_8,HEX_2,IMM0_8}, arch_sh_dsp_up}
+ repeat 10 20 r4 ;!/* repeat start end <REG_N> */{"repeat",{A_DISP_PC,A_DISP_PC,A_REG_N},{REPEAT,REG_N,HEX_1,HEX_4}, arch_sh_dsp_up}
+ repeat 10 20 #4 ;!/* repeat start end #<imm> */{"repeat",{A_DISP_PC,A_DISP_PC,A_IMM},{REPEAT,HEX_2,IMM0_8,HEX_8}, arch_sh_dsp_up}
+- shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_up}
+- shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_up}
++ shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
++ shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
+ shal r4 ;!/* 0100nnnn00100000 shal <REG_N> */{"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}, arch_sh_up}
+ shar r4 ;!/* 0100nnnn00100001 shar <REG_N> */{"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}, arch_sh_up}
+ shll r4 ;!/* 0100nnnn00000000 shll <REG_N> */{"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}, arch_sh_up}
+diff -Nur binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh3e.s binutils-2.42/gas/testsuite/gas/sh/arch/sh3e.s
+--- binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh3e.s 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/gas/testsuite/gas/sh/arch/sh3e.s 2024-02-22 16:50:03.689904606 +0100
+@@ -12,7 +12,7 @@
+ sh3e:
+ ! Instructions introduced into sh3e
+
+-! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-or-sh3e sh2e sh3 sh3-nommu
++! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh3-nommu-or-sh2j-nofpu sh2a-or-sh3e sh2e sh3 sh3-nommu
+ add #4,r4 ;!/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM0_8}, arch_sh_up}
+ add r5,r4 ;!/* 0011nnnnmmmm1100 add <REG_M>,<REG_N> */{"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}, arch_sh_up}
+ addc r5,r4 ;!/* 0011nnnnmmmm1110 addc <REG_M>,<REG_N>*/{"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}, arch_sh_up}
+@@ -132,8 +132,8 @@
+ rts ;!/* 0000000000001011 rts */{"rts",{0},{HEX_0,HEX_0,HEX_0,HEX_B}, arch_sh_up}
+ sets ;!/* 0000000001011000 sets */{"sets",{0},{HEX_0,HEX_0,HEX_5,HEX_8}, arch_sh3_nommu_up}
+ sett ;!/* 0000000000011000 sett */{"sett",{0},{HEX_0,HEX_0,HEX_1,HEX_8}, arch_sh_up}
+- shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_up}
+- shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_up}
++ shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
++ shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
+ shal r4 ;!/* 0100nnnn00100000 shal <REG_N> */{"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}, arch_sh_up}
+ shar r4 ;!/* 0100nnnn00100001 shar <REG_N> */{"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}, arch_sh_up}
+ shll r4 ;!/* 0100nnnn00000000 shll <REG_N> */{"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}, arch_sh_up}
+diff -Nur binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh3-nommu.s binutils-2.42/gas/testsuite/gas/sh/arch/sh3-nommu.s
+--- binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh3-nommu.s 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/gas/testsuite/gas/sh/arch/sh3-nommu.s 2024-02-22 16:50:03.689904606 +0100
+@@ -26,7 +26,7 @@
+ stc.l SPC,@-r4 ;!/* 0100nnnn01000011 stc.l SPC,@-<REG_N> */{"stc.l",{A_SPC,A_DEC_N},{HEX_4,REG_N,HEX_4,HEX_3}, arch_sh3_nommu_up}
+ stc.l r1_bank,@-r4 ;!/* 0100nnnn1xxx0011 stc.l Rn_BANK,@-<REG_N> */{"stc.l",{A_REG_B,A_DEC_N},{HEX_4,REG_N,REG_B,HEX_3}, arch_sh3_nommu_up}
+
+-! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu
++! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh3-nommu-or-sh2j-nofpu
+ add #4,r4 ;!/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM0_8}, arch_sh_up}
+ add r5,r4 ;!/* 0011nnnnmmmm1100 add <REG_M>,<REG_N> */{"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}, arch_sh_up}
+ addc r5,r4 ;!/* 0011nnnnmmmm1110 addc <REG_M>,<REG_N>*/{"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}, arch_sh_up}
+@@ -133,8 +133,8 @@
+ rte ;!/* 0000000000101011 rte */{"rte",{0},{HEX_0,HEX_0,HEX_2,HEX_B}, arch_sh_up}
+ rts ;!/* 0000000000001011 rts */{"rts",{0},{HEX_0,HEX_0,HEX_0,HEX_B}, arch_sh_up}
+ sett ;!/* 0000000000011000 sett */{"sett",{0},{HEX_0,HEX_0,HEX_1,HEX_8}, arch_sh_up}
+- shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_up}
+- shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_up}
++ shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
++ shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
+ shal r4 ;!/* 0100nnnn00100000 shal <REG_N> */{"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}, arch_sh_up}
+ shar r4 ;!/* 0100nnnn00100001 shar <REG_N> */{"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}, arch_sh_up}
+ shll r4 ;!/* 0100nnnn00000000 shll <REG_N> */{"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}, arch_sh_up}
+diff -Nur binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh3.s binutils-2.42/gas/testsuite/gas/sh/arch/sh3.s
+--- binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh3.s 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/gas/testsuite/gas/sh/arch/sh3.s 2024-02-22 16:50:03.689904606 +0100
+@@ -13,7 +13,7 @@
+ ! Instructions introduced into sh3
+ ldtlb ;!/* 0000000000111000 ldtlb */{"ldtlb",{0},{HEX_0,HEX_0,HEX_3,HEX_8}, arch_sh3_up}
+
+-! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh3-nommu
++! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh3-nommu-or-sh2j-nofpu sh3-nommu
+ add #4,r4 ;!/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM0_8}, arch_sh_up}
+ add r5,r4 ;!/* 0011nnnnmmmm1100 add <REG_M>,<REG_N> */{"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}, arch_sh_up}
+ addc r5,r4 ;!/* 0011nnnnmmmm1110 addc <REG_M>,<REG_N>*/{"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}, arch_sh_up}
+@@ -128,8 +128,8 @@
+ rts ;!/* 0000000000001011 rts */{"rts",{0},{HEX_0,HEX_0,HEX_0,HEX_B}, arch_sh_up}
+ sets ;!/* 0000000001011000 sets */{"sets",{0},{HEX_0,HEX_0,HEX_5,HEX_8}, arch_sh3_nommu_up}
+ sett ;!/* 0000000000011000 sett */{"sett",{0},{HEX_0,HEX_0,HEX_1,HEX_8}, arch_sh_up}
+- shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_up}
+- shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_up}
++ shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
++ shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
+ shal r4 ;!/* 0100nnnn00100000 shal <REG_N> */{"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}, arch_sh_up}
+ shar r4 ;!/* 0100nnnn00100001 shar <REG_N> */{"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}, arch_sh_up}
+ shll r4 ;!/* 0100nnnn00000000 shll <REG_N> */{"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}, arch_sh_up}
+diff -Nur binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh4al-dsp.s binutils-2.42/gas/testsuite/gas/sh/arch/sh4al-dsp.s
+--- binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh4al-dsp.s 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/gas/testsuite/gas/sh/arch/sh4al-dsp.s 2024-02-22 16:50:03.689904606 +0100
+@@ -48,7 +48,7 @@
+ dct pswap x1,m0 ;!/* 10011101xx01zzzz pswap <DSP_REG_X>,<DSP_REG_N> */ {"pswap", {DSP_REG_X,DSP_REG_N},{PPI,PPIC,HEX_9,HEX_D,HEX_1}, arch_sh4al_dsp_up}
+ dct pswap y0,m0 ;!/* 1011110101yyzzzz pswap <DSP_REG_Y>,<DSP_REG_N> */ {"pswap", {DSP_REG_Y,DSP_REG_N},{PPI,PPIC,HEX_B,HEX_D,HEX_4}, arch_sh4al_dsp_up}
+
+-! Instructions inherited from ancestors: sh sh-dsp sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh4-nommu-nofpu sh3 sh3-dsp sh3-nommu sh4-nofpu sh4-nommu-nofpu sh4a-nofpu
++! Instructions inherited from ancestors: sh sh-dsp sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh3-nommu-or-sh2j-nofpu sh2a-nofpu-or-sh4-nommu-nofpu sh3 sh3-dsp sh3-nommu sh4-nofpu sh4-nommu-nofpu sh4a-nofpu
+ add #4,r4 ;!/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM0_8}, arch_sh_up}
+ add r5,r4 ;!/* 0011nnnnmmmm1100 add <REG_M>,<REG_N> */{"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}, arch_sh_up}
+ addc r5,r4 ;!/* 0011nnnnmmmm1110 addc <REG_M>,<REG_N>*/{"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}, arch_sh_up}
+@@ -202,8 +202,8 @@
+ setrc #4 ;!/* 10000010i8*1.... setrc #<imm> */{"setrc",{A_IMM},{HEX_8,HEX_2,IMM0_8}, arch_sh_dsp_up}
+ repeat 10 20 r4 ;!/* repeat start end <REG_N> */{"repeat",{A_DISP_PC,A_DISP_PC,A_REG_N},{REPEAT,REG_N,HEX_1,HEX_4}, arch_sh_dsp_up}
+ repeat 10 20 #4 ;!/* repeat start end #<imm> */{"repeat",{A_DISP_PC,A_DISP_PC,A_IMM},{REPEAT,HEX_2,IMM0_8,HEX_8}, arch_sh_dsp_up}
+- shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_up}
+- shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_up}
++ shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
++ shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
+ shal r4 ;!/* 0100nnnn00100000 shal <REG_N> */{"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}, arch_sh_up}
+ shar r4 ;!/* 0100nnnn00100001 shar <REG_N> */{"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}, arch_sh_up}
+ shll r4 ;!/* 0100nnnn00000000 shll <REG_N> */{"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}, arch_sh_up}
+diff -Nur binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh4a-nofpu.s binutils-2.42/gas/testsuite/gas/sh/arch/sh4a-nofpu.s
+--- binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh4a-nofpu.s 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/gas/testsuite/gas/sh/arch/sh4a-nofpu.s 2024-02-22 16:50:03.693904638 +0100
+@@ -19,7 +19,7 @@
+ prefi @r4 ;!/* 0000nnnn11010011 prefi @<REG_N> */{"prefi",{A_IND_N},{HEX_0,REG_N,HEX_D,HEX_3}, arch_sh4a_nofpu_up}
+ synco ;!/* 0000000010101011 synco */{"synco",{0},{HEX_0,HEX_0,HEX_A,HEX_B}, arch_sh4a_nofpu_up}
+
+-! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh4-nommu-nofpu sh3 sh3-nommu sh4-nofpu sh4-nommu-nofpu
++! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh3-nommu-or-sh2j-nofpu sh2a-nofpu-or-sh4-nommu-nofpu sh3 sh3-nommu sh4-nofpu sh4-nommu-nofpu
+ add #4,r4 ;!/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM0_8}, arch_sh_up}
+ add r5,r4 ;!/* 0011nnnnmmmm1100 add <REG_M>,<REG_N> */{"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}, arch_sh_up}
+ addc r5,r4 ;!/* 0011nnnnmmmm1110 addc <REG_M>,<REG_N>*/{"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}, arch_sh_up}
+@@ -143,8 +143,8 @@
+ rts ;!/* 0000000000001011 rts */{"rts",{0},{HEX_0,HEX_0,HEX_0,HEX_B}, arch_sh_up}
+ sets ;!/* 0000000001011000 sets */{"sets",{0},{HEX_0,HEX_0,HEX_5,HEX_8}, arch_sh3_nommu_up}
+ sett ;!/* 0000000000011000 sett */{"sett",{0},{HEX_0,HEX_0,HEX_1,HEX_8}, arch_sh_up}
+- shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_up}
+- shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_up}
++ shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
++ shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
+ shal r4 ;!/* 0100nnnn00100000 shal <REG_N> */{"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}, arch_sh_up}
+ shar r4 ;!/* 0100nnnn00100001 shar <REG_N> */{"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}, arch_sh_up}
+ shll r4 ;!/* 0100nnnn00000000 shll <REG_N> */{"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}, arch_sh_up}
+diff -Nur binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh4a.s binutils-2.42/gas/testsuite/gas/sh/arch/sh4a.s
+--- binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh4a.s 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/gas/testsuite/gas/sh/arch/sh4a.s 2024-02-22 16:50:03.693904638 +0100
+@@ -13,7 +13,7 @@
+ ! Instructions introduced into sh4a
+ fpchg ;!/* 1111011111111101 fpchg */{"fpchg",{0},{HEX_F,HEX_7,HEX_F,HEX_D}, arch_sh4a_up}
+
+-! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh4-nommu-nofpu sh2a-or-sh3e sh2a-or-sh4 sh2e sh3 sh3-nommu sh3e sh4 sh4-nofpu sh4-nommu-nofpu sh4a-nofpu
++! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh3-nommu-or-sh2j-nofpu sh2a-nofpu-or-sh4-nommu-nofpu sh2a-or-sh3e sh2a-or-sh4 sh2e sh3 sh3-nommu sh3e sh4 sh4-nofpu sh4-nommu-nofpu sh4a-nofpu
+ add #4,r4 ;!/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM0_8}, arch_sh_up}
+ add r5,r4 ;!/* 0011nnnnmmmm1100 add <REG_M>,<REG_N> */{"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}, arch_sh_up}
+ addc r5,r4 ;!/* 0011nnnnmmmm1110 addc <REG_M>,<REG_N>*/{"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}, arch_sh_up}
+@@ -147,8 +147,8 @@
+ rts ;!/* 0000000000001011 rts */{"rts",{0},{HEX_0,HEX_0,HEX_0,HEX_B}, arch_sh_up}
+ sets ;!/* 0000000001011000 sets */{"sets",{0},{HEX_0,HEX_0,HEX_5,HEX_8}, arch_sh3_nommu_up}
+ sett ;!/* 0000000000011000 sett */{"sett",{0},{HEX_0,HEX_0,HEX_1,HEX_8}, arch_sh_up}
+- shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_up}
+- shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_up}
++ shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
++ shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
+ shal r4 ;!/* 0100nnnn00100000 shal <REG_N> */{"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}, arch_sh_up}
+ shar r4 ;!/* 0100nnnn00100001 shar <REG_N> */{"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}, arch_sh_up}
+ shll r4 ;!/* 0100nnnn00000000 shll <REG_N> */{"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}, arch_sh_up}
+diff -Nur binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh4-nofpu.s binutils-2.42/gas/testsuite/gas/sh/arch/sh4-nofpu.s
+--- binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh4-nofpu.s 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/gas/testsuite/gas/sh/arch/sh4-nofpu.s 2024-02-22 16:50:03.693904638 +0100
+@@ -12,7 +12,7 @@
+ sh4_nofpu:
+ ! Instructions introduced into sh4-nofpu
+
+-! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh4-nommu-nofpu sh3 sh3-nommu sh4-nommu-nofpu
++! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh3-nommu-or-sh2j-nofpu sh2a-nofpu-or-sh4-nommu-nofpu sh3 sh3-nommu sh4-nommu-nofpu
+ add #4,r4 ;!/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM0_8}, arch_sh_up}
+ add r5,r4 ;!/* 0011nnnnmmmm1100 add <REG_M>,<REG_N> */{"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}, arch_sh_up}
+ addc r5,r4 ;!/* 0011nnnnmmmm1110 addc <REG_M>,<REG_N>*/{"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}, arch_sh_up}
+@@ -136,8 +136,8 @@
+ rts ;!/* 0000000000001011 rts */{"rts",{0},{HEX_0,HEX_0,HEX_0,HEX_B}, arch_sh_up}
+ sets ;!/* 0000000001011000 sets */{"sets",{0},{HEX_0,HEX_0,HEX_5,HEX_8}, arch_sh3_nommu_up}
+ sett ;!/* 0000000000011000 sett */{"sett",{0},{HEX_0,HEX_0,HEX_1,HEX_8}, arch_sh_up}
+- shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_up}
+- shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_up}
++ shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
++ shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
+ shal r4 ;!/* 0100nnnn00100000 shal <REG_N> */{"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}, arch_sh_up}
+ shar r4 ;!/* 0100nnnn00100001 shar <REG_N> */{"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}, arch_sh_up}
+ shll r4 ;!/* 0100nnnn00000000 shll <REG_N> */{"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}, arch_sh_up}
+diff -Nur binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh4-nommu-nofpu.s binutils-2.42/gas/testsuite/gas/sh/arch/sh4-nommu-nofpu.s
+--- binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh4-nommu-nofpu.s 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/gas/testsuite/gas/sh/arch/sh4-nommu-nofpu.s 2024-02-22 16:50:03.693904638 +0100
+@@ -24,7 +24,7 @@
+ stc.l SGR,@-r4 ;!/* 0100nnnn00110010 stc.l SGR,@-<REG_N> */{"stc.l",{A_SGR,A_DEC_N},{HEX_4,REG_N,HEX_3,HEX_2}, arch_sh4_nommu_nofpu_up}
+ stc.l DBR,@-r4 ;!/* 0100nnnn11110010 stc.l DBR,@-<REG_N> */{"stc.l",{A_DBR,A_DEC_N},{HEX_4,REG_N,HEX_F,HEX_2}, arch_sh4_nommu_nofpu_up}
+
+-! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh4-nommu-nofpu sh3-nommu
++! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh3-nommu-or-sh2j-nofpu sh2a-nofpu-or-sh4-nommu-nofpu sh3-nommu
+ add #4,r4 ;!/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM0_8}, arch_sh_up}
+ add r5,r4 ;!/* 0011nnnnmmmm1100 add <REG_M>,<REG_N> */{"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}, arch_sh_up}
+ addc r5,r4 ;!/* 0011nnnnmmmm1110 addc <REG_M>,<REG_N>*/{"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}, arch_sh_up}
+@@ -139,8 +139,8 @@
+ rts ;!/* 0000000000001011 rts */{"rts",{0},{HEX_0,HEX_0,HEX_0,HEX_B}, arch_sh_up}
+ sets ;!/* 0000000001011000 sets */{"sets",{0},{HEX_0,HEX_0,HEX_5,HEX_8}, arch_sh3_nommu_up}
+ sett ;!/* 0000000000011000 sett */{"sett",{0},{HEX_0,HEX_0,HEX_1,HEX_8}, arch_sh_up}
+- shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_up}
+- shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_up}
++ shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
++ shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
+ shal r4 ;!/* 0100nnnn00100000 shal <REG_N> */{"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}, arch_sh_up}
+ shar r4 ;!/* 0100nnnn00100001 shar <REG_N> */{"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}, arch_sh_up}
+ shll r4 ;!/* 0100nnnn00000000 shll <REG_N> */{"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}, arch_sh_up}
+diff -Nur binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh4.s binutils-2.42/gas/testsuite/gas/sh/arch/sh4.s
+--- binutils-2.42.orig/gas/testsuite/gas/sh/arch/sh4.s 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/gas/testsuite/gas/sh/arch/sh4.s 2024-02-22 16:50:03.693904638 +0100
+@@ -17,7 +17,7 @@
+ fsrra fr1 ;!/* 1111nnnn01111101 fsrra <F_REG_N> */{"fsrra",{F_REG_N},{HEX_F,REG_N,HEX_7,HEX_D}, arch_sh4_up}
+ ftrv xmtrx,fv0 ;!/* 1111nn0111111101 ftrv XMTRX_M4,<V_REG_n>*/{"ftrv",{XMTRX_M4,V_REG_N},{HEX_F,REG_N_B01,HEX_F,HEX_D}, arch_sh4_up}
+
+-! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh4-nommu-nofpu sh2a-or-sh3e sh2a-or-sh4 sh2e sh3 sh3-nommu sh3e sh4-nofpu sh4-nommu-nofpu
++! Instructions inherited from ancestors: sh sh2 sh2a-nofpu-or-sh3-nommu sh2a-nofpu-or-sh3-nommu-or-sh2j-nofpu sh2a-nofpu-or-sh4-nommu-nofpu sh2a-or-sh3e sh2a-or-sh4 sh2e sh3 sh3-nommu sh3e sh4-nofpu sh4-nommu-nofpu
+ add #4,r4 ;!/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM0_8}, arch_sh_up}
+ add r5,r4 ;!/* 0011nnnnmmmm1100 add <REG_M>,<REG_N> */{"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}, arch_sh_up}
+ addc r5,r4 ;!/* 0011nnnnmmmm1110 addc <REG_M>,<REG_N>*/{"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}, arch_sh_up}
+@@ -145,8 +145,8 @@
+ rts ;!/* 0000000000001011 rts */{"rts",{0},{HEX_0,HEX_0,HEX_0,HEX_B}, arch_sh_up}
+ sets ;!/* 0000000001011000 sets */{"sets",{0},{HEX_0,HEX_0,HEX_5,HEX_8}, arch_sh3_nommu_up}
+ sett ;!/* 0000000000011000 sett */{"sett",{0},{HEX_0,HEX_0,HEX_1,HEX_8}, arch_sh_up}
+- shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_up}
+- shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_up}
++ shad r5,r4 ;!/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
++ shld r5,r4 ;!/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_or_sh2j_nofpu_up}
+ shal r4 ;!/* 0100nnnn00100000 shal <REG_N> */{"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}, arch_sh_up}
+ shar r4 ;!/* 0100nnnn00100001 shar <REG_N> */{"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}, arch_sh_up}
+ shll r4 ;!/* 0100nnnn00000000 shll <REG_N> */{"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}, arch_sh_up}
+diff -Nur binutils-2.42.orig/include/elf/sh.h binutils-2.42/include/elf/sh.h
+--- binutils-2.42.orig/include/elf/sh.h 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/include/elf/sh.h 2024-02-22 16:50:03.693904638 +0100
+@@ -39,6 +39,7 @@
+ #define EF_SH2E 11
+ #define EF_SH4A 12
+ #define EF_SH2A 13
++#define EF_SHJ2 14
+
+ #define EF_SH4_NOFPU 16
+ #define EF_SH4A_NOFPU 17
+@@ -50,6 +51,7 @@
+ #define EF_SH2A_SH3_NOFPU 22
+ #define EF_SH2A_SH4 23
+ #define EF_SH2A_SH3E 24
++#define EF_SH2A_SH3_SHJ2 25
+
+ /* This one can only mix in objects from other EF_SH5 objects. */
+ #define EF_SH5 10
+@@ -72,7 +74,8 @@
+ /* EF_SH2E */ bfd_mach_sh2e , \
+ /* EF_SH4A */ bfd_mach_sh4a , \
+ /* EF_SH2A */ bfd_mach_sh2a , \
+-/* 14, 15 */ 0, 0, \
++/* EF_SHJ2 */ bfd_mach_shj2 , \
++/* 15 */ 0, \
+ /* EF_SH4_NOFPU */ bfd_mach_sh4_nofpu , \
+ /* EF_SH4A_NOFPU */ bfd_mach_sh4a_nofpu , \
+ /* EF_SH4_NOMMU_NOFPU */ bfd_mach_sh4_nommu_nofpu, \
+@@ -81,7 +84,8 @@
+ /* EF_SH2A_SH4_NOFPU */ bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu, \
+ /* EF_SH2A_SH3_NOFPU */ bfd_mach_sh2a_nofpu_or_sh3_nommu, \
+ /* EF_SH2A_SH4 */ bfd_mach_sh2a_or_sh4 , \
+-/* EF_SH2A_SH3E */ bfd_mach_sh2a_or_sh3e
++/* EF_SH2A_SH3E */ bfd_mach_sh2a_or_sh3e, \
++/* EF_SH2A_SH3_SHJ2_NOFPU */ bfd_mach_sh2a_nofpu_or_sh3_nommu_or_shj2_nofpu
+
+ /* Convert arch_sh* into EF_SH*. */
+ int sh_find_elf_flags (unsigned int arch_set);
+diff -Nur binutils-2.42.orig/opcodes/sh-dis.c binutils-2.42/opcodes/sh-dis.c
+--- binutils-2.42.orig/opcodes/sh-dis.c 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/opcodes/sh-dis.c 2024-02-22 16:50:03.693904638 +0100
+@@ -866,6 +866,9 @@
+ case XMTRX_M4:
+ fprintf_fn (stream, "xmtrx");
+ break;
++ case A_IND_0:
++ fprintf_fn (stream, "@r0");
++ break;
+ default:
+ abort ();
+ }
+diff -Nur binutils-2.42.orig/opcodes/sh-opc.h binutils-2.42/opcodes/sh-opc.h
+--- binutils-2.42.orig/opcodes/sh-opc.h 2024-01-29 01:00:00.000000000 +0100
++++ binutils-2.42/opcodes/sh-opc.h 2024-02-22 16:50:03.697904670 +0100
+@@ -192,7 +192,8 @@
+ FPUL_N,
+ FPUL_M,
+ FPSCR_N,
+- FPSCR_M
++ FPSCR_M,
++ A_IND_0
+ }
+ sh_arg_type;
+
+@@ -216,9 +217,11 @@
+ #define arch_sh4_base (1 << 5)
+ #define arch_sh4a_base (1 << 6)
+ #define arch_sh2a_base (1 << 7)
+-#define arch_sh_base_mask MASK (0, 7)
++#define arch_shj2_base (1 << 8)
++#define arch_sh2a_sh3_shj2_base (1 << 9)
++#define arch_sh_base_mask MASK (0, 9)
+
+-/* Bits 8 ... 24 are currently free. */
++/* Bits 10 ... 24 are currently free. */
+
+ /* This is an annotation on instruction types, but we
+ abuse the arch field in instructions to denote it. */
+@@ -256,6 +259,8 @@
+ #define arch_sh2a_nofpu_or_sh3_nommu (arch_sh2a_sh3_base|arch_sh_no_mmu |arch_sh_no_co)
+ #define arch_sh2a_or_sh3e (arch_sh2a_sh4_base|arch_sh_no_mmu |arch_sh_sp_fpu)
+ #define arch_sh2a_or_sh4 (arch_sh2a_sh4_base|arch_sh_no_mmu |arch_sh_dp_fpu)
++#define arch_shj2 (arch_shj2_base |arch_sh_no_mmu |arch_sh_no_co)
++#define arch_sh2a_nofpu_or_sh3_nommu_or_shj2_nofpu (arch_sh2a_sh3_shj2_base|arch_sh_no_mmu |arch_sh_no_co)
+
+ #define SH_MERGE_ARCH_SET(SET1, SET2) ((SET1) & (SET2))
+ #define SH_VALID_BASE_ARCH_SET(SET) (((SET) & arch_sh_base_mask) != 0)
+@@ -320,7 +325,8 @@
+ #define arch_sh2_up (arch_sh2 \
+ | arch_sh2e_up \
+ | arch_sh2a_nofpu_or_sh3_nommu_up \
+- | arch_sh_dsp_up)
++ | arch_sh_dsp_up \
++ | arch_shj2_up)
+ #define arch_sh2a_nofpu_or_sh3_nommu_up (arch_sh2a_nofpu_or_sh3_nommu \
+ | arch_sh2a_nofpu_or_sh4_nommu_nofpu_up \
+ | arch_sh2a_or_sh3e_up \
+@@ -346,6 +352,12 @@
+ #define arch_sh4a_nofpu_up (arch_sh4a_nofpu \
+ | arch_sh4a_up \
+ | arch_sh4al_dsp_up)
++#define arch_shj2_up ( arch_shj2)
++#define arch_sh2a_nofpu_or_sh3_nommu_or_shj2_nofpu_up (arch_sh2a_nofpu_or_sh3_nommu \
++ | arch_sh2a_nofpu_or_sh4_nommu_nofpu_up \
++ | arch_sh2a_or_sh3e_up \
++ | arch_sh3_nommu_up \
++ | arch_shj2_up)
+
+ /* Right branches. */
+ #define arch_sh2e_up (arch_sh2e \
+@@ -714,9 +726,9 @@
+
+ /* repeat start end #<imm> */{"repeat",{A_DISP_PC,A_DISP_PC,A_IMM},{REPEAT,HEX_2,IMM0_8S,HEX_8}, arch_sh_dsp_up},
+
+-/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_up},
++/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}, arch_sh2a_nofpu_or_sh3_nommu_or_shj2_nofpu_up},
+
+-/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_up},
++/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}, arch_sh2a_nofpu_or_sh3_nommu_or_shj2_nofpu_up},
+
+ /* 0100nnnn00100000 shal <REG_N> */{"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}, arch_sh_up},
+
+@@ -1194,7 +1206,7 @@
+ {"movu.b",{A_DISP_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_1,HEX_8,DISP0_12}, arch_sh2a_nofpu_up | arch_op32},
+ /* 0011nnnnmmmm0001 1001dddddddddddd movu.w @(<DISP12>,<REG_M>),<REG_N> */
+ {"movu.w",{A_DISP_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_1,HEX_9,DISP0_12BY2}, arch_sh2a_nofpu_up | arch_op32},
+-
++ /* 0010nnnnmmmm0011 cas.l Rm,Rn,@R0 */ {"cas.l", { A_REG_M,A_REG_N,A_IND_0},{HEX_2,REG_N,REG_M,HEX_3}, arch_shj2_up},
+ { 0, {0}, {0}, 0 }
+ };
+
diff --git a/toolchain/binutils/patches/2.42/kvx.patch b/toolchain/binutils/patches/2.42/kvx.patch
new file mode 100644
index 000000000..c3690ca8e
--- /dev/null
+++ b/toolchain/binutils/patches/2.42/kvx.patch
@@ -0,0 +1,29 @@
+From 234938d8b7df2f069c6cbbaff47eb2ba338ec532 Mon Sep 17 00:00:00 2001
+From: Paul Iannetta <piannetta@kalrayinc.com>
+Date: Mon, 4 Sep 2023 15:31:53 +0200
+Subject: [PATCH] kvx: gas: fix the detection of negative powers of 2
+
+gas/ChangeLog:
+
+2023-09-04 Paul Iannetta <piannetta@kalrayinc.com>
+
+ * config/kvx-parse.c (get_token_class): Use the signed value.
+
+---
+ gas/config/kvx-parse.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gas/config/kvx-parse.c b/gas/config/kvx-parse.c
+index bb51c861625..0bd6b75ef30 100644
+--- a/gas/config/kvx-parse.c
++++ b/gas/config/kvx-parse.c
+@@ -525,7 +525,7 @@ get_token_class (struct token_s *token, struct token_classes *classes, int insn_
+ : strtoull (tok + (tok[0] == '-') + (tok[0] == '+'), NULL, 0));
+ int64_t val = uval;
+ int64_t pval = val < 0 ? -uval : uval;
+- int neg_power2_p = val < 0 && !(uval & (uval - 1));
++ int neg_power2_p = val < 0 && !(pval & (pval - 1));
+ unsigned len = pval ? 8 * sizeof (pval) - __builtin_clzll (pval) : 0;
+ while (class[cur].class_id != -1
+ && ((unsigned) (class[cur].sz < 0
+
diff --git a/toolchain/elf2flt/Makefile b/toolchain/elf2flt/Makefile
index c258ff082..8e5fec5a4 100644
--- a/toolchain/elf2flt/Makefile
+++ b/toolchain/elf2flt/Makefile
@@ -8,23 +8,38 @@ include $(ADK_TOPDIR)/mk/buildhlp.mk
ifeq ($(ADK_TOOLCHAIN_BINUTILS_GIT),y)
BINUTILS_VERSION:= git
+BFDLIB:= .libs/libbfd.a
endif
-ifeq ($(ADK_TOOLCHAIN_BINUTILS_2_37),y)
-BINUTILS_VERSION:= 2.37
+ifeq ($(ADK_TOOLCHAIN_BINUTILS_2_42),y)
+BINUTILS_VERSION:= 2.42
+BFDLIB:= .libs/libbfd.a
+endif
+ifeq ($(ADK_TOOLCHAIN_BINUTILS_2_41),y)
+BINUTILS_VERSION:= 2.41
+BFDLIB:= .libs/libbfd.a
+endif
+ifeq ($(ADK_TOOLCHAIN_BINUTILS_2_40),y)
+BINUTILS_VERSION:= 2.40
+BFDLIB:= libbfd.a
+endif
+ifeq ($(ADK_TOOLCHAIN_BINUTILS_2_39),y)
+BINUTILS_VERSION:= 2.39
+BFDLIB:= libbfd.a
endif
ifeq ($(ADK_TOOLCHAIN_BINUTILS_2_28),y)
BINUTILS_VERSION:= 2.28
+BFDLIB:= libbfd.a
endif
$(WRKBUILD)/.configured:
- (cd $(WRKBUILD); autoreconf -vif;)
+ (cd $(WRKBUILD); PATH='${HOST_PATH}' autoreconf -vif;)
(cd $(WRKBUILD); \
CPPFLAGS="-idirafter $(ADK_TOPDIR)/adk/include" \
./configure --prefix=$(STAGING_HOST_DIR)/usr \
--target=$(GNU_TARGET_NAME) \
--with-bfd-include-dir=$(TOOLCHAIN_BUILD_DIR)/w-binutils-$(BINUTILS_VERSION)-1/binutils-$(BINUTILS_VERSION)/bfd \
--with-binutils-include-dir=$(TOOLCHAIN_BUILD_DIR)/w-binutils-$(BINUTILS_VERSION)-1/binutils-$(BINUTILS_VERSION)/include \
- --with-libbfd=$(TOOLCHAIN_BUILD_DIR)/w-binutils-$(BINUTILS_VERSION)-1/binutils-$(BINUTILS_VERSION)/bfd/libbfd.a \
+ --with-libbfd=$(TOOLCHAIN_BUILD_DIR)/w-binutils-$(BINUTILS_VERSION)-1/binutils-$(BINUTILS_VERSION)/bfd/$(BFDLIB) \
--with-libiberty=$(TOOLCHAIN_BUILD_DIR)/w-binutils-$(BINUTILS_VERSION)-1/binutils-$(BINUTILS_VERSION)/libiberty/libiberty.a )
touch $@
diff --git a/toolchain/elf2flt/Makefile.inc b/toolchain/elf2flt/Makefile.inc
index 15434aeee..dee90e037 100644
--- a/toolchain/elf2flt/Makefile.inc
+++ b/toolchain/elf2flt/Makefile.inc
@@ -2,7 +2,16 @@
# material, please see the LICENCE file in the top-level directory.
PKG_NAME:= elf2flt
+ifeq ($(ADK_TOOLCHAIN_ELF2FLT_2024_02),y)
+PKG_VERSION:= v2024.02
+PKG_GIT:= tag
+PKG_RELEASE:= 1
+PKG_SITES:= https://github.com/uclinux-dev/elf2flt.git
+endif
+ifeq ($(ADK_TOOLCHAIN_ELF2FLT_OLD),y)
PKG_VERSION:= 453398f917d167f8c308c8f997270c48ae8f8b12
PKG_GIT:= hash
PKG_RELEASE:= 1
PKG_SITES:= https://github.com/uclinux-dev/elf2flt.git
+endif
+DISTFILES:= $(PKG_NAME)-$(PKG_VERSION).tar.gz
diff --git a/toolchain/elf2flt/patches/26dfb54a59c8c0106418a0c46ccb4288d9e066fd/0001-riscv32.patch b/toolchain/elf2flt/patches/26dfb54a59c8c0106418a0c46ccb4288d9e066fd/0001-riscv32.patch
new file mode 100644
index 000000000..a99de4f9f
--- /dev/null
+++ b/toolchain/elf2flt/patches/26dfb54a59c8c0106418a0c46ccb4288d9e066fd/0001-riscv32.patch
@@ -0,0 +1,42 @@
+diff -Nur elf2flt-v2023.04.orig/elf2flt.c elf2flt-v2023.04/elf2flt.c
+--- elf2flt-v2023.04.orig/elf2flt.c 2023-09-04 11:29:05.952417209 +0200
++++ elf2flt-v2023.04/elf2flt.c 2023-09-04 11:30:05.371065966 +0200
+@@ -81,7 +81,7 @@
+ #include <elf/v850.h>
+ #elif defined(TARGET_xtensa)
+ #include <elf/xtensa.h>
+-#elif defined(TARGET_riscv64)
++#elif defined(TARGET_riscv64) || defined(TARGET_riscv32)
+ #include <elf/riscv.h>
+ #endif
+
+@@ -127,6 +127,8 @@
+ #define ARCH "xtensa"
+ #elif defined(TARGET_riscv64)
+ #define ARCH "riscv64"
++#elif defined(TARGET_riscv32)
++#define ARCH "riscv32"
+ #else
+ #error "Don't know how to support your CPU architecture??"
+ #endif
+@@ -822,7 +824,7 @@
+ goto good_32bit_resolved_reloc_update_text;
+ default:
+ goto bad_resolved_reloc;
+-#elif defined(TARGET_riscv64)
++#elif defined(TARGET_riscv64) || defined(TARGET_riscv32)
+ case R_RISCV_NONE:
+ case R_RISCV_32_PCREL:
+ case R_RISCV_ADD8:
+diff -Nur elf2flt-v2023.04.orig/ld-elf2flt.c elf2flt-v2023.04/ld-elf2flt.c
+--- elf2flt-v2023.04.orig/ld-elf2flt.c 2023-09-04 11:28:59.072573514 +0200
++++ elf2flt-v2023.04/ld-elf2flt.c 2023-09-04 11:29:32.507813592 +0200
+@@ -327,7 +327,7 @@
+ /* riscv adds a global pointer symbol to the linker file with the
+ "RISCV_GP:" prefix. Remove the prefix for riscv64 architecture and
+ the entire line for other architectures. */
+- if (streq(TARGET_CPU, "riscv64"))
++ if (streq(TARGET_CPU, "riscv64") || streq(TARGET_CPU, "riscv32"))
+ append_sed(&sed, "^RISCV_GP:", "");
+ else
+ append_sed(&sed, "^RISCV_GP:", NULL);
diff --git a/toolchain/elf2flt/patches/26dfb54a59c8c0106418a0c46ccb4288d9e066fd/0002-lm32.patch b/toolchain/elf2flt/patches/26dfb54a59c8c0106418a0c46ccb4288d9e066fd/0002-lm32.patch
new file mode 100644
index 000000000..b24b214c7
--- /dev/null
+++ b/toolchain/elf2flt/patches/26dfb54a59c8c0106418a0c46ccb4288d9e066fd/0002-lm32.patch
@@ -0,0 +1,167 @@
+diff -Nur elf2flt.orig/elf2flt.c elf2flt/elf2flt.c
+--- elf2flt.orig/elf2flt.c 2023-09-07 15:59:10.019349031 +0200
++++ elf2flt/elf2flt.c 2023-09-07 16:40:06.281961316 +0200
+@@ -62,6 +62,8 @@
+ #include <elf/bfin.h>
+ #elif defined(TARGET_h8300)
+ #include <elf/h8.h>
++#elif defined(TARGET_lm32)
++#include <elf/lm32.h>
+ #elif defined(TARGET_m68k)
+ #include <elf/m68k.h>
+ #elif defined(TARGET_microblaze)
+@@ -123,6 +125,11 @@
+ #define ARCH "nios"
+ #elif defined(TARGET_nios2)
+ #define ARCH "nios2"
++#elif defined(TARGET_lm32)
++#define ARCH "lm32"
++#define FLAT_LM32_RELOC_TYPE_32_BIT 0
++#define FLAT_LM32_RELOC_TYPE_HI16_BIT 1
++#define FLAT_LM32_RELOC_TYPE_LO16_BIT 2
+ #elif defined(TARGET_xtensa)
+ #define ARCH "xtensa"
+ #elif defined(TARGET_riscv64)
+@@ -373,7 +380,7 @@
+ int bad_relocs = 0;
+ asymbol **symb;
+ long nsymb;
+-#ifdef TARGET_bfin
++#if defined (TARGET_bfin) || defined (TARGET_lm32)
+ unsigned long persistent_data = 0;
+ #endif
+
+@@ -690,6 +697,36 @@
+ break;
+ default:
+ goto bad_resolved_reloc;
++#elif defined(TARGET_lm32)
++ case R_LM32_HI16:
++ case R_LM32_LO16:
++ if (q->howto->type == R_LM32_HI16) {
++ pflags = FLAT_LM32_RELOC_TYPE_HI16_BIT << 29;
++ } else {
++ pflags = FLAT_LM32_RELOC_TYPE_LO16_BIT << 29;
++ }
++
++ relocation_needed = 1;
++
++ /* remember the upper 16 bits */
++ if ((0xffff0000 & sym_addr) != persistent_data) {
++ flat_relocs = (uint32_t *)
++ (realloc (flat_relocs, (flat_reloc_count + 1) * sizeof (uint32_t)));
++ if (verbose)
++ printf ("New persistent data for %08lx\n", sym_addr);
++ persistent_data = 0xffff0000 & sym_addr;
++ flat_relocs[flat_reloc_count++] = (sym_addr >> 16) | (3 << 29);
++ }
++ break;
++ case R_LM32_32:
++ pflags = FLAT_LM32_RELOC_TYPE_32_BIT << 29;
++ relocation_needed = 1;
++ break;
++ case R_LM32_CALL:
++ relocation_needed = 0;
++ break;
++ default:
++ goto bad_resolved_reloc;
+ #elif defined(TARGET_m68k)
+ case R_68K_32:
+ goto good_32bit_resolved_reloc;
+@@ -1478,6 +1515,63 @@
+ #undef _30BITS_RELOC
+ #undef _28BITS_RELOC
+ #endif
++#ifdef TARGET_lm32
++ case R_LM32_32:
++ {
++ pflags = FLAT_LM32_RELOC_TYPE_32_BIT << 29;
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
++ sym_addr += sym_vma + q->addend;
++ relocation_needed = 1;
++ break;
++ }
++ case R_LM32_CALL:
++ {
++ sym_vma = 0;
++ sym_addr += sym_vma + q->addend;
++ sym_addr -= q->address;
++ sym_addr = (int32_t)sym_addr >> q->howto->rightshift;
++
++ if ((int32_t)sym_addr < -0x8000000 || (int32_t)sym_addr > 0x7ffffff) {
++ printf("ERROR: Relocation overflow for R_LM32_CALL relocation against %s\n", sym_name);
++ bad_relocs++;
++ continue;
++ }
++
++ r_mem[0] |= (sym_addr >> 24) & 0x03;
++ r_mem[1] = (sym_addr >> 16) & 0xff;
++ r_mem[2] = (sym_addr >> 8) & 0xff;
++ r_mem[3] = sym_addr & 0xff;
++ break;
++ }
++ case R_LM32_HI16:
++ case R_LM32_LO16:
++ {
++ if (q->howto->type == R_LM32_HI16) {
++ pflags = FLAT_LM32_RELOC_TYPE_HI16_BIT << 29;
++ } else {
++ pflags = FLAT_LM32_RELOC_TYPE_LO16_BIT << 29;
++ }
++
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
++ sym_addr += sym_vma + q->addend;
++
++ relocation_needed = 1;
++
++ /* remember the upper 16 bits */
++ if ((0xffff0000 & sym_addr) != persistent_data) {
++ flat_relocs = (uint32_t *)
++ (realloc (flat_relocs, (flat_reloc_count + 1) * sizeof (uint32_t)));
++ if (verbose)
++ printf ("New persistent data for %08lx\n", sym_addr);
++ persistent_data = 0xffff0000 & sym_addr;
++ flat_relocs[flat_reloc_count++] = (sym_addr >> 16) | (3 << 29);
++ }
++
++ r_mem[2] = (sym_addr >> 8) & 0xff;
++ r_mem[3] = sym_addr & 0xff;
++ break;
++ }
++#endif /* TARGET_lm32 */
+ default:
+ /* missing support for other types of relocs */
+ printf("ERROR: bad reloc type (%s)%d\n", q->howto->name, (*p)->howto->type);
+@@ -1616,6 +1710,13 @@
+ break;
+ #endif
+
++#ifdef TARGET_lm32
++ case R_LM32_HI16:
++ case R_LM32_LO16:
++ case R_LM32_CALL:
++ /* entry has already been written */
++ break;
++#endif
+ default:
+ /* The alignment of the build host
+ might be stricter than that of the
+diff -Nur elf2flt.orig/elf2flt.ld.in elf2flt/elf2flt.ld.in
+--- elf2flt.orig/elf2flt.ld.in 2023-09-07 11:32:34.223463015 +0200
++++ elf2flt/elf2flt.ld.in 2023-09-07 16:06:02.781672190 +0200
+@@ -73,6 +73,7 @@
+ W_RODAT: *(.rodata1)
+ W_RODAT: *(.rodata.*)
+ W_RODAT: *(.gnu.linkonce.r*)
++W_RODAT: *(.rofixup)
+
+ /* .ARM.extab name sections containing exception unwinding information */
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+@@ -111,6 +112,7 @@
+ R_RODAT: *(.rodata1)
+ R_RODAT: *(.rodata.*)
+ R_RODAT: *(.gnu.linkonce.r*)
++R_RODAT: *(.rofixup)
+ *(.data)
+ *(.data1)
+ *(.data.*)
diff --git a/toolchain/elf2flt/patches/26dfb54a59c8c0106418a0c46ccb4288d9e066fd/0003-sh2.patch b/toolchain/elf2flt/patches/26dfb54a59c8c0106418a0c46ccb4288d9e066fd/0003-sh2.patch
new file mode 100644
index 000000000..9587a0315
--- /dev/null
+++ b/toolchain/elf2flt/patches/26dfb54a59c8c0106418a0c46ccb4288d9e066fd/0003-sh2.patch
@@ -0,0 +1,52 @@
+diff -Nur elf2flt-26dfb54a59c8c0106418a0c46ccb4288d9e066fd.orig/elf2flt.c elf2flt-26dfb54a59c8c0106418a0c46ccb4288d9e066fd/elf2flt.c
+--- elf2flt-26dfb54a59c8c0106418a0c46ccb4288d9e066fd.orig/elf2flt.c 2023-09-08 08:49:00.529082893 +0200
++++ elf2flt-26dfb54a59c8c0106418a0c46ccb4288d9e066fd/elf2flt.c 2023-09-08 08:51:08.117679134 +0200
+@@ -75,7 +75,7 @@
+ #define FLAT_NIOS2_R_HIADJ_LO 2
+ #define FLAT_NIOS2_R_CALL26 4
+ #include <elf/nios2.h>
+-#elif defined(TARGET_sh)
++#elif defined(TARGET_sh2eb)
+ #include <elf/sh.h>
+ #elif defined(TARGET_sparc)
+ #include <elf/sparc.h>
+@@ -111,7 +111,7 @@
+ #define ARCH "sparc"
+ #elif defined(TARGET_v850)
+ #define ARCH "v850"
+-#elif defined(TARGET_sh)
++#elif defined(TARGET_sh2eb)
+ #define ARCH "sh"
+ #elif defined(TARGET_h8300)
+ #define ARCH "h8300"
+@@ -795,6 +795,12 @@
+
+ flat_reloc_count++;
+ break;
++#elif defined (TARGET_sh2eb)
++ case R_SH_DIR32:
++ goto good_32bit_resolved_reloc;
++ case R_SH_REL32:
++ relocation_needed = 0;
++ continue;
+ #elif defined (TARGET_h8300)
+ case R_H8_DIR32:
+ case R_H8_DIR32A16:
+@@ -1328,7 +1334,7 @@
+ #endif /* TARGET_sparc */
+
+
+-#ifdef TARGET_sh
++#ifdef TARGET_sh2eb
+ case R_SH_DIR32:
+ relocation_needed = 1;
+ sym_vma = elf2flt_bfd_section_vma(sym_section);
+@@ -1339,7 +1345,7 @@
+ sym_addr += sym_vma + q->addend;
+ sym_addr -= q->address;
+ break;
+-#endif /* TARGET_sh */
++#endif /* TARGET_sh2eb */
+
+ #ifdef TARGET_e1
+ #define htoe1l(x) htonl(x)
diff --git a/toolchain/elf2flt/patches/3051fec89bbd30de6f952dc3100712feff3ca076/0001-.rofixup-fix.patch b/toolchain/elf2flt/patches/3051fec89bbd30de6f952dc3100712feff3ca076/0001-.rofixup-fix.patch
new file mode 100644
index 000000000..79186642e
--- /dev/null
+++ b/toolchain/elf2flt/patches/3051fec89bbd30de6f952dc3100712feff3ca076/0001-.rofixup-fix.patch
@@ -0,0 +1,33 @@
+From 270b461e88b47781b3ef9bba2779074d0eb4996b Mon Sep 17 00:00:00 2001
+From: Waldemar Brodkorb <wbx@openadk.org>
+Date: Fri, 25 Aug 2023 05:04:53 +0200
+Subject: [PATCH] .rofixup fix
+
+Signed-off-by: Waldemar Brodkorb <wbx@openadk.org>
+---
+ elf2flt.ld.in | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/elf2flt.ld.in b/elf2flt.ld.in
+index c7e01a6..c69531e 100644
+--- a/elf2flt.ld.in
++++ b/elf2flt.ld.in
+@@ -31,6 +31,7 @@ W_RODAT *(.rodata)
+ W_RODAT *(.rodata1)
+ W_RODAT *(.rodata.*)
+ W_RODAT *(.gnu.linkonce.r*)
++W_RODAT *(.rofixup)
+
+ /* This is special code area at the end of the normal
+ text section. It contains a small lookup table at
+@@ -60,6 +61,7 @@ R_RODAT *(.rodata)
+ R_RODAT *(.rodata1)
+ R_RODAT *(.rodata.*)
+ R_RODAT *(.gnu.linkonce.r*)
++R_RODAT *(.rofixup)
+ *(.data)
+ *(.data1)
+ *(.data.*)
+--
+2.30.2
+
diff --git a/toolchain/elf2flt/patches/453398f917d167f8c308c8f997270c48ae8f8b12/0005-elf2flt-add-riscv-64-bits-support.patch b/toolchain/elf2flt/patches/453398f917d167f8c308c8f997270c48ae8f8b12/0005-elf2flt-add-riscv-64-bits-support.patch
new file mode 100644
index 000000000..4b0075844
--- /dev/null
+++ b/toolchain/elf2flt/patches/453398f917d167f8c308c8f997270c48ae8f8b12/0005-elf2flt-add-riscv-64-bits-support.patch
@@ -0,0 +1,137 @@
+From 1dea576eac4289602adc4a37f48c80330bf82e63 Mon Sep 17 00:00:00 2001
+From: Damien Le Moal <damien.lemoal@wdc.com>
+Date: Wed, 9 Sep 2020 17:31:33 +0900
+Subject: [PATCH] elf2flt: add riscv 64-bits support
+
+Add support for riscv 64bits ISA by defining the relocation types
+R_RISCV_32_PCREL, R_RISCV_ADD32, R_RISCV_SUB32, R_RISCV_32 and
+R_RISCV_64. riscv64 support also needs the __global_pointer$ symbol to
+be defined right after the relocation tables in the data section.
+Furthermore, the .got and .got.plt sections must be reversed. These 2
+requirements are handled with runtime modifications of the default
+linker script using the append_sed() function.
+(1) For the .got.plt and .got sections order swap, append_sed() is used
+to rename "(.got.plt)" to "(.got.tmp)" and to rename "(.got)" to
+"(.got.plt)". A last call finalize the name swap by replacing
+"(.got.tmp)" with "(.got)"
+(2) For the global pointer synbol, a definition line starting with
+"RISCV_GP" is added. The "RISCV_GP" string is removed if the target CPU
+type is riscv64. The definition line is dropped for other CPU types.
+
+With these changes, buildroot/busybox builds and run on NOMMU
+systems with kernel 5.13. Tested on Canaan Kendryte K210 boards.
+
+This patch is based on earlier work by Christoph Hellwig <hch@lst.de>.
+
+Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
+---
+ elf2flt.c | 23 +++++++++++++++++++++++
+ elf2flt.ld.in | 9 +++++----
+ ld-elf2flt.c | 16 ++++++++++++++++
+ 3 files changed, 44 insertions(+), 4 deletions(-)
+
+diff --git a/elf2flt.c b/elf2flt.c
+index f87f1fc..dbce467 100644
+--- a/elf2flt.c
++++ b/elf2flt.c
+@@ -80,6 +80,8 @@ const char *elf2flt_progname;
+ #include <elf/v850.h>
+ #elif defined(TARGET_xtensa)
+ #include <elf/xtensa.h>
++#elif defined(TARGET_riscv64)
++#include <elf/riscv.h>
+ #endif
+
+ #if defined(__MINGW32__)
+@@ -122,6 +124,8 @@ const char *elf2flt_progname;
+ #define ARCH "nios2"
+ #elif defined(TARGET_xtensa)
+ #define ARCH "xtensa"
++#elif defined(TARGET_riscv64)
++#define ARCH "riscv64"
+ #else
+ #error "Don't know how to support your CPU architecture??"
+ #endif
+@@ -797,6 +801,16 @@ output_relocs (
+ goto good_32bit_resolved_reloc;
+ default:
+ goto bad_resolved_reloc;
++#elif defined(TARGET_riscv64)
++ case R_RISCV_32_PCREL:
++ case R_RISCV_ADD32:
++ case R_RISCV_SUB32:
++ continue;
++ case R_RISCV_32:
++ case R_RISCV_64:
++ goto good_32bit_resolved_reloc;
++ default:
++ goto bad_resolved_reloc;
+ #else
+ default:
+ /* The default is to assume that the
+@@ -1806,6 +1820,15 @@ int main(int argc, char *argv[])
+ if (!load_to_ram && !pfile)
+ load_to_ram = 1;
+
++#if defined(TARGET_riscv64)
++ /*
++ * riscv only supports loading text and data contiguously.
++ * So fail if load_to_ram is false.
++ */
++ if (!load_to_ram)
++ fatal("Loading to RAM ('-r' option) is required");
++#endif
++
+ fname = argv[argc-1];
+
+ if (pfile) {
+diff --git a/elf2flt.ld.in b/elf2flt.ld.in
+index ec1fe6f..c0c44b8 100644
+--- a/elf2flt.ld.in
++++ b/elf2flt.ld.in
+@@ -70,10 +70,11 @@ W_RODAT *(.gnu.linkonce.r*)
+ . = ALIGN(0x20) ;
+ LONG(-1)
+ . = ALIGN(0x20) ;
+-R_RODAT *(.rodata)
+-R_RODAT *(.rodata1)
+-R_RODAT *(.rodata.*)
+-R_RODAT *(.gnu.linkonce.r*)
++RISCV_GP: __global_pointer$ = . + 0x800 ;
++R_RODAT *(.rodata)
++R_RODAT *(.rodata1)
++R_RODAT *(.rodata.*)
++R_RODAT *(.gnu.linkonce.r*)
+ *(.data)
+ *(.data1)
+ *(.data.*)
+diff --git a/ld-elf2flt.c b/ld-elf2flt.c
+index e5de506..31b565f 100644
+--- a/ld-elf2flt.c
++++ b/ld-elf2flt.c
+@@ -324,6 +324,22 @@ static int do_final_link(void)
+ append_option(&other_options, concat(got_offset, "=", buf, NULL));
+ }
+
++ if (streq(TARGET_CPU, "riscv64")) {
++ /*
++ * The .got section must come before the .got.plt section
++ * (gcc/ld bug ?).
++ */
++ append_sed(&sed, "(.got.plt)", "(.got.tmp)");
++ append_sed(&sed, "(.got.plt)", "(.got)");
++ append_sed(&sed, "(.got.tmp)", "(.got.plt)");
++
++ /* The global pointer symbol is defined after the GOT. */
++ append_sed(&sed, "^RISCV_GP:", "");
++ } else {
++ /* Get rid of the global pointer definition. */
++ append_sed(&sed, "^RISCV_GP:", NULL);
++ }
++
+ /* Locate the default linker script, if we don't have one provided. */
+ if (!linker_script)
+ linker_script = concat(ldscriptpath, "/elf2flt.ld", NULL);
+--
+2.31.1
+
diff --git a/toolchain/elf2flt/patches/453398f917d167f8c308c8f997270c48ae8f8b12/0008-remove_BFD_VMA_FMT.patch b/toolchain/elf2flt/patches/453398f917d167f8c308c8f997270c48ae8f8b12/0008-remove_BFD_VMA_FMT.patch
new file mode 100644
index 000000000..d20b993da
--- /dev/null
+++ b/toolchain/elf2flt/patches/453398f917d167f8c308c8f997270c48ae8f8b12/0008-remove_BFD_VMA_FMT.patch
@@ -0,0 +1,125 @@
+diff -Nur elf2flt-453398f917d167f8c308c8f997270c48ae8f8b12.orig/elf2flt.c elf2flt-453398f917d167f8c308c8f997270c48ae8f8b12/elf2flt.c
+--- elf2flt-453398f917d167f8c308c8f997270c48ae8f8b12.orig/elf2flt.c 2023-01-30 08:48:56.632981732 +0100
++++ elf2flt-453398f917d167f8c308c8f997270c48ae8f8b12/elf2flt.c 2023-01-30 08:53:34.510426754 +0100
+@@ -222,7 +222,7 @@
+ long i;
+ printf("SYMBOL TABLE:\n");
+ for (i=0; i<number_of_symbols; i++) {
+- printf(" NAME=%s VALUE=0x%"BFD_VMA_FMT"x\n",
++ printf(" NAME=%s VALUE=0x%x\n",
+ symbol_table[i]->name, symbol_table[i]->value);
+ }
+ printf("\n");
+@@ -458,7 +458,7 @@
+ if (r == NULL)
+ continue;
+ if (verbose)
+- printf(" RELOCS: %s [%p]: flags=0x%x vma=0x%"BFD_VMA_FMT"x\n",
++ printf(" RELOCS: %s [%p]: flags=0x%x vma=0x%x\n",
+ r->name, r, r->flags, elf2flt_bfd_section_vma(abs_bfd, r));
+ if ((r->flags & SEC_RELOC) == 0)
+ continue;
+@@ -903,8 +903,8 @@
+ if (verbose)
+ fprintf(stderr,
+ "%s vma=0x%x, "
+- "value=0x%"BFD_VMA_FMT"x, "
+- "address=0x%"BFD_VMA_FMT"x "
++ "value=0x%x, "
++ "address=0x%x "
+ "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
+ "ABS32",
+ sym_vma, (*(q->sym_ptr_ptr))->value,
+@@ -922,8 +922,8 @@
+ if (verbose)
+ fprintf(stderr,
+ "%s vma=0x%x, "
+- "value=0x%"BFD_VMA_FMT"x, "
+- "address=0x%"BFD_VMA_FMT"x "
++ "value=0x%x, "
++ "address=0x%x "
+ "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
+ "PLT32",
+ sym_vma, (*(q->sym_ptr_ptr))->value,
+@@ -945,7 +945,7 @@
+ case R_V850_ZDA_16_16_OFFSET:
+ case R_V850_ZDA_16_16_SPLIT_OFFSET:
+ /* Can't support zero-relocations. */
+- printf ("ERROR: %s+0x%"BFD_VMA_FMT"x: zero relocations not supported\n",
++ printf ("ERROR: %s+0x%x: zero relocations not supported\n",
+ sym_name, q->addend);
+ continue;
+ #endif /* TARGET_v850 */
+@@ -1038,15 +1038,15 @@
+ sprintf(&addstr[0], "+0x%ld", sym_addr - (*(q->sym_ptr_ptr))->value -
+ elf2flt_bfd_section_vma(abs_bfd, sym_section));
+ if (verbose)
+- printf(" RELOC[%d]: offset=0x%"BFD_VMA_FMT"x symbol=%s%s "
++ printf(" RELOC[%d]: offset=0x%x symbol=%s%s "
+ "section=%s size=%d "
+- "fixup=0x%x (reloc=0x%"BFD_VMA_FMT"x)\n",
++ "fixup=0x%x (reloc=0x%x)\n",
+ flat_reloc_count,
+ q->address, sym_name, addstr,
+ section_name, sym_reloc_size,
+ sym_addr, section_vma + q->address);
+ if (verbose)
+- printf("reloc[%d] = 0x%"BFD_VMA_FMT"x\n",
++ printf("reloc[%d] = 0x%x\n",
+ flat_reloc_count, section_vma + q->address);
+
+ continue;
+@@ -1163,9 +1163,9 @@
+ temp |= (exist_val & 0x3f);
+ *(unsigned long *)r_mem = htoniosl(temp);
+ if (verbose)
+- printf("omit: offset=0x%"BFD_VMA_FMT"x symbol=%s%s "
++ printf("omit: offset=0x%x symbol=%s%s "
+ "section=%s size=%d "
+- "fixup=0x%x (reloc=0x%"BFD_VMA_FMT"x) GPREL\n",
++ "fixup=0x%x (reloc=0x%x) GPREL\n",
+ q->address, sym_name, addstr,
+ section_name, sym_reloc_size,
+ sym_addr, section_vma + q->address);
+@@ -1183,9 +1183,9 @@
+ exist_val |= ((sym_addr & 0xFFFF) << 6);
+ *(unsigned long *)r_mem = htoniosl(exist_val);
+ if (verbose)
+- printf("omit: offset=0x%"BFD_VMA_FMT"x symbol=%s%s "
++ printf("omit: offset=0x%x symbol=%s%s "
+ "section=%s size=%d "
+- "fixup=0x%x (reloc=0x%"BFD_VMA_FMT"x) PCREL\n",
++ "fixup=0x%x (reloc=0x%x) PCREL\n",
+ q->address, sym_name, addstr,
+ section_name, sym_reloc_size,
+ sym_addr, section_vma + q->address);
+@@ -1200,7 +1200,7 @@
+ && (p[-1]->sym_ptr_ptr == p[0]->sym_ptr_ptr)
+ && (p[-1]->addend == p[0]->addend)) {
+ if (verbose)
+- printf("omit: offset=0x%"BFD_VMA_FMT"x symbol=%s%s "
++ printf("omit: offset=0x%x symbol=%s%s "
+ "section=%s size=%d LO16\n",
+ q->address, sym_name, addstr,
+ section_name, sym_reloc_size);
+@@ -1610,9 +1610,9 @@
+ }
+
+ if (verbose)
+- printf(" RELOC[%d]: offset=0x%"BFD_VMA_FMT"x symbol=%s%s "
++ printf(" RELOC[%d]: offset=0x%x symbol=%s%s "
+ "section=%s size=%d "
+- "fixup=0x%x (reloc=0x%"BFD_VMA_FMT"x)\n",
++ "fixup=0x%x (reloc=0x%x)\n",
+ flat_reloc_count,
+ q->address, sym_name, addstr,
+ section_name, sym_reloc_size,
+@@ -1630,7 +1630,7 @@
+ (section_vma + q->address);
+
+ if (verbose)
+- printf("reloc[%d] = 0x%"BFD_VMA_FMT"x\n",
++ printf("reloc[%d] = 0x%x\n",
+ flat_reloc_count, section_vma + q->address);
+ #else
+ switch ((*p)->howto->type) {
diff --git a/toolchain/elf2flt/patches/v2021.08/0001-elf2flt-handle-binutils-2.34.patch b/toolchain/elf2flt/patches/v2021.08/0001-elf2flt-handle-binutils-2.34.patch
new file mode 100644
index 000000000..4aa473c24
--- /dev/null
+++ b/toolchain/elf2flt/patches/v2021.08/0001-elf2flt-handle-binutils-2.34.patch
@@ -0,0 +1,377 @@
+From d78acba6510527aaa01a41eaf4c931f7a57e5f44 Mon Sep 17 00:00:00 2001
+From: Romain Naour <romain.naour@smile.fr>
+Date: Wed, 5 Feb 2020 10:31:32 +0100
+Subject: [PATCH] elf2flt: handle binutils >= 2.34
+
+The latest Binutils release (2.34) is not compatible with elf2flt due
+to a change in bfd_section_* macros [1]. The issue has been reported
+to the Binutils mailing list but Alan Modra recommend to bundle
+libbfd library sources into each projects using it [2]. That's
+because the API is not stable over the time without any backward
+compatibility guaranties.
+
+On the other hand, the elf2flt tools needs to support modified
+version of binutils for specific arch/target [3].
+
+Add two tests in the configure script to detect this API change
+in order to support binutils < 2.34 and binutils >= 2.34.
+
+Upstream status: [4]
+
+[1] https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=fd3619828e94a24a92cddec42cbc0ab33352eeb4
+[2] https://sourceware.org/ml/binutils/2020-02/msg00044.html
+[3] https://github.com/uclinux-dev/elf2flt/issues/14
+[4] https://github.com/uclinux-dev/elf2flt/pull/15
+
+Signed-off-by: Romain Naour <romain.naour@smile.fr>
+---
+ configure.ac | 16 +++++++++++
+ elf2flt.c | 81 +++++++++++++++++++++++++++++-----------------------
+ 2 files changed, 61 insertions(+), 36 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index b7db2cb..fdc0876 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -229,6 +229,22 @@ AC_CHECK_FUNCS([ \
+ strsignal \
+ ])
+
++dnl Various bfd section macros and functions like bfd_section_size() have been
++dnl modified starting with binutils >= 2.34.
++dnl Check if the prototypes take a bfd argument.
++if test "$binutils_build_dir" != "NONE"; then
++ CFLAGS="-I$binutils_include_dir -I$bfd_include_dir $CFLAGS"
++fi
++
++AC_TRY_COMPILE([#include <bfd.h>],
++ [const asection *sec; bfd_section_size(sec);],
++ bfd_section_api_takes_bfd=no,
++ bfd_section_api_takes_bfd=yes)
++if test "$bfd_section_api_takes_bfd" = "yes" ; then
++ AC_DEFINE(HAVE_BFD_SECTION_API_TAKES_BFD, 1,
++ [define to 1 for binutils < 2.34])
++fi
++
+ if test "$GCC" = yes ; then
+ CFLAGS="-Wall $CFLAGS"
+ if test "$werror" = 1 ; then
+diff --git a/elf2flt.c b/elf2flt.c
+index 7ac0617..ea6b5a1 100644
+--- a/elf2flt.c
++++ b/elf2flt.c
+@@ -149,6 +149,17 @@ const char *elf2flt_progname;
+ #define O_BINARY 0
+ #endif
+
++/*
++ * The bfd parameter isn't actually used by any of the bfd_section funcs and
++ * have been removed since binutils 2.34.
++ */
++#ifdef HAVE_BFD_SECTION_API_TAKES_BFD
++#define elf2flt_bfd_section_size(s) bfd_section_size(NULL, s)
++#define elf2flt_bfd_section_vma(s) bfd_section_vma(NULL, s)
++#else
++#define elf2flt_bfd_section_size(s) bfd_section_size(s)
++#define elf2flt_bfd_section_vma(s) bfd_section_vma(s)
++#endif
+
+ /* Extra output when running. */
+ static int verbose = 0;
+@@ -323,10 +334,8 @@ compare_relocs (const void *pa, const void *pb)
+ else if (!rb->sym_ptr_ptr || !*rb->sym_ptr_ptr)
+ return 1;
+
+- a_vma = bfd_section_vma(compare_relocs_bfd,
+- (*(ra->sym_ptr_ptr))->section);
+- b_vma = bfd_section_vma(compare_relocs_bfd,
+- (*(rb->sym_ptr_ptr))->section);
++ a_vma = elf2flt_bfd_section_vma((*(ra->sym_ptr_ptr))->section);
++ b_vma = elf2flt_bfd_section_vma((*(rb->sym_ptr_ptr))->section);
+ va = (*(ra->sym_ptr_ptr))->value + a_vma + ra->addend;
+ vb = (*(rb->sym_ptr_ptr))->value + b_vma + rb->addend;
+ return va - vb;
+@@ -403,7 +412,7 @@ output_relocs (
+ }
+
+ for (a = abs_bfd->sections; (a != (asection *) NULL); a = a->next) {
+- section_vma = bfd_section_vma(abs_bfd, a);
++ section_vma = elf2flt_bfd_section_vma(a);
+
+ if (verbose)
+ printf("SECTION: %s [%p]: flags=0x%x vma=0x%"PRIx32"\n",
+@@ -443,7 +452,7 @@ output_relocs (
+ continue;
+ if (verbose)
+ printf(" RELOCS: %s [%p]: flags=0x%x vma=0x%"BFD_VMA_FMT"x\n",
+- r->name, r, r->flags, bfd_section_vma(abs_bfd, r));
++ r->name, r, r->flags, elf2flt_bfd_section_vma(r));
+ if ((r->flags & SEC_RELOC) == 0)
+ continue;
+ relsize = bfd_get_reloc_upper_bound(rel_bfd, r);
+@@ -695,7 +704,7 @@ output_relocs (
+ case R_BFIN_RIMM16:
+ case R_BFIN_LUIMM16:
+ case R_BFIN_HUIMM16:
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
+ sym_addr += sym_vma + q->addend;
+
+ if (weak_und_symbol(sym_section->name, (*(q->sym_ptr_ptr))))
+@@ -728,7 +737,7 @@ output_relocs (
+ break;
+
+ case R_BFIN_BYTE4_DATA:
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
+ sym_addr += sym_vma + q->addend;
+
+ if (weak_und_symbol (sym_section->name, (*(q->sym_ptr_ptr))))
+@@ -886,7 +895,7 @@ output_relocs (
+ #if defined(TARGET_m68k)
+ case R_68K_32:
+ relocation_needed = 1;
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
+ sym_addr += sym_vma + q->addend;
+ break;
+ case R_68K_PC16:
+@@ -911,7 +920,7 @@ output_relocs (
+ q->address, sym_addr,
+ (*p)->howto->rightshift,
+ *(uint32_t *)r_mem);
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
+ sym_addr += sym_vma + q->addend;
+ break;
+ case R_ARM_GOT32:
+@@ -939,7 +948,7 @@ output_relocs (
+ #ifdef TARGET_v850
+ case R_V850_ABS32:
+ relocation_needed = 1;
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
+ sym_addr += sym_vma + q->addend;
+ break;
+ case R_V850_ZDA_16_16_OFFSET:
+@@ -961,7 +970,7 @@ output_relocs (
+ sym_addr = (*(q->sym_ptr_ptr))->value;
+ q->address -= 1;
+ r_mem -= 1; /* tracks q->address */
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
+ sym_addr += sym_vma + q->addend;
+ sym_addr |= (*(unsigned char *)r_mem<<24);
+ break;
+@@ -974,7 +983,7 @@ output_relocs (
+ /* Absolute symbol done not relocation */
+ relocation_needed = !bfd_is_abs_section(sym_section);
+ sym_addr = (*(q->sym_ptr_ptr))->value;
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
+ sym_addr += sym_vma + q->addend;
+ break;
+ case R_H8_DIR32:
+@@ -987,7 +996,7 @@ output_relocs (
+ }
+ relocation_needed = 1;
+ sym_addr = (*(q->sym_ptr_ptr))->value;
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
+ sym_addr += sym_vma + q->addend;
+ break;
+ case R_H8_PCREL16:
+@@ -1013,7 +1022,7 @@ output_relocs (
+ #ifdef TARGET_microblaze
+ case R_MICROBLAZE_64:
+ /* work out the relocation */
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
+ sym_addr += sym_vma + q->addend;
+ /* Write relocated pointer back */
+ r_mem[2] = (sym_addr >> 24) & 0xff;
+@@ -1027,7 +1036,7 @@ output_relocs (
+ pflags = 0x80000000;
+ break;
+ case R_MICROBLAZE_32:
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
+ sym_addr += sym_vma + q->addend;
+ relocation_needed = 1;
+ break;
+@@ -1059,7 +1068,7 @@ output_relocs (
+ case R_NIOS2_BFD_RELOC_32:
+ relocation_needed = 1;
+ pflags = (FLAT_NIOS2_R_32 << 28);
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
+ sym_addr += sym_vma + q->addend;
+ /* modify target, in target order */
+ *(unsigned long *)r_mem = htoniosl(sym_addr);
+@@ -1069,7 +1078,7 @@ output_relocs (
+ unsigned long exist_val;
+ relocation_needed = 1;
+ pflags = (FLAT_NIOS2_R_CALL26 << 28);
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
+ sym_addr += sym_vma + q->addend;
+
+ /* modify target, in target order */
+@@ -1100,7 +1109,7 @@ output_relocs (
+ ? FLAT_NIOS2_R_HIADJ_LO : FLAT_NIOS2_R_HI_LO;
+ pflags <<= 28;
+
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(abs_bfd, sym_section);
+ sym_addr += sym_vma + q->addend;
+
+ /* modify high 16 bits, in target order */
+@@ -1133,7 +1142,7 @@ output_relocs (
+ goto NIOS2_RELOC_ERR;
+ }
+ /* _gp holds a absolute value, otherwise the ld cannot generate correct code */
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
+ //printf("sym=%x, %d, _gp=%x, %d\n", sym_addr+sym_vma, sym_addr+sym_vma, gp, gp);
+ sym_addr += sym_vma + q->addend;
+ sym_addr -= gp;
+@@ -1214,7 +1223,7 @@ NIOS2_RELOC_ERR:
+ case R_SPARC_32:
+ case R_SPARC_UA32:
+ relocation_needed = 1;
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
+ sym_addr += sym_vma + q->addend;
+ break;
+ case R_SPARC_PC22:
+@@ -1233,7 +1242,7 @@ NIOS2_RELOC_ERR:
+ case R_SPARC_HI22:
+ relocation_needed = 1;
+ pflags = 0x80000000;
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
+ sym_addr += sym_vma + q->addend;
+ sym_addr |= (
+ htonl(*(uint32_t *)r_mem)
+@@ -1243,7 +1252,7 @@ NIOS2_RELOC_ERR:
+ case R_SPARC_LO10:
+ relocation_needed = 1;
+ pflags = 0x40000000;
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
+ sym_addr += sym_vma + q->addend;
+ sym_addr &= 0x000003ff;
+ sym_addr |= (
+@@ -1257,7 +1266,7 @@ NIOS2_RELOC_ERR:
+ #ifdef TARGET_sh
+ case R_SH_DIR32:
+ relocation_needed = 1;
+- sym_vma = bfd_section_vma(abs_bfd, sym_section);
++ sym_vma = elf2flt_bfd_section_vma(sym_section);
+ sym_addr += sym_vma + q->addend;
+ break;
+ case R_SH_REL32:
+@@ -1289,7 +1298,7 @@ NIOS2_RELOC_ERR:
+ case R_E1_CONST31:
+ relocation_needed = 1;
+ DBG_E1("Handling Reloc <CONST31>\n");
+- sec_vma = bfd_section_vma(abs_bfd, sym_section);
++ sec_vma = elf2flt_bfd_section_vma(sym_section);
+ DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
+ sec_vma, sym_addr, q->address);
+ sym_addr = sec_vma + sym_addr;
+@@ -1304,7 +1313,7 @@ NIOS2_RELOC_ERR:
+ relocation_needed = 0;
+ DBG_E1("Handling Reloc <CONST31_PCREL>\n");
+ DBG_E1("DONT RELOCATE AT LOADING\n");
+- sec_vma = bfd_section_vma(abs_bfd, sym_section);
++ sec_vma = elf2flt_bfd_section_vma(sym_section);
+ DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
+ sec_vma, sym_addr, q->address);
+ sym_addr = sec_vma + sym_addr;
+@@ -1331,7 +1340,7 @@ NIOS2_RELOC_ERR:
+ relocation_needed = 0;
+ DBG_E1("Handling Reloc <DIS29W_PCREL>\n");
+ DBG_E1("DONT RELOCATE AT LOADING\n");
+- sec_vma = bfd_section_vma(abs_bfd, sym_section);
++ sec_vma = elf2flt_bfd_section_vma(sym_section);
+ DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
+ sec_vma, sym_addr, q->address);
+ sym_addr = sec_vma + sym_addr;
+@@ -1364,7 +1373,7 @@ NIOS2_RELOC_ERR:
+ DBG_E1("Handling Reloc <DIS29B>\n");
+ DIS29_RELOCATION:
+ relocation_needed = 1;
+- sec_vma = bfd_section_vma(abs_bfd, sym_section);
++ sec_vma = elf2flt_bfd_section_vma(sym_section);
+ DBG_E1("sec_vma : [0x%x], sym_addr : [0x%08x]\n",
+ sec_vma, sym_addr);
+ sym_addr = sec_vma + sym_addr;
+@@ -1381,7 +1390,7 @@ DIS29_RELOCATION:
+ relocation_needed = 0;
+ DBG_E1("Handling Reloc <IMM32_PCREL>\n");
+ DBG_E1("DONT RELOCATE AT LOADING\n");
+- sec_vma = bfd_section_vma(abs_bfd, sym_section);
++ sec_vma = elf2flt_bfd_section_vma(sym_section);
+ DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
+ sec_vma, sym_addr);
+ sym_addr = sec_vma + sym_addr;
+@@ -1407,7 +1416,7 @@ DIS29_RELOCATION:
+ case R_E1_IMM32:
+ relocation_needed = 1;
+ DBG_E1("Handling Reloc <IMM32>\n");
+- sec_vma = bfd_section_vma(abs_bfd, sym_section);
++ sec_vma = elf2flt_bfd_section_vma(sym_section);
+ DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
+ sec_vma, sym_addr);
+ sym_addr = sec_vma + sym_addr;
+@@ -1423,7 +1432,7 @@ DIS29_RELOCATION:
+ case R_E1_WORD:
+ relocation_needed = 1;
+ DBG_E1("Handling Reloc <WORD>\n");
+- sec_vma = bfd_section_vma(abs_bfd, sym_section);
++ sec_vma = elf2flt_bfd_section_vma(sym_section);
+ DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
+ sec_vma, sym_addr);
+ sym_addr = sec_vma + sym_addr;
+@@ -1450,7 +1459,7 @@ DIS29_RELOCATION:
+ }
+
+ sprintf(&addstr[0], "+0x%lx", sym_addr - (*(q->sym_ptr_ptr))->value -
+- bfd_section_vma(abs_bfd, sym_section));
++ elf2flt_bfd_section_vma(sym_section));
+
+
+ /*
+@@ -1890,8 +1899,8 @@ int main(int argc, char *argv[])
+ } else
+ continue;
+
+- sec_size = bfd_section_size(abs_bfd, s);
+- sec_vma = bfd_section_vma(abs_bfd, s);
++ sec_size = elf2flt_bfd_section_size(s);
++ sec_vma = elf2flt_bfd_section_vma(s);
+
+ if (sec_vma < *vma) {
+ if (*len > 0)
+@@ -1920,7 +1929,7 @@ int main(int argc, char *argv[])
+ (SEC_DATA | SEC_READONLY | SEC_RELOC)))
+ if (!bfd_get_section_contents(abs_bfd, s,
+ text + (s->vma - text_vma), 0,
+- bfd_section_size(abs_bfd, s)))
++ elf2flt_bfd_section_size(s)))
+ {
+ fatal("read error section %s", s->name);
+ }
+@@ -1950,7 +1959,7 @@ int main(int argc, char *argv[])
+ (SEC_READONLY | SEC_RELOC)))
+ if (!bfd_get_section_contents(abs_bfd, s,
+ data + (s->vma - data_vma), 0,
+- bfd_section_size(abs_bfd, s)))
++ elf2flt_bfd_section_size(s)))
+ {
+ fatal("read error section %s", s->name);
+ }
+--
+2.35.1
+
diff --git a/toolchain/elf2flt/patches/v2021.08/0002-elf2flt.ld-reinstate-32-byte-alignment-for-.data-sec.patch b/toolchain/elf2flt/patches/v2021.08/0002-elf2flt.ld-reinstate-32-byte-alignment-for-.data-sec.patch
new file mode 100644
index 000000000..4df3ea592
--- /dev/null
+++ b/toolchain/elf2flt/patches/v2021.08/0002-elf2flt.ld-reinstate-32-byte-alignment-for-.data-sec.patch
@@ -0,0 +1,81 @@
+From 85ba5664eb368eb1cbd2c30b7cd574acd75edd4c Mon Sep 17 00:00:00 2001
+From: Niklas Cassel <niklas.cassel@wdc.com>
+Date: Mon, 4 Apr 2022 15:30:24 +0200
+Subject: [PATCH] elf2flt.ld: reinstate 32 byte alignment for .data section
+
+Commit 8a3e74446fe7 ("allow to build arm flat binaries") moved the
+following commands:
+ . = ALIGN(0x20) ;
+ @SYMBOL_PREFIX@_etext = . ;
+from the .text section to the top level in the SECTIONS node.
+
+The .text output section is being directed to a memory region using the
+"> flatmem :text" output section attribute. Commands in the top level in
+the SECTIONS node are not.
+
+This means that the ALIGN() command is no longer being appended to the
+flatmem memory region, it will simply update the Location Counter.
+
+The heuristic for placing an output section is described here:
+https://sourceware.org/binutils/docs-2.38/ld.html#Output-Section-Address
+
+"If an output memory region is set for the section then it is added to this
+region and its address will be the next free address in that region."
+
+Since the .data section is being directed to the same memory region as the
+.text section, this means that the Location Counter is not used when
+assigning an address to the .data output section, it will simply use the
+next free address.
+
+No longer directing these commands to the flatmem memory region means that
+the .data output section is no longer aligned to a 32 byte boundary.
+
+Before commit 8a3e74446fe7 ("allow to build arm flat binaries"):
+$ readelf -S busybox_unstripped.gdb | grep data
+ [ 3] .data PROGBITS 0000000000035ac0 00036ac0
+$ readelf -s busybox_unstripped.gdb | grep _etext
+ 19286: 0000000000035ac0 0 NOTYPE GLOBAL DEFAULT 1 _etext
+
+After commit 8a3e74446fe7 ("allow to build arm flat binaries"):
+$ readelf -S busybox_unstripped.gdb | grep data
+ [ 3] .data PROGBITS 0000000000035ab0 00036ab0
+$ readelf -s busybox_unstripped.gdb | grep _etext
+ 19287: 0000000000035ac0 0 NOTYPE GLOBAL DEFAULT 3 _etext
+
+The .data output section has to be aligned to a 32 byte boundary, see the
+FLAT_DATA_ALIGN 0x20 macro and its usage in fs/binfmt_flat.c:
+https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/binfmt_flat.c?h=v5.17#n59
+
+Readd an explicit ALIGN attribute on the .data section itself, since the
+linker will obey this attribute regardless if being directed to a memory
+region or not. Also remove the ALIGN() command before the .data section,
+since this misleads the reader to think that the Location Counter is used
+when assigning an address to the .data section, when it actually is not.
+
+Fixes: 8a3e74446fe7 ("allow to build arm flat binaries")
+Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com>
+---
+ elf2flt.ld.in | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+diff --git a/elf2flt.ld.in b/elf2flt.ld.in
+index 0df999d..e5aea14 100644
+--- a/elf2flt.ld.in
++++ b/elf2flt.ld.in
+@@ -94,12 +94,9 @@ W_RODAT: *(.gnu.linkonce.r*)
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } > flatmem
+ @SYMBOL_PREFIX@__exidx_end = .;
+-
+- . = ALIGN(0x20) ;
+ @SYMBOL_PREFIX@_etext = . ;
+
+- .data : {
+- . = ALIGN(0x4) ;
++ .data ALIGN(0x20): {
+ @SYMBOL_PREFIX@_sdata = . ;
+ @SYMBOL_PREFIX@__data_start = . ;
+ @SYMBOL_PREFIX@data_start = . ;
+--
+2.35.1
+
diff --git a/toolchain/elf2flt/patches/v2021.08/0003-elf2flt-add-riscv-64-bits-support.patch b/toolchain/elf2flt/patches/v2021.08/0003-elf2flt-add-riscv-64-bits-support.patch
new file mode 100644
index 000000000..15c191c83
--- /dev/null
+++ b/toolchain/elf2flt/patches/v2021.08/0003-elf2flt-add-riscv-64-bits-support.patch
@@ -0,0 +1,103 @@
+From 3f1f323feb5cf25d8c80861991d0360784f4d2e6 Mon Sep 17 00:00:00 2001
+From: Damien Le Moal <damien.lemoal@wdc.com>
+Date: Wed, 9 Sep 2020 17:31:33 +0900
+Subject: [PATCH] elf2flt: add riscv 64-bits support
+
+Add support for riscv 64bits ISA by defining the relocation types
+R_RISCV_32_PCREL, R_RISCV_ADD32, R_RISCV_SUB32, R_RISCV_32 and
+R_RISCV_64. riscv64 support also needs the __global_pointer$ symbol to
+be defined right after the relocation tables in the data section. To
+define this symbol, the "RISCV_GP" line prefix is added. The "RISCV_GP"
+string is removed if the target CPU type is riscv64 and the definition
+line is dropped for other CPU types.
+
+With these changes, buildroot and busybox build and run on riscv NOMMU
+systems with Linux kernel including patch 6045ab5fea4c
+("binfmt_flat: do not stop relocating GOT entries prematurely on riscv")
+fixing the binfmt_flat loader. Tested on QEMU and Canaan Kendryte K210
+boards.
+
+This patch is based on earlier work by Christoph Hellwig <hch@lst.de>.
+
+Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
+---
+ elf2flt.c | 16 ++++++++++++++++
+ elf2flt.ld.in | 1 +
+ ld-elf2flt.c | 8 ++++++++
+ 3 files changed, 25 insertions(+)
+
+diff --git a/elf2flt.c b/elf2flt.c
+index da25e93..a03ea3a 100644
+--- a/elf2flt.c
++++ b/elf2flt.c
+@@ -81,6 +81,8 @@ const char *elf2flt_progname;
+ #include <elf/v850.h>
+ #elif defined(TARGET_xtensa)
+ #include <elf/xtensa.h>
++#elif defined(TARGET_riscv64)
++#include <elf/riscv.h>
+ #endif
+
+ #if defined(__MINGW32__)
+@@ -123,6 +125,8 @@ const char *elf2flt_progname;
+ #define ARCH "nios2"
+ #elif defined(TARGET_xtensa)
+ #define ARCH "xtensa"
++#elif defined(TARGET_riscv64)
++#define ARCH "riscv64"
+ #else
+ #error "Don't know how to support your CPU architecture??"
+ #endif
+@@ -812,6 +816,18 @@ output_relocs (
+ goto good_32bit_resolved_reloc;
+ default:
+ goto bad_resolved_reloc;
++#elif defined(TARGET_riscv64)
++ case R_RISCV_32_PCREL:
++ case R_RISCV_ADD32:
++ case R_RISCV_ADD64:
++ case R_RISCV_SUB32:
++ case R_RISCV_SUB64:
++ continue;
++ case R_RISCV_32:
++ case R_RISCV_64:
++ goto good_32bit_resolved_reloc;
++ default:
++ goto bad_resolved_reloc;
+ #else
+ default:
+ /* The default is to assume that the
+diff --git a/elf2flt.ld.in b/elf2flt.ld.in
+index e5aea14..950849e 100644
+--- a/elf2flt.ld.in
++++ b/elf2flt.ld.in
+@@ -106,6 +106,7 @@ W_RODAT: *(.gnu.linkonce.r*)
+ . = ALIGN(0x20) ;
+ LONG(-1)
+ . = ALIGN(0x20) ;
++RISCV_GP: __global_pointer$ = . + 0x800 ;
+ R_RODAT: *(.rodata)
+ R_RODAT: *(.rodata1)
+ R_RODAT: *(.rodata.*)
+diff --git a/ld-elf2flt.c b/ld-elf2flt.c
+index 7cb02d5..75ee1bb 100644
+--- a/ld-elf2flt.c
++++ b/ld-elf2flt.c
+@@ -324,6 +324,14 @@ static int do_final_link(void)
+ append_option(&other_options, concat(got_offset, "=", buf, NULL));
+ }
+
++ /* riscv adds a global pointer symbol to the linker file with the
++ "RISCV_GP:" prefix. Remove the prefix for riscv64 architecture and
++ the entire line for other architectures. */
++ if (streq(TARGET_CPU, "riscv64"))
++ append_sed(&sed, "^RISCV_GP:", "");
++ else
++ append_sed(&sed, "^RISCV_GP:", NULL);
++
+ /* Locate the default linker script, if we don't have one provided. */
+ if (!linker_script)
+ linker_script = concat(ldscriptpath, "/elf2flt.ld", NULL);
+--
+2.36.1
+
diff --git a/toolchain/elf2flt/patches/v2021.08/0004-elf2flt-create-a-common-helper-function.patch b/toolchain/elf2flt/patches/v2021.08/0004-elf2flt-create-a-common-helper-function.patch
new file mode 100644
index 000000000..6fee99d45
--- /dev/null
+++ b/toolchain/elf2flt/patches/v2021.08/0004-elf2flt-create-a-common-helper-function.patch
@@ -0,0 +1,76 @@
+From 37e1e0ace8ccebf54ec2f5522bfc1f9db86946ad Mon Sep 17 00:00:00 2001
+From: Niklas Cassel <niklas.cassel@wdc.com>
+Date: Tue, 9 Aug 2022 12:13:50 +0200
+Subject: [PATCH] elf2flt: create a common helper function
+
+In order to make the code more maintainable,
+move duplicated code to a common helper function.
+
+No functional change intended.
+
+Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com>
+---
+ elf2flt.c | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/elf2flt.c b/elf2flt.c
+index 669591e..9c32f9a 100644
+--- a/elf2flt.c
++++ b/elf2flt.c
+@@ -337,6 +337,13 @@ compare_relocs (const void *pa, const void *pb)
+ }
+ #endif
+
++static bool
++ro_reloc_data_section_should_be_in_text(asection *s)
++{
++ return (s->flags & (SEC_DATA | SEC_READONLY | SEC_RELOC)) ==
++ (SEC_DATA | SEC_READONLY | SEC_RELOC);
++}
++
+ static uint32_t *
+ output_relocs (
+ bfd *abs_bfd,
+@@ -428,8 +435,7 @@ output_relocs (
+ */
+ if ((!pic_with_got || ALWAYS_RELOC_TEXT) &&
+ ((a->flags & SEC_CODE) ||
+- ((a->flags & (SEC_DATA | SEC_READONLY | SEC_RELOC)) ==
+- (SEC_DATA | SEC_READONLY | SEC_RELOC))))
++ ro_reloc_data_section_should_be_in_text(a)))
+ sectionp = text + (a->vma - text_vma);
+ else if (a->flags & SEC_DATA)
+ sectionp = data + (a->vma - data_vma);
+@@ -1893,8 +1899,7 @@ int main(int argc, char *argv[])
+ bfd_vma sec_vma;
+
+ if ((s->flags & SEC_CODE) ||
+- ((s->flags & (SEC_DATA | SEC_READONLY | SEC_RELOC)) ==
+- (SEC_DATA | SEC_READONLY | SEC_RELOC))) {
++ ro_reloc_data_section_should_be_in_text(s)) {
+ vma = &text_vma;
+ len = &text_len;
+ } else if (s->flags & SEC_DATA) {
+@@ -1932,8 +1937,7 @@ int main(int argc, char *argv[])
+ * data sections.*/
+ for (s = abs_bfd->sections; s != NULL; s = s->next)
+ if ((s->flags & SEC_CODE) ||
+- ((s->flags & (SEC_DATA | SEC_READONLY | SEC_RELOC)) ==
+- (SEC_DATA | SEC_READONLY | SEC_RELOC)))
++ ro_reloc_data_section_should_be_in_text(s))
+ if (!bfd_get_section_contents(abs_bfd, s,
+ text + (s->vma - text_vma), 0,
+ bfd_section_size(abs_bfd, s)))
+@@ -1962,8 +1966,7 @@ int main(int argc, char *argv[])
+ * data sections already included in the text output section.*/
+ for (s = abs_bfd->sections; s != NULL; s = s->next)
+ if ((s->flags & SEC_DATA) &&
+- ((s->flags & (SEC_READONLY | SEC_RELOC)) !=
+- (SEC_READONLY | SEC_RELOC)))
++ !ro_reloc_data_section_should_be_in_text(s))
+ if (!bfd_get_section_contents(abs_bfd, s,
+ data + (s->vma - data_vma), 0,
+ bfd_section_size(abs_bfd, s)))
+--
+2.37.1
+
diff --git a/toolchain/elf2flt/patches/v2021.08/0005-elf2flt-fix-fatal-error-regression-on-m68k-xtensa-ri.patch b/toolchain/elf2flt/patches/v2021.08/0005-elf2flt-fix-fatal-error-regression-on-m68k-xtensa-ri.patch
new file mode 100644
index 000000000..616bbc891
--- /dev/null
+++ b/toolchain/elf2flt/patches/v2021.08/0005-elf2flt-fix-fatal-error-regression-on-m68k-xtensa-ri.patch
@@ -0,0 +1,74 @@
+From a8c9f650b82109abf7aa730f298ea5182ed62613 Mon Sep 17 00:00:00 2001
+From: Niklas Cassel <niklas.cassel@wdc.com>
+Date: Tue, 9 Aug 2022 21:06:05 +0200
+Subject: [PATCH] elf2flt: fix fatal error regression on m68k, xtensa, riscv64
+
+Commit ba379d08bb78 ("elf2flt: fix for segfault on some ARM ELFs")
+changed the condition of which input sections that should be included
+in the .text output section from:
+((a->flags & (SEC_DATA | SEC_READONLY)) == (SEC_DATA | SEC_READONLY))
+to:
+((a->flags & (SEC_DATA | SEC_READONLY | SEC_RELOC)) ==
+(SEC_DATA | SEC_READONLY | SEC_RELOC))
+
+On ARM, the .eh_frame input section does not have the SEC_RELOC flag set,
+so on ARM, this change caused .eh_frame to move from .text to .data.
+
+However, on e.g. m68k, xtensa and riscv64, the .eh_frame input section
+does have the SEC_RELOC flag set, which means that the change in
+commit ba379d08bb78 ("elf2flt: fix for segfault on some ARM ELFs")
+caused .eh_frame to move in an opposite way, i.e. from .data to .text.
+
+This resulted in a fatal error on m68k, xtensa and riscv64:
+ERROR: text=0x3bab8 overlaps data=0x33f60 ?
+
+This is because elf2flt cannot append to .text after .data has been
+appended to.
+
+Note that the binutils maintainer says that the correct thing is
+to put read-only relocation data sections in .text:
+https://sourceware.org/legacy-ml/binutils/2019-10/msg00132.html
+
+So the proper fix is probably to rewrite elf2flt so that it can append
+to .text after .data has been appended to (which will require elf2flt
+to move/relocate everything that has already been appended to .data,
+since the virtual addresses are contiguous).
+
+However, for now, add an exception for input sections which have all
+three flags SEC_DATA, SEC_READONLY, and SEC_RELOC set, and which have a
+name equal to a problematic input section (.eh_frame, .gcc_except_table).
+That way, we get the same behavior as older elf2flt releases for m68k,
+xtensa and riscv64, where we put read-only relocation data in .data,
+which was working perfectly fine.
+
+This exception will not change any behavior on ARM, as the .eh_frame
+input section does not have flag SEC_RELOC set.
+
+Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com>
+---
+ elf2flt.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/elf2flt.c b/elf2flt.c
+index e0d7891..39d035f 100644
+--- a/elf2flt.c
++++ b/elf2flt.c
+@@ -341,8 +341,13 @@ compare_relocs (const void *pa, const void *pb)
+ static bool
+ ro_reloc_data_section_should_be_in_text(asection *s)
+ {
+- return (s->flags & (SEC_DATA | SEC_READONLY | SEC_RELOC)) ==
+- (SEC_DATA | SEC_READONLY | SEC_RELOC);
++ if ((s->flags & (SEC_DATA | SEC_READONLY | SEC_RELOC)) ==
++ (SEC_DATA | SEC_READONLY | SEC_RELOC)) {
++ if (!strcmp(".eh_frame", s->name) || !strcmp(".gcc_except_table", s->name))
++ return false;
++ return true;
++ }
++ return false;
+ }
+
+ static uint32_t *
+--
+2.39.0
+
diff --git a/toolchain/elf2flt/patches/v2021.08/0006-elf2flt-xtensa-fix-text-relocations.patch b/toolchain/elf2flt/patches/v2021.08/0006-elf2flt-xtensa-fix-text-relocations.patch
new file mode 100644
index 000000000..fc8784a1b
--- /dev/null
+++ b/toolchain/elf2flt/patches/v2021.08/0006-elf2flt-xtensa-fix-text-relocations.patch
@@ -0,0 +1,25 @@
+diff -Nur elf2flt-v2021.08.orig/elf2flt.c elf2flt-v2021.08/elf2flt.c
+--- elf2flt-v2021.08.orig/elf2flt.c 2023-01-09 11:08:28.637676113 +0100
++++ elf2flt-v2021.08/elf2flt.c 2023-01-09 11:09:04.502804007 +0100
+@@ -835,7 +835,20 @@
+ continue;
+ case R_XTENSA_32:
+ case R_XTENSA_PLT:
+- goto good_32bit_resolved_reloc;
++ if (bfd_big_endian (abs_bfd))
++ sym_addr =
++ (r_mem[0] << 24)
++ + (r_mem[1] << 16)
++ + (r_mem[2] << 8)
++ + r_mem[3];
++ else
++ sym_addr =
++ r_mem[0]
++ + (r_mem[1] << 8)
++ + (r_mem[2] << 16)
++ + (r_mem[3] << 24);
++ relocation_needed = 1;
++ break;
+ default:
+ goto bad_resolved_reloc;
+ #elif defined(TARGET_riscv64)
diff --git a/toolchain/elf2flt/patches/v2021.08/0007-riscv32.patch b/toolchain/elf2flt/patches/v2021.08/0007-riscv32.patch
new file mode 100644
index 000000000..b3c4677be
--- /dev/null
+++ b/toolchain/elf2flt/patches/v2021.08/0007-riscv32.patch
@@ -0,0 +1,56 @@
+diff -Nur elf2flt-v2021.08.orig/elf2flt.c elf2flt-v2021.08/elf2flt.c
+--- elf2flt-v2021.08.orig/elf2flt.c 2023-02-26 11:31:48.758810872 +0100
++++ elf2flt-v2021.08/elf2flt.c 2023-02-26 11:32:05.714465277 +0100
+@@ -81,7 +81,7 @@
+ #include <elf/v850.h>
+ #elif defined(TARGET_xtensa)
+ #include <elf/xtensa.h>
+-#elif defined(TARGET_riscv64)
++#elif defined(TARGET_riscv64) || defined(TARGET_riscv32)
+ #include <elf/riscv.h>
+ #endif
+
+@@ -127,6 +127,8 @@
+ #define ARCH "xtensa"
+ #elif defined(TARGET_riscv64)
+ #define ARCH "riscv64"
++#elif defined(TARGET_riscv32)
++#define ARCH "riscv32"
+ #else
+ #error "Don't know how to support your CPU architecture??"
+ #endif
+@@ -849,12 +851,21 @@
+ break;
+ default:
+ goto bad_resolved_reloc;
+-#elif defined(TARGET_riscv64)
++#elif defined(TARGET_riscv64) || defined(TARGET_riscv32)
+ case R_RISCV_32_PCREL:
++ case R_RISCV_ADD8:
++ case R_RISCV_ADD16:
+ case R_RISCV_ADD32:
+ case R_RISCV_ADD64:
++ case R_RISCV_SUB6:
++ case R_RISCV_SUB8:
++ case R_RISCV_SUB16:
+ case R_RISCV_SUB32:
+ case R_RISCV_SUB64:
++ case R_RISCV_SET6:
++ case R_RISCV_SET8:
++ case R_RISCV_SET16:
++ case R_RISCV_SET32:
+ continue;
+ case R_RISCV_32:
+ case R_RISCV_64:
+diff -Nur elf2flt-v2021.08.orig/ld-elf2flt.c elf2flt-v2021.08/ld-elf2flt.c
+--- elf2flt-v2021.08.orig/ld-elf2flt.c 2023-02-26 11:31:21.047376888 +0100
++++ elf2flt-v2021.08/ld-elf2flt.c 2023-02-26 11:32:05.714465277 +0100
+@@ -327,7 +327,7 @@
+ /* riscv adds a global pointer symbol to the linker file with the
+ "RISCV_GP:" prefix. Remove the prefix for riscv64 architecture and
+ the entire line for other architectures. */
+- if (streq(TARGET_CPU, "riscv64"))
++ if (streq(TARGET_CPU, "riscv64") || streq(TARGET_CPU, "riscv32"))
+ append_sed(&sed, "^RISCV_GP:", "");
+ else
+ append_sed(&sed, "^RISCV_GP:", NULL);
diff --git a/toolchain/elf2flt/patches/v2021.08/0008-remove_BFD_VMA_FMT.patch b/toolchain/elf2flt/patches/v2021.08/0008-remove_BFD_VMA_FMT.patch
new file mode 100644
index 000000000..6367f1383
--- /dev/null
+++ b/toolchain/elf2flt/patches/v2021.08/0008-remove_BFD_VMA_FMT.patch
@@ -0,0 +1,97 @@
+diff -Nur elf2flt-v2021.08.orig/elf2flt.c elf2flt-v2021.08/elf2flt.c
+--- elf2flt-v2021.08.orig/elf2flt.c 2023-01-29 16:47:24.791851890 +0100
++++ elf2flt-v2021.08/elf2flt.c 2023-01-29 16:49:46.628476326 +0100
+@@ -222,7 +222,7 @@
+ long i;
+ printf("SYMBOL TABLE:\n");
+ for (i=0; i<number_of_symbols; i++) {
+- printf(" NAME=%s VALUE=0x%"BFD_VMA_FMT"x\n",
++ printf(" NAME=%s VALUE=0x%x\n",
+ symbol_table[i]->name, symbol_table[i]->value);
+ }
+ printf("\n");
+@@ -471,7 +471,7 @@
+ if (r == NULL)
+ continue;
+ if (verbose)
+- printf(" RELOCS: %s [%p]: flags=0x%x vma=0x%"BFD_VMA_FMT"x\n",
++ printf(" RELOCS: %s [%p]: flags=0x%x vma=0x%x\n",
+ r->name, r, r->flags, elf2flt_bfd_section_vma(r));
+ if ((r->flags & SEC_RELOC) == 0)
+ continue;
+@@ -966,8 +966,8 @@
+ if (verbose)
+ fprintf(stderr,
+ "%s vma=0x%x, "
+- "value=0x%"BFD_VMA_FMT"x, "
+- "address=0x%"BFD_VMA_FMT"x "
++ "value=0x%x, "
++ "address=0x%x "
+ "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
+ "ABS32",
+ sym_vma, (*(q->sym_ptr_ptr))->value,
+@@ -985,8 +985,8 @@
+ if (verbose)
+ fprintf(stderr,
+ "%s vma=0x%x, "
+- "value=0x%"BFD_VMA_FMT"x, "
+- "address=0x%"BFD_VMA_FMT"x "
++ "value=0x%x, "
++ "address=0x%x "
+ "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
+ "PLT32",
+ sym_vma, (*(q->sym_ptr_ptr))->value,
+@@ -1008,7 +1008,7 @@
+ case R_V850_ZDA_16_16_OFFSET:
+ case R_V850_ZDA_16_16_SPLIT_OFFSET:
+ /* Can't support zero-relocations. */
+- printf ("ERROR: %s+0x%"BFD_VMA_FMT"x: zero relocations not supported\n",
++ printf ("ERROR: %s+0x%x: zero relocations not supported\n",
+ sym_name, q->addend);
+ continue;
+ #endif /* TARGET_v850 */
+@@ -1208,9 +1208,9 @@
+ temp |= (exist_val & 0x3f);
+ *(unsigned long *)r_mem = htoniosl(temp);
+ if (verbose)
+- printf("omit: offset=0x%"BFD_VMA_FMT"x symbol=%s%s "
++ printf("omit: offset=0x%x symbol=%s%s "
+ "section=%s size=%d "
+- "fixup=0x%x (reloc=0x%"BFD_VMA_FMT"x) GPREL\n",
++ "fixup=0x%x (reloc=0x%x) GPREL\n",
+ q->address, sym_name, addstr,
+ section_name, sym_reloc_size,
+ sym_addr, section_vma + q->address);
+@@ -1228,9 +1228,9 @@
+ exist_val |= ((sym_addr & 0xFFFF) << 6);
+ *(unsigned long *)r_mem = htoniosl(exist_val);
+ if (verbose)
+- printf("omit: offset=0x%"BFD_VMA_FMT"x symbol=%s%s "
++ printf("omit: offset=0x%x symbol=%s%s "
+ "section=%s size=%d "
+- "fixup=0x%x (reloc=0x%"BFD_VMA_FMT"x) PCREL\n",
++ "fixup=0x%x (reloc=0x%x) PCREL\n",
+ q->address, sym_name, addstr,
+ section_name, sym_reloc_size,
+ sym_addr, section_vma + q->address);
+@@ -1245,7 +1245,7 @@
+ && (p[-1]->sym_ptr_ptr == p[0]->sym_ptr_ptr)
+ && (p[-1]->addend == p[0]->addend)) {
+ if (verbose)
+- printf("omit: offset=0x%"BFD_VMA_FMT"x symbol=%s%s "
++ printf("omit: offset=0x%x symbol=%s%s "
+ "section=%s size=%d LO16\n",
+ q->address, sym_name, addstr,
+ section_name, sym_reloc_size);
+@@ -1660,9 +1660,9 @@
+ */
+ if (relocation_needed) {
+ if (verbose)
+- printf(" RELOC[%d]: offset=0x%"BFD_VMA_FMT"x symbol=%s%s "
++ printf(" RELOC[%d]: offset=0x%x symbol=%s%s "
+ "section=%s size=%d "
+- "fixup=0x%x (reloc=0x%"BFD_VMA_FMT"x)\n",
++ "fixup=0x%x (reloc=0x%x)\n",
+ flat_reloc_count,
+ q->address, sym_name, addstr,
+ section_name, sym_reloc_size,
diff --git a/toolchain/elf2flt/patches/v2021.08/0009-riscv.patch b/toolchain/elf2flt/patches/v2021.08/0009-riscv.patch
new file mode 100644
index 000000000..c1072cb45
--- /dev/null
+++ b/toolchain/elf2flt/patches/v2021.08/0009-riscv.patch
@@ -0,0 +1,11 @@
+diff -Nur elf2flt-v2021.08.orig/elf2flt.c elf2flt-v2021.08/elf2flt.c
+--- elf2flt-v2021.08.orig/elf2flt.c 2023-02-26 11:32:05.714465277 +0100
++++ elf2flt-v2021.08/elf2flt.c 2023-02-26 15:04:52.726514896 +0100
+@@ -852,6 +852,7 @@
+ default:
+ goto bad_resolved_reloc;
+ #elif defined(TARGET_riscv64) || defined(TARGET_riscv32)
++ case R_RISCV_NONE:
+ case R_RISCV_32_PCREL:
+ case R_RISCV_ADD8:
+ case R_RISCV_ADD16:
diff --git a/toolchain/elf2flt/patches/v2024.02/0001-sh2.patch b/toolchain/elf2flt/patches/v2024.02/0001-sh2.patch
new file mode 100644
index 000000000..b14a78e23
--- /dev/null
+++ b/toolchain/elf2flt/patches/v2024.02/0001-sh2.patch
@@ -0,0 +1,43 @@
+diff -Nur elf2flt-v2023.09.orig/elf2flt.c elf2flt-v2023.09/elf2flt.c
+--- elf2flt-v2023.09.orig/elf2flt.c 2023-12-22 10:44:11.000000000 +0100
++++ elf2flt-v2023.09/elf2flt.c 2023-12-23 02:26:06.323239781 +0100
+@@ -73,7 +73,7 @@
+ #define FLAT_NIOS2_R_HIADJ_LO 2
+ #define FLAT_NIOS2_R_CALL26 4
+ #include <elf/nios2.h>
+-#elif defined(TARGET_sh)
++#elif defined(TARGET_sh2) || defined(TARGET_sh2eb)
+ #include <elf/sh.h>
+ #elif defined(TARGET_sparc)
+ #include <elf/sparc.h>
+@@ -109,8 +109,10 @@
+ #define ARCH "sparc"
+ #elif defined(TARGET_v850)
+ #define ARCH "v850"
+-#elif defined(TARGET_sh)
+-#define ARCH "sh"
++#elif defined(TARGET_sh2)
++#define ARCH "sh2"
++#elif defined(TARGET_sh2eb)
++#define ARCH "sh2"
+ #elif defined(TARGET_h8300)
+ #define ARCH "h8300"
+ #elif defined(TARGET_microblaze)
+@@ -1289,7 +1291,7 @@
+ #endif /* TARGET_sparc */
+
+
+-#ifdef TARGET_sh
++#if defined(TARGET_sh2) || defined(TARGET_sh2eb)
+ case R_SH_DIR32:
+ relocation_needed = 1;
+ sym_vma = elf2flt_bfd_section_vma(sym_section);
+@@ -1300,7 +1302,7 @@
+ sym_addr += sym_vma + q->addend;
+ sym_addr -= q->address;
+ break;
+-#endif /* TARGET_sh */
++#endif /* TARGET_sh2 / TARGET_sh2eb */
+
+ #ifdef TARGET_e1
+ #define htoe1l(x) htonl(x)
diff --git a/toolchain/elf2flt/patches/v2024.02/0002-h8300.patch b/toolchain/elf2flt/patches/v2024.02/0002-h8300.patch
new file mode 100644
index 000000000..2c7b73482
--- /dev/null
+++ b/toolchain/elf2flt/patches/v2024.02/0002-h8300.patch
@@ -0,0 +1,20 @@
+diff -Nur elf2flt-v2023.09.orig/flthdr.c elf2flt-v2023.09/flthdr.c
+--- elf2flt-v2023.09.orig/flthdr.c 2023-12-23 03:20:20.000000000 +0100
++++ elf2flt-v2023.09/flthdr.c 2023-12-23 17:11:22.699413170 +0100
+@@ -164,8 +164,16 @@
+ r = ntohl(relocs[i]);
+ raddr = flat_get_relocate_addr(r);
+ printf(" %u\t0x%08lx (0x%08"PRIx32")\t", i, r, raddr);
++#if defined(TARGET_h8300)
++ raddr &= ~0x00000001;
++#endif
+ fseek_stream(&ifp, sizeof(old_hdr) + raddr, SEEK_SET);
+ fread_stream(&addr, sizeof(addr), 1, &ifp);
++#if defined(TARGET_h8300)
++ addr = ntohl(addr);
++ if (r & 1)
++ addr &= 0x00ffffff;
++#endif
+ printf("%"PRIx32"\n", addr);
+ }
+
diff --git a/toolchain/elf2flt/patches/v2024.02/0003-riscv64-alignment.patch b/toolchain/elf2flt/patches/v2024.02/0003-riscv64-alignment.patch
new file mode 100644
index 000000000..9feef7951
--- /dev/null
+++ b/toolchain/elf2flt/patches/v2024.02/0003-riscv64-alignment.patch
@@ -0,0 +1,12 @@
+diff -Nur elf2flt-v2024.02.orig/elf2flt.ld.in elf2flt-v2024.02/elf2flt.ld.in
+--- elf2flt-v2024.02.orig/elf2flt.ld.in 2024-03-22 04:51:08.000000000 +0100
++++ elf2flt-v2024.02/elf2flt.ld.in 2024-03-22 13:08:31.793773247 +0100
+@@ -139,7 +139,7 @@
+ @SYMBOL_PREFIX@_ssro_size = @SYMBOL_PREFIX@_essro - @SYMBOL_PREFIX@_ssro;
+ PROVIDE(@SYMBOL_PREFIX@_SDA2_BASE_ = @SYMBOL_PREFIX@_ssro + (@SYMBOL_PREFIX@_ssro_size / 2));
+
+- . = ALIGN(4) ;
++ . = ALIGN(8) ;
+ TOR: @SYMBOL_PREFIX@__CTOR_LIST__ = .;
+ TOR: LONG((@SYMBOL_PREFIX@__CTOR_END__ - @SYMBOL_PREFIX@__CTOR_LIST__) / 4 - 2)
+ SINGLE_LINK: /* gcc uses crtbegin.o to find the start of
diff --git a/toolchain/gcc/Makefile b/toolchain/gcc/Makefile
index 3f533bad9..175af8aae 100644
--- a/toolchain/gcc/Makefile
+++ b/toolchain/gcc/Makefile
@@ -26,6 +26,15 @@ ifeq ($(ADK_TARGET_ARCH_ARM),y)
TARGET_CFLAGS:= $(filter-out -mcpu=cortex-a9,$(TARGET_CFLAGS))
TARGET_CXXFLAGS:= $(filter-out -mcpu=cortex-a9,$(TARGET_CXXFLAGS))
endif
+ifeq ($(ADK_TARGET_ARCH_ARM),y)
+TARGET_CFLAGS:= $(filter-out -mcpu=cortex-a7,$(TARGET_CFLAGS))
+TARGET_CXXFLAGS:= $(filter-out -mcpu=cortex-a7,$(TARGET_CXXFLAGS))
+endif
+
+ifeq ($(ADK_TARGET_ARCH_ARM),y)
+TARGET_CFLAGS:= $(filter-out -mcpu=xscale,$(TARGET_CFLAGS))
+TARGET_CXXFLAGS:= $(filter-out -mcpu=xscale,$(TARGET_CXXFLAGS))
+endif
ifeq ($(ADK_TARGET_USE_STATIC_AND_SHARED_LIBS),y)
TARGET_CFLAGS:= $(filter-out -static,$(TARGET_CFLAGS))
@@ -54,6 +63,7 @@ GCC_CONFOPTS:= --prefix=$(TOOLCHAIN_DIR)/usr \
--disable-libquadmath \
--disable-libquadmath-support \
--disable-decimal-float \
+ --disable-gcov \
--disable-libstdcxx-pch \
--disable-ppl-version-check \
--disable-cloog-version-check \
@@ -155,10 +165,6 @@ ifeq ($(ADK_TARGET_ARCH_METAG),y)
GCC_CONFOPTS+= --with-cpu=2.1 --enable-meta-default --disable-symvers
endif
-ifeq ($(ADK_TARGET_CPU_CF),y)
-GCC_CONFOPTS+= --with-arch=cf --disable-multilib
-endif
-
ifeq ($(ADK_TARGET_ARCH_NDS32),y)
GCC_CONFOPTS+= --with-arch=v3
endif
@@ -167,6 +173,16 @@ ifeq ($(ADK_TARGET_ARCH_M68K)$(ADK_TARGET_ARCH_X86_64)$(ADK_TARGET_ARCH_X86),)
GCC_FINAL_CONFOPTS+= --disable-biarch --disable-multilib
endif
+ifeq ($(ADK_TARGET_CPU_CF),y)
+GCC_CONFOPTS+= --with-arch=cf
+GCC_INITIAL_CONFOPTS+= --enable-multilib
+ifeq ($(ADK_TARGET_BINFMT_ELF)$(ADK_TARGET_WITH_MMU),y)
+GCC_FINAL_CONFOPTS+= --disable-multilib --disable-threads --disable-libatomic
+endif
+else
+GCC_INITIAL_CONFOPTS+= --disable-multilib
+endif
+
ifeq ($(ADK_TARGET_ARCH_SH),y)
ifeq ($(ADK_TARGET_LITTLE_ENDIAN),y)
@@ -299,6 +315,12 @@ ifeq ($(ADK_TARGET_CPU_SH_SH4A),y)
(cd ${STAGING_TARGET_DIR}/ && ln -sf . m4a)
endif
endif
+ifeq ($(ADK_TARGET_ARCH_M68K),y)
+ # Need to get gcc to generate _all_ the multilib variants
+ # (so both MMU and non-mmu M68k and ColdFire).
+ $(SED) 's/M68K_MLIB_CPU +=/#M68K_MLIB_CPU +=/' $(WRKBUILD)/gcc/config/m68k/t-m68k
+ $(SED) 's/&& (FLAGS ~ "FL_MMU")//' $(WRKBUILD)/gcc/config/m68k/t-linux
+endif
$(SED) '/k prot/agcc_cv_libc_provides_ssp=yes' $(WRKBUILD)/gcc/configure
cd $(GCC_BUILD_DIR_INITIAL); \
PATH='$(TARGET_PATH)' \
@@ -307,13 +329,13 @@ endif
CFLAGS="-O0 -g0 -fomit-frame-pointer" \
CXXFLAGS="-O0 -g0 -fomit-frame-pointer" \
$(WRKBUILD)/configure \
+ ${GCC_INITIAL_CONFOPTS} \
${GCC_CONFOPTS} \
${GCC_TLS_CONFOPTS} \
--enable-languages=c \
--with-newlib \
--disable-shared \
--disable-threads \
- --disable-multilib \
--without-headers
touch $@
diff --git a/toolchain/gcc/Makefile.inc b/toolchain/gcc/Makefile.inc
index b765f9b66..b6c24865a 100644
--- a/toolchain/gcc/Makefile.inc
+++ b/toolchain/gcc/Makefile.inc
@@ -2,52 +2,69 @@
# material, please see the LICENCE file in the top-level directory.
PKG_NAME:= gcc
+ifeq ($(ADK_TOOLCHAIN_GCC_13),y)
+PKG_VERSION:= 13.2.0
+PKG_HASH:= 8cb4be3796651976f94b9356fa08d833524f62420d6292c5033a9a26af315078
+PKG_SITES:= ${MASTER_SITE_GNU:=gcc/gcc-${PKG_VERSION}/}
+PKG_RELEASE:= 1
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
+LIBSTDCXXVER:= 29
+endif
+ifeq ($(ADK_TOOLCHAIN_GCC_12),y)
+PKG_VERSION:= 12.3.0
+PKG_HASH:= 11275aa7bb34cd8ab101d01b341015499f8d9466342a2574ece93f954d92273b
+PKG_SITES:= ${MASTER_SITE_GNU:=gcc/gcc-${PKG_VERSION}/}
+PKG_RELEASE:= 1
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
+LIBSTDCXXVER:= 28
+endif
ifeq ($(ADK_TOOLCHAIN_GCC_11),y)
-PKG_VERSION:= 11.2.0
-PKG_HASH:= d08edc536b54c372a1010ff6619dd274c0f1603aa49212ba20f7aa2cda36fa8b
+PKG_VERSION:= 11.4.0
+PKG_HASH:= af828619dd1970734dda3cfb792ea3f2cba61b5a00170ba8bce4910749d73c07
PKG_SITES:= ${MASTER_SITE_GNU:=gcc/gcc-${PKG_VERSION}/}
PKG_RELEASE:= 1
-DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
LIBSTDCXXVER:= 27
endif
ifeq ($(ADK_TOOLCHAIN_GCC_10),y)
-PKG_VERSION:= 10.3.0
-PKG_HASH:= 64f404c1a650f27fc33da242e1f2df54952e3963a49e06e73f6940f3223ac344
+PKG_VERSION:= 10.5.0
+PKG_HASH:= eed4dd5fc3cd9f52cb3a51a4fde1728cb19ec76292f559518e83652e7437befe
PKG_SITES:= ${MASTER_SITE_GNU:=gcc/gcc-${PKG_VERSION}/}
PKG_RELEASE:= 1
-DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
LIBSTDCXXVER:= 26
endif
ifeq ($(ADK_TOOLCHAIN_GCC_9),y)
-PKG_VERSION:= 9.4.0
-PKG_HASH:= c95da32f440378d7751dd95533186f7fc05ceb4fb65eb5b85234e6299eb9838e
+PKG_VERSION:= 9.5.0
+PKG_HASH:= 15b34072105272a3eb37f6927409f7ce9aa0dd1498efebc35f851d6e6f029a4d
PKG_SITES:= ${MASTER_SITE_GNU:=gcc/gcc-${PKG_VERSION}/}
PKG_RELEASE:= 1
-DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
LIBSTDCXXVER:= 25
endif
ifeq ($(ADK_TOOLCHAIN_GCC_8),y)
PKG_VERSION:= 8.5.0
-PKG_HASH:= d308841a511bb830a6100397b0042db24ce11f642dab6ea6ee44842e5325ed50
+PKG_HASH:= 6e6e0628573d2185727a2dd83211d04a2b2748e4a262099099b9c8064634c9ee
PKG_SITES:= ${MASTER_SITE_GNU:=gcc/gcc-${PKG_VERSION}/}
PKG_RELEASE:= 1
-DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
LIBSTDCXXVER:= 24
endif
ifeq ($(ADK_TOOLCHAIN_GCC_7),y)
PKG_VERSION:= 7.5.0
-PKG_HASH:= b81946e7f01f90528a1f7352ab08cc602b9ccc05d4e44da4bd501c5a189ee661
+PKG_HASH:= 4f518f18cfb694ad7975064e99e200fe98af13603b47e67e801ba9580e50a07f
PKG_SITES:= ${MASTER_SITE_GNU:=gcc/gcc-${PKG_VERSION}/}
PKG_RELEASE:= 1
-DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
LIBSTDCXXVER:= 23
endif
ifeq ($(ADK_TOOLCHAIN_GCC_ARC),y)
-PKG_VERSION:= arc-2020.09
-PKG_GIT:= tag
-PKG_SITES:= https://github.com/foss-for-synopsys-dwc-arc-processors/gcc.git
-PKG_RELEASE:= 1
-DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
+PKG_VERSION:= arc-2023.09
+PKG_GIT:= tag
+PKG_SITES:= https://github.com/foss-for-synopsys-dwc-arc-processors/gcc.git
+PKG_RELEASE:= 1
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
+LIBSTDCXXVER:= 29
endif
ifeq ($(ADK_TOOLCHAIN_GCC_AVR32),y)
PKG_VERSION:= 4.4.7
@@ -57,6 +74,14 @@ PKG_RELEASE:= 1
DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
LIBSTDCXXVER:= 19
endif
+ifeq ($(ADK_TOOLCHAIN_GCC_LM32),y)
+PKG_VERSION:= 4.5.4
+PKG_HASH:= 33fb968907ef7b6c528f6395ba049eb34c4df859bf5aa6c2bc3856268801e078
+PKG_SITES:= https://ftp.gnu.org/gnu/gcc/gcc-$(PKG_VERSION)/
+PKG_RELEASE:= 1
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
+LIBSTDCXXVER:= 19
+endif
ifeq ($(ADK_TOOLCHAIN_GCC_METAG),y)
PKG_VERSION:= 4.2.4
PKG_HASH:= 7cb75c5183bd18f415860084440377016dc78feeee2852227b831f2e4fcaa5d6
@@ -66,26 +91,11 @@ DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
LIBSTDCXXVER:= 19
endif
ifeq ($(ADK_TOOLCHAIN_GCC_KVX),y)
-PKG_VERSION:= 50bb1935d20f383c3d37c98b681f63de873688b2
+PKG_VERSION:= f98c17b1e78dd3a3da45c0ac1af7b105edf2bf66
PKG_GIT:= hash
PKG_SITES:= https://github.com/kalray/gcc.git
PKG_RELEASE:= 1
-DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
-endif
-ifeq ($(ADK_TOOLCHAIN_GCC_LM32),y)
-PKG_VERSION:= 4.5.4
-PKG_HASH:= 33fb968907ef7b6c528f6395ba049eb34c4df859bf5aa6c2bc3856268801e078
-PKG_SITES:= https://ftp.gnu.org/gnu/gcc/gcc-$(PKG_VERSION)/
-PKG_RELEASE:= 1
DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
-LIBSTDCXXVER:= 19
-endif
-ifeq ($(ADK_TOOLCHAIN_GCC_NDS32),y)
-PKG_VERSION:= nds32-6.3.0-open
-PKG_HASH:= b23ce96df25dfdd5526496a3c2cd7ee1da4ed4094971a2e0c47c73ad7e1ad30a
-PKG_SITES:= https://github.com/andestech/gcc.git
-PKG_RELEASE:= 1
-DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
endif
ifeq ($(ADK_TOOLCHAIN_GCC_GIT),y)
PKG_VERSION:= git
diff --git a/toolchain/gcc/patches/10.3.0/revert-sparc.patch b/toolchain/gcc/patches/10.3.0/revert-sparc.patch
deleted file mode 100644
index 5df11ce40..000000000
--- a/toolchain/gcc/patches/10.3.0/revert-sparc.patch
+++ /dev/null
@@ -1,23628 +0,0 @@
-diff -Nur gcc-10.3.0.orig/gcc/config/sparc/sparc.c gcc-10.3.0/gcc/config/sparc/sparc.c
---- gcc-10.3.0.orig/gcc/config/sparc/sparc.c 2021-04-08 13:56:28.201742273 +0200
-+++ gcc-10.3.0/gcc/config/sparc/sparc.c 2021-04-09 07:51:37.884501308 +0200
-@@ -4157,6 +4157,13 @@
- static bool
- sparc_cannot_force_const_mem (machine_mode mode, rtx x)
- {
-+ /* After IRA has run in PIC mode, it is too late to put anything into the
-+ constant pool if the PIC register hasn't already been initialized. */
-+ if ((lra_in_progress || reload_in_progress)
-+ && flag_pic
-+ && !crtl->uses_pic_offset_table)
-+ return true;
-+
- switch (GET_CODE (x))
- {
- case CONST_INT:
-@@ -4192,11 +4199,9 @@
- }
-
- /* Global Offset Table support. */
--static GTY(()) rtx got_symbol_rtx = NULL_RTX;
--static GTY(()) rtx got_register_rtx = NULL_RTX;
- static GTY(()) rtx got_helper_rtx = NULL_RTX;
--
--static GTY(()) bool got_helper_needed = false;
-+static GTY(()) rtx got_register_rtx = NULL_RTX;
-+static GTY(()) rtx got_symbol_rtx = NULL_RTX;
-
- /* Return the SYMBOL_REF for the Global Offset Table. */
-
-@@ -4209,6 +4214,27 @@
- return got_symbol_rtx;
- }
-
-+#ifdef HAVE_GAS_HIDDEN
-+# define USE_HIDDEN_LINKONCE 1
-+#else
-+# define USE_HIDDEN_LINKONCE 0
-+#endif
-+
-+static void
-+get_pc_thunk_name (char name[32], unsigned int regno)
-+{
-+ const char *reg_name = reg_names[regno];
-+
-+ /* Skip the leading '%' as that cannot be used in a
-+ symbol name. */
-+ reg_name += 1;
-+
-+ if (USE_HIDDEN_LINKONCE)
-+ sprintf (name, "__sparc_get_pc_thunk.%s", reg_name);
-+ else
-+ ASM_GENERATE_INTERNAL_LABEL (name, "LADDPC", regno);
-+}
-+
- /* Wrapper around the load_pcrel_sym{si,di} patterns. */
-
- static rtx
-@@ -4228,78 +4254,30 @@
- return insn;
- }
-
--/* Output the load_pcrel_sym{si,di} patterns. */
--
--const char *
--output_load_pcrel_sym (rtx *operands)
--{
-- if (flag_delayed_branch)
-- {
-- output_asm_insn ("sethi\t%%hi(%a1-4), %0", operands);
-- output_asm_insn ("call\t%a2", operands);
-- output_asm_insn (" add\t%0, %%lo(%a1+4), %0", operands);
-- }
-- else
-- {
-- output_asm_insn ("sethi\t%%hi(%a1-8), %0", operands);
-- output_asm_insn ("add\t%0, %%lo(%a1-4), %0", operands);
-- output_asm_insn ("call\t%a2", operands);
-- output_asm_insn (" nop", NULL);
-- }
--
-- if (operands[2] == got_helper_rtx)
-- got_helper_needed = true;
--
-- return "";
--}
--
--#ifdef HAVE_GAS_HIDDEN
--# define USE_HIDDEN_LINKONCE 1
--#else
--# define USE_HIDDEN_LINKONCE 0
--#endif
--
- /* Emit code to load the GOT register. */
-
- void
- load_got_register (void)
- {
-- rtx insn;
-+ if (!got_register_rtx)
-+ got_register_rtx = gen_rtx_REG (Pmode, GLOBAL_OFFSET_TABLE_REGNUM);
-
- if (TARGET_VXWORKS_RTP)
-- {
-- if (!got_register_rtx)
-- got_register_rtx = pic_offset_table_rtx;
--
-- insn = gen_vxworks_load_got ();
-- }
-+ emit_insn (gen_vxworks_load_got ());
- else
- {
-- if (!got_register_rtx)
-- got_register_rtx = gen_rtx_REG (Pmode, GLOBAL_OFFSET_TABLE_REGNUM);
--
- /* The GOT symbol is subject to a PC-relative relocation so we need a
- helper function to add the PC value and thus get the final value. */
- if (!got_helper_rtx)
- {
- char name[32];
--
-- /* Skip the leading '%' as that cannot be used in a symbol name. */
-- if (USE_HIDDEN_LINKONCE)
-- sprintf (name, "__sparc_get_pc_thunk.%s",
-- reg_names[REGNO (got_register_rtx)] + 1);
-- else
-- ASM_GENERATE_INTERNAL_LABEL (name, "LADDPC",
-- REGNO (got_register_rtx));
--
-+ get_pc_thunk_name (name, GLOBAL_OFFSET_TABLE_REGNUM);
- got_helper_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
- }
-
-- insn
-- = gen_load_pcrel_sym (got_register_rtx, sparc_got (), got_helper_rtx);
-+ emit_insn (gen_load_pcrel_sym (got_register_rtx, sparc_got (),
-+ got_helper_rtx));
- }
--
-- emit_insn (insn);
- }
-
- /* Ensure that we are not using patterns that are not OK with PIC. */
-@@ -5464,7 +5442,7 @@
- return true;
-
- /* GOT register (%l7) if needed. */
-- if (got_register_rtx && regno == REGNO (got_register_rtx))
-+ if (regno == GLOBAL_OFFSET_TABLE_REGNUM && got_register_rtx)
- return true;
-
- /* If the function accesses prior frames, the frame pointer and the return
-@@ -12507,9 +12485,10 @@
- sparc_file_end (void)
- {
- /* If we need to emit the special GOT helper function, do so now. */
-- if (got_helper_needed)
-+ if (got_helper_rtx)
- {
- const char *name = XSTR (got_helper_rtx, 0);
-+ const char *reg_name = reg_names[GLOBAL_OFFSET_TABLE_REGNUM];
- #ifdef DWARF2_UNWIND_INFO
- bool do_cfi;
- #endif
-@@ -12546,22 +12525,17 @@
- #ifdef DWARF2_UNWIND_INFO
- do_cfi = dwarf2out_do_cfi_asm ();
- if (do_cfi)
-- output_asm_insn (".cfi_startproc", NULL);
-+ fprintf (asm_out_file, "\t.cfi_startproc\n");
- #endif
- if (flag_delayed_branch)
-- {
-- output_asm_insn ("jmp\t%%o7+8", NULL);
-- output_asm_insn (" add\t%%o7, %0, %0", &got_register_rtx);
-- }
-+ fprintf (asm_out_file, "\tjmp\t%%o7+8\n\t add\t%%o7, %s, %s\n",
-+ reg_name, reg_name);
- else
-- {
-- output_asm_insn ("add\t%%o7, %0, %0", &got_register_rtx);
-- output_asm_insn ("jmp\t%%o7+8", NULL);
-- output_asm_insn (" nop", NULL);
-- }
-+ fprintf (asm_out_file, "\tadd\t%%o7, %s, %s\n\tjmp\t%%o7+8\n\t nop\n",
-+ reg_name, reg_name);
- #ifdef DWARF2_UNWIND_INFO
- if (do_cfi)
-- output_asm_insn (".cfi_endproc", NULL);
-+ fprintf (asm_out_file, "\t.cfi_endproc\n");
- #endif
- }
-
-@@ -13056,10 +13030,7 @@
- edge entry_edge;
- rtx_insn *seq;
-
-- /* In PIC mode, we need to always initialize the PIC register if optimization
-- is enabled, because we are called from IRA and LRA may later force things
-- to the constant pool for optimization purposes. */
-- if (!flag_pic || (!crtl->uses_pic_offset_table && !optimize))
-+ if (!crtl->uses_pic_offset_table)
- return;
-
- start_sequence ();
-diff -Nur gcc-10.3.0.orig/gcc/config/sparc/sparc.c.orig gcc-10.3.0/gcc/config/sparc/sparc.c.orig
---- gcc-10.3.0.orig/gcc/config/sparc/sparc.c.orig 1970-01-01 01:00:00.000000000 +0100
-+++ gcc-10.3.0/gcc/config/sparc/sparc.c.orig 2021-04-08 13:56:28.201742273 +0200
-@@ -0,0 +1,13813 @@
-+/* Subroutines for insn-output.c for SPARC.
-+ Copyright (C) 1987-2020 Free Software Foundation, Inc.
-+ Contributed by Michael Tiemann (tiemann@cygnus.com)
-+ 64-bit SPARC-V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
-+ at Cygnus Support.
-+
-+This file is part of 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 3, 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 COPYING3. If not see
-+<http://www.gnu.org/licenses/>. */
-+
-+#define IN_TARGET_CODE 1
-+
-+#include "config.h"
-+#include "system.h"
-+#include "coretypes.h"
-+#include "backend.h"
-+#include "target.h"
-+#include "rtl.h"
-+#include "tree.h"
-+#include "memmodel.h"
-+#include "gimple.h"
-+#include "df.h"
-+#include "tm_p.h"
-+#include "stringpool.h"
-+#include "attribs.h"
-+#include "expmed.h"
-+#include "optabs.h"
-+#include "regs.h"
-+#include "emit-rtl.h"
-+#include "recog.h"
-+#include "diagnostic-core.h"
-+#include "alias.h"
-+#include "fold-const.h"
-+#include "stor-layout.h"
-+#include "calls.h"
-+#include "varasm.h"
-+#include "output.h"
-+#include "insn-attr.h"
-+#include "explow.h"
-+#include "expr.h"
-+#include "debug.h"
-+#include "cfgrtl.h"
-+#include "common/common-target.h"
-+#include "gimplify.h"
-+#include "langhooks.h"
-+#include "reload.h"
-+#include "tree-pass.h"
-+#include "context.h"
-+#include "builtins.h"
-+#include "tree-vector-builder.h"
-+#include "opts.h"
-+
-+/* This file should be included last. */
-+#include "target-def.h"
-+
-+/* Processor costs */
-+
-+struct processor_costs {
-+ /* Integer load */
-+ const int int_load;
-+
-+ /* Integer signed load */
-+ const int int_sload;
-+
-+ /* Integer zeroed load */
-+ const int int_zload;
-+
-+ /* Float load */
-+ const int float_load;
-+
-+ /* fmov, fneg, fabs */
-+ const int float_move;
-+
-+ /* fadd, fsub */
-+ const int float_plusminus;
-+
-+ /* fcmp */
-+ const int float_cmp;
-+
-+ /* fmov, fmovr */
-+ const int float_cmove;
-+
-+ /* fmul */
-+ const int float_mul;
-+
-+ /* fdivs */
-+ const int float_div_sf;
-+
-+ /* fdivd */
-+ const int float_div_df;
-+
-+ /* fsqrts */
-+ const int float_sqrt_sf;
-+
-+ /* fsqrtd */
-+ const int float_sqrt_df;
-+
-+ /* umul/smul */
-+ const int int_mul;
-+
-+ /* mulX */
-+ const int int_mulX;
-+
-+ /* integer multiply cost for each bit set past the most
-+ significant 3, so the formula for multiply cost becomes:
-+
-+ if (rs1 < 0)
-+ highest_bit = highest_clear_bit(rs1);
-+ else
-+ highest_bit = highest_set_bit(rs1);
-+ if (highest_bit < 3)
-+ highest_bit = 3;
-+ cost = int_mul{,X} + ((highest_bit - 3) / int_mul_bit_factor);
-+
-+ A value of zero indicates that the multiply costs is fixed,
-+ and not variable. */
-+ const int int_mul_bit_factor;
-+
-+ /* udiv/sdiv */
-+ const int int_div;
-+
-+ /* divX */
-+ const int int_divX;
-+
-+ /* movcc, movr */
-+ const int int_cmove;
-+
-+ /* penalty for shifts, due to scheduling rules etc. */
-+ const int shift_penalty;
-+
-+ /* cost of a (predictable) branch. */
-+ const int branch_cost;
-+};
-+
-+static const
-+struct processor_costs cypress_costs = {
-+ COSTS_N_INSNS (2), /* int load */
-+ COSTS_N_INSNS (2), /* int signed load */
-+ COSTS_N_INSNS (2), /* int zeroed load */
-+ COSTS_N_INSNS (2), /* float load */
-+ COSTS_N_INSNS (5), /* fmov, fneg, fabs */
-+ COSTS_N_INSNS (5), /* fadd, fsub */
-+ COSTS_N_INSNS (1), /* fcmp */
-+ COSTS_N_INSNS (1), /* fmov, fmovr */
-+ COSTS_N_INSNS (7), /* fmul */
-+ COSTS_N_INSNS (37), /* fdivs */
-+ COSTS_N_INSNS (37), /* fdivd */
-+ COSTS_N_INSNS (63), /* fsqrts */
-+ COSTS_N_INSNS (63), /* fsqrtd */
-+ COSTS_N_INSNS (1), /* imul */
-+ COSTS_N_INSNS (1), /* imulX */
-+ 0, /* imul bit factor */
-+ COSTS_N_INSNS (1), /* idiv */
-+ COSTS_N_INSNS (1), /* idivX */
-+ COSTS_N_INSNS (1), /* movcc/movr */
-+ 0, /* shift penalty */
-+ 3 /* branch cost */
-+};
-+
-+static const
-+struct processor_costs supersparc_costs = {
-+ COSTS_N_INSNS (1), /* int load */
-+ COSTS_N_INSNS (1), /* int signed load */
-+ COSTS_N_INSNS (1), /* int zeroed load */
-+ COSTS_N_INSNS (0), /* float load */
-+ COSTS_N_INSNS (3), /* fmov, fneg, fabs */
-+ COSTS_N_INSNS (3), /* fadd, fsub */
-+ COSTS_N_INSNS (3), /* fcmp */
-+ COSTS_N_INSNS (1), /* fmov, fmovr */
-+ COSTS_N_INSNS (3), /* fmul */
-+ COSTS_N_INSNS (6), /* fdivs */
-+ COSTS_N_INSNS (9), /* fdivd */
-+ COSTS_N_INSNS (12), /* fsqrts */
-+ COSTS_N_INSNS (12), /* fsqrtd */
-+ COSTS_N_INSNS (4), /* imul */
-+ COSTS_N_INSNS (4), /* imulX */
-+ 0, /* imul bit factor */
-+ COSTS_N_INSNS (4), /* idiv */
-+ COSTS_N_INSNS (4), /* idivX */
-+ COSTS_N_INSNS (1), /* movcc/movr */
-+ 1, /* shift penalty */
-+ 3 /* branch cost */
-+};
-+
-+static const
-+struct processor_costs hypersparc_costs = {
-+ COSTS_N_INSNS (1), /* int load */
-+ COSTS_N_INSNS (1), /* int signed load */
-+ COSTS_N_INSNS (1), /* int zeroed load */
-+ COSTS_N_INSNS (1), /* float load */
-+ COSTS_N_INSNS (1), /* fmov, fneg, fabs */
-+ COSTS_N_INSNS (1), /* fadd, fsub */
-+ COSTS_N_INSNS (1), /* fcmp */
-+ COSTS_N_INSNS (1), /* fmov, fmovr */
-+ COSTS_N_INSNS (1), /* fmul */
-+ COSTS_N_INSNS (8), /* fdivs */
-+ COSTS_N_INSNS (12), /* fdivd */
-+ COSTS_N_INSNS (17), /* fsqrts */
-+ COSTS_N_INSNS (17), /* fsqrtd */
-+ COSTS_N_INSNS (17), /* imul */
-+ COSTS_N_INSNS (17), /* imulX */
-+ 0, /* imul bit factor */
-+ COSTS_N_INSNS (17), /* idiv */
-+ COSTS_N_INSNS (17), /* idivX */
-+ COSTS_N_INSNS (1), /* movcc/movr */
-+ 0, /* shift penalty */
-+ 3 /* branch cost */
-+};
-+
-+static const
-+struct processor_costs leon_costs = {
-+ COSTS_N_INSNS (1), /* int load */
-+ COSTS_N_INSNS (1), /* int signed load */
-+ COSTS_N_INSNS (1), /* int zeroed load */
-+ COSTS_N_INSNS (1), /* float load */
-+ COSTS_N_INSNS (1), /* fmov, fneg, fabs */
-+ COSTS_N_INSNS (1), /* fadd, fsub */
-+ COSTS_N_INSNS (1), /* fcmp */
-+ COSTS_N_INSNS (1), /* fmov, fmovr */
-+ COSTS_N_INSNS (1), /* fmul */
-+ COSTS_N_INSNS (15), /* fdivs */
-+ COSTS_N_INSNS (15), /* fdivd */
-+ COSTS_N_INSNS (23), /* fsqrts */
-+ COSTS_N_INSNS (23), /* fsqrtd */
-+ COSTS_N_INSNS (5), /* imul */
-+ COSTS_N_INSNS (5), /* imulX */
-+ 0, /* imul bit factor */
-+ COSTS_N_INSNS (5), /* idiv */
-+ COSTS_N_INSNS (5), /* idivX */
-+ COSTS_N_INSNS (1), /* movcc/movr */
-+ 0, /* shift penalty */
-+ 3 /* branch cost */
-+};
-+
-+static const
-+struct processor_costs leon3_costs = {
-+ COSTS_N_INSNS (1), /* int load */
-+ COSTS_N_INSNS (1), /* int signed load */
-+ COSTS_N_INSNS (1), /* int zeroed load */
-+ COSTS_N_INSNS (1), /* float load */
-+ COSTS_N_INSNS (1), /* fmov, fneg, fabs */
-+ COSTS_N_INSNS (1), /* fadd, fsub */
-+ COSTS_N_INSNS (1), /* fcmp */
-+ COSTS_N_INSNS (1), /* fmov, fmovr */
-+ COSTS_N_INSNS (1), /* fmul */
-+ COSTS_N_INSNS (14), /* fdivs */
-+ COSTS_N_INSNS (15), /* fdivd */
-+ COSTS_N_INSNS (22), /* fsqrts */
-+ COSTS_N_INSNS (23), /* fsqrtd */
-+ COSTS_N_INSNS (5), /* imul */
-+ COSTS_N_INSNS (5), /* imulX */
-+ 0, /* imul bit factor */
-+ COSTS_N_INSNS (35), /* idiv */
-+ COSTS_N_INSNS (35), /* idivX */
-+ COSTS_N_INSNS (1), /* movcc/movr */
-+ 0, /* shift penalty */
-+ 3 /* branch cost */
-+};
-+
-+static const
-+struct processor_costs sparclet_costs = {
-+ COSTS_N_INSNS (3), /* int load */
-+ COSTS_N_INSNS (3), /* int signed load */
-+ COSTS_N_INSNS (1), /* int zeroed load */
-+ COSTS_N_INSNS (1), /* float load */
-+ COSTS_N_INSNS (1), /* fmov, fneg, fabs */
-+ COSTS_N_INSNS (1), /* fadd, fsub */
-+ COSTS_N_INSNS (1), /* fcmp */
-+ COSTS_N_INSNS (1), /* fmov, fmovr */
-+ COSTS_N_INSNS (1), /* fmul */
-+ COSTS_N_INSNS (1), /* fdivs */
-+ COSTS_N_INSNS (1), /* fdivd */
-+ COSTS_N_INSNS (1), /* fsqrts */
-+ COSTS_N_INSNS (1), /* fsqrtd */
-+ COSTS_N_INSNS (5), /* imul */
-+ COSTS_N_INSNS (5), /* imulX */
-+ 0, /* imul bit factor */
-+ COSTS_N_INSNS (5), /* idiv */
-+ COSTS_N_INSNS (5), /* idivX */
-+ COSTS_N_INSNS (1), /* movcc/movr */
-+ 0, /* shift penalty */
-+ 3 /* branch cost */
-+};
-+
-+static const
-+struct processor_costs ultrasparc_costs = {
-+ COSTS_N_INSNS (2), /* int load */
-+ COSTS_N_INSNS (3), /* int signed load */
-+ COSTS_N_INSNS (2), /* int zeroed load */
-+ COSTS_N_INSNS (2), /* float load */
-+ COSTS_N_INSNS (1), /* fmov, fneg, fabs */
-+ COSTS_N_INSNS (4), /* fadd, fsub */
-+ COSTS_N_INSNS (1), /* fcmp */
-+ COSTS_N_INSNS (2), /* fmov, fmovr */
-+ COSTS_N_INSNS (4), /* fmul */
-+ COSTS_N_INSNS (13), /* fdivs */
-+ COSTS_N_INSNS (23), /* fdivd */
-+ COSTS_N_INSNS (13), /* fsqrts */
-+ COSTS_N_INSNS (23), /* fsqrtd */
-+ COSTS_N_INSNS (4), /* imul */
-+ COSTS_N_INSNS (4), /* imulX */
-+ 2, /* imul bit factor */
-+ COSTS_N_INSNS (37), /* idiv */
-+ COSTS_N_INSNS (68), /* idivX */
-+ COSTS_N_INSNS (2), /* movcc/movr */
-+ 2, /* shift penalty */
-+ 2 /* branch cost */
-+};
-+
-+static const
-+struct processor_costs ultrasparc3_costs = {
-+ COSTS_N_INSNS (2), /* int load */
-+ COSTS_N_INSNS (3), /* int signed load */
-+ COSTS_N_INSNS (3), /* int zeroed load */
-+ COSTS_N_INSNS (2), /* float load */
-+ COSTS_N_INSNS (3), /* fmov, fneg, fabs */
-+ COSTS_N_INSNS (4), /* fadd, fsub */
-+ COSTS_N_INSNS (5), /* fcmp */
-+ COSTS_N_INSNS (3), /* fmov, fmovr */
-+ COSTS_N_INSNS (4), /* fmul */
-+ COSTS_N_INSNS (17), /* fdivs */
-+ COSTS_N_INSNS (20), /* fdivd */
-+ COSTS_N_INSNS (20), /* fsqrts */
-+ COSTS_N_INSNS (29), /* fsqrtd */
-+ COSTS_N_INSNS (6), /* imul */
-+ COSTS_N_INSNS (6), /* imulX */
-+ 0, /* imul bit factor */
-+ COSTS_N_INSNS (40), /* idiv */
-+ COSTS_N_INSNS (71), /* idivX */
-+ COSTS_N_INSNS (2), /* movcc/movr */
-+ 0, /* shift penalty */
-+ 2 /* branch cost */
-+};
-+
-+static const
-+struct processor_costs niagara_costs = {
-+ COSTS_N_INSNS (3), /* int load */
-+ COSTS_N_INSNS (3), /* int signed load */
-+ COSTS_N_INSNS (3), /* int zeroed load */
-+ COSTS_N_INSNS (9), /* float load */
-+ COSTS_N_INSNS (8), /* fmov, fneg, fabs */
-+ COSTS_N_INSNS (8), /* fadd, fsub */
-+ COSTS_N_INSNS (26), /* fcmp */
-+ COSTS_N_INSNS (8), /* fmov, fmovr */
-+ COSTS_N_INSNS (29), /* fmul */
-+ COSTS_N_INSNS (54), /* fdivs */
-+ COSTS_N_INSNS (83), /* fdivd */
-+ COSTS_N_INSNS (100), /* fsqrts - not implemented in hardware */
-+ COSTS_N_INSNS (100), /* fsqrtd - not implemented in hardware */
-+ COSTS_N_INSNS (11), /* imul */
-+ COSTS_N_INSNS (11), /* imulX */
-+ 0, /* imul bit factor */
-+ COSTS_N_INSNS (72), /* idiv */
-+ COSTS_N_INSNS (72), /* idivX */
-+ COSTS_N_INSNS (1), /* movcc/movr */
-+ 0, /* shift penalty */
-+ 4 /* branch cost */
-+};
-+
-+static const
-+struct processor_costs niagara2_costs = {
-+ COSTS_N_INSNS (3), /* int load */
-+ COSTS_N_INSNS (3), /* int signed load */
-+ COSTS_N_INSNS (3), /* int zeroed load */
-+ COSTS_N_INSNS (3), /* float load */
-+ COSTS_N_INSNS (6), /* fmov, fneg, fabs */
-+ COSTS_N_INSNS (6), /* fadd, fsub */
-+ COSTS_N_INSNS (6), /* fcmp */
-+ COSTS_N_INSNS (6), /* fmov, fmovr */
-+ COSTS_N_INSNS (6), /* fmul */
-+ COSTS_N_INSNS (19), /* fdivs */
-+ COSTS_N_INSNS (33), /* fdivd */
-+ COSTS_N_INSNS (19), /* fsqrts */
-+ COSTS_N_INSNS (33), /* fsqrtd */
-+ COSTS_N_INSNS (5), /* imul */
-+ COSTS_N_INSNS (5), /* imulX */
-+ 0, /* imul bit factor */
-+ COSTS_N_INSNS (26), /* idiv, average of 12 - 41 cycle range */
-+ COSTS_N_INSNS (26), /* idivX, average of 12 - 41 cycle range */
-+ COSTS_N_INSNS (1), /* movcc/movr */
-+ 0, /* shift penalty */
-+ 5 /* branch cost */
-+};
-+
-+static const
-+struct processor_costs niagara3_costs = {
-+ COSTS_N_INSNS (3), /* int load */
-+ COSTS_N_INSNS (3), /* int signed load */
-+ COSTS_N_INSNS (3), /* int zeroed load */
-+ COSTS_N_INSNS (3), /* float load */
-+ COSTS_N_INSNS (9), /* fmov, fneg, fabs */
-+ COSTS_N_INSNS (9), /* fadd, fsub */
-+ COSTS_N_INSNS (9), /* fcmp */
-+ COSTS_N_INSNS (9), /* fmov, fmovr */
-+ COSTS_N_INSNS (9), /* fmul */
-+ COSTS_N_INSNS (23), /* fdivs */
-+ COSTS_N_INSNS (37), /* fdivd */
-+ COSTS_N_INSNS (23), /* fsqrts */
-+ COSTS_N_INSNS (37), /* fsqrtd */
-+ COSTS_N_INSNS (9), /* imul */
-+ COSTS_N_INSNS (9), /* imulX */
-+ 0, /* imul bit factor */
-+ COSTS_N_INSNS (31), /* idiv, average of 17 - 45 cycle range */
-+ COSTS_N_INSNS (30), /* idivX, average of 16 - 44 cycle range */
-+ COSTS_N_INSNS (1), /* movcc/movr */
-+ 0, /* shift penalty */
-+ 5 /* branch cost */
-+};
-+
-+static const
-+struct processor_costs niagara4_costs = {
-+ COSTS_N_INSNS (5), /* int load */
-+ COSTS_N_INSNS (5), /* int signed load */
-+ COSTS_N_INSNS (5), /* int zeroed load */
-+ COSTS_N_INSNS (5), /* float load */
-+ COSTS_N_INSNS (11), /* fmov, fneg, fabs */
-+ COSTS_N_INSNS (11), /* fadd, fsub */
-+ COSTS_N_INSNS (11), /* fcmp */
-+ COSTS_N_INSNS (11), /* fmov, fmovr */
-+ COSTS_N_INSNS (11), /* fmul */
-+ COSTS_N_INSNS (24), /* fdivs */
-+ COSTS_N_INSNS (37), /* fdivd */
-+ COSTS_N_INSNS (24), /* fsqrts */
-+ COSTS_N_INSNS (37), /* fsqrtd */
-+ COSTS_N_INSNS (12), /* imul */
-+ COSTS_N_INSNS (12), /* imulX */
-+ 0, /* imul bit factor */
-+ COSTS_N_INSNS (50), /* idiv, average of 41 - 60 cycle range */
-+ COSTS_N_INSNS (35), /* idivX, average of 26 - 44 cycle range */
-+ COSTS_N_INSNS (1), /* movcc/movr */
-+ 0, /* shift penalty */
-+ 2 /* branch cost */
-+};
-+
-+static const
-+struct processor_costs niagara7_costs = {
-+ COSTS_N_INSNS (5), /* int load */
-+ COSTS_N_INSNS (5), /* int signed load */
-+ COSTS_N_INSNS (5), /* int zeroed load */
-+ COSTS_N_INSNS (5), /* float load */
-+ COSTS_N_INSNS (11), /* fmov, fneg, fabs */
-+ COSTS_N_INSNS (11), /* fadd, fsub */
-+ COSTS_N_INSNS (11), /* fcmp */
-+ COSTS_N_INSNS (11), /* fmov, fmovr */
-+ COSTS_N_INSNS (11), /* fmul */
-+ COSTS_N_INSNS (24), /* fdivs */
-+ COSTS_N_INSNS (37), /* fdivd */
-+ COSTS_N_INSNS (24), /* fsqrts */
-+ COSTS_N_INSNS (37), /* fsqrtd */
-+ COSTS_N_INSNS (12), /* imul */
-+ COSTS_N_INSNS (12), /* imulX */
-+ 0, /* imul bit factor */
-+ COSTS_N_INSNS (51), /* idiv, average of 42 - 61 cycle range */
-+ COSTS_N_INSNS (35), /* idivX, average of 26 - 44 cycle range */
-+ COSTS_N_INSNS (1), /* movcc/movr */
-+ 0, /* shift penalty */
-+ 1 /* branch cost */
-+};
-+
-+static const
-+struct processor_costs m8_costs = {
-+ COSTS_N_INSNS (3), /* int load */
-+ COSTS_N_INSNS (3), /* int signed load */
-+ COSTS_N_INSNS (3), /* int zeroed load */
-+ COSTS_N_INSNS (3), /* float load */
-+ COSTS_N_INSNS (9), /* fmov, fneg, fabs */
-+ COSTS_N_INSNS (9), /* fadd, fsub */
-+ COSTS_N_INSNS (9), /* fcmp */
-+ COSTS_N_INSNS (9), /* fmov, fmovr */
-+ COSTS_N_INSNS (9), /* fmul */
-+ COSTS_N_INSNS (26), /* fdivs */
-+ COSTS_N_INSNS (30), /* fdivd */
-+ COSTS_N_INSNS (33), /* fsqrts */
-+ COSTS_N_INSNS (41), /* fsqrtd */
-+ COSTS_N_INSNS (12), /* imul */
-+ COSTS_N_INSNS (10), /* imulX */
-+ 0, /* imul bit factor */
-+ COSTS_N_INSNS (57), /* udiv/sdiv */
-+ COSTS_N_INSNS (30), /* udivx/sdivx */
-+ COSTS_N_INSNS (1), /* movcc/movr */
-+ 0, /* shift penalty */
-+ 1 /* branch cost */
-+};
-+
-+static const struct processor_costs *sparc_costs = &cypress_costs;
-+
-+#ifdef HAVE_AS_RELAX_OPTION
-+/* If 'as' and 'ld' are relaxing tail call insns into branch always, use
-+ "or %o7,%g0,X; call Y; or X,%g0,%o7" always, so that it can be optimized.
-+ With sethi/jmp, neither 'as' nor 'ld' has an easy way how to find out if
-+ somebody does not branch between the sethi and jmp. */
-+#define LEAF_SIBCALL_SLOT_RESERVED_P 1
-+#else
-+#define LEAF_SIBCALL_SLOT_RESERVED_P \
-+ ((TARGET_ARCH64 && !TARGET_CM_MEDLOW) || flag_pic)
-+#endif
-+
-+/* Vector to say how input registers are mapped to output registers.
-+ HARD_FRAME_POINTER_REGNUM cannot be remapped by this function to
-+ eliminate it. You must use -fomit-frame-pointer to get that. */
-+char leaf_reg_remap[] =
-+{ 0, 1, 2, 3, 4, 5, 6, 7,
-+ -1, -1, -1, -1, -1, -1, 14, -1,
-+ -1, -1, -1, -1, -1, -1, -1, -1,
-+ 8, 9, 10, 11, 12, 13, -1, 15,
-+
-+ 32, 33, 34, 35, 36, 37, 38, 39,
-+ 40, 41, 42, 43, 44, 45, 46, 47,
-+ 48, 49, 50, 51, 52, 53, 54, 55,
-+ 56, 57, 58, 59, 60, 61, 62, 63,
-+ 64, 65, 66, 67, 68, 69, 70, 71,
-+ 72, 73, 74, 75, 76, 77, 78, 79,
-+ 80, 81, 82, 83, 84, 85, 86, 87,
-+ 88, 89, 90, 91, 92, 93, 94, 95,
-+ 96, 97, 98, 99, 100, 101, 102};
-+
-+/* Vector, indexed by hard register number, which contains 1
-+ for a register that is allowable in a candidate for leaf
-+ function treatment. */
-+char sparc_leaf_regs[] =
-+{ 1, 1, 1, 1, 1, 1, 1, 1,
-+ 0, 0, 0, 0, 0, 0, 1, 0,
-+ 0, 0, 0, 0, 0, 0, 0, 0,
-+ 1, 1, 1, 1, 1, 1, 0, 1,
-+ 1, 1, 1, 1, 1, 1, 1, 1,
-+ 1, 1, 1, 1, 1, 1, 1, 1,
-+ 1, 1, 1, 1, 1, 1, 1, 1,
-+ 1, 1, 1, 1, 1, 1, 1, 1,
-+ 1, 1, 1, 1, 1, 1, 1, 1,
-+ 1, 1, 1, 1, 1, 1, 1, 1,
-+ 1, 1, 1, 1, 1, 1, 1, 1,
-+ 1, 1, 1, 1, 1, 1, 1, 1,
-+ 1, 1, 1, 1, 1, 1, 1};
-+
-+struct GTY(()) machine_function
-+{
-+ /* Size of the frame of the function. */
-+ HOST_WIDE_INT frame_size;
-+
-+ /* Size of the frame of the function minus the register window save area
-+ and the outgoing argument area. */
-+ HOST_WIDE_INT apparent_frame_size;
-+
-+ /* Register we pretend the frame pointer is allocated to. Normally, this
-+ is %fp, but if we are in a leaf procedure, this is (%sp + offset). We
-+ record "offset" separately as it may be too big for (reg + disp). */
-+ rtx frame_base_reg;
-+ HOST_WIDE_INT frame_base_offset;
-+
-+ /* Number of global or FP registers to be saved (as 4-byte quantities). */
-+ int n_global_fp_regs;
-+
-+ /* True if the current function is leaf and uses only leaf regs,
-+ so that the SPARC leaf function optimization can be applied.
-+ Private version of crtl->uses_only_leaf_regs, see
-+ sparc_expand_prologue for the rationale. */
-+ int leaf_function_p;
-+
-+ /* True if the prologue saves local or in registers. */
-+ bool save_local_in_regs_p;
-+
-+ /* True if the data calculated by sparc_expand_prologue are valid. */
-+ bool prologue_data_valid_p;
-+};
-+
-+#define sparc_frame_size cfun->machine->frame_size
-+#define sparc_apparent_frame_size cfun->machine->apparent_frame_size
-+#define sparc_frame_base_reg cfun->machine->frame_base_reg
-+#define sparc_frame_base_offset cfun->machine->frame_base_offset
-+#define sparc_n_global_fp_regs cfun->machine->n_global_fp_regs
-+#define sparc_leaf_function_p cfun->machine->leaf_function_p
-+#define sparc_save_local_in_regs_p cfun->machine->save_local_in_regs_p
-+#define sparc_prologue_data_valid_p cfun->machine->prologue_data_valid_p
-+
-+/* 1 if the next opcode is to be specially indented. */
-+int sparc_indent_opcode = 0;
-+
-+static void sparc_option_override (void);
-+static void sparc_init_modes (void);
-+static int function_arg_slotno (const CUMULATIVE_ARGS *, machine_mode,
-+ const_tree, bool, bool, int *, int *);
-+
-+static int supersparc_adjust_cost (rtx_insn *, int, rtx_insn *, int);
-+static int hypersparc_adjust_cost (rtx_insn *, int, rtx_insn *, int);
-+
-+static void sparc_emit_set_const32 (rtx, rtx);
-+static void sparc_emit_set_const64 (rtx, rtx);
-+static void sparc_output_addr_vec (rtx);
-+static void sparc_output_addr_diff_vec (rtx);
-+static void sparc_output_deferred_case_vectors (void);
-+static bool sparc_legitimate_address_p (machine_mode, rtx, bool);
-+static bool sparc_legitimate_constant_p (machine_mode, rtx);
-+static rtx sparc_builtin_saveregs (void);
-+static int epilogue_renumber (rtx *, int);
-+static bool sparc_assemble_integer (rtx, unsigned int, int);
-+static int set_extends (rtx_insn *);
-+static void sparc_asm_function_prologue (FILE *);
-+static void sparc_asm_function_epilogue (FILE *);
-+#ifdef TARGET_SOLARIS
-+static void sparc_solaris_elf_asm_named_section (const char *, unsigned int,
-+ tree) ATTRIBUTE_UNUSED;
-+#endif
-+static int sparc_adjust_cost (rtx_insn *, int, rtx_insn *, int, unsigned int);
-+static int sparc_issue_rate (void);
-+static void sparc_sched_init (FILE *, int, int);
-+static int sparc_use_sched_lookahead (void);
-+
-+static void emit_soft_tfmode_libcall (const char *, int, rtx *);
-+static void emit_soft_tfmode_binop (enum rtx_code, rtx *);
-+static void emit_soft_tfmode_unop (enum rtx_code, rtx *);
-+static void emit_soft_tfmode_cvt (enum rtx_code, rtx *);
-+static void emit_hard_tfmode_operation (enum rtx_code, rtx *);
-+
-+static bool sparc_function_ok_for_sibcall (tree, tree);
-+static void sparc_init_libfuncs (void);
-+static void sparc_init_builtins (void);
-+static void sparc_fpu_init_builtins (void);
-+static void sparc_vis_init_builtins (void);
-+static tree sparc_builtin_decl (unsigned, bool);
-+static rtx sparc_expand_builtin (tree, rtx, rtx, machine_mode, int);
-+static tree sparc_fold_builtin (tree, int, tree *, bool);
-+static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
-+ HOST_WIDE_INT, tree);
-+static bool sparc_can_output_mi_thunk (const_tree, HOST_WIDE_INT,
-+ HOST_WIDE_INT, const_tree);
-+static struct machine_function * sparc_init_machine_status (void);
-+static bool sparc_cannot_force_const_mem (machine_mode, rtx);
-+static rtx sparc_tls_get_addr (void);
-+static rtx sparc_tls_got (void);
-+static int sparc_register_move_cost (machine_mode,
-+ reg_class_t, reg_class_t);
-+static bool sparc_rtx_costs (rtx, machine_mode, int, int, int *, bool);
-+static machine_mode sparc_promote_function_mode (const_tree, machine_mode,
-+ int *, const_tree, int);
-+static bool sparc_strict_argument_naming (cumulative_args_t);
-+static void sparc_va_start (tree, rtx);
-+static tree sparc_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *);
-+static bool sparc_vector_mode_supported_p (machine_mode);
-+static bool sparc_tls_referenced_p (rtx);
-+static rtx sparc_legitimize_tls_address (rtx);
-+static rtx sparc_legitimize_pic_address (rtx, rtx);
-+static rtx sparc_legitimize_address (rtx, rtx, machine_mode);
-+static rtx sparc_delegitimize_address (rtx);
-+static bool sparc_mode_dependent_address_p (const_rtx, addr_space_t);
-+static bool sparc_pass_by_reference (cumulative_args_t,
-+ const function_arg_info &);
-+static void sparc_function_arg_advance (cumulative_args_t,
-+ const function_arg_info &);
-+static rtx sparc_function_arg (cumulative_args_t, const function_arg_info &);
-+static rtx sparc_function_incoming_arg (cumulative_args_t,
-+ const function_arg_info &);
-+static pad_direction sparc_function_arg_padding (machine_mode, const_tree);
-+static unsigned int sparc_function_arg_boundary (machine_mode,
-+ const_tree);
-+static int sparc_arg_partial_bytes (cumulative_args_t,
-+ const function_arg_info &);
-+static bool sparc_return_in_memory (const_tree, const_tree);
-+static rtx sparc_struct_value_rtx (tree, int);
-+static rtx sparc_function_value (const_tree, const_tree, bool);
-+static rtx sparc_libcall_value (machine_mode, const_rtx);
-+static bool sparc_function_value_regno_p (const unsigned int);
-+static unsigned HOST_WIDE_INT sparc_asan_shadow_offset (void);
-+static void sparc_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
-+static void sparc_file_end (void);
-+static bool sparc_frame_pointer_required (void);
-+static bool sparc_can_eliminate (const int, const int);
-+static void sparc_conditional_register_usage (void);
-+static bool sparc_use_pseudo_pic_reg (void);
-+static void sparc_init_pic_reg (void);
-+#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
-+static const char *sparc_mangle_type (const_tree);
-+#endif
-+static void sparc_trampoline_init (rtx, tree, rtx);
-+static machine_mode sparc_preferred_simd_mode (scalar_mode);
-+static reg_class_t sparc_preferred_reload_class (rtx x, reg_class_t rclass);
-+static bool sparc_lra_p (void);
-+static bool sparc_print_operand_punct_valid_p (unsigned char);
-+static void sparc_print_operand (FILE *, rtx, int);
-+static void sparc_print_operand_address (FILE *, machine_mode, rtx);
-+static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t,
-+ machine_mode,
-+ secondary_reload_info *);
-+static bool sparc_secondary_memory_needed (machine_mode, reg_class_t,
-+ reg_class_t);
-+static machine_mode sparc_secondary_memory_needed_mode (machine_mode);
-+static scalar_int_mode sparc_cstore_mode (enum insn_code icode);
-+static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *);
-+static bool sparc_fixed_condition_code_regs (unsigned int *, unsigned int *);
-+static unsigned int sparc_min_arithmetic_precision (void);
-+static unsigned int sparc_hard_regno_nregs (unsigned int, machine_mode);
-+static bool sparc_hard_regno_mode_ok (unsigned int, machine_mode);
-+static bool sparc_modes_tieable_p (machine_mode, machine_mode);
-+static bool sparc_can_change_mode_class (machine_mode, machine_mode,
-+ reg_class_t);
-+static HOST_WIDE_INT sparc_constant_alignment (const_tree, HOST_WIDE_INT);
-+static bool sparc_vectorize_vec_perm_const (machine_mode, rtx, rtx, rtx,
-+ const vec_perm_indices &);
-+static bool sparc_can_follow_jump (const rtx_insn *, const rtx_insn *);
-+
-+#ifdef SUBTARGET_ATTRIBUTE_TABLE
-+/* Table of valid machine attributes. */
-+static const struct attribute_spec sparc_attribute_table[] =
-+{
-+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
-+ do_diagnostic, handler, exclude } */
-+ SUBTARGET_ATTRIBUTE_TABLE,
-+ { NULL, 0, 0, false, false, false, false, NULL, NULL }
-+};
-+#endif
-+
-+char sparc_hard_reg_printed[8];
-+
-+/* Initialize the GCC target structure. */
-+
-+/* The default is to use .half rather than .short for aligned HI objects. */
-+#undef TARGET_ASM_ALIGNED_HI_OP
-+#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
-+
-+#undef TARGET_ASM_UNALIGNED_HI_OP
-+#define TARGET_ASM_UNALIGNED_HI_OP "\t.uahalf\t"
-+#undef TARGET_ASM_UNALIGNED_SI_OP
-+#define TARGET_ASM_UNALIGNED_SI_OP "\t.uaword\t"
-+#undef TARGET_ASM_UNALIGNED_DI_OP
-+#define TARGET_ASM_UNALIGNED_DI_OP "\t.uaxword\t"
-+
-+/* The target hook has to handle DI-mode values. */
-+#undef TARGET_ASM_INTEGER
-+#define TARGET_ASM_INTEGER sparc_assemble_integer
-+
-+#undef TARGET_ASM_FUNCTION_PROLOGUE
-+#define TARGET_ASM_FUNCTION_PROLOGUE sparc_asm_function_prologue
-+#undef TARGET_ASM_FUNCTION_EPILOGUE
-+#define TARGET_ASM_FUNCTION_EPILOGUE sparc_asm_function_epilogue
-+
-+#undef TARGET_SCHED_ADJUST_COST
-+#define TARGET_SCHED_ADJUST_COST sparc_adjust_cost
-+#undef TARGET_SCHED_ISSUE_RATE
-+#define TARGET_SCHED_ISSUE_RATE sparc_issue_rate
-+#undef TARGET_SCHED_INIT
-+#define TARGET_SCHED_INIT sparc_sched_init
-+#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
-+#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD sparc_use_sched_lookahead
-+
-+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
-+#define TARGET_FUNCTION_OK_FOR_SIBCALL sparc_function_ok_for_sibcall
-+
-+#undef TARGET_INIT_LIBFUNCS
-+#define TARGET_INIT_LIBFUNCS sparc_init_libfuncs
-+
-+#undef TARGET_LEGITIMIZE_ADDRESS
-+#define TARGET_LEGITIMIZE_ADDRESS sparc_legitimize_address
-+#undef TARGET_DELEGITIMIZE_ADDRESS
-+#define TARGET_DELEGITIMIZE_ADDRESS sparc_delegitimize_address
-+#undef TARGET_MODE_DEPENDENT_ADDRESS_P
-+#define TARGET_MODE_DEPENDENT_ADDRESS_P sparc_mode_dependent_address_p
-+
-+#undef TARGET_INIT_BUILTINS
-+#define TARGET_INIT_BUILTINS sparc_init_builtins
-+#undef TARGET_BUILTIN_DECL
-+#define TARGET_BUILTIN_DECL sparc_builtin_decl
-+#undef TARGET_EXPAND_BUILTIN
-+#define TARGET_EXPAND_BUILTIN sparc_expand_builtin
-+#undef TARGET_FOLD_BUILTIN
-+#define TARGET_FOLD_BUILTIN sparc_fold_builtin
-+
-+#if TARGET_TLS
-+#undef TARGET_HAVE_TLS
-+#define TARGET_HAVE_TLS true
-+#endif
-+
-+#undef TARGET_CANNOT_FORCE_CONST_MEM
-+#define TARGET_CANNOT_FORCE_CONST_MEM sparc_cannot_force_const_mem
-+
-+#undef TARGET_ASM_OUTPUT_MI_THUNK
-+#define TARGET_ASM_OUTPUT_MI_THUNK sparc_output_mi_thunk
-+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
-+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK sparc_can_output_mi_thunk
-+
-+#undef TARGET_RTX_COSTS
-+#define TARGET_RTX_COSTS sparc_rtx_costs
-+#undef TARGET_ADDRESS_COST
-+#define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
-+#undef TARGET_REGISTER_MOVE_COST
-+#define TARGET_REGISTER_MOVE_COST sparc_register_move_cost
-+
-+#undef TARGET_PROMOTE_FUNCTION_MODE
-+#define TARGET_PROMOTE_FUNCTION_MODE sparc_promote_function_mode
-+#undef TARGET_STRICT_ARGUMENT_NAMING
-+#define TARGET_STRICT_ARGUMENT_NAMING sparc_strict_argument_naming
-+
-+#undef TARGET_MUST_PASS_IN_STACK
-+#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
-+#undef TARGET_PASS_BY_REFERENCE
-+#define TARGET_PASS_BY_REFERENCE sparc_pass_by_reference
-+#undef TARGET_ARG_PARTIAL_BYTES
-+#define TARGET_ARG_PARTIAL_BYTES sparc_arg_partial_bytes
-+#undef TARGET_FUNCTION_ARG_ADVANCE
-+#define TARGET_FUNCTION_ARG_ADVANCE sparc_function_arg_advance
-+#undef TARGET_FUNCTION_ARG
-+#define TARGET_FUNCTION_ARG sparc_function_arg
-+#undef TARGET_FUNCTION_INCOMING_ARG
-+#define TARGET_FUNCTION_INCOMING_ARG sparc_function_incoming_arg
-+#undef TARGET_FUNCTION_ARG_PADDING
-+#define TARGET_FUNCTION_ARG_PADDING sparc_function_arg_padding
-+#undef TARGET_FUNCTION_ARG_BOUNDARY
-+#define TARGET_FUNCTION_ARG_BOUNDARY sparc_function_arg_boundary
-+
-+#undef TARGET_RETURN_IN_MEMORY
-+#define TARGET_RETURN_IN_MEMORY sparc_return_in_memory
-+#undef TARGET_STRUCT_VALUE_RTX
-+#define TARGET_STRUCT_VALUE_RTX sparc_struct_value_rtx
-+#undef TARGET_FUNCTION_VALUE
-+#define TARGET_FUNCTION_VALUE sparc_function_value
-+#undef TARGET_LIBCALL_VALUE
-+#define TARGET_LIBCALL_VALUE sparc_libcall_value
-+#undef TARGET_FUNCTION_VALUE_REGNO_P
-+#define TARGET_FUNCTION_VALUE_REGNO_P sparc_function_value_regno_p
-+
-+#undef TARGET_EXPAND_BUILTIN_SAVEREGS
-+#define TARGET_EXPAND_BUILTIN_SAVEREGS sparc_builtin_saveregs
-+
-+#undef TARGET_ASAN_SHADOW_OFFSET
-+#define TARGET_ASAN_SHADOW_OFFSET sparc_asan_shadow_offset
-+
-+#undef TARGET_EXPAND_BUILTIN_VA_START
-+#define TARGET_EXPAND_BUILTIN_VA_START sparc_va_start
-+#undef TARGET_GIMPLIFY_VA_ARG_EXPR
-+#define TARGET_GIMPLIFY_VA_ARG_EXPR sparc_gimplify_va_arg
-+
-+#undef TARGET_VECTOR_MODE_SUPPORTED_P
-+#define TARGET_VECTOR_MODE_SUPPORTED_P sparc_vector_mode_supported_p
-+
-+#undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE
-+#define TARGET_VECTORIZE_PREFERRED_SIMD_MODE sparc_preferred_simd_mode
-+
-+#ifdef SUBTARGET_INSERT_ATTRIBUTES
-+#undef TARGET_INSERT_ATTRIBUTES
-+#define TARGET_INSERT_ATTRIBUTES SUBTARGET_INSERT_ATTRIBUTES
-+#endif
-+
-+#ifdef SUBTARGET_ATTRIBUTE_TABLE
-+#undef TARGET_ATTRIBUTE_TABLE
-+#define TARGET_ATTRIBUTE_TABLE sparc_attribute_table
-+#endif
-+
-+#undef TARGET_OPTION_OVERRIDE
-+#define TARGET_OPTION_OVERRIDE sparc_option_override
-+
-+#ifdef TARGET_THREAD_SSP_OFFSET
-+#undef TARGET_STACK_PROTECT_GUARD
-+#define TARGET_STACK_PROTECT_GUARD hook_tree_void_null
-+#endif
-+
-+#if TARGET_GNU_TLS && defined(HAVE_AS_SPARC_UA_PCREL)
-+#undef TARGET_ASM_OUTPUT_DWARF_DTPREL
-+#define TARGET_ASM_OUTPUT_DWARF_DTPREL sparc_output_dwarf_dtprel
-+#endif
-+
-+#undef TARGET_ASM_FILE_END
-+#define TARGET_ASM_FILE_END sparc_file_end
-+
-+#undef TARGET_FRAME_POINTER_REQUIRED
-+#define TARGET_FRAME_POINTER_REQUIRED sparc_frame_pointer_required
-+
-+#undef TARGET_CAN_ELIMINATE
-+#define TARGET_CAN_ELIMINATE sparc_can_eliminate
-+
-+#undef TARGET_PREFERRED_RELOAD_CLASS
-+#define TARGET_PREFERRED_RELOAD_CLASS sparc_preferred_reload_class
-+
-+#undef TARGET_SECONDARY_RELOAD
-+#define TARGET_SECONDARY_RELOAD sparc_secondary_reload
-+#undef TARGET_SECONDARY_MEMORY_NEEDED
-+#define TARGET_SECONDARY_MEMORY_NEEDED sparc_secondary_memory_needed
-+#undef TARGET_SECONDARY_MEMORY_NEEDED_MODE
-+#define TARGET_SECONDARY_MEMORY_NEEDED_MODE sparc_secondary_memory_needed_mode
-+
-+#undef TARGET_CONDITIONAL_REGISTER_USAGE
-+#define TARGET_CONDITIONAL_REGISTER_USAGE sparc_conditional_register_usage
-+
-+#undef TARGET_INIT_PIC_REG
-+#define TARGET_INIT_PIC_REG sparc_init_pic_reg
-+
-+#undef TARGET_USE_PSEUDO_PIC_REG
-+#define TARGET_USE_PSEUDO_PIC_REG sparc_use_pseudo_pic_reg
-+
-+#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
-+#undef TARGET_MANGLE_TYPE
-+#define TARGET_MANGLE_TYPE sparc_mangle_type
-+#endif
-+
-+#undef TARGET_LRA_P
-+#define TARGET_LRA_P sparc_lra_p
-+
-+#undef TARGET_LEGITIMATE_ADDRESS_P
-+#define TARGET_LEGITIMATE_ADDRESS_P sparc_legitimate_address_p
-+
-+#undef TARGET_LEGITIMATE_CONSTANT_P
-+#define TARGET_LEGITIMATE_CONSTANT_P sparc_legitimate_constant_p
-+
-+#undef TARGET_TRAMPOLINE_INIT
-+#define TARGET_TRAMPOLINE_INIT sparc_trampoline_init
-+
-+#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
-+#define TARGET_PRINT_OPERAND_PUNCT_VALID_P sparc_print_operand_punct_valid_p
-+#undef TARGET_PRINT_OPERAND
-+#define TARGET_PRINT_OPERAND sparc_print_operand
-+#undef TARGET_PRINT_OPERAND_ADDRESS
-+#define TARGET_PRINT_OPERAND_ADDRESS sparc_print_operand_address
-+
-+/* The value stored by LDSTUB. */
-+#undef TARGET_ATOMIC_TEST_AND_SET_TRUEVAL
-+#define TARGET_ATOMIC_TEST_AND_SET_TRUEVAL 0xff
-+
-+#undef TARGET_CSTORE_MODE
-+#define TARGET_CSTORE_MODE sparc_cstore_mode
-+
-+#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
-+#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV sparc_atomic_assign_expand_fenv
-+
-+#undef TARGET_FIXED_CONDITION_CODE_REGS
-+#define TARGET_FIXED_CONDITION_CODE_REGS sparc_fixed_condition_code_regs
-+
-+#undef TARGET_MIN_ARITHMETIC_PRECISION
-+#define TARGET_MIN_ARITHMETIC_PRECISION sparc_min_arithmetic_precision
-+
-+#undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
-+#define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 1
-+
-+#undef TARGET_HARD_REGNO_NREGS
-+#define TARGET_HARD_REGNO_NREGS sparc_hard_regno_nregs
-+#undef TARGET_HARD_REGNO_MODE_OK
-+#define TARGET_HARD_REGNO_MODE_OK sparc_hard_regno_mode_ok
-+
-+#undef TARGET_MODES_TIEABLE_P
-+#define TARGET_MODES_TIEABLE_P sparc_modes_tieable_p
-+
-+#undef TARGET_CAN_CHANGE_MODE_CLASS
-+#define TARGET_CAN_CHANGE_MODE_CLASS sparc_can_change_mode_class
-+
-+#undef TARGET_CONSTANT_ALIGNMENT
-+#define TARGET_CONSTANT_ALIGNMENT sparc_constant_alignment
-+
-+#undef TARGET_VECTORIZE_VEC_PERM_CONST
-+#define TARGET_VECTORIZE_VEC_PERM_CONST sparc_vectorize_vec_perm_const
-+
-+#undef TARGET_CAN_FOLLOW_JUMP
-+#define TARGET_CAN_FOLLOW_JUMP sparc_can_follow_jump
-+
-+struct gcc_target targetm = TARGET_INITIALIZER;
-+
-+/* Return the memory reference contained in X if any, zero otherwise. */
-+
-+static rtx
-+mem_ref (rtx x)
-+{
-+ if (GET_CODE (x) == SIGN_EXTEND || GET_CODE (x) == ZERO_EXTEND)
-+ x = XEXP (x, 0);
-+
-+ if (MEM_P (x))
-+ return x;
-+
-+ return NULL_RTX;
-+}
-+
-+/* True if any of INSN's source register(s) is REG. */
-+
-+static bool
-+insn_uses_reg_p (rtx_insn *insn, unsigned int reg)
-+{
-+ extract_insn (insn);
-+ return ((REG_P (recog_data.operand[1])
-+ && REGNO (recog_data.operand[1]) == reg)
-+ || (recog_data.n_operands == 3
-+ && REG_P (recog_data.operand[2])
-+ && REGNO (recog_data.operand[2]) == reg));
-+}
-+
-+/* True if INSN is a floating-point division or square-root. */
-+
-+static bool
-+div_sqrt_insn_p (rtx_insn *insn)
-+{
-+ if (GET_CODE (PATTERN (insn)) != SET)
-+ return false;
-+
-+ switch (get_attr_type (insn))
-+ {
-+ case TYPE_FPDIVS:
-+ case TYPE_FPSQRTS:
-+ case TYPE_FPDIVD:
-+ case TYPE_FPSQRTD:
-+ return true;
-+ default:
-+ return false;
-+ }
-+}
-+
-+/* True if INSN is a floating-point instruction. */
-+
-+static bool
-+fpop_insn_p (rtx_insn *insn)
-+{
-+ if (GET_CODE (PATTERN (insn)) != SET)
-+ return false;
-+
-+ switch (get_attr_type (insn))
-+ {
-+ case TYPE_FPMOVE:
-+ case TYPE_FPCMOVE:
-+ case TYPE_FP:
-+ case TYPE_FPCMP:
-+ case TYPE_FPMUL:
-+ case TYPE_FPDIVS:
-+ case TYPE_FPSQRTS:
-+ case TYPE_FPDIVD:
-+ case TYPE_FPSQRTD:
-+ return true;
-+ default:
-+ return false;
-+ }
-+}
-+
-+/* True if INSN is an atomic instruction. */
-+
-+static bool
-+atomic_insn_for_leon3_p (rtx_insn *insn)
-+{
-+ switch (INSN_CODE (insn))
-+ {
-+ case CODE_FOR_swapsi:
-+ case CODE_FOR_ldstub:
-+ case CODE_FOR_atomic_compare_and_swap_leon3_1:
-+ return true;
-+ default:
-+ return false;
-+ }
-+}
-+
-+/* We use a machine specific pass to enable workarounds for errata.
-+
-+ We need to have the (essentially) final form of the insn stream in order
-+ to properly detect the various hazards. Therefore, this machine specific
-+ pass runs as late as possible. */
-+
-+/* True if INSN is a md pattern or asm statement. */
-+#define USEFUL_INSN_P(INSN) \
-+ (NONDEBUG_INSN_P (INSN) \
-+ && GET_CODE (PATTERN (INSN)) != USE \
-+ && GET_CODE (PATTERN (INSN)) != CLOBBER)
-+
-+static unsigned int
-+sparc_do_work_around_errata (void)
-+{
-+ rtx_insn *insn, *next;
-+
-+ /* Force all instructions to be split into their final form. */
-+ split_all_insns_noflow ();
-+
-+ /* Now look for specific patterns in the insn stream. */
-+ for (insn = get_insns (); insn; insn = next)
-+ {
-+ bool insert_nop = false;
-+ rtx set;
-+ rtx_insn *jump;
-+ rtx_sequence *seq;
-+
-+ /* Look into the instruction in a delay slot. */
-+ if (NONJUMP_INSN_P (insn)
-+ && (seq = dyn_cast <rtx_sequence *> (PATTERN (insn))))
-+ {
-+ jump = seq->insn (0);
-+ insn = seq->insn (1);
-+ }
-+ else if (JUMP_P (insn))
-+ jump = insn;
-+ else
-+ jump = NULL;
-+
-+ /* Place a NOP at the branch target of an integer branch if it is a
-+ floating-point operation or a floating-point branch. */
-+ if (sparc_fix_gr712rc
-+ && jump
-+ && jump_to_label_p (jump)
-+ && get_attr_branch_type (jump) == BRANCH_TYPE_ICC)
-+ {
-+ rtx_insn *target = next_active_insn (JUMP_LABEL_AS_INSN (jump));
-+ if (target
-+ && (fpop_insn_p (target)
-+ || (JUMP_P (target)
-+ && get_attr_branch_type (target) == BRANCH_TYPE_FCC)))
-+ emit_insn_before (gen_nop (), target);
-+ }
-+
-+ /* Insert a NOP between load instruction and atomic instruction. Insert
-+ a NOP at branch target if there is a load in delay slot and an atomic
-+ instruction at branch target. */
-+ if (sparc_fix_ut700
-+ && NONJUMP_INSN_P (insn)
-+ && (set = single_set (insn)) != NULL_RTX
-+ && mem_ref (SET_SRC (set))
-+ && REG_P (SET_DEST (set)))
-+ {
-+ if (jump && jump_to_label_p (jump))
-+ {
-+ rtx_insn *target = next_active_insn (JUMP_LABEL_AS_INSN (jump));
-+ if (target && atomic_insn_for_leon3_p (target))
-+ emit_insn_before (gen_nop (), target);
-+ }
-+
-+ next = next_active_insn (insn);
-+ if (!next)
-+ break;
-+
-+ if (atomic_insn_for_leon3_p (next))
-+ insert_nop = true;
-+ }
-+
-+ /* Look for a sequence that starts with a fdiv or fsqrt instruction and
-+ ends with another fdiv or fsqrt instruction with no dependencies on
-+ the former, along with an appropriate pattern in between. */
-+ if (sparc_fix_lost_divsqrt
-+ && NONJUMP_INSN_P (insn)
-+ && div_sqrt_insn_p (insn))
-+ {
-+ int i;
-+ int fp_found = 0;
-+ rtx_insn *after;
-+
-+ const unsigned int dest_reg = REGNO (SET_DEST (single_set (insn)));
-+
-+ next = next_active_insn (insn);
-+ if (!next)
-+ break;
-+
-+ for (after = next, i = 0; i < 4; i++)
-+ {
-+ /* Count floating-point operations. */
-+ if (i != 3 && fpop_insn_p (after))
-+ {
-+ /* If the insn uses the destination register of
-+ the div/sqrt, then it cannot be problematic. */
-+ if (insn_uses_reg_p (after, dest_reg))
-+ break;
-+ fp_found++;
-+ }
-+
-+ /* Count floating-point loads. */
-+ if (i != 3
-+ && (set = single_set (after)) != NULL_RTX
-+ && REG_P (SET_DEST (set))
-+ && REGNO (SET_DEST (set)) > 31)
-+ {
-+ /* If the insn uses the destination register of
-+ the div/sqrt, then it cannot be problematic. */
-+ if (REGNO (SET_DEST (set)) == dest_reg)
-+ break;
-+ fp_found++;
-+ }
-+
-+ /* Check if this is a problematic sequence. */
-+ if (i > 1
-+ && fp_found >= 2
-+ && div_sqrt_insn_p (after))
-+ {
-+ /* If this is the short version of the problematic
-+ sequence we add two NOPs in a row to also prevent
-+ the long version. */
-+ if (i == 2)
-+ emit_insn_before (gen_nop (), next);
-+ insert_nop = true;
-+ break;
-+ }
-+
-+ /* No need to scan past a second div/sqrt. */
-+ if (div_sqrt_insn_p (after))
-+ break;
-+
-+ /* Insert NOP before branch. */
-+ if (i < 3
-+ && (!NONJUMP_INSN_P (after)
-+ || GET_CODE (PATTERN (after)) == SEQUENCE))
-+ {
-+ insert_nop = true;
-+ break;
-+ }
-+
-+ after = next_active_insn (after);
-+ if (!after)
-+ break;
-+ }
-+ }
-+
-+ /* Look for either of these two sequences:
-+
-+ Sequence A:
-+ 1. store of word size or less (e.g. st / stb / sth / stf)
-+ 2. any single instruction that is not a load or store
-+ 3. any store instruction (e.g. st / stb / sth / stf / std / stdf)
-+
-+ Sequence B:
-+ 1. store of double word size (e.g. std / stdf)
-+ 2. any store instruction (e.g. st / stb / sth / stf / std / stdf) */
-+ if (sparc_fix_b2bst
-+ && NONJUMP_INSN_P (insn)
-+ && (set = single_set (insn)) != NULL_RTX
-+ && MEM_P (SET_DEST (set)))
-+ {
-+ /* Sequence B begins with a double-word store. */
-+ bool seq_b = GET_MODE_SIZE (GET_MODE (SET_DEST (set))) == 8;
-+ rtx_insn *after;
-+ int i;
-+
-+ next = next_active_insn (insn);
-+ if (!next)
-+ break;
-+
-+ for (after = next, i = 0; i < 2; i++)
-+ {
-+ /* Skip empty assembly statements. */
-+ if ((GET_CODE (PATTERN (after)) == UNSPEC_VOLATILE)
-+ || (USEFUL_INSN_P (after)
-+ && (asm_noperands (PATTERN (after))>=0)
-+ && !strcmp (decode_asm_operands (PATTERN (after),
-+ NULL, NULL, NULL,
-+ NULL, NULL), "")))
-+ after = next_active_insn (after);
-+ if (!after)
-+ break;
-+
-+ /* If the insn is a branch, then it cannot be problematic. */
-+ if (!NONJUMP_INSN_P (after)
-+ || GET_CODE (PATTERN (after)) == SEQUENCE)
-+ break;
-+
-+ /* Sequence B is only two instructions long. */
-+ if (seq_b)
-+ {
-+ /* Add NOP if followed by a store. */
-+ if ((set = single_set (after)) != NULL_RTX
-+ && MEM_P (SET_DEST (set)))
-+ insert_nop = true;
-+
-+ /* Otherwise it is ok. */
-+ break;
-+ }
-+
-+ /* If the second instruction is a load or a store,
-+ then the sequence cannot be problematic. */
-+ if (i == 0)
-+ {
-+ if ((set = single_set (after)) != NULL_RTX
-+ && (MEM_P (SET_DEST (set)) || mem_ref (SET_SRC (set))))
-+ break;
-+
-+ after = next_active_insn (after);
-+ if (!after)
-+ break;
-+ }
-+
-+ /* Add NOP if third instruction is a store. */
-+ if (i == 1
-+ && (set = single_set (after)) != NULL_RTX
-+ && MEM_P (SET_DEST (set)))
-+ insert_nop = true;
-+ }
-+ }
-+
-+ /* Look for a single-word load into an odd-numbered FP register. */
-+ else if (sparc_fix_at697f
-+ && NONJUMP_INSN_P (insn)
-+ && (set = single_set (insn)) != NULL_RTX
-+ && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4
-+ && mem_ref (SET_SRC (set))
-+ && REG_P (SET_DEST (set))
-+ && REGNO (SET_DEST (set)) > 31
-+ && REGNO (SET_DEST (set)) % 2 != 0)
-+ {
-+ /* The wrong dependency is on the enclosing double register. */
-+ const unsigned int x = REGNO (SET_DEST (set)) - 1;
-+ unsigned int src1, src2, dest;
-+ int code;
-+
-+ next = next_active_insn (insn);
-+ if (!next)
-+ break;
-+ /* If the insn is a branch, then it cannot be problematic. */
-+ if (!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) == SEQUENCE)
-+ continue;
-+
-+ extract_insn (next);
-+ code = INSN_CODE (next);
-+
-+ switch (code)
-+ {
-+ case CODE_FOR_adddf3:
-+ case CODE_FOR_subdf3:
-+ case CODE_FOR_muldf3:
-+ case CODE_FOR_divdf3:
-+ dest = REGNO (recog_data.operand[0]);
-+ src1 = REGNO (recog_data.operand[1]);
-+ src2 = REGNO (recog_data.operand[2]);
-+ if (src1 != src2)
-+ {
-+ /* Case [1-4]:
-+ ld [address], %fx+1
-+ FPOPd %f{x,y}, %f{y,x}, %f{x,y} */
-+ if ((src1 == x || src2 == x)
-+ && (dest == src1 || dest == src2))
-+ insert_nop = true;
-+ }
-+ else
-+ {
-+ /* Case 5:
-+ ld [address], %fx+1
-+ FPOPd %fx, %fx, %fx */
-+ if (src1 == x
-+ && dest == src1
-+ && (code == CODE_FOR_adddf3 || code == CODE_FOR_muldf3))
-+ insert_nop = true;
-+ }
-+ break;
-+
-+ case CODE_FOR_sqrtdf2:
-+ dest = REGNO (recog_data.operand[0]);
-+ src1 = REGNO (recog_data.operand[1]);
-+ /* Case 6:
-+ ld [address], %fx+1
-+ fsqrtd %fx, %fx */
-+ if (src1 == x && dest == src1)
-+ insert_nop = true;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ }
-+
-+ /* Look for a single-word load into an integer register. */
-+ else if (sparc_fix_ut699
-+ && NONJUMP_INSN_P (insn)
-+ && (set = single_set (insn)) != NULL_RTX
-+ && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) <= 4
-+ && (mem_ref (SET_SRC (set)) != NULL_RTX
-+ || INSN_CODE (insn) == CODE_FOR_movsi_pic_gotdata_op)
-+ && REG_P (SET_DEST (set))
-+ && REGNO (SET_DEST (set)) < 32)
-+ {
-+ /* There is no problem if the second memory access has a data
-+ dependency on the first single-cycle load. */
-+ rtx x = SET_DEST (set);
-+
-+ next = next_active_insn (insn);
-+ if (!next)
-+ break;
-+ /* If the insn is a branch, then it cannot be problematic. */
-+ if (!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) == SEQUENCE)
-+ continue;
-+
-+ /* Look for a second memory access to/from an integer register. */
-+ if ((set = single_set (next)) != NULL_RTX)
-+ {
-+ rtx src = SET_SRC (set);
-+ rtx dest = SET_DEST (set);
-+ rtx mem;
-+
-+ /* LDD is affected. */
-+ if ((mem = mem_ref (src)) != NULL_RTX
-+ && REG_P (dest)
-+ && REGNO (dest) < 32
-+ && !reg_mentioned_p (x, XEXP (mem, 0)))
-+ insert_nop = true;
-+
-+ /* STD is *not* affected. */
-+ else if (MEM_P (dest)
-+ && GET_MODE_SIZE (GET_MODE (dest)) <= 4
-+ && (src == CONST0_RTX (GET_MODE (dest))
-+ || (REG_P (src)
-+ && REGNO (src) < 32
-+ && REGNO (src) != REGNO (x)))
-+ && !reg_mentioned_p (x, XEXP (dest, 0)))
-+ insert_nop = true;
-+
-+ /* GOT accesses uses LD. */
-+ else if (INSN_CODE (next) == CODE_FOR_movsi_pic_gotdata_op
-+ && !reg_mentioned_p (x, XEXP (XEXP (src, 0), 1)))
-+ insert_nop = true;
-+ }
-+ }
-+
-+ /* Look for a single-word load/operation into an FP register. */
-+ else if (sparc_fix_ut699
-+ && NONJUMP_INSN_P (insn)
-+ && (set = single_set (insn)) != NULL_RTX
-+ && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4
-+ && REG_P (SET_DEST (set))
-+ && REGNO (SET_DEST (set)) > 31)
-+ {
-+ /* Number of instructions in the problematic window. */
-+ const int n_insns = 4;
-+ /* The problematic combination is with the sibling FP register. */
-+ const unsigned int x = REGNO (SET_DEST (set));
-+ const unsigned int y = x ^ 1;
-+ rtx_insn *after;
-+ int i;
-+
-+ next = next_active_insn (insn);
-+ if (!next)
-+ break;
-+ /* If the insn is a branch, then it cannot be problematic. */
-+ if (!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) == SEQUENCE)
-+ continue;
-+
-+ /* Look for a second load/operation into the sibling FP register. */
-+ if (!((set = single_set (next)) != NULL_RTX
-+ && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4
-+ && REG_P (SET_DEST (set))
-+ && REGNO (SET_DEST (set)) == y))
-+ continue;
-+
-+ /* Look for a (possible) store from the FP register in the next N
-+ instructions, but bail out if it is again modified or if there
-+ is a store from the sibling FP register before this store. */
-+ for (after = next, i = 0; i < n_insns; i++)
-+ {
-+ bool branch_p;
-+
-+ after = next_active_insn (after);
-+ if (!after)
-+ break;
-+
-+ /* This is a branch with an empty delay slot. */
-+ if (!NONJUMP_INSN_P (after))
-+ {
-+ if (++i == n_insns)
-+ break;
-+ branch_p = true;
-+ after = NULL;
-+ }
-+ /* This is a branch with a filled delay slot. */
-+ else if (rtx_sequence *seq =
-+ dyn_cast <rtx_sequence *> (PATTERN (after)))
-+ {
-+ if (++i == n_insns)
-+ break;
-+ branch_p = true;
-+ after = seq->insn (1);
-+ }
-+ /* This is a regular instruction. */
-+ else
-+ branch_p = false;
-+
-+ if (after && (set = single_set (after)) != NULL_RTX)
-+ {
-+ const rtx src = SET_SRC (set);
-+ const rtx dest = SET_DEST (set);
-+ const unsigned int size = GET_MODE_SIZE (GET_MODE (dest));
-+
-+ /* If the FP register is again modified before the store,
-+ then the store isn't affected. */
-+ if (REG_P (dest)
-+ && (REGNO (dest) == x
-+ || (REGNO (dest) == y && size == 8)))
-+ break;
-+
-+ if (MEM_P (dest) && REG_P (src))
-+ {
-+ /* If there is a store from the sibling FP register
-+ before the store, then the store is not affected. */
-+ if (REGNO (src) == y || (REGNO (src) == x && size == 8))
-+ break;
-+
-+ /* Otherwise, the store is affected. */
-+ if (REGNO (src) == x && size == 4)
-+ {
-+ insert_nop = true;
-+ break;
-+ }
-+ }
-+ }
-+
-+ /* If we have a branch in the first M instructions, then we
-+ cannot see the (M+2)th instruction so we play safe. */
-+ if (branch_p && i <= (n_insns - 2))
-+ {
-+ insert_nop = true;
-+ break;
-+ }
-+ }
-+ }
-+
-+ else
-+ next = NEXT_INSN (insn);
-+
-+ if (insert_nop)
-+ emit_insn_before (gen_nop (), next);
-+ }
-+
-+ return 0;
-+}
-+
-+namespace {
-+
-+const pass_data pass_data_work_around_errata =
-+{
-+ RTL_PASS, /* type */
-+ "errata", /* name */
-+ OPTGROUP_NONE, /* optinfo_flags */
-+ TV_MACH_DEP, /* tv_id */
-+ 0, /* properties_required */
-+ 0, /* properties_provided */
-+ 0, /* properties_destroyed */
-+ 0, /* todo_flags_start */
-+ 0, /* todo_flags_finish */
-+};
-+
-+class pass_work_around_errata : public rtl_opt_pass
-+{
-+public:
-+ pass_work_around_errata(gcc::context *ctxt)
-+ : rtl_opt_pass(pass_data_work_around_errata, ctxt)
-+ {}
-+
-+ /* opt_pass methods: */
-+ virtual bool gate (function *)
-+ {
-+ return sparc_fix_at697f
-+ || sparc_fix_ut699 || sparc_fix_ut700 || sparc_fix_gr712rc
-+ || sparc_fix_b2bst || sparc_fix_lost_divsqrt;
-+ }
-+
-+ virtual unsigned int execute (function *)
-+ {
-+ return sparc_do_work_around_errata ();
-+ }
-+
-+}; // class pass_work_around_errata
-+
-+} // anon namespace
-+
-+rtl_opt_pass *
-+make_pass_work_around_errata (gcc::context *ctxt)
-+{
-+ return new pass_work_around_errata (ctxt);
-+}
-+
-+/* Helpers for TARGET_DEBUG_OPTIONS. */
-+static void
-+dump_target_flag_bits (const int flags)
-+{
-+ if (flags & MASK_64BIT)
-+ fprintf (stderr, "64BIT ");
-+ if (flags & MASK_APP_REGS)
-+ fprintf (stderr, "APP_REGS ");
-+ if (flags & MASK_FASTER_STRUCTS)
-+ fprintf (stderr, "FASTER_STRUCTS ");
-+ if (flags & MASK_FLAT)
-+ fprintf (stderr, "FLAT ");
-+ if (flags & MASK_FMAF)
-+ fprintf (stderr, "FMAF ");
-+ if (flags & MASK_FSMULD)
-+ fprintf (stderr, "FSMULD ");
-+ if (flags & MASK_FPU)
-+ fprintf (stderr, "FPU ");
-+ if (flags & MASK_HARD_QUAD)
-+ fprintf (stderr, "HARD_QUAD ");
-+ if (flags & MASK_POPC)
-+ fprintf (stderr, "POPC ");
-+ if (flags & MASK_PTR64)
-+ fprintf (stderr, "PTR64 ");
-+ if (flags & MASK_STACK_BIAS)
-+ fprintf (stderr, "STACK_BIAS ");
-+ if (flags & MASK_UNALIGNED_DOUBLES)
-+ fprintf (stderr, "UNALIGNED_DOUBLES ");
-+ if (flags & MASK_V8PLUS)
-+ fprintf (stderr, "V8PLUS ");
-+ if (flags & MASK_VIS)
-+ fprintf (stderr, "VIS ");
-+ if (flags & MASK_VIS2)
-+ fprintf (stderr, "VIS2 ");
-+ if (flags & MASK_VIS3)
-+ fprintf (stderr, "VIS3 ");
-+ if (flags & MASK_VIS4)
-+ fprintf (stderr, "VIS4 ");
-+ if (flags & MASK_VIS4B)
-+ fprintf (stderr, "VIS4B ");
-+ if (flags & MASK_CBCOND)
-+ fprintf (stderr, "CBCOND ");
-+ if (flags & MASK_DEPRECATED_V8_INSNS)
-+ fprintf (stderr, "DEPRECATED_V8_INSNS ");
-+ if (flags & MASK_SPARCLET)
-+ fprintf (stderr, "SPARCLET ");
-+ if (flags & MASK_SPARCLITE)
-+ fprintf (stderr, "SPARCLITE ");
-+ if (flags & MASK_V8)
-+ fprintf (stderr, "V8 ");
-+ if (flags & MASK_V9)
-+ fprintf (stderr, "V9 ");
-+}
-+
-+static void
-+dump_target_flags (const char *prefix, const int flags)
-+{
-+ fprintf (stderr, "%s: (%08x) [ ", prefix, flags);
-+ dump_target_flag_bits (flags);
-+ fprintf(stderr, "]\n");
-+}
-+
-+/* Validate and override various options, and do some machine dependent
-+ initialization. */
-+
-+static void
-+sparc_option_override (void)
-+{
-+ /* Map TARGET_CPU_DEFAULT to value for -m{cpu,tune}=. */
-+ static struct cpu_default {
-+ const int cpu;
-+ const enum sparc_processor_type processor;
-+ } const cpu_default[] = {
-+ /* There must be one entry here for each TARGET_CPU value. */
-+ { TARGET_CPU_sparc, PROCESSOR_CYPRESS },
-+ { TARGET_CPU_v8, PROCESSOR_V8 },
-+ { TARGET_CPU_supersparc, PROCESSOR_SUPERSPARC },
-+ { TARGET_CPU_hypersparc, PROCESSOR_HYPERSPARC },
-+ { TARGET_CPU_leon, PROCESSOR_LEON },
-+ { TARGET_CPU_leon3, PROCESSOR_LEON3 },
-+ { TARGET_CPU_leon3v7, PROCESSOR_LEON3V7 },
-+ { TARGET_CPU_sparclite, PROCESSOR_F930 },
-+ { TARGET_CPU_sparclite86x, PROCESSOR_SPARCLITE86X },
-+ { TARGET_CPU_sparclet, PROCESSOR_TSC701 },
-+ { TARGET_CPU_v9, PROCESSOR_V9 },
-+ { TARGET_CPU_ultrasparc, PROCESSOR_ULTRASPARC },
-+ { TARGET_CPU_ultrasparc3, PROCESSOR_ULTRASPARC3 },
-+ { TARGET_CPU_niagara, PROCESSOR_NIAGARA },
-+ { TARGET_CPU_niagara2, PROCESSOR_NIAGARA2 },
-+ { TARGET_CPU_niagara3, PROCESSOR_NIAGARA3 },
-+ { TARGET_CPU_niagara4, PROCESSOR_NIAGARA4 },
-+ { TARGET_CPU_niagara7, PROCESSOR_NIAGARA7 },
-+ { TARGET_CPU_m8, PROCESSOR_M8 },
-+ { -1, PROCESSOR_V7 }
-+ };
-+ const struct cpu_default *def;
-+ /* Table of values for -m{cpu,tune}=. This must match the order of
-+ the enum processor_type in sparc-opts.h. */
-+ static struct cpu_table {
-+ const char *const name;
-+ const int disable;
-+ const int enable;
-+ } const cpu_table[] = {
-+ { "v7", MASK_ISA, 0 },
-+ { "cypress", MASK_ISA, 0 },
-+ { "v8", MASK_ISA, MASK_V8 },
-+ /* TI TMS390Z55 supersparc */
-+ { "supersparc", MASK_ISA, MASK_V8 },
-+ { "hypersparc", MASK_ISA, MASK_V8 },
-+ { "leon", MASK_ISA|MASK_FSMULD, MASK_V8|MASK_LEON },
-+ { "leon3", MASK_ISA, MASK_V8|MASK_LEON3 },
-+ { "leon3v7", MASK_ISA, MASK_LEON3 },
-+ { "sparclite", MASK_ISA, MASK_SPARCLITE },
-+ /* The Fujitsu MB86930 is the original sparclite chip, with no FPU. */
-+ { "f930", MASK_ISA|MASK_FPU, MASK_SPARCLITE },
-+ /* The Fujitsu MB86934 is the recent sparclite chip, with an FPU. */
-+ { "f934", MASK_ISA, MASK_SPARCLITE },
-+ { "sparclite86x", MASK_ISA|MASK_FPU, MASK_SPARCLITE },
-+ { "sparclet", MASK_ISA, MASK_SPARCLET },
-+ /* TEMIC sparclet */
-+ { "tsc701", MASK_ISA, MASK_SPARCLET },
-+ { "v9", MASK_ISA, MASK_V9 },
-+ /* UltraSPARC I, II, IIi */
-+ { "ultrasparc", MASK_ISA,
-+ /* Although insns using %y are deprecated, it is a clear win. */
-+ MASK_V9|MASK_DEPRECATED_V8_INSNS },
-+ /* UltraSPARC III */
-+ /* ??? Check if %y issue still holds true. */
-+ { "ultrasparc3", MASK_ISA,
-+ MASK_V9|MASK_DEPRECATED_V8_INSNS|MASK_VIS2 },
-+ /* UltraSPARC T1 */
-+ { "niagara", MASK_ISA,
-+ MASK_V9|MASK_DEPRECATED_V8_INSNS },
-+ /* UltraSPARC T2 */
-+ { "niagara2", MASK_ISA,
-+ MASK_V9|MASK_POPC|MASK_VIS2 },
-+ /* UltraSPARC T3 */
-+ { "niagara3", MASK_ISA,
-+ MASK_V9|MASK_POPC|MASK_VIS3|MASK_FMAF },
-+ /* UltraSPARC T4 */
-+ { "niagara4", MASK_ISA,
-+ MASK_V9|MASK_POPC|MASK_VIS3|MASK_FMAF|MASK_CBCOND },
-+ /* UltraSPARC M7 */
-+ { "niagara7", MASK_ISA,
-+ MASK_V9|MASK_POPC|MASK_VIS4|MASK_FMAF|MASK_CBCOND|MASK_SUBXC },
-+ /* UltraSPARC M8 */
-+ { "m8", MASK_ISA,
-+ MASK_V9|MASK_POPC|MASK_VIS4B|MASK_FMAF|MASK_CBCOND|MASK_SUBXC }
-+ };
-+ const struct cpu_table *cpu;
-+ unsigned int i;
-+
-+ if (sparc_debug_string != NULL)
-+ {
-+ const char *q;
-+ char *p;
-+
-+ p = ASTRDUP (sparc_debug_string);
-+ while ((q = strtok (p, ",")) != NULL)
-+ {
-+ bool invert;
-+ int mask;
-+
-+ p = NULL;
-+ if (*q == '!')
-+ {
-+ invert = true;
-+ q++;
-+ }
-+ else
-+ invert = false;
-+
-+ if (! strcmp (q, "all"))
-+ mask = MASK_DEBUG_ALL;
-+ else if (! strcmp (q, "options"))
-+ mask = MASK_DEBUG_OPTIONS;
-+ else
-+ error ("unknown %<-mdebug-%s%> switch", q);
-+
-+ if (invert)
-+ sparc_debug &= ~mask;
-+ else
-+ sparc_debug |= mask;
-+ }
-+ }
-+
-+ /* Enable the FsMULd instruction by default if not explicitly specified by
-+ the user. It may be later disabled by the CPU (explicitly or not). */
-+ if (TARGET_FPU && !(target_flags_explicit & MASK_FSMULD))
-+ target_flags |= MASK_FSMULD;
-+
-+ if (TARGET_DEBUG_OPTIONS)
-+ {
-+ dump_target_flags("Initial target_flags", target_flags);
-+ dump_target_flags("target_flags_explicit", target_flags_explicit);
-+ }
-+
-+#ifdef SUBTARGET_OVERRIDE_OPTIONS
-+ SUBTARGET_OVERRIDE_OPTIONS;
-+#endif
-+
-+#ifndef SPARC_BI_ARCH
-+ /* Check for unsupported architecture size. */
-+ if (!TARGET_64BIT != DEFAULT_ARCH32_P)
-+ error ("%s is not supported by this configuration",
-+ DEFAULT_ARCH32_P ? "-m64" : "-m32");
-+#endif
-+
-+ /* We force all 64bit archs to use 128 bit long double */
-+ if (TARGET_ARCH64 && !TARGET_LONG_DOUBLE_128)
-+ {
-+ error ("%<-mlong-double-64%> not allowed with %<-m64%>");
-+ target_flags |= MASK_LONG_DOUBLE_128;
-+ }
-+
-+ /* Check that -fcall-saved-REG wasn't specified for out registers. */
-+ for (i = 8; i < 16; i++)
-+ if (!call_used_regs [i])
-+ {
-+ error ("%<-fcall-saved-REG%> is not supported for out registers");
-+ call_used_regs [i] = 1;
-+ }
-+
-+ /* Set the default CPU if no -mcpu option was specified. */
-+ if (!global_options_set.x_sparc_cpu_and_features)
-+ {
-+ for (def = &cpu_default[0]; def->cpu != -1; ++def)
-+ if (def->cpu == TARGET_CPU_DEFAULT)
-+ break;
-+ gcc_assert (def->cpu != -1);
-+ sparc_cpu_and_features = def->processor;
-+ }
-+
-+ /* Set the default CPU if no -mtune option was specified. */
-+ if (!global_options_set.x_sparc_cpu)
-+ sparc_cpu = sparc_cpu_and_features;
-+
-+ cpu = &cpu_table[(int) sparc_cpu_and_features];
-+
-+ if (TARGET_DEBUG_OPTIONS)
-+ {
-+ fprintf (stderr, "sparc_cpu_and_features: %s\n", cpu->name);
-+ dump_target_flags ("cpu->disable", cpu->disable);
-+ dump_target_flags ("cpu->enable", cpu->enable);
-+ }
-+
-+ target_flags &= ~cpu->disable;
-+ target_flags |= (cpu->enable
-+#ifndef HAVE_AS_FMAF_HPC_VIS3
-+ & ~(MASK_FMAF | MASK_VIS3)
-+#endif
-+#ifndef HAVE_AS_SPARC4
-+ & ~MASK_CBCOND
-+#endif
-+#ifndef HAVE_AS_SPARC5_VIS4
-+ & ~(MASK_VIS4 | MASK_SUBXC)
-+#endif
-+#ifndef HAVE_AS_SPARC6
-+ & ~(MASK_VIS4B)
-+#endif
-+#ifndef HAVE_AS_LEON
-+ & ~(MASK_LEON | MASK_LEON3)
-+#endif
-+ & ~(target_flags_explicit & MASK_FEATURES)
-+ );
-+
-+ /* FsMULd is a V8 instruction. */
-+ if (!TARGET_V8 && !TARGET_V9)
-+ target_flags &= ~MASK_FSMULD;
-+
-+ /* -mvis2 implies -mvis. */
-+ if (TARGET_VIS2)
-+ target_flags |= MASK_VIS;
-+
-+ /* -mvis3 implies -mvis2 and -mvis. */
-+ if (TARGET_VIS3)
-+ target_flags |= MASK_VIS2 | MASK_VIS;
-+
-+ /* -mvis4 implies -mvis3, -mvis2 and -mvis. */
-+ if (TARGET_VIS4)
-+ target_flags |= MASK_VIS3 | MASK_VIS2 | MASK_VIS;
-+
-+ /* -mvis4b implies -mvis4, -mvis3, -mvis2 and -mvis */
-+ if (TARGET_VIS4B)
-+ target_flags |= MASK_VIS4 | MASK_VIS3 | MASK_VIS2 | MASK_VIS;
-+
-+ /* Don't allow -mvis, -mvis2, -mvis3, -mvis4, -mvis4b, -mfmaf and -mfsmuld if
-+ FPU is disabled. */
-+ if (!TARGET_FPU)
-+ target_flags &= ~(MASK_VIS | MASK_VIS2 | MASK_VIS3 | MASK_VIS4
-+ | MASK_VIS4B | MASK_FMAF | MASK_FSMULD);
-+
-+ /* -mvis assumes UltraSPARC+, so we are sure v9 instructions
-+ are available; -m64 also implies v9. */
-+ if (TARGET_VIS || TARGET_ARCH64)
-+ {
-+ target_flags |= MASK_V9;
-+ target_flags &= ~(MASK_V8 | MASK_SPARCLET | MASK_SPARCLITE);
-+ }
-+
-+ /* -mvis also implies -mv8plus on 32-bit. */
-+ if (TARGET_VIS && !TARGET_ARCH64)
-+ target_flags |= MASK_V8PLUS;
-+
-+ /* Use the deprecated v8 insns for sparc64 in 32-bit mode. */
-+ if (TARGET_V9 && TARGET_ARCH32)
-+ target_flags |= MASK_DEPRECATED_V8_INSNS;
-+
-+ /* V8PLUS requires V9 and makes no sense in 64-bit mode. */
-+ if (!TARGET_V9 || TARGET_ARCH64)
-+ target_flags &= ~MASK_V8PLUS;
-+
-+ /* Don't use stack biasing in 32-bit mode. */
-+ if (TARGET_ARCH32)
-+ target_flags &= ~MASK_STACK_BIAS;
-+
-+ /* Use LRA instead of reload, unless otherwise instructed. */
-+ if (!(target_flags_explicit & MASK_LRA))
-+ target_flags |= MASK_LRA;
-+
-+ /* Enable applicable errata workarounds for LEON3FT. */
-+ if (sparc_fix_ut699 || sparc_fix_ut700 || sparc_fix_gr712rc)
-+ {
-+ sparc_fix_b2bst = 1;
-+ sparc_fix_lost_divsqrt = 1;
-+ }
-+
-+ /* Disable FsMULd for the UT699 since it doesn't work correctly. */
-+ if (sparc_fix_ut699)
-+ target_flags &= ~MASK_FSMULD;
-+
-+#ifdef TARGET_DEFAULT_LONG_DOUBLE_128
-+ if (!(target_flags_explicit & MASK_LONG_DOUBLE_128))
-+ target_flags |= MASK_LONG_DOUBLE_128;
-+#endif
-+
-+ if (TARGET_DEBUG_OPTIONS)
-+ dump_target_flags ("Final target_flags", target_flags);
-+
-+ /* Set the code model if no -mcmodel option was specified. */
-+ if (global_options_set.x_sparc_code_model)
-+ {
-+ if (TARGET_ARCH32)
-+ error ("%<-mcmodel=%> is not supported in 32-bit mode");
-+ }
-+ else
-+ {
-+ if (TARGET_ARCH32)
-+ sparc_code_model = CM_32;
-+ else
-+ sparc_code_model = SPARC_DEFAULT_CMODEL;
-+ }
-+
-+ /* Set the memory model if no -mmemory-model option was specified. */
-+ if (!global_options_set.x_sparc_memory_model)
-+ {
-+ /* Choose the memory model for the operating system. */
-+ enum sparc_memory_model_type os_default = SUBTARGET_DEFAULT_MEMORY_MODEL;
-+ if (os_default != SMM_DEFAULT)
-+ sparc_memory_model = os_default;
-+ /* Choose the most relaxed model for the processor. */
-+ else if (TARGET_V9)
-+ sparc_memory_model = SMM_RMO;
-+ else if (TARGET_LEON3)
-+ sparc_memory_model = SMM_TSO;
-+ else if (TARGET_LEON)
-+ sparc_memory_model = SMM_SC;
-+ else if (TARGET_V8)
-+ sparc_memory_model = SMM_PSO;
-+ else
-+ sparc_memory_model = SMM_SC;
-+ }
-+
-+ /* Supply a default value for align_functions. */
-+ if (flag_align_functions && !str_align_functions)
-+ {
-+ if (sparc_cpu == PROCESSOR_ULTRASPARC
-+ || sparc_cpu == PROCESSOR_ULTRASPARC3
-+ || sparc_cpu == PROCESSOR_NIAGARA
-+ || sparc_cpu == PROCESSOR_NIAGARA2
-+ || sparc_cpu == PROCESSOR_NIAGARA3
-+ || sparc_cpu == PROCESSOR_NIAGARA4)
-+ str_align_functions = "32";
-+ else if (sparc_cpu == PROCESSOR_NIAGARA7
-+ || sparc_cpu == PROCESSOR_M8)
-+ str_align_functions = "64";
-+ }
-+
-+ /* Validate PCC_STRUCT_RETURN. */
-+ if (flag_pcc_struct_return == DEFAULT_PCC_STRUCT_RETURN)
-+ flag_pcc_struct_return = (TARGET_ARCH64 ? 0 : 1);
-+
-+ /* Only use .uaxword when compiling for a 64-bit target. */
-+ if (!TARGET_ARCH64)
-+ targetm.asm_out.unaligned_op.di = NULL;
-+
-+ /* Set the processor costs. */
-+ switch (sparc_cpu)
-+ {
-+ case PROCESSOR_V7:
-+ case PROCESSOR_CYPRESS:
-+ sparc_costs = &cypress_costs;
-+ break;
-+ case PROCESSOR_V8:
-+ case PROCESSOR_SPARCLITE:
-+ case PROCESSOR_SUPERSPARC:
-+ sparc_costs = &supersparc_costs;
-+ break;
-+ case PROCESSOR_F930:
-+ case PROCESSOR_F934:
-+ case PROCESSOR_HYPERSPARC:
-+ case PROCESSOR_SPARCLITE86X:
-+ sparc_costs = &hypersparc_costs;
-+ break;
-+ case PROCESSOR_LEON:
-+ sparc_costs = &leon_costs;
-+ break;
-+ case PROCESSOR_LEON3:
-+ case PROCESSOR_LEON3V7:
-+ sparc_costs = &leon3_costs;
-+ break;
-+ case PROCESSOR_SPARCLET:
-+ case PROCESSOR_TSC701:
-+ sparc_costs = &sparclet_costs;
-+ break;
-+ case PROCESSOR_V9:
-+ case PROCESSOR_ULTRASPARC:
-+ sparc_costs = &ultrasparc_costs;
-+ break;
-+ case PROCESSOR_ULTRASPARC3:
-+ sparc_costs = &ultrasparc3_costs;
-+ break;
-+ case PROCESSOR_NIAGARA:
-+ sparc_costs = &niagara_costs;
-+ break;
-+ case PROCESSOR_NIAGARA2:
-+ sparc_costs = &niagara2_costs;
-+ break;
-+ case PROCESSOR_NIAGARA3:
-+ sparc_costs = &niagara3_costs;
-+ break;
-+ case PROCESSOR_NIAGARA4:
-+ sparc_costs = &niagara4_costs;
-+ break;
-+ case PROCESSOR_NIAGARA7:
-+ sparc_costs = &niagara7_costs;
-+ break;
-+ case PROCESSOR_M8:
-+ sparc_costs = &m8_costs;
-+ break;
-+ case PROCESSOR_NATIVE:
-+ gcc_unreachable ();
-+ };
-+
-+ /* param_simultaneous_prefetches is the number of prefetches that
-+ can run at the same time. More important, it is the threshold
-+ defining when additional prefetches will be dropped by the
-+ hardware.
-+
-+ The UltraSPARC-III features a documented prefetch queue with a
-+ size of 8. Additional prefetches issued in the cpu are
-+ dropped.
-+
-+ Niagara processors are different. In these processors prefetches
-+ are handled much like regular loads. The L1 miss buffer is 32
-+ entries, but prefetches start getting affected when 30 entries
-+ become occupied. That occupation could be a mix of regular loads
-+ and prefetches though. And that buffer is shared by all threads.
-+ Once the threshold is reached, if the core is running a single
-+ thread the prefetch will retry. If more than one thread is
-+ running, the prefetch will be dropped.
-+
-+ All this makes it very difficult to determine how many
-+ simultaneous prefetches can be issued simultaneously, even in a
-+ single-threaded program. Experimental results show that setting
-+ this parameter to 32 works well when the number of threads is not
-+ high. */
-+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
-+ param_simultaneous_prefetches,
-+ ((sparc_cpu == PROCESSOR_ULTRASPARC
-+ || sparc_cpu == PROCESSOR_NIAGARA
-+ || sparc_cpu == PROCESSOR_NIAGARA2
-+ || sparc_cpu == PROCESSOR_NIAGARA3
-+ || sparc_cpu == PROCESSOR_NIAGARA4)
-+ ? 2
-+ : (sparc_cpu == PROCESSOR_ULTRASPARC3
-+ ? 8 : ((sparc_cpu == PROCESSOR_NIAGARA7
-+ || sparc_cpu == PROCESSOR_M8)
-+ ? 32 : 3))));
-+
-+ /* param_l1_cache_line_size is the size of the L1 cache line, in
-+ bytes.
-+
-+ The Oracle SPARC Architecture (previously the UltraSPARC
-+ Architecture) specification states that when a PREFETCH[A]
-+ instruction is executed an implementation-specific amount of data
-+ is prefetched, and that it is at least 64 bytes long (aligned to
-+ at least 64 bytes).
-+
-+ However, this is not correct. The M7 (and implementations prior
-+ to that) does not guarantee a 64B prefetch into a cache if the
-+ line size is smaller. A single cache line is all that is ever
-+ prefetched. So for the M7, where the L1D$ has 32B lines and the
-+ L2D$ and L3 have 64B lines, a prefetch will prefetch 64B into the
-+ L2 and L3, but only 32B are brought into the L1D$. (Assuming it
-+ is a read_n prefetch, which is the only type which allocates to
-+ the L1.) */
-+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
-+ param_l1_cache_line_size,
-+ (sparc_cpu == PROCESSOR_M8 ? 64 : 32));
-+
-+ /* param_l1_cache_size is the size of the L1D$ (most SPARC chips use
-+ Hardvard level-1 caches) in kilobytes. Both UltraSPARC and
-+ Niagara processors feature a L1D$ of 16KB. */
-+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
-+ param_l1_cache_size,
-+ ((sparc_cpu == PROCESSOR_ULTRASPARC
-+ || sparc_cpu == PROCESSOR_ULTRASPARC3
-+ || sparc_cpu == PROCESSOR_NIAGARA
-+ || sparc_cpu == PROCESSOR_NIAGARA2
-+ || sparc_cpu == PROCESSOR_NIAGARA3
-+ || sparc_cpu == PROCESSOR_NIAGARA4
-+ || sparc_cpu == PROCESSOR_NIAGARA7
-+ || sparc_cpu == PROCESSOR_M8)
-+ ? 16 : 64));
-+
-+ /* param_l2_cache_size is the size fo the L2 in kilobytes. Note
-+ that 512 is the default in params.def. */
-+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
-+ param_l2_cache_size,
-+ ((sparc_cpu == PROCESSOR_NIAGARA4
-+ || sparc_cpu == PROCESSOR_M8)
-+ ? 128 : (sparc_cpu == PROCESSOR_NIAGARA7
-+ ? 256 : 512)));
-+
-+
-+ /* Disable save slot sharing for call-clobbered registers by default.
-+ The IRA sharing algorithm works on single registers only and this
-+ pessimizes for double floating-point registers. */
-+ if (!global_options_set.x_flag_ira_share_save_slots)
-+ flag_ira_share_save_slots = 0;
-+
-+ /* Only enable REE by default in 64-bit mode where it helps to eliminate
-+ redundant 32-to-64-bit extensions. */
-+ if (!global_options_set.x_flag_ree && TARGET_ARCH32)
-+ flag_ree = 0;
-+
-+ /* Do various machine dependent initializations. */
-+ sparc_init_modes ();
-+
-+ /* Set up function hooks. */
-+ init_machine_status = sparc_init_machine_status;
-+}
-+
-+/* Miscellaneous utilities. */
-+
-+/* Nonzero if CODE, a comparison, is suitable for use in v9 conditional move
-+ or branch on register contents instructions. */
-+
-+int
-+v9_regcmp_p (enum rtx_code code)
-+{
-+ return (code == EQ || code == NE || code == GE || code == LT
-+ || code == LE || code == GT);
-+}
-+
-+/* Nonzero if OP is a floating point constant which can
-+ be loaded into an integer register using a single
-+ sethi instruction. */
-+
-+int
-+fp_sethi_p (rtx op)
-+{
-+ if (GET_CODE (op) == CONST_DOUBLE)
-+ {
-+ long i;
-+
-+ REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op), i);
-+ return !SPARC_SIMM13_P (i) && SPARC_SETHI_P (i);
-+ }
-+
-+ return 0;
-+}
-+
-+/* Nonzero if OP is a floating point constant which can
-+ be loaded into an integer register using a single
-+ mov instruction. */
-+
-+int
-+fp_mov_p (rtx op)
-+{
-+ if (GET_CODE (op) == CONST_DOUBLE)
-+ {
-+ long i;
-+
-+ REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op), i);
-+ return SPARC_SIMM13_P (i);
-+ }
-+
-+ return 0;
-+}
-+
-+/* Nonzero if OP is a floating point constant which can
-+ be loaded into an integer register using a high/losum
-+ instruction sequence. */
-+
-+int
-+fp_high_losum_p (rtx op)
-+{
-+ /* The constraints calling this should only be in
-+ SFmode move insns, so any constant which cannot
-+ be moved using a single insn will do. */
-+ if (GET_CODE (op) == CONST_DOUBLE)
-+ {
-+ long i;
-+
-+ REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op), i);
-+ return !SPARC_SIMM13_P (i) && !SPARC_SETHI_P (i);
-+ }
-+
-+ return 0;
-+}
-+
-+/* Return true if the address of LABEL can be loaded by means of the
-+ mov{si,di}_pic_label_ref patterns in PIC mode. */
-+
-+static bool
-+can_use_mov_pic_label_ref (rtx label)
-+{
-+ /* VxWorks does not impose a fixed gap between segments; the run-time
-+ gap can be different from the object-file gap. We therefore can't
-+ assume X - _GLOBAL_OFFSET_TABLE_ is a link-time constant unless we
-+ are absolutely sure that X is in the same segment as the GOT.
-+ Unfortunately, the flexibility of linker scripts means that we
-+ can't be sure of that in general, so assume that GOT-relative
-+ accesses are never valid on VxWorks. */
-+ if (TARGET_VXWORKS_RTP)
-+ return false;
-+
-+ /* Similarly, if the label is non-local, it might end up being placed
-+ in a different section than the current one; now mov_pic_label_ref
-+ requires the label and the code to be in the same section. */
-+ if (LABEL_REF_NONLOCAL_P (label))
-+ return false;
-+
-+ /* Finally, if we are reordering basic blocks and partition into hot
-+ and cold sections, this might happen for any label. */
-+ if (flag_reorder_blocks_and_partition)
-+ return false;
-+
-+ return true;
-+}
-+
-+/* Expand a move instruction. Return true if all work is done. */
-+
-+bool
-+sparc_expand_move (machine_mode mode, rtx *operands)
-+{
-+ /* Handle sets of MEM first. */
-+ if (GET_CODE (operands[0]) == MEM)
-+ {
-+ /* 0 is a register (or a pair of registers) on SPARC. */
-+ if (register_or_zero_operand (operands[1], mode))
-+ return false;
-+
-+ if (!reload_in_progress)
-+ {
-+ operands[0] = validize_mem (operands[0]);
-+ operands[1] = force_reg (mode, operands[1]);
-+ }
-+ }
-+
-+ /* Fix up TLS cases. */
-+ if (TARGET_HAVE_TLS
-+ && CONSTANT_P (operands[1])
-+ && sparc_tls_referenced_p (operands [1]))
-+ {
-+ operands[1] = sparc_legitimize_tls_address (operands[1]);
-+ return false;
-+ }
-+
-+ /* Fix up PIC cases. */
-+ if (flag_pic && CONSTANT_P (operands[1]))
-+ {
-+ if (pic_address_needs_scratch (operands[1]))
-+ operands[1] = sparc_legitimize_pic_address (operands[1], NULL_RTX);
-+
-+ /* We cannot use the mov{si,di}_pic_label_ref patterns in all cases. */
-+ if ((GET_CODE (operands[1]) == LABEL_REF
-+ && can_use_mov_pic_label_ref (operands[1]))
-+ || (GET_CODE (operands[1]) == CONST
-+ && GET_CODE (XEXP (operands[1], 0)) == PLUS
-+ && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
-+ && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT
-+ && can_use_mov_pic_label_ref (XEXP (XEXP (operands[1], 0), 0))))
-+ {
-+ if (mode == SImode)
-+ {
-+ emit_insn (gen_movsi_pic_label_ref (operands[0], operands[1]));
-+ return true;
-+ }
-+
-+ if (mode == DImode)
-+ {
-+ emit_insn (gen_movdi_pic_label_ref (operands[0], operands[1]));
-+ return true;
-+ }
-+ }
-+
-+ if (symbolic_operand (operands[1], mode))
-+ {
-+ operands[1]
-+ = sparc_legitimize_pic_address (operands[1],
-+ reload_in_progress
-+ ? operands[0] : NULL_RTX);
-+ return false;
-+ }
-+ }
-+
-+ /* If we are trying to toss an integer constant into FP registers,
-+ or loading a FP or vector constant, force it into memory. */
-+ if (CONSTANT_P (operands[1])
-+ && REG_P (operands[0])
-+ && (SPARC_FP_REG_P (REGNO (operands[0]))
-+ || SCALAR_FLOAT_MODE_P (mode)
-+ || VECTOR_MODE_P (mode)))
-+ {
-+ /* emit_group_store will send such bogosity to us when it is
-+ not storing directly into memory. So fix this up to avoid
-+ crashes in output_constant_pool. */
-+ if (operands [1] == const0_rtx)
-+ operands[1] = CONST0_RTX (mode);
-+
-+ /* We can clear or set to all-ones FP registers if TARGET_VIS, and
-+ always other regs. */
-+ if ((TARGET_VIS || REGNO (operands[0]) < SPARC_FIRST_FP_REG)
-+ && (const_zero_operand (operands[1], mode)
-+ || const_all_ones_operand (operands[1], mode)))
-+ return false;
-+
-+ if (REGNO (operands[0]) < SPARC_FIRST_FP_REG
-+ /* We are able to build any SF constant in integer registers
-+ with at most 2 instructions. */
-+ && (mode == SFmode
-+ /* And any DF constant in integer registers if needed. */
-+ || (mode == DFmode && !can_create_pseudo_p ())))
-+ return false;
-+
-+ operands[1] = force_const_mem (mode, operands[1]);
-+ if (!reload_in_progress)
-+ operands[1] = validize_mem (operands[1]);
-+ return false;
-+ }
-+
-+ /* Accept non-constants and valid constants unmodified. */
-+ if (!CONSTANT_P (operands[1])
-+ || GET_CODE (operands[1]) == HIGH
-+ || input_operand (operands[1], mode))
-+ return false;
-+
-+ switch (mode)
-+ {
-+ case E_QImode:
-+ /* All QImode constants require only one insn, so proceed. */
-+ break;
-+
-+ case E_HImode:
-+ case E_SImode:
-+ sparc_emit_set_const32 (operands[0], operands[1]);
-+ return true;
-+
-+ case E_DImode:
-+ /* input_operand should have filtered out 32-bit mode. */
-+ sparc_emit_set_const64 (operands[0], operands[1]);
-+ return true;
-+
-+ case E_TImode:
-+ {
-+ rtx high, low;
-+ /* TImode isn't available in 32-bit mode. */
-+ split_double (operands[1], &high, &low);
-+ emit_insn (gen_movdi (operand_subword (operands[0], 0, 0, TImode),
-+ high));
-+ emit_insn (gen_movdi (operand_subword (operands[0], 1, 0, TImode),
-+ low));
-+ }
-+ return true;
-+
-+ default:
-+ gcc_unreachable ();
-+ }
-+
-+ return false;
-+}
-+
-+/* Load OP1, a 32-bit constant, into OP0, a register.
-+ We know it can't be done in one insn when we get
-+ here, the move expander guarantees this. */
-+
-+static void
-+sparc_emit_set_const32 (rtx op0, rtx op1)
-+{
-+ machine_mode mode = GET_MODE (op0);
-+ rtx temp = op0;
-+
-+ if (can_create_pseudo_p ())
-+ temp = gen_reg_rtx (mode);
-+
-+ if (GET_CODE (op1) == CONST_INT)
-+ {
-+ gcc_assert (!small_int_operand (op1, mode)
-+ && !const_high_operand (op1, mode));
-+
-+ /* Emit them as real moves instead of a HIGH/LO_SUM,
-+ this way CSE can see everything and reuse intermediate
-+ values if it wants. */
-+ emit_insn (gen_rtx_SET (temp, GEN_INT (INTVAL (op1)
-+ & ~(HOST_WIDE_INT) 0x3ff)));
-+
-+ emit_insn (gen_rtx_SET (op0,
-+ gen_rtx_IOR (mode, temp,
-+ GEN_INT (INTVAL (op1) & 0x3ff))));
-+ }
-+ else
-+ {
-+ /* A symbol, emit in the traditional way. */
-+ emit_insn (gen_rtx_SET (temp, gen_rtx_HIGH (mode, op1)));
-+ emit_insn (gen_rtx_SET (op0, gen_rtx_LO_SUM (mode, temp, op1)));
-+ }
-+}
-+
-+/* Load OP1, a symbolic 64-bit constant, into OP0, a DImode register.
-+ If TEMP is nonzero, we are forbidden to use any other scratch
-+ registers. Otherwise, we are allowed to generate them as needed.
-+
-+ Note that TEMP may have TImode if the code model is TARGET_CM_MEDANY
-+ or TARGET_CM_EMBMEDANY (see the reload_indi and reload_outdi patterns). */
-+
-+void
-+sparc_emit_set_symbolic_const64 (rtx op0, rtx op1, rtx temp)
-+{
-+ rtx cst, temp1, temp2, temp3, temp4, temp5;
-+ rtx ti_temp = 0;
-+
-+ /* Deal with too large offsets. */
-+ if (GET_CODE (op1) == CONST
-+ && GET_CODE (XEXP (op1, 0)) == PLUS
-+ && CONST_INT_P (cst = XEXP (XEXP (op1, 0), 1))
-+ && trunc_int_for_mode (INTVAL (cst), SImode) != INTVAL (cst))
-+ {
-+ gcc_assert (!temp);
-+ temp1 = gen_reg_rtx (DImode);
-+ temp2 = gen_reg_rtx (DImode);
-+ sparc_emit_set_const64 (temp2, cst);
-+ sparc_emit_set_symbolic_const64 (temp1, XEXP (XEXP (op1, 0), 0),
-+ NULL_RTX);
-+ emit_insn (gen_rtx_SET (op0, gen_rtx_PLUS (DImode, temp1, temp2)));
-+ return;
-+ }
-+
-+ if (temp && GET_MODE (temp) == TImode)
-+ {
-+ ti_temp = temp;
-+ temp = gen_rtx_REG (DImode, REGNO (temp));
-+ }
-+
-+ /* SPARC-V9 code model support. */
-+ switch (sparc_code_model)
-+ {
-+ case CM_MEDLOW:
-+ /* The range spanned by all instructions in the object is less
-+ than 2^31 bytes (2GB) and the distance from any instruction
-+ to the location of the label _GLOBAL_OFFSET_TABLE_ is less
-+ than 2^31 bytes (2GB).
-+
-+ The executable must be in the low 4TB of the virtual address
-+ space.
-+
-+ sethi %hi(symbol), %temp1
-+ or %temp1, %lo(symbol), %reg */
-+ if (temp)
-+ temp1 = temp; /* op0 is allowed. */
-+ else
-+ temp1 = gen_reg_rtx (DImode);
-+
-+ emit_insn (gen_rtx_SET (temp1, gen_rtx_HIGH (DImode, op1)));
-+ emit_insn (gen_rtx_SET (op0, gen_rtx_LO_SUM (DImode, temp1, op1)));
-+ break;
-+
-+ case CM_MEDMID:
-+ /* The range spanned by all instructions in the object is less
-+ than 2^31 bytes (2GB) and the distance from any instruction
-+ to the location of the label _GLOBAL_OFFSET_TABLE_ is less
-+ than 2^31 bytes (2GB).
-+
-+ The executable must be in the low 16TB of the virtual address
-+ space.
-+
-+ sethi %h44(symbol), %temp1
-+ or %temp1, %m44(symbol), %temp2
-+ sllx %temp2, 12, %temp3
-+ or %temp3, %l44(symbol), %reg */
-+ if (temp)
-+ {
-+ temp1 = op0;
-+ temp2 = op0;
-+ temp3 = temp; /* op0 is allowed. */
-+ }
-+ else
-+ {
-+ temp1 = gen_reg_rtx (DImode);
-+ temp2 = gen_reg_rtx (DImode);
-+ temp3 = gen_reg_rtx (DImode);
-+ }
-+
-+ emit_insn (gen_seth44 (temp1, op1));
-+ emit_insn (gen_setm44 (temp2, temp1, op1));
-+ emit_insn (gen_rtx_SET (temp3,
-+ gen_rtx_ASHIFT (DImode, temp2, GEN_INT (12))));
-+ emit_insn (gen_setl44 (op0, temp3, op1));
-+ break;
-+
-+ case CM_MEDANY:
-+ /* The range spanned by all instructions in the object is less
-+ than 2^31 bytes (2GB) and the distance from any instruction
-+ to the location of the label _GLOBAL_OFFSET_TABLE_ is less
-+ than 2^31 bytes (2GB).
-+
-+ The executable can be placed anywhere in the virtual address
-+ space.
-+
-+ sethi %hh(symbol), %temp1
-+ sethi %lm(symbol), %temp2
-+ or %temp1, %hm(symbol), %temp3
-+ sllx %temp3, 32, %temp4
-+ or %temp4, %temp2, %temp5
-+ or %temp5, %lo(symbol), %reg */
-+ if (temp)
-+ {
-+ /* It is possible that one of the registers we got for operands[2]
-+ might coincide with that of operands[0] (which is why we made
-+ it TImode). Pick the other one to use as our scratch. */
-+ if (rtx_equal_p (temp, op0))
-+ {
-+ gcc_assert (ti_temp);
-+ temp = gen_rtx_REG (DImode, REGNO (temp) + 1);
-+ }
-+ temp1 = op0;
-+ temp2 = temp; /* op0 is _not_ allowed, see above. */
-+ temp3 = op0;
-+ temp4 = op0;
-+ temp5 = op0;
-+ }
-+ else
-+ {
-+ temp1 = gen_reg_rtx (DImode);
-+ temp2 = gen_reg_rtx (DImode);
-+ temp3 = gen_reg_rtx (DImode);
-+ temp4 = gen_reg_rtx (DImode);
-+ temp5 = gen_reg_rtx (DImode);
-+ }
-+
-+ emit_insn (gen_sethh (temp1, op1));
-+ emit_insn (gen_setlm (temp2, op1));
-+ emit_insn (gen_sethm (temp3, temp1, op1));
-+ emit_insn (gen_rtx_SET (temp4,
-+ gen_rtx_ASHIFT (DImode, temp3, GEN_INT (32))));
-+ emit_insn (gen_rtx_SET (temp5, gen_rtx_PLUS (DImode, temp4, temp2)));
-+ emit_insn (gen_setlo (op0, temp5, op1));
-+ break;
-+
-+ case CM_EMBMEDANY:
-+ /* Old old old backwards compatibility kruft here.
-+ Essentially it is MEDLOW with a fixed 64-bit
-+ virtual base added to all data segment addresses.
-+ Text-segment stuff is computed like MEDANY, we can't
-+ reuse the code above because the relocation knobs
-+ look different.
-+
-+ Data segment: sethi %hi(symbol), %temp1
-+ add %temp1, EMBMEDANY_BASE_REG, %temp2
-+ or %temp2, %lo(symbol), %reg */
-+ if (data_segment_operand (op1, GET_MODE (op1)))
-+ {
-+ if (temp)
-+ {
-+ temp1 = temp; /* op0 is allowed. */
-+ temp2 = op0;
-+ }
-+ else
-+ {
-+ temp1 = gen_reg_rtx (DImode);
-+ temp2 = gen_reg_rtx (DImode);
-+ }
-+
-+ emit_insn (gen_embmedany_sethi (temp1, op1));
-+ emit_insn (gen_embmedany_brsum (temp2, temp1));
-+ emit_insn (gen_embmedany_losum (op0, temp2, op1));
-+ }
-+
-+ /* Text segment: sethi %uhi(symbol), %temp1
-+ sethi %hi(symbol), %temp2
-+ or %temp1, %ulo(symbol), %temp3
-+ sllx %temp3, 32, %temp4
-+ or %temp4, %temp2, %temp5
-+ or %temp5, %lo(symbol), %reg */
-+ else
-+ {
-+ if (temp)
-+ {
-+ /* It is possible that one of the registers we got for operands[2]
-+ might coincide with that of operands[0] (which is why we made
-+ it TImode). Pick the other one to use as our scratch. */
-+ if (rtx_equal_p (temp, op0))
-+ {
-+ gcc_assert (ti_temp);
-+ temp = gen_rtx_REG (DImode, REGNO (temp) + 1);
-+ }
-+ temp1 = op0;
-+ temp2 = temp; /* op0 is _not_ allowed, see above. */
-+ temp3 = op0;
-+ temp4 = op0;
-+ temp5 = op0;
-+ }
-+ else
-+ {
-+ temp1 = gen_reg_rtx (DImode);
-+ temp2 = gen_reg_rtx (DImode);
-+ temp3 = gen_reg_rtx (DImode);
-+ temp4 = gen_reg_rtx (DImode);
-+ temp5 = gen_reg_rtx (DImode);
-+ }
-+
-+ emit_insn (gen_embmedany_textuhi (temp1, op1));
-+ emit_insn (gen_embmedany_texthi (temp2, op1));
-+ emit_insn (gen_embmedany_textulo (temp3, temp1, op1));
-+ emit_insn (gen_rtx_SET (temp4,
-+ gen_rtx_ASHIFT (DImode, temp3, GEN_INT (32))));
-+ emit_insn (gen_rtx_SET (temp5, gen_rtx_PLUS (DImode, temp4, temp2)));
-+ emit_insn (gen_embmedany_textlo (op0, temp5, op1));
-+ }
-+ break;
-+
-+ default:
-+ gcc_unreachable ();
-+ }
-+}
-+
-+/* These avoid problems when cross compiling. If we do not
-+ go through all this hair then the optimizer will see
-+ invalid REG_EQUAL notes or in some cases none at all. */
-+static rtx gen_safe_HIGH64 (rtx, HOST_WIDE_INT);
-+static rtx gen_safe_SET64 (rtx, HOST_WIDE_INT);
-+static rtx gen_safe_OR64 (rtx, HOST_WIDE_INT);
-+static rtx gen_safe_XOR64 (rtx, HOST_WIDE_INT);
-+
-+/* The optimizer is not to assume anything about exactly
-+ which bits are set for a HIGH, they are unspecified.
-+ Unfortunately this leads to many missed optimizations
-+ during CSE. We mask out the non-HIGH bits, and matches
-+ a plain movdi, to alleviate this problem. */
-+static rtx
-+gen_safe_HIGH64 (rtx dest, HOST_WIDE_INT val)
-+{
-+ return gen_rtx_SET (dest, GEN_INT (val & ~(HOST_WIDE_INT)0x3ff));
-+}
-+
-+static rtx
-+gen_safe_SET64 (rtx dest, HOST_WIDE_INT val)
-+{
-+ return gen_rtx_SET (dest, GEN_INT (val));
-+}
-+
-+static rtx
-+gen_safe_OR64 (rtx src, HOST_WIDE_INT val)
-+{
-+ return gen_rtx_IOR (DImode, src, GEN_INT (val));
-+}
-+
-+static rtx
-+gen_safe_XOR64 (rtx src, HOST_WIDE_INT val)
-+{
-+ return gen_rtx_XOR (DImode, src, GEN_INT (val));
-+}
-+
-+/* Worker routines for 64-bit constant formation on arch64.
-+ One of the key things to be doing in these emissions is
-+ to create as many temp REGs as possible. This makes it
-+ possible for half-built constants to be used later when
-+ such values are similar to something required later on.
-+ Without doing this, the optimizer cannot see such
-+ opportunities. */
-+
-+static void sparc_emit_set_const64_quick1 (rtx, rtx,
-+ unsigned HOST_WIDE_INT, int);
-+
-+static void
-+sparc_emit_set_const64_quick1 (rtx op0, rtx temp,
-+ unsigned HOST_WIDE_INT low_bits, int is_neg)
-+{
-+ unsigned HOST_WIDE_INT high_bits;
-+
-+ if (is_neg)
-+ high_bits = (~low_bits) & 0xffffffff;
-+ else
-+ high_bits = low_bits;
-+
-+ emit_insn (gen_safe_HIGH64 (temp, high_bits));
-+ if (!is_neg)
-+ {
-+ emit_insn (gen_rtx_SET (op0, gen_safe_OR64 (temp, (high_bits & 0x3ff))));
-+ }
-+ else
-+ {
-+ /* If we are XOR'ing with -1, then we should emit a one's complement
-+ instead. This way the combiner will notice logical operations
-+ such as ANDN later on and substitute. */
-+ if ((low_bits & 0x3ff) == 0x3ff)
-+ {
-+ emit_insn (gen_rtx_SET (op0, gen_rtx_NOT (DImode, temp)));
-+ }
-+ else
-+ {
-+ emit_insn (gen_rtx_SET (op0,
-+ gen_safe_XOR64 (temp,
-+ (-(HOST_WIDE_INT)0x400
-+ | (low_bits & 0x3ff)))));
-+ }
-+ }
-+}
-+
-+static void sparc_emit_set_const64_quick2 (rtx, rtx, unsigned HOST_WIDE_INT,
-+ unsigned HOST_WIDE_INT, int);
-+
-+static void
-+sparc_emit_set_const64_quick2 (rtx op0, rtx temp,
-+ unsigned HOST_WIDE_INT high_bits,
-+ unsigned HOST_WIDE_INT low_immediate,
-+ int shift_count)
-+{
-+ rtx temp2 = op0;
-+
-+ if ((high_bits & 0xfffffc00) != 0)
-+ {
-+ emit_insn (gen_safe_HIGH64 (temp, high_bits));
-+ if ((high_bits & ~0xfffffc00) != 0)
-+ emit_insn (gen_rtx_SET (op0,
-+ gen_safe_OR64 (temp, (high_bits & 0x3ff))));
-+ else
-+ temp2 = temp;
-+ }
-+ else
-+ {
-+ emit_insn (gen_safe_SET64 (temp, high_bits));
-+ temp2 = temp;
-+ }
-+
-+ /* Now shift it up into place. */
-+ emit_insn (gen_rtx_SET (op0, gen_rtx_ASHIFT (DImode, temp2,
-+ GEN_INT (shift_count))));
-+
-+ /* If there is a low immediate part piece, finish up by
-+ putting that in as well. */
-+ if (low_immediate != 0)
-+ emit_insn (gen_rtx_SET (op0, gen_safe_OR64 (op0, low_immediate)));
-+}
-+
-+static void sparc_emit_set_const64_longway (rtx, rtx, unsigned HOST_WIDE_INT,
-+ unsigned HOST_WIDE_INT);
-+
-+/* Full 64-bit constant decomposition. Even though this is the
-+ 'worst' case, we still optimize a few things away. */
-+static void
-+sparc_emit_set_const64_longway (rtx op0, rtx temp,
-+ unsigned HOST_WIDE_INT high_bits,
-+ unsigned HOST_WIDE_INT low_bits)
-+{
-+ rtx sub_temp = op0;
-+
-+ if (can_create_pseudo_p ())
-+ sub_temp = gen_reg_rtx (DImode);
-+
-+ if ((high_bits & 0xfffffc00) != 0)
-+ {
-+ emit_insn (gen_safe_HIGH64 (temp, high_bits));
-+ if ((high_bits & ~0xfffffc00) != 0)
-+ emit_insn (gen_rtx_SET (sub_temp,
-+ gen_safe_OR64 (temp, (high_bits & 0x3ff))));
-+ else
-+ sub_temp = temp;
-+ }
-+ else
-+ {
-+ emit_insn (gen_safe_SET64 (temp, high_bits));
-+ sub_temp = temp;
-+ }
-+
-+ if (can_create_pseudo_p ())
-+ {
-+ rtx temp2 = gen_reg_rtx (DImode);
-+ rtx temp3 = gen_reg_rtx (DImode);
-+ rtx temp4 = gen_reg_rtx (DImode);
-+
-+ emit_insn (gen_rtx_SET (temp4, gen_rtx_ASHIFT (DImode, sub_temp,
-+ GEN_INT (32))));
-+
-+ emit_insn (gen_safe_HIGH64 (temp2, low_bits));
-+ if ((low_bits & ~0xfffffc00) != 0)
-+ {
-+ emit_insn (gen_rtx_SET (temp3,
-+ gen_safe_OR64 (temp2, (low_bits & 0x3ff))));
-+ emit_insn (gen_rtx_SET (op0, gen_rtx_PLUS (DImode, temp4, temp3)));
-+ }
-+ else
-+ {
-+ emit_insn (gen_rtx_SET (op0, gen_rtx_PLUS (DImode, temp4, temp2)));
-+ }
-+ }
-+ else
-+ {
-+ rtx low1 = GEN_INT ((low_bits >> (32 - 12)) & 0xfff);
-+ rtx low2 = GEN_INT ((low_bits >> (32 - 12 - 12)) & 0xfff);
-+ rtx low3 = GEN_INT ((low_bits >> (32 - 12 - 12 - 8)) & 0x0ff);
-+ int to_shift = 12;
-+
-+ /* We are in the middle of reload, so this is really
-+ painful. However we do still make an attempt to
-+ avoid emitting truly stupid code. */
-+ if (low1 != const0_rtx)
-+ {
-+ emit_insn (gen_rtx_SET (op0, gen_rtx_ASHIFT (DImode, sub_temp,
-+ GEN_INT (to_shift))));
-+ emit_insn (gen_rtx_SET (op0, gen_rtx_IOR (DImode, op0, low1)));
-+ sub_temp = op0;
-+ to_shift = 12;
-+ }
-+ else
-+ {
-+ to_shift += 12;
-+ }
-+ if (low2 != const0_rtx)
-+ {
-+ emit_insn (gen_rtx_SET (op0, gen_rtx_ASHIFT (DImode, sub_temp,
-+ GEN_INT (to_shift))));
-+ emit_insn (gen_rtx_SET (op0, gen_rtx_IOR (DImode, op0, low2)));
-+ sub_temp = op0;
-+ to_shift = 8;
-+ }
-+ else
-+ {
-+ to_shift += 8;
-+ }
-+ emit_insn (gen_rtx_SET (op0, gen_rtx_ASHIFT (DImode, sub_temp,
-+ GEN_INT (to_shift))));
-+ if (low3 != const0_rtx)
-+ emit_insn (gen_rtx_SET (op0, gen_rtx_IOR (DImode, op0, low3)));
-+ /* phew... */
-+ }
-+}
-+
-+/* Analyze a 64-bit constant for certain properties. */
-+static void analyze_64bit_constant (unsigned HOST_WIDE_INT,
-+ unsigned HOST_WIDE_INT,
-+ int *, int *, int *);
-+
-+static void
-+analyze_64bit_constant (unsigned HOST_WIDE_INT high_bits,
-+ unsigned HOST_WIDE_INT low_bits,
-+ int *hbsp, int *lbsp, int *abbasp)
-+{
-+ int lowest_bit_set, highest_bit_set, all_bits_between_are_set;
-+ int i;
-+
-+ lowest_bit_set = highest_bit_set = -1;
-+ i = 0;
-+ do
-+ {
-+ if ((lowest_bit_set == -1)
-+ && ((low_bits >> i) & 1))
-+ lowest_bit_set = i;
-+ if ((highest_bit_set == -1)
-+ && ((high_bits >> (32 - i - 1)) & 1))
-+ highest_bit_set = (64 - i - 1);
-+ }
-+ while (++i < 32
-+ && ((highest_bit_set == -1)
-+ || (lowest_bit_set == -1)));
-+ if (i == 32)
-+ {
-+ i = 0;
-+ do
-+ {
-+ if ((lowest_bit_set == -1)
-+ && ((high_bits >> i) & 1))
-+ lowest_bit_set = i + 32;
-+ if ((highest_bit_set == -1)
-+ && ((low_bits >> (32 - i - 1)) & 1))
-+ highest_bit_set = 32 - i - 1;
-+ }
-+ while (++i < 32
-+ && ((highest_bit_set == -1)
-+ || (lowest_bit_set == -1)));
-+ }
-+ /* If there are no bits set this should have gone out
-+ as one instruction! */
-+ gcc_assert (lowest_bit_set != -1 && highest_bit_set != -1);
-+ all_bits_between_are_set = 1;
-+ for (i = lowest_bit_set; i <= highest_bit_set; i++)
-+ {
-+ if (i < 32)
-+ {
-+ if ((low_bits & (1 << i)) != 0)
-+ continue;
-+ }
-+ else
-+ {
-+ if ((high_bits & (1 << (i - 32))) != 0)
-+ continue;
-+ }
-+ all_bits_between_are_set = 0;
-+ break;
-+ }
-+ *hbsp = highest_bit_set;
-+ *lbsp = lowest_bit_set;
-+ *abbasp = all_bits_between_are_set;
-+}
-+
-+static int const64_is_2insns (unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT);
-+
-+static int
-+const64_is_2insns (unsigned HOST_WIDE_INT high_bits,
-+ unsigned HOST_WIDE_INT low_bits)
-+{
-+ int highest_bit_set, lowest_bit_set, all_bits_between_are_set;
-+
-+ if (high_bits == 0
-+ || high_bits == 0xffffffff)
-+ return 1;
-+
-+ analyze_64bit_constant (high_bits, low_bits,
-+ &highest_bit_set, &lowest_bit_set,
-+ &all_bits_between_are_set);
-+
-+ if ((highest_bit_set == 63
-+ || lowest_bit_set == 0)
-+ && all_bits_between_are_set != 0)
-+ return 1;
-+
-+ if ((highest_bit_set - lowest_bit_set) < 21)
-+ return 1;
-+
-+ return 0;
-+}
-+
-+static unsigned HOST_WIDE_INT create_simple_focus_bits (unsigned HOST_WIDE_INT,
-+ unsigned HOST_WIDE_INT,
-+ int, int);
-+
-+static unsigned HOST_WIDE_INT
-+create_simple_focus_bits (unsigned HOST_WIDE_INT high_bits,
-+ unsigned HOST_WIDE_INT low_bits,
-+ int lowest_bit_set, int shift)
-+{
-+ HOST_WIDE_INT hi, lo;
-+
-+ if (lowest_bit_set < 32)
-+ {
-+ lo = (low_bits >> lowest_bit_set) << shift;
-+ hi = ((high_bits << (32 - lowest_bit_set)) << shift);
-+ }
-+ else
-+ {
-+ lo = 0;
-+ hi = ((high_bits >> (lowest_bit_set - 32)) << shift);
-+ }
-+ gcc_assert (! (hi & lo));
-+ return (hi | lo);
-+}
-+
-+/* Here we are sure to be arch64 and this is an integer constant
-+ being loaded into a register. Emit the most efficient
-+ insn sequence possible. Detection of all the 1-insn cases
-+ has been done already. */
-+static void
-+sparc_emit_set_const64 (rtx op0, rtx op1)
-+{
-+ unsigned HOST_WIDE_INT high_bits, low_bits;
-+ int lowest_bit_set, highest_bit_set;
-+ int all_bits_between_are_set;
-+ rtx temp = 0;
-+
-+ /* Sanity check that we know what we are working with. */
-+ gcc_assert (TARGET_ARCH64
-+ && (GET_CODE (op0) == SUBREG
-+ || (REG_P (op0) && ! SPARC_FP_REG_P (REGNO (op0)))));
-+
-+ if (! can_create_pseudo_p ())
-+ temp = op0;
-+
-+ if (GET_CODE (op1) != CONST_INT)
-+ {
-+ sparc_emit_set_symbolic_const64 (op0, op1, temp);
-+ return;
-+ }
-+
-+ if (! temp)
-+ temp = gen_reg_rtx (DImode);
-+
-+ high_bits = ((INTVAL (op1) >> 32) & 0xffffffff);
-+ low_bits = (INTVAL (op1) & 0xffffffff);
-+
-+ /* low_bits bits 0 --> 31
-+ high_bits bits 32 --> 63 */
-+
-+ analyze_64bit_constant (high_bits, low_bits,
-+ &highest_bit_set, &lowest_bit_set,
-+ &all_bits_between_are_set);
-+
-+ /* First try for a 2-insn sequence. */
-+
-+ /* These situations are preferred because the optimizer can
-+ * do more things with them:
-+ * 1) mov -1, %reg
-+ * sllx %reg, shift, %reg
-+ * 2) mov -1, %reg
-+ * srlx %reg, shift, %reg
-+ * 3) mov some_small_const, %reg
-+ * sllx %reg, shift, %reg
-+ */
-+ if (((highest_bit_set == 63
-+ || lowest_bit_set == 0)
-+ && all_bits_between_are_set != 0)
-+ || ((highest_bit_set - lowest_bit_set) < 12))
-+ {
-+ HOST_WIDE_INT the_const = -1;
-+ int shift = lowest_bit_set;
-+
-+ if ((highest_bit_set != 63
-+ && lowest_bit_set != 0)
-+ || all_bits_between_are_set == 0)
-+ {
-+ the_const =
-+ create_simple_focus_bits (high_bits, low_bits,
-+ lowest_bit_set, 0);
-+ }
-+ else if (lowest_bit_set == 0)
-+ shift = -(63 - highest_bit_set);
-+
-+ gcc_assert (SPARC_SIMM13_P (the_const));
-+ gcc_assert (shift != 0);
-+
-+ emit_insn (gen_safe_SET64 (temp, the_const));
-+ if (shift > 0)
-+ emit_insn (gen_rtx_SET (op0, gen_rtx_ASHIFT (DImode, temp,
-+ GEN_INT (shift))));
-+ else if (shift < 0)
-+ emit_insn (gen_rtx_SET (op0, gen_rtx_LSHIFTRT (DImode, temp,
-+ GEN_INT (-shift))));
-+ return;
-+ }
-+
-+ /* Now a range of 22 or less bits set somewhere.
-+ * 1) sethi %hi(focus_bits), %reg
-+ * sllx %reg, shift, %reg
-+ * 2) sethi %hi(focus_bits), %reg
-+ * srlx %reg, shift, %reg
-+ */
-+ if ((highest_bit_set - lowest_bit_set) < 21)
-+ {
-+ unsigned HOST_WIDE_INT focus_bits =
-+ create_simple_focus_bits (high_bits, low_bits,
-+ lowest_bit_set, 10);
-+
-+ gcc_assert (SPARC_SETHI_P (focus_bits));
-+ gcc_assert (lowest_bit_set != 10);
-+
-+ emit_insn (gen_safe_HIGH64 (temp, focus_bits));
-+
-+ /* If lowest_bit_set == 10 then a sethi alone could have done it. */
-+ if (lowest_bit_set < 10)
-+ emit_insn (gen_rtx_SET (op0,
-+ gen_rtx_LSHIFTRT (DImode, temp,
-+ GEN_INT (10 - lowest_bit_set))));
-+ else if (lowest_bit_set > 10)
-+ emit_insn (gen_rtx_SET (op0,
-+ gen_rtx_ASHIFT (DImode, temp,
-+ GEN_INT (lowest_bit_set - 10))));
-+ return;
-+ }
-+
-+ /* 1) sethi %hi(low_bits), %reg
-+ * or %reg, %lo(low_bits), %reg
-+ * 2) sethi %hi(~low_bits), %reg
-+ * xor %reg, %lo(-0x400 | (low_bits & 0x3ff)), %reg
-+ */
-+ if (high_bits == 0
-+ || high_bits == 0xffffffff)
-+ {
-+ sparc_emit_set_const64_quick1 (op0, temp, low_bits,
-+ (high_bits == 0xffffffff));
-+ return;
-+ }
-+
-+ /* Now, try 3-insn sequences. */
-+
-+ /* 1) sethi %hi(high_bits), %reg
-+ * or %reg, %lo(high_bits), %reg
-+ * sllx %reg, 32, %reg
-+ */
-+ if (low_bits == 0)
-+ {
-+ sparc_emit_set_const64_quick2 (op0, temp, high_bits, 0, 32);
-+ return;
-+ }
-+
-+ /* We may be able to do something quick
-+ when the constant is negated, so try that. */
-+ if (const64_is_2insns ((~high_bits) & 0xffffffff,
-+ (~low_bits) & 0xfffffc00))
-+ {
-+ /* NOTE: The trailing bits get XOR'd so we need the
-+ non-negated bits, not the negated ones. */
-+ unsigned HOST_WIDE_INT trailing_bits = low_bits & 0x3ff;
-+
-+ if ((((~high_bits) & 0xffffffff) == 0
-+ && ((~low_bits) & 0x80000000) == 0)
-+ || (((~high_bits) & 0xffffffff) == 0xffffffff
-+ && ((~low_bits) & 0x80000000) != 0))
-+ {
-+ unsigned HOST_WIDE_INT fast_int = (~low_bits & 0xffffffff);
-+
-+ if ((SPARC_SETHI_P (fast_int)
-+ && (~high_bits & 0xffffffff) == 0)
-+ || SPARC_SIMM13_P (fast_int))
-+ emit_insn (gen_safe_SET64 (temp, fast_int));
-+ else
-+ sparc_emit_set_const64 (temp, GEN_INT (fast_int));
-+ }
-+ else
-+ {
-+ rtx negated_const;
-+ negated_const = GEN_INT (((~low_bits) & 0xfffffc00) |
-+ (((HOST_WIDE_INT)((~high_bits) & 0xffffffff))<<32));
-+ sparc_emit_set_const64 (temp, negated_const);
-+ }
-+
-+ /* If we are XOR'ing with -1, then we should emit a one's complement
-+ instead. This way the combiner will notice logical operations
-+ such as ANDN later on and substitute. */
-+ if (trailing_bits == 0x3ff)
-+ {
-+ emit_insn (gen_rtx_SET (op0, gen_rtx_NOT (DImode, temp)));
-+ }
-+ else
-+ {
-+ emit_insn (gen_rtx_SET (op0,
-+ gen_safe_XOR64 (temp,
-+ (-0x400 | trailing_bits))));
-+ }
-+ return;
-+ }
-+
-+ /* 1) sethi %hi(xxx), %reg
-+ * or %reg, %lo(xxx), %reg
-+ * sllx %reg, yyy, %reg
-+ *
-+ * ??? This is just a generalized version of the low_bits==0
-+ * thing above, FIXME...
-+ */
-+ if ((highest_bit_set - lowest_bit_set) < 32)
-+ {
-+ unsigned HOST_WIDE_INT focus_bits =
-+ create_simple_focus_bits (high_bits, low_bits,
-+ lowest_bit_set, 0);
-+
-+ /* We can't get here in this state. */
-+ gcc_assert (highest_bit_set >= 32 && lowest_bit_set < 32);
-+
-+ /* So what we know is that the set bits straddle the
-+ middle of the 64-bit word. */
-+ sparc_emit_set_const64_quick2 (op0, temp,
-+ focus_bits, 0,
-+ lowest_bit_set);
-+ return;
-+ }
-+
-+ /* 1) sethi %hi(high_bits), %reg
-+ * or %reg, %lo(high_bits), %reg
-+ * sllx %reg, 32, %reg
-+ * or %reg, low_bits, %reg
-+ */
-+ if (SPARC_SIMM13_P (low_bits) && ((int)low_bits > 0))
-+ {
-+ sparc_emit_set_const64_quick2 (op0, temp, high_bits, low_bits, 32);
-+ return;
-+ }
-+
-+ /* The easiest way when all else fails, is full decomposition. */
-+ sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits);
-+}
-+
-+/* Implement TARGET_FIXED_CONDITION_CODE_REGS. */
-+
-+static bool
-+sparc_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
-+{
-+ *p1 = SPARC_ICC_REG;
-+ *p2 = SPARC_FCC_REG;
-+ return true;
-+}
-+
-+/* Implement TARGET_MIN_ARITHMETIC_PRECISION. */
-+
-+static unsigned int
-+sparc_min_arithmetic_precision (void)
-+{
-+ return 32;
-+}
-+
-+/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
-+ return the mode to be used for the comparison. For floating-point,
-+ CCFP[E]mode is used. CCNZmode should be used when the first operand
-+ is a PLUS, MINUS, NEG, or ASHIFT. CCmode should be used when no special
-+ processing is needed. */
-+
-+machine_mode
-+select_cc_mode (enum rtx_code op, rtx x, rtx y)
-+{
-+ if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
-+ {
-+ switch (op)
-+ {
-+ case EQ:
-+ case NE:
-+ case UNORDERED:
-+ case ORDERED:
-+ case UNLT:
-+ case UNLE:
-+ case UNGT:
-+ case UNGE:
-+ case UNEQ:
-+ return CCFPmode;
-+
-+ case LT:
-+ case LE:
-+ case GT:
-+ case GE:
-+ case LTGT:
-+ return CCFPEmode;
-+
-+ default:
-+ gcc_unreachable ();
-+ }
-+ }
-+ else if ((GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
-+ || GET_CODE (x) == NEG || GET_CODE (x) == ASHIFT)
-+ && y == const0_rtx)
-+ {
-+ if (TARGET_ARCH64 && GET_MODE (x) == DImode)
-+ return CCXNZmode;
-+ else
-+ return CCNZmode;
-+ }
-+ else
-+ {
-+ /* This is for the cmp<mode>_sne pattern. */
-+ if (GET_CODE (x) == NOT && y == constm1_rtx)
-+ {
-+ if (TARGET_ARCH64 && GET_MODE (x) == DImode)
-+ return CCXCmode;
-+ else
-+ return CCCmode;
-+ }
-+
-+ /* This is for the [u]addvdi4_sp32 and [u]subvdi4_sp32 patterns. */
-+ if (!TARGET_ARCH64 && GET_MODE (x) == DImode)
-+ {
-+ if (GET_CODE (y) == UNSPEC
-+ && (XINT (y, 1) == UNSPEC_ADDV
-+ || XINT (y, 1) == UNSPEC_SUBV
-+ || XINT (y, 1) == UNSPEC_NEGV))
-+ return CCVmode;
-+ else
-+ return CCCmode;
-+ }
-+
-+ if (TARGET_ARCH64 && GET_MODE (x) == DImode)
-+ return CCXmode;
-+ else
-+ return CCmode;
-+ }
-+}
-+
-+/* Emit the compare insn and return the CC reg for a CODE comparison
-+ with operands X and Y. */
-+
-+static rtx
-+gen_compare_reg_1 (enum rtx_code code, rtx x, rtx y)
-+{
-+ machine_mode mode;
-+ rtx cc_reg;
-+
-+ if (GET_MODE_CLASS (GET_MODE (x)) == MODE_CC)
-+ return x;
-+
-+ mode = SELECT_CC_MODE (code, x, y);
-+
-+ /* ??? We don't have movcc patterns so we cannot generate pseudo regs for the
-+ fcc regs (cse can't tell they're really call clobbered regs and will
-+ remove a duplicate comparison even if there is an intervening function
-+ call - it will then try to reload the cc reg via an int reg which is why
-+ we need the movcc patterns). It is possible to provide the movcc
-+ patterns by using the ldxfsr/stxfsr v9 insns. I tried it: you need two
-+ registers (say %g1,%g5) and it takes about 6 insns. A better fix would be
-+ to tell cse that CCFPE mode registers (even pseudos) are call
-+ clobbered. */
-+
-+ /* ??? This is an experiment. Rather than making changes to cse which may
-+ or may not be easy/clean, we do our own cse. This is possible because
-+ we will generate hard registers. Cse knows they're call clobbered (it
-+ doesn't know the same thing about pseudos). If we guess wrong, no big
-+ deal, but if we win, great! */
-+
-+ if (TARGET_V9 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
-+#if 1 /* experiment */
-+ {
-+ int reg;
-+ /* We cycle through the registers to ensure they're all exercised. */
-+ static int next_fcc_reg = 0;
-+ /* Previous x,y for each fcc reg. */
-+ static rtx prev_args[4][2];
-+
-+ /* Scan prev_args for x,y. */
-+ for (reg = 0; reg < 4; reg++)
-+ if (prev_args[reg][0] == x && prev_args[reg][1] == y)
-+ break;
-+ if (reg == 4)
-+ {
-+ reg = next_fcc_reg;
-+ prev_args[reg][0] = x;
-+ prev_args[reg][1] = y;
-+ next_fcc_reg = (next_fcc_reg + 1) & 3;
-+ }
-+ cc_reg = gen_rtx_REG (mode, reg + SPARC_FIRST_V9_FCC_REG);
-+ }
-+#else
-+ cc_reg = gen_reg_rtx (mode);
-+#endif /* ! experiment */
-+ else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
-+ cc_reg = gen_rtx_REG (mode, SPARC_FCC_REG);
-+ else
-+ cc_reg = gen_rtx_REG (mode, SPARC_ICC_REG);
-+
-+ /* We shouldn't get there for TFmode if !TARGET_HARD_QUAD. If we do, this
-+ will only result in an unrecognizable insn so no point in asserting. */
-+ emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (mode, x, y)));
-+
-+ return cc_reg;
-+}
-+
-+
-+/* Emit the compare insn and return the CC reg for the comparison in CMP. */
-+
-+rtx
-+gen_compare_reg (rtx cmp)
-+{
-+ return gen_compare_reg_1 (GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1));
-+}
-+
-+/* This function is used for v9 only.
-+ DEST is the target of the Scc insn.
-+ CODE is the code for an Scc's comparison.
-+ X and Y are the values we compare.
-+
-+ This function is needed to turn
-+
-+ (set (reg:SI 110)
-+ (gt (reg:CCX 100 %icc)
-+ (const_int 0)))
-+ into
-+ (set (reg:SI 110)
-+ (gt:DI (reg:CCX 100 %icc)
-+ (const_int 0)))
-+
-+ IE: The instruction recognizer needs to see the mode of the comparison to
-+ find the right instruction. We could use "gt:DI" right in the
-+ define_expand, but leaving it out allows us to handle DI, SI, etc. */
-+
-+static int
-+gen_v9_scc (rtx dest, enum rtx_code compare_code, rtx x, rtx y)
-+{
-+ if (! TARGET_ARCH64
-+ && (GET_MODE (x) == DImode
-+ || GET_MODE (dest) == DImode))
-+ return 0;
-+
-+ /* Try to use the movrCC insns. */
-+ if (TARGET_ARCH64
-+ && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
-+ && y == const0_rtx
-+ && v9_regcmp_p (compare_code))
-+ {
-+ rtx op0 = x;
-+ rtx temp;
-+
-+ /* Special case for op0 != 0. This can be done with one instruction if
-+ dest == x. */
-+
-+ if (compare_code == NE
-+ && GET_MODE (dest) == DImode
-+ && rtx_equal_p (op0, dest))
-+ {
-+ emit_insn (gen_rtx_SET (dest,
-+ gen_rtx_IF_THEN_ELSE (DImode,
-+ gen_rtx_fmt_ee (compare_code, DImode,
-+ op0, const0_rtx),
-+ const1_rtx,
-+ dest)));
-+ return 1;
-+ }
-+
-+ if (reg_overlap_mentioned_p (dest, op0))
-+ {
-+ /* Handle the case where dest == x.
-+ We "early clobber" the result. */
-+ op0 = gen_reg_rtx (GET_MODE (x));
-+ emit_move_insn (op0, x);
-+ }
-+
-+ emit_insn (gen_rtx_SET (dest, const0_rtx));
-+ if (GET_MODE (op0) != DImode)
-+ {
-+ temp = gen_reg_rtx (DImode);
-+ convert_move (temp, op0, 0);
-+ }
-+ else
-+ temp = op0;
-+ emit_insn (gen_rtx_SET (dest,
-+ gen_rtx_IF_THEN_ELSE (GET_MODE (dest),
-+ gen_rtx_fmt_ee (compare_code, DImode,
-+ temp, const0_rtx),
-+ const1_rtx,
-+ dest)));
-+ return 1;
-+ }
-+ else
-+ {
-+ x = gen_compare_reg_1 (compare_code, x, y);
-+ y = const0_rtx;
-+
-+ emit_insn (gen_rtx_SET (dest, const0_rtx));
-+ emit_insn (gen_rtx_SET (dest,
-+ gen_rtx_IF_THEN_ELSE (GET_MODE (dest),
-+ gen_rtx_fmt_ee (compare_code,
-+ GET_MODE (x), x, y),
-+ const1_rtx, dest)));
-+ return 1;
-+ }
-+}
-+
-+
-+/* Emit an scc insn. For seq, sne, sgeu, and sltu, we can do this
-+ without jumps using the addx/subx instructions. */
-+
-+bool
-+emit_scc_insn (rtx operands[])
-+{
-+ rtx tem, x, y;
-+ enum rtx_code code;
-+ machine_mode mode;
-+
-+ /* The quad-word fp compare library routines all return nonzero to indicate
-+ true, which is different from the equivalent libgcc routines, so we must
-+ handle them specially here. */
-+ if (GET_MODE (operands[2]) == TFmode && ! TARGET_HARD_QUAD)
-+ {
-+ operands[1] = sparc_emit_float_lib_cmp (operands[2], operands[3],
-+ GET_CODE (operands[1]));
-+ operands[2] = XEXP (operands[1], 0);
-+ operands[3] = XEXP (operands[1], 1);
-+ }
-+
-+ code = GET_CODE (operands[1]);
-+ x = operands[2];
-+ y = operands[3];
-+ mode = GET_MODE (x);
-+
-+ /* For seq/sne on v9 we use the same code as v8 (the addx/subx method has
-+ more applications). The exception to this is "reg != 0" which can
-+ be done in one instruction on v9 (so we do it). */
-+ if ((code == EQ || code == NE) && (mode == SImode || mode == DImode))
-+ {
-+ if (y != const0_rtx)
-+ x = force_reg (mode, gen_rtx_XOR (mode, x, y));
-+
-+ rtx pat = gen_rtx_SET (operands[0],
-+ gen_rtx_fmt_ee (code, GET_MODE (operands[0]),
-+ x, const0_rtx));
-+
-+ /* If we can use addx/subx or addxc, add a clobber for CC. */
-+ if (mode == SImode || (code == NE && TARGET_VIS3))
-+ {
-+ rtx clobber
-+ = gen_rtx_CLOBBER (VOIDmode,
-+ gen_rtx_REG (mode == SImode ? CCmode : CCXmode,
-+ SPARC_ICC_REG));
-+ pat = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, pat, clobber));
-+ }
-+
-+ emit_insn (pat);
-+ return true;
-+ }
-+
-+ /* We can do LTU in DImode using the addxc instruction with VIS3. */
-+ if (TARGET_ARCH64
-+ && mode == DImode
-+ && !((code == LTU || code == GTU) && TARGET_VIS3)
-+ && gen_v9_scc (operands[0], code, x, y))
-+ return true;
-+
-+ /* We can do LTU and GEU using the addx/subx instructions too. And
-+ for GTU/LEU, if both operands are registers swap them and fall
-+ back to the easy case. */
-+ if (code == GTU || code == LEU)
-+ {
-+ if ((GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
-+ && (GET_CODE (y) == REG || GET_CODE (y) == SUBREG))
-+ {
-+ tem = x;
-+ x = y;
-+ y = tem;
-+ code = swap_condition (code);
-+ }
-+ }
-+
-+ if (code == LTU || code == GEU)
-+ {
-+ emit_insn (gen_rtx_SET (operands[0],
-+ gen_rtx_fmt_ee (code, GET_MODE (operands[0]),
-+ gen_compare_reg_1 (code, x, y),
-+ const0_rtx)));
-+ return true;
-+ }
-+
-+ /* All the posibilities to use addx/subx based sequences has been
-+ exhausted, try for a 3 instruction sequence using v9 conditional
-+ moves. */
-+ if (TARGET_V9 && gen_v9_scc (operands[0], code, x, y))
-+ return true;
-+
-+ /* Nope, do branches. */
-+ return false;
-+}
-+
-+/* Emit a conditional jump insn for the v9 architecture using comparison code
-+ CODE and jump target LABEL.
-+ This function exists to take advantage of the v9 brxx insns. */
-+
-+static void
-+emit_v9_brxx_insn (enum rtx_code code, rtx op0, rtx label)
-+{
-+ emit_jump_insn (gen_rtx_SET (pc_rtx,
-+ gen_rtx_IF_THEN_ELSE (VOIDmode,
-+ gen_rtx_fmt_ee (code, GET_MODE (op0),
-+ op0, const0_rtx),
-+ gen_rtx_LABEL_REF (VOIDmode, label),
-+ pc_rtx)));
-+}
-+
-+/* Emit a conditional jump insn for the UA2011 architecture using
-+ comparison code CODE and jump target LABEL. This function exists
-+ to take advantage of the UA2011 Compare and Branch insns. */
-+
-+static void
-+emit_cbcond_insn (enum rtx_code code, rtx op0, rtx op1, rtx label)
-+{
-+ rtx if_then_else;
-+
-+ if_then_else = gen_rtx_IF_THEN_ELSE (VOIDmode,
-+ gen_rtx_fmt_ee(code, GET_MODE(op0),
-+ op0, op1),
-+ gen_rtx_LABEL_REF (VOIDmode, label),
-+ pc_rtx);
-+
-+ emit_jump_insn (gen_rtx_SET (pc_rtx, if_then_else));
-+}
-+
-+void
-+emit_conditional_branch_insn (rtx operands[])
-+{
-+ /* The quad-word fp compare library routines all return nonzero to indicate
-+ true, which is different from the equivalent libgcc routines, so we must
-+ handle them specially here. */
-+ if (GET_MODE (operands[1]) == TFmode && ! TARGET_HARD_QUAD)
-+ {
-+ operands[0] = sparc_emit_float_lib_cmp (operands[1], operands[2],
-+ GET_CODE (operands[0]));
-+ operands[1] = XEXP (operands[0], 0);
-+ operands[2] = XEXP (operands[0], 1);
-+ }
-+
-+ /* If we can tell early on that the comparison is against a constant
-+ that won't fit in the 5-bit signed immediate field of a cbcond,
-+ use one of the other v9 conditional branch sequences. */
-+ if (TARGET_CBCOND
-+ && GET_CODE (operands[1]) == REG
-+ && (GET_MODE (operands[1]) == SImode
-+ || (TARGET_ARCH64 && GET_MODE (operands[1]) == DImode))
-+ && (GET_CODE (operands[2]) != CONST_INT
-+ || SPARC_SIMM5_P (INTVAL (operands[2]))))
-+ {
-+ emit_cbcond_insn (GET_CODE (operands[0]), operands[1], operands[2], operands[3]);
-+ return;
-+ }
-+
-+ if (TARGET_ARCH64 && operands[2] == const0_rtx
-+ && GET_CODE (operands[1]) == REG
-+ && GET_MODE (operands[1]) == DImode)
-+ {
-+ emit_v9_brxx_insn (GET_CODE (operands[0]), operands[1], operands[3]);
-+ return;
-+ }
-+
-+ operands[1] = gen_compare_reg (operands[0]);
-+ operands[2] = const0_rtx;
-+ operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]), VOIDmode,
-+ operands[1], operands[2]);
-+ emit_jump_insn (gen_cbranchcc4 (operands[0], operands[1], operands[2],
-+ operands[3]));
-+}
-+
-+
-+/* Generate a DFmode part of a hard TFmode register.
-+ REG is the TFmode hard register, LOW is 1 for the
-+ low 64bit of the register and 0 otherwise.
-+ */
-+rtx
-+gen_df_reg (rtx reg, int low)
-+{
-+ int regno = REGNO (reg);
-+
-+ if ((WORDS_BIG_ENDIAN == 0) ^ (low != 0))
-+ regno += (TARGET_ARCH64 && SPARC_INT_REG_P (regno)) ? 1 : 2;
-+ return gen_rtx_REG (DFmode, regno);
-+}
-+
-+/* Generate a call to FUNC with OPERANDS. Operand 0 is the return value.
-+ Unlike normal calls, TFmode operands are passed by reference. It is
-+ assumed that no more than 3 operands are required. */
-+
-+static void
-+emit_soft_tfmode_libcall (const char *func_name, int nargs, rtx *operands)
-+{
-+ rtx ret_slot = NULL, arg[3], func_sym;
-+ int i;
-+
-+ /* We only expect to be called for conversions, unary, and binary ops. */
-+ gcc_assert (nargs == 2 || nargs == 3);
-+
-+ for (i = 0; i < nargs; ++i)
-+ {
-+ rtx this_arg = operands[i];
-+ rtx this_slot;
-+
-+ /* TFmode arguments and return values are passed by reference. */
-+ if (GET_MODE (this_arg) == TFmode)
-+ {
-+ int force_stack_temp;
-+
-+ force_stack_temp = 0;
-+ if (TARGET_BUGGY_QP_LIB && i == 0)
-+ force_stack_temp = 1;
-+
-+ if (GET_CODE (this_arg) == MEM
-+ && ! force_stack_temp)
-+ {
-+ tree expr = MEM_EXPR (this_arg);
-+ if (expr)
-+ mark_addressable (expr);
-+ this_arg = XEXP (this_arg, 0);
-+ }
-+ else if (CONSTANT_P (this_arg)
-+ && ! force_stack_temp)
-+ {
-+ this_slot = force_const_mem (TFmode, this_arg);
-+ this_arg = XEXP (this_slot, 0);
-+ }
-+ else
-+ {
-+ this_slot = assign_stack_temp (TFmode, GET_MODE_SIZE (TFmode));
-+
-+ /* Operand 0 is the return value. We'll copy it out later. */
-+ if (i > 0)
-+ emit_move_insn (this_slot, this_arg);
-+ else
-+ ret_slot = this_slot;
-+
-+ this_arg = XEXP (this_slot, 0);
-+ }
-+ }
-+
-+ arg[i] = this_arg;
-+ }
-+
-+ func_sym = gen_rtx_SYMBOL_REF (Pmode, func_name);
-+
-+ if (GET_MODE (operands[0]) == TFmode)
-+ {
-+ if (nargs == 2)
-+ emit_library_call (func_sym, LCT_NORMAL, VOIDmode,
-+ arg[0], GET_MODE (arg[0]),
-+ arg[1], GET_MODE (arg[1]));
-+ else
-+ emit_library_call (func_sym, LCT_NORMAL, VOIDmode,
-+ arg[0], GET_MODE (arg[0]),
-+ arg[1], GET_MODE (arg[1]),
-+ arg[2], GET_MODE (arg[2]));
-+
-+ if (ret_slot)
-+ emit_move_insn (operands[0], ret_slot);
-+ }
-+ else
-+ {
-+ rtx ret;
-+
-+ gcc_assert (nargs == 2);
-+
-+ ret = emit_library_call_value (func_sym, operands[0], LCT_NORMAL,
-+ GET_MODE (operands[0]),
-+ arg[1], GET_MODE (arg[1]));
-+
-+ if (ret != operands[0])
-+ emit_move_insn (operands[0], ret);
-+ }
-+}
-+
-+/* Expand soft-float TFmode calls to sparc abi routines. */
-+
-+static void
-+emit_soft_tfmode_binop (enum rtx_code code, rtx *operands)
-+{
-+ const char *func;
-+
-+ switch (code)
-+ {
-+ case PLUS:
-+ func = "_Qp_add";
-+ break;
-+ case MINUS:
-+ func = "_Qp_sub";
-+ break;
-+ case MULT:
-+ func = "_Qp_mul";
-+ break;
-+ case DIV:
-+ func = "_Qp_div";
-+ break;
-+ default:
-+ gcc_unreachable ();
-+ }
-+
-+ emit_soft_tfmode_libcall (func, 3, operands);
-+}
-+
-+static void
-+emit_soft_tfmode_unop (enum rtx_code code, rtx *operands)
-+{
-+ const char *func;
-+
-+ gcc_assert (code == SQRT);
-+ func = "_Qp_sqrt";
-+
-+ emit_soft_tfmode_libcall (func, 2, operands);
-+}
-+
-+static void
-+emit_soft_tfmode_cvt (enum rtx_code code, rtx *operands)
-+{
-+ const char *func;
-+
-+ switch (code)
-+ {
-+ case FLOAT_EXTEND:
-+ switch (GET_MODE (operands[1]))
-+ {
-+ case E_SFmode:
-+ func = "_Qp_stoq";
-+ break;
-+ case E_DFmode:
-+ func = "_Qp_dtoq";
-+ break;
-+ default:
-+ gcc_unreachable ();
-+ }
-+ break;
-+
-+ case FLOAT_TRUNCATE:
-+ switch (GET_MODE (operands[0]))
-+ {
-+ case E_SFmode:
-+ func = "_Qp_qtos";
-+ break;
-+ case E_DFmode:
-+ func = "_Qp_qtod";
-+ break;
-+ default:
-+ gcc_unreachable ();
-+ }
-+ break;
-+
-+ case FLOAT:
-+ switch (GET_MODE (operands[1]))
-+ {
-+ case E_SImode:
-+ func = "_Qp_itoq";
-+ if (TARGET_ARCH64)
-+ operands[1] = gen_rtx_SIGN_EXTEND (DImode, operands[1]);
-+ break;
-+ case E_DImode:
-+ func = "_Qp_xtoq";
-+ break;
-+ default:
-+ gcc_unreachable ();
-+ }
-+ break;
-+
-+ case UNSIGNED_FLOAT:
-+ switch (GET_MODE (operands[1]))
-+ {
-+ case E_SImode:
-+ func = "_Qp_uitoq";
-+ if (TARGET_ARCH64)
-+ operands[1] = gen_rtx_ZERO_EXTEND (DImode, operands[1]);
-+ break;
-+ case E_DImode:
-+ func = "_Qp_uxtoq";
-+ break;
-+ default:
-+ gcc_unreachable ();
-+ }
-+ break;
-+
-+ case FIX:
-+ switch (GET_MODE (operands[0]))
-+ {
-+ case E_SImode:
-+ func = "_Qp_qtoi";
-+ break;
-+ case E_DImode:
-+ func = "_Qp_qtox";
-+ break;
-+ default:
-+ gcc_unreachable ();
-+ }
-+ break;
-+
-+ case UNSIGNED_FIX:
-+ switch (GET_MODE (operands[0]))
-+ {
-+ case E_SImode:
-+ func = "_Qp_qtoui";
-+ break;
-+ case E_DImode:
-+ func = "_Qp_qtoux";
-+ break;
-+ default:
-+ gcc_unreachable ();
-+ }
-+ break;
-+
-+ default:
-+ gcc_unreachable ();
-+ }
-+
-+ emit_soft_tfmode_libcall (func, 2, operands);
-+}
-+
-+/* Expand a hard-float tfmode operation. All arguments must be in
-+ registers. */
-+
-+static void
-+emit_hard_tfmode_operation (enum rtx_code code, rtx *operands)
-+{
-+ rtx op, dest;
-+
-+ if (GET_RTX_CLASS (code) == RTX_UNARY)
-+ {
-+ operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
-+ op = gen_rtx_fmt_e (code, GET_MODE (operands[0]), operands[1]);
-+ }
-+ else
-+ {
-+ operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
-+ operands[2] = force_reg (GET_MODE (operands[2]), operands[2]);
-+ op = gen_rtx_fmt_ee (code, GET_MODE (operands[0]),
-+ operands[1], operands[2]);
-+ }
-+
-+ if (register_operand (operands[0], VOIDmode))
-+ dest = operands[0];
-+ else
-+ dest = gen_reg_rtx (GET_MODE (operands[0]));
-+
-+ emit_insn (gen_rtx_SET (dest, op));
-+
-+ if (dest != operands[0])
-+ emit_move_insn (operands[0], dest);
-+}
-+
-+void
-+emit_tfmode_binop (enum rtx_code code, rtx *operands)
-+{
-+ if (TARGET_HARD_QUAD)
-+ emit_hard_tfmode_operation (code, operands);
-+ else
-+ emit_soft_tfmode_binop (code, operands);
-+}
-+
-+void
-+emit_tfmode_unop (enum rtx_code code, rtx *operands)
-+{
-+ if (TARGET_HARD_QUAD)
-+ emit_hard_tfmode_operation (code, operands);
-+ else
-+ emit_soft_tfmode_unop (code, operands);
-+}
-+
-+void
-+emit_tfmode_cvt (enum rtx_code code, rtx *operands)
-+{
-+ if (TARGET_HARD_QUAD)
-+ emit_hard_tfmode_operation (code, operands);
-+ else
-+ emit_soft_tfmode_cvt (code, operands);
-+}
-+
-+/* Return nonzero if a branch/jump/call instruction will be emitting
-+ nop into its delay slot. */
-+
-+int
-+empty_delay_slot (rtx_insn *insn)
-+{
-+ rtx seq;
-+
-+ /* If no previous instruction (should not happen), return true. */
-+ if (PREV_INSN (insn) == NULL)
-+ return 1;
-+
-+ seq = NEXT_INSN (PREV_INSN (insn));
-+ if (GET_CODE (PATTERN (seq)) == SEQUENCE)
-+ return 0;
-+
-+ return 1;
-+}
-+
-+/* Return nonzero if we should emit a nop after a cbcond instruction.
-+ The cbcond instruction does not have a delay slot, however there is
-+ a severe performance penalty if a control transfer appears right
-+ after a cbcond. Therefore we emit a nop when we detect this
-+ situation. */
-+
-+int
-+emit_cbcond_nop (rtx_insn *insn)
-+{
-+ rtx next = next_active_insn (insn);
-+
-+ if (!next)
-+ return 1;
-+
-+ if (NONJUMP_INSN_P (next)
-+ && GET_CODE (PATTERN (next)) == SEQUENCE)
-+ next = XVECEXP (PATTERN (next), 0, 0);
-+ else if (CALL_P (next)
-+ && GET_CODE (PATTERN (next)) == PARALLEL)
-+ {
-+ rtx delay = XVECEXP (PATTERN (next), 0, 1);
-+
-+ if (GET_CODE (delay) == RETURN)
-+ {
-+ /* It's a sibling call. Do not emit the nop if we're going
-+ to emit something other than the jump itself as the first
-+ instruction of the sibcall sequence. */
-+ if (sparc_leaf_function_p || TARGET_FLAT)
-+ return 0;
-+ }
-+ }
-+
-+ if (NONJUMP_INSN_P (next))
-+ return 0;
-+
-+ return 1;
-+}
-+
-+/* Return nonzero if TRIAL, an insn, can be combined with a 'restore'
-+ instruction. RETURN_P is true if the v9 variant 'return' is to be
-+ considered in the test too.
-+
-+ TRIAL must be a SET whose destination is a REG appropriate for the
-+ 'restore' instruction or, if RETURN_P is true, for the 'return'
-+ instruction. */
-+
-+static int
-+eligible_for_restore_insn (rtx trial, bool return_p)
-+{
-+ rtx pat = PATTERN (trial);
-+ rtx src = SET_SRC (pat);
-+ bool src_is_freg = false;
-+ rtx src_reg;
-+
-+ /* Since we now can do moves between float and integer registers when
-+ VIS3 is enabled, we have to catch this case. We can allow such
-+ moves when doing a 'return' however. */
-+ src_reg = src;
-+ if (GET_CODE (src_reg) == SUBREG)
-+ src_reg = SUBREG_REG (src_reg);
-+ if (GET_CODE (src_reg) == REG
-+ && SPARC_FP_REG_P (REGNO (src_reg)))
-+ src_is_freg = true;
-+
-+ /* The 'restore src,%g0,dest' pattern for word mode and below. */
-+ if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
-+ && arith_operand (src, GET_MODE (src))
-+ && ! src_is_freg)
-+ {
-+ if (TARGET_ARCH64)
-+ return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
-+ else
-+ return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
-+ }
-+
-+ /* The 'restore src,%g0,dest' pattern for double-word mode. */
-+ else if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
-+ && arith_double_operand (src, GET_MODE (src))
-+ && ! src_is_freg)
-+ return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
-+
-+ /* The 'restore src,%g0,dest' pattern for float if no FPU. */
-+ else if (! TARGET_FPU && register_operand (src, SFmode))
-+ return 1;
-+
-+ /* The 'restore src,%g0,dest' pattern for double if no FPU. */
-+ else if (! TARGET_FPU && TARGET_ARCH64 && register_operand (src, DFmode))
-+ return 1;
-+
-+ /* If we have the 'return' instruction, anything that does not use
-+ local or output registers and can go into a delay slot wins. */
-+ else if (return_p && TARGET_V9 && !epilogue_renumber (&pat, 1))
-+ return 1;
-+
-+ /* The 'restore src1,src2,dest' pattern for SImode. */
-+ else if (GET_CODE (src) == PLUS
-+ && register_operand (XEXP (src, 0), SImode)
-+ && arith_operand (XEXP (src, 1), SImode))
-+ return 1;
-+
-+ /* The 'restore src1,src2,dest' pattern for DImode. */
-+ else if (GET_CODE (src) == PLUS
-+ && register_operand (XEXP (src, 0), DImode)
-+ && arith_double_operand (XEXP (src, 1), DImode))
-+ return 1;
-+
-+ /* The 'restore src1,%lo(src2),dest' pattern. */
-+ else if (GET_CODE (src) == LO_SUM
-+ && ! TARGET_CM_MEDMID
-+ && ((register_operand (XEXP (src, 0), SImode)
-+ && immediate_operand (XEXP (src, 1), SImode))
-+ || (TARGET_ARCH64
-+ && register_operand (XEXP (src, 0), DImode)
-+ && immediate_operand (XEXP (src, 1), DImode))))
-+ return 1;
-+
-+ /* The 'restore src,src,dest' pattern. */
-+ else if (GET_CODE (src) == ASHIFT
-+ && (register_operand (XEXP (src, 0), SImode)
-+ || register_operand (XEXP (src, 0), DImode))
-+ && XEXP (src, 1) == const1_rtx)
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/* Return nonzero if TRIAL can go into the function return's delay slot. */
-+
-+int
-+eligible_for_return_delay (rtx_insn *trial)
-+{
-+ int regno;
-+ rtx pat;
-+
-+ /* If the function uses __builtin_eh_return, the eh_return machinery
-+ occupies the delay slot. */
-+ if (crtl->calls_eh_return)
-+ return 0;
-+
-+ if (get_attr_in_branch_delay (trial) == IN_BRANCH_DELAY_FALSE)
-+ return 0;
-+
-+ /* In the case of a leaf or flat function, anything can go into the slot. */
-+ if (sparc_leaf_function_p || TARGET_FLAT)
-+ return 1;
-+
-+ if (!NONJUMP_INSN_P (trial))
-+ return 0;
-+
-+ pat = PATTERN (trial);
-+ if (GET_CODE (pat) == PARALLEL)
-+ {
-+ int i;
-+
-+ if (! TARGET_V9)
-+ return 0;
-+ for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)
-+ {
-+ rtx expr = XVECEXP (pat, 0, i);
-+ if (GET_CODE (expr) != SET)
-+ return 0;
-+ if (GET_CODE (SET_DEST (expr)) != REG)
-+ return 0;
-+ regno = REGNO (SET_DEST (expr));
-+ if (regno >= 8 && regno < 24)
-+ return 0;
-+ }
-+ return !epilogue_renumber (&pat, 1);
-+ }
-+
-+ if (GET_CODE (pat) != SET)
-+ return 0;
-+
-+ if (GET_CODE (SET_DEST (pat)) != REG)
-+ return 0;
-+
-+ regno = REGNO (SET_DEST (pat));
-+
-+ /* Otherwise, only operations which can be done in tandem with
-+ a `restore' or `return' insn can go into the delay slot. */
-+ if (regno >= 8 && regno < 24)
-+ return 0;
-+
-+ /* If this instruction sets up floating point register and we have a return
-+ instruction, it can probably go in. But restore will not work
-+ with FP_REGS. */
-+ if (! SPARC_INT_REG_P (regno))
-+ return TARGET_V9 && !epilogue_renumber (&pat, 1);
-+
-+ return eligible_for_restore_insn (trial, true);
-+}
-+
-+/* Return nonzero if TRIAL can go into the sibling call's delay slot. */
-+
-+int
-+eligible_for_sibcall_delay (rtx_insn *trial)
-+{
-+ rtx pat;
-+
-+ if (get_attr_in_branch_delay (trial) == IN_BRANCH_DELAY_FALSE)
-+ return 0;
-+
-+ if (!NONJUMP_INSN_P (trial))
-+ return 0;
-+
-+ pat = PATTERN (trial);
-+
-+ if (sparc_leaf_function_p || TARGET_FLAT)
-+ {
-+ /* If the tail call is done using the call instruction,
-+ we have to restore %o7 in the delay slot. */
-+ if (LEAF_SIBCALL_SLOT_RESERVED_P)
-+ return 0;
-+
-+ /* %g1 is used to build the function address */
-+ if (reg_mentioned_p (gen_rtx_REG (Pmode, 1), pat))
-+ return 0;
-+
-+ return 1;
-+ }
-+
-+ if (GET_CODE (pat) != SET)
-+ return 0;
-+
-+ /* Otherwise, only operations which can be done in tandem with
-+ a `restore' insn can go into the delay slot. */
-+ if (GET_CODE (SET_DEST (pat)) != REG
-+ || (REGNO (SET_DEST (pat)) >= 8 && REGNO (SET_DEST (pat)) < 24)
-+ || ! SPARC_INT_REG_P (REGNO (SET_DEST (pat))))
-+ return 0;
-+
-+ /* If it mentions %o7, it can't go in, because sibcall will clobber it
-+ in most cases. */
-+ if (reg_mentioned_p (gen_rtx_REG (Pmode, 15), pat))
-+ return 0;
-+
-+ return eligible_for_restore_insn (trial, false);
-+}
-+
-+/* Determine if it's legal to put X into the constant pool. This
-+ is not possible if X contains the address of a symbol that is
-+ not constant (TLS) or not known at final link time (PIC). */
-+
-+static bool
-+sparc_cannot_force_const_mem (machine_mode mode, rtx x)
-+{
-+ switch (GET_CODE (x))
-+ {
-+ case CONST_INT:
-+ case CONST_WIDE_INT:
-+ case CONST_DOUBLE:
-+ case CONST_VECTOR:
-+ /* Accept all non-symbolic constants. */
-+ return false;
-+
-+ case LABEL_REF:
-+ /* Labels are OK iff we are non-PIC. */
-+ return flag_pic != 0;
-+
-+ case SYMBOL_REF:
-+ /* 'Naked' TLS symbol references are never OK,
-+ non-TLS symbols are OK iff we are non-PIC. */
-+ if (SYMBOL_REF_TLS_MODEL (x))
-+ return true;
-+ else
-+ return flag_pic != 0;
-+
-+ case CONST:
-+ return sparc_cannot_force_const_mem (mode, XEXP (x, 0));
-+ case PLUS:
-+ case MINUS:
-+ return sparc_cannot_force_const_mem (mode, XEXP (x, 0))
-+ || sparc_cannot_force_const_mem (mode, XEXP (x, 1));
-+ case UNSPEC:
-+ return true;
-+ default:
-+ gcc_unreachable ();
-+ }
-+}
-+
-+/* Global Offset Table support. */
-+static GTY(()) rtx got_symbol_rtx = NULL_RTX;
-+static GTY(()) rtx got_register_rtx = NULL_RTX;
-+static GTY(()) rtx got_helper_rtx = NULL_RTX;
-+
-+static GTY(()) bool got_helper_needed = false;
-+
-+/* Return the SYMBOL_REF for the Global Offset Table. */
-+
-+static rtx
-+sparc_got (void)
-+{
-+ if (!got_symbol_rtx)
-+ got_symbol_rtx = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
-+
-+ return got_symbol_rtx;
-+}
-+
-+/* Wrapper around the load_pcrel_sym{si,di} patterns. */
-+
-+static rtx
-+gen_load_pcrel_sym (rtx op0, rtx op1, rtx op2)
-+{
-+ int orig_flag_pic = flag_pic;
-+ rtx insn;
-+
-+ /* The load_pcrel_sym{si,di} patterns require absolute addressing. */
-+ flag_pic = 0;
-+ if (TARGET_ARCH64)
-+ insn = gen_load_pcrel_symdi (op0, op1, op2, GEN_INT (REGNO (op0)));
-+ else
-+ insn = gen_load_pcrel_symsi (op0, op1, op2, GEN_INT (REGNO (op0)));
-+ flag_pic = orig_flag_pic;
-+
-+ return insn;
-+}
-+
-+/* Output the load_pcrel_sym{si,di} patterns. */
-+
-+const char *
-+output_load_pcrel_sym (rtx *operands)
-+{
-+ if (flag_delayed_branch)
-+ {
-+ output_asm_insn ("sethi\t%%hi(%a1-4), %0", operands);
-+ output_asm_insn ("call\t%a2", operands);
-+ output_asm_insn (" add\t%0, %%lo(%a1+4), %0", operands);
-+ }
-+ else
-+ {
-+ output_asm_insn ("sethi\t%%hi(%a1-8), %0", operands);
-+ output_asm_insn ("add\t%0, %%lo(%a1-4), %0", operands);
-+ output_asm_insn ("call\t%a2", operands);
-+ output_asm_insn (" nop", NULL);
-+ }
-+
-+ if (operands[2] == got_helper_rtx)
-+ got_helper_needed = true;
-+
-+ return "";
-+}
-+
-+#ifdef HAVE_GAS_HIDDEN
-+# define USE_HIDDEN_LINKONCE 1
-+#else
-+# define USE_HIDDEN_LINKONCE 0
-+#endif
-+
-+/* Emit code to load the GOT register. */
-+
-+void
-+load_got_register (void)
-+{
-+ rtx insn;
-+
-+ if (TARGET_VXWORKS_RTP)
-+ {
-+ if (!got_register_rtx)
-+ got_register_rtx = pic_offset_table_rtx;
-+
-+ insn = gen_vxworks_load_got ();
-+ }
-+ else
-+ {
-+ if (!got_register_rtx)
-+ got_register_rtx = gen_rtx_REG (Pmode, GLOBAL_OFFSET_TABLE_REGNUM);
-+
-+ /* The GOT symbol is subject to a PC-relative relocation so we need a
-+ helper function to add the PC value and thus get the final value. */
-+ if (!got_helper_rtx)
-+ {
-+ char name[32];
-+
-+ /* Skip the leading '%' as that cannot be used in a symbol name. */
-+ if (USE_HIDDEN_LINKONCE)
-+ sprintf (name, "__sparc_get_pc_thunk.%s",
-+ reg_names[REGNO (got_register_rtx)] + 1);
-+ else
-+ ASM_GENERATE_INTERNAL_LABEL (name, "LADDPC",
-+ REGNO (got_register_rtx));
-+
-+ got_helper_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
-+ }
-+
-+ insn
-+ = gen_load_pcrel_sym (got_register_rtx, sparc_got (), got_helper_rtx);
-+ }
-+
-+ emit_insn (insn);
-+}
-+
-+/* Ensure that we are not using patterns that are not OK with PIC. */
-+
-+int
-+check_pic (int i)
-+{
-+ rtx op;
-+
-+ switch (flag_pic)
-+ {
-+ case 1:
-+ op = recog_data.operand[i];
-+ gcc_assert (GET_CODE (op) != SYMBOL_REF
-+ && (GET_CODE (op) != CONST
-+ || (GET_CODE (XEXP (op, 0)) == MINUS
-+ && XEXP (XEXP (op, 0), 0) == sparc_got ()
-+ && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST)));
-+ /* fallthrough */
-+ case 2:
-+ default:
-+ return 1;
-+ }
-+}
-+
-+/* Return true if X is an address which needs a temporary register when
-+ reloaded while generating PIC code. */
-+
-+int
-+pic_address_needs_scratch (rtx x)
-+{
-+ /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
-+ if (GET_CODE (x) == CONST
-+ && GET_CODE (XEXP (x, 0)) == PLUS
-+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
-+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
-+ && !SMALL_INT (XEXP (XEXP (x, 0), 1)))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/* Determine if a given RTX is a valid constant. We already know this
-+ satisfies CONSTANT_P. */
-+
-+static bool
-+sparc_legitimate_constant_p (machine_mode mode, rtx x)
-+{
-+ switch (GET_CODE (x))
-+ {
-+ case CONST:
-+ case SYMBOL_REF:
-+ if (sparc_tls_referenced_p (x))
-+ return false;
-+ break;
-+
-+ case CONST_DOUBLE:
-+ /* Floating point constants are generally not ok.
-+ The only exception is 0.0 and all-ones in VIS. */
-+ if (TARGET_VIS
-+ && SCALAR_FLOAT_MODE_P (mode)
-+ && (const_zero_operand (x, mode)
-+ || const_all_ones_operand (x, mode)))
-+ return true;
-+
-+ return false;
-+
-+ case CONST_VECTOR:
-+ /* Vector constants are generally not ok.
-+ The only exception is 0 or -1 in VIS. */
-+ if (TARGET_VIS
-+ && (const_zero_operand (x, mode)
-+ || const_all_ones_operand (x, mode)))
-+ return true;
-+
-+ return false;
-+
-+ default:
-+ break;
-+ }
-+
-+ return true;
-+}
-+
-+/* Determine if a given RTX is a valid constant address. */
-+
-+bool
-+constant_address_p (rtx x)
-+{
-+ switch (GET_CODE (x))
-+ {
-+ case LABEL_REF:
-+ case CONST_INT:
-+ case HIGH:
-+ return true;
-+
-+ case CONST:
-+ if (flag_pic && pic_address_needs_scratch (x))
-+ return false;
-+ return sparc_legitimate_constant_p (Pmode, x);
-+
-+ case SYMBOL_REF:
-+ return !flag_pic && sparc_legitimate_constant_p (Pmode, x);
-+
-+ default:
-+ return false;
-+ }
-+}
-+
-+/* Nonzero if the constant value X is a legitimate general operand
-+ when generating PIC code. It is given that flag_pic is on and
-+ that X satisfies CONSTANT_P. */
-+
-+bool
-+legitimate_pic_operand_p (rtx x)
-+{
-+ if (pic_address_needs_scratch (x))
-+ return false;
-+ if (sparc_tls_referenced_p (x))
-+ return false;
-+ return true;
-+}
-+
-+/* Return true if X is a representation of the PIC register. */
-+
-+static bool
-+sparc_pic_register_p (rtx x)
-+{
-+ if (!REG_P (x) || !pic_offset_table_rtx)
-+ return false;
-+
-+ if (x == pic_offset_table_rtx)
-+ return true;
-+
-+ if (!HARD_REGISTER_P (pic_offset_table_rtx)
-+ && (HARD_REGISTER_P (x) || lra_in_progress || reload_in_progress)
-+ && ORIGINAL_REGNO (x) == REGNO (pic_offset_table_rtx))
-+ return true;
-+
-+ return false;
-+}
-+
-+#define RTX_OK_FOR_OFFSET_P(X, MODE) \
-+ (CONST_INT_P (X) \
-+ && INTVAL (X) >= -0x1000 \
-+ && INTVAL (X) <= (0x1000 - GET_MODE_SIZE (MODE)))
-+
-+#define RTX_OK_FOR_OLO10_P(X, MODE) \
-+ (CONST_INT_P (X) \
-+ && INTVAL (X) >= -0x1000 \
-+ && INTVAL (X) <= (0xc00 - GET_MODE_SIZE (MODE)))
-+
-+/* Handle the TARGET_LEGITIMATE_ADDRESS_P target hook.
-+
-+ On SPARC, the actual legitimate addresses must be REG+REG or REG+SMALLINT
-+ ordinarily. This changes a bit when generating PIC. */
-+
-+static bool
-+sparc_legitimate_address_p (machine_mode mode, rtx addr, bool strict)
-+{
-+ rtx rs1 = NULL, rs2 = NULL, imm1 = NULL;
-+
-+ if (REG_P (addr) || GET_CODE (addr) == SUBREG)
-+ rs1 = addr;
-+ else if (GET_CODE (addr) == PLUS)
-+ {
-+ rs1 = XEXP (addr, 0);
-+ rs2 = XEXP (addr, 1);
-+
-+ /* Canonicalize. REG comes first, if there are no regs,
-+ LO_SUM comes first. */
-+ if (!REG_P (rs1)
-+ && GET_CODE (rs1) != SUBREG
-+ && (REG_P (rs2)
-+ || GET_CODE (rs2) == SUBREG
-+ || (GET_CODE (rs2) == LO_SUM && GET_CODE (rs1) != LO_SUM)))
-+ {
-+ rs1 = XEXP (addr, 1);
-+ rs2 = XEXP (addr, 0);
-+ }
-+
-+ if ((flag_pic == 1
-+ && sparc_pic_register_p (rs1)
-+ && !REG_P (rs2)
-+ && GET_CODE (rs2) != SUBREG
-+ && GET_CODE (rs2) != LO_SUM
-+ && GET_CODE (rs2) != MEM
-+ && !(GET_CODE (rs2) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (rs2))
-+ && (! symbolic_operand (rs2, VOIDmode) || mode == Pmode)
-+ && (GET_CODE (rs2) != CONST_INT || SMALL_INT (rs2)))
-+ || ((REG_P (rs1)
-+ || GET_CODE (rs1) == SUBREG)
-+ && RTX_OK_FOR_OFFSET_P (rs2, mode)))
-+ {
-+ imm1 = rs2;
-+ rs2 = NULL;
-+ }
-+ else if ((REG_P (rs1) || GET_CODE (rs1) == SUBREG)
-+ && (REG_P (rs2) || GET_CODE (rs2) == SUBREG))
-+ {
-+ /* We prohibit REG + REG for TFmode when there are no quad move insns
-+ and we consequently need to split. We do this because REG+REG
-+ is not an offsettable address. If we get the situation in reload
-+ where source and destination of a movtf pattern are both MEMs with
-+ REG+REG address, then only one of them gets converted to an
-+ offsettable address. */
-+ if (mode == TFmode
-+ && ! (TARGET_ARCH64 && TARGET_HARD_QUAD))
-+ return 0;
-+
-+ /* Likewise for TImode, but in all cases. */
-+ if (mode == TImode)
-+ return 0;
-+
-+ /* We prohibit REG + REG on ARCH32 if not optimizing for
-+ DFmode/DImode because then mem_min_alignment is likely to be zero
-+ after reload and the forced split would lack a matching splitter
-+ pattern. */
-+ if (TARGET_ARCH32 && !optimize
-+ && (mode == DFmode || mode == DImode))
-+ return 0;
-+ }
-+ else if (USE_AS_OFFSETABLE_LO10
-+ && GET_CODE (rs1) == LO_SUM
-+ && TARGET_ARCH64
-+ && ! TARGET_CM_MEDMID
-+ && RTX_OK_FOR_OLO10_P (rs2, mode))
-+ {
-+ rs2 = NULL;
-+ imm1 = XEXP (rs1, 1);
-+ rs1 = XEXP (rs1, 0);
-+ if (!CONSTANT_P (imm1)
-+ || (GET_CODE (rs1) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (rs1)))
-+ return 0;
-+ }
-+ }
-+ else if (GET_CODE (addr) == LO_SUM)
-+ {
-+ rs1 = XEXP (addr, 0);
-+ imm1 = XEXP (addr, 1);
-+
-+ if (!CONSTANT_P (imm1)
-+ || (GET_CODE (rs1) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (rs1)))
-+ return 0;
-+
-+ /* We can't allow TFmode in 32-bit mode, because an offset greater
-+ than the alignment (8) may cause the LO_SUM to overflow. */
-+ if (mode == TFmode && TARGET_ARCH32)
-+ return 0;
-+
-+ /* During reload, accept the HIGH+LO_SUM construct generated by
-+ sparc_legitimize_reload_address. */
-+ if (reload_in_progress
-+ && GET_CODE (rs1) == HIGH
-+ && XEXP (rs1, 0) == imm1)
-+ return 1;
-+ }
-+ else if (GET_CODE (addr) == CONST_INT && SMALL_INT (addr))
-+ return 1;
-+ else
-+ return 0;
-+
-+ if (GET_CODE (rs1) == SUBREG)
-+ rs1 = SUBREG_REG (rs1);
-+ if (!REG_P (rs1))
-+ return 0;
-+
-+ if (rs2)
-+ {
-+ if (GET_CODE (rs2) == SUBREG)
-+ rs2 = SUBREG_REG (rs2);
-+ if (!REG_P (rs2))
-+ return 0;
-+ }
-+
-+ if (strict)
-+ {
-+ if (!REGNO_OK_FOR_BASE_P (REGNO (rs1))
-+ || (rs2 && !REGNO_OK_FOR_BASE_P (REGNO (rs2))))
-+ return 0;
-+ }
-+ else
-+ {
-+ if ((! SPARC_INT_REG_P (REGNO (rs1))
-+ && REGNO (rs1) != FRAME_POINTER_REGNUM
-+ && REGNO (rs1) < FIRST_PSEUDO_REGISTER)
-+ || (rs2
-+ && (! SPARC_INT_REG_P (REGNO (rs2))
-+ && REGNO (rs2) != FRAME_POINTER_REGNUM
-+ && REGNO (rs2) < FIRST_PSEUDO_REGISTER)))
-+ return 0;
-+ }
-+ return 1;
-+}
-+
-+/* Return the SYMBOL_REF for the tls_get_addr function. */
-+
-+static GTY(()) rtx sparc_tls_symbol = NULL_RTX;
-+
-+static rtx
-+sparc_tls_get_addr (void)
-+{
-+ if (!sparc_tls_symbol)
-+ sparc_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr");
-+
-+ return sparc_tls_symbol;
-+}
-+
-+/* Return the Global Offset Table to be used in TLS mode. */
-+
-+static rtx
-+sparc_tls_got (void)
-+{
-+ /* In PIC mode, this is just the PIC offset table. */
-+ if (flag_pic)
-+ {
-+ crtl->uses_pic_offset_table = 1;
-+ return pic_offset_table_rtx;
-+ }
-+
-+ /* In non-PIC mode, Sun as (unlike GNU as) emits PC-relative relocations for
-+ the GOT symbol with the 32-bit ABI, so we reload the GOT register. */
-+ if (TARGET_SUN_TLS && TARGET_ARCH32)
-+ {
-+ load_got_register ();
-+ return got_register_rtx;
-+ }
-+
-+ /* In all other cases, we load a new pseudo with the GOT symbol. */
-+ return copy_to_reg (sparc_got ());
-+}
-+
-+/* Return true if X contains a thread-local symbol. */
-+
-+static bool
-+sparc_tls_referenced_p (rtx x)
-+{
-+ if (!TARGET_HAVE_TLS)
-+ return false;
-+
-+ if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS)
-+ x = XEXP (XEXP (x, 0), 0);
-+
-+ if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x))
-+ return true;
-+
-+ /* That's all we handle in sparc_legitimize_tls_address for now. */
-+ return false;
-+}
-+
-+/* ADDR contains a thread-local SYMBOL_REF. Generate code to compute
-+ this (thread-local) address. */
-+
-+static rtx
-+sparc_legitimize_tls_address (rtx addr)
-+{
-+ rtx temp1, temp2, temp3, ret, o0, got;
-+ rtx_insn *insn;
-+
-+ gcc_assert (can_create_pseudo_p ());
-+
-+ if (GET_CODE (addr) == SYMBOL_REF)
-+ /* Although the various sethi/or sequences generate SImode values, many of
-+ them can be transformed by the linker when relaxing and, if relaxing to
-+ local-exec, will become a sethi/xor pair, which is signed and therefore
-+ a full DImode value in 64-bit mode. Thus we must use Pmode, lest these
-+ values be spilled onto the stack in 64-bit mode. */
-+ switch (SYMBOL_REF_TLS_MODEL (addr))
-+ {
-+ case TLS_MODEL_GLOBAL_DYNAMIC:
-+ start_sequence ();
-+ temp1 = gen_reg_rtx (Pmode);
-+ temp2 = gen_reg_rtx (Pmode);
-+ ret = gen_reg_rtx (Pmode);
-+ o0 = gen_rtx_REG (Pmode, 8);
-+ got = sparc_tls_got ();
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_tgd_hi22si (temp1, addr));
-+ emit_insn (gen_tgd_lo10si (temp2, temp1, addr));
-+ emit_insn (gen_tgd_addsi (o0, got, temp2, addr));
-+ insn = emit_call_insn (gen_tgd_callsi (o0, sparc_tls_get_addr (),
-+ addr, const1_rtx));
-+ }
-+ else
-+ {
-+ emit_insn (gen_tgd_hi22di (temp1, addr));
-+ emit_insn (gen_tgd_lo10di (temp2, temp1, addr));
-+ emit_insn (gen_tgd_adddi (o0, got, temp2, addr));
-+ insn = emit_call_insn (gen_tgd_calldi (o0, sparc_tls_get_addr (),
-+ addr, const1_rtx));
-+ }
-+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), o0);
-+ RTL_CONST_CALL_P (insn) = 1;
-+ insn = get_insns ();
-+ end_sequence ();
-+ emit_libcall_block (insn, ret, o0, addr);
-+ break;
-+
-+ case TLS_MODEL_LOCAL_DYNAMIC:
-+ start_sequence ();
-+ temp1 = gen_reg_rtx (Pmode);
-+ temp2 = gen_reg_rtx (Pmode);
-+ temp3 = gen_reg_rtx (Pmode);
-+ ret = gen_reg_rtx (Pmode);
-+ o0 = gen_rtx_REG (Pmode, 8);
-+ got = sparc_tls_got ();
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_tldm_hi22si (temp1));
-+ emit_insn (gen_tldm_lo10si (temp2, temp1));
-+ emit_insn (gen_tldm_addsi (o0, got, temp2));
-+ insn = emit_call_insn (gen_tldm_callsi (o0, sparc_tls_get_addr (),
-+ const1_rtx));
-+ }
-+ else
-+ {
-+ emit_insn (gen_tldm_hi22di (temp1));
-+ emit_insn (gen_tldm_lo10di (temp2, temp1));
-+ emit_insn (gen_tldm_adddi (o0, got, temp2));
-+ insn = emit_call_insn (gen_tldm_calldi (o0, sparc_tls_get_addr (),
-+ const1_rtx));
-+ }
-+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), o0);
-+ RTL_CONST_CALL_P (insn) = 1;
-+ insn = get_insns ();
-+ end_sequence ();
-+ /* Attach a unique REG_EQUAL, to allow the RTL optimizers to
-+ share the LD_BASE result with other LD model accesses. */
-+ emit_libcall_block (insn, temp3, o0,
-+ gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
-+ UNSPEC_TLSLD_BASE));
-+ temp1 = gen_reg_rtx (Pmode);
-+ temp2 = gen_reg_rtx (Pmode);
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_tldo_hix22si (temp1, addr));
-+ emit_insn (gen_tldo_lox10si (temp2, temp1, addr));
-+ emit_insn (gen_tldo_addsi (ret, temp3, temp2, addr));
-+ }
-+ else
-+ {
-+ emit_insn (gen_tldo_hix22di (temp1, addr));
-+ emit_insn (gen_tldo_lox10di (temp2, temp1, addr));
-+ emit_insn (gen_tldo_adddi (ret, temp3, temp2, addr));
-+ }
-+ break;
-+
-+ case TLS_MODEL_INITIAL_EXEC:
-+ temp1 = gen_reg_rtx (Pmode);
-+ temp2 = gen_reg_rtx (Pmode);
-+ temp3 = gen_reg_rtx (Pmode);
-+ got = sparc_tls_got ();
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_tie_hi22si (temp1, addr));
-+ emit_insn (gen_tie_lo10si (temp2, temp1, addr));
-+ emit_insn (gen_tie_ld32 (temp3, got, temp2, addr));
-+ }
-+ else
-+ {
-+ emit_insn (gen_tie_hi22di (temp1, addr));
-+ emit_insn (gen_tie_lo10di (temp2, temp1, addr));
-+ emit_insn (gen_tie_ld64 (temp3, got, temp2, addr));
-+ }
-+ if (TARGET_SUN_TLS)
-+ {
-+ ret = gen_reg_rtx (Pmode);
-+ if (TARGET_ARCH32)
-+ emit_insn (gen_tie_addsi (ret, gen_rtx_REG (Pmode, 7),
-+ temp3, addr));
-+ else
-+ emit_insn (gen_tie_adddi (ret, gen_rtx_REG (Pmode, 7),
-+ temp3, addr));
-+ }
-+ else
-+ ret = gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, 7), temp3);
-+ break;
-+
-+ case TLS_MODEL_LOCAL_EXEC:
-+ temp1 = gen_reg_rtx (Pmode);
-+ temp2 = gen_reg_rtx (Pmode);
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_tle_hix22si (temp1, addr));
-+ emit_insn (gen_tle_lox10si (temp2, temp1, addr));
-+ }
-+ else
-+ {
-+ emit_insn (gen_tle_hix22di (temp1, addr));
-+ emit_insn (gen_tle_lox10di (temp2, temp1, addr));
-+ }
-+ ret = gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, 7), temp2);
-+ break;
-+
-+ default:
-+ gcc_unreachable ();
-+ }
-+
-+ else if (GET_CODE (addr) == CONST)
-+ {
-+ rtx base, offset;
-+
-+ gcc_assert (GET_CODE (XEXP (addr, 0)) == PLUS);
-+
-+ base = sparc_legitimize_tls_address (XEXP (XEXP (addr, 0), 0));
-+ offset = XEXP (XEXP (addr, 0), 1);
-+
-+ base = force_operand (base, NULL_RTX);
-+ if (!(GET_CODE (offset) == CONST_INT && SMALL_INT (offset)))
-+ offset = force_reg (Pmode, offset);
-+ ret = gen_rtx_PLUS (Pmode, base, offset);
-+ }
-+
-+ else
-+ gcc_unreachable (); /* for now ... */
-+
-+ return ret;
-+}
-+
-+/* Legitimize PIC addresses. If the address is already position-independent,
-+ we return ORIG. Newly generated position-independent addresses go into a
-+ reg. This is REG if nonzero, otherwise we allocate register(s) as
-+ necessary. */
-+
-+static rtx
-+sparc_legitimize_pic_address (rtx orig, rtx reg)
-+{
-+ if (GET_CODE (orig) == SYMBOL_REF
-+ /* See the comment in sparc_expand_move. */
-+ || (GET_CODE (orig) == LABEL_REF && !can_use_mov_pic_label_ref (orig)))
-+ {
-+ bool gotdata_op = false;
-+ rtx pic_ref, address;
-+ rtx_insn *insn;
-+
-+ if (!reg)
-+ {
-+ gcc_assert (can_create_pseudo_p ());
-+ reg = gen_reg_rtx (Pmode);
-+ }
-+
-+ if (flag_pic == 2)
-+ {
-+ /* If not during reload, allocate another temp reg here for loading
-+ in the address, so that these instructions can be optimized
-+ properly. */
-+ rtx temp_reg = can_create_pseudo_p () ? gen_reg_rtx (Pmode) : reg;
-+
-+ /* Must put the SYMBOL_REF inside an UNSPEC here so that cse
-+ won't get confused into thinking that these two instructions
-+ are loading in the true address of the symbol. If in the
-+ future a PIC rtx exists, that should be used instead. */
-+ if (TARGET_ARCH64)
-+ {
-+ emit_insn (gen_movdi_high_pic (temp_reg, orig));
-+ emit_insn (gen_movdi_lo_sum_pic (temp_reg, temp_reg, orig));
-+ }
-+ else
-+ {
-+ emit_insn (gen_movsi_high_pic (temp_reg, orig));
-+ emit_insn (gen_movsi_lo_sum_pic (temp_reg, temp_reg, orig));
-+ }
-+
-+ address = temp_reg;
-+ gotdata_op = true;
-+ }
-+ else
-+ address = orig;
-+
-+ crtl->uses_pic_offset_table = 1;
-+ if (gotdata_op)
-+ {
-+ if (TARGET_ARCH64)
-+ insn = emit_insn (gen_movdi_pic_gotdata_op (reg,
-+ pic_offset_table_rtx,
-+ address, orig));
-+ else
-+ insn = emit_insn (gen_movsi_pic_gotdata_op (reg,
-+ pic_offset_table_rtx,
-+ address, orig));
-+ }
-+ else
-+ {
-+ pic_ref
-+ = gen_const_mem (Pmode,
-+ gen_rtx_PLUS (Pmode,
-+ pic_offset_table_rtx, address));
-+ insn = emit_move_insn (reg, pic_ref);
-+ }
-+
-+ /* Put a REG_EQUAL note on this insn, so that it can be optimized
-+ by loop. */
-+ set_unique_reg_note (insn, REG_EQUAL, orig);
-+ return reg;
-+ }
-+ else if (GET_CODE (orig) == CONST)
-+ {
-+ rtx base, offset;
-+
-+ if (GET_CODE (XEXP (orig, 0)) == PLUS
-+ && sparc_pic_register_p (XEXP (XEXP (orig, 0), 0)))
-+ return orig;
-+
-+ if (!reg)
-+ {
-+ gcc_assert (can_create_pseudo_p ());
-+ reg = gen_reg_rtx (Pmode);
-+ }
-+
-+ gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
-+ base = sparc_legitimize_pic_address (XEXP (XEXP (orig, 0), 0), reg);
-+ offset = sparc_legitimize_pic_address (XEXP (XEXP (orig, 0), 1),
-+ base == reg ? NULL_RTX : reg);
-+
-+ if (GET_CODE (offset) == CONST_INT)
-+ {
-+ if (SMALL_INT (offset))
-+ return plus_constant (Pmode, base, INTVAL (offset));
-+ else if (can_create_pseudo_p ())
-+ offset = force_reg (Pmode, offset);
-+ else
-+ /* If we reach here, then something is seriously wrong. */
-+ gcc_unreachable ();
-+ }
-+ return gen_rtx_PLUS (Pmode, base, offset);
-+ }
-+ else if (GET_CODE (orig) == LABEL_REF)
-+ /* ??? We ought to be checking that the register is live instead, in case
-+ it is eliminated. */
-+ crtl->uses_pic_offset_table = 1;
-+
-+ return orig;
-+}
-+
-+/* Try machine-dependent ways of modifying an illegitimate address X
-+ to be legitimate. If we find one, return the new, valid address.
-+
-+ OLDX is the address as it was before break_out_memory_refs was called.
-+ In some cases it is useful to look at this to decide what needs to be done.
-+
-+ MODE is the mode of the operand pointed to by X.
-+
-+ On SPARC, change REG+N into REG+REG, and REG+(X*Y) into REG+REG. */
-+
-+static rtx
-+sparc_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
-+ machine_mode mode)
-+{
-+ rtx orig_x = x;
-+
-+ if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT)
-+ x = gen_rtx_PLUS (Pmode, XEXP (x, 1),
-+ force_operand (XEXP (x, 0), NULL_RTX));
-+ if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == MULT)
-+ x = gen_rtx_PLUS (Pmode, XEXP (x, 0),
-+ force_operand (XEXP (x, 1), NULL_RTX));
-+ if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS)
-+ x = gen_rtx_PLUS (Pmode, force_operand (XEXP (x, 0), NULL_RTX),
-+ XEXP (x, 1));
-+ if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == PLUS)
-+ x = gen_rtx_PLUS (Pmode, XEXP (x, 0),
-+ force_operand (XEXP (x, 1), NULL_RTX));
-+
-+ if (x != orig_x && sparc_legitimate_address_p (mode, x, FALSE))
-+ return x;
-+
-+ if (sparc_tls_referenced_p (x))
-+ x = sparc_legitimize_tls_address (x);
-+ else if (flag_pic)
-+ x = sparc_legitimize_pic_address (x, NULL_RTX);
-+ else if (GET_CODE (x) == PLUS && CONSTANT_ADDRESS_P (XEXP (x, 1)))
-+ x = gen_rtx_PLUS (Pmode, XEXP (x, 0),
-+ copy_to_mode_reg (Pmode, XEXP (x, 1)));
-+ else if (GET_CODE (x) == PLUS && CONSTANT_ADDRESS_P (XEXP (x, 0)))
-+ x = gen_rtx_PLUS (Pmode, XEXP (x, 1),
-+ copy_to_mode_reg (Pmode, XEXP (x, 0)));
-+ else if (GET_CODE (x) == SYMBOL_REF
-+ || GET_CODE (x) == CONST
-+ || GET_CODE (x) == LABEL_REF)
-+ x = copy_to_suggested_reg (x, NULL_RTX, Pmode);
-+
-+ return x;
-+}
-+
-+/* Delegitimize an address that was legitimized by the above function. */
-+
-+static rtx
-+sparc_delegitimize_address (rtx x)
-+{
-+ x = delegitimize_mem_from_attrs (x);
-+
-+ if (GET_CODE (x) == LO_SUM)
-+ x = XEXP (x, 1);
-+
-+ if (GET_CODE (x) == UNSPEC)
-+ switch (XINT (x, 1))
-+ {
-+ case UNSPEC_MOVE_PIC:
-+ case UNSPEC_TLSLE:
-+ x = XVECEXP (x, 0, 0);
-+ gcc_assert (GET_CODE (x) == SYMBOL_REF);
-+ break;
-+ case UNSPEC_MOVE_GOTDATA:
-+ x = XVECEXP (x, 0, 2);
-+ gcc_assert (GET_CODE (x) == SYMBOL_REF);
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ /* This is generated by mov{si,di}_pic_label_ref in PIC mode. */
-+ if (GET_CODE (x) == MINUS
-+ && (XEXP (x, 0) == got_register_rtx
-+ || sparc_pic_register_p (XEXP (x, 0))))
-+ {
-+ rtx y = XEXP (x, 1);
-+
-+ if (GET_CODE (y) == LO_SUM)
-+ y = XEXP (y, 1);
-+
-+ if (GET_CODE (y) == UNSPEC && XINT (y, 1) == UNSPEC_MOVE_PIC_LABEL)
-+ {
-+ x = XVECEXP (y, 0, 0);
-+ gcc_assert (GET_CODE (x) == LABEL_REF
-+ || (GET_CODE (x) == CONST
-+ && GET_CODE (XEXP (x, 0)) == PLUS
-+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF
-+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT));
-+ }
-+ }
-+
-+ return x;
-+}
-+
-+/* SPARC implementation of LEGITIMIZE_RELOAD_ADDRESS. Returns a value to
-+ replace the input X, or the original X if no replacement is called for.
-+ The output parameter *WIN is 1 if the calling macro should goto WIN,
-+ 0 if it should not.
-+
-+ For SPARC, we wish to handle addresses by splitting them into
-+ HIGH+LO_SUM pairs, retaining the LO_SUM in the memory reference.
-+ This cuts the number of extra insns by one.
-+
-+ Do nothing when generating PIC code and the address is a symbolic
-+ operand or requires a scratch register. */
-+
-+rtx
-+sparc_legitimize_reload_address (rtx x, machine_mode mode,
-+ int opnum, int type,
-+ int ind_levels ATTRIBUTE_UNUSED, int *win)
-+{
-+ /* Decompose SImode constants into HIGH+LO_SUM. */
-+ if (CONSTANT_P (x)
-+ && (mode != TFmode || TARGET_ARCH64)
-+ && GET_MODE (x) == SImode
-+ && GET_CODE (x) != LO_SUM
-+ && GET_CODE (x) != HIGH
-+ && sparc_code_model <= CM_MEDLOW
-+ && !(flag_pic
-+ && (symbolic_operand (x, Pmode) || pic_address_needs_scratch (x))))
-+ {
-+ x = gen_rtx_LO_SUM (GET_MODE (x), gen_rtx_HIGH (GET_MODE (x), x), x);
-+ push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
-+ BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
-+ opnum, (enum reload_type)type);
-+ *win = 1;
-+ return x;
-+ }
-+
-+ /* We have to recognize what we have already generated above. */
-+ if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == HIGH)
-+ {
-+ push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
-+ BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
-+ opnum, (enum reload_type)type);
-+ *win = 1;
-+ return x;
-+ }
-+
-+ *win = 0;
-+ return x;
-+}
-+
-+/* Return true if ADDR (a legitimate address expression)
-+ has an effect that depends on the machine mode it is used for.
-+
-+ In PIC mode,
-+
-+ (mem:HI [%l7+a])
-+
-+ is not equivalent to
-+
-+ (mem:QI [%l7+a]) (mem:QI [%l7+a+1])
-+
-+ because [%l7+a+1] is interpreted as the address of (a+1). */
-+
-+
-+static bool
-+sparc_mode_dependent_address_p (const_rtx addr,
-+ addr_space_t as ATTRIBUTE_UNUSED)
-+{
-+ if (GET_CODE (addr) == PLUS
-+ && sparc_pic_register_p (XEXP (addr, 0))
-+ && symbolic_operand (XEXP (addr, 1), VOIDmode))
-+ return true;
-+
-+ return false;
-+}
-+
-+/* Emit a call instruction with the pattern given by PAT. ADDR is the
-+ address of the call target. */
-+
-+void
-+sparc_emit_call_insn (rtx pat, rtx addr)
-+{
-+ rtx_insn *insn;
-+
-+ insn = emit_call_insn (pat);
-+
-+ /* The PIC register is live on entry to VxWorks PIC PLT entries. */
-+ if (TARGET_VXWORKS_RTP
-+ && flag_pic
-+ && GET_CODE (addr) == SYMBOL_REF
-+ && (SYMBOL_REF_DECL (addr)
-+ ? !targetm.binds_local_p (SYMBOL_REF_DECL (addr))
-+ : !SYMBOL_REF_LOCAL_P (addr)))
-+ {
-+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
-+ crtl->uses_pic_offset_table = 1;
-+ }
-+}
-+
-+/* Return 1 if RTX is a MEM which is known to be aligned to at
-+ least a DESIRED byte boundary. */
-+
-+int
-+mem_min_alignment (rtx mem, int desired)
-+{
-+ rtx addr, base, offset;
-+
-+ /* If it's not a MEM we can't accept it. */
-+ if (GET_CODE (mem) != MEM)
-+ return 0;
-+
-+ /* Obviously... */
-+ if (!TARGET_UNALIGNED_DOUBLES
-+ && MEM_ALIGN (mem) / BITS_PER_UNIT >= (unsigned)desired)
-+ return 1;
-+
-+ /* ??? The rest of the function predates MEM_ALIGN so
-+ there is probably a bit of redundancy. */
-+ addr = XEXP (mem, 0);
-+ base = offset = NULL_RTX;
-+ if (GET_CODE (addr) == PLUS)
-+ {
-+ if (GET_CODE (XEXP (addr, 0)) == REG)
-+ {
-+ base = XEXP (addr, 0);
-+
-+ /* What we are saying here is that if the base
-+ REG is aligned properly, the compiler will make
-+ sure any REG based index upon it will be so
-+ as well. */
-+ if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
-+ offset = XEXP (addr, 1);
-+ else
-+ offset = const0_rtx;
-+ }
-+ }
-+ else if (GET_CODE (addr) == REG)
-+ {
-+ base = addr;
-+ offset = const0_rtx;
-+ }
-+
-+ if (base != NULL_RTX)
-+ {
-+ int regno = REGNO (base);
-+
-+ if (regno != HARD_FRAME_POINTER_REGNUM && regno != STACK_POINTER_REGNUM)
-+ {
-+ /* Check if the compiler has recorded some information
-+ about the alignment of the base REG. If reload has
-+ completed, we already matched with proper alignments.
-+ If not running global_alloc, reload might give us
-+ unaligned pointer to local stack though. */
-+ if (((cfun != 0
-+ && REGNO_POINTER_ALIGN (regno) >= desired * BITS_PER_UNIT)
-+ || (optimize && reload_completed))
-+ && (INTVAL (offset) & (desired - 1)) == 0)
-+ return 1;
-+ }
-+ else
-+ {
-+ if (((INTVAL (offset) - SPARC_STACK_BIAS) & (desired - 1)) == 0)
-+ return 1;
-+ }
-+ }
-+ else if (! TARGET_UNALIGNED_DOUBLES
-+ || CONSTANT_P (addr)
-+ || GET_CODE (addr) == LO_SUM)
-+ {
-+ /* Anything else we know is properly aligned unless TARGET_UNALIGNED_DOUBLES
-+ is true, in which case we can only assume that an access is aligned if
-+ it is to a constant address, or the address involves a LO_SUM. */
-+ return 1;
-+ }
-+
-+ /* An obviously unaligned address. */
-+ return 0;
-+}
-+
-+
-+/* Vectors to keep interesting information about registers where it can easily
-+ be got. We used to use the actual mode value as the bit number, but there
-+ are more than 32 modes now. Instead we use two tables: one indexed by
-+ hard register number, and one indexed by mode. */
-+
-+/* The purpose of sparc_mode_class is to shrink the range of modes so that
-+ they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
-+ mapped into one sparc_mode_class mode. */
-+
-+enum sparc_mode_class {
-+ H_MODE, S_MODE, D_MODE, T_MODE, O_MODE,
-+ SF_MODE, DF_MODE, TF_MODE, OF_MODE,
-+ CC_MODE, CCFP_MODE
-+};
-+
-+/* Modes for single-word and smaller quantities. */
-+#define S_MODES \
-+ ((1 << (int) H_MODE) | (1 << (int) S_MODE) | (1 << (int) SF_MODE))
-+
-+/* Modes for double-word and smaller quantities. */
-+#define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << (int) DF_MODE))
-+
-+/* Modes for quad-word and smaller quantities. */
-+#define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
-+
-+/* Modes for 8-word and smaller quantities. */
-+#define O_MODES (T_MODES | (1 << (int) O_MODE) | (1 << (int) OF_MODE))
-+
-+/* Modes for single-float quantities. */
-+#define SF_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
-+
-+/* Modes for double-float and smaller quantities. */
-+#define DF_MODES (SF_MODES | (1 << (int) D_MODE) | (1 << (int) DF_MODE))
-+
-+/* Modes for quad-float and smaller quantities. */
-+#define TF_MODES (DF_MODES | (1 << (int) TF_MODE))
-+
-+/* Modes for quad-float pairs and smaller quantities. */
-+#define OF_MODES (TF_MODES | (1 << (int) OF_MODE))
-+
-+/* Modes for double-float only quantities. */
-+#define DF_MODES_NO_S ((1 << (int) D_MODE) | (1 << (int) DF_MODE))
-+
-+/* Modes for quad-float and double-float only quantities. */
-+#define TF_MODES_NO_S (DF_MODES_NO_S | (1 << (int) TF_MODE))
-+
-+/* Modes for quad-float pairs and double-float only quantities. */
-+#define OF_MODES_NO_S (TF_MODES_NO_S | (1 << (int) OF_MODE))
-+
-+/* Modes for condition codes. */
-+#define CC_MODES (1 << (int) CC_MODE)
-+#define CCFP_MODES (1 << (int) CCFP_MODE)
-+
-+/* Value is 1 if register/mode pair is acceptable on sparc.
-+
-+ The funny mixture of D and T modes is because integer operations
-+ do not specially operate on tetra quantities, so non-quad-aligned
-+ registers can hold quadword quantities (except %o4 and %i4 because
-+ they cross fixed registers).
-+
-+ ??? Note that, despite the settings, non-double-aligned parameter
-+ registers can hold double-word quantities in 32-bit mode. */
-+
-+/* This points to either the 32-bit or the 64-bit version. */
-+static const int *hard_regno_mode_classes;
-+
-+static const int hard_32bit_mode_classes[] = {
-+ S_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
-+ T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
-+ T_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
-+ T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
-+
-+ OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
-+ OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
-+ OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
-+ OF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
-+
-+ /* FP regs f32 to f63. Only the even numbered registers actually exist,
-+ and none can hold SFmode/SImode values. */
-+ OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
-+ OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
-+ OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
-+ OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, TF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
-+
-+ /* %fcc[0123] */
-+ CCFP_MODES, CCFP_MODES, CCFP_MODES, CCFP_MODES,
-+
-+ /* %icc, %sfp, %gsr */
-+ CC_MODES, 0, D_MODES
-+};
-+
-+static const int hard_64bit_mode_classes[] = {
-+ D_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
-+ O_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
-+ T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
-+ O_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
-+
-+ OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
-+ OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
-+ OF_MODES, SF_MODES, DF_MODES, SF_MODES, OF_MODES, SF_MODES, DF_MODES, SF_MODES,
-+ OF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
-+
-+ /* FP regs f32 to f63. Only the even numbered registers actually exist,
-+ and none can hold SFmode/SImode values. */
-+ OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
-+ OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
-+ OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, OF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
-+ OF_MODES_NO_S, 0, DF_MODES_NO_S, 0, TF_MODES_NO_S, 0, DF_MODES_NO_S, 0,
-+
-+ /* %fcc[0123] */
-+ CCFP_MODES, CCFP_MODES, CCFP_MODES, CCFP_MODES,
-+
-+ /* %icc, %sfp, %gsr */
-+ CC_MODES, 0, D_MODES
-+};
-+
-+static int sparc_mode_class [NUM_MACHINE_MODES];
-+
-+enum reg_class sparc_regno_reg_class[FIRST_PSEUDO_REGISTER];
-+
-+static void
-+sparc_init_modes (void)
-+{
-+ int i;
-+
-+ for (i = 0; i < NUM_MACHINE_MODES; i++)
-+ {
-+ machine_mode m = (machine_mode) i;
-+ unsigned int size = GET_MODE_SIZE (m);
-+
-+ switch (GET_MODE_CLASS (m))
-+ {
-+ case MODE_INT:
-+ case MODE_PARTIAL_INT:
-+ case MODE_COMPLEX_INT:
-+ if (size < 4)
-+ sparc_mode_class[i] = 1 << (int) H_MODE;
-+ else if (size == 4)
-+ sparc_mode_class[i] = 1 << (int) S_MODE;
-+ else if (size == 8)
-+ sparc_mode_class[i] = 1 << (int) D_MODE;
-+ else if (size == 16)
-+ sparc_mode_class[i] = 1 << (int) T_MODE;
-+ else if (size == 32)
-+ sparc_mode_class[i] = 1 << (int) O_MODE;
-+ else
-+ sparc_mode_class[i] = 0;
-+ break;
-+ case MODE_VECTOR_INT:
-+ if (size == 4)
-+ sparc_mode_class[i] = 1 << (int) SF_MODE;
-+ else if (size == 8)
-+ sparc_mode_class[i] = 1 << (int) DF_MODE;
-+ else
-+ sparc_mode_class[i] = 0;
-+ break;
-+ case MODE_FLOAT:
-+ case MODE_COMPLEX_FLOAT:
-+ if (size == 4)
-+ sparc_mode_class[i] = 1 << (int) SF_MODE;
-+ else if (size == 8)
-+ sparc_mode_class[i] = 1 << (int) DF_MODE;
-+ else if (size == 16)
-+ sparc_mode_class[i] = 1 << (int) TF_MODE;
-+ else if (size == 32)
-+ sparc_mode_class[i] = 1 << (int) OF_MODE;
-+ else
-+ sparc_mode_class[i] = 0;
-+ break;
-+ case MODE_CC:
-+ if (m == CCFPmode || m == CCFPEmode)
-+ sparc_mode_class[i] = 1 << (int) CCFP_MODE;
-+ else
-+ sparc_mode_class[i] = 1 << (int) CC_MODE;
-+ break;
-+ default:
-+ sparc_mode_class[i] = 0;
-+ break;
-+ }
-+ }
-+
-+ if (TARGET_ARCH64)
-+ hard_regno_mode_classes = hard_64bit_mode_classes;
-+ else
-+ hard_regno_mode_classes = hard_32bit_mode_classes;
-+
-+ /* Initialize the array used by REGNO_REG_CLASS. */
-+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-+ {
-+ if (i < 16 && TARGET_V8PLUS)
-+ sparc_regno_reg_class[i] = I64_REGS;
-+ else if (i < 32 || i == FRAME_POINTER_REGNUM)
-+ sparc_regno_reg_class[i] = GENERAL_REGS;
-+ else if (i < 64)
-+ sparc_regno_reg_class[i] = FP_REGS;
-+ else if (i < 96)
-+ sparc_regno_reg_class[i] = EXTRA_FP_REGS;
-+ else if (i < 100)
-+ sparc_regno_reg_class[i] = FPCC_REGS;
-+ else
-+ sparc_regno_reg_class[i] = NO_REGS;
-+ }
-+}
-+
-+/* Return whether REGNO, a global or FP register, must be saved/restored. */
-+
-+static inline bool
-+save_global_or_fp_reg_p (unsigned int regno,
-+ int leaf_function ATTRIBUTE_UNUSED)
-+{
-+ return !call_used_or_fixed_reg_p (regno) && df_regs_ever_live_p (regno);
-+}
-+
-+/* Return whether the return address register (%i7) is needed. */
-+
-+static inline bool
-+return_addr_reg_needed_p (int leaf_function)
-+{
-+ /* If it is live, for example because of __builtin_return_address (0). */
-+ if (df_regs_ever_live_p (RETURN_ADDR_REGNUM))
-+ return true;
-+
-+ /* Otherwise, it is needed as save register if %o7 is clobbered. */
-+ if (!leaf_function
-+ /* Loading the GOT register clobbers %o7. */
-+ || crtl->uses_pic_offset_table
-+ || df_regs_ever_live_p (INCOMING_RETURN_ADDR_REGNUM))
-+ return true;
-+
-+ return false;
-+}
-+
-+/* Return whether REGNO, a local or in register, must be saved/restored. */
-+
-+static bool
-+save_local_or_in_reg_p (unsigned int regno, int leaf_function)
-+{
-+ /* General case: call-saved registers live at some point. */
-+ if (!call_used_or_fixed_reg_p (regno) && df_regs_ever_live_p (regno))
-+ return true;
-+
-+ /* Frame pointer register (%fp) if needed. */
-+ if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
-+ return true;
-+
-+ /* Return address register (%i7) if needed. */
-+ if (regno == RETURN_ADDR_REGNUM && return_addr_reg_needed_p (leaf_function))
-+ return true;
-+
-+ /* GOT register (%l7) if needed. */
-+ if (got_register_rtx && regno == REGNO (got_register_rtx))
-+ return true;
-+
-+ /* If the function accesses prior frames, the frame pointer and the return
-+ address of the previous frame must be saved on the stack. */
-+ if (crtl->accesses_prior_frames
-+ && (regno == HARD_FRAME_POINTER_REGNUM || regno == RETURN_ADDR_REGNUM))
-+ return true;
-+
-+ return false;
-+}
-+
-+/* Compute the frame size required by the function. This function is called
-+ during the reload pass and also by sparc_expand_prologue. */
-+
-+static HOST_WIDE_INT
-+sparc_compute_frame_size (HOST_WIDE_INT size, int leaf_function)
-+{
-+ HOST_WIDE_INT frame_size, apparent_frame_size;
-+ int args_size, n_global_fp_regs = 0;
-+ bool save_local_in_regs_p = false;
-+ unsigned int i;
-+
-+ /* If the function allocates dynamic stack space, the dynamic offset is
-+ computed early and contains REG_PARM_STACK_SPACE, so we need to cope. */
-+ if (leaf_function && !cfun->calls_alloca)
-+ args_size = 0;
-+ else
-+ args_size = crtl->outgoing_args_size + REG_PARM_STACK_SPACE (cfun->decl);
-+
-+ /* Calculate space needed for global registers. */
-+ if (TARGET_ARCH64)
-+ {
-+ for (i = 0; i < 8; i++)
-+ if (save_global_or_fp_reg_p (i, 0))
-+ n_global_fp_regs += 2;
-+ }
-+ else
-+ {
-+ for (i = 0; i < 8; i += 2)
-+ if (save_global_or_fp_reg_p (i, 0)
-+ || save_global_or_fp_reg_p (i + 1, 0))
-+ n_global_fp_regs += 2;
-+ }
-+
-+ /* In the flat window model, find out which local and in registers need to
-+ be saved. We don't reserve space in the current frame for them as they
-+ will be spilled into the register window save area of the caller's frame.
-+ However, as soon as we use this register window save area, we must create
-+ that of the current frame to make it the live one. */
-+ if (TARGET_FLAT)
-+ for (i = 16; i < 32; i++)
-+ if (save_local_or_in_reg_p (i, leaf_function))
-+ {
-+ save_local_in_regs_p = true;
-+ break;
-+ }
-+
-+ /* Calculate space needed for FP registers. */
-+ for (i = 32; i < (TARGET_V9 ? 96 : 64); i += 2)
-+ if (save_global_or_fp_reg_p (i, 0) || save_global_or_fp_reg_p (i + 1, 0))
-+ n_global_fp_regs += 2;
-+
-+ if (size == 0
-+ && n_global_fp_regs == 0
-+ && args_size == 0
-+ && !save_local_in_regs_p)
-+ frame_size = apparent_frame_size = 0;
-+ else
-+ {
-+ /* Start from the apparent frame size. */
-+ apparent_frame_size = ROUND_UP (size, 8) + n_global_fp_regs * 4;
-+
-+ /* We need to add the size of the outgoing argument area. */
-+ frame_size = apparent_frame_size + ROUND_UP (args_size, 8);
-+
-+ /* And that of the register window save area. */
-+ frame_size += FIRST_PARM_OFFSET (cfun->decl);
-+
-+ /* Finally, bump to the appropriate alignment. */
-+ frame_size = SPARC_STACK_ALIGN (frame_size);
-+ }
-+
-+ /* Set up values for use in prologue and epilogue. */
-+ sparc_frame_size = frame_size;
-+ sparc_apparent_frame_size = apparent_frame_size;
-+ sparc_n_global_fp_regs = n_global_fp_regs;
-+ sparc_save_local_in_regs_p = save_local_in_regs_p;
-+
-+ return frame_size;
-+}
-+
-+/* Implement the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */
-+
-+int
-+sparc_initial_elimination_offset (int to)
-+{
-+ int offset;
-+
-+ if (to == STACK_POINTER_REGNUM)
-+ offset = sparc_compute_frame_size (get_frame_size (), crtl->is_leaf);
-+ else
-+ offset = 0;
-+
-+ offset += SPARC_STACK_BIAS;
-+ return offset;
-+}
-+
-+/* Output any necessary .register pseudo-ops. */
-+
-+void
-+sparc_output_scratch_registers (FILE *file ATTRIBUTE_UNUSED)
-+{
-+ int i;
-+
-+ if (TARGET_ARCH32)
-+ return;
-+
-+ /* Check if %g[2367] were used without
-+ .register being printed for them already. */
-+ for (i = 2; i < 8; i++)
-+ {
-+ if (df_regs_ever_live_p (i)
-+ && ! sparc_hard_reg_printed [i])
-+ {
-+ sparc_hard_reg_printed [i] = 1;
-+ /* %g7 is used as TLS base register, use #ignore
-+ for it instead of #scratch. */
-+ fprintf (file, "\t.register\t%%g%d, #%s\n", i,
-+ i == 7 ? "ignore" : "scratch");
-+ }
-+ if (i == 3) i = 5;
-+ }
-+}
-+
-+#define PROBE_INTERVAL (1 << STACK_CHECK_PROBE_INTERVAL_EXP)
-+
-+#if PROBE_INTERVAL > 4096
-+#error Cannot use indexed addressing mode for stack probing
-+#endif
-+
-+/* Emit code to probe a range of stack addresses from FIRST to FIRST+SIZE,
-+ inclusive. These are offsets from the current stack pointer.
-+
-+ Note that we don't use the REG+REG addressing mode for the probes because
-+ of the stack bias in 64-bit mode. And it doesn't really buy us anything
-+ so the advantages of having a single code win here. */
-+
-+static void
-+sparc_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size)
-+{
-+ rtx g1 = gen_rtx_REG (Pmode, 1);
-+
-+ /* See if we have a constant small number of probes to generate. If so,
-+ that's the easy case. */
-+ if (size <= PROBE_INTERVAL)
-+ {
-+ emit_move_insn (g1, GEN_INT (first));
-+ emit_insn (gen_rtx_SET (g1,
-+ gen_rtx_MINUS (Pmode, stack_pointer_rtx, g1)));
-+ emit_stack_probe (plus_constant (Pmode, g1, -size));
-+ }
-+
-+ /* The run-time loop is made up of 9 insns in the generic case while the
-+ compile-time loop is made up of 4+2*(n-2) insns for n # of intervals. */
-+ else if (size <= 4 * PROBE_INTERVAL)
-+ {
-+ HOST_WIDE_INT i;
-+
-+ emit_move_insn (g1, GEN_INT (first + PROBE_INTERVAL));
-+ emit_insn (gen_rtx_SET (g1,
-+ gen_rtx_MINUS (Pmode, stack_pointer_rtx, g1)));
-+ emit_stack_probe (g1);
-+
-+ /* Probe at FIRST + N * PROBE_INTERVAL for values of N from 2 until
-+ it exceeds SIZE. If only two probes are needed, this will not
-+ generate any code. Then probe at FIRST + SIZE. */
-+ for (i = 2 * PROBE_INTERVAL; i < size; i += PROBE_INTERVAL)
-+ {
-+ emit_insn (gen_rtx_SET (g1,
-+ plus_constant (Pmode, g1, -PROBE_INTERVAL)));
-+ emit_stack_probe (g1);
-+ }
-+
-+ emit_stack_probe (plus_constant (Pmode, g1,
-+ (i - PROBE_INTERVAL) - size));
-+ }
-+
-+ /* Otherwise, do the same as above, but in a loop. Note that we must be
-+ extra careful with variables wrapping around because we might be at
-+ the very top (or the very bottom) of the address space and we have
-+ to be able to handle this case properly; in particular, we use an
-+ equality test for the loop condition. */
-+ else
-+ {
-+ HOST_WIDE_INT rounded_size;
-+ rtx g4 = gen_rtx_REG (Pmode, 4);
-+
-+ emit_move_insn (g1, GEN_INT (first));
-+
-+
-+ /* Step 1: round SIZE to the previous multiple of the interval. */
-+
-+ rounded_size = ROUND_DOWN (size, PROBE_INTERVAL);
-+ emit_move_insn (g4, GEN_INT (rounded_size));
-+
-+
-+ /* Step 2: compute initial and final value of the loop counter. */
-+
-+ /* TEST_ADDR = SP + FIRST. */
-+ emit_insn (gen_rtx_SET (g1,
-+ gen_rtx_MINUS (Pmode, stack_pointer_rtx, g1)));
-+
-+ /* LAST_ADDR = SP + FIRST + ROUNDED_SIZE. */
-+ emit_insn (gen_rtx_SET (g4, gen_rtx_MINUS (Pmode, g1, g4)));
-+
-+
-+ /* Step 3: the loop
-+
-+ while (TEST_ADDR != LAST_ADDR)
-+ {
-+ TEST_ADDR = TEST_ADDR + PROBE_INTERVAL
-+ probe at TEST_ADDR
-+ }
-+
-+ probes at FIRST + N * PROBE_INTERVAL for values of N from 1
-+ until it is equal to ROUNDED_SIZE. */
-+
-+ if (TARGET_ARCH64)
-+ emit_insn (gen_probe_stack_rangedi (g1, g1, g4));
-+ else
-+ emit_insn (gen_probe_stack_rangesi (g1, g1, g4));
-+
-+
-+ /* Step 4: probe at FIRST + SIZE if we cannot assert at compile-time
-+ that SIZE is equal to ROUNDED_SIZE. */
-+
-+ if (size != rounded_size)
-+ emit_stack_probe (plus_constant (Pmode, g4, rounded_size - size));
-+ }
-+
-+ /* Make sure nothing is scheduled before we are done. */
-+ emit_insn (gen_blockage ());
-+}
-+
-+/* Probe a range of stack addresses from REG1 to REG2 inclusive. These are
-+ absolute addresses. */
-+
-+const char *
-+output_probe_stack_range (rtx reg1, rtx reg2)
-+{
-+ static int labelno = 0;
-+ char loop_lab[32];
-+ rtx xops[2];
-+
-+ ASM_GENERATE_INTERNAL_LABEL (loop_lab, "LPSRL", labelno++);
-+
-+ /* Loop. */
-+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_lab);
-+
-+ /* TEST_ADDR = TEST_ADDR + PROBE_INTERVAL. */
-+ xops[0] = reg1;
-+ xops[1] = GEN_INT (-PROBE_INTERVAL);
-+ output_asm_insn ("add\t%0, %1, %0", xops);
-+
-+ /* Test if TEST_ADDR == LAST_ADDR. */
-+ xops[1] = reg2;
-+ output_asm_insn ("cmp\t%0, %1", xops);
-+
-+ /* Probe at TEST_ADDR and branch. */
-+ if (TARGET_ARCH64)
-+ fputs ("\tbne,pt\t%xcc,", asm_out_file);
-+ else
-+ fputs ("\tbne\t", asm_out_file);
-+ assemble_name_raw (asm_out_file, loop_lab);
-+ fputc ('\n', asm_out_file);
-+ xops[1] = GEN_INT (SPARC_STACK_BIAS);
-+ output_asm_insn (" st\t%%g0, [%0+%1]", xops);
-+
-+ return "";
-+}
-+
-+/* Emit code to save/restore registers from LOW to HIGH at BASE+OFFSET as
-+ needed. LOW is supposed to be double-word aligned for 32-bit registers.
-+ SAVE_P decides whether a register must be saved/restored. ACTION_TRUE
-+ is the action to be performed if SAVE_P returns true and ACTION_FALSE
-+ the action to be performed if it returns false. Return the new offset. */
-+
-+typedef bool (*sorr_pred_t) (unsigned int, int);
-+typedef enum { SORR_NONE, SORR_ADVANCE, SORR_SAVE, SORR_RESTORE } sorr_act_t;
-+
-+static int
-+emit_save_or_restore_regs (unsigned int low, unsigned int high, rtx base,
-+ int offset, int leaf_function, sorr_pred_t save_p,
-+ sorr_act_t action_true, sorr_act_t action_false)
-+{
-+ unsigned int i;
-+ rtx mem;
-+ rtx_insn *insn;
-+
-+ if (TARGET_ARCH64 && high <= 32)
-+ {
-+ int fp_offset = -1;
-+
-+ for (i = low; i < high; i++)
-+ {
-+ if (save_p (i, leaf_function))
-+ {
-+ mem = gen_frame_mem (DImode, plus_constant (Pmode,
-+ base, offset));
-+ if (action_true == SORR_SAVE)
-+ {
-+ insn = emit_move_insn (mem, gen_rtx_REG (DImode, i));
-+ RTX_FRAME_RELATED_P (insn) = 1;
-+ }
-+ else /* action_true == SORR_RESTORE */
-+ {
-+ /* The frame pointer must be restored last since its old
-+ value may be used as base address for the frame. This
-+ is problematic in 64-bit mode only because of the lack
-+ of double-word load instruction. */
-+ if (i == HARD_FRAME_POINTER_REGNUM)
-+ fp_offset = offset;
-+ else
-+ emit_move_insn (gen_rtx_REG (DImode, i), mem);
-+ }
-+ offset += 8;
-+ }
-+ else if (action_false == SORR_ADVANCE)
-+ offset += 8;
-+ }
-+
-+ if (fp_offset >= 0)
-+ {
-+ mem = gen_frame_mem (DImode, plus_constant (Pmode, base, fp_offset));
-+ emit_move_insn (hard_frame_pointer_rtx, mem);
-+ }
-+ }
-+ else
-+ {
-+ for (i = low; i < high; i += 2)
-+ {
-+ bool reg0 = save_p (i, leaf_function);
-+ bool reg1 = save_p (i + 1, leaf_function);
-+ machine_mode mode;
-+ int regno;
-+
-+ if (reg0 && reg1)
-+ {
-+ mode = SPARC_INT_REG_P (i) ? E_DImode : E_DFmode;
-+ regno = i;
-+ }
-+ else if (reg0)
-+ {
-+ mode = SPARC_INT_REG_P (i) ? E_SImode : E_SFmode;
-+ regno = i;
-+ }
-+ else if (reg1)
-+ {
-+ mode = SPARC_INT_REG_P (i) ? E_SImode : E_SFmode;
-+ regno = i + 1;
-+ offset += 4;
-+ }
-+ else
-+ {
-+ if (action_false == SORR_ADVANCE)
-+ offset += 8;
-+ continue;
-+ }
-+
-+ mem = gen_frame_mem (mode, plus_constant (Pmode, base, offset));
-+ if (action_true == SORR_SAVE)
-+ {
-+ insn = emit_move_insn (mem, gen_rtx_REG (mode, regno));
-+ RTX_FRAME_RELATED_P (insn) = 1;
-+ if (mode == DImode)
-+ {
-+ rtx set1, set2;
-+ mem = gen_frame_mem (SImode, plus_constant (Pmode, base,
-+ offset));
-+ set1 = gen_rtx_SET (mem, gen_rtx_REG (SImode, regno));
-+ RTX_FRAME_RELATED_P (set1) = 1;
-+ mem
-+ = gen_frame_mem (SImode, plus_constant (Pmode, base,
-+ offset + 4));
-+ set2 = gen_rtx_SET (mem, gen_rtx_REG (SImode, regno + 1));
-+ RTX_FRAME_RELATED_P (set2) = 1;
-+ add_reg_note (insn, REG_FRAME_RELATED_EXPR,
-+ gen_rtx_PARALLEL (VOIDmode,
-+ gen_rtvec (2, set1, set2)));
-+ }
-+ }
-+ else /* action_true == SORR_RESTORE */
-+ emit_move_insn (gen_rtx_REG (mode, regno), mem);
-+
-+ /* Bump and round down to double word
-+ in case we already bumped by 4. */
-+ offset = ROUND_DOWN (offset + 8, 8);
-+ }
-+ }
-+
-+ return offset;
-+}
-+
-+/* Emit code to adjust BASE to OFFSET. Return the new base. */
-+
-+static rtx
-+emit_adjust_base_to_offset (rtx base, int offset)
-+{
-+ /* ??? This might be optimized a little as %g1 might already have a
-+ value close enough that a single add insn will do. */
-+ /* ??? Although, all of this is probably only a temporary fix because
-+ if %g1 can hold a function result, then sparc_expand_epilogue will
-+ lose (the result will be clobbered). */
-+ rtx new_base = gen_rtx_REG (Pmode, 1);
-+ emit_move_insn (new_base, GEN_INT (offset));
-+ emit_insn (gen_rtx_SET (new_base, gen_rtx_PLUS (Pmode, base, new_base)));
-+ return new_base;
-+}
-+
-+/* Emit code to save/restore call-saved global and FP registers. */
-+
-+static void
-+emit_save_or_restore_global_fp_regs (rtx base, int offset, sorr_act_t action)
-+{
-+ if (offset < -4096 || offset + sparc_n_global_fp_regs * 4 > 4095)
-+ {
-+ base = emit_adjust_base_to_offset (base, offset);
-+ offset = 0;
-+ }
-+
-+ offset
-+ = emit_save_or_restore_regs (0, 8, base, offset, 0,
-+ save_global_or_fp_reg_p, action, SORR_NONE);
-+ emit_save_or_restore_regs (32, TARGET_V9 ? 96 : 64, base, offset, 0,
-+ save_global_or_fp_reg_p, action, SORR_NONE);
-+}
-+
-+/* Emit code to save/restore call-saved local and in registers. */
-+
-+static void
-+emit_save_or_restore_local_in_regs (rtx base, int offset, sorr_act_t action)
-+{
-+ if (offset < -4096 || offset + 16 * UNITS_PER_WORD > 4095)
-+ {
-+ base = emit_adjust_base_to_offset (base, offset);
-+ offset = 0;
-+ }
-+
-+ emit_save_or_restore_regs (16, 32, base, offset, sparc_leaf_function_p,
-+ save_local_or_in_reg_p, action, SORR_ADVANCE);
-+}
-+
-+/* Emit a window_save insn. */
-+
-+static rtx_insn *
-+emit_window_save (rtx increment)
-+{
-+ rtx_insn *insn = emit_insn (gen_window_save (increment));
-+ RTX_FRAME_RELATED_P (insn) = 1;
-+
-+ /* The incoming return address (%o7) is saved in %i7. */
-+ add_reg_note (insn, REG_CFA_REGISTER,
-+ gen_rtx_SET (gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM),
-+ gen_rtx_REG (Pmode,
-+ INCOMING_RETURN_ADDR_REGNUM)));
-+
-+ /* The window save event. */
-+ add_reg_note (insn, REG_CFA_WINDOW_SAVE, const0_rtx);
-+
-+ /* The CFA is %fp, the hard frame pointer. */
-+ add_reg_note (insn, REG_CFA_DEF_CFA,
-+ plus_constant (Pmode, hard_frame_pointer_rtx,
-+ INCOMING_FRAME_SP_OFFSET));
-+
-+ return insn;
-+}
-+
-+/* Generate an increment for the stack pointer. */
-+
-+static rtx
-+gen_stack_pointer_inc (rtx increment)
-+{
-+ return gen_rtx_SET (stack_pointer_rtx,
-+ gen_rtx_PLUS (Pmode,
-+ stack_pointer_rtx,
-+ increment));
-+}
-+
-+/* Expand the function prologue. The prologue is responsible for reserving
-+ storage for the frame, saving the call-saved registers and loading the
-+ GOT register if needed. */
-+
-+void
-+sparc_expand_prologue (void)
-+{
-+ HOST_WIDE_INT size;
-+ rtx_insn *insn;
-+
-+ /* Compute a snapshot of crtl->uses_only_leaf_regs. Relying
-+ on the final value of the flag means deferring the prologue/epilogue
-+ expansion until just before the second scheduling pass, which is too
-+ late to emit multiple epilogues or return insns.
-+
-+ Of course we are making the assumption that the value of the flag
-+ will not change between now and its final value. Of the three parts
-+ of the formula, only the last one can reasonably vary. Let's take a
-+ closer look, after assuming that the first two ones are set to true
-+ (otherwise the last value is effectively silenced).
-+
-+ If only_leaf_regs_used returns false, the global predicate will also
-+ be false so the actual frame size calculated below will be positive.
-+ As a consequence, the save_register_window insn will be emitted in
-+ the instruction stream; now this insn explicitly references %fp
-+ which is not a leaf register so only_leaf_regs_used will always
-+ return false subsequently.
-+
-+ If only_leaf_regs_used returns true, we hope that the subsequent
-+ optimization passes won't cause non-leaf registers to pop up. For
-+ example, the regrename pass has special provisions to not rename to
-+ non-leaf registers in a leaf function. */
-+ sparc_leaf_function_p
-+ = optimize > 0 && crtl->is_leaf && only_leaf_regs_used ();
-+
-+ size = sparc_compute_frame_size (get_frame_size(), sparc_leaf_function_p);
-+
-+ if (flag_stack_usage_info)
-+ current_function_static_stack_size = size;
-+
-+ if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
-+ || flag_stack_clash_protection)
-+ {
-+ if (crtl->is_leaf && !cfun->calls_alloca)
-+ {
-+ if (size > PROBE_INTERVAL && size > get_stack_check_protect ())
-+ sparc_emit_probe_stack_range (get_stack_check_protect (),
-+ size - get_stack_check_protect ());
-+ }
-+ else if (size > 0)
-+ sparc_emit_probe_stack_range (get_stack_check_protect (), size);
-+ }
-+
-+ if (size == 0)
-+ ; /* do nothing. */
-+ else if (sparc_leaf_function_p)
-+ {
-+ rtx size_int_rtx = GEN_INT (-size);
-+
-+ if (size <= 4096)
-+ insn = emit_insn (gen_stack_pointer_inc (size_int_rtx));
-+ else if (size <= 8192)
-+ {
-+ insn = emit_insn (gen_stack_pointer_inc (GEN_INT (-4096)));
-+ RTX_FRAME_RELATED_P (insn) = 1;
-+
-+ /* %sp is still the CFA register. */
-+ insn = emit_insn (gen_stack_pointer_inc (GEN_INT (4096 - size)));
-+ }
-+ else
-+ {
-+ rtx size_rtx = gen_rtx_REG (Pmode, 1);
-+ emit_move_insn (size_rtx, size_int_rtx);
-+ insn = emit_insn (gen_stack_pointer_inc (size_rtx));
-+ add_reg_note (insn, REG_FRAME_RELATED_EXPR,
-+ gen_stack_pointer_inc (size_int_rtx));
-+ }
-+
-+ RTX_FRAME_RELATED_P (insn) = 1;
-+ }
-+ else
-+ {
-+ rtx size_int_rtx = GEN_INT (-size);
-+
-+ if (size <= 4096)
-+ emit_window_save (size_int_rtx);
-+ else if (size <= 8192)
-+ {
-+ emit_window_save (GEN_INT (-4096));
-+
-+ /* %sp is not the CFA register anymore. */
-+ emit_insn (gen_stack_pointer_inc (GEN_INT (4096 - size)));
-+
-+ /* Make sure no %fp-based store is issued until after the frame is
-+ established. The offset between the frame pointer and the stack
-+ pointer is calculated relative to the value of the stack pointer
-+ at the end of the function prologue, and moving instructions that
-+ access the stack via the frame pointer between the instructions
-+ that decrement the stack pointer could result in accessing the
-+ register window save area, which is volatile. */
-+ emit_insn (gen_frame_blockage ());
-+ }
-+ else
-+ {
-+ rtx size_rtx = gen_rtx_REG (Pmode, 1);
-+ emit_move_insn (size_rtx, size_int_rtx);
-+ emit_window_save (size_rtx);
-+ }
-+ }
-+
-+ if (sparc_leaf_function_p)
-+ {
-+ sparc_frame_base_reg = stack_pointer_rtx;
-+ sparc_frame_base_offset = size + SPARC_STACK_BIAS;
-+ }
-+ else
-+ {
-+ sparc_frame_base_reg = hard_frame_pointer_rtx;
-+ sparc_frame_base_offset = SPARC_STACK_BIAS;
-+ }
-+
-+ if (sparc_n_global_fp_regs > 0)
-+ emit_save_or_restore_global_fp_regs (sparc_frame_base_reg,
-+ sparc_frame_base_offset
-+ - sparc_apparent_frame_size,
-+ SORR_SAVE);
-+
-+ /* Advertise that the data calculated just above are now valid. */
-+ sparc_prologue_data_valid_p = true;
-+}
-+
-+/* Expand the function prologue. The prologue is responsible for reserving
-+ storage for the frame, saving the call-saved registers and loading the
-+ GOT register if needed. */
-+
-+void
-+sparc_flat_expand_prologue (void)
-+{
-+ HOST_WIDE_INT size;
-+ rtx_insn *insn;
-+
-+ sparc_leaf_function_p = optimize > 0 && crtl->is_leaf;
-+
-+ size = sparc_compute_frame_size (get_frame_size(), sparc_leaf_function_p);
-+
-+ if (flag_stack_usage_info)
-+ current_function_static_stack_size = size;
-+
-+ if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
-+ || flag_stack_clash_protection)
-+ {
-+ if (crtl->is_leaf && !cfun->calls_alloca)
-+ {
-+ if (size > PROBE_INTERVAL && size > get_stack_check_protect ())
-+ sparc_emit_probe_stack_range (get_stack_check_protect (),
-+ size - get_stack_check_protect ());
-+ }
-+ else if (size > 0)
-+ sparc_emit_probe_stack_range (get_stack_check_protect (), size);
-+ }
-+
-+ if (sparc_save_local_in_regs_p)
-+ emit_save_or_restore_local_in_regs (stack_pointer_rtx, SPARC_STACK_BIAS,
-+ SORR_SAVE);
-+
-+ if (size == 0)
-+ ; /* do nothing. */
-+ else
-+ {
-+ rtx size_int_rtx, size_rtx;
-+
-+ size_rtx = size_int_rtx = GEN_INT (-size);
-+
-+ /* We establish the frame (i.e. decrement the stack pointer) first, even
-+ if we use a frame pointer, because we cannot clobber any call-saved
-+ registers, including the frame pointer, if we haven't created a new
-+ register save area, for the sake of compatibility with the ABI. */
-+ if (size <= 4096)
-+ insn = emit_insn (gen_stack_pointer_inc (size_int_rtx));
-+ else if (size <= 8192 && !frame_pointer_needed)
-+ {
-+ insn = emit_insn (gen_stack_pointer_inc (GEN_INT (-4096)));
-+ RTX_FRAME_RELATED_P (insn) = 1;
-+ insn = emit_insn (gen_stack_pointer_inc (GEN_INT (4096 - size)));
-+ }
-+ else
-+ {
-+ size_rtx = gen_rtx_REG (Pmode, 1);
-+ emit_move_insn (size_rtx, size_int_rtx);
-+ insn = emit_insn (gen_stack_pointer_inc (size_rtx));
-+ add_reg_note (insn, REG_CFA_ADJUST_CFA,
-+ gen_stack_pointer_inc (size_int_rtx));
-+ }
-+ RTX_FRAME_RELATED_P (insn) = 1;
-+
-+ /* Ensure nothing is scheduled until after the frame is established. */
-+ emit_insn (gen_blockage ());
-+
-+ if (frame_pointer_needed)
-+ {
-+ insn = emit_insn (gen_rtx_SET (hard_frame_pointer_rtx,
-+ gen_rtx_MINUS (Pmode,
-+ stack_pointer_rtx,
-+ size_rtx)));
-+ RTX_FRAME_RELATED_P (insn) = 1;
-+
-+ add_reg_note (insn, REG_CFA_ADJUST_CFA,
-+ gen_rtx_SET (hard_frame_pointer_rtx,
-+ plus_constant (Pmode, stack_pointer_rtx,
-+ size)));
-+ }
-+
-+ if (return_addr_reg_needed_p (sparc_leaf_function_p))
-+ {
-+ rtx o7 = gen_rtx_REG (Pmode, INCOMING_RETURN_ADDR_REGNUM);
-+ rtx i7 = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
-+
-+ insn = emit_move_insn (i7, o7);
-+ RTX_FRAME_RELATED_P (insn) = 1;
-+
-+ add_reg_note (insn, REG_CFA_REGISTER, gen_rtx_SET (i7, o7));
-+
-+ /* Prevent this instruction from ever being considered dead,
-+ even if this function has no epilogue. */
-+ emit_use (i7);
-+ }
-+ }
-+
-+ if (frame_pointer_needed)
-+ {
-+ sparc_frame_base_reg = hard_frame_pointer_rtx;
-+ sparc_frame_base_offset = SPARC_STACK_BIAS;
-+ }
-+ else
-+ {
-+ sparc_frame_base_reg = stack_pointer_rtx;
-+ sparc_frame_base_offset = size + SPARC_STACK_BIAS;
-+ }
-+
-+ if (sparc_n_global_fp_regs > 0)
-+ emit_save_or_restore_global_fp_regs (sparc_frame_base_reg,
-+ sparc_frame_base_offset
-+ - sparc_apparent_frame_size,
-+ SORR_SAVE);
-+
-+ /* Advertise that the data calculated just above are now valid. */
-+ sparc_prologue_data_valid_p = true;
-+}
-+
-+/* This function generates the assembly code for function entry, which boils
-+ down to emitting the necessary .register directives. */
-+
-+static void
-+sparc_asm_function_prologue (FILE *file)
-+{
-+ /* Check that the assumption we made in sparc_expand_prologue is valid. */
-+ if (!TARGET_FLAT)
-+ gcc_assert (sparc_leaf_function_p == crtl->uses_only_leaf_regs);
-+
-+ sparc_output_scratch_registers (file);
-+}
-+
-+/* Expand the function epilogue, either normal or part of a sibcall.
-+ We emit all the instructions except the return or the call. */
-+
-+void
-+sparc_expand_epilogue (bool for_eh)
-+{
-+ HOST_WIDE_INT size = sparc_frame_size;
-+
-+ if (cfun->calls_alloca)
-+ emit_insn (gen_frame_blockage ());
-+
-+ if (sparc_n_global_fp_regs > 0)
-+ emit_save_or_restore_global_fp_regs (sparc_frame_base_reg,
-+ sparc_frame_base_offset
-+ - sparc_apparent_frame_size,
-+ SORR_RESTORE);
-+
-+ if (size == 0 || for_eh)
-+ ; /* do nothing. */
-+ else if (sparc_leaf_function_p)
-+ {
-+ if (size <= 4096)
-+ emit_insn (gen_stack_pointer_inc (GEN_INT (size)));
-+ else if (size <= 8192)
-+ {
-+ emit_insn (gen_stack_pointer_inc (GEN_INT (4096)));
-+ emit_insn (gen_stack_pointer_inc (GEN_INT (size - 4096)));
-+ }
-+ else
-+ {
-+ rtx reg = gen_rtx_REG (Pmode, 1);
-+ emit_move_insn (reg, GEN_INT (size));
-+ emit_insn (gen_stack_pointer_inc (reg));
-+ }
-+ }
-+}
-+
-+/* Expand the function epilogue, either normal or part of a sibcall.
-+ We emit all the instructions except the return or the call. */
-+
-+void
-+sparc_flat_expand_epilogue (bool for_eh)
-+{
-+ HOST_WIDE_INT size = sparc_frame_size;
-+
-+ if (sparc_n_global_fp_regs > 0)
-+ emit_save_or_restore_global_fp_regs (sparc_frame_base_reg,
-+ sparc_frame_base_offset
-+ - sparc_apparent_frame_size,
-+ SORR_RESTORE);
-+
-+ /* If we have a frame pointer, we'll need both to restore it before the
-+ frame is destroyed and use its current value in destroying the frame.
-+ Since we don't have an atomic way to do that in the flat window model,
-+ we save the current value into a temporary register (%g1). */
-+ if (frame_pointer_needed && !for_eh)
-+ emit_move_insn (gen_rtx_REG (Pmode, 1), hard_frame_pointer_rtx);
-+
-+ if (return_addr_reg_needed_p (sparc_leaf_function_p))
-+ emit_move_insn (gen_rtx_REG (Pmode, INCOMING_RETURN_ADDR_REGNUM),
-+ gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM));
-+
-+ if (sparc_save_local_in_regs_p)
-+ emit_save_or_restore_local_in_regs (sparc_frame_base_reg,
-+ sparc_frame_base_offset,
-+ SORR_RESTORE);
-+
-+ if (size == 0 || for_eh)
-+ ; /* do nothing. */
-+ else if (frame_pointer_needed)
-+ {
-+ /* Make sure the frame is destroyed after everything else is done. */
-+ emit_insn (gen_blockage ());
-+
-+ emit_move_insn (stack_pointer_rtx, gen_rtx_REG (Pmode, 1));
-+ }
-+ else
-+ {
-+ /* Likewise. */
-+ emit_insn (gen_blockage ());
-+
-+ if (size <= 4096)
-+ emit_insn (gen_stack_pointer_inc (GEN_INT (size)));
-+ else if (size <= 8192)
-+ {
-+ emit_insn (gen_stack_pointer_inc (GEN_INT (4096)));
-+ emit_insn (gen_stack_pointer_inc (GEN_INT (size - 4096)));
-+ }
-+ else
-+ {
-+ rtx reg = gen_rtx_REG (Pmode, 1);
-+ emit_move_insn (reg, GEN_INT (size));
-+ emit_insn (gen_stack_pointer_inc (reg));
-+ }
-+ }
-+}
-+
-+/* Return true if it is appropriate to emit `return' instructions in the
-+ body of a function. */
-+
-+bool
-+sparc_can_use_return_insn_p (void)
-+{
-+ return sparc_prologue_data_valid_p
-+ && sparc_n_global_fp_regs == 0
-+ && TARGET_FLAT
-+ ? (sparc_frame_size == 0 && !sparc_save_local_in_regs_p)
-+ : (sparc_frame_size == 0 || !sparc_leaf_function_p);
-+}
-+
-+/* This function generates the assembly code for function exit. */
-+
-+static void
-+sparc_asm_function_epilogue (FILE *file)
-+{
-+ /* If the last two instructions of a function are "call foo; dslot;"
-+ the return address might point to the first instruction in the next
-+ function and we have to output a dummy nop for the sake of sane
-+ backtraces in such cases. This is pointless for sibling calls since
-+ the return address is explicitly adjusted. */
-+
-+ rtx_insn *insn = get_last_insn ();
-+
-+ rtx last_real_insn = prev_real_insn (insn);
-+ if (last_real_insn
-+ && NONJUMP_INSN_P (last_real_insn)
-+ && GET_CODE (PATTERN (last_real_insn)) == SEQUENCE)
-+ last_real_insn = XVECEXP (PATTERN (last_real_insn), 0, 0);
-+
-+ if (last_real_insn
-+ && CALL_P (last_real_insn)
-+ && !SIBLING_CALL_P (last_real_insn))
-+ fputs("\tnop\n", file);
-+
-+ sparc_output_deferred_case_vectors ();
-+}
-+
-+/* Output a 'restore' instruction. */
-+
-+static void
-+output_restore (rtx pat)
-+{
-+ rtx operands[3];
-+
-+ if (! pat)
-+ {
-+ fputs ("\t restore\n", asm_out_file);
-+ return;
-+ }
-+
-+ gcc_assert (GET_CODE (pat) == SET);
-+
-+ operands[0] = SET_DEST (pat);
-+ pat = SET_SRC (pat);
-+
-+ switch (GET_CODE (pat))
-+ {
-+ case PLUS:
-+ operands[1] = XEXP (pat, 0);
-+ operands[2] = XEXP (pat, 1);
-+ output_asm_insn (" restore %r1, %2, %Y0", operands);
-+ break;
-+ case LO_SUM:
-+ operands[1] = XEXP (pat, 0);
-+ operands[2] = XEXP (pat, 1);
-+ output_asm_insn (" restore %r1, %%lo(%a2), %Y0", operands);
-+ break;
-+ case ASHIFT:
-+ operands[1] = XEXP (pat, 0);
-+ gcc_assert (XEXP (pat, 1) == const1_rtx);
-+ output_asm_insn (" restore %r1, %r1, %Y0", operands);
-+ break;
-+ default:
-+ operands[1] = pat;
-+ output_asm_insn (" restore %%g0, %1, %Y0", operands);
-+ break;
-+ }
-+}
-+
-+/* Output a return. */
-+
-+const char *
-+output_return (rtx_insn *insn)
-+{
-+ if (crtl->calls_eh_return)
-+ {
-+ /* If the function uses __builtin_eh_return, the eh_return
-+ machinery occupies the delay slot. */
-+ gcc_assert (!final_sequence);
-+
-+ if (flag_delayed_branch)
-+ {
-+ if (!TARGET_FLAT && TARGET_V9)
-+ fputs ("\treturn\t%i7+8\n", asm_out_file);
-+ else
-+ {
-+ if (!TARGET_FLAT)
-+ fputs ("\trestore\n", asm_out_file);
-+
-+ fputs ("\tjmp\t%o7+8\n", asm_out_file);
-+ }
-+
-+ fputs ("\t add\t%sp, %g1, %sp\n", asm_out_file);
-+ }
-+ else
-+ {
-+ if (!TARGET_FLAT)
-+ fputs ("\trestore\n", asm_out_file);
-+
-+ fputs ("\tadd\t%sp, %g1, %sp\n", asm_out_file);
-+ fputs ("\tjmp\t%o7+8\n\t nop\n", asm_out_file);
-+ }
-+ }
-+ else if (sparc_leaf_function_p || TARGET_FLAT)
-+ {
-+ /* This is a leaf or flat function so we don't have to bother restoring
-+ the register window, which frees us from dealing with the convoluted
-+ semantics of restore/return. We simply output the jump to the
-+ return address and the insn in the delay slot (if any). */
-+
-+ return "jmp\t%%o7+%)%#";
-+ }
-+ else
-+ {
-+ /* This is a regular function so we have to restore the register window.
-+ We may have a pending insn for the delay slot, which will be either
-+ combined with the 'restore' instruction or put in the delay slot of
-+ the 'return' instruction. */
-+
-+ if (final_sequence)
-+ {
-+ rtx_insn *delay;
-+ rtx pat;
-+
-+ delay = NEXT_INSN (insn);
-+ gcc_assert (delay);
-+
-+ pat = PATTERN (delay);
-+
-+ if (TARGET_V9 && ! epilogue_renumber (&pat, 1))
-+ {
-+ epilogue_renumber (&pat, 0);
-+ return "return\t%%i7+%)%#";
-+ }
-+ else
-+ {
-+ output_asm_insn ("jmp\t%%i7+%)", NULL);
-+
-+ /* We're going to output the insn in the delay slot manually.
-+ Make sure to output its source location first. */
-+ PATTERN (delay) = gen_blockage ();
-+ INSN_CODE (delay) = -1;
-+ final_scan_insn (delay, asm_out_file, optimize, 0, NULL);
-+ INSN_LOCATION (delay) = UNKNOWN_LOCATION;
-+
-+ output_restore (pat);
-+ }
-+ }
-+ else
-+ {
-+ /* The delay slot is empty. */
-+ if (TARGET_V9)
-+ return "return\t%%i7+%)\n\t nop";
-+ else if (flag_delayed_branch)
-+ return "jmp\t%%i7+%)\n\t restore";
-+ else
-+ return "restore\n\tjmp\t%%o7+%)\n\t nop";
-+ }
-+ }
-+
-+ return "";
-+}
-+
-+/* Output a sibling call. */
-+
-+const char *
-+output_sibcall (rtx_insn *insn, rtx call_operand)
-+{
-+ rtx operands[1];
-+
-+ gcc_assert (flag_delayed_branch);
-+
-+ operands[0] = call_operand;
-+
-+ if (sparc_leaf_function_p || TARGET_FLAT)
-+ {
-+ /* This is a leaf or flat function so we don't have to bother restoring
-+ the register window. We simply output the jump to the function and
-+ the insn in the delay slot (if any). */
-+
-+ gcc_assert (!(LEAF_SIBCALL_SLOT_RESERVED_P && final_sequence));
-+
-+ if (final_sequence)
-+ output_asm_insn ("sethi\t%%hi(%a0), %%g1\n\tjmp\t%%g1 + %%lo(%a0)%#",
-+ operands);
-+ else
-+ /* Use or with rs2 %%g0 instead of mov, so that as/ld can optimize
-+ it into branch if possible. */
-+ output_asm_insn ("or\t%%o7, %%g0, %%g1\n\tcall\t%a0, 0\n\t or\t%%g1, %%g0, %%o7",
-+ operands);
-+ }
-+ else
-+ {
-+ /* This is a regular function so we have to restore the register window.
-+ We may have a pending insn for the delay slot, which will be combined
-+ with the 'restore' instruction. */
-+
-+ output_asm_insn ("call\t%a0, 0", operands);
-+
-+ if (final_sequence)
-+ {
-+ rtx_insn *delay;
-+ rtx pat;
-+
-+ delay = NEXT_INSN (insn);
-+ gcc_assert (delay);
-+
-+ pat = PATTERN (delay);
-+
-+ /* We're going to output the insn in the delay slot manually.
-+ Make sure to output its source location first. */
-+ PATTERN (delay) = gen_blockage ();
-+ INSN_CODE (delay) = -1;
-+ final_scan_insn (delay, asm_out_file, optimize, 0, NULL);
-+ INSN_LOCATION (delay) = UNKNOWN_LOCATION;
-+
-+ output_restore (pat);
-+ }
-+ else
-+ output_restore (NULL_RTX);
-+ }
-+
-+ return "";
-+}
-+
-+/* Functions for handling argument passing.
-+
-+ For 32-bit, the first 6 args are normally in registers and the rest are
-+ pushed. Any arg that starts within the first 6 words is at least
-+ partially passed in a register unless its data type forbids.
-+
-+ For 64-bit, the argument registers are laid out as an array of 16 elements
-+ and arguments are added sequentially. The first 6 int args and up to the
-+ first 16 fp args (depending on size) are passed in regs.
-+
-+ Slot Stack Integral Float Float in structure Double Long Double
-+ ---- ----- -------- ----- ------------------ ------ -----------
-+ 15 [SP+248] %f31 %f30,%f31 %d30
-+ 14 [SP+240] %f29 %f28,%f29 %d28 %q28
-+ 13 [SP+232] %f27 %f26,%f27 %d26
-+ 12 [SP+224] %f25 %f24,%f25 %d24 %q24
-+ 11 [SP+216] %f23 %f22,%f23 %d22
-+ 10 [SP+208] %f21 %f20,%f21 %d20 %q20
-+ 9 [SP+200] %f19 %f18,%f19 %d18
-+ 8 [SP+192] %f17 %f16,%f17 %d16 %q16
-+ 7 [SP+184] %f15 %f14,%f15 %d14
-+ 6 [SP+176] %f13 %f12,%f13 %d12 %q12
-+ 5 [SP+168] %o5 %f11 %f10,%f11 %d10
-+ 4 [SP+160] %o4 %f9 %f8,%f9 %d8 %q8
-+ 3 [SP+152] %o3 %f7 %f6,%f7 %d6
-+ 2 [SP+144] %o2 %f5 %f4,%f5 %d4 %q4
-+ 1 [SP+136] %o1 %f3 %f2,%f3 %d2
-+ 0 [SP+128] %o0 %f1 %f0,%f1 %d0 %q0
-+
-+ Here SP = %sp if -mno-stack-bias or %sp+stack_bias otherwise.
-+
-+ Integral arguments are always passed as 64-bit quantities appropriately
-+ extended.
-+
-+ Passing of floating point values is handled as follows.
-+ If a prototype is in scope:
-+ If the value is in a named argument (i.e. not a stdarg function or a
-+ value not part of the `...') then the value is passed in the appropriate
-+ fp reg.
-+ If the value is part of the `...' and is passed in one of the first 6
-+ slots then the value is passed in the appropriate int reg.
-+ If the value is part of the `...' and is not passed in one of the first 6
-+ slots then the value is passed in memory.
-+ If a prototype is not in scope:
-+ If the value is one of the first 6 arguments the value is passed in the
-+ appropriate integer reg and the appropriate fp reg.
-+ If the value is not one of the first 6 arguments the value is passed in
-+ the appropriate fp reg and in memory.
-+
-+
-+ Summary of the calling conventions implemented by GCC on the SPARC:
-+
-+ 32-bit ABI:
-+ size argument return value
-+
-+ small integer <4 int. reg. int. reg.
-+ word 4 int. reg. int. reg.
-+ double word 8 int. reg. int. reg.
-+
-+ _Complex small integer <8 int. reg. int. reg.
-+ _Complex word 8 int. reg. int. reg.
-+ _Complex double word 16 memory int. reg.
-+
-+ vector integer <=8 int. reg. FP reg.
-+ vector integer >8 memory memory
-+
-+ float 4 int. reg. FP reg.
-+ double 8 int. reg. FP reg.
-+ long double 16 memory memory
-+
-+ _Complex float 8 memory FP reg.
-+ _Complex double 16 memory FP reg.
-+ _Complex long double 32 memory FP reg.
-+
-+ vector float any memory memory
-+
-+ aggregate any memory memory
-+
-+
-+
-+ 64-bit ABI:
-+ size argument return value
-+
-+ small integer <8 int. reg. int. reg.
-+ word 8 int. reg. int. reg.
-+ double word 16 int. reg. int. reg.
-+
-+ _Complex small integer <16 int. reg. int. reg.
-+ _Complex word 16 int. reg. int. reg.
-+ _Complex double word 32 memory int. reg.
-+
-+ vector integer <=16 FP reg. FP reg.
-+ vector integer 16<s<=32 memory FP reg.
-+ vector integer >32 memory memory
-+
-+ float 4 FP reg. FP reg.
-+ double 8 FP reg. FP reg.
-+ long double 16 FP reg. FP reg.
-+
-+ _Complex float 8 FP reg. FP reg.
-+ _Complex double 16 FP reg. FP reg.
-+ _Complex long double 32 memory FP reg.
-+
-+ vector float <=16 FP reg. FP reg.
-+ vector float 16<s<=32 memory FP reg.
-+ vector float >32 memory memory
-+
-+ aggregate <=16 reg. reg.
-+ aggregate 16<s<=32 memory reg.
-+ aggregate >32 memory memory
-+
-+
-+
-+Note #1: complex floating-point types follow the extended SPARC ABIs as
-+implemented by the Sun compiler.
-+
-+Note #2: integer vector types follow the scalar floating-point types
-+conventions to match what is implemented by the Sun VIS SDK.
-+
-+Note #3: floating-point vector types follow the aggregate types
-+conventions. */
-+
-+
-+/* Maximum number of int regs for args. */
-+#define SPARC_INT_ARG_MAX 6
-+/* Maximum number of fp regs for args. */
-+#define SPARC_FP_ARG_MAX 16
-+/* Number of words (partially) occupied for a given size in units. */
-+#define CEIL_NWORDS(SIZE) CEIL((SIZE), UNITS_PER_WORD)
-+
-+/* Handle the INIT_CUMULATIVE_ARGS macro.
-+ Initialize a variable CUM of type CUMULATIVE_ARGS
-+ for a call to a function whose data type is FNTYPE.
-+ For a library call, FNTYPE is 0. */
-+
-+void
-+init_cumulative_args (struct sparc_args *cum, tree fntype, rtx, tree)
-+{
-+ cum->words = 0;
-+ cum->prototype_p = fntype && prototype_p (fntype);
-+ cum->libcall_p = !fntype;
-+}
-+
-+/* Handle promotion of pointer and integer arguments. */
-+
-+static machine_mode
-+sparc_promote_function_mode (const_tree type, machine_mode mode,
-+ int *punsignedp, const_tree, int)
-+{
-+ if (type && POINTER_TYPE_P (type))
-+ {
-+ *punsignedp = POINTERS_EXTEND_UNSIGNED;
-+ return Pmode;
-+ }
-+
-+ /* Integral arguments are passed as full words, as per the ABI. */
-+ if (GET_MODE_CLASS (mode) == MODE_INT
-+ && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
-+ return word_mode;
-+
-+ return mode;
-+}
-+
-+/* Handle the TARGET_STRICT_ARGUMENT_NAMING target hook. */
-+
-+static bool
-+sparc_strict_argument_naming (cumulative_args_t ca ATTRIBUTE_UNUSED)
-+{
-+ return TARGET_ARCH64 ? true : false;
-+}
-+
-+/* Handle the TARGET_PASS_BY_REFERENCE target hook.
-+ Specify whether to pass the argument by reference. */
-+
-+static bool
-+sparc_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
-+{
-+ tree type = arg.type;
-+ machine_mode mode = arg.mode;
-+ if (TARGET_ARCH32)
-+ /* Original SPARC 32-bit ABI says that structures and unions,
-+ and quad-precision floats are passed by reference.
-+ All other base types are passed in registers.
-+
-+ Extended ABI (as implemented by the Sun compiler) says that all
-+ complex floats are passed by reference. Pass complex integers
-+ in registers up to 8 bytes. More generally, enforce the 2-word
-+ cap for passing arguments in registers.
-+
-+ Vector ABI (as implemented by the Sun VIS SDK) says that integer
-+ vectors are passed like floats of the same size, that is in
-+ registers up to 8 bytes. Pass all vector floats by reference
-+ like structure and unions. */
-+ return ((type && (AGGREGATE_TYPE_P (type) || VECTOR_FLOAT_TYPE_P (type)))
-+ || mode == SCmode
-+ /* Catch CDImode, TFmode, DCmode and TCmode. */
-+ || GET_MODE_SIZE (mode) > 8
-+ || (type
-+ && VECTOR_TYPE_P (type)
-+ && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8));
-+ else
-+ /* Original SPARC 64-bit ABI says that structures and unions
-+ smaller than 16 bytes are passed in registers, as well as
-+ all other base types.
-+
-+ Extended ABI (as implemented by the Sun compiler) says that
-+ complex floats are passed in registers up to 16 bytes. Pass
-+ all complex integers in registers up to 16 bytes. More generally,
-+ enforce the 2-word cap for passing arguments in registers.
-+
-+ Vector ABI (as implemented by the Sun VIS SDK) says that integer
-+ vectors are passed like floats of the same size, that is in
-+ registers (up to 16 bytes). Pass all vector floats like structure
-+ and unions. */
-+ return ((type
-+ && (AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type))
-+ && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 16)
-+ /* Catch CTImode and TCmode. */
-+ || GET_MODE_SIZE (mode) > 16);
-+}
-+
-+/* Traverse the record TYPE recursively and call FUNC on its fields.
-+ NAMED is true if this is for a named parameter. DATA is passed
-+ to FUNC for each field. OFFSET is the starting position and
-+ PACKED is true if we are inside a packed record. */
-+
-+template <typename T, void Func (const_tree, int, bool, T*)>
-+static void
-+traverse_record_type (const_tree type, bool named, T *data,
-+ int offset = 0, bool packed = false)
-+{
-+ /* The ABI obviously doesn't specify how packed structures are passed.
-+ These are passed in integer regs if possible, otherwise memory. */
-+ if (!packed)
-+ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
-+ if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field))
-+ {
-+ packed = true;
-+ break;
-+ }
-+
-+ /* Walk the real fields, but skip those with no size or a zero size.
-+ ??? Fields with variable offset are handled as having zero offset. */
-+ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
-+ if (TREE_CODE (field) == FIELD_DECL)
-+ {
-+ if (!DECL_SIZE (field) || integer_zerop (DECL_SIZE (field)))
-+ continue;
-+
-+ int bitpos = offset;
-+ if (TREE_CODE (DECL_FIELD_OFFSET (field)) == INTEGER_CST)
-+ bitpos += int_bit_position (field);
-+
-+ tree field_type = TREE_TYPE (field);
-+ if (TREE_CODE (field_type) == RECORD_TYPE)
-+ traverse_record_type<T, Func> (field_type, named, data, bitpos,
-+ packed);
-+ else
-+ {
-+ const bool fp_type
-+ = FLOAT_TYPE_P (field_type) || VECTOR_TYPE_P (field_type);
-+ Func (field, bitpos, fp_type && named && !packed && TARGET_FPU,
-+ data);
-+ }
-+ }
-+}
-+
-+/* Handle recursive register classifying for structure layout. */
-+
-+typedef struct
-+{
-+ bool fp_regs; /* true if field eligible to FP registers. */
-+ bool fp_regs_in_first_word; /* true if such field in first word. */
-+} classify_data_t;
-+
-+/* A subroutine of function_arg_slotno. Classify the field. */
-+
-+inline void
-+classify_registers (const_tree, int bitpos, bool fp, classify_data_t *data)
-+{
-+ if (fp)
-+ {
-+ data->fp_regs = true;
-+ if (bitpos < BITS_PER_WORD)
-+ data->fp_regs_in_first_word = true;
-+ }
-+}
-+
-+/* Compute the slot number to pass an argument in.
-+ Return the slot number or -1 if passing on the stack.
-+
-+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
-+ the preceding args and about the function being called.
-+ MODE is the argument's machine mode.
-+ TYPE is the data type of the argument (as a tree).
-+ This is null for libcalls where that information may
-+ not be available.
-+ NAMED is nonzero if this argument is a named parameter
-+ (otherwise it is an extra parameter matching an ellipsis).
-+ INCOMING is zero for FUNCTION_ARG, nonzero for FUNCTION_INCOMING_ARG.
-+ *PREGNO records the register number to use if scalar type.
-+ *PPADDING records the amount of padding needed in words. */
-+
-+static int
-+function_arg_slotno (const struct sparc_args *cum, machine_mode mode,
-+ const_tree type, bool named, bool incoming,
-+ int *pregno, int *ppadding)
-+{
-+ const int regbase
-+ = incoming ? SPARC_INCOMING_INT_ARG_FIRST : SPARC_OUTGOING_INT_ARG_FIRST;
-+ int slotno = cum->words, regno;
-+ enum mode_class mclass = GET_MODE_CLASS (mode);
-+
-+ /* Silence warnings in the callers. */
-+ *pregno = -1;
-+ *ppadding = -1;
-+
-+ if (type && TREE_ADDRESSABLE (type))
-+ return -1;
-+
-+ /* In 64-bit mode, objects requiring 16-byte alignment get it. */
-+ if (TARGET_ARCH64
-+ && (type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode)) >= 128
-+ && (slotno & 1) != 0)
-+ {
-+ slotno++;
-+ *ppadding = 1;
-+ }
-+ else
-+ *ppadding = 0;
-+
-+ /* Vector types deserve special treatment because they are polymorphic wrt
-+ their mode, depending upon whether VIS instructions are enabled. */
-+ if (type && VECTOR_TYPE_P (type))
-+ {
-+ if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE)
-+ {
-+ /* The SPARC port defines no floating-point vector modes. */
-+ gcc_assert (mode == BLKmode);
-+ }
-+ else
-+ {
-+ /* Integer vector types should either have a vector
-+ mode or an integral mode, because we are guaranteed
-+ by pass_by_reference that their size is not greater
-+ than 16 bytes and TImode is 16-byte wide. */
-+ gcc_assert (mode != BLKmode);
-+
-+ /* Integer vectors are handled like floats as per
-+ the Sun VIS SDK. */
-+ mclass = MODE_FLOAT;
-+ }
-+ }
-+
-+ switch (mclass)
-+ {
-+ case MODE_FLOAT:
-+ case MODE_COMPLEX_FLOAT:
-+ case MODE_VECTOR_INT:
-+ if (TARGET_ARCH64 && TARGET_FPU && named)
-+ {
-+ /* If all arg slots are filled, then must pass on stack. */
-+ if (slotno >= SPARC_FP_ARG_MAX)
-+ return -1;
-+
-+ regno = SPARC_FP_ARG_FIRST + slotno * 2;
-+ /* Arguments filling only one single FP register are
-+ right-justified in the outer double FP register. */
-+ if (GET_MODE_SIZE (mode) <= 4)
-+ regno++;
-+ break;
-+ }
-+ /* fallthrough */
-+
-+ case MODE_INT:
-+ case MODE_COMPLEX_INT:
-+ /* If all arg slots are filled, then must pass on stack. */
-+ if (slotno >= SPARC_INT_ARG_MAX)
-+ return -1;
-+
-+ regno = regbase + slotno;
-+ break;
-+
-+ case MODE_RANDOM:
-+ /* MODE is VOIDmode when generating the actual call. */
-+ if (mode == VOIDmode)
-+ return -1;
-+
-+ if (TARGET_64BIT && TARGET_FPU && named
-+ && type
-+ && (TREE_CODE (type) == RECORD_TYPE || VECTOR_TYPE_P (type)))
-+ {
-+ /* If all arg slots are filled, then must pass on stack. */
-+ if (slotno >= SPARC_FP_ARG_MAX)
-+ return -1;
-+
-+ if (TREE_CODE (type) == RECORD_TYPE)
-+ {
-+ classify_data_t data = { false, false };
-+ traverse_record_type<classify_data_t, classify_registers>
-+ (type, named, &data);
-+
-+ if (data.fp_regs)
-+ {
-+ /* If all FP slots are filled except for the last one and
-+ there is no FP field in the first word, then must pass
-+ on stack. */
-+ if (slotno >= SPARC_FP_ARG_MAX - 1
-+ && !data.fp_regs_in_first_word)
-+ return -1;
-+ }
-+ else
-+ {
-+ /* If all int slots are filled, then must pass on stack. */
-+ if (slotno >= SPARC_INT_ARG_MAX)
-+ return -1;
-+ }
-+
-+ /* PREGNO isn't set since both int and FP regs can be used. */
-+ return slotno;
-+ }
-+
-+ regno = SPARC_FP_ARG_FIRST + slotno * 2;
-+ }
-+ else
-+ {
-+ /* If all arg slots are filled, then must pass on stack. */
-+ if (slotno >= SPARC_INT_ARG_MAX)
-+ return -1;
-+
-+ regno = regbase + slotno;
-+ }
-+ break;
-+
-+ default :
-+ gcc_unreachable ();
-+ }
-+
-+ *pregno = regno;
-+ return slotno;
-+}
-+
-+/* Handle recursive register counting/assigning for structure layout. */
-+
-+typedef struct
-+{
-+ int slotno; /* slot number of the argument. */
-+ int regbase; /* regno of the base register. */
-+ int intoffset; /* offset of the first pending integer field. */
-+ int nregs; /* number of words passed in registers. */
-+ bool stack; /* true if part of the argument is on the stack. */
-+ rtx ret; /* return expression being built. */
-+} assign_data_t;
-+
-+/* A subroutine of function_arg_record_value. Compute the number of integer
-+ registers to be assigned between PARMS->intoffset and BITPOS. Return
-+ true if at least one integer register is assigned or false otherwise. */
-+
-+static bool
-+compute_int_layout (int bitpos, assign_data_t *data, int *pnregs)
-+{
-+ if (data->intoffset < 0)
-+ return false;
-+
-+ const int intoffset = data->intoffset;
-+ data->intoffset = -1;
-+
-+ const int this_slotno = data->slotno + intoffset / BITS_PER_WORD;
-+ const unsigned int startbit = ROUND_DOWN (intoffset, BITS_PER_WORD);
-+ const unsigned int endbit = ROUND_UP (bitpos, BITS_PER_WORD);
-+ int nregs = (endbit - startbit) / BITS_PER_WORD;
-+
-+ if (nregs > 0 && nregs > SPARC_INT_ARG_MAX - this_slotno)
-+ {
-+ nregs = SPARC_INT_ARG_MAX - this_slotno;
-+
-+ /* We need to pass this field (partly) on the stack. */
-+ data->stack = 1;
-+ }
-+
-+ if (nregs <= 0)
-+ return false;
-+
-+ *pnregs = nregs;
-+ return true;
-+}
-+
-+/* A subroutine of function_arg_record_value. Compute the number and the mode
-+ of the FP registers to be assigned for FIELD. Return true if at least one
-+ FP register is assigned or false otherwise. */
-+
-+static bool
-+compute_fp_layout (const_tree field, int bitpos, assign_data_t *data,
-+ int *pnregs, machine_mode *pmode)
-+{
-+ const int this_slotno = data->slotno + bitpos / BITS_PER_WORD;
-+ machine_mode mode = DECL_MODE (field);
-+ int nregs, nslots;
-+
-+ /* Slots are counted as words while regs are counted as having the size of
-+ the (inner) mode. */
-+ if (VECTOR_TYPE_P (TREE_TYPE (field)) && mode == BLKmode)
-+ {
-+ mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (field)));
-+ nregs = TYPE_VECTOR_SUBPARTS (TREE_TYPE (field));
-+ }
-+ else if (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE)
-+ {
-+ mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (field)));
-+ nregs = 2;
-+ }
-+ else
-+ nregs = 1;
-+
-+ nslots = CEIL_NWORDS (nregs * GET_MODE_SIZE (mode));
-+
-+ if (nslots > SPARC_FP_ARG_MAX - this_slotno)
-+ {
-+ nslots = SPARC_FP_ARG_MAX - this_slotno;
-+ nregs = (nslots * UNITS_PER_WORD) / GET_MODE_SIZE (mode);
-+
-+ /* We need to pass this field (partly) on the stack. */
-+ data->stack = 1;
-+
-+ if (nregs <= 0)
-+ return false;
-+ }
-+
-+ *pnregs = nregs;
-+ *pmode = mode;
-+ return true;
-+}
-+
-+/* A subroutine of function_arg_record_value. Count the number of registers
-+ to be assigned for FIELD and between PARMS->intoffset and BITPOS. */
-+
-+inline void
-+count_registers (const_tree field, int bitpos, bool fp, assign_data_t *data)
-+{
-+ if (fp)
-+ {
-+ int nregs;
-+ machine_mode mode;
-+
-+ if (compute_int_layout (bitpos, data, &nregs))
-+ data->nregs += nregs;
-+
-+ if (compute_fp_layout (field, bitpos, data, &nregs, &mode))
-+ data->nregs += nregs;
-+ }
-+ else
-+ {
-+ if (data->intoffset < 0)
-+ data->intoffset = bitpos;
-+ }
-+}
-+
-+/* A subroutine of function_arg_record_value. Assign the bits of the
-+ structure between PARMS->intoffset and BITPOS to integer registers. */
-+
-+static void
-+assign_int_registers (int bitpos, assign_data_t *data)
-+{
-+ int intoffset = data->intoffset;
-+ machine_mode mode;
-+ int nregs;
-+
-+ if (!compute_int_layout (bitpos, data, &nregs))
-+ return;
-+
-+ /* If this is the trailing part of a word, only load that much into
-+ the register. Otherwise load the whole register. Note that in
-+ the latter case we may pick up unwanted bits. It's not a problem
-+ at the moment but may wish to revisit. */
-+ if (intoffset % BITS_PER_WORD != 0)
-+ mode = smallest_int_mode_for_size (BITS_PER_WORD
-+ - intoffset % BITS_PER_WORD);
-+ else
-+ mode = word_mode;
-+
-+ const int this_slotno = data->slotno + intoffset / BITS_PER_WORD;
-+ unsigned int regno = data->regbase + this_slotno;
-+ intoffset /= BITS_PER_UNIT;
-+
-+ do
-+ {
-+ rtx reg = gen_rtx_REG (mode, regno);
-+ XVECEXP (data->ret, 0, data->stack + data->nregs)
-+ = gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (intoffset));
-+ data->nregs += 1;
-+ mode = word_mode;
-+ regno += 1;
-+ intoffset = (intoffset | (UNITS_PER_WORD - 1)) + 1;
-+ }
-+ while (--nregs > 0);
-+}
-+
-+/* A subroutine of function_arg_record_value. Assign FIELD at position
-+ BITPOS to FP registers. */
-+
-+static void
-+assign_fp_registers (const_tree field, int bitpos, assign_data_t *data)
-+{
-+ int nregs;
-+ machine_mode mode;
-+
-+ if (!compute_fp_layout (field, bitpos, data, &nregs, &mode))
-+ return;
-+
-+ const int this_slotno = data->slotno + bitpos / BITS_PER_WORD;
-+ int regno = SPARC_FP_ARG_FIRST + this_slotno * 2;
-+ if (GET_MODE_SIZE (mode) <= 4 && (bitpos & 32) != 0)
-+ regno++;
-+ int pos = bitpos / BITS_PER_UNIT;
-+
-+ do
-+ {
-+ rtx reg = gen_rtx_REG (mode, regno);
-+ XVECEXP (data->ret, 0, data->stack + data->nregs)
-+ = gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (pos));
-+ data->nregs += 1;
-+ regno += GET_MODE_SIZE (mode) / 4;
-+ pos += GET_MODE_SIZE (mode);
-+ }
-+ while (--nregs > 0);
-+}
-+
-+/* A subroutine of function_arg_record_value. Assign FIELD and the bits of
-+ the structure between PARMS->intoffset and BITPOS to registers. */
-+
-+inline void
-+assign_registers (const_tree field, int bitpos, bool fp, assign_data_t *data)
-+{
-+ if (fp)
-+ {
-+ assign_int_registers (bitpos, data);
-+
-+ assign_fp_registers (field, bitpos, data);
-+ }
-+ else
-+ {
-+ if (data->intoffset < 0)
-+ data->intoffset = bitpos;
-+ }
-+}
-+
-+/* Used by function_arg and function_value to implement the complex
-+ conventions of the 64-bit ABI for passing and returning structures.
-+ Return an expression valid as a return value for the FUNCTION_ARG
-+ and TARGET_FUNCTION_VALUE.
-+
-+ TYPE is the data type of the argument (as a tree).
-+ This is null for libcalls where that information may
-+ not be available.
-+ MODE is the argument's machine mode.
-+ SLOTNO is the index number of the argument's slot in the parameter array.
-+ NAMED is true if this argument is a named parameter
-+ (otherwise it is an extra parameter matching an ellipsis).
-+ REGBASE is the regno of the base register for the parameter array. */
-+
-+static rtx
-+function_arg_record_value (const_tree type, machine_mode mode,
-+ int slotno, bool named, int regbase)
-+{
-+ const int size = int_size_in_bytes (type);
-+ assign_data_t data;
-+ int nregs;
-+
-+ data.slotno = slotno;
-+ data.regbase = regbase;
-+
-+ /* Count how many registers we need. */
-+ data.nregs = 0;
-+ data.intoffset = 0;
-+ data.stack = false;
-+ traverse_record_type<assign_data_t, count_registers> (type, named, &data);
-+
-+ /* Take into account pending integer fields. */
-+ if (compute_int_layout (size * BITS_PER_UNIT, &data, &nregs))
-+ data.nregs += nregs;
-+
-+ /* Allocate the vector and handle some annoying special cases. */
-+ nregs = data.nregs;
-+
-+ if (nregs == 0)
-+ {
-+ /* ??? Empty structure has no value? Duh? */
-+ if (size <= 0)
-+ {
-+ /* Though there's nothing really to store, return a word register
-+ anyway so the rest of gcc doesn't go nuts. Returning a PARALLEL
-+ leads to breakage due to the fact that there are zero bytes to
-+ load. */
-+ return gen_rtx_REG (mode, regbase);
-+ }
-+
-+ /* ??? C++ has structures with no fields, and yet a size. Give up
-+ for now and pass everything back in integer registers. */
-+ nregs = CEIL_NWORDS (size);
-+ if (nregs + slotno > SPARC_INT_ARG_MAX)
-+ nregs = SPARC_INT_ARG_MAX - slotno;
-+ }
-+
-+ gcc_assert (nregs > 0);
-+
-+ data.ret = gen_rtx_PARALLEL (mode, rtvec_alloc (data.stack + nregs));
-+
-+ /* If at least one field must be passed on the stack, generate
-+ (parallel [(expr_list (nil) ...) ...]) so that all fields will
-+ also be passed on the stack. We can't do much better because the
-+ semantics of TARGET_ARG_PARTIAL_BYTES doesn't handle the case
-+ of structures for which the fields passed exclusively in registers
-+ are not at the beginning of the structure. */
-+ if (data.stack)
-+ XVECEXP (data.ret, 0, 0)
-+ = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
-+
-+ /* Assign the registers. */
-+ data.nregs = 0;
-+ data.intoffset = 0;
-+ traverse_record_type<assign_data_t, assign_registers> (type, named, &data);
-+
-+ /* Assign pending integer fields. */
-+ assign_int_registers (size * BITS_PER_UNIT, &data);
-+
-+ gcc_assert (data.nregs == nregs);
-+
-+ return data.ret;
-+}
-+
-+/* Used by function_arg and function_value to implement the conventions
-+ of the 64-bit ABI for passing and returning unions.
-+ Return an expression valid as a return value for the FUNCTION_ARG
-+ and TARGET_FUNCTION_VALUE.
-+
-+ SIZE is the size in bytes of the union.
-+ MODE is the argument's machine mode.
-+ SLOTNO is the index number of the argument's slot in the parameter array.
-+ REGNO is the hard register the union will be passed in. */
-+
-+static rtx
-+function_arg_union_value (int size, machine_mode mode, int slotno, int regno)
-+{
-+ unsigned int nwords;
-+
-+ /* See comment in function_arg_record_value for empty structures. */
-+ if (size <= 0)
-+ return gen_rtx_REG (mode, regno);
-+
-+ if (slotno == SPARC_INT_ARG_MAX - 1)
-+ nwords = 1;
-+ else
-+ nwords = CEIL_NWORDS (size);
-+
-+ rtx regs = gen_rtx_PARALLEL (mode, rtvec_alloc (nwords));
-+
-+ /* Unions are passed left-justified. */
-+ for (unsigned int i = 0; i < nwords; i++)
-+ XVECEXP (regs, 0, i)
-+ = gen_rtx_EXPR_LIST (VOIDmode,
-+ gen_rtx_REG (word_mode, regno + i),
-+ GEN_INT (UNITS_PER_WORD * i));
-+
-+ return regs;
-+}
-+
-+/* Used by function_arg and function_value to implement the conventions
-+ of the 64-bit ABI for passing and returning BLKmode vectors.
-+ Return an expression valid as a return value for the FUNCTION_ARG
-+ and TARGET_FUNCTION_VALUE.
-+
-+ SIZE is the size in bytes of the vector.
-+ SLOTNO is the index number of the argument's slot in the parameter array.
-+ NAMED is true if this argument is a named parameter
-+ (otherwise it is an extra parameter matching an ellipsis).
-+ REGNO is the hard register the vector will be passed in. */
-+
-+static rtx
-+function_arg_vector_value (int size, int slotno, bool named, int regno)
-+{
-+ const int mult = (named ? 2 : 1);
-+ unsigned int nwords;
-+
-+ if (slotno == (named ? SPARC_FP_ARG_MAX : SPARC_INT_ARG_MAX) - 1)
-+ nwords = 1;
-+ else
-+ nwords = CEIL_NWORDS (size);
-+
-+ rtx regs = gen_rtx_PARALLEL (BLKmode, rtvec_alloc (nwords));
-+
-+ if (size < UNITS_PER_WORD)
-+ XVECEXP (regs, 0, 0)
-+ = gen_rtx_EXPR_LIST (VOIDmode,
-+ gen_rtx_REG (SImode, regno),
-+ const0_rtx);
-+ else
-+ for (unsigned int i = 0; i < nwords; i++)
-+ XVECEXP (regs, 0, i)
-+ = gen_rtx_EXPR_LIST (VOIDmode,
-+ gen_rtx_REG (word_mode, regno + i * mult),
-+ GEN_INT (i * UNITS_PER_WORD));
-+
-+ return regs;
-+}
-+
-+/* Determine where to put an argument to a function.
-+ Value is zero to push the argument on the stack,
-+ or a hard register in which to store the argument.
-+
-+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
-+ the preceding args and about the function being called.
-+ ARG is a description of the argument.
-+ INCOMING_P is false for TARGET_FUNCTION_ARG, true for
-+ TARGET_FUNCTION_INCOMING_ARG. */
-+
-+static rtx
-+sparc_function_arg_1 (cumulative_args_t cum_v, const function_arg_info &arg,
-+ bool incoming)
-+{
-+ const CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
-+ const int regbase
-+ = incoming ? SPARC_INCOMING_INT_ARG_FIRST : SPARC_OUTGOING_INT_ARG_FIRST;
-+ int slotno, regno, padding;
-+ tree type = arg.type;
-+ machine_mode mode = arg.mode;
-+ enum mode_class mclass = GET_MODE_CLASS (mode);
-+ bool named = arg.named;
-+
-+ slotno
-+ = function_arg_slotno (cum, mode, type, named, incoming, &regno, &padding);
-+ if (slotno == -1)
-+ return 0;
-+
-+ /* Integer vectors are handled like floats as per the Sun VIS SDK. */
-+ if (type && VECTOR_INTEGER_TYPE_P (type))
-+ mclass = MODE_FLOAT;
-+
-+ if (TARGET_ARCH32)
-+ return gen_rtx_REG (mode, regno);
-+
-+ /* Structures up to 16 bytes in size are passed in arg slots on the stack
-+ and are promoted to registers if possible. */
-+ if (type && TREE_CODE (type) == RECORD_TYPE)
-+ {
-+ const int size = int_size_in_bytes (type);
-+ gcc_assert (size <= 16);
-+
-+ return function_arg_record_value (type, mode, slotno, named, regbase);
-+ }
-+
-+ /* Unions up to 16 bytes in size are passed in integer registers. */
-+ else if (type && TREE_CODE (type) == UNION_TYPE)
-+ {
-+ const int size = int_size_in_bytes (type);
-+ gcc_assert (size <= 16);
-+
-+ return function_arg_union_value (size, mode, slotno, regno);
-+ }
-+
-+ /* Floating-point vectors up to 16 bytes are passed in registers. */
-+ else if (type && VECTOR_TYPE_P (type) && mode == BLKmode)
-+ {
-+ const int size = int_size_in_bytes (type);
-+ gcc_assert (size <= 16);
-+
-+ return function_arg_vector_value (size, slotno, named, regno);
-+ }
-+
-+ /* v9 fp args in reg slots beyond the int reg slots get passed in regs
-+ but also have the slot allocated for them.
-+ If no prototype is in scope fp values in register slots get passed
-+ in two places, either fp regs and int regs or fp regs and memory. */
-+ else if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT)
-+ && SPARC_FP_REG_P (regno))
-+ {
-+ rtx reg = gen_rtx_REG (mode, regno);
-+ if (cum->prototype_p || cum->libcall_p)
-+ return reg;
-+ else
-+ {
-+ rtx v0, v1;
-+
-+ if ((regno - SPARC_FP_ARG_FIRST) < SPARC_INT_ARG_MAX * 2)
-+ {
-+ int intreg;
-+
-+ /* On incoming, we don't need to know that the value
-+ is passed in %f0 and %i0, and it confuses other parts
-+ causing needless spillage even on the simplest cases. */
-+ if (incoming)
-+ return reg;
-+
-+ intreg = (SPARC_OUTGOING_INT_ARG_FIRST
-+ + (regno - SPARC_FP_ARG_FIRST) / 2);
-+
-+ v0 = gen_rtx_EXPR_LIST (VOIDmode, reg, const0_rtx);
-+ v1 = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (mode, intreg),
-+ const0_rtx);
-+ return gen_rtx_PARALLEL (mode, gen_rtvec (2, v0, v1));
-+ }
-+ else
-+ {
-+ v0 = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
-+ v1 = gen_rtx_EXPR_LIST (VOIDmode, reg, const0_rtx);
-+ return gen_rtx_PARALLEL (mode, gen_rtvec (2, v0, v1));
-+ }
-+ }
-+ }
-+
-+ /* All other aggregate types are passed in an integer register in a mode
-+ corresponding to the size of the type. */
-+ else if (type && AGGREGATE_TYPE_P (type))
-+ {
-+ const int size = int_size_in_bytes (type);
-+ gcc_assert (size <= 16);
-+
-+ mode = int_mode_for_size (size * BITS_PER_UNIT, 0).else_blk ();
-+ }
-+
-+ return gen_rtx_REG (mode, regno);
-+}
-+
-+/* Handle the TARGET_FUNCTION_ARG target hook. */
-+
-+static rtx
-+sparc_function_arg (cumulative_args_t cum, const function_arg_info &arg)
-+{
-+ return sparc_function_arg_1 (cum, arg, false);
-+}
-+
-+/* Handle the TARGET_FUNCTION_INCOMING_ARG target hook. */
-+
-+static rtx
-+sparc_function_incoming_arg (cumulative_args_t cum,
-+ const function_arg_info &arg)
-+{
-+ return sparc_function_arg_1 (cum, arg, true);
-+}
-+
-+/* For sparc64, objects requiring 16 byte alignment are passed that way. */
-+
-+static unsigned int
-+sparc_function_arg_boundary (machine_mode mode, const_tree type)
-+{
-+ return ((TARGET_ARCH64
-+ && (GET_MODE_ALIGNMENT (mode) == 128
-+ || (type && TYPE_ALIGN (type) == 128)))
-+ ? 128
-+ : PARM_BOUNDARY);
-+}
-+
-+/* For an arg passed partly in registers and partly in memory,
-+ this is the number of bytes of registers used.
-+ For args passed entirely in registers or entirely in memory, zero.
-+
-+ Any arg that starts in the first 6 regs but won't entirely fit in them
-+ needs partial registers on v8. On v9, structures with integer
-+ values in arg slots 5,6 will be passed in %o5 and SP+176, and complex fp
-+ values that begin in the last fp reg [where "last fp reg" varies with the
-+ mode] will be split between that reg and memory. */
-+
-+static int
-+sparc_arg_partial_bytes (cumulative_args_t cum, const function_arg_info &arg)
-+{
-+ int slotno, regno, padding;
-+
-+ /* We pass false for incoming here, it doesn't matter. */
-+ slotno = function_arg_slotno (get_cumulative_args (cum), arg.mode, arg.type,
-+ arg.named, false, &regno, &padding);
-+
-+ if (slotno == -1)
-+ return 0;
-+
-+ if (TARGET_ARCH32)
-+ {
-+ /* We are guaranteed by pass_by_reference that the size of the
-+ argument is not greater than 8 bytes, so we only need to return
-+ one word if the argument is partially passed in registers. */
-+ const int size = GET_MODE_SIZE (arg.mode);
-+
-+ if (size > UNITS_PER_WORD && slotno == SPARC_INT_ARG_MAX - 1)
-+ return UNITS_PER_WORD;
-+ }
-+ else
-+ {
-+ /* We are guaranteed by pass_by_reference that the size of the
-+ argument is not greater than 16 bytes, so we only need to return
-+ one word if the argument is partially passed in registers. */
-+ if (arg.aggregate_type_p ())
-+ {
-+ const int size = int_size_in_bytes (arg.type);
-+
-+ if (size > UNITS_PER_WORD
-+ && (slotno == SPARC_INT_ARG_MAX - 1
-+ || slotno == SPARC_FP_ARG_MAX - 1))
-+ return UNITS_PER_WORD;
-+ }
-+ else if (GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_INT
-+ || ((GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_FLOAT
-+ || (arg.type && VECTOR_TYPE_P (arg.type)))
-+ && !(TARGET_FPU && arg.named)))
-+ {
-+ const int size = (arg.type && VECTOR_FLOAT_TYPE_P (arg.type))
-+ ? int_size_in_bytes (arg.type)
-+ : GET_MODE_SIZE (arg.mode);
-+
-+ if (size > UNITS_PER_WORD && slotno == SPARC_INT_ARG_MAX - 1)
-+ return UNITS_PER_WORD;
-+ }
-+ else if (GET_MODE_CLASS (arg.mode) == MODE_COMPLEX_FLOAT
-+ || (arg.type && VECTOR_TYPE_P (arg.type)))
-+ {
-+ const int size = (arg.type && VECTOR_FLOAT_TYPE_P (arg.type))
-+ ? int_size_in_bytes (arg.type)
-+ : GET_MODE_SIZE (arg.mode);
-+
-+ if (size > UNITS_PER_WORD && slotno == SPARC_FP_ARG_MAX - 1)
-+ return UNITS_PER_WORD;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+/* Handle the TARGET_FUNCTION_ARG_ADVANCE hook.
-+ Update the data in CUM to advance over argument ARG. */
-+
-+static void
-+sparc_function_arg_advance (cumulative_args_t cum_v,
-+ const function_arg_info &arg)
-+{
-+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
-+ tree type = arg.type;
-+ machine_mode mode = arg.mode;
-+ int regno, padding;
-+
-+ /* We pass false for incoming here, it doesn't matter. */
-+ function_arg_slotno (cum, mode, type, arg.named, false, &regno, &padding);
-+
-+ /* If argument requires leading padding, add it. */
-+ cum->words += padding;
-+
-+ if (TARGET_ARCH32)
-+ cum->words += CEIL_NWORDS (GET_MODE_SIZE (mode));
-+ else
-+ {
-+ /* For types that can have BLKmode, get the size from the type. */
-+ if (type && (AGGREGATE_TYPE_P (type) || VECTOR_FLOAT_TYPE_P (type)))
-+ {
-+ const int size = int_size_in_bytes (type);
-+
-+ /* See comment in function_arg_record_value for empty structures. */
-+ if (size <= 0)
-+ cum->words++;
-+ else
-+ cum->words += CEIL_NWORDS (size);
-+ }
-+ else
-+ cum->words += CEIL_NWORDS (GET_MODE_SIZE (mode));
-+ }
-+}
-+
-+/* Implement TARGET_FUNCTION_ARG_PADDING. For the 64-bit ABI structs
-+ are always stored left shifted in their argument slot. */
-+
-+static pad_direction
-+sparc_function_arg_padding (machine_mode mode, const_tree type)
-+{
-+ if (TARGET_ARCH64 && type && AGGREGATE_TYPE_P (type))
-+ return PAD_UPWARD;
-+
-+ /* Fall back to the default. */
-+ return default_function_arg_padding (mode, type);
-+}
-+
-+/* Handle the TARGET_RETURN_IN_MEMORY target hook.
-+ Specify whether to return the return value in memory. */
-+
-+static bool
-+sparc_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
-+{
-+ if (TARGET_ARCH32)
-+ /* Original SPARC 32-bit ABI says that structures and unions, and
-+ quad-precision floats are returned in memory. But note that the
-+ first part is implemented through -fpcc-struct-return being the
-+ default, so here we only implement -freg-struct-return instead.
-+ All other base types are returned in registers.
-+
-+ Extended ABI (as implemented by the Sun compiler) says that
-+ all complex floats are returned in registers (8 FP registers
-+ at most for '_Complex long double'). Return all complex integers
-+ in registers (4 at most for '_Complex long long').
-+
-+ Vector ABI (as implemented by the Sun VIS SDK) says that vector
-+ integers are returned like floats of the same size, that is in
-+ registers up to 8 bytes and in memory otherwise. Return all
-+ vector floats in memory like structure and unions; note that
-+ they always have BLKmode like the latter. */
-+ return (TYPE_MODE (type) == BLKmode
-+ || TYPE_MODE (type) == TFmode
-+ || (TREE_CODE (type) == VECTOR_TYPE
-+ && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8));
-+ else
-+ /* Original SPARC 64-bit ABI says that structures and unions
-+ smaller than 32 bytes are returned in registers, as well as
-+ all other base types.
-+
-+ Extended ABI (as implemented by the Sun compiler) says that all
-+ complex floats are returned in registers (8 FP registers at most
-+ for '_Complex long double'). Return all complex integers in
-+ registers (4 at most for '_Complex TItype').
-+
-+ Vector ABI (as implemented by the Sun VIS SDK) says that vector
-+ integers are returned like floats of the same size, that is in
-+ registers. Return all vector floats like structure and unions;
-+ note that they always have BLKmode like the latter. */
-+ return (TYPE_MODE (type) == BLKmode
-+ && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 32);
-+}
-+
-+/* Handle the TARGET_STRUCT_VALUE target hook.
-+ Return where to find the structure return value address. */
-+
-+static rtx
-+sparc_struct_value_rtx (tree fndecl, int incoming)
-+{
-+ if (TARGET_ARCH64)
-+ return NULL_RTX;
-+ else
-+ {
-+ rtx mem;
-+
-+ if (incoming)
-+ mem = gen_frame_mem (Pmode, plus_constant (Pmode, frame_pointer_rtx,
-+ STRUCT_VALUE_OFFSET));
-+ else
-+ mem = gen_frame_mem (Pmode, plus_constant (Pmode, stack_pointer_rtx,
-+ STRUCT_VALUE_OFFSET));
-+
-+ /* Only follow the SPARC ABI for fixed-size structure returns.
-+ Variable size structure returns are handled per the normal
-+ procedures in GCC. This is enabled by -mstd-struct-return */
-+ if (incoming == 2
-+ && sparc_std_struct_return
-+ && TYPE_SIZE_UNIT (TREE_TYPE (fndecl))
-+ && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (fndecl))) == INTEGER_CST)
-+ {
-+ /* We must check and adjust the return address, as it is optional
-+ as to whether the return object is really provided. */
-+ rtx ret_reg = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
-+ rtx scratch = gen_reg_rtx (SImode);
-+ rtx_code_label *endlab = gen_label_rtx ();
-+
-+ /* Calculate the return object size. */
-+ tree size = TYPE_SIZE_UNIT (TREE_TYPE (fndecl));
-+ rtx size_rtx = GEN_INT (TREE_INT_CST_LOW (size) & 0xfff);
-+ /* Construct a temporary return value. */
-+ rtx temp_val
-+ = assign_stack_local (Pmode, TREE_INT_CST_LOW (size), 0);
-+
-+ /* Implement SPARC 32-bit psABI callee return struct checking:
-+
-+ Fetch the instruction where we will return to and see if
-+ it's an unimp instruction (the most significant 10 bits
-+ will be zero). */
-+ emit_move_insn (scratch, gen_rtx_MEM (SImode,
-+ plus_constant (Pmode,
-+ ret_reg, 8)));
-+ /* Assume the size is valid and pre-adjust. */
-+ emit_insn (gen_add3_insn (ret_reg, ret_reg, GEN_INT (4)));
-+ emit_cmp_and_jump_insns (scratch, size_rtx, EQ, const0_rtx, SImode,
-+ 0, endlab);
-+ emit_insn (gen_sub3_insn (ret_reg, ret_reg, GEN_INT (4)));
-+ /* Write the address of the memory pointed to by temp_val into
-+ the memory pointed to by mem. */
-+ emit_move_insn (mem, XEXP (temp_val, 0));
-+ emit_label (endlab);
-+ }
-+
-+ return mem;
-+ }
-+}
-+
-+/* Handle TARGET_FUNCTION_VALUE, and TARGET_LIBCALL_VALUE target hook.
-+ For v9, function return values are subject to the same rules as arguments,
-+ except that up to 32 bytes may be returned in registers. */
-+
-+static rtx
-+sparc_function_value_1 (const_tree type, machine_mode mode, bool outgoing)
-+{
-+ /* Beware that the two values are swapped here wrt function_arg. */
-+ const int regbase
-+ = outgoing ? SPARC_INCOMING_INT_ARG_FIRST : SPARC_OUTGOING_INT_ARG_FIRST;
-+ enum mode_class mclass = GET_MODE_CLASS (mode);
-+ int regno;
-+
-+ /* Integer vectors are handled like floats as per the Sun VIS SDK.
-+ Note that integer vectors larger than 16 bytes have BLKmode so
-+ they need to be handled like floating-point vectors below. */
-+ if (type && VECTOR_INTEGER_TYPE_P (type) && mode != BLKmode)
-+ mclass = MODE_FLOAT;
-+
-+ if (TARGET_ARCH64 && type)
-+ {
-+ /* Structures up to 32 bytes in size are returned in registers. */
-+ if (TREE_CODE (type) == RECORD_TYPE)
-+ {
-+ const int size = int_size_in_bytes (type);
-+ gcc_assert (size <= 32);
-+
-+ return function_arg_record_value (type, mode, 0, true, regbase);
-+ }
-+
-+ /* Unions up to 32 bytes in size are returned in integer registers. */
-+ else if (TREE_CODE (type) == UNION_TYPE)
-+ {
-+ const int size = int_size_in_bytes (type);
-+ gcc_assert (size <= 32);
-+
-+ return function_arg_union_value (size, mode, 0, regbase);
-+ }
-+
-+ /* Vectors up to 32 bytes are returned in FP registers. */
-+ else if (VECTOR_TYPE_P (type) && mode == BLKmode)
-+ {
-+ const int size = int_size_in_bytes (type);
-+ gcc_assert (size <= 32);
-+
-+ return function_arg_vector_value (size, 0, true, SPARC_FP_ARG_FIRST);
-+ }
-+
-+ /* Objects that require it are returned in FP registers. */
-+ else if (mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT)
-+ ;
-+
-+ /* All other aggregate types are returned in an integer register in a
-+ mode corresponding to the size of the type. */
-+ else if (AGGREGATE_TYPE_P (type))
-+ {
-+ /* All other aggregate types are passed in an integer register
-+ in a mode corresponding to the size of the type. */
-+ const int size = int_size_in_bytes (type);
-+ gcc_assert (size <= 32);
-+
-+ mode = int_mode_for_size (size * BITS_PER_UNIT, 0).else_blk ();
-+
-+ /* ??? We probably should have made the same ABI change in
-+ 3.4.0 as the one we made for unions. The latter was
-+ required by the SCD though, while the former is not
-+ specified, so we favored compatibility and efficiency.
-+
-+ Now we're stuck for aggregates larger than 16 bytes,
-+ because OImode vanished in the meantime. Let's not
-+ try to be unduly clever, and simply follow the ABI
-+ for unions in that case. */
-+ if (mode == BLKmode)
-+ return function_arg_union_value (size, mode, 0, regbase);
-+ else
-+ mclass = MODE_INT;
-+ }
-+
-+ /* We should only have pointer and integer types at this point. This
-+ must match sparc_promote_function_mode. */
-+ else if (mclass == MODE_INT && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
-+ mode = word_mode;
-+ }
-+
-+ /* We should only have pointer and integer types at this point, except with
-+ -freg-struct-return. This must match sparc_promote_function_mode. */
-+ else if (TARGET_ARCH32
-+ && !(type && AGGREGATE_TYPE_P (type))
-+ && mclass == MODE_INT
-+ && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
-+ mode = word_mode;
-+
-+ if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT) && TARGET_FPU)
-+ regno = SPARC_FP_ARG_FIRST;
-+ else
-+ regno = regbase;
-+
-+ return gen_rtx_REG (mode, regno);
-+}
-+
-+/* Handle TARGET_FUNCTION_VALUE.
-+ On the SPARC, the value is found in the first "output" register, but the
-+ called function leaves it in the first "input" register. */
-+
-+static rtx
-+sparc_function_value (const_tree valtype,
-+ const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
-+ bool outgoing)
-+{
-+ return sparc_function_value_1 (valtype, TYPE_MODE (valtype), outgoing);
-+}
-+
-+/* Handle TARGET_LIBCALL_VALUE. */
-+
-+static rtx
-+sparc_libcall_value (machine_mode mode,
-+ const_rtx fun ATTRIBUTE_UNUSED)
-+{
-+ return sparc_function_value_1 (NULL_TREE, mode, false);
-+}
-+
-+/* Handle FUNCTION_VALUE_REGNO_P.
-+ On the SPARC, the first "output" reg is used for integer values, and the
-+ first floating point register is used for floating point values. */
-+
-+static bool
-+sparc_function_value_regno_p (const unsigned int regno)
-+{
-+ return (regno == 8 || (TARGET_FPU && regno == 32));
-+}
-+
-+/* Do what is necessary for `va_start'. We look at the current function
-+ to determine if stdarg or varargs is used and return the address of
-+ the first unnamed parameter. */
-+
-+static rtx
-+sparc_builtin_saveregs (void)
-+{
-+ int first_reg = crtl->args.info.words;
-+ rtx address;
-+ int regno;
-+
-+ for (regno = first_reg; regno < SPARC_INT_ARG_MAX; regno++)
-+ emit_move_insn (gen_rtx_MEM (word_mode,
-+ gen_rtx_PLUS (Pmode,
-+ frame_pointer_rtx,
-+ GEN_INT (FIRST_PARM_OFFSET (0)
-+ + (UNITS_PER_WORD
-+ * regno)))),
-+ gen_rtx_REG (word_mode,
-+ SPARC_INCOMING_INT_ARG_FIRST + regno));
-+
-+ address = gen_rtx_PLUS (Pmode,
-+ frame_pointer_rtx,
-+ GEN_INT (FIRST_PARM_OFFSET (0)
-+ + UNITS_PER_WORD * first_reg));
-+
-+ return address;
-+}
-+
-+/* Implement `va_start' for stdarg. */
-+
-+static void
-+sparc_va_start (tree valist, rtx nextarg)
-+{
-+ nextarg = expand_builtin_saveregs ();
-+ std_expand_builtin_va_start (valist, nextarg);
-+}
-+
-+/* Implement `va_arg' for stdarg. */
-+
-+static tree
-+sparc_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
-+ gimple_seq *post_p)
-+{
-+ HOST_WIDE_INT size, rsize, align;
-+ tree addr, incr;
-+ bool indirect;
-+ tree ptrtype = build_pointer_type (type);
-+
-+ if (pass_va_arg_by_reference (type))
-+ {
-+ indirect = true;
-+ size = rsize = UNITS_PER_WORD;
-+ align = 0;
-+ }
-+ else
-+ {
-+ indirect = false;
-+ size = int_size_in_bytes (type);
-+ rsize = ROUND_UP (size, UNITS_PER_WORD);
-+ align = 0;
-+
-+ if (TARGET_ARCH64)
-+ {
-+ /* For SPARC64, objects requiring 16-byte alignment get it. */
-+ if (TYPE_ALIGN (type) >= 2 * (unsigned) BITS_PER_WORD)
-+ align = 2 * UNITS_PER_WORD;
-+
-+ /* SPARC-V9 ABI states that structures up to 16 bytes in size
-+ are left-justified in their slots. */
-+ if (AGGREGATE_TYPE_P (type))
-+ {
-+ if (size == 0)
-+ size = rsize = UNITS_PER_WORD;
-+ else
-+ size = rsize;
-+ }
-+ }
-+ }
-+
-+ incr = valist;
-+ if (align)
-+ {
-+ incr = fold_build_pointer_plus_hwi (incr, align - 1);
-+ incr = fold_convert (sizetype, incr);
-+ incr = fold_build2 (BIT_AND_EXPR, sizetype, incr,
-+ size_int (-align));
-+ incr = fold_convert (ptr_type_node, incr);
-+ }
-+
-+ gimplify_expr (&incr, pre_p, post_p, is_gimple_val, fb_rvalue);
-+ addr = incr;
-+
-+ if (BYTES_BIG_ENDIAN && size < rsize)
-+ addr = fold_build_pointer_plus_hwi (incr, rsize - size);
-+
-+ if (indirect)
-+ {
-+ addr = fold_convert (build_pointer_type (ptrtype), addr);
-+ addr = build_va_arg_indirect_ref (addr);
-+ }
-+
-+ /* If the address isn't aligned properly for the type, we need a temporary.
-+ FIXME: This is inefficient, usually we can do this in registers. */
-+ else if (align == 0 && TYPE_ALIGN (type) > BITS_PER_WORD)
-+ {
-+ tree tmp = create_tmp_var (type, "va_arg_tmp");
-+ tree dest_addr = build_fold_addr_expr (tmp);
-+ tree copy = build_call_expr (builtin_decl_implicit (BUILT_IN_MEMCPY),
-+ 3, dest_addr, addr, size_int (rsize));
-+ TREE_ADDRESSABLE (tmp) = 1;
-+ gimplify_and_add (copy, pre_p);
-+ addr = dest_addr;
-+ }
-+
-+ else
-+ addr = fold_convert (ptrtype, addr);
-+
-+ incr = fold_build_pointer_plus_hwi (incr, rsize);
-+ gimplify_assign (valist, incr, post_p);
-+
-+ return build_va_arg_indirect_ref (addr);
-+}
-+
-+/* Implement the TARGET_VECTOR_MODE_SUPPORTED_P target hook.
-+ Specify whether the vector mode is supported by the hardware. */
-+
-+static bool
-+sparc_vector_mode_supported_p (machine_mode mode)
-+{
-+ return TARGET_VIS && VECTOR_MODE_P (mode) ? true : false;
-+}
-+
-+/* Implement the TARGET_VECTORIZE_PREFERRED_SIMD_MODE target hook. */
-+
-+static machine_mode
-+sparc_preferred_simd_mode (scalar_mode mode)
-+{
-+ if (TARGET_VIS)
-+ switch (mode)
-+ {
-+ case E_SImode:
-+ return V2SImode;
-+ case E_HImode:
-+ return V4HImode;
-+ case E_QImode:
-+ return V8QImode;
-+
-+ default:;
-+ }
-+
-+ return word_mode;
-+}
-+
-+ /* Implement TARGET_CAN_FOLLOW_JUMP. */
-+
-+static bool
-+sparc_can_follow_jump (const rtx_insn *follower, const rtx_insn *followee)
-+{
-+ /* Do not fold unconditional jumps that have been created for crossing
-+ partition boundaries. */
-+ if (CROSSING_JUMP_P (followee) && !CROSSING_JUMP_P (follower))
-+ return false;
-+
-+ return true;
-+}
-+
-+/* Return the string to output an unconditional branch to LABEL, which is
-+ the operand number of the label.
-+
-+ DEST is the destination insn (i.e. the label), INSN is the source. */
-+
-+const char *
-+output_ubranch (rtx dest, rtx_insn *insn)
-+{
-+ static char string[64];
-+ bool v9_form = false;
-+ int delta;
-+ char *p;
-+
-+ /* Even if we are trying to use cbcond for this, evaluate
-+ whether we can use V9 branches as our backup plan. */
-+ delta = 5000000;
-+ if (!CROSSING_JUMP_P (insn) && INSN_ADDRESSES_SET_P ())
-+ delta = (INSN_ADDRESSES (INSN_UID (dest))
-+ - INSN_ADDRESSES (INSN_UID (insn)));
-+
-+ /* Leave some instructions for "slop". */
-+ if (TARGET_V9 && delta >= -260000 && delta < 260000)
-+ v9_form = true;
-+
-+ if (TARGET_CBCOND)
-+ {
-+ bool emit_nop = emit_cbcond_nop (insn);
-+ bool far = false;
-+ const char *rval;
-+
-+ if (delta < -500 || delta > 500)
-+ far = true;
-+
-+ if (far)
-+ {
-+ if (v9_form)
-+ rval = "ba,a,pt\t%%xcc, %l0";
-+ else
-+ rval = "b,a\t%l0";
-+ }
-+ else
-+ {
-+ if (emit_nop)
-+ rval = "cwbe\t%%g0, %%g0, %l0\n\tnop";
-+ else
-+ rval = "cwbe\t%%g0, %%g0, %l0";
-+ }
-+ return rval;
-+ }
-+
-+ if (v9_form)
-+ strcpy (string, "ba%*,pt\t%%xcc, ");
-+ else
-+ strcpy (string, "b%*\t");
-+
-+ p = strchr (string, '\0');
-+ *p++ = '%';
-+ *p++ = 'l';
-+ *p++ = '0';
-+ *p++ = '%';
-+ *p++ = '(';
-+ *p = '\0';
-+
-+ return string;
-+}
-+
-+/* Return the string to output a conditional branch to LABEL, which is
-+ the operand number of the label. OP is the conditional expression.
-+ XEXP (OP, 0) is assumed to be a condition code register (integer or
-+ floating point) and its mode specifies what kind of comparison we made.
-+
-+ DEST is the destination insn (i.e. the label), INSN is the source.
-+
-+ REVERSED is nonzero if we should reverse the sense of the comparison.
-+
-+ ANNUL is nonzero if we should generate an annulling branch. */
-+
-+const char *
-+output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
-+ rtx_insn *insn)
-+{
-+ static char string[64];
-+ enum rtx_code code = GET_CODE (op);
-+ rtx cc_reg = XEXP (op, 0);
-+ machine_mode mode = GET_MODE (cc_reg);
-+ const char *labelno, *branch;
-+ int spaces = 8, far;
-+ char *p;
-+
-+ /* v9 branches are limited to +-1MB. If it is too far away,
-+ change
-+
-+ bne,pt %xcc, .LC30
-+
-+ to
-+
-+ be,pn %xcc, .+12
-+ nop
-+ ba .LC30
-+
-+ and
-+
-+ fbne,a,pn %fcc2, .LC29
-+
-+ to
-+
-+ fbe,pt %fcc2, .+16
-+ nop
-+ ba .LC29 */
-+
-+ far = TARGET_V9 && (get_attr_length (insn) >= 3);
-+ if (reversed ^ far)
-+ {
-+ /* Reversal of FP compares takes care -- an ordered compare
-+ becomes an unordered compare and vice versa. */
-+ if (mode == CCFPmode || mode == CCFPEmode)
-+ code = reverse_condition_maybe_unordered (code);
-+ else
-+ code = reverse_condition (code);
-+ }
-+
-+ /* Start by writing the branch condition. */
-+ if (mode == CCFPmode || mode == CCFPEmode)
-+ {
-+ switch (code)
-+ {
-+ case NE:
-+ branch = "fbne";
-+ break;
-+ case EQ:
-+ branch = "fbe";
-+ break;
-+ case GE:
-+ branch = "fbge";
-+ break;
-+ case GT:
-+ branch = "fbg";
-+ break;
-+ case LE:
-+ branch = "fble";
-+ break;
-+ case LT:
-+ branch = "fbl";
-+ break;
-+ case UNORDERED:
-+ branch = "fbu";
-+ break;
-+ case ORDERED:
-+ branch = "fbo";
-+ break;
-+ case UNGT:
-+ branch = "fbug";
-+ break;
-+ case UNLT:
-+ branch = "fbul";
-+ break;
-+ case UNEQ:
-+ branch = "fbue";
-+ break;
-+ case UNGE:
-+ branch = "fbuge";
-+ break;
-+ case UNLE:
-+ branch = "fbule";
-+ break;
-+ case LTGT:
-+ branch = "fblg";
-+ break;
-+ default:
-+ gcc_unreachable ();
-+ }
-+
-+ /* ??? !v9: FP branches cannot be preceded by another floating point
-+ insn. Because there is currently no concept of pre-delay slots,
-+ we can fix this only by always emitting a nop before a floating
-+ point branch. */
-+
-+ string[0] = '\0';
-+ if (! TARGET_V9)
-+ strcpy (string, "nop\n\t");
-+ strcat (string, branch);
-+ }
-+ else
-+ {
-+ switch (code)
-+ {
-+ case NE:
-+ if (mode == CCVmode || mode == CCXVmode)
-+ branch = "bvs";
-+ else
-+ branch = "bne";
-+ break;
-+ case EQ:
-+ if (mode == CCVmode || mode == CCXVmode)
-+ branch = "bvc";
-+ else
-+ branch = "be";
-+ break;
-+ case GE:
-+ if (mode == CCNZmode || mode == CCXNZmode)
-+ branch = "bpos";
-+ else
-+ branch = "bge";
-+ break;
-+ case GT:
-+ branch = "bg";
-+ break;
-+ case LE:
-+ branch = "ble";
-+ break;
-+ case LT:
-+ if (mode == CCNZmode || mode == CCXNZmode)
-+ branch = "bneg";
-+ else
-+ branch = "bl";
-+ break;
-+ case GEU:
-+ branch = "bgeu";
-+ break;
-+ case GTU:
-+ branch = "bgu";
-+ break;
-+ case LEU:
-+ branch = "bleu";
-+ break;
-+ case LTU:
-+ branch = "blu";
-+ break;
-+ default:
-+ gcc_unreachable ();
-+ }
-+ strcpy (string, branch);
-+ }
-+ spaces -= strlen (branch);
-+ p = strchr (string, '\0');
-+
-+ /* Now add the annulling, the label, and a possible noop. */
-+ if (annul && ! far)
-+ {
-+ strcpy (p, ",a");
-+ p += 2;
-+ spaces -= 2;
-+ }
-+
-+ if (TARGET_V9)
-+ {
-+ rtx note;
-+ int v8 = 0;
-+
-+ if (! far && insn && INSN_ADDRESSES_SET_P ())
-+ {
-+ int delta = (INSN_ADDRESSES (INSN_UID (dest))
-+ - INSN_ADDRESSES (INSN_UID (insn)));
-+ /* Leave some instructions for "slop". */
-+ if (delta < -260000 || delta >= 260000)
-+ v8 = 1;
-+ }
-+
-+ switch (mode)
-+ {
-+ case E_CCmode:
-+ case E_CCNZmode:
-+ case E_CCCmode:
-+ case E_CCVmode:
-+ labelno = "%%icc, ";
-+ if (v8)
-+ labelno = "";
-+ break;
-+ case E_CCXmode:
-+ case E_CCXNZmode:
-+ case E_CCXCmode:
-+ case E_CCXVmode:
-+ labelno = "%%xcc, ";
-+ gcc_assert (!v8);
-+ break;
-+ case E_CCFPmode:
-+ case E_CCFPEmode:
-+ {
-+ static char v9_fcc_labelno[] = "%%fccX, ";
-+ /* Set the char indicating the number of the fcc reg to use. */
-+ v9_fcc_labelno[5] = REGNO (cc_reg) - SPARC_FIRST_V9_FCC_REG + '0';
-+ labelno = v9_fcc_labelno;
-+ if (v8)
-+ {
-+ gcc_assert (REGNO (cc_reg) == SPARC_FCC_REG);
-+ labelno = "";
-+ }
-+ }
-+ break;
-+ default:
-+ gcc_unreachable ();
-+ }
-+
-+ if (*labelno && insn && (note = find_reg_note (insn, REG_BR_PROB, NULL_RTX)))
-+ {
-+ strcpy (p,
-+ ((profile_probability::from_reg_br_prob_note (XINT (note, 0))
-+ >= profile_probability::even ()) ^ far)
-+ ? ",pt" : ",pn");
-+ p += 3;
-+ spaces -= 3;
-+ }
-+ }
-+ else
-+ labelno = "";
-+
-+ if (spaces > 0)
-+ *p++ = '\t';
-+ else
-+ *p++ = ' ';
-+ strcpy (p, labelno);
-+ p = strchr (p, '\0');
-+ if (far)
-+ {
-+ strcpy (p, ".+12\n\t nop\n\tb\t");
-+ /* Skip the next insn if requested or
-+ if we know that it will be a nop. */
-+ if (annul || ! final_sequence)
-+ p[3] = '6';
-+ p += 14;
-+ }
-+ *p++ = '%';
-+ *p++ = 'l';
-+ *p++ = label + '0';
-+ *p++ = '%';
-+ *p++ = '#';
-+ *p = '\0';
-+
-+ return string;
-+}
-+
-+/* Emit a library call comparison between floating point X and Y.
-+ COMPARISON is the operator to compare with (EQ, NE, GT, etc).
-+ Return the new operator to be used in the comparison sequence.
-+
-+ TARGET_ARCH64 uses _Qp_* functions, which use pointers to TFmode
-+ values as arguments instead of the TFmode registers themselves,
-+ that's why we cannot call emit_float_lib_cmp. */
-+
-+rtx
-+sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison)
-+{
-+ const char *qpfunc;
-+ rtx slot0, slot1, result, tem, tem2, libfunc;
-+ machine_mode mode;
-+ enum rtx_code new_comparison;
-+
-+ switch (comparison)
-+ {
-+ case EQ:
-+ qpfunc = (TARGET_ARCH64 ? "_Qp_feq" : "_Q_feq");
-+ break;
-+
-+ case NE:
-+ qpfunc = (TARGET_ARCH64 ? "_Qp_fne" : "_Q_fne");
-+ break;
-+
-+ case GT:
-+ qpfunc = (TARGET_ARCH64 ? "_Qp_fgt" : "_Q_fgt");
-+ break;
-+
-+ case GE:
-+ qpfunc = (TARGET_ARCH64 ? "_Qp_fge" : "_Q_fge");
-+ break;
-+
-+ case LT:
-+ qpfunc = (TARGET_ARCH64 ? "_Qp_flt" : "_Q_flt");
-+ break;
-+
-+ case LE:
-+ qpfunc = (TARGET_ARCH64 ? "_Qp_fle" : "_Q_fle");
-+ break;
-+
-+ case ORDERED:
-+ case UNORDERED:
-+ case UNGT:
-+ case UNLT:
-+ case UNEQ:
-+ case UNGE:
-+ case UNLE:
-+ case LTGT:
-+ qpfunc = (TARGET_ARCH64 ? "_Qp_cmp" : "_Q_cmp");
-+ break;
-+
-+ default:
-+ gcc_unreachable ();
-+ }
-+
-+ if (TARGET_ARCH64)
-+ {
-+ if (MEM_P (x))
-+ {
-+ tree expr = MEM_EXPR (x);
-+ if (expr)
-+ mark_addressable (expr);
-+ slot0 = x;
-+ }
-+ else
-+ {
-+ slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode));
-+ emit_move_insn (slot0, x);
-+ }
-+
-+ if (MEM_P (y))
-+ {
-+ tree expr = MEM_EXPR (y);
-+ if (expr)
-+ mark_addressable (expr);
-+ slot1 = y;
-+ }
-+ else
-+ {
-+ slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode));
-+ emit_move_insn (slot1, y);
-+ }
-+
-+ libfunc = gen_rtx_SYMBOL_REF (Pmode, qpfunc);
-+ emit_library_call (libfunc, LCT_NORMAL,
-+ DImode,
-+ XEXP (slot0, 0), Pmode,
-+ XEXP (slot1, 0), Pmode);
-+ mode = DImode;
-+ }
-+ else
-+ {
-+ libfunc = gen_rtx_SYMBOL_REF (Pmode, qpfunc);
-+ emit_library_call (libfunc, LCT_NORMAL,
-+ SImode,
-+ x, TFmode, y, TFmode);
-+ mode = SImode;
-+ }
-+
-+
-+ /* Immediately move the result of the libcall into a pseudo
-+ register so reload doesn't clobber the value if it needs
-+ the return register for a spill reg. */
-+ result = gen_reg_rtx (mode);
-+ emit_move_insn (result, hard_libcall_value (mode, libfunc));
-+
-+ switch (comparison)
-+ {
-+ default:
-+ return gen_rtx_NE (VOIDmode, result, const0_rtx);
-+ case ORDERED:
-+ case UNORDERED:
-+ new_comparison = (comparison == UNORDERED ? EQ : NE);
-+ return gen_rtx_fmt_ee (new_comparison, VOIDmode, result, GEN_INT(3));
-+ case UNGT:
-+ case UNGE:
-+ new_comparison = (comparison == UNGT ? GT : NE);
-+ return gen_rtx_fmt_ee (new_comparison, VOIDmode, result, const1_rtx);
-+ case UNLE:
-+ return gen_rtx_NE (VOIDmode, result, const2_rtx);
-+ case UNLT:
-+ tem = gen_reg_rtx (mode);
-+ if (TARGET_ARCH32)
-+ emit_insn (gen_andsi3 (tem, result, const1_rtx));
-+ else
-+ emit_insn (gen_anddi3 (tem, result, const1_rtx));
-+ return gen_rtx_NE (VOIDmode, tem, const0_rtx);
-+ case UNEQ:
-+ case LTGT:
-+ tem = gen_reg_rtx (mode);
-+ if (TARGET_ARCH32)
-+ emit_insn (gen_addsi3 (tem, result, const1_rtx));
-+ else
-+ emit_insn (gen_adddi3 (tem, result, const1_rtx));
-+ tem2 = gen_reg_rtx (mode);
-+ if (TARGET_ARCH32)
-+ emit_insn (gen_andsi3 (tem2, tem, const2_rtx));
-+ else
-+ emit_insn (gen_anddi3 (tem2, tem, const2_rtx));
-+ new_comparison = (comparison == UNEQ ? EQ : NE);
-+ return gen_rtx_fmt_ee (new_comparison, VOIDmode, tem2, const0_rtx);
-+ }
-+
-+ gcc_unreachable ();
-+}
-+
-+/* Generate an unsigned DImode to FP conversion. This is the same code
-+ optabs would emit if we didn't have TFmode patterns. */
-+
-+void
-+sparc_emit_floatunsdi (rtx *operands, machine_mode mode)
-+{
-+ rtx i0, i1, f0, in, out;
-+
-+ out = operands[0];
-+ in = force_reg (DImode, operands[1]);
-+ rtx_code_label *neglab = gen_label_rtx ();
-+ rtx_code_label *donelab = gen_label_rtx ();
-+ i0 = gen_reg_rtx (DImode);
-+ i1 = gen_reg_rtx (DImode);
-+ f0 = gen_reg_rtx (mode);
-+
-+ emit_cmp_and_jump_insns (in, const0_rtx, LT, const0_rtx, DImode, 0, neglab);
-+
-+ emit_insn (gen_rtx_SET (out, gen_rtx_FLOAT (mode, in)));
-+ emit_jump_insn (gen_jump (donelab));
-+ emit_barrier ();
-+
-+ emit_label (neglab);
-+
-+ emit_insn (gen_lshrdi3 (i0, in, const1_rtx));
-+ emit_insn (gen_anddi3 (i1, in, const1_rtx));
-+ emit_insn (gen_iordi3 (i0, i0, i1));
-+ emit_insn (gen_rtx_SET (f0, gen_rtx_FLOAT (mode, i0)));
-+ emit_insn (gen_rtx_SET (out, gen_rtx_PLUS (mode, f0, f0)));
-+
-+ emit_label (donelab);
-+}
-+
-+/* Generate an FP to unsigned DImode conversion. This is the same code
-+ optabs would emit if we didn't have TFmode patterns. */
-+
-+void
-+sparc_emit_fixunsdi (rtx *operands, machine_mode mode)
-+{
-+ rtx i0, i1, f0, in, out, limit;
-+
-+ out = operands[0];
-+ in = force_reg (mode, operands[1]);
-+ rtx_code_label *neglab = gen_label_rtx ();
-+ rtx_code_label *donelab = gen_label_rtx ();
-+ i0 = gen_reg_rtx (DImode);
-+ i1 = gen_reg_rtx (DImode);
-+ limit = gen_reg_rtx (mode);
-+ f0 = gen_reg_rtx (mode);
-+
-+ emit_move_insn (limit,
-+ const_double_from_real_value (
-+ REAL_VALUE_ATOF ("9223372036854775808.0", mode), mode));
-+ emit_cmp_and_jump_insns (in, limit, GE, NULL_RTX, mode, 0, neglab);
-+
-+ emit_insn (gen_rtx_SET (out,
-+ gen_rtx_FIX (DImode, gen_rtx_FIX (mode, in))));
-+ emit_jump_insn (gen_jump (donelab));
-+ emit_barrier ();
-+
-+ emit_label (neglab);
-+
-+ emit_insn (gen_rtx_SET (f0, gen_rtx_MINUS (mode, in, limit)));
-+ emit_insn (gen_rtx_SET (i0,
-+ gen_rtx_FIX (DImode, gen_rtx_FIX (mode, f0))));
-+ emit_insn (gen_movdi (i1, const1_rtx));
-+ emit_insn (gen_ashldi3 (i1, i1, GEN_INT (63)));
-+ emit_insn (gen_xordi3 (out, i0, i1));
-+
-+ emit_label (donelab);
-+}
-+
-+/* Return the string to output a compare and branch instruction to DEST.
-+ DEST is the destination insn (i.e. the label), INSN is the source,
-+ and OP is the conditional expression. */
-+
-+const char *
-+output_cbcond (rtx op, rtx dest, rtx_insn *insn)
-+{
-+ machine_mode mode = GET_MODE (XEXP (op, 0));
-+ enum rtx_code code = GET_CODE (op);
-+ const char *cond_str, *tmpl;
-+ int far, emit_nop, len;
-+ static char string[64];
-+ char size_char;
-+
-+ /* Compare and Branch is limited to +-2KB. If it is too far away,
-+ change
-+
-+ cxbne X, Y, .LC30
-+
-+ to
-+
-+ cxbe X, Y, .+16
-+ nop
-+ ba,pt xcc, .LC30
-+ nop */
-+
-+ len = get_attr_length (insn);
-+
-+ far = len == 4;
-+ emit_nop = len == 2;
-+
-+ if (far)
-+ code = reverse_condition (code);
-+
-+ size_char = ((mode == SImode) ? 'w' : 'x');
-+
-+ switch (code)
-+ {
-+ case NE:
-+ cond_str = "ne";
-+ break;
-+
-+ case EQ:
-+ cond_str = "e";
-+ break;
-+
-+ case GE:
-+ cond_str = "ge";
-+ break;
-+
-+ case GT:
-+ cond_str = "g";
-+ break;
-+
-+ case LE:
-+ cond_str = "le";
-+ break;
-+
-+ case LT:
-+ cond_str = "l";
-+ break;
-+
-+ case GEU:
-+ cond_str = "cc";
-+ break;
-+
-+ case GTU:
-+ cond_str = "gu";
-+ break;
-+
-+ case LEU:
-+ cond_str = "leu";
-+ break;
-+
-+ case LTU:
-+ cond_str = "cs";
-+ break;
-+
-+ default:
-+ gcc_unreachable ();
-+ }
-+
-+ if (far)
-+ {
-+ int veryfar = 1, delta;
-+
-+ if (INSN_ADDRESSES_SET_P ())
-+ {
-+ delta = (INSN_ADDRESSES (INSN_UID (dest))
-+ - INSN_ADDRESSES (INSN_UID (insn)));
-+ /* Leave some instructions for "slop". */
-+ if (delta >= -260000 && delta < 260000)
-+ veryfar = 0;
-+ }
-+
-+ if (veryfar)
-+ tmpl = "c%cb%s\t%%1, %%2, .+16\n\tnop\n\tb\t%%3\n\tnop";
-+ else
-+ tmpl = "c%cb%s\t%%1, %%2, .+16\n\tnop\n\tba,pt\t%%%%xcc, %%3\n\tnop";
-+ }
-+ else
-+ {
-+ if (emit_nop)
-+ tmpl = "c%cb%s\t%%1, %%2, %%3\n\tnop";
-+ else
-+ tmpl = "c%cb%s\t%%1, %%2, %%3";
-+ }
-+
-+ snprintf (string, sizeof(string), tmpl, size_char, cond_str);
-+
-+ return string;
-+}
-+
-+/* Return the string to output a conditional branch to LABEL, testing
-+ register REG. LABEL is the operand number of the label; REG is the
-+ operand number of the reg. OP is the conditional expression. The mode
-+ of REG says what kind of comparison we made.
-+
-+ DEST is the destination insn (i.e. the label), INSN is the source.
-+
-+ REVERSED is nonzero if we should reverse the sense of the comparison.
-+
-+ ANNUL is nonzero if we should generate an annulling branch. */
-+
-+const char *
-+output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
-+ int annul, rtx_insn *insn)
-+{
-+ static char string[64];
-+ enum rtx_code code = GET_CODE (op);
-+ machine_mode mode = GET_MODE (XEXP (op, 0));
-+ rtx note;
-+ int far;
-+ char *p;
-+
-+ /* branch on register are limited to +-128KB. If it is too far away,
-+ change
-+
-+ brnz,pt %g1, .LC30
-+
-+ to
-+
-+ brz,pn %g1, .+12
-+ nop
-+ ba,pt %xcc, .LC30
-+
-+ and
-+
-+ brgez,a,pn %o1, .LC29
-+
-+ to
-+
-+ brlz,pt %o1, .+16
-+ nop
-+ ba,pt %xcc, .LC29 */
-+
-+ far = get_attr_length (insn) >= 3;
-+
-+ /* If not floating-point or if EQ or NE, we can just reverse the code. */
-+ if (reversed ^ far)
-+ code = reverse_condition (code);
-+
-+ /* Only 64-bit versions of these instructions exist. */
-+ gcc_assert (mode == DImode);
-+
-+ /* Start by writing the branch condition. */
-+
-+ switch (code)
-+ {
-+ case NE:
-+ strcpy (string, "brnz");
-+ break;
-+
-+ case EQ:
-+ strcpy (string, "brz");
-+ break;
-+
-+ case GE:
-+ strcpy (string, "brgez");
-+ break;
-+
-+ case LT:
-+ strcpy (string, "brlz");
-+ break;
-+
-+ case LE:
-+ strcpy (string, "brlez");
-+ break;
-+
-+ case GT:
-+ strcpy (string, "brgz");
-+ break;
-+
-+ default:
-+ gcc_unreachable ();
-+ }
-+
-+ p = strchr (string, '\0');
-+
-+ /* Now add the annulling, reg, label, and nop. */
-+ if (annul && ! far)
-+ {
-+ strcpy (p, ",a");
-+ p += 2;
-+ }
-+
-+ if (insn && (note = find_reg_note (insn, REG_BR_PROB, NULL_RTX)))
-+ {
-+ strcpy (p,
-+ ((profile_probability::from_reg_br_prob_note (XINT (note, 0))
-+ >= profile_probability::even ()) ^ far)
-+ ? ",pt" : ",pn");
-+ p += 3;
-+ }
-+
-+ *p = p < string + 8 ? '\t' : ' ';
-+ p++;
-+ *p++ = '%';
-+ *p++ = '0' + reg;
-+ *p++ = ',';
-+ *p++ = ' ';
-+ if (far)
-+ {
-+ int veryfar = 1, delta;
-+
-+ if (INSN_ADDRESSES_SET_P ())
-+ {
-+ delta = (INSN_ADDRESSES (INSN_UID (dest))
-+ - INSN_ADDRESSES (INSN_UID (insn)));
-+ /* Leave some instructions for "slop". */
-+ if (delta >= -260000 && delta < 260000)
-+ veryfar = 0;
-+ }
-+
-+ strcpy (p, ".+12\n\t nop\n\t");
-+ /* Skip the next insn if requested or
-+ if we know that it will be a nop. */
-+ if (annul || ! final_sequence)
-+ p[3] = '6';
-+ p += 12;
-+ if (veryfar)
-+ {
-+ strcpy (p, "b\t");
-+ p += 2;
-+ }
-+ else
-+ {
-+ strcpy (p, "ba,pt\t%%xcc, ");
-+ p += 13;
-+ }
-+ }
-+ *p++ = '%';
-+ *p++ = 'l';
-+ *p++ = '0' + label;
-+ *p++ = '%';
-+ *p++ = '#';
-+ *p = '\0';
-+
-+ return string;
-+}
-+
-+/* Return 1, if any of the registers of the instruction are %l[0-7] or %o[0-7].
-+ Such instructions cannot be used in the delay slot of return insn on v9.
-+ If TEST is 0, also rename all %i[0-7] registers to their %o[0-7] counterparts.
-+ */
-+
-+static int
-+epilogue_renumber (register rtx *where, int test)
-+{
-+ register const char *fmt;
-+ register int i;
-+ register enum rtx_code code;
-+
-+ if (*where == 0)
-+ return 0;
-+
-+ code = GET_CODE (*where);
-+
-+ switch (code)
-+ {
-+ case REG:
-+ if (REGNO (*where) >= 8 && REGNO (*where) < 24) /* oX or lX */
-+ return 1;
-+ if (! test && REGNO (*where) >= 24 && REGNO (*where) < 32)
-+ *where = gen_rtx_REG (GET_MODE (*where), OUTGOING_REGNO (REGNO(*where)));
-+ /* fallthrough */
-+ case SCRATCH:
-+ case CC0:
-+ case PC:
-+ case CONST_INT:
-+ case CONST_WIDE_INT:
-+ case CONST_DOUBLE:
-+ return 0;
-+
-+ /* Do not replace the frame pointer with the stack pointer because
-+ it can cause the delayed instruction to load below the stack.
-+ This occurs when instructions like:
-+
-+ (set (reg/i:SI 24 %i0)
-+ (mem/f:SI (plus:SI (reg/f:SI 30 %fp)
-+ (const_int -20 [0xffffffec])) 0))
-+
-+ are in the return delayed slot. */
-+ case PLUS:
-+ if (GET_CODE (XEXP (*where, 0)) == REG
-+ && REGNO (XEXP (*where, 0)) == HARD_FRAME_POINTER_REGNUM
-+ && (GET_CODE (XEXP (*where, 1)) != CONST_INT
-+ || INTVAL (XEXP (*where, 1)) < SPARC_STACK_BIAS))
-+ return 1;
-+ break;
-+
-+ case MEM:
-+ if (SPARC_STACK_BIAS
-+ && GET_CODE (XEXP (*where, 0)) == REG
-+ && REGNO (XEXP (*where, 0)) == HARD_FRAME_POINTER_REGNUM)
-+ return 1;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ fmt = GET_RTX_FORMAT (code);
-+
-+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-+ {
-+ if (fmt[i] == 'E')
-+ {
-+ register int j;
-+ for (j = XVECLEN (*where, i) - 1; j >= 0; j--)
-+ if (epilogue_renumber (&(XVECEXP (*where, i, j)), test))
-+ return 1;
-+ }
-+ else if (fmt[i] == 'e'
-+ && epilogue_renumber (&(XEXP (*where, i)), test))
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+/* Leaf functions and non-leaf functions have different needs. */
-+
-+static const int
-+reg_leaf_alloc_order[] = REG_LEAF_ALLOC_ORDER;
-+
-+static const int
-+reg_nonleaf_alloc_order[] = REG_ALLOC_ORDER;
-+
-+static const int *const reg_alloc_orders[] = {
-+ reg_leaf_alloc_order,
-+ reg_nonleaf_alloc_order};
-+
-+void
-+order_regs_for_local_alloc (void)
-+{
-+ static int last_order_nonleaf = 1;
-+
-+ if (df_regs_ever_live_p (15) != last_order_nonleaf)
-+ {
-+ last_order_nonleaf = !last_order_nonleaf;
-+ memcpy ((char *) reg_alloc_order,
-+ (const char *) reg_alloc_orders[last_order_nonleaf],
-+ FIRST_PSEUDO_REGISTER * sizeof (int));
-+ }
-+}
-+
-+/* Return 1 if REG and MEM are legitimate enough to allow the various
-+ MEM<-->REG splits to be run. */
-+
-+int
-+sparc_split_reg_mem_legitimate (rtx reg, rtx mem)
-+{
-+ /* Punt if we are here by mistake. */
-+ gcc_assert (reload_completed);
-+
-+ /* We must have an offsettable memory reference. */
-+ if (!offsettable_memref_p (mem))
-+ return 0;
-+
-+ /* If we have legitimate args for ldd/std, we do not want
-+ the split to happen. */
-+ if ((REGNO (reg) % 2) == 0 && mem_min_alignment (mem, 8))
-+ return 0;
-+
-+ /* Success. */
-+ return 1;
-+}
-+
-+/* Split a REG <-- MEM move into a pair of moves in MODE. */
-+
-+void
-+sparc_split_reg_mem (rtx dest, rtx src, machine_mode mode)
-+{
-+ rtx high_part = gen_highpart (mode, dest);
-+ rtx low_part = gen_lowpart (mode, dest);
-+ rtx word0 = adjust_address (src, mode, 0);
-+ rtx word1 = adjust_address (src, mode, 4);
-+
-+ if (reg_overlap_mentioned_p (high_part, word1))
-+ {
-+ emit_move_insn_1 (low_part, word1);
-+ emit_move_insn_1 (high_part, word0);
-+ }
-+ else
-+ {
-+ emit_move_insn_1 (high_part, word0);
-+ emit_move_insn_1 (low_part, word1);
-+ }
-+}
-+
-+/* Split a MEM <-- REG move into a pair of moves in MODE. */
-+
-+void
-+sparc_split_mem_reg (rtx dest, rtx src, machine_mode mode)
-+{
-+ rtx word0 = adjust_address (dest, mode, 0);
-+ rtx word1 = adjust_address (dest, mode, 4);
-+ rtx high_part = gen_highpart (mode, src);
-+ rtx low_part = gen_lowpart (mode, src);
-+
-+ emit_move_insn_1 (word0, high_part);
-+ emit_move_insn_1 (word1, low_part);
-+}
-+
-+/* Like sparc_split_reg_mem_legitimate but for REG <--> REG moves. */
-+
-+int
-+sparc_split_reg_reg_legitimate (rtx reg1, rtx reg2)
-+{
-+ /* Punt if we are here by mistake. */
-+ gcc_assert (reload_completed);
-+
-+ if (GET_CODE (reg1) == SUBREG)
-+ reg1 = SUBREG_REG (reg1);
-+ if (GET_CODE (reg1) != REG)
-+ return 0;
-+ const int regno1 = REGNO (reg1);
-+
-+ if (GET_CODE (reg2) == SUBREG)
-+ reg2 = SUBREG_REG (reg2);
-+ if (GET_CODE (reg2) != REG)
-+ return 0;
-+ const int regno2 = REGNO (reg2);
-+
-+ if (SPARC_INT_REG_P (regno1) && SPARC_INT_REG_P (regno2))
-+ return 1;
-+
-+ if (TARGET_VIS3)
-+ {
-+ if ((SPARC_INT_REG_P (regno1) && SPARC_FP_REG_P (regno2))
-+ || (SPARC_FP_REG_P (regno1) && SPARC_INT_REG_P (regno2)))
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+/* Split a REG <--> REG move into a pair of moves in MODE. */
-+
-+void
-+sparc_split_reg_reg (rtx dest, rtx src, machine_mode mode)
-+{
-+ rtx dest1 = gen_highpart (mode, dest);
-+ rtx dest2 = gen_lowpart (mode, dest);
-+ rtx src1 = gen_highpart (mode, src);
-+ rtx src2 = gen_lowpart (mode, src);
-+
-+ /* Now emit using the real source and destination we found, swapping
-+ the order if we detect overlap. */
-+ if (reg_overlap_mentioned_p (dest1, src2))
-+ {
-+ emit_move_insn_1 (dest2, src2);
-+ emit_move_insn_1 (dest1, src1);
-+ }
-+ else
-+ {
-+ emit_move_insn_1 (dest1, src1);
-+ emit_move_insn_1 (dest2, src2);
-+ }
-+}
-+
-+/* Return 1 if REGNO (reg1) is even and REGNO (reg1) == REGNO (reg2) - 1.
-+ This makes them candidates for using ldd and std insns.
-+
-+ Note reg1 and reg2 *must* be hard registers. */
-+
-+int
-+registers_ok_for_ldd_peep (rtx reg1, rtx reg2)
-+{
-+ /* We might have been passed a SUBREG. */
-+ if (GET_CODE (reg1) != REG || GET_CODE (reg2) != REG)
-+ return 0;
-+
-+ if (REGNO (reg1) % 2 != 0)
-+ return 0;
-+
-+ /* Integer ldd is deprecated in SPARC V9 */
-+ if (TARGET_V9 && SPARC_INT_REG_P (REGNO (reg1)))
-+ return 0;
-+
-+ return (REGNO (reg1) == REGNO (reg2) - 1);
-+}
-+
-+/* Return 1 if the addresses in mem1 and mem2 are suitable for use in
-+ an ldd or std insn.
-+
-+ This can only happen when addr1 and addr2, the addresses in mem1
-+ and mem2, are consecutive memory locations (addr1 + 4 == addr2).
-+ addr1 must also be aligned on a 64-bit boundary.
-+
-+ Also iff dependent_reg_rtx is not null it should not be used to
-+ compute the address for mem1, i.e. we cannot optimize a sequence
-+ like:
-+ ld [%o0], %o0
-+ ld [%o0 + 4], %o1
-+ to
-+ ldd [%o0], %o0
-+ nor:
-+ ld [%g3 + 4], %g3
-+ ld [%g3], %g2
-+ to
-+ ldd [%g3], %g2
-+
-+ But, note that the transformation from:
-+ ld [%g2 + 4], %g3
-+ ld [%g2], %g2
-+ to
-+ ldd [%g2], %g2
-+ is perfectly fine. Thus, the peephole2 patterns always pass us
-+ the destination register of the first load, never the second one.
-+
-+ For stores we don't have a similar problem, so dependent_reg_rtx is
-+ NULL_RTX. */
-+
-+int
-+mems_ok_for_ldd_peep (rtx mem1, rtx mem2, rtx dependent_reg_rtx)
-+{
-+ rtx addr1, addr2;
-+ unsigned int reg1;
-+ HOST_WIDE_INT offset1;
-+
-+ /* The mems cannot be volatile. */
-+ if (MEM_VOLATILE_P (mem1) || MEM_VOLATILE_P (mem2))
-+ return 0;
-+
-+ /* MEM1 should be aligned on a 64-bit boundary. */
-+ if (MEM_ALIGN (mem1) < 64)
-+ return 0;
-+
-+ addr1 = XEXP (mem1, 0);
-+ addr2 = XEXP (mem2, 0);
-+
-+ /* Extract a register number and offset (if used) from the first addr. */
-+ if (GET_CODE (addr1) == PLUS)
-+ {
-+ /* If not a REG, return zero. */
-+ if (GET_CODE (XEXP (addr1, 0)) != REG)
-+ return 0;
-+ else
-+ {
-+ reg1 = REGNO (XEXP (addr1, 0));
-+ /* The offset must be constant! */
-+ if (GET_CODE (XEXP (addr1, 1)) != CONST_INT)
-+ return 0;
-+ offset1 = INTVAL (XEXP (addr1, 1));
-+ }
-+ }
-+ else if (GET_CODE (addr1) != REG)
-+ return 0;
-+ else
-+ {
-+ reg1 = REGNO (addr1);
-+ /* This was a simple (mem (reg)) expression. Offset is 0. */
-+ offset1 = 0;
-+ }
-+
-+ /* Make sure the second address is a (mem (plus (reg) (const_int). */
-+ if (GET_CODE (addr2) != PLUS)
-+ return 0;
-+
-+ if (GET_CODE (XEXP (addr2, 0)) != REG
-+ || GET_CODE (XEXP (addr2, 1)) != CONST_INT)
-+ return 0;
-+
-+ if (reg1 != REGNO (XEXP (addr2, 0)))
-+ return 0;
-+
-+ if (dependent_reg_rtx != NULL_RTX && reg1 == REGNO (dependent_reg_rtx))
-+ return 0;
-+
-+ /* The first offset must be evenly divisible by 8 to ensure the
-+ address is 64-bit aligned. */
-+ if (offset1 % 8 != 0)
-+ return 0;
-+
-+ /* The offset for the second addr must be 4 more than the first addr. */
-+ if (INTVAL (XEXP (addr2, 1)) != offset1 + 4)
-+ return 0;
-+
-+ /* All the tests passed. addr1 and addr2 are valid for ldd and std
-+ instructions. */
-+ return 1;
-+}
-+
-+/* Return the widened memory access made of MEM1 and MEM2 in MODE. */
-+
-+rtx
-+widen_mem_for_ldd_peep (rtx mem1, rtx mem2, machine_mode mode)
-+{
-+ rtx x = widen_memory_access (mem1, mode, 0);
-+ MEM_NOTRAP_P (x) = MEM_NOTRAP_P (mem1) && MEM_NOTRAP_P (mem2);
-+ return x;
-+}
-+
-+/* Return 1 if reg is a pseudo, or is the first register in
-+ a hard register pair. This makes it suitable for use in
-+ ldd and std insns. */
-+
-+int
-+register_ok_for_ldd (rtx reg)
-+{
-+ /* We might have been passed a SUBREG. */
-+ if (!REG_P (reg))
-+ return 0;
-+
-+ if (REGNO (reg) < FIRST_PSEUDO_REGISTER)
-+ return (REGNO (reg) % 2 == 0);
-+
-+ return 1;
-+}
-+
-+/* Return 1 if OP, a MEM, has an address which is known to be
-+ aligned to an 8-byte boundary. */
-+
-+int
-+memory_ok_for_ldd (rtx op)
-+{
-+ /* In 64-bit mode, we assume that the address is word-aligned. */
-+ if (TARGET_ARCH32 && !mem_min_alignment (op, 8))
-+ return 0;
-+
-+ if (! can_create_pseudo_p ()
-+ && !strict_memory_address_p (Pmode, XEXP (op, 0)))
-+ return 0;
-+
-+ return 1;
-+}
-+
-+/* Implement TARGET_PRINT_OPERAND_PUNCT_VALID_P. */
-+
-+static bool
-+sparc_print_operand_punct_valid_p (unsigned char code)
-+{
-+ if (code == '#'
-+ || code == '*'
-+ || code == '('
-+ || code == ')'
-+ || code == '_'
-+ || code == '&')
-+ return true;
-+
-+ return false;
-+}
-+
-+/* Implement TARGET_PRINT_OPERAND.
-+ Print operand X (an rtx) in assembler syntax to file FILE.
-+ CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
-+ For `%' followed by punctuation, CODE is the punctuation and X is null. */
-+
-+static void
-+sparc_print_operand (FILE *file, rtx x, int code)
-+{
-+ const char *s;
-+
-+ switch (code)
-+ {
-+ case '#':
-+ /* Output an insn in a delay slot. */
-+ if (final_sequence)
-+ sparc_indent_opcode = 1;
-+ else
-+ fputs ("\n\t nop", file);
-+ return;
-+ case '*':
-+ /* Output an annul flag if there's nothing for the delay slot and we
-+ are optimizing. This is always used with '(' below.
-+ Sun OS 4.1.1 dbx can't handle an annulled unconditional branch;
-+ this is a dbx bug. So, we only do this when optimizing.
-+ On UltraSPARC, a branch in a delay slot causes a pipeline flush.
-+ Always emit a nop in case the next instruction is a branch. */
-+ if (! final_sequence && (optimize && (int)sparc_cpu < PROCESSOR_V9))
-+ fputs (",a", file);
-+ return;
-+ case '(':
-+ /* Output a 'nop' if there's nothing for the delay slot and we are
-+ not optimizing. This is always used with '*' above. */
-+ if (! final_sequence && ! (optimize && (int)sparc_cpu < PROCESSOR_V9))
-+ fputs ("\n\t nop", file);
-+ else if (final_sequence)
-+ sparc_indent_opcode = 1;
-+ return;
-+ case ')':
-+ /* Output the right displacement from the saved PC on function return.
-+ The caller may have placed an "unimp" insn immediately after the call
-+ so we have to account for it. This insn is used in the 32-bit ABI
-+ when calling a function that returns a non zero-sized structure. The
-+ 64-bit ABI doesn't have it. Be careful to have this test be the same
-+ as that for the call. The exception is when sparc_std_struct_return
-+ is enabled, the psABI is followed exactly and the adjustment is made
-+ by the code in sparc_struct_value_rtx. The call emitted is the same
-+ when sparc_std_struct_return is enabled. */
-+ if (!TARGET_ARCH64
-+ && cfun->returns_struct
-+ && !sparc_std_struct_return
-+ && DECL_SIZE (DECL_RESULT (current_function_decl))
-+ && TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl)))
-+ == INTEGER_CST
-+ && !integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl))))
-+ fputs ("12", file);
-+ else
-+ fputc ('8', file);
-+ return;
-+ case '_':
-+ /* Output the Embedded Medium/Anywhere code model base register. */
-+ fputs (EMBMEDANY_BASE_REG, file);
-+ return;
-+ case '&':
-+ /* Print some local dynamic TLS name. */
-+ if (const char *name = get_some_local_dynamic_name ())
-+ assemble_name (file, name);
-+ else
-+ output_operand_lossage ("'%%&' used without any "
-+ "local dynamic TLS references");
-+ return;
-+
-+ case 'Y':
-+ /* Adjust the operand to take into account a RESTORE operation. */
-+ if (GET_CODE (x) == CONST_INT)
-+ break;
-+ else if (GET_CODE (x) != REG)
-+ output_operand_lossage ("invalid %%Y operand");
-+ else if (REGNO (x) < 8)
-+ fputs (reg_names[REGNO (x)], file);
-+ else if (REGNO (x) >= 24 && REGNO (x) < 32)
-+ fputs (reg_names[REGNO (x)-16], file);
-+ else
-+ output_operand_lossage ("invalid %%Y operand");
-+ return;
-+ case 'L':
-+ /* Print out the low order register name of a register pair. */
-+ if (WORDS_BIG_ENDIAN)
-+ fputs (reg_names[REGNO (x)+1], file);
-+ else
-+ fputs (reg_names[REGNO (x)], file);
-+ return;
-+ case 'H':
-+ /* Print out the high order register name of a register pair. */
-+ if (WORDS_BIG_ENDIAN)
-+ fputs (reg_names[REGNO (x)], file);
-+ else
-+ fputs (reg_names[REGNO (x)+1], file);
-+ return;
-+ case 'R':
-+ /* Print out the second register name of a register pair or quad.
-+ I.e., R (%o0) => %o1. */
-+ fputs (reg_names[REGNO (x)+1], file);
-+ return;
-+ case 'S':
-+ /* Print out the third register name of a register quad.
-+ I.e., S (%o0) => %o2. */
-+ fputs (reg_names[REGNO (x)+2], file);
-+ return;
-+ case 'T':
-+ /* Print out the fourth register name of a register quad.
-+ I.e., T (%o0) => %o3. */
-+ fputs (reg_names[REGNO (x)+3], file);
-+ return;
-+ case 'x':
-+ /* Print a condition code register. */
-+ if (REGNO (x) == SPARC_ICC_REG)
-+ {
-+ switch (GET_MODE (x))
-+ {
-+ case E_CCmode:
-+ case E_CCNZmode:
-+ case E_CCCmode:
-+ case E_CCVmode:
-+ s = "%icc";
-+ break;
-+ case E_CCXmode:
-+ case E_CCXNZmode:
-+ case E_CCXCmode:
-+ case E_CCXVmode:
-+ s = "%xcc";
-+ break;
-+ default:
-+ gcc_unreachable ();
-+ }
-+ fputs (s, file);
-+ }
-+ else
-+ /* %fccN register */
-+ fputs (reg_names[REGNO (x)], file);
-+ return;
-+ case 'm':
-+ /* Print the operand's address only. */
-+ output_address (GET_MODE (x), XEXP (x, 0));
-+ return;
-+ case 'r':
-+ /* In this case we need a register. Use %g0 if the
-+ operand is const0_rtx. */
-+ if (x == const0_rtx
-+ || (GET_MODE (x) != VOIDmode && x == CONST0_RTX (GET_MODE (x))))
-+ {
-+ fputs ("%g0", file);
-+ return;
-+ }
-+ else
-+ break;
-+
-+ case 'A':
-+ switch (GET_CODE (x))
-+ {
-+ case IOR:
-+ s = "or";
-+ break;
-+ case AND:
-+ s = "and";
-+ break;
-+ case XOR:
-+ s = "xor";
-+ break;
-+ default:
-+ output_operand_lossage ("invalid %%A operand");
-+ s = "";
-+ break;
-+ }
-+ fputs (s, file);
-+ return;
-+
-+ case 'B':
-+ switch (GET_CODE (x))
-+ {
-+ case IOR:
-+ s = "orn";
-+ break;
-+ case AND:
-+ s = "andn";
-+ break;
-+ case XOR:
-+ s = "xnor";
-+ break;
-+ default:
-+ output_operand_lossage ("invalid %%B operand");
-+ s = "";
-+ break;
-+ }
-+ fputs (s, file);
-+ return;
-+
-+ /* This is used by the conditional move instructions. */
-+ case 'C':
-+ {
-+ machine_mode mode = GET_MODE (XEXP (x, 0));
-+ switch (GET_CODE (x))
-+ {
-+ case NE:
-+ if (mode == CCVmode || mode == CCXVmode)
-+ s = "vs";
-+ else
-+ s = "ne";
-+ break;
-+ case EQ:
-+ if (mode == CCVmode || mode == CCXVmode)
-+ s = "vc";
-+ else
-+ s = "e";
-+ break;
-+ case GE:
-+ if (mode == CCNZmode || mode == CCXNZmode)
-+ s = "pos";
-+ else
-+ s = "ge";
-+ break;
-+ case GT:
-+ s = "g";
-+ break;
-+ case LE:
-+ s = "le";
-+ break;
-+ case LT:
-+ if (mode == CCNZmode || mode == CCXNZmode)
-+ s = "neg";
-+ else
-+ s = "l";
-+ break;
-+ case GEU:
-+ s = "geu";
-+ break;
-+ case GTU:
-+ s = "gu";
-+ break;
-+ case LEU:
-+ s = "leu";
-+ break;
-+ case LTU:
-+ s = "lu";
-+ break;
-+ case LTGT:
-+ s = "lg";
-+ break;
-+ case UNORDERED:
-+ s = "u";
-+ break;
-+ case ORDERED:
-+ s = "o";
-+ break;
-+ case UNLT:
-+ s = "ul";
-+ break;
-+ case UNLE:
-+ s = "ule";
-+ break;
-+ case UNGT:
-+ s = "ug";
-+ break;
-+ case UNGE:
-+ s = "uge"
-+ ; break;
-+ case UNEQ:
-+ s = "ue";
-+ break;
-+ default:
-+ output_operand_lossage ("invalid %%C operand");
-+ s = "";
-+ break;
-+ }
-+ fputs (s, file);
-+ return;
-+ }
-+
-+ /* This are used by the movr instruction pattern. */
-+ case 'D':
-+ {
-+ switch (GET_CODE (x))
-+ {
-+ case NE:
-+ s = "ne";
-+ break;
-+ case EQ:
-+ s = "e";
-+ break;
-+ case GE:
-+ s = "gez";
-+ break;
-+ case LT:
-+ s = "lz";
-+ break;
-+ case LE:
-+ s = "lez";
-+ break;
-+ case GT:
-+ s = "gz";
-+ break;
-+ default:
-+ output_operand_lossage ("invalid %%D operand");
-+ s = "";
-+ break;
-+ }
-+ fputs (s, file);
-+ return;
-+ }
-+
-+ case 'b':
-+ {
-+ /* Print a sign-extended character. */
-+ int i = trunc_int_for_mode (INTVAL (x), QImode);
-+ fprintf (file, "%d", i);
-+ return;
-+ }
-+
-+ case 'f':
-+ /* Operand must be a MEM; write its address. */
-+ if (GET_CODE (x) != MEM)
-+ output_operand_lossage ("invalid %%f operand");
-+ output_address (GET_MODE (x), XEXP (x, 0));
-+ return;
-+
-+ case 's':
-+ {
-+ /* Print a sign-extended 32-bit value. */
-+ HOST_WIDE_INT i;
-+ if (GET_CODE(x) == CONST_INT)
-+ i = INTVAL (x);
-+ else
-+ {
-+ output_operand_lossage ("invalid %%s operand");
-+ return;
-+ }
-+ i = trunc_int_for_mode (i, SImode);
-+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, i);
-+ return;
-+ }
-+
-+ case 0:
-+ /* Do nothing special. */
-+ break;
-+
-+ default:
-+ /* Undocumented flag. */
-+ output_operand_lossage ("invalid operand output code");
-+ }
-+
-+ if (GET_CODE (x) == REG)
-+ fputs (reg_names[REGNO (x)], file);
-+ else if (GET_CODE (x) == MEM)
-+ {
-+ fputc ('[', file);
-+ /* Poor Sun assembler doesn't understand absolute addressing. */
-+ if (CONSTANT_P (XEXP (x, 0)))
-+ fputs ("%g0+", file);
-+ output_address (GET_MODE (x), XEXP (x, 0));
-+ fputc (']', file);
-+ }
-+ else if (GET_CODE (x) == HIGH)
-+ {
-+ fputs ("%hi(", file);
-+ output_addr_const (file, XEXP (x, 0));
-+ fputc (')', file);
-+ }
-+ else if (GET_CODE (x) == LO_SUM)
-+ {
-+ sparc_print_operand (file, XEXP (x, 0), 0);
-+ if (TARGET_CM_MEDMID)
-+ fputs ("+%l44(", file);
-+ else
-+ fputs ("+%lo(", file);
-+ output_addr_const (file, XEXP (x, 1));
-+ fputc (')', file);
-+ }
-+ else if (GET_CODE (x) == CONST_DOUBLE)
-+ output_operand_lossage ("floating-point constant not a valid immediate operand");
-+ else
-+ output_addr_const (file, x);
-+}
-+
-+/* Implement TARGET_PRINT_OPERAND_ADDRESS. */
-+
-+static void
-+sparc_print_operand_address (FILE *file, machine_mode /*mode*/, rtx x)
-+{
-+ register rtx base, index = 0;
-+ int offset = 0;
-+ register rtx addr = x;
-+
-+ if (REG_P (addr))
-+ fputs (reg_names[REGNO (addr)], file);
-+ else if (GET_CODE (addr) == PLUS)
-+ {
-+ if (CONST_INT_P (XEXP (addr, 0)))
-+ offset = INTVAL (XEXP (addr, 0)), base = XEXP (addr, 1);
-+ else if (CONST_INT_P (XEXP (addr, 1)))
-+ offset = INTVAL (XEXP (addr, 1)), base = XEXP (addr, 0);
-+ else
-+ base = XEXP (addr, 0), index = XEXP (addr, 1);
-+ if (GET_CODE (base) == LO_SUM)
-+ {
-+ gcc_assert (USE_AS_OFFSETABLE_LO10
-+ && TARGET_ARCH64
-+ && ! TARGET_CM_MEDMID);
-+ output_operand (XEXP (base, 0), 0);
-+ fputs ("+%lo(", file);
-+ output_address (VOIDmode, XEXP (base, 1));
-+ fprintf (file, ")+%d", offset);
-+ }
-+ else
-+ {
-+ fputs (reg_names[REGNO (base)], file);
-+ if (index == 0)
-+ fprintf (file, "%+d", offset);
-+ else if (REG_P (index))
-+ fprintf (file, "+%s", reg_names[REGNO (index)]);
-+ else if (GET_CODE (index) == SYMBOL_REF
-+ || GET_CODE (index) == LABEL_REF
-+ || GET_CODE (index) == CONST)
-+ fputc ('+', file), output_addr_const (file, index);
-+ else gcc_unreachable ();
-+ }
-+ }
-+ else if (GET_CODE (addr) == MINUS
-+ && GET_CODE (XEXP (addr, 1)) == LABEL_REF)
-+ {
-+ output_addr_const (file, XEXP (addr, 0));
-+ fputs ("-(", file);
-+ output_addr_const (file, XEXP (addr, 1));
-+ fputs ("-.)", file);
-+ }
-+ else if (GET_CODE (addr) == LO_SUM)
-+ {
-+ output_operand (XEXP (addr, 0), 0);
-+ if (TARGET_CM_MEDMID)
-+ fputs ("+%l44(", file);
-+ else
-+ fputs ("+%lo(", file);
-+ output_address (VOIDmode, XEXP (addr, 1));
-+ fputc (')', file);
-+ }
-+ else if (flag_pic
-+ && GET_CODE (addr) == CONST
-+ && GET_CODE (XEXP (addr, 0)) == MINUS
-+ && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST
-+ && GET_CODE (XEXP (XEXP (XEXP (addr, 0), 1), 0)) == MINUS
-+ && XEXP (XEXP (XEXP (XEXP (addr, 0), 1), 0), 1) == pc_rtx)
-+ {
-+ addr = XEXP (addr, 0);
-+ output_addr_const (file, XEXP (addr, 0));
-+ /* Group the args of the second CONST in parenthesis. */
-+ fputs ("-(", file);
-+ /* Skip past the second CONST--it does nothing for us. */
-+ output_addr_const (file, XEXP (XEXP (addr, 1), 0));
-+ /* Close the parenthesis. */
-+ fputc (')', file);
-+ }
-+ else
-+ {
-+ output_addr_const (file, addr);
-+ }
-+}
-+
-+/* Target hook for assembling integer objects. The sparc version has
-+ special handling for aligned DI-mode objects. */
-+
-+static bool
-+sparc_assemble_integer (rtx x, unsigned int size, int aligned_p)
-+{
-+ /* ??? We only output .xword's for symbols and only then in environments
-+ where the assembler can handle them. */
-+ if (aligned_p && size == 8 && GET_CODE (x) != CONST_INT)
-+ {
-+ if (TARGET_V9)
-+ {
-+ assemble_integer_with_op ("\t.xword\t", x);
-+ return true;
-+ }
-+ else
-+ {
-+ assemble_aligned_integer (4, const0_rtx);
-+ assemble_aligned_integer (4, x);
-+ return true;
-+ }
-+ }
-+ return default_assemble_integer (x, size, aligned_p);
-+}
-+
-+/* Return the value of a code used in the .proc pseudo-op that says
-+ what kind of result this function returns. For non-C types, we pick
-+ the closest C type. */
-+
-+#ifndef SHORT_TYPE_SIZE
-+#define SHORT_TYPE_SIZE (BITS_PER_UNIT * 2)
-+#endif
-+
-+#ifndef INT_TYPE_SIZE
-+#define INT_TYPE_SIZE BITS_PER_WORD
-+#endif
-+
-+#ifndef LONG_TYPE_SIZE
-+#define LONG_TYPE_SIZE BITS_PER_WORD
-+#endif
-+
-+#ifndef LONG_LONG_TYPE_SIZE
-+#define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2)
-+#endif
-+
-+#ifndef FLOAT_TYPE_SIZE
-+#define FLOAT_TYPE_SIZE BITS_PER_WORD
-+#endif
-+
-+#ifndef DOUBLE_TYPE_SIZE
-+#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
-+#endif
-+
-+#ifndef LONG_DOUBLE_TYPE_SIZE
-+#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
-+#endif
-+
-+unsigned long
-+sparc_type_code (register tree type)
-+{
-+ register unsigned long qualifiers = 0;
-+ register unsigned shift;
-+
-+ /* Only the first 30 bits of the qualifier are valid. We must refrain from
-+ setting more, since some assemblers will give an error for this. Also,
-+ we must be careful to avoid shifts of 32 bits or more to avoid getting
-+ unpredictable results. */
-+
-+ for (shift = 6; shift < 30; shift += 2, type = TREE_TYPE (type))
-+ {
-+ switch (TREE_CODE (type))
-+ {
-+ case ERROR_MARK:
-+ return qualifiers;
-+
-+ case ARRAY_TYPE:
-+ qualifiers |= (3 << shift);
-+ break;
-+
-+ case FUNCTION_TYPE:
-+ case METHOD_TYPE:
-+ qualifiers |= (2 << shift);
-+ break;
-+
-+ case POINTER_TYPE:
-+ case REFERENCE_TYPE:
-+ case OFFSET_TYPE:
-+ qualifiers |= (1 << shift);
-+ break;
-+
-+ case RECORD_TYPE:
-+ return (qualifiers | 8);
-+
-+ case UNION_TYPE:
-+ case QUAL_UNION_TYPE:
-+ return (qualifiers | 9);
-+
-+ case ENUMERAL_TYPE:
-+ return (qualifiers | 10);
-+
-+ case VOID_TYPE:
-+ return (qualifiers | 16);
-+
-+ case INTEGER_TYPE:
-+ /* If this is a range type, consider it to be the underlying
-+ type. */
-+ if (TREE_TYPE (type) != 0)
-+ break;
-+
-+ /* Carefully distinguish all the standard types of C,
-+ without messing up if the language is not C. We do this by
-+ testing TYPE_PRECISION and TYPE_UNSIGNED. The old code used to
-+ look at both the names and the above fields, but that's redundant.
-+ Any type whose size is between two C types will be considered
-+ to be the wider of the two types. Also, we do not have a
-+ special code to use for "long long", so anything wider than
-+ long is treated the same. Note that we can't distinguish
-+ between "int" and "long" in this code if they are the same
-+ size, but that's fine, since neither can the assembler. */
-+
-+ if (TYPE_PRECISION (type) <= CHAR_TYPE_SIZE)
-+ return (qualifiers | (TYPE_UNSIGNED (type) ? 12 : 2));
-+
-+ else if (TYPE_PRECISION (type) <= SHORT_TYPE_SIZE)
-+ return (qualifiers | (TYPE_UNSIGNED (type) ? 13 : 3));
-+
-+ else if (TYPE_PRECISION (type) <= INT_TYPE_SIZE)
-+ return (qualifiers | (TYPE_UNSIGNED (type) ? 14 : 4));
-+
-+ else
-+ return (qualifiers | (TYPE_UNSIGNED (type) ? 15 : 5));
-+
-+ case REAL_TYPE:
-+ /* If this is a range type, consider it to be the underlying
-+ type. */
-+ if (TREE_TYPE (type) != 0)
-+ break;
-+
-+ /* Carefully distinguish all the standard types of C,
-+ without messing up if the language is not C. */
-+
-+ if (TYPE_PRECISION (type) == FLOAT_TYPE_SIZE)
-+ return (qualifiers | 6);
-+
-+ else
-+ return (qualifiers | 7);
-+
-+ case COMPLEX_TYPE: /* GNU Fortran COMPLEX type. */
-+ /* ??? We need to distinguish between double and float complex types,
-+ but I don't know how yet because I can't reach this code from
-+ existing front-ends. */
-+ return (qualifiers | 7); /* Who knows? */
-+
-+ case VECTOR_TYPE:
-+ case BOOLEAN_TYPE: /* Boolean truth value type. */
-+ case LANG_TYPE:
-+ case NULLPTR_TYPE:
-+ return qualifiers;
-+
-+ default:
-+ gcc_unreachable (); /* Not a type! */
-+ }
-+ }
-+
-+ return qualifiers;
-+}
-+
-+/* Nested function support. */
-+
-+/* Emit RTL insns to initialize the variable parts of a trampoline.
-+ FNADDR is an RTX for the address of the function's pure code.
-+ CXT is an RTX for the static chain value for the function.
-+
-+ This takes 16 insns: 2 shifts & 2 ands (to split up addresses), 4 sethi
-+ (to load in opcodes), 4 iors (to merge address and opcodes), and 4 writes
-+ (to store insns). This is a bit excessive. Perhaps a different
-+ mechanism would be better here.
-+
-+ Emit enough FLUSH insns to synchronize the data and instruction caches. */
-+
-+static void
-+sparc32_initialize_trampoline (rtx m_tramp, rtx fnaddr, rtx cxt)
-+{
-+ /* SPARC 32-bit trampoline:
-+
-+ sethi %hi(fn), %g1
-+ sethi %hi(static), %g2
-+ jmp %g1+%lo(fn)
-+ or %g2, %lo(static), %g2
-+
-+ SETHI i,r = 00rr rrr1 00ii iiii iiii iiii iiii iiii
-+ JMPL r+i,d = 10dd ddd1 1100 0rrr rr1i iiii iiii iiii
-+ */
-+
-+ emit_move_insn
-+ (adjust_address (m_tramp, SImode, 0),
-+ expand_binop (SImode, ior_optab,
-+ expand_shift (RSHIFT_EXPR, SImode, fnaddr, 10, 0, 1),
-+ GEN_INT (trunc_int_for_mode (0x03000000, SImode)),
-+ NULL_RTX, 1, OPTAB_DIRECT));
-+
-+ emit_move_insn
-+ (adjust_address (m_tramp, SImode, 4),
-+ expand_binop (SImode, ior_optab,
-+ expand_shift (RSHIFT_EXPR, SImode, cxt, 10, 0, 1),
-+ GEN_INT (trunc_int_for_mode (0x05000000, SImode)),
-+ NULL_RTX, 1, OPTAB_DIRECT));
-+
-+ emit_move_insn
-+ (adjust_address (m_tramp, SImode, 8),
-+ expand_binop (SImode, ior_optab,
-+ expand_and (SImode, fnaddr, GEN_INT (0x3ff), NULL_RTX),
-+ GEN_INT (trunc_int_for_mode (0x81c06000, SImode)),
-+ NULL_RTX, 1, OPTAB_DIRECT));
-+
-+ emit_move_insn
-+ (adjust_address (m_tramp, SImode, 12),
-+ expand_binop (SImode, ior_optab,
-+ expand_and (SImode, cxt, GEN_INT (0x3ff), NULL_RTX),
-+ GEN_INT (trunc_int_for_mode (0x8410a000, SImode)),
-+ NULL_RTX, 1, OPTAB_DIRECT));
-+
-+ /* On UltraSPARC a flush flushes an entire cache line. The trampoline is
-+ aligned on a 16 byte boundary so one flush clears it all. */
-+ emit_insn (gen_flushsi (validize_mem (adjust_address (m_tramp, SImode, 0))));
-+ if (sparc_cpu != PROCESSOR_ULTRASPARC
-+ && sparc_cpu != PROCESSOR_ULTRASPARC3
-+ && sparc_cpu != PROCESSOR_NIAGARA
-+ && sparc_cpu != PROCESSOR_NIAGARA2
-+ && sparc_cpu != PROCESSOR_NIAGARA3
-+ && sparc_cpu != PROCESSOR_NIAGARA4
-+ && sparc_cpu != PROCESSOR_NIAGARA7
-+ && sparc_cpu != PROCESSOR_M8)
-+ emit_insn (gen_flushsi (validize_mem (adjust_address (m_tramp, SImode, 8))));
-+
-+ /* Call __enable_execute_stack after writing onto the stack to make sure
-+ the stack address is accessible. */
-+#ifdef HAVE_ENABLE_EXECUTE_STACK
-+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__enable_execute_stack"),
-+ LCT_NORMAL, VOIDmode, XEXP (m_tramp, 0), Pmode);
-+#endif
-+
-+}
-+
-+/* The 64-bit version is simpler because it makes more sense to load the
-+ values as "immediate" data out of the trampoline. It's also easier since
-+ we can read the PC without clobbering a register. */
-+
-+static void
-+sparc64_initialize_trampoline (rtx m_tramp, rtx fnaddr, rtx cxt)
-+{
-+ /* SPARC 64-bit trampoline:
-+
-+ rd %pc, %g1
-+ ldx [%g1+24], %g5
-+ jmp %g5
-+ ldx [%g1+16], %g5
-+ +16 bytes data
-+ */
-+
-+ emit_move_insn (adjust_address (m_tramp, SImode, 0),
-+ GEN_INT (trunc_int_for_mode (0x83414000, SImode)));
-+ emit_move_insn (adjust_address (m_tramp, SImode, 4),
-+ GEN_INT (trunc_int_for_mode (0xca586018, SImode)));
-+ emit_move_insn (adjust_address (m_tramp, SImode, 8),
-+ GEN_INT (trunc_int_for_mode (0x81c14000, SImode)));
-+ emit_move_insn (adjust_address (m_tramp, SImode, 12),
-+ GEN_INT (trunc_int_for_mode (0xca586010, SImode)));
-+ emit_move_insn (adjust_address (m_tramp, DImode, 16), cxt);
-+ emit_move_insn (adjust_address (m_tramp, DImode, 24), fnaddr);
-+ emit_insn (gen_flushdi (validize_mem (adjust_address (m_tramp, DImode, 0))));
-+
-+ if (sparc_cpu != PROCESSOR_ULTRASPARC
-+ && sparc_cpu != PROCESSOR_ULTRASPARC3
-+ && sparc_cpu != PROCESSOR_NIAGARA
-+ && sparc_cpu != PROCESSOR_NIAGARA2
-+ && sparc_cpu != PROCESSOR_NIAGARA3
-+ && sparc_cpu != PROCESSOR_NIAGARA4
-+ && sparc_cpu != PROCESSOR_NIAGARA7
-+ && sparc_cpu != PROCESSOR_M8)
-+ emit_insn (gen_flushdi (validize_mem (adjust_address (m_tramp, DImode, 8))));
-+
-+ /* Call __enable_execute_stack after writing onto the stack to make sure
-+ the stack address is accessible. */
-+#ifdef HAVE_ENABLE_EXECUTE_STACK
-+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__enable_execute_stack"),
-+ LCT_NORMAL, VOIDmode, XEXP (m_tramp, 0), Pmode);
-+#endif
-+}
-+
-+/* Worker for TARGET_TRAMPOLINE_INIT. */
-+
-+static void
-+sparc_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
-+{
-+ rtx fnaddr = force_reg (Pmode, XEXP (DECL_RTL (fndecl), 0));
-+ cxt = force_reg (Pmode, cxt);
-+ if (TARGET_ARCH64)
-+ sparc64_initialize_trampoline (m_tramp, fnaddr, cxt);
-+ else
-+ sparc32_initialize_trampoline (m_tramp, fnaddr, cxt);
-+}
-+
-+/* 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. */
-+
-+static int
-+supersparc_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn,
-+ int cost)
-+{
-+ enum attr_type insn_type;
-+
-+ if (recog_memoized (insn) < 0)
-+ return cost;
-+
-+ insn_type = get_attr_type (insn);
-+
-+ if (dep_type == 0)
-+ {
-+ /* Data dependency; DEP_INSN writes a register that INSN reads some
-+ cycles later. */
-+
-+ /* if a load, then the dependence must be on the memory address;
-+ add an extra "cycle". Note that the cost could be two cycles
-+ if the reg was written late in an instruction group; we ca not tell
-+ here. */
-+ if (insn_type == TYPE_LOAD || insn_type == TYPE_FPLOAD)
-+ return cost + 3;
-+
-+ /* Get the delay only if the address of the store is the dependence. */
-+ if (insn_type == TYPE_STORE || insn_type == TYPE_FPSTORE)
-+ {
-+ rtx pat = PATTERN(insn);
-+ rtx dep_pat = PATTERN (dep_insn);
-+
-+ if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
-+ return cost; /* This should not happen! */
-+
-+ /* The dependency between the two instructions was on the data that
-+ is being stored. Assume that this implies that the address of the
-+ store is not dependent. */
-+ if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat)))
-+ return cost;
-+
-+ return cost + 3; /* An approximation. */
-+ }
-+
-+ /* A shift instruction cannot receive its data from an instruction
-+ in the same cycle; add a one cycle penalty. */
-+ if (insn_type == TYPE_SHIFT)
-+ return cost + 3; /* Split before cascade into shift. */
-+ }
-+ else
-+ {
-+ /* Anti- or output- dependency; DEP_INSN reads/writes a register that
-+ INSN writes some cycles later. */
-+
-+ /* These are only significant for the fpu unit; writing a fp reg before
-+ the fpu has finished with it stalls the processor. */
-+
-+ /* Reusing an integer register causes no problems. */
-+ if (insn_type == TYPE_IALU || insn_type == TYPE_SHIFT)
-+ return 0;
-+ }
-+
-+ return cost;
-+}
-+
-+static int
-+hypersparc_adjust_cost (rtx_insn *insn, int dtype, rtx_insn *dep_insn,
-+ int cost)
-+{
-+ enum attr_type insn_type, dep_type;
-+ rtx pat = PATTERN(insn);
-+ rtx dep_pat = PATTERN (dep_insn);
-+
-+ if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0)
-+ return cost;
-+
-+ insn_type = get_attr_type (insn);
-+ dep_type = get_attr_type (dep_insn);
-+
-+ switch (dtype)
-+ {
-+ case 0:
-+ /* Data dependency; DEP_INSN writes a register that INSN reads some
-+ cycles later. */
-+
-+ switch (insn_type)
-+ {
-+ case TYPE_STORE:
-+ case TYPE_FPSTORE:
-+ /* Get the delay iff the address of the store is the dependence. */
-+ if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
-+ return cost;
-+
-+ if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat)))
-+ return cost;
-+ return cost + 3;
-+
-+ case TYPE_LOAD:
-+ case TYPE_SLOAD:
-+ case TYPE_FPLOAD:
-+ /* If a load, then the dependence must be on the memory address. If
-+ the addresses aren't equal, then it might be a false dependency */
-+ if (dep_type == TYPE_STORE || dep_type == TYPE_FPSTORE)
-+ {
-+ if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET
-+ || GET_CODE (SET_DEST (dep_pat)) != MEM
-+ || GET_CODE (SET_SRC (pat)) != MEM
-+ || ! rtx_equal_p (XEXP (SET_DEST (dep_pat), 0),
-+ XEXP (SET_SRC (pat), 0)))
-+ return cost + 2;
-+
-+ return cost + 8;
-+ }
-+ break;
-+
-+ case TYPE_BRANCH:
-+ /* Compare to branch latency is 0. There is no benefit from
-+ separating compare and branch. */
-+ if (dep_type == TYPE_COMPARE)
-+ return 0;
-+ /* Floating point compare to branch latency is less than
-+ compare to conditional move. */
-+ if (dep_type == TYPE_FPCMP)
-+ return cost - 1;
-+ break;
-+ default:
-+ break;
-+ }
-+ break;
-+
-+ case REG_DEP_ANTI:
-+ /* Anti-dependencies only penalize the fpu unit. */
-+ if (insn_type == TYPE_IALU || insn_type == TYPE_SHIFT)
-+ return 0;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ return cost;
-+}
-+
-+static int
-+sparc_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep, int cost,
-+ unsigned int)
-+{
-+ switch (sparc_cpu)
-+ {
-+ case PROCESSOR_SUPERSPARC:
-+ cost = supersparc_adjust_cost (insn, dep_type, dep, cost);
-+ break;
-+ case PROCESSOR_HYPERSPARC:
-+ case PROCESSOR_SPARCLITE86X:
-+ cost = hypersparc_adjust_cost (insn, dep_type, dep, cost);
-+ break;
-+ default:
-+ break;
-+ }
-+ return cost;
-+}
-+
-+static void
-+sparc_sched_init (FILE *dump ATTRIBUTE_UNUSED,
-+ int sched_verbose ATTRIBUTE_UNUSED,
-+ int max_ready ATTRIBUTE_UNUSED)
-+{}
-+
-+static int
-+sparc_use_sched_lookahead (void)
-+{
-+ switch (sparc_cpu)
-+ {
-+ case PROCESSOR_ULTRASPARC:
-+ case PROCESSOR_ULTRASPARC3:
-+ return 4;
-+ case PROCESSOR_SUPERSPARC:
-+ case PROCESSOR_HYPERSPARC:
-+ case PROCESSOR_SPARCLITE86X:
-+ return 3;
-+ case PROCESSOR_NIAGARA4:
-+ case PROCESSOR_NIAGARA7:
-+ case PROCESSOR_M8:
-+ return 2;
-+ case PROCESSOR_NIAGARA:
-+ case PROCESSOR_NIAGARA2:
-+ case PROCESSOR_NIAGARA3:
-+ default:
-+ return 0;
-+ }
-+}
-+
-+static int
-+sparc_issue_rate (void)
-+{
-+ switch (sparc_cpu)
-+ {
-+ case PROCESSOR_ULTRASPARC:
-+ case PROCESSOR_ULTRASPARC3:
-+ case PROCESSOR_M8:
-+ return 4;
-+ case PROCESSOR_SUPERSPARC:
-+ return 3;
-+ case PROCESSOR_HYPERSPARC:
-+ case PROCESSOR_SPARCLITE86X:
-+ case PROCESSOR_V9:
-+ /* Assume V9 processors are capable of at least dual-issue. */
-+ case PROCESSOR_NIAGARA4:
-+ case PROCESSOR_NIAGARA7:
-+ return 2;
-+ case PROCESSOR_NIAGARA:
-+ case PROCESSOR_NIAGARA2:
-+ case PROCESSOR_NIAGARA3:
-+ default:
-+ return 1;
-+ }
-+}
-+
-+int
-+sparc_branch_cost (bool speed_p, bool predictable_p)
-+{
-+ if (!speed_p)
-+ return 2;
-+
-+ /* For pre-V9 processors we use a single value (usually 3) to take into
-+ account the potential annulling of the delay slot (which ends up being
-+ a bubble in the pipeline slot) plus a cycle to take into consideration
-+ the instruction cache effects.
-+
-+ On V9 and later processors, which have branch prediction facilities,
-+ we take into account whether the branch is (easily) predictable. */
-+ const int cost = sparc_costs->branch_cost;
-+
-+ switch (sparc_cpu)
-+ {
-+ case PROCESSOR_V9:
-+ case PROCESSOR_ULTRASPARC:
-+ case PROCESSOR_ULTRASPARC3:
-+ case PROCESSOR_NIAGARA:
-+ case PROCESSOR_NIAGARA2:
-+ case PROCESSOR_NIAGARA3:
-+ case PROCESSOR_NIAGARA4:
-+ case PROCESSOR_NIAGARA7:
-+ case PROCESSOR_M8:
-+ return cost + (predictable_p ? 0 : 2);
-+
-+ default:
-+ return cost;
-+ }
-+}
-+
-+static int
-+set_extends (rtx_insn *insn)
-+{
-+ register rtx pat = PATTERN (insn);
-+
-+ switch (GET_CODE (SET_SRC (pat)))
-+ {
-+ /* Load and some shift instructions zero extend. */
-+ case MEM:
-+ case ZERO_EXTEND:
-+ /* sethi clears the high bits */
-+ case HIGH:
-+ /* LO_SUM is used with sethi. sethi cleared the high
-+ bits and the values used with lo_sum are positive */
-+ case LO_SUM:
-+ /* Store flag stores 0 or 1 */
-+ case LT: case LTU:
-+ case GT: case GTU:
-+ case LE: case LEU:
-+ case GE: case GEU:
-+ case EQ:
-+ case NE:
-+ return 1;
-+ case AND:
-+ {
-+ rtx op0 = XEXP (SET_SRC (pat), 0);
-+ rtx op1 = XEXP (SET_SRC (pat), 1);
-+ if (GET_CODE (op1) == CONST_INT)
-+ return INTVAL (op1) >= 0;
-+ if (GET_CODE (op0) != REG)
-+ return 0;
-+ if (sparc_check_64 (op0, insn) == 1)
-+ return 1;
-+ return (GET_CODE (op1) == REG && sparc_check_64 (op1, insn) == 1);
-+ }
-+ case IOR:
-+ case XOR:
-+ {
-+ rtx op0 = XEXP (SET_SRC (pat), 0);
-+ rtx op1 = XEXP (SET_SRC (pat), 1);
-+ if (GET_CODE (op0) != REG || sparc_check_64 (op0, insn) <= 0)
-+ return 0;
-+ if (GET_CODE (op1) == CONST_INT)
-+ return INTVAL (op1) >= 0;
-+ return (GET_CODE (op1) == REG && sparc_check_64 (op1, insn) == 1);
-+ }
-+ case LSHIFTRT:
-+ return GET_MODE (SET_SRC (pat)) == SImode;
-+ /* Positive integers leave the high bits zero. */
-+ case CONST_INT:
-+ return !(INTVAL (SET_SRC (pat)) & 0x80000000);
-+ case ASHIFTRT:
-+ case SIGN_EXTEND:
-+ return - (GET_MODE (SET_SRC (pat)) == SImode);
-+ case REG:
-+ return sparc_check_64 (SET_SRC (pat), insn);
-+ default:
-+ return 0;
-+ }
-+}
-+
-+/* We _ought_ to have only one kind per function, but... */
-+static GTY(()) rtx sparc_addr_diff_list;
-+static GTY(()) rtx sparc_addr_list;
-+
-+void
-+sparc_defer_case_vector (rtx lab, rtx vec, int diff)
-+{
-+ vec = gen_rtx_EXPR_LIST (VOIDmode, lab, vec);
-+ if (diff)
-+ sparc_addr_diff_list
-+ = gen_rtx_EXPR_LIST (VOIDmode, vec, sparc_addr_diff_list);
-+ else
-+ sparc_addr_list = gen_rtx_EXPR_LIST (VOIDmode, vec, sparc_addr_list);
-+}
-+
-+static void
-+sparc_output_addr_vec (rtx vec)
-+{
-+ rtx lab = XEXP (vec, 0), body = XEXP (vec, 1);
-+ int idx, vlen = XVECLEN (body, 0);
-+
-+#ifdef ASM_OUTPUT_ADDR_VEC_START
-+ ASM_OUTPUT_ADDR_VEC_START (asm_out_file);
-+#endif
-+
-+#ifdef ASM_OUTPUT_CASE_LABEL
-+ ASM_OUTPUT_CASE_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab),
-+ NEXT_INSN (lab));
-+#else
-+ (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (lab));
-+#endif
-+
-+ for (idx = 0; idx < vlen; idx++)
-+ {
-+ ASM_OUTPUT_ADDR_VEC_ELT
-+ (asm_out_file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
-+ }
-+
-+#ifdef ASM_OUTPUT_ADDR_VEC_END
-+ ASM_OUTPUT_ADDR_VEC_END (asm_out_file);
-+#endif
-+}
-+
-+static void
-+sparc_output_addr_diff_vec (rtx vec)
-+{
-+ rtx lab = XEXP (vec, 0), body = XEXP (vec, 1);
-+ rtx base = XEXP (XEXP (body, 0), 0);
-+ int idx, vlen = XVECLEN (body, 1);
-+
-+#ifdef ASM_OUTPUT_ADDR_VEC_START
-+ ASM_OUTPUT_ADDR_VEC_START (asm_out_file);
-+#endif
-+
-+#ifdef ASM_OUTPUT_CASE_LABEL
-+ ASM_OUTPUT_CASE_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (lab),
-+ NEXT_INSN (lab));
-+#else
-+ (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (lab));
-+#endif
-+
-+ for (idx = 0; idx < vlen; idx++)
-+ {
-+ ASM_OUTPUT_ADDR_DIFF_ELT
-+ (asm_out_file,
-+ body,
-+ CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)),
-+ CODE_LABEL_NUMBER (base));
-+ }
-+
-+#ifdef ASM_OUTPUT_ADDR_VEC_END
-+ ASM_OUTPUT_ADDR_VEC_END (asm_out_file);
-+#endif
-+}
-+
-+static void
-+sparc_output_deferred_case_vectors (void)
-+{
-+ rtx t;
-+ int align;
-+
-+ if (sparc_addr_list == NULL_RTX
-+ && sparc_addr_diff_list == NULL_RTX)
-+ return;
-+
-+ /* Align to cache line in the function's code section. */
-+ switch_to_section (current_function_section ());
-+
-+ align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
-+ if (align > 0)
-+ ASM_OUTPUT_ALIGN (asm_out_file, align);
-+
-+ for (t = sparc_addr_list; t ; t = XEXP (t, 1))
-+ sparc_output_addr_vec (XEXP (t, 0));
-+ for (t = sparc_addr_diff_list; t ; t = XEXP (t, 1))
-+ sparc_output_addr_diff_vec (XEXP (t, 0));
-+
-+ sparc_addr_list = sparc_addr_diff_list = NULL_RTX;
-+}
-+
-+/* Return 0 if the high 32 bits of X (the low word of X, if DImode) are
-+ unknown. Return 1 if the high bits are zero, -1 if the register is
-+ sign extended. */
-+int
-+sparc_check_64 (rtx x, rtx_insn *insn)
-+{
-+ /* If a register is set only once it is safe to ignore insns this
-+ code does not know how to handle. The loop will either recognize
-+ the single set and return the correct value or fail to recognize
-+ it and return 0. */
-+ int set_once = 0;
-+ rtx y = x;
-+
-+ gcc_assert (GET_CODE (x) == REG);
-+
-+ if (GET_MODE (x) == DImode)
-+ y = gen_rtx_REG (SImode, REGNO (x) + WORDS_BIG_ENDIAN);
-+
-+ if (flag_expensive_optimizations
-+ && df && DF_REG_DEF_COUNT (REGNO (y)) == 1)
-+ set_once = 1;
-+
-+ if (insn == 0)
-+ {
-+ if (set_once)
-+ insn = get_last_insn_anywhere ();
-+ else
-+ return 0;
-+ }
-+
-+ while ((insn = PREV_INSN (insn)))
-+ {
-+ switch (GET_CODE (insn))
-+ {
-+ case JUMP_INSN:
-+ case NOTE:
-+ break;
-+ case CODE_LABEL:
-+ case CALL_INSN:
-+ default:
-+ if (! set_once)
-+ return 0;
-+ break;
-+ case INSN:
-+ {
-+ rtx pat = PATTERN (insn);
-+ if (GET_CODE (pat) != SET)
-+ return 0;
-+ if (rtx_equal_p (x, SET_DEST (pat)))
-+ return set_extends (insn);
-+ if (y && rtx_equal_p (y, SET_DEST (pat)))
-+ return set_extends (insn);
-+ if (reg_overlap_mentioned_p (SET_DEST (pat), y))
-+ return 0;
-+ }
-+ }
-+ }
-+ return 0;
-+}
-+
-+/* Output a wide shift instruction in V8+ mode. INSN is the instruction,
-+ OPERANDS are its operands and OPCODE is the mnemonic to be used. */
-+
-+const char *
-+output_v8plus_shift (rtx_insn *insn, rtx *operands, const char *opcode)
-+{
-+ static char asm_code[60];
-+
-+ /* The scratch register is only required when the destination
-+ register is not a 64-bit global or out register. */
-+ if (which_alternative != 2)
-+ operands[3] = operands[0];
-+
-+ /* We can only shift by constants <= 63. */
-+ if (GET_CODE (operands[2]) == CONST_INT)
-+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
-+
-+ if (GET_CODE (operands[1]) == CONST_INT)
-+ {
-+ output_asm_insn ("mov\t%1, %3", operands);
-+ }
-+ else
-+ {
-+ output_asm_insn ("sllx\t%H1, 32, %3", operands);
-+ if (sparc_check_64 (operands[1], insn) <= 0)
-+ output_asm_insn ("srl\t%L1, 0, %L1", operands);
-+ output_asm_insn ("or\t%L1, %3, %3", operands);
-+ }
-+
-+ strcpy (asm_code, opcode);
-+
-+ if (which_alternative != 2)
-+ return strcat (asm_code, "\t%0, %2, %L0\n\tsrlx\t%L0, 32, %H0");
-+ else
-+ return
-+ strcat (asm_code, "\t%3, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0");
-+}
-+
-+/* Output rtl to increment the profiler label LABELNO
-+ for profiling a function entry. */
-+
-+void
-+sparc_profile_hook (int labelno)
-+{
-+ char buf[32];
-+ rtx lab, fun;
-+
-+ fun = gen_rtx_SYMBOL_REF (Pmode, MCOUNT_FUNCTION);
-+ if (NO_PROFILE_COUNTERS)
-+ {
-+ emit_library_call (fun, LCT_NORMAL, VOIDmode);
-+ }
-+ else
-+ {
-+ ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
-+ lab = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
-+ emit_library_call (fun, LCT_NORMAL, VOIDmode, lab, Pmode);
-+ }
-+}
-+
-+#ifdef TARGET_SOLARIS
-+/* Solaris implementation of TARGET_ASM_NAMED_SECTION. */
-+
-+static void
-+sparc_solaris_elf_asm_named_section (const char *name, unsigned int flags,
-+ tree decl ATTRIBUTE_UNUSED)
-+{
-+ if (HAVE_COMDAT_GROUP && flags & SECTION_LINKONCE)
-+ {
-+ solaris_elf_asm_comdat_section (name, flags, decl);
-+ return;
-+ }
-+
-+ fprintf (asm_out_file, "\t.section\t\"%s\"", name);
-+
-+ if (!(flags & SECTION_DEBUG))
-+ fputs (",#alloc", asm_out_file);
-+#if HAVE_GAS_SECTION_EXCLUDE
-+ if (flags & SECTION_EXCLUDE)
-+ fputs (",#exclude", asm_out_file);
-+#endif
-+ if (flags & SECTION_WRITE)
-+ fputs (",#write", asm_out_file);
-+ if (flags & SECTION_TLS)
-+ fputs (",#tls", asm_out_file);
-+ if (flags & SECTION_CODE)
-+ fputs (",#execinstr", asm_out_file);
-+
-+ if (flags & SECTION_NOTYPE)
-+ ;
-+ else if (flags & SECTION_BSS)
-+ fputs (",#nobits", asm_out_file);
-+ else
-+ fputs (",#progbits", asm_out_file);
-+
-+ fputc ('\n', asm_out_file);
-+}
-+#endif /* TARGET_SOLARIS */
-+
-+/* We do not allow indirect calls to be optimized into sibling calls.
-+
-+ We cannot use sibling calls when delayed branches are disabled
-+ because they will likely require the call delay slot to be filled.
-+
-+ Also, on SPARC 32-bit we cannot emit a sibling call when the
-+ current function returns a structure. This is because the "unimp
-+ after call" convention would cause the callee to return to the
-+ wrong place. The generic code already disallows cases where the
-+ function being called returns a structure.
-+
-+ It may seem strange how this last case could occur. Usually there
-+ is code after the call which jumps to epilogue code which dumps the
-+ return value into the struct return area. That ought to invalidate
-+ the sibling call right? Well, in the C++ case we can end up passing
-+ the pointer to the struct return area to a constructor (which returns
-+ void) and then nothing else happens. Such a sibling call would look
-+ valid without the added check here.
-+
-+ VxWorks PIC PLT entries require the global pointer to be initialized
-+ on entry. We therefore can't emit sibling calls to them. */
-+static bool
-+sparc_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
-+{
-+ return (decl
-+ && flag_delayed_branch
-+ && (TARGET_ARCH64 || ! cfun->returns_struct)
-+ && !(TARGET_VXWORKS_RTP
-+ && flag_pic
-+ && !targetm.binds_local_p (decl)));
-+}
-+
-+/* libfunc renaming. */
-+
-+static void
-+sparc_init_libfuncs (void)
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ /* Use the subroutines that Sun's library provides for integer
-+ multiply and divide. The `*' prevents an underscore from
-+ being prepended by the compiler. .umul is a little faster
-+ than .mul. */
-+ set_optab_libfunc (smul_optab, SImode, "*.umul");
-+ set_optab_libfunc (sdiv_optab, SImode, "*.div");
-+ set_optab_libfunc (udiv_optab, SImode, "*.udiv");
-+ set_optab_libfunc (smod_optab, SImode, "*.rem");
-+ set_optab_libfunc (umod_optab, SImode, "*.urem");
-+
-+ /* TFmode arithmetic. These names are part of the SPARC 32bit ABI. */
-+ set_optab_libfunc (add_optab, TFmode, "_Q_add");
-+ set_optab_libfunc (sub_optab, TFmode, "_Q_sub");
-+ set_optab_libfunc (neg_optab, TFmode, "_Q_neg");
-+ set_optab_libfunc (smul_optab, TFmode, "_Q_mul");
-+ set_optab_libfunc (sdiv_optab, TFmode, "_Q_div");
-+
-+ /* We can define the TFmode sqrt optab only if TARGET_FPU. This
-+ is because with soft-float, the SFmode and DFmode sqrt
-+ instructions will be absent, and the compiler will notice and
-+ try to use the TFmode sqrt instruction for calls to the
-+ builtin function sqrt, but this fails. */
-+ if (TARGET_FPU)
-+ set_optab_libfunc (sqrt_optab, TFmode, "_Q_sqrt");
-+
-+ set_optab_libfunc (eq_optab, TFmode, "_Q_feq");
-+ set_optab_libfunc (ne_optab, TFmode, "_Q_fne");
-+ set_optab_libfunc (gt_optab, TFmode, "_Q_fgt");
-+ set_optab_libfunc (ge_optab, TFmode, "_Q_fge");
-+ set_optab_libfunc (lt_optab, TFmode, "_Q_flt");
-+ set_optab_libfunc (le_optab, TFmode, "_Q_fle");
-+
-+ set_conv_libfunc (sext_optab, TFmode, SFmode, "_Q_stoq");
-+ set_conv_libfunc (sext_optab, TFmode, DFmode, "_Q_dtoq");
-+ set_conv_libfunc (trunc_optab, SFmode, TFmode, "_Q_qtos");
-+ set_conv_libfunc (trunc_optab, DFmode, TFmode, "_Q_qtod");
-+
-+ set_conv_libfunc (sfix_optab, SImode, TFmode, "_Q_qtoi");
-+ set_conv_libfunc (ufix_optab, SImode, TFmode, "_Q_qtou");
-+ set_conv_libfunc (sfloat_optab, TFmode, SImode, "_Q_itoq");
-+ set_conv_libfunc (ufloat_optab, TFmode, SImode, "_Q_utoq");
-+
-+ if (DITF_CONVERSION_LIBFUNCS)
-+ {
-+ set_conv_libfunc (sfix_optab, DImode, TFmode, "_Q_qtoll");
-+ set_conv_libfunc (ufix_optab, DImode, TFmode, "_Q_qtoull");
-+ set_conv_libfunc (sfloat_optab, TFmode, DImode, "_Q_lltoq");
-+ set_conv_libfunc (ufloat_optab, TFmode, DImode, "_Q_ulltoq");
-+ }
-+
-+ if (SUN_CONVERSION_LIBFUNCS)
-+ {
-+ set_conv_libfunc (sfix_optab, DImode, SFmode, "__ftoll");
-+ set_conv_libfunc (ufix_optab, DImode, SFmode, "__ftoull");
-+ set_conv_libfunc (sfix_optab, DImode, DFmode, "__dtoll");
-+ set_conv_libfunc (ufix_optab, DImode, DFmode, "__dtoull");
-+ }
-+ }
-+ if (TARGET_ARCH64)
-+ {
-+ /* In the SPARC 64bit ABI, SImode multiply and divide functions
-+ do not exist in the library. Make sure the compiler does not
-+ emit calls to them by accident. (It should always use the
-+ hardware instructions.) */
-+ set_optab_libfunc (smul_optab, SImode, 0);
-+ set_optab_libfunc (sdiv_optab, SImode, 0);
-+ set_optab_libfunc (udiv_optab, SImode, 0);
-+ set_optab_libfunc (smod_optab, SImode, 0);
-+ set_optab_libfunc (umod_optab, SImode, 0);
-+
-+ if (SUN_INTEGER_MULTIPLY_64)
-+ {
-+ set_optab_libfunc (smul_optab, DImode, "__mul64");
-+ set_optab_libfunc (sdiv_optab, DImode, "__div64");
-+ set_optab_libfunc (udiv_optab, DImode, "__udiv64");
-+ set_optab_libfunc (smod_optab, DImode, "__rem64");
-+ set_optab_libfunc (umod_optab, DImode, "__urem64");
-+ }
-+
-+ if (SUN_CONVERSION_LIBFUNCS)
-+ {
-+ set_conv_libfunc (sfix_optab, DImode, SFmode, "__ftol");
-+ set_conv_libfunc (ufix_optab, DImode, SFmode, "__ftoul");
-+ set_conv_libfunc (sfix_optab, DImode, DFmode, "__dtol");
-+ set_conv_libfunc (ufix_optab, DImode, DFmode, "__dtoul");
-+ }
-+ }
-+}
-+
-+/* SPARC builtins. */
-+enum sparc_builtins
-+{
-+ /* FPU builtins. */
-+ SPARC_BUILTIN_LDFSR,
-+ SPARC_BUILTIN_STFSR,
-+
-+ /* VIS 1.0 builtins. */
-+ SPARC_BUILTIN_FPACK16,
-+ SPARC_BUILTIN_FPACK32,
-+ SPARC_BUILTIN_FPACKFIX,
-+ SPARC_BUILTIN_FEXPAND,
-+ SPARC_BUILTIN_FPMERGE,
-+ SPARC_BUILTIN_FMUL8X16,
-+ SPARC_BUILTIN_FMUL8X16AU,
-+ SPARC_BUILTIN_FMUL8X16AL,
-+ SPARC_BUILTIN_FMUL8SUX16,
-+ SPARC_BUILTIN_FMUL8ULX16,
-+ SPARC_BUILTIN_FMULD8SUX16,
-+ SPARC_BUILTIN_FMULD8ULX16,
-+ SPARC_BUILTIN_FALIGNDATAV4HI,
-+ SPARC_BUILTIN_FALIGNDATAV8QI,
-+ SPARC_BUILTIN_FALIGNDATAV2SI,
-+ SPARC_BUILTIN_FALIGNDATADI,
-+ SPARC_BUILTIN_WRGSR,
-+ SPARC_BUILTIN_RDGSR,
-+ SPARC_BUILTIN_ALIGNADDR,
-+ SPARC_BUILTIN_ALIGNADDRL,
-+ SPARC_BUILTIN_PDIST,
-+ SPARC_BUILTIN_EDGE8,
-+ SPARC_BUILTIN_EDGE8L,
-+ SPARC_BUILTIN_EDGE16,
-+ SPARC_BUILTIN_EDGE16L,
-+ SPARC_BUILTIN_EDGE32,
-+ SPARC_BUILTIN_EDGE32L,
-+ SPARC_BUILTIN_FCMPLE16,
-+ SPARC_BUILTIN_FCMPLE32,
-+ SPARC_BUILTIN_FCMPNE16,
-+ SPARC_BUILTIN_FCMPNE32,
-+ SPARC_BUILTIN_FCMPGT16,
-+ SPARC_BUILTIN_FCMPGT32,
-+ SPARC_BUILTIN_FCMPEQ16,
-+ SPARC_BUILTIN_FCMPEQ32,
-+ SPARC_BUILTIN_FPADD16,
-+ SPARC_BUILTIN_FPADD16S,
-+ SPARC_BUILTIN_FPADD32,
-+ SPARC_BUILTIN_FPADD32S,
-+ SPARC_BUILTIN_FPSUB16,
-+ SPARC_BUILTIN_FPSUB16S,
-+ SPARC_BUILTIN_FPSUB32,
-+ SPARC_BUILTIN_FPSUB32S,
-+ SPARC_BUILTIN_ARRAY8,
-+ SPARC_BUILTIN_ARRAY16,
-+ SPARC_BUILTIN_ARRAY32,
-+
-+ /* VIS 2.0 builtins. */
-+ SPARC_BUILTIN_EDGE8N,
-+ SPARC_BUILTIN_EDGE8LN,
-+ SPARC_BUILTIN_EDGE16N,
-+ SPARC_BUILTIN_EDGE16LN,
-+ SPARC_BUILTIN_EDGE32N,
-+ SPARC_BUILTIN_EDGE32LN,
-+ SPARC_BUILTIN_BMASK,
-+ SPARC_BUILTIN_BSHUFFLEV4HI,
-+ SPARC_BUILTIN_BSHUFFLEV8QI,
-+ SPARC_BUILTIN_BSHUFFLEV2SI,
-+ SPARC_BUILTIN_BSHUFFLEDI,
-+
-+ /* VIS 3.0 builtins. */
-+ SPARC_BUILTIN_CMASK8,
-+ SPARC_BUILTIN_CMASK16,
-+ SPARC_BUILTIN_CMASK32,
-+ SPARC_BUILTIN_FCHKSM16,
-+ SPARC_BUILTIN_FSLL16,
-+ SPARC_BUILTIN_FSLAS16,
-+ SPARC_BUILTIN_FSRL16,
-+ SPARC_BUILTIN_FSRA16,
-+ SPARC_BUILTIN_FSLL32,
-+ SPARC_BUILTIN_FSLAS32,
-+ SPARC_BUILTIN_FSRL32,
-+ SPARC_BUILTIN_FSRA32,
-+ SPARC_BUILTIN_PDISTN,
-+ SPARC_BUILTIN_FMEAN16,
-+ SPARC_BUILTIN_FPADD64,
-+ SPARC_BUILTIN_FPSUB64,
-+ SPARC_BUILTIN_FPADDS16,
-+ SPARC_BUILTIN_FPADDS16S,
-+ SPARC_BUILTIN_FPSUBS16,
-+ SPARC_BUILTIN_FPSUBS16S,
-+ SPARC_BUILTIN_FPADDS32,
-+ SPARC_BUILTIN_FPADDS32S,
-+ SPARC_BUILTIN_FPSUBS32,
-+ SPARC_BUILTIN_FPSUBS32S,
-+ SPARC_BUILTIN_FUCMPLE8,
-+ SPARC_BUILTIN_FUCMPNE8,
-+ SPARC_BUILTIN_FUCMPGT8,
-+ SPARC_BUILTIN_FUCMPEQ8,
-+ SPARC_BUILTIN_FHADDS,
-+ SPARC_BUILTIN_FHADDD,
-+ SPARC_BUILTIN_FHSUBS,
-+ SPARC_BUILTIN_FHSUBD,
-+ SPARC_BUILTIN_FNHADDS,
-+ SPARC_BUILTIN_FNHADDD,
-+ SPARC_BUILTIN_UMULXHI,
-+ SPARC_BUILTIN_XMULX,
-+ SPARC_BUILTIN_XMULXHI,
-+
-+ /* VIS 4.0 builtins. */
-+ SPARC_BUILTIN_FPADD8,
-+ SPARC_BUILTIN_FPADDS8,
-+ SPARC_BUILTIN_FPADDUS8,
-+ SPARC_BUILTIN_FPADDUS16,
-+ SPARC_BUILTIN_FPCMPLE8,
-+ SPARC_BUILTIN_FPCMPGT8,
-+ SPARC_BUILTIN_FPCMPULE16,
-+ SPARC_BUILTIN_FPCMPUGT16,
-+ SPARC_BUILTIN_FPCMPULE32,
-+ SPARC_BUILTIN_FPCMPUGT32,
-+ SPARC_BUILTIN_FPMAX8,
-+ SPARC_BUILTIN_FPMAX16,
-+ SPARC_BUILTIN_FPMAX32,
-+ SPARC_BUILTIN_FPMAXU8,
-+ SPARC_BUILTIN_FPMAXU16,
-+ SPARC_BUILTIN_FPMAXU32,
-+ SPARC_BUILTIN_FPMIN8,
-+ SPARC_BUILTIN_FPMIN16,
-+ SPARC_BUILTIN_FPMIN32,
-+ SPARC_BUILTIN_FPMINU8,
-+ SPARC_BUILTIN_FPMINU16,
-+ SPARC_BUILTIN_FPMINU32,
-+ SPARC_BUILTIN_FPSUB8,
-+ SPARC_BUILTIN_FPSUBS8,
-+ SPARC_BUILTIN_FPSUBUS8,
-+ SPARC_BUILTIN_FPSUBUS16,
-+
-+ /* VIS 4.0B builtins. */
-+
-+ /* Note that all the DICTUNPACK* entries should be kept
-+ contiguous. */
-+ SPARC_BUILTIN_FIRST_DICTUNPACK,
-+ SPARC_BUILTIN_DICTUNPACK8 = SPARC_BUILTIN_FIRST_DICTUNPACK,
-+ SPARC_BUILTIN_DICTUNPACK16,
-+ SPARC_BUILTIN_DICTUNPACK32,
-+ SPARC_BUILTIN_LAST_DICTUNPACK = SPARC_BUILTIN_DICTUNPACK32,
-+
-+ /* Note that all the FPCMP*SHL entries should be kept
-+ contiguous. */
-+ SPARC_BUILTIN_FIRST_FPCMPSHL,
-+ SPARC_BUILTIN_FPCMPLE8SHL = SPARC_BUILTIN_FIRST_FPCMPSHL,
-+ SPARC_BUILTIN_FPCMPGT8SHL,
-+ SPARC_BUILTIN_FPCMPEQ8SHL,
-+ SPARC_BUILTIN_FPCMPNE8SHL,
-+ SPARC_BUILTIN_FPCMPLE16SHL,
-+ SPARC_BUILTIN_FPCMPGT16SHL,
-+ SPARC_BUILTIN_FPCMPEQ16SHL,
-+ SPARC_BUILTIN_FPCMPNE16SHL,
-+ SPARC_BUILTIN_FPCMPLE32SHL,
-+ SPARC_BUILTIN_FPCMPGT32SHL,
-+ SPARC_BUILTIN_FPCMPEQ32SHL,
-+ SPARC_BUILTIN_FPCMPNE32SHL,
-+ SPARC_BUILTIN_FPCMPULE8SHL,
-+ SPARC_BUILTIN_FPCMPUGT8SHL,
-+ SPARC_BUILTIN_FPCMPULE16SHL,
-+ SPARC_BUILTIN_FPCMPUGT16SHL,
-+ SPARC_BUILTIN_FPCMPULE32SHL,
-+ SPARC_BUILTIN_FPCMPUGT32SHL,
-+ SPARC_BUILTIN_FPCMPDE8SHL,
-+ SPARC_BUILTIN_FPCMPDE16SHL,
-+ SPARC_BUILTIN_FPCMPDE32SHL,
-+ SPARC_BUILTIN_FPCMPUR8SHL,
-+ SPARC_BUILTIN_FPCMPUR16SHL,
-+ SPARC_BUILTIN_FPCMPUR32SHL,
-+ SPARC_BUILTIN_LAST_FPCMPSHL = SPARC_BUILTIN_FPCMPUR32SHL,
-+
-+ SPARC_BUILTIN_MAX
-+};
-+
-+static GTY (()) tree sparc_builtins[(int) SPARC_BUILTIN_MAX];
-+static enum insn_code sparc_builtins_icode[(int) SPARC_BUILTIN_MAX];
-+
-+/* Return true if OPVAL can be used for operand OPNUM of instruction ICODE.
-+ The instruction should require a constant operand of some sort. The
-+ function prints an error if OPVAL is not valid. */
-+
-+static int
-+check_constant_argument (enum insn_code icode, int opnum, rtx opval)
-+{
-+ if (GET_CODE (opval) != CONST_INT)
-+ {
-+ error ("%qs expects a constant argument", insn_data[icode].name);
-+ return false;
-+ }
-+
-+ if (!(*insn_data[icode].operand[opnum].predicate) (opval, VOIDmode))
-+ {
-+ error ("constant argument out of range for %qs", insn_data[icode].name);
-+ return false;
-+ }
-+ return true;
-+}
-+
-+/* Add a SPARC builtin function with NAME, ICODE, CODE and TYPE. Return the
-+ function decl or NULL_TREE if the builtin was not added. */
-+
-+static tree
-+def_builtin (const char *name, enum insn_code icode, enum sparc_builtins code,
-+ tree type)
-+{
-+ tree t
-+ = add_builtin_function (name, type, code, BUILT_IN_MD, NULL, NULL_TREE);
-+
-+ if (t)
-+ {
-+ sparc_builtins[code] = t;
-+ sparc_builtins_icode[code] = icode;
-+ }
-+
-+ return t;
-+}
-+
-+/* Likewise, but also marks the function as "const". */
-+
-+static tree
-+def_builtin_const (const char *name, enum insn_code icode,
-+ enum sparc_builtins code, tree type)
-+{
-+ tree t = def_builtin (name, icode, code, type);
-+
-+ if (t)
-+ TREE_READONLY (t) = 1;
-+
-+ return t;
-+}
-+
-+/* Implement the TARGET_INIT_BUILTINS target hook.
-+ Create builtin functions for special SPARC instructions. */
-+
-+static void
-+sparc_init_builtins (void)
-+{
-+ if (TARGET_FPU)
-+ sparc_fpu_init_builtins ();
-+
-+ if (TARGET_VIS)
-+ sparc_vis_init_builtins ();
-+}
-+
-+/* Create builtin functions for FPU instructions. */
-+
-+static void
-+sparc_fpu_init_builtins (void)
-+{
-+ tree ftype
-+ = build_function_type_list (void_type_node,
-+ build_pointer_type (unsigned_type_node), 0);
-+ def_builtin ("__builtin_load_fsr", CODE_FOR_ldfsr,
-+ SPARC_BUILTIN_LDFSR, ftype);
-+ def_builtin ("__builtin_store_fsr", CODE_FOR_stfsr,
-+ SPARC_BUILTIN_STFSR, ftype);
-+}
-+
-+/* Create builtin functions for VIS instructions. */
-+
-+static void
-+sparc_vis_init_builtins (void)
-+{
-+ tree v4qi = build_vector_type (unsigned_intQI_type_node, 4);
-+ tree v8qi = build_vector_type (unsigned_intQI_type_node, 8);
-+ tree v4hi = build_vector_type (intHI_type_node, 4);
-+ tree v2hi = build_vector_type (intHI_type_node, 2);
-+ tree v2si = build_vector_type (intSI_type_node, 2);
-+ tree v1si = build_vector_type (intSI_type_node, 1);
-+
-+ tree v4qi_ftype_v4hi = build_function_type_list (v4qi, v4hi, 0);
-+ tree v8qi_ftype_v2si_v8qi = build_function_type_list (v8qi, v2si, v8qi, 0);
-+ tree v2hi_ftype_v2si = build_function_type_list (v2hi, v2si, 0);
-+ tree v4hi_ftype_v4qi = build_function_type_list (v4hi, v4qi, 0);
-+ tree v8qi_ftype_v4qi_v4qi = build_function_type_list (v8qi, v4qi, v4qi, 0);
-+ tree v4hi_ftype_v4qi_v4hi = build_function_type_list (v4hi, v4qi, v4hi, 0);
-+ tree v4hi_ftype_v4qi_v2hi = build_function_type_list (v4hi, v4qi, v2hi, 0);
-+ tree v2si_ftype_v4qi_v2hi = build_function_type_list (v2si, v4qi, v2hi, 0);
-+ tree v4hi_ftype_v8qi_v4hi = build_function_type_list (v4hi, v8qi, v4hi, 0);
-+ tree v4hi_ftype_v4hi_v4hi = build_function_type_list (v4hi, v4hi, v4hi, 0);
-+ tree v2si_ftype_v2si_v2si = build_function_type_list (v2si, v2si, v2si, 0);
-+ tree v8qi_ftype_v8qi_v8qi = build_function_type_list (v8qi, v8qi, v8qi, 0);
-+ tree v2hi_ftype_v2hi_v2hi = build_function_type_list (v2hi, v2hi, v2hi, 0);
-+ tree v1si_ftype_v1si_v1si = build_function_type_list (v1si, v1si, v1si, 0);
-+ tree di_ftype_v8qi_v8qi_di = build_function_type_list (intDI_type_node,
-+ v8qi, v8qi,
-+ intDI_type_node, 0);
-+ tree di_ftype_v8qi_v8qi = build_function_type_list (intDI_type_node,
-+ v8qi, v8qi, 0);
-+ tree si_ftype_v8qi_v8qi = build_function_type_list (intSI_type_node,
-+ v8qi, v8qi, 0);
-+ tree v8qi_ftype_df_si = build_function_type_list (v8qi, double_type_node,
-+ intSI_type_node, 0);
-+ tree v4hi_ftype_df_si = build_function_type_list (v4hi, double_type_node,
-+ intSI_type_node, 0);
-+ tree v2si_ftype_df_si = build_function_type_list (v2si, double_type_node,
-+ intDI_type_node, 0);
-+ tree di_ftype_di_di = build_function_type_list (intDI_type_node,
-+ intDI_type_node,
-+ intDI_type_node, 0);
-+ tree si_ftype_si_si = build_function_type_list (intSI_type_node,
-+ intSI_type_node,
-+ intSI_type_node, 0);
-+ tree ptr_ftype_ptr_si = build_function_type_list (ptr_type_node,
-+ ptr_type_node,
-+ intSI_type_node, 0);
-+ tree ptr_ftype_ptr_di = build_function_type_list (ptr_type_node,
-+ ptr_type_node,
-+ intDI_type_node, 0);
-+ tree si_ftype_ptr_ptr = build_function_type_list (intSI_type_node,
-+ ptr_type_node,
-+ ptr_type_node, 0);
-+ tree di_ftype_ptr_ptr = build_function_type_list (intDI_type_node,
-+ ptr_type_node,
-+ ptr_type_node, 0);
-+ tree si_ftype_v4hi_v4hi = build_function_type_list (intSI_type_node,
-+ v4hi, v4hi, 0);
-+ tree si_ftype_v2si_v2si = build_function_type_list (intSI_type_node,
-+ v2si, v2si, 0);
-+ tree di_ftype_v4hi_v4hi = build_function_type_list (intDI_type_node,
-+ v4hi, v4hi, 0);
-+ tree di_ftype_v2si_v2si = build_function_type_list (intDI_type_node,
-+ v2si, v2si, 0);
-+ tree void_ftype_di = build_function_type_list (void_type_node,
-+ intDI_type_node, 0);
-+ tree di_ftype_void = build_function_type_list (intDI_type_node,
-+ void_type_node, 0);
-+ tree void_ftype_si = build_function_type_list (void_type_node,
-+ intSI_type_node, 0);
-+ tree sf_ftype_sf_sf = build_function_type_list (float_type_node,
-+ float_type_node,
-+ float_type_node, 0);
-+ tree df_ftype_df_df = build_function_type_list (double_type_node,
-+ double_type_node,
-+ double_type_node, 0);
-+
-+ /* Packing and expanding vectors. */
-+ def_builtin ("__builtin_vis_fpack16", CODE_FOR_fpack16_vis,
-+ SPARC_BUILTIN_FPACK16, v4qi_ftype_v4hi);
-+ def_builtin ("__builtin_vis_fpack32", CODE_FOR_fpack32_vis,
-+ SPARC_BUILTIN_FPACK32, v8qi_ftype_v2si_v8qi);
-+ def_builtin ("__builtin_vis_fpackfix", CODE_FOR_fpackfix_vis,
-+ SPARC_BUILTIN_FPACKFIX, v2hi_ftype_v2si);
-+ def_builtin_const ("__builtin_vis_fexpand", CODE_FOR_fexpand_vis,
-+ SPARC_BUILTIN_FEXPAND, v4hi_ftype_v4qi);
-+ def_builtin_const ("__builtin_vis_fpmerge", CODE_FOR_fpmerge_vis,
-+ SPARC_BUILTIN_FPMERGE, v8qi_ftype_v4qi_v4qi);
-+
-+ /* Multiplications. */
-+ def_builtin_const ("__builtin_vis_fmul8x16", CODE_FOR_fmul8x16_vis,
-+ SPARC_BUILTIN_FMUL8X16, v4hi_ftype_v4qi_v4hi);
-+ def_builtin_const ("__builtin_vis_fmul8x16au", CODE_FOR_fmul8x16au_vis,
-+ SPARC_BUILTIN_FMUL8X16AU, v4hi_ftype_v4qi_v2hi);
-+ def_builtin_const ("__builtin_vis_fmul8x16al", CODE_FOR_fmul8x16al_vis,
-+ SPARC_BUILTIN_FMUL8X16AL, v4hi_ftype_v4qi_v2hi);
-+ def_builtin_const ("__builtin_vis_fmul8sux16", CODE_FOR_fmul8sux16_vis,
-+ SPARC_BUILTIN_FMUL8SUX16, v4hi_ftype_v8qi_v4hi);
-+ def_builtin_const ("__builtin_vis_fmul8ulx16", CODE_FOR_fmul8ulx16_vis,
-+ SPARC_BUILTIN_FMUL8ULX16, v4hi_ftype_v8qi_v4hi);
-+ def_builtin_const ("__builtin_vis_fmuld8sux16", CODE_FOR_fmuld8sux16_vis,
-+ SPARC_BUILTIN_FMULD8SUX16, v2si_ftype_v4qi_v2hi);
-+ def_builtin_const ("__builtin_vis_fmuld8ulx16", CODE_FOR_fmuld8ulx16_vis,
-+ SPARC_BUILTIN_FMULD8ULX16, v2si_ftype_v4qi_v2hi);
-+
-+ /* Data aligning. */
-+ def_builtin ("__builtin_vis_faligndatav4hi", CODE_FOR_faligndatav4hi_vis,
-+ SPARC_BUILTIN_FALIGNDATAV4HI, v4hi_ftype_v4hi_v4hi);
-+ def_builtin ("__builtin_vis_faligndatav8qi", CODE_FOR_faligndatav8qi_vis,
-+ SPARC_BUILTIN_FALIGNDATAV8QI, v8qi_ftype_v8qi_v8qi);
-+ def_builtin ("__builtin_vis_faligndatav2si", CODE_FOR_faligndatav2si_vis,
-+ SPARC_BUILTIN_FALIGNDATAV2SI, v2si_ftype_v2si_v2si);
-+ def_builtin ("__builtin_vis_faligndatadi", CODE_FOR_faligndatav1di_vis,
-+ SPARC_BUILTIN_FALIGNDATADI, di_ftype_di_di);
-+
-+ def_builtin ("__builtin_vis_write_gsr", CODE_FOR_wrgsr_vis,
-+ SPARC_BUILTIN_WRGSR, void_ftype_di);
-+ def_builtin ("__builtin_vis_read_gsr", CODE_FOR_rdgsr_vis,
-+ SPARC_BUILTIN_RDGSR, di_ftype_void);
-+
-+ if (TARGET_ARCH64)
-+ {
-+ def_builtin ("__builtin_vis_alignaddr", CODE_FOR_alignaddrdi_vis,
-+ SPARC_BUILTIN_ALIGNADDR, ptr_ftype_ptr_di);
-+ def_builtin ("__builtin_vis_alignaddrl", CODE_FOR_alignaddrldi_vis,
-+ SPARC_BUILTIN_ALIGNADDRL, ptr_ftype_ptr_di);
-+ }
-+ else
-+ {
-+ def_builtin ("__builtin_vis_alignaddr", CODE_FOR_alignaddrsi_vis,
-+ SPARC_BUILTIN_ALIGNADDR, ptr_ftype_ptr_si);
-+ def_builtin ("__builtin_vis_alignaddrl", CODE_FOR_alignaddrlsi_vis,
-+ SPARC_BUILTIN_ALIGNADDRL, ptr_ftype_ptr_si);
-+ }
-+
-+ /* Pixel distance. */
-+ def_builtin_const ("__builtin_vis_pdist", CODE_FOR_pdist_vis,
-+ SPARC_BUILTIN_PDIST, di_ftype_v8qi_v8qi_di);
-+
-+ /* Edge handling. */
-+ if (TARGET_ARCH64)
-+ {
-+ def_builtin_const ("__builtin_vis_edge8", CODE_FOR_edge8di_vis,
-+ SPARC_BUILTIN_EDGE8, di_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge8l", CODE_FOR_edge8ldi_vis,
-+ SPARC_BUILTIN_EDGE8L, di_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge16", CODE_FOR_edge16di_vis,
-+ SPARC_BUILTIN_EDGE16, di_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge16l", CODE_FOR_edge16ldi_vis,
-+ SPARC_BUILTIN_EDGE16L, di_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge32", CODE_FOR_edge32di_vis,
-+ SPARC_BUILTIN_EDGE32, di_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge32l", CODE_FOR_edge32ldi_vis,
-+ SPARC_BUILTIN_EDGE32L, di_ftype_ptr_ptr);
-+ }
-+ else
-+ {
-+ def_builtin_const ("__builtin_vis_edge8", CODE_FOR_edge8si_vis,
-+ SPARC_BUILTIN_EDGE8, si_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge8l", CODE_FOR_edge8lsi_vis,
-+ SPARC_BUILTIN_EDGE8L, si_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge16", CODE_FOR_edge16si_vis,
-+ SPARC_BUILTIN_EDGE16, si_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge16l", CODE_FOR_edge16lsi_vis,
-+ SPARC_BUILTIN_EDGE16L, si_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge32", CODE_FOR_edge32si_vis,
-+ SPARC_BUILTIN_EDGE32, si_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge32l", CODE_FOR_edge32lsi_vis,
-+ SPARC_BUILTIN_EDGE32L, si_ftype_ptr_ptr);
-+ }
-+
-+ /* Pixel compare. */
-+ if (TARGET_ARCH64)
-+ {
-+ def_builtin_const ("__builtin_vis_fcmple16", CODE_FOR_fcmple16di_vis,
-+ SPARC_BUILTIN_FCMPLE16, di_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fcmple32", CODE_FOR_fcmple32di_vis,
-+ SPARC_BUILTIN_FCMPLE32, di_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fcmpne16", CODE_FOR_fcmpne16di_vis,
-+ SPARC_BUILTIN_FCMPNE16, di_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fcmpne32", CODE_FOR_fcmpne32di_vis,
-+ SPARC_BUILTIN_FCMPNE32, di_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fcmpgt16", CODE_FOR_fcmpgt16di_vis,
-+ SPARC_BUILTIN_FCMPGT16, di_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fcmpgt32", CODE_FOR_fcmpgt32di_vis,
-+ SPARC_BUILTIN_FCMPGT32, di_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fcmpeq16", CODE_FOR_fcmpeq16di_vis,
-+ SPARC_BUILTIN_FCMPEQ16, di_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fcmpeq32", CODE_FOR_fcmpeq32di_vis,
-+ SPARC_BUILTIN_FCMPEQ32, di_ftype_v2si_v2si);
-+ }
-+ else
-+ {
-+ def_builtin_const ("__builtin_vis_fcmple16", CODE_FOR_fcmple16si_vis,
-+ SPARC_BUILTIN_FCMPLE16, si_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fcmple32", CODE_FOR_fcmple32si_vis,
-+ SPARC_BUILTIN_FCMPLE32, si_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fcmpne16", CODE_FOR_fcmpne16si_vis,
-+ SPARC_BUILTIN_FCMPNE16, si_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fcmpne32", CODE_FOR_fcmpne32si_vis,
-+ SPARC_BUILTIN_FCMPNE32, si_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fcmpgt16", CODE_FOR_fcmpgt16si_vis,
-+ SPARC_BUILTIN_FCMPGT16, si_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fcmpgt32", CODE_FOR_fcmpgt32si_vis,
-+ SPARC_BUILTIN_FCMPGT32, si_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fcmpeq16", CODE_FOR_fcmpeq16si_vis,
-+ SPARC_BUILTIN_FCMPEQ16, si_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fcmpeq32", CODE_FOR_fcmpeq32si_vis,
-+ SPARC_BUILTIN_FCMPEQ32, si_ftype_v2si_v2si);
-+ }
-+
-+ /* Addition and subtraction. */
-+ def_builtin_const ("__builtin_vis_fpadd16", CODE_FOR_addv4hi3,
-+ SPARC_BUILTIN_FPADD16, v4hi_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fpadd16s", CODE_FOR_addv2hi3,
-+ SPARC_BUILTIN_FPADD16S, v2hi_ftype_v2hi_v2hi);
-+ def_builtin_const ("__builtin_vis_fpadd32", CODE_FOR_addv2si3,
-+ SPARC_BUILTIN_FPADD32, v2si_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fpadd32s", CODE_FOR_addv1si3,
-+ SPARC_BUILTIN_FPADD32S, v1si_ftype_v1si_v1si);
-+ def_builtin_const ("__builtin_vis_fpsub16", CODE_FOR_subv4hi3,
-+ SPARC_BUILTIN_FPSUB16, v4hi_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fpsub16s", CODE_FOR_subv2hi3,
-+ SPARC_BUILTIN_FPSUB16S, v2hi_ftype_v2hi_v2hi);
-+ def_builtin_const ("__builtin_vis_fpsub32", CODE_FOR_subv2si3,
-+ SPARC_BUILTIN_FPSUB32, v2si_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fpsub32s", CODE_FOR_subv1si3,
-+ SPARC_BUILTIN_FPSUB32S, v1si_ftype_v1si_v1si);
-+
-+ /* Three-dimensional array addressing. */
-+ if (TARGET_ARCH64)
-+ {
-+ def_builtin_const ("__builtin_vis_array8", CODE_FOR_array8di_vis,
-+ SPARC_BUILTIN_ARRAY8, di_ftype_di_di);
-+ def_builtin_const ("__builtin_vis_array16", CODE_FOR_array16di_vis,
-+ SPARC_BUILTIN_ARRAY16, di_ftype_di_di);
-+ def_builtin_const ("__builtin_vis_array32", CODE_FOR_array32di_vis,
-+ SPARC_BUILTIN_ARRAY32, di_ftype_di_di);
-+ }
-+ else
-+ {
-+ def_builtin_const ("__builtin_vis_array8", CODE_FOR_array8si_vis,
-+ SPARC_BUILTIN_ARRAY8, si_ftype_si_si);
-+ def_builtin_const ("__builtin_vis_array16", CODE_FOR_array16si_vis,
-+ SPARC_BUILTIN_ARRAY16, si_ftype_si_si);
-+ def_builtin_const ("__builtin_vis_array32", CODE_FOR_array32si_vis,
-+ SPARC_BUILTIN_ARRAY32, si_ftype_si_si);
-+ }
-+
-+ if (TARGET_VIS2)
-+ {
-+ /* Edge handling. */
-+ if (TARGET_ARCH64)
-+ {
-+ def_builtin_const ("__builtin_vis_edge8n", CODE_FOR_edge8ndi_vis,
-+ SPARC_BUILTIN_EDGE8N, di_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge8ln", CODE_FOR_edge8lndi_vis,
-+ SPARC_BUILTIN_EDGE8LN, di_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge16n", CODE_FOR_edge16ndi_vis,
-+ SPARC_BUILTIN_EDGE16N, di_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge16ln", CODE_FOR_edge16lndi_vis,
-+ SPARC_BUILTIN_EDGE16LN, di_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge32n", CODE_FOR_edge32ndi_vis,
-+ SPARC_BUILTIN_EDGE32N, di_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge32ln", CODE_FOR_edge32lndi_vis,
-+ SPARC_BUILTIN_EDGE32LN, di_ftype_ptr_ptr);
-+ }
-+ else
-+ {
-+ def_builtin_const ("__builtin_vis_edge8n", CODE_FOR_edge8nsi_vis,
-+ SPARC_BUILTIN_EDGE8N, si_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge8ln", CODE_FOR_edge8lnsi_vis,
-+ SPARC_BUILTIN_EDGE8LN, si_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge16n", CODE_FOR_edge16nsi_vis,
-+ SPARC_BUILTIN_EDGE16N, si_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge16ln", CODE_FOR_edge16lnsi_vis,
-+ SPARC_BUILTIN_EDGE16LN, si_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge32n", CODE_FOR_edge32nsi_vis,
-+ SPARC_BUILTIN_EDGE32N, si_ftype_ptr_ptr);
-+ def_builtin_const ("__builtin_vis_edge32ln", CODE_FOR_edge32lnsi_vis,
-+ SPARC_BUILTIN_EDGE32LN, si_ftype_ptr_ptr);
-+ }
-+
-+ /* Byte mask and shuffle. */
-+ if (TARGET_ARCH64)
-+ def_builtin ("__builtin_vis_bmask", CODE_FOR_bmaskdi_vis,
-+ SPARC_BUILTIN_BMASK, di_ftype_di_di);
-+ else
-+ def_builtin ("__builtin_vis_bmask", CODE_FOR_bmasksi_vis,
-+ SPARC_BUILTIN_BMASK, si_ftype_si_si);
-+ def_builtin ("__builtin_vis_bshufflev4hi", CODE_FOR_bshufflev4hi_vis,
-+ SPARC_BUILTIN_BSHUFFLEV4HI, v4hi_ftype_v4hi_v4hi);
-+ def_builtin ("__builtin_vis_bshufflev8qi", CODE_FOR_bshufflev8qi_vis,
-+ SPARC_BUILTIN_BSHUFFLEV8QI, v8qi_ftype_v8qi_v8qi);
-+ def_builtin ("__builtin_vis_bshufflev2si", CODE_FOR_bshufflev2si_vis,
-+ SPARC_BUILTIN_BSHUFFLEV2SI, v2si_ftype_v2si_v2si);
-+ def_builtin ("__builtin_vis_bshuffledi", CODE_FOR_bshufflev1di_vis,
-+ SPARC_BUILTIN_BSHUFFLEDI, di_ftype_di_di);
-+ }
-+
-+ if (TARGET_VIS3)
-+ {
-+ if (TARGET_ARCH64)
-+ {
-+ def_builtin ("__builtin_vis_cmask8", CODE_FOR_cmask8di_vis,
-+ SPARC_BUILTIN_CMASK8, void_ftype_di);
-+ def_builtin ("__builtin_vis_cmask16", CODE_FOR_cmask16di_vis,
-+ SPARC_BUILTIN_CMASK16, void_ftype_di);
-+ def_builtin ("__builtin_vis_cmask32", CODE_FOR_cmask32di_vis,
-+ SPARC_BUILTIN_CMASK32, void_ftype_di);
-+ }
-+ else
-+ {
-+ def_builtin ("__builtin_vis_cmask8", CODE_FOR_cmask8si_vis,
-+ SPARC_BUILTIN_CMASK8, void_ftype_si);
-+ def_builtin ("__builtin_vis_cmask16", CODE_FOR_cmask16si_vis,
-+ SPARC_BUILTIN_CMASK16, void_ftype_si);
-+ def_builtin ("__builtin_vis_cmask32", CODE_FOR_cmask32si_vis,
-+ SPARC_BUILTIN_CMASK32, void_ftype_si);
-+ }
-+
-+ def_builtin_const ("__builtin_vis_fchksm16", CODE_FOR_fchksm16_vis,
-+ SPARC_BUILTIN_FCHKSM16, v4hi_ftype_v4hi_v4hi);
-+
-+ def_builtin_const ("__builtin_vis_fsll16", CODE_FOR_vashlv4hi3,
-+ SPARC_BUILTIN_FSLL16, v4hi_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fslas16", CODE_FOR_vssashlv4hi3,
-+ SPARC_BUILTIN_FSLAS16, v4hi_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fsrl16", CODE_FOR_vlshrv4hi3,
-+ SPARC_BUILTIN_FSRL16, v4hi_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fsra16", CODE_FOR_vashrv4hi3,
-+ SPARC_BUILTIN_FSRA16, v4hi_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fsll32", CODE_FOR_vashlv2si3,
-+ SPARC_BUILTIN_FSLL32, v2si_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fslas32", CODE_FOR_vssashlv2si3,
-+ SPARC_BUILTIN_FSLAS32, v2si_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fsrl32", CODE_FOR_vlshrv2si3,
-+ SPARC_BUILTIN_FSRL32, v2si_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fsra32", CODE_FOR_vashrv2si3,
-+ SPARC_BUILTIN_FSRA32, v2si_ftype_v2si_v2si);
-+
-+ if (TARGET_ARCH64)
-+ def_builtin_const ("__builtin_vis_pdistn", CODE_FOR_pdistndi_vis,
-+ SPARC_BUILTIN_PDISTN, di_ftype_v8qi_v8qi);
-+ else
-+ def_builtin_const ("__builtin_vis_pdistn", CODE_FOR_pdistnsi_vis,
-+ SPARC_BUILTIN_PDISTN, si_ftype_v8qi_v8qi);
-+
-+ def_builtin_const ("__builtin_vis_fmean16", CODE_FOR_fmean16_vis,
-+ SPARC_BUILTIN_FMEAN16, v4hi_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fpadd64", CODE_FOR_fpadd64_vis,
-+ SPARC_BUILTIN_FPADD64, di_ftype_di_di);
-+ def_builtin_const ("__builtin_vis_fpsub64", CODE_FOR_fpsub64_vis,
-+ SPARC_BUILTIN_FPSUB64, di_ftype_di_di);
-+
-+ def_builtin_const ("__builtin_vis_fpadds16", CODE_FOR_ssaddv4hi3,
-+ SPARC_BUILTIN_FPADDS16, v4hi_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fpadds16s", CODE_FOR_ssaddv2hi3,
-+ SPARC_BUILTIN_FPADDS16S, v2hi_ftype_v2hi_v2hi);
-+ def_builtin_const ("__builtin_vis_fpsubs16", CODE_FOR_sssubv4hi3,
-+ SPARC_BUILTIN_FPSUBS16, v4hi_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fpsubs16s", CODE_FOR_sssubv2hi3,
-+ SPARC_BUILTIN_FPSUBS16S, v2hi_ftype_v2hi_v2hi);
-+ def_builtin_const ("__builtin_vis_fpadds32", CODE_FOR_ssaddv2si3,
-+ SPARC_BUILTIN_FPADDS32, v2si_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fpadds32s", CODE_FOR_ssaddv1si3,
-+ SPARC_BUILTIN_FPADDS32S, v1si_ftype_v1si_v1si);
-+ def_builtin_const ("__builtin_vis_fpsubs32", CODE_FOR_sssubv2si3,
-+ SPARC_BUILTIN_FPSUBS32, v2si_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fpsubs32s", CODE_FOR_sssubv1si3,
-+ SPARC_BUILTIN_FPSUBS32S, v1si_ftype_v1si_v1si);
-+
-+ if (TARGET_ARCH64)
-+ {
-+ def_builtin_const ("__builtin_vis_fucmple8", CODE_FOR_fucmple8di_vis,
-+ SPARC_BUILTIN_FUCMPLE8, di_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fucmpne8", CODE_FOR_fucmpne8di_vis,
-+ SPARC_BUILTIN_FUCMPNE8, di_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fucmpgt8", CODE_FOR_fucmpgt8di_vis,
-+ SPARC_BUILTIN_FUCMPGT8, di_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fucmpeq8", CODE_FOR_fucmpeq8di_vis,
-+ SPARC_BUILTIN_FUCMPEQ8, di_ftype_v8qi_v8qi);
-+ }
-+ else
-+ {
-+ def_builtin_const ("__builtin_vis_fucmple8", CODE_FOR_fucmple8si_vis,
-+ SPARC_BUILTIN_FUCMPLE8, si_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fucmpne8", CODE_FOR_fucmpne8si_vis,
-+ SPARC_BUILTIN_FUCMPNE8, si_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fucmpgt8", CODE_FOR_fucmpgt8si_vis,
-+ SPARC_BUILTIN_FUCMPGT8, si_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fucmpeq8", CODE_FOR_fucmpeq8si_vis,
-+ SPARC_BUILTIN_FUCMPEQ8, si_ftype_v8qi_v8qi);
-+ }
-+
-+ def_builtin_const ("__builtin_vis_fhadds", CODE_FOR_fhaddsf_vis,
-+ SPARC_BUILTIN_FHADDS, sf_ftype_sf_sf);
-+ def_builtin_const ("__builtin_vis_fhaddd", CODE_FOR_fhadddf_vis,
-+ SPARC_BUILTIN_FHADDD, df_ftype_df_df);
-+ def_builtin_const ("__builtin_vis_fhsubs", CODE_FOR_fhsubsf_vis,
-+ SPARC_BUILTIN_FHSUBS, sf_ftype_sf_sf);
-+ def_builtin_const ("__builtin_vis_fhsubd", CODE_FOR_fhsubdf_vis,
-+ SPARC_BUILTIN_FHSUBD, df_ftype_df_df);
-+ def_builtin_const ("__builtin_vis_fnhadds", CODE_FOR_fnhaddsf_vis,
-+ SPARC_BUILTIN_FNHADDS, sf_ftype_sf_sf);
-+ def_builtin_const ("__builtin_vis_fnhaddd", CODE_FOR_fnhadddf_vis,
-+ SPARC_BUILTIN_FNHADDD, df_ftype_df_df);
-+
-+ def_builtin_const ("__builtin_vis_umulxhi", CODE_FOR_umulxhi_vis,
-+ SPARC_BUILTIN_UMULXHI, di_ftype_di_di);
-+ def_builtin_const ("__builtin_vis_xmulx", CODE_FOR_xmulx_vis,
-+ SPARC_BUILTIN_XMULX, di_ftype_di_di);
-+ def_builtin_const ("__builtin_vis_xmulxhi", CODE_FOR_xmulxhi_vis,
-+ SPARC_BUILTIN_XMULXHI, di_ftype_di_di);
-+ }
-+
-+ if (TARGET_VIS4)
-+ {
-+ def_builtin_const ("__builtin_vis_fpadd8", CODE_FOR_addv8qi3,
-+ SPARC_BUILTIN_FPADD8, v8qi_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fpadds8", CODE_FOR_ssaddv8qi3,
-+ SPARC_BUILTIN_FPADDS8, v8qi_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fpaddus8", CODE_FOR_usaddv8qi3,
-+ SPARC_BUILTIN_FPADDUS8, v8qi_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fpaddus16", CODE_FOR_usaddv4hi3,
-+ SPARC_BUILTIN_FPADDUS16, v4hi_ftype_v4hi_v4hi);
-+
-+
-+ if (TARGET_ARCH64)
-+ {
-+ def_builtin_const ("__builtin_vis_fpcmple8", CODE_FOR_fpcmple8di_vis,
-+ SPARC_BUILTIN_FPCMPLE8, di_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fpcmpgt8", CODE_FOR_fpcmpgt8di_vis,
-+ SPARC_BUILTIN_FPCMPGT8, di_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fpcmpule16", CODE_FOR_fpcmpule16di_vis,
-+ SPARC_BUILTIN_FPCMPULE16, di_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fpcmpugt16", CODE_FOR_fpcmpugt16di_vis,
-+ SPARC_BUILTIN_FPCMPUGT16, di_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fpcmpule32", CODE_FOR_fpcmpule32di_vis,
-+ SPARC_BUILTIN_FPCMPULE32, di_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fpcmpugt32", CODE_FOR_fpcmpugt32di_vis,
-+ SPARC_BUILTIN_FPCMPUGT32, di_ftype_v2si_v2si);
-+ }
-+ else
-+ {
-+ def_builtin_const ("__builtin_vis_fpcmple8", CODE_FOR_fpcmple8si_vis,
-+ SPARC_BUILTIN_FPCMPLE8, si_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fpcmpgt8", CODE_FOR_fpcmpgt8si_vis,
-+ SPARC_BUILTIN_FPCMPGT8, si_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fpcmpule16", CODE_FOR_fpcmpule16si_vis,
-+ SPARC_BUILTIN_FPCMPULE16, si_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fpcmpugt16", CODE_FOR_fpcmpugt16si_vis,
-+ SPARC_BUILTIN_FPCMPUGT16, si_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fpcmpule32", CODE_FOR_fpcmpule32si_vis,
-+ SPARC_BUILTIN_FPCMPULE32, di_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fpcmpugt32", CODE_FOR_fpcmpugt32si_vis,
-+ SPARC_BUILTIN_FPCMPUGT32, di_ftype_v2si_v2si);
-+ }
-+
-+ def_builtin_const ("__builtin_vis_fpmax8", CODE_FOR_maxv8qi3,
-+ SPARC_BUILTIN_FPMAX8, v8qi_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fpmax16", CODE_FOR_maxv4hi3,
-+ SPARC_BUILTIN_FPMAX16, v4hi_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fpmax32", CODE_FOR_maxv2si3,
-+ SPARC_BUILTIN_FPMAX32, v2si_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fpmaxu8", CODE_FOR_maxuv8qi3,
-+ SPARC_BUILTIN_FPMAXU8, v8qi_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fpmaxu16", CODE_FOR_maxuv4hi3,
-+ SPARC_BUILTIN_FPMAXU16, v4hi_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fpmaxu32", CODE_FOR_maxuv2si3,
-+ SPARC_BUILTIN_FPMAXU32, v2si_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fpmin8", CODE_FOR_minv8qi3,
-+ SPARC_BUILTIN_FPMIN8, v8qi_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fpmin16", CODE_FOR_minv4hi3,
-+ SPARC_BUILTIN_FPMIN16, v4hi_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fpmin32", CODE_FOR_minv2si3,
-+ SPARC_BUILTIN_FPMIN32, v2si_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fpminu8", CODE_FOR_minuv8qi3,
-+ SPARC_BUILTIN_FPMINU8, v8qi_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fpminu16", CODE_FOR_minuv4hi3,
-+ SPARC_BUILTIN_FPMINU16, v4hi_ftype_v4hi_v4hi);
-+ def_builtin_const ("__builtin_vis_fpminu32", CODE_FOR_minuv2si3,
-+ SPARC_BUILTIN_FPMINU32, v2si_ftype_v2si_v2si);
-+ def_builtin_const ("__builtin_vis_fpsub8", CODE_FOR_subv8qi3,
-+ SPARC_BUILTIN_FPSUB8, v8qi_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fpsubs8", CODE_FOR_sssubv8qi3,
-+ SPARC_BUILTIN_FPSUBS8, v8qi_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fpsubus8", CODE_FOR_ussubv8qi3,
-+ SPARC_BUILTIN_FPSUBUS8, v8qi_ftype_v8qi_v8qi);
-+ def_builtin_const ("__builtin_vis_fpsubus16", CODE_FOR_ussubv4hi3,
-+ SPARC_BUILTIN_FPSUBUS16, v4hi_ftype_v4hi_v4hi);
-+ }
-+
-+ if (TARGET_VIS4B)
-+ {
-+ def_builtin_const ("__builtin_vis_dictunpack8", CODE_FOR_dictunpack8,
-+ SPARC_BUILTIN_DICTUNPACK8, v8qi_ftype_df_si);
-+ def_builtin_const ("__builtin_vis_dictunpack16", CODE_FOR_dictunpack16,
-+ SPARC_BUILTIN_DICTUNPACK16, v4hi_ftype_df_si);
-+ def_builtin_const ("__builtin_vis_dictunpack32", CODE_FOR_dictunpack32,
-+ SPARC_BUILTIN_DICTUNPACK32, v2si_ftype_df_si);
-+
-+ if (TARGET_ARCH64)
-+ {
-+ tree di_ftype_v8qi_v8qi_si = build_function_type_list (intDI_type_node,
-+ v8qi, v8qi,
-+ intSI_type_node, 0);
-+ tree di_ftype_v4hi_v4hi_si = build_function_type_list (intDI_type_node,
-+ v4hi, v4hi,
-+ intSI_type_node, 0);
-+ tree di_ftype_v2si_v2si_si = build_function_type_list (intDI_type_node,
-+ v2si, v2si,
-+ intSI_type_node, 0);
-+
-+ def_builtin_const ("__builtin_vis_fpcmple8shl", CODE_FOR_fpcmple8dishl,
-+ SPARC_BUILTIN_FPCMPLE8SHL, di_ftype_v8qi_v8qi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpgt8shl", CODE_FOR_fpcmpgt8dishl,
-+ SPARC_BUILTIN_FPCMPGT8SHL, di_ftype_v8qi_v8qi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpeq8shl", CODE_FOR_fpcmpeq8dishl,
-+ SPARC_BUILTIN_FPCMPEQ8SHL, di_ftype_v8qi_v8qi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpne8shl", CODE_FOR_fpcmpne8dishl,
-+ SPARC_BUILTIN_FPCMPNE8SHL, di_ftype_v8qi_v8qi_si);
-+
-+ def_builtin_const ("__builtin_vis_fpcmple16shl", CODE_FOR_fpcmple16dishl,
-+ SPARC_BUILTIN_FPCMPLE16SHL, di_ftype_v4hi_v4hi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpgt16shl", CODE_FOR_fpcmpgt16dishl,
-+ SPARC_BUILTIN_FPCMPGT16SHL, di_ftype_v4hi_v4hi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpeq16shl", CODE_FOR_fpcmpeq16dishl,
-+ SPARC_BUILTIN_FPCMPEQ16SHL, di_ftype_v4hi_v4hi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpne16shl", CODE_FOR_fpcmpne16dishl,
-+ SPARC_BUILTIN_FPCMPNE16SHL, di_ftype_v4hi_v4hi_si);
-+
-+ def_builtin_const ("__builtin_vis_fpcmple32shl", CODE_FOR_fpcmple32dishl,
-+ SPARC_BUILTIN_FPCMPLE32SHL, di_ftype_v2si_v2si_si);
-+ def_builtin_const ("__builtin_vis_fpcmpgt32shl", CODE_FOR_fpcmpgt32dishl,
-+ SPARC_BUILTIN_FPCMPGT32SHL, di_ftype_v2si_v2si_si);
-+ def_builtin_const ("__builtin_vis_fpcmpeq32shl", CODE_FOR_fpcmpeq32dishl,
-+ SPARC_BUILTIN_FPCMPEQ32SHL, di_ftype_v2si_v2si_si);
-+ def_builtin_const ("__builtin_vis_fpcmpne32shl", CODE_FOR_fpcmpne32dishl,
-+ SPARC_BUILTIN_FPCMPNE32SHL, di_ftype_v2si_v2si_si);
-+
-+
-+ def_builtin_const ("__builtin_vis_fpcmpule8shl", CODE_FOR_fpcmpule8dishl,
-+ SPARC_BUILTIN_FPCMPULE8SHL, di_ftype_v8qi_v8qi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpugt8shl", CODE_FOR_fpcmpugt8dishl,
-+ SPARC_BUILTIN_FPCMPUGT8SHL, di_ftype_v8qi_v8qi_si);
-+
-+ def_builtin_const ("__builtin_vis_fpcmpule16shl", CODE_FOR_fpcmpule16dishl,
-+ SPARC_BUILTIN_FPCMPULE16SHL, di_ftype_v4hi_v4hi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpugt16shl", CODE_FOR_fpcmpugt16dishl,
-+ SPARC_BUILTIN_FPCMPUGT16SHL, di_ftype_v4hi_v4hi_si);
-+
-+ def_builtin_const ("__builtin_vis_fpcmpule32shl", CODE_FOR_fpcmpule32dishl,
-+ SPARC_BUILTIN_FPCMPULE32SHL, di_ftype_v2si_v2si_si);
-+ def_builtin_const ("__builtin_vis_fpcmpugt32shl", CODE_FOR_fpcmpugt32dishl,
-+ SPARC_BUILTIN_FPCMPUGT32SHL, di_ftype_v2si_v2si_si);
-+
-+ def_builtin_const ("__builtin_vis_fpcmpde8shl", CODE_FOR_fpcmpde8dishl,
-+ SPARC_BUILTIN_FPCMPDE8SHL, di_ftype_v8qi_v8qi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpde16shl", CODE_FOR_fpcmpde16dishl,
-+ SPARC_BUILTIN_FPCMPDE16SHL, di_ftype_v4hi_v4hi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpde32shl", CODE_FOR_fpcmpde32dishl,
-+ SPARC_BUILTIN_FPCMPDE32SHL, di_ftype_v2si_v2si_si);
-+
-+ def_builtin_const ("__builtin_vis_fpcmpur8shl", CODE_FOR_fpcmpur8dishl,
-+ SPARC_BUILTIN_FPCMPUR8SHL, di_ftype_v8qi_v8qi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpur16shl", CODE_FOR_fpcmpur16dishl,
-+ SPARC_BUILTIN_FPCMPUR16SHL, di_ftype_v4hi_v4hi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpur32shl", CODE_FOR_fpcmpur32dishl,
-+ SPARC_BUILTIN_FPCMPUR32SHL, di_ftype_v2si_v2si_si);
-+
-+ }
-+ else
-+ {
-+ tree si_ftype_v8qi_v8qi_si = build_function_type_list (intSI_type_node,
-+ v8qi, v8qi,
-+ intSI_type_node, 0);
-+ tree si_ftype_v4hi_v4hi_si = build_function_type_list (intSI_type_node,
-+ v4hi, v4hi,
-+ intSI_type_node, 0);
-+ tree si_ftype_v2si_v2si_si = build_function_type_list (intSI_type_node,
-+ v2si, v2si,
-+ intSI_type_node, 0);
-+
-+ def_builtin_const ("__builtin_vis_fpcmple8shl", CODE_FOR_fpcmple8sishl,
-+ SPARC_BUILTIN_FPCMPLE8SHL, si_ftype_v8qi_v8qi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpgt8shl", CODE_FOR_fpcmpgt8sishl,
-+ SPARC_BUILTIN_FPCMPGT8SHL, si_ftype_v8qi_v8qi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpeq8shl", CODE_FOR_fpcmpeq8sishl,
-+ SPARC_BUILTIN_FPCMPEQ8SHL, si_ftype_v8qi_v8qi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpne8shl", CODE_FOR_fpcmpne8sishl,
-+ SPARC_BUILTIN_FPCMPNE8SHL, si_ftype_v8qi_v8qi_si);
-+
-+ def_builtin_const ("__builtin_vis_fpcmple16shl", CODE_FOR_fpcmple16sishl,
-+ SPARC_BUILTIN_FPCMPLE16SHL, si_ftype_v4hi_v4hi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpgt16shl", CODE_FOR_fpcmpgt16sishl,
-+ SPARC_BUILTIN_FPCMPGT16SHL, si_ftype_v4hi_v4hi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpeq16shl", CODE_FOR_fpcmpeq16sishl,
-+ SPARC_BUILTIN_FPCMPEQ16SHL, si_ftype_v4hi_v4hi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpne16shl", CODE_FOR_fpcmpne16sishl,
-+ SPARC_BUILTIN_FPCMPNE16SHL, si_ftype_v4hi_v4hi_si);
-+
-+ def_builtin_const ("__builtin_vis_fpcmple32shl", CODE_FOR_fpcmple32sishl,
-+ SPARC_BUILTIN_FPCMPLE32SHL, si_ftype_v2si_v2si_si);
-+ def_builtin_const ("__builtin_vis_fpcmpgt32shl", CODE_FOR_fpcmpgt32sishl,
-+ SPARC_BUILTIN_FPCMPGT32SHL, si_ftype_v2si_v2si_si);
-+ def_builtin_const ("__builtin_vis_fpcmpeq32shl", CODE_FOR_fpcmpeq32sishl,
-+ SPARC_BUILTIN_FPCMPEQ32SHL, si_ftype_v2si_v2si_si);
-+ def_builtin_const ("__builtin_vis_fpcmpne32shl", CODE_FOR_fpcmpne32sishl,
-+ SPARC_BUILTIN_FPCMPNE32SHL, si_ftype_v2si_v2si_si);
-+
-+
-+ def_builtin_const ("__builtin_vis_fpcmpule8shl", CODE_FOR_fpcmpule8sishl,
-+ SPARC_BUILTIN_FPCMPULE8SHL, si_ftype_v8qi_v8qi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpugt8shl", CODE_FOR_fpcmpugt8sishl,
-+ SPARC_BUILTIN_FPCMPUGT8SHL, si_ftype_v8qi_v8qi_si);
-+
-+ def_builtin_const ("__builtin_vis_fpcmpule16shl", CODE_FOR_fpcmpule16sishl,
-+ SPARC_BUILTIN_FPCMPULE16SHL, si_ftype_v4hi_v4hi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpugt16shl", CODE_FOR_fpcmpugt16sishl,
-+ SPARC_BUILTIN_FPCMPUGT16SHL, si_ftype_v4hi_v4hi_si);
-+
-+ def_builtin_const ("__builtin_vis_fpcmpule32shl", CODE_FOR_fpcmpule32sishl,
-+ SPARC_BUILTIN_FPCMPULE32SHL, si_ftype_v2si_v2si_si);
-+ def_builtin_const ("__builtin_vis_fpcmpugt32shl", CODE_FOR_fpcmpugt32sishl,
-+ SPARC_BUILTIN_FPCMPUGT32SHL, si_ftype_v2si_v2si_si);
-+
-+ def_builtin_const ("__builtin_vis_fpcmpde8shl", CODE_FOR_fpcmpde8sishl,
-+ SPARC_BUILTIN_FPCMPDE8SHL, si_ftype_v8qi_v8qi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpde16shl", CODE_FOR_fpcmpde16sishl,
-+ SPARC_BUILTIN_FPCMPDE16SHL, si_ftype_v4hi_v4hi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpde32shl", CODE_FOR_fpcmpde32sishl,
-+ SPARC_BUILTIN_FPCMPDE32SHL, si_ftype_v2si_v2si_si);
-+
-+ def_builtin_const ("__builtin_vis_fpcmpur8shl", CODE_FOR_fpcmpur8sishl,
-+ SPARC_BUILTIN_FPCMPUR8SHL, si_ftype_v8qi_v8qi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpur16shl", CODE_FOR_fpcmpur16sishl,
-+ SPARC_BUILTIN_FPCMPUR16SHL, si_ftype_v4hi_v4hi_si);
-+ def_builtin_const ("__builtin_vis_fpcmpur32shl", CODE_FOR_fpcmpur32sishl,
-+ SPARC_BUILTIN_FPCMPUR32SHL, si_ftype_v2si_v2si_si);
-+ }
-+ }
-+}
-+
-+/* Implement TARGET_BUILTIN_DECL hook. */
-+
-+static tree
-+sparc_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
-+{
-+ if (code >= SPARC_BUILTIN_MAX)
-+ return error_mark_node;
-+
-+ return sparc_builtins[code];
-+}
-+
-+/* Implemented TARGET_EXPAND_BUILTIN hook. */
-+
-+static rtx
-+sparc_expand_builtin (tree exp, rtx target,
-+ rtx subtarget ATTRIBUTE_UNUSED,
-+ machine_mode tmode ATTRIBUTE_UNUSED,
-+ int ignore ATTRIBUTE_UNUSED)
-+{
-+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
-+ enum sparc_builtins code
-+ = (enum sparc_builtins) DECL_MD_FUNCTION_CODE (fndecl);
-+ enum insn_code icode = sparc_builtins_icode[code];
-+ bool nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
-+ call_expr_arg_iterator iter;
-+ int arg_count = 0;
-+ rtx pat, op[4];
-+ tree arg;
-+
-+ if (nonvoid)
-+ {
-+ machine_mode tmode = insn_data[icode].operand[0].mode;
-+ if (!target
-+ || GET_MODE (target) != tmode
-+ || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
-+ op[0] = gen_reg_rtx (tmode);
-+ else
-+ op[0] = target;
-+ }
-+ else
-+ op[0] = NULL_RTX;
-+
-+ FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
-+ {
-+ const struct insn_operand_data *insn_op;
-+ int idx;
-+
-+ if (arg == error_mark_node)
-+ return NULL_RTX;
-+
-+ arg_count++;
-+ idx = arg_count - !nonvoid;
-+ insn_op = &insn_data[icode].operand[idx];
-+ op[arg_count] = expand_normal (arg);
-+
-+ /* Some of the builtins require constant arguments. We check
-+ for this here. */
-+ if ((code >= SPARC_BUILTIN_FIRST_FPCMPSHL
-+ && code <= SPARC_BUILTIN_LAST_FPCMPSHL
-+ && arg_count == 3)
-+ || (code >= SPARC_BUILTIN_FIRST_DICTUNPACK
-+ && code <= SPARC_BUILTIN_LAST_DICTUNPACK
-+ && arg_count == 2))
-+ {
-+ if (!check_constant_argument (icode, idx, op[arg_count]))
-+ return const0_rtx;
-+ }
-+
-+ if (code == SPARC_BUILTIN_LDFSR || code == SPARC_BUILTIN_STFSR)
-+ {
-+ if (!address_operand (op[arg_count], SImode))
-+ {
-+ op[arg_count] = convert_memory_address (Pmode, op[arg_count]);
-+ op[arg_count] = copy_addr_to_reg (op[arg_count]);
-+ }
-+ op[arg_count] = gen_rtx_MEM (SImode, op[arg_count]);
-+ }
-+
-+ else if (insn_op->mode == V1DImode
-+ && GET_MODE (op[arg_count]) == DImode)
-+ op[arg_count] = gen_lowpart (V1DImode, op[arg_count]);
-+
-+ else if (insn_op->mode == V1SImode
-+ && GET_MODE (op[arg_count]) == SImode)
-+ op[arg_count] = gen_lowpart (V1SImode, op[arg_count]);
-+
-+ if (! (*insn_data[icode].operand[idx].predicate) (op[arg_count],
-+ insn_op->mode))
-+ op[arg_count] = copy_to_mode_reg (insn_op->mode, op[arg_count]);
-+ }
-+
-+ switch (arg_count)
-+ {
-+ case 0:
-+ pat = GEN_FCN (icode) (op[0]);
-+ break;
-+ case 1:
-+ if (nonvoid)
-+ pat = GEN_FCN (icode) (op[0], op[1]);
-+ else
-+ pat = GEN_FCN (icode) (op[1]);
-+ break;
-+ case 2:
-+ pat = GEN_FCN (icode) (op[0], op[1], op[2]);
-+ break;
-+ case 3:
-+ pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
-+ break;
-+ default:
-+ gcc_unreachable ();
-+ }
-+
-+ if (!pat)
-+ return NULL_RTX;
-+
-+ emit_insn (pat);
-+
-+ return (nonvoid ? op[0] : const0_rtx);
-+}
-+
-+/* Return the upper 16 bits of the 8x16 multiplication. */
-+
-+static int
-+sparc_vis_mul8x16 (int e8, int e16)
-+{
-+ return (e8 * e16 + 128) / 256;
-+}
-+
-+/* Multiply the VECTOR_CSTs CST0 and CST1 as specified by FNCODE and put
-+ the result into the array N_ELTS, whose elements are of INNER_TYPE. */
-+
-+static void
-+sparc_handle_vis_mul8x16 (vec<tree> *n_elts, enum sparc_builtins fncode,
-+ tree inner_type, tree cst0, tree cst1)
-+{
-+ unsigned i, num = VECTOR_CST_NELTS (cst0);
-+ int scale;
-+
-+ switch (fncode)
-+ {
-+ case SPARC_BUILTIN_FMUL8X16:
-+ for (i = 0; i < num; ++i)
-+ {
-+ int val
-+ = sparc_vis_mul8x16 (TREE_INT_CST_LOW (VECTOR_CST_ELT (cst0, i)),
-+ TREE_INT_CST_LOW (VECTOR_CST_ELT (cst1, i)));
-+ n_elts->quick_push (build_int_cst (inner_type, val));
-+ }
-+ break;
-+
-+ case SPARC_BUILTIN_FMUL8X16AU:
-+ scale = TREE_INT_CST_LOW (VECTOR_CST_ELT (cst1, 0));
-+
-+ for (i = 0; i < num; ++i)
-+ {
-+ int val
-+ = sparc_vis_mul8x16 (TREE_INT_CST_LOW (VECTOR_CST_ELT (cst0, i)),
-+ scale);
-+ n_elts->quick_push (build_int_cst (inner_type, val));
-+ }
-+ break;
-+
-+ case SPARC_BUILTIN_FMUL8X16AL:
-+ scale = TREE_INT_CST_LOW (VECTOR_CST_ELT (cst1, 1));
-+
-+ for (i = 0; i < num; ++i)
-+ {
-+ int val
-+ = sparc_vis_mul8x16 (TREE_INT_CST_LOW (VECTOR_CST_ELT (cst0, i)),
-+ scale);
-+ n_elts->quick_push (build_int_cst (inner_type, val));
-+ }
-+ break;
-+
-+ default:
-+ gcc_unreachable ();
-+ }
-+}
-+
-+/* Implement TARGET_FOLD_BUILTIN hook.
-+
-+ Fold builtin functions for SPARC intrinsics. If IGNORE is true the
-+ result of the function call is ignored. NULL_TREE is returned if the
-+ function could not be folded. */
-+
-+static tree
-+sparc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
-+ tree *args, bool ignore)
-+{
-+ enum sparc_builtins code
-+ = (enum sparc_builtins) DECL_MD_FUNCTION_CODE (fndecl);
-+ tree rtype = TREE_TYPE (TREE_TYPE (fndecl));
-+ tree arg0, arg1, arg2;
-+
-+ if (ignore)
-+ switch (code)
-+ {
-+ case SPARC_BUILTIN_LDFSR:
-+ case SPARC_BUILTIN_STFSR:
-+ case SPARC_BUILTIN_ALIGNADDR:
-+ case SPARC_BUILTIN_WRGSR:
-+ case SPARC_BUILTIN_BMASK:
-+ case SPARC_BUILTIN_CMASK8:
-+ case SPARC_BUILTIN_CMASK16:
-+ case SPARC_BUILTIN_CMASK32:
-+ break;
-+
-+ default:
-+ return build_zero_cst (rtype);
-+ }
-+
-+ switch (code)
-+ {
-+ case SPARC_BUILTIN_FEXPAND:
-+ arg0 = args[0];
-+ STRIP_NOPS (arg0);
-+
-+ if (TREE_CODE (arg0) == VECTOR_CST)
-+ {
-+ tree inner_type = TREE_TYPE (rtype);
-+ unsigned i;
-+
-+ tree_vector_builder n_elts (rtype, VECTOR_CST_NELTS (arg0), 1);
-+ for (i = 0; i < VECTOR_CST_NELTS (arg0); ++i)
-+ {
-+ unsigned HOST_WIDE_INT val
-+ = TREE_INT_CST_LOW (VECTOR_CST_ELT (arg0, i));
-+ n_elts.quick_push (build_int_cst (inner_type, val << 4));
-+ }
-+ return n_elts.build ();
-+ }
-+ break;
-+
-+ case SPARC_BUILTIN_FMUL8X16:
-+ case SPARC_BUILTIN_FMUL8X16AU:
-+ case SPARC_BUILTIN_FMUL8X16AL:
-+ arg0 = args[0];
-+ arg1 = args[1];
-+ STRIP_NOPS (arg0);
-+ STRIP_NOPS (arg1);
-+
-+ if (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST)
-+ {
-+ tree inner_type = TREE_TYPE (rtype);
-+ tree_vector_builder n_elts (rtype, VECTOR_CST_NELTS (arg0), 1);
-+ sparc_handle_vis_mul8x16 (&n_elts, code, inner_type, arg0, arg1);
-+ return n_elts.build ();
-+ }
-+ break;
-+
-+ case SPARC_BUILTIN_FPMERGE:
-+ arg0 = args[0];
-+ arg1 = args[1];
-+ STRIP_NOPS (arg0);
-+ STRIP_NOPS (arg1);
-+
-+ if (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST)
-+ {
-+ tree_vector_builder n_elts (rtype, 2 * VECTOR_CST_NELTS (arg0), 1);
-+ unsigned i;
-+ for (i = 0; i < VECTOR_CST_NELTS (arg0); ++i)
-+ {
-+ n_elts.quick_push (VECTOR_CST_ELT (arg0, i));
-+ n_elts.quick_push (VECTOR_CST_ELT (arg1, i));
-+ }
-+
-+ return n_elts.build ();
-+ }
-+ break;
-+
-+ case SPARC_BUILTIN_PDIST:
-+ case SPARC_BUILTIN_PDISTN:
-+ arg0 = args[0];
-+ arg1 = args[1];
-+ STRIP_NOPS (arg0);
-+ STRIP_NOPS (arg1);
-+ if (code == SPARC_BUILTIN_PDIST)
-+ {
-+ arg2 = args[2];
-+ STRIP_NOPS (arg2);
-+ }
-+ else
-+ arg2 = integer_zero_node;
-+
-+ if (TREE_CODE (arg0) == VECTOR_CST
-+ && TREE_CODE (arg1) == VECTOR_CST
-+ && TREE_CODE (arg2) == INTEGER_CST)
-+ {
-+ bool overflow = false;
-+ widest_int result = wi::to_widest (arg2);
-+ widest_int tmp;
-+ unsigned i;
-+
-+ for (i = 0; i < VECTOR_CST_NELTS (arg0); ++i)
-+ {
-+ tree e0 = VECTOR_CST_ELT (arg0, i);
-+ tree e1 = VECTOR_CST_ELT (arg1, i);
-+
-+ wi::overflow_type neg1_ovf, neg2_ovf, add1_ovf, add2_ovf;
-+
-+ tmp = wi::neg (wi::to_widest (e1), &neg1_ovf);
-+ tmp = wi::add (wi::to_widest (e0), tmp, SIGNED, &add1_ovf);
-+ if (wi::neg_p (tmp))
-+ tmp = wi::neg (tmp, &neg2_ovf);
-+ else
-+ neg2_ovf = wi::OVF_NONE;
-+ result = wi::add (result, tmp, SIGNED, &add2_ovf);
-+ overflow |= ((neg1_ovf != wi::OVF_NONE)
-+ | (neg2_ovf != wi::OVF_NONE)
-+ | (add1_ovf != wi::OVF_NONE)
-+ | (add2_ovf != wi::OVF_NONE));
-+ }
-+
-+ gcc_assert (!overflow);
-+
-+ return wide_int_to_tree (rtype, result);
-+ }
-+
-+ default:
-+ break;
-+ }
-+
-+ return NULL_TREE;
-+}
-+
-+/* ??? This duplicates information provided to the compiler by the
-+ ??? scheduler description. Some day, teach genautomata to output
-+ ??? the latencies and then CSE will just use that. */
-+
-+static bool
-+sparc_rtx_costs (rtx x, machine_mode mode, int outer_code,
-+ int opno ATTRIBUTE_UNUSED,
-+ int *total, bool speed ATTRIBUTE_UNUSED)
-+{
-+ int code = GET_CODE (x);
-+ bool float_mode_p = FLOAT_MODE_P (mode);
-+
-+ switch (code)
-+ {
-+ case CONST_INT:
-+ if (SMALL_INT (x))
-+ *total = 0;
-+ else
-+ *total = 2;
-+ return true;
-+
-+ case CONST_WIDE_INT:
-+ *total = 0;
-+ if (!SPARC_SIMM13_P (CONST_WIDE_INT_ELT (x, 0)))
-+ *total += 2;
-+ if (!SPARC_SIMM13_P (CONST_WIDE_INT_ELT (x, 1)))
-+ *total += 2;
-+ return true;
-+
-+ case HIGH:
-+ *total = 2;
-+ return true;
-+
-+ case CONST:
-+ case LABEL_REF:
-+ case SYMBOL_REF:
-+ *total = 4;
-+ return true;
-+
-+ case CONST_DOUBLE:
-+ *total = 8;
-+ return true;
-+
-+ case MEM:
-+ /* If outer-code was a sign or zero extension, a cost
-+ of COSTS_N_INSNS (1) was already added in. This is
-+ why we are subtracting it back out. */
-+ if (outer_code == ZERO_EXTEND)
-+ {
-+ *total = sparc_costs->int_zload - COSTS_N_INSNS (1);
-+ }
-+ else if (outer_code == SIGN_EXTEND)
-+ {
-+ *total = sparc_costs->int_sload - COSTS_N_INSNS (1);
-+ }
-+ else if (float_mode_p)
-+ {
-+ *total = sparc_costs->float_load;
-+ }
-+ else
-+ {
-+ *total = sparc_costs->int_load;
-+ }
-+
-+ return true;
-+
-+ case PLUS:
-+ case MINUS:
-+ if (float_mode_p)
-+ *total = sparc_costs->float_plusminus;
-+ else
-+ *total = COSTS_N_INSNS (1);
-+ return false;
-+
-+ case FMA:
-+ {
-+ rtx sub;
-+
-+ gcc_assert (float_mode_p);
-+ *total = sparc_costs->float_mul;
-+
-+ sub = XEXP (x, 0);
-+ if (GET_CODE (sub) == NEG)
-+ sub = XEXP (sub, 0);
-+ *total += rtx_cost (sub, mode, FMA, 0, speed);
-+
-+ sub = XEXP (x, 2);
-+ if (GET_CODE (sub) == NEG)
-+ sub = XEXP (sub, 0);
-+ *total += rtx_cost (sub, mode, FMA, 2, speed);
-+ return true;
-+ }
-+
-+ case MULT:
-+ if (float_mode_p)
-+ *total = sparc_costs->float_mul;
-+ else if (TARGET_ARCH32 && !TARGET_HARD_MUL)
-+ *total = COSTS_N_INSNS (25);
-+ else
-+ {
-+ int bit_cost;
-+
-+ bit_cost = 0;
-+ if (sparc_costs->int_mul_bit_factor)
-+ {
-+ int nbits;
-+
-+ if (GET_CODE (XEXP (x, 1)) == CONST_INT)
-+ {
-+ unsigned HOST_WIDE_INT value = INTVAL (XEXP (x, 1));
-+ for (nbits = 0; value != 0; value &= value - 1)
-+ nbits++;
-+ }
-+ else
-+ nbits = 7;
-+
-+ if (nbits < 3)
-+ nbits = 3;
-+ bit_cost = (nbits - 3) / sparc_costs->int_mul_bit_factor;
-+ bit_cost = COSTS_N_INSNS (bit_cost);
-+ }
-+
-+ if (mode == DImode || !TARGET_HARD_MUL)
-+ *total = sparc_costs->int_mulX + bit_cost;
-+ else
-+ *total = sparc_costs->int_mul + bit_cost;
-+ }
-+ return false;
-+
-+ case ASHIFT:
-+ case ASHIFTRT:
-+ case LSHIFTRT:
-+ *total = COSTS_N_INSNS (1) + sparc_costs->shift_penalty;
-+ return false;
-+
-+ case DIV:
-+ case UDIV:
-+ case MOD:
-+ case UMOD:
-+ if (float_mode_p)
-+ {
-+ if (mode == DFmode)
-+ *total = sparc_costs->float_div_df;
-+ else
-+ *total = sparc_costs->float_div_sf;
-+ }
-+ else
-+ {
-+ if (mode == DImode)
-+ *total = sparc_costs->int_divX;
-+ else
-+ *total = sparc_costs->int_div;
-+ }
-+ return false;
-+
-+ case NEG:
-+ if (! float_mode_p)
-+ {
-+ *total = COSTS_N_INSNS (1);
-+ return false;
-+ }
-+ /* FALLTHRU */
-+
-+ case ABS:
-+ case FLOAT:
-+ case UNSIGNED_FLOAT:
-+ case FIX:
-+ case UNSIGNED_FIX:
-+ case FLOAT_EXTEND:
-+ case FLOAT_TRUNCATE:
-+ *total = sparc_costs->float_move;
-+ return false;
-+
-+ case SQRT:
-+ if (mode == DFmode)
-+ *total = sparc_costs->float_sqrt_df;
-+ else
-+ *total = sparc_costs->float_sqrt_sf;
-+ return false;
-+
-+ case COMPARE:
-+ if (float_mode_p)
-+ *total = sparc_costs->float_cmp;
-+ else
-+ *total = COSTS_N_INSNS (1);
-+ return false;
-+
-+ case IF_THEN_ELSE:
-+ if (float_mode_p)
-+ *total = sparc_costs->float_cmove;
-+ else
-+ *total = sparc_costs->int_cmove;
-+ return false;
-+
-+ case IOR:
-+ /* Handle the NAND vector patterns. */
-+ if (sparc_vector_mode_supported_p (mode)
-+ && GET_CODE (XEXP (x, 0)) == NOT
-+ && GET_CODE (XEXP (x, 1)) == NOT)
-+ {
-+ *total = COSTS_N_INSNS (1);
-+ return true;
-+ }
-+ else
-+ return false;
-+
-+ default:
-+ return false;
-+ }
-+}
-+
-+/* Return true if CLASS is either GENERAL_REGS or I64_REGS. */
-+
-+static inline bool
-+general_or_i64_p (reg_class_t rclass)
-+{
-+ return (rclass == GENERAL_REGS || rclass == I64_REGS);
-+}
-+
-+/* Implement TARGET_REGISTER_MOVE_COST. */
-+
-+static int
-+sparc_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
-+ reg_class_t from, reg_class_t to)
-+{
-+ bool need_memory = false;
-+
-+ /* This helps postreload CSE to eliminate redundant comparisons. */
-+ if (from == NO_REGS || to == NO_REGS)
-+ return 100;
-+
-+ if (from == FPCC_REGS || to == FPCC_REGS)
-+ need_memory = true;
-+ else if ((FP_REG_CLASS_P (from) && general_or_i64_p (to))
-+ || (general_or_i64_p (from) && FP_REG_CLASS_P (to)))
-+ {
-+ if (TARGET_VIS3)
-+ {
-+ int size = GET_MODE_SIZE (mode);
-+ if (size == 8 || size == 4)
-+ {
-+ if (! TARGET_ARCH32 || size == 4)
-+ return 4;
-+ else
-+ return 6;
-+ }
-+ }
-+ need_memory = true;
-+ }
-+
-+ if (need_memory)
-+ {
-+ if (sparc_cpu == PROCESSOR_ULTRASPARC
-+ || sparc_cpu == PROCESSOR_ULTRASPARC3
-+ || sparc_cpu == PROCESSOR_NIAGARA
-+ || sparc_cpu == PROCESSOR_NIAGARA2
-+ || sparc_cpu == PROCESSOR_NIAGARA3
-+ || sparc_cpu == PROCESSOR_NIAGARA4
-+ || sparc_cpu == PROCESSOR_NIAGARA7
-+ || sparc_cpu == PROCESSOR_M8)
-+ return 12;
-+
-+ return 6;
-+ }
-+
-+ return 2;
-+}
-+
-+/* Emit the sequence of insns SEQ while preserving the registers REG and REG2.
-+ This is achieved by means of a manual dynamic stack space allocation in
-+ the current frame. We make the assumption that SEQ doesn't contain any
-+ function calls, with the possible exception of calls to the GOT helper. */
-+
-+static void
-+emit_and_preserve (rtx seq, rtx reg, rtx reg2)
-+{
-+ /* We must preserve the lowest 16 words for the register save area. */
-+ HOST_WIDE_INT offset = 16*UNITS_PER_WORD;
-+ /* We really need only 2 words of fresh stack space. */
-+ HOST_WIDE_INT size = SPARC_STACK_ALIGN (offset + 2*UNITS_PER_WORD);
-+
-+ rtx slot
-+ = gen_rtx_MEM (word_mode, plus_constant (Pmode, stack_pointer_rtx,
-+ SPARC_STACK_BIAS + offset));
-+
-+ emit_insn (gen_stack_pointer_inc (GEN_INT (-size)));
-+ emit_insn (gen_rtx_SET (slot, reg));
-+ if (reg2)
-+ emit_insn (gen_rtx_SET (adjust_address (slot, word_mode, UNITS_PER_WORD),
-+ reg2));
-+ emit_insn (seq);
-+ if (reg2)
-+ emit_insn (gen_rtx_SET (reg2,
-+ adjust_address (slot, word_mode, UNITS_PER_WORD)));
-+ emit_insn (gen_rtx_SET (reg, slot));
-+ emit_insn (gen_stack_pointer_inc (GEN_INT (size)));
-+}
-+
-+/* Output the assembler code for a thunk function. THUNK_DECL is the
-+ declaration for the thunk function itself, FUNCTION is the decl for
-+ the target function. DELTA is an immediate constant offset to be
-+ added to THIS. If VCALL_OFFSET is nonzero, the word at address
-+ (*THIS + VCALL_OFFSET) should be additionally added to THIS. */
-+
-+static void
-+sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
-+ HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
-+ tree function)
-+{
-+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
-+ rtx this_rtx, funexp;
-+ rtx_insn *insn;
-+ unsigned int int_arg_first;
-+
-+ reload_completed = 1;
-+ epilogue_completed = 1;
-+
-+ emit_note (NOTE_INSN_PROLOGUE_END);
-+
-+ if (TARGET_FLAT)
-+ {
-+ sparc_leaf_function_p = 1;
-+
-+ int_arg_first = SPARC_OUTGOING_INT_ARG_FIRST;
-+ }
-+ else if (flag_delayed_branch)
-+ {
-+ /* We will emit a regular sibcall below, so we need to instruct
-+ output_sibcall that we are in a leaf function. */
-+ sparc_leaf_function_p = crtl->uses_only_leaf_regs = 1;
-+
-+ /* This will cause final.c to invoke leaf_renumber_regs so we
-+ must behave as if we were in a not-yet-leafified function. */
-+ int_arg_first = SPARC_INCOMING_INT_ARG_FIRST;
-+ }
-+ else
-+ {
-+ /* We will emit the sibcall manually below, so we will need to
-+ manually spill non-leaf registers. */
-+ sparc_leaf_function_p = crtl->uses_only_leaf_regs = 0;
-+
-+ /* We really are in a leaf function. */
-+ int_arg_first = SPARC_OUTGOING_INT_ARG_FIRST;
-+ }
-+
-+ /* Find the "this" pointer. Normally in %o0, but in ARCH64 if the function
-+ returns a structure, the structure return pointer is there instead. */
-+ if (TARGET_ARCH64
-+ && aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
-+ this_rtx = gen_rtx_REG (Pmode, int_arg_first + 1);
-+ else
-+ this_rtx = gen_rtx_REG (Pmode, int_arg_first);
-+
-+ /* Add DELTA. When possible use a plain add, otherwise load it into
-+ a register first. */
-+ if (delta)
-+ {
-+ rtx delta_rtx = GEN_INT (delta);
-+
-+ if (! SPARC_SIMM13_P (delta))
-+ {
-+ rtx scratch = gen_rtx_REG (Pmode, 1);
-+ emit_move_insn (scratch, delta_rtx);
-+ delta_rtx = scratch;
-+ }
-+
-+ /* THIS_RTX += DELTA. */
-+ emit_insn (gen_add2_insn (this_rtx, delta_rtx));
-+ }
-+
-+ /* Add the word at address (*THIS_RTX + VCALL_OFFSET). */
-+ if (vcall_offset)
-+ {
-+ rtx vcall_offset_rtx = GEN_INT (vcall_offset);
-+ rtx scratch = gen_rtx_REG (Pmode, 1);
-+
-+ gcc_assert (vcall_offset < 0);
-+
-+ /* SCRATCH = *THIS_RTX. */
-+ emit_move_insn (scratch, gen_rtx_MEM (Pmode, this_rtx));
-+
-+ /* Prepare for adding VCALL_OFFSET. The difficulty is that we
-+ may not have any available scratch register at this point. */
-+ if (SPARC_SIMM13_P (vcall_offset))
-+ ;
-+ /* This is the case if ARCH64 (unless -ffixed-g5 is passed). */
-+ else if (! fixed_regs[5]
-+ /* The below sequence is made up of at least 2 insns,
-+ while the default method may need only one. */
-+ && vcall_offset < -8192)
-+ {
-+ rtx scratch2 = gen_rtx_REG (Pmode, 5);
-+ emit_move_insn (scratch2, vcall_offset_rtx);
-+ vcall_offset_rtx = scratch2;
-+ }
-+ else
-+ {
-+ rtx increment = GEN_INT (-4096);
-+
-+ /* VCALL_OFFSET is a negative number whose typical range can be
-+ estimated as -32768..0 in 32-bit mode. In almost all cases
-+ it is therefore cheaper to emit multiple add insns than
-+ spilling and loading the constant into a register (at least
-+ 6 insns). */
-+ while (! SPARC_SIMM13_P (vcall_offset))
-+ {
-+ emit_insn (gen_add2_insn (scratch, increment));
-+ vcall_offset += 4096;
-+ }
-+ vcall_offset_rtx = GEN_INT (vcall_offset); /* cannot be 0 */
-+ }
-+
-+ /* SCRATCH = *(*THIS_RTX + VCALL_OFFSET). */
-+ emit_move_insn (scratch, gen_rtx_MEM (Pmode,
-+ gen_rtx_PLUS (Pmode,
-+ scratch,
-+ vcall_offset_rtx)));
-+
-+ /* THIS_RTX += *(*THIS_RTX + VCALL_OFFSET). */
-+ emit_insn (gen_add2_insn (this_rtx, scratch));
-+ }
-+
-+ /* Generate a tail call to the target function. */
-+ if (! TREE_USED (function))
-+ {
-+ assemble_external (function);
-+ TREE_USED (function) = 1;
-+ }
-+ funexp = XEXP (DECL_RTL (function), 0);
-+
-+ if (flag_delayed_branch)
-+ {
-+ funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
-+ insn = emit_call_insn (gen_sibcall (funexp));
-+ SIBLING_CALL_P (insn) = 1;
-+ }
-+ else
-+ {
-+ /* The hoops we have to jump through in order to generate a sibcall
-+ without using delay slots... */
-+ rtx spill_reg, seq, scratch = gen_rtx_REG (Pmode, 1);
-+
-+ if (flag_pic)
-+ {
-+ spill_reg = gen_rtx_REG (word_mode, 15); /* %o7 */
-+ start_sequence ();
-+ load_got_register (); /* clobbers %o7 */
-+ if (!TARGET_VXWORKS_RTP)
-+ pic_offset_table_rtx = got_register_rtx;
-+ scratch = sparc_legitimize_pic_address (funexp, scratch);
-+ seq = get_insns ();
-+ end_sequence ();
-+ emit_and_preserve (seq, spill_reg, pic_offset_table_rtx);
-+ }
-+ else if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_rtx_SET (scratch,
-+ gen_rtx_HIGH (SImode, funexp)));
-+ emit_insn (gen_rtx_SET (scratch,
-+ gen_rtx_LO_SUM (SImode, scratch, funexp)));
-+ }
-+ else /* TARGET_ARCH64 */
-+ {
-+ switch (sparc_code_model)
-+ {
-+ case CM_MEDLOW:
-+ case CM_MEDMID:
-+ /* The destination can serve as a temporary. */
-+ sparc_emit_set_symbolic_const64 (scratch, funexp, scratch);
-+ break;
-+
-+ case CM_MEDANY:
-+ case CM_EMBMEDANY:
-+ /* The destination cannot serve as a temporary. */
-+ spill_reg = gen_rtx_REG (DImode, 15); /* %o7 */
-+ start_sequence ();
-+ sparc_emit_set_symbolic_const64 (scratch, funexp, spill_reg);
-+ seq = get_insns ();
-+ end_sequence ();
-+ emit_and_preserve (seq, spill_reg, 0);
-+ break;
-+
-+ default:
-+ gcc_unreachable ();
-+ }
-+ }
-+
-+ emit_jump_insn (gen_indirect_jump (scratch));
-+ }
-+
-+ emit_barrier ();
-+
-+ /* Run just enough of rest_of_compilation to get the insns emitted.
-+ There's not really enough bulk here to make other passes such as
-+ instruction scheduling worth while. */
-+ insn = get_insns ();
-+ shorten_branches (insn);
-+ assemble_start_function (thunk_fndecl, fnname);
-+ final_start_function (insn, file, 1);
-+ final (insn, file, 1);
-+ final_end_function ();
-+ assemble_end_function (thunk_fndecl, fnname);
-+
-+ reload_completed = 0;
-+ epilogue_completed = 0;
-+}
-+
-+/* Return true if sparc_output_mi_thunk would be able to output the
-+ assembler code for the thunk function specified by the arguments
-+ it is passed, and false otherwise. */
-+static bool
-+sparc_can_output_mi_thunk (const_tree thunk_fndecl ATTRIBUTE_UNUSED,
-+ HOST_WIDE_INT delta ATTRIBUTE_UNUSED,
-+ HOST_WIDE_INT vcall_offset,
-+ const_tree function ATTRIBUTE_UNUSED)
-+{
-+ /* Bound the loop used in the default method above. */
-+ return (vcall_offset >= -32768 || ! fixed_regs[5]);
-+}
-+
-+/* How to allocate a 'struct machine_function'. */
-+
-+static struct machine_function *
-+sparc_init_machine_status (void)
-+{
-+ return ggc_cleared_alloc<machine_function> ();
-+}
-+
-+/* Implement the TARGET_ASAN_SHADOW_OFFSET hook. */
-+
-+static unsigned HOST_WIDE_INT
-+sparc_asan_shadow_offset (void)
-+{
-+ return TARGET_ARCH64 ? (HOST_WIDE_INT_1 << 43) : (HOST_WIDE_INT_1 << 29);
-+}
-+
-+/* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
-+ We need to emit DTP-relative relocations. */
-+
-+static void
-+sparc_output_dwarf_dtprel (FILE *file, int size, rtx x)
-+{
-+ switch (size)
-+ {
-+ case 4:
-+ fputs ("\t.word\t%r_tls_dtpoff32(", file);
-+ break;
-+ case 8:
-+ fputs ("\t.xword\t%r_tls_dtpoff64(", file);
-+ break;
-+ default:
-+ gcc_unreachable ();
-+ }
-+ output_addr_const (file, x);
-+ fputs (")", file);
-+}
-+
-+/* Do whatever processing is required at the end of a file. */
-+
-+static void
-+sparc_file_end (void)
-+{
-+ /* If we need to emit the special GOT helper function, do so now. */
-+ if (got_helper_needed)
-+ {
-+ const char *name = XSTR (got_helper_rtx, 0);
-+#ifdef DWARF2_UNWIND_INFO
-+ bool do_cfi;
-+#endif
-+
-+ if (USE_HIDDEN_LINKONCE)
-+ {
-+ tree decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
-+ get_identifier (name),
-+ build_function_type_list (void_type_node,
-+ NULL_TREE));
-+ DECL_RESULT (decl) = build_decl (BUILTINS_LOCATION, RESULT_DECL,
-+ NULL_TREE, void_type_node);
-+ TREE_PUBLIC (decl) = 1;
-+ TREE_STATIC (decl) = 1;
-+ make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
-+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
-+ DECL_VISIBILITY_SPECIFIED (decl) = 1;
-+ resolve_unique_section (decl, 0, flag_function_sections);
-+ allocate_struct_function (decl, true);
-+ cfun->is_thunk = 1;
-+ current_function_decl = decl;
-+ init_varasm_status ();
-+ assemble_start_function (decl, name);
-+ }
-+ else
-+ {
-+ const int align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
-+ switch_to_section (text_section);
-+ if (align > 0)
-+ ASM_OUTPUT_ALIGN (asm_out_file, align);
-+ ASM_OUTPUT_LABEL (asm_out_file, name);
-+ }
-+
-+#ifdef DWARF2_UNWIND_INFO
-+ do_cfi = dwarf2out_do_cfi_asm ();
-+ if (do_cfi)
-+ output_asm_insn (".cfi_startproc", NULL);
-+#endif
-+ if (flag_delayed_branch)
-+ {
-+ output_asm_insn ("jmp\t%%o7+8", NULL);
-+ output_asm_insn (" add\t%%o7, %0, %0", &got_register_rtx);
-+ }
-+ else
-+ {
-+ output_asm_insn ("add\t%%o7, %0, %0", &got_register_rtx);
-+ output_asm_insn ("jmp\t%%o7+8", NULL);
-+ output_asm_insn (" nop", NULL);
-+ }
-+#ifdef DWARF2_UNWIND_INFO
-+ if (do_cfi)
-+ output_asm_insn (".cfi_endproc", NULL);
-+#endif
-+ }
-+
-+ if (NEED_INDICATE_EXEC_STACK)
-+ file_end_indicate_exec_stack ();
-+
-+#ifdef TARGET_SOLARIS
-+ solaris_file_end ();
-+#endif
-+}
-+
-+#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
-+/* Implement TARGET_MANGLE_TYPE. */
-+
-+static const char *
-+sparc_mangle_type (const_tree type)
-+{
-+ if (TARGET_ARCH32
-+ && TYPE_MAIN_VARIANT (type) == long_double_type_node
-+ && TARGET_LONG_DOUBLE_128)
-+ return "g";
-+
-+ /* For all other types, use normal C++ mangling. */
-+ return NULL;
-+}
-+#endif
-+
-+/* Expand a membar instruction for various use cases. Both the LOAD_STORE
-+ and BEFORE_AFTER arguments of the form X_Y. They are two-bit masks where
-+ bit 0 indicates that X is true, and bit 1 indicates Y is true. */
-+
-+void
-+sparc_emit_membar_for_model (enum memmodel model,
-+ int load_store, int before_after)
-+{
-+ /* Bits for the MEMBAR mmask field. */
-+ const int LoadLoad = 1;
-+ const int StoreLoad = 2;
-+ const int LoadStore = 4;
-+ const int StoreStore = 8;
-+
-+ int mm = 0, implied = 0;
-+
-+ switch (sparc_memory_model)
-+ {
-+ case SMM_SC:
-+ /* Sequential Consistency. All memory transactions are immediately
-+ visible in sequential execution order. No barriers needed. */
-+ implied = LoadLoad | StoreLoad | LoadStore | StoreStore;
-+ break;
-+
-+ case SMM_TSO:
-+ /* Total Store Ordering: all memory transactions with store semantics
-+ are followed by an implied StoreStore. */
-+ implied |= StoreStore;
-+
-+ /* If we're not looking for a raw barrer (before+after), then atomic
-+ operations get the benefit of being both load and store. */
-+ if (load_store == 3 && before_after == 1)
-+ implied |= StoreLoad;
-+ /* FALLTHRU */
-+
-+ case SMM_PSO:
-+ /* Partial Store Ordering: all memory transactions with load semantics
-+ are followed by an implied LoadLoad | LoadStore. */
-+ implied |= LoadLoad | LoadStore;
-+
-+ /* If we're not looking for a raw barrer (before+after), then atomic
-+ operations get the benefit of being both load and store. */
-+ if (load_store == 3 && before_after == 2)
-+ implied |= StoreLoad | StoreStore;
-+ /* FALLTHRU */
-+
-+ case SMM_RMO:
-+ /* Relaxed Memory Ordering: no implicit bits. */
-+ break;
-+
-+ default:
-+ gcc_unreachable ();
-+ }
-+
-+ if (before_after & 1)
-+ {
-+ if (is_mm_release (model) || is_mm_acq_rel (model)
-+ || is_mm_seq_cst (model))
-+ {
-+ if (load_store & 1)
-+ mm |= LoadLoad | StoreLoad;
-+ if (load_store & 2)
-+ mm |= LoadStore | StoreStore;
-+ }
-+ }
-+ if (before_after & 2)
-+ {
-+ if (is_mm_acquire (model) || is_mm_acq_rel (model)
-+ || is_mm_seq_cst (model))
-+ {
-+ if (load_store & 1)
-+ mm |= LoadLoad | LoadStore;
-+ if (load_store & 2)
-+ mm |= StoreLoad | StoreStore;
-+ }
-+ }
-+
-+ /* Remove the bits implied by the system memory model. */
-+ mm &= ~implied;
-+
-+ /* For raw barriers (before+after), always emit a barrier.
-+ This will become a compile-time barrier if needed. */
-+ if (mm || before_after == 3)
-+ emit_insn (gen_membar (GEN_INT (mm)));
-+}
-+
-+/* Expand code to perform a 8 or 16-bit compare and swap by doing 32-bit
-+ compare and swap on the word containing the byte or half-word. */
-+
-+static void
-+sparc_expand_compare_and_swap_12 (rtx bool_result, rtx result, rtx mem,
-+ rtx oldval, rtx newval)
-+{
-+ rtx addr1 = force_reg (Pmode, XEXP (mem, 0));
-+ rtx addr = gen_reg_rtx (Pmode);
-+ rtx off = gen_reg_rtx (SImode);
-+ rtx oldv = gen_reg_rtx (SImode);
-+ rtx newv = gen_reg_rtx (SImode);
-+ rtx oldvalue = gen_reg_rtx (SImode);
-+ rtx newvalue = gen_reg_rtx (SImode);
-+ rtx res = gen_reg_rtx (SImode);
-+ rtx resv = gen_reg_rtx (SImode);
-+ rtx memsi, val, mask, cc;
-+
-+ emit_insn (gen_rtx_SET (addr, gen_rtx_AND (Pmode, addr1, GEN_INT (-4))));
-+
-+ if (Pmode != SImode)
-+ addr1 = gen_lowpart (SImode, addr1);
-+ emit_insn (gen_rtx_SET (off, gen_rtx_AND (SImode, addr1, GEN_INT (3))));
-+
-+ memsi = gen_rtx_MEM (SImode, addr);
-+ set_mem_alias_set (memsi, ALIAS_SET_MEMORY_BARRIER);
-+ MEM_VOLATILE_P (memsi) = MEM_VOLATILE_P (mem);
-+
-+ val = copy_to_reg (memsi);
-+
-+ emit_insn (gen_rtx_SET (off,
-+ gen_rtx_XOR (SImode, off,
-+ GEN_INT (GET_MODE (mem) == QImode
-+ ? 3 : 2))));
-+
-+ emit_insn (gen_rtx_SET (off, gen_rtx_ASHIFT (SImode, off, GEN_INT (3))));
-+
-+ if (GET_MODE (mem) == QImode)
-+ mask = force_reg (SImode, GEN_INT (0xff));
-+ else
-+ mask = force_reg (SImode, GEN_INT (0xffff));
-+
-+ emit_insn (gen_rtx_SET (mask, gen_rtx_ASHIFT (SImode, mask, off)));
-+
-+ emit_insn (gen_rtx_SET (val,
-+ gen_rtx_AND (SImode, gen_rtx_NOT (SImode, mask),
-+ val)));
-+
-+ oldval = gen_lowpart (SImode, oldval);
-+ emit_insn (gen_rtx_SET (oldv, gen_rtx_ASHIFT (SImode, oldval, off)));
-+
-+ newval = gen_lowpart_common (SImode, newval);
-+ emit_insn (gen_rtx_SET (newv, gen_rtx_ASHIFT (SImode, newval, off)));
-+
-+ emit_insn (gen_rtx_SET (oldv, gen_rtx_AND (SImode, oldv, mask)));
-+
-+ emit_insn (gen_rtx_SET (newv, gen_rtx_AND (SImode, newv, mask)));
-+
-+ rtx_code_label *end_label = gen_label_rtx ();
-+ rtx_code_label *loop_label = gen_label_rtx ();
-+ emit_label (loop_label);
-+
-+ emit_insn (gen_rtx_SET (oldvalue, gen_rtx_IOR (SImode, oldv, val)));
-+
-+ emit_insn (gen_rtx_SET (newvalue, gen_rtx_IOR (SImode, newv, val)));
-+
-+ emit_move_insn (bool_result, const1_rtx);
-+
-+ emit_insn (gen_atomic_compare_and_swapsi_1 (res, memsi, oldvalue, newvalue));
-+
-+ emit_cmp_and_jump_insns (res, oldvalue, EQ, NULL, SImode, 0, end_label);
-+
-+ emit_insn (gen_rtx_SET (resv,
-+ gen_rtx_AND (SImode, gen_rtx_NOT (SImode, mask),
-+ res)));
-+
-+ emit_move_insn (bool_result, const0_rtx);
-+
-+ cc = gen_compare_reg_1 (NE, resv, val);
-+ emit_insn (gen_rtx_SET (val, resv));
-+
-+ /* Use cbranchcc4 to separate the compare and branch! */
-+ emit_jump_insn (gen_cbranchcc4 (gen_rtx_NE (VOIDmode, cc, const0_rtx),
-+ cc, const0_rtx, loop_label));
-+
-+ emit_label (end_label);
-+
-+ emit_insn (gen_rtx_SET (res, gen_rtx_AND (SImode, res, mask)));
-+
-+ emit_insn (gen_rtx_SET (res, gen_rtx_LSHIFTRT (SImode, res, off)));
-+
-+ emit_move_insn (result, gen_lowpart (GET_MODE (result), res));
-+}
-+
-+/* Expand code to perform a compare-and-swap. */
-+
-+void
-+sparc_expand_compare_and_swap (rtx operands[])
-+{
-+ rtx bval, retval, mem, oldval, newval;
-+ machine_mode mode;
-+ enum memmodel model;
-+
-+ bval = operands[0];
-+ retval = operands[1];
-+ mem = operands[2];
-+ oldval = operands[3];
-+ newval = operands[4];
-+ model = (enum memmodel) INTVAL (operands[6]);
-+ mode = GET_MODE (mem);
-+
-+ sparc_emit_membar_for_model (model, 3, 1);
-+
-+ if (reg_overlap_mentioned_p (retval, oldval))
-+ oldval = copy_to_reg (oldval);
-+
-+ if (mode == QImode || mode == HImode)
-+ sparc_expand_compare_and_swap_12 (bval, retval, mem, oldval, newval);
-+ else
-+ {
-+ rtx (*gen) (rtx, rtx, rtx, rtx);
-+ rtx x;
-+
-+ if (mode == SImode)
-+ gen = gen_atomic_compare_and_swapsi_1;
-+ else
-+ gen = gen_atomic_compare_and_swapdi_1;
-+ emit_insn (gen (retval, mem, oldval, newval));
-+
-+ x = emit_store_flag (bval, EQ, retval, oldval, mode, 1, 1);
-+ if (x != bval)
-+ convert_move (bval, x, 1);
-+ }
-+
-+ sparc_emit_membar_for_model (model, 3, 2);
-+}
-+
-+void
-+sparc_expand_vec_perm_bmask (machine_mode vmode, rtx sel)
-+{
-+ rtx t_1, t_2, t_3;
-+
-+ sel = gen_lowpart (DImode, sel);
-+ switch (vmode)
-+ {
-+ case E_V2SImode:
-+ /* inp = xxxxxxxAxxxxxxxB */
-+ t_1 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (16),
-+ NULL_RTX, 1, OPTAB_DIRECT);
-+ /* t_1 = ....xxxxxxxAxxx. */
-+ sel = expand_simple_binop (SImode, AND, gen_lowpart (SImode, sel),
-+ GEN_INT (3), NULL_RTX, 1, OPTAB_DIRECT);
-+ t_1 = expand_simple_binop (SImode, AND, gen_lowpart (SImode, t_1),
-+ GEN_INT (0x30000), NULL_RTX, 1, OPTAB_DIRECT);
-+ /* sel = .......B */
-+ /* t_1 = ...A.... */
-+ sel = expand_simple_binop (SImode, IOR, sel, t_1, sel, 1, OPTAB_DIRECT);
-+ /* sel = ...A...B */
-+ sel = expand_mult (SImode, sel, GEN_INT (0x4444), sel, 1);
-+ /* sel = AAAABBBB * 4 */
-+ t_1 = force_reg (SImode, GEN_INT (0x01230123));
-+ /* sel = { A*4, A*4+1, A*4+2, ... } */
-+ break;
-+
-+ case E_V4HImode:
-+ /* inp = xxxAxxxBxxxCxxxD */
-+ t_1 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (8),
-+ NULL_RTX, 1, OPTAB_DIRECT);
-+ t_2 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (16),
-+ NULL_RTX, 1, OPTAB_DIRECT);
-+ t_3 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (24),
-+ NULL_RTX, 1, OPTAB_DIRECT);
-+ /* t_1 = ..xxxAxxxBxxxCxx */
-+ /* t_2 = ....xxxAxxxBxxxC */
-+ /* t_3 = ......xxxAxxxBxx */
-+ sel = expand_simple_binop (SImode, AND, gen_lowpart (SImode, sel),
-+ GEN_INT (0x07),
-+ NULL_RTX, 1, OPTAB_DIRECT);
-+ t_1 = expand_simple_binop (SImode, AND, gen_lowpart (SImode, t_1),
-+ GEN_INT (0x0700),
-+ NULL_RTX, 1, OPTAB_DIRECT);
-+ t_2 = expand_simple_binop (SImode, AND, gen_lowpart (SImode, t_2),
-+ GEN_INT (0x070000),
-+ NULL_RTX, 1, OPTAB_DIRECT);
-+ t_3 = expand_simple_binop (SImode, AND, gen_lowpart (SImode, t_3),
-+ GEN_INT (0x07000000),
-+ NULL_RTX, 1, OPTAB_DIRECT);
-+ /* sel = .......D */
-+ /* t_1 = .....C.. */
-+ /* t_2 = ...B.... */
-+ /* t_3 = .A...... */
-+ sel = expand_simple_binop (SImode, IOR, sel, t_1, sel, 1, OPTAB_DIRECT);
-+ t_2 = expand_simple_binop (SImode, IOR, t_2, t_3, t_2, 1, OPTAB_DIRECT);
-+ sel = expand_simple_binop (SImode, IOR, sel, t_2, sel, 1, OPTAB_DIRECT);
-+ /* sel = .A.B.C.D */
-+ sel = expand_mult (SImode, sel, GEN_INT (0x22), sel, 1);
-+ /* sel = AABBCCDD * 2 */
-+ t_1 = force_reg (SImode, GEN_INT (0x01010101));
-+ /* sel = { A*2, A*2+1, B*2, B*2+1, ... } */
-+ break;
-+
-+ case E_V8QImode:
-+ /* input = xAxBxCxDxExFxGxH */
-+ sel = expand_simple_binop (DImode, AND, sel,
-+ GEN_INT ((HOST_WIDE_INT)0x0f0f0f0f << 32
-+ | 0x0f0f0f0f),
-+ NULL_RTX, 1, OPTAB_DIRECT);
-+ /* sel = .A.B.C.D.E.F.G.H */
-+ t_1 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (4),
-+ NULL_RTX, 1, OPTAB_DIRECT);
-+ /* t_1 = ..A.B.C.D.E.F.G. */
-+ sel = expand_simple_binop (DImode, IOR, sel, t_1,
-+ NULL_RTX, 1, OPTAB_DIRECT);
-+ /* sel = .AABBCCDDEEFFGGH */
-+ sel = expand_simple_binop (DImode, AND, sel,
-+ GEN_INT ((HOST_WIDE_INT)0xff00ff << 32
-+ | 0xff00ff),
-+ NULL_RTX, 1, OPTAB_DIRECT);
-+ /* sel = ..AB..CD..EF..GH */
-+ t_1 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (8),
-+ NULL_RTX, 1, OPTAB_DIRECT);
-+ /* t_1 = ....AB..CD..EF.. */
-+ sel = expand_simple_binop (DImode, IOR, sel, t_1,
-+ NULL_RTX, 1, OPTAB_DIRECT);
-+ /* sel = ..ABABCDCDEFEFGH */
-+ sel = expand_simple_binop (DImode, AND, sel,
-+ GEN_INT ((HOST_WIDE_INT)0xffff << 32 | 0xffff),
-+ NULL_RTX, 1, OPTAB_DIRECT);
-+ /* sel = ....ABCD....EFGH */
-+ t_1 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (16),
-+ NULL_RTX, 1, OPTAB_DIRECT);
-+ /* t_1 = ........ABCD.... */
-+ sel = gen_lowpart (SImode, sel);
-+ t_1 = gen_lowpart (SImode, t_1);
-+ break;
-+
-+ default:
-+ gcc_unreachable ();
-+ }
-+
-+ /* Always perform the final addition/merge within the bmask insn. */
-+ emit_insn (gen_bmasksi_vis (gen_reg_rtx (SImode), sel, t_1));
-+}
-+
-+/* Implement TARGET_VEC_PERM_CONST. */
-+
-+static bool
-+sparc_vectorize_vec_perm_const (machine_mode vmode, rtx target, rtx op0,
-+ rtx op1, const vec_perm_indices &sel)
-+{
-+ if (!TARGET_VIS2)
-+ return false;
-+
-+ /* All permutes are supported. */
-+ if (!target)
-+ return true;
-+
-+ /* Force target-independent code to convert constant permutations on other
-+ modes down to V8QI. Rely on this to avoid the complexity of the byte
-+ order of the permutation. */
-+ if (vmode != V8QImode)
-+ return false;
-+
-+ unsigned int i, mask;
-+ for (i = mask = 0; i < 8; ++i)
-+ mask |= (sel[i] & 0xf) << (28 - i*4);
-+ rtx mask_rtx = force_reg (SImode, gen_int_mode (mask, SImode));
-+
-+ emit_insn (gen_bmasksi_vis (gen_reg_rtx (SImode), mask_rtx, const0_rtx));
-+ emit_insn (gen_bshufflev8qi_vis (target, op0, op1));
-+ return true;
-+}
-+
-+/* Implement TARGET_FRAME_POINTER_REQUIRED. */
-+
-+static bool
-+sparc_frame_pointer_required (void)
-+{
-+ /* If the stack pointer is dynamically modified in the function, it cannot
-+ serve as the frame pointer. */
-+ if (cfun->calls_alloca)
-+ return true;
-+
-+ /* If the function receives nonlocal gotos, it needs to save the frame
-+ pointer in the nonlocal_goto_save_area object. */
-+ if (cfun->has_nonlocal_label)
-+ return true;
-+
-+ /* In flat mode, that's it. */
-+ if (TARGET_FLAT)
-+ return false;
-+
-+ /* Otherwise, the frame pointer is required if the function isn't leaf, but
-+ we cannot use sparc_leaf_function_p since it hasn't been computed yet. */
-+ return !(optimize > 0 && crtl->is_leaf && only_leaf_regs_used ());
-+}
-+
-+/* The way this is structured, we can't eliminate SFP in favor of SP
-+ if the frame pointer is required: we want to use the SFP->HFP elimination
-+ in that case. But the test in update_eliminables doesn't know we are
-+ assuming below that we only do the former elimination. */
-+
-+static bool
-+sparc_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
-+{
-+ return to == HARD_FRAME_POINTER_REGNUM || !sparc_frame_pointer_required ();
-+}
-+
-+/* If !TARGET_FPU, then make the fp registers and fp cc regs fixed so that
-+ they won't be allocated. */
-+
-+static void
-+sparc_conditional_register_usage (void)
-+{
-+ if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
-+ fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
-+ /* If the user has passed -f{fixed,call-{used,saved}}-g5 */
-+ /* then honor it. */
-+ if (TARGET_ARCH32 && fixed_regs[5])
-+ fixed_regs[5] = 1;
-+ else if (TARGET_ARCH64 && fixed_regs[5] == 2)
-+ fixed_regs[5] = 0;
-+ if (! TARGET_V9)
-+ {
-+ int regno;
-+ for (regno = SPARC_FIRST_V9_FP_REG;
-+ regno <= SPARC_LAST_V9_FP_REG;
-+ regno++)
-+ fixed_regs[regno] = 1;
-+ /* %fcc0 is used by v8 and v9. */
-+ for (regno = SPARC_FIRST_V9_FCC_REG + 1;
-+ regno <= SPARC_LAST_V9_FCC_REG;
-+ regno++)
-+ fixed_regs[regno] = 1;
-+ }
-+ if (! TARGET_FPU)
-+ {
-+ int regno;
-+ for (regno = 32; regno < SPARC_LAST_V9_FCC_REG; regno++)
-+ fixed_regs[regno] = 1;
-+ }
-+ /* If the user has passed -f{fixed,call-{used,saved}}-g2 */
-+ /* then honor it. Likewise with g3 and g4. */
-+ if (fixed_regs[2] == 2)
-+ fixed_regs[2] = ! TARGET_APP_REGS;
-+ if (fixed_regs[3] == 2)
-+ fixed_regs[3] = ! TARGET_APP_REGS;
-+ if (TARGET_ARCH32 && fixed_regs[4] == 2)
-+ fixed_regs[4] = ! TARGET_APP_REGS;
-+ else if (TARGET_CM_EMBMEDANY)
-+ fixed_regs[4] = 1;
-+ else if (fixed_regs[4] == 2)
-+ fixed_regs[4] = 0;
-+ if (TARGET_FLAT)
-+ {
-+ int regno;
-+ /* Disable leaf functions. */
-+ memset (sparc_leaf_regs, 0, FIRST_PSEUDO_REGISTER);
-+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
-+ leaf_reg_remap [regno] = regno;
-+ }
-+ if (TARGET_VIS)
-+ global_regs[SPARC_GSR_REG] = 1;
-+}
-+
-+/* Implement TARGET_USE_PSEUDO_PIC_REG. */
-+
-+static bool
-+sparc_use_pseudo_pic_reg (void)
-+{
-+ return !TARGET_VXWORKS_RTP && flag_pic;
-+}
-+
-+/* Implement TARGET_INIT_PIC_REG. */
-+
-+static void
-+sparc_init_pic_reg (void)
-+{
-+ edge entry_edge;
-+ rtx_insn *seq;
-+
-+ /* In PIC mode, we need to always initialize the PIC register if optimization
-+ is enabled, because we are called from IRA and LRA may later force things
-+ to the constant pool for optimization purposes. */
-+ if (!flag_pic || (!crtl->uses_pic_offset_table && !optimize))
-+ return;
-+
-+ start_sequence ();
-+ load_got_register ();
-+ if (!TARGET_VXWORKS_RTP)
-+ emit_move_insn (pic_offset_table_rtx, got_register_rtx);
-+ seq = get_insns ();
-+ end_sequence ();
-+
-+ entry_edge = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
-+ insert_insn_on_edge (seq, entry_edge);
-+ commit_one_edge_insertion (entry_edge);
-+}
-+
-+/* Implement TARGET_PREFERRED_RELOAD_CLASS:
-+
-+ - We can't load constants into FP registers.
-+ - We can't load FP constants into integer registers when soft-float,
-+ because there is no soft-float pattern with a r/F constraint.
-+ - We can't load FP constants into integer registers for TFmode unless
-+ it is 0.0L, because there is no movtf pattern with a r/F constraint.
-+ - Try and reload integer constants (symbolic or otherwise) back into
-+ registers directly, rather than having them dumped to memory. */
-+
-+static reg_class_t
-+sparc_preferred_reload_class (rtx x, reg_class_t rclass)
-+{
-+ machine_mode mode = GET_MODE (x);
-+ if (CONSTANT_P (x))
-+ {
-+ if (FP_REG_CLASS_P (rclass)
-+ || rclass == GENERAL_OR_FP_REGS
-+ || rclass == GENERAL_OR_EXTRA_FP_REGS
-+ || (GET_MODE_CLASS (mode) == MODE_FLOAT && ! TARGET_FPU)
-+ || (mode == TFmode && ! const_zero_operand (x, mode)))
-+ return NO_REGS;
-+
-+ if (GET_MODE_CLASS (mode) == MODE_INT)
-+ return GENERAL_REGS;
-+
-+ if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
-+ {
-+ if (! FP_REG_CLASS_P (rclass)
-+ || !(const_zero_operand (x, mode)
-+ || const_all_ones_operand (x, mode)))
-+ return NO_REGS;
-+ }
-+ }
-+
-+ if (TARGET_VIS3
-+ && ! TARGET_ARCH64
-+ && (rclass == EXTRA_FP_REGS
-+ || rclass == GENERAL_OR_EXTRA_FP_REGS))
-+ {
-+ int regno = true_regnum (x);
-+
-+ if (SPARC_INT_REG_P (regno))
-+ return (rclass == EXTRA_FP_REGS
-+ ? FP_REGS : GENERAL_OR_FP_REGS);
-+ }
-+
-+ return rclass;
-+}
-+
-+/* Return true if we use LRA instead of reload pass. */
-+
-+static bool
-+sparc_lra_p (void)
-+{
-+ return TARGET_LRA;
-+}
-+
-+/* Output a wide multiply instruction in V8+ mode. INSN is the instruction,
-+ OPERANDS are its operands and OPCODE is the mnemonic to be used. */
-+
-+const char *
-+output_v8plus_mult (rtx_insn *insn, rtx *operands, const char *opcode)
-+{
-+ char mulstr[32];
-+
-+ gcc_assert (! TARGET_ARCH64);
-+
-+ if (sparc_check_64 (operands[1], insn) <= 0)
-+ output_asm_insn ("srl\t%L1, 0, %L1", operands);
-+ if (which_alternative == 1)
-+ output_asm_insn ("sllx\t%H1, 32, %H1", operands);
-+ if (GET_CODE (operands[2]) == CONST_INT)
-+ {
-+ if (which_alternative == 1)
-+ {
-+ output_asm_insn ("or\t%L1, %H1, %H1", operands);
-+ sprintf (mulstr, "%s\t%%H1, %%2, %%L0", opcode);
-+ output_asm_insn (mulstr, operands);
-+ return "srlx\t%L0, 32, %H0";
-+ }
-+ else
-+ {
-+ output_asm_insn ("sllx\t%H1, 32, %3", operands);
-+ output_asm_insn ("or\t%L1, %3, %3", operands);
-+ sprintf (mulstr, "%s\t%%3, %%2, %%3", opcode);
-+ output_asm_insn (mulstr, operands);
-+ output_asm_insn ("srlx\t%3, 32, %H0", operands);
-+ return "mov\t%3, %L0";
-+ }
-+ }
-+ else if (rtx_equal_p (operands[1], operands[2]))
-+ {
-+ if (which_alternative == 1)
-+ {
-+ output_asm_insn ("or\t%L1, %H1, %H1", operands);
-+ sprintf (mulstr, "%s\t%%H1, %%H1, %%L0", opcode);
-+ output_asm_insn (mulstr, operands);
-+ return "srlx\t%L0, 32, %H0";
-+ }
-+ else
-+ {
-+ output_asm_insn ("sllx\t%H1, 32, %3", operands);
-+ output_asm_insn ("or\t%L1, %3, %3", operands);
-+ sprintf (mulstr, "%s\t%%3, %%3, %%3", opcode);
-+ output_asm_insn (mulstr, operands);
-+ output_asm_insn ("srlx\t%3, 32, %H0", operands);
-+ return "mov\t%3, %L0";
-+ }
-+ }
-+ if (sparc_check_64 (operands[2], insn) <= 0)
-+ output_asm_insn ("srl\t%L2, 0, %L2", operands);
-+ if (which_alternative == 1)
-+ {
-+ output_asm_insn ("or\t%L1, %H1, %H1", operands);
-+ output_asm_insn ("sllx\t%H2, 32, %L1", operands);
-+ output_asm_insn ("or\t%L2, %L1, %L1", operands);
-+ sprintf (mulstr, "%s\t%%H1, %%L1, %%L0", opcode);
-+ output_asm_insn (mulstr, operands);
-+ return "srlx\t%L0, 32, %H0";
-+ }
-+ else
-+ {
-+ output_asm_insn ("sllx\t%H1, 32, %3", operands);
-+ output_asm_insn ("sllx\t%H2, 32, %4", operands);
-+ output_asm_insn ("or\t%L1, %3, %3", operands);
-+ output_asm_insn ("or\t%L2, %4, %4", operands);
-+ sprintf (mulstr, "%s\t%%3, %%4, %%3", opcode);
-+ output_asm_insn (mulstr, operands);
-+ output_asm_insn ("srlx\t%3, 32, %H0", operands);
-+ return "mov\t%3, %L0";
-+ }
-+}
-+
-+/* Subroutine of sparc_expand_vector_init. Emit code to initialize
-+ all fields of TARGET to ELT by means of VIS2 BSHUFFLE insn. MODE
-+ and INNER_MODE are the modes describing TARGET. */
-+
-+static void
-+vector_init_bshuffle (rtx target, rtx elt, machine_mode mode,
-+ machine_mode inner_mode)
-+{
-+ rtx t1, final_insn, sel;
-+ int bmask;
-+
-+ t1 = gen_reg_rtx (mode);
-+
-+ elt = convert_modes (SImode, inner_mode, elt, true);
-+ emit_move_insn (gen_lowpart(SImode, t1), elt);
-+
-+ switch (mode)
-+ {
-+ case E_V2SImode:
-+ final_insn = gen_bshufflev2si_vis (target, t1, t1);
-+ bmask = 0x45674567;
-+ break;
-+ case E_V4HImode:
-+ final_insn = gen_bshufflev4hi_vis (target, t1, t1);
-+ bmask = 0x67676767;
-+ break;
-+ case E_V8QImode:
-+ final_insn = gen_bshufflev8qi_vis (target, t1, t1);
-+ bmask = 0x77777777;
-+ break;
-+ default:
-+ gcc_unreachable ();
-+ }
-+
-+ sel = force_reg (SImode, GEN_INT (bmask));
-+ emit_insn (gen_bmasksi_vis (gen_reg_rtx (SImode), sel, const0_rtx));
-+ emit_insn (final_insn);
-+}
-+
-+/* Subroutine of sparc_expand_vector_init. Emit code to initialize
-+ all fields of TARGET to ELT in V8QI by means of VIS FPMERGE insn. */
-+
-+static void
-+vector_init_fpmerge (rtx target, rtx elt)
-+{
-+ rtx t1, t2, t2_low, t3, t3_low;
-+
-+ t1 = gen_reg_rtx (V4QImode);
-+ elt = convert_modes (SImode, QImode, elt, true);
-+ emit_move_insn (gen_lowpart (SImode, t1), elt);
-+
-+ t2 = gen_reg_rtx (V8QImode);
-+ t2_low = gen_lowpart (V4QImode, t2);
-+ emit_insn (gen_fpmerge_vis (t2, t1, t1));
-+
-+ t3 = gen_reg_rtx (V8QImode);
-+ t3_low = gen_lowpart (V4QImode, t3);
-+ emit_insn (gen_fpmerge_vis (t3, t2_low, t2_low));
-+
-+ emit_insn (gen_fpmerge_vis (target, t3_low, t3_low));
-+}
-+
-+/* Subroutine of sparc_expand_vector_init. Emit code to initialize
-+ all fields of TARGET to ELT in V4HI by means of VIS FALIGNDATA insn. */
-+
-+static void
-+vector_init_faligndata (rtx target, rtx elt)
-+{
-+ rtx t1 = gen_reg_rtx (V4HImode);
-+ int i;
-+
-+ elt = convert_modes (SImode, HImode, elt, true);
-+ emit_move_insn (gen_lowpart (SImode, t1), elt);
-+
-+ emit_insn (gen_alignaddrsi_vis (gen_reg_rtx (SImode),
-+ force_reg (SImode, GEN_INT (6)),
-+ const0_rtx));
-+
-+ for (i = 0; i < 4; i++)
-+ emit_insn (gen_faligndatav4hi_vis (target, t1, target));
-+}
-+
-+/* Emit code to initialize TARGET to values for individual fields VALS. */
-+
-+void
-+sparc_expand_vector_init (rtx target, rtx vals)
-+{
-+ const machine_mode mode = GET_MODE (target);
-+ const machine_mode inner_mode = GET_MODE_INNER (mode);
-+ const int n_elts = GET_MODE_NUNITS (mode);
-+ int i, n_var = 0;
-+ bool all_same = true;
-+ rtx mem;
-+
-+ for (i = 0; i < n_elts; i++)
-+ {
-+ rtx x = XVECEXP (vals, 0, i);
-+ if (!(CONST_SCALAR_INT_P (x) || CONST_DOUBLE_P (x) || CONST_FIXED_P (x)))
-+ n_var++;
-+
-+ if (i > 0 && !rtx_equal_p (x, XVECEXP (vals, 0, 0)))
-+ all_same = false;
-+ }
-+
-+ if (n_var == 0)
-+ {
-+ emit_move_insn (target, gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)));
-+ return;
-+ }
-+
-+ if (GET_MODE_SIZE (inner_mode) == GET_MODE_SIZE (mode))
-+ {
-+ if (GET_MODE_SIZE (inner_mode) == 4)
-+ {
-+ emit_move_insn (gen_lowpart (SImode, target),
-+ gen_lowpart (SImode, XVECEXP (vals, 0, 0)));
-+ return;
-+ }
-+ else if (GET_MODE_SIZE (inner_mode) == 8)
-+ {
-+ emit_move_insn (gen_lowpart (DImode, target),
-+ gen_lowpart (DImode, XVECEXP (vals, 0, 0)));
-+ return;
-+ }
-+ }
-+ else if (GET_MODE_SIZE (inner_mode) == GET_MODE_SIZE (word_mode)
-+ && GET_MODE_SIZE (mode) == 2 * GET_MODE_SIZE (word_mode))
-+ {
-+ emit_move_insn (gen_highpart (word_mode, target),
-+ gen_lowpart (word_mode, XVECEXP (vals, 0, 0)));
-+ emit_move_insn (gen_lowpart (word_mode, target),
-+ gen_lowpart (word_mode, XVECEXP (vals, 0, 1)));
-+ return;
-+ }
-+
-+ if (all_same && GET_MODE_SIZE (mode) == 8)
-+ {
-+ if (TARGET_VIS2)
-+ {
-+ vector_init_bshuffle (target, XVECEXP (vals, 0, 0), mode, inner_mode);
-+ return;
-+ }
-+ if (mode == V8QImode)
-+ {
-+ vector_init_fpmerge (target, XVECEXP (vals, 0, 0));
-+ return;
-+ }
-+ if (mode == V4HImode)
-+ {
-+ vector_init_faligndata (target, XVECEXP (vals, 0, 0));
-+ return;
-+ }
-+ }
-+
-+ mem = assign_stack_temp (mode, GET_MODE_SIZE (mode));
-+ for (i = 0; i < n_elts; i++)
-+ emit_move_insn (adjust_address_nv (mem, inner_mode,
-+ i * GET_MODE_SIZE (inner_mode)),
-+ XVECEXP (vals, 0, i));
-+ emit_move_insn (target, mem);
-+}
-+
-+/* Implement TARGET_SECONDARY_RELOAD. */
-+
-+static reg_class_t
-+sparc_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
-+ machine_mode mode, secondary_reload_info *sri)
-+{
-+ enum reg_class rclass = (enum reg_class) rclass_i;
-+
-+ sri->icode = CODE_FOR_nothing;
-+ sri->extra_cost = 0;
-+
-+ /* We need a temporary when loading/storing a HImode/QImode value
-+ between memory and the FPU registers. This can happen when combine puts
-+ a paradoxical subreg in a float/fix conversion insn. */
-+ if (FP_REG_CLASS_P (rclass)
-+ && (mode == HImode || mode == QImode)
-+ && (GET_CODE (x) == MEM
-+ || ((GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
-+ && true_regnum (x) == -1)))
-+ return GENERAL_REGS;
-+
-+ /* On 32-bit we need a temporary when loading/storing a DFmode value
-+ between unaligned memory and the upper FPU registers. */
-+ if (TARGET_ARCH32
-+ && rclass == EXTRA_FP_REGS
-+ && mode == DFmode
-+ && GET_CODE (x) == MEM
-+ && ! mem_min_alignment (x, 8))
-+ return FP_REGS;
-+
-+ if (((TARGET_CM_MEDANY
-+ && symbolic_operand (x, mode))
-+ || (TARGET_CM_EMBMEDANY
-+ && text_segment_operand (x, mode)))
-+ && ! flag_pic)
-+ {
-+ if (in_p)
-+ sri->icode = direct_optab_handler (reload_in_optab, mode);
-+ else
-+ sri->icode = direct_optab_handler (reload_out_optab, mode);
-+ return NO_REGS;
-+ }
-+
-+ if (TARGET_VIS3 && TARGET_ARCH32)
-+ {
-+ int regno = true_regnum (x);
-+
-+ /* When using VIS3 fp<-->int register moves, on 32-bit we have
-+ to move 8-byte values in 4-byte pieces. This only works via
-+ FP_REGS, and not via EXTRA_FP_REGS. Therefore if we try to
-+ move between EXTRA_FP_REGS and GENERAL_REGS, we will need
-+ an FP_REGS intermediate move. */
-+ if ((rclass == EXTRA_FP_REGS && SPARC_INT_REG_P (regno))
-+ || ((general_or_i64_p (rclass)
-+ || rclass == GENERAL_OR_FP_REGS)
-+ && SPARC_FP_REG_P (regno)))
-+ {
-+ sri->extra_cost = 2;
-+ return FP_REGS;
-+ }
-+ }
-+
-+ return NO_REGS;
-+}
-+
-+/* Implement TARGET_SECONDARY_MEMORY_NEEDED.
-+
-+ On SPARC when not VIS3 it is not possible to directly move data
-+ between GENERAL_REGS and FP_REGS. */
-+
-+static bool
-+sparc_secondary_memory_needed (machine_mode mode, reg_class_t class1,
-+ reg_class_t class2)
-+{
-+ return ((FP_REG_CLASS_P (class1) != FP_REG_CLASS_P (class2))
-+ && (! TARGET_VIS3
-+ || GET_MODE_SIZE (mode) > 8
-+ || GET_MODE_SIZE (mode) < 4));
-+}
-+
-+/* Implement TARGET_SECONDARY_MEMORY_NEEDED_MODE.
-+
-+ get_secondary_mem widens its argument to BITS_PER_WORD which loses on v9
-+ because the movsi and movsf patterns don't handle r/f moves.
-+ For v8 we copy the default definition. */
-+
-+static machine_mode
-+sparc_secondary_memory_needed_mode (machine_mode mode)
-+{
-+ if (TARGET_ARCH64)
-+ {
-+ if (GET_MODE_BITSIZE (mode) < 32)
-+ return mode_for_size (32, GET_MODE_CLASS (mode), 0).require ();
-+ return mode;
-+ }
-+ else
-+ {
-+ if (GET_MODE_BITSIZE (mode) < BITS_PER_WORD)
-+ return mode_for_size (BITS_PER_WORD,
-+ GET_MODE_CLASS (mode), 0).require ();
-+ return mode;
-+ }
-+}
-+
-+/* Emit code to conditionally move either OPERANDS[2] or OPERANDS[3] into
-+ OPERANDS[0] in MODE. OPERANDS[1] is the operator of the condition. */
-+
-+bool
-+sparc_expand_conditional_move (machine_mode mode, rtx *operands)
-+{
-+ enum rtx_code rc = GET_CODE (operands[1]);
-+ machine_mode cmp_mode;
-+ rtx cc_reg, dst, cmp;
-+
-+ cmp = operands[1];
-+ if (GET_MODE (XEXP (cmp, 0)) == DImode && !TARGET_ARCH64)
-+ return false;
-+
-+ if (GET_MODE (XEXP (cmp, 0)) == TFmode && !TARGET_HARD_QUAD)
-+ cmp = sparc_emit_float_lib_cmp (XEXP (cmp, 0), XEXP (cmp, 1), rc);
-+
-+ cmp_mode = GET_MODE (XEXP (cmp, 0));
-+ rc = GET_CODE (cmp);
-+
-+ dst = operands[0];
-+ if (! rtx_equal_p (operands[2], dst)
-+ && ! rtx_equal_p (operands[3], dst))
-+ {
-+ if (reg_overlap_mentioned_p (dst, cmp))
-+ dst = gen_reg_rtx (mode);
-+
-+ emit_move_insn (dst, operands[3]);
-+ }
-+ else if (operands[2] == dst)
-+ {
-+ operands[2] = operands[3];
-+
-+ if (GET_MODE_CLASS (cmp_mode) == MODE_FLOAT)
-+ rc = reverse_condition_maybe_unordered (rc);
-+ else
-+ rc = reverse_condition (rc);
-+ }
-+
-+ if (XEXP (cmp, 1) == const0_rtx
-+ && GET_CODE (XEXP (cmp, 0)) == REG
-+ && cmp_mode == DImode
-+ && v9_regcmp_p (rc))
-+ cc_reg = XEXP (cmp, 0);
-+ else
-+ cc_reg = gen_compare_reg_1 (rc, XEXP (cmp, 0), XEXP (cmp, 1));
-+
-+ cmp = gen_rtx_fmt_ee (rc, GET_MODE (cc_reg), cc_reg, const0_rtx);
-+
-+ emit_insn (gen_rtx_SET (dst,
-+ gen_rtx_IF_THEN_ELSE (mode, cmp, operands[2], dst)));
-+
-+ if (dst != operands[0])
-+ emit_move_insn (operands[0], dst);
-+
-+ return true;
-+}
-+
-+/* Emit code to conditionally move a combination of OPERANDS[1] and OPERANDS[2]
-+ into OPERANDS[0] in MODE, depending on the outcome of the comparison of
-+ OPERANDS[4] and OPERANDS[5]. OPERANDS[3] is the operator of the condition.
-+ FCODE is the machine code to be used for OPERANDS[3] and CCODE the machine
-+ code to be used for the condition mask. */
-+
-+void
-+sparc_expand_vcond (machine_mode mode, rtx *operands, int ccode, int fcode)
-+{
-+ rtx mask, cop0, cop1, fcmp, cmask, bshuf, gsr;
-+ enum rtx_code code = GET_CODE (operands[3]);
-+
-+ mask = gen_reg_rtx (Pmode);
-+ cop0 = operands[4];
-+ cop1 = operands[5];
-+ if (code == LT || code == GE)
-+ {
-+ rtx t;
-+
-+ code = swap_condition (code);
-+ t = cop0; cop0 = cop1; cop1 = t;
-+ }
-+
-+ gsr = gen_rtx_REG (DImode, SPARC_GSR_REG);
-+
-+ fcmp = gen_rtx_UNSPEC (Pmode,
-+ gen_rtvec (1, gen_rtx_fmt_ee (code, mode, cop0, cop1)),
-+ fcode);
-+
-+ cmask = gen_rtx_UNSPEC (DImode,
-+ gen_rtvec (2, mask, gsr),
-+ ccode);
-+
-+ bshuf = gen_rtx_UNSPEC (mode,
-+ gen_rtvec (3, operands[1], operands[2], gsr),
-+ UNSPEC_BSHUFFLE);
-+
-+ emit_insn (gen_rtx_SET (mask, fcmp));
-+ emit_insn (gen_rtx_SET (gsr, cmask));
-+
-+ emit_insn (gen_rtx_SET (operands[0], bshuf));
-+}
-+
-+/* On sparc, any mode which naturally allocates into the float
-+ registers should return 4 here. */
-+
-+unsigned int
-+sparc_regmode_natural_size (machine_mode mode)
-+{
-+ int size = UNITS_PER_WORD;
-+
-+ if (TARGET_ARCH64)
-+ {
-+ enum mode_class mclass = GET_MODE_CLASS (mode);
-+
-+ if (mclass == MODE_FLOAT || mclass == MODE_VECTOR_INT)
-+ size = 4;
-+ }
-+
-+ return size;
-+}
-+
-+/* Implement TARGET_HARD_REGNO_NREGS.
-+
-+ On SPARC, ordinary registers hold 32 bits worth; this means both
-+ integer and floating point registers. On v9, integer regs hold 64
-+ bits worth; floating point regs hold 32 bits worth (this includes the
-+ new fp regs as even the odd ones are included in the hard register
-+ count). */
-+
-+static unsigned int
-+sparc_hard_regno_nregs (unsigned int regno, machine_mode mode)
-+{
-+ if (regno == SPARC_GSR_REG)
-+ return 1;
-+ if (TARGET_ARCH64)
-+ {
-+ if (SPARC_INT_REG_P (regno) || regno == FRAME_POINTER_REGNUM)
-+ return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
-+ return CEIL (GET_MODE_SIZE (mode), 4);
-+ }
-+ return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
-+}
-+
-+/* Implement TARGET_HARD_REGNO_MODE_OK.
-+
-+ ??? Because of the funny way we pass parameters we should allow certain
-+ ??? types of float/complex values to be in integer registers during
-+ ??? RTL generation. This only matters on arch32. */
-+
-+static bool
-+sparc_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
-+{
-+ return (hard_regno_mode_classes[regno] & sparc_mode_class[mode]) != 0;
-+}
-+
-+/* Implement TARGET_MODES_TIEABLE_P.
-+
-+ For V9 we have to deal with the fact that only the lower 32 floating
-+ point registers are 32-bit addressable. */
-+
-+static bool
-+sparc_modes_tieable_p (machine_mode mode1, machine_mode mode2)
-+{
-+ enum mode_class mclass1, mclass2;
-+ unsigned short size1, size2;
-+
-+ if (mode1 == mode2)
-+ return true;
-+
-+ mclass1 = GET_MODE_CLASS (mode1);
-+ mclass2 = GET_MODE_CLASS (mode2);
-+ if (mclass1 != mclass2)
-+ return false;
-+
-+ if (! TARGET_V9)
-+ return true;
-+
-+ /* Classes are the same and we are V9 so we have to deal with upper
-+ vs. lower floating point registers. If one of the modes is a
-+ 4-byte mode, and the other is not, we have to mark them as not
-+ tieable because only the lower 32 floating point register are
-+ addressable 32-bits at a time.
-+
-+ We can't just test explicitly for SFmode, otherwise we won't
-+ cover the vector mode cases properly. */
-+
-+ if (mclass1 != MODE_FLOAT && mclass1 != MODE_VECTOR_INT)
-+ return true;
-+
-+ size1 = GET_MODE_SIZE (mode1);
-+ size2 = GET_MODE_SIZE (mode2);
-+ if ((size1 > 4 && size2 == 4)
-+ || (size2 > 4 && size1 == 4))
-+ return false;
-+
-+ return true;
-+}
-+
-+/* Implement TARGET_CSTORE_MODE. */
-+
-+static scalar_int_mode
-+sparc_cstore_mode (enum insn_code icode ATTRIBUTE_UNUSED)
-+{
-+ return (TARGET_ARCH64 ? DImode : SImode);
-+}
-+
-+/* Return the compound expression made of T1 and T2. */
-+
-+static inline tree
-+compound_expr (tree t1, tree t2)
-+{
-+ return build2 (COMPOUND_EXPR, void_type_node, t1, t2);
-+}
-+
-+/* Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV hook. */
-+
-+static void
-+sparc_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
-+{
-+ if (!TARGET_FPU)
-+ return;
-+
-+ const unsigned HOST_WIDE_INT accrued_exception_mask = 0x1f << 5;
-+ const unsigned HOST_WIDE_INT trap_enable_mask = 0x1f << 23;
-+
-+ /* We generate the equivalent of feholdexcept (&fenv_var):
-+
-+ unsigned int fenv_var;
-+ __builtin_store_fsr (&fenv_var);
-+
-+ unsigned int tmp1_var;
-+ tmp1_var = fenv_var & ~(accrued_exception_mask | trap_enable_mask);
-+
-+ __builtin_load_fsr (&tmp1_var); */
-+
-+ tree fenv_var = create_tmp_var_raw (unsigned_type_node);
-+ TREE_ADDRESSABLE (fenv_var) = 1;
-+ tree fenv_addr = build_fold_addr_expr (fenv_var);
-+ tree stfsr = sparc_builtins[SPARC_BUILTIN_STFSR];
-+ tree hold_stfsr
-+ = build4 (TARGET_EXPR, unsigned_type_node, fenv_var,
-+ build_call_expr (stfsr, 1, fenv_addr), NULL_TREE, NULL_TREE);
-+
-+ tree tmp1_var = create_tmp_var_raw (unsigned_type_node);
-+ TREE_ADDRESSABLE (tmp1_var) = 1;
-+ tree masked_fenv_var
-+ = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_var,
-+ build_int_cst (unsigned_type_node,
-+ ~(accrued_exception_mask | trap_enable_mask)));
-+ tree hold_mask
-+ = build4 (TARGET_EXPR, unsigned_type_node, tmp1_var, masked_fenv_var,
-+ NULL_TREE, NULL_TREE);
-+
-+ tree tmp1_addr = build_fold_addr_expr (tmp1_var);
-+ tree ldfsr = sparc_builtins[SPARC_BUILTIN_LDFSR];
-+ tree hold_ldfsr = build_call_expr (ldfsr, 1, tmp1_addr);
-+
-+ *hold = compound_expr (compound_expr (hold_stfsr, hold_mask), hold_ldfsr);
-+
-+ /* We reload the value of tmp1_var to clear the exceptions:
-+
-+ __builtin_load_fsr (&tmp1_var); */
-+
-+ *clear = build_call_expr (ldfsr, 1, tmp1_addr);
-+
-+ /* We generate the equivalent of feupdateenv (&fenv_var):
-+
-+ unsigned int tmp2_var;
-+ __builtin_store_fsr (&tmp2_var);
-+
-+ __builtin_load_fsr (&fenv_var);
-+
-+ if (SPARC_LOW_FE_EXCEPT_VALUES)
-+ tmp2_var >>= 5;
-+ __atomic_feraiseexcept ((int) tmp2_var); */
-+
-+ tree tmp2_var = create_tmp_var_raw (unsigned_type_node);
-+ TREE_ADDRESSABLE (tmp2_var) = 1;
-+ tree tmp2_addr = build_fold_addr_expr (tmp2_var);
-+ tree update_stfsr
-+ = build4 (TARGET_EXPR, unsigned_type_node, tmp2_var,
-+ build_call_expr (stfsr, 1, tmp2_addr), NULL_TREE, NULL_TREE);
-+
-+ tree update_ldfsr = build_call_expr (ldfsr, 1, fenv_addr);
-+
-+ tree atomic_feraiseexcept
-+ = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
-+ tree update_call
-+ = build_call_expr (atomic_feraiseexcept, 1,
-+ fold_convert (integer_type_node, tmp2_var));
-+
-+ if (SPARC_LOW_FE_EXCEPT_VALUES)
-+ {
-+ tree shifted_tmp2_var
-+ = build2 (RSHIFT_EXPR, unsigned_type_node, tmp2_var,
-+ build_int_cst (unsigned_type_node, 5));
-+ tree update_shift
-+ = build2 (MODIFY_EXPR, void_type_node, tmp2_var, shifted_tmp2_var);
-+ update_call = compound_expr (update_shift, update_call);
-+ }
-+
-+ *update
-+ = compound_expr (compound_expr (update_stfsr, update_ldfsr), update_call);
-+}
-+
-+/* Implement TARGET_CAN_CHANGE_MODE_CLASS. Borrowed from the PA port.
-+
-+ SImode loads to floating-point registers are not zero-extended.
-+ The definition for LOAD_EXTEND_OP specifies that integer loads
-+ narrower than BITS_PER_WORD will be zero-extended. As a result,
-+ we inhibit changes from SImode unless they are to a mode that is
-+ identical in size.
-+
-+ Likewise for SFmode, since word-mode paradoxical subregs are
-+ problematic on big-endian architectures. */
-+
-+static bool
-+sparc_can_change_mode_class (machine_mode from, machine_mode to,
-+ reg_class_t rclass)
-+{
-+ if (TARGET_ARCH64
-+ && GET_MODE_SIZE (from) == 4
-+ && GET_MODE_SIZE (to) != 4)
-+ return !reg_classes_intersect_p (rclass, FP_REGS);
-+ return true;
-+}
-+
-+/* Implement TARGET_CONSTANT_ALIGNMENT. */
-+
-+static HOST_WIDE_INT
-+sparc_constant_alignment (const_tree exp, HOST_WIDE_INT align)
-+{
-+ if (TREE_CODE (exp) == STRING_CST)
-+ return MAX (align, FASTEST_ALIGNMENT);
-+ return align;
-+}
-+
-+#include "gt-sparc.h"
-diff -Nur gcc-10.3.0.orig/gcc/config/sparc/sparc.md gcc-10.3.0/gcc/config/sparc/sparc.md
---- gcc-10.3.0.orig/gcc/config/sparc/sparc.md 2021-04-08 13:56:28.205742322 +0200
-+++ gcc-10.3.0/gcc/config/sparc/sparc.md 2021-04-09 07:51:37.936504607 +0200
-@@ -1601,7 +1601,10 @@
- (clobber (reg:P O7_REG))]
- "REGNO (operands[0]) == INTVAL (operands[3])"
- {
-- return output_load_pcrel_sym (operands);
-+ if (flag_delayed_branch)
-+ return "sethi\t%%hi(%a1-4), %0\n\tcall\t%a2\n\t add\t%0, %%lo(%a1+4), %0";
-+ else
-+ return "sethi\t%%hi(%a1-8), %0\n\tadd\t%0, %%lo(%a1-4), %0\n\tcall\t%a2\n\t nop";
- }
- [(set (attr "type") (const_string "multi"))
- (set (attr "length")
-diff -Nur gcc-10.3.0.orig/gcc/config/sparc/sparc.md.orig gcc-10.3.0/gcc/config/sparc/sparc.md.orig
---- gcc-10.3.0.orig/gcc/config/sparc/sparc.md.orig 1970-01-01 01:00:00.000000000 +0100
-+++ gcc-10.3.0/gcc/config/sparc/sparc.md.orig 2021-04-08 13:56:28.205742322 +0200
-@@ -0,0 +1,9524 @@
-+;; Machine description for SPARC.
-+;; Copyright (C) 1987-2020 Free Software Foundation, Inc.
-+;; Contributed by Michael Tiemann (tiemann@cygnus.com)
-+;; 64-bit SPARC-V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
-+;; at Cygnus Support.
-+
-+;; This file is part of 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 3, 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 COPYING3. If not see
-+;; <http://www.gnu.org/licenses/>.
-+
-+(define_c_enum "unspec" [
-+ UNSPEC_MOVE_PIC
-+ UNSPEC_UPDATE_RETURN
-+ UNSPEC_LOAD_PCREL_SYM
-+ UNSPEC_FRAME_BLOCKAGE
-+ UNSPEC_MOVE_PIC_LABEL
-+ UNSPEC_SETH44
-+ UNSPEC_SETM44
-+ UNSPEC_SETHH
-+ UNSPEC_SETLM
-+ UNSPEC_EMB_HISUM
-+ UNSPEC_EMB_TEXTUHI
-+ UNSPEC_EMB_TEXTHI
-+ UNSPEC_EMB_TEXTULO
-+ UNSPEC_EMB_SETHM
-+ UNSPEC_MOVE_GOTDATA
-+
-+ UNSPEC_MEMBAR
-+ UNSPEC_ATOMIC
-+
-+ UNSPEC_TLSGD
-+ UNSPEC_TLSLDM
-+ UNSPEC_TLSLDO
-+ UNSPEC_TLSIE
-+ UNSPEC_TLSLE
-+ UNSPEC_TLSLD_BASE
-+
-+ UNSPEC_FPACK16
-+ UNSPEC_FPACK32
-+ UNSPEC_FPACKFIX
-+ UNSPEC_FEXPAND
-+ UNSPEC_MUL16AU
-+ UNSPEC_MUL16AL
-+ UNSPEC_MUL8UL
-+ UNSPEC_MULDUL
-+ UNSPEC_ALIGNDATA
-+ UNSPEC_FCMP
-+ UNSPEC_PDIST
-+ UNSPEC_EDGE8
-+ UNSPEC_EDGE8L
-+ UNSPEC_EDGE16
-+ UNSPEC_EDGE16L
-+ UNSPEC_EDGE32
-+ UNSPEC_EDGE32L
-+ UNSPEC_ARRAY8
-+ UNSPEC_ARRAY16
-+ UNSPEC_ARRAY32
-+
-+ UNSPEC_SP_SET
-+ UNSPEC_SP_TEST
-+
-+ UNSPEC_EDGE8N
-+ UNSPEC_EDGE8LN
-+ UNSPEC_EDGE16N
-+ UNSPEC_EDGE16LN
-+ UNSPEC_EDGE32N
-+ UNSPEC_EDGE32LN
-+ UNSPEC_BSHUFFLE
-+ UNSPEC_CMASK8
-+ UNSPEC_CMASK16
-+ UNSPEC_CMASK32
-+ UNSPEC_FCHKSM16
-+ UNSPEC_PDISTN
-+ UNSPEC_FUCMP
-+ UNSPEC_FHADD
-+ UNSPEC_FHSUB
-+ UNSPEC_XMUL
-+ UNSPEC_MUL8
-+ UNSPEC_MUL8SU
-+ UNSPEC_MULDSU
-+
-+ UNSPEC_ADDV
-+ UNSPEC_SUBV
-+ UNSPEC_NEGV
-+
-+ UNSPEC_DICTUNPACK
-+ UNSPEC_FPCMPSHL
-+ UNSPEC_FPUCMPSHL
-+ UNSPEC_FPCMPDESHL
-+ UNSPEC_FPCMPURSHL
-+])
-+
-+(define_c_enum "unspecv" [
-+ UNSPECV_BLOCKAGE
-+
-+ UNSPECV_SPECULATION_BARRIER
-+
-+ UNSPECV_PROBE_STACK_RANGE
-+
-+ UNSPECV_FLUSHW
-+ UNSPECV_SAVEW
-+
-+ UNSPECV_FLUSH
-+
-+ UNSPECV_LDSTUB
-+ UNSPECV_SWAP
-+ UNSPECV_CAS
-+
-+ UNSPECV_LDFSR
-+ UNSPECV_STFSR
-+])
-+
-+(define_constants
-+ [(G0_REG 0)
-+ (G1_REG 1)
-+ (G2_REG 2)
-+ (G3_REG 3)
-+ (G4_REG 4)
-+ (G5_REG 5)
-+ (G6_REG 6)
-+ (G7_REG 7)
-+ (O0_REG 8)
-+ (O1_REG 9)
-+ (O2_REG 10)
-+ (O3_REG 11)
-+ (O4_REG 12)
-+ (O5_REG 13)
-+ (O6_REG 14)
-+ (O7_REG 15)
-+ (L0_REG 16)
-+ (L1_REG 17)
-+ (L2_REG 18)
-+ (L3_REG 19)
-+ (L4_REG 20)
-+ (L5_REG 21)
-+ (L6_REG 22)
-+ (L7_REG 23)
-+ (I0_REG 24)
-+ (I1_REG 25)
-+ (I2_REG 26)
-+ (I3_REG 27)
-+ (I4_REG 28)
-+ (I5_REG 29)
-+ (I6_REG 30)
-+ (I7_REG 31)
-+ (F0_REG 32)
-+ (F1_REG 33)
-+ (F2_REG 34)
-+ (F3_REG 35)
-+ (F4_REG 36)
-+ (F5_REG 37)
-+ (F6_REG 38)
-+ (F7_REG 39)
-+ (F8_REG 40)
-+ (F9_REG 41)
-+ (F10_REG 42)
-+ (F11_REG 43)
-+ (F12_REG 44)
-+ (F13_REG 45)
-+ (F14_REG 46)
-+ (F15_REG 47)
-+ (F16_REG 48)
-+ (F17_REG 49)
-+ (F18_REG 50)
-+ (F19_REG 51)
-+ (F20_REG 52)
-+ (F21_REG 53)
-+ (F22_REG 54)
-+ (F23_REG 55)
-+ (F24_REG 56)
-+ (F25_REG 57)
-+ (F26_REG 58)
-+ (F27_REG 59)
-+ (F28_REG 60)
-+ (F29_REG 61)
-+ (F30_REG 62)
-+ (F31_REG 63)
-+ (F32_REG 64)
-+ (F34_REG 66)
-+ (F36_REG 68)
-+ (F38_REG 70)
-+ (F40_REG 72)
-+ (F42_REG 74)
-+ (F44_REG 76)
-+ (F46_REG 78)
-+ (F48_REG 80)
-+ (F50_REG 82)
-+ (F52_REG 84)
-+ (F54_REG 86)
-+ (F56_REG 88)
-+ (F58_REG 90)
-+ (F60_REG 92)
-+ (F62_REG 94)
-+ (FCC0_REG 96)
-+ (FCC1_REG 97)
-+ (FCC2_REG 98)
-+ (FCC3_REG 99)
-+ (CC_REG 100)
-+ (SFP_REG 101)
-+ (GSR_REG 102)
-+ ])
-+
-+(define_mode_iterator I [QI HI SI DI])
-+(define_mode_iterator P [(SI "TARGET_ARCH32") (DI "TARGET_ARCH64")])
-+(define_mode_iterator W [SI (DI "TARGET_ARCH64")])
-+(define_mode_iterator F [SF DF TF])
-+
-+;; The upper 32 fp regs on the v9 can't hold SFmode values. To deal with this
-+;; a second register class, EXTRA_FP_REGS, exists for the v9 chip. The name
-+;; is a bit of a misnomer as it covers all 64 fp regs. The corresponding
-+;; constraint letter is 'e'. To avoid any confusion, 'e' is used instead of
-+;; 'f' for all DF/TFmode values, including those that are specific to the v8.
-+
-+;; Attribute for cpu type.
-+;; These must match the values of enum sparc_processor_type in sparc-opts.h.
-+(define_attr "cpu"
-+ "v7,
-+ cypress,
-+ v8,
-+ supersparc,
-+ hypersparc,
-+ leon,
-+ leon3,
-+ leon3v7,
-+ sparclite,
-+ f930,
-+ f934,
-+ sparclite86x,
-+ sparclet,
-+ tsc701,
-+ v9,
-+ ultrasparc,
-+ ultrasparc3,
-+ niagara,
-+ niagara2,
-+ niagara3,
-+ niagara4,
-+ niagara7,
-+ m8"
-+ (const (symbol_ref "sparc_cpu_attr")))
-+
-+;; Attribute for the instruction set.
-+;; At present we only need to distinguish v9/!v9, but for clarity we
-+;; test TARGET_V8 too.
-+(define_attr "isa" "v7,v8,v9,sparclet"
-+ (const
-+ (cond [(symbol_ref "TARGET_V9") (const_string "v9")
-+ (symbol_ref "TARGET_V8") (const_string "v8")
-+ (symbol_ref "TARGET_SPARCLET") (const_string "sparclet")]
-+ (const_string "v7"))))
-+
-+(define_attr "cpu_feature" "none,fpu,fpunotv9,v9,vis,vis3,vis4,vis4b"
-+ (const_string "none"))
-+
-+(define_attr "lra" "disabled,enabled"
-+ (const_string "enabled"))
-+
-+(define_attr "enabled" ""
-+ (cond [(eq_attr "cpu_feature" "none")
-+ (cond [(eq_attr "lra" "disabled") (symbol_ref "!TARGET_LRA")] (const_int 1))
-+ (eq_attr "cpu_feature" "fpu") (symbol_ref "TARGET_FPU")
-+ (eq_attr "cpu_feature" "fpunotv9") (symbol_ref "TARGET_FPU && !TARGET_V9")
-+ (eq_attr "cpu_feature" "v9") (symbol_ref "TARGET_V9")
-+ (eq_attr "cpu_feature" "vis") (symbol_ref "TARGET_VIS")
-+ (eq_attr "cpu_feature" "vis3") (symbol_ref "TARGET_VIS3")
-+ (eq_attr "cpu_feature" "vis4") (symbol_ref "TARGET_VIS4")
-+ (eq_attr "cpu_feature" "vis4b") (symbol_ref "TARGET_VIS4B")]
-+ (const_int 0)))
-+
-+;; The SPARC instructions used by the backend are organized into a
-+;; hierarchy using the insn attributes "type" and "subtype".
-+;;
-+;; The mnemonics used in the list below are the architectural names
-+;; used in the Oracle SPARC Architecture specs. A / character
-+;; separates the type from the subtype where appropriate. For
-+;; brevity, text enclosed in {} denotes alternatives, while text
-+;; enclosed in [] is optional.
-+;;
-+;; Please keep this list updated. It is of great help for keeping the
-+;; correctness and coherence of the DFA schedulers.
-+;;
-+;; ialu: <empty>
-+;; ialuX: ADD[X]C SUB[X]C
-+;; shift: SLL[X] SRL[X] SRA[X]
-+;; cmove: MOV{A,N,NE,E,G,LE,GE,L,GU,LEU,CC,CS,POS,NEG,VC,VS}
-+;; MOVF{A,N,U,G,UG,L,UL,LG,NE,E,UE,GE,UGE,LE,ULE,O}
-+;; MOVR{Z,LEZ,LZ,NZ,GZ,GEZ}
-+;; compare: ADDcc ADDCcc ANDcc ORcc SUBcc SUBCcc XORcc XNORcc
-+;; imul: MULX SMUL[cc] UMUL UMULXHI XMULX XMULXHI
-+;; idiv: UDIVX SDIVX
-+;; flush: FLUSH
-+;; load/regular: LD{UB,UH,UW} LDFSR
-+;; load/prefetch: PREFETCH
-+;; fpload: LDF LDDF LDQF
-+;; sload: LD{SB,SH,SW}
-+;; store: ST{B,H,W,X} STFSR
-+;; fpstore: STF STDF STQF
-+;; cbcond: CWB{NE,E,G,LE,GE,L,GU,LEU,CC,CS,POS,NEG,VC,VS}
-+;; CXB{NE,E,G,LE,GE,L,GU,LEU,CC,CS,POS,NEG,VC,VS}
-+;; uncond_branch: BA BPA JMPL
-+;; branch: B{NE,E,G,LE,GE,L,GU,LEU,CC,CS,POS,NEG,VC,VS}
-+;; BP{NE,E,G,LE,GE,L,GU,LEU,CC,CS,POS,NEG,VC,VS}
-+;; FB{U,G,UG,L,UL,LG,NE,BE,UE,GE,UGE,LE,ULE,O}
-+;; call: CALL
-+;; return: RESTORE RETURN
-+;; fpmove: FABS{s,d,q} FMOV{s,d,q} FNEG{s,d,q}
-+;; fpcmove: FMOV{S,D,Q}{icc,xcc,fcc}
-+;; fpcrmove: FMOVR{s,d,q}{Z,LEZ,LZ,NZ,GZ,GEZ}
-+;; fp: FADD{s,d,q} FSUB{s,d,q} FHSUB{s,d} FNHADD{s,d} FNADD{s,d}
-+;; FiTO{s,d,q} FsTO{i,x,d,q} FdTO{i,x,s,q} FxTO{d,s,q} FqTO{i,x,s,d}
-+;; fpcmp: FCMP{s,d,q} FCMPE{s,d,q}
-+;; fpmul: FMADD{s,d} FMSUB{s,d} FMUL{s,d,q} FNMADD{s,d}
-+;; FNMSUB{s,d} FNMUL{s,d} FNsMULd FsMULd
-+;; FdMULq
-+;; array: ARRAY{8,16,32}
-+;; bmask: BMASK
-+;; edge: EDGE{8,16,32}[L]cc
-+;; edgen: EDGE{8,16,32}[L]n
-+;; fpdivs: FDIV{s,q}
-+;; fpsqrts: FSQRT{s,q}
-+;; fpdivd: FDIVd
-+;; fpsqrtd: FSQRTd
-+;; lzd: LZCNT
-+;; fga/addsub64: FP{ADD,SUB}64
-+;; fga/fpu: FCHKSM16 FEXPANd FMEAN16 FPMERGE
-+;; FS{LL,RA,RL}{16,32}
-+;; fga/maxmin: FP{MAX,MIN}[U]{8,16,32}
-+;; fga/cmask: CMASK{8,16,32}
-+;; fga/other: BSHUFFLE FALIGNDATAg FP{ADD,SUB}[S]{8,16,32}
-+;; FP{ADD,SUB}US{8,16} DICTUNPACK
-+;; gsr/reg: RDGSR WRGSR
-+;; gsr/alignaddr: ALIGNADDRESS[_LITTLE]
-+;; vismv/double: FSRC2d
-+;; vismv/single: MOVwTOs FSRC2s
-+;; vismv/movstouw: MOVsTOuw
-+;; vismv/movxtod: MOVxTOd
-+;; vismv/movdtox: MOVdTOx
-+;; visl/single: F{AND,NAND,NOR,OR,NOT1}s
-+;; F{AND,OR}NOT{1,2}s
-+;; FONEs F{ZERO,XNOR,XOR}s FNOT2s
-+;; visl/double: FONEd FZEROd FNOT1d F{OR,AND,XOR}d F{NOR,NAND,XNOR}d
-+;; F{OR,AND}NOT1d F{OR,AND}NOT2d
-+;; viscmp: FPCMP{LE,GT,NE,EQ}{8,16,32} FPCMPU{LE,GT,NE,EQ}{8,16,32}
-+;; FPCMP{LE,GT,EQ,NE}{8,16,32}SHL FPCMPU{LE,GT,EQ,NE}{8,16,32}SHL
-+;; FPCMPDE{8,16,32}SHL FPCMPUR{8,16,32}SHL
-+;; fgm_pack: FPACKFIX FPACK{8,16,32}
-+;; fgm_mul: FMUL8SUx16 FMUL8ULx16 FMUL8x16 FMUL8x16AL
-+;; FMUL8x16AU FMULD8SUx16 FMULD8ULx16
-+;; pdist: PDIST
-+;; pdistn: PDISTN
-+
-+(define_attr "type"
-+ "ialu,compare,shift,
-+ load,sload,store,
-+ uncond_branch,branch,call,sibcall,call_no_delay_slot,return,
-+ cbcond,uncond_cbcond,
-+ imul,idiv,
-+ fpload,fpstore,
-+ fp,fpmove,
-+ fpcmove,fpcrmove,
-+ fpcmp,
-+ fpmul,fpdivs,fpdivd,
-+ fpsqrts,fpsqrtd,
-+ fga,visl,vismv,viscmp,
-+ fgm_pack,fgm_mul,pdist,pdistn,edge,edgen,gsr,array,bmask,
-+ cmove,
-+ ialuX,
-+ multi,savew,flushw,iflush,trap,lzd"
-+ (const_string "ialu"))
-+
-+(define_attr "subtype"
-+ "single,double,movstouw,movxtod,movdtox,
-+ addsub64,cmask,fpu,maxmin,other,
-+ reg,alignaddr,
-+ prefetch,regular"
-+ (const_string "single"))
-+
-+;; True if branch/call has empty delay slot and will emit a nop in it
-+(define_attr "empty_delay_slot" "false,true"
-+ (symbol_ref "(empty_delay_slot (insn)
-+ ? EMPTY_DELAY_SLOT_TRUE : EMPTY_DELAY_SLOT_FALSE)"))
-+
-+;; True if we are making use of compare-and-branch instructions.
-+;; True if we should emit a nop after a cbcond instruction
-+(define_attr "emit_cbcond_nop" "false,true"
-+ (symbol_ref "(emit_cbcond_nop (insn)
-+ ? EMIT_CBCOND_NOP_TRUE : EMIT_CBCOND_NOP_FALSE)"))
-+
-+(define_attr "branch_type" "none,icc,fcc,reg"
-+ (const_string "none"))
-+
-+(define_attr "pic" "false,true"
-+ (symbol_ref "(flag_pic != 0
-+ ? PIC_TRUE : PIC_FALSE)"))
-+
-+(define_attr "calls_alloca" "false,true"
-+ (symbol_ref "(cfun->calls_alloca != 0
-+ ? CALLS_ALLOCA_TRUE : CALLS_ALLOCA_FALSE)"))
-+
-+(define_attr "calls_eh_return" "false,true"
-+ (symbol_ref "(crtl->calls_eh_return != 0
-+ ? CALLS_EH_RETURN_TRUE : CALLS_EH_RETURN_FALSE)"))
-+
-+(define_attr "leaf_function" "false,true"
-+ (symbol_ref "(crtl->uses_only_leaf_regs != 0
-+ ? LEAF_FUNCTION_TRUE : LEAF_FUNCTION_FALSE)"))
-+
-+(define_attr "delayed_branch" "false,true"
-+ (symbol_ref "(flag_delayed_branch != 0
-+ ? DELAYED_BRANCH_TRUE : DELAYED_BRANCH_FALSE)"))
-+
-+(define_attr "flat" "false,true"
-+ (symbol_ref "(TARGET_FLAT != 0
-+ ? FLAT_TRUE : FLAT_FALSE)"))
-+
-+(define_attr "fix_ut699" "false,true"
-+ (symbol_ref "(sparc_fix_ut699 != 0
-+ ? FIX_UT699_TRUE : FIX_UT699_FALSE)"))
-+
-+(define_attr "fix_b2bst" "false,true"
-+ (symbol_ref "(sparc_fix_b2bst != 0
-+ ? FIX_B2BST_TRUE : FIX_B2BST_FALSE)"))
-+
-+(define_attr "fix_lost_divsqrt" "false,true"
-+ (symbol_ref "(sparc_fix_lost_divsqrt != 0
-+ ? FIX_LOST_DIVSQRT_TRUE : FIX_LOST_DIVSQRT_FALSE)"))
-+
-+(define_attr "fix_gr712rc" "false,true"
-+ (symbol_ref "(sparc_fix_gr712rc != 0
-+ ? FIX_GR712RC_TRUE : FIX_GR712RC_FALSE)"))
-+
-+;; Length (in # of insns).
-+;; Beware that setting a length greater or equal to 3 for conditional branches
-+;; has a side-effect (see output_cbranch and output_v9branch).
-+(define_attr "length" ""
-+ (cond [(eq_attr "type" "uncond_branch,call")
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (const_int 2)
-+ (const_int 1))
-+ (eq_attr "type" "sibcall")
-+ (if_then_else (ior (eq_attr "leaf_function" "true")
-+ (eq_attr "flat" "true"))
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (const_int 3)
-+ (const_int 2))
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (const_int 2)
-+ (const_int 1)))
-+ (eq_attr "branch_type" "icc")
-+ (if_then_else (match_operand 0 "v9_comparison_operator" "")
-+ (if_then_else (lt (pc) (match_dup 1))
-+ (if_then_else (lt (minus (match_dup 1) (pc)) (const_int 260000))
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (const_int 2)
-+ (const_int 1))
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (const_int 4)
-+ (const_int 3)))
-+ (if_then_else (lt (minus (pc) (match_dup 1)) (const_int 260000))
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (const_int 2)
-+ (const_int 1))
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (const_int 4)
-+ (const_int 3))))
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (const_int 2)
-+ (const_int 1)))
-+ (eq_attr "branch_type" "fcc")
-+ (if_then_else (match_operand 0 "fcc0_register_operand" "")
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (if_then_else (not (match_test "TARGET_V9"))
-+ (const_int 3)
-+ (const_int 2))
-+ (if_then_else (not (match_test "TARGET_V9"))
-+ (const_int 2)
-+ (const_int 1)))
-+ (if_then_else (lt (pc) (match_dup 2))
-+ (if_then_else (lt (minus (match_dup 2) (pc)) (const_int 260000))
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (const_int 2)
-+ (const_int 1))
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (const_int 4)
-+ (const_int 3)))
-+ (if_then_else (lt (minus (pc) (match_dup 2)) (const_int 260000))
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (const_int 2)
-+ (const_int 1))
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (const_int 4)
-+ (const_int 3)))))
-+ (eq_attr "branch_type" "reg")
-+ (if_then_else (lt (pc) (match_dup 2))
-+ (if_then_else (lt (minus (match_dup 2) (pc)) (const_int 32000))
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (const_int 2)
-+ (const_int 1))
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (const_int 4)
-+ (const_int 3)))
-+ (if_then_else (lt (minus (pc) (match_dup 2)) (const_int 32000))
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (const_int 2)
-+ (const_int 1))
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (const_int 4)
-+ (const_int 3))))
-+ (eq_attr "type" "cbcond")
-+ (if_then_else (lt (pc) (match_dup 3))
-+ (if_then_else (lt (minus (match_dup 3) (pc)) (const_int 500))
-+ (if_then_else (eq_attr "emit_cbcond_nop" "true")
-+ (const_int 2)
-+ (const_int 1))
-+ (const_int 4))
-+ (if_then_else (lt (minus (pc) (match_dup 3)) (const_int 500))
-+ (if_then_else (eq_attr "emit_cbcond_nop" "true")
-+ (const_int 2)
-+ (const_int 1))
-+ (const_int 4)))
-+ (eq_attr "type" "uncond_cbcond")
-+ (if_then_else (lt (pc) (match_dup 0))
-+ (if_then_else (lt (minus (match_dup 0) (pc)) (const_int 500))
-+ (if_then_else (eq_attr "emit_cbcond_nop" "true")
-+ (const_int 2)
-+ (const_int 1))
-+ (const_int 1))
-+ (if_then_else (lt (minus (pc) (match_dup 0)) (const_int 500))
-+ (if_then_else (eq_attr "emit_cbcond_nop" "true")
-+ (const_int 2)
-+ (const_int 1))
-+ (const_int 1)))
-+ ] (const_int 1)))
-+
-+;; FP precision.
-+(define_attr "fptype" "single,double"
-+ (const_string "single"))
-+
-+;; FP precision specific to the UT699.
-+(define_attr "fptype_ut699" "none,single"
-+ (const_string "none"))
-+
-+;; UltraSPARC-III integer load type.
-+(define_attr "us3load_type" "2cycle,3cycle"
-+ (const_string "2cycle"))
-+
-+(define_asm_attributes
-+ [(set_attr "length" "2")
-+ (set_attr "type" "multi")])
-+
-+;; Attributes for branch scheduling
-+(define_attr "tls_delay_slot" "false,true"
-+ (symbol_ref "((TARGET_GNU_TLS && HAVE_GNU_LD) != 0
-+ ? TLS_DELAY_SLOT_TRUE : TLS_DELAY_SLOT_FALSE)"))
-+
-+(define_attr "in_sibcall_delay" "false,true"
-+ (symbol_ref "(eligible_for_sibcall_delay (insn)
-+ ? IN_SIBCALL_DELAY_TRUE : IN_SIBCALL_DELAY_FALSE)"))
-+
-+(define_attr "in_return_delay" "false,true"
-+ (symbol_ref "(eligible_for_return_delay (insn)
-+ ? IN_RETURN_DELAY_TRUE : IN_RETURN_DELAY_FALSE)"))
-+
-+;; ??? !v9: Should implement the notion of predelay slots for floating-point
-+;; branches. This would allow us to remove the nop always inserted before
-+;; a floating point branch.
-+
-+;; ??? It is OK for fill_simple_delay_slots to put load/store instructions
-+;; in a delay slot, but it is not OK for fill_eager_delay_slots to do so.
-+;; This is because doing so will add several pipeline stalls to the path
-+;; that the load/store did not come from. Unfortunately, there is no way
-+;; to prevent fill_eager_delay_slots from using load/store without completely
-+;; disabling them. For the SPEC benchmark set, this is a serious lose,
-+;; because it prevents us from moving back the final store of inner loops.
-+
-+(define_attr "in_branch_delay" "false,true"
-+ (cond [(eq_attr "type" "uncond_branch,branch,cbcond,uncond_cbcond,call,sibcall,call_no_delay_slot,multi")
-+ (const_string "false")
-+ (and (eq_attr "fix_lost_divsqrt" "true")
-+ (eq_attr "type" "fpdivs,fpsqrts,fpdivd,fpsqrtd"))
-+ (const_string "false")
-+ (and (eq_attr "fix_b2bst" "true") (eq_attr "type" "store,fpstore"))
-+ (const_string "false")
-+ (and (eq_attr "fix_ut699" "true") (eq_attr "type" "load,sload"))
-+ (const_string "false")
-+ (and (eq_attr "fix_ut699" "true")
-+ (and (eq_attr "type" "fpload,fp,fpmove,fpmul,fpdivs,fpsqrts")
-+ (ior (eq_attr "fptype" "single")
-+ (eq_attr "fptype_ut699" "single"))))
-+ (const_string "false")
-+ (eq_attr "length" "1")
-+ (const_string "true")
-+ ] (const_string "false")))
-+
-+(define_attr "in_integer_branch_annul_delay" "false,true"
-+ (cond [(and (eq_attr "fix_gr712rc" "true")
-+ (eq_attr "type" "fp,fpcmp,fpmove,fpcmove,fpmul,
-+ fpdivs,fpsqrts,fpdivd,fpsqrtd"))
-+ (const_string "false")
-+ (eq_attr "in_branch_delay" "true")
-+ (const_string "true")
-+ ] (const_string "false")))
-+
-+(define_delay (eq_attr "type" "sibcall")
-+ [(eq_attr "in_sibcall_delay" "true") (nil) (nil)])
-+
-+(define_delay (eq_attr "type" "return")
-+ [(eq_attr "in_return_delay" "true") (nil) (nil)])
-+
-+(define_delay (ior (eq_attr "type" "call") (eq_attr "type" "uncond_branch"))
-+ [(eq_attr "in_branch_delay" "true") (nil) (nil)])
-+
-+(define_delay (and (eq_attr "type" "branch") (not (eq_attr "branch_type" "icc")))
-+ [(eq_attr "in_branch_delay" "true")
-+ (nil)
-+ (eq_attr "in_branch_delay" "true")])
-+
-+(define_delay (and (eq_attr "type" "branch") (eq_attr "branch_type" "icc"))
-+ [(eq_attr "in_branch_delay" "true")
-+ (nil)
-+ (eq_attr "in_integer_branch_annul_delay" "true")])
-+
-+;; Include SPARC DFA schedulers
-+
-+(include "cypress.md")
-+(include "supersparc.md")
-+(include "hypersparc.md")
-+(include "leon.md")
-+(include "sparclet.md")
-+(include "ultra1_2.md")
-+(include "ultra3.md")
-+(include "niagara.md")
-+(include "niagara2.md")
-+(include "niagara4.md")
-+(include "niagara7.md")
-+(include "m8.md")
-+
-+
-+;; Operand and operator predicates and constraints
-+
-+(include "predicates.md")
-+(include "constraints.md")
-+
-+
-+;; Compare instructions.
-+
-+;; These are just the DEFINE_INSNs to match the patterns and the
-+;; DEFINE_SPLITs for some of the scc insns that actually require
-+;; more than one machine instruction. DEFINE_EXPANDs are further down.
-+
-+(define_insn "*cmpsi_insn"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (match_operand:SI 0 "register_operand" "r")
-+ (match_operand:SI 1 "arith_operand" "rI")))]
-+ ""
-+ "cmp\t%0, %1"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmpdi_sp64"
-+ [(set (reg:CCX CC_REG)
-+ (compare:CCX (match_operand:DI 0 "register_operand" "r")
-+ (match_operand:DI 1 "arith_operand" "rI")))]
-+ "TARGET_ARCH64"
-+ "cmp\t%0, %1"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmpsi_sne"
-+ [(set (reg:CCC CC_REG)
-+ (compare:CCC (not:SI (match_operand:SI 0 "arith_operand" "rI"))
-+ (const_int -1)))]
-+ ""
-+ "cmp\t%%g0, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmpdi_sne"
-+ [(set (reg:CCXC CC_REG)
-+ (compare:CCXC (not:DI (match_operand:DI 0 "arith_operand" "rI"))
-+ (const_int -1)))]
-+ "TARGET_ARCH64"
-+ "cmp\t%%g0, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmpsf_fpe"
-+ [(set (match_operand:CCFPE 0 "fcc_register_operand" "=c")
-+ (compare:CCFPE (match_operand:SF 1 "register_operand" "f")
-+ (match_operand:SF 2 "register_operand" "f")))]
-+ "TARGET_FPU"
-+{
-+ if (TARGET_V9)
-+ return "fcmpes\t%0, %1, %2";
-+ return "fcmpes\t%1, %2";
-+}
-+ [(set_attr "type" "fpcmp")])
-+
-+(define_insn "*cmpdf_fpe"
-+ [(set (match_operand:CCFPE 0 "fcc_register_operand" "=c")
-+ (compare:CCFPE (match_operand:DF 1 "register_operand" "e")
-+ (match_operand:DF 2 "register_operand" "e")))]
-+ "TARGET_FPU"
-+{
-+ if (TARGET_V9)
-+ return "fcmped\t%0, %1, %2";
-+ return "fcmped\t%1, %2";
-+}
-+ [(set_attr "type" "fpcmp")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "*cmptf_fpe"
-+ [(set (match_operand:CCFPE 0 "fcc_register_operand" "=c")
-+ (compare:CCFPE (match_operand:TF 1 "register_operand" "e")
-+ (match_operand:TF 2 "register_operand" "e")))]
-+ "TARGET_FPU && TARGET_HARD_QUAD"
-+{
-+ if (TARGET_V9)
-+ return "fcmpeq\t%0, %1, %2";
-+ return "fcmpeq\t%1, %2";
-+}
-+ [(set_attr "type" "fpcmp")])
-+
-+(define_insn "*cmpsf_fp"
-+ [(set (match_operand:CCFP 0 "fcc_register_operand" "=c")
-+ (compare:CCFP (match_operand:SF 1 "register_operand" "f")
-+ (match_operand:SF 2 "register_operand" "f")))]
-+ "TARGET_FPU"
-+{
-+ if (TARGET_V9)
-+ return "fcmps\t%0, %1, %2";
-+ return "fcmps\t%1, %2";
-+}
-+ [(set_attr "type" "fpcmp")])
-+
-+(define_insn "*cmpdf_fp"
-+ [(set (match_operand:CCFP 0 "fcc_register_operand" "=c")
-+ (compare:CCFP (match_operand:DF 1 "register_operand" "e")
-+ (match_operand:DF 2 "register_operand" "e")))]
-+ "TARGET_FPU"
-+{
-+ if (TARGET_V9)
-+ return "fcmpd\t%0, %1, %2";
-+ return "fcmpd\t%1, %2";
-+}
-+ [(set_attr "type" "fpcmp")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "*cmptf_fp"
-+ [(set (match_operand:CCFP 0 "fcc_register_operand" "=c")
-+ (compare:CCFP (match_operand:TF 1 "register_operand" "e")
-+ (match_operand:TF 2 "register_operand" "e")))]
-+ "TARGET_FPU && TARGET_HARD_QUAD"
-+{
-+ if (TARGET_V9)
-+ return "fcmpq\t%0, %1, %2";
-+ return "fcmpq\t%1, %2";
-+}
-+ [(set_attr "type" "fpcmp")])
-+
-+;; Next come the scc insns.
-+
-+;; Note that the boolean result (operand 0) takes on DImode
-+;; (not SImode) when TARGET_ARCH64.
-+
-+(define_expand "cstoresi4"
-+ [(use (match_operator 1 "comparison_operator"
-+ [(match_operand:SI 2 "compare_operand" "")
-+ (match_operand:SI 3 "arith_operand" "")]))
-+ (clobber (match_operand:SI 0 "cstore_result_operand"))]
-+ ""
-+{
-+ if (GET_CODE (operands[2]) == ZERO_EXTRACT && operands[3] != const0_rtx)
-+ operands[2] = force_reg (SImode, operands[2]);
-+ if (emit_scc_insn (operands)) DONE; else FAIL;
-+})
-+
-+(define_expand "cstoredi4"
-+ [(use (match_operator 1 "comparison_operator"
-+ [(match_operand:DI 2 "compare_operand" "")
-+ (match_operand:DI 3 "arith_operand" "")]))
-+ (clobber (match_operand:SI 0 "cstore_result_operand"))]
-+ "TARGET_ARCH64"
-+{
-+ if (GET_CODE (operands[2]) == ZERO_EXTRACT && operands[3] != const0_rtx)
-+ operands[2] = force_reg (DImode, operands[2]);
-+ if (emit_scc_insn (operands)) DONE; else FAIL;
-+})
-+
-+(define_expand "cstore<F:mode>4"
-+ [(use (match_operator 1 "comparison_operator"
-+ [(match_operand:F 2 "register_operand" "")
-+ (match_operand:F 3 "register_operand" "")]))
-+ (clobber (match_operand:SI 0 "cstore_result_operand"))]
-+ "TARGET_FPU"
-+{
-+ if (emit_scc_insn (operands)) DONE; else FAIL;
-+})
-+
-+;; The SNE and SEQ patterns are special because they can be done
-+;; without any branching and do not involve a COMPARE.
-+
-+(define_insn_and_split "*snesi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (ne:W (match_operand:SI 1 "register_operand" "r")
-+ (const_int 0)))
-+ (clobber (reg:CC CC_REG))]
-+ ""
-+ "#"
-+ ""
-+ [(set (reg:CCC CC_REG) (compare:CCC (not:SI (match_dup 1)) (const_int -1)))
-+ (set (match_dup 0) (ltu:W (reg:CCC CC_REG) (const_int 0)))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*neg_snesi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (neg:W (ne:W (match_operand:SI 1 "register_operand" "r")
-+ (const_int 0))))
-+ (clobber (reg:CC CC_REG))]
-+ ""
-+ "#"
-+ ""
-+ [(set (reg:CCC CC_REG) (compare:CCC (not:SI (match_dup 1)) (const_int -1)))
-+ (set (match_dup 0) (neg:W (ltu:W (reg:CCC CC_REG) (const_int 0))))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*snedi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=&r")
-+ (ne:W (match_operand:DI 1 "register_operand" "r")
-+ (const_int 0)))]
-+ "TARGET_ARCH64 && !TARGET_VIS3"
-+ "#"
-+ "&& !reg_overlap_mentioned_p (operands[1], operands[0])"
-+ [(set (match_dup 0) (const_int 0))
-+ (set (match_dup 0) (if_then_else:W (ne:DI (match_dup 1) (const_int 0))
-+ (const_int 1)
-+ (match_dup 0)))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*snedi<W:mode>_zero_vis3"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (ne:W (match_operand:DI 1 "register_operand" "r")
-+ (const_int 0)))
-+ (clobber (reg:CCX CC_REG))]
-+ "TARGET_ARCH64 && TARGET_VIS3"
-+ "#"
-+ ""
-+ [(set (reg:CCXC CC_REG) (compare:CCXC (not:DI (match_dup 1)) (const_int -1)))
-+ (set (match_dup 0) (ltu:W (reg:CCXC CC_REG) (const_int 0)))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*neg_snedi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=&r")
-+ (neg:W (ne:W (match_operand:DI 1 "register_operand" "r")
-+ (const_int 0))))]
-+ "TARGET_ARCH64 && !TARGET_SUBXC"
-+ "#"
-+ "&& !reg_overlap_mentioned_p (operands[1], operands[0])"
-+ [(set (match_dup 0) (const_int 0))
-+ (set (match_dup 0) (if_then_else:W (ne:DI (match_dup 1) (const_int 0))
-+ (const_int -1)
-+ (match_dup 0)))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*neg_snedi<W:mode>_zero_subxc"
-+ [(set (match_operand:W 0 "register_operand" "=&r")
-+ (neg:W (ne:W (match_operand:DI 1 "register_operand" "r")
-+ (const_int 0))))
-+ (clobber (reg:CCX CC_REG))]
-+ "TARGET_ARCH64 && TARGET_SUBXC"
-+ "#"
-+ ""
-+ [(set (reg:CCXC CC_REG) (compare:CCXC (not:DI (match_dup 1)) (const_int -1)))
-+ (set (match_dup 0) (neg:W (ltu:W (reg:CCXC CC_REG) (const_int 0))))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*seqsi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (eq:W (match_operand:SI 1 "register_operand" "r")
-+ (const_int 0)))
-+ (clobber (reg:CC CC_REG))]
-+ ""
-+ "#"
-+ ""
-+ [(set (reg:CCC CC_REG) (compare:CCC (not:SI (match_dup 1)) (const_int -1)))
-+ (set (match_dup 0) (geu:W (reg:CCC CC_REG) (const_int 0)))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*neg_seqsi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (neg:W (eq:W (match_operand:SI 1 "register_operand" "r")
-+ (const_int 0))))
-+ (clobber (reg:CC CC_REG))]
-+ ""
-+ "#"
-+ ""
-+ [(set (reg:CCC CC_REG) (compare:CCC (not:SI (match_dup 1)) (const_int -1)))
-+ (set (match_dup 0) (neg:W (geu:W (reg:CCC CC_REG) (const_int 0))))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*seqdi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=&r")
-+ (eq:W (match_operand:DI 1 "register_operand" "r")
-+ (const_int 0)))]
-+ "TARGET_ARCH64"
-+ "#"
-+ "&& !reg_overlap_mentioned_p (operands[1], operands[0])"
-+ [(set (match_dup 0) (const_int 0))
-+ (set (match_dup 0) (if_then_else:W (eq:DI (match_dup 1) (const_int 0))
-+ (const_int 1)
-+ (match_dup 0)))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*neg_seqdi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=&r")
-+ (neg:W (eq:W (match_operand:DI 1 "register_operand" "r")
-+ (const_int 0))))]
-+ "TARGET_ARCH64"
-+ "#"
-+ "&& !reg_overlap_mentioned_p (operands[1], operands[0])"
-+ [(set (match_dup 0) (const_int 0))
-+ (set (match_dup 0) (if_then_else:W (eq:DI (match_dup 1) (const_int 0))
-+ (const_int -1)
-+ (match_dup 0)))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+;; We can also do (x + (i == 0)) and related, so put them in.
-+
-+(define_insn_and_split "*plus_snesi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (plus:W (ne:W (match_operand:SI 1 "register_operand" "r")
-+ (const_int 0))
-+ (match_operand:W 2 "register_operand" "r")))
-+ (clobber (reg:CC CC_REG))]
-+ ""
-+ "#"
-+ ""
-+ [(set (reg:CCC CC_REG) (compare:CCC (not:SI (match_dup 1)) (const_int -1)))
-+ (set (match_dup 0) (plus:W (ltu:W (reg:CCC CC_REG) (const_int 0))
-+ (match_dup 2)))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*plus_plus_snesi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (plus:W (plus:W (ne:W (match_operand:SI 1 "register_operand" "r")
-+ (const_int 0))
-+ (match_operand:W 2 "register_operand" "r"))
-+ (match_operand:W 3 "register_operand" "r")))
-+ (clobber (reg:CC CC_REG))]
-+ ""
-+ "#"
-+ ""
-+ [(set (reg:CCC CC_REG) (compare:CCC (not:SI (match_dup 1)) (const_int -1)))
-+ (set (match_dup 0) (plus:W (plus:W (ltu:W (reg:CCC CC_REG) (const_int 0))
-+ (match_dup 2))
-+ (match_dup 3)))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*plus_snedi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (plus:W (ne:W (match_operand:DI 1 "register_operand" "r")
-+ (const_int 0))
-+ (match_operand:W 2 "register_operand" "r")))
-+ (clobber (reg:CCX CC_REG))]
-+ "TARGET_ARCH64 && TARGET_VIS3"
-+ "#"
-+ ""
-+ [(set (reg:CCXC CC_REG) (compare:CCXC (not:DI (match_dup 1)) (const_int -1)))
-+ (set (match_dup 0) (plus:W (ltu:W (reg:CCXC CC_REG) (const_int 0))
-+ (match_dup 2)))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*plus_plus_snedi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (plus:W (plus:W (ne:W (match_operand:DI 1 "register_operand" "r")
-+ (const_int 0))
-+ (match_operand:W 2 "register_operand" "r"))
-+ (match_operand:W 3 "register_operand" "r")))
-+ (clobber (reg:CCX CC_REG))]
-+ "TARGET_ARCH64 && TARGET_VIS3"
-+ "#"
-+ ""
-+ [(set (reg:CCXC CC_REG) (compare:CCXC (not:DI (match_dup 1)) (const_int -1)))
-+ (set (match_dup 0) (plus:W (plus:W (ltu:W (reg:CCXC CC_REG) (const_int 0))
-+ (match_dup 2))
-+ (match_dup 3)))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*minus_snesi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (minus:W (match_operand:W 2 "register_operand" "r")
-+ (ne:W (match_operand:SI 1 "register_operand" "r")
-+ (const_int 0))))
-+ (clobber (reg:CC CC_REG))]
-+ ""
-+ "#"
-+ ""
-+ [(set (reg:CCC CC_REG) (compare:CCC (not:SI (match_dup 1)) (const_int -1)))
-+ (set (match_dup 0) (minus:W (match_dup 2)
-+ (ltu:W (reg:CCC CC_REG) (const_int 0))))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*minus_minus_snesi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (minus:W (minus:W (match_operand:W 2 "register_operand" "r")
-+ (ne:W (match_operand:SI 1 "register_operand" "r")
-+ (const_int 0)))
-+ (match_operand:W 3 "register_operand" "r")))
-+ (clobber (reg:CC CC_REG))]
-+ ""
-+ "#"
-+ ""
-+ [(set (reg:CCC CC_REG) (compare:CCC (not:SI (match_dup 1)) (const_int -1)))
-+ (set (match_dup 0) (minus:W (minus:W (match_dup 2)
-+ (ltu:W (reg:CCC CC_REG) (const_int 0)))
-+ (match_dup 3)))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*minus_snedi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (minus:W (match_operand:W 2 "register_operand" "r")
-+ (ne:W (match_operand:DI 1 "register_operand" "r")
-+ (const_int 0))))
-+ (clobber (reg:CCX CC_REG))]
-+ "TARGET_ARCH64 && TARGET_SUBXC"
-+ "#"
-+ ""
-+ [(set (reg:CCXC CC_REG) (compare:CCXC (not:DI (match_dup 1)) (const_int -1)))
-+ (set (match_dup 0) (minus:W (match_dup 2)
-+ (ltu:W (reg:CCXC CC_REG) (const_int 0))))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*minus_minus_snedi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (minus:W (minus:W (match_operand:W 2 "register_operand" "r")
-+ (ne:W (match_operand:DI 1 "register_operand" "r")
-+ (const_int 0)))
-+ (match_operand:W 3 "register_operand" "r")))
-+ (clobber (reg:CCX CC_REG))]
-+ "TARGET_ARCH64 && TARGET_SUBXC"
-+ "#"
-+ ""
-+ [(set (reg:CCXC CC_REG) (compare:CCXC (not:DI (match_dup 1)) (const_int -1)))
-+ (set (match_dup 0) (minus:W (minus:W (match_dup 2)
-+ (ltu:W (reg:CCXC CC_REG) (const_int 0)))
-+ (match_dup 3)))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*plus_seqsi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (plus:W (eq:W (match_operand:SI 1 "register_operand" "r")
-+ (const_int 0))
-+ (match_operand:W 2 "register_operand" "r")))
-+ (clobber (reg:CC CC_REG))]
-+ ""
-+ "#"
-+ ""
-+ [(set (reg:CCC CC_REG) (compare:CCC (not:SI (match_dup 1)) (const_int -1)))
-+ (set (match_dup 0) (plus:W (geu:W (reg:CCC CC_REG) (const_int 0))
-+ (match_dup 2)))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*minus_seqsi<W:mode>_zero"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (minus:W (match_operand:W 2 "register_operand" "r")
-+ (eq:W (match_operand:SI 1 "register_operand" "r")
-+ (const_int 0))))
-+ (clobber (reg:CC CC_REG))]
-+ ""
-+ "#"
-+ ""
-+ [(set (reg:CCC CC_REG) (compare:CCC (not:SI (match_dup 1)) (const_int -1)))
-+ (set (match_dup 0) (minus:W (match_dup 2)
-+ (geu:W (reg:CCC CC_REG) (const_int 0))))]
-+ ""
-+ [(set_attr "length" "2")])
-+
-+;; We can also do GEU and LTU directly, but these operate after a compare.
-+
-+(define_insn "*sltu<W:mode>_insn"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (ltu:W (match_operand 1 "icc_register_operand" "X") (const_int 0)))]
-+ "GET_MODE (operands[1]) == CCmode || GET_MODE (operands[1]) == CCCmode"
-+ "addx\t%%g0, 0, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*plus_sltu<W:mode>"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (plus:W (ltu:W (match_operand 2 "icc_register_operand" "X")
-+ (const_int 0))
-+ (match_operand:W 1 "arith_operand" "rI")))]
-+ "GET_MODE (operands[2]) == CCmode || GET_MODE (operands[2]) == CCCmode"
-+ "addx\t%%g0, %1, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*plus_plus_sltu<W:mode>"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (plus:W (plus:W (ltu:W (match_operand 3 "icc_register_operand" "X")
-+ (const_int 0))
-+ (match_operand:W 1 "register_operand" "%r"))
-+ (match_operand:W 2 "arith_operand" "rI")))]
-+ "GET_MODE (operands[3]) == CCmode || GET_MODE (operands[3]) == CCCmode"
-+ "addx\t%1, %2, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*neg_sgeu<W:mode>"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (neg:W (geu:W (match_operand 1 "icc_register_operand" "X")
-+ (const_int 0))))]
-+ "GET_MODE (operands[1]) == CCmode || GET_MODE (operands[1]) == CCCmode"
-+ "addx\t%%g0, -1, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*neg_sgeusidi"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (sign_extend:DI (neg:SI (geu:SI (match_operand 1 "icc_register_operand" "X")
-+ (const_int 0)))))]
-+ "TARGET_ARCH64
-+ && (GET_MODE (operands[1]) == CCmode || GET_MODE (operands[1]) == CCCmode)"
-+ "addx\t%%g0, -1, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*minus_sgeu<W:mode>"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (minus:W (match_operand:W 1 "register_operand" "r")
-+ (geu:W (match_operand 2 "icc_register_operand" "X")
-+ (const_int 0))))]
-+ "GET_MODE (operands[2]) == CCmode || GET_MODE (operands[2]) == CCCmode"
-+ "addx\t%1, -1, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*addx<W:mode>"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (plus:W (plus:W (match_operand:W 1 "register_operand" "%r")
-+ (match_operand:W 2 "arith_operand" "rI"))
-+ (ltu:W (match_operand 3 "icc_register_operand" "X")
-+ (const_int 0))))]
-+ "GET_MODE (operands[3]) == CCmode || GET_MODE (operands[3]) == CCCmode"
-+ "addx\t%1, %2, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*sltu<W:mode>_insn_vis3"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (ltu:W (match_operand 1 "icc_register_operand" "X") (const_int 0)))]
-+ "TARGET_ARCH64 && TARGET_VIS3
-+ && (GET_MODE (operands[1]) == CCXmode || GET_MODE (operands[1]) == CCXCmode)"
-+ "addxc\t%%g0, %%g0, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*plus_sltu<W:mode>_vis3"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (plus:W (ltu:W (match_operand 2 "icc_register_operand" "X")
-+ (const_int 0))
-+ (match_operand:W 1 "register_operand" "r")))]
-+ "TARGET_ARCH64 && TARGET_VIS3
-+ && (GET_MODE (operands[2]) == CCXmode || GET_MODE (operands[2]) == CCXCmode)"
-+ "addxc\t%%g0, %1, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*plus_plus_sltu<W:mode>_vis3"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (plus:W (plus:W (ltu:W (match_operand 3 "icc_register_operand" "X")
-+ (const_int 0))
-+ (match_operand:W 1 "register_operand" "%r"))
-+ (match_operand:W 2 "register_operand" "r")))]
-+ "TARGET_ARCH64 && TARGET_VIS3
-+ && (GET_MODE (operands[3]) == CCXmode || GET_MODE (operands[3]) == CCXCmode)"
-+ "addxc\t%1, %2, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*addxc<W:mode>"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (plus:W (plus:W (match_operand:W 1 "register_operand" "%r")
-+ (match_operand:W 2 "register_operand" "r"))
-+ (ltu:W (match_operand 3 "icc_register_operand" "X")
-+ (const_int 0))))]
-+ "TARGET_ARCH64 && TARGET_VIS3
-+ && (GET_MODE (operands[3]) == CCXmode || GET_MODE (operands[3]) == CCXCmode)"
-+ "addxc\t%1, %2, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*neg_sltu<W:mode>"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (neg:W (ltu:W (match_operand 1 "icc_register_operand" "X")
-+ (const_int 0))))]
-+ "GET_MODE (operands[1]) == CCmode || GET_MODE (operands[1]) == CCCmode"
-+ "subx\t%%g0, 0, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*neg_sltusidi"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (sign_extend:DI (neg:SI (ltu:SI (match_operand 1 "icc_register_operand" "X")
-+ (const_int 0)))))]
-+ "TARGET_ARCH64
-+ && (GET_MODE (operands[1]) == CCmode || GET_MODE (operands[1]) == CCCmode)"
-+ "subx\t%%g0, 0, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*minus_neg_sltu<W:mode>"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (minus:W (neg:W (ltu:W (match_operand 2 "icc_register_operand" "X")
-+ (const_int 0)))
-+ (match_operand:W 1 "arith_operand" "rI")))]
-+ "GET_MODE (operands[2]) == CCmode || GET_MODE (operands[2]) == CCCmode"
-+ "subx\t%%g0, %1, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*neg_plus_sltu<W:mode>"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (neg:W (plus:W (ltu:W (match_operand 2 "icc_register_operand" "X")
-+ (const_int 0))
-+ (match_operand:W 1 "arith_operand" "rI"))))]
-+ "GET_MODE (operands[2]) == CCmode || GET_MODE (operands[2]) == CCCmode"
-+ "subx\t%%g0, %1, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*minus_sltu<W:mode>"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (minus:W (match_operand:W 1 "register_operand" "r")
-+ (ltu:W (match_operand 2 "icc_register_operand" "X")
-+ (const_int 0))))]
-+ "GET_MODE (operands[2]) == CCmode || GET_MODE (operands[2]) == CCCmode"
-+ "subx\t%1, 0, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*minus_minus_sltu<W:mode>"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (minus:W (minus:W (match_operand:W 1 "register_or_zero_operand" "rJ")
-+ (ltu:W (match_operand 3 "icc_register_operand" "X")
-+ (const_int 0)))
-+ (match_operand:W 2 "arith_operand" "rI")))]
-+ "GET_MODE (operands[3]) == CCmode || GET_MODE (operands[3]) == CCCmode"
-+ "subx\t%r1, %2, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*sgeu<W:mode>_insn"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (geu:W (match_operand 1 "icc_register_operand" "X") (const_int 0)))]
-+ "GET_MODE (operands[1]) == CCmode || GET_MODE (operands[1]) == CCCmode"
-+ "subx\t%%g0, -1, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*plus_sgeu<W:mode>"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (plus:W (geu:W (match_operand 2 "icc_register_operand" "X")
-+ (const_int 0))
-+ (match_operand:W 1 "register_operand" "r")))]
-+ "GET_MODE (operands[2]) == CCmode || GET_MODE (operands[2]) == CCCmode"
-+ "subx\t%1, -1, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*subx<W:mode>"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (minus:W (minus:W (match_operand:W 1 "register_or_zero_operand" "rJ")
-+ (match_operand:W 2 "arith_operand" "rI"))
-+ (ltu:W (match_operand 3 "icc_register_operand" "X")
-+ (const_int 0))))]
-+ "GET_MODE (operands[3]) == CCmode || GET_MODE (operands[3]) == CCCmode"
-+ "subx\t%r1, %2, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*neg_sltu<W:mode>_subxc"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (neg:W (ltu:W (match_operand 1 "icc_register_operand" "X")
-+ (const_int 0))))]
-+ "TARGET_ARCH64 && TARGET_SUBXC
-+ && (GET_MODE (operands[1]) == CCXmode || GET_MODE (operands[1]) == CCXCmode)"
-+ "subxc\t%%g0, %%g0, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*minus_neg_sltu<W:mode>_subxc"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (minus:W (neg:W (ltu:W (match_operand 2 "icc_register_operand" "X")
-+ (const_int 0)))
-+ (match_operand:W 1 "register_operand" "r")))]
-+ "TARGET_ARCH64 && TARGET_SUBXC
-+ && (GET_MODE (operands[2]) == CCXmode || GET_MODE (operands[2]) == CCXCmode)"
-+ "subxc\t%%g0, %1, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*neg_plus_sltu<W:mode>_subxc"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (neg:W (plus:W (ltu:W (match_operand 2 "icc_register_operand" "X")
-+ (const_int 0))
-+ (match_operand:W 1 "register_operand" "r"))))]
-+ "TARGET_ARCH64 && TARGET_SUBXC
-+ && (GET_MODE (operands[2]) == CCXmode || GET_MODE (operands[2]) == CCXCmode)"
-+ "subxc\t%%g0, %1, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*minus_sltu<W:mode>_subxc"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (minus:W (match_operand:W 1 "register_operand" "r")
-+ (ltu:W (match_operand 2 "icc_register_operand" "X")
-+ (const_int 0))))]
-+ "TARGET_ARCH64 && TARGET_SUBXC
-+ && (GET_MODE (operands[2]) == CCXmode || GET_MODE (operands[2]) == CCXCmode)"
-+ "subxc\t%1, %%g0, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*minus_minus_sltu<W:mode>_subxc"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (minus:W (minus:W (match_operand:W 1 "register_or_zero_operand" "rJ")
-+ (ltu:W (match_operand 3 "icc_register_operand" "X")
-+ (const_int 0)))
-+ (match_operand:W 2 "register_operand" "r")))]
-+ "TARGET_ARCH64 && TARGET_SUBXC
-+ && (GET_MODE (operands[3]) == CCXmode || GET_MODE (operands[3]) == CCXCmode)"
-+ "subxc\t%r1, %2, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_insn "*subxc<W:mode>"
-+ [(set (match_operand:W 0 "register_operand" "=r")
-+ (minus:W (minus:W (match_operand:W 1 "register_or_zero_operand" "rJ")
-+ (match_operand:W 2 "register_operand" "r"))
-+ (ltu:W (match_operand 3 "icc_register_operand" "X")
-+ (const_int 0))))]
-+ "TARGET_ARCH64 && TARGET_SUBXC
-+ && (GET_MODE (operands[3]) == CCXmode || GET_MODE (operands[3]) == CCXCmode)"
-+ "subxc\t%r1, %2, %0"
-+ [(set_attr "type" "ialuX")])
-+
-+(define_split
-+ [(set (match_operand:W 0 "register_operand" "")
-+ (match_operator:W 1 "icc_comparison_operator"
-+ [(match_operand 2 "icc_register_operand" "") (const_int 0)]))]
-+ "TARGET_V9
-+ /* 64-bit LTU is better implemented using addxc with VIS3. */
-+ && !(GET_CODE (operands[1]) == LTU
-+ && (GET_MODE (operands[2]) == CCXmode
-+ || GET_MODE (operands[2]) == CCXCmode)
-+ && TARGET_VIS3)
-+ /* 32-bit LTU/GEU are better implemented using addx/subx. */
-+ && !((GET_CODE (operands[1]) == LTU || GET_CODE (operands[1]) == GEU)
-+ && (GET_MODE (operands[2]) == CCmode
-+ || GET_MODE (operands[2]) == CCCmode))"
-+ [(set (match_dup 0) (const_int 0))
-+ (set (match_dup 0)
-+ (if_then_else:SI (match_op_dup:W 1 [(match_dup 2) (const_int 0)])
-+ (const_int 1)
-+ (match_dup 0)))]
-+ "")
-+
-+;; These control RTL generation for conditional jump insns
-+
-+(define_expand "cbranchcc4"
-+ [(set (pc)
-+ (if_then_else (match_operator 0 "comparison_operator"
-+ [(match_operand 1 "compare_operand" "")
-+ (match_operand 2 "const_zero_operand" "")])
-+ (label_ref (match_operand 3 "" ""))
-+ (pc)))]
-+ ""
-+ "")
-+
-+(define_expand "cbranchsi4"
-+ [(use (match_operator 0 "comparison_operator"
-+ [(match_operand:SI 1 "compare_operand" "")
-+ (match_operand:SI 2 "arith_operand" "")]))
-+ (use (match_operand 3 ""))]
-+ ""
-+{
-+ if (GET_CODE (operands[1]) == ZERO_EXTRACT && operands[2] != const0_rtx)
-+ operands[1] = force_reg (SImode, operands[1]);
-+ emit_conditional_branch_insn (operands);
-+ DONE;
-+})
-+
-+(define_expand "cbranchdi4"
-+ [(use (match_operator 0 "comparison_operator"
-+ [(match_operand:DI 1 "compare_operand" "")
-+ (match_operand:DI 2 "arith_operand" "")]))
-+ (use (match_operand 3 ""))]
-+ "TARGET_ARCH64"
-+{
-+ if (GET_CODE (operands[1]) == ZERO_EXTRACT && operands[2] != const0_rtx)
-+ operands[1] = force_reg (DImode, operands[1]);
-+ emit_conditional_branch_insn (operands);
-+ DONE;
-+})
-+
-+(define_expand "cbranch<F:mode>4"
-+ [(use (match_operator 0 "comparison_operator"
-+ [(match_operand:F 1 "register_operand" "")
-+ (match_operand:F 2 "register_operand" "")]))
-+ (use (match_operand 3 ""))]
-+ "TARGET_FPU"
-+{
-+ emit_conditional_branch_insn (operands);
-+ DONE;
-+})
-+
-+
-+;; Now match both normal and inverted jump.
-+
-+;; XXX fpcmp nop braindamage
-+(define_insn "*normal_branch"
-+ [(set (pc)
-+ (if_then_else (match_operator 0 "icc_comparison_operator"
-+ [(reg CC_REG) (const_int 0)])
-+ (label_ref (match_operand 1 "" ""))
-+ (pc)))]
-+ ""
-+{
-+ return output_cbranch (operands[0], operands[1], 1, 0,
-+ final_sequence && INSN_ANNULLED_BRANCH_P (insn),
-+ insn);
-+}
-+ [(set_attr "type" "branch")
-+ (set_attr "branch_type" "icc")])
-+
-+;; XXX fpcmp nop braindamage
-+(define_insn "*inverted_branch"
-+ [(set (pc)
-+ (if_then_else (match_operator 0 "icc_comparison_operator"
-+ [(reg CC_REG) (const_int 0)])
-+ (pc)
-+ (label_ref (match_operand 1 "" ""))))]
-+ ""
-+{
-+ return output_cbranch (operands[0], operands[1], 1, 1,
-+ final_sequence && INSN_ANNULLED_BRANCH_P (insn),
-+ insn);
-+}
-+ [(set_attr "type" "branch")
-+ (set_attr "branch_type" "icc")])
-+
-+;; XXX fpcmp nop braindamage
-+(define_insn "*normal_fp_branch"
-+ [(set (pc)
-+ (if_then_else (match_operator 1 "comparison_operator"
-+ [(match_operand:CCFP 0 "fcc_register_operand" "c")
-+ (const_int 0)])
-+ (label_ref (match_operand 2 "" ""))
-+ (pc)))]
-+ ""
-+{
-+ return output_cbranch (operands[1], operands[2], 2, 0,
-+ final_sequence && INSN_ANNULLED_BRANCH_P (insn),
-+ insn);
-+}
-+ [(set_attr "type" "branch")
-+ (set_attr "branch_type" "fcc")])
-+
-+;; XXX fpcmp nop braindamage
-+(define_insn "*inverted_fp_branch"
-+ [(set (pc)
-+ (if_then_else (match_operator 1 "comparison_operator"
-+ [(match_operand:CCFP 0 "fcc_register_operand" "c")
-+ (const_int 0)])
-+ (pc)
-+ (label_ref (match_operand 2 "" ""))))]
-+ ""
-+{
-+ return output_cbranch (operands[1], operands[2], 2, 1,
-+ final_sequence && INSN_ANNULLED_BRANCH_P (insn),
-+ insn);
-+}
-+ [(set_attr "type" "branch")
-+ (set_attr "branch_type" "fcc")])
-+
-+;; XXX fpcmp nop braindamage
-+(define_insn "*normal_fpe_branch"
-+ [(set (pc)
-+ (if_then_else (match_operator 1 "comparison_operator"
-+ [(match_operand:CCFPE 0 "fcc_register_operand" "c")
-+ (const_int 0)])
-+ (label_ref (match_operand 2 "" ""))
-+ (pc)))]
-+ ""
-+{
-+ return output_cbranch (operands[1], operands[2], 2, 0,
-+ final_sequence && INSN_ANNULLED_BRANCH_P (insn),
-+ insn);
-+}
-+ [(set_attr "type" "branch")
-+ (set_attr "branch_type" "fcc")])
-+
-+;; XXX fpcmp nop braindamage
-+(define_insn "*inverted_fpe_branch"
-+ [(set (pc)
-+ (if_then_else (match_operator 1 "comparison_operator"
-+ [(match_operand:CCFPE 0 "fcc_register_operand" "c")
-+ (const_int 0)])
-+ (pc)
-+ (label_ref (match_operand 2 "" ""))))]
-+ ""
-+{
-+ return output_cbranch (operands[1], operands[2], 2, 1,
-+ final_sequence && INSN_ANNULLED_BRANCH_P (insn),
-+ insn);
-+}
-+ [(set_attr "type" "branch")
-+ (set_attr "branch_type" "fcc")])
-+
-+;; SPARC V9-specific jump insns. None of these are guaranteed to be
-+;; in the architecture.
-+
-+(define_insn "*cbcond_sp32"
-+ [(set (pc)
-+ (if_then_else (match_operator 0 "comparison_operator"
-+ [(match_operand:SI 1 "register_operand" "r")
-+ (match_operand:SI 2 "arith5_operand" "rA")])
-+ (label_ref (match_operand 3 "" ""))
-+ (pc)))]
-+ "TARGET_CBCOND"
-+{
-+ return output_cbcond (operands[0], operands[3], insn);
-+}
-+ [(set_attr "type" "cbcond")])
-+
-+(define_insn "*cbcond_sp64"
-+ [(set (pc)
-+ (if_then_else (match_operator 0 "comparison_operator"
-+ [(match_operand:DI 1 "register_operand" "r")
-+ (match_operand:DI 2 "arith5_operand" "rA")])
-+ (label_ref (match_operand 3 "" ""))
-+ (pc)))]
-+ "TARGET_ARCH64 && TARGET_CBCOND"
-+{
-+ return output_cbcond (operands[0], operands[3], insn);
-+}
-+ [(set_attr "type" "cbcond")])
-+
-+;; There are no 32-bit brreg insns.
-+
-+(define_insn "*normal_int_branch_sp64"
-+ [(set (pc)
-+ (if_then_else (match_operator 0 "v9_register_comparison_operator"
-+ [(match_operand:DI 1 "register_operand" "r")
-+ (const_int 0)])
-+ (label_ref (match_operand 2 "" ""))
-+ (pc)))]
-+ "TARGET_ARCH64"
-+{
-+ return output_v9branch (operands[0], operands[2], 1, 2, 0,
-+ final_sequence && INSN_ANNULLED_BRANCH_P (insn),
-+ insn);
-+}
-+ [(set_attr "type" "branch")
-+ (set_attr "branch_type" "reg")])
-+
-+(define_insn "*inverted_int_branch_sp64"
-+ [(set (pc)
-+ (if_then_else (match_operator 0 "v9_register_comparison_operator"
-+ [(match_operand:DI 1 "register_operand" "r")
-+ (const_int 0)])
-+ (pc)
-+ (label_ref (match_operand 2 "" ""))))]
-+ "TARGET_ARCH64"
-+{
-+ return output_v9branch (operands[0], operands[2], 1, 2, 1,
-+ final_sequence && INSN_ANNULLED_BRANCH_P (insn),
-+ insn);
-+}
-+ [(set_attr "type" "branch")
-+ (set_attr "branch_type" "reg")])
-+
-+
-+;; Load in operand 0 the (absolute) address of operand 1, which is a symbolic
-+;; value subject to a PC-relative relocation. Operand 2 is a helper function
-+;; that adds the PC value at the call point to register #(operand 3).
-+;;
-+;; Even on V9 we use this call sequence with a stub, instead of "rd %pc, ..."
-+;; because the RDPC instruction is extremely expensive and incurs a complete
-+;; instruction pipeline flush.
-+
-+(define_insn "load_pcrel_sym<P:mode>"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_operand:P 1 "symbolic_operand" "")
-+ (match_operand:P 2 "call_address_operand" "")
-+ (match_operand:P 3 "const_int_operand" "")]
-+ UNSPEC_LOAD_PCREL_SYM))
-+ (clobber (reg:P O7_REG))]
-+ "REGNO (operands[0]) == INTVAL (operands[3])"
-+{
-+ return output_load_pcrel_sym (operands);
-+}
-+ [(set (attr "type") (const_string "multi"))
-+ (set (attr "length")
-+ (if_then_else (eq_attr "delayed_branch" "true")
-+ (const_int 3)
-+ (const_int 4)))])
-+
-+
-+;; Integer move instructions
-+
-+(define_expand "movqi"
-+ [(set (match_operand:QI 0 "nonimmediate_operand" "")
-+ (match_operand:QI 1 "general_operand" ""))]
-+ ""
-+{
-+ if (sparc_expand_move (QImode, operands))
-+ DONE;
-+})
-+
-+(define_insn "*movqi_insn"
-+ [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m")
-+ (match_operand:QI 1 "input_operand" "rI,m,rJ"))]
-+ "(register_operand (operands[0], QImode)
-+ || register_or_zero_operand (operands[1], QImode))"
-+ "@
-+ mov\t%1, %0
-+ ldub\t%1, %0
-+ stb\t%r1, %0"
-+ [(set_attr "type" "*,load,store")
-+ (set_attr "subtype" "*,regular,*")
-+ (set_attr "us3load_type" "*,3cycle,*")])
-+
-+(define_expand "movhi"
-+ [(set (match_operand:HI 0 "nonimmediate_operand" "")
-+ (match_operand:HI 1 "general_operand" ""))]
-+ ""
-+{
-+ if (sparc_expand_move (HImode, operands))
-+ DONE;
-+})
-+
-+(define_insn "*movhi_insn"
-+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
-+ (match_operand:HI 1 "input_operand" "rI,K,m,rJ"))]
-+ "(register_operand (operands[0], HImode)
-+ || register_or_zero_operand (operands[1], HImode))"
-+ "@
-+ mov\t%1, %0
-+ sethi\t%%hi(%a1), %0
-+ lduh\t%1, %0
-+ sth\t%r1, %0"
-+ [(set_attr "type" "*,*,load,store")
-+ (set_attr "subtype" "*,*,regular,*")
-+ (set_attr "us3load_type" "*,*,3cycle,*")])
-+
-+;; We always work with constants here.
-+(define_insn "*movhi_lo_sum"
-+ [(set (match_operand:HI 0 "register_operand" "=r")
-+ (ior:HI (match_operand:HI 1 "register_operand" "%r")
-+ (match_operand:HI 2 "small_int_operand" "I")))]
-+ ""
-+ "or\t%1, %2, %0")
-+
-+(define_expand "movsi"
-+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
-+ (match_operand:SI 1 "general_operand" ""))]
-+ ""
-+{
-+ if (sparc_expand_move (SImode, operands))
-+ DONE;
-+})
-+
-+(define_insn "*movsi_insn"
-+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m, r,*f,?*f,?*f, m,d,d")
-+ (match_operand:SI 1 "input_operand" "rI,K,m,rJ,*f, r, f, m,?*f,J,P"))]
-+ "register_operand (operands[0], SImode)
-+ || register_or_zero_or_all_ones_operand (operands[1], SImode)"
-+ "@
-+ mov\t%1, %0
-+ sethi\t%%hi(%a1), %0
-+ ld\t%1, %0
-+ st\t%r1, %0
-+ movstouw\t%1, %0
-+ movwtos\t%1, %0
-+ fmovs\t%1, %0
-+ ld\t%1, %0
-+ st\t%1, %0
-+ fzeros\t%0
-+ fones\t%0"
-+ [(set_attr "type" "*,*,load,store,vismv,vismv,fpmove,fpload,fpstore,visl,visl")
-+ (set_attr "subtype" "*,*,regular,*,movstouw,single,*,*,*,single,single")
-+ (set_attr "cpu_feature" "*,*,*,*,vis3,vis3,*,*,*,vis,vis")])
-+
-+(define_insn "*movsi_lo_sum"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
-+ (match_operand:SI 2 "immediate_operand" "in")))]
-+ "!flag_pic"
-+ "or\t%1, %%lo(%a2), %0")
-+
-+(define_insn "*movsi_high"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (high:SI (match_operand:SI 1 "immediate_operand" "in")))]
-+ "!flag_pic"
-+ "sethi\t%%hi(%a1), %0")
-+
-+;; The next two patterns must wrap the SYMBOL_REF in an UNSPEC
-+;; so that CSE won't optimize the address computation away.
-+(define_insn "movsi_lo_sum_pic"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
-+ (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")]
-+ UNSPEC_MOVE_PIC)))]
-+ "flag_pic"
-+{
-+#ifdef HAVE_AS_SPARC_GOTDATA_OP
-+ return "xor\t%1, %%gdop_lox10(%a2), %0";
-+#else
-+ return "or\t%1, %%lo(%a2), %0";
-+#endif
-+})
-+
-+(define_insn "movsi_high_pic"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (high:SI (unspec:SI [(match_operand 1 "" "")] UNSPEC_MOVE_PIC)))]
-+ "flag_pic && check_pic (1)"
-+{
-+#ifdef HAVE_AS_SPARC_GOTDATA_OP
-+ return "sethi\t%%gdop_hix22(%a1), %0";
-+#else
-+ return "sethi\t%%hi(%a1), %0";
-+#endif
-+})
-+
-+(define_insn "movsi_pic_gotdata_op"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")
-+ (match_operand:SI 2 "register_operand" "r")
-+ (match_operand 3 "symbolic_operand" "")]
-+ UNSPEC_MOVE_GOTDATA))]
-+ "flag_pic && check_pic (1)"
-+{
-+#ifdef HAVE_AS_SPARC_GOTDATA_OP
-+ return "ld\t[%1 + %2], %0, %%gdop(%a3)";
-+#else
-+ return "ld\t[%1 + %2], %0";
-+#endif
-+}
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "regular")])
-+
-+(define_expand "movsi_pic_label_ref"
-+ [(set (match_dup 3) (high:SI
-+ (unspec:SI [(match_operand:SI 1 "symbolic_operand" "")
-+ (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
-+ (set (match_dup 4) (lo_sum:SI (match_dup 3)
-+ (unspec:SI [(match_dup 1) (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (minus:SI (match_dup 5) (match_dup 4)))]
-+ "flag_pic"
-+{
-+ crtl->uses_pic_offset_table = 1;
-+ operands[2] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
-+ if (!can_create_pseudo_p ())
-+ {
-+ operands[3] = operands[0];
-+ operands[4] = operands[0];
-+ }
-+ else
-+ {
-+ operands[3] = gen_reg_rtx (SImode);
-+ operands[4] = gen_reg_rtx (SImode);
-+ }
-+ operands[5] = pic_offset_table_rtx;
-+})
-+
-+(define_insn "*movsi_high_pic_label_ref"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (high:SI
-+ (unspec:SI [(match_operand:SI 1 "symbolic_operand" "")
-+ (match_operand:SI 2 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
-+ "flag_pic"
-+ "sethi\t%%hi(%a2-(%a1-.)), %0")
-+
-+(define_insn "*movsi_lo_sum_pic_label_ref"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
-+ (unspec:SI [(match_operand:SI 2 "symbolic_operand" "")
-+ (match_operand:SI 3 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
-+ "flag_pic"
-+ "or\t%1, %%lo(%a3-(%a2-.)), %0")
-+
-+;; Set up the PIC register for VxWorks.
-+
-+(define_expand "vxworks_load_got"
-+ [(set (match_dup 0)
-+ (high:SI (match_dup 1)))
-+ (set (match_dup 0)
-+ (mem:SI (lo_sum:SI (match_dup 0) (match_dup 1))))
-+ (set (match_dup 0)
-+ (mem:SI (lo_sum:SI (match_dup 0) (match_dup 2))))]
-+ "TARGET_VXWORKS_RTP"
-+{
-+ operands[0] = pic_offset_table_rtx;
-+ operands[1] = gen_rtx_SYMBOL_REF (SImode, VXWORKS_GOTT_BASE);
-+ operands[2] = gen_rtx_SYMBOL_REF (SImode, VXWORKS_GOTT_INDEX);
-+})
-+
-+(define_expand "movdi"
-+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
-+ (match_operand:DI 1 "general_operand" ""))]
-+ ""
-+{
-+ if (sparc_expand_move (DImode, operands))
-+ DONE;
-+})
-+
-+;; Be careful, fmovd does not exist when !v9.
-+;; We match MEM moves directly when we have correct even
-+;; numbered registers, but fall into splits otherwise.
-+;; The constraint ordering here is really important to
-+;; avoid insane problems in reload, especially for patterns
-+;; of the form:
-+;;
-+;; (set (mem:DI (plus:SI (reg:SI 30 %fp)
-+;; (const_int -5016)))
-+;; (reg:DI 2 %g2))
-+;;
-+
-+(define_insn "*movdi_insn_sp32"
-+ [(set (match_operand:DI 0 "nonimmediate_operand"
-+ "=T,o,U,T,r,o,r,r,?*f, T,?*f, o,?*e,?*e, r,?*f,?*e, T,*b,*b")
-+ (match_operand:DI 1 "input_operand"
-+ " J,J,T,U,o,r,i,r, T,?*f, o,?*f, *e, *e,?*f, r, T,?*e, J, P"))]
-+ "TARGET_ARCH32
-+ && (register_operand (operands[0], DImode)
-+ || register_or_zero_operand (operands[1], DImode))"
-+ "@
-+ stx\t%r1, %0
-+ #
-+ ldd\t%1, %0
-+ std\t%1, %0
-+ ldd\t%1, %0
-+ std\t%1, %0
-+ #
-+ #
-+ ldd\t%1, %0
-+ std\t%1, %0
-+ #
-+ #
-+ fmovd\t%1, %0
-+ #
-+ #
-+ #
-+ ldd\t%1, %0
-+ std\t%1, %0
-+ fzero\t%0
-+ fone\t%0"
-+ [(set_attr "type" "store,*,load,store,load,store,*,*,fpload,fpstore,*,*,fpmove,*,*,*,fpload,fpstore,visl,
-+visl")
-+ (set_attr "subtype" "*,*,regular,*,regular,*,*,*,*,*,*,*,*,*,*,*,*,*,double,double")
-+ (set_attr "length" "*,2,*,*,*,*,2,2,*,*,2,2,*,2,2,2,*,*,*,*")
-+ (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,double,*,*,*,*,*,double,double")
-+ (set_attr "cpu_feature" "v9,*,*,*,*,*,*,*,fpu,fpu,fpu,fpu,v9,fpunotv9,vis3,vis3,fpu,fpu,vis,vis")
-+ (set_attr "lra" "*,*,disabled,disabled,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
-+
-+(define_insn "*movdi_insn_sp64"
-+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m, r,*e,?*e,?*e, W,b,b")
-+ (match_operand:DI 1 "input_operand" "rI,N,m,rJ,*e, r, *e, W,?*e,J,P"))]
-+ "TARGET_ARCH64
-+ && (register_operand (operands[0], DImode)
-+ || register_or_zero_or_all_ones_operand (operands[1], DImode))"
-+ "@
-+ mov\t%1, %0
-+ sethi\t%%hi(%a1), %0
-+ ldx\t%1, %0
-+ stx\t%r1, %0
-+ movdtox\t%1, %0
-+ movxtod\t%1, %0
-+ fmovd\t%1, %0
-+ ldd\t%1, %0
-+ std\t%1, %0
-+ fzero\t%0
-+ fone\t%0"
-+ [(set_attr "type" "*,*,load,store,vismv,vismv,fpmove,fpload,fpstore,visl,visl")
-+ (set_attr "subtype" "*,*,regular,*,movdtox,movxtod,*,*,*,double,double")
-+ (set_attr "fptype" "*,*,*,*,*,*,double,*,*,double,double")
-+ (set_attr "cpu_feature" "*,*,*,*,vis3,vis3,*,*,*,vis,vis")])
-+
-+(define_expand "movdi_pic_label_ref"
-+ [(set (match_dup 3) (high:DI
-+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")
-+ (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
-+ (set (match_dup 4) (lo_sum:DI (match_dup 3)
-+ (unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
-+ (set (match_operand:DI 0 "register_operand" "=r")
-+ (minus:DI (match_dup 5) (match_dup 4)))]
-+ "TARGET_ARCH64 && flag_pic"
-+{
-+ crtl->uses_pic_offset_table = 1;
-+ operands[2] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
-+ if (!can_create_pseudo_p ())
-+ {
-+ operands[3] = operands[0];
-+ operands[4] = operands[0];
-+ }
-+ else
-+ {
-+ operands[3] = gen_reg_rtx (DImode);
-+ operands[4] = gen_reg_rtx (DImode);
-+ }
-+ operands[5] = pic_offset_table_rtx;
-+})
-+
-+(define_insn "*movdi_high_pic_label_ref"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (high:DI
-+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")
-+ (match_operand:DI 2 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
-+ "TARGET_ARCH64 && flag_pic"
-+ "sethi\t%%hi(%a2-(%a1-.)), %0")
-+
-+(define_insn "*movdi_lo_sum_pic_label_ref"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
-+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")
-+ (match_operand:DI 3 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
-+ "TARGET_ARCH64 && flag_pic"
-+ "or\t%1, %%lo(%a3-(%a2-.)), %0")
-+
-+;; SPARC-v9 code model support insns. See sparc_emit_set_symbolic_const64
-+;; in sparc.c to see what is going on here... PIC stuff comes first.
-+
-+(define_insn "movdi_lo_sum_pic"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
-+ (unspec:DI [(match_operand:DI 2 "immediate_operand" "in")]
-+ UNSPEC_MOVE_PIC)))]
-+ "TARGET_ARCH64 && flag_pic"
-+{
-+#ifdef HAVE_AS_SPARC_GOTDATA_OP
-+ return "xor\t%1, %%gdop_lox10(%a2), %0";
-+#else
-+ return "or\t%1, %%lo(%a2), %0";
-+#endif
-+})
-+
-+(define_insn "movdi_high_pic"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (high:DI (unspec:DI [(match_operand 1 "" "")] UNSPEC_MOVE_PIC)))]
-+ "TARGET_ARCH64 && flag_pic && check_pic (1)"
-+{
-+#ifdef HAVE_AS_SPARC_GOTDATA_OP
-+ return "sethi\t%%gdop_hix22(%a1), %0";
-+#else
-+ return "sethi\t%%hi(%a1), %0";
-+#endif
-+})
-+
-+(define_insn "movdi_pic_gotdata_op"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (unspec:DI [(match_operand:DI 1 "register_operand" "r")
-+ (match_operand:DI 2 "register_operand" "r")
-+ (match_operand 3 "symbolic_operand" "")]
-+ UNSPEC_MOVE_GOTDATA))]
-+ "TARGET_ARCH64 && flag_pic && check_pic (1)"
-+{
-+#ifdef HAVE_AS_SPARC_GOTDATA_OP
-+ return "ldx\t[%1 + %2], %0, %%gdop(%a3)";
-+#else
-+ return "ldx\t[%1 + %2], %0";
-+#endif
-+}
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "regular")])
-+
-+(define_insn "*sethi_di_medlow_embmedany_pic"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (high:DI (match_operand:DI 1 "medium_pic_operand" "")))]
-+ "(TARGET_CM_MEDLOW || TARGET_CM_EMBMEDANY) && flag_pic && check_pic (1)"
-+ "sethi\t%%hi(%a1), %0")
-+
-+(define_insn "*sethi_di_medlow"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (high:DI (match_operand:DI 1 "symbolic_operand" "")))]
-+ "TARGET_CM_MEDLOW && !flag_pic"
-+ "sethi\t%%hi(%a1), %0")
-+
-+(define_insn "*losum_di_medlow"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
-+ (match_operand:DI 2 "symbolic_operand" "")))]
-+ "TARGET_CM_MEDLOW && !flag_pic"
-+ "or\t%1, %%lo(%a2), %0")
-+
-+(define_insn "seth44"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
-+ UNSPEC_SETH44)))]
-+ "TARGET_CM_MEDMID && !flag_pic"
-+ "sethi\t%%h44(%a1), %0")
-+
-+(define_insn "setm44"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
-+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
-+ UNSPEC_SETM44)))]
-+ "TARGET_CM_MEDMID && !flag_pic"
-+ "or\t%1, %%m44(%a2), %0")
-+
-+(define_insn "setl44"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
-+ (match_operand:DI 2 "symbolic_operand" "")))]
-+ "TARGET_CM_MEDMID && !flag_pic"
-+ "or\t%1, %%l44(%a2), %0")
-+
-+(define_insn "sethh"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
-+ UNSPEC_SETHH)))]
-+ "TARGET_CM_MEDANY && !flag_pic"
-+ "sethi\t%%hh(%a1), %0")
-+
-+(define_insn "setlm"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
-+ UNSPEC_SETLM)))]
-+ "TARGET_CM_MEDANY && !flag_pic"
-+ "sethi\t%%lm(%a1), %0")
-+
-+(define_insn "sethm"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
-+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
-+ UNSPEC_EMB_SETHM)))]
-+ "TARGET_CM_MEDANY && !flag_pic"
-+ "or\t%1, %%hm(%a2), %0")
-+
-+(define_insn "setlo"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
-+ (match_operand:DI 2 "symbolic_operand" "")))]
-+ "TARGET_CM_MEDANY && !flag_pic"
-+ "or\t%1, %%lo(%a2), %0")
-+
-+(define_insn "embmedany_sethi"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (high:DI (unspec:DI [(match_operand:DI 1 "data_segment_operand" "")]
-+ UNSPEC_EMB_HISUM)))]
-+ "TARGET_CM_EMBMEDANY && !flag_pic"
-+ "sethi\t%%hi(%a1), %0")
-+
-+(define_insn "embmedany_losum"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
-+ (match_operand:DI 2 "data_segment_operand" "")))]
-+ "TARGET_CM_EMBMEDANY && !flag_pic"
-+ "add\t%1, %%lo(%a2), %0")
-+
-+(define_insn "embmedany_brsum"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (unspec:DI [(match_operand:DI 1 "register_operand" "r")]
-+ UNSPEC_EMB_HISUM))]
-+ "TARGET_CM_EMBMEDANY && !flag_pic"
-+ "add\t%1, %_, %0")
-+
-+(define_insn "embmedany_textuhi"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")]
-+ UNSPEC_EMB_TEXTUHI)))]
-+ "TARGET_CM_EMBMEDANY && !flag_pic"
-+ "sethi\t%%uhi(%a1), %0")
-+
-+(define_insn "embmedany_texthi"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")]
-+ UNSPEC_EMB_TEXTHI)))]
-+ "TARGET_CM_EMBMEDANY && !flag_pic"
-+ "sethi\t%%hi(%a1), %0")
-+
-+(define_insn "embmedany_textulo"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
-+ (unspec:DI [(match_operand:DI 2 "text_segment_operand" "")]
-+ UNSPEC_EMB_TEXTULO)))]
-+ "TARGET_CM_EMBMEDANY && !flag_pic"
-+ "or\t%1, %%ulo(%a2), %0")
-+
-+(define_insn "embmedany_textlo"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
-+ (match_operand:DI 2 "text_segment_operand" "")))]
-+ "TARGET_CM_EMBMEDANY && !flag_pic"
-+ "or\t%1, %%lo(%a2), %0")
-+
-+;; Now some patterns to help reload out a bit.
-+(define_expand "reload_indi"
-+ [(parallel [(match_operand:DI 0 "register_operand" "=r")
-+ (match_operand:DI 1 "immediate_operand" "")
-+ (match_operand:TI 2 "register_operand" "=&r")])]
-+ "(TARGET_CM_MEDANY || TARGET_CM_EMBMEDANY) && !flag_pic"
-+{
-+ sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
-+ DONE;
-+})
-+
-+(define_expand "reload_outdi"
-+ [(parallel [(match_operand:DI 0 "register_operand" "=r")
-+ (match_operand:DI 1 "immediate_operand" "")
-+ (match_operand:TI 2 "register_operand" "=&r")])]
-+ "(TARGET_CM_MEDANY || TARGET_CM_EMBMEDANY) && !flag_pic"
-+{
-+ sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
-+ DONE;
-+})
-+
-+;; Split up putting CONSTs and REGs into DI regs when !arch64
-+(define_split
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (match_operand:DI 1 "const_int_operand" ""))]
-+ "reload_completed
-+ && TARGET_ARCH32
-+ && ((GET_CODE (operands[0]) == REG
-+ && SPARC_INT_REG_P (REGNO (operands[0])))
-+ || (GET_CODE (operands[0]) == SUBREG
-+ && GET_CODE (SUBREG_REG (operands[0])) == REG
-+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))"
-+ [(clobber (const_int 0))]
-+{
-+ HOST_WIDE_INT low = trunc_int_for_mode (INTVAL (operands[1]), SImode);
-+ HOST_WIDE_INT high = trunc_int_for_mode (INTVAL (operands[1]) >> 32, SImode);
-+ rtx high_part = gen_highpart (SImode, operands[0]);
-+ rtx low_part = gen_lowpart (SImode, operands[0]);
-+
-+ emit_move_insn_1 (high_part, GEN_INT (high));
-+
-+ /* Slick... but this loses if the constant can be done in one insn. */
-+ if (low == high && !SPARC_SETHI32_P (high) && !SPARC_SIMM13_P (high))
-+ emit_move_insn_1 (low_part, high_part);
-+ else
-+ emit_move_insn_1 (low_part, GEN_INT (low));
-+
-+ DONE;
-+})
-+
-+(define_split
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (match_operand:DI 1 "register_operand" ""))]
-+ "reload_completed
-+ && (!TARGET_V9
-+ || (TARGET_ARCH32
-+ && sparc_split_reg_reg_legitimate (operands[0], operands[1])))"
-+ [(clobber (const_int 0))]
-+{
-+ sparc_split_reg_reg (operands[0], operands[1], SImode);
-+ DONE;
-+})
-+
-+;; Now handle the cases of memory moves from/to non-even
-+;; DI mode register pairs.
-+(define_split
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (match_operand:DI 1 "memory_operand" ""))]
-+ "reload_completed
-+ && TARGET_ARCH32
-+ && sparc_split_reg_mem_legitimate (operands[0], operands[1])"
-+ [(clobber (const_int 0))]
-+{
-+ sparc_split_reg_mem (operands[0], operands[1], SImode);
-+ DONE;
-+})
-+
-+(define_split
-+ [(set (match_operand:DI 0 "memory_operand" "")
-+ (match_operand:DI 1 "register_operand" ""))]
-+ "reload_completed
-+ && TARGET_ARCH32
-+ && sparc_split_reg_mem_legitimate (operands[1], operands[0])"
-+ [(clobber (const_int 0))]
-+{
-+ sparc_split_mem_reg (operands[0], operands[1], SImode);
-+ DONE;
-+})
-+
-+(define_split
-+ [(set (match_operand:DI 0 "memory_operand" "")
-+ (match_operand:DI 1 "const_zero_operand" ""))]
-+ "reload_completed
-+ && (!TARGET_V9
-+ || (TARGET_ARCH32
-+ && !mem_min_alignment (operands[0], 8)))
-+ && offsettable_memref_p (operands[0])"
-+ [(clobber (const_int 0))]
-+{
-+ emit_move_insn_1 (adjust_address (operands[0], SImode, 0), const0_rtx);
-+ emit_move_insn_1 (adjust_address (operands[0], SImode, 4), const0_rtx);
-+ DONE;
-+})
-+
-+(define_expand "movti"
-+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
-+ (match_operand:TI 1 "general_operand" ""))]
-+ "TARGET_ARCH64"
-+{
-+ if (sparc_expand_move (TImode, operands))
-+ DONE;
-+})
-+
-+;; We need to prevent reload from splitting TImode moves, because it
-+;; might decide to overwrite a pointer with 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.
-+
-+(define_insn "*movti_insn_sp64"
-+ [(set (match_operand:TI 0 "nonimmediate_operand" "=r , o,?*e,?o,b")
-+ (match_operand:TI 1 "input_operand" "roJ,rJ, eo, e,J"))]
-+ "TARGET_ARCH64
-+ && !TARGET_HARD_QUAD
-+ && (register_operand (operands[0], TImode)
-+ || register_or_zero_operand (operands[1], TImode))"
-+ "#"
-+ [(set_attr "length" "2,2,2,2,2")
-+ (set_attr "cpu_feature" "*,*,fpu,fpu,vis")])
-+
-+(define_insn "*movti_insn_sp64_hq"
-+ [(set (match_operand:TI 0 "nonimmediate_operand" "=r , o,?*e,?*e,?m,b")
-+ (match_operand:TI 1 "input_operand" "roJ,rJ, e, m, e,J"))]
-+ "TARGET_ARCH64
-+ && TARGET_HARD_QUAD
-+ && (register_operand (operands[0], TImode)
-+ || register_or_zero_operand (operands[1], TImode))"
-+ "@
-+ #
-+ #
-+ fmovq\t%1, %0
-+ ldq\t%1, %0
-+ stq\t%1, %0
-+ #"
-+ [(set_attr "type" "*,*,fpmove,fpload,fpstore,*")
-+ (set_attr "length" "2,2,*,*,*,2")])
-+
-+;; Now all the splits to handle multi-insn TI mode moves.
-+(define_split
-+ [(set (match_operand:TI 0 "register_operand" "")
-+ (match_operand:TI 1 "register_operand" ""))]
-+ "reload_completed
-+ && ((TARGET_FPU
-+ && !TARGET_HARD_QUAD)
-+ || (!fp_register_operand (operands[0], TImode)
-+ && !fp_register_operand (operands[1], TImode)))"
-+ [(clobber (const_int 0))]
-+{
-+ rtx set_dest = operands[0];
-+ rtx set_src = operands[1];
-+ rtx dest1, dest2;
-+ rtx src1, src2;
-+
-+ dest1 = gen_highpart (DImode, set_dest);
-+ dest2 = gen_lowpart (DImode, set_dest);
-+ src1 = gen_highpart (DImode, set_src);
-+ src2 = gen_lowpart (DImode, set_src);
-+
-+ /* Now emit using the real source and destination we found, swapping
-+ the order if we detect overlap. */
-+ if (reg_overlap_mentioned_p (dest1, src2))
-+ {
-+ emit_insn (gen_movdi (dest2, src2));
-+ emit_insn (gen_movdi (dest1, src1));
-+ }
-+ else
-+ {
-+ emit_insn (gen_movdi (dest1, src1));
-+ emit_insn (gen_movdi (dest2, src2));
-+ }
-+ DONE;
-+})
-+
-+(define_split
-+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
-+ (match_operand:TI 1 "const_zero_operand" ""))]
-+ "reload_completed"
-+ [(clobber (const_int 0))]
-+{
-+ rtx set_dest = operands[0];
-+ rtx dest1, dest2;
-+
-+ switch (GET_CODE (set_dest))
-+ {
-+ case REG:
-+ dest1 = gen_highpart (DImode, set_dest);
-+ dest2 = gen_lowpart (DImode, set_dest);
-+ break;
-+ case MEM:
-+ dest1 = adjust_address (set_dest, DImode, 0);
-+ dest2 = adjust_address (set_dest, DImode, 8);
-+ break;
-+ default:
-+ gcc_unreachable ();
-+ }
-+
-+ emit_insn (gen_movdi (dest1, const0_rtx));
-+ emit_insn (gen_movdi (dest2, const0_rtx));
-+ DONE;
-+})
-+
-+(define_split
-+ [(set (match_operand:TI 0 "register_operand" "")
-+ (match_operand:TI 1 "memory_operand" ""))]
-+ "reload_completed
-+ && offsettable_memref_p (operands[1])
-+ && (!TARGET_HARD_QUAD
-+ || !fp_register_operand (operands[0], TImode))"
-+ [(clobber (const_int 0))]
-+{
-+ rtx word0 = adjust_address (operands[1], DImode, 0);
-+ rtx word1 = adjust_address (operands[1], DImode, 8);
-+ rtx set_dest, dest1, dest2;
-+
-+ set_dest = operands[0];
-+
-+ dest1 = gen_highpart (DImode, set_dest);
-+ dest2 = gen_lowpart (DImode, set_dest);
-+
-+ /* Now output, ordering such that we don't clobber any registers
-+ mentioned in the address. */
-+ if (reg_overlap_mentioned_p (dest1, word1))
-+
-+ {
-+ emit_insn (gen_movdi (dest2, word1));
-+ emit_insn (gen_movdi (dest1, word0));
-+ }
-+ else
-+ {
-+ emit_insn (gen_movdi (dest1, word0));
-+ emit_insn (gen_movdi (dest2, word1));
-+ }
-+ DONE;
-+})
-+
-+(define_split
-+ [(set (match_operand:TI 0 "memory_operand" "")
-+ (match_operand:TI 1 "register_operand" ""))]
-+ "reload_completed
-+ && offsettable_memref_p (operands[0])
-+ && (!TARGET_HARD_QUAD
-+ || !fp_register_operand (operands[1], TImode))"
-+ [(clobber (const_int 0))]
-+{
-+ rtx set_src = operands[1];
-+
-+ emit_insn (gen_movdi (adjust_address (operands[0], DImode, 0),
-+ gen_highpart (DImode, set_src)));
-+ emit_insn (gen_movdi (adjust_address (operands[0], DImode, 8),
-+ gen_lowpart (DImode, set_src)));
-+ DONE;
-+})
-+
-+
-+;; Floating point move instructions
-+
-+(define_expand "movsf"
-+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
-+ (match_operand:SF 1 "general_operand" ""))]
-+ ""
-+{
-+ if (sparc_expand_move (SFmode, operands))
-+ DONE;
-+})
-+
-+(define_insn "*movsf_insn"
-+ [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,f, *r,*r,*r,*r, f,f,*r,m, m")
-+ (match_operand:SF 1 "input_operand" "G,C,f,*rR, Q, S, f,*r,m, m,f,*rG"))]
-+ "(register_operand (operands[0], SFmode)
-+ || register_or_zero_or_all_ones_operand (operands[1], SFmode))"
-+{
-+ if (GET_CODE (operands[1]) == CONST_DOUBLE
-+ && (which_alternative == 3
-+ || which_alternative == 4
-+ || which_alternative == 5))
-+ {
-+ long i;
-+
-+ REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (operands[1]), i);
-+ operands[1] = GEN_INT (i);
-+ }
-+
-+ switch (which_alternative)
-+ {
-+ case 0:
-+ return "fzeros\t%0";
-+ case 1:
-+ return "fones\t%0";
-+ case 2:
-+ return "fmovs\t%1, %0";
-+ case 3:
-+ return "mov\t%1, %0";
-+ case 4:
-+ return "sethi\t%%hi(%a1), %0";
-+ case 5:
-+ return "#";
-+ case 6:
-+ return "movstouw\t%1, %0";
-+ case 7:
-+ return "movwtos\t%1, %0";
-+ case 8:
-+ case 9:
-+ return "ld\t%1, %0";
-+ case 10:
-+ case 11:
-+ return "st\t%r1, %0";
-+ default:
-+ gcc_unreachable ();
-+ }
-+}
-+ [(set_attr "type" "visl,visl,fpmove,*,*,*,vismv,vismv,fpload,load,fpstore,store")
-+ (set_attr "subtype" "single,single,*,*,*,*,movstouw,single,*,regular,*,*")
-+ (set_attr "cpu_feature" "vis,vis,fpu,*,*,*,vis3,vis3,fpu,*,fpu,*")])
-+
-+;; The following 3 patterns build SFmode constants in integer registers.
-+
-+(define_insn "*movsf_lo_sum"
-+ [(set (match_operand:SF 0 "register_operand" "=r")
-+ (lo_sum:SF (match_operand:SF 1 "register_operand" "r")
-+ (match_operand:SF 2 "fp_const_high_losum_operand" "S")))]
-+ ""
-+{
-+ long i;
-+
-+ REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (operands[2]), i);
-+ operands[2] = GEN_INT (i);
-+ return "or\t%1, %%lo(%a2), %0";
-+})
-+
-+(define_insn "*movsf_high"
-+ [(set (match_operand:SF 0 "register_operand" "=r")
-+ (high:SF (match_operand:SF 1 "fp_const_high_losum_operand" "S")))]
-+ ""
-+{
-+ long i;
-+
-+ REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (operands[1]), i);
-+ operands[1] = GEN_INT (i);
-+ return "sethi\t%%hi(%1), %0";
-+})
-+
-+(define_split
-+ [(set (match_operand:SF 0 "register_operand" "")
-+ (match_operand:SF 1 "fp_const_high_losum_operand" ""))]
-+ "REG_P (operands[0]) && SPARC_INT_REG_P (REGNO (operands[0]))"
-+ [(set (match_dup 0) (high:SF (match_dup 1)))
-+ (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
-+
-+(define_expand "movdf"
-+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
-+ (match_operand:DF 1 "general_operand" ""))]
-+ ""
-+{
-+ if (sparc_expand_move (DFmode, operands))
-+ DONE;
-+})
-+
-+(define_insn "*movdf_insn_sp32"
-+ [(set (match_operand:DF 0 "nonimmediate_operand"
-+ "=T,o,b,b,e,e,*r, f, e,T,U,T, f,o, *r,*r, o")
-+ (match_operand:DF 1 "input_operand"
-+ " G,G,G,C,e,e, f,*r,T#F,e,T,U,o#F,f,*rF, o,*r"))]
-+ "TARGET_ARCH32
-+ && (register_operand (operands[0], DFmode)
-+ || register_or_zero_or_all_ones_operand (operands[1], DFmode))"
-+ "@
-+ stx\t%r1, %0
-+ #
-+ fzero\t%0
-+ fone\t%0
-+ fmovd\t%1, %0
-+ #
-+ #
-+ #
-+ ldd\t%1, %0
-+ std\t%1, %0
-+ ldd\t%1, %0
-+ std\t%1, %0
-+ #
-+ #
-+ #
-+ ldd\t%1, %0
-+ std\t%1, %0"
-+ [(set_attr "type" "store,*,visl,visl,fpmove,*,*,*,fpload,fpstore,load,store,*,*,*,load,store")
-+ (set_attr "subtype" "*,*,double,double,*,*,*,*,*,*,regular,*,*,*,*,regular,*")
-+ (set_attr "length" "*,2,*,*,*,2,2,2,*,*,*,*,2,2,2,*,*")
-+ (set_attr "fptype" "*,*,double,double,double,*,*,*,*,*,*,*,*,*,*,*,*")
-+ (set_attr "cpu_feature" "v9,*,vis,vis,v9,fpunotv9,vis3,vis3,fpu,fpu,*,*,fpu,fpu,*,*,*")
-+ (set_attr "lra" "*,*,*,*,*,*,*,*,*,*,disabled,disabled,*,*,*,*,*")])
-+
-+(define_insn "*movdf_insn_sp64"
-+ [(set (match_operand:DF 0 "nonimmediate_operand" "=b,b,e,*r, e, e,W, *r,*r, m,*r")
-+ (match_operand:DF 1 "input_operand" "G,C,e, e,*r,W#F,e,*rG, m,*rG, F"))]
-+ "TARGET_ARCH64
-+ && (register_operand (operands[0], DFmode)
-+ || register_or_zero_or_all_ones_operand (operands[1], DFmode))"
-+ "@
-+ fzero\t%0
-+ fone\t%0
-+ fmovd\t%1, %0
-+ movdtox\t%1, %0
-+ movxtod\t%1, %0
-+ ldd\t%1, %0
-+ std\t%1, %0
-+ mov\t%r1, %0
-+ ldx\t%1, %0
-+ stx\t%r1, %0
-+ #"
-+ [(set_attr "type" "visl,visl,fpmove,vismv,vismv,load,store,*,load,store,*")
-+ (set_attr "subtype" "double,double,*,movdtox,movxtod,regular,*,*,regular,*,*")
-+ (set_attr "length" "*,*,*,*,*,*,*,*,*,*,2")
-+ (set_attr "fptype" "double,double,double,double,double,*,*,*,*,*,*")
-+ (set_attr "cpu_feature" "vis,vis,fpu,vis3,vis3,fpu,fpu,*,*,*,*")])
-+
-+;; This pattern builds DFmode constants in integer registers.
-+(define_split
-+ [(set (match_operand:DF 0 "register_operand" "")
-+ (match_operand:DF 1 "const_double_operand" ""))]
-+ "reload_completed
-+ && REG_P (operands[0])
-+ && SPARC_INT_REG_P (REGNO (operands[0]))
-+ && !const_zero_operand (operands[1], GET_MODE (operands[0]))"
-+ [(clobber (const_int 0))]
-+{
-+ operands[0] = gen_raw_REG (DImode, REGNO (operands[0]));
-+
-+ if (TARGET_ARCH64)
-+ {
-+ rtx tem = simplify_subreg (DImode, operands[1], DFmode, 0);
-+ emit_insn (gen_movdi (operands[0], tem));
-+ }
-+ else
-+ {
-+ rtx hi = simplify_subreg (SImode, operands[1], DFmode, 0);
-+ rtx lo = simplify_subreg (SImode, operands[1], DFmode, 4);
-+ rtx high_part = gen_highpart (SImode, operands[0]);
-+ rtx low_part = gen_lowpart (SImode, operands[0]);
-+
-+ gcc_assert (GET_CODE (hi) == CONST_INT);
-+ gcc_assert (GET_CODE (lo) == CONST_INT);
-+
-+ emit_move_insn_1 (high_part, hi);
-+
-+ /* Slick... but this loses if the constant can be done in one insn. */
-+ if (lo == hi
-+ && !SPARC_SETHI32_P (INTVAL (hi))
-+ && !SPARC_SIMM13_P (INTVAL (hi)))
-+ emit_move_insn_1 (low_part, high_part);
-+ else
-+ emit_move_insn_1 (low_part, lo);
-+ }
-+ DONE;
-+})
-+
-+;; Ok, now the splits to handle all the multi insn and
-+;; mis-aligned memory address cases.
-+;; In these splits please take note that we must be
-+;; careful when V9 but not ARCH64 because the integer
-+;; register DFmode cases must be handled.
-+(define_split
-+ [(set (match_operand:DF 0 "register_operand" "")
-+ (match_operand:DF 1 "const_zero_operand" ""))]
-+ "reload_completed
-+ && TARGET_ARCH32
-+ && ((GET_CODE (operands[0]) == REG
-+ && SPARC_INT_REG_P (REGNO (operands[0])))
-+ || (GET_CODE (operands[0]) == SUBREG
-+ && GET_CODE (SUBREG_REG (operands[0])) == REG
-+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))"
-+ [(clobber (const_int 0))]
-+{
-+ emit_move_insn_1 (gen_highpart (SFmode, operands[0]), CONST0_RTX (SFmode));
-+ emit_move_insn_1 (gen_lowpart (SFmode, operands[0]), CONST0_RTX (SFmode));
-+ DONE;
-+})
-+
-+(define_split
-+ [(set (match_operand:DF 0 "register_operand" "")
-+ (match_operand:DF 1 "register_operand" ""))]
-+ "reload_completed
-+ && (!TARGET_V9
-+ || (TARGET_ARCH32
-+ && sparc_split_reg_reg_legitimate (operands[0], operands[1])))"
-+ [(clobber (const_int 0))]
-+{
-+ sparc_split_reg_reg (operands[0], operands[1], SFmode);
-+ DONE;
-+})
-+
-+(define_split
-+ [(set (match_operand:DF 0 "register_operand" "")
-+ (match_operand:DF 1 "memory_operand" ""))]
-+ "reload_completed
-+ && TARGET_ARCH32
-+ && sparc_split_reg_mem_legitimate (operands[0], operands[1])"
-+ [(clobber (const_int 0))]
-+{
-+ sparc_split_reg_mem (operands[0], operands[1], SFmode);
-+ DONE;
-+})
-+
-+(define_split
-+ [(set (match_operand:DF 0 "memory_operand" "")
-+ (match_operand:DF 1 "register_operand" ""))]
-+ "reload_completed
-+ && TARGET_ARCH32
-+ && sparc_split_reg_mem_legitimate (operands[1], operands[0])"
-+ [(clobber (const_int 0))]
-+{
-+ sparc_split_mem_reg (operands[0], operands[1], SFmode);
-+ DONE;
-+})
-+
-+(define_split
-+ [(set (match_operand:DF 0 "memory_operand" "")
-+ (match_operand:DF 1 "const_zero_operand" ""))]
-+ "reload_completed
-+ && (!TARGET_V9
-+ || (TARGET_ARCH32
-+ && !mem_min_alignment (operands[0], 8)))
-+ && offsettable_memref_p (operands[0])"
-+ [(clobber (const_int 0))]
-+{
-+ emit_move_insn_1 (adjust_address (operands[0], SFmode, 0), CONST0_RTX (SFmode));
-+ emit_move_insn_1 (adjust_address (operands[0], SFmode, 4), CONST0_RTX (SFmode));
-+ DONE;
-+})
-+
-+(define_expand "movtf"
-+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
-+ (match_operand:TF 1 "general_operand" ""))]
-+ ""
-+{
-+ if (sparc_expand_move (TFmode, operands))
-+ DONE;
-+})
-+
-+(define_insn "*movtf_insn_sp32"
-+ [(set (match_operand:TF 0 "nonimmediate_operand" "=b, e,o, o, r")
-+ (match_operand:TF 1 "input_operand" " G,oe,e,rG,roG"))]
-+ "TARGET_ARCH32
-+ && (register_operand (operands[0], TFmode)
-+ || register_or_zero_operand (operands[1], TFmode))"
-+ "#"
-+ [(set_attr "length" "4,4,4,4,4")
-+ (set_attr "cpu_feature" "fpu,fpu,fpu,*,*")])
-+
-+(define_insn "*movtf_insn_sp64"
-+ [(set (match_operand:TF 0 "nonimmediate_operand" "=b, e,o, o, r")
-+ (match_operand:TF 1 "input_operand" "G,oe,e,rG,roG"))]
-+ "TARGET_ARCH64
-+ && !TARGET_HARD_QUAD
-+ && (register_operand (operands[0], TFmode)
-+ || register_or_zero_operand (operands[1], TFmode))"
-+ "#"
-+ [(set_attr "length" "2,2,2,2,2")
-+ (set_attr "cpu_feature" "fpu,fpu,fpu,*,*")])
-+
-+(define_insn "*movtf_insn_sp64_hq"
-+ [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,e,m, o, r")
-+ (match_operand:TF 1 "input_operand" "G,e,m,e,rG,roG"))]
-+ "TARGET_ARCH64
-+ && TARGET_HARD_QUAD
-+ && (register_operand (operands[0], TFmode)
-+ || register_or_zero_operand (operands[1], TFmode))"
-+ "@
-+ #
-+ fmovq\t%1, %0
-+ ldq\t%1, %0
-+ stq\t%1, %0
-+ #
-+ #"
-+ [(set_attr "type" "*,fpmove,fpload,fpstore,*,*")
-+ (set_attr "length" "2,*,*,*,2,2")])
-+
-+;; Now all the splits to handle multi-insn TF mode moves.
-+(define_split
-+ [(set (match_operand:TF 0 "register_operand" "")
-+ (match_operand:TF 1 "register_operand" ""))]
-+ "reload_completed
-+ && (TARGET_ARCH32
-+ || (TARGET_FPU
-+ && !TARGET_HARD_QUAD)
-+ || (!fp_register_operand (operands[0], TFmode)
-+ && !fp_register_operand (operands[1], TFmode)))"
-+ [(clobber (const_int 0))]
-+{
-+ rtx set_dest = operands[0];
-+ rtx set_src = operands[1];
-+ rtx dest1, dest2;
-+ rtx src1, src2;
-+
-+ dest1 = gen_df_reg (set_dest, 0);
-+ dest2 = gen_df_reg (set_dest, 1);
-+ src1 = gen_df_reg (set_src, 0);
-+ src2 = gen_df_reg (set_src, 1);
-+
-+ /* Now emit using the real source and destination we found, swapping
-+ the order if we detect overlap. */
-+ if (reg_overlap_mentioned_p (dest1, src2))
-+ {
-+ emit_insn (gen_movdf (dest2, src2));
-+ emit_insn (gen_movdf (dest1, src1));
-+ }
-+ else
-+ {
-+ emit_insn (gen_movdf (dest1, src1));
-+ emit_insn (gen_movdf (dest2, src2));
-+ }
-+ DONE;
-+})
-+
-+(define_split
-+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
-+ (match_operand:TF 1 "const_zero_operand" ""))]
-+ "reload_completed"
-+ [(clobber (const_int 0))]
-+{
-+ rtx set_dest = operands[0];
-+ rtx dest1, dest2;
-+
-+ switch (GET_CODE (set_dest))
-+ {
-+ case REG:
-+ dest1 = gen_df_reg (set_dest, 0);
-+ dest2 = gen_df_reg (set_dest, 1);
-+ break;
-+ case MEM:
-+ dest1 = adjust_address (set_dest, DFmode, 0);
-+ dest2 = adjust_address (set_dest, DFmode, 8);
-+ break;
-+ default:
-+ gcc_unreachable ();
-+ }
-+
-+ emit_insn (gen_movdf (dest1, CONST0_RTX (DFmode)));
-+ emit_insn (gen_movdf (dest2, CONST0_RTX (DFmode)));
-+ DONE;
-+})
-+
-+(define_split
-+ [(set (match_operand:TF 0 "register_operand" "")
-+ (match_operand:TF 1 "memory_operand" ""))]
-+ "(reload_completed
-+ && offsettable_memref_p (operands[1])
-+ && (TARGET_ARCH32
-+ || !TARGET_HARD_QUAD
-+ || !fp_register_operand (operands[0], TFmode)))"
-+ [(clobber (const_int 0))]
-+{
-+ rtx word0 = adjust_address (operands[1], DFmode, 0);
-+ rtx word1 = adjust_address (operands[1], DFmode, 8);
-+ rtx set_dest, dest1, dest2;
-+
-+ set_dest = operands[0];
-+
-+ dest1 = gen_df_reg (set_dest, 0);
-+ dest2 = gen_df_reg (set_dest, 1);
-+
-+ /* Now output, ordering such that we don't clobber any registers
-+ mentioned in the address. */
-+ if (reg_overlap_mentioned_p (dest1, word1))
-+
-+ {
-+ emit_insn (gen_movdf (dest2, word1));
-+ emit_insn (gen_movdf (dest1, word0));
-+ }
-+ else
-+ {
-+ emit_insn (gen_movdf (dest1, word0));
-+ emit_insn (gen_movdf (dest2, word1));
-+ }
-+ DONE;
-+})
-+
-+(define_split
-+ [(set (match_operand:TF 0 "memory_operand" "")
-+ (match_operand:TF 1 "register_operand" ""))]
-+ "(reload_completed
-+ && offsettable_memref_p (operands[0])
-+ && (TARGET_ARCH32
-+ || !TARGET_HARD_QUAD
-+ || !fp_register_operand (operands[1], TFmode)))"
-+ [(clobber (const_int 0))]
-+{
-+ rtx set_src = operands[1];
-+
-+ emit_insn (gen_movdf (adjust_address (operands[0], DFmode, 0),
-+ gen_df_reg (set_src, 0)));
-+ emit_insn (gen_movdf (adjust_address (operands[0], DFmode, 8),
-+ gen_df_reg (set_src, 1)));
-+ DONE;
-+})
-+
-+
-+;; SPARC-V9 conditional move instructions
-+
-+;; We can handle larger constants here for some flavors, but for now we keep
-+;; it simple and only allow those constants supported by all flavors.
-+;; Note that emit_conditional_move canonicalizes operands 2,3 so that operand
-+;; 3 contains the constant if one is present, but we handle either for
-+;; generality (sparc.c puts a constant in operand 2).
-+;;
-+;; Our instruction patterns, on the other hand, canonicalize such that
-+;; operand 3 must be the set destination.
-+
-+(define_expand "mov<I:mode>cc"
-+ [(set (match_operand:I 0 "register_operand" "")
-+ (if_then_else:I (match_operand 1 "comparison_operator" "")
-+ (match_operand:I 2 "arith10_operand" "")
-+ (match_operand:I 3 "arith10_operand" "")))]
-+ "TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)"
-+{
-+ if (!sparc_expand_conditional_move (<I:MODE>mode, operands))
-+ FAIL;
-+ DONE;
-+})
-+
-+(define_expand "mov<F:mode>cc"
-+ [(set (match_operand:F 0 "register_operand" "")
-+ (if_then_else:F (match_operand 1 "comparison_operator" "")
-+ (match_operand:F 2 "register_operand" "")
-+ (match_operand:F 3 "register_operand" "")))]
-+ "TARGET_V9 && TARGET_FPU"
-+{
-+ if (!sparc_expand_conditional_move (<F:MODE>mode, operands))
-+ FAIL;
-+ DONE;
-+})
-+
-+(define_insn "*mov<I:mode>_cc_v9"
-+ [(set (match_operand:I 0 "register_operand" "=r")
-+ (if_then_else:I (match_operator 1 "icc_or_fcc_comparison_operator"
-+ [(match_operand 2 "icc_or_fcc_register_operand" "X")
-+ (const_int 0)])
-+ (match_operand:I 3 "arith11_operand" "rL")
-+ (match_operand:I 4 "register_operand" "0")))]
-+ "TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)"
-+ "mov%C1\t%x2, %3, %0"
-+ [(set_attr "type" "cmove")])
-+
-+(define_insn "*mov<I:mode>_cc_reg_sp64"
-+ [(set (match_operand:I 0 "register_operand" "=r")
-+ (if_then_else:I (match_operator 1 "v9_register_comparison_operator"
-+ [(match_operand:DI 2 "register_operand" "r")
-+ (const_int 0)])
-+ (match_operand:I 3 "arith10_operand" "rM")
-+ (match_operand:I 4 "register_operand" "0")))]
-+ "TARGET_ARCH64"
-+ "movr%D1\t%2, %r3, %0"
-+ [(set_attr "type" "cmove")])
-+
-+(define_insn "*movsf_cc_v9"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (if_then_else:SF (match_operator 1 "icc_or_fcc_comparison_operator"
-+ [(match_operand 2 "icc_or_fcc_register_operand" "X")
-+ (const_int 0)])
-+ (match_operand:SF 3 "register_operand" "f")
-+ (match_operand:SF 4 "register_operand" "0")))]
-+ "TARGET_V9 && TARGET_FPU"
-+ "fmovs%C1\t%x2, %3, %0"
-+ [(set_attr "type" "fpcmove")])
-+
-+(define_insn "*movsf_cc_reg_sp64"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (if_then_else:SF (match_operator 1 "v9_register_comparison_operator"
-+ [(match_operand:DI 2 "register_operand" "r")
-+ (const_int 0)])
-+ (match_operand:SF 3 "register_operand" "f")
-+ (match_operand:SF 4 "register_operand" "0")))]
-+ "TARGET_ARCH64 && TARGET_FPU"
-+ "fmovrs%D1\t%2, %3, %0"
-+ [(set_attr "type" "fpcrmove")])
-+
-+;; Named because invoked by movtf_cc_v9
-+(define_insn "movdf_cc_v9"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (if_then_else:DF (match_operator 1 "icc_or_fcc_comparison_operator"
-+ [(match_operand 2 "icc_or_fcc_register_operand" "X")
-+ (const_int 0)])
-+ (match_operand:DF 3 "register_operand" "e")
-+ (match_operand:DF 4 "register_operand" "0")))]
-+ "TARGET_V9 && TARGET_FPU"
-+ "fmovd%C1\t%x2, %3, %0"
-+ [(set_attr "type" "fpcmove")
-+ (set_attr "fptype" "double")])
-+
-+;; Named because invoked by movtf_cc_reg_sp64
-+(define_insn "movdf_cc_reg_sp64"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (if_then_else:DF (match_operator 1 "v9_register_comparison_operator"
-+ [(match_operand:DI 2 "register_operand" "r")
-+ (const_int 0)])
-+ (match_operand:DF 3 "register_operand" "e")
-+ (match_operand:DF 4 "register_operand" "0")))]
-+ "TARGET_ARCH64 && TARGET_FPU"
-+ "fmovrd%D1\t%2, %3, %0"
-+ [(set_attr "type" "fpcrmove")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "*movtf_cc_hq_v9"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (if_then_else:TF (match_operator 1 "icc_or_fcc_comparison_operator"
-+ [(match_operand 2 "icc_or_fcc_register_operand" "X")
-+ (const_int 0)])
-+ (match_operand:TF 3 "register_operand" "e")
-+ (match_operand:TF 4 "register_operand" "0")))]
-+ "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
-+ "fmovq%C1\t%x2, %3, %0"
-+ [(set_attr "type" "fpcmove")])
-+
-+(define_insn "*movtf_cc_reg_hq_sp64"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (if_then_else:TF (match_operator 1 "v9_register_comparison_operator"
-+ [(match_operand:DI 2 "register_operand" "r")
-+ (const_int 0)])
-+ (match_operand:TF 3 "register_operand" "e")
-+ (match_operand:TF 4 "register_operand" "0")))]
-+ "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
-+ "fmovrq%D1\t%2, %3, %0"
-+ [(set_attr "type" "fpcrmove")])
-+
-+(define_insn_and_split "*movtf_cc_v9"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (if_then_else:TF (match_operator 1 "icc_or_fcc_comparison_operator"
-+ [(match_operand 2 "icc_or_fcc_register_operand" "X")
-+ (const_int 0)])
-+ (match_operand:TF 3 "register_operand" "e")
-+ (match_operand:TF 4 "register_operand" "0")))]
-+ "TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
-+ "#"
-+ "&& reload_completed"
-+ [(clobber (const_int 0))]
-+{
-+ rtx set_dest = operands[0];
-+ rtx set_srca = operands[3];
-+ rtx dest1, dest2;
-+ rtx srca1, srca2;
-+
-+ dest1 = gen_df_reg (set_dest, 0);
-+ dest2 = gen_df_reg (set_dest, 1);
-+ srca1 = gen_df_reg (set_srca, 0);
-+ srca2 = gen_df_reg (set_srca, 1);
-+
-+ if (reg_overlap_mentioned_p (dest1, srca2))
-+ {
-+ emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2],
-+ srca2, dest2));
-+ emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2],
-+ srca1, dest1));
-+ }
-+ else
-+ {
-+ emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2],
-+ srca1, dest1));
-+ emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2],
-+ srca2, dest2));
-+ }
-+ DONE;
-+}
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*movtf_cc_reg_sp64"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (if_then_else:TF (match_operator 1 "v9_register_comparison_operator"
-+ [(match_operand:DI 2 "register_operand" "r")
-+ (const_int 0)])
-+ (match_operand:TF 3 "register_operand" "e")
-+ (match_operand:TF 4 "register_operand" "0")))]
-+ "TARGET_ARCH64 && TARGET_FPU && !TARGET_HARD_QUAD"
-+ "#"
-+ "&& reload_completed"
-+ [(clobber (const_int 0))]
-+{
-+ rtx set_dest = operands[0];
-+ rtx set_srca = operands[3];
-+ rtx dest1, dest2;
-+ rtx srca1, srca2;
-+
-+ dest1 = gen_df_reg (set_dest, 0);
-+ dest2 = gen_df_reg (set_dest, 1);
-+ srca1 = gen_df_reg (set_srca, 0);
-+ srca2 = gen_df_reg (set_srca, 1);
-+
-+ if (reg_overlap_mentioned_p (dest1, srca2))
-+ {
-+ emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2],
-+ srca2, dest2));
-+ emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2],
-+ srca1, dest1));
-+ }
-+ else
-+ {
-+ emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2],
-+ srca1, dest1));
-+ emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2],
-+ srca2, dest2));
-+ }
-+ DONE;
-+}
-+ [(set_attr "length" "2")])
-+
-+
-+;; Zero-extension instructions
-+
-+;; These patterns originally accepted general_operands, however, slightly
-+;; better code is generated by only accepting register_operands, and then
-+;; letting combine generate the ldu[hb] insns.
-+
-+(define_expand "zero_extendhisi2"
-+ [(set (match_operand:SI 0 "register_operand" "")
-+ (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
-+ ""
-+{
-+ rtx temp = gen_reg_rtx (SImode);
-+ rtx shift_16 = GEN_INT (16);
-+ int op1_subbyte = 0;
-+
-+ if (GET_CODE (operand1) == SUBREG)
-+ {
-+ op1_subbyte = SUBREG_BYTE (operand1);
-+ op1_subbyte /= GET_MODE_SIZE (SImode);
-+ op1_subbyte *= GET_MODE_SIZE (SImode);
-+ operand1 = XEXP (operand1, 0);
-+ }
-+
-+ emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
-+ shift_16));
-+ emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
-+ DONE;
-+})
-+
-+(define_insn "*zero_extendhisi2_insn"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
-+ ""
-+ "lduh\t%1, %0"
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "regular")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_expand "zero_extendqihi2"
-+ [(set (match_operand:HI 0 "register_operand" "")
-+ (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
-+ ""
-+ "")
-+
-+(define_insn "*zero_extendqihi2_insn"
-+ [(set (match_operand:HI 0 "register_operand" "=r,r")
-+ (zero_extend:HI (match_operand:QI 1 "input_operand" "r,m")))]
-+ "GET_CODE (operands[1]) != CONST_INT"
-+ "@
-+ and\t%1, 0xff, %0
-+ ldub\t%1, %0"
-+ [(set_attr "type" "*,load")
-+ (set_attr "subtype" "*,regular")
-+ (set_attr "us3load_type" "*,3cycle")])
-+
-+(define_expand "zero_extendqisi2"
-+ [(set (match_operand:SI 0 "register_operand" "")
-+ (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
-+ ""
-+ "")
-+
-+(define_insn "*zero_extendqisi2_insn"
-+ [(set (match_operand:SI 0 "register_operand" "=r,r")
-+ (zero_extend:SI (match_operand:QI 1 "input_operand" "r,m")))]
-+ "GET_CODE (operands[1]) != CONST_INT"
-+ "@
-+ and\t%1, 0xff, %0
-+ ldub\t%1, %0"
-+ [(set_attr "type" "*,load")
-+ (set_attr "subtype" "*,regular")
-+ (set_attr "us3load_type" "*,3cycle")])
-+
-+(define_expand "zero_extendqidi2"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (zero_extend:DI (match_operand:QI 1 "register_operand" "")))]
-+ "TARGET_ARCH64"
-+ "")
-+
-+(define_insn "*zero_extendqidi2_insn"
-+ [(set (match_operand:DI 0 "register_operand" "=r,r")
-+ (zero_extend:DI (match_operand:QI 1 "input_operand" "r,m")))]
-+ "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
-+ "@
-+ and\t%1, 0xff, %0
-+ ldub\t%1, %0"
-+ [(set_attr "type" "*,load")
-+ (set_attr "subtype" "*,regular")
-+ (set_attr "us3load_type" "*,3cycle")])
-+
-+(define_expand "zero_extendhidi2"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (zero_extend:DI (match_operand:HI 1 "register_operand" "")))]
-+ "TARGET_ARCH64"
-+{
-+ rtx temp = gen_reg_rtx (DImode);
-+ rtx shift_48 = GEN_INT (48);
-+ int op1_subbyte = 0;
-+
-+ if (GET_CODE (operand1) == SUBREG)
-+ {
-+ op1_subbyte = SUBREG_BYTE (operand1);
-+ op1_subbyte /= GET_MODE_SIZE (DImode);
-+ op1_subbyte *= GET_MODE_SIZE (DImode);
-+ operand1 = XEXP (operand1, 0);
-+ }
-+
-+ emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
-+ shift_48));
-+ emit_insn (gen_lshrdi3 (operand0, temp, shift_48));
-+ DONE;
-+})
-+
-+(define_insn "*zero_extendhidi2_insn"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
-+ "TARGET_ARCH64"
-+ "lduh\t%1, %0"
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "regular")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+;; ??? Write truncdisi pattern using sra?
-+
-+(define_expand "zero_extendsidi2"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
-+ ""
-+ "")
-+
-+(define_insn "*zero_extendsidi2_insn_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r,r,r")
-+ (zero_extend:DI (match_operand:SI 1 "input_operand" "r,m,*f")))]
-+ "TARGET_ARCH64
-+ && GET_CODE (operands[1]) != CONST_INT"
-+ "@
-+ srl\t%1, 0, %0
-+ lduw\t%1, %0
-+ movstouw\t%1, %0"
-+ [(set_attr "type" "shift,load,vismv")
-+ (set_attr "subtype" "*,regular,movstouw")
-+ (set_attr "cpu_feature" "*,*,vis3")])
-+
-+(define_insn_and_split "*zero_extendsidi2_insn_sp32"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
-+ "TARGET_ARCH32"
-+ "#"
-+ "&& reload_completed"
-+ [(set (match_dup 2) (match_dup 1))
-+ (set (match_dup 3) (const_int 0))]
-+ "operands[2] = gen_lowpart (SImode, operands[0]);
-+ operands[3] = gen_highpart (SImode, operands[0]);"
-+ [(set_attr "length" "2")])
-+
-+;; Simplify comparisons of extended values.
-+
-+(define_insn "*cmp_zero_extendqisi2"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
-+ (const_int 0)))]
-+ ""
-+ "andcc\t%0, 0xff, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_zero_qi"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (match_operand:QI 0 "register_operand" "r")
-+ (const_int 0)))]
-+ ""
-+ "andcc\t%0, 0xff, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_zero_extendqisi2_set"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
-+ (const_int 0)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (zero_extend:SI (match_dup 1)))]
-+ ""
-+ "andcc\t%1, 0xff, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_zero_extendqisi2_andcc_set"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (and:SI (match_operand:SI 1 "register_operand" "r")
-+ (const_int 255))
-+ (const_int 0)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (zero_extend:SI (subreg:QI (match_dup 1) 0)))]
-+ ""
-+ "andcc\t%1, 0xff, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_zero_extendqidi2"
-+ [(set (reg:CCX CC_REG)
-+ (compare:CCX (zero_extend:DI (match_operand:QI 0 "register_operand" "r"))
-+ (const_int 0)))]
-+ "TARGET_ARCH64"
-+ "andcc\t%0, 0xff, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_zero_qi_sp64"
-+ [(set (reg:CCX CC_REG)
-+ (compare:CCX (match_operand:QI 0 "register_operand" "r")
-+ (const_int 0)))]
-+ "TARGET_ARCH64"
-+ "andcc\t%0, 0xff, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_zero_extendqidi2_set"
-+ [(set (reg:CCX CC_REG)
-+ (compare:CCX (zero_extend:DI (match_operand:QI 1 "register_operand" "r"))
-+ (const_int 0)))
-+ (set (match_operand:DI 0 "register_operand" "=r")
-+ (zero_extend:DI (match_dup 1)))]
-+ "TARGET_ARCH64"
-+ "andcc\t%1, 0xff, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_zero_extendqidi2_andcc_set"
-+ [(set (reg:CCX CC_REG)
-+ (compare:CCX (and:DI (match_operand:DI 1 "register_operand" "r")
-+ (const_int 255))
-+ (const_int 0)))
-+ (set (match_operand:DI 0 "register_operand" "=r")
-+ (zero_extend:DI (subreg:QI (match_dup 1) 0)))]
-+ "TARGET_ARCH64"
-+ "andcc\t%1, 0xff, %0"
-+ [(set_attr "type" "compare")])
-+
-+;; Similarly, handle {SI,DI}->QI mode truncation followed by a compare.
-+
-+(define_insn "*cmp_siqi_trunc"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 3)
-+ (const_int 0)))]
-+ ""
-+ "andcc\t%0, 0xff, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_siqi_trunc_set"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 3)
-+ (const_int 0)))
-+ (set (match_operand:QI 0 "register_operand" "=r")
-+ (subreg:QI (match_dup 1) 3))]
-+ ""
-+ "andcc\t%1, 0xff, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_diqi_trunc"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (subreg:QI (match_operand:DI 0 "register_operand" "r") 7)
-+ (const_int 0)))]
-+ "TARGET_ARCH64"
-+ "andcc\t%0, 0xff, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_diqi_trunc_set"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (subreg:QI (match_operand:DI 1 "register_operand" "r") 7)
-+ (const_int 0)))
-+ (set (match_operand:QI 0 "register_operand" "=r")
-+ (subreg:QI (match_dup 1) 7))]
-+ "TARGET_ARCH64"
-+ "andcc\t%1, 0xff, %0"
-+ [(set_attr "type" "compare")])
-+
-+
-+;; Sign-extension instructions
-+
-+;; These patterns originally accepted general_operands, however, slightly
-+;; better code is generated by only accepting register_operands, and then
-+;; letting combine generate the lds[hb] insns.
-+
-+(define_expand "extendhisi2"
-+ [(set (match_operand:SI 0 "register_operand" "")
-+ (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
-+ ""
-+{
-+ rtx temp = gen_reg_rtx (SImode);
-+ rtx shift_16 = GEN_INT (16);
-+ int op1_subbyte = 0;
-+
-+ if (GET_CODE (operand1) == SUBREG)
-+ {
-+ op1_subbyte = SUBREG_BYTE (operand1);
-+ op1_subbyte /= GET_MODE_SIZE (SImode);
-+ op1_subbyte *= GET_MODE_SIZE (SImode);
-+ operand1 = XEXP (operand1, 0);
-+ }
-+
-+ emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
-+ shift_16));
-+ emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
-+ DONE;
-+})
-+
-+(define_insn "*sign_extendhisi2_insn"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
-+ ""
-+ "ldsh\t%1, %0"
-+ [(set_attr "type" "sload")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_expand "extendqihi2"
-+ [(set (match_operand:HI 0 "register_operand" "")
-+ (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
-+ ""
-+{
-+ rtx temp = gen_reg_rtx (SImode);
-+ rtx shift_24 = GEN_INT (24);
-+ int op1_subbyte = 0;
-+ int op0_subbyte = 0;
-+
-+ if (GET_CODE (operand1) == SUBREG)
-+ {
-+ op1_subbyte = SUBREG_BYTE (operand1);
-+ op1_subbyte /= GET_MODE_SIZE (SImode);
-+ op1_subbyte *= GET_MODE_SIZE (SImode);
-+ operand1 = XEXP (operand1, 0);
-+ }
-+ if (GET_CODE (operand0) == SUBREG)
-+ {
-+ op0_subbyte = SUBREG_BYTE (operand0);
-+ op0_subbyte /= GET_MODE_SIZE (SImode);
-+ op0_subbyte *= GET_MODE_SIZE (SImode);
-+ operand0 = XEXP (operand0, 0);
-+ }
-+ emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
-+ shift_24));
-+ if (GET_MODE (operand0) != SImode)
-+ operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subbyte);
-+ emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
-+ DONE;
-+})
-+
-+(define_insn "*sign_extendqihi2_insn"
-+ [(set (match_operand:HI 0 "register_operand" "=r")
-+ (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
-+ ""
-+ "ldsb\t%1, %0"
-+ [(set_attr "type" "sload")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_expand "extendqisi2"
-+ [(set (match_operand:SI 0 "register_operand" "")
-+ (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
-+ ""
-+{
-+ rtx temp = gen_reg_rtx (SImode);
-+ rtx shift_24 = GEN_INT (24);
-+ int op1_subbyte = 0;
-+
-+ if (GET_CODE (operand1) == SUBREG)
-+ {
-+ op1_subbyte = SUBREG_BYTE (operand1);
-+ op1_subbyte /= GET_MODE_SIZE (SImode);
-+ op1_subbyte *= GET_MODE_SIZE (SImode);
-+ operand1 = XEXP (operand1, 0);
-+ }
-+
-+ emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
-+ shift_24));
-+ emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
-+ DONE;
-+})
-+
-+(define_insn "*sign_extendqisi2_insn"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
-+ ""
-+ "ldsb\t%1, %0"
-+ [(set_attr "type" "sload")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_expand "extendqidi2"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (sign_extend:DI (match_operand:QI 1 "register_operand" "")))]
-+ "TARGET_ARCH64"
-+{
-+ rtx temp = gen_reg_rtx (DImode);
-+ rtx shift_56 = GEN_INT (56);
-+ int op1_subbyte = 0;
-+
-+ if (GET_CODE (operand1) == SUBREG)
-+ {
-+ op1_subbyte = SUBREG_BYTE (operand1);
-+ op1_subbyte /= GET_MODE_SIZE (DImode);
-+ op1_subbyte *= GET_MODE_SIZE (DImode);
-+ operand1 = XEXP (operand1, 0);
-+ }
-+
-+ emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
-+ shift_56));
-+ emit_insn (gen_ashrdi3 (operand0, temp, shift_56));
-+ DONE;
-+})
-+
-+(define_insn "*sign_extendqidi2_insn"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
-+ "TARGET_ARCH64"
-+ "ldsb\t%1, %0"
-+ [(set_attr "type" "sload")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_expand "extendhidi2"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (sign_extend:DI (match_operand:HI 1 "register_operand" "")))]
-+ "TARGET_ARCH64"
-+{
-+ rtx temp = gen_reg_rtx (DImode);
-+ rtx shift_48 = GEN_INT (48);
-+ int op1_subbyte = 0;
-+
-+ if (GET_CODE (operand1) == SUBREG)
-+ {
-+ op1_subbyte = SUBREG_BYTE (operand1);
-+ op1_subbyte /= GET_MODE_SIZE (DImode);
-+ op1_subbyte *= GET_MODE_SIZE (DImode);
-+ operand1 = XEXP (operand1, 0);
-+ }
-+
-+ emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
-+ shift_48));
-+ emit_insn (gen_ashrdi3 (operand0, temp, shift_48));
-+ DONE;
-+})
-+
-+(define_insn "*sign_extendhidi2_insn"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
-+ "TARGET_ARCH64"
-+ "ldsh\t%1, %0"
-+ [(set_attr "type" "sload")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_expand "extendsidi2"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (sign_extend:DI (match_operand:SI 1 "register_operand" "")))]
-+ "TARGET_ARCH64"
-+ "")
-+
-+(define_insn "*sign_extendsidi2_insn"
-+ [(set (match_operand:DI 0 "register_operand" "=r,r,r")
-+ (sign_extend:DI (match_operand:SI 1 "input_operand" "r,m,*f")))]
-+ "TARGET_ARCH64"
-+ "@
-+ sra\t%1, 0, %0
-+ ldsw\t%1, %0
-+ movstosw\t%1, %0"
-+ [(set_attr "type" "shift,sload,vismv")
-+ (set_attr "us3load_type" "*,3cycle,*")
-+ (set_attr "cpu_feature" "*,*,vis3")])
-+
-+
-+;; Special pattern for optimizing bit-field compares. This is needed
-+;; because combine uses this as a canonical form.
-+
-+(define_insn "*cmp_zero_extract"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC
-+ (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
-+ (match_operand:SI 1 "small_int_operand" "I")
-+ (match_operand:SI 2 "small_int_operand" "I"))
-+ (const_int 0)))]
-+ "INTVAL (operands[2]) > 19"
-+{
-+ int len = INTVAL (operands[1]);
-+ int pos = 32 - INTVAL (operands[2]) - len;
-+ HOST_WIDE_INT mask = ((1 << len) - 1) << pos;
-+ operands[1] = GEN_INT (mask);
-+ return "andcc\t%0, %1, %%g0";
-+}
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_zero_extract_sp64"
-+ [(set (reg:CCX CC_REG)
-+ (compare:CCX
-+ (zero_extract:DI (match_operand:DI 0 "register_operand" "r")
-+ (match_operand:SI 1 "small_int_operand" "I")
-+ (match_operand:SI 2 "small_int_operand" "I"))
-+ (const_int 0)))]
-+ "TARGET_ARCH64 && INTVAL (operands[2]) > 51"
-+{
-+ int len = INTVAL (operands[1]);
-+ int pos = 64 - INTVAL (operands[2]) - len;
-+ HOST_WIDE_INT mask = (((unsigned HOST_WIDE_INT) 1 << len) - 1) << pos;
-+ operands[1] = GEN_INT (mask);
-+ return "andcc\t%0, %1, %%g0";
-+}
-+ [(set_attr "type" "compare")])
-+
-+
-+;; Conversions between float, double and long double.
-+
-+(define_insn "extendsfdf2"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
-+ "TARGET_FPU"
-+ "fstod\t%1, %0"
-+ [(set_attr "type" "fp")
-+ (set_attr "fptype" "double")])
-+
-+(define_expand "extendsftf2"
-+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
-+ (float_extend:TF (match_operand:SF 1 "register_operand" "")))]
-+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-+ "emit_tfmode_cvt (FLOAT_EXTEND, operands); DONE;")
-+
-+(define_insn "*extendsftf2_hq"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (float_extend:TF (match_operand:SF 1 "register_operand" "f")))]
-+ "TARGET_FPU && TARGET_HARD_QUAD"
-+ "fstoq\t%1, %0"
-+ [(set_attr "type" "fp")])
-+
-+(define_expand "extenddftf2"
-+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
-+ (float_extend:TF (match_operand:DF 1 "register_operand" "")))]
-+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-+ "emit_tfmode_cvt (FLOAT_EXTEND, operands); DONE;")
-+
-+(define_insn "*extenddftf2_hq"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (float_extend:TF (match_operand:DF 1 "register_operand" "e")))]
-+ "TARGET_FPU && TARGET_HARD_QUAD"
-+ "fdtoq\t%1, %0"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "truncdfsf2"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (float_truncate:SF (match_operand:DF 1 "register_operand" "e")))]
-+ "TARGET_FPU"
-+ "fdtos\t%1, %0"
-+ [(set_attr "type" "fp")
-+ (set_attr "fptype" "double")
-+ (set_attr "fptype_ut699" "single")])
-+
-+(define_expand "trunctfsf2"
-+ [(set (match_operand:SF 0 "register_operand" "")
-+ (float_truncate:SF (match_operand:TF 1 "general_operand" "")))]
-+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-+ "emit_tfmode_cvt (FLOAT_TRUNCATE, operands); DONE;")
-+
-+(define_insn "*trunctfsf2_hq"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (float_truncate:SF (match_operand:TF 1 "register_operand" "e")))]
-+ "TARGET_FPU && TARGET_HARD_QUAD"
-+ "fqtos\t%1, %0"
-+ [(set_attr "type" "fp")])
-+
-+(define_expand "trunctfdf2"
-+ [(set (match_operand:DF 0 "register_operand" "")
-+ (float_truncate:DF (match_operand:TF 1 "general_operand" "")))]
-+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-+ "emit_tfmode_cvt (FLOAT_TRUNCATE, operands); DONE;")
-+
-+(define_insn "*trunctfdf2_hq"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (float_truncate:DF (match_operand:TF 1 "register_operand" "e")))]
-+ "TARGET_FPU && TARGET_HARD_QUAD"
-+ "fqtod\t%1, %0"
-+ [(set_attr "type" "fp")])
-+
-+
-+;; Conversion between fixed point and floating point.
-+
-+(define_insn "floatsisf2"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (float:SF (match_operand:SI 1 "register_operand" "f")))]
-+ "TARGET_FPU"
-+ "fitos\t%1, %0"
-+ [(set_attr "type" "fp")
-+ (set_attr "fptype" "single")])
-+
-+(define_insn "floatsidf2"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (float:DF (match_operand:SI 1 "register_operand" "f")))]
-+ "TARGET_FPU"
-+ "fitod\t%1, %0"
-+ [(set_attr "type" "fp")
-+ (set_attr "fptype" "double")])
-+
-+(define_expand "floatsitf2"
-+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
-+ (float:TF (match_operand:SI 1 "register_operand" "")))]
-+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-+ "emit_tfmode_cvt (FLOAT, operands); DONE;")
-+
-+(define_insn "*floatsitf2_hq"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (float:TF (match_operand:SI 1 "register_operand" "f")))]
-+ "TARGET_FPU && TARGET_HARD_QUAD"
-+ "fitoq\t%1, %0"
-+ [(set_attr "type" "fp")])
-+
-+(define_expand "floatunssitf2"
-+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
-+ (unsigned_float:TF (match_operand:SI 1 "register_operand" "")))]
-+ "TARGET_FPU && TARGET_ARCH64 && !TARGET_HARD_QUAD"
-+ "emit_tfmode_cvt (UNSIGNED_FLOAT, operands); DONE;")
-+
-+;; Now the same for 64 bit sources.
-+
-+(define_insn "floatdisf2"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (float:SF (match_operand:DI 1 "register_operand" "e")))]
-+ "TARGET_V9 && TARGET_FPU"
-+ "fxtos\t%1, %0"
-+ [(set_attr "type" "fp")
-+ (set_attr "fptype" "double")])
-+
-+(define_expand "floatunsdisf2"
-+ [(use (match_operand:SF 0 "register_operand" ""))
-+ (use (match_operand:DI 1 "general_operand" ""))]
-+ "TARGET_ARCH64 && TARGET_FPU"
-+ "sparc_emit_floatunsdi (operands, SFmode); DONE;")
-+
-+(define_insn "floatdidf2"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (float:DF (match_operand:DI 1 "register_operand" "e")))]
-+ "TARGET_V9 && TARGET_FPU"
-+ "fxtod\t%1, %0"
-+ [(set_attr "type" "fp")
-+ (set_attr "fptype" "double")])
-+
-+(define_expand "floatunsdidf2"
-+ [(use (match_operand:DF 0 "register_operand" ""))
-+ (use (match_operand:DI 1 "general_operand" ""))]
-+ "TARGET_ARCH64 && TARGET_FPU"
-+ "sparc_emit_floatunsdi (operands, DFmode); DONE;")
-+
-+(define_expand "floatditf2"
-+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
-+ (float:TF (match_operand:DI 1 "register_operand" "")))]
-+ "TARGET_FPU && TARGET_V9 && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-+ "emit_tfmode_cvt (FLOAT, operands); DONE;")
-+
-+(define_insn "*floatditf2_hq"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (float:TF (match_operand:DI 1 "register_operand" "e")))]
-+ "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
-+ "fxtoq\t%1, %0"
-+ [(set_attr "type" "fp")])
-+
-+(define_expand "floatunsditf2"
-+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
-+ (unsigned_float:TF (match_operand:DI 1 "register_operand" "")))]
-+ "TARGET_FPU && TARGET_ARCH64 && !TARGET_HARD_QUAD"
-+ "emit_tfmode_cvt (UNSIGNED_FLOAT, operands); DONE;")
-+
-+;; Convert a float to an actual integer.
-+;; Truncation is performed as part of the conversion.
-+
-+(define_insn "fix_truncsfsi2"
-+ [(set (match_operand:SI 0 "register_operand" "=f")
-+ (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
-+ "TARGET_FPU"
-+ "fstoi\t%1, %0"
-+ [(set_attr "type" "fp")
-+ (set_attr "fptype" "single")])
-+
-+(define_insn "fix_truncdfsi2"
-+ [(set (match_operand:SI 0 "register_operand" "=f")
-+ (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
-+ "TARGET_FPU"
-+ "fdtoi\t%1, %0"
-+ [(set_attr "type" "fp")
-+ (set_attr "fptype" "double")
-+ (set_attr "fptype_ut699" "single")])
-+
-+(define_expand "fix_trunctfsi2"
-+ [(set (match_operand:SI 0 "register_operand" "")
-+ (fix:SI (match_operand:TF 1 "general_operand" "")))]
-+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-+ "emit_tfmode_cvt (FIX, operands); DONE;")
-+
-+(define_insn "*fix_trunctfsi2_hq"
-+ [(set (match_operand:SI 0 "register_operand" "=f")
-+ (fix:SI (match_operand:TF 1 "register_operand" "e")))]
-+ "TARGET_FPU && TARGET_HARD_QUAD"
-+ "fqtoi\t%1, %0"
-+ [(set_attr "type" "fp")])
-+
-+(define_expand "fixuns_trunctfsi2"
-+ [(set (match_operand:SI 0 "register_operand" "")
-+ (unsigned_fix:SI (match_operand:TF 1 "general_operand" "")))]
-+ "TARGET_FPU && TARGET_ARCH64 && !TARGET_HARD_QUAD"
-+ "emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
-+
-+;; Now the same, for V9 targets
-+
-+(define_insn "fix_truncsfdi2"
-+ [(set (match_operand:DI 0 "register_operand" "=e")
-+ (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
-+ "TARGET_V9 && TARGET_FPU"
-+ "fstox\t%1, %0"
-+ [(set_attr "type" "fp")
-+ (set_attr "fptype" "double")])
-+
-+(define_expand "fixuns_truncsfdi2"
-+ [(use (match_operand:DI 0 "register_operand" ""))
-+ (use (match_operand:SF 1 "general_operand" ""))]
-+ "TARGET_ARCH64 && TARGET_FPU"
-+ "sparc_emit_fixunsdi (operands, SFmode); DONE;")
-+
-+(define_insn "fix_truncdfdi2"
-+ [(set (match_operand:DI 0 "register_operand" "=e")
-+ (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
-+ "TARGET_V9 && TARGET_FPU"
-+ "fdtox\t%1, %0"
-+ [(set_attr "type" "fp")
-+ (set_attr "fptype" "double")])
-+
-+(define_expand "fixuns_truncdfdi2"
-+ [(use (match_operand:DI 0 "register_operand" ""))
-+ (use (match_operand:DF 1 "general_operand" ""))]
-+ "TARGET_ARCH64 && TARGET_FPU"
-+ "sparc_emit_fixunsdi (operands, DFmode); DONE;")
-+
-+(define_expand "fix_trunctfdi2"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (fix:DI (match_operand:TF 1 "general_operand" "")))]
-+ "TARGET_V9 && TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-+ "emit_tfmode_cvt (FIX, operands); DONE;")
-+
-+(define_insn "*fix_trunctfdi2_hq"
-+ [(set (match_operand:DI 0 "register_operand" "=e")
-+ (fix:DI (match_operand:TF 1 "register_operand" "e")))]
-+ "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
-+ "fqtox\t%1, %0"
-+ [(set_attr "type" "fp")])
-+
-+(define_expand "fixuns_trunctfdi2"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (unsigned_fix:DI (match_operand:TF 1 "general_operand" "")))]
-+ "TARGET_FPU && TARGET_ARCH64 && !TARGET_HARD_QUAD"
-+ "emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
-+
-+
-+;; Integer addition/subtraction instructions.
-+
-+(define_expand "adddi3"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (plus:DI (match_operand:DI 1 "register_operand" "")
-+ (match_operand:DI 2 "arith_double_add_operand" "")))]
-+ ""
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_adddi3_sp32 (operands[0], operands[1], operands[2]));
-+ DONE;
-+ }
-+})
-+
-+;; Turning an add/sub instruction into the other changes the Carry flag
-+;; so the 4096 trick cannot be used for operations in CCXCmode.
-+
-+(define_expand "uaddvdi4"
-+ [(parallel [(set (reg:CCXC CC_REG)
-+ (compare:CCXC (plus:DI (match_operand:DI 1 "register_operand")
-+ (match_operand:DI 2 "arith_double_operand"))
-+ (match_dup 1)))
-+ (set (match_operand:DI 0 "register_operand")
-+ (plus:DI (match_dup 1) (match_dup 2)))])
-+ (set (pc) (if_then_else (ltu (reg:CCXC CC_REG) (const_int 0))
-+ (label_ref (match_operand 3))
-+ (pc)))]
-+ ""
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_uaddvdi4_sp32 (operands[0], operands[1], operands[2]));
-+ rtx x = gen_rtx_LTU (VOIDmode, gen_rtx_REG (CCCmode, SPARC_ICC_REG),
-+ const0_rtx);
-+ emit_jump_insn (gen_cbranchcc4 (x, XEXP (x, 0), XEXP (x, 1), operands[3]));
-+ DONE;
-+ }
-+})
-+
-+;; Turning an add/sub instruction into the other does not change the Overflow
-+;; flag so the 4096 trick can be used for operations in CCXVmode.
-+
-+(define_expand "addvdi4"
-+ [(parallel [(set (reg:CCXV CC_REG)
-+ (compare:CCXV (plus:DI (match_operand:DI 1 "register_operand")
-+ (match_operand:DI 2 "arith_double_add_operand"))
-+ (unspec:DI [(match_dup 1) (match_dup 2)]
-+ UNSPEC_ADDV)))
-+ (set (match_operand:DI 0 "register_operand")
-+ (plus:DI (match_dup 1) (match_dup 2)))])
-+ (set (pc) (if_then_else (ne (reg:CCXV CC_REG) (const_int 0))
-+ (label_ref (match_operand 3))
-+ (pc)))]
-+ ""
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_addvdi4_sp32 (operands[0], operands[1], operands[2]));
-+ rtx x = gen_rtx_NE (VOIDmode, gen_rtx_REG (CCVmode, SPARC_ICC_REG),
-+ const0_rtx);
-+ emit_jump_insn (gen_cbranchcc4 (x, XEXP (x, 0), XEXP (x, 1), operands[3]));
-+ DONE;
-+ }
-+})
-+
-+(define_insn_and_split "adddi3_sp32"
-+ [(set (match_operand:DI 0 "register_operand" "=&r")
-+ (plus:DI (match_operand:DI 1 "register_operand" "%r")
-+ (match_operand:DI 2 "arith_double_operand" "rHI")))
-+ (clobber (reg:CC CC_REG))]
-+ "TARGET_ARCH32"
-+ "#"
-+ "&& reload_completed"
-+ [(parallel [(set (reg:CCC CC_REG)
-+ (compare:CCC (plus:SI (match_dup 4) (match_dup 5))
-+ (match_dup 4)))
-+ (set (match_dup 3)
-+ (plus:SI (match_dup 4) (match_dup 5)))])
-+ (set (match_dup 6)
-+ (plus:SI (plus:SI (match_dup 7) (match_dup 8))
-+ (ltu:SI (reg:CCC CC_REG) (const_int 0))))]
-+{
-+ operands[3] = gen_lowpart (SImode, operands[0]);
-+ operands[4] = gen_lowpart (SImode, operands[1]);
-+ operands[5] = gen_lowpart (SImode, operands[2]);
-+ operands[6] = gen_highpart (SImode, operands[0]);
-+ operands[7] = gen_highpart_mode (SImode, DImode, operands[1]);
-+ operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
-+}
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "uaddvdi4_sp32"
-+ [(set (reg:CCC CC_REG)
-+ (compare:CCC (plus:DI (match_operand:DI 1 "register_operand" "%r")
-+ (match_operand:DI 2 "arith_double_operand" "rHI"))
-+ (match_dup 1)))
-+ (set (match_operand:DI 0 "register_operand" "=&r")
-+ (plus:DI (match_dup 1) (match_dup 2)))]
-+ "TARGET_ARCH32"
-+ "#"
-+ "&& reload_completed"
-+ [(parallel [(set (reg:CCC CC_REG)
-+ (compare:CCC (plus:SI (match_dup 4) (match_dup 5))
-+ (match_dup 4)))
-+ (set (match_dup 3)
-+ (plus:SI (match_dup 4) (match_dup 5)))])
-+ (parallel [(set (reg:CCC CC_REG)
-+ (compare:CCC (zero_extend:DI
-+ (plus:SI (plus:SI (match_dup 7) (match_dup 8))
-+ (ltu:SI (reg:CCC CC_REG)
-+ (const_int 0))))
-+ (plus:DI (plus:DI (zero_extend:DI (match_dup 7))
-+ (zero_extend:DI (match_dup 8)))
-+ (ltu:DI (reg:CCC CC_REG)
-+ (const_int 0)))))
-+ (set (match_dup 6)
-+ (plus:SI (plus:SI (match_dup 7) (match_dup 8))
-+ (ltu:SI (reg:CCC CC_REG)
-+ (const_int 0))))])]
-+{
-+ operands[3] = gen_lowpart (SImode, operands[0]);
-+ operands[4] = gen_lowpart (SImode, operands[1]);
-+ operands[5] = gen_lowpart (SImode, operands[2]);
-+ operands[6] = gen_highpart (SImode, operands[0]);
-+ operands[7] = gen_highpart_mode (SImode, DImode, operands[1]);
-+ operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
-+}
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "addvdi4_sp32"
-+ [(set (reg:CCV CC_REG)
-+ (compare:CCV (plus:DI (match_operand:DI 1 "register_operand" "%r")
-+ (match_operand:DI 2 "arith_double_operand" "rHI"))
-+ (unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_ADDV)))
-+ (set (match_operand:DI 0 "register_operand" "=&r")
-+ (plus:DI (match_dup 1) (match_dup 2)))]
-+ "TARGET_ARCH32"
-+ "#"
-+ "&& reload_completed"
-+ [(parallel [(set (reg:CCC CC_REG)
-+ (compare:CCC (plus:SI (match_dup 4) (match_dup 5))
-+ (match_dup 4)))
-+ (set (match_dup 3)
-+ (plus:SI (match_dup 4) (match_dup 5)))])
-+ (parallel [(set (reg:CCV CC_REG)
-+ (compare:CCV (plus:SI (plus:SI (match_dup 7) (match_dup 8))
-+ (ltu:SI (reg:CCC CC_REG)
-+ (const_int 0)))
-+ (unspec:SI [(plus:SI (match_dup 7) (match_dup 8))
-+ (ltu:SI (reg:CCC CC_REG)
-+ (const_int 0))]
-+ UNSPEC_ADDV)))
-+ (set (match_dup 6)
-+ (plus:SI (plus:SI (match_dup 7) (match_dup 8))
-+ (ltu:SI (reg:CCC CC_REG) (const_int 0))))])]
-+{
-+ operands[3] = gen_lowpart (SImode, operands[0]);
-+ operands[4] = gen_lowpart (SImode, operands[1]);
-+ operands[5] = gen_lowpart (SImode, operands[2]);
-+ operands[6] = gen_highpart (SImode, operands[0]);
-+ operands[7] = gen_highpart_mode (SImode, DImode, operands[1]);
-+ operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
-+}
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*addx_extend_sp32"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (zero_extend:DI (plus:SI (plus:SI
-+ (match_operand:SI 1 "register_operand" "%r")
-+ (match_operand:SI 2 "arith_operand" "rI"))
-+ (ltu:SI (reg:CCC CC_REG) (const_int 0)))))]
-+ "TARGET_ARCH32"
-+ "#"
-+ "&& reload_completed"
-+ [(set (match_dup 3) (plus:SI (plus:SI (match_dup 1) (match_dup 2))
-+ (ltu:SI (reg:CCC CC_REG) (const_int 0))))
-+ (set (match_dup 4) (const_int 0))]
-+ "operands[3] = gen_lowpart (SImode, operands[0]);
-+ operands[4] = gen_highpart (SImode, operands[0]);"
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*adddi3_extend_sp32"
-+ [(set (match_operand:DI 0 "register_operand" "=&r")
-+ (plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
-+ (match_operand:DI 2 "register_operand" "r")))
-+ (clobber (reg:CC CC_REG))]
-+ "TARGET_ARCH32"
-+ "#"
-+ "&& reload_completed"
-+ [(parallel [(set (reg:CCC CC_REG)
-+ (compare:CCC (plus:SI (match_dup 3) (match_dup 1))
-+ (match_dup 3)))
-+ (set (match_dup 5) (plus:SI (match_dup 3) (match_dup 1)))])
-+ (set (match_dup 6)
-+ (plus:SI (plus:SI (match_dup 4) (const_int 0))
-+ (ltu:SI (reg:CCC CC_REG) (const_int 0))))]
-+ "operands[3] = gen_lowpart (SImode, operands[2]);
-+ operands[4] = gen_highpart (SImode, operands[2]);
-+ operands[5] = gen_lowpart (SImode, operands[0]);
-+ operands[6] = gen_highpart (SImode, operands[0]);"
-+ [(set_attr "length" "2")])
-+
-+(define_insn "*adddi3_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r,r")
-+ (plus:DI (match_operand:DI 1 "register_operand" "%r,r")
-+ (match_operand:DI 2 "arith_add_operand" "rI,O")))]
-+ "TARGET_ARCH64"
-+ "@
-+ add\t%1, %2, %0
-+ sub\t%1, -%2, %0")
-+
-+(define_insn "addsi3"
-+ [(set (match_operand:SI 0 "register_operand" "=r,r")
-+ (plus:SI (match_operand:SI 1 "register_operand" "%r,r")
-+ (match_operand:SI 2 "arith_add_operand" "rI,O")))]
-+ ""
-+ "@
-+ add\t%1, %2, %0
-+ sub\t%1, -%2, %0")
-+
-+;; Turning an add/sub instruction into the other changes the Carry flag
-+;; so the 4096 trick cannot be used for operations in CCCmode.
-+
-+(define_expand "uaddvsi4"
-+ [(parallel [(set (reg:CCC CC_REG)
-+ (compare:CCC (plus:SI (match_operand:SI 1 "register_operand")
-+ (match_operand:SI 2 "arith_operand"))
-+ (match_dup 1)))
-+ (set (match_operand:SI 0 "register_operand")
-+ (plus:SI (match_dup 1) (match_dup 2)))])
-+ (set (pc) (if_then_else (ltu (reg:CCC CC_REG) (const_int 0))
-+ (label_ref (match_operand 3))
-+ (pc)))]
-+ "")
-+
-+;; Turning an add/sub instruction into the other does not change the Overflow
-+;; flag so the 4096 trick can be used for operations in CCVmode.
-+
-+(define_expand "addvsi4"
-+ [(parallel [(set (reg:CCV CC_REG)
-+ (compare:CCV (plus:SI (match_operand:SI 1 "register_operand")
-+ (match_operand:SI 2 "arith_add_operand"))
-+ (unspec:SI [(match_dup 1) (match_dup 2)]
-+ UNSPEC_ADDV)))
-+ (set (match_operand:SI 0 "register_operand")
-+ (plus:SI (match_dup 1) (match_dup 2)))])
-+ (set (pc) (if_then_else (ne (reg:CCV CC_REG) (const_int 0))
-+ (label_ref (match_operand 3))
-+ (pc)))]
-+ "")
-+
-+(define_insn "*cmp_ccnz_plus"
-+ [(set (reg:CCNZ CC_REG)
-+ (compare:CCNZ (plus:SI (match_operand:SI 0 "register_operand" "%r")
-+ (match_operand:SI 1 "arith_operand" "rI"))
-+ (const_int 0)))]
-+ ""
-+ "addcc\t%0, %1, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccxnz_plus"
-+ [(set (reg:CCXNZ CC_REG)
-+ (compare:CCXNZ (plus:DI (match_operand:DI 0 "register_operand" "%r")
-+ (match_operand:DI 1 "arith_operand" "rI"))
-+ (const_int 0)))]
-+ "TARGET_ARCH64"
-+ "addcc\t%0, %1, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccnz_plus_set"
-+ [(set (reg:CCNZ CC_REG)
-+ (compare:CCNZ (plus:SI (match_operand:SI 1 "register_operand" "%r")
-+ (match_operand:SI 2 "arith_operand" "rI"))
-+ (const_int 0)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (plus:SI (match_dup 1) (match_dup 2)))]
-+ ""
-+ "addcc\t%1, %2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccxnz_plus_set"
-+ [(set (reg:CCXNZ CC_REG)
-+ (compare:CCXNZ (plus:DI (match_operand:DI 1 "register_operand" "%r")
-+ (match_operand:DI 2 "arith_operand" "rI"))
-+ (const_int 0)))
-+ (set (match_operand:DI 0 "register_operand" "=r")
-+ (plus:DI (match_dup 1) (match_dup 2)))]
-+ "TARGET_ARCH64"
-+ "addcc\t%1, %2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccc_plus"
-+ [(set (reg:CCC CC_REG)
-+ (compare:CCC (plus:SI (match_operand:SI 0 "register_operand" "%r")
-+ (match_operand:SI 1 "arith_operand" "rI"))
-+ (match_dup 0)))]
-+ ""
-+ "addcc\t%0, %1, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccxc_plus"
-+ [(set (reg:CCXC CC_REG)
-+ (compare:CCXC (plus:DI (match_operand:DI 0 "register_operand" "%r")
-+ (match_operand:DI 1 "arith_operand" "rI"))
-+ (match_dup 0)))]
-+ "TARGET_ARCH64"
-+ "addcc\t%0, %1, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccc_plus_set"
-+ [(set (reg:CCC CC_REG)
-+ (compare:CCC (plus:SI (match_operand:SI 1 "register_operand" "%r")
-+ (match_operand:SI 2 "arith_operand" "rI"))
-+ (match_dup 1)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (plus:SI (match_dup 1) (match_dup 2)))]
-+ ""
-+ "addcc\t%1, %2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccxc_plus_set"
-+ [(set (reg:CCXC CC_REG)
-+ (compare:CCXC (plus:DI (match_operand:DI 1 "register_operand" "%r")
-+ (match_operand:DI 2 "arith_operand" "rI"))
-+ (match_dup 1)))
-+ (set (match_operand:DI 0 "register_operand" "=r")
-+ (plus:DI (match_dup 1) (match_dup 2)))]
-+ "TARGET_ARCH64"
-+ "addcc\t%1, %2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccc_plus_sltu_set"
-+ [(set (reg:CCC CC_REG)
-+ (compare:CCC (zero_extend:DI
-+ (plus:SI
-+ (plus:SI (match_operand:SI 1 "register_operand" "%r")
-+ (match_operand:SI 2 "arith_operand" "rI"))
-+ (ltu:SI (reg:CCC CC_REG) (const_int 0))))
-+ (plus:DI (plus:DI (zero_extend:DI (match_dup 1))
-+ (zero_extend:DI (match_dup 2)))
-+ (ltu:DI (reg:CCC CC_REG) (const_int 0)))))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (plus:SI (plus:SI (match_dup 1) (match_dup 2))
-+ (ltu:SI (reg:CCC CC_REG) (const_int 0))))]
-+ ""
-+ "addxcc\t%1, %2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccv_plus"
-+ [(set (reg:CCV CC_REG)
-+ (compare:CCV (plus:SI (match_operand:SI 0 "register_operand" "%r,r")
-+ (match_operand:SI 1 "arith_add_operand" "rI,O"))
-+ (unspec:SI [(match_dup 0) (match_dup 1)] UNSPEC_ADDV)))]
-+ ""
-+ "@
-+ addcc\t%0, %1, %%g0
-+ subcc\t%0, -%1, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccxv_plus"
-+ [(set (reg:CCXV CC_REG)
-+ (compare:CCXV (plus:DI (match_operand:DI 0 "register_operand" "%r,r")
-+ (match_operand:DI 1 "arith_add_operand" "rI,O"))
-+ (unspec:DI [(match_dup 0) (match_dup 1)] UNSPEC_ADDV)))]
-+ "TARGET_ARCH64"
-+ "@
-+ addcc\t%0, %1, %%g0
-+ subcc\t%0, -%1, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccv_plus_set"
-+ [(set (reg:CCV CC_REG)
-+ (compare:CCV (plus:SI (match_operand:SI 1 "register_operand" "%r,r")
-+ (match_operand:SI 2 "arith_add_operand" "rI,O"))
-+ (unspec:SI [(match_dup 1) (match_dup 2)] UNSPEC_ADDV)))
-+ (set (match_operand:SI 0 "register_operand" "=r,r")
-+ (plus:SI (match_dup 1) (match_dup 2)))]
-+ ""
-+ "@
-+ addcc\t%1, %2, %0
-+ subcc\t%1, -%2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccxv_plus_set"
-+ [(set (reg:CCXV CC_REG)
-+ (compare:CCXV (plus:DI (match_operand:DI 1 "register_operand" "%r,r")
-+ (match_operand:DI 2 "arith_add_operand" "rI,O"))
-+ (unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_ADDV)))
-+ (set (match_operand:DI 0 "register_operand" "=r,r")
-+ (plus:DI (match_dup 1) (match_dup 2)))]
-+ "TARGET_ARCH64"
-+ "@
-+ addcc\t%1, %2, %0
-+ subcc\t%1, -%2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccv_plus_sltu_set"
-+ [(set (reg:CCV CC_REG)
-+ (compare:CCV (plus:SI (plus:SI (match_operand:SI 1 "register_operand" "%r")
-+ (match_operand:SI 2 "arith_operand" "rI"))
-+ (ltu:SI (reg:CCC CC_REG) (const_int 0)))
-+ (unspec:SI [(plus:SI (match_dup 1) (match_dup 2))
-+ (ltu:SI (reg:CCC CC_REG) (const_int 0))]
-+ UNSPEC_ADDV)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (plus:SI (plus:SI (match_dup 1) (match_dup 2))
-+ (ltu:SI (reg:CCC CC_REG) (const_int 0))))]
-+ ""
-+ "addxcc\t%1, %2, %0"
-+ [(set_attr "type" "compare")])
-+
-+
-+(define_expand "subdi3"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (minus:DI (match_operand:DI 1 "register_operand" "")
-+ (match_operand:DI 2 "arith_double_add_operand" "")))]
-+ ""
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_subdi3_sp32 (operands[0], operands[1], operands[2]));
-+ DONE;
-+ }
-+})
-+
-+;; Turning an add/sub instruction into the other changes the Carry flag
-+;; so the 4096 trick cannot be used for operations in CCXmode.
-+
-+(define_expand "usubvdi4"
-+ [(parallel [(set (reg:CCX CC_REG)
-+ (compare:CCX (match_operand:DI 1 "register_or_zero_operand")
-+ (match_operand:DI 2 "arith_double_operand")))
-+ (set (match_operand:DI 0 "register_operand")
-+ (minus:DI (match_dup 1) (match_dup 2)))])
-+ (set (pc) (if_then_else (ltu (reg:CCX CC_REG) (const_int 0))
-+ (label_ref (match_operand 3))
-+ (pc)))]
-+ ""
-+{
-+ if (operands[1] == const0_rtx)
-+ {
-+ emit_insn (gen_unegvdi3 (operands[0], operands[2], operands[3]));
-+ DONE;
-+ }
-+
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_usubvdi4_sp32 (operands[0], operands[1], operands[2]));
-+ rtx x = gen_rtx_LTU (VOIDmode, gen_rtx_REG (CCCmode, SPARC_ICC_REG),
-+ const0_rtx);
-+ emit_jump_insn (gen_cbranchcc4 (x, XEXP (x, 0), XEXP (x, 1), operands[3]));
-+ DONE;
-+ }
-+})
-+
-+;; Turning an add/sub instruction into the other does not change the Overflow
-+;; flag so the 4096 trick can be used for operations in CCXVmode.
-+
-+(define_expand "subvdi4"
-+ [(parallel [(set (reg:CCXV CC_REG)
-+ (compare:CCXV (minus:DI (match_operand:DI 1 "register_operand")
-+ (match_operand:DI 2 "arith_double_add_operand"))
-+ (unspec:DI [(match_dup 1) (match_dup 2)]
-+ UNSPEC_SUBV)))
-+ (set (match_operand:DI 0 "register_operand")
-+ (minus:DI (match_dup 1) (match_dup 2)))])
-+ (set (pc) (if_then_else (ne (reg:CCXV CC_REG) (const_int 0))
-+ (label_ref (match_operand 3))
-+ (pc)))]
-+ ""
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_subvdi4_sp32 (operands[0], operands[1], operands[2]));
-+ rtx x = gen_rtx_NE (VOIDmode, gen_rtx_REG (CCVmode, SPARC_ICC_REG),
-+ const0_rtx);
-+ emit_jump_insn (gen_cbranchcc4 (x, XEXP (x, 0), XEXP (x, 1), operands[3]));
-+ DONE;
-+ }
-+})
-+
-+(define_insn_and_split "subdi3_sp32"
-+ [(set (match_operand:DI 0 "register_operand" "=&r")
-+ (minus:DI (match_operand:DI 1 "register_operand" "r")
-+ (match_operand:DI 2 "arith_double_operand" "rHI")))
-+ (clobber (reg:CC CC_REG))]
-+ "TARGET_ARCH32"
-+ "#"
-+ "&& reload_completed"
-+ [(parallel [(set (reg:CC CC_REG)
-+ (compare:CC (match_dup 4) (match_dup 5)))
-+ (set (match_dup 3)
-+ (minus:SI (match_dup 4) (match_dup 5)))])
-+ (set (match_dup 6)
-+ (minus:SI (minus:SI (match_dup 7) (match_dup 8))
-+ (ltu:SI (reg:CC CC_REG) (const_int 0))))]
-+{
-+ operands[3] = gen_lowpart (SImode, operands[0]);
-+ operands[4] = gen_lowpart (SImode, operands[1]);
-+ operands[5] = gen_lowpart (SImode, operands[2]);
-+ operands[6] = gen_highpart (SImode, operands[0]);
-+ operands[7] = gen_highpart (SImode, operands[1]);
-+ operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
-+}
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "usubvdi4_sp32"
-+ [(set (reg:CCC CC_REG)
-+ (compare:CCC (match_operand:DI 1 "register_operand" "r")
-+ (match_operand:DI 2 "arith_double_operand" "rHI")))
-+ (set (match_operand:DI 0 "register_operand" "=&r")
-+ (minus:DI (match_dup 1) (match_dup 2)))]
-+ "TARGET_ARCH32"
-+ "#"
-+ "&& reload_completed"
-+ [(parallel [(set (reg:CC CC_REG)
-+ (compare:CC (match_dup 4) (match_dup 5)))
-+ (set (match_dup 3)
-+ (minus:SI (match_dup 4) (match_dup 5)))])
-+ (parallel [(set (reg:CCC CC_REG)
-+ (compare:CCC (zero_extend:DI
-+ (minus:SI (minus:SI (match_dup 7)
-+ (ltu:SI (reg:CC CC_REG)
-+ (const_int 0)))
-+ (match_dup 8)))
-+ (minus:DI
-+ (minus:DI (zero_extend:DI (match_dup 7))
-+ (ltu:DI (reg:CC CC_REG)
-+ (const_int 0)))
-+ (zero_extend:DI (match_dup 8)))))
-+ (set (match_dup 6)
-+ (minus:SI (minus:SI (match_dup 7)
-+ (ltu:SI (reg:CC CC_REG)
-+ (const_int 0)))
-+ (match_dup 8)))])]
-+{
-+ operands[3] = gen_lowpart (SImode, operands[0]);
-+ operands[4] = gen_lowpart (SImode, operands[1]);
-+ operands[5] = gen_lowpart (SImode, operands[2]);
-+ operands[6] = gen_highpart (SImode, operands[0]);
-+ operands[7] = gen_highpart_mode (SImode, DImode, operands[1]);
-+ operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
-+}
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "subvdi4_sp32"
-+ [(set (reg:CCV CC_REG)
-+ (compare:CCV (minus:DI (match_operand:DI 1 "register_operand" "%r")
-+ (match_operand:DI 2 "arith_double_operand" "rHI"))
-+ (unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_SUBV)))
-+ (set (match_operand:DI 0 "register_operand" "=&r")
-+ (minus:DI (match_dup 1) (match_dup 2)))]
-+ "TARGET_ARCH32"
-+ "#"
-+ "&& reload_completed"
-+ [(parallel [(set (reg:CC CC_REG)
-+ (compare:CC (match_dup 4) (match_dup 5)))
-+ (set (match_dup 3)
-+ (minus:SI (match_dup 4) (match_dup 5)))])
-+ (parallel [(set (reg:CCV CC_REG)
-+ (compare:CCV (minus:SI (minus:SI (match_dup 7) (match_dup 8))
-+ (ltu:SI (reg:CC CC_REG)
-+ (const_int 0)))
-+ (unspec:SI [(minus:SI (match_dup 7) (match_dup 8))
-+ (ltu:SI (reg:CC CC_REG)
-+ (const_int 0))]
-+ UNSPEC_SUBV)))
-+ (set (match_dup 6)
-+ (minus:SI (minus:SI (match_dup 7) (match_dup 8))
-+ (ltu:SI (reg:CC CC_REG) (const_int 0))))])]
-+{
-+ operands[3] = gen_lowpart (SImode, operands[0]);
-+ operands[4] = gen_lowpart (SImode, operands[1]);
-+ operands[5] = gen_lowpart (SImode, operands[2]);
-+ operands[6] = gen_highpart (SImode, operands[0]);
-+ operands[7] = gen_highpart_mode (SImode, DImode, operands[1]);
-+ operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
-+}
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*subx_extend_sp32"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (zero_extend:DI (minus:SI (minus:SI
-+ (match_operand:SI 1 "register_or_zero_operand" "rJ")
-+ (match_operand:SI 2 "arith_operand" "rI"))
-+ (ltu:SI (reg:CCC CC_REG) (const_int 0)))))]
-+ "TARGET_ARCH32"
-+ "#"
-+ "&& reload_completed"
-+ [(set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 2))
-+ (ltu:SI (reg:CCC CC_REG) (const_int 0))))
-+ (set (match_dup 4) (const_int 0))]
-+ "operands[3] = gen_lowpart (SImode, operands[0]);
-+ operands[4] = gen_highpart (SImode, operands[0]);"
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "*subdi3_extend_sp32"
-+ [(set (match_operand:DI 0 "register_operand" "=&r")
-+ (minus:DI (match_operand:DI 1 "register_operand" "r")
-+ (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))
-+ (clobber (reg:CC CC_REG))]
-+ "TARGET_ARCH32"
-+ "#"
-+ "&& reload_completed"
-+ [(parallel [(set (reg:CC CC_REG)
-+ (compare:CC (match_dup 3) (match_dup 2)))
-+ (set (match_dup 5) (minus:SI (match_dup 3) (match_dup 2)))])
-+ (set (match_dup 6)
-+ (minus:SI (minus:SI (match_dup 4) (const_int 0))
-+ (ltu:SI (reg:CC CC_REG) (const_int 0))))]
-+ "operands[3] = gen_lowpart (SImode, operands[1]);
-+ operands[4] = gen_highpart (SImode, operands[1]);
-+ operands[5] = gen_lowpart (SImode, operands[0]);
-+ operands[6] = gen_highpart (SImode, operands[0]);"
-+ [(set_attr "length" "2")])
-+
-+(define_insn "*subdi3_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r,r")
-+ (minus:DI (match_operand:DI 1 "register_operand" "r,r")
-+ (match_operand:DI 2 "arith_add_operand" "rI,O")))]
-+ "TARGET_ARCH64"
-+ "@
-+ sub\t%1, %2, %0
-+ add\t%1, -%2, %0")
-+
-+(define_insn "subsi3"
-+ [(set (match_operand:SI 0 "register_operand" "=r,r")
-+ (minus:SI (match_operand:SI 1 "register_operand" "r,r")
-+ (match_operand:SI 2 "arith_add_operand" "rI,O")))]
-+ ""
-+ "@
-+ sub\t%1, %2, %0
-+ add\t%1, -%2, %0")
-+
-+;; Turning an add/sub instruction into the other changes the Carry flag
-+;; so the 4096 trick cannot be used for operations in CCmode.
-+
-+(define_expand "usubvsi4"
-+ [(parallel [(set (reg:CC CC_REG)
-+ (compare:CC (match_operand:SI 1 "register_or_zero_operand")
-+ (match_operand:SI 2 "arith_operand")))
-+ (set (match_operand:SI 0 "register_operand")
-+ (minus:SI (match_dup 1) (match_dup 2)))])
-+ (set (pc) (if_then_else (ltu (reg:CC CC_REG) (const_int 0))
-+ (label_ref (match_operand 3))
-+ (pc)))]
-+ ""
-+{
-+ if (operands[1] == const0_rtx)
-+ {
-+ emit_insn (gen_unegvsi3 (operands[0], operands[2], operands[3]));
-+ DONE;
-+ }
-+})
-+
-+;; Turning an add/sub instruction into the other does not change the Overflow
-+;; flag so the 4096 trick can be used for operations in CCVmode.
-+
-+(define_expand "subvsi4"
-+ [(parallel [(set (reg:CCV CC_REG)
-+ (compare:CCV (minus:SI (match_operand:SI 1 "register_operand")
-+ (match_operand:SI 2 "arith_add_operand"))
-+ (unspec:SI [(match_dup 1) (match_dup 2)]
-+ UNSPEC_SUBV)))
-+ (set (match_operand:SI 0 "register_operand")
-+ (minus:SI (match_dup 1) (match_dup 2)))])
-+ (set (pc) (if_then_else (ne (reg:CCV CC_REG) (const_int 0))
-+ (label_ref (match_operand 3))
-+ (pc)))]
-+ "")
-+
-+(define_insn "*cmp_ccnz_minus"
-+ [(set (reg:CCNZ CC_REG)
-+ (compare:CCNZ (minus:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
-+ (match_operand:SI 1 "arith_operand" "rI"))
-+ (const_int 0)))]
-+ ""
-+ "subcc\t%r0, %1, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccxnz_minus"
-+ [(set (reg:CCXNZ CC_REG)
-+ (compare:CCXNZ (minus:DI (match_operand:DI 0 "register_or_zero_operand" "rJ")
-+ (match_operand:DI 1 "arith_operand" "rI"))
-+ (const_int 0)))]
-+ "TARGET_ARCH64"
-+ "subcc\t%r0, %1, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccnz_minus_set"
-+ [(set (reg:CCNZ CC_REG)
-+ (compare:CCNZ (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
-+ (match_operand:SI 2 "arith_operand" "rI"))
-+ (const_int 0)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (minus:SI (match_dup 1) (match_dup 2)))]
-+ ""
-+ "subcc\t%r1, %2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccxnz_minus_set"
-+ [(set (reg:CCXNZ CC_REG)
-+ (compare:CCXNZ (minus:DI (match_operand:DI 1 "register_or_zero_operand" "rJ")
-+ (match_operand:DI 2 "arith_operand" "rI"))
-+ (const_int 0)))
-+ (set (match_operand:DI 0 "register_operand" "=r")
-+ (minus:DI (match_dup 1) (match_dup 2)))]
-+ "TARGET_ARCH64"
-+ "subcc\t%r1, %2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmpsi_set"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (match_operand:SI 1 "register_or_zero_operand" "rJ")
-+ (match_operand:SI 2 "arith_operand" "rI")))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (minus:SI (match_dup 1) (match_dup 2)))]
-+ ""
-+ "subcc\t%r1, %2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmpdi_set"
-+ [(set (reg:CCX CC_REG)
-+ (compare:CCX (match_operand:DI 1 "register_or_zero_operand" "rJ")
-+ (match_operand:DI 2 "arith_operand" "rI")))
-+ (set (match_operand:DI 0 "register_operand" "=r")
-+ (minus:DI (match_dup 1) (match_dup 2)))]
-+ "TARGET_ARCH64"
-+ "subcc\t%r1, %2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccc_minus_sltu_set"
-+ [(set (reg:CCC CC_REG)
-+ (compare:CCC (zero_extend:DI
-+ (minus:SI
-+ (minus:SI
-+ (match_operand:SI 1 "register_or_zero_operand" "rJ")
-+ (ltu:SI (reg:CC CC_REG) (const_int 0)))
-+ (match_operand:SI 2 "arith_operand" "rI")))
-+ (minus:DI
-+ (minus:DI
-+ (zero_extend:DI (match_dup 1))
-+ (ltu:DI (reg:CC CC_REG) (const_int 0)))
-+ (zero_extend:DI (match_dup 2)))))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (minus:SI (minus:SI (match_dup 1)
-+ (ltu:SI (reg:CC CC_REG) (const_int 0)))
-+ (match_dup 2)))]
-+ ""
-+ "subxcc\t%r1, %2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccv_minus"
-+ [(set (reg:CCV CC_REG)
-+ (compare:CCV (minus:SI (match_operand:SI 0 "register_or_zero_operand" "rJ,rJ")
-+ (match_operand:SI 1 "arith_add_operand" "rI,O"))
-+ (unspec:SI [(match_dup 0) (match_dup 1)] UNSPEC_SUBV)))]
-+ ""
-+ "@
-+ subcc\t%r0, %1, %%g0
-+ addcc\t%r0, -%1, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccxv_minus"
-+ [(set (reg:CCXV CC_REG)
-+ (compare:CCXV (minus:DI (match_operand:DI 0 "register_or_zero_operand" "rJ,rJ")
-+ (match_operand:DI 1 "arith_add_operand" "rI,O"))
-+ (unspec:DI [(match_dup 0) (match_dup 1)] UNSPEC_SUBV)))]
-+ "TARGET_ARCH64"
-+ "@
-+ subcc\t%r0, %1, %%g0
-+ addcc\t%r0, -%1, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccv_minus_set"
-+ [(set (reg:CCV CC_REG)
-+ (compare:CCV (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ")
-+ (match_operand:SI 2 "arith_add_operand" "rI,O"))
-+ (unspec:SI [(match_dup 1) (match_dup 2)] UNSPEC_SUBV)))
-+ (set (match_operand:SI 0 "register_operand" "=r,r")
-+ (minus:SI (match_dup 1) (match_dup 2)))]
-+ ""
-+ "@
-+ subcc\t%r1, %2, %0
-+ addcc\t%r1, -%2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccxv_minus_set"
-+ [(set (reg:CCXV CC_REG)
-+ (compare:CCXV (minus:DI (match_operand:DI 1 "register_or_zero_operand" "rJ,rJ")
-+ (match_operand:DI 2 "arith_add_operand" "rI,O"))
-+ (unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_SUBV)))
-+ (set (match_operand:DI 0 "register_operand" "=r,r")
-+ (minus:DI (match_dup 1) (match_dup 2)))]
-+ "TARGET_ARCH64"
-+ "@
-+ subcc\t%r1, %2, %0
-+ addcc\t%r1, -%2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccv_minus_sltu_set"
-+ [(set (reg:CCV CC_REG)
-+ (compare:CCV
-+ (minus:SI (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
-+ (match_operand:SI 2 "arith_operand" "rI"))
-+ (ltu:SI (reg:CC CC_REG) (const_int 0)))
-+ (unspec:SI [(minus:SI (match_dup 1) (match_dup 2))
-+ (ltu:SI (reg:CC CC_REG) (const_int 0))]
-+ UNSPEC_SUBV)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (minus:SI (minus:SI (match_dup 1) (match_dup 2))
-+ (ltu:SI (reg:CC CC_REG) (const_int 0))))]
-+ ""
-+ "subxcc\t%1, %2, %0"
-+ [(set_attr "type" "compare")])
-+
-+
-+;; Integer multiply/divide instructions.
-+
-+;; The 32-bit multiply/divide instructions are deprecated on v9, but at
-+;; least in UltraSPARC I, II and IIi it is a win tick-wise.
-+
-+(define_expand "mulsi3"
-+ [(set (match_operand:SI 0 "register_operand" "")
-+ (mult:SI (match_operand:SI 1 "arith_operand" "")
-+ (match_operand:SI 2 "arith_operand" "")))]
-+ "TARGET_HARD_MUL || TARGET_ARCH64"
-+ "")
-+
-+(define_insn "*mulsi3_sp32"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (mult:SI (match_operand:SI 1 "arith_operand" "%r")
-+ (match_operand:SI 2 "arith_operand" "rI")))]
-+ "TARGET_HARD_MUL"
-+ "smul\t%1, %2, %0"
-+ [(set_attr "type" "imul")])
-+
-+(define_insn "*mulsi3_sp64"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (mult:SI (match_operand:SI 1 "arith_operand" "%r")
-+ (match_operand:SI 2 "arith_operand" "rI")))]
-+ "TARGET_ARCH64"
-+ "mulx\t%1, %2, %0"
-+ [(set_attr "type" "imul")])
-+
-+(define_expand "muldi3"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (mult:DI (match_operand:DI 1 "arith_operand" "")
-+ (match_operand:DI 2 "arith_operand" "")))]
-+ "TARGET_ARCH64 || TARGET_V8PLUS"
-+{
-+ if (TARGET_V8PLUS)
-+ {
-+ emit_insn (gen_muldi3_v8plus (operands[0], operands[1], operands[2]));
-+ DONE;
-+ }
-+})
-+
-+(define_insn "*muldi3_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (mult:DI (match_operand:DI 1 "arith_operand" "%r")
-+ (match_operand:DI 2 "arith_operand" "rI")))]
-+ "TARGET_ARCH64"
-+ "mulx\t%1, %2, %0"
-+ [(set_attr "type" "imul")])
-+
-+;; V8plus wide multiply.
-+(define_insn "muldi3_v8plus"
-+ [(set (match_operand:DI 0 "register_operand" "=r,h")
-+ (mult:DI (match_operand:DI 1 "arith_operand" "%r,0")
-+ (match_operand:DI 2 "arith_operand" "rI,rI")))
-+ (clobber (match_scratch:SI 3 "=&h,X"))
-+ (clobber (match_scratch:SI 4 "=&h,X"))]
-+ "TARGET_V8PLUS"
-+{
-+ return output_v8plus_mult (insn, operands, \"mulx\");
-+}
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "9,8")])
-+
-+(define_insn "*cmp_mul_set"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (mult:SI (match_operand:SI 1 "arith_operand" "%r")
-+ (match_operand:SI 2 "arith_operand" "rI"))
-+ (const_int 0)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (mult:SI (match_dup 1) (match_dup 2)))]
-+ "TARGET_V8 || TARGET_SPARCLITE || TARGET_DEPRECATED_V8_INSNS"
-+ "smulcc\t%1, %2, %0"
-+ [(set_attr "type" "imul")])
-+
-+(define_expand "mulsidi3"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
-+ (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))))]
-+ "TARGET_HARD_MUL"
-+{
-+ if (CONSTANT_P (operands[2]))
-+ {
-+ if (TARGET_V8PLUS)
-+ emit_insn (gen_const_mulsidi3_v8plus (operands[0], operands[1],
-+ operands[2]));
-+ else if (TARGET_ARCH32)
-+ emit_insn (gen_const_mulsidi3_sp32 (operands[0], operands[1],
-+ operands[2]));
-+ else
-+ emit_insn (gen_const_mulsidi3_sp64 (operands[0], operands[1],
-+ operands[2]));
-+ DONE;
-+ }
-+ if (TARGET_V8PLUS)
-+ {
-+ emit_insn (gen_mulsidi3_v8plus (operands[0], operands[1], operands[2]));
-+ DONE;
-+ }
-+})
-+
-+;; V9 puts the 64-bit product in a 64-bit register. Only out or global
-+;; registers can hold 64-bit values in the V8plus environment.
-+(define_insn "mulsidi3_v8plus"
-+ [(set (match_operand:DI 0 "register_operand" "=h,r")
-+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
-+ (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r"))))
-+ (clobber (match_scratch:SI 3 "=X,&h"))]
-+ "TARGET_V8PLUS"
-+ "@
-+ smul\t%1, %2, %L0\n\tsrlx\t%L0, 32, %H0
-+ smul\t%1, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "2,3")])
-+
-+(define_insn "const_mulsidi3_v8plus"
-+ [(set (match_operand:DI 0 "register_operand" "=h,r")
-+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
-+ (match_operand:DI 2 "small_int_operand" "I,I")))
-+ (clobber (match_scratch:SI 3 "=X,&h"))]
-+ "TARGET_V8PLUS"
-+ "@
-+ smul\t%1, %2, %L0\n\tsrlx\t%L0, 32, %H0
-+ smul\t%1, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "2,3")])
-+
-+(define_insn "*mulsidi3_sp32"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
-+ (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
-+ "TARGET_HARD_MUL32"
-+{
-+ return TARGET_SPARCLET
-+ ? "smuld\t%1, %2, %L0"
-+ : "smul\t%1, %2, %L0\n\trd\t%%y, %H0";
-+}
-+ [(set (attr "type")
-+ (if_then_else (eq_attr "isa" "sparclet")
-+ (const_string "imul") (const_string "multi")))
-+ (set (attr "length")
-+ (if_then_else (eq_attr "isa" "sparclet")
-+ (const_int 1) (const_int 2)))])
-+
-+(define_insn "*mulsidi3_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
-+ (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
-+ "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
-+ "smul\t%1, %2, %0"
-+ [(set_attr "type" "imul")])
-+
-+;; Extra pattern, because sign_extend of a constant isn't valid.
-+
-+(define_insn "const_mulsidi3_sp32"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
-+ (match_operand:DI 2 "small_int_operand" "I")))]
-+ "TARGET_HARD_MUL32"
-+{
-+ return TARGET_SPARCLET
-+ ? "smuld\t%1, %2, %L0"
-+ : "smul\t%1, %2, %L0\n\trd\t%%y, %H0";
-+}
-+ [(set (attr "type")
-+ (if_then_else (eq_attr "isa" "sparclet")
-+ (const_string "imul") (const_string "multi")))
-+ (set (attr "length")
-+ (if_then_else (eq_attr "isa" "sparclet")
-+ (const_int 1) (const_int 2)))])
-+
-+(define_insn "const_mulsidi3_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
-+ (match_operand:DI 2 "small_int_operand" "I")))]
-+ "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
-+ "smul\t%1, %2, %0"
-+ [(set_attr "type" "imul")])
-+
-+(define_expand "smulsi3_highpart"
-+ [(set (match_operand:SI 0 "register_operand" "")
-+ (truncate:SI
-+ (lshiftrt:DI
-+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
-+ (sign_extend:DI (match_operand:SI 2 "arith_operand" "")))
-+ (const_int 32))))]
-+ "TARGET_HARD_MUL && TARGET_ARCH32"
-+{
-+ if (CONSTANT_P (operands[2]))
-+ {
-+ if (TARGET_V8PLUS)
-+ {
-+ emit_insn (gen_const_smulsi3_highpart_v8plus (operands[0],
-+ operands[1],
-+ operands[2],
-+ GEN_INT (32)));
-+ DONE;
-+ }
-+ emit_insn (gen_const_smulsi3_highpart (operands[0], operands[1], operands[2]));
-+ DONE;
-+ }
-+ if (TARGET_V8PLUS)
-+ {
-+ emit_insn (gen_smulsi3_highpart_v8plus (operands[0], operands[1],
-+ operands[2], GEN_INT (32)));
-+ DONE;
-+ }
-+})
-+
-+(define_insn "smulsi3_highpart_v8plus"
-+ [(set (match_operand:SI 0 "register_operand" "=h,r")
-+ (truncate:SI
-+ (lshiftrt:DI
-+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
-+ (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
-+ (match_operand:SI 3 "small_int_operand" "I,I"))))
-+ (clobber (match_scratch:SI 4 "=X,&h"))]
-+ "TARGET_V8PLUS"
-+ "@
-+ smul\t%1, %2, %0\;srlx\t%0, %3, %0
-+ smul\t%1, %2, %4\;srlx\t%4, %3, %0"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "2")])
-+
-+;; The combiner changes TRUNCATE in the previous pattern to SUBREG.
-+(define_insn ""
-+ [(set (match_operand:SI 0 "register_operand" "=h,r")
-+ (subreg:SI
-+ (lshiftrt:DI
-+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
-+ (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
-+ (match_operand:SI 3 "small_int_operand" "I,I")) 4))
-+ (clobber (match_scratch:SI 4 "=X,&h"))]
-+ "TARGET_V8PLUS"
-+ "@
-+ smul\t%1, %2, %0\n\tsrlx\t%0, %3, %0
-+ smul\t%1, %2, %4\n\tsrlx\t%4, %3, %0"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "2")])
-+
-+(define_insn "const_smulsi3_highpart_v8plus"
-+ [(set (match_operand:SI 0 "register_operand" "=h,r")
-+ (truncate:SI
-+ (lshiftrt:DI
-+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
-+ (match_operand:DI 2 "small_int_operand" "I,I"))
-+ (match_operand:SI 3 "small_int_operand" "I,I"))))
-+ (clobber (match_scratch:SI 4 "=X,&h"))]
-+ "TARGET_V8PLUS"
-+ "@
-+ smul\t%1, %2, %0\n\tsrlx\t%0, %3, %0
-+ smul\t%1, %2, %4\n\tsrlx\t%4, %3, %0"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "2")])
-+
-+(define_insn "*smulsi3_highpart_sp32"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (truncate:SI
-+ (lshiftrt:DI
-+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
-+ (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
-+ (const_int 32))))]
-+ "TARGET_HARD_MUL32"
-+ "smul\t%1, %2, %%g0\n\trd\t%%y, %0"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "2")])
-+
-+(define_insn "const_smulsi3_highpart"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (truncate:SI
-+ (lshiftrt:DI
-+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
-+ (match_operand:DI 2 "small_int_operand" "i"))
-+ (const_int 32))))]
-+ "TARGET_HARD_MUL32"
-+ "smul\t%1, %2, %%g0\n\trd\t%%y, %0"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "2")])
-+
-+(define_expand "umulsidi3"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
-+ (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))))]
-+ "TARGET_HARD_MUL"
-+{
-+ if (CONSTANT_P (operands[2]))
-+ {
-+ if (TARGET_V8PLUS)
-+ emit_insn (gen_const_umulsidi3_v8plus (operands[0], operands[1],
-+ operands[2]));
-+ else if (TARGET_ARCH32)
-+ emit_insn (gen_const_umulsidi3_sp32 (operands[0], operands[1],
-+ operands[2]));
-+ else
-+ emit_insn (gen_const_umulsidi3_sp64 (operands[0], operands[1],
-+ operands[2]));
-+ DONE;
-+ }
-+ if (TARGET_V8PLUS)
-+ {
-+ emit_insn (gen_umulsidi3_v8plus (operands[0], operands[1], operands[2]));
-+ DONE;
-+ }
-+})
-+
-+(define_insn "umulsidi3_v8plus"
-+ [(set (match_operand:DI 0 "register_operand" "=h,r")
-+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
-+ (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r"))))
-+ (clobber (match_scratch:SI 3 "=X,&h"))]
-+ "TARGET_V8PLUS"
-+ "@
-+ umul\t%1, %2, %L0\n\tsrlx\t%L0, 32, %H0
-+ umul\t%1, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "2,3")])
-+
-+(define_insn "*umulsidi3_sp32"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
-+ (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
-+ "TARGET_HARD_MUL32"
-+{
-+ return TARGET_SPARCLET
-+ ? "umuld\t%1, %2, %L0"
-+ : "umul\t%1, %2, %L0\n\trd\t%%y, %H0";
-+}
-+ [(set (attr "type")
-+ (if_then_else (eq_attr "isa" "sparclet")
-+ (const_string "imul") (const_string "multi")))
-+ (set (attr "length")
-+ (if_then_else (eq_attr "isa" "sparclet")
-+ (const_int 1) (const_int 2)))])
-+
-+(define_insn "*umulsidi3_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
-+ (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
-+ "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
-+ "umul\t%1, %2, %0"
-+ [(set_attr "type" "imul")])
-+
-+;; Extra pattern, because sign_extend of a constant isn't valid.
-+
-+(define_insn "const_umulsidi3_sp32"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
-+ (match_operand:DI 2 "uns_small_int_operand" "")))]
-+ "TARGET_HARD_MUL32"
-+{
-+ return TARGET_SPARCLET
-+ ? "umuld\t%1, %s2, %L0"
-+ : "umul\t%1, %s2, %L0\n\trd\t%%y, %H0";
-+}
-+ [(set (attr "type")
-+ (if_then_else (eq_attr "isa" "sparclet")
-+ (const_string "imul") (const_string "multi")))
-+ (set (attr "length")
-+ (if_then_else (eq_attr "isa" "sparclet")
-+ (const_int 1) (const_int 2)))])
-+
-+(define_insn "const_umulsidi3_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
-+ (match_operand:DI 2 "uns_small_int_operand" "")))]
-+ "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
-+ "umul\t%1, %s2, %0"
-+ [(set_attr "type" "imul")])
-+
-+(define_insn "const_umulsidi3_v8plus"
-+ [(set (match_operand:DI 0 "register_operand" "=h,r")
-+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
-+ (match_operand:DI 2 "uns_small_int_operand" "")))
-+ (clobber (match_scratch:SI 3 "=X,h"))]
-+ "TARGET_V8PLUS"
-+ "@
-+ umul\t%1, %s2, %L0\n\tsrlx\t%L0, 32, %H0
-+ umul\t%1, %s2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "2,3")])
-+
-+(define_expand "umulsi3_highpart"
-+ [(set (match_operand:SI 0 "register_operand" "")
-+ (truncate:SI
-+ (lshiftrt:DI
-+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
-+ (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" "")))
-+ (const_int 32))))]
-+ "TARGET_HARD_MUL && TARGET_ARCH32"
-+{
-+ if (CONSTANT_P (operands[2]))
-+ {
-+ if (TARGET_V8PLUS)
-+ {
-+ emit_insn (gen_const_umulsi3_highpart_v8plus (operands[0],
-+ operands[1],
-+ operands[2],
-+ GEN_INT (32)));
-+ DONE;
-+ }
-+ emit_insn (gen_const_umulsi3_highpart (operands[0], operands[1], operands[2]));
-+ DONE;
-+ }
-+ if (TARGET_V8PLUS)
-+ {
-+ emit_insn (gen_umulsi3_highpart_v8plus (operands[0], operands[1],
-+ operands[2], GEN_INT (32)));
-+ DONE;
-+ }
-+})
-+
-+(define_insn "umulsi3_highpart_v8plus"
-+ [(set (match_operand:SI 0 "register_operand" "=h,r")
-+ (truncate:SI
-+ (lshiftrt:DI
-+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
-+ (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
-+ (match_operand:SI 3 "small_int_operand" "I,I"))))
-+ (clobber (match_scratch:SI 4 "=X,h"))]
-+ "TARGET_V8PLUS"
-+ "@
-+ umul\t%1, %2, %0\n\tsrlx\t%0, %3, %0
-+ umul\t%1, %2, %4\n\tsrlx\t%4, %3, %0"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "2")])
-+
-+(define_insn "const_umulsi3_highpart_v8plus"
-+ [(set (match_operand:SI 0 "register_operand" "=h,r")
-+ (truncate:SI
-+ (lshiftrt:DI
-+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
-+ (match_operand:DI 2 "uns_small_int_operand" ""))
-+ (match_operand:SI 3 "small_int_operand" "I,I"))))
-+ (clobber (match_scratch:SI 4 "=X,h"))]
-+ "TARGET_V8PLUS"
-+ "@
-+ umul\t%1, %s2, %0\n\tsrlx\t%0, %3, %0
-+ umul\t%1, %s2, %4\n\tsrlx\t%4, %3, %0"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "2")])
-+
-+(define_insn "*umulsi3_highpart_sp32"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (truncate:SI
-+ (lshiftrt:DI
-+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
-+ (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
-+ (const_int 32))))]
-+ "TARGET_HARD_MUL32"
-+ "umul\t%1, %2, %%g0\n\trd\t%%y, %0"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "2")])
-+
-+(define_insn "const_umulsi3_highpart"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (truncate:SI
-+ (lshiftrt:DI
-+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
-+ (match_operand:DI 2 "uns_small_int_operand" ""))
-+ (const_int 32))))]
-+ "TARGET_HARD_MUL32"
-+ "umul\t%1, %s2, %%g0\n\trd\t%%y, %0"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "2")])
-+
-+
-+(define_expand "umulxhi_vis"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (truncate:DI
-+ (lshiftrt:TI
-+ (mult:TI (zero_extend:TI (match_operand:DI 1 "arith_operand" ""))
-+ (zero_extend:TI (match_operand:DI 2 "arith_operand" "")))
-+ (const_int 64))))]
-+ "TARGET_VIS3"
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_umulxhi_v8plus (operands[0], operands[1], operands[2]));
-+ DONE;
-+ }
-+})
-+
-+(define_insn "*umulxhi_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (truncate:DI
-+ (lshiftrt:TI
-+ (mult:TI (zero_extend:TI (match_operand:DI 1 "arith_operand" "%r"))
-+ (zero_extend:TI (match_operand:DI 2 "arith_operand" "rI")))
-+ (const_int 64))))]
-+ "TARGET_VIS3 && TARGET_ARCH64"
-+ "umulxhi\t%1, %2, %0"
-+ [(set_attr "type" "imul")])
-+
-+(define_insn "umulxhi_v8plus"
-+ [(set (match_operand:DI 0 "register_operand" "=r,h")
-+ (truncate:DI
-+ (lshiftrt:TI
-+ (mult:TI (zero_extend:TI (match_operand:DI 1 "arith_operand" "%r,0"))
-+ (zero_extend:TI (match_operand:DI 2 "arith_operand" "rI,rI")))
-+ (const_int 64))))
-+ (clobber (match_scratch:SI 3 "=&h,X"))
-+ (clobber (match_scratch:SI 4 "=&h,X"))]
-+ "TARGET_VIS3 && TARGET_ARCH32"
-+{
-+ return output_v8plus_mult (insn, operands, \"umulxhi\");
-+}
-+ [(set_attr "type" "imul")
-+ (set_attr "length" "9,8")])
-+
-+(define_expand "xmulx_vis"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (truncate:DI
-+ (unspec:TI [(zero_extend:TI (match_operand:DI 1 "arith_operand" ""))
-+ (zero_extend:TI (match_operand:DI 2 "arith_operand" ""))]
-+ UNSPEC_XMUL)))]
-+ "TARGET_VIS3"
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_xmulx_v8plus (operands[0], operands[1], operands[2]));
-+ DONE;
-+ }
-+})
-+
-+(define_insn "*xmulx_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (truncate:DI
-+ (unspec:TI [(zero_extend:TI (match_operand:DI 1 "arith_operand" "%r"))
-+ (zero_extend:TI (match_operand:DI 2 "arith_operand" "rI"))]
-+ UNSPEC_XMUL)))]
-+ "TARGET_VIS3 && TARGET_ARCH64"
-+ "xmulx\t%1, %2, %0"
-+ [(set_attr "type" "imul")])
-+
-+(define_insn "xmulx_v8plus"
-+ [(set (match_operand:DI 0 "register_operand" "=r,h")
-+ (truncate:DI
-+ (unspec:TI [(zero_extend:TI (match_operand:DI 1 "arith_operand" "%r,0"))
-+ (zero_extend:TI (match_operand:DI 2 "arith_operand" "rI,rI"))]
-+ UNSPEC_XMUL)))
-+ (clobber (match_scratch:SI 3 "=&h,X"))
-+ (clobber (match_scratch:SI 4 "=&h,X"))]
-+ "TARGET_VIS3 && TARGET_ARCH32"
-+{
-+ return output_v8plus_mult (insn, operands, \"xmulx\");
-+}
-+ [(set_attr "type" "imul")
-+ (set_attr "length" "9,8")])
-+
-+(define_expand "xmulxhi_vis"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (truncate:DI
-+ (lshiftrt:TI
-+ (unspec:TI [(zero_extend:TI (match_operand:DI 1 "arith_operand" ""))
-+ (zero_extend:TI (match_operand:DI 2 "arith_operand" ""))]
-+ UNSPEC_XMUL)
-+ (const_int 64))))]
-+ "TARGET_VIS3"
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_xmulxhi_v8plus (operands[0], operands[1], operands[2]));
-+ DONE;
-+ }
-+})
-+
-+(define_insn "*xmulxhi_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (truncate:DI
-+ (lshiftrt:TI
-+ (unspec:TI [(zero_extend:TI (match_operand:DI 1 "arith_operand" "%r"))
-+ (zero_extend:TI (match_operand:DI 2 "arith_operand" "rI"))]
-+ UNSPEC_XMUL)
-+ (const_int 64))))]
-+ "TARGET_VIS3 && TARGET_ARCH64"
-+ "xmulxhi\t%1, %2, %0"
-+ [(set_attr "type" "imul")])
-+
-+(define_insn "xmulxhi_v8plus"
-+ [(set (match_operand:DI 0 "register_operand" "=r,h")
-+ (truncate:DI
-+ (lshiftrt:TI
-+ (unspec:TI [(zero_extend:TI (match_operand:DI 1 "arith_operand" "%r,0"))
-+ (zero_extend:TI (match_operand:DI 2 "arith_operand" "rI,rI"))]
-+ UNSPEC_XMUL)
-+ (const_int 64))))
-+ (clobber (match_scratch:SI 3 "=&h,X"))
-+ (clobber (match_scratch:SI 4 "=&h,X"))]
-+ "TARGET_VIS3 && TARGET_ARCH32"
-+{
-+ return output_v8plus_mult (insn, operands, \"xmulxhi\");
-+}
-+ [(set_attr "type" "imul")
-+ (set_attr "length" "9,8")])
-+
-+(define_expand "divsi3"
-+ [(parallel [(set (match_operand:SI 0 "register_operand" "")
-+ (div:SI (match_operand:SI 1 "register_operand" "")
-+ (match_operand:SI 2 "input_operand" "")))
-+ (clobber (match_scratch:SI 3 ""))])]
-+ "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
-+{
-+ if (TARGET_ARCH64)
-+ {
-+ operands[3] = gen_reg_rtx(SImode);
-+ emit_insn (gen_ashrsi3 (operands[3], operands[1], GEN_INT (31)));
-+ emit_insn (gen_divsi3_sp64 (operands[0], operands[1], operands[2],
-+ operands[3]));
-+ DONE;
-+ }
-+})
-+
-+;; The V8 architecture specifies that there must be at least 3 instructions
-+;; between a write to the Y register and a use of it for correct results.
-+;; We try to fill one of them with a simple constant or a memory load.
-+
-+(define_insn "divsi3_sp32"
-+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
-+ (div:SI (match_operand:SI 1 "register_operand" "r,r,r")
-+ (match_operand:SI 2 "input_operand" "rI,K,m")))
-+ (clobber (match_scratch:SI 3 "=&r,&r,&r"))]
-+ "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS) && TARGET_ARCH32"
-+{
-+ output_asm_insn ("sra\t%1, 31, %3", operands);
-+ output_asm_insn ("wr\t%3, 0, %%y", operands);
-+
-+ switch (which_alternative)
-+ {
-+ case 0:
-+ if (TARGET_V9)
-+ return "sdiv\t%1, %2, %0";
-+ else
-+ return "nop\n\tnop\n\tnop\n\tsdiv\t%1, %2, %0";
-+ case 1:
-+ if (TARGET_V9)
-+ return "sethi\t%%hi(%a2), %3\n\tsdiv\t%1, %3, %0";
-+ else
-+ return "sethi\t%%hi(%a2), %3\n\tnop\n\tnop\n\tsdiv\t%1, %3, %0";
-+ case 2:
-+ if (TARGET_V9)
-+ return "ld\t%2, %3\n\tsdiv\t%1, %3, %0";
-+ else
-+ return "ld\t%2, %3\n\tnop\n\tnop\n\tsdiv\t%1, %3, %0";
-+ default:
-+ gcc_unreachable ();
-+ }
-+}
-+ [(set_attr "type" "multi")
-+ (set (attr "length")
-+ (if_then_else (eq_attr "isa" "v9")
-+ (const_int 4) (const_int 6)))])
-+
-+(define_insn "divsi3_sp64"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (div:SI (match_operand:SI 1 "register_operand" "r")
-+ (match_operand:SI 2 "input_operand" "rI")))
-+ (use (match_operand:SI 3 "register_operand" "r"))]
-+ "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
-+ "wr\t%%g0, %3, %%y\n\tsdiv\t%1, %2, %0"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "2")])
-+
-+(define_insn "divdi3"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (div:DI (match_operand:DI 1 "register_operand" "r")
-+ (match_operand:DI 2 "arith_operand" "rI")))]
-+ "TARGET_ARCH64"
-+ "sdivx\t%1, %2, %0"
-+ [(set_attr "type" "idiv")])
-+
-+(define_insn "*cmp_sdiv_cc_set"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (div:SI (match_operand:SI 1 "register_operand" "r")
-+ (match_operand:SI 2 "arith_operand" "rI"))
-+ (const_int 0)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (div:SI (match_dup 1) (match_dup 2)))
-+ (clobber (match_scratch:SI 3 "=&r"))]
-+ "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
-+{
-+ output_asm_insn ("sra\t%1, 31, %3", operands);
-+ output_asm_insn ("wr\t%3, 0, %%y", operands);
-+
-+ if (TARGET_V9)
-+ return "sdivcc\t%1, %2, %0";
-+ else
-+ return "nop\n\tnop\n\tnop\n\tsdivcc\t%1, %2, %0";
-+}
-+ [(set_attr "type" "multi")
-+ (set (attr "length")
-+ (if_then_else (eq_attr "isa" "v9")
-+ (const_int 3) (const_int 6)))])
-+
-+(define_expand "udivsi3"
-+ [(set (match_operand:SI 0 "register_operand" "")
-+ (udiv:SI (match_operand:SI 1 "nonimmediate_operand" "")
-+ (match_operand:SI 2 "input_operand" "")))]
-+ "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
-+ "")
-+
-+;; The V8 architecture specifies that there must be at least 3 instructions
-+;; between a write to the Y register and a use of it for correct results.
-+;; We try to fill one of them with a simple constant or a memory load.
-+
-+(define_insn "udivsi3_sp32"
-+ [(set (match_operand:SI 0 "register_operand" "=r,&r,&r,&r")
-+ (udiv:SI (match_operand:SI 1 "nonimmediate_operand" "r,r,r,m")
-+ (match_operand:SI 2 "input_operand" "rI,K,m,r")))]
-+ "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS) && TARGET_ARCH32"
-+{
-+ output_asm_insn ("wr\t%%g0, 0, %%y", operands);
-+
-+ switch (which_alternative)
-+ {
-+ case 0:
-+ if (TARGET_V9)
-+ return "udiv\t%1, %2, %0";
-+ else
-+ return "nop\n\tnop\n\tnop\n\tudiv\t%1, %2, %0";
-+ case 1:
-+ if (TARGET_V9)
-+ return "sethi\t%%hi(%a2), %0\n\tudiv\t%1, %0, %0";
-+ else
-+ return "sethi\t%%hi(%a2), %0\n\tnop\n\tnop\n\tudiv\t%1, %0, %0";
-+ case 2:
-+ if (TARGET_V9)
-+ return "ld\t%2, %0\n\tudiv\t%1, %0, %0";
-+ else
-+ return "ld\t%2, %0\n\tnop\n\tnop\n\tudiv\t%1, %0, %0";
-+ case 3:
-+ if (TARGET_V9)
-+ return "ld\t%1, %0\n\tudiv\t%0, %2, %0";
-+ else
-+ return "ld\t%1, %0\n\tnop\n\tnop\n\tudiv\t%0, %2, %0";
-+ default:
-+ gcc_unreachable ();
-+ }
-+}
-+ [(set_attr "type" "multi")
-+ (set (attr "length")
-+ (if_then_else (eq_attr "isa" "v9")
-+ (const_int 3) (const_int 5)))])
-+
-+(define_insn "udivsi3_sp64"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (udiv:SI (match_operand:SI 1 "nonimmediate_operand" "r")
-+ (match_operand:SI 2 "input_operand" "rI")))]
-+ "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
-+ "wr\t%%g0, 0, %%y\n\tudiv\t%1, %2, %0"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "2")])
-+
-+(define_insn "udivdi3"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (udiv:DI (match_operand:DI 1 "register_operand" "r")
-+ (match_operand:DI 2 "arith_operand" "rI")))]
-+ "TARGET_ARCH64"
-+ "udivx\t%1, %2, %0"
-+ [(set_attr "type" "idiv")])
-+
-+(define_insn "*cmp_udiv_cc_set"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (udiv:SI (match_operand:SI 1 "register_operand" "r")
-+ (match_operand:SI 2 "arith_operand" "rI"))
-+ (const_int 0)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (udiv:SI (match_dup 1) (match_dup 2)))]
-+ "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
-+{
-+ output_asm_insn ("wr\t%%g0, 0, %%y", operands);
-+
-+ if (TARGET_V9)
-+ return "udivcc\t%1, %2, %0";
-+ else
-+ return "nop\n\tnop\n\tnop\n\tudivcc\t%1, %2, %0";
-+}
-+ [(set_attr "type" "multi")
-+ (set (attr "length")
-+ (if_then_else (eq_attr "isa" "v9")
-+ (const_int 2) (const_int 5)))])
-+
-+
-+;; SPARClet multiply/accumulate insns
-+
-+(define_insn "*smacsi"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "%r")
-+ (match_operand:SI 2 "arith_operand" "rI"))
-+ (match_operand:SI 3 "register_operand" "0")))]
-+ "TARGET_SPARCLET"
-+ "smac\t%1, %2, %0"
-+ [(set_attr "type" "imul")])
-+
-+(define_insn "*smacdi"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (plus:DI (mult:DI (sign_extend:DI
-+ (match_operand:SI 1 "register_operand" "%r"))
-+ (sign_extend:DI
-+ (match_operand:SI 2 "register_operand" "r")))
-+ (match_operand:DI 3 "register_operand" "0")))]
-+ "TARGET_SPARCLET"
-+ "smacd\t%1, %2, %L0"
-+ [(set_attr "type" "imul")])
-+
-+(define_insn "*umacdi"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (plus:DI (mult:DI (zero_extend:DI
-+ (match_operand:SI 1 "register_operand" "%r"))
-+ (zero_extend:DI
-+ (match_operand:SI 2 "register_operand" "r")))
-+ (match_operand:DI 3 "register_operand" "0")))]
-+ "TARGET_SPARCLET"
-+ "umacd\t%1, %2, %L0"
-+ [(set_attr "type" "imul")])
-+
-+
-+;; Boolean instructions.
-+
-+(define_insn "anddi3"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (and:DI (match_operand:DI 1 "arith_operand" "%r")
-+ (match_operand:DI 2 "arith_operand" "rI")))]
-+ "TARGET_ARCH64"
-+ "and\t%1, %2, %0")
-+
-+(define_insn "andsi3"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (and:SI (match_operand:SI 1 "arith_operand" "%r")
-+ (match_operand:SI 2 "arith_operand" "rI")))]
-+ ""
-+ "and\t%1, %2, %0")
-+
-+(define_split
-+ [(set (match_operand:SI 0 "register_operand" "")
-+ (and:SI (match_operand:SI 1 "register_operand" "")
-+ (match_operand:SI 2 "const_compl_high_operand" "")))
-+ (clobber (match_operand:SI 3 "register_operand" ""))]
-+ ""
-+ [(set (match_dup 3) (match_dup 4))
-+ (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))]
-+{
-+ operands[4] = GEN_INT (~INTVAL (operands[2]));
-+})
-+
-+(define_insn "*and_not_di_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (and:DI (not:DI (match_operand:DI 1 "register_operand" "%r"))
-+ (match_operand:DI 2 "register_operand" "r")))]
-+ "TARGET_ARCH64"
-+ "andn\t%2, %1, %0")
-+
-+(define_insn "*and_not_si"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (and:SI (not:SI (match_operand:SI 1 "register_operand" "%r"))
-+ (match_operand:SI 2 "register_operand" "r")))]
-+ ""
-+ "andn\t%2, %1, %0")
-+
-+(define_insn "iordi3"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (ior:DI (match_operand:DI 1 "arith_operand" "%r")
-+ (match_operand:DI 2 "arith_operand" "rI")))]
-+ "TARGET_ARCH64"
-+ "or\t%1, %2, %0")
-+
-+(define_insn "iorsi3"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (ior:SI (match_operand:SI 1 "arith_operand" "%r")
-+ (match_operand:SI 2 "arith_operand" "rI")))]
-+ ""
-+ "or\t%1, %2, %0")
-+
-+(define_split
-+ [(set (match_operand:SI 0 "register_operand" "")
-+ (ior:SI (match_operand:SI 1 "register_operand" "")
-+ (match_operand:SI 2 "const_compl_high_operand" "")))
-+ (clobber (match_operand:SI 3 "register_operand" ""))]
-+ ""
-+ [(set (match_dup 3) (match_dup 4))
-+ (set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))]
-+{
-+ operands[4] = gen_int_mode (~INTVAL (operands[2]), SImode);
-+})
-+
-+(define_insn "*or_not_di_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
-+ (match_operand:DI 2 "register_operand" "r")))]
-+ "TARGET_ARCH64"
-+ "orn\t%2, %1, %0")
-+
-+(define_insn "*or_not_si"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
-+ (match_operand:SI 2 "register_operand" "r")))]
-+ ""
-+ "orn\t%2, %1, %0")
-+
-+(define_insn "xordi3"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (xor:DI (match_operand:DI 1 "arith_operand" "%rJ")
-+ (match_operand:DI 2 "arith_operand" "rI")))]
-+ "TARGET_ARCH64"
-+ "xor\t%r1, %2, %0")
-+
-+(define_insn "xorsi3"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (xor:SI (match_operand:SI 1 "arith_operand" "%rJ")
-+ (match_operand:SI 2 "arith_operand" "rI")))]
-+ ""
-+ "xor\t%r1, %2, %0")
-+
-+(define_split
-+ [(set (match_operand:SI 0 "register_operand" "")
-+ (xor:SI (match_operand:SI 1 "register_operand" "")
-+ (match_operand:SI 2 "const_compl_high_operand" "")))
-+ (clobber (match_operand:SI 3 "register_operand" ""))]
-+ ""
-+ [(set (match_dup 3) (match_dup 4))
-+ (set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))]
-+{
-+ operands[4] = gen_int_mode (~INTVAL (operands[2]), SImode);
-+})
-+
-+(define_split
-+ [(set (match_operand:SI 0 "register_operand" "")
-+ (not:SI (xor:SI (match_operand:SI 1 "register_operand" "")
-+ (match_operand:SI 2 "const_compl_high_operand" ""))))
-+ (clobber (match_operand:SI 3 "register_operand" ""))]
-+ ""
-+ [(set (match_dup 3) (match_dup 4))
-+ (set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))]
-+{
-+ operands[4] = gen_int_mode (~INTVAL (operands[2]), SImode);
-+})
-+
-+(define_insn "*xor_not_di_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (not:DI (xor:DI (match_operand:DI 1 "register_or_zero_operand" "rJ")
-+ (match_operand:DI 2 "arith_operand" "rI"))))]
-+ "TARGET_ARCH64"
-+ "xnor\t%r1, %2, %0")
-+
-+(define_insn "*xor_not_si"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (not:SI (xor:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
-+ (match_operand:SI 2 "arith_operand" "rI"))))]
-+ ""
-+ "xnor\t%r1, %2, %0")
-+
-+;; These correspond to the above in the case where we also (or only)
-+;; want to set the condition code.
-+
-+(define_insn "*cmp_cc_arith_op"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (match_operator:SI 2 "cc_arith_operator"
-+ [(match_operand:SI 0 "arith_operand" "%r")
-+ (match_operand:SI 1 "arith_operand" "rI")])
-+ (const_int 0)))]
-+ ""
-+ "%A2cc\t%0, %1, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccx_arith_op"
-+ [(set (reg:CCX CC_REG)
-+ (compare:CCX (match_operator:DI 2 "cc_arith_operator"
-+ [(match_operand:DI 0 "arith_operand" "%r")
-+ (match_operand:DI 1 "arith_operand" "rI")])
-+ (const_int 0)))]
-+ "TARGET_ARCH64"
-+ "%A2cc\t%0, %1, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_cc_arith_op_set"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (match_operator:SI 3 "cc_arith_operator"
-+ [(match_operand:SI 1 "arith_operand" "%r")
-+ (match_operand:SI 2 "arith_operand" "rI")])
-+ (const_int 0)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (match_operator:SI 4 "cc_arith_operator"
-+ [(match_dup 1) (match_dup 2)]))]
-+ "GET_CODE (operands[3]) == GET_CODE (operands[4])"
-+ "%A3cc\t%1, %2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccx_arith_op_set"
-+ [(set (reg:CCX CC_REG)
-+ (compare:CCX (match_operator:DI 3 "cc_arith_operator"
-+ [(match_operand:DI 1 "arith_operand" "%r")
-+ (match_operand:DI 2 "arith_operand" "rI")])
-+ (const_int 0)))
-+ (set (match_operand:DI 0 "register_operand" "=r")
-+ (match_operator:DI 4 "cc_arith_operator"
-+ [(match_dup 1) (match_dup 2)]))]
-+ "TARGET_ARCH64 && GET_CODE (operands[3]) == GET_CODE (operands[4])"
-+ "%A3cc\t%1, %2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_cc_xor_not"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC
-+ (not:SI (xor:SI (match_operand:SI 0 "register_or_zero_operand" "%rJ")
-+ (match_operand:SI 1 "arith_operand" "rI")))
-+ (const_int 0)))]
-+ ""
-+ "xnorcc\t%r0, %1, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccx_xor_not"
-+ [(set (reg:CCX CC_REG)
-+ (compare:CCX
-+ (not:DI (xor:DI (match_operand:DI 0 "register_or_zero_operand" "%rJ")
-+ (match_operand:DI 1 "arith_operand" "rI")))
-+ (const_int 0)))]
-+ "TARGET_ARCH64"
-+ "xnorcc\t%r0, %1, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_cc_xor_not_set"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC
-+ (not:SI (xor:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ")
-+ (match_operand:SI 2 "arith_operand" "rI")))
-+ (const_int 0)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (not:SI (xor:SI (match_dup 1) (match_dup 2))))]
-+ ""
-+ "xnorcc\t%r1, %2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccx_xor_not_set"
-+ [(set (reg:CCX CC_REG)
-+ (compare:CCX
-+ (not:DI (xor:DI (match_operand:DI 1 "register_or_zero_operand" "%rJ")
-+ (match_operand:DI 2 "arith_operand" "rI")))
-+ (const_int 0)))
-+ (set (match_operand:DI 0 "register_operand" "=r")
-+ (not:DI (xor:DI (match_dup 1) (match_dup 2))))]
-+ "TARGET_ARCH64"
-+ "xnorcc\t%r1, %2, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_cc_arith_op_not"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (match_operator:SI 2 "cc_arith_not_operator"
-+ [(not:SI (match_operand:SI 0 "arith_operand" "rI"))
-+ (match_operand:SI 1 "register_or_zero_operand" "rJ")])
-+ (const_int 0)))]
-+ ""
-+ "%B2cc\t%r1, %0, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccx_arith_op_not"
-+ [(set (reg:CCX CC_REG)
-+ (compare:CCX (match_operator:DI 2 "cc_arith_not_operator"
-+ [(not:DI (match_operand:DI 0 "arith_operand" "rI"))
-+ (match_operand:DI 1 "register_or_zero_operand" "rJ")])
-+ (const_int 0)))]
-+ "TARGET_ARCH64"
-+ "%B2cc\t%r1, %0, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_cc_arith_op_not_set"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (match_operator:SI 3 "cc_arith_not_operator"
-+ [(not:SI (match_operand:SI 1 "arith_operand" "rI"))
-+ (match_operand:SI 2 "register_or_zero_operand" "rJ")])
-+ (const_int 0)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (match_operator:SI 4 "cc_arith_not_operator"
-+ [(not:SI (match_dup 1)) (match_dup 2)]))]
-+ "GET_CODE (operands[3]) == GET_CODE (operands[4])"
-+ "%B3cc\t%r2, %1, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccx_arith_op_not_set"
-+ [(set (reg:CCX CC_REG)
-+ (compare:CCX (match_operator:DI 3 "cc_arith_not_operator"
-+ [(not:DI (match_operand:DI 1 "arith_operand" "rI"))
-+ (match_operand:DI 2 "register_or_zero_operand" "rJ")])
-+ (const_int 0)))
-+ (set (match_operand:DI 0 "register_operand" "=r")
-+ (match_operator:DI 4 "cc_arith_not_operator"
-+ [(not:DI (match_dup 1)) (match_dup 2)]))]
-+ "TARGET_ARCH64 && GET_CODE (operands[3]) == GET_CODE (operands[4])"
-+ "%B3cc\t%r2, %1, %0"
-+ [(set_attr "type" "compare")])
-+
-+;; We cannot use the "neg" pseudo insn because the Sun assembler
-+;; does not know how to make it work for constants.
-+
-+(define_expand "negdi2"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (neg:DI (match_operand:DI 1 "register_operand" "r")))]
-+ ""
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_negdi2_sp32 (operands[0], operands[1]));
-+ DONE;
-+ }
-+})
-+
-+(define_expand "unegvdi3"
-+ [(parallel [(set (reg:CCXC CC_REG)
-+ (compare:CCXC (not:DI (match_operand:DI 1 "register_operand" ""))
-+ (const_int -1)))
-+ (set (match_operand:DI 0 "register_operand" "")
-+ (neg:DI (match_dup 1)))])
-+ (set (pc)
-+ (if_then_else (ltu (reg:CCXC CC_REG) (const_int 0))
-+ (label_ref (match_operand 2 ""))
-+ (pc)))]
-+ ""
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_unegvdi3_sp32 (operands[0], operands[1]));
-+ rtx x = gen_rtx_LTU (VOIDmode, gen_rtx_REG (CCCmode, SPARC_ICC_REG),
-+ const0_rtx);
-+ emit_jump_insn (gen_cbranchcc4 (x, XEXP (x, 0), XEXP (x, 1), operands[2]));
-+ DONE;
-+ }
-+})
-+
-+(define_expand "negvdi3"
-+ [(parallel [(set (reg:CCXV CC_REG)
-+ (compare:CCXV (neg:DI (match_operand:DI 1 "register_operand" ""))
-+ (unspec:DI [(match_dup 1)] UNSPEC_NEGV)))
-+ (set (match_operand:DI 0 "register_operand" "")
-+ (neg:DI (match_dup 1)))])
-+ (set (pc)
-+ (if_then_else (ne (reg:CCXV CC_REG) (const_int 0))
-+ (label_ref (match_operand 2 ""))
-+ (pc)))]
-+ ""
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_negvdi3_sp32 (operands[0], operands[1]));
-+ rtx x = gen_rtx_NE (VOIDmode, gen_rtx_REG (CCVmode, SPARC_ICC_REG),
-+ const0_rtx);
-+ emit_jump_insn (gen_cbranchcc4 (x, XEXP (x, 0), XEXP (x, 1), operands[2]));
-+ DONE;
-+ }
-+})
-+
-+(define_insn_and_split "negdi2_sp32"
-+ [(set (match_operand:DI 0 "register_operand" "=&r")
-+ (neg:DI (match_operand:DI 1 "register_operand" "r")))
-+ (clobber (reg:CC CC_REG))]
-+ "TARGET_ARCH32"
-+ "#"
-+ "&& reload_completed"
-+ [(parallel [(set (reg:CCC CC_REG)
-+ (compare:CCC (not:SI (match_dup 5)) (const_int -1)))
-+ (set (match_dup 4) (neg:SI (match_dup 5)))])
-+ (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
-+ (ltu:SI (reg:CCC CC_REG) (const_int 0))))]
-+ "operands[2] = gen_highpart (SImode, operands[0]);
-+ operands[3] = gen_highpart (SImode, operands[1]);
-+ operands[4] = gen_lowpart (SImode, operands[0]);
-+ operands[5] = gen_lowpart (SImode, operands[1]);"
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "unegvdi3_sp32"
-+ [(set (reg:CCC CC_REG)
-+ (compare:CCC (not:DI (match_operand:DI 1 "register_operand" "r"))
-+ (const_int -1)))
-+ (set (match_operand:DI 0 "register_operand" "=&r")
-+ (neg:DI (match_dup 1)))]
-+ "TARGET_ARCH32"
-+ "#"
-+ "&& reload_completed"
-+ [(parallel [(set (reg:CCC CC_REG)
-+ (compare:CCC (not:SI (match_dup 5)) (const_int -1)))
-+ (set (match_dup 4) (neg:SI (match_dup 5)))])
-+ (parallel [(set (reg:CCC CC_REG)
-+ (compare:CCC (zero_extend:DI
-+ (neg:SI (plus:SI (match_dup 3)
-+ (ltu:SI (reg:CCC CC_REG)
-+ (const_int 0)))))
-+ (neg:DI (plus:DI (zero_extend:DI (match_dup 3))
-+ (ltu:DI (reg:CCC CC_REG)
-+ (const_int 0))))))
-+ (set (match_dup 2) (neg:SI (plus:SI (match_dup 3)
-+ (ltu:SI (reg:CCC CC_REG)
-+ (const_int 0)))))])]
-+ "operands[2] = gen_highpart (SImode, operands[0]);
-+ operands[3] = gen_highpart (SImode, operands[1]);
-+ operands[4] = gen_lowpart (SImode, operands[0]);
-+ operands[5] = gen_lowpart (SImode, operands[1]);"
-+ [(set_attr "length" "2")])
-+
-+(define_insn_and_split "negvdi3_sp32"
-+ [(set (reg:CCV CC_REG)
-+ (compare:CCV (neg:DI (match_operand:DI 1 "register_operand" "r"))
-+ (unspec:DI [(match_dup 1)] UNSPEC_NEGV)))
-+ (set (match_operand:DI 0 "register_operand" "=&r")
-+ (neg:DI (match_dup 1)))]
-+ "TARGET_ARCH32"
-+ "#"
-+ "&& reload_completed"
-+ [(parallel [(set (reg:CCC CC_REG)
-+ (compare:CCC (not:SI (match_dup 5)) (const_int -1)))
-+ (set (match_dup 4) (neg:SI (match_dup 5)))])
-+ (parallel [(set (reg:CCV CC_REG)
-+ (compare:CCV (neg:SI (plus:SI (match_dup 3)
-+ (ltu:SI (reg:CCC CC_REG)
-+ (const_int 0))))
-+ (unspec:SI [(plus:SI (match_dup 3)
-+ (ltu:SI (reg:CCC CC_REG)
-+ (const_int 0)))]
-+ UNSPEC_NEGV)))
-+ (set (match_dup 2) (neg:SI (plus:SI (match_dup 3)
-+ (ltu:SI (reg:CCC CC_REG)
-+ (const_int 0)))))])]
-+ "operands[2] = gen_highpart (SImode, operands[0]);
-+ operands[3] = gen_highpart (SImode, operands[1]);
-+ operands[4] = gen_lowpart (SImode, operands[0]);
-+ operands[5] = gen_lowpart (SImode, operands[1]);"
-+ [(set_attr "length" "2")])
-+
-+(define_insn "*negdi2_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (neg:DI (match_operand:DI 1 "register_operand" "r")))]
-+ "TARGET_ARCH64"
-+ "sub\t%%g0, %1, %0")
-+
-+(define_insn "negsi2"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (neg:SI (match_operand:SI 1 "register_operand" "r")))]
-+ ""
-+ "sub\t%%g0, %1, %0")
-+
-+(define_expand "unegvsi3"
-+ [(parallel [(set (reg:CCC CC_REG)
-+ (compare:CCC (not:SI (match_operand:SI 1 "register_operand" ""))
-+ (const_int -1)))
-+ (set (match_operand:SI 0 "register_operand" "")
-+ (neg:SI (match_dup 1)))])
-+ (set (pc)
-+ (if_then_else (ltu (reg:CCC CC_REG) (const_int 0))
-+ (label_ref (match_operand 2 ""))
-+ (pc)))]
-+ "")
-+
-+(define_expand "negvsi3"
-+ [(parallel [(set (reg:CCV CC_REG)
-+ (compare:CCV (neg:SI (match_operand:SI 1 "register_operand" ""))
-+ (unspec:SI [(match_dup 1)] UNSPEC_NEGV)))
-+ (set (match_operand:SI 0 "register_operand" "")
-+ (neg:SI (match_dup 1)))])
-+ (set (pc)
-+ (if_then_else (ne (reg:CCV CC_REG) (const_int 0))
-+ (label_ref (match_operand 2 ""))
-+ (pc)))]
-+"")
-+
-+(define_insn "*cmp_ccnz_neg"
-+ [(set (reg:CCNZ CC_REG)
-+ (compare:CCNZ (neg:SI (match_operand:SI 0 "register_operand" "r"))
-+ (const_int 0)))]
-+ ""
-+ "subcc\t%%g0, %0, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccxnz_neg"
-+ [(set (reg:CCXNZ CC_REG)
-+ (compare:CCXNZ (neg:DI (match_operand:DI 0 "register_operand" "r"))
-+ (const_int 0)))]
-+ "TARGET_ARCH64"
-+ "subcc\t%%g0, %0, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccnz_neg_set"
-+ [(set (reg:CCNZ CC_REG)
-+ (compare:CCNZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
-+ (const_int 0)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (neg:SI (match_dup 1)))]
-+ ""
-+ "subcc\t%%g0, %1, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccxnz_neg_set"
-+ [(set (reg:CCXNZ CC_REG)
-+ (compare:CCXNZ (neg:DI (match_operand:DI 1 "register_operand" "r"))
-+ (const_int 0)))
-+ (set (match_operand:DI 0 "register_operand" "=r")
-+ (neg:DI (match_dup 1)))]
-+ "TARGET_ARCH64"
-+ "subcc\t%%g0, %1, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccc_neg_set"
-+ [(set (reg:CCC CC_REG)
-+ (compare:CCC (not:SI (match_operand:SI 1 "register_operand" "r"))
-+ (const_int -1)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (neg:SI (match_dup 1)))]
-+ ""
-+ "subcc\t%%g0, %1, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccxc_neg_set"
-+ [(set (reg:CCXC CC_REG)
-+ (compare:CCXC (not:DI (match_operand:DI 1 "register_operand" "r"))
-+ (const_int -1)))
-+ (set (match_operand:DI 0 "register_operand" "=r")
-+ (neg:DI (match_dup 1)))]
-+ "TARGET_ARCH64"
-+ "subcc\t%%g0, %1, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccc_neg_sltu_set"
-+ [(set (reg:CCC CC_REG)
-+ (compare:CCC (zero_extend:DI
-+ (neg:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
-+ (ltu:SI (reg:CCC CC_REG)
-+ (const_int 0)))))
-+ (neg:DI (plus:DI (zero_extend:DI (match_dup 1))
-+ (ltu:DI (reg:CCC CC_REG)
-+ (const_int 0))))))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (neg:SI (plus:SI (match_dup 1)
-+ (ltu:SI (reg:CCC CC_REG) (const_int 0)))))]
-+ ""
-+ "subxcc\t%%g0, %1, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccv_neg"
-+ [(set (reg:CCV CC_REG)
-+ (compare:CCV (neg:SI (match_operand:SI 0 "register_operand" "r"))
-+ (unspec:SI [(match_dup 0)] UNSPEC_NEGV)))]
-+ ""
-+ "subcc\t%%g0, %0, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccxv_neg"
-+ [(set (reg:CCXV CC_REG)
-+ (compare:CCXV (neg:DI (match_operand:DI 0 "register_operand" "r"))
-+ (unspec:DI [(match_dup 0)] UNSPEC_NEGV)))]
-+ "TARGET_ARCH64"
-+ "subcc\t%%g0, %0, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccv_neg_set"
-+ [(set (reg:CCV CC_REG)
-+ (compare:CCV (neg:SI (match_operand:SI 1 "register_operand" "r"))
-+ (unspec:SI [(match_dup 1)] UNSPEC_NEGV)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (neg:SI (match_dup 1)))]
-+ ""
-+ "subcc\t%%g0, %1, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccxv_neg_set"
-+ [(set (reg:CCXV CC_REG)
-+ (compare:CCXV (neg:DI (match_operand:DI 1 "register_operand" "r"))
-+ (unspec:DI [(match_dup 1)] UNSPEC_NEGV)))
-+ (set (match_operand:DI 0 "register_operand" "=r")
-+ (neg:DI (match_dup 1)))]
-+ "TARGET_ARCH64"
-+ "subcc\t%%g0, %1, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccv_neg_sltu_set"
-+ [(set (reg:CCV CC_REG)
-+ (compare:CCV (neg:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
-+ (ltu:SI (reg:CCC CC_REG) (const_int 0))))
-+ (unspec:SI [(plus:SI (match_dup 1)
-+ (ltu:SI (reg:CCC CC_REG)
-+ (const_int 0)))]
-+ UNSPEC_NEGV)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (neg:SI (plus:SI (match_dup 1)
-+ (ltu:SI (reg:CCC CC_REG) (const_int 0)))))]
-+ ""
-+ "subxcc\t%%g0, %1, %0"
-+ [(set_attr "type" "compare")])
-+
-+
-+(define_insn "one_cmpldi2"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (not:DI (match_operand:DI 1 "arith_operand" "rI")))]
-+ "TARGET_ARCH64"
-+ "xnor\t%%g0, %1, %0")
-+
-+(define_insn "one_cmplsi2"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (not:SI (match_operand:SI 1 "arith_operand" "rI")))]
-+ ""
-+ "xnor\t%%g0, %1, %0")
-+
-+(define_insn "*cmp_cc_not"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI"))
-+ (const_int 0)))]
-+ ""
-+ "xnorcc\t%%g0, %0, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccx_not"
-+ [(set (reg:CCX CC_REG)
-+ (compare:CCX (not:DI (match_operand:DI 0 "arith_operand" "rI"))
-+ (const_int 0)))]
-+ "TARGET_ARCH64"
-+ "xnorcc\t%%g0, %0, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_cc_set_not"
-+ [(set (reg:CC CC_REG)
-+ (compare:CC (not:SI (match_operand:SI 1 "arith_operand" "rI"))
-+ (const_int 0)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (not:SI (match_dup 1)))]
-+ ""
-+ "xnorcc\t%%g0, %1, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccx_set_not"
-+ [(set (reg:CCX CC_REG)
-+ (compare:CCX (not:DI (match_operand:DI 1 "arith_operand" "rI"))
-+ (const_int 0)))
-+ (set (match_operand:DI 0 "register_operand" "=r")
-+ (not:DI (match_dup 1)))]
-+ "TARGET_ARCH64"
-+ "xnorcc\t%%g0, %1, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_cc_set"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (match_operand:SI 1 "register_operand" "r"))
-+ (set (reg:CC CC_REG)
-+ (compare:CC (match_dup 1) (const_int 0)))]
-+ ""
-+ "orcc\t%1, 0, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccx_set64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (match_operand:DI 1 "register_operand" "r"))
-+ (set (reg:CCX CC_REG)
-+ (compare:CCX (match_dup 1) (const_int 0)))]
-+ "TARGET_ARCH64"
-+ "orcc\t%1, 0, %0"
-+ [(set_attr "type" "compare")])
-+
-+
-+;; Floating point arithmetic instructions.
-+
-+(define_expand "addtf3"
-+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
-+ (plus:TF (match_operand:TF 1 "general_operand" "")
-+ (match_operand:TF 2 "general_operand" "")))]
-+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-+ "emit_tfmode_binop (PLUS, operands); DONE;")
-+
-+(define_insn "*addtf3_hq"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (plus:TF (match_operand:TF 1 "register_operand" "e")
-+ (match_operand:TF 2 "register_operand" "e")))]
-+ "TARGET_FPU && TARGET_HARD_QUAD"
-+ "faddq\t%1, %2, %0"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "adddf3"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (plus:DF (match_operand:DF 1 "register_operand" "e")
-+ (match_operand:DF 2 "register_operand" "e")))]
-+ "TARGET_FPU"
-+ "faddd\t%1, %2, %0"
-+ [(set_attr "type" "fp")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "addsf3"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (plus:SF (match_operand:SF 1 "register_operand" "f")
-+ (match_operand:SF 2 "register_operand" "f")))]
-+ "TARGET_FPU"
-+ "fadds\t%1, %2, %0"
-+ [(set_attr "type" "fp")])
-+
-+(define_expand "subtf3"
-+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
-+ (minus:TF (match_operand:TF 1 "general_operand" "")
-+ (match_operand:TF 2 "general_operand" "")))]
-+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-+ "emit_tfmode_binop (MINUS, operands); DONE;")
-+
-+(define_insn "*subtf3_hq"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (minus:TF (match_operand:TF 1 "register_operand" "e")
-+ (match_operand:TF 2 "register_operand" "e")))]
-+ "TARGET_FPU && TARGET_HARD_QUAD"
-+ "fsubq\t%1, %2, %0"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "subdf3"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (minus:DF (match_operand:DF 1 "register_operand" "e")
-+ (match_operand:DF 2 "register_operand" "e")))]
-+ "TARGET_FPU"
-+ "fsubd\t%1, %2, %0"
-+ [(set_attr "type" "fp")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "subsf3"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (minus:SF (match_operand:SF 1 "register_operand" "f")
-+ (match_operand:SF 2 "register_operand" "f")))]
-+ "TARGET_FPU"
-+ "fsubs\t%1, %2, %0"
-+ [(set_attr "type" "fp")])
-+
-+(define_expand "multf3"
-+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
-+ (mult:TF (match_operand:TF 1 "general_operand" "")
-+ (match_operand:TF 2 "general_operand" "")))]
-+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-+ "emit_tfmode_binop (MULT, operands); DONE;")
-+
-+(define_insn "*multf3_hq"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (mult:TF (match_operand:TF 1 "register_operand" "e")
-+ (match_operand:TF 2 "register_operand" "e")))]
-+ "TARGET_FPU && TARGET_HARD_QUAD"
-+ "fmulq\t%1, %2, %0"
-+ [(set_attr "type" "fpmul")])
-+
-+(define_insn "muldf3"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (mult:DF (match_operand:DF 1 "register_operand" "e")
-+ (match_operand:DF 2 "register_operand" "e")))]
-+ "TARGET_FPU"
-+ "fmuld\t%1, %2, %0"
-+ [(set_attr "type" "fpmul")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "mulsf3"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (mult:SF (match_operand:SF 1 "register_operand" "f")
-+ (match_operand:SF 2 "register_operand" "f")))]
-+ "TARGET_FPU"
-+ "fmuls\t%1, %2, %0"
-+ [(set_attr "type" "fpmul")])
-+
-+(define_insn "fmadf4"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (fma:DF (match_operand:DF 1 "register_operand" "e")
-+ (match_operand:DF 2 "register_operand" "e")
-+ (match_operand:DF 3 "register_operand" "e")))]
-+ "TARGET_FMAF"
-+ "fmaddd\t%1, %2, %3, %0"
-+ [(set_attr "type" "fpmul")])
-+
-+(define_insn "fmsdf4"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (fma:DF (match_operand:DF 1 "register_operand" "e")
-+ (match_operand:DF 2 "register_operand" "e")
-+ (neg:DF (match_operand:DF 3 "register_operand" "e"))))]
-+ "TARGET_FMAF"
-+ "fmsubd\t%1, %2, %3, %0"
-+ [(set_attr "type" "fpmul")])
-+
-+(define_insn "*nfmadf4"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (neg:DF (fma:DF (match_operand:DF 1 "register_operand" "e")
-+ (match_operand:DF 2 "register_operand" "e")
-+ (match_operand:DF 3 "register_operand" "e"))))]
-+ "TARGET_FMAF"
-+ "fnmaddd\t%1, %2, %3, %0"
-+ [(set_attr "type" "fpmul")])
-+
-+(define_insn "*nfmsdf4"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (neg:DF (fma:DF (match_operand:DF 1 "register_operand" "e")
-+ (match_operand:DF 2 "register_operand" "e")
-+ (neg:DF (match_operand:DF 3 "register_operand" "e")))))]
-+ "TARGET_FMAF"
-+ "fnmsubd\t%1, %2, %3, %0"
-+ [(set_attr "type" "fpmul")])
-+
-+(define_insn "fmasf4"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (fma:SF (match_operand:SF 1 "register_operand" "f")
-+ (match_operand:SF 2 "register_operand" "f")
-+ (match_operand:SF 3 "register_operand" "f")))]
-+ "TARGET_FMAF"
-+ "fmadds\t%1, %2, %3, %0"
-+ [(set_attr "type" "fpmul")])
-+
-+(define_insn "fmssf4"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (fma:SF (match_operand:SF 1 "register_operand" "f")
-+ (match_operand:SF 2 "register_operand" "f")
-+ (neg:SF (match_operand:SF 3 "register_operand" "f"))))]
-+ "TARGET_FMAF"
-+ "fmsubs\t%1, %2, %3, %0"
-+ [(set_attr "type" "fpmul")])
-+
-+(define_insn "*nfmasf4"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (neg:SF (fma:SF (match_operand:SF 1 "register_operand" "f")
-+ (match_operand:SF 2 "register_operand" "f")
-+ (match_operand:SF 3 "register_operand" "f"))))]
-+ "TARGET_FMAF"
-+ "fnmadds\t%1, %2, %3, %0"
-+ [(set_attr "type" "fpmul")])
-+
-+(define_insn "*nfmssf4"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (neg:SF (fma:SF (match_operand:SF 1 "register_operand" "f")
-+ (match_operand:SF 2 "register_operand" "f")
-+ (neg:SF (match_operand:SF 3 "register_operand" "f")))))]
-+ "TARGET_FMAF"
-+ "fnmsubs\t%1, %2, %3, %0"
-+ [(set_attr "type" "fpmul")])
-+
-+(define_insn "*muldf3_extend"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f"))
-+ (float_extend:DF (match_operand:SF 2 "register_operand" "f"))))]
-+ "TARGET_FSMULD"
-+ "fsmuld\t%1, %2, %0"
-+ [(set_attr "type" "fpmul")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "*multf3_extend"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (mult:TF (float_extend:TF (match_operand:DF 1 "register_operand" "e"))
-+ (float_extend:TF (match_operand:DF 2 "register_operand" "e"))))]
-+ "(TARGET_V8 || TARGET_V9) && TARGET_FPU && TARGET_HARD_QUAD"
-+ "fdmulq\t%1, %2, %0"
-+ [(set_attr "type" "fpmul")])
-+
-+(define_expand "divtf3"
-+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
-+ (div:TF (match_operand:TF 1 "general_operand" "")
-+ (match_operand:TF 2 "general_operand" "")))]
-+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-+ "emit_tfmode_binop (DIV, operands); DONE;")
-+
-+;; don't have timing for quad-prec. divide.
-+(define_insn "*divtf3_hq"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (div:TF (match_operand:TF 1 "register_operand" "e")
-+ (match_operand:TF 2 "register_operand" "e")))]
-+ "TARGET_FPU && TARGET_HARD_QUAD"
-+ "fdivq\t%1, %2, %0"
-+ [(set_attr "type" "fpdivs")])
-+
-+(define_expand "divdf3"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (div:DF (match_operand:DF 1 "register_operand" "e")
-+ (match_operand:DF 2 "register_operand" "e")))]
-+ "TARGET_FPU"
-+ "")
-+
-+(define_insn "*divdf3_nofix"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (div:DF (match_operand:DF 1 "register_operand" "e")
-+ (match_operand:DF 2 "register_operand" "e")))]
-+ "TARGET_FPU && !sparc_fix_ut699"
-+ "fdivd\t%1, %2, %0"
-+ [(set_attr "type" "fpdivd")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "*divdf3_fix"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (div:DF (match_operand:DF 1 "register_operand" "e")
-+ (match_operand:DF 2 "register_operand" "e")))]
-+ "TARGET_FPU && sparc_fix_ut699"
-+ "fdivd\t%1, %2, %0\n\tstd\t%0, [%%sp-8]\n\tnop"
-+ [(set_attr "type" "fpdivd")
-+ (set_attr "fptype" "double")
-+ (set_attr "length" "3")])
-+
-+(define_insn "divsf3"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (div:SF (match_operand:SF 1 "register_operand" "f")
-+ (match_operand:SF 2 "register_operand" "f")))]
-+ "TARGET_FPU && !sparc_fix_ut699"
-+ "fdivs\t%1, %2, %0"
-+ [(set_attr "type" "fpdivs")])
-+
-+(define_expand "negtf2"
-+ [(set (match_operand:TF 0 "register_operand" "")
-+ (neg:TF (match_operand:TF 1 "register_operand" "")))]
-+ "TARGET_FPU"
-+ "")
-+
-+(define_insn "*negtf2_hq"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (neg:TF (match_operand:TF 1 "register_operand" "e")))]
-+ "TARGET_FPU && TARGET_HARD_QUAD"
-+ "fnegq\t%1, %0"
-+ [(set_attr "type" "fpmove")])
-+
-+(define_insn_and_split "*negtf2"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (neg:TF (match_operand:TF 1 "register_operand" "e")))]
-+ "TARGET_FPU && !TARGET_HARD_QUAD"
-+ "#"
-+ "&& reload_completed"
-+ [(clobber (const_int 0))]
-+{
-+ rtx set_dest = operands[0];
-+ rtx set_src = operands[1];
-+ rtx dest1, dest2;
-+ rtx src1, src2;
-+
-+ dest1 = gen_df_reg (set_dest, 0);
-+ dest2 = gen_df_reg (set_dest, 1);
-+ src1 = gen_df_reg (set_src, 0);
-+ src2 = gen_df_reg (set_src, 1);
-+
-+ /* Now emit using the real source and destination we found, swapping
-+ the order if we detect overlap. */
-+ if (reg_overlap_mentioned_p (dest1, src2))
-+ {
-+ emit_insn (gen_movdf (dest2, src2));
-+ emit_insn (gen_negdf2 (dest1, src1));
-+ }
-+ else
-+ {
-+ emit_insn (gen_negdf2 (dest1, src1));
-+ if (REGNO (dest2) != REGNO (src2))
-+ emit_insn (gen_movdf (dest2, src2));
-+ }
-+ DONE;
-+}
-+ [(set_attr "length" "2")])
-+
-+(define_expand "negdf2"
-+ [(set (match_operand:DF 0 "register_operand" "")
-+ (neg:DF (match_operand:DF 1 "register_operand" "")))]
-+ "TARGET_FPU"
-+ "")
-+
-+(define_insn_and_split "*negdf2_notv9"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (neg:DF (match_operand:DF 1 "register_operand" "e")))]
-+ "TARGET_FPU && !TARGET_V9"
-+ "#"
-+ "&& reload_completed"
-+ [(clobber (const_int 0))]
-+{
-+ rtx set_dest = operands[0];
-+ rtx set_src = operands[1];
-+ rtx dest1, dest2;
-+ rtx src1, src2;
-+
-+ dest1 = gen_highpart (SFmode, set_dest);
-+ dest2 = gen_lowpart (SFmode, set_dest);
-+ src1 = gen_highpart (SFmode, set_src);
-+ src2 = gen_lowpart (SFmode, set_src);
-+
-+ /* Now emit using the real source and destination we found, swapping
-+ the order if we detect overlap. */
-+ if (reg_overlap_mentioned_p (dest1, src2))
-+ {
-+ emit_insn (gen_movsf (dest2, src2));
-+ emit_insn (gen_negsf2 (dest1, src1));
-+ }
-+ else
-+ {
-+ emit_insn (gen_negsf2 (dest1, src1));
-+ if (REGNO (dest2) != REGNO (src2))
-+ emit_insn (gen_movsf (dest2, src2));
-+ }
-+ DONE;
-+}
-+ [(set_attr "length" "2")])
-+
-+(define_insn "*negdf2_v9"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (neg:DF (match_operand:DF 1 "register_operand" "e")))]
-+ "TARGET_FPU && TARGET_V9"
-+ "fnegd\t%1, %0"
-+ [(set_attr "type" "fpmove")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "negsf2"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (neg:SF (match_operand:SF 1 "register_operand" "f")))]
-+ "TARGET_FPU"
-+ "fnegs\t%1, %0"
-+ [(set_attr "type" "fpmove")])
-+
-+(define_expand "abstf2"
-+ [(set (match_operand:TF 0 "register_operand" "")
-+ (abs:TF (match_operand:TF 1 "register_operand" "")))]
-+ "TARGET_FPU"
-+ "")
-+
-+(define_insn "*abstf2_hq"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (abs:TF (match_operand:TF 1 "register_operand" "e")))]
-+ "TARGET_FPU && TARGET_HARD_QUAD"
-+ "fabsq\t%1, %0"
-+ [(set_attr "type" "fpmove")])
-+
-+(define_insn_and_split "*abstf2"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (abs:TF (match_operand:TF 1 "register_operand" "e")))]
-+ "TARGET_FPU && !TARGET_HARD_QUAD"
-+ "#"
-+ "&& reload_completed"
-+ [(clobber (const_int 0))]
-+{
-+ rtx set_dest = operands[0];
-+ rtx set_src = operands[1];
-+ rtx dest1, dest2;
-+ rtx src1, src2;
-+
-+ dest1 = gen_df_reg (set_dest, 0);
-+ dest2 = gen_df_reg (set_dest, 1);
-+ src1 = gen_df_reg (set_src, 0);
-+ src2 = gen_df_reg (set_src, 1);
-+
-+ /* Now emit using the real source and destination we found, swapping
-+ the order if we detect overlap. */
-+ if (reg_overlap_mentioned_p (dest1, src2))
-+ {
-+ emit_insn (gen_movdf (dest2, src2));
-+ emit_insn (gen_absdf2 (dest1, src1));
-+ }
-+ else
-+ {
-+ emit_insn (gen_absdf2 (dest1, src1));
-+ if (REGNO (dest2) != REGNO (src2))
-+ emit_insn (gen_movdf (dest2, src2));
-+ }
-+ DONE;
-+}
-+ [(set_attr "length" "2")])
-+
-+(define_expand "absdf2"
-+ [(set (match_operand:DF 0 "register_operand" "")
-+ (abs:DF (match_operand:DF 1 "register_operand" "")))]
-+ "TARGET_FPU"
-+ "")
-+
-+(define_insn_and_split "*absdf2_notv9"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (abs:DF (match_operand:DF 1 "register_operand" "e")))]
-+ "TARGET_FPU && !TARGET_V9"
-+ "#"
-+ "&& reload_completed"
-+ [(clobber (const_int 0))]
-+{
-+ rtx set_dest = operands[0];
-+ rtx set_src = operands[1];
-+ rtx dest1, dest2;
-+ rtx src1, src2;
-+
-+ dest1 = gen_highpart (SFmode, set_dest);
-+ dest2 = gen_lowpart (SFmode, set_dest);
-+ src1 = gen_highpart (SFmode, set_src);
-+ src2 = gen_lowpart (SFmode, set_src);
-+
-+ /* Now emit using the real source and destination we found, swapping
-+ the order if we detect overlap. */
-+ if (reg_overlap_mentioned_p (dest1, src2))
-+ {
-+ emit_insn (gen_movsf (dest2, src2));
-+ emit_insn (gen_abssf2 (dest1, src1));
-+ }
-+ else
-+ {
-+ emit_insn (gen_abssf2 (dest1, src1));
-+ if (REGNO (dest2) != REGNO (src2))
-+ emit_insn (gen_movsf (dest2, src2));
-+ }
-+ DONE;
-+}
-+ [(set_attr "length" "2")])
-+
-+(define_insn "*absdf2_v9"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (abs:DF (match_operand:DF 1 "register_operand" "e")))]
-+ "TARGET_FPU && TARGET_V9"
-+ "fabsd\t%1, %0"
-+ [(set_attr "type" "fpmove")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "abssf2"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (abs:SF (match_operand:SF 1 "register_operand" "f")))]
-+ "TARGET_FPU"
-+ "fabss\t%1, %0"
-+ [(set_attr "type" "fpmove")])
-+
-+(define_expand "sqrttf2"
-+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
-+ (sqrt:TF (match_operand:TF 1 "general_operand" "")))]
-+ "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
-+ "emit_tfmode_unop (SQRT, operands); DONE;")
-+
-+(define_insn "*sqrttf2_hq"
-+ [(set (match_operand:TF 0 "register_operand" "=e")
-+ (sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
-+ "TARGET_FPU && TARGET_HARD_QUAD"
-+ "fsqrtq\t%1, %0"
-+ [(set_attr "type" "fpsqrts")])
-+
-+(define_expand "sqrtdf2"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
-+ "TARGET_FPU"
-+ "")
-+
-+(define_insn "*sqrtdf2_nofix"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
-+ "TARGET_FPU && !sparc_fix_ut699"
-+ "fsqrtd\t%1, %0"
-+ [(set_attr "type" "fpsqrtd")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "*sqrtdf2_fix"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
-+ "TARGET_FPU && sparc_fix_ut699"
-+ "fsqrtd\t%1, %0\n\tstd\t%0, [%%sp-8]\n\tnop"
-+ [(set_attr "type" "fpsqrtd")
-+ (set_attr "fptype" "double")
-+ (set_attr "length" "3")])
-+
-+(define_insn "sqrtsf2"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
-+ "TARGET_FPU && !sparc_fix_ut699"
-+ "fsqrts\t%1, %0"
-+ [(set_attr "type" "fpsqrts")])
-+
-+
-+;; Arithmetic shift instructions.
-+
-+(define_insn "ashlsi3"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (ashift:SI (match_operand:SI 1 "register_operand" "r")
-+ (match_operand:SI 2 "arith_operand" "rI")))]
-+ ""
-+{
-+ if (GET_CODE (operands[2]) == CONST_INT)
-+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
-+ return "sll\t%1, %2, %0";
-+}
-+ [(set_attr "type" "shift")])
-+
-+(define_expand "ashldi3"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (ashift:DI (match_operand:DI 1 "register_operand" "r")
-+ (match_operand:SI 2 "arith_operand" "rI")))]
-+ "TARGET_ARCH64 || TARGET_V8PLUS"
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ if (GET_CODE (operands[2]) == CONST_INT)
-+ FAIL;
-+ emit_insn (gen_ashldi3_v8plus (operands[0], operands[1], operands[2]));
-+ DONE;
-+ }
-+})
-+
-+(define_insn "*ashldi3_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (ashift:DI (match_operand:DI 1 "register_operand" "r")
-+ (match_operand:SI 2 "arith_operand" "rI")))]
-+ "TARGET_ARCH64"
-+{
-+ if (GET_CODE (operands[2]) == CONST_INT)
-+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
-+ return "sllx\t%1, %2, %0";
-+}
-+ [(set_attr "type" "shift")])
-+
-+(define_insn "ashldi3_v8plus"
-+ [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
-+ (ashift:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
-+ (match_operand:SI 2 "arith_operand" "rI,rI,rI")))
-+ (clobber (match_scratch:SI 3 "=X,X,&h"))]
-+ "TARGET_V8PLUS"
-+{
-+ return output_v8plus_shift (insn ,operands, \"sllx\");
-+}
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "5,5,6")])
-+
-+(define_insn "*cmp_ccnz_ashift_1"
-+ [(set (reg:CCNZ CC_REG)
-+ (compare:CCNZ (ashift:SI (match_operand:SI 0 "register_operand" "r")
-+ (const_int 1))
-+ (const_int 0)))]
-+ ""
-+ "addcc\t%0, %0, %%g0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "*cmp_ccnz_set_ashift_1"
-+ [(set (reg:CCNZ CC_REG)
-+ (compare:CCNZ (ashift:SI (match_operand:SI 1 "register_operand" "r")
-+ (const_int 1))
-+ (const_int 0)))
-+ (set (match_operand:SI 0 "register_operand" "=r")
-+ (ashift:SI (match_dup 1) (const_int 1)))]
-+ ""
-+ "addcc\t%1, %1, %0"
-+ [(set_attr "type" "compare")])
-+
-+(define_insn "ashrsi3"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
-+ (match_operand:SI 2 "arith_operand" "rI")))]
-+ ""
-+{
-+ if (GET_CODE (operands[2]) == CONST_INT)
-+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
-+ return "sra\t%1, %2, %0";
-+}
-+ [(set_attr "type" "shift")])
-+
-+(define_insn "*ashrsi3_extend0"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (sign_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
-+ (match_operand:SI 2 "arith_operand" "rI"))))]
-+ "TARGET_ARCH64"
-+{
-+ if (GET_CODE (operands[2]) == CONST_INT)
-+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
-+ return "sra\t%1, %2, %0";
-+}
-+ [(set_attr "type" "shift")])
-+
-+;; This handles the case where
-+;; (sign_extend:DI (ashiftrt:SI (match_operand:SI) (match_operand:SI)))
-+;; but combiner "simplifies" it for us.
-+(define_insn "*ashrsi3_extend1"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (ashiftrt:DI (ashift:DI (subreg:DI (match_operand:SI 1 "register_operand" "r") 0)
-+ (const_int 32))
-+ (match_operand:SI 2 "small_int_operand" "I")))]
-+ "TARGET_ARCH64 && INTVAL (operands[2]) >= 32 && INTVAL (operands[2]) < 64"
-+{
-+ operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
-+ return "sra\t%1, %2, %0";
-+}
-+ [(set_attr "type" "shift")])
-+
-+;; This handles the case where
-+;; (ashiftrt:DI (sign_extend:DI (match_operand:SI)) (const_int))
-+;; but combiner "simplifies" it for us.
-+(define_insn "*ashrsi3_extend2"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (sign_extract:DI (subreg:DI (match_operand:SI 1 "register_operand" "r") 0)
-+ (match_operand 2 "small_int_operand" "I")
-+ (const_int 32)))]
-+ "TARGET_ARCH64 && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 32"
-+{
-+ operands[2] = GEN_INT (32 - INTVAL (operands[2]));
-+ return "sra\t%1, %2, %0";
-+}
-+ [(set_attr "type" "shift")])
-+
-+(define_expand "ashrdi3"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
-+ (match_operand:SI 2 "arith_operand" "rI")))]
-+ "TARGET_ARCH64 || TARGET_V8PLUS"
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ if (GET_CODE (operands[2]) == CONST_INT)
-+ FAIL; /* prefer generic code in this case */
-+ emit_insn (gen_ashrdi3_v8plus (operands[0], operands[1], operands[2]));
-+ DONE;
-+ }
-+})
-+
-+(define_insn "*ashrdi3_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
-+ (match_operand:SI 2 "arith_operand" "rI")))]
-+ "TARGET_ARCH64"
-+{
-+ if (GET_CODE (operands[2]) == CONST_INT)
-+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
-+ return "srax\t%1, %2, %0";
-+}
-+ [(set_attr "type" "shift")])
-+
-+(define_insn "ashrdi3_v8plus"
-+ [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
-+ (ashiftrt:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
-+ (match_operand:SI 2 "arith_operand" "rI,rI,rI")))
-+ (clobber (match_scratch:SI 3 "=X,X,&h"))]
-+ "TARGET_V8PLUS"
-+{
-+ return output_v8plus_shift (insn, operands, \"srax\");
-+}
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "5,5,6")])
-+
-+(define_insn "lshrsi3"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
-+ (match_operand:SI 2 "arith_operand" "rI")))]
-+ ""
-+{
-+ if (GET_CODE (operands[2]) == CONST_INT)
-+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
-+ return "srl\t%1, %2, %0";
-+}
-+ [(set_attr "type" "shift")])
-+
-+(define_insn "*lshrsi3_extend0"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (zero_extend:DI
-+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
-+ (match_operand:SI 2 "arith_operand" "rI"))))]
-+ "TARGET_ARCH64"
-+{
-+ if (GET_CODE (operands[2]) == CONST_INT)
-+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
-+ return "srl\t%1, %2, %0";
-+}
-+ [(set_attr "type" "shift")])
-+
-+;; This handles the case where
-+;; (zero_extend:DI (lshiftrt:SI (match_operand:SI) (match_operand:SI)))
-+;; but combiner "simplifies" it for us.
-+(define_insn "*lshrsi3_extend1"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (and:DI (subreg:DI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
-+ (match_operand:SI 2 "arith_operand" "rI")) 0)
-+ (match_operand 3 "const_int_operand" "")))]
-+ "TARGET_ARCH64 && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) == 0xffffffff"
-+{
-+ if (GET_CODE (operands[2]) == CONST_INT)
-+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
-+ return "srl\t%1, %2, %0";
-+}
-+ [(set_attr "type" "shift")])
-+
-+;; This handles the case where
-+;; (lshiftrt:DI (zero_extend:DI (match_operand:SI)) (const_int))
-+;; but combiner "simplifies" it for us.
-+(define_insn "*lshrsi3_extend2"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (zero_extract:DI (subreg:DI (match_operand:SI 1 "register_operand" "r") 0)
-+ (match_operand 2 "small_int_operand" "I")
-+ (const_int 32)))]
-+ "TARGET_ARCH64 && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 32"
-+{
-+ operands[2] = GEN_INT (32 - INTVAL (operands[2]));
-+ return "srl\t%1, %2, %0";
-+}
-+ [(set_attr "type" "shift")])
-+
-+(define_expand "lshrdi3"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
-+ (match_operand:SI 2 "arith_operand" "rI")))]
-+ "TARGET_ARCH64 || TARGET_V8PLUS"
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ if (GET_CODE (operands[2]) == CONST_INT)
-+ FAIL;
-+ emit_insn (gen_lshrdi3_v8plus (operands[0], operands[1], operands[2]));
-+ DONE;
-+ }
-+})
-+
-+(define_insn "*lshrdi3_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
-+ (match_operand:SI 2 "arith_operand" "rI")))]
-+ "TARGET_ARCH64"
-+{
-+ if (GET_CODE (operands[2]) == CONST_INT)
-+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
-+ return "srlx\t%1, %2, %0";
-+}
-+ [(set_attr "type" "shift")])
-+
-+(define_insn "lshrdi3_v8plus"
-+ [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
-+ (lshiftrt:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
-+ (match_operand:SI 2 "arith_operand" "rI,rI,rI")))
-+ (clobber (match_scratch:SI 3 "=X,X,&h"))]
-+ "TARGET_V8PLUS"
-+{
-+ return output_v8plus_shift (insn, operands, \"srlx\");
-+}
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "5,5,6")])
-+
-+(define_insn ""
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (ashiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
-+ (const_int 32)) 4)
-+ (match_operand:SI 2 "small_int_operand" "I")))]
-+ "TARGET_ARCH64 && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32"
-+{
-+ operands[2] = GEN_INT (INTVAL (operands[2]) + 32);
-+ return "srax\t%1, %2, %0";
-+}
-+ [(set_attr "type" "shift")])
-+
-+(define_insn ""
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (lshiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
-+ (const_int 32)) 4)
-+ (match_operand:SI 2 "small_int_operand" "I")))]
-+ "TARGET_ARCH64 && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32"
-+{
-+ operands[2] = GEN_INT (INTVAL (operands[2]) + 32);
-+ return "srlx\t%1, %2, %0";
-+}
-+ [(set_attr "type" "shift")])
-+
-+(define_insn ""
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (ashiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
-+ (match_operand:SI 2 "small_int_operand" "I")) 4)
-+ (match_operand:SI 3 "small_int_operand" "I")))]
-+ "TARGET_ARCH64
-+ && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 32
-+ && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) < 32
-+ && (unsigned HOST_WIDE_INT) (INTVAL (operands[2]) + INTVAL (operands[3])) < 64"
-+{
-+ operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]));
-+
-+ return "srax\t%1, %2, %0";
-+}
-+ [(set_attr "type" "shift")])
-+
-+(define_insn ""
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (lshiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
-+ (match_operand:SI 2 "small_int_operand" "I")) 4)
-+ (match_operand:SI 3 "small_int_operand" "I")))]
-+ "TARGET_ARCH64
-+ && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 32
-+ && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) < 32
-+ && (unsigned HOST_WIDE_INT) (INTVAL (operands[2]) + INTVAL (operands[3])) < 64"
-+{
-+ operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]));
-+
-+ return "srlx\t%1, %2, %0";
-+}
-+ [(set_attr "type" "shift")])
-+
-+
-+;; Unconditional and other jump instructions.
-+
-+(define_expand "jump"
-+ [(set (pc) (label_ref (match_operand 0 "" "")))]
-+ "")
-+
-+(define_insn "*jump_ubranch"
-+ [(set (pc) (label_ref (match_operand 0 "" "")))]
-+ "!TARGET_CBCOND"
-+{
-+ return output_ubranch (operands[0], insn);
-+}
-+ [(set_attr "type" "uncond_branch")])
-+
-+(define_insn "*jump_cbcond"
-+ [(set (pc) (label_ref (match_operand 0 "" "")))]
-+ "TARGET_CBCOND"
-+{
-+ return output_ubranch (operands[0], insn);
-+}
-+ [(set_attr "type" "uncond_cbcond")])
-+
-+(define_expand "tablejump"
-+ [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
-+ (use (label_ref (match_operand 1 "" "")))])]
-+ ""
-+{
-+ gcc_assert (GET_MODE (operands[0]) == CASE_VECTOR_MODE);
-+
-+ /* In pic mode, our address differences are against the base of the
-+ table. Add that base value back in; CSE ought to be able to combine
-+ the two address loads. */
-+ if (flag_pic)
-+ {
-+ rtx tmp, tmp2;
-+ tmp = gen_rtx_LABEL_REF (Pmode, operands[1]);
-+ tmp2 = operands[0];
-+ if (CASE_VECTOR_MODE != Pmode)
-+ tmp2 = gen_rtx_SIGN_EXTEND (Pmode, tmp2);
-+ tmp = gen_rtx_PLUS (Pmode, tmp2, tmp);
-+ operands[0] = memory_address (Pmode, tmp);
-+ }
-+})
-+
-+(define_insn "*tablejump<P:mode>"
-+ [(set (pc) (match_operand:P 0 "address_operand" "p"))
-+ (use (label_ref (match_operand 1 "" "")))]
-+ ""
-+ "jmp\t%a0%#"
-+ [(set_attr "type" "uncond_branch")])
-+
-+
-+;; Jump to subroutine instructions.
-+
-+(define_expand "call"
-+ ;; Note that this expression is not used for generating RTL.
-+ ;; All the RTL is generated explicitly below.
-+ [(call (match_operand 0 "call_operand" "")
-+ (match_operand 3 "" "i"))]
-+ ;; operands[2] is next_arg_register
-+ ;; operands[3] is struct_value_size_rtx.
-+ ""
-+{
-+ rtx fn_rtx;
-+
-+ gcc_assert (MEM_P (operands[0]) && GET_MODE (operands[0]) == FUNCTION_MODE);
-+
-+ gcc_assert (GET_CODE (operands[3]) == CONST_INT);
-+
-+ if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
-+ {
-+ /* This is really a PIC sequence. We want to represent
-+ it as a funny jump so its delay slots can be filled.
-+
-+ ??? But if this really *is* a CALL, will not it clobber the
-+ call-clobbered registers? We lose this if it is a JUMP_INSN.
-+ Why cannot we have delay slots filled if it were a CALL? */
-+
-+ /* We accept negative sizes for untyped calls. */
-+ if (TARGET_ARCH32 && INTVAL (operands[3]) != 0)
-+ emit_jump_insn
-+ (gen_rtx_PARALLEL
-+ (VOIDmode,
-+ gen_rtvec (3,
-+ gen_rtx_SET (pc_rtx, XEXP (operands[0], 0)),
-+ operands[3],
-+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
-+ else
-+ emit_jump_insn
-+ (gen_rtx_PARALLEL
-+ (VOIDmode,
-+ gen_rtvec (2,
-+ gen_rtx_SET (pc_rtx, XEXP (operands[0], 0)),
-+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
-+ goto finish_call;
-+ }
-+
-+ fn_rtx = operands[0];
-+
-+ /* We accept negative sizes for untyped calls. */
-+ if (TARGET_ARCH32 && INTVAL (operands[3]) != 0)
-+ sparc_emit_call_insn
-+ (gen_rtx_PARALLEL
-+ (VOIDmode,
-+ gen_rtvec (3, gen_rtx_CALL (VOIDmode, fn_rtx, const0_rtx),
-+ operands[3],
-+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))),
-+ XEXP (fn_rtx, 0));
-+ else
-+ sparc_emit_call_insn
-+ (gen_rtx_PARALLEL
-+ (VOIDmode,
-+ gen_rtvec (2, gen_rtx_CALL (VOIDmode, fn_rtx, const0_rtx),
-+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))),
-+ XEXP (fn_rtx, 0));
-+
-+ finish_call:
-+
-+ DONE;
-+})
-+
-+;; We can't use the same pattern for these two insns, because then registers
-+;; in the address may not be properly reloaded.
-+
-+(define_insn "*call_address<P:mode>"
-+ [(call (mem:P (match_operand:P 0 "address_operand" "p"))
-+ (match_operand 1 "" ""))
-+ (clobber (reg:P O7_REG))]
-+ ;;- Do not use operand 1 for most machines.
-+ ""
-+ "call\t%a0, %1%#"
-+ [(set_attr "type" "call")])
-+
-+(define_insn "*call_symbolic<P:mode>"
-+ [(call (mem:P (match_operand:P 0 "symbolic_operand" "s"))
-+ (match_operand 1 "" ""))
-+ (clobber (reg:P O7_REG))]
-+ ;;- Do not use operand 1 for most machines.
-+ ""
-+ "call\t%a0, %1%#"
-+ [(set_attr "type" "call")])
-+
-+;; This is a call that wants a structure value.
-+;; There is no such critter for v9 (??? we may need one anyway).
-+(define_insn "*call_address_struct_value_sp32"
-+ [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
-+ (match_operand 1 "" ""))
-+ (match_operand 2 "immediate_operand" "")
-+ (clobber (reg:SI O7_REG))]
-+ ;;- Do not use operand 1 for most machines.
-+ "TARGET_ARCH32 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
-+{
-+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0xfff);
-+ return "call\t%a0, %1\n\t nop\n\tunimp\t%2";
-+}
-+ [(set_attr "type" "call_no_delay_slot")
-+ (set_attr "length" "3")])
-+
-+;; This is a call that wants a structure value.
-+;; There is no such critter for v9 (??? we may need one anyway).
-+(define_insn "*call_symbolic_struct_value_sp32"
-+ [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
-+ (match_operand 1 "" ""))
-+ (match_operand 2 "immediate_operand" "")
-+ (clobber (reg:SI O7_REG))]
-+ ;;- Do not use operand 1 for most machines.
-+ "TARGET_ARCH32 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
-+{
-+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0xfff);
-+ return "call\t%a0, %1\n\t nop\n\tunimp\t%2";
-+}
-+ [(set_attr "type" "call_no_delay_slot")
-+ (set_attr "length" "3")])
-+
-+;; This is a call that may want a structure value. This is used for
-+;; untyped_calls.
-+(define_insn "*call_address_untyped_struct_value_sp32"
-+ [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
-+ (match_operand 1 "" ""))
-+ (match_operand 2 "immediate_operand" "")
-+ (clobber (reg:SI O7_REG))]
-+ ;;- Do not use operand 1 for most machines.
-+ "TARGET_ARCH32 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
-+ "call\t%a0, %1\n\t nop\n\tnop"
-+ [(set_attr "type" "call_no_delay_slot")
-+ (set_attr "length" "3")])
-+
-+;; This is a call that may want a structure value. This is used for
-+;; untyped_calls.
-+(define_insn "*call_symbolic_untyped_struct_value_sp32"
-+ [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
-+ (match_operand 1 "" ""))
-+ (match_operand 2 "immediate_operand" "")
-+ (clobber (reg:SI O7_REG))]
-+ ;;- Do not use operand 1 for most machines.
-+ "TARGET_ARCH32 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
-+ "call\t%a0, %1\n\t nop\n\tnop"
-+ [(set_attr "type" "call_no_delay_slot")
-+ (set_attr "length" "3")])
-+
-+(define_expand "call_value"
-+ ;; Note that this expression is not used for generating RTL.
-+ ;; All the RTL is generated explicitly below.
-+ [(set (match_operand 0 "register_operand" "")
-+ (call (match_operand 1 "call_operand" "")
-+ (match_operand 4 "" "")))]
-+ ;; operand 2 is stack_size_rtx
-+ ;; operand 3 is next_arg_register
-+ ""
-+{
-+ rtx fn_rtx;
-+ rtvec vec;
-+
-+ gcc_assert (MEM_P (operands[1]) && GET_MODE (operands[1]) == FUNCTION_MODE);
-+
-+ fn_rtx = operands[1];
-+
-+ vec = gen_rtvec (2,
-+ gen_rtx_SET (operands[0],
-+ gen_rtx_CALL (VOIDmode, fn_rtx, const0_rtx)),
-+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)));
-+
-+ sparc_emit_call_insn (gen_rtx_PARALLEL (VOIDmode, vec), XEXP (fn_rtx, 0));
-+
-+ DONE;
-+})
-+
-+(define_insn "*call_value_address<P:mode>"
-+ [(set (match_operand 0 "" "")
-+ (call (mem:P (match_operand:P 1 "address_operand" "p"))
-+ (match_operand 2 "" "")))
-+ (clobber (reg:P O7_REG))]
-+ ;;- Do not use operand 2 for most machines.
-+ ""
-+ "call\t%a1, %2%#"
-+ [(set_attr "type" "call")])
-+
-+(define_insn "*call_value_symbolic<P:mode>"
-+ [(set (match_operand 0 "" "")
-+ (call (mem:P (match_operand:P 1 "symbolic_operand" "s"))
-+ (match_operand 2 "" "")))
-+ (clobber (reg:P O7_REG))]
-+ ;;- Do not use operand 2 for most machines.
-+ ""
-+ "call\t%a1, %2%#"
-+ [(set_attr "type" "call")])
-+
-+(define_expand "untyped_call"
-+ [(parallel [(call (match_operand 0 "" "")
-+ (const_int 0))
-+ (match_operand:BLK 1 "memory_operand" "")
-+ (match_operand 2 "" "")])]
-+ ""
-+{
-+ rtx valreg1 = gen_rtx_REG (DImode, 8);
-+ rtx result = operands[1];
-+
-+ /* Pass constm1 to indicate that it may expect a structure value, but
-+ we don't know what size it is. */
-+ emit_call_insn (gen_call (operands[0], const0_rtx, NULL, constm1_rtx));
-+
-+ /* Save the function value registers. */
-+ emit_move_insn (adjust_address (result, DImode, 0), valreg1);
-+ if (TARGET_FPU)
-+ {
-+ rtx valreg2 = gen_rtx_REG (TARGET_ARCH64 ? TFmode : DFmode, 32);
-+ emit_move_insn (adjust_address (result, TARGET_ARCH64 ? TFmode : DFmode, 8),
-+ valreg2);
-+ }
-+
-+ /* The optimizer does not know that the call sets the function value
-+ registers we stored in the result block. We avoid problems by
-+ claiming that all hard registers are used and clobbered at this
-+ point. */
-+ emit_insn (gen_blockage ());
-+
-+ DONE;
-+})
-+
-+
-+;; Tail call instructions.
-+
-+(define_expand "sibcall"
-+ [(parallel [(call (match_operand 0 "call_operand" "") (const_int 0))
-+ (return)])]
-+ ""
-+ "")
-+
-+(define_insn "*sibcall_symbolic<P:mode>"
-+ [(call (mem:P (match_operand:P 0 "symbolic_operand" "s"))
-+ (match_operand 1 "" ""))
-+ (return)]
-+ ""
-+{
-+ return output_sibcall (insn, operands[0]);
-+}
-+ [(set_attr "type" "sibcall")])
-+
-+(define_expand "sibcall_value"
-+ [(parallel [(set (match_operand 0 "register_operand")
-+ (call (match_operand 1 "call_operand" "") (const_int 0)))
-+ (return)])]
-+ ""
-+ "")
-+
-+(define_insn "*sibcall_value_symbolic<P:mode>"
-+ [(set (match_operand 0 "" "")
-+ (call (mem:P (match_operand:P 1 "symbolic_operand" "s"))
-+ (match_operand 2 "" "")))
-+ (return)]
-+ ""
-+{
-+ return output_sibcall (insn, operands[1]);
-+}
-+ [(set_attr "type" "sibcall")])
-+
-+
-+;; Special instructions.
-+
-+(define_expand "prologue"
-+ [(const_int 0)]
-+ ""
-+{
-+ if (TARGET_FLAT)
-+ sparc_flat_expand_prologue ();
-+ else
-+ sparc_expand_prologue ();
-+ DONE;
-+})
-+
-+;; The "register window save" insn is modelled as follows. The dwarf2
-+;; information is manually added in emit_window_save.
-+
-+(define_insn "window_save"
-+ [(unspec_volatile [(match_operand 0 "arith_operand" "rI")] UNSPECV_SAVEW)]
-+ "!TARGET_FLAT"
-+ "save\t%%sp, %0, %%sp"
-+ [(set_attr "type" "savew")])
-+
-+(define_expand "epilogue"
-+ [(return)]
-+ ""
-+{
-+ if (TARGET_FLAT)
-+ sparc_flat_expand_epilogue (false);
-+ else
-+ sparc_expand_epilogue (false);
-+})
-+
-+(define_expand "sibcall_epilogue"
-+ [(return)]
-+ ""
-+{
-+ if (TARGET_FLAT)
-+ sparc_flat_expand_epilogue (false);
-+ else
-+ sparc_expand_epilogue (false);
-+ DONE;
-+})
-+
-+(define_expand "eh_return"
-+ [(use (match_operand 0 "general_operand" ""))]
-+ ""
-+{
-+ emit_move_insn (gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM), operands[0]);
-+ emit_jump_insn (gen_eh_return_internal ());
-+ emit_barrier ();
-+ DONE;
-+})
-+
-+(define_insn_and_split "eh_return_internal"
-+ [(eh_return)]
-+ ""
-+ "#"
-+ "epilogue_completed"
-+ [(return)]
-+{
-+ if (TARGET_FLAT)
-+ sparc_flat_expand_epilogue (true);
-+ else
-+ sparc_expand_epilogue (true);
-+})
-+
-+(define_expand "return"
-+ [(return)]
-+ "sparc_can_use_return_insn_p ()"
-+{
-+ if (cfun->calls_alloca)
-+ emit_insn (gen_frame_blockage ());
-+})
-+
-+(define_insn "*return_internal"
-+ [(return)]
-+ ""
-+{
-+ return output_return (insn);
-+}
-+ [(set_attr "type" "return")
-+ (set (attr "length")
-+ (cond [(eq_attr "calls_eh_return" "true")
-+ (if_then_else (eq_attr "delayed_branch" "true")
-+ (if_then_else (ior (eq_attr "isa" "v9")
-+ (eq_attr "flat" "true"))
-+ (const_int 2)
-+ (const_int 3))
-+ (if_then_else (eq_attr "flat" "true")
-+ (const_int 3)
-+ (const_int 4)))
-+ (ior (eq_attr "leaf_function" "true") (eq_attr "flat" "true"))
-+ (if_then_else (eq_attr "empty_delay_slot" "true")
-+ (const_int 2)
-+ (const_int 1))
-+ (eq_attr "empty_delay_slot" "true")
-+ (if_then_else (eq_attr "delayed_branch" "true")
-+ (const_int 2)
-+ (const_int 3))
-+ ] (const_int 1)))])
-+
-+;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
-+;; all of memory. This blocks insns from being moved across this point.
-+
-+(define_insn "blockage"
-+ [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
-+ ""
-+ ""
-+ [(set_attr "length" "0")])
-+
-+;; Do not schedule instructions accessing memory before this point.
-+
-+(define_expand "frame_blockage"
-+ [(set (match_dup 0)
-+ (unspec:BLK [(match_dup 1)] UNSPEC_FRAME_BLOCKAGE))]
-+ ""
-+{
-+ operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
-+ MEM_VOLATILE_P (operands[0]) = 1;
-+ operands[1] = stack_pointer_rtx;
-+})
-+
-+(define_insn "*frame_blockage<P:mode>"
-+ [(set (match_operand:BLK 0 "" "")
-+ (unspec:BLK [(match_operand:P 1 "" "")] UNSPEC_FRAME_BLOCKAGE))]
-+ ""
-+ ""
-+ [(set_attr "length" "0")])
-+
-+;; We use membar #Sync for the speculation barrier on V9.
-+
-+(define_insn "speculation_barrier"
-+ [(unspec_volatile [(const_int 0)] UNSPECV_SPECULATION_BARRIER)]
-+ "TARGET_V9"
-+ "membar\t64"
-+ [(set_attr "type" "multi")])
-+
-+(define_expand "probe_stack"
-+ [(set (match_operand 0 "memory_operand" "") (const_int 0))]
-+ ""
-+{
-+ operands[0]
-+ = adjust_address (operands[0], GET_MODE (operands[0]), SPARC_STACK_BIAS);
-+})
-+
-+(define_insn "probe_stack_range<P:mode>"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec_volatile:P [(match_operand:P 1 "register_operand" "0")
-+ (match_operand:P 2 "register_operand" "r")]
-+ UNSPECV_PROBE_STACK_RANGE))]
-+ ""
-+{
-+ return output_probe_stack_range (operands[0], operands[2]);
-+}
-+ [(set_attr "type" "multi")])
-+
-+;; Prepare to return any type including a structure value.
-+
-+(define_expand "untyped_return"
-+ [(match_operand:BLK 0 "memory_operand" "")
-+ (match_operand 1 "" "")]
-+ ""
-+{
-+ rtx valreg1 = gen_rtx_REG (DImode, 24);
-+ rtx result = operands[0];
-+
-+ if (TARGET_ARCH32)
-+ {
-+ rtx rtnreg = gen_rtx_REG (SImode, RETURN_ADDR_REGNUM);
-+ rtx value = gen_reg_rtx (SImode);
-+
-+ /* Fetch the instruction where we will return to and see if it's an unimp
-+ instruction (the most significant 10 bits will be zero). If so,
-+ update the return address to skip the unimp instruction. */
-+ emit_move_insn (value,
-+ gen_rtx_MEM (SImode, plus_constant (SImode, rtnreg, 8)));
-+ emit_insn (gen_lshrsi3 (value, value, GEN_INT (22)));
-+ emit_insn (gen_update_return (rtnreg, value));
-+ }
-+
-+ /* Reload the function value registers.
-+ Put USE insns before the return. */
-+ emit_move_insn (valreg1, adjust_address (result, DImode, 0));
-+ emit_use (valreg1);
-+
-+ if (TARGET_FPU)
-+ {
-+ rtx valreg2 = gen_rtx_REG (TARGET_ARCH64 ? TFmode : DFmode, 32);
-+ emit_move_insn (valreg2,
-+ adjust_address (result, TARGET_ARCH64 ? TFmode : DFmode, 8));
-+ emit_use (valreg2);
-+ }
-+
-+ /* Construct the return. */
-+ expand_naked_return ();
-+
-+ DONE;
-+})
-+
-+;; Adjust the return address conditionally. If the value of op1 is equal
-+;; to all zero then adjust the return address i.e. op0 = op0 + 4.
-+;; This is technically *half* the check required by the 32-bit SPARC
-+;; psABI. This check only ensures that an "unimp" insn was written by
-+;; the caller, but doesn't check to see if the expected size matches
-+;; (this is encoded in the 12 lower bits). This check is obsolete and
-+;; only used by the above code "untyped_return".
-+
-+(define_insn "update_return"
-+ [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
-+ (match_operand:SI 1 "register_operand" "r")] UNSPEC_UPDATE_RETURN)]
-+ "TARGET_ARCH32"
-+{
-+ if (flag_delayed_branch)
-+ return "cmp\t%1, 0\n\tbe,a\t.+8\n\t add\t%0, 4, %0";
-+ else
-+ return "cmp\t%1, 0\n\tbne\t.+12\n\t nop\n\tadd\t%0, 4, %0";
-+}
-+ [(set (attr "type") (const_string "multi"))
-+ (set (attr "length")
-+ (if_then_else (eq_attr "delayed_branch" "true")
-+ (const_int 3)
-+ (const_int 4)))])
-+
-+(define_insn "nop"
-+ [(const_int 0)]
-+ ""
-+ "nop")
-+
-+(define_expand "indirect_jump"
-+ [(set (pc) (match_operand 0 "address_operand" "p"))]
-+ ""
-+ "")
-+
-+(define_insn "*branch<P:mode>"
-+ [(set (pc) (match_operand:P 0 "address_operand" "p"))]
-+ ""
-+ "jmp\t%a0%#"
-+ [(set_attr "type" "uncond_branch")])
-+
-+(define_expand "save_stack_nonlocal"
-+ [(set (match_operand 0 "memory_operand" "")
-+ (match_operand 1 "register_operand" ""))
-+ (set (match_dup 2) (match_dup 3))]
-+ ""
-+{
-+ operands[0] = adjust_address (operands[0], Pmode, 0);
-+ operands[2] = adjust_address (operands[0], Pmode, GET_MODE_SIZE (Pmode));
-+ operands[3] = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
-+})
-+
-+(define_expand "restore_stack_nonlocal"
-+ [(set (match_operand 0 "register_operand" "")
-+ (match_operand 1 "memory_operand" ""))]
-+ ""
-+{
-+ operands[1] = adjust_address (operands[1], Pmode, 0);
-+})
-+
-+(define_expand "nonlocal_goto"
-+ [(match_operand 0 "general_operand" "")
-+ (match_operand 1 "general_operand" "")
-+ (match_operand 2 "memory_operand" "")
-+ (match_operand 3 "memory_operand" "")]
-+ ""
-+{
-+ rtx i7 = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
-+ rtx r_label = operands[1];
-+ rtx r_sp = adjust_address (operands[2], Pmode, 0);
-+ rtx r_fp = operands[3];
-+ rtx r_i7 = adjust_address (operands[2], Pmode, GET_MODE_SIZE (Pmode));
-+
-+ /* We need to flush all the register windows so that their contents will
-+ be re-synchronized by the restore insn of the target function. */
-+ if (!TARGET_FLAT)
-+ emit_insn (gen_flush_register_windows ());
-+
-+ emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
-+ emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
-+
-+ r_label = copy_to_reg (r_label);
-+
-+ /* Restore the frame pointer and stack pointer. We must use a
-+ temporary since the setjmp buffer may be a local. */
-+ r_fp = copy_to_reg (r_fp);
-+ emit_stack_restore (SAVE_NONLOCAL, r_sp);
-+ r_i7 = copy_to_reg (r_i7);
-+
-+ /* Ensure the frame pointer move is not optimized. */
-+ emit_insn (gen_blockage ());
-+ emit_clobber (hard_frame_pointer_rtx);
-+ emit_move_insn (hard_frame_pointer_rtx, r_fp);
-+ emit_move_insn (i7, r_i7);
-+
-+ /* USE of hard_frame_pointer_rtx added for consistency;
-+ not clear if really needed. */
-+ emit_use (hard_frame_pointer_rtx);
-+ emit_use (stack_pointer_rtx);
-+ emit_use (i7);
-+
-+ emit_indirect_jump (r_label);
-+ DONE;
-+})
-+
-+(define_expand "builtin_setjmp_receiver"
-+ [(label_ref (match_operand 0 "" ""))]
-+ "TARGET_VXWORKS_RTP && flag_pic"
-+{
-+ load_got_register ();
-+ DONE;
-+})
-+
-+;; Special insn to flush register windows.
-+
-+(define_insn "flush_register_windows"
-+ [(unspec_volatile [(const_int 0)] UNSPECV_FLUSHW)]
-+ ""
-+{
-+ return TARGET_V9 ? "flushw" : "ta\t3";
-+}
-+ [(set_attr "type" "flushw")])
-+
-+;; Special pattern for the FLUSH instruction.
-+
-+(define_insn "flush<P:mode>"
-+ [(unspec_volatile [(match_operand:P 0 "memory_operand" "m")] UNSPECV_FLUSH)]
-+ ""
-+{
-+ return TARGET_V9 ? "flush\t%f0" : "iflush\t%f0";
-+}
-+ [(set_attr "type" "iflush")])
-+
-+;; Special insns to load and store the 32-bit FP Status Register.
-+
-+(define_insn "ldfsr"
-+ [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] UNSPECV_LDFSR)]
-+ "TARGET_FPU"
-+ "ld\t%0, %%fsr"
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "regular")])
-+
-+(define_insn "stfsr"
-+ [(set (match_operand:SI 0 "memory_operand" "=m")
-+ (unspec_volatile:SI [(const_int 0)] UNSPECV_STFSR))]
-+ "TARGET_FPU"
-+ "st\t%%fsr, %0"
-+ [(set_attr "type" "store")])
-+
-+
-+;; Find first set instructions.
-+
-+(define_expand "popcountdi2"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (popcount:DI (match_operand:DI 1 "register_operand" "")))]
-+ "TARGET_POPC"
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_popcountdi_v8plus (operands[0], operands[1]));
-+ DONE;
-+ }
-+})
-+
-+(define_insn "*popcountdi_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (popcount:DI (match_operand:DI 1 "register_operand" "r")))]
-+ "TARGET_POPC && TARGET_ARCH64"
-+ "popc\t%1, %0")
-+
-+(define_insn "popcountdi_v8plus"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (popcount:DI (match_operand:DI 1 "register_operand" "r")))
-+ (clobber (match_scratch:SI 2 "=&h"))]
-+ "TARGET_POPC && TARGET_ARCH32"
-+{
-+ if (sparc_check_64 (operands[1], insn) <= 0)
-+ output_asm_insn ("srl\t%L1, 0, %L1", operands);
-+ return "sllx\t%H1, 32, %2\n\tor\t%L1, %2, %2\n\tpopc\t%2, %L0\n\tclr\t%H0";
-+}
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "5")])
-+
-+(define_expand "popcountsi2"
-+ [(set (match_dup 2)
-+ (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
-+ (set (match_operand:SI 0 "register_operand" "")
-+ (truncate:SI (popcount:DI (match_dup 2))))]
-+ "TARGET_POPC"
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_popcountsi_v8plus (operands[0], operands[1]));
-+ DONE;
-+ }
-+ else
-+ operands[2] = gen_reg_rtx (DImode);
-+})
-+
-+(define_insn "*popcountsi_sp64"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (truncate:SI
-+ (popcount:DI (match_operand:DI 1 "register_operand" "r"))))]
-+ "TARGET_POPC && TARGET_ARCH64"
-+ "popc\t%1, %0")
-+
-+(define_insn "popcountsi_v8plus"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (popcount:SI (match_operand:SI 1 "register_operand" "r")))]
-+ "TARGET_POPC && TARGET_ARCH32"
-+{
-+ if (sparc_check_64 (operands[1], insn) <= 0)
-+ output_asm_insn ("srl\t%1, 0, %1", operands);
-+ return "popc\t%1, %0";
-+}
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "2")])
-+
-+(define_expand "clzdi2"
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (clz:DI (match_operand:DI 1 "register_operand" "")))]
-+ "TARGET_VIS3"
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_clzdi_v8plus (operands[0], operands[1]));
-+ DONE;
-+ }
-+})
-+
-+(define_insn "*clzdi_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (clz:DI (match_operand:DI 1 "register_operand" "r")))]
-+ "TARGET_VIS3 && TARGET_ARCH64"
-+ "lzd\t%1, %0"
-+ [(set_attr "type" "lzd")])
-+
-+(define_insn "clzdi_v8plus"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (clz:DI (match_operand:DI 1 "register_operand" "r")))
-+ (clobber (match_scratch:SI 2 "=&h"))]
-+ "TARGET_VIS3 && TARGET_ARCH32"
-+{
-+ if (sparc_check_64 (operands[1], insn) <= 0)
-+ output_asm_insn ("srl\t%L1, 0, %L1", operands);
-+ return "sllx\t%H1, 32, %2\n\tor\t%L1, %2, %2\n\tlzd\t%2, %L0\n\tclr\t%H0";
-+}
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "5")])
-+
-+(define_expand "clzsi2"
-+ [(set (match_dup 2)
-+ (zero_extend:DI (match_operand:SI 1 "register_operand" "")))
-+ (set (match_dup 3)
-+ (truncate:SI (clz:DI (match_dup 2))))
-+ (set (match_operand:SI 0 "register_operand" "")
-+ (minus:SI (match_dup 3) (const_int 32)))]
-+ "TARGET_VIS3"
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_clzsi_v8plus (operands[0], operands[1]));
-+ DONE;
-+ }
-+ else
-+ {
-+ operands[2] = gen_reg_rtx (DImode);
-+ operands[3] = gen_reg_rtx (SImode);
-+ }
-+})
-+
-+(define_insn "*clzsi_sp64"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (truncate:SI
-+ (clz:DI (match_operand:DI 1 "register_operand" "r"))))]
-+ "TARGET_VIS3 && TARGET_ARCH64"
-+ "lzd\t%1, %0"
-+ [(set_attr "type" "lzd")])
-+
-+(define_insn "clzsi_v8plus"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (clz:SI (match_operand:SI 1 "register_operand" "r")))]
-+ "TARGET_VIS3 && TARGET_ARCH32"
-+{
-+ if (sparc_check_64 (operands[1], insn) <= 0)
-+ output_asm_insn ("srl\t%1, 0, %1", operands);
-+ return "lzd\t%1, %0\n\tsub\t%0, 32, %0";
-+}
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "3")])
-+
-+
-+;; Peepholes go at the end.
-+
-+;; Optimize consecutive loads or stores into ldd and std when possible.
-+;; The conditions in which we do this are very restricted and are
-+;; explained in the code for {registers,memory}_ok_for_ldd functions.
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "memory_operand" "")
-+ (const_int 0))
-+ (set (match_operand:SI 1 "memory_operand" "")
-+ (const_int 0))]
-+ "TARGET_V9
-+ && mems_ok_for_ldd_peep (operands[0], operands[1], NULL_RTX)"
-+ [(set (match_dup 0) (const_int 0))]
-+{
-+ operands[0] = widen_mem_for_ldd_peep (operands[0], operands[1], DImode);
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "memory_operand" "")
-+ (const_int 0))
-+ (set (match_operand:SI 1 "memory_operand" "")
-+ (const_int 0))]
-+ "TARGET_V9
-+ && mems_ok_for_ldd_peep (operands[1], operands[0], NULL_RTX)"
-+ [(set (match_dup 1) (const_int 0))]
-+{
-+ operands[1] = widen_mem_for_ldd_peep (operands[1], operands[0], DImode);
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "register_operand" "")
-+ (match_operand:SI 1 "memory_operand" ""))
-+ (set (match_operand:SI 2 "register_operand" "")
-+ (match_operand:SI 3 "memory_operand" ""))]
-+ "registers_ok_for_ldd_peep (operands[0], operands[2])
-+ && mems_ok_for_ldd_peep (operands[1], operands[3], operands[0])"
-+ [(set (match_dup 0) (match_dup 1))]
-+{
-+ operands[1] = widen_mem_for_ldd_peep (operands[1], operands[3], DImode);
-+ operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "memory_operand" "")
-+ (match_operand:SI 1 "register_operand" ""))
-+ (set (match_operand:SI 2 "memory_operand" "")
-+ (match_operand:SI 3 "register_operand" ""))]
-+ "registers_ok_for_ldd_peep (operands[1], operands[3])
-+ && mems_ok_for_ldd_peep (operands[0], operands[2], NULL_RTX)"
-+ [(set (match_dup 0) (match_dup 1))]
-+{
-+ operands[0] = widen_mem_for_ldd_peep (operands[0], operands[2], DImode);
-+ operands[1] = gen_rtx_REG (DImode, REGNO (operands[1]));
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SF 0 "register_operand" "")
-+ (match_operand:SF 1 "memory_operand" ""))
-+ (set (match_operand:SF 2 "register_operand" "")
-+ (match_operand:SF 3 "memory_operand" ""))]
-+ "registers_ok_for_ldd_peep (operands[0], operands[2])
-+ && mems_ok_for_ldd_peep (operands[1], operands[3], operands[0])"
-+ [(set (match_dup 0) (match_dup 1))]
-+{
-+ operands[1] = widen_mem_for_ldd_peep (operands[1], operands[3], DFmode);
-+ operands[0] = gen_rtx_REG (DFmode, REGNO (operands[0]));
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SF 0 "memory_operand" "")
-+ (match_operand:SF 1 "register_operand" ""))
-+ (set (match_operand:SF 2 "memory_operand" "")
-+ (match_operand:SF 3 "register_operand" ""))]
-+ "registers_ok_for_ldd_peep (operands[1], operands[3])
-+ && mems_ok_for_ldd_peep (operands[0], operands[2], NULL_RTX)"
-+ [(set (match_dup 0) (match_dup 1))]
-+{
-+ operands[0] = widen_mem_for_ldd_peep (operands[0], operands[2], DFmode);
-+ operands[1] = gen_rtx_REG (DFmode, REGNO (operands[1]));
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "register_operand" "")
-+ (match_operand:SI 1 "memory_operand" ""))
-+ (set (match_operand:SI 2 "register_operand" "")
-+ (match_operand:SI 3 "memory_operand" ""))]
-+ "registers_ok_for_ldd_peep (operands[2], operands[0])
-+ && mems_ok_for_ldd_peep (operands[3], operands[1], operands[0])"
-+ [(set (match_dup 2) (match_dup 3))]
-+{
-+ operands[3] = widen_mem_for_ldd_peep (operands[3], operands[1], DImode);
-+ operands[2] = gen_rtx_REG (DImode, REGNO (operands[2]));
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "memory_operand" "")
-+ (match_operand:SI 1 "register_operand" ""))
-+ (set (match_operand:SI 2 "memory_operand" "")
-+ (match_operand:SI 3 "register_operand" ""))]
-+ "registers_ok_for_ldd_peep (operands[3], operands[1])
-+ && mems_ok_for_ldd_peep (operands[2], operands[0], NULL_RTX)"
-+ [(set (match_dup 2) (match_dup 3))]
-+{
-+ operands[2] = widen_mem_for_ldd_peep (operands[2], operands[0], DImode);
-+ operands[3] = gen_rtx_REG (DImode, REGNO (operands[3]));
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SF 0 "register_operand" "")
-+ (match_operand:SF 1 "memory_operand" ""))
-+ (set (match_operand:SF 2 "register_operand" "")
-+ (match_operand:SF 3 "memory_operand" ""))]
-+ "registers_ok_for_ldd_peep (operands[2], operands[0])
-+ && mems_ok_for_ldd_peep (operands[3], operands[1], operands[0])"
-+ [(set (match_dup 2) (match_dup 3))]
-+{
-+ operands[3] = widen_mem_for_ldd_peep (operands[3], operands[1], DFmode);
-+ operands[2] = gen_rtx_REG (DFmode, REGNO (operands[2]));
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SF 0 "memory_operand" "")
-+ (match_operand:SF 1 "register_operand" ""))
-+ (set (match_operand:SF 2 "memory_operand" "")
-+ (match_operand:SF 3 "register_operand" ""))]
-+ "registers_ok_for_ldd_peep (operands[3], operands[1])
-+ && mems_ok_for_ldd_peep (operands[2], operands[0], NULL_RTX)"
-+ [(set (match_dup 2) (match_dup 3))]
-+{
-+ operands[2] = widen_mem_for_ldd_peep (operands[2], operands[0], DFmode);
-+ operands[3] = gen_rtx_REG (DFmode, REGNO (operands[3]));
-+})
-+
-+;; Optimize the case of following a reg-reg move with a test
-+;; of reg just moved. Don't allow floating point regs for operand 0 or 1.
-+;; This can result from a float to fix conversion.
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "register_operand" "")
-+ (match_operand:SI 1 "register_operand" ""))
-+ (set (reg:CC CC_REG)
-+ (compare:CC (match_operand:SI 2 "register_operand" "")
-+ (const_int 0)))]
-+ "(rtx_equal_p (operands[2], operands[0])
-+ || rtx_equal_p (operands[2], operands[1]))
-+ && !SPARC_FP_REG_P (REGNO (operands[0]))
-+ && !SPARC_FP_REG_P (REGNO (operands[1]))"
-+ [(parallel [(set (match_dup 0) (match_dup 1))
-+ (set (reg:CC CC_REG)
-+ (compare:CC (match_dup 1) (const_int 0)))])]
-+ "")
-+
-+(define_peephole2
-+ [(set (match_operand:DI 0 "register_operand" "")
-+ (match_operand:DI 1 "register_operand" ""))
-+ (set (reg:CCX CC_REG)
-+ (compare:CCX (match_operand:DI 2 "register_operand" "")
-+ (const_int 0)))]
-+ "TARGET_ARCH64
-+ && (rtx_equal_p (operands[2], operands[0])
-+ || rtx_equal_p (operands[2], operands[1]))
-+ && !SPARC_FP_REG_P (REGNO (operands[0]))
-+ && !SPARC_FP_REG_P (REGNO (operands[1]))"
-+ [(parallel [(set (match_dup 0) (match_dup 1))
-+ (set (reg:CCX CC_REG)
-+ (compare:CCX (match_dup 1) (const_int 0)))])]
-+ "")
-+
-+
-+;; Prefetch instructions.
-+
-+;; ??? UltraSPARC-III note: A memory operation loading into the floating point
-+;; register file, if it hits the prefetch cache, has a chance to dual-issue
-+;; with other memory operations. With DFA we might be able to model this,
-+;; but it requires a lot of state.
-+(define_expand "prefetch"
-+ [(match_operand 0 "address_operand" "")
-+ (match_operand 1 "const_int_operand" "")
-+ (match_operand 2 "const_int_operand" "")]
-+ "TARGET_V9"
-+{
-+ if (TARGET_ARCH64)
-+ emit_insn (gen_prefetch_64 (operands[0], operands[1], operands[2]));
-+ else
-+ emit_insn (gen_prefetch_32 (operands[0], operands[1], operands[2]));
-+ DONE;
-+})
-+
-+(define_insn "prefetch_64"
-+ [(prefetch (match_operand:DI 0 "address_operand" "p")
-+ (match_operand:DI 1 "const_int_operand" "n")
-+ (match_operand:DI 2 "const_int_operand" "n"))]
-+ ""
-+{
-+ static const char * const prefetch_instr[2][2] = {
-+ {
-+ "prefetch\t[%a0], 1", /* no locality: prefetch for one read */
-+ "prefetch\t[%a0], 0", /* medium to high locality: prefetch for several reads */
-+ },
-+ {
-+ "prefetch\t[%a0], 3", /* no locality: prefetch for one write */
-+ "prefetch\t[%a0], 2", /* medium to high locality: prefetch for several writes */
-+ }
-+ };
-+ int read_or_write = INTVAL (operands[1]);
-+ int locality = INTVAL (operands[2]);
-+
-+ gcc_assert (read_or_write == 0 || read_or_write == 1);
-+ gcc_assert (locality >= 0 && locality < 4);
-+ return prefetch_instr [read_or_write][locality == 0 ? 0 : 1];
-+}
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "prefetch")])
-+
-+(define_insn "prefetch_32"
-+ [(prefetch (match_operand:SI 0 "address_operand" "p")
-+ (match_operand:SI 1 "const_int_operand" "n")
-+ (match_operand:SI 2 "const_int_operand" "n"))]
-+ ""
-+{
-+ static const char * const prefetch_instr[2][2] = {
-+ {
-+ "prefetch\t[%a0], 1", /* no locality: prefetch for one read */
-+ "prefetch\t[%a0], 0", /* medium to high locality: prefetch for several reads */
-+ },
-+ {
-+ "prefetch\t[%a0], 3", /* no locality: prefetch for one write */
-+ "prefetch\t[%a0], 2", /* medium to high locality: prefetch for several writes */
-+ }
-+ };
-+ int read_or_write = INTVAL (operands[1]);
-+ int locality = INTVAL (operands[2]);
-+
-+ gcc_assert (read_or_write == 0 || read_or_write == 1);
-+ gcc_assert (locality >= 0 && locality < 4);
-+ return prefetch_instr [read_or_write][locality == 0 ? 0 : 1];
-+}
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "prefetch")])
-+
-+
-+;; Trap instructions.
-+
-+(define_insn "trap"
-+ [(trap_if (const_int 1) (const_int 5))]
-+ ""
-+ "ta\t5"
-+ [(set_attr "type" "trap")])
-+
-+(define_expand "ctrapsi4"
-+ [(trap_if (match_operator 0 "comparison_operator"
-+ [(match_operand:SI 1 "compare_operand" "")
-+ (match_operand:SI 2 "arith_operand" "")])
-+ (match_operand 3 "arith_operand"))]
-+ ""
-+{
-+ operands[1] = gen_compare_reg (operands[0]);
-+ if (GET_MODE (operands[1]) != CCmode && GET_MODE (operands[1]) != CCXmode)
-+ FAIL;
-+ operands[2] = const0_rtx;
-+})
-+
-+(define_expand "ctrapdi4"
-+ [(trap_if (match_operator 0 "comparison_operator"
-+ [(match_operand:DI 1 "compare_operand" "")
-+ (match_operand:DI 2 "arith_operand" "")])
-+ (match_operand 3 "arith_operand"))]
-+ "TARGET_ARCH64"
-+{
-+ operands[1] = gen_compare_reg (operands[0]);
-+ if (GET_MODE (operands[1]) != CCmode && GET_MODE (operands[1]) != CCXmode)
-+ FAIL;
-+ operands[2] = const0_rtx;
-+})
-+
-+(define_insn "*trapsi_insn"
-+ [(trap_if (match_operator 0 "icc_comparison_operator"
-+ [(reg:CC CC_REG) (const_int 0)])
-+ (match_operand:SI 1 "arith_operand" "rM"))]
-+ ""
-+{
-+ if (TARGET_V9)
-+ return "t%C0\t%%icc, %1";
-+ else
-+ return "t%C0\t%1";
-+}
-+ [(set_attr "type" "trap")])
-+
-+(define_insn "*trapdi_insn"
-+ [(trap_if (match_operator 0 "icc_comparison_operator"
-+ [(reg:CCX CC_REG) (const_int 0)])
-+ (match_operand:SI 1 "arith_operand" "rM"))]
-+ "TARGET_V9"
-+ "t%C0\t%%xcc, %1"
-+ [(set_attr "type" "trap")])
-+
-+
-+;; TLS support instructions.
-+
-+(define_insn "tgd_hi22<P:mode>"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (high:P (unspec:P [(match_operand 1 "tgd_symbolic_operand" "")]
-+ UNSPEC_TLSGD)))]
-+ "TARGET_TLS"
-+ "sethi\\t%%tgd_hi22(%a1), %0")
-+
-+(define_insn "tgd_lo10<P:mode>"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (lo_sum:P (match_operand:P 1 "register_operand" "r")
-+ (unspec:P [(match_operand 2 "tgd_symbolic_operand" "")]
-+ UNSPEC_TLSGD)))]
-+ "TARGET_TLS"
-+ "add\\t%1, %%tgd_lo10(%a2), %0")
-+
-+(define_insn "tgd_add<P:mode>"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (plus:P (match_operand:P 1 "register_operand" "r")
-+ (unspec:P [(match_operand:P 2 "register_operand" "r")
-+ (match_operand 3 "tgd_symbolic_operand" "")]
-+ UNSPEC_TLSGD)))]
-+ "TARGET_TLS"
-+ "add\\t%1, %2, %0, %%tgd_add(%a3)")
-+
-+(define_insn "tgd_call<P:mode>"
-+ [(set (match_operand 0 "register_operand" "=r")
-+ (call (mem:P (unspec:P [(match_operand:P 1 "symbolic_operand" "s")
-+ (match_operand 2 "tgd_symbolic_operand" "")]
-+ UNSPEC_TLSGD))
-+ (match_operand 3 "" "")))
-+ (clobber (reg:P O7_REG))]
-+ "TARGET_TLS"
-+ "call\t%a1, %%tgd_call(%a2)%#"
-+ [(set (attr "type") (if_then_else (eq_attr "tls_delay_slot" "true")
-+ (const_string "call")
-+ (const_string "call_no_delay_slot")))])
-+
-+(define_insn "tldm_hi22<P:mode>"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (high:P (unspec:P [(const_int 0)] UNSPEC_TLSLDM)))]
-+ "TARGET_TLS"
-+ "sethi\\t%%tldm_hi22(%&), %0")
-+
-+(define_insn "tldm_lo10<P:mode>"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (lo_sum:P (match_operand:P 1 "register_operand" "r")
-+ (unspec:P [(const_int 0)] UNSPEC_TLSLDM)))]
-+ "TARGET_TLS"
-+ "add\\t%1, %%tldm_lo10(%&), %0")
-+
-+(define_insn "tldm_add<P:mode>"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (plus:P (match_operand:P 1 "register_operand" "r")
-+ (unspec:P [(match_operand:P 2 "register_operand" "r")]
-+ UNSPEC_TLSLDM)))]
-+ "TARGET_TLS"
-+ "add\\t%1, %2, %0, %%tldm_add(%&)")
-+
-+(define_insn "tldm_call<P:mode>"
-+ [(set (match_operand 0 "register_operand" "=r")
-+ (call (mem:P (unspec:P [(match_operand:P 1 "symbolic_operand" "s")]
-+ UNSPEC_TLSLDM))
-+ (match_operand 2 "" "")))
-+ (clobber (reg:P O7_REG))]
-+ "TARGET_TLS"
-+ "call\t%a1, %%tldm_call(%&)%#"
-+ [(set (attr "type") (if_then_else (eq_attr "tls_delay_slot" "true")
-+ (const_string "call")
-+ (const_string "call_no_delay_slot")))])
-+
-+(define_insn "tldo_hix22<P:mode>"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (high:P (unspec:P [(match_operand 1 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)))]
-+ "TARGET_TLS"
-+ "sethi\\t%%tldo_hix22(%a1), %0")
-+
-+(define_insn "tldo_lox10<P:mode>"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (lo_sum:P (match_operand:P 1 "register_operand" "r")
-+ (unspec:P [(match_operand 2 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)))]
-+ "TARGET_TLS"
-+ "xor\\t%1, %%tldo_lox10(%a2), %0")
-+
-+(define_insn "tldo_add<P:mode>"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (plus:P (match_operand:P 1 "register_operand" "r")
-+ (unspec:P [(match_operand:P 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)))]
-+ "TARGET_TLS"
-+ "add\\t%1, %2, %0, %%tldo_add(%a3)")
-+
-+(define_insn "tie_hi22<P:mode>"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (high:P (unspec:P [(match_operand 1 "tie_symbolic_operand" "")]
-+ UNSPEC_TLSIE)))]
-+ "TARGET_TLS"
-+ "sethi\\t%%tie_hi22(%a1), %0")
-+
-+(define_insn "tie_lo10<P:mode>"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (lo_sum:P (match_operand:P 1 "register_operand" "r")
-+ (unspec:P [(match_operand 2 "tie_symbolic_operand" "")]
-+ UNSPEC_TLSIE)))]
-+ "TARGET_TLS"
-+ "add\\t%1, %%tie_lo10(%a2), %0")
-+
-+; Note the %%tie_ld operator
-+(define_insn "tie_ld32"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")
-+ (match_operand:SI 2 "register_operand" "r")
-+ (match_operand 3 "tie_symbolic_operand" "")]
-+ UNSPEC_TLSIE))]
-+ "TARGET_TLS && TARGET_ARCH32"
-+ "ld\\t[%1 + %2], %0, %%tie_ld(%a3)"
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "regular")])
-+
-+; Note the %%tie_ldx operator
-+(define_insn "tie_ld64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (unspec:DI [(match_operand:DI 1 "register_operand" "r")
-+ (match_operand:DI 2 "register_operand" "r")
-+ (match_operand 3 "tie_symbolic_operand" "")]
-+ UNSPEC_TLSIE))]
-+ "TARGET_TLS && TARGET_ARCH64"
-+ "ldx\\t[%1 + %2], %0, %%tie_ldx(%a3)"
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "regular")])
-+
-+(define_insn "tie_add<P:mode>"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (plus:P (match_operand:P 1 "register_operand" "r")
-+ (unspec:P [(match_operand:P 2 "register_operand" "r")
-+ (match_operand 3 "tie_symbolic_operand" "")]
-+ UNSPEC_TLSIE)))]
-+ "TARGET_SUN_TLS"
-+ "add\\t%1, %2, %0, %%tie_add(%a3)")
-+
-+(define_insn "tle_hix22<P:mode>"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (high:P (unspec:P [(match_operand 1 "tle_symbolic_operand" "")]
-+ UNSPEC_TLSLE)))]
-+ "TARGET_TLS"
-+ "sethi\\t%%tle_hix22(%a1), %0")
-+
-+(define_insn "tle_lox10<P:mode>"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (lo_sum:P (match_operand:P 1 "register_operand" "r")
-+ (unspec:P [(match_operand 2 "tle_symbolic_operand" "")]
-+ UNSPEC_TLSLE)))]
-+ "TARGET_TLS"
-+ "xor\\t%1, %%tle_lox10(%a2), %0")
-+
-+;; Now patterns combining tldo_add with some integer loads or stores
-+(define_insn "*tldo_ldub<P:mode>"
-+ [(set (match_operand:QI 0 "register_operand" "=r")
-+ (mem:QI (plus:P (unspec:P [(match_operand:P 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:P 1 "register_operand" "r"))))]
-+ "TARGET_TLS"
-+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "regular")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_insn "*tldo_ldub1<P:mode>"
-+ [(set (match_operand:HI 0 "register_operand" "=r")
-+ (zero_extend:HI
-+ (mem:QI (plus:P (unspec:P [(match_operand:P 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:P 1 "register_operand" "r")))))]
-+ "TARGET_TLS"
-+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "regular")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_insn "*tldo_ldub2<P:mode>"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (zero_extend:SI
-+ (mem:QI (plus:P (unspec:P [(match_operand:P 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:P 1 "register_operand" "r")))))]
-+ "TARGET_TLS"
-+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "regular")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_insn "*tldo_ldsb1<P:mode>"
-+ [(set (match_operand:HI 0 "register_operand" "=r")
-+ (sign_extend:HI
-+ (mem:QI (plus:P (unspec:P [(match_operand:P 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:P 1 "register_operand" "r")))))]
-+ "TARGET_TLS"
-+ "ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
-+ [(set_attr "type" "sload")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_insn "*tldo_ldsb2<P:mode>"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (sign_extend:SI
-+ (mem:QI (plus:P (unspec:P [(match_operand:P 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:P 1 "register_operand" "r")))))]
-+ "TARGET_TLS"
-+ "ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
-+ [(set_attr "type" "sload")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_insn "*tldo_ldub3_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (zero_extend:DI
-+ (mem:QI (plus:DI (unspec:DI [(match_operand:DI 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:DI 1 "register_operand" "r")))))]
-+ "TARGET_TLS && TARGET_ARCH64"
-+ "ldub\t[%1 + %2], %0, %%tldo_add(%3)"
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "regular")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_insn "*tldo_ldsb3_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (sign_extend:DI
-+ (mem:QI (plus:DI (unspec:DI [(match_operand:DI 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:DI 1 "register_operand" "r")))))]
-+ "TARGET_TLS && TARGET_ARCH64"
-+ "ldsb\t[%1 + %2], %0, %%tldo_add(%3)"
-+ [(set_attr "type" "sload")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_insn "*tldo_lduh<P:mode>"
-+ [(set (match_operand:HI 0 "register_operand" "=r")
-+ (mem:HI (plus:P (unspec:P [(match_operand:P 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:P 1 "register_operand" "r"))))]
-+ "TARGET_TLS"
-+ "lduh\t[%1 + %2], %0, %%tldo_add(%3)"
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "regular")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_insn "*tldo_lduh1<P:mode>"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (zero_extend:SI
-+ (mem:HI (plus:P (unspec:P [(match_operand:P 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:P 1 "register_operand" "r")))))]
-+ "TARGET_TLS"
-+ "lduh\t[%1 + %2], %0, %%tldo_add(%3)"
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "regular")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_insn "*tldo_ldsh1<P:mode>"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (sign_extend:SI
-+ (mem:HI (plus:P (unspec:P [(match_operand:P 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:P 1 "register_operand" "r")))))]
-+ "TARGET_TLS"
-+ "ldsh\t[%1 + %2], %0, %%tldo_add(%3)"
-+ [(set_attr "type" "sload")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_insn "*tldo_lduh2_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (zero_extend:DI
-+ (mem:HI (plus:DI (unspec:DI [(match_operand:DI 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:DI 1 "register_operand" "r")))))]
-+ "TARGET_TLS && TARGET_ARCH64"
-+ "lduh\t[%1 + %2], %0, %%tldo_add(%3)"
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "regular")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_insn "*tldo_ldsh2_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (sign_extend:DI
-+ (mem:HI (plus:DI (unspec:DI [(match_operand:DI 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:DI 1 "register_operand" "r")))))]
-+ "TARGET_TLS && TARGET_ARCH64"
-+ "ldsh\t[%1 + %2], %0, %%tldo_add(%3)"
-+ [(set_attr "type" "sload")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_insn "*tldo_lduw<P:mode>"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (mem:SI (plus:P (unspec:P [(match_operand:P 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:P 1 "register_operand" "r"))))]
-+ "TARGET_TLS"
-+ "ld\t[%1 + %2], %0, %%tldo_add(%3)"
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "regular")])
-+
-+(define_insn "*tldo_lduw1_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (zero_extend:DI
-+ (mem:SI (plus:DI (unspec:DI [(match_operand:DI 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:DI 1 "register_operand" "r")))))]
-+ "TARGET_TLS && TARGET_ARCH64"
-+ "lduw\t[%1 + %2], %0, %%tldo_add(%3)"
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "regular")])
-+
-+(define_insn "*tldo_ldsw1_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (sign_extend:DI
-+ (mem:SI (plus:DI (unspec:DI [(match_operand:DI 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:DI 1 "register_operand" "r")))))]
-+ "TARGET_TLS && TARGET_ARCH64"
-+ "ldsw\t[%1 + %2], %0, %%tldo_add(%3)"
-+ [(set_attr "type" "sload")
-+ (set_attr "us3load_type" "3cycle")])
-+
-+(define_insn "*tldo_ldx_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (mem:DI (plus:DI (unspec:DI [(match_operand:DI 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:DI 1 "register_operand" "r"))))]
-+ "TARGET_TLS && TARGET_ARCH64"
-+ "ldx\t[%1 + %2], %0, %%tldo_add(%3)"
-+ [(set_attr "type" "load")
-+ (set_attr "subtype" "regular")])
-+
-+(define_insn "*tldo_stb<P:mode>"
-+ [(set (mem:QI (plus:P (unspec:P [(match_operand:P 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:P 1 "register_operand" "r")))
-+ (match_operand:QI 0 "register_operand" "r"))]
-+ "TARGET_TLS"
-+ "stb\t%0, [%1 + %2], %%tldo_add(%3)"
-+ [(set_attr "type" "store")])
-+
-+(define_insn "*tldo_sth<P:mode>"
-+ [(set (mem:HI (plus:P (unspec:P [(match_operand:P 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:P 1 "register_operand" "r")))
-+ (match_operand:HI 0 "register_operand" "r"))]
-+ "TARGET_TLS"
-+ "sth\t%0, [%1 + %2], %%tldo_add(%3)"
-+ [(set_attr "type" "store")])
-+
-+(define_insn "*tldo_stw<P:mode>"
-+ [(set (mem:SI (plus:P (unspec:P [(match_operand:P 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:P 1 "register_operand" "r")))
-+ (match_operand:SI 0 "register_operand" "r"))]
-+ "TARGET_TLS"
-+ "st\t%0, [%1 + %2], %%tldo_add(%3)"
-+ [(set_attr "type" "store")])
-+
-+(define_insn "*tldo_stx_sp64"
-+ [(set (mem:DI (plus:DI (unspec:DI [(match_operand:DI 2 "register_operand" "r")
-+ (match_operand 3 "tld_symbolic_operand" "")]
-+ UNSPEC_TLSLDO)
-+ (match_operand:DI 1 "register_operand" "r")))
-+ (match_operand:DI 0 "register_operand" "r"))]
-+ "TARGET_TLS && TARGET_ARCH64"
-+ "stx\t%0, [%1 + %2], %%tldo_add(%3)"
-+ [(set_attr "type" "store")])
-+
-+
-+;; Stack protector instructions.
-+
-+(define_expand "stack_protect_set"
-+ [(match_operand 0 "memory_operand" "")
-+ (match_operand 1 "memory_operand" "")]
-+ ""
-+{
-+#ifdef TARGET_THREAD_SSP_OFFSET
-+ rtx tlsreg = gen_rtx_REG (Pmode, 7);
-+ rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
-+ operands[1] = gen_rtx_MEM (Pmode, addr);
-+#endif
-+ if (TARGET_ARCH64)
-+ emit_insn (gen_stack_protect_setdi (operands[0], operands[1]));
-+ else
-+ emit_insn (gen_stack_protect_setsi (operands[0], operands[1]));
-+ DONE;
-+})
-+
-+(define_insn "stack_protect_setsi"
-+ [(set (match_operand:SI 0 "memory_operand" "=m")
-+ (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
-+ (set (match_scratch:SI 2 "=&r") (const_int 0))]
-+ "TARGET_ARCH32"
-+ "ld\t%1, %2\;st\t%2, %0\;mov\t0, %2"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "3")])
-+
-+(define_insn "stack_protect_setdi"
-+ [(set (match_operand:DI 0 "memory_operand" "=m")
-+ (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
-+ (set (match_scratch:DI 2 "=&r") (const_int 0))]
-+ "TARGET_ARCH64"
-+ "ldx\t%1, %2\;stx\t%2, %0\;mov\t0, %2"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "3")])
-+
-+(define_expand "stack_protect_test"
-+ [(match_operand 0 "memory_operand" "")
-+ (match_operand 1 "memory_operand" "")
-+ (match_operand 2 "" "")]
-+ ""
-+{
-+ rtx result, test;
-+#ifdef TARGET_THREAD_SSP_OFFSET
-+ rtx tlsreg = gen_rtx_REG (Pmode, 7);
-+ rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
-+ operands[1] = gen_rtx_MEM (Pmode, addr);
-+#endif
-+ if (TARGET_ARCH64)
-+ {
-+ result = gen_reg_rtx (Pmode);
-+ emit_insn (gen_stack_protect_testdi (result, operands[0], operands[1]));
-+ test = gen_rtx_EQ (VOIDmode, result, const0_rtx);
-+ emit_jump_insn (gen_cbranchdi4 (test, result, const0_rtx, operands[2]));
-+ }
-+ else
-+ {
-+ emit_insn (gen_stack_protect_testsi (operands[0], operands[1]));
-+ result = gen_rtx_REG (CCmode, SPARC_ICC_REG);
-+ test = gen_rtx_EQ (VOIDmode, result, const0_rtx);
-+ emit_jump_insn (gen_cbranchcc4 (test, result, const0_rtx, operands[2]));
-+ }
-+ DONE;
-+})
-+
-+(define_insn "stack_protect_testsi"
-+ [(set (reg:CC CC_REG)
-+ (unspec:CC [(match_operand:SI 0 "memory_operand" "m")
-+ (match_operand:SI 1 "memory_operand" "m")]
-+ UNSPEC_SP_TEST))
-+ (set (match_scratch:SI 3 "=r") (const_int 0))
-+ (clobber (match_scratch:SI 2 "=&r"))]
-+ "TARGET_ARCH32"
-+ "ld\t%0, %2\;ld\t%1, %3\;xorcc\t%2, %3, %2\;mov\t0, %3"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "4")])
-+
-+(define_insn "stack_protect_testdi"
-+ [(set (match_operand:DI 0 "register_operand" "=&r")
-+ (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
-+ (match_operand:DI 2 "memory_operand" "m")]
-+ UNSPEC_SP_TEST))
-+ (set (match_scratch:DI 3 "=r") (const_int 0))]
-+ "TARGET_ARCH64"
-+ "ldx\t%1, %0\;ldx\t%2, %3\;xor\t%0, %3, %0\;mov\t0, %3"
-+ [(set_attr "type" "multi")
-+ (set_attr "length" "4")])
-+
-+
-+;; Vector instructions.
-+
-+(define_mode_iterator VM32 [V1SI V2HI V4QI])
-+(define_mode_iterator VM64 [V1DI V2SI V4HI V8QI])
-+(define_mode_iterator VMALL [V1SI V2HI V4QI V1DI V2SI V4HI V8QI])
-+
-+(define_mode_attr vbits [(V2SI "32") (V4HI "16") (V1SI "32s") (V2HI "16s")
-+ (V8QI "8")])
-+(define_mode_attr vconstr [(V1SI "f") (V2HI "f") (V4QI "f")
-+ (V1DI "e") (V2SI "e") (V4HI "e") (V8QI "e")])
-+(define_mode_attr vfptype [(V1SI "single") (V2HI "single") (V4QI "single")
-+ (V1DI "double") (V2SI "double") (V4HI "double")
-+ (V8QI "double")])
-+(define_mode_attr veltmode [(V1SI "si") (V2HI "hi") (V4QI "qi") (V1DI "di")
-+ (V2SI "si") (V4HI "hi") (V8QI "qi")])
-+
-+(define_expand "mov<VMALL:mode>"
-+ [(set (match_operand:VMALL 0 "nonimmediate_operand" "")
-+ (match_operand:VMALL 1 "general_operand" ""))]
-+ "TARGET_VIS"
-+{
-+ if (sparc_expand_move (<VMALL:MODE>mode, operands))
-+ DONE;
-+})
-+
-+(define_insn "*mov<VM32:mode>_insn"
-+ [(set (match_operand:VM32 0 "nonimmediate_operand" "=f,f,f,f,m,m,*r, m,*r,*r, f")
-+ (match_operand:VM32 1 "input_operand" "Y,Z,f,m,f,Y, m,*r,*r, f,*r"))]
-+ "TARGET_VIS
-+ && (register_operand (operands[0], <VM32:MODE>mode)
-+ || register_or_zero_or_all_ones_operand (operands[1], <VM32:MODE>mode))"
-+ "@
-+ fzeros\t%0
-+ fones\t%0
-+ fsrc2s\t%1, %0
-+ ld\t%1, %0
-+ st\t%1, %0
-+ st\t%r1, %0
-+ ld\t%1, %0
-+ st\t%1, %0
-+ mov\t%1, %0
-+ movstouw\t%1, %0
-+ movwtos\t%1, %0"
-+ [(set_attr "type" "visl,visl,vismv,fpload,fpstore,store,load,store,*,vismv,vismv")
-+ (set_attr "subtype" "single,single,single,*,*,*,regular,*,*,movstouw,single")
-+ (set_attr "cpu_feature" "vis,vis,vis,*,*,*,*,*,*,vis3,vis3")])
-+
-+(define_insn "*mov<VM64:mode>_insn_sp64"
-+ [(set (match_operand:VM64 0 "nonimmediate_operand" "=e,e,e,e,W,m,*r, m,*r, e,*r")
-+ (match_operand:VM64 1 "input_operand" "Y,Z,e,W,e,Y, m,*r, e,*r,*r"))]
-+ "TARGET_VIS
-+ && TARGET_ARCH64
-+ && (register_operand (operands[0], <VM64:MODE>mode)
-+ || register_or_zero_or_all_ones_operand (operands[1], <VM64:MODE>mode))"
-+ "@
-+ fzero\t%0
-+ fone\t%0
-+ fsrc2\t%1, %0
-+ ldd\t%1, %0
-+ std\t%1, %0
-+ stx\t%r1, %0
-+ ldx\t%1, %0
-+ stx\t%1, %0
-+ movdtox\t%1, %0
-+ movxtod\t%1, %0
-+ mov\t%1, %0"
-+ [(set_attr "type" "visl,visl,vismv,fpload,fpstore,store,load,store,vismv,vismv,*")
-+ (set_attr "subtype" "double,double,double,*,*,*,regular,*,movdtox,movxtod,*")
-+ (set_attr "cpu_feature" "vis,vis,vis,*,*,*,*,*,vis3,vis3,*")])
-+
-+(define_insn "*mov<VM64:mode>_insn_sp32"
-+ [(set (match_operand:VM64 0 "nonimmediate_operand"
-+ "=T,o,e,e,e,*r, f,e,T,U,T,f,o,*r,*r, o")
-+ (match_operand:VM64 1 "input_operand"
-+ " Y,Y,Y,Z,e, f,*r,T,e,T,U,o,f,*r, o,*r"))]
-+ "TARGET_VIS
-+ && TARGET_ARCH32
-+ && (register_operand (operands[0], <VM64:MODE>mode)
-+ || register_or_zero_or_all_ones_operand (operands[1], <VM64:MODE>mode))"
-+ "@
-+ stx\t%r1, %0
-+ #
-+ fzero\t%0
-+ fone\t%0
-+ fsrc2\t%1, %0
-+ #
-+ #
-+ ldd\t%1, %0
-+ std\t%1, %0
-+ ldd\t%1, %0
-+ std\t%1, %0
-+ #
-+ #
-+ #
-+ ldd\t%1, %0
-+ std\t%1, %0"
-+ [(set_attr "type" "store,*,visl,visl,vismv,*,*,fpload,fpstore,load,store,*,*,*,load,store")
-+ (set_attr "subtype" "*,*,double,double,double,*,*,*,*,regular,*,*,*,*,regular,*")
-+ (set_attr "length" "*,2,*,*,*,2,2,*,*,*,*,2,2,2,*,*")
-+ (set_attr "cpu_feature" "*,*,vis,vis,vis,vis3,vis3,*,*,*,*,*,*,*,*,*")
-+ (set_attr "lra" "*,*,*,*,*,*,*,*,*,disabled,disabled,*,*,*,*,*")])
-+
-+(define_split
-+ [(set (match_operand:VM64 0 "register_operand" "")
-+ (match_operand:VM64 1 "register_operand" ""))]
-+ "reload_completed
-+ && TARGET_VIS
-+ && TARGET_ARCH32
-+ && sparc_split_reg_reg_legitimate (operands[0], operands[1])"
-+ [(clobber (const_int 0))]
-+{
-+ sparc_split_reg_reg (operands[0], operands[1], SImode);
-+ DONE;
-+})
-+
-+(define_split
-+ [(set (match_operand:VM64 0 "register_operand" "")
-+ (match_operand:VM64 1 "memory_operand" ""))]
-+ "reload_completed
-+ && TARGET_VIS
-+ && TARGET_ARCH32
-+ && sparc_split_reg_mem_legitimate (operands[0], operands[1])"
-+ [(clobber (const_int 0))]
-+{
-+ sparc_split_reg_mem (operands[0], operands[1], SImode);
-+ DONE;
-+})
-+
-+(define_split
-+ [(set (match_operand:VM64 0 "memory_operand" "")
-+ (match_operand:VM64 1 "register_operand" ""))]
-+ "reload_completed
-+ && TARGET_VIS
-+ && TARGET_ARCH32
-+ && sparc_split_reg_mem_legitimate (operands[1], operands[0])"
-+ [(clobber (const_int 0))]
-+{
-+ sparc_split_mem_reg (operands[0], operands[1], SImode);
-+ DONE;
-+})
-+
-+(define_split
-+ [(set (match_operand:VM64 0 "memory_operand" "")
-+ (match_operand:VM64 1 "const_zero_operand" ""))]
-+ "reload_completed
-+ && TARGET_VIS
-+ && TARGET_ARCH32
-+ && !mem_min_alignment (operands[0], 8)
-+ && offsettable_memref_p (operands[0])"
-+ [(clobber (const_int 0))]
-+{
-+ emit_move_insn_1 (adjust_address (operands[0], SImode, 0), const0_rtx);
-+ emit_move_insn_1 (adjust_address (operands[0], SImode, 4), const0_rtx);
-+ DONE;
-+})
-+
-+(define_expand "vec_init<VMALL:mode><VMALL:veltmode>"
-+ [(match_operand:VMALL 0 "register_operand" "")
-+ (match_operand:VMALL 1 "" "")]
-+ "TARGET_VIS"
-+{
-+ sparc_expand_vector_init (operands[0], operands[1]);
-+ DONE;
-+})
-+
-+(define_code_iterator plusminus [plus minus])
-+(define_code_attr plusminus_insn [(plus "add") (minus "sub")])
-+
-+(define_mode_iterator VADDSUB [V1SI V2SI V2HI V4HI])
-+
-+(define_insn "<plusminus_insn><VADDSUB:mode>3"
-+ [(set (match_operand:VADDSUB 0 "register_operand" "=<vconstr>")
-+ (plusminus:VADDSUB (match_operand:VADDSUB 1 "register_operand" "<vconstr>")
-+ (match_operand:VADDSUB 2 "register_operand" "<vconstr>")))]
-+ "TARGET_VIS"
-+ "fp<plusminus_insn><vbits>\t%1, %2, %0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "other")
-+ (set_attr "fptype" "<vfptype>")])
-+
-+(define_mode_iterator VL [V1SI V2HI V4QI V1DI V2SI V4HI V8QI])
-+(define_mode_attr vlsuf [(V1SI "s") (V2HI "s") (V4QI "s")
-+ (V1DI "") (V2SI "") (V4HI "") (V8QI "")])
-+(define_code_iterator vlop [ior and xor])
-+(define_code_attr vlinsn [(ior "or") (and "and") (xor "xor")])
-+(define_code_attr vlninsn [(ior "nor") (and "nand") (xor "xnor")])
-+
-+(define_insn "<vlop:code><VL:mode>3"
-+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
-+ (vlop:VL (match_operand:VL 1 "register_operand" "<vconstr>")
-+ (match_operand:VL 2 "register_operand" "<vconstr>")))]
-+ "TARGET_VIS"
-+ "f<vlinsn><vlsuf>\t%1, %2, %0"
-+ [(set_attr "type" "visl")
-+ (set_attr "fptype" "<vfptype>")])
-+
-+(define_insn "*not_<vlop:code><VL:mode>3"
-+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
-+ (not:VL (vlop:VL (match_operand:VL 1 "register_operand" "<vconstr>")
-+ (match_operand:VL 2 "register_operand" "<vconstr>"))))]
-+ "TARGET_VIS"
-+ "f<vlninsn><vlsuf>\t%1, %2, %0"
-+ [(set_attr "type" "visl")
-+ (set_attr "fptype" "<vfptype>")])
-+
-+;; (ior (not (op1)) (not (op2))) is the canonical form of NAND.
-+(define_insn "*nand<VL:mode>_vis"
-+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
-+ (ior:VL (not:VL (match_operand:VL 1 "register_operand" "<vconstr>"))
-+ (not:VL (match_operand:VL 2 "register_operand" "<vconstr>"))))]
-+ "TARGET_VIS"
-+ "fnand<vlsuf>\t%1, %2, %0"
-+ [(set_attr "type" "visl")
-+ (set_attr "fptype" "<vfptype>")])
-+
-+(define_code_iterator vlnotop [ior and])
-+
-+(define_insn "*<vlnotop:code>_not1<VL:mode>_vis"
-+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
-+ (vlnotop:VL (not:VL (match_operand:VL 1 "register_operand" "<vconstr>"))
-+ (match_operand:VL 2 "register_operand" "<vconstr>")))]
-+ "TARGET_VIS"
-+ "f<vlinsn>not1<vlsuf>\t%1, %2, %0"
-+ [(set_attr "type" "visl")
-+ (set_attr "fptype" "<vfptype>")])
-+
-+(define_insn "*<vlnotop:code>_not2<VL:mode>_vis"
-+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
-+ (vlnotop:VL (match_operand:VL 1 "register_operand" "<vconstr>")
-+ (not:VL (match_operand:VL 2 "register_operand" "<vconstr>"))))]
-+ "TARGET_VIS"
-+ "f<vlinsn>not2<vlsuf>\t%1, %2, %0"
-+ [(set_attr "type" "visl")
-+ (set_attr "fptype" "<vfptype>")])
-+
-+(define_insn "one_cmpl<VL:mode>2"
-+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
-+ (not:VL (match_operand:VL 1 "register_operand" "<vconstr>")))]
-+ "TARGET_VIS"
-+ "fnot1<vlsuf>\t%1, %0"
-+ [(set_attr "type" "visl")
-+ (set_attr "fptype" "<vfptype>")])
-+
-+;; Hard to generate VIS instructions. We have builtins for these.
-+
-+(define_insn "fpack16_vis"
-+ [(set (match_operand:V4QI 0 "register_operand" "=f")
-+ (unspec:V4QI [(match_operand:V4HI 1 "register_operand" "e")
-+ (reg:DI GSR_REG)]
-+ UNSPEC_FPACK16))]
-+ "TARGET_VIS"
-+ "fpack16\t%1, %0"
-+ [(set_attr "type" "fgm_pack")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "fpackfix_vis"
-+ [(set (match_operand:V2HI 0 "register_operand" "=f")
-+ (unspec:V2HI [(match_operand:V2SI 1 "register_operand" "e")
-+ (reg:DI GSR_REG)]
-+ UNSPEC_FPACKFIX))]
-+ "TARGET_VIS"
-+ "fpackfix\t%1, %0"
-+ [(set_attr "type" "fgm_pack")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "fpack32_vis"
-+ [(set (match_operand:V8QI 0 "register_operand" "=e")
-+ (unspec:V8QI [(match_operand:V2SI 1 "register_operand" "e")
-+ (match_operand:V8QI 2 "register_operand" "e")
-+ (reg:DI GSR_REG)]
-+ UNSPEC_FPACK32))]
-+ "TARGET_VIS"
-+ "fpack32\t%1, %2, %0"
-+ [(set_attr "type" "fgm_pack")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "fexpand_vis"
-+ [(set (match_operand:V4HI 0 "register_operand" "=e")
-+ (unspec:V4HI [(match_operand:V4QI 1 "register_operand" "f")]
-+ UNSPEC_FEXPAND))]
-+ "TARGET_VIS"
-+ "fexpand\t%1, %0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "fpu")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "fpmerge_vis"
-+ [(set (match_operand:V8QI 0 "register_operand" "=e")
-+ (vec_select:V8QI
-+ (vec_concat:V8QI (match_operand:V4QI 1 "register_operand" "f")
-+ (match_operand:V4QI 2 "register_operand" "f"))
-+ (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)])))]
-+ "TARGET_VIS"
-+ "fpmerge\t%1, %2, %0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "fpu")
-+ (set_attr "fptype" "double")])
-+
-+;; Partitioned multiply instructions
-+(define_insn "fmul8x16_vis"
-+ [(set (match_operand:V4HI 0 "register_operand" "=e")
-+ (unspec:V4HI [(match_operand:V4QI 1 "register_operand" "f")
-+ (match_operand:V4HI 2 "register_operand" "e")]
-+ UNSPEC_MUL8))]
-+ "TARGET_VIS"
-+ "fmul8x16\t%1, %2, %0"
-+ [(set_attr "type" "fgm_mul")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "fmul8x16au_vis"
-+ [(set (match_operand:V4HI 0 "register_operand" "=e")
-+ (unspec:V4HI [(match_operand:V4QI 1 "register_operand" "f")
-+ (match_operand:V2HI 2 "register_operand" "f")]
-+ UNSPEC_MUL16AU))]
-+ "TARGET_VIS"
-+ "fmul8x16au\t%1, %2, %0"
-+ [(set_attr "type" "fgm_mul")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "fmul8x16al_vis"
-+ [(set (match_operand:V4HI 0 "register_operand" "=e")
-+ (unspec:V4HI [(match_operand:V4QI 1 "register_operand" "f")
-+ (match_operand:V2HI 2 "register_operand" "f")]
-+ UNSPEC_MUL16AL))]
-+ "TARGET_VIS"
-+ "fmul8x16al\t%1, %2, %0"
-+ [(set_attr "type" "fgm_mul")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "fmul8sux16_vis"
-+ [(set (match_operand:V4HI 0 "register_operand" "=e")
-+ (unspec:V4HI [(match_operand:V8QI 1 "register_operand" "e")
-+ (match_operand:V4HI 2 "register_operand" "e")]
-+ UNSPEC_MUL8SU))]
-+ "TARGET_VIS"
-+ "fmul8sux16\t%1, %2, %0"
-+ [(set_attr "type" "fgm_mul")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "fmul8ulx16_vis"
-+ [(set (match_operand:V4HI 0 "register_operand" "=e")
-+ (unspec:V4HI [(match_operand:V8QI 1 "register_operand" "e")
-+ (match_operand:V4HI 2 "register_operand" "e")]
-+ UNSPEC_MUL8UL))]
-+ "TARGET_VIS"
-+ "fmul8ulx16\t%1, %2, %0"
-+ [(set_attr "type" "fgm_mul")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "fmuld8sux16_vis"
-+ [(set (match_operand:V2SI 0 "register_operand" "=e")
-+ (unspec:V2SI [(match_operand:V4QI 1 "register_operand" "f")
-+ (match_operand:V2HI 2 "register_operand" "f")]
-+ UNSPEC_MULDSU))]
-+ "TARGET_VIS"
-+ "fmuld8sux16\t%1, %2, %0"
-+ [(set_attr "type" "fgm_mul")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "fmuld8ulx16_vis"
-+ [(set (match_operand:V2SI 0 "register_operand" "=e")
-+ (unspec:V2SI [(match_operand:V4QI 1 "register_operand" "f")
-+ (match_operand:V2HI 2 "register_operand" "f")]
-+ UNSPEC_MULDUL))]
-+ "TARGET_VIS"
-+ "fmuld8ulx16\t%1, %2, %0"
-+ [(set_attr "type" "fgm_mul")
-+ (set_attr "fptype" "double")])
-+
-+(define_expand "wrgsr_vis"
-+ [(set (reg:DI GSR_REG) (match_operand:DI 0 "arith_operand" ""))]
-+ "TARGET_VIS"
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_wrgsr_v8plus (operands[0]));
-+ DONE;
-+ }
-+})
-+
-+(define_insn "*wrgsr_sp64"
-+ [(set (reg:DI GSR_REG) (match_operand:DI 0 "arith_operand" "rI"))]
-+ "TARGET_VIS && TARGET_ARCH64"
-+ "wr\t%%g0, %0, %%gsr"
-+ [(set_attr "type" "gsr")
-+ (set_attr "subtype" "reg")])
-+
-+(define_insn "wrgsr_v8plus"
-+ [(set (reg:DI GSR_REG) (match_operand:DI 0 "arith_operand" "I,r"))
-+ (clobber (match_scratch:SI 1 "=X,&h"))]
-+ "TARGET_VIS && TARGET_ARCH32"
-+{
-+ if (GET_CODE (operands[0]) == CONST_INT
-+ || sparc_check_64 (operands[0], insn))
-+ return "wr\t%%g0, %0, %%gsr";
-+
-+ output_asm_insn("srl\t%L0, 0, %L0", operands);
-+ return "sllx\t%H0, 32, %1\n\tor\t%L0, %1, %1\n\twr\t%%g0, %1, %%gsr";
-+}
-+ [(set_attr "type" "multi")])
-+
-+(define_expand "rdgsr_vis"
-+ [(set (match_operand:DI 0 "register_operand" "") (reg:DI GSR_REG))]
-+ "TARGET_VIS"
-+{
-+ if (TARGET_ARCH32)
-+ {
-+ emit_insn (gen_rdgsr_v8plus (operands[0]));
-+ DONE;
-+ }
-+})
-+
-+(define_insn "*rdgsr_sp64"
-+ [(set (match_operand:DI 0 "register_operand" "=r") (reg:DI GSR_REG))]
-+ "TARGET_VIS && TARGET_ARCH64"
-+ "rd\t%%gsr, %0"
-+ [(set_attr "type" "gsr")
-+ (set_attr "subtype" "reg")])
-+
-+(define_insn "rdgsr_v8plus"
-+ [(set (match_operand:DI 0 "register_operand" "=r") (reg:DI GSR_REG))
-+ (clobber (match_scratch:SI 1 "=&h"))]
-+ "TARGET_VIS && TARGET_ARCH32"
-+{
-+ return "rd\t%%gsr, %1\n\tsrlx\t%1, 32, %H0\n\tmov %1, %L0";
-+}
-+ [(set_attr "type" "multi")])
-+
-+;; Using faligndata only makes sense after an alignaddr since the choice of
-+;; bytes to take out of each operand is dependent on the results of the last
-+;; alignaddr.
-+(define_insn "faligndata<VM64:mode>_vis"
-+ [(set (match_operand:VM64 0 "register_operand" "=e")
-+ (unspec:VM64 [(match_operand:VM64 1 "register_operand" "e")
-+ (match_operand:VM64 2 "register_operand" "e")
-+ (reg:DI GSR_REG)]
-+ UNSPEC_ALIGNDATA))]
-+ "TARGET_VIS"
-+ "faligndata\t%1, %2, %0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "other")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "alignaddrsi_vis"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (plus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
-+ (match_operand:SI 2 "register_or_zero_operand" "rJ")))
-+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 3) (const_int 0))
-+ (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
-+ "TARGET_VIS"
-+ "alignaddr\t%r1, %r2, %0"
-+ [(set_attr "type" "gsr")
-+ (set_attr "subtype" "alignaddr")])
-+
-+(define_insn "alignaddrdi_vis"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (plus:DI (match_operand:DI 1 "register_or_zero_operand" "rJ")
-+ (match_operand:DI 2 "register_or_zero_operand" "rJ")))
-+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 3) (const_int 0))
-+ (plus:DI (match_dup 1) (match_dup 2)))]
-+ "TARGET_VIS"
-+ "alignaddr\t%r1, %r2, %0"
-+ [(set_attr "type" "gsr")
-+ (set_attr "subtype" "alignaddr")])
-+
-+(define_insn "alignaddrlsi_vis"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (plus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
-+ (match_operand:SI 2 "register_or_zero_operand" "rJ")))
-+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 3) (const_int 0))
-+ (xor:DI (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2)))
-+ (const_int 7)))]
-+ "TARGET_VIS"
-+ "alignaddrl\t%r1, %r2, %0"
-+ [(set_attr "type" "gsr")
-+ (set_attr "subtype" "alignaddr")])
-+
-+(define_insn "alignaddrldi_vis"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (plus:DI (match_operand:DI 1 "register_or_zero_operand" "rJ")
-+ (match_operand:DI 2 "register_or_zero_operand" "rJ")))
-+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 3) (const_int 0))
-+ (xor:DI (plus:DI (match_dup 1) (match_dup 2))
-+ (const_int 7)))]
-+ "TARGET_VIS"
-+ "alignaddrl\t%r1, %r2, %0"
-+ [(set_attr "type" "gsr")
-+ (set_attr "subtype" "alignaddr")])
-+
-+(define_insn "pdist_vis"
-+ [(set (match_operand:DI 0 "register_operand" "=e")
-+ (unspec:DI [(match_operand:V8QI 1 "register_operand" "e")
-+ (match_operand:V8QI 2 "register_operand" "e")
-+ (match_operand:DI 3 "register_operand" "0")]
-+ UNSPEC_PDIST))]
-+ "TARGET_VIS"
-+ "pdist\t%1, %2, %0"
-+ [(set_attr "type" "pdist")
-+ (set_attr "fptype" "double")])
-+
-+;; Edge instructions produce condition codes equivalent to a 'subcc'
-+;; with the same operands.
-+(define_insn "edge8<P:mode>_vis"
-+ [(set (reg:CCNZ CC_REG)
-+ (compare:CCNZ (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
-+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
-+ (const_int 0)))
-+ (set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE8))]
-+ "TARGET_VIS"
-+ "edge8\t%r1, %r2, %0"
-+ [(set_attr "type" "edge")])
-+
-+(define_insn "edge8l<P:mode>_vis"
-+ [(set (reg:CCNZ CC_REG)
-+ (compare:CCNZ (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
-+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
-+ (const_int 0)))
-+ (set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE8L))]
-+ "TARGET_VIS"
-+ "edge8l\t%r1, %r2, %0"
-+ [(set_attr "type" "edge")])
-+
-+(define_insn "edge16<P:mode>_vis"
-+ [(set (reg:CCNZ CC_REG)
-+ (compare:CCNZ (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
-+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
-+ (const_int 0)))
-+ (set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE16))]
-+ "TARGET_VIS"
-+ "edge16\t%r1, %r2, %0"
-+ [(set_attr "type" "edge")])
-+
-+(define_insn "edge16l<P:mode>_vis"
-+ [(set (reg:CCNZ CC_REG)
-+ (compare:CCNZ (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
-+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
-+ (const_int 0)))
-+ (set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE16L))]
-+ "TARGET_VIS"
-+ "edge16l\t%r1, %r2, %0"
-+ [(set_attr "type" "edge")])
-+
-+(define_insn "edge32<P:mode>_vis"
-+ [(set (reg:CCNZ CC_REG)
-+ (compare:CCNZ (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
-+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
-+ (const_int 0)))
-+ (set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE32))]
-+ "TARGET_VIS"
-+ "edge32\t%r1, %r2, %0"
-+ [(set_attr "type" "edge")])
-+
-+(define_insn "edge32l<P:mode>_vis"
-+ [(set (reg:CCNZ CC_REG)
-+ (compare:CCNZ (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
-+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
-+ (const_int 0)))
-+ (set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE32L))]
-+ "TARGET_VIS"
-+ "edge32l\t%r1, %r2, %0"
-+ [(set_attr "type" "edge")])
-+
-+(define_code_iterator gcond [le ne gt eq])
-+(define_mode_iterator GCM [V4HI V2SI])
-+(define_mode_attr gcm_name [(V4HI "16") (V2SI "32")])
-+
-+(define_insn "fcmp<gcond:code><GCM:gcm_name><P:mode>_vis"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(gcond:GCM (match_operand:GCM 1 "register_operand" "e")
-+ (match_operand:GCM 2 "register_operand" "e"))]
-+ UNSPEC_FCMP))]
-+ "TARGET_VIS"
-+ "fcmp<gcond:code><GCM:gcm_name>\t%1, %2, %0"
-+ [(set_attr "type" "viscmp")])
-+
-+(define_insn "fpcmp<gcond:code>8<P:mode>_vis"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(gcond:V8QI (match_operand:V8QI 1 "register_operand" "e")
-+ (match_operand:V8QI 2 "register_operand" "e"))]
-+ UNSPEC_FCMP))]
-+ "TARGET_VIS4"
-+ "fpcmp<gcond:code>8\t%1, %2, %0"
-+ [(set_attr "type" "viscmp")])
-+
-+(define_expand "vcond<GCM:mode><GCM:mode>"
-+ [(match_operand:GCM 0 "register_operand" "")
-+ (match_operand:GCM 1 "register_operand" "")
-+ (match_operand:GCM 2 "register_operand" "")
-+ (match_operator 3 ""
-+ [(match_operand:GCM 4 "register_operand" "")
-+ (match_operand:GCM 5 "register_operand" "")])]
-+ "TARGET_VIS3"
-+{
-+ sparc_expand_vcond (<MODE>mode, operands, UNSPEC_CMASK<gcm_name>, UNSPEC_FCMP);
-+ DONE;
-+})
-+
-+(define_expand "vconduv8qiv8qi"
-+ [(match_operand:V8QI 0 "register_operand" "")
-+ (match_operand:V8QI 1 "register_operand" "")
-+ (match_operand:V8QI 2 "register_operand" "")
-+ (match_operator 3 ""
-+ [(match_operand:V8QI 4 "register_operand" "")
-+ (match_operand:V8QI 5 "register_operand" "")])]
-+ "TARGET_VIS3"
-+{
-+ sparc_expand_vcond (V8QImode, operands, UNSPEC_CMASK8, UNSPEC_FUCMP);
-+ DONE;
-+})
-+
-+(define_insn "array8<P:mode>_vis"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
-+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
-+ UNSPEC_ARRAY8))]
-+ "TARGET_VIS"
-+ "array8\t%r1, %r2, %0"
-+ [(set_attr "type" "array")])
-+
-+(define_insn "array16<P:mode>_vis"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
-+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
-+ UNSPEC_ARRAY16))]
-+ "TARGET_VIS"
-+ "array16\t%r1, %r2, %0"
-+ [(set_attr "type" "array")])
-+
-+(define_insn "array32<P:mode>_vis"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
-+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
-+ UNSPEC_ARRAY32))]
-+ "TARGET_VIS"
-+ "array32\t%r1, %r2, %0"
-+ [(set_attr "type" "array")])
-+
-+(define_insn "bmaskdi_vis"
-+ [(set (match_operand:DI 0 "register_operand" "=r")
-+ (plus:DI (match_operand:DI 1 "register_or_zero_operand" "rJ")
-+ (match_operand:DI 2 "register_or_zero_operand" "rJ")))
-+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 32) (const_int 32))
-+ (plus:DI (match_dup 1) (match_dup 2)))]
-+ "TARGET_VIS2 && TARGET_ARCH64"
-+ "bmask\t%r1, %r2, %0"
-+ [(set_attr "type" "bmask")])
-+
-+(define_insn "bmasksi_vis"
-+ [(set (match_operand:SI 0 "register_operand" "=r")
-+ (plus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
-+ (match_operand:SI 2 "register_or_zero_operand" "rJ")))
-+ (set (zero_extract:DI (reg:DI GSR_REG) (const_int 32) (const_int 32))
-+ (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
-+ "TARGET_VIS2"
-+ "bmask\t%r1, %r2, %0"
-+ [(set_attr "type" "bmask")])
-+
-+(define_insn "bshuffle<VM64:mode>_vis"
-+ [(set (match_operand:VM64 0 "register_operand" "=e")
-+ (unspec:VM64 [(match_operand:VM64 1 "register_operand" "e")
-+ (match_operand:VM64 2 "register_operand" "e")
-+ (reg:DI GSR_REG)]
-+ UNSPEC_BSHUFFLE))]
-+ "TARGET_VIS2"
-+ "bshuffle\t%1, %2, %0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "other")
-+ (set_attr "fptype" "double")])
-+
-+;; Unlike constant permutation, we can vastly simplify the compression of
-+;; the 64-bit selector input to the 32-bit %gsr value by knowing what the
-+;; width of the input is.
-+(define_expand "vec_perm<VM64:mode>"
-+ [(match_operand:VM64 0 "register_operand" "")
-+ (match_operand:VM64 1 "register_operand" "")
-+ (match_operand:VM64 2 "register_operand" "")
-+ (match_operand:VM64 3 "register_operand" "")]
-+ "TARGET_VIS2"
-+{
-+ sparc_expand_vec_perm_bmask (<MODE>mode, operands[3]);
-+ emit_insn (gen_bshuffle<VM64:mode>_vis (operands[0], operands[1], operands[2]));
-+ DONE;
-+})
-+
-+;; VIS 2.0 adds edge variants which do not set the condition codes
-+(define_insn "edge8n<P:mode>_vis"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
-+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
-+ UNSPEC_EDGE8N))]
-+ "TARGET_VIS2"
-+ "edge8n\t%r1, %r2, %0"
-+ [(set_attr "type" "edgen")])
-+
-+(define_insn "edge8ln<P:mode>_vis"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
-+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
-+ UNSPEC_EDGE8LN))]
-+ "TARGET_VIS2"
-+ "edge8ln\t%r1, %r2, %0"
-+ [(set_attr "type" "edgen")])
-+
-+(define_insn "edge16n<P:mode>_vis"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
-+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
-+ UNSPEC_EDGE16N))]
-+ "TARGET_VIS2"
-+ "edge16n\t%r1, %r2, %0"
-+ [(set_attr "type" "edgen")])
-+
-+(define_insn "edge16ln<P:mode>_vis"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
-+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
-+ UNSPEC_EDGE16LN))]
-+ "TARGET_VIS2"
-+ "edge16ln\t%r1, %r2, %0"
-+ [(set_attr "type" "edgen")])
-+
-+(define_insn "edge32n<P:mode>_vis"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
-+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
-+ UNSPEC_EDGE32N))]
-+ "TARGET_VIS2"
-+ "edge32n\t%r1, %r2, %0"
-+ [(set_attr "type" "edgen")])
-+
-+(define_insn "edge32ln<P:mode>_vis"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
-+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
-+ UNSPEC_EDGE32LN))]
-+ "TARGET_VIS2"
-+ "edge32ln\t%r1, %r2, %0"
-+ [(set_attr "type" "edge")])
-+
-+;; Conditional moves are possible via fcmpX --> cmaskX -> bshuffle
-+(define_insn "cmask8<P:mode>_vis"
-+ [(set (reg:DI GSR_REG)
-+ (unspec:DI [(match_operand:P 0 "register_or_zero_operand" "rJ")
-+ (reg:DI GSR_REG)]
-+ UNSPEC_CMASK8))]
-+ "TARGET_VIS3"
-+ "cmask8\t%r0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "cmask")])
-+
-+(define_insn "cmask16<P:mode>_vis"
-+ [(set (reg:DI GSR_REG)
-+ (unspec:DI [(match_operand:P 0 "register_or_zero_operand" "rJ")
-+ (reg:DI GSR_REG)]
-+ UNSPEC_CMASK16))]
-+ "TARGET_VIS3"
-+ "cmask16\t%r0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "cmask")])
-+
-+(define_insn "cmask32<P:mode>_vis"
-+ [(set (reg:DI GSR_REG)
-+ (unspec:DI [(match_operand:P 0 "register_or_zero_operand" "rJ")
-+ (reg:DI GSR_REG)]
-+ UNSPEC_CMASK32))]
-+ "TARGET_VIS3"
-+ "cmask32\t%r0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "cmask")])
-+
-+(define_insn "fchksm16_vis"
-+ [(set (match_operand:V4HI 0 "register_operand" "=e")
-+ (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "e")
-+ (match_operand:V4HI 2 "register_operand" "e")]
-+ UNSPEC_FCHKSM16))]
-+ "TARGET_VIS3"
-+ "fchksm16\t%1, %2, %0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "fpu")])
-+
-+(define_code_iterator vis3_shift [ashift ss_ashift lshiftrt ashiftrt])
-+(define_code_attr vis3_shift_insn
-+ [(ashift "fsll") (ss_ashift "fslas") (lshiftrt "fsrl") (ashiftrt "fsra")])
-+(define_code_attr vis3_shift_patname
-+ [(ashift "ashl") (ss_ashift "ssashl") (lshiftrt "lshr") (ashiftrt "ashr")])
-+
-+(define_insn "v<vis3_shift_patname><GCM:mode>3"
-+ [(set (match_operand:GCM 0 "register_operand" "=<vconstr>")
-+ (vis3_shift:GCM (match_operand:GCM 1 "register_operand" "<vconstr>")
-+ (match_operand:GCM 2 "register_operand" "<vconstr>")))]
-+ "TARGET_VIS3"
-+ "<vis3_shift_insn><vbits>\t%1, %2, %0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "fpu")])
-+
-+(define_insn "pdistn<P:mode>_vis"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_operand:V8QI 1 "register_operand" "e")
-+ (match_operand:V8QI 2 "register_operand" "e")]
-+ UNSPEC_PDISTN))]
-+ "TARGET_VIS3"
-+ "pdistn\t%1, %2, %0"
-+ [(set_attr "type" "pdistn")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "fmean16_vis"
-+ [(set (match_operand:V4HI 0 "register_operand" "=e")
-+ (truncate:V4HI
-+ (lshiftrt:V4SI
-+ (plus:V4SI
-+ (plus:V4SI
-+ (zero_extend:V4SI
-+ (match_operand:V4HI 1 "register_operand" "e"))
-+ (zero_extend:V4SI
-+ (match_operand:V4HI 2 "register_operand" "e")))
-+ (const_vector:V4SI [(const_int 1) (const_int 1)
-+ (const_int 1) (const_int 1)]))
-+ (const_int 1))))]
-+ "TARGET_VIS3"
-+ "fmean16\t%1, %2, %0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "fpu")])
-+
-+(define_insn "fp<plusminus_insn>64_vis"
-+ [(set (match_operand:V1DI 0 "register_operand" "=e")
-+ (plusminus:V1DI (match_operand:V1DI 1 "register_operand" "e")
-+ (match_operand:V1DI 2 "register_operand" "e")))]
-+ "TARGET_VIS3"
-+ "fp<plusminus_insn>64\t%1, %2, %0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "addsub64")])
-+
-+(define_insn "<plusminus_insn>v8qi3"
-+ [(set (match_operand:V8QI 0 "register_operand" "=e")
-+ (plusminus:V8QI (match_operand:V8QI 1 "register_operand" "e")
-+ (match_operand:V8QI 2 "register_operand" "e")))]
-+ "TARGET_VIS4"
-+ "fp<plusminus_insn>8\t%1, %2, %0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "other")])
-+
-+(define_mode_iterator VASS [V4HI V2SI V2HI V1SI])
-+(define_code_iterator vis3_addsub_ss [ss_plus ss_minus])
-+(define_code_attr vis3_addsub_ss_insn
-+ [(ss_plus "fpadds") (ss_minus "fpsubs")])
-+(define_code_attr vis3_addsub_ss_patname
-+ [(ss_plus "ssadd") (ss_minus "sssub")])
-+
-+(define_insn "<vis3_addsub_ss_patname><VASS:mode>3"
-+ [(set (match_operand:VASS 0 "register_operand" "=<vconstr>")
-+ (vis3_addsub_ss:VASS (match_operand:VASS 1 "register_operand" "<vconstr>")
-+ (match_operand:VASS 2 "register_operand" "<vconstr>")))]
-+ "TARGET_VIS3"
-+ "<vis3_addsub_ss_insn><vbits>\t%1, %2, %0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "other")])
-+
-+(define_mode_iterator VMMAX [V8QI V4HI V2SI])
-+(define_code_iterator vis4_minmax [smin smax])
-+(define_code_attr vis4_minmax_insn
-+ [(smin "fpmin") (smax "fpmax")])
-+(define_code_attr vis4_minmax_patname
-+ [(smin "min") (smax "max")])
-+
-+(define_insn "<vis4_minmax_patname><VMMAX:mode>3"
-+ [(set (match_operand:VMMAX 0 "register_operand" "=<vconstr>")
-+ (vis4_minmax:VMMAX (match_operand:VMMAX 1 "register_operand" "<vconstr>")
-+ (match_operand:VMMAX 2 "register_operand" "<vconstr>")))]
-+ "TARGET_VIS4"
-+ "<vis4_minmax_insn><vbits>\t%1, %2, %0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "maxmin")])
-+
-+(define_code_iterator vis4_uminmax [umin umax])
-+(define_code_attr vis4_uminmax_insn
-+ [(umin "fpminu") (umax "fpmaxu")])
-+(define_code_attr vis4_uminmax_patname
-+ [(umin "minu") (umax "maxu")])
-+
-+(define_insn "<vis4_uminmax_patname><VMMAX:mode>3"
-+ [(set (match_operand:VMMAX 0 "register_operand" "=<vconstr>")
-+ (vis4_uminmax:VMMAX (match_operand:VMMAX 1 "register_operand" "<vconstr>")
-+ (match_operand:VMMAX 2 "register_operand" "<vconstr>")))]
-+ "TARGET_VIS4"
-+ "<vis4_uminmax_insn><vbits>\t%1, %2, %0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "maxmin")])
-+
-+;; The use of vis3_addsub_ss_patname in the VIS4 instruction below is
-+;; intended.
-+(define_insn "<vis3_addsub_ss_patname>v8qi3"
-+ [(set (match_operand:V8QI 0 "register_operand" "=e")
-+ (vis3_addsub_ss:V8QI (match_operand:V8QI 1 "register_operand" "e")
-+ (match_operand:V8QI 2 "register_operand" "e")))]
-+ "TARGET_VIS4"
-+ "<vis3_addsub_ss_insn>8\t%1, %2, %0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "other")])
-+
-+(define_mode_iterator VAUS [V4HI V8QI])
-+(define_code_iterator vis4_addsub_us [us_plus us_minus])
-+(define_code_attr vis4_addsub_us_insn
-+ [(us_plus "fpaddus") (us_minus "fpsubus")])
-+(define_code_attr vis4_addsub_us_patname
-+ [(us_plus "usadd") (us_minus "ussub")])
-+
-+(define_insn "<vis4_addsub_us_patname><VAUS:mode>3"
-+ [(set (match_operand:VAUS 0 "register_operand" "=<vconstr>")
-+ (vis4_addsub_us:VAUS (match_operand:VAUS 1 "register_operand" "<vconstr>")
-+ (match_operand:VAUS 2 "register_operand" "<vconstr>")))]
-+ "TARGET_VIS4"
-+ "<vis4_addsub_us_insn><vbits>\t%1, %2, %0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "other")])
-+
-+(define_insn "fucmp<gcond:code>8<P:mode>_vis"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(gcond:V8QI (match_operand:V8QI 1 "register_operand" "e")
-+ (match_operand:V8QI 2 "register_operand" "e"))]
-+ UNSPEC_FUCMP))]
-+ "TARGET_VIS3"
-+ "fucmp<gcond:code>8\t%1, %2, %0"
-+ [(set_attr "type" "viscmp")])
-+
-+(define_insn "fpcmpu<gcond:code><GCM:gcm_name><P:mode>_vis"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(gcond:GCM (match_operand:GCM 1 "register_operand" "e")
-+ (match_operand:GCM 2 "register_operand" "e"))]
-+ UNSPEC_FUCMP))]
-+ "TARGET_VIS4"
-+ "fpcmpu<gcond:code><GCM:gcm_name>\t%1, %2, %0"
-+ [(set_attr "type" "viscmp")])
-+
-+(define_insn "*naddsf3"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (neg:SF (plus:SF (match_operand:SF 1 "register_operand" "f")
-+ (match_operand:SF 2 "register_operand" "f"))))]
-+ "TARGET_VIS3"
-+ "fnadds\t%1, %2, %0"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "*nadddf3"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (neg:DF (plus:DF (match_operand:DF 1 "register_operand" "e")
-+ (match_operand:DF 2 "register_operand" "e"))))]
-+ "TARGET_VIS3"
-+ "fnaddd\t%1, %2, %0"
-+ [(set_attr "type" "fp")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "*nmulsf3"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (mult:SF (neg:SF (match_operand:SF 1 "register_operand" "f"))
-+ (match_operand:SF 2 "register_operand" "f")))]
-+ "TARGET_VIS3"
-+ "fnmuls\t%1, %2, %0"
-+ [(set_attr "type" "fpmul")])
-+
-+(define_insn "*nmuldf3"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (mult:DF (neg:DF (match_operand:DF 1 "register_operand" "e"))
-+ (match_operand:DF 2 "register_operand" "e")))]
-+ "TARGET_VIS3"
-+ "fnmuld\t%1, %2, %0"
-+ [(set_attr "type" "fpmul")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "*nmuldf3_extend"
-+ [(set (match_operand:DF 0 "register_operand" "=e")
-+ (mult:DF (neg:DF (float_extend:DF
-+ (match_operand:SF 1 "register_operand" "f")))
-+ (float_extend:DF
-+ (match_operand:SF 2 "register_operand" "f"))))]
-+ "TARGET_VIS3"
-+ "fnsmuld\t%1, %2, %0"
-+ [(set_attr "type" "fpmul")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "fhaddsf_vis"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (unspec:SF [(match_operand:SF 1 "register_operand" "f")
-+ (match_operand:SF 2 "register_operand" "f")]
-+ UNSPEC_FHADD))]
-+ "TARGET_VIS3"
-+ "fhadds\t%1, %2, %0"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "fhadddf_vis"
-+ [(set (match_operand:DF 0 "register_operand" "=f")
-+ (unspec:DF [(match_operand:DF 1 "register_operand" "f")
-+ (match_operand:DF 2 "register_operand" "f")]
-+ UNSPEC_FHADD))]
-+ "TARGET_VIS3"
-+ "fhaddd\t%1, %2, %0"
-+ [(set_attr "type" "fp")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "fhsubsf_vis"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (unspec:SF [(match_operand:SF 1 "register_operand" "f")
-+ (match_operand:SF 2 "register_operand" "f")]
-+ UNSPEC_FHSUB))]
-+ "TARGET_VIS3"
-+ "fhsubs\t%1, %2, %0"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "fhsubdf_vis"
-+ [(set (match_operand:DF 0 "register_operand" "=f")
-+ (unspec:DF [(match_operand:DF 1 "register_operand" "f")
-+ (match_operand:DF 2 "register_operand" "f")]
-+ UNSPEC_FHSUB))]
-+ "TARGET_VIS3"
-+ "fhsubd\t%1, %2, %0"
-+ [(set_attr "type" "fp")
-+ (set_attr "fptype" "double")])
-+
-+(define_insn "fnhaddsf_vis"
-+ [(set (match_operand:SF 0 "register_operand" "=f")
-+ (neg:SF (unspec:SF [(match_operand:SF 1 "register_operand" "f")
-+ (match_operand:SF 2 "register_operand" "f")]
-+ UNSPEC_FHADD)))]
-+ "TARGET_VIS3"
-+ "fnhadds\t%1, %2, %0"
-+ [(set_attr "type" "fp")])
-+
-+(define_insn "fnhadddf_vis"
-+ [(set (match_operand:DF 0 "register_operand" "=f")
-+ (neg:DF (unspec:DF [(match_operand:DF 1 "register_operand" "f")
-+ (match_operand:DF 2 "register_operand" "f")]
-+ UNSPEC_FHADD)))]
-+ "TARGET_VIS3"
-+ "fnhaddd\t%1, %2, %0"
-+ [(set_attr "type" "fp")
-+ (set_attr "fptype" "double")])
-+
-+;; VIS4B instructions.
-+
-+(define_mode_iterator DUMODE [V2SI V4HI V8QI])
-+
-+(define_insn "dictunpack<DUMODE:vbits>"
-+ [(set (match_operand:DUMODE 0 "register_operand" "=e")
-+ (unspec:DUMODE [(match_operand:DF 1 "register_operand" "e")
-+ (match_operand:SI 2 "imm5_operand_dictunpack<DUMODE:vbits>" "t")]
-+ UNSPEC_DICTUNPACK))]
-+ "TARGET_VIS4B"
-+ "dictunpack\t%1, %2, %0"
-+ [(set_attr "type" "fga")
-+ (set_attr "subtype" "other")])
-+
-+(define_mode_iterator FPCSMODE [V2SI V4HI V8QI])
-+(define_code_iterator fpcscond [le gt eq ne])
-+(define_code_iterator fpcsucond [le gt])
-+
-+(define_insn "fpcmp<fpcscond:code><FPCSMODE:vbits><P:mode>shl"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(fpcscond:FPCSMODE (match_operand:FPCSMODE 1 "register_operand" "e")
-+ (match_operand:FPCSMODE 2 "register_operand" "e"))
-+ (match_operand:SI 3 "imm2_operand" "q")]
-+ UNSPEC_FPCMPSHL))]
-+ "TARGET_VIS4B"
-+ "fpcmp<fpcscond:code><FPCSMODE:vbits>shl\t%1, %2, %3, %0"
-+ [(set_attr "type" "viscmp")])
-+
-+(define_insn "fpcmpu<fpcsucond:code><FPCSMODE:vbits><P:mode>shl"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(fpcsucond:FPCSMODE (match_operand:FPCSMODE 1 "register_operand" "e")
-+ (match_operand:FPCSMODE 2 "register_operand" "e"))
-+ (match_operand:SI 3 "imm2_operand" "q")]
-+ UNSPEC_FPUCMPSHL))]
-+ "TARGET_VIS4B"
-+ "fpcmpu<fpcsucond:code><FPCSMODE:vbits>shl\t%1, %2, %3, %0"
-+ [(set_attr "type" "viscmp")])
-+
-+(define_insn "fpcmpde<FPCSMODE:vbits><P:mode>shl"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_operand:FPCSMODE 1 "register_operand" "e")
-+ (match_operand:FPCSMODE 2 "register_operand" "e")
-+ (match_operand:SI 3 "imm2_operand" "q")]
-+ UNSPEC_FPCMPDESHL))]
-+ "TARGET_VIS4B"
-+ "fpcmpde<FPCSMODE:vbits>shl\t%1, %2, %3, %0"
-+ [(set_attr "type" "viscmp")])
-+
-+(define_insn "fpcmpur<FPCSMODE:vbits><P:mode>shl"
-+ [(set (match_operand:P 0 "register_operand" "=r")
-+ (unspec:P [(match_operand:FPCSMODE 1 "register_operand" "e")
-+ (match_operand:FPCSMODE 2 "register_operand" "e")
-+ (match_operand:SI 3 "imm2_operand" "q")]
-+ UNSPEC_FPCMPURSHL))]
-+ "TARGET_VIS4B"
-+ "fpcmpur<FPCSMODE:vbits>shl\t%1, %2, %3, %0"
-+ [(set_attr "type" "viscmp")])
-+
-+(include "sync.md")
-diff -Nur gcc-10.3.0.orig/gcc/config/sparc/sparc-protos.h gcc-10.3.0/gcc/config/sparc/sparc-protos.h
---- gcc-10.3.0.orig/gcc/config/sparc/sparc-protos.h 2021-04-08 13:56:28.201742273 +0200
-+++ gcc-10.3.0/gcc/config/sparc/sparc-protos.h 2021-04-09 07:51:37.812496739 +0200
-@@ -69,7 +69,6 @@
- extern void sparc_split_mem_reg (rtx, rtx, machine_mode);
- extern int sparc_split_reg_reg_legitimate (rtx, rtx);
- extern void sparc_split_reg_reg (rtx, rtx, machine_mode);
--extern const char *output_load_pcrel_sym (rtx *);
- extern const char *output_ubranch (rtx, rtx_insn *);
- extern const char *output_cbranch (rtx, rtx, int, int, int, rtx_insn *);
- extern const char *output_return (rtx_insn *);
-diff -Nur gcc-10.3.0.orig/gcc/testsuite/gcc.c-torture/compile/20191108-1.c gcc-10.3.0/gcc/testsuite/gcc.c-torture/compile/20191108-1.c
---- gcc-10.3.0.orig/gcc/testsuite/gcc.c-torture/compile/20191108-1.c 2021-04-08 13:56:28.929751064 +0200
-+++ gcc-10.3.0/gcc/testsuite/gcc.c-torture/compile/20191108-1.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,14 +0,0 @@
--/* PR target/92095 */
--/* Testcase by Sergei Trofimovich <slyfox@inbox.ru> */
--
--typedef union {
-- double a;
-- int b[2];
--} c;
--
--double d(int e)
--{
-- c f;
-- (&f)->b[0] = 15728640;
-- return e ? -(&f)->a : (&f)->a;
--}
-diff -Nur gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-3.c gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-3.c
---- gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-3.c 2021-04-08 13:56:29.453757389 +0200
-+++ gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-3.c 2021-04-09 07:51:37.988507907 +0200
-@@ -1,6 +1,6 @@
- /* { dg-do compile } */
- /* { dg-require-effective-target lp64 } */
--/* { dg-options "-O -fno-pie" } */
-+/* { dg-options "-O" } */
-
- #include <stdbool.h>
- #include <stdint.h>
-diff -Nur gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-4.c gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-4.c
---- gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-4.c 2021-04-08 13:56:29.453757389 +0200
-+++ gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-4.c 2021-04-09 07:51:37.988507907 +0200
-@@ -1,6 +1,6 @@
- /* { dg-do compile } */
- /* { dg-require-effective-target lp64 } */
--/* { dg-options "-O -fno-pie -mno-vis3 -mno-vis4" } */
-+/* { dg-options "-O -mno-vis3 -mno-vis4" } */
-
- #include <stdbool.h>
- #include <stdint.h>
-diff -Nur gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-5.c gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-5.c
---- gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-5.c 2021-04-08 13:56:29.453757389 +0200
-+++ gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-5.c 2021-04-09 07:51:37.992508161 +0200
-@@ -1,6 +1,6 @@
- /* { dg-do compile } */
- /* { dg-require-effective-target lp64 } */
--/* { dg-options "-O -fno-pie -mvis3" } */
-+/* { dg-options "-O -mvis3" } */
-
- #include <stdbool.h>
- #include <stdint.h>
diff --git a/toolchain/gcc/patches/10.3.0/add-crtreloc.frv b/toolchain/gcc/patches/10.5.0/add-crtreloc.frv
index 30de24cdc..30de24cdc 100644
--- a/toolchain/gcc/patches/10.3.0/add-crtreloc.frv
+++ b/toolchain/gcc/patches/10.5.0/add-crtreloc.frv
diff --git a/toolchain/gcc/patches/10.3.0/c6x-disable-multilib.patch b/toolchain/gcc/patches/10.5.0/c6x-disable-multilib.patch
index cbee6f785..cbee6f785 100644
--- a/toolchain/gcc/patches/10.3.0/c6x-disable-multilib.patch
+++ b/toolchain/gcc/patches/10.5.0/c6x-disable-multilib.patch
diff --git a/toolchain/gcc/patches/10.3.0/ia64-fix-libgcc.patch b/toolchain/gcc/patches/10.5.0/ia64-fix-libgcc.patch
index f1f3c8d2d..f1f3c8d2d 100644
--- a/toolchain/gcc/patches/10.3.0/ia64-fix-libgcc.patch
+++ b/toolchain/gcc/patches/10.5.0/ia64-fix-libgcc.patch
diff --git a/toolchain/gcc/patches/10.5.0/j2.patch b/toolchain/gcc/patches/10.5.0/j2.patch
new file mode 100644
index 000000000..416475546
--- /dev/null
+++ b/toolchain/gcc/patches/10.5.0/j2.patch
@@ -0,0 +1,346 @@
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index 6fcdd771d4c..839a60d866e 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -547,7 +547,7 @@ s390*-*-*)
+ extra_headers="s390intrin.h htmintrin.h htmxlintrin.h vecintrin.h"
+ ;;
+ # Note the 'l'; we need to be able to match e.g. "shle" or "shl".
+-sh[123456789lbe]*-*-* | sh-*-*)
++sh[123456789lbej]*-*-* | sh-*-*)
+ cpu_type=sh
+ extra_options="${extra_options} fused-madd.opt"
+ extra_objs="${extra_objs} sh_treg_combine.o sh-mem.o sh_optimize_sett_clrt.o"
+@@ -3149,18 +3149,18 @@ s390x-ibm-tpf*)
+ extra_options="${extra_options} s390/tpf.opt"
+ tmake_file="${tmake_file} s390/t-s390"
+ ;;
+-sh-*-elf* | sh[12346l]*-*-elf* | \
+- sh-*-linux* | sh[2346lbe]*-*-linux* | \
++sh-*-elf* | sh[12346lj]*-*-elf* | \
++ sh-*-linux* | sh[2346lbej]*-*-linux* | \
+ sh-*-netbsdelf* | shl*-*-netbsdelf*)
+ tmake_file="${tmake_file} sh/t-sh sh/t-elf"
+ if test x${with_endian} = x; then
+ case ${target} in
+- sh[1234]*be-*-* | sh[1234]*eb-*-*) with_endian=big ;;
++ sh[j1234]*be-*-* | sh[j1234]*eb-*-*) with_endian=big ;;
+ shbe-*-* | sheb-*-*) with_endian=big,little ;;
+ sh[1234]l* | sh[34]*-*-linux*) with_endian=little ;;
+ shl* | sh*-*-linux* | \
+ sh-superh-elf) with_endian=little,big ;;
+- sh[1234]*-*-*) with_endian=big ;;
++ sh[j1234]*-*-*) with_endian=big ;;
+ *) with_endian=big,little ;;
+ esac
+ fi
+@@ -3227,6 +3227,7 @@ sh-*-elf* | sh[12346l]*-*-elf* | \
+ sh2a_nofpu*) sh_cpu_target=sh2a-nofpu ;;
+ sh2a*) sh_cpu_target=sh2a ;;
+ sh2e*) sh_cpu_target=sh2e ;;
++ shj2*) sh_cpu_target=shj2;;
+ sh2*) sh_cpu_target=sh2 ;;
+ *) sh_cpu_target=sh1 ;;
+ esac
+@@ -3248,7 +3249,7 @@ sh-*-elf* | sh[12346l]*-*-elf* | \
+ sh2a-single-only | sh2a-single | sh2a-nofpu | sh2a | \
+ sh4a-single-only | sh4a-single | sh4a-nofpu | sh4a | sh4al | \
+ sh4-single-only | sh4-single | sh4-nofpu | sh4 | sh4-300 | \
+- sh3e | sh3 | sh2e | sh2 | sh1) ;;
++ sh3e | sh3 | sh2e | sh2 | sh1 | shj2) ;;
+ "") sh_cpu_default=${sh_cpu_target} ;;
+ *) echo "with_cpu=$with_cpu not supported"; exit 1 ;;
+ esac
+@@ -3257,9 +3258,9 @@ sh-*-elf* | sh[12346l]*-*-elf* | \
+ case ${target} in
+ sh[1234]*) sh_multilibs=${sh_cpu_target} ;;
+ sh-superh-*) sh_multilibs=m4,m4-single,m4-single-only,m4-nofpu ;;
+- sh*-*-linux*) sh_multilibs=m1,m2,m2a,m3e,m4 ;;
++ sh*-*-linux*) sh_multilibs=m1,m2,m2a,m3e,m4,mj2 ;;
+ sh*-*-netbsd*) sh_multilibs=m3,m3e,m4 ;;
+- *) sh_multilibs=m1,m2,m2e,m4,m4-single,m4-single-only,m2a,m2a-single ;;
++ *) sh_multilibs=m1,m2,m2e,m4,m4-single,m4-single-only,m2a,m2a-single,mj2 ;;
+ esac
+ if test x$with_fp = xno; then
+ sh_multilibs="`echo $sh_multilibs|sed -e s/m4/sh4-nofpu/ -e s/,m4-[^,]*//g -e s/,m[23]e// -e s/m2a,m2a-single/m2a-nofpu/ -e s/m5-..m....,//g`"
+@@ -3274,7 +3275,8 @@ sh-*-elf* | sh[12346l]*-*-elf* | \
+ m1 | m2 | m2e | m3 | m3e | \
+ m4 | m4-single | m4-single-only | m4-nofpu | m4-300 |\
+ m4a | m4a-single | m4a-single-only | m4a-nofpu | m4al | \
+- m2a | m2a-single | m2a-single-only | m2a-nofpu)
++ m2a | m2a-single | m2a-single-only | m2a-nofpu | \
++ mj2)
+ # TM_MULTILIB_CONFIG is used by t-sh for the non-endian multilib definition
+ # It is passed to MULTIILIB_OPTIONS verbatim.
+ TM_MULTILIB_CONFIG="${TM_MULTILIB_CONFIG}/${sh_multilib}"
+@@ -3291,7 +3293,7 @@ sh-*-elf* | sh[12346l]*-*-elf* | \
+ done
+ TM_MULTILIB_CONFIG=`echo $TM_MULTILIB_CONFIG | sed 's:^/::'`
+ if test x${enable_incomplete_targets} = xyes ; then
+- tm_defines="$tm_defines SUPPORT_SH1=1 SUPPORT_SH2E=1 SUPPORT_SH4=1 SUPPORT_SH4_SINGLE=1 SUPPORT_SH2A=1 SUPPORT_SH2A_SINGLE=1"
++ tm_defines="$tm_defines SUPPORT_SH1=1 SUPPORT_SH2E=1 SUPPORT_SH4=1 SUPPORT_SH4_SINGLE=1 SUPPORT_SH2A=1 SUPPORT_SH2A_SINGLE=1 SUPPORT_SHJ2=1"
+ fi
+ tm_file="$tm_file ./sysroot-suffix.h"
+ tmake_file="$tmake_file t-sysroot-suffix"
+@@ -5105,6 +5107,8 @@ case "${target}" in
+ ;;
+ m4a | m4a-single | m4a-single-only | m4a-nofpu | m4al)
+ ;;
++ mj2)
++ ;;
+ *)
+ echo "Unknown CPU used in --with-cpu=$with_cpu, known values:" 1>&2
+ echo "m1 m2 m2e m3 m3e m4 m4-single m4-single-only m4-nofpu" 1>&2
+@@ -5315,7 +5319,7 @@ case ${target} in
+ tmake_file="${cpu_type}/t-${cpu_type} ${tmake_file}"
+ ;;
+
+- sh[123456ble]*-*-* | sh-*-*)
++ sh[123456blej]*-*-* | sh-*-*)
+ c_target_objs="${c_target_objs} sh-c.o"
+ cxx_target_objs="${cxx_target_objs} sh-c.o"
+ ;;
+diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
+index 84c0ea025b4..f15552af011 100644
+--- a/gcc/config/sh/sh.c
++++ b/gcc/config/sh/sh.c
+@@ -686,6 +686,7 @@ parse_validate_atomic_model_option (const char* str)
+ model_names[sh_atomic_model::hard_llcs] = "hard-llcs";
+ model_names[sh_atomic_model::soft_tcb] = "soft-tcb";
+ model_names[sh_atomic_model::soft_imask] = "soft-imask";
++ model_names[sh_atomic_model::hard_cas] = "hard-cas";
+
+ const char* model_cdef_names[sh_atomic_model::num_models];
+ model_cdef_names[sh_atomic_model::none] = "NONE";
+@@ -693,6 +694,7 @@ parse_validate_atomic_model_option (const char* str)
+ model_cdef_names[sh_atomic_model::hard_llcs] = "HARD_LLCS";
+ model_cdef_names[sh_atomic_model::soft_tcb] = "SOFT_TCB";
+ model_cdef_names[sh_atomic_model::soft_imask] = "SOFT_IMASK";
++ model_cdef_names[sh_atomic_model::hard_cas] = "HARD_CAS";
+
+ sh_atomic_model ret;
+ ret.type = sh_atomic_model::none;
+@@ -771,6 +773,9 @@ got_mode_name:;
+ if (ret.type == sh_atomic_model::soft_imask && TARGET_USERMODE)
+ err_ret ("cannot use atomic model %s in user mode", ret.name);
+
++ if (ret.type == sh_atomic_model::hard_cas && !TARGET_SHJ2)
++ err_ret ("atomic model %s is only available J2 targets", ret.name);
++
+ return ret;
+
+ #undef err_ret
+@@ -827,6 +832,8 @@ sh_option_override (void)
+ sh_cpu = PROCESSOR_SH2E;
+ if (TARGET_SH2A)
+ sh_cpu = PROCESSOR_SH2A;
++ if (TARGET_SHJ2)
++ sh_cpu = PROCESSOR_SHJ2;
+ if (TARGET_SH3)
+ sh_cpu = PROCESSOR_SH3;
+ if (TARGET_SH3E)
+diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
+index 8ab5455505c..6ffed6da403 100644
+--- a/gcc/config/sh/sh.h
++++ b/gcc/config/sh/sh.h
+@@ -85,6 +85,7 @@ extern int code_for_indirect_jump_scratch;
+ #define SUPPORT_SH4_SINGLE 1
+ #define SUPPORT_SH2A 1
+ #define SUPPORT_SH2A_SINGLE 1
++#define SUPPORT_SHJ2 1
+ #endif
+
+ #define TARGET_DIVIDE_CALL_DIV1 (sh_div_strategy == SH_DIV_CALL_DIV1)
+@@ -117,6 +118,7 @@ extern int code_for_indirect_jump_scratch;
+ #define SELECT_SH4A_SINGLE_ONLY (MASK_SH4A | SELECT_SH4_SINGLE_ONLY)
+ #define SELECT_SH4A (MASK_SH4A | SELECT_SH4)
+ #define SELECT_SH4A_SINGLE (MASK_SH4A | SELECT_SH4_SINGLE)
++#define SELECT_SHJ2 (MASK_SHJ2 | SELECT_SH2)
+
+ #if SUPPORT_SH1
+ #define SUPPORT_SH2 1
+@@ -124,6 +126,7 @@ extern int code_for_indirect_jump_scratch;
+ #if SUPPORT_SH2
+ #define SUPPORT_SH3 1
+ #define SUPPORT_SH2A_NOFPU 1
++#define SUPPORT_SHJ2 1
+ #endif
+ #if SUPPORT_SH3
+ #define SUPPORT_SH4_NOFPU 1
+@@ -156,7 +159,7 @@ extern int code_for_indirect_jump_scratch;
+ #define MASK_ARCH (MASK_SH1 | MASK_SH2 | MASK_SH3 | MASK_SH_E | MASK_SH4 \
+ | MASK_HARD_SH2A | MASK_HARD_SH2A_DOUBLE | MASK_SH4A \
+ | MASK_HARD_SH4 | MASK_FPU_SINGLE \
+- | MASK_FPU_SINGLE_ONLY)
++ | MASK_FPU_SINGLE_ONLY | MASK_SHJ2)
+
+ /* This defaults us to big-endian. */
+ #ifndef TARGET_ENDIAN_DEFAULT
+@@ -231,7 +234,8 @@ extern int code_for_indirect_jump_scratch;
+ %{m2a-single:--isa=sh2a} \
+ %{m2a-single-only:--isa=sh2a} \
+ %{m2a-nofpu:--isa=sh2a-nofpu} \
+-%{m4al:-dsp}"
++%{m4al:-dsp} \
++%{mj2:-isa=j2}"
+
+ #define ASM_SPEC SH_ASM_SPEC
+
+@@ -347,6 +351,7 @@ struct sh_atomic_model
+ hard_llcs,
+ soft_tcb,
+ soft_imask,
++ hard_cas,
+
+ num_models
+ };
+@@ -390,6 +395,9 @@ extern const sh_atomic_model& selected_atomic_model (void);
+ #define TARGET_ATOMIC_SOFT_IMASK \
+ (selected_atomic_model ().type == sh_atomic_model::soft_imask)
+
++#define TARGET_ATOMIC_HARD_CAS \
++ (selected_atomic_model ().type == sh_atomic_model::hard_cas)
++
+ #endif // __cplusplus
+
+ #define SUBTARGET_OVERRIDE_OPTIONS (void) 0
+@@ -1484,7 +1492,7 @@ extern bool current_function_interrupt;
+
+ /* Nonzero if the target supports dynamic shift instructions
+ like shad and shld. */
+-#define TARGET_DYNSHIFT (TARGET_SH3 || TARGET_SH2A)
++#define TARGET_DYNSHIFT (TARGET_SH3 || TARGET_SH2A || TARGET_SHJ2)
+
+ /* The cost of using the dynamic shift insns (shad, shld) are the same
+ if they are available. If they are not available a library function will
+@@ -1747,6 +1755,7 @@ enum processor_type {
+ PROCESSOR_SH2,
+ PROCESSOR_SH2E,
+ PROCESSOR_SH2A,
++ PROCESSOR_SHJ2,
+ PROCESSOR_SH3,
+ PROCESSOR_SH3E,
+ PROCESSOR_SH4,
+diff --git a/gcc/config/sh/sh.opt b/gcc/config/sh/sh.opt
+index 908603b92e1..e6108dabbc6 100644
+--- a/gcc/config/sh/sh.opt
++++ b/gcc/config/sh/sh.opt
+@@ -65,6 +65,10 @@ m2e
+ Target RejectNegative Condition(SUPPORT_SH2E)
+ Generate SH2e code.
+
++mj2
++Target RejectNegative Mask(SHJ2) Condition(SUPPORT_SHJ2)
++Generate J2 code.
++
+ m3
+ Target RejectNegative Mask(SH3) Condition(SUPPORT_SH3)
+ Generate SH3 code.
+diff --git a/gcc/config/sh/sync.md b/gcc/config/sh/sync.md
+index 25f3b695d2f..55119386a18 100644
+--- a/gcc/config/sh/sync.md
++++ b/gcc/config/sh/sync.md
+@@ -240,6 +240,9 @@
+ || (TARGET_SH4A && <MODE>mode == SImode && !TARGET_ATOMIC_STRICT))
+ atomic_insn = gen_atomic_compare_and_swap<mode>_hard (old_val, mem,
+ exp_val, new_val);
++ else if (TARGET_ATOMIC_HARD_CAS && <MODE>mode == SImode)
++ atomic_insn = gen_atomic_compare_and_swap<mode>_cas (old_val, mem,
++ exp_val, new_val);
+ else if (TARGET_ATOMIC_SOFT_GUSA)
+ atomic_insn = gen_atomic_compare_and_swap<mode>_soft_gusa (old_val, mem,
+ exp_val, new_val);
+@@ -306,6 +309,57 @@
+ }
+ [(set_attr "length" "14")])
+
++(define_expand "atomic_compare_and_swapsi_cas"
++ [(set (match_operand:SI 0 "register_operand" "=r")
++ (unspec_volatile:SI
++ [(match_operand:SI 1 "atomic_mem_operand_0" "=Sra")
++ (match_operand:SI 2 "register_operand" "r")
++ (match_operand:SI 3 "register_operand" "r")]
++ UNSPECV_CMPXCHG_1))]
++ "TARGET_ATOMIC_HARD_CAS"
++{
++ rtx mem = gen_rtx_REG (SImode, 0);
++ emit_move_insn (mem, force_reg (SImode, XEXP (operands[1], 0)));
++ emit_insn (gen_shj2_cas (operands[0], mem, operands[2], operands[3]));
++ DONE;
++})
++
++(define_insn "shj2_cas"
++ [(set (match_operand:SI 0 "register_operand" "=&r")
++ (unspec_volatile:SI
++ [(match_operand:SI 1 "register_operand" "=r")
++ (match_operand:SI 2 "register_operand" "r")
++ (match_operand:SI 3 "register_operand" "0")]
++ UNSPECV_CMPXCHG_1))
++ (set (reg:SI T_REG)
++ (unspec_volatile:SI [(const_int 0)] UNSPECV_CMPXCHG_3))]
++ "TARGET_ATOMIC_HARD_CAS"
++ "cas.l %2,%0,@%1"
++ [(set_attr "length" "2")]
++)
++
++(define_expand "atomic_compare_and_swapqi_cas"
++ [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
++ (unspec_volatile:SI
++ [(match_operand:SI 1 "atomic_mem_operand_0" "=Sra")
++ (match_operand:SI 2 "arith_operand" "rI08")
++ (match_operand:SI 3 "arith_operand" "rI08")]
++ UNSPECV_CMPXCHG_1))]
++ "TARGET_ATOMIC_HARD_CAS"
++{FAIL;}
++)
++
++(define_expand "atomic_compare_and_swaphi_cas"
++ [(set (match_operand:SI 0 "arith_reg_dest" "=&r")
++ (unspec_volatile:SI
++ [(match_operand:SI 1 "atomic_mem_operand_0" "=Sra")
++ (match_operand:SI 2 "arith_operand" "rI08")
++ (match_operand:SI 3 "arith_operand" "rI08")]
++ UNSPECV_CMPXCHG_1))]
++ "TARGET_ATOMIC_HARD_CAS"
++{FAIL;}
++)
++
+ ;; The QIHImode llcs patterns modify the address register of the memory
+ ;; operand. In order to express that, we have to open code the memory
+ ;; operand. Initially the insn is expanded like every other atomic insn
+diff --git a/gcc/config/sh/t-sh b/gcc/config/sh/t-sh
+index a402359be72..dbd0bf992bf 100644
+--- a/gcc/config/sh/t-sh
++++ b/gcc/config/sh/t-sh
+@@ -50,7 +50,8 @@ MULTILIB_MATCHES = $(shell \
+ m2e,m3e,m4-single-only,m4-100-single-only,m4-200-single-only,m4-300-single-only,m4a-single-only \
+ m2a-single,m2a-single-only \
+ m4-single,m4-100-single,m4-200-single,m4-300-single,m4a-single \
+- m4,m4-100,m4-200,m4-300,m4a; do \
++ m4,m4-100,m4-200,m4-300,m4a \
++ mj2; do \
+ subst= ; \
+ for lib in `echo $$abi|tr , ' '` ; do \
+ if test "`echo $$multilibs|sed s/$$lib//`" != "$$multilibs"; then \
+@@ -63,9 +64,9 @@ MULTILIB_MATCHES = $(shell \
+
+ # SH1 and SH2A support big endian only.
+ ifeq ($(DEFAULT_ENDIAN),ml)
+-MULTILIB_EXCEPTIONS = m1 ml/m1 m2a* ml/m2a* $(TM_MULTILIB_EXCEPTIONS_CONFIG)
++MULTILIB_EXCEPTIONS = m1 ml/m1 m2a* ml/m2a* ml/mj2 $(TM_MULTILIB_EXCEPTIONS_CONFIG)
+ else
+-MULTILIB_EXCEPTIONS = ml/m1 ml/m2a* $(TM_MULTILIB_EXCEPTIONS_CONFIG)
++MULTILIB_EXCEPTIONS = ml/m1 ml/m2a* ml/mj2 $(TM_MULTILIB_EXCEPTIONS_CONFIG)
+ endif
+
+ MULTILIB_OSDIRNAMES = \
+@@ -87,7 +88,8 @@ MULTILIB_OSDIRNAMES = \
+ m4a-single-only=!m4a-single-only $(OTHER_ENDIAN)/m4a-single-only=!$(OTHER_ENDIAN)/m4a-single-only \
+ m4a-single=!m4a-single $(OTHER_ENDIAN)/m4a-single=!$(OTHER_ENDIAN)/m4a-single \
+ m4a=!m4a $(OTHER_ENDIAN)/m4a=!$(OTHER_ENDIAN)/m4a \
+- m4al=!m4al $(OTHER_ENDIAN)/m4al=!$(OTHER_ENDIAN)/m4al
++ m4al=!m4al $(OTHER_ENDIAN)/m4al=!$(OTHER_ENDIAN)/m4al \
++ mj2=!j2
+
+ $(out_object_file): gt-sh.h
+ gt-sh.h : s-gtype ; @true
diff --git a/toolchain/gcc/patches/10.3.0/nios2-softfp.patch b/toolchain/gcc/patches/10.5.0/nios2-softfp.patch
index c677c6c2f..c677c6c2f 100644
--- a/toolchain/gcc/patches/10.3.0/nios2-softfp.patch
+++ b/toolchain/gcc/patches/10.5.0/nios2-softfp.patch
diff --git a/toolchain/gcc/patches/10.5.0/revert-sparc.patch b/toolchain/gcc/patches/10.5.0/revert-sparc.patch
new file mode 100644
index 000000000..2ce948c82
--- /dev/null
+++ b/toolchain/gcc/patches/10.5.0/revert-sparc.patch
@@ -0,0 +1,283 @@
+diff -Nur gcc-10.3.0.orig/gcc/config/sparc/sparc.c gcc-10.3.0/gcc/config/sparc/sparc.c
+--- gcc-10.3.0.orig/gcc/config/sparc/sparc.c 2021-04-08 13:56:28.201742273 +0200
++++ gcc-10.3.0/gcc/config/sparc/sparc.c 2022-01-24 10:19:53.724121161 +0100
+@@ -4157,6 +4157,13 @@
+ static bool
+ sparc_cannot_force_const_mem (machine_mode mode, rtx x)
+ {
++ /* After IRA has run in PIC mode, it is too late to put anything into the
++ constant pool if the PIC register hasn't already been initialized. */
++ if ((lra_in_progress || reload_in_progress)
++ && flag_pic
++ && !crtl->uses_pic_offset_table)
++ return true;
++
+ switch (GET_CODE (x))
+ {
+ case CONST_INT:
+@@ -4192,11 +4199,9 @@
+ }
+
+ /* Global Offset Table support. */
+-static GTY(()) rtx got_symbol_rtx = NULL_RTX;
+-static GTY(()) rtx got_register_rtx = NULL_RTX;
+ static GTY(()) rtx got_helper_rtx = NULL_RTX;
+-
+-static GTY(()) bool got_helper_needed = false;
++static GTY(()) rtx got_register_rtx = NULL_RTX;
++static GTY(()) rtx got_symbol_rtx = NULL_RTX;
+
+ /* Return the SYMBOL_REF for the Global Offset Table. */
+
+@@ -4209,6 +4214,27 @@
+ return got_symbol_rtx;
+ }
+
++#ifdef HAVE_GAS_HIDDEN
++# define USE_HIDDEN_LINKONCE 1
++#else
++# define USE_HIDDEN_LINKONCE 0
++#endif
++
++static void
++get_pc_thunk_name (char name[32], unsigned int regno)
++{
++ const char *reg_name = reg_names[regno];
++
++ /* Skip the leading '%' as that cannot be used in a
++ symbol name. */
++ reg_name += 1;
++
++ if (USE_HIDDEN_LINKONCE)
++ sprintf (name, "__sparc_get_pc_thunk.%s", reg_name);
++ else
++ ASM_GENERATE_INTERNAL_LABEL (name, "LADDPC", regno);
++}
++
+ /* Wrapper around the load_pcrel_sym{si,di} patterns. */
+
+ static rtx
+@@ -4228,78 +4254,30 @@
+ return insn;
+ }
+
+-/* Output the load_pcrel_sym{si,di} patterns. */
+-
+-const char *
+-output_load_pcrel_sym (rtx *operands)
+-{
+- if (flag_delayed_branch)
+- {
+- output_asm_insn ("sethi\t%%hi(%a1-4), %0", operands);
+- output_asm_insn ("call\t%a2", operands);
+- output_asm_insn (" add\t%0, %%lo(%a1+4), %0", operands);
+- }
+- else
+- {
+- output_asm_insn ("sethi\t%%hi(%a1-8), %0", operands);
+- output_asm_insn ("add\t%0, %%lo(%a1-4), %0", operands);
+- output_asm_insn ("call\t%a2", operands);
+- output_asm_insn (" nop", NULL);
+- }
+-
+- if (operands[2] == got_helper_rtx)
+- got_helper_needed = true;
+-
+- return "";
+-}
+-
+-#ifdef HAVE_GAS_HIDDEN
+-# define USE_HIDDEN_LINKONCE 1
+-#else
+-# define USE_HIDDEN_LINKONCE 0
+-#endif
+-
+ /* Emit code to load the GOT register. */
+
+ void
+ load_got_register (void)
+ {
+- rtx insn;
++ if (!got_register_rtx)
++ got_register_rtx = gen_rtx_REG (Pmode, GLOBAL_OFFSET_TABLE_REGNUM);
+
+ if (TARGET_VXWORKS_RTP)
+- {
+- if (!got_register_rtx)
+- got_register_rtx = pic_offset_table_rtx;
+-
+- insn = gen_vxworks_load_got ();
+- }
++ emit_insn (gen_vxworks_load_got ());
+ else
+ {
+- if (!got_register_rtx)
+- got_register_rtx = gen_rtx_REG (Pmode, GLOBAL_OFFSET_TABLE_REGNUM);
+-
+ /* The GOT symbol is subject to a PC-relative relocation so we need a
+ helper function to add the PC value and thus get the final value. */
+ if (!got_helper_rtx)
+ {
+ char name[32];
+-
+- /* Skip the leading '%' as that cannot be used in a symbol name. */
+- if (USE_HIDDEN_LINKONCE)
+- sprintf (name, "__sparc_get_pc_thunk.%s",
+- reg_names[REGNO (got_register_rtx)] + 1);
+- else
+- ASM_GENERATE_INTERNAL_LABEL (name, "LADDPC",
+- REGNO (got_register_rtx));
+-
++ get_pc_thunk_name (name, GLOBAL_OFFSET_TABLE_REGNUM);
+ got_helper_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
+ }
+
+- insn
+- = gen_load_pcrel_sym (got_register_rtx, sparc_got (), got_helper_rtx);
++ emit_insn (gen_load_pcrel_sym (got_register_rtx, sparc_got (),
++ got_helper_rtx));
+ }
+-
+- emit_insn (insn);
+ }
+
+ /* Ensure that we are not using patterns that are not OK with PIC. */
+@@ -5464,7 +5442,7 @@
+ return true;
+
+ /* GOT register (%l7) if needed. */
+- if (got_register_rtx && regno == REGNO (got_register_rtx))
++ if (regno == GLOBAL_OFFSET_TABLE_REGNUM && got_register_rtx)
+ return true;
+
+ /* If the function accesses prior frames, the frame pointer and the return
+@@ -12507,9 +12485,10 @@
+ sparc_file_end (void)
+ {
+ /* If we need to emit the special GOT helper function, do so now. */
+- if (got_helper_needed)
++ if (got_helper_rtx)
+ {
+ const char *name = XSTR (got_helper_rtx, 0);
++ const char *reg_name = reg_names[GLOBAL_OFFSET_TABLE_REGNUM];
+ #ifdef DWARF2_UNWIND_INFO
+ bool do_cfi;
+ #endif
+@@ -12546,22 +12525,17 @@
+ #ifdef DWARF2_UNWIND_INFO
+ do_cfi = dwarf2out_do_cfi_asm ();
+ if (do_cfi)
+- output_asm_insn (".cfi_startproc", NULL);
++ fprintf (asm_out_file, "\t.cfi_startproc\n");
+ #endif
+ if (flag_delayed_branch)
+- {
+- output_asm_insn ("jmp\t%%o7+8", NULL);
+- output_asm_insn (" add\t%%o7, %0, %0", &got_register_rtx);
+- }
++ fprintf (asm_out_file, "\tjmp\t%%o7+8\n\t add\t%%o7, %s, %s\n",
++ reg_name, reg_name);
+ else
+- {
+- output_asm_insn ("add\t%%o7, %0, %0", &got_register_rtx);
+- output_asm_insn ("jmp\t%%o7+8", NULL);
+- output_asm_insn (" nop", NULL);
+- }
++ fprintf (asm_out_file, "\tadd\t%%o7, %s, %s\n\tjmp\t%%o7+8\n\t nop\n",
++ reg_name, reg_name);
+ #ifdef DWARF2_UNWIND_INFO
+ if (do_cfi)
+- output_asm_insn (".cfi_endproc", NULL);
++ fprintf (asm_out_file, "\t.cfi_endproc\n");
+ #endif
+ }
+
+@@ -13056,10 +13030,7 @@
+ edge entry_edge;
+ rtx_insn *seq;
+
+- /* In PIC mode, we need to always initialize the PIC register if optimization
+- is enabled, because we are called from IRA and LRA may later force things
+- to the constant pool for optimization purposes. */
+- if (!flag_pic || (!crtl->uses_pic_offset_table && !optimize))
++ if (!crtl->uses_pic_offset_table)
+ return;
+
+ start_sequence ();
+diff -Nur gcc-10.3.0.orig/gcc/config/sparc/sparc.md gcc-10.3.0/gcc/config/sparc/sparc.md
+--- gcc-10.3.0.orig/gcc/config/sparc/sparc.md 2021-04-08 13:56:28.205742322 +0200
++++ gcc-10.3.0/gcc/config/sparc/sparc.md 2022-01-24 10:19:54.504102046 +0100
+@@ -1601,7 +1601,10 @@
+ (clobber (reg:P O7_REG))]
+ "REGNO (operands[0]) == INTVAL (operands[3])"
+ {
+- return output_load_pcrel_sym (operands);
++ if (flag_delayed_branch)
++ return "sethi\t%%hi(%a1-4), %0\n\tcall\t%a2\n\t add\t%0, %%lo(%a1+4), %0";
++ else
++ return "sethi\t%%hi(%a1-8), %0\n\tadd\t%0, %%lo(%a1-4), %0\n\tcall\t%a2\n\t nop";
+ }
+ [(set (attr "type") (const_string "multi"))
+ (set (attr "length")
+diff -Nur gcc-10.3.0.orig/gcc/config/sparc/sparc-protos.h gcc-10.3.0/gcc/config/sparc/sparc-protos.h
+--- gcc-10.3.0.orig/gcc/config/sparc/sparc-protos.h 2021-04-08 13:56:28.201742273 +0200
++++ gcc-10.3.0/gcc/config/sparc/sparc-protos.h 2022-01-24 10:19:54.548100968 +0100
+@@ -69,7 +69,6 @@
+ extern void sparc_split_mem_reg (rtx, rtx, machine_mode);
+ extern int sparc_split_reg_reg_legitimate (rtx, rtx);
+ extern void sparc_split_reg_reg (rtx, rtx, machine_mode);
+-extern const char *output_load_pcrel_sym (rtx *);
+ extern const char *output_ubranch (rtx, rtx_insn *);
+ extern const char *output_cbranch (rtx, rtx, int, int, int, rtx_insn *);
+ extern const char *output_return (rtx_insn *);
+diff -Nur gcc-10.3.0.orig/gcc/testsuite/gcc.c-torture/compile/20191108-1.c gcc-10.3.0/gcc/testsuite/gcc.c-torture/compile/20191108-1.c
+--- gcc-10.3.0.orig/gcc/testsuite/gcc.c-torture/compile/20191108-1.c 2021-04-08 13:56:28.929751064 +0200
++++ gcc-10.3.0/gcc/testsuite/gcc.c-torture/compile/20191108-1.c 1970-01-01 01:00:00.000000000 +0100
+@@ -1,14 +0,0 @@
+-/* PR target/92095 */
+-/* Testcase by Sergei Trofimovich <slyfox@inbox.ru> */
+-
+-typedef union {
+- double a;
+- int b[2];
+-} c;
+-
+-double d(int e)
+-{
+- c f;
+- (&f)->b[0] = 15728640;
+- return e ? -(&f)->a : (&f)->a;
+-}
+diff -Nur gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-3.c gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-3.c
+--- gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-3.c 2021-04-08 13:56:29.453757389 +0200
++++ gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-3.c 2022-01-24 10:19:54.688097536 +0100
+@@ -1,6 +1,6 @@
+ /* { dg-do compile } */
+ /* { dg-require-effective-target lp64 } */
+-/* { dg-options "-O -fno-pie" } */
++/* { dg-options "-O" } */
+
+ #include <stdbool.h>
+ #include <stdint.h>
+diff -Nur gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-4.c gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-4.c
+--- gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-4.c 2021-04-08 13:56:29.453757389 +0200
++++ gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-4.c 2022-01-24 10:19:55.336081656 +0100
+@@ -1,6 +1,6 @@
+ /* { dg-do compile } */
+ /* { dg-require-effective-target lp64 } */
+-/* { dg-options "-O -fno-pie -mno-vis3 -mno-vis4" } */
++/* { dg-options "-O -mno-vis3 -mno-vis4" } */
+
+ #include <stdbool.h>
+ #include <stdint.h>
+diff -Nur gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-5.c gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-5.c
+--- gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-5.c 2021-04-08 13:56:29.453757389 +0200
++++ gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-5.c 2022-01-24 10:19:55.336081656 +0100
+@@ -1,6 +1,6 @@
+ /* { dg-do compile } */
+ /* { dg-require-effective-target lp64 } */
+-/* { dg-options "-O -fno-pie -mvis3" } */
++/* { dg-options "-O -mvis3" } */
+
+ #include <stdbool.h>
+ #include <stdint.h>
diff --git a/toolchain/gcc/patches/11.4.0/add-crtreloc.frv b/toolchain/gcc/patches/11.4.0/add-crtreloc.frv
new file mode 100644
index 000000000..30de24cdc
--- /dev/null
+++ b/toolchain/gcc/patches/11.4.0/add-crtreloc.frv
@@ -0,0 +1,12 @@
+diff -Nur gcc-8.3.0.orig/gcc/config/frv/linux.h gcc-8.3.0/gcc/config/frv/linux.h
+--- gcc-8.3.0.orig/gcc/config/frv/linux.h 2018-01-03 11:03:58.000000000 +0100
++++ gcc-8.3.0/gcc/config/frv/linux.h 2019-10-08 10:52:00.176295821 +0200
+@@ -27,7 +27,7 @@
+
+ #undef STARTFILE_SPEC
+ #define STARTFILE_SPEC \
+- "%{!shared: %{pg|p|profile:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}} \
++ "%{!shared: %{pg|p|profile:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}} crtreloc.o%s \
+ crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}"
+
+ #undef ENDFILE_SPEC
diff --git a/toolchain/gcc/patches/11.4.0/c6x-disable-multilib.patch b/toolchain/gcc/patches/11.4.0/c6x-disable-multilib.patch
new file mode 100644
index 000000000..cbee6f785
--- /dev/null
+++ b/toolchain/gcc/patches/11.4.0/c6x-disable-multilib.patch
@@ -0,0 +1,10 @@
+diff -Nur gcc-8.3.0.orig/gcc/config/c6x/t-c6x-uclinux gcc-8.3.0/gcc/config/c6x/t-c6x-uclinux
+--- gcc-8.3.0.orig/gcc/config/c6x/t-c6x-uclinux 2011-11-02 16:23:48.000000000 +0100
++++ gcc-8.3.0/gcc/config/c6x/t-c6x-uclinux 2019-10-08 07:49:50.255159650 +0200
+@@ -1,3 +1,3 @@
+-MULTILIB_OSDIRNAMES = march.c674x=!c674x
+-MULTILIB_OSDIRNAMES += mbig-endian=!be
+-MULTILIB_OSDIRNAMES += mbig-endian/march.c674x=!be/c674x
++MULTILIB_OSDIRNAMES =
++#MULTILIB_OSDIRNAMES += mbig-endian=!be
++#MULTILIB_OSDIRNAMES += mbig-endian/march.c674x=!be/c674x
diff --git a/toolchain/gcc/patches/11.4.0/csky.patch b/toolchain/gcc/patches/11.4.0/csky.patch
new file mode 100644
index 000000000..ee352951b
--- /dev/null
+++ b/toolchain/gcc/patches/11.4.0/csky.patch
@@ -0,0 +1,12 @@
+diff -Nur gcc-11.2.0.orig/libgcc/config/csky/linux-atomic.c gcc-11.2.0/libgcc/config/csky/linux-atomic.c
+--- gcc-11.2.0.orig/libgcc/config/csky/linux-atomic.c 2021-07-28 08:55:08.760307899 +0200
++++ gcc-11.2.0/libgcc/config/csky/linux-atomic.c 2021-12-14 14:19:23.685729233 +0100
+@@ -24,7 +24,7 @@
+ <http://www.gnu.org/licenses/>. */
+
+ /* Kernel helper for compare-and-exchange. */
+-inline int
++int
+ __kernel_cmpxchg (int oldval, int newval, volatile int *ptr)
+ {
+ register int _a0 asm ("a0") = oldval;
diff --git a/toolchain/gcc/patches/11.4.0/ia64-fix-libgcc.patch b/toolchain/gcc/patches/11.4.0/ia64-fix-libgcc.patch
new file mode 100644
index 000000000..f1f3c8d2d
--- /dev/null
+++ b/toolchain/gcc/patches/11.4.0/ia64-fix-libgcc.patch
@@ -0,0 +1,17 @@
+diff -Nur gcc-6.3.0.orig/libgcc/config/ia64/fde-glibc.c gcc-6.3.0/libgcc/config/ia64/fde-glibc.c
+--- gcc-6.3.0.orig/libgcc/config/ia64/fde-glibc.c 2016-01-04 15:30:50.000000000 +0100
++++ gcc-6.3.0/libgcc/config/ia64/fde-glibc.c 2017-03-05 13:07:33.316600613 +0100
+@@ -25,6 +25,8 @@
+ /* Locate the FDE entry for a given address, using glibc ld.so routines
+ to avoid register/deregister calls at DSO load/unload. */
+
++#ifndef inhibit_libc
++
+ #ifndef _GNU_SOURCE
+ #define _GNU_SOURCE 1
+ #endif
+@@ -159,3 +161,4 @@
+
+ return data.ret;
+ }
++#endif
diff --git a/toolchain/gcc/patches/11.4.0/nios2-softfp.patch b/toolchain/gcc/patches/11.4.0/nios2-softfp.patch
new file mode 100644
index 000000000..c677c6c2f
--- /dev/null
+++ b/toolchain/gcc/patches/11.4.0/nios2-softfp.patch
@@ -0,0 +1,14 @@
+diff -Nur gcc-6.2.0.orig/libgcc/config.host gcc-6.2.0/libgcc/config.host
+--- gcc-6.2.0.orig/libgcc/config.host 2016-05-17 08:15:52.000000000 +0200
++++ gcc-6.2.0/libgcc/config.host 2016-10-15 14:42:53.971919904 +0200
+@@ -962,6 +962,10 @@
+ ;;
+ esac
+ ;;
++nios2-*-linux-uclibc*)
++ tmake_file="$tmake_file nios2/t-nios2 nios2/t-linux t-libgcc-pic t-slibgcc-libgcc t-softfp-sfdf t-softfp"
++ md_unwind_header=nios2/linux-unwind.h
++ ;;
+ nios2-*-linux*)
+ tmake_file="$tmake_file nios2/t-nios2 nios2/t-linux t-libgcc-pic t-slibgcc-libgcc"
+ md_unwind_header=nios2/linux-unwind.h
diff --git a/toolchain/gcc/patches/11.4.0/revert.sparc b/toolchain/gcc/patches/11.4.0/revert.sparc
new file mode 100644
index 000000000..2ce948c82
--- /dev/null
+++ b/toolchain/gcc/patches/11.4.0/revert.sparc
@@ -0,0 +1,283 @@
+diff -Nur gcc-10.3.0.orig/gcc/config/sparc/sparc.c gcc-10.3.0/gcc/config/sparc/sparc.c
+--- gcc-10.3.0.orig/gcc/config/sparc/sparc.c 2021-04-08 13:56:28.201742273 +0200
++++ gcc-10.3.0/gcc/config/sparc/sparc.c 2022-01-24 10:19:53.724121161 +0100
+@@ -4157,6 +4157,13 @@
+ static bool
+ sparc_cannot_force_const_mem (machine_mode mode, rtx x)
+ {
++ /* After IRA has run in PIC mode, it is too late to put anything into the
++ constant pool if the PIC register hasn't already been initialized. */
++ if ((lra_in_progress || reload_in_progress)
++ && flag_pic
++ && !crtl->uses_pic_offset_table)
++ return true;
++
+ switch (GET_CODE (x))
+ {
+ case CONST_INT:
+@@ -4192,11 +4199,9 @@
+ }
+
+ /* Global Offset Table support. */
+-static GTY(()) rtx got_symbol_rtx = NULL_RTX;
+-static GTY(()) rtx got_register_rtx = NULL_RTX;
+ static GTY(()) rtx got_helper_rtx = NULL_RTX;
+-
+-static GTY(()) bool got_helper_needed = false;
++static GTY(()) rtx got_register_rtx = NULL_RTX;
++static GTY(()) rtx got_symbol_rtx = NULL_RTX;
+
+ /* Return the SYMBOL_REF for the Global Offset Table. */
+
+@@ -4209,6 +4214,27 @@
+ return got_symbol_rtx;
+ }
+
++#ifdef HAVE_GAS_HIDDEN
++# define USE_HIDDEN_LINKONCE 1
++#else
++# define USE_HIDDEN_LINKONCE 0
++#endif
++
++static void
++get_pc_thunk_name (char name[32], unsigned int regno)
++{
++ const char *reg_name = reg_names[regno];
++
++ /* Skip the leading '%' as that cannot be used in a
++ symbol name. */
++ reg_name += 1;
++
++ if (USE_HIDDEN_LINKONCE)
++ sprintf (name, "__sparc_get_pc_thunk.%s", reg_name);
++ else
++ ASM_GENERATE_INTERNAL_LABEL (name, "LADDPC", regno);
++}
++
+ /* Wrapper around the load_pcrel_sym{si,di} patterns. */
+
+ static rtx
+@@ -4228,78 +4254,30 @@
+ return insn;
+ }
+
+-/* Output the load_pcrel_sym{si,di} patterns. */
+-
+-const char *
+-output_load_pcrel_sym (rtx *operands)
+-{
+- if (flag_delayed_branch)
+- {
+- output_asm_insn ("sethi\t%%hi(%a1-4), %0", operands);
+- output_asm_insn ("call\t%a2", operands);
+- output_asm_insn (" add\t%0, %%lo(%a1+4), %0", operands);
+- }
+- else
+- {
+- output_asm_insn ("sethi\t%%hi(%a1-8), %0", operands);
+- output_asm_insn ("add\t%0, %%lo(%a1-4), %0", operands);
+- output_asm_insn ("call\t%a2", operands);
+- output_asm_insn (" nop", NULL);
+- }
+-
+- if (operands[2] == got_helper_rtx)
+- got_helper_needed = true;
+-
+- return "";
+-}
+-
+-#ifdef HAVE_GAS_HIDDEN
+-# define USE_HIDDEN_LINKONCE 1
+-#else
+-# define USE_HIDDEN_LINKONCE 0
+-#endif
+-
+ /* Emit code to load the GOT register. */
+
+ void
+ load_got_register (void)
+ {
+- rtx insn;
++ if (!got_register_rtx)
++ got_register_rtx = gen_rtx_REG (Pmode, GLOBAL_OFFSET_TABLE_REGNUM);
+
+ if (TARGET_VXWORKS_RTP)
+- {
+- if (!got_register_rtx)
+- got_register_rtx = pic_offset_table_rtx;
+-
+- insn = gen_vxworks_load_got ();
+- }
++ emit_insn (gen_vxworks_load_got ());
+ else
+ {
+- if (!got_register_rtx)
+- got_register_rtx = gen_rtx_REG (Pmode, GLOBAL_OFFSET_TABLE_REGNUM);
+-
+ /* The GOT symbol is subject to a PC-relative relocation so we need a
+ helper function to add the PC value and thus get the final value. */
+ if (!got_helper_rtx)
+ {
+ char name[32];
+-
+- /* Skip the leading '%' as that cannot be used in a symbol name. */
+- if (USE_HIDDEN_LINKONCE)
+- sprintf (name, "__sparc_get_pc_thunk.%s",
+- reg_names[REGNO (got_register_rtx)] + 1);
+- else
+- ASM_GENERATE_INTERNAL_LABEL (name, "LADDPC",
+- REGNO (got_register_rtx));
+-
++ get_pc_thunk_name (name, GLOBAL_OFFSET_TABLE_REGNUM);
+ got_helper_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
+ }
+
+- insn
+- = gen_load_pcrel_sym (got_register_rtx, sparc_got (), got_helper_rtx);
++ emit_insn (gen_load_pcrel_sym (got_register_rtx, sparc_got (),
++ got_helper_rtx));
+ }
+-
+- emit_insn (insn);
+ }
+
+ /* Ensure that we are not using patterns that are not OK with PIC. */
+@@ -5464,7 +5442,7 @@
+ return true;
+
+ /* GOT register (%l7) if needed. */
+- if (got_register_rtx && regno == REGNO (got_register_rtx))
++ if (regno == GLOBAL_OFFSET_TABLE_REGNUM && got_register_rtx)
+ return true;
+
+ /* If the function accesses prior frames, the frame pointer and the return
+@@ -12507,9 +12485,10 @@
+ sparc_file_end (void)
+ {
+ /* If we need to emit the special GOT helper function, do so now. */
+- if (got_helper_needed)
++ if (got_helper_rtx)
+ {
+ const char *name = XSTR (got_helper_rtx, 0);
++ const char *reg_name = reg_names[GLOBAL_OFFSET_TABLE_REGNUM];
+ #ifdef DWARF2_UNWIND_INFO
+ bool do_cfi;
+ #endif
+@@ -12546,22 +12525,17 @@
+ #ifdef DWARF2_UNWIND_INFO
+ do_cfi = dwarf2out_do_cfi_asm ();
+ if (do_cfi)
+- output_asm_insn (".cfi_startproc", NULL);
++ fprintf (asm_out_file, "\t.cfi_startproc\n");
+ #endif
+ if (flag_delayed_branch)
+- {
+- output_asm_insn ("jmp\t%%o7+8", NULL);
+- output_asm_insn (" add\t%%o7, %0, %0", &got_register_rtx);
+- }
++ fprintf (asm_out_file, "\tjmp\t%%o7+8\n\t add\t%%o7, %s, %s\n",
++ reg_name, reg_name);
+ else
+- {
+- output_asm_insn ("add\t%%o7, %0, %0", &got_register_rtx);
+- output_asm_insn ("jmp\t%%o7+8", NULL);
+- output_asm_insn (" nop", NULL);
+- }
++ fprintf (asm_out_file, "\tadd\t%%o7, %s, %s\n\tjmp\t%%o7+8\n\t nop\n",
++ reg_name, reg_name);
+ #ifdef DWARF2_UNWIND_INFO
+ if (do_cfi)
+- output_asm_insn (".cfi_endproc", NULL);
++ fprintf (asm_out_file, "\t.cfi_endproc\n");
+ #endif
+ }
+
+@@ -13056,10 +13030,7 @@
+ edge entry_edge;
+ rtx_insn *seq;
+
+- /* In PIC mode, we need to always initialize the PIC register if optimization
+- is enabled, because we are called from IRA and LRA may later force things
+- to the constant pool for optimization purposes. */
+- if (!flag_pic || (!crtl->uses_pic_offset_table && !optimize))
++ if (!crtl->uses_pic_offset_table)
+ return;
+
+ start_sequence ();
+diff -Nur gcc-10.3.0.orig/gcc/config/sparc/sparc.md gcc-10.3.0/gcc/config/sparc/sparc.md
+--- gcc-10.3.0.orig/gcc/config/sparc/sparc.md 2021-04-08 13:56:28.205742322 +0200
++++ gcc-10.3.0/gcc/config/sparc/sparc.md 2022-01-24 10:19:54.504102046 +0100
+@@ -1601,7 +1601,10 @@
+ (clobber (reg:P O7_REG))]
+ "REGNO (operands[0]) == INTVAL (operands[3])"
+ {
+- return output_load_pcrel_sym (operands);
++ if (flag_delayed_branch)
++ return "sethi\t%%hi(%a1-4), %0\n\tcall\t%a2\n\t add\t%0, %%lo(%a1+4), %0";
++ else
++ return "sethi\t%%hi(%a1-8), %0\n\tadd\t%0, %%lo(%a1-4), %0\n\tcall\t%a2\n\t nop";
+ }
+ [(set (attr "type") (const_string "multi"))
+ (set (attr "length")
+diff -Nur gcc-10.3.0.orig/gcc/config/sparc/sparc-protos.h gcc-10.3.0/gcc/config/sparc/sparc-protos.h
+--- gcc-10.3.0.orig/gcc/config/sparc/sparc-protos.h 2021-04-08 13:56:28.201742273 +0200
++++ gcc-10.3.0/gcc/config/sparc/sparc-protos.h 2022-01-24 10:19:54.548100968 +0100
+@@ -69,7 +69,6 @@
+ extern void sparc_split_mem_reg (rtx, rtx, machine_mode);
+ extern int sparc_split_reg_reg_legitimate (rtx, rtx);
+ extern void sparc_split_reg_reg (rtx, rtx, machine_mode);
+-extern const char *output_load_pcrel_sym (rtx *);
+ extern const char *output_ubranch (rtx, rtx_insn *);
+ extern const char *output_cbranch (rtx, rtx, int, int, int, rtx_insn *);
+ extern const char *output_return (rtx_insn *);
+diff -Nur gcc-10.3.0.orig/gcc/testsuite/gcc.c-torture/compile/20191108-1.c gcc-10.3.0/gcc/testsuite/gcc.c-torture/compile/20191108-1.c
+--- gcc-10.3.0.orig/gcc/testsuite/gcc.c-torture/compile/20191108-1.c 2021-04-08 13:56:28.929751064 +0200
++++ gcc-10.3.0/gcc/testsuite/gcc.c-torture/compile/20191108-1.c 1970-01-01 01:00:00.000000000 +0100
+@@ -1,14 +0,0 @@
+-/* PR target/92095 */
+-/* Testcase by Sergei Trofimovich <slyfox@inbox.ru> */
+-
+-typedef union {
+- double a;
+- int b[2];
+-} c;
+-
+-double d(int e)
+-{
+- c f;
+- (&f)->b[0] = 15728640;
+- return e ? -(&f)->a : (&f)->a;
+-}
+diff -Nur gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-3.c gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-3.c
+--- gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-3.c 2021-04-08 13:56:29.453757389 +0200
++++ gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-3.c 2022-01-24 10:19:54.688097536 +0100
+@@ -1,6 +1,6 @@
+ /* { dg-do compile } */
+ /* { dg-require-effective-target lp64 } */
+-/* { dg-options "-O -fno-pie" } */
++/* { dg-options "-O" } */
+
+ #include <stdbool.h>
+ #include <stdint.h>
+diff -Nur gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-4.c gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-4.c
+--- gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-4.c 2021-04-08 13:56:29.453757389 +0200
++++ gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-4.c 2022-01-24 10:19:55.336081656 +0100
+@@ -1,6 +1,6 @@
+ /* { dg-do compile } */
+ /* { dg-require-effective-target lp64 } */
+-/* { dg-options "-O -fno-pie -mno-vis3 -mno-vis4" } */
++/* { dg-options "-O -mno-vis3 -mno-vis4" } */
+
+ #include <stdbool.h>
+ #include <stdint.h>
+diff -Nur gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-5.c gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-5.c
+--- gcc-10.3.0.orig/gcc/testsuite/gcc.target/sparc/overflow-5.c 2021-04-08 13:56:29.453757389 +0200
++++ gcc-10.3.0/gcc/testsuite/gcc.target/sparc/overflow-5.c 2022-01-24 10:19:55.336081656 +0100
+@@ -1,6 +1,6 @@
+ /* { dg-do compile } */
+ /* { dg-require-effective-target lp64 } */
+-/* { dg-options "-O -fno-pie -mvis3" } */
++/* { dg-options "-O -mvis3" } */
+
+ #include <stdbool.h>
+ #include <stdint.h>
diff --git a/toolchain/gcc/patches/12.3.0/csky.patch b/toolchain/gcc/patches/12.3.0/csky.patch
new file mode 100644
index 000000000..ee352951b
--- /dev/null
+++ b/toolchain/gcc/patches/12.3.0/csky.patch
@@ -0,0 +1,12 @@
+diff -Nur gcc-11.2.0.orig/libgcc/config/csky/linux-atomic.c gcc-11.2.0/libgcc/config/csky/linux-atomic.c
+--- gcc-11.2.0.orig/libgcc/config/csky/linux-atomic.c 2021-07-28 08:55:08.760307899 +0200
++++ gcc-11.2.0/libgcc/config/csky/linux-atomic.c 2021-12-14 14:19:23.685729233 +0100
+@@ -24,7 +24,7 @@
+ <http://www.gnu.org/licenses/>. */
+
+ /* Kernel helper for compare-and-exchange. */
+-inline int
++int
+ __kernel_cmpxchg (int oldval, int newval, volatile int *ptr)
+ {
+ register int _a0 asm ("a0") = oldval;
diff --git a/toolchain/gcc/patches/12.3.0/nios2-softfp.patch b/toolchain/gcc/patches/12.3.0/nios2-softfp.patch
new file mode 100644
index 000000000..c677c6c2f
--- /dev/null
+++ b/toolchain/gcc/patches/12.3.0/nios2-softfp.patch
@@ -0,0 +1,14 @@
+diff -Nur gcc-6.2.0.orig/libgcc/config.host gcc-6.2.0/libgcc/config.host
+--- gcc-6.2.0.orig/libgcc/config.host 2016-05-17 08:15:52.000000000 +0200
++++ gcc-6.2.0/libgcc/config.host 2016-10-15 14:42:53.971919904 +0200
+@@ -962,6 +962,10 @@
+ ;;
+ esac
+ ;;
++nios2-*-linux-uclibc*)
++ tmake_file="$tmake_file nios2/t-nios2 nios2/t-linux t-libgcc-pic t-slibgcc-libgcc t-softfp-sfdf t-softfp"
++ md_unwind_header=nios2/linux-unwind.h
++ ;;
+ nios2-*-linux*)
+ tmake_file="$tmake_file nios2/t-nios2 nios2/t-linux t-libgcc-pic t-slibgcc-libgcc"
+ md_unwind_header=nios2/linux-unwind.h
diff --git a/toolchain/gcc/patches/13.2.0/csky.patch b/toolchain/gcc/patches/13.2.0/csky.patch
new file mode 100644
index 000000000..ee352951b
--- /dev/null
+++ b/toolchain/gcc/patches/13.2.0/csky.patch
@@ -0,0 +1,12 @@
+diff -Nur gcc-11.2.0.orig/libgcc/config/csky/linux-atomic.c gcc-11.2.0/libgcc/config/csky/linux-atomic.c
+--- gcc-11.2.0.orig/libgcc/config/csky/linux-atomic.c 2021-07-28 08:55:08.760307899 +0200
++++ gcc-11.2.0/libgcc/config/csky/linux-atomic.c 2021-12-14 14:19:23.685729233 +0100
+@@ -24,7 +24,7 @@
+ <http://www.gnu.org/licenses/>. */
+
+ /* Kernel helper for compare-and-exchange. */
+-inline int
++int
+ __kernel_cmpxchg (int oldval, int newval, volatile int *ptr)
+ {
+ register int _a0 asm ("a0") = oldval;
diff --git a/toolchain/gcc/patches/13.2.0/nios2-softfp.patch b/toolchain/gcc/patches/13.2.0/nios2-softfp.patch
new file mode 100644
index 000000000..c677c6c2f
--- /dev/null
+++ b/toolchain/gcc/patches/13.2.0/nios2-softfp.patch
@@ -0,0 +1,14 @@
+diff -Nur gcc-6.2.0.orig/libgcc/config.host gcc-6.2.0/libgcc/config.host
+--- gcc-6.2.0.orig/libgcc/config.host 2016-05-17 08:15:52.000000000 +0200
++++ gcc-6.2.0/libgcc/config.host 2016-10-15 14:42:53.971919904 +0200
+@@ -962,6 +962,10 @@
+ ;;
+ esac
+ ;;
++nios2-*-linux-uclibc*)
++ tmake_file="$tmake_file nios2/t-nios2 nios2/t-linux t-libgcc-pic t-slibgcc-libgcc t-softfp-sfdf t-softfp"
++ md_unwind_header=nios2/linux-unwind.h
++ ;;
+ nios2-*-linux*)
+ tmake_file="$tmake_file nios2/t-nios2 nios2/t-linux t-libgcc-pic t-slibgcc-libgcc"
+ md_unwind_header=nios2/linux-unwind.h
diff --git a/toolchain/gcc/patches/4.5.4/gcc.lm32 b/toolchain/gcc/patches/4.5.4/gcc.lm32
index f32fb0dbd..df77ddf83 100644
--- a/toolchain/gcc/patches/4.5.4/gcc.lm32
+++ b/toolchain/gcc/patches/4.5.4/gcc.lm32
@@ -114,7 +114,7 @@ diff -Nur gcc-4.5.4.orig/libgcc/config.host gcc-4.5.4/libgcc/config.host
tmake_file="lm32/t-lm32 lm32/t-elf t-softfp"
;;
-lm32-*-uclinux*)
-+lm32-*-linux*)
++lm32-*-*linux*)
extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o"
- tmake_file="lm32/t-lm32 lm32/t-uclinux t-softfp"
+ tmake_file="lm32/t-lm32 t-softfp"
diff --git a/toolchain/gdb/Makefile.inc b/toolchain/gdb/Makefile.inc
index b12d535f2..c38242eef 100644
--- a/toolchain/gdb/Makefile.inc
+++ b/toolchain/gdb/Makefile.inc
@@ -2,12 +2,26 @@
# material, please see the LICENCE file in the top-level directory.
PKG_NAME:= gdb
-ifeq ($(ADK_TOOLCHAIN_GDB_11_1),y)
-PKG_VERSION:= 11.1
+ifeq ($(ADK_TOOLCHAIN_GDB_14_2),y)
+PKG_VERSION:= 14.2
PKG_RELEASE:= 1
-PKG_HASH:= cccfcc407b20d343fb320d4a9a2110776dd3165118ffd41f4b1b162340333f94
+PKG_HASH:= 2de5174762e959a5e529e20c20d88a04735469d8fffd98f61664e70b341dc47c
PKG_SITES:= ${MASTER_SITE_GNU:=gdb/}
-DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
+endif
+ifeq ($(ADK_TOOLCHAIN_GDB_13_2),y)
+PKG_VERSION:= 13.2
+PKG_RELEASE:= 1
+PKG_HASH:= 7ead13d9e19fa0c57bb19104e1a5f67eefa9fc79f2e6360de491e8fddeda1e30
+PKG_SITES:= ${MASTER_SITE_GNU:=gdb/}
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
+endif
+ifeq ($(ADK_TOOLCHAIN_GDB_12_1),y)
+PKG_VERSION:= 12.1
+PKG_RELEASE:= 1
+PKG_HASH:= 87296a3a9727356b56712c793704082d5df0ff36a34ca9ec9734fc9a8bdfdaab
+PKG_SITES:= ${MASTER_SITE_GNU:=gdb/}
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
endif
ifeq ($(ADK_TOOLCHAIN_GDB_6_7_1),y)
PKG_VERSION:= 6.7.1
@@ -22,11 +36,11 @@ PKG_VERSION:= ysato-h8300
PKG_RELEASE:= 1
PKG_GIT:= branch
PKG_SITES:= git://git.pf.osdn.jp/gitroot/y/ys/ysato/binutils_gdb.git
-DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
endif
ifeq ($(ADK_TOOLCHAIN_GDB_GIT),y)
PKG_VERSION:= git
PKG_RELEASE:= 1
PKG_SITES:= git://sourceware.org/git/binutils-gdb.git
-DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
+DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
endif
diff --git a/toolchain/glibc/Makefile b/toolchain/glibc/Makefile
index 684da9b78..ecd6f8d2b 100644
--- a/toolchain/glibc/Makefile
+++ b/toolchain/glibc/Makefile
@@ -6,12 +6,13 @@ include ../rules.mk
include Makefile.inc
include ${ADK_TOPDIR}/mk/buildhlp.mk
-# glibc does not compile with Os and CPU specific FLAGS for m68k/x86_64
-ifeq ($(ADK_TARGET_ARCH_X86_64)$(ADK_TARGET_ARCH_M68K),y)
+# glibc does not boot with Os and CPU specific FLAGS for nios2
+ifeq ($(ADK_TARGET_ARCH_NIOS2),y)
TARGET_CFLAGS:= -O2
TARGET_CXXFLAGS:= -O2
endif
+# glibc does not compile with NEON suggested CFLAGS/CXXFLAGS
TARGET_CFLAGS:= $(filter-out -ffast-math,$(TARGET_CFLAGS))
TARGET_CXXFLAGS:= $(filter-out -ffast-math,$(TARGET_CXXFLAGS))
@@ -40,6 +41,13 @@ GLIBC_ENV:= PATH='${HOST_PATH}:${TARGET_PATH}' \
libc_cv_gnu99_inline=yes \
libc_cv_initfini_array=yes
+ifeq ($(ADK_TARGET_ARCH_RISCV64),y)
+GLIBC_ENV+= libc_cv_slibdir=/lib libc_cv_rtlddir=/lib
+endif
+ifeq ($(ADK_TARGET_ARCH_RISCV32),y)
+GLIBC_ENV+= libc_cv_slibdir=/lib libc_cv_rtlddir=/lib
+endif
+
GLIBC_MAKEOPTS+= cross-compiling=yes
ifeq (${ADK_MAKE_PARALLEL},y)
GLIBC_MAKEOPTS+= PARALLELMFLAGS="-j$(ADK_MAKE_JOBS)"
diff --git a/toolchain/glibc/Makefile.inc b/toolchain/glibc/Makefile.inc
index e5adc4b43..0cd8f4987 100644
--- a/toolchain/glibc/Makefile.inc
+++ b/toolchain/glibc/Makefile.inc
@@ -3,16 +3,16 @@
PKG_NAME:= glibc
ifeq ($(ADK_LIBC_VERSION),git)
-PKG_VERSION:= 2.34.90
-PKG_GLIBCVER:= 2.34.9000
-PKG_SITES:= git://sourceware.org/git/glibc.git
+PKG_VERSION:= 2.39.90
+PKG_GLIBCVER:= 2.39.9000
+PKG_SITES:= https://sourceware.org/git/glibc.git
PKG_RELEASE:= 1
endif
-ifeq ($(ADK_TARGET_LIB_GLIBC_2_34),y)
-PKG_VERSION:= 2.34
-PKG_GLIBCVER:= 2.34
+ifeq ($(ADK_TARGET_LIB_GLIBC_2_39),y)
+PKG_VERSION:= 2.39
+PKG_GLIBCVER:= 2.39
PKG_RELEASE:= 1
PKG_SITES:= ${MASTER_SITE_GNU:=glibc/}
-PKG_HASH:= 44d26a1fe20b8853a48f470ead01e4279e869ac149b195dda4e44a195d981ab2
+PKG_HASH:= f77bd47cf8170c57365ae7bf86696c118adb3b120d3259c64c502d3dc1e2d926
endif
DISTFILES:= $(PKG_NAME)-$(PKG_VERSION).tar.xz
diff --git a/toolchain/glibc/patches/2.26/0001-Do-not-use-__builtin_types_compatible_p-in-C-mode-bu.patch b/toolchain/glibc/patches/2.26/0001-Do-not-use-__builtin_types_compatible_p-in-C-mode-bu.patch
deleted file mode 100644
index 27a785e31..000000000
--- a/toolchain/glibc/patches/2.26/0001-Do-not-use-__builtin_types_compatible_p-in-C-mode-bu.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From f7439f9b1089e17b6721f28e228682831a2f0135 Mon Sep 17 00:00:00 2001
-From: "Gabriel F. T. Gomes" <gftg@linux.vnet.ibm.com>
-Date: Mon, 21 Aug 2017 14:23:27 +0200
-Subject: [PATCH] Do not use __builtin_types_compatible_p in C++ mode (bug
- 21930)
-
-The logic to define isinf for float128 depends on the availability of
-__builtin_types_compatible_p, which is only available in C mode,
-however, the conditionals do not check for C or C++ mode. This lead to
-an error in libstdc++ configure, as reported by bug 21930.
-
-This patch adds a conditional for C mode in the definition of isinf for
-float128. No definition is provided in C++ mode, since libstdc++
-headers undefine isinf.
-
-Tested for powerpc64le (glibc test suite and libstdc++-v3 configure).
-
- [BZ #21930]
- * math/math.h (isinf): Check if in C or C++ mode before using
- __builtin_types_compatible_p, since this is a C mode feature.
-
-(cherry picked from commit 47a67213a9f51c5f8816d240500b10db605d8b77)
-[Romain rebase on glibc 2.26]
-Signed-off-by: Romain Naour <romain.naour@gmail.com>
----
- math/math.h | 8 ++++++--
- 1 file changed, 6 insertions(+), 2 deletions(-)
-
-diff --git a/math/math.h b/math/math.h
-index e217080..dea8dbe 100644
---- a/math/math.h
-+++ b/math/math.h
-@@ -442,8 +442,12 @@ enum
-
- /* Return nonzero value if X is positive or negative infinity. */
- # if __HAVE_DISTINCT_FLOAT128 && !__GNUC_PREREQ (7,0) \
-- && !defined __SUPPORT_SNAN__
-- /* __builtin_isinf_sign is broken for float128 only before GCC 7.0. */
-+ && !defined __SUPPORT_SNAN__ && !defined __cplusplus
-+ /* Since __builtin_isinf_sign is broken for float128 before GCC 7.0,
-+ use the helper function, __isinff128, with older compilers. This is
-+ only provided for C mode, because in C++ mode, GCC has no support
-+ for __builtin_types_compatible_p (and when in C++ mode, this macro is
-+ not used anyway, because libstdc++ headers undefine it). */
- # define isinf(x) \
- (__builtin_types_compatible_p (__typeof (x), _Float128) \
- ? __isinff128 (x) : __builtin_isinf_sign (x))
---
-2.9.5
-
diff --git a/toolchain/glibc/patches/2.26/0002-Do-not-use-generic-selection-in-C-mode.patch b/toolchain/glibc/patches/2.26/0002-Do-not-use-generic-selection-in-C-mode.patch
deleted file mode 100644
index 7321eebd6..000000000
--- a/toolchain/glibc/patches/2.26/0002-Do-not-use-generic-selection-in-C-mode.patch
+++ /dev/null
@@ -1,56 +0,0 @@
-From bb21afc362a3ecba07ab386a0bc4385e75fbd4b5 Mon Sep 17 00:00:00 2001
-From: "Gabriel F. T. Gomes" <gftg@linux.vnet.ibm.com>
-Date: Mon, 14 Aug 2017 17:51:51 -0300
-Subject: [PATCH] Do not use generic selection in C++ mode
-
-The logic to protect the use of generic selection (_Generic) does not
-check for C or C++ mode, however, generic selection is a C-only
-feature.
-
-Tested for powerpc64le.
-
- * misc/sys/cdefs.h (__HAVE_GENERIC_SELECTION): Define to 0, if
- in C++ mode.
-
-(cherry picked from commit 6913ad65e00bb32417ad39c41d292b976171e27e)
-[Romain rebase on glibc 2.26]
-Signed-off-by: Romain Naour <romain.naour@gmail.com>
----
- misc/sys/cdefs.h | 19 ++++++++++---------
- 1 file changed, 10 insertions(+), 9 deletions(-)
-
-diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
-index 06523bf..0c80821 100644
---- a/misc/sys/cdefs.h
-+++ b/misc/sys/cdefs.h
-@@ -464,17 +464,18 @@
- # define __glibc_macro_warning(msg)
- #endif
-
--/* Support for generic selection (ISO C11) is available in GCC since
-- version 4.9. Previous versions do not provide generic selection,
-- even though they might set __STDC_VERSION__ to 201112L, when in
-- -std=c11 mode. Thus, we must check for !defined __GNUC__ when
-- testing __STDC_VERSION__ for generic selection support.
-+/* Generic selection (ISO C11) is a C-only feature, available in GCC
-+ since version 4.9. Previous versions do not provide generic
-+ selection, even though they might set __STDC_VERSION__ to 201112L,
-+ when in -std=c11 mode. Thus, we must check for !defined __GNUC__
-+ when testing __STDC_VERSION__ for generic selection support.
- On the other hand, Clang also defines __GNUC__, so a clang-specific
- check is required to enable the use of generic selection. */
--#if __GNUC_PREREQ (4, 9) \
-- || __glibc_clang_has_extension (c_generic_selections) \
-- || (!defined __GNUC__ && defined __STDC_VERSION__ \
-- && __STDC_VERSION__ >= 201112L)
-+#if !defined __cplusplus \
-+ && (__GNUC_PREREQ (4, 9) \
-+ || __glibc_clang_has_extension (c_generic_selections) \
-+ || (!defined __GNUC__ && defined __STDC_VERSION__ \
-+ && __STDC_VERSION__ >= 201112L))
- # define __HAVE_GENERIC_SELECTION 1
- #else
- # define __HAVE_GENERIC_SELECTION 0
---
-2.9.5
-
diff --git a/toolchain/glibc/patches/2.26/0003-Provide-a-C-version-of-issignaling-that-does-not-use.patch b/toolchain/glibc/patches/2.26/0003-Provide-a-C-version-of-issignaling-that-does-not-use.patch
deleted file mode 100644
index b9cd3df39..000000000
--- a/toolchain/glibc/patches/2.26/0003-Provide-a-C-version-of-issignaling-that-does-not-use.patch
+++ /dev/null
@@ -1,225 +0,0 @@
-From 9bcf391a21677c6d5fa1c2be71554ec181e24f39 Mon Sep 17 00:00:00 2001
-From: "Gabriel F. T. Gomes" <gftg@linux.vnet.ibm.com>
-Date: Mon, 14 Aug 2017 13:46:15 -0300
-Subject: [PATCH] Provide a C++ version of issignaling that does not use
- __MATH_TG
-
-The macro __MATH_TG contains the logic to select between long double and
-_Float128, when these types are ABI-distinct. This logic relies on
-__builtin_types_compatible_p, which is not available in C++ mode.
-
-On the other hand, C++ function overloading provides the means to
-distinguish between the floating-point types. The overloading
-resolution will match the correct parameter regardless of type
-qualifiers, i.e.: const and volatile.
-
-Tested for powerpc64le, s390x, and x86_64.
-
- * math/math.h [defined __cplusplus] (issignaling): Provide a C++
- definition for issignaling that does not rely on __MATH_TG,
- since __MATH_TG uses __builtin_types_compatible_p, which is only
- available in C mode.
- (CFLAGS-test-math-issignaling.cc): New variable.
- * math/Makefile [CXX] (tests): Add test-math-issignaling.
- * math/test-math-issignaling.cc: New test for C++ implementation
- of type-generic issignaling.
- * sysdeps/powerpc/powerpc64le/Makefile [subdir == math]
- (CXXFLAGS-test-math-issignaling.cc): Add -mfloat128 to the build
- options of test-math-issignaling on powerpc64le.
-
-(cherry picked from commit a16e8bc08edca84d507715c66d6cddbbc7ed3b62)
-[Romain rebase on glibc 2.26]
-Signed-off-by: Romain Naour <romain.naour@gmail.com>
----
- math/Makefile | 3 +-
- math/math.h | 19 +++++-
- math/test-math-issignaling.cc | 113 +++++++++++++++++++++++++++++++++++
- sysdeps/powerpc/powerpc64le/Makefile | 1 +
- 4 files changed, 134 insertions(+), 2 deletions(-)
- create mode 100644 math/test-math-issignaling.cc
-
-diff --git a/math/Makefile b/math/Makefile
-index e09b0c0..0130fcf 100644
---- a/math/Makefile
-+++ b/math/Makefile
-@@ -203,7 +203,7 @@ tests-static = test-fpucw-static test-fpucw-ieee-static \
- test-signgam-ullong-static test-signgam-ullong-init-static
-
- ifneq (,$(CXX))
--tests += test-math-isinff test-math-iszero
-+tests += test-math-isinff test-math-iszero test-math-issignaling
- endif
-
- ifneq (no,$(PERL))
-@@ -350,6 +350,7 @@ CFLAGS-test-signgam-ullong-init-static.c = -std=c99
-
- CFLAGS-test-math-isinff.cc = -std=gnu++11
- CFLAGS-test-math-iszero.cc = -std=gnu++11
-+CFLAGS-test-math-issignaling.cc = -std=gnu++11
-
- CFLAGS-test-iszero-excess-precision.c = -fexcess-precision=standard
- CFLAGS-test-iseqsig-excess-precision.c = -fexcess-precision=standard
-diff --git a/math/math.h b/math/math.h
-index dea8dbe..add86af 100644
---- a/math/math.h
-+++ b/math/math.h
-@@ -474,7 +474,24 @@ enum
- # include <bits/iscanonical.h>
-
- /* Return nonzero value if X is a signaling NaN. */
--# define issignaling(x) __MATH_TG ((x), __issignaling, (x))
-+# ifndef __cplusplus
-+# define issignaling(x) __MATH_TG ((x), __issignaling, (x))
-+# else
-+ /* In C++ mode, __MATH_TG cannot be used, because it relies on
-+ __builtin_types_compatible_p, which is a C-only builtin. On the
-+ other hand, overloading provides the means to distinguish between
-+ the floating-point types. The overloading resolution will match
-+ the correct parameter (regardless of type qualifiers (i.e.: const
-+ and volatile). */
-+extern "C++" {
-+inline int issignaling (float __val) { return __issignalingf (__val); }
-+inline int issignaling (double __val) { return __issignaling (__val); }
-+inline int issignaling (long double __val) { return __issignalingl (__val); }
-+# if __HAVE_DISTINCT_FLOAT128
-+inline int issignaling (_Float128 __val) { return __issignalingf128 (__val); }
-+# endif
-+} /* extern C++ */
-+# endif
-
- /* Return nonzero value if X is subnormal. */
- # define issubnormal(x) (fpclassify (x) == FP_SUBNORMAL)
-diff --git a/math/test-math-issignaling.cc b/math/test-math-issignaling.cc
-new file mode 100644
-index 0000000..22ae9e1
---- /dev/null
-+++ b/math/test-math-issignaling.cc
-@@ -0,0 +1,113 @@
-+/* Test for the C++ implementation of issignaling.
-+ Copyright (C) 2017 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ 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
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#define _GNU_SOURCE 1
-+#include <math.h>
-+#include <stdio.h>
-+
-+#include <limits>
-+
-+/* There is no signaling_NaN for _Float128 in std::numeric_limits.
-+ Include ieee754_float128.h and use the bitfields in the union
-+ ieee854_float128.ieee_nan to build a signaling NaN. */
-+#if __HAVE_DISTINCT_FLOAT128
-+# include <ieee754_float128.h>
-+#endif
-+
-+static bool errors;
-+
-+static void
-+check (int actual, int expected, const char *actual_expr, int line)
-+{
-+ if (actual != expected)
-+ {
-+ errors = true;
-+ printf ("%s:%d: error: %s\n", __FILE__, line, actual_expr);
-+ printf ("%s:%d: expected: %d\n", __FILE__, line, expected);
-+ printf ("%s:%d: actual: %d\n", __FILE__, line, actual);
-+ }
-+}
-+
-+#define CHECK(actual, expected) \
-+ check ((actual), (expected), #actual, __LINE__)
-+
-+template <class T>
-+static void
-+check_type ()
-+{
-+ typedef std::numeric_limits<T> limits;
-+ CHECK (issignaling (T{0}), 0);
-+ if (limits::has_infinity)
-+ {
-+ CHECK (issignaling (limits::infinity ()), 0);
-+ CHECK (issignaling (-limits::infinity ()), 0);
-+ }
-+ if (limits::has_quiet_NaN)
-+ CHECK (issignaling (limits::quiet_NaN ()), 0);
-+ if (limits::has_signaling_NaN)
-+ CHECK (issignaling (limits::signaling_NaN ()), 1);
-+}
-+
-+#if __HAVE_DISTINCT_FLOAT128
-+static void
-+check_float128 ()
-+{
-+ ieee854_float128 q;
-+
-+ q.d = 0;
-+ CHECK (issignaling (q.d), 0);
-+
-+ /* Infinity. */
-+ q.ieee.negative = 0;
-+ q.ieee.exponent = 0x7FFF;
-+ q.ieee.mantissa0 = 0x0000;
-+ q.ieee.mantissa1 = 0x00000000;
-+ q.ieee.mantissa2 = 0x00000000;
-+ q.ieee.mantissa3 = 0x00000000;
-+ CHECK (issignaling (q.d), 0);
-+
-+ /* Quiet NaN. */
-+ q.ieee_nan.quiet_nan = 1;
-+ q.ieee_nan.mantissa0 = 0x0000;
-+ CHECK (issignaling (q.d), 0);
-+
-+ /* Still a quiet NaN. */
-+ q.ieee_nan.quiet_nan = 1;
-+ q.ieee_nan.mantissa0 = 0x4000;
-+ CHECK (issignaling (q.d), 0);
-+
-+ /* Signaling NaN. */
-+ q.ieee_nan.quiet_nan = 0;
-+ q.ieee_nan.mantissa0 = 0x4000;
-+ CHECK (issignaling (q.d), 1);
-+}
-+#endif
-+
-+static int
-+do_test (void)
-+{
-+ check_type<float> ();
-+ check_type<double> ();
-+ check_type<long double> ();
-+#if __HAVE_DISTINCT_FLOAT128
-+ check_float128 ();
-+#endif
-+ return errors;
-+}
-+
-+#include <support/test-driver.c>
-diff --git a/sysdeps/powerpc/powerpc64le/Makefile b/sysdeps/powerpc/powerpc64le/Makefile
-index 77617b6..19adbfa 100644
---- a/sysdeps/powerpc/powerpc64le/Makefile
-+++ b/sysdeps/powerpc/powerpc64le/Makefile
-@@ -16,6 +16,7 @@ $(foreach suf,$(all-object-suffixes),%f128_r$(suf)): CFLAGS += -mfloat128
- $(foreach suf,$(all-object-suffixes),$(objpfx)test-float128%$(suf)): CFLAGS += -mfloat128
- $(foreach suf,$(all-object-suffixes),$(objpfx)test-ifloat128%$(suf)): CFLAGS += -mfloat128
- CFLAGS-libm-test-support-float128.c += -mfloat128
-+CFLAGS-test-math-issignaling.cc += -mfloat128
- $(objpfx)test-float128% $(objpfx)test-ifloat128%: \
- gnulib-tests += $(f128-loader-link)
- endif
---
-2.9.5
-
diff --git a/toolchain/glibc/patches/2.26/0004-Fix-the-C-version-of-issignaling-when-__NO_LONG_DOUB.patch b/toolchain/glibc/patches/2.26/0004-Fix-the-C-version-of-issignaling-when-__NO_LONG_DOUB.patch
deleted file mode 100644
index 5e32f754d..000000000
--- a/toolchain/glibc/patches/2.26/0004-Fix-the-C-version-of-issignaling-when-__NO_LONG_DOUB.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-From 9dbd8386a1b706beb30291a7e76bbfe69c2620cf Mon Sep 17 00:00:00 2001
-From: "Gabriel F. T. Gomes" <gftg@linux.vnet.ibm.com>
-Date: Wed, 23 Aug 2017 10:16:54 -0300
-Subject: [PATCH] Fix the C++ version of issignaling when __NO_LONG_DOUBLE_MATH
- is defined
-
-When __NO_LONG_DOUBLE_MATH is defined, __issignalingl is not available,
-thus issignaling with long double argument should call __issignaling,
-instead.
-
-Tested for powerpc64le.
-
- * math/math.h [defined __cplusplus] (issignaling): In the long
- double case, call __issignalingl only if __NO_LONG_DOUBLE_MATH
- is not defined. Call __issignaling, otherwise.
-
-(cherry picked from commit 3d7b66f66cb223e899a7ebc0f4c20f13e711c9e0)
-[Romain rebase on glibc 2.26]
-Signed-off-by: Romain Naour <romain.naour@gmail.com>
----
- math/math.h | 10 +++++++++-
- 1 file changed, 9 insertions(+), 1 deletion(-)
-
-diff --git a/math/math.h b/math/math.h
-index add86af..60dfa31 100644
---- a/math/math.h
-+++ b/math/math.h
-@@ -486,7 +486,15 @@ enum
- extern "C++" {
- inline int issignaling (float __val) { return __issignalingf (__val); }
- inline int issignaling (double __val) { return __issignaling (__val); }
--inline int issignaling (long double __val) { return __issignalingl (__val); }
-+inline int
-+issignaling (long double __val)
-+{
-+# ifdef __NO_LONG_DOUBLE_MATH
-+ return __issignaling (__val);
-+# else
-+ return __issignalingl (__val);
-+# endif
-+}
- # if __HAVE_DISTINCT_FLOAT128
- inline int issignaling (_Float128 __val) { return __issignalingf128 (__val); }
- # endif
---
-2.9.5
-
diff --git a/toolchain/glibc/patches/2.26/0005-Provide-a-C-version-of-iszero-that-does-not-use-__MA.patch b/toolchain/glibc/patches/2.26/0005-Provide-a-C-version-of-iszero-that-does-not-use-__MA.patch
deleted file mode 100644
index e12c8438f..000000000
--- a/toolchain/glibc/patches/2.26/0005-Provide-a-C-version-of-iszero-that-does-not-use-__MA.patch
+++ /dev/null
@@ -1,210 +0,0 @@
-From 45970aa26d1af87b016ef95b4b35c566aeb6e841 Mon Sep 17 00:00:00 2001
-From: "Gabriel F. T. Gomes" <gftg@linux.vnet.ibm.com>
-Date: Tue, 22 Aug 2017 16:34:42 -0300
-Subject: [PATCH] Provide a C++ version of iszero that does not use __MATH_TG
- (bug 21930)
-
-When signaling nans are enabled (with -fsignaling-nans), the C++ version
-of iszero uses the fpclassify macro, which is defined with __MATH_TG.
-However, when support for float128 is available, __MATH_TG uses the
-builtin __builtin_types_compatible_p, which is only available in C mode.
-
-This patch refactors the C++ version of iszero so that it uses function
-overloading to select between the floating-point types, instead of
-relying on fpclassify and __MATH_TG.
-
-Tested for powerpc64le, s390x, x86_64, and with build-many-glibcs.py.
-
- [BZ #21930]
- * math/math.h [defined __cplusplus && defined __SUPPORT_SNAN__]
- (iszero): New C++ implementation that does not use
- fpclassify/__MATH_TG/__builtin_types_compatible_p, when
- signaling nans are enabled, since __builtin_types_compatible_p
- is a C-only feature.
- * math/test-math-iszero.cc: When __HAVE_DISTINCT_FLOAT128 is
- defined, include ieee754_float128.h for access to the union and
- member ieee854_float128.ieee.
- [__HAVE_DISTINCT_FLOAT128] (do_test): Call check_float128.
- [__HAVE_DISTINCT_FLOAT128] (check_float128): New function.
- * sysdeps/powerpc/powerpc64le/Makefile [subdir == math]
- (CXXFLAGS-test-math-iszero.cc): Add -mfloat128 to the build
- options of test-math-zero on powerpc64le.
-
-(cherry picked from commit 42496114ec0eb7d6d039d05d4262e109951c600c)
-[Romain rebase on glibc 2.26]
-Signed-off-by: Romain Naour <romain.naour@gmail.com>
----
- math/math.h | 33 +++++++++++++--
- math/test-math-iszero.cc | 79 ++++++++++++++++++++++++++++++++++++
- sysdeps/powerpc/powerpc64le/Makefile | 3 +-
- 3 files changed, 110 insertions(+), 5 deletions(-)
-
-diff --git a/math/math.h b/math/math.h
-index 60dfa31..7c0fc6d 100644
---- a/math/math.h
-+++ b/math/math.h
-@@ -513,15 +513,40 @@ inline int issignaling (_Float128 __val) { return __issignalingf128 (__val); }
- # endif
- # else /* __cplusplus */
- extern "C++" {
-+# ifdef __SUPPORT_SNAN__
-+inline int
-+iszero (float __val)
-+{
-+ return __fpclassifyf (__val) == FP_ZERO;
-+}
-+inline int
-+iszero (double __val)
-+{
-+ return __fpclassify (__val) == FP_ZERO;
-+}
-+inline int
-+iszero (long double __val)
-+{
-+# ifdef __NO_LONG_DOUBLE_MATH
-+ return __fpclassify (__val) == FP_ZERO;
-+# else
-+ return __fpclassifyl (__val) == FP_ZERO;
-+# endif
-+}
-+# if __HAVE_DISTINCT_FLOAT128
-+inline int
-+iszero (_Float128 __val)
-+{
-+ return __fpclassifyf128 (__val) == FP_ZERO;
-+}
-+# endif
-+# else
- template <class __T> inline bool
- iszero (__T __val)
- {
--# ifdef __SUPPORT_SNAN__
-- return fpclassify (__val) == FP_ZERO;
--# else
- return __val == 0;
--# endif
- }
-+# endif
- } /* extern C++ */
- # endif /* __cplusplus */
- #endif /* Use IEC_60559_BFP_EXT. */
-diff --git a/math/test-math-iszero.cc b/math/test-math-iszero.cc
-index 027e972..5c07261 100644
---- a/math/test-math-iszero.cc
-+++ b/math/test-math-iszero.cc
-@@ -22,6 +22,13 @@
-
- #include <limits>
-
-+/* Support for _Float128 in std::numeric_limits is limited.
-+ Include ieee754_float128.h and use the bitfields in the union
-+ ieee854_float128.ieee_nan to build corner-case inputs. */
-+#if __HAVE_DISTINCT_FLOAT128
-+# include <ieee754_float128.h>
-+#endif
-+
- static bool errors;
-
- static void
-@@ -72,12 +79,84 @@ check_type ()
- std::numeric_limits<T>::has_denorm == std::denorm_absent);
- }
-
-+#if __HAVE_DISTINCT_FLOAT128
-+static void
-+check_float128 ()
-+{
-+ ieee854_float128 q;
-+
-+ q.d = 0.0Q;
-+ CHECK (iszero (q.d), 1);
-+ q.d = -0.0Q;
-+ CHECK (iszero (q.d), 1);
-+ q.d = 1.0Q;
-+ CHECK (iszero (q.d), 0);
-+ q.d = -1.0Q;
-+ CHECK (iszero (q.d), 0);
-+
-+ /* Normal min. */
-+ q.ieee.negative = 0;
-+ q.ieee.exponent = 0x0001;
-+ q.ieee.mantissa0 = 0x0000;
-+ q.ieee.mantissa1 = 0x00000000;
-+ q.ieee.mantissa2 = 0x00000000;
-+ q.ieee.mantissa3 = 0x00000000;
-+ CHECK (iszero (q.d), 0);
-+ q.ieee.negative = 1;
-+ CHECK (iszero (q.d), 0);
-+
-+ /* Normal max. */
-+ q.ieee.negative = 0;
-+ q.ieee.exponent = 0x7FFE;
-+ q.ieee.mantissa0 = 0xFFFF;
-+ q.ieee.mantissa1 = 0xFFFFFFFF;
-+ q.ieee.mantissa2 = 0xFFFFFFFF;
-+ q.ieee.mantissa3 = 0xFFFFFFFF;
-+ CHECK (iszero (q.d), 0);
-+ q.ieee.negative = 1;
-+ CHECK (iszero (q.d), 0);
-+
-+ /* Infinity. */
-+ q.ieee.negative = 0;
-+ q.ieee.exponent = 0x7FFF;
-+ q.ieee.mantissa0 = 0x0000;
-+ q.ieee.mantissa1 = 0x00000000;
-+ q.ieee.mantissa2 = 0x00000000;
-+ q.ieee.mantissa3 = 0x00000000;
-+ CHECK (iszero (q.d), 0);
-+
-+ /* Quiet NaN. */
-+ q.ieee_nan.quiet_nan = 1;
-+ q.ieee_nan.mantissa0 = 0x0000;
-+ CHECK (iszero (q.d), 0);
-+
-+ /* Signaling NaN. */
-+ q.ieee_nan.quiet_nan = 0;
-+ q.ieee_nan.mantissa0 = 0x4000;
-+ CHECK (iszero (q.d), 0);
-+
-+ /* Denormal min. */
-+ q.ieee.negative = 0;
-+ q.ieee.exponent = 0x0000;
-+ q.ieee.mantissa0 = 0x0000;
-+ q.ieee.mantissa1 = 0x00000000;
-+ q.ieee.mantissa2 = 0x00000000;
-+ q.ieee.mantissa3 = 0x00000001;
-+ CHECK (iszero (q.d), 0);
-+ q.ieee.negative = 1;
-+ CHECK (iszero (q.d), 0);
-+}
-+#endif
-+
- static int
- do_test (void)
- {
- check_type<float> ();
- check_type<double> ();
- check_type<long double> ();
-+#if __HAVE_DISTINCT_FLOAT128
-+ check_float128 ();
-+#endif
- return errors;
- }
-
-diff --git a/sysdeps/powerpc/powerpc64le/Makefile b/sysdeps/powerpc/powerpc64le/Makefile
-index 19adbfa..dea2290 100644
---- a/sysdeps/powerpc/powerpc64le/Makefile
-+++ b/sysdeps/powerpc/powerpc64le/Makefile
-@@ -17,7 +17,8 @@ $(foreach suf,$(all-object-suffixes),$(objpfx)test-float128%$(suf)): CFLAGS += -
- $(foreach suf,$(all-object-suffixes),$(objpfx)test-ifloat128%$(suf)): CFLAGS += -mfloat128
- CFLAGS-libm-test-support-float128.c += -mfloat128
- CFLAGS-test-math-issignaling.cc += -mfloat128
--$(objpfx)test-float128% $(objpfx)test-ifloat128%: \
-+CFLAGS-test-math-iszero.cc += -mfloat128
-+$(objpfx)test-float128% $(objpfx)test-ifloat128% $(objpfx)test-math-iszero: \
- gnulib-tests += $(f128-loader-link)
- endif
-
---
-2.9.5
-
diff --git a/toolchain/glibc/patches/2.26/0006-Let-fpclassify-use-the-builtin-when-optimizing-for-s.patch b/toolchain/glibc/patches/2.26/0006-Let-fpclassify-use-the-builtin-when-optimizing-for-s.patch
deleted file mode 100644
index 37807c459..000000000
--- a/toolchain/glibc/patches/2.26/0006-Let-fpclassify-use-the-builtin-when-optimizing-for-s.patch
+++ /dev/null
@@ -1,63 +0,0 @@
-From 33f54cf4f81a51e5c8cbfb2408edd439bdee9435 Mon Sep 17 00:00:00 2001
-From: "Gabriel F. T. Gomes" <gabriel@inconstante.eti.br>
-Date: Wed, 20 Sep 2017 15:10:26 -0300
-Subject: [PATCH] Let fpclassify use the builtin when optimizing for size in
- C++ mode (bug 22146)
-
-When optimization for size is on (-Os), fpclassify does not use the
-type-generic __builtin_fpclassify builtin, instead it uses __MATH_TG.
-However, when library support for float128 is available, __MATH_TG uses
-__builtin_types_compatible_p, which is not available in C++ mode.
-
-On the other hand, libstdc++ undefines (in cmath) many macros from
-math.h, including fpclassify, so that it can provide its own functions.
-However, during its configure tests, libstdc++ just tests for the
-availability of the macros (it does not undefine them, nor does it
-provide its own functions).
-
-Finally, when libstdc++ is configured with optimization for size
-enabled, its configure tests include math.h and get the definition of
-fpclassify that uses __MATH_TG (and __builtin_types_compatible_p).
-Since libstdc++ does not undefine the macros during its configure tests,
-they fail.
-
-This patch lets fpclassify use the builtin in C++ mode, even when
-optimization for size is on. This allows the configure test in
-libstdc++ to work.
-
-Tested for powerpc64le and x86_64.
-
- [BZ #22146]
- math/math.h: Let fpclassify use the builtin in C++ mode, even
- when optimazing for size.
-
-(cherry picked from commit c5c4a626098ec884b8527356abdf2a4bb7b6bf27)
-
-[Romain rebase on glibc 2.26)
-Signed-off-by: Romain Naour <romain.naour@gmail.com>
----
- math/math.h | 8 +++++++-
- 1 file changed, 7 insertions(+), 1 deletion(-)
-
-diff --git a/math/math.h b/math/math.h
-index 7c0fc6d..f9348ec 100644
---- a/math/math.h
-+++ b/math/math.h
-@@ -402,7 +402,13 @@ enum
-
- /* Return number of classification appropriate for X. */
- # if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__ \
-- && !defined __OPTIMIZE_SIZE__
-+ && (!defined __OPTIMIZE_SIZE__ || defined __cplusplus)
-+ /* The check for __cplusplus allows the use of the builtin, even
-+ when optimization for size is on. This is provided for
-+ libstdc++, only to let its configure test work when it is built
-+ with -Os. No further use of this definition of fpclassify is
-+ expected in C++ mode, since libstdc++ provides its own version
-+ of fpclassify in cmath (which undefines fpclassify). */
- # define fpclassify(x) __builtin_fpclassify (FP_NAN, FP_INFINITE, \
- FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x)
- # else
---
-2.9.5
-
diff --git a/toolchain/glibc/patches/2.38/0001-m68k-fix-__mpn_lshift-and-__mpn_rshift-for-non-68020.patch b/toolchain/glibc/patches/2.38/0001-m68k-fix-__mpn_lshift-and-__mpn_rshift-for-non-68020.patch
new file mode 100644
index 000000000..d5d8e34e9
--- /dev/null
+++ b/toolchain/glibc/patches/2.38/0001-m68k-fix-__mpn_lshift-and-__mpn_rshift-for-non-68020.patch
@@ -0,0 +1,46 @@
+From 464fd8249e8b791248cab7b0e0cd91757435fa9e Mon Sep 17 00:00:00 2001
+From: Andreas Schwab <schwab@linux-m68k.org>
+Date: Thu, 17 Aug 2023 17:15:34 +0200
+Subject: [PATCH] m68k: fix __mpn_lshift and __mpn_rshift for non-68020
+
+From revision 03f3d275d0d6 in the gmp repository.
+
+Signed-off-by: Waldemar Brodkorb <wbx@openadk.org>
+---
+ sysdeps/m68k/m680x0/lshift.S | 4 ++--
+ sysdeps/m68k/m680x0/rshift.S | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/sysdeps/m68k/m680x0/lshift.S b/sysdeps/m68k/m680x0/lshift.S
+index 2aee10348e..4240738959 100644
+--- a/sysdeps/m68k/m680x0/lshift.S
++++ b/sysdeps/m68k/m680x0/lshift.S
+@@ -77,8 +77,8 @@ L(Lnormal:)
+ #else /* not mc68000 */
+ movel R(s_size),R(d0)
+ asll #2,R(d0)
+- addl R(s_size),R(s_ptr)
+- addl R(s_size),R(res_ptr)
++ addl R(d0),R(s_ptr)
++ addl R(d0),R(res_ptr)
+ #endif
+ movel MEM_PREDEC(s_ptr),R(d2)
+ movel R(d2),R(d0)
+diff --git a/sysdeps/m68k/m680x0/rshift.S b/sysdeps/m68k/m680x0/rshift.S
+index d16bca9307..d56a2b4a44 100644
+--- a/sysdeps/m68k/m680x0/rshift.S
++++ b/sysdeps/m68k/m680x0/rshift.S
+@@ -127,8 +127,8 @@ L(Lspecial:)
+ #else /* not mc68000 */
+ movel R(s_size),R(d0)
+ asll #2,R(d0)
+- addl R(s_size),R(s_ptr)
+- addl R(s_size),R(res_ptr)
++ addl R(d0),R(s_ptr)
++ addl R(d0),R(res_ptr)
+ #endif
+
+ clrl R(d0) /* initialize carry */
+--
+2.39.2
+
diff --git a/toolchain/glibc/patches/2.38/0004-ARC-Add-support-for-ARCv3-processors.patch b/toolchain/glibc/patches/2.38/0004-ARC-Add-support-for-ARCv3-processors.patch
new file mode 100644
index 000000000..cf4ca7352
--- /dev/null
+++ b/toolchain/glibc/patches/2.38/0004-ARC-Add-support-for-ARCv3-processors.patch
@@ -0,0 +1,4036 @@
+From ac6163148698545dd56471edabf97ffc23a519da Mon Sep 17 00:00:00 2001
+From: Alexey Brodkin <abrodkin@synopsys.com>
+Date: Tue, 2 Jan 2024 03:38:32 -0800
+Subject: [PATCH] ARC: Add support for ARCv3 processors
+
+Signed-off-by: Vineet Gupta <vgupta@kernel.org>
+Signed-off-by: Pavel Kozlov <pavel.kozlov@synopsys.com>
+Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
+---
+ config.h.in | 6 +
+ elf/dl-runtime.c | 4 +-
+ elf/elf.h | 5 +-
+ nptl/Makefile | 5 +-
+ scripts/build-many-glibcs.py | 6 +
+ scripts/config.sub | 8 +
+ sysdeps/arc/Implies | 1 -
+ sysdeps/arc/__longjmp.S | 62 +-
+ sysdeps/arc/arc32/Implies | 1 +
+ sysdeps/arc/arc64/Implies | 1 +
+ sysdeps/arc/arc64/fpu/libm-test-ulps | 1141 +++++++++++++++++
+ sysdeps/arc/arc64/fpu/libm-test-ulps-name | 1 +
+ sysdeps/arc/{ => arc64}/nofpu/libm-test-ulps | 1 +
+ sysdeps/arc/arc64/nofpu/libm-test-ulps-name | 1 +
+ sysdeps/arc/atomic-machine.h | 41 +-
+ sysdeps/arc/bits/setjmp.h | 6 +-
+ sysdeps/arc/configure | 80 +-
+ sysdeps/arc/configure.ac | 36 +
+ sysdeps/arc/dl-machine.h | 75 +-
+ sysdeps/arc/dl-trampoline.S | 89 +-
+ sysdeps/arc/fpu/math-use-builtins-fma.h | 18 +-
+ sysdeps/arc/fpu/math-use-builtins-sqrt.h | 18 +-
+ sysdeps/arc/isa-asm-macro-32.h | 61 +
+ sysdeps/arc/isa-asm-macro-64.h | 86 ++
+ sysdeps/arc/isa-asm-macros.h | 35 +
+ sysdeps/arc/nofpu/libm-test-ulps | 1 +
+ sysdeps/arc/nptl/pthreaddef.h | 2 +-
+ sysdeps/arc/preconfigure | 18 +-
+ sysdeps/arc/setjmp.S | 55 +-
+ sysdeps/arc/sfp-machine.h | 55 +-
+ sysdeps/arc/start.S | 14 +-
+ sysdeps/arc/sysdep.h | 5 +-
+ sysdeps/unix/sysv/linux/arc/Makefile | 8 +-
+ sysdeps/unix/sysv/linux/arc/arc32/Implies | 1 +
+ .../sysv/linux/arc/{ => arc32}/arch-syscall.h | 0
+ .../sysv/linux/arc/{ => arc32}/c++-types.data | 0
+ .../linux/arc/{ => arc32}/fixup-asm-unistd.h | 0
+ .../sysv/linux/arc/{ => arc32}/ld.abilist | 0
+ .../arc/{ => arc32}/libBrokenLocale.abilist | 0
+ .../sysv/linux/arc/{ => arc32}/libanl.abilist | 0
+ .../sysv/linux/arc/{ => arc32}/libc.abilist | 0
+ .../arc/{ => arc32}/libc_malloc_debug.abilist | 0
+ .../linux/arc/{ => arc32}/libcrypt.abilist | 0
+ .../sysv/linux/arc/{ => arc32}/libdl.abilist | 0
+ .../sysv/linux/arc/{ => arc32}/libm.abilist | 0
+ .../linux/arc/{ => arc32}/libpthread.abilist | 0
+ .../linux/arc/{ => arc32}/libresolv.abilist | 0
+ .../sysv/linux/arc/{ => arc32}/librt.abilist | 0
+ .../arc/{ => arc32}/libthread_db.abilist | 0
+ .../linux/arc/{ => arc32}/libutil.abilist | 0
+ sysdeps/unix/sysv/linux/arc/arc64/Implies | 2 +
+ .../sysv/linux/arc/{ => arc64}/arch-syscall.h | 59 +-
+ .../sysv/linux/arc/{ => arc64}/c++-types.data | 48 +-
+ .../sysv/linux/arc/{ => arc64}/ld.abilist | 8 +-
+ .../arc/{ => arc64}/libBrokenLocale.abilist | 0
+ .../sysv/linux/arc/{ => arc64}/libanl.abilist | 0
+ .../sysv/linux/arc/{ => arc64}/libc.abilist | 82 +-
+ .../arc/{ => arc64}/libc_malloc_debug.abilist | 8 +-
+ .../linux/arc/{ => arc64}/libcrypt.abilist | 0
+ .../sysv/linux/arc/{ => arc64}/libdl.abilist | 0
+ .../sysv/linux/arc/{ => arc64}/libm.abilist | 0
+ .../linux/arc/{ => arc64}/libpthread.abilist | 0
+ .../linux/arc/{ => arc64}/libresolv.abilist | 4 +-
+ .../sysv/linux/arc/{ => arc64}/librt.abilist | 0
+ .../arc/{ => arc64}/libthread_db.abilist | 0
+ .../linux/arc/{ => arc64}/libutil.abilist | 0
+ sysdeps/unix/sysv/linux/arc/bits/fcntl.h | 62 +
+ .../sysv/linux/arc/bits/types/__sigset_t.h | 2 +-
+ sysdeps/unix/sysv/linux/arc/clone.S | 30 +-
+ sysdeps/unix/sysv/linux/arc/clone3.S | 14 +-
+ sysdeps/unix/sysv/linux/arc/getcontext.S | 71 +-
+ sysdeps/unix/sysv/linux/arc/setcontext.S | 88 +-
+ sysdeps/unix/sysv/linux/arc/shlib-versions | 8 +
+ sysdeps/unix/sysv/linux/arc/swapcontext.S | 129 +-
+ sysdeps/unix/sysv/linux/arc/sys/ucontext.h | 1 +
+ sysdeps/unix/sysv/linux/arc/syscall.S | 16 +-
+ sysdeps/unix/sysv/linux/arc/sysdep.h | 16 +-
+ sysdeps/unix/sysv/linux/arc/vfork.S | 4 +-
+ timezone/zic.c | 2 +-
+ 79 files changed, 2211 insertions(+), 390 deletions(-)
+ mode change 100755 => 100644 scripts/config.sub
+ create mode 100644 sysdeps/arc/arc32/Implies
+ create mode 100644 sysdeps/arc/arc64/Implies
+ create mode 100644 sysdeps/arc/arc64/fpu/libm-test-ulps
+ create mode 100644 sysdeps/arc/arc64/fpu/libm-test-ulps-name
+ copy sysdeps/arc/{ => arc64}/nofpu/libm-test-ulps (99%)
+ create mode 100644 sysdeps/arc/arc64/nofpu/libm-test-ulps-name
+ create mode 100644 sysdeps/arc/isa-asm-macro-32.h
+ create mode 100644 sysdeps/arc/isa-asm-macro-64.h
+ create mode 100644 sysdeps/arc/isa-asm-macros.h
+ create mode 100644 sysdeps/unix/sysv/linux/arc/arc32/Implies
+ copy sysdeps/unix/sysv/linux/arc/{ => arc32}/arch-syscall.h (100%)
+ copy sysdeps/unix/sysv/linux/arc/{ => arc32}/c++-types.data (100%)
+ rename sysdeps/unix/sysv/linux/arc/{ => arc32}/fixup-asm-unistd.h (100%)
+ copy sysdeps/unix/sysv/linux/arc/{ => arc32}/ld.abilist (100%)
+ copy sysdeps/unix/sysv/linux/arc/{ => arc32}/libBrokenLocale.abilist (100%)
+ copy sysdeps/unix/sysv/linux/arc/{ => arc32}/libanl.abilist (100%)
+ copy sysdeps/unix/sysv/linux/arc/{ => arc32}/libc.abilist (100%)
+ copy sysdeps/unix/sysv/linux/arc/{ => arc32}/libc_malloc_debug.abilist (100%)
+ copy sysdeps/unix/sysv/linux/arc/{ => arc32}/libcrypt.abilist (100%)
+ copy sysdeps/unix/sysv/linux/arc/{ => arc32}/libdl.abilist (100%)
+ copy sysdeps/unix/sysv/linux/arc/{ => arc32}/libm.abilist (100%)
+ copy sysdeps/unix/sysv/linux/arc/{ => arc32}/libpthread.abilist (100%)
+ copy sysdeps/unix/sysv/linux/arc/{ => arc32}/libresolv.abilist (100%)
+ copy sysdeps/unix/sysv/linux/arc/{ => arc32}/librt.abilist (100%)
+ copy sysdeps/unix/sysv/linux/arc/{ => arc32}/libthread_db.abilist (100%)
+ copy sysdeps/unix/sysv/linux/arc/{ => arc32}/libutil.abilist (100%)
+ create mode 100644 sysdeps/unix/sysv/linux/arc/arc64/Implies
+ rename sysdeps/unix/sysv/linux/arc/{ => arc64}/arch-syscall.h (89%)
+ rename sysdeps/unix/sysv/linux/arc/{ => arc64}/c++-types.data (73%)
+ rename sysdeps/unix/sysv/linux/arc/{ => arc64}/ld.abilist (54%)
+ rename sysdeps/unix/sysv/linux/arc/{ => arc64}/libBrokenLocale.abilist (100%)
+ rename sysdeps/unix/sysv/linux/arc/{ => arc64}/libanl.abilist (100%)
+ rename sysdeps/unix/sysv/linux/arc/{ => arc64}/libc.abilist (97%)
+ rename sysdeps/unix/sysv/linux/arc/{ => arc64}/libc_malloc_debug.abilist (80%)
+ rename sysdeps/unix/sysv/linux/arc/{ => arc64}/libcrypt.abilist (100%)
+ rename sysdeps/unix/sysv/linux/arc/{ => arc64}/libdl.abilist (100%)
+ rename sysdeps/unix/sysv/linux/arc/{ => arc64}/libm.abilist (100%)
+ rename sysdeps/unix/sysv/linux/arc/{ => arc64}/libpthread.abilist (100%)
+ rename sysdeps/unix/sysv/linux/arc/{ => arc64}/libresolv.abilist (95%)
+ rename sysdeps/unix/sysv/linux/arc/{ => arc64}/librt.abilist (100%)
+ rename sysdeps/unix/sysv/linux/arc/{ => arc64}/libthread_db.abilist (100%)
+ rename sysdeps/unix/sysv/linux/arc/{ => arc64}/libutil.abilist (100%)
+ create mode 100644 sysdeps/unix/sysv/linux/arc/bits/fcntl.h
+
+diff --git a/config.h.in b/config.h.in
+index 0dedc124f7..d69b4166c0 100644
+--- a/config.h.in
++++ b/config.h.in
+@@ -120,6 +120,12 @@
+ /* ARC big endian ABI */
+ #undef HAVE_ARC_BE
+
++/* ARC64:32 ABI */
++#undef HAVE_ARC32
++
++/* ARC64:64 ABI */
++#undef HAVE_ARC64
++
+ /* C-SKY ABI version. */
+ #undef CSKYABI
+
+diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
+index 32a8bfcf74..68ffdb1c24 100644
+--- a/elf/dl-runtime.c
++++ b/elf/dl-runtime.c
+@@ -42,7 +42,7 @@ _dl_fixup (
+ # ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
+ ELF_MACHINE_RUNTIME_FIXUP_ARGS,
+ # endif
+- struct link_map *l, ElfW(Word) reloc_arg)
++ struct link_map *l, uintptr_t reloc_arg)
+ {
+ const ElfW(Sym) *const symtab
+ = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
+@@ -170,7 +170,7 @@ _dl_profile_fixup (
+ #ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
+ ELF_MACHINE_RUNTIME_FIXUP_ARGS,
+ #endif
+- struct link_map *l, ElfW(Word) reloc_arg,
++ struct link_map *l, uintptr_t reloc_arg,
+ ElfW(Addr) retaddr, void *regs, long int *framesizep)
+ {
+ void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;
+diff --git a/elf/elf.h b/elf/elf.h
+index 89fc8021e9..05cc75c631 100644
+--- a/elf/elf.h
++++ b/elf/elf.h
+@@ -358,6 +358,8 @@ typedef struct
+
+ #define EM_BPF 247 /* Linux BPF -- in-kernel virtual machine */
+ #define EM_CSKY 252 /* C-SKY */
++#define EM_ARCV3 253 /* Synopsys ARCv3 64-bit ISA */
++#define EM_ARCV3_32 255 /* Synopsys ARCv3 32-bit ISA */
+ #define EM_LOONGARCH 258 /* LoongArch */
+
+ #define EM_NUM 259
+@@ -4216,12 +4218,13 @@ enum
+ /* Processor specific values for the Shdr sh_type field. */
+ #define SHT_ARC_ATTRIBUTES (SHT_LOPROC + 1) /* ARC attributes section. */
+
+-/* ARCompact/ARCv2 specific relocs. */
++/* ARCompact/ARCv2/ARCv3 specific relocs. */
+ #define R_ARC_NONE 0x0
+ #define R_ARC_8 0x1
+ #define R_ARC_16 0x2
+ #define R_ARC_24 0x3
+ #define R_ARC_32 0x4
++#define R_ARC_64 0x5
+
+ #define R_ARC_B22_PCREL 0x6
+ #define R_ARC_H30 0x7
+diff --git a/nptl/Makefile b/nptl/Makefile
+index ffa5722e48..c8b7674c27 100644
+--- a/nptl/Makefile
++++ b/nptl/Makefile
+@@ -353,6 +353,7 @@ tests = \
+ tst-thread-exit-clobber \
+ tst-thread-setspecific \
+ tst-thread_local1 \
++ tst-eintr1 \
+ tst-tsd3 \
+ tst-tsd4 \
+ # tests
+@@ -397,10 +398,6 @@ tests-time64 := \
+ tst-cancel4_2-time64
+ # tests-time64
+
+-# This test can run into task limits because of a linux kernel bug
+-# and then cause the make process to fail too, see bug 24537.
+-xtests += tst-eintr1
+-
+ test-srcs = tst-oddstacklimit
+
+ gen-as-const-headers = unwindbuf.sym
+diff --git a/scripts/build-many-glibcs.py b/scripts/build-many-glibcs.py
+index 73ffc57c86..6f53c195cd 100755
+--- a/scripts/build-many-glibcs.py
++++ b/scripts/build-many-glibcs.py
+@@ -172,6 +172,12 @@ class Context(object):
+ self.add_config(arch='arceb',
+ os_name='linux-gnu',
+ gcc_cfg=['--disable-multilib', '--with-cpu=hs38'])
++ self.add_config(arch='arc64',
++ os_name='linux-gnu',
++ gcc_cfg=['--disable-multilib'])
++ self.add_config(arch='arc64',
++ os_name='linux-gnuhf',
++ gcc_cfg=['--disable-multilib', '--with-fpu=fpud'])
+ self.add_config(arch='alpha',
+ os_name='linux-gnu')
+ self.add_config(arch='arm',
+diff --git a/scripts/config.sub b/scripts/config.sub
+old mode 100755
+new mode 100644
+index dba16e84c7..4d9a117c9c
+--- a/scripts/config.sub
++++ b/scripts/config.sub
+@@ -1170,6 +1170,14 @@ case $cpu-$vendor in
+ cpu=mipsallegrexel
+ vendor=sony
+ ;;
++ arc32*-*)
++ cpu=arc32
++ vendor=linux
++ ;;
++ arc64*-*)
++ cpu=arc64
++ vendor=linux
++ ;;
+ tile*-*)
+ basic_os=${basic_os:-linux-gnu}
+ ;;
+diff --git a/sysdeps/arc/Implies b/sysdeps/arc/Implies
+index 780c4e2467..12ca48b4c9 100644
+--- a/sysdeps/arc/Implies
++++ b/sysdeps/arc/Implies
+@@ -1,3 +1,2 @@
+-wordsize-32
+ ieee754/flt-32
+ ieee754/dbl-64
+diff --git a/sysdeps/arc/__longjmp.S b/sysdeps/arc/__longjmp.S
+index a57054bce0..920e535ffd 100644
+--- a/sysdeps/arc/__longjmp.S
++++ b/sysdeps/arc/__longjmp.S
+@@ -24,25 +24,49 @@
+
+ ENTRY (__longjmp)
+
+- LDR (blink, r0, 0)
+- LDR (sp, r0, 1)
+- LDR (fp, r0, 2)
+- LDR (gp, r0, 3)
+-
+- LDR (r13, r0, 4)
+- LDR (r14, r0, 5)
+- LDR (r15, r0, 6)
+- LDR (r16, r0, 7)
+- LDR (r17, r0, 8)
+- LDR (r18, r0, 9)
+- LDR (r19, r0, 10)
+- LDR (r20, r0, 11)
+- LDR (r21, r0, 12)
+- LDR (r22, r0, 13)
+- LDR (r23, r0, 14)
+- LDR (r24, r0, 15)
+-
+- mov.f r0, r1
++ LDR.as blink, r0, 0
++ LDR.as sp, r0, 1
++ LDR.as fp, r0, 2
++ LDR.as gp, r0, 3
++
++ LDR.as r13, r0, 4
++ LDR.as r14, r0, 5
++ LDR.as r15, r0, 6
++ LDR.as r16, r0, 7
++ LDR.as r17, r0, 8
++ LDR.as r18, r0, 9
++ LDR.as r19, r0, 10
++ LDR.as r20, r0, 11
++ LDR.as r21, r0, 12
++ LDR.as r22, r0, 13
++ LDR.as r23, r0, 14
++ LDR.as r24, r0, 15
++
++#if defined(__ARCV3__)
++ LDR.as r25, r0, 16
++ LDR.as r26, r0, 17
++#endif
++
++#if defined (__ARC_FLOAT_ABI_HARD__)
++ FLDR.as f16, r0, 18
++ FLDR.as f17, r0, 19
++ FLDR.as f18, r0, 20
++ FLDR.as f19, r0, 21
++ FLDR.as f20, r0, 22
++ FLDR.as f21, r0, 23
++ FLDR.as f22, r0, 24
++ FLDR.as f23, r0, 25
++ FLDR.as f24, r0, 26
++ FLDR.as f25, r0, 27
++ FLDR.as f26, r0, 28
++ FLDR.as f27, r0, 29
++ FLDR.as f28, r0, 30
++ FLDR.as f29, r0, 31
++ FLDR.as f30, r0, 32
++ FLDR.as f31, r0, 33
++#endif
++
++ MOVR.f r0, r1
+ j.d [blink]
+ mov.z r0, 1 /* don't return 0 to setjmp callsite from longjmp. */
+
+diff --git a/sysdeps/arc/arc32/Implies b/sysdeps/arc/arc32/Implies
+new file mode 100644
+index 0000000000..39a34c5f57
+--- /dev/null
++++ b/sysdeps/arc/arc32/Implies
+@@ -0,0 +1 @@
++wordsize-32
+diff --git a/sysdeps/arc/arc64/Implies b/sysdeps/arc/arc64/Implies
+new file mode 100644
+index 0000000000..a8cae95f9d
+--- /dev/null
++++ b/sysdeps/arc/arc64/Implies
+@@ -0,0 +1 @@
++wordsize-64
+diff --git a/sysdeps/arc/arc64/fpu/libm-test-ulps b/sysdeps/arc/arc64/fpu/libm-test-ulps
+new file mode 100644
+index 0000000000..f3b8753c4d
+--- /dev/null
++++ b/sysdeps/arc/arc64/fpu/libm-test-ulps
+@@ -0,0 +1,1141 @@
++# Begin of automatic generation
++
++# Maximal error of functions:
++Function: "acos":
++double: 1
++float: 1
++
++Function: "acos_downward":
++double: 1
++float: 1
++
++Function: "acos_towardzero":
++double: 1
++float: 1
++
++Function: "acos_upward":
++double: 1
++float: 1
++
++Function: "acosh":
++double: 2
++float: 2
++
++Function: "acosh_downward":
++double: 2
++float: 2
++
++Function: "acosh_towardzero":
++double: 2
++float: 2
++
++Function: "acosh_upward":
++double: 2
++float: 2
++
++Function: "asin":
++double: 1
++float: 1
++
++Function: "asin_downward":
++double: 1
++float: 1
++
++Function: "asin_towardzero":
++double: 1
++float: 1
++
++Function: "asin_upward":
++double: 2
++float: 1
++
++Function: "asinh":
++double: 2
++float: 2
++
++Function: "asinh_downward":
++double: 3
++float: 3
++
++Function: "asinh_towardzero":
++double: 2
++float: 2
++
++Function: "asinh_upward":
++double: 3
++float: 3
++
++Function: "atan":
++double: 1
++float: 1
++
++Function: "atan2":
++float: 1
++
++Function: "atan2_downward":
++double: 1
++float: 2
++
++Function: "atan2_towardzero":
++double: 1
++float: 2
++
++Function: "atan2_upward":
++double: 1
++float: 1
++
++Function: "atan_downward":
++double: 1
++float: 2
++
++Function: "atan_towardzero":
++double: 1
++float: 1
++
++Function: "atan_upward":
++double: 1
++float: 2
++
++Function: "atanh":
++double: 2
++float: 2
++
++Function: "atanh_downward":
++double: 3
++float: 3
++
++Function: "atanh_towardzero":
++double: 2
++float: 2
++
++Function: "atanh_upward":
++double: 3
++float: 3
++
++Function: "cabs":
++double: 1
++
++Function: "cabs_downward":
++double: 1
++
++Function: "cabs_towardzero":
++double: 1
++
++Function: "cabs_upward":
++double: 1
++float: 1
++
++Function: Real part of "cacos":
++double: 1
++float: 2
++
++Function: Imaginary part of "cacos":
++double: 2
++float: 2
++
++Function: Real part of "cacos_downward":
++double: 3
++float: 2
++
++Function: Imaginary part of "cacos_downward":
++double: 5
++float: 3
++
++Function: Real part of "cacos_towardzero":
++double: 3
++float: 2
++
++Function: Imaginary part of "cacos_towardzero":
++double: 4
++float: 2
++
++Function: Real part of "cacos_upward":
++double: 2
++float: 2
++
++Function: Imaginary part of "cacos_upward":
++double: 5
++float: 5
++
++Function: Real part of "cacosh":
++double: 2
++float: 2
++
++Function: Imaginary part of "cacosh":
++double: 1
++float: 2
++
++Function: Real part of "cacosh_downward":
++double: 4
++float: 2
++
++Function: Imaginary part of "cacosh_downward":
++double: 3
++float: 3
++
++Function: Real part of "cacosh_towardzero":
++double: 4
++float: 2
++
++Function: Imaginary part of "cacosh_towardzero":
++double: 3
++float: 2
++
++Function: Real part of "cacosh_upward":
++double: 4
++float: 3
++
++Function: Imaginary part of "cacosh_upward":
++double: 3
++float: 2
++
++Function: "carg":
++float: 1
++
++Function: "carg_downward":
++double: 1
++float: 2
++
++Function: "carg_towardzero":
++double: 1
++float: 2
++
++Function: "carg_upward":
++double: 1
++float: 1
++
++Function: Real part of "casin":
++double: 1
++float: 1
++
++Function: Imaginary part of "casin":
++double: 2
++float: 2
++
++Function: Real part of "casin_downward":
++double: 3
++float: 2
++
++Function: Imaginary part of "casin_downward":
++double: 5
++float: 3
++
++Function: Real part of "casin_towardzero":
++double: 3
++float: 1
++
++Function: Imaginary part of "casin_towardzero":
++double: 4
++float: 2
++
++Function: Real part of "casin_upward":
++double: 3
++float: 2
++
++Function: Imaginary part of "casin_upward":
++double: 5
++float: 5
++
++Function: Real part of "casinh":
++double: 2
++float: 2
++
++Function: Imaginary part of "casinh":
++double: 1
++float: 1
++
++Function: Real part of "casinh_downward":
++double: 5
++float: 3
++
++Function: Imaginary part of "casinh_downward":
++double: 3
++float: 2
++
++Function: Real part of "casinh_towardzero":
++double: 4
++float: 2
++
++Function: Imaginary part of "casinh_towardzero":
++double: 3
++float: 1
++
++Function: Real part of "casinh_upward":
++double: 5
++float: 5
++
++Function: Imaginary part of "casinh_upward":
++double: 3
++float: 2
++
++Function: Real part of "catan":
++double: 1
++float: 1
++
++Function: Imaginary part of "catan":
++double: 1
++float: 1
++
++Function: Real part of "catan_downward":
++double: 1
++float: 2
++
++Function: Imaginary part of "catan_downward":
++double: 2
++float: 2
++
++Function: Real part of "catan_towardzero":
++double: 1
++float: 2
++
++Function: Imaginary part of "catan_towardzero":
++double: 2
++float: 2
++
++Function: Real part of "catan_upward":
++double: 1
++float: 1
++
++Function: Imaginary part of "catan_upward":
++double: 2
++float: 2
++
++Function: Real part of "catanh":
++double: 1
++float: 1
++
++Function: Imaginary part of "catanh":
++double: 1
++float: 1
++
++Function: Real part of "catanh_downward":
++double: 2
++float: 2
++
++Function: Imaginary part of "catanh_downward":
++double: 1
++float: 2
++
++Function: Real part of "catanh_towardzero":
++double: 2
++float: 2
++
++Function: Imaginary part of "catanh_towardzero":
++double: 1
++float: 2
++
++Function: Real part of "catanh_upward":
++double: 4
++float: 4
++
++Function: Imaginary part of "catanh_upward":
++double: 1
++float: 1
++
++Function: "cbrt":
++double: 4
++float: 1
++
++Function: "cbrt_downward":
++double: 4
++float: 1
++
++Function: "cbrt_towardzero":
++double: 3
++float: 1
++
++Function: "cbrt_upward":
++double: 5
++float: 1
++
++Function: Real part of "ccos":
++double: 1
++float: 1
++
++Function: Imaginary part of "ccos":
++double: 1
++float: 1
++
++Function: Real part of "ccos_downward":
++double: 1
++float: 1
++
++Function: Imaginary part of "ccos_downward":
++double: 3
++float: 3
++
++Function: Real part of "ccos_towardzero":
++double: 1
++float: 2
++
++Function: Imaginary part of "ccos_towardzero":
++double: 3
++float: 3
++
++Function: Real part of "ccos_upward":
++double: 1
++float: 2
++
++Function: Imaginary part of "ccos_upward":
++double: 2
++float: 2
++
++Function: Real part of "ccosh":
++double: 1
++float: 1
++
++Function: Imaginary part of "ccosh":
++double: 1
++float: 1
++
++Function: Real part of "ccosh_downward":
++double: 2
++float: 2
++
++Function: Imaginary part of "ccosh_downward":
++double: 3
++float: 3
++
++Function: Real part of "ccosh_towardzero":
++double: 2
++float: 3
++
++Function: Imaginary part of "ccosh_towardzero":
++double: 3
++float: 3
++
++Function: Real part of "ccosh_upward":
++double: 1
++float: 2
++
++Function: Imaginary part of "ccosh_upward":
++double: 2
++float: 2
++
++Function: Real part of "cexp":
++double: 2
++float: 1
++
++Function: Imaginary part of "cexp":
++double: 1
++float: 2
++
++Function: Real part of "cexp_downward":
++double: 2
++float: 2
++
++Function: Imaginary part of "cexp_downward":
++double: 3
++float: 3
++
++Function: Real part of "cexp_towardzero":
++double: 2
++float: 2
++
++Function: Imaginary part of "cexp_towardzero":
++double: 3
++float: 3
++
++Function: Real part of "cexp_upward":
++double: 2
++float: 2
++
++Function: Imaginary part of "cexp_upward":
++double: 3
++float: 2
++
++Function: Real part of "clog":
++double: 3
++float: 3
++
++Function: Imaginary part of "clog":
++double: 1
++float: 1
++
++Function: Real part of "clog10":
++double: 3
++float: 4
++
++Function: Imaginary part of "clog10":
++double: 2
++float: 2
++
++Function: Real part of "clog10_downward":
++double: 5
++float: 5
++
++Function: Imaginary part of "clog10_downward":
++double: 2
++float: 4
++
++Function: Real part of "clog10_towardzero":
++double: 5
++float: 6
++
++Function: Imaginary part of "clog10_towardzero":
++double: 2
++float: 4
++
++Function: Real part of "clog10_upward":
++double: 6
++float: 5
++
++Function: Imaginary part of "clog10_upward":
++double: 2
++float: 4
++
++Function: Real part of "clog_downward":
++double: 4
++float: 3
++
++Function: Imaginary part of "clog_downward":
++double: 1
++float: 2
++
++Function: Real part of "clog_towardzero":
++double: 4
++float: 4
++
++Function: Imaginary part of "clog_towardzero":
++double: 1
++float: 3
++
++Function: Real part of "clog_upward":
++double: 4
++float: 3
++
++Function: Imaginary part of "clog_upward":
++double: 1
++float: 2
++
++Function: "cos":
++double: 1
++float: 1
++
++Function: "cos_downward":
++double: 1
++float: 1
++
++Function: "cos_towardzero":
++double: 1
++float: 1
++
++Function: "cos_upward":
++double: 1
++float: 1
++
++Function: "cosh":
++double: 2
++float: 2
++
++Function: "cosh_downward":
++double: 3
++float: 2
++
++Function: "cosh_towardzero":
++double: 3
++float: 2
++
++Function: "cosh_upward":
++double: 2
++float: 2
++
++Function: Real part of "cpow":
++double: 2
++float: 5
++
++Function: Imaginary part of "cpow":
++float: 2
++
++Function: Real part of "cpow_downward":
++double: 5
++float: 8
++
++Function: Imaginary part of "cpow_downward":
++double: 1
++float: 2
++
++Function: Real part of "cpow_towardzero":
++double: 5
++float: 8
++
++Function: Imaginary part of "cpow_towardzero":
++double: 1
++float: 2
++
++Function: Real part of "cpow_upward":
++double: 4
++float: 1
++
++Function: Imaginary part of "cpow_upward":
++double: 1
++float: 2
++
++Function: Real part of "csin":
++double: 1
++float: 1
++
++Function: Real part of "csin_downward":
++double: 3
++float: 3
++
++Function: Imaginary part of "csin_downward":
++double: 1
++float: 1
++
++Function: Real part of "csin_towardzero":
++double: 3
++float: 3
++
++Function: Imaginary part of "csin_towardzero":
++double: 1
++float: 1
++
++Function: Real part of "csin_upward":
++double: 2
++float: 2
++
++Function: Imaginary part of "csin_upward":
++double: 1
++float: 2
++
++Function: Real part of "csinh":
++float: 1
++
++Function: Imaginary part of "csinh":
++double: 1
++float: 1
++
++Function: Real part of "csinh_downward":
++double: 2
++float: 1
++
++Function: Imaginary part of "csinh_downward":
++double: 3
++float: 3
++
++Function: Real part of "csinh_towardzero":
++double: 2
++float: 2
++
++Function: Imaginary part of "csinh_towardzero":
++double: 3
++float: 3
++
++Function: Real part of "csinh_upward":
++double: 1
++float: 2
++
++Function: Imaginary part of "csinh_upward":
++double: 2
++float: 2
++
++Function: Real part of "csqrt":
++double: 2
++float: 2
++
++Function: Imaginary part of "csqrt":
++double: 2
++float: 2
++
++Function: Real part of "csqrt_downward":
++double: 5
++float: 4
++
++Function: Imaginary part of "csqrt_downward":
++double: 4
++float: 3
++
++Function: Real part of "csqrt_towardzero":
++double: 4
++float: 3
++
++Function: Imaginary part of "csqrt_towardzero":
++double: 4
++float: 3
++
++Function: Real part of "csqrt_upward":
++double: 5
++float: 4
++
++Function: Imaginary part of "csqrt_upward":
++double: 3
++float: 3
++
++Function: Real part of "ctan":
++double: 1
++float: 1
++
++Function: Imaginary part of "ctan":
++double: 2
++float: 2
++
++Function: Real part of "ctan_downward":
++double: 6
++float: 5
++
++Function: Imaginary part of "ctan_downward":
++double: 2
++float: 2
++
++Function: Real part of "ctan_towardzero":
++double: 5
++float: 2
++
++Function: Imaginary part of "ctan_towardzero":
++double: 2
++float: 2
++
++Function: Real part of "ctan_upward":
++double: 2
++float: 4
++
++Function: Imaginary part of "ctan_upward":
++double: 1
++float: 2
++
++Function: Real part of "ctanh":
++double: 2
++float: 2
++
++Function: Imaginary part of "ctanh":
++double: 2
++float: 2
++
++Function: Real part of "ctanh_downward":
++double: 2
++float: 2
++
++Function: Imaginary part of "ctanh_downward":
++double: 6
++float: 5
++
++Function: Real part of "ctanh_towardzero":
++double: 2
++float: 2
++
++Function: Imaginary part of "ctanh_towardzero":
++double: 5
++float: 2
++
++Function: Real part of "ctanh_upward":
++double: 1
++float: 2
++
++Function: Imaginary part of "ctanh_upward":
++double: 3
++float: 3
++
++Function: "erf":
++double: 1
++float: 1
++
++Function: "erf_downward":
++double: 1
++float: 1
++
++Function: "erf_towardzero":
++double: 1
++float: 1
++
++Function: "erf_upward":
++double: 1
++float: 1
++
++Function: "erfc":
++double: 3
++float: 3
++
++Function: "erfc_downward":
++double: 4
++float: 4
++
++Function: "erfc_towardzero":
++double: 3
++float: 3
++
++Function: "erfc_upward":
++double: 4
++float: 4
++
++Function: "exp":
++double: 1
++float: 1
++
++Function: "exp10":
++double: 2
++float: 1
++
++Function: "exp10_downward":
++double: 3
++float: 1
++
++Function: "exp10_towardzero":
++double: 3
++float: 1
++
++Function: "exp10_upward":
++double: 2
++float: 1
++
++Function: "exp2":
++double: 1
++
++Function: "exp2_downward":
++double: 1
++float: 1
++
++Function: "exp2_towardzero":
++double: 1
++float: 1
++
++Function: "exp2_upward":
++double: 1
++float: 1
++
++Function: "exp_downward":
++double: 1
++float: 1
++
++Function: "exp_towardzero":
++double: 1
++float: 1
++
++Function: "exp_upward":
++double: 1
++float: 1
++
++Function: "expm1":
++double: 1
++float: 1
++
++Function: "expm1_downward":
++double: 1
++float: 1
++
++Function: "expm1_towardzero":
++double: 1
++float: 2
++
++Function: "expm1_upward":
++double: 1
++float: 1
++
++Function: "gamma":
++double: 4
++float: 7
++
++Function: "gamma_downward":
++double: 4
++float: 4
++
++Function: "gamma_towardzero":
++double: 4
++float: 3
++
++Function: "gamma_upward":
++double: 4
++float: 5
++
++Function: "hypot":
++double: 1
++float: 1
++
++Function: "hypot_downward":
++double: 1
++float: 1
++
++Function: "hypot_towardzero":
++double: 1
++float: 1
++
++Function: "hypot_upward":
++double: 1
++float: 1
++
++Function: "j0":
++double: 4
++float: 9
++
++Function: "j0_downward":
++double: 6
++float: 8
++
++Function: "j0_towardzero":
++double: 4
++float: 9
++
++Function: "j0_upward":
++double: 4
++float: 9
++
++Function: "j1":
++double: 3
++float: 9
++
++Function: "j1_downward":
++double: 9
++float: 9
++
++Function: "j1_towardzero":
++double: 5
++float: 9
++
++Function: "j1_upward":
++double: 5
++float: 8
++
++Function: "jn":
++double: 4
++float: 4
++
++Function: "jn_downward":
++double: 4
++float: 5
++
++Function: "jn_towardzero":
++double: 4
++float: 5
++
++Function: "jn_upward":
++double: 5
++float: 5
++
++Function: "lgamma":
++double: 4
++float: 7
++
++Function: "lgamma_downward":
++double: 4
++float: 4
++
++Function: "lgamma_towardzero":
++double: 4
++float: 3
++
++Function: "lgamma_upward":
++double: 4
++float: 5
++
++Function: "log":
++double: 1
++
++Function: "log10":
++double: 2
++float: 2
++
++Function: "log10_downward":
++double: 2
++float: 3
++
++Function: "log10_towardzero":
++double: 2
++float: 2
++
++Function: "log10_upward":
++double: 2
++float: 2
++
++Function: "log1p":
++double: 1
++float: 1
++
++Function: "log1p_downward":
++double: 1
++float: 2
++
++Function: "log1p_towardzero":
++double: 2
++float: 2
++
++Function: "log1p_upward":
++double: 2
++float: 2
++
++Function: "log2":
++double: 2
++float: 1
++
++Function: "log2_downward":
++double: 1
++float: 1
++
++Function: "log2_towardzero":
++double: 1
++float: 1
++
++Function: "log2_upward":
++double: 1
++float: 1
++
++Function: "log_downward":
++double: 1
++float: 1
++
++Function: "log_towardzero":
++double: 1
++float: 1
++
++Function: "log_upward":
++double: 1
++float: 1
++
++Function: "pow":
++double: 1
++
++Function: "pow_downward":
++double: 1
++float: 1
++
++Function: "pow_towardzero":
++double: 1
++float: 1
++
++Function: "pow_upward":
++double: 1
++float: 1
++
++Function: "sin":
++double: 1
++float: 1
++
++Function: "sin_downward":
++double: 1
++float: 1
++
++Function: "sin_towardzero":
++double: 1
++float: 1
++
++Function: "sin_upward":
++double: 1
++float: 1
++
++Function: "sincos":
++double: 1
++float: 1
++
++Function: "sincos_downward":
++double: 1
++float: 1
++
++Function: "sincos_towardzero":
++double: 1
++float: 1
++
++Function: "sincos_upward":
++double: 1
++float: 1
++
++Function: "sinh":
++double: 2
++float: 2
++
++Function: "sinh_downward":
++double: 3
++float: 3
++
++Function: "sinh_towardzero":
++double: 3
++float: 2
++
++Function: "sinh_upward":
++double: 3
++float: 3
++
++Function: "tan":
++float: 1
++
++Function: "tan_downward":
++double: 1
++float: 2
++
++Function: "tan_towardzero":
++double: 1
++float: 1
++
++Function: "tan_upward":
++double: 1
++float: 1
++
++Function: "tanh":
++double: 2
++float: 2
++
++Function: "tanh_downward":
++double: 3
++float: 3
++
++Function: "tanh_towardzero":
++double: 2
++float: 2
++
++Function: "tanh_upward":
++double: 3
++float: 3
++
++Function: "tgamma":
++double: 9
++float: 8
++
++Function: "tgamma_downward":
++double: 9
++float: 7
++
++Function: "tgamma_towardzero":
++double: 9
++float: 7
++
++Function: "tgamma_upward":
++double: 8
++float: 8
++
++Function: "y0":
++double: 3
++float: 8
++
++Function: "y0_downward":
++double: 3
++float: 8
++
++Function: "y0_towardzero":
++double: 3
++float: 8
++
++Function: "y0_upward":
++double: 2
++float: 8
++
++Function: "y1":
++double: 3
++float: 9
++
++Function: "y1_downward":
++double: 6
++float: 8
++
++Function: "y1_towardzero":
++double: 3
++float: 9
++
++Function: "y1_upward":
++double: 6
++float: 9
++
++Function: "yn":
++double: 3
++float: 3
++
++Function: "yn_downward":
++double: 3
++float: 4
++
++Function: "yn_towardzero":
++double: 3
++float: 3
++
++Function: "yn_upward":
++double: 4
++float: 5
++
++# end of automatic generation
+diff --git a/sysdeps/arc/arc64/fpu/libm-test-ulps-name b/sysdeps/arc/arc64/fpu/libm-test-ulps-name
+new file mode 100644
+index 0000000000..8c4fba4f9a
+--- /dev/null
++++ b/sysdeps/arc/arc64/fpu/libm-test-ulps-name
+@@ -0,0 +1 @@
++ARC
+diff --git a/sysdeps/arc/nofpu/libm-test-ulps b/sysdeps/arc/arc64/nofpu/libm-test-ulps
+similarity index 99%
+copy from sysdeps/arc/nofpu/libm-test-ulps
+copy to sysdeps/arc/arc64/nofpu/libm-test-ulps
+index 6ac2830b25..26632ff8f2 100644
+--- a/sysdeps/arc/nofpu/libm-test-ulps
++++ b/sysdeps/arc/arc64/nofpu/libm-test-ulps
+@@ -205,6 +205,7 @@ float: 7
+
+ Function: "hypot":
+ double: 1
++float: 1
+
+ Function: "j0":
+ double: 2
+diff --git a/sysdeps/arc/arc64/nofpu/libm-test-ulps-name b/sysdeps/arc/arc64/nofpu/libm-test-ulps-name
+new file mode 100644
+index 0000000000..8a9879ebd6
+--- /dev/null
++++ b/sysdeps/arc/arc64/nofpu/libm-test-ulps-name
+@@ -0,0 +1 @@
++ARC soft-float
+diff --git a/sysdeps/arc/atomic-machine.h b/sysdeps/arc/atomic-machine.h
+index 6ac3d87dd9..f1565b317b 100644
+--- a/sysdeps/arc/atomic-machine.h
++++ b/sysdeps/arc/atomic-machine.h
+@@ -19,7 +19,23 @@
+ #ifndef _ARC_BITS_ATOMIC_H
+ #define _ARC_BITS_ATOMIC_H 1
+
+-#define __HAVE_64B_ATOMICS 0
++#include <stdint.h>
++
++typedef int32_t atomic32_t;
++typedef uint32_t uatomic32_t;
++typedef int64_t atomic64_t;
++typedef uint64_t uatomic64_t;
++
++typedef intptr_t atomicptr_t;
++typedef uintptr_t uatomicptr_t;
++typedef intmax_t atomic_max_t;
++typedef uintmax_t uatomic_max_t;
++
++# if defined(__ARC64_ARCH64__)
++# define __HAVE_64B_ATOMICS 1
++# else
++# define __HAVE_64B_ATOMICS 0
++# endif
+ #define USE_ATOMIC_COMPILER_BUILTINS 1
+
+ /* ARC does have legacy atomic EX reg, [mem] instruction but the micro-arch
+@@ -30,15 +46,16 @@
+ (abort (), 0)
+ #define __arch_compare_and_exchange_bool_16_acq(mem, newval, oldval) \
+ (abort (), 0)
+-#define __arch_compare_and_exchange_bool_64_acq(mem, newval, oldval) \
+- (abort (), 0)
++
++# if !defined(__ARC64__)
++# define __arch_compare_and_exchange_bool_64_acq(mem, newval, oldval) \
++ (abort (), 0)
++#endif
+
+ #define __arch_compare_and_exchange_val_8_int(mem, newval, oldval, model) \
+ (abort (), (__typeof (*mem)) 0)
+ #define __arch_compare_and_exchange_val_16_int(mem, newval, oldval, model) \
+ (abort (), (__typeof (*mem)) 0)
+-#define __arch_compare_and_exchange_val_64_int(mem, newval, oldval, model) \
+- (abort (), (__typeof (*mem)) 0)
+
+ #define __arch_compare_and_exchange_val_32_int(mem, newval, oldval, model) \
+ ({ \
+@@ -48,6 +65,20 @@
+ __oldval; \
+ })
+
++# if defined(__ARC64__)
++# define __arch_compare_and_exchange_val_64_int(mem, newval, oldval, model) \
++ ({ \
++ typeof (*mem) __oldval = (oldval); \
++ __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \
++ model, __ATOMIC_RELAXED); \
++ __oldval; \
++ })
++# else
++/* ARCv2 has LOCKD/SCOND but not sure if gcc atomic builtins exist. */
++# define __arch_compare_and_exchange_val_64_int(mem, newval, oldval, model) \
++ (abort (), (__typeof (*mem)) 0)
++#endif
++
+ #define atomic_compare_and_exchange_val_acq(mem, new, old) \
+ __atomic_val_bysize (__arch_compare_and_exchange_val, int, \
+ mem, new, old, __ATOMIC_ACQUIRE)
+diff --git a/sysdeps/arc/bits/setjmp.h b/sysdeps/arc/bits/setjmp.h
+index d1604cde1f..2ca85a679d 100644
+--- a/sysdeps/arc/bits/setjmp.h
++++ b/sysdeps/arc/bits/setjmp.h
+@@ -20,7 +20,11 @@
+ #define _ARC_BITS_SETJMP_H 1
+
+ /* Saves r13-r25 (callee-saved), fp (frame pointer), sp (stack pointer),
+- blink (branch-n-link). */
++ blink (branch-n-link), FP regs. */
++#if defined (__ARC_FLOAT_ABI_HARD__)
++typedef long int __jmp_buf[64];
++#else
+ typedef long int __jmp_buf[32];
++#endif
+
+ #endif
+diff --git a/sysdeps/arc/configure b/sysdeps/arc/configure
+index 7b27e26490..d7b19db793 100644
+--- a/sysdeps/arc/configure
++++ b/sysdeps/arc/configure
+@@ -10,7 +10,7 @@ libc_cv_asm_line_sep='`'
+ printf "%s\n" "#define ASM_LINE_SEP $libc_cv_asm_line_sep" >>confdefs.h
+
+
+-# For big endian ABI, generate a symbol for selecting right dynamic linker
++# For arc64:64 generate a symbol for selecting right dynamic linker
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+@@ -155,6 +155,77 @@ printf "%s\n" "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for arc64" >&5
++printf %s "checking for arc64... " >&6; }
++if test ${libc_cv_arc64+y}
++then :
++ printf %s "(cached) " >&6
++else $as_nop
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#ifdef __ARC64_ARCH64__
++ yes
++ #endif
++
++_ACEOF
++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
++ $EGREP "yes" >/dev/null 2>&1
++then :
++ libc_cv_arc64=yes
++else $as_nop
++ libc_cv_arc64=no
++fi
++rm -rf conftest*
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_arc64" >&5
++printf "%s\n" "$libc_cv_arc64" >&6; }
++if test $libc_cv_arc64 = yes; then
++ # For shlib-versions.
++ printf "%s\n" "#define HAVE_ARC64 1" >>confdefs.h
++
++ config_vars="$config_vars
++default-abi = arc64le"
++
++else
++
++# For arc64:32 generate a symbol for selecting right dynamic linker
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for arc32" >&5
++printf %s "checking for arc32... " >&6; }
++if test ${libc_cv_arc32+y}
++then :
++ printf %s "(cached) " >&6
++else $as_nop
++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++#ifdef __ARC64_ARCH32__
++ yes
++ #endif
++
++_ACEOF
++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
++ $EGREP "yes" >/dev/null 2>&1
++then :
++ libc_cv_arc32=yes
++else $as_nop
++ libc_cv_arc32=no
++fi
++rm -rf conftest*
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_arc32" >&5
++printf "%s\n" "$libc_cv_arc32" >&6; }
++
++if test $libc_cv_arc32 = yes; then
++ # For shlib-versions.
++ printf "%s\n" "#define HAVE_ARC32 1" >>confdefs.h
++
++ config_vars="$config_vars
++default-abi = arc32le"
++
++else
++
++# For big endian ABI, generate a symbol for selecting right dynamic linker
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for big endian" >&5
+ printf %s "checking for big endian... " >&6; }
+ if test ${libc_cv_arc_be+y}
+@@ -189,5 +260,12 @@ default-abi = arcbe"
+ else
+ config_vars="$config_vars
+ default-abi = arcle"
++# big endian
++fi
++
++# arc64:32
++fi
++
++# arc64:64
+ fi
+
+diff --git a/sysdeps/arc/configure.ac b/sysdeps/arc/configure.ac
+index 619da4e088..4e84f17105 100644
+--- a/sysdeps/arc/configure.ac
++++ b/sysdeps/arc/configure.ac
+@@ -9,6 +9,35 @@ libc_cv_have_sdata_section=no
+ libc_cv_asm_line_sep='`'
+ AC_DEFINE_UNQUOTED(ASM_LINE_SEP, $libc_cv_asm_line_sep)
+
++# For arc64:64 generate a symbol for selecting right dynamic linker
++AC_CACHE_CHECK([for arc64],
++ [libc_cv_arc64],
++ [AC_EGREP_CPP(yes,[#ifdef __ARC64_ARCH64__
++ yes
++ #endif
++ ], libc_cv_arc64=yes, libc_cv_arc64=no)])
++if test $libc_cv_arc64 = yes; then
++ # For shlib-versions.
++ AC_DEFINE(HAVE_ARC64)
++ LIBC_CONFIG_VAR([default-abi], [arc64le])
++
++else
++
++# For arc64:32 generate a symbol for selecting right dynamic linker
++AC_CACHE_CHECK([for arc32],
++ [libc_cv_arc32],
++ [AC_EGREP_CPP(yes,[#ifdef __ARC64_ARCH32__
++ yes
++ #endif
++ ], libc_cv_arc32=yes, libc_cv_arc32=no)])
++
++if test $libc_cv_arc32 = yes; then
++ # For shlib-versions.
++ AC_DEFINE(HAVE_ARC32)
++ LIBC_CONFIG_VAR([default-abi], [arc32le])
++
++else
++
+ # For big endian ABI, generate a symbol for selecting right dynamic linker
+ AC_CACHE_CHECK([for big endian],
+ [libc_cv_arc_be],
+@@ -22,4 +51,11 @@ if test $libc_cv_arc_be = yes; then
+ LIBC_CONFIG_VAR([default-abi], [arcbe])
+ else
+ LIBC_CONFIG_VAR([default-abi], [arcle])
++# big endian
++fi
++
++# arc64:32
++fi
++
++# arc64:64
+ fi
+diff --git a/sysdeps/arc/dl-machine.h b/sysdeps/arc/dl-machine.h
+index 4dc652a449..dbb7394c27 100644
+--- a/sysdeps/arc/dl-machine.h
++++ b/sysdeps/arc/dl-machine.h
+@@ -32,18 +32,19 @@
+ #include <dl-tls.h>
+ #include <dl-static-tls.h>
+ #include <dl-machine-rel.h>
++#include <sysdep.h>
+
+ /* Dynamic Linking ABI for ARCv2 ISA.
+
+- PLT
++ .plt
+ -------------------------------- <---- DT_PLTGOT
+ | ld r11, [pcl, off-to-GOT[1] | 0
+ | | 4
+- plt0 | ld r10, [pcl, off-to-GOT[2] | 8
++ PLT0 | ld r10, [pcl, off-to-GOT[2] | 8
+ | | 12
+ | j [r10] | 16
+ --------------------------------
+- | Base address of GOT | 20
++ | Base address of .got.plt | 20
+ --------------------------------
+ | ld r12, [pcl, off-to-GOT[3] | 24
+ plt1 | |
+@@ -69,11 +70,11 @@
+ --------------
+ | [1] | Module info - setup by ld.so
+ --------------
+- | [2] | resolver entry point
++ | [2] | resolver entry point: _dl_runtime_resolve
+ --------------
+ | [3] |
+ | ... | Runtime address for function symbols
+- | [f] |
++ | [f] | Initially point to PLT0
+ --------------
+
+ For ARCompact, the PLT is 12 bytes due to short instructions
+@@ -91,6 +92,8 @@ static inline int
+ elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
+ {
+ return (ehdr->e_machine == EM_ARCV2 /* ARC HS. */
++ || ehdr->e_machine == EM_ARCV3 /* ARCv3: ARC64. */
++ || ehdr->e_machine == EM_ARCV3_32 /* ARCv3: ARC32. */
+ || ehdr->e_machine == EM_ARC_COMPACT); /* ARC 700. */
+ }
+
+@@ -114,7 +117,7 @@ elf_machine_load_address (void)
+ /* For build address, below generates
+ ld r0, [pcl, _GLOBAL_OFFSET_TABLE_@pcl]. */
+ build_addr = elf_machine_dynamic ();
+- __asm__ ("add %0, pcl, _DYNAMIC@pcl \n" : "=r" (run_addr));
++ __asm__ ("ADDR %0, pcl, _DYNAMIC@pcl \n" : "=r" (run_addr));
+
+ return run_addr - build_addr;
+ }
+@@ -131,10 +134,13 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
+
+ if (l->l_info[DT_JMPREL] && lazy)
+ {
+- /* On ARC DT_PLTGOT point to .plt whose 5th word (after the PLT header)
+- contains the address of .got. */
++ /* update .got.plt[1] and .got.plt[2].
++ DT_PLTGOT point to base of .plt and PLT0 is 3 instructions
++ for total of 20 bytes, see illustration at top.
++ The word right after contains base address of .got.plt. */
+ ElfW(Addr) *plt_base = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]);
+- ElfW(Addr) *got = (ElfW(Addr) *) (plt_base[5] + l->l_addr);
++ ElfW(Addr) *got_build = (ElfW(Addr) *) ((uintptr_t)plt_base + 20);
++ ElfW(Addr) *got = (ElfW(Addr) *) (*got_build + l->l_addr);
+
+ got[1] = (ElfW(Addr)) l; /* Identify this shared object. */
+
+@@ -152,6 +158,8 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
+ -optionally adjusts argc for executable if exec passed as cmd
+ -calls into app main with address of finaliser. */
+
++#ifdef __ARC64_ARCH64__
++
+ #define RTLD_START asm ("\
+ .text \n\
+ .globl __start \n\
+@@ -159,25 +167,55 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
+ __start: \n\
+ /* (1). bootstrap ld.so. */ \n\
+ bl.d _dl_start \n\
+- mov_s r0, sp /* pass ptr to aux vector tbl. */ \n\
+- mov r13, r0 /* safekeep app elf entry point. */ \n\
+- ld_s r1, [sp] /* orig argc. */ \n\
++ MOVR r0, sp /* pass ptr to aux vector tbl. */ \n\
++ MOVR r14, r0 /* safekeep app elf entry point. */ \n\
++ LDR r1, sp /* orig argc. */ \n\
+ \n\
+ /* (2). call preinit stuff. */ \n\
+- ld r0, [pcl, _rtld_local@pcl] \n\
+- add r2, sp, 4 ; argv \n\
+- add2 r3, r2, r1 \n\
+- add r3, r3, 4 ; env \n\
++ LDR r0, pcl, _rtld_local@pcl \n\
++ ADDR r2, sp, 8 ; argv \n\
++ ADD3R r3, r2, r1 \n\
++ ADDR r3, r3, 8 ; env \n\
+ bl _dl_init@plt \n\
+ \n\
+ /* (3) call app elf entry point. */ \n\
+- add r0, pcl, _dl_fini@pcl \n\
+- j [r13] \n\
++ ADDR r0, pcl, _dl_fini@pcl \n\
++ j [r14] \n\
+ \n\
+ .size __start,.-__start \n\
+ .previous \n\
+ ");
+
++#else
++
++#define RTLD_START asm ("\
++.text \n\
++.globl __start \n\
++.type __start, @function \n\
++__start: \n\
++ /* (1). bootstrap ld.so. */ \n\
++ bl.d _dl_start \n\
++ MOVR r0, sp /* pass ptr to aux vector tbl. */ \n\
++ MOVR r14, r0 /* safekeep app elf entry point. */ \n\
++ LDR r1, sp /* orig argc. */ \n\
++ \n\
++ /* (2). call preinit stuff. */ \n\
++ LDR r0, pcl, _rtld_local@pcl \n\
++ ADDR r2, sp, 4 ; argv \n\
++ ADD2R r3, r2, r1 \n\
++ ADDR r3, r3, 4 ; env \n\
++ bl _dl_init@plt \n\
++ \n\
++ /* (3) call app elf entry point. */ \n\
++ ADDR r0, pcl, _dl_fini@pcl \n\
++ j [r14] \n\
++ \n\
++ .size __start,.-__start \n\
++ .previous \n\
++");
++
++#endif
++
+ /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+ PLT entries should not be allowed to define the value.
+ ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+@@ -289,6 +327,7 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
+ break;
+
+ case R_ARC_32:
++ case R_ARC_64:
+ *reloc_addr += value + reloc->r_addend;
+ break;
+
+diff --git a/sysdeps/arc/dl-trampoline.S b/sysdeps/arc/dl-trampoline.S
+index 1b307a616f..386009d41e 100644
+--- a/sysdeps/arc/dl-trampoline.S
++++ b/sysdeps/arc/dl-trampoline.S
+@@ -31,42 +31,71 @@
+ ENTRY (_dl_runtime_resolve)
+
+ /* save args to func being resolved before entering resolver. */
+- push_s r0
+- push_s r1
+- push_s r2
+- push_s r3
+- st.a r4, [sp, -4]
+- st.a r5, [sp, -4]
+- st.a r6, [sp, -4]
+- st.a r7, [sp, -4]
+- st.a r8, [sp, -4]
+- st.a r9, [sp, -4]
+- cfi_adjust_cfa_offset (40)
+- push_s blink
+- cfi_adjust_cfa_offset (4)
++ PUSHR r0
++ PUSHR r1
++ PUSHR r2
++ PUSHR r3
++ PUSHR r4
++ PUSHR r5
++ PUSHR r6
++ PUSHR r7
++ PUSHR r8
++ PUSHR r9
++
++#if defined (__ARC_FLOAT_ABI_HARD__)
++ FPUSHR f0
++ FPUSHR f1
++ FPUSHR f2
++ FPUSHR f3
++ FPUSHR f4
++ FPUSHR f5
++ FPUSHR f6
++ FPUSHR f7
++ cfi_adjust_cfa_offset (18*REGSZ)
++#else
++ cfi_adjust_cfa_offset (10*REGSZ)
++#endif
++
++ PUSHR blink
++ cfi_adjust_cfa_offset (REGSZ)
+ cfi_rel_offset (blink, 0)
+
+- mov_s r1, r12
++ MOVR r1, r12
+ bl.d _dl_fixup
+- mov r0, r11
++ MOVR r0, r11
+
+ /* restore regs back. */
+- ld.ab blink,[sp, 4]
+- cfi_adjust_cfa_offset (-4)
++ POPR blink
++ cfi_adjust_cfa_offset (-REGSZ)
+ cfi_restore (blink)
+- ld.ab r9, [sp, 4]
+- ld.ab r8, [sp, 4]
+- ld.ab r7, [sp, 4]
+- ld.ab r6, [sp, 4]
+- ld.ab r5, [sp, 4]
+- ld.ab r4, [sp, 4]
+- pop_s r3
+- pop_s r2
+- pop_s r1
+- cfi_adjust_cfa_offset (-36)
+
+- j_s.d [r0] /* r0 has resolved function addr. */
+- pop_s r0 /* restore first arg to resolved call. */
+- cfi_adjust_cfa_offset (-4)
++#if defined (__ARC_FLOAT_ABI_HARD__)
++ FPOPR f7
++ FPOPR f6
++ FPOPR f5
++ FPOPR f4
++ FPOPR f3
++ FPOPR f2
++ FPOPR f1
++ FPOPR f0
++#endif
++ POPR r9
++ POPR r8
++ POPR r7
++ POPR r6
++ POPR r5
++ POPR r4
++ POPR r3
++ POPR r2
++ POPR r1
++#if defined (__ARC_FLOAT_ABI_HARD__)
++ cfi_adjust_cfa_offset (-17*REGSZ)
++#else
++ cfi_adjust_cfa_offset (-9*REGSZ)
++#endif
++
++ j.d [r0] /* r0 has resolved function addr. */
++ POPR r0 /* restore first arg to resolved call. */
++ cfi_adjust_cfa_offset (-REGSZ)
+ cfi_restore (r0)
+ END (_dl_runtime_resolve)
+diff --git a/sysdeps/arc/fpu/math-use-builtins-fma.h b/sysdeps/arc/fpu/math-use-builtins-fma.h
+index 2acd8113ce..59c7ed0343 100644
+--- a/sysdeps/arc/fpu/math-use-builtins-fma.h
++++ b/sysdeps/arc/fpu/math-use-builtins-fma.h
+@@ -1,13 +1,17 @@
+-#if defined __ARC_FPU_DP_FMA__
++#if defined __ARCV3__
+ # define USE_FMA_BUILTIN 1
+-#else
+-# define USE_FMA_BUILTIN 0
+-#endif
+-
+-#if defined __ARC_FPU_SP_FMA__
+ # define USE_FMAF_BUILTIN 1
+ #else
+-# define USE_FMAF_BUILTIN 0
++# if defined __ARC_FPU_DP_FMA__
++# define USE_FMA_BUILTIN 1
++# else
++# define USE_FMA_BUILTIN 0
++# endif
++# if defined __ARC_FPU_SP_FMA__
++# define USE_FMAF_BUILTIN 1
++# else
++# define USE_FMAF_BUILTIN 0
++# endif
+ #endif
+
+ #define USE_FMAL_BUILTIN 0
+diff --git a/sysdeps/arc/fpu/math-use-builtins-sqrt.h b/sysdeps/arc/fpu/math-use-builtins-sqrt.h
+index a449bc6092..40a07730ea 100644
+--- a/sysdeps/arc/fpu/math-use-builtins-sqrt.h
++++ b/sysdeps/arc/fpu/math-use-builtins-sqrt.h
+@@ -1,13 +1,17 @@
+-#if defined __ARC_FPU_DP_DIV__
++#if defined __ARCV3__
+ # define USE_SQRT_BUILTIN 1
+-#else
+-# define USE_SQRT_BUILTIN 0
+-#endif
+-
+-#if defined __ARC_FPU_SP_DIV__
+ # define USE_SQRTF_BUILTIN 1
+ #else
+-# define USE_SQRTF_BUILTIN 0
++# if defined __ARC_FPU_DP_DIV__
++# define USE_SQRT_BUILTIN 1
++# else
++# define USE_SQRT_BUILTIN 0
++# endif
++# if defined __ARC_FPU_SP_DIV__
++# define USE_SQRTF_BUILTIN 1
++# else
++# define USE_SQRTF_BUILTIN 0
++# endif
+ #endif
+
+ #define USE_SQRTL_BUILTIN 0
+diff --git a/sysdeps/arc/isa-asm-macro-32.h b/sysdeps/arc/isa-asm-macro-32.h
+new file mode 100644
+index 0000000000..98cd249059
+--- /dev/null
++++ b/sysdeps/arc/isa-asm-macro-32.h
+@@ -0,0 +1,61 @@
++# define REGSZ 4
++
++.irp aa,,.as
++.macro LDR\aa d, s, off=0
++ ld\aa \d, [\s, \off]
++.endm
++.endr
++
++.irp aa,,.as
++.macro STR\aa d, s, off=0
++ st\aa \d, [\s, \off]
++.endm
++.endr
++
++.macro PUSHR r
++ push \r
++.endm
++
++.macro POPR r
++ pop \r
++.endm
++
++.irp cc,,.f
++.macro MOVR\cc d, s
++ mov\cc \d, \s
++.endm
++.endr
++
++.irp cc,,.nz
++.macro ADDR\cc d, s, v
++ add\cc \d, \s, \v
++.endm
++.endr
++
++.macro ADD2R d, s, v
++ add2 \d, \s, \v
++.endm
++
++.macro ADD3R d, s, v
++ add3 \d, \s, \v
++.endm
++
++.macro SUBR d, s, v
++ sub \d, \s, \v
++.endm
++
++.macro ANDR d, s, v
++ and \d, \s, \v
++.endm
++
++.irp cc,,eq,hi
++.macro BRR\cc d, s, v
++ br\cc \d, \s, \v
++.endm
++.endr
++
++.irp cc,,.ne
++.macro CMPR\cc d, s
++ cmp\cc \d, \s
++.endm
++.endr
+diff --git a/sysdeps/arc/isa-asm-macro-64.h b/sysdeps/arc/isa-asm-macro-64.h
+new file mode 100644
+index 0000000000..02b1dc2c37
+--- /dev/null
++++ b/sysdeps/arc/isa-asm-macro-64.h
+@@ -0,0 +1,86 @@
++# define REGSZ 8
++
++.irp aa,,.as
++.macro LDR\aa d, s, off=0
++ ldl\aa \d, [\s, \off]
++.endm
++.endr
++
++.irp aa,,.as
++.macro STR\aa d, s, off=0
++ stl\aa \d, [\s, \off]
++.endm
++.endr
++
++.macro PUSHR r
++ pushl \r
++.endm
++
++.macro POPR r
++ popl \r
++.endm
++
++.irp cc,,.f
++.macro MOVR\cc d, s
++ movl\cc \d, \s
++.endm
++.endr
++
++.irp cc,,.nz
++.macro ADDR\cc d, s, v
++ addl\cc \d, \s, \v
++.endm
++.endr
++
++.macro ADD2R d, s, v
++ add2l \d, \s, \v
++.endm
++
++.macro ADD3R d, s, v
++ add3l \d, \s, \v
++.endm
++
++.macro SUBR d, s, v
++ subl \d, \s, \v
++.endm
++
++.macro ANDR d, s, v
++ andl \d, \s, \v
++.endm
++
++.irp cc,eq,hi
++.macro BRR\cc d, s, v
++; arc64 gas doesn't support BRHIL pseudo-instruction
++.ifeqs "\cc","hi"
++ brlo\()l \s, \d, \v
++.else
++ br\cc\()l \d, \s, \v
++.endif
++.endm
++.endr
++
++.irp cc,,.ne
++.macro CMPR\cc d, s
++ cmpl\cc \d, \s
++.endm
++.endr
++
++.irp aa,,.as,.aw,.ab
++.macro FLDR\aa d, s, off=0
++ fld64\aa \d, [\s, \off]
++.endm
++.endr
++
++.irp aa,,.as,.aw,.ab
++.macro FSTR\aa d, s, off=0
++ fst64\aa \d, [\s, \off]
++.endm
++.endr
++
++.macro FPUSHR r
++ FSTR.aw \r, sp, -REGSZ
++.endm
++
++.macro FPOPR r
++ FLDR.ab \r, sp, REGSZ
++.endm
+diff --git a/sysdeps/arc/isa-asm-macros.h b/sysdeps/arc/isa-asm-macros.h
+new file mode 100644
+index 0000000000..f9f5e4f630
+--- /dev/null
++++ b/sysdeps/arc/isa-asm-macros.h
+@@ -0,0 +1,35 @@
++/* ISA Specific Assembler macros for ARC.
++ Copyright (C) 2020 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public License as
++ published by the Free Software Foundation; either version 2.1 of the
++ License, or (at your option) any later version.
++
++ 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
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifdef __ASSEMBLER__
++
++# ifdef __ARC64_ARCH64__
++# include <sysdeps/arc/isa-asm-macro-64.h>
++# else
++# include <sysdeps/arc/isa-asm-macro-32.h>
++# endif
++
++#else
++
++# ifdef __ARC64_ARCH64__
++asm(".include \"sysdeps/arc/isa-asm-macro-64.h\"\n");
++# else
++asm(".include \"sysdeps/arc/isa-asm-macro-32.h\"\n");
++# endif
++
++#endif
+diff --git a/sysdeps/arc/nofpu/libm-test-ulps b/sysdeps/arc/nofpu/libm-test-ulps
+index 6ac2830b25..26632ff8f2 100644
+--- a/sysdeps/arc/nofpu/libm-test-ulps
++++ b/sysdeps/arc/nofpu/libm-test-ulps
+@@ -205,6 +205,7 @@ float: 7
+
+ Function: "hypot":
+ double: 1
++float: 1
+
+ Function: "j0":
+ double: 2
+diff --git a/sysdeps/arc/nptl/pthreaddef.h b/sysdeps/arc/nptl/pthreaddef.h
+index 336eded15c..3b51e59a35 100644
+--- a/sysdeps/arc/nptl/pthreaddef.h
++++ b/sysdeps/arc/nptl/pthreaddef.h
+@@ -23,7 +23,7 @@
+ #define ARCH_MIN_GUARD_SIZE 0
+
+ /* Required stack pointer alignment at beginning. */
+-#define STACK_ALIGN 4
++#define STACK_ALIGN 8
+
+ /* Minimal stack size after allocating thread descriptor and guard size. */
+ #define MINIMAL_REST_STACK 2048
+diff --git a/sysdeps/arc/preconfigure b/sysdeps/arc/preconfigure
+index a79db0239a..eab4af0eab 100644
+--- a/sysdeps/arc/preconfigure
++++ b/sysdeps/arc/preconfigure
+@@ -1,14 +1,22 @@
+ case "$machine" in
+ arc*)
+- base_machine=arc
+- machine=arc
++ with_fp_cond=0
++ isarc64=`$CC $CFLAGS $CPPFLAGS -E -dM -xc /dev/null | grep __LP64__| wc -l`
++
++ case "$isarc64" in
++ 0)
++ base_machine=arc
++ machine=arc/arc32
++ ;;
++ 1)
++ base_machine=arc
++ machine=arc/arc64
++ ;;
++ esac
+
+ gccfloat=`$CC $CFLAGS $CPPFLAGS -E -dM -xc /dev/null | grep __ARC_FPU_| wc -l`
+ if test "$gccfloat" != "0"; then
+ with_fp_cond=1
+- else
+- with_fp_cond=0
+ fi
+ ;;
+-
+ esac
+diff --git a/sysdeps/arc/setjmp.S b/sysdeps/arc/setjmp.S
+index 9ecdb9daae..e39b526837 100644
+--- a/sysdeps/arc/setjmp.S
++++ b/sysdeps/arc/setjmp.S
+@@ -41,24 +41,47 @@ ENTRY (__sigsetjmp)
+ that will be right next to this setjmp call-site in BLINK
+ since "C" caller of this routine will do a branch-n-link. */
+
+- STR (blink, r0, 0)
+- STR (sp, r0, 1)
+- STR (fp, r0, 2)
+- STR (gp, r0, 3)
++ STR.as blink, r0, 0
++ STR.as sp, r0, 1
++ STR.as fp, r0, 2
++ STR.as gp, r0, 3
+
+- STR (r13, r0, 4)
+- STR (r14, r0, 5)
+- STR (r15, r0, 6)
+- STR (r16, r0, 7)
+- STR (r17, r0, 8)
+- STR (r18, r0, 9)
+- STR (r19, r0, 10)
+- STR (r20, r0, 11)
+- STR (r21, r0, 12)
+- STR (r22, r0, 13)
+- STR (r23, r0, 14)
+- STR (r24, r0, 15)
++ STR.as r13, r0, 4
++ STR.as r14, r0, 5
++ STR.as r15, r0, 6
++ STR.as r16, r0, 7
++ STR.as r17, r0, 8
++ STR.as r18, r0, 9
++ STR.as r19, r0, 10
++ STR.as r20, r0, 11
++ STR.as r21, r0, 12
++ STR.as r22, r0, 13
++ STR.as r23, r0, 14
++ STR.as r24, r0, 15
+
++#if defined(__ARCV3__)
++ STR.as r25, r0, 16
++ STR.as r26, r0, 17
++#endif
++
++#if defined (__ARC_FLOAT_ABI_HARD__)
++ FSTR.as f16, r0, 18
++ FSTR.as f17, r0, 19
++ FSTR.as f18, r0, 20
++ FSTR.as f19, r0, 21
++ FSTR.as f20, r0, 22
++ FSTR.as f21, r0, 23
++ FSTR.as f22, r0, 24
++ FSTR.as f23, r0, 25
++ FSTR.as f24, r0, 26
++ FSTR.as f25, r0, 27
++ FSTR.as f26, r0, 28
++ FSTR.as f27, r0, 29
++ FSTR.as f28, r0, 30
++ FSTR.as f29, r0, 31
++ FSTR.as f30, r0, 32
++ FSTR.as f31, r0, 33
++#endif
+ b __sigjmp_save
+
+ END (__sigsetjmp)
+diff --git a/sysdeps/arc/sfp-machine.h b/sysdeps/arc/sfp-machine.h
+index 0917a7ae17..4743b694a2 100644
+--- a/sysdeps/arc/sfp-machine.h
++++ b/sysdeps/arc/sfp-machine.h
+@@ -17,10 +17,12 @@
+ <https://www.gnu.org/licenses/>. */
+
+
+-#define _FP_W_TYPE_SIZE 32
+-#define _FP_W_TYPE unsigned long
+-#define _FP_WS_TYPE signed long
+-#define _FP_I_TYPE long
++#ifndef __ARC64__
++
++# define _FP_W_TYPE_SIZE 32
++# define _FP_W_TYPE unsigned long
++# define _FP_WS_TYPE signed long
++# define _FP_I_TYPE long
+
+ #define _FP_MUL_MEAT_S(R,X,Y) \
+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+@@ -67,4 +69,49 @@
+ R##_c = FP_CLS_NAN; \
+ } while (0)
+
++#else
++
++# define _FP_W_TYPE_SIZE 64
++# define _FP_W_TYPE unsigned long long
++# define _FP_WS_TYPE signed long long
++# define _FP_I_TYPE long long
++
++# define _FP_MUL_MEAT_S(R, X, Y) \
++ _FP_MUL_MEAT_1_imm (_FP_WFRACBITS_S, R, X, Y)
++# define _FP_MUL_MEAT_D(R, X, Y) \
++ _FP_MUL_MEAT_1_wide (_FP_WFRACBITS_D, R, X, Y, umul_ppmm)
++# define _FP_MUL_MEAT_Q(R, X, Y) \
++ _FP_MUL_MEAT_2_wide_3mul (_FP_WFRACBITS_Q, R, X, Y, umul_ppmm)
++
++# define _FP_MUL_MEAT_DW_S(R, X, Y) \
++ _FP_MUL_MEAT_DW_1_imm (_FP_WFRACBITS_S, R, X, Y)
++# define _FP_MUL_MEAT_DW_D(R, X, Y) \
++ _FP_MUL_MEAT_DW_1_wide (_FP_WFRACBITS_D, R, X, Y, umul_ppmm)
++# define _FP_MUL_MEAT_DW_Q(R, X, Y) \
++ _FP_MUL_MEAT_DW_2_wide_3mul (_FP_WFRACBITS_Q, R, X, Y, umul_ppmm)
++
++# define _FP_DIV_MEAT_S(R, X, Y) _FP_DIV_MEAT_1_imm (S, R, X, Y, _FP_DIV_HELP_imm)
++# define _FP_DIV_MEAT_D(R, X, Y) _FP_DIV_MEAT_1_udiv_norm (D, R, X, Y)
++# define _FP_DIV_MEAT_Q(R, X, Y) _FP_DIV_MEAT_2_udiv (Q, R, X, Y)
++
++# define _FP_NANFRAC_S _FP_QNANBIT_S
++# define _FP_NANFRAC_D _FP_QNANBIT_D
++# define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0
++
++#define _FP_NANSIGN_S 0
++#define _FP_NANSIGN_D 0
++#define _FP_NANSIGN_Q 0
++
++#define _FP_KEEPNANFRACP 0
++#define _FP_QNANNEGATEDP 0
++
++#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
++ do { \
++ R##_s = _FP_NANSIGN_##fs; \
++ _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
++ R##_c = FP_CLS_NAN; \
++ } while (0)
++
++#endif
++
+ #define _FP_TININESS_AFTER_ROUNDING 1
+diff --git a/sysdeps/arc/start.S b/sysdeps/arc/start.S
+index db3bab6395..42ead9d302 100644
+--- a/sysdeps/arc/start.S
++++ b/sysdeps/arc/start.S
+@@ -57,12 +57,12 @@ ENTRY (ENTRY_POINT)
+ cfi_undefined (blink)
+
+ mov fp, 0
+- ld_s r1, [sp] /* argc. */
++ LDR r1, sp /* argc. */
+
+- mov_s r5, r0 /* rltd_fini. */
+- add_s r2, sp, 4 /* argv. */
+- and sp, sp, -8
+- mov r6, sp
++ MOVR r5, r0 /* rltd_fini. */
++ ADDR r2, sp, REGSZ /* argv. */
++ ANDR sp, sp, -2*REGSZ
++ MOVR r6, sp
+
+ /* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end). */
+
+@@ -70,10 +70,10 @@ ENTRY (ENTRY_POINT)
+ mov r4, 0 /* Used to be fini. */
+
+ #ifdef SHARED
+- ld r0, [pcl, @main@gotpc]
++ LDR r0, pcl, @main@gotpc
+ bl __libc_start_main@plt
+ #else
+- mov_s r0, main
++ MOVR r0, main
+ bl __libc_start_main
+ #endif
+
+diff --git a/sysdeps/arc/sysdep.h b/sysdeps/arc/sysdep.h
+index 4f024f6b73..ba6ecddbac 100644
+--- a/sysdeps/arc/sysdep.h
++++ b/sysdeps/arc/sysdep.h
+@@ -47,7 +47,6 @@
+
+ # define CALL_MCOUNT /* Do nothing for now. */
+
+-# define STR(reg, rbase, off) st reg, [rbase, off * 4]
+-# define LDR(reg, rbase, off) ld reg, [rbase, off * 4]
+-
+ #endif /* __ASSEMBLER__ */
++
++#include <sysdeps/arc/isa-asm-macros.h>
+diff --git a/sysdeps/unix/sysv/linux/arc/Makefile b/sysdeps/unix/sysv/linux/arc/Makefile
+index eca9a9fd3a..00d655bcd3 100644
+--- a/sysdeps/unix/sysv/linux/arc/Makefile
++++ b/sysdeps/unix/sysv/linux/arc/Makefile
+@@ -12,11 +12,13 @@ sysdep_headers += sys/cachectl.h
+ sysdep_routines += cacheflush
+ endif
+
+-abi-variants := arcle arcbe
++abi-variants := arcle arcbe arc32le arc64le
+
+ ifeq (,$(filter $(default-abi),$(abi-variants)))
+ $(error Unknown ABI $(default-abi), must be one of $(abi-variants))
+ endif
+
+-abi-arcle-condition := !defined __BIG_ENDIAN__
+-abi-arcbe-condition := defined __BIG_ENDIAN__
++abi-arcle-condition := !defined __ARC64__ && !defined __BIG_ENDIAN__
++abi-arcbe-condition := !defined __ARC64__ && defined __BIG_ENDIAN__
++abi-arc32le-condition := defined __ARC64_ARCH32__ && !defined __BIG_ENDIAN__
++abi-arc64le-condition := defined __ARC64_ARCH64__ && !defined __BIG_ENDIAN__
+diff --git a/sysdeps/unix/sysv/linux/arc/arc32/Implies b/sysdeps/unix/sysv/linux/arc/arc32/Implies
+new file mode 100644
+index 0000000000..9670973cfa
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/arc/arc32/Implies
+@@ -0,0 +1 @@
++unix/sysv/linux/arc
+diff --git a/sysdeps/unix/sysv/linux/arc/arch-syscall.h b/sysdeps/unix/sysv/linux/arc/arc32/arch-syscall.h
+similarity index 100%
+copy from sysdeps/unix/sysv/linux/arc/arch-syscall.h
+copy to sysdeps/unix/sysv/linux/arc/arc32/arch-syscall.h
+diff --git a/sysdeps/unix/sysv/linux/arc/c++-types.data b/sysdeps/unix/sysv/linux/arc/arc32/c++-types.data
+similarity index 100%
+copy from sysdeps/unix/sysv/linux/arc/c++-types.data
+copy to sysdeps/unix/sysv/linux/arc/arc32/c++-types.data
+diff --git a/sysdeps/unix/sysv/linux/arc/fixup-asm-unistd.h b/sysdeps/unix/sysv/linux/arc/arc32/fixup-asm-unistd.h
+similarity index 100%
+rename from sysdeps/unix/sysv/linux/arc/fixup-asm-unistd.h
+rename to sysdeps/unix/sysv/linux/arc/arc32/fixup-asm-unistd.h
+diff --git a/sysdeps/unix/sysv/linux/arc/ld.abilist b/sysdeps/unix/sysv/linux/arc/arc32/ld.abilist
+similarity index 100%
+copy from sysdeps/unix/sysv/linux/arc/ld.abilist
+copy to sysdeps/unix/sysv/linux/arc/arc32/ld.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libBrokenLocale.abilist b/sysdeps/unix/sysv/linux/arc/arc32/libBrokenLocale.abilist
+similarity index 100%
+copy from sysdeps/unix/sysv/linux/arc/libBrokenLocale.abilist
+copy to sysdeps/unix/sysv/linux/arc/arc32/libBrokenLocale.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libanl.abilist b/sysdeps/unix/sysv/linux/arc/arc32/libanl.abilist
+similarity index 100%
+copy from sysdeps/unix/sysv/linux/arc/libanl.abilist
+copy to sysdeps/unix/sysv/linux/arc/arc32/libanl.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/arc32/libc.abilist
+similarity index 100%
+copy from sysdeps/unix/sysv/linux/arc/libc.abilist
+copy to sysdeps/unix/sysv/linux/arc/arc32/libc.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/arc/arc32/libc_malloc_debug.abilist
+similarity index 100%
+copy from sysdeps/unix/sysv/linux/arc/libc_malloc_debug.abilist
+copy to sysdeps/unix/sysv/linux/arc/arc32/libc_malloc_debug.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libcrypt.abilist b/sysdeps/unix/sysv/linux/arc/arc32/libcrypt.abilist
+similarity index 100%
+copy from sysdeps/unix/sysv/linux/arc/libcrypt.abilist
+copy to sysdeps/unix/sysv/linux/arc/arc32/libcrypt.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libdl.abilist b/sysdeps/unix/sysv/linux/arc/arc32/libdl.abilist
+similarity index 100%
+copy from sysdeps/unix/sysv/linux/arc/libdl.abilist
+copy to sysdeps/unix/sysv/linux/arc/arc32/libdl.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libm.abilist b/sysdeps/unix/sysv/linux/arc/arc32/libm.abilist
+similarity index 100%
+copy from sysdeps/unix/sysv/linux/arc/libm.abilist
+copy to sysdeps/unix/sysv/linux/arc/arc32/libm.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libpthread.abilist b/sysdeps/unix/sysv/linux/arc/arc32/libpthread.abilist
+similarity index 100%
+copy from sysdeps/unix/sysv/linux/arc/libpthread.abilist
+copy to sysdeps/unix/sysv/linux/arc/arc32/libpthread.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libresolv.abilist b/sysdeps/unix/sysv/linux/arc/arc32/libresolv.abilist
+similarity index 100%
+copy from sysdeps/unix/sysv/linux/arc/libresolv.abilist
+copy to sysdeps/unix/sysv/linux/arc/arc32/libresolv.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/librt.abilist b/sysdeps/unix/sysv/linux/arc/arc32/librt.abilist
+similarity index 100%
+copy from sysdeps/unix/sysv/linux/arc/librt.abilist
+copy to sysdeps/unix/sysv/linux/arc/arc32/librt.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libthread_db.abilist b/sysdeps/unix/sysv/linux/arc/arc32/libthread_db.abilist
+similarity index 100%
+copy from sysdeps/unix/sysv/linux/arc/libthread_db.abilist
+copy to sysdeps/unix/sysv/linux/arc/arc32/libthread_db.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libutil.abilist b/sysdeps/unix/sysv/linux/arc/arc32/libutil.abilist
+similarity index 100%
+copy from sysdeps/unix/sysv/linux/arc/libutil.abilist
+copy to sysdeps/unix/sysv/linux/arc/arc32/libutil.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/arc64/Implies b/sysdeps/unix/sysv/linux/arc/arc64/Implies
+new file mode 100644
+index 0000000000..05abf4461a
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/arc/arc64/Implies
+@@ -0,0 +1,2 @@
++unix/sysv/linux/arc
++unix/sysv/linux/wordsize-64
+diff --git a/sysdeps/unix/sysv/linux/arc/arch-syscall.h b/sysdeps/unix/sysv/linux/arc/arc64/arch-syscall.h
+similarity index 89%
+rename from sysdeps/unix/sysv/linux/arc/arch-syscall.h
+rename to sysdeps/unix/sysv/linux/arc/arc64/arch-syscall.h
+index c1207aaa12..c73f38e567 100644
+--- a/sysdeps/unix/sysv/linux/arc/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/arc/arc64/arch-syscall.h
+@@ -15,11 +15,11 @@
+ #define __NR_capset 91
+ #define __NR_chdir 49
+ #define __NR_chroot 51
+-#define __NR_clock_adjtime64 405
+-#define __NR_clock_getres_time64 406
+-#define __NR_clock_gettime64 403
+-#define __NR_clock_nanosleep_time64 407
+-#define __NR_clock_settime64 404
++#define __NR_clock_adjtime 266
++#define __NR_clock_getres 114
++#define __NR_clock_gettime 113
++#define __NR_clock_nanosleep 115
++#define __NR_clock_settime 112
+ #define __NR_clone 220
+ #define __NR_clone3 435
+ #define __NR_close 57
+@@ -40,7 +40,7 @@
+ #define __NR_exit_group 94
+ #define __NR_faccessat 48
+ #define __NR_faccessat2 439
+-#define __NR_fadvise64_64 223
++#define __NR_fadvise64 223
+ #define __NR_fallocate 47
+ #define __NR_fanotify_init 262
+ #define __NR_fanotify_mark 263
+@@ -49,7 +49,7 @@
+ #define __NR_fchmodat 53
+ #define __NR_fchown 55
+ #define __NR_fchownat 54
+-#define __NR_fcntl64 25
++#define __NR_fcntl 25
+ #define __NR_fdatasync 83
+ #define __NR_fgetxattr 10
+ #define __NR_finit_module 273
+@@ -61,10 +61,11 @@
+ #define __NR_fsmount 432
+ #define __NR_fsopen 430
+ #define __NR_fspick 433
+-#define __NR_fstatfs64 44
++#define __NR_fstat 80
++#define __NR_fstatfs 44
+ #define __NR_fsync 82
+-#define __NR_ftruncate64 46
+-#define __NR_futex_time64 422
++#define __NR_ftruncate 46
++#define __NR_futex 98
+ #define __NR_futex_waitv 449
+ #define __NR_get_mempolicy 236
+ #define __NR_get_robust_list 100
+@@ -101,7 +102,6 @@
+ #define __NR_io_destroy 1
+ #define __NR_io_getevents 4
+ #define __NR_io_pgetevents 292
+-#define __NR_io_pgetevents_time64 416
+ #define __NR_io_setup 0
+ #define __NR_io_submit 2
+ #define __NR_io_uring_enter 426
+@@ -123,9 +123,9 @@
+ #define __NR_listen 201
+ #define __NR_listxattr 11
+ #define __NR_llistxattr 12
+-#define __NR_llseek 62
+ #define __NR_lookup_dcookie 18
+ #define __NR_lremovexattr 15
++#define __NR_lseek 62
+ #define __NR_lsetxattr 6
+ #define __NR_madvise 233
+ #define __NR_mbind 235
+@@ -138,7 +138,7 @@
+ #define __NR_mlock 228
+ #define __NR_mlock2 284
+ #define __NR_mlockall 230
+-#define __NR_mmap2 222
++#define __NR_mmap 222
+ #define __NR_mount 40
+ #define __NR_mount_setattr 442
+ #define __NR_move_mount 429
+@@ -147,8 +147,8 @@
+ #define __NR_mq_getsetattr 185
+ #define __NR_mq_notify 184
+ #define __NR_mq_open 180
+-#define __NR_mq_timedreceive_time64 419
+-#define __NR_mq_timedsend_time64 418
++#define __NR_mq_timedreceive 183
++#define __NR_mq_timedsend 182
+ #define __NR_mq_unlink 181
+ #define __NR_mremap 216
+ #define __NR_msgctl 187
+@@ -161,6 +161,7 @@
+ #define __NR_munmap 215
+ #define __NR_name_to_handle_at 264
+ #define __NR_nanosleep 101
++#define __NR_newfstatat 79
+ #define __NR_nfsservctl 42
+ #define __NR_open_by_handle_at 265
+ #define __NR_open_tree 428
+@@ -176,7 +177,7 @@
+ #define __NR_pkey_alloc 289
+ #define __NR_pkey_free 290
+ #define __NR_pkey_mprotect 288
+-#define __NR_ppoll_time64 414
++#define __NR_ppoll 73
+ #define __NR_prctl 167
+ #define __NR_pread64 67
+ #define __NR_preadv 69
+@@ -186,7 +187,7 @@
+ #define __NR_process_mrelease 448
+ #define __NR_process_vm_readv 270
+ #define __NR_process_vm_writev 271
+-#define __NR_pselect6_time64 413
++#define __NR_pselect6 72
+ #define __NR_ptrace 117
+ #define __NR_pwrite64 68
+ #define __NR_pwritev 70
+@@ -199,7 +200,7 @@
+ #define __NR_readv 65
+ #define __NR_reboot 142
+ #define __NR_recvfrom 207
+-#define __NR_recvmmsg_time64 417
++#define __NR_recvmmsg 243
+ #define __NR_recvmsg 212
+ #define __NR_remap_file_pages 234
+ #define __NR_removexattr 14
+@@ -214,7 +215,7 @@
+ #define __NR_rt_sigqueueinfo 138
+ #define __NR_rt_sigreturn 139
+ #define __NR_rt_sigsuspend 133
+-#define __NR_rt_sigtimedwait_time64 421
++#define __NR_rt_sigtimedwait 137
+ #define __NR_rt_tgsigqueueinfo 240
+ #define __NR_sched_get_priority_max 125
+ #define __NR_sched_get_priority_min 126
+@@ -222,7 +223,7 @@
+ #define __NR_sched_getattr 275
+ #define __NR_sched_getparam 121
+ #define __NR_sched_getscheduler 120
+-#define __NR_sched_rr_get_interval_time64 423
++#define __NR_sched_rr_get_interval 127
+ #define __NR_sched_setaffinity 122
+ #define __NR_sched_setattr 274
+ #define __NR_sched_setparam 118
+@@ -232,8 +233,8 @@
+ #define __NR_semctl 191
+ #define __NR_semget 190
+ #define __NR_semop 193
+-#define __NR_semtimedop_time64 420
+-#define __NR_sendfile64 71
++#define __NR_semtimedop 192
++#define __NR_sendfile 71
+ #define __NR_sendmmsg 269
+ #define __NR_sendmsg 211
+ #define __NR_sendto 206
+@@ -271,7 +272,7 @@
+ #define __NR_socket 198
+ #define __NR_socketpair 199
+ #define __NR_splice 76
+-#define __NR_statfs64 43
++#define __NR_statfs 43
+ #define __NR_statx 291
+ #define __NR_swapoff 225
+ #define __NR_swapon 224
+@@ -287,21 +288,21 @@
+ #define __NR_timer_create 107
+ #define __NR_timer_delete 111
+ #define __NR_timer_getoverrun 109
+-#define __NR_timer_gettime64 408
+-#define __NR_timer_settime64 409
++#define __NR_timer_gettime 108
++#define __NR_timer_settime 110
+ #define __NR_timerfd_create 85
+-#define __NR_timerfd_gettime64 410
+-#define __NR_timerfd_settime64 411
++#define __NR_timerfd_gettime 87
++#define __NR_timerfd_settime 86
+ #define __NR_times 153
+ #define __NR_tkill 130
+-#define __NR_truncate64 45
++#define __NR_truncate 45
+ #define __NR_umask 166
+ #define __NR_umount2 39
+ #define __NR_uname 160
+ #define __NR_unlinkat 35
+ #define __NR_unshare 97
+ #define __NR_userfaultfd 282
+-#define __NR_utimensat_time64 412
++#define __NR_utimensat 88
+ #define __NR_vhangup 58
+ #define __NR_vmsplice 75
+ #define __NR_wait4 260
+diff --git a/sysdeps/unix/sysv/linux/arc/c++-types.data b/sysdeps/unix/sysv/linux/arc/arc64/c++-types.data
+similarity index 73%
+rename from sysdeps/unix/sysv/linux/arc/c++-types.data
+rename to sysdeps/unix/sysv/linux/arc/arc64/c++-types.data
+index 0fb0143ae7..ac925ccb36 100644
+--- a/sysdeps/unix/sysv/linux/arc/c++-types.data
++++ b/sysdeps/unix/sysv/linux/arc/arc64/c++-types.data
+@@ -1,32 +1,32 @@
+-blkcnt64_t:x
+-blkcnt_t:x
++blkcnt64_t:l
++blkcnt_t:l
+ blksize_t:i
+ caddr_t:Pc
+ clockid_t:i
+ clock_t:l
+ daddr_t:i
+-dev_t:y
++dev_t:m
+ fd_mask:l
+-fsblkcnt64_t:y
+-fsblkcnt_t:y
+-fsfilcnt64_t:y
+-fsfilcnt_t:y
++fsblkcnt64_t:m
++fsblkcnt_t:m
++fsfilcnt64_t:m
++fsfilcnt_t:m
+ fsid_t:8__fsid_t
+ gid_t:j
+ id_t:j
+-ino64_t:y
+-ino_t:y
++ino64_t:m
++ino_t:m
+ int16_t:s
+ int32_t:i
+-int64_t:x
++int64_t:l
+ int8_t:a
+-intptr_t:i
++intptr_t:l
+ key_t:i
+-loff_t:x
++loff_t:l
+ mode_t:j
+ nlink_t:j
+-off64_t:x
+-off_t:x
++off64_t:l
++off_t:l
+ pid_t:i
+ pthread_attr_t:14pthread_attr_t
+ pthread_barrier_t:17pthread_barrier_t
+@@ -41,27 +41,27 @@ pthread_rwlock_t:16pthread_rwlock_t
+ pthread_rwlockattr_t:20pthread_rwlockattr_t
+ pthread_spinlock_t:i
+ pthread_t:m
+-quad_t:x
+-register_t:i
+-rlim64_t:y
+-rlim_t:y
++quad_t:l
++register_t:l
++rlim64_t:m
++rlim_t:m
+ sigset_t:10__sigset_t
+-size_t:j
++size_t:m
+ socklen_t:j
+-ssize_t:i
+-suseconds_t:x
+-time_t:x
++ssize_t:l
++suseconds_t:l
++time_t:l
+ u_char:h
+ uid_t:j
+ uint:j
+ u_int:j
+ u_int16_t:t
+ u_int32_t:j
+-u_int64_t:y
++u_int64_t:m
+ u_int8_t:h
+ ulong:m
+ u_long:m
+-u_quad_t:y
++u_quad_t:m
+ useconds_t:j
+ ushort:t
+ u_short:t
+diff --git a/sysdeps/unix/sysv/linux/arc/ld.abilist b/sysdeps/unix/sysv/linux/arc/arc64/ld.abilist
+similarity index 54%
+rename from sysdeps/unix/sysv/linux/arc/ld.abilist
+rename to sysdeps/unix/sysv/linux/arc/arc64/ld.abilist
+index 55f0c2ab9c..3a4bcb95f2 100644
+--- a/sysdeps/unix/sysv/linux/arc/ld.abilist
++++ b/sysdeps/unix/sysv/linux/arc/arc64/ld.abilist
+@@ -1,9 +1,9 @@
+-GLIBC_2.32 __libc_stack_end D 0x4
+-GLIBC_2.32 __stack_chk_guard D 0x4
++GLIBC_2.32 __libc_stack_end D 0x8
++GLIBC_2.32 __stack_chk_guard D 0x8
+ GLIBC_2.32 __tls_get_addr F
+ GLIBC_2.32 _dl_mcount F
+-GLIBC_2.32 _r_debug D 0x14
++GLIBC_2.32 _r_debug D 0x28
+ GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.35 __rseq_flags D 0x4
+-GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_offset D 0x8
+ GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/arc/libBrokenLocale.abilist b/sysdeps/unix/sysv/linux/arc/arc64/libBrokenLocale.abilist
+similarity index 100%
+rename from sysdeps/unix/sysv/linux/arc/libBrokenLocale.abilist
+rename to sysdeps/unix/sysv/linux/arc/arc64/libBrokenLocale.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libanl.abilist b/sysdeps/unix/sysv/linux/arc/arc64/libanl.abilist
+similarity index 100%
+rename from sysdeps/unix/sysv/linux/arc/libanl.abilist
+rename to sysdeps/unix/sysv/linux/arc/arc64/libanl.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/arc64/libc.abilist
+similarity index 97%
+rename from sysdeps/unix/sysv/linux/arc/libc.abilist
+rename to sysdeps/unix/sysv/linux/arc/arc64/libc.abilist
+index dfe0c3f7b6..d07723e742 100644
+--- a/sysdeps/unix/sysv/linux/arc/libc.abilist
++++ b/sysdeps/unix/sysv/linux/arc/arc64/libc.abilist
+@@ -1,7 +1,7 @@
+ GLIBC_2.32 _Exit F
+-GLIBC_2.32 _IO_2_1_stderr_ D 0x9c
+-GLIBC_2.32 _IO_2_1_stdin_ D 0x9c
+-GLIBC_2.32 _IO_2_1_stdout_ D 0x9c
++GLIBC_2.32 _IO_2_1_stderr_ D 0xe0
++GLIBC_2.32 _IO_2_1_stdin_ D 0xe0
++GLIBC_2.32 _IO_2_1_stdout_ D 0xe0
+ GLIBC_2.32 _IO_adjust_column F
+ GLIBC_2.32 _IO_adjust_wcolumn F
+ GLIBC_2.32 _IO_default_doallocate F
+@@ -27,7 +27,7 @@ GLIBC_2.32 _IO_file_doallocate F
+ GLIBC_2.32 _IO_file_finish F
+ GLIBC_2.32 _IO_file_fopen F
+ GLIBC_2.32 _IO_file_init F
+-GLIBC_2.32 _IO_file_jumps D 0x54
++GLIBC_2.32 _IO_file_jumps D 0xa8
+ GLIBC_2.32 _IO_file_open F
+ GLIBC_2.32 _IO_file_overflow F
+ GLIBC_2.32 _IO_file_read F
+@@ -67,7 +67,7 @@ GLIBC_2.32 _IO_iter_file F
+ GLIBC_2.32 _IO_iter_next F
+ GLIBC_2.32 _IO_least_wmarker F
+ GLIBC_2.32 _IO_link_in F
+-GLIBC_2.32 _IO_list_all D 0x4
++GLIBC_2.32 _IO_list_all D 0x8
+ GLIBC_2.32 _IO_list_lock F
+ GLIBC_2.32 _IO_list_resetlock F
+ GLIBC_2.32 _IO_list_unlock F
+@@ -120,7 +120,7 @@ GLIBC_2.32 _IO_wdefault_xsgetn F
+ GLIBC_2.32 _IO_wdefault_xsputn F
+ GLIBC_2.32 _IO_wdo_write F
+ GLIBC_2.32 _IO_wdoallocbuf F
+-GLIBC_2.32 _IO_wfile_jumps D 0x54
++GLIBC_2.32 _IO_wfile_jumps D 0xa8
+ GLIBC_2.32 _IO_wfile_overflow F
+ GLIBC_2.32 _IO_wfile_seekoff F
+ GLIBC_2.32 _IO_wfile_sync F
+@@ -128,9 +128,9 @@ GLIBC_2.32 _IO_wfile_underflow F
+ GLIBC_2.32 _IO_wfile_xsputn F
+ GLIBC_2.32 _IO_wmarker_delta F
+ GLIBC_2.32 _IO_wsetb F
+-GLIBC_2.32 ___brk_addr D 0x4
++GLIBC_2.32 ___brk_addr D 0x8
+ GLIBC_2.32 __adjtimex F
+-GLIBC_2.32 __after_morecore_hook D 0x4
++GLIBC_2.32 __after_morecore_hook D 0x8
+ GLIBC_2.32 __argz_count F
+ GLIBC_2.32 __argz_next F
+ GLIBC_2.32 __argz_stringify F
+@@ -155,7 +155,7 @@ GLIBC_2.32 __ctype_b_loc F
+ GLIBC_2.32 __ctype_get_mb_cur_max F
+ GLIBC_2.32 __ctype_tolower_loc F
+ GLIBC_2.32 __ctype_toupper_loc F
+-GLIBC_2.32 __curbrk D 0x4
++GLIBC_2.32 __curbrk D 0x8
+ GLIBC_2.32 __cxa_at_quick_exit F
+ GLIBC_2.32 __cxa_atexit F
+ GLIBC_2.32 __cxa_finalize F
+@@ -173,7 +173,7 @@ GLIBC_2.32 __dprintf_chk F
+ GLIBC_2.32 __dup2 F
+ GLIBC_2.32 __duplocale F
+ GLIBC_2.32 __endmntent F
+-GLIBC_2.32 __environ D 0x4
++GLIBC_2.32 __environ D 0x8
+ GLIBC_2.32 __errno_location F
+ GLIBC_2.32 __explicit_bzero_chk F
+ GLIBC_2.32 __fbufsize F
+@@ -197,7 +197,7 @@ GLIBC_2.32 __fread_chk F
+ GLIBC_2.32 __fread_unlocked_chk F
+ GLIBC_2.32 __freadable F
+ GLIBC_2.32 __freading F
+-GLIBC_2.32 __free_hook D 0x4
++GLIBC_2.32 __free_hook D 0x8
+ GLIBC_2.32 __freelocale F
+ GLIBC_2.32 __fsetlocking F
+ GLIBC_2.32 __fwprintf_chk F
+@@ -289,20 +289,20 @@ GLIBC_2.32 __longjmp_chk F
+ GLIBC_2.32 __lseek F
+ GLIBC_2.32 __lxstat F
+ GLIBC_2.32 __lxstat64 F
+-GLIBC_2.32 __malloc_hook D 0x4
++GLIBC_2.32 __malloc_hook D 0x8
+ GLIBC_2.32 __mbrlen F
+ GLIBC_2.32 __mbrtowc F
+ GLIBC_2.32 __mbsnrtowcs_chk F
+ GLIBC_2.32 __mbsrtowcs_chk F
+ GLIBC_2.32 __mbstowcs_chk F
+-GLIBC_2.32 __memalign_hook D 0x4
++GLIBC_2.32 __memalign_hook D 0x8
+ GLIBC_2.32 __memcpy_chk F
+ GLIBC_2.32 __memmove_chk F
+ GLIBC_2.32 __mempcpy F
+ GLIBC_2.32 __mempcpy_chk F
+ GLIBC_2.32 __memset_chk F
+ GLIBC_2.32 __monstartup F
+-GLIBC_2.32 __morecore D 0x4
++GLIBC_2.32 __morecore D 0x8
+ GLIBC_2.32 __mq_open_2 F
+ GLIBC_2.32 __nanosleep F
+ GLIBC_2.32 __newlocale F
+@@ -329,8 +329,8 @@ GLIBC_2.32 __pread_chk F
+ GLIBC_2.32 __printf_chk F
+ GLIBC_2.32 __printf_fp F
+ GLIBC_2.32 __profile_frequency F
+-GLIBC_2.32 __progname D 0x4
+-GLIBC_2.32 __progname_full D 0x4
++GLIBC_2.32 __progname D 0x8
++GLIBC_2.32 __progname_full D 0x8
+ GLIBC_2.32 __pthread_cleanup_routine F
+ GLIBC_2.32 __pthread_getspecific F
+ GLIBC_2.32 __pthread_key_create F
+@@ -359,12 +359,12 @@ GLIBC_2.32 __pthread_unwind_next F
+ GLIBC_2.32 __ptsname_r_chk F
+ GLIBC_2.32 __pwrite64 F
+ GLIBC_2.32 __rawmemchr F
+-GLIBC_2.32 __rcmd_errstr D 0x4
++GLIBC_2.32 __rcmd_errstr D 0x8
+ GLIBC_2.32 __read F
+ GLIBC_2.32 __read_chk F
+ GLIBC_2.32 __readlink_chk F
+ GLIBC_2.32 __readlinkat_chk F
+-GLIBC_2.32 __realloc_hook D 0x4
++GLIBC_2.32 __realloc_hook D 0x8
+ GLIBC_2.32 __realpath_chk F
+ GLIBC_2.32 __recv_chk F
+ GLIBC_2.32 __recvfrom_chk F
+@@ -452,7 +452,7 @@ GLIBC_2.32 __swprintf_chk F
+ GLIBC_2.32 __sysconf F
+ GLIBC_2.32 __syslog_chk F
+ GLIBC_2.32 __sysv_signal F
+-GLIBC_2.32 __timezone D 0x4
++GLIBC_2.32 __timezone D 0x8
+ GLIBC_2.32 __toascii_l F
+ GLIBC_2.32 __tolower_l F
+ GLIBC_2.32 __toupper_l F
+@@ -461,7 +461,7 @@ GLIBC_2.32 __towctrans_l F
+ GLIBC_2.32 __towlower_l F
+ GLIBC_2.32 __towupper_l F
+ GLIBC_2.32 __ttyname_r_chk F
+-GLIBC_2.32 __tzname D 0x8
++GLIBC_2.32 __tzname D 0x10
+ GLIBC_2.32 __uflow F
+ GLIBC_2.32 __underflow F
+ GLIBC_2.32 __uselocale F
+@@ -531,7 +531,7 @@ GLIBC_2.32 __xstat F
+ GLIBC_2.32 __xstat64 F
+ GLIBC_2.32 _dl_mcount_wrapper F
+ GLIBC_2.32 _dl_mcount_wrapper_check F
+-GLIBC_2.32 _environ D 0x4
++GLIBC_2.32 _environ D 0x8
+ GLIBC_2.32 _exit F
+ GLIBC_2.32 _flush_cache F
+ GLIBC_2.32 _flushlbf F
+@@ -540,7 +540,7 @@ GLIBC_2.32 _longjmp F
+ GLIBC_2.32 _mcleanup F
+ GLIBC_2.32 _mcount F
+ GLIBC_2.32 _nl_default_dirname D 0x12
+-GLIBC_2.32 _nl_domain_bindings D 0x4
++GLIBC_2.32 _nl_domain_bindings D 0x8
+ GLIBC_2.32 _nl_msg_cat_cntr D 0x4
+ GLIBC_2.32 _obstack_allocated_p F
+ GLIBC_2.32 _obstack_begin F
+@@ -552,8 +552,8 @@ GLIBC_2.32 _pthread_cleanup_pop F
+ GLIBC_2.32 _pthread_cleanup_pop_restore F
+ GLIBC_2.32 _pthread_cleanup_push F
+ GLIBC_2.32 _pthread_cleanup_push_defer F
+-GLIBC_2.32 _res D 0x200
+-GLIBC_2.32 _res_hconf D 0x30
++GLIBC_2.32 _res D 0x238
++GLIBC_2.32 _res_hconf D 0x48
+ GLIBC_2.32 _setjmp F
+ GLIBC_2.32 _tolower F
+ GLIBC_2.32 _toupper F
+@@ -592,9 +592,9 @@ GLIBC_2.32 argp_error F
+ GLIBC_2.32 argp_failure F
+ GLIBC_2.32 argp_help F
+ GLIBC_2.32 argp_parse F
+-GLIBC_2.32 argp_program_bug_address D 0x4
+-GLIBC_2.32 argp_program_version D 0x4
+-GLIBC_2.32 argp_program_version_hook D 0x4
++GLIBC_2.32 argp_program_bug_address D 0x8
++GLIBC_2.32 argp_program_version D 0x8
++GLIBC_2.32 argp_program_version_hook D 0x8
+ GLIBC_2.32 argp_state_help F
+ GLIBC_2.32 argp_usage F
+ GLIBC_2.32 argz_add F
+@@ -734,7 +734,7 @@ GLIBC_2.32 endttyent F
+ GLIBC_2.32 endusershell F
+ GLIBC_2.32 endutent F
+ GLIBC_2.32 endutxent F
+-GLIBC_2.32 environ D 0x4
++GLIBC_2.32 environ D 0x8
+ GLIBC_2.32 envz_add F
+ GLIBC_2.32 envz_entry F
+ GLIBC_2.32 envz_get F
+@@ -753,7 +753,7 @@ GLIBC_2.32 error F
+ GLIBC_2.32 error_at_line F
+ GLIBC_2.32 error_message_count D 0x4
+ GLIBC_2.32 error_one_per_line D 0x4
+-GLIBC_2.32 error_print_progname D 0x4
++GLIBC_2.32 error_print_progname D 0x8
+ GLIBC_2.32 errx F
+ GLIBC_2.32 ether_aton F
+ GLIBC_2.32 ether_aton_r F
+@@ -1078,7 +1078,7 @@ GLIBC_2.32 grantpt F
+ GLIBC_2.32 group_member F
+ GLIBC_2.32 gsignal F
+ GLIBC_2.32 gtty F
+-GLIBC_2.32 h_errlist D 0x14
++GLIBC_2.32 h_errlist D 0x28
+ GLIBC_2.32 h_nerr D 0x4
+ GLIBC_2.32 hasmntopt F
+ GLIBC_2.32 hcreate F
+@@ -1260,7 +1260,7 @@ GLIBC_2.32 malloc_stats F
+ GLIBC_2.32 malloc_trim F
+ GLIBC_2.32 malloc_usable_size F
+ GLIBC_2.32 mallopt F
+-GLIBC_2.32 mallwatch D 0x4
++GLIBC_2.32 mallwatch D 0x8
+ GLIBC_2.32 mblen F
+ GLIBC_2.32 mbrlen F
+ GLIBC_2.32 mbrtoc16 F
+@@ -1367,7 +1367,7 @@ GLIBC_2.32 ntohs F
+ GLIBC_2.32 ntp_adjtime F
+ GLIBC_2.32 ntp_gettime F
+ GLIBC_2.32 ntp_gettimex F
+-GLIBC_2.32 obstack_alloc_failed_handler D 0x4
++GLIBC_2.32 obstack_alloc_failed_handler D 0x8
+ GLIBC_2.32 obstack_exit_failure D 0x4
+ GLIBC_2.32 obstack_free F
+ GLIBC_2.32 obstack_printf F
+@@ -1383,7 +1383,7 @@ GLIBC_2.32 openat64 F
+ GLIBC_2.32 opendir F
+ GLIBC_2.32 openlog F
+ GLIBC_2.32 openpty F
+-GLIBC_2.32 optarg D 0x4
++GLIBC_2.32 optarg D 0x8
+ GLIBC_2.32 opterr D 0x4
+ GLIBC_2.32 optind D 0x4
+ GLIBC_2.32 optopt D 0x4
+@@ -1449,8 +1449,8 @@ GLIBC_2.32 prlimit64 F
+ GLIBC_2.32 process_vm_readv F
+ GLIBC_2.32 process_vm_writev F
+ GLIBC_2.32 profil F
+-GLIBC_2.32 program_invocation_name D 0x4
+-GLIBC_2.32 program_invocation_short_name D 0x4
++GLIBC_2.32 program_invocation_name D 0x8
++GLIBC_2.32 program_invocation_short_name D 0x8
+ GLIBC_2.32 pselect F
+ GLIBC_2.32 psiginfo F
+ GLIBC_2.32 psignal F
+@@ -1637,7 +1637,7 @@ GLIBC_2.32 re_search F
+ GLIBC_2.32 re_search_2 F
+ GLIBC_2.32 re_set_registers F
+ GLIBC_2.32 re_set_syntax F
+-GLIBC_2.32 re_syntax_options D 0x4
++GLIBC_2.32 re_syntax_options D 0x8
+ GLIBC_2.32 read F
+ GLIBC_2.32 readahead F
+ GLIBC_2.32 readdir F
+@@ -1850,9 +1850,9 @@ GLIBC_2.32 statfs64 F
+ GLIBC_2.32 statvfs F
+ GLIBC_2.32 statvfs64 F
+ GLIBC_2.32 statx F
+-GLIBC_2.32 stderr D 0x4
+-GLIBC_2.32 stdin D 0x4
+-GLIBC_2.32 stdout D 0x4
++GLIBC_2.32 stderr D 0x8
++GLIBC_2.32 stdin D 0x8
++GLIBC_2.32 stdout D 0x8
+ GLIBC_2.32 stpcpy F
+ GLIBC_2.32 stpncpy F
+ GLIBC_2.32 strcasecmp F
+@@ -1984,7 +1984,7 @@ GLIBC_2.32 timerfd_gettime F
+ GLIBC_2.32 timerfd_settime F
+ GLIBC_2.32 times F
+ GLIBC_2.32 timespec_get F
+-GLIBC_2.32 timezone D 0x4
++GLIBC_2.32 timezone D 0x8
+ GLIBC_2.32 tmpfile F
+ GLIBC_2.32 tmpfile64 F
+ GLIBC_2.32 tmpnam F
+@@ -2013,7 +2013,7 @@ GLIBC_2.32 ttyname_r F
+ GLIBC_2.32 ttyslot F
+ GLIBC_2.32 twalk F
+ GLIBC_2.32 twalk_r F
+-GLIBC_2.32 tzname D 0x8
++GLIBC_2.32 tzname D 0x10
+ GLIBC_2.32 tzset F
+ GLIBC_2.32 ualarm F
+ GLIBC_2.32 ulckpwdf F
+diff --git a/sysdeps/unix/sysv/linux/arc/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/arc/arc64/libc_malloc_debug.abilist
+similarity index 80%
+rename from sysdeps/unix/sysv/linux/arc/libc_malloc_debug.abilist
+rename to sysdeps/unix/sysv/linux/arc/arc64/libc_malloc_debug.abilist
+index cf9f611403..c50393d8cc 100644
+--- a/sysdeps/unix/sysv/linux/arc/libc_malloc_debug.abilist
++++ b/sysdeps/unix/sysv/linux/arc/arc64/libc_malloc_debug.abilist
+@@ -1,7 +1,7 @@
+-GLIBC_2.32 __free_hook D 0x4
+-GLIBC_2.32 __malloc_hook D 0x4
+-GLIBC_2.32 __memalign_hook D 0x4
+-GLIBC_2.32 __realloc_hook D 0x4
++GLIBC_2.32 __free_hook D 0x8
++GLIBC_2.32 __malloc_hook D 0x8
++GLIBC_2.32 __memalign_hook D 0x8
++GLIBC_2.32 __realloc_hook D 0x8
+ GLIBC_2.32 aligned_alloc F
+ GLIBC_2.32 calloc F
+ GLIBC_2.32 free F
+diff --git a/sysdeps/unix/sysv/linux/arc/libcrypt.abilist b/sysdeps/unix/sysv/linux/arc/arc64/libcrypt.abilist
+similarity index 100%
+rename from sysdeps/unix/sysv/linux/arc/libcrypt.abilist
+rename to sysdeps/unix/sysv/linux/arc/arc64/libcrypt.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libdl.abilist b/sysdeps/unix/sysv/linux/arc/arc64/libdl.abilist
+similarity index 100%
+rename from sysdeps/unix/sysv/linux/arc/libdl.abilist
+rename to sysdeps/unix/sysv/linux/arc/arc64/libdl.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libm.abilist b/sysdeps/unix/sysv/linux/arc/arc64/libm.abilist
+similarity index 100%
+rename from sysdeps/unix/sysv/linux/arc/libm.abilist
+rename to sysdeps/unix/sysv/linux/arc/arc64/libm.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libpthread.abilist b/sysdeps/unix/sysv/linux/arc/arc64/libpthread.abilist
+similarity index 100%
+rename from sysdeps/unix/sysv/linux/arc/libpthread.abilist
+rename to sysdeps/unix/sysv/linux/arc/arc64/libpthread.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libresolv.abilist b/sysdeps/unix/sysv/linux/arc/arc64/libresolv.abilist
+similarity index 95%
+rename from sysdeps/unix/sysv/linux/arc/libresolv.abilist
+rename to sysdeps/unix/sysv/linux/arc/arc64/libresolv.abilist
+index 47c5072f61..76ab1dedfb 100644
+--- a/sysdeps/unix/sysv/linux/arc/libresolv.abilist
++++ b/sysdeps/unix/sysv/linux/arc/arc64/libresolv.abilist
+@@ -10,7 +10,7 @@ GLIBC_2.32 __loc_ntoa F
+ GLIBC_2.32 __p_cdname F
+ GLIBC_2.32 __p_cdnname F
+ GLIBC_2.32 __p_class F
+-GLIBC_2.32 __p_class_syms D 0x54
++GLIBC_2.32 __p_class_syms D 0xa8
+ GLIBC_2.32 __p_fqname F
+ GLIBC_2.32 __p_fqnname F
+ GLIBC_2.32 __p_option F
+@@ -18,7 +18,7 @@ GLIBC_2.32 __p_query F
+ GLIBC_2.32 __p_rcode F
+ GLIBC_2.32 __p_time F
+ GLIBC_2.32 __p_type F
+-GLIBC_2.32 __p_type_syms D 0x228
++GLIBC_2.32 __p_type_syms D 0x450
+ GLIBC_2.32 __putlong F
+ GLIBC_2.32 __putshort F
+ GLIBC_2.32 __res_close F
+diff --git a/sysdeps/unix/sysv/linux/arc/librt.abilist b/sysdeps/unix/sysv/linux/arc/arc64/librt.abilist
+similarity index 100%
+rename from sysdeps/unix/sysv/linux/arc/librt.abilist
+rename to sysdeps/unix/sysv/linux/arc/arc64/librt.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libthread_db.abilist b/sysdeps/unix/sysv/linux/arc/arc64/libthread_db.abilist
+similarity index 100%
+rename from sysdeps/unix/sysv/linux/arc/libthread_db.abilist
+rename to sysdeps/unix/sysv/linux/arc/arc64/libthread_db.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/libutil.abilist b/sysdeps/unix/sysv/linux/arc/arc64/libutil.abilist
+similarity index 100%
+rename from sysdeps/unix/sysv/linux/arc/libutil.abilist
+rename to sysdeps/unix/sysv/linux/arc/arc64/libutil.abilist
+diff --git a/sysdeps/unix/sysv/linux/arc/bits/fcntl.h b/sysdeps/unix/sysv/linux/arc/bits/fcntl.h
+new file mode 100644
+index 0000000000..20292fd32f
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/arc/bits/fcntl.h
+@@ -0,0 +1,62 @@
++/* O_*, F_*, FD_* bit values for Linux / ARC
++ Copyright (C) 2011-2021 Free Software Foundation, Inc.
++
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ 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
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _FCNTL_H
++# error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead."
++#endif
++
++#include <bits/wordsize.h>
++
++/* In 64-bit ISA files are always with 64bit off_t and F_*LK64 are the same as
++ non-64-bit versions. It will need to be revised for 128-bit. */
++#if __WORDSIZE == 64
++# define __O_LARGEFILE 0
++
++# define F_GETLK64 5 /* Get record locking info. */
++# define F_SETLK64 6 /* Set record locking info (non-blocking). */
++# define F_SETLKW64 7 /* Set record locking info (blocking). */
++#endif
++
++struct flock
++ {
++ short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */
++ short int l_whence; /* Where `l_start' is relative to (like `lseek'). */
++#if __WORDSIZE == 64 || !defined __USE_FILE_OFFSET64
++ __off_t l_start; /* Offset where the lock begins. */
++ __off_t l_len; /* Size of the locked area; zero means until EOF. */
++#else
++ __off64_t l_start; /* Offset where the lock begins. */
++ __off64_t l_len; /* Size of the locked area; zero means until EOF. */
++#endif
++ __pid_t l_pid; /* Process holding the lock. */
++ };
++
++#ifdef __USE_LARGEFILE64
++struct flock64
++ {
++ short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */
++ short int l_whence; /* Where `l_start' is relative to (like `lseek'). */
++ __off64_t l_start; /* Offset where the lock begins. */
++ __off64_t l_len; /* Size of the locked area; zero means until EOF. */
++ __pid_t l_pid; /* Process holding the lock. */
++ };
++#endif
++
++/* Include generic Linux declarations. */
++#include <bits/fcntl-linux.h>
+diff --git a/sysdeps/unix/sysv/linux/arc/bits/types/__sigset_t.h b/sysdeps/unix/sysv/linux/arc/bits/types/__sigset_t.h
+index 795638a30b..6be69437f8 100644
+--- a/sysdeps/unix/sysv/linux/arc/bits/types/__sigset_t.h
++++ b/sysdeps/unix/sysv/linux/arc/bits/types/__sigset_t.h
+@@ -3,7 +3,7 @@
+ #define ____sigset_t_defined
+
+ /* Linux asm-generic syscall ABI expects sigset_t to hold 64 signals. */
+-#define _SIGSET_NWORDS (64 / (8 * sizeof (unsigned long int)))
++#define _SIGSET_NWORDS 2
+ typedef struct
+ {
+ unsigned long int __val[_SIGSET_NWORDS];
+diff --git a/sysdeps/unix/sysv/linux/arc/clone.S b/sysdeps/unix/sysv/linux/arc/clone.S
+index d8c7b93d1c..364fa1edde 100644
+--- a/sysdeps/unix/sysv/linux/arc/clone.S
++++ b/sysdeps/unix/sysv/linux/arc/clone.S
+@@ -31,41 +31,41 @@
+ clone syscall in kernel (ABI: CONFIG_CLONE_BACKWARDS)
+
+ int sys_clone(unsigned long int clone_flags,
+- unsigned long int newsp,
++ unsigned long int newsp,
+ int __user *parent_tidptr,
+ void *tls,
+ int __user *child_tidptr). */
+
+ ENTRY (__clone)
+- cmp r0, 0 /* @fn can't be NULL. */
+- and r1,r1,-4 /* @child_stack be 4 bytes aligned per ABI. */
+- cmp.ne r1, 0 /* @child_stack can't be NULL. */
++ CMPR r0, 0 /* @fn can't be NULL. */
++ ANDR r1, r1, -REGSZ /* @child_stack 4/8 aligned per ABI. */
++ CMPR.ne r1, 0 /* @child_stack can't be NULL. */
+ bz L (__sys_err)
+
+ /* save some of the orig args
+ r0 containing @fn will be clobbered AFTER syscall (with ret val)
+ rest are clobbered BEFORE syscall due to different arg ordering. */
+- mov r10, r0 /* @fn. */
+- mov r11, r3 /* @args. */
+- mov r12, r2 /* @clone_flags. */
+- mov r9, r5 /* @tls. */
++ MOVR r10, r0 /* @fn. */
++ MOVR r11, r3 /* @args. */
++ MOVR r12, r2 /* @clone_flags. */
++ MOVR r9, r5 /* @tls. */
+
+ /* adjust libc args for syscall. */
+
+- mov r0, r2 /* libc @flags is 1st syscall arg. */
+- mov r2, r4 /* libc @ptid. */
+- mov r3, r5 /* libc @tls. */
+- mov r4, r6 /* libc @ctid. */
++ MOVR r0, r2 /* libc @flags is 1st syscall arg. */
++ MOVR r2, r4 /* libc @ptid. */
++ MOVR r3, r5 /* libc @tls. */
++ MOVR r4, r6 /* libc @ctid. */
+ mov r8, __NR_clone
+ ARC_TRAP_INSN
+
+- cmp r0, 0 /* return code : 0 new process, !0 parent. */
++ CMPR r0, 0 /* return code : 0 new process, !0 parent. */
+ beq thread_start_clone
+ blt L (__sys_err2) /* < 0 (signed) error. */
+ j [blink] /* Parent returns. */
+
+ L (__sys_err):
+- mov r0, -EINVAL
++ MOVR r0, -EINVAL
+ L (__sys_err2):
+ /* (1) No need to make -ve kernel error code as positive errno
+ __syscall_error expects the -ve error code returned by kernel
+@@ -87,7 +87,7 @@ thread_start_clone:
+
+ /* Child jumps off to @fn with @arg as argument. */
+ jl.d [r10]
+- mov r0, r11
++ MOVR r0, r11
+
+ /* exit() with result from @fn (already in r0). */
+ mov r8, __NR_exit
+diff --git a/sysdeps/unix/sysv/linux/arc/clone3.S b/sysdeps/unix/sysv/linux/arc/clone3.S
+index 87a8272a39..7fc61524b5 100644
+--- a/sysdeps/unix/sysv/linux/arc/clone3.S
++++ b/sysdeps/unix/sysv/linux/arc/clone3.S
+@@ -37,9 +37,9 @@
+ ENTRY(__clone3)
+
+ /* Save args for the child. */
+- mov r10, r0 /* cl_args */
+- mov r11, r2 /* func */
+- mov r12, r3 /* args */
++ MOVR r10, r0 /* cl_args */
++ MOVR r11, r2 /* func */
++ MOVR r12, r3 /* args */
+
+ /* Sanity check args. */
+ breq r10, 0, L (__sys_err) /* No NULL cl_args pointer. */
+@@ -49,17 +49,17 @@ ENTRY(__clone3)
+ r8: system call number
+ r0: cl_args
+ r1: size */
+- mov r0, r10
++ MOVR r0, r10
+ mov r8, __NR_clone3
+ ARC_TRAP_INSN
+
+- cmp r0, 0
++ CMPR r0, 0
+ beq thread_start_clone3 /* Child returns. */
+ blt L (__sys_err2)
+ j [blink] /* Parent returns. */
+
+ L (__sys_err):
+- mov r0, -EINVAL
++ MOVR r0, -EINVAL
+ L (__sys_err2):
+ b __syscall_error
+ PSEUDO_END (__clone3)
+@@ -74,7 +74,7 @@ thread_start_clone3:
+
+ /* Child jumps off to @fn with @arg as argument. */
+ jl.d [r11]
+- mov r0, r12
++ MOVR r0, r12
+
+ /* exit() with result from @fn (already in r0). */
+ mov r8, __NR_exit
+diff --git a/sysdeps/unix/sysv/linux/arc/getcontext.S b/sysdeps/unix/sysv/linux/arc/getcontext.S
+index eb75c8ce02..851981b64c 100644
+--- a/sysdeps/unix/sysv/linux/arc/getcontext.S
++++ b/sysdeps/unix/sysv/linux/arc/getcontext.S
+@@ -26,39 +26,58 @@
+ ENTRY (__getcontext)
+
+ /* Callee saved registers. */
+- add r2, r0, UCONTEXT_MCONTEXT
+- STR (r13, r2, 37)
+- STR (r14, r2, 36)
+- STR (r15, r2, 35)
+- STR (r16, r2, 34)
+- STR (r17, r2, 33)
+- STR (r18, r2, 32)
+- STR (r19, r2, 31)
+- STR (r20, r2, 30)
+- STR (r21, r2, 29)
+- STR (r22, r2, 28)
+- STR (r23, r2, 27)
+- STR (r24, r2, 26)
++ ADDR r2, r0, UCONTEXT_MCONTEXT
++ STR.as r13, r2, 37
++ STR.as r14, r2, 36
++ STR.as r15, r2, 35
++ STR.as r16, r2, 34
++ STR.as r17, r2, 33
++ STR.as r18, r2, 32
++ STR.as r19, r2, 31
++ STR.as r20, r2, 30
++ STR.as r21, r2, 29
++ STR.as r22, r2, 28
++ STR.as r23, r2, 27
++ STR.as r24, r2, 26
+
+- STR (blink, r2, 7)
+- STR (fp, r2, 8)
+- STR (gp, r2, 9)
+- STR (sp, r2, 23)
++ STR.as blink, r2, 7
++ STR.as fp, r2, 8
++ STR.as gp, r2, 9
++ STR.as sp, r2, 23
++
++#if defined (__ARC_FLOAT_ABI_HARD__)
++ FSTR.as f16, r2, 51
++ FSTR.as f17, r2, 52
++ FSTR.as f18, r2, 53
++ FSTR.as f19, r2, 54
++ FSTR.as f20, r2, 55
++ FSTR.as f21, r2, 56
++ FSTR.as f22, r2, 57
++ FSTR.as f23, r2, 58
++ FSTR.as f24, r2, 59
++ FSTR.as f25, r2, 60
++ FSTR.as f26, r2, 61
++ FSTR.as f27, r2, 62
++ FSTR.as f28, r2, 63
++ FSTR.as f29, r2, 64
++ FSTR.as f30, r2, 65
++ FSTR.as f31, r2, 66
++#endif
+
+ /* Save 0 in r0 placeholder to return 0 when this @ucp activated. */
+- mov r9, 0
+- STR (r9, r2, 22)
++ mov r9, 0
++ STR.as r9, r2, 22
+
+ /* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8). */
+- mov r3, _NSIG8
+- add r2, r0, UCONTEXT_SIGMASK
+- mov r1, 0
+- mov r0, SIG_BLOCK
+- mov r8, __NR_rt_sigprocmask
++ mov r3, _NSIG8
++ ADDR r2, r0, UCONTEXT_SIGMASK
++ mov r1, 0
++ mov r0, SIG_BLOCK
++ mov r8, __NR_rt_sigprocmask
+ ARC_TRAP_INSN
+- brhi r0, -1024, L (call_syscall_err)
++ BRRhi r0, -1024, L (call_syscall_err)
+ j.d [blink]
+- mov r0, 0 /* Success, error handled in .Lcall_syscall_err. */
++ mov r0, 0 /* Success, error handled in .Lcall_syscall_err. */
+
+ PSEUDO_END (__getcontext)
+ weak_alias (__getcontext, getcontext)
+diff --git a/sysdeps/unix/sysv/linux/arc/setcontext.S b/sysdeps/unix/sysv/linux/arc/setcontext.S
+index 12708379d2..e0b8b1a183 100644
+--- a/sysdeps/unix/sysv/linux/arc/setcontext.S
++++ b/sysdeps/unix/sysv/linux/arc/setcontext.S
+@@ -24,46 +24,74 @@
+
+ ENTRY (__setcontext)
+
+- mov r9, r0 /* Stash @ucp across syscall. */
++ MOVR r9, r0 /* Stash @ucp across syscall. */
+
+ /* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, NULL, _NSIG8). */
+ mov r3, _NSIG8
+ mov r2, 0
+- add r1, r0, UCONTEXT_SIGMASK
++ ADDR r1, r0, UCONTEXT_SIGMASK
+ mov r0, SIG_SETMASK
+ mov r8, __NR_rt_sigprocmask
+ ARC_TRAP_INSN
+- brhi r0, -1024, L (call_syscall_err)
++ BRRhi r0, -1024, L (call_syscall_err)
+
+ /* Restore scratch/arg regs for makecontext case. */
+ add r9, r9, UCONTEXT_MCONTEXT
+- LDR (r0, r9, 22)
+- LDR (r1, r9, 21)
+- LDR (r2, r9, 20)
+- LDR (r3, r9, 19)
+- LDR (r4, r9, 18)
+- LDR (r5, r9, 17)
+- LDR (r6, r9, 16)
+- LDR (r7, r9, 15)
++ LDR.as r0, r9, 22
++ LDR.as r1, r9, 21
++ LDR.as r2, r9, 20
++ LDR.as r3, r9, 19
++ LDR.as r4, r9, 18
++ LDR.as r5, r9, 17
++ LDR.as r6, r9, 16
++ LDR.as r7, r9, 15
+
+ /* Restore callee saved registers. */
+- LDR (r13, r9, 37)
+- LDR (r14, r9, 36)
+- LDR (r15, r9, 35)
+- LDR (r16, r9, 34)
+- LDR (r17, r9, 33)
+- LDR (r18, r9, 32)
+- LDR (r19, r9, 31)
+- LDR (r20, r9, 30)
+- LDR (r21, r9, 29)
+- LDR (r22, r9, 28)
+- LDR (r23, r9, 27)
+- LDR (r24, r9, 26)
+-
+- LDR (blink, r9, 7)
+- LDR (fp, r9, 8)
+- LDR (gp, r9, 9)
+- LDR (sp, r9, 23)
++ LDR.as r13, r9, 37
++ LDR.as r14, r9, 36
++ LDR.as r15, r9, 35
++ LDR.as r16, r9, 34
++ LDR.as r17, r9, 33
++ LDR.as r18, r9, 32
++ LDR.as r19, r9, 31
++ LDR.as r20, r9, 30
++ LDR.as r21, r9, 29
++ LDR.as r22, r9, 28
++ LDR.as r23, r9, 27
++ LDR.as r24, r9, 26
++
++ LDR.as blink, r9, 7
++ LDR.as fp, r9, 8
++ LDR.as gp, r9, 9
++ LDR.as sp, r9, 23
++
++#if defined (__ARC_FLOAT_ABI_HARD__)
++ FLDR.as f0, r9, 43
++ FLDR.as f1, r9, 44
++ FLDR.as f2, r9, 45
++ FLDR.as f3, r9, 46
++ FLDR.as f4, r9, 47
++ FLDR.as f5, r9, 48
++ FLDR.as f6, r9, 49
++ FLDR.as f7, r9, 50
++
++ FLDR.as f16, r9, 51
++ FLDR.as f17, r9, 52
++ FLDR.as f18, r9, 53
++ FLDR.as f19, r9, 54
++ FLDR.as f20, r9, 55
++ FLDR.as f21, r9, 56
++ FLDR.as f22, r9, 57
++ FLDR.as f23, r9, 58
++ FLDR.as f24, r9, 59
++ FLDR.as f25, r9, 60
++ FLDR.as f26, r9, 61
++ FLDR.as f27, r9, 62
++ FLDR.as f28, r9, 63
++ FLDR.as f29, r9, 64
++ FLDR.as f30, r9, 66
++ FLDR.as f31, r9, 68
++#endif
+
+ j [blink]
+
+@@ -83,8 +111,8 @@ ENTRY (__startcontext)
+ jl [r14]
+
+ /* If uc_link (r15) call setcontext with that. */
+- mov r0, r15
+- breq r0, 0, 1f
++ MOVR r0, r15
++ BRReq r0, 0, 1f
+
+ bl __setcontext
+ 1:
+diff --git a/sysdeps/unix/sysv/linux/arc/shlib-versions b/sysdeps/unix/sysv/linux/arc/shlib-versions
+index 343c0a0450..92a61e53fc 100644
+--- a/sysdeps/unix/sysv/linux/arc/shlib-versions
++++ b/sysdeps/unix/sysv/linux/arc/shlib-versions
+@@ -1,7 +1,15 @@
+ DEFAULT GLIBC_2.32
+
++%ifdef HAVE_ARC32
++ld=ld-linux-arc32.so.2
++%else
++%ifdef HAVE_ARC64
++ld=ld-linux-arc64.so.2
++%else
+ %ifdef HAVE_ARC_BE
+ ld=ld-linux-arceb.so.2
+ %else
+ ld=ld-linux-arc.so.2
+ %endif
++%endif
++%endif
+diff --git a/sysdeps/unix/sysv/linux/arc/swapcontext.S b/sysdeps/unix/sysv/linux/arc/swapcontext.S
+index 76111af596..ff1741a08a 100644
+--- a/sysdeps/unix/sysv/linux/arc/swapcontext.S
++++ b/sysdeps/unix/sysv/linux/arc/swapcontext.S
+@@ -24,69 +24,88 @@ ENTRY (__swapcontext)
+
+ /* Save context into @oucp pointed to by r0. */
+
+- add r2, r0, UCONTEXT_MCONTEXT
+- STR (r13, r2, 37)
+- STR (r14, r2, 36)
+- STR (r15, r2, 35)
+- STR (r16, r2, 34)
+- STR (r17, r2, 33)
+- STR (r18, r2, 32)
+- STR (r19, r2, 31)
+- STR (r20, r2, 30)
+- STR (r21, r2, 29)
+- STR (r22, r2, 28)
+- STR (r23, r2, 27)
+- STR (r24, r2, 26)
+-
+- STR (blink, r2, 7)
+- STR (fp, r2, 8)
+- STR (gp, r2, 9)
+- STR (sp, r2, 23)
++ ADDR r2, r0, UCONTEXT_MCONTEXT
++ STR.as r13, r2, 37
++ STR.as r14, r2, 36
++ STR.as r15, r2, 35
++ STR.as r16, r2, 34
++ STR.as r17, r2, 33
++ STR.as r18, r2, 32
++ STR.as r19, r2, 31
++ STR.as r20, r2, 30
++ STR.as r21, r2, 29
++ STR.as r22, r2, 28
++ STR.as r23, r2, 27
++ STR.as r24, r2, 26
++
++ STR.as blink, r2, 7
++ STR.as fp, r2, 8
++ STR.as gp, r2, 9
++ STR.as sp, r2, 23
++
++#if defined (__ARC_FLOAT_ABI_HARD__)
++ FSTR.as f16, r2, 51
++ FSTR.as f17, r2, 52
++ FSTR.as f18, r2, 53
++ FSTR.as f19, r2, 54
++ FSTR.as f20, r2, 55
++ FSTR.as f21, r2, 56
++ FSTR.as f22, r2, 57
++ FSTR.as f23, r2, 58
++ FSTR.as f24, r2, 59
++ FSTR.as f25, r2, 60
++ FSTR.as f26, r2, 61
++ FSTR.as f27, r2, 62
++ FSTR.as f28, r2, 63
++ FSTR.as f29, r2, 64
++ FSTR.as f30, r2, 65
++ FSTR.as f31, r2, 66
++#endif
+
+ /* Save 0 in r0 placeholder to return 0 when @oucp activated. */
+- mov r9, 0
+- STR (r9, r2, 22)
++ mov r9, 0
++ STR.as r9, r2, 22
+
+ /* Load context from @ucp. */
+
+- mov r9, r1 /* Safekeep @ucp across syscall. */
++ MOVR r9, r1 /* Safekeep @ucp across syscall. */
+
+ /* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask, _NSIG8) */
+- mov r3, _NSIG8
+- add r2, r0, UCONTEXT_SIGMASK
+- add r1, r1, UCONTEXT_SIGMASK
+- mov r0, SIG_SETMASK
+- mov r8, __NR_rt_sigprocmask
++ mov r3, _NSIG8
++ ADDR r2, r0, UCONTEXT_SIGMASK
++ ADDR r1, r1, UCONTEXT_SIGMASK
++ mov r0, SIG_SETMASK
++ mov r8, __NR_rt_sigprocmask
+ ARC_TRAP_INSN
+- brhi r0, -1024, L (call_syscall_err)
+-
+- add r9, r9, UCONTEXT_MCONTEXT
+- LDR (r0, r9, 22)
+- LDR (r1, r9, 21)
+- LDR (r2, r9, 20)
+- LDR (r3, r9, 19)
+- LDR (r4, r9, 18)
+- LDR (r5, r9, 17)
+- LDR (r6, r9, 16)
+- LDR (r7, r9, 15)
+-
+- LDR (r13, r9, 37)
+- LDR (r14, r9, 36)
+- LDR (r15, r9, 35)
+- LDR (r16, r9, 34)
+- LDR (r17, r9, 33)
+- LDR (r18, r9, 32)
+- LDR (r19, r9, 31)
+- LDR (r20, r9, 30)
+- LDR (r21, r9, 29)
+- LDR (r22, r9, 28)
+- LDR (r23, r9, 27)
+- LDR (r24, r9, 26)
+-
+- LDR (blink, r9, 7)
+- LDR (fp, r9, 8)
+- LDR (gp, r9, 9)
+- LDR (sp, r9, 23)
++ BRRhi r0, -1024, L (call_syscall_err)
++
++ ADDR r9, r9, UCONTEXT_MCONTEXT
++ LDR.as r0, r9, 22
++ LDR.as r1, r9, 21
++ LDR.as r2, r9, 20
++ LDR.as r3, r9, 19
++ LDR.as r4, r9, 18
++ LDR.as r5, r9, 17
++ LDR.as r6, r9, 16
++ LDR.as r7, r9, 15
++
++ LDR.as r13, r9, 37
++ LDR.as r14, r9, 36
++ LDR.as r15, r9, 35
++ LDR.as r16, r9, 34
++ LDR.as r17, r9, 33
++ LDR.as r18, r9, 32
++ LDR.as r19, r9, 31
++ LDR.as r20, r9, 30
++ LDR.as r21, r9, 29
++ LDR.as r22, r9, 28
++ LDR.as r23, r9, 27
++ LDR.as r24, r9, 26
++
++ LDR.as blink, r9, 7
++ LDR.as fp, r9, 8
++ LDR.as gp, r9, 9
++ LDR.as sp, r9, 23
+
+ j [blink]
+
+diff --git a/sysdeps/unix/sysv/linux/arc/sys/ucontext.h b/sysdeps/unix/sysv/linux/arc/sys/ucontext.h
+index 831b81a922..3a0f1d4aba 100644
+--- a/sysdeps/unix/sysv/linux/arc/sys/ucontext.h
++++ b/sysdeps/unix/sysv/linux/arc/sys/ucontext.h
+@@ -42,6 +42,7 @@ typedef struct
+ unsigned long int __efa;
+ unsigned long int __stop_pc;
+ unsigned long int __r30, __r58, __r59;
++ unsigned long int __fpr[32];
+ } mcontext_t;
+
+ /* Userlevel context. */
+diff --git a/sysdeps/unix/sysv/linux/arc/syscall.S b/sysdeps/unix/sysv/linux/arc/syscall.S
+index c6ca329e9a..db1ffdad2a 100644
+--- a/sysdeps/unix/sysv/linux/arc/syscall.S
++++ b/sysdeps/unix/sysv/linux/arc/syscall.S
+@@ -19,15 +19,15 @@
+ #include <sysdep.h>
+
+ ENTRY (syscall)
+- mov_s r8, r0
+- mov_s r0, r1
+- mov_s r1, r2
+- mov_s r2, r3
+- mov_s r3, r4
+- mov_s r4, r5
+- mov_s r5, r6
++ MOVR r8, r0
++ MOVR r0, r1
++ MOVR r1, r2
++ MOVR r2, r3
++ MOVR r3, r4
++ MOVR r4, r5
++ MOVR r5, r6
+
+ ARC_TRAP_INSN
+- brhi r0, -4096, L (call_syscall_err)
++ BRRhi r0, -4096, L (call_syscall_err)
+ j [blink]
+ PSEUDO_END (syscall)
+diff --git a/sysdeps/unix/sysv/linux/arc/sysdep.h b/sysdeps/unix/sysv/linux/arc/sysdep.h
+index 7f90d64124..14d11f038b 100644
+--- a/sysdeps/unix/sysv/linux/arc/sysdep.h
++++ b/sysdeps/unix/sysv/linux/arc/sysdep.h
+@@ -26,6 +26,8 @@
+
+ /* "workarounds" for generic code needing to handle 64-bit time_t. */
+
++#ifndef __ARC64_ARCH64__
++
+ /* Fix sysdeps/unix/sysv/linux/clock_getcpuclockid.c. */
+ #define __NR_clock_getres __NR_clock_getres_time64
+ /* Fix sysdeps/nptl/lowlevellock-futex.h. */
+@@ -43,6 +45,8 @@
+ /* Hack sysdeps/unix/sysv/linux/generic/utimes.c. */
+ #define __NR_utimensat __NR_utimensat_time64
+
++#endif
++
+ /* For RTLD_PRIVATE_ERRNO. */
+ #include <dl-sysdep.h>
+
+@@ -59,7 +63,7 @@
+ # undef PSEUDO
+ # define PSEUDO(name, syscall_name, args) \
+ PSEUDO_NOERRNO(name, syscall_name, args) ASM_LINE_SEP \
+- brhi r0, -4096, L (call_syscall_err) ASM_LINE_SEP
++ BRRhi r0, -4096, L (call_syscall_err) ASM_LINE_SEP
+
+ # define ret j_s [blink]
+
+@@ -98,7 +102,7 @@
+
+ /* Don't set errno, return kernel error (in errno form) or zero. */
+ # define ret_ERRVAL \
+- rsub r0, r0, 0 ASM_LINE_SEP \
++ SUBR r0, 0, r0 ASM_LINE_SEP \
+ ret_NOERRNO
+
+ # undef PSEUDO_END_ERRVAL
+@@ -117,12 +121,12 @@
+
+ # define SYSCALL_ERROR_HANDLER \
+ L (call_syscall_err): ASM_LINE_SEP \
+- push_s blink ASM_LINE_SEP \
+- cfi_adjust_cfa_offset (4) ASM_LINE_SEP \
++ PUSHR blink ASM_LINE_SEP \
++ cfi_adjust_cfa_offset (REGSZ) ASM_LINE_SEP \
+ cfi_rel_offset (blink, 0) ASM_LINE_SEP \
+ CALL_ERRNO_SETTER_C ASM_LINE_SEP \
+- pop_s blink ASM_LINE_SEP \
+- cfi_adjust_cfa_offset (-4) ASM_LINE_SEP \
++ POPR blink ASM_LINE_SEP \
++ cfi_adjust_cfa_offset (-REGSZ) ASM_LINE_SEP \
+ cfi_restore (blink) ASM_LINE_SEP \
+ j_s [blink]
+
+diff --git a/sysdeps/unix/sysv/linux/arc/vfork.S b/sysdeps/unix/sysv/linux/arc/vfork.S
+index 57b85988e3..57bd8d3d81 100644
+--- a/sysdeps/unix/sysv/linux/arc/vfork.S
++++ b/sysdeps/unix/sysv/linux/arc/vfork.S
+@@ -28,11 +28,11 @@
+
+ ENTRY (__vfork)
+ mov r0, CLONE_FLAGS_FOR_VFORK
+- mov_s r1, sp
++ MOVR r1, sp
+ mov r8, __NR_clone
+ ARC_TRAP_INSN
+
+- cmp r0, 0
++ CMPR r0, 0
+ jge [blink] ; child continues
+
+ b __syscall_error
+diff --git a/timezone/zic.c b/timezone/zic.c
+index 2875b5544c..3d606c8e6e 100644
+--- a/timezone/zic.c
++++ b/timezone/zic.c
+@@ -39,7 +39,7 @@ typedef int_fast64_t zic_t;
+ #include <sys/stat.h>
+ #endif
+ #ifdef S_IRUSR
+-#define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
++#define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH|S_IWOTH)
+ #else
+ #define MKDIR_UMASK 0755
+ #endif
+--
+2.31.1
+
diff --git a/toolchain/glibc/patches/2.38/m68k-m68040.patch b/toolchain/glibc/patches/2.38/m68k-m68040.patch
new file mode 100644
index 000000000..bfa0b3da8
--- /dev/null
+++ b/toolchain/glibc/patches/2.38/m68k-m68040.patch
@@ -0,0 +1,59 @@
+diff -Nur glibc-2.38.orig/sysdeps/m68k/m680x0/bits/flt-eval-method.h glibc-2.38/sysdeps/m68k/m680x0/bits/flt-eval-method.h
+--- glibc-2.38.orig/sysdeps/m68k/m680x0/bits/flt-eval-method.h 2023-07-31 19:54:16.000000000 +0200
++++ glibc-2.38/sysdeps/m68k/m680x0/bits/flt-eval-method.h 1970-01-01 01:00:00.000000000 +0100
+@@ -1,25 +0,0 @@
+-/* Define __GLIBC_FLT_EVAL_METHOD. M68K version.
+- Copyright (C) 2016-2023 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- 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
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library; if not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#ifndef _MATH_H
+-# error "Never use <bits/flt-eval-method.h> directly; include <math.h> instead."
+-#endif
+-
+-/* The m68k FPUs evaluate all values in the 96-bit floating-point
+- format which is also available for the user as 'long double'. */
+-#define __GLIBC_FLT_EVAL_METHOD 2
+diff -Nur glibc-2.38.orig/sysdeps/m68k/m680x0/m68020/wordcopy.S glibc-2.38/sysdeps/m68k/m680x0/m68020/wordcopy.S
+--- glibc-2.38.orig/sysdeps/m68k/m680x0/m68020/wordcopy.S 2023-07-31 19:54:16.000000000 +0200
++++ glibc-2.38/sysdeps/m68k/m680x0/m68020/wordcopy.S 1970-01-01 01:00:00.000000000 +0100
+@@ -1 +0,0 @@
+-/* Empty, not needed. */
+diff -Nur glibc-2.38.orig/sysdeps/m68k/wordcopy.c glibc-2.38/sysdeps/m68k/wordcopy.c
+--- glibc-2.38.orig/sysdeps/m68k/wordcopy.c 1970-01-01 01:00:00.000000000 +0100
++++ glibc-2.38/sysdeps/m68k/wordcopy.c 2023-08-10 16:23:10.972526508 +0200
+@@ -0,0 +1,21 @@
++/* Definitions for memory copy functions. Motorola 68020 version.
++ Copyright (C) 2023 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ 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
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#if !defined(__mc68020__) && !defined(mc68020)
++#include <string/wordcopy.c>
++#endif
diff --git a/toolchain/gmp/Makefile.inc b/toolchain/gmp/Makefile.inc
index 88087b7e3..c7f99320b 100644
--- a/toolchain/gmp/Makefile.inc
+++ b/toolchain/gmp/Makefile.inc
@@ -2,7 +2,7 @@
# material, please see the LICENCE file in the top-level directory.
PKG_NAME:= gmp
-PKG_VERSION:= 6.1.2
+PKG_VERSION:= 6.3.0
PKG_RELEASE:= 1
-PKG_HASH:= 87b565e89a9a684fe4ebeeddb8399dce2599f9c9049854ca8c0dfbdea0e21912
+PKG_HASH:= a3c2b80201b89e68616f4ad30bc66aee4927c3ce50e33929ca819d5c43538898
PKG_SITES:= ${MASTER_SITE_GNU:=gmp/}
diff --git a/toolchain/mpfr/Makefile.inc b/toolchain/mpfr/Makefile.inc
index 74b888e95..4aa9f0e9b 100644
--- a/toolchain/mpfr/Makefile.inc
+++ b/toolchain/mpfr/Makefile.inc
@@ -2,7 +2,7 @@
# material, please see the LICENCE file in the top-level directory.
PKG_NAME:= mpfr
-PKG_VERSION:= 4.1.0
+PKG_VERSION:= 4.2.1
PKG_RELEASE:= 1
-PKG_HASH:= 0c98a3f1732ff6ca4ea690552079da9c597872d30e96ec28414ee23c95558a7f
+PKG_HASH:= 277807353a6726978996945af13e52829e3abd7a9a5b7fb2793894e18f1fcbb2
PKG_SITES:= http://www.mpfr.org/mpfr-current/
diff --git a/toolchain/musl/Makefile.inc b/toolchain/musl/Makefile.inc
index b5ce58af0..b5e1800f0 100644
--- a/toolchain/musl/Makefile.inc
+++ b/toolchain/musl/Makefile.inc
@@ -8,10 +8,10 @@ PKG_RELEASE:= 1
PKG_SITES:= git://git.musl-libc.org/musl
DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
endif
-ifeq ($(ADK_TARGET_LIB_MUSL_1_2_2),y)
-PKG_VERSION:= 1.2.2
+ifeq ($(ADK_TARGET_LIB_MUSL_1_2_5),y)
+PKG_VERSION:= 1.2.5
PKG_RELEASE:= 1
-PKG_HASH:= 9b969322012d796dc23dda27a35866034fa67d8fb67e0e2c45c913c3d43219dd
+PKG_HASH:= a9a118bbe84d8764da0ea0d28b3ab3fae8477fc7e4085d90102b8596fc7c75e4
PKG_SITES:= http://www.musl-libc.org/releases/
DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
endif
diff --git a/toolchain/newlib/Makefile.inc b/toolchain/newlib/Makefile.inc
index 591377022..c9ce3a2ad 100644
--- a/toolchain/newlib/Makefile.inc
+++ b/toolchain/newlib/Makefile.inc
@@ -8,17 +8,10 @@ PKG_RELEASE:= 1
PKG_SITES:= git://sourceware.org/git/newlib-cygwin.git
DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
endif
-ifeq ($(ADK_TARGET_LIB_NEWLIB_4_1_0),y)
-PKG_VERSION:= 4.1.0
+ifeq ($(ADK_TARGET_LIB_NEWLIB_4_4_0),y)
+PKG_VERSION:= 4.4.0.20231231
PKG_RELEASE:= 1
-PKG_HASH:= f296e372f51324224d387cc116dc37a6bd397198756746f93a2b02e9a5d40154
+PKG_HASH:= 0c166a39e1bf0951dfafcd68949fe0e4b6d3658081d6282f39aeefc6310f2f13
PKG_SITES:= ftp://sourceware.org/pub/newlib/
DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.gz
endif
-ifeq ($(ADK_TARGET_LIB_NEWLIB_XTENSA),y)
-PKG_VERSION:= xtensa
-PKG_GIT:= branch
-PKG_RELEASE:= 1
-PKG_SITES:= https://github.com/jcmvbkbc/newlib-xtensa.git
-DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.xz
-endif
diff --git a/toolchain/newlib/patches/3.1.0/fix-tooldir.patch b/toolchain/newlib/patches/3.1.0/fix-tooldir.patch
deleted file mode 100644
index 652f7494b..000000000
--- a/toolchain/newlib/patches/3.1.0/fix-tooldir.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -Nur newlib-2.2.0-1.orig/configure newlib-2.2.0-1/configure
---- newlib-2.2.0-1.orig/configure 2014-07-05 23:09:07.000000000 +0200
-+++ newlib-2.2.0-1/configure 2015-11-25 06:33:11.461178398 +0100
-@@ -6985,7 +6985,7 @@
-
- # Some systems (e.g., one of the i386-aix systems the gas testers are
- # using) don't handle "\$" correctly, so don't use it here.
--tooldir='${exec_prefix}'/${target_noncanonical}
-+tooldir='${exec_prefix}'
- build_tooldir=${tooldir}
-
- # Create a .gdbinit file which runs the one in srcdir
diff --git a/toolchain/newlib/patches/git/fix-tooldir.patch b/toolchain/newlib/patches/git/fix-tooldir.patch
deleted file mode 100644
index 652f7494b..000000000
--- a/toolchain/newlib/patches/git/fix-tooldir.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -Nur newlib-2.2.0-1.orig/configure newlib-2.2.0-1/configure
---- newlib-2.2.0-1.orig/configure 2014-07-05 23:09:07.000000000 +0200
-+++ newlib-2.2.0-1/configure 2015-11-25 06:33:11.461178398 +0100
-@@ -6985,7 +6985,7 @@
-
- # Some systems (e.g., one of the i386-aix systems the gas testers are
- # using) don't handle "\$" correctly, so don't use it here.
--tooldir='${exec_prefix}'/${target_noncanonical}
-+tooldir='${exec_prefix}'
- build_tooldir=${tooldir}
-
- # Create a .gdbinit file which runs the one in srcdir
diff --git a/toolchain/newlib/patches/newlib-xtensa/fix-tooldir.patch b/toolchain/newlib/patches/newlib-xtensa/fix-tooldir.patch
deleted file mode 100644
index 1ad0f373d..000000000
--- a/toolchain/newlib/patches/newlib-xtensa/fix-tooldir.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -Nur newlib-xtensa.orig/configure newlib-xtensa/configure
---- newlib-xtensa.orig/configure 2017-12-29 15:26:12.000000000 +0100
-+++ newlib-xtensa/configure 2017-12-29 15:35:01.420208845 +0100
-@@ -6847,7 +6847,7 @@
-
- # Some systems (e.g., one of the i386-aix systems the gas testers are
- # using) don't handle "\$" correctly, so don't use it here.
--tooldir='${exec_prefix}'/${target_noncanonical}
-+tooldir='${exec_prefix}'
- build_tooldir=${tooldir}
-
- # Create a .gdbinit file which runs the one in srcdir
diff --git a/toolchain/uclibc-ng/Makefile b/toolchain/uclibc-ng/Makefile
index e07ab8ece..6b1fd31ce 100644
--- a/toolchain/uclibc-ng/Makefile
+++ b/toolchain/uclibc-ng/Makefile
@@ -50,8 +50,13 @@ UCLIBC_MAKEOPTS+= -j${ADK_MAKE_JOBS}
endif
$(WRKBUILD)/.configured: $(WRKBUILD)/.prepared
+ifeq ($(ADK_TARGET_WITH_MMU),y)
PATH='$(HOST_PATH)' sed -e 's^KERNEL_HEADERS.*$$KERNEL_HEADERS=\"${STAGING_TARGET_DIR}/usr/include\"' \
$(ADK_TOPDIR)/target/$(ADK_TARGET_ARCH)/uclibc-ng.config >${WRKBUILD}/.config
+else
+ PATH='$(HOST_PATH)' sed -e 's^KERNEL_HEADERS.*$$KERNEL_HEADERS=\"${STAGING_TARGET_DIR}/usr/include\"' \
+ $(ADK_TOPDIR)/target/$(ADK_TARGET_ARCH)/uclibc-ng-nommu.config >${WRKBUILD}/.config
+endif
$(SED) 's^.*\(CROSS_COMPILER_PREFIX\).*^\1=\"$(TARGET_CROSS)\"^' ${WRKBUILD}/.config
ifeq ($(ADK_TARGET_ENDIAN),little)
$(SED) 's/.*\(ARCH_LITTLE_ENDIAN\).*/\1=y/' ${WRKBUILD}/.config
@@ -80,8 +85,16 @@ ifeq ($(ADK_TARGET_HARD_FLOAT_DP),y)
$(SED) 's/.*\(UCLIBC_HAS_FPU\).*/\1=y/' ${WRKBUILD}/.config
$(SED) 's/.*\(UCLIBC_HAS_SOFT_FLOAT\).*/# \1 is not set/' ${WRKBUILD}/.config
endif
+ifeq ($(ADK_TARGET_BINFMT_ELF),y)
+ $(SED) 's/.*\(UCLIBC_FORMAT_ELF\).*/\1=y/' ${WRKBUILD}/.config
+ $(SED) 's/.*\(UCLIBC_FORMAT_FDPIC_ELF\).*/# \1 is not set/' ${WRKBUILD}/.config
+ $(SED) 's/.*\(UCLIBC_FORMAT_FLAT\).*/# \1 is not set/' ${WRKBUILD}/.config
+ $(SED) 's/.*\(UCLIBC_FORMAT_FLAT_SEP_DATA\).*/# \1 is not set/' ${WRKBUILD}/.config
+ $(SED) 's/.*\(UCLIBC_FORMAT_SHARED_FLAT\).*/# \1 is not set/' ${WRKBUILD}/.config
+endif
ifeq ($(ADK_TARGET_BINFMT_FDPIC),y)
$(SED) 's/.*\(UCLIBC_FORMAT_FDPIC_ELF\).*/\1=y/' ${WRKBUILD}/.config
+ $(SED) 's/.*\(UCLIBC_FORMAT_ELF\).*/# \1 is not set/' ${WRKBUILD}/.config
$(SED) 's/.*\(UCLIBC_FORMAT_FLAT\).*/# \1 is not set/' ${WRKBUILD}/.config
$(SED) 's/.*\(UCLIBC_FORMAT_FLAT_SEP_DATA\).*/# \1 is not set/' ${WRKBUILD}/.config
$(SED) 's/.*\(UCLIBC_FORMAT_SHARED_FLAT\).*/# \1 is not set/' ${WRKBUILD}/.config
@@ -174,12 +187,19 @@ endif
# arc
ifeq ($(ADK_TARGET_ARCH_ARC),y)
ifeq ($(ADK_TARGET_CPU_ARC_ARC700),y)
- $(SED) 's/.*\(CONFIG_ARC_CPU_HS\).*/# \1 is not set/' ${WRKBUILD}/.config
- $(SED) 's/.*\(CONFIG_ARC_CPU_700\).*/\1=y/' ${WRKBUILD}/.config
+ $(SED) 's/.*\(CONFIG_ARC_PAGE_SIZE_16K\).*/# \1 is not set/' ${WRKBUILD}/.config
+ $(SED) 's/.*\(CONFIG_ARC_PAGE_SIZE_4K\).*/# \1 is not set/' ${WRKBUILD}/.config
+ $(SED) 's/.*\(CONFIG_ARC_PAGE_SIZE_8K\).*/\1=y/' ${WRKBUILD}/.config
+endif
+ifeq ($(ADK_TARGET_CPU_ARC_ARCHS),y)
+ $(SED) 's/.*\(CONFIG_ARC_PAGE_SIZE_16K\).*/# \1 is not set/' ${WRKBUILD}/.config
+ $(SED) 's/.*\(CONFIG_ARC_PAGE_SIZE_4K\).*/# \1 is not set/' ${WRKBUILD}/.config
+ $(SED) 's/.*\(CONFIG_ARC_PAGE_SIZE_8K\).*/\1=y/' ${WRKBUILD}/.config
endif
-ifeq ($(ADK_TARGET_CPU_ARC_ARC_HS),y)
- $(SED) 's/.*\(CONFIG_ARC_CPU_700\).*/# \1 is not set/' ${WRKBUILD}/.config
- $(SED) 's/.*\(CONFIG_ARC_CPU_HS\).*/\1=y/' ${WRKBUILD}/.config
+ifeq ($(ADK_TARGET_CPU_ARC_ARC32),y)
+ $(SED) 's/.*\(CONFIG_ARC_PAGE_SIZE_16K\).*/# \1 is not set/' ${WRKBUILD}/.config
+ $(SED) 's/.*\(CONFIG_ARC_PAGE_SIZE_8K\).*/# \1 is not set/' ${WRKBUILD}/.config
+ $(SED) 's/.*\(CONFIG_ARC_PAGE_SIZE_4K\).*/\1=y/' ${WRKBUILD}/.config
endif
endif
@@ -368,6 +388,8 @@ $(WRKBUILD)/.installed: $(WRKBUILD)/.compiled
UCLIBC_EXTRA_LDFLAGS="$(TARGET_LDFLAGS)" \
VERBOSE=1 \
install_runtime install_dev
+ ln -f ${STAGING_TARGET_DIR}/usr/lib/crt1.o \
+ ${STAGING_TARGET_DIR}/usr/lib/Scrt1.o
ifeq ($(ADK_TARGET_LIBC_UTILS),y)
PATH='$(HOST_PATH)' $(MAKE) -C $(WRKBUILD) \
ARCH="$(ADK_TARGET_ARCH)" \
diff --git a/toolchain/uclibc-ng/Makefile.inc b/toolchain/uclibc-ng/Makefile.inc
index ad73b49bd..c4b4745fa 100644
--- a/toolchain/uclibc-ng/Makefile.inc
+++ b/toolchain/uclibc-ng/Makefile.inc
@@ -5,12 +5,12 @@ PKG_NAME:= uClibc-ng
ifeq ($(ADK_LIBC_VERSION),git)
PKG_VERSION:= git
PKG_RELEASE:= 1
-PKG_SITES:= git://uclibc-ng.org/git/uclibc-ng
+PKG_SITES:= https://git.uclibc-ng.org/git/uclibc-ng.git
endif
-ifeq ($(ADK_TARGET_LIB_UCLIBC_NG_1_0_39),y)
-PKG_VERSION:= 1.0.39
+ifeq ($(ADK_TARGET_LIB_UCLIBC_NG_1_0_47),y)
+PKG_VERSION:= 1.0.47
PKG_RELEASE:= 1
-PKG_SITES:= http://downloads.uclibc-ng.org/releases/1.0.39/
-PKG_HASH:= cb089dfe14867a38f222d6428e85d0e1191dcbb66dd9b1a671484f6bc7c81920
+PKG_SITES:= http://downloads.uclibc-ng.org/releases/1.0.47/
+PKG_HASH:= c58640ba7c2ce70f09574365bc8039cf580b52e1ce369db527376891b2249028
endif
-DISTFILES:= $(PKG_NAME)-$(PKG_VERSION).tar.xz
+DISTFILES:= $(PKG_NAME)-$(PKG_VERSION).tar.gz