import gcc-3.4.6
authorMike Frysinger <vapier@gentoo.org>
Fri, 17 Mar 2006 23:58:47 +0000 (23:58 -0000)
committerMike Frysinger <vapier@gentoo.org>
Fri, 17 Mar 2006 23:58:47 +0000 (23:58 -0000)
16 files changed:
toolchain/gcc/3.4.6/100-uclibc-conf.patch [new file with mode: 0644]
toolchain/gcc/3.4.6/200-uclibc-locale.patch [new file with mode: 0644]
toolchain/gcc/3.4.6/300-libstdc++-pic.patch [new file with mode: 0644]
toolchain/gcc/3.4.6/600-gcc34-arm-ldm-peephole.patch [new file with mode: 0644]
toolchain/gcc/3.4.6/601-gcc34-arm-ldm-peephole2.patch [new file with mode: 0644]
toolchain/gcc/3.4.6/601-gcc34-arm-ldm.patch [new file with mode: 0644]
toolchain/gcc/3.4.6/602-sdk-libstdc++-includes.patch [new file with mode: 0644]
toolchain/gcc/3.4.6/700-pr15068-fix.patch [new file with mode: 0644]
toolchain/gcc/3.4.6/71_all_sh-pr16665-fix.patch [new file with mode: 0644]
toolchain/gcc/3.4.6/72_all_sh-no-reorder-blocks.patch [new file with mode: 0644]
toolchain/gcc/3.4.6/73_all_sh-pr20617.patch [new file with mode: 0644]
toolchain/gcc/3.4.6/800-arm-bigendian.patch [new file with mode: 0644]
toolchain/gcc/3.4.6/800-powerpc-libc_stack_end-uclibc.patch [new file with mode: 0644]
toolchain/gcc/3.4.6/900-nios2.patch [new file with mode: 0644]
toolchain/gcc/3.4.6/arm-softfloat.patch.conditional [new file with mode: 0644]
toolchain/gcc/Config.in

diff --git a/toolchain/gcc/3.4.6/100-uclibc-conf.patch b/toolchain/gcc/3.4.6/100-uclibc-conf.patch
new file mode 100644 (file)
index 0000000..00ea4ee
--- /dev/null
@@ -0,0 +1,470 @@
+--- gcc-3.4.1/gcc/config/t-linux-uclibc
++++ gcc-3.4.1/gcc/config/t-linux-uclibc
+@@ -0,0 +1,5 @@
++# Remove glibc specific files added in t-linux
++SHLIB_MAPFILES := $(filter-out $(srcdir)/config/libgcc-glibc.ver, $(SHLIB_MAPFILES))
++
++# Use unwind-dw2-fde instead of unwind-dw2-fde-glibc
++LIB2ADDEH := $(subst unwind-dw2-fde-glibc.c,unwind-dw2-fde.c,$(LIB2ADDEH))
+--- gcc-3.4.1/gcc/config.gcc
++++ gcc-3.4.1/gcc/config.gcc
+@@ -2310,10 +2310,16 @@
+ *)
+       echo "*** Configuration ${target} not supported" 1>&2
+       exit 1
+       ;;
+ esac
++
++# Rather than hook into each target, just do it after all the linux
++# targets have been processed
++case ${target} in
++*-linux-uclibc*) tm_defines="${tm_defines} USE_UCLIBC" ; tmake_file="${tmake_file} t-linux-uclibc"
++esac
+ # Support for --with-cpu and related options (and a few unrelated options,
+ # too).
+ case ${with_cpu} in
+   yes | no)
+--- gcc-3.4.4/gcc/config/alpha/linux-elf.h
++++ gcc-3.4.4/gcc/config/alpha/linux-elf.h
+@@ -27,7 +27,11 @@
+ #define SUBTARGET_EXTRA_SPECS \
+ { "elf_dynamic_linker", ELF_DYNAMIC_LINKER },
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER    "/lib/ld-uClibc.so.0"
++#else
+ #define ELF_DYNAMIC_LINKER    "/lib/ld-linux.so.2"
++#endif
+ #define LINK_SPEC "-m elf64alpha %{G*} %{relax:-relax}                \
+   %{O*:-O3} %{!O*:-O1}                                                \
+--- gcc-3.4.1-dist/gcc/config/arm/linux-elf.h  2004-01-31 00:18:11.000000000 -0600
++++ gcc-3.4.1/gcc/config/arm/linux-elf.h       2004-08-12 15:54:42.000000000 -0500
+@@ -80,14 +80,19 @@
+ #define ENDFILE_SPEC \
+   "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#else
++#define ELF_DYNAMIC_LINKER "/lib/ld-linux.so.2"
++#endif
+ #undef  LINK_SPEC
+ #define LINK_SPEC "%{h*} %{version:-v} \
+    %{b} %{Wl,*:%*} \
+    %{static:-Bstatic} \
+    %{shared:-shared} \
+    %{symbolic:-Bsymbolic} \
+    %{rdynamic:-export-dynamic} \
+-   %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2} \
++   %{!dynamic-linker:-dynamic-linker " ELF_DYNAMIC_LINKER "} \
+    -X \
+    %{mbig-endian:-EB}" \
+    SUBTARGET_EXTRA_LINK_SPEC
+--- gcc-3.4.1-dist/gcc/config/cris/linux.h     2003-11-28 21:08:09.000000000 -0600
++++ gcc-3.4.1/gcc/config/cris/linux.h  2004-08-12 15:54:43.000000000 -0500
+@@ -79,6 +79,25 @@
+ #undef CRIS_DEFAULT_CPU_VERSION
+ #define CRIS_DEFAULT_CPU_VERSION CRIS_CPU_NG
++#ifdef USE_UCLIBC
++
++#undef CRIS_SUBTARGET_VERSION
++#define CRIS_SUBTARGET_VERSION " - cris-axis-linux-uclibc"
++
++#undef CRIS_LINK_SUBTARGET_SPEC
++#define CRIS_LINK_SUBTARGET_SPEC \
++ "-mcrislinux\
++  -rpath-link include/asm/../..%s\
++  %{shared} %{static}\
++  %{symbolic:-Bdynamic} %{shlib:-Bdynamic} %{static:-Bstatic}\
++  %{!shared: \
++    %{!static: \
++      %{rdynamic:-export-dynamic} \
++      %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}}} \
++  %{!r:%{O2|O3: --gc-sections}}"
++
++#else  /* USE_UCLIBC */
++
+ #undef CRIS_SUBTARGET_VERSION
+ #define CRIS_SUBTARGET_VERSION " - cris-axis-linux-gnu"
+@@ -93,6 +112,8 @@
+   %{!shared:%{!static:%{rdynamic:-export-dynamic}}}\
+   %{!r:%{O2|O3: --gc-sections}}"
++#endif  /* USE_UCLIBC */
++
+ /* Node: Run-time Target */
+--- gcc-3.4.1-dist/gcc/config/i386/linux.h     2003-11-28 21:08:10.000000000 -0600
++++ gcc-3.4.1/gcc/config/i386/linux.h  2004-08-12 15:54:43.000000000 -0500
+@@ -110,22 +110,21 @@
+ #undef        LINK_SPEC
+ #ifdef USE_GNULIBC_1
+-#define LINK_SPEC "-m elf_i386 %{shared:-shared} \
+-  %{!shared: \
+-    %{!ibcs: \
+-      %{!static: \
+-      %{rdynamic:-export-dynamic} \
+-      %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \
+-      %{static:-static}}}"
++#define ELF_DYNAMIC_LINKER "/lib/ld-linux.so.1"
++#else
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
+ #else
++#define ELF_DYNAMIC_LINKER "/lib/ld-linux.so.2"
++#endif
++#endif
+ #define LINK_SPEC "-m elf_i386 %{shared:-shared} \
+   %{!shared: \
+     %{!ibcs: \
+       %{!static: \
+       %{rdynamic:-export-dynamic} \
+-      %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
++      %{!dynamic-linker:-dynamic-linker " ELF_DYNAMIC_LINKER "}} \
+       %{static:-static}}}"
+-#endif
+ /* A C statement (sans semicolon) to output to the stdio stream
+    FILE the assembler definition of uninitialized global DECL named
+--- gcc-3.4.4/gcc/config/i386/linux64.h
++++ gcc-3.4.4/gcc/config/i386/linux64.h
+@@ -54,14 +54,21 @@
+    When the -shared link option is used a final link is not being
+    done.  */
++#ifdef USE_UCLIBC
++#define ELF32_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#define ELF64_DYNAMIC_LINKER "/lib/ld64-uClibc.so.0"
++#else
++#define ELF32_DYNAMIC_LINKER "/lib/ld-linux.so.2"
++#define ELF64_DYNAMIC_LINKER "/lib64/ld-linux-x86-64.so.2"
++#endif
+ #undef        LINK_SPEC
+ #define LINK_SPEC "%{!m32:-m elf_x86_64} %{m32:-m elf_i386} \
+   %{shared:-shared} \
+   %{!shared: \
+     %{!static: \
+       %{rdynamic:-export-dynamic} \
+-      %{m32:%{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
+-      %{!m32:%{!dynamic-linker:-dynamic-linker /lib64/ld-linux-x86-64.so.2}}} \
++      %{m32:%{!dynamic-linker:-dynamic-linker " ELF32_DYNAMIC_LINKER "}} \
++      %{!m32:%{!dynamic-linker:-dynamic-linker " ELF64_DYNAMIC_LINKER "}}} \
+     %{static:-static}}"
+ #define MULTILIB_DEFAULTS { "m64" }
+--- gcc-3.4.4/gcc/config/ia64/linux.h
++++ gcc-3.4.4/gcc/config/ia64/linux.h
+@@ -37,13 +37,18 @@
+ /* Define this for shared library support because it isn't in the main
+    linux.h file.  */
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER    "/lib/ld-uClibc.so.0"
++#else
++#define ELF_DYNAMIC_LINKER "/lib/ld-linux-ia64.so.2"
++#endif
+ #undef LINK_SPEC
+ #define LINK_SPEC "\
+   %{shared:-shared} \
+   %{!shared: \
+     %{!static: \
+       %{rdynamic:-export-dynamic} \
+-      %{!dynamic-linker:-dynamic-linker /lib/ld-linux-ia64.so.2}} \
++      %{!dynamic-linker:-dynamic-linker " ELF_DYNAMIC_LINKER "}} \
+       %{static:-static}}"
+--- gcc-3.4.4/gcc/config/m68k/linux.h
++++ gcc-3.4.4/gcc/config/m68k/linux.h
+@@ -131,12 +131,17 @@
+ /* If ELF is the default format, we should not use /lib/elf.  */
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#else
++#define ELF_DYNAMIC_LINKER "/lib/ld.so.1"
++#endif
+ #undef        LINK_SPEC
+ #define LINK_SPEC "-m m68kelf %{shared} \
+   %{!shared: \
+     %{!static: \
+       %{rdynamic:-export-dynamic} \
+-      %{!dynamic-linker*:-dynamic-linker /lib/ld.so.1}} \
++      %{!dynamic-linker*:-dynamic-linker " ELF_DYNAMIC_LINKER "}} \
+     %{static}}"
+ /* For compatibility with linux/a.out */
+--- gcc-3.4.1-dist/gcc/config/mips/linux.h     2004-06-15 20:42:24.000000000 -0500
++++ gcc-3.4.1/gcc/config/mips/linux.h  2004-08-12 15:54:43.000000000 -0500
+@@ -109,14 +109,19 @@
+ /* Borrowed from sparc/linux.h */
+ #undef LINK_SPEC
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#else
++#define ELF_DYNAMIC_LINKER "/lib/ld.so.1"
++#endif
+ #define LINK_SPEC \
+  "%(endian_spec) \
+   %{shared:-shared} \
+   %{!shared: \
+     %{!ibcs: \
+       %{!static: \
+         %{rdynamic:-export-dynamic} \
+-        %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}} \
++        %{!dynamic-linker:-dynamic-linker " ELF_DYNAMIC_LINKER "}} \
+         %{static:-static}}}"
+ #undef SUBTARGET_ASM_SPEC
+--- gcc-3.4.4/gcc/config/pa/pa-linux.h
++++ gcc-3.4.4/gcc/config/pa/pa-linux.h
+@@ -77,13 +77,18 @@
+ /* Define this for shared library support because it isn't in the main
+    linux.h file.  */
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#else
++#define ELF_DYNAMIC_LINKER "/lib/ld.so.1"
++#endif
+ #undef LINK_SPEC
+ #define LINK_SPEC "\
+   %{shared:-shared} \
+   %{!shared: \
+     %{!static: \
+       %{rdynamic:-export-dynamic} \
+-      %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}} \
++      %{!dynamic-linker:-dynamic-linker " ELF_DYNAMIC_LINKER "}} \
+       %{static:-static}}"
+ /* glibc's profiling functions don't need gcc to allocate counters.  */
+--- gcc-3.4.1-dist/gcc/config/rs6000/linux.h   2004-02-25 09:11:19.000000000 -0600
++++ gcc-3.4.1/gcc/config/rs6000/linux.h        2004-08-12 15:54:43.000000000 -0500
+@@ -69,7 +69,11 @@
+ #define LINK_START_DEFAULT_SPEC "%(link_start_linux)"
+ #undef        LINK_OS_DEFAULT_SPEC
++#ifdef USE_UCLIBC
++#define LINK_OS_DEFAULT_SPEC "%(link_os_linux_uclibc)"
++#else
+ #define LINK_OS_DEFAULT_SPEC "%(link_os_linux)"
++#endif
+ #define LINK_GCC_C_SEQUENCE_SPEC \
+   "%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}"
+--- gcc-3.4.1-dist/gcc/config/rs6000/sysv4.h   2004-06-10 01:39:50.000000000 -0500
++++ gcc-3.4.1/gcc/config/rs6000/sysv4.h        2004-08-12 15:54:43.000000000 -0500
+@@ -947,6 +947,7 @@
+   mcall-linux  : %(link_os_linux)       ; \
+   mcall-gnu    : %(link_os_gnu)         ; \
+   mcall-netbsd : %(link_os_netbsd)      ; \
++  mcall-linux-uclibc : %(link_os_linux_uclibc); \
+   mcall-openbsd: %(link_os_openbsd)     ; \
+                : %(link_os_default)     }"
+@@ -1125,6 +1126,10 @@
+   %{rdynamic:-export-dynamic} \
+   %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}}}"
++#define LINK_OS_LINUX_UCLIBC_SPEC "-m elf32ppclinux %{!shared: %{!static: \
++  %{rdynamic:-export-dynamic} \
++  %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}}}"
++
+ #if defined(HAVE_LD_EH_FRAME_HDR)
+ # define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
+ #endif
+@@ -1291,6 +1296,7 @@
+   { "link_os_sim",            LINK_OS_SIM_SPEC },                     \
+   { "link_os_freebsd",                LINK_OS_FREEBSD_SPEC },                 \
+   { "link_os_linux",          LINK_OS_LINUX_SPEC },                   \
++  { "link_os_linux_uclibc",   LINK_OS_LINUX_UCLIBC_SPEC },            \
+   { "link_os_gnu",            LINK_OS_GNU_SPEC },                     \
+   { "link_os_netbsd",         LINK_OS_NETBSD_SPEC },                  \
+   { "link_os_openbsd",                LINK_OS_OPENBSD_SPEC },                 \
+--- gcc-3.4.4/gcc/config/s390/linux.h
++++ gcc-3.4.4/gcc/config/s390/linux.h
+@@ -77,6 +77,13 @@
+ #define MULTILIB_DEFAULTS { "m31" }
+ #endif
++#ifdef USE_UCLIBC
++#define ELF31_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#define ELF64_DYNAMIC_LINKER "/lib/ld64-uClibc.so.0"
++#else
++#define ELF31_DYNAMIC_LINKER "/lib/ld.so.1"
++#define ELF64_DYNAMIC_LINKER "/lib/ld64.so.1"
++#endif
+ #undef  LINK_SPEC
+ #define LINK_SPEC \
+   "%{m31:-m elf_s390}%{m64:-m elf64_s390} \
+@@ -86,8 +93,8 @@
+       %{!static: \
+       %{rdynamic:-export-dynamic} \
+       %{!dynamic-linker: \
+-          %{m31:-dynamic-linker /lib/ld.so.1} \
+-          %{m64:-dynamic-linker /lib/ld64.so.1}}}}"
++          %{m31:-dynamic-linker " ELF31_DYNAMIC_LINKER "} \
++          %{m64:-dynamic-linker " ELF64_DYNAMIC_LINKER "}}}}"
+ #define TARGET_ASM_FILE_END file_end_indicate_exec_stack
+--- gcc-3.4.1-dist/gcc/config/sh/linux.h       2004-01-11 20:29:13.000000000 -0600
++++ gcc-3.4.1/gcc/config/sh/linux.h    2004-08-12 15:54:43.000000000 -0500
+@@ -73,11 +73,16 @@
+ #undef SUBTARGET_LINK_EMUL_SUFFIX
+ #define SUBTARGET_LINK_EMUL_SUFFIX "_linux"
+ #undef SUBTARGET_LINK_SPEC
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#else
++#define ELF_DYNAMIC_LINKER "/lib/ld-linux.so.2"
++#endif
+ #define SUBTARGET_LINK_SPEC \
+   "%{shared:-shared} \
+    %{!static: \
+      %{rdynamic:-export-dynamic} \
+-     %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
++     %{!dynamic-linker:-dynamic-linker " ELF_DYNAMIC_LINKER "}} \
+    %{static:-static}"
+ #undef LIB_SPEC
+--- gcc-3.4.4/gcc/config/sparc/linux.h
++++ gcc-3.4.4/gcc/config/sparc/linux.h
+@@ -162,13 +162,18 @@
+         %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \
+         %{static:-static}}}"
+ #else
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
++#else
++#define ELF_DYNAMIC_LINKER "/lib/ld-linux.so.2"
++#endif
+ #define LINK_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \
+   %{!mno-relax:%{!r:-relax}} \
+   %{!shared: \
+     %{!ibcs: \
+       %{!static: \
+         %{rdynamic:-export-dynamic} \
+-        %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
++        %{!dynamic-linker:-dynamic-linker " ELF_DYNAMIC_LINKER "}} \
+         %{static:-static}}}"
+ #endif
+--- gcc-3.4.4/gcc/config/sparc/linux64.h
++++ gcc-3.4.4/gcc/config/sparc/linux64.h
+@@ -167,12 +166,17 @@
+   { "link_arch_default", LINK_ARCH_DEFAULT_SPEC },      \
+   { "link_arch",       LINK_ARCH_SPEC },
+     
++#ifdef USE_UCLIBC
++#define ELF_DYNAMIC_LINKER    "/lib/ld-uClibc.so.0"
++#else
++#define ELF_DYNAMIC_LINKER  "/lib/ld-linux.so.2"
++#endif
+ #define LINK_ARCH32_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \
+   %{!shared: \
+     %{!ibcs: \
+       %{!static: \
+         %{rdynamic:-export-dynamic} \
+-        %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
++        %{!dynamic-linker:-dynamic-linker " ELF_DYNAMIC_LINKER "}} \
+         %{static:-static}}} \
+ "
+--- gcc-3.4.1-dist/libtool.m4  2004-05-18 04:08:37.000000000 -0500
++++ gcc-3.4.1/libtool.m4       2004-08-12 15:54:43.000000000 -0500
+@@ -689,6 +689,11 @@
+   lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+   ;;
++linux-uclibc*)
++  lt_cv_deplibs_check_method=pass_all
++  lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++  ;;
++
+ netbsd*)
+   if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+     [lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$']
+--- gcc-3.4.1-dist/ltconfig    2004-03-05 15:05:41.000000000 -0600
++++ gcc-3.4.1/ltconfig 2004-08-12 15:55:48.000000000 -0500
+@@ -602,6 +602,7 @@
+ # Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+ case $host_os in
++linux-uclibc*) ;;
+ linux-gnu*) ;;
+ linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+ esac
+@@ -1262,6 +1263,24 @@
+   dynamic_linker='GNU/Linux ld.so'
+   ;;
++linux-uclibc*)
++  version_type=linux
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
++  soname_spec='${libname}${release}.so$major'
++  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=no
++  # This implies no fast_install, which is unacceptable.
++  # Some rework will be needed to allow for fast_install
++  # before this can be enabled.
++  # Note: copied from linux-gnu, and may not be appropriate.
++  hardcode_into_libs=yes
++  # Assume using the uClibc dynamic linker.
++  dynamic_linker="uClibc ld.so"
++  ;;
++
+ netbsd*)
+   need_lib_prefix=no
+   need_version=no
+--- gcc-3.4.1-dist/boehm-gc/configure  2004-07-01 14:14:03.000000000 -0500
++++ gcc-3.4.1/boehm-gc/configure       2004-08-12 16:22:57.000000000 -0500
+@@ -1947,6 +1947,11 @@
+   lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+   ;;
++linux-uclibc*)
++  lt_cv_deplibs_check_method=pass_all
++  lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++  ;;
++
+ netbsd*)
+   if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+     lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+--- gcc-3.4.1-dist/boehm-gc/ltconfig   2002-11-20 09:59:06.000000000 -0600
++++ gcc-3.4.1/boehm-gc/ltconfig        2004-08-12 15:54:42.000000000 -0500
+@@ -1981,6 +1981,23 @@
+   fi
+   ;;
++linux-uclibc*)
++  version_type=linux
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
++  soname_spec='${libname}${release}.so$major'
++  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=no
++  deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
++  file_magic_cmd=/usr/bin/file
++  file_magic_test_file=`echo /lib/libuClibc-*.so`
++
++  # Assume using the uClibc dynamic linker.
++  dynamic_linker="uClibc ld.so"
++  ;;
++
+ netbsd*)
+   version_type=sunos
+   if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
diff --git a/toolchain/gcc/3.4.6/200-uclibc-locale.patch b/toolchain/gcc/3.4.6/200-uclibc-locale.patch
new file mode 100644 (file)
index 0000000..a97f22b
--- /dev/null
@@ -0,0 +1,3255 @@
+diff -urN gcc-3.4.2-dist/libstdc++-v3/acinclude.m4 gcc-3.4.2/libstdc++-v3/acinclude.m4
+--- gcc-3.4.2-dist/libstdc++-v3/acinclude.m4   2004-07-15 12:42:45.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/acinclude.m4        2004-09-10 10:47:40.000000000 -0500
+@@ -996,7 +996,7 @@
+   AC_MSG_CHECKING([for C locale to use])
+   GLIBCXX_ENABLE(clocale,auto,[@<:@=MODEL@:>@],
+     [use MODEL for target locale package],
+-    [permit generic|gnu|ieee_1003.1-2001|yes|no|auto])
++    [permit generic|gnu|ieee_1003.1-2001|uclibc|yes|no|auto])
+   
+   # If they didn't use this option switch, or if they specified --enable
+   # with no specific model, we'll have to look for one.  If they
+@@ -1012,6 +1012,9 @@
+   # Default to "generic".
+   if test $enable_clocale_flag = auto; then
+     case x${target_os} in
++      x*-uclibc*)
++        enable_clocale_flag=uclibc
++        ;;
+       xlinux* | xgnu* | xkfreebsd*-gnu | xknetbsd*-gnu)
+         AC_EGREP_CPP([_GLIBCXX_ok], [
+         #include <features.h>
+@@ -1138,6 +1141,41 @@
+       CTIME_CC=config/locale/generic/time_members.cc
+       CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+       ;;
++    uclibc)
++      AC_MSG_RESULT(uclibc)
++
++      # Declare intention to use gettext, and add support for specific
++      # languages.
++      # For some reason, ALL_LINGUAS has to be before AM-GNU-GETTEXT
++      ALL_LINGUAS="de fr"
++
++      # Don't call AM-GNU-GETTEXT here. Instead, assume glibc.
++      AC_CHECK_PROG(check_msgfmt, msgfmt, yes, no)
++      if test x"$check_msgfmt" = x"yes" && test x"$enable_nls" = x"yes"; then
++        USE_NLS=yes
++      fi
++      # Export the build objects.
++      for ling in $ALL_LINGUAS; do \
++        glibcxx_MOFILES="$glibcxx_MOFILES $ling.mo"; \
++        glibcxx_POFILES="$glibcxx_POFILES $ling.po"; \
++      done
++      AC_SUBST(glibcxx_MOFILES)
++      AC_SUBST(glibcxx_POFILES)
++
++      CLOCALE_H=config/locale/uclibc/c_locale.h
++      CLOCALE_CC=config/locale/uclibc/c_locale.cc
++      CCODECVT_H=config/locale/ieee_1003.1-2001/codecvt_specializations.h
++      CCODECVT_CC=config/locale/uclibc/codecvt_members.cc
++      CCOLLATE_CC=config/locale/uclibc/collate_members.cc
++      CCTYPE_CC=config/locale/uclibc/ctype_members.cc
++      CMESSAGES_H=config/locale/uclibc/messages_members.h
++      CMESSAGES_CC=config/locale/uclibc/messages_members.cc
++      CMONEY_CC=config/locale/uclibc/monetary_members.cc
++      CNUMERIC_CC=config/locale/uclibc/numeric_members.cc
++      CTIME_H=config/locale/uclibc/time_members.h
++      CTIME_CC=config/locale/uclibc/time_members.cc
++      CLOCALE_INTERNAL_H=config/locale/uclibc/c++locale_internal.h
++      ;;
+   esac
+   # This is where the testsuite looks for locale catalogs, using the
+diff -urN gcc-3.4.2-dist/libstdc++-v3/aclocal.m4 gcc-3.4.2/libstdc++-v3/aclocal.m4
+--- gcc-3.4.2-dist/libstdc++-v3/aclocal.m4     2004-08-13 15:44:03.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/aclocal.m4  2004-09-10 10:47:40.000000000 -0500
+@@ -1025,6 +1025,9 @@
+   # Default to "generic".
+   if test $enable_clocale_flag = auto; then
+     case x${target_os} in
++      x*-uclibc*)
++      enable_clocale_flag=uclibc
++      ;;
+       xlinux* | xgnu* | xkfreebsd*-gnu | xknetbsd*-gnu)
+         AC_EGREP_CPP([_GLIBCXX_ok], [
+         #include <features.h>
+@@ -1151,6 +1154,41 @@
+       CTIME_CC=config/locale/generic/time_members.cc
+       CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+       ;;
++    uclibc)
++      AC_MSG_RESULT(uclibc)
++
++      # Declare intention to use gettext, and add support for specific
++      # languages.
++      # For some reason, ALL_LINGUAS has to be before AM-GNU-GETTEXT
++      ALL_LINGUAS="de fr"
++
++      # Don't call AM-GNU-GETTEXT here. Instead, assume glibc.
++      AC_CHECK_PROG(check_msgfmt, msgfmt, yes, no)
++      if test x"$check_msgfmt" = x"yes" && test x"$enable_nls" = x"yes"; then
++        USE_NLS=yes
++      fi
++      # Export the build objects.
++      for ling in $ALL_LINGUAS; do \
++        glibcxx_MOFILES="$glibcxx_MOFILES $ling.mo"; \
++        glibcxx_POFILES="$glibcxx_POFILES $ling.po"; \
++      done
++      AC_SUBST(glibcxx_MOFILES)
++      AC_SUBST(glibcxx_POFILES)
++
++      CLOCALE_H=config/locale/uclibc/c_locale.h
++      CLOCALE_CC=config/locale/uclibc/c_locale.cc
++      CCODECVT_H=config/locale/ieee_1003.1-2001/codecvt_specializations.h
++      CCODECVT_CC=config/locale/uclibc/codecvt_members.cc
++      CCOLLATE_CC=config/locale/uclibc/collate_members.cc
++      CCTYPE_CC=config/locale/uclibc/ctype_members.cc
++      CMESSAGES_H=config/locale/uclibc/messages_members.h
++      CMESSAGES_CC=config/locale/uclibc/messages_members.cc
++      CMONEY_CC=config/locale/uclibc/monetary_members.cc
++      CNUMERIC_CC=config/locale/uclibc/numeric_members.cc
++      CTIME_H=config/locale/uclibc/time_members.h
++      CTIME_CC=config/locale/uclibc/time_members.cc
++      CLOCALE_INTERNAL_H=config/locale/uclibc/c++locale_internal.h
++      ;;
+   esac
+   # This is where the testsuite looks for locale catalogs, using the
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c++locale_internal.h gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c++locale_internal.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c++locale_internal.h      1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c++locale_internal.h   2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,59 @@
++// Prototypes for GLIBC thread locale __-prefixed functions -*- C++ -*-
++
++// Copyright (C) 2002, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library.  This library 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.
++
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++
++// You should have received a copy of the GNU General Public License along
++// with this library; 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, you may use this file as part of a free software
++// library without restriction.  Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License.  This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++// Written by Jakub Jelinek <jakub@redhat.com>
++
++#include <clocale>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning clean this up
++#endif
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++                                                  
++extern "C" __typeof(iswctype_l) __iswctype_l;
++extern "C" __typeof(nl_langinfo_l) __nl_langinfo_l;
++extern "C" __typeof(strcoll_l) __strcoll_l;
++extern "C" __typeof(strftime_l) __strftime_l;
++extern "C" __typeof(strtod_l) __strtod_l;
++extern "C" __typeof(strtof_l) __strtof_l;
++extern "C" __typeof(strtold_l) __strtold_l;
++extern "C" __typeof(strxfrm_l) __strxfrm_l;
++extern "C" __typeof(towlower_l) __towlower_l;
++extern "C" __typeof(towupper_l) __towupper_l;
++extern "C" __typeof(wcscoll_l) __wcscoll_l;
++extern "C" __typeof(wcsftime_l) __wcsftime_l;
++extern "C" __typeof(wcsxfrm_l) __wcsxfrm_l;
++extern "C" __typeof(wctype_l) __wctype_l;
++extern "C" __typeof(newlocale) __newlocale;
++extern "C" __typeof(freelocale) __freelocale;
++extern "C" __typeof(duplocale) __duplocale;
++extern "C" __typeof(uselocale) __uselocale;
++
++#endif // GLIBC 2.3 and later
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.cc       1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.cc    2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,160 @@
++// Wrapper for underlying C-language localization -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library.  This library 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.
++
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++
++// You should have received a copy of the GNU General Public License along
++// with this library; 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, you may use this file as part of a free software
++// library without restriction.  Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License.  This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.8  Standard locale categories.
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <cerrno>  // For errno
++#include <locale>
++#include <stdexcept>
++#include <langinfo.h>
++#include <bits/c++locale_internal.h>
++
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __strtol_l(S, E, B, L)      strtol((S), (E), (B))
++#define __strtoul_l(S, E, B, L)     strtoul((S), (E), (B))
++#define __strtoll_l(S, E, B, L)     strtoll((S), (E), (B))
++#define __strtoull_l(S, E, B, L)    strtoull((S), (E), (B))
++#define __strtof_l(S, E, L)         strtof((S), (E))
++#define __strtod_l(S, E, L)         strtod((S), (E))
++#define __strtold_l(S, E, L)        strtold((S), (E))
++#warning should dummy __newlocale check for C|POSIX ?
++#define __newlocale(a, b, c)        NULL
++#define __freelocale(a)             ((void)0)
++#define __duplocale(a)              __c_locale()
++#endif
++
++namespace std 
++{
++  template<>
++    void
++    __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err, 
++                 const __c_locale& __cloc)
++    {
++      if (!(__err & ios_base::failbit))
++      {
++        char* __sanity;
++        errno = 0;
++        float __f = __strtof_l(__s, &__sanity, __cloc);
++          if (__sanity != __s && errno != ERANGE)
++          __v = __f;
++        else
++          __err |= ios_base::failbit;
++      }
++    }
++
++  template<>
++    void
++    __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err, 
++                 const __c_locale& __cloc)
++    {
++      if (!(__err & ios_base::failbit))
++      {
++        char* __sanity;
++        errno = 0;
++        double __d = __strtod_l(__s, &__sanity, __cloc);
++          if (__sanity != __s && errno != ERANGE)
++          __v = __d;
++        else
++          __err |= ios_base::failbit;
++      }
++    }
++
++  template<>
++    void
++    __convert_to_v(const char* __s, long double& __v, ios_base::iostate& __err,
++                 const __c_locale& __cloc)
++    {
++      if (!(__err & ios_base::failbit))
++      {
++        char* __sanity;
++        errno = 0;
++        long double __ld = __strtold_l(__s, &__sanity, __cloc);
++          if (__sanity != __s && errno != ERANGE)
++          __v = __ld;
++        else
++          __err |= ios_base::failbit;
++      }
++    }
++
++  void
++  locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s, 
++                                  __c_locale __old)
++  {
++    __cloc = __newlocale(1 << LC_ALL, __s, __old);
++#ifdef __UCLIBC_HAS_XLOCALE__
++    if (!__cloc)
++      {
++      // This named locale is not supported by the underlying OS.
++      __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
++                            "name not valid"));
++      }
++#endif
++  }
++  
++  void
++  locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
++  {
++    if (_S_get_c_locale() != __cloc)
++      __freelocale(__cloc); 
++  }
++
++  __c_locale
++  locale::facet::_S_clone_c_locale(__c_locale& __cloc)
++  { return __duplocale(__cloc); }
++} // namespace std
++
++namespace __gnu_cxx
++{
++  const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
++    {
++      "LC_CTYPE", 
++      "LC_NUMERIC",
++      "LC_TIME", 
++      "LC_COLLATE", 
++      "LC_MONETARY",
++      "LC_MESSAGES", 
++#if _GLIBCXX_NUM_CATEGORIES != 0
++      "LC_PAPER", 
++      "LC_NAME", 
++      "LC_ADDRESS",
++      "LC_TELEPHONE", 
++      "LC_MEASUREMENT", 
++      "LC_IDENTIFICATION" 
++#endif
++    };
++}
++
++namespace std
++{
++  const char* const* const locale::_S_categories = __gnu_cxx::category_names;
++}  // namespace std
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.h gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/c_locale.h        1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/c_locale.h     2004-09-10 10:48:08.000000000 -0500
+@@ -0,0 +1,115 @@
++// Wrapper for underlying C-language localization -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library.  This library 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.
++
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++
++// You should have received a copy of the GNU General Public License along
++// with this library; 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, you may use this file as part of a free software
++// library without restriction.  Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License.  This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.8  Standard locale categories.
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#ifndef _C_LOCALE_H
++#define _C_LOCALE_H 1
++
++#pragma GCC system_header
++
++#include <cstring>              // get std::strlen
++#include <cstdio>               // get std::snprintf or std::sprintf
++#include <clocale>
++#include <langinfo.h>         // For codecvt
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix this
++#endif
++#ifdef __UCLIBC_HAS_LOCALE__
++#include <iconv.h>            // For codecvt using iconv, iconv_t
++#endif
++#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
++#include <libintl.h>          // For messages
++#endif
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning what is _GLIBCXX_C_LOCALE_GNU for
++#endif
++#define _GLIBCXX_C_LOCALE_GNU 1
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix categories
++#endif
++// #define _GLIBCXX_NUM_CATEGORIES 6
++#define _GLIBCXX_NUM_CATEGORIES 0
++ 
++#ifdef __UCLIBC_HAS_XLOCALE__
++namespace __gnu_cxx
++{
++  extern "C" __typeof(uselocale) __uselocale;
++}
++#endif
++
++namespace std
++{
++#ifdef __UCLIBC_HAS_XLOCALE__
++  typedef __locale_t          __c_locale;
++#else
++  typedef int*                        __c_locale;
++#endif
++
++  // Convert numeric value of type _Tv to string and return length of
++  // string.  If snprintf is available use it, otherwise fall back to
++  // the unsafe sprintf which, in general, can be dangerous and should
++  // be avoided.
++  template<typename _Tv>
++    int
++    __convert_from_v(char* __out, const int __size, const char* __fmt,
++#ifdef __UCLIBC_HAS_XLOCALE__
++                   _Tv __v, const __c_locale& __cloc, int __prec)
++    {
++      __c_locale __old = __gnu_cxx::__uselocale(__cloc);
++#else
++                   _Tv __v, const __c_locale&, int __prec)
++    {
++# ifdef __UCLIBC_HAS_LOCALE__
++      char* __old = std::setlocale(LC_ALL, NULL);
++      char* __sav = new char[std::strlen(__old) + 1];
++      std::strcpy(__sav, __old);
++      std::setlocale(LC_ALL, "C");
++# endif
++#endif
++
++      const int __ret = std::snprintf(__out, __size, __fmt, __prec, __v);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++      __gnu_cxx::__uselocale(__old);
++#elif defined __UCLIBC_HAS_LOCALE__
++      std::setlocale(LC_ALL, __sav);
++      delete [] __sav;
++#endif
++      return __ret;
++    }
++}
++
++#endif
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/codecvt_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/codecvt_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/codecvt_members.cc        1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/codecvt_members.cc     2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,306 @@
++// std::codecvt implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2002, 2003 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library.  This library 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.
++
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++
++// You should have received a copy of the GNU General Public License along
++// with this library; 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, you may use this file as part of a free software
++// library without restriction.  Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License.  This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.1.5 - Template class codecvt
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <locale>
++#include <bits/c++locale_internal.h>
++
++namespace std
++{
++  // Specializations.
++#ifdef _GLIBCXX_USE_WCHAR_T
++  codecvt_base::result
++  codecvt<wchar_t, char, mbstate_t>::
++  do_out(state_type& __state, const intern_type* __from, 
++       const intern_type* __from_end, const intern_type*& __from_next,
++       extern_type* __to, extern_type* __to_end,
++       extern_type*& __to_next) const
++  {
++    result __ret = ok;
++    state_type __tmp_state(__state);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++    __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++
++    // wcsnrtombs is *very* fast but stops if encounters NUL characters:
++    // in case we fall back to wcrtomb and then continue, in a loop.
++    // NB: wcsnrtombs is a GNU extension
++    for (__from_next = __from, __to_next = __to;
++       __from_next < __from_end && __to_next < __to_end
++       && __ret == ok;)
++      {
++      const intern_type* __from_chunk_end = wmemchr(__from_next, L'\0',
++                                                    __from_end - __from_next);
++      if (!__from_chunk_end)
++        __from_chunk_end = __from_end;
++
++      __from = __from_next;
++      const size_t __conv = wcsnrtombs(__to_next, &__from_next,
++                                       __from_chunk_end - __from_next,
++                                       __to_end - __to_next, &__state);
++      if (__conv == static_cast<size_t>(-1))
++        {
++          // In case of error, in order to stop at the exact place we
++          // have to start again from the beginning with a series of
++          // wcrtomb.
++          for (; __from < __from_next; ++__from)
++            __to_next += wcrtomb(__to_next, *__from, &__tmp_state);
++          __state = __tmp_state;
++          __ret = error;
++        }
++      else if (__from_next && __from_next < __from_chunk_end)
++        {
++          __to_next += __conv;
++          __ret = partial;
++        }
++      else
++        {
++          __from_next = __from_chunk_end;
++          __to_next += __conv;
++        }
++
++      if (__from_next < __from_end && __ret == ok)
++        {
++          extern_type __buf[MB_LEN_MAX];
++          __tmp_state = __state;
++          const size_t __conv = wcrtomb(__buf, *__from_next, &__tmp_state);
++          if (__conv > static_cast<size_t>(__to_end - __to_next))
++            __ret = partial;
++          else
++            {
++              memcpy(__to_next, __buf, __conv);
++              __state = __tmp_state;
++              __to_next += __conv;
++              ++__from_next;
++            }
++        }
++      }
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++    __uselocale(__old);
++#endif
++
++    return __ret; 
++  }
++  
++  codecvt_base::result
++  codecvt<wchar_t, char, mbstate_t>::
++  do_in(state_type& __state, const extern_type* __from, 
++      const extern_type* __from_end, const extern_type*& __from_next,
++      intern_type* __to, intern_type* __to_end,
++      intern_type*& __to_next) const
++  {
++    result __ret = ok;
++    state_type __tmp_state(__state);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++    __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++
++    // mbsnrtowcs is *very* fast but stops if encounters NUL characters:
++    // in case we store a L'\0' and then continue, in a loop.
++    // NB: mbsnrtowcs is a GNU extension
++    for (__from_next = __from, __to_next = __to;
++       __from_next < __from_end && __to_next < __to_end
++       && __ret == ok;)
++      {
++      const extern_type* __from_chunk_end;
++      __from_chunk_end = static_cast<const extern_type*>(memchr(__from_next, '\0',
++                                                                __from_end
++                                                                - __from_next));
++      if (!__from_chunk_end)
++        __from_chunk_end = __from_end;
++
++      __from = __from_next;
++      size_t __conv = mbsnrtowcs(__to_next, &__from_next,
++                                 __from_chunk_end - __from_next,
++                                 __to_end - __to_next, &__state);
++      if (__conv == static_cast<size_t>(-1))
++        {
++          // In case of error, in order to stop at the exact place we
++          // have to start again from the beginning with a series of
++          // mbrtowc.
++          for (;; ++__to_next, __from += __conv)
++            {
++              __conv = mbrtowc(__to_next, __from, __from_end - __from,
++                               &__tmp_state);
++              if (__conv == static_cast<size_t>(-1)
++                  || __conv == static_cast<size_t>(-2))
++                break;
++            }
++          __from_next = __from;
++          __state = __tmp_state;          
++          __ret = error;
++        }
++      else if (__from_next && __from_next < __from_chunk_end)
++        {
++          // It is unclear what to return in this case (see DR 382). 
++          __to_next += __conv;
++          __ret = partial;
++        }
++      else
++        {
++          __from_next = __from_chunk_end;
++          __to_next += __conv;
++        }
++
++      if (__from_next < __from_end && __ret == ok)
++        {
++          if (__to_next < __to_end)
++            {
++              // XXX Probably wrong for stateful encodings
++              __tmp_state = __state;          
++              ++__from_next;
++              *__to_next++ = L'\0';
++            }
++          else
++            __ret = partial;
++        }
++      }
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++    __uselocale(__old);
++#endif
++
++    return __ret; 
++  }
++
++  int 
++  codecvt<wchar_t, char, mbstate_t>::
++  do_encoding() const throw()
++  {
++    // XXX This implementation assumes that the encoding is
++    // stateless and is either single-byte or variable-width.
++    int __ret = 0;
++#ifdef __UCLIBC_HAS_XLOCALE__
++    __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++    if (MB_CUR_MAX == 1)
++      __ret = 1;
++#ifdef __UCLIBC_HAS_XLOCALE__
++    __uselocale(__old);
++#endif
++    return __ret;
++  }  
++
++  int 
++  codecvt<wchar_t, char, mbstate_t>::
++  do_max_length() const throw()
++  {
++#ifdef __UCLIBC_HAS_XLOCALE__
++    __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++    // XXX Probably wrong for stateful encodings.
++    int __ret = MB_CUR_MAX;
++#ifdef __UCLIBC_HAS_XLOCALE__
++    __uselocale(__old);
++#endif
++    return __ret;
++  }
++  
++  int 
++  codecvt<wchar_t, char, mbstate_t>::
++  do_length(state_type& __state, const extern_type* __from,
++          const extern_type* __end, size_t __max) const
++  {
++    int __ret = 0;
++    state_type __tmp_state(__state);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++    __c_locale __old = __uselocale(_M_c_locale_codecvt);
++#endif
++
++    // mbsnrtowcs is *very* fast but stops if encounters NUL characters:
++    // in case we advance past it and then continue, in a loop.
++    // NB: mbsnrtowcs is a GNU extension
++  
++    // A dummy internal buffer is needed in order for mbsnrtocws to consider
++    // its fourth parameter (it wouldn't with NULL as first parameter).
++    wchar_t* __to = static_cast<wchar_t*>(__builtin_alloca(sizeof(wchar_t) 
++                                                         * __max));
++    while (__from < __end && __max)
++      {
++      const extern_type* __from_chunk_end;
++      __from_chunk_end = static_cast<const extern_type*>(memchr(__from, '\0',
++                                                                __end
++                                                                - __from));
++      if (!__from_chunk_end)
++        __from_chunk_end = __end;
++
++      const extern_type* __tmp_from = __from;
++      size_t __conv = mbsnrtowcs(__to, &__from,
++                                 __from_chunk_end - __from,
++                                 __max, &__state);
++      if (__conv == static_cast<size_t>(-1))
++        {
++          // In case of error, in order to stop at the exact place we
++          // have to start again from the beginning with a series of
++          // mbrtowc.
++          for (__from = __tmp_from;; __from += __conv)
++            {
++              __conv = mbrtowc(NULL, __from, __end - __from,
++                               &__tmp_state);
++              if (__conv == static_cast<size_t>(-1)
++                  || __conv == static_cast<size_t>(-2))
++                break;
++            }
++          __state = __tmp_state;
++          __ret += __from - __tmp_from;
++          break;
++        }
++      if (!__from)
++        __from = __from_chunk_end;
++      
++      __ret += __from - __tmp_from;
++      __max -= __conv;
++
++      if (__from < __end && __max)
++        {
++          // XXX Probably wrong for stateful encodings
++          __tmp_state = __state;
++          ++__from;
++          ++__ret;
++          --__max;
++        }
++      }
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++    __uselocale(__old);
++#endif
++
++    return __ret; 
++  }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/collate_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/collate_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/collate_members.cc        1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/collate_members.cc     2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,80 @@
++// std::collate implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library.  This library 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.
++
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++
++// You should have received a copy of the GNU General Public License along
++// with this library; 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, you may use this file as part of a free software
++// library without restriction.  Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License.  This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.4.1.2  collate virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <locale>
++#include <bits/c++locale_internal.h>
++
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __strcoll_l(S1, S2, L)      strcoll((S1), (S2))
++#define __strxfrm_l(S1, S2, N, L)   strxfrm((S1), (S2), (N))
++#define __wcscoll_l(S1, S2, L)      wcscoll((S1), (S2))
++#define __wcsxfrm_l(S1, S2, N, L)   wcsxfrm((S1), (S2), (N))
++#endif
++
++namespace std
++{
++  // These are basically extensions to char_traits, and perhaps should
++  // be put there instead of here.
++  template<>
++    int 
++    collate<char>::_M_compare(const char* __one, const char* __two) const
++    { 
++      int __cmp = __strcoll_l(__one, __two, _M_c_locale_collate);
++      return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0);
++    }
++  
++  template<>
++    size_t
++    collate<char>::_M_transform(char* __to, const char* __from, 
++                              size_t __n) const 
++    { return __strxfrm_l(__to, __from, __n, _M_c_locale_collate); }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++  template<>
++    int 
++    collate<wchar_t>::_M_compare(const wchar_t* __one, 
++                               const wchar_t* __two) const
++    {
++      int __cmp = __wcscoll_l(__one, __two, _M_c_locale_collate);
++      return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0);
++    }
++  
++  template<>
++    size_t
++    collate<wchar_t>::_M_transform(wchar_t* __to, const wchar_t* __from,
++                                 size_t __n) const
++    { return __wcsxfrm_l(__to, __from, __n, _M_c_locale_collate); }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/ctype_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/ctype_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/ctype_members.cc  1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/ctype_members.cc       2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,300 @@
++// std::ctype implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library.  This library 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.
++
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++
++// You should have received a copy of the GNU General Public License along
++// with this library; 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, you may use this file as part of a free software
++// library without restriction.  Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License.  This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.1.1.2  ctype virtual functions.
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#define _LIBC
++#include <locale>
++#undef _LIBC
++#include <bits/c++locale_internal.h>
++
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __wctype_l(S, L)           wctype((S))
++#define __towupper_l(C, L)         towupper((C))
++#define __towlower_l(C, L)         towlower((C))
++#define __iswctype_l(C, M, L)      iswctype((C), (M))
++#endif
++
++namespace std
++{
++  // NB: The other ctype<char> specializations are in src/locale.cc and
++  // various /config/os/* files.
++  template<>
++    ctype_byname<char>::ctype_byname(const char* __s, size_t __refs)
++    : ctype<char>(0, false, __refs) 
++    {                 
++      if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
++      {
++        this->_S_destroy_c_locale(this->_M_c_locale_ctype);
++        this->_S_create_c_locale(this->_M_c_locale_ctype, __s); 
++#ifdef __UCLIBC_HAS_XLOCALE__
++        this->_M_toupper = this->_M_c_locale_ctype->__ctype_toupper;
++        this->_M_tolower = this->_M_c_locale_ctype->__ctype_tolower;
++        this->_M_table = this->_M_c_locale_ctype->__ctype_b;
++#endif
++      }
++    }
++
++#ifdef _GLIBCXX_USE_WCHAR_T  
++  ctype<wchar_t>::__wmask_type
++  ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const
++  {
++    __wmask_type __ret;
++    switch (__m)
++      {
++      case space:
++      __ret = __wctype_l("space", _M_c_locale_ctype);
++      break;
++      case print:
++      __ret = __wctype_l("print", _M_c_locale_ctype);
++      break;
++      case cntrl:
++      __ret = __wctype_l("cntrl", _M_c_locale_ctype);
++      break;
++      case upper:
++      __ret = __wctype_l("upper", _M_c_locale_ctype);
++      break;
++      case lower:
++      __ret = __wctype_l("lower", _M_c_locale_ctype);
++      break;
++      case alpha:
++      __ret = __wctype_l("alpha", _M_c_locale_ctype);
++      break;
++      case digit:
++      __ret = __wctype_l("digit", _M_c_locale_ctype);
++      break;
++      case punct:
++      __ret = __wctype_l("punct", _M_c_locale_ctype);
++      break;
++      case xdigit:
++      __ret = __wctype_l("xdigit", _M_c_locale_ctype);
++      break;
++      case alnum:
++      __ret = __wctype_l("alnum", _M_c_locale_ctype);
++      break;
++      case graph:
++      __ret = __wctype_l("graph", _M_c_locale_ctype);
++      break;
++      default:
++      __ret = 0;
++      }
++    return __ret;
++  }
++  
++  wchar_t
++  ctype<wchar_t>::do_toupper(wchar_t __c) const
++  { return __towupper_l(__c, _M_c_locale_ctype); }
++
++  const wchar_t*
++  ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const
++  {
++    while (__lo < __hi)
++      {
++        *__lo = __towupper_l(*__lo, _M_c_locale_ctype);
++        ++__lo;
++      }
++    return __hi;
++  }
++  
++  wchar_t
++  ctype<wchar_t>::do_tolower(wchar_t __c) const
++  { return __towlower_l(__c, _M_c_locale_ctype); }
++  
++  const wchar_t*
++  ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const
++  {
++    while (__lo < __hi)
++      {
++        *__lo = __towlower_l(*__lo, _M_c_locale_ctype);
++        ++__lo;
++      }
++    return __hi;
++  }
++
++  bool
++  ctype<wchar_t>::
++  do_is(mask __m, wchar_t __c) const
++  { 
++    // Highest bitmask in ctype_base == 10, but extra in "C"
++    // library for blank.
++    bool __ret = false;
++    const size_t __bitmasksize = 11; 
++    for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
++      if (__m & _M_bit[__bitcur]
++        && __iswctype_l(__c, _M_wmask[__bitcur], _M_c_locale_ctype))
++      {
++        __ret = true;
++        break;
++      }
++    return __ret;    
++  }
++  
++  const wchar_t* 
++  ctype<wchar_t>::
++  do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __vec) const
++  {
++    for (; __lo < __hi; ++__vec, ++__lo)
++      {
++      // Highest bitmask in ctype_base == 10, but extra in "C"
++      // library for blank.
++      const size_t __bitmasksize = 11; 
++      mask __m = 0;
++      for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
++        if (__iswctype_l(*__lo, _M_wmask[__bitcur], _M_c_locale_ctype))
++          __m |= _M_bit[__bitcur];
++      *__vec = __m;
++      }
++    return __hi;
++  }
++  
++  const wchar_t* 
++  ctype<wchar_t>::
++  do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const
++  {
++    while (__lo < __hi && !this->do_is(__m, *__lo))
++      ++__lo;
++    return __lo;
++  }
++
++  const wchar_t*
++  ctype<wchar_t>::
++  do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const
++  {
++    while (__lo < __hi && this->do_is(__m, *__lo) != 0)
++      ++__lo;
++    return __lo;
++  }
++
++  wchar_t
++  ctype<wchar_t>::
++  do_widen(char __c) const
++  { return _M_widen[static_cast<unsigned char>(__c)]; }
++
++  const char* 
++  ctype<wchar_t>::
++  do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const
++  {
++    while (__lo < __hi)
++      {
++      *__dest = _M_widen[static_cast<unsigned char>(*__lo)];
++      ++__lo;
++      ++__dest;
++      }
++    return __hi;
++  }
++
++  char
++  ctype<wchar_t>::
++  do_narrow(wchar_t __wc, char __dfault) const
++  {
++    if (__wc >= 0 && __wc < 128 && _M_narrow_ok)
++      return _M_narrow[__wc];
++#ifdef __UCLIBC_HAS_XLOCALE__
++    __c_locale __old = __uselocale(_M_c_locale_ctype);
++#endif
++    const int __c = wctob(__wc);
++#ifdef __UCLIBC_HAS_XLOCALE__
++    __uselocale(__old);
++#endif
++    return (__c == EOF ? __dfault : static_cast<char>(__c)); 
++  }
++
++  const wchar_t*
++  ctype<wchar_t>::
++  do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault, 
++          char* __dest) const
++  {
++#ifdef __UCLIBC_HAS_XLOCALE__
++    __c_locale __old = __uselocale(_M_c_locale_ctype);
++#endif
++    if (_M_narrow_ok)
++      while (__lo < __hi)
++      {
++        if (*__lo >= 0 && *__lo < 128)
++          *__dest = _M_narrow[*__lo];
++        else
++          {
++            const int __c = wctob(*__lo);
++            *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
++          }
++        ++__lo;
++        ++__dest;
++      }
++    else
++      while (__lo < __hi)
++      {
++        const int __c = wctob(*__lo);
++        *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
++        ++__lo;
++        ++__dest;
++      }
++#ifdef __UCLIBC_HAS_XLOCALE__
++    __uselocale(__old);
++#endif
++    return __hi;
++  }
++
++  void
++  ctype<wchar_t>::_M_initialize_ctype()
++  {
++#ifdef __UCLIBC_HAS_XLOCALE__
++    __c_locale __old = __uselocale(_M_c_locale_ctype);
++#endif
++    wint_t __i;
++    for (__i = 0; __i < 128; ++__i)
++      {
++      const int __c = wctob(__i);
++      if (__c == EOF)
++        break;
++      else
++        _M_narrow[__i] = static_cast<char>(__c);
++      }
++    if (__i == 128)
++      _M_narrow_ok = true;
++    else
++      _M_narrow_ok = false;
++    for (size_t __j = 0;
++       __j < sizeof(_M_widen) / sizeof(wint_t); ++__j)
++      _M_widen[__j] = btowc(__j);
++
++    for (size_t __k = 0; __k <= 11; ++__k)
++      { 
++      _M_bit[__k] = static_cast<mask>(_ISbit(__k));
++      _M_wmask[__k] = _M_convert_to_wmask(_M_bit[__k]);
++      }
++#ifdef __UCLIBC_HAS_XLOCALE__
++    __uselocale(__old);
++#endif
++  }
++#endif //  _GLIBCXX_USE_WCHAR_T
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/messages_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/messages_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/messages_members.cc       1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/messages_members.cc    2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,100 @@
++// std::messages implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library.  This library 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.
++
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++
++// You should have received a copy of the GNU General Public License along
++// with this library; 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, you may use this file as part of a free software
++// library without restriction.  Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License.  This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.7.1.2  messages virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <locale>
++#include <bits/c++locale_internal.h>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix gettext stuff
++#endif
++#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
++extern "C" char *__dcgettext(const char *domainname,
++                           const char *msgid, int category);
++#undef gettext
++#define gettext(msgid) __dcgettext(NULL, msgid, LC_MESSAGES)
++#else
++#undef gettext
++#define gettext(msgid) (msgid)
++#endif
++
++namespace std
++{
++  // Specializations.
++  template<>
++    string
++    messages<char>::do_get(catalog, int, int, const string& __dfault) const
++    {
++#ifdef __UCLIBC_HAS_XLOCALE__
++      __c_locale __old = __uselocale(_M_c_locale_messages);
++      const char* __msg = const_cast<const char*>(gettext(__dfault.c_str()));
++      __uselocale(__old);
++      return string(__msg);
++#elif defined __UCLIBC_HAS_LOCALE__
++      char* __old = strdup(setlocale(LC_ALL, NULL));
++      setlocale(LC_ALL, _M_name_messages);
++      const char* __msg = gettext(__dfault.c_str());
++      setlocale(LC_ALL, __old);
++      free(__old);
++      return string(__msg);
++#else
++      const char* __msg = gettext(__dfault.c_str());
++      return string(__msg);
++#endif
++    }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++  template<>
++    wstring
++    messages<wchar_t>::do_get(catalog, int, int, const wstring& __dfault) const
++    {
++# ifdef __UCLIBC_HAS_XLOCALE__
++      __c_locale __old = __uselocale(_M_c_locale_messages);
++      char* __msg = gettext(_M_convert_to_char(__dfault));
++      __uselocale(__old);
++      return _M_convert_from_char(__msg);
++# elif defined __UCLIBC_HAS_LOCALE__
++      char* __old = strdup(setlocale(LC_ALL, NULL));
++      setlocale(LC_ALL, _M_name_messages);
++      char* __msg = gettext(_M_convert_to_char(__dfault));
++      setlocale(LC_ALL, __old);
++      free(__old);
++      return _M_convert_from_char(__msg);
++# else
++      char* __msg = gettext(_M_convert_to_char(__dfault));
++      return _M_convert_from_char(__msg);
++# endif
++    }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/messages_members.h gcc-3.4.2/libstdc++-v3/config/locale/uclibc/messages_members.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/messages_members.h        1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/messages_members.h     2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,118 @@
++// std::messages implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library.  This library 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.
++
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++
++// You should have received a copy of the GNU General Public License along
++// with this library; 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, you may use this file as part of a free software
++// library without restriction.  Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License.  This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.7.1.2  messages functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix prototypes for *textdomain funcs
++#endif
++#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
++extern "C" char *__textdomain(const char *domainname);
++extern "C" char *__bindtextdomain(const char *domainname,
++                                const char *dirname);
++#else
++#undef __textdomain
++#undef __bindtextdomain
++#define __textdomain(D)           ((void)0)
++#define __bindtextdomain(D,P)     ((void)0)
++#endif
++
++  // Non-virtual member functions.
++  template<typename _CharT>
++     messages<_CharT>::messages(size_t __refs)
++     : facet(__refs), _M_c_locale_messages(_S_get_c_locale()), 
++     _M_name_messages(_S_get_c_name())
++     { }
++
++  template<typename _CharT>
++     messages<_CharT>::messages(__c_locale __cloc, const char* __s, 
++                              size_t __refs) 
++     : facet(__refs), _M_c_locale_messages(_S_clone_c_locale(__cloc)),
++     _M_name_messages(__s)
++     {
++       char* __tmp = new char[std::strlen(__s) + 1];
++       std::strcpy(__tmp, __s);
++       _M_name_messages = __tmp;
++     }
++
++  template<typename _CharT>
++    typename messages<_CharT>::catalog 
++    messages<_CharT>::open(const basic_string<char>& __s, const locale& __loc, 
++                         const char* __dir) const
++    { 
++      __bindtextdomain(__s.c_str(), __dir);
++      return this->do_open(__s, __loc); 
++    }
++
++  // Virtual member functions.
++  template<typename _CharT>
++    messages<_CharT>::~messages()
++    { 
++      if (_M_name_messages != _S_get_c_name())
++      delete [] _M_name_messages;
++      _S_destroy_c_locale(_M_c_locale_messages); 
++    }
++
++  template<typename _CharT>
++    typename messages<_CharT>::catalog 
++    messages<_CharT>::do_open(const basic_string<char>& __s, 
++                            const locale&) const
++    { 
++      // No error checking is done, assume the catalog exists and can
++      // be used.
++      __textdomain(__s.c_str());
++      return 0;
++    }
++
++  template<typename _CharT>
++    void    
++    messages<_CharT>::do_close(catalog) const 
++    { }
++
++   // messages_byname
++   template<typename _CharT>
++     messages_byname<_CharT>::messages_byname(const char* __s, size_t __refs)
++     : messages<_CharT>(__refs) 
++     { 
++       if (this->_M_name_messages != locale::facet::_S_get_c_name())
++       delete [] this->_M_name_messages;
++       char* __tmp = new char[std::strlen(__s) + 1];
++       std::strcpy(__tmp, __s);
++       this->_M_name_messages = __tmp;
++
++       if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
++       {
++         this->_S_destroy_c_locale(this->_M_c_locale_messages);
++         this->_S_create_c_locale(this->_M_c_locale_messages, __s); 
++       }
++     }
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/monetary_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/monetary_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/monetary_members.cc       1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/monetary_members.cc    2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,698 @@
++// std::moneypunct implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library.  This library 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.
++
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++
++// You should have received a copy of the GNU General Public License along
++// with this library; 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, you may use this file as part of a free software
++// library without restriction.  Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License.  This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.6.3.2  moneypunct virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#define _LIBC
++#include <locale>
++#undef _LIBC
++#include <bits/c++locale_internal.h>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning optimize this for uclibc
++#warning tailor for stub locale support
++#endif
++
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __nl_langinfo_l(N, L)         nl_langinfo((N))
++#endif
++
++namespace std
++{
++  // Construct and return valid pattern consisting of some combination of:
++  // space none symbol sign value
++  money_base::pattern
++  money_base::_S_construct_pattern(char __precedes, char __space, char __posn)
++  { 
++    pattern __ret;
++
++    // This insanely complicated routine attempts to construct a valid
++    // pattern for use with monyepunct. A couple of invariants:
++
++    // if (__precedes) symbol -> value
++    // else value -> symbol
++    
++    // if (__space) space
++    // else none
++
++    // none == never first
++    // space never first or last
++
++    // Any elegant implementations of this are welcome.
++    switch (__posn)
++      {
++      case 0:
++      case 1:
++      // 1 The sign precedes the value and symbol.
++      __ret.field[0] = sign;
++      if (__space)
++        {
++          // Pattern starts with sign.
++          if (__precedes)
++            {
++              __ret.field[1] = symbol;
++              __ret.field[3] = value;
++            }
++          else
++            {
++              __ret.field[1] = value;
++              __ret.field[3] = symbol;
++            }
++          __ret.field[2] = space;
++        }
++      else
++        {
++          // Pattern starts with sign and ends with none.
++          if (__precedes)
++            {
++              __ret.field[1] = symbol;
++              __ret.field[2] = value;
++            }
++          else
++            {
++              __ret.field[1] = value;
++              __ret.field[2] = symbol;
++            }
++          __ret.field[3] = none;
++        }
++      break;
++      case 2:
++      // 2 The sign follows the value and symbol.
++      if (__space)
++        {
++          // Pattern either ends with sign.
++          if (__precedes)
++            {
++              __ret.field[0] = symbol;
++              __ret.field[2] = value;
++            }
++          else
++            {
++              __ret.field[0] = value;
++              __ret.field[2] = symbol;
++            }
++          __ret.field[1] = space;
++          __ret.field[3] = sign;
++        }
++      else
++        {
++          // Pattern ends with sign then none.
++          if (__precedes)
++            {
++              __ret.field[0] = symbol;
++              __ret.field[1] = value;
++            }
++          else
++            {
++              __ret.field[0] = value;
++              __ret.field[1] = symbol;
++            }
++          __ret.field[2] = sign;
++          __ret.field[3] = none;
++        }
++      break;
++      case 3:
++      // 3 The sign immediately precedes the symbol.
++      if (__precedes)
++        {
++          __ret.field[0] = sign;
++          __ret.field[1] = symbol;        
++          if (__space)
++            {
++              __ret.field[2] = space;
++              __ret.field[3] = value;
++            }
++          else
++            {
++              __ret.field[2] = value;         
++              __ret.field[3] = none;
++            }
++        }
++      else
++        {
++          __ret.field[0] = value;
++          if (__space)
++            {
++              __ret.field[1] = space;
++              __ret.field[2] = sign;
++              __ret.field[3] = symbol;
++            }
++          else
++            {
++              __ret.field[1] = sign;
++              __ret.field[2] = symbol;
++              __ret.field[3] = none;
++            }
++        }
++      break;
++      case 4:
++      // 4 The sign immediately follows the symbol.
++      if (__precedes)
++        {
++          __ret.field[0] = symbol;
++          __ret.field[1] = sign;
++          if (__space)
++            {
++              __ret.field[2] = space;
++              __ret.field[3] = value;
++            }
++          else
++            {
++              __ret.field[2] = value;
++              __ret.field[3] = none;
++            }
++        }
++      else
++        {
++          __ret.field[0] = value;
++          if (__space)
++            {
++              __ret.field[1] = space;
++              __ret.field[2] = symbol;
++              __ret.field[3] = sign;
++            }
++          else
++            {
++              __ret.field[1] = symbol;
++              __ret.field[2] = sign;
++              __ret.field[3] = none;
++            }
++        }
++      break;
++      default:
++      ;
++      }
++    return __ret;
++  }
++
++  template<> 
++    void
++    moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc, 
++                                                   const char*)
++    {
++      if (!_M_data)
++      _M_data = new __moneypunct_cache<char, true>;
++
++      if (!__cloc)
++      {
++        // "C" locale
++        _M_data->_M_decimal_point = '.';
++        _M_data->_M_thousands_sep = ',';
++        _M_data->_M_grouping = "";
++        _M_data->_M_grouping_size = 0;
++        _M_data->_M_curr_symbol = "";
++        _M_data->_M_curr_symbol_size = 0;
++        _M_data->_M_positive_sign = "";
++        _M_data->_M_positive_sign_size = 0;
++        _M_data->_M_negative_sign = "";
++        _M_data->_M_negative_sign_size = 0;
++        _M_data->_M_frac_digits = 0;
++        _M_data->_M_pos_format = money_base::_S_default_pattern;
++        _M_data->_M_neg_format = money_base::_S_default_pattern;
++
++        for (size_t __i = 0; __i < money_base::_S_end; ++__i)
++          _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
++      }
++      else
++      {
++        // Named locale.
++        _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT, 
++                                                      __cloc));
++        _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, 
++                                                      __cloc));
++        _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
++        _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++        _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
++        _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign);
++
++        char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
++        if (!__nposn)
++          _M_data->_M_negative_sign = "()";
++        else
++          _M_data->_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN, 
++                                                      __cloc);
++        _M_data->_M_negative_sign_size = strlen(_M_data->_M_negative_sign);
++
++        // _Intl == true
++        _M_data->_M_curr_symbol = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
++        _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol);
++        _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, 
++                                                    __cloc));
++        char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
++        char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
++        char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
++        _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, 
++                                                      __pposn);
++        char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
++        char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
++        _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, 
++                                                      __nposn);
++      }
++    }
++
++  template<> 
++    void
++    moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc, 
++                                                    const char*)
++    {
++      if (!_M_data)
++      _M_data = new __moneypunct_cache<char, false>;
++
++      if (!__cloc)
++      {
++        // "C" locale
++        _M_data->_M_decimal_point = '.';
++        _M_data->_M_thousands_sep = ',';
++        _M_data->_M_grouping = "";
++        _M_data->_M_grouping_size = 0;
++        _M_data->_M_curr_symbol = "";
++        _M_data->_M_curr_symbol_size = 0;
++        _M_data->_M_positive_sign = "";
++        _M_data->_M_positive_sign_size = 0;
++        _M_data->_M_negative_sign = "";
++        _M_data->_M_negative_sign_size = 0;
++        _M_data->_M_frac_digits = 0;
++        _M_data->_M_pos_format = money_base::_S_default_pattern;
++        _M_data->_M_neg_format = money_base::_S_default_pattern;
++
++        for (size_t __i = 0; __i < money_base::_S_end; ++__i)
++          _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
++      }
++      else
++      {
++        // Named locale.
++        _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT, 
++                                                      __cloc));
++        _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, 
++                                                      __cloc));
++        _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
++        _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++        _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
++        _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign);
++
++        char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
++        if (!__nposn)
++          _M_data->_M_negative_sign = "()";
++        else
++          _M_data->_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN,
++                                                      __cloc);
++        _M_data->_M_negative_sign_size = strlen(_M_data->_M_negative_sign);
++
++        // _Intl == false
++        _M_data->_M_curr_symbol = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
++        _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol);
++        _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
++        char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
++        char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
++        char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
++        _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, 
++                                                      __pposn);
++        char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
++        char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
++        _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, 
++                                                      __nposn);
++      }
++    }
++
++  template<> 
++    moneypunct<char, true>::~moneypunct()
++    { delete _M_data; }
++
++  template<> 
++    moneypunct<char, false>::~moneypunct()
++    { delete _M_data; }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++  template<> 
++    void
++    moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc, 
++#ifdef __UCLIBC_HAS_XLOCALE__
++                                                      const char*)
++#else
++                                                      const char* __name)
++#endif
++    {
++      if (!_M_data)
++      _M_data = new __moneypunct_cache<wchar_t, true>;
++
++      if (!__cloc)
++      {
++        // "C" locale
++        _M_data->_M_decimal_point = L'.';
++        _M_data->_M_thousands_sep = L',';
++        _M_data->_M_grouping = "";
++        _M_data->_M_grouping_size = 0;
++        _M_data->_M_curr_symbol = L"";
++        _M_data->_M_curr_symbol_size = 0;
++        _M_data->_M_positive_sign = L"";
++        _M_data->_M_positive_sign_size = 0;
++        _M_data->_M_negative_sign = L"";
++        _M_data->_M_negative_sign_size = 0;
++        _M_data->_M_frac_digits = 0;
++        _M_data->_M_pos_format = money_base::_S_default_pattern;
++        _M_data->_M_neg_format = money_base::_S_default_pattern;
++
++        // Use ctype::widen code without the facet...
++        unsigned char uc;
++        for (size_t __i = 0; __i < money_base::_S_end; ++__i)
++          {
++            uc = static_cast<unsigned char>(money_base::_S_atoms[__i]);
++            _M_data->_M_atoms[__i] = btowc(uc);
++          }
++      }
++      else
++      {
++        // Named locale.
++#ifdef __UCLIBC_HAS_XLOCALE__
++        __c_locale __old = __uselocale(__cloc);
++#else
++        // Switch to named locale so that mbsrtowcs will work.
++        char* __old = strdup(setlocale(LC_ALL, NULL));
++        setlocale(LC_ALL, __name);
++#endif
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix this... should be monetary
++#endif
++#ifdef __UCLIBC__
++# ifdef __UCLIBC_HAS_XLOCALE__
++        _M_data->_M_decimal_point = __cloc->decimal_point_wc;
++        _M_data->_M_thousands_sep = __cloc->thousands_sep_wc;
++# else
++        _M_data->_M_decimal_point = __global_locale->decimal_point_wc;
++        _M_data->_M_thousands_sep = __global_locale->thousands_sep_wc;
++# endif
++#else
++        union __s_and_w { const char *__s; unsigned int __w; } __u;
++        __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
++        _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
++
++        __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
++        _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
++#endif
++        _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
++        _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++
++        const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
++        const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
++        const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
++
++        wchar_t* __wcs_ps = 0;
++        wchar_t* __wcs_ns = 0;
++        const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
++        try
++          {
++            mbstate_t __state;
++            size_t __len = strlen(__cpossign);
++            if (__len)
++              {
++                ++__len;
++                memset(&__state, 0, sizeof(mbstate_t));
++                __wcs_ps = new wchar_t[__len];
++                mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
++                _M_data->_M_positive_sign = __wcs_ps;
++              }
++            else
++              _M_data->_M_positive_sign = L"";
++            _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
++            
++            __len = strlen(__cnegsign);
++            if (!__nposn)
++              _M_data->_M_negative_sign = L"()";
++            else if (__len)
++              { 
++                ++__len;
++                memset(&__state, 0, sizeof(mbstate_t));
++                __wcs_ns = new wchar_t[__len];
++                mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
++                _M_data->_M_negative_sign = __wcs_ns;
++              }
++            else
++              _M_data->_M_negative_sign = L"";
++            _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
++            
++            // _Intl == true.
++            __len = strlen(__ccurr);
++            if (__len)
++              {
++                ++__len;
++                memset(&__state, 0, sizeof(mbstate_t));
++                wchar_t* __wcs = new wchar_t[__len];
++                mbsrtowcs(__wcs, &__ccurr, __len, &__state);
++                _M_data->_M_curr_symbol = __wcs;
++              }
++            else
++              _M_data->_M_curr_symbol = L"";
++            _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
++          }
++        catch (...)
++          {
++            delete _M_data;
++            _M_data = 0;
++            delete __wcs_ps;
++            delete __wcs_ns;        
++#ifdef __UCLIBC_HAS_XLOCALE__
++            __uselocale(__old);
++#else
++            setlocale(LC_ALL, __old);
++            free(__old);
++#endif
++            __throw_exception_again;
++          } 
++        
++        _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, 
++                                                    __cloc));
++        char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
++        char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
++        char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
++        _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, 
++                                                      __pposn);
++        char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
++        char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
++        _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, 
++                                                      __nposn);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++        __uselocale(__old);
++#else
++        setlocale(LC_ALL, __old);
++        free(__old);
++#endif
++      }
++    }
++
++  template<> 
++  void
++  moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
++#ifdef __UCLIBC_HAS_XLOCALE__
++                                                     const char*)
++#else
++                                                       const char* __name)
++#endif
++  {
++    if (!_M_data)
++      _M_data = new __moneypunct_cache<wchar_t, false>;
++
++    if (!__cloc)
++      {
++        // "C" locale
++        _M_data->_M_decimal_point = L'.';
++        _M_data->_M_thousands_sep = L',';
++        _M_data->_M_grouping = "";
++          _M_data->_M_grouping_size = 0;
++        _M_data->_M_curr_symbol = L"";
++        _M_data->_M_curr_symbol_size = 0;
++        _M_data->_M_positive_sign = L"";
++        _M_data->_M_positive_sign_size = 0;
++        _M_data->_M_negative_sign = L"";
++        _M_data->_M_negative_sign_size = 0;
++        _M_data->_M_frac_digits = 0;
++        _M_data->_M_pos_format = money_base::_S_default_pattern;
++        _M_data->_M_neg_format = money_base::_S_default_pattern;
++
++        // Use ctype::widen code without the facet...
++        unsigned char uc;
++        for (size_t __i = 0; __i < money_base::_S_end; ++__i)
++          {
++            uc = static_cast<unsigned char>(money_base::_S_atoms[__i]);
++            _M_data->_M_atoms[__i] = btowc(uc);
++          }
++      }
++      else
++      {
++        // Named locale.
++#ifdef __UCLIBC_HAS_XLOCALE__
++        __c_locale __old = __uselocale(__cloc);
++#else
++        // Switch to named locale so that mbsrtowcs will work.
++        char* __old = strdup(setlocale(LC_ALL, NULL));
++        setlocale(LC_ALL, __name);
++#endif
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix this... should be monetary
++#endif
++#ifdef __UCLIBC__
++# ifdef __UCLIBC_HAS_XLOCALE__
++        _M_data->_M_decimal_point = __cloc->decimal_point_wc;
++        _M_data->_M_thousands_sep = __cloc->thousands_sep_wc;
++# else
++        _M_data->_M_decimal_point = __global_locale->decimal_point_wc;
++        _M_data->_M_thousands_sep = __global_locale->thousands_sep_wc;
++# endif
++#else
++        union __s_and_w { const char *__s; unsigned int __w; } __u;
++        __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
++        _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
++
++        __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
++        _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
++#endif
++        _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
++          _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++
++        const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
++        const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
++        const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
++
++        wchar_t* __wcs_ps = 0;
++        wchar_t* __wcs_ns = 0;
++        const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
++        try
++            {
++              mbstate_t __state;
++              size_t __len;
++              __len = strlen(__cpossign);
++              if (__len)
++                {
++                ++__len;
++                memset(&__state, 0, sizeof(mbstate_t));
++                __wcs_ps = new wchar_t[__len];
++                mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
++                _M_data->_M_positive_sign = __wcs_ps;
++              }
++            else
++              _M_data->_M_positive_sign = L"";
++              _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
++            
++            __len = strlen(__cnegsign);
++            if (!__nposn)
++              _M_data->_M_negative_sign = L"()";
++            else if (__len)
++              { 
++                ++__len;
++                memset(&__state, 0, sizeof(mbstate_t));
++                __wcs_ns = new wchar_t[__len];
++                mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
++                _M_data->_M_negative_sign = __wcs_ns;
++              }
++            else
++              _M_data->_M_negative_sign = L"";
++              _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
++
++            // _Intl == true.
++            __len = strlen(__ccurr);
++            if (__len)
++              {
++                ++__len;
++                memset(&__state, 0, sizeof(mbstate_t));
++                wchar_t* __wcs = new wchar_t[__len];
++                mbsrtowcs(__wcs, &__ccurr, __len, &__state);
++                _M_data->_M_curr_symbol = __wcs;
++              }
++            else
++              _M_data->_M_curr_symbol = L"";
++              _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
++          }
++          catch (...)
++          {
++            delete _M_data;
++              _M_data = 0;
++            delete __wcs_ps;
++            delete __wcs_ns;        
++#ifdef __UCLIBC_HAS_XLOCALE__
++            __uselocale(__old);
++#else
++            setlocale(LC_ALL, __old);
++            free(__old);
++#endif
++              __throw_exception_again;
++          }
++
++        _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
++        char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
++        char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
++        char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
++        _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, 
++                                                      __pposn);
++        char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
++        char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
++        _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, 
++                                                      __nposn);
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++        __uselocale(__old);
++#else
++        setlocale(LC_ALL, __old);
++        free(__old);
++#endif
++      }
++    }
++
++  template<> 
++    moneypunct<wchar_t, true>::~moneypunct()
++    {
++      if (_M_data->_M_positive_sign_size)
++      delete [] _M_data->_M_positive_sign;
++      if (_M_data->_M_negative_sign_size
++          && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
++      delete [] _M_data->_M_negative_sign;
++      if (_M_data->_M_curr_symbol_size)
++      delete [] _M_data->_M_curr_symbol;
++      delete _M_data;
++    }
++
++  template<> 
++    moneypunct<wchar_t, false>::~moneypunct()
++    {
++      if (_M_data->_M_positive_sign_size)
++      delete [] _M_data->_M_positive_sign;
++      if (_M_data->_M_negative_sign_size
++          && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
++      delete [] _M_data->_M_negative_sign;
++      if (_M_data->_M_curr_symbol_size)
++      delete [] _M_data->_M_curr_symbol;
++      delete _M_data;
++    }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/numeric_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/numeric_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/numeric_members.cc        1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/numeric_members.cc     2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,183 @@
++// std::numpunct implementation details, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library.  This library 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.
++
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++
++// You should have received a copy of the GNU General Public License along
++// with this library; 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, you may use this file as part of a free software
++// library without restriction.  Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License.  This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.3.1.2  numpunct virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#define _LIBC
++#include <locale>
++#undef _LIBC
++#include <bits/c++locale_internal.h>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning tailor for stub locale support
++#endif
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __nl_langinfo_l(N, L)         nl_langinfo((N))
++#endif
++
++namespace std
++{
++  template<> 
++    void
++    numpunct<char>::_M_initialize_numpunct(__c_locale __cloc)
++    {
++      if (!_M_data)
++      _M_data = new __numpunct_cache<char>;
++
++      if (!__cloc)
++      {
++        // "C" locale
++        _M_data->_M_grouping = "";
++        _M_data->_M_grouping_size = 0;
++        _M_data->_M_use_grouping = false;
++
++        _M_data->_M_decimal_point = '.';
++        _M_data->_M_thousands_sep = ',';
++
++        for (size_t __i = 0; __i < __num_base::_S_oend; ++__i)
++          _M_data->_M_atoms_out[__i] = __num_base::_S_atoms_out[__i];
++
++        for (size_t __j = 0; __j < __num_base::_S_iend; ++__j)
++          _M_data->_M_atoms_in[__j] = __num_base::_S_atoms_in[__j];
++      }
++      else
++      {
++        // Named locale.
++        _M_data->_M_decimal_point = *(__nl_langinfo_l(DECIMAL_POINT, 
++                                                      __cloc));
++        _M_data->_M_thousands_sep = *(__nl_langinfo_l(THOUSANDS_SEP, 
++                                                      __cloc));
++
++        // Check for NULL, which implies no grouping.
++        if (_M_data->_M_thousands_sep == '\0')
++          _M_data->_M_grouping = "";
++        else
++          _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
++        _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++      }
++
++      // NB: There is no way to extact this info from posix locales.
++      // _M_truename = __nl_langinfo_l(YESSTR, __cloc);
++      _M_data->_M_truename = "true";
++      _M_data->_M_truename_size = strlen(_M_data->_M_truename);
++      // _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
++      _M_data->_M_falsename = "false";
++      _M_data->_M_falsename_size = strlen(_M_data->_M_falsename);
++    }
++ 
++  template<> 
++    numpunct<char>::~numpunct()
++    { delete _M_data; }
++   
++#ifdef _GLIBCXX_USE_WCHAR_T
++  template<> 
++    void
++    numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc)
++    {
++      if (!_M_data)
++      _M_data = new __numpunct_cache<wchar_t>;
++
++      if (!__cloc)
++      {
++        // "C" locale
++        _M_data->_M_grouping = "";
++        _M_data->_M_grouping_size = 0;
++        _M_data->_M_use_grouping = false;
++
++        _M_data->_M_decimal_point = L'.';
++        _M_data->_M_thousands_sep = L',';
++
++#ifdef __UCLIBC_HAS_XLOCALE__
++        __c_locale __old = __uselocale(_S_get_c_locale());
++#endif
++        // Use ctype::widen code without the facet...
++        unsigned char uc;
++        for (size_t __i = 0; __i < __num_base::_S_oend; ++__i)
++          {
++            uc = static_cast<unsigned char>(__num_base::_S_atoms_out[__i]);
++            _M_data->_M_atoms_out[__i] = btowc(uc);
++          }
++
++        for (size_t __j = 0; __j < __num_base::_S_iend; ++__j)
++          {
++            uc = static_cast<unsigned char>(__num_base::_S_atoms_in[__j]);
++            _M_data->_M_atoms_in[__j] = btowc(uc);
++          }
++#ifdef __UCLIBC_HAS_XLOCALE__
++        __uselocale(__old);
++#endif
++      }
++      else
++      {
++        // Named locale.
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning fix this
++#endif
++#ifdef __UCLIBC__
++# ifdef __UCLIBC_HAS_XLOCALE__
++        _M_data->_M_decimal_point = __cloc->decimal_point_wc;
++        _M_data->_M_thousands_sep = __cloc->thousands_sep_wc;
++# else
++        _M_data->_M_decimal_point = __global_locale->decimal_point_wc;
++        _M_data->_M_thousands_sep = __global_locale->thousands_sep_wc;
++# endif
++#else
++        union __s_and_w { const char *__s; unsigned int __w; } __u;
++        __u.__s = __nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc);
++        _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
++
++        __u.__s = __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc);
++        _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
++#endif
++
++        if (_M_data->_M_thousands_sep == L'\0')
++          _M_data->_M_grouping = "";
++        else
++          _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
++        _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
++      }
++
++      // NB: There is no way to extact this info from posix locales.
++      // _M_truename = __nl_langinfo_l(YESSTR, __cloc);
++      _M_data->_M_truename = L"true";
++      _M_data->_M_truename_size = wcslen(_M_data->_M_truename);
++      // _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
++      _M_data->_M_falsename = L"false";
++      _M_data->_M_falsename_size = wcslen(_M_data->_M_falsename);
++    }
++
++  template<> 
++    numpunct<wchar_t>::~numpunct()
++    { delete _M_data; }
++ #endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/time_members.cc gcc-3.4.2/libstdc++-v3/config/locale/uclibc/time_members.cc
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/time_members.cc   1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/time_members.cc        2004-09-10 10:48:00.000000000 -0500
+@@ -0,0 +1,356 @@
++// std::time_get, std::time_put implementation, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library.  This library 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.
++
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++
++// You should have received a copy of the GNU General Public License along
++// with this library; 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, you may use this file as part of a free software
++// library without restriction.  Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License.  This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.5.1.2 - time_get virtual functions
++// ISO C++ 14882: 22.2.5.3.2 - time_put virtual functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++#include <locale>
++#include <bits/c++locale_internal.h>
++
++#ifdef __UCLIBC_MJN3_ONLY__
++#warning tailor for stub locale support
++#endif
++#ifndef __UCLIBC_HAS_XLOCALE__
++#define __nl_langinfo_l(N, L)         nl_langinfo((N))
++#endif
++
++namespace std
++{
++  template<>
++    void
++    __timepunct<char>::
++    _M_put(char* __s, size_t __maxlen, const char* __format, 
++         const tm* __tm) const
++    {
++#ifdef __UCLIBC_HAS_XLOCALE__
++      const size_t __len = __strftime_l(__s, __maxlen, __format, __tm,
++                                      _M_c_locale_timepunct);
++#else
++      char* __old = strdup(setlocale(LC_ALL, NULL));
++      setlocale(LC_ALL, _M_name_timepunct);
++      const size_t __len = strftime(__s, __maxlen, __format, __tm);
++      setlocale(LC_ALL, __old);
++      free(__old);
++#endif
++      // Make sure __s is null terminated.
++      if (__len == 0)
++      __s[0] = '\0';
++    }
++
++  template<> 
++    void
++    __timepunct<char>::_M_initialize_timepunct(__c_locale __cloc)
++    {
++      if (!_M_data)
++      _M_data = new __timepunct_cache<char>;
++
++      if (!__cloc)
++      {
++        // "C" locale
++        _M_c_locale_timepunct = _S_get_c_locale();
++
++        _M_data->_M_date_format = "%m/%d/%y";
++        _M_data->_M_date_era_format = "%m/%d/%y";
++        _M_data->_M_time_format = "%H:%M:%S";
++        _M_data->_M_time_era_format = "%H:%M:%S";
++        _M_data->_M_date_time_format = "";
++        _M_data->_M_date_time_era_format = "";
++        _M_data->_M_am = "AM";
++        _M_data->_M_pm = "PM";
++        _M_data->_M_am_pm_format = "";
++
++        // Day names, starting with "C"'s Sunday.
++        _M_data->_M_day1 = "Sunday";
++        _M_data->_M_day2 = "Monday";
++        _M_data->_M_day3 = "Tuesday";
++        _M_data->_M_day4 = "Wednesday";
++        _M_data->_M_day5 = "Thursday";
++        _M_data->_M_day6 = "Friday";
++        _M_data->_M_day7 = "Saturday";
++
++        // Abbreviated day names, starting with "C"'s Sun.
++        _M_data->_M_aday1 = "Sun";
++        _M_data->_M_aday2 = "Mon";
++        _M_data->_M_aday3 = "Tue";
++        _M_data->_M_aday4 = "Wed";
++        _M_data->_M_aday5 = "Thu";
++        _M_data->_M_aday6 = "Fri";
++        _M_data->_M_aday7 = "Sat";
++
++        // Month names, starting with "C"'s January.
++        _M_data->_M_month01 = "January";
++        _M_data->_M_month02 = "February";
++        _M_data->_M_month03 = "March";
++        _M_data->_M_month04 = "April";
++        _M_data->_M_month05 = "May";
++        _M_data->_M_month06 = "June";
++        _M_data->_M_month07 = "July";
++        _M_data->_M_month08 = "August";
++        _M_data->_M_month09 = "September";
++        _M_data->_M_month10 = "October";
++        _M_data->_M_month11 = "November";
++        _M_data->_M_month12 = "December";
++
++        // Abbreviated month names, starting with "C"'s Jan.
++        _M_data->_M_amonth01 = "Jan";
++        _M_data->_M_amonth02 = "Feb";
++        _M_data->_M_amonth03 = "Mar";
++        _M_data->_M_amonth04 = "Apr";
++        _M_data->_M_amonth05 = "May";
++        _M_data->_M_amonth06 = "Jun";
++        _M_data->_M_amonth07 = "Jul";
++        _M_data->_M_amonth08 = "Aug";
++        _M_data->_M_amonth09 = "Sep";
++        _M_data->_M_amonth10 = "Oct";
++        _M_data->_M_amonth11 = "Nov";
++        _M_data->_M_amonth12 = "Dec";
++      }
++      else
++      {
++        _M_c_locale_timepunct = _S_clone_c_locale(__cloc); 
++
++        _M_data->_M_date_format = __nl_langinfo_l(D_FMT, __cloc);
++        _M_data->_M_date_era_format = __nl_langinfo_l(ERA_D_FMT, __cloc);
++        _M_data->_M_time_format = __nl_langinfo_l(T_FMT, __cloc);
++        _M_data->_M_time_era_format = __nl_langinfo_l(ERA_T_FMT, __cloc);
++        _M_data->_M_date_time_format = __nl_langinfo_l(D_T_FMT, __cloc);
++        _M_data->_M_date_time_era_format = __nl_langinfo_l(ERA_D_T_FMT, __cloc);
++        _M_data->_M_am = __nl_langinfo_l(AM_STR, __cloc);
++        _M_data->_M_pm = __nl_langinfo_l(PM_STR, __cloc);
++        _M_data->_M_am_pm_format = __nl_langinfo_l(T_FMT_AMPM, __cloc);
++
++        // Day names, starting with "C"'s Sunday.
++        _M_data->_M_day1 = __nl_langinfo_l(DAY_1, __cloc);
++        _M_data->_M_day2 = __nl_langinfo_l(DAY_2, __cloc);
++        _M_data->_M_day3 = __nl_langinfo_l(DAY_3, __cloc);
++        _M_data->_M_day4 = __nl_langinfo_l(DAY_4, __cloc);
++        _M_data->_M_day5 = __nl_langinfo_l(DAY_5, __cloc);
++        _M_data->_M_day6 = __nl_langinfo_l(DAY_6, __cloc);
++        _M_data->_M_day7 = __nl_langinfo_l(DAY_7, __cloc);
++
++        // Abbreviated day names, starting with "C"'s Sun.
++        _M_data->_M_aday1 = __nl_langinfo_l(ABDAY_1, __cloc);
++        _M_data->_M_aday2 = __nl_langinfo_l(ABDAY_2, __cloc);
++        _M_data->_M_aday3 = __nl_langinfo_l(ABDAY_3, __cloc);
++        _M_data->_M_aday4 = __nl_langinfo_l(ABDAY_4, __cloc);
++        _M_data->_M_aday5 = __nl_langinfo_l(ABDAY_5, __cloc);
++        _M_data->_M_aday6 = __nl_langinfo_l(ABDAY_6, __cloc);
++        _M_data->_M_aday7 = __nl_langinfo_l(ABDAY_7, __cloc);
++
++        // Month names, starting with "C"'s January.
++        _M_data->_M_month01 = __nl_langinfo_l(MON_1, __cloc);
++        _M_data->_M_month02 = __nl_langinfo_l(MON_2, __cloc);
++        _M_data->_M_month03 = __nl_langinfo_l(MON_3, __cloc);
++        _M_data->_M_month04 = __nl_langinfo_l(MON_4, __cloc);
++        _M_data->_M_month05 = __nl_langinfo_l(MON_5, __cloc);
++        _M_data->_M_month06 = __nl_langinfo_l(MON_6, __cloc);
++        _M_data->_M_month07 = __nl_langinfo_l(MON_7, __cloc);
++        _M_data->_M_month08 = __nl_langinfo_l(MON_8, __cloc);
++        _M_data->_M_month09 = __nl_langinfo_l(MON_9, __cloc);
++        _M_data->_M_month10 = __nl_langinfo_l(MON_10, __cloc);
++        _M_data->_M_month11 = __nl_langinfo_l(MON_11, __cloc);
++        _M_data->_M_month12 = __nl_langinfo_l(MON_12, __cloc);
++
++        // Abbreviated month names, starting with "C"'s Jan.
++        _M_data->_M_amonth01 = __nl_langinfo_l(ABMON_1, __cloc);
++        _M_data->_M_amonth02 = __nl_langinfo_l(ABMON_2, __cloc);
++        _M_data->_M_amonth03 = __nl_langinfo_l(ABMON_3, __cloc);
++        _M_data->_M_amonth04 = __nl_langinfo_l(ABMON_4, __cloc);
++        _M_data->_M_amonth05 = __nl_langinfo_l(ABMON_5, __cloc);
++        _M_data->_M_amonth06 = __nl_langinfo_l(ABMON_6, __cloc);
++        _M_data->_M_amonth07 = __nl_langinfo_l(ABMON_7, __cloc);
++        _M_data->_M_amonth08 = __nl_langinfo_l(ABMON_8, __cloc);
++        _M_data->_M_amonth09 = __nl_langinfo_l(ABMON_9, __cloc);
++        _M_data->_M_amonth10 = __nl_langinfo_l(ABMON_10, __cloc);
++        _M_data->_M_amonth11 = __nl_langinfo_l(ABMON_11, __cloc);
++        _M_data->_M_amonth12 = __nl_langinfo_l(ABMON_12, __cloc);
++      }
++    }
++
++#ifdef _GLIBCXX_USE_WCHAR_T
++  template<>
++    void
++    __timepunct<wchar_t>::
++    _M_put(wchar_t* __s, size_t __maxlen, const wchar_t* __format, 
++         const tm* __tm) const
++    {
++#ifdef __UCLIBC_HAS_XLOCALE__
++      __wcsftime_l(__s, __maxlen, __format, __tm, _M_c_locale_timepunct);
++      const size_t __len = __wcsftime_l(__s, __maxlen, __format, __tm,
++                                      _M_c_locale_timepunct);
++#else
++      char* __old = strdup(setlocale(LC_ALL, NULL));
++      setlocale(LC_ALL, _M_name_timepunct);
++      const size_t __len = wcsftime(__s, __maxlen, __format, __tm);
++      setlocale(LC_ALL, __old);
++      free(__old);
++#endif
++      // Make sure __s is null terminated.
++      if (__len == 0)
++      __s[0] = L'\0';
++    }
++
++  template<> 
++    void
++    __timepunct<wchar_t>::_M_initialize_timepunct(__c_locale __cloc)
++    {
++      if (!_M_data)
++      _M_data = new __timepunct_cache<wchar_t>;
++
++#warning wide time stuff
++//       if (!__cloc)
++      {
++        // "C" locale
++        _M_c_locale_timepunct = _S_get_c_locale();
++
++        _M_data->_M_date_format = L"%m/%d/%y";
++        _M_data->_M_date_era_format = L"%m/%d/%y";
++        _M_data->_M_time_format = L"%H:%M:%S";
++        _M_data->_M_time_era_format = L"%H:%M:%S";
++        _M_data->_M_date_time_format = L"";
++        _M_data->_M_date_time_era_format = L"";
++        _M_data->_M_am = L"AM";
++        _M_data->_M_pm = L"PM";
++        _M_data->_M_am_pm_format = L"";
++
++        // Day names, starting with "C"'s Sunday.
++        _M_data->_M_day1 = L"Sunday";
++        _M_data->_M_day2 = L"Monday";
++        _M_data->_M_day3 = L"Tuesday";
++        _M_data->_M_day4 = L"Wednesday";
++        _M_data->_M_day5 = L"Thursday";
++        _M_data->_M_day6 = L"Friday";
++        _M_data->_M_day7 = L"Saturday";
++
++        // Abbreviated day names, starting with "C"'s Sun.
++        _M_data->_M_aday1 = L"Sun";
++        _M_data->_M_aday2 = L"Mon";
++        _M_data->_M_aday3 = L"Tue";
++        _M_data->_M_aday4 = L"Wed";
++        _M_data->_M_aday5 = L"Thu";
++        _M_data->_M_aday6 = L"Fri";
++        _M_data->_M_aday7 = L"Sat";
++
++        // Month names, starting with "C"'s January.
++        _M_data->_M_month01 = L"January";
++        _M_data->_M_month02 = L"February";
++        _M_data->_M_month03 = L"March";
++        _M_data->_M_month04 = L"April";
++        _M_data->_M_month05 = L"May";
++        _M_data->_M_month06 = L"June";
++        _M_data->_M_month07 = L"July";
++        _M_data->_M_month08 = L"August";
++        _M_data->_M_month09 = L"September";
++        _M_data->_M_month10 = L"October";
++        _M_data->_M_month11 = L"November";
++        _M_data->_M_month12 = L"December";
++
++        // Abbreviated month names, starting with "C"'s Jan.
++        _M_data->_M_amonth01 = L"Jan";
++        _M_data->_M_amonth02 = L"Feb";
++        _M_data->_M_amonth03 = L"Mar";
++        _M_data->_M_amonth04 = L"Apr";
++        _M_data->_M_amonth05 = L"May";
++        _M_data->_M_amonth06 = L"Jun";
++        _M_data->_M_amonth07 = L"Jul";
++        _M_data->_M_amonth08 = L"Aug";
++        _M_data->_M_amonth09 = L"Sep";
++        _M_data->_M_amonth10 = L"Oct";
++        _M_data->_M_amonth11 = L"Nov";
++        _M_data->_M_amonth12 = L"Dec";
++      }
++#if 0
++      else
++      {
++        _M_c_locale_timepunct = _S_clone_c_locale(__cloc); 
++
++        _M_data->_M_date_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WD_FMT, __cloc));
++        _M_data->_M_date_era_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WERA_D_FMT, __cloc));
++        _M_data->_M_time_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WT_FMT, __cloc));
++        _M_data->_M_time_era_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WERA_T_FMT, __cloc));
++        _M_data->_M_date_time_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WD_T_FMT, __cloc));
++        _M_data->_M_date_time_era_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WERA_D_T_FMT, __cloc));
++        _M_data->_M_am = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WAM_STR, __cloc));
++        _M_data->_M_pm = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WPM_STR, __cloc));
++        _M_data->_M_am_pm_format = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WT_FMT_AMPM, __cloc));
++
++        // Day names, starting with "C"'s Sunday.
++        _M_data->_M_day1 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_1, __cloc));
++        _M_data->_M_day2 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_2, __cloc));
++        _M_data->_M_day3 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_3, __cloc));
++        _M_data->_M_day4 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_4, __cloc));
++        _M_data->_M_day5 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_5, __cloc));
++        _M_data->_M_day6 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_6, __cloc));
++        _M_data->_M_day7 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WDAY_7, __cloc));
++
++        // Abbreviated day names, starting with "C"'s Sun.
++        _M_data->_M_aday1 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_1, __cloc));
++        _M_data->_M_aday2 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_2, __cloc));
++        _M_data->_M_aday3 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_3, __cloc));
++        _M_data->_M_aday4 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_4, __cloc));
++        _M_data->_M_aday5 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_5, __cloc));
++        _M_data->_M_aday6 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_6, __cloc));
++        _M_data->_M_aday7 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABDAY_7, __cloc));
++
++        // Month names, starting with "C"'s January.
++        _M_data->_M_month01 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_1, __cloc));
++        _M_data->_M_month02 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_2, __cloc));
++        _M_data->_M_month03 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_3, __cloc));
++        _M_data->_M_month04 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_4, __cloc));
++        _M_data->_M_month05 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_5, __cloc));
++        _M_data->_M_month06 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_6, __cloc));
++        _M_data->_M_month07 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_7, __cloc));
++        _M_data->_M_month08 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_8, __cloc));
++        _M_data->_M_month09 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_9, __cloc));
++        _M_data->_M_month10 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_10, __cloc));
++        _M_data->_M_month11 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_11, __cloc));
++        _M_data->_M_month12 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WMON_12, __cloc));
++
++        // Abbreviated month names, starting with "C"'s Jan.
++        _M_data->_M_amonth01 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_1, __cloc));
++        _M_data->_M_amonth02 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_2, __cloc));
++        _M_data->_M_amonth03 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_3, __cloc));
++        _M_data->_M_amonth04 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_4, __cloc));
++        _M_data->_M_amonth05 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_5, __cloc));
++        _M_data->_M_amonth06 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_6, __cloc));
++        _M_data->_M_amonth07 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_7, __cloc));
++        _M_data->_M_amonth08 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_8, __cloc));
++        _M_data->_M_amonth09 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_9, __cloc));
++        _M_data->_M_amonth10 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_10, __cloc));
++        _M_data->_M_amonth11 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_11, __cloc));
++        _M_data->_M_amonth12 = reinterpret_cast<wchar_t*>(__nl_langinfo_l(_NL_WABMON_12, __cloc));
++      }
++#endif // 0
++    }
++#endif
++}
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/time_members.h gcc-3.4.2/libstdc++-v3/config/locale/uclibc/time_members.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/locale/uclibc/time_members.h    1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/locale/uclibc/time_members.h 2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,68 @@
++// std::time_get, std::time_put implementation, GNU version -*- C++ -*-
++
++// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library.  This library 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.
++
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++
++// You should have received a copy of the GNU General Public License along
++// with this library; 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, you may use this file as part of a free software
++// library without restriction.  Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License.  This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.2.5.1.2 - time_get functions
++// ISO C++ 14882: 22.2.5.3.2 - time_put functions
++//
++
++// Written by Benjamin Kosnik <bkoz@redhat.com>
++
++  template<typename _CharT>
++    __timepunct<_CharT>::__timepunct(size_t __refs) 
++    : facet(__refs), _M_data(NULL), _M_c_locale_timepunct(NULL), 
++    _M_name_timepunct(_S_get_c_name())
++    { _M_initialize_timepunct(); }
++
++  template<typename _CharT>
++    __timepunct<_CharT>::__timepunct(__cache_type* __cache, size_t __refs) 
++    : facet(__refs), _M_data(__cache), _M_c_locale_timepunct(NULL), 
++    _M_name_timepunct(_S_get_c_name())
++    { _M_initialize_timepunct(); }
++
++  template<typename _CharT>
++    __timepunct<_CharT>::__timepunct(__c_locale __cloc, const char* __s,
++                                   size_t __refs) 
++    : facet(__refs), _M_data(NULL), _M_c_locale_timepunct(NULL), 
++    _M_name_timepunct(__s)
++    { 
++      char* __tmp = new char[std::strlen(__s) + 1];
++      std::strcpy(__tmp, __s);
++      _M_name_timepunct = __tmp;
++      _M_initialize_timepunct(__cloc); 
++    }
++
++  template<typename _CharT>
++    __timepunct<_CharT>::~__timepunct()
++    { 
++      if (_M_name_timepunct != _S_get_c_name())
++      delete [] _M_name_timepunct;
++      delete _M_data; 
++      _S_destroy_c_locale(_M_c_locale_timepunct); 
++    }
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_base.h gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_base.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_base.h  1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_base.h       2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,58 @@
++// Locale support -*- C++ -*-
++
++// Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003
++// Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library.  This library 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.
++
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++
++// You should have received a copy of the GNU General Public License along
++// with this library; 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, you may use this file as part of a free software
++// library without restriction.  Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License.  This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.1  Locales
++//
++  
++// Information as gleaned from /usr/include/ctype.h
++  
++  struct ctype_base
++  {
++    // Note: In uClibc, the following two types depend on configuration.
++ 
++    // Non-standard typedefs.
++    typedef const __ctype_touplow_t* __to_type;
++
++    // NB: Offsets into ctype<char>::_M_table force a particular size
++    // on the mask type. Because of this, we don't use an enum.
++    typedef __ctype_mask_t    mask;   
++    static const mask upper           = _ISupper;
++    static const mask lower   = _ISlower;
++    static const mask alpha   = _ISalpha;
++    static const mask digit   = _ISdigit;
++    static const mask xdigit  = _ISxdigit;
++    static const mask space   = _ISspace;
++    static const mask print   = _ISprint;
++    static const mask graph   = _ISalpha | _ISdigit | _ISpunct;
++    static const mask cntrl   = _IScntrl;
++    static const mask punct   = _ISpunct;
++    static const mask alnum   = _ISalpha | _ISdigit;
++  };
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_inline.h gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_inline.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_inline.h        1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_inline.h     2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,69 @@
++// Locale support -*- C++ -*-
++
++// Copyright (C) 2000, 2002 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library.  This library 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.
++
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++
++// You should have received a copy of the GNU General Public License along
++// with this library; 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, you may use this file as part of a free software
++// library without restriction.  Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License.  This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.1  Locales
++//
++  
++// ctype bits to be inlined go here. Non-inlinable (ie virtual do_*)
++// functions go in ctype.cc
++  
++  bool
++  ctype<char>::
++  is(mask __m, char __c) const
++  { return _M_table[static_cast<unsigned char>(__c)] & __m; }
++
++  const char*
++  ctype<char>::
++  is(const char* __low, const char* __high, mask* __vec) const
++  {
++    while (__low < __high)
++      *__vec++ = _M_table[static_cast<unsigned char>(*__low++)];
++    return __high;
++  }
++
++  const char*
++  ctype<char>::
++  scan_is(mask __m, const char* __low, const char* __high) const
++  {
++    while (__low < __high 
++         && !(_M_table[static_cast<unsigned char>(*__low)] & __m))
++      ++__low;
++    return __low;
++  }
++
++  const char*
++  ctype<char>::
++  scan_not(mask __m, const char* __low, const char* __high) const
++  {
++    while (__low < __high 
++         && (_M_table[static_cast<unsigned char>(*__low)] & __m) != 0)
++      ++__low;
++    return __low;
++  }
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_noninline.h gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_noninline.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/ctype_noninline.h     1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/os/uclibc/ctype_noninline.h  2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,92 @@
++// Locale support -*- C++ -*-
++
++// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2004
++// Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library.  This library 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.
++
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++
++// You should have received a copy of the GNU General Public License along
++// with this library; 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, you may use this file as part of a free software
++// library without restriction.  Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License.  This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++//
++// ISO C++ 14882: 22.1  Locales
++//
++  
++// Information as gleaned from /usr/include/ctype.h
++
++  const ctype_base::mask*
++  ctype<char>::classic_table() throw()
++  { return __C_ctype_b; }
++
++  ctype<char>::ctype(__c_locale, const mask* __table, bool __del, 
++                   size_t __refs) 
++  : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()), 
++  _M_del(__table != 0 && __del), _M_widen_ok(0), _M_narrow_ok(0)
++  {
++    _M_toupper = __C_ctype_toupper;
++    _M_tolower = __C_ctype_tolower;
++    _M_table = __table ? __table : __C_ctype_b;
++    memset(_M_widen, 0, sizeof(_M_widen));
++    memset(_M_narrow, 0, sizeof(_M_narrow));
++  }
++
++  ctype<char>::ctype(const mask* __table, bool __del, size_t __refs)
++  : facet(__refs), _M_c_locale_ctype(_S_get_c_locale()), 
++  _M_del(__table != 0 && __del), _M_widen_ok(0), _M_narrow_ok(0)
++  {
++    _M_toupper = __C_ctype_toupper;
++    _M_tolower = __C_ctype_tolower;
++    _M_table = __table ? __table : __C_ctype_b;
++    memset(_M_widen, 0, sizeof(_M_widen));
++    memset(_M_narrow, 0, sizeof(_M_narrow));
++  }
++
++  char
++  ctype<char>::do_toupper(char __c) const
++  { return _M_toupper[static_cast<unsigned char>(__c)]; }
++
++  const char*
++  ctype<char>::do_toupper(char* __low, const char* __high) const
++  {
++    while (__low < __high)
++      {
++      *__low = _M_toupper[static_cast<unsigned char>(*__low)];
++      ++__low;
++      }
++    return __high;
++  }
++
++  char
++  ctype<char>::do_tolower(char __c) const
++  { return _M_tolower[static_cast<unsigned char>(__c)]; }
++
++  const char* 
++  ctype<char>::do_tolower(char* __low, const char* __high) const
++  {
++    while (__low < __high)
++      {
++      *__low = _M_tolower[static_cast<unsigned char>(*__low)];
++      ++__low;
++      }
++    return __high;
++  }
+diff -urN gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/os_defines.h gcc-3.4.2/libstdc++-v3/config/os/uclibc/os_defines.h
+--- gcc-3.4.2-dist/libstdc++-v3/config/os/uclibc/os_defines.h  1969-12-31 18:00:00.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/config/os/uclibc/os_defines.h       2004-09-10 10:47:40.000000000 -0500
+@@ -0,0 +1,44 @@
++// Specific definitions for GNU/Linux  -*- C++ -*-
++
++// Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
++//
++// This file is part of the GNU ISO C++ Library.  This library 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.
++
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++// GNU General Public License for more details.
++
++// You should have received a copy of the GNU General Public License along
++// with this library; 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, you may use this file as part of a free software
++// library without restriction.  Specifically, if other files instantiate
++// templates or use macros or inline functions from this file, or you compile
++// this file and link it with other files to produce an executable, this
++// file does not by itself cause the resulting executable to be covered by
++// the GNU General Public License.  This exception does not however
++// invalidate any other reasons why the executable file might be covered by
++// the GNU General Public License.
++
++#ifndef _GLIBCXX_OS_DEFINES
++#define _GLIBCXX_OS_DEFINES 1
++
++// System-specific #define, typedefs, corrections, etc, go here.  This
++// file will come before all others.
++
++// This keeps isanum, et al from being propagated as macros.
++#define __NO_CTYPE 1
++
++#include <features.h>
++
++// We must not see the optimized string functions GNU libc defines.
++#define __NO_STRING_INLINES
++
++#endif
+diff -urN gcc-3.4.2-dist/libstdc++-v3/configure gcc-3.4.2/libstdc++-v3/configure
+--- gcc-3.4.2-dist/libstdc++-v3/configure      2004-08-13 15:44:04.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/configure   2004-09-10 10:47:40.000000000 -0500
+@@ -3878,6 +3878,11 @@
+   lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+   ;;
++linux-uclibc*)
++  lt_cv_deplibs_check_method=pass_all
++  lt_cv_file_magic_test_file=`echo /lib/libuClibc-*.so`
++  ;;
++
+ netbsd*)
+   if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+     lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$'
+@@ -5479,7 +5479,7 @@
+   enableval="$enable_clocale"
+       case "$enableval" in
+-       generic|gnu|ieee_1003.1-2001|yes|no|auto) ;;
++       generic|gnu|ieee_1003.1-2001|uclibc|yes|no|auto) ;;
+        *) { { echo "$as_me:$LINENO: error: Unknown argument to enable/disable clocale" >&5
+ echo "$as_me: error: Unknown argument to enable/disable clocale" >&2;}
+    { (exit 1); exit 1; }; } ;;
+@@ -5545,6 +5550,9 @@
+   # Default to "generic".
+   if test $enable_clocale_flag = auto; then
+     case x${target_os} in
++      xlinux-uclibc*)
++      enable_clocale_flag=uclibc
++      ;;
+       xlinux* | xgnu* | xkfreebsd*-gnu | xknetbsd*-gnu)
+         cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+@@ -5759,6 +5767,77 @@
+       CTIME_CC=config/locale/generic/time_members.cc
+       CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
+       ;;
++    uclibc)
++      echo "$as_me:$LINENO: result: uclibc" >&5
++echo "${ECHO_T}uclibc" >&6
++
++      # Declare intention to use gettext, and add support for specific
++      # languages.
++      # For some reason, ALL_LINGUAS has to be before AM-GNU-GETTEXT
++      ALL_LINGUAS="de fr"
++
++      # Don't call AM-GNU-GETTEXT here. Instead, assume glibc.
++      # Extract the first word of "msgfmt", so it can be a program name with args.
++set dummy msgfmt; ac_word=$2
++echo "$as_me:$LINENO: checking for $ac_word" >&5
++echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
++if test "${ac_cv_prog_check_msgfmt+set}" = set; then
++  echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++  if test -n "$check_msgfmt"; then
++  ac_cv_prog_check_msgfmt="$check_msgfmt" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  test -z "$as_dir" && as_dir=.
++  for ac_exec_ext in '' $ac_executable_extensions; do
++  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++    ac_cv_prog_check_msgfmt="yes"
++    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++done
++
++  test -z "$ac_cv_prog_check_msgfmt" && ac_cv_prog_check_msgfmt="no"
++fi
++fi
++check_msgfmt=$ac_cv_prog_check_msgfmt
++if test -n "$check_msgfmt"; then
++  echo "$as_me:$LINENO: result: $check_msgfmt" >&5
++echo "${ECHO_T}$check_msgfmt" >&6
++else
++  echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6
++fi
++
++      if test x"$check_msgfmt" = x"yes" && test x"$enable_nls" = x"yes"; then
++        USE_NLS=yes
++      fi
++      # Export the build objects.
++      for ling in $ALL_LINGUAS; do \
++        glibcxx_MOFILES="$glibcxx_MOFILES $ling.mo"; \
++        glibcxx_POFILES="$glibcxx_POFILES $ling.po"; \
++      done
++
++
++
++      CLOCALE_H=config/locale/uclibc/c_locale.h
++      CLOCALE_CC=config/locale/uclibc/c_locale.cc
++      CCODECVT_H=config/locale/ieee_1003.1-2001/codecvt_specializations.h
++      CCODECVT_CC=config/locale/uclibc/codecvt_members.cc
++      CCOLLATE_CC=config/locale/uclibc/collate_members.cc
++      CCTYPE_CC=config/locale/uclibc/ctype_members.cc
++      CMESSAGES_H=config/locale/uclibc/messages_members.h
++      CMESSAGES_CC=config/locale/uclibc/messages_members.cc
++      CMONEY_CC=config/locale/uclibc/monetary_members.cc
++      CNUMERIC_CC=config/locale/uclibc/numeric_members.cc
++      CTIME_H=config/locale/uclibc/time_members.h
++      CTIME_CC=config/locale/uclibc/time_members.cc
++      CLOCALE_INTERNAL_H=config/locale/uclibc/c++locale_internal.h
++      ;;
+   esac
+   # This is where the testsuite looks for locale catalogs, using the
+diff -urN gcc-3.4.2-dist/libstdc++-v3/configure.host gcc-3.4.2/libstdc++-v3/configure.host
+--- gcc-3.4.2-dist/libstdc++-v3/configure.host 2004-08-27 14:52:30.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/configure.host      2004-09-10 10:47:40.000000000 -0500
+@@ -217,6 +217,12 @@
+     ;;
+ esac
++# Override for uClibc since linux-uclibc gets mishandled above.
++case "${host_os}" in
++  *-uclibc*)
++    os_include_dir="os/uclibc"
++    ;;
++esac
+ # Set any OS-dependent and CPU-dependent bits.
+ # THIS TABLE IS SORTED.  KEEP IT THAT WAY.
+diff -urN gcc-3.4.2-dist/libstdc++-v3/crossconfig.m4 gcc-3.4.2/libstdc++-v3/crossconfig.m4
+--- gcc-3.4.2-dist/libstdc++-v3/crossconfig.m4 2004-07-06 20:23:49.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/crossconfig.m4      2004-09-10 10:47:40.000000000 -0500
+@@ -138,6 +138,99 @@
+       ;;
+     esac
+     ;;
++  *-uclibc*)
++# Temporary hack until we implement the float versions of the libm funcs
++    AC_CHECK_HEADERS([nan.h ieeefp.h endian.h sys/isa_defs.h \
++      machine/endian.h machine/param.h sys/machine.h sys/types.h \
++      fp.h float.h endian.h inttypes.h locale.h float.h stdint.h])
++    SECTION_FLAGS='-ffunction-sections -fdata-sections'
++    AC_SUBST(SECTION_FLAGS)
++    GLIBCXX_CHECK_LINKER_FEATURES
++    GLIBCXX_CHECK_COMPLEX_MATH_SUPPORT
++    GLIBCXX_CHECK_WCHAR_T_SUPPORT
++
++    # For LFS.
++    AC_DEFINE(HAVE_INT64_T)
++    case "$target" in
++      *-uclinux*)
++        # Don't enable LFS with uClinux
++        ;;
++      *)
++        AC_DEFINE(_GLIBCXX_USE_LFS)
++    esac
++
++    # For showmanyc_helper().
++    AC_CHECK_HEADERS(sys/ioctl.h sys/filio.h)
++    GLIBCXX_CHECK_POLL
++    GLIBCXX_CHECK_S_ISREG_OR_S_IFREG
++
++    # For xsputn_2().
++    AC_CHECK_HEADERS(sys/uio.h)
++    GLIBCXX_CHECK_WRITEV
++
++#     AC_DEFINE(HAVE_ACOSF)
++#     AC_DEFINE(HAVE_ASINF)
++#     AC_DEFINE(HAVE_ATANF)
++#     AC_DEFINE(HAVE_ATAN2F)
++    AC_DEFINE(HAVE_CEILF)
++    AC_DEFINE(HAVE_COPYSIGN)
++#     AC_DEFINE(HAVE_COPYSIGNF)
++#     AC_DEFINE(HAVE_COSF)
++#     AC_DEFINE(HAVE_COSHF)
++#     AC_DEFINE(HAVE_EXPF)
++#     AC_DEFINE(HAVE_FABSF)
++    AC_DEFINE(HAVE_FINITE)
++    AC_DEFINE(HAVE_FINITEF)
++    AC_DEFINE(HAVE_FLOORF)
++#     AC_DEFINE(HAVE_FMODF)
++#     AC_DEFINE(HAVE_FREXPF)
++    AC_DEFINE(HAVE_HYPOT)
++#     AC_DEFINE(HAVE_HYPOTF)
++    AC_DEFINE(HAVE_ISINF)
++    AC_DEFINE(HAVE_ISINFF)
++    AC_DEFINE(HAVE_ISNAN)
++    AC_DEFINE(HAVE_ISNANF)
++#     AC_DEFINE(HAVE_LOGF)
++#     AC_DEFINE(HAVE_LOG10F)
++#     AC_DEFINE(HAVE_MODFF)
++#     AC_DEFINE(HAVE_SINF)
++#     AC_DEFINE(HAVE_SINHF)
++#     AC_DEFINE(HAVE_SINCOS)
++#     AC_DEFINE(HAVE_SINCOSF)
++    AC_DEFINE(HAVE_SQRTF)
++#     AC_DEFINE(HAVE_TANF)
++#     AC_DEFINE(HAVE_TANHF)
++    if test x"long_double_math_on_this_cpu" = x"yes"; then
++      AC_MSG_ERROR([long_double_math_on_this_cpu is yes!])
++#       AC_DEFINE(HAVE_ACOSL)
++#       AC_DEFINE(HAVE_ASINL)
++#       AC_DEFINE(HAVE_ATANL)
++#       AC_DEFINE(HAVE_ATAN2L)
++#       AC_DEFINE(HAVE_CEILL)
++#       AC_DEFINE(HAVE_COPYSIGNL)
++#       AC_DEFINE(HAVE_COSL)
++#       AC_DEFINE(HAVE_COSHL)
++#       AC_DEFINE(HAVE_EXPL)
++#       AC_DEFINE(HAVE_FABSL)
++#       AC_DEFINE(HAVE_FINITEL)
++#       AC_DEFINE(HAVE_FLOORL)
++#       AC_DEFINE(HAVE_FMODL)
++#       AC_DEFINE(HAVE_FREXPL)
++#       AC_DEFINE(HAVE_HYPOTL)
++#       AC_DEFINE(HAVE_ISINFL)
++#       AC_DEFINE(HAVE_ISNANL)
++#       AC_DEFINE(HAVE_LOGL)
++#       AC_DEFINE(HAVE_LOG10L)
++#       AC_DEFINE(HAVE_MODFL)
++#       AC_DEFINE(HAVE_POWL)
++#       AC_DEFINE(HAVE_SINL)
++#       AC_DEFINE(HAVE_SINHL)
++#       AC_DEFINE(HAVE_SINCOSL)
++#       AC_DEFINE(HAVE_SQRTL)
++#       AC_DEFINE(HAVE_TANL)
++#       AC_DEFINE(HAVE_TANHL)
++    fi
++    ;;
+   *-linux* | *-uclinux* | *-gnu* | *-kfreebsd*-gnu | *-knetbsd*-gnu)
+     AC_CHECK_HEADERS([nan.h ieeefp.h endian.h sys/isa_defs.h \
+       machine/endian.h machine/param.h sys/machine.h sys/types.h \
+@@ -152,7 +245,7 @@
+     AC_DEFINE(HAVE_INT64_T)
+     case "$target" in
+       *-uclinux*)
+-        # Don't enable LFS with uClibc
++        # Don't enable LFS with uClinux
+         ;;
+       *)
+         AC_DEFINE(_GLIBCXX_USE_LFS)
+diff -urN gcc-3.4.2-dist/libstdc++-v3/include/c_compatibility/wchar.h gcc-3.4.2/libstdc++-v3/include/c_compatibility/wchar.h
+--- gcc-3.4.2-dist/libstdc++-v3/include/c_compatibility/wchar.h        2003-12-08 21:51:45.000000000 -0600
++++ gcc-3.4.2/libstdc++-v3/include/c_compatibility/wchar.h     2004-09-10 10:47:40.000000000 -0500
+@@ -101,7 +101,9 @@
+ using std::wmemcpy;
+ using std::wmemmove;
+ using std::wmemset;
++#if _GLIBCXX_HAVE_WCSFTIME
+ using std::wcsftime;
++#endif
+ #if _GLIBCXX_USE_C99
+ using std::wcstold;
+diff -urN gcc-3.4.2-dist/libstdc++-v3/include/c_std/std_cwchar.h gcc-3.4.2/libstdc++-v3/include/c_std/std_cwchar.h
+--- gcc-3.4.2-dist/libstdc++-v3/include/c_std/std_cwchar.h     2004-07-20 03:52:12.000000000 -0500
++++ gcc-3.4.2/libstdc++-v3/include/c_std/std_cwchar.h  2004-09-10 10:47:40.000000000 -0500
+@@ -179,7 +179,9 @@
+   using ::wcscoll;
+   using ::wcscpy;
+   using ::wcscspn;
++#if _GLIBCXX_HAVE_WCSFTIME
+   using ::wcsftime;
++#endif
+   using ::wcslen;
+   using ::wcsncat;
+   using ::wcsncmp;
diff --git a/toolchain/gcc/3.4.6/300-libstdc++-pic.patch b/toolchain/gcc/3.4.6/300-libstdc++-pic.patch
new file mode 100644 (file)
index 0000000..c030ba6
--- /dev/null
@@ -0,0 +1,47 @@
+# DP: Build and install libstdc++_pic.a library.
+
+--- gcc/libstdc++-v3/src/Makefile.am~  2003-02-28 09:21:05.000000000 +0100
++++ gcc/libstdc++-v3/src/Makefile.am   2003-02-28 09:28:50.000000000 +0100
+@@ -224,6 +224,10 @@
+         @OPT_LDFLAGS@ @SECTION_LDFLAGS@ $(AM_CXXFLAGS) $(LDFLAGS) -o $@
++install-exec-local:
++      $(AR) cru libstdc++_pic.a .libs/*.o $(top_builddir)/libsupc++/*.o
++      $(INSTALL_DATA) libstdc++_pic.a $(DESTDIR)$(toolexeclibdir)
++
+ # Added bits to build debug library.
+ if GLIBCPP_BUILD_DEBUG
+ all-local: build_debug
+
+--- gcc/libstdc++-v3/src/Makefile.in~  2004-02-21 09:55:48.000000000 +0100
++++ gcc/libstdc++-v3/src/Makefile.in   2004-02-21 09:59:34.000000000 +0100
+@@ -585,7 +585,7 @@
+ install-data-am: install-data-local
+-install-exec-am: install-toolexeclibLTLIBRARIES
++install-exec-am: install-toolexeclibLTLIBRARIES install-exec-local
+ install-info: install-info-am
+@@ -618,6 +618,7 @@
+       distclean-tags distdir dvi dvi-am info info-am install \
+       install-am install-data install-data-am install-data-local \
+       install-exec install-exec-am install-info install-info-am \
++      install-exec-local \
+       install-man install-strip install-toolexeclibLTLIBRARIES \
+       installcheck installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+@@ -707,6 +708,11 @@
+ install_debug:
+       (cd ${debugdir} && $(MAKE) \
+       toolexeclibdir=$(glibcxx_toolexeclibdir)/debug install)
++
++install-exec-local:
++      $(AR) cru libstdc++_pic.a .libs/*.o $(top_builddir)/libsupc++/*.o
++      $(INSTALL_DATA) libstdc++_pic.a $(DESTDIR)$(toolexeclibdir)
++
+ # Tell versions [3.59,3.63) of GNU make to not export all variables.
+ # Otherwise a system limit (for SysV at least) may be exceeded.
+ .NOEXPORT:
diff --git a/toolchain/gcc/3.4.6/600-gcc34-arm-ldm-peephole.patch b/toolchain/gcc/3.4.6/600-gcc34-arm-ldm-peephole.patch
new file mode 100644 (file)
index 0000000..0c37050
--- /dev/null
@@ -0,0 +1,65 @@
+--- gcc-3.4.0/gcc/config/arm/arm.md.arm-ldm-peephole   2004-01-13 08:24:37.000000000 -0500
++++ gcc-3.4.0/gcc/config/arm/arm.md    2004-04-24 18:18:04.000000000 -0400
+@@ -8810,13 +8810,16 @@
+    (set_attr "length" "4,8,8")]
+ )
++; Try to convert LDR+LDR+arith into [add+]LDM+arith
++; On XScale, LDM is always slower than two LDRs, so only do this if
++; optimising for size.
+ (define_insn "*arith_adjacentmem"
+   [(set (match_operand:SI 0 "s_register_operand" "=r")
+       (match_operator:SI 1 "shiftable_operator"
+        [(match_operand:SI 2 "memory_operand" "m")
+         (match_operand:SI 3 "memory_operand" "m")]))
+    (clobber (match_scratch:SI 4 "=r"))]
+-  "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
++  "TARGET_ARM && (!arm_tune_xscale || optimize_size) && adjacent_mem_locations (operands[2], operands[3])"
+   "*
+   {
+     rtx ldm[3];
+@@ -8851,6 +8854,8 @@
+       }
+    if (val1 && val2)
+       {
++      /* This would be a loss on a Harvard core, but adjacent_mem_locations()
++         will prevent it from happening.  */
+       rtx ops[3];
+       ldm[0] = ops[0] = operands[4];
+       ops[1] = XEXP (XEXP (operands[2], 0), 0);
+--- gcc-3.4.0/gcc/config/arm/arm.c.arm-ldm-peephole    2004-04-24 18:16:25.000000000 -0400
++++ gcc-3.4.0/gcc/config/arm/arm.c     2004-04-24 18:18:04.000000000 -0400
+@@ -4838,6 +4841,11 @@
+       *load_offset = unsorted_offsets[order[0]];
+     }
++  /* For XScale a two-word LDM is a performance loss, so only do this if
++     size is more important.  See comments in arm_gen_load_multiple.  */
++  if (nops == 2 && arm_tune_xscale && !optimize_size)
++    return 0;
++
+   if (unsorted_offsets[order[0]] == 0)
+     return 1; /* ldmia */
+@@ -5064,6 +5072,11 @@
+       *load_offset = unsorted_offsets[order[0]];
+     }
++  /* For XScale a two-word LDM is a performance loss, so only do this if
++     size is more important.  See comments in arm_gen_load_multiple.  */
++  if (nops == 2 && arm_tune_xscale && !optimize_size)
++    return 0;
++
+   if (unsorted_offsets[order[0]] == 0)
+     return 1; /* stmia */
+--- gcc-3.4.0/gcc/genpeep.c.arm-ldm-peephole   2003-07-05 01:27:22.000000000 -0400
++++ gcc-3.4.0/gcc/genpeep.c    2004-04-24 18:18:04.000000000 -0400
+@@ -381,6 +381,7 @@
+   printf ("#include \"recog.h\"\n");
+   printf ("#include \"except.h\"\n\n");
+   printf ("#include \"function.h\"\n\n");
++  printf ("#include \"flags.h\"\n\n");
+   printf ("#ifdef HAVE_peephole\n");
+   printf ("extern rtx peep_operand[];\n\n");
diff --git a/toolchain/gcc/3.4.6/601-gcc34-arm-ldm-peephole2.patch b/toolchain/gcc/3.4.6/601-gcc34-arm-ldm-peephole2.patch
new file mode 100644 (file)
index 0000000..27f7c07
--- /dev/null
@@ -0,0 +1,42 @@
+The 30_all_gcc34-arm-ldm-peephole.patch from Debian was conflicting 
+with the newer 36_all_pr16201-fix.patch, so i cut out the hunk from 
+it that was causing problems and grabbed an updated version from 
+upstream cvs.
+
+Index: gcc/config/arm/arm.c
+===================================================================
+RCS file: /cvsroot/gcc/gcc/gcc/config/arm/arm.c,v
+retrieving revision 1.432
+retrieving revision 1.433
+diff -u -r1.432 -r1.433
+--- gcc-3.4.4/gcc/config/arm/arm.c     29 Mar 2005 03:00:23 -0000      1.432
++++ gcc-3.4.4/gcc/config/arm/arm.c     1 Apr 2005 11:02:22 -0000       1.433
+@@ -5139,6 +5139,10 @@
+ int
+ adjacent_mem_locations (rtx a, rtx b)
+ {
++  /* We don't guarantee to preserve the order of these memory refs.  */
++  if (volatile_refs_p (a) || volatile_refs_p (b))
++    return 0;
++
+   if ((GET_CODE (XEXP (a, 0)) == REG
+        || (GET_CODE (XEXP (a, 0)) == PLUS
+          && GET_CODE (XEXP (XEXP (a, 0), 1)) == CONST_INT))
+@@ -5178,6 +5182,17 @@
+       return 0;
+       val_diff = val1 - val0;
++
++      if (arm_ld_sched)
++      {
++        /* If the target has load delay slots, then there's no benefit
++           to using an ldm instruction unless the offset is zero and
++           we are optimizing for size.  */
++        return (optimize_size && (REGNO (reg0) == REGNO (reg1))
++                && (val0 == 0 || val1 == 0 || val0 == 4 || val1 == 4)
++                && (val_diff == 4 || val_diff == -4));
++      }
++
+       return ((REGNO (reg0) == REGNO (reg1))
+             && (val_diff == 4 || val_diff == -4));
+     }
diff --git a/toolchain/gcc/3.4.6/601-gcc34-arm-ldm.patch b/toolchain/gcc/3.4.6/601-gcc34-arm-ldm.patch
new file mode 100644 (file)
index 0000000..142052f
--- /dev/null
@@ -0,0 +1,119 @@
+--- gcc-3.4.0/gcc/config/arm/arm.c.arm-ldm     2004-02-27 09:51:05.000000000 -0500
++++ gcc-3.4.0/gcc/config/arm/arm.c     2004-04-24 18:16:25.000000000 -0400
+@@ -8520,6 +8520,26 @@
+   return_used_this_function = 0;  
+ }
++/* Return the number (counting from 0) of
++   the least significant set bit in MASK.  */
++
++#ifdef __GNUC__
++inline
++#endif
++static int
++number_of_first_bit_set (mask)
++     int mask;
++{
++  int bit;
++
++  for (bit = 0;
++       (mask & (1 << bit)) == 0;
++       ++bit)
++    continue;
++
++  return bit;
++}
++
+ const char *
+ arm_output_epilogue (rtx sibling)
+ {
+@@ -8753,27 +8773,47 @@
+         saved_regs_mask |=   (1 << PC_REGNUM);
+       }
+-      /* Load the registers off the stack.  If we only have one register
+-       to load use the LDR instruction - it is faster.  */
+-      if (saved_regs_mask == (1 << LR_REGNUM))
+-      {
+-        /* The exception handler ignores the LR, so we do
+-           not really need to load it off the stack.  */
+-        if (eh_ofs)
+-          asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
+-        else
+-          asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM);
+-      }
+-      else if (saved_regs_mask)
++      if (saved_regs_mask)
+       {
+-        if (saved_regs_mask & (1 << SP_REGNUM))
+-          /* Note - write back to the stack register is not enabled
+-             (ie "ldmfd sp!...").  We know that the stack pointer is
+-             in the list of registers and if we add writeback the
+-             instruction becomes UNPREDICTABLE.  */
+-          print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
++        /* Load the registers off the stack.  If we only have one register
++           to load use the LDR instruction - it is faster.  */
++        if (bit_count (saved_regs_mask) == 1)
++          {
++            int reg = number_of_first_bit_set (saved_regs_mask);
++
++            switch (reg)
++              {
++              case SP_REGNUM:
++                /* Mustn't use base writeback when loading SP.  */
++                asm_fprintf (f, "\tldr\t%r, [%r]\n", SP_REGNUM, SP_REGNUM);
++                break;
++                
++              case LR_REGNUM:
++                if (eh_ofs)
++                  {
++                    /* The exception handler ignores the LR, so we do
++                       not really need to load it off the stack.  */
++                    asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
++                    break;
++                  }
++                /* else fall through */
++                
++              default:
++                asm_fprintf (f, "\tldr\t%r, [%r], #4\n", reg, SP_REGNUM);
++                break;
++              }
++          }
+         else
+-          print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
++          {
++            if (saved_regs_mask & (1 << SP_REGNUM))
++              /* Note - write back to the stack register is not enabled
++                 (ie "ldmfd sp!...").  We know that the stack pointer is
++                 in the list of registers and if we add writeback the
++                 instruction becomes UNPREDICTABLE.  */
++              print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
++            else
++              print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
++          }
+       }
+       if (current_function_pretend_args_size)
+@@ -11401,22 +11441,6 @@
+     }
+ }
+-/* Return the number (counting from 0) of
+-   the least significant set bit in MASK.  */
+-
+-inline static int
+-number_of_first_bit_set (int mask)
+-{
+-  int bit;
+-
+-  for (bit = 0;
+-       (mask & (1 << bit)) == 0;
+-       ++bit)
+-    continue;
+-
+-  return bit;
+-}
+-
+ /* Generate code to return from a thumb function.
+    If 'reg_containing_return_addr' is -1, then the return address is
+    actually on the stack, at the stack pointer.  */
diff --git a/toolchain/gcc/3.4.6/602-sdk-libstdc++-includes.patch b/toolchain/gcc/3.4.6/602-sdk-libstdc++-includes.patch
new file mode 100644 (file)
index 0000000..4377c21
--- /dev/null
@@ -0,0 +1,22 @@
+--- gcc-3.4.1/libstdc++-v3/libmath/Makefile.am~        2003-08-27 22:29:42.000000000 +0100
++++ gcc-3.4.1/libstdc++-v3/libmath/Makefile.am 2004-07-22 16:41:45.152130128 +0100
+@@ -32,7 +32,7 @@
+ libmath_la_SOURCES = stubs.c
+-AM_CPPFLAGS = $(CANADIAN_INCLUDES)
++AM_CPPFLAGS = $(CANADIAN_INCLUDES) -I$(toplevel_srcdir)/include
+ # Only compiling "C" sources in this directory.
+ LIBTOOL = @LIBTOOL@ --tag CC
+--- gcc-3.4.1/libstdc++-v3/fragment.am.old     2004-07-22 18:24:58.024083656 +0100
++++ gcc-3.4.1/libstdc++-v3/fragment.am 2004-07-22 18:24:59.019932264 +0100
+@@ -18,7 +18,7 @@
+       $(WARN_FLAGS) $(WERROR) -fdiagnostics-show-location=once
+ # -I/-D flags to pass when compiling.
+-AM_CPPFLAGS = $(GLIBCXX_INCLUDES)
++AM_CPPFLAGS = $(GLIBCXX_INCLUDES) -I$(toplevel_srcdir)/include
diff --git a/toolchain/gcc/3.4.6/700-pr15068-fix.patch b/toolchain/gcc/3.4.6/700-pr15068-fix.patch
new file mode 100644 (file)
index 0000000..2977765
--- /dev/null
@@ -0,0 +1,44 @@
+See http://gcc.gnu.org/PR15068
+
+Fixes error
+
+../sysdeps/generic/s_fmax.c: In function `__fmax':
+../sysdeps/generic/s_fmax.c:28: internal compiler error: in elim_reg_cond, at flow.c:3257
+Please submit a full bug report,
+with preprocessed source if appropriate.
+See <URL:http://gcc.gnu.org/bugs.html> for instructions.
+make[2]: *** [/home/dank/wk/crosstool-0.28-rc35/build/arm-unknown-linux-gnu/gcc-3.4.1-glibc-20040822/build-glibc/math/s_fmax.o] Error 1
+make[2]: Leaving directory `/home/dank/wk/crosstool-0.28-rc35/build/arm-unknown-linux-gnu/gcc-3.4.1-glibc-20040822/glibc-20040822/math'
+make[1]: *** [math/others] Error 2
+make[1]: Leaving directory `/home/dank/wk/crosstool-0.28-rc35/build/arm-unknown-linux-gnu/gcc-3.4.1-glibc-20040822/glibc-20040822'
+make: *** [all] Error 2
+
+[ rediffed against gcc-3.4.1, with elbow grease, ending up with same thing as
+http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/flow.c.diff?cvsroot=gcc&only_with_tag=csl-arm-branch&r1=1.563.4.2&r2=1.563.4.3 ]
+
+--- gcc-3.4.1/gcc/flow.c.old   2004-02-27 19:39:19.000000000 -0800
++++ gcc-3.4.1/gcc/flow.c       2004-08-26 07:29:46.000000000 -0700
+@@ -1878,6 +1878,7 @@
+         rtx set_src = SET_SRC (pc_set (BB_END (bb)));
+         rtx cond_true = XEXP (set_src, 0);
+         rtx reg = XEXP (cond_true, 0);
++        enum rtx_code inv_cond;
+         if (GET_CODE (reg) == SUBREG)
+           reg = SUBREG_REG (reg);
+@@ -1886,11 +1887,13 @@
+            in the form of a comparison of a register against zero.  
+            If the condition is more complex than that, then it is safe
+            not to record any information.  */
+-        if (GET_CODE (reg) == REG
++        inv_cond = reversed_comparison_code (cond_true, BB_END (bb));
++        if (inv_cond != UNKNOWN
++            && GET_CODE (reg) == REG
+             && XEXP (cond_true, 1) == const0_rtx)
+           {
+             rtx cond_false
+-              = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond_true)),
++              = gen_rtx_fmt_ee (inv_cond,
+                                 GET_MODE (cond_true), XEXP (cond_true, 0),
+                                 XEXP (cond_true, 1));
+             if (GET_CODE (XEXP (set_src, 1)) == PC)
diff --git a/toolchain/gcc/3.4.6/71_all_sh-pr16665-fix.patch b/toolchain/gcc/3.4.6/71_all_sh-pr16665-fix.patch
new file mode 100644 (file)
index 0000000..680bb39
--- /dev/null
@@ -0,0 +1,43 @@
+--- gcc/gcc/config/sh/sh.c
++++ gcc/gcc/config/sh/sh.c
+@@ -9106,6 +9106,15 @@ sh_output_mi_thunk (FILE *file, tree thu
+     }
+   this = FUNCTION_ARG (cum, Pmode, ptr_type_node, 1);
++  /* In PIC case, we set PIC register to compute the target address.  We
++     can use a scratch register to save and restore the original value  
++     except for SHcompact.  For SHcompact, use stack.  */
++  if (flag_pic && TARGET_SHCOMPACT)
++    {
++      push (PIC_OFFSET_TABLE_REGNUM);
++      emit_insn (gen_GOTaddr2picreg ());
++    }
++
+   /* For SHcompact, we only have r0 for a scratch register: r1 is the
+      static chain pointer (even if you can't have nested virtual functions
+      right now, someone might implement them sometime), and the rest of the
+@@ -9188,8 +9197,24 @@ sh_output_mi_thunk (FILE *file, tree thu
+       assemble_external (function);
+       TREE_USED (function) = 1;
+     }
++  /* We can use scratch1 to save and restore the original value of
++     PIC register except for SHcompact.  */
++  if (flag_pic && ! TARGET_SHCOMPACT)
++    {
++      emit_move_insn (scratch1,
++                    gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM));
++      emit_insn (gen_GOTaddr2picreg ());
++    }
+   funexp = XEXP (DECL_RTL (function), 0);
+   emit_move_insn (scratch2, funexp);
++  if (flag_pic)
++    {
++      if (! TARGET_SHCOMPACT)
++      emit_move_insn (gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM),
++                      scratch1);
++      else
++      pop (PIC_OFFSET_TABLE_REGNUM);
++    }
+   funexp = gen_rtx_MEM (FUNCTION_MODE, scratch2);
+   sibcall = emit_call_insn (gen_sibcall (funexp, const0_rtx, NULL_RTX));
+   SIBLING_CALL_P (sibcall) = 1;
diff --git a/toolchain/gcc/3.4.6/72_all_sh-no-reorder-blocks.patch b/toolchain/gcc/3.4.6/72_all_sh-no-reorder-blocks.patch
new file mode 100644 (file)
index 0000000..8b98268
--- /dev/null
@@ -0,0 +1,13 @@
+--- g/gcc/config/sh/sh.h
++++ g/gcc/config/sh/sh.h
+@@ -422,6 +422,10 @@
+ do {                                                                  \
+   if (LEVEL)                                                          \
+     flag_omit_frame_pointer = -1;                                     \
++  if (LEVEL <= 2)                                                     \
++    {                                                                 \
++      flag_reorder_blocks = 0;                                                \
++    }                                                                 \
+   if (SIZE)                                                           \
+     target_flags |= SPACE_BIT;                                                \
+   if (TARGET_SHMEDIA && LEVEL > 1)                                    \
diff --git a/toolchain/gcc/3.4.6/73_all_sh-pr20617.patch b/toolchain/gcc/3.4.6/73_all_sh-pr20617.patch
new file mode 100644 (file)
index 0000000..6d8021c
--- /dev/null
@@ -0,0 +1,28 @@
+2005-03-24  J"orn Rennecke <joern.rennecke@st.com>
+
+       Band aid for PR target/20617:
+       * config/sh/lib1funcs.asm (FUNC, ALIAS): Add .hidden directive.
+
+--- g/gcc/config/sh/lib1funcs.asm
++++ g/gcc/config/sh/lib1funcs.asm
+@@ -37,9 +37,19 @@ Boston, MA 02111-1307, USA.  */
+    ELF local label prefixes by J"orn Rennecke
+    amylaar@cygnus.com  */
++#define ALIAS(X,Y)    .global GLOBAL(X); .set GLOBAL(X),GLOBAL(Y)
++
+ #ifdef __ELF__
+ #define LOCAL(X)      .L_##X
+-#define FUNC(X)               .type X,@function
++
++#if 1 /* ??? The export list mechanism is broken, everything that is not
++       hidden is exported.  */
++#undef FUNC
++#define FUNC(X)               .type X,@function; .hidden X
++#undef ALIAS
++#define ALIAS(X,Y)    .global GLOBAL(X); .set GLOBAL(X),GLOBAL(Y); .hidden GLOBAL(X)
++#endif
++
+ #define ENDFUNC0(X)   .Lfe_##X: .size X,.Lfe_##X-X
+ #define ENDFUNC(X)    ENDFUNC0(X)
+ #else
diff --git a/toolchain/gcc/3.4.6/800-arm-bigendian.patch b/toolchain/gcc/3.4.6/800-arm-bigendian.patch
new file mode 100644 (file)
index 0000000..0bae8f4
--- /dev/null
@@ -0,0 +1,70 @@
+By Lennert Buytenhek <buytenh@wantstofly.org>
+Adds support for arm*b-linux* big-endian ARM targets
+
+See http://gcc.gnu.org/PR16350
+
+diff -urN gcc-3.4.1-dist/gcc/config/arm/linux-elf.h gcc-3.4.1/gcc/config/arm/linux-elf.h
+--- gcc-3.4.1-dist/gcc/config/arm/linux-elf.h  2004-08-16 16:01:50.000000000 -0500
++++ gcc-3.4.1/gcc/config/arm/linux-elf.h       2004-08-16 15:43:40.000000000 -0500
+@@ -30,17 +30,34 @@
+ /* Do not assume anything about header files.  */
+ #define NO_IMPLICIT_EXTERN_C
++/*
++ * 'config.gcc' defines TARGET_BIG_ENDIAN_DEFAULT as 1 for arm*b-*
++ * (big endian) configurations.
++ */
++#if TARGET_BIG_ENDIAN_DEFAULT
++#define TARGET_ENDIAN_DEFAULT ARM_FLAG_BIG_END
++#define TARGET_ENDIAN_OPTION "mbig-endian"
++#define TARGET_LINKER_EMULATION "armelfb_linux"
++#else
++#define TARGET_ENDIAN_DEFAULT 0
++#define TARGET_ENDIAN_OPTION "mlittle-endian"
++#define TARGET_LINKER_EMULATION "armelf_linux"
++#endif
++
+ /* Default is to use APCS-32 mode.  */
+ #undef  TARGET_DEFAULT
+-#define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_MMU_TRAPS)
++#define TARGET_DEFAULT \
++              ( ARM_FLAG_APCS_32 | \
++                ARM_FLAG_MMU_TRAPS | \
++                TARGET_ENDIAN_DEFAULT )
+ #define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6
+-#define SUBTARGET_EXTRA_LINK_SPEC " -m armelf_linux -p"
++#define SUBTARGET_EXTRA_LINK_SPEC " -m " TARGET_LINKER_EMULATION " -p"
+ #undef  MULTILIB_DEFAULTS
+ #define MULTILIB_DEFAULTS \
+-      { "marm", "mlittle-endian", "mhard-float", "mapcs-32", "mno-thumb-interwork" }
++      { "marm", TARGET_ENDIAN_OPTION, "mhard-float", "mapcs-32", "mno-thumb-interwork" }
+ #define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
+@@ -101,7 +118,7 @@
+    %{rdynamic:-export-dynamic} \
+    %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2} \
+    -X \
+-   %{mbig-endian:-EB}" \
++   %{mbig-endian:-EB} %{mlittle-endian:-EL}" \
+    SUBTARGET_EXTRA_LINK_SPEC
+ #endif
+diff -urN gcc-3.4.1-dist/gcc/config.gcc gcc-3.4.1/gcc/config.gcc
+--- gcc-3.4.1-dist/gcc/config.gcc      2004-08-16 16:01:50.000000000 -0500
++++ gcc-3.4.1/gcc/config.gcc   2004-08-16 16:01:25.000000000 -0500
+@@ -672,6 +672,11 @@
+       ;;
+ arm*-*-linux*)                        # ARM GNU/Linux with ELF
+       tm_file="dbxelf.h elfos.h linux.h arm/elf.h  arm/linux-gas.h arm/linux-elf.h arm/aout.h arm/arm.h"
++      case $target in
++      arm*b-*)
++              tm_defines="TARGET_BIG_ENDIAN_DEFAULT=1 $tm_defines"
++              ;;
++      esac
+       tmake_file="t-slibgcc-elf-ver t-linux arm/t-linux"
+       extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
+       gnu_ld=yes
diff --git a/toolchain/gcc/3.4.6/800-powerpc-libc_stack_end-uclibc.patch b/toolchain/gcc/3.4.6/800-powerpc-libc_stack_end-uclibc.patch
new file mode 100644 (file)
index 0000000..a209470
--- /dev/null
@@ -0,0 +1,15 @@
+--- gcc-3.4.4/gcc/config/rs6000/linux-unwind.h.org     2005-06-23 17:50:34.000000000 -0600
++++ gcc-3.4.4/gcc/config/rs6000/linux-unwind.h 2005-06-23 17:52:02.000000000 -0600
+@@ -32,6 +32,7 @@
+    these structs elsewhere;  Many fields are missing, particularly
+    from the end of the structures.  */
++#ifndef inhibit_libc
+ struct gcc_vregs
+ {
+   __attribute__ ((vector_size (16))) int vr[32];
+@@ -320,3 +321,4 @@
+                                                                       \
+     goto SUCCESS;                                                     \
+   } while (0)
++#endif
diff --git a/toolchain/gcc/3.4.6/900-nios2.patch b/toolchain/gcc/3.4.6/900-nios2.patch
new file mode 100644 (file)
index 0000000..bfa06a2
--- /dev/null
@@ -0,0 +1,10211 @@
+--- gcc-3.4.3/gcc/Makefile.in
++++ gcc-3.4.3-nios2/gcc/Makefile.in
+@@ -3085,7 +3085,7 @@ install-mkheaders: stmp-int-hdrs $(STMP_
+         $(INSTALL_DATA) $(srcdir)/README-fixinc \
+           $(DESTDIR)$(itoolsdatadir)/include/README ; \
+         $(INSTALL_SCRIPT) fixinc.sh $(DESTDIR)$(itoolsdir)/fixinc.sh ; \
+-        $(INSTALL_PROGRAM) fixinc/fixincl $(DESTDIR)$(itoolsdir)/fixincl ; \
++        $(INSTALL_PROGRAM) fixinc/fixincl$(build_exeext) $(DESTDIR)$(itoolsdir)/fixincl$(build_exeext) ; \
+         $(INSTALL_DATA) $(srcdir)/gsyslimits.h \
+           $(DESTDIR)$(itoolsdatadir)/gsyslimits.h ; \
+       else :; fi
+--- gcc-3.4.3/gcc/combine.c
++++ gcc-3.4.3-nios2/gcc/combine.c
+@@ -4380,6 +4380,14 @@ combine_simplify_rtx (rtx x, enum machin
+                                        mode);
+           }
++#ifndef __nios2__
++/* This screws up Nios II in this test case:
++
++if (x & 1)
++  return 2;
++else
++  return 3;
++*/
+         else if (STORE_FLAG_VALUE == 1
+                  && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
+                  && op1 == const0_rtx
+@@ -4391,6 +4399,7 @@ combine_simplify_rtx (rtx x, enum machin
+                                gen_lowpart_for_combine (mode, op0),
+                                const1_rtx);
+           }
++#endif
+         else if (STORE_FLAG_VALUE == 1
+                  && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
+--- gcc-3.4.3/gcc/config/nios2/crti.asm
++++ gcc-3.4.3-nios2/gcc/config/nios2/crti.asm
+@@ -0,0 +1,88 @@
++/*
++  Copyright (C) 2003 
++ by Jonah Graham (jgraham@altera.com)
++
++This file is free software; you can redistribute it and/or modify it
++under the terms of the GNU General Public License as published by the
++Free Software Foundation; either version 2, or (at your option) any
++later version.
++
++In addition to the permissions in the GNU General Public License, the
++Free Software Foundation gives you unlimited permission to link the
++compiled version of this file with other programs, and to distribute
++those programs without any restriction coming from the use of this
++file.  (The General Public License restrictions do apply in other
++respects; for example, they cover modification of the file, and
++distribution when not linked into another program.)
++
++This file 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 this program; 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 make a stack frame for the contents of the .fini and
++.init sections.  Users may put any desired instructions in those
++sections.
++
++
++While technically any code can be put in the init and fini sections
++most stuff will not work other than stuff which obeys the call frame
++and ABI. All the call-preserved registers are saved, the call clobbered
++registers should have been saved by the code calling init and fini.
++
++See crtstuff.c for an example of code that inserts itself in the 
++init and fini sections. 
++
++See crt0.s for the code that calls init and fini.
++*/
++
++      .file   "crti.asm"
++
++      .section        ".init"
++      .align 2
++      .global _init
++_init:
++      addi    sp, sp, -48
++      stw     ra, 44(sp)
++      stw     r23, 40(sp)
++      stw     r22, 36(sp)
++      stw     r21, 32(sp)
++      stw     r20, 28(sp)
++      stw     r19, 24(sp)
++      stw     r18, 20(sp)
++      stw     r17, 16(sp)
++      stw     r16, 12(sp)
++      stw     fp, 8(sp)
++      mov     fp, sp
++      
++      
++      .section        ".fini"
++      .align  2
++      .global _fini
++_fini:
++      addi    sp, sp, -48
++      stw     ra, 44(sp)
++      stw     r23, 40(sp)
++      stw     r22, 36(sp)
++      stw     r21, 32(sp)
++      stw     r20, 28(sp)
++      stw     r19, 24(sp)
++      stw     r18, 20(sp)
++      stw     r17, 16(sp)
++      stw     r16, 12(sp)
++      stw     fp, 8(sp)
++      mov     fp, sp
++      
++
+--- gcc-3.4.3/gcc/config/nios2/crtn.asm
++++ gcc-3.4.3-nios2/gcc/config/nios2/crtn.asm
+@@ -0,0 +1,70 @@
++/*
++  Copyright (C) 2003 
++ by Jonah Graham (jgraham@altera.com)
++
++This file is free software; you can redistribute it and/or modify it
++under the terms of the GNU General Public License as published by the
++Free Software Foundation; either version 2, or (at your option) any
++later version.
++
++In addition to the permissions in the GNU General Public License, the
++Free Software Foundation gives you unlimited permission to link the
++compiled version of this file with other programs, and to distribute
++those programs without any restriction coming from the use of this
++file.  (The General Public License restrictions do apply in other
++respects; for example, they cover modification of the file, and
++distribution when not linked into another program.)
++
++This file 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 this program; 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 makes sure that the .fini and .init sections do in
++fact return.  Users may put any desired instructions in those sections.
++This file is the last thing linked into any executable.
++*/    
++      .file   "crtn.asm"
++
++
++
++      .section        ".init"
++      ldw     ra, 44(sp)
++      ldw     r23, 40(sp)
++      ldw     r22, 36(sp)
++      ldw     r21, 32(sp)
++      ldw     r20, 28(sp)
++      ldw     r19, 24(sp)
++      ldw     r18, 20(sp)
++      ldw     r17, 16(sp)
++      ldw     r16, 12(sp)
++      ldw     fp, 8(sp)
++      addi    sp, sp, -48
++      ret
++      
++      .section        ".fini"
++      ldw     ra, 44(sp)
++      ldw     r23, 40(sp)
++      ldw     r22, 36(sp)
++      ldw     r21, 32(sp)
++      ldw     r20, 28(sp)
++      ldw     r19, 24(sp)
++      ldw     r18, 20(sp)
++      ldw     r17, 16(sp)
++      ldw     r16, 12(sp)
++      ldw     fp, 8(sp)
++      addi    sp, sp, -48
++      ret
++      
+--- gcc-3.4.3/gcc/config/nios2/lib2-divmod-hi.c
++++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divmod-hi.c
+@@ -0,0 +1,123 @@
++
++/* We include auto-host.h here to get HAVE_GAS_HIDDEN.  This is
++   supposedly valid even though this is a "target" file.  */
++#include "auto-host.h"
++
++
++#include "tconfig.h"
++#include "tsystem.h"
++#include "coretypes.h"
++#include "tm.h"
++
++
++/* Don't use `fancy_abort' here even if config.h says to use it.  */
++#ifdef abort
++#undef abort
++#endif
++
++
++#ifdef HAVE_GAS_HIDDEN
++#define ATTRIBUTE_HIDDEN  __attribute__ ((__visibility__ ("hidden")))
++#else
++#define ATTRIBUTE_HIDDEN
++#endif
++
++#include "libgcc2.h"
++
++extern HItype __modhi3 (HItype, HItype);
++extern HItype __divhi3 (HItype, HItype);
++extern HItype __umodhi3 (HItype, HItype);
++extern HItype __udivhi3 (HItype, HItype);
++
++static UHItype udivmodhi4(UHItype, UHItype, word_type);
++
++static UHItype
++udivmodhi4(UHItype num, UHItype den, word_type modwanted)
++{
++  UHItype bit = 1;
++  UHItype res = 0;
++
++  while (den < num && bit && !(den & (1L<<15)))
++    {
++      den <<=1;
++      bit <<=1;
++    }
++  while (bit)
++    {
++      if (num >= den)
++      {
++        num -= den;
++        res |= bit;
++      }
++      bit >>=1;
++      den >>=1;
++    }
++  if (modwanted) return num;
++  return res;
++}
++
++
++HItype
++__divhi3 (HItype a, HItype b)
++{
++  word_type neg = 0;
++  HItype res;
++
++  if (a < 0)
++    {
++      a = -a;
++      neg = !neg;
++    }
++
++  if (b < 0)
++    {
++      b = -b;
++      neg = !neg;
++    }
++
++  res = udivmodhi4 (a, b, 0);
++
++  if (neg)
++    res = -res;
++
++  return res;
++}
++
++
++HItype
++__modhi3 (HItype a, HItype b)
++{
++  word_type neg = 0;
++  HItype res;
++
++  if (a < 0)
++    {
++      a = -a;
++      neg = 1;
++    }
++
++  if (b < 0)
++    b = -b;
++
++  res = udivmodhi4 (a, b, 1);
++
++  if (neg)
++    res = -res;
++
++  return res;
++}
++
++
++HItype
++__udivhi3 (HItype a, HItype b)
++{
++  return udivmodhi4 (a, b, 0);
++}
++
++
++HItype
++__umodhi3 (HItype a, HItype b)
++{
++  return udivmodhi4 (a, b, 1);
++}
++
+--- gcc-3.4.3/gcc/config/nios2/lib2-divmod.c
++++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divmod.c
+@@ -0,0 +1,126 @@
++
++/* We include auto-host.h here to get HAVE_GAS_HIDDEN.  This is
++   supposedly valid even though this is a "target" file.  */
++#include "auto-host.h"
++
++
++#include "tconfig.h"
++#include "tsystem.h"
++#include "coretypes.h"
++#include "tm.h"
++
++
++/* Don't use `fancy_abort' here even if config.h says to use it.  */
++#ifdef abort
++#undef abort
++#endif
++
++
++#ifdef HAVE_GAS_HIDDEN
++#define ATTRIBUTE_HIDDEN  __attribute__ ((__visibility__ ("hidden")))
++#else
++#define ATTRIBUTE_HIDDEN
++#endif
++
++#include "libgcc2.h"
++
++extern SItype __modsi3 (SItype, SItype);
++extern SItype __divsi3 (SItype, SItype);
++extern SItype __umodsi3 (SItype, SItype);
++extern SItype __udivsi3 (SItype, SItype);
++
++static USItype udivmodsi4(USItype, USItype, word_type);
++
++/* 16-bit SI divide and modulo as used in NIOS */
++
++
++static USItype
++udivmodsi4(USItype num, USItype den, word_type modwanted)
++{
++  USItype bit = 1;
++  USItype res = 0;
++
++  while (den < num && bit && !(den & (1L<<31)))
++    {
++      den <<=1;
++      bit <<=1;
++    }
++  while (bit)
++    {
++      if (num >= den)
++      {
++        num -= den;
++        res |= bit;
++      }
++      bit >>=1;
++      den >>=1;
++    }
++  if (modwanted) return num;
++  return res;
++}
++
++
++SItype
++__divsi3 (SItype a, SItype b)
++{
++  word_type neg = 0;
++  SItype res;
++
++  if (a < 0)
++    {
++      a = -a;
++      neg = !neg;
++    }
++
++  if (b < 0)
++    {
++      b = -b;
++      neg = !neg;
++    }
++
++  res = udivmodsi4 (a, b, 0);
++
++  if (neg)
++    res = -res;
++
++  return res;
++}
++
++
++SItype
++__modsi3 (SItype a, SItype b)
++{
++  word_type neg = 0;
++  SItype res;
++
++  if (a < 0)
++    {
++      a = -a;
++      neg = 1;
++    }
++
++  if (b < 0)
++    b = -b;
++
++  res = udivmodsi4 (a, b, 1);
++
++  if (neg)
++    res = -res;
++
++  return res;
++}
++
++
++SItype
++__udivsi3 (SItype a, SItype b)
++{
++  return udivmodsi4 (a, b, 0);
++}
++
++
++SItype
++__umodsi3 (SItype a, SItype b)
++{
++  return udivmodsi4 (a, b, 1);
++}
++
+--- gcc-3.4.3/gcc/config/nios2/lib2-divtable.c
++++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divtable.c
+@@ -0,0 +1,46 @@
++
++/* We include auto-host.h here to get HAVE_GAS_HIDDEN.  This is
++   supposedly valid even though this is a "target" file.  */
++#include "auto-host.h"
++
++
++#include "tconfig.h"
++#include "tsystem.h"
++#include "coretypes.h"
++#include "tm.h"
++
++
++/* Don't use `fancy_abort' here even if config.h says to use it.  */
++#ifdef abort
++#undef abort
++#endif
++
++
++#ifdef HAVE_GAS_HIDDEN
++#define ATTRIBUTE_HIDDEN  __attribute__ ((__visibility__ ("hidden")))
++#else
++#define ATTRIBUTE_HIDDEN
++#endif
++
++#include "libgcc2.h"
++
++UQItype __divsi3_table[] =
++{
++  0, 0/1, 0/2, 0/3, 0/4, 0/5, 0/6, 0/7, 0/8, 0/9, 0/10, 0/11, 0/12, 0/13, 0/14, 0/15,
++  0, 1/1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10, 1/11, 1/12, 1/13, 1/14, 1/15,
++  0, 2/1, 2/2, 2/3, 2/4, 2/5, 2/6, 2/7, 2/8, 2/9, 2/10, 2/11, 2/12, 2/13, 2/14, 2/15,
++  0, 3/1, 3/2, 3/3, 3/4, 3/5, 3/6, 3/7, 3/8, 3/9, 3/10, 3/11, 3/12, 3/13, 3/14, 3/15,
++  0, 4/1, 4/2, 4/3, 4/4, 4/5, 4/6, 4/7, 4/8, 4/9, 4/10, 4/11, 4/12, 4/13, 4/14, 4/15,
++  0, 5/1, 5/2, 5/3, 5/4, 5/5, 5/6, 5/7, 5/8, 5/9, 5/10, 5/11, 5/12, 5/13, 5/14, 5/15,
++  0, 6/1, 6/2, 6/3, 6/4, 6/5, 6/6, 6/7, 6/8, 6/9, 6/10, 6/11, 6/12, 6/13, 6/14, 6/15,
++  0, 7/1, 7/2, 7/3, 7/4, 7/5, 7/6, 7/7, 7/8, 7/9, 7/10, 7/11, 7/12, 7/13, 7/14, 7/15,
++  0, 8/1, 8/2, 8/3, 8/4, 8/5, 8/6, 8/7, 8/8, 8/9, 8/10, 8/11, 8/12, 8/13, 8/14, 8/15,
++  0, 9/1, 9/2, 9/3, 9/4, 9/5, 9/6, 9/7, 9/8, 9/9, 9/10, 9/11, 9/12, 9/13, 9/14, 9/15,
++  0, 10/1, 10/2, 10/3, 10/4, 10/5, 10/6, 10/7, 10/8, 10/9, 10/10, 10/11, 10/12, 10/13, 10/14, 10/15,
++  0, 11/1, 11/2, 11/3, 11/4, 11/5, 11/6, 11/7, 11/8, 11/9, 11/10, 11/11, 11/12, 11/13, 11/14, 11/15,
++  0, 12/1, 12/2, 12/3, 12/4, 12/5, 12/6, 12/7, 12/8, 12/9, 12/10, 12/11, 12/12, 12/13, 12/14, 12/15,
++  0, 13/1, 13/2, 13/3, 13/4, 13/5, 13/6, 13/7, 13/8, 13/9, 13/10, 13/11, 13/12, 13/13, 13/14, 13/15,
++  0, 14/1, 14/2, 14/3, 14/4, 14/5, 14/6, 14/7, 14/8, 14/9, 14/10, 14/11, 14/12, 14/13, 14/14, 14/15,
++  0, 15/1, 15/2, 15/3, 15/4, 15/5, 15/6, 15/7, 15/8, 15/9, 15/10, 15/11, 15/12, 15/13, 15/14, 15/15,
++};
++
+--- gcc-3.4.3/gcc/config/nios2/lib2-mul.c
++++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-mul.c
+@@ -0,0 +1,103 @@
++/* while we are debugging (ie compile outside of gcc build) 
++   disable gcc specific headers */
++#ifndef DEBUG_MULSI3
++
++
++/* We include auto-host.h here to get HAVE_GAS_HIDDEN.  This is
++   supposedly valid even though this is a "target" file.  */
++#include "auto-host.h"
++
++
++#include "tconfig.h"
++#include "tsystem.h"
++#include "coretypes.h"
++#include "tm.h"
++
++
++/* Don't use `fancy_abort' here even if config.h says to use it.  */
++#ifdef abort
++#undef abort
++#endif
++
++
++#ifdef HAVE_GAS_HIDDEN
++#define ATTRIBUTE_HIDDEN  __attribute__ ((__visibility__ ("hidden")))
++#else
++#define ATTRIBUTE_HIDDEN
++#endif
++
++#include "libgcc2.h"
++
++#else
++#define SItype int
++#define USItype unsigned int
++#endif
++
++
++extern SItype __mulsi3 (SItype, SItype);
++
++SItype
++__mulsi3 (SItype a, SItype b)
++{
++  SItype res = 0;
++  USItype cnt = a;
++  
++  while (cnt)
++    {
++      if (cnt & 1)
++        {
++        res += b;       
++      }
++      b <<= 1;
++      cnt >>= 1;
++    }
++    
++  return res;
++}
++/*
++TODO: Choose best alternative implementation.
++
++SItype
++__divsi3 (SItype a, SItype b)
++{
++  SItype res = 0;
++  USItype cnt = 0;
++  
++  while (cnt < 32)
++    {
++      if (a & (1L << cnt))
++        {
++        res += b;       
++      }
++      b <<= 1;
++      cnt++;
++    }
++    
++  return res;
++}
++*/
++
++
++#ifdef DEBUG_MULSI3
++
++int
++main ()
++{
++  int i, j;
++  int error = 0;
++  
++  for (i = -1000; i < 1000; i++)
++    for (j = -1000; j < 1000; j++)
++      {
++      int expect = i * j;
++      int actual = A__divsi3 (i, j);
++      if (expect != actual)
++        {
++          printf ("error: %d * %d = %d not %d\n", i, j, expect, actual);
++          error = 1;
++        }
++      }
++
++  return error;
++}
++#endif
+--- gcc-3.4.3/gcc/config/nios2/nios2-dp-bit.c
++++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-dp-bit.c
+@@ -0,0 +1,1652 @@
++
++/* This is a software floating point library which can be used
++   for targets without hardware floating point. 
++   Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004
++   Free Software Foundation, Inc.
++
++This file is free software; you can redistribute it and/or modify it
++under the terms of the GNU General Public License as published by the
++Free Software Foundation; either version 2, or (at your option) any
++later version.
++
++In addition to the permissions in the GNU General Public License, the
++Free Software Foundation gives you unlimited permission to link the
++compiled version of this file with other programs, and to distribute
++those programs without any restriction coming from the use of this
++file.  (The General Public License restrictions do apply in other
++respects; for example, they cover modification of the file, and
++distribution when not linked into another program.)
++
++This file 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 this program; 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 other files,
++   some of which are compiled with GCC, to produce an executable,
++   this library does not by itself cause the resulting executable
++   to be covered by the GNU General Public License.
++   This exception does not however invalidate any other reasons why
++   the executable file might be covered by the GNU General Public License.  */
++
++/* This implements IEEE 754 format arithmetic, but does not provide a
++   mechanism for setting the rounding mode, or for generating or handling
++   exceptions.
++
++   The original code by Steve Chamberlain, hacked by Mark Eichin and Jim
++   Wilson, all of Cygnus Support.  */
++
++/* The intended way to use this file is to make two copies, add `#define FLOAT'
++   to one copy, then compile both copies and add them to libgcc.a.  */
++
++#include "tconfig.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "config/fp-bit.h"
++
++/* The following macros can be defined to change the behavior of this file:
++   FLOAT: Implement a `float', aka SFmode, fp library.  If this is not
++     defined, then this file implements a `double', aka DFmode, fp library.
++   FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e.
++     don't include float->double conversion which requires the double library.
++     This is useful only for machines which can't support doubles, e.g. some
++     8-bit processors.
++   CMPtype: Specify the type that floating point compares should return.
++     This defaults to SItype, aka int.
++   US_SOFTWARE_GOFAST: This makes all entry points use the same names as the
++     US Software goFast library.
++   _DEBUG_BITFLOAT: This makes debugging the code a little easier, by adding
++     two integers to the FLO_union_type.
++   NO_DENORMALS: Disable handling of denormals.
++   NO_NANS: Disable nan and infinity handling
++   SMALL_MACHINE: Useful when operations on QIs and HIs are faster
++     than on an SI */
++
++/* We don't currently support extended floats (long doubles) on machines
++   without hardware to deal with them.
++
++   These stubs are just to keep the linker from complaining about unresolved
++   references which can be pulled in from libio & libstdc++, even if the
++   user isn't using long doubles.  However, they may generate an unresolved
++   external to abort if abort is not used by the function, and the stubs
++   are referenced from within libc, since libgcc goes before and after the
++   system library.  */
++
++#ifdef DECLARE_LIBRARY_RENAMES
++  DECLARE_LIBRARY_RENAMES
++#endif
++
++#ifdef EXTENDED_FLOAT_STUBS
++extern void abort (void);
++void __extendsfxf2 (void) { abort(); }
++void __extenddfxf2 (void) { abort(); }
++void __truncxfdf2 (void) { abort(); }
++void __truncxfsf2 (void) { abort(); }
++void __fixxfsi (void) { abort(); }
++void __floatsixf (void) { abort(); }
++void __addxf3 (void) { abort(); }
++void __subxf3 (void) { abort(); }
++void __mulxf3 (void) { abort(); }
++void __divxf3 (void) { abort(); }
++void __negxf2 (void) { abort(); }
++void __eqxf2 (void) { abort(); }
++void __nexf2 (void) { abort(); }
++void __gtxf2 (void) { abort(); }
++void __gexf2 (void) { abort(); }
++void __lexf2 (void) { abort(); }
++void __ltxf2 (void) { abort(); }
++
++void __extendsftf2 (void) { abort(); }
++void __extenddftf2 (void) { abort(); }
++void __trunctfdf2 (void) { abort(); }
++void __trunctfsf2 (void) { abort(); }
++void __fixtfsi (void) { abort(); }
++void __floatsitf (void) { abort(); }
++void __addtf3 (void) { abort(); }
++void __subtf3 (void) { abort(); }
++void __multf3 (void) { abort(); }
++void __divtf3 (void) { abort(); }
++void __negtf2 (void) { abort(); }
++void __eqtf2 (void) { abort(); }
++void __netf2 (void) { abort(); }
++void __gttf2 (void) { abort(); }
++void __getf2 (void) { abort(); }
++void __letf2 (void) { abort(); }
++void __lttf2 (void) { abort(); }
++#else /* !EXTENDED_FLOAT_STUBS, rest of file */
++
++/* IEEE "special" number predicates */
++
++#ifdef NO_NANS
++
++#define nan() 0
++#define isnan(x) 0
++#define isinf(x) 0
++#else
++
++#if   defined L_thenan_sf
++const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
++#elif defined L_thenan_df
++const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} };
++#elif defined L_thenan_tf
++const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
++#elif defined TFLOAT
++extern const fp_number_type __thenan_tf;
++#elif defined FLOAT
++extern const fp_number_type __thenan_sf;
++#else
++extern const fp_number_type __thenan_df;
++#endif
++
++INLINE
++static fp_number_type *
++nan (void)
++{
++  /* Discard the const qualifier...  */
++#ifdef TFLOAT
++  return (fp_number_type *) (& __thenan_tf);
++#elif defined FLOAT  
++  return (fp_number_type *) (& __thenan_sf);
++#else
++  return (fp_number_type *) (& __thenan_df);
++#endif
++}
++
++INLINE
++static int
++isnan ( fp_number_type *  x)
++{
++  return x->class == CLASS_SNAN || x->class == CLASS_QNAN;
++}
++
++INLINE
++static int
++isinf ( fp_number_type *  x)
++{
++  return x->class == CLASS_INFINITY;
++}
++
++#endif /* NO_NANS */
++
++INLINE
++static int
++iszero ( fp_number_type *  x)
++{
++  return x->class == CLASS_ZERO;
++}
++
++INLINE 
++static void
++flip_sign ( fp_number_type *  x)
++{
++  x->sign = !x->sign;
++}
++
++extern FLO_type pack_d ( fp_number_type * );
++
++#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
++FLO_type
++pack_d ( fp_number_type *  src)
++{
++  FLO_union_type dst;
++  fractype fraction = src->fraction.ll;       /* wasn't unsigned before? */
++  int sign = src->sign;
++  int exp = 0;
++
++  if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src)))
++    {
++      /* We can't represent these values accurately.  By using the
++       largest possible magnitude, we guarantee that the conversion
++       of infinity is at least as big as any finite number.  */
++      exp = EXPMAX;
++      fraction = ((fractype) 1 << FRACBITS) - 1;
++    }
++  else if (isnan (src))
++    {
++      exp = EXPMAX;
++      if (src->class == CLASS_QNAN || 1)
++      {
++#ifdef QUIET_NAN_NEGATED
++        fraction |= QUIET_NAN - 1;
++#else
++        fraction |= QUIET_NAN;
++#endif
++      }
++    }
++  else if (isinf (src))
++    {
++      exp = EXPMAX;
++      fraction = 0;
++    }
++  else if (iszero (src))
++    {
++      exp = 0;
++      fraction = 0;
++    }
++  else if (fraction == 0)
++    {
++      exp = 0;
++    }
++  else
++    {
++      if (src->normal_exp < NORMAL_EXPMIN)
++      {
++#ifdef NO_DENORMALS
++        /* Go straight to a zero representation if denormals are not
++           supported.  The denormal handling would be harmless but
++           isn't unnecessary.  */
++        exp = 0;
++        fraction = 0;
++#else /* NO_DENORMALS */
++        /* This number's exponent is too low to fit into the bits
++           available in the number, so we'll store 0 in the exponent and
++           shift the fraction to the right to make up for it.  */
++
++        int shift = NORMAL_EXPMIN - src->normal_exp;
++
++        exp = 0;
++
++        if (shift > FRAC_NBITS - NGARDS)
++          {
++            /* No point shifting, since it's more that 64 out.  */
++            fraction = 0;
++          }
++        else
++          {
++            int lowbit = (fraction & (((fractype)1 << shift) - 1)) ? 1 : 0;
++            fraction = (fraction >> shift) | lowbit;
++          }
++        if ((fraction & GARDMASK) == GARDMSB)
++          {
++            if ((fraction & (1 << NGARDS)))
++              fraction += GARDROUND + 1;
++          }
++        else
++          {
++            /* Add to the guards to round up.  */
++            fraction += GARDROUND;
++          }
++        /* Perhaps the rounding means we now need to change the
++             exponent, because the fraction is no longer denormal.  */
++        if (fraction >= IMPLICIT_1)
++          {
++            exp += 1;
++          }
++        fraction >>= NGARDS;
++#endif /* NO_DENORMALS */
++      }
++      else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
++             && src->normal_exp > EXPBIAS)
++      {
++        exp = EXPMAX;
++        fraction = 0;
++      }
++      else
++      {
++        exp = src->normal_exp + EXPBIAS;
++        if (!ROUND_TOWARDS_ZERO)
++          {
++            /* IF the gard bits are the all zero, but the first, then we're
++               half way between two numbers, choose the one which makes the
++               lsb of the answer 0.  */
++            if ((fraction & GARDMASK) == GARDMSB)
++              {
++                if (fraction & (1 << NGARDS))
++                  fraction += GARDROUND + 1;
++              }
++            else
++              {
++                /* Add a one to the guards to round up */
++                fraction += GARDROUND;
++              }
++            if (fraction >= IMPLICIT_2)
++              {
++                fraction >>= 1;
++                exp += 1;
++              }
++          }
++        fraction >>= NGARDS;
++
++        if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX)
++          {
++            /* Saturate on overflow.  */
++            exp = EXPMAX;
++            fraction = ((fractype) 1 << FRACBITS) - 1;
++          }
++      }
++    }
++
++  /* We previously used bitfields to store the number, but this doesn't
++     handle little/big endian systems conveniently, so use shifts and
++     masks */
++#ifdef FLOAT_BIT_ORDER_MISMATCH
++  dst.bits.fraction = fraction;
++  dst.bits.exp = exp;
++  dst.bits.sign = sign;
++#else
++# if defined TFLOAT && defined HALFFRACBITS
++ {
++   halffractype high, low, unity;
++   int lowsign, lowexp;
++
++   unity = (halffractype) 1 << HALFFRACBITS;
++
++   /* Set HIGH to the high double's significand, masking out the implicit 1.
++      Set LOW to the low double's full significand.  */
++   high = (fraction >> (FRACBITS - HALFFRACBITS)) & (unity - 1);
++   low = fraction & (unity * 2 - 1);
++
++   /* Get the initial sign and exponent of the low double.  */
++   lowexp = exp - HALFFRACBITS - 1;
++   lowsign = sign;
++
++   /* HIGH should be rounded like a normal double, making |LOW| <=
++      0.5 ULP of HIGH.  Assume round-to-nearest.  */
++   if (exp < EXPMAX)
++     if (low > unity || (low == unity && (high & 1) == 1))
++       {
++       /* Round HIGH up and adjust LOW to match.  */
++       high++;
++       if (high == unity)
++         {
++           /* May make it infinite, but that's OK.  */
++           high = 0;
++           exp++;
++         }
++       low = unity * 2 - low;
++       lowsign ^= 1;
++       }
++
++   high |= (halffractype) exp << HALFFRACBITS;
++   high |= (halffractype) sign << (HALFFRACBITS + EXPBITS);
++
++   if (exp == EXPMAX || exp == 0 || low == 0)
++     low = 0;
++   else
++     {
++       while (lowexp > 0 && low < unity)
++       {
++         low <<= 1;
++         lowexp--;
++       }
++
++       if (lowexp <= 0)
++       {
++         halffractype roundmsb, round;
++         int shift;
++
++         shift = 1 - lowexp;
++         roundmsb = (1 << (shift - 1));
++         round = low & ((roundmsb << 1) - 1);
++
++         low >>= shift;
++         lowexp = 0;
++
++         if (round > roundmsb || (round == roundmsb && (low & 1) == 1))
++           {
++             low++;
++             if (low == unity)
++               /* LOW rounds up to the smallest normal number.  */
++               lowexp++;
++           }
++       }
++
++       low &= unity - 1;
++       low |= (halffractype) lowexp << HALFFRACBITS;
++       low |= (halffractype) lowsign << (HALFFRACBITS + EXPBITS);
++     }
++   dst.value_raw = ((fractype) high << HALFSHIFT) | low;
++ }
++# else
++  dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1);
++  dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS;
++  dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS);
++# endif
++#endif
++
++#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
++#ifdef TFLOAT
++  {
++    qrtrfractype tmp1 = dst.words[0];
++    qrtrfractype tmp2 = dst.words[1];
++    dst.words[0] = dst.words[3];
++    dst.words[1] = dst.words[2];
++    dst.words[2] = tmp2;
++    dst.words[3] = tmp1;
++  }
++#else
++  {
++    halffractype tmp = dst.words[0];
++    dst.words[0] = dst.words[1];
++    dst.words[1] = tmp;
++  }
++#endif
++#endif
++
++  return dst.value;
++}
++#endif
++
++#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf)
++void
++unpack_d (FLO_union_type * src, fp_number_type * dst)
++{
++  /* We previously used bitfields to store the number, but this doesn't
++     handle little/big endian systems conveniently, so use shifts and
++     masks */
++  fractype fraction;
++  int exp;
++  int sign;
++
++#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
++  FLO_union_type swapped;
++
++#ifdef TFLOAT
++  swapped.words[0] = src->words[3];
++  swapped.words[1] = src->words[2];
++  swapped.words[2] = src->words[1];
++  swapped.words[3] = src->words[0];
++#else
++  swapped.words[0] = src->words[1];
++  swapped.words[1] = src->words[0];
++#endif
++  src = &swapped;
++#endif
++  
++#ifdef FLOAT_BIT_ORDER_MISMATCH
++  fraction = src->bits.fraction;
++  exp = src->bits.exp;
++  sign = src->bits.sign;
++#else
++# if defined TFLOAT && defined HALFFRACBITS
++ {
++   halffractype high, low;
++   
++   high = src->value_raw >> HALFSHIFT;
++   low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1);
++
++   fraction = high & ((((fractype)1) << HALFFRACBITS) - 1);
++   fraction <<= FRACBITS - HALFFRACBITS;
++   exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
++   sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1;
++
++   if (exp != EXPMAX && exp != 0 && low != 0)
++     {
++       int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
++       int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1;
++       int shift;
++       fractype xlow;
++
++       xlow = low & ((((fractype)1) << HALFFRACBITS) - 1);
++       if (lowexp)
++       xlow |= (((halffractype)1) << HALFFRACBITS);
++       else
++       lowexp = 1;
++       shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp);
++       if (shift > 0)
++       xlow <<= shift;
++       else if (shift < 0)
++       xlow >>= -shift;
++       if (sign == lowsign)
++       fraction += xlow;
++       else if (fraction >= xlow)
++       fraction -= xlow;
++       else
++       {
++         /* The high part is a power of two but the full number is lower.
++            This code will leave the implicit 1 in FRACTION, but we'd
++            have added that below anyway.  */
++         fraction = (((fractype) 1 << FRACBITS) - xlow) << 1;
++         exp--;
++       }
++     }
++ }
++# else
++  fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1);
++  exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1);
++  sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1;
++# endif
++#endif
++
++  dst->sign = sign;
++  if (exp == 0)
++    {
++      /* Hmm.  Looks like 0 */
++      if (fraction == 0
++#ifdef NO_DENORMALS
++        || 1
++#endif
++        )
++      {
++        /* tastes like zero */
++        dst->class = CLASS_ZERO;
++      }
++      else
++      {
++        /* Zero exponent with nonzero fraction - it's denormalized,
++           so there isn't a leading implicit one - we'll shift it so
++           it gets one.  */
++        dst->normal_exp = exp - EXPBIAS + 1;
++        fraction <<= NGARDS;
++
++        dst->class = CLASS_NUMBER;
++#if 1
++        while (fraction < IMPLICIT_1)
++          {
++            fraction <<= 1;
++            dst->normal_exp--;
++          }
++#endif
++        dst->fraction.ll = fraction;
++      }
++    }
++  else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX)
++    {
++      /* Huge exponent*/
++      if (fraction == 0)
++      {
++        /* Attached to a zero fraction - means infinity */
++        dst->class = CLASS_INFINITY;
++      }
++      else
++      {
++        /* Nonzero fraction, means nan */
++#ifdef QUIET_NAN_NEGATED
++        if ((fraction & QUIET_NAN) == 0)
++#else
++        if (fraction & QUIET_NAN)
++#endif
++          {
++            dst->class = CLASS_QNAN;
++          }
++        else
++          {
++            dst->class = CLASS_SNAN;
++          }
++        /* Keep the fraction part as the nan number */
++        dst->fraction.ll = fraction;
++      }
++    }
++  else
++    {
++      /* Nothing strange about this number */
++      dst->normal_exp = exp - EXPBIAS;
++      dst->class = CLASS_NUMBER;
++      dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1;
++    }
++}
++#endif /* L_unpack_df || L_unpack_sf */
++
++#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
++static fp_number_type *
++_fpadd_parts (fp_number_type * a,
++            fp_number_type * b,
++            fp_number_type * tmp)
++{
++  intfrac tfraction;
++
++  /* Put commonly used fields in local variables.  */
++  int a_normal_exp;
++  int b_normal_exp;
++  fractype a_fraction;
++  fractype b_fraction;
++
++  if (isnan (a))
++    {
++      return a;
++    }
++  if (isnan (b))
++    {
++      return b;
++    }
++  if (isinf (a))
++    {
++      /* Adding infinities with opposite signs yields a NaN.  */
++      if (isinf (b) && a->sign != b->sign)
++      return nan ();
++      return a;
++    }
++  if (isinf (b))
++    {
++      return b;
++    }
++  if (iszero (b))
++    {
++      if (iszero (a))
++      {
++        *tmp = *a;
++        tmp->sign = a->sign & b->sign;
++        return tmp;
++      }
++      return a;
++    }
++  if (iszero (a))
++    {
++      return b;
++    }
++
++  /* Got two numbers. shift the smaller and increment the exponent till
++     they're the same */
++  {
++    int diff;
++
++    a_normal_exp = a->normal_exp;
++    b_normal_exp = b->normal_exp;
++    a_fraction = a->fraction.ll;
++    b_fraction = b->fraction.ll;
++
++    diff = a_normal_exp - b_normal_exp;
++
++    if (diff < 0)
++      diff = -diff;
++    if (diff < FRAC_NBITS)
++      {
++      /* ??? This does shifts one bit at a time.  Optimize.  */
++      while (a_normal_exp > b_normal_exp)
++        {
++          b_normal_exp++;
++          LSHIFT (b_fraction);
++        }
++      while (b_normal_exp > a_normal_exp)
++        {
++          a_normal_exp++;
++          LSHIFT (a_fraction);
++        }
++      }
++    else
++      {
++      /* Somethings's up.. choose the biggest */
++      if (a_normal_exp > b_normal_exp)
++        {
++          b_normal_exp = a_normal_exp;
++          b_fraction = 0;
++        }
++      else
++        {
++          a_normal_exp = b_normal_exp;
++          a_fraction = 0;
++        }
++      }
++  }
++
++  if (a->sign != b->sign)
++    {
++      if (a->sign)
++      {
++        tfraction = -a_fraction + b_fraction;
++      }
++      else
++      {
++        tfraction = a_fraction - b_fraction;
++      }
++      if (tfraction >= 0)
++      {
++        tmp->sign = 0;
++        tmp->normal_exp = a_normal_exp;
++        tmp->fraction.ll = tfraction;
++      }
++      else
++      {
++        tmp->sign = 1;
++        tmp->normal_exp = a_normal_exp;
++        tmp->fraction.ll = -tfraction;
++      }
++      /* and renormalize it */
++
++      while (tmp->fraction.ll < IMPLICIT_1 && tmp->fraction.ll)
++      {
++        tmp->fraction.ll <<= 1;
++        tmp->normal_exp--;
++      }
++    }
++  else
++    {
++      tmp->sign = a->sign;
++      tmp->normal_exp = a_normal_exp;
++      tmp->fraction.ll = a_fraction + b_fraction;
++    }
++  tmp->class = CLASS_NUMBER;
++  /* Now the fraction is added, we have to shift down to renormalize the
++     number */
++
++  if (tmp->fraction.ll >= IMPLICIT_2)
++    {
++      LSHIFT (tmp->fraction.ll);
++      tmp->normal_exp++;
++    }
++  return tmp;
++
++}
++
++FLO_type
++add (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  fp_number_type tmp;
++  fp_number_type *res;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  res = _fpadd_parts (&a, &b, &tmp);
++
++  return pack_d (res);
++}
++
++FLO_type
++sub (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  fp_number_type tmp;
++  fp_number_type *res;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  b.sign ^= 1;
++
++  res = _fpadd_parts (&a, &b, &tmp);
++
++  return pack_d (res);
++}
++#endif /* L_addsub_sf || L_addsub_df */
++
++#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
++static inline __attribute__ ((__always_inline__)) fp_number_type *
++_fpmul_parts ( fp_number_type *  a,
++             fp_number_type *  b,
++             fp_number_type * tmp)
++{
++  fractype low = 0;
++  fractype high = 0;
++
++  if (isnan (a))
++    {
++      a->sign = a->sign != b->sign;
++      return a;
++    }
++  if (isnan (b))
++    {
++      b->sign = a->sign != b->sign;
++      return b;
++    }
++  if (isinf (a))
++    {
++      if (iszero (b))
++      return nan ();
++      a->sign = a->sign != b->sign;
++      return a;
++    }
++  if (isinf (b))
++    {
++      if (iszero (a))
++      {
++        return nan ();
++      }
++      b->sign = a->sign != b->sign;
++      return b;
++    }
++  if (iszero (a))
++    {
++      a->sign = a->sign != b->sign;
++      return a;
++    }
++  if (iszero (b))
++    {
++      b->sign = a->sign != b->sign;
++      return b;
++    }
++
++  /* Calculate the mantissa by multiplying both numbers to get a
++     twice-as-wide number.  */
++  {
++#if defined(NO_DI_MODE) || defined(TFLOAT)
++    {
++      fractype x = a->fraction.ll;
++      fractype ylow = b->fraction.ll;
++      fractype yhigh = 0;
++      int bit;
++
++      /* ??? This does multiplies one bit at a time.  Optimize.  */
++      for (bit = 0; bit < FRAC_NBITS; bit++)
++      {
++        int carry;
++
++        if (x & 1)
++          {
++            carry = (low += ylow) < ylow;
++            high += yhigh + carry;
++          }
++        yhigh <<= 1;
++        if (ylow & FRACHIGH)
++          {
++            yhigh |= 1;
++          }
++        ylow <<= 1;
++        x >>= 1;
++      }
++    }
++#elif defined(FLOAT) 
++    /* Multiplying two USIs to get a UDI, we're safe.  */
++    {
++      UDItype answer = (UDItype)a->fraction.ll * (UDItype)b->fraction.ll;
++      
++      high = answer >> BITS_PER_SI;
++      low = answer;
++    }
++#else
++    /* fractype is DImode, but we need the result to be twice as wide.
++       Assuming a widening multiply from DImode to TImode is not
++       available, build one by hand.  */
++    {
++      USItype nl = a->fraction.ll;
++      USItype nh = a->fraction.ll >> BITS_PER_SI;
++      USItype ml = b->fraction.ll;
++      USItype mh = b->fraction.ll >> BITS_PER_SI;
++      UDItype pp_ll = (UDItype) ml * nl;
++      UDItype pp_hl = (UDItype) mh * nl;
++      UDItype pp_lh = (UDItype) ml * nh;
++      UDItype pp_hh = (UDItype) mh * nh;
++      UDItype res2 = 0;
++      UDItype res0 = 0;
++      UDItype ps_hh__ = pp_hl + pp_lh;
++      if (ps_hh__ < pp_hl)
++      res2 += (UDItype)1 << BITS_PER_SI;
++      pp_hl = (UDItype)(USItype)ps_hh__ << BITS_PER_SI;
++      res0 = pp_ll + pp_hl;
++      if (res0 < pp_ll)
++      res2++;
++      res2 += (ps_hh__ >> BITS_PER_SI) + pp_hh;
++      high = res2;
++      low = res0;
++    }
++#endif
++  }
++
++  tmp->normal_exp = a->normal_exp + b->normal_exp
++    + FRAC_NBITS - (FRACBITS + NGARDS);
++  tmp->sign = a->sign != b->sign;
++  while (high >= IMPLICIT_2)
++    {
++      tmp->normal_exp++;
++      if (high & 1)
++      {
++        low >>= 1;
++        low |= FRACHIGH;
++      }
++      high >>= 1;
++    }
++  while (high < IMPLICIT_1)
++    {
++      tmp->normal_exp--;
++
++      high <<= 1;
++      if (low & FRACHIGH)
++      high |= 1;
++      low <<= 1;
++    }
++  /* rounding is tricky. if we only round if it won't make us round later.  */
++#if 0
++  if (low & FRACHIGH2)
++    {
++      if (((high & GARDMASK) != GARDMSB)
++        && (((high + 1) & GARDMASK) == GARDMSB))
++      {
++        /* don't round, it gets done again later.  */
++      }
++      else
++      {
++        high++;
++      }
++    }
++#endif
++  if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB)
++    {
++      if (high & (1 << NGARDS))
++      {
++        /* half way, so round to even */
++        high += GARDROUND + 1;
++      }
++      else if (low)
++      {
++        /* but we really weren't half way */
++        high += GARDROUND + 1;
++      }
++    }
++  tmp->fraction.ll = high;
++  tmp->class = CLASS_NUMBER;
++  return tmp;
++}
++
++FLO_type
++multiply (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  fp_number_type tmp;
++  fp_number_type *res;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  res = _fpmul_parts (&a, &b, &tmp);
++
++  return pack_d (res);
++}
++#endif /* L_mul_sf || L_mul_df */
++
++#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
++static inline __attribute__ ((__always_inline__)) fp_number_type *
++_fpdiv_parts (fp_number_type * a,
++            fp_number_type * b)
++{
++  fractype bit;
++  fractype numerator;
++  fractype denominator;
++  fractype quotient;
++
++  if (isnan (a))
++    {
++      return a;
++    }
++  if (isnan (b))
++    {
++      return b;
++    }
++
++  a->sign = a->sign ^ b->sign;
++
++  if (isinf (a) || iszero (a))
++    {
++      if (a->class == b->class)
++      return nan ();
++      return a;
++    }
++
++  if (isinf (b))
++    {
++      a->fraction.ll = 0;
++      a->normal_exp = 0;
++      return a;
++    }
++  if (iszero (b))
++    {
++      a->class = CLASS_INFINITY;
++      return a;
++    }
++
++  /* Calculate the mantissa by multiplying both 64bit numbers to get a
++     128 bit number */
++  {
++    /* quotient =
++       ( numerator / denominator) * 2^(numerator exponent -  denominator exponent)
++     */
++
++    a->normal_exp = a->normal_exp - b->normal_exp;
++    numerator = a->fraction.ll;
++    denominator = b->fraction.ll;
++
++    if (numerator < denominator)
++      {
++      /* Fraction will be less than 1.0 */
++      numerator *= 2;
++      a->normal_exp--;
++      }
++    bit = IMPLICIT_1;
++    quotient = 0;
++    /* ??? Does divide one bit at a time.  Optimize.  */
++    while (bit)
++      {
++      if (numerator >= denominator)
++        {
++          quotient |= bit;
++          numerator -= denominator;
++        }
++      bit >>= 1;
++      numerator *= 2;
++      }
++
++    if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB)
++      {
++      if (quotient & (1 << NGARDS))
++        {
++          /* half way, so round to even */
++          quotient += GARDROUND + 1;
++        }
++      else if (numerator)
++        {
++          /* but we really weren't half way, more bits exist */
++          quotient += GARDROUND + 1;
++        }
++      }
++
++    a->fraction.ll = quotient;
++    return (a);
++  }
++}
++
++FLO_type
++divide (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  fp_number_type *res;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  res = _fpdiv_parts (&a, &b);
++
++  return pack_d (res);
++}
++#endif /* L_div_sf || L_div_df */
++
++#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \
++    || defined(L_fpcmp_parts_tf)
++/* according to the demo, fpcmp returns a comparison with 0... thus
++   a<b -> -1
++   a==b -> 0
++   a>b -> +1
++ */
++
++int
++__fpcmp_parts (fp_number_type * a, fp_number_type * b)
++{
++#if 0
++  /* either nan -> unordered. Must be checked outside of this routine.  */
++  if (isnan (a) && isnan (b))
++    {
++      return 1;                       /* still unordered! */
++    }
++#endif
++
++  if (isnan (a) || isnan (b))
++    {
++      return 1;                       /* how to indicate unordered compare? */
++    }
++  if (isinf (a) && isinf (b))
++    {
++      /* +inf > -inf, but +inf != +inf */
++      /* b    \a| +inf(0)| -inf(1)
++       ______\+--------+--------
++       +inf(0)| a==b(0)| a<b(-1)
++       -------+--------+--------
++       -inf(1)| a>b(1) | a==b(0)
++       -------+--------+--------
++       So since unordered must be nonzero, just line up the columns...
++       */
++      return b->sign - a->sign;
++    }
++  /* but not both...  */
++  if (isinf (a))
++    {
++      return a->sign ? -1 : 1;
++    }
++  if (isinf (b))
++    {
++      return b->sign ? 1 : -1;
++    }
++  if (iszero (a) && iszero (b))
++    {
++      return 0;
++    }
++  if (iszero (a))
++    {
++      return b->sign ? 1 : -1;
++    }
++  if (iszero (b))
++    {
++      return a->sign ? -1 : 1;
++    }
++  /* now both are "normal".  */
++  if (a->sign != b->sign)
++    {
++      /* opposite signs */
++      return a->sign ? -1 : 1;
++    }
++  /* same sign; exponents? */
++  if (a->normal_exp > b->normal_exp)
++    {
++      return a->sign ? -1 : 1;
++    }
++  if (a->normal_exp < b->normal_exp)
++    {
++      return a->sign ? 1 : -1;
++    }
++  /* same exponents; check size.  */
++  if (a->fraction.ll > b->fraction.ll)
++    {
++      return a->sign ? -1 : 1;
++    }
++  if (a->fraction.ll < b->fraction.ll)
++    {
++      return a->sign ? 1 : -1;
++    }
++  /* after all that, they're equal.  */
++  return 0;
++}
++#endif
++
++#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf)
++CMPtype
++compare (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  return __fpcmp_parts (&a, &b);
++}
++#endif /* L_compare_sf || L_compare_df */
++
++#ifndef US_SOFTWARE_GOFAST
++
++/* These should be optimized for their specific tasks someday.  */
++
++#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf)
++CMPtype
++_eq_f2 (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  if (isnan (&a) || isnan (&b))
++    return 1;                 /* false, truth == 0 */
++
++  return __fpcmp_parts (&a, &b) ;
++}
++#endif /* L_eq_sf || L_eq_df */
++
++#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf)
++CMPtype
++_ne_f2 (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  if (isnan (&a) || isnan (&b))
++    return 1;                 /* true, truth != 0 */
++
++  return  __fpcmp_parts (&a, &b) ;
++}
++#endif /* L_ne_sf || L_ne_df */
++
++#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf)
++CMPtype
++_gt_f2 (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  if (isnan (&a) || isnan (&b))
++    return -1;                        /* false, truth > 0 */
++
++  return __fpcmp_parts (&a, &b);
++}
++#endif /* L_gt_sf || L_gt_df */
++
++#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf)
++CMPtype
++_ge_f2 (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  if (isnan (&a) || isnan (&b))
++    return -1;                        /* false, truth >= 0 */
++  return __fpcmp_parts (&a, &b) ;
++}
++#endif /* L_ge_sf || L_ge_df */
++
++#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf)
++CMPtype
++_lt_f2 (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  if (isnan (&a) || isnan (&b))
++    return 1;                 /* false, truth < 0 */
++
++  return __fpcmp_parts (&a, &b);
++}
++#endif /* L_lt_sf || L_lt_df */
++
++#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf)
++CMPtype
++_le_f2 (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  if (isnan (&a) || isnan (&b))
++    return 1;                 /* false, truth <= 0 */
++
++  return __fpcmp_parts (&a, &b) ;
++}
++#endif /* L_le_sf || L_le_df */
++
++#endif /* ! US_SOFTWARE_GOFAST */
++
++#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf)
++CMPtype
++_unord_f2 (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  return (isnan (&a) || isnan (&b));
++}
++#endif /* L_unord_sf || L_unord_df */
++
++#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf)
++FLO_type
++si_to_float (SItype arg_a)
++{
++  fp_number_type in;
++
++  in.class = CLASS_NUMBER;
++  in.sign = arg_a < 0;
++  if (!arg_a)
++    {
++      in.class = CLASS_ZERO;
++    }
++  else
++    {
++      in.normal_exp = FRACBITS + NGARDS;
++      if (in.sign) 
++      {
++        /* Special case for minint, since there is no +ve integer
++           representation for it */
++        if (arg_a == (- MAX_SI_INT - 1))
++          {
++            return (FLO_type)(- MAX_SI_INT - 1);
++          }
++        in.fraction.ll = (-arg_a);
++      }
++      else
++      in.fraction.ll = arg_a;
++
++      while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
++      {
++        in.fraction.ll <<= 1;
++        in.normal_exp -= 1;
++      }
++    }
++  return pack_d (&in);
++}
++#endif /* L_si_to_sf || L_si_to_df */
++
++#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf)
++FLO_type
++usi_to_float (USItype arg_a)
++{
++  fp_number_type in;
++
++  in.sign = 0;
++  if (!arg_a)
++    {
++      in.class = CLASS_ZERO;
++    }
++  else
++    {
++      in.class = CLASS_NUMBER;
++      in.normal_exp = FRACBITS + NGARDS;
++      in.fraction.ll = arg_a;
++
++      while (in.fraction.ll > ((fractype)1 << (FRACBITS + NGARDS)))
++        {
++          in.fraction.ll >>= 1;
++          in.normal_exp += 1;
++        }
++      while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
++      {
++        in.fraction.ll <<= 1;
++        in.normal_exp -= 1;
++      }
++    }
++  return pack_d (&in);
++}
++#endif
++
++#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si)
++SItype
++float_to_si (FLO_type arg_a)
++{
++  fp_number_type a;
++  SItype tmp;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &a);
++
++  if (iszero (&a))
++    return 0;
++  if (isnan (&a))
++    return 0;
++  /* get reasonable MAX_SI_INT...  */
++  if (isinf (&a))
++    return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
++  /* it is a number, but a small one */
++  if (a.normal_exp < 0)
++    return 0;
++  if (a.normal_exp > BITS_PER_SI - 2)
++    return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
++  tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
++  return a.sign ? (-tmp) : (tmp);
++}
++#endif /* L_sf_to_si || L_df_to_si */
++
++#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi)
++#if defined US_SOFTWARE_GOFAST || defined(L_tf_to_usi)
++/* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines,
++   we also define them for GOFAST because the ones in libgcc2.c have the
++   wrong names and I'd rather define these here and keep GOFAST CYG-LOC's
++   out of libgcc2.c.  We can't define these here if not GOFAST because then
++   there'd be duplicate copies.  */
++
++USItype
++float_to_usi (FLO_type arg_a)
++{
++  fp_number_type a;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &a);
++
++  if (iszero (&a))
++    return 0;
++  if (isnan (&a))
++    return 0;
++  /* it is a negative number */
++  if (a.sign)
++    return 0;
++  /* get reasonable MAX_USI_INT...  */
++  if (isinf (&a))
++    return MAX_USI_INT;
++  /* it is a number, but a small one */
++  if (a.normal_exp < 0)
++    return 0;
++  if (a.normal_exp > BITS_PER_SI - 1)
++    return MAX_USI_INT;
++  else if (a.normal_exp > (FRACBITS + NGARDS))
++    return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS));
++  else
++    return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
++}
++#endif /* US_SOFTWARE_GOFAST */
++#endif /* L_sf_to_usi || L_df_to_usi */
++
++#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf)
++FLO_type
++negate (FLO_type arg_a)
++{
++  fp_number_type a;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &a);
++
++  flip_sign (&a);
++  return pack_d (&a);
++}
++#endif /* L_negate_sf || L_negate_df */
++
++#ifdef FLOAT
++
++#if defined(L_make_sf)
++SFtype
++__make_fp(fp_class_type class,
++           unsigned int sign,
++           int exp, 
++           USItype frac)
++{
++  fp_number_type in;
++
++  in.class = class;
++  in.sign = sign;
++  in.normal_exp = exp;
++  in.fraction.ll = frac;
++  return pack_d (&in);
++}
++#endif /* L_make_sf */
++
++#ifndef FLOAT_ONLY
++
++/* This enables one to build an fp library that supports float but not double.
++   Otherwise, we would get an undefined reference to __make_dp.
++   This is needed for some 8-bit ports that can't handle well values that
++   are 8-bytes in size, so we just don't support double for them at all.  */
++
++#if defined(L_sf_to_df)
++DFtype
++sf_to_df (SFtype arg_a)
++{
++  fp_number_type in;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &in);
++
++  return __make_dp (in.class, in.sign, in.normal_exp,
++                  ((UDItype) in.fraction.ll) << F_D_BITOFF);
++}
++#endif /* L_sf_to_df */
++
++#if defined(L_sf_to_tf) && defined(TMODES)
++TFtype
++sf_to_tf (SFtype arg_a)
++{
++  fp_number_type in;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &in);
++
++  return __make_tp (in.class, in.sign, in.normal_exp,
++                  ((UTItype) in.fraction.ll) << F_T_BITOFF);
++}
++#endif /* L_sf_to_df */
++
++#endif /* ! FLOAT_ONLY */
++#endif /* FLOAT */
++
++#ifndef FLOAT
++
++extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype);
++
++#if defined(L_make_df)
++DFtype
++__make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac)
++{
++  fp_number_type in;
++
++  in.class = class;
++  in.sign = sign;
++  in.normal_exp = exp;
++  in.fraction.ll = frac;
++  return pack_d (&in);
++}
++#endif /* L_make_df */
++
++#if defined(L_df_to_sf)
++SFtype
++df_to_sf (DFtype arg_a)
++{
++  fp_number_type in;
++  USItype sffrac;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &in);
++
++  sffrac = in.fraction.ll >> F_D_BITOFF;
++
++  /* We set the lowest guard bit in SFFRAC if we discarded any non
++     zero bits.  */
++  if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0)
++    sffrac |= 1;
++
++  return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
++}
++#endif /* L_df_to_sf */
++
++#if defined(L_df_to_tf) && defined(TMODES) \
++    && !defined(FLOAT) && !defined(TFLOAT)
++TFtype
++df_to_tf (DFtype arg_a)
++{
++  fp_number_type in;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &in);
++
++  return __make_tp (in.class, in.sign, in.normal_exp,
++                  ((UTItype) in.fraction.ll) << D_T_BITOFF);
++}
++#endif /* L_sf_to_df */
++
++#ifdef TFLOAT
++#if defined(L_make_tf)
++TFtype
++__make_tp(fp_class_type class,
++           unsigned int sign,
++           int exp, 
++           UTItype frac)
++{
++  fp_number_type in;
++
++  in.class = class;
++  in.sign = sign;
++  in.normal_exp = exp;
++  in.fraction.ll = frac;
++  return pack_d (&in);
++}
++#endif /* L_make_tf */
++
++#if defined(L_tf_to_df)
++DFtype
++tf_to_df (TFtype arg_a)
++{
++  fp_number_type in;
++  UDItype sffrac;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &in);
++
++  sffrac = in.fraction.ll >> D_T_BITOFF;
++
++  /* We set the lowest guard bit in SFFRAC if we discarded any non
++     zero bits.  */
++  if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0)
++    sffrac |= 1;
++
++  return __make_dp (in.class, in.sign, in.normal_exp, sffrac);
++}
++#endif /* L_tf_to_df */
++
++#if defined(L_tf_to_sf)
++SFtype
++tf_to_sf (TFtype arg_a)
++{
++  fp_number_type in;
++  USItype sffrac;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &in);
++
++  sffrac = in.fraction.ll >> F_T_BITOFF;
++
++  /* We set the lowest guard bit in SFFRAC if we discarded any non
++     zero bits.  */
++  if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0)
++    sffrac |= 1;
++
++  return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
++}
++#endif /* L_tf_to_sf */
++#endif /* TFLOAT */
++
++#endif /* ! FLOAT */
++#endif /* !EXTENDED_FLOAT_STUBS */
+--- gcc-3.4.3/gcc/config/nios2/nios2-fp-bit.c
++++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-fp-bit.c
+@@ -0,0 +1,1652 @@
++#define FLOAT
++/* This is a software floating point library which can be used
++   for targets without hardware floating point. 
++   Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004
++   Free Software Foundation, Inc.
++
++This file is free software; you can redistribute it and/or modify it
++under the terms of the GNU General Public License as published by the
++Free Software Foundation; either version 2, or (at your option) any
++later version.
++
++In addition to the permissions in the GNU General Public License, the
++Free Software Foundation gives you unlimited permission to link the
++compiled version of this file with other programs, and to distribute
++those programs without any restriction coming from the use of this
++file.  (The General Public License restrictions do apply in other
++respects; for example, they cover modification of the file, and
++distribution when not linked into another program.)
++
++This file 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 this program; 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 other files,
++   some of which are compiled with GCC, to produce an executable,
++   this library does not by itself cause the resulting executable
++   to be covered by the GNU General Public License.
++   This exception does not however invalidate any other reasons why
++   the executable file might be covered by the GNU General Public License.  */
++
++/* This implements IEEE 754 format arithmetic, but does not provide a
++   mechanism for setting the rounding mode, or for generating or handling
++   exceptions.
++
++   The original code by Steve Chamberlain, hacked by Mark Eichin and Jim
++   Wilson, all of Cygnus Support.  */
++
++/* The intended way to use this file is to make two copies, add `#define FLOAT'
++   to one copy, then compile both copies and add them to libgcc.a.  */
++
++#include "tconfig.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "config/fp-bit.h"
++
++/* The following macros can be defined to change the behavior of this file:
++   FLOAT: Implement a `float', aka SFmode, fp library.  If this is not
++     defined, then this file implements a `double', aka DFmode, fp library.
++   FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e.
++     don't include float->double conversion which requires the double library.
++     This is useful only for machines which can't support doubles, e.g. some
++     8-bit processors.
++   CMPtype: Specify the type that floating point compares should return.
++     This defaults to SItype, aka int.
++   US_SOFTWARE_GOFAST: This makes all entry points use the same names as the
++     US Software goFast library.
++   _DEBUG_BITFLOAT: This makes debugging the code a little easier, by adding
++     two integers to the FLO_union_type.
++   NO_DENORMALS: Disable handling of denormals.
++   NO_NANS: Disable nan and infinity handling
++   SMALL_MACHINE: Useful when operations on QIs and HIs are faster
++     than on an SI */
++
++/* We don't currently support extended floats (long doubles) on machines
++   without hardware to deal with them.
++
++   These stubs are just to keep the linker from complaining about unresolved
++   references which can be pulled in from libio & libstdc++, even if the
++   user isn't using long doubles.  However, they may generate an unresolved
++   external to abort if abort is not used by the function, and the stubs
++   are referenced from within libc, since libgcc goes before and after the
++   system library.  */
++
++#ifdef DECLARE_LIBRARY_RENAMES
++  DECLARE_LIBRARY_RENAMES
++#endif
++
++#ifdef EXTENDED_FLOAT_STUBS
++extern void abort (void);
++void __extendsfxf2 (void) { abort(); }
++void __extenddfxf2 (void) { abort(); }
++void __truncxfdf2 (void) { abort(); }
++void __truncxfsf2 (void) { abort(); }
++void __fixxfsi (void) { abort(); }
++void __floatsixf (void) { abort(); }
++void __addxf3 (void) { abort(); }
++void __subxf3 (void) { abort(); }
++void __mulxf3 (void) { abort(); }
++void __divxf3 (void) { abort(); }
++void __negxf2 (void) { abort(); }
++void __eqxf2 (void) { abort(); }
++void __nexf2 (void) { abort(); }
++void __gtxf2 (void) { abort(); }
++void __gexf2 (void) { abort(); }
++void __lexf2 (void) { abort(); }
++void __ltxf2 (void) { abort(); }
++
++void __extendsftf2 (void) { abort(); }
++void __extenddftf2 (void) { abort(); }
++void __trunctfdf2 (void) { abort(); }
++void __trunctfsf2 (void) { abort(); }
++void __fixtfsi (void) { abort(); }
++void __floatsitf (void) { abort(); }
++void __addtf3 (void) { abort(); }
++void __subtf3 (void) { abort(); }
++void __multf3 (void) { abort(); }
++void __divtf3 (void) { abort(); }
++void __negtf2 (void) { abort(); }
++void __eqtf2 (void) { abort(); }
++void __netf2 (void) { abort(); }
++void __gttf2 (void) { abort(); }
++void __getf2 (void) { abort(); }
++void __letf2 (void) { abort(); }
++void __lttf2 (void) { abort(); }
++#else /* !EXTENDED_FLOAT_STUBS, rest of file */
++
++/* IEEE "special" number predicates */
++
++#ifdef NO_NANS
++
++#define nan() 0
++#define isnan(x) 0
++#define isinf(x) 0
++#else
++
++#if   defined L_thenan_sf
++const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
++#elif defined L_thenan_df
++const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} };
++#elif defined L_thenan_tf
++const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
++#elif defined TFLOAT
++extern const fp_number_type __thenan_tf;
++#elif defined FLOAT
++extern const fp_number_type __thenan_sf;
++#else
++extern const fp_number_type __thenan_df;
++#endif
++
++INLINE
++static fp_number_type *
++nan (void)
++{
++  /* Discard the const qualifier...  */
++#ifdef TFLOAT
++  return (fp_number_type *) (& __thenan_tf);
++#elif defined FLOAT  
++  return (fp_number_type *) (& __thenan_sf);
++#else
++  return (fp_number_type *) (& __thenan_df);
++#endif
++}
++
++INLINE
++static int
++isnan ( fp_number_type *  x)
++{
++  return x->class == CLASS_SNAN || x->class == CLASS_QNAN;
++}
++
++INLINE
++static int
++isinf ( fp_number_type *  x)
++{
++  return x->class == CLASS_INFINITY;
++}
++
++#endif /* NO_NANS */
++
++INLINE
++static int
++iszero ( fp_number_type *  x)
++{
++  return x->class == CLASS_ZERO;
++}
++
++INLINE 
++static void
++flip_sign ( fp_number_type *  x)
++{
++  x->sign = !x->sign;
++}
++
++extern FLO_type pack_d ( fp_number_type * );
++
++#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
++FLO_type
++pack_d ( fp_number_type *  src)
++{
++  FLO_union_type dst;
++  fractype fraction = src->fraction.ll;       /* wasn't unsigned before? */
++  int sign = src->sign;
++  int exp = 0;
++
++  if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src)))
++    {
++      /* We can't represent these values accurately.  By using the
++       largest possible magnitude, we guarantee that the conversion
++       of infinity is at least as big as any finite number.  */
++      exp = EXPMAX;
++      fraction = ((fractype) 1 << FRACBITS) - 1;
++    }
++  else if (isnan (src))
++    {
++      exp = EXPMAX;
++      if (src->class == CLASS_QNAN || 1)
++      {
++#ifdef QUIET_NAN_NEGATED
++        fraction |= QUIET_NAN - 1;
++#else
++        fraction |= QUIET_NAN;
++#endif
++      }
++    }
++  else if (isinf (src))
++    {
++      exp = EXPMAX;
++      fraction = 0;
++    }
++  else if (iszero (src))
++    {
++      exp = 0;
++      fraction = 0;
++    }
++  else if (fraction == 0)
++    {
++      exp = 0;
++    }
++  else
++    {
++      if (src->normal_exp < NORMAL_EXPMIN)
++      {
++#ifdef NO_DENORMALS
++        /* Go straight to a zero representation if denormals are not
++           supported.  The denormal handling would be harmless but
++           isn't unnecessary.  */
++        exp = 0;
++        fraction = 0;
++#else /* NO_DENORMALS */
++        /* This number's exponent is too low to fit into the bits
++           available in the number, so we'll store 0 in the exponent and
++           shift the fraction to the right to make up for it.  */
++
++        int shift = NORMAL_EXPMIN - src->normal_exp;
++
++        exp = 0;
++
++        if (shift > FRAC_NBITS - NGARDS)
++          {
++            /* No point shifting, since it's more that 64 out.  */
++            fraction = 0;
++          }
++        else
++          {
++            int lowbit = (fraction & (((fractype)1 << shift) - 1)) ? 1 : 0;
++            fraction = (fraction >> shift) | lowbit;
++          }
++        if ((fraction & GARDMASK) == GARDMSB)
++          {
++            if ((fraction & (1 << NGARDS)))
++              fraction += GARDROUND + 1;
++          }
++        else
++          {
++            /* Add to the guards to round up.  */
++            fraction += GARDROUND;
++          }
++        /* Perhaps the rounding means we now need to change the
++             exponent, because the fraction is no longer denormal.  */
++        if (fraction >= IMPLICIT_1)
++          {
++            exp += 1;
++          }
++        fraction >>= NGARDS;
++#endif /* NO_DENORMALS */
++      }
++      else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
++             && src->normal_exp > EXPBIAS)
++      {
++        exp = EXPMAX;
++        fraction = 0;
++      }
++      else
++      {
++        exp = src->normal_exp + EXPBIAS;
++        if (!ROUND_TOWARDS_ZERO)
++          {
++            /* IF the gard bits are the all zero, but the first, then we're
++               half way between two numbers, choose the one which makes the
++               lsb of the answer 0.  */
++            if ((fraction & GARDMASK) == GARDMSB)
++              {
++                if (fraction & (1 << NGARDS))
++                  fraction += GARDROUND + 1;
++              }
++            else
++              {
++                /* Add a one to the guards to round up */
++                fraction += GARDROUND;
++              }
++            if (fraction >= IMPLICIT_2)
++              {
++                fraction >>= 1;
++                exp += 1;
++              }
++          }
++        fraction >>= NGARDS;
++
++        if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX)
++          {
++            /* Saturate on overflow.  */
++            exp = EXPMAX;
++            fraction = ((fractype) 1 << FRACBITS) - 1;
++          }
++      }
++    }
++
++  /* We previously used bitfields to store the number, but this doesn't
++     handle little/big endian systems conveniently, so use shifts and
++     masks */
++#ifdef FLOAT_BIT_ORDER_MISMATCH
++  dst.bits.fraction = fraction;
++  dst.bits.exp = exp;
++  dst.bits.sign = sign;
++#else
++# if defined TFLOAT && defined HALFFRACBITS
++ {
++   halffractype high, low, unity;
++   int lowsign, lowexp;
++
++   unity = (halffractype) 1 << HALFFRACBITS;
++
++   /* Set HIGH to the high double's significand, masking out the implicit 1.
++      Set LOW to the low double's full significand.  */
++   high = (fraction >> (FRACBITS - HALFFRACBITS)) & (unity - 1);
++   low = fraction & (unity * 2 - 1);
++
++   /* Get the initial sign and exponent of the low double.  */
++   lowexp = exp - HALFFRACBITS - 1;
++   lowsign = sign;
++
++   /* HIGH should be rounded like a normal double, making |LOW| <=
++      0.5 ULP of HIGH.  Assume round-to-nearest.  */
++   if (exp < EXPMAX)
++     if (low > unity || (low == unity && (high & 1) == 1))
++       {
++       /* Round HIGH up and adjust LOW to match.  */
++       high++;
++       if (high == unity)
++         {
++           /* May make it infinite, but that's OK.  */
++           high = 0;
++           exp++;
++         }
++       low = unity * 2 - low;
++       lowsign ^= 1;
++       }
++
++   high |= (halffractype) exp << HALFFRACBITS;
++   high |= (halffractype) sign << (HALFFRACBITS + EXPBITS);
++
++   if (exp == EXPMAX || exp == 0 || low == 0)
++     low = 0;
++   else
++     {
++       while (lowexp > 0 && low < unity)
++       {
++         low <<= 1;
++         lowexp--;
++       }
++
++       if (lowexp <= 0)
++       {
++         halffractype roundmsb, round;
++         int shift;
++
++         shift = 1 - lowexp;
++         roundmsb = (1 << (shift - 1));
++         round = low & ((roundmsb << 1) - 1);
++
++         low >>= shift;
++         lowexp = 0;
++
++         if (round > roundmsb || (round == roundmsb && (low & 1) == 1))
++           {
++             low++;
++             if (low == unity)
++               /* LOW rounds up to the smallest normal number.  */
++               lowexp++;
++           }
++       }
++
++       low &= unity - 1;
++       low |= (halffractype) lowexp << HALFFRACBITS;
++       low |= (halffractype) lowsign << (HALFFRACBITS + EXPBITS);
++     }
++   dst.value_raw = ((fractype) high << HALFSHIFT) | low;
++ }
++# else
++  dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1);
++  dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS;
++  dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS);
++# endif
++#endif
++
++#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
++#ifdef TFLOAT
++  {
++    qrtrfractype tmp1 = dst.words[0];
++    qrtrfractype tmp2 = dst.words[1];
++    dst.words[0] = dst.words[3];
++    dst.words[1] = dst.words[2];
++    dst.words[2] = tmp2;
++    dst.words[3] = tmp1;
++  }
++#else
++  {
++    halffractype tmp = dst.words[0];
++    dst.words[0] = dst.words[1];
++    dst.words[1] = tmp;
++  }
++#endif
++#endif
++
++  return dst.value;
++}
++#endif
++
++#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf)
++void
++unpack_d (FLO_union_type * src, fp_number_type * dst)
++{
++  /* We previously used bitfields to store the number, but this doesn't
++     handle little/big endian systems conveniently, so use shifts and
++     masks */
++  fractype fraction;
++  int exp;
++  int sign;
++
++#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
++  FLO_union_type swapped;
++
++#ifdef TFLOAT
++  swapped.words[0] = src->words[3];
++  swapped.words[1] = src->words[2];
++  swapped.words[2] = src->words[1];
++  swapped.words[3] = src->words[0];
++#else
++  swapped.words[0] = src->words[1];
++  swapped.words[1] = src->words[0];
++#endif
++  src = &swapped;
++#endif
++  
++#ifdef FLOAT_BIT_ORDER_MISMATCH
++  fraction = src->bits.fraction;
++  exp = src->bits.exp;
++  sign = src->bits.sign;
++#else
++# if defined TFLOAT && defined HALFFRACBITS
++ {
++   halffractype high, low;
++   
++   high = src->value_raw >> HALFSHIFT;
++   low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1);
++
++   fraction = high & ((((fractype)1) << HALFFRACBITS) - 1);
++   fraction <<= FRACBITS - HALFFRACBITS;
++   exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
++   sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1;
++
++   if (exp != EXPMAX && exp != 0 && low != 0)
++     {
++       int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
++       int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1;
++       int shift;
++       fractype xlow;
++
++       xlow = low & ((((fractype)1) << HALFFRACBITS) - 1);
++       if (lowexp)
++       xlow |= (((halffractype)1) << HALFFRACBITS);
++       else
++       lowexp = 1;
++       shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp);
++       if (shift > 0)
++       xlow <<= shift;
++       else if (shift < 0)
++       xlow >>= -shift;
++       if (sign == lowsign)
++       fraction += xlow;
++       else if (fraction >= xlow)
++       fraction -= xlow;
++       else
++       {
++         /* The high part is a power of two but the full number is lower.
++            This code will leave the implicit 1 in FRACTION, but we'd
++            have added that below anyway.  */
++         fraction = (((fractype) 1 << FRACBITS) - xlow) << 1;
++         exp--;
++       }
++     }
++ }
++# else
++  fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1);
++  exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1);
++  sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1;
++# endif
++#endif
++
++  dst->sign = sign;
++  if (exp == 0)
++    {
++      /* Hmm.  Looks like 0 */
++      if (fraction == 0
++#ifdef NO_DENORMALS
++        || 1
++#endif
++        )
++      {
++        /* tastes like zero */
++        dst->class = CLASS_ZERO;
++      }
++      else
++      {
++        /* Zero exponent with nonzero fraction - it's denormalized,
++           so there isn't a leading implicit one - we'll shift it so
++           it gets one.  */
++        dst->normal_exp = exp - EXPBIAS + 1;
++        fraction <<= NGARDS;
++
++        dst->class = CLASS_NUMBER;
++#if 1
++        while (fraction < IMPLICIT_1)
++          {
++            fraction <<= 1;
++            dst->normal_exp--;
++          }
++#endif
++        dst->fraction.ll = fraction;
++      }
++    }
++  else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX)
++    {
++      /* Huge exponent*/
++      if (fraction == 0)
++      {
++        /* Attached to a zero fraction - means infinity */
++        dst->class = CLASS_INFINITY;
++      }
++      else
++      {
++        /* Nonzero fraction, means nan */
++#ifdef QUIET_NAN_NEGATED
++        if ((fraction & QUIET_NAN) == 0)
++#else
++        if (fraction & QUIET_NAN)
++#endif
++          {
++            dst->class = CLASS_QNAN;
++          }
++        else
++          {
++            dst->class = CLASS_SNAN;
++          }
++        /* Keep the fraction part as the nan number */
++        dst->fraction.ll = fraction;
++      }
++    }
++  else
++    {
++      /* Nothing strange about this number */
++      dst->normal_exp = exp - EXPBIAS;
++      dst->class = CLASS_NUMBER;
++      dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1;
++    }
++}
++#endif /* L_unpack_df || L_unpack_sf */
++
++#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
++static fp_number_type *
++_fpadd_parts (fp_number_type * a,
++            fp_number_type * b,
++            fp_number_type * tmp)
++{
++  intfrac tfraction;
++
++  /* Put commonly used fields in local variables.  */
++  int a_normal_exp;
++  int b_normal_exp;
++  fractype a_fraction;
++  fractype b_fraction;
++
++  if (isnan (a))
++    {
++      return a;
++    }
++  if (isnan (b))
++    {
++      return b;
++    }
++  if (isinf (a))
++    {
++      /* Adding infinities with opposite signs yields a NaN.  */
++      if (isinf (b) && a->sign != b->sign)
++      return nan ();
++      return a;
++    }
++  if (isinf (b))
++    {
++      return b;
++    }
++  if (iszero (b))
++    {
++      if (iszero (a))
++      {
++        *tmp = *a;
++        tmp->sign = a->sign & b->sign;
++        return tmp;
++      }
++      return a;
++    }
++  if (iszero (a))
++    {
++      return b;
++    }
++
++  /* Got two numbers. shift the smaller and increment the exponent till
++     they're the same */
++  {
++    int diff;
++
++    a_normal_exp = a->normal_exp;
++    b_normal_exp = b->normal_exp;
++    a_fraction = a->fraction.ll;
++    b_fraction = b->fraction.ll;
++
++    diff = a_normal_exp - b_normal_exp;
++
++    if (diff < 0)
++      diff = -diff;
++    if (diff < FRAC_NBITS)
++      {
++      /* ??? This does shifts one bit at a time.  Optimize.  */
++      while (a_normal_exp > b_normal_exp)
++        {
++          b_normal_exp++;
++          LSHIFT (b_fraction);
++        }
++      while (b_normal_exp > a_normal_exp)
++        {
++          a_normal_exp++;
++          LSHIFT (a_fraction);
++        }
++      }
++    else
++      {
++      /* Somethings's up.. choose the biggest */
++      if (a_normal_exp > b_normal_exp)
++        {
++          b_normal_exp = a_normal_exp;
++          b_fraction = 0;
++        }
++      else
++        {
++          a_normal_exp = b_normal_exp;
++          a_fraction = 0;
++        }
++      }
++  }
++
++  if (a->sign != b->sign)
++    {
++      if (a->sign)
++      {
++        tfraction = -a_fraction + b_fraction;
++      }
++      else
++      {
++        tfraction = a_fraction - b_fraction;
++      }
++      if (tfraction >= 0)
++      {
++        tmp->sign = 0;
++        tmp->normal_exp = a_normal_exp;
++        tmp->fraction.ll = tfraction;
++      }
++      else
++      {
++        tmp->sign = 1;
++        tmp->normal_exp = a_normal_exp;
++        tmp->fraction.ll = -tfraction;
++      }
++      /* and renormalize it */
++
++      while (tmp->fraction.ll < IMPLICIT_1 && tmp->fraction.ll)
++      {
++        tmp->fraction.ll <<= 1;
++        tmp->normal_exp--;
++      }
++    }
++  else
++    {
++      tmp->sign = a->sign;
++      tmp->normal_exp = a_normal_exp;
++      tmp->fraction.ll = a_fraction + b_fraction;
++    }
++  tmp->class = CLASS_NUMBER;
++  /* Now the fraction is added, we have to shift down to renormalize the
++     number */
++
++  if (tmp->fraction.ll >= IMPLICIT_2)
++    {
++      LSHIFT (tmp->fraction.ll);
++      tmp->normal_exp++;
++    }
++  return tmp;
++
++}
++
++FLO_type
++add (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  fp_number_type tmp;
++  fp_number_type *res;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  res = _fpadd_parts (&a, &b, &tmp);
++
++  return pack_d (res);
++}
++
++FLO_type
++sub (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  fp_number_type tmp;
++  fp_number_type *res;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  b.sign ^= 1;
++
++  res = _fpadd_parts (&a, &b, &tmp);
++
++  return pack_d (res);
++}
++#endif /* L_addsub_sf || L_addsub_df */
++
++#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
++static inline __attribute__ ((__always_inline__)) fp_number_type *
++_fpmul_parts ( fp_number_type *  a,
++             fp_number_type *  b,
++             fp_number_type * tmp)
++{
++  fractype low = 0;
++  fractype high = 0;
++
++  if (isnan (a))
++    {
++      a->sign = a->sign != b->sign;
++      return a;
++    }
++  if (isnan (b))
++    {
++      b->sign = a->sign != b->sign;
++      return b;
++    }
++  if (isinf (a))
++    {
++      if (iszero (b))
++      return nan ();
++      a->sign = a->sign != b->sign;
++      return a;
++    }
++  if (isinf (b))
++    {
++      if (iszero (a))
++      {
++        return nan ();
++      }
++      b->sign = a->sign != b->sign;
++      return b;
++    }
++  if (iszero (a))
++    {
++      a->sign = a->sign != b->sign;
++      return a;
++    }
++  if (iszero (b))
++    {
++      b->sign = a->sign != b->sign;
++      return b;
++    }
++
++  /* Calculate the mantissa by multiplying both numbers to get a
++     twice-as-wide number.  */
++  {
++#if defined(NO_DI_MODE) || defined(TFLOAT)
++    {
++      fractype x = a->fraction.ll;
++      fractype ylow = b->fraction.ll;
++      fractype yhigh = 0;
++      int bit;
++
++      /* ??? This does multiplies one bit at a time.  Optimize.  */
++      for (bit = 0; bit < FRAC_NBITS; bit++)
++      {
++        int carry;
++
++        if (x & 1)
++          {
++            carry = (low += ylow) < ylow;
++            high += yhigh + carry;
++          }
++        yhigh <<= 1;
++        if (ylow & FRACHIGH)
++          {
++            yhigh |= 1;
++          }
++        ylow <<= 1;
++        x >>= 1;
++      }
++    }
++#elif defined(FLOAT) 
++    /* Multiplying two USIs to get a UDI, we're safe.  */
++    {
++      UDItype answer = (UDItype)a->fraction.ll * (UDItype)b->fraction.ll;
++      
++      high = answer >> BITS_PER_SI;
++      low = answer;
++    }
++#else
++    /* fractype is DImode, but we need the result to be twice as wide.
++       Assuming a widening multiply from DImode to TImode is not
++       available, build one by hand.  */
++    {
++      USItype nl = a->fraction.ll;
++      USItype nh = a->fraction.ll >> BITS_PER_SI;
++      USItype ml = b->fraction.ll;
++      USItype mh = b->fraction.ll >> BITS_PER_SI;
++      UDItype pp_ll = (UDItype) ml * nl;
++      UDItype pp_hl = (UDItype) mh * nl;
++      UDItype pp_lh = (UDItype) ml * nh;
++      UDItype pp_hh = (UDItype) mh * nh;
++      UDItype res2 = 0;
++      UDItype res0 = 0;
++      UDItype ps_hh__ = pp_hl + pp_lh;
++      if (ps_hh__ < pp_hl)
++      res2 += (UDItype)1 << BITS_PER_SI;
++      pp_hl = (UDItype)(USItype)ps_hh__ << BITS_PER_SI;
++      res0 = pp_ll + pp_hl;
++      if (res0 < pp_ll)
++      res2++;
++      res2 += (ps_hh__ >> BITS_PER_SI) + pp_hh;
++      high = res2;
++      low = res0;
++    }
++#endif
++  }
++
++  tmp->normal_exp = a->normal_exp + b->normal_exp
++    + FRAC_NBITS - (FRACBITS + NGARDS);
++  tmp->sign = a->sign != b->sign;
++  while (high >= IMPLICIT_2)
++    {
++      tmp->normal_exp++;
++      if (high & 1)
++      {
++        low >>= 1;
++        low |= FRACHIGH;
++      }
++      high >>= 1;
++    }
++  while (high < IMPLICIT_1)
++    {
++      tmp->normal_exp--;
++
++      high <<= 1;
++      if (low & FRACHIGH)
++      high |= 1;
++      low <<= 1;
++    }
++  /* rounding is tricky. if we only round if it won't make us round later.  */
++#if 0
++  if (low & FRACHIGH2)
++    {
++      if (((high & GARDMASK) != GARDMSB)
++        && (((high + 1) & GARDMASK) == GARDMSB))
++      {
++        /* don't round, it gets done again later.  */
++      }
++      else
++      {
++        high++;
++      }
++    }
++#endif
++  if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB)
++    {
++      if (high & (1 << NGARDS))
++      {
++        /* half way, so round to even */
++        high += GARDROUND + 1;
++      }
++      else if (low)
++      {
++        /* but we really weren't half way */
++        high += GARDROUND + 1;
++      }
++    }
++  tmp->fraction.ll = high;
++  tmp->class = CLASS_NUMBER;
++  return tmp;
++}
++
++FLO_type
++multiply (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  fp_number_type tmp;
++  fp_number_type *res;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  res = _fpmul_parts (&a, &b, &tmp);
++
++  return pack_d (res);
++}
++#endif /* L_mul_sf || L_mul_df */
++
++#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
++static inline __attribute__ ((__always_inline__)) fp_number_type *
++_fpdiv_parts (fp_number_type * a,
++            fp_number_type * b)
++{
++  fractype bit;
++  fractype numerator;
++  fractype denominator;
++  fractype quotient;
++
++  if (isnan (a))
++    {
++      return a;
++    }
++  if (isnan (b))
++    {
++      return b;
++    }
++
++  a->sign = a->sign ^ b->sign;
++
++  if (isinf (a) || iszero (a))
++    {
++      if (a->class == b->class)
++      return nan ();
++      return a;
++    }
++
++  if (isinf (b))
++    {
++      a->fraction.ll = 0;
++      a->normal_exp = 0;
++      return a;
++    }
++  if (iszero (b))
++    {
++      a->class = CLASS_INFINITY;
++      return a;
++    }
++
++  /* Calculate the mantissa by multiplying both 64bit numbers to get a
++     128 bit number */
++  {
++    /* quotient =
++       ( numerator / denominator) * 2^(numerator exponent -  denominator exponent)
++     */
++
++    a->normal_exp = a->normal_exp - b->normal_exp;
++    numerator = a->fraction.ll;
++    denominator = b->fraction.ll;
++
++    if (numerator < denominator)
++      {
++      /* Fraction will be less than 1.0 */
++      numerator *= 2;
++      a->normal_exp--;
++      }
++    bit = IMPLICIT_1;
++    quotient = 0;
++    /* ??? Does divide one bit at a time.  Optimize.  */
++    while (bit)
++      {
++      if (numerator >= denominator)
++        {
++          quotient |= bit;
++          numerator -= denominator;
++        }
++      bit >>= 1;
++      numerator *= 2;
++      }
++
++    if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB)
++      {
++      if (quotient & (1 << NGARDS))
++        {
++          /* half way, so round to even */
++          quotient += GARDROUND + 1;
++        }
++      else if (numerator)
++        {
++          /* but we really weren't half way, more bits exist */
++          quotient += GARDROUND + 1;
++        }
++      }
++
++    a->fraction.ll = quotient;
++    return (a);
++  }
++}
++
++FLO_type
++divide (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  fp_number_type *res;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  res = _fpdiv_parts (&a, &b);
++
++  return pack_d (res);
++}
++#endif /* L_div_sf || L_div_df */
++
++#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \
++    || defined(L_fpcmp_parts_tf)
++/* according to the demo, fpcmp returns a comparison with 0... thus
++   a<b -> -1
++   a==b -> 0
++   a>b -> +1
++ */
++
++int
++__fpcmp_parts (fp_number_type * a, fp_number_type * b)
++{
++#if 0
++  /* either nan -> unordered. Must be checked outside of this routine.  */
++  if (isnan (a) && isnan (b))
++    {
++      return 1;                       /* still unordered! */
++    }
++#endif
++
++  if (isnan (a) || isnan (b))
++    {
++      return 1;                       /* how to indicate unordered compare? */
++    }
++  if (isinf (a) && isinf (b))
++    {
++      /* +inf > -inf, but +inf != +inf */
++      /* b    \a| +inf(0)| -inf(1)
++       ______\+--------+--------
++       +inf(0)| a==b(0)| a<b(-1)
++       -------+--------+--------
++       -inf(1)| a>b(1) | a==b(0)
++       -------+--------+--------
++       So since unordered must be nonzero, just line up the columns...
++       */
++      return b->sign - a->sign;
++    }
++  /* but not both...  */
++  if (isinf (a))
++    {
++      return a->sign ? -1 : 1;
++    }
++  if (isinf (b))
++    {
++      return b->sign ? 1 : -1;
++    }
++  if (iszero (a) && iszero (b))
++    {
++      return 0;
++    }
++  if (iszero (a))
++    {
++      return b->sign ? 1 : -1;
++    }
++  if (iszero (b))
++    {
++      return a->sign ? -1 : 1;
++    }
++  /* now both are "normal".  */
++  if (a->sign != b->sign)
++    {
++      /* opposite signs */
++      return a->sign ? -1 : 1;
++    }
++  /* same sign; exponents? */
++  if (a->normal_exp > b->normal_exp)
++    {
++      return a->sign ? -1 : 1;
++    }
++  if (a->normal_exp < b->normal_exp)
++    {
++      return a->sign ? 1 : -1;
++    }
++  /* same exponents; check size.  */
++  if (a->fraction.ll > b->fraction.ll)
++    {
++      return a->sign ? -1 : 1;
++    }
++  if (a->fraction.ll < b->fraction.ll)
++    {
++      return a->sign ? 1 : -1;
++    }
++  /* after all that, they're equal.  */
++  return 0;
++}
++#endif
++
++#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf)
++CMPtype
++compare (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  return __fpcmp_parts (&a, &b);
++}
++#endif /* L_compare_sf || L_compare_df */
++
++#ifndef US_SOFTWARE_GOFAST
++
++/* These should be optimized for their specific tasks someday.  */
++
++#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf)
++CMPtype
++_eq_f2 (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  if (isnan (&a) || isnan (&b))
++    return 1;                 /* false, truth == 0 */
++
++  return __fpcmp_parts (&a, &b) ;
++}
++#endif /* L_eq_sf || L_eq_df */
++
++#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf)
++CMPtype
++_ne_f2 (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  if (isnan (&a) || isnan (&b))
++    return 1;                 /* true, truth != 0 */
++
++  return  __fpcmp_parts (&a, &b) ;
++}
++#endif /* L_ne_sf || L_ne_df */
++
++#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf)
++CMPtype
++_gt_f2 (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  if (isnan (&a) || isnan (&b))
++    return -1;                        /* false, truth > 0 */
++
++  return __fpcmp_parts (&a, &b);
++}
++#endif /* L_gt_sf || L_gt_df */
++
++#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf)
++CMPtype
++_ge_f2 (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  if (isnan (&a) || isnan (&b))
++    return -1;                        /* false, truth >= 0 */
++  return __fpcmp_parts (&a, &b) ;
++}
++#endif /* L_ge_sf || L_ge_df */
++
++#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf)
++CMPtype
++_lt_f2 (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  if (isnan (&a) || isnan (&b))
++    return 1;                 /* false, truth < 0 */
++
++  return __fpcmp_parts (&a, &b);
++}
++#endif /* L_lt_sf || L_lt_df */
++
++#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf)
++CMPtype
++_le_f2 (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  if (isnan (&a) || isnan (&b))
++    return 1;                 /* false, truth <= 0 */
++
++  return __fpcmp_parts (&a, &b) ;
++}
++#endif /* L_le_sf || L_le_df */
++
++#endif /* ! US_SOFTWARE_GOFAST */
++
++#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf)
++CMPtype
++_unord_f2 (FLO_type arg_a, FLO_type arg_b)
++{
++  fp_number_type a;
++  fp_number_type b;
++  FLO_union_type au, bu;
++
++  au.value = arg_a;
++  bu.value = arg_b;
++
++  unpack_d (&au, &a);
++  unpack_d (&bu, &b);
++
++  return (isnan (&a) || isnan (&b));
++}
++#endif /* L_unord_sf || L_unord_df */
++
++#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf)
++FLO_type
++si_to_float (SItype arg_a)
++{
++  fp_number_type in;
++
++  in.class = CLASS_NUMBER;
++  in.sign = arg_a < 0;
++  if (!arg_a)
++    {
++      in.class = CLASS_ZERO;
++    }
++  else
++    {
++      in.normal_exp = FRACBITS + NGARDS;
++      if (in.sign) 
++      {
++        /* Special case for minint, since there is no +ve integer
++           representation for it */
++        if (arg_a == (- MAX_SI_INT - 1))
++          {
++            return (FLO_type)(- MAX_SI_INT - 1);
++          }
++        in.fraction.ll = (-arg_a);
++      }
++      else
++      in.fraction.ll = arg_a;
++
++      while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
++      {
++        in.fraction.ll <<= 1;
++        in.normal_exp -= 1;
++      }
++    }
++  return pack_d (&in);
++}
++#endif /* L_si_to_sf || L_si_to_df */
++
++#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf)
++FLO_type
++usi_to_float (USItype arg_a)
++{
++  fp_number_type in;
++
++  in.sign = 0;
++  if (!arg_a)
++    {
++      in.class = CLASS_ZERO;
++    }
++  else
++    {
++      in.class = CLASS_NUMBER;
++      in.normal_exp = FRACBITS + NGARDS;
++      in.fraction.ll = arg_a;
++
++      while (in.fraction.ll > ((fractype)1 << (FRACBITS + NGARDS)))
++        {
++          in.fraction.ll >>= 1;
++          in.normal_exp += 1;
++        }
++      while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
++      {
++        in.fraction.ll <<= 1;
++        in.normal_exp -= 1;
++      }
++    }
++  return pack_d (&in);
++}
++#endif
++
++#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si)
++SItype
++float_to_si (FLO_type arg_a)
++{
++  fp_number_type a;
++  SItype tmp;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &a);
++
++  if (iszero (&a))
++    return 0;
++  if (isnan (&a))
++    return 0;
++  /* get reasonable MAX_SI_INT...  */
++  if (isinf (&a))
++    return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
++  /* it is a number, but a small one */
++  if (a.normal_exp < 0)
++    return 0;
++  if (a.normal_exp > BITS_PER_SI - 2)
++    return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
++  tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
++  return a.sign ? (-tmp) : (tmp);
++}
++#endif /* L_sf_to_si || L_df_to_si */
++
++#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi)
++#if defined US_SOFTWARE_GOFAST || defined(L_tf_to_usi)
++/* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines,
++   we also define them for GOFAST because the ones in libgcc2.c have the
++   wrong names and I'd rather define these here and keep GOFAST CYG-LOC's
++   out of libgcc2.c.  We can't define these here if not GOFAST because then
++   there'd be duplicate copies.  */
++
++USItype
++float_to_usi (FLO_type arg_a)
++{
++  fp_number_type a;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &a);
++
++  if (iszero (&a))
++    return 0;
++  if (isnan (&a))
++    return 0;
++  /* it is a negative number */
++  if (a.sign)
++    return 0;
++  /* get reasonable MAX_USI_INT...  */
++  if (isinf (&a))
++    return MAX_USI_INT;
++  /* it is a number, but a small one */
++  if (a.normal_exp < 0)
++    return 0;
++  if (a.normal_exp > BITS_PER_SI - 1)
++    return MAX_USI_INT;
++  else if (a.normal_exp > (FRACBITS + NGARDS))
++    return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS));
++  else
++    return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
++}
++#endif /* US_SOFTWARE_GOFAST */
++#endif /* L_sf_to_usi || L_df_to_usi */
++
++#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf)
++FLO_type
++negate (FLO_type arg_a)
++{
++  fp_number_type a;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &a);
++
++  flip_sign (&a);
++  return pack_d (&a);
++}
++#endif /* L_negate_sf || L_negate_df */
++
++#ifdef FLOAT
++
++#if defined(L_make_sf)
++SFtype
++__make_fp(fp_class_type class,
++           unsigned int sign,
++           int exp, 
++           USItype frac)
++{
++  fp_number_type in;
++
++  in.class = class;
++  in.sign = sign;
++  in.normal_exp = exp;
++  in.fraction.ll = frac;
++  return pack_d (&in);
++}
++#endif /* L_make_sf */
++
++#ifndef FLOAT_ONLY
++
++/* This enables one to build an fp library that supports float but not double.
++   Otherwise, we would get an undefined reference to __make_dp.
++   This is needed for some 8-bit ports that can't handle well values that
++   are 8-bytes in size, so we just don't support double for them at all.  */
++
++#if defined(L_sf_to_df)
++DFtype
++sf_to_df (SFtype arg_a)
++{
++  fp_number_type in;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &in);
++
++  return __make_dp (in.class, in.sign, in.normal_exp,
++                  ((UDItype) in.fraction.ll) << F_D_BITOFF);
++}
++#endif /* L_sf_to_df */
++
++#if defined(L_sf_to_tf) && defined(TMODES)
++TFtype
++sf_to_tf (SFtype arg_a)
++{
++  fp_number_type in;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &in);
++
++  return __make_tp (in.class, in.sign, in.normal_exp,
++                  ((UTItype) in.fraction.ll) << F_T_BITOFF);
++}
++#endif /* L_sf_to_df */
++
++#endif /* ! FLOAT_ONLY */
++#endif /* FLOAT */
++
++#ifndef FLOAT
++
++extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype);
++
++#if defined(L_make_df)
++DFtype
++__make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac)
++{
++  fp_number_type in;
++
++  in.class = class;
++  in.sign = sign;
++  in.normal_exp = exp;
++  in.fraction.ll = frac;
++  return pack_d (&in);
++}
++#endif /* L_make_df */
++
++#if defined(L_df_to_sf)
++SFtype
++df_to_sf (DFtype arg_a)
++{
++  fp_number_type in;
++  USItype sffrac;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &in);
++
++  sffrac = in.fraction.ll >> F_D_BITOFF;
++
++  /* We set the lowest guard bit in SFFRAC if we discarded any non
++     zero bits.  */
++  if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0)
++    sffrac |= 1;
++
++  return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
++}
++#endif /* L_df_to_sf */
++
++#if defined(L_df_to_tf) && defined(TMODES) \
++    && !defined(FLOAT) && !defined(TFLOAT)
++TFtype
++df_to_tf (DFtype arg_a)
++{
++  fp_number_type in;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &in);
++
++  return __make_tp (in.class, in.sign, in.normal_exp,
++                  ((UTItype) in.fraction.ll) << D_T_BITOFF);
++}
++#endif /* L_sf_to_df */
++
++#ifdef TFLOAT
++#if defined(L_make_tf)
++TFtype
++__make_tp(fp_class_type class,
++           unsigned int sign,
++           int exp, 
++           UTItype frac)
++{
++  fp_number_type in;
++
++  in.class = class;
++  in.sign = sign;
++  in.normal_exp = exp;
++  in.fraction.ll = frac;
++  return pack_d (&in);
++}
++#endif /* L_make_tf */
++
++#if defined(L_tf_to_df)
++DFtype
++tf_to_df (TFtype arg_a)
++{
++  fp_number_type in;
++  UDItype sffrac;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &in);
++
++  sffrac = in.fraction.ll >> D_T_BITOFF;
++
++  /* We set the lowest guard bit in SFFRAC if we discarded any non
++     zero bits.  */
++  if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0)
++    sffrac |= 1;
++
++  return __make_dp (in.class, in.sign, in.normal_exp, sffrac);
++}
++#endif /* L_tf_to_df */
++
++#if defined(L_tf_to_sf)
++SFtype
++tf_to_sf (TFtype arg_a)
++{
++  fp_number_type in;
++  USItype sffrac;
++  FLO_union_type au;
++
++  au.value = arg_a;
++  unpack_d (&au, &in);
++
++  sffrac = in.fraction.ll >> F_T_BITOFF;
++
++  /* We set the lowest guard bit in SFFRAC if we discarded any non
++     zero bits.  */
++  if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0)
++    sffrac |= 1;
++
++  return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
++}
++#endif /* L_tf_to_sf */
++#endif /* TFLOAT */
++
++#endif /* ! FLOAT */
++#endif /* !EXTENDED_FLOAT_STUBS */
+--- gcc-3.4.3/gcc/config/nios2/nios2-protos.h
++++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-protos.h
+@@ -0,0 +1,70 @@
++/* Subroutines for assembler code output for Altera NIOS 2G NIOS2 version.
++   Copyright (C) 2003 Altera 
++   Contributed by Jonah Graham (jgraham@altera.com).
++
++This file is part of GNU CC.
++
++GNU CC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 2, or (at your option)
++any later version.
++
++GNU CC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GNU CC; see the file COPYING.  If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA.  */
++
++extern void dump_frame_size (FILE *);
++extern HOST_WIDE_INT compute_frame_size (void);
++extern int nios2_initial_elimination_offset (int, int);
++extern void override_options (void);
++extern void optimization_options (int, int);
++extern int nios2_can_use_return_insn (void);
++extern void expand_prologue (void);
++extern void expand_epilogue (bool);
++extern void function_profiler (FILE *, int);
++
++
++#ifdef RTX_CODE
++extern int nios2_legitimate_address (rtx, enum machine_mode, int);
++extern void nios2_print_operand (FILE *, rtx, int);
++extern void nios2_print_operand_address (FILE *, rtx);
++
++extern int nios2_emit_move_sequence (rtx *, enum machine_mode);
++extern int nios2_emit_expensive_div (rtx *, enum machine_mode);
++
++extern void gen_int_relational (enum rtx_code, rtx, rtx, rtx, rtx);
++extern void gen_conditional_move (rtx *, enum machine_mode);
++extern const char *asm_output_opcode (FILE *, const char *);
++
++/* predicates */
++extern int arith_operand (rtx, enum machine_mode);
++extern int uns_arith_operand (rtx, enum machine_mode);
++extern int logical_operand (rtx, enum machine_mode);
++extern int shift_operand (rtx, enum machine_mode);
++extern int reg_or_0_operand (rtx, enum machine_mode);
++extern int equality_op (rtx, enum machine_mode);
++extern int custom_insn_opcode (rtx, enum machine_mode);
++extern int rdwrctl_operand (rtx, enum machine_mode);
++
++# ifdef HAVE_MACHINE_MODES
++#  if defined TREE_CODE
++extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
++extern rtx function_arg (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
++extern int function_arg_partial_nregs (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
++extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
++extern int nios2_setup_incoming_varargs (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
++
++#  endif /* TREE_CODE */
++# endif       /* HAVE_MACHINE_MODES */
++#endif
++
++#ifdef TREE_CODE
++extern int nios2_return_in_memory (tree);
++
++#endif /* TREE_CODE */
+--- gcc-3.4.3/gcc/config/nios2/nios2.c
++++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.c
+@@ -0,0 +1,2853 @@
++/* Subroutines for assembler code output for Altera NIOS 2G NIOS2 version.
++   Copyright (C) 2003 Altera
++   Contributed by Jonah Graham (jgraham@altera.com).
++
++This file is part of GNU CC.
++
++GNU CC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 2, or (at your option)
++any later version.
++
++GNU CC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GNU CC; see the file COPYING.  If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA.  */
++
++
++#include <stdio.h>
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "rtl.h"
++#include "tree.h"
++#include "tm_p.h"
++#include "regs.h"
++#include "hard-reg-set.h"
++#include "real.h"
++#include "insn-config.h"
++#include "conditions.h"
++#include "output.h"
++#include "insn-attr.h"
++#include "flags.h"
++#include "recog.h"
++#include "expr.h"
++#include "toplev.h"
++#include "basic-block.h"
++#include "function.h"
++#include "ggc.h"
++#include "reload.h"
++#include "debug.h"
++#include "optabs.h"
++#include "target.h"
++#include "target-def.h"
++
++/* local prototypes */
++static bool nios2_rtx_costs (rtx, int, int, int *);
++
++static void nios2_asm_function_prologue (FILE *, HOST_WIDE_INT);
++static int nios2_use_dfa_pipeline_interface (void);
++static int nios2_issue_rate (void);
++static struct machine_function *nios2_init_machine_status (void);
++static bool nios2_in_small_data_p (tree);
++static rtx save_reg (int, HOST_WIDE_INT, rtx);
++static rtx restore_reg (int, HOST_WIDE_INT);
++static unsigned int nios2_section_type_flags (tree, const char *, int);
++static void nios2_init_builtins (void);
++static rtx nios2_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
++static bool nios2_function_ok_for_sibcall (tree, tree);
++static void nios2_encode_section_info (tree, rtx, int);
++
++/* Initialize the GCC target structure.  */
++#undef TARGET_ASM_FUNCTION_PROLOGUE
++#define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue
++
++#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
++#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE \
++ nios2_use_dfa_pipeline_interface
++#undef TARGET_SCHED_ISSUE_RATE
++#define TARGET_SCHED_ISSUE_RATE nios2_issue_rate
++#undef TARGET_IN_SMALL_DATA_P
++#define TARGET_IN_SMALL_DATA_P nios2_in_small_data_p
++#undef  TARGET_ENCODE_SECTION_INFO
++#define TARGET_ENCODE_SECTION_INFO nios2_encode_section_info
++#undef  TARGET_SECTION_TYPE_FLAGS
++#define TARGET_SECTION_TYPE_FLAGS  nios2_section_type_flags
++
++#undef TARGET_INIT_BUILTINS
++#define TARGET_INIT_BUILTINS nios2_init_builtins
++#undef TARGET_EXPAND_BUILTIN
++#define TARGET_EXPAND_BUILTIN nios2_expand_builtin
++
++#undef TARGET_FUNCTION_OK_FOR_SIBCALL
++#define TARGET_FUNCTION_OK_FOR_SIBCALL nios2_function_ok_for_sibcall
++
++#undef TARGET_RTX_COSTS
++#define TARGET_RTX_COSTS nios2_rtx_costs
++
++
++struct gcc_target targetm = TARGET_INITIALIZER;
++\f
++
++
++/* Threshold for data being put into the small data/bss area, instead
++   of the normal data area (references to the small data/bss area take
++   1 instruction, and use the global pointer, references to the normal
++   data area takes 2 instructions).  */
++unsigned HOST_WIDE_INT nios2_section_threshold = NIOS2_DEFAULT_GVALUE;
++
++
++/* Structure to be filled in by compute_frame_size with register
++   save masks, and offsets for the current function.  */
++
++struct nios2_frame_info
++GTY (())
++{
++  long total_size;            /* # bytes that the entire frame takes up */
++  long var_size;              /* # bytes that variables take up */
++  long args_size;             /* # bytes that outgoing arguments take up */
++  int save_reg_size;          /* # bytes needed to store gp regs */
++  int save_reg_rounded;               /* # bytes needed to store gp regs */
++  long save_regs_offset;      /* offset from new sp to store gp registers */
++  int initialized;            /* != 0 if frame size already calculated */
++  int num_regs;                       /* number of gp registers saved */
++};
++
++struct machine_function
++GTY (())
++{
++
++  /* Current frame information, calculated by compute_frame_size.  */
++  struct nios2_frame_info frame;
++};
++\f
++
++/***************************************
++ * Section encodings
++ ***************************************/
++\f
++
++
++
++
++/***************************************
++ * Stack Layout and Calling Conventions
++ ***************************************/
++
++
++#define TOO_BIG_OFFSET(X) ((X) > ((1 << 15) - 1))
++#define TEMP_REG_NUM 8
++
++static void
++nios2_asm_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
++{
++  if (flag_verbose_asm || flag_debug_asm)
++    {
++      compute_frame_size ();
++      dump_frame_size (file);
++    }
++}
++
++static rtx
++save_reg (int regno, HOST_WIDE_INT offset, rtx cfa_store_reg)
++{
++  rtx insn, stack_slot;
++
++  stack_slot = gen_rtx_PLUS (SImode,
++                           cfa_store_reg,
++                           GEN_INT (offset));
++
++  insn = emit_insn (gen_rtx_SET (SImode,
++                               gen_rtx_MEM (SImode, stack_slot),
++                               gen_rtx_REG (SImode, regno)));
++
++  RTX_FRAME_RELATED_P (insn) = 1;
++
++  return insn;
++}
++
++static rtx
++restore_reg (int regno, HOST_WIDE_INT offset)
++{
++  rtx insn, stack_slot;
++
++  if (TOO_BIG_OFFSET (offset))
++    {
++      stack_slot = gen_rtx_REG (SImode, TEMP_REG_NUM);
++      insn = emit_insn (gen_rtx_SET (SImode,
++                                   stack_slot,
++                                   GEN_INT (offset)));
++
++      insn = emit_insn (gen_rtx_SET (SImode,
++                                   stack_slot,
++                                     gen_rtx_PLUS (SImode,
++                                                 stack_slot,
++                                                 stack_pointer_rtx)));
++    }
++  else
++    {
++      stack_slot = gen_rtx_PLUS (SImode,
++                               stack_pointer_rtx,
++                               GEN_INT (offset));
++    }
++
++  stack_slot = gen_rtx_MEM (SImode, stack_slot);
++
++  insn = emit_move_insn (gen_rtx_REG (SImode, regno), stack_slot);
++
++  return insn;
++}
++
++
++/* There are two possible paths for prologue expansion,
++- the first is if the total frame size is < 2^15-1. In that
++case all the immediates will fit into the 16-bit immediate
++fields.
++- the second is when the frame size is too big, in that
++case an additional temporary register is used, first 
++as a cfa_temp to offset the sp, second as the cfa_store
++register.
++
++See the comment above dwarf2out_frame_debug_expr in 
++dwarf2out.c for more explanation of the "rules."
++
++
++Case 1:
++Rule #  Example Insn                       Effect
++2     addi    sp, sp, -total_frame_size  cfa.reg=sp, cfa.offset=total_frame_size
++                                           cfa_store.reg=sp, cfa_store.offset=total_frame_size
++12    stw     ra, offset(sp)             
++12    stw     r16, offset(sp)
++1     mov     fp, sp
++  
++Case 2: 
++Rule #  Example Insn                       Effect
++6     movi    r8, total_frame_size       cfa_temp.reg=r8, cfa_temp.offset=total_frame_size
++2     sub     sp, sp, r8                 cfa.reg=sp, cfa.offset=total_frame_size
++                                           cfa_store.reg=sp, cfa_store.offset=total_frame_size
++5     add     r8, r8, sp                 cfa_store.reg=r8, cfa_store.offset=0
++12    stw     ra, offset(r8)
++12    stw     r16, offset(r8)
++1     mov     fp, sp
++
++*/
++
++void
++expand_prologue ()
++{
++  int i;
++  HOST_WIDE_INT total_frame_size;
++  int cfa_store_offset;
++  rtx insn;
++  rtx cfa_store_reg = 0;
++
++  total_frame_size = compute_frame_size ();
++
++  if (total_frame_size)
++    {
++
++      if (TOO_BIG_OFFSET (total_frame_size)) 
++      {
++          /* cfa_temp and cfa_store_reg are the same register,
++             cfa_store_reg overwrites cfa_temp */
++          cfa_store_reg = gen_rtx_REG (SImode, TEMP_REG_NUM);
++          insn = emit_insn (gen_rtx_SET (SImode,
++                                         cfa_store_reg,
++                                         GEN_INT (total_frame_size)));
++
++          RTX_FRAME_RELATED_P (insn) = 1;
++
++
++          insn = gen_rtx_SET (SImode,
++                              stack_pointer_rtx,
++                              gen_rtx_MINUS (SImode,
++                                             stack_pointer_rtx,
++                                             cfa_store_reg));
++
++          insn = emit_insn (insn);
++          RTX_FRAME_RELATED_P (insn) = 1;
++
++
++          /* if there are no registers to save, I don't need to
++             create a cfa_store */
++          if (cfun->machine->frame.save_reg_size) 
++            {
++              insn = gen_rtx_SET (SImode,
++                                  cfa_store_reg,
++                                  gen_rtx_PLUS (SImode,
++                                                cfa_store_reg,
++                                                stack_pointer_rtx));
++
++              insn = emit_insn (insn);
++              RTX_FRAME_RELATED_P (insn) = 1;
++            }
++
++          cfa_store_offset 
++            = total_frame_size 
++              - (cfun->machine->frame.save_regs_offset
++                 + cfun->machine->frame.save_reg_rounded);
++      }
++      else
++      {
++          insn = gen_rtx_SET (SImode,
++                              stack_pointer_rtx,
++                              gen_rtx_PLUS (SImode,
++                                            stack_pointer_rtx,
++                                            GEN_INT (-total_frame_size)));
++          insn = emit_insn (insn);
++          RTX_FRAME_RELATED_P (insn) = 1;
++
++          cfa_store_reg = stack_pointer_rtx;
++          cfa_store_offset 
++            = cfun->machine->frame.save_regs_offset
++              + cfun->machine->frame.save_reg_rounded;
++      }
++    }
++
++  if (MUST_SAVE_REGISTER (RA_REGNO))
++    {
++      cfa_store_offset -= 4;
++      save_reg (RA_REGNO, cfa_store_offset, cfa_store_reg);
++    }
++  if (MUST_SAVE_REGISTER (FP_REGNO))
++    {
++      cfa_store_offset -= 4;
++      save_reg (FP_REGNO, cfa_store_offset, cfa_store_reg);
++    }
++
++  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
++    {
++      if (MUST_SAVE_REGISTER (i) && i != FP_REGNO && i != RA_REGNO)
++      {
++        cfa_store_offset -= 4;
++        save_reg (i, cfa_store_offset, cfa_store_reg);
++      }
++    }
++
++  if (frame_pointer_needed)
++    {
++      insn = emit_insn (gen_rtx_SET (SImode,
++                                   gen_rtx_REG (SImode, FP_REGNO),
++                                   gen_rtx_REG (SImode, SP_REGNO)));
++
++      RTX_FRAME_RELATED_P (insn) = 1;
++    }
++
++  /* If we are profiling, make sure no instructions are scheduled before
++     the call to mcount.  */
++  if (current_function_profile)
++    emit_insn (gen_blockage ());
++}
++
++void
++expand_epilogue (bool sibcall_p)
++{
++  rtx insn;
++  int i;
++  HOST_WIDE_INT total_frame_size;
++  int register_store_offset;
++
++  total_frame_size = compute_frame_size ();
++
++  if (!sibcall_p && nios2_can_use_return_insn ())
++    {
++      insn = emit_jump_insn (gen_return ());
++      return;
++    }
++
++  emit_insn (gen_blockage ());
++
++  register_store_offset =
++    cfun->machine->frame.save_regs_offset +
++    cfun->machine->frame.save_reg_rounded;
++
++  if (MUST_SAVE_REGISTER (RA_REGNO))
++    {
++      register_store_offset -= 4;
++      restore_reg (RA_REGNO, register_store_offset);
++    }
++
++  if (MUST_SAVE_REGISTER (FP_REGNO))
++    {
++      register_store_offset -= 4;
++      restore_reg (FP_REGNO, register_store_offset);
++    }
++
++  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
++    {
++      if (MUST_SAVE_REGISTER (i) && i != FP_REGNO && i != RA_REGNO)
++      {
++        register_store_offset -= 4;
++        restore_reg (i, register_store_offset);
++      }
++    }
++
++  if (total_frame_size)
++    {
++      rtx sp_adjust;
++
++      if (TOO_BIG_OFFSET (total_frame_size))
++        {
++        sp_adjust = gen_rtx_REG (SImode, TEMP_REG_NUM);
++        insn = emit_insn (gen_rtx_SET (SImode,
++                                       sp_adjust,
++                                       GEN_INT (total_frame_size)));
++
++              }
++      else
++        {
++        sp_adjust = GEN_INT (total_frame_size);
++      }
++
++      insn = gen_rtx_SET (SImode,
++                        stack_pointer_rtx,
++                        gen_rtx_PLUS (SImode,
++                                      stack_pointer_rtx,
++                                      sp_adjust));
++      insn = emit_insn (insn);
++    }
++
++
++  if (!sibcall_p)
++    {
++      insn = emit_jump_insn (gen_return_from_epilogue (gen_rtx (REG, Pmode,
++                                                              RA_REGNO)));
++    }
++}
++
++
++bool
++nios2_function_ok_for_sibcall (tree a ATTRIBUTE_UNUSED, tree b ATTRIBUTE_UNUSED)
++{
++  return true;
++}
++
++
++
++\f
++
++/* ----------------------- *
++ * Profiling
++ * ----------------------- */
++
++void
++function_profiler (FILE *file, int labelno)
++{
++  fprintf (file, "\t%s mcount begin, label: .LP%d\n", 
++           ASM_COMMENT_START, labelno);
++  fprintf (file, "\tnextpc\tr8\n");
++  fprintf (file, "\tmov\tr9, ra\n");
++  fprintf (file, "\tmovhi\tr10, %%hiadj(.LP%d)\n", labelno);
++  fprintf (file, "\taddi\tr10, r10, %%lo(.LP%d)\n", labelno);
++  fprintf (file, "\tcall\tmcount\n");
++  fprintf (file, "\tmov\tra, r9\n");
++  fprintf (file, "\t%s mcount end\n", ASM_COMMENT_START);
++}
++
++
++/***************************************
++ * Stack Layout
++ ***************************************/
++
++
++void
++dump_frame_size (FILE *file)
++{
++  fprintf (file, "\t%s Current Frame Info\n", ASM_COMMENT_START);
++
++  fprintf (file, "\t%s total_size = %ld\n", ASM_COMMENT_START,
++         cfun->machine->frame.total_size);
++  fprintf (file, "\t%s var_size = %ld\n", ASM_COMMENT_START,
++         cfun->machine->frame.var_size);
++  fprintf (file, "\t%s args_size = %ld\n", ASM_COMMENT_START,
++         cfun->machine->frame.args_size);
++  fprintf (file, "\t%s save_reg_size = %d\n", ASM_COMMENT_START,
++         cfun->machine->frame.save_reg_size);
++  fprintf (file, "\t%s save_reg_rounded = %d\n", ASM_COMMENT_START,
++         cfun->machine->frame.save_reg_rounded);
++  fprintf (file, "\t%s initialized = %d\n", ASM_COMMENT_START,
++         cfun->machine->frame.initialized);
++  fprintf (file, "\t%s num_regs = %d\n", ASM_COMMENT_START,
++         cfun->machine->frame.num_regs);
++  fprintf (file, "\t%s save_regs_offset = %ld\n", ASM_COMMENT_START,
++         cfun->machine->frame.save_regs_offset);
++  fprintf (file, "\t%s current_function_is_leaf = %d\n", ASM_COMMENT_START,
++         current_function_is_leaf);
++  fprintf (file, "\t%s frame_pointer_needed = %d\n", ASM_COMMENT_START,
++         frame_pointer_needed);
++  fprintf (file, "\t%s pretend_args_size = %d\n", ASM_COMMENT_START,
++         current_function_pretend_args_size);
++
++}
++
++
++/* Return the bytes needed to compute the frame pointer from the current
++   stack pointer.
++*/
++
++HOST_WIDE_INT
++compute_frame_size ()
++{
++  unsigned int regno;
++  HOST_WIDE_INT var_size;     /* # of var. bytes allocated */
++  HOST_WIDE_INT total_size;   /* # bytes that the entire frame takes up */
++  HOST_WIDE_INT save_reg_size;        /* # bytes needed to store callee save regs */
++  HOST_WIDE_INT save_reg_rounded;     
++    /* # bytes needed to store callee save regs (rounded) */
++  HOST_WIDE_INT out_args_size;        /* # bytes needed for outgoing args */
++
++  save_reg_size = 0;
++  var_size = STACK_ALIGN (get_frame_size ());
++  out_args_size = STACK_ALIGN (current_function_outgoing_args_size);
++
++  total_size = var_size + out_args_size;
++
++  /* Calculate space needed for gp registers.  */
++  for (regno = 0; regno <= FIRST_PSEUDO_REGISTER; regno++)
++    {
++      if (MUST_SAVE_REGISTER (regno))
++      {
++        save_reg_size += 4;
++      }
++    }
++
++  save_reg_rounded = STACK_ALIGN (save_reg_size);
++  total_size += save_reg_rounded;
++
++  total_size += STACK_ALIGN (current_function_pretend_args_size);
++
++  /* Save other computed information.  */
++  cfun->machine->frame.total_size = total_size;
++  cfun->machine->frame.var_size = var_size;
++  cfun->machine->frame.args_size = current_function_outgoing_args_size;
++  cfun->machine->frame.save_reg_size = save_reg_size;
++  cfun->machine->frame.save_reg_rounded = save_reg_rounded;
++  cfun->machine->frame.initialized = reload_completed;
++  cfun->machine->frame.num_regs = save_reg_size / UNITS_PER_WORD;
++
++  cfun->machine->frame.save_regs_offset
++    = save_reg_rounded ? current_function_outgoing_args_size + var_size : 0;
++
++  return total_size;
++}
++
++
++int
++nios2_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED)
++{
++  int offset;
++
++  /* Set OFFSET to the offset from the stack pointer.  */
++  switch (from)
++    {
++    case FRAME_POINTER_REGNUM:
++      offset = 0;
++      break;
++
++    case ARG_POINTER_REGNUM:
++      compute_frame_size ();
++      offset = cfun->machine->frame.total_size;
++      offset -= current_function_pretend_args_size;
++      break;
++
++    case RETURN_ADDRESS_POINTER_REGNUM:
++      compute_frame_size ();
++      /* since the return address is always the first of the
++         saved registers, return the offset to the beginning
++         of the saved registers block */
++      offset = cfun->machine->frame.save_regs_offset;
++      break;
++
++    default:
++      abort ();
++    }
++
++  return offset;
++}
++
++/* Return nonzero if this function is known to have a null epilogue.
++   This allows the optimizer to omit jumps to jumps if no stack
++   was created.  */
++int
++nios2_can_use_return_insn ()
++{
++  if (!reload_completed)
++    return 0;
++
++  if (regs_ever_live[RA_REGNO] || current_function_profile)
++    return 0;
++
++  if (cfun->machine->frame.initialized)
++    return cfun->machine->frame.total_size == 0;
++
++  return compute_frame_size () == 0;
++}
++
++
++
++\f
++
++/***************************************
++ *
++ ***************************************/
++
++const char *nios2_sys_nosys_string;    /* for -msys=nosys */
++const char *nios2_sys_lib_string;    /* for -msys-lib= */
++const char *nios2_sys_crt0_string;    /* for -msys-crt0= */
++
++void
++override_options ()
++{
++  /* Function to allocate machine-dependent function status.  */
++  init_machine_status = &nios2_init_machine_status;
++
++  nios2_section_threshold 
++    = g_switch_set ? g_switch_value : NIOS2_DEFAULT_GVALUE;
++
++  if (nios2_sys_nosys_string && *nios2_sys_nosys_string)
++    {
++      error ("invalid option '-msys=nosys%s'", nios2_sys_nosys_string);
++    }
++
++  /* If we don't have mul, we don't have mulx either! */
++  if (!TARGET_HAS_MUL && TARGET_HAS_MULX) 
++    {
++      target_flags &= ~HAS_MULX_FLAG;
++    }
++
++}
++
++void
++optimization_options (int level, int size)
++{
++  if (level || size)
++    {
++      target_flags |= INLINE_MEMCPY_FLAG;
++    }
++
++  if (level >= 3 && !size)
++    {
++      target_flags |= FAST_SW_DIV_FLAG;
++    }
++}
++
++/* Allocate a chunk of memory for per-function machine-dependent data.  */
++static struct machine_function *
++nios2_init_machine_status ()
++{
++  return ((struct machine_function *)
++        ggc_alloc_cleared (sizeof (struct machine_function)));
++}
++
++\f
++
++/*****************
++ * Describing Relative Costs of Operations
++ *****************/
++
++/* 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
++nios2_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total)
++{
++  switch (code)
++    {
++      case CONST_INT:
++      if (INTVAL (x) == 0)
++        {
++          *total = COSTS_N_INSNS (0);
++          return true;
++        }
++      else if (SMALL_INT (INTVAL (x))
++              || SMALL_INT_UNSIGNED (INTVAL (x))
++              || UPPER16_INT (INTVAL (x)))
++        {
++          *total = COSTS_N_INSNS (2);
++          return true;
++        }
++      else
++        {
++          *total = COSTS_N_INSNS (4);
++          return true;
++        }
++
++      case LABEL_REF:
++      case SYMBOL_REF:
++      /* ??? gp relative stuff will fit in here */
++      /* fall through */
++      case CONST:
++      case CONST_DOUBLE:
++      {
++        *total = COSTS_N_INSNS (4);
++        return true;
++      }
++
++      case MULT:
++      {
++        *total = COSTS_N_INSNS (1);
++        return false;
++      }
++      case SIGN_EXTEND:
++      {
++        *total = COSTS_N_INSNS (3);
++        return false;
++      }
++      case ZERO_EXTEND:
++      {
++        *total = COSTS_N_INSNS (1);
++        return false;
++      }
++
++    default:
++      return false;
++    }
++}
++
++
++/***************************************
++ * INSTRUCTION SUPPORT
++ *
++ * These functions are used within the Machine Description to
++ * handle common or complicated output and expansions from
++ * instructions.
++ ***************************************/
++
++int
++nios2_emit_move_sequence (rtx *operands, enum machine_mode mode)
++{
++  rtx to = operands[0];
++  rtx from = operands[1];
++
++  if (!register_operand (to, mode) && !reg_or_0_operand (from, mode))
++    {
++      if (no_new_pseudos)
++      internal_error ("Trying to force_reg no_new_pseudos == 1");
++      from = copy_to_mode_reg (mode, from);
++    }
++
++  operands[0] = to;
++  operands[1] = from;
++  return 0;
++}
++
++/* Divide Support */
++
++/*
++  If -O3 is used, we want to output a table lookup for
++  divides between small numbers (both num and den >= 0
++  and < 0x10). The overhead of this method in the worse
++  case is 40 bytes in the text section (10 insns) and
++  256 bytes in the data section. Additional divides do
++  not incur additional penalties in the data section.
++
++  Code speed is improved for small divides by about 5x
++  when using this method in the worse case (~9 cycles
++  vs ~45). And in the worse case divides not within the
++  table are penalized by about 10% (~5 cycles vs ~45).
++  However in the typical case the penalty is not as bad
++  because doing the long divide in only 45 cycles is
++  quite optimistic.
++
++  ??? It would be nice to have some benchmarks other
++  than Dhrystone to back this up.
++
++  This bit of expansion is to create this instruction
++  sequence as rtl.
++      or      $8, $4, $5
++      slli    $9, $4, 4
++      cmpgeui $3, $8, 16
++      beq     $3, $0, .L3
++      or      $10, $9, $5
++      add     $12, $11, divide_table
++      ldbu    $2, 0($12)
++      br      .L1
++.L3:
++      call    slow_div
++.L1:
++#     continue here with result in $2
++
++  ??? Ideally I would like the emit libcall block to contain
++  all of this code, but I don't know how to do that. What it
++  means is that if the divide can be eliminated, it may not
++  completely disappear.
++
++  ??? The __divsi3_table label should ideally be moved out
++  of this block and into a global. If it is placed into the
++  sdata section we can save even more cycles by doing things
++  gp relative.
++*/
++int
++nios2_emit_expensive_div (rtx *operands, enum machine_mode mode)
++{
++  rtx or_result, shift_left_result;
++  rtx lookup_value;
++  rtx lab1, lab3;
++  rtx insns;
++  rtx libfunc;
++  rtx final_result;
++  rtx tmp;
++
++  /* it may look a little generic, but only SImode
++     is supported for now */
++  if (mode != SImode)
++    abort ();
++
++  libfunc = sdiv_optab->handlers[(int) SImode].libfunc;
++
++
++
++  lab1 = gen_label_rtx ();
++  lab3 = gen_label_rtx ();
++
++  or_result = expand_simple_binop (SImode, IOR,
++                                 operands[1], operands[2],
++                                 0, 0, OPTAB_LIB_WIDEN);
++
++  emit_cmp_and_jump_insns (or_result, GEN_INT (15), GTU, 0,
++                         GET_MODE (or_result), 0, lab3);
++  JUMP_LABEL (get_last_insn ()) = lab3;
++
++  shift_left_result = expand_simple_binop (SImode, ASHIFT,
++                                         operands[1], GEN_INT (4),
++                                         0, 0, OPTAB_LIB_WIDEN);
++
++  lookup_value = expand_simple_binop (SImode, IOR,
++                                    shift_left_result, operands[2],
++                                    0, 0, OPTAB_LIB_WIDEN);
++
++  convert_move (operands[0],
++              gen_rtx (MEM, QImode,
++                       gen_rtx (PLUS, SImode,
++                                lookup_value,
++                                gen_rtx_SYMBOL_REF (SImode, "__divsi3_table"))),
++              1);
++
++
++  tmp = emit_jump_insn (gen_jump (lab1));
++  JUMP_LABEL (tmp) = lab1;
++  emit_barrier ();
++
++  emit_label (lab3);
++  LABEL_NUSES (lab3) = 1;
++
++  start_sequence ();
++  final_result = emit_library_call_value (libfunc, NULL_RTX,
++                                        LCT_CONST, SImode, 2,
++                                        operands[1], SImode,
++                                        operands[2], SImode);
++
++
++  insns = get_insns ();
++  end_sequence ();
++  emit_libcall_block (insns, operands[0], final_result,
++                    gen_rtx (DIV, SImode, operands[1], operands[2]));
++
++  emit_label (lab1);
++  LABEL_NUSES (lab1) = 1;
++  return 1;
++}
++
++/* Branches/Compares */
++
++/* the way of handling branches/compares
++   in gcc is heavily borrowed from MIPS */
++
++enum internal_test
++{
++  ITEST_EQ,
++  ITEST_NE,
++  ITEST_GT,
++  ITEST_GE,
++  ITEST_LT,
++  ITEST_LE,
++  ITEST_GTU,
++  ITEST_GEU,
++  ITEST_LTU,
++  ITEST_LEU,
++  ITEST_MAX
++};
++
++static enum internal_test map_test_to_internal_test (enum rtx_code);
++
++/* Cached operands, and operator to compare for use in set/branch/trap
++   on condition codes.  */
++rtx branch_cmp[2];
++enum cmp_type branch_type;
++
++/* Make normal rtx_code into something we can index from an array */
++
++static enum internal_test
++map_test_to_internal_test (enum rtx_code test_code)
++{
++  enum internal_test test = ITEST_MAX;
++
++  switch (test_code)
++    {
++    case EQ:
++      test = ITEST_EQ;
++      break;
++    case NE:
++      test = ITEST_NE;
++      break;
++    case GT:
++      test = ITEST_GT;
++      break;
++    case GE:
++      test = ITEST_GE;
++      break;
++    case LT:
++      test = ITEST_LT;
++      break;
++    case LE:
++      test = ITEST_LE;
++      break;
++    case GTU:
++      test = ITEST_GTU;
++      break;
++    case GEU:
++      test = ITEST_GEU;
++      break;
++    case LTU:
++      test = ITEST_LTU;
++      break;
++    case LEU:
++      test = ITEST_LEU;
++      break;
++    default:
++      break;
++    }
++
++  return test;
++}
++
++/* Generate the code to compare (and possibly branch) two integer values
++   TEST_CODE is the comparison code we are trying to emulate 
++     (or implement directly)
++   RESULT is where to store the result of the comparison, 
++     or null to emit a branch
++   CMP0 CMP1 are the two comparison operands
++   DESTINATION is the destination of the branch, or null to only compare
++   */
++
++void
++gen_int_relational (enum rtx_code test_code, /* relational test (EQ, etc) */
++                  rtx result,         /* result to store comp. or 0 if branch */
++                  rtx cmp0,           /* first operand to compare */
++                  rtx cmp1,           /* second operand to compare */
++                  rtx destination)    /* destination of the branch, or 0 if compare */
++{
++  struct cmp_info
++  {
++    /* for register (or 0) compares */
++    enum rtx_code test_code_reg;      /* code to use in instruction (LT vs. LTU) */
++    int reverse_regs;         /* reverse registers in test */
++
++    /* for immediate compares */
++    enum rtx_code test_code_const;    
++         /* code to use in instruction (LT vs. LTU) */
++    int const_low;            /* low bound of constant we can accept */
++    int const_high;           /* high bound of constant we can accept */
++    int const_add;            /* constant to add */
++
++    /* generic info */
++    int unsignedp;            /* != 0 for unsigned comparisons.  */
++  };
++
++  static const struct cmp_info info[(int) ITEST_MAX] = {
++
++    {EQ, 0, EQ, -32768, 32767, 0, 0}, /* EQ  */
++    {NE, 0, NE, -32768, 32767, 0, 0}, /* NE  */
++
++    {LT, 1, GE, -32769, 32766, 1, 0}, /* GT  */
++    {GE, 0, GE, -32768, 32767, 0, 0}, /* GE  */
++    {LT, 0, LT, -32768, 32767, 0, 0}, /* LT  */
++    {GE, 1, LT, -32769, 32766, 1, 0}, /* LE  */
++
++    {LTU, 1, GEU, 0, 65534, 1, 0}, /* GTU */
++    {GEU, 0, GEU, 0, 65535, 0, 0}, /* GEU */
++    {LTU, 0, LTU, 0, 65535, 0, 0}, /* LTU */
++    {GEU, 1, LTU, 0, 65534, 1, 0}, /* LEU */
++  };
++
++  enum internal_test test;
++  enum machine_mode mode;
++  const struct cmp_info *p_info;
++  int branch_p;
++
++
++
++
++  test = map_test_to_internal_test (test_code);
++  if (test == ITEST_MAX)
++    abort ();
++
++  p_info = &info[(int) test];
++
++  mode = GET_MODE (cmp0);
++  if (mode == VOIDmode)
++    mode = GET_MODE (cmp1);
++
++  branch_p = (destination != 0);
++
++  /* We can't, under any circumstances, have const_ints in cmp0
++     ??? Actually we could have const0 */
++  if (GET_CODE (cmp0) == CONST_INT)
++    cmp0 = force_reg (mode, cmp0);
++
++  /* if the comparison is against an int not in legal range
++     move it into a register */
++  if (GET_CODE (cmp1) == CONST_INT)
++    {
++      HOST_WIDE_INT value = INTVAL (cmp1);
++
++      if (value < p_info->const_low || value > p_info->const_high)
++      cmp1 = force_reg (mode, cmp1);
++    }
++
++  /* Comparison to constants, may involve adding 1 to change a GT into GE.
++     Comparison between two registers, may involve switching operands.  */
++  if (GET_CODE (cmp1) == CONST_INT)
++    {
++      if (p_info->const_add != 0)
++      {
++        HOST_WIDE_INT new = INTVAL (cmp1) + p_info->const_add;
++
++        /* If modification of cmp1 caused overflow,
++           we would get the wrong answer if we follow the usual path;
++           thus, x > 0xffffffffU would turn into x > 0U.  */
++        if ((p_info->unsignedp
++             ? (unsigned HOST_WIDE_INT) new >
++             (unsigned HOST_WIDE_INT) INTVAL (cmp1)
++             : new > INTVAL (cmp1)) != (p_info->const_add > 0))
++          {
++            /* ??? This case can never happen with the current numbers,
++               but I am paranoid and would rather an abort than
++               a bug I will never find */
++            abort ();
++          }
++        else
++          cmp1 = GEN_INT (new);
++      }
++    }
++
++  else if (p_info->reverse_regs)
++    {
++      rtx temp = cmp0;
++      cmp0 = cmp1;
++      cmp1 = temp;
++    }
++
++
++
++  if (branch_p)
++    {
++      if (register_operand (cmp0, mode) && register_operand (cmp1, mode))
++      {
++        rtx insn;
++        rtx cond = gen_rtx (p_info->test_code_reg, mode, cmp0, cmp1);
++        rtx label = gen_rtx_LABEL_REF (VOIDmode, destination);
++
++        insn = gen_rtx_SET (VOIDmode, pc_rtx,
++                            gen_rtx_IF_THEN_ELSE (VOIDmode,
++                                                  cond, label, pc_rtx));
++        emit_jump_insn (insn);
++      }
++      else
++      {
++        rtx cond, label;
++
++        result = gen_reg_rtx (mode);
++
++        emit_move_insn (result,
++                        gen_rtx (p_info->test_code_const, mode, cmp0,
++                                 cmp1));
++
++        cond = gen_rtx (NE, mode, result, const0_rtx);
++        label = gen_rtx_LABEL_REF (VOIDmode, destination);
++
++        emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
++                                     gen_rtx_IF_THEN_ELSE (VOIDmode,
++                                                           cond,
++                                                           label, pc_rtx)));
++      }
++    }
++  else
++    {
++      if (register_operand (cmp0, mode) && register_operand (cmp1, mode))
++      {
++        emit_move_insn (result,
++                        gen_rtx (p_info->test_code_reg, mode, cmp0, cmp1));
++      }
++      else
++      {
++        emit_move_insn (result,
++                        gen_rtx (p_info->test_code_const, mode, cmp0,
++                                 cmp1));
++      }
++    }
++
++}
++
++
++/* ??? For now conditional moves are only supported
++   when the mode of the operands being compared are
++   the same as the ones being moved */
++
++void
++gen_conditional_move (rtx *operands, enum machine_mode mode)
++{
++  rtx insn, cond;
++  rtx cmp_reg = gen_reg_rtx (mode);
++  enum rtx_code cmp_code = GET_CODE (operands[1]);
++  enum rtx_code move_code = EQ;
++
++  /* emit a comparison if it is not "simple".
++     Simple comparisons are X eq 0 and X ne 0 */
++  if ((cmp_code == EQ || cmp_code == NE) && branch_cmp[1] == const0_rtx)
++    {
++      cmp_reg = branch_cmp[0];
++      move_code = cmp_code;
++    }
++  else if ((cmp_code == EQ || cmp_code == NE) && branch_cmp[0] == const0_rtx)
++    {
++      cmp_reg = branch_cmp[1];
++      move_code = cmp_code == EQ ? NE : EQ;
++    }
++  else
++    gen_int_relational (cmp_code, cmp_reg, branch_cmp[0], branch_cmp[1],
++                      NULL_RTX);
++
++  cond = gen_rtx (move_code, VOIDmode, cmp_reg, CONST0_RTX (mode));
++  insn = gen_rtx_SET (mode, operands[0],
++                    gen_rtx_IF_THEN_ELSE (mode,
++                                          cond, operands[2], operands[3]));
++  emit_insn (insn);
++}
++
++/*******************
++ * Addressing Modes
++ *******************/
++
++int
++nios2_legitimate_address (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED, 
++                          int strict)
++{
++  int ret_val = 0;
++
++  switch (GET_CODE (operand))
++    {
++      /* direct.  */
++    case SYMBOL_REF:
++      if (SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (operand))
++        {
++          ret_val = 1;
++          break;
++      }
++      /* else, fall through */
++    case LABEL_REF:
++    case CONST_INT:
++    case CONST:
++    case CONST_DOUBLE:
++      /* ??? In here I need to add gp addressing */
++      ret_val = 0;
++
++      break;
++
++      /* Register indirect.  */
++    case REG:
++      ret_val = REG_OK_FOR_BASE_P2 (operand, strict);
++      break;
++
++      /* Register indirect with displacement */
++    case PLUS:
++      {
++      rtx op0 = XEXP (operand, 0);
++      rtx op1 = XEXP (operand, 1);
++
++      if (REG_P (op0) && REG_P (op1))
++        ret_val = 0;
++      else if (REG_P (op0) && CONSTANT_P (op1))
++        ret_val = REG_OK_FOR_BASE_P2 (op0, strict)
++          && SMALL_INT (INTVAL (op1));
++      else if (REG_P (op1) && CONSTANT_P (op0))
++        ret_val = REG_OK_FOR_BASE_P2 (op1, strict)
++          && SMALL_INT (INTVAL (op0));
++      else
++        ret_val = 0;
++      }
++      break;
++
++    default:
++      ret_val = 0;
++      break;
++    }
++
++  return ret_val;
++}
++
++/* Return true if EXP should be placed in the small data section.  */
++
++static bool
++nios2_in_small_data_p (tree exp)
++{
++  /* We want to merge strings, so we never consider them small data.  */
++  if (TREE_CODE (exp) == STRING_CST)
++    return false;
++
++  if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
++    {
++      const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
++      /* ??? these string names need moving into 
++         an array in some header file */
++      if (nios2_section_threshold > 0
++          && (strcmp (section, ".sbss") == 0
++            || strncmp (section, ".sbss.", 6) == 0
++            || strcmp (section, ".sdata") == 0
++            || strncmp (section, ".sdata.", 7) == 0))
++      return true;
++    }
++  else if (TREE_CODE (exp) == VAR_DECL)
++    {
++      HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
++
++      /* If this is an incomplete type with size 0, then we can't put it
++         in sdata because it might be too big when completed.  */
++      if (size > 0 && size <= nios2_section_threshold)
++      return true;
++    }
++
++  return false;
++}
++
++static void
++nios2_encode_section_info (tree decl, rtx rtl, int first)
++{
++
++  rtx symbol;
++  int flags;
++
++  default_encode_section_info (decl, rtl, first);
++  
++  /* Careful not to prod global register variables.  */
++  if (GET_CODE (rtl) != MEM)
++    return;
++  symbol = XEXP (rtl, 0);
++  if (GET_CODE (symbol) != SYMBOL_REF)
++    return;
++
++  flags = SYMBOL_REF_FLAGS (symbol);
++    
++  /* We don't want weak variables to be addressed with gp in case they end up with
++     value 0 which is not within 2^15 of $gp */
++  if (DECL_P (decl) && DECL_WEAK (decl))
++    flags |= SYMBOL_FLAG_WEAK_DECL;
++
++  SYMBOL_REF_FLAGS (symbol) = flags;
++}
++
++
++static unsigned int
++nios2_section_type_flags (tree decl, const char *name, int reloc)
++{
++  unsigned int flags;
++
++  flags = default_section_type_flags (decl, name, reloc);
++
++  /* ??? these string names need moving into an array in some header file */
++  if (strcmp (name, ".sbss") == 0
++      || strncmp (name, ".sbss.", 6) == 0
++      || strcmp (name, ".sdata") == 0
++      || strncmp (name, ".sdata.", 7) == 0)
++    flags |= SECTION_SMALL;
++
++  return flags;
++}
++
++
++
++
++/*****************************************
++ * Defining the Output Assembler Language
++ *****************************************/
++
++/* -------------- *
++ * Output of Data
++ * -------------- */
++
++
++/* -------------------------------- *
++ * Output of Assembler Instructions
++ * -------------------------------- */
++
++
++/* print the operand OP to file stream
++   FILE modified by LETTER. LETTER
++   can be one of:
++     i: print "i" if OP is an immediate, except 0
++     o: print "io" if OP is volatile
++
++     z: for const0_rtx print $0 instead of 0
++     H: for %hiadj
++     L: for %lo
++     U: for upper half of 32 bit value
++ */
++
++void
++nios2_print_operand (FILE *file, rtx op, int letter)
++{
++
++  switch (letter)
++    {
++    case 'i':
++      if (CONSTANT_P (op) && (op != const0_rtx))
++      fprintf (file, "i");
++      return;
++
++    case 'o':
++      if (GET_CODE (op) == MEM
++          && ((MEM_VOLATILE_P (op) && !TARGET_CACHE_VOLATILE)
++              || TARGET_BYPASS_CACHE))
++      fprintf (file, "io");
++      return;
++
++    default:
++      break;
++    }
++
++  if (comparison_operator (op, VOIDmode))
++    {
++      if (letter == 0)
++      {
++        fprintf (file, "%s", GET_RTX_NAME (GET_CODE (op)));
++        return;
++      }
++    }
++
++
++  switch (GET_CODE (op))
++    {
++    case REG:
++      if (letter == 0 || letter == 'z')
++      {
++        fprintf (file, "%s", reg_names[REGNO (op)]);
++        return;
++      }
++
++    case CONST_INT:
++      if (INTVAL (op) == 0 && letter == 'z')
++      {
++        fprintf (file, "zero");
++        return;
++      }
++      else if (letter == 'U')
++      {
++        HOST_WIDE_INT val = INTVAL (op);
++        rtx new_op;
++        val = (val / 65536) & 0xFFFF;
++        new_op = GEN_INT (val);
++        output_addr_const (file, new_op);
++        return;
++      }
++
++      /* else, fall through */
++    case CONST:
++    case LABEL_REF:
++    case SYMBOL_REF:
++    case CONST_DOUBLE:
++      if (letter == 0 || letter == 'z')
++      {
++        output_addr_const (file, op);
++        return;
++      }
++      else if (letter == 'H')
++      {
++        fprintf (file, "%%hiadj(");
++        output_addr_const (file, op);
++        fprintf (file, ")");
++        return;
++      }
++      else if (letter == 'L')
++      {
++        fprintf (file, "%%lo(");
++        output_addr_const (file, op);
++        fprintf (file, ")");
++        return;
++      }
++
++
++    case SUBREG:
++    case MEM:
++      if (letter == 0)
++      {
++        output_address (op);
++        return;
++      }
++
++    case CODE_LABEL:
++      if (letter == 0)
++      {
++        output_addr_const (file, op);
++        return;
++      }
++
++    default:
++      break;
++    }
++
++  fprintf (stderr, "Missing way to print (%c) ", letter);
++  debug_rtx (op);
++  abort ();
++}
++
++static int gprel_constant (rtx);
++
++static int
++gprel_constant (rtx op)
++{
++  if (GET_CODE (op) == SYMBOL_REF
++      && SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (op))
++    {
++      return 1;
++    }
++  else if (GET_CODE (op) == CONST
++           && GET_CODE (XEXP (op, 0)) == PLUS)
++    {
++      return gprel_constant (XEXP (XEXP (op, 0), 0));
++    }
++  else
++    {
++      return 0;
++    }
++}
++
++void
++nios2_print_operand_address (FILE *file, rtx op)
++{
++  switch (GET_CODE (op))
++    {
++    case CONST:
++    case CONST_INT:
++    case LABEL_REF:
++    case CONST_DOUBLE:
++    case SYMBOL_REF:
++      if (gprel_constant (op))
++        {
++          fprintf (file, "%%gprel(");
++          output_addr_const (file, op);
++          fprintf (file, ")(%s)", reg_names[GP_REGNO]);
++          return;
++        }
++
++      break;
++
++    case PLUS:
++      {
++      rtx op0 = XEXP (op, 0);
++      rtx op1 = XEXP (op, 1);
++
++      if (REG_P (op0) && CONSTANT_P (op1))
++        {
++          output_addr_const (file, op1);
++          fprintf (file, "(%s)", reg_names[REGNO (op0)]);
++          return;
++        }
++      else if (REG_P (op1) && CONSTANT_P (op0))
++        {
++          output_addr_const (file, op0);
++          fprintf (file, "(%s)", reg_names[REGNO (op1)]);
++          return;
++        }
++      }
++      break;
++
++    case REG:
++      fprintf (file, "0(%s)", reg_names[REGNO (op)]);
++      return;
++
++    case MEM:
++      {
++      rtx base = XEXP (op, 0);
++      PRINT_OPERAND_ADDRESS (file, base);
++      return;
++      }
++    default:
++      break;
++    }
++
++  fprintf (stderr, "Missing way to print address\n");
++  debug_rtx (op);
++  abort ();
++}
++\f
++
++
++
++
++/****************************
++ * Predicates
++ ****************************/
++
++int
++arith_operand (rtx op, enum machine_mode mode)
++{
++  if (GET_CODE (op) == CONST_INT && SMALL_INT (INTVAL (op)))
++    return 1;
++
++  return register_operand (op, mode);
++}
++
++int
++uns_arith_operand (rtx op, enum machine_mode mode)
++{
++  if (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (INTVAL (op)))
++    return 1;
++
++  return register_operand (op, mode);
++}
++
++int
++logical_operand (rtx op, enum machine_mode mode)
++{
++  if (GET_CODE (op) == CONST_INT
++      && (SMALL_INT_UNSIGNED (INTVAL (op)) || UPPER16_INT (INTVAL (op))))
++    return 1;
++
++  return register_operand (op, mode);
++}
++
++int
++shift_operand (rtx op, enum machine_mode mode)
++{
++  if (GET_CODE (op) == CONST_INT && SHIFT_INT (INTVAL (op)))
++    return 1;
++
++  return register_operand (op, mode);
++}
++
++int
++rdwrctl_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
++{
++  return GET_CODE (op) == CONST_INT && RDWRCTL_INT (INTVAL (op));
++}
++
++/* Return truth value of whether OP is a register or the constant 0. */
++
++int
++reg_or_0_operand (rtx op, enum machine_mode mode)
++{
++  switch (GET_CODE (op))
++    {
++    case CONST_INT:
++      return INTVAL (op) == 0;
++
++    case CONST_DOUBLE:
++      return op == CONST0_RTX (mode);
++
++    default:
++      break;
++    }
++
++  return register_operand (op, mode);
++}
++
++
++int
++equality_op (rtx op, enum machine_mode mode)
++{
++  if (mode != GET_MODE (op))
++    return 0;
++
++  return GET_CODE (op) == EQ || GET_CODE (op) == NE;
++}
++
++int
++custom_insn_opcode (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
++{
++  return GET_CODE (op) == CONST_INT && CUSTOM_INSN_OPCODE (INTVAL (op));
++}
++
++
++\f
++
++
++
++
++/*****************************************************************************
++**
++** instruction scheduler
++**
++*****************************************************************************/
++static int
++nios2_use_dfa_pipeline_interface ()
++{
++  return 1;
++}
++
++
++static int
++nios2_issue_rate ()
++{
++#ifdef MAX_DFA_ISSUE_RATE
++  return MAX_DFA_ISSUE_RATE;
++#else
++  return 1;
++#endif
++}
++
++
++const char *
++asm_output_opcode (FILE *file ATTRIBUTE_UNUSED, 
++                   const char *ptr ATTRIBUTE_UNUSED)
++{
++  const char *p;
++
++  p = ptr;
++  return ptr;
++}
++\f
++
++
++/*****************************************************************************
++**
++** function arguments
++**
++*****************************************************************************/
++
++void
++init_cumulative_args (CUMULATIVE_ARGS *cum, 
++                      tree fntype ATTRIBUTE_UNUSED, 
++                      rtx libname ATTRIBUTE_UNUSED, 
++                      tree fndecl ATTRIBUTE_UNUSED, 
++                      int n_named_args ATTRIBUTE_UNUSED)
++{
++  cum->regs_used = 0;
++}
++
++
++/* Update the data in CUM to advance over an argument
++   of mode MODE and data type TYPE.
++   (TYPE is null for libcalls where that information may not be available.)  */
++
++void
++function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, 
++                      tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
++{
++  HOST_WIDE_INT param_size;
++
++  if (mode == BLKmode)
++    {
++      param_size = int_size_in_bytes (type);
++      if (param_size < 0)
++      internal_error
++        ("Do not know how to handle large structs or variable length types");
++    }
++  else
++    {
++      param_size = GET_MODE_SIZE (mode);
++    }
++
++  /* convert to words (round up) */
++  param_size = (3 + param_size) / 4;
++
++  if (cum->regs_used + param_size > NUM_ARG_REGS)
++    {
++      cum->regs_used = NUM_ARG_REGS;
++    }
++  else
++    {
++      cum->regs_used += param_size;
++    }
++
++  return;
++}
++
++/* Define where to put the arguments to a function.  Value is zero to
++   push the argument on the stack, or a hard register in which to
++   store the argument.
++
++   MODE is the argument's machine mode.
++   TYPE is the data type of the argument (as a tree).
++   This is null for libcalls where that information may
++   not be available.
++   CUM is a variable of type CUMULATIVE_ARGS which gives info about
++   the preceding args and about the function being called.
++   NAMED is nonzero if this argument is a named parameter
++   (otherwise it is an extra parameter matching an ellipsis).  */
++rtx
++function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, 
++              tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
++{
++  rtx return_rtx = NULL_RTX;
++
++  if (cum->regs_used < NUM_ARG_REGS)
++    {
++      return_rtx = gen_rtx_REG (mode, FIRST_ARG_REGNO + cum->regs_used);
++    }
++
++  return return_rtx;
++}
++
++int
++function_arg_partial_nregs (const CUMULATIVE_ARGS *cum,
++                            enum machine_mode mode, tree type, 
++                            int named ATTRIBUTE_UNUSED)
++{
++  HOST_WIDE_INT param_size;
++
++  if (mode == BLKmode)
++    {
++      param_size = int_size_in_bytes (type);
++      if (param_size < 0)
++      internal_error
++        ("Do not know how to handle large structs or variable length types");
++    }
++  else
++    {
++      param_size = GET_MODE_SIZE (mode);
++    }
++
++  /* convert to words (round up) */
++  param_size = (3 + param_size) / 4;
++
++  if (cum->regs_used < NUM_ARG_REGS
++      && cum->regs_used + param_size > NUM_ARG_REGS)
++    {
++      return NUM_ARG_REGS - cum->regs_used;
++    }
++  else
++    {
++      return 0;
++    }
++}
++
++
++int
++nios2_return_in_memory (tree type)
++{
++  int res = ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD))
++           || (int_size_in_bytes (type) == -1));
++
++  return res;
++}
++
++/* ??? It may be possible to eliminate the copyback and implement
++       my own va_arg type, but that is more work for now. */
++int
++nios2_setup_incoming_varargs (const CUMULATIVE_ARGS *cum, 
++                              enum machine_mode mode, tree type, 
++                              int no_rtl)
++{
++  CUMULATIVE_ARGS local_cum;
++  int regs_to_push;
++
++  local_cum = *cum;
++  FUNCTION_ARG_ADVANCE (local_cum, mode, type, 1);
++
++  regs_to_push = NUM_ARG_REGS - local_cum.regs_used;
++
++  if (!no_rtl)
++    {
++      if (regs_to_push > 0)
++      {
++        rtx ptr, mem;
++
++        ptr = virtual_incoming_args_rtx;
++        mem = gen_rtx_MEM (BLKmode, ptr);
++
++        /* va_arg is an array access in this case, which causes
++           it to get MEM_IN_STRUCT_P set.  We must set it here
++           so that the insn scheduler won't assume that these
++           stores can't possibly overlap with the va_arg loads.  */
++        MEM_SET_IN_STRUCT_P (mem, 1);
++
++        emit_insn (gen_blockage ());
++        move_block_from_reg (local_cum.regs_used + FIRST_ARG_REGNO, mem,
++                             regs_to_push);
++        emit_insn (gen_blockage ());
++      }
++    }
++
++  return regs_to_push * UNITS_PER_WORD;
++
++}
++
++
++\f
++/*****************************************************************************
++**
++** builtins
++**
++** This method for handling builtins is from CSP where _many_ more types of
++** expanders have already been written. Check there first before writing
++** new ones.
++**
++*****************************************************************************/
++
++enum nios2_builtins
++{
++  NIOS2_BUILTIN_LDBIO,
++  NIOS2_BUILTIN_LDBUIO,
++  NIOS2_BUILTIN_LDHIO,
++  NIOS2_BUILTIN_LDHUIO,
++  NIOS2_BUILTIN_LDWIO,
++  NIOS2_BUILTIN_STBIO,
++  NIOS2_BUILTIN_STHIO,
++  NIOS2_BUILTIN_STWIO,
++  NIOS2_BUILTIN_SYNC,
++  NIOS2_BUILTIN_RDCTL,
++  NIOS2_BUILTIN_WRCTL,
++
++  NIOS2_BUILTIN_CUSTOM_N,
++  NIOS2_BUILTIN_CUSTOM_NI,
++  NIOS2_BUILTIN_CUSTOM_NF,
++  NIOS2_BUILTIN_CUSTOM_NP,
++  NIOS2_BUILTIN_CUSTOM_NII,
++  NIOS2_BUILTIN_CUSTOM_NIF,
++  NIOS2_BUILTIN_CUSTOM_NIP,
++  NIOS2_BUILTIN_CUSTOM_NFI,
++  NIOS2_BUILTIN_CUSTOM_NFF,
++  NIOS2_BUILTIN_CUSTOM_NFP,
++  NIOS2_BUILTIN_CUSTOM_NPI,
++  NIOS2_BUILTIN_CUSTOM_NPF,
++  NIOS2_BUILTIN_CUSTOM_NPP,
++  NIOS2_BUILTIN_CUSTOM_IN,
++  NIOS2_BUILTIN_CUSTOM_INI,
++  NIOS2_BUILTIN_CUSTOM_INF,
++  NIOS2_BUILTIN_CUSTOM_INP,
++  NIOS2_BUILTIN_CUSTOM_INII,
++  NIOS2_BUILTIN_CUSTOM_INIF,
++  NIOS2_BUILTIN_CUSTOM_INIP,
++  NIOS2_BUILTIN_CUSTOM_INFI,
++  NIOS2_BUILTIN_CUSTOM_INFF,
++  NIOS2_BUILTIN_CUSTOM_INFP,
++  NIOS2_BUILTIN_CUSTOM_INPI,
++  NIOS2_BUILTIN_CUSTOM_INPF,
++  NIOS2_BUILTIN_CUSTOM_INPP,
++  NIOS2_BUILTIN_CUSTOM_FN,
++  NIOS2_BUILTIN_CUSTOM_FNI,
++  NIOS2_BUILTIN_CUSTOM_FNF,
++  NIOS2_BUILTIN_CUSTOM_FNP,
++  NIOS2_BUILTIN_CUSTOM_FNII,
++  NIOS2_BUILTIN_CUSTOM_FNIF,
++  NIOS2_BUILTIN_CUSTOM_FNIP,
++  NIOS2_BUILTIN_CUSTOM_FNFI,
++  NIOS2_BUILTIN_CUSTOM_FNFF,
++  NIOS2_BUILTIN_CUSTOM_FNFP,
++  NIOS2_BUILTIN_CUSTOM_FNPI,
++  NIOS2_BUILTIN_CUSTOM_FNPF,
++  NIOS2_BUILTIN_CUSTOM_FNPP,
++  NIOS2_BUILTIN_CUSTOM_PN,
++  NIOS2_BUILTIN_CUSTOM_PNI,
++  NIOS2_BUILTIN_CUSTOM_PNF,
++  NIOS2_BUILTIN_CUSTOM_PNP,
++  NIOS2_BUILTIN_CUSTOM_PNII,
++  NIOS2_BUILTIN_CUSTOM_PNIF,
++  NIOS2_BUILTIN_CUSTOM_PNIP,
++  NIOS2_BUILTIN_CUSTOM_PNFI,
++  NIOS2_BUILTIN_CUSTOM_PNFF,
++  NIOS2_BUILTIN_CUSTOM_PNFP,
++  NIOS2_BUILTIN_CUSTOM_PNPI,
++  NIOS2_BUILTIN_CUSTOM_PNPF,
++  NIOS2_BUILTIN_CUSTOM_PNPP,
++
++
++  LIM_NIOS2_BUILTINS
++};
++
++struct builtin_description
++{
++    const enum insn_code icode;
++    const char *const name;
++    const enum nios2_builtins code;
++    const tree *type;
++    rtx (* expander) PARAMS ((const struct builtin_description *,
++                              tree, rtx, rtx, enum machine_mode, int));
++};
++
++static rtx nios2_expand_STXIO (const struct builtin_description *, 
++                               tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_LDXIO (const struct builtin_description *, 
++                               tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_sync (const struct builtin_description *, 
++                              tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_rdctl (const struct builtin_description *, 
++                               tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_wrctl (const struct builtin_description *, 
++                               tree, rtx, rtx, enum machine_mode, int);
++
++static rtx nios2_expand_custom_n (const struct builtin_description *, 
++                                  tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_Xn (const struct builtin_description *, 
++                                   tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_nX (const struct builtin_description *, 
++                                   tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_XnX (const struct builtin_description *, 
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_nXX (const struct builtin_description *, 
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_XnXX (const struct builtin_description *, 
++                                     tree, rtx, rtx, enum machine_mode, int);
++
++static tree endlink;
++
++/* int fn (volatile const void *)
++ */
++static tree int_ftype_volatile_const_void_p;
++
++/* int fn (int)
++ */
++static tree int_ftype_int;
++
++/* void fn (int, int)
++ */
++static tree void_ftype_int_int;
++
++/* void fn (volatile void *, int)
++ */
++static tree void_ftype_volatile_void_p_int;
++
++/* void fn (void)
++ */
++static tree void_ftype_void;
++
++static tree custom_n;
++static tree custom_ni;
++static tree custom_nf;
++static tree custom_np;
++static tree custom_nii;
++static tree custom_nif;
++static tree custom_nip;
++static tree custom_nfi;
++static tree custom_nff;
++static tree custom_nfp;
++static tree custom_npi;
++static tree custom_npf;
++static tree custom_npp;
++static tree custom_in;
++static tree custom_ini;
++static tree custom_inf;
++static tree custom_inp;
++static tree custom_inii;
++static tree custom_inif;
++static tree custom_inip;
++static tree custom_infi;
++static tree custom_inff;
++static tree custom_infp;
++static tree custom_inpi;
++static tree custom_inpf;
++static tree custom_inpp;
++static tree custom_fn;
++static tree custom_fni;
++static tree custom_fnf;
++static tree custom_fnp;
++static tree custom_fnii;
++static tree custom_fnif;
++static tree custom_fnip;
++static tree custom_fnfi;
++static tree custom_fnff;
++static tree custom_fnfp;
++static tree custom_fnpi;
++static tree custom_fnpf;
++static tree custom_fnpp;
++static tree custom_pn;
++static tree custom_pni;
++static tree custom_pnf;
++static tree custom_pnp;
++static tree custom_pnii;
++static tree custom_pnif;
++static tree custom_pnip;
++static tree custom_pnfi;
++static tree custom_pnff;
++static tree custom_pnfp;
++static tree custom_pnpi;
++static tree custom_pnpf;
++static tree custom_pnpp;
++
++
++static const struct builtin_description bdesc[] = {
++    {CODE_FOR_ldbio, "__builtin_ldbio", NIOS2_BUILTIN_LDBIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
++    {CODE_FOR_ldbuio, "__builtin_ldbuio", NIOS2_BUILTIN_LDBUIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
++    {CODE_FOR_ldhio, "__builtin_ldhio", NIOS2_BUILTIN_LDHIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
++    {CODE_FOR_ldhuio, "__builtin_ldhuio", NIOS2_BUILTIN_LDHUIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
++    {CODE_FOR_ldwio, "__builtin_ldwio", NIOS2_BUILTIN_LDWIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
++
++    {CODE_FOR_stbio, "__builtin_stbio", NIOS2_BUILTIN_STBIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO},
++    {CODE_FOR_sthio, "__builtin_sthio", NIOS2_BUILTIN_STHIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO},
++    {CODE_FOR_stwio, "__builtin_stwio", NIOS2_BUILTIN_STWIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO},
++
++    {CODE_FOR_sync, "__builtin_sync", NIOS2_BUILTIN_SYNC, &void_ftype_void, nios2_expand_sync},
++    {CODE_FOR_rdctl, "__builtin_rdctl", NIOS2_BUILTIN_RDCTL, &int_ftype_int, nios2_expand_rdctl},
++    {CODE_FOR_wrctl, "__builtin_wrctl", NIOS2_BUILTIN_WRCTL, &void_ftype_int_int, nios2_expand_wrctl},
++
++    {CODE_FOR_custom_n, "__builtin_custom_n", NIOS2_BUILTIN_CUSTOM_N, &custom_n, nios2_expand_custom_n},
++    {CODE_FOR_custom_ni, "__builtin_custom_ni", NIOS2_BUILTIN_CUSTOM_NI, &custom_ni, nios2_expand_custom_nX},
++    {CODE_FOR_custom_nf, "__builtin_custom_nf", NIOS2_BUILTIN_CUSTOM_NF, &custom_nf, nios2_expand_custom_nX},
++    {CODE_FOR_custom_np, "__builtin_custom_np", NIOS2_BUILTIN_CUSTOM_NP, &custom_np, nios2_expand_custom_nX},
++    {CODE_FOR_custom_nii, "__builtin_custom_nii", NIOS2_BUILTIN_CUSTOM_NII, &custom_nii, nios2_expand_custom_nXX},
++    {CODE_FOR_custom_nif, "__builtin_custom_nif", NIOS2_BUILTIN_CUSTOM_NIF, &custom_nif, nios2_expand_custom_nXX},
++    {CODE_FOR_custom_nip, "__builtin_custom_nip", NIOS2_BUILTIN_CUSTOM_NIP, &custom_nip, nios2_expand_custom_nXX},
++    {CODE_FOR_custom_nfi, "__builtin_custom_nfi", NIOS2_BUILTIN_CUSTOM_NFI, &custom_nfi, nios2_expand_custom_nXX},
++    {CODE_FOR_custom_nff, "__builtin_custom_nff", NIOS2_BUILTIN_CUSTOM_NFF, &custom_nff, nios2_expand_custom_nXX},
++    {CODE_FOR_custom_nfp, "__builtin_custom_nfp", NIOS2_BUILTIN_CUSTOM_NFP, &custom_nfp, nios2_expand_custom_nXX},
++    {CODE_FOR_custom_npi, "__builtin_custom_npi", NIOS2_BUILTIN_CUSTOM_NPI, &custom_npi, nios2_expand_custom_nXX},
++    {CODE_FOR_custom_npf, "__builtin_custom_npf", NIOS2_BUILTIN_CUSTOM_NPF, &custom_npf, nios2_expand_custom_nXX},
++    {CODE_FOR_custom_npp, "__builtin_custom_npp", NIOS2_BUILTIN_CUSTOM_NPP, &custom_npp, nios2_expand_custom_nXX},
++    {CODE_FOR_custom_in, "__builtin_custom_in", NIOS2_BUILTIN_CUSTOM_IN, &custom_in, nios2_expand_custom_Xn},
++    {CODE_FOR_custom_ini, "__builtin_custom_ini", NIOS2_BUILTIN_CUSTOM_INI, &custom_ini, nios2_expand_custom_XnX},
++    {CODE_FOR_custom_inf, "__builtin_custom_inf", NIOS2_BUILTIN_CUSTOM_INF, &custom_inf, nios2_expand_custom_XnX},
++    {CODE_FOR_custom_inp, "__builtin_custom_inp", NIOS2_BUILTIN_CUSTOM_INP, &custom_inp, nios2_expand_custom_XnX},
++    {CODE_FOR_custom_inii, "__builtin_custom_inii", NIOS2_BUILTIN_CUSTOM_INII, &custom_inii, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_inif, "__builtin_custom_inif", NIOS2_BUILTIN_CUSTOM_INIF, &custom_inif, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_inip, "__builtin_custom_inip", NIOS2_BUILTIN_CUSTOM_INIP, &custom_inip, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_infi, "__builtin_custom_infi", NIOS2_BUILTIN_CUSTOM_INFI, &custom_infi, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_inff, "__builtin_custom_inff", NIOS2_BUILTIN_CUSTOM_INFF, &custom_inff, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_infp, "__builtin_custom_infp", NIOS2_BUILTIN_CUSTOM_INFP, &custom_infp, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_inpi, "__builtin_custom_inpi", NIOS2_BUILTIN_CUSTOM_INPI, &custom_inpi, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_inpf, "__builtin_custom_inpf", NIOS2_BUILTIN_CUSTOM_INPF, &custom_inpf, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_inpp, "__builtin_custom_inpp", NIOS2_BUILTIN_CUSTOM_INPP, &custom_inpp, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_fn, "__builtin_custom_fn", NIOS2_BUILTIN_CUSTOM_FN, &custom_fn, nios2_expand_custom_Xn},
++    {CODE_FOR_custom_fni, "__builtin_custom_fni", NIOS2_BUILTIN_CUSTOM_FNI, &custom_fni, nios2_expand_custom_XnX},
++    {CODE_FOR_custom_fnf, "__builtin_custom_fnf", NIOS2_BUILTIN_CUSTOM_FNF, &custom_fnf, nios2_expand_custom_XnX},
++    {CODE_FOR_custom_fnp, "__builtin_custom_fnp", NIOS2_BUILTIN_CUSTOM_FNP, &custom_fnp, nios2_expand_custom_XnX},
++    {CODE_FOR_custom_fnii, "__builtin_custom_fnii", NIOS2_BUILTIN_CUSTOM_FNII, &custom_fnii, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_fnif, "__builtin_custom_fnif", NIOS2_BUILTIN_CUSTOM_FNIF, &custom_fnif, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_fnip, "__builtin_custom_fnip", NIOS2_BUILTIN_CUSTOM_FNIP, &custom_fnip, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_fnfi, "__builtin_custom_fnfi", NIOS2_BUILTIN_CUSTOM_FNFI, &custom_fnfi, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_fnff, "__builtin_custom_fnff", NIOS2_BUILTIN_CUSTOM_FNFF, &custom_fnff, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_fnfp, "__builtin_custom_fnfp", NIOS2_BUILTIN_CUSTOM_FNFP, &custom_fnfp, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_fnpi, "__builtin_custom_fnpi", NIOS2_BUILTIN_CUSTOM_FNPI, &custom_fnpi, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_fnpf, "__builtin_custom_fnpf", NIOS2_BUILTIN_CUSTOM_FNPF, &custom_fnpf, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_fnpp, "__builtin_custom_fnpp", NIOS2_BUILTIN_CUSTOM_FNPP, &custom_fnpp, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_pn, "__builtin_custom_pn", NIOS2_BUILTIN_CUSTOM_PN, &custom_pn, nios2_expand_custom_Xn},
++    {CODE_FOR_custom_pni, "__builtin_custom_pni", NIOS2_BUILTIN_CUSTOM_PNI, &custom_pni, nios2_expand_custom_XnX},
++    {CODE_FOR_custom_pnf, "__builtin_custom_pnf", NIOS2_BUILTIN_CUSTOM_PNF, &custom_pnf, nios2_expand_custom_XnX},
++    {CODE_FOR_custom_pnp, "__builtin_custom_pnp", NIOS2_BUILTIN_CUSTOM_PNP, &custom_pnp, nios2_expand_custom_XnX},
++    {CODE_FOR_custom_pnii, "__builtin_custom_pnii", NIOS2_BUILTIN_CUSTOM_PNII, &custom_pnii, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_pnif, "__builtin_custom_pnif", NIOS2_BUILTIN_CUSTOM_PNIF, &custom_pnif, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_pnip, "__builtin_custom_pnip", NIOS2_BUILTIN_CUSTOM_PNIP, &custom_pnip, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_pnfi, "__builtin_custom_pnfi", NIOS2_BUILTIN_CUSTOM_PNFI, &custom_pnfi, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_pnff, "__builtin_custom_pnff", NIOS2_BUILTIN_CUSTOM_PNFF, &custom_pnff, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_pnfp, "__builtin_custom_pnfp", NIOS2_BUILTIN_CUSTOM_PNFP, &custom_pnfp, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_pnpi, "__builtin_custom_pnpi", NIOS2_BUILTIN_CUSTOM_PNPI, &custom_pnpi, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_pnpf, "__builtin_custom_pnpf", NIOS2_BUILTIN_CUSTOM_PNPF, &custom_pnpf, nios2_expand_custom_XnXX},
++    {CODE_FOR_custom_pnpp, "__builtin_custom_pnpp", NIOS2_BUILTIN_CUSTOM_PNPP, &custom_pnpp, nios2_expand_custom_XnXX},
++
++
++    {0, 0, 0, 0, 0},
++};
++
++/* This does not have a closing bracket on purpose (see use) */
++#define def_param(TYPE) \
++  tree_cons (NULL_TREE, TYPE,
++
++static void
++nios2_init_builtins ()
++{
++  const struct builtin_description *d;
++
++
++  endlink = void_list_node;
++
++  /* Special indenting here because one of the brackets is in def_param */
++  /* *INDENT-OFF* */
++
++  /* int fn (volatile const void *)
++   */
++  int_ftype_volatile_const_void_p
++    = build_function_type (integer_type_node,
++                         def_param (build_qualified_type (ptr_type_node,
++                                                          TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE))
++                         endlink));
++
++
++  /* void fn (volatile void *, int)
++   */
++  void_ftype_volatile_void_p_int
++    = build_function_type (void_type_node,
++                         def_param (build_qualified_type (ptr_type_node,
++                                                          TYPE_QUAL_VOLATILE))
++                         def_param (integer_type_node)
++                         endlink)));
++
++  /* void fn (void)
++   */
++  void_ftype_void
++      = build_function_type (void_type_node,
++                             endlink);
++
++  /* int fn (int)
++   */
++  int_ftype_int
++      = build_function_type (integer_type_node,
++                             def_param (integer_type_node)
++                             endlink));
++
++  /* void fn (int, int)
++   */
++  void_ftype_int_int
++      = build_function_type (void_type_node,
++                             def_param (integer_type_node)
++                             def_param (integer_type_node)
++                             endlink)));
++
++
++#define CUSTOM_NUM def_param (integer_type_node)
++
++  custom_n
++      = build_function_type (void_type_node,
++                           CUSTOM_NUM
++                           endlink));
++  custom_ni
++      = build_function_type (void_type_node,
++                           CUSTOM_NUM
++                           def_param (integer_type_node)
++                           endlink)));
++  custom_nf
++      = build_function_type (void_type_node,
++                           CUSTOM_NUM
++                           def_param (float_type_node)
++                           endlink)));
++  custom_np
++      = build_function_type (void_type_node,
++                           CUSTOM_NUM
++                           def_param (ptr_type_node)
++                           endlink)));
++  custom_nii
++      = build_function_type (void_type_node,
++                           CUSTOM_NUM
++                           def_param (integer_type_node)
++                           def_param (integer_type_node)
++                           endlink))));
++  custom_nif
++      = build_function_type (void_type_node,
++                           CUSTOM_NUM
++                           def_param (integer_type_node)
++                           def_param (float_type_node)
++                           endlink))));
++  custom_nip
++      = build_function_type (void_type_node,
++                           CUSTOM_NUM
++                           def_param (integer_type_node)
++                           def_param (ptr_type_node)
++                           endlink))));
++  custom_nfi
++      = build_function_type (void_type_node,
++                           CUSTOM_NUM
++                           def_param (float_type_node)
++                           def_param (integer_type_node)
++                           endlink))));
++  custom_nff
++      = build_function_type (void_type_node,
++                           CUSTOM_NUM
++                           def_param (float_type_node)
++                           def_param (float_type_node)
++                           endlink))));
++  custom_nfp
++      = build_function_type (void_type_node,
++                           CUSTOM_NUM
++                           def_param (float_type_node)
++                           def_param (ptr_type_node)
++                           endlink))));
++  custom_npi
++      = build_function_type (void_type_node,
++                           CUSTOM_NUM
++                           def_param (ptr_type_node)
++                           def_param (integer_type_node)
++                           endlink))));
++  custom_npf
++      = build_function_type (void_type_node,
++                           CUSTOM_NUM
++                           def_param (ptr_type_node)
++                           def_param (float_type_node)
++                           endlink))));
++  custom_npp
++      = build_function_type (void_type_node,
++                           CUSTOM_NUM
++                           def_param (ptr_type_node)
++                           def_param (ptr_type_node)
++                           endlink))));
++
++  custom_in
++      = build_function_type (integer_type_node,
++                           CUSTOM_NUM
++                           endlink));
++  custom_ini
++      = build_function_type (integer_type_node,
++                           CUSTOM_NUM
++                           def_param (integer_type_node)
++                           endlink)));
++  custom_inf
++      = build_function_type (integer_type_node,
++                           CUSTOM_NUM
++                           def_param (float_type_node)
++                           endlink)));
++  custom_inp
++      = build_function_type (integer_type_node,
++                           CUSTOM_NUM
++                           def_param (ptr_type_node)
++                           endlink)));
++  custom_inii
++      = build_function_type (integer_type_node,
++                           CUSTOM_NUM
++                           def_param (integer_type_node)
++                           def_param (integer_type_node)
++                           endlink))));
++  custom_inif
++      = build_function_type (integer_type_node,
++                           CUSTOM_NUM
++                           def_param (integer_type_node)
++                           def_param (float_type_node)
++                           endlink))));
++  custom_inip
++      = build_function_type (integer_type_node,
++                           CUSTOM_NUM
++                           def_param (integer_type_node)
++                           def_param (ptr_type_node)
++                           endlink))));
++  custom_infi
++      = build_function_type (integer_type_node,
++                           CUSTOM_NUM
++                           def_param (float_type_node)
++                           def_param (integer_type_node)
++                           endlink))));
++  custom_inff
++      = build_function_type (integer_type_node,
++                           CUSTOM_NUM
++                           def_param (float_type_node)
++                           def_param (float_type_node)
++                           endlink))));
++  custom_infp
++      = build_function_type (integer_type_node,
++                           CUSTOM_NUM
++                           def_param (float_type_node)
++                           def_param (ptr_type_node)
++                           endlink))));
++  custom_inpi
++      = build_function_type (integer_type_node,
++                           CUSTOM_NUM
++                           def_param (ptr_type_node)
++                           def_param (integer_type_node)
++                           endlink))));
++  custom_inpf
++      = build_function_type (integer_type_node,
++                           CUSTOM_NUM
++                           def_param (ptr_type_node)
++                           def_param (float_type_node)
++                           endlink))));
++  custom_inpp
++      = build_function_type (integer_type_node,
++                           CUSTOM_NUM
++                           def_param (ptr_type_node)
++                           def_param (ptr_type_node)
++                           endlink))));
++
++  custom_fn
++      = build_function_type (float_type_node,
++                           CUSTOM_NUM
++                           endlink));
++  custom_fni
++      = build_function_type (float_type_node,
++                           CUSTOM_NUM
++                           def_param (integer_type_node)
++                           endlink)));
++  custom_fnf
++      = build_function_type (float_type_node,
++                           CUSTOM_NUM
++                           def_param (float_type_node)
++                           endlink)));
++  custom_fnp
++      = build_function_type (float_type_node,
++                           CUSTOM_NUM
++                           def_param (ptr_type_node)
++                           endlink)));
++  custom_fnii
++      = build_function_type (float_type_node,
++                           CUSTOM_NUM
++                           def_param (integer_type_node)
++                           def_param (integer_type_node)
++                           endlink))));
++  custom_fnif
++      = build_function_type (float_type_node,
++                           CUSTOM_NUM
++                           def_param (integer_type_node)
++                           def_param (float_type_node)
++                           endlink))));
++  custom_fnip
++      = build_function_type (float_type_node,
++                           CUSTOM_NUM
++                           def_param (integer_type_node)
++                           def_param (ptr_type_node)
++                           endlink))));
++  custom_fnfi
++      = build_function_type (float_type_node,
++                           CUSTOM_NUM
++                           def_param (float_type_node)
++                           def_param (integer_type_node)
++                           endlink))));
++  custom_fnff
++      = build_function_type (float_type_node,
++                           CUSTOM_NUM
++                           def_param (float_type_node)
++                           def_param (float_type_node)
++                           endlink))));
++  custom_fnfp
++      = build_function_type (float_type_node,
++                           CUSTOM_NUM
++                           def_param (float_type_node)
++                           def_param (ptr_type_node)
++                           endlink))));
++  custom_fnpi
++      = build_function_type (float_type_node,
++                           CUSTOM_NUM
++                           def_param (ptr_type_node)
++                           def_param (integer_type_node)
++                           endlink))));
++  custom_fnpf
++      = build_function_type (float_type_node,
++                           CUSTOM_NUM
++                           def_param (ptr_type_node)
++                           def_param (float_type_node)
++                           endlink))));
++  custom_fnpp
++      = build_function_type (float_type_node,
++                           CUSTOM_NUM
++                           def_param (ptr_type_node)
++                           def_param (ptr_type_node)
++                           endlink))));
++
++
++  custom_pn
++      = build_function_type (ptr_type_node,
++                           CUSTOM_NUM
++                           endlink));
++  custom_pni
++      = build_function_type (ptr_type_node,
++                           CUSTOM_NUM
++                           def_param (integer_type_node)
++                           endlink)));
++  custom_pnf
++      = build_function_type (ptr_type_node,
++                           CUSTOM_NUM
++                           def_param (float_type_node)
++                           endlink)));
++  custom_pnp
++      = build_function_type (ptr_type_node,
++                           CUSTOM_NUM
++                           def_param (ptr_type_node)
++                           endlink)));
++  custom_pnii
++      = build_function_type (ptr_type_node,
++                           CUSTOM_NUM
++                           def_param (integer_type_node)
++                           def_param (integer_type_node)
++                           endlink))));
++  custom_pnif
++      = build_function_type (ptr_type_node,
++                           CUSTOM_NUM
++                           def_param (integer_type_node)
++                           def_param (float_type_node)
++                           endlink))));
++  custom_pnip
++      = build_function_type (ptr_type_node,
++                           CUSTOM_NUM
++                           def_param (integer_type_node)
++                           def_param (ptr_type_node)
++                           endlink))));
++  custom_pnfi
++      = build_function_type (ptr_type_node,
++                           CUSTOM_NUM
++                           def_param (float_type_node)
++                           def_param (integer_type_node)
++                           endlink))));
++  custom_pnff
++      = build_function_type (ptr_type_node,
++                           CUSTOM_NUM
++                           def_param (float_type_node)
++                           def_param (float_type_node)
++                           endlink))));
++  custom_pnfp
++      = build_function_type (ptr_type_node,
++                           CUSTOM_NUM
++                           def_param (float_type_node)
++                           def_param (ptr_type_node)
++                           endlink))));
++  custom_pnpi
++      = build_function_type (ptr_type_node,
++                           CUSTOM_NUM
++                           def_param (ptr_type_node)
++                           def_param (integer_type_node)
++                           endlink))));
++  custom_pnpf
++      = build_function_type (ptr_type_node,
++                           CUSTOM_NUM
++                           def_param (ptr_type_node)
++                           def_param (float_type_node)
++                           endlink))));
++  custom_pnpp
++      = build_function_type (ptr_type_node,
++                           CUSTOM_NUM
++                           def_param (ptr_type_node)
++                           def_param (ptr_type_node)
++                           endlink))));
++
++
++
++  /* *INDENT-ON* */
++
++
++  for (d = bdesc; d->name; d++)
++    {
++      builtin_function (d->name, *d->type, d->code,
++                      BUILT_IN_MD, NULL, NULL);
++    }
++}
++
++/* Expand an expression EXP that calls a built-in function,
++   with result going to TARGET if that's convenient
++   (and in mode MODE if that's convenient).
++   SUBTARGET may be used as the target for computing one of EXP's operands.
++   IGNORE is nonzero if the value is to be ignored.  */
++
++static rtx
++nios2_expand_builtin (tree exp, rtx target, rtx subtarget, 
++                      enum machine_mode mode, int ignore)
++{
++  const struct builtin_description *d;
++  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
++  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
++
++  for (d = bdesc; d->name; d++)
++    if (d->code == fcode)
++      return (d->expander) (d, exp, target, subtarget, mode, ignore);
++
++  /* we should have seen one of the functins we registered */
++  abort ();
++}
++
++static rtx nios2_create_target (const struct builtin_description *, rtx);
++
++
++static rtx
++nios2_create_target (const struct builtin_description *d, rtx target)
++{
++  if (!target
++      || !(*insn_data[d->icode].operand[0].predicate) (target,
++                                                       insn_data[d->icode].operand[0].mode))
++    {
++      target = gen_reg_rtx (insn_data[d->icode].operand[0].mode);
++    }
++
++  return target;
++}
++
++
++static rtx nios2_extract_opcode (const struct builtin_description *, int, tree);
++static rtx nios2_extract_operand (const struct builtin_description *, int, int, tree);
++
++static rtx
++nios2_extract_opcode (const struct builtin_description *d, int op, tree arglist)
++{
++  enum machine_mode mode = insn_data[d->icode].operand[op].mode;
++  tree arg = TREE_VALUE (arglist);
++  rtx opcode = expand_expr (arg, NULL_RTX, mode, 0);
++  opcode = protect_from_queue (opcode, 0);
++
++  if (!(*insn_data[d->icode].operand[op].predicate) (opcode, mode))
++    error ("Custom instruction opcode must be compile time constant in the range 0-255 for %s", d->name);
++
++  return opcode;
++}
++
++static rtx
++nios2_extract_operand (const struct builtin_description *d, int op, int argnum, tree arglist)
++{
++  enum machine_mode mode = insn_data[d->icode].operand[op].mode;
++  tree arg = TREE_VALUE (arglist);
++  rtx operand = expand_expr (arg, NULL_RTX, mode, 0);
++  operand = protect_from_queue (operand, 0);
++
++  if (!(*insn_data[d->icode].operand[op].predicate) (operand, mode))
++    operand = copy_to_mode_reg (mode, operand);
++
++  /* ??? Better errors would be nice */
++  if (!(*insn_data[d->icode].operand[op].predicate) (operand, mode))
++    error ("Invalid argument %d to %s", argnum, d->name);
++
++  return operand;
++}
++
++
++static rtx
++nios2_expand_custom_n (const struct builtin_description *d, tree exp, 
++                       rtx target ATTRIBUTE_UNUSED, rtx subtarget ATTRIBUTE_UNUSED, 
++                       enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED)
++{
++  tree arglist = TREE_OPERAND (exp, 1);
++  rtx pat;
++  rtx opcode;
++
++  /* custom_n should have exactly one operand */
++  if (insn_data[d->icode].n_operands != 1)
++    abort ();
++
++  opcode = nios2_extract_opcode (d, 0, arglist);
++
++  pat = GEN_FCN (d->icode) (opcode);
++  if (!pat)
++    return 0;
++  emit_insn (pat);
++  return 0;
++}
++
++static rtx
++nios2_expand_custom_Xn (const struct builtin_description *d, tree exp, 
++                        rtx target, rtx subtarget ATTRIBUTE_UNUSED, 
++                        enum machine_mode mode ATTRIBUTE_UNUSED, 
++                        int ignore ATTRIBUTE_UNUSED)
++{
++  tree arglist = TREE_OPERAND (exp, 1);
++  rtx pat;
++  rtx opcode;
++
++  /* custom_Xn should have exactly two operands */
++  if (insn_data[d->icode].n_operands != 2)
++    abort ();
++
++  target = nios2_create_target (d, target);
++  opcode = nios2_extract_opcode (d, 1, arglist);
++
++  pat = GEN_FCN (d->icode) (target, opcode);
++  if (!pat)
++    return 0;
++  emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_nX (const struct builtin_description *d, tree exp, 
++                        rtx target ATTRIBUTE_UNUSED, rtx subtarget ATTRIBUTE_UNUSED, 
++                        enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED)
++{
++  tree arglist = TREE_OPERAND (exp, 1);
++  rtx pat;
++  rtx opcode;
++  rtx operands[1];
++  int i;
++
++
++  /* custom_nX should have exactly two operands */
++  if (insn_data[d->icode].n_operands != 2)
++    abort ();
++
++  opcode = nios2_extract_opcode (d, 0, arglist);
++  for (i = 0; i < 1; i++)
++    {
++      arglist = TREE_CHAIN (arglist);
++      operands[i] = nios2_extract_operand (d, i + 1, i + 1, arglist);
++    }
++
++  pat = GEN_FCN (d->icode) (opcode, operands[0]);
++  if (!pat)
++    return 0;
++  emit_insn (pat);
++  return 0;
++}
++
++static rtx
++nios2_expand_custom_XnX (const struct builtin_description *d, tree exp, rtx target, 
++                         rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, 
++                         int ignore ATTRIBUTE_UNUSED)
++{
++  tree arglist = TREE_OPERAND (exp, 1);
++  rtx pat;
++  rtx opcode;
++  rtx operands[1];
++  int i;
++
++  /* custom_Xn should have exactly three operands */
++  if (insn_data[d->icode].n_operands != 3)
++    abort ();
++
++  target = nios2_create_target (d, target);
++  opcode = nios2_extract_opcode (d, 1, arglist);
++
++  for (i = 0; i < 1; i++)
++    {
++      arglist = TREE_CHAIN (arglist);
++      operands[i] = nios2_extract_operand (d, i + 2, i + 1, arglist);
++    }
++
++  pat = GEN_FCN (d->icode) (target, opcode, operands[0]);
++
++  if (!pat)
++    return 0;
++  emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_nXX (const struct builtin_description *d, tree exp, rtx target ATTRIBUTE_UNUSED, 
++                         rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, 
++                         int ignore ATTRIBUTE_UNUSED)
++{
++  tree arglist = TREE_OPERAND (exp, 1);
++  rtx pat;
++  rtx opcode;
++  rtx operands[2];
++  int i;
++
++
++  /* custom_nX should have exactly three operands */
++  if (insn_data[d->icode].n_operands != 3)
++    abort ();
++
++  opcode = nios2_extract_opcode (d, 0, arglist);
++  for (i = 0; i < 2; i++)
++    {
++      arglist = TREE_CHAIN (arglist);
++      operands[i] = nios2_extract_operand (d, i + 1, i + 1, arglist);
++    }
++
++  pat = GEN_FCN (d->icode) (opcode, operands[0], operands[1]);
++  if (!pat)
++    return 0;
++  emit_insn (pat);
++  return 0;
++}
++
++static rtx
++nios2_expand_custom_XnXX (const struct builtin_description *d, tree exp, rtx target, 
++                          rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, 
++                          int ignore ATTRIBUTE_UNUSED)
++{
++  tree arglist = TREE_OPERAND (exp, 1);
++  rtx pat;
++  rtx opcode;
++  rtx operands[2];
++  int i;
++
++
++  /* custom_XnX should have exactly four operands */
++  if (insn_data[d->icode].n_operands != 4)
++    abort ();
++
++  target = nios2_create_target (d, target);
++  opcode = nios2_extract_opcode (d, 1, arglist);
++  for (i = 0; i < 2; i++)
++    {
++      arglist = TREE_CHAIN (arglist);
++      operands[i] = nios2_extract_operand (d, i + 2, i + 1, arglist);
++    }
++
++  pat = GEN_FCN (d->icode) (target, opcode, operands[0], operands[1]);
++
++  if (!pat)
++    return 0;
++  emit_insn (pat);
++  return target;
++}
++
++
++
++static rtx
++nios2_expand_STXIO (const struct builtin_description *d, tree exp, rtx target ATTRIBUTE_UNUSED, 
++                    rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, 
++                    int ignore ATTRIBUTE_UNUSED)
++{
++  tree arglist = TREE_OPERAND (exp, 1);
++  rtx pat;
++  rtx store_dest, store_val;
++  enum insn_code icode = d->icode;
++
++  /* stores should have exactly two operands */
++  if (insn_data[icode].n_operands != 2)
++    abort ();
++
++  /* process the destination of the store */
++  {
++    enum machine_mode mode = insn_data[icode].operand[0].mode;
++    tree arg = TREE_VALUE (arglist);
++    store_dest = expand_expr (arg, NULL_RTX, VOIDmode, 0);
++    store_dest = protect_from_queue (store_dest, 0);
++
++    store_dest = gen_rtx_MEM (mode, copy_to_mode_reg (Pmode, store_dest));
++
++    /* ??? Better errors would be nice */
++    if (!(*insn_data[icode].operand[0].predicate) (store_dest, mode))
++      error ("Invalid argument 1 to %s", d->name);
++  }
++
++
++  /* process the value to store */
++  {
++    enum machine_mode mode = insn_data[icode].operand[1].mode;
++    tree arg = TREE_VALUE (TREE_CHAIN (arglist));
++    store_val = expand_expr (arg, NULL_RTX, mode, 0);
++    store_val = protect_from_queue (store_val, 0);
++
++    if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
++      store_val = copy_to_mode_reg (mode, store_val);
++
++    /* ??? Better errors would be nice */
++    if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
++      error ("Invalid argument 2 to %s", d->name);
++  }
++
++  pat = GEN_FCN (d->icode) (store_dest, store_val);
++  if (!pat)
++    return 0;
++  emit_insn (pat);
++  return 0;
++}
++
++
++static rtx
++nios2_expand_LDXIO (const struct builtin_description * d, tree exp, rtx target, 
++                    rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, 
++                    int ignore ATTRIBUTE_UNUSED)
++{
++  tree arglist = TREE_OPERAND (exp, 1);
++  rtx pat;
++  rtx ld_src;
++  enum insn_code icode = d->icode;
++
++  /* loads should have exactly two operands */
++  if (insn_data[icode].n_operands != 2)
++    abort ();
++
++  target = nios2_create_target (d, target);
++
++  {
++    enum machine_mode mode = insn_data[icode].operand[1].mode;
++    tree arg = TREE_VALUE (arglist);
++    ld_src = expand_expr (arg, NULL_RTX, VOIDmode, 0);
++    ld_src = protect_from_queue (ld_src, 0);
++
++    ld_src = gen_rtx_MEM (mode, copy_to_mode_reg (Pmode, ld_src));
++
++    /* ??? Better errors would be nice */
++    if (!(*insn_data[icode].operand[1].predicate) (ld_src, mode))
++      {
++        error ("Invalid argument 1 to %s", d->name);
++      }
++  }
++
++  pat = GEN_FCN (d->icode) (target, ld_src);
++  if (!pat)
++    return 0;
++  emit_insn (pat);
++  return target;
++}
++
++
++static rtx
++nios2_expand_sync (const struct builtin_description * d ATTRIBUTE_UNUSED, 
++                   tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED, 
++                   rtx subtarget ATTRIBUTE_UNUSED, 
++                   enum machine_mode mode ATTRIBUTE_UNUSED, 
++                   int ignore ATTRIBUTE_UNUSED)
++{
++  emit_insn (gen_sync ());
++  return 0;
++}
++
++static rtx
++nios2_expand_rdctl (const struct builtin_description * d ATTRIBUTE_UNUSED, 
++                   tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED, 
++                   rtx subtarget ATTRIBUTE_UNUSED, 
++                   enum machine_mode mode ATTRIBUTE_UNUSED, 
++                   int ignore ATTRIBUTE_UNUSED)
++{
++  tree arglist = TREE_OPERAND (exp, 1);
++  rtx pat;
++  rtx rdctl_reg;
++  enum insn_code icode = d->icode;
++
++  /* rdctl should have exactly two operands */
++  if (insn_data[icode].n_operands != 2)
++    abort ();
++
++  target = nios2_create_target (d, target);
++
++  {
++    enum machine_mode mode = insn_data[icode].operand[1].mode;
++    tree arg = TREE_VALUE (arglist);
++    rdctl_reg = expand_expr (arg, NULL_RTX, VOIDmode, 0);
++    rdctl_reg = protect_from_queue (rdctl_reg, 0);
++
++    if (!(*insn_data[icode].operand[1].predicate) (rdctl_reg, mode))
++      {
++        error ("Control register number must be in range 0-31 for %s", d->name);
++      }
++  }
++
++  pat = GEN_FCN (d->icode) (target, rdctl_reg);
++  if (!pat)
++    return 0;
++  emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_wrctl (const struct builtin_description * d ATTRIBUTE_UNUSED, 
++                   tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED, 
++                   rtx subtarget ATTRIBUTE_UNUSED, 
++                   enum machine_mode mode ATTRIBUTE_UNUSED, 
++                   int ignore ATTRIBUTE_UNUSED)
++{
++  tree arglist = TREE_OPERAND (exp, 1);
++  rtx pat;
++  rtx wrctl_reg, store_val;
++  enum insn_code icode = d->icode;
++
++  /* stores should have exactly two operands */
++  if (insn_data[icode].n_operands != 2)
++    abort ();
++
++  /* process the destination of the store */
++  {
++    enum machine_mode mode = insn_data[icode].operand[0].mode;
++    tree arg = TREE_VALUE (arglist);
++    wrctl_reg = expand_expr (arg, NULL_RTX, VOIDmode, 0);
++    wrctl_reg = protect_from_queue (wrctl_reg, 0);
++
++    if (!(*insn_data[icode].operand[0].predicate) (wrctl_reg, mode))
++      error ("Control register number must be in range 0-31 for %s", d->name);
++  }
++
++
++  /* process the value to store */
++  {
++    enum machine_mode mode = insn_data[icode].operand[1].mode;
++    tree arg = TREE_VALUE (TREE_CHAIN (arglist));
++    store_val = expand_expr (arg, NULL_RTX, mode, 0);
++    store_val = protect_from_queue (store_val, 0);
++
++    if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
++      store_val = copy_to_mode_reg (mode, store_val);
++
++    /* ??? Better errors would be nice */
++    if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
++      error ("Invalid argument 2 to %s", d->name);
++  }
++
++  pat = GEN_FCN (d->icode) (wrctl_reg, store_val);
++  if (!pat)
++    return 0;
++  emit_insn (pat);
++  return 0;
++}
++
++
++#include "gt-nios2.h"
++
+--- gcc-3.4.3/gcc/config/nios2/nios2.h
++++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.h
+@@ -0,0 +1,824 @@
++/* Definitions of target machine for Altera NIOS 2G NIOS2 version.
++   Copyright (C) 2003 Altera 
++   Contributed by Jonah Graham (jgraham@altera.com).
++
++This file is part of GNU CC.
++
++GNU CC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 2, or (at your option)
++any later version.
++
++GNU CC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GNU CC; see the file COPYING.  If not, write to
++the Free Software Foundation, 59 Temple Place - Suite 330,
++Boston, MA 02111-1307, USA.  */
++
++
++
++#define TARGET_CPU_CPP_BUILTINS()             \
++  do                                          \
++    {                                         \
++      builtin_define_std ("NIOS2");           \
++      builtin_define_std ("nios2");           \
++      builtin_define ("_GNU_SOURCE");         \
++    }                                         \
++  while (0)
++#define TARGET_VERSION fprintf (stderr, " (Altera Nios II)")
++
++
++
++
++
++/*********************************
++ * Run-time Target Specification
++ *********************************/
++
++#define HAS_DIV_FLAG 0x0001
++#define HAS_MUL_FLAG 0x0002
++#define HAS_MULX_FLAG 0x0004
++#define FAST_SW_DIV_FLAG 0x0008
++#define INLINE_MEMCPY_FLAG 0x00010
++#define CACHE_VOLATILE_FLAG 0x0020
++#define BYPASS_CACHE_FLAG 0x0040
++
++extern int target_flags;
++#define TARGET_HAS_DIV (target_flags & HAS_DIV_FLAG)
++#define TARGET_HAS_MUL (target_flags & HAS_MUL_FLAG)
++#define TARGET_HAS_MULX (target_flags & HAS_MULX_FLAG)
++#define TARGET_FAST_SW_DIV (target_flags & FAST_SW_DIV_FLAG)
++#define TARGET_INLINE_MEMCPY (target_flags & INLINE_MEMCPY_FLAG)
++#define TARGET_CACHE_VOLATILE (target_flags & CACHE_VOLATILE_FLAG)
++#define TARGET_BYPASS_CACHE (target_flags & BYPASS_CACHE_FLAG)
++
++#define TARGET_SWITCHES                                       \
++{                                                     \
++    { "hw-div", HAS_DIV_FLAG,                         \
++      N_("Enable DIV, DIVU") },                               \
++    { "no-hw-div", -HAS_DIV_FLAG,                     \
++      N_("Disable DIV, DIVU (default)") },            \
++    { "hw-mul", HAS_MUL_FLAG,                         \
++      N_("Enable MUL instructions (default)") },                              \
++    { "hw-mulx", HAS_MULX_FLAG,                               \
++      N_("Enable MULX instructions, assume fast shifter") },                          \
++    { "no-hw-mul", -HAS_MUL_FLAG,                     \
++      N_("Disable MUL instructions") },               \
++    { "no-hw-mulx", -HAS_MULX_FLAG,                   \
++      N_("Disable MULX instructions, assume slow shifter (default and implied by -mno-hw-mul)") },            \
++    { "fast-sw-div", FAST_SW_DIV_FLAG,                                \
++      N_("Use table based fast divide (default at -O3)") },                           \
++    { "no-fast-sw-div", -FAST_SW_DIV_FLAG,                    \
++      N_("Don't use table based fast divide ever") },         \
++    { "inline-memcpy", INLINE_MEMCPY_FLAG,                            \
++      N_("Inline small memcpy (default when optimizing)") },                          \
++    { "no-inline-memcpy", -INLINE_MEMCPY_FLAG,                        \
++      N_("Don't Inline small memcpy") },              \
++    { "cache-volatile", CACHE_VOLATILE_FLAG,                          \
++      N_("Volatile accesses use non-io variants of instructions (default)") },                                \
++    { "no-cache-volatile", -CACHE_VOLATILE_FLAG,                      \
++      N_("Volatile accesses use io variants of instructions") },              \
++    { "bypass-cache", BYPASS_CACHE_FLAG,                              \
++      N_("All ld/st instructins use io variants") },                          \
++    { "no-bypass-cache", -BYPASS_CACHE_FLAG,                  \
++      N_("All ld/st instructins do not use io variants (default)") },         \
++    { "smallc", 0,                    \
++      N_("Link with a limited version of the C library") },           \
++    { "ctors-in-init", 0,                     \
++      "" /* undocumented: N_("Link with static constructors and destructors in init") */ },           \
++    { "", TARGET_DEFAULT, 0 }                         \
++}
++
++
++extern const char *nios2_sys_nosys_string;    /* for -msys=nosys */
++extern const char *nios2_sys_lib_string;    /* for -msys-lib= */
++extern const char *nios2_sys_crt0_string;    /* for -msys-crt0= */
++
++#define TARGET_OPTIONS                                        \
++{                                                     \
++  { "sys=nosys",    &nios2_sys_nosys_string,          \
++      N_("Use stub versions of OS library calls (default)"), 0},      \
++  { "sys-lib=",    &nios2_sys_lib_string,             \
++      N_("Name of System Library to link against. (Converted to a -l option)"), 0},   \
++  { "sys-crt0=",    &nios2_sys_crt0_string,           \
++      N_("Name of the startfile. (default is a crt0 for the ISS only)"), 0},  \
++}
++
++
++/* Default target_flags if no switches specified.  */
++#ifndef TARGET_DEFAULT
++# define TARGET_DEFAULT (HAS_MUL_FLAG | CACHE_VOLATILE_FLAG)
++#endif
++
++/* Switch  Recognition by gcc.c.  Add -G xx support */
++#undef  SWITCH_TAKES_ARG
++#define SWITCH_TAKES_ARG(CHAR)                                                \
++  (DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G')
++
++#define OVERRIDE_OPTIONS override_options ()
++#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) optimization_options (LEVEL, SIZE)
++#define CAN_DEBUG_WITHOUT_FP
++ 
++#define CC1_SPEC "\
++%{G*}"
++
++#undef LIB_SPEC
++#define LIB_SPEC \
++"--start-group %{msmallc: -lsmallc} %{!msmallc: -lc} -lgcc \
++ %{msys-lib=*: -l%*} \
++ %{!msys-lib=*: -lc } \
++ --end-group \
++ %{msys-lib=: %eYou need a library name for -msys-lib=} \
++"
++
++
++#undef STARTFILE_SPEC 
++#define STARTFILE_SPEC  \
++"%{msys-crt0=*: %*} %{!msys-crt0=*: crt1%O%s} \
++ %{msys-crt0=: %eYou need a C startup file for -msys-crt0=} \
++ %{mctors-in-init: crti%O%s crtbegin%O%s} \
++"
++
++#undef ENDFILE_SPEC 
++#define ENDFILE_SPEC \
++ "%{mctors-in-init: crtend%O%s crtn%O%s}"
++
++
++/***********************
++ * Storage Layout
++ ***********************/
++
++#define DEFAULT_SIGNED_CHAR 1
++#define BITS_BIG_ENDIAN 0
++#define BYTES_BIG_ENDIAN 0
++#define WORDS_BIG_ENDIAN 0
++#define BITS_PER_UNIT 8
++#define BITS_PER_WORD 32
++#define UNITS_PER_WORD 4
++#define POINTER_SIZE 32
++#define BIGGEST_ALIGNMENT 32
++#define STRICT_ALIGNMENT 1
++#define FUNCTION_BOUNDARY 32
++#define PARM_BOUNDARY 32
++#define STACK_BOUNDARY 32
++#define PREFERRED_STACK_BOUNDARY 32
++#define MAX_FIXED_MODE_SIZE 64
++
++#define CONSTANT_ALIGNMENT(EXP, ALIGN)                                \
++  ((TREE_CODE (EXP) == STRING_CST)                            \
++   && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
++
++
++/**********************
++ * Layout of Source Language Data Types
++ **********************/
++
++#define INT_TYPE_SIZE 32
++#define SHORT_TYPE_SIZE 16
++#define LONG_TYPE_SIZE 32
++#define LONG_LONG_TYPE_SIZE 64
++#define FLOAT_TYPE_SIZE 32
++#define DOUBLE_TYPE_SIZE 64
++#define LONG_DOUBLE_TYPE_SIZE DOUBLE_TYPE_SIZE
++
++
++/*************************
++ * Condition Code Status
++ ************************/
++
++/* comparison type */
++/* ??? currently only CMP_SI is used */
++enum cmp_type {
++  CMP_SI,                             /* compare four byte integers */
++  CMP_DI,                             /* compare eight byte integers */
++  CMP_SF,                             /* compare single precision floats */
++  CMP_DF,                             /* compare double precision floats */
++  CMP_MAX                             /* max comparison type */
++};
++
++extern GTY(()) rtx branch_cmp[2];     /* operands for compare */
++extern enum cmp_type branch_type;     /* what type of branch to use */
++
++/**********************
++ * Register Usage
++ **********************/
++
++/* ---------------------------------- *
++ * Basic Characteristics of Registers
++ * ---------------------------------- */
++
++/*
++Register Number
++      Register Name
++          Alternate Name
++                Purpose
++0     r0  zero  always zero
++1     r1  at    Assembler Temporary
++2-3   r2-r3     Return Location
++4-7   r4-r7     Register Arguments
++8-15  r8-r15    Caller Saved Registers
++16-22 r16-r22   Callee Saved Registers
++23    r23 sc    Static Chain (Callee Saved)
++                ??? Does $sc want to be caller or callee 
++                saved. If caller, 15, else 23. 
++24    r24       Exception Temporary
++25    r25       Breakpoint Temporary
++26    r26 gp    Global Pointer
++27    r27 sp    Stack Pointer
++28    r28 fp    Frame Pointer
++29    r29 ea    Exception Return Address
++30    r30 ba    Breakpoint Return Address
++31    r31 ra    Return Address
++
++32    ctl0 status
++33    ctl1 estatus STATUS saved by exception ?        
++34    ctl2 bstatus STATUS saved by break ?    
++35    ctl3 ipri    Interrupt Priority Mask ?  
++36    ctl4 ecause  Exception Cause ?  
++
++37         pc   Not an actual register        
++
++38    rap      Return address pointer, this does not
++                   actually exist and will be eliminated
++
++39    fake_fp  Fake Frame Pointer which will always be eliminated.
++40    fake_ap  Fake Argument Pointer which will always be eliminated.
++
++41             First Pseudo Register
++
++
++The definitions for all the hard register numbers
++are located in nios2.md.
++*/
++
++#define FIRST_PSEUDO_REGISTER 41
++#define NUM_ARG_REGS (LAST_ARG_REGNO - FIRST_ARG_REGNO + 1)
++
++
++
++/* also see CONDITIONAL_REGISTER_USAGE */
++#define FIXED_REGISTERS                            \
++    {                                      \
++/*        +0  1  2  3  4  5  6  7  8  9 */   \
++/*   0 */  1, 1, 0, 0, 0, 0, 0, 0, 0, 0,     \
++/*  10 */  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     \
++/*  20 */  0, 0, 0, 0, 1, 1, 1, 1, 0, 1,     \
++/*  30 */  1, 0, 1, 1, 1, 1, 1, 1, 1, 1,     \
++/*  40 */  1,                                \
++    }
++
++/* call used is the same as caller saved
++   + fixed regs + args + ret vals */
++#define CALL_USED_REGISTERS                \
++    {                                              \
++/*        +0  1  2  3  4  5  6  7  8  9 */   \
++/*   0 */  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     \
++/*  10 */  1, 1, 1, 1, 1, 1, 0, 0, 0, 0,     \
++/*  20 */  0, 0, 0, 0, 1, 1, 1, 1, 0, 1,     \
++/*  30 */  1, 0, 1, 1, 1, 1, 1, 1, 1, 1,     \
++/*  40 */  1,                                \
++    }
++
++#define HARD_REGNO_NREGS(REGNO, MODE)            \
++   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)  \
++    / UNITS_PER_WORD)
++
++/* --------------------------- *
++ * How Values Fit in Registers
++ * --------------------------- */
++
++#define HARD_REGNO_MODE_OK(REGNO, MODE) 1
++
++#define MODES_TIEABLE_P(MODE1, MODE2) 1
++
++
++/*************************
++ * Register Classes
++ *************************/
++
++enum reg_class
++{
++    NO_REGS,
++    ALL_REGS,
++    LIM_REG_CLASSES
++};
++
++#define N_REG_CLASSES (int) LIM_REG_CLASSES
++
++#define REG_CLASS_NAMES   \
++    {"NO_REGS",           \
++     "ALL_REGS"}
++
++#define GENERAL_REGS ALL_REGS
++
++#define REG_CLASS_CONTENTS   \
++/* NO_REGS  */       {{ 0, 0},     \
++/* ALL_REGS */        {~0,~0}}    \
++
++#define REGNO_REG_CLASS(REGNO) ALL_REGS
++
++#define BASE_REG_CLASS ALL_REGS
++#define INDEX_REG_CLASS ALL_REGS
++
++/* only one reg class, 'r', is handled automatically */
++#define REG_CLASS_FROM_LETTER(CHAR) NO_REGS
++
++#define REGNO_OK_FOR_BASE_P2(REGNO, STRICT) \
++    ((STRICT) \
++     ? (REGNO) < FIRST_PSEUDO_REGISTER \
++     : (REGNO) < FIRST_PSEUDO_REGISTER || (reg_renumber && reg_renumber[REGNO] < FIRST_PSEUDO_REGISTER))
++
++#define REGNO_OK_FOR_INDEX_P2(REGNO, STRICT) \
++    (REGNO_OK_FOR_BASE_P2 (REGNO, STRICT))
++
++#define REGNO_OK_FOR_BASE_P(REGNO) \
++    (REGNO_OK_FOR_BASE_P2 (REGNO, 1))
++
++#define REGNO_OK_FOR_INDEX_P(REGNO) \
++    (REGNO_OK_FOR_INDEX_P2 (REGNO, 1))
++
++#define REG_OK_FOR_BASE_P2(X, STRICT)                                   \
++    (STRICT                                                             \
++     ? REGNO_OK_FOR_BASE_P2 (REGNO (X), 1)                              \
++     : REGNO_OK_FOR_BASE_P2 (REGNO (X), 1) || REGNO(X) >= FIRST_PSEUDO_REGISTER)
++
++#define REG_OK_FOR_INDEX_P2(X, STRICT)                                  \
++    (STRICT                                                             \
++     ? REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1)                             \
++     : REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1) || REGNO(X) >= FIRST_PSEUDO_REGISTER)
++
++#define CLASS_MAX_NREGS(CLASS, MODE)             \
++   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)  \
++    / UNITS_PER_WORD)
++
++
++#define SMALL_INT(X) ((unsigned HOST_WIDE_INT) ((X) + 0x8000) < 0x10000)
++#define SMALL_INT_UNSIGNED(X) ((unsigned HOST_WIDE_INT) (X) < 0x10000)
++#define UPPER16_INT(X) (((X) & 0xffff) == 0)
++#define SHIFT_INT(X) ((X) >= 0 && (X) <= 31)
++#define RDWRCTL_INT(X) ((X) >= 0 && (X) <= 31)
++#define CUSTOM_INSN_OPCODE(X) ((X) >= 0 && (X) <= 255)
++
++#define CONST_OK_FOR_LETTER_P(VALUE, C)                       \
++ (                                                    \
++  (C) == 'I' ? SMALL_INT (VALUE) :                    \
++  (C) == 'J' ? SMALL_INT_UNSIGNED (VALUE) :           \
++  (C) == 'K' ? UPPER16_INT (VALUE) :                  \
++  (C) == 'L' ? SHIFT_INT (VALUE) :                    \
++  (C) == 'M' ? (VALUE) == 0 :                         \
++  (C) == 'N' ? CUSTOM_INSN_OPCODE (VALUE) :           \
++  (C) == 'O' ? RDWRCTL_INT (VALUE) :                  \
++  0)
++
++#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0
++
++#define PREFERRED_RELOAD_CLASS(X, CLASS) \
++    ((CLASS) == NO_REGS ? GENERAL_REGS : (CLASS))
++
++/* 'S' matches immediates which are in small data 
++   and therefore can be added to gp to create a 
++   32-bit value. */
++#define EXTRA_CONSTRAINT(VALUE, C)            \
++  ((C) == 'S'                                         \
++   && (GET_CODE (VALUE) == SYMBOL_REF)        \
++   && SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (VALUE))
++
++
++
++
++/* Say that the epilogue uses the return address register.  Note that
++   in the case of sibcalls, the values "used by the epilogue" are
++   considered live at the start of the called function.  */
++#define EPILOGUE_USES(REGNO) ((REGNO) == RA_REGNO)
++
++
++#define DEFAULT_MAIN_RETURN  c_expand_return (integer_zero_node)
++
++/**********************************
++ * Trampolines for Nested Functions
++ ***********************************/
++
++#define TRAMPOLINE_TEMPLATE(FILE) \
++    error ("trampolines not yet implemented")
++#define TRAMPOLINE_SIZE 20
++#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
++    error ("trampolines not yet implemented")
++
++/***************************
++ * Stack Layout and Calling Conventions
++ ***************************/
++
++/* ------------------ *
++ * Basic Stack Layout
++ * ------------------ */
++
++/* The downward variants are used by the compiler,
++   the upward ones serve as documentation */
++#define STACK_GROWS_DOWNWARD
++#define FRAME_GROWS_UPWARD
++#define ARGS_GROW_UPWARD
++
++#define STARTING_FRAME_OFFSET current_function_outgoing_args_size
++#define FIRST_PARM_OFFSET(FUNDECL) 0
++
++/* Before the prologue, RA lives in r31.  */
++#define INCOMING_RETURN_ADDR_RTX  gen_rtx_REG (VOIDmode, RA_REGNO)
++
++/* -------------------------------------- *
++ * Registers That Address the Stack Frame
++ * -------------------------------------- */
++
++#define STACK_POINTER_REGNUM SP_REGNO
++#define STATIC_CHAIN_REGNUM SC_REGNO
++#define PC_REGNUM PC_REGNO
++#define DWARF_FRAME_RETURN_COLUMN RA_REGNO
++
++/* Base register for access to local variables of the function.  We
++   pretend that the frame pointer is a non-existent hard register, and 
++   then eliminate it to HARD_FRAME_POINTER_REGNUM. */
++#define FRAME_POINTER_REGNUM FAKE_FP_REGNO
++
++#define HARD_FRAME_POINTER_REGNUM FP_REGNO
++#define RETURN_ADDRESS_POINTER_REGNUM RAP_REGNO
++/* the argumnet pointer needs to always be eliminated
++   so it is set to a fake hard register. */
++#define ARG_POINTER_REGNUM FAKE_AP_REGNO
++
++/* ----------------------------------------- *
++ * Eliminating Frame Pointer and Arg Pointer
++ * ----------------------------------------- */
++
++#define FRAME_POINTER_REQUIRED 0
++
++#define ELIMINABLE_REGS                                                       \
++{{ ARG_POINTER_REGNUM,   STACK_POINTER_REGNUM},                               \
++ { ARG_POINTER_REGNUM,   HARD_FRAME_POINTER_REGNUM},                  \
++ { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM},              \
++ { RETURN_ADDRESS_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},         \
++ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},                               \
++ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
++
++#define CAN_ELIMINATE(FROM, TO)       1
++
++#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
++      (OFFSET) = nios2_initial_elimination_offset ((FROM), (TO))
++
++#define MUST_SAVE_REGISTER(regno) \
++ ((regs_ever_live[regno] && !call_used_regs[regno])                   \
++  || (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)     \
++  || (regno == RA_REGNO && regs_ever_live[RA_REGNO]))
++
++/* Treat LOC as a byte offset from the stack pointer and round it up
++   to the next fully-aligned offset.  */
++#define STACK_ALIGN(LOC)                                              \
++  (((LOC) + ((PREFERRED_STACK_BOUNDARY / 8) - 1)) & ~((PREFERRED_STACK_BOUNDARY / 8) - 1))
++
++
++/* ------------------------------ *
++ * Passing Arguments in Registers
++ * ------------------------------ */
++
++/* see nios2.c */
++#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
++  (function_arg (&CUM, MODE, TYPE, NAMED))
++
++#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
++  (function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED))
++
++#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) 0
++
++#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) 0
++
++typedef struct nios2_args
++{
++    int regs_used;
++} CUMULATIVE_ARGS;
++
++/* This is to initialize the above unused CUM data type */
++#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
++    (init_cumulative_args (&CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS))
++
++#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
++    (function_arg_advance (&CUM, MODE, TYPE, NAMED))
++
++#define FUNCTION_ARG_REGNO_P(REGNO) \
++    ((REGNO) >= FIRST_ARG_REGNO && (REGNO) <= LAST_ARG_REGNO)
++
++#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL)   \
++  {                                                               \
++    int pret_size = nios2_setup_incoming_varargs (&(CUM), (MODE),         \
++                                              (TYPE), (NO_RTL));  \
++    if (pret_size)                                                \
++      (PRETEND_SIZE) = pret_size;                                 \
++  }
++
++/* ----------------------------- *
++ * Generating Code for Profiling
++ * ----------------------------- */
++
++#define PROFILE_BEFORE_PROLOGUE
++
++#define FUNCTION_PROFILER(FILE, LABELNO) \
++  function_profiler ((FILE), (LABELNO))
++
++/* --------------------------------------- *
++ * Passing Function Arguments on the Stack
++ * --------------------------------------- */
++
++#define PROMOTE_PROTOTYPES 1
++
++#define PUSH_ARGS 0
++#define ACCUMULATE_OUTGOING_ARGS 1
++
++#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACKSIZE) 0
++
++/* --------------------------------------- *
++ * How Scalar Function Values Are Returned
++ * --------------------------------------- */
++
++#define FUNCTION_VALUE(VALTYPE, FUNC) \
++    gen_rtx(REG, TYPE_MODE(VALTYPE), FIRST_RETVAL_REGNO)
++
++#define LIBCALL_VALUE(MODE) \
++    gen_rtx(REG, MODE, FIRST_RETVAL_REGNO)
++
++#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == FIRST_RETVAL_REGNO)
++
++/* ----------------------------- *
++ * How Large Values Are Returned
++ * ----------------------------- */
++
++
++#define RETURN_IN_MEMORY(TYPE)        \
++  nios2_return_in_memory (TYPE)
++
++
++#define STRUCT_VALUE 0
++
++#define DEFAULT_PCC_STRUCT_RETURN 0
++
++/*******************
++ * Addressing Modes
++ *******************/
++
++
++#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)
++
++#define CONSTANT_ADDRESS_P(X) (CONSTANT_P (X))
++
++#define MAX_REGS_PER_ADDRESS 1
++
++/* Go to ADDR if X is a valid address.  */
++#ifndef REG_OK_STRICT
++#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)        \
++    {                                                  \
++        if (nios2_legitimate_address ((X), (MODE), 0))  \
++            goto ADDR;                                 \
++    }
++#else
++#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)        \
++    {                                                  \
++        if (nios2_legitimate_address ((X), (MODE), 1))  \
++            goto ADDR;                                 \
++    }
++#endif
++
++#ifndef REG_OK_STRICT
++#define REG_OK_FOR_BASE_P(X)   REGNO_OK_FOR_BASE_P2 (REGNO (X), 0)
++#define REG_OK_FOR_INDEX_P(X)  REGNO_OK_FOR_INDEX_P2 (REGNO (X), 0)
++#else
++#define REG_OK_FOR_BASE_P(X)   REGNO_OK_FOR_BASE_P2 (REGNO (X), 1)
++#define REG_OK_FOR_INDEX_P(X)  REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1)
++#endif
++
++#define LEGITIMATE_CONSTANT_P(X) 1
++
++/* Nios II has no mode dependent addresses.  */
++#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
++
++/* Set if this has a weak declaration  */
++#define SYMBOL_FLAG_WEAK_DECL (1 << SYMBOL_FLAG_MACH_DEP_SHIFT)
++#define SYMBOL_REF_WEAK_DECL_P(RTX) \
++  ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_WEAK_DECL) != 0)
++
++
++/* true if a symbol is both small and not weak. In this case, gp
++   relative access can be used */
++#define SYMBOL_REF_IN_NIOS2_SMALL_DATA_P(RTX) \
++   (SYMBOL_REF_SMALL_P(RTX) && !SYMBOL_REF_WEAK_DECL_P(RTX))
++
++/*****************
++ * Describing Relative Costs of Operations
++ *****************/
++
++#define SLOW_BYTE_ACCESS 1
++
++/* It is as good to call a constant function address as to call an address
++   kept in a register.
++   ??? Not true anymore really. Now that call cannot address full range
++   of memory callr may need to be used */
++
++#define NO_FUNCTION_CSE
++#define NO_RECURSIVE_FUNCTION_CSE
++
++
++
++/*****************************************
++ * Defining the Output Assembler Language
++ *****************************************/
++
++/* ------------------------------------------ *
++ * The Overall Framework of an Assembler File
++ * ------------------------------------------ */
++
++#define ASM_APP_ON "#APP\n"
++#define ASM_APP_OFF "#NO_APP\n"
++
++#define ASM_COMMENT_START "# "
++
++/* ------------------------------- *
++ * Output and Generation of Labels
++ * ------------------------------- */
++
++#define GLOBAL_ASM_OP "\t.global\t"
++
++
++/* -------------- *
++ * Output of Data
++ * -------------- */
++
++#define DWARF2_UNWIND_INFO 0
++
++
++/* -------------------------------- *
++ * Assembler Commands for Alignment
++ * -------------------------------- */
++
++#define ASM_OUTPUT_ALIGN(FILE, LOG) \
++  do { \
++    fprintf ((FILE), "%s%d\n", ALIGN_ASM_OP, (LOG)); \
++  } while (0)
++
++
++/* -------------------------------- *
++ * Output of Assembler Instructions
++ * -------------------------------- */
++
++#define REGISTER_NAMES \
++{ \
++    "zero", \
++    "at", \
++    "r2", \
++    "r3", \
++    "r4", \
++    "r5", \
++    "r6", \
++    "r7", \
++    "r8", \
++    "r9", \
++    "r10", \
++    "r11", \
++    "r12", \
++    "r13", \
++    "r14", \
++    "r15", \
++    "r16", \
++    "r17", \
++    "r18", \
++    "r19", \
++    "r20", \
++    "r21", \
++    "r22", \
++    "r23", \
++    "r24", \
++    "r25", \
++    "gp", \
++    "sp", \
++    "fp", \
++    "ta", \
++    "ba", \
++    "ra", \
++    "status", \
++    "estatus", \
++    "bstatus", \
++    "ipri", \
++    "ecause", \
++    "pc", \
++    "rap", \
++    "fake_fp", \
++    "fake_ap", \
++}
++
++#define ASM_OUTPUT_OPCODE(STREAM, PTR)\
++   (PTR) = asm_output_opcode (STREAM, PTR)
++
++#define PRINT_OPERAND(STREAM, X, CODE) \
++    nios2_print_operand (STREAM, X, CODE)
++
++#define PRINT_OPERAND_ADDRESS(STREAM, X) \
++    nios2_print_operand_address (STREAM, X)
++
++#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)  \
++do { fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), FILE); \
++     fprintf (FILE, ".L%u\n", (unsigned) (VALUE));               \
++   } while (0)
++
++
++/* ------------ *
++ * Label Output
++ * ------------ */
++
++
++/* ---------------------------------------------------- *
++ * Dividing the Output into Sections (Texts, Data, ...)
++ * ---------------------------------------------------- */
++
++/* Output before read-only data.  */
++#define TEXT_SECTION_ASM_OP ("\t.section\t.text")
++
++/* Output before writable data.  */
++#define DATA_SECTION_ASM_OP ("\t.section\t.data")
++
++
++/* Default the definition of "small data" to 8 bytes. */
++/* ??? How come I can't use HOST_WIDE_INT here? */
++extern unsigned long nios2_section_threshold;
++#define NIOS2_DEFAULT_GVALUE 8
++
++
++
++/* 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.  */
++
++#undef COMMON_ASM_OP
++#define COMMON_ASM_OP "\t.comm\t"
++
++#undef  ASM_OUTPUT_ALIGNED_COMMON
++#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN)            \
++do                                                                    \
++{                                                                     \
++  if ((SIZE) <= nios2_section_threshold)                              \
++    {                                                                 \
++      named_section (0, ".sbss", 0);                                  \
++      (*targetm.asm_out.globalize_label) (FILE, NAME);                        \
++      ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object");                       \
++      if (!flag_inhibit_size_directive)                                       \
++      ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE);                   \
++      ASM_OUTPUT_ALIGN ((FILE), exact_log2((ALIGN) / BITS_PER_UNIT)); \
++      ASM_OUTPUT_LABEL(FILE, NAME);                                   \
++      ASM_OUTPUT_SKIP((FILE), (SIZE) ? (SIZE) : 1);                   \
++    }                                                                 \
++  else                                                                        \
++    {                                                                 \
++      fprintf ((FILE), "%s", COMMON_ASM_OP);                          \
++      assemble_name ((FILE), (NAME));                                 \
++      fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT);      \
++    }                                                                 \
++}                                                                     \
++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.  */
++
++#undef  ASM_OUTPUT_ALIGNED_LOCAL
++#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN)             \
++do {                                                                  \
++  if ((SIZE) <= nios2_section_threshold)                              \
++    named_section (0, ".sbss", 0);                                    \
++  else                                                                        \
++    named_section (0, ".bss", 0);                                     \
++  ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object");                   \
++  if (!flag_inhibit_size_directive)                                   \
++    ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE);                     \
++  ASM_OUTPUT_ALIGN ((FILE), exact_log2((ALIGN) / BITS_PER_UNIT));     \
++  ASM_OUTPUT_LABEL(FILE, NAME);                                               \
++  ASM_OUTPUT_SKIP((FILE), (SIZE) ? (SIZE) : 1);                               \
++} while (0)
++
++
++
++/***************************
++ * Miscellaneous Parameters
++ ***************************/
++
++#define MOVE_MAX 4
++
++#define Pmode SImode
++#define FUNCTION_MODE QImode
++
++#define CASE_VECTOR_MODE Pmode
++
++#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
++
++#define LOAD_EXTEND_OP(MODE) (ZERO_EXTEND)
++
++#define WORD_REGISTER_OPERATIONS
+--- gcc-3.4.3/gcc/config/nios2/nios2.md
++++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.md
+@@ -0,0 +1,2078 @@
++;; Machine Description for Altera NIOS 2G NIOS2 version.
++;;    Copyright (C) 2003 Altera 
++;;    Contributed by Jonah Graham (jgraham@altera.com).
++;; 
++;; This file is part of GNU CC.
++;; 
++;; GNU CC is free software; you can redistribute it and/or modify
++;; it under the terms of the GNU General Public License as published by
++;; the Free Software Foundation; either version 2, or (at your option)
++;; any later version.
++;; 
++;; GNU CC is distributed in the hope that it will be useful,
++;; but WITHOUT ANY WARRANTY; without even the implied warranty of
++;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++;; GNU General Public License for more details.
++;; 
++;; You should have received a copy of the GNU General Public License
++;; along with GNU CC; see the file COPYING.  If not, write to
++;; the Free Software Foundation, 59 Temple Place - Suite 330,
++;; Boston, MA 02111-1307, USA.  */
++
++
++\f
++;*****************************************************************************
++;*
++;* constants
++;*
++;*****************************************************************************
++(define_constants [
++  (GP_REGNO 26)
++  (SP_REGNO 27)
++  (FP_REGNO 28)
++  (RA_REGNO 31)
++  (RAP_REGNO 38)
++  (FIRST_RETVAL_REGNO 2)
++  (LAST_RETVAL_REGNO 3)
++  (FIRST_ARG_REGNO 4)
++  (LAST_ARG_REGNO 7)
++  (SC_REGNO 23)
++  (PC_REGNO 37)
++  (FAKE_FP_REGNO 39)
++  (FAKE_AP_REGNO 40)
++
++
++  (UNSPEC_BLOCKAGE 0)
++  (UNSPEC_LDBIO 1)
++  (UNSPEC_LDBUIO 2)
++  (UNSPEC_LDHIO 3)
++  (UNSPEC_LDHUIO 4)
++  (UNSPEC_LDWIO 5)
++  (UNSPEC_STBIO 6)
++  (UNSPEC_STHIO 7)
++  (UNSPEC_STWIO 8)
++  (UNSPEC_SYNC 9)
++  (UNSPEC_WRCTL 10)
++  (UNSPEC_RDCTL 11)
++  
++])
++
++
++\f
++;*****************************************************************************
++;*
++;* instruction scheduler
++;*
++;*****************************************************************************
++
++; No schedule info is currently available, using an assumption that no
++; instruction can use the results of the previous instruction without
++; incuring a stall.
++
++; length of an instruction (in bytes)
++(define_attr "length" "" (const_int 4))
++(define_attr "type" "unknown,complex,control,alu,cond_alu,st,ld,shift,mul,div,custom" (const_string "complex"))
++
++(define_asm_attributes
++ [(set_attr "length" "4")
++  (set_attr "type" "complex")])
++
++(define_automaton "nios2")
++(automata_option "v")
++;(automata_option "no-minimization")
++(automata_option "ndfa")
++
++; The nios2 pipeline is fairly straightforward for the fast model.
++; Every alu operation is pipelined so that an instruction can
++; be issued every cycle. However, there are still potential
++; stalls which this description tries to deal with.
++
++(define_cpu_unit "cpu" "nios2")
++
++(define_insn_reservation "complex" 1
++  (eq_attr "type" "complex")
++  "cpu")
++
++(define_insn_reservation "control" 1
++  (eq_attr "type" "control")
++  "cpu")
++
++(define_insn_reservation "alu" 1
++  (eq_attr "type" "alu")
++  "cpu")
++
++(define_insn_reservation "cond_alu" 1
++  (eq_attr "type" "cond_alu")
++  "cpu")
++
++(define_insn_reservation "st" 1
++  (eq_attr "type" "st")
++  "cpu")
++  
++(define_insn_reservation "custom" 1
++  (eq_attr "type" "custom")
++  "cpu")
++
++; shifts, muls and lds have three cycle latency
++(define_insn_reservation "ld" 3
++  (eq_attr "type" "ld")
++  "cpu")
++
++(define_insn_reservation "shift" 3
++  (eq_attr "type" "shift")
++  "cpu")
++
++(define_insn_reservation "mul" 3
++  (eq_attr "type" "mul")
++  "cpu")
++
++(define_insn_reservation "div" 1
++  (eq_attr "type" "div")
++  "cpu")
++
++\f
++;*****************************************************************************
++;*
++;* MOV Instructions
++;*
++;*****************************************************************************
++
++(define_expand "movqi"
++  [(set (match_operand:QI 0 "nonimmediate_operand" "")
++        (match_operand:QI 1 "general_operand" ""))]
++  ""
++{
++  if (nios2_emit_move_sequence (operands, QImode))
++    DONE;
++})
++
++(define_insn "movqi_internal"
++  [(set (match_operand:QI 0 "nonimmediate_operand" "=m, r,r, r")
++        (match_operand:QI 1 "general_operand"       "rM,m,rM,I"))]
++  "(register_operand (operands[0], QImode)
++    || register_operand (operands[1], QImode)
++    || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
++  "@
++    stb%o0\\t%z1, %0
++    ldbu%o1\\t%0, %1
++    mov\\t%0, %z1
++    movi\\t%0, %1"
++  [(set_attr "type" "st,ld,alu,alu")])
++
++(define_insn "ldbio"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (unspec_volatile:SI [(const_int 0)] UNSPEC_LDBIO))
++   (use (match_operand:SI 1 "memory_operand" "m"))]
++  ""
++  "ldbio\\t%0, %1"
++  [(set_attr "type" "ld")])
++
++(define_insn "ldbuio"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (unspec_volatile:SI [(const_int 0)] UNSPEC_LDBUIO))
++   (use (match_operand:SI 1 "memory_operand" "m"))]
++  ""
++  "ldbuio\\t%0, %1"
++  [(set_attr "type" "ld")])
++
++(define_insn "stbio"
++  [(set (match_operand:SI 0 "memory_operand" "=m")
++      (match_operand:SI 1 "register_operand"   "r"))
++   (unspec_volatile:SI [(const_int 0)] UNSPEC_STBIO)]
++  ""
++  "stbio\\t%z1, %0"
++  [(set_attr "type" "st")])
++
++
++(define_expand "movhi"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "")
++        (match_operand:HI 1 "general_operand" ""))]
++  ""
++{
++  if (nios2_emit_move_sequence (operands, HImode))
++    DONE;
++})
++
++(define_insn "movhi_internal"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "=m, r,r, r,r")
++        (match_operand:HI 1 "general_operand"       "rM,m,rM,I,J"))]
++  "(register_operand (operands[0], HImode)
++    || register_operand (operands[1], HImode)
++    || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
++  "@
++    sth%o0\\t%z1, %0
++    ldhu%o1\\t%0, %1
++    mov\\t%0, %z1
++    movi\\t%0, %1
++    movui\\t%0, %1"
++  [(set_attr "type" "st,ld,alu,alu,alu")])
++
++(define_insn "ldhio"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (unspec_volatile:SI [(const_int 0)] UNSPEC_LDHIO))
++   (use (match_operand:SI 1 "memory_operand" "m"))]
++  ""
++  "ldhio\\t%0, %1"
++  [(set_attr "type" "ld")])
++
++(define_insn "ldhuio"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (unspec_volatile:SI [(const_int 0)] UNSPEC_LDHUIO))
++   (use (match_operand:SI 1 "memory_operand" "m"))]
++  ""
++  "ldhuio\\t%0, %1"
++  [(set_attr "type" "ld")])
++
++(define_insn "sthio"
++  [(set (match_operand:SI 0 "memory_operand" "=m")
++      (match_operand:SI 1 "register_operand"   "r"))
++   (unspec_volatile:SI [(const_int 0)] UNSPEC_STHIO)]
++  ""
++  "sthio\\t%z1, %0"
++  [(set_attr "type" "st")])
++
++(define_expand "movsi"
++  [(set (match_operand:SI 0 "nonimmediate_operand" "")
++        (match_operand:SI 1 "general_operand" ""))]
++  ""
++{
++  if (nios2_emit_move_sequence (operands, SImode))
++    DONE;
++})
++
++(define_insn "movsi_internal"
++  [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r, r,r,r,r")
++        (match_operand:SI 1 "general_operand"       "rM,m,rM,I,J,S,i"))]
++  "(register_operand (operands[0], SImode)
++    || register_operand (operands[1], SImode)
++    || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
++  "@
++    stw%o0\\t%z1, %0
++    ldw%o1\\t%0, %1
++    mov\\t%0, %z1
++    movi\\t%0, %1
++    movui\\t%0, %1
++    addi\\t%0, gp, %%gprel(%1)
++    movhi\\t%0, %H1\;addi\\t%0, %0, %L1"
++  [(set_attr "type" "st,ld,alu,alu,alu,alu,alu")])
++
++(define_insn "ldwio"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (unspec_volatile:SI [(const_int 0)] UNSPEC_LDWIO))
++   (use (match_operand:SI 1 "memory_operand" "m"))]
++  ""
++  "ldwio\\t%0, %1"
++  [(set_attr "type" "ld")])
++
++(define_insn "stwio"
++  [(set (match_operand:SI 0 "memory_operand" "=m")
++      (match_operand:SI 1 "register_operand"   "r"))
++   (unspec_volatile:SI [(const_int 0)] UNSPEC_STWIO)]
++  ""
++  "stwio\\t%z1, %0"
++  [(set_attr "type" "st")])
++
++
++\f
++;*****************************************************************************
++;*
++;* zero extension
++;*
++;*****************************************************************************
++
++
++(define_insn "zero_extendhisi2"
++  [(set (match_operand:SI 0 "register_operand" "=r,r")
++      (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
++  ""
++  "@
++    andi\\t%0, %1, 0xffff
++    ldhu%o1\\t%0, %1"
++  [(set_attr "type"   "alu,ld")])
++
++(define_insn "zero_extendqihi2"
++  [(set (match_operand:HI 0 "register_operand" "=r,r")
++      (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
++  ""
++  "@
++    andi\\t%0, %1, 0xff
++    ldbu%o1\\t%0, %1"
++  [(set_attr "type"   "alu,ld")])
++
++(define_insn "zero_extendqisi2"
++  [(set (match_operand:SI 0 "register_operand" "=r,r")
++      (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
++  ""
++  "@
++    andi\\t%0, %1, 0xff
++    ldbu%o1\\t%0, %1"
++  [(set_attr "type"   "alu,ld")])
++
++
++\f
++;*****************************************************************************
++;*
++;* sign extension
++;*
++;*****************************************************************************
++
++(define_expand "extendhisi2"
++  [(set (match_operand:SI 0 "register_operand" "")
++      (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
++  ""
++{
++  if (optimize && GET_CODE (operands[1]) == MEM)
++    operands[1] = force_not_mem (operands[1]);
++
++  if (GET_CODE (operands[1]) != MEM)
++    {
++      rtx op1   = gen_lowpart (SImode, operands[1]);
++      rtx temp  = gen_reg_rtx (SImode);
++      rtx shift = GEN_INT (16);
++
++      emit_insn (gen_ashlsi3 (temp, op1, shift));
++      emit_insn (gen_ashrsi3 (operands[0], temp, shift));
++      DONE;
++    }
++})
++
++(define_insn "extendhisi2_internal"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
++  ""
++  "ldh%o1\\t%0, %1"
++  [(set_attr "type"   "ld")])
++
++(define_expand "extendqihi2"
++  [(set (match_operand:HI 0 "register_operand" "")
++      (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))]
++  ""
++{
++  if (optimize && GET_CODE (operands[1]) == MEM)
++    operands[1] = force_not_mem (operands[1]);
++
++  if (GET_CODE (operands[1]) != MEM)
++    {
++      rtx op0   = gen_lowpart (SImode, operands[0]);
++      rtx op1   = gen_lowpart (SImode, operands[1]);
++      rtx temp  = gen_reg_rtx (SImode);
++      rtx shift = GEN_INT (24);
++
++      emit_insn (gen_ashlsi3 (temp, op1, shift));
++      emit_insn (gen_ashrsi3 (op0, temp, shift));
++      DONE;
++    }
++})
++
++(define_insn "extendqihi2_internal"
++  [(set (match_operand:HI 0 "register_operand" "=r")
++      (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
++  ""
++  "ldb%o1\\t%0, %1"
++  [(set_attr "type"   "ld")])
++
++
++(define_expand "extendqisi2"
++  [(set (match_operand:SI 0 "register_operand" "")
++      (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
++  ""
++{
++  if (optimize && GET_CODE (operands[1]) == MEM)
++    operands[1] = force_not_mem (operands[1]);
++
++  if (GET_CODE (operands[1]) != MEM)
++    {
++      rtx op1   = gen_lowpart (SImode, operands[1]);
++      rtx temp  = gen_reg_rtx (SImode);
++      rtx shift = GEN_INT (24);
++
++      emit_insn (gen_ashlsi3 (temp, op1, shift));
++      emit_insn (gen_ashrsi3 (operands[0], temp, shift));
++      DONE;
++    }
++})
++
++(define_insn "extendqisi2_insn"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
++  ""
++  "ldb%o1\\t%0, %1"
++  [(set_attr "type"   "ld")])
++
++
++\f
++;*****************************************************************************
++;*
++;* Arithmetic Operations
++;*
++;*****************************************************************************
++
++(define_insn "addsi3"
++  [(set (match_operand:SI 0 "register_operand"          "=r,r")
++        (plus:SI (match_operand:SI 1 "register_operand" "%r,r")
++                 (match_operand:SI 2 "arith_operand"     "r,I")))]
++  ""
++  "add%i2\\t%0, %1, %z2"
++  [(set_attr "type" "alu")])
++
++(define_insn "subsi3"
++  [(set (match_operand:SI 0 "register_operand"           "=r")
++        (minus:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
++                  (match_operand:SI 2 "register_operand"  "r")))]
++  ""
++  "sub\\t%0, %z1, %2"
++  [(set_attr "type" "alu")])
++
++(define_insn "mulsi3"
++  [(set (match_operand:SI 0 "register_operand"            "=r,r")
++        (mult:SI (match_operand:SI 1 "register_operand"    "r,r")
++                 (match_operand:SI 2 "arith_operand"       "r,I")))]
++  "TARGET_HAS_MUL"
++  "mul%i2\\t%0, %1, %z2"
++  [(set_attr "type" "mul")])
++
++(define_expand "divsi3"
++  [(set (match_operand:SI 0 "register_operand"            "=r")
++        (div:SI (match_operand:SI 1 "register_operand"     "r")
++                (match_operand:SI 2 "register_operand"     "r")))]
++  ""
++{
++  if (!TARGET_HAS_DIV)
++    {
++      if (!TARGET_FAST_SW_DIV)
++      FAIL;
++      else
++        {
++        if (nios2_emit_expensive_div (operands, SImode))
++          DONE;
++      }
++    }
++})
++
++(define_insn "divsi3_insn"
++  [(set (match_operand:SI 0 "register_operand"            "=r")
++        (div:SI (match_operand:SI 1 "register_operand"     "r")
++                (match_operand:SI 2 "register_operand"     "r")))]
++  "TARGET_HAS_DIV"
++  "div\\t%0, %1, %2"
++  [(set_attr "type" "div")])
++
++(define_insn "udivsi3"
++  [(set (match_operand:SI 0 "register_operand"            "=r")
++        (udiv:SI (match_operand:SI 1 "register_operand"     "r")
++                (match_operand:SI 2 "register_operand"     "r")))]
++  "TARGET_HAS_DIV"
++  "divu\\t%0, %1, %2"
++  [(set_attr "type" "div")])
++
++(define_insn "smulsi3_highpart"
++  [(set (match_operand:SI 0 "register_operand"                            "=r")
++      (truncate:SI
++       (lshiftrt:DI
++        (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand"  "r"))
++                 (sign_extend:DI (match_operand:SI 2 "register_operand"  "r")))
++        (const_int 32))))]
++  "TARGET_HAS_MULX"
++  "mulxss\\t%0, %1, %2"
++  [(set_attr "type" "mul")])
++
++(define_insn "umulsi3_highpart"
++  [(set (match_operand:SI 0 "register_operand"                            "=r")
++      (truncate:SI
++       (lshiftrt:DI
++        (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"  "r"))
++                 (zero_extend:DI (match_operand:SI 2 "register_operand"  "r")))
++        (const_int 32))))]
++  "TARGET_HAS_MULX"
++  "mulxuu\\t%0, %1, %2"
++  [(set_attr "type" "mul")])
++
++
++(define_expand "mulsidi3"
++    [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0)
++        (mult:SI (match_operand:SI 1 "register_operand" "")
++                 (match_operand:SI 2 "register_operand" "")))
++     (set (subreg:SI (match_dup 0) 4)
++        (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
++                                           (sign_extend:DI (match_dup 2)))
++                                  (const_int 32))))]
++  "TARGET_HAS_MULX"
++  "")
++
++(define_expand "umulsidi3"
++    [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0)
++        (mult:SI (match_operand:SI 1 "register_operand" "")
++                 (match_operand:SI 2 "register_operand" "")))
++     (set (subreg:SI (match_dup 0) 4)
++        (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
++                                           (zero_extend:DI (match_dup 2)))
++                                  (const_int 32))))]
++  "TARGET_HAS_MULX"
++  "")
++
++
++\f
++;*****************************************************************************
++;*
++;* Negate and ones complement
++;*
++;*****************************************************************************
++
++(define_insn "negsi2"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++      (neg:SI (match_operand:SI 1 "register_operand" "r")))]
++  ""
++{
++  operands[2] = const0_rtx;
++  return "sub\\t%0, %z2, %1";
++}
++  [(set_attr "type" "alu")])
++
++(define_insn "one_cmplsi2"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++      (not:SI (match_operand:SI 1 "register_operand" "r")))]
++  ""
++{
++  operands[2] = const0_rtx;
++  return "nor\\t%0, %z2, %1";
++}
++  [(set_attr "type" "alu")])
++
++
++
++; Logical Operantions
++
++(define_insn "andsi3"
++  [(set (match_operand:SI 0 "register_operand"         "=r, r,r")
++        (and:SI (match_operand:SI 1 "register_operand" "%r, r,r")
++                (match_operand:SI 2 "logical_operand"   "rM,J,K")))]
++  ""
++  "@
++    and\\t%0, %1, %z2
++    and%i2\\t%0, %1, %2
++    andh%i2\\t%0, %1, %U2"
++  [(set_attr "type" "alu")])
++
++(define_insn "iorsi3"
++  [(set (match_operand:SI 0 "register_operand"          "=r, r,r")
++        (ior:SI (match_operand:SI 1 "register_operand"  "%r, r,r")
++                (match_operand:SI 2 "logical_operand"    "rM,J,K")))]
++  ""
++  "@
++    or\\t%0, %1, %z2
++    or%i2\\t%0, %1, %2
++    orh%i2\\t%0, %1, %U2"
++  [(set_attr "type" "alu")])
++
++(define_insn "*norsi3"
++  [(set (match_operand:SI 0 "register_operand"                  "=r")
++        (and:SI (not:SI (match_operand:SI 1 "register_operand"  "%r"))
++                (not:SI (match_operand:SI 2 "reg_or_0_operand"   "rM"))))]
++  ""
++  "nor\\t%0, %1, %z2"
++  [(set_attr "type" "alu")])
++
++(define_insn "xorsi3"
++  [(set (match_operand:SI 0 "register_operand"          "=r, r,r")
++        (xor:SI (match_operand:SI 1 "register_operand"  "%r, r,r")
++                (match_operand:SI 2 "logical_operand"    "rM,J,K")))]
++  ""
++  "@
++    xor\\t%0, %1, %z2
++    xor%i2\\t%0, %1, %2
++    xorh%i2\\t%0, %1, %U2"
++  [(set_attr "type" "alu")])
++
++
++\f
++;*****************************************************************************
++;*
++;* Shifts
++;*
++;*****************************************************************************
++
++(define_insn "ashlsi3"
++  [(set (match_operand:SI 0 "register_operand"           "=r,r")
++      (ashift:SI (match_operand:SI 1 "register_operand" "r,r")
++                 (match_operand:SI 2 "shift_operand"    "r,L")))]
++  ""
++  "sll%i2\\t%0, %1, %z2"
++  [(set_attr "type" "shift")])
++
++(define_insn "ashrsi3"
++  [(set (match_operand:SI 0 "register_operand"             "=r,r")
++      (ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
++                   (match_operand:SI 2 "shift_operand"    "r,L")))]
++  ""
++  "sra%i2\\t%0, %1, %z2"
++  [(set_attr "type" "shift")])
++
++(define_insn "lshrsi3"
++  [(set (match_operand:SI 0 "register_operand"             "=r,r")
++      (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
++                   (match_operand:SI 2 "shift_operand"    "r,L")))]
++  ""
++  "srl%i2\\t%0, %1, %z2"
++  [(set_attr "type" "shift")])
++
++(define_insn "rotlsi3"
++  [(set (match_operand:SI 0 "register_operand"           "=r,r")
++      (rotate:SI (match_operand:SI 1 "register_operand" "r,r")
++                 (match_operand:SI 2 "shift_operand"    "r,L")))]
++  ""
++  "rol%i2\\t%0, %1, %z2"
++  [(set_attr "type" "shift")])
++
++(define_insn "rotrsi3"
++  [(set (match_operand:SI 0 "register_operand"             "=r,r")
++      (rotatert:SI (match_operand:SI 1 "register_operand" "r,r")
++                   (match_operand:SI 2 "register_operand" "r,r")))]
++  ""
++  "ror\\t%0, %1, %2"
++  [(set_attr "type" "shift")])
++
++(define_insn "*shift_mul_constants"
++  [(set (match_operand:SI 0 "register_operand"                     "=r")
++      (ashift:SI (mult:SI (match_operand:SI 1 "register_operand"  "r")
++                          (match_operand:SI 2 "const_int_operand" "I"))
++                 (match_operand:SI 3          "const_int_operand" "I")))]
++  "TARGET_HAS_MUL && SMALL_INT (INTVAL (operands[2]) << INTVAL (operands[3]))"
++{
++  HOST_WIDE_INT mul = INTVAL (operands[2]) << INTVAL (operands[3]);
++  rtx ops[3];
++  
++  ops[0] = operands[0];
++  ops[1] = operands[1];
++  ops[2] = GEN_INT (mul);
++  
++  output_asm_insn ("muli\t%0, %1, %2", ops);
++  return "";
++}
++  [(set_attr "type" "mul")])
++
++
++
++\f
++;*****************************************************************************
++;*
++;* Prologue, Epilogue and Return
++;*
++;*****************************************************************************
++
++(define_expand "prologue"
++  [(const_int 1)]
++  ""
++{
++  expand_prologue ();
++  DONE;
++})
++
++(define_expand "epilogue"
++  [(return)]
++  ""
++{
++  expand_epilogue (false);
++  DONE;
++})
++
++(define_expand "sibcall_epilogue"
++  [(return)]
++  ""
++{
++  expand_epilogue (true);
++  DONE;
++})
++
++(define_insn "return"
++  [(return)]
++  "reload_completed && nios2_can_use_return_insn ()"
++  "ret\\t"
++)
++
++(define_insn "return_from_epilogue"
++  [(use (match_operand 0 "pmode_register_operand" ""))
++   (return)]
++  "reload_completed"
++  "ret\\t"
++)
++
++;; Block any insns from being moved before this point, since the
++;; profiling call to mcount can use various registers that aren't
++;; saved or used to pass arguments.
++
++(define_insn "blockage"
++  [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)]
++  ""
++  ""
++  [(set_attr "type" "unknown")
++   (set_attr "length" "0")])
++
++
++\f
++;*****************************************************************************
++;*
++;* Jumps and Calls
++;*
++;*****************************************************************************
++
++(define_insn "indirect_jump"
++  [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
++  ""
++  "jmp\\t%0"
++  [(set_attr "type" "control")])
++
++(define_insn "jump"
++  [(set (pc)
++        (label_ref (match_operand 0 "" "")))]
++  ""
++  "br\\t%0"
++  [(set_attr "type" "control")])
++
++
++(define_insn "indirect_call"
++  [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
++         (match_operand 1 "" ""))
++   (clobber (reg:SI RA_REGNO))]
++  ""
++  "callr\\t%0"
++  [(set_attr "type" "control")])
++
++(define_insn "indirect_call_value"
++  [(set (match_operand 0 "" "")
++        (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
++              (match_operand 2 "" "")))
++   (clobber (reg:SI RA_REGNO))]
++  ""
++  "callr\\t%1"
++)
++
++(define_expand "call"
++  [(parallel [(call (match_operand 0 "" "")
++                    (match_operand 1 "" ""))
++              (clobber (reg:SI RA_REGNO))])]
++  ""
++  "")
++
++(define_expand "call_value"
++  [(parallel [(set (match_operand 0 "" "")
++                   (call (match_operand 1 "" "")
++                         (match_operand 2 "" "")))
++              (clobber (reg:SI RA_REGNO))])]
++  ""
++  "")
++
++(define_insn "*call"
++  [(call (mem:QI (match_operand:SI 0 "immediate_operand" "i"))
++         (match_operand 1 "" ""))
++   (clobber (match_operand:SI 2 "register_operand" "=r"))]
++  ""
++  "call\\t%0"
++  [(set_attr "type" "control")])
++
++(define_insn "*call_value"
++  [(set (match_operand 0 "" "")
++        (call (mem:QI (match_operand:SI 1 "immediate_operand" "i"))
++              (match_operand 2 "" "")))
++   (clobber (match_operand:SI 3 "register_operand" "=r"))]
++  ""
++  "call\\t%1"
++  [(set_attr "type" "control")])
++
++(define_expand "sibcall"
++  [(parallel [(call (match_operand 0 "" "")
++                  (match_operand 1 "" ""))
++            (return)
++            (use (match_operand 2 "" ""))])]
++  ""
++  {
++    XEXP (operands[0], 0) = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
++
++    if (operands[2] == NULL_RTX)
++      operands[2] = const0_rtx;
++  }
++)
++
++(define_expand "sibcall_value"
++  [(parallel [(set (match_operand 0 "" "")
++                 (call (match_operand 1 "" "")
++                       (match_operand 2 "" "")))
++            (return)
++            (use (match_operand 3 "" ""))])]
++  ""
++  {
++    XEXP (operands[1], 0) = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
++
++    if (operands[3] == NULL_RTX)
++      operands[3] = const0_rtx;
++  }
++)
++
++(define_insn "sibcall_insn"
++ [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
++      (match_operand 1 "" ""))
++  (return)
++  (use (match_operand 2 "" ""))]
++  ""
++  "jmp\\t%0"
++)
++
++(define_insn "sibcall_value_insn"
++ [(set (match_operand 0 "register_operand" "")
++       (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
++           (match_operand 2 "" "")))
++  (return)
++  (use (match_operand 3 "" ""))]
++  ""
++  "jmp\\t%1"
++)
++
++
++
++
++(define_expand "tablejump"
++  [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
++              (use (label_ref (match_operand 1 "" "")))])]
++  ""
++  ""
++)
++
++(define_insn "*tablejump"
++  [(set (pc)
++      (match_operand:SI 0 "register_operand" "r"))
++   (use (label_ref (match_operand 1 "" "")))]
++  ""
++  "jmp\\t%0"
++  [(set_attr "type" "control")])
++
++
++\f
++;*****************************************************************************
++;*
++;* Comparisons
++;*
++;*****************************************************************************
++;; Flow here is rather complex (based on MIPS):
++;;
++;;  1)        The cmp{si,di,sf,df} routine is called.  It deposits the
++;;    arguments into the branch_cmp array, and the type into
++;;    branch_type.  No RTL is generated.
++;;
++;;  2)        The appropriate branch define_expand is called, which then
++;;    creates the appropriate RTL for the comparison and branch.
++;;    Different CC modes are used, based on what type of branch is
++;;    done, so that we can constrain things appropriately.  There
++;;    are assumptions in the rest of GCC that break if we fold the
++;;    operands into the branchs for integer operations, and use cc0
++;;    for floating point, so we use the fp status register instead.
++;;    If needed, an appropriate temporary is created to hold the
++;;    of the integer compare.
++
++(define_expand "cmpsi"
++  [(set (cc0)
++      (compare:CC (match_operand:SI 0 "register_operand" "")
++                  (match_operand:SI 1 "arith_operand" "")))]
++  ""
++{
++  branch_cmp[0] = operands[0];
++  branch_cmp[1] = operands[1];
++  branch_type = CMP_SI;
++  DONE;
++})
++
++(define_expand "tstsi"
++  [(set (cc0)
++      (match_operand:SI 0 "register_operand" ""))]
++  ""
++{
++  branch_cmp[0] = operands[0];
++  branch_cmp[1] = const0_rtx;
++  branch_type = CMP_SI;
++  DONE;
++})
++
++\f
++;*****************************************************************************
++;*
++;* setting a register from a comparison
++;*
++;*****************************************************************************
++
++(define_expand "seq"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (eq:SI (match_dup 1)
++             (match_dup 2)))]
++  ""
++{
++  if (branch_type != CMP_SI)
++    FAIL;
++
++  /* set up operands from compare.  */
++  operands[1] = branch_cmp[0];
++  operands[2] = branch_cmp[1];
++
++  gen_int_relational (EQ, operands[0], operands[1], operands[2], NULL_RTX);
++  DONE;
++})
++
++
++(define_insn "*seq"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++      (eq:SI (match_operand:SI 1 "reg_or_0_operand" "%rM")
++             (match_operand:SI 2 "arith_operand"     "rI")))]
++  ""
++  "cmpeq%i2\\t%0, %z1, %z2"
++  [(set_attr "type" "alu")])
++
++
++(define_expand "sne"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (ne:SI (match_dup 1)
++             (match_dup 2)))]
++  ""
++{
++  if (branch_type != CMP_SI)
++    FAIL;
++
++  /* set up operands from compare.  */
++  operands[1] = branch_cmp[0];
++  operands[2] = branch_cmp[1];
++
++  gen_int_relational (NE, operands[0], operands[1], operands[2], NULL_RTX);
++  DONE;
++})
++
++
++(define_insn "*sne"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++      (ne:SI (match_operand:SI 1 "reg_or_0_operand" "%rM")
++             (match_operand:SI 2 "arith_operand"     "rI")))]
++  ""
++  "cmpne%i2\\t%0, %z1, %z2"
++  [(set_attr "type" "alu")])
++
++
++(define_expand "sgt"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (gt:SI (match_dup 1)
++             (match_dup 2)))]
++  ""
++{
++  if (branch_type != CMP_SI)
++    FAIL;
++
++  /* set up operands from compare.  */
++  operands[1] = branch_cmp[0];
++  operands[2] = branch_cmp[1];
++
++  gen_int_relational (GT, operands[0], operands[1], operands[2], NULL_RTX);
++  DONE;
++})
++
++
++(define_insn "*sgt"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++      (gt:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
++             (match_operand:SI 2 "reg_or_0_operand"  "rM")))]
++  ""
++  "cmplt\\t%0, %z2, %z1"
++  [(set_attr "type" "alu")])
++
++
++(define_expand "sge"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (ge:SI (match_dup 1)
++             (match_dup 2)))]
++  ""
++{
++  if (branch_type != CMP_SI)
++    FAIL;
++
++  /* set up operands from compare.  */
++  operands[1] = branch_cmp[0];
++  operands[2] = branch_cmp[1];
++
++  gen_int_relational (GE, operands[0], operands[1], operands[2], NULL_RTX);
++  DONE;
++})
++
++
++(define_insn "*sge"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++      (ge:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
++             (match_operand:SI 2 "arith_operand"     "rI")))]
++  ""
++  "cmpge%i2\\t%0, %z1, %z2"
++  [(set_attr "type" "alu")])
++
++(define_expand "sle"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (le:SI (match_dup 1)
++             (match_dup 2)))]
++  ""
++{
++  if (branch_type != CMP_SI)
++    FAIL;
++
++  /* set up operands from compare.  */
++  operands[1] = branch_cmp[0];
++  operands[2] = branch_cmp[1];
++
++  gen_int_relational (LE, operands[0], operands[1], operands[2], NULL_RTX);
++  DONE;
++})
++
++
++(define_insn "*sle"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++      (le:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
++             (match_operand:SI 2 "reg_or_0_operand"  "rM")))]
++  ""
++  "cmpge\\t%0, %z2, %z1"
++  [(set_attr "type" "alu")])
++
++
++(define_expand "slt"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (lt:SI (match_dup 1)
++             (match_dup 2)))]
++  ""
++{
++  if (branch_type != CMP_SI)
++    FAIL;
++
++  /* set up operands from compare.  */
++  operands[1] = branch_cmp[0];
++  operands[2] = branch_cmp[1];
++
++  gen_int_relational (LT, operands[0], operands[1], operands[2], NULL_RTX);
++  DONE;
++})
++
++
++(define_insn "*slt"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++      (lt:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
++             (match_operand:SI 2 "arith_operand"     "rI")))]
++  ""
++  "cmplt%i2\\t%0, %z1, %z2"
++  [(set_attr "type" "alu")])
++
++
++(define_expand "sgtu"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (gtu:SI (match_dup 1)
++              (match_dup 2)))]
++  ""
++{
++  if (branch_type != CMP_SI)
++    FAIL;
++
++  /* set up operands from compare.  */
++  operands[1] = branch_cmp[0];
++  operands[2] = branch_cmp[1];
++
++  gen_int_relational (GTU, operands[0], operands[1], operands[2], NULL_RTX);
++  DONE;
++})
++
++
++(define_insn "*sgtu"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++      (gtu:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
++              (match_operand:SI 2 "reg_or_0_operand"  "rM")))]
++  ""
++  "cmpltu\\t%0, %z2, %z1"
++  [(set_attr "type" "alu")])
++
++
++(define_expand "sgeu"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (geu:SI (match_dup 1)
++              (match_dup 2)))]
++  ""
++{
++  if (branch_type != CMP_SI)
++    FAIL;
++
++  /* set up operands from compare.  */
++  operands[1] = branch_cmp[0];
++  operands[2] = branch_cmp[1];
++
++  gen_int_relational (GEU, operands[0], operands[1], operands[2], NULL_RTX);
++  DONE;
++})
++
++
++(define_insn "*sgeu"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++      (geu:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
++              (match_operand:SI 2 "uns_arith_operand"     "rJ")))]
++  ""
++  "cmpgeu%i2\\t%0, %z1, %z2"
++  [(set_attr "type" "alu")])
++
++(define_expand "sleu"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (leu:SI (match_dup 1)
++              (match_dup 2)))]
++  ""
++{
++  if (branch_type != CMP_SI)
++    FAIL;
++
++  /* set up operands from compare.  */
++  operands[1] = branch_cmp[0];
++  operands[2] = branch_cmp[1];
++
++  gen_int_relational (LEU, operands[0], operands[1], operands[2], NULL_RTX);
++  DONE;
++})
++
++
++(define_insn "*sleu"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++      (leu:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
++              (match_operand:SI 2 "reg_or_0_operand"  "rM")))]
++  ""
++  "cmpgeu\\t%0, %z2, %z1"
++  [(set_attr "type" "alu")])
++
++
++(define_expand "sltu"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (ltu:SI (match_dup 1)
++              (match_dup 2)))]
++  ""
++{
++  if (branch_type != CMP_SI)
++    FAIL;
++
++  /* set up operands from compare.  */
++  operands[1] = branch_cmp[0];
++  operands[2] = branch_cmp[1];
++
++  gen_int_relational (LTU, operands[0], operands[1], operands[2], NULL_RTX);
++  DONE;
++})
++
++
++(define_insn "*sltu"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++      (ltu:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
++              (match_operand:SI 2 "uns_arith_operand"     "rJ")))]
++  ""
++  "cmpltu%i2\\t%0, %z1, %z2"
++  [(set_attr "type" "alu")])
++
++
++
++\f
++;*****************************************************************************
++;*
++;* branches
++;*
++;*****************************************************************************
++
++(define_insn "*cbranch"
++  [(set (pc)
++      (if_then_else
++         (match_operator:SI 0 "comparison_operator"
++                          [(match_operand:SI 2 "reg_or_0_operand" "rM")
++                           (match_operand:SI 3 "reg_or_0_operand" "rM")])
++        (label_ref (match_operand 1 "" ""))
++        (pc)))]
++  ""
++  "b%0\\t%z2, %z3, %l1"
++  [(set_attr "type" "control")])
++
++
++(define_expand "beq"
++  [(set (pc)
++      (if_then_else (eq:CC (cc0)
++                           (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++{
++  gen_int_relational (EQ, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
++  DONE;
++})
++
++
++(define_expand "bne"
++  [(set (pc)
++      (if_then_else (ne:CC (cc0)
++                           (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++{
++  gen_int_relational (NE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
++  DONE;
++})
++
++
++(define_expand "bgt"
++  [(set (pc)
++      (if_then_else (gt:CC (cc0)
++                           (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++{
++  gen_int_relational (GT, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
++  DONE;
++})
++
++(define_expand "bge"
++  [(set (pc)
++      (if_then_else (ge:CC (cc0)
++                           (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++{
++  gen_int_relational (GE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
++  DONE;
++})
++
++(define_expand "ble"
++  [(set (pc)
++      (if_then_else (le:CC (cc0)
++                           (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++{
++  gen_int_relational (LE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
++  DONE;
++})
++
++(define_expand "blt"
++  [(set (pc)
++      (if_then_else (lt:CC (cc0)
++                           (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++{
++  gen_int_relational (LT, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
++  DONE;
++})
++
++
++(define_expand "bgtu"
++  [(set (pc)
++      (if_then_else (gtu:CC (cc0)
++                            (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++{
++  gen_int_relational (GTU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
++  DONE;
++})
++
++(define_expand "bgeu"
++  [(set (pc)
++      (if_then_else (geu:CC (cc0)
++                            (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++{
++  gen_int_relational (GEU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
++  DONE;
++})
++
++(define_expand "bleu"
++  [(set (pc)
++      (if_then_else (leu:CC (cc0)
++                            (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++{
++  gen_int_relational (LEU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
++  DONE;
++})
++
++(define_expand "bltu"
++  [(set (pc)
++      (if_then_else (ltu:CC (cc0)
++                            (const_int 0))
++                    (label_ref (match_operand 0 "" ""))
++                    (pc)))]
++  ""
++{
++  gen_int_relational (LTU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
++  DONE;
++})
++
++\f
++;*****************************************************************************
++;*
++;* String and Block Operations
++;*
++;*****************************************************************************
++
++; ??? This is all really a hack to get Dhrystone to work as fast as possible
++;     things to be fixed:
++;        * let the compiler core handle all of this, for that to work the extra
++;          aliasing needs to be addressed.
++;        * we use three temporary registers for loading and storing to ensure no
++;          ld use stalls, this is excessive, because after the first ld/st only
++;          two are needed. Only two would be needed all the way through if 
++;          we could schedule with other code. Consider:
++;           1  ld $1, 0($src)
++;           2  ld $2, 4($src)
++;           3  ld $3, 8($src)
++;           4  st $1, 0($dest)
++;           5  ld $1, 12($src)
++;           6  st $2, 4($src)
++;           7  etc.
++;          The first store has to wait until 4. If it does not there will be one
++;          cycle of stalling. However, if any other instruction could be placed
++;          between 1 and 4, $3 would not be needed.
++;        * In small we probably don't want to ever do this ourself because there
++;          is no ld use stall.
++
++(define_expand "movstrsi"
++  [(parallel [(set (match_operand:BLK 0 "general_operand"  "")
++                 (match_operand:BLK 1 "general_operand"  ""))
++            (use (match_operand:SI 2 "const_int_operand" ""))
++            (use (match_operand:SI 3 "const_int_operand" ""))
++            (clobber (match_scratch:SI 4                "=&r"))
++            (clobber (match_scratch:SI 5                "=&r"))
++            (clobber (match_scratch:SI 6                "=&r"))])]
++  "TARGET_INLINE_MEMCPY"
++{
++  rtx ld_addr_reg, st_addr_reg;
++
++  /* If the predicate for op2 fails in expr.c:emit_block_move_via_movstr 
++     it trys to copy to a register, but does not re-try the predicate.
++     ??? Intead of fixing expr.c, I fix it here. */
++  if (!const_int_operand (operands[2], SImode))
++    FAIL;
++
++  /* ??? there are some magic numbers which need to be sorted out here.
++         the basis for them is not increasing code size hugely or going
++         out of range of offset addressing */
++  if (INTVAL (operands[3]) < 4)
++    FAIL;
++  if (!optimize
++      || (optimize_size && INTVAL (operands[2]) > 12)
++      || (optimize < 3 && INTVAL (operands[2]) > 100)
++      || INTVAL (operands[2]) > 200)
++    FAIL;
++
++  st_addr_reg
++    = replace_equiv_address (operands[0],
++                           copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
++  ld_addr_reg
++    = replace_equiv_address (operands[1],
++                           copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
++  emit_insn (gen_movstrsi_internal (st_addr_reg, ld_addr_reg,
++                                  operands[2], operands[3]));
++
++  DONE;
++})
++
++
++(define_insn "movstrsi_internal"
++  [(set (match_operand:BLK 0 "memory_operand"   "=o")
++      (match_operand:BLK 1 "memory_operand"    "o"))
++   (use (match_operand:SI 2 "const_int_operand"  "i"))
++   (use (match_operand:SI 3 "const_int_operand"  "i"))
++   (clobber (match_scratch:SI 4                "=&r"))
++   (clobber (match_scratch:SI 5                "=&r"))
++   (clobber (match_scratch:SI 6                "=&r"))]
++  "TARGET_INLINE_MEMCPY"
++{
++  int ld_offset = INTVAL (operands[2]);
++  int ld_len = INTVAL (operands[2]);
++  int ld_reg = 0;
++  rtx ld_addr_reg = XEXP (operands[1], 0);
++  int st_offset = INTVAL (operands[2]);
++  int st_len = INTVAL (operands[2]);
++  int st_reg = 0;
++  rtx st_addr_reg = XEXP (operands[0], 0);
++  int delay_count = 0;
++  
++  /* ops[0] is the address used by the insn
++     ops[1] is the register being loaded or stored */
++  rtx ops[2];
++  
++  if (INTVAL (operands[3]) < 4)
++    abort ();
++  
++  while (ld_offset >= 4)
++    {
++      /* if the load use delay has been met, I can start
++         storing */
++      if (delay_count >= 3)
++        {
++        ops[0] = gen_rtx (MEM, SImode, 
++                          plus_constant (st_addr_reg, st_len - st_offset));
++        ops[1] = operands[st_reg + 4];                         
++        output_asm_insn ("stw\t%1, %0", ops);
++        
++        st_reg = (st_reg + 1) % 3;
++        st_offset -= 4;
++        }
++    
++      ops[0] = gen_rtx (MEM, SImode, 
++                      plus_constant (ld_addr_reg, ld_len - ld_offset));
++      ops[1] = operands[ld_reg + 4];                   
++      output_asm_insn ("ldw\t%1, %0", ops);
++      
++      ld_reg = (ld_reg + 1) % 3;
++      ld_offset -= 4;
++      delay_count++;
++    }
++  
++  if (ld_offset >= 2)
++    {
++      /* if the load use delay has been met, I can start
++         storing */
++      if (delay_count >= 3)
++        {
++        ops[0] = gen_rtx (MEM, SImode, 
++                          plus_constant (st_addr_reg, st_len - st_offset));
++        ops[1] = operands[st_reg + 4];                         
++        output_asm_insn ("stw\t%1, %0", ops);
++        
++        st_reg = (st_reg + 1) % 3;
++        st_offset -= 4;
++        }
++    
++      ops[0] = gen_rtx (MEM, HImode, 
++                      plus_constant (ld_addr_reg, ld_len - ld_offset));
++      ops[1] = operands[ld_reg + 4];                   
++      output_asm_insn ("ldh\t%1, %0", ops);
++      
++      ld_reg = (ld_reg + 1) % 3;
++      ld_offset -= 2;
++      delay_count++;
++    }
++  
++  if (ld_offset >= 1)
++    {
++      /* if the load use delay has been met, I can start
++         storing */
++      if (delay_count >= 3)
++        {
++        ops[0] = gen_rtx (MEM, SImode, 
++                          plus_constant (st_addr_reg, st_len - st_offset));
++        ops[1] = operands[st_reg + 4];                         
++        output_asm_insn ("stw\t%1, %0", ops);
++        
++        st_reg = (st_reg + 1) % 3;
++        st_offset -= 4;
++        }
++    
++      ops[0] = gen_rtx (MEM, QImode, 
++                      plus_constant (ld_addr_reg, ld_len - ld_offset));
++      ops[1] = operands[ld_reg + 4];                   
++      output_asm_insn ("ldb\t%1, %0", ops);
++      
++      ld_reg = (ld_reg + 1) % 3;
++      ld_offset -= 1;
++      delay_count++;
++    }
++
++    while (st_offset >= 4)
++      {
++      ops[0] = gen_rtx (MEM, SImode, 
++                        plus_constant (st_addr_reg, st_len - st_offset));
++      ops[1] = operands[st_reg + 4];                   
++      output_asm_insn ("stw\t%1, %0", ops);
++
++      st_reg = (st_reg + 1) % 3;
++      st_offset -= 4;
++      }
++  
++    while (st_offset >= 2)
++      {
++      ops[0] = gen_rtx (MEM, HImode, 
++                        plus_constant (st_addr_reg, st_len - st_offset));
++      ops[1] = operands[st_reg + 4];                   
++      output_asm_insn ("sth\t%1, %0", ops);
++
++      st_reg = (st_reg + 1) % 3;
++      st_offset -= 2;
++      }
++  
++    while (st_offset >= 1)
++      {
++      ops[0] = gen_rtx (MEM, QImode, 
++                        plus_constant (st_addr_reg, st_len - st_offset));
++      ops[1] = operands[st_reg + 4];                   
++      output_asm_insn ("stb\t%1, %0", ops);
++
++      st_reg = (st_reg + 1) % 3;
++      st_offset -= 1;
++      }
++  
++  return "";
++}
++; ??? lengths are not being used yet, but I will probably forget
++; to update this once I am using lengths, so set it to something
++; definetely big enough to cover it. 400 allows for 200 bytes
++; of motion.
++  [(set_attr "length" "400")])
++
++
++\f
++;*****************************************************************************
++;*
++;* Custom instructions
++;*
++;*****************************************************************************
++
++(define_constants [
++  (CUSTOM_N 100)
++  (CUSTOM_NI 101)
++  (CUSTOM_NF 102)
++  (CUSTOM_NP 103)
++  (CUSTOM_NII 104)
++  (CUSTOM_NIF 105)
++  (CUSTOM_NIP 106)
++  (CUSTOM_NFI 107)
++  (CUSTOM_NFF 108)
++  (CUSTOM_NFP 109)
++  (CUSTOM_NPI 110)
++  (CUSTOM_NPF 111)
++  (CUSTOM_NPP 112)
++  (CUSTOM_IN 113)
++  (CUSTOM_INI 114)
++  (CUSTOM_INF 115)
++  (CUSTOM_INP 116)
++  (CUSTOM_INII 117)
++  (CUSTOM_INIF 118)
++  (CUSTOM_INIP 119)
++  (CUSTOM_INFI 120)
++  (CUSTOM_INFF 121)
++  (CUSTOM_INFP 122)
++  (CUSTOM_INPI 123)
++  (CUSTOM_INPF 124)
++  (CUSTOM_INPP 125)
++  (CUSTOM_FN 126)
++  (CUSTOM_FNI 127)
++  (CUSTOM_FNF 128)
++  (CUSTOM_FNP 129)
++  (CUSTOM_FNII 130)
++  (CUSTOM_FNIF 131)
++  (CUSTOM_FNIP 132)
++  (CUSTOM_FNFI 133)
++  (CUSTOM_FNFF 134)
++  (CUSTOM_FNFP 135)
++  (CUSTOM_FNPI 136)
++  (CUSTOM_FNPF 137)
++  (CUSTOM_FNPP 138)
++  (CUSTOM_PN 139)
++  (CUSTOM_PNI 140)
++  (CUSTOM_PNF 141)
++  (CUSTOM_PNP 142)
++  (CUSTOM_PNII 143)
++  (CUSTOM_PNIF 144)
++  (CUSTOM_PNIP 145)
++  (CUSTOM_PNFI 146)
++  (CUSTOM_PNFF 147)
++  (CUSTOM_PNFP 148)
++  (CUSTOM_PNPI 149)
++  (CUSTOM_PNPF 150)
++  (CUSTOM_PNPP 151)
++])
++
++
++(define_insn "custom_n"
++  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")] CUSTOM_N)]
++  ""
++  "custom\\t%0, zero, zero, zero"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_ni"
++  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
++                     (match_operand:SI 1 "register_operand"   "r")] CUSTOM_NI)]
++  ""
++  "custom\\t%0, zero, %1, zero"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_nf"
++  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
++                     (match_operand:SF 1 "register_operand"   "r")] CUSTOM_NF)]
++  ""
++  "custom\\t%0, zero, %1, zero"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_np"
++  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
++                     (match_operand:SI 1 "register_operand"   "r")] CUSTOM_NP)]
++  ""
++  "custom\\t%0, zero, %1, zero"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_nii"
++  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
++                     (match_operand:SI 1 "register_operand"   "r")
++                     (match_operand:SI 2 "register_operand"   "r")] CUSTOM_NII)]
++  ""
++  "custom\\t%0, zero, %1, %2"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_nif"
++  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
++                     (match_operand:SI 1 "register_operand"   "r")
++                     (match_operand:SF 2 "register_operand"   "r")] CUSTOM_NIF)]
++  ""
++  "custom\\t%0, zero, %1, %2"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_nip"
++  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
++                     (match_operand:SI 1 "register_operand"   "r")
++                     (match_operand:SI 2 "register_operand"   "r")] CUSTOM_NIP)]
++  ""
++  "custom\\t%0, zero, %1, %2"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_nfi"
++  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
++                     (match_operand:SF 1 "register_operand"   "r")
++                     (match_operand:SI 2 "register_operand"   "r")] CUSTOM_NFI)]
++  ""
++  "custom\\t%0, zero, %1, %2"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_nff"
++  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
++                     (match_operand:SF 1 "register_operand"   "r")
++                     (match_operand:SF 2 "register_operand"   "r")] CUSTOM_NFF)]
++  ""
++  "custom\\t%0, zero, %1, %2"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_nfp"
++  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
++                     (match_operand:SF 1 "register_operand"   "r")
++                     (match_operand:SI 2 "register_operand"   "r")] CUSTOM_NFP)]
++  ""
++  "custom\\t%0, zero, %1, %2"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_npi"
++  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
++                     (match_operand:SI 1 "register_operand"   "r")
++                     (match_operand:SI 2 "register_operand"   "r")] CUSTOM_NPI)]
++  ""
++  "custom\\t%0, zero, %1, %2"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_npf"
++  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
++                     (match_operand:SI 1 "register_operand"   "r")
++                     (match_operand:SF 2 "register_operand"   "r")] CUSTOM_NPF)]
++  ""
++  "custom\\t%0, zero, %1, %2"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_npp"
++  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
++                     (match_operand:SI 1 "register_operand"   "r")
++                     (match_operand:SI 2 "register_operand"   "r")] CUSTOM_NPP)]
++  ""
++  "custom\\t%0, zero, %1, %2"
++  [(set_attr "type" "custom")])
++
++
++
++(define_insn "custom_in"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_IN))]
++  ""
++  "custom\\t%1, %0, zero, zero"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_ini"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")] CUSTOM_INI))]
++  ""
++  "custom\\t%1, %0, %2, zero"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_inf"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SF 2 "register_operand"   "r")] CUSTOM_INF))]
++  ""
++  "custom\\t%1, %0, %2, zero"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_inp"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")] CUSTOM_INP))]
++  ""
++  "custom\\t%1, %0, %2, zero"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_inii"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_INII))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_inif"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_INIF))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_inip"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_INIP))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_infi"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SF 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_INFI))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_inff"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SF 2 "register_operand"   "r")
++                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_INFF))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_infp"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SF 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_INFP))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_inpi"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_INPI))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_inpf"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_INPF))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_inpp"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_INPP))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++
++
++
++
++(define_insn "custom_fn"
++  [(set (match_operand:SF 0 "register_operand"   "=r")
++        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_FN))]
++  ""
++  "custom\\t%1, %0, zero, zero"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_fni"
++  [(set (match_operand:SF 0 "register_operand"   "=r")
++        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")] CUSTOM_FNI))]
++  ""
++  "custom\\t%1, %0, %2, zero"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_fnf"
++  [(set (match_operand:SF 0 "register_operand"   "=r")
++        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SF 2 "register_operand"   "r")] CUSTOM_FNF))]
++  ""
++  "custom\\t%1, %0, %2, zero"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_fnp"
++  [(set (match_operand:SF 0 "register_operand"   "=r")
++        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")] CUSTOM_FNP))]
++  ""
++  "custom\\t%1, %0, %2, zero"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_fnii"
++  [(set (match_operand:SF 0 "register_operand"   "=r")
++        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_FNII))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_fnif"
++  [(set (match_operand:SF 0 "register_operand"   "=r")
++        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_FNIF))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_fnip"
++  [(set (match_operand:SF 0 "register_operand"   "=r")
++        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_FNIP))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_fnfi"
++  [(set (match_operand:SF 0 "register_operand"   "=r")
++        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SF 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_FNFI))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_fnff"
++  [(set (match_operand:SF 0 "register_operand"   "=r")
++        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SF 2 "register_operand"   "r")
++                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_FNFF))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_fnfp"
++  [(set (match_operand:SF 0 "register_operand"   "=r")
++        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SF 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_FNFP))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_fnpi"
++  [(set (match_operand:SF 0 "register_operand"   "=r")
++        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_FNPI))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_fnpf"
++  [(set (match_operand:SF 0 "register_operand"   "=r")
++        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_FNPF))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_fnpp"
++  [(set (match_operand:SF 0 "register_operand"   "=r")
++        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_FNPP))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++
++
++(define_insn "custom_pn"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_PN))]
++  ""
++  "custom\\t%1, %0, zero, zero"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_pni"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")] CUSTOM_PNI))]
++  ""
++  "custom\\t%1, %0, %2, zero"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_pnf"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SF 2 "register_operand"   "r")] CUSTOM_PNF))]
++  ""
++  "custom\\t%1, %0, %2, zero"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_pnp"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")] CUSTOM_PNP))]
++  ""
++  "custom\\t%1, %0, %2, zero"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_pnii"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_PNII))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_pnif"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_PNIF))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_pnip"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_PNIP))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_pnfi"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SF 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_PNFI))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_pnff"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SF 2 "register_operand"   "r")
++                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_PNFF))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_pnfp"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SF 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_PNFP))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_pnpi"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_PNPI))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_pnpf"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_PNPF))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++(define_insn "custom_pnpp"
++  [(set (match_operand:SI 0 "register_operand"   "=r")
++        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
++                          (match_operand:SI 2 "register_operand"   "r")
++                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_PNPP))]
++  ""
++  "custom\\t%1, %0, %2, %3"
++  [(set_attr "type" "custom")])
++
++
++
++
++
++\f
++;*****************************************************************************
++;*
++;* Misc
++;*
++;*****************************************************************************
++
++(define_insn "nop"
++  [(const_int 0)]
++  ""
++  "nop\\t"
++  [(set_attr "type" "alu")])
++
++(define_insn "sync"
++  [(unspec_volatile [(const_int 0)] UNSPEC_SYNC)]
++  ""
++  "sync\\t"
++  [(set_attr "type" "control")])
++
++
++(define_insn "rdctl"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++      (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")] UNSPEC_RDCTL))]
++  ""
++  "rdctl\\t%0, ctl%1"
++  [(set_attr "type" "control")])
++
++(define_insn "wrctl"
++  [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand"  "O")
++                        (match_operand:SI 1 "register_operand" "r")] UNSPEC_WRCTL)]
++  ""
++  "wrctl\\tctl%0, %1"
++  [(set_attr "type" "control")])
++
++
++\f
++;*****************************************************************************
++;*
++;* Peepholes
++;*
++;*****************************************************************************
++
++
+--- gcc-3.4.3/gcc/config/nios2/t-nios2
++++ gcc-3.4.3-nios2/gcc/config/nios2/t-nios2
+@@ -0,0 +1,123 @@
++##
++## Compiler flags to use when compiling libgcc2.c.
++##
++## LIB2FUNCS_EXTRA
++## A list of source file names to be compiled or assembled and inserted into libgcc.a.
++
++LIB2FUNCS_EXTRA=$(srcdir)/config/nios2/lib2-divmod.c \
++  $(srcdir)/config/nios2/lib2-divmod-hi.c \
++  $(srcdir)/config/nios2/lib2-divtable.c \
++  $(srcdir)/config/nios2/lib2-mul.c
++
++##
++## Floating Point Emulation
++## To have GCC include software floating point libraries in libgcc.a define FPBIT
++## and DPBIT along with a few rules as follows:
++##
++## # We want fine grained libraries, so use the new code
++## # to build the floating point emulation libraries.
++FPBIT=$(srcdir)/config/nios2/nios2-fp-bit.c
++DPBIT=$(srcdir)/config/nios2/nios2-dp-bit.c
++
++TARGET_LIBGCC2_CFLAGS = -O2
++
++# FLOAT_ONLY - no doubles
++# SMALL_MACHINE - QI/HI is faster than SI
++#     Actually SMALL_MACHINE uses chars and shorts instead of ints
++#     since ints (16-bit ones as they are today) are at least as fast
++#     as chars and shorts, don't define SMALL_MACHINE
++# CMPtype - type returned by FP compare, i.e. INT (hard coded in fp-bit - see code )
++
++$(FPBIT): $(srcdir)/config/fp-bit.c Makefile
++      echo '#define FLOAT'          >  ${FPBIT}
++      cat $(srcdir)/config/fp-bit.c >> ${FPBIT}
++
++$(DPBIT): $(srcdir)/config/fp-bit.c Makefile
++      echo ''          >  ${DPBIT}
++      cat $(srcdir)/config/fp-bit.c >> ${DPBIT}
++
++EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o 
++
++# Assemble startup files. 
++$(T)crti.o: $(srcdir)/config/nios2/crti.asm $(GCC_PASSES) 
++      $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
++      -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/nios2/crti.asm 
++
++$(T)crtn.o: $(srcdir)/config/nios2/crtn.asm $(GCC_PASSES) 
++      $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
++      -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/nios2/crtn.asm 
++
++
++## You may need to provide additional #defines at the beginning of
++## fp-bit.c and dp-bit.c to control target endianness and other options
++##
++## CRTSTUFF_T_CFLAGS
++## Special flags used when compiling crtstuff.c.  See Initialization.
++##
++## CRTSTUFF_T_CFLAGS_S
++## Special flags used when compiling crtstuff.c for shared linking.  Used
++## if you use crtbeginS.o and crtendS.o in EXTRA-PARTS. See Initialization.
++##
++## MULTILIB_OPTIONS
++## For some targets, invoking GCC in different ways produces objects that
++## can not be linked together.  For example, for some targets GCC produces
++## both big and little endian code.  For these targets, you must arrange
++## for multiple versions of libgcc.a to be compiled, one for each set of
++## incompatible options.  When GCC invokes the linker, it arranges to link
++## in the right version of libgcc.a, based on the command line options
++## used.
++## The MULTILIB_OPTIONS macro lists the set of options for which special
++## versions of libgcc.a must be built.  Write options that are mutually
++## incompatible side by side, separated by a slash.  Write options that may
++## be used together separated by a space.  The build procedure will build
++## all combinations of compatible options.
++##
++## For example, if you set MULTILIB_OPTIONS to m68000/m68020 msoft-float,
++## Makefile will build special versions of libgcc.a using the following
++## sets of options: -m68000, -m68020, -msoft-float, -m68000 -msoft-float,
++## and -m68020 -msoft-float.
++
++MULTILIB_OPTIONS = mno-hw-mul mhw-mulx
++
++## MULTILIB_DIRNAMES
++## If MULTILIB_OPTIONS is used, this variable specifies the directory names
++## that should be used to hold the various libraries.  Write one element in
++## MULTILIB_DIRNAMES for each element in MULTILIB_OPTIONS. If
++## MULTILIB_DIRNAMES is not used, the default value will be
++## MULTILIB_OPTIONS, with all slashes treated as spaces.
++## For example, if MULTILIB_OPTIONS is set to m68000/m68020 msoft-float,
++## then the default value of MULTILIB_DIRNAMES is m68000 m68020
++## msoft-float.  You may specify a different value if you desire a
++## different set of directory names.
++
++# MULTILIB_DIRNAMES =
++
++## MULTILIB_MATCHES
++## Sometimes the same option may be written in two different ways.  If an
++## option is listed in MULTILIB_OPTIONS, GCC needs to know about any
++## synonyms.  In that case, set MULTILIB_MATCHES to a list of items of the
++## form option=option to describe all relevant synonyms.  For example,
++## m68000=mc68000 m68020=mc68020.
++##
++## MULTILIB_EXCEPTIONS
++## Sometimes when there are multiple sets of MULTILIB_OPTIONS being
++## specified, there are combinations that should not be built.  In that
++## case, set MULTILIB_EXCEPTIONS to be all of the switch exceptions in
++## shell case syntax that should not be built.
++## For example, in the PowerPC embedded ABI support, it is not desirable to
++## build libraries compiled with the -mcall-aix option and either of the
++## -fleading-underscore or -mlittle options at the same time.  Therefore
++## MULTILIB_EXCEPTIONS is set to
++##
++## *mcall-aix/*fleading-underscore* *mlittle/*mcall-aix*
++##
++
++MULTILIB_EXCEPTIONS = *mno-hw-mul/*mhw-mulx*
++
++##
++## MULTILIB_EXTRA_OPTS Sometimes it is desirable that when building
++## multiple versions of libgcc.a certain options should always be passed on
++## to the compiler.  In that case, set MULTILIB_EXTRA_OPTS to be the list
++## of options to be used for all builds.
++##
++
+--- gcc-3.4.3/gcc/config.gcc
++++ gcc-3.4.3-nios2/gcc/config.gcc
+@@ -1321,6 +1321,10 @@ m32rle-*-linux*)
+               thread_file='posix'
+       fi
+       ;;
++# JBG
++nios2-*-* | nios2-*-*)
++      tm_file="elfos.h ${tm_file}"
++      ;;
+ # m68hc11 and m68hc12 share the same machine description.
+ m68hc11-*-*|m6811-*-*)
+       tm_file="dbxelf.h elfos.h m68hc11/m68hc11.h"
+--- gcc-3.4.3/gcc/cse.c
++++ gcc-3.4.3-nios2/gcc/cse.c
+@@ -3134,6 +3134,10 @@ find_comparison_args (enum rtx_code code
+ #ifdef FLOAT_STORE_FLAG_VALUE
+         REAL_VALUE_TYPE fsfv;
+ #endif
++#ifdef __nios2__
++        if (p->is_const)
++          break;
++#endif
+         /* If the entry isn't valid, skip it.  */
+         if (! exp_equiv_p (p->exp, p->exp, 1, 0))
+--- gcc-3.4.3/gcc/doc/extend.texi
++++ gcc-3.4.3-nios2/gcc/doc/extend.texi
+@@ -5636,12 +5636,118 @@ to those machines.  Generally these gene
+ instructions, but allow the compiler to schedule those calls.
+ @menu
++* Altera Nios II Built-in Functions::
+ * Alpha Built-in Functions::
+ * ARM Built-in Functions::
+ * X86 Built-in Functions::
+ * PowerPC AltiVec Built-in Functions::
+ @end menu
++@node Altera Nios II Built-in Functions
++@subsection Altera Nios II Built-in Functions
++
++These built-in functions are available for the Altera Nios II
++family of processors.
++
++The following built-in functions are always available.  They
++all generate the machine instruction that is part of the name.
++
++@example
++int __builtin_ldbio (volatile const void *)
++int __builtin_ldbuio (volatile const void *)
++int __builtin_ldhio (volatile const void *)
++int __builtin_ldhuio (volatile const void *)
++int __builtin_ldwio (volatile const void *)
++void __builtin_stbio (volatile void *, int)
++void __builtin_sthio (volatile void *, int)
++void __builtin_stwio (volatile void *, int)
++void __builtin_sync (void)
++int __builtin_rdctl (int) 
++void __builtin_wrctl (int, int)
++@end example
++
++The following built-in functions are always available.  They
++all generate a Nios II Custom Instruction. The name of the 
++function represents the types that the function takes and 
++returns. The letter before the @code{n} is the return type
++or void if absent. The @code{n} represnts the first parameter
++to all the custom instructions, the custom instruction number.
++The two letters after the @code{n} represent the up to two 
++parameters to the function.
++
++The letters reprsent the following data types:
++@table @code
++@item <no letter>
++@code{void} for return type and no parameter for parameter types.
++
++@item i
++@code{int} for return type and parameter type
++
++@item f
++@code{float} for return type and parameter type
++
++@item p
++@code{void *} for return type and parameter type
++
++@end table
++
++And the function names are:
++@example
++void __builtin_custom_n (void)
++void __builtin_custom_ni (int)
++void __builtin_custom_nf (float)
++void __builtin_custom_np (void *)
++void __builtin_custom_nii (int, int)
++void __builtin_custom_nif (int, float)
++void __builtin_custom_nip (int, void *)
++void __builtin_custom_nfi (float, int)
++void __builtin_custom_nff (float, float)
++void __builtin_custom_nfp (float, void *)
++void __builtin_custom_npi (void *, int)
++void __builtin_custom_npf (void *, float)
++void __builtin_custom_npp (void *, void *)
++int __builtin_custom_in (void)
++int __builtin_custom_ini (int)
++int __builtin_custom_inf (float)
++int __builtin_custom_inp (void *)
++int __builtin_custom_inii (int, int)
++int __builtin_custom_inif (int, float)
++int __builtin_custom_inip (int, void *)
++int __builtin_custom_infi (float, int)
++int __builtin_custom_inff (float, float)
++int __builtin_custom_infp (float, void *)
++int __builtin_custom_inpi (void *, int)
++int __builtin_custom_inpf (void *, float)
++int __builtin_custom_inpp (void *, void *)
++float __builtin_custom_fn (void)
++float __builtin_custom_fni (int)
++float __builtin_custom_fnf (float)
++float __builtin_custom_fnp (void *)
++float __builtin_custom_fnii (int, int)
++float __builtin_custom_fnif (int, float)
++float __builtin_custom_fnip (int, void *)
++float __builtin_custom_fnfi (float, int)
++float __builtin_custom_fnff (float, float)
++float __builtin_custom_fnfp (float, void *)
++float __builtin_custom_fnpi (void *, int)
++float __builtin_custom_fnpf (void *, float)
++float __builtin_custom_fnpp (void *, void *)
++void * __builtin_custom_pn (void)
++void * __builtin_custom_pni (int)
++void * __builtin_custom_pnf (float)
++void * __builtin_custom_pnp (void *)
++void * __builtin_custom_pnii (int, int)
++void * __builtin_custom_pnif (int, float)
++void * __builtin_custom_pnip (int, void *)
++void * __builtin_custom_pnfi (float, int)
++void * __builtin_custom_pnff (float, float)
++void * __builtin_custom_pnfp (float, void *)
++void * __builtin_custom_pnpi (void *, int)
++void * __builtin_custom_pnpf (void *, float)
++void * __builtin_custom_pnpp (void *, void *)
++@end example
++
++
+ @node Alpha Built-in Functions
+ @subsection Alpha Built-in Functions
+--- gcc-3.4.3/gcc/doc/invoke.texi
++++ gcc-3.4.3-nios2/gcc/doc/invoke.texi
+@@ -337,6 +337,14 @@ in the following sections.
+ @item Machine Dependent Options
+ @xref{Submodel Options,,Hardware Models and Configurations}.
++@emph{Altera Nios II Options}
++@gccoptlist{-msmallc -mno-bypass-cache -mbypass-cache @gol
++-mno-cache-volatile -mcache-volatile -mno-inline-memcpy @gol 
++-minline-memcpy -mno-fast-sw-div -mfast-sw-div @gol
++-mhw-mul -mno-hw-mul -mhw-mulx -mno-hw-mulx @gol
++-mno-hw-div -mhw-div @gol
++-msys-crt0= -msys-lib= -msys=nosys }
++
+ @emph{M680x0 Options}
+ @gccoptlist{-m68000  -m68020  -m68020-40  -m68020-60  -m68030  -m68040 @gol
+ -m68060  -mcpu32  -m5200  -m68881  -mbitfield  -mc68000  -mc68020   @gol
+@@ -5836,6 +5844,7 @@ machine description.  The default for th
+ that macro, which enables you to change the defaults.
+ @menu
++* Altera Nios II Options::
+ * M680x0 Options::
+ * M68hc1x Options::
+ * VAX Options::
+@@ -5871,6 +5880,103 @@ that macro, which enables you to change 
+ * FRV Options::
+ @end menu
++
++@node Altera Nios II Options
++@subsection Altera Nios II Options
++@cindex Altera Nios II options
++
++These are the @samp{-m} options defined for the Altera Nios II 
++processor.
++
++@table @gcctabopt
++
++@item -msmallc
++@opindex msmallc
++
++Link with a limited version of the C library, -lsmallc. For more 
++information see the C Library Documentation.
++
++
++@item -mbypass-cache
++@itemx -mno-bypass-cache
++@opindex mno-bypass-cache
++@opindex mbypass-cache
++
++Force all load and store instructions to always bypass cache by 
++using io variants of the instructions. The default is to not
++bypass the cache.
++
++@item -mno-cache-volatile 
++@itemx -mcache-volatile       
++@opindex mcache-volatile 
++@opindex mno-cache-volatile
++
++Volatile memory access bypass the cache using the io variants of 
++the ld and st instructions. The default is to cache volatile 
++accesses. 
++
++-mno-cache-volatile is deprecated and will be deleted in a 
++future GCC release.
++
++
++@item -mno-inline-memcpy
++@itemx -minline-memcpy
++@opindex mno-inline-memcpy 
++@opindex minline-memcpy
++
++Do not inline memcpy. The default is to inline when -O is on.
++
++
++@item -mno-fast-sw-div
++@itemx -mfast-sw-div
++@opindex mno-fast-sw-div
++@opindex mfast-sw-div
++
++Do no use table based fast divide for small numbers. The default 
++is to use the fast divide at -O3 and above.
++
++
++@item -mno-hw-mul
++@itemx -mhw-mul
++@itemx -mno-hw-mulx
++@itemx -mhw-mulx
++@itemx -mno-hw-div
++@itemx -mhw-div
++@opindex mno-hw-mul
++@opindex mhw-mul
++@opindex mno-hw-mulx
++@opindex mhw-mulx
++@opindex mno-hw-div
++@opindex mhw-div
++
++Enable or disable emitting @code{mul}, @code{mulx} and @code{div} family of 
++instructions by the compiler. The default is to emit @code{mul}
++and not emit @code{div} and @code{mulx}.
++
++The different combinations of @code{mul} and @code{mulx} instructions 
++generate a different multilib options. 
++
++
++@item -msys-crt0=@var{startfile}
++@opindex msys-crt0
++
++@var{startfile} is the file name  of the startfile (crt0) to use 
++when linking. The default is crt0.o that comes with libgloss
++and is only suitable for use with the instruction set
++simulator.
++
++@item -msys-lib=@var{systemlib}
++@itemx -msys-lib=nosys
++@opindex msys-lib
++
++@var{systemlib} is the library name of the library which provides
++the system calls required by the C library, e.g. @code{read}, @code{write}
++etc. The default is to use nosys, this library provides
++stub implementations of the calls and is part of libgloss.
++
++@end table
++
++
+ @node M680x0 Options
+ @subsection M680x0 Options
+ @cindex M680x0 options
+--- gcc-3.4.3/gcc/doc/md.texi
++++ gcc-3.4.3-nios2/gcc/doc/md.texi
+@@ -1335,6 +1335,49 @@ However, here is a summary of the machin
+ available on some particular machines.
+ @table @emph
++
++@item Altera Nios II family---@file{nios2.h}
++@table @code
++
++@item I
++Integer that is valid as an immediate operand in an
++instruction taking a signed 16-bit number. Range
++@minus{}32768 to 32767.
++
++@item J
++Integer that is valid as an immediate operand in an
++instruction taking an unsigned 16-bit number. Range
++0 to 65535.
++
++@item K
++Integer that is valid as an immediate operand in an
++instruction taking only the upper 16-bits of a
++32-bit number. Range 32-bit numbers with the lower
++16-bits being 0.
++
++@item L
++Integer that is valid as an immediate operand for a 
++shift instruction. Range 0 to 31.
++
++
++@item M
++Integer that is valid as an immediate operand for
++only the value 0. Can be used in conjunction with
++the format modifier @code{z} to use @code{r0}
++instead of @code{0} in the assembly output.
++
++@item N
++Integer that is valid as an immediate operand for
++a custom instruction opcode. Range 0 to 255.
++
++@item S
++Matches immediates which are addresses in the small
++data section and therefore can be added to @code{gp}
++as a 16-bit immediate to re-create their 32-bit value.
++
++@end table
++
++
+ @item ARM family---@file{arm.h}
+ @table @code
+ @item f
diff --git a/toolchain/gcc/3.4.6/arm-softfloat.patch.conditional b/toolchain/gcc/3.4.6/arm-softfloat.patch.conditional
new file mode 100644 (file)
index 0000000..19d1b90
--- /dev/null
@@ -0,0 +1,270 @@
+Note... modified my mjn3 to not conflict with the big endian arm patch.
+Warning!!!  Only the linux target is aware of TARGET_ENDIAN_DEFAULT.
+Also changed
+  #define SUBTARGET_EXTRA_ASM_SPEC "\
+  %{!mcpu=*:-mcpu=xscale} \
+  %{mhard-float:-mfpu=fpa} \
+  %{!mhard-float: %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}}"
+to
+  #define SUBTARGET_EXTRA_ASM_SPEC "\
+  %{mhard-float:-mfpu=fpa} \
+  %{!mhard-float: %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}}"
+in gcc/config/arm/linux-elf.h.
+#
+# Submitted:
+#
+# Dimitry Andric <dimitry@andric.com>, 2004-05-01
+#
+# Description:
+#
+# Nicholas Pitre released this patch for gcc soft-float support here: 
+# http://lists.arm.linux.org.uk/pipermail/linux-arm/2003-October/006436.html
+#
+# This version has been adapted to work with gcc 3.4.0.
+#
+# The original patch doesn't distinguish between softfpa and softvfp modes
+# in the way Nicholas Pitre probably meant.  His description is:
+#
+# "Default is to use APCS-32 mode with soft-vfp.  The old Linux default for
+# floats can be achieved with -mhard-float or with the configure
+# --with-float=hard option.  If -msoft-float or --with-float=soft is used then
+# software float support will be used just like the default but with the legacy
+# big endian word ordering for double float representation instead."
+#
+# Which means the following:
+#
+# * If you compile without -mhard-float or -msoft-float, you should get
+#   software floating point, using the VFP format.  The produced object file
+#   should have these flags in its header:
+#
+#     private flags = 600: [APCS-32] [VFP float format] [software FP]
+#
+# * If you compile with -mhard-float, you should get hardware floating point,
+#   which always uses the FPA format.  Object file header flags should be:
+#
+#     private flags = 0: [APCS-32] [FPA float format]
+#
+# * If you compile with -msoft-float, you should get software floating point,
+#   using the FPA format.  This is done for compatibility reasons with many
+#   existing distributions.  Object file header flags should be:
+#
+#     private flags = 200: [APCS-32] [FPA float format] [software FP]
+#
+# The original patch from Nicholas Pitre contained the following constructs:
+#
+#   #define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mcpu=xscale} \
+#     %{mhard-float:-mfpu=fpa} \
+#     %{!mhard-float: %{msoft-float:-mfpu=softfpa;:-mfpu=softvfp}}"
+#
+# However, gcc doesn't accept this ";:" notation, used in the 3rd line.  This
+# is probably the reason Robert Schwebel modified it to:
+#
+#   #define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mcpu=xscale} \
+#     %{mhard-float:-mfpu=fpa} \
+#     %{!mhard-float: %{msoft-float:-mfpu=softfpa -mfpu=softvfp}}"
+#
+# But this causes the following behaviour:
+#
+# * If you compile without -mhard-float or -msoft-float, the compiler generates
+#   software floating point instructions, but *nothing* is passed to the
+#   assembler, which results in an object file which has flags:
+#
+#     private flags = 0: [APCS-32] [FPA float format]
+#
+#   This is not correct!
+#
+# * If you compile with -mhard-float, the compiler generates hardware floating
+#   point instructions, and passes "-mfpu=fpa" to the assembler, which results
+#   in an object file which has the same flags as in the previous item, but now
+#   those *are* correct.
+#    
+# * If you compile with -msoft-float, the compiler generates software floating
+#   point instructions, and passes "-mfpu=softfpa -mfpu=softvfp" (in that
+#   order) to the assembler, which results in an object file with flags:
+#
+#   private flags = 600: [APCS-32] [VFP float format] [software FP]
+#
+#   This is not correct, because the last "-mfpu=" option on the assembler
+#   command line determines the actual FPU convention used (which should be FPA
+#   in this case).
+#
+# Therefore, I modified this patch to get the desired behaviour.  Every
+# instance of the notation:
+#
+#   %{msoft-float:-mfpu=softfpa -mfpu=softvfp}
+#
+# was changed to:
+#
+#   %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}
+#
+# I also did the following:
+# 
+# * Modified all TARGET_DEFAULT macros I could find to include ARM_FLAG_VFP, to
+#   be consistent with Nicholas' original patch.
+# * Removed any "msoft-float" or "mhard-float" from all MULTILIB_DEFAULTS
+#   macros I could find.  I think that if you compile without any options, you
+#   would like to get the defaults. :)
+# * Removed the extra -lfloat option from LIBGCC_SPEC, since it isn't needed
+#   anymore.  (The required functions are now in libgcc.)
+
+diff -urN gcc-3.4.1-old/gcc/config/arm/coff.h gcc-3.4.1/gcc/config/arm/coff.h
+--- gcc-3.4.1-old/gcc/config/arm/coff.h        2004-02-24 08:25:22.000000000 -0600
++++ gcc-3.4.1/gcc/config/arm/coff.h    2004-09-02 21:51:15.000000000 -0500
+@@ -31,11 +31,16 @@
+ #define TARGET_VERSION fputs (" (ARM/coff)", stderr)
+ #undef  TARGET_DEFAULT
+-#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_32 | ARM_FLAG_APCS_FRAME | ARM_FLAG_MMU_TRAPS)
++#define TARGET_DEFAULT                \
++      ( ARM_FLAG_SOFT_FLOAT   \
++      | ARM_FLAG_VFP          \
++      | ARM_FLAG_APCS_32      \
++      | ARM_FLAG_APCS_FRAME   \
++      | ARM_FLAG_MMU_TRAPS )
+ #ifndef MULTILIB_DEFAULTS
+ #define MULTILIB_DEFAULTS \
+-  { "marm", "mlittle-endian", "msoft-float", "mapcs-32", "mno-thumb-interwork" }
++  { "marm", "mlittle-endian", "mapcs-32", "mno-thumb-interwork" }
+ #endif
\f
+ /* This is COFF, but prefer stabs.  */
+diff -urN gcc-3.4.1-old/gcc/config/arm/elf.h gcc-3.4.1/gcc/config/arm/elf.h
+--- gcc-3.4.1-old/gcc/config/arm/elf.h 2004-02-24 08:25:22.000000000 -0600
++++ gcc-3.4.1/gcc/config/arm/elf.h     2004-09-02 21:51:15.000000000 -0500
+@@ -46,7 +46,9 @@
+ #ifndef SUBTARGET_ASM_FLOAT_SPEC
+ #define SUBTARGET_ASM_FLOAT_SPEC "\
+-%{mapcs-float:-mfloat} %{msoft-float:-mfpu=softfpa}"
++%{mapcs-float:-mfloat} \
++%{mhard-float:-mfpu=fpa} \
++%{!mhard-float: %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}}"
+ #endif
+ #ifndef ASM_SPEC
+@@ -106,12 +108,17 @@
+ #endif
+ #ifndef TARGET_DEFAULT
+-#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_32 | ARM_FLAG_APCS_FRAME | ARM_FLAG_MMU_TRAPS)
++#define TARGET_DEFAULT                \
++      ( ARM_FLAG_SOFT_FLOAT   \
++      | ARM_FLAG_VFP          \
++      | ARM_FLAG_APCS_32      \
++      | ARM_FLAG_APCS_FRAME   \
++      | ARM_FLAG_MMU_TRAPS )
+ #endif
+ #ifndef MULTILIB_DEFAULTS
+ #define MULTILIB_DEFAULTS \
+-  { "marm", "mlittle-endian", "msoft-float", "mapcs-32", "mno-thumb-interwork", "fno-leading-underscore" }
++  { "marm", "mlittle-endian", "mapcs-32", "mno-thumb-interwork", "fno-leading-underscore" }
+ #endif
\f
+ #define TARGET_ASM_FILE_START_APP_OFF true
+diff -urN gcc-3.4.1-old/gcc/config/arm/linux-elf.h gcc-3.4.1/gcc/config/arm/linux-elf.h
+--- gcc-3.4.1-old/gcc/config/arm/linux-elf.h   2004-09-02 21:50:52.000000000 -0500
++++ gcc-3.4.1/gcc/config/arm/linux-elf.h       2004-09-02 22:00:49.000000000 -0500
+@@ -44,12 +44,26 @@
+ #define TARGET_LINKER_EMULATION "armelf_linux"
+ #endif
+-/* Default is to use APCS-32 mode.  */
++/*
++ * Default is to use APCS-32 mode with soft-vfp.
++ * The old Linux default for floats can be achieved with -mhard-float
++ * or with the configure --with-float=hard option.
++ * If -msoft-float or --with-float=soft is used then software float 
++ * support will be used just like the default but with the legacy
++ * big endian word ordering for double float representation instead.
++ */
+ #undef  TARGET_DEFAULT
+-#define TARGET_DEFAULT \
+-              ( ARM_FLAG_APCS_32 | \
+-                ARM_FLAG_MMU_TRAPS | \
+-                TARGET_ENDIAN_DEFAULT )
++#define TARGET_DEFAULT                \
++      ( ARM_FLAG_APCS_32      \
++      | ARM_FLAG_SOFT_FLOAT   \
++      | TARGET_ENDIAN_DEFAULT \
++      | ARM_FLAG_VFP          \
++      | ARM_FLAG_MMU_TRAPS )
++
++#undef  SUBTARGET_EXTRA_ASM_SPEC
++#define SUBTARGET_EXTRA_ASM_SPEC "\
++%{mhard-float:-mfpu=fpa} \
++%{!mhard-float: %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}}"
+ #define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6
+@@ -57,7 +71,7 @@
+ #undef  MULTILIB_DEFAULTS
+ #define MULTILIB_DEFAULTS \
+-      { "marm", TARGET_ENDIAN_OPTION, "mhard-float", "mapcs-32", "mno-thumb-interwork" }
++      { "marm", TARGET_ENDIAN_OPTION, "mapcs-32", "mno-thumb-interwork" }
+ #define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
+@@ -72,7 +86,7 @@
+    %{shared:-lc} \
+    %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
+-#define LIBGCC_SPEC "%{msoft-float:-lfloat} -lgcc"
++#define LIBGCC_SPEC "-lgcc"
+ /* Provide a STARTFILE_SPEC appropriate for GNU/Linux.  Here we add
+    the GNU/Linux magical crtbegin.o file (see crtstuff.c) which
+diff -urN gcc-3.4.1-old/gcc/config/arm/t-linux gcc-3.4.1/gcc/config/arm/t-linux
+--- gcc-3.4.1-old/gcc/config/arm/t-linux       2003-09-20 16:09:07.000000000 -0500
++++ gcc-3.4.1/gcc/config/arm/t-linux   2004-09-02 21:51:15.000000000 -0500
+@@ -4,7 +4,10 @@
+ LIBGCC2_DEBUG_CFLAGS = -g0
+ LIB1ASMSRC = arm/lib1funcs.asm
+-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx
++LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx \
++      _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \
++      _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
++      _fixsfsi _fixunssfsi
+ # MULTILIB_OPTIONS = mhard-float/msoft-float
+ # MULTILIB_DIRNAMES = hard-float soft-float
+diff -urN gcc-3.4.1-old/gcc/config/arm/unknown-elf.h gcc-3.4.1/gcc/config/arm/unknown-elf.h
+--- gcc-3.4.1-old/gcc/config/arm/unknown-elf.h 2004-02-24 08:25:22.000000000 -0600
++++ gcc-3.4.1/gcc/config/arm/unknown-elf.h     2004-09-02 21:51:15.000000000 -0500
+@@ -30,7 +30,12 @@
+ /* Default to using APCS-32 and software floating point.  */
+ #ifndef TARGET_DEFAULT
+-#define TARGET_DEFAULT        (ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_32 | ARM_FLAG_APCS_FRAME | ARM_FLAG_MMU_TRAPS)
++#define TARGET_DEFAULT                \
++      ( ARM_FLAG_SOFT_FLOAT   \
++      | ARM_FLAG_VFP          \
++      | ARM_FLAG_APCS_32      \
++      | ARM_FLAG_APCS_FRAME   \
++      | ARM_FLAG_MMU_TRAPS )
+ #endif
+ /* Now we define the strings used to build the spec file.  */
+diff -urN gcc-3.4.1-old/gcc/config/arm/xscale-elf.h gcc-3.4.1/gcc/config/arm/xscale-elf.h
+--- gcc-3.4.1-old/gcc/config/arm/xscale-elf.h  2003-07-01 18:26:43.000000000 -0500
++++ gcc-3.4.1/gcc/config/arm/xscale-elf.h      2004-09-02 21:51:15.000000000 -0500
+@@ -49,11 +49,12 @@
+                    endian, regardless of the endian-ness of the memory
+                    system.  */
+                    
+-#define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mcpu=xscale} \
+-  %{mhard-float:-mfpu=fpa} \
+-  %{!mhard-float: %{msoft-float:-mfpu=softfpa;:-mfpu=softvfp}}"
++#define SUBTARGET_EXTRA_ASM_SPEC "\
++%{!mcpu=*:-mcpu=xscale} \
++%{mhard-float:-mfpu=fpa} \
++%{!mhard-float: %{msoft-float:-mfpu=softfpa} %{!msoft-float:-mfpu=softvfp}}"
+ #ifndef MULTILIB_DEFAULTS
+ #define MULTILIB_DEFAULTS \
+-  { "mlittle-endian", "mno-thumb-interwork", "marm", "msoft-float" }
++  { "mlittle-endian", "mno-thumb-interwork", "marm" }
+ #endif
index fb5915d6c1f64042d075f3975e14a7faad54b2df..f2f0a56be82019c6a9d0189c52e8bb83966593e4 100644 (file)
@@ -28,6 +28,9 @@ choice
        config BR2_GCC_VERSION_3_4_5
                bool "gcc 3.4.5"
 
+       config BR2_GCC_VERSION_3_4_6
+               bool "gcc 3.4.6"
+
        config BR2_GCC_VERSION_4_0_0
                depends !BR2_nios2
                bool "gcc 4.0.0"
@@ -62,6 +65,7 @@ config BR2_GCC_VERSION
        default "3.4.3"     if BR2_GCC_VERSION_3_4_3
        default "3.4.4"     if BR2_GCC_VERSION_3_4_4
        default "3.4.5"     if BR2_GCC_VERSION_3_4_5
+       default "3.4.6"     if BR2_GCC_VERSION_3_4_6
        default "4.0.0"     if BR2_GCC_VERSION_4_0_0
        default "4.0.1"     if BR2_GCC_VERSION_4_0_1
        default "4.0.2"     if BR2_GCC_VERSION_4_0_2