[toolchain]: replace gcc 4.5.2 support with 4.6.1
authorImre Kaloz <kaloz@openwrt.org>
Fri, 1 Jul 2011 11:43:15 +0000 (11:43 +0000)
committerImre Kaloz <kaloz@openwrt.org>
Fri, 1 Jul 2011 11:43:15 +0000 (11:43 +0000)
SVN-Revision: 27333

28 files changed:
toolchain/gcc/Config.in
toolchain/gcc/Config.version
toolchain/gcc/common.mk
toolchain/gcc/final/Makefile
toolchain/gcc/patches/4.5.2/002-fix_pr44392.patch [deleted file]
toolchain/gcc/patches/4.5.2/100-uclibc-conf.patch [deleted file]
toolchain/gcc/patches/4.5.2/301-missing-execinfo_h.patch [deleted file]
toolchain/gcc/patches/4.5.2/302-c99-snprintf.patch [deleted file]
toolchain/gcc/patches/4.5.2/305-libmudflap-susv3-legacy.patch [deleted file]
toolchain/gcc/patches/4.5.2/600-ubicom_support.patch [deleted file]
toolchain/gcc/patches/4.5.2/810-arm-softfloat-libgcc.patch [deleted file]
toolchain/gcc/patches/4.5.2/820-libgcc_pic.patch [deleted file]
toolchain/gcc/patches/4.5.2/910-mbsd_multi.patch [deleted file]
toolchain/gcc/patches/4.5.2/993-arm_insn-opinit-RTX_CODE-fixup.patch [deleted file]
toolchain/gcc/patches/4.5.2/995-fa526.patch [deleted file]
toolchain/gcc/patches/4.5.2/999-coldfire.patch [deleted file]
toolchain/gcc/patches/4.6.1/100-uclibc-conf.patch [new file with mode: 0644]
toolchain/gcc/patches/4.6.1/301-missing-execinfo_h.patch [new file with mode: 0644]
toolchain/gcc/patches/4.6.1/302-c99-snprintf.patch [new file with mode: 0644]
toolchain/gcc/patches/4.6.1/305-libmudflap-susv3-legacy.patch [new file with mode: 0644]
toolchain/gcc/patches/4.6.1/600-ubicom_support.patch [new file with mode: 0644]
toolchain/gcc/patches/4.6.1/810-arm-softfloat-libgcc.patch [new file with mode: 0644]
toolchain/gcc/patches/4.6.1/820-libgcc_pic.patch [new file with mode: 0644]
toolchain/gcc/patches/4.6.1/830-arm_unbreak_armv4t.patch [new file with mode: 0644]
toolchain/gcc/patches/4.6.1/840-armv4_pass_fix-v4bx_to_ld.patch [new file with mode: 0644]
toolchain/gcc/patches/4.6.1/910-mbsd_multi.patch [new file with mode: 0644]
toolchain/gcc/patches/4.6.1/993-arm_insn-opinit-RTX_CODE-fixup.patch [new file with mode: 0644]
toolchain/gcc/patches/4.6.1/999-coldfire.patch [new file with mode: 0644]

index 6b45da55bd20cb26de1e92c3e0badc6633ca81f2..9e6d0ed86b55bf301e0774b234aa10d161c33310 100644 (file)
@@ -15,8 +15,8 @@ choice
        config GCC_VERSION_4_4_5
                bool "gcc 4.4.5"
 
-       config GCC_VERSION_4_5_2
-               bool "gcc 4.5.2"
+       config GCC_VERSION_4_6_1
+               bool "gcc 4.6.1"
 
        config GCC_VERSION_LINARO
                bool "gcc 4.5.x with Linaro enhancements"
@@ -36,7 +36,7 @@ endchoice
 config GCC_USE_GRAPHITE
        bool
        prompt "Compile in support for the new Graphite framework in GCC 4.4+" if TOOLCHAINOPTS
-       depends GCC_VERSION_4_4 || GCC_VERSION_4_5
+       depends GCC_VERSION_4_4 || GCC_VERSION_4_5 || GCC_VERSION_4_6
 
 config GCC_USE_SYSTEM_PPL_CLOOG
        bool
index 14712d949b271568d8e382f0b58cc68a93bd3c8a..c8aff02203461d0f19c6c8baa0797b3153c772d9 100644 (file)
@@ -26,7 +26,7 @@ config GCC_VERSION
        default "4.3.5"     if GCC_VERSION_4_3_5
        default "4.4.1+cs"  if GCC_VERSION_4_4_1_CS
        default "4.4.5"     if GCC_VERSION_4_4_5
-       default "4.5.2"     if GCC_VERSION_4_5_2
+       default "4.6.1"     if GCC_VERSION_4_6_1
        default "linaro"    if GCC_VERSION_LINARO
        default "llvm"      if GCC_VERSION_LLVM
        default "linaro"
@@ -43,9 +43,12 @@ config GCC_VERSION_4_4
 
 config GCC_VERSION_4_5
        bool
-       default y       if GCC_VERSION_4_5_2
        default y       if GCC_VERSION_LINARO
 
+config GCC_VERSION_4_6
+       bool
+       default y       if GCC_VERSION_4_6_1
+
 if !TOOLCHAINOPTS
 
        config GCC_VERSION_4_3_3_CS
index f0e22bf895d3e581bede2e5c6dc5f9fbee69be71..a71f2981da3045c98c7e85eccffd3e8d05e5535d 100644 (file)
@@ -2,7 +2,7 @@
 # Copyright (C) 2002-2003 Erik Andersen <andersen@uclibc.org>
 # Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org>
 # Copyright (C) 2005-2006 Felix Fietkau <nbd@openwrt.org>
-# Copyright (C) 2006-2010 OpenWrt.org
+# Copyright (C) 2006-2011 OpenWrt.org
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -60,8 +60,8 @@ else
   ifeq ($(PKG_VERSION),4.4.5)
     PKG_MD5SUM:=44b3192c4c584b9be5243d9e8e7e0ed1
   endif
-  ifeq ($(PKG_VERSION),4.5.2)
-  PKG_MD5SUM:=d6559145853fbaaa0fd7556ed93bce9a
+  ifeq ($(PKG_VERSION),4.6.1)
+  PKG_MD5SUM:=c57a9170c677bf795bdc04ed796ca491
   endif
 endif
 endif
@@ -114,7 +114,7 @@ GCC_CONFIGURE:= \
                $(if $(CONFIG_GCC_VERSION_LLVM),--enable-llvm=$(BUILD_DIR_BASE)/host/llvm) \
                $(if $(CONFIG_GCC_VERSION_4_3_3_CS)$(CONFIG_GCC_VERSION_4_4_1_CS),--enable-poison-system-directories)
 
-ifneq ($(CONFIG_GCC_VERSION_4_4)$(CONFIG_GCC_VERSION_4_5),)
+ifneq ($(CONFIG_GCC_VERSION_4_4)$(CONFIG_GCC_VERSION_4_5)$(CONFIG_GCC_VERSION_4_6),)
   ifneq ($(CONFIG_mips)$(CONFIG_mipsel),)
     GCC_CONFIGURE += --with-mips-plt
   endif
@@ -128,7 +128,7 @@ ifeq ($(CONFIG_GCC_LLVM),)
                --disable-decimal-float
 endif
 
-ifneq ($(CONFIG_GCC_VERSION_4_5),)
+ifneq ($(CONFIG_GCC_VERSION_4_5)$(CONFIG_GCC_VERSION_4_6),)
   GCC_BUILD_TARGET_LIBGCC:=y
   GCC_CONFIGURE+= \
                 --with-gmp=$(TOPDIR)/staging_dir/host \
index 337f7ab1c5deaa74aa3a9d389eb493bdb3765e00..dc884ab9c101c996fe6a5b7a3388de73afc17e9d 100644 (file)
@@ -8,7 +8,7 @@ GCC_CONFIGURE += \
        --enable-threads \
        --with-slibdir=$(TOOLCHAIN_DIR)/lib
 
-ifneq ($(CONFIG_GCC_VERSION_4_5),)
+ifneq ($(CONFIG_GCC_VERSION_4_5)$(CONFIG_GCC_VERSION_4_6),)
   GCC_CONFIGURE += \
        --enable-lto \
        --with-libelf=$(TOPDIR)/staging_dir/host
diff --git a/toolchain/gcc/patches/4.5.2/002-fix_pr44392.patch b/toolchain/gcc/patches/4.5.2/002-fix_pr44392.patch
deleted file mode 100644 (file)
index 4ad6c44..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
->From d0557763b0713a4c006bd2405eede3924569cafd Mon Sep 17 00:00:00 2001
-From: Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
-Date: Mon, 5 Jul 2010 11:28:49 +0100
-Subject: [PATCH 2/2] Fix PR44392
-
----
- gcc/config/arm/arm.md |   43 +++++++++++++++++++------------------------
- 1 files changed, 19 insertions(+), 24 deletions(-)
-
-diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
-index 2096ec6..f0348f3 100644
---- a/gcc/config/arm/arm.md
-+++ b/gcc/config/arm/arm.md
-@@ -11318,34 +11318,29 @@
- (define_expand "bswapsi2"
-   [(set (match_operand:SI 0 "s_register_operand" "=r")
-       (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
--"TARGET_EITHER"
-+"TARGET_EITHER && (arm_arch6 || !optimize_size)"
- "
--  if (!arm_arch6)
--    {
--      if (!optimize_size)
--      {
--        rtx op2 = gen_reg_rtx (SImode);
--        rtx op3 = gen_reg_rtx (SImode);
-+    if (!arm_arch6)
-+      {
-+      rtx op2 = gen_reg_rtx (SImode);
-+      rtx op3 = gen_reg_rtx (SImode);
--        if (TARGET_THUMB)
--          {
--            rtx op4 = gen_reg_rtx (SImode);
--            rtx op5 = gen_reg_rtx (SImode);
-+      if (TARGET_THUMB)
-+        {
-+          rtx op4 = gen_reg_rtx (SImode);
-+          rtx op5 = gen_reg_rtx (SImode);
--            emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
--                                             op2, op3, op4, op5));
--          }
--        else
--          {
--            emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
--                                           op2, op3));
--          }
-+          emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
-+                                           op2, op3, op4, op5));
-+        }
-+      else
-+        {
-+          emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
-+                                         op2, op3));
-+        }
--        DONE;
--      }
--      else
--      FAIL;
--    }
-+      DONE;
-+      }
-   "
- )
--- 
-1.6.2
-
diff --git a/toolchain/gcc/patches/4.5.2/100-uclibc-conf.patch b/toolchain/gcc/patches/4.5.2/100-uclibc-conf.patch
deleted file mode 100644 (file)
index 7c6b791..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
---- a/contrib/regression/objs-gcc.sh
-+++ b/contrib/regression/objs-gcc.sh
-@@ -106,6 +106,10 @@
-  then
-   make all-gdb all-dejagnu all-ld || exit 1
-   make install-gdb install-dejagnu install-ld || exit 1
-+elif [ $H_REAL_TARGET = $H_REAL_HOST -a $H_REAL_TARGET = i686-pc-linux-uclibc ]
-+ then
-+  make all-gdb all-dejagnu all-ld || exit 1
-+  make install-gdb install-dejagnu install-ld || exit 1
- elif [ $H_REAL_TARGET = $H_REAL_HOST ] ; then
-   make bootstrap || exit 1
-   make install || exit 1
---- a/libjava/classpath/ltconfig
-+++ b/libjava/classpath/ltconfig
-@@ -603,7 +603,7 @@
- # Transform linux* to *-*-linux-gnu*, to support old configure scripts.
- case $host_os in
--linux-gnu*) ;;
-+linux-gnu*|linux-uclibc*) ;;
- linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
- esac
-@@ -1251,7 +1251,7 @@
-   ;;
- # This must be Linux ELF.
--linux-gnu*)
-+linux*)
-   version_type=linux
-   need_lib_prefix=no
-   need_version=no
diff --git a/toolchain/gcc/patches/4.5.2/301-missing-execinfo_h.patch b/toolchain/gcc/patches/4.5.2/301-missing-execinfo_h.patch
deleted file mode 100644 (file)
index 5a7aa4e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/boehm-gc/include/gc.h
-+++ b/boehm-gc/include/gc.h
-@@ -503,7 +503,7 @@
- #if defined(__linux__) || defined(__GLIBC__)
- # include <features.h>
- # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \
--     && !defined(__ia64__)
-+     && !defined(__ia64__) && !defined(__UCLIBC__)
- #   ifndef GC_HAVE_BUILTIN_BACKTRACE
- #     define GC_HAVE_BUILTIN_BACKTRACE
- #   endif
diff --git a/toolchain/gcc/patches/4.5.2/302-c99-snprintf.patch b/toolchain/gcc/patches/4.5.2/302-c99-snprintf.patch
deleted file mode 100644 (file)
index f0ba541..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/libstdc++-v3/include/c_global/cstdio
-+++ b/libstdc++-v3/include/c_global/cstdio
-@@ -139,7 +139,7 @@
- _GLIBCXX_END_NAMESPACE
--#if _GLIBCXX_USE_C99
-+#if _GLIBCXX_USE_C99 || defined __UCLIBC__
- #undef snprintf
- #undef vfscanf
diff --git a/toolchain/gcc/patches/4.5.2/305-libmudflap-susv3-legacy.patch b/toolchain/gcc/patches/4.5.2/305-libmudflap-susv3-legacy.patch
deleted file mode 100644 (file)
index 5bc4aeb..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
---- a/libmudflap/mf-hooks2.c
-+++ b/libmudflap/mf-hooks2.c
-@@ -421,7 +421,7 @@
- {
-   TRACE ("%s\n", __PRETTY_FUNCTION__);
-   MF_VALIDATE_EXTENT(s, n, __MF_CHECK_WRITE, "bzero region");
--  bzero (s, n);
-+  memset (s, 0, n);
- }
-@@ -431,7 +431,7 @@
-   TRACE ("%s\n", __PRETTY_FUNCTION__);
-   MF_VALIDATE_EXTENT(src, n, __MF_CHECK_READ, "bcopy src");
-   MF_VALIDATE_EXTENT(dest, n, __MF_CHECK_WRITE, "bcopy dest");
--  bcopy (src, dest, n);
-+  memmove (dest, src, n);
- }
-@@ -441,7 +441,7 @@
-   TRACE ("%s\n", __PRETTY_FUNCTION__);
-   MF_VALIDATE_EXTENT(s1, n, __MF_CHECK_READ, "bcmp 1st arg");
-   MF_VALIDATE_EXTENT(s2, n, __MF_CHECK_READ, "bcmp 2nd arg");
--  return bcmp (s1, s2, n);
-+  return n == 0 ? 0 : memcmp (s1, s2, n);
- }
-@@ -450,7 +450,7 @@
-   size_t n = strlen (s);
-   TRACE ("%s\n", __PRETTY_FUNCTION__);
-   MF_VALIDATE_EXTENT(s, CLAMPADD(n, 1), __MF_CHECK_READ, "index region");
--  return index (s, c);
-+  return strchr (s, c);
- }
-@@ -459,7 +459,7 @@
-   size_t n = strlen (s);
-   TRACE ("%s\n", __PRETTY_FUNCTION__);
-   MF_VALIDATE_EXTENT(s, CLAMPADD(n, 1), __MF_CHECK_READ, "rindex region");
--  return rindex (s, c);
-+  return strrchr (s, c);
- }
- /* XXX:  stpcpy, memccpy */
diff --git a/toolchain/gcc/patches/4.5.2/600-ubicom_support.patch b/toolchain/gcc/patches/4.5.2/600-ubicom_support.patch
deleted file mode 100644 (file)
index a8dbaf4..0000000
+++ /dev/null
@@ -1,9368 +0,0 @@
---- a/configure
-+++ b/configure
-@@ -2688,6 +2688,9 @@ case "${target}" in
-   ip2k-*-*)
-     noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 ${libgcj}"
-     ;;
-+  ubicom32-*-*)
-+    noconfigdirs="$noconfigdirs target-libffi"
-+    ;;
-   *-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu | *-*-kopensolaris*-gnu)
-     noconfigdirs="$noconfigdirs target-newlib target-libgloss"
-     ;;
---- /dev/null
-+++ b/gcc/config/ubicom32/constraints.md
-@@ -0,0 +1,149 @@
-+; Constraint definitions for Ubicom32
-+
-+; Copyright (C) 2009 Free Software Foundation, Inc.
-+; Contributed by Ubicom, Inc.
-+
-+; This file is part of GCC.
-+
-+; GCC is free software; you can redistribute it and/or modify it
-+; under the terms of the GNU General Public License as published
-+; by the Free Software Foundation; either version 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_register_constraint "a" "ALL_ADDRESS_REGS"
-+  "An An register.")
-+
-+(define_register_constraint "d" "DATA_REGS"
-+  "A Dn register.")
-+
-+(define_register_constraint "h" "ACC_REGS"
-+  "An accumulator register.")
-+
-+(define_register_constraint "l" "ACC_LO_REGS"
-+  "An accn_lo register.")
-+
-+(define_register_constraint "Z" "FDPIC_REG"
-+  "The FD-PIC GOT pointer: A0.")
-+
-+(define_constraint "I"
-+  "An 8-bit signed constant value."
-+  (and (match_code "const_int")
-+       (match_test "(ival >= -128) && (ival <= 127)")))
-+
-+(define_constraint "Q"
-+  "An 8-bit signed constant value represented as unsigned."
-+  (and (match_code "const_int")
-+       (match_test "(ival >= 0x00) && (ival <= 0xff)")))
-+
-+(define_constraint "R"
-+  "An 8-bit signed constant value represented as unsigned."
-+  (and (match_code "const_int")
-+       (match_test "((ival >= 0x0000) && (ival <= 0x007f)) || ((ival >= 0xff80) && (ival <= 0xffff))")))
-+
-+(define_constraint "J"
-+  "A 7-bit unsigned constant value."
-+  (and (match_code "const_int")
-+       (match_test "(ival >= 0) && (ival <= 127)")))
-+
-+(define_constraint "K"
-+  "A 7-bit unsigned constant value shifted << 1."
-+  (and (match_code "const_int")
-+       (match_test "(ival >= 0) && (ival <= 254) && ((ival & 1) == 0)")))
-+
-+(define_constraint "L"
-+  "A 7-bit unsigned constant value shifted << 2."
-+  (and (match_code "const_int")
-+       (match_test "(ival >= 0) && (ival <= 508) && ((ival & 3) == 0)")))
-+
-+(define_constraint "M"
-+  "A 5-bit unsigned constant value."
-+  (and (match_code "const_int")
-+       (match_test "(ival >= 0) && (ival <= 31)")))
-+
-+(define_constraint "N"
-+  "A signed 16 bit constant value."
-+  (and (match_code "const_int")
-+       (match_test "(ival >= -32768) && (ival <= 32767)")))
-+
-+(define_constraint "O"
-+  "An exact bitmask of contiguous 1 bits starting at bit 0."
-+  (and (match_code "const_int")
-+       (match_test "exact_log2 (ival + 1) != -1")))
-+
-+(define_constraint "P"
-+  "A 7-bit negative constant value shifted << 2."
-+  (and (match_code "const_int")
-+       (match_test "(ival >= -504) && (ival <= 0) && ((ival & 3) == 0)")))
-+
-+(define_constraint "S"
-+  "A symbolic reference."
-+  (match_code "symbol_ref"))
-+
-+(define_constraint "Y"
-+  "An FD-PIC symbolic reference."
-+  (and (match_test "TARGET_FDPIC")
-+       (match_test "GET_CODE (op) == UNSPEC")
-+       (ior (match_test "XINT (op, 1) == UNSPEC_FDPIC_GOT")
-+          (match_test "XINT (op, 1) == UNSPEC_FDPIC_GOT_FUNCDESC"))))
-+
-+(define_memory_constraint "T1"
-+  "A memory operand that can be used for .1 instruction."
-+  (and (match_test "memory_operand (op, GET_MODE(op))")
-+       (match_test "GET_MODE (op) == QImode")))
-+
-+(define_memory_constraint "T2"
-+  "A memory operand that can be used for .2 instruction."
-+  (and (match_test "memory_operand (op, GET_MODE(op))")
-+       (match_test "GET_MODE (op) == HImode")))
-+
-+(define_memory_constraint "T4"
-+  "A memory operand that can be used for .4 instruction."
-+  (and (match_test "memory_operand (op, GET_MODE(op))")
-+       (ior (match_test "GET_MODE (op) == SImode")
-+          (match_test "GET_MODE (op) == DImode")
-+          (match_test "GET_MODE (op) == SFmode"))))
-+
-+(define_memory_constraint "U1"
-+  "An offsettable memory operand that can be used for .1 instruction."
-+  (and (match_test "memory_operand (op, GET_MODE(op))")
-+       (match_test "GET_MODE (op) == QImode")
-+       (match_test "GET_CODE (XEXP (op, 0)) != POST_INC")
-+       (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC")
-+       (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC")
-+       (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC")
-+       (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY")
-+       (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY")))
-+
-+(define_memory_constraint "U2"
-+  "An offsettable memory operand that can be used for .2 instruction."
-+  (and (match_test "memory_operand (op, GET_MODE(op))")
-+       (match_test "GET_MODE (op) == HImode")
-+       (match_test "GET_CODE (XEXP (op, 0)) != POST_INC")
-+       (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC")
-+       (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC")
-+       (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC")
-+       (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY")
-+       (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY")))
-+
-+(define_memory_constraint "U4"
-+  "An offsettable memory operand that can be used for .4 instruction."
-+  (and (match_test "memory_operand (op, GET_MODE(op))")
-+       (ior (match_test "GET_MODE (op) == SImode")
-+          (match_test "GET_MODE (op) == DImode")
-+          (match_test "GET_MODE (op) == SFmode"))
-+       (match_test "GET_CODE (XEXP (op, 0)) != POST_INC")
-+       (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC")
-+       (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC")
-+       (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC")
-+       (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY")
-+       (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY")))
-+
---- /dev/null
-+++ b/gcc/config/ubicom32/crti.S
-@@ -0,0 +1,54 @@
-+/* Specialized code needed to support construction and destruction of
-+   file-scope objects in C++ and Java code, and to support exception handling.
-+   Copyright (C) 1999 Free Software Foundation, Inc.
-+   Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca).
-+
-+This file is part of GCC.
-+
-+GCC is free software; you can redistribute it and/or modify
-+it under the terms of the GNU General Public License as published by
-+the Free Software Foundation; either version 2, or (at your option)
-+any later version.
-+
-+GCC is distributed in the hope that it will be useful,
-+but WITHOUT ANY WARRANTY; without even the implied warranty of
-+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+GNU General Public License for more details.
-+
-+You should have received a copy of the GNU General Public License
-+along with GCC; see the file COPYING.  If not, write to
-+the Free Software Foundation, 59 Temple Place - Suite 330,
-+Boston, MA 02111-1307, USA.  */
-+
-+/* As a special exception, if you link this library with files
-+   compiled with GCC to produce an executable, this does not cause
-+   the resulting executable to be covered by the GNU General Public License.
-+   This exception does not however invalidate any other reasons why
-+   the executable file might be covered by the GNU General Public License.  */
-+
-+/*
-+ * This file just supplies function prologues for the .init and .fini
-+ * sections.  It is linked in before crtbegin.o.
-+ */
-+      .file   "crti.o"
-+      .ident  "GNU C crti.o"
-+
-+      .section .init
-+      .align  2
-+      .globl  _init
-+      .type   _init, @function
-+_init:
-+      move.4 -4(sp)++, a5
-+#ifdef __UBICOM32_FDPIC__
-+      move.4 -4(sp)++, a0
-+#endif
-+
-+      .section .fini
-+      .align  2
-+      .globl  _fini
-+      .type   _fini, @function
-+_fini:
-+      move.4 -4(sp)++, a5
-+#ifdef __UBICOM32_FDPIC__
-+      move.4 -4(sp)++, a0
-+#endif
---- /dev/null
-+++ b/gcc/config/ubicom32/crtn.S
-@@ -0,0 +1,47 @@
-+/* Specialized code needed to support construction and destruction of
-+   file-scope objects in C++ and Java code, and to support exception handling.
-+   Copyright (C) 1999 Free Software Foundation, Inc.
-+   Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca).
-+
-+This file is part of GCC.
-+
-+GCC is free software; you can redistribute it and/or modify
-+it under the terms of the GNU General Public License as published by
-+the Free Software Foundation; either version 2, or (at your option)
-+any later version.
-+
-+GCC is distributed in the hope that it will be useful,
-+but WITHOUT ANY WARRANTY; without even the implied warranty of
-+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+GNU General Public License for more details.
-+
-+You should have received a copy of the GNU General Public License
-+along with GCC; see the file COPYING.  If not, write to
-+the Free Software Foundation, 59 Temple Place - Suite 330,
-+Boston, MA 02111-1307, USA.  */
-+
-+/* As a special exception, if you link this library with files
-+   compiled with GCC to produce an executable, this does not cause
-+   the resulting executable to be covered by the GNU General Public License.
-+   This exception does not however invalidate any other reasons why
-+   the executable file might be covered by the GNU General Public License.  */
-+
-+/*
-+ * This file supplies function epilogues for the .init and .fini sections.
-+ * It is linked in after all other files.
-+ */
-+
-+      .file   "crtn.o"
-+      .ident  "GNU C crtn.o"
-+
-+      .section .init
-+#ifdef __UBICOM32_FDPIC__
-+      move.4  a0, (sp)4++
-+#endif
-+      ret     (sp)4++
-+
-+      .section .fini
-+#ifdef __UBICOM32_FDPIC__
-+      move.4  a0, (sp)4++
-+#endif
-+      ret     (sp)4++
---- /dev/null
-+++ b/gcc/config/ubicom32/elf.h
-@@ -0,0 +1,29 @@
-+#undef  STARTFILE_SPEC
-+#define STARTFILE_SPEC "\
-+%{msim:%{!shared:crt0%O%s}} \
-+crti%O%s crtbegin%O%s"
-+
-+#undef  ENDFILE_SPEC
-+#define ENDFILE_SPEC  "crtend%O%s crtn%O%s"
-+
-+#ifdef __UBICOM32_FDPIC__
-+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC)                    \
-+  asm (SECTION_OP);                                                   \
-+  asm ("move.4 a0, 0(sp);\n\t"                                                \
-+       "call a5," USER_LABEL_PREFIX #FUNC ";");                               \
-+  asm (TEXT_SECTION_ASM_OP);
-+#endif
-+
-+#undef SUBTARGET_DRIVER_SELF_SPECS
-+#define SUBTARGET_DRIVER_SELF_SPECS \
-+     "%{mfdpic:-msim} "
-+
-+#define NO_IMPLICIT_EXTERN_C
-+
-+/*
-+ * We need this to compile crtbegin/crtend. This should really be picked
-+ * up from elfos.h but at the moment including elfos.h causes other more
-+ * serous linker issues.
-+ */
-+#define INIT_SECTION_ASM_OP   "\t.section\t.init"
-+#define FINI_SECTION_ASM_OP   "\t.section\t.fini"
---- /dev/null
-+++ b/gcc/config/ubicom32/linux.h
-@@ -0,0 +1,80 @@
-+/* Definitions of target machine for Ubicom32-uclinux
-+
-+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
-+   2009 Free Software Foundation, Inc.
-+   Contributed by Ubicom, Inc.
-+
-+   This file is part of GCC.
-+
-+   GCC is free software; you can redistribute it and/or modify it
-+   under the terms of the GNU General Public License as published
-+   by the Free Software Foundation; either version 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/>.  */
-+
-+/* Don't assume anything about the header files.  */
-+#define NO_IMPLICIT_EXTERN_C
-+
-+#undef  LIB_SPEC
-+#define LIB_SPEC  \
-+      "%{pthread:-lpthread} " \
-+      "-lc"
-+
-+#undef LINK_GCC_C_SEQUENCE_SPEC
-+#define LINK_GCC_C_SEQUENCE_SPEC \
-+  "%{static:--start-group} %G %L %{static:--end-group} " \
-+  "%{!static: %G}"
-+
-+#undef STARTFILE_SPEC
-+#define STARTFILE_SPEC \
-+  "%{!shared: %{pg|p|profile:gcrt1%O%s;pie:Scrt1%O%s;:crt1%O%s}} " \
-+  "crtreloc%O%s crti%O%s %{shared|pie:crtbeginS%O%s;:crtbegin%O%s}"
-+
-+#undef ENDFILE_SPEC
-+#define ENDFILE_SPEC \
-+  "%{shared|pie:crtendS%O%s;:crtend%O%s} crtn%O%s"
-+
-+/* taken from linux.h */
-+/* The GNU C++ standard library requires that these macros be defined.  */
-+#undef CPLUSPLUS_CPP_SPEC
-+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
-+
-+#define TARGET_OS_CPP_BUILTINS()                              \
-+    do {                                                      \
-+      builtin_define_std ("__UBICOM32__");                    \
-+      builtin_define_std ("__ubicom32__");                    \
-+      builtin_define ("__gnu_linux__");                       \
-+      builtin_define_std ("linux");                           \
-+      builtin_define_std ("unix");                            \
-+      builtin_assert ("system=linux");                        \
-+      builtin_assert ("system=unix");                         \
-+      builtin_assert ("system=posix");                        \
-+    } while (0)
-+
-+#define OBJECT_FORMAT_ELF
-+
-+
-+#undef DRIVER_SELF_SPECS
-+#define DRIVER_SELF_SPECS \
-+  "%{!mno-fdpic:-mfdpic}"
-+
-+#undef LINK_SPEC
-+#define LINK_SPEC "%{mfdpic: -m elf32ubicom32fdpic -z text } %{shared} %{pie} \
-+  %{static:-dn -Bstatic} \
-+  %{shared:-G -Bdynamic} \
-+  %{!shared: %{!static: \
-+   %{rdynamic:-export-dynamic} \
-+   %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}} \
-+   %{static}} "
-+
-+/*
-+#define MD_UNWIND_SUPPORT "config/bfin/linux-unwind.h"
-+*/
---- /dev/null
-+++ b/gcc/config/ubicom32/predicates.md
-@@ -0,0 +1,327 @@
-+; Predicate definitions for Ubicom32.
-+
-+; Copyright (C) 2009 Free Software Foundation, Inc.
-+; Contributed by Ubicom, Inc.
-+
-+; This file is part of GCC.
-+
-+; GCC is free software; you can redistribute it and/or modify it
-+; under the terms of the GNU General Public License as published
-+; by the Free Software Foundation; either version 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_predicate "ubicom32_move_operand"
-+  (match_code "const_int, const_double, const, mem, subreg, reg, lo_sum")
-+{
-+  if (CONST_INT_P (op))
-+    return true;
-+
-+  if (GET_CODE (op) == CONST_DOUBLE)
-+    return true;
-+  
-+  if (GET_CODE (op) == CONST)
-+    return memory_address_p (mode, op);
-+
-+  if (GET_MODE (op) != mode)
-+    return false;
-+
-+  if (MEM_P (op))
-+    return memory_address_p (mode, XEXP (op, 0));
-+  
-+  if (GET_CODE (op) == SUBREG) {
-+      op = SUBREG_REG (op);
-+
-+      if (REG_P (op))
-+      return true;
-+  
-+      if (! MEM_P (op))
-+      return false;
-+
-+      /* Paradoxical SUBREG.  */
-+      if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (op)))
-+      return false;
-+
-+      return memory_address_p (GET_MODE (op), XEXP (op, 0));
-+    }
-+
-+  return register_operand (op, mode);
-+})
-+
-+;; Returns true if OP is either a symbol reference or a sum of a
-+;; symbol reference and a constant.
-+
-+(define_predicate "ubicom32_symbolic_address_operand"
-+  (match_code "symbol_ref, label_ref, const")
-+{
-+  switch (GET_CODE (op))
-+    {
-+    case SYMBOL_REF:
-+    case LABEL_REF:
-+      return true;
-+
-+    case CONST:
-+      op = XEXP (op, 0);
-+      return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
-+             || GET_CODE (XEXP (op, 0)) == LABEL_REF)
-+            && CONST_INT_P (XEXP (op, 1)));
-+
-+    default:
-+      return false;
-+    }
-+})
-+
-+;; Return true if operand is the uClinux FD-PIC register.
-+
-+(define_predicate "ubicom32_fdpic_operand"
-+  (match_code "reg")
-+{
-+  if (! TARGET_FDPIC)
-+    return false;
-+
-+  if (!REG_P (op))
-+    return false;
-+
-+  if (GET_MODE (op) != mode && mode != VOIDmode)
-+    return false;
-+
-+  if (REGNO (op) != FDPIC_REGNUM && REGNO (op) < FIRST_PSEUDO_REGISTER)
-+    return false;
-+
-+  return true;
-+})
-+
-+(define_predicate "ubicom32_fdpic_got_offset_operand"
-+  (match_code "unspec")
-+{
-+  if (! TARGET_FDPIC)
-+    return false;
-+
-+  if (GET_CODE (op) != UNSPEC)
-+    return false;
-+
-+  if (XINT (op, 1) != UNSPEC_FDPIC_GOT
-+      && XINT (op, 1) != UNSPEC_FDPIC_GOT_FUNCDESC)
-+    return false;
-+
-+  return true;
-+})
-+
-+(define_predicate "ubicom32_arith_operand"
-+  (match_code "subreg, reg, const_int, lo_sum, mem")
-+{
-+  return (ubicom32_move_operand (op, mode)
-+        && ! ubicom32_symbolic_address_operand (op, mode)
-+        && (! CONST_INT_P (op)
-+            || satisfies_constraint_I (op)));
-+})
-+
-+(define_predicate "ubicom32_arith_operand_dot1"
-+  (match_code "subreg, reg, const_int, lo_sum, mem")
-+{
-+  return (ubicom32_move_operand (op, mode)
-+        && ! ubicom32_symbolic_address_operand (op, mode)
-+        && (! CONST_INT_P (op)
-+            || satisfies_constraint_Q (op)));
-+})
-+
-+(define_predicate "ubicom32_arith_operand_dot2"
-+  (match_code "subreg, reg, const_int, lo_sum, mem")
-+{
-+  return (ubicom32_move_operand (op, mode)
-+        && ! ubicom32_symbolic_address_operand (op, mode)
-+        && (! CONST_INT_P (op)
-+            || satisfies_constraint_R (op)));
-+})
-+
-+(define_predicate "ubicom32_compare_operand"
-+  (match_code "subreg, reg, const_int, lo_sum, mem")
-+{
-+ return (ubicom32_move_operand (op, mode)
-+        && ! ubicom32_symbolic_address_operand (op, mode)
-+        && (! CONST_INT_P (op)
-+            || satisfies_constraint_N (op)));
-+})
-+
-+(define_predicate "ubicom32_compare_operator"
-+  (match_code "compare"))
-+
-+(define_predicate "ubicom32_and_or_si3_operand"
-+  (match_code "subreg, reg, const_int, lo_sum, mem")
-+{
-+  return (ubicom32_arith_operand (op, mode)
-+        || (CONST_INT_P (op)
-+            && ((exact_log2 (INTVAL (op) + 1) != -1
-+                 && exact_log2 (INTVAL (op) + 1) <= 31)
-+                || (exact_log2 (INTVAL (op)) != -1
-+                    && exact_log2 (INTVAL (op)) <= 31)
-+                || (exact_log2 (~INTVAL (op)) != -1
-+                    && exact_log2 (~INTVAL (op)) <= 31))));
-+})
-+
-+(define_predicate "ubicom32_and_or_hi3_operand"
-+  (match_code "subreg, reg, const_int, lo_sum, mem")
-+{
-+  return (ubicom32_arith_operand (op, mode)
-+        || (CONST_INT_P (op)
-+            && exact_log2 (INTVAL (op) + 1) != -1
-+            && exact_log2 (INTVAL (op) + 1) <= 15));
-+})
-+
-+(define_predicate "ubicom32_mem_or_address_register_operand"
-+  (match_code "subreg, reg, mem")
-+{
-+  unsigned int regno;
-+
-+  if (MEM_P (op)
-+      && memory_operand (op, mode))
-+    return true;
-+
-+  if (REG_P (op))
-+    regno = REGNO (op);
-+  else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
-+    {
-+      int offset;
-+      if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
-+      offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
-+      else
-+      offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
-+                                    GET_MODE (SUBREG_REG (op)),
-+                                    SUBREG_BYTE (op),
-+                                    GET_MODE (op));
-+      regno = REGNO (SUBREG_REG (op)) + offset;
-+    }
-+  else
-+    return false;
-+
-+  return (regno >= FIRST_PSEUDO_REGISTER 
-+        || REGNO_REG_CLASS (regno) == FDPIC_REG
-+        || REGNO_REG_CLASS (regno) == ADDRESS_REGS);
-+})
-+
-+(define_predicate "ubicom32_data_register_operand"
-+  (match_code "subreg, reg")
-+{
-+  unsigned int regno;
-+
-+  if (REG_P (op))
-+    regno = REGNO (op);
-+  else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
-+    {
-+      int offset;
-+      if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
-+      offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
-+      else
-+      offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
-+                                    GET_MODE (SUBREG_REG (op)),
-+                                    SUBREG_BYTE (op),
-+                                    GET_MODE (op));
-+      regno = REGNO (SUBREG_REG (op)) + offset;
-+    }
-+  else
-+    return false;
-+
-+  return ((regno >= FIRST_PSEUDO_REGISTER 
-+         && regno != REGNO (virtual_stack_vars_rtx))
-+        || REGNO_REG_CLASS (regno) == DATA_REGS);
-+})
-+
-+(define_predicate "ubicom32_address_register_operand"
-+  (match_code "subreg, reg")
-+{
-+  unsigned int regno;
-+
-+  if (REG_P (op))
-+    regno = REGNO (op);
-+  else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
-+    {
-+      int offset;
-+      if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
-+      offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
-+      else
-+      offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
-+                                    GET_MODE (SUBREG_REG (op)),
-+                                    SUBREG_BYTE (op),
-+                                    GET_MODE (op));
-+      regno = REGNO (SUBREG_REG (op)) + offset;
-+    }
-+  else
-+    return false;
-+
-+  return (regno >= FIRST_PSEUDO_REGISTER 
-+        || REGNO_REG_CLASS (regno) == FDPIC_REG
-+        || REGNO_REG_CLASS (regno) == ADDRESS_REGS);
-+})
-+
-+(define_predicate "ubicom32_acc_lo_register_operand"
-+  (match_code "subreg, reg")
-+{
-+  unsigned int regno;
-+
-+  if (REG_P (op))
-+    regno = REGNO (op);
-+  else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
-+    {
-+      int offset;
-+      if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
-+      offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
-+      else
-+      offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
-+                                    GET_MODE (SUBREG_REG (op)),
-+                                    SUBREG_BYTE (op),
-+                                    GET_MODE (op));
-+      regno = REGNO (SUBREG_REG (op)) + offset;
-+    }
-+  else
-+    return false;
-+
-+  return ((regno >= FIRST_PSEUDO_REGISTER 
-+         && regno != REGNO (virtual_stack_vars_rtx))
-+        || REGNO_REG_CLASS (regno) == ACC_LO_REGS);
-+})
-+
-+(define_predicate "ubicom32_acc_hi_register_operand"
-+  (match_code "subreg, reg")
-+{
-+  unsigned int regno;
-+
-+  if (REG_P (op))
-+    regno = REGNO (op);
-+  else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
-+    {
-+      int offset;
-+      if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
-+      offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
-+      else
-+      offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
-+                                    GET_MODE (SUBREG_REG (op)),
-+                                    SUBREG_BYTE (op),
-+                                    GET_MODE (op));
-+      regno = REGNO (SUBREG_REG (op)) + offset;
-+    }
-+  else
-+    return false;
-+
-+  return ((regno >= FIRST_PSEUDO_REGISTER 
-+         && regno != REGNO (virtual_stack_vars_rtx))
-+        || REGNO_REG_CLASS (regno) == ACC_REGS);
-+})
-+
-+(define_predicate "ubicom32_call_address_operand"
-+  (match_code "symbol_ref, subreg, reg")
-+{
-+  return (GET_CODE (op) == SYMBOL_REF || REG_P (op));
-+})
-+
-+(define_special_predicate "ubicom32_cc_register_operand"
-+  (and (match_code "reg")
-+       (match_test "REGNO (op) == CC_REGNUM")))
-+
---- /dev/null
-+++ b/gcc/config/ubicom32/t-ubicom32
-@@ -0,0 +1,52 @@
-+# Name of assembly file containing libgcc1 functions.
-+# This entry must be present, but it can be empty if the target does
-+# not need any assembler functions to support its code generation.
-+CROSS_LIBGCC1 =
-+
-+# Alternatively if assembler functions *are* needed then define the
-+# entries below:
-+# CROSS_LIBGCC1 = libgcc1-asm.a
-+
-+LIB2FUNCS_EXTRA = \
-+      $(srcdir)/config/udivmodsi4.c \
-+      $(srcdir)/config/divmod.c \
-+      $(srcdir)/config/udivmod.c
-+
-+# If any special flags are necessary when building libgcc2 put them here.
-+#
-+# TARGET_LIBGCC2_CFLAGS = 
-+
-+# We want fine grained libraries, so use the new code to build the
-+# floating point emulation libraries.
-+FPBIT = fp-bit.c
-+DPBIT = dp-bit.c
-+
-+fp-bit.c: $(srcdir)/config/fp-bit.c
-+      echo '#define FLOAT'                            > fp-bit.c
-+      cat $(srcdir)/config/fp-bit.c                   >> fp-bit.c
-+
-+dp-bit.c: $(srcdir)/config/fp-bit.c
-+      cat $(srcdir)/config/fp-bit.c > dp-bit.c
-+
-+# Commented out to speed up compiler development!
-+#
-+# MULTILIB_OPTIONS = march=ubicom32v1/march=ubicom32v2/march=ubicom32v3/march=ubicom32v4
-+# MULTILIB_DIRNAMES = ubicom32v1 ubicom32v2 ubicom32v3 ubicom32v4
-+
-+MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4
-+MULTILIB_OPTIONS += mfdpic
-+MULTILIB_OPTIONS += mno-ipos-abi/mipos-abi
-+MULTILIB_OPTIONS += fno-leading-underscore/fleading-underscore
-+
-+# Assemble startup files.
-+$(T)crti.o: $(srcdir)/config/ubicom32/crti.S $(GCC_PASSES)
-+      $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
-+      -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/ubicom32/crti.S
-+
-+$(T)crtn.o: $(srcdir)/config/ubicom32/crtn.S $(GCC_PASSES)
-+      $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
-+      -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/ubicom32/crtn.S
-+
-+# these parts are required because uClibc ldso needs them to link.
-+# they are not in the specfile so they will not be included automatically.
-+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o crti.o crtn.o
---- /dev/null
-+++ b/gcc/config/ubicom32/t-ubicom32-linux
-@@ -0,0 +1,35 @@
-+# Name of assembly file containing libgcc1 functions.
-+# This entry must be present, but it can be empty if the target does
-+# not need any assembler functions to support its code generation.
-+CROSS_LIBGCC1 =
-+
-+# Alternatively if assembler functions *are* needed then define the
-+# entries below:
-+# CROSS_LIBGCC1 = libgcc1-asm.a
-+
-+LIB2FUNCS_EXTRA = \
-+      $(srcdir)/config/udivmodsi4.c \
-+      $(srcdir)/config/divmod.c \
-+      $(srcdir)/config/udivmod.c
-+
-+# If any special flags are necessary when building libgcc2 put them here.
-+#
-+# TARGET_LIBGCC2_CFLAGS =
-+
-+# We want fine grained libraries, so use the new code to build the
-+# floating point emulation libraries.
-+FPBIT = fp-bit.c
-+DPBIT = dp-bit.c
-+
-+fp-bit.c: $(srcdir)/config/fp-bit.c
-+      echo '#define FLOAT'                            > fp-bit.c
-+      cat $(srcdir)/config/fp-bit.c                   >> fp-bit.c
-+
-+dp-bit.c: $(srcdir)/config/fp-bit.c
-+      cat $(srcdir)/config/fp-bit.c > dp-bit.c
-+
-+# We only support v3 and v4 ISAs for uClinux.
-+
-+MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4
-+
-+#EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o
---- /dev/null
-+++ b/gcc/config/ubicom32/t-ubicom32-uclinux
-@@ -0,0 +1,35 @@
-+# Name of assembly file containing libgcc1 functions.
-+# This entry must be present, but it can be empty if the target does
-+# not need any assembler functions to support its code generation.
-+CROSS_LIBGCC1 =
-+
-+# Alternatively if assembler functions *are* needed then define the
-+# entries below:
-+# CROSS_LIBGCC1 = libgcc1-asm.a
-+
-+LIB2FUNCS_EXTRA = \
-+      $(srcdir)/config/udivmodsi4.c \
-+      $(srcdir)/config/divmod.c \
-+      $(srcdir)/config/udivmod.c
-+
-+# If any special flags are necessary when building libgcc2 put them here.
-+#
-+# TARGET_LIBGCC2_CFLAGS = 
-+
-+# We want fine grained libraries, so use the new code to build the
-+# floating point emulation libraries.
-+FPBIT = fp-bit.c
-+DPBIT = dp-bit.c
-+
-+fp-bit.c: $(srcdir)/config/fp-bit.c
-+      echo '#define FLOAT'                            > fp-bit.c
-+      cat $(srcdir)/config/fp-bit.c                   >> fp-bit.c
-+
-+dp-bit.c: $(srcdir)/config/fp-bit.c
-+      cat $(srcdir)/config/fp-bit.c > dp-bit.c
-+
-+# We only support v3 and v4 ISAs for uClinux.
-+
-+MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4
-+
-+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o # crtbeginS.o crtendS.o
---- /dev/null
-+++ b/gcc/config/ubicom32/ubicom32-modes.def
-@@ -0,0 +1,30 @@
-+/* Definitions of target machine for GNU compiler, Ubicom32 architecture.
-+   Copyright (C) 2009 Free Software Foundation, Inc.
-+   Contributed by Ubicom, Inc.
-+
-+   This file is part of GCC.
-+
-+   GCC is free software; you can redistribute it and/or modify it
-+   under the terms of the GNU General Public License as published
-+   by the Free Software Foundation; either version 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/>.  */
-+
-+/* Some insns set all condition code flags, some only set the Z and N flags, and
-+   some only set the Z flag.  */
-+
-+CC_MODE (CCW);
-+CC_MODE (CCWZN);
-+CC_MODE (CCWZ);
-+CC_MODE (CCS);
-+CC_MODE (CCSZN);
-+CC_MODE (CCSZ);
-+
---- /dev/null
-+++ b/gcc/config/ubicom32/ubicom32-protos.h
-@@ -0,0 +1,84 @@
-+/* Function prototypes for Ubicom IP3000.
-+
-+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
-+   2009 Free Software Foundation, Inc.
-+   Contributed by Ubicom, Inc.
-+
-+   This file is part of GNU CC.
-+
-+   GNU CC is free software; you can redistribute it and/or modify it under
-+   the terms of the GNU General Public License as published by the Free
-+   Software Foundation; either version 2, or (at your option) any later
-+   version.
-+
-+   GNU CC is distributed in the hope that it will be useful, but WITHOUT
-+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-+   for more details.
-+
-+   You should have received a copy of the GNU General Public License along
-+   with GNU CC; see the file COPYING.  If not, write to the Free Software
-+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-+
-+#ifdef RTX_CODE
-+
-+#ifdef TREE_CODE
-+extern void ubicom32_va_start (tree, rtx);
-+#endif /* TREE_CODE */
-+
-+extern void ubicom32_print_operand (FILE *, rtx, int);
-+extern void ubicom32_print_operand_address (FILE *, rtx);
-+
-+extern void ubicom32_conditional_register_usage (void);
-+extern enum reg_class ubicom32_preferred_reload_class (rtx, enum reg_class);
-+extern int ubicom32_regno_ok_for_index_p (int, int);
-+extern void ubicom32_expand_movsi (rtx *);
-+extern void ubicom32_expand_addsi3 (rtx *);
-+extern int ubicom32_emit_mult_sequence (rtx *);
-+extern void ubicom32_emit_move_const_int (rtx, rtx);
-+extern bool ubicom32_legitimate_constant_p (rtx);
-+extern bool ubicom32_legitimate_address_p (enum machine_mode, rtx, int);
-+extern rtx ubicom32_legitimize_address (rtx, rtx, enum machine_mode);
-+extern rtx ubicom32_legitimize_reload_address (rtx, enum machine_mode, int, int);
-+extern void ubicom32_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1);
-+extern int ubicom32_mode_dependent_address_p (rtx);
-+extern void ubicom32_output_cond_jump (rtx, rtx, rtx);
-+extern void ubicom32_expand_eh_return (rtx *);
-+extern void ubicom32_expand_call_fdpic (rtx *);
-+extern void ubicom32_expand_call_value_fdpic (rtx *);
-+extern enum machine_mode ubicom32_select_cc_mode (RTX_CODE, rtx, rtx);
-+extern rtx ubicom32_gen_compare_reg (RTX_CODE, rtx, rtx);
-+extern int ubicom32_shiftable_const_int (int);
-+#endif /* RTX_CODE */
-+
-+#ifdef TREE_CODE
-+extern void init_cumulative_args (CUMULATIVE_ARGS *cum,
-+                                tree fntype,
-+                                struct rtx_def *libname,
-+                                int indirect);
-+extern struct rtx_def *function_arg (CUMULATIVE_ARGS *,
-+                                   enum machine_mode, tree, int);
-+extern struct rtx_def *function_incoming_arg (CUMULATIVE_ARGS *,
-+                                            enum machine_mode,
-+                                            tree, int);
-+extern int function_arg_partial_nregs (CUMULATIVE_ARGS *,
-+                                     enum machine_mode, tree, int);
-+extern struct rtx_def *ubicom32_va_arg (tree, tree);
-+extern int ubicom32_reg_parm_stack_space (tree);
-+#endif /* TREE_CODE */
-+
-+extern struct rtx_def * ubicom32_builtin_saveregs (void);
-+extern void asm_file_start (FILE *);
-+extern void ubicom32_expand_prologue (void);
-+extern void ubicom32_expand_epilogue (void);
-+extern int ubicom32_initial_elimination_offset (int, int);
-+extern int ubicom32_regno_ok_for_base_p (int, int);
-+extern bool ubicom32_hard_regno_mode_ok (unsigned int, enum machine_mode);
-+extern int ubicom32_can_use_return_insn_p (void);
-+extern rtx ubicom32_return_addr_rtx (int, rtx);
-+extern void ubicom32_optimization_options (int, int);
-+extern void ubicom32_override_options (void);
-+extern bool ubicom32_match_cc_mode (rtx, enum machine_mode);
-+
-+extern int ubicom32_reorg_completed;
-+
---- /dev/null
-+++ b/gcc/config/ubicom32/ubicom32.c
-@@ -0,0 +1,2881 @@
-+/* Subroutines for insn-output.c for Ubicom32
-+
-+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
-+   2009 Free Software Foundation, Inc.
-+   Contributed by Ubicom, Inc.
-+
-+   This file is part of GCC.
-+
-+   GCC is free software; you can redistribute it and/or modify it
-+   under the terms of the GNU General Public License as published
-+   by the Free Software Foundation; either version 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/>.  */
-+
-+#include "config.h"
-+#include "system.h"
-+#include "coretypes.h"
-+#include "tm.h"
-+#include "rtl.h"
-+#include "tree.h"
-+#include "regs.h"
-+#include "hard-reg-set.h"
-+#include "real.h"
-+#include "insn-config.h"
-+#include "conditions.h"
-+#include "insn-flags.h"
-+#include "output.h"
-+#include "insn-attr.h"
-+#include "insn-codes.h"
-+#include "flags.h"
-+#include "recog.h"
-+#include "expr.h"
-+#include "function.h"
-+#include "obstack.h"
-+#include "toplev.h"
-+#include "tm_p.h"
-+#include "tm-constrs.h"
-+#include "basic-block.h"
-+#include "integrate.h"
-+#include "target.h"
-+#include "target-def.h"
-+#include "reload.h"
-+#include "df.h"
-+#include "langhooks.h"
-+#include "optabs.h"
-+
-+static tree ubicom32_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
-+static void ubicom32_layout_frame (void);
-+static void ubicom32_function_prologue (FILE *, HOST_WIDE_INT);
-+static void ubicom32_function_epilogue (FILE *, HOST_WIDE_INT);
-+static bool ubicom32_rtx_costs (rtx, int, int, int *, bool speed);
-+static bool ubicom32_fixed_condition_code_regs (unsigned int *,
-+                                              unsigned int *);
-+static enum machine_mode ubicom32_cc_modes_compatible (enum machine_mode,
-+                                                     enum machine_mode);
-+static int ubicom32_naked_function_p (void);
-+static void ubicom32_machine_dependent_reorg (void);
-+static bool ubicom32_assemble_integer (rtx, unsigned int, int);
-+static void ubicom32_asm_init_sections (void);
-+static int ubicom32_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,tree, 
-+                                     bool);
-+static bool ubicom32_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
-+                                      enum machine_mode mode, const_tree type,
-+                                      bool named ATTRIBUTE_UNUSED);
-+static bool ubicom32_callee_copies (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
-+                                  enum machine_mode mode, const_tree type,
-+                                  bool named ATTRIBUTE_UNUSED);
-+
-+static bool ubicom32_return_in_memory (const_tree type, 
-+                                     const_tree fntype ATTRIBUTE_UNUSED);
-+static bool ubicom32_is_base_reg (rtx, int);
-+static void ubicom32_init_builtins (void);
-+static rtx ubicom32_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
-+static tree ubicom32_fold_builtin (tree, tree, bool);
-+static int ubicom32_get_valid_offset_mask (enum machine_mode);
-+static bool ubicom32_cannot_force_const_mem (rtx);
-+
-+/* Case values threshold */
-+int ubicom32_case_values_threshold = 6;
-+
-+/* Nonzero if this chip supports the Ubicom32 v3 ISA.  */
-+int ubicom32_v3 = 1;
-+
-+/* Nonzero if this chip supports the Ubicom32 v4 ISA.  */
-+int ubicom32_v4 = 1;
-+
-+/* Valid attributes:
-+   naked - don't generate function prologue/epilogue and `ret' command.  */
-+const struct attribute_spec ubicom32_attribute_table[] =
-+{
-+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
-+  { "naked", 0, 0, true,  false, false, ubicom32_handle_fndecl_attribute },
-+  { NULL,    0, 0, false, false, false, NULL }
-+};
-+
-+#undef TARGET_ASM_FUNCTION_PROLOGUE
-+#define TARGET_ASM_FUNCTION_PROLOGUE ubicom32_function_prologue
-+
-+#undef TARGET_ASM_FUNCTION_EPILOGUE
-+#define TARGET_ASM_FUNCTION_EPILOGUE ubicom32_function_epilogue
-+
-+#undef TARGET_ATTRIBUTE_TABLE
-+#define TARGET_ATTRIBUTE_TABLE ubicom32_attribute_table
-+
-+/* All addresses cost the same amount.  */
-+#undef TARGET_ADDRESS_COST
-+#define TARGET_ADDRESS_COST hook_int_rtx_bool_0
-+
-+#undef TARGET_RTX_COSTS
-+#define TARGET_RTX_COSTS ubicom32_rtx_costs
-+
-+#undef TARGET_FIXED_CONDITION_CODE_REGS
-+#define TARGET_FIXED_CONDITION_CODE_REGS ubicom32_fixed_condition_code_regs
-+
-+#undef TARGET_CC_MODES_COMPATIBLE
-+#define TARGET_CC_MODES_COMPATIBLE ubicom32_cc_modes_compatible
-+
-+#undef TARGET_MACHINE_DEPENDENT_REORG
-+#define TARGET_MACHINE_DEPENDENT_REORG ubicom32_machine_dependent_reorg
-+
-+#undef  TARGET_ASM_INTEGER
-+#define TARGET_ASM_INTEGER ubicom32_assemble_integer
-+
-+#undef TARGET_ASM_INIT_SECTIONS
-+#define TARGET_ASM_INIT_SECTIONS ubicom32_asm_init_sections
-+
-+#undef TARGET_ARG_PARTIAL_BYTES
-+#define TARGET_ARG_PARTIAL_BYTES ubicom32_arg_partial_bytes
-+
-+#undef TARGET_PASS_BY_REFERENCE
-+#define TARGET_PASS_BY_REFERENCE ubicom32_pass_by_reference
-+
-+#undef TARGET_CALLEE_COPIES
-+#define TARGET_CALLEE_COPIES ubicom32_callee_copies
-+
-+#undef TARGET_RETURN_IN_MEMORY
-+#define TARGET_RETURN_IN_MEMORY ubicom32_return_in_memory
-+
-+#undef TARGET_INIT_BUILTINS
-+#define TARGET_INIT_BUILTINS ubicom32_init_builtins
-+
-+#undef TARGET_EXPAND_BUILTIN
-+#define TARGET_EXPAND_BUILTIN ubicom32_expand_builtin
-+
-+#undef TARGET_FOLD_BUILTIN
-+#define TARGET_FOLD_BUILTIN ubicom32_fold_builtin
-+
-+#undef TARGET_CANNOT_FORCE_CONST_MEM
-+#define TARGET_CANNOT_FORCE_CONST_MEM ubicom32_cannot_force_const_mem
-+
-+struct gcc_target targetm = TARGET_INITIALIZER;
-+
-+static char save_regs[FIRST_PSEUDO_REGISTER];
-+static int nregs;
-+static int frame_size;
-+int ubicom32_stack_size = 0;  /* size of allocated stack (including frame) */
-+int ubicom32_can_use_calli_to_ret;
-+
-+#define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
-+#define ROUND_CALL_BLOCK_SIZE(BYTES) \
-+  (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
-+
-+/* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference, we
-+   must report the mode of the memory reference from PRINT_OPERAND to
-+   PRINT_OPERAND_ADDRESS.  */
-+enum machine_mode output_memory_reference_mode;
-+
-+/* Flag for some split insns from the ubicom32.md.  */
-+int ubicom32_reorg_completed;
-+
-+enum reg_class const ubicom32_regclass_map[FIRST_PSEUDO_REGISTER] =
-+{
-+  DATA_REGS, 
-+  DATA_REGS, 
-+  DATA_REGS, 
-+  DATA_REGS, 
-+  DATA_REGS, 
-+  DATA_REGS, 
-+  DATA_REGS, 
-+  DATA_REGS, 
-+  DATA_REGS, 
-+  DATA_REGS, 
-+  DATA_REGS, 
-+  DATA_REGS, 
-+  DATA_REGS, 
-+  DATA_REGS, 
-+  DATA_REGS, 
-+  DATA_REGS, 
-+  FDPIC_REG, 
-+  ADDRESS_REGS, 
-+  ADDRESS_REGS, 
-+  ADDRESS_REGS, 
-+  ADDRESS_REGS, 
-+  ADDRESS_REGS, 
-+  ADDRESS_REGS, 
-+  ADDRESS_REGS, 
-+  ACC_REGS,
-+  ACC_LO_REGS,
-+  ACC_REGS,
-+  ACC_LO_REGS,
-+  SOURCE3_REG,
-+  ADDRESS_REGS,
-+  NO_REGS,                    /* CC_REG must be NO_REGS */
-+  SPECIAL_REGS,
-+  SPECIAL_REGS,
-+  SPECIAL_REGS,
-+  SPECIAL_REGS,
-+  SPECIAL_REGS,
-+  SPECIAL_REGS,
-+  SPECIAL_REGS,
-+  SPECIAL_REGS
-+};
-+
-+rtx ubicom32_compare_op0;
-+rtx ubicom32_compare_op1;
-+
-+/* Handle command line option overrides.  */
-+
-+void
-+ubicom32_override_options (void)
-+{
-+  flag_pic = 0;
-+
-+  if (strcmp (ubicom32_arch_name, "ubicom32v1") == 0) {
-+    /* If we have a version 1 architecture then we want to avoid using jump
-+       tables.  */
-+    ubicom32_case_values_threshold = 30000;
-+    ubicom32_v3 = 0;
-+    ubicom32_v4 = 0;
-+  } else if (strcmp (ubicom32_arch_name, "ubicom32v2") == 0) {
-+    ubicom32_v3 = 0;
-+    ubicom32_v4 = 0;
-+  } else if (strcmp (ubicom32_arch_name, "ubicom32v3") == 0) {
-+    ubicom32_v3 = 1;
-+    ubicom32_v4 = 0;
-+  } else if (strcmp (ubicom32_arch_name, "ubicom32v4") == 0) {
-+    ubicom32_v3 = 1;
-+    ubicom32_v4 = 1;
-+  }
-+
-+  /* There is no single unaligned SI op for PIC code.  Sometimes we
-+     need to use ".4byte" and sometimes we need to use ".picptr".
-+     See ubicom32_assemble_integer for details.  */
-+  if (TARGET_FDPIC)
-+    targetm.asm_out.unaligned_op.si = 0;
-+}
-+
-+void
-+ubicom32_conditional_register_usage (void)
-+{
-+  /* If we're using the old ipOS ABI we need to make D10 through D13
-+     caller-clobbered.  */
-+  if (TARGET_IPOS_ABI)
-+    {
-+      call_used_regs[D10_REGNUM] = 1;
-+      call_used_regs[D11_REGNUM] = 1;
-+      call_used_regs[D12_REGNUM] = 1;
-+      call_used_regs[D13_REGNUM] = 1;
-+    }
-+}
-+
-+/* We have some number of optimizations that don't really work for the Ubicom32
-+   architecture so we deal with them here.  */
-+
-+void
-+ubicom32_optimization_options (int level ATTRIBUTE_UNUSED,
-+                             int size ATTRIBUTE_UNUSED)
-+{
-+  /* The tree IVOPTs pass seems to do really bad things for the Ubicom32
-+     architecture - it tends to turn things that would happily use pre/post
-+     increment/decrement into operations involving unecessary loop
-+     indicies.  */
-+  flag_ivopts = 0;
-+
-+  /* We have problems where DSE at the RTL level misses partial stores
-+     to the stack.  For now we disable it to avoid this.  */
-+  flag_dse = 0;
-+}
-+
-+/* Print operand X using operand code CODE to assembly language output file
-+   FILE.  */
-+
-+void
-+ubicom32_print_operand (FILE *file, rtx x, int code)
-+{
-+  switch (code)
-+    {
-+    case 'A':
-+      /* Identify the correct accumulator to use.  */
-+      if (REGNO (x) == ACC0_HI_REGNUM || REGNO (x) == ACC0_LO_REGNUM)
-+      fprintf (file, "acc0");
-+      else if (REGNO (x) == ACC1_HI_REGNUM || REGNO (x) == ACC1_LO_REGNUM)
-+      fprintf (file, "acc1");
-+      else
-+      abort ();
-+      break;
-+
-+    case 'b':
-+    case 'B':
-+      {
-+      enum machine_mode mode;
-+
-+      mode = GET_MODE (XEXP (x, 0));
-+
-+      /* These are normal and reversed branches.  */
-+      switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x)))
-+        {
-+        case NE:
-+          fprintf (file, "ne");
-+          break;
-+
-+        case EQ:
-+          fprintf (file, "eq");
-+          break;
-+
-+        case GE:
-+          if (mode == CCSZNmode || mode == CCWZNmode)
-+            fprintf (file, "pl");
-+          else
-+            fprintf (file, "ge");
-+          break;
-+
-+        case GT:
-+          fprintf (file, "gt");
-+          break;
-+
-+        case LE:
-+          fprintf (file, "le");
-+          break;
-+
-+        case LT:
-+          if (mode == CCSZNmode || mode == CCWZNmode)
-+            fprintf (file, "mi");
-+          else
-+            fprintf (file, "lt");
-+          break;
-+
-+        case GEU:
-+          fprintf (file, "cs");
-+          break;
-+
-+        case GTU:
-+          fprintf (file, "hi");
-+          break;
-+
-+        case LEU:
-+          fprintf (file, "ls");
-+          break;
-+
-+        case LTU:
-+          fprintf (file, "cc");
-+          break;
-+
-+        default:
-+          abort ();
-+        }
-+      }
-+      break;
-+
-+    case 'C':
-+      /* This is used for the operand to a call instruction;
-+       if it's a REG, enclose it in parens, else output
-+       the operand normally.  */
-+      if (REG_P (x))
-+      {
-+        fputc ('(', file);
-+        ubicom32_print_operand (file, x, 0);
-+        fputc (')', file);
-+      }
-+      else
-+      ubicom32_print_operand (file, x, 0);
-+      break;
-+
-+    case 'd':
-+      /* Bit operations we need bit numbers. */
-+      fprintf (file, "%d", exact_log2 (INTVAL (x)));
-+      break;
-+
-+    case 'D':
-+      /* Bit operations we need bit numbers. */
-+      fprintf (file, "%d", exact_log2 (~ INTVAL (x)));
-+      break;
-+
-+    case 'E':
-+      /* For lea, which we use to add address registers.
-+       We don't want the '#' on a constant. */
-+      if (CONST_INT_P (x))
-+      {
-+        fprintf (file, "%ld", INTVAL (x));
-+        break;
-+      }
-+      /* FALL THROUGH */
-+
-+    default:
-+      switch (GET_CODE (x))
-+      {
-+      case MEM:
-+        output_memory_reference_mode = GET_MODE (x);
-+        output_address (XEXP (x, 0));
-+        break;
-+
-+      case PLUS:
-+        output_address (x);
-+        break;
-+
-+      case REG:
-+        fprintf (file, "%s", reg_names[REGNO (x)]);
-+        break;
-+
-+      case SUBREG:
-+        fprintf (file, "%s", reg_names[subreg_regno (x)]);
-+        break;
-+
-+      /* This will only be single precision....  */
-+      case CONST_DOUBLE:
-+        {
-+          unsigned long val;
-+          REAL_VALUE_TYPE rv;
-+
-+          REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
-+          REAL_VALUE_TO_TARGET_SINGLE (rv, val);
-+          fprintf (file, "0x%lx", val);
-+          break;
-+        }
-+
-+      case CONST_INT:
-+      case SYMBOL_REF:
-+      case CONST:
-+      case LABEL_REF:
-+      case CODE_LABEL:
-+      case LO_SUM:
-+        ubicom32_print_operand_address (file, x);
-+        break;
-+
-+      case HIGH:
-+        fprintf (file, "#%%hi(");
-+        ubicom32_print_operand_address (file, XEXP (x, 0));
-+        fprintf (file, ")");
-+        break;
-+
-+      case UNSPEC:
-+        switch (XINT (x, 1))
-+          {
-+          case UNSPEC_FDPIC_GOT:
-+            fprintf (file, "#%%got_lo(");
-+            ubicom32_print_operand_address (file, XVECEXP (x, 0, 0));
-+            fprintf (file, ")");
-+            break;
-+
-+          case UNSPEC_FDPIC_GOT_FUNCDESC:
-+            fprintf (file, "#%%got_funcdesc_lo(");
-+            ubicom32_print_operand_address (file, XVECEXP (x, 0, 0));
-+            fprintf (file, ")");
-+            break;
-+
-+          default:
-+            abort ();
-+          }
-+          break;
-+
-+      default:
-+        abort ();
-+      }
-+      break;
-+   }
-+}
-+
-+/* Output assembly language output for the address ADDR to FILE.  */
-+
-+void
-+ubicom32_print_operand_address (FILE *file, rtx addr)
-+{
-+  switch (GET_CODE (addr))
-+    {
-+    case POST_INC:
-+      ubicom32_print_operand_address (file, XEXP (addr, 0));
-+      fprintf (file, "%d++", GET_MODE_SIZE (output_memory_reference_mode));
-+      break;
-+
-+    case PRE_INC:
-+      fprintf (file, "%d", GET_MODE_SIZE (output_memory_reference_mode));
-+      ubicom32_print_operand_address (file, XEXP (addr, 0));
-+      fprintf (file, "++");
-+      break;
-+
-+    case POST_DEC:
-+      ubicom32_print_operand_address (file, XEXP (addr, 0));
-+      fprintf (file, "%d++", -GET_MODE_SIZE (output_memory_reference_mode));
-+      break;
-+
-+    case PRE_DEC:
-+      fprintf (file, "%d", -GET_MODE_SIZE (output_memory_reference_mode));
-+      ubicom32_print_operand_address (file, XEXP (addr, 0));
-+      fprintf (file, "++");
-+      break;
-+
-+    case POST_MODIFY:
-+      ubicom32_print_operand_address (file, XEXP (addr, 0));
-+      fprintf (file, "%ld++", INTVAL (XEXP (XEXP (addr,1), 1)));
-+      break;
-+
-+    case PRE_MODIFY:
-+      fprintf (file, "%ld", INTVAL (XEXP (XEXP (addr,1), 1)));
-+      ubicom32_print_operand_address (file, XEXP (addr, 0));
-+      fprintf (file, "++");
-+      break;
-+
-+    case REG:
-+      fputc ('(', file);
-+      fprintf (file, "%s", reg_names[REGNO (addr)]); 
-+      fputc (')', file);
-+      break;
-+
-+    case PLUS:
-+      {
-+      rtx base = XEXP (addr, 0);
-+      rtx index = XEXP (addr, 1); 
-+
-+      /* Switch around addresses of the form index * scaling + base.  */
-+      if (! ubicom32_is_base_reg (base, 1))
-+        {
-+          rtx tmp = base;
-+          base = index;
-+          index = tmp;
-+        }
-+
-+      if (CONST_INT_P (index)) 
-+        {
-+          fprintf (file, "%ld", INTVAL (index)); 
-+          fputc ('(', file);
-+          fputs (reg_names[REGNO (base)], file); 
-+        }
-+      else if (GET_CODE (index) == MULT
-+               || REG_P (index))
-+        {
-+          if (GET_CODE (index) == MULT)
-+            index = XEXP (index, 0);
-+          fputc ('(', file);
-+          fputs (reg_names[REGNO (base)], file); 
-+          fputc (',', file);
-+          fputs (reg_names[REGNO (index)], file); 
-+        }
-+      else 
-+        abort (); 
-+
-+      fputc (')', file);
-+      break;
-+      }
-+
-+    case LO_SUM:
-+      fprintf (file, "%%lo(");
-+      ubicom32_print_operand (file, XEXP (addr, 1), 'L');
-+      fprintf (file, ")(");
-+      ubicom32_print_operand (file, XEXP (addr, 0), 0);
-+      fprintf (file, ")");
-+      break;
-+
-+    case CONST_INT:
-+      fputc ('#', file);
-+      output_addr_const (file, addr); 
-+      break;
-+
-+    default:
-+      output_addr_const (file, addr);
-+      break;
-+    }
-+}
-+
-+/* X and Y are two things to compare using CODE.  Emit the compare insn and
-+   return the rtx for the cc reg in the proper mode.  */
-+
-+rtx
-+ubicom32_gen_compare_reg (enum rtx_code code, rtx x, rtx y)
-+{
-+  enum machine_mode mode = SELECT_CC_MODE (code, x, y);
-+  rtx cc_reg;
-+
-+  cc_reg = gen_rtx_REG (mode, CC_REGNUM);
-+
-+  emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
-+                        gen_rtx_COMPARE (mode, x, y)));
-+
-+  return cc_reg;
-+}
-+
-+/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
-+   return the mode to be used for the comparison.  */
-+
-+enum machine_mode
-+ubicom32_select_cc_mode (enum rtx_code op, rtx x, rtx y)
-+{
-+  /* Is this a short compare?  */
-+  if (GET_MODE (x) == QImode
-+      || GET_MODE (x) == HImode
-+      || GET_MODE (y) == QImode
-+      || GET_MODE (y) == HImode)
-+    {
-+      switch (op)
-+      {
-+      case EQ :
-+      case NE :
-+        return CCSZmode;
-+
-+      case GE:
-+      case LT:
-+        if (y == const0_rtx)
-+          return CCSZNmode;
-+
-+      default :
-+        return CCSmode;
-+      }
-+    }
-+
-+  /* We have a word compare.  */
-+  switch (op)
-+    {
-+    case EQ :
-+    case NE :
-+      return CCWZmode;
-+
-+    case GE :
-+    case LT :
-+      if (y == const0_rtx)
-+      return CCWZNmode;
-+
-+    default :
-+      return CCWmode;
-+    }
-+}
-+
-+/* Return TRUE or FALSE depending on whether the first SET in INSN
-+   has source and destination with matching CC modes, and that the
-+   CC mode is at least as constrained as REQ_MODE.  */
-+bool
-+ubicom32_match_cc_mode (rtx insn, enum machine_mode req_mode)
-+{
-+  rtx set;
-+  enum machine_mode set_mode;
-+
-+  set = PATTERN (insn);
-+  if (GET_CODE (set) == PARALLEL)
-+    set = XVECEXP (set, 0, 0);
-+  gcc_assert (GET_CODE (set) == SET);
-+  gcc_assert (GET_CODE (SET_SRC (set)) == COMPARE);
-+
-+  /* SET_MODE is the mode we have in the instruction.  This must either
-+     be the same or less restrictive that the required mode REQ_MODE.  */
-+  set_mode = GET_MODE (SET_DEST (set));
-+
-+  switch (req_mode)
-+    {
-+    case CCSZmode:
-+      if (set_mode != CCSZmode)
-+      return 0;
-+      break;
-+
-+    case CCSZNmode:
-+      if (set_mode != CCSZmode
-+        && set_mode != CCSZNmode)
-+      return 0;
-+      break;
-+
-+    case CCSmode:
-+      if (set_mode != CCSmode
-+        && set_mode != CCSZmode
-+        && set_mode != CCSZNmode)
-+      return 0;
-+      break;
-+
-+    case CCWZmode:
-+      if (set_mode != CCWZmode)
-+      return 0;
-+      break;
-+
-+    case CCWZNmode:
-+      if (set_mode != CCWZmode
-+        && set_mode != CCWZNmode)
-+      return 0;
-+      break;
-+
-+    case CCWmode:
-+      if (set_mode != CCWmode
-+        && set_mode != CCWZmode
-+        && set_mode != CCWZNmode)
-+      return 0;
-+      break;
-+
-+    default:
-+      gcc_unreachable ();
-+    }
-+
-+  return (GET_MODE (SET_SRC (set)) == set_mode);
-+}
-+
-+/* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
-+   that we can implement more efficiently.  */
-+
-+void
-+ubicom32_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
-+{
-+  /* If we have a REG and a MEM then compare the MEM with the REG and not
-+     the other way round.  */
-+  if (REG_P (*op0) && MEM_P (*op1))
-+    {
-+      rtx tem = *op0;
-+      *op0 = *op1;
-+      *op1 = tem;
-+      *code = swap_condition (*code);
-+      return;
-+    }
-+
-+  /* If we have a REG and a CONST_INT then we may want to reverse things
-+     if the constant can be represented as an "I" constraint.  */
-+  if (REG_P (*op0) && CONST_INT_P (*op1) && satisfies_constraint_I (*op1))
-+    {
-+      rtx tem = *op0;
-+      *op0 = *op1;
-+      *op1 = tem;
-+      *code = swap_condition (*code);
-+      return;
-+    }
-+}
-+
-+/* Return the fixed registers used for condition codes.  */
-+
-+static bool
-+ubicom32_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
-+{
-+  *p1 = CC_REGNUM;
-+  *p2 = INVALID_REGNUM;
-+ 
-+  return true;
-+}
-+
-+/* If two condition code modes are compatible, return a condition code
-+   mode which is compatible with both.  Otherwise, return
-+   VOIDmode.  */
-+
-+static enum machine_mode
-+ubicom32_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
-+{
-+  if (m1 == m2)
-+    return m1;
-+
-+  if (GET_MODE_CLASS (m1) != MODE_CC || GET_MODE_CLASS (m2) != MODE_CC)
-+    return VOIDmode;
-+
-+  switch (m1)
-+    {
-+    case CCWmode:
-+      if (m2 == CCWZNmode || m2 == CCWZmode)
-+      return m1;
-+
-+      return VOIDmode;
-+
-+    case CCWZNmode:
-+      if (m2 == CCWmode)
-+      return m2;
-+
-+      if (m2 == CCWZmode)
-+      return m1;
-+
-+      return VOIDmode;
-+
-+    case CCWZmode:
-+      if (m2 == CCWmode || m2 == CCWZNmode)
-+      return m2;
-+
-+      return VOIDmode;
-+
-+    case CCSmode:
-+      if (m2 == CCSZNmode || m2 == CCSZmode)
-+      return m1;
-+
-+      return VOIDmode;
-+
-+    case CCSZNmode:
-+      if (m2 == CCSmode)
-+      return m2;
-+
-+      if (m2 == CCSZmode)
-+      return m1;
-+
-+      return VOIDmode;
-+
-+    case CCSZmode:
-+      if (m2 == CCSmode || m2 == CCSZNmode)
-+      return m2;
-+
-+      return VOIDmode;
-+
-+    default:
-+      gcc_unreachable ();
-+    }
-+}
-+
-+static rtx
-+ubicom32_legitimize_fdpic_address_symbol (rtx orig, rtx reg, rtx fdpic_reg)
-+{
-+  int unspec;
-+  rtx got_offs;
-+  rtx got_offs_scaled;
-+  rtx plus_scaled;
-+  rtx tmp;
-+  rtx new_rtx;
-+
-+  gcc_assert (reg != 0);
-+
-+  if (GET_CODE (orig) == SYMBOL_REF
-+      && SYMBOL_REF_FUNCTION_P (orig))
-+    unspec = UNSPEC_FDPIC_GOT_FUNCDESC;
-+  else
-+    unspec = UNSPEC_FDPIC_GOT;
-+
-+  got_offs = gen_reg_rtx (SImode);
-+  tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, orig), unspec);
-+  emit_move_insn (got_offs, tmp);
-+
-+  got_offs_scaled = gen_rtx_MULT (SImode, got_offs, GEN_INT (4));
-+  plus_scaled = gen_rtx_PLUS (Pmode, fdpic_reg, got_offs_scaled);
-+  new_rtx = gen_const_mem (Pmode, plus_scaled);
-+  emit_move_insn (reg, new_rtx);
-+
-+  return reg;
-+}
-+
-+static rtx
-+ubicom32_legitimize_fdpic_address (rtx orig, rtx reg, rtx fdpic_reg)
-+{
-+  rtx addr = orig;
-+  rtx new_rtx = orig;
-+
-+  if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
-+    {
-+      rtx base;
-+
-+      if (GET_CODE (addr) == CONST)
-+      {
-+        addr = XEXP (addr, 0);
-+        gcc_assert (GET_CODE (addr) == PLUS);
-+      }
-+
-+      base = ubicom32_legitimize_fdpic_address_symbol (XEXP (addr, 0), reg, fdpic_reg);
-+      return gen_rtx_PLUS (Pmode, base, XEXP (addr, 1));
-+    }
-+
-+  return new_rtx;
-+}
-+
-+/* Code generation.  */
-+
-+void
-+ubicom32_expand_movsi (rtx *operands)
-+{
-+  if (GET_CODE (operands[1]) == SYMBOL_REF
-+      || (GET_CODE (operands[1]) == CONST
-+        && GET_CODE (XEXP (operands[1], 0)) == PLUS
-+        && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
-+      || CONSTANT_ADDRESS_P (operands[1]))
-+    {
-+      if (TARGET_FDPIC)
-+      {
-+        rtx tmp;
-+        rtx fdpic_reg;
-+
-+        gcc_assert (can_create_pseudo_p ());
-+        tmp = gen_reg_rtx (Pmode);
-+        fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM);
-+        if (GET_CODE (operands[1]) == SYMBOL_REF
-+            || GET_CODE (operands[1]) == LABEL_REF)
-+          operands[1] = ubicom32_legitimize_fdpic_address_symbol (operands[1], tmp, fdpic_reg);
-+        else
-+          operands[1] = ubicom32_legitimize_fdpic_address (operands[1], tmp, fdpic_reg);
-+      }
-+      else
-+      {
-+        rtx tmp;
-+        enum machine_mode mode;
-+
-+        /* We want to avoid reusing operand 0 if we can because it limits
-+           our ability to optimize later.  */
-+        tmp = ! can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
-+
-+        mode = GET_MODE (operands[0]);
-+        emit_insn (gen_rtx_SET (VOIDmode, tmp,
-+                                gen_rtx_HIGH (mode, operands[1])));
-+        operands[1] = gen_rtx_LO_SUM (mode, tmp, operands[1]);
-+        if (can_create_pseudo_p() && ! REG_P (operands[0]))
-+          {
-+            tmp = gen_reg_rtx (mode);
-+            emit_insn (gen_rtx_SET (VOIDmode, tmp, operands[1]));
-+            operands[1] = tmp;
-+          }
-+      }
-+    }
-+}
-+
-+/* Emit code for addsi3.  */
-+
-+void
-+ubicom32_expand_addsi3 (rtx *operands)
-+{
-+  rtx op, clob;
-+
-+  if (can_create_pseudo_p ())
-+    {
-+      /* If we have a non-data reg for operand 1 then prefer that over
-+         a CONST_INT in operand 2.  */
-+      if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
-+        && CONST_INT_P (operands[2]))
-+      operands[2] = copy_to_mode_reg (SImode, operands[2]);
-+
-+      if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
-+      operands[2] = copy_to_mode_reg (SImode, operands[2]);
-+    }
-+
-+  /* Emit the instruction.  */
-+
-+  op = gen_rtx_SET (VOIDmode, operands[0],
-+                  gen_rtx_PLUS (SImode, operands[1], operands[2]));
-+
-+  if (! can_create_pseudo_p ())
-+    {
-+      /* Reload doesn't know about the flags register, and doesn't know that
-+         it doesn't want to clobber it.  We can only do this with PLUS.  */
-+      emit_insn (op);
-+    }
-+  else
-+    {
-+      clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
-+      emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
-+    }
-+}
-+
-+/* Emit code for mulsi3.  Return 1 if we have generated all the code
-+   necessary to do the multiplication.  */
-+
-+int
-+ubicom32_emit_mult_sequence (rtx *operands)
-+{
-+  if (! ubicom32_v4)
-+    {
-+      rtx a1, a1_1, a2;
-+      rtx b1, b1_1, b2;
-+      rtx mac_lo_rtx;
-+      rtx t1, t2, t3;
-+
-+      /* Give up if we cannot create new pseudos.  */
-+      if (!can_create_pseudo_p())
-+      return 0;
-+
-+      /* Synthesize 32-bit multiplication using 16-bit operations:
-+     
-+       a1 = highpart (a)
-+       a2 = lowpart (a)
-+
-+       b1 = highpart (b)
-+       b2 = lowpart (b)
-+
-+       c = (a1 * b1) << 32 + (a1 * b2) << 16 + (a2 * b1) << 16 + a2 * b2
-+         =        0        + (a1 * b2) << 16 + (a2 * b1) << 16 + a2 * b2
-+                             ^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^   ^^^^^^^
-+                                 Signed             Signed      Unsigned  */
-+
-+      if (!ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])))
-+      {
-+        rtx op1;
-+
-+        op1 = gen_reg_rtx (SImode);
-+        emit_move_insn (op1, operands[1]);
-+        operands[1] = op1;
-+      }
-+
-+      if (!ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))
-+      {
-+        rtx op2;
-+
-+        op2 = gen_reg_rtx (SImode);
-+        emit_move_insn (op2, operands[2]);
-+        operands[2] = op2;
-+      }
-+
-+      /* a1 = highpart (a)  */
-+      a1 = gen_reg_rtx (HImode);
-+      a1_1 = gen_reg_rtx (SImode);
-+      emit_insn (gen_ashrsi3 (a1_1, operands[1], GEN_INT (16)));
-+      emit_move_insn (a1, gen_lowpart (HImode, a1_1));
-+
-+      /* a2 = lowpart (a)  */
-+      a2 = gen_reg_rtx (HImode);
-+      emit_move_insn (a2, gen_lowpart (HImode, operands[1]));
-+
-+      /* b1 = highpart (b)  */
-+      b1 = gen_reg_rtx (HImode);
-+      b1_1 = gen_reg_rtx (SImode);
-+      emit_insn (gen_ashrsi3 (b1_1, operands[2], GEN_INT (16)));
-+      emit_move_insn (b1, gen_lowpart (HImode, b1_1));
-+
-+      /* b2 = lowpart (b)  */
-+      b2 = gen_reg_rtx (HImode);
-+      emit_move_insn (b2, gen_lowpart (HImode, operands[2]));
-+
-+      /* t1 = (a1 * b2) << 16  */
-+      t1 = gen_reg_rtx (SImode);
-+      mac_lo_rtx = gen_rtx_REG (SImode, ACC0_LO_REGNUM);
-+      emit_insn (gen_mulhisi3 (mac_lo_rtx, a1, b2));
-+      emit_insn (gen_ashlsi3 (t1, mac_lo_rtx, GEN_INT (16)));
-+
-+      /* t2 = (a2 * b1) << 16  */
-+      t2 = gen_reg_rtx (SImode);
-+      emit_insn (gen_mulhisi3 (mac_lo_rtx, a2, b1));
-+      emit_insn (gen_ashlsi3 (t2, mac_lo_rtx, GEN_INT (16)));
-+
-+      /* mac_lo = a2 * b2  */
-+      emit_insn (gen_umulhisi3 (mac_lo_rtx, a2, b2));
-+
-+      /* t3 = t1 + t2  */
-+      t3 = gen_reg_rtx (SImode);
-+      emit_insn (gen_addsi3 (t3, t1, t2));
-+
-+      /* c = t3 + mac_lo_rtx  */
-+      emit_insn (gen_addsi3 (operands[0], mac_lo_rtx, t3));
-+
-+      return 1;
-+    }
-+  else
-+    {
-+      rtx acc_rtx;
-+
-+      /* Give up if we cannot create new pseudos.  */
-+      if (!can_create_pseudo_p())
-+      return 0;
-+
-+      if (!ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])))
-+        {
-+        rtx op1;
-+
-+        op1 = gen_reg_rtx (SImode);
-+        emit_move_insn (op1, operands[1]);
-+        operands[1] = op1;
-+      }
-+
-+      if (!ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))
-+      {
-+        rtx op2;
-+
-+        op2 = gen_reg_rtx (SImode);
-+        emit_move_insn (op2, operands[2]);
-+        operands[2] = op2;
-+      }
-+
-+      acc_rtx = gen_reg_rtx (DImode);
-+      emit_insn (gen_umulsidi3 (acc_rtx, operands[1], operands[2]));
-+      emit_move_insn (operands[0], gen_lowpart (SImode, acc_rtx));
-+
-+      return 1;
-+    }
-+}
-+
-+/* Move the integer value VAL into OPERANDS[0].  */
-+
-+void
-+ubicom32_emit_move_const_int (rtx dest, rtx imm)
-+{
-+  rtx xoperands[2];
-+  
-+  xoperands[0] = dest;
-+  xoperands[1] = imm;
-+
-+  /* Treat mem destinations separately.  Values must be explicitly sign
-+     extended.  */
-+  if (MEM_P (dest))
-+    {
-+      rtx low_hword_mem;
-+      rtx low_hword_addr;
-+
-+      /* Emit shorter sequence for signed 7-bit quantities.  */
-+      if (satisfies_constraint_I (imm))
-+      {
-+          output_asm_insn ("move.4\t%0, %1", xoperands);
-+          return;
-+      }
-+
-+      /* Special case for pushing constants.  */
-+      if (GET_CODE (XEXP (dest, 0)) == PRE_DEC
-+        && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx)
-+      {
-+        output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
-+        output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
-+        return;
-+      }
-+
-+      /* See if we can add 2 to the original address.  This is only
-+       possible if the original address is of the form REG or
-+       REG+const.  */
-+      low_hword_addr = plus_constant (XEXP (dest, 0), 2);
-+      if (ubicom32_legitimate_address_p (HImode, low_hword_addr, 1))
-+      {
-+        low_hword_mem = gen_rtx_MEM (HImode, low_hword_addr);
-+        MEM_COPY_ATTRIBUTES (low_hword_mem, dest);
-+        output_asm_insn ("movei\t%0, #%%hi(%E1)", xoperands);
-+        xoperands[0] = low_hword_mem;
-+        output_asm_insn ("movei\t%0, #%%lo(%E1)", xoperands);
-+        return;
-+      }
-+
-+      /* The original address is too complex.  We need to use a
-+       scratch memory by (sp) and move that to the original
-+       destination.  */
-+      if (! reg_mentioned_p (stack_pointer_rtx, dest))
-+      {
-+        output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
-+        output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
-+        output_asm_insn ("move.4\t%0, (sp)4++", xoperands);
-+        return;
-+      }
-+
-+      /* Our address mentions the stack pointer so we need to
-+       use our scratch data register here as well as scratch
-+       memory.  */
-+      output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
-+      output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
-+      output_asm_insn ("move.4\td15, (sp)4++", xoperands);
-+      output_asm_insn ("move.4\t%0, d15", xoperands);
-+      return;
-+    }
-+
-+  /* Move into registers are zero extended by default.  */
-+  if (! REG_P (dest))
-+    abort ();
-+
-+  if (satisfies_constraint_N (imm))
-+    {
-+      output_asm_insn ("movei\t%0, %1", xoperands);
-+      return;
-+    }
-+
-+  if (INTVAL (xoperands[1]) >= 0xff80
-+      && INTVAL (xoperands[1]) < 0x10000)
-+    {
-+      xoperands[1] = GEN_INT (INTVAL (xoperands[1]) - 0x10000);
-+      output_asm_insn ("move.2\t%0, %1", xoperands);
-+      return;
-+    }
-+
-+  if ((REGNO_REG_CLASS (REGNO (xoperands[0])) == ADDRESS_REGS
-+       || REGNO_REG_CLASS (REGNO (xoperands[0])) == FDPIC_REG)
-+      && ((INTVAL (xoperands[1]) & 0x80000000) == 0))
-+    {
-+      output_asm_insn ("moveai\t%0, #%%hi(%E1)", xoperands);
-+      if ((INTVAL (xoperands[1]) & 0x7f) != 0)
-+      output_asm_insn ("lea.1\t%0, %%lo(%E1)(%0)", xoperands);
-+      return;
-+    }
-+
-+  if ((INTVAL (xoperands[1]) & 0xffff0000) == 0)
-+    {
-+      output_asm_insn ("movei\t%0, #%%lo(%E1)", xoperands);
-+      output_asm_insn ("move.2\t%0, %0", xoperands);
-+      return;
-+    }
-+
-+  /* This is very expensive.  The constant is so large that we
-+     need to use the stack to do the load.  */
-+  output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
-+  output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
-+  output_asm_insn ("move.4\t%0, (sp)4++", xoperands);
-+}
-+
-+/* Stack layout. Prologue/Epilogue.  */
-+
-+static int save_regs_size;
-+
-+static void 
-+ubicom32_layout_frame (void)
-+{
-+  int regno;
-+  
-+  memset ((char *) &save_regs[0], 0, sizeof (save_regs));
-+  nregs = 0;
-+  frame_size = get_frame_size ();
-+
-+  if (frame_pointer_needed || df_regs_ever_live_p (FRAME_POINTER_REGNUM))
-+    {
-+      save_regs[FRAME_POINTER_REGNUM] = 1;
-+      ++nregs;
-+    }
-+
-+  if (current_function_is_leaf && ! df_regs_ever_live_p (LINK_REGNO))
-+    ubicom32_can_use_calli_to_ret = 1;
-+  else
-+    {
-+      ubicom32_can_use_calli_to_ret = 0;
-+      save_regs[LINK_REGNO] = 1;
-+      ++nregs;
-+    }
-+
-+  /* Figure out which register(s) needs to be saved.  */
-+  for (regno = 0; regno <= LAST_ADDRESS_REGNUM; regno++)
-+      if (df_regs_ever_live_p(regno)
-+      && ! call_used_regs[regno]
-+      && ! fixed_regs[regno]
-+      && ! save_regs[regno])
-+    {
-+      save_regs[regno] = 1;
-+      ++nregs;
-+    }
-+
-+  save_regs_size = 4 * nregs;
-+}
-+
-+static void
-+ubicom32_emit_add_movsi (int regno, int adj)
-+{
-+  rtx x;
-+  rtx reg = gen_rtx_REG (SImode, regno);
-+
-+  adj += 4;
-+  if (adj > 8 * 4) 
-+    {
-+      x = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-+                               GEN_INT (-adj)));
-+      RTX_FRAME_RELATED_P (x) = 1;
-+      x = emit_move_insn (gen_rtx_MEM (SImode, stack_pointer_rtx), reg);
-+    }
-+  else
-+    {
-+      rtx addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx,
-+                                   gen_rtx_PLUS (Pmode, stack_pointer_rtx,
-+                                                 GEN_INT (-adj)));
-+      x = emit_move_insn (gen_rtx_MEM (SImode, addr), reg);
-+    }
-+  RTX_FRAME_RELATED_P (x) = 1;      
-+}
-+
-+void
-+ubicom32_expand_prologue (void)
-+{
-+  rtx x;
-+  int regno;
-+  int outgoing_args_size = crtl->outgoing_args_size;
-+  int adj;
-+
-+  if (ubicom32_naked_function_p ())
-+    return;
-+
-+  ubicom32_builtin_saveregs ();
-+  
-+  ubicom32_layout_frame ();
-+  adj = (outgoing_args_size + get_frame_size () + save_regs_size
-+       + crtl->args.pretend_args_size);
-+  
-+  if (!adj)
-+    ;
-+  else if (outgoing_args_size + save_regs_size < 508
-+         && get_frame_size () + save_regs_size > 508)
-+    {
-+      int i = 0;
-+      x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-+                    GEN_INT (-adj));
-+      x = emit_insn (x);
-+      RTX_FRAME_RELATED_P (x) = 1;
-+
-+      for (regno = LAST_ADDRESS_REGNUM; regno >= 0; --regno)
-+      if (save_regs[regno] && regno != LINK_REGNO)
-+        {
-+          x = gen_rtx_MEM (SImode,
-+                           gen_rtx_PLUS (Pmode,
-+                                         stack_pointer_rtx,
-+                                         GEN_INT (i * 4 + outgoing_args_size)));
-+          x = emit_move_insn (x, gen_rtx_REG (SImode, regno));
-+          RTX_FRAME_RELATED_P (x) = 1;
-+          ++i;
-+        }
-+      if (save_regs[LINK_REGNO])
-+      {
-+        x = gen_rtx_MEM (SImode,
-+                         gen_rtx_PLUS (Pmode,
-+                                       stack_pointer_rtx,
-+                                       GEN_INT (i * 4 + outgoing_args_size)));
-+        x = emit_move_insn (x, gen_rtx_REG (SImode, LINK_REGNO));
-+        RTX_FRAME_RELATED_P (x) = 1;
-+      }
-+    }
-+  else
-+    {
-+      int regno;
-+      int adj = get_frame_size () + crtl->args.pretend_args_size;
-+      int i = 0;
-+
-+      if (save_regs[LINK_REGNO])
-+      {
-+        ubicom32_emit_add_movsi (LINK_REGNO, adj);
-+        ++i;
-+      }
-+      
-+      for (regno = 0; regno <= LAST_ADDRESS_REGNUM; ++regno)
-+      if (save_regs[regno] && regno != LINK_REGNO)
-+        {
-+          if (i)
-+            {
-+              rtx mem = gen_rtx_MEM (SImode,
-+                                     gen_rtx_PRE_DEC (Pmode,
-+                                                      stack_pointer_rtx));
-+              x = emit_move_insn (mem, gen_rtx_REG (SImode, regno));
-+              RTX_FRAME_RELATED_P (x) = 1;
-+            }
-+          else
-+            ubicom32_emit_add_movsi (regno, adj);
-+          ++i;
-+        }
-+      
-+      if (outgoing_args_size || (!i && adj))
-+      {
-+        x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-+                        GEN_INT (-outgoing_args_size - (i ? 0 : adj)));
-+        x = emit_insn (x);
-+        RTX_FRAME_RELATED_P (x) = 1;
-+      }
-+    }
-+
-+  if (frame_pointer_needed)
-+    {
-+      int fp_adj = save_regs_size + outgoing_args_size;
-+      x = gen_addsi3 (frame_pointer_rtx, stack_pointer_rtx,
-+                    GEN_INT (fp_adj));
-+      x = emit_insn (x);
-+      RTX_FRAME_RELATED_P (x) = 1;
-+    }
-+}
-+
-+void
-+ubicom32_expand_epilogue (void)
-+{
-+  rtx x;
-+  int regno;
-+  int outgoing_args_size = crtl->outgoing_args_size;
-+  int adj;
-+  int i;
-+
-+  if (ubicom32_naked_function_p ())
-+    {
-+      emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode,
-+                                                      LINK_REGNO)));
-+      return;
-+    }
-+
-+  if (cfun->calls_alloca)
-+    {
-+      x = gen_addsi3 (stack_pointer_rtx, frame_pointer_rtx,
-+                    GEN_INT (-save_regs_size));
-+      emit_insn (x);
-+      outgoing_args_size = 0;
-+    }
-+  
-+  if (outgoing_args_size)
-+    {
-+      x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-+                    GEN_INT (outgoing_args_size));
-+      emit_insn (x);
-+    }
-+
-+  i = 0;
-+  for (regno = LAST_ADDRESS_REGNUM; regno >= 0; --regno)
-+    if (save_regs[regno] && regno != LINK_REGNO)
-+      {
-+      x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
-+      emit_move_insn (gen_rtx_REG (SImode, regno), x);
-+      ++i;
-+      }
-+
-+  /* Do we have to adjust the stack after we've finished restoring regs?  */
-+  adj = get_frame_size() + crtl->args.pretend_args_size;
-+  if (cfun->stdarg)
-+    adj += UBICOM32_FUNCTION_ARG_REGS * UNITS_PER_WORD;
-+ 
-+#if 0
-+  if (crtl->calls_eh_return && 0)
-+    {
-+      if (save_regs[LINK_REGNO])
-+        {
-+          x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
-+          emit_move_insn (gen_rtx_REG (SImode, LINK_REGNO), x);
-+        }
-+
-+      if (adj)
-+        {
-+          x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-+                        GEN_INT (adj));
-+          x = emit_insn (x);
-+        }
-+
-+      /* Perform the additional bump for __throw.  */
-+      emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-+                           EH_RETURN_STACKADJ_RTX));
-+      emit_jump_insn (gen_eh_return_internal ());
-+      return;
-+    }
-+#endif
-+
-+  if (save_regs[LINK_REGNO])
-+    {
-+      if (adj >= 4 && adj <= (6 * 4))
-+        {
-+        x = GEN_INT (adj + 4);
-+          emit_jump_insn (gen_return_from_post_modify_sp (x));
-+        return;
-+        }
-+
-+      if (adj == 0)
-+      {
-+          x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
-+          emit_jump_insn (gen_return_internal (x));
-+          return;
-+      }
-+
-+      x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
-+      emit_move_insn (gen_rtx_REG (SImode, LINK_REGNO), x);
-+    }
-+
-+  if (adj)
-+    {
-+      x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-+                    GEN_INT (adj));
-+      x = emit_insn (x);
-+      adj = 0;
-+    }
-+
-+  /* Given that we've just done all the hard work here we may as well use
-+     a calli to return.  */
-+  ubicom32_can_use_calli_to_ret = 1;
-+  emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode, LINK_REGNO)));
-+}
-+
-+void
-+ubicom32_expand_call_fdpic (rtx *operands)
-+{
-+  rtx c;
-+  rtx addr;
-+  rtx fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM);
-+
-+  addr = XEXP (operands[0], 0);
-+
-+  c = gen_call_fdpic (addr, operands[1], fdpic_reg);
-+  emit_call_insn (c);
-+}
-+
-+void
-+ubicom32_expand_call_value_fdpic (rtx *operands)
-+{
-+  rtx c;
-+  rtx addr;
-+  rtx fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM);
-+
-+  addr = XEXP (operands[1], 0);
-+
-+  c = gen_call_value_fdpic (operands[0], addr, operands[2], fdpic_reg);
-+  emit_call_insn (c);
-+}
-+
-+void
-+ubicom32_expand_eh_return (rtx *operands)
-+{
-+  if (REG_P (operands[0])
-+      || REGNO (operands[0]) != EH_RETURN_STACKADJ_REGNO)
-+    {
-+      rtx sp = EH_RETURN_STACKADJ_RTX;
-+      emit_move_insn (sp, operands[0]);
-+      operands[0] = sp;
-+    }
-+
-+  if (REG_P (operands[1])
-+      || REGNO (operands[1]) != EH_RETURN_HANDLER_REGNO)
-+    {
-+      rtx ra = EH_RETURN_HANDLER_RTX;
-+      emit_move_insn (ra, operands[1]);
-+      operands[1] = ra;
-+    }
-+}
-+
-+/* Compute the offsets between eliminable registers.  */
-+
-+int
-+ubicom32_initial_elimination_offset (int from, int to)
-+{
-+  ubicom32_layout_frame ();
-+  if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
-+    return save_regs_size + crtl->outgoing_args_size;
-+
-+  if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
-+    return get_frame_size ()/* + save_regs_size */;
-+
-+  if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
-+    return get_frame_size ()
-+         + crtl->outgoing_args_size
-+         + save_regs_size;
-+
-+  return 0;
-+}
-+
-+/* Return 1 if it is appropriate to emit `ret' instructions in the
-+   body of a function.  Do this only if the epilogue is simple, needing a
-+   couple of insns.  Prior to reloading, we can't tell how many registers
-+   must be saved, so return 0 then.  Return 0 if there is no frame
-+   marker to de-allocate.
-+
-+   If NON_SAVING_SETJMP is defined and true, then it is not possible
-+   for the epilogue to be simple, so return 0.  This is a special case
-+   since NON_SAVING_SETJMP will not cause regs_ever_live to change
-+   until final, but jump_optimize may need to know sooner if a
-+   `return' is OK.  */
-+
-+int
-+ubicom32_can_use_return_insn_p (void)
-+{
-+  if (! reload_completed || frame_pointer_needed)
-+    return 0;
-+
-+  return 1;
-+}
-+
-+/* Attributes and CC handling.  */
-+
-+/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
-+   struct attribute_spec.handler.  */
-+static tree
-+ubicom32_handle_fndecl_attribute (tree *node, tree name,
-+                            tree args ATTRIBUTE_UNUSED,
-+                            int flags ATTRIBUTE_UNUSED,
-+                            bool *no_add_attrs)
-+{
-+  if (TREE_CODE (*node) != FUNCTION_DECL)
-+    {
-+      warning ("'%s' attribute only applies to functions",
-+             IDENTIFIER_POINTER (name));
-+      *no_add_attrs = true;
-+    }
-+
-+  return NULL_TREE;
-+}
-+
-+/* A C expression that places additional restrictions on the register class to
-+   use when it is necessary to copy value X into a register in class CLASS.
-+   The value is a register class; perhaps CLASS, or perhaps another, smaller
-+   class.  On many machines, the following definition is safe:
-+
-+        #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS
-+
-+   Sometimes returning a more restrictive class makes better code.  For
-+   example, on the 68000, when X is an integer constant that is in range for a
-+   `moveq' instruction, the value of this macro is always `DATA_REGS' as long
-+   as CLASS includes the data registers.  Requiring a data register guarantees
-+   that a `moveq' will be used.
-+
-+   If X is a `const_double', by returning `NO_REGS' you can force X into a
-+   memory constant.  This is useful on certain machines where immediate
-+   floating values cannot be loaded into certain kinds of registers.  */
-+
-+enum reg_class
-+ubicom32_preferred_reload_class (rtx x, enum reg_class class)
-+{
-+  /* If a symbolic constant, HIGH or a PLUS is reloaded,
-+     it is most likely being used as an address, so
-+     prefer ADDRESS_REGS.  If 'class' is not a superset
-+     of ADDRESS_REGS, e.g. DATA_REGS, then reject this reload.  */
-+  if (GET_CODE (x) == PLUS
-+      || GET_CODE (x) == HIGH
-+      || GET_CODE (x) == LABEL_REF
-+      || GET_CODE (x) == SYMBOL_REF
-+      || GET_CODE (x) == CONST)
-+    {
-+      if (reg_class_subset_p (ALL_ADDRESS_REGS, class))
-+      return ALL_ADDRESS_REGS;
-+
-+      return NO_REGS;
-+    }
-+
-+  return class;
-+}
-+
-+/* Function arguments and varargs.  */
-+
-+int
-+ubicom32_reg_parm_stack_space (tree fndecl)
-+{
-+  return 0;
-+  
-+  if (fndecl
-+      && TYPE_ARG_TYPES (TREE_TYPE (fndecl)) != 0
-+      && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))) 
-+        != void_type_node))
-+    return UBICOM32_FUNCTION_ARG_REGS * UNITS_PER_WORD;
-+
-+  return 0;
-+}
-+
-+/* Flush the argument registers to the stack for a stdarg function;
-+   return the new argument pointer.  */
-+
-+rtx
-+ubicom32_builtin_saveregs (void)
-+{
-+  int regno;
-+  
-+  if (! cfun->stdarg)
-+    return 0;
-+  
-+  for (regno = UBICOM32_FUNCTION_ARG_REGS - 1; regno >= 0; --regno)
-+    emit_move_insn (gen_rtx_MEM (SImode,
-+                               gen_rtx_PRE_DEC (SImode,
-+                                                stack_pointer_rtx)),
-+                  gen_rtx_REG (SImode, regno));
-+  
-+  return stack_pointer_rtx;
-+}
-+
-+void
-+ubicom32_va_start (tree valist, rtx nextarg)
-+{
-+  std_expand_builtin_va_start (valist, nextarg);
-+}
-+
-+rtx
-+ubicom32_va_arg (tree valist, tree type)
-+{
-+  HOST_WIDE_INT size, rsize;
-+  tree addr, incr, tmp;
-+  rtx addr_rtx;
-+  int indirect = 0;
-+
-+  /* Round up sizeof(type) to a word.  */
-+  size = int_size_in_bytes (type);
-+  rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
-+
-+  /* Large types are passed by reference.  */
-+  if (size > 8)
-+    {
-+      indirect = 1;
-+      size = rsize = UNITS_PER_WORD;
-+    }
-+
-+  incr = valist;
-+  addr = incr = save_expr (incr);
-+
-+  /* FIXME Nat's version - is it correct?  */
-+  tmp = fold_convert (ptr_type_node, size_int (rsize));
-+  tmp = build2 (PLUS_EXPR, ptr_type_node, incr, tmp);
-+  incr = fold (tmp);
-+
-+  /* FIXME Nat's version - is it correct? */
-+  incr = build2 (MODIFY_EXPR, ptr_type_node, valist, incr);
-+
-+  TREE_SIDE_EFFECTS (incr) = 1;
-+  expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL);
-+
-+  addr_rtx = expand_expr (addr, NULL, Pmode, EXPAND_NORMAL);
-+
-+  if (size < UNITS_PER_WORD)
-+    emit_insn (gen_addsi3 (addr_rtx, addr_rtx,
-+                         GEN_INT (UNITS_PER_WORD - size)));
-+
-+  if (indirect)
-+    {
-+      addr_rtx = force_reg (Pmode, addr_rtx);
-+      addr_rtx = gen_rtx_MEM (Pmode, addr_rtx);
-+      set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
-+    }
-+
-+  return addr_rtx;
-+}
-+
-+void
-+init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
-+                    int indirect ATTRIBUTE_UNUSED)
-+{
-+  cum->nbytes = 0;
-+
-+  if (!libname)
-+    {
-+      cum->stdarg = (TYPE_ARG_TYPES (fntype) != 0
-+                   && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
-+                       != void_type_node));
-+    }
-+}
-+
-+/* Return an RTX to represent where a value in mode MODE will be passed
-+   to a function.  If the result is 0, the argument will be pushed.  */
-+
-+rtx
-+function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
-+            int named ATTRIBUTE_UNUSED)
-+{
-+  rtx result = 0;
-+  int size, align;
-+  int nregs = UBICOM32_FUNCTION_ARG_REGS;
-+  
-+  /* Figure out the size of the object to be passed.  */
-+  if (mode == BLKmode)
-+    size = int_size_in_bytes (type);
-+  else
-+    size = GET_MODE_SIZE (mode);
-+
-+  /* Figure out the alignment of the object to be passed.  */
-+  align = size;
-+
-+  cum->nbytes = (cum->nbytes + 3) & ~3;
-+
-+  /* Don't pass this arg via a register if all the argument registers
-+     are used up.  */
-+  if (cum->nbytes >= nregs * UNITS_PER_WORD)
-+    return 0;
-+
-+  /* Don't pass this arg via a register if it would be split between
-+     registers and memory.  */
-+  result = gen_rtx_REG (mode, cum->nbytes / UNITS_PER_WORD);
-+
-+  return result;
-+}
-+
-+rtx
-+function_incoming_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
-+                     int named ATTRIBUTE_UNUSED)
-+{
-+  if (cfun->stdarg)
-+    return 0;
-+
-+  return function_arg (cum, mode, type, named);
-+}
-+
-+
-+/* Implement hook TARGET_ARG_PARTIAL_BYTES.
-+
-+   Returns the number of bytes at the beginning of an argument that
-+   must be put in registers.  The value must be zero for arguments
-+   that are passed entirely in registers or that are entirely pushed
-+   on the stack.  */
-+static int
-+ubicom32_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
-+                          tree type, bool named ATTRIBUTE_UNUSED)
-+{
-+  int size, diff;
-+
-+  int nregs = UBICOM32_FUNCTION_ARG_REGS;
-+
-+  /* round up to full word */
-+  cum->nbytes = (cum->nbytes + 3) & ~3;
-+
-+  if (targetm.calls.pass_by_reference (cum, mode, type, named))
-+      return 0;
-+
-+  /* number of bytes left in registers */
-+  diff = nregs*UNITS_PER_WORD - cum->nbytes;
-+
-+  /* regs all used up */
-+  if (diff <= 0)
-+    return 0;
-+
-+  /* Figure out the size of the object to be passed.  */
-+  if (mode == BLKmode)
-+    size = int_size_in_bytes (type);
-+  else
-+    size = GET_MODE_SIZE (mode);
-+
-+  /* enough space left in regs for size */
-+  if (size <= diff)
-+    return 0;
-+
-+  /* put diff bytes in regs and rest on stack */
-+  return diff;
-+
-+}
-+
-+static bool
-+ubicom32_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
-+                          enum machine_mode mode, const_tree type,
-+                          bool named ATTRIBUTE_UNUSED)
-+{
-+  int size;
-+
-+  if (type)
-+    size = int_size_in_bytes (type);
-+  else
-+    size = GET_MODE_SIZE (mode);
-+
-+  return size <= 0 || size > 8;
-+}
-+
-+static bool
-+ubicom32_callee_copies (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
-+                      enum machine_mode mode, const_tree type,
-+                      bool named ATTRIBUTE_UNUSED)
-+{
-+  int size;
-+
-+  if (type)
-+    size = int_size_in_bytes (type);
-+  else
-+    size = GET_MODE_SIZE (mode);
-+
-+  return size <= 0 || size > 8;
-+}
-+ 
-+static bool
-+ubicom32_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
-+{
-+  int size, mode;
-+
-+  if (!type)
-+    return true;
-+
-+  size = int_size_in_bytes(type);
-+  if (size > 8) 
-+    return true;
-+
-+  mode = TYPE_MODE(type);
-+  if (mode == BLKmode)
-+    return true;
-+
-+  return false;
-+}
-+
-+/* Return true if a given register number REGNO is acceptable for machine
-+   mode MODE.  */
-+bool
-+ubicom32_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
-+{
-+  /* If we're not at least a v3 ISA then ACC0_HI is only 16 bits.  */
-+  if (! ubicom32_v3)
-+    {
-+      if (regno == ACC0_HI_REGNUM)
-+      return (mode == QImode || mode == HImode);
-+    }
-+
-+  /* Only the flags reg can hold CCmode.  */
-+  if (GET_MODE_CLASS (mode) == MODE_CC)
-+    return regno == CC_REGNUM;
-+
-+  /* We restrict the choice of DImode registers to only being address,
-+     data or accumulator regs.  We also restrict them to only start on
-+     even register numbers so we never have to worry about partial
-+     overlaps between operands in instructions.  */
-+  if (GET_MODE_SIZE (mode) > 4)
-+    {
-+      switch (REGNO_REG_CLASS (regno))
-+      {
-+      case ADDRESS_REGS:
-+      case DATA_REGS:
-+      case ACC_REGS:
-+        return (regno & 1) == 0;
-+
-+        default:
-+        return false;
-+      }
-+    }
-+
-+  return true;
-+}
-+
-+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
-+   and check its validity for a certain class.
-+   We have two alternate definitions for each of them.
-+   The usual definition accepts all pseudo regs; the other rejects
-+   them unless they have been allocated suitable hard regs.
-+   The symbol REG_OK_STRICT causes the latter definition to be used.
-+
-+   Most source files want to accept pseudo regs in the hope that
-+   they will get allocated to the class that the insn wants them to be in.
-+   Source files for reload pass need to be strict.
-+   After reload, it makes no difference, since pseudo regs have
-+   been eliminated by then.  
-+
-+   These assume that REGNO is a hard or pseudo reg number.
-+   They give nonzero only if REGNO is a hard reg of the suitable class
-+   or a pseudo reg currently allocated to a suitable hard reg.
-+   Since they use reg_renumber, they are safe only once reg_renumber
-+   has been allocated, which happens in local-alloc.c.  */
-+
-+int
-+ubicom32_regno_ok_for_base_p (int regno, int strict)
-+{
-+  if ((regno >= FIRST_ADDRESS_REGNUM && regno <= STACK_POINTER_REGNUM) 
-+      || (!strict
-+        && (regno >= FIRST_PSEUDO_REGISTER
-+            || regno == ARG_POINTER_REGNUM))
-+      || (strict && (reg_renumber 
-+                   && reg_renumber[regno] >= FIRST_ADDRESS_REGNUM
-+                   && reg_renumber[regno] <= STACK_POINTER_REGNUM)))
-+    return 1;
-+
-+  return 0;
-+}
-+
-+int
-+ubicom32_regno_ok_for_index_p (int regno, int strict)
-+{
-+  if ((regno >= FIRST_DATA_REGNUM && regno <= LAST_DATA_REGNUM)
-+      || (!strict && regno >= FIRST_PSEUDO_REGISTER)
-+      || (strict && (reg_renumber 
-+                   && reg_renumber[regno] >= FIRST_DATA_REGNUM
-+                   && reg_renumber[regno] <= LAST_DATA_REGNUM)))
-+    return 1;
-+
-+  return 0;
-+}
-+
-+/* Returns 1 if X is a valid index register.  STRICT is 1 if only hard
-+   registers should be accepted.  Accept either REG or SUBREG where a
-+   register is valid.  */
-+
-+static bool
-+ubicom32_is_index_reg (rtx x, int strict)
-+{
-+  if ((REG_P (x) && ubicom32_regno_ok_for_index_p (REGNO (x), strict))
-+      || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x))
-+        && ubicom32_regno_ok_for_index_p (REGNO (SUBREG_REG (x)), strict)))
-+    return true;
-+
-+  return false;
-+}
-+
-+/* Return 1 if X is a valid index for a memory address.  */
-+
-+static bool
-+ubicom32_is_index_expr (enum machine_mode mode, rtx x, int strict)
-+{
-+  /* Immediate index must be an unsigned 7-bit offset multiple of 1, 2
-+     or 4 depending on mode.  */
-+  if (CONST_INT_P (x))
-+    {
-+      switch (mode)
-+      {
-+      case QImode:
-+        return satisfies_constraint_J (x);
-+        
-+      case HImode:
-+        return satisfies_constraint_K (x);
-+
-+      case SImode:
-+      case SFmode:
-+        return satisfies_constraint_L (x);
-+
-+      case DImode:
-+        return satisfies_constraint_L (x)
-+               && satisfies_constraint_L (GEN_INT (INTVAL (x) + 4));
-+        
-+      default:          
-+        return false;
-+      }
-+    }
-+
-+  if (mode != SImode && mode != HImode && mode != QImode)
-+    return false;
-+
-+  /* Register index scaled by mode of operand: REG + REG * modesize.
-+     Valid scaled index registers are:
-+
-+     SImode   (mult (dreg) 4))
-+     HImode   (mult (dreg) 2))
-+     QImode   (mult (dreg) 1))  */
-+  if (GET_CODE (x) == MULT
-+      && ubicom32_is_index_reg (XEXP (x, 0), strict)
-+      && CONST_INT_P (XEXP (x, 1))
-+      && INTVAL (XEXP (x, 1)) == (HOST_WIDE_INT)GET_MODE_SIZE (mode))
-+    return true;
-+
-+  /* REG + REG addressing is allowed for QImode.  */
-+  if (ubicom32_is_index_reg (x, strict) && mode == QImode)
-+    return true;
-+
-+  return false;
-+}
-+
-+static bool
-+ubicom32_is_valid_offset (enum machine_mode mode, HOST_WIDE_INT offs)
-+{
-+  if (offs < 0)
-+    return false;
-+
-+  switch (mode)
-+    {
-+    case QImode:
-+      return offs <= 127;
-+
-+    case HImode:
-+      return offs <= 254;
-+
-+    case SImode:
-+    case SFmode:
-+      return offs <= 508;
-+
-+    case DImode:
-+      return offs <= 504;
-+
-+    default:
-+      return false;
-+    }
-+}
-+
-+static int
-+ubicom32_get_valid_offset_mask (enum machine_mode mode)
-+{
-+  switch (mode)
-+    {
-+    case QImode:
-+      return 127;
-+
-+    case HImode:
-+      return 255;
-+
-+    case SImode:
-+    case SFmode:
-+      return 511;
-+
-+    case DImode:
-+      return 255;
-+
-+    default:
-+      return 0;
-+    }
-+}
-+
-+/* Returns 1 if X is a valid base register.  STRICT is 1 if only hard
-+   registers should be accepted.  Accept either REG or SUBREG where a
-+   register is valid.  */
-+
-+static bool
-+ubicom32_is_base_reg (rtx x, int strict)
-+{
-+  if ((REG_P (x) && ubicom32_regno_ok_for_base_p (REGNO (x), strict))
-+      || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x))
-+        && ubicom32_regno_ok_for_base_p (REGNO (SUBREG_REG (x)), strict)))
-+    return true;
-+
-+  return false;
-+}
-+
-+static bool
-+ubicom32_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
-+{
-+  return TARGET_FDPIC;
-+}
-+
-+/* Determine if X is a legitimate constant.  */
-+
-+bool
-+ubicom32_legitimate_constant_p (rtx x)
-+{
-+  /* Among its other duties, LEGITIMATE_CONSTANT_P decides whether
-+     a constant can be entered into reg_equiv_constant[].  If we return true,
-+     reload can create new instances of the constant whenever it likes.
-+
-+     The idea is therefore to accept as many constants as possible (to give
-+     reload more freedom) while rejecting constants that can only be created
-+     at certain times.  In particular, anything with a symbolic component will
-+     require use of the pseudo FDPIC register, which is only available before
-+     reload.  */
-+  if (TARGET_FDPIC)
-+    {
-+      if (GET_CODE (x) == SYMBOL_REF
-+        || (GET_CODE (x) == CONST
-+            && GET_CODE (XEXP (x, 0)) == PLUS
-+            && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)
-+        || CONSTANT_ADDRESS_P (x))
-+      return false;
-+
-+      return true;
-+    }
-+
-+  /* For non-PIC code anything goes!  */
-+  return true;
-+}
-+
-+/* Address validation.  */
-+
-+bool
-+ubicom32_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
-+{
-+  if (TARGET_DEBUG_ADDRESS)
-+    {                                                                 
-+      fprintf (stderr, "\n==> GO_IF_LEGITIMATE_ADDRESS%s\n",
-+             (strict) ? " (STRICT)" : "");
-+      debug_rtx (x);
-+    }                                                                 
-+
-+  if (CONSTANT_ADDRESS_P (x))
-+    return false;
-+
-+  if (ubicom32_is_base_reg (x, strict)) 
-+    return true;
-+
-+  if ((GET_CODE (x) == POST_INC 
-+       || GET_CODE (x) == PRE_INC 
-+       || GET_CODE (x) == POST_DEC 
-+       || GET_CODE (x) == PRE_DEC)
-+      && REG_P (XEXP (x, 0))
-+      && ubicom32_is_base_reg (XEXP (x, 0), strict)
-+      && mode != DImode)
-+    return true;
-+
-+  if ((GET_CODE (x) == PRE_MODIFY || GET_CODE (x) == POST_MODIFY)
-+      && ubicom32_is_base_reg (XEXP (x, 0), strict)
-+      && GET_CODE (XEXP (x, 1)) == PLUS
-+      && rtx_equal_p (XEXP (x, 0), XEXP (XEXP (x, 1), 0))
-+      && CONST_INT_P (XEXP (XEXP (x, 1), 1))
-+      && mode != DImode)
-+    {
-+      HOST_WIDE_INT disp = INTVAL (XEXP (XEXP (x, 1), 1));
-+      switch (mode)
-+      {
-+      case QImode:
-+        return disp >= -8 && disp <= 7;
-+        
-+      case HImode:
-+        return disp >= -16 && disp <= 14 && ! (disp & 1);
-+        
-+      case SImode:
-+        return disp >= -32 && disp <= 28 && ! (disp & 3);
-+        
-+      default:
-+        return false;
-+      }
-+    }
-+  
-+  /* Accept base + index * scale.  */
-+  if (GET_CODE (x) == PLUS
-+      && ubicom32_is_base_reg (XEXP (x, 0), strict)
-+      && ubicom32_is_index_expr (mode, XEXP (x, 1), strict))
-+    return true;
-+
-+  /* Accept index * scale + base.  */
-+  if (GET_CODE (x) == PLUS
-+      && ubicom32_is_base_reg (XEXP (x, 1), strict)
-+      && ubicom32_is_index_expr (mode, XEXP (x, 0), strict))
-+    return true;
-+
-+  if (! TARGET_FDPIC)
-+    {
-+      /* Accept (lo_sum (reg) (symbol_ref)) that can be used as a mem+7bits
-+       displacement operand:
-+
-+       moveai a1, #%hi(SYM)
-+       move.4 d3, %lo(SYM)(a1)  */
-+      if (GET_CODE (x) == LO_SUM
-+        && ubicom32_is_base_reg (XEXP (x, 0), strict)
-+        && (GET_CODE (XEXP (x, 1)) == SYMBOL_REF
-+            || GET_CODE (XEXP (x, 1)) == LABEL_REF /* FIXME: wrong */)
-+        && mode != DImode)
-+      return true;
-+    }
-+
-+  if (TARGET_DEBUG_ADDRESS)
-+    fprintf (stderr, "\nNot a legitimate address.\n");
-+
-+  return false;
-+}
-+
-+rtx
-+ubicom32_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
-+                           enum machine_mode mode)
-+{
-+  if (mode == BLKmode)
-+    return NULL_RTX;
-+
-+  if (GET_CODE (x) == PLUS
-+      && REG_P (XEXP (x, 0))
-+      && ! REGNO_PTR_FRAME_P (REGNO (XEXP (x, 0))) 
-+      && CONST_INT_P (XEXP (x, 1))
-+      && ! ubicom32_is_valid_offset (mode, INTVAL (XEXP (x, 1))))
-+    {
-+      rtx base;
-+      rtx plus;
-+      rtx new_rtx;
-+      HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
-+      HOST_WIDE_INT low = val & ubicom32_get_valid_offset_mask (mode);
-+      HOST_WIDE_INT high = val ^ low;
-+
-+      if (val < 0)
-+      return NULL_RTX;
-+
-+      if (! low)
-+      return NULL_RTX;
-+
-+      /* Reload the high part into a base reg; leave the low part
-+       in the mem directly.  */
-+      base = XEXP (x, 0);
-+      if (! ubicom32_is_base_reg (base, 0))
-+      base = copy_to_mode_reg (Pmode, base);
-+
-+      plus = expand_simple_binop (Pmode, PLUS,
-+                                gen_int_mode (high, Pmode),
-+                                base, NULL, 0, OPTAB_WIDEN);
-+      new_rtx = plus_constant (plus, low);
-+
-+      return new_rtx;
-+    }
-+
-+  return NULL_RTX;
-+}
-+
-+/* Try a machine-dependent way of reloading an illegitimate address AD
-+   operand.  If we find one, push the reload and and return the new address.
-+
-+   MODE is the mode of the enclosing MEM.  OPNUM is the operand number
-+   and TYPE is the reload type of the current reload.  */
-+
-+rtx 
-+ubicom32_legitimize_reload_address (rtx ad, enum machine_mode mode,
-+                                  int opnum, int type)
-+{
-+  /* Is this an address that we've already fixed up?  If it is then
-+     recognize it and move on.  */
-+  if (GET_CODE (ad) == PLUS
-+      && GET_CODE (XEXP (ad, 0)) == PLUS
-+      && REG_P (XEXP (XEXP (ad, 0), 0))
-+      && CONST_INT_P (XEXP (XEXP (ad, 0), 1))
-+      && CONST_INT_P (XEXP (ad, 1)))
-+    {
-+      push_reload (XEXP (ad, 0), NULL_RTX, &XEXP (ad, 0), NULL,
-+                 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
-+                 opnum, (enum reload_type) type);
-+      return ad;
-+    }
-+
-+  /* Have we got an address where the offset is simply out of range?  If
-+     yes then reload the range as a high part and smaller offset.  */
-+  if (GET_CODE (ad) == PLUS
-+      && REG_P (XEXP (ad, 0))
-+      && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
-+      && REGNO_OK_FOR_BASE_P (REGNO (XEXP (ad, 0)))
-+      && CONST_INT_P (XEXP (ad, 1))
-+      && ! ubicom32_is_valid_offset (mode, INTVAL (XEXP (ad, 1))))
-+    {
-+      rtx temp;
-+      rtx new_rtx;
-+
-+      HOST_WIDE_INT val = INTVAL (XEXP (ad, 1));
-+      HOST_WIDE_INT low = val & ubicom32_get_valid_offset_mask (mode);
-+      HOST_WIDE_INT high = val ^ low;
-+
-+      /* Reload the high part into a base reg; leave the low part
-+       in the mem directly.  */
-+      temp = gen_rtx_PLUS (Pmode, XEXP (ad, 0), GEN_INT (high));
-+      new_rtx = gen_rtx_PLUS (Pmode, temp, GEN_INT (low));
-+
-+      push_reload (XEXP (new_rtx, 0), NULL_RTX, &XEXP (new_rtx, 0), NULL,
-+                 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
-+                 opnum, (enum reload_type) type);
-+      return new_rtx;
-+    }
-+
-+  /* If we're presented with an pre/post inc/dec then we must force this
-+     to be done in an address register.  The register allocator should
-+     work this out for itself but at times ends up trying to use the wrong
-+     class.  If we get the wrong class then reload will end up generating
-+     at least 3 instructions whereas this way we can hopefully keep it to
-+     just 2.  */
-+  if ((GET_CODE (ad) == POST_INC 
-+       || GET_CODE (ad) == PRE_INC 
-+       || GET_CODE (ad) == POST_DEC 
-+       || GET_CODE (ad) == PRE_DEC)
-+      && REG_P (XEXP (ad, 0))
-+      && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
-+      && ! REGNO_OK_FOR_BASE_P (REGNO (XEXP (ad, 0))))
-+    {
-+      push_reload (XEXP (ad, 0), XEXP (ad, 0), &XEXP (ad, 0), &XEXP (ad, 0),
-+                 BASE_REG_CLASS, GET_MODE (XEXP (ad, 0)), GET_MODE (XEXP (ad, 0)), 0, 0,
-+                 opnum, RELOAD_OTHER);
-+      return ad;
-+    }
-+
-+  return NULL_RTX;
-+}
-+
-+/* Compute a (partial) cost for rtx X.  Return true if the complete
-+   cost has been computed, and false if subexpressions should be
-+   scanned.  In either case, *TOTAL contains the cost result.  */
-+
-+static bool
-+ubicom32_rtx_costs (rtx x, int code, int outer_code, int *total,
-+                  bool speed ATTRIBUTE_UNUSED)
-+{
-+  enum machine_mode mode = GET_MODE (x);
-+
-+  switch (code)
-+    {
-+    case CONST_INT:
-+      /* Very short constants often fold into instructions so
-+         we pretend that they don't cost anything!  This is
-+       really important as regards zero values as otherwise
-+       the compiler has a nasty habit of wanting to reuse
-+       zeroes that are in regs but that tends to pessimize
-+       the code.  */
-+      if (satisfies_constraint_I (x))
-+      {
-+        *total = 0;
-+        return true;
-+      }
-+
-+      /* Bit clearing costs nothing  */
-+      if (outer_code == AND
-+        && exact_log2 (~INTVAL (x)) != -1)
-+      {
-+        *total = 0;
-+        return true;
-+      }
-+
-+      /* Masking the lower set of bits costs nothing.  */
-+      if (outer_code == AND
-+        && exact_log2 (INTVAL (x) + 1) != -1)
-+      {
-+        *total = 0;
-+        return true;
-+      }
-+
-+      /* Bit setting costs nothing.  */
-+      if (outer_code == IOR
-+        && exact_log2 (INTVAL (x)) != -1)
-+      {
-+        *total = 0;
-+        return true;
-+      }
-+
-+      /* Larger constants that can be loaded via movei aren't too
-+         bad.  If we're just doing a set they cost nothing extra.  */
-+      if (satisfies_constraint_N (x))
-+      {
-+        if (mode == DImode)
-+          *total = COSTS_N_INSNS (2);
-+        else 
-+          *total = COSTS_N_INSNS (1);
-+        return true;
-+      }
-+
-+      if (mode == DImode)
-+      *total = COSTS_N_INSNS (5);
-+      else
-+        *total = COSTS_N_INSNS (3);
-+      return true;
-+
-+    case CONST_DOUBLE:
-+      /* We don't optimize CONST_DOUBLEs well nor do we relax them well,
-+       so their cost is very high.  */
-+      *total = COSTS_N_INSNS (6);
-+      return true;
-+
-+    case CONST:
-+    case SYMBOL_REF:
-+    case MEM:
-+      *total = 0;
-+      return true;
-+
-+    case IF_THEN_ELSE:
-+      *total = COSTS_N_INSNS (1);
-+      return true;
-+
-+    case LABEL_REF:
-+    case HIGH:
-+    case LO_SUM:
-+    case BSWAP:
-+    case PLUS:
-+    case MINUS:
-+    case AND:
-+    case IOR:
-+    case XOR:
-+    case ASHIFT:
-+    case ASHIFTRT:
-+    case LSHIFTRT:
-+    case NEG:
-+    case NOT:
-+    case SIGN_EXTEND:
-+    case ZERO_EXTEND:
-+    case ZERO_EXTRACT:
-+      if (outer_code == SET)
-+      {
-+        if (mode == DImode)
-+          *total = COSTS_N_INSNS (2);
-+        else
-+          *total = COSTS_N_INSNS (1);
-+      }
-+      return true;
-+
-+    case COMPARE:
-+      if (outer_code == SET)
-+      {
-+        if (GET_MODE (XEXP (x, 0)) == DImode
-+            || GET_MODE (XEXP (x, 1)) == DImode)
-+          *total = COSTS_N_INSNS (2);
-+        else
-+          *total = COSTS_N_INSNS (1);
-+      }
-+      return true;
-+
-+    case UMOD:
-+    case UDIV:
-+    case MOD:
-+    case DIV:
-+      if (outer_code == SET)
-+      {
-+        if (mode == DImode)
-+          *total = COSTS_N_INSNS (600);
-+        else
-+          *total = COSTS_N_INSNS (200);
-+      }
-+      return true;
-+
-+    case MULT:
-+      if (outer_code == SET)
-+      {
-+        if (! ubicom32_v4)
-+          {
-+            if (mode == DImode)
-+              *total = COSTS_N_INSNS (15);
-+            else
-+              *total = COSTS_N_INSNS (5);
-+          }
-+        else
-+          {
-+            if (mode == DImode)
-+              *total = COSTS_N_INSNS (6);
-+            else
-+              *total = COSTS_N_INSNS (2);
-+          }
-+      }
-+      return true;
-+
-+    case UNSPEC:
-+      if (XINT (x, 1) == UNSPEC_FDPIC_GOT
-+        || XINT (x, 1) == UNSPEC_FDPIC_GOT_FUNCDESC)
-+      *total = 0;
-+      return true;
-+
-+    default:
-+      return false;
-+    }
-+}
-+
-+/* Return 1 if ADDR can have different meanings depending on the machine
-+   mode of the memory reference it is used for or if the address is
-+   valid for some modes but not others.
-+
-+   Autoincrement and autodecrement addresses typically have
-+   mode-dependent effects because the amount of the increment or
-+   decrement is the size of the operand being addressed.  Some machines
-+   have other mode-dependent addresses. Many RISC machines have no
-+   mode-dependent addresses.
-+
-+   You may assume that ADDR is a valid address for the machine.  */
-+
-+int
-+ubicom32_mode_dependent_address_p (rtx addr)
-+{
-+  if (GET_CODE (addr) == POST_INC 
-+      || GET_CODE (addr) == PRE_INC 
-+      || GET_CODE (addr) == POST_DEC 
-+      || GET_CODE (addr) == PRE_DEC 
-+      || GET_CODE (addr) == POST_MODIFY 
-+      || GET_CODE (addr) == PRE_MODIFY)
-+    return 1;
-+
-+  return 0;
-+}
-+
-+static void
-+ubicom32_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
-+{
-+  fprintf (file, "/* frame/pretend: %ld/%d save_regs: %d out_args: %d  %s */\n",
-+         get_frame_size (), crtl->args.pretend_args_size,
-+         save_regs_size, crtl->outgoing_args_size,
-+         current_function_is_leaf ? "leaf" : "nonleaf");
-+}
-+
-+static void
-+ubicom32_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
-+                          HOST_WIDE_INT size ATTRIBUTE_UNUSED)
-+{
-+  ubicom32_reorg_completed = 0;  
-+}
-+
-+static void
-+ubicom32_machine_dependent_reorg (void)
-+{
-+#if 0 /* Commenting out this optimization until it is fixed */
-+  if (optimize)
-+    {
-+      compute_bb_for_insn ();
-+
-+      /* Do a very simple CSE pass over just the hard registers.  */
-+      reload_cse_regs (get_insns ());
-+
-+      /* Reload_cse_regs can eliminate potentially-trapping MEMs.
-+       Remove any EH edges associated with them.  */
-+      if (flag_non_call_exceptions)
-+      purge_all_dead_edges ();
-+    }
-+#endif
-+  ubicom32_reorg_completed = 1;
-+}
-+
-+void
-+ubicom32_output_cond_jump (rtx insn, rtx cond, rtx target)
-+{
-+  rtx note;
-+  int mostly_false_jump;
-+  rtx xoperands[2];
-+  rtx cc_reg;
-+
-+  note = find_reg_note (insn, REG_BR_PROB, 0);
-+  mostly_false_jump = !note || (INTVAL (XEXP (note, 0))
-+                              <= REG_BR_PROB_BASE / 2);
-+
-+  xoperands[0] = target;
-+  xoperands[1] = cond;
-+  cc_reg = XEXP (cond, 0);
-+
-+  if (GET_MODE (cc_reg) == CCWmode
-+      || GET_MODE (cc_reg) == CCWZmode
-+      || GET_MODE (cc_reg) == CCWZNmode)
-+    {
-+      if (mostly_false_jump)
-+        output_asm_insn ("jmp%b1.w.f\t%0", xoperands);
-+      else
-+        output_asm_insn ("jmp%b1.w.t\t%0", xoperands);
-+      return;
-+    }
-+
-+  if (GET_MODE (cc_reg) == CCSmode
-+      || GET_MODE (cc_reg) == CCSZmode
-+      || GET_MODE (cc_reg) == CCSZNmode)
-+    {
-+      if (mostly_false_jump)
-+        output_asm_insn ("jmp%b1.s.f\t%0", xoperands);
-+      else
-+        output_asm_insn ("jmp%b1.s.t\t%0", xoperands);
-+      return;
-+    }
-+
-+  abort ();
-+}
-+
-+/* Return non-zero if FUNC is a naked function.  */
-+
-+static int
-+ubicom32_naked_function_p (void)
-+{
-+  return lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE;
-+}
-+
-+/* Return an RTX indicating where the return address to the
-+   calling function can be found.  */
-+rtx
-+ubicom32_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED)
-+{
-+  if (count != 0)
-+    return NULL_RTX;
-+
-+  return get_hard_reg_initial_val (Pmode, LINK_REGNO);
-+}
-+
-+/*
-+ * ubicom32_readonly_data_section: This routtine handles code
-+ * at the start of readonly data sections
-+ */
-+static void
-+ubicom32_readonly_data_section (const void *data ATTRIBUTE_UNUSED)
-+{
-+  static int num = 0;
-+  if (in_section == readonly_data_section){
-+    fprintf (asm_out_file, "%s", DATA_SECTION_ASM_OP);
-+    if (flag_data_sections){
-+      fprintf (asm_out_file, ".rodata%d", num);
-+      fprintf (asm_out_file, ",\"a\"");
-+    }
-+    fprintf (asm_out_file, "\n");
-+  }
-+  num++;
-+}
-+
-+/*
-+ * ubicom32_text_section: not in readonly section
-+ */
-+static void
-+ubicom32_text_section(const void *data ATTRIBUTE_UNUSED)
-+{
-+  fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
-+}
-+
-+/*
-+ * ubicom32_data_section: not in readonly section
-+ */
-+static void
-+ubicom32_data_section(const void *data ATTRIBUTE_UNUSED)
-+{
-+  fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
-+}
-+
-+/*
-+ * ubicom32_asm_init_sections: This routine implements special
-+ * section handling
-+ */
-+static void
-+ubicom32_asm_init_sections(void)
-+{
-+  text_section = get_unnamed_section(SECTION_CODE, ubicom32_text_section, NULL);
-+
-+  data_section = get_unnamed_section(SECTION_WRITE, ubicom32_data_section, NULL);
-+
-+  readonly_data_section = get_unnamed_section(0, ubicom32_readonly_data_section, NULL);
-+}
-+
-+/*
-+ * ubicom32_profiler:  This routine would call
-+ * mcount to support prof and gprof if mcount
-+ * was supported. Currently, do nothing.
-+ */
-+void
-+ubicom32_profiler(void)
-+{
-+}
-+
-+/* Initialise the builtin functions.  Start by initialising
-+   descriptions of different types of functions (e.g., void fn(int),
-+   int fn(void)), and then use these to define the builtins. */
-+static void
-+ubicom32_init_builtins (void)
-+{
-+  tree endlink;
-+  tree short_unsigned_endlink;
-+  tree unsigned_endlink;
-+  tree short_unsigned_ftype_short_unsigned;
-+  tree unsigned_ftype_unsigned;
-+
-+  endlink = void_list_node;
-+
-+  short_unsigned_endlink
-+    = tree_cons (NULL_TREE, short_unsigned_type_node, endlink);
-+
-+  unsigned_endlink
-+    = tree_cons (NULL_TREE, unsigned_type_node, endlink);
-+
-+  short_unsigned_ftype_short_unsigned
-+    = build_function_type (short_unsigned_type_node, short_unsigned_endlink);
-+
-+  unsigned_ftype_unsigned
-+    = build_function_type (unsigned_type_node, unsigned_endlink);
-+
-+  /* Initialise the byte swap function. */
-+  add_builtin_function ("__builtin_ubicom32_swapb_2",
-+                      short_unsigned_ftype_short_unsigned,
-+                      UBICOM32_BUILTIN_UBICOM32_SWAPB_2,
-+                      BUILT_IN_MD, NULL,
-+                      NULL_TREE);
-+
-+  /* Initialise the byte swap function. */
-+  add_builtin_function ("__builtin_ubicom32_swapb_4",
-+                      unsigned_ftype_unsigned,
-+                      UBICOM32_BUILTIN_UBICOM32_SWAPB_4,
-+                      BUILT_IN_MD, NULL,
-+                      NULL_TREE);
-+}
-+
-+/* Given a builtin function taking 2 operands (i.e., target + source),
-+   emit the RTL for the underlying instruction. */
-+static rtx
-+ubicom32_expand_builtin_2op (enum insn_code icode, tree arglist, rtx target)
-+{
-+  tree arg0;
-+  rtx op0, pat;
-+  enum machine_mode tmode, mode0;
-+
-+  /* Grab the incoming argument and emit its RTL. */
-+  arg0 = TREE_VALUE (arglist);
-+  op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
-+
-+  /* Determine the modes of the instruction operands. */
-+  tmode = insn_data[icode].operand[0].mode;
-+  mode0 = insn_data[icode].operand[1].mode;
-+
-+  /* Ensure that the incoming argument RTL is in a register of the
-+     correct mode. */
-+  if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
-+    op0 = copy_to_mode_reg (mode0, op0);
-+
-+  /* If there isn't a suitable target, emit a target register. */
-+  if (target == 0
-+      || GET_MODE (target) != tmode
-+      || !(*insn_data[icode].operand[0].predicate) (target, tmode))
-+    target = gen_reg_rtx (tmode);
-+
-+  /* Emit and return the new instruction. */
-+  pat = GEN_FCN (icode) (target, op0);
-+  if (!pat)
-+    return 0;
-+  emit_insn (pat);
-+
-+  return target;
-+}
-+
-+/* Expand a call to a builtin function. */
-+static rtx
-+ubicom32_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
-+                       enum machine_mode mode ATTRIBUTE_UNUSED,
-+                       int ignore ATTRIBUTE_UNUSED)
-+{
-+  tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
-+  tree arglist = CALL_EXPR_ARGS(exp);
-+  int fcode = DECL_FUNCTION_CODE (fndecl);
-+
-+  switch (fcode)
-+    {
-+    case UBICOM32_BUILTIN_UBICOM32_SWAPB_2:
-+      return ubicom32_expand_builtin_2op (CODE_FOR_bswaphi, arglist, target);
-+
-+    case UBICOM32_BUILTIN_UBICOM32_SWAPB_4:
-+      return ubicom32_expand_builtin_2op (CODE_FOR_bswapsi, arglist, target);
-+
-+    default:
-+      gcc_unreachable();
-+    }
-+
-+  /* Should really do something sensible here.  */
-+  return NULL_RTX;
-+}
-+
-+/* Fold any constant argument for a swapb.2 instruction.  */
-+static tree
-+ubicom32_fold_builtin_ubicom32_swapb_2 (tree fndecl, tree arglist)
-+{
-+  tree arg0;
-+
-+  arg0 = TREE_VALUE (arglist);
-+
-+  /* Optimize constant value.  */
-+  if (TREE_CODE (arg0) == INTEGER_CST)
-+    {
-+      HOST_WIDE_INT v;
-+      HOST_WIDE_INT res;
-+
-+      v = TREE_INT_CST_LOW (arg0);
-+      res = ((v >> 8) & 0xff)
-+           | ((v & 0xff) << 8);
-+
-+      return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), res);
-+    }
-+
-+  return NULL_TREE;
-+}
-+
-+/* Fold any constant argument for a swapb.4 instruction.  */
-+static tree
-+ubicom32_fold_builtin_ubicom32_swapb_4 (tree fndecl, tree arglist)
-+{
-+  tree arg0;
-+
-+  arg0 = TREE_VALUE (arglist);
-+
-+  /* Optimize constant value.  */
-+  if (TREE_CODE (arg0) == INTEGER_CST)
-+    {
-+      unsigned HOST_WIDE_INT v;
-+      unsigned HOST_WIDE_INT res;
-+
-+      v = TREE_INT_CST_LOW (arg0);
-+      res = ((v >> 24) & 0xff)
-+           | (((v >> 16) & 0xff) << 8)
-+           | (((v >> 8) & 0xff) << 16)
-+           | ((v & 0xff) << 24);
-+
-+      return build_int_cst_wide (TREE_TYPE (TREE_TYPE (fndecl)), res, 0);
-+    }
-+
-+  return NULL_TREE;
-+}
-+
-+/* Fold any constant arguments for builtin functions.  */
-+static tree
-+ubicom32_fold_builtin (tree fndecl, tree arglist, bool ignore ATTRIBUTE_UNUSED)
-+{
-+  switch (DECL_FUNCTION_CODE (fndecl))
-+    {
-+    case UBICOM32_BUILTIN_UBICOM32_SWAPB_2:
-+      return ubicom32_fold_builtin_ubicom32_swapb_2 (fndecl, arglist);
-+
-+    case UBICOM32_BUILTIN_UBICOM32_SWAPB_4:
-+      return ubicom32_fold_builtin_ubicom32_swapb_4 (fndecl, arglist);
-+
-+    default:
-+      return NULL;
-+    }
-+}
-+
-+/* Implementation of TARGET_ASM_INTEGER.  When using FD-PIC, we need to
-+   tell the assembler to generate pointers to function descriptors in
-+   some cases.  */
-+static bool
-+ubicom32_assemble_integer (rtx value, unsigned int size, int aligned_p)
-+{
-+  if (TARGET_FDPIC && size == UNITS_PER_WORD)
-+    {
-+      if (GET_CODE (value) == SYMBOL_REF
-+        && SYMBOL_REF_FUNCTION_P (value))
-+      {
-+        fputs ("\t.picptr\t%funcdesc(", asm_out_file);
-+        output_addr_const (asm_out_file, value);
-+        fputs (")\n", asm_out_file);
-+        return true;
-+      }
-+
-+      if (!aligned_p)
-+      {
-+        /* We've set the unaligned SI op to NULL, so we always have to
-+           handle the unaligned case here.  */
-+        assemble_integer_with_op ("\t.4byte\t", value);
-+        return true;
-+      }
-+    }
-+
-+  return default_assemble_integer (value, size, aligned_p);
-+}
-+
-+/* If the constant I can be constructed by shifting a source-1 immediate
-+   by a constant number of bits then return the bit count.  If not
-+   return 0.  */
-+
-+int
-+ubicom32_shiftable_const_int (int i)
-+{
-+  int shift = 0;
-+
-+  /* Note that any constant that can be represented as an immediate to
-+     a movei instruction is automatically ignored here in the interests
-+     of the clarity of the output asm code.  */
-+  if (i >= -32768 && i <= 32767)
-+    return 0;
-+
-+  /* Find the number of trailing zeroes.  We could use __builtin_ctz
-+     here but it's not obvious if this is supported on all build
-+     compilers so we err on the side of caution.  */
-+  if ((i & 0xffff) == 0)
-+    {
-+      shift += 16;
-+      i >>= 16;
-+    }
-+
-+  if ((i & 0xff) == 0)
-+    {
-+      shift += 8;
-+      i >>= 8;
-+    }
-+
-+  if ((i & 0xf) == 0)
-+    {
-+      shift += 4;
-+      i >>= 4;
-+    }
-+
-+  if ((i & 0x3) == 0)
-+    {
-+      shift += 2;
-+      i >>= 2;
-+    }
-+
-+  if ((i & 0x1) == 0)
-+    {
-+      shift += 1;
-+      i >>= 1;
-+    }
-+
-+  if (i >= -128 && i <= 127)
-+    return shift;
-+
-+  return 0;
-+}
-+
---- /dev/null
-+++ b/gcc/config/ubicom32/ubicom32.h
-@@ -0,0 +1,1564 @@
-+/* Definitions of target machine for Ubicom32
-+
-+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
-+   2009 Free Software Foundation, Inc.
-+   Contributed by Ubicom, Inc.
-+
-+   This file is part of GCC.
-+
-+   GCC is free software; you can redistribute it and/or modify it
-+   under the terms of the GNU General Public License as published
-+   by the Free Software Foundation; either version 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/>.  */
-+
-+\f
-+
-+#define OBJECT_FORMAT_ELF
-+
-+/* Run-time target specifications. */
-+
-+/* Target CPU builtins.  */
-+#define TARGET_CPU_CPP_BUILTINS()                     \
-+  do                                                  \
-+    {                                                 \
-+      builtin_define_std ("__UBICOM32__");            \
-+      builtin_define_std ("__ubicom32__");            \
-+                                                      \
-+      if (TARGET_FDPIC)                                       \
-+      {                                               \
-+        builtin_define ("__UBICOM32_FDPIC__");        \
-+        builtin_define ("__FDPIC__");                 \
-+      }                                               \
-+    }                                                 \
-+  while (0)
-+
-+#ifndef TARGET_DEFAULT
-+#define TARGET_DEFAULT 0
-+#endif
-+
-+extern int ubicom32_case_values_threshold;
-+
-+/* Nonzero if this chip supports the Ubicom32 v3 ISA.  */
-+extern int ubicom32_v3;
-+
-+/* Nonzero if this chip supports the Ubicom32 v4 ISA.  */
-+extern int ubicom32_v4;
-+
-+extern int ubicom32_stack_size;
-+
-+/* Flag for whether we can use calli instead of ret in returns.  */
-+extern int ubicom32_can_use_calli_to_ret;
-+
-+/* This macro is a C statement to print on `stderr' a string describing the
-+   particular machine description choice.  Every machine description should
-+   define `TARGET_VERSION'. */
-+#define TARGET_VERSION fprintf (stderr, " (UBICOM32)");
-+
-+/* We don't need a frame pointer to debug things.  Doing this means
-+   that gcc can turn on -fomit-frame-pointer when '-O' is specified.  */
-+#define CAN_DEBUG_WITHOUT_FP
-+
-+/* We need to handle processor-specific options.  */
-+#define OVERRIDE_OPTIONS ubicom32_override_options ()
-+
-+#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) \
-+  ubicom32_optimization_options (LEVEL, SIZE)
-+
-+/* For Ubicom32 the least significant bit has the lowest bit number
-+   so we define this to be 0.  */
-+#define BITS_BIG_ENDIAN 0
-+
-+/* For Ubicom32 the most significant byte in a word has the lowest
-+   number.  */
-+#define BYTES_BIG_ENDIAN 1
-+
-+/* For Ubicom32, in a multiword object, the most signifant word has the
-+   lowest number.  */
-+#define WORDS_BIG_ENDIAN 1
-+
-+/* Ubicom32 has 8 bits per byte.  */
-+#define BITS_PER_UNIT 8
-+
-+/* Ubicom32 has 32 bits per word.  */
-+#define BITS_PER_WORD 32
-+
-+/* Width of a word, in units (bytes).  */
-+#define UNITS_PER_WORD 4
-+
-+/* Width of a pointer, in bits.  */
-+#define POINTER_SIZE 32
-+
-+/* Alias for pointers.  Ubicom32 is a 32-bit architecture so we use
-+   SImode.  */
-+#define Pmode SImode
-+
-+/* Normal alignment required for function parameters on the stack, in
-+   bits.  */
-+#define PARM_BOUNDARY 32
-+
-+/* We need to maintain the stack on a 32-bit boundary.  */
-+#define STACK_BOUNDARY 32
-+
-+/* Alignment required for a function entry point, in bits.  */
-+#define FUNCTION_BOUNDARY 32
-+
-+/* Alias for the machine mode used for memory references to functions being
-+   called, in `call' RTL expressions.  We use byte-oriented addresses
-+   here.  */
-+#define FUNCTION_MODE QImode
-+
-+/* Biggest alignment that any data type can require on this machine,
-+   in bits.  */
-+#define BIGGEST_ALIGNMENT 32
-+
-+/* this default to BIGGEST_ALIGNMENT unless defined       */
-+/* ART: What's the correct value here? Default is (((unsigned int)1<<28)*8)*/
-+#undef MAX_OFILE_ALIGNMENT
-+#define MAX_OFILE_ALIGNMENT (128 * 8)
-+
-+/* Alignment in bits to be given to a structure bit field that follows an empty
-+   field such as `int : 0;'.  */
-+#define EMPTY_FIELD_BOUNDARY 32
-+
-+/* All structures must be a multiple of 32 bits in size.  */
-+#define STRUCTURE_SIZE_BOUNDARY 32
-+
-+/* A bit-field declared as `int' forces `int' alignment for the struct.  */
-+#define PCC_BITFIELD_TYPE_MATTERS 1
-+
-+/* For Ubicom32 we absolutely require that data be aligned with nominal
-+   alignment.  */
-+#define STRICT_ALIGNMENT 1
-+
-+/* Make strcpy of constants fast.  */
-+#define CONSTANT_ALIGNMENT(EXP, ALIGN)  \
-+  (TREE_CODE (EXP) == STRING_CST      \
-+   && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
-+
-+/* Define this macro as an expression for the alignment of a structure
-+   (given by STRUCT as a tree node) if the alignment computed in the
-+   usual way is COMPUTED and the alignment explicitly specified was
-+   SPECIFIED. */
-+#define DATA_ALIGNMENT(TYPE, ALIGN)                                   \
-+  ((((ALIGN) < BITS_PER_WORD)                                         \
-+    && (TREE_CODE (TYPE) == ARRAY_TYPE                                        \
-+      || TREE_CODE (TYPE) == UNION_TYPE                               \
-+      || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN))
-+
-+#define LOCAL_ALIGNMENT(TYPE,ALIGN) DATA_ALIGNMENT(TYPE,ALIGN)
-+
-+/* For Ubicom32 we default to unsigned chars.  */
-+#define DEFAULT_SIGNED_CHAR 0
-+
-+/* Machine-specific data register numbers.  */
-+#define FIRST_DATA_REGNUM 0
-+#define D10_REGNUM 10
-+#define D11_REGNUM 11
-+#define D12_REGNUM 12
-+#define D13_REGNUM 13
-+#define LAST_DATA_REGNUM 15
-+
-+/* Machine-specific address register numbers.  */
-+#define FIRST_ADDRESS_REGNUM 16
-+#define LAST_ADDRESS_REGNUM 22
-+
-+/* Register numbers used for passing a function's static chain pointer.  If
-+   register windows are used, the register number as seen by the called
-+   function is `STATIC_CHAIN_INCOMING_REGNUM', while the register number as
-+   seen by the calling function is `STATIC_CHAIN_REGNUM'.  If these registers
-+   are the same, `STATIC_CHAIN_INCOMING_REGNUM' need not be defined.
-+
-+   The static chain register need not be a fixed register.
-+
-+   If the static chain is passed in memory, these macros should not be defined;
-+   instead, the next two macros should be defined.  */
-+#define STATIC_CHAIN_REGNUM (FIRST_ADDRESS_REGNUM + 1)
-+
-+/* The register number of the frame pointer register, which is used to access
-+   automatic variables in the stack frame.  We generally eliminate this anyway
-+   for Ubicom32 but we make it A6 by default.  */
-+#define FRAME_POINTER_REGNUM (LAST_ADDRESS_REGNUM)
-+
-+/* The register number of the stack pointer register, which is also be a
-+   fixed register according to `FIXED_REGISTERS'.  For Ubicom32 we don't
-+   have a hardware requirement about which register this is, but by convention
-+   we use A7.  */
-+#define STACK_POINTER_REGNUM (LAST_ADDRESS_REGNUM + 1)
-+
-+/* Machine-specific accumulator register numbers.  */
-+#define ACC0_HI_REGNUM 24
-+#define ACC0_LO_REGNUM 25
-+#define ACC1_HI_REGNUM 26
-+#define ACC1_LO_REGNUM 27
-+
-+/* source3 register number */
-+#define SOURCE3_REGNUM 28
-+
-+/* The register number of the arg pointer register, which is used to access the
-+   function's argument list.  On some machines, this is the same as the frame
-+   pointer register.  On some machines, the hardware determines which register
-+   this is.  On other machines, you can choose any register you wish for this
-+   purpose.  If this is not the same register as the frame pointer register,
-+   then you must mark it as a fixed register according to `FIXED_REGISTERS', or
-+   arrange to be able to eliminate it.  */
-+#define ARG_POINTER_REGNUM 29
-+
-+/* Pseudo-reg for condition code.  */
-+#define CC_REGNUM 30
-+
-+/* Interrupt set/clear registers.  */
-+#define INT_SET0_REGNUM 31
-+#define INT_SET1_REGNUM 32
-+#define INT_CLR0_REGNUM 33
-+#define INT_CLR1_REGNUM 34
-+
-+/* Scratchpad registers.  */
-+#define SCRATCHPAD0_REGNUM 35
-+#define SCRATCHPAD1_REGNUM 36
-+#define SCRATCHPAD2_REGNUM 37
-+#define SCRATCHPAD3_REGNUM 38
-+
-+/* FDPIC register.  */
-+#define FDPIC_REGNUM 16
-+
-+/* Number of hardware registers known to the compiler.  They receive numbers 0
-+   through `FIRST_PSEUDO_REGISTER-1'; thus, the first pseudo register's number
-+   really is assigned the number `FIRST_PSEUDO_REGISTER'.  */
-+#define FIRST_PSEUDO_REGISTER 39
-+
-+/* An initializer that says which registers are used for fixed purposes all
-+   throughout the compiled code and are therefore not available for general
-+   allocation.  These would include the stack pointer, the frame pointer
-+   (except on machines where that can be used as a general register when no
-+   frame pointer is needed), the program counter on machines where that is
-+   considered one of the addressable registers, and any other numbered register
-+   with a standard use.
-+
-+   This information is expressed as a sequence of numbers, separated by commas
-+   and surrounded by braces.  The Nth number is 1 if register N is fixed, 0
-+   otherwise.
-+
-+   The table initialized from this macro, and the table initialized by the
-+   following one, may be overridden at run time either automatically, by the
-+   actions of the macro `CONDITIONAL_REGISTER_USAGE', or by the user with the
-+   command options `-ffixed-REG', `-fcall-used-REG' and `-fcall-saved-REG'.  */
-+#define FIXED_REGISTERS                                       \
-+  {                                                   \
-+    0, 0, 0, 0, 0, 0, 0, 0,   /* d0 - d7 */           \
-+    0, 0, 0, 0, 0, 0, 0, 1,   /* d8 - d15 */          \
-+    0, 0, 0, 0, 0, 0, 0, 1,   /* a0 - a7 */           \
-+    0, 0,                     /* acc0 hi/lo */        \
-+    0, 0,                     /* acc1 hi/lo */        \
-+    0,                                /* source3 */           \
-+    1,                                /* arg */               \
-+    1,                                /* cc */                \
-+    1, 1,                     /* int_set[01] */       \
-+    1, 1,                     /* int_clr[01] */       \
-+    1, 1, 1, 1                        /* scratchpad[0123] */  \
-+  }
-+
-+/* Like `FIXED_REGISTERS' but has 1 for each register that is clobbered (in
-+   general) by function calls as well as for fixed registers.  This macro
-+   therefore identifies the registers that are not available for general
-+   allocation of values that must live across function calls.
-+
-+   If a register has 0 in `CALL_USED_REGISTERS', the compiler automatically
-+   saves it on function entry and restores it on function exit, if the register
-+   is used within the function.  */
-+#define CALL_USED_REGISTERS                           \
-+  {                                                   \
-+    1, 1, 1, 1, 1, 1, 1, 1,   /* d0 - d7 */           \
-+    1, 1, 0, 0, 0, 0, 1, 1,   /* d8 - d15 */          \
-+    1, 0, 0, 1, 1, 1, 0, 1,   /* a0 - a7 */           \
-+    1, 1,                     /* acc0 hi/lo */        \
-+    1, 1,                     /* acc1 hi/lo */        \
-+    1,                                /* source3 */           \
-+    1,                                /* arg */               \
-+    1,                                /* cc */                \
-+    1, 1,                     /* int_set[01] */       \
-+    1, 1,                     /* int_clr[01] */       \
-+    1, 1, 1, 1                        /* scratchpad[0123] */  \
-+  }
-+
-+/* How to refer to registers in assembler output.
-+   This sequence is indexed by compiler's hard-register-number (see above).  */
-+
-+/* A C initializer containing the assembler's names for the machine registers,
-+   each one as a C string constant.  This is what translates register numbers
-+   in the compiler into assembler language.  */
-+#define REGISTER_NAMES                                                \
-+  {                                                           \
-+    "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",           \
-+    "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",     \
-+    "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",           \
-+    "acc0_hi", "acc0_lo",                                     \
-+    "acc1_hi", "acc1_lo",                                     \
-+    "source3",                                                        \
-+    "arg",                                                    \
-+    "cc",                                                     \
-+    "int_set0", "int_set1",                                   \
-+    "int_clr0", "int_clr1",                                   \
-+    "scratchpad0", "scratchpad1", "scratchpad2", "scratchpad3"        \
-+  }
-+
-+#define CONDITIONAL_REGISTER_USAGE                            \
-+  ubicom32_conditional_register_usage ();
-+
-+/* Order of allocation of registers.  */
-+
-+/* If defined, an initializer for a vector of integers, containing the numbers
-+   of hard registers in the order in which GNU CC should prefer to use them
-+   (from most preferred to least).
-+
-+   For Ubicom32 we try using caller-clobbered data registers first, then
-+   callee-saved data registers, then caller-clobbered address registers,
-+   then callee-saved address registers and finally everything else.
-+
-+   The caller-clobbered registers are usually slightly cheaper to use because
-+   there's no need to save/restore.  */
-+#define REG_ALLOC_ORDER                                               \
-+  {                                                           \
-+    0, 1, 2, 3, 4,            /* d0 - d4 */                   \
-+    5, 6, 7, 8, 9,            /* d5 - d9 */                   \
-+    14,                               /* d14 */                       \
-+    10, 11, 12, 13,           /* d10 - d13 */                 \
-+    19, 20, 16, 21,           /* a3, a4, a0, a5 */            \
-+    17, 18, 22,                       /* a1, a2, a6 */                \
-+    24, 25,                   /* acc0 hi/lo */                \
-+    26, 27,                   /* acc0 hi/lo */                \
-+    28                                /* source3 */                   \
-+  }
-+
-+/* C expression for the number of consecutive hard registers, starting at
-+   register number REGNO, required to hold a value of mode MODE.  */
-+#define HARD_REGNO_NREGS(REGNO, MODE) \
-+  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-+
-+/* Most registers can hold QImode, HImode and SImode values but we have to
-+   be able to indicate any hard registers that cannot hold values with some
-+   modes.  */
-+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
-+  ubicom32_hard_regno_mode_ok(REGNO, MODE)
-+
-+/* We can rename most registers aside from the FDPIC register if we're using
-+   FDPIC.  */
-+#define HARD_REGNO_RENAME_OK(from, to) (TARGET_FDPIC ? ((to) != FDPIC_REGNUM) : 1)
-+
-+/* A C expression that is nonzero if it is desirable to choose register
-+   allocation so as to avoid move instructions between a value of mode MODE1
-+   and a value of mode MODE2.
-+
-+   If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, MODE2)' are
-+   ever different for any R, then `MODES_TIEABLE_P (MODE1, MODE2)' must be
-+   zero.  */
-+#define MODES_TIEABLE_P(MODE1, MODE2) 1
-+
-+/* An enumeral type that must be defined with all the register class names as
-+   enumeral values.  `NO_REGS' must be first.  `ALL_REGS' must be the last
-+   register class, followed by one more enumeral value, `LIM_REG_CLASSES',
-+   which is not a register class but rather tells how many classes there are.
-+
-+   Each register class has a number, which is the value of casting the class
-+   name to type `int'.  The number serves as an index in many of the tables
-+   described below.  */
-+
-+enum reg_class
-+{
-+  NO_REGS,
-+  DATA_REGS,
-+  FDPIC_REG,
-+  ADDRESS_REGS,
-+  ALL_ADDRESS_REGS,
-+  ACC_LO_REGS,
-+  ACC_REGS,
-+  CC_REG,
-+  DATA_ACC_REGS,
-+  SOURCE3_REG,
-+  SPECIAL_REGS,
-+  GENERAL_REGS,
-+  ALL_REGS,
-+  LIM_REG_CLASSES
-+};
-+
-+/* The number of distinct register classes.  */
-+#define N_REG_CLASSES (int) LIM_REG_CLASSES
-+
-+/* An initializer containing the names of the register classes as C string
-+   constants.  These names are used in writing some of the debugging dumps.  */
-+
-+#define REG_CLASS_NAMES               \
-+{                             \
-+  "NO_REGS",                  \
-+  "DATA_REGS",                        \
-+  "FDPIC_REG",                        \
-+  "ADDRESS_REGS",             \
-+  "ALL_ADDRESS_REGS",         \
-+  "ACC_LO_REGS",              \
-+  "ACC_REGS",                 \
-+  "CC_REG",                   \
-+  "DATA_ACC_REGS",            \
-+  "SOURCE3_REG",              \
-+  "SPECIAL_REGS",             \
-+  "GENERAL_REGS",             \
-+  "ALL_REGS",                 \
-+  "LIM_REGS"                  \
-+}
-+
-+/* An initializer containing the contents of the register classes, as integers
-+   which are bit masks.  The Nth integer specifies the contents of class N.
-+   The way the integer MASK is interpreted is that register R is in the class
-+   if `MASK & (1 << R)' is 1.
-+
-+   When the machine has more than 32 registers, an integer does not suffice.
-+   Then the integers are replaced by sub-initializers, braced groupings
-+   containing several integers.  Each sub-initializer must be suitable as an
-+   initializer for the type `HARD_REG_SET' which is defined in
-+   `hard-reg-set.h'.  */
-+#define REG_CLASS_CONTENTS                                    \
-+{                                                             \
-+  {0x00000000, 0x00000000},   /* No regs */                   \
-+  {0x0000ffff, 0x00000000},   /* DATA_REGS */                 \
-+  {0x00010000, 0x00000000},   /* FDPIC_REG */                 \
-+  {0x20fe0000, 0x00000000},   /* ADDRESS_REGS */              \
-+  {0x20ff0000, 0x00000000},   /* ALL_ADDRESS_REGS */          \
-+  {0x0a000000, 0x00000000},   /* ACC_LO_REGS */               \
-+  {0x0f000000, 0x00000000},   /* ACC_REGS */                  \
-+  {0x40000000, 0x00000000},   /* CC_REG */                    \
-+  {0x0f00ffff, 0x00000000},   /* DATA_ACC_REGS */             \
-+  {0x10000000, 0x00000000},   /* SOURGE3_REG */               \
-+  {0x80000000, 0x0000007f},   /* SPECIAL_REGS */              \
-+  {0xbfffffff, 0x0000007f},   /* GENERAL_REGS */              \
-+  {0xbfffffff, 0x0000007f}    /* ALL_REGS     */              \
-+}
-+
-+extern enum reg_class const ubicom32_regclass_map[FIRST_PSEUDO_REGISTER];
-+
-+/* A C expression whose value is a register class containing hard register
-+   REGNO.  In general there is more than one such class; choose a class which
-+   is "minimal", meaning that no smaller class also contains the register.  */
-+#define REGNO_REG_CLASS(REGNO) (ubicom32_regclass_map[REGNO])
-+
-+#define IRA_COVER_CLASSES             \
-+{                                     \
-+  GENERAL_REGS,                               \
-+  LIM_REG_CLASSES                     \
-+}
-+
-+/* Ubicom32 base registers must be address registers since addresses can
-+   only be reached via address registers.  */
-+#define BASE_REG_CLASS ALL_ADDRESS_REGS
-+
-+/* Ubicom32 index registers must be data registers since we cannot add
-+   two address registers together to form an address.  */
-+#define INDEX_REG_CLASS DATA_REGS
-+
-+/* A C expression which is nonzero if register number NUM is suitable for use
-+   as a base register in operand addresses.  It may be either a suitable hard
-+   register or a pseudo register that has been allocated such a hard register.  */
-+
-+#ifndef REG_OK_STRICT
-+#define REGNO_OK_FOR_BASE_P(regno) \
-+  ubicom32_regno_ok_for_base_p (regno, 0)
-+#else
-+#define REGNO_OK_FOR_BASE_P(regno) \
-+  ubicom32_regno_ok_for_base_p (regno, 1)
-+#endif
-+
-+/* A C expression which is nonzero if register number NUM is suitable for use
-+   as an index register in operand addresses.  It may be either a suitable hard
-+   register or a pseudo register that has been allocated such a hard register.
-+
-+   The difference between an index register and a base register is that the
-+   index register may be scaled.  If an address involves the sum of two
-+   registers, neither one of them scaled, then either one may be labeled the
-+   "base" and the other the "index"; but whichever labeling is used must fit
-+   the machine's constraints of which registers may serve in each capacity.
-+   The compiler will try both labelings, looking for one that is valid, and
-+   will reload one or both registers only if neither labeling works.  */
-+#ifndef REG_OK_STRICT
-+#define REGNO_OK_FOR_INDEX_P(regno) \
-+  ubicom32_regno_ok_for_index_p (regno, 0)
-+#else
-+#define REGNO_OK_FOR_INDEX_P(regno) \
-+  ubicom32_regno_ok_for_index_p (regno, 1)
-+#endif
-+
-+/* Attempt to restrict the register class we need to copy value X intoto the
-+   would-be register class CLASS.  Most things are fine for Ubicom32 but we
-+   have to restrict certain types of address loads.  */
-+#define PREFERRED_RELOAD_CLASS(X, CLASS) \
-+  ubicom32_preferred_reload_class (X, CLASS)
-+
-+/* A C expression for the maximum number of consecutive registers of
-+   class CLASS needed to hold a value of mode MODE.  For Ubicom32 this
-+   is pretty much identical to HARD_REGNO_NREGS.  */
-+#define CLASS_MAX_NREGS(CLASS, MODE)  \
-+  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-+
-+/* For Ubicom32 the stack grows downwards when we push a word onto the stack
-+   - i.e. it moves to a smaller address.  */
-+#define STACK_GROWS_DOWNWARD 1
-+
-+/* Offset from the frame pointer to the first local variable slot to
-+   be allocated.  */
-+#define STARTING_FRAME_OFFSET 0
-+
-+/* Offset from the argument pointer register to the first argument's
-+   address.  */
-+#define FIRST_PARM_OFFSET(FNDECL) 0
-+
-+/* A C expression whose value is RTL representing the value of the return
-+   address for the frame COUNT steps up from the current frame, after the
-+   prologue.  FRAMEADDR is the frame pointer of the COUNT frame, or the frame
-+   pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is
-+   defined.
-+
-+   The value of the expression must always be the correct address when COUNT is
-+   zero, but may be `NULL_RTX' if there is not way to determine the return
-+   address of other frames.  */
-+#define RETURN_ADDR_RTX(COUNT, FRAME) \
-+  ubicom32_return_addr_rtx (COUNT, FRAME)
-+
-+/* Register That Address the Stack Frame.  */
-+
-+/* We don't actually require a frame pointer in most functions with the
-+   Ubicom32 architecture so we allow it to be eliminated.  */
-+#define FRAME_POINTER_REQUIRED 0
-+
-+/* Macro that defines a table of register pairs used to eliminate unecessary
-+   registers that point into the stack frame.
-+
-+   For Ubicom32 we don't generally need an arg pointer of a frame pointer
-+   so we allow the arg pointer to be replaced by either the frame pointer or
-+   the stack pointer.  We also allow the frame pointer to be replaced by
-+   the stack pointer.  */
-+#define ELIMINABLE_REGS                                       \
-+{                                                     \
-+  {ARG_POINTER_REGNUM,         STACK_POINTER_REGNUM},         \
-+  {ARG_POINTER_REGNUM,         FRAME_POINTER_REGNUM},         \
-+  {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}                \
-+}
-+
-+/* Let the compiler know that we want to use the ELIMINABLE_REGS macro
-+   above.  */
-+#define CAN_ELIMINATE(FROM, TO) 1
-+
-+/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'.  It specifies the
-+   initial difference between the specified pair of registers.  This macro must
-+   be defined if `ELIMINABLE_REGS' is defined.  */
-+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
-+  (OFFSET) = ubicom32_initial_elimination_offset (FROM, TO)
-+
-+/* If defined, the maximum amount of space required for outgoing arguments will
-+   be computed and placed into the variable
-+   `current_function_outgoing_args_size'.  No space will be pushed onto the
-+   stack for each call; instead, the function prologue should increase the
-+   stack frame size by this amount.
-+
-+   Defining both `PUSH_ROUNDING' and `ACCUMULATE_OUTGOING_ARGS' is not
-+   proper.  */
-+#define ACCUMULATE_OUTGOING_ARGS 1
-+
-+/* Define this macro if functions should assume that stack space has been
-+   allocated for arguments even when their values are passed in registers.
-+
-+   The value of this macro is the size, in bytes, of the area reserved for
-+   arguments passed in registers for the function represented by FNDECL.
-+
-+   This space can be allocated by the caller, or be a part of the
-+   machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' says
-+   which.  */
-+#define REG_PARM_STACK_SPACE(FNDECL) ubicom32_reg_parm_stack_space(FNDECL)
-+
-+/* A C expression that should indicate the number of bytes of its own arguments
-+   that a function pops on returning, or 0 if the function pops no arguments
-+   and the caller must therefore pop them all after the function returns.
-+
-+   FUNDECL is a C variable whose value is a tree node that describes the
-+   function in question.  Normally it is a node of type `FUNCTION_DECL' that
-+   describes the declaration of the function.  From this it is possible to
-+   obtain the DECL_MACHINE_ATTRIBUTES of the function.
-+
-+   FUNTYPE is a C variable whose value is a tree node that describes the
-+   function in question.  Normally it is a node of type `FUNCTION_TYPE' that
-+   describes the data type of the function.  From this it is possible to obtain
-+   the data types of the value and arguments (if known).
-+
-+   When a call to a library function is being considered, FUNTYPE will contain
-+   an identifier node for the library function.  Thus, if you need to
-+   distinguish among various library functions, you can do so by their names.
-+   Note that "library function" in this context means a function used to
-+   perform arithmetic, whose name is known specially in the compiler and was
-+   not mentioned in the C code being compiled.
-+
-+   STACK-SIZE is the number of bytes of arguments passed on the stack.  If a
-+   variable number of bytes is passed, it is zero, and argument popping will
-+   always be the responsibility of the calling function.
-+
-+   On the Vax, all functions always pop their arguments, so the definition of
-+   this macro is STACK-SIZE.  On the 68000, using the standard calling
-+   convention, no functions pop their arguments, so the value of the macro is
-+   always 0 in this case.  But an alternative calling convention is available
-+   in which functions that take a fixed number of arguments pop them but other
-+   functions (such as `printf') pop nothing (the caller pops all).  When this
-+   convention is in use, FUNTYPE is examined to determine whether a function
-+   takes a fixed number of arguments.  */
-+#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0
-+
-+/* A C expression that controls whether a function argument is passed in a
-+   register, and which register.
-+
-+   The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes (in a way
-+   defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE) all of the previous
-+   arguments so far passed in registers; MODE, the machine mode of the argument;
-+   TYPE, the data type of the argument as a tree node or 0 if that is not known
-+   (which happens for C support library functions); and NAMED, which is 1 for an
-+   ordinary argument and 0 for nameless arguments that correspond to `...' in the
-+   called function's prototype.
-+
-+   The value of the expression should either be a `reg' RTX for the hard
-+   register in which to pass the argument, or zero to pass the argument on the
-+   stack.
-+
-+   For machines like the Vax and 68000, where normally all arguments are
-+   pushed, zero suffices as a definition.
-+
-+   The usual way to make the ANSI library `stdarg.h' work on a machine where
-+   some arguments are usually passed in registers, is to cause nameless
-+   arguments to be passed on the stack instead.  This is done by making
-+   `FUNCTION_ARG' return 0 whenever NAMED is 0.
-+
-+   You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the definition of
-+   this macro to determine if this argument is of a type that must be passed in
-+   the stack.  If `REG_PARM_STACK_SPACE' is not defined and `FUNCTION_ARG'
-+   returns non-zero for such an argument, the compiler will abort.  If
-+   `REG_PARM_STACK_SPACE' is defined, the argument will be computed in the
-+   stack and then loaded into a register.  */
-+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
-+  function_arg (&CUM, MODE, TYPE, NAMED)
-+
-+#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
-+  function_incoming_arg (&CUM, MODE, TYPE, NAMED)
-+
-+/* A C expression for the number of words, at the beginning of an argument,
-+   must be put in registers.  The value must be zero for arguments that are
-+   passed entirely in registers or that are entirely pushed on the stack.
-+
-+   On some machines, certain arguments must be passed partially in registers
-+   and partially in memory.  On these machines, typically the first N words of
-+   arguments are passed in registers, and the rest on the stack.  If a
-+   multi-word argument (a `double' or a structure) crosses that boundary, its
-+   first few words must be passed in registers and the rest must be pushed.
-+   This macro tells the compiler when this occurs, and how many of the words
-+   should go in registers.
-+
-+   `FUNCTION_ARG' for these arguments should return the first register to be
-+   used by the caller for this argument; likewise `FUNCTION_INCOMING_ARG', for
-+   the called function.  */
-+
-+/* A C expression that indicates when an argument must be passed by reference.
-+   If nonzero for an argument, a copy of that argument is made in memory and a
-+   pointer to the argument is passed instead of the argument itself.  The
-+   pointer is passed in whatever way is appropriate for passing a pointer to
-+   that type.
-+
-+   On machines where `REG_PARM_STACK_SPACE' is not defined, a suitable
-+   definition of this macro might be
-+      #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED)  \
-+        MUST_PASS_IN_STACK (MODE, TYPE)  */
-+
-+/* If defined, a C expression that indicates when it is the called function's
-+   responsibility to make a copy of arguments passed by invisible reference.
-+   Normally, the caller makes a copy and passes the address of the copy to the
-+   routine being called.  When FUNCTION_ARG_CALLEE_COPIES is defined and is
-+   nonzero, the caller does not make a copy.  Instead, it passes a pointer to
-+   the "live" value.  The called function must not modify this value.  If it
-+   can be determined that the value won't be modified, it need not make a copy;
-+   otherwise a copy must be made.  */
-+
-+/* A C type for declaring a variable that is used as the first argument of
-+   `FUNCTION_ARG' and other related values.  For some target machines, the type
-+   `int' suffices and can hold the number of bytes of argument so far.
-+
-+   There is no need to record in `CUMULATIVE_ARGS' anything about the arguments
-+   that have been passed on the stack.  The compiler has other variables to
-+   keep track of that.  For target machines on which all arguments are passed
-+   on the stack, there is no need to store anything in `CUMULATIVE_ARGS';
-+   however, the data structure must exist and should not be empty, so use
-+   `int'.  */
-+struct cum_arg
-+{
-+  int nbytes;
-+  int reg;
-+  int stdarg;
-+};
-+#define CUMULATIVE_ARGS struct cum_arg
-+
-+/* A C statement (sans semicolon) for initializing the variable CUM for the
-+   state at the beginning of the argument list.  The variable has type
-+   `CUMULATIVE_ARGS'.  The value of FNTYPE is the tree node for the data type
-+   of the function which will receive the args, or 0 if the args are to a
-+   compiler support library function.  The value of INDIRECT is nonzero when
-+   processing an indirect call, for example a call through a function pointer.
-+   The value of INDIRECT is zero for a call to an explicitly named function, a
-+   library function call, or when `INIT_CUMULATIVE_ARGS' is used to find
-+   arguments for the function being compiled.
-+
-+   When processing a call to a compiler support library function, LIBNAME
-+   identifies which one.  It is a `symbol_ref' rtx which contains the name of
-+   the function, as a string.  LIBNAME is 0 when an ordinary C function call is
-+   being processed.  Thus, each time this macro is called, either LIBNAME or
-+   FNTYPE is nonzero, but never both of them at once.  */
-+
-+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT, NAMED_ARGS) \
-+ init_cumulative_args (&(CUM), FNTYPE, LIBNAME, INDIRECT);
-+
-+/* A C statement (sans semicolon) to update the summarizer variable CUM to
-+   advance past an argument in the argument list.  The values MODE, TYPE and
-+   NAMED describe that argument.  Once this is done, the variable CUM is
-+   suitable for analyzing the *following* argument with `FUNCTION_ARG', etc.
-+
-+   This macro need not do anything if the argument in question was passed on
-+   the stack.  The compiler knows how to track the amount of stack space used
-+   for arguments without any special help.  */
-+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)  \
-+ ((CUM).nbytes += ((MODE) != BLKmode                  \
-+                 ? (GET_MODE_SIZE (MODE) + 3) & ~3    \
-+                 : (int_size_in_bytes (TYPE) + 3) & ~3))
-+
-+/* For the Ubicom32 we define the upper function argument register here.  */
-+#define UBICOM32_FUNCTION_ARG_REGS 10
-+
-+/* A C expression that is nonzero if REGNO is the number of a hard register in
-+   which function arguments are sometimes passed.  This does *not* include
-+   implicit arguments such as the static chain and the structure-value address.
-+   On many machines, no registers can be used for this purpose since all
-+   function arguments are pushed on the stack.  */
-+#define FUNCTION_ARG_REGNO_P(N) ((N) < UBICOM32_FUNCTION_ARG_REGS)
-+
-+\f
-+/* How Scalar Function Values are Returned.  */
-+
-+/* The number of the hard register that is used to return a scalar value from a
-+   function call.  */
-+#define RETURN_VALUE_REGNUM 0
-+
-+/* A C expression to create an RTX representing the place where a function
-+   returns a value of data type VALTYPE.  VALTYPE is a tree node representing a
-+   data type.  Write `TYPE_MODE (VALTYPE)' to get the machine mode used to
-+   represent that type.  On many machines, only the mode is relevant.
-+   (Actually, on most machines, scalar values are returned in the same place
-+   regardless of mode).
-+
-+   If `PROMOTE_FUNCTION_RETURN' is defined, you must apply the same promotion
-+   rules specified in `PROMOTE_MODE' if VALTYPE is a scalar type.
-+
-+   If the precise function being called is known, FUNC is a tree node
-+   (`FUNCTION_DECL') for it; otherwise, FUNC is a null pointer.  This makes it
-+   possible to use a different value-returning convention for specific
-+   functions when all their calls are known.
-+
-+   `FUNCTION_VALUE' is not used for return vales with aggregate data types,
-+   because these are returned in another way.  See `STRUCT_VALUE_REGNUM' and
-+   related macros, below.  */
-+#define FUNCTION_VALUE(VALTYPE, FUNC) \
-+  gen_rtx_REG (TYPE_MODE (VALTYPE), FIRST_DATA_REGNUM)
-+
-+/* A C expression to create an RTX representing the place where a library
-+   function returns a value of mode MODE.
-+
-+   Note that "library function" in this context means a compiler support
-+   routine, used to perform arithmetic, whose name is known specially by the
-+   compiler and was not mentioned in the C code being compiled.
-+
-+   The definition of `LIBRARY_VALUE' need not be concerned aggregate data
-+   types, because none of the library functions returns such types.  */
-+#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, FIRST_DATA_REGNUM)
-+
-+/* A C expression that is nonzero if REGNO is the number of a hard register in
-+   which the values of called function may come back.
-+
-+   A register whose use for returning values is limited to serving as the
-+   second of a pair (for a value of type `double', say) need not be recognized
-+   by this macro.  So for most machines, this definition suffices:
-+
-+      #define FUNCTION_VALUE_REGNO_P(N) ((N) == RETURN)
-+
-+   If the machine has register windows, so that the caller and the called
-+   function use different registers for the return value, this macro should
-+   recognize only the caller's register numbers.  */
-+#define FUNCTION_VALUE_REGNO_P(N) ((N) == FIRST_DATA_REGNUM)
-+
-+\f
-+/* How Large Values are Returned.  */
-+
-+/* A C expression which can inhibit the returning of certain function values in
-+   registers, based on the type of value.  A nonzero value says to return the
-+   function value in memory, just as large structures are always returned.
-+   Here TYPE will be a C expression of type `tree', representing the data type
-+   of the value.
-+
-+   Note that values of mode `BLKmode' must be explicitly handled by this macro.
-+   Also, the option `-fpcc-struct-return' takes effect regardless of this
-+   macro.  On most systems, it is possible to leave the macro undefined; this
-+   causes a default definition to be used, whose value is the constant 1 for
-+   `BLKmode' values, and 0 otherwise.
-+
-+   Do not use this macro to indicate that structures and unions should always
-+   be returned in memory.  You should instead use `DEFAULT_PCC_STRUCT_RETURN'
-+   to indicate this.  */
-+#define RETURN_IN_MEMORY(TYPE)  \
-+  (int_size_in_bytes (TYPE) > 8 || TYPE_MODE (TYPE) == BLKmode)
-+
-+/* Define this macro to be 1 if all structure and union return values must be
-+   in memory.  Since this results in slower code, this should be defined only
-+   if needed for compatibility with other compilers or with an ABI.  If you
-+   define this macro to be 0, then the conventions used for structure and union
-+   return values are decided by the `RETURN_IN_MEMORY' macro.
-+
-+   If not defined, this defaults to the value 1.  */
-+#define DEFAULT_PCC_STRUCT_RETURN 0
-+
-+/*   If the structure value address is not passed in a register, define
-+     `STRUCT_VALUE' as an expression returning an RTX for the place
-+     where the address is passed.  If it returns 0, the address is
-+     passed as an "invisible" first argument.  */
-+#define STRUCT_VALUE 0
-+
-+/* Define this macro as a C expression that is nonzero if the return
-+   instruction or the function epilogue ignores the value of the stack pointer;
-+   in other words, if it is safe to delete an instruction to adjust the stack
-+   pointer before a return from the function.
-+
-+   Note that this macro's value is relevant only for functions for which frame
-+   pointers are maintained.  It is never safe to delete a final stack
-+   adjustment in a function that has no frame pointer, and the compiler knows
-+   this regardless of `EXIT_IGNORE_STACK'.  */
-+#define EXIT_IGNORE_STACK 1
-+
-+/* A C statement or compound statement to output to FILE some assembler code to
-+   call the profiling subroutine `mcount'.  Before calling, the assembler code
-+   must load the address of a counter variable into a register where `mcount'
-+   expects to find the address.  The name of this variable is `LP' followed by
-+   the number LABELNO, so you would generate the name using `LP%d' in a
-+   `fprintf'.
-+
-+   The details of how the address should be passed to `mcount' are determined
-+   by your operating system environment, not by GNU CC.  To figure them out,
-+   compile a small program for profiling using the system's installed C
-+   compiler and look at the assembler code that results.
-+
-+   This declaration must be present, but it can be an abort if profiling is
-+   not implemented.  */
-+
-+#define FUNCTION_PROFILER(file, labelno) ubicom32_profiler(file, labelno)
-+
-+/* A C statement to output, on the stream FILE, assembler code for a block of
-+   data that contains the constant parts of a trampoline.  This code should not
-+   include a label--the label is taken care of automatically.  */
-+#if 0
-+#define TRAMPOLINE_TEMPLATE(FILE)                     \
-+  do {                                                        \
-+    fprintf (FILE, "\tadd -4,sp\n");                  \
-+    fprintf (FILE, "\t.long 0x0004fffa\n");           \
-+    fprintf (FILE, "\tmov (0,sp),a0\n");              \
-+    fprintf (FILE, "\tadd 4,sp\n");                   \
-+    fprintf (FILE, "\tmov (13,a0),a1\n");             \
-+    fprintf (FILE, "\tmov (17,a0),a0\n");             \
-+    fprintf (FILE, "\tjmp (a0)\n");                   \
-+    fprintf (FILE, "\t.long 0\n");                    \
-+    fprintf (FILE, "\t.long 0\n");                    \
-+  } while (0)
-+#endif
-+
-+/* A C expression for the size in bytes of the trampoline, as an integer.  */
-+#define TRAMPOLINE_SIZE 0x1b
-+
-+/* Alignment required for trampolines, in bits.
-+
-+   If you don't define this macro, the value of `BIGGEST_ALIGNMENT' is used for
-+   aligning trampolines.  */
-+#define TRAMPOLINE_ALIGNMENT 32
-+
-+/* A C statement to initialize the variable parts of a trampoline.  ADDR is an
-+   RTX for the address of the trampoline; FNADDR is an RTX for the address of
-+   the nested function; STATIC_CHAIN is an RTX for the static chain value that
-+   should be passed to the function when it is called.  */
-+#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT)                     \
-+{                                                                     \
-+  emit_move_insn (gen_rtx_MEM (SImode, plus_constant ((TRAMP), 0x14)),        \
-+               (CXT));                                                \
-+  emit_move_insn (gen_rtx_MEM (SImode, plus_constant ((TRAMP), 0x18)),        \
-+               (FNADDR));                                             \
-+}
-+
-+/* Ubicom32 supports pre and post increment/decrement addressing.  */
-+#define HAVE_POST_INCREMENT 1
-+#define HAVE_PRE_INCREMENT 1
-+#define HAVE_POST_DECREMENT 1
-+#define HAVE_PRE_DECREMENT 1
-+
-+/* Ubicom32 supports pre and post address side-effects with constants
-+   other than the size of the memory operand.  */
-+#define HAVE_PRE_MODIFY_DISP 1
-+#define HAVE_POST_MODIFY_DISP 1
-+
-+/* A C expression that is 1 if the RTX X is a constant which is a valid
-+   address.  On most machines, this can be defined as `CONSTANT_P (X)',
-+   but a few machines are more restrictive in which constant addresses
-+   are supported.
-+
-+   `CONSTANT_P' accepts integer-values expressions whose values are not
-+   explicitly known, such as `symbol_ref', `label_ref', and `high'
-+   expressions and `const' arithmetic expressions, in addition to
-+   `const_int' and `const_double' expressions.  */
-+#define CONSTANT_ADDRESS_P(X)                                         \
-+  (GET_CODE (X) == LABEL_REF                                          \
-+   || (GET_CODE (X) == CONST                                          \
-+       && GET_CODE (XEXP (X, 0)) == PLUS                              \
-+       && GET_CODE (XEXP (XEXP (X, 0), 0)) == LABEL_REF))
-+
-+/* Ubicom32 supports a maximum of 2 registers in a valid memory address.
-+   One is always an address register while a second, optional, one may be a
-+   data register.  */
-+#define MAX_REGS_PER_ADDRESS 2
-+
-+/* A C compound statement with a conditional `goto LABEL;' executed if X (an
-+   RTX) is a legitimate memory address on the target machine for a memory
-+   operand of mode MODE.
-+
-+   It usually pays to define several simpler macros to serve as subroutines for
-+   this one.  Otherwise it may be too complicated to understand.
-+
-+   This macro must exist in two variants: a strict variant and a non-strict
-+   one.  The strict variant is used in the reload pass.  It must be defined so
-+   that any pseudo-register that has not been allocated a hard register is
-+   considered a memory reference.  In contexts where some kind of register is
-+   required, a pseudo-register with no hard register must be rejected.
-+
-+   The non-strict variant is used in other passes.  It must be defined to
-+   accept all pseudo-registers in every context where some kind of register is
-+   required.
-+
-+   Compiler source files that want to use the strict variant of this macro
-+   define the macro `REG_OK_STRICT'.  You should use an `#ifdef REG_OK_STRICT'
-+   conditional to define the strict variant in that case and the non-strict
-+   variant otherwise.
-+
-+   Subroutines to check for acceptable registers for various purposes (one for
-+   base registers, one for index registers, and so on) are typically among the
-+   subroutines used to define `GO_IF_LEGITIMATE_ADDRESS'.  Then only these
-+   subroutine macros need have two variants; the higher levels of macros may be
-+   the same whether strict or not.
-+
-+   Normally, constant addresses which are the sum of a `symbol_ref' and an
-+   integer are stored inside a `const' RTX to mark them as constant.
-+   Therefore, there is no need to recognize such sums specifically as
-+   legitimate addresses.  Normally you would simply recognize any `const' as
-+   legitimate.
-+
-+   Usually `PRINT_OPERAND_ADDRESS' is not prepared to handle constant sums that
-+   are not marked with `const'.  It assumes that a naked `plus' indicates
-+   indexing.  If so, then you *must* reject such naked constant sums as
-+   illegitimate addresses, so that none of them will be given to
-+   `PRINT_OPERAND_ADDRESS'.
-+
-+   On some machines, whether a symbolic address is legitimate depends on the
-+   section that the address refers to.  On these machines, define the macro
-+   `ENCODE_SECTION_INFO' to store the information into the `symbol_ref', and
-+   then check for it here.  When you see a `const', you will have to look
-+   inside it to find the `symbol_ref' in order to determine the section.
-+
-+   The best way to modify the name string is by adding text to the beginning,
-+   with suitable punctuation to prevent any ambiguity.  Allocate the new name
-+   in `saveable_obstack'.  You will have to modify `ASM_OUTPUT_LABELREF' to
-+   remove and decode the added text and output the name accordingly, and define
-+   `STRIP_NAME_ENCODING' to access the original name string.
-+
-+   You can check the information stored here into the `symbol_ref' in the
-+   definitions of the macros `GO_IF_LEGITIMATE_ADDRESS' and
-+   `PRINT_OPERAND_ADDRESS'.  */
-+/* On the ubicom32, the value in the address register must be
-+   in the same memory space/segment as the effective address.
-+
-+   This is problematical for reload since it does not understand
-+   that base+index != index+base in a memory reference.  */
-+
-+#ifdef REG_OK_STRICT
-+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)       \
-+  if (ubicom32_legitimate_address_p (MODE, X, 1)) goto ADDR;
-+#else
-+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)       \
-+  if (ubicom32_legitimate_address_p (MODE, X, 0)) goto ADDR;
-+#endif
-+
-+/* Try machine-dependent ways of modifying an illegitimate address
-+   to be legitimate.  If we find one, return the new, valid address.
-+   This macro is used in only one place: `memory_address' in explow.c.
-+
-+   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 and WIN are passed so that this macro can use
-+   GO_IF_LEGITIMATE_ADDRESS.
-+
-+   It is always safe for this macro to do nothing.  It exists to recognize
-+   opportunities to optimize the output.
-+
-+   On RS/6000, first check for the sum of a register with a constant
-+   integer that is out of range.  If so, generate code to add the
-+   constant with the low-order 16 bits masked to the register and force
-+   this result into another register (this can be done with `cau').
-+   Then generate an address of REG+(CONST&0xffff), allowing for the
-+   possibility of bit 16 being a one.
-+
-+   Then check for the sum of a register and something not constant, try to
-+   load the other things into a register and return the sum.  */
-+
-+#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)                                \
-+{                                                                     \
-+   rtx result = ubicom32_legitimize_address ((X), (OLDX), (MODE));    \
-+   if (result != NULL_RTX)                                            \
-+     {                                                                        \
-+       (X) = result;                                                  \
-+       goto WIN;                                                      \
-+     }                                                                        \
-+}
-+
-+/* Try a machine-dependent way of reloading an illegitimate address
-+   operand.  If we find one, push the reload and jump to WIN.  This
-+   macro is used in only one place: `find_reloads_address' in reload.c.  */
-+#define LEGITIMIZE_RELOAD_ADDRESS(AD, MODE, OPNUM, TYPE, IND, WIN)    \
-+{                                                                     \
-+  rtx new_rtx = ubicom32_legitimize_reload_address ((AD), (MODE), (OPNUM), (int)(TYPE));      \
-+  if (new_rtx)                                                                \
-+    {                                                                 \
-+      (AD) = new_rtx;                                                 \
-+      goto WIN;                                                               \
-+    }                                                                 \
-+}
-+
-+/* A C statement or compound statement with a conditional `goto LABEL;'
-+   executed if memory address X (an RTX) can have different meanings depending
-+   on the machine mode of the memory reference it is used for or if the address
-+   is valid for some modes but not others.
-+
-+   Autoincrement and autodecrement addresses typically have mode-dependent
-+   effects because the amount of the increment or decrement is the size of the
-+   operand being addressed.  Some machines have other mode-dependent addresses.
-+   Many RISC machines have no mode-dependent addresses.
-+
-+   You may assume that ADDR is a valid address for the machine.  */
-+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)     \
-+  if (ubicom32_mode_dependent_address_p (ADDR))               \
-+    goto LABEL;
-+
-+/* A C expression that is nonzero if X is a legitimate constant for an
-+   immediate operand on the target machine.  You can assume that X
-+   satisfies `CONSTANT_P', so you need not check this.  In fact, `1' is
-+   a suitable definition for this macro on machines where anything
-+   `CONSTANT_P' is valid.  */
-+#define LEGITIMATE_CONSTANT_P(X) \
-+  ubicom32_legitimate_constant_p ((X))
-+
-+/* Moves between registers are pretty-much single instructions for
-+   Ubicom32.  We make this the default "2" that gcc likes.  */
-+#define REGISTER_MOVE_COST(MODE, FROM, TO) 2
-+
-+/* This is a little bit of magic from the S390 port that wins 2% on code
-+   size when building the Linux kernel!  Unfortunately while it wins on
-+   that size the user-space apps built using FD-PIC don't improve and the
-+   performance is lower because we put more pressure on the caches.  We may
-+   want this back on some future CPU that has higher cache performance.  */
-+/* #define IRA_HARD_REGNO_ADD_COST_MULTIPLIER(regno) 0.5 */
-+
-+/* Moves between registers and memory are more expensive than between
-+   registers because we have caches and write buffers that slow things
-+   down!  */
-+#define MEMORY_MOVE_COST(MODE, CLASS, IN) 2
-+
-+/* A fall-through branch is very low cost but anything that changes the PC
-+   incurs a major pipeline hazard.  We don't make the full extent of this
-+   hazard visible because we hope that multiple threads will absorb much
-+   of the cost and so we don't want a jump being replaced with, say, 7
-+   instructions.  */
-+#define BRANCH_COST(SPEED_P, PREDICTABLE_P) \
-+  ((PREDICTABLE_P) ? 1 : 3)
-+
-+/* Define this macro as a C expression which is nonzero if accessing less than
-+   a word of memory (i.e. a `char' or a `short') is no faster than accessing a
-+   word of memory, i.e., if such access require more than one instruction or if
-+   there is no difference in cost between byte and (aligned) word loads.
-+
-+   When this macro is not defined, the compiler will access a field by finding
-+   the smallest containing object; when it is defined, a fullword load will be
-+   used if alignment permits.  Unless bytes accesses are faster than word
-+   accesses, using word accesses is preferable since it may eliminate
-+   subsequent memory access if subsequent accesses occur to other fields in the
-+   same word of the structure, but to different bytes.  */
-+#define SLOW_BYTE_ACCESS 0
-+
-+/* The number of scalar move insns which should be generated instead of a
-+   string move insn or a library call.  Increasing the value will always make
-+   code faster, but eventually incurs high cost in increased code size.
-+
-+   If you don't define this, a reasonable default is used.  */
-+/* According to expr.c, a value of around 6 should minimize code size.  */
-+#define MOVE_RATIO(SPEED) 6
-+
-+/* We're much better off calling a constant function address with the
-+   Ubicom32 architecture because we have an opcode for doing so.  Don't
-+   let the compiler extract function addresses as common subexpressions
-+   into an address register.  */
-+#define NO_FUNCTION_CSE
-+
-+#define SELECT_CC_MODE(OP, X, Y) ubicom32_select_cc_mode (OP, X, Y)
-+
-+#define REVERSIBLE_CC_MODE(MODE) 1
-+
-+/* Canonicalize a comparison from one we don't have to one we do have.  */
-+#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
-+  ubicom32_canonicalize_comparison (&(CODE), &(OP0), &(OP1))
-+
-+/* Dividing the output into sections.  */
-+
-+/* A C expression whose value is a string containing the assembler operation
-+   that should precede instructions and read-only data.  Normally `".text"' is
-+   right.  */
-+#define TEXT_SECTION_ASM_OP "\t.section .text"
-+
-+/* A C expression whose value is a string containing the assembler operation to
-+   identify the following data as writable initialized data.  Normally
-+   `".data"' is right.  */
-+#define DATA_SECTION_ASM_OP "\t.section .data"
-+
-+
-+/* If defined, a C expression whose value is a string containing the
-+   assembler operation to identify the following data as
-+   uninitialized global data.  If not defined, and neither
-+   `ASM_OUTPUT_BSS' nor `ASM_OUTPUT_ALIGNED_BSS' are defined,
-+   uninitialized global data will be output in the data section if
-+   `-fno-common' is passed, otherwise `ASM_OUTPUT_COMMON' will be
-+   used.  */
-+#define BSS_SECTION_ASM_OP "\t.section .bss"
-+
-+/* This is how we tell the assembler that a symbol is weak.  */
-+
-+#define ASM_WEAKEN_LABEL(FILE, NAME)  \
-+  do                                  \
-+    {                                 \
-+      fputs ("\t.weak\t", (FILE));    \
-+      assemble_name ((FILE), (NAME)); \
-+      fputc ('\n', (FILE));           \
-+    }                                 \
-+  while (0)
-+
-+/* The Overall Framework of an Assembler File.  */
-+
-+#undef SET_ASM_OP
-+#define SET_ASM_OP "\t.set\t"
-+
-+/* A C string constant describing how to begin a comment in the target
-+   assembler language.  The compiler assumes that the comment will end at the
-+   end of the line.  */
-+#define ASM_COMMENT_START ";"
-+
-+/* A C string constant for text to be output before each `asm' statement or
-+   group of consecutive ones.  Normally this is `"#APP"', which is a comment
-+   that has no effect on most assemblers but tells the GNU assembler that it
-+   must check the lines that follow for all valid assembler constructs.  */
-+#define ASM_APP_ON "#APP\n"
-+
-+/* A C string constant for text to be output after each `asm' statement or
-+   group of consecutive ones.  Normally this is `"#NO_APP"', which tells the
-+   GNU assembler to resume making the time-saving assumptions that are valid
-+   for ordinary compiler output.  */
-+#define ASM_APP_OFF "#NO_APP\n"
-+
-+/* Like `ASM_OUTPUT_BSS' except takes the required alignment as a separate,
-+   explicit argument.  If you define this macro, it is used in place of
-+   `ASM_OUTPUT_BSS', and gives you more flexibility in handling the required
-+   alignment of the variable.  The alignment is specified as the number of
-+   bits.
-+
-+   Try to use function `asm_output_aligned_bss' defined in file `varasm.c' when
-+   defining this macro.  */
-+#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
-+  asm_output_aligned_bss ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
-+
-+/* A C expression to assign to OUTVAR (which is a variable of type `char *') a
-+   newly allocated string made from the string NAME and the number NUMBER, with
-+   some suitable punctuation added.  Use `alloca' to get space for the string.
-+
-+   The string will be used as an argument to `ASM_OUTPUT_LABELREF' to produce
-+   an assembler label for an internal static variable whose name is NAME.
-+   Therefore, the string must be such as to result in valid assembler code.
-+   The argument NUMBER is different each time this macro is executed; it
-+   prevents conflicts between similarly-named internal static variables in
-+   different scopes.
-+
-+   Ideally this string should not be a valid C identifier, to prevent any
-+   conflict with the user's own symbols.  Most assemblers allow periods or
-+   percent signs in assembler symbols; putting at least one of these between
-+   the name and the number will suffice.  */
-+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO)        \
-+  ((OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
-+   sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO)))
-+
-+#define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM)      \
-+  sprintf (STRING, "*.%s%ld", PREFIX, (long)(NUM))
-+/* A C statement to store into the string STRING a label whose name
-+   is made from the string PREFIX and the number NUM.
-+
-+   This string, when output subsequently by `assemble_name', should
-+   produce the output that `(*targetm.asm_out.internal_label)' would produce
-+   with the same PREFIX and NUM.
-+
-+   If the string begins with `*', then `assemble_name' will output
-+   the rest of the string unchanged.  It is often convenient for
-+   `ASM_GENERATE_INTERNAL_LABEL' to use `*' in this way.  If the
-+   string doesn't start with `*', then `ASM_OUTPUT_LABELREF' gets to
-+   output the string, and may change it.  (Of course,
-+   `ASM_OUTPUT_LABELREF' is also part of your machine description, so
-+   you should know what it does on your machine.)  */
-+
-+/* This says how to output assembler code to declare an
-+   uninitialized external linkage data object.  Under SVR4,
-+   the linker seems to want the alignment of data objects
-+   to depend on their types.  We do exactly that here.  */
-+
-+#define COMMON_ASM_OP "\t.comm\t"
-+
-+#undef  ASM_OUTPUT_COMMON
-+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED)          \
-+  do                                                          \
-+    {                                                         \
-+      fprintf ((FILE), "%s", COMMON_ASM_OP);                  \
-+      assemble_name ((FILE), (NAME));                         \
-+      fprintf ((FILE), ", %u\n", (SIZE));                     \
-+    }                                                         \
-+  while (0)
-+
-+/* This says how to output assembler code to declare an
-+   uninitialized internal linkage data object.  Under SVR4,
-+   the linker seems to want the alignment of data objects
-+   to depend on their types.  We do exactly that here.  */
-+#define LOCAL_ASM_OP  "\t.lcomm\t"
-+
-+#undef  ASM_OUTPUT_LOCAL
-+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)           \
-+  do                                                          \
-+    {                                                         \
-+      fprintf ((FILE), "%s", LOCAL_ASM_OP);                   \
-+      assemble_name ((FILE), (NAME));                         \
-+      fprintf ((FILE), ", %u\n", (SIZE));                     \
-+    }                                                         \
-+  while (0)
-+
-+/* Globalizing directive for a label.  */
-+#define GLOBAL_ASM_OP ".global\t"
-+
-+/* Output the operand of an instruction.  */
-+#define PRINT_OPERAND(FILE, X, CODE) \
-+  ubicom32_print_operand(FILE, X, CODE)
-+
-+/* Output the address of an operand.  */
-+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
-+  ubicom32_print_operand_address (FILE, ADDR)
-+
-+/* A C expression to output to STREAM some assembler code which will push hard
-+   register number REGNO onto the stack.  The code need not be optimal, since
-+   this macro is used only when profiling.  */
-+#define ASM_OUTPUT_REG_PUSH(FILE, REGNO)
-+
-+/* A C expression to output to STREAM some assembler code which will pop hard
-+   register number REGNO off of the stack.  The code need not be optimal, since
-+   this macro is used only when profiling.  */
-+#define ASM_OUTPUT_REG_POP(FILE, REGNO)
-+
-+/* This macro should be provided on machines where the addresses in a dispatch
-+   table are relative to the table's own address.
-+
-+   The definition should be a C statement to output to the stdio stream STREAM
-+   an assembler pseudo-instruction to generate a difference between two labels.
-+   VALUE and REL are the numbers of two internal labels.  The definitions of
-+   these labels are output using `ASM_OUTPUT_INTERNAL_LABEL', and they must be
-+   printed in the same way here.  For example,
-+
-+      fprintf (STREAM, "\t.word L%d-L%d\n", VALUE, REL)  */
-+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
-+  fprintf (FILE, "\t%s .L%d-.L%d\n", ".long", VALUE, REL)
-+
-+/* This macro should be provided on machines where the addresses in a dispatch
-+   table are absolute.
-+
-+   The definition should be a C statement to output to the stdio stream STREAM
-+   an assembler pseudo-instruction to generate a reference to a label.  VALUE
-+   is the number of an internal label whose definition is output using
-+   `ASM_OUTPUT_INTERNAL_LABEL'.  For example,
-+
-+      fprintf (STREAM, "\t.word L%d\n", VALUE)  */
-+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
-+  fprintf (STREAM, "\t.word .L%d\n", VALUE)
-+
-+/* Switch into a generic section.  */
-+#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
-+
-+/* Assembler Commands for Alignment.  */
-+
-+#define ASM_OUTPUT_SKIP(STREAM, N) fprintf (STREAM, "\t.skip %d,0\n", N)
-+/* A C statement to output to the stdio stream STREAM an assembler
-+   instruction to advance the location counter by NBYTES bytes.
-+   Those bytes should be zero when loaded.  NBYTES will be a C
-+   expression of type `int'.  */
-+
-+/* A C statement to output to the stdio stream STREAM an assembler command to
-+   advance the location counter to a multiple of 2 to the POWER bytes.  POWER
-+   will be a C expression of type `int'.  */
-+#define ASM_OUTPUT_ALIGN(FILE, LOG)   \
-+  if ((LOG) != 0)                     \
-+    fprintf (FILE, "\t.align %d\n", (LOG))
-+
-+/* A C expression that returns the DBX register number for the compiler
-+   register number REGNO.  In simple cases, the value of this expression may be
-+   REGNO itself.  But sometimes there are some registers that the compiler
-+   knows about and DBX does not, or vice versa.  In such cases, some register
-+   may need to have one number in the compiler and another for DBX.
-+
-+   If two registers have consecutive numbers inside GNU CC, and they can be
-+   used as a pair to hold a multiword value, then they *must* have consecutive
-+   numbers after renumbering with `DBX_REGISTER_NUMBER'.  Otherwise, debuggers
-+   will be unable to access such a pair, because they expect register pairs to
-+   be consecutive in their own numbering scheme.
-+
-+   If you find yourself defining `DBX_REGISTER_NUMBER' in way that does not
-+   preserve register pairs, then what you must do instead is redefine the
-+   actual register numbering scheme.
-+
-+   This declaration is required.  */
-+#define DBX_REGISTER_NUMBER(REGNO) REGNO
-+
-+/* A C expression that returns the integer offset value for an automatic
-+   variable having address X (an RTL expression).  The default computation
-+   assumes that X is based on the frame-pointer and gives the offset from the
-+   frame-pointer.  This is required for targets that produce debugging output
-+   for DBX or COFF-style debugging output for SDB and allow the frame-pointer
-+   to be eliminated when the `-g' options is used.  */
-+#define DEBUGGER_AUTO_OFFSET(X)                                               \
-+  ((GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)                  \
-+    + (frame_pointer_needed                                           \
-+       ? 0 : -initial_elimination_offset (FRAME_POINTER_REGNUM,               \
-+                                        STACK_POINTER_REGNUM)))
-+
-+/* A C expression that returns the integer offset value for an argument having
-+   address X (an RTL expression).  The nominal offset is OFFSET.  */
-+#define DEBUGGER_ARG_OFFSET(OFFSET, X)                                        \
-+  ((GET_CODE (X) == PLUS ? OFFSET : 0)                                        \
-+    + (frame_pointer_needed                                           \
-+       ? 0 : -initial_elimination_offset (ARG_POINTER_REGNUM,         \
-+                                        STACK_POINTER_REGNUM)))
-+
-+/* A C expression that returns the type of debugging output GNU CC produces
-+   when the user specifies `-g' or `-ggdb'.  Define this if you have arranged
-+   for GNU CC to support more than one format of debugging output.  Currently,
-+   the allowable values are `DBX_DEBUG', `SDB_DEBUG', `DWARF_DEBUG',
-+   `DWARF2_DEBUG', and `XCOFF_DEBUG'.
-+
-+   The value of this macro only affects the default debugging output; the user
-+   can always get a specific type of output by using `-gstabs', `-gcoff',
-+   `-gdwarf-1', `-gdwarf-2', or `-gxcoff'.
-+
-+   Defined in svr4.h.
-+*/
-+#undef PREFERRED_DEBUGGING_TYPE
-+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-+
-+/* Define this macro if GNU CC should produce dwarf version 2 format debugging
-+   output in response to the `-g' option.
-+
-+   To support optional call frame debugging information, you must also define
-+   `INCOMING_RETURN_ADDR_RTX' and either set `RTX_FRAME_RELATED_P' on the
-+   prologue insns if you use RTL for the prologue, or call `dwarf2out_def_cfa'
-+   and `dwarf2out_reg_save' as appropriate from `FUNCTION_PROLOGUE' if you
-+   don't.
-+
-+   Defined in svr4.h.  */
-+
-+#define DWARF2_DEBUGGING_INFO 1
-+/*#define DWARF2_UNWIND_INFO 1*/
-+#define DWARF2_UNWIND_INFO 0
-+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, LINK_REGNO)
-+#define INCOMING_FRAME_SP_OFFSET 0
-+#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LINK_REGNO)
-+#define EH_RETURN_FIRST 9
-+#define EH_RETURN_DATA_REGNO(N) ((N) < 2 ? (N) + EH_RETURN_FIRST : INVALID_REGNUM)
-+
-+/* The EH_RETURN_STACKADJ_RTX macro returns RTL which describes the
-+   location used to store the amount to ajdust the stack.  This is
-+   usually a registers that is available from end of the function's body
-+   to the end of the epilogue. Thus, this cannot be a register used as a
-+   temporary by the epilogue.
-+
-+   This must be an integer register.  */
-+#define EH_RETURN_STACKADJ_REGNO      11
-+#define EH_RETURN_STACKADJ_RTX                \
-+      gen_rtx_REG (Pmode, EH_RETURN_STACKADJ_REGNO)
-+
-+/* The EH_RETURN_HANDLER_RTX macro returns RTL which describes the
-+   location used to store the address the processor should jump to
-+   catch exception.  This is usually a registers that is available from
-+   end of the function's body to the end of the epilogue. Thus, this
-+   cannot be a register used as a temporary by the epilogue.
-+
-+   This must be an address register.  */
-+#define EH_RETURN_HANDLER_REGNO               18
-+#define EH_RETURN_HANDLER_RTX         \
-+      gen_rtx_REG (Pmode, EH_RETURN_HANDLER_REGNO)
-+
-+/* #define DWARF2_DEBUGGING_INFO */
-+
-+/* Define this macro if GNU CC should produce dwarf version 2-style
-+   line numbers.  This usually requires extending the assembler to
-+   support them, and #defining DWARF2_LINE_MIN_INSN_LENGTH in the
-+   assembler configuration header files.  */
-+/* #define DWARF2_ASM_LINE_DEBUG_INFO 1 */
-+
-+
-+/* An alias for a machine mode name.  This is the machine mode that elements
-+   of a jump-table have.  */
-+#define CASE_VECTOR_MODE Pmode
-+
-+/* Smallest number of different values for which it is best to use a
-+   jump-table instead of a tree of conditional branches.  For most Ubicom32
-+   targets this is quite small, but for the v1 architecture implementations
-+   we had very little data memory and so heavily prefer the tree approach
-+   rather than the jump tables.  */
-+#define CASE_VALUES_THRESHOLD ubicom32_case_values_threshold
-+
-+/* Register operations within the Ubicom32 architecture always operate on
-+   the whole register word and not just the sub-bits required for the opcode
-+   mode size.  */
-+#define WORD_REGISTER_OPERATIONS
-+
-+/* The maximum number of bytes that a single instruction can move quickly from
-+   memory to memory.  */
-+#define MOVE_MAX 4
-+
-+/* A C expression that is nonzero if on this machine the number of bits
-+   actually used for the count of a shift operation is equal to the number of
-+   bits needed to represent the size of the object being shifted.  When this
-+   macro is non-zero, the compiler will assume that it is safe to omit a
-+   sign-extend, zero-extend, and certain bitwise `and' instructions that
-+   truncates the count of a shift operation.  On machines that have
-+   instructions that act on bitfields at variable positions, which may include
-+   `bit test' instructions, a nonzero `SHIFT_COUNT_TRUNCATED' also enables
-+   deletion of truncations of the values that serve as arguments to bitfield
-+   instructions.
-+
-+   If both types of instructions truncate the count (for shifts) and position
-+   (for bitfield operations), or if no variable-position bitfield instructions
-+   exist, you should define this macro.
-+
-+   However, on some machines, such as the 80386 and the 680x0, truncation only
-+   applies to shift operations and not the (real or pretended) bitfield
-+   operations.  Define `SHIFT_COUNT_TRUNCATED' to be zero on such machines.
-+   Instead, add patterns to the `md' file that include the implied truncation
-+   of the shift instructions.
-+
-+   You need not define this macro if it would always have the value of zero.  */
-+#define SHIFT_COUNT_TRUNCATED 1
-+
-+/* A C expression which is nonzero if on this machine it is safe to "convert"
-+   an integer of INPREC bits to one of OUTPREC bits (where OUTPREC is smaller
-+   than INPREC) by merely operating on it as if it had only OUTPREC bits.
-+
-+   On many machines, this expression can be 1.
-+
-+   When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for modes for
-+   which `MODES_TIEABLE_P' is 0, suboptimal code can result.  If this is the
-+   case, making `TRULY_NOOP_TRUNCATION' return 0 in such cases may improve
-+   things.  */
-+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-+
-+/* A C string constant that tells the GNU CC driver program options to pass
-+   to the assembler.  It can also specify how to translate options you give
-+   to GNU CC into options for GNU CC to pass to the assembler.  See the
-+   file `sun3.h' for an example of this.
-+
-+   Defined in svr4.h.  */
-+#undef ASM_SPEC
-+#define ASM_SPEC \
-+  "%{march=*:-m%*} %{!march=*:-mubicom32v4} %{mfdpic:-mfdpic}"
-+
-+#define LINK_SPEC "\
-+%{h*} %{v:-V} \
-+%{b} \
-+%{mfdpic:-melf32ubicom32fdpic -z text} \
-+%{static:-dn -Bstatic} \
-+%{shared:-G -Bdynamic} \
-+%{symbolic:-Bsymbolic} \
-+%{G*} \
-+%{YP,*} \
-+%{Qy:} %{!Qn:-Qy}"
-+
-+#undef STARTFILE_SPEC
-+#undef ENDFILE_SPEC
-+
-+/* The svr4.h LIB_SPEC with -leval and --*group tacked on */
-+
-+#undef  LIB_SPEC
-+#define LIB_SPEC "%{!shared:%{!symbolic:--start-group -lc -leval -lgcc --end-group}}"
-+
-+#undef HAVE_GAS_SHF_MERGE
-+#define HAVE_GAS_SHF_MERGE 0
-+
-+#define HANDLE_SYSV_PRAGMA 1
-+#undef HANDLE_PRAGMA_PACK
-+
-+typedef void (*ubicom32_func_ptr) (void);
-+
-+/* Define builtins for selected special-purpose instructions. */
-+enum ubicom32_builtins
-+{
-+  UBICOM32_BUILTIN_UBICOM32_SWAPB_2,
-+  UBICOM32_BUILTIN_UBICOM32_SWAPB_4
-+};
-+
-+extern rtx ubicom32_compare_op0;
-+extern rtx ubicom32_compare_op1;
-+
-+#define TYPE_ASM_OP   "\t.type\t"
-+#define TYPE_OPERAND_FMT      "@%s"
-+
-+#ifndef ASM_DECLARE_RESULT
-+#define ASM_DECLARE_RESULT(FILE, RESULT)
-+#endif
-+
-+/* These macros generate the special .type and .size directives which
-+   are used to set the corresponding fields of the linker symbol table
-+   entries in an ELF object file under SVR4.  These macros also output
-+   the starting labels for the relevant functions/objects.  */
-+
-+/* Write the extra assembler code needed to declare a function properly.
-+   Some svr4 assemblers need to also have something extra said about the
-+   function's return value.  We allow for that here.  */
-+
-+#ifndef ASM_DECLARE_FUNCTION_NAME
-+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL)           \
-+  do                                                          \
-+    {                                                         \
-+      ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function");     \
-+      ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL));          \
-+      ASM_OUTPUT_LABEL (FILE, NAME);                          \
-+    }                                                         \
-+  while (0)
-+#endif
---- /dev/null
-+++ b/gcc/config/ubicom32/ubicom32.md
-@@ -0,0 +1,3753 @@
-+; GCC machine description for Ubicom32
-+;
-+; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software
-+; Foundation, Inc.
-+; Contributed by Ubicom, Inc.
-+;
-+; This file is part of GCC.
-+;
-+; GCC is free software; you can redistribute it and/or modify
-+; it under the terms of the GNU General Public License as published by
-+; the Free Software Foundation; either version 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_constants
-+  [(AUX_DATA_REGNO 15)
-+   (LINK_REGNO     21)
-+   (SP_REGNO       23)
-+   (ACC0_HI_REGNO  24)
-+   (ACC1_HI_REGNO  26)
-+   (CC_REGNO       30)])
-+
-+(define_constants
-+  [(UNSPEC_FDPIC_GOT 0)
-+   (UNSPEC_FDPIC_GOT_FUNCDESC 1)])
-+
-+(define_constants
-+  [(UNSPEC_VOLATILE_LOAD_FDPIC_FUNCDESC 0)])
-+
-+;; Types of instructions (for scheduling purposes).
-+
-+(define_attr "type" "mul,addr,other"
-+  (const_string "other"))
-+
-+; Define instruction scheduling characteristics.  We can only issue
-+; one instruction per clock so we don't need to define CPU units.
-+;
-+(define_automaton "ubicom32")
-+
-+(define_cpu_unit "i_pipeline" "ubicom32");
-+
-+; We have a 4 cycle hazard associated with address calculations which
-+; seems rather tricky to avoid so we go with a defensive assumption
-+; that almost anything can be used to generate addresses.
-+;
-+;(define_insn_reservation "ubicom32_other" 4
-+;                      (eq_attr "type" "other")
-+;                      "i_pipeline")
-+
-+; Some moves don't generate hazards.
-+;
-+;(define_insn_reservation "ubicom32_addr" 1
-+;                      (eq_attr "type" "addr")
-+;                      "i_pipeline")
-+
-+; We need 3 cycles between a multiply instruction and any use of the
-+; matching accumulator register(s).
-+;
-+(define_insn_reservation "ubicom32_mul" 4
-+                       (eq_attr "type" "mul")
-+                       "i_pipeline")
-+
-+(define_attr "length" ""
-+  (const_int 4))
-+
-+(include "predicates.md")
-+(include "constraints.md")
-+
-+; 8-bit move with no change to the flags reg.
-+;
-+(define_insn "movqi"
-+  [(set (match_operand:QI 0 "nonimmediate_operand" "=rm")
-+      (match_operand:QI 1 "ubicom32_move_operand"  "g"))]
-+  ""
-+  "move.1\\t%0, %1")
-+
-+; Combiner-generated 8-bit move with the zero flag set accordingly.
-+;
-+(define_insn "movqi_ccszn"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:QI 0 "nonimmediate_operand" "rm")
-+               (const_int 0)))
-+   (set (match_operand:QI 1 "nonimmediate_operand"       "=rm")
-+      (match_dup 0))]
-+  "ubicom32_match_cc_mode(insn, CCSZNmode)"
-+  "ext.1\\t%1, %0")
-+
-+; Combine isn't very good at merging some types of operations so we
-+; have to make do with a peephole.  It's not as effective but it's better
-+; than doing nothing.
-+;
-+(define_peephole2
-+  [(set (match_operand:QI 0 "nonimmediate_operand" "")
-+      (match_operand:QI 1 "nonimmediate_operand" ""))
-+   (set (match_operand 2 "ubicom32_cc_register_operand" "")
-+      (match_operator 3 "ubicom32_compare_operator"
-+        [(match_dup 0)
-+         (const_int 0)]))]
-+  "(GET_MODE (operands[2]) == CCSZNmode
-+    || GET_MODE (operands[2]) == CCSZmode)"
-+  [(parallel
-+     [(set (match_dup 2)
-+         (match_op_dup 3
-+           [(match_dup 1)
-+            (const_int 0)]))
-+      (set (match_dup 0)
-+         (match_dup 1))])]
-+   "")
-+
-+; Combine isn't very good at merging some types of operations so we
-+; have to make do with a peephole.  It's not as effective but it's better
-+; than doing nothing.
-+;
-+(define_peephole2
-+  [(set (match_operand:QI 0 "nonimmediate_operand" "")
-+      (match_operand:QI 1 "nonimmediate_operand" ""))
-+   (set (match_operand 2 "ubicom32_cc_register_operand" "")
-+      (match_operator 3 "ubicom32_compare_operator"
-+        [(match_dup 1)
-+         (const_int 0)]))]
-+  "(GET_MODE (operands[2]) == CCSZNmode
-+    || GET_MODE (operands[2]) == CCSZmode)"
-+  [(parallel
-+     [(set (match_dup 2)
-+         (match_op_dup 3
-+           [(match_dup 1)
-+            (const_int 0)]))
-+      (set (match_dup 0)
-+         (match_dup 1))])]
-+   "")
-+
-+; 16-bit move with no change to the flags reg.
-+;
-+(define_insn "movhi"
-+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
-+      (match_operand:HI 1 "ubicom32_move_operand"  "g"))]
-+  ""
-+  "*
-+   {
-+     if (CONST_INT_P (operands[1]))
-+       return \"movei\\t%0, %1\";
-+
-+     return \"move.2\\t%0, %1\";
-+   }")
-+
-+; Combiner-generated 16-bit move with the zero flag set accordingly.
-+;
-+(define_insn "movhi_ccszn"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:HI 0 "nonimmediate_operand" "rm")
-+               (const_int 0)))
-+   (set (match_operand:HI 1 "nonimmediate_operand"       "=rm")
-+      (match_dup 0))]
-+  "ubicom32_match_cc_mode(insn, CCSZNmode)"
-+  "ext.2\\t%1, %0")
-+
-+; Combine isn't very good at merging some types of operations so we
-+; have to make do with a peephole.  It's not as effective but it's better
-+; than doing nothing.
-+;
-+(define_peephole2
-+  [(set (match_operand:HI 0 "nonimmediate_operand" "")
-+      (match_operand:HI 1 "nonimmediate_operand" ""))
-+   (set (match_operand 2 "ubicom32_cc_register_operand" "")
-+      (match_operator 3 "ubicom32_compare_operator"
-+        [(match_dup 0)
-+         (const_int 0)]))]
-+  "(GET_MODE (operands[2]) == CCSZNmode
-+    || GET_MODE (operands[2]) == CCSZmode)"
-+  [(parallel
-+     [(set (match_dup 2)
-+         (match_op_dup 3
-+           [(match_dup 1)
-+            (const_int 0)]))
-+      (set (match_dup 0)
-+         (match_dup 1))])]
-+   "")
-+
-+; Combine isn't very good at merging some types of operations so we
-+; have to make do with a peephole.  It's not as effective but it's better
-+; than doing nothing.
-+;
-+(define_peephole2
-+  [(set (match_operand:HI 0 "nonimmediate_operand" "")
-+      (match_operand:HI 1 "nonimmediate_operand" ""))
-+   (set (match_operand 2 "ubicom32_cc_register_operand" "")
-+      (match_operator 3 "ubicom32_compare_operator"
-+        [(match_dup 1)
-+         (const_int 0)]))]
-+  "(GET_MODE (operands[2]) == CCSZNmode
-+    || GET_MODE (operands[2]) == CCSZmode)"
-+  [(parallel
-+     [(set (match_dup 2)
-+         (match_op_dup 3
-+           [(match_dup 1)
-+            (const_int 0)]))
-+      (set (match_dup 0)
-+         (match_dup 1))])]
-+   "")
-+
-+; 32-bit move with no change to the flags reg.
-+;
-+(define_expand "movsi"
-+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
-+      (match_operand:SI 1 "general_operand" ""))]
-+  ""
-+  "{
-+     /* Convert any complexities in operand 1 into something that can just
-+        fall into the default expander code.  */
-+     ubicom32_expand_movsi (operands);
-+   }")
-+
-+(define_insn "movsi_high"
-+  [(set (match_operand:SI 0 "ubicom32_address_register_operand"               "=a")
-+      (high:SI (match_operand:SI 1 "ubicom32_symbolic_address_operand" "s")))]
-+  ""
-+  "moveai\\t%0, #%%hi(%E1)")
-+
-+(define_insn "movsi_lo_sum"
-+  [(set (match_operand:SI 0 "nonimmediate_operand"                     "=rm")
-+      (lo_sum:SI (match_operand:SI 1 "ubicom32_address_register_operand" "a")
-+                   (match_operand:SI 2 "immediate_operand"               "s")))]
-+  ""
-+  "lea.1\\t%0, %%lo(%E2)(%1)")
-+
-+(define_insn "movsi_internal"
-+  [(set (match_operand:SI 0 "nonimmediate_operand"   "=rm")
-+      (match_operand:SI 1 "ubicom32_move_operand" "rmnY"))]
-+  ""
-+  "*
-+   {
-+     if (CONST_INT_P (operands[1]))
-+       {
-+         ubicom32_emit_move_const_int (operands[0], operands[1]);
-+         return \"\";
-+       }
-+
-+     if (GET_CODE (operands[1]) == CONST_DOUBLE)
-+       {
-+         HOST_WIDE_INT i = CONST_DOUBLE_LOW (operands[1]);
-+
-+         ubicom32_emit_move_const_int (operands[0], GEN_INT (i));
-+         return \"\";
-+       }
-+
-+     if (ubicom32_address_register_operand (operands[0], VOIDmode)
-+       && register_operand (operands[1], VOIDmode))
-+       {
-+       if (ubicom32_address_register_operand (operands[1], VOIDmode))
-+         return \"lea.1\\t%0, 0(%1)\";
-+
-+       /* Use movea here to utilize the hazard bypass in the >= v4 ISA.  */
-+         if (ubicom32_v4)
-+         return \"movea\\t%0, %1\";
-+
-+         return \"move.4\\t%0, %1\";
-+       }
-+
-+     return \"move.4\\t%0, %1\";
-+   }")
-+
-+; If we're not dependent on the state of the condition codes we can construct
-+; constants of value 2^n by using a bset.
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
-+      (match_operand:SI 1 "const_int_operand" ""))]
-+  "(exact_log2 (INTVAL (operands[1])) > 14
-+    && peep2_regno_dead_p (0, CC_REGNO))"
-+  [(parallel
-+     [(set (match_dup 0)
-+         (ior:SI (const_int 0)
-+                 (match_dup 1)))
-+      (clobber (reg:CC CC_REGNO))])]
-+  "")
-+
-+; If we're not dependent on the state of the condition codes we can construct
-+; constants of value ~(2^n) by using a bclr.
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
-+      (match_operand:SI 1 "const_int_operand" ""))]
-+  "(exact_log2 (~INTVAL (operands[1])) > 14
-+    && peep2_regno_dead_p (0, CC_REGNO))"
-+  [(parallel
-+     [(set (match_dup 0)
-+         (and:SI (const_int -1)
-+                 (match_dup 1)))
-+      (clobber (reg:CC CC_REGNO))])]
-+  "")
-+
-+; For 32-bit constants that have bits 0 through 24 and bit 31 set the same
-+; we can use swapb.4!
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
-+      (match_operand:SI 1 "const_int_operand" ""))]
-+  "(ubicom32_v4
-+    && (INTVAL (operands[1]) & 0xffffffff) != 0xffffffff
-+    && (INTVAL (operands[1]) & 0xffffffff) != 0
-+    && ((INTVAL (operands[1]) & 0x80ffffff) == 0
-+      || (INTVAL (operands[1]) & 0x80ffffff) == 0x80ffffff))"
-+  [(set (match_dup 0)
-+      (bswap:SI (match_dup 2)))]
-+  "{
-+     operands[2] = GEN_INT (INTVAL (operands[1]) >> 24);
-+   }")
-+
-+; If this is a write of a constant to memory look to see if we can usefully
-+; transform this into 2 smaller writes.
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "memory_operand" "")
-+      (match_operand:SI 1 "const_int_operand" ""))]
-+  "! satisfies_constraint_I (operands[1])
-+   && ubicom32_legitimate_address_p (HImode, plus_constant (XEXP (operands[0], 0), 2), 1)"
-+  [(set (match_dup 4) (match_dup 2))
-+   (set (match_dup 5) (match_dup 3))]
-+  "{
-+     rtx low_hword_addr;
-+
-+     operands[2] = gen_highpart_mode (HImode, SImode, operands[1]);
-+     operands[3] = gen_lowpart (HImode, operands[1]);
-+
-+     operands[4] = gen_rtx_MEM (HImode, XEXP (operands[0], 0));
-+     MEM_COPY_ATTRIBUTES (operands[4], operands[0]);
-+
-+     low_hword_addr = plus_constant (XEXP (operands[0], 0), 2);
-+     operands[5] = gen_rtx_MEM (HImode, low_hword_addr);
-+     MEM_COPY_ATTRIBUTES (operands[5], operands[0]);
-+   }")
-+
-+; If we're writing memory and we've not found a better way to do this then
-+; try loading into a D register and then copying to memory.  This will
-+; perform the fewest possible memory read/writes.
-+;
-+(define_peephole2
-+  [(match_scratch:SI 2 "d")
-+   (set (match_operand:SI 0 "memory_operand" "")
-+      (match_operand:SI 1 "const_int_operand" ""))]
-+  "! satisfies_constraint_I (operands[1])"
-+  [(set (match_dup 2) (match_dup 1))
-+   (set (match_dup 0) (match_dup 2))]
-+  "")
-+
-+; If we're not dependent on the state of the condition codes we can construct
-+; constants of value (2^n - 1) by using an lsr.4.
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "")
-+      (match_operand:SI 1 "const_int_operand" ""))]
-+  "(exact_log2 (INTVAL (operands[1]) + 1) > 14
-+    && peep2_regno_dead_p (0, CC_REGNO))"
-+  [(parallel
-+     [(set (match_dup 0)
-+         (lshiftrt:SI (const_int -1)
-+                      (match_dup 2)))
-+      (clobber (reg:CC CC_REGNO))])]
-+  "{
-+     operands[2] = GEN_INT (32 - exact_log2 (INTVAL (operands[1]) + 1));
-+   }")
-+
-+; If we're not dependent on the state of the condition codes we can construct
-+; constants of value (2^n - 1) by using an lsr.4.
-+;
-+(define_peephole2
-+  [(match_scratch:SI 2 "d")
-+   (set (match_operand:SI 0 "nonimmediate_operand" "")
-+      (match_operand:SI 1 "const_int_operand" ""))]
-+  "(exact_log2 (INTVAL (operands[1]) + 1) > 14
-+    && peep2_regno_dead_p (0, CC_REGNO))"
-+  [(parallel
-+     [(set (match_dup 2)
-+         (lshiftrt:SI (const_int -1)
-+                      (match_dup 3)))
-+      (clobber (reg:CC CC_REGNO))])
-+   (set (match_dup 0)
-+      (match_dup 2))]
-+  "{
-+     operands[3] = GEN_INT (32 - exact_log2 (INTVAL (operands[1]) + 1));
-+   }")
-+
-+; If we're not dependent on the state of the condition codes we can construct
-+; some other constants by using an lsl.4 to shift 7 bits left by some
-+; constant.
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "")
-+      (match_operand:SI 1 "const_int_operand" ""))]
-+  "(ubicom32_shiftable_const_int (INTVAL (operands[1]))
-+    && peep2_regno_dead_p (0, CC_REGNO))"
-+  [(parallel
-+     [(set (match_dup 0)
-+         (ashift:SI (match_dup 2)
-+                    (match_dup 3)))
-+      (clobber (reg:CC CC_REGNO))])]
-+  "{
-+     int shift = ubicom32_shiftable_const_int (INTVAL (operands[1]));
-+     operands[2] = GEN_INT (INTVAL (operands[1]) >> shift);
-+     operands[3] = GEN_INT (shift);
-+   }")
-+
-+; If we're not dependent on the state of the condition codes we can construct
-+; some other constants by using an lsl.4 to shift 7 bits left by some
-+; constant.
-+;
-+(define_peephole2
-+  [(match_scratch:SI 2 "d")
-+   (set (match_operand:SI 0 "nonimmediate_operand" "")
-+      (match_operand:SI 1 "const_int_operand" ""))]
-+  "(ubicom32_shiftable_const_int (INTVAL (operands[1]))
-+    && peep2_regno_dead_p (0, CC_REGNO))"
-+  [(parallel
-+     [(set (match_dup 2)
-+         (ashift:SI (match_dup 3)
-+                    (match_dup 4)))
-+      (clobber (reg:CC CC_REGNO))])
-+   (set (match_dup 0)
-+      (match_dup 2))]
-+  "{
-+     int shift = ubicom32_shiftable_const_int (INTVAL (operands[1]));
-+     operands[3] = GEN_INT (INTVAL (operands[1]) >> shift);
-+     operands[4] = GEN_INT (shift);
-+   }")
-+
-+; For some 16-bit unsigned constants that have bit 15 set we can use
-+; swapb.2!
-+;
-+; Note that the movsi code emits the same sequence but by using a peephole2
-+; we split the pattern early enough to allow instruction scheduling to
-+; occur.
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "register_operand" "")
-+      (match_operand:SI 1 "const_int_operand" ""))]
-+  "(ubicom32_v4
-+    && (INTVAL (operands[1]) & 0xffff80ff) == 0x80ff)"
-+  [(set (match_dup 0)
-+      (zero_extend:SI (bswap:HI (match_dup 2))))]
-+  "{
-+     HOST_WIDE_INT i = INTVAL (operands[1]) >> 8;
-+     if (i >= 0x80)
-+       i -= 0x100;
-+     operands[2] = GEN_INT (i);
-+   }")
-+
-+; In general for a 16-bit unsigned constant that has bit 15 set
-+; then we need a movei/move.2 pair unless we can represent it
-+; via just a move.2.
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "register_operand" "")
-+      (match_operand:SI 1 "const_int_operand" ""))]
-+  "(INTVAL (operands[1]) & 0xffff8000) == 0x8000
-+    && (INTVAL (operands[1]) & 0xffff) < 0xff80"
-+  [(set (match_dup 2)
-+      (match_dup 1))
-+   (set (match_dup 0)
-+      (zero_extend:SI (match_dup 2)))]
-+  "{
-+     operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));
-+   }")
-+
-+; If we're not dependent on the state of the condition codes we can construct
-+; 32-bit constants that have bits 16 through 31 set to arbitrary values
-+; and have bits 0 through 15 set to something representable as a default
-+; source-1 immediate - we use movei/shmrg.2
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "")
-+      (match_operand:SI 1 "const_int_operand" ""))]
-+  "(((INTVAL (operands[1]) >= 0x8000
-+      && INTVAL (operands[1]) < 0xff80)
-+     || INTVAL (operands[1]) >= 0x10000
-+     || INTVAL (operands[1]) < -0x8000)
-+    && ((INTVAL (operands[1]) & 0xffff) >= 0xff80
-+      || (INTVAL (operands[1]) & 0xffff) < 0x80)
-+    && peep2_regno_dead_p (0, CC_REGNO))"
-+  [(set (match_dup 0)
-+      (match_dup 2))
-+   (parallel
-+     [(set (match_dup 0)
-+         (ior:SI
-+           (ashift:SI (match_dup 0)
-+                      (const_int 16))
-+           (zero_extend:SI
-+             (match_dup 3))))
-+      (clobber (reg:CC CC_REGNO))])]
-+  "{
-+     operands[2] = gen_highpart_mode (HImode, SImode, operands[1]);
-+     operands[3] = gen_lowpart (HImode, operands[1]);
-+   }")
-+
-+; Exactly the same as the peephole2 preceding except that this targets a
-+; general register instead of D register.  Hopefully the later optimization
-+; passes will notice that the value ended up in a D register first here
-+; and eliminate away the other register!
-+;
-+(define_peephole2
-+  [(match_scratch:SI 2 "d")
-+   (set (match_operand:SI 0 "register_operand" "")
-+      (match_operand:SI 1 "const_int_operand" ""))]
-+  "(((INTVAL (operands[1]) >= 0x8000
-+      && INTVAL (operands[1]) < 0xff80)
-+     || INTVAL (operands[1]) >= 0x10000
-+     || INTVAL (operands[1]) < -0x8000)
-+    && ((INTVAL (operands[1]) & 0xffff) >= 0xff80
-+      || (INTVAL (operands[1]) & 0xffff) < 0x80)
-+    && peep2_regno_dead_p (0, CC_REGNO))"
-+  [(set (match_dup 2)
-+      (match_dup 3))
-+   (parallel
-+     [(set (match_dup 2)
-+         (ior:SI
-+           (ashift:SI (match_dup 2)
-+                      (const_int 16))
-+           (zero_extend:SI
-+             (match_dup 4))))
-+      (clobber (reg:CC CC_REGNO))])
-+   (set (match_dup 0)
-+      (match_dup 2))]
-+  "{
-+     operands[3] = gen_highpart_mode (HImode, SImode, operands[1]);
-+     operands[4] = gen_lowpart (HImode, operands[1]);
-+   }")
-+
-+; If we have a load of a large integer constant which does not have bit 31
-+; set and we have a spare A reg then construct it with a moveai/lea.1 pair
-+; instead.  This avoids constructing it in 3 instructions on the stack.
-+;
-+; Note that we have to be careful not to match anything that matches
-+; something we can do in a single instruction!  There aren't many such
-+; constants but there are some.
-+;
-+(define_peephole2
-+  [(match_scratch:SI 2 "a")
-+   (set (match_operand:SI 0 "register_operand" "")
-+      (match_operand:SI 1 "const_int_operand" ""))]
-+  "(! (INTVAL (operands[1]) & 0x80000000)
-+    && ((INTVAL (operands[1]) >= 0x8000
-+       && INTVAL (operands[1]) < 0xff80)
-+      || INTVAL (operands[1]) >= 0x10000))"
-+  [(set (match_dup 2)
-+      (match_dup 3))
-+   (set (match_dup 0)
-+      (plus:SI (match_dup 2)
-+               (match_dup 4)))]
-+  "{
-+     HOST_WIDE_INT i = INTVAL (operands[1]);
-+     operands[3] = GEN_INT (i & 0xffffff80);
-+     operands[4] = GEN_INT (i & 0x7f);
-+   }")
-+
-+; If we're not dependent on the state of the condition codes we can construct
-+; a 32-bit constant with a movei/movei/shmrg.2 sequence if possible.
-+;
-+(define_peephole2
-+  [(match_scratch:HI 2 "d")
-+   (set (match_operand:SI 0 "ubicom32_data_register_operand" "")
-+      (match_operand:SI 1 "const_int_operand" ""))
-+   (match_dup 2)]
-+  "(INTVAL (operands[1]) & 0x80000000
-+    && INTVAL (operands[1]) < -0x8000
-+    && peep2_regno_dead_p (0, CC_REGNO))"
-+  [(set (match_dup 0)
-+      (match_dup 3))
-+   (set (match_dup 2)
-+      (match_dup 4))
-+   (parallel
-+     [(set (match_dup 0)
-+         (ior:SI
-+           (ashift:SI (match_dup 0)
-+                      (const_int 16))
-+           (zero_extend:SI
-+             (match_dup 2))))
-+      (clobber (reg:CC CC_REGNO))])]
-+  "{
-+     operands[3] = gen_highpart_mode (HImode, SImode, operands[1]);
-+     operands[4] = gen_lowpart (HImode, operands[1]);
-+   }")
-+
-+; Exactly the same as the peephole2 preceding except that this targets a
-+; general register instead of D register.  Hopefully the later optimization
-+; passes will notice that the value ended up in a D register first here
-+; and eliminate away the other register!
-+;
-+(define_peephole2
-+  [(match_scratch:SI 2 "d")
-+   (match_scratch:HI 3 "d")
-+   (set (match_operand:SI 0 "register_operand" "")
-+      (match_operand:SI 1 "const_int_operand" ""))
-+   (match_dup 3)]
-+  "(INTVAL (operands[1]) & 0x80000000
-+    && INTVAL (operands[1]) < -0x8000
-+    && peep2_regno_dead_p (0, CC_REGNO))"
-+  [(set (match_dup 2)
-+      (match_dup 4))
-+   (set (match_dup 3)
-+      (match_dup 5))
-+   (parallel
-+     [(set (match_dup 2)
-+         (ior:SI
-+           (ashift:SI (match_dup 2)
-+                      (const_int 16))
-+           (zero_extend:SI
-+             (match_dup 3))))
-+      (clobber (reg:CC CC_REGNO))])
-+   (set (match_dup 0)
-+      (match_dup 2))]
-+  "{
-+     operands[4] = gen_highpart_mode (HImode, SImode, operands[1]);
-+     operands[5] = gen_lowpart (HImode, operands[1]);
-+   }")
-+
-+(define_insn "movsi_fdpic_got_offset"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
-+      (match_operand:SI 1 "ubicom32_fdpic_got_offset_operand" "Y"))]
-+  ""
-+  "movei\\t%0, %1")
-+
-+; The explicit MEM inside the UNSPEC prevents the compiler from moving
-+; the load before a branch after a NULL test, or before a store that
-+; initializes a function descriptor.
-+
-+(define_insn_and_split "load_fdpic_funcdesc"
-+  [(set (match_operand:SI 0 "ubicom32_address_register_operand" "=a")
-+      (unspec_volatile:SI [(mem:SI (match_operand:SI 1 "address_operand" "p"))]
-+                           UNSPEC_VOLATILE_LOAD_FDPIC_FUNCDESC))]
-+  ""
-+  "#"
-+  "reload_completed"
-+  [(set (match_dup 0)
-+      (mem:SI (match_dup 1)))])
-+
-+; Combiner-generated 32-bit move with the zero flag set accordingly.
-+;
-+(define_insn "movsi_ccwzn"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:SI 0 "nonimmediate_operand" "rm, d")
-+               (const_int 0)))
-+   (set (match_operand:SI 1 "nonimmediate_operand"        "=d,rm")
-+      (match_dup 0))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "@
-+   lsl.4\\t%1, %0, #0
-+   add.4\\t%1, #0, %0")
-+
-+; Combiner-generated 32-bit move with all flags set accordingly.
-+;
-+(define_insn "movsi_ccw"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:SI 0 "ubicom32_data_register_operand" "d")
-+               (const_int 0)))
-+   (set (match_operand:SI 1 "nonimmediate_operand"                "=rm")
-+      (match_dup 0))]
-+  "ubicom32_match_cc_mode(insn, CCWmode)"
-+  "add.4\\t%1, #0, %0")
-+
-+; Combine isn't very good at merging some types of operations so we
-+; have to make do with a peephole.  It's not as effective but it's better
-+; than doing nothing.
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "")
-+      (match_operand:SI 1 "nonimmediate_operand" ""))
-+   (parallel
-+     [(set (match_operand 2 "ubicom32_cc_register_operand" "")
-+         (match_operator 3 "ubicom32_compare_operator"
-+           [(match_dup 0)
-+            (const_int 0)]))
-+      (clobber (match_operand:SI 4 "ubicom32_data_register_operand" ""))])]
-+  "(GET_MODE (operands[2]) == CCWZNmode
-+    || GET_MODE (operands[2]) == CCWZmode)"
-+  [(parallel
-+     [(set (match_dup 2)
-+         (match_op_dup 3
-+           [(match_dup 1)
-+            (const_int 0)]))
-+      (set (match_dup 0)
-+         (match_dup 1))])]
-+   "")
-+
-+; Combine isn't very good at merging some types of operations so we
-+; have to make do with a peephole.  It's not as effective but it's better
-+; than doing nothing.
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
-+      (match_operand:SI 1 "ubicom32_data_register_operand" ""))
-+   (parallel
-+     [(set (match_operand 2 "ubicom32_cc_register_operand" "")
-+         (match_operator 3 "ubicom32_compare_operator"
-+           [(match_dup 1)
-+            (const_int 0)]))
-+      (clobber (match_operand:SI 4 "ubicom32_data_register_operand" ""))])]
-+  "(GET_MODE (operands[2]) == CCWZNmode
-+    || GET_MODE (operands[2]) == CCWZmode)"
-+  [(parallel
-+     [(set (match_dup 2)
-+         (match_op_dup 3
-+           [(match_dup 1)
-+            (const_int 0)]))
-+      (set (match_dup 0)
-+         (match_dup 1))])]
-+   "")
-+
-+; Combine isn't very good at merging some types of operations so we
-+; have to make do with a peephole.  It's not as effective but it's better
-+; than doing nothing.
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "register_operand" "")
-+      (match_operand:SI 1 "nonimmediate_operand" ""))
-+   (parallel
-+     [(set (match_operand 2 "ubicom32_cc_register_operand" "")
-+         (match_operator 3 "ubicom32_compare_operator"
-+           [(match_dup 0)
-+            (const_int 0)]))
-+      (set (match_operand:SI 4 "ubicom32_data_register_operand" "")
-+         (match_dup 0))])]
-+  "(peep2_reg_dead_p (2, operands[0])
-+    && (GET_MODE (operands[2]) == CCWZNmode
-+      || GET_MODE (operands[2]) == CCWZmode))"
-+  [(parallel
-+     [(set (match_dup 2)
-+         (match_op_dup 3
-+           [(match_dup 1)
-+            (const_int 0)]))
-+      (set (match_dup 4)
-+         (match_dup 1))])]
-+   "")
-+
-+; Register renaming may make a general reg into a D reg in which case
-+; we may be able to simplify a compare.
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "register_operand" "")
-+      (match_operand:SI 1 "nonimmediate_operand" ""))
-+   (parallel
-+     [(set (match_operand 2 "ubicom32_cc_register_operand" "")
-+         (match_operator 3 "ubicom32_compare_operator"
-+           [(match_dup 0)
-+            (const_int 0)]))
-+      (clobber (match_operand:SI 4 "ubicom32_data_register_operand" ""))])]
-+  "(peep2_reg_dead_p (2, operands[0])
-+    && (GET_MODE (operands[2]) == CCWZNmode
-+      || GET_MODE (operands[2]) == CCWZmode))"
-+  [(parallel
-+     [(set (match_dup 2)
-+         (match_op_dup 3
-+           [(match_dup 1)
-+            (const_int 0)]))
-+      (clobber (match_dup 4))])]
-+   "")
-+
-+(define_insn_and_split "movdi"
-+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
-+      (match_operand:DI 1 "general_operand"     "rmi,ri"))]
-+  ""
-+  "#"
-+  "reload_completed"
-+  [(set (match_dup 2) (match_dup 3))
-+   (set (match_dup 4) (match_dup 5))]
-+  "{
-+     rtx dest_low;
-+     rtx src_low;
-+
-+     dest_low = gen_lowpart (SImode, operands[0]);
-+     src_low = gen_lowpart (SImode, operands[1]);
-+
-+     if (REG_P (operands[0])
-+       && REG_P (operands[1])
-+       && REGNO (operands[0]) < REGNO (operands[1]))
-+       {
-+       operands[2] = gen_highpart (SImode, operands[0]);
-+       operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
-+       operands[4] = dest_low;
-+       operands[5] = src_low;
-+       }
-+     else if (reg_mentioned_p (dest_low, src_low))
-+       {
-+       operands[2] = gen_highpart (SImode, operands[0]);
-+       operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
-+       operands[4] = dest_low;
-+       operands[5] = src_low;
-+       }
-+     else
-+       {
-+       operands[2] = dest_low;
-+       operands[3] = src_low;
-+       operands[4] = gen_highpart (SImode, operands[0]);
-+       operands[5] = gen_highpart_mode (SImode, DImode, operands[1]);
-+       }
-+   }"
-+  [(set_attr "length" "8")])
-+
-+; Combiner-generated 64-bit move with all flags set accordingly.
-+;
-+(define_insn "movdi_ccwzn"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:DI 0 "nonimmediate_operand" "d, m,   r")
-+               (const_int 0)))
-+   (set (match_operand:DI 1 "nonimmediate_operand"     "=&rm,rm,!&rm")
-+      (match_dup 0))
-+   (clobber (match_scratch:SI 2                                  "=X, d,   d"))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "*
-+   {
-+     operands[3] = gen_lowpart (SImode, operands[0]);
-+     operands[4] = gen_lowpart (SImode, operands[1]);
-+     operands[5] = gen_highpart (SImode, operands[0]);
-+     operands[6] = gen_highpart (SImode, operands[1]);
-+
-+     if (ubicom32_data_register_operand (operands[0], VOIDmode))
-+       return \"add.4\\t%4, #0, %3\;addc\\t%6, #0, %5\";
-+
-+     return \"movei\\t%2, #0\;add.4\\t%4, %3, %2\;addc\\t%6, %5, %2\";
-+   }"
-+  [(set_attr "length" "8")])
-+
-+(define_insn "movdi_ccw"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:DI 0 "nonimmediate_operand" "d, m,   r")
-+               (const_int 0)))
-+   (set (match_operand:DI 1 "nonimmediate_operand"     "=&rm,rm,!&rm")
-+      (match_dup 0))
-+   (clobber (match_scratch:SI 2                                  "=X, d,   d"))]
-+  "ubicom32_match_cc_mode(insn, CCWmode)"
-+  "*
-+   {
-+     operands[3] = gen_lowpart (SImode, operands[0]);
-+     operands[4] = gen_lowpart (SImode, operands[1]);
-+     operands[5] = gen_highpart (SImode, operands[0]);
-+     operands[6] = gen_highpart (SImode, operands[1]);
-+
-+     if (ubicom32_data_register_operand (operands[0], VOIDmode))
-+       return \"add.4\\t%4, #0, %3\;addc\\t%6, #0, %5\";
-+
-+     return \"movei\\t%2, #0\;add.4\\t%4, %3, %2\;addc\\t%6, %5, %2\";
-+   }"
-+  [(set_attr "length" "8")])
-+
-+(define_insn "movsf"
-+  [(set (match_operand:SF 0 "nonimmediate_operand"  "=!d,*rm")
-+      (match_operand:SF 1 "ubicom32_move_operand" "rmF,rmF"))]
-+  ""
-+  "*
-+   {
-+     if (GET_CODE (operands[1]) == CONST_DOUBLE)
-+       {
-+       HOST_WIDE_INT val;
-+       REAL_VALUE_TYPE rv;
-+
-+       REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
-+       REAL_VALUE_TO_TARGET_SINGLE (rv, val);
-+
-+       ubicom32_emit_move_const_int (operands[0], GEN_INT (val));
-+       return \"\";
-+       }
-+
-+     return \"move.4\\t%0, %1\";
-+   }")
-+
-+(define_insn "zero_extendqihi2"
-+  [(set (match_operand:HI 0 "register_operand"                           "=r")
-+      (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
-+  ""
-+  "move.1\\t%0, %1")
-+
-+(define_insn "zero_extendqisi2"
-+  [(set (match_operand:SI 0 "register_operand"                           "=r")
-+      (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
-+  ""
-+  "move.1\\t%0, %1")
-+
-+(define_insn "zero_extendqisi2_ccwz_1"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm"))
-+          (const_int 0)))
-+   (set (match_operand:SI 0 "ubicom32_data_register_operand"       "=d")
-+      (zero_extend:SI (match_dup 1)))]
-+  "ubicom32_match_cc_mode(insn, CCWZmode)"
-+  "shmrg.1\\t%0, %1, #0")
-+
-+(define_insn "zero_extendhisi2"
-+  [(set (match_operand:SI 0 "register_operand"                           "=r")
-+      (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
-+  ""
-+  "move.2\\t%0, %1")
-+
-+(define_insn "zero_extendhisi2_ccwz_1"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm"))
-+          (const_int 0)))
-+   (set (match_operand:SI 0 "ubicom32_data_register_operand"       "=d")
-+      (zero_extend:SI (match_dup 1)))]
-+  "ubicom32_match_cc_mode(insn, CCWZmode)"
-+  "shmrg.2\\t%0, %1, #0")
-+
-+(define_insn_and_split "zero_extendqidi2"
-+  [(set (match_operand:DI 0 "register_operand"                           "=r")
-+      (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
-+  ""
-+  "#"
-+  "reload_completed"
-+  [(set (match_dup 2)
-+      (zero_extend:SI (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" "8")])
-+
-+(define_insn_and_split "zero_extendhidi2"
-+  [(set (match_operand:DI 0 "register_operand"                           "=r")
-+      (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
-+  ""
-+  "#"
-+  "reload_completed"
-+  [(set (match_dup 2)
-+      (zero_extend:SI (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" "8")])
-+
-+(define_insn_and_split "zero_extendsidi2"
-+  [(set (match_operand:DI 0 "nonimmediate_operand"              "=rm")
-+      (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm")))]
-+  ""
-+  "#"
-+  "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" "8")])
-+
-+(define_insn "extendqihi2"
-+  [(set (match_operand:HI 0 "register_operand"                           "=r")
-+      (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "ext.1\\t%0, %1")
-+
-+(define_insn "extendqisi2"
-+  [(set (match_operand:SI 0 "register_operand"                           "=r")
-+      (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "ext.1\\t%0, %1")
-+
-+(define_insn "extendhisi2"
-+  [(set (match_operand:SI 0 "register_operand"                           "=r")
-+      (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "ext.2\\t%0, %1")
-+
-+(define_insn_and_split "extendsidi2"
-+  [(set (match_operand:DI 0 "nonimmediate_operand"               "=d")
-+      (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "#"
-+  "reload_completed"
-+  [(set (match_dup 2)
-+      (match_dup 1))
-+   (parallel
-+     [(set (match_dup 3)
-+         (ashiftrt:SI (match_dup 2)
-+                      (const_int 31)))
-+      (clobber (reg:CC CC_REGNO))])]
-+  "{
-+     operands[2] = gen_lowpart (SImode, operands[0]);
-+     operands[3] = gen_highpart (SImode, operands[0]);
-+   }"
-+  [(set_attr "length" "8")])
-+
-+(define_insn "bswaphi"
-+  [(set (match_operand:HI 0 "nonimmediate_operand"           "=rm")
-+      (bswap:HI (match_operand:HI 1 "ubicom32_arith_operand" "rmI")))]
-+  "(ubicom32_v4)"
-+  "swapb.2\\t%0, %1");
-+
-+(define_insn "bswaphisi"
-+  [(set (match_operand:SI 0 "register_operand"                          "=r")
-+      (zero_extend:SI
-+        (bswap:HI (match_operand:HI 1 "ubicom32_arith_operand" "rmI"))))]
-+  "(ubicom32_v4)"
-+  "swapb.2\\t%0, %1");
-+
-+(define_insn "bswapsi"
-+  [(set (match_operand:SI 0 "nonimmediate_operand"           "=rm")
-+      (bswap:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")))]
-+  "(ubicom32_v4)"
-+  "swapb.4\\t%0, %1");
-+
-+(define_insn "tstqi_ext1"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:QI 0 "nonimmediate_operand" "rm")
-+               (const_int 0)))]
-+  "ubicom32_match_cc_mode(insn, CCSZNmode)"
-+  "ext.1\\t#0, %0")
-+
-+(define_expand "cmpqi"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:QI 0 "ubicom32_arith_operand" "")
-+               (match_operand:QI 1 "ubicom32_data_register_operand" "")))]
-+  "(ubicom32_v4)"
-+  "{
-+     ubicom32_compare_op0 = operands[0];
-+     ubicom32_compare_op1 = operands[1];
-+     DONE;
-+   }")
-+
-+(define_insn "sub1_ccs"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:QI 0 "ubicom32_arith_operand"       "rmI")
-+               (match_operand:QI 1 "ubicom32_data_register_operand" "d")))]
-+  "(ubicom32_v4)"
-+  "sub.1\\t#0, %0, %1")
-+
-+; If we're testing for equality we don't have to worry about reversing conditions.
-+;
-+(define_insn "sub1_ccsz_1"
-+  [(set (reg:CCSZ CC_REGNO)
-+      (compare:CCSZ (match_operand:QI 0 "nonimmediate_operand"          "rm")
-+                    (match_operand:QI 1 "ubicom32_data_register_operand" "d")))]
-+  "(ubicom32_v4)"
-+  "sub.1\\t#0, %0, %1")
-+
-+(define_insn "sub1_ccsz_2"
-+  [(set (reg:CCSZ CC_REGNO)
-+      (compare:CCSZ (match_operand:QI 0 "ubicom32_data_register_operand" "d")
-+                    (match_operand:QI 1 "ubicom32_arith_operand"       "rmI")))]
-+  "(ubicom32_v4)"
-+  "sub.1\\t#0, %1, %0")
-+
-+; When the combiner runs it doesn't have any insight into whether or not an argument
-+; to a compare is spilled to the stack and therefore can't swap the comparison in
-+; an attempt to use sub.1 more effectively.  We peephole this case here.
-+;
-+(define_peephole2
-+  [(set (match_operand:QI 0 "register_operand" "")
-+      (match_operand:QI 1 "ubicom32_arith_operand" ""))
-+   (set (match_operand 2 "ubicom32_cc_register_operand" "")
-+      (compare (match_operand:QI 3 "ubicom32_data_register_operand" "")
-+               (match_dup 0)))
-+   (set (pc)
-+      (if_then_else (match_operator 4 "comparison_operator"
-+                      [(match_dup 2)
-+                       (const_int 0)])
-+                    (label_ref (match_operand 5 "" ""))
-+                    (pc)))]
-+  "(peep2_reg_dead_p (2, operands[0])
-+    && peep2_regno_dead_p (3, CC_REGNO))"
-+  [(set (match_dup 2)
-+      (compare (match_dup 1)
-+               (match_dup 3)))
-+   (set (pc)
-+      (if_then_else (match_op_dup 6
-+                      [(match_dup 2)
-+                       (const_int 0)])
-+                    (label_ref (match_dup 5))
-+                    (pc)))]
-+  "{
-+     rtx cc_reg;
-+
-+     cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
-+     operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])),
-+                                 GET_MODE (operands[4]),
-+                                 cc_reg,
-+                                 const0_rtx);
-+   }")
-+
-+(define_insn "tsthi_ext2"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:HI 0 "nonimmediate_operand" "rm")
-+               (const_int 0)))]
-+  "ubicom32_match_cc_mode(insn, CCSZNmode)"
-+  "ext.2\\t#0, %0")
-+
-+(define_expand "cmphi"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:HI 0 "ubicom32_arith_operand" "")
-+               (match_operand:HI 1 "ubicom32_compare_operand" "")))]
-+  ""
-+  "{
-+     do
-+       {
-+       /* Is this a cmpi? */
-+       if (CONST_INT_P (operands[1]))
-+         break;
-+
-+       /* Must be a sub.2 - if necessary copy an operand into a reg.  */
-+       if (! ubicom32_data_register_operand (operands[1], HImode))
-+         operands[1] = copy_to_mode_reg (HImode, operands[1]);
-+       }
-+     while (0);
-+
-+     ubicom32_compare_op0 = operands[0];
-+     ubicom32_compare_op1 = operands[1];
-+     DONE;
-+   }")
-+
-+(define_insn "cmpi"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:HI 0 "nonimmediate_operand" "rm")
-+               (match_operand 1 "const_int_operand"        "N")))]
-+  ""
-+  "cmpi\\t%0, %1")
-+
-+(define_insn "sub2_ccs"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:HI 0 "ubicom32_arith_operand"       "rmI")
-+               (match_operand:HI 1 "ubicom32_data_register_operand" "d")))]
-+  ""
-+  "sub.2\\t#0, %0, %1")
-+
-+; If we're testing for equality we don't have to worry about reversing conditions.
-+;
-+(define_insn "sub2_ccsz_1"
-+  [(set (reg:CCSZ CC_REGNO)
-+      (compare:CCSZ (match_operand:HI 0 "nonimmediate_operand"          "rm")
-+                    (match_operand:HI 1 "ubicom32_data_register_operand" "d")))]
-+  ""
-+  "sub.2\\t#0, %0, %1")
-+
-+(define_insn "sub2_ccsz_2"
-+  [(set (reg:CCSZ CC_REGNO)
-+      (compare:CCSZ (match_operand:HI 0 "ubicom32_data_register_operand" "d")
-+                    (match_operand:HI 1 "ubicom32_arith_operand"       "rmI")))]
-+  ""
-+  "sub.2\\t#0, %1, %0")
-+
-+; When the combiner runs it doesn't have any insight into whether or not an argument
-+; to a compare is spilled to the stack and therefore can't swap the comparison in
-+; an attempt to use sub.2 more effectively.  We peephole this case here.
-+;
-+(define_peephole2
-+  [(set (match_operand:HI 0 "register_operand" "")
-+      (match_operand:HI 1 "ubicom32_arith_operand" ""))
-+   (set (match_operand 2 "ubicom32_cc_register_operand" "")
-+      (compare (match_operand:HI 3 "ubicom32_data_register_operand" "")
-+               (match_dup 0)))
-+   (set (pc)
-+      (if_then_else (match_operator 4 "comparison_operator"
-+                      [(match_dup 2)
-+                       (const_int 0)])
-+                    (label_ref (match_operand 5 "" ""))
-+                    (pc)))]
-+  "(peep2_reg_dead_p (2, operands[0])
-+    && peep2_regno_dead_p (3, CC_REGNO))"
-+  [(set (match_dup 2)
-+      (compare (match_dup 1)
-+               (match_dup 3)))
-+   (set (pc)
-+      (if_then_else (match_op_dup 6
-+                      [(match_dup 2)
-+                       (const_int 0)])
-+                    (label_ref (match_dup 5))
-+                    (pc)))]
-+  "{
-+     rtx cc_reg;
-+
-+     cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
-+     operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])),
-+                                 GET_MODE (operands[4]),
-+                                 cc_reg,
-+                                 const0_rtx);
-+   }")
-+
-+(define_insn_and_split "tstsi_lsl4"
-+  [(set (match_operand 0 "ubicom32_cc_register_operand" "=r")
-+      (match_operator 1 "ubicom32_compare_operator"
-+        [(match_operand:SI 2 "nonimmediate_operand"   "rm")
-+         (const_int 0)]))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "#"
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  [(parallel
-+     [(set (match_dup 0)
-+         (match_op_dup 1
-+           [(match_dup 2)
-+            (const_int 0)]))
-+      (clobber (match_dup 3))])]
-+  "{
-+     operands[3] = gen_reg_rtx (SImode);
-+   }")
-+
-+(define_insn "tstsi_lsl4_d"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:SI 0 "nonimmediate_operand" "rm")
-+               (const_int 0)))
-+   (clobber (match_operand:SI 1 "ubicom32_data_register_operand" "=d"))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "lsl.4\\t%1, %0, #0")
-+
-+; Comparison for equality with -1.
-+;
-+(define_insn "cmpsi_not4_ccwz"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:SI 0 "nonimmediate_operand" "rm")
-+               (const_int -1)))]
-+  "ubicom32_match_cc_mode(insn, CCWZmode)"
-+  "not.4\\t#0, %0")
-+
-+(define_expand "cmpsi"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:SI 0 "ubicom32_arith_operand" "")
-+               (match_operand:SI 1 "ubicom32_compare_operand" "")))]
-+  ""
-+  "{
-+     do
-+       {
-+       /* Is this a cmpi?  We can't take a memory address as cmpi takes
-+            16-bit operands.  */
-+       if (register_operand (operands[0], SImode)
-+           && CONST_INT_P (operands[1])
-+           && satisfies_constraint_N (operands[1]))
-+         break;
-+
-+       /* Must be a sub.4 - if necessary copy an operand into a reg.  */
-+       if (! ubicom32_data_register_operand (operands[1], SImode))
-+         operands[1] = copy_to_mode_reg (SImode, operands[1]);
-+       }
-+     while (0);
-+
-+     ubicom32_compare_op0 = operands[0];
-+     ubicom32_compare_op1 = operands[1];
-+     DONE;
-+   }")
-+
-+(define_insn "cmpsi_cmpi"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:SI 0 "register_operand" "r")
-+               (match_operand 1 "const_int_operand"   "N")))]
-+  "(satisfies_constraint_N (operands[1]))"
-+  "cmpi\\t%0, %1")
-+
-+(define_insn "cmpsi_sub4"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:SI 0 "ubicom32_arith_operand"       "rmI")
-+               (match_operand:SI 1 "ubicom32_data_register_operand" "d")))]
-+  ""
-+  "sub.4\\t#0, %0, %1")
-+
-+; If we're testing for equality we don't have to worry about reversing conditions.
-+;
-+(define_insn "cmpsi_sub4_ccwz_1"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:SI 0 "nonimmediate_operand"          "rm")
-+               (match_operand:SI 1 "ubicom32_data_register_operand" "d")))]
-+  "ubicom32_match_cc_mode(insn, CCWZmode)"
-+  "sub.4\\t#0, %0, %1")
-+
-+(define_insn "cmpsi_sub4_ccwz_2"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:SI 0 "ubicom32_data_register_operand" "d")
-+               (match_operand:SI 1 "nonimmediate_operand"          "rm")))]
-+  "ubicom32_match_cc_mode(insn, CCWZmode)"
-+  "sub.4\\t#0, %1, %0")
-+
-+; When the combiner runs it doesn't have any insight into whether or not an argument
-+; to a compare is spilled to the stack and therefore can't swap the comparison in
-+; an attempt to use sub.4 more effectively.  We peephole this case here.
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "register_operand" "")
-+      (match_operand:SI 1 "ubicom32_arith_operand" ""))
-+   (set (match_operand 2 "ubicom32_cc_register_operand" "")
-+      (compare (match_operand:SI 3 "ubicom32_data_register_operand" "")
-+               (match_dup 0)))
-+   (set (pc)
-+      (if_then_else (match_operator 4 "comparison_operator"
-+                      [(match_dup 2)
-+                       (const_int 0)])
-+                    (label_ref (match_operand 5 "" ""))
-+                    (pc)))]
-+  "(peep2_reg_dead_p (2, operands[0])
-+    && peep2_regno_dead_p (3, CC_REGNO))"
-+  [(set (match_dup 2)
-+      (compare (match_dup 1)
-+               (match_dup 3)))
-+   (set (pc)
-+      (if_then_else (match_op_dup 6
-+                      [(match_dup 2)
-+                       (const_int 0)])
-+                    (label_ref (match_dup 5))
-+                    (pc)))]
-+  "{
-+     rtx cc_reg;
-+
-+     cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
-+     operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])),
-+                                 GET_MODE (operands[4]),
-+                                 cc_reg,
-+                                 const0_rtx);
-+   }")
-+
-+(define_insn_and_split "tstdi_or4"
-+  [(set (reg:CCWZ CC_REGNO)
-+      (compare:CCWZ (match_operand:DI 0 "nonimmediate_operand" "rm")
-+                    (const_int 0)))]
-+  ""
-+  "#"
-+  ""
-+  [(parallel
-+     [(set (reg:CCWZ CC_REGNO)
-+         (compare:CCWZ (match_dup 0)
-+                       (const_int 0)))
-+      (clobber (match_dup 1))])]
-+  "{
-+     operands[1] = gen_reg_rtx (SImode);
-+   }")
-+
-+(define_insn "tstdi_or4_d"
-+  [(set (reg:CCWZ CC_REGNO)
-+      (compare:CCWZ (match_operand:DI 0 "nonimmediate_operand" "rm")
-+                    (const_int 0)))
-+   (clobber (match_operand:SI 1 "ubicom32_data_register_operand" "=d"))]
-+  ""
-+  "*
-+   {
-+     operands[2] = gen_lowpart (SImode, operands[0]);
-+     operands[3] = gen_highpart_mode (SImode, DImode, operands[0]);
-+
-+     if (ubicom32_data_register_operand (operands[0], GET_MODE (operands[0])))
-+       return \"or.4\\t#0, %2, %3\";
-+
-+     return \"move.4\\t%1, %2\;or.4\\t%1, %3, %1\";
-+   }"
-+  [(set_attr "length" "8")])
-+
-+(define_expand "cmpdi"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:DI 0 "ubicom32_arith_operand" "")
-+               (match_operand:DI 1 "ubicom32_data_register_operand" "")))]
-+  ""
-+  "{
-+     ubicom32_compare_op0 = operands[0];
-+     ubicom32_compare_op1 = operands[1];
-+     DONE;
-+   }")
-+
-+(define_insn "cmpdi_sub4subc"
-+  [(set (reg CC_REGNO)
-+      (compare (match_operand:DI 0 "ubicom32_arith_operand"       "rmI")
-+               (match_operand:DI 1 "ubicom32_data_register_operand" "d")))]
-+  ""
-+  "*
-+   {
-+     operands[2] = gen_lowpart (SImode, operands[0]);
-+     operands[3] = gen_lowpart (SImode, operands[1]);
-+     operands[4] = gen_highpart_mode (SImode, DImode, operands[0]);
-+     operands[5] = gen_highpart_mode (SImode, DImode, operands[1]);
-+
-+     return \"sub.4\\t#0, %2, %3\;subc\\t#0, %4, %5\";
-+   }"
-+  [(set_attr "length" "8")])
-+
-+; When the combiner runs it doesn't have any insight into whether or not an argument
-+; to a compare is spilled to the stack and therefore can't swap the comparison in
-+; an attempt to use sub.4/subc more effectively.  We peephole this case here.
-+;
-+(define_peephole2
-+  [(set (match_operand:DI 0 "register_operand" "")
-+      (match_operand:DI 1 "ubicom32_arith_operand" ""))
-+   (set (match_operand 2 "ubicom32_cc_register_operand" "")
-+      (compare (match_operand:DI 3 "ubicom32_data_register_operand" "")
-+               (match_dup 0)))
-+   (set (pc)
-+      (if_then_else (match_operator 4 "comparison_operator"
-+                      [(match_dup 2)
-+                       (const_int 0)])
-+                    (label_ref (match_operand 5 "" ""))
-+                    (pc)))]
-+  "(peep2_reg_dead_p (2, operands[0])
-+    && peep2_regno_dead_p (3, CC_REGNO))"
-+  [(set (match_dup 2)
-+      (compare (match_dup 1)
-+               (match_dup 3)))
-+   (set (pc)
-+      (if_then_else (match_op_dup 6
-+                      [(match_dup 2)
-+                       (const_int 0)])
-+                    (label_ref (match_dup 5))
-+                    (pc)))]
-+  "{
-+     rtx cc_reg;
-+
-+     cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
-+     operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])),
-+                                 GET_MODE (operands[4]),
-+                                 cc_reg,
-+                                 const0_rtx);
-+   }")
-+
-+(define_insn "btst"
-+  [(set (reg:CCWZ CC_REGNO)
-+      (compare:CCWZ
-+        (zero_extract:SI
-+          (match_operand:SI 0 "nonimmediate_operand"   "rm")
-+          (const_int 1)
-+          (match_operand:SI 1 "ubicom32_arith_operand" "dM"))
-+        (const_int 0)))]
-+  ""
-+  "btst\\t%0, %1")
-+
-+(define_insn "bfextu_ccwz_null"
-+  [(set (reg:CCWZ CC_REGNO)
-+      (compare:CCWZ
-+        (zero_extract:SI
-+          (match_operand:SI 0 "nonimmediate_operand" "rm")
-+          (match_operand 1 "const_int_operand"        "M")
-+          (const_int 0))
-+        (const_int 0)))
-+   (clobber (match_scratch:SI 2                              "=d"))]
-+  ""
-+  "bfextu\\t%2, %0, %1")
-+
-+(define_expand "addqi3"
-+  [(parallel
-+     [(set (match_operand:QI 0 "memory_operand" "")
-+         (plus:QI (match_operand:QI 1 "nonimmediate_operand" "")
-+                  (match_operand:QI 2 "ubicom32_arith_operand" "")))
-+      (clobber (reg:CC CC_REGNO))])]
-+  "(ubicom32_v4)"
-+  "{
-+     if (!memory_operand (operands[0], QImode))
-+       FAIL;
-+
-+     /* If we have a non-data reg for operand 1 then prefer that over
-+        a CONST_INT in operand 2.  */
-+     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
-+       && CONST_INT_P (operands[2]))
-+       operands[2] = copy_to_mode_reg (QImode, operands[2]);
-+
-+     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
-+       operands[2] = copy_to_mode_reg (QImode, operands[2]);
-+   }")
-+
-+(define_insn "addqi3_add1"
-+  [(set (match_operand:QI 0 "memory_operand"                 "=m, m")
-+      (plus:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
-+               (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(ubicom32_v4)"
-+  "@
-+   add.1\\t%0, %2, %1
-+   add.1\\t%0, %1, %2")
-+
-+(define_insn "addqi3_add1_ccszn_null"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (neg:QI (match_operand:QI 0 "nonimmediate_operand" "%d,rm"))
-+        (match_operand:QI 1 "ubicom32_arith_operand"      "rmI, d")))]
-+  "(ubicom32_v4
-+    && ubicom32_match_cc_mode(insn, CCSZNmode))"
-+  "@
-+   add.1\\t#0, %1, %0
-+   add.1\\t#0, %0, %1")
-+
-+(define_expand "addhi3"
-+  [(parallel
-+     [(set (match_operand:HI 0 "memory_operand" "")
-+         (plus:HI (match_operand:HI 1 "nonimmediate_operand" "")
-+                  (match_operand:HI 2 "ubicom32_arith_operand" "")))
-+      (clobber (reg:CC CC_REGNO))])]
-+  ""
-+  "{
-+     if (!memory_operand (operands[0], HImode))
-+       FAIL;
-+
-+     /* If we have a non-data reg for operand 1 then prefer that over
-+        a CONST_INT in operand 2.  */
-+     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
-+       && CONST_INT_P (operands[2]))
-+       operands[2] = copy_to_mode_reg (HImode, operands[2]);
-+
-+     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
-+       operands[2] = copy_to_mode_reg (HImode, operands[2]);
-+   }")
-+
-+(define_insn "addhi3_add2"
-+  [(set (match_operand:HI 0 "memory_operand"                 "=m, m")
-+      (plus:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
-+               (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "@
-+   add.2\\t%0, %2, %1
-+   add.2\\t%0, %1, %2")
-+
-+(define_insn "addhi3_add2_ccszn_null"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (neg:HI (match_operand:HI 0 "nonimmediate_operand" "%d,rm"))
-+        (match_operand:HI 1 "ubicom32_arith_operand"      "rmI, d")))]
-+  "ubicom32_match_cc_mode(insn, CCSZNmode)"
-+  "@
-+   add.2\\t#0, %1, %0
-+   add.2\\t#0, %0, %1")
-+
-+(define_expand "addsi3"
-+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
-+      (plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
-+               (match_operand:SI 2 "ubicom32_move_operand" "")))]
-+  ""
-+  "{
-+     ubicom32_expand_addsi3 (operands);
-+     DONE;
-+   }")
-+
-+; We start with an instruction pattern that can do all sorts of interesting
-+; things but we split out any uses of lea or pdec instructions because
-+; those instructions don't clobber the condition codes.
-+;
-+(define_insn_and_split "addsi3_1"
-+  [(set (match_operand:SI 0 "nonimmediate_operand"       "=rm,rm,rm,rm,rm, rm,rm")
-+      (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%a, a, a, a, a,  d,rm")
-+               (match_operand:SI 2 "ubicom32_move_operand" "L, K, J, P, d,rmI, d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "@
-+   #
-+   #
-+   #
-+   #
-+   #
-+   add.4\\t%0, %2, %1
-+   add.4\\t%0, %1, %2"
-+  "(reload_completed
-+    && ubicom32_address_register_operand (operands[1], GET_MODE (operands[1])))"
-+  [(set (match_dup 0)
-+      (plus:SI (match_dup 1)
-+               (match_dup 2)))]
-+  ""
-+)
-+
-+(define_insn "addsi3_1_ccwzn"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (plus:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
-+                 (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))
-+        (const_int 0)))
-+   (set (match_operand:SI 0 "nonimmediate_operand"            "=rm,rm")
-+      (plus:SI (match_dup 1)
-+               (match_dup 2)))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "@
-+   add.4\\t%0, %2, %1
-+   add.4\\t%0, %1, %2")
-+
-+(define_insn "addsi3_1_ccwzn_null"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (neg:SI (match_operand:SI 0 "nonimmediate_operand" "%d,rm"))
-+        (match_operand:SI 1 "ubicom32_arith_operand"      "rmI, d")))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "@
-+   add.4\\t#0, %1, %0
-+   add.4\\t#0, %0, %1")
-+
-+(define_insn_and_split "addsi3_2"
-+  [(set (match_operand:SI 0 "nonimmediate_operand"                    "=rm,rm,rm,rm,rm,rm")
-+      (plus:SI (match_operand:SI 1 "ubicom32_address_register_operand" "%a, a, a, a, a, a")
-+               (match_operand:SI 2 "ubicom32_move_operand"              "L, K, J, P, d, n")))]
-+  ""
-+  "@
-+   lea.4\\t%0, %E2(%1)
-+   lea.2\\t%0, %E2(%1)
-+   lea.1\\t%0, %E2(%1)
-+   pdec\\t%0, %n2(%1)
-+   lea.1\\t%0, (%1,%2)
-+   #"
-+  "(reload_completed
-+    && ! satisfies_constraint_L (operands[2])
-+    && ! satisfies_constraint_K (operands[2])
-+    && ! satisfies_constraint_J (operands[2])
-+    && ! satisfies_constraint_P (operands[2])
-+    && ! ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))"
-+  [(set (reg:SI AUX_DATA_REGNO)
-+      (match_dup 2))
-+   (set (match_dup 0)
-+      (plus:SI (match_dup 1)
-+               (reg:SI AUX_DATA_REGNO)))]
-+  ""
-+)
-+
-+(define_insn "lea_2"
-+  [(set (match_operand:SI 0 "nonimmediate_operand"                         "=rm")
-+      (plus:SI (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
-+                        (const_int 2))
-+               (match_operand:SI 2 "ubicom32_address_register_operand"       "a")))]
-+  ""
-+  "lea.2\\t%0, (%2,%1)")
-+
-+(define_insn "lea_4"
-+  [(set (match_operand:SI 0 "nonimmediate_operand"                         "=rm")
-+      (plus:SI (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
-+                        (const_int 4))
-+               (match_operand:SI 2 "ubicom32_address_register_operand"       "a")))]
-+  ""
-+  "lea.4\\t%0, (%2,%1)")
-+
-+(define_expand "adddi3"
-+  [(parallel
-+     [(set (match_operand:DI 0 "nonimmediate_operand" "")
-+         (plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
-+                  (match_operand:DI 2 "ubicom32_arith_operand" "")))
-+      (clobber (reg:CC CC_REGNO))])]
-+  ""
-+  "{
-+     /* If we have a non-data reg for operand 1 then prefer that over
-+        a CONST_INT in operand 2.  */
-+     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
-+       && CONST_INT_P (operands[2]))
-+       operands[2] = copy_to_mode_reg (DImode, operands[2]);
-+
-+     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
-+       operands[2] = copy_to_mode_reg (DImode, operands[2]);
-+   }")
-+
-+; We construct a 64-bit add from 32-bit operations.  Note that we use the
-+; & constraint to prevent overlapping registers being allocated.  We do
-+; allow identical registers though as that won't break anything.
-+;
-+(define_insn "adddi3_add4addc"
-+  [(set (match_operand:DI 0 "nonimmediate_operand"          "=&r,&r,rm,  d,  m, m")
-+      (plus:DI (match_operand:DI 1 "nonimmediate_operand"    "%d,rm, 0,  0,  d,rm")
-+               (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d, d,rmI,rmI, d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "*
-+   {
-+     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]);
-+
-+     if (ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))
-+       return \"add.4\\t%3, %4, %5\;addc\\t%6, %7, %8\";
-+
-+     return \"add.4\\t%3, %5, %4\;addc\\t%6, %8, %7\";
-+   }"
-+  [(set_attr "length" "8")])
-+
-+(define_insn "adddi3_ccwz"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (plus:DI (match_operand:DI 1 "nonimmediate_operand"    "%d,rm, 0,  0,  d,rm")
-+                 (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d, d,rmI,rmI, d"))
-+        (const_int 0)))
-+   (set (match_operand:DI 0 "nonimmediate_operand"            "=&r,&r,rm,  d,  m, m")
-+      (plus:DI (match_dup 1)
-+               (match_dup 2)))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "*
-+   {
-+     operands[3] = gen_lowpart (SImode, operands[0]);
-+     operands[6] = gen_highpart (SImode, operands[0]);
-+
-+     if (ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])))
-+       {
-+       operands[4] = gen_lowpart (SImode, operands[1]);
-+       operands[5] = gen_lowpart (SImode, operands[2]);
-+       operands[7] = gen_highpart (SImode, operands[1]);
-+       operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
-+       }
-+     else
-+       {
-+       operands[4] = gen_lowpart (SImode, operands[2]);
-+       operands[5] = gen_lowpart (SImode, operands[1]);
-+       operands[7] = gen_highpart (SImode, operands[2]);
-+       operands[8] = gen_highpart (SImode, operands[1]);
-+       }
-+
-+     return \"add.4\\t%3, %5, %4\;addc\\t%6, %8, %7\";
-+   }"
-+  [(set_attr "length" "8")])
-+
-+(define_insn "adddi3_ccwz_null"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (neg:DI (match_operand:DI 0 "nonimmediate_operand" "%d,rm"))
-+        (match_operand:DI 1 "ubicom32_arith_operand"      "rmI, d")))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "*
-+   {
-+     if (ubicom32_data_register_operand (operands[0], GET_MODE (operands[0])))
-+       {
-+       operands[2] = gen_lowpart (SImode, operands[0]);
-+       operands[3] = gen_lowpart (SImode, operands[1]);
-+       operands[4] = gen_highpart (SImode, operands[0]);
-+       operands[5] = gen_highpart_mode (SImode, DImode, operands[1]);
-+       }
-+     else
-+       {
-+       operands[2] = gen_lowpart (SImode, operands[1]);
-+       operands[3] = gen_lowpart (SImode, operands[0]);
-+       operands[4] = gen_highpart (SImode, operands[1]);
-+       operands[5] = gen_highpart (SImode, operands[0]);
-+       }
-+
-+     return \"add.4\\t#0, %3, %2\;addc\\t#0, %5, %4\";
-+   }"
-+  [(set_attr "length" "8")])
-+
-+(define_expand "subqi3"
-+  [(parallel
-+     [(set (match_operand:QI 0 "memory_operand" "")
-+         (minus:QI (match_operand:QI 1 "ubicom32_arith_operand" "")
-+                   (match_operand:QI 2 "ubicom32_data_register_operand" "")))
-+      (clobber (reg:CC CC_REGNO))])]
-+  "(ubicom32_v4)"
-+  "{
-+     if (!memory_operand (operands[0], QImode))
-+       FAIL;
-+   }")
-+
-+(define_insn "subqi3_sub1"
-+  [(set (match_operand:QI 0 "memory_operand"                        "=m")
-+      (minus:QI (match_operand:QI 1 "ubicom32_arith_operand"       "rmI")
-+                (match_operand:QI 2 "ubicom32_data_register_operand" "d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(ubicom32_v4)"
-+  "sub.1\\t%0, %1, %2")
-+
-+(define_expand "subhi3"
-+  [(parallel
-+     [(set (match_operand:HI 0 "memory_operand" "")
-+         (minus:HI (match_operand:HI 1 "ubicom32_arith_operand" "")
-+                   (match_operand:HI 2 "ubicom32_data_register_operand" "")))
-+      (clobber (reg:CC CC_REGNO))])]
-+  "(ubicom32_v4)"
-+  "{
-+     if (!memory_operand (operands[0], HImode))
-+       FAIL;
-+   }")
-+
-+(define_insn "subhi3_sub2"
-+  [(set (match_operand:HI 0 "memory_operand"                        "=m")
-+      (minus:HI (match_operand:HI 1 "ubicom32_arith_operand"       "rmI")
-+                (match_operand:HI 2 "ubicom32_data_register_operand" "d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "sub.2\\t%0, %1, %2")
-+
-+(define_insn "subsi3"
-+  [(set (match_operand:SI 0 "nonimmediate_operand"                 "=rm")
-+      (minus:SI (match_operand:SI 1 "ubicom32_arith_operand"       "rmI")
-+                (match_operand:SI 2 "ubicom32_data_register_operand" "d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "sub.4\\t%0, %1, %2")
-+
-+(define_insn "subsi3_ccwz"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (minus:SI (match_operand:SI 1 "ubicom32_arith_operand"       "rmI")
-+                  (match_operand:SI 2 "ubicom32_data_register_operand" "d"))
-+        (const_int 0)))
-+   (set (match_operand:SI 0 "nonimmediate_operand"                   "=rm")
-+      (minus:SI (match_dup 1)
-+                (match_dup 2)))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "sub.4\\t%0, %1, %2")
-+
-+; We construct a 64-bit add from 32-bit operations.  Note that we use the
-+; & constraint to prevent overlapping registers being allocated.  We do
-+; allow identical registers though as that won't break anything.
-+;
-+(define_insn "subdi3"
-+  [(set (match_operand:DI 0 "nonimmediate_operand"                 "=&r,r,  d,  m")
-+      (minus:DI (match_operand:DI 1 "ubicom32_arith_operand"       "rmI,0,rmI,rmI")
-+                (match_operand:DI 2 "ubicom32_data_register_operand" "d,d,  0,  d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "*
-+   {
-+     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 (SImode, operands[2]);
-+
-+     return \"sub.4\\t%3, %4, %5\;subc\\t%6, %7, %8\";
-+   }"
-+  [(set_attr "length" "8")])
-+
-+(define_insn "subdi3_ccwz"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (minus:DI (match_operand:DI 1 "ubicom32_arith_operand"       "rmI,rmI")
-+                  (match_operand:DI 2 "ubicom32_data_register_operand" "d,  d"))
-+        (const_int 0)))
-+   (set (match_operand:DI 0 "nonimmediate_operand"                   "=&r,  m")
-+      (minus:DI (match_dup 1)
-+                (match_dup 2)))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "*
-+   {
-+     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 (SImode, operands[2]);
-+
-+     return \"sub.4\\t%3, %4, %5\;subc\\t%6, %7, %8\";
-+   }"
-+  [(set_attr "length" "8")])
-+
-+;(define_insn "negqi2"
-+;  [(set (match_operand:QI 0 "nonimmediate_operand"              "=rm")
-+;     (neg:QI (match_operand:QI 1 "ubicom32_data_register_operand" "d")))
-+;   (clobber (reg:CC CC_REGNO))]
-+;  "(ubicom32_v4)"
-+;  "sub.1\\t%0, #0, %1")
-+
-+;(define_insn "neghi2"
-+;  [(set (match_operand:HI 0 "nonimmediate_operand"              "=rm")
-+;     (neg:HI (match_operand:HI 1 "ubicom32_data_register_operand" "d")))
-+;   (clobber (reg:CC CC_REGNO))]
-+;  ""
-+;  "sub.2\\t%0, #0, %1")
-+
-+(define_insn "negsi2"
-+  [(set (match_operand:SI 0 "nonimmediate_operand"               "=rm")
-+      (neg:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "sub.4\\t%0, #0, %1")
-+
-+(define_insn_and_split "negdi2"
-+  [(set (match_operand:DI 0 "nonimmediate_operand"              "=&rm")
-+      (neg:DI (match_operand:DI 1 "ubicom32_data_register_operand" "d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "#"
-+  "reload_completed"
-+  [(parallel [(set (match_dup 0)
-+                 (minus:DI (const_int 0)
-+                           (match_dup 1)))
-+            (clobber (reg:CC CC_REGNO))])]
-+  ""
-+  [(set_attr "length" "8")])
-+
-+(define_insn "umulhisi3"
-+  [(set (match_operand:SI 0 "ubicom32_acc_lo_register_operand"             "=l, l")
-+      (mult:SI
-+        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "%d,rm"))
-+        (zero_extend:SI (match_operand:HI 2 "nonimmediate_operand" "rm, d"))))
-+   (clobber (reg:HI ACC0_HI_REGNO))
-+   (clobber (reg:HI ACC1_HI_REGNO))]
-+  ""
-+  "@
-+   mulu\\t%A0, %2, %1
-+   mulu\\t%A0, %1, %2"
-+  [(set_attr "type" "mul,mul")])
-+
-+(define_insn "mulhisi3"
-+  [(set (match_operand:SI 0 "ubicom32_acc_lo_register_operand"             "=l, l")
-+      (mult:SI
-+        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "%d,rm"))
-+        (sign_extend:SI (match_operand:HI 2 "nonimmediate_operand" "rm, d"))))
-+   (clobber (reg:HI ACC0_HI_REGNO))
-+   (clobber (reg:HI ACC1_HI_REGNO))]
-+  ""
-+  "@
-+   muls\\t%A0, %2, %1
-+   muls\\t%A0, %1, %2"
-+  [(set_attr "type" "mul,mul")])
-+
-+(define_expand "mulsi3"
-+  [(set (match_operand:SI 0 "ubicom32_acc_hi_register_operand" "")
-+      (mult:SI (match_operand:SI 1 "ubicom32_arith_operand" "")
-+               (match_operand:SI 2 "ubicom32_arith_operand" "")))]
-+  ""
-+  "{
-+     if (ubicom32_emit_mult_sequence (operands))
-+       DONE;
-+   }")
-+
-+(define_insn "umulsidi3"
-+  [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand"             "=h, h")
-+      (mult:DI
-+        (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%d,rm"))
-+        (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm, d"))))]
-+  "(ubicom32_v4)"
-+  "@
-+   mulu.4\\t%A0, %2, %1
-+   mulu.4\\t%A0, %1, %2"
-+  [(set_attr "type" "mul,mul")])
-+
-+(define_peephole2
-+  [(set (match_operand:SI 0 "register_operand" "")
-+      (match_operand:SI 1 "nonimmediate_operand" ""))
-+   (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "")
-+      (mult:DI
-+        (zero_extend:DI (match_dup 0))
-+        (zero_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))))]
-+  "(peep2_reg_dead_p (2, operands[0])
-+    || REGNO (operands[0]) == REGNO (operands[2])
-+    || REGNO (operands[0]) == REGNO (operands[2]) + 1)
-+   && ! rtx_equal_p (operands[0], operands[3])"
-+  [(set (match_dup 2)
-+      (mult:DI
-+        (zero_extend:DI (match_dup 1))
-+        (zero_extend:DI (match_dup 3))))]
-+  "")
-+
-+(define_peephole2
-+  [(set (match_operand:SI 0 "register_operand" "")
-+      (match_operand:SI 1 "nonimmediate_operand" ""))
-+   (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "")
-+      (mult:DI
-+        (zero_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))
-+        (zero_extend:DI (match_dup 0))))]
-+  "(peep2_reg_dead_p (2, operands[0])
-+    || REGNO (operands[0]) == REGNO (operands[2])
-+    || REGNO (operands[0]) == REGNO (operands[2]) + 1)
-+   && ! rtx_equal_p (operands[0], operands[3])"
-+  [(set (match_dup 2)
-+      (mult:DI
-+        (zero_extend:DI (match_dup 1))
-+        (zero_extend:DI (match_dup 3))))]
-+  "")
-+
-+(define_insn "umulsidi3_const"
-+  [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand"                       "=h")
-+      (mult:DI
-+        (zero_extend:DI (match_operand:SI 1 "ubicom32_data_register_operand" "%d"))
-+        (match_operand 2 "const_int_operand"                                  "I")))]
-+  "(ubicom32_v4 && satisfies_constraint_I (operands[2]))"
-+  "mulu.4\\t%A0, %2, %1"
-+  [(set_attr "type" "mul")])
-+
-+(define_insn "mulsidi3"
-+  [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand"             "=h, h")
-+      (mult:DI
-+        (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%d,rm"))
-+        (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm, d"))))]
-+  "(ubicom32_v4)"
-+  "@
-+   muls.4\\t%A0, %2, %1
-+   muls.4\\t%A0, %1, %2"
-+  [(set_attr "type" "mul,mul")])
-+
-+(define_peephole2
-+  [(set (match_operand:SI 0 "register_operand" "")
-+      (match_operand:SI 1 "nonimmediate_operand" ""))
-+   (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "")
-+      (mult:DI
-+        (sign_extend:DI (match_dup 0))
-+        (sign_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))))]
-+  "(peep2_reg_dead_p (2, operands[0])
-+    || REGNO (operands[0]) == REGNO (operands[2])
-+    || REGNO (operands[0]) == REGNO (operands[2]) + 1)
-+   && ! rtx_equal_p (operands[0], operands[3])"
-+  [(set (match_dup 2)
-+      (mult:DI
-+        (sign_extend:DI (match_dup 1))
-+        (sign_extend:DI (match_dup 3))))]
-+  "")
-+
-+(define_peephole2
-+  [(set (match_operand:SI 0 "register_operand" "")
-+      (match_operand:SI 1 "nonimmediate_operand" ""))
-+   (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "")
-+      (mult:DI
-+        (sign_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))
-+        (sign_extend:DI (match_dup 0))))]
-+  "(peep2_reg_dead_p (2, operands[0])
-+    || REGNO (operands[0]) == REGNO (operands[2])
-+    || REGNO (operands[0]) == REGNO (operands[2]) + 1)
-+   && ! rtx_equal_p (operands[0], operands[3])"
-+  [(set (match_dup 2)
-+      (mult:DI
-+        (sign_extend:DI (match_dup 1))
-+        (sign_extend:DI (match_dup 3))))]
-+  "")
-+
-+(define_insn "mulsidi3_const"
-+  [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand"                       "=h")
-+      (mult:DI
-+        (sign_extend:DI (match_operand:SI 1 "ubicom32_data_register_operand" "%d"))
-+        (match_operand 2 "const_int_operand"                                  "I")))]
-+  "(ubicom32_v4 && satisfies_constraint_I (operands[2]))"
-+  "muls.4\\t%A0, %2, %1"
-+  [(set_attr "type" "mul")])
-+
-+(define_expand "andqi3"
-+  [(parallel
-+     [(set (match_operand:QI 0 "memory_operand" "")
-+         (and:QI (match_operand:QI 1 "nonimmediate_operand" "")
-+                 (match_operand:QI 2 "ubicom32_arith_operand" "")))
-+      (clobber (reg:CC CC_REGNO))])]
-+  "(ubicom32_v4)"
-+  "{
-+     if (!memory_operand (operands[0], QImode))
-+       FAIL;
-+
-+     /* If we have a non-data reg for operand 1 then prefer that over
-+        a CONST_INT in operand 2.  */
-+     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
-+       && CONST_INT_P (operands[2]))
-+       operands[2] = copy_to_mode_reg (QImode, operands[2]);
-+
-+     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
-+       operands[2] = copy_to_mode_reg (QImode, operands[2]);
-+   }")
-+
-+(define_insn "andqi3_and1"
-+  [(set (match_operand:QI 0 "memory_operand"                "=m, m")
-+      (and:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
-+              (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(ubicom32_v4)"
-+  "@
-+   and.1\\t%0, %2, %1
-+   and.1\\t%0, %1, %2")
-+
-+(define_insn "andqi3_and1_ccszn"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (and:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
-+                (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d"))
-+        (const_int 0)))
-+   (set (match_operand:QI 0 "memory_operand"                  "=m, m")
-+      (and:QI (match_dup 1)
-+              (match_dup 2)))]
-+  "(ubicom32_v4
-+    && ubicom32_match_cc_mode(insn, CCSZNmode))"
-+  "@
-+   and.1\\t%0, %2, %1
-+   and.1\\t%0, %1, %2")
-+
-+(define_insn "andqi3_and1_ccszn_null"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (and:QI (match_operand:QI 0 "nonimmediate_operand"    "%d,rm")
-+                (match_operand:QI 1 "ubicom32_arith_operand" "rmI, d"))
-+        (const_int 0)))]
-+  "(ubicom32_v4
-+    && ubicom32_match_cc_mode(insn, CCSZNmode))"
-+  "@
-+   and.1\\t#0, %1, %0
-+   and.1\\t#0, %0, %1")
-+
-+(define_insn "and1_ccszn_null_1"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (subreg:QI
-+          (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d")
-+                  (match_operand:SI 1 "ubicom32_arith_operand"         "rI"))
-+          3)
-+        (const_int 0)))]
-+  "(ubicom32_v4
-+    && ubicom32_match_cc_mode(insn, CCSZNmode))"
-+  "and.1\\t#0, %1, %0")
-+
-+(define_insn "and1_ccszn_null_2"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (subreg:QI
-+          (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d")
-+                  (subreg:SI
-+                    (match_operand:QI 1 "memory_operand"               "m")
-+                    0))
-+          3)
-+        (const_int 0)))]
-+  "(ubicom32_v4
-+    && ubicom32_match_cc_mode(insn, CCSZNmode))"
-+  "and.1\\t#0, %1, %0")
-+
-+(define_insn "and1_ccszn_null_3"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (subreg:QI
-+          (and:SI (subreg:SI
-+                    (match_operand:QI 0 "memory_operand"               "m")
-+                    0)
-+                  (match_operand:SI 1 "ubicom32_data_register_operand" "d"))
-+          3)
-+        (const_int 0)))]
-+  "(ubicom32_v4
-+    && ubicom32_match_cc_mode(insn, CCSZNmode))"
-+  "and.1\\t#0, %0, %1")
-+
-+(define_expand "andhi3"
-+  [(parallel
-+     [(set (match_operand:HI 0 "memory_operand" "")
-+         (and:HI (match_operand:HI 1 "nonimmediate_operand" "")
-+                 (match_operand:HI 2 "ubicom32_arith_operand" "")))
-+      (clobber (reg:CC CC_REGNO))])]
-+  ""
-+  "{
-+     if (!memory_operand (operands[0], HImode))
-+       FAIL;
-+
-+     /* If we have a non-data reg for operand 1 then prefer that over
-+        a CONST_INT in operand 2.  */
-+     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
-+       && CONST_INT_P (operands[2]))
-+       operands[2] = copy_to_mode_reg (HImode, operands[2]);
-+
-+     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
-+       operands[2] = copy_to_mode_reg (HImode, operands[2]);
-+   }")
-+
-+(define_insn "andhi3_and2"
-+  [(set (match_operand:HI 0 "memory_operand"                "=m, m")
-+      (and:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
-+              (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "@
-+   and.2\\t%0, %2, %1
-+   and.2\\t%0, %1, %2")
-+
-+(define_insn "andhi3_and2_ccszn"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (and:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
-+                (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d"))
-+        (const_int 0)))
-+   (set (match_operand:HI 0 "memory_operand"                  "=m, m")
-+      (and:HI (match_dup 1)
-+              (match_dup 2)))]
-+  "ubicom32_match_cc_mode(insn, CCSZNmode)"
-+  "@
-+   and.2\\t%0, %2, %1
-+   and.2\\t%0, %1, %2")
-+
-+(define_insn "andhi3_and2_ccszn_null"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (and:HI (match_operand:HI 0 "nonimmediate_operand"    "%d,rm")
-+                (match_operand:HI 1 "ubicom32_arith_operand" "rmI, d"))
-+        (const_int 0)))]
-+  "ubicom32_match_cc_mode(insn, CCSZNmode)"
-+  "@
-+   and.2\\t#0, %1, %0
-+   and.2\\t#0, %0, %1")
-+
-+(define_insn "and2_ccszn_null_1"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (subreg:HI
-+          (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d")
-+                  (match_operand:SI 1 "ubicom32_arith_operand"         "rI"))
-+          2)
-+        (const_int 0)))]
-+  "ubicom32_match_cc_mode(insn, CCSZNmode)"
-+  "and.2\\t#0, %1, %0")
-+
-+(define_insn "and2_ccszn_null_2"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (subreg:HI
-+          (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d")
-+                  (subreg:SI
-+                    (match_operand:HI 1 "memory_operand"               "m")
-+                    0))
-+          2)
-+        (const_int 0)))]
-+  "ubicom32_match_cc_mode(insn, CCSZNmode)"
-+  "and.2\\t#0, %1, %0")
-+
-+(define_insn "and2_ccszn_null_3"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (subreg:HI
-+          (and:SI (subreg:SI
-+                    (match_operand:HI 0 "memory_operand"               "m")
-+                    0)
-+                  (match_operand:SI 1 "ubicom32_data_register_operand" "d"))
-+          2)
-+        (const_int 0)))]
-+  "ubicom32_match_cc_mode(insn, CCSZNmode)"
-+  "and.2\\t#0, %0, %1")
-+
-+(define_expand "andsi3"
-+  [(parallel
-+     [(set (match_operand:SI 0 "nonimmediate_operand" "")
-+         (and:SI (match_operand:SI 1 "nonimmediate_operand" "")
-+                 (match_operand:SI 2 "ubicom32_and_or_si3_operand" "")))
-+      (clobber (reg:CC CC_REGNO))])]
-+  ""
-+  "{
-+     do
-+       {
-+       /* Is this a bfextu?  */
-+       if (ubicom32_data_register_operand (operands[0], SImode)
-+           && CONST_INT_P (operands[2])
-+           && exact_log2 (INTVAL (operands[2]) + 1) != -1)
-+         break;
-+
-+       /* Is this a bclr?  */
-+       if (CONST_INT_P (operands[2])
-+           && exact_log2 (~INTVAL (operands[2])) != -1)
-+         break;
-+
-+       /* Must be an and.4  */
-+       if (!ubicom32_data_register_operand (operands[1], SImode))
-+         operands[1] = copy_to_mode_reg (SImode, operands[1]);
-+
-+       if (!ubicom32_arith_operand (operands[2], SImode))
-+         operands[2] = copy_to_mode_reg (SImode, operands[2]);
-+       }
-+     while (0);
-+   }")
-+
-+(define_insn "andsi3_bfextu"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
-+      (and:SI (match_operand:SI 1 "nonimmediate_operand"  "%rm")
-+              (match_operand:SI 2 "const_int_operand"       "O")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(satisfies_constraint_O (operands[2]))"
-+  "*
-+   {
-+     operands[3] = GEN_INT (exact_log2 (INTVAL (operands[2]) + 1));
-+
-+     return \"bfextu\\t%0, %1, %3\";
-+   }")
-+
-+(define_insn "andsi3_bfextu_ccwz"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (and:SI (match_operand:SI 1 "nonimmediate_operand" "%rm")
-+                (match_operand:SI 2 "const_int_operand"      "O"))
-+        (const_int 0)))
-+   (set (match_operand:SI 0 "ubicom32_data_register_operand"  "=d")
-+      (and:SI (match_dup 1)
-+              (match_dup 2)))]
-+  "(satisfies_constraint_O (operands[2])
-+    && ubicom32_match_cc_mode(insn, CCWZmode))"
-+  "*
-+   {
-+     operands[3] = GEN_INT (exact_log2 (INTVAL (operands[2]) + 1));
-+
-+     return \"bfextu\\t%0, %1, %3\";
-+   }")
-+
-+(define_insn "andsi3_bfextu_ccwz_null"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm")
-+                (match_operand:SI 1 "const_int_operand"      "O"))
-+        (const_int 0)))
-+   (clobber (match_scratch:SI 2                                     "=d"))]
-+  "(satisfies_constraint_O (operands[1])
-+    && ubicom32_match_cc_mode(insn, CCWZmode))"
-+  "*
-+   {
-+     operands[3] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1));
-+
-+     return \"bfextu\\t%2, %0, %3\";
-+   }")
-+
-+(define_insn "andsi3_bclr"
-+  [(set (match_operand:SI 0 "nonimmediate_operand"          "=rm")
-+      (and:SI (match_operand:SI 1 "ubicom32_arith_operand" "%rmI")
-+              (match_operand:SI 2 "const_int_operand"         "n")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(exact_log2 (~INTVAL (operands[2])) != -1)"
-+  "bclr\\t%0, %1, #%D2")
-+
-+(define_insn "andsi3_and4"
-+  [(set (match_operand:SI 0 "nonimmediate_operand"         "=rm,rm")
-+      (and:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
-+              (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "@
-+   and.4\\t%0, %2, %1
-+   and.4\\t%0, %1, %2")
-+
-+(define_insn "andsi3_and4_ccwzn"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (and:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
-+                (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))
-+        (const_int 0)))
-+   (set (match_operand:SI 0 "nonimmediate_operand"           "=rm,rm")
-+      (and:SI (match_dup 1)
-+              (match_dup 2)))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "@
-+   and.4\\t%0, %2, %1
-+   and.4\\t%0, %1, %2")
-+
-+(define_insn "andsi3_and4_ccwzn_null"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (and:SI (match_operand:SI 0 "nonimmediate_operand"    "%d,rm")
-+                (match_operand:SI 1 "ubicom32_arith_operand" "rmI, d"))
-+        (const_int 0)))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "@
-+   and.4\\t#0, %1, %0
-+   and.4\\t#0, %0, %1")
-+
-+(define_insn "andsi3_lsr4_ccwz_null"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm")
-+                (match_operand:SI 1 "const_int_operand"      "n"))
-+        (const_int 0)))
-+   (clobber (match_scratch:SI 2                                     "=d"))]
-+  "(exact_log2 ((~(INTVAL (operands[1]))) + 1) != -1
-+    && ubicom32_match_cc_mode(insn, CCWZmode))"
-+  "*
-+   {
-+     operands[3] = GEN_INT (exact_log2 ((~(INTVAL (operands[1]))) + 1));
-+
-+     return \"lsr.4\\t%2, %0, %3\";
-+   }")
-+
-+; We really would like the combiner to recognize this scenario and deal with
-+; it but unfortunately it tries to canonicalize zero_extract ops on MEMs
-+; into QImode operations and we can't match them in any useful way.
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "register_operand" "")
-+      (match_operand:SI 1 "const_int_operand" ""))
-+   (set (reg:CCWZ CC_REGNO)
-+      (compare:CCWZ
-+        (and:SI (match_operand:SI 2 "nonimmediate_operand" "")
-+                (match_dup 0))
-+        (const_int 0)))]
-+  "(exact_log2 (INTVAL (operands[1])) != -1
-+    && peep2_reg_dead_p (2, operands[0]))"
-+  [(set (reg:CCWZ CC_REGNO)
-+      (compare:CCWZ
-+        (zero_extract:SI
-+          (match_dup 2)
-+          (const_int 1)
-+          (match_dup 3))
-+        (const_int 0)))]
-+  "{
-+     operands[3] = GEN_INT (exact_log2 (INTVAL (operands[1])));
-+   }")
-+
-+(define_expand "anddi3"
-+  [(parallel
-+     [(set (match_operand:DI 0 "nonimmediate_operand" "")
-+         (and:DI (match_operand:DI 1 "nonimmediate_operand" "")
-+                 (match_operand:DI 2 "ubicom32_arith_operand" "")))
-+      (clobber (reg:CC CC_REGNO))])]
-+  ""
-+  "{
-+     /* If we have a non-data reg for operand 1 then prefer that over
-+        a CONST_INT in operand 2.  */
-+     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
-+       && CONST_INT_P (operands[2]))
-+       operands[2] = copy_to_mode_reg (DImode, operands[2]);
-+
-+     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
-+       operands[2] = copy_to_mode_reg (DImode, operands[2]);
-+   }")
-+
-+(define_insn_and_split "anddi3_and4"
-+  [(set (match_operand:DI 0 "nonimmediate_operand"         "=&r,&r,  d,rm,  m, m")
-+      (and:DI (match_operand:DI 1 "nonimmediate_operand"    "%d,rm,  0, 0,  d,rm")
-+              (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d,rmI, d,rmI, d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "#"
-+  "reload_completed"
-+  [(parallel [(set (match_dup 3)
-+                 (and:SI (match_dup 4)
-+                         (match_dup 5)))
-+            (clobber (reg:CC CC_REGNO))])
-+   (parallel [(set (match_dup 6)
-+                 (and:SI (match_dup 7)
-+                         (match_dup 8)))
-+            (clobber (reg:CC CC_REGNO))])]
-+  "{
-+     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" "8")])
-+
-+(define_expand "iorqi3"
-+  [(parallel
-+     [(set (match_operand:QI 0 "memory_operand" "")
-+         (ior:QI (match_operand:QI 1 "nonimmediate_operand" "")
-+                 (match_operand:QI 2 "ubicom32_arith_operand" "")))
-+      (clobber (reg:CC CC_REGNO))])]
-+  "(ubicom32_v4)"
-+  "{
-+     if (!memory_operand (operands[0], QImode))
-+       FAIL;
-+
-+     /* If we have a non-data reg for operand 1 then prefer that over
-+        a CONST_INT in operand 2.  */
-+     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
-+       && CONST_INT_P (operands[2]))
-+       operands[2] = copy_to_mode_reg (QImode, operands[2]);
-+
-+     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
-+       operands[2] = copy_to_mode_reg (QImode, operands[2]);
-+   }")
-+
-+(define_insn "iorqi3_or1"
-+  [(set (match_operand:QI 0 "memory_operand"                "=m, m")
-+      (ior:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
-+              (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(ubicom32_v4)"
-+  "@
-+   or.1\\t%0, %2, %1
-+   or.1\\t%0, %1, %2")
-+
-+(define_expand "iorhi3"
-+  [(parallel
-+     [(set (match_operand:HI 0 "memory_operand" "")
-+         (ior:HI (match_operand:HI 1 "nonimmediate_operand" "")
-+                 (match_operand:HI 2 "ubicom32_arith_operand" "")))
-+      (clobber (reg:CC CC_REGNO))])]
-+  ""
-+  "{
-+     if (!memory_operand (operands[0], HImode))
-+       FAIL;
-+
-+     /* If we have a non-data reg for operand 1 then prefer that over
-+        a CONST_INT in operand 2.  */
-+     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
-+       && CONST_INT_P (operands[2]))
-+       operands[2] = copy_to_mode_reg (HImode, operands[2]);
-+
-+     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
-+       operands[2] = copy_to_mode_reg (HImode, operands[2]);
-+   }")
-+
-+(define_insn "iorhi3_or2"
-+  [(set (match_operand:HI 0 "memory_operand"                "=m, m")
-+      (ior:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
-+              (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "@
-+   or.2\\t%0, %2, %1
-+   or.2\\t%0, %1, %2")
-+
-+(define_expand "iorsi3"
-+  [(parallel
-+     [(set (match_operand:SI 0 "nonimmediate_operand" "")
-+         (ior:SI (match_operand:SI 1 "nonimmediate_operand" "")
-+                 (match_operand:SI 2 "ubicom32_and_or_si3_operand" "")))
-+      (clobber (reg:CC CC_REGNO))])]
-+  ""
-+  "{
-+     do
-+       {
-+       /* Is this a bset?  */
-+       if (CONST_INT_P (operands[2])
-+           && exact_log2 (INTVAL (operands[2])) != -1)
-+         break;
-+
-+       /* Must be an or.4  */
-+       if (!ubicom32_data_register_operand (operands[1], SImode))
-+         operands[1] = copy_to_mode_reg (SImode, operands[1]);
-+
-+       if (!ubicom32_arith_operand (operands[2], SImode))
-+         operands[2] = copy_to_mode_reg (SImode, operands[2]);
-+       } 
-+     while (0);
-+   }")
-+
-+(define_insn "iorsi3_bset"
-+  [(set (match_operand:SI 0 "nonimmediate_operand"          "=rm")
-+      (ior:SI (match_operand:SI 1 "ubicom32_arith_operand" "%rmI")
-+              (match_operand 2 "const_int_operand"            "n")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(exact_log2 (INTVAL (operands[2])) != -1)"
-+  "bset\\t%0, %1, #%d2")
-+
-+(define_insn "iorsi3_or4"
-+  [(set (match_operand:SI 0 "nonimmediate_operand"         "=rm,rm")
-+      (ior:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
-+              (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "@
-+   or.4\\t%0, %2, %1
-+   or.4\\t%0, %1, %2")
-+
-+(define_insn "iorsi3_ccwzn"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (ior:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
-+                (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))
-+        (const_int 0)))
-+   (set (match_operand:SI 0 "nonimmediate_operand"           "=rm,rm")
-+      (ior:SI (match_dup 1)
-+              (match_dup 2)))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "@
-+   or.4\\t%0, %2, %1
-+   or.4\\t%0, %1, %2")
-+
-+(define_insn "iorsi3_ccwzn_null"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (ior:SI (match_operand:SI 0 "nonimmediate_operand"    "%d,rm")
-+                (match_operand:SI 1 "ubicom32_arith_operand" "rmI, d"))
-+        (const_int 0)))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "@
-+   or.4\\t#0, %1, %0
-+   or.4\\t#0, %0, %1")
-+
-+(define_expand "iordi3"
-+  [(parallel
-+     [(set (match_operand:DI 0 "nonimmediate_operand" "")
-+         (ior:DI (match_operand:DI 1 "nonimmediate_operand" "")
-+                 (match_operand:DI 2 "ubicom32_arith_operand" "")))
-+      (clobber (reg:CC CC_REGNO))])]
-+  ""
-+  "{
-+     /* If we have a non-data reg for operand 1 then prefer that over
-+        a CONST_INT in operand 2.  */
-+     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
-+       && CONST_INT_P (operands[2]))
-+       operands[2] = copy_to_mode_reg (DImode, operands[2]);
-+
-+     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
-+       operands[2] = copy_to_mode_reg (DImode, operands[2]);
-+   }")
-+
-+(define_insn_and_split "iordi3_or4"
-+  [(set (match_operand:DI 0 "nonimmediate_operand"         "=&r,&r,  d,rm,  m, m")
-+      (ior:DI (match_operand:DI 1 "nonimmediate_operand"    "%d,rm,  0, 0,  d,rm")
-+              (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d,rmI, d,rmI, d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "#"
-+  "reload_completed"
-+  [(parallel [(set (match_dup 3)
-+                 (ior:SI (match_dup 4)
-+                         (match_dup 5)))
-+            (clobber (reg:CC CC_REGNO))])
-+   (parallel [(set (match_dup 6)
-+                 (ior:SI (match_dup 7)
-+                         (match_dup 8)))
-+            (clobber (reg:CC CC_REGNO))])]
-+  "{
-+     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" "8")])
-+
-+(define_expand "xorqi3"
-+  [(parallel
-+     [(set (match_operand:QI 0 "memory_operand" "")
-+         (xor:QI (match_operand:QI 1 "nonimmediate_operand" "")
-+                 (match_operand:QI 2 "ubicom32_arith_operand" "")))
-+      (clobber (reg:CC CC_REGNO))])]
-+  "(ubicom32_v4)"
-+  "{
-+     if (!memory_operand (operands[0], QImode))
-+       FAIL;
-+
-+     /* If we have a non-data reg for operand 1 then prefer that over
-+        a CONST_INT in operand 2.  */
-+     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
-+       && CONST_INT_P (operands[2]))
-+       operands[2] = copy_to_mode_reg (QImode, operands[2]);
-+
-+     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
-+       operands[2] = copy_to_mode_reg (QImode, operands[2]);
-+   }")
-+
-+(define_insn "xorqi3_xor1"
-+  [(set (match_operand:QI 0 "memory_operand"                "=m, m")
-+      (xor:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
-+              (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(ubicom32_v4)"
-+  "@
-+   xor.1\\t%0, %2, %1
-+   xor.1\\t%0, %1, %2")
-+
-+(define_insn "xorqi3_xor1_ccszn"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (xor:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
-+                (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d"))
-+        (const_int 0)))
-+   (set (match_operand:QI 0 "memory_operand"                  "=m, m")
-+      (xor:QI (match_dup 1)
-+              (match_dup 2)))]
-+  "(ubicom32_v4
-+    && ubicom32_match_cc_mode(insn, CCSZNmode))"
-+  "@
-+   xor.1\\t%0, %2, %1
-+   xor.1\\t%0, %1, %2")
-+
-+(define_insn "xorqi3_xor1_ccszn_null"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (xor:QI (match_operand:QI 0 "nonimmediate_operand"    "%d,rm")
-+                (match_operand:QI 1 "ubicom32_arith_operand" "rmI, d"))
-+        (const_int 0)))]
-+  "(ubicom32_v4
-+    && ubicom32_match_cc_mode(insn, CCSZNmode))"
-+  "@
-+   xor.1\\t#0, %1, %0
-+   xor.1\\t#0, %0, %1")
-+
-+(define_insn "xor1_ccszn_null_1"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (subreg:QI
-+          (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d")
-+                  (match_operand:SI 1 "ubicom32_arith_operand"         "rI"))
-+          3)
-+        (const_int 0)))]
-+  "(ubicom32_v4
-+    && ubicom32_match_cc_mode(insn, CCSZNmode))"
-+  "xor.1\\t#0, %1, %0")
-+
-+(define_insn "xor1_ccszn_null_2"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (subreg:QI
-+          (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d")
-+                  (subreg:SI
-+                    (match_operand:QI 1 "memory_operand"               "m")
-+                    0))
-+          3)
-+        (const_int 0)))]
-+  "(ubicom32_v4
-+    && ubicom32_match_cc_mode(insn, CCSZNmode))"
-+  "xor.1\\t#0, %1, %0")
-+
-+(define_insn "xor1_ccwzn_null_3"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (subreg:QI
-+          (xor:SI (subreg:SI
-+                    (match_operand:QI 0 "memory_operand"               "m")
-+                    0)
-+                  (match_operand:SI 1 "ubicom32_data_register_operand" "d"))
-+          3)
-+        (const_int 0)))]
-+  "(ubicom32_v4
-+    && ubicom32_match_cc_mode(insn, CCSZNmode))"
-+  "xor.1\\t#0, %0, %1")
-+
-+(define_expand "xorhi3"
-+  [(parallel
-+     [(set (match_operand:HI 0 "memory_operand" "")
-+         (xor:HI (match_operand:HI 1 "nonimmediate_operand" "")
-+                 (match_operand:HI 2 "ubicom32_arith_operand" "")))
-+      (clobber (reg:CC CC_REGNO))])]
-+  ""
-+  "{
-+     if (!memory_operand (operands[0], HImode))
-+       FAIL;
-+
-+     /* If we have a non-data reg for operand 1 then prefer that over
-+        a CONST_INT in operand 2.  */
-+     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
-+       && CONST_INT_P (operands[2]))
-+       operands[2] = copy_to_mode_reg (HImode, operands[2]);
-+
-+     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
-+       operands[2] = copy_to_mode_reg (HImode, operands[2]);
-+   }")
-+
-+(define_insn "xorhi3_xor2"
-+  [(set (match_operand:HI 0 "memory_operand"                "=m, m")
-+      (xor:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
-+              (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "@
-+   xor.2\\t%0, %2, %1
-+   xor.2\\t%0, %1, %2")
-+
-+(define_insn "xorhi3_xor2_ccszn"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (xor:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
-+                (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d"))
-+        (const_int 0)))
-+   (set (match_operand:HI 0 "memory_operand"                  "=m, m")
-+      (xor:HI (match_dup 1)
-+              (match_dup 2)))]
-+  "ubicom32_match_cc_mode(insn, CCSZNmode)"
-+  "@
-+   xor.2\\t%0, %2, %1
-+   xor.2\\t%0, %1, %2")
-+
-+(define_insn "xorhi3_xor2_ccszn_null"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (xor:HI (match_operand:HI 0 "nonimmediate_operand"    "%d,rm")
-+                (match_operand:HI 1 "ubicom32_arith_operand" "rmI, d"))
-+        (const_int 0)))]
-+  "ubicom32_match_cc_mode(insn, CCSZNmode)"
-+  "@
-+   xor.2\\t#0, %1, %0
-+   xor.2\\t#0, %0, %1")
-+
-+(define_insn "xor2_ccszn_null_1"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (subreg:HI
-+          (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d")
-+                  (match_operand:SI 1 "ubicom32_arith_operand"         "rI"))
-+          2)
-+        (const_int 0)))]
-+  "ubicom32_match_cc_mode(insn, CCSZNmode)"
-+  "xor.2\\t#0, %1, %0")
-+
-+(define_insn "xor2_ccszn_null_2"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (subreg:HI
-+          (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d")
-+                  (subreg:SI
-+                    (match_operand:HI 1 "memory_operand"               "m")
-+                    0))
-+          2)
-+        (const_int 0)))]
-+  "ubicom32_match_cc_mode(insn, CCSZNmode)"
-+  "xor.2\\t#0, %1, %0")
-+
-+(define_insn "xor2_ccszn_null_3"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (subreg:HI
-+          (xor:SI (subreg:SI
-+                    (match_operand:HI 0 "memory_operand"               "m")
-+                    0)
-+                  (match_operand:SI 1 "ubicom32_data_register_operand" "d"))
-+          2)
-+        (const_int 0)))]
-+  "ubicom32_match_cc_mode(insn, CCSZNmode)"
-+  "xor.2\\t#0, %0, %1")
-+
-+(define_insn "xorsi3"
-+  [(set (match_operand:SI 0 "nonimmediate_operand"         "=rm,rm")
-+      (xor:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
-+              (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "@
-+   xor.4\\t%0, %2, %1
-+   xor.4\\t%0, %1, %2")
-+
-+(define_insn "xorsi3_ccwzn"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (xor:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
-+                (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))
-+        (const_int 0)))
-+   (set (match_operand:SI 0 "nonimmediate_operand"           "=rm,rm")
-+      (xor:SI (match_dup 1)
-+              (match_dup 2)))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "@
-+   xor.4\\t%0, %2, %1
-+   xor.4\\t%0, %1, %2")
-+
-+(define_insn "xorsi3_ccwzn_null"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (xor:SI (match_operand:SI 0 "nonimmediate_operand"    "%d,rm")
-+                (match_operand:SI 1 "ubicom32_arith_operand" "rmI, d"))
-+        (const_int 0)))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "@
-+   xor.4\\t#0, %1, %0
-+   xor.4\\t#0, %0, %1")
-+
-+(define_expand "xordi3"
-+  [(parallel
-+     [(set (match_operand:DI 0 "nonimmediate_operand" "")
-+         (xor:DI (match_operand:DI 1 "nonimmediate_operand" "")
-+                 (match_operand:DI 2 "ubicom32_arith_operand" "")))
-+      (clobber (reg:CC CC_REGNO))])]
-+  ""
-+  "{
-+     /* If we have a non-data reg for operand 1 then prefer that over
-+        a CONST_INT in operand 2.  */
-+     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
-+       && CONST_INT_P (operands[2]))
-+       operands[2] = copy_to_mode_reg (DImode, operands[2]);
-+
-+     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
-+       operands[2] = copy_to_mode_reg (DImode, operands[2]);
-+   }")
-+
-+(define_insn_and_split "xordi3_xor4"
-+  [(set (match_operand:DI 0 "nonimmediate_operand"         "=&r,&r,  d,rm,  m, m")
-+      (xor:DI (match_operand:DI 1 "nonimmediate_operand"    "%d,rm,  0, 0,  d,rm")
-+              (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d,rmI, d,rmI, d")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "#"
-+  "reload_completed"
-+  [(parallel [(set (match_dup 3)
-+                 (xor:SI (match_dup 4)
-+                         (match_dup 5)))
-+            (clobber (reg:CC CC_REGNO))])
-+   (parallel [(set (match_dup 6)
-+                 (xor:SI (match_dup 7)
-+                         (match_dup 8)))
-+            (clobber (reg:CC CC_REGNO))])]
-+  "{
-+     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" "8")])
-+
-+(define_insn "not2_2"
-+  [(set (match_operand:HI 0 "memory_operand"                  "=m")
-+      (subreg:HI
-+        (not:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI"))
-+        2))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "not.2\\t%0, %1")
-+
-+(define_insn "one_cmplsi2"
-+  [(set (match_operand:SI 0 "nonimmediate_operand"         "=rm")
-+      (not:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "not.4\\t%0, %1")
-+
-+(define_insn "one_cmplsi2_ccwzn"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (not:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI"))
-+        (const_int 0)))
-+   (set (match_operand:SI 0 "nonimmediate_operand"           "=rm")
-+      (not:SI (match_dup 1)))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "not.4\\t%0, %1")
-+
-+(define_insn "one_cmplsi2_ccwzn_null"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (not:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmI"))
-+        (const_int 0)))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "not.4\\t#0, %0")
-+
-+(define_insn_and_split "one_cmpldi2"
-+  [(set (match_operand:DI 0 "nonimmediate_operand"       "=&rm")
-+      (not:DI (match_operand:DI 1 "nonimmediate_operand" "rmI0")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "#"
-+  ""
-+  [(parallel [(set (match_dup 2)
-+                 (not:SI (match_dup 3)))
-+            (clobber (reg:CC CC_REGNO))])
-+   (parallel [(set (match_dup 4)
-+                 (not:SI (match_dup 5)))
-+            (clobber (reg:CC CC_REGNO))])]
-+  "{
-+     operands[2] = gen_lowpart (SImode, operands[0]);
-+     operands[3] = gen_lowpart (SImode, operands[1]);
-+     operands[4] = gen_highpart (SImode, operands[0]);
-+     operands[5] = gen_highpart (SImode, operands[1]);
-+   }"
-+  [(set_attr "length" "8")])
-+
-+; Conditional jump instructions
-+
-+(define_expand "beq"
-+  [(set (pc)
-+      (if_then_else (eq (match_dup 1)
-+                        (const_int 0))
-+                    (label_ref (match_operand 0 "" ""))
-+                    (pc)))]
-+  ""
-+  "{
-+     operands[1] = ubicom32_gen_compare_reg (EQ, ubicom32_compare_op0,
-+                                           ubicom32_compare_op1);
-+   }")
-+
-+(define_expand "bne"
-+  [(set (pc)
-+      (if_then_else (ne (match_dup 1)
-+                        (const_int 0))
-+                    (label_ref (match_operand 0 "" ""))
-+                    (pc)))]
-+  ""
-+  "{
-+     operands[1] = ubicom32_gen_compare_reg (NE, ubicom32_compare_op0,
-+                                           ubicom32_compare_op1);
-+   }")
-+
-+(define_expand "bgt"
-+  [(set (pc)
-+      (if_then_else (gt (match_dup 1)
-+                        (const_int 0))
-+                    (label_ref (match_operand 0 "" ""))
-+                    (pc)))]
-+  ""
-+  "{
-+     operands[1] = ubicom32_gen_compare_reg (GT, ubicom32_compare_op0,
-+                                           ubicom32_compare_op1);
-+   }")
-+
-+(define_expand "ble"
-+  [(set (pc)
-+      (if_then_else (le (match_dup 1)
-+                        (const_int 0))
-+                    (label_ref (match_operand 0 "" ""))
-+                    (pc)))]
-+  ""
-+  "{
-+     operands[1] = ubicom32_gen_compare_reg (LE, ubicom32_compare_op0,
-+                                           ubicom32_compare_op1);
-+   }")
-+
-+(define_expand "bge"
-+  [(set (pc)
-+      (if_then_else (ge (match_dup 1)
-+                        (const_int 0))
-+                    (label_ref (match_operand 0 "" ""))
-+                    (pc)))]
-+  ""
-+  "{
-+     operands[1] = ubicom32_gen_compare_reg (GE, ubicom32_compare_op0,
-+                                           ubicom32_compare_op1);
-+   }")
-+
-+(define_expand "blt"
-+  [(set (pc)
-+      (if_then_else (lt (match_dup 1)
-+                        (const_int 0))
-+                    (label_ref (match_operand 0 "" ""))
-+                    (pc)))]
-+  ""
-+  "{
-+     operands[1] = ubicom32_gen_compare_reg (LT, ubicom32_compare_op0,
-+                                           ubicom32_compare_op1);
-+   }")
-+
-+(define_expand "bgtu"
-+  [(set (pc)
-+      (if_then_else (gtu (match_dup 1)
-+                         (const_int 0))
-+                    (label_ref (match_operand 0 "" ""))
-+                    (pc)))]
-+  ""
-+  "{
-+     operands[1] = ubicom32_gen_compare_reg (GTU, ubicom32_compare_op0,
-+                                           ubicom32_compare_op1);
-+   }")
-+
-+(define_expand "bleu"
-+  [(set (pc)
-+      (if_then_else (leu (match_dup 1)
-+                         (const_int 0))
-+                    (label_ref (match_operand 0 "" ""))
-+                    (pc)))]
-+  ""
-+  "{
-+     operands[1] = ubicom32_gen_compare_reg (LEU, ubicom32_compare_op0,
-+                                           ubicom32_compare_op1);
-+   }")
-+
-+(define_expand "bgeu"
-+  [(set (pc)
-+      (if_then_else (geu (match_dup 1)
-+                         (const_int 0))
-+                    (label_ref (match_operand 0 "" ""))
-+                    (pc)))]
-+  ""
-+  "{
-+     operands[1] = ubicom32_gen_compare_reg (GEU, ubicom32_compare_op0,
-+                                           ubicom32_compare_op1);
-+   }")
-+
-+(define_expand "bltu"
-+  [(set (pc)
-+      (if_then_else (ltu (match_dup 1)
-+                         (const_int 0))
-+                    (label_ref (match_operand 0 "" ""))
-+                    (pc)))]
-+  ""
-+  "{
-+     operands[1] = ubicom32_gen_compare_reg (LTU, ubicom32_compare_op0,
-+                                           ubicom32_compare_op1);
-+   }")
-+
-+(define_insn "jcc"
-+  [(set (pc)
-+      (if_then_else (match_operator 1 "comparison_operator"
-+                      [(match_operand 2 "ubicom32_cc_register_operand" "")
-+                       (const_int 0)])
-+                    (label_ref (match_operand 0 "" ""))
-+                    (pc)))]
-+  ""
-+  "*
-+   {
-+     ubicom32_output_cond_jump (insn, operands[1], operands[0]);
-+     return \"\";
-+   }")
-+
-+; Reverse branch - reverse our comparison condition so that we can
-+; branch in the opposite sense.
-+;
-+(define_insn_and_split "jcc_reverse"
-+  [(set (pc)
-+      (if_then_else (match_operator 1 "comparison_operator"
-+                      [(match_operand 2 "ubicom32_cc_register_operand" "")
-+                       (const_int 0)])
-+                    (pc)
-+                    (label_ref (match_operand 0 "" ""))))]
-+  ""
-+  "#"
-+  "reload_completed"
-+  [(set (pc)
-+      (if_then_else (match_dup 3)
-+                    (label_ref (match_dup 0))
-+                    (pc)))]
-+  "{
-+     rtx cc_reg;
-+
-+     cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
-+     operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[1])),
-+                                 GET_MODE (operands[1]),
-+                                 cc_reg,
-+                                 const0_rtx);
-+   }")
-+
-+(define_insn "jump"
-+  [(set (pc)
-+      (label_ref (match_operand 0 "" "")))]
-+  ""
-+  "jmpt\\t%l0")
-+
-+(define_expand "indirect_jump"
-+  [(parallel [(set (pc)
-+                 (match_operand:SI 0 "register_operand" ""))
-+            (clobber (match_dup 0))])]
-+  ""
-+  "")
-+
-+(define_insn "indirect_jump_internal"
-+  [(set (pc)
-+      (match_operand:SI 0 "register_operand" "a"))
-+  (clobber (match_dup 0))]
-+  ""
-+  "calli\\t%0,0(%0)")
-+
-+; Program Space: The table contains instructions, typically jumps. 
-+; CALL An,TABLE_SIZE(PC)      ;An = Jump Table Base Address. 
-+; <Jump Table is Here>        ;An -> Here. 
-+; LEA Ak, (An,Dn)     ;Ak -> Table Entry
-+; JMP/CALL (Ak) 
-+
-+(define_expand "tablejump"
-+  [(parallel [(set (pc)
-+                 (match_operand:SI 0 "nonimmediate_operand" ""))
-+            (use (label_ref (match_operand 1 "" "")))])]
-+  ""
-+  "")
-+
-+(define_insn "tablejump_internal"
-+  [(set (pc)
-+      (match_operand:SI 0 "nonimmediate_operand" "rm"))
-+   (use (label_ref (match_operand 1 "" "")))]
-+  ""
-+  "ret\\t%0")
-+
-+; Call subroutine with no return value.
-+;
-+(define_expand "call"
-+  [(call (match_operand:QI 0 "general_operand" "")
-+       (match_operand:SI 1 "general_operand" ""))]
-+  ""
-+  "{
-+     if (TARGET_FDPIC)
-+       {
-+       ubicom32_expand_call_fdpic (operands);
-+       DONE;
-+       }
-+
-+     if (! ubicom32_call_address_operand (XEXP (operands[0], 0), VOIDmode))
-+       XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
-+   }")
-+
-+; We expand to a simple form that doesn't clobber the link register and
-+; then split to a form that does.  This allows the RTL optimizers that
-+; run before the splitter to have the opportunity to eliminate the call
-+; without marking A5 as being clobbered and this in turn avoids saves
-+; and returns in a number of cases.
-+;
-+(define_insn_and_split "call_1"
-+  [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
-+       (match_operand:SI 1 "general_operand"                       "g,g"))]
-+  "! TARGET_FDPIC"
-+  "#"
-+  ""
-+  [(parallel
-+     [(call (mem:QI (match_dup 0))
-+          (match_dup 1))
-+      (clobber (reg:SI LINK_REGNO))])]
-+  "")
-+
-+(define_insn "call_slow"
-+  [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
-+       (match_operand:SI 1 "general_operand"                       "g,g"))
-+   (clobber (reg:SI LINK_REGNO))]
-+  "(! TARGET_FDPIC && ! TARGET_FASTCALL)"
-+  "@
-+   calli\\ta5, 0(%0)
-+   moveai\\ta5, #%%hi(%C0)\;calli\\ta5, %%lo(%C0)(a5)")
-+
-+(define_insn "call_fast"
-+  [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
-+       (match_operand:SI 1 "general_operand"                       "g,g"))
-+   (clobber (reg:SI LINK_REGNO))]
-+  "(! TARGET_FDPIC && TARGET_FASTCALL)"
-+  "@
-+   calli\\ta5, 0(%0)
-+   call\\ta5, %C0")
-+
-+; We expand to a simple form that doesn't clobber the link register and
-+; then split to a form that does.  This allows the RTL optimizers that
-+; run before the splitter to have the opportunity to eliminate the call
-+; without marking A5 as being clobbered and this in turn avoids saves
-+; and returns in a number of cases.
-+;
-+(define_insn_and_split "call_fdpic"
-+  [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
-+       (match_operand:SI 1 "general_operand"                       "g,g"))
-+   (use (match_operand:SI 2 "ubicom32_fdpic_operand"               "Z,Z"))]
-+  "TARGET_FDPIC"
-+  "#"
-+  ""
-+  [(parallel
-+     [(call (mem:QI (match_dup 0))
-+          (match_dup 1))
-+      (use (match_dup 2))
-+      (clobber (reg:SI LINK_REGNO))])]
-+  "")
-+
-+(define_insn "call_fdpic_clobber"
-+  [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
-+       (match_operand:SI 1 "general_operand"                       "g,g"))
-+   (use (match_operand:SI 2 "ubicom32_fdpic_operand"               "Z,Z"))
-+   (clobber (reg:SI LINK_REGNO))]
-+  "TARGET_FDPIC"
-+  "@
-+   move.4\\ta5, 0(%0)\;move.4\\t%2, 4(%0)\;calli\\ta5, 0(a5)
-+   call\\ta5, %C0")
-+
-+; Call subroutine, returning value in operand 0
-+; (which must be a hard register).
-+;
-+(define_expand "call_value"
-+  [(set (match_operand 0 "" "")
-+      (call (match_operand:QI 1 "general_operand" "")
-+            (match_operand:SI 2 "general_operand" "")))]
-+  ""
-+  "{
-+     if (TARGET_FDPIC)
-+       {
-+       ubicom32_expand_call_value_fdpic (operands);
-+       DONE;
-+       }
-+
-+     if (! ubicom32_call_address_operand (XEXP (operands[1], 0), VOIDmode))
-+       XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
-+   }")
-+
-+; We expand to a simple form that doesn't clobber the link register and
-+; then split to a form that does.  This allows the RTL optimizers that
-+; run before the splitter to have the opportunity to eliminate the call
-+; without marking A5 as being clobbered and this in turn avoids saves
-+; and returns in a number of cases.
-+;
-+(define_insn_and_split "call_value_1"
-+  [(set (match_operand 0 "register_operand"                            "=r,r")
-+      (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
-+            (match_operand:SI 2 "general_operand"                       "g,g")))]
-+  "! TARGET_FDPIC"
-+  "#"
-+  ""
-+  [(parallel
-+     [(set (match_dup 0)
-+         (call (mem:QI (match_dup 1))
-+               (match_dup 2)))
-+      (clobber (reg:SI LINK_REGNO))])]
-+  "")
-+
-+(define_insn "call_value_slow"
-+  [(set (match_operand 0 "register_operand"                            "=r,r")
-+      (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
-+            (match_operand:SI 2 "general_operand"                       "g,g")))
-+   (clobber (reg:SI LINK_REGNO))]
-+  "(! TARGET_FDPIC && ! TARGET_FASTCALL)"
-+  "@
-+   calli\\ta5, 0(%1)
-+   moveai\\ta5, #%%hi(%C1)\;calli\\ta5, %%lo(%C1)(a5)")
-+
-+(define_insn "call_value_fast"
-+  [(set (match_operand 0 "register_operand"                            "=r,r")
-+      (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
-+            (match_operand:SI 2 "general_operand"                       "g,g")))
-+   (clobber (reg:SI LINK_REGNO))]
-+  "(! TARGET_FDPIC && TARGET_FASTCALL)"
-+  "@
-+   calli\\ta5, 0(%1)
-+   call\\ta5, %C1")
-+
-+; We expand to a simple form that doesn't clobber the link register and
-+; then split to a form that does.  This allows the RTL optimizers that
-+; run before the splitter to have the opportunity to eliminate the call
-+; without marking A5 as being clobbered and this in turn avoids saves
-+; and returns in a number of cases.
-+;
-+(define_insn_and_split "call_value_fdpic"
-+  [(set (match_operand 0 "register_operand"                            "=r,r")
-+      (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
-+            (match_operand:SI 2 "general_operand"                       "g,g")))
-+   (use (match_operand:SI 3 "ubicom32_fdpic_operand"                    "Z,Z"))]
-+  "TARGET_FDPIC"
-+  "#"
-+  ""
-+  [(parallel
-+     [(set (match_dup 0)
-+         (call (mem:QI (match_dup 1))
-+               (match_dup 2)))
-+      (use (match_dup 3))
-+      (clobber (reg:SI LINK_REGNO))])]
-+  "")
-+
-+(define_insn "call_value_fdpic_clobber"
-+  [(set (match_operand 0 "register_operand"                            "=r,r")
-+      (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
-+            (match_operand:SI 2 "general_operand"                       "g,g")))
-+   (use (match_operand:SI 3 "ubicom32_fdpic_operand"                    "Z,Z"))
-+   (clobber (reg:SI LINK_REGNO))]
-+  "TARGET_FDPIC"
-+  "@
-+   move.4\\ta5, 0(%1)\;move.4\\t%3, 4(%1)\;calli\\ta5, 0(a5)
-+   call\\ta5, %C1")
-+
-+(define_expand "untyped_call"
-+  [(parallel [(call (match_operand 0 "" "")
-+                    (const_int 0))
-+              (match_operand 1 "" "")
-+              (match_operand 2 "" "")])]
-+  ""
-+  "{
-+     int i;
-+
-+     emit_call_insn (gen_call (operands[0], const0_rtx));
-+
-+     for (i = 0; i < XVECLEN (operands[2], 0); i++)
-+       {
-+         rtx set = XVECEXP (operands[2], 0, i);
-+         emit_move_insn (SET_DEST (set), SET_SRC (set));
-+       }
-+     DONE;
-+   }")
-+
-+(define_insn "lsl1_1"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
-+      (ashift:SI (subreg:SI
-+                   (match_operand:QI 1 "memory_operand"         "m")
-+                   0)
-+                 (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(ubicom32_v4)"
-+  "lsl.1\\t%0, %1, %2")
-+
-+; The combiner gets rather creative about left shifts of sub-word memory
-+; operands because it's uncertain about whether the memory is sign or
-+; zero extended.  It only wants zero-extended behaviour and so throws
-+; in an extra and operation.
-+;
-+(define_insn "lsl1_2"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
-+      (and:SI
-+        (ashift:SI (subreg:SI
-+                     (match_operand:QI 1 "memory_operand"   "m")
-+                     0)
-+                   (match_operand:SI 2 "const_int_operand"  "M"))
-+        (match_operand:SI 3 "const_int_operand"             "n")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(ubicom32_v4
-+    && INTVAL (operands[3]) == (0xff << INTVAL (operands[2])))"
-+  "lsl.1\\t%0, %1, %2")
-+
-+(define_insn "lsl2_1"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
-+      (ashift:SI (subreg:SI
-+                   (match_operand:HI 1 "memory_operand"         "m")
-+                   0)
-+                 (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(ubicom32_v4)"
-+  "lsl.2\\t%0, %1, %2")
-+
-+; The combiner gets rather creative about left shifts of sub-word memory
-+; operands because it's uncertain about whether the memory is sign or
-+; zero extended.  It only wants zero-extended behaviour and so throws
-+; in an extra and operation.
-+;
-+(define_insn "lsl2_2"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
-+      (and:SI
-+        (ashift:SI (subreg:SI
-+                     (match_operand:HI 1 "memory_operand"   "m")
-+                     0)
-+                   (match_operand:SI 2 "const_int_operand"  "M"))
-+        (match_operand:SI 3 "const_int_operand"             "n")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(ubicom32_v4
-+    && INTVAL (operands[3]) == (0xffff << INTVAL (operands[2])))"
-+  "lsl.2\\t%0, %1, %2")
-+
-+(define_insn "ashlsi3"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
-+      (ashift:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
-+                 (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "lsl.4\\t%0, %1, %2")
-+
-+(define_insn "lshlsi3_ccwz"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (ashift:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
-+                   (match_operand:SI 2 "ubicom32_arith_operand"  "dM"))
-+        (const_int 0)))
-+   (set (match_operand:SI 0 "ubicom32_data_register_operand"     "=d")
-+      (ashift:SI (match_dup 1)
-+                 (match_dup 2)))]
-+  "ubicom32_match_cc_mode(insn, CCWZmode)"
-+  "lsl.4\\t%0, %1, %2")
-+
-+(define_insn "lshlsi3_ccwz_null"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (ashift:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmI")
-+                   (match_operand:SI 1 "ubicom32_arith_operand"  "dM"))
-+        (const_int 0)))
-+   (clobber (match_scratch:SI 2                                          "=d"))]
-+  "ubicom32_match_cc_mode(insn, CCWZmode)"
-+  "lsl.4\\t%2, %0, %1")
-+
-+; The combiner finds this canonical form for what is in essence a right
-+; shift.
-+;
-+(define_insn "asr1_2"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
-+      (sign_extract:SI (match_operand:QI 1 "memory_operand"     "m")
-+                       (match_operand:SI 2 "const_int_operand"  "M")
-+                       (match_operand:SI 3 "const_int_operand"  "M")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(ubicom32_v4
-+    && (INTVAL (operands[2]) + INTVAL (operands[3]) == 8))"
-+  "asr.1\\t%0, %1, %3")
-+
-+; The combiner finds this canonical form for what is in essence a right
-+; shift.
-+;
-+(define_insn "asr2_2"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
-+      (sign_extract:SI (match_operand:HI 1 "memory_operand"     "m")
-+                       (match_operand:SI 2 "const_int_operand"  "M")
-+                       (match_operand:SI 3 "const_int_operand"  "M")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(ubicom32_v4
-+    && (INTVAL (operands[2]) + INTVAL (operands[3]) == 16))"
-+  "asr.2\\t%0, %1, %3")
-+
-+(define_insn "ashrsi3"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand"     "=d")
-+      (ashiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmJ")
-+                   (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "asr.4\\t%0, %1, %2")
-+
-+(define_insn "ashrsi3_ccwzn"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (ashiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmJ")
-+                     (match_operand:SI 2 "ubicom32_arith_operand"  "dM"))
-+        (const_int 0)))
-+   (set (match_operand:SI 0 "ubicom32_data_register_operand"       "=d")
-+      (ashiftrt:SI (match_dup 1)
-+                   (match_dup 2)))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "asr.4\\t%0, %1, %2")
-+
-+(define_insn "ashrsi3_ccwzn_null"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (ashiftrt:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmJ")
-+                     (match_operand:SI 1 "ubicom32_arith_operand"  "dM"))
-+        (const_int 0)))
-+   (clobber (match_scratch:SI 2                                            "=d"))]
-+  "ubicom32_match_cc_mode(insn, CCWZNmode)"
-+  "asr.4\\t%2, %0, %1")
-+
-+(define_insn "lsr1_1"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
-+      (lshiftrt:SI (subreg:SI
-+                     (match_operand:QI 1 "memory_operand"       "m")
-+                     0)
-+                 (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(ubicom32_v4)"
-+  "lsr.1\\t%0, %1, %2")
-+
-+; The combiner finds this canonical form for what is in essence a right
-+; shift.
-+;
-+(define_insn "lsr1_2"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
-+      (zero_extract:SI (match_operand:QI 1 "memory_operand"     "m")
-+                       (match_operand:SI 2 "const_int_operand"  "M")
-+                       (match_operand:SI 3 "const_int_operand"  "M")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(ubicom32_v4
-+    && (INTVAL (operands[2]) + INTVAL (operands[3]) == 8))"
-+  "lsr.1\\t%0, %1, %3")
-+
-+(define_insn "lsr2_1"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
-+      (lshiftrt:SI (subreg:SI
-+                     (match_operand:HI 1 "memory_operand"       "m")
-+                     0)
-+                 (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(ubicom32_v4)"
-+  "lsr.2\\t%0, %1, %2")
-+
-+; The combiner finds this canonical form for what is in essence a right
-+; shift.
-+;
-+(define_insn "lsr2_2"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
-+      (zero_extract:SI (match_operand:HI 1 "memory_operand"     "m")
-+                       (match_operand:SI 2 "const_int_operand"  "M")
-+                       (match_operand:SI 3 "const_int_operand"  "M")))
-+   (clobber (reg:CC CC_REGNO))]
-+  "(ubicom32_v4
-+    && (INTVAL (operands[2]) + INTVAL (operands[3]) == 16))"
-+  "lsr.2\\t%0, %1, %3")
-+
-+(define_insn "lshrsi3"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand"     "=d")
-+      (lshiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
-+                   (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "lsr.4\\t%0, %1, %2")
-+
-+(define_insn "lshrsi3_ccwz"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (lshiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
-+                     (match_operand:SI 2 "ubicom32_arith_operand"  "dM"))
-+        (const_int 0)))
-+   (set (match_operand:SI 0 "ubicom32_data_register_operand"       "=d")
-+      (lshiftrt:SI (match_dup 1)
-+                   (match_dup 2)))]
-+  "ubicom32_match_cc_mode(insn, CCWZmode)"
-+  "lsr.4\\t%0, %1, %2")
-+
-+(define_insn "lshrsi3_ccwz_null"
-+  [(set (reg CC_REGNO)
-+      (compare
-+        (lshiftrt:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmI")
-+                     (match_operand:SI 1 "ubicom32_arith_operand"  "dM"))
-+        (const_int 0)))
-+   (clobber (match_scratch:SI 2                                            "=d"))]
-+  "ubicom32_match_cc_mode(insn, CCWZmode)"
-+  "lsr.4\\t%2, %0, %1")
-+
-+(define_expand "prologue"
-+  [(const_int 0)]
-+  ""
-+  "{
-+     ubicom32_expand_prologue ();
-+     DONE;
-+   }")
-+
-+(define_expand "epilogue"
-+  [(return)]
-+  ""
-+  "{
-+     ubicom32_expand_epilogue ();
-+     DONE;
-+   }")
-+
-+(define_expand "return"
-+  [(return)]
-+  ""
-+  "{
-+     ubicom32_expand_epilogue ();
-+     DONE;
-+   }")
-+
-+(define_expand "_eh_return"
-+  [(use (match_operand:SI 0 "register_operand" "r"))
-+   (use (match_operand:SI 1 "register_operand" "r"))]
-+  ""
-+  "{
-+     ubicom32_expand_eh_return (operands);
-+     DONE;
-+   }")
-+
-+; XXX - it looks almost certain that we could make return_internal use a Dn
-+; register too.  In that instance we'd have to use a ret instruction
-+; rather than a calli but it might save cycles.
-+;
-+(define_insn "return_internal"
-+  [(const_int 2)
-+   (return)
-+   (use (match_operand:SI 0 "ubicom32_mem_or_address_register_operand" "rm"))]
-+  ""
-+  "*
-+   {
-+     if (REG_P (operands[0]) && REGNO (operands[0]) == LINK_REGNO
-+       && ubicom32_can_use_calli_to_ret)
-+       return \"calli\\t%0, 0(%0)\";
-+
-+     return \"ret\\t%0\";
-+   }")
-+
-+(define_insn "return_from_post_modify_sp"
-+  [(parallel
-+     [(const_int 2)
-+      (return)
-+      (use (mem:SI (post_modify:SI
-+                   (reg:SI SP_REGNO)
-+                   (plus:SI (reg:SI SP_REGNO)
-+                            (match_operand:SI 0 "const_int_operand" "n")))))])]
-+  "INTVAL (operands[0]) >= 4 && INTVAL (operands[0]) <= 7 * 4"
-+  "ret\\t(sp)%E0++")
-+
-+;(define_insn "eh_return_internal"
-+;  [(const_int 4)
-+;   (return)
-+;   (use (reg:SI 34))]
-+;  ""
-+;  "ret\\ta2")
-+
-+; No operation, needed in case the user uses -g but not -O.
-+(define_expand "nop"
-+  [(const_int 0)]
-+  ""
-+  "")
-+
-+(define_insn "nop_internal"
-+  [(const_int 0)]
-+  ""
-+  "nop")
-+
-+; The combiner will generate this pattern given shift and add operations.
-+; The canonical form that the combiner wants to use appears to be multiplies
-+; instead of shifts even if the compiled sources use shifts.
-+;
-+(define_insn "shmrg1_add"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand"         "=d")
-+      (plus:SI
-+        (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
-+                 (const_int 256))
-+        (zero_extend:SI
-+          (match_operand:QI 2 "ubicom32_arith_operand"              "rmI"))))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "shmrg.1\\t%0, %2, %1")
-+
-+; The combiner will generate this pattern given shift and or operations.
-+;
-+(define_insn "shmrg1_ior"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand"           "=d")
-+      (ior:SI
-+        (ashift:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
-+                   (const_int 8))
-+        (zero_extend:SI
-+          (match_operand:QI 2 "ubicom32_arith_operand"                "rmI"))))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "shmrg.1\\t%0, %2, %1")
-+
-+; The combiner will generate this pattern given shift and add operations.
-+; The canonical form that the combiner wants to use appears to be multiplies
-+; instead of shifts even if the compiled sources use shifts.
-+;
-+(define_insn "shmrg2_add"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand"         "=d")
-+      (plus:SI
-+        (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
-+                 (const_int 65536))
-+        (zero_extend:SI
-+          (match_operand:HI 2 "ubicom32_arith_operand"              "rmI"))))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "shmrg.2\\t%0, %2, %1")
-+
-+; The combiner will generate this pattern given shift and or operations.
-+;
-+(define_insn "shmrg2_ior"
-+  [(set (match_operand:SI 0 "ubicom32_data_register_operand"           "=d")
-+      (ior:SI
-+        (ashift:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
-+                   (const_int 16))
-+        (zero_extend:SI
-+          (match_operand:HI 2 "ubicom32_arith_operand"                "rmI"))))
-+   (clobber (reg:CC CC_REGNO))]
-+  ""
-+  "shmrg.2\\t%0, %2, %1")
-+
-+; Match the case where we load a word from the stack but then discard the
-+; upper 16 bits.  We turn this into a zero-extended load of that useful
-+; 16 bits direct from the stack where possible.
-+;
-+
-+; XXX - do these peephole2 ops actually work after the CCmode conversion?
-+(define_peephole2
-+  [(set (match_operand:SI 0 "register_operand" "")
-+      (mem:SI (plus:SI (reg:SI SP_REGNO)
-+                       (match_operand:SI 1 "const_int_operand" ""))))
-+   (set (match_operand:SI 2 "nonimmediate_operand" "")
-+      (zero_extend:SI (match_operand:HI 3 "register_operand" "")))]
-+  "(INTVAL (operands[1]) <= 252
-+    && REGNO (operands[3]) == REGNO (operands[0])
-+    && ((peep2_reg_dead_p (2, operands[0])
-+       && ! reg_mentioned_p (operands[0], operands[2]))
-+        || rtx_equal_p (operands[0], operands[2])))"
-+  [(set (match_dup 2)
-+      (zero_extend:SI (mem:HI (plus:SI (reg:SI SP_REGNO)
-+                                       (match_dup 4)))))]
-+  "{
-+     operands[4] = GEN_INT (INTVAL (operands[1]) + 2);
-+   }")
-+
-+; Match the case where we load a word from the stack but then discard the
-+; upper 16 bits.  We turn this into a 16-bit load of that useful
-+; 16 bits direct from the stack where possible.
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "register_operand" "")
-+      (mem:SI (plus:SI (reg:SI SP_REGNO)
-+                       (match_operand:SI 1 "const_int_operand" ""))))
-+   (set (match_operand:HI 2 "nonimmediate_operand" "")
-+      (match_operand:HI 3 "register_operand" ""))]
-+  "(INTVAL (operands[1]) <= 252
-+    && REGNO (operands[3]) == REGNO (operands[0])
-+    && ((peep2_reg_dead_p (2, operands[0])
-+       && ! reg_mentioned_p (operands[0], operands[2]))
-+        || rtx_equal_p (operands[0], operands[2])))"
-+  [(set (match_dup 2)
-+      (mem:HI (plus:SI (reg:SI SP_REGNO)
-+                       (match_dup 4))))]
-+  "{
-+     operands[4] = GEN_INT (INTVAL (operands[1]) + 2);
-+   }")
-+
-+; Match the case where we load a word from the stack but then discard the
-+; upper 24 bits.  We turn this into a zero-extended load of that useful
-+; 8 bits direct from the stack where possible.
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "register_operand" "")
-+      (mem:SI (plus:SI (reg:SI SP_REGNO)
-+                       (match_operand:SI 1 "const_int_operand" ""))))
-+   (set (match_operand:SI 2 "nonimmediate_operand" "")
-+      (zero_extend:SI (match_operand:QI 3 "register_operand" "")))]
-+  "(INTVAL (operands[1]) <= 124
-+    && REGNO (operands[3]) == REGNO (operands[0])
-+    && ((peep2_reg_dead_p (2, operands[0])
-+       && ! reg_mentioned_p (operands[0], operands[2]))
-+        || rtx_equal_p (operands[0], operands[2])))"
-+  [(set (match_dup 2)
-+      (zero_extend:SI (mem:QI (plus:SI (reg:SI SP_REGNO)
-+                                       (match_dup 4)))))]
-+  "{
-+     operands[4] = GEN_INT (INTVAL (operands[1]) + 3);
-+   }")
-+
-+; Match the case where we load a word from the stack but then discard the
-+; upper 24 bits.  We turn this into an 8-bit load of that useful
-+; 8 bits direct from the stack where possible.
-+;
-+(define_peephole2
-+  [(set (match_operand:SI 0 "register_operand" "")
-+      (mem:SI (plus:SI (reg:SI SP_REGNO)
-+                       (match_operand:SI 1 "const_int_operand" ""))))
-+   (set (match_operand:QI 2 "nonimmediate_operand" "")
-+      (match_operand:QI 3 "register_operand" ""))]
-+  "(INTVAL (operands[1]) <= 124
-+    && REGNO (operands[3]) == REGNO (operands[0])
-+    && ((peep2_reg_dead_p (2, operands[0])
-+       && ! reg_mentioned_p (operands[0], operands[2]))
-+        || rtx_equal_p (operands[0], operands[2])))"
-+  [(set (match_dup 2)
-+      (mem:QI (plus:SI (reg:SI SP_REGNO)
-+                       (match_dup 4))))]
-+  "{
-+     operands[4] = GEN_INT (INTVAL (operands[1]) + 3);
-+   }")
-+
---- /dev/null
-+++ b/gcc/config/ubicom32/ubicom32.opt
-@@ -0,0 +1,27 @@
-+mdebug-address
-+Target RejectNegative Report Undocumented Mask(DEBUG_ADDRESS)
-+Debug addresses
-+
-+mdebug-context
-+Target RejectNegative Report Undocumented Mask(DEBUG_CONTEXT)
-+Debug contexts
-+
-+march=
-+Target Report Var(ubicom32_arch_name) Init("ubicom32v4") Joined
-+Specify the name of the target architecture
-+
-+mfdpic
-+Target Report Mask(FDPIC)
-+Enable Function Descriptor PIC mode
-+
-+minline-plt
-+Target Report Mask(INLINE_PLT)
-+Enable inlining of PLT in function calls
-+
-+mfastcall
-+Target Report Mask(FASTCALL)
-+Enable default fast (call) calling sequence for smaller applications
-+
-+mipos-abi
-+Target Report Mask(IPOS_ABI)
-+Enable the ipOS ABI in which D10-D13 are caller-clobbered
---- /dev/null
-+++ b/gcc/config/ubicom32/uclinux.h
-@@ -0,0 +1,67 @@
-+/* Definitions of target machine for Ubicom32-uclinux
-+
-+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
-+   2009 Free Software Foundation, Inc.
-+   Contributed by Ubicom, Inc.
-+
-+   This file is part of GCC.
-+
-+   GCC is free software; you can redistribute it and/or modify it
-+   under the terms of the GNU General Public License as published
-+   by the Free Software Foundation; either version 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/>.  */
-+
-+/* Don't assume anything about the header files.  */
-+#define NO_IMPLICIT_EXTERN_C
-+
-+#undef  LIB_SPEC
-+#define LIB_SPEC  \
-+      "%{pthread:-lpthread} " \
-+      "%{!shared:%{!symbolic: -lc}} "
-+
-+
-+#undef LINK_GCC_C_SEQUENCE_SPEC
-+#define LINK_GCC_C_SEQUENCE_SPEC \
-+  "%{!shared:--start-group} %G %L %{!shared:--end-group}%{shared:%G} "
-+
-+#undef STARTFILE_SPEC
-+#define STARTFILE_SPEC \
-+      "%{!shared: crt1%O%s}" \
-+      " crti%O%s crtbegin%O%s"
-+
-+#undef ENDFILE_SPEC
-+#define ENDFILE_SPEC "crtend%O%s crtn%O%s"
-+
-+/* This macro applies on top of OBJECT_FORMAT_ELF and indicates that
-+   we want to support both flat and ELF output.  */
-+#define OBJECT_FORMAT_FLAT
-+
-+#undef DRIVER_SELF_SPECS
-+#define DRIVER_SELF_SPECS \
-+  "%{!mno-fastcall:-mfastcall}"
-+
-+/* taken from linux.h */
-+/* The GNU C++ standard library requires that these macros be defined.  */
-+#undef CPLUSPLUS_CPP_SPEC
-+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
-+
-+#define TARGET_OS_CPP_BUILTINS()                              \
-+    do {                                                      \
-+      builtin_define_std ("__UBICOM32__");                    \
-+      builtin_define_std ("__ubicom32__");                    \
-+      builtin_define ("__gnu_linux__");                       \
-+      builtin_define_std ("linux");                           \
-+      builtin_define_std ("unix");                            \
-+      builtin_assert ("system=linux");                        \
-+      builtin_assert ("system=unix");                         \
-+      builtin_assert ("system=posix");                        \
-+    } while (0)
---- /dev/null
-+++ b/gcc/config/ubicom32/xm-ubicom32.h
-@@ -0,0 +1,36 @@
-+/* Configuration for Ubicom's Ubicom32 architecture.
-+   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software
-+   Foundation, Inc.
-+   Contributed by Ubicom Inc.
-+
-+This file is part of GNU CC.
-+
-+GNU CC is free software; you can redistribute it and/or modify
-+it under the terms of the GNU General Public License as published by
-+the Free Software Foundation; either version 2, or (at your option)
-+any later version.
-+
-+GNU CC is distributed in the hope that it will be useful,
-+but WITHOUT ANY WARRANTY; without even the implied warranty of
-+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+GNU General Public License for more details.
-+
-+You should have received a copy of the GNU General Public License
-+along with GNU CC; see the file COPYING.  If not, write to
-+the Free Software Foundation, 59 Temple Place - Suite 330,
-+Boston, MA 02111-1307, USA.  */
-+
-+/* #defines that need visibility everywhere.  */
-+#define FALSE 0
-+#define TRUE 1
-+
-+/* This describes the machine the compiler is hosted on.  */
-+#define HOST_BITS_PER_CHAR 8
-+#define HOST_BITS_PER_SHORT 16
-+#define HOST_BITS_PER_INT 32
-+#define HOST_BITS_PER_LONG 32
-+#define HOST_BITS_PER_LONGLONG 64
-+
-+/* Arguments to use with `exit'.  */
-+#define SUCCESS_EXIT_CODE 0
-+#define FATAL_EXIT_CODE 33
---- a/gcc/config.gcc
-+++ b/gcc/config.gcc
-@@ -2314,6 +2314,34 @@ spu-*-elf*)
-       c_target_objs="${c_target_objs} spu-c.o"
-       cxx_target_objs="${cxx_target_objs} spu-c.o"
-       ;;
-+ubicom32-*-elf)
-+      xm_file=ubicom32/xm-ubicom32.h
-+      tm_file="${tm_file} ubicom32/elf.h" # still need dbxelf.h elfos.h
-+      tmake_file=ubicom32/t-ubicom32
-+      ;;
-+ubicom32-*-uclinux*)
-+      xm_file=ubicom32/xm-ubicom32.h
-+      tm_file="${tm_file} ubicom32/elf.h ubicom32/uclinux.h"  # still need dbxelf.h elfos.h linux.h
-+      tm_defines="${tm_defines} UCLIBC_DEFAULT=1"
-+      extra_options="${extra_options} linux.opt"
-+      tmake_file=ubicom32/t-ubicom32-uclinux
-+      use_collect2=no
-+      ;;
-+ubicom32-*-linux-uclibc)
-+      xm_file=ubicom32/xm-ubicom32.h
-+      tm_file="${tm_file} ubicom32/elf.h linux.h ubicom32/linux.h"  # still need dbxelf.h elfos.h
-+      tmake_file="t-slibgcc-elf-ver ubicom32/t-ubicom32-linux"
-+      extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
-+      use_collect2=no
-+      ;;
-+ubicom32-*-linux*)
-+      xm_file=ubicom32/xm-ubicom32.h
-+      tm_file="${tm_file} ubicom32/elf.h linux.h ubicom32/linux.h"  # still need dbxelf.h elfos.h
-+      tmake_file="t-slibgcc-elf-ver ubicom32/t-ubicom32-linux"
-+      tm_defines="${tm_defines} UCLIBC_DEFAULT=1"
-+      extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
-+      use_collect2=no
-+      ;;
- v850e1-*-*)
-       target_cpu_default="TARGET_CPU_v850e1"
-       tm_file="dbxelf.h elfos.h svr4.h v850/v850.h"
---- a/libgcc/config.host
-+++ b/libgcc/config.host
-@@ -551,6 +551,15 @@ sparc64-*-netbsd*)
-       ;;
- spu-*-elf*)
-       ;;
-+ubicom32*-*-elf*)
-+      ;;
-+ubicom32*-*-uclinux*)
-+        ;;
-+ubicom32*-*-linux*)
-+      # No need to build crtbeginT.o on uClibc systems.  Should probably
-+      # be moved to the OS specific section above.
-+      extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
-+        ;;
- v850e1-*-*)
-       ;;
- v850e-*-*)
diff --git a/toolchain/gcc/patches/4.5.2/810-arm-softfloat-libgcc.patch b/toolchain/gcc/patches/4.5.2/810-arm-softfloat-libgcc.patch
deleted file mode 100644 (file)
index 4ca297a..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
---- a/gcc/config/arm/linux-elf.h
-+++ b/gcc/config/arm/linux-elf.h
-@@ -60,7 +60,7 @@
-    %{shared:-lc} \
-    %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
--#define LIBGCC_SPEC "%{msoft-float:-lfloat} %{mfloat-abi=soft*:-lfloat} -lgcc"
-+#define LIBGCC_SPEC "-lgcc"
- #define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
---- a/gcc/config/arm/t-linux
-+++ b/gcc/config/arm/t-linux
-@@ -4,7 +4,10 @@
- LIB1ASMSRC = arm/lib1funcs.asm
- LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx _clzsi2 _clzdi2 \
--      _arm_addsubdf3 _arm_addsubsf3
-+      _arm_addsubdf3 _arm_addsubsf3 \
-+      _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \
-+      _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
-+      _fixsfsi _fixunssfsi _floatdidf _floatundidf _floatdisf _floatundisf
- # MULTILIB_OPTIONS = mhard-float/msoft-float
- # MULTILIB_DIRNAMES = hard-float soft-float
diff --git a/toolchain/gcc/patches/4.5.2/820-libgcc_pic.patch b/toolchain/gcc/patches/4.5.2/820-libgcc_pic.patch
deleted file mode 100644 (file)
index 18386df..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
---- a/libgcc/Makefile.in
-+++ b/libgcc/Makefile.in
-@@ -729,11 +729,12 @@ $(libgcov-objects): %$(objext): $(gcc_sr
- # Static libraries.
- libgcc.a: $(libgcc-objects)
-+libgcc_pic.a: $(libgcc-s-objects)
- libgcov.a: $(libgcov-objects)
- libunwind.a: $(libunwind-objects)
- libgcc_eh.a: $(libgcc-eh-objects)
--libgcc.a libgcov.a libunwind.a libgcc_eh.a:
-+libgcc.a libgcov.a libunwind.a libgcc_eh.a libgcc_pic.a:
-       -rm -f $@
-       objects="$(objects)";                                   \
-@@ -755,7 +756,7 @@ libgcc_s$(SHLIB_EXT): libunwind$(SHLIB_E
- endif
- ifeq ($(enable_shared),yes)
--all: libgcc_eh.a libgcc_s$(SHLIB_EXT)
-+all: libgcc_eh.a libgcc_pic.a libgcc_s$(SHLIB_EXT)
- ifneq ($(LIBUNWIND),)
- all: libunwind$(SHLIB_EXT)
- endif
-@@ -928,6 +929,10 @@ install-shared:
-       chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_eh.a
-       $(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_eh.a
-+      $(INSTALL_DATA) libgcc_pic.a $(mapfile) $(DESTDIR)$(inst_libdir)/
-+      chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_pic.a
-+      $(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_pic.a
-+
-       $(subst @multilib_dir@,$(MULTIDIR),$(subst \
-               @shlib_base_name@,libgcc_s,$(subst \
-               @shlib_slibdir_qual@,$(MULTIOSSUBDIR),$(SHLIB_INSTALL))))
diff --git a/toolchain/gcc/patches/4.5.2/910-mbsd_multi.patch b/toolchain/gcc/patches/4.5.2/910-mbsd_multi.patch
deleted file mode 100644 (file)
index 0d5815a..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-
-       This patch brings over a few features from MirBSD:
-       * -fhonour-copts
-         If this option is not given, it's warned (depending
-         on environment variables). This is to catch errors
-         of misbuilt packages which override CFLAGS themselves.
-       * -Werror-maybe-reset
-         Has the effect of -Wno-error if GCC_NO_WERROR is
-         set and not '0', a no-operation otherwise. This is
-         to be able to use -Werror in "make" but prevent
-         GNU autoconf generated configure scripts from
-         freaking out.
-       * Make -fno-strict-aliasing and -fno-delete-null-pointer-checks
-         the default for -O2/-Os, because they trigger gcc bugs
-         and can delete code with security implications.
-
-       This patch was authored by Thorsten Glaser <tg at mirbsd.de>
-       with copyright assignment to the FSF in effect.
-
---- a/gcc/c-opts.c
-+++ b/gcc/c-opts.c
-@@ -105,6 +105,9 @@
- /* Number of deferred options scanned for -include.  */
- static size_t include_cursor;
-+/* Check if a port honours COPTS.  */
-+static int honour_copts = 0;
-+
- static void set_Wimplicit (int);
- static void handle_OPT_d (const char *);
- static void set_std_cxx98 (int);
-@@ -454,6 +457,9 @@
-       enable_warning_as_error ("implicit-function-declaration", value, CL_C | CL_ObjC); 
-       break;
-+    case OPT_Werror_maybe_reset:
-+      break;
-+
-     case OPT_Wformat:
-       set_Wformat (value);
-       break;
-@@ -690,6 +701,12 @@
-       flag_exceptions = value;
-       break;
-+    case OPT_fhonour_copts:
-+      if (c_language == clk_c) {
-+      honour_copts++;
-+      }
-+      break;
-+
-     case OPT_fimplement_inlines:
-       flag_implement_inlines = value;
-       break;
-@@ -1209,6 +1226,47 @@
-       return false;
-     }
-+  if (c_language == clk_c) {
-+    char *ev = getenv ("GCC_HONOUR_COPTS");
-+    int evv;
-+    if (ev == NULL)
-+      evv = -1;
-+    else if ((*ev == '0') || (*ev == '\0'))
-+      evv = 0;
-+    else if (*ev == '1')
-+      evv = 1;
-+    else if (*ev == '2')
-+      evv = 2;
-+    else if (*ev == 's')
-+      evv = -1;
-+    else {
-+      warning (0, "unknown GCC_HONOUR_COPTS value, assuming 1");
-+      evv = 1; /* maybe depend this on something like MIRBSD_NATIVE?  */
-+    }
-+    if (evv == 1) {
-+      if (honour_copts == 0) {
-+      error ("someone does not honour COPTS at all in lenient mode");
-+      return false;
-+      } else if (honour_copts != 1) {
-+      warning (0, "someone does not honour COPTS correctly, passed %d times",
-+       honour_copts);
-+      }
-+    } else if (evv == 2) {
-+      if (honour_copts == 0) {
-+      error ("someone does not honour COPTS at all in strict mode");
-+      return false;
-+      } else if (honour_copts != 1) {
-+      error ("someone does not honour COPTS correctly, passed %d times",
-+       honour_copts);
-+      return false;
-+      }
-+    } else if (evv == 0) {
-+      if (honour_copts != 1)
-+      inform (0, "someone does not honour COPTS correctly, passed %d times",
-+       honour_copts);
-+    }
-+  }
-+
-   return true;
- }
---- a/gcc/c.opt
-+++ b/gcc/c.opt
-@@ -215,6 +215,10 @@
- C ObjC RejectNegative Warning
- This switch is deprecated; use -Werror=implicit-function-declaration instead
-+Werror-maybe-reset
-+C ObjC C++ ObjC++
-+; Documented in common.opt
-+
- Wfloat-equal
- C ObjC C++ ObjC++ Var(warn_float_equal) Warning
- Warn if testing floating point numbers for equality
-@@ -609,6 +613,9 @@
- fhonor-std
- C++ ObjC++
-+fhonour-copts
-+C ObjC C++ ObjC++ RejectNegative
-+
- fhosted
- C ObjC
- Assume normal C execution environment
---- a/gcc/common.opt
-+++ b/gcc/common.opt
-@@ -102,6 +102,10 @@
- Common Joined
- Treat specified warning as error
-+Werror-maybe-reset
-+Common
-+If environment variable GCC_NO_WERROR is set, act as -Wno-error
-+
- Wextra
- Common Warning
- Print extra (possibly unwanted) warnings
-@@ -573,6 +577,9 @@
- Common Report Var(flag_guess_branch_prob) Optimization
- Enable guessing of branch probabilities
-+fhonour-copts
-+Common RejectNegative
-+
- ; Nonzero means ignore `#ident' directives.  0 means handle them.
- ; Generate position-independent code for executables if possible
- ; On SVR4 targets, it also controls whether or not to emit a
---- a/gcc/opts.c
-+++ b/gcc/opts.c
-@@ -896,8 +896,6 @@
-   flag_schedule_insns_after_reload = opt2;
- #endif
-   flag_regmove = opt2;
--  flag_strict_aliasing = opt2;
--  flag_strict_overflow = opt2;
-   flag_reorder_blocks = opt2;
-   flag_reorder_functions = opt2;
-   flag_tree_vrp = opt2;
-@@ -922,6 +919,8 @@
-   /* -O3 optimizations.  */
-   opt3 = (optimize >= 3);
-+  flag_strict_aliasing = opt3;
-+  flag_strict_overflow = opt3;
-   flag_predictive_commoning = opt3;
-   flag_inline_functions = opt3;
-   flag_unswitch_loops = opt3;
-@@ -1601,6 +1601,17 @@
-       enable_warning_as_error (arg, value, lang_mask);
-       break;
-+    case OPT_Werror_maybe_reset:
-+      {
-+      char *ev = getenv ("GCC_NO_WERROR");
-+      if ((ev != NULL) && (*ev != '0'))
-+        warnings_are_errors = 0;
-+      }
-+      break;
-+
-+    case OPT_fhonour_copts:
-+      break;
-+
-     case OPT_Wlarger_than_:
-       /* This form corresponds to -Wlarger-than-. 
-          Kept for backward compatibility.
---- a/gcc/doc/cppopts.texi
-+++ b/gcc/doc/cppopts.texi
-@@ -164,6 +164,11 @@
- Make all warnings into hard errors.  Source code which triggers warnings
- will be rejected.
-+ at item -Werror-maybe-reset
-+ at opindex Werror-maybe-reset
-+Act like @samp{-Wno-error} if the @env{GCC_NO_WERROR} environment
-+variable is set to anything other than 0 or empty.
-+
- @item -Wsystem-headers
- @opindex Wsystem-headers
- Issue warnings for code in system headers.  These are normally unhelpful
---- a/gcc/doc/invoke.texi
-+++ b/gcc/doc/invoke.texi
-@@ -234,7 +234,7 @@
- -Wconversion  -Wcoverage-mismatch  -Wno-deprecated  @gol
- -Wno-deprecated-declarations -Wdisabled-optimization  @gol
- -Wno-div-by-zero -Wempty-body  -Wenum-compare -Wno-endif-labels @gol
---Werror  -Werror=* @gol
-+-Werror  -Werror=* -Werror-maybe-reset @gol
- -Wfatal-errors  -Wfloat-equal  -Wformat  -Wformat=2 @gol
- -Wno-format-contains-nul -Wno-format-extra-args -Wformat-nonliteral @gol
- -Wformat-security  -Wformat-y2k @gol
-@@ -4161,6 +4161,22 @@
- @option{-Wall} and by @option{-pedantic}, which can be disabled with
- @option{-Wno-pointer-sign}.
-+ at item -Werror-maybe-reset
-+ at opindex Werror-maybe-reset
-+Act like @samp{-Wno-error} if the @env{GCC_NO_WERROR} environment
-+variable is set to anything other than 0 or empty.
-+
-+ at item -fhonour-copts
-+ at opindex fhonour-copts
-+If @env{GCC_HONOUR_COPTS} is set to 1, abort if this option is not
-+given at least once, and warn if it is given more than once.
-+If @env{GCC_HONOUR_COPTS} is set to 2, abort if this option is not
-+given exactly once.
-+If @env{GCC_HONOUR_COPTS} is set to 0 or unset, warn if this option
-+is not given exactly once.
-+The warning is quelled if @env{GCC_HONOUR_COPTS} is set to @samp{s}.
-+This flag and environment variable only affect the C language.
-+
- @item -Wstack-protector
- @opindex Wstack-protector
- @opindex Wno-stack-protector
-@@ -5699,7 +5715,7 @@
- second branch or a point immediately following it, depending on whether
- the condition is known to be true or false.
--Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
-+Enabled at levels @option{-O3}.
- @item -fsplit-wide-types
- @opindex fsplit-wide-types
---- a/gcc/java/jvspec.c
-+++ b/gcc/java/jvspec.c
-@@ -670,6 +670,7 @@
-      class name.  Append dummy `.c' that can be stripped by set_input so %b
-      is correct.  */ 
-   set_input (concat (main_class_name, "main.c", NULL));
-+  putenv ("GCC_HONOUR_COPTS=s"); /* XXX hack!  */
-   err = do_spec (jvgenmain_spec);
-   if (err == 0)
-     {
diff --git a/toolchain/gcc/patches/4.5.2/993-arm_insn-opinit-RTX_CODE-fixup.patch b/toolchain/gcc/patches/4.5.2/993-arm_insn-opinit-RTX_CODE-fixup.patch
deleted file mode 100644 (file)
index 4c4be9f..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
---- gcc-4.4.0/gcc/config/arm/arm-protos.h      2009-02-20 16:20:38.000000000 +0100
-+++ gcc-4.4.0.new/gcc/config/arm/arm-protos.h  2009-04-22 16:00:58.000000000 +0200
-@@ -43,10 +43,10 @@
- extern void arm_output_fn_unwind (FILE *, bool);
-   
--#ifdef RTX_CODE
- extern bool arm_vector_mode_supported_p (enum machine_mode);
- extern int arm_hard_regno_mode_ok (unsigned int, enum machine_mode);
- extern int const_ok_for_arm (HOST_WIDE_INT);
-+#ifdef RTX_CODE
- extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
-                              HOST_WIDE_INT, rtx, rtx, int);
- extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, enum machine_mode,
diff --git a/toolchain/gcc/patches/4.5.2/995-fa526.patch b/toolchain/gcc/patches/4.5.2/995-fa526.patch
deleted file mode 100644 (file)
index 508e123..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
---- a/gcc/config/arm/arm-cores.def
-+++ b/gcc/config/arm/arm-cores.def
-@@ -74,6 +74,7 @@ ARM_CORE("strongarm",     strongarm, 4,
- ARM_CORE("strongarm110",  strongarm110,       4,                   FL_MODE26 | FL_LDSCHED | FL_STRONG, fastmul)
- ARM_CORE("strongarm1100", strongarm1100, 4,                FL_MODE26 | FL_LDSCHED | FL_STRONG, fastmul)
- ARM_CORE("strongarm1110", strongarm1110, 4,                FL_MODE26 | FL_LDSCHED | FL_STRONG, fastmul)
-+ARM_CORE("fa526",         fa526,        4,                               FL_LDSCHED, fastmul)
- /* V4T Architecture Processors */
- ARM_CORE("arm7tdmi",      arm7tdmi,   4T,     FL_CO_PROC          , fastmul)
---- a/gcc/config/arm/arm.md
-+++ b/gcc/config/arm/arm.md
-@@ -417,7 +417,7 @@
- (define_attr "generic_sched" "yes,no"
-   (const (if_then_else 
--          (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8,cortexa9")
-+          (ior (eq_attr "tune" "fa526,arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,cortexm4")
-             (eq_attr "tune_cortexr4" "yes"))
-           (const_string "no")
-           (const_string "yes"))))
-@@ -435,6 +435,7 @@
- (include "arm1020e.md")
- (include "arm1026ejs.md")
- (include "arm1136jfs.md")
-+(include "fa526.md")
- (include "cortex-a8.md")
- (include "cortex-a9.md")
- (include "cortex-r4.md")
---- a/gcc/config/arm/arm-tune.md
-+++ b/gcc/config/arm/arm-tune.md
-@@ -1,5 +1,5 @@
- ;; -*- buffer-read-only: t -*-
- ;; Generated automatically by gentune.sh from arm-cores.def
- (define_attr "tune"
--      "arm2,arm250,arm3,arm6,arm60,arm600,arm610,arm620,arm7,arm7d,arm7di,arm70,arm700,arm700i,arm710,arm720,arm710c,arm7100,arm7500,arm7500fe,arm7m,arm7dm,arm7dmi,arm8,arm810,strongarm,strongarm110,strongarm1100,strongarm1110,arm7tdmi,arm7tdmis,arm710t,arm720t,arm740t,arm9,arm9tdmi,arm920,arm920t,arm922t,arm940t,ep9312,arm10tdmi,arm1020t,arm9e,arm946es,arm966es,arm968es,arm10e,arm1020e,arm1022e,xscale,iwmmxt,iwmmxt2,arm926ejs,arm1026ejs,arm1136js,arm1136jfs,arm1176jzs,arm1176jzfs,mpcorenovfp,mpcore,arm1156t2s,arm1156t2fs,cortexa5,cortexa8,cortexa9,cortexr4,cortexr4f,cortexm3,cortexm1,cortexm0"
-+      "arm2,arm250,arm3,arm6,arm60,arm600,arm610,arm620,arm7,arm7d,arm7di,arm70,arm700,arm700i,arm710,arm720,arm710c,arm7100,arm7500,arm7500fe,arm7m,arm7dm,arm7dmi,arm8,arm810,strongarm,strongarm110,strongarm1100,strongarm1110,fa526,arm7tdmi,arm7tdmis,arm710t,arm720t,arm740t,arm9,arm9tdmi,arm920,arm920t,arm922t,arm940t,ep9312,arm10tdmi,arm1020t,arm9e,arm946es,arm966es,arm968es,arm10e,arm1020e,arm1022e,xscale,iwmmxt,iwmmxt2,arm926ejs,arm1026ejs,arm1136js,arm1136jfs,arm1176jzs,arm1176jzfs,mpcorenovfp,mpcore,arm1156t2s,arm1156t2fs,cortexa5,cortexa8,cortexa9,cortexr4,cortexr4f,cortexm4,cortexm3,cortexm1,cortexm0"
-       (const (symbol_ref "((enum attr_tune) arm_tune)")))
---- a/gcc/config/arm/bpabi.h
-+++ b/gcc/config/arm/bpabi.h
-@@ -52,7 +52,8 @@
- /* The BPABI integer comparison routines return { -1, 0, 1 }.  */
- #define TARGET_LIB_INT_CMP_BIASED !TARGET_BPABI
--#define TARGET_FIX_V4BX_SPEC " %{mcpu=arm8|mcpu=arm810|mcpu=strongarm*|march=armv4:--fix-v4bx}"
-+#define TARGET_FIX_V4BX_SPEC " %{mcpu=arm8|mcpu=arm810|mcpu=strongarm*\
-+|march=armv4|mcpu=fa526:--fix-v4bx}"
- #define BE8_LINK_SPEC " %{mbig-endian:%{march=armv7-a|mcpu=cortex-a5|mcpu=cortex-a8|mcpu=cortex-a9:%{!r:--be8}}}"
---- /dev/null
-+++ b/gcc/config/arm/fa526.md
-@@ -0,0 +1,161 @@
-+;; Faraday FA526 Pipeline Description
-+;; Copyright (C) 2010 Free Software Foundation, Inc.
-+;; Written by I-Jui Sung, based on ARM926EJ-S Pipeline Description.
-+
-+;; 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/>.  */
-+
-+;; These descriptions are based on the information contained in the
-+;; FA526 Core Design Note, Copyright (c) 2010 Faraday Technology Corp.
-+;;
-+;; Modeled pipeline characteristics:
-+;; LD -> any use: latency = 3 (2 cycle penalty).
-+;; ALU -> any use: latency = 2 (1 cycle penalty).
-+
-+;; This automaton provides a pipeline description for the Faraday
-+;; FA526 core.
-+;;
-+;; The model given here assumes that the condition for all conditional
-+;; instructions is "true", i.e., that all of the instructions are
-+;; actually executed.
-+
-+(define_automaton "fa526")
-+
-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-+;; Pipelines
-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-+
-+;; There is a single pipeline
-+;;
-+;;   The ALU pipeline has fetch, decode, execute, memory, and
-+;;   write stages.  We only need to model the execute, memory and write
-+;;   stages.
-+
-+;;      S      E      M      W
-+
-+(define_cpu_unit "fa526_core" "fa526")
-+
-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-+;; ALU Instructions
-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-+
-+;; ALU instructions require two cycles to execute, and use the ALU
-+;; pipeline in each of the three stages.  The results are available
-+;; after the execute stage stage has finished.
-+;;
-+;; If the destination register is the PC, the pipelines are stalled
-+;; for several cycles.  That case is not modeled here.
-+
-+;; ALU operations
-+(define_insn_reservation "526_alu_op" 1
-+ (and (eq_attr "tune" "fa526")
-+      (eq_attr "type" "alu"))
-+ "fa526_core")
-+
-+(define_insn_reservation "526_alu_shift_op" 2
-+ (and (eq_attr "tune" "fa526")
-+      (eq_attr "type" "alu_shift,alu_shift_reg"))
-+ "fa526_core")
-+
-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-+;; Multiplication Instructions
-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-+
-+(define_insn_reservation "526_mult1" 2
-+ (and (eq_attr "tune" "fa526")
-+      (eq_attr "insn" "smlalxy,smulxy,smlaxy,smlalxy"))
-+ "fa526_core")
-+
-+(define_insn_reservation "526_mult2" 5
-+ (and (eq_attr "tune" "fa526")
-+      (eq_attr "insn" "mul,mla,muls,mlas,umull,umlal,smull,smlal,umulls,\
-+                       umlals,smulls,smlals,smlawx"))
-+ "fa526_core*4")
-+
-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-+;; Load/Store Instructions
-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-+
-+;; The models for load/store instructions do not accurately describe
-+;; the difference between operations with a base register writeback
-+;; (such as "ldm!").  These models assume that all memory references
-+;; hit in dcache.
-+
-+(define_insn_reservation "526_load1_op" 3
-+ (and (eq_attr "tune" "fa526")
-+      (eq_attr "type" "load1,load_byte"))
-+ "fa526_core")
-+
-+(define_insn_reservation "526_load2_op" 4
-+ (and (eq_attr "tune" "fa526")
-+      (eq_attr "type" "load2"))
-+ "fa526_core*2")
-+
-+(define_insn_reservation "526_load3_op" 5
-+ (and (eq_attr "tune" "fa526")
-+      (eq_attr "type" "load3"))
-+ "fa526_core*3")
-+
-+(define_insn_reservation "526_load4_op" 6
-+ (and (eq_attr "tune" "fa526")
-+      (eq_attr "type" "load4"))
-+ "fa526_core*4")
-+
-+(define_insn_reservation "526_store1_op" 0
-+ (and (eq_attr "tune" "fa526")
-+      (eq_attr "type" "store1"))
-+ "fa526_core")
-+
-+(define_insn_reservation "526_store2_op" 1
-+ (and (eq_attr "tune" "fa526")
-+      (eq_attr "type" "store2"))
-+ "fa526_core*2")
-+
-+(define_insn_reservation "526_store3_op" 2
-+ (and (eq_attr "tune" "fa526")
-+      (eq_attr "type" "store3"))
-+ "fa526_core*3")
-+
-+(define_insn_reservation "526_store4_op" 3
-+ (and (eq_attr "tune" "fa526")
-+      (eq_attr "type" "store4"))
-+ "fa526_core*4")
-+
-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-+;; Branch and Call Instructions
-+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-+
-+;; Branch instructions are difficult to model accurately.  The FA526
-+;; core can predict most branches.  If the branch is predicted
-+;; correctly, and predicted early enough, the branch can be completely
-+;; eliminated from the instruction stream.  Some branches can
-+;; therefore appear to require zero cycle to execute.  We assume that
-+;; all branches are predicted correctly, and that the latency is
-+;; therefore the minimum value.
-+
-+(define_insn_reservation "526_branch_op" 0
-+ (and (eq_attr "tune" "fa526")
-+      (eq_attr "type" "branch"))
-+ "fa526_core")
-+
-+;; The latency for a call is actually the latency when the result is available.
-+;; i.e. R0 ready for int return value.  For most cases, the return value is set
-+;; by a mov instruction, which has 1 cycle latency.
-+(define_insn_reservation "526_call_op" 1
-+ (and (eq_attr "tune" "fa526")
-+      (eq_attr "type" "call"))
-+ "fa526_core")
-+
---- a/gcc/config/arm/t-arm
-+++ b/gcc/config/arm/t-arm
-@@ -24,6 +24,7 @@ MD_INCLUDES=         $(srcdir)/config/arm/arm-t
-               $(srcdir)/config/arm/arm1020e.md \
-               $(srcdir)/config/arm/arm1026ejs.md \
-               $(srcdir)/config/arm/arm1136jfs.md \
-+              $(srcdir)/config/arm/fa526.md \
-               $(srcdir)/config/arm/arm926ejs.md \
-               $(srcdir)/config/arm/cirrus.md \
-               $(srcdir)/config/arm/fpa.md \
---- a/gcc/config/arm/t-arm-elf
-+++ b/gcc/config/arm/t-arm-elf
-@@ -36,6 +36,10 @@ MULTILIB_DIRNAMES    = arm thumb
- MULTILIB_EXCEPTIONS  = 
- MULTILIB_MATCHES     =
-+#MULTILIB_OPTIONS     += mcpu=fa526
-+#MULTILIB_DIRNAMES    += fa526
-+#MULTILIB_EXCEPTIONS  += *mthumb*/*mcpu=fa526
-+
- #MULTILIB_OPTIONS      += march=armv7
- #MULTILIB_DIRNAMES     += thumb2
- #MULTILIB_EXCEPTIONS   += march=armv7* marm/*march=armv7*
-@@ -52,6 +56,7 @@ MULTILIB_MATCHES     =
- MULTILIB_OPTIONS       += mfloat-abi=hard
- MULTILIB_DIRNAMES      += fpu
- MULTILIB_EXCEPTIONS    += *mthumb/*mfloat-abi=hard*
-+MULTILIB_EXCEPTIONS    += *mcpu=fa526/*mfloat-abi=hard*
- # MULTILIB_OPTIONS    += mcpu=ep9312
- # MULTILIB_DIRNAMES   += ep9312
---- a/gcc/doc/invoke.texi
-+++ b/gcc/doc/invoke.texi
-@@ -9900,7 +9900,8 @@ assembly code.  Permissible names are: @
- @samp{cortex-r4}, @samp{cortex-r4f}, @samp{cortex-m4}, @samp{cortex-m3},
- @samp{cortex-m1},
- @samp{cortex-m0},
--@samp{xscale}, @samp{iwmmxt}, @samp{iwmmxt2}, @samp{ep9312}.
-+@samp{xscale}, @samp{iwmmxt}, @samp{iwmmxt2}, @samp{ep9312},
-+@samp{fa526}.
- @item -mtune=@var{name}
- @opindex mtune
diff --git a/toolchain/gcc/patches/4.5.2/999-coldfire.patch b/toolchain/gcc/patches/4.5.2/999-coldfire.patch
deleted file mode 100644 (file)
index 980e276..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-Index: gcc-4.4.2/gcc/config.gcc
-===================================================================
---- gcc-4.4.2.orig/gcc/config.gcc      2009-10-21 16:19:39.000000000 +0200
-+++ gcc-4.4.2/gcc/config.gcc   2009-10-21 16:19:40.000000000 +0200
-@@ -1506,6 +1506,7 @@
-       if test x$sjlj != x1; then
-           tmake_file="$tmake_file m68k/t-slibgcc-elf-ver"
-       fi
-+      tmake_file="m68k/t-floatlib m68k/t-m68kbare m68k/t-m68kelf"
-       ;;
- m68k-*-rtems*)
-       default_m68k_cpu=68020
diff --git a/toolchain/gcc/patches/4.6.1/100-uclibc-conf.patch b/toolchain/gcc/patches/4.6.1/100-uclibc-conf.patch
new file mode 100644 (file)
index 0000000..ff9ad94
--- /dev/null
@@ -0,0 +1,33 @@
+--- a/contrib/regression/objs-gcc.sh
++++ b/contrib/regression/objs-gcc.sh
+@@ -106,6 +106,10 @@ if [ $H_REAL_TARGET = $H_REAL_HOST -a $H
+  then
+   make all-gdb all-dejagnu all-ld || exit 1
+   make install-gdb install-dejagnu install-ld || exit 1
++elif [ $H_REAL_TARGET = $H_REAL_HOST -a $H_REAL_TARGET = i686-pc-linux-uclibc ]
++ then
++  make all-gdb all-dejagnu all-ld || exit 1
++  make install-gdb install-dejagnu install-ld || exit 1
+ elif [ $H_REAL_TARGET = $H_REAL_HOST ] ; then
+   make bootstrap || exit 1
+   make install || exit 1
+--- a/libjava/classpath/ltconfig
++++ b/libjava/classpath/ltconfig
+@@ -603,7 +603,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-
+ # Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+ case $host_os in
+-linux-gnu*) ;;
++linux-gnu*|linux-uclibc*) ;;
+ linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+ esac
+@@ -1247,7 +1247,7 @@ linux-gnuoldld* | linux-gnuaout* | linux
+   ;;
+ # This must be Linux ELF.
+-linux-gnu*)
++linux*)
+   version_type=linux
+   need_lib_prefix=no
+   need_version=no
diff --git a/toolchain/gcc/patches/4.6.1/301-missing-execinfo_h.patch b/toolchain/gcc/patches/4.6.1/301-missing-execinfo_h.patch
new file mode 100644 (file)
index 0000000..b3f1e68
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/boehm-gc/include/gc.h
++++ b/boehm-gc/include/gc.h
+@@ -503,7 +503,7 @@ GC_API GC_PTR GC_malloc_atomic_ignore_of
+ #if defined(__linux__) || defined(__GLIBC__)
+ # include <features.h>
+ # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \
+-     && !defined(__ia64__)
++     && !defined(__ia64__) && !defined(__UCLIBC__)
+ #   ifndef GC_HAVE_BUILTIN_BACKTRACE
+ #     define GC_HAVE_BUILTIN_BACKTRACE
+ #   endif
diff --git a/toolchain/gcc/patches/4.6.1/302-c99-snprintf.patch b/toolchain/gcc/patches/4.6.1/302-c99-snprintf.patch
new file mode 100644 (file)
index 0000000..eda1854
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/libstdc++-v3/include/c_global/cstdio
++++ b/libstdc++-v3/include/c_global/cstdio
+@@ -137,7 +137,7 @@ namespace std
+   using ::vsprintf;
+ } // namespace
+-#if _GLIBCXX_USE_C99
++#if _GLIBCXX_USE_C99 || defined __UCLIBC__
+ #undef snprintf
+ #undef vfscanf
diff --git a/toolchain/gcc/patches/4.6.1/305-libmudflap-susv3-legacy.patch b/toolchain/gcc/patches/4.6.1/305-libmudflap-susv3-legacy.patch
new file mode 100644 (file)
index 0000000..8e2d15f
--- /dev/null
@@ -0,0 +1,47 @@
+--- a/libmudflap/mf-hooks2.c
++++ b/libmudflap/mf-hooks2.c
+@@ -421,7 +421,7 @@ WRAPPER2(void, bzero, void *s, size_t n)
+ {
+   TRACE ("%s\n", __PRETTY_FUNCTION__);
+   MF_VALIDATE_EXTENT(s, n, __MF_CHECK_WRITE, "bzero region");
+-  bzero (s, n);
++  memset (s, 0, n);
+ }
+@@ -431,7 +431,7 @@ WRAPPER2(void, bcopy, const void *src, v
+   TRACE ("%s\n", __PRETTY_FUNCTION__);
+   MF_VALIDATE_EXTENT(src, n, __MF_CHECK_READ, "bcopy src");
+   MF_VALIDATE_EXTENT(dest, n, __MF_CHECK_WRITE, "bcopy dest");
+-  bcopy (src, dest, n);
++  memmove (dest, src, n);
+ }
+@@ -441,7 +441,7 @@ WRAPPER2(int, bcmp, const void *s1, cons
+   TRACE ("%s\n", __PRETTY_FUNCTION__);
+   MF_VALIDATE_EXTENT(s1, n, __MF_CHECK_READ, "bcmp 1st arg");
+   MF_VALIDATE_EXTENT(s2, n, __MF_CHECK_READ, "bcmp 2nd arg");
+-  return bcmp (s1, s2, n);
++  return n == 0 ? 0 : memcmp (s1, s2, n);
+ }
+@@ -450,7 +450,7 @@ WRAPPER2(char *, index, const char *s, i
+   size_t n = strlen (s);
+   TRACE ("%s\n", __PRETTY_FUNCTION__);
+   MF_VALIDATE_EXTENT(s, CLAMPADD(n, 1), __MF_CHECK_READ, "index region");
+-  return index (s, c);
++  return strchr (s, c);
+ }
+@@ -459,7 +459,7 @@ WRAPPER2(char *, rindex, const char *s,
+   size_t n = strlen (s);
+   TRACE ("%s\n", __PRETTY_FUNCTION__);
+   MF_VALIDATE_EXTENT(s, CLAMPADD(n, 1), __MF_CHECK_READ, "rindex region");
+-  return rindex (s, c);
++  return strrchr (s, c);
+ }
+ /* XXX:  stpcpy, memccpy */
diff --git a/toolchain/gcc/patches/4.6.1/600-ubicom_support.patch b/toolchain/gcc/patches/4.6.1/600-ubicom_support.patch
new file mode 100644 (file)
index 0000000..8268b5e
--- /dev/null
@@ -0,0 +1,9368 @@
+--- a/configure
++++ b/configure
+@@ -3608,6 +3608,9 @@ case "${target}" in
+   ip2k-*-*)
+     noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 ${libgcj}"
+     ;;
++  ubicom32-*-*)
++    noconfigdirs="$noconfigdirs target-libffi"
++    ;;
+   *-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu | *-*-kopensolaris*-gnu)
+     noconfigdirs="$noconfigdirs target-newlib target-libgloss"
+     ;;
+--- /dev/null
++++ b/gcc/config/ubicom32/constraints.md
+@@ -0,0 +1,149 @@
++; Constraint definitions for Ubicom32
++
++; Copyright (C) 2009 Free Software Foundation, Inc.
++; Contributed by Ubicom, Inc.
++
++; This file is part of GCC.
++
++; GCC is free software; you can redistribute it and/or modify it
++; under the terms of the GNU General Public License as published
++; by the Free Software Foundation; either version 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_register_constraint "a" "ALL_ADDRESS_REGS"
++  "An An register.")
++
++(define_register_constraint "d" "DATA_REGS"
++  "A Dn register.")
++
++(define_register_constraint "h" "ACC_REGS"
++  "An accumulator register.")
++
++(define_register_constraint "l" "ACC_LO_REGS"
++  "An accn_lo register.")
++
++(define_register_constraint "Z" "FDPIC_REG"
++  "The FD-PIC GOT pointer: A0.")
++
++(define_constraint "I"
++  "An 8-bit signed constant value."
++  (and (match_code "const_int")
++       (match_test "(ival >= -128) && (ival <= 127)")))
++
++(define_constraint "Q"
++  "An 8-bit signed constant value represented as unsigned."
++  (and (match_code "const_int")
++       (match_test "(ival >= 0x00) && (ival <= 0xff)")))
++
++(define_constraint "R"
++  "An 8-bit signed constant value represented as unsigned."
++  (and (match_code "const_int")
++       (match_test "((ival >= 0x0000) && (ival <= 0x007f)) || ((ival >= 0xff80) && (ival <= 0xffff))")))
++
++(define_constraint "J"
++  "A 7-bit unsigned constant value."
++  (and (match_code "const_int")
++       (match_test "(ival >= 0) && (ival <= 127)")))
++
++(define_constraint "K"
++  "A 7-bit unsigned constant value shifted << 1."
++  (and (match_code "const_int")
++       (match_test "(ival >= 0) && (ival <= 254) && ((ival & 1) == 0)")))
++
++(define_constraint "L"
++  "A 7-bit unsigned constant value shifted << 2."
++  (and (match_code "const_int")
++       (match_test "(ival >= 0) && (ival <= 508) && ((ival & 3) == 0)")))
++
++(define_constraint "M"
++  "A 5-bit unsigned constant value."
++  (and (match_code "const_int")
++       (match_test "(ival >= 0) && (ival <= 31)")))
++
++(define_constraint "N"
++  "A signed 16 bit constant value."
++  (and (match_code "const_int")
++       (match_test "(ival >= -32768) && (ival <= 32767)")))
++
++(define_constraint "O"
++  "An exact bitmask of contiguous 1 bits starting at bit 0."
++  (and (match_code "const_int")
++       (match_test "exact_log2 (ival + 1) != -1")))
++
++(define_constraint "P"
++  "A 7-bit negative constant value shifted << 2."
++  (and (match_code "const_int")
++       (match_test "(ival >= -504) && (ival <= 0) && ((ival & 3) == 0)")))
++
++(define_constraint "S"
++  "A symbolic reference."
++  (match_code "symbol_ref"))
++
++(define_constraint "Y"
++  "An FD-PIC symbolic reference."
++  (and (match_test "TARGET_FDPIC")
++       (match_test "GET_CODE (op) == UNSPEC")
++       (ior (match_test "XINT (op, 1) == UNSPEC_FDPIC_GOT")
++          (match_test "XINT (op, 1) == UNSPEC_FDPIC_GOT_FUNCDESC"))))
++
++(define_memory_constraint "T1"
++  "A memory operand that can be used for .1 instruction."
++  (and (match_test "memory_operand (op, GET_MODE(op))")
++       (match_test "GET_MODE (op) == QImode")))
++
++(define_memory_constraint "T2"
++  "A memory operand that can be used for .2 instruction."
++  (and (match_test "memory_operand (op, GET_MODE(op))")
++       (match_test "GET_MODE (op) == HImode")))
++
++(define_memory_constraint "T4"
++  "A memory operand that can be used for .4 instruction."
++  (and (match_test "memory_operand (op, GET_MODE(op))")
++       (ior (match_test "GET_MODE (op) == SImode")
++          (match_test "GET_MODE (op) == DImode")
++          (match_test "GET_MODE (op) == SFmode"))))
++
++(define_memory_constraint "U1"
++  "An offsettable memory operand that can be used for .1 instruction."
++  (and (match_test "memory_operand (op, GET_MODE(op))")
++       (match_test "GET_MODE (op) == QImode")
++       (match_test "GET_CODE (XEXP (op, 0)) != POST_INC")
++       (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC")
++       (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC")
++       (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC")
++       (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY")
++       (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY")))
++
++(define_memory_constraint "U2"
++  "An offsettable memory operand that can be used for .2 instruction."
++  (and (match_test "memory_operand (op, GET_MODE(op))")
++       (match_test "GET_MODE (op) == HImode")
++       (match_test "GET_CODE (XEXP (op, 0)) != POST_INC")
++       (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC")
++       (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC")
++       (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC")
++       (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY")
++       (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY")))
++
++(define_memory_constraint "U4"
++  "An offsettable memory operand that can be used for .4 instruction."
++  (and (match_test "memory_operand (op, GET_MODE(op))")
++       (ior (match_test "GET_MODE (op) == SImode")
++          (match_test "GET_MODE (op) == DImode")
++          (match_test "GET_MODE (op) == SFmode"))
++       (match_test "GET_CODE (XEXP (op, 0)) != POST_INC")
++       (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC")
++       (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC")
++       (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC")
++       (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY")
++       (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY")))
++
+--- /dev/null
++++ b/gcc/config/ubicom32/crti.S
+@@ -0,0 +1,54 @@
++/* Specialized code needed to support construction and destruction of
++   file-scope objects in C++ and Java code, and to support exception handling.
++   Copyright (C) 1999 Free Software Foundation, Inc.
++   Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca).
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 2, or (at your option)
++any later version.
++
++GCC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING.  If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA.  */
++
++/* As a special exception, if you link this library with files
++   compiled with GCC to produce an executable, this does not cause
++   the resulting executable to be covered by the GNU General Public License.
++   This exception does not however invalidate any other reasons why
++   the executable file might be covered by the GNU General Public License.  */
++
++/*
++ * This file just supplies function prologues for the .init and .fini
++ * sections.  It is linked in before crtbegin.o.
++ */
++      .file   "crti.o"
++      .ident  "GNU C crti.o"
++
++      .section .init
++      .align  2
++      .globl  _init
++      .type   _init, @function
++_init:
++      move.4 -4(sp)++, a5
++#ifdef __UBICOM32_FDPIC__
++      move.4 -4(sp)++, a0
++#endif
++
++      .section .fini
++      .align  2
++      .globl  _fini
++      .type   _fini, @function
++_fini:
++      move.4 -4(sp)++, a5
++#ifdef __UBICOM32_FDPIC__
++      move.4 -4(sp)++, a0
++#endif
+--- /dev/null
++++ b/gcc/config/ubicom32/crtn.S
+@@ -0,0 +1,47 @@
++/* Specialized code needed to support construction and destruction of
++   file-scope objects in C++ and Java code, and to support exception handling.
++   Copyright (C) 1999 Free Software Foundation, Inc.
++   Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca).
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 2, or (at your option)
++any later version.
++
++GCC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING.  If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA.  */
++
++/* As a special exception, if you link this library with files
++   compiled with GCC to produce an executable, this does not cause
++   the resulting executable to be covered by the GNU General Public License.
++   This exception does not however invalidate any other reasons why
++   the executable file might be covered by the GNU General Public License.  */
++
++/*
++ * This file supplies function epilogues for the .init and .fini sections.
++ * It is linked in after all other files.
++ */
++
++      .file   "crtn.o"
++      .ident  "GNU C crtn.o"
++
++      .section .init
++#ifdef __UBICOM32_FDPIC__
++      move.4  a0, (sp)4++
++#endif
++      ret     (sp)4++
++
++      .section .fini
++#ifdef __UBICOM32_FDPIC__
++      move.4  a0, (sp)4++
++#endif
++      ret     (sp)4++
+--- /dev/null
++++ b/gcc/config/ubicom32/elf.h
+@@ -0,0 +1,29 @@
++#undef  STARTFILE_SPEC
++#define STARTFILE_SPEC "\
++%{msim:%{!shared:crt0%O%s}} \
++crti%O%s crtbegin%O%s"
++
++#undef  ENDFILE_SPEC
++#define ENDFILE_SPEC  "crtend%O%s crtn%O%s"
++
++#ifdef __UBICOM32_FDPIC__
++#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC)                    \
++  asm (SECTION_OP);                                                   \
++  asm ("move.4 a0, 0(sp);\n\t"                                                \
++       "call a5," USER_LABEL_PREFIX #FUNC ";");                               \
++  asm (TEXT_SECTION_ASM_OP);
++#endif
++
++#undef SUBTARGET_DRIVER_SELF_SPECS
++#define SUBTARGET_DRIVER_SELF_SPECS \
++     "%{mfdpic:-msim} "
++
++#define NO_IMPLICIT_EXTERN_C
++
++/*
++ * We need this to compile crtbegin/crtend. This should really be picked
++ * up from elfos.h but at the moment including elfos.h causes other more
++ * serous linker issues.
++ */
++#define INIT_SECTION_ASM_OP   "\t.section\t.init"
++#define FINI_SECTION_ASM_OP   "\t.section\t.fini"
+--- /dev/null
++++ b/gcc/config/ubicom32/linux.h
+@@ -0,0 +1,80 @@
++/* Definitions of target machine for Ubicom32-uclinux
++
++   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
++   2009 Free Software Foundation, Inc.
++   Contributed by Ubicom, Inc.
++
++   This file is part of GCC.
++
++   GCC is free software; you can redistribute it and/or modify it
++   under the terms of the GNU General Public License as published
++   by the Free Software Foundation; either version 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/>.  */
++
++/* Don't assume anything about the header files.  */
++#define NO_IMPLICIT_EXTERN_C
++
++#undef  LIB_SPEC
++#define LIB_SPEC  \
++      "%{pthread:-lpthread} " \
++      "-lc"
++
++#undef LINK_GCC_C_SEQUENCE_SPEC
++#define LINK_GCC_C_SEQUENCE_SPEC \
++  "%{static:--start-group} %G %L %{static:--end-group} " \
++  "%{!static: %G}"
++
++#undef STARTFILE_SPEC
++#define STARTFILE_SPEC \
++  "%{!shared: %{pg|p|profile:gcrt1%O%s;pie:Scrt1%O%s;:crt1%O%s}} " \
++  "crtreloc%O%s crti%O%s %{shared|pie:crtbeginS%O%s;:crtbegin%O%s}"
++
++#undef ENDFILE_SPEC
++#define ENDFILE_SPEC \
++  "%{shared|pie:crtendS%O%s;:crtend%O%s} crtn%O%s"
++
++/* taken from linux.h */
++/* The GNU C++ standard library requires that these macros be defined.  */
++#undef CPLUSPLUS_CPP_SPEC
++#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
++
++#define TARGET_OS_CPP_BUILTINS()                              \
++    do {                                                      \
++      builtin_define_std ("__UBICOM32__");                    \
++      builtin_define_std ("__ubicom32__");                    \
++      builtin_define ("__gnu_linux__");                       \
++      builtin_define_std ("linux");                           \
++      builtin_define_std ("unix");                            \
++      builtin_assert ("system=linux");                        \
++      builtin_assert ("system=unix");                         \
++      builtin_assert ("system=posix");                        \
++    } while (0)
++
++#define OBJECT_FORMAT_ELF
++
++
++#undef DRIVER_SELF_SPECS
++#define DRIVER_SELF_SPECS \
++  "%{!mno-fdpic:-mfdpic}"
++
++#undef LINK_SPEC
++#define LINK_SPEC "%{mfdpic: -m elf32ubicom32fdpic -z text } %{shared} %{pie} \
++  %{static:-dn -Bstatic} \
++  %{shared:-G -Bdynamic} \
++  %{!shared: %{!static: \
++   %{rdynamic:-export-dynamic} \
++   %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}} \
++   %{static}} "
++
++/*
++#define MD_UNWIND_SUPPORT "config/bfin/linux-unwind.h"
++*/
+--- /dev/null
++++ b/gcc/config/ubicom32/predicates.md
+@@ -0,0 +1,327 @@
++; Predicate definitions for Ubicom32.
++
++; Copyright (C) 2009 Free Software Foundation, Inc.
++; Contributed by Ubicom, Inc.
++
++; This file is part of GCC.
++
++; GCC is free software; you can redistribute it and/or modify it
++; under the terms of the GNU General Public License as published
++; by the Free Software Foundation; either version 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_predicate "ubicom32_move_operand"
++  (match_code "const_int, const_double, const, mem, subreg, reg, lo_sum")
++{
++  if (CONST_INT_P (op))
++    return true;
++
++  if (GET_CODE (op) == CONST_DOUBLE)
++    return true;
++  
++  if (GET_CODE (op) == CONST)
++    return memory_address_p (mode, op);
++
++  if (GET_MODE (op) != mode)
++    return false;
++
++  if (MEM_P (op))
++    return memory_address_p (mode, XEXP (op, 0));
++  
++  if (GET_CODE (op) == SUBREG) {
++      op = SUBREG_REG (op);
++
++      if (REG_P (op))
++      return true;
++  
++      if (! MEM_P (op))
++      return false;
++
++      /* Paradoxical SUBREG.  */
++      if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (op)))
++      return false;
++
++      return memory_address_p (GET_MODE (op), XEXP (op, 0));
++    }
++
++  return register_operand (op, mode);
++})
++
++;; Returns true if OP is either a symbol reference or a sum of a
++;; symbol reference and a constant.
++
++(define_predicate "ubicom32_symbolic_address_operand"
++  (match_code "symbol_ref, label_ref, const")
++{
++  switch (GET_CODE (op))
++    {
++    case SYMBOL_REF:
++    case LABEL_REF:
++      return true;
++
++    case CONST:
++      op = XEXP (op, 0);
++      return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
++             || GET_CODE (XEXP (op, 0)) == LABEL_REF)
++            && CONST_INT_P (XEXP (op, 1)));
++
++    default:
++      return false;
++    }
++})
++
++;; Return true if operand is the uClinux FD-PIC register.
++
++(define_predicate "ubicom32_fdpic_operand"
++  (match_code "reg")
++{
++  if (! TARGET_FDPIC)
++    return false;
++
++  if (!REG_P (op))
++    return false;
++
++  if (GET_MODE (op) != mode && mode != VOIDmode)
++    return false;
++
++  if (REGNO (op) != FDPIC_REGNUM && REGNO (op) < FIRST_PSEUDO_REGISTER)
++    return false;
++
++  return true;
++})
++
++(define_predicate "ubicom32_fdpic_got_offset_operand"
++  (match_code "unspec")
++{
++  if (! TARGET_FDPIC)
++    return false;
++
++  if (GET_CODE (op) != UNSPEC)
++    return false;
++
++  if (XINT (op, 1) != UNSPEC_FDPIC_GOT
++      && XINT (op, 1) != UNSPEC_FDPIC_GOT_FUNCDESC)
++    return false;
++
++  return true;
++})
++
++(define_predicate "ubicom32_arith_operand"
++  (match_code "subreg, reg, const_int, lo_sum, mem")
++{
++  return (ubicom32_move_operand (op, mode)
++        && ! ubicom32_symbolic_address_operand (op, mode)
++        && (! CONST_INT_P (op)
++            || satisfies_constraint_I (op)));
++})
++
++(define_predicate "ubicom32_arith_operand_dot1"
++  (match_code "subreg, reg, const_int, lo_sum, mem")
++{
++  return (ubicom32_move_operand (op, mode)
++        && ! ubicom32_symbolic_address_operand (op, mode)
++        && (! CONST_INT_P (op)
++            || satisfies_constraint_Q (op)));
++})
++
++(define_predicate "ubicom32_arith_operand_dot2"
++  (match_code "subreg, reg, const_int, lo_sum, mem")
++{
++  return (ubicom32_move_operand (op, mode)
++        && ! ubicom32_symbolic_address_operand (op, mode)
++        && (! CONST_INT_P (op)
++            || satisfies_constraint_R (op)));
++})
++
++(define_predicate "ubicom32_compare_operand"
++  (match_code "subreg, reg, const_int, lo_sum, mem")
++{
++ return (ubicom32_move_operand (op, mode)
++        && ! ubicom32_symbolic_address_operand (op, mode)
++        && (! CONST_INT_P (op)
++            || satisfies_constraint_N (op)));
++})
++
++(define_predicate "ubicom32_compare_operator"
++  (match_code "compare"))
++
++(define_predicate "ubicom32_and_or_si3_operand"
++  (match_code "subreg, reg, const_int, lo_sum, mem")
++{
++  return (ubicom32_arith_operand (op, mode)
++        || (CONST_INT_P (op)
++            && ((exact_log2 (INTVAL (op) + 1) != -1
++                 && exact_log2 (INTVAL (op) + 1) <= 31)
++                || (exact_log2 (INTVAL (op)) != -1
++                    && exact_log2 (INTVAL (op)) <= 31)
++                || (exact_log2 (~INTVAL (op)) != -1
++                    && exact_log2 (~INTVAL (op)) <= 31))));
++})
++
++(define_predicate "ubicom32_and_or_hi3_operand"
++  (match_code "subreg, reg, const_int, lo_sum, mem")
++{
++  return (ubicom32_arith_operand (op, mode)
++        || (CONST_INT_P (op)
++            && exact_log2 (INTVAL (op) + 1) != -1
++            && exact_log2 (INTVAL (op) + 1) <= 15));
++})
++
++(define_predicate "ubicom32_mem_or_address_register_operand"
++  (match_code "subreg, reg, mem")
++{
++  unsigned int regno;
++
++  if (MEM_P (op)
++      && memory_operand (op, mode))
++    return true;
++
++  if (REG_P (op))
++    regno = REGNO (op);
++  else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
++    {
++      int offset;
++      if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
++      offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
++      else
++      offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
++                                    GET_MODE (SUBREG_REG (op)),
++                                    SUBREG_BYTE (op),
++                                    GET_MODE (op));
++      regno = REGNO (SUBREG_REG (op)) + offset;
++    }
++  else
++    return false;
++
++  return (regno >= FIRST_PSEUDO_REGISTER 
++        || REGNO_REG_CLASS (regno) == FDPIC_REG
++        || REGNO_REG_CLASS (regno) == ADDRESS_REGS);
++})
++
++(define_predicate "ubicom32_data_register_operand"
++  (match_code "subreg, reg")
++{
++  unsigned int regno;
++
++  if (REG_P (op))
++    regno = REGNO (op);
++  else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
++    {
++      int offset;
++      if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
++      offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
++      else
++      offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
++                                    GET_MODE (SUBREG_REG (op)),
++                                    SUBREG_BYTE (op),
++                                    GET_MODE (op));
++      regno = REGNO (SUBREG_REG (op)) + offset;
++    }
++  else
++    return false;
++
++  return ((regno >= FIRST_PSEUDO_REGISTER 
++         && regno != REGNO (virtual_stack_vars_rtx))
++        || REGNO_REG_CLASS (regno) == DATA_REGS);
++})
++
++(define_predicate "ubicom32_address_register_operand"
++  (match_code "subreg, reg")
++{
++  unsigned int regno;
++
++  if (REG_P (op))
++    regno = REGNO (op);
++  else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
++    {
++      int offset;
++      if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
++      offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
++      else
++      offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
++                                    GET_MODE (SUBREG_REG (op)),
++                                    SUBREG_BYTE (op),
++                                    GET_MODE (op));
++      regno = REGNO (SUBREG_REG (op)) + offset;
++    }
++  else
++    return false;
++
++  return (regno >= FIRST_PSEUDO_REGISTER 
++        || REGNO_REG_CLASS (regno) == FDPIC_REG
++        || REGNO_REG_CLASS (regno) == ADDRESS_REGS);
++})
++
++(define_predicate "ubicom32_acc_lo_register_operand"
++  (match_code "subreg, reg")
++{
++  unsigned int regno;
++
++  if (REG_P (op))
++    regno = REGNO (op);
++  else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
++    {
++      int offset;
++      if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
++      offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
++      else
++      offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
++                                    GET_MODE (SUBREG_REG (op)),
++                                    SUBREG_BYTE (op),
++                                    GET_MODE (op));
++      regno = REGNO (SUBREG_REG (op)) + offset;
++    }
++  else
++    return false;
++
++  return ((regno >= FIRST_PSEUDO_REGISTER 
++         && regno != REGNO (virtual_stack_vars_rtx))
++        || REGNO_REG_CLASS (regno) == ACC_LO_REGS);
++})
++
++(define_predicate "ubicom32_acc_hi_register_operand"
++  (match_code "subreg, reg")
++{
++  unsigned int regno;
++
++  if (REG_P (op))
++    regno = REGNO (op);
++  else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
++    {
++      int offset;
++      if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
++      offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
++      else
++      offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
++                                    GET_MODE (SUBREG_REG (op)),
++                                    SUBREG_BYTE (op),
++                                    GET_MODE (op));
++      regno = REGNO (SUBREG_REG (op)) + offset;
++    }
++  else
++    return false;
++
++  return ((regno >= FIRST_PSEUDO_REGISTER 
++         && regno != REGNO (virtual_stack_vars_rtx))
++        || REGNO_REG_CLASS (regno) == ACC_REGS);
++})
++
++(define_predicate "ubicom32_call_address_operand"
++  (match_code "symbol_ref, subreg, reg")
++{
++  return (GET_CODE (op) == SYMBOL_REF || REG_P (op));
++})
++
++(define_special_predicate "ubicom32_cc_register_operand"
++  (and (match_code "reg")
++       (match_test "REGNO (op) == CC_REGNUM")))
++
+--- /dev/null
++++ b/gcc/config/ubicom32/t-ubicom32
+@@ -0,0 +1,52 @@
++# Name of assembly file containing libgcc1 functions.
++# This entry must be present, but it can be empty if the target does
++# not need any assembler functions to support its code generation.
++CROSS_LIBGCC1 =
++
++# Alternatively if assembler functions *are* needed then define the
++# entries below:
++# CROSS_LIBGCC1 = libgcc1-asm.a
++
++LIB2FUNCS_EXTRA = \
++      $(srcdir)/config/udivmodsi4.c \
++      $(srcdir)/config/divmod.c \
++      $(srcdir)/config/udivmod.c
++
++# If any special flags are necessary when building libgcc2 put them here.
++#
++# TARGET_LIBGCC2_CFLAGS = 
++
++# We want fine grained libraries, so use the new code to build the
++# floating point emulation libraries.
++FPBIT = fp-bit.c
++DPBIT = dp-bit.c
++
++fp-bit.c: $(srcdir)/config/fp-bit.c
++      echo '#define FLOAT'                            > fp-bit.c
++      cat $(srcdir)/config/fp-bit.c                   >> fp-bit.c
++
++dp-bit.c: $(srcdir)/config/fp-bit.c
++      cat $(srcdir)/config/fp-bit.c > dp-bit.c
++
++# Commented out to speed up compiler development!
++#
++# MULTILIB_OPTIONS = march=ubicom32v1/march=ubicom32v2/march=ubicom32v3/march=ubicom32v4
++# MULTILIB_DIRNAMES = ubicom32v1 ubicom32v2 ubicom32v3 ubicom32v4
++
++MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4
++MULTILIB_OPTIONS += mfdpic
++MULTILIB_OPTIONS += mno-ipos-abi/mipos-abi
++MULTILIB_OPTIONS += fno-leading-underscore/fleading-underscore
++
++# Assemble startup files.
++$(T)crti.o: $(srcdir)/config/ubicom32/crti.S $(GCC_PASSES)
++      $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
++      -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/ubicom32/crti.S
++
++$(T)crtn.o: $(srcdir)/config/ubicom32/crtn.S $(GCC_PASSES)
++      $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
++      -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/ubicom32/crtn.S
++
++# these parts are required because uClibc ldso needs them to link.
++# they are not in the specfile so they will not be included automatically.
++EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o crti.o crtn.o
+--- /dev/null
++++ b/gcc/config/ubicom32/t-ubicom32-linux
+@@ -0,0 +1,35 @@
++# Name of assembly file containing libgcc1 functions.
++# This entry must be present, but it can be empty if the target does
++# not need any assembler functions to support its code generation.
++CROSS_LIBGCC1 =
++
++# Alternatively if assembler functions *are* needed then define the
++# entries below:
++# CROSS_LIBGCC1 = libgcc1-asm.a
++
++LIB2FUNCS_EXTRA = \
++      $(srcdir)/config/udivmodsi4.c \
++      $(srcdir)/config/divmod.c \
++      $(srcdir)/config/udivmod.c
++
++# If any special flags are necessary when building libgcc2 put them here.
++#
++# TARGET_LIBGCC2_CFLAGS =
++
++# We want fine grained libraries, so use the new code to build the
++# floating point emulation libraries.
++FPBIT = fp-bit.c
++DPBIT = dp-bit.c
++
++fp-bit.c: $(srcdir)/config/fp-bit.c
++      echo '#define FLOAT'                            > fp-bit.c
++      cat $(srcdir)/config/fp-bit.c                   >> fp-bit.c
++
++dp-bit.c: $(srcdir)/config/fp-bit.c
++      cat $(srcdir)/config/fp-bit.c > dp-bit.c
++
++# We only support v3 and v4 ISAs for uClinux.
++
++MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4
++
++#EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o
+--- /dev/null
++++ b/gcc/config/ubicom32/t-ubicom32-uclinux
+@@ -0,0 +1,35 @@
++# Name of assembly file containing libgcc1 functions.
++# This entry must be present, but it can be empty if the target does
++# not need any assembler functions to support its code generation.
++CROSS_LIBGCC1 =
++
++# Alternatively if assembler functions *are* needed then define the
++# entries below:
++# CROSS_LIBGCC1 = libgcc1-asm.a
++
++LIB2FUNCS_EXTRA = \
++      $(srcdir)/config/udivmodsi4.c \
++      $(srcdir)/config/divmod.c \
++      $(srcdir)/config/udivmod.c
++
++# If any special flags are necessary when building libgcc2 put them here.
++#
++# TARGET_LIBGCC2_CFLAGS = 
++
++# We want fine grained libraries, so use the new code to build the
++# floating point emulation libraries.
++FPBIT = fp-bit.c
++DPBIT = dp-bit.c
++
++fp-bit.c: $(srcdir)/config/fp-bit.c
++      echo '#define FLOAT'                            > fp-bit.c
++      cat $(srcdir)/config/fp-bit.c                   >> fp-bit.c
++
++dp-bit.c: $(srcdir)/config/fp-bit.c
++      cat $(srcdir)/config/fp-bit.c > dp-bit.c
++
++# We only support v3 and v4 ISAs for uClinux.
++
++MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4
++
++EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o # crtbeginS.o crtendS.o
+--- /dev/null
++++ b/gcc/config/ubicom32/ubicom32-modes.def
+@@ -0,0 +1,30 @@
++/* Definitions of target machine for GNU compiler, Ubicom32 architecture.
++   Copyright (C) 2009 Free Software Foundation, Inc.
++   Contributed by Ubicom, Inc.
++
++   This file is part of GCC.
++
++   GCC is free software; you can redistribute it and/or modify it
++   under the terms of the GNU General Public License as published
++   by the Free Software Foundation; either version 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/>.  */
++
++/* Some insns set all condition code flags, some only set the Z and N flags, and
++   some only set the Z flag.  */
++
++CC_MODE (CCW);
++CC_MODE (CCWZN);
++CC_MODE (CCWZ);
++CC_MODE (CCS);
++CC_MODE (CCSZN);
++CC_MODE (CCSZ);
++
+--- /dev/null
++++ b/gcc/config/ubicom32/ubicom32-protos.h
+@@ -0,0 +1,84 @@
++/* Function prototypes for Ubicom IP3000.
++
++   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
++   2009 Free Software Foundation, Inc.
++   Contributed by Ubicom, Inc.
++
++   This file is part of GNU CC.
++
++   GNU CC is free software; you can redistribute it and/or modify it under
++   the terms of the GNU General Public License as published by the Free
++   Software Foundation; either version 2, or (at your option) any later
++   version.
++
++   GNU CC is distributed in the hope that it will be useful, but WITHOUT
++   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++   for more details.
++
++   You should have received a copy of the GNU General Public License along
++   with GNU CC; see the file COPYING.  If not, write to the Free Software
++   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
++
++#ifdef RTX_CODE
++
++#ifdef TREE_CODE
++extern void ubicom32_va_start (tree, rtx);
++#endif /* TREE_CODE */
++
++extern void ubicom32_print_operand (FILE *, rtx, int);
++extern void ubicom32_print_operand_address (FILE *, rtx);
++
++extern void ubicom32_conditional_register_usage (void);
++extern enum reg_class ubicom32_preferred_reload_class (rtx, enum reg_class);
++extern int ubicom32_regno_ok_for_index_p (int, int);
++extern void ubicom32_expand_movsi (rtx *);
++extern void ubicom32_expand_addsi3 (rtx *);
++extern int ubicom32_emit_mult_sequence (rtx *);
++extern void ubicom32_emit_move_const_int (rtx, rtx);
++extern bool ubicom32_legitimate_constant_p (rtx);
++extern bool ubicom32_legitimate_address_p (enum machine_mode, rtx, int);
++extern rtx ubicom32_legitimize_address (rtx, rtx, enum machine_mode);
++extern rtx ubicom32_legitimize_reload_address (rtx, enum machine_mode, int, int);
++extern void ubicom32_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1);
++extern int ubicom32_mode_dependent_address_p (rtx);
++extern void ubicom32_output_cond_jump (rtx, rtx, rtx);
++extern void ubicom32_expand_eh_return (rtx *);
++extern void ubicom32_expand_call_fdpic (rtx *);
++extern void ubicom32_expand_call_value_fdpic (rtx *);
++extern enum machine_mode ubicom32_select_cc_mode (RTX_CODE, rtx, rtx);
++extern rtx ubicom32_gen_compare_reg (RTX_CODE, rtx, rtx);
++extern int ubicom32_shiftable_const_int (int);
++#endif /* RTX_CODE */
++
++#ifdef TREE_CODE
++extern void init_cumulative_args (CUMULATIVE_ARGS *cum,
++                                tree fntype,
++                                struct rtx_def *libname,
++                                int indirect);
++extern struct rtx_def *function_arg (CUMULATIVE_ARGS *,
++                                   enum machine_mode, tree, int);
++extern struct rtx_def *function_incoming_arg (CUMULATIVE_ARGS *,
++                                            enum machine_mode,
++                                            tree, int);
++extern int function_arg_partial_nregs (CUMULATIVE_ARGS *,
++                                     enum machine_mode, tree, int);
++extern struct rtx_def *ubicom32_va_arg (tree, tree);
++extern int ubicom32_reg_parm_stack_space (tree);
++#endif /* TREE_CODE */
++
++extern struct rtx_def * ubicom32_builtin_saveregs (void);
++extern void asm_file_start (FILE *);
++extern void ubicom32_expand_prologue (void);
++extern void ubicom32_expand_epilogue (void);
++extern int ubicom32_initial_elimination_offset (int, int);
++extern int ubicom32_regno_ok_for_base_p (int, int);
++extern bool ubicom32_hard_regno_mode_ok (unsigned int, enum machine_mode);
++extern int ubicom32_can_use_return_insn_p (void);
++extern rtx ubicom32_return_addr_rtx (int, rtx);
++extern void ubicom32_optimization_options (int, int);
++extern void ubicom32_override_options (void);
++extern bool ubicom32_match_cc_mode (rtx, enum machine_mode);
++
++extern int ubicom32_reorg_completed;
++
+--- /dev/null
++++ b/gcc/config/ubicom32/ubicom32.c
+@@ -0,0 +1,2881 @@
++/* Subroutines for insn-output.c for Ubicom32
++
++   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
++   2009 Free Software Foundation, Inc.
++   Contributed by Ubicom, Inc.
++
++   This file is part of GCC.
++
++   GCC is free software; you can redistribute it and/or modify it
++   under the terms of the GNU General Public License as published
++   by the Free Software Foundation; either version 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/>.  */
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "rtl.h"
++#include "tree.h"
++#include "regs.h"
++#include "hard-reg-set.h"
++#include "real.h"
++#include "insn-config.h"
++#include "conditions.h"
++#include "insn-flags.h"
++#include "output.h"
++#include "insn-attr.h"
++#include "insn-codes.h"
++#include "flags.h"
++#include "recog.h"
++#include "expr.h"
++#include "function.h"
++#include "obstack.h"
++#include "toplev.h"
++#include "tm_p.h"
++#include "tm-constrs.h"
++#include "basic-block.h"
++#include "integrate.h"
++#include "target.h"
++#include "target-def.h"
++#include "reload.h"
++#include "df.h"
++#include "langhooks.h"
++#include "optabs.h"
++
++static tree ubicom32_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
++static void ubicom32_layout_frame (void);
++static void ubicom32_function_prologue (FILE *, HOST_WIDE_INT);
++static void ubicom32_function_epilogue (FILE *, HOST_WIDE_INT);
++static bool ubicom32_rtx_costs (rtx, int, int, int *, bool speed);
++static bool ubicom32_fixed_condition_code_regs (unsigned int *,
++                                              unsigned int *);
++static enum machine_mode ubicom32_cc_modes_compatible (enum machine_mode,
++                                                     enum machine_mode);
++static int ubicom32_naked_function_p (void);
++static void ubicom32_machine_dependent_reorg (void);
++static bool ubicom32_assemble_integer (rtx, unsigned int, int);
++static void ubicom32_asm_init_sections (void);
++static int ubicom32_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,tree, 
++                                     bool);
++static bool ubicom32_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
++                                      enum machine_mode mode, const_tree type,
++                                      bool named ATTRIBUTE_UNUSED);
++static bool ubicom32_callee_copies (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
++                                  enum machine_mode mode, const_tree type,
++                                  bool named ATTRIBUTE_UNUSED);
++
++static bool ubicom32_return_in_memory (const_tree type, 
++                                     const_tree fntype ATTRIBUTE_UNUSED);
++static bool ubicom32_is_base_reg (rtx, int);
++static void ubicom32_init_builtins (void);
++static rtx ubicom32_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
++static tree ubicom32_fold_builtin (tree, tree, bool);
++static int ubicom32_get_valid_offset_mask (enum machine_mode);
++static bool ubicom32_cannot_force_const_mem (rtx);
++
++/* Case values threshold */
++int ubicom32_case_values_threshold = 6;
++
++/* Nonzero if this chip supports the Ubicom32 v3 ISA.  */
++int ubicom32_v3 = 1;
++
++/* Nonzero if this chip supports the Ubicom32 v4 ISA.  */
++int ubicom32_v4 = 1;
++
++/* Valid attributes:
++   naked - don't generate function prologue/epilogue and `ret' command.  */
++const struct attribute_spec ubicom32_attribute_table[] =
++{
++  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
++  { "naked", 0, 0, true,  false, false, ubicom32_handle_fndecl_attribute },
++  { NULL,    0, 0, false, false, false, NULL }
++};
++
++#undef TARGET_ASM_FUNCTION_PROLOGUE
++#define TARGET_ASM_FUNCTION_PROLOGUE ubicom32_function_prologue
++
++#undef TARGET_ASM_FUNCTION_EPILOGUE
++#define TARGET_ASM_FUNCTION_EPILOGUE ubicom32_function_epilogue
++
++#undef TARGET_ATTRIBUTE_TABLE
++#define TARGET_ATTRIBUTE_TABLE ubicom32_attribute_table
++
++/* All addresses cost the same amount.  */
++#undef TARGET_ADDRESS_COST
++#define TARGET_ADDRESS_COST hook_int_rtx_bool_0
++
++#undef TARGET_RTX_COSTS
++#define TARGET_RTX_COSTS ubicom32_rtx_costs
++
++#undef TARGET_FIXED_CONDITION_CODE_REGS
++#define TARGET_FIXED_CONDITION_CODE_REGS ubicom32_fixed_condition_code_regs
++
++#undef TARGET_CC_MODES_COMPATIBLE
++#define TARGET_CC_MODES_COMPATIBLE ubicom32_cc_modes_compatible
++
++#undef TARGET_MACHINE_DEPENDENT_REORG
++#define TARGET_MACHINE_DEPENDENT_REORG ubicom32_machine_dependent_reorg
++
++#undef  TARGET_ASM_INTEGER
++#define TARGET_ASM_INTEGER ubicom32_assemble_integer
++
++#undef TARGET_ASM_INIT_SECTIONS
++#define TARGET_ASM_INIT_SECTIONS ubicom32_asm_init_sections
++
++#undef TARGET_ARG_PARTIAL_BYTES
++#define TARGET_ARG_PARTIAL_BYTES ubicom32_arg_partial_bytes
++
++#undef TARGET_PASS_BY_REFERENCE
++#define TARGET_PASS_BY_REFERENCE ubicom32_pass_by_reference
++
++#undef TARGET_CALLEE_COPIES
++#define TARGET_CALLEE_COPIES ubicom32_callee_copies
++
++#undef TARGET_RETURN_IN_MEMORY
++#define TARGET_RETURN_IN_MEMORY ubicom32_return_in_memory
++
++#undef TARGET_INIT_BUILTINS
++#define TARGET_INIT_BUILTINS ubicom32_init_builtins
++
++#undef TARGET_EXPAND_BUILTIN
++#define TARGET_EXPAND_BUILTIN ubicom32_expand_builtin
++
++#undef TARGET_FOLD_BUILTIN
++#define TARGET_FOLD_BUILTIN ubicom32_fold_builtin
++
++#undef TARGET_CANNOT_FORCE_CONST_MEM
++#define TARGET_CANNOT_FORCE_CONST_MEM ubicom32_cannot_force_const_mem
++
++struct gcc_target targetm = TARGET_INITIALIZER;
++
++static char save_regs[FIRST_PSEUDO_REGISTER];
++static int nregs;
++static int frame_size;
++int ubicom32_stack_size = 0;  /* size of allocated stack (including frame) */
++int ubicom32_can_use_calli_to_ret;
++
++#define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
++#define ROUND_CALL_BLOCK_SIZE(BYTES) \
++  (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
++
++/* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference, we
++   must report the mode of the memory reference from PRINT_OPERAND to
++   PRINT_OPERAND_ADDRESS.  */
++enum machine_mode output_memory_reference_mode;
++
++/* Flag for some split insns from the ubicom32.md.  */
++int ubicom32_reorg_completed;
++
++enum reg_class const ubicom32_regclass_map[FIRST_PSEUDO_REGISTER] =
++{
++  DATA_REGS, 
++  DATA_REGS, 
++  DATA_REGS, 
++  DATA_REGS, 
++  DATA_REGS, 
++  DATA_REGS, 
++  DATA_REGS, 
++  DATA_REGS, 
++  DATA_REGS, 
++  DATA_REGS, 
++  DATA_REGS, 
++  DATA_REGS, 
++  DATA_REGS, 
++  DATA_REGS, 
++  DATA_REGS, 
++  DATA_REGS, 
++  FDPIC_REG, 
++  ADDRESS_REGS, 
++  ADDRESS_REGS, 
++  ADDRESS_REGS, 
++  ADDRESS_REGS, 
++  ADDRESS_REGS, 
++  ADDRESS_REGS, 
++  ADDRESS_REGS, 
++  ACC_REGS,
++  ACC_LO_REGS,
++  ACC_REGS,
++  ACC_LO_REGS,
++  SOURCE3_REG,
++  ADDRESS_REGS,
++  NO_REGS,                    /* CC_REG must be NO_REGS */
++  SPECIAL_REGS,
++  SPECIAL_REGS,
++  SPECIAL_REGS,
++  SPECIAL_REGS,
++  SPECIAL_REGS,
++  SPECIAL_REGS,
++  SPECIAL_REGS,
++  SPECIAL_REGS
++};
++
++rtx ubicom32_compare_op0;
++rtx ubicom32_compare_op1;
++
++/* Handle command line option overrides.  */
++
++void
++ubicom32_override_options (void)
++{
++  flag_pic = 0;
++
++  if (strcmp (ubicom32_arch_name, "ubicom32v1") == 0) {
++    /* If we have a version 1 architecture then we want to avoid using jump
++       tables.  */
++    ubicom32_case_values_threshold = 30000;
++    ubicom32_v3 = 0;
++    ubicom32_v4 = 0;
++  } else if (strcmp (ubicom32_arch_name, "ubicom32v2") == 0) {
++    ubicom32_v3 = 0;
++    ubicom32_v4 = 0;
++  } else if (strcmp (ubicom32_arch_name, "ubicom32v3") == 0) {
++    ubicom32_v3 = 1;
++    ubicom32_v4 = 0;
++  } else if (strcmp (ubicom32_arch_name, "ubicom32v4") == 0) {
++    ubicom32_v3 = 1;
++    ubicom32_v4 = 1;
++  }
++
++  /* There is no single unaligned SI op for PIC code.  Sometimes we
++     need to use ".4byte" and sometimes we need to use ".picptr".
++     See ubicom32_assemble_integer for details.  */
++  if (TARGET_FDPIC)
++    targetm.asm_out.unaligned_op.si = 0;
++}
++
++void
++ubicom32_conditional_register_usage (void)
++{
++  /* If we're using the old ipOS ABI we need to make D10 through D13
++     caller-clobbered.  */
++  if (TARGET_IPOS_ABI)
++    {
++      call_used_regs[D10_REGNUM] = 1;
++      call_used_regs[D11_REGNUM] = 1;
++      call_used_regs[D12_REGNUM] = 1;
++      call_used_regs[D13_REGNUM] = 1;
++    }
++}
++
++/* We have some number of optimizations that don't really work for the Ubicom32
++   architecture so we deal with them here.  */
++
++void
++ubicom32_optimization_options (int level ATTRIBUTE_UNUSED,
++                             int size ATTRIBUTE_UNUSED)
++{
++  /* The tree IVOPTs pass seems to do really bad things for the Ubicom32
++     architecture - it tends to turn things that would happily use pre/post
++     increment/decrement into operations involving unecessary loop
++     indicies.  */
++  flag_ivopts = 0;
++
++  /* We have problems where DSE at the RTL level misses partial stores
++     to the stack.  For now we disable it to avoid this.  */
++  flag_dse = 0;
++}
++
++/* Print operand X using operand code CODE to assembly language output file
++   FILE.  */
++
++void
++ubicom32_print_operand (FILE *file, rtx x, int code)
++{
++  switch (code)
++    {
++    case 'A':
++      /* Identify the correct accumulator to use.  */
++      if (REGNO (x) == ACC0_HI_REGNUM || REGNO (x) == ACC0_LO_REGNUM)
++      fprintf (file, "acc0");
++      else if (REGNO (x) == ACC1_HI_REGNUM || REGNO (x) == ACC1_LO_REGNUM)
++      fprintf (file, "acc1");
++      else
++      abort ();
++      break;
++
++    case 'b':
++    case 'B':
++      {
++      enum machine_mode mode;
++
++      mode = GET_MODE (XEXP (x, 0));
++
++      /* These are normal and reversed branches.  */
++      switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x)))
++        {
++        case NE:
++          fprintf (file, "ne");
++          break;
++
++        case EQ:
++          fprintf (file, "eq");
++          break;
++
++        case GE:
++          if (mode == CCSZNmode || mode == CCWZNmode)
++            fprintf (file, "pl");
++          else
++            fprintf (file, "ge");
++          break;
++
++        case GT:
++          fprintf (file, "gt");
++          break;
++
++        case LE:
++          fprintf (file, "le");
++          break;
++
++        case LT:
++          if (mode == CCSZNmode || mode == CCWZNmode)
++            fprintf (file, "mi");
++          else
++            fprintf (file, "lt");
++          break;
++
++        case GEU:
++          fprintf (file, "cs");
++          break;
++
++        case GTU:
++          fprintf (file, "hi");
++          break;
++
++        case LEU:
++          fprintf (file, "ls");
++          break;
++
++        case LTU:
++          fprintf (file, "cc");
++          break;
++
++        default:
++          abort ();
++        }
++      }
++      break;
++
++    case 'C':
++      /* This is used for the operand to a call instruction;
++       if it's a REG, enclose it in parens, else output
++       the operand normally.  */
++      if (REG_P (x))
++      {
++        fputc ('(', file);
++        ubicom32_print_operand (file, x, 0);
++        fputc (')', file);
++      }
++      else
++      ubicom32_print_operand (file, x, 0);
++      break;
++
++    case 'd':
++      /* Bit operations we need bit numbers. */
++      fprintf (file, "%d", exact_log2 (INTVAL (x)));
++      break;
++
++    case 'D':
++      /* Bit operations we need bit numbers. */
++      fprintf (file, "%d", exact_log2 (~ INTVAL (x)));
++      break;
++
++    case 'E':
++      /* For lea, which we use to add address registers.
++       We don't want the '#' on a constant. */
++      if (CONST_INT_P (x))
++      {
++        fprintf (file, "%ld", INTVAL (x));
++        break;
++      }
++      /* FALL THROUGH */
++
++    default:
++      switch (GET_CODE (x))
++      {
++      case MEM:
++        output_memory_reference_mode = GET_MODE (x);
++        output_address (XEXP (x, 0));
++        break;
++
++      case PLUS:
++        output_address (x);
++        break;
++
++      case REG:
++        fprintf (file, "%s", reg_names[REGNO (x)]);
++        break;
++
++      case SUBREG:
++        fprintf (file, "%s", reg_names[subreg_regno (x)]);
++        break;
++
++      /* This will only be single precision....  */
++      case CONST_DOUBLE:
++        {
++          unsigned long val;
++          REAL_VALUE_TYPE rv;
++
++          REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
++          REAL_VALUE_TO_TARGET_SINGLE (rv, val);
++          fprintf (file, "0x%lx", val);
++          break;
++        }
++
++      case CONST_INT:
++      case SYMBOL_REF:
++      case CONST:
++      case LABEL_REF:
++      case CODE_LABEL:
++      case LO_SUM:
++        ubicom32_print_operand_address (file, x);
++        break;
++
++      case HIGH:
++        fprintf (file, "#%%hi(");
++        ubicom32_print_operand_address (file, XEXP (x, 0));
++        fprintf (file, ")");
++        break;
++
++      case UNSPEC:
++        switch (XINT (x, 1))
++          {
++          case UNSPEC_FDPIC_GOT:
++            fprintf (file, "#%%got_lo(");
++            ubicom32_print_operand_address (file, XVECEXP (x, 0, 0));
++            fprintf (file, ")");
++            break;
++
++          case UNSPEC_FDPIC_GOT_FUNCDESC:
++            fprintf (file, "#%%got_funcdesc_lo(");
++            ubicom32_print_operand_address (file, XVECEXP (x, 0, 0));
++            fprintf (file, ")");
++            break;
++
++          default:
++            abort ();
++          }
++          break;
++
++      default:
++        abort ();
++      }
++      break;
++   }
++}
++
++/* Output assembly language output for the address ADDR to FILE.  */
++
++void
++ubicom32_print_operand_address (FILE *file, rtx addr)
++{
++  switch (GET_CODE (addr))
++    {
++    case POST_INC:
++      ubicom32_print_operand_address (file, XEXP (addr, 0));
++      fprintf (file, "%d++", GET_MODE_SIZE (output_memory_reference_mode));
++      break;
++
++    case PRE_INC:
++      fprintf (file, "%d", GET_MODE_SIZE (output_memory_reference_mode));
++      ubicom32_print_operand_address (file, XEXP (addr, 0));
++      fprintf (file, "++");
++      break;
++
++    case POST_DEC:
++      ubicom32_print_operand_address (file, XEXP (addr, 0));
++      fprintf (file, "%d++", -GET_MODE_SIZE (output_memory_reference_mode));
++      break;
++
++    case PRE_DEC:
++      fprintf (file, "%d", -GET_MODE_SIZE (output_memory_reference_mode));
++      ubicom32_print_operand_address (file, XEXP (addr, 0));
++      fprintf (file, "++");
++      break;
++
++    case POST_MODIFY:
++      ubicom32_print_operand_address (file, XEXP (addr, 0));
++      fprintf (file, "%ld++", INTVAL (XEXP (XEXP (addr,1), 1)));
++      break;
++
++    case PRE_MODIFY:
++      fprintf (file, "%ld", INTVAL (XEXP (XEXP (addr,1), 1)));
++      ubicom32_print_operand_address (file, XEXP (addr, 0));
++      fprintf (file, "++");
++      break;
++
++    case REG:
++      fputc ('(', file);
++      fprintf (file, "%s", reg_names[REGNO (addr)]); 
++      fputc (')', file);
++      break;
++
++    case PLUS:
++      {
++      rtx base = XEXP (addr, 0);
++      rtx index = XEXP (addr, 1); 
++
++      /* Switch around addresses of the form index * scaling + base.  */
++      if (! ubicom32_is_base_reg (base, 1))
++        {
++          rtx tmp = base;
++          base = index;
++          index = tmp;
++        }
++
++      if (CONST_INT_P (index)) 
++        {
++          fprintf (file, "%ld", INTVAL (index)); 
++          fputc ('(', file);
++          fputs (reg_names[REGNO (base)], file); 
++        }
++      else if (GET_CODE (index) == MULT
++               || REG_P (index))
++        {
++          if (GET_CODE (index) == MULT)
++            index = XEXP (index, 0);
++          fputc ('(', file);
++          fputs (reg_names[REGNO (base)], file); 
++          fputc (',', file);
++          fputs (reg_names[REGNO (index)], file); 
++        }
++      else 
++        abort (); 
++
++      fputc (')', file);
++      break;
++      }
++
++    case LO_SUM:
++      fprintf (file, "%%lo(");
++      ubicom32_print_operand (file, XEXP (addr, 1), 'L');
++      fprintf (file, ")(");
++      ubicom32_print_operand (file, XEXP (addr, 0), 0);
++      fprintf (file, ")");
++      break;
++
++    case CONST_INT:
++      fputc ('#', file);
++      output_addr_const (file, addr); 
++      break;
++
++    default:
++      output_addr_const (file, addr);
++      break;
++    }
++}
++
++/* X and Y are two things to compare using CODE.  Emit the compare insn and
++   return the rtx for the cc reg in the proper mode.  */
++
++rtx
++ubicom32_gen_compare_reg (enum rtx_code code, rtx x, rtx y)
++{
++  enum machine_mode mode = SELECT_CC_MODE (code, x, y);
++  rtx cc_reg;
++
++  cc_reg = gen_rtx_REG (mode, CC_REGNUM);
++
++  emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
++                        gen_rtx_COMPARE (mode, x, y)));
++
++  return cc_reg;
++}
++
++/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
++   return the mode to be used for the comparison.  */
++
++enum machine_mode
++ubicom32_select_cc_mode (enum rtx_code op, rtx x, rtx y)
++{
++  /* Is this a short compare?  */
++  if (GET_MODE (x) == QImode
++      || GET_MODE (x) == HImode
++      || GET_MODE (y) == QImode
++      || GET_MODE (y) == HImode)
++    {
++      switch (op)
++      {
++      case EQ :
++      case NE :
++        return CCSZmode;
++
++      case GE:
++      case LT:
++        if (y == const0_rtx)
++          return CCSZNmode;
++
++      default :
++        return CCSmode;
++      }
++    }
++
++  /* We have a word compare.  */
++  switch (op)
++    {
++    case EQ :
++    case NE :
++      return CCWZmode;
++
++    case GE :
++    case LT :
++      if (y == const0_rtx)
++      return CCWZNmode;
++
++    default :
++      return CCWmode;
++    }
++}
++
++/* Return TRUE or FALSE depending on whether the first SET in INSN
++   has source and destination with matching CC modes, and that the
++   CC mode is at least as constrained as REQ_MODE.  */
++bool
++ubicom32_match_cc_mode (rtx insn, enum machine_mode req_mode)
++{
++  rtx set;
++  enum machine_mode set_mode;
++
++  set = PATTERN (insn);
++  if (GET_CODE (set) == PARALLEL)
++    set = XVECEXP (set, 0, 0);
++  gcc_assert (GET_CODE (set) == SET);
++  gcc_assert (GET_CODE (SET_SRC (set)) == COMPARE);
++
++  /* SET_MODE is the mode we have in the instruction.  This must either
++     be the same or less restrictive that the required mode REQ_MODE.  */
++  set_mode = GET_MODE (SET_DEST (set));
++
++  switch (req_mode)
++    {
++    case CCSZmode:
++      if (set_mode != CCSZmode)
++      return 0;
++      break;
++
++    case CCSZNmode:
++      if (set_mode != CCSZmode
++        && set_mode != CCSZNmode)
++      return 0;
++      break;
++
++    case CCSmode:
++      if (set_mode != CCSmode
++        && set_mode != CCSZmode
++        && set_mode != CCSZNmode)
++      return 0;
++      break;
++
++    case CCWZmode:
++      if (set_mode != CCWZmode)
++      return 0;
++      break;
++
++    case CCWZNmode:
++      if (set_mode != CCWZmode
++        && set_mode != CCWZNmode)
++      return 0;
++      break;
++
++    case CCWmode:
++      if (set_mode != CCWmode
++        && set_mode != CCWZmode
++        && set_mode != CCWZNmode)
++      return 0;
++      break;
++
++    default:
++      gcc_unreachable ();
++    }
++
++  return (GET_MODE (SET_SRC (set)) == set_mode);
++}
++
++/* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
++   that we can implement more efficiently.  */
++
++void
++ubicom32_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
++{
++  /* If we have a REG and a MEM then compare the MEM with the REG and not
++     the other way round.  */
++  if (REG_P (*op0) && MEM_P (*op1))
++    {
++      rtx tem = *op0;
++      *op0 = *op1;
++      *op1 = tem;
++      *code = swap_condition (*code);
++      return;
++    }
++
++  /* If we have a REG and a CONST_INT then we may want to reverse things
++     if the constant can be represented as an "I" constraint.  */
++  if (REG_P (*op0) && CONST_INT_P (*op1) && satisfies_constraint_I (*op1))
++    {
++      rtx tem = *op0;
++      *op0 = *op1;
++      *op1 = tem;
++      *code = swap_condition (*code);
++      return;
++    }
++}
++
++/* Return the fixed registers used for condition codes.  */
++
++static bool
++ubicom32_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
++{
++  *p1 = CC_REGNUM;
++  *p2 = INVALID_REGNUM;
++ 
++  return true;
++}
++
++/* If two condition code modes are compatible, return a condition code
++   mode which is compatible with both.  Otherwise, return
++   VOIDmode.  */
++
++static enum machine_mode
++ubicom32_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
++{
++  if (m1 == m2)
++    return m1;
++
++  if (GET_MODE_CLASS (m1) != MODE_CC || GET_MODE_CLASS (m2) != MODE_CC)
++    return VOIDmode;
++
++  switch (m1)
++    {
++    case CCWmode:
++      if (m2 == CCWZNmode || m2 == CCWZmode)
++      return m1;
++
++      return VOIDmode;
++
++    case CCWZNmode:
++      if (m2 == CCWmode)
++      return m2;
++
++      if (m2 == CCWZmode)
++      return m1;
++
++      return VOIDmode;
++
++    case CCWZmode:
++      if (m2 == CCWmode || m2 == CCWZNmode)
++      return m2;
++
++      return VOIDmode;
++
++    case CCSmode:
++      if (m2 == CCSZNmode || m2 == CCSZmode)
++      return m1;
++
++      return VOIDmode;
++
++    case CCSZNmode:
++      if (m2 == CCSmode)
++      return m2;
++
++      if (m2 == CCSZmode)
++      return m1;
++
++      return VOIDmode;
++
++    case CCSZmode:
++      if (m2 == CCSmode || m2 == CCSZNmode)
++      return m2;
++
++      return VOIDmode;
++
++    default:
++      gcc_unreachable ();
++    }
++}
++
++static rtx
++ubicom32_legitimize_fdpic_address_symbol (rtx orig, rtx reg, rtx fdpic_reg)
++{
++  int unspec;
++  rtx got_offs;
++  rtx got_offs_scaled;
++  rtx plus_scaled;
++  rtx tmp;
++  rtx new_rtx;
++
++  gcc_assert (reg != 0);
++
++  if (GET_CODE (orig) == SYMBOL_REF
++      && SYMBOL_REF_FUNCTION_P (orig))
++    unspec = UNSPEC_FDPIC_GOT_FUNCDESC;
++  else
++    unspec = UNSPEC_FDPIC_GOT;
++
++  got_offs = gen_reg_rtx (SImode);
++  tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, orig), unspec);
++  emit_move_insn (got_offs, tmp);
++
++  got_offs_scaled = gen_rtx_MULT (SImode, got_offs, GEN_INT (4));
++  plus_scaled = gen_rtx_PLUS (Pmode, fdpic_reg, got_offs_scaled);
++  new_rtx = gen_const_mem (Pmode, plus_scaled);
++  emit_move_insn (reg, new_rtx);
++
++  return reg;
++}
++
++static rtx
++ubicom32_legitimize_fdpic_address (rtx orig, rtx reg, rtx fdpic_reg)
++{
++  rtx addr = orig;
++  rtx new_rtx = orig;
++
++  if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
++    {
++      rtx base;
++
++      if (GET_CODE (addr) == CONST)
++      {
++        addr = XEXP (addr, 0);
++        gcc_assert (GET_CODE (addr) == PLUS);
++      }
++
++      base = ubicom32_legitimize_fdpic_address_symbol (XEXP (addr, 0), reg, fdpic_reg);
++      return gen_rtx_PLUS (Pmode, base, XEXP (addr, 1));
++    }
++
++  return new_rtx;
++}
++
++/* Code generation.  */
++
++void
++ubicom32_expand_movsi (rtx *operands)
++{
++  if (GET_CODE (operands[1]) == SYMBOL_REF
++      || (GET_CODE (operands[1]) == CONST
++        && GET_CODE (XEXP (operands[1], 0)) == PLUS
++        && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
++      || CONSTANT_ADDRESS_P (operands[1]))
++    {
++      if (TARGET_FDPIC)
++      {
++        rtx tmp;
++        rtx fdpic_reg;
++
++        gcc_assert (can_create_pseudo_p ());
++        tmp = gen_reg_rtx (Pmode);
++        fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM);
++        if (GET_CODE (operands[1]) == SYMBOL_REF
++            || GET_CODE (operands[1]) == LABEL_REF)
++          operands[1] = ubicom32_legitimize_fdpic_address_symbol (operands[1], tmp, fdpic_reg);
++        else
++          operands[1] = ubicom32_legitimize_fdpic_address (operands[1], tmp, fdpic_reg);
++      }
++      else
++      {
++        rtx tmp;
++        enum machine_mode mode;
++
++        /* We want to avoid reusing operand 0 if we can because it limits
++           our ability to optimize later.  */
++        tmp = ! can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
++
++        mode = GET_MODE (operands[0]);
++        emit_insn (gen_rtx_SET (VOIDmode, tmp,
++                                gen_rtx_HIGH (mode, operands[1])));
++        operands[1] = gen_rtx_LO_SUM (mode, tmp, operands[1]);
++        if (can_create_pseudo_p() && ! REG_P (operands[0]))
++          {
++            tmp = gen_reg_rtx (mode);
++            emit_insn (gen_rtx_SET (VOIDmode, tmp, operands[1]));
++            operands[1] = tmp;
++          }
++      }
++    }
++}
++
++/* Emit code for addsi3.  */
++
++void
++ubicom32_expand_addsi3 (rtx *operands)
++{
++  rtx op, clob;
++
++  if (can_create_pseudo_p ())
++    {
++      /* If we have a non-data reg for operand 1 then prefer that over
++         a CONST_INT in operand 2.  */
++      if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
++        && CONST_INT_P (operands[2]))
++      operands[2] = copy_to_mode_reg (SImode, operands[2]);
++
++      if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
++      operands[2] = copy_to_mode_reg (SImode, operands[2]);
++    }
++
++  /* Emit the instruction.  */
++
++  op = gen_rtx_SET (VOIDmode, operands[0],
++                  gen_rtx_PLUS (SImode, operands[1], operands[2]));
++
++  if (! can_create_pseudo_p ())
++    {
++      /* Reload doesn't know about the flags register, and doesn't know that
++         it doesn't want to clobber it.  We can only do this with PLUS.  */
++      emit_insn (op);
++    }
++  else
++    {
++      clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
++      emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
++    }
++}
++
++/* Emit code for mulsi3.  Return 1 if we have generated all the code
++   necessary to do the multiplication.  */
++
++int
++ubicom32_emit_mult_sequence (rtx *operands)
++{
++  if (! ubicom32_v4)
++    {
++      rtx a1, a1_1, a2;
++      rtx b1, b1_1, b2;
++      rtx mac_lo_rtx;
++      rtx t1, t2, t3;
++
++      /* Give up if we cannot create new pseudos.  */
++      if (!can_create_pseudo_p())
++      return 0;
++
++      /* Synthesize 32-bit multiplication using 16-bit operations:
++     
++       a1 = highpart (a)
++       a2 = lowpart (a)
++
++       b1 = highpart (b)
++       b2 = lowpart (b)
++
++       c = (a1 * b1) << 32 + (a1 * b2) << 16 + (a2 * b1) << 16 + a2 * b2
++         =        0        + (a1 * b2) << 16 + (a2 * b1) << 16 + a2 * b2
++                             ^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^   ^^^^^^^
++                                 Signed             Signed      Unsigned  */
++
++      if (!ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])))
++      {
++        rtx op1;
++
++        op1 = gen_reg_rtx (SImode);
++        emit_move_insn (op1, operands[1]);
++        operands[1] = op1;
++      }
++
++      if (!ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))
++      {
++        rtx op2;
++
++        op2 = gen_reg_rtx (SImode);
++        emit_move_insn (op2, operands[2]);
++        operands[2] = op2;
++      }
++
++      /* a1 = highpart (a)  */
++      a1 = gen_reg_rtx (HImode);
++      a1_1 = gen_reg_rtx (SImode);
++      emit_insn (gen_ashrsi3 (a1_1, operands[1], GEN_INT (16)));
++      emit_move_insn (a1, gen_lowpart (HImode, a1_1));
++
++      /* a2 = lowpart (a)  */
++      a2 = gen_reg_rtx (HImode);
++      emit_move_insn (a2, gen_lowpart (HImode, operands[1]));
++
++      /* b1 = highpart (b)  */
++      b1 = gen_reg_rtx (HImode);
++      b1_1 = gen_reg_rtx (SImode);
++      emit_insn (gen_ashrsi3 (b1_1, operands[2], GEN_INT (16)));
++      emit_move_insn (b1, gen_lowpart (HImode, b1_1));
++
++      /* b2 = lowpart (b)  */
++      b2 = gen_reg_rtx (HImode);
++      emit_move_insn (b2, gen_lowpart (HImode, operands[2]));
++
++      /* t1 = (a1 * b2) << 16  */
++      t1 = gen_reg_rtx (SImode);
++      mac_lo_rtx = gen_rtx_REG (SImode, ACC0_LO_REGNUM);
++      emit_insn (gen_mulhisi3 (mac_lo_rtx, a1, b2));
++      emit_insn (gen_ashlsi3 (t1, mac_lo_rtx, GEN_INT (16)));
++
++      /* t2 = (a2 * b1) << 16  */
++      t2 = gen_reg_rtx (SImode);
++      emit_insn (gen_mulhisi3 (mac_lo_rtx, a2, b1));
++      emit_insn (gen_ashlsi3 (t2, mac_lo_rtx, GEN_INT (16)));
++
++      /* mac_lo = a2 * b2  */
++      emit_insn (gen_umulhisi3 (mac_lo_rtx, a2, b2));
++
++      /* t3 = t1 + t2  */
++      t3 = gen_reg_rtx (SImode);
++      emit_insn (gen_addsi3 (t3, t1, t2));
++
++      /* c = t3 + mac_lo_rtx  */
++      emit_insn (gen_addsi3 (operands[0], mac_lo_rtx, t3));
++
++      return 1;
++    }
++  else
++    {
++      rtx acc_rtx;
++
++      /* Give up if we cannot create new pseudos.  */
++      if (!can_create_pseudo_p())
++      return 0;
++
++      if (!ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])))
++        {
++        rtx op1;
++
++        op1 = gen_reg_rtx (SImode);
++        emit_move_insn (op1, operands[1]);
++        operands[1] = op1;
++      }
++
++      if (!ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))
++      {
++        rtx op2;
++
++        op2 = gen_reg_rtx (SImode);
++        emit_move_insn (op2, operands[2]);
++        operands[2] = op2;
++      }
++
++      acc_rtx = gen_reg_rtx (DImode);
++      emit_insn (gen_umulsidi3 (acc_rtx, operands[1], operands[2]));
++      emit_move_insn (operands[0], gen_lowpart (SImode, acc_rtx));
++
++      return 1;
++    }
++}
++
++/* Move the integer value VAL into OPERANDS[0].  */
++
++void
++ubicom32_emit_move_const_int (rtx dest, rtx imm)
++{
++  rtx xoperands[2];
++  
++  xoperands[0] = dest;
++  xoperands[1] = imm;
++
++  /* Treat mem destinations separately.  Values must be explicitly sign
++     extended.  */
++  if (MEM_P (dest))
++    {
++      rtx low_hword_mem;
++      rtx low_hword_addr;
++
++      /* Emit shorter sequence for signed 7-bit quantities.  */
++      if (satisfies_constraint_I (imm))
++      {
++          output_asm_insn ("move.4\t%0, %1", xoperands);
++          return;
++      }
++
++      /* Special case for pushing constants.  */
++      if (GET_CODE (XEXP (dest, 0)) == PRE_DEC
++        && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx)
++      {
++        output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
++        output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
++        return;
++      }
++
++      /* See if we can add 2 to the original address.  This is only
++       possible if the original address is of the form REG or
++       REG+const.  */
++      low_hword_addr = plus_constant (XEXP (dest, 0), 2);
++      if (ubicom32_legitimate_address_p (HImode, low_hword_addr, 1))
++      {
++        low_hword_mem = gen_rtx_MEM (HImode, low_hword_addr);
++        MEM_COPY_ATTRIBUTES (low_hword_mem, dest);
++        output_asm_insn ("movei\t%0, #%%hi(%E1)", xoperands);
++        xoperands[0] = low_hword_mem;
++        output_asm_insn ("movei\t%0, #%%lo(%E1)", xoperands);
++        return;
++      }
++
++      /* The original address is too complex.  We need to use a
++       scratch memory by (sp) and move that to the original
++       destination.  */
++      if (! reg_mentioned_p (stack_pointer_rtx, dest))
++      {
++        output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
++        output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
++        output_asm_insn ("move.4\t%0, (sp)4++", xoperands);
++        return;
++      }
++
++      /* Our address mentions the stack pointer so we need to
++       use our scratch data register here as well as scratch
++       memory.  */
++      output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
++      output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
++      output_asm_insn ("move.4\td15, (sp)4++", xoperands);
++      output_asm_insn ("move.4\t%0, d15", xoperands);
++      return;
++    }
++
++  /* Move into registers are zero extended by default.  */
++  if (! REG_P (dest))
++    abort ();
++
++  if (satisfies_constraint_N (imm))
++    {
++      output_asm_insn ("movei\t%0, %1", xoperands);
++      return;
++    }
++
++  if (INTVAL (xoperands[1]) >= 0xff80
++      && INTVAL (xoperands[1]) < 0x10000)
++    {
++      xoperands[1] = GEN_INT (INTVAL (xoperands[1]) - 0x10000);
++      output_asm_insn ("move.2\t%0, %1", xoperands);
++      return;
++    }
++
++  if ((REGNO_REG_CLASS (REGNO (xoperands[0])) == ADDRESS_REGS
++       || REGNO_REG_CLASS (REGNO (xoperands[0])) == FDPIC_REG)
++      && ((INTVAL (xoperands[1]) & 0x80000000) == 0))
++    {
++      output_asm_insn ("moveai\t%0, #%%hi(%E1)", xoperands);
++      if ((INTVAL (xoperands[1]) & 0x7f) != 0)
++      output_asm_insn ("lea.1\t%0, %%lo(%E1)(%0)", xoperands);
++      return;
++    }
++
++  if ((INTVAL (xoperands[1]) & 0xffff0000) == 0)
++    {
++      output_asm_insn ("movei\t%0, #%%lo(%E1)", xoperands);
++      output_asm_insn ("move.2\t%0, %0", xoperands);
++      return;
++    }
++
++  /* This is very expensive.  The constant is so large that we
++     need to use the stack to do the load.  */
++  output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
++  output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
++  output_asm_insn ("move.4\t%0, (sp)4++", xoperands);
++}
++
++/* Stack layout. Prologue/Epilogue.  */
++
++static int save_regs_size;
++
++static void 
++ubicom32_layout_frame (void)
++{
++  int regno;
++  
++  memset ((char *) &save_regs[0], 0, sizeof (save_regs));
++  nregs = 0;
++  frame_size = get_frame_size ();
++
++  if (frame_pointer_needed || df_regs_ever_live_p (FRAME_POINTER_REGNUM))
++    {
++      save_regs[FRAME_POINTER_REGNUM] = 1;
++      ++nregs;
++    }
++
++  if (current_function_is_leaf && ! df_regs_ever_live_p (LINK_REGNO))
++    ubicom32_can_use_calli_to_ret = 1;
++  else
++    {
++      ubicom32_can_use_calli_to_ret = 0;
++      save_regs[LINK_REGNO] = 1;
++      ++nregs;
++    }
++
++  /* Figure out which register(s) needs to be saved.  */
++  for (regno = 0; regno <= LAST_ADDRESS_REGNUM; regno++)
++      if (df_regs_ever_live_p(regno)
++      && ! call_used_regs[regno]
++      && ! fixed_regs[regno]
++      && ! save_regs[regno])
++    {
++      save_regs[regno] = 1;
++      ++nregs;
++    }
++
++  save_regs_size = 4 * nregs;
++}
++
++static void
++ubicom32_emit_add_movsi (int regno, int adj)
++{
++  rtx x;
++  rtx reg = gen_rtx_REG (SImode, regno);
++
++  adj += 4;
++  if (adj > 8 * 4) 
++    {
++      x = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
++                               GEN_INT (-adj)));
++      RTX_FRAME_RELATED_P (x) = 1;
++      x = emit_move_insn (gen_rtx_MEM (SImode, stack_pointer_rtx), reg);
++    }
++  else
++    {
++      rtx addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx,
++                                   gen_rtx_PLUS (Pmode, stack_pointer_rtx,
++                                                 GEN_INT (-adj)));
++      x = emit_move_insn (gen_rtx_MEM (SImode, addr), reg);
++    }
++  RTX_FRAME_RELATED_P (x) = 1;      
++}
++
++void
++ubicom32_expand_prologue (void)
++{
++  rtx x;
++  int regno;
++  int outgoing_args_size = crtl->outgoing_args_size;
++  int adj;
++
++  if (ubicom32_naked_function_p ())
++    return;
++
++  ubicom32_builtin_saveregs ();
++  
++  ubicom32_layout_frame ();
++  adj = (outgoing_args_size + get_frame_size () + save_regs_size
++       + crtl->args.pretend_args_size);
++  
++  if (!adj)
++    ;
++  else if (outgoing_args_size + save_regs_size < 508
++         && get_frame_size () + save_regs_size > 508)
++    {
++      int i = 0;
++      x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
++                    GEN_INT (-adj));
++      x = emit_insn (x);
++      RTX_FRAME_RELATED_P (x) = 1;
++
++      for (regno = LAST_ADDRESS_REGNUM; regno >= 0; --regno)
++      if (save_regs[regno] && regno != LINK_REGNO)
++        {
++          x = gen_rtx_MEM (SImode,
++                           gen_rtx_PLUS (Pmode,
++                                         stack_pointer_rtx,
++                                         GEN_INT (i * 4 + outgoing_args_size)));
++          x = emit_move_insn (x, gen_rtx_REG (SImode, regno));
++          RTX_FRAME_RELATED_P (x) = 1;
++          ++i;
++        }
++      if (save_regs[LINK_REGNO])
++      {
++        x = gen_rtx_MEM (SImode,
++                         gen_rtx_PLUS (Pmode,
++                                       stack_pointer_rtx,
++                                       GEN_INT (i * 4 + outgoing_args_size)));
++        x = emit_move_insn (x, gen_rtx_REG (SImode, LINK_REGNO));
++        RTX_FRAME_RELATED_P (x) = 1;
++      }
++    }
++  else
++    {
++      int regno;
++      int adj = get_frame_size () + crtl->args.pretend_args_size;
++      int i = 0;
++
++      if (save_regs[LINK_REGNO])
++      {
++        ubicom32_emit_add_movsi (LINK_REGNO, adj);
++        ++i;
++      }
++      
++      for (regno = 0; regno <= LAST_ADDRESS_REGNUM; ++regno)
++      if (save_regs[regno] && regno != LINK_REGNO)
++        {
++          if (i)
++            {
++              rtx mem = gen_rtx_MEM (SImode,
++                                     gen_rtx_PRE_DEC (Pmode,
++                                                      stack_pointer_rtx));
++              x = emit_move_insn (mem, gen_rtx_REG (SImode, regno));
++              RTX_FRAME_RELATED_P (x) = 1;
++            }
++          else
++            ubicom32_emit_add_movsi (regno, adj);
++          ++i;
++        }
++      
++      if (outgoing_args_size || (!i && adj))
++      {
++        x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
++                        GEN_INT (-outgoing_args_size - (i ? 0 : adj)));
++        x = emit_insn (x);
++        RTX_FRAME_RELATED_P (x) = 1;
++      }
++    }
++
++  if (frame_pointer_needed)
++    {
++      int fp_adj = save_regs_size + outgoing_args_size;
++      x = gen_addsi3 (frame_pointer_rtx, stack_pointer_rtx,
++                    GEN_INT (fp_adj));
++      x = emit_insn (x);
++      RTX_FRAME_RELATED_P (x) = 1;
++    }
++}
++
++void
++ubicom32_expand_epilogue (void)
++{
++  rtx x;
++  int regno;
++  int outgoing_args_size = crtl->outgoing_args_size;
++  int adj;
++  int i;
++
++  if (ubicom32_naked_function_p ())
++    {
++      emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode,
++                                                      LINK_REGNO)));
++      return;
++    }
++
++  if (cfun->calls_alloca)
++    {
++      x = gen_addsi3 (stack_pointer_rtx, frame_pointer_rtx,
++                    GEN_INT (-save_regs_size));
++      emit_insn (x);
++      outgoing_args_size = 0;
++    }
++  
++  if (outgoing_args_size)
++    {
++      x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
++                    GEN_INT (outgoing_args_size));
++      emit_insn (x);
++    }
++
++  i = 0;
++  for (regno = LAST_ADDRESS_REGNUM; regno >= 0; --regno)
++    if (save_regs[regno] && regno != LINK_REGNO)
++      {
++      x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
++      emit_move_insn (gen_rtx_REG (SImode, regno), x);
++      ++i;
++      }
++
++  /* Do we have to adjust the stack after we've finished restoring regs?  */
++  adj = get_frame_size() + crtl->args.pretend_args_size;
++  if (cfun->stdarg)
++    adj += UBICOM32_FUNCTION_ARG_REGS * UNITS_PER_WORD;
++ 
++#if 0
++  if (crtl->calls_eh_return && 0)
++    {
++      if (save_regs[LINK_REGNO])
++        {
++          x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
++          emit_move_insn (gen_rtx_REG (SImode, LINK_REGNO), x);
++        }
++
++      if (adj)
++        {
++          x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
++                        GEN_INT (adj));
++          x = emit_insn (x);
++        }
++
++      /* Perform the additional bump for __throw.  */
++      emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
++                           EH_RETURN_STACKADJ_RTX));
++      emit_jump_insn (gen_eh_return_internal ());
++      return;
++    }
++#endif
++
++  if (save_regs[LINK_REGNO])
++    {
++      if (adj >= 4 && adj <= (6 * 4))
++        {
++        x = GEN_INT (adj + 4);
++          emit_jump_insn (gen_return_from_post_modify_sp (x));
++        return;
++        }
++
++      if (adj == 0)
++      {
++          x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
++          emit_jump_insn (gen_return_internal (x));
++          return;
++      }
++
++      x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
++      emit_move_insn (gen_rtx_REG (SImode, LINK_REGNO), x);
++    }
++
++  if (adj)
++    {
++      x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
++                    GEN_INT (adj));
++      x = emit_insn (x);
++      adj = 0;
++    }
++
++  /* Given that we've just done all the hard work here we may as well use
++     a calli to return.  */
++  ubicom32_can_use_calli_to_ret = 1;
++  emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode, LINK_REGNO)));
++}
++
++void
++ubicom32_expand_call_fdpic (rtx *operands)
++{
++  rtx c;
++  rtx addr;
++  rtx fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM);
++
++  addr = XEXP (operands[0], 0);
++
++  c = gen_call_fdpic (addr, operands[1], fdpic_reg);
++  emit_call_insn (c);
++}
++
++void
++ubicom32_expand_call_value_fdpic (rtx *operands)
++{
++  rtx c;
++  rtx addr;
++  rtx fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM);
++
++  addr = XEXP (operands[1], 0);
++
++  c = gen_call_value_fdpic (operands[0], addr, operands[2], fdpic_reg);
++  emit_call_insn (c);
++}
++
++void
++ubicom32_expand_eh_return (rtx *operands)
++{
++  if (REG_P (operands[0])
++      || REGNO (operands[0]) != EH_RETURN_STACKADJ_REGNO)
++    {
++      rtx sp = EH_RETURN_STACKADJ_RTX;
++      emit_move_insn (sp, operands[0]);
++      operands[0] = sp;
++    }
++
++  if (REG_P (operands[1])
++      || REGNO (operands[1]) != EH_RETURN_HANDLER_REGNO)
++    {
++      rtx ra = EH_RETURN_HANDLER_RTX;
++      emit_move_insn (ra, operands[1]);
++      operands[1] = ra;
++    }
++}
++
++/* Compute the offsets between eliminable registers.  */
++
++int
++ubicom32_initial_elimination_offset (int from, int to)
++{
++  ubicom32_layout_frame ();
++  if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
++    return save_regs_size + crtl->outgoing_args_size;
++
++  if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
++    return get_frame_size ()/* + save_regs_size */;
++
++  if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
++    return get_frame_size ()
++         + crtl->outgoing_args_size
++         + save_regs_size;
++
++  return 0;
++}
++
++/* Return 1 if it is appropriate to emit `ret' instructions in the
++   body of a function.  Do this only if the epilogue is simple, needing a
++   couple of insns.  Prior to reloading, we can't tell how many registers
++   must be saved, so return 0 then.  Return 0 if there is no frame
++   marker to de-allocate.
++
++   If NON_SAVING_SETJMP is defined and true, then it is not possible
++   for the epilogue to be simple, so return 0.  This is a special case
++   since NON_SAVING_SETJMP will not cause regs_ever_live to change
++   until final, but jump_optimize may need to know sooner if a
++   `return' is OK.  */
++
++int
++ubicom32_can_use_return_insn_p (void)
++{
++  if (! reload_completed || frame_pointer_needed)
++    return 0;
++
++  return 1;
++}
++
++/* Attributes and CC handling.  */
++
++/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
++   struct attribute_spec.handler.  */
++static tree
++ubicom32_handle_fndecl_attribute (tree *node, tree name,
++                            tree args ATTRIBUTE_UNUSED,
++                            int flags ATTRIBUTE_UNUSED,
++                            bool *no_add_attrs)
++{
++  if (TREE_CODE (*node) != FUNCTION_DECL)
++    {
++      warning ("'%s' attribute only applies to functions",
++             IDENTIFIER_POINTER (name));
++      *no_add_attrs = true;
++    }
++
++  return NULL_TREE;
++}
++
++/* A C expression that places additional restrictions on the register class to
++   use when it is necessary to copy value X into a register in class CLASS.
++   The value is a register class; perhaps CLASS, or perhaps another, smaller
++   class.  On many machines, the following definition is safe:
++
++        #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS
++
++   Sometimes returning a more restrictive class makes better code.  For
++   example, on the 68000, when X is an integer constant that is in range for a
++   `moveq' instruction, the value of this macro is always `DATA_REGS' as long
++   as CLASS includes the data registers.  Requiring a data register guarantees
++   that a `moveq' will be used.
++
++   If X is a `const_double', by returning `NO_REGS' you can force X into a
++   memory constant.  This is useful on certain machines where immediate
++   floating values cannot be loaded into certain kinds of registers.  */
++
++enum reg_class
++ubicom32_preferred_reload_class (rtx x, enum reg_class class)
++{
++  /* If a symbolic constant, HIGH or a PLUS is reloaded,
++     it is most likely being used as an address, so
++     prefer ADDRESS_REGS.  If 'class' is not a superset
++     of ADDRESS_REGS, e.g. DATA_REGS, then reject this reload.  */
++  if (GET_CODE (x) == PLUS
++      || GET_CODE (x) == HIGH
++      || GET_CODE (x) == LABEL_REF
++      || GET_CODE (x) == SYMBOL_REF
++      || GET_CODE (x) == CONST)
++    {
++      if (reg_class_subset_p (ALL_ADDRESS_REGS, class))
++      return ALL_ADDRESS_REGS;
++
++      return NO_REGS;
++    }
++
++  return class;
++}
++
++/* Function arguments and varargs.  */
++
++int
++ubicom32_reg_parm_stack_space (tree fndecl)
++{
++  return 0;
++  
++  if (fndecl
++      && TYPE_ARG_TYPES (TREE_TYPE (fndecl)) != 0
++      && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))) 
++        != void_type_node))
++    return UBICOM32_FUNCTION_ARG_REGS * UNITS_PER_WORD;
++
++  return 0;
++}
++
++/* Flush the argument registers to the stack for a stdarg function;
++   return the new argument pointer.  */
++
++rtx
++ubicom32_builtin_saveregs (void)
++{
++  int regno;
++  
++  if (! cfun->stdarg)
++    return 0;
++  
++  for (regno = UBICOM32_FUNCTION_ARG_REGS - 1; regno >= 0; --regno)
++    emit_move_insn (gen_rtx_MEM (SImode,
++                               gen_rtx_PRE_DEC (SImode,
++                                                stack_pointer_rtx)),
++                  gen_rtx_REG (SImode, regno));
++  
++  return stack_pointer_rtx;
++}
++
++void
++ubicom32_va_start (tree valist, rtx nextarg)
++{
++  std_expand_builtin_va_start (valist, nextarg);
++}
++
++rtx
++ubicom32_va_arg (tree valist, tree type)
++{
++  HOST_WIDE_INT size, rsize;
++  tree addr, incr, tmp;
++  rtx addr_rtx;
++  int indirect = 0;
++
++  /* Round up sizeof(type) to a word.  */
++  size = int_size_in_bytes (type);
++  rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
++
++  /* Large types are passed by reference.  */
++  if (size > 8)
++    {
++      indirect = 1;
++      size = rsize = UNITS_PER_WORD;
++    }
++
++  incr = valist;
++  addr = incr = save_expr (incr);
++
++  /* FIXME Nat's version - is it correct?  */
++  tmp = fold_convert (ptr_type_node, size_int (rsize));
++  tmp = build2 (PLUS_EXPR, ptr_type_node, incr, tmp);
++  incr = fold (tmp);
++
++  /* FIXME Nat's version - is it correct? */
++  incr = build2 (MODIFY_EXPR, ptr_type_node, valist, incr);
++
++  TREE_SIDE_EFFECTS (incr) = 1;
++  expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL);
++
++  addr_rtx = expand_expr (addr, NULL, Pmode, EXPAND_NORMAL);
++
++  if (size < UNITS_PER_WORD)
++    emit_insn (gen_addsi3 (addr_rtx, addr_rtx,
++                         GEN_INT (UNITS_PER_WORD - size)));
++
++  if (indirect)
++    {
++      addr_rtx = force_reg (Pmode, addr_rtx);
++      addr_rtx = gen_rtx_MEM (Pmode, addr_rtx);
++      set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
++    }
++
++  return addr_rtx;
++}
++
++void
++init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
++                    int indirect ATTRIBUTE_UNUSED)
++{
++  cum->nbytes = 0;
++
++  if (!libname)
++    {
++      cum->stdarg = (TYPE_ARG_TYPES (fntype) != 0
++                   && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
++                       != void_type_node));
++    }
++}
++
++/* Return an RTX to represent where a value in mode MODE will be passed
++   to a function.  If the result is 0, the argument will be pushed.  */
++
++rtx
++function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
++            int named ATTRIBUTE_UNUSED)
++{
++  rtx result = 0;
++  int size, align;
++  int nregs = UBICOM32_FUNCTION_ARG_REGS;
++  
++  /* Figure out the size of the object to be passed.  */
++  if (mode == BLKmode)
++    size = int_size_in_bytes (type);
++  else
++    size = GET_MODE_SIZE (mode);
++
++  /* Figure out the alignment of the object to be passed.  */
++  align = size;
++
++  cum->nbytes = (cum->nbytes + 3) & ~3;
++
++  /* Don't pass this arg via a register if all the argument registers
++     are used up.  */
++  if (cum->nbytes >= nregs * UNITS_PER_WORD)
++    return 0;
++
++  /* Don't pass this arg via a register if it would be split between
++     registers and memory.  */
++  result = gen_rtx_REG (mode, cum->nbytes / UNITS_PER_WORD);
++
++  return result;
++}
++
++rtx
++function_incoming_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
++                     int named ATTRIBUTE_UNUSED)
++{
++  if (cfun->stdarg)
++    return 0;
++
++  return function_arg (cum, mode, type, named);
++}
++
++
++/* Implement hook TARGET_ARG_PARTIAL_BYTES.
++
++   Returns the number of bytes at the beginning of an argument that
++   must be put in registers.  The value must be zero for arguments
++   that are passed entirely in registers or that are entirely pushed
++   on the stack.  */
++static int
++ubicom32_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
++                          tree type, bool named ATTRIBUTE_UNUSED)
++{
++  int size, diff;
++
++  int nregs = UBICOM32_FUNCTION_ARG_REGS;
++
++  /* round up to full word */
++  cum->nbytes = (cum->nbytes + 3) & ~3;
++
++  if (targetm.calls.pass_by_reference (cum, mode, type, named))
++      return 0;
++
++  /* number of bytes left in registers */
++  diff = nregs*UNITS_PER_WORD - cum->nbytes;
++
++  /* regs all used up */
++  if (diff <= 0)
++    return 0;
++
++  /* Figure out the size of the object to be passed.  */
++  if (mode == BLKmode)
++    size = int_size_in_bytes (type);
++  else
++    size = GET_MODE_SIZE (mode);
++
++  /* enough space left in regs for size */
++  if (size <= diff)
++    return 0;
++
++  /* put diff bytes in regs and rest on stack */
++  return diff;
++
++}
++
++static bool
++ubicom32_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
++                          enum machine_mode mode, const_tree type,
++                          bool named ATTRIBUTE_UNUSED)
++{
++  int size;
++
++  if (type)
++    size = int_size_in_bytes (type);
++  else
++    size = GET_MODE_SIZE (mode);
++
++  return size <= 0 || size > 8;
++}
++
++static bool
++ubicom32_callee_copies (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
++                      enum machine_mode mode, const_tree type,
++                      bool named ATTRIBUTE_UNUSED)
++{
++  int size;
++
++  if (type)
++    size = int_size_in_bytes (type);
++  else
++    size = GET_MODE_SIZE (mode);
++
++  return size <= 0 || size > 8;
++}
++ 
++static bool
++ubicom32_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
++{
++  int size, mode;
++
++  if (!type)
++    return true;
++
++  size = int_size_in_bytes(type);
++  if (size > 8) 
++    return true;
++
++  mode = TYPE_MODE(type);
++  if (mode == BLKmode)
++    return true;
++
++  return false;
++}
++
++/* Return true if a given register number REGNO is acceptable for machine
++   mode MODE.  */
++bool
++ubicom32_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
++{
++  /* If we're not at least a v3 ISA then ACC0_HI is only 16 bits.  */
++  if (! ubicom32_v3)
++    {
++      if (regno == ACC0_HI_REGNUM)
++      return (mode == QImode || mode == HImode);
++    }
++
++  /* Only the flags reg can hold CCmode.  */
++  if (GET_MODE_CLASS (mode) == MODE_CC)
++    return regno == CC_REGNUM;
++
++  /* We restrict the choice of DImode registers to only being address,
++     data or accumulator regs.  We also restrict them to only start on
++     even register numbers so we never have to worry about partial
++     overlaps between operands in instructions.  */
++  if (GET_MODE_SIZE (mode) > 4)
++    {
++      switch (REGNO_REG_CLASS (regno))
++      {
++      case ADDRESS_REGS:
++      case DATA_REGS:
++      case ACC_REGS:
++        return (regno & 1) == 0;
++
++        default:
++        return false;
++      }
++    }
++
++  return true;
++}
++
++/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
++   and check its validity for a certain class.
++   We have two alternate definitions for each of them.
++   The usual definition accepts all pseudo regs; the other rejects
++   them unless they have been allocated suitable hard regs.
++   The symbol REG_OK_STRICT causes the latter definition to be used.
++
++   Most source files want to accept pseudo regs in the hope that
++   they will get allocated to the class that the insn wants them to be in.
++   Source files for reload pass need to be strict.
++   After reload, it makes no difference, since pseudo regs have
++   been eliminated by then.  
++
++   These assume that REGNO is a hard or pseudo reg number.
++   They give nonzero only if REGNO is a hard reg of the suitable class
++   or a pseudo reg currently allocated to a suitable hard reg.
++   Since they use reg_renumber, they are safe only once reg_renumber
++   has been allocated, which happens in local-alloc.c.  */
++
++int
++ubicom32_regno_ok_for_base_p (int regno, int strict)
++{
++  if ((regno >= FIRST_ADDRESS_REGNUM && regno <= STACK_POINTER_REGNUM) 
++      || (!strict
++        && (regno >= FIRST_PSEUDO_REGISTER
++            || regno == ARG_POINTER_REGNUM))
++      || (strict && (reg_renumber 
++                   && reg_renumber[regno] >= FIRST_ADDRESS_REGNUM
++                   && reg_renumber[regno] <= STACK_POINTER_REGNUM)))
++    return 1;
++
++  return 0;
++}
++
++int
++ubicom32_regno_ok_for_index_p (int regno, int strict)
++{
++  if ((regno >= FIRST_DATA_REGNUM && regno <= LAST_DATA_REGNUM)
++      || (!strict && regno >= FIRST_PSEUDO_REGISTER)
++      || (strict && (reg_renumber 
++                   && reg_renumber[regno] >= FIRST_DATA_REGNUM
++                   && reg_renumber[regno] <= LAST_DATA_REGNUM)))
++    return 1;
++
++  return 0;
++}
++
++/* Returns 1 if X is a valid index register.  STRICT is 1 if only hard
++   registers should be accepted.  Accept either REG or SUBREG where a
++   register is valid.  */
++
++static bool
++ubicom32_is_index_reg (rtx x, int strict)
++{
++  if ((REG_P (x) && ubicom32_regno_ok_for_index_p (REGNO (x), strict))
++      || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x))
++        && ubicom32_regno_ok_for_index_p (REGNO (SUBREG_REG (x)), strict)))
++    return true;
++
++  return false;
++}
++
++/* Return 1 if X is a valid index for a memory address.  */
++
++static bool
++ubicom32_is_index_expr (enum machine_mode mode, rtx x, int strict)
++{
++  /* Immediate index must be an unsigned 7-bit offset multiple of 1, 2
++     or 4 depending on mode.  */
++  if (CONST_INT_P (x))
++    {
++      switch (mode)
++      {
++      case QImode:
++        return satisfies_constraint_J (x);
++        
++      case HImode:
++        return satisfies_constraint_K (x);
++
++      case SImode:
++      case SFmode:
++        return satisfies_constraint_L (x);
++
++      case DImode:
++        return satisfies_constraint_L (x)
++               && satisfies_constraint_L (GEN_INT (INTVAL (x) + 4));
++        
++      default:          
++        return false;
++      }
++    }
++
++  if (mode != SImode && mode != HImode && mode != QImode)
++    return false;
++
++  /* Register index scaled by mode of operand: REG + REG * modesize.
++     Valid scaled index registers are:
++
++     SImode   (mult (dreg) 4))
++     HImode   (mult (dreg) 2))
++     QImode   (mult (dreg) 1))  */
++  if (GET_CODE (x) == MULT
++      && ubicom32_is_index_reg (XEXP (x, 0), strict)
++      && CONST_INT_P (XEXP (x, 1))
++      && INTVAL (XEXP (x, 1)) == (HOST_WIDE_INT)GET_MODE_SIZE (mode))
++    return true;
++
++  /* REG + REG addressing is allowed for QImode.  */
++  if (ubicom32_is_index_reg (x, strict) && mode == QImode)
++    return true;
++
++  return false;
++}
++
++static bool
++ubicom32_is_valid_offset (enum machine_mode mode, HOST_WIDE_INT offs)
++{
++  if (offs < 0)
++    return false;
++
++  switch (mode)
++    {
++    case QImode:
++      return offs <= 127;
++
++    case HImode:
++      return offs <= 254;
++
++    case SImode:
++    case SFmode:
++      return offs <= 508;
++
++    case DImode:
++      return offs <= 504;
++
++    default:
++      return false;
++    }
++}
++
++static int
++ubicom32_get_valid_offset_mask (enum machine_mode mode)
++{
++  switch (mode)
++    {
++    case QImode:
++      return 127;
++
++    case HImode:
++      return 255;
++
++    case SImode:
++    case SFmode:
++      return 511;
++
++    case DImode:
++      return 255;
++
++    default:
++      return 0;
++    }
++}
++
++/* Returns 1 if X is a valid base register.  STRICT is 1 if only hard
++   registers should be accepted.  Accept either REG or SUBREG where a
++   register is valid.  */
++
++static bool
++ubicom32_is_base_reg (rtx x, int strict)
++{
++  if ((REG_P (x) && ubicom32_regno_ok_for_base_p (REGNO (x), strict))
++      || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x))
++        && ubicom32_regno_ok_for_base_p (REGNO (SUBREG_REG (x)), strict)))
++    return true;
++
++  return false;
++}
++
++static bool
++ubicom32_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
++{
++  return TARGET_FDPIC;
++}
++
++/* Determine if X is a legitimate constant.  */
++
++bool
++ubicom32_legitimate_constant_p (rtx x)
++{
++  /* Among its other duties, LEGITIMATE_CONSTANT_P decides whether
++     a constant can be entered into reg_equiv_constant[].  If we return true,
++     reload can create new instances of the constant whenever it likes.
++
++     The idea is therefore to accept as many constants as possible (to give
++     reload more freedom) while rejecting constants that can only be created
++     at certain times.  In particular, anything with a symbolic component will
++     require use of the pseudo FDPIC register, which is only available before
++     reload.  */
++  if (TARGET_FDPIC)
++    {
++      if (GET_CODE (x) == SYMBOL_REF
++        || (GET_CODE (x) == CONST
++            && GET_CODE (XEXP (x, 0)) == PLUS
++            && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)
++        || CONSTANT_ADDRESS_P (x))
++      return false;
++
++      return true;
++    }
++
++  /* For non-PIC code anything goes!  */
++  return true;
++}
++
++/* Address validation.  */
++
++bool
++ubicom32_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
++{
++  if (TARGET_DEBUG_ADDRESS)
++    {                                                                 
++      fprintf (stderr, "\n==> GO_IF_LEGITIMATE_ADDRESS%s\n",
++             (strict) ? " (STRICT)" : "");
++      debug_rtx (x);
++    }                                                                 
++
++  if (CONSTANT_ADDRESS_P (x))
++    return false;
++
++  if (ubicom32_is_base_reg (x, strict)) 
++    return true;
++
++  if ((GET_CODE (x) == POST_INC 
++       || GET_CODE (x) == PRE_INC 
++       || GET_CODE (x) == POST_DEC 
++       || GET_CODE (x) == PRE_DEC)
++      && REG_P (XEXP (x, 0))
++      && ubicom32_is_base_reg (XEXP (x, 0), strict)
++      && mode != DImode)
++    return true;
++
++  if ((GET_CODE (x) == PRE_MODIFY || GET_CODE (x) == POST_MODIFY)
++      && ubicom32_is_base_reg (XEXP (x, 0), strict)
++      && GET_CODE (XEXP (x, 1)) == PLUS
++      && rtx_equal_p (XEXP (x, 0), XEXP (XEXP (x, 1), 0))
++      && CONST_INT_P (XEXP (XEXP (x, 1), 1))
++      && mode != DImode)
++    {
++      HOST_WIDE_INT disp = INTVAL (XEXP (XEXP (x, 1), 1));
++      switch (mode)
++      {
++      case QImode:
++        return disp >= -8 && disp <= 7;
++        
++      case HImode:
++        return disp >= -16 && disp <= 14 && ! (disp & 1);
++        
++      case SImode:
++        return disp >= -32 && disp <= 28 && ! (disp & 3);
++        
++      default:
++        return false;
++      }
++    }
++  
++  /* Accept base + index * scale.  */
++  if (GET_CODE (x) == PLUS
++      && ubicom32_is_base_reg (XEXP (x, 0), strict)
++      && ubicom32_is_index_expr (mode, XEXP (x, 1), strict))
++    return true;
++
++  /* Accept index * scale + base.  */
++  if (GET_CODE (x) == PLUS
++      && ubicom32_is_base_reg (XEXP (x, 1), strict)
++      && ubicom32_is_index_expr (mode, XEXP (x, 0), strict))
++    return true;
++
++  if (! TARGET_FDPIC)
++    {
++      /* Accept (lo_sum (reg) (symbol_ref)) that can be used as a mem+7bits
++       displacement operand:
++
++       moveai a1, #%hi(SYM)
++       move.4 d3, %lo(SYM)(a1)  */
++      if (GET_CODE (x) == LO_SUM
++        && ubicom32_is_base_reg (XEXP (x, 0), strict)
++        && (GET_CODE (XEXP (x, 1)) == SYMBOL_REF
++            || GET_CODE (XEXP (x, 1)) == LABEL_REF /* FIXME: wrong */)
++        && mode != DImode)
++      return true;
++    }
++
++  if (TARGET_DEBUG_ADDRESS)
++    fprintf (stderr, "\nNot a legitimate address.\n");
++
++  return false;
++}
++
++rtx
++ubicom32_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
++                           enum machine_mode mode)
++{
++  if (mode == BLKmode)
++    return NULL_RTX;
++
++  if (GET_CODE (x) == PLUS
++      && REG_P (XEXP (x, 0))
++      && ! REGNO_PTR_FRAME_P (REGNO (XEXP (x, 0))) 
++      && CONST_INT_P (XEXP (x, 1))
++      && ! ubicom32_is_valid_offset (mode, INTVAL (XEXP (x, 1))))
++    {
++      rtx base;
++      rtx plus;
++      rtx new_rtx;
++      HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
++      HOST_WIDE_INT low = val & ubicom32_get_valid_offset_mask (mode);
++      HOST_WIDE_INT high = val ^ low;
++
++      if (val < 0)
++      return NULL_RTX;
++
++      if (! low)
++      return NULL_RTX;
++
++      /* Reload the high part into a base reg; leave the low part
++       in the mem directly.  */
++      base = XEXP (x, 0);
++      if (! ubicom32_is_base_reg (base, 0))
++      base = copy_to_mode_reg (Pmode, base);
++
++      plus = expand_simple_binop (Pmode, PLUS,
++                                gen_int_mode (high, Pmode),
++                                base, NULL, 0, OPTAB_WIDEN);
++      new_rtx = plus_constant (plus, low);
++
++      return new_rtx;
++    }
++
++  return NULL_RTX;
++}
++
++/* Try a machine-dependent way of reloading an illegitimate address AD
++   operand.  If we find one, push the reload and and return the new address.
++
++   MODE is the mode of the enclosing MEM.  OPNUM is the operand number
++   and TYPE is the reload type of the current reload.  */
++
++rtx 
++ubicom32_legitimize_reload_address (rtx ad, enum machine_mode mode,
++                                  int opnum, int type)
++{
++  /* Is this an address that we've already fixed up?  If it is then
++     recognize it and move on.  */
++  if (GET_CODE (ad) == PLUS
++      && GET_CODE (XEXP (ad, 0)) == PLUS
++      && REG_P (XEXP (XEXP (ad, 0), 0))
++      && CONST_INT_P (XEXP (XEXP (ad, 0), 1))
++      && CONST_INT_P (XEXP (ad, 1)))
++    {
++      push_reload (XEXP (ad, 0), NULL_RTX, &XEXP (ad, 0), NULL,
++                 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
++                 opnum, (enum reload_type) type);
++      return ad;
++    }
++
++  /* Have we got an address where the offset is simply out of range?  If
++     yes then reload the range as a high part and smaller offset.  */
++  if (GET_CODE (ad) == PLUS
++      && REG_P (XEXP (ad, 0))
++      && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
++      && REGNO_OK_FOR_BASE_P (REGNO (XEXP (ad, 0)))
++      && CONST_INT_P (XEXP (ad, 1))
++      && ! ubicom32_is_valid_offset (mode, INTVAL (XEXP (ad, 1))))
++    {
++      rtx temp;
++      rtx new_rtx;
++
++      HOST_WIDE_INT val = INTVAL (XEXP (ad, 1));
++      HOST_WIDE_INT low = val & ubicom32_get_valid_offset_mask (mode);
++      HOST_WIDE_INT high = val ^ low;
++
++      /* Reload the high part into a base reg; leave the low part
++       in the mem directly.  */
++      temp = gen_rtx_PLUS (Pmode, XEXP (ad, 0), GEN_INT (high));
++      new_rtx = gen_rtx_PLUS (Pmode, temp, GEN_INT (low));
++
++      push_reload (XEXP (new_rtx, 0), NULL_RTX, &XEXP (new_rtx, 0), NULL,
++                 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
++                 opnum, (enum reload_type) type);
++      return new_rtx;
++    }
++
++  /* If we're presented with an pre/post inc/dec then we must force this
++     to be done in an address register.  The register allocator should
++     work this out for itself but at times ends up trying to use the wrong
++     class.  If we get the wrong class then reload will end up generating
++     at least 3 instructions whereas this way we can hopefully keep it to
++     just 2.  */
++  if ((GET_CODE (ad) == POST_INC 
++       || GET_CODE (ad) == PRE_INC 
++       || GET_CODE (ad) == POST_DEC 
++       || GET_CODE (ad) == PRE_DEC)
++      && REG_P (XEXP (ad, 0))
++      && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
++      && ! REGNO_OK_FOR_BASE_P (REGNO (XEXP (ad, 0))))
++    {
++      push_reload (XEXP (ad, 0), XEXP (ad, 0), &XEXP (ad, 0), &XEXP (ad, 0),
++                 BASE_REG_CLASS, GET_MODE (XEXP (ad, 0)), GET_MODE (XEXP (ad, 0)), 0, 0,
++                 opnum, RELOAD_OTHER);
++      return ad;
++    }
++
++  return NULL_RTX;
++}
++
++/* Compute a (partial) cost for rtx X.  Return true if the complete
++   cost has been computed, and false if subexpressions should be
++   scanned.  In either case, *TOTAL contains the cost result.  */
++
++static bool
++ubicom32_rtx_costs (rtx x, int code, int outer_code, int *total,
++                  bool speed ATTRIBUTE_UNUSED)
++{
++  enum machine_mode mode = GET_MODE (x);
++
++  switch (code)
++    {
++    case CONST_INT:
++      /* Very short constants often fold into instructions so
++         we pretend that they don't cost anything!  This is
++       really important as regards zero values as otherwise
++       the compiler has a nasty habit of wanting to reuse
++       zeroes that are in regs but that tends to pessimize
++       the code.  */
++      if (satisfies_constraint_I (x))
++      {
++        *total = 0;
++        return true;
++      }
++
++      /* Bit clearing costs nothing  */
++      if (outer_code == AND
++        && exact_log2 (~INTVAL (x)) != -1)
++      {
++        *total = 0;
++        return true;
++      }
++
++      /* Masking the lower set of bits costs nothing.  */
++      if (outer_code == AND
++        && exact_log2 (INTVAL (x) + 1) != -1)
++      {
++        *total = 0;
++        return true;
++      }
++
++      /* Bit setting costs nothing.  */
++      if (outer_code == IOR
++        && exact_log2 (INTVAL (x)) != -1)
++      {
++        *total = 0;
++        return true;
++      }
++
++      /* Larger constants that can be loaded via movei aren't too
++         bad.  If we're just doing a set they cost nothing extra.  */
++      if (satisfies_constraint_N (x))
++      {
++        if (mode == DImode)
++          *total = COSTS_N_INSNS (2);
++        else 
++          *total = COSTS_N_INSNS (1);
++        return true;
++      }
++
++      if (mode == DImode)
++      *total = COSTS_N_INSNS (5);
++      else
++        *total = COSTS_N_INSNS (3);
++      return true;
++
++    case CONST_DOUBLE:
++      /* We don't optimize CONST_DOUBLEs well nor do we relax them well,
++       so their cost is very high.  */
++      *total = COSTS_N_INSNS (6);
++      return true;
++
++    case CONST:
++    case SYMBOL_REF:
++    case MEM:
++      *total = 0;
++      return true;
++
++    case IF_THEN_ELSE:
++      *total = COSTS_N_INSNS (1);
++      return true;
++
++    case LABEL_REF:
++    case HIGH:
++    case LO_SUM:
++    case BSWAP:
++    case PLUS:
++    case MINUS:
++    case AND:
++    case IOR:
++    case XOR:
++    case ASHIFT:
++    case ASHIFTRT:
++    case LSHIFTRT:
++    case NEG:
++    case NOT:
++    case SIGN_EXTEND:
++    case ZERO_EXTEND:
++    case ZERO_EXTRACT:
++      if (outer_code == SET)
++      {
++        if (mode == DImode)
++          *total = COSTS_N_INSNS (2);
++        else
++          *total = COSTS_N_INSNS (1);
++      }
++      return true;
++
++    case COMPARE:
++      if (outer_code == SET)
++      {
++        if (GET_MODE (XEXP (x, 0)) == DImode
++            || GET_MODE (XEXP (x, 1)) == DImode)
++          *total = COSTS_N_INSNS (2);
++        else
++          *total = COSTS_N_INSNS (1);
++      }
++      return true;
++
++    case UMOD:
++    case UDIV:
++    case MOD:
++    case DIV:
++      if (outer_code == SET)
++      {
++        if (mode == DImode)
++          *total = COSTS_N_INSNS (600);
++        else
++          *total = COSTS_N_INSNS (200);
++      }
++      return true;
++
++    case MULT:
++      if (outer_code == SET)
++      {
++        if (! ubicom32_v4)
++          {
++            if (mode == DImode)
++              *total = COSTS_N_INSNS (15);
++            else
++              *total = COSTS_N_INSNS (5);
++          }
++        else
++          {
++            if (mode == DImode)
++              *total = COSTS_N_INSNS (6);
++            else
++              *total = COSTS_N_INSNS (2);
++          }
++      }
++      return true;
++
++    case UNSPEC:
++      if (XINT (x, 1) == UNSPEC_FDPIC_GOT
++        || XINT (x, 1) == UNSPEC_FDPIC_GOT_FUNCDESC)
++      *total = 0;
++      return true;
++
++    default:
++      return false;
++    }
++}
++
++/* Return 1 if ADDR can have different meanings depending on the machine
++   mode of the memory reference it is used for or if the address is
++   valid for some modes but not others.
++
++   Autoincrement and autodecrement addresses typically have
++   mode-dependent effects because the amount of the increment or
++   decrement is the size of the operand being addressed.  Some machines
++   have other mode-dependent addresses. Many RISC machines have no
++   mode-dependent addresses.
++
++   You may assume that ADDR is a valid address for the machine.  */
++
++int
++ubicom32_mode_dependent_address_p (rtx addr)
++{
++  if (GET_CODE (addr) == POST_INC 
++      || GET_CODE (addr) == PRE_INC 
++      || GET_CODE (addr) == POST_DEC 
++      || GET_CODE (addr) == PRE_DEC 
++      || GET_CODE (addr) == POST_MODIFY 
++      || GET_CODE (addr) == PRE_MODIFY)
++    return 1;
++
++  return 0;
++}
++
++static void
++ubicom32_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
++{
++  fprintf (file, "/* frame/pretend: %ld/%d save_regs: %d out_args: %d  %s */\n",
++         get_frame_size (), crtl->args.pretend_args_size,
++         save_regs_size, crtl->outgoing_args_size,
++         current_function_is_leaf ? "leaf" : "nonleaf");
++}
++
++static void
++ubicom32_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
++                          HOST_WIDE_INT size ATTRIBUTE_UNUSED)
++{
++  ubicom32_reorg_completed = 0;  
++}
++
++static void
++ubicom32_machine_dependent_reorg (void)
++{
++#if 0 /* Commenting out this optimization until it is fixed */
++  if (optimize)
++    {
++      compute_bb_for_insn ();
++
++      /* Do a very simple CSE pass over just the hard registers.  */
++      reload_cse_regs (get_insns ());
++
++      /* Reload_cse_regs can eliminate potentially-trapping MEMs.
++       Remove any EH edges associated with them.  */
++      if (flag_non_call_exceptions)
++      purge_all_dead_edges ();
++    }
++#endif
++  ubicom32_reorg_completed = 1;
++}
++
++void
++ubicom32_output_cond_jump (rtx insn, rtx cond, rtx target)
++{
++  rtx note;
++  int mostly_false_jump;
++  rtx xoperands[2];
++  rtx cc_reg;
++
++  note = find_reg_note (insn, REG_BR_PROB, 0);
++  mostly_false_jump = !note || (INTVAL (XEXP (note, 0))
++                              <= REG_BR_PROB_BASE / 2);
++
++  xoperands[0] = target;
++  xoperands[1] = cond;
++  cc_reg = XEXP (cond, 0);
++
++  if (GET_MODE (cc_reg) == CCWmode
++      || GET_MODE (cc_reg) == CCWZmode
++      || GET_MODE (cc_reg) == CCWZNmode)
++    {
++      if (mostly_false_jump)
++        output_asm_insn ("jmp%b1.w.f\t%0", xoperands);
++      else
++        output_asm_insn ("jmp%b1.w.t\t%0", xoperands);
++      return;
++    }
++
++  if (GET_MODE (cc_reg) == CCSmode
++      || GET_MODE (cc_reg) == CCSZmode
++      || GET_MODE (cc_reg) == CCSZNmode)
++    {
++      if (mostly_false_jump)
++        output_asm_insn ("jmp%b1.s.f\t%0", xoperands);
++      else
++        output_asm_insn ("jmp%b1.s.t\t%0", xoperands);
++      return;
++    }
++
++  abort ();
++}
++
++/* Return non-zero if FUNC is a naked function.  */
++
++static int
++ubicom32_naked_function_p (void)
++{
++  return lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE;
++}
++
++/* Return an RTX indicating where the return address to the
++   calling function can be found.  */
++rtx
++ubicom32_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED)
++{
++  if (count != 0)
++    return NULL_RTX;
++
++  return get_hard_reg_initial_val (Pmode, LINK_REGNO);
++}
++
++/*
++ * ubicom32_readonly_data_section: This routtine handles code
++ * at the start of readonly data sections
++ */
++static void
++ubicom32_readonly_data_section (const void *data ATTRIBUTE_UNUSED)
++{
++  static int num = 0;
++  if (in_section == readonly_data_section){
++    fprintf (asm_out_file, "%s", DATA_SECTION_ASM_OP);
++    if (flag_data_sections){
++      fprintf (asm_out_file, ".rodata%d", num);
++      fprintf (asm_out_file, ",\"a\"");
++    }
++    fprintf (asm_out_file, "\n");
++  }
++  num++;
++}
++
++/*
++ * ubicom32_text_section: not in readonly section
++ */
++static void
++ubicom32_text_section(const void *data ATTRIBUTE_UNUSED)
++{
++  fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
++}
++
++/*
++ * ubicom32_data_section: not in readonly section
++ */
++static void
++ubicom32_data_section(const void *data ATTRIBUTE_UNUSED)
++{
++  fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
++}
++
++/*
++ * ubicom32_asm_init_sections: This routine implements special
++ * section handling
++ */
++static void
++ubicom32_asm_init_sections(void)
++{
++  text_section = get_unnamed_section(SECTION_CODE, ubicom32_text_section, NULL);
++
++  data_section = get_unnamed_section(SECTION_WRITE, ubicom32_data_section, NULL);
++
++  readonly_data_section = get_unnamed_section(0, ubicom32_readonly_data_section, NULL);
++}
++
++/*
++ * ubicom32_profiler:  This routine would call
++ * mcount to support prof and gprof if mcount
++ * was supported. Currently, do nothing.
++ */
++void
++ubicom32_profiler(void)
++{
++}
++
++/* Initialise the builtin functions.  Start by initialising
++   descriptions of different types of functions (e.g., void fn(int),
++   int fn(void)), and then use these to define the builtins. */
++static void
++ubicom32_init_builtins (void)
++{
++  tree endlink;
++  tree short_unsigned_endlink;
++  tree unsigned_endlink;
++  tree short_unsigned_ftype_short_unsigned;
++  tree unsigned_ftype_unsigned;
++
++  endlink = void_list_node;
++
++  short_unsigned_endlink
++    = tree_cons (NULL_TREE, short_unsigned_type_node, endlink);
++
++  unsigned_endlink
++    = tree_cons (NULL_TREE, unsigned_type_node, endlink);
++
++  short_unsigned_ftype_short_unsigned
++    = build_function_type (short_unsigned_type_node, short_unsigned_endlink);
++
++  unsigned_ftype_unsigned
++    = build_function_type (unsigned_type_node, unsigned_endlink);
++
++  /* Initialise the byte swap function. */
++  add_builtin_function ("__builtin_ubicom32_swapb_2",
++                      short_unsigned_ftype_short_unsigned,
++                      UBICOM32_BUILTIN_UBICOM32_SWAPB_2,
++                      BUILT_IN_MD, NULL,
++                      NULL_TREE);
++
++  /* Initialise the byte swap function. */
++  add_builtin_function ("__builtin_ubicom32_swapb_4",
++                      unsigned_ftype_unsigned,
++                      UBICOM32_BUILTIN_UBICOM32_SWAPB_4,
++                      BUILT_IN_MD, NULL,
++                      NULL_TREE);
++}
++
++/* Given a builtin function taking 2 operands (i.e., target + source),
++   emit the RTL for the underlying instruction. */
++static rtx
++ubicom32_expand_builtin_2op (enum insn_code icode, tree arglist, rtx target)
++{
++  tree arg0;
++  rtx op0, pat;
++  enum machine_mode tmode, mode0;
++
++  /* Grab the incoming argument and emit its RTL. */
++  arg0 = TREE_VALUE (arglist);
++  op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
++
++  /* Determine the modes of the instruction operands. */
++  tmode = insn_data[icode].operand[0].mode;
++  mode0 = insn_data[icode].operand[1].mode;
++
++  /* Ensure that the incoming argument RTL is in a register of the
++     correct mode. */
++  if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
++    op0 = copy_to_mode_reg (mode0, op0);
++
++  /* If there isn't a suitable target, emit a target register. */
++  if (target == 0
++      || GET_MODE (target) != tmode
++      || !(*insn_data[icode].operand[0].predicate) (target, tmode))
++    target = gen_reg_rtx (tmode);
++
++  /* Emit and return the new instruction. */
++  pat = GEN_FCN (icode) (target, op0);
++  if (!pat)
++    return 0;
++  emit_insn (pat);
++
++  return target;
++}
++
++/* Expand a call to a builtin function. */
++static rtx
++ubicom32_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
++                       enum machine_mode mode ATTRIBUTE_UNUSED,
++                       int ignore ATTRIBUTE_UNUSED)
++{
++  tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
++  tree arglist = CALL_EXPR_ARGS(exp);
++  int fcode = DECL_FUNCTION_CODE (fndecl);
++
++  switch (fcode)
++    {
++    case UBICOM32_BUILTIN_UBICOM32_SWAPB_2:
++      return ubicom32_expand_builtin_2op (CODE_FOR_bswaphi, arglist, target);
++
++    case UBICOM32_BUILTIN_UBICOM32_SWAPB_4:
++      return ubicom32_expand_builtin_2op (CODE_FOR_bswapsi, arglist, target);
++
++    default:
++      gcc_unreachable();
++    }
++
++  /* Should really do something sensible here.  */
++  return NULL_RTX;
++}
++
++/* Fold any constant argument for a swapb.2 instruction.  */
++static tree
++ubicom32_fold_builtin_ubicom32_swapb_2 (tree fndecl, tree arglist)
++{
++  tree arg0;
++
++  arg0 = TREE_VALUE (arglist);
++
++  /* Optimize constant value.  */
++  if (TREE_CODE (arg0) == INTEGER_CST)
++    {
++      HOST_WIDE_INT v;
++      HOST_WIDE_INT res;
++
++      v = TREE_INT_CST_LOW (arg0);
++      res = ((v >> 8) & 0xff)
++           | ((v & 0xff) << 8);
++
++      return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), res);
++    }
++
++  return NULL_TREE;
++}
++
++/* Fold any constant argument for a swapb.4 instruction.  */
++static tree
++ubicom32_fold_builtin_ubicom32_swapb_4 (tree fndecl, tree arglist)
++{
++  tree arg0;
++
++  arg0 = TREE_VALUE (arglist);
++
++  /* Optimize constant value.  */
++  if (TREE_CODE (arg0) == INTEGER_CST)
++    {
++      unsigned HOST_WIDE_INT v;
++      unsigned HOST_WIDE_INT res;
++
++      v = TREE_INT_CST_LOW (arg0);
++      res = ((v >> 24) & 0xff)
++           | (((v >> 16) & 0xff) << 8)
++           | (((v >> 8) & 0xff) << 16)
++           | ((v & 0xff) << 24);
++
++      return build_int_cst_wide (TREE_TYPE (TREE_TYPE (fndecl)), res, 0);
++    }
++
++  return NULL_TREE;
++}
++
++/* Fold any constant arguments for builtin functions.  */
++static tree
++ubicom32_fold_builtin (tree fndecl, tree arglist, bool ignore ATTRIBUTE_UNUSED)
++{
++  switch (DECL_FUNCTION_CODE (fndecl))
++    {
++    case UBICOM32_BUILTIN_UBICOM32_SWAPB_2:
++      return ubicom32_fold_builtin_ubicom32_swapb_2 (fndecl, arglist);
++
++    case UBICOM32_BUILTIN_UBICOM32_SWAPB_4:
++      return ubicom32_fold_builtin_ubicom32_swapb_4 (fndecl, arglist);
++
++    default:
++      return NULL;
++    }
++}
++
++/* Implementation of TARGET_ASM_INTEGER.  When using FD-PIC, we need to
++   tell the assembler to generate pointers to function descriptors in
++   some cases.  */
++static bool
++ubicom32_assemble_integer (rtx value, unsigned int size, int aligned_p)
++{
++  if (TARGET_FDPIC && size == UNITS_PER_WORD)
++    {
++      if (GET_CODE (value) == SYMBOL_REF
++        && SYMBOL_REF_FUNCTION_P (value))
++      {
++        fputs ("\t.picptr\t%funcdesc(", asm_out_file);
++        output_addr_const (asm_out_file, value);
++        fputs (")\n", asm_out_file);
++        return true;
++      }
++
++      if (!aligned_p)
++      {
++        /* We've set the unaligned SI op to NULL, so we always have to
++           handle the unaligned case here.  */
++        assemble_integer_with_op ("\t.4byte\t", value);
++        return true;
++      }
++    }
++
++  return default_assemble_integer (value, size, aligned_p);
++}
++
++/* If the constant I can be constructed by shifting a source-1 immediate
++   by a constant number of bits then return the bit count.  If not
++   return 0.  */
++
++int
++ubicom32_shiftable_const_int (int i)
++{
++  int shift = 0;
++
++  /* Note that any constant that can be represented as an immediate to
++     a movei instruction is automatically ignored here in the interests
++     of the clarity of the output asm code.  */
++  if (i >= -32768 && i <= 32767)
++    return 0;
++
++  /* Find the number of trailing zeroes.  We could use __builtin_ctz
++     here but it's not obvious if this is supported on all build
++     compilers so we err on the side of caution.  */
++  if ((i & 0xffff) == 0)
++    {
++      shift += 16;
++      i >>= 16;
++    }
++
++  if ((i & 0xff) == 0)
++    {
++      shift += 8;
++      i >>= 8;
++    }
++
++  if ((i & 0xf) == 0)
++    {
++      shift += 4;
++      i >>= 4;
++    }
++
++  if ((i & 0x3) == 0)
++    {
++      shift += 2;
++      i >>= 2;
++    }
++
++  if ((i & 0x1) == 0)
++    {
++      shift += 1;
++      i >>= 1;
++    }
++
++  if (i >= -128 && i <= 127)
++    return shift;
++
++  return 0;
++}
++
+--- /dev/null
++++ b/gcc/config/ubicom32/ubicom32.h
+@@ -0,0 +1,1564 @@
++/* Definitions of target machine for Ubicom32
++
++   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
++   2009 Free Software Foundation, Inc.
++   Contributed by Ubicom, Inc.
++
++   This file is part of GCC.
++
++   GCC is free software; you can redistribute it and/or modify it
++   under the terms of the GNU General Public License as published
++   by the Free Software Foundation; either version 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/>.  */
++
++\f
++
++#define OBJECT_FORMAT_ELF
++
++/* Run-time target specifications. */
++
++/* Target CPU builtins.  */
++#define TARGET_CPU_CPP_BUILTINS()                     \
++  do                                                  \
++    {                                                 \
++      builtin_define_std ("__UBICOM32__");            \
++      builtin_define_std ("__ubicom32__");            \
++                                                      \
++      if (TARGET_FDPIC)                                       \
++      {                                               \
++        builtin_define ("__UBICOM32_FDPIC__");        \
++        builtin_define ("__FDPIC__");                 \
++      }                                               \
++    }                                                 \
++  while (0)
++
++#ifndef TARGET_DEFAULT
++#define TARGET_DEFAULT 0
++#endif
++
++extern int ubicom32_case_values_threshold;
++
++/* Nonzero if this chip supports the Ubicom32 v3 ISA.  */
++extern int ubicom32_v3;
++
++/* Nonzero if this chip supports the Ubicom32 v4 ISA.  */
++extern int ubicom32_v4;
++
++extern int ubicom32_stack_size;
++
++/* Flag for whether we can use calli instead of ret in returns.  */
++extern int ubicom32_can_use_calli_to_ret;
++
++/* This macro is a C statement to print on `stderr' a string describing the
++   particular machine description choice.  Every machine description should
++   define `TARGET_VERSION'. */
++#define TARGET_VERSION fprintf (stderr, " (UBICOM32)");
++
++/* We don't need a frame pointer to debug things.  Doing this means
++   that gcc can turn on -fomit-frame-pointer when '-O' is specified.  */
++#define CAN_DEBUG_WITHOUT_FP
++
++/* We need to handle processor-specific options.  */
++#define OVERRIDE_OPTIONS ubicom32_override_options ()
++
++#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) \
++  ubicom32_optimization_options (LEVEL, SIZE)
++
++/* For Ubicom32 the least significant bit has the lowest bit number
++   so we define this to be 0.  */
++#define BITS_BIG_ENDIAN 0
++
++/* For Ubicom32 the most significant byte in a word has the lowest
++   number.  */
++#define BYTES_BIG_ENDIAN 1
++
++/* For Ubicom32, in a multiword object, the most signifant word has the
++   lowest number.  */
++#define WORDS_BIG_ENDIAN 1
++
++/* Ubicom32 has 8 bits per byte.  */
++#define BITS_PER_UNIT 8
++
++/* Ubicom32 has 32 bits per word.  */
++#define BITS_PER_WORD 32
++
++/* Width of a word, in units (bytes).  */
++#define UNITS_PER_WORD 4
++
++/* Width of a pointer, in bits.  */
++#define POINTER_SIZE 32
++
++/* Alias for pointers.  Ubicom32 is a 32-bit architecture so we use
++   SImode.  */
++#define Pmode SImode
++
++/* Normal alignment required for function parameters on the stack, in
++   bits.  */
++#define PARM_BOUNDARY 32
++
++/* We need to maintain the stack on a 32-bit boundary.  */
++#define STACK_BOUNDARY 32
++
++/* Alignment required for a function entry point, in bits.  */
++#define FUNCTION_BOUNDARY 32
++
++/* Alias for the machine mode used for memory references to functions being
++   called, in `call' RTL expressions.  We use byte-oriented addresses
++   here.  */
++#define FUNCTION_MODE QImode
++
++/* Biggest alignment that any data type can require on this machine,
++   in bits.  */
++#define BIGGEST_ALIGNMENT 32
++
++/* this default to BIGGEST_ALIGNMENT unless defined       */
++/* ART: What's the correct value here? Default is (((unsigned int)1<<28)*8)*/
++#undef MAX_OFILE_ALIGNMENT
++#define MAX_OFILE_ALIGNMENT (128 * 8)
++
++/* Alignment in bits to be given to a structure bit field that follows an empty
++   field such as `int : 0;'.  */
++#define EMPTY_FIELD_BOUNDARY 32
++
++/* All structures must be a multiple of 32 bits in size.  */
++#define STRUCTURE_SIZE_BOUNDARY 32
++
++/* A bit-field declared as `int' forces `int' alignment for the struct.  */
++#define PCC_BITFIELD_TYPE_MATTERS 1
++
++/* For Ubicom32 we absolutely require that data be aligned with nominal
++   alignment.  */
++#define STRICT_ALIGNMENT 1
++
++/* Make strcpy of constants fast.  */
++#define CONSTANT_ALIGNMENT(EXP, ALIGN)  \
++  (TREE_CODE (EXP) == STRING_CST      \
++   && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
++
++/* Define this macro as an expression for the alignment of a structure
++   (given by STRUCT as a tree node) if the alignment computed in the
++   usual way is COMPUTED and the alignment explicitly specified was
++   SPECIFIED. */
++#define DATA_ALIGNMENT(TYPE, ALIGN)                                   \
++  ((((ALIGN) < BITS_PER_WORD)                                         \
++    && (TREE_CODE (TYPE) == ARRAY_TYPE                                        \
++      || TREE_CODE (TYPE) == UNION_TYPE                               \
++      || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN))
++
++#define LOCAL_ALIGNMENT(TYPE,ALIGN) DATA_ALIGNMENT(TYPE,ALIGN)
++
++/* For Ubicom32 we default to unsigned chars.  */
++#define DEFAULT_SIGNED_CHAR 0
++
++/* Machine-specific data register numbers.  */
++#define FIRST_DATA_REGNUM 0
++#define D10_REGNUM 10
++#define D11_REGNUM 11
++#define D12_REGNUM 12
++#define D13_REGNUM 13
++#define LAST_DATA_REGNUM 15
++
++/* Machine-specific address register numbers.  */
++#define FIRST_ADDRESS_REGNUM 16
++#define LAST_ADDRESS_REGNUM 22
++
++/* Register numbers used for passing a function's static chain pointer.  If
++   register windows are used, the register number as seen by the called
++   function is `STATIC_CHAIN_INCOMING_REGNUM', while the register number as
++   seen by the calling function is `STATIC_CHAIN_REGNUM'.  If these registers
++   are the same, `STATIC_CHAIN_INCOMING_REGNUM' need not be defined.
++
++   The static chain register need not be a fixed register.
++
++   If the static chain is passed in memory, these macros should not be defined;
++   instead, the next two macros should be defined.  */
++#define STATIC_CHAIN_REGNUM (FIRST_ADDRESS_REGNUM + 1)
++
++/* The register number of the frame pointer register, which is used to access
++   automatic variables in the stack frame.  We generally eliminate this anyway
++   for Ubicom32 but we make it A6 by default.  */
++#define FRAME_POINTER_REGNUM (LAST_ADDRESS_REGNUM)
++
++/* The register number of the stack pointer register, which is also be a
++   fixed register according to `FIXED_REGISTERS'.  For Ubicom32 we don't
++   have a hardware requirement about which register this is, but by convention
++   we use A7.  */
++#define STACK_POINTER_REGNUM (LAST_ADDRESS_REGNUM + 1)
++
++/* Machine-specific accumulator register numbers.  */
++#define ACC0_HI_REGNUM 24
++#define ACC0_LO_REGNUM 25
++#define ACC1_HI_REGNUM 26
++#define ACC1_LO_REGNUM 27
++
++/* source3 register number */
++#define SOURCE3_REGNUM 28
++
++/* The register number of the arg pointer register, which is used to access the
++   function's argument list.  On some machines, this is the same as the frame
++   pointer register.  On some machines, the hardware determines which register
++   this is.  On other machines, you can choose any register you wish for this
++   purpose.  If this is not the same register as the frame pointer register,
++   then you must mark it as a fixed register according to `FIXED_REGISTERS', or
++   arrange to be able to eliminate it.  */
++#define ARG_POINTER_REGNUM 29
++
++/* Pseudo-reg for condition code.  */
++#define CC_REGNUM 30
++
++/* Interrupt set/clear registers.  */
++#define INT_SET0_REGNUM 31
++#define INT_SET1_REGNUM 32
++#define INT_CLR0_REGNUM 33
++#define INT_CLR1_REGNUM 34
++
++/* Scratchpad registers.  */
++#define SCRATCHPAD0_REGNUM 35
++#define SCRATCHPAD1_REGNUM 36
++#define SCRATCHPAD2_REGNUM 37
++#define SCRATCHPAD3_REGNUM 38
++
++/* FDPIC register.  */
++#define FDPIC_REGNUM 16
++
++/* Number of hardware registers known to the compiler.  They receive numbers 0
++   through `FIRST_PSEUDO_REGISTER-1'; thus, the first pseudo register's number
++   really is assigned the number `FIRST_PSEUDO_REGISTER'.  */
++#define FIRST_PSEUDO_REGISTER 39
++
++/* An initializer that says which registers are used for fixed purposes all
++   throughout the compiled code and are therefore not available for general
++   allocation.  These would include the stack pointer, the frame pointer
++   (except on machines where that can be used as a general register when no
++   frame pointer is needed), the program counter on machines where that is
++   considered one of the addressable registers, and any other numbered register
++   with a standard use.
++
++   This information is expressed as a sequence of numbers, separated by commas
++   and surrounded by braces.  The Nth number is 1 if register N is fixed, 0
++   otherwise.
++
++   The table initialized from this macro, and the table initialized by the
++   following one, may be overridden at run time either automatically, by the
++   actions of the macro `CONDITIONAL_REGISTER_USAGE', or by the user with the
++   command options `-ffixed-REG', `-fcall-used-REG' and `-fcall-saved-REG'.  */
++#define FIXED_REGISTERS                                       \
++  {                                                   \
++    0, 0, 0, 0, 0, 0, 0, 0,   /* d0 - d7 */           \
++    0, 0, 0, 0, 0, 0, 0, 1,   /* d8 - d15 */          \
++    0, 0, 0, 0, 0, 0, 0, 1,   /* a0 - a7 */           \
++    0, 0,                     /* acc0 hi/lo */        \
++    0, 0,                     /* acc1 hi/lo */        \
++    0,                                /* source3 */           \
++    1,                                /* arg */               \
++    1,                                /* cc */                \
++    1, 1,                     /* int_set[01] */       \
++    1, 1,                     /* int_clr[01] */       \
++    1, 1, 1, 1                        /* scratchpad[0123] */  \
++  }
++
++/* Like `FIXED_REGISTERS' but has 1 for each register that is clobbered (in
++   general) by function calls as well as for fixed registers.  This macro
++   therefore identifies the registers that are not available for general
++   allocation of values that must live across function calls.
++
++   If a register has 0 in `CALL_USED_REGISTERS', the compiler automatically
++   saves it on function entry and restores it on function exit, if the register
++   is used within the function.  */
++#define CALL_USED_REGISTERS                           \
++  {                                                   \
++    1, 1, 1, 1, 1, 1, 1, 1,   /* d0 - d7 */           \
++    1, 1, 0, 0, 0, 0, 1, 1,   /* d8 - d15 */          \
++    1, 0, 0, 1, 1, 1, 0, 1,   /* a0 - a7 */           \
++    1, 1,                     /* acc0 hi/lo */        \
++    1, 1,                     /* acc1 hi/lo */        \
++    1,                                /* source3 */           \
++    1,                                /* arg */               \
++    1,                                /* cc */                \
++    1, 1,                     /* int_set[01] */       \
++    1, 1,                     /* int_clr[01] */       \
++    1, 1, 1, 1                        /* scratchpad[0123] */  \
++  }
++
++/* How to refer to registers in assembler output.
++   This sequence is indexed by compiler's hard-register-number (see above).  */
++
++/* A C initializer containing the assembler's names for the machine registers,
++   each one as a C string constant.  This is what translates register numbers
++   in the compiler into assembler language.  */
++#define REGISTER_NAMES                                                \
++  {                                                           \
++    "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",           \
++    "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",     \
++    "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",           \
++    "acc0_hi", "acc0_lo",                                     \
++    "acc1_hi", "acc1_lo",                                     \
++    "source3",                                                        \
++    "arg",                                                    \
++    "cc",                                                     \
++    "int_set0", "int_set1",                                   \
++    "int_clr0", "int_clr1",                                   \
++    "scratchpad0", "scratchpad1", "scratchpad2", "scratchpad3"        \
++  }
++
++#define CONDITIONAL_REGISTER_USAGE                            \
++  ubicom32_conditional_register_usage ();
++
++/* Order of allocation of registers.  */
++
++/* If defined, an initializer for a vector of integers, containing the numbers
++   of hard registers in the order in which GNU CC should prefer to use them
++   (from most preferred to least).
++
++   For Ubicom32 we try using caller-clobbered data registers first, then
++   callee-saved data registers, then caller-clobbered address registers,
++   then callee-saved address registers and finally everything else.
++
++   The caller-clobbered registers are usually slightly cheaper to use because
++   there's no need to save/restore.  */
++#define REG_ALLOC_ORDER                                               \
++  {                                                           \
++    0, 1, 2, 3, 4,            /* d0 - d4 */                   \
++    5, 6, 7, 8, 9,            /* d5 - d9 */                   \
++    14,                               /* d14 */                       \
++    10, 11, 12, 13,           /* d10 - d13 */                 \
++    19, 20, 16, 21,           /* a3, a4, a0, a5 */            \
++    17, 18, 22,                       /* a1, a2, a6 */                \
++    24, 25,                   /* acc0 hi/lo */                \
++    26, 27,                   /* acc0 hi/lo */                \
++    28                                /* source3 */                   \
++  }
++
++/* C expression for the number of consecutive hard registers, starting at
++   register number REGNO, required to hold a value of mode MODE.  */
++#define HARD_REGNO_NREGS(REGNO, MODE) \
++  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
++
++/* Most registers can hold QImode, HImode and SImode values but we have to
++   be able to indicate any hard registers that cannot hold values with some
++   modes.  */
++#define HARD_REGNO_MODE_OK(REGNO, MODE) \
++  ubicom32_hard_regno_mode_ok(REGNO, MODE)
++
++/* We can rename most registers aside from the FDPIC register if we're using
++   FDPIC.  */
++#define HARD_REGNO_RENAME_OK(from, to) (TARGET_FDPIC ? ((to) != FDPIC_REGNUM) : 1)
++
++/* A C expression that is nonzero if it is desirable to choose register
++   allocation so as to avoid move instructions between a value of mode MODE1
++   and a value of mode MODE2.
++
++   If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, MODE2)' are
++   ever different for any R, then `MODES_TIEABLE_P (MODE1, MODE2)' must be
++   zero.  */
++#define MODES_TIEABLE_P(MODE1, MODE2) 1
++
++/* An enumeral type that must be defined with all the register class names as
++   enumeral values.  `NO_REGS' must be first.  `ALL_REGS' must be the last
++   register class, followed by one more enumeral value, `LIM_REG_CLASSES',
++   which is not a register class but rather tells how many classes there are.
++
++   Each register class has a number, which is the value of casting the class
++   name to type `int'.  The number serves as an index in many of the tables
++   described below.  */
++
++enum reg_class
++{
++  NO_REGS,
++  DATA_REGS,
++  FDPIC_REG,
++  ADDRESS_REGS,
++  ALL_ADDRESS_REGS,
++  ACC_LO_REGS,
++  ACC_REGS,
++  CC_REG,
++  DATA_ACC_REGS,
++  SOURCE3_REG,
++  SPECIAL_REGS,
++  GENERAL_REGS,
++  ALL_REGS,
++  LIM_REG_CLASSES
++};
++
++/* The number of distinct register classes.  */
++#define N_REG_CLASSES (int) LIM_REG_CLASSES
++
++/* An initializer containing the names of the register classes as C string
++   constants.  These names are used in writing some of the debugging dumps.  */
++
++#define REG_CLASS_NAMES               \
++{                             \
++  "NO_REGS",                  \
++  "DATA_REGS",                        \
++  "FDPIC_REG",                        \
++  "ADDRESS_REGS",             \
++  "ALL_ADDRESS_REGS",         \
++  "ACC_LO_REGS",              \
++  "ACC_REGS",                 \
++  "CC_REG",                   \
++  "DATA_ACC_REGS",            \
++  "SOURCE3_REG",              \
++  "SPECIAL_REGS",             \
++  "GENERAL_REGS",             \
++  "ALL_REGS",                 \
++  "LIM_REGS"                  \
++}
++
++/* An initializer containing the contents of the register classes, as integers
++   which are bit masks.  The Nth integer specifies the contents of class N.
++   The way the integer MASK is interpreted is that register R is in the class
++   if `MASK & (1 << R)' is 1.
++
++   When the machine has more than 32 registers, an integer does not suffice.
++   Then the integers are replaced by sub-initializers, braced groupings
++   containing several integers.  Each sub-initializer must be suitable as an
++   initializer for the type `HARD_REG_SET' which is defined in
++   `hard-reg-set.h'.  */
++#define REG_CLASS_CONTENTS                                    \
++{                                                             \
++  {0x00000000, 0x00000000},   /* No regs */                   \
++  {0x0000ffff, 0x00000000},   /* DATA_REGS */                 \
++  {0x00010000, 0x00000000},   /* FDPIC_REG */                 \
++  {0x20fe0000, 0x00000000},   /* ADDRESS_REGS */              \
++  {0x20ff0000, 0x00000000},   /* ALL_ADDRESS_REGS */          \
++  {0x0a000000, 0x00000000},   /* ACC_LO_REGS */               \
++  {0x0f000000, 0x00000000},   /* ACC_REGS */                  \
++  {0x40000000, 0x00000000},   /* CC_REG */                    \
++  {0x0f00ffff, 0x00000000},   /* DATA_ACC_REGS */             \
++  {0x10000000, 0x00000000},   /* SOURGE3_REG */               \
++  {0x80000000, 0x0000007f},   /* SPECIAL_REGS */              \
++  {0xbfffffff, 0x0000007f},   /* GENERAL_REGS */              \
++  {0xbfffffff, 0x0000007f}    /* ALL_REGS     */              \
++}
++
++extern enum reg_class const ubicom32_regclass_map[FIRST_PSEUDO_REGISTER];
++
++/* A C expression whose value is a register class containing hard register
++   REGNO.  In general there is more than one such class; choose a class which
++   is "minimal", meaning that no smaller class also contains the register.  */
++#define REGNO_REG_CLASS(REGNO) (ubicom32_regclass_map[REGNO])
++
++#define IRA_COVER_CLASSES             \
++{                                     \
++  GENERAL_REGS,                               \
++  LIM_REG_CLASSES                     \
++}
++
++/* Ubicom32 base registers must be address registers since addresses can
++   only be reached via address registers.  */
++#define BASE_REG_CLASS ALL_ADDRESS_REGS
++
++/* Ubicom32 index registers must be data registers since we cannot add
++   two address registers together to form an address.  */
++#define INDEX_REG_CLASS DATA_REGS
++
++/* A C expression which is nonzero if register number NUM is suitable for use
++   as a base register in operand addresses.  It may be either a suitable hard
++   register or a pseudo register that has been allocated such a hard register.  */
++
++#ifndef REG_OK_STRICT
++#define REGNO_OK_FOR_BASE_P(regno) \
++  ubicom32_regno_ok_for_base_p (regno, 0)
++#else
++#define REGNO_OK_FOR_BASE_P(regno) \
++  ubicom32_regno_ok_for_base_p (regno, 1)
++#endif
++
++/* A C expression which is nonzero if register number NUM is suitable for use
++   as an index register in operand addresses.  It may be either a suitable hard
++   register or a pseudo register that has been allocated such a hard register.
++
++   The difference between an index register and a base register is that the
++   index register may be scaled.  If an address involves the sum of two
++   registers, neither one of them scaled, then either one may be labeled the
++   "base" and the other the "index"; but whichever labeling is used must fit
++   the machine's constraints of which registers may serve in each capacity.
++   The compiler will try both labelings, looking for one that is valid, and
++   will reload one or both registers only if neither labeling works.  */
++#ifndef REG_OK_STRICT
++#define REGNO_OK_FOR_INDEX_P(regno) \
++  ubicom32_regno_ok_for_index_p (regno, 0)
++#else
++#define REGNO_OK_FOR_INDEX_P(regno) \
++  ubicom32_regno_ok_for_index_p (regno, 1)
++#endif
++
++/* Attempt to restrict the register class we need to copy value X intoto the
++   would-be register class CLASS.  Most things are fine for Ubicom32 but we
++   have to restrict certain types of address loads.  */
++#define PREFERRED_RELOAD_CLASS(X, CLASS) \
++  ubicom32_preferred_reload_class (X, CLASS)
++
++/* A C expression for the maximum number of consecutive registers of
++   class CLASS needed to hold a value of mode MODE.  For Ubicom32 this
++   is pretty much identical to HARD_REGNO_NREGS.  */
++#define CLASS_MAX_NREGS(CLASS, MODE)  \
++  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
++
++/* For Ubicom32 the stack grows downwards when we push a word onto the stack
++   - i.e. it moves to a smaller address.  */
++#define STACK_GROWS_DOWNWARD 1
++
++/* Offset from the frame pointer to the first local variable slot to
++   be allocated.  */
++#define STARTING_FRAME_OFFSET 0
++
++/* Offset from the argument pointer register to the first argument's
++   address.  */
++#define FIRST_PARM_OFFSET(FNDECL) 0
++
++/* A C expression whose value is RTL representing the value of the return
++   address for the frame COUNT steps up from the current frame, after the
++   prologue.  FRAMEADDR is the frame pointer of the COUNT frame, or the frame
++   pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is
++   defined.
++
++   The value of the expression must always be the correct address when COUNT is
++   zero, but may be `NULL_RTX' if there is not way to determine the return
++   address of other frames.  */
++#define RETURN_ADDR_RTX(COUNT, FRAME) \
++  ubicom32_return_addr_rtx (COUNT, FRAME)
++
++/* Register That Address the Stack Frame.  */
++
++/* We don't actually require a frame pointer in most functions with the
++   Ubicom32 architecture so we allow it to be eliminated.  */
++#define FRAME_POINTER_REQUIRED 0
++
++/* Macro that defines a table of register pairs used to eliminate unecessary
++   registers that point into the stack frame.
++
++   For Ubicom32 we don't generally need an arg pointer of a frame pointer
++   so we allow the arg pointer to be replaced by either the frame pointer or
++   the stack pointer.  We also allow the frame pointer to be replaced by
++   the stack pointer.  */
++#define ELIMINABLE_REGS                                       \
++{                                                     \
++  {ARG_POINTER_REGNUM,         STACK_POINTER_REGNUM},         \
++  {ARG_POINTER_REGNUM,         FRAME_POINTER_REGNUM},         \
++  {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}                \
++}
++
++/* Let the compiler know that we want to use the ELIMINABLE_REGS macro
++   above.  */
++#define CAN_ELIMINATE(FROM, TO) 1
++
++/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'.  It specifies the
++   initial difference between the specified pair of registers.  This macro must
++   be defined if `ELIMINABLE_REGS' is defined.  */
++#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
++  (OFFSET) = ubicom32_initial_elimination_offset (FROM, TO)
++
++/* If defined, the maximum amount of space required for outgoing arguments will
++   be computed and placed into the variable
++   `current_function_outgoing_args_size'.  No space will be pushed onto the
++   stack for each call; instead, the function prologue should increase the
++   stack frame size by this amount.
++
++   Defining both `PUSH_ROUNDING' and `ACCUMULATE_OUTGOING_ARGS' is not
++   proper.  */
++#define ACCUMULATE_OUTGOING_ARGS 1
++
++/* Define this macro if functions should assume that stack space has been
++   allocated for arguments even when their values are passed in registers.
++
++   The value of this macro is the size, in bytes, of the area reserved for
++   arguments passed in registers for the function represented by FNDECL.
++
++   This space can be allocated by the caller, or be a part of the
++   machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' says
++   which.  */
++#define REG_PARM_STACK_SPACE(FNDECL) ubicom32_reg_parm_stack_space(FNDECL)
++
++/* A C expression that should indicate the number of bytes of its own arguments
++   that a function pops on returning, or 0 if the function pops no arguments
++   and the caller must therefore pop them all after the function returns.
++
++   FUNDECL is a C variable whose value is a tree node that describes the
++   function in question.  Normally it is a node of type `FUNCTION_DECL' that
++   describes the declaration of the function.  From this it is possible to
++   obtain the DECL_MACHINE_ATTRIBUTES of the function.
++
++   FUNTYPE is a C variable whose value is a tree node that describes the
++   function in question.  Normally it is a node of type `FUNCTION_TYPE' that
++   describes the data type of the function.  From this it is possible to obtain
++   the data types of the value and arguments (if known).
++
++   When a call to a library function is being considered, FUNTYPE will contain
++   an identifier node for the library function.  Thus, if you need to
++   distinguish among various library functions, you can do so by their names.
++   Note that "library function" in this context means a function used to
++   perform arithmetic, whose name is known specially in the compiler and was
++   not mentioned in the C code being compiled.
++
++   STACK-SIZE is the number of bytes of arguments passed on the stack.  If a
++   variable number of bytes is passed, it is zero, and argument popping will
++   always be the responsibility of the calling function.
++
++   On the Vax, all functions always pop their arguments, so the definition of
++   this macro is STACK-SIZE.  On the 68000, using the standard calling
++   convention, no functions pop their arguments, so the value of the macro is
++   always 0 in this case.  But an alternative calling convention is available
++   in which functions that take a fixed number of arguments pop them but other
++   functions (such as `printf') pop nothing (the caller pops all).  When this
++   convention is in use, FUNTYPE is examined to determine whether a function
++   takes a fixed number of arguments.  */
++#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0
++
++/* A C expression that controls whether a function argument is passed in a
++   register, and which register.
++
++   The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes (in a way
++   defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE) all of the previous
++   arguments so far passed in registers; MODE, the machine mode of the argument;
++   TYPE, the data type of the argument as a tree node or 0 if that is not known
++   (which happens for C support library functions); and NAMED, which is 1 for an
++   ordinary argument and 0 for nameless arguments that correspond to `...' in the
++   called function's prototype.
++
++   The value of the expression should either be a `reg' RTX for the hard
++   register in which to pass the argument, or zero to pass the argument on the
++   stack.
++
++   For machines like the Vax and 68000, where normally all arguments are
++   pushed, zero suffices as a definition.
++
++   The usual way to make the ANSI library `stdarg.h' work on a machine where
++   some arguments are usually passed in registers, is to cause nameless
++   arguments to be passed on the stack instead.  This is done by making
++   `FUNCTION_ARG' return 0 whenever NAMED is 0.
++
++   You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the definition of
++   this macro to determine if this argument is of a type that must be passed in
++   the stack.  If `REG_PARM_STACK_SPACE' is not defined and `FUNCTION_ARG'
++   returns non-zero for such an argument, the compiler will abort.  If
++   `REG_PARM_STACK_SPACE' is defined, the argument will be computed in the
++   stack and then loaded into a register.  */
++#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
++  function_arg (&CUM, MODE, TYPE, NAMED)
++
++#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
++  function_incoming_arg (&CUM, MODE, TYPE, NAMED)
++
++/* A C expression for the number of words, at the beginning of an argument,
++   must be put in registers.  The value must be zero for arguments that are
++   passed entirely in registers or that are entirely pushed on the stack.
++
++   On some machines, certain arguments must be passed partially in registers
++   and partially in memory.  On these machines, typically the first N words of
++   arguments are passed in registers, and the rest on the stack.  If a
++   multi-word argument (a `double' or a structure) crosses that boundary, its
++   first few words must be passed in registers and the rest must be pushed.
++   This macro tells the compiler when this occurs, and how many of the words
++   should go in registers.
++
++   `FUNCTION_ARG' for these arguments should return the first register to be
++   used by the caller for this argument; likewise `FUNCTION_INCOMING_ARG', for
++   the called function.  */
++
++/* A C expression that indicates when an argument must be passed by reference.
++   If nonzero for an argument, a copy of that argument is made in memory and a
++   pointer to the argument is passed instead of the argument itself.  The
++   pointer is passed in whatever way is appropriate for passing a pointer to
++   that type.
++
++   On machines where `REG_PARM_STACK_SPACE' is not defined, a suitable
++   definition of this macro might be
++      #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED)  \
++        MUST_PASS_IN_STACK (MODE, TYPE)  */
++
++/* If defined, a C expression that indicates when it is the called function's
++   responsibility to make a copy of arguments passed by invisible reference.
++   Normally, the caller makes a copy and passes the address of the copy to the
++   routine being called.  When FUNCTION_ARG_CALLEE_COPIES is defined and is
++   nonzero, the caller does not make a copy.  Instead, it passes a pointer to
++   the "live" value.  The called function must not modify this value.  If it
++   can be determined that the value won't be modified, it need not make a copy;
++   otherwise a copy must be made.  */
++
++/* A C type for declaring a variable that is used as the first argument of
++   `FUNCTION_ARG' and other related values.  For some target machines, the type
++   `int' suffices and can hold the number of bytes of argument so far.
++
++   There is no need to record in `CUMULATIVE_ARGS' anything about the arguments
++   that have been passed on the stack.  The compiler has other variables to
++   keep track of that.  For target machines on which all arguments are passed
++   on the stack, there is no need to store anything in `CUMULATIVE_ARGS';
++   however, the data structure must exist and should not be empty, so use
++   `int'.  */
++struct cum_arg
++{
++  int nbytes;
++  int reg;
++  int stdarg;
++};
++#define CUMULATIVE_ARGS struct cum_arg
++
++/* A C statement (sans semicolon) for initializing the variable CUM for the
++   state at the beginning of the argument list.  The variable has type
++   `CUMULATIVE_ARGS'.  The value of FNTYPE is the tree node for the data type
++   of the function which will receive the args, or 0 if the args are to a
++   compiler support library function.  The value of INDIRECT is nonzero when
++   processing an indirect call, for example a call through a function pointer.
++   The value of INDIRECT is zero for a call to an explicitly named function, a
++   library function call, or when `INIT_CUMULATIVE_ARGS' is used to find
++   arguments for the function being compiled.
++
++   When processing a call to a compiler support library function, LIBNAME
++   identifies which one.  It is a `symbol_ref' rtx which contains the name of
++   the function, as a string.  LIBNAME is 0 when an ordinary C function call is
++   being processed.  Thus, each time this macro is called, either LIBNAME or
++   FNTYPE is nonzero, but never both of them at once.  */
++
++#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT, NAMED_ARGS) \
++ init_cumulative_args (&(CUM), FNTYPE, LIBNAME, INDIRECT);
++
++/* A C statement (sans semicolon) to update the summarizer variable CUM to
++   advance past an argument in the argument list.  The values MODE, TYPE and
++   NAMED describe that argument.  Once this is done, the variable CUM is
++   suitable for analyzing the *following* argument with `FUNCTION_ARG', etc.
++
++   This macro need not do anything if the argument in question was passed on
++   the stack.  The compiler knows how to track the amount of stack space used
++   for arguments without any special help.  */
++#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)  \
++ ((CUM).nbytes += ((MODE) != BLKmode                  \
++                 ? (GET_MODE_SIZE (MODE) + 3) & ~3    \
++                 : (int_size_in_bytes (TYPE) + 3) & ~3))
++
++/* For the Ubicom32 we define the upper function argument register here.  */
++#define UBICOM32_FUNCTION_ARG_REGS 10
++
++/* A C expression that is nonzero if REGNO is the number of a hard register in
++   which function arguments are sometimes passed.  This does *not* include
++   implicit arguments such as the static chain and the structure-value address.
++   On many machines, no registers can be used for this purpose since all
++   function arguments are pushed on the stack.  */
++#define FUNCTION_ARG_REGNO_P(N) ((N) < UBICOM32_FUNCTION_ARG_REGS)
++
++\f
++/* How Scalar Function Values are Returned.  */
++
++/* The number of the hard register that is used to return a scalar value from a
++   function call.  */
++#define RETURN_VALUE_REGNUM 0
++
++/* A C expression to create an RTX representing the place where a function
++   returns a value of data type VALTYPE.  VALTYPE is a tree node representing a
++   data type.  Write `TYPE_MODE (VALTYPE)' to get the machine mode used to
++   represent that type.  On many machines, only the mode is relevant.
++   (Actually, on most machines, scalar values are returned in the same place
++   regardless of mode).
++
++   If `PROMOTE_FUNCTION_RETURN' is defined, you must apply the same promotion
++   rules specified in `PROMOTE_MODE' if VALTYPE is a scalar type.
++
++   If the precise function being called is known, FUNC is a tree node
++   (`FUNCTION_DECL') for it; otherwise, FUNC is a null pointer.  This makes it
++   possible to use a different value-returning convention for specific
++   functions when all their calls are known.
++
++   `FUNCTION_VALUE' is not used for return vales with aggregate data types,
++   because these are returned in another way.  See `STRUCT_VALUE_REGNUM' and
++   related macros, below.  */
++#define FUNCTION_VALUE(VALTYPE, FUNC) \
++  gen_rtx_REG (TYPE_MODE (VALTYPE), FIRST_DATA_REGNUM)
++
++/* A C expression to create an RTX representing the place where a library
++   function returns a value of mode MODE.
++
++   Note that "library function" in this context means a compiler support
++   routine, used to perform arithmetic, whose name is known specially by the
++   compiler and was not mentioned in the C code being compiled.
++
++   The definition of `LIBRARY_VALUE' need not be concerned aggregate data
++   types, because none of the library functions returns such types.  */
++#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, FIRST_DATA_REGNUM)
++
++/* A C expression that is nonzero if REGNO is the number of a hard register in
++   which the values of called function may come back.
++
++   A register whose use for returning values is limited to serving as the
++   second of a pair (for a value of type `double', say) need not be recognized
++   by this macro.  So for most machines, this definition suffices:
++
++      #define FUNCTION_VALUE_REGNO_P(N) ((N) == RETURN)
++
++   If the machine has register windows, so that the caller and the called
++   function use different registers for the return value, this macro should
++   recognize only the caller's register numbers.  */
++#define FUNCTION_VALUE_REGNO_P(N) ((N) == FIRST_DATA_REGNUM)
++
++\f
++/* How Large Values are Returned.  */
++
++/* A C expression which can inhibit the returning of certain function values in
++   registers, based on the type of value.  A nonzero value says to return the
++   function value in memory, just as large structures are always returned.
++   Here TYPE will be a C expression of type `tree', representing the data type
++   of the value.
++
++   Note that values of mode `BLKmode' must be explicitly handled by this macro.
++   Also, the option `-fpcc-struct-return' takes effect regardless of this
++   macro.  On most systems, it is possible to leave the macro undefined; this
++   causes a default definition to be used, whose value is the constant 1 for
++   `BLKmode' values, and 0 otherwise.
++
++   Do not use this macro to indicate that structures and unions should always
++   be returned in memory.  You should instead use `DEFAULT_PCC_STRUCT_RETURN'
++   to indicate this.  */
++#define RETURN_IN_MEMORY(TYPE)  \
++  (int_size_in_bytes (TYPE) > 8 || TYPE_MODE (TYPE) == BLKmode)
++
++/* Define this macro to be 1 if all structure and union return values must be
++   in memory.  Since this results in slower code, this should be defined only
++   if needed for compatibility with other compilers or with an ABI.  If you
++   define this macro to be 0, then the conventions used for structure and union
++   return values are decided by the `RETURN_IN_MEMORY' macro.
++
++   If not defined, this defaults to the value 1.  */
++#define DEFAULT_PCC_STRUCT_RETURN 0
++
++/*   If the structure value address is not passed in a register, define
++     `STRUCT_VALUE' as an expression returning an RTX for the place
++     where the address is passed.  If it returns 0, the address is
++     passed as an "invisible" first argument.  */
++#define STRUCT_VALUE 0
++
++/* Define this macro as a C expression that is nonzero if the return
++   instruction or the function epilogue ignores the value of the stack pointer;
++   in other words, if it is safe to delete an instruction to adjust the stack
++   pointer before a return from the function.
++
++   Note that this macro's value is relevant only for functions for which frame
++   pointers are maintained.  It is never safe to delete a final stack
++   adjustment in a function that has no frame pointer, and the compiler knows
++   this regardless of `EXIT_IGNORE_STACK'.  */
++#define EXIT_IGNORE_STACK 1
++
++/* A C statement or compound statement to output to FILE some assembler code to
++   call the profiling subroutine `mcount'.  Before calling, the assembler code
++   must load the address of a counter variable into a register where `mcount'
++   expects to find the address.  The name of this variable is `LP' followed by
++   the number LABELNO, so you would generate the name using `LP%d' in a
++   `fprintf'.
++
++   The details of how the address should be passed to `mcount' are determined
++   by your operating system environment, not by GNU CC.  To figure them out,
++   compile a small program for profiling using the system's installed C
++   compiler and look at the assembler code that results.
++
++   This declaration must be present, but it can be an abort if profiling is
++   not implemented.  */
++
++#define FUNCTION_PROFILER(file, labelno) ubicom32_profiler(file, labelno)
++
++/* A C statement to output, on the stream FILE, assembler code for a block of
++   data that contains the constant parts of a trampoline.  This code should not
++   include a label--the label is taken care of automatically.  */
++#if 0
++#define TRAMPOLINE_TEMPLATE(FILE)                     \
++  do {                                                        \
++    fprintf (FILE, "\tadd -4,sp\n");                  \
++    fprintf (FILE, "\t.long 0x0004fffa\n");           \
++    fprintf (FILE, "\tmov (0,sp),a0\n");              \
++    fprintf (FILE, "\tadd 4,sp\n");                   \
++    fprintf (FILE, "\tmov (13,a0),a1\n");             \
++    fprintf (FILE, "\tmov (17,a0),a0\n");             \
++    fprintf (FILE, "\tjmp (a0)\n");                   \
++    fprintf (FILE, "\t.long 0\n");                    \
++    fprintf (FILE, "\t.long 0\n");                    \
++  } while (0)
++#endif
++
++/* A C expression for the size in bytes of the trampoline, as an integer.  */
++#define TRAMPOLINE_SIZE 0x1b
++
++/* Alignment required for trampolines, in bits.
++
++   If you don't define this macro, the value of `BIGGEST_ALIGNMENT' is used for
++   aligning trampolines.  */
++#define TRAMPOLINE_ALIGNMENT 32
++
++/* A C statement to initialize the variable parts of a trampoline.  ADDR is an
++   RTX for the address of the trampoline; FNADDR is an RTX for the address of
++   the nested function; STATIC_CHAIN is an RTX for the static chain value that
++   should be passed to the function when it is called.  */
++#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT)                     \
++{                                                                     \
++  emit_move_insn (gen_rtx_MEM (SImode, plus_constant ((TRAMP), 0x14)),        \
++               (CXT));                                                \
++  emit_move_insn (gen_rtx_MEM (SImode, plus_constant ((TRAMP), 0x18)),        \
++               (FNADDR));                                             \
++}
++
++/* Ubicom32 supports pre and post increment/decrement addressing.  */
++#define HAVE_POST_INCREMENT 1
++#define HAVE_PRE_INCREMENT 1
++#define HAVE_POST_DECREMENT 1
++#define HAVE_PRE_DECREMENT 1
++
++/* Ubicom32 supports pre and post address side-effects with constants
++   other than the size of the memory operand.  */
++#define HAVE_PRE_MODIFY_DISP 1
++#define HAVE_POST_MODIFY_DISP 1
++
++/* A C expression that is 1 if the RTX X is a constant which is a valid
++   address.  On most machines, this can be defined as `CONSTANT_P (X)',
++   but a few machines are more restrictive in which constant addresses
++   are supported.
++
++   `CONSTANT_P' accepts integer-values expressions whose values are not
++   explicitly known, such as `symbol_ref', `label_ref', and `high'
++   expressions and `const' arithmetic expressions, in addition to
++   `const_int' and `const_double' expressions.  */
++#define CONSTANT_ADDRESS_P(X)                                         \
++  (GET_CODE (X) == LABEL_REF                                          \
++   || (GET_CODE (X) == CONST                                          \
++       && GET_CODE (XEXP (X, 0)) == PLUS                              \
++       && GET_CODE (XEXP (XEXP (X, 0), 0)) == LABEL_REF))
++
++/* Ubicom32 supports a maximum of 2 registers in a valid memory address.
++   One is always an address register while a second, optional, one may be a
++   data register.  */
++#define MAX_REGS_PER_ADDRESS 2
++
++/* A C compound statement with a conditional `goto LABEL;' executed if X (an
++   RTX) is a legitimate memory address on the target machine for a memory
++   operand of mode MODE.
++
++   It usually pays to define several simpler macros to serve as subroutines for
++   this one.  Otherwise it may be too complicated to understand.
++
++   This macro must exist in two variants: a strict variant and a non-strict
++   one.  The strict variant is used in the reload pass.  It must be defined so
++   that any pseudo-register that has not been allocated a hard register is
++   considered a memory reference.  In contexts where some kind of register is
++   required, a pseudo-register with no hard register must be rejected.
++
++   The non-strict variant is used in other passes.  It must be defined to
++   accept all pseudo-registers in every context where some kind of register is
++   required.
++
++   Compiler source files that want to use the strict variant of this macro
++   define the macro `REG_OK_STRICT'.  You should use an `#ifdef REG_OK_STRICT'
++   conditional to define the strict variant in that case and the non-strict
++   variant otherwise.
++
++   Subroutines to check for acceptable registers for various purposes (one for
++   base registers, one for index registers, and so on) are typically among the
++   subroutines used to define `GO_IF_LEGITIMATE_ADDRESS'.  Then only these
++   subroutine macros need have two variants; the higher levels of macros may be
++   the same whether strict or not.
++
++   Normally, constant addresses which are the sum of a `symbol_ref' and an
++   integer are stored inside a `const' RTX to mark them as constant.
++   Therefore, there is no need to recognize such sums specifically as
++   legitimate addresses.  Normally you would simply recognize any `const' as
++   legitimate.
++
++   Usually `PRINT_OPERAND_ADDRESS' is not prepared to handle constant sums that
++   are not marked with `const'.  It assumes that a naked `plus' indicates
++   indexing.  If so, then you *must* reject such naked constant sums as
++   illegitimate addresses, so that none of them will be given to
++   `PRINT_OPERAND_ADDRESS'.
++
++   On some machines, whether a symbolic address is legitimate depends on the
++   section that the address refers to.  On these machines, define the macro
++   `ENCODE_SECTION_INFO' to store the information into the `symbol_ref', and
++   then check for it here.  When you see a `const', you will have to look
++   inside it to find the `symbol_ref' in order to determine the section.
++
++   The best way to modify the name string is by adding text to the beginning,
++   with suitable punctuation to prevent any ambiguity.  Allocate the new name
++   in `saveable_obstack'.  You will have to modify `ASM_OUTPUT_LABELREF' to
++   remove and decode the added text and output the name accordingly, and define
++   `STRIP_NAME_ENCODING' to access the original name string.
++
++   You can check the information stored here into the `symbol_ref' in the
++   definitions of the macros `GO_IF_LEGITIMATE_ADDRESS' and
++   `PRINT_OPERAND_ADDRESS'.  */
++/* On the ubicom32, the value in the address register must be
++   in the same memory space/segment as the effective address.
++
++   This is problematical for reload since it does not understand
++   that base+index != index+base in a memory reference.  */
++
++#ifdef REG_OK_STRICT
++#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)       \
++  if (ubicom32_legitimate_address_p (MODE, X, 1)) goto ADDR;
++#else
++#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)       \
++  if (ubicom32_legitimate_address_p (MODE, X, 0)) goto ADDR;
++#endif
++
++/* Try machine-dependent ways of modifying an illegitimate address
++   to be legitimate.  If we find one, return the new, valid address.
++   This macro is used in only one place: `memory_address' in explow.c.
++
++   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 and WIN are passed so that this macro can use
++   GO_IF_LEGITIMATE_ADDRESS.
++
++   It is always safe for this macro to do nothing.  It exists to recognize
++   opportunities to optimize the output.
++
++   On RS/6000, first check for the sum of a register with a constant
++   integer that is out of range.  If so, generate code to add the
++   constant with the low-order 16 bits masked to the register and force
++   this result into another register (this can be done with `cau').
++   Then generate an address of REG+(CONST&0xffff), allowing for the
++   possibility of bit 16 being a one.
++
++   Then check for the sum of a register and something not constant, try to
++   load the other things into a register and return the sum.  */
++
++#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)                                \
++{                                                                     \
++   rtx result = ubicom32_legitimize_address ((X), (OLDX), (MODE));    \
++   if (result != NULL_RTX)                                            \
++     {                                                                        \
++       (X) = result;                                                  \
++       goto WIN;                                                      \
++     }                                                                        \
++}
++
++/* Try a machine-dependent way of reloading an illegitimate address
++   operand.  If we find one, push the reload and jump to WIN.  This
++   macro is used in only one place: `find_reloads_address' in reload.c.  */
++#define LEGITIMIZE_RELOAD_ADDRESS(AD, MODE, OPNUM, TYPE, IND, WIN)    \
++{                                                                     \
++  rtx new_rtx = ubicom32_legitimize_reload_address ((AD), (MODE), (OPNUM), (int)(TYPE));      \
++  if (new_rtx)                                                                \
++    {                                                                 \
++      (AD) = new_rtx;                                                 \
++      goto WIN;                                                               \
++    }                                                                 \
++}
++
++/* A C statement or compound statement with a conditional `goto LABEL;'
++   executed if memory address X (an RTX) can have different meanings depending
++   on the machine mode of the memory reference it is used for or if the address
++   is valid for some modes but not others.
++
++   Autoincrement and autodecrement addresses typically have mode-dependent
++   effects because the amount of the increment or decrement is the size of the
++   operand being addressed.  Some machines have other mode-dependent addresses.
++   Many RISC machines have no mode-dependent addresses.
++
++   You may assume that ADDR is a valid address for the machine.  */
++#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)     \
++  if (ubicom32_mode_dependent_address_p (ADDR))               \
++    goto LABEL;
++
++/* A C expression that is nonzero if X is a legitimate constant for an
++   immediate operand on the target machine.  You can assume that X
++   satisfies `CONSTANT_P', so you need not check this.  In fact, `1' is
++   a suitable definition for this macro on machines where anything
++   `CONSTANT_P' is valid.  */
++#define LEGITIMATE_CONSTANT_P(X) \
++  ubicom32_legitimate_constant_p ((X))
++
++/* Moves between registers are pretty-much single instructions for
++   Ubicom32.  We make this the default "2" that gcc likes.  */
++#define REGISTER_MOVE_COST(MODE, FROM, TO) 2
++
++/* This is a little bit of magic from the S390 port that wins 2% on code
++   size when building the Linux kernel!  Unfortunately while it wins on
++   that size the user-space apps built using FD-PIC don't improve and the
++   performance is lower because we put more pressure on the caches.  We may
++   want this back on some future CPU that has higher cache performance.  */
++/* #define IRA_HARD_REGNO_ADD_COST_MULTIPLIER(regno) 0.5 */
++
++/* Moves between registers and memory are more expensive than between
++   registers because we have caches and write buffers that slow things
++   down!  */
++#define MEMORY_MOVE_COST(MODE, CLASS, IN) 2
++
++/* A fall-through branch is very low cost but anything that changes the PC
++   incurs a major pipeline hazard.  We don't make the full extent of this
++   hazard visible because we hope that multiple threads will absorb much
++   of the cost and so we don't want a jump being replaced with, say, 7
++   instructions.  */
++#define BRANCH_COST(SPEED_P, PREDICTABLE_P) \
++  ((PREDICTABLE_P) ? 1 : 3)
++
++/* Define this macro as a C expression which is nonzero if accessing less than
++   a word of memory (i.e. a `char' or a `short') is no faster than accessing a
++   word of memory, i.e., if such access require more than one instruction or if
++   there is no difference in cost between byte and (aligned) word loads.
++
++   When this macro is not defined, the compiler will access a field by finding
++   the smallest containing object; when it is defined, a fullword load will be
++   used if alignment permits.  Unless bytes accesses are faster than word
++   accesses, using word accesses is preferable since it may eliminate
++   subsequent memory access if subsequent accesses occur to other fields in the
++   same word of the structure, but to different bytes.  */
++#define SLOW_BYTE_ACCESS 0
++
++/* The number of scalar move insns which should be generated instead of a
++   string move insn or a library call.  Increasing the value will always make
++   code faster, but eventually incurs high cost in increased code size.
++
++   If you don't define this, a reasonable default is used.  */
++/* According to expr.c, a value of around 6 should minimize code size.  */
++#define MOVE_RATIO(SPEED) 6
++
++/* We're much better off calling a constant function address with the
++   Ubicom32 architecture because we have an opcode for doing so.  Don't
++   let the compiler extract function addresses as common subexpressions
++   into an address register.  */
++#define NO_FUNCTION_CSE
++
++#define SELECT_CC_MODE(OP, X, Y) ubicom32_select_cc_mode (OP, X, Y)
++
++#define REVERSIBLE_CC_MODE(MODE) 1
++
++/* Canonicalize a comparison from one we don't have to one we do have.  */
++#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
++  ubicom32_canonicalize_comparison (&(CODE), &(OP0), &(OP1))
++
++/* Dividing the output into sections.  */
++
++/* A C expression whose value is a string containing the assembler operation
++   that should precede instructions and read-only data.  Normally `".text"' is
++   right.  */
++#define TEXT_SECTION_ASM_OP "\t.section .text"
++
++/* A C expression whose value is a string containing the assembler operation to
++   identify the following data as writable initialized data.  Normally
++   `".data"' is right.  */
++#define DATA_SECTION_ASM_OP "\t.section .data"
++
++
++/* If defined, a C expression whose value is a string containing the
++   assembler operation to identify the following data as
++   uninitialized global data.  If not defined, and neither
++   `ASM_OUTPUT_BSS' nor `ASM_OUTPUT_ALIGNED_BSS' are defined,
++   uninitialized global data will be output in the data section if
++   `-fno-common' is passed, otherwise `ASM_OUTPUT_COMMON' will be
++   used.  */
++#define BSS_SECTION_ASM_OP "\t.section .bss"
++
++/* This is how we tell the assembler that a symbol is weak.  */
++
++#define ASM_WEAKEN_LABEL(FILE, NAME)  \
++  do                                  \
++    {                                 \
++      fputs ("\t.weak\t", (FILE));    \
++      assemble_name ((FILE), (NAME)); \
++      fputc ('\n', (FILE));           \
++    }                                 \
++  while (0)
++
++/* The Overall Framework of an Assembler File.  */
++
++#undef SET_ASM_OP
++#define SET_ASM_OP "\t.set\t"
++
++/* A C string constant describing how to begin a comment in the target
++   assembler language.  The compiler assumes that the comment will end at the
++   end of the line.  */
++#define ASM_COMMENT_START ";"
++
++/* A C string constant for text to be output before each `asm' statement or
++   group of consecutive ones.  Normally this is `"#APP"', which is a comment
++   that has no effect on most assemblers but tells the GNU assembler that it
++   must check the lines that follow for all valid assembler constructs.  */
++#define ASM_APP_ON "#APP\n"
++
++/* A C string constant for text to be output after each `asm' statement or
++   group of consecutive ones.  Normally this is `"#NO_APP"', which tells the
++   GNU assembler to resume making the time-saving assumptions that are valid
++   for ordinary compiler output.  */
++#define ASM_APP_OFF "#NO_APP\n"
++
++/* Like `ASM_OUTPUT_BSS' except takes the required alignment as a separate,
++   explicit argument.  If you define this macro, it is used in place of
++   `ASM_OUTPUT_BSS', and gives you more flexibility in handling the required
++   alignment of the variable.  The alignment is specified as the number of
++   bits.
++
++   Try to use function `asm_output_aligned_bss' defined in file `varasm.c' when
++   defining this macro.  */
++#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
++  asm_output_aligned_bss ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
++
++/* A C expression to assign to OUTVAR (which is a variable of type `char *') a
++   newly allocated string made from the string NAME and the number NUMBER, with
++   some suitable punctuation added.  Use `alloca' to get space for the string.
++
++   The string will be used as an argument to `ASM_OUTPUT_LABELREF' to produce
++   an assembler label for an internal static variable whose name is NAME.
++   Therefore, the string must be such as to result in valid assembler code.
++   The argument NUMBER is different each time this macro is executed; it
++   prevents conflicts between similarly-named internal static variables in
++   different scopes.
++
++   Ideally this string should not be a valid C identifier, to prevent any
++   conflict with the user's own symbols.  Most assemblers allow periods or
++   percent signs in assembler symbols; putting at least one of these between
++   the name and the number will suffice.  */
++#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO)        \
++  ((OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
++   sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO)))
++
++#define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM)      \
++  sprintf (STRING, "*.%s%ld", PREFIX, (long)(NUM))
++/* A C statement to store into the string STRING a label whose name
++   is made from the string PREFIX and the number NUM.
++
++   This string, when output subsequently by `assemble_name', should
++   produce the output that `(*targetm.asm_out.internal_label)' would produce
++   with the same PREFIX and NUM.
++
++   If the string begins with `*', then `assemble_name' will output
++   the rest of the string unchanged.  It is often convenient for
++   `ASM_GENERATE_INTERNAL_LABEL' to use `*' in this way.  If the
++   string doesn't start with `*', then `ASM_OUTPUT_LABELREF' gets to
++   output the string, and may change it.  (Of course,
++   `ASM_OUTPUT_LABELREF' is also part of your machine description, so
++   you should know what it does on your machine.)  */
++
++/* This says how to output assembler code to declare an
++   uninitialized external linkage data object.  Under SVR4,
++   the linker seems to want the alignment of data objects
++   to depend on their types.  We do exactly that here.  */
++
++#define COMMON_ASM_OP "\t.comm\t"
++
++#undef  ASM_OUTPUT_COMMON
++#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED)          \
++  do                                                          \
++    {                                                         \
++      fprintf ((FILE), "%s", COMMON_ASM_OP);                  \
++      assemble_name ((FILE), (NAME));                         \
++      fprintf ((FILE), ", %u\n", (SIZE));                     \
++    }                                                         \
++  while (0)
++
++/* This says how to output assembler code to declare an
++   uninitialized internal linkage data object.  Under SVR4,
++   the linker seems to want the alignment of data objects
++   to depend on their types.  We do exactly that here.  */
++#define LOCAL_ASM_OP  "\t.lcomm\t"
++
++#undef  ASM_OUTPUT_LOCAL
++#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)           \
++  do                                                          \
++    {                                                         \
++      fprintf ((FILE), "%s", LOCAL_ASM_OP);                   \
++      assemble_name ((FILE), (NAME));                         \
++      fprintf ((FILE), ", %u\n", (SIZE));                     \
++    }                                                         \
++  while (0)
++
++/* Globalizing directive for a label.  */
++#define GLOBAL_ASM_OP ".global\t"
++
++/* Output the operand of an instruction.  */
++#define PRINT_OPERAND(FILE, X, CODE) \
++  ubicom32_print_operand(FILE, X, CODE)
++
++/* Output the address of an operand.  */
++#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
++  ubicom32_print_operand_address (FILE, ADDR)
++
++/* A C expression to output to STREAM some assembler code which will push hard
++   register number REGNO onto the stack.  The code need not be optimal, since
++   this macro is used only when profiling.  */
++#define ASM_OUTPUT_REG_PUSH(FILE, REGNO)
++
++/* A C expression to output to STREAM some assembler code which will pop hard
++   register number REGNO off of the stack.  The code need not be optimal, since
++   this macro is used only when profiling.  */
++#define ASM_OUTPUT_REG_POP(FILE, REGNO)
++
++/* This macro should be provided on machines where the addresses in a dispatch
++   table are relative to the table's own address.
++
++   The definition should be a C statement to output to the stdio stream STREAM
++   an assembler pseudo-instruction to generate a difference between two labels.
++   VALUE and REL are the numbers of two internal labels.  The definitions of
++   these labels are output using `ASM_OUTPUT_INTERNAL_LABEL', and they must be
++   printed in the same way here.  For example,
++
++      fprintf (STREAM, "\t.word L%d-L%d\n", VALUE, REL)  */
++#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
++  fprintf (FILE, "\t%s .L%d-.L%d\n", ".long", VALUE, REL)
++
++/* This macro should be provided on machines where the addresses in a dispatch
++   table are absolute.
++
++   The definition should be a C statement to output to the stdio stream STREAM
++   an assembler pseudo-instruction to generate a reference to a label.  VALUE
++   is the number of an internal label whose definition is output using
++   `ASM_OUTPUT_INTERNAL_LABEL'.  For example,
++
++      fprintf (STREAM, "\t.word L%d\n", VALUE)  */
++#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
++  fprintf (STREAM, "\t.word .L%d\n", VALUE)
++
++/* Switch into a generic section.  */
++#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
++
++/* Assembler Commands for Alignment.  */
++
++#define ASM_OUTPUT_SKIP(STREAM, N) fprintf (STREAM, "\t.skip %d,0\n", N)
++/* A C statement to output to the stdio stream STREAM an assembler
++   instruction to advance the location counter by NBYTES bytes.
++   Those bytes should be zero when loaded.  NBYTES will be a C
++   expression of type `int'.  */
++
++/* A C statement to output to the stdio stream STREAM an assembler command to
++   advance the location counter to a multiple of 2 to the POWER bytes.  POWER
++   will be a C expression of type `int'.  */
++#define ASM_OUTPUT_ALIGN(FILE, LOG)   \
++  if ((LOG) != 0)                     \
++    fprintf (FILE, "\t.align %d\n", (LOG))
++
++/* A C expression that returns the DBX register number for the compiler
++   register number REGNO.  In simple cases, the value of this expression may be
++   REGNO itself.  But sometimes there are some registers that the compiler
++   knows about and DBX does not, or vice versa.  In such cases, some register
++   may need to have one number in the compiler and another for DBX.
++
++   If two registers have consecutive numbers inside GNU CC, and they can be
++   used as a pair to hold a multiword value, then they *must* have consecutive
++   numbers after renumbering with `DBX_REGISTER_NUMBER'.  Otherwise, debuggers
++   will be unable to access such a pair, because they expect register pairs to
++   be consecutive in their own numbering scheme.
++
++   If you find yourself defining `DBX_REGISTER_NUMBER' in way that does not
++   preserve register pairs, then what you must do instead is redefine the
++   actual register numbering scheme.
++
++   This declaration is required.  */
++#define DBX_REGISTER_NUMBER(REGNO) REGNO
++
++/* A C expression that returns the integer offset value for an automatic
++   variable having address X (an RTL expression).  The default computation
++   assumes that X is based on the frame-pointer and gives the offset from the
++   frame-pointer.  This is required for targets that produce debugging output
++   for DBX or COFF-style debugging output for SDB and allow the frame-pointer
++   to be eliminated when the `-g' options is used.  */
++#define DEBUGGER_AUTO_OFFSET(X)                                               \
++  ((GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)                  \
++    + (frame_pointer_needed                                           \
++       ? 0 : -initial_elimination_offset (FRAME_POINTER_REGNUM,               \
++                                        STACK_POINTER_REGNUM)))
++
++/* A C expression that returns the integer offset value for an argument having
++   address X (an RTL expression).  The nominal offset is OFFSET.  */
++#define DEBUGGER_ARG_OFFSET(OFFSET, X)                                        \
++  ((GET_CODE (X) == PLUS ? OFFSET : 0)                                        \
++    + (frame_pointer_needed                                           \
++       ? 0 : -initial_elimination_offset (ARG_POINTER_REGNUM,         \
++                                        STACK_POINTER_REGNUM)))
++
++/* A C expression that returns the type of debugging output GNU CC produces
++   when the user specifies `-g' or `-ggdb'.  Define this if you have arranged
++   for GNU CC to support more than one format of debugging output.  Currently,
++   the allowable values are `DBX_DEBUG', `SDB_DEBUG', `DWARF_DEBUG',
++   `DWARF2_DEBUG', and `XCOFF_DEBUG'.
++
++   The value of this macro only affects the default debugging output; the user
++   can always get a specific type of output by using `-gstabs', `-gcoff',
++   `-gdwarf-1', `-gdwarf-2', or `-gxcoff'.
++
++   Defined in svr4.h.
++*/
++#undef PREFERRED_DEBUGGING_TYPE
++#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
++
++/* Define this macro if GNU CC should produce dwarf version 2 format debugging
++   output in response to the `-g' option.
++
++   To support optional call frame debugging information, you must also define
++   `INCOMING_RETURN_ADDR_RTX' and either set `RTX_FRAME_RELATED_P' on the
++   prologue insns if you use RTL for the prologue, or call `dwarf2out_def_cfa'
++   and `dwarf2out_reg_save' as appropriate from `FUNCTION_PROLOGUE' if you
++   don't.
++
++   Defined in svr4.h.  */
++
++#define DWARF2_DEBUGGING_INFO 1
++/*#define DWARF2_UNWIND_INFO 1*/
++#define DWARF2_UNWIND_INFO 0
++#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, LINK_REGNO)
++#define INCOMING_FRAME_SP_OFFSET 0
++#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LINK_REGNO)
++#define EH_RETURN_FIRST 9
++#define EH_RETURN_DATA_REGNO(N) ((N) < 2 ? (N) + EH_RETURN_FIRST : INVALID_REGNUM)
++
++/* The EH_RETURN_STACKADJ_RTX macro returns RTL which describes the
++   location used to store the amount to ajdust the stack.  This is
++   usually a registers that is available from end of the function's body
++   to the end of the epilogue. Thus, this cannot be a register used as a
++   temporary by the epilogue.
++
++   This must be an integer register.  */
++#define EH_RETURN_STACKADJ_REGNO      11
++#define EH_RETURN_STACKADJ_RTX                \
++      gen_rtx_REG (Pmode, EH_RETURN_STACKADJ_REGNO)
++
++/* The EH_RETURN_HANDLER_RTX macro returns RTL which describes the
++   location used to store the address the processor should jump to
++   catch exception.  This is usually a registers that is available from
++   end of the function's body to the end of the epilogue. Thus, this
++   cannot be a register used as a temporary by the epilogue.
++
++   This must be an address register.  */
++#define EH_RETURN_HANDLER_REGNO               18
++#define EH_RETURN_HANDLER_RTX         \
++      gen_rtx_REG (Pmode, EH_RETURN_HANDLER_REGNO)
++
++/* #define DWARF2_DEBUGGING_INFO */
++
++/* Define this macro if GNU CC should produce dwarf version 2-style
++   line numbers.  This usually requires extending the assembler to
++   support them, and #defining DWARF2_LINE_MIN_INSN_LENGTH in the
++   assembler configuration header files.  */
++/* #define DWARF2_ASM_LINE_DEBUG_INFO 1 */
++
++
++/* An alias for a machine mode name.  This is the machine mode that elements
++   of a jump-table have.  */
++#define CASE_VECTOR_MODE Pmode
++
++/* Smallest number of different values for which it is best to use a
++   jump-table instead of a tree of conditional branches.  For most Ubicom32
++   targets this is quite small, but for the v1 architecture implementations
++   we had very little data memory and so heavily prefer the tree approach
++   rather than the jump tables.  */
++#define CASE_VALUES_THRESHOLD ubicom32_case_values_threshold
++
++/* Register operations within the Ubicom32 architecture always operate on
++   the whole register word and not just the sub-bits required for the opcode
++   mode size.  */
++#define WORD_REGISTER_OPERATIONS
++
++/* The maximum number of bytes that a single instruction can move quickly from
++   memory to memory.  */
++#define MOVE_MAX 4
++
++/* A C expression that is nonzero if on this machine the number of bits
++   actually used for the count of a shift operation is equal to the number of
++   bits needed to represent the size of the object being shifted.  When this
++   macro is non-zero, the compiler will assume that it is safe to omit a
++   sign-extend, zero-extend, and certain bitwise `and' instructions that
++   truncates the count of a shift operation.  On machines that have
++   instructions that act on bitfields at variable positions, which may include
++   `bit test' instructions, a nonzero `SHIFT_COUNT_TRUNCATED' also enables
++   deletion of truncations of the values that serve as arguments to bitfield
++   instructions.
++
++   If both types of instructions truncate the count (for shifts) and position
++   (for bitfield operations), or if no variable-position bitfield instructions
++   exist, you should define this macro.
++
++   However, on some machines, such as the 80386 and the 680x0, truncation only
++   applies to shift operations and not the (real or pretended) bitfield
++   operations.  Define `SHIFT_COUNT_TRUNCATED' to be zero on such machines.
++   Instead, add patterns to the `md' file that include the implied truncation
++   of the shift instructions.
++
++   You need not define this macro if it would always have the value of zero.  */
++#define SHIFT_COUNT_TRUNCATED 1
++
++/* A C expression which is nonzero if on this machine it is safe to "convert"
++   an integer of INPREC bits to one of OUTPREC bits (where OUTPREC is smaller
++   than INPREC) by merely operating on it as if it had only OUTPREC bits.
++
++   On many machines, this expression can be 1.
++
++   When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for modes for
++   which `MODES_TIEABLE_P' is 0, suboptimal code can result.  If this is the
++   case, making `TRULY_NOOP_TRUNCATION' return 0 in such cases may improve
++   things.  */
++#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
++
++/* A C string constant that tells the GNU CC driver program options to pass
++   to the assembler.  It can also specify how to translate options you give
++   to GNU CC into options for GNU CC to pass to the assembler.  See the
++   file `sun3.h' for an example of this.
++
++   Defined in svr4.h.  */
++#undef ASM_SPEC
++#define ASM_SPEC \
++  "%{march=*:-m%*} %{!march=*:-mubicom32v4} %{mfdpic:-mfdpic}"
++
++#define LINK_SPEC "\
++%{h*} %{v:-V} \
++%{b} \
++%{mfdpic:-melf32ubicom32fdpic -z text} \
++%{static:-dn -Bstatic} \
++%{shared:-G -Bdynamic} \
++%{symbolic:-Bsymbolic} \
++%{G*} \
++%{YP,*} \
++%{Qy:} %{!Qn:-Qy}"
++
++#undef STARTFILE_SPEC
++#undef ENDFILE_SPEC
++
++/* The svr4.h LIB_SPEC with -leval and --*group tacked on */
++
++#undef  LIB_SPEC
++#define LIB_SPEC "%{!shared:%{!symbolic:--start-group -lc -leval -lgcc --end-group}}"
++
++#undef HAVE_GAS_SHF_MERGE
++#define HAVE_GAS_SHF_MERGE 0
++
++#define HANDLE_SYSV_PRAGMA 1
++#undef HANDLE_PRAGMA_PACK
++
++typedef void (*ubicom32_func_ptr) (void);
++
++/* Define builtins for selected special-purpose instructions. */
++enum ubicom32_builtins
++{
++  UBICOM32_BUILTIN_UBICOM32_SWAPB_2,
++  UBICOM32_BUILTIN_UBICOM32_SWAPB_4
++};
++
++extern rtx ubicom32_compare_op0;
++extern rtx ubicom32_compare_op1;
++
++#define TYPE_ASM_OP   "\t.type\t"
++#define TYPE_OPERAND_FMT      "@%s"
++
++#ifndef ASM_DECLARE_RESULT
++#define ASM_DECLARE_RESULT(FILE, RESULT)
++#endif
++
++/* These macros generate the special .type and .size directives which
++   are used to set the corresponding fields of the linker symbol table
++   entries in an ELF object file under SVR4.  These macros also output
++   the starting labels for the relevant functions/objects.  */
++
++/* Write the extra assembler code needed to declare a function properly.
++   Some svr4 assemblers need to also have something extra said about the
++   function's return value.  We allow for that here.  */
++
++#ifndef ASM_DECLARE_FUNCTION_NAME
++#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL)           \
++  do                                                          \
++    {                                                         \
++      ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function");     \
++      ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL));          \
++      ASM_OUTPUT_LABEL (FILE, NAME);                          \
++    }                                                         \
++  while (0)
++#endif
+--- /dev/null
++++ b/gcc/config/ubicom32/ubicom32.md
+@@ -0,0 +1,3753 @@
++; GCC machine description for Ubicom32
++;
++; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software
++; Foundation, Inc.
++; Contributed by Ubicom, Inc.
++;
++; This file is part of GCC.
++;
++; GCC is free software; you can redistribute it and/or modify
++; it under the terms of the GNU General Public License as published by
++; the Free Software Foundation; either version 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_constants
++  [(AUX_DATA_REGNO 15)
++   (LINK_REGNO     21)
++   (SP_REGNO       23)
++   (ACC0_HI_REGNO  24)
++   (ACC1_HI_REGNO  26)
++   (CC_REGNO       30)])
++
++(define_constants
++  [(UNSPEC_FDPIC_GOT 0)
++   (UNSPEC_FDPIC_GOT_FUNCDESC 1)])
++
++(define_constants
++  [(UNSPEC_VOLATILE_LOAD_FDPIC_FUNCDESC 0)])
++
++;; Types of instructions (for scheduling purposes).
++
++(define_attr "type" "mul,addr,other"
++  (const_string "other"))
++
++; Define instruction scheduling characteristics.  We can only issue
++; one instruction per clock so we don't need to define CPU units.
++;
++(define_automaton "ubicom32")
++
++(define_cpu_unit "i_pipeline" "ubicom32");
++
++; We have a 4 cycle hazard associated with address calculations which
++; seems rather tricky to avoid so we go with a defensive assumption
++; that almost anything can be used to generate addresses.
++;
++;(define_insn_reservation "ubicom32_other" 4
++;                      (eq_attr "type" "other")
++;                      "i_pipeline")
++
++; Some moves don't generate hazards.
++;
++;(define_insn_reservation "ubicom32_addr" 1
++;                      (eq_attr "type" "addr")
++;                      "i_pipeline")
++
++; We need 3 cycles between a multiply instruction and any use of the
++; matching accumulator register(s).
++;
++(define_insn_reservation "ubicom32_mul" 4
++                       (eq_attr "type" "mul")
++                       "i_pipeline")
++
++(define_attr "length" ""
++  (const_int 4))
++
++(include "predicates.md")
++(include "constraints.md")
++
++; 8-bit move with no change to the flags reg.
++;
++(define_insn "movqi"
++  [(set (match_operand:QI 0 "nonimmediate_operand" "=rm")
++      (match_operand:QI 1 "ubicom32_move_operand"  "g"))]
++  ""
++  "move.1\\t%0, %1")
++
++; Combiner-generated 8-bit move with the zero flag set accordingly.
++;
++(define_insn "movqi_ccszn"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:QI 0 "nonimmediate_operand" "rm")
++               (const_int 0)))
++   (set (match_operand:QI 1 "nonimmediate_operand"       "=rm")
++      (match_dup 0))]
++  "ubicom32_match_cc_mode(insn, CCSZNmode)"
++  "ext.1\\t%1, %0")
++
++; Combine isn't very good at merging some types of operations so we
++; have to make do with a peephole.  It's not as effective but it's better
++; than doing nothing.
++;
++(define_peephole2
++  [(set (match_operand:QI 0 "nonimmediate_operand" "")
++      (match_operand:QI 1 "nonimmediate_operand" ""))
++   (set (match_operand 2 "ubicom32_cc_register_operand" "")
++      (match_operator 3 "ubicom32_compare_operator"
++        [(match_dup 0)
++         (const_int 0)]))]
++  "(GET_MODE (operands[2]) == CCSZNmode
++    || GET_MODE (operands[2]) == CCSZmode)"
++  [(parallel
++     [(set (match_dup 2)
++         (match_op_dup 3
++           [(match_dup 1)
++            (const_int 0)]))
++      (set (match_dup 0)
++         (match_dup 1))])]
++   "")
++
++; Combine isn't very good at merging some types of operations so we
++; have to make do with a peephole.  It's not as effective but it's better
++; than doing nothing.
++;
++(define_peephole2
++  [(set (match_operand:QI 0 "nonimmediate_operand" "")
++      (match_operand:QI 1 "nonimmediate_operand" ""))
++   (set (match_operand 2 "ubicom32_cc_register_operand" "")
++      (match_operator 3 "ubicom32_compare_operator"
++        [(match_dup 1)
++         (const_int 0)]))]
++  "(GET_MODE (operands[2]) == CCSZNmode
++    || GET_MODE (operands[2]) == CCSZmode)"
++  [(parallel
++     [(set (match_dup 2)
++         (match_op_dup 3
++           [(match_dup 1)
++            (const_int 0)]))
++      (set (match_dup 0)
++         (match_dup 1))])]
++   "")
++
++; 16-bit move with no change to the flags reg.
++;
++(define_insn "movhi"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
++      (match_operand:HI 1 "ubicom32_move_operand"  "g"))]
++  ""
++  "*
++   {
++     if (CONST_INT_P (operands[1]))
++       return \"movei\\t%0, %1\";
++
++     return \"move.2\\t%0, %1\";
++   }")
++
++; Combiner-generated 16-bit move with the zero flag set accordingly.
++;
++(define_insn "movhi_ccszn"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:HI 0 "nonimmediate_operand" "rm")
++               (const_int 0)))
++   (set (match_operand:HI 1 "nonimmediate_operand"       "=rm")
++      (match_dup 0))]
++  "ubicom32_match_cc_mode(insn, CCSZNmode)"
++  "ext.2\\t%1, %0")
++
++; Combine isn't very good at merging some types of operations so we
++; have to make do with a peephole.  It's not as effective but it's better
++; than doing nothing.
++;
++(define_peephole2
++  [(set (match_operand:HI 0 "nonimmediate_operand" "")
++      (match_operand:HI 1 "nonimmediate_operand" ""))
++   (set (match_operand 2 "ubicom32_cc_register_operand" "")
++      (match_operator 3 "ubicom32_compare_operator"
++        [(match_dup 0)
++         (const_int 0)]))]
++  "(GET_MODE (operands[2]) == CCSZNmode
++    || GET_MODE (operands[2]) == CCSZmode)"
++  [(parallel
++     [(set (match_dup 2)
++         (match_op_dup 3
++           [(match_dup 1)
++            (const_int 0)]))
++      (set (match_dup 0)
++         (match_dup 1))])]
++   "")
++
++; Combine isn't very good at merging some types of operations so we
++; have to make do with a peephole.  It's not as effective but it's better
++; than doing nothing.
++;
++(define_peephole2
++  [(set (match_operand:HI 0 "nonimmediate_operand" "")
++      (match_operand:HI 1 "nonimmediate_operand" ""))
++   (set (match_operand 2 "ubicom32_cc_register_operand" "")
++      (match_operator 3 "ubicom32_compare_operator"
++        [(match_dup 1)
++         (const_int 0)]))]
++  "(GET_MODE (operands[2]) == CCSZNmode
++    || GET_MODE (operands[2]) == CCSZmode)"
++  [(parallel
++     [(set (match_dup 2)
++         (match_op_dup 3
++           [(match_dup 1)
++            (const_int 0)]))
++      (set (match_dup 0)
++         (match_dup 1))])]
++   "")
++
++; 32-bit move with no change to the flags reg.
++;
++(define_expand "movsi"
++  [(set (match_operand:SI 0 "nonimmediate_operand" "")
++      (match_operand:SI 1 "general_operand" ""))]
++  ""
++  "{
++     /* Convert any complexities in operand 1 into something that can just
++        fall into the default expander code.  */
++     ubicom32_expand_movsi (operands);
++   }")
++
++(define_insn "movsi_high"
++  [(set (match_operand:SI 0 "ubicom32_address_register_operand"               "=a")
++      (high:SI (match_operand:SI 1 "ubicom32_symbolic_address_operand" "s")))]
++  ""
++  "moveai\\t%0, #%%hi(%E1)")
++
++(define_insn "movsi_lo_sum"
++  [(set (match_operand:SI 0 "nonimmediate_operand"                     "=rm")
++      (lo_sum:SI (match_operand:SI 1 "ubicom32_address_register_operand" "a")
++                   (match_operand:SI 2 "immediate_operand"               "s")))]
++  ""
++  "lea.1\\t%0, %%lo(%E2)(%1)")
++
++(define_insn "movsi_internal"
++  [(set (match_operand:SI 0 "nonimmediate_operand"   "=rm")
++      (match_operand:SI 1 "ubicom32_move_operand" "rmnY"))]
++  ""
++  "*
++   {
++     if (CONST_INT_P (operands[1]))
++       {
++         ubicom32_emit_move_const_int (operands[0], operands[1]);
++         return \"\";
++       }
++
++     if (GET_CODE (operands[1]) == CONST_DOUBLE)
++       {
++         HOST_WIDE_INT i = CONST_DOUBLE_LOW (operands[1]);
++
++         ubicom32_emit_move_const_int (operands[0], GEN_INT (i));
++         return \"\";
++       }
++
++     if (ubicom32_address_register_operand (operands[0], VOIDmode)
++       && register_operand (operands[1], VOIDmode))
++       {
++       if (ubicom32_address_register_operand (operands[1], VOIDmode))
++         return \"lea.1\\t%0, 0(%1)\";
++
++       /* Use movea here to utilize the hazard bypass in the >= v4 ISA.  */
++         if (ubicom32_v4)
++         return \"movea\\t%0, %1\";
++
++         return \"move.4\\t%0, %1\";
++       }
++
++     return \"move.4\\t%0, %1\";
++   }")
++
++; If we're not dependent on the state of the condition codes we can construct
++; constants of value 2^n by using a bset.
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "nonimmediate_operand" "")
++      (match_operand:SI 1 "const_int_operand" ""))]
++  "(exact_log2 (INTVAL (operands[1])) > 14
++    && peep2_regno_dead_p (0, CC_REGNO))"
++  [(parallel
++     [(set (match_dup 0)
++         (ior:SI (const_int 0)
++                 (match_dup 1)))
++      (clobber (reg:CC CC_REGNO))])]
++  "")
++
++; If we're not dependent on the state of the condition codes we can construct
++; constants of value ~(2^n) by using a bclr.
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "nonimmediate_operand" "")
++      (match_operand:SI 1 "const_int_operand" ""))]
++  "(exact_log2 (~INTVAL (operands[1])) > 14
++    && peep2_regno_dead_p (0, CC_REGNO))"
++  [(parallel
++     [(set (match_dup 0)
++         (and:SI (const_int -1)
++                 (match_dup 1)))
++      (clobber (reg:CC CC_REGNO))])]
++  "")
++
++; For 32-bit constants that have bits 0 through 24 and bit 31 set the same
++; we can use swapb.4!
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "nonimmediate_operand" "")
++      (match_operand:SI 1 "const_int_operand" ""))]
++  "(ubicom32_v4
++    && (INTVAL (operands[1]) & 0xffffffff) != 0xffffffff
++    && (INTVAL (operands[1]) & 0xffffffff) != 0
++    && ((INTVAL (operands[1]) & 0x80ffffff) == 0
++      || (INTVAL (operands[1]) & 0x80ffffff) == 0x80ffffff))"
++  [(set (match_dup 0)
++      (bswap:SI (match_dup 2)))]
++  "{
++     operands[2] = GEN_INT (INTVAL (operands[1]) >> 24);
++   }")
++
++; If this is a write of a constant to memory look to see if we can usefully
++; transform this into 2 smaller writes.
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "memory_operand" "")
++      (match_operand:SI 1 "const_int_operand" ""))]
++  "! satisfies_constraint_I (operands[1])
++   && ubicom32_legitimate_address_p (HImode, plus_constant (XEXP (operands[0], 0), 2), 1)"
++  [(set (match_dup 4) (match_dup 2))
++   (set (match_dup 5) (match_dup 3))]
++  "{
++     rtx low_hword_addr;
++
++     operands[2] = gen_highpart_mode (HImode, SImode, operands[1]);
++     operands[3] = gen_lowpart (HImode, operands[1]);
++
++     operands[4] = gen_rtx_MEM (HImode, XEXP (operands[0], 0));
++     MEM_COPY_ATTRIBUTES (operands[4], operands[0]);
++
++     low_hword_addr = plus_constant (XEXP (operands[0], 0), 2);
++     operands[5] = gen_rtx_MEM (HImode, low_hword_addr);
++     MEM_COPY_ATTRIBUTES (operands[5], operands[0]);
++   }")
++
++; If we're writing memory and we've not found a better way to do this then
++; try loading into a D register and then copying to memory.  This will
++; perform the fewest possible memory read/writes.
++;
++(define_peephole2
++  [(match_scratch:SI 2 "d")
++   (set (match_operand:SI 0 "memory_operand" "")
++      (match_operand:SI 1 "const_int_operand" ""))]
++  "! satisfies_constraint_I (operands[1])"
++  [(set (match_dup 2) (match_dup 1))
++   (set (match_dup 0) (match_dup 2))]
++  "")
++
++; If we're not dependent on the state of the condition codes we can construct
++; constants of value (2^n - 1) by using an lsr.4.
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "")
++      (match_operand:SI 1 "const_int_operand" ""))]
++  "(exact_log2 (INTVAL (operands[1]) + 1) > 14
++    && peep2_regno_dead_p (0, CC_REGNO))"
++  [(parallel
++     [(set (match_dup 0)
++         (lshiftrt:SI (const_int -1)
++                      (match_dup 2)))
++      (clobber (reg:CC CC_REGNO))])]
++  "{
++     operands[2] = GEN_INT (32 - exact_log2 (INTVAL (operands[1]) + 1));
++   }")
++
++; If we're not dependent on the state of the condition codes we can construct
++; constants of value (2^n - 1) by using an lsr.4.
++;
++(define_peephole2
++  [(match_scratch:SI 2 "d")
++   (set (match_operand:SI 0 "nonimmediate_operand" "")
++      (match_operand:SI 1 "const_int_operand" ""))]
++  "(exact_log2 (INTVAL (operands[1]) + 1) > 14
++    && peep2_regno_dead_p (0, CC_REGNO))"
++  [(parallel
++     [(set (match_dup 2)
++         (lshiftrt:SI (const_int -1)
++                      (match_dup 3)))
++      (clobber (reg:CC CC_REGNO))])
++   (set (match_dup 0)
++      (match_dup 2))]
++  "{
++     operands[3] = GEN_INT (32 - exact_log2 (INTVAL (operands[1]) + 1));
++   }")
++
++; If we're not dependent on the state of the condition codes we can construct
++; some other constants by using an lsl.4 to shift 7 bits left by some
++; constant.
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "")
++      (match_operand:SI 1 "const_int_operand" ""))]
++  "(ubicom32_shiftable_const_int (INTVAL (operands[1]))
++    && peep2_regno_dead_p (0, CC_REGNO))"
++  [(parallel
++     [(set (match_dup 0)
++         (ashift:SI (match_dup 2)
++                    (match_dup 3)))
++      (clobber (reg:CC CC_REGNO))])]
++  "{
++     int shift = ubicom32_shiftable_const_int (INTVAL (operands[1]));
++     operands[2] = GEN_INT (INTVAL (operands[1]) >> shift);
++     operands[3] = GEN_INT (shift);
++   }")
++
++; If we're not dependent on the state of the condition codes we can construct
++; some other constants by using an lsl.4 to shift 7 bits left by some
++; constant.
++;
++(define_peephole2
++  [(match_scratch:SI 2 "d")
++   (set (match_operand:SI 0 "nonimmediate_operand" "")
++      (match_operand:SI 1 "const_int_operand" ""))]
++  "(ubicom32_shiftable_const_int (INTVAL (operands[1]))
++    && peep2_regno_dead_p (0, CC_REGNO))"
++  [(parallel
++     [(set (match_dup 2)
++         (ashift:SI (match_dup 3)
++                    (match_dup 4)))
++      (clobber (reg:CC CC_REGNO))])
++   (set (match_dup 0)
++      (match_dup 2))]
++  "{
++     int shift = ubicom32_shiftable_const_int (INTVAL (operands[1]));
++     operands[3] = GEN_INT (INTVAL (operands[1]) >> shift);
++     operands[4] = GEN_INT (shift);
++   }")
++
++; For some 16-bit unsigned constants that have bit 15 set we can use
++; swapb.2!
++;
++; Note that the movsi code emits the same sequence but by using a peephole2
++; we split the pattern early enough to allow instruction scheduling to
++; occur.
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "register_operand" "")
++      (match_operand:SI 1 "const_int_operand" ""))]
++  "(ubicom32_v4
++    && (INTVAL (operands[1]) & 0xffff80ff) == 0x80ff)"
++  [(set (match_dup 0)
++      (zero_extend:SI (bswap:HI (match_dup 2))))]
++  "{
++     HOST_WIDE_INT i = INTVAL (operands[1]) >> 8;
++     if (i >= 0x80)
++       i -= 0x100;
++     operands[2] = GEN_INT (i);
++   }")
++
++; In general for a 16-bit unsigned constant that has bit 15 set
++; then we need a movei/move.2 pair unless we can represent it
++; via just a move.2.
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "register_operand" "")
++      (match_operand:SI 1 "const_int_operand" ""))]
++  "(INTVAL (operands[1]) & 0xffff8000) == 0x8000
++    && (INTVAL (operands[1]) & 0xffff) < 0xff80"
++  [(set (match_dup 2)
++      (match_dup 1))
++   (set (match_dup 0)
++      (zero_extend:SI (match_dup 2)))]
++  "{
++     operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));
++   }")
++
++; If we're not dependent on the state of the condition codes we can construct
++; 32-bit constants that have bits 16 through 31 set to arbitrary values
++; and have bits 0 through 15 set to something representable as a default
++; source-1 immediate - we use movei/shmrg.2
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "")
++      (match_operand:SI 1 "const_int_operand" ""))]
++  "(((INTVAL (operands[1]) >= 0x8000
++      && INTVAL (operands[1]) < 0xff80)
++     || INTVAL (operands[1]) >= 0x10000
++     || INTVAL (operands[1]) < -0x8000)
++    && ((INTVAL (operands[1]) & 0xffff) >= 0xff80
++      || (INTVAL (operands[1]) & 0xffff) < 0x80)
++    && peep2_regno_dead_p (0, CC_REGNO))"
++  [(set (match_dup 0)
++      (match_dup 2))
++   (parallel
++     [(set (match_dup 0)
++         (ior:SI
++           (ashift:SI (match_dup 0)
++                      (const_int 16))
++           (zero_extend:SI
++             (match_dup 3))))
++      (clobber (reg:CC CC_REGNO))])]
++  "{
++     operands[2] = gen_highpart_mode (HImode, SImode, operands[1]);
++     operands[3] = gen_lowpart (HImode, operands[1]);
++   }")
++
++; Exactly the same as the peephole2 preceding except that this targets a
++; general register instead of D register.  Hopefully the later optimization
++; passes will notice that the value ended up in a D register first here
++; and eliminate away the other register!
++;
++(define_peephole2
++  [(match_scratch:SI 2 "d")
++   (set (match_operand:SI 0 "register_operand" "")
++      (match_operand:SI 1 "const_int_operand" ""))]
++  "(((INTVAL (operands[1]) >= 0x8000
++      && INTVAL (operands[1]) < 0xff80)
++     || INTVAL (operands[1]) >= 0x10000
++     || INTVAL (operands[1]) < -0x8000)
++    && ((INTVAL (operands[1]) & 0xffff) >= 0xff80
++      || (INTVAL (operands[1]) & 0xffff) < 0x80)
++    && peep2_regno_dead_p (0, CC_REGNO))"
++  [(set (match_dup 2)
++      (match_dup 3))
++   (parallel
++     [(set (match_dup 2)
++         (ior:SI
++           (ashift:SI (match_dup 2)
++                      (const_int 16))
++           (zero_extend:SI
++             (match_dup 4))))
++      (clobber (reg:CC CC_REGNO))])
++   (set (match_dup 0)
++      (match_dup 2))]
++  "{
++     operands[3] = gen_highpart_mode (HImode, SImode, operands[1]);
++     operands[4] = gen_lowpart (HImode, operands[1]);
++   }")
++
++; If we have a load of a large integer constant which does not have bit 31
++; set and we have a spare A reg then construct it with a moveai/lea.1 pair
++; instead.  This avoids constructing it in 3 instructions on the stack.
++;
++; Note that we have to be careful not to match anything that matches
++; something we can do in a single instruction!  There aren't many such
++; constants but there are some.
++;
++(define_peephole2
++  [(match_scratch:SI 2 "a")
++   (set (match_operand:SI 0 "register_operand" "")
++      (match_operand:SI 1 "const_int_operand" ""))]
++  "(! (INTVAL (operands[1]) & 0x80000000)
++    && ((INTVAL (operands[1]) >= 0x8000
++       && INTVAL (operands[1]) < 0xff80)
++      || INTVAL (operands[1]) >= 0x10000))"
++  [(set (match_dup 2)
++      (match_dup 3))
++   (set (match_dup 0)
++      (plus:SI (match_dup 2)
++               (match_dup 4)))]
++  "{
++     HOST_WIDE_INT i = INTVAL (operands[1]);
++     operands[3] = GEN_INT (i & 0xffffff80);
++     operands[4] = GEN_INT (i & 0x7f);
++   }")
++
++; If we're not dependent on the state of the condition codes we can construct
++; a 32-bit constant with a movei/movei/shmrg.2 sequence if possible.
++;
++(define_peephole2
++  [(match_scratch:HI 2 "d")
++   (set (match_operand:SI 0 "ubicom32_data_register_operand" "")
++      (match_operand:SI 1 "const_int_operand" ""))
++   (match_dup 2)]
++  "(INTVAL (operands[1]) & 0x80000000
++    && INTVAL (operands[1]) < -0x8000
++    && peep2_regno_dead_p (0, CC_REGNO))"
++  [(set (match_dup 0)
++      (match_dup 3))
++   (set (match_dup 2)
++      (match_dup 4))
++   (parallel
++     [(set (match_dup 0)
++         (ior:SI
++           (ashift:SI (match_dup 0)
++                      (const_int 16))
++           (zero_extend:SI
++             (match_dup 2))))
++      (clobber (reg:CC CC_REGNO))])]
++  "{
++     operands[3] = gen_highpart_mode (HImode, SImode, operands[1]);
++     operands[4] = gen_lowpart (HImode, operands[1]);
++   }")
++
++; Exactly the same as the peephole2 preceding except that this targets a
++; general register instead of D register.  Hopefully the later optimization
++; passes will notice that the value ended up in a D register first here
++; and eliminate away the other register!
++;
++(define_peephole2
++  [(match_scratch:SI 2 "d")
++   (match_scratch:HI 3 "d")
++   (set (match_operand:SI 0 "register_operand" "")
++      (match_operand:SI 1 "const_int_operand" ""))
++   (match_dup 3)]
++  "(INTVAL (operands[1]) & 0x80000000
++    && INTVAL (operands[1]) < -0x8000
++    && peep2_regno_dead_p (0, CC_REGNO))"
++  [(set (match_dup 2)
++      (match_dup 4))
++   (set (match_dup 3)
++      (match_dup 5))
++   (parallel
++     [(set (match_dup 2)
++         (ior:SI
++           (ashift:SI (match_dup 2)
++                      (const_int 16))
++           (zero_extend:SI
++             (match_dup 3))))
++      (clobber (reg:CC CC_REGNO))])
++   (set (match_dup 0)
++      (match_dup 2))]
++  "{
++     operands[4] = gen_highpart_mode (HImode, SImode, operands[1]);
++     operands[5] = gen_lowpart (HImode, operands[1]);
++   }")
++
++(define_insn "movsi_fdpic_got_offset"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
++      (match_operand:SI 1 "ubicom32_fdpic_got_offset_operand" "Y"))]
++  ""
++  "movei\\t%0, %1")
++
++; The explicit MEM inside the UNSPEC prevents the compiler from moving
++; the load before a branch after a NULL test, or before a store that
++; initializes a function descriptor.
++
++(define_insn_and_split "load_fdpic_funcdesc"
++  [(set (match_operand:SI 0 "ubicom32_address_register_operand" "=a")
++      (unspec_volatile:SI [(mem:SI (match_operand:SI 1 "address_operand" "p"))]
++                           UNSPEC_VOLATILE_LOAD_FDPIC_FUNCDESC))]
++  ""
++  "#"
++  "reload_completed"
++  [(set (match_dup 0)
++      (mem:SI (match_dup 1)))])
++
++; Combiner-generated 32-bit move with the zero flag set accordingly.
++;
++(define_insn "movsi_ccwzn"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:SI 0 "nonimmediate_operand" "rm, d")
++               (const_int 0)))
++   (set (match_operand:SI 1 "nonimmediate_operand"        "=d,rm")
++      (match_dup 0))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "@
++   lsl.4\\t%1, %0, #0
++   add.4\\t%1, #0, %0")
++
++; Combiner-generated 32-bit move with all flags set accordingly.
++;
++(define_insn "movsi_ccw"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:SI 0 "ubicom32_data_register_operand" "d")
++               (const_int 0)))
++   (set (match_operand:SI 1 "nonimmediate_operand"                "=rm")
++      (match_dup 0))]
++  "ubicom32_match_cc_mode(insn, CCWmode)"
++  "add.4\\t%1, #0, %0")
++
++; Combine isn't very good at merging some types of operations so we
++; have to make do with a peephole.  It's not as effective but it's better
++; than doing nothing.
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "")
++      (match_operand:SI 1 "nonimmediate_operand" ""))
++   (parallel
++     [(set (match_operand 2 "ubicom32_cc_register_operand" "")
++         (match_operator 3 "ubicom32_compare_operator"
++           [(match_dup 0)
++            (const_int 0)]))
++      (clobber (match_operand:SI 4 "ubicom32_data_register_operand" ""))])]
++  "(GET_MODE (operands[2]) == CCWZNmode
++    || GET_MODE (operands[2]) == CCWZmode)"
++  [(parallel
++     [(set (match_dup 2)
++         (match_op_dup 3
++           [(match_dup 1)
++            (const_int 0)]))
++      (set (match_dup 0)
++         (match_dup 1))])]
++   "")
++
++; Combine isn't very good at merging some types of operations so we
++; have to make do with a peephole.  It's not as effective but it's better
++; than doing nothing.
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "nonimmediate_operand" "")
++      (match_operand:SI 1 "ubicom32_data_register_operand" ""))
++   (parallel
++     [(set (match_operand 2 "ubicom32_cc_register_operand" "")
++         (match_operator 3 "ubicom32_compare_operator"
++           [(match_dup 1)
++            (const_int 0)]))
++      (clobber (match_operand:SI 4 "ubicom32_data_register_operand" ""))])]
++  "(GET_MODE (operands[2]) == CCWZNmode
++    || GET_MODE (operands[2]) == CCWZmode)"
++  [(parallel
++     [(set (match_dup 2)
++         (match_op_dup 3
++           [(match_dup 1)
++            (const_int 0)]))
++      (set (match_dup 0)
++         (match_dup 1))])]
++   "")
++
++; Combine isn't very good at merging some types of operations so we
++; have to make do with a peephole.  It's not as effective but it's better
++; than doing nothing.
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "register_operand" "")
++      (match_operand:SI 1 "nonimmediate_operand" ""))
++   (parallel
++     [(set (match_operand 2 "ubicom32_cc_register_operand" "")
++         (match_operator 3 "ubicom32_compare_operator"
++           [(match_dup 0)
++            (const_int 0)]))
++      (set (match_operand:SI 4 "ubicom32_data_register_operand" "")
++         (match_dup 0))])]
++  "(peep2_reg_dead_p (2, operands[0])
++    && (GET_MODE (operands[2]) == CCWZNmode
++      || GET_MODE (operands[2]) == CCWZmode))"
++  [(parallel
++     [(set (match_dup 2)
++         (match_op_dup 3
++           [(match_dup 1)
++            (const_int 0)]))
++      (set (match_dup 4)
++         (match_dup 1))])]
++   "")
++
++; Register renaming may make a general reg into a D reg in which case
++; we may be able to simplify a compare.
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "register_operand" "")
++      (match_operand:SI 1 "nonimmediate_operand" ""))
++   (parallel
++     [(set (match_operand 2 "ubicom32_cc_register_operand" "")
++         (match_operator 3 "ubicom32_compare_operator"
++           [(match_dup 0)
++            (const_int 0)]))
++      (clobber (match_operand:SI 4 "ubicom32_data_register_operand" ""))])]
++  "(peep2_reg_dead_p (2, operands[0])
++    && (GET_MODE (operands[2]) == CCWZNmode
++      || GET_MODE (operands[2]) == CCWZmode))"
++  [(parallel
++     [(set (match_dup 2)
++         (match_op_dup 3
++           [(match_dup 1)
++            (const_int 0)]))
++      (clobber (match_dup 4))])]
++   "")
++
++(define_insn_and_split "movdi"
++  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
++      (match_operand:DI 1 "general_operand"     "rmi,ri"))]
++  ""
++  "#"
++  "reload_completed"
++  [(set (match_dup 2) (match_dup 3))
++   (set (match_dup 4) (match_dup 5))]
++  "{
++     rtx dest_low;
++     rtx src_low;
++
++     dest_low = gen_lowpart (SImode, operands[0]);
++     src_low = gen_lowpart (SImode, operands[1]);
++
++     if (REG_P (operands[0])
++       && REG_P (operands[1])
++       && REGNO (operands[0]) < REGNO (operands[1]))
++       {
++       operands[2] = gen_highpart (SImode, operands[0]);
++       operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
++       operands[4] = dest_low;
++       operands[5] = src_low;
++       }
++     else if (reg_mentioned_p (dest_low, src_low))
++       {
++       operands[2] = gen_highpart (SImode, operands[0]);
++       operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
++       operands[4] = dest_low;
++       operands[5] = src_low;
++       }
++     else
++       {
++       operands[2] = dest_low;
++       operands[3] = src_low;
++       operands[4] = gen_highpart (SImode, operands[0]);
++       operands[5] = gen_highpart_mode (SImode, DImode, operands[1]);
++       }
++   }"
++  [(set_attr "length" "8")])
++
++; Combiner-generated 64-bit move with all flags set accordingly.
++;
++(define_insn "movdi_ccwzn"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:DI 0 "nonimmediate_operand" "d, m,   r")
++               (const_int 0)))
++   (set (match_operand:DI 1 "nonimmediate_operand"     "=&rm,rm,!&rm")
++      (match_dup 0))
++   (clobber (match_scratch:SI 2                                  "=X, d,   d"))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "*
++   {
++     operands[3] = gen_lowpart (SImode, operands[0]);
++     operands[4] = gen_lowpart (SImode, operands[1]);
++     operands[5] = gen_highpart (SImode, operands[0]);
++     operands[6] = gen_highpart (SImode, operands[1]);
++
++     if (ubicom32_data_register_operand (operands[0], VOIDmode))
++       return \"add.4\\t%4, #0, %3\;addc\\t%6, #0, %5\";
++
++     return \"movei\\t%2, #0\;add.4\\t%4, %3, %2\;addc\\t%6, %5, %2\";
++   }"
++  [(set_attr "length" "8")])
++
++(define_insn "movdi_ccw"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:DI 0 "nonimmediate_operand" "d, m,   r")
++               (const_int 0)))
++   (set (match_operand:DI 1 "nonimmediate_operand"     "=&rm,rm,!&rm")
++      (match_dup 0))
++   (clobber (match_scratch:SI 2                                  "=X, d,   d"))]
++  "ubicom32_match_cc_mode(insn, CCWmode)"
++  "*
++   {
++     operands[3] = gen_lowpart (SImode, operands[0]);
++     operands[4] = gen_lowpart (SImode, operands[1]);
++     operands[5] = gen_highpart (SImode, operands[0]);
++     operands[6] = gen_highpart (SImode, operands[1]);
++
++     if (ubicom32_data_register_operand (operands[0], VOIDmode))
++       return \"add.4\\t%4, #0, %3\;addc\\t%6, #0, %5\";
++
++     return \"movei\\t%2, #0\;add.4\\t%4, %3, %2\;addc\\t%6, %5, %2\";
++   }"
++  [(set_attr "length" "8")])
++
++(define_insn "movsf"
++  [(set (match_operand:SF 0 "nonimmediate_operand"  "=!d,*rm")
++      (match_operand:SF 1 "ubicom32_move_operand" "rmF,rmF"))]
++  ""
++  "*
++   {
++     if (GET_CODE (operands[1]) == CONST_DOUBLE)
++       {
++       HOST_WIDE_INT val;
++       REAL_VALUE_TYPE rv;
++
++       REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
++       REAL_VALUE_TO_TARGET_SINGLE (rv, val);
++
++       ubicom32_emit_move_const_int (operands[0], GEN_INT (val));
++       return \"\";
++       }
++
++     return \"move.4\\t%0, %1\";
++   }")
++
++(define_insn "zero_extendqihi2"
++  [(set (match_operand:HI 0 "register_operand"                           "=r")
++      (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
++  ""
++  "move.1\\t%0, %1")
++
++(define_insn "zero_extendqisi2"
++  [(set (match_operand:SI 0 "register_operand"                           "=r")
++      (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
++  ""
++  "move.1\\t%0, %1")
++
++(define_insn "zero_extendqisi2_ccwz_1"
++  [(set (reg CC_REGNO)
++      (compare
++        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm"))
++          (const_int 0)))
++   (set (match_operand:SI 0 "ubicom32_data_register_operand"       "=d")
++      (zero_extend:SI (match_dup 1)))]
++  "ubicom32_match_cc_mode(insn, CCWZmode)"
++  "shmrg.1\\t%0, %1, #0")
++
++(define_insn "zero_extendhisi2"
++  [(set (match_operand:SI 0 "register_operand"                           "=r")
++      (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
++  ""
++  "move.2\\t%0, %1")
++
++(define_insn "zero_extendhisi2_ccwz_1"
++  [(set (reg CC_REGNO)
++      (compare
++        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm"))
++          (const_int 0)))
++   (set (match_operand:SI 0 "ubicom32_data_register_operand"       "=d")
++      (zero_extend:SI (match_dup 1)))]
++  "ubicom32_match_cc_mode(insn, CCWZmode)"
++  "shmrg.2\\t%0, %1, #0")
++
++(define_insn_and_split "zero_extendqidi2"
++  [(set (match_operand:DI 0 "register_operand"                           "=r")
++      (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
++  ""
++  "#"
++  "reload_completed"
++  [(set (match_dup 2)
++      (zero_extend:SI (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" "8")])
++
++(define_insn_and_split "zero_extendhidi2"
++  [(set (match_operand:DI 0 "register_operand"                           "=r")
++      (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
++  ""
++  "#"
++  "reload_completed"
++  [(set (match_dup 2)
++      (zero_extend:SI (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" "8")])
++
++(define_insn_and_split "zero_extendsidi2"
++  [(set (match_operand:DI 0 "nonimmediate_operand"              "=rm")
++      (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm")))]
++  ""
++  "#"
++  "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" "8")])
++
++(define_insn "extendqihi2"
++  [(set (match_operand:HI 0 "register_operand"                           "=r")
++      (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "ext.1\\t%0, %1")
++
++(define_insn "extendqisi2"
++  [(set (match_operand:SI 0 "register_operand"                           "=r")
++      (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "ext.1\\t%0, %1")
++
++(define_insn "extendhisi2"
++  [(set (match_operand:SI 0 "register_operand"                           "=r")
++      (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "ext.2\\t%0, %1")
++
++(define_insn_and_split "extendsidi2"
++  [(set (match_operand:DI 0 "nonimmediate_operand"               "=d")
++      (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "#"
++  "reload_completed"
++  [(set (match_dup 2)
++      (match_dup 1))
++   (parallel
++     [(set (match_dup 3)
++         (ashiftrt:SI (match_dup 2)
++                      (const_int 31)))
++      (clobber (reg:CC CC_REGNO))])]
++  "{
++     operands[2] = gen_lowpart (SImode, operands[0]);
++     operands[3] = gen_highpart (SImode, operands[0]);
++   }"
++  [(set_attr "length" "8")])
++
++(define_insn "bswaphi"
++  [(set (match_operand:HI 0 "nonimmediate_operand"           "=rm")
++      (bswap:HI (match_operand:HI 1 "ubicom32_arith_operand" "rmI")))]
++  "(ubicom32_v4)"
++  "swapb.2\\t%0, %1");
++
++(define_insn "bswaphisi"
++  [(set (match_operand:SI 0 "register_operand"                          "=r")
++      (zero_extend:SI
++        (bswap:HI (match_operand:HI 1 "ubicom32_arith_operand" "rmI"))))]
++  "(ubicom32_v4)"
++  "swapb.2\\t%0, %1");
++
++(define_insn "bswapsi"
++  [(set (match_operand:SI 0 "nonimmediate_operand"           "=rm")
++      (bswap:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")))]
++  "(ubicom32_v4)"
++  "swapb.4\\t%0, %1");
++
++(define_insn "tstqi_ext1"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:QI 0 "nonimmediate_operand" "rm")
++               (const_int 0)))]
++  "ubicom32_match_cc_mode(insn, CCSZNmode)"
++  "ext.1\\t#0, %0")
++
++(define_expand "cmpqi"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:QI 0 "ubicom32_arith_operand" "")
++               (match_operand:QI 1 "ubicom32_data_register_operand" "")))]
++  "(ubicom32_v4)"
++  "{
++     ubicom32_compare_op0 = operands[0];
++     ubicom32_compare_op1 = operands[1];
++     DONE;
++   }")
++
++(define_insn "sub1_ccs"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:QI 0 "ubicom32_arith_operand"       "rmI")
++               (match_operand:QI 1 "ubicom32_data_register_operand" "d")))]
++  "(ubicom32_v4)"
++  "sub.1\\t#0, %0, %1")
++
++; If we're testing for equality we don't have to worry about reversing conditions.
++;
++(define_insn "sub1_ccsz_1"
++  [(set (reg:CCSZ CC_REGNO)
++      (compare:CCSZ (match_operand:QI 0 "nonimmediate_operand"          "rm")
++                    (match_operand:QI 1 "ubicom32_data_register_operand" "d")))]
++  "(ubicom32_v4)"
++  "sub.1\\t#0, %0, %1")
++
++(define_insn "sub1_ccsz_2"
++  [(set (reg:CCSZ CC_REGNO)
++      (compare:CCSZ (match_operand:QI 0 "ubicom32_data_register_operand" "d")
++                    (match_operand:QI 1 "ubicom32_arith_operand"       "rmI")))]
++  "(ubicom32_v4)"
++  "sub.1\\t#0, %1, %0")
++
++; When the combiner runs it doesn't have any insight into whether or not an argument
++; to a compare is spilled to the stack and therefore can't swap the comparison in
++; an attempt to use sub.1 more effectively.  We peephole this case here.
++;
++(define_peephole2
++  [(set (match_operand:QI 0 "register_operand" "")
++      (match_operand:QI 1 "ubicom32_arith_operand" ""))
++   (set (match_operand 2 "ubicom32_cc_register_operand" "")
++      (compare (match_operand:QI 3 "ubicom32_data_register_operand" "")
++               (match_dup 0)))
++   (set (pc)
++      (if_then_else (match_operator 4 "comparison_operator"
++                      [(match_dup 2)
++                       (const_int 0)])
++                    (label_ref (match_operand 5 "" ""))
++                    (pc)))]
++  "(peep2_reg_dead_p (2, operands[0])
++    && peep2_regno_dead_p (3, CC_REGNO))"
++  [(set (match_dup 2)
++      (compare (match_dup 1)
++               (match_dup 3)))
++   (set (pc)
++      (if_then_else (match_op_dup 6
++                      [(match_dup 2)
++                       (const_int 0)])
++                    (label_ref (match_dup 5))
++                    (pc)))]
++  "{
++     rtx cc_reg;
++
++     cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
++     operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])),
++                                 GET_MODE (operands[4]),
++                                 cc_reg,
++                                 const0_rtx);
++   }")
++
++(define_insn "tsthi_ext2"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:HI 0 "nonimmediate_operand" "rm")
++               (const_int 0)))]
++  "ubicom32_match_cc_mode(insn, CCSZNmode)"
++  "ext.2\\t#0, %0")
++
++(define_expand "cmphi"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:HI 0 "ubicom32_arith_operand" "")
++               (match_operand:HI 1 "ubicom32_compare_operand" "")))]
++  ""
++  "{
++     do
++       {
++       /* Is this a cmpi? */
++       if (CONST_INT_P (operands[1]))
++         break;
++
++       /* Must be a sub.2 - if necessary copy an operand into a reg.  */
++       if (! ubicom32_data_register_operand (operands[1], HImode))
++         operands[1] = copy_to_mode_reg (HImode, operands[1]);
++       }
++     while (0);
++
++     ubicom32_compare_op0 = operands[0];
++     ubicom32_compare_op1 = operands[1];
++     DONE;
++   }")
++
++(define_insn "cmpi"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:HI 0 "nonimmediate_operand" "rm")
++               (match_operand 1 "const_int_operand"        "N")))]
++  ""
++  "cmpi\\t%0, %1")
++
++(define_insn "sub2_ccs"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:HI 0 "ubicom32_arith_operand"       "rmI")
++               (match_operand:HI 1 "ubicom32_data_register_operand" "d")))]
++  ""
++  "sub.2\\t#0, %0, %1")
++
++; If we're testing for equality we don't have to worry about reversing conditions.
++;
++(define_insn "sub2_ccsz_1"
++  [(set (reg:CCSZ CC_REGNO)
++      (compare:CCSZ (match_operand:HI 0 "nonimmediate_operand"          "rm")
++                    (match_operand:HI 1 "ubicom32_data_register_operand" "d")))]
++  ""
++  "sub.2\\t#0, %0, %1")
++
++(define_insn "sub2_ccsz_2"
++  [(set (reg:CCSZ CC_REGNO)
++      (compare:CCSZ (match_operand:HI 0 "ubicom32_data_register_operand" "d")
++                    (match_operand:HI 1 "ubicom32_arith_operand"       "rmI")))]
++  ""
++  "sub.2\\t#0, %1, %0")
++
++; When the combiner runs it doesn't have any insight into whether or not an argument
++; to a compare is spilled to the stack and therefore can't swap the comparison in
++; an attempt to use sub.2 more effectively.  We peephole this case here.
++;
++(define_peephole2
++  [(set (match_operand:HI 0 "register_operand" "")
++      (match_operand:HI 1 "ubicom32_arith_operand" ""))
++   (set (match_operand 2 "ubicom32_cc_register_operand" "")
++      (compare (match_operand:HI 3 "ubicom32_data_register_operand" "")
++               (match_dup 0)))
++   (set (pc)
++      (if_then_else (match_operator 4 "comparison_operator"
++                      [(match_dup 2)
++                       (const_int 0)])
++                    (label_ref (match_operand 5 "" ""))
++                    (pc)))]
++  "(peep2_reg_dead_p (2, operands[0])
++    && peep2_regno_dead_p (3, CC_REGNO))"
++  [(set (match_dup 2)
++      (compare (match_dup 1)
++               (match_dup 3)))
++   (set (pc)
++      (if_then_else (match_op_dup 6
++                      [(match_dup 2)
++                       (const_int 0)])
++                    (label_ref (match_dup 5))
++                    (pc)))]
++  "{
++     rtx cc_reg;
++
++     cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
++     operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])),
++                                 GET_MODE (operands[4]),
++                                 cc_reg,
++                                 const0_rtx);
++   }")
++
++(define_insn_and_split "tstsi_lsl4"
++  [(set (match_operand 0 "ubicom32_cc_register_operand" "=r")
++      (match_operator 1 "ubicom32_compare_operator"
++        [(match_operand:SI 2 "nonimmediate_operand"   "rm")
++         (const_int 0)]))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "#"
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  [(parallel
++     [(set (match_dup 0)
++         (match_op_dup 1
++           [(match_dup 2)
++            (const_int 0)]))
++      (clobber (match_dup 3))])]
++  "{
++     operands[3] = gen_reg_rtx (SImode);
++   }")
++
++(define_insn "tstsi_lsl4_d"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:SI 0 "nonimmediate_operand" "rm")
++               (const_int 0)))
++   (clobber (match_operand:SI 1 "ubicom32_data_register_operand" "=d"))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "lsl.4\\t%1, %0, #0")
++
++; Comparison for equality with -1.
++;
++(define_insn "cmpsi_not4_ccwz"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:SI 0 "nonimmediate_operand" "rm")
++               (const_int -1)))]
++  "ubicom32_match_cc_mode(insn, CCWZmode)"
++  "not.4\\t#0, %0")
++
++(define_expand "cmpsi"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:SI 0 "ubicom32_arith_operand" "")
++               (match_operand:SI 1 "ubicom32_compare_operand" "")))]
++  ""
++  "{
++     do
++       {
++       /* Is this a cmpi?  We can't take a memory address as cmpi takes
++            16-bit operands.  */
++       if (register_operand (operands[0], SImode)
++           && CONST_INT_P (operands[1])
++           && satisfies_constraint_N (operands[1]))
++         break;
++
++       /* Must be a sub.4 - if necessary copy an operand into a reg.  */
++       if (! ubicom32_data_register_operand (operands[1], SImode))
++         operands[1] = copy_to_mode_reg (SImode, operands[1]);
++       }
++     while (0);
++
++     ubicom32_compare_op0 = operands[0];
++     ubicom32_compare_op1 = operands[1];
++     DONE;
++   }")
++
++(define_insn "cmpsi_cmpi"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:SI 0 "register_operand" "r")
++               (match_operand 1 "const_int_operand"   "N")))]
++  "(satisfies_constraint_N (operands[1]))"
++  "cmpi\\t%0, %1")
++
++(define_insn "cmpsi_sub4"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:SI 0 "ubicom32_arith_operand"       "rmI")
++               (match_operand:SI 1 "ubicom32_data_register_operand" "d")))]
++  ""
++  "sub.4\\t#0, %0, %1")
++
++; If we're testing for equality we don't have to worry about reversing conditions.
++;
++(define_insn "cmpsi_sub4_ccwz_1"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:SI 0 "nonimmediate_operand"          "rm")
++               (match_operand:SI 1 "ubicom32_data_register_operand" "d")))]
++  "ubicom32_match_cc_mode(insn, CCWZmode)"
++  "sub.4\\t#0, %0, %1")
++
++(define_insn "cmpsi_sub4_ccwz_2"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:SI 0 "ubicom32_data_register_operand" "d")
++               (match_operand:SI 1 "nonimmediate_operand"          "rm")))]
++  "ubicom32_match_cc_mode(insn, CCWZmode)"
++  "sub.4\\t#0, %1, %0")
++
++; When the combiner runs it doesn't have any insight into whether or not an argument
++; to a compare is spilled to the stack and therefore can't swap the comparison in
++; an attempt to use sub.4 more effectively.  We peephole this case here.
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "register_operand" "")
++      (match_operand:SI 1 "ubicom32_arith_operand" ""))
++   (set (match_operand 2 "ubicom32_cc_register_operand" "")
++      (compare (match_operand:SI 3 "ubicom32_data_register_operand" "")
++               (match_dup 0)))
++   (set (pc)
++      (if_then_else (match_operator 4 "comparison_operator"
++                      [(match_dup 2)
++                       (const_int 0)])
++                    (label_ref (match_operand 5 "" ""))
++                    (pc)))]
++  "(peep2_reg_dead_p (2, operands[0])
++    && peep2_regno_dead_p (3, CC_REGNO))"
++  [(set (match_dup 2)
++      (compare (match_dup 1)
++               (match_dup 3)))
++   (set (pc)
++      (if_then_else (match_op_dup 6
++                      [(match_dup 2)
++                       (const_int 0)])
++                    (label_ref (match_dup 5))
++                    (pc)))]
++  "{
++     rtx cc_reg;
++
++     cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
++     operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])),
++                                 GET_MODE (operands[4]),
++                                 cc_reg,
++                                 const0_rtx);
++   }")
++
++(define_insn_and_split "tstdi_or4"
++  [(set (reg:CCWZ CC_REGNO)
++      (compare:CCWZ (match_operand:DI 0 "nonimmediate_operand" "rm")
++                    (const_int 0)))]
++  ""
++  "#"
++  ""
++  [(parallel
++     [(set (reg:CCWZ CC_REGNO)
++         (compare:CCWZ (match_dup 0)
++                       (const_int 0)))
++      (clobber (match_dup 1))])]
++  "{
++     operands[1] = gen_reg_rtx (SImode);
++   }")
++
++(define_insn "tstdi_or4_d"
++  [(set (reg:CCWZ CC_REGNO)
++      (compare:CCWZ (match_operand:DI 0 "nonimmediate_operand" "rm")
++                    (const_int 0)))
++   (clobber (match_operand:SI 1 "ubicom32_data_register_operand" "=d"))]
++  ""
++  "*
++   {
++     operands[2] = gen_lowpart (SImode, operands[0]);
++     operands[3] = gen_highpart_mode (SImode, DImode, operands[0]);
++
++     if (ubicom32_data_register_operand (operands[0], GET_MODE (operands[0])))
++       return \"or.4\\t#0, %2, %3\";
++
++     return \"move.4\\t%1, %2\;or.4\\t%1, %3, %1\";
++   }"
++  [(set_attr "length" "8")])
++
++(define_expand "cmpdi"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:DI 0 "ubicom32_arith_operand" "")
++               (match_operand:DI 1 "ubicom32_data_register_operand" "")))]
++  ""
++  "{
++     ubicom32_compare_op0 = operands[0];
++     ubicom32_compare_op1 = operands[1];
++     DONE;
++   }")
++
++(define_insn "cmpdi_sub4subc"
++  [(set (reg CC_REGNO)
++      (compare (match_operand:DI 0 "ubicom32_arith_operand"       "rmI")
++               (match_operand:DI 1 "ubicom32_data_register_operand" "d")))]
++  ""
++  "*
++   {
++     operands[2] = gen_lowpart (SImode, operands[0]);
++     operands[3] = gen_lowpart (SImode, operands[1]);
++     operands[4] = gen_highpart_mode (SImode, DImode, operands[0]);
++     operands[5] = gen_highpart_mode (SImode, DImode, operands[1]);
++
++     return \"sub.4\\t#0, %2, %3\;subc\\t#0, %4, %5\";
++   }"
++  [(set_attr "length" "8")])
++
++; When the combiner runs it doesn't have any insight into whether or not an argument
++; to a compare is spilled to the stack and therefore can't swap the comparison in
++; an attempt to use sub.4/subc more effectively.  We peephole this case here.
++;
++(define_peephole2
++  [(set (match_operand:DI 0 "register_operand" "")
++      (match_operand:DI 1 "ubicom32_arith_operand" ""))
++   (set (match_operand 2 "ubicom32_cc_register_operand" "")
++      (compare (match_operand:DI 3 "ubicom32_data_register_operand" "")
++               (match_dup 0)))
++   (set (pc)
++      (if_then_else (match_operator 4 "comparison_operator"
++                      [(match_dup 2)
++                       (const_int 0)])
++                    (label_ref (match_operand 5 "" ""))
++                    (pc)))]
++  "(peep2_reg_dead_p (2, operands[0])
++    && peep2_regno_dead_p (3, CC_REGNO))"
++  [(set (match_dup 2)
++      (compare (match_dup 1)
++               (match_dup 3)))
++   (set (pc)
++      (if_then_else (match_op_dup 6
++                      [(match_dup 2)
++                       (const_int 0)])
++                    (label_ref (match_dup 5))
++                    (pc)))]
++  "{
++     rtx cc_reg;
++
++     cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
++     operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])),
++                                 GET_MODE (operands[4]),
++                                 cc_reg,
++                                 const0_rtx);
++   }")
++
++(define_insn "btst"
++  [(set (reg:CCWZ CC_REGNO)
++      (compare:CCWZ
++        (zero_extract:SI
++          (match_operand:SI 0 "nonimmediate_operand"   "rm")
++          (const_int 1)
++          (match_operand:SI 1 "ubicom32_arith_operand" "dM"))
++        (const_int 0)))]
++  ""
++  "btst\\t%0, %1")
++
++(define_insn "bfextu_ccwz_null"
++  [(set (reg:CCWZ CC_REGNO)
++      (compare:CCWZ
++        (zero_extract:SI
++          (match_operand:SI 0 "nonimmediate_operand" "rm")
++          (match_operand 1 "const_int_operand"        "M")
++          (const_int 0))
++        (const_int 0)))
++   (clobber (match_scratch:SI 2                              "=d"))]
++  ""
++  "bfextu\\t%2, %0, %1")
++
++(define_expand "addqi3"
++  [(parallel
++     [(set (match_operand:QI 0 "memory_operand" "")
++         (plus:QI (match_operand:QI 1 "nonimmediate_operand" "")
++                  (match_operand:QI 2 "ubicom32_arith_operand" "")))
++      (clobber (reg:CC CC_REGNO))])]
++  "(ubicom32_v4)"
++  "{
++     if (!memory_operand (operands[0], QImode))
++       FAIL;
++
++     /* If we have a non-data reg for operand 1 then prefer that over
++        a CONST_INT in operand 2.  */
++     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
++       && CONST_INT_P (operands[2]))
++       operands[2] = copy_to_mode_reg (QImode, operands[2]);
++
++     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
++       operands[2] = copy_to_mode_reg (QImode, operands[2]);
++   }")
++
++(define_insn "addqi3_add1"
++  [(set (match_operand:QI 0 "memory_operand"                 "=m, m")
++      (plus:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
++               (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")))
++   (clobber (reg:CC CC_REGNO))]
++  "(ubicom32_v4)"
++  "@
++   add.1\\t%0, %2, %1
++   add.1\\t%0, %1, %2")
++
++(define_insn "addqi3_add1_ccszn_null"
++  [(set (reg CC_REGNO)
++      (compare
++        (neg:QI (match_operand:QI 0 "nonimmediate_operand" "%d,rm"))
++        (match_operand:QI 1 "ubicom32_arith_operand"      "rmI, d")))]
++  "(ubicom32_v4
++    && ubicom32_match_cc_mode(insn, CCSZNmode))"
++  "@
++   add.1\\t#0, %1, %0
++   add.1\\t#0, %0, %1")
++
++(define_expand "addhi3"
++  [(parallel
++     [(set (match_operand:HI 0 "memory_operand" "")
++         (plus:HI (match_operand:HI 1 "nonimmediate_operand" "")
++                  (match_operand:HI 2 "ubicom32_arith_operand" "")))
++      (clobber (reg:CC CC_REGNO))])]
++  ""
++  "{
++     if (!memory_operand (operands[0], HImode))
++       FAIL;
++
++     /* If we have a non-data reg for operand 1 then prefer that over
++        a CONST_INT in operand 2.  */
++     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
++       && CONST_INT_P (operands[2]))
++       operands[2] = copy_to_mode_reg (HImode, operands[2]);
++
++     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
++       operands[2] = copy_to_mode_reg (HImode, operands[2]);
++   }")
++
++(define_insn "addhi3_add2"
++  [(set (match_operand:HI 0 "memory_operand"                 "=m, m")
++      (plus:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
++               (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "@
++   add.2\\t%0, %2, %1
++   add.2\\t%0, %1, %2")
++
++(define_insn "addhi3_add2_ccszn_null"
++  [(set (reg CC_REGNO)
++      (compare
++        (neg:HI (match_operand:HI 0 "nonimmediate_operand" "%d,rm"))
++        (match_operand:HI 1 "ubicom32_arith_operand"      "rmI, d")))]
++  "ubicom32_match_cc_mode(insn, CCSZNmode)"
++  "@
++   add.2\\t#0, %1, %0
++   add.2\\t#0, %0, %1")
++
++(define_expand "addsi3"
++  [(set (match_operand:SI 0 "nonimmediate_operand" "")
++      (plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
++               (match_operand:SI 2 "ubicom32_move_operand" "")))]
++  ""
++  "{
++     ubicom32_expand_addsi3 (operands);
++     DONE;
++   }")
++
++; We start with an instruction pattern that can do all sorts of interesting
++; things but we split out any uses of lea or pdec instructions because
++; those instructions don't clobber the condition codes.
++;
++(define_insn_and_split "addsi3_1"
++  [(set (match_operand:SI 0 "nonimmediate_operand"       "=rm,rm,rm,rm,rm, rm,rm")
++      (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%a, a, a, a, a,  d,rm")
++               (match_operand:SI 2 "ubicom32_move_operand" "L, K, J, P, d,rmI, d")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "@
++   #
++   #
++   #
++   #
++   #
++   add.4\\t%0, %2, %1
++   add.4\\t%0, %1, %2"
++  "(reload_completed
++    && ubicom32_address_register_operand (operands[1], GET_MODE (operands[1])))"
++  [(set (match_dup 0)
++      (plus:SI (match_dup 1)
++               (match_dup 2)))]
++  ""
++)
++
++(define_insn "addsi3_1_ccwzn"
++  [(set (reg CC_REGNO)
++      (compare
++        (plus:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
++                 (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))
++        (const_int 0)))
++   (set (match_operand:SI 0 "nonimmediate_operand"            "=rm,rm")
++      (plus:SI (match_dup 1)
++               (match_dup 2)))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "@
++   add.4\\t%0, %2, %1
++   add.4\\t%0, %1, %2")
++
++(define_insn "addsi3_1_ccwzn_null"
++  [(set (reg CC_REGNO)
++      (compare
++        (neg:SI (match_operand:SI 0 "nonimmediate_operand" "%d,rm"))
++        (match_operand:SI 1 "ubicom32_arith_operand"      "rmI, d")))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "@
++   add.4\\t#0, %1, %0
++   add.4\\t#0, %0, %1")
++
++(define_insn_and_split "addsi3_2"
++  [(set (match_operand:SI 0 "nonimmediate_operand"                    "=rm,rm,rm,rm,rm,rm")
++      (plus:SI (match_operand:SI 1 "ubicom32_address_register_operand" "%a, a, a, a, a, a")
++               (match_operand:SI 2 "ubicom32_move_operand"              "L, K, J, P, d, n")))]
++  ""
++  "@
++   lea.4\\t%0, %E2(%1)
++   lea.2\\t%0, %E2(%1)
++   lea.1\\t%0, %E2(%1)
++   pdec\\t%0, %n2(%1)
++   lea.1\\t%0, (%1,%2)
++   #"
++  "(reload_completed
++    && ! satisfies_constraint_L (operands[2])
++    && ! satisfies_constraint_K (operands[2])
++    && ! satisfies_constraint_J (operands[2])
++    && ! satisfies_constraint_P (operands[2])
++    && ! ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))"
++  [(set (reg:SI AUX_DATA_REGNO)
++      (match_dup 2))
++   (set (match_dup 0)
++      (plus:SI (match_dup 1)
++               (reg:SI AUX_DATA_REGNO)))]
++  ""
++)
++
++(define_insn "lea_2"
++  [(set (match_operand:SI 0 "nonimmediate_operand"                         "=rm")
++      (plus:SI (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
++                        (const_int 2))
++               (match_operand:SI 2 "ubicom32_address_register_operand"       "a")))]
++  ""
++  "lea.2\\t%0, (%2,%1)")
++
++(define_insn "lea_4"
++  [(set (match_operand:SI 0 "nonimmediate_operand"                         "=rm")
++      (plus:SI (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
++                        (const_int 4))
++               (match_operand:SI 2 "ubicom32_address_register_operand"       "a")))]
++  ""
++  "lea.4\\t%0, (%2,%1)")
++
++(define_expand "adddi3"
++  [(parallel
++     [(set (match_operand:DI 0 "nonimmediate_operand" "")
++         (plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
++                  (match_operand:DI 2 "ubicom32_arith_operand" "")))
++      (clobber (reg:CC CC_REGNO))])]
++  ""
++  "{
++     /* If we have a non-data reg for operand 1 then prefer that over
++        a CONST_INT in operand 2.  */
++     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
++       && CONST_INT_P (operands[2]))
++       operands[2] = copy_to_mode_reg (DImode, operands[2]);
++
++     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
++       operands[2] = copy_to_mode_reg (DImode, operands[2]);
++   }")
++
++; We construct a 64-bit add from 32-bit operations.  Note that we use the
++; & constraint to prevent overlapping registers being allocated.  We do
++; allow identical registers though as that won't break anything.
++;
++(define_insn "adddi3_add4addc"
++  [(set (match_operand:DI 0 "nonimmediate_operand"          "=&r,&r,rm,  d,  m, m")
++      (plus:DI (match_operand:DI 1 "nonimmediate_operand"    "%d,rm, 0,  0,  d,rm")
++               (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d, d,rmI,rmI, d")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "*
++   {
++     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]);
++
++     if (ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))
++       return \"add.4\\t%3, %4, %5\;addc\\t%6, %7, %8\";
++
++     return \"add.4\\t%3, %5, %4\;addc\\t%6, %8, %7\";
++   }"
++  [(set_attr "length" "8")])
++
++(define_insn "adddi3_ccwz"
++  [(set (reg CC_REGNO)
++      (compare
++        (plus:DI (match_operand:DI 1 "nonimmediate_operand"    "%d,rm, 0,  0,  d,rm")
++                 (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d, d,rmI,rmI, d"))
++        (const_int 0)))
++   (set (match_operand:DI 0 "nonimmediate_operand"            "=&r,&r,rm,  d,  m, m")
++      (plus:DI (match_dup 1)
++               (match_dup 2)))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "*
++   {
++     operands[3] = gen_lowpart (SImode, operands[0]);
++     operands[6] = gen_highpart (SImode, operands[0]);
++
++     if (ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])))
++       {
++       operands[4] = gen_lowpart (SImode, operands[1]);
++       operands[5] = gen_lowpart (SImode, operands[2]);
++       operands[7] = gen_highpart (SImode, operands[1]);
++       operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
++       }
++     else
++       {
++       operands[4] = gen_lowpart (SImode, operands[2]);
++       operands[5] = gen_lowpart (SImode, operands[1]);
++       operands[7] = gen_highpart (SImode, operands[2]);
++       operands[8] = gen_highpart (SImode, operands[1]);
++       }
++
++     return \"add.4\\t%3, %5, %4\;addc\\t%6, %8, %7\";
++   }"
++  [(set_attr "length" "8")])
++
++(define_insn "adddi3_ccwz_null"
++  [(set (reg CC_REGNO)
++      (compare
++        (neg:DI (match_operand:DI 0 "nonimmediate_operand" "%d,rm"))
++        (match_operand:DI 1 "ubicom32_arith_operand"      "rmI, d")))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "*
++   {
++     if (ubicom32_data_register_operand (operands[0], GET_MODE (operands[0])))
++       {
++       operands[2] = gen_lowpart (SImode, operands[0]);
++       operands[3] = gen_lowpart (SImode, operands[1]);
++       operands[4] = gen_highpart (SImode, operands[0]);
++       operands[5] = gen_highpart_mode (SImode, DImode, operands[1]);
++       }
++     else
++       {
++       operands[2] = gen_lowpart (SImode, operands[1]);
++       operands[3] = gen_lowpart (SImode, operands[0]);
++       operands[4] = gen_highpart (SImode, operands[1]);
++       operands[5] = gen_highpart (SImode, operands[0]);
++       }
++
++     return \"add.4\\t#0, %3, %2\;addc\\t#0, %5, %4\";
++   }"
++  [(set_attr "length" "8")])
++
++(define_expand "subqi3"
++  [(parallel
++     [(set (match_operand:QI 0 "memory_operand" "")
++         (minus:QI (match_operand:QI 1 "ubicom32_arith_operand" "")
++                   (match_operand:QI 2 "ubicom32_data_register_operand" "")))
++      (clobber (reg:CC CC_REGNO))])]
++  "(ubicom32_v4)"
++  "{
++     if (!memory_operand (operands[0], QImode))
++       FAIL;
++   }")
++
++(define_insn "subqi3_sub1"
++  [(set (match_operand:QI 0 "memory_operand"                        "=m")
++      (minus:QI (match_operand:QI 1 "ubicom32_arith_operand"       "rmI")
++                (match_operand:QI 2 "ubicom32_data_register_operand" "d")))
++   (clobber (reg:CC CC_REGNO))]
++  "(ubicom32_v4)"
++  "sub.1\\t%0, %1, %2")
++
++(define_expand "subhi3"
++  [(parallel
++     [(set (match_operand:HI 0 "memory_operand" "")
++         (minus:HI (match_operand:HI 1 "ubicom32_arith_operand" "")
++                   (match_operand:HI 2 "ubicom32_data_register_operand" "")))
++      (clobber (reg:CC CC_REGNO))])]
++  "(ubicom32_v4)"
++  "{
++     if (!memory_operand (operands[0], HImode))
++       FAIL;
++   }")
++
++(define_insn "subhi3_sub2"
++  [(set (match_operand:HI 0 "memory_operand"                        "=m")
++      (minus:HI (match_operand:HI 1 "ubicom32_arith_operand"       "rmI")
++                (match_operand:HI 2 "ubicom32_data_register_operand" "d")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "sub.2\\t%0, %1, %2")
++
++(define_insn "subsi3"
++  [(set (match_operand:SI 0 "nonimmediate_operand"                 "=rm")
++      (minus:SI (match_operand:SI 1 "ubicom32_arith_operand"       "rmI")
++                (match_operand:SI 2 "ubicom32_data_register_operand" "d")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "sub.4\\t%0, %1, %2")
++
++(define_insn "subsi3_ccwz"
++  [(set (reg CC_REGNO)
++      (compare
++        (minus:SI (match_operand:SI 1 "ubicom32_arith_operand"       "rmI")
++                  (match_operand:SI 2 "ubicom32_data_register_operand" "d"))
++        (const_int 0)))
++   (set (match_operand:SI 0 "nonimmediate_operand"                   "=rm")
++      (minus:SI (match_dup 1)
++                (match_dup 2)))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "sub.4\\t%0, %1, %2")
++
++; We construct a 64-bit add from 32-bit operations.  Note that we use the
++; & constraint to prevent overlapping registers being allocated.  We do
++; allow identical registers though as that won't break anything.
++;
++(define_insn "subdi3"
++  [(set (match_operand:DI 0 "nonimmediate_operand"                 "=&r,r,  d,  m")
++      (minus:DI (match_operand:DI 1 "ubicom32_arith_operand"       "rmI,0,rmI,rmI")
++                (match_operand:DI 2 "ubicom32_data_register_operand" "d,d,  0,  d")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "*
++   {
++     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 (SImode, operands[2]);
++
++     return \"sub.4\\t%3, %4, %5\;subc\\t%6, %7, %8\";
++   }"
++  [(set_attr "length" "8")])
++
++(define_insn "subdi3_ccwz"
++  [(set (reg CC_REGNO)
++      (compare
++        (minus:DI (match_operand:DI 1 "ubicom32_arith_operand"       "rmI,rmI")
++                  (match_operand:DI 2 "ubicom32_data_register_operand" "d,  d"))
++        (const_int 0)))
++   (set (match_operand:DI 0 "nonimmediate_operand"                   "=&r,  m")
++      (minus:DI (match_dup 1)
++                (match_dup 2)))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "*
++   {
++     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 (SImode, operands[2]);
++
++     return \"sub.4\\t%3, %4, %5\;subc\\t%6, %7, %8\";
++   }"
++  [(set_attr "length" "8")])
++
++;(define_insn "negqi2"
++;  [(set (match_operand:QI 0 "nonimmediate_operand"              "=rm")
++;     (neg:QI (match_operand:QI 1 "ubicom32_data_register_operand" "d")))
++;   (clobber (reg:CC CC_REGNO))]
++;  "(ubicom32_v4)"
++;  "sub.1\\t%0, #0, %1")
++
++;(define_insn "neghi2"
++;  [(set (match_operand:HI 0 "nonimmediate_operand"              "=rm")
++;     (neg:HI (match_operand:HI 1 "ubicom32_data_register_operand" "d")))
++;   (clobber (reg:CC CC_REGNO))]
++;  ""
++;  "sub.2\\t%0, #0, %1")
++
++(define_insn "negsi2"
++  [(set (match_operand:SI 0 "nonimmediate_operand"               "=rm")
++      (neg:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "sub.4\\t%0, #0, %1")
++
++(define_insn_and_split "negdi2"
++  [(set (match_operand:DI 0 "nonimmediate_operand"              "=&rm")
++      (neg:DI (match_operand:DI 1 "ubicom32_data_register_operand" "d")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "#"
++  "reload_completed"
++  [(parallel [(set (match_dup 0)
++                 (minus:DI (const_int 0)
++                           (match_dup 1)))
++            (clobber (reg:CC CC_REGNO))])]
++  ""
++  [(set_attr "length" "8")])
++
++(define_insn "umulhisi3"
++  [(set (match_operand:SI 0 "ubicom32_acc_lo_register_operand"             "=l, l")
++      (mult:SI
++        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "%d,rm"))
++        (zero_extend:SI (match_operand:HI 2 "nonimmediate_operand" "rm, d"))))
++   (clobber (reg:HI ACC0_HI_REGNO))
++   (clobber (reg:HI ACC1_HI_REGNO))]
++  ""
++  "@
++   mulu\\t%A0, %2, %1
++   mulu\\t%A0, %1, %2"
++  [(set_attr "type" "mul,mul")])
++
++(define_insn "mulhisi3"
++  [(set (match_operand:SI 0 "ubicom32_acc_lo_register_operand"             "=l, l")
++      (mult:SI
++        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "%d,rm"))
++        (sign_extend:SI (match_operand:HI 2 "nonimmediate_operand" "rm, d"))))
++   (clobber (reg:HI ACC0_HI_REGNO))
++   (clobber (reg:HI ACC1_HI_REGNO))]
++  ""
++  "@
++   muls\\t%A0, %2, %1
++   muls\\t%A0, %1, %2"
++  [(set_attr "type" "mul,mul")])
++
++(define_expand "mulsi3"
++  [(set (match_operand:SI 0 "ubicom32_acc_hi_register_operand" "")
++      (mult:SI (match_operand:SI 1 "ubicom32_arith_operand" "")
++               (match_operand:SI 2 "ubicom32_arith_operand" "")))]
++  ""
++  "{
++     if (ubicom32_emit_mult_sequence (operands))
++       DONE;
++   }")
++
++(define_insn "umulsidi3"
++  [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand"             "=h, h")
++      (mult:DI
++        (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%d,rm"))
++        (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm, d"))))]
++  "(ubicom32_v4)"
++  "@
++   mulu.4\\t%A0, %2, %1
++   mulu.4\\t%A0, %1, %2"
++  [(set_attr "type" "mul,mul")])
++
++(define_peephole2
++  [(set (match_operand:SI 0 "register_operand" "")
++      (match_operand:SI 1 "nonimmediate_operand" ""))
++   (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "")
++      (mult:DI
++        (zero_extend:DI (match_dup 0))
++        (zero_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))))]
++  "(peep2_reg_dead_p (2, operands[0])
++    || REGNO (operands[0]) == REGNO (operands[2])
++    || REGNO (operands[0]) == REGNO (operands[2]) + 1)
++   && ! rtx_equal_p (operands[0], operands[3])"
++  [(set (match_dup 2)
++      (mult:DI
++        (zero_extend:DI (match_dup 1))
++        (zero_extend:DI (match_dup 3))))]
++  "")
++
++(define_peephole2
++  [(set (match_operand:SI 0 "register_operand" "")
++      (match_operand:SI 1 "nonimmediate_operand" ""))
++   (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "")
++      (mult:DI
++        (zero_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))
++        (zero_extend:DI (match_dup 0))))]
++  "(peep2_reg_dead_p (2, operands[0])
++    || REGNO (operands[0]) == REGNO (operands[2])
++    || REGNO (operands[0]) == REGNO (operands[2]) + 1)
++   && ! rtx_equal_p (operands[0], operands[3])"
++  [(set (match_dup 2)
++      (mult:DI
++        (zero_extend:DI (match_dup 1))
++        (zero_extend:DI (match_dup 3))))]
++  "")
++
++(define_insn "umulsidi3_const"
++  [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand"                       "=h")
++      (mult:DI
++        (zero_extend:DI (match_operand:SI 1 "ubicom32_data_register_operand" "%d"))
++        (match_operand 2 "const_int_operand"                                  "I")))]
++  "(ubicom32_v4 && satisfies_constraint_I (operands[2]))"
++  "mulu.4\\t%A0, %2, %1"
++  [(set_attr "type" "mul")])
++
++(define_insn "mulsidi3"
++  [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand"             "=h, h")
++      (mult:DI
++        (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%d,rm"))
++        (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm, d"))))]
++  "(ubicom32_v4)"
++  "@
++   muls.4\\t%A0, %2, %1
++   muls.4\\t%A0, %1, %2"
++  [(set_attr "type" "mul,mul")])
++
++(define_peephole2
++  [(set (match_operand:SI 0 "register_operand" "")
++      (match_operand:SI 1 "nonimmediate_operand" ""))
++   (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "")
++      (mult:DI
++        (sign_extend:DI (match_dup 0))
++        (sign_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))))]
++  "(peep2_reg_dead_p (2, operands[0])
++    || REGNO (operands[0]) == REGNO (operands[2])
++    || REGNO (operands[0]) == REGNO (operands[2]) + 1)
++   && ! rtx_equal_p (operands[0], operands[3])"
++  [(set (match_dup 2)
++      (mult:DI
++        (sign_extend:DI (match_dup 1))
++        (sign_extend:DI (match_dup 3))))]
++  "")
++
++(define_peephole2
++  [(set (match_operand:SI 0 "register_operand" "")
++      (match_operand:SI 1 "nonimmediate_operand" ""))
++   (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "")
++      (mult:DI
++        (sign_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))
++        (sign_extend:DI (match_dup 0))))]
++  "(peep2_reg_dead_p (2, operands[0])
++    || REGNO (operands[0]) == REGNO (operands[2])
++    || REGNO (operands[0]) == REGNO (operands[2]) + 1)
++   && ! rtx_equal_p (operands[0], operands[3])"
++  [(set (match_dup 2)
++      (mult:DI
++        (sign_extend:DI (match_dup 1))
++        (sign_extend:DI (match_dup 3))))]
++  "")
++
++(define_insn "mulsidi3_const"
++  [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand"                       "=h")
++      (mult:DI
++        (sign_extend:DI (match_operand:SI 1 "ubicom32_data_register_operand" "%d"))
++        (match_operand 2 "const_int_operand"                                  "I")))]
++  "(ubicom32_v4 && satisfies_constraint_I (operands[2]))"
++  "muls.4\\t%A0, %2, %1"
++  [(set_attr "type" "mul")])
++
++(define_expand "andqi3"
++  [(parallel
++     [(set (match_operand:QI 0 "memory_operand" "")
++         (and:QI (match_operand:QI 1 "nonimmediate_operand" "")
++                 (match_operand:QI 2 "ubicom32_arith_operand" "")))
++      (clobber (reg:CC CC_REGNO))])]
++  "(ubicom32_v4)"
++  "{
++     if (!memory_operand (operands[0], QImode))
++       FAIL;
++
++     /* If we have a non-data reg for operand 1 then prefer that over
++        a CONST_INT in operand 2.  */
++     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
++       && CONST_INT_P (operands[2]))
++       operands[2] = copy_to_mode_reg (QImode, operands[2]);
++
++     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
++       operands[2] = copy_to_mode_reg (QImode, operands[2]);
++   }")
++
++(define_insn "andqi3_and1"
++  [(set (match_operand:QI 0 "memory_operand"                "=m, m")
++      (and:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
++              (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")))
++   (clobber (reg:CC CC_REGNO))]
++  "(ubicom32_v4)"
++  "@
++   and.1\\t%0, %2, %1
++   and.1\\t%0, %1, %2")
++
++(define_insn "andqi3_and1_ccszn"
++  [(set (reg CC_REGNO)
++      (compare
++        (and:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
++                (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d"))
++        (const_int 0)))
++   (set (match_operand:QI 0 "memory_operand"                  "=m, m")
++      (and:QI (match_dup 1)
++              (match_dup 2)))]
++  "(ubicom32_v4
++    && ubicom32_match_cc_mode(insn, CCSZNmode))"
++  "@
++   and.1\\t%0, %2, %1
++   and.1\\t%0, %1, %2")
++
++(define_insn "andqi3_and1_ccszn_null"
++  [(set (reg CC_REGNO)
++      (compare
++        (and:QI (match_operand:QI 0 "nonimmediate_operand"    "%d,rm")
++                (match_operand:QI 1 "ubicom32_arith_operand" "rmI, d"))
++        (const_int 0)))]
++  "(ubicom32_v4
++    && ubicom32_match_cc_mode(insn, CCSZNmode))"
++  "@
++   and.1\\t#0, %1, %0
++   and.1\\t#0, %0, %1")
++
++(define_insn "and1_ccszn_null_1"
++  [(set (reg CC_REGNO)
++      (compare
++        (subreg:QI
++          (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d")
++                  (match_operand:SI 1 "ubicom32_arith_operand"         "rI"))
++          3)
++        (const_int 0)))]
++  "(ubicom32_v4
++    && ubicom32_match_cc_mode(insn, CCSZNmode))"
++  "and.1\\t#0, %1, %0")
++
++(define_insn "and1_ccszn_null_2"
++  [(set (reg CC_REGNO)
++      (compare
++        (subreg:QI
++          (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d")
++                  (subreg:SI
++                    (match_operand:QI 1 "memory_operand"               "m")
++                    0))
++          3)
++        (const_int 0)))]
++  "(ubicom32_v4
++    && ubicom32_match_cc_mode(insn, CCSZNmode))"
++  "and.1\\t#0, %1, %0")
++
++(define_insn "and1_ccszn_null_3"
++  [(set (reg CC_REGNO)
++      (compare
++        (subreg:QI
++          (and:SI (subreg:SI
++                    (match_operand:QI 0 "memory_operand"               "m")
++                    0)
++                  (match_operand:SI 1 "ubicom32_data_register_operand" "d"))
++          3)
++        (const_int 0)))]
++  "(ubicom32_v4
++    && ubicom32_match_cc_mode(insn, CCSZNmode))"
++  "and.1\\t#0, %0, %1")
++
++(define_expand "andhi3"
++  [(parallel
++     [(set (match_operand:HI 0 "memory_operand" "")
++         (and:HI (match_operand:HI 1 "nonimmediate_operand" "")
++                 (match_operand:HI 2 "ubicom32_arith_operand" "")))
++      (clobber (reg:CC CC_REGNO))])]
++  ""
++  "{
++     if (!memory_operand (operands[0], HImode))
++       FAIL;
++
++     /* If we have a non-data reg for operand 1 then prefer that over
++        a CONST_INT in operand 2.  */
++     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
++       && CONST_INT_P (operands[2]))
++       operands[2] = copy_to_mode_reg (HImode, operands[2]);
++
++     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
++       operands[2] = copy_to_mode_reg (HImode, operands[2]);
++   }")
++
++(define_insn "andhi3_and2"
++  [(set (match_operand:HI 0 "memory_operand"                "=m, m")
++      (and:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
++              (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "@
++   and.2\\t%0, %2, %1
++   and.2\\t%0, %1, %2")
++
++(define_insn "andhi3_and2_ccszn"
++  [(set (reg CC_REGNO)
++      (compare
++        (and:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
++                (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d"))
++        (const_int 0)))
++   (set (match_operand:HI 0 "memory_operand"                  "=m, m")
++      (and:HI (match_dup 1)
++              (match_dup 2)))]
++  "ubicom32_match_cc_mode(insn, CCSZNmode)"
++  "@
++   and.2\\t%0, %2, %1
++   and.2\\t%0, %1, %2")
++
++(define_insn "andhi3_and2_ccszn_null"
++  [(set (reg CC_REGNO)
++      (compare
++        (and:HI (match_operand:HI 0 "nonimmediate_operand"    "%d,rm")
++                (match_operand:HI 1 "ubicom32_arith_operand" "rmI, d"))
++        (const_int 0)))]
++  "ubicom32_match_cc_mode(insn, CCSZNmode)"
++  "@
++   and.2\\t#0, %1, %0
++   and.2\\t#0, %0, %1")
++
++(define_insn "and2_ccszn_null_1"
++  [(set (reg CC_REGNO)
++      (compare
++        (subreg:HI
++          (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d")
++                  (match_operand:SI 1 "ubicom32_arith_operand"         "rI"))
++          2)
++        (const_int 0)))]
++  "ubicom32_match_cc_mode(insn, CCSZNmode)"
++  "and.2\\t#0, %1, %0")
++
++(define_insn "and2_ccszn_null_2"
++  [(set (reg CC_REGNO)
++      (compare
++        (subreg:HI
++          (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d")
++                  (subreg:SI
++                    (match_operand:HI 1 "memory_operand"               "m")
++                    0))
++          2)
++        (const_int 0)))]
++  "ubicom32_match_cc_mode(insn, CCSZNmode)"
++  "and.2\\t#0, %1, %0")
++
++(define_insn "and2_ccszn_null_3"
++  [(set (reg CC_REGNO)
++      (compare
++        (subreg:HI
++          (and:SI (subreg:SI
++                    (match_operand:HI 0 "memory_operand"               "m")
++                    0)
++                  (match_operand:SI 1 "ubicom32_data_register_operand" "d"))
++          2)
++        (const_int 0)))]
++  "ubicom32_match_cc_mode(insn, CCSZNmode)"
++  "and.2\\t#0, %0, %1")
++
++(define_expand "andsi3"
++  [(parallel
++     [(set (match_operand:SI 0 "nonimmediate_operand" "")
++         (and:SI (match_operand:SI 1 "nonimmediate_operand" "")
++                 (match_operand:SI 2 "ubicom32_and_or_si3_operand" "")))
++      (clobber (reg:CC CC_REGNO))])]
++  ""
++  "{
++     do
++       {
++       /* Is this a bfextu?  */
++       if (ubicom32_data_register_operand (operands[0], SImode)
++           && CONST_INT_P (operands[2])
++           && exact_log2 (INTVAL (operands[2]) + 1) != -1)
++         break;
++
++       /* Is this a bclr?  */
++       if (CONST_INT_P (operands[2])
++           && exact_log2 (~INTVAL (operands[2])) != -1)
++         break;
++
++       /* Must be an and.4  */
++       if (!ubicom32_data_register_operand (operands[1], SImode))
++         operands[1] = copy_to_mode_reg (SImode, operands[1]);
++
++       if (!ubicom32_arith_operand (operands[2], SImode))
++         operands[2] = copy_to_mode_reg (SImode, operands[2]);
++       }
++     while (0);
++   }")
++
++(define_insn "andsi3_bfextu"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
++      (and:SI (match_operand:SI 1 "nonimmediate_operand"  "%rm")
++              (match_operand:SI 2 "const_int_operand"       "O")))
++   (clobber (reg:CC CC_REGNO))]
++  "(satisfies_constraint_O (operands[2]))"
++  "*
++   {
++     operands[3] = GEN_INT (exact_log2 (INTVAL (operands[2]) + 1));
++
++     return \"bfextu\\t%0, %1, %3\";
++   }")
++
++(define_insn "andsi3_bfextu_ccwz"
++  [(set (reg CC_REGNO)
++      (compare
++        (and:SI (match_operand:SI 1 "nonimmediate_operand" "%rm")
++                (match_operand:SI 2 "const_int_operand"      "O"))
++        (const_int 0)))
++   (set (match_operand:SI 0 "ubicom32_data_register_operand"  "=d")
++      (and:SI (match_dup 1)
++              (match_dup 2)))]
++  "(satisfies_constraint_O (operands[2])
++    && ubicom32_match_cc_mode(insn, CCWZmode))"
++  "*
++   {
++     operands[3] = GEN_INT (exact_log2 (INTVAL (operands[2]) + 1));
++
++     return \"bfextu\\t%0, %1, %3\";
++   }")
++
++(define_insn "andsi3_bfextu_ccwz_null"
++  [(set (reg CC_REGNO)
++      (compare
++        (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm")
++                (match_operand:SI 1 "const_int_operand"      "O"))
++        (const_int 0)))
++   (clobber (match_scratch:SI 2                                     "=d"))]
++  "(satisfies_constraint_O (operands[1])
++    && ubicom32_match_cc_mode(insn, CCWZmode))"
++  "*
++   {
++     operands[3] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1));
++
++     return \"bfextu\\t%2, %0, %3\";
++   }")
++
++(define_insn "andsi3_bclr"
++  [(set (match_operand:SI 0 "nonimmediate_operand"          "=rm")
++      (and:SI (match_operand:SI 1 "ubicom32_arith_operand" "%rmI")
++              (match_operand:SI 2 "const_int_operand"         "n")))
++   (clobber (reg:CC CC_REGNO))]
++  "(exact_log2 (~INTVAL (operands[2])) != -1)"
++  "bclr\\t%0, %1, #%D2")
++
++(define_insn "andsi3_and4"
++  [(set (match_operand:SI 0 "nonimmediate_operand"         "=rm,rm")
++      (and:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
++              (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "@
++   and.4\\t%0, %2, %1
++   and.4\\t%0, %1, %2")
++
++(define_insn "andsi3_and4_ccwzn"
++  [(set (reg CC_REGNO)
++      (compare
++        (and:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
++                (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))
++        (const_int 0)))
++   (set (match_operand:SI 0 "nonimmediate_operand"           "=rm,rm")
++      (and:SI (match_dup 1)
++              (match_dup 2)))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "@
++   and.4\\t%0, %2, %1
++   and.4\\t%0, %1, %2")
++
++(define_insn "andsi3_and4_ccwzn_null"
++  [(set (reg CC_REGNO)
++      (compare
++        (and:SI (match_operand:SI 0 "nonimmediate_operand"    "%d,rm")
++                (match_operand:SI 1 "ubicom32_arith_operand" "rmI, d"))
++        (const_int 0)))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "@
++   and.4\\t#0, %1, %0
++   and.4\\t#0, %0, %1")
++
++(define_insn "andsi3_lsr4_ccwz_null"
++  [(set (reg CC_REGNO)
++      (compare
++        (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm")
++                (match_operand:SI 1 "const_int_operand"      "n"))
++        (const_int 0)))
++   (clobber (match_scratch:SI 2                                     "=d"))]
++  "(exact_log2 ((~(INTVAL (operands[1]))) + 1) != -1
++    && ubicom32_match_cc_mode(insn, CCWZmode))"
++  "*
++   {
++     operands[3] = GEN_INT (exact_log2 ((~(INTVAL (operands[1]))) + 1));
++
++     return \"lsr.4\\t%2, %0, %3\";
++   }")
++
++; We really would like the combiner to recognize this scenario and deal with
++; it but unfortunately it tries to canonicalize zero_extract ops on MEMs
++; into QImode operations and we can't match them in any useful way.
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "register_operand" "")
++      (match_operand:SI 1 "const_int_operand" ""))
++   (set (reg:CCWZ CC_REGNO)
++      (compare:CCWZ
++        (and:SI (match_operand:SI 2 "nonimmediate_operand" "")
++                (match_dup 0))
++        (const_int 0)))]
++  "(exact_log2 (INTVAL (operands[1])) != -1
++    && peep2_reg_dead_p (2, operands[0]))"
++  [(set (reg:CCWZ CC_REGNO)
++      (compare:CCWZ
++        (zero_extract:SI
++          (match_dup 2)
++          (const_int 1)
++          (match_dup 3))
++        (const_int 0)))]
++  "{
++     operands[3] = GEN_INT (exact_log2 (INTVAL (operands[1])));
++   }")
++
++(define_expand "anddi3"
++  [(parallel
++     [(set (match_operand:DI 0 "nonimmediate_operand" "")
++         (and:DI (match_operand:DI 1 "nonimmediate_operand" "")
++                 (match_operand:DI 2 "ubicom32_arith_operand" "")))
++      (clobber (reg:CC CC_REGNO))])]
++  ""
++  "{
++     /* If we have a non-data reg for operand 1 then prefer that over
++        a CONST_INT in operand 2.  */
++     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
++       && CONST_INT_P (operands[2]))
++       operands[2] = copy_to_mode_reg (DImode, operands[2]);
++
++     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
++       operands[2] = copy_to_mode_reg (DImode, operands[2]);
++   }")
++
++(define_insn_and_split "anddi3_and4"
++  [(set (match_operand:DI 0 "nonimmediate_operand"         "=&r,&r,  d,rm,  m, m")
++      (and:DI (match_operand:DI 1 "nonimmediate_operand"    "%d,rm,  0, 0,  d,rm")
++              (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d,rmI, d,rmI, d")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "#"
++  "reload_completed"
++  [(parallel [(set (match_dup 3)
++                 (and:SI (match_dup 4)
++                         (match_dup 5)))
++            (clobber (reg:CC CC_REGNO))])
++   (parallel [(set (match_dup 6)
++                 (and:SI (match_dup 7)
++                         (match_dup 8)))
++            (clobber (reg:CC CC_REGNO))])]
++  "{
++     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" "8")])
++
++(define_expand "iorqi3"
++  [(parallel
++     [(set (match_operand:QI 0 "memory_operand" "")
++         (ior:QI (match_operand:QI 1 "nonimmediate_operand" "")
++                 (match_operand:QI 2 "ubicom32_arith_operand" "")))
++      (clobber (reg:CC CC_REGNO))])]
++  "(ubicom32_v4)"
++  "{
++     if (!memory_operand (operands[0], QImode))
++       FAIL;
++
++     /* If we have a non-data reg for operand 1 then prefer that over
++        a CONST_INT in operand 2.  */
++     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
++       && CONST_INT_P (operands[2]))
++       operands[2] = copy_to_mode_reg (QImode, operands[2]);
++
++     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
++       operands[2] = copy_to_mode_reg (QImode, operands[2]);
++   }")
++
++(define_insn "iorqi3_or1"
++  [(set (match_operand:QI 0 "memory_operand"                "=m, m")
++      (ior:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
++              (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")))
++   (clobber (reg:CC CC_REGNO))]
++  "(ubicom32_v4)"
++  "@
++   or.1\\t%0, %2, %1
++   or.1\\t%0, %1, %2")
++
++(define_expand "iorhi3"
++  [(parallel
++     [(set (match_operand:HI 0 "memory_operand" "")
++         (ior:HI (match_operand:HI 1 "nonimmediate_operand" "")
++                 (match_operand:HI 2 "ubicom32_arith_operand" "")))
++      (clobber (reg:CC CC_REGNO))])]
++  ""
++  "{
++     if (!memory_operand (operands[0], HImode))
++       FAIL;
++
++     /* If we have a non-data reg for operand 1 then prefer that over
++        a CONST_INT in operand 2.  */
++     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
++       && CONST_INT_P (operands[2]))
++       operands[2] = copy_to_mode_reg (HImode, operands[2]);
++
++     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
++       operands[2] = copy_to_mode_reg (HImode, operands[2]);
++   }")
++
++(define_insn "iorhi3_or2"
++  [(set (match_operand:HI 0 "memory_operand"                "=m, m")
++      (ior:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
++              (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "@
++   or.2\\t%0, %2, %1
++   or.2\\t%0, %1, %2")
++
++(define_expand "iorsi3"
++  [(parallel
++     [(set (match_operand:SI 0 "nonimmediate_operand" "")
++         (ior:SI (match_operand:SI 1 "nonimmediate_operand" "")
++                 (match_operand:SI 2 "ubicom32_and_or_si3_operand" "")))
++      (clobber (reg:CC CC_REGNO))])]
++  ""
++  "{
++     do
++       {
++       /* Is this a bset?  */
++       if (CONST_INT_P (operands[2])
++           && exact_log2 (INTVAL (operands[2])) != -1)
++         break;
++
++       /* Must be an or.4  */
++       if (!ubicom32_data_register_operand (operands[1], SImode))
++         operands[1] = copy_to_mode_reg (SImode, operands[1]);
++
++       if (!ubicom32_arith_operand (operands[2], SImode))
++         operands[2] = copy_to_mode_reg (SImode, operands[2]);
++       } 
++     while (0);
++   }")
++
++(define_insn "iorsi3_bset"
++  [(set (match_operand:SI 0 "nonimmediate_operand"          "=rm")
++      (ior:SI (match_operand:SI 1 "ubicom32_arith_operand" "%rmI")
++              (match_operand 2 "const_int_operand"            "n")))
++   (clobber (reg:CC CC_REGNO))]
++  "(exact_log2 (INTVAL (operands[2])) != -1)"
++  "bset\\t%0, %1, #%d2")
++
++(define_insn "iorsi3_or4"
++  [(set (match_operand:SI 0 "nonimmediate_operand"         "=rm,rm")
++      (ior:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
++              (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "@
++   or.4\\t%0, %2, %1
++   or.4\\t%0, %1, %2")
++
++(define_insn "iorsi3_ccwzn"
++  [(set (reg CC_REGNO)
++      (compare
++        (ior:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
++                (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))
++        (const_int 0)))
++   (set (match_operand:SI 0 "nonimmediate_operand"           "=rm,rm")
++      (ior:SI (match_dup 1)
++              (match_dup 2)))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "@
++   or.4\\t%0, %2, %1
++   or.4\\t%0, %1, %2")
++
++(define_insn "iorsi3_ccwzn_null"
++  [(set (reg CC_REGNO)
++      (compare
++        (ior:SI (match_operand:SI 0 "nonimmediate_operand"    "%d,rm")
++                (match_operand:SI 1 "ubicom32_arith_operand" "rmI, d"))
++        (const_int 0)))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "@
++   or.4\\t#0, %1, %0
++   or.4\\t#0, %0, %1")
++
++(define_expand "iordi3"
++  [(parallel
++     [(set (match_operand:DI 0 "nonimmediate_operand" "")
++         (ior:DI (match_operand:DI 1 "nonimmediate_operand" "")
++                 (match_operand:DI 2 "ubicom32_arith_operand" "")))
++      (clobber (reg:CC CC_REGNO))])]
++  ""
++  "{
++     /* If we have a non-data reg for operand 1 then prefer that over
++        a CONST_INT in operand 2.  */
++     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
++       && CONST_INT_P (operands[2]))
++       operands[2] = copy_to_mode_reg (DImode, operands[2]);
++
++     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
++       operands[2] = copy_to_mode_reg (DImode, operands[2]);
++   }")
++
++(define_insn_and_split "iordi3_or4"
++  [(set (match_operand:DI 0 "nonimmediate_operand"         "=&r,&r,  d,rm,  m, m")
++      (ior:DI (match_operand:DI 1 "nonimmediate_operand"    "%d,rm,  0, 0,  d,rm")
++              (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d,rmI, d,rmI, d")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "#"
++  "reload_completed"
++  [(parallel [(set (match_dup 3)
++                 (ior:SI (match_dup 4)
++                         (match_dup 5)))
++            (clobber (reg:CC CC_REGNO))])
++   (parallel [(set (match_dup 6)
++                 (ior:SI (match_dup 7)
++                         (match_dup 8)))
++            (clobber (reg:CC CC_REGNO))])]
++  "{
++     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" "8")])
++
++(define_expand "xorqi3"
++  [(parallel
++     [(set (match_operand:QI 0 "memory_operand" "")
++         (xor:QI (match_operand:QI 1 "nonimmediate_operand" "")
++                 (match_operand:QI 2 "ubicom32_arith_operand" "")))
++      (clobber (reg:CC CC_REGNO))])]
++  "(ubicom32_v4)"
++  "{
++     if (!memory_operand (operands[0], QImode))
++       FAIL;
++
++     /* If we have a non-data reg for operand 1 then prefer that over
++        a CONST_INT in operand 2.  */
++     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
++       && CONST_INT_P (operands[2]))
++       operands[2] = copy_to_mode_reg (QImode, operands[2]);
++
++     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
++       operands[2] = copy_to_mode_reg (QImode, operands[2]);
++   }")
++
++(define_insn "xorqi3_xor1"
++  [(set (match_operand:QI 0 "memory_operand"                "=m, m")
++      (xor:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
++              (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")))
++   (clobber (reg:CC CC_REGNO))]
++  "(ubicom32_v4)"
++  "@
++   xor.1\\t%0, %2, %1
++   xor.1\\t%0, %1, %2")
++
++(define_insn "xorqi3_xor1_ccszn"
++  [(set (reg CC_REGNO)
++      (compare
++        (xor:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
++                (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d"))
++        (const_int 0)))
++   (set (match_operand:QI 0 "memory_operand"                  "=m, m")
++      (xor:QI (match_dup 1)
++              (match_dup 2)))]
++  "(ubicom32_v4
++    && ubicom32_match_cc_mode(insn, CCSZNmode))"
++  "@
++   xor.1\\t%0, %2, %1
++   xor.1\\t%0, %1, %2")
++
++(define_insn "xorqi3_xor1_ccszn_null"
++  [(set (reg CC_REGNO)
++      (compare
++        (xor:QI (match_operand:QI 0 "nonimmediate_operand"    "%d,rm")
++                (match_operand:QI 1 "ubicom32_arith_operand" "rmI, d"))
++        (const_int 0)))]
++  "(ubicom32_v4
++    && ubicom32_match_cc_mode(insn, CCSZNmode))"
++  "@
++   xor.1\\t#0, %1, %0
++   xor.1\\t#0, %0, %1")
++
++(define_insn "xor1_ccszn_null_1"
++  [(set (reg CC_REGNO)
++      (compare
++        (subreg:QI
++          (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d")
++                  (match_operand:SI 1 "ubicom32_arith_operand"         "rI"))
++          3)
++        (const_int 0)))]
++  "(ubicom32_v4
++    && ubicom32_match_cc_mode(insn, CCSZNmode))"
++  "xor.1\\t#0, %1, %0")
++
++(define_insn "xor1_ccszn_null_2"
++  [(set (reg CC_REGNO)
++      (compare
++        (subreg:QI
++          (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d")
++                  (subreg:SI
++                    (match_operand:QI 1 "memory_operand"               "m")
++                    0))
++          3)
++        (const_int 0)))]
++  "(ubicom32_v4
++    && ubicom32_match_cc_mode(insn, CCSZNmode))"
++  "xor.1\\t#0, %1, %0")
++
++(define_insn "xor1_ccwzn_null_3"
++  [(set (reg CC_REGNO)
++      (compare
++        (subreg:QI
++          (xor:SI (subreg:SI
++                    (match_operand:QI 0 "memory_operand"               "m")
++                    0)
++                  (match_operand:SI 1 "ubicom32_data_register_operand" "d"))
++          3)
++        (const_int 0)))]
++  "(ubicom32_v4
++    && ubicom32_match_cc_mode(insn, CCSZNmode))"
++  "xor.1\\t#0, %0, %1")
++
++(define_expand "xorhi3"
++  [(parallel
++     [(set (match_operand:HI 0 "memory_operand" "")
++         (xor:HI (match_operand:HI 1 "nonimmediate_operand" "")
++                 (match_operand:HI 2 "ubicom32_arith_operand" "")))
++      (clobber (reg:CC CC_REGNO))])]
++  ""
++  "{
++     if (!memory_operand (operands[0], HImode))
++       FAIL;
++
++     /* If we have a non-data reg for operand 1 then prefer that over
++        a CONST_INT in operand 2.  */
++     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
++       && CONST_INT_P (operands[2]))
++       operands[2] = copy_to_mode_reg (HImode, operands[2]);
++
++     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
++       operands[2] = copy_to_mode_reg (HImode, operands[2]);
++   }")
++
++(define_insn "xorhi3_xor2"
++  [(set (match_operand:HI 0 "memory_operand"                "=m, m")
++      (xor:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
++              (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "@
++   xor.2\\t%0, %2, %1
++   xor.2\\t%0, %1, %2")
++
++(define_insn "xorhi3_xor2_ccszn"
++  [(set (reg CC_REGNO)
++      (compare
++        (xor:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
++                (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d"))
++        (const_int 0)))
++   (set (match_operand:HI 0 "memory_operand"                  "=m, m")
++      (xor:HI (match_dup 1)
++              (match_dup 2)))]
++  "ubicom32_match_cc_mode(insn, CCSZNmode)"
++  "@
++   xor.2\\t%0, %2, %1
++   xor.2\\t%0, %1, %2")
++
++(define_insn "xorhi3_xor2_ccszn_null"
++  [(set (reg CC_REGNO)
++      (compare
++        (xor:HI (match_operand:HI 0 "nonimmediate_operand"    "%d,rm")
++                (match_operand:HI 1 "ubicom32_arith_operand" "rmI, d"))
++        (const_int 0)))]
++  "ubicom32_match_cc_mode(insn, CCSZNmode)"
++  "@
++   xor.2\\t#0, %1, %0
++   xor.2\\t#0, %0, %1")
++
++(define_insn "xor2_ccszn_null_1"
++  [(set (reg CC_REGNO)
++      (compare
++        (subreg:HI
++          (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d")
++                  (match_operand:SI 1 "ubicom32_arith_operand"         "rI"))
++          2)
++        (const_int 0)))]
++  "ubicom32_match_cc_mode(insn, CCSZNmode)"
++  "xor.2\\t#0, %1, %0")
++
++(define_insn "xor2_ccszn_null_2"
++  [(set (reg CC_REGNO)
++      (compare
++        (subreg:HI
++          (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d")
++                  (subreg:SI
++                    (match_operand:HI 1 "memory_operand"               "m")
++                    0))
++          2)
++        (const_int 0)))]
++  "ubicom32_match_cc_mode(insn, CCSZNmode)"
++  "xor.2\\t#0, %1, %0")
++
++(define_insn "xor2_ccszn_null_3"
++  [(set (reg CC_REGNO)
++      (compare
++        (subreg:HI
++          (xor:SI (subreg:SI
++                    (match_operand:HI 0 "memory_operand"               "m")
++                    0)
++                  (match_operand:SI 1 "ubicom32_data_register_operand" "d"))
++          2)
++        (const_int 0)))]
++  "ubicom32_match_cc_mode(insn, CCSZNmode)"
++  "xor.2\\t#0, %0, %1")
++
++(define_insn "xorsi3"
++  [(set (match_operand:SI 0 "nonimmediate_operand"         "=rm,rm")
++      (xor:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
++              (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "@
++   xor.4\\t%0, %2, %1
++   xor.4\\t%0, %1, %2")
++
++(define_insn "xorsi3_ccwzn"
++  [(set (reg CC_REGNO)
++      (compare
++        (xor:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
++                (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))
++        (const_int 0)))
++   (set (match_operand:SI 0 "nonimmediate_operand"           "=rm,rm")
++      (xor:SI (match_dup 1)
++              (match_dup 2)))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "@
++   xor.4\\t%0, %2, %1
++   xor.4\\t%0, %1, %2")
++
++(define_insn "xorsi3_ccwzn_null"
++  [(set (reg CC_REGNO)
++      (compare
++        (xor:SI (match_operand:SI 0 "nonimmediate_operand"    "%d,rm")
++                (match_operand:SI 1 "ubicom32_arith_operand" "rmI, d"))
++        (const_int 0)))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "@
++   xor.4\\t#0, %1, %0
++   xor.4\\t#0, %0, %1")
++
++(define_expand "xordi3"
++  [(parallel
++     [(set (match_operand:DI 0 "nonimmediate_operand" "")
++         (xor:DI (match_operand:DI 1 "nonimmediate_operand" "")
++                 (match_operand:DI 2 "ubicom32_arith_operand" "")))
++      (clobber (reg:CC CC_REGNO))])]
++  ""
++  "{
++     /* If we have a non-data reg for operand 1 then prefer that over
++        a CONST_INT in operand 2.  */
++     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
++       && CONST_INT_P (operands[2]))
++       operands[2] = copy_to_mode_reg (DImode, operands[2]);
++
++     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
++       operands[2] = copy_to_mode_reg (DImode, operands[2]);
++   }")
++
++(define_insn_and_split "xordi3_xor4"
++  [(set (match_operand:DI 0 "nonimmediate_operand"         "=&r,&r,  d,rm,  m, m")
++      (xor:DI (match_operand:DI 1 "nonimmediate_operand"    "%d,rm,  0, 0,  d,rm")
++              (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d,rmI, d,rmI, d")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "#"
++  "reload_completed"
++  [(parallel [(set (match_dup 3)
++                 (xor:SI (match_dup 4)
++                         (match_dup 5)))
++            (clobber (reg:CC CC_REGNO))])
++   (parallel [(set (match_dup 6)
++                 (xor:SI (match_dup 7)
++                         (match_dup 8)))
++            (clobber (reg:CC CC_REGNO))])]
++  "{
++     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" "8")])
++
++(define_insn "not2_2"
++  [(set (match_operand:HI 0 "memory_operand"                  "=m")
++      (subreg:HI
++        (not:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI"))
++        2))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "not.2\\t%0, %1")
++
++(define_insn "one_cmplsi2"
++  [(set (match_operand:SI 0 "nonimmediate_operand"         "=rm")
++      (not:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "not.4\\t%0, %1")
++
++(define_insn "one_cmplsi2_ccwzn"
++  [(set (reg CC_REGNO)
++      (compare
++        (not:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI"))
++        (const_int 0)))
++   (set (match_operand:SI 0 "nonimmediate_operand"           "=rm")
++      (not:SI (match_dup 1)))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "not.4\\t%0, %1")
++
++(define_insn "one_cmplsi2_ccwzn_null"
++  [(set (reg CC_REGNO)
++      (compare
++        (not:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmI"))
++        (const_int 0)))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "not.4\\t#0, %0")
++
++(define_insn_and_split "one_cmpldi2"
++  [(set (match_operand:DI 0 "nonimmediate_operand"       "=&rm")
++      (not:DI (match_operand:DI 1 "nonimmediate_operand" "rmI0")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "#"
++  ""
++  [(parallel [(set (match_dup 2)
++                 (not:SI (match_dup 3)))
++            (clobber (reg:CC CC_REGNO))])
++   (parallel [(set (match_dup 4)
++                 (not:SI (match_dup 5)))
++            (clobber (reg:CC CC_REGNO))])]
++  "{
++     operands[2] = gen_lowpart (SImode, operands[0]);
++     operands[3] = gen_lowpart (SImode, operands[1]);
++     operands[4] = gen_highpart (SImode, operands[0]);
++     operands[5] = gen_highpart (SImode, operands[1]);
++   }"
++  [(set_attr "length" "8")])
++
++; Conditional jump instructions
++
++(define_expand "beq"
++  [(set (pc)
++      (if_then_else (eq (match_dup 1)
++                        (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++  "{
++     operands[1] = ubicom32_gen_compare_reg (EQ, ubicom32_compare_op0,
++                                           ubicom32_compare_op1);
++   }")
++
++(define_expand "bne"
++  [(set (pc)
++      (if_then_else (ne (match_dup 1)
++                        (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++  "{
++     operands[1] = ubicom32_gen_compare_reg (NE, ubicom32_compare_op0,
++                                           ubicom32_compare_op1);
++   }")
++
++(define_expand "bgt"
++  [(set (pc)
++      (if_then_else (gt (match_dup 1)
++                        (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++  "{
++     operands[1] = ubicom32_gen_compare_reg (GT, ubicom32_compare_op0,
++                                           ubicom32_compare_op1);
++   }")
++
++(define_expand "ble"
++  [(set (pc)
++      (if_then_else (le (match_dup 1)
++                        (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++  "{
++     operands[1] = ubicom32_gen_compare_reg (LE, ubicom32_compare_op0,
++                                           ubicom32_compare_op1);
++   }")
++
++(define_expand "bge"
++  [(set (pc)
++      (if_then_else (ge (match_dup 1)
++                        (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++  "{
++     operands[1] = ubicom32_gen_compare_reg (GE, ubicom32_compare_op0,
++                                           ubicom32_compare_op1);
++   }")
++
++(define_expand "blt"
++  [(set (pc)
++      (if_then_else (lt (match_dup 1)
++                        (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++  "{
++     operands[1] = ubicom32_gen_compare_reg (LT, ubicom32_compare_op0,
++                                           ubicom32_compare_op1);
++   }")
++
++(define_expand "bgtu"
++  [(set (pc)
++      (if_then_else (gtu (match_dup 1)
++                         (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++  "{
++     operands[1] = ubicom32_gen_compare_reg (GTU, ubicom32_compare_op0,
++                                           ubicom32_compare_op1);
++   }")
++
++(define_expand "bleu"
++  [(set (pc)
++      (if_then_else (leu (match_dup 1)
++                         (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++  "{
++     operands[1] = ubicom32_gen_compare_reg (LEU, ubicom32_compare_op0,
++                                           ubicom32_compare_op1);
++   }")
++
++(define_expand "bgeu"
++  [(set (pc)
++      (if_then_else (geu (match_dup 1)
++                         (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++  "{
++     operands[1] = ubicom32_gen_compare_reg (GEU, ubicom32_compare_op0,
++                                           ubicom32_compare_op1);
++   }")
++
++(define_expand "bltu"
++  [(set (pc)
++      (if_then_else (ltu (match_dup 1)
++                         (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++  "{
++     operands[1] = ubicom32_gen_compare_reg (LTU, ubicom32_compare_op0,
++                                           ubicom32_compare_op1);
++   }")
++
++(define_insn "jcc"
++  [(set (pc)
++      (if_then_else (match_operator 1 "comparison_operator"
++                      [(match_operand 2 "ubicom32_cc_register_operand" "")
++                       (const_int 0)])
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++  "*
++   {
++     ubicom32_output_cond_jump (insn, operands[1], operands[0]);
++     return \"\";
++   }")
++
++; Reverse branch - reverse our comparison condition so that we can
++; branch in the opposite sense.
++;
++(define_insn_and_split "jcc_reverse"
++  [(set (pc)
++      (if_then_else (match_operator 1 "comparison_operator"
++                      [(match_operand 2 "ubicom32_cc_register_operand" "")
++                       (const_int 0)])
++                    (pc)
++                    (label_ref (match_operand 0 "" ""))))]
++  ""
++  "#"
++  "reload_completed"
++  [(set (pc)
++      (if_then_else (match_dup 3)
++                    (label_ref (match_dup 0))
++                    (pc)))]
++  "{
++     rtx cc_reg;
++
++     cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
++     operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[1])),
++                                 GET_MODE (operands[1]),
++                                 cc_reg,
++                                 const0_rtx);
++   }")
++
++(define_insn "jump"
++  [(set (pc)
++      (label_ref (match_operand 0 "" "")))]
++  ""
++  "jmpt\\t%l0")
++
++(define_expand "indirect_jump"
++  [(parallel [(set (pc)
++                 (match_operand:SI 0 "register_operand" ""))
++            (clobber (match_dup 0))])]
++  ""
++  "")
++
++(define_insn "indirect_jump_internal"
++  [(set (pc)
++      (match_operand:SI 0 "register_operand" "a"))
++  (clobber (match_dup 0))]
++  ""
++  "calli\\t%0,0(%0)")
++
++; Program Space: The table contains instructions, typically jumps. 
++; CALL An,TABLE_SIZE(PC)      ;An = Jump Table Base Address. 
++; <Jump Table is Here>        ;An -> Here. 
++; LEA Ak, (An,Dn)     ;Ak -> Table Entry
++; JMP/CALL (Ak) 
++
++(define_expand "tablejump"
++  [(parallel [(set (pc)
++                 (match_operand:SI 0 "nonimmediate_operand" ""))
++            (use (label_ref (match_operand 1 "" "")))])]
++  ""
++  "")
++
++(define_insn "tablejump_internal"
++  [(set (pc)
++      (match_operand:SI 0 "nonimmediate_operand" "rm"))
++   (use (label_ref (match_operand 1 "" "")))]
++  ""
++  "ret\\t%0")
++
++; Call subroutine with no return value.
++;
++(define_expand "call"
++  [(call (match_operand:QI 0 "general_operand" "")
++       (match_operand:SI 1 "general_operand" ""))]
++  ""
++  "{
++     if (TARGET_FDPIC)
++       {
++       ubicom32_expand_call_fdpic (operands);
++       DONE;
++       }
++
++     if (! ubicom32_call_address_operand (XEXP (operands[0], 0), VOIDmode))
++       XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
++   }")
++
++; We expand to a simple form that doesn't clobber the link register and
++; then split to a form that does.  This allows the RTL optimizers that
++; run before the splitter to have the opportunity to eliminate the call
++; without marking A5 as being clobbered and this in turn avoids saves
++; and returns in a number of cases.
++;
++(define_insn_and_split "call_1"
++  [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
++       (match_operand:SI 1 "general_operand"                       "g,g"))]
++  "! TARGET_FDPIC"
++  "#"
++  ""
++  [(parallel
++     [(call (mem:QI (match_dup 0))
++          (match_dup 1))
++      (clobber (reg:SI LINK_REGNO))])]
++  "")
++
++(define_insn "call_slow"
++  [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
++       (match_operand:SI 1 "general_operand"                       "g,g"))
++   (clobber (reg:SI LINK_REGNO))]
++  "(! TARGET_FDPIC && ! TARGET_FASTCALL)"
++  "@
++   calli\\ta5, 0(%0)
++   moveai\\ta5, #%%hi(%C0)\;calli\\ta5, %%lo(%C0)(a5)")
++
++(define_insn "call_fast"
++  [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
++       (match_operand:SI 1 "general_operand"                       "g,g"))
++   (clobber (reg:SI LINK_REGNO))]
++  "(! TARGET_FDPIC && TARGET_FASTCALL)"
++  "@
++   calli\\ta5, 0(%0)
++   call\\ta5, %C0")
++
++; We expand to a simple form that doesn't clobber the link register and
++; then split to a form that does.  This allows the RTL optimizers that
++; run before the splitter to have the opportunity to eliminate the call
++; without marking A5 as being clobbered and this in turn avoids saves
++; and returns in a number of cases.
++;
++(define_insn_and_split "call_fdpic"
++  [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
++       (match_operand:SI 1 "general_operand"                       "g,g"))
++   (use (match_operand:SI 2 "ubicom32_fdpic_operand"               "Z,Z"))]
++  "TARGET_FDPIC"
++  "#"
++  ""
++  [(parallel
++     [(call (mem:QI (match_dup 0))
++          (match_dup 1))
++      (use (match_dup 2))
++      (clobber (reg:SI LINK_REGNO))])]
++  "")
++
++(define_insn "call_fdpic_clobber"
++  [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
++       (match_operand:SI 1 "general_operand"                       "g,g"))
++   (use (match_operand:SI 2 "ubicom32_fdpic_operand"               "Z,Z"))
++   (clobber (reg:SI LINK_REGNO))]
++  "TARGET_FDPIC"
++  "@
++   move.4\\ta5, 0(%0)\;move.4\\t%2, 4(%0)\;calli\\ta5, 0(a5)
++   call\\ta5, %C0")
++
++; Call subroutine, returning value in operand 0
++; (which must be a hard register).
++;
++(define_expand "call_value"
++  [(set (match_operand 0 "" "")
++      (call (match_operand:QI 1 "general_operand" "")
++            (match_operand:SI 2 "general_operand" "")))]
++  ""
++  "{
++     if (TARGET_FDPIC)
++       {
++       ubicom32_expand_call_value_fdpic (operands);
++       DONE;
++       }
++
++     if (! ubicom32_call_address_operand (XEXP (operands[1], 0), VOIDmode))
++       XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
++   }")
++
++; We expand to a simple form that doesn't clobber the link register and
++; then split to a form that does.  This allows the RTL optimizers that
++; run before the splitter to have the opportunity to eliminate the call
++; without marking A5 as being clobbered and this in turn avoids saves
++; and returns in a number of cases.
++;
++(define_insn_and_split "call_value_1"
++  [(set (match_operand 0 "register_operand"                            "=r,r")
++      (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
++            (match_operand:SI 2 "general_operand"                       "g,g")))]
++  "! TARGET_FDPIC"
++  "#"
++  ""
++  [(parallel
++     [(set (match_dup 0)
++         (call (mem:QI (match_dup 1))
++               (match_dup 2)))
++      (clobber (reg:SI LINK_REGNO))])]
++  "")
++
++(define_insn "call_value_slow"
++  [(set (match_operand 0 "register_operand"                            "=r,r")
++      (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
++            (match_operand:SI 2 "general_operand"                       "g,g")))
++   (clobber (reg:SI LINK_REGNO))]
++  "(! TARGET_FDPIC && ! TARGET_FASTCALL)"
++  "@
++   calli\\ta5, 0(%1)
++   moveai\\ta5, #%%hi(%C1)\;calli\\ta5, %%lo(%C1)(a5)")
++
++(define_insn "call_value_fast"
++  [(set (match_operand 0 "register_operand"                            "=r,r")
++      (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
++            (match_operand:SI 2 "general_operand"                       "g,g")))
++   (clobber (reg:SI LINK_REGNO))]
++  "(! TARGET_FDPIC && TARGET_FASTCALL)"
++  "@
++   calli\\ta5, 0(%1)
++   call\\ta5, %C1")
++
++; We expand to a simple form that doesn't clobber the link register and
++; then split to a form that does.  This allows the RTL optimizers that
++; run before the splitter to have the opportunity to eliminate the call
++; without marking A5 as being clobbered and this in turn avoids saves
++; and returns in a number of cases.
++;
++(define_insn_and_split "call_value_fdpic"
++  [(set (match_operand 0 "register_operand"                            "=r,r")
++      (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
++            (match_operand:SI 2 "general_operand"                       "g,g")))
++   (use (match_operand:SI 3 "ubicom32_fdpic_operand"                    "Z,Z"))]
++  "TARGET_FDPIC"
++  "#"
++  ""
++  [(parallel
++     [(set (match_dup 0)
++         (call (mem:QI (match_dup 1))
++               (match_dup 2)))
++      (use (match_dup 3))
++      (clobber (reg:SI LINK_REGNO))])]
++  "")
++
++(define_insn "call_value_fdpic_clobber"
++  [(set (match_operand 0 "register_operand"                            "=r,r")
++      (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
++            (match_operand:SI 2 "general_operand"                       "g,g")))
++   (use (match_operand:SI 3 "ubicom32_fdpic_operand"                    "Z,Z"))
++   (clobber (reg:SI LINK_REGNO))]
++  "TARGET_FDPIC"
++  "@
++   move.4\\ta5, 0(%1)\;move.4\\t%3, 4(%1)\;calli\\ta5, 0(a5)
++   call\\ta5, %C1")
++
++(define_expand "untyped_call"
++  [(parallel [(call (match_operand 0 "" "")
++                    (const_int 0))
++              (match_operand 1 "" "")
++              (match_operand 2 "" "")])]
++  ""
++  "{
++     int i;
++
++     emit_call_insn (gen_call (operands[0], const0_rtx));
++
++     for (i = 0; i < XVECLEN (operands[2], 0); i++)
++       {
++         rtx set = XVECEXP (operands[2], 0, i);
++         emit_move_insn (SET_DEST (set), SET_SRC (set));
++       }
++     DONE;
++   }")
++
++(define_insn "lsl1_1"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
++      (ashift:SI (subreg:SI
++                   (match_operand:QI 1 "memory_operand"         "m")
++                   0)
++                 (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
++   (clobber (reg:CC CC_REGNO))]
++  "(ubicom32_v4)"
++  "lsl.1\\t%0, %1, %2")
++
++; The combiner gets rather creative about left shifts of sub-word memory
++; operands because it's uncertain about whether the memory is sign or
++; zero extended.  It only wants zero-extended behaviour and so throws
++; in an extra and operation.
++;
++(define_insn "lsl1_2"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
++      (and:SI
++        (ashift:SI (subreg:SI
++                     (match_operand:QI 1 "memory_operand"   "m")
++                     0)
++                   (match_operand:SI 2 "const_int_operand"  "M"))
++        (match_operand:SI 3 "const_int_operand"             "n")))
++   (clobber (reg:CC CC_REGNO))]
++  "(ubicom32_v4
++    && INTVAL (operands[3]) == (0xff << INTVAL (operands[2])))"
++  "lsl.1\\t%0, %1, %2")
++
++(define_insn "lsl2_1"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
++      (ashift:SI (subreg:SI
++                   (match_operand:HI 1 "memory_operand"         "m")
++                   0)
++                 (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
++   (clobber (reg:CC CC_REGNO))]
++  "(ubicom32_v4)"
++  "lsl.2\\t%0, %1, %2")
++
++; The combiner gets rather creative about left shifts of sub-word memory
++; operands because it's uncertain about whether the memory is sign or
++; zero extended.  It only wants zero-extended behaviour and so throws
++; in an extra and operation.
++;
++(define_insn "lsl2_2"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
++      (and:SI
++        (ashift:SI (subreg:SI
++                     (match_operand:HI 1 "memory_operand"   "m")
++                     0)
++                   (match_operand:SI 2 "const_int_operand"  "M"))
++        (match_operand:SI 3 "const_int_operand"             "n")))
++   (clobber (reg:CC CC_REGNO))]
++  "(ubicom32_v4
++    && INTVAL (operands[3]) == (0xffff << INTVAL (operands[2])))"
++  "lsl.2\\t%0, %1, %2")
++
++(define_insn "ashlsi3"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
++      (ashift:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
++                 (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "lsl.4\\t%0, %1, %2")
++
++(define_insn "lshlsi3_ccwz"
++  [(set (reg CC_REGNO)
++      (compare
++        (ashift:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
++                   (match_operand:SI 2 "ubicom32_arith_operand"  "dM"))
++        (const_int 0)))
++   (set (match_operand:SI 0 "ubicom32_data_register_operand"     "=d")
++      (ashift:SI (match_dup 1)
++                 (match_dup 2)))]
++  "ubicom32_match_cc_mode(insn, CCWZmode)"
++  "lsl.4\\t%0, %1, %2")
++
++(define_insn "lshlsi3_ccwz_null"
++  [(set (reg CC_REGNO)
++      (compare
++        (ashift:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmI")
++                   (match_operand:SI 1 "ubicom32_arith_operand"  "dM"))
++        (const_int 0)))
++   (clobber (match_scratch:SI 2                                          "=d"))]
++  "ubicom32_match_cc_mode(insn, CCWZmode)"
++  "lsl.4\\t%2, %0, %1")
++
++; The combiner finds this canonical form for what is in essence a right
++; shift.
++;
++(define_insn "asr1_2"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
++      (sign_extract:SI (match_operand:QI 1 "memory_operand"     "m")
++                       (match_operand:SI 2 "const_int_operand"  "M")
++                       (match_operand:SI 3 "const_int_operand"  "M")))
++   (clobber (reg:CC CC_REGNO))]
++  "(ubicom32_v4
++    && (INTVAL (operands[2]) + INTVAL (operands[3]) == 8))"
++  "asr.1\\t%0, %1, %3")
++
++; The combiner finds this canonical form for what is in essence a right
++; shift.
++;
++(define_insn "asr2_2"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
++      (sign_extract:SI (match_operand:HI 1 "memory_operand"     "m")
++                       (match_operand:SI 2 "const_int_operand"  "M")
++                       (match_operand:SI 3 "const_int_operand"  "M")))
++   (clobber (reg:CC CC_REGNO))]
++  "(ubicom32_v4
++    && (INTVAL (operands[2]) + INTVAL (operands[3]) == 16))"
++  "asr.2\\t%0, %1, %3")
++
++(define_insn "ashrsi3"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand"     "=d")
++      (ashiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmJ")
++                   (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "asr.4\\t%0, %1, %2")
++
++(define_insn "ashrsi3_ccwzn"
++  [(set (reg CC_REGNO)
++      (compare
++        (ashiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmJ")
++                     (match_operand:SI 2 "ubicom32_arith_operand"  "dM"))
++        (const_int 0)))
++   (set (match_operand:SI 0 "ubicom32_data_register_operand"       "=d")
++      (ashiftrt:SI (match_dup 1)
++                   (match_dup 2)))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "asr.4\\t%0, %1, %2")
++
++(define_insn "ashrsi3_ccwzn_null"
++  [(set (reg CC_REGNO)
++      (compare
++        (ashiftrt:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmJ")
++                     (match_operand:SI 1 "ubicom32_arith_operand"  "dM"))
++        (const_int 0)))
++   (clobber (match_scratch:SI 2                                            "=d"))]
++  "ubicom32_match_cc_mode(insn, CCWZNmode)"
++  "asr.4\\t%2, %0, %1")
++
++(define_insn "lsr1_1"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
++      (lshiftrt:SI (subreg:SI
++                     (match_operand:QI 1 "memory_operand"       "m")
++                     0)
++                 (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
++   (clobber (reg:CC CC_REGNO))]
++  "(ubicom32_v4)"
++  "lsr.1\\t%0, %1, %2")
++
++; The combiner finds this canonical form for what is in essence a right
++; shift.
++;
++(define_insn "lsr1_2"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
++      (zero_extract:SI (match_operand:QI 1 "memory_operand"     "m")
++                       (match_operand:SI 2 "const_int_operand"  "M")
++                       (match_operand:SI 3 "const_int_operand"  "M")))
++   (clobber (reg:CC CC_REGNO))]
++  "(ubicom32_v4
++    && (INTVAL (operands[2]) + INTVAL (operands[3]) == 8))"
++  "lsr.1\\t%0, %1, %3")
++
++(define_insn "lsr2_1"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
++      (lshiftrt:SI (subreg:SI
++                     (match_operand:HI 1 "memory_operand"       "m")
++                     0)
++                 (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
++   (clobber (reg:CC CC_REGNO))]
++  "(ubicom32_v4)"
++  "lsr.2\\t%0, %1, %2")
++
++; The combiner finds this canonical form for what is in essence a right
++; shift.
++;
++(define_insn "lsr2_2"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
++      (zero_extract:SI (match_operand:HI 1 "memory_operand"     "m")
++                       (match_operand:SI 2 "const_int_operand"  "M")
++                       (match_operand:SI 3 "const_int_operand"  "M")))
++   (clobber (reg:CC CC_REGNO))]
++  "(ubicom32_v4
++    && (INTVAL (operands[2]) + INTVAL (operands[3]) == 16))"
++  "lsr.2\\t%0, %1, %3")
++
++(define_insn "lshrsi3"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand"     "=d")
++      (lshiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
++                   (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "lsr.4\\t%0, %1, %2")
++
++(define_insn "lshrsi3_ccwz"
++  [(set (reg CC_REGNO)
++      (compare
++        (lshiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
++                     (match_operand:SI 2 "ubicom32_arith_operand"  "dM"))
++        (const_int 0)))
++   (set (match_operand:SI 0 "ubicom32_data_register_operand"       "=d")
++      (lshiftrt:SI (match_dup 1)
++                   (match_dup 2)))]
++  "ubicom32_match_cc_mode(insn, CCWZmode)"
++  "lsr.4\\t%0, %1, %2")
++
++(define_insn "lshrsi3_ccwz_null"
++  [(set (reg CC_REGNO)
++      (compare
++        (lshiftrt:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmI")
++                     (match_operand:SI 1 "ubicom32_arith_operand"  "dM"))
++        (const_int 0)))
++   (clobber (match_scratch:SI 2                                            "=d"))]
++  "ubicom32_match_cc_mode(insn, CCWZmode)"
++  "lsr.4\\t%2, %0, %1")
++
++(define_expand "prologue"
++  [(const_int 0)]
++  ""
++  "{
++     ubicom32_expand_prologue ();
++     DONE;
++   }")
++
++(define_expand "epilogue"
++  [(return)]
++  ""
++  "{
++     ubicom32_expand_epilogue ();
++     DONE;
++   }")
++
++(define_expand "return"
++  [(return)]
++  ""
++  "{
++     ubicom32_expand_epilogue ();
++     DONE;
++   }")
++
++(define_expand "_eh_return"
++  [(use (match_operand:SI 0 "register_operand" "r"))
++   (use (match_operand:SI 1 "register_operand" "r"))]
++  ""
++  "{
++     ubicom32_expand_eh_return (operands);
++     DONE;
++   }")
++
++; XXX - it looks almost certain that we could make return_internal use a Dn
++; register too.  In that instance we'd have to use a ret instruction
++; rather than a calli but it might save cycles.
++;
++(define_insn "return_internal"
++  [(const_int 2)
++   (return)
++   (use (match_operand:SI 0 "ubicom32_mem_or_address_register_operand" "rm"))]
++  ""
++  "*
++   {
++     if (REG_P (operands[0]) && REGNO (operands[0]) == LINK_REGNO
++       && ubicom32_can_use_calli_to_ret)
++       return \"calli\\t%0, 0(%0)\";
++
++     return \"ret\\t%0\";
++   }")
++
++(define_insn "return_from_post_modify_sp"
++  [(parallel
++     [(const_int 2)
++      (return)
++      (use (mem:SI (post_modify:SI
++                   (reg:SI SP_REGNO)
++                   (plus:SI (reg:SI SP_REGNO)
++                            (match_operand:SI 0 "const_int_operand" "n")))))])]
++  "INTVAL (operands[0]) >= 4 && INTVAL (operands[0]) <= 7 * 4"
++  "ret\\t(sp)%E0++")
++
++;(define_insn "eh_return_internal"
++;  [(const_int 4)
++;   (return)
++;   (use (reg:SI 34))]
++;  ""
++;  "ret\\ta2")
++
++; No operation, needed in case the user uses -g but not -O.
++(define_expand "nop"
++  [(const_int 0)]
++  ""
++  "")
++
++(define_insn "nop_internal"
++  [(const_int 0)]
++  ""
++  "nop")
++
++; The combiner will generate this pattern given shift and add operations.
++; The canonical form that the combiner wants to use appears to be multiplies
++; instead of shifts even if the compiled sources use shifts.
++;
++(define_insn "shmrg1_add"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand"         "=d")
++      (plus:SI
++        (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
++                 (const_int 256))
++        (zero_extend:SI
++          (match_operand:QI 2 "ubicom32_arith_operand"              "rmI"))))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "shmrg.1\\t%0, %2, %1")
++
++; The combiner will generate this pattern given shift and or operations.
++;
++(define_insn "shmrg1_ior"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand"           "=d")
++      (ior:SI
++        (ashift:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
++                   (const_int 8))
++        (zero_extend:SI
++          (match_operand:QI 2 "ubicom32_arith_operand"                "rmI"))))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "shmrg.1\\t%0, %2, %1")
++
++; The combiner will generate this pattern given shift and add operations.
++; The canonical form that the combiner wants to use appears to be multiplies
++; instead of shifts even if the compiled sources use shifts.
++;
++(define_insn "shmrg2_add"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand"         "=d")
++      (plus:SI
++        (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
++                 (const_int 65536))
++        (zero_extend:SI
++          (match_operand:HI 2 "ubicom32_arith_operand"              "rmI"))))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "shmrg.2\\t%0, %2, %1")
++
++; The combiner will generate this pattern given shift and or operations.
++;
++(define_insn "shmrg2_ior"
++  [(set (match_operand:SI 0 "ubicom32_data_register_operand"           "=d")
++      (ior:SI
++        (ashift:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
++                   (const_int 16))
++        (zero_extend:SI
++          (match_operand:HI 2 "ubicom32_arith_operand"                "rmI"))))
++   (clobber (reg:CC CC_REGNO))]
++  ""
++  "shmrg.2\\t%0, %2, %1")
++
++; Match the case where we load a word from the stack but then discard the
++; upper 16 bits.  We turn this into a zero-extended load of that useful
++; 16 bits direct from the stack where possible.
++;
++
++; XXX - do these peephole2 ops actually work after the CCmode conversion?
++(define_peephole2
++  [(set (match_operand:SI 0 "register_operand" "")
++      (mem:SI (plus:SI (reg:SI SP_REGNO)
++                       (match_operand:SI 1 "const_int_operand" ""))))
++   (set (match_operand:SI 2 "nonimmediate_operand" "")
++      (zero_extend:SI (match_operand:HI 3 "register_operand" "")))]
++  "(INTVAL (operands[1]) <= 252
++    && REGNO (operands[3]) == REGNO (operands[0])
++    && ((peep2_reg_dead_p (2, operands[0])
++       && ! reg_mentioned_p (operands[0], operands[2]))
++        || rtx_equal_p (operands[0], operands[2])))"
++  [(set (match_dup 2)
++      (zero_extend:SI (mem:HI (plus:SI (reg:SI SP_REGNO)
++                                       (match_dup 4)))))]
++  "{
++     operands[4] = GEN_INT (INTVAL (operands[1]) + 2);
++   }")
++
++; Match the case where we load a word from the stack but then discard the
++; upper 16 bits.  We turn this into a 16-bit load of that useful
++; 16 bits direct from the stack where possible.
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "register_operand" "")
++      (mem:SI (plus:SI (reg:SI SP_REGNO)
++                       (match_operand:SI 1 "const_int_operand" ""))))
++   (set (match_operand:HI 2 "nonimmediate_operand" "")
++      (match_operand:HI 3 "register_operand" ""))]
++  "(INTVAL (operands[1]) <= 252
++    && REGNO (operands[3]) == REGNO (operands[0])
++    && ((peep2_reg_dead_p (2, operands[0])
++       && ! reg_mentioned_p (operands[0], operands[2]))
++        || rtx_equal_p (operands[0], operands[2])))"
++  [(set (match_dup 2)
++      (mem:HI (plus:SI (reg:SI SP_REGNO)
++                       (match_dup 4))))]
++  "{
++     operands[4] = GEN_INT (INTVAL (operands[1]) + 2);
++   }")
++
++; Match the case where we load a word from the stack but then discard the
++; upper 24 bits.  We turn this into a zero-extended load of that useful
++; 8 bits direct from the stack where possible.
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "register_operand" "")
++      (mem:SI (plus:SI (reg:SI SP_REGNO)
++                       (match_operand:SI 1 "const_int_operand" ""))))
++   (set (match_operand:SI 2 "nonimmediate_operand" "")
++      (zero_extend:SI (match_operand:QI 3 "register_operand" "")))]
++  "(INTVAL (operands[1]) <= 124
++    && REGNO (operands[3]) == REGNO (operands[0])
++    && ((peep2_reg_dead_p (2, operands[0])
++       && ! reg_mentioned_p (operands[0], operands[2]))
++        || rtx_equal_p (operands[0], operands[2])))"
++  [(set (match_dup 2)
++      (zero_extend:SI (mem:QI (plus:SI (reg:SI SP_REGNO)
++                                       (match_dup 4)))))]
++  "{
++     operands[4] = GEN_INT (INTVAL (operands[1]) + 3);
++   }")
++
++; Match the case where we load a word from the stack but then discard the
++; upper 24 bits.  We turn this into an 8-bit load of that useful
++; 8 bits direct from the stack where possible.
++;
++(define_peephole2
++  [(set (match_operand:SI 0 "register_operand" "")
++      (mem:SI (plus:SI (reg:SI SP_REGNO)
++                       (match_operand:SI 1 "const_int_operand" ""))))
++   (set (match_operand:QI 2 "nonimmediate_operand" "")
++      (match_operand:QI 3 "register_operand" ""))]
++  "(INTVAL (operands[1]) <= 124
++    && REGNO (operands[3]) == REGNO (operands[0])
++    && ((peep2_reg_dead_p (2, operands[0])
++       && ! reg_mentioned_p (operands[0], operands[2]))
++        || rtx_equal_p (operands[0], operands[2])))"
++  [(set (match_dup 2)
++      (mem:QI (plus:SI (reg:SI SP_REGNO)
++                       (match_dup 4))))]
++  "{
++     operands[4] = GEN_INT (INTVAL (operands[1]) + 3);
++   }")
++
+--- /dev/null
++++ b/gcc/config/ubicom32/ubicom32.opt
+@@ -0,0 +1,27 @@
++mdebug-address
++Target RejectNegative Report Undocumented Mask(DEBUG_ADDRESS)
++Debug addresses
++
++mdebug-context
++Target RejectNegative Report Undocumented Mask(DEBUG_CONTEXT)
++Debug contexts
++
++march=
++Target Report Var(ubicom32_arch_name) Init("ubicom32v4") Joined
++Specify the name of the target architecture
++
++mfdpic
++Target Report Mask(FDPIC)
++Enable Function Descriptor PIC mode
++
++minline-plt
++Target Report Mask(INLINE_PLT)
++Enable inlining of PLT in function calls
++
++mfastcall
++Target Report Mask(FASTCALL)
++Enable default fast (call) calling sequence for smaller applications
++
++mipos-abi
++Target Report Mask(IPOS_ABI)
++Enable the ipOS ABI in which D10-D13 are caller-clobbered
+--- /dev/null
++++ b/gcc/config/ubicom32/uclinux.h
+@@ -0,0 +1,67 @@
++/* Definitions of target machine for Ubicom32-uclinux
++
++   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
++   2009 Free Software Foundation, Inc.
++   Contributed by Ubicom, Inc.
++
++   This file is part of GCC.
++
++   GCC is free software; you can redistribute it and/or modify it
++   under the terms of the GNU General Public License as published
++   by the Free Software Foundation; either version 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/>.  */
++
++/* Don't assume anything about the header files.  */
++#define NO_IMPLICIT_EXTERN_C
++
++#undef  LIB_SPEC
++#define LIB_SPEC  \
++      "%{pthread:-lpthread} " \
++      "%{!shared:%{!symbolic: -lc}} "
++
++
++#undef LINK_GCC_C_SEQUENCE_SPEC
++#define LINK_GCC_C_SEQUENCE_SPEC \
++  "%{!shared:--start-group} %G %L %{!shared:--end-group}%{shared:%G} "
++
++#undef STARTFILE_SPEC
++#define STARTFILE_SPEC \
++      "%{!shared: crt1%O%s}" \
++      " crti%O%s crtbegin%O%s"
++
++#undef ENDFILE_SPEC
++#define ENDFILE_SPEC "crtend%O%s crtn%O%s"
++
++/* This macro applies on top of OBJECT_FORMAT_ELF and indicates that
++   we want to support both flat and ELF output.  */
++#define OBJECT_FORMAT_FLAT
++
++#undef DRIVER_SELF_SPECS
++#define DRIVER_SELF_SPECS \
++  "%{!mno-fastcall:-mfastcall}"
++
++/* taken from linux.h */
++/* The GNU C++ standard library requires that these macros be defined.  */
++#undef CPLUSPLUS_CPP_SPEC
++#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
++
++#define TARGET_OS_CPP_BUILTINS()                              \
++    do {                                                      \
++      builtin_define_std ("__UBICOM32__");                    \
++      builtin_define_std ("__ubicom32__");                    \
++      builtin_define ("__gnu_linux__");                       \
++      builtin_define_std ("linux");                           \
++      builtin_define_std ("unix");                            \
++      builtin_assert ("system=linux");                        \
++      builtin_assert ("system=unix");                         \
++      builtin_assert ("system=posix");                        \
++    } while (0)
+--- /dev/null
++++ b/gcc/config/ubicom32/xm-ubicom32.h
+@@ -0,0 +1,36 @@
++/* Configuration for Ubicom's Ubicom32 architecture.
++   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software
++   Foundation, Inc.
++   Contributed by Ubicom Inc.
++
++This file is part of GNU CC.
++
++GNU CC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 2, or (at your option)
++any later version.
++
++GNU CC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GNU CC; see the file COPYING.  If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA.  */
++
++/* #defines that need visibility everywhere.  */
++#define FALSE 0
++#define TRUE 1
++
++/* This describes the machine the compiler is hosted on.  */
++#define HOST_BITS_PER_CHAR 8
++#define HOST_BITS_PER_SHORT 16
++#define HOST_BITS_PER_INT 32
++#define HOST_BITS_PER_LONG 32
++#define HOST_BITS_PER_LONGLONG 64
++
++/* Arguments to use with `exit'.  */
++#define SUCCESS_EXIT_CODE 0
++#define FATAL_EXIT_CODE 33
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -2662,6 +2662,34 @@ spu-*-elf*)
+       c_target_objs="${c_target_objs} spu-c.o"
+       cxx_target_objs="${cxx_target_objs} spu-c.o"
+       ;;
++ubicom32-*-elf)
++      xm_file=ubicom32/xm-ubicom32.h
++      tm_file="${tm_file} ubicom32/elf.h" # still need dbxelf.h elfos.h
++      tmake_file=ubicom32/t-ubicom32
++      ;;
++ubicom32-*-uclinux*)
++      xm_file=ubicom32/xm-ubicom32.h
++      tm_file="${tm_file} ubicom32/elf.h ubicom32/uclinux.h"  # still need dbxelf.h elfos.h linux.h
++      tm_defines="${tm_defines} UCLIBC_DEFAULT=1"
++      extra_options="${extra_options} linux.opt"
++      tmake_file=ubicom32/t-ubicom32-uclinux
++      use_collect2=no
++      ;;
++ubicom32-*-linux-uclibc)
++      xm_file=ubicom32/xm-ubicom32.h
++      tm_file="${tm_file} ubicom32/elf.h linux.h ubicom32/linux.h"  # still need dbxelf.h elfos.h
++      tmake_file="t-slibgcc-elf-ver ubicom32/t-ubicom32-linux"
++      extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
++      use_collect2=no
++      ;;
++ubicom32-*-linux*)
++      xm_file=ubicom32/xm-ubicom32.h
++      tm_file="${tm_file} ubicom32/elf.h linux.h ubicom32/linux.h"  # still need dbxelf.h elfos.h
++      tmake_file="t-slibgcc-elf-ver ubicom32/t-ubicom32-linux"
++      tm_defines="${tm_defines} UCLIBC_DEFAULT=1"
++      extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
++      use_collect2=no
++      ;;
+ v850e1-*-*)
+       target_cpu_default="TARGET_CPU_v850e1"
+       tm_file="dbxelf.h elfos.h newlib-stdint.h v850/v850.h"
+--- a/libgcc/config.host
++++ b/libgcc/config.host
+@@ -572,6 +572,15 @@ sparc64-*-netbsd*)
+       ;;
+ spu-*-elf*)
+       ;;
++ubicom32*-*-elf*)
++      ;;
++ubicom32*-*-uclinux*)
++        ;;
++ubicom32*-*-linux*)
++      # No need to build crtbeginT.o on uClibc systems.  Should probably
++      # be moved to the OS specific section above.
++      extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
++        ;;
+ v850e1-*-*)
+       ;;
+ v850e-*-*)
diff --git a/toolchain/gcc/patches/4.6.1/810-arm-softfloat-libgcc.patch b/toolchain/gcc/patches/4.6.1/810-arm-softfloat-libgcc.patch
new file mode 100644 (file)
index 0000000..60cfde4
--- /dev/null
@@ -0,0 +1,26 @@
+--- a/gcc/config/arm/linux-elf.h
++++ b/gcc/config/arm/linux-elf.h
+@@ -60,7 +60,7 @@
+    %{shared:-lc} \
+    %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
+-#define LIBGCC_SPEC "%{msoft-float:-lfloat} %{mfloat-abi=soft*:-lfloat} -lgcc"
++#define LIBGCC_SPEC "-lgcc"
+ #define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
+--- a/gcc/config/arm/t-linux
++++ b/gcc/config/arm/t-linux
+@@ -23,7 +23,11 @@ TARGET_LIBGCC2_CFLAGS = -fomit-frame-poi
+ LIB1ASMSRC = arm/lib1funcs.asm
+ LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx _clzsi2 _clzdi2 \
+-      _arm_addsubdf3 _arm_addsubsf3
++      _arm_addsubdf3 _arm_addsubsf3 \
++      _arm_negdf2 _arm_muldivdf3 _arm_cmpdf2 _arm_unorddf2 \
++      _arm_fixdfsi _arm_fixunsdfsi _arm_truncdfsf2 \
++      _arm_negsf2 _arm_muldivsf3 _arm_cmpsf2 _arm_unordsf2 \
++      _arm_fixsfsi _arm_fixunssfsi
+ # MULTILIB_OPTIONS = mhard-float/msoft-float
+ # MULTILIB_DIRNAMES = hard-float soft-float
diff --git a/toolchain/gcc/patches/4.6.1/820-libgcc_pic.patch b/toolchain/gcc/patches/4.6.1/820-libgcc_pic.patch
new file mode 100644 (file)
index 0000000..3760ac2
--- /dev/null
@@ -0,0 +1,36 @@
+--- a/libgcc/Makefile.in
++++ b/libgcc/Makefile.in
+@@ -747,11 +747,12 @@ $(libgcov-objects): %$(objext): $(gcc_sr
+ # Static libraries.
+ libgcc.a: $(libgcc-objects)
++libgcc_pic.a: $(libgcc-s-objects)
+ libgcov.a: $(libgcov-objects)
+ libunwind.a: $(libunwind-objects)
+ libgcc_eh.a: $(libgcc-eh-objects)
+-libgcc.a libgcov.a libunwind.a libgcc_eh.a:
++libgcc.a libgcov.a libunwind.a libgcc_eh.a libgcc_pic.a:
+       -rm -f $@
+       objects="$(objects)";                                   \
+@@ -773,7 +774,7 @@ libgcc_s$(SHLIB_EXT): libunwind$(SHLIB_E
+ endif
+ ifeq ($(enable_shared),yes)
+-all: libgcc_eh.a libgcc_s$(SHLIB_EXT)
++all: libgcc_eh.a libgcc_pic.a libgcc_s$(SHLIB_EXT)
+ ifneq ($(LIBUNWIND),)
+ all: libunwind$(SHLIB_EXT)
+ endif
+@@ -954,6 +955,10 @@ install-shared:
+       chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_eh.a
+       $(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_eh.a
++      $(INSTALL_DATA) libgcc_pic.a $(mapfile) $(DESTDIR)$(inst_libdir)/
++      chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_pic.a
++      $(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_pic.a
++
+       $(subst @multilib_dir@,$(MULTIDIR),$(subst \
+               @shlib_base_name@,libgcc_s,$(subst \
+               @shlib_slibdir_qual@,$(MULTIOSSUBDIR),$(SHLIB_INSTALL))))
diff --git a/toolchain/gcc/patches/4.6.1/830-arm_unbreak_armv4t.patch b/toolchain/gcc/patches/4.6.1/830-arm_unbreak_armv4t.patch
new file mode 100644 (file)
index 0000000..37f8f2a
--- /dev/null
@@ -0,0 +1,13 @@
+http://sourceware.org/ml/crossgcc/2008-05/msg00009.html
+
+--- a/gcc/config/arm/linux-eabi.h
++++ b/gcc/config/arm/linux-eabi.h
+@@ -45,7 +45,7 @@
+    The ARM10TDMI core is the default for armv5t, so set
+    SUBTARGET_CPU_DEFAULT to achieve this.  */
+ #undef  SUBTARGET_CPU_DEFAULT
+-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm10tdmi
++#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm9tdmi
+ /* TARGET_BIG_ENDIAN_DEFAULT is set in
+    config.gcc for big endian configurations.  */
diff --git a/toolchain/gcc/patches/4.6.1/840-armv4_pass_fix-v4bx_to_ld.patch b/toolchain/gcc/patches/4.6.1/840-armv4_pass_fix-v4bx_to_ld.patch
new file mode 100644 (file)
index 0000000..e5a26c1
--- /dev/null
@@ -0,0 +1,20 @@
+--- a/gcc/config/arm/linux-eabi.h
++++ b/gcc/config/arm/linux-eabi.h
+@@ -64,12 +64,16 @@
+ #undef  GLIBC_DYNAMIC_LINKER
+ #define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.3"
++/* For armv4 we pass --fix-v4bx to linker to support EABI */
++#undef TARGET_FIX_V4BX_SPEC
++#define TARGET_FIX_V4BX_SPEC " %{mcpu=arm8|mcpu=arm810|mcpu=strongarm*|march=armv4:--fix-v4bx}"
++
+ /* At this point, bpabi.h will have clobbered LINK_SPEC.  We want to
+    use the GNU/Linux version, not the generic BPABI version.  */
+ #undef  LINK_SPEC
+ #define LINK_SPEC BE8_LINK_SPEC                                               \
+   LINUX_OR_ANDROID_LD (LINUX_TARGET_LINK_SPEC,                                \
+-                     LINUX_TARGET_LINK_SPEC " " ANDROID_LINK_SPEC)
++                     LINUX_TARGET_LINK_SPEC " " ANDROID_LINK_SPEC)    \
+ #undef  CC1_SPEC
+ #define CC1_SPEC                                                      \
diff --git a/toolchain/gcc/patches/4.6.1/910-mbsd_multi.patch b/toolchain/gcc/patches/4.6.1/910-mbsd_multi.patch
new file mode 100644 (file)
index 0000000..5a1adc9
--- /dev/null
@@ -0,0 +1,253 @@
+
+       This patch brings over a few features from MirBSD:
+       * -fhonour-copts
+         If this option is not given, it's warned (depending
+         on environment variables). This is to catch errors
+         of misbuilt packages which override CFLAGS themselves.
+       * -Werror-maybe-reset
+         Has the effect of -Wno-error if GCC_NO_WERROR is
+         set and not '0', a no-operation otherwise. This is
+         to be able to use -Werror in "make" but prevent
+         GNU autoconf generated configure scripts from
+         freaking out.
+       * Make -fno-strict-aliasing and -fno-delete-null-pointer-checks
+         the default for -O2/-Os, because they trigger gcc bugs
+         and can delete code with security implications.
+
+       This patch was authored by Thorsten Glaser <tg at mirbsd.de>
+       with copyright assignment to the FSF in effect.
+
+--- a/gcc/c-family/c-opts.c
++++ b/gcc/c-family/c-opts.c
+@@ -103,6 +103,9 @@ static size_t deferred_count;
+ /* Number of deferred options scanned for -include.  */
+ static size_t include_cursor;
++/* Check if a port honours COPTS.  */
++static int honour_copts = 0;
++
+ static void handle_OPT_d (const char *);
+ static void set_std_cxx98 (int);
+ static void set_std_cxx0x (int);
+@@ -441,6 +444,9 @@ c_common_handle_option (size_t scode, co
+       global_dc->warning_as_error_requested = value;
+       break;
++    case OPT_Werror_maybe_reset:
++      break;
++
+     case OPT_Wformat:
+       set_Wformat (value);
+       break;
+@@ -584,6 +590,12 @@ c_common_handle_option (size_t scode, co
+       flag_no_builtin = !value;
+       break;
++    case OPT_fhonour_copts:
++      if (c_language == clk_c) {
++        honour_copts++;
++      }
++      break;
++
+     case OPT_fconstant_string_class_:
+       constant_string_class_name = arg;
+       break;
+@@ -1058,6 +1070,47 @@ c_common_init (void)
+       return false;
+     }
++  if (c_language == clk_c) {
++    char *ev = getenv ("GCC_HONOUR_COPTS");
++    int evv;
++    if (ev == NULL)
++      evv = -1;
++    else if ((*ev == '0') || (*ev == '\0'))
++      evv = 0;
++    else if (*ev == '1')
++      evv = 1;
++    else if (*ev == '2')
++      evv = 2;
++    else if (*ev == 's')
++      evv = -1;
++    else {
++      warning (0, "unknown GCC_HONOUR_COPTS value, assuming 1");
++      evv = 1; /* maybe depend this on something like MIRBSD_NATIVE?  */
++    }
++    if (evv == 1) {
++      if (honour_copts == 0) {
++        error ("someone does not honour COPTS at all in lenient mode");
++        return false;
++      } else if (honour_copts != 1) {
++        warning (0, "someone does not honour COPTS correctly, passed %d times",
++         honour_copts);
++      }
++    } else if (evv == 2) {
++      if (honour_copts == 0) {
++        error ("someone does not honour COPTS at all in strict mode");
++        return false;
++      } else if (honour_copts != 1) {
++        error ("someone does not honour COPTS correctly, passed %d times",
++         honour_copts);
++        return false;
++      }
++    } else if (evv == 0) {
++      if (honour_copts != 1)
++        inform (0, "someone does not honour COPTS correctly, passed %d times",
++         honour_copts);
++    }
++  }
++
+   return true;
+ }
+--- a/gcc/c-family/c.opt
++++ b/gcc/c-family/c.opt
+@@ -363,6 +363,10 @@ Werror-implicit-function-declaration
+ C ObjC RejectNegative Warning Alias(Werror=, implicit-function-declaration)
+ This switch is deprecated; use -Werror=implicit-function-declaration instead
++Werror-maybe-reset
++C ObjC C++ ObjC++
++; Documented in common.opt
++
+ Wfloat-equal
+ C ObjC C++ ObjC++ Var(warn_float_equal) Warning
+ Warn if testing floating point numbers for equality
+@@ -794,6 +798,9 @@ C++ ObjC++ Optimization Alias(fexception
+ fhonor-std
+ C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
++fhonour-copts
++C ObjC C++ ObjC++ RejectNegative
++
+ fhosted
+ C ObjC
+ Assume normal C execution environment
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -520,6 +520,10 @@ Werror=
+ Common Joined
+ Treat specified warning as error
++Werror-maybe-reset
++Common
++If environment variable GCC_NO_WERROR is set, act as -Wno-error
++
+ Wextra
+ Common Var(extra_warnings) Warning
+ Print extra (possibly unwanted) warnings
+@@ -1156,6 +1160,9 @@ fguess-branch-probability
+ Common Report Var(flag_guess_branch_prob) Optimization
+ Enable guessing of branch probabilities
++fhonour-copts
++Common RejectNegative
++
+ ; Nonzero means ignore `#ident' directives.  0 means handle them.
+ ; Generate position-independent code for executables if possible
+ ; On SVR4 targets, it also controls whether or not to emit a
+--- a/gcc/opts.c
++++ b/gcc/opts.c
+@@ -477,8 +477,6 @@ static const struct default_options defa
+     { OPT_LEVELS_2_PLUS, OPT_fschedule_insns2, NULL, 1 },
+ #endif
+     { OPT_LEVELS_2_PLUS, OPT_fregmove, NULL, 1 },
+-    { OPT_LEVELS_2_PLUS, OPT_fstrict_aliasing, NULL, 1 },
+-    { OPT_LEVELS_2_PLUS, OPT_fstrict_overflow, NULL, 1 },
+     { OPT_LEVELS_2_PLUS, OPT_freorder_blocks, NULL, 1 },
+     { OPT_LEVELS_2_PLUS, OPT_freorder_functions, NULL, 1 },
+     { OPT_LEVELS_2_PLUS, OPT_ftree_vrp, NULL, 1 },
+@@ -494,6 +492,8 @@ static const struct default_options defa
+     { OPT_LEVELS_2_PLUS, OPT_falign_functions, NULL, 1 },
+     /* -O3 optimizations.  */
++    { OPT_LEVELS_3_PLUS, OPT_fstrict_aliasing, NULL, 1 },
++    { OPT_LEVELS_3_PLUS, OPT_fstrict_overflow, NULL, 1 },
+     { OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
+     { OPT_LEVELS_3_PLUS, OPT_fpredictive_commoning, NULL, 1 },
+     /* Inlining of functions reducing size is a good idea with -Os
+@@ -1399,6 +1399,17 @@ common_handle_option (struct gcc_options
+                              opts, opts_set, loc, dc);
+       break;
++    case OPT_Werror_maybe_reset:
++      {
++        char *ev = getenv ("GCC_NO_WERROR");
++        if ((ev != NULL) && (*ev != '0'))
++          warnings_are_errors = 0;
++      }
++      break;
++
++    case OPT_fhonour_copts:
++      break;
++
+     case OPT_Wlarger_than_:
+       opts->x_larger_than_size = value;
+       opts->x_warn_larger_than = value != -1;
+--- a/gcc/doc/cppopts.texi
++++ b/gcc/doc/cppopts.texi
+@@ -164,6 +164,11 @@ in older programs.  This warning is on b
+ Make all warnings into hard errors.  Source code which triggers warnings
+ will be rejected.
++ at item -Werror-maybe-reset
++ at opindex Werror-maybe-reset
++Act like @samp{-Wno-error} if the @env{GCC_NO_WERROR} environment
++variable is set to anything other than 0 or empty.
++
+ @item -Wsystem-headers
+ @opindex Wsystem-headers
+ Issue warnings for code in system headers.  These are normally unhelpful
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -240,7 +240,7 @@ Objective-C and Objective-C++ Dialects}.
+ -Wconversion  -Wcoverage-mismatch  -Wno-cpp  -Wno-deprecated  @gol
+ -Wno-deprecated-declarations -Wdisabled-optimization  @gol
+ -Wno-div-by-zero -Wdouble-promotion -Wempty-body  -Wenum-compare @gol
+--Wno-endif-labels -Werror  -Werror=* @gol
++-Wno-endif-labels -Werror  -Werror=* -Werror-maybe-reset @gol
+ -Wfatal-errors  -Wfloat-equal  -Wformat  -Wformat=2 @gol
+ -Wno-format-contains-nul -Wno-format-extra-args -Wformat-nonliteral @gol
+ -Wformat-security  -Wformat-y2k @gol
+@@ -4495,6 +4495,22 @@ This option is only supported for C and
+ @option{-Wall} and by @option{-pedantic}, which can be disabled with
+ @option{-Wno-pointer-sign}.
++ at item -Werror-maybe-reset
++ at opindex Werror-maybe-reset
++Act like @samp{-Wno-error} if the @env{GCC_NO_WERROR} environment
++variable is set to anything other than 0 or empty.
++
++ at item -fhonour-copts
++ at opindex fhonour-copts
++If @env{GCC_HONOUR_COPTS} is set to 1, abort if this option is not
++given at least once, and warn if it is given more than once.
++If @env{GCC_HONOUR_COPTS} is set to 2, abort if this option is not
++given exactly once.
++If @env{GCC_HONOUR_COPTS} is set to 0 or unset, warn if this option
++is not given exactly once.
++The warning is quelled if @env{GCC_HONOUR_COPTS} is set to @samp{s}.
++This flag and environment variable only affect the C language.
++
+ @item -Wstack-protector
+ @opindex Wstack-protector
+ @opindex Wno-stack-protector
+@@ -6317,7 +6333,7 @@ so, the first branch is redirected to ei
+ second branch or a point immediately following it, depending on whether
+ the condition is known to be true or false.
+-Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
++Enabled at levels @option{-O3}.
+ @item -fsplit-wide-types
+ @opindex fsplit-wide-types
+--- a/gcc/java/jvspec.c
++++ b/gcc/java/jvspec.c
+@@ -627,6 +627,7 @@ lang_specific_pre_link (void)
+      class name.  Append dummy `.c' that can be stripped by set_input so %b
+      is correct.  */ 
+   set_input (concat (main_class_name, "main.c", NULL));
++  putenv ("GCC_HONOUR_COPTS=s"); /* XXX hack!  */
+   err = do_spec (jvgenmain_spec);
+   if (err == 0)
+     {
diff --git a/toolchain/gcc/patches/4.6.1/993-arm_insn-opinit-RTX_CODE-fixup.patch b/toolchain/gcc/patches/4.6.1/993-arm_insn-opinit-RTX_CODE-fixup.patch
new file mode 100644 (file)
index 0000000..864f972
--- /dev/null
@@ -0,0 +1,15 @@
+--- a/gcc/config/arm/arm-protos.h
++++ b/gcc/config/arm/arm-protos.h
+@@ -41,11 +41,11 @@ extern unsigned int arm_dbx_register_num
+ extern void arm_output_fn_unwind (FILE *, bool);
+   
+-#ifdef RTX_CODE
+ extern bool arm_vector_mode_supported_p (enum machine_mode);
+ extern bool arm_small_register_classes_for_mode_p (enum machine_mode);
+ extern int arm_hard_regno_mode_ok (unsigned int, enum machine_mode);
+ extern int const_ok_for_arm (HOST_WIDE_INT);
++#ifdef RTX_CODE
+ extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
+                              HOST_WIDE_INT, rtx, rtx, int);
+ extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *, rtx *);
diff --git a/toolchain/gcc/patches/4.6.1/999-coldfire.patch b/toolchain/gcc/patches/4.6.1/999-coldfire.patch
new file mode 100644 (file)
index 0000000..cda4237
--- /dev/null
@@ -0,0 +1,10 @@
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -1791,6 +1791,7 @@ m68k-*-linux*)           # Motorola m68k's runnin
+       if test x$sjlj != x1; then
+           tmake_file="$tmake_file m68k/t-slibgcc-elf-ver"
+       fi
++      tmake_file="m68k/t-floatlib m68k/t-m68kbare m68k/t-m68kelf"
+       ;;
+ m68k-*-rtems*)
+       default_m68k_cpu=68020