From 7eb9574e2b79b0f23b945850c59c1695bd3d9dca Mon Sep 17 00:00:00 2001
From: Ivan Kuten <ivan.kuten@promwad.com>
Date: Fri, 23 Nov 2007 10:32:50 +0000
Subject: update the nios2-patches for binutils-2.15 and gcc-3.4.6 with the
 latest sources from Altera, and removes obsolete patches

---
 toolchain/gcc/3.4.6/900-nios2.patch                | 5118 ++++++++++++++++++--
 toolchain/gcc/3.4.6/901-nios2-ctor_dtor.patch      |   52 -
 .../gcc/3.4.6/nios2-config-fix.patch.conditional   |   19 -
 toolchain/gcc/gcc-uclibc-3.x.mk                    |    3 -
 4 files changed, 4642 insertions(+), 550 deletions(-)

(limited to 'toolchain/gcc')

diff --git a/toolchain/gcc/3.4.6/900-nios2.patch b/toolchain/gcc/3.4.6/900-nios2.patch
index bfa06a21c..3a84d01ab 100644
--- a/toolchain/gcc/3.4.6/900-nios2.patch
+++ b/toolchain/gcc/3.4.6/900-nios2.patch
@@ -1,17 +1,28 @@
---- 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
+diff --git a/config.sub b/config.sub
+index d2e3557..2297c30 100755
+--- a/config.sub
++++ b/config.sub
+@@ -276,6 +276,15 @@ case $basic_machine in
+ 		basic_machine=$basic_machine-unknown
+ 		os=-none
+ 		;;
++	# JBG
++	nios2 | nios2-* | nios2el | nios2el-*)
++		basic_machine=nios2-altera
++		os=-none_el
++		;;
++	nios2eb | nios2eb-*)
++		basic_machine=nios2-altera
++		os=-none_eb
++		;;
+ 	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ 		;;
+ 
+diff --git a/gcc/combine.c b/gcc/combine.c
+index 8f43c23..02648b1 100644
+--- a/gcc/combine.c
++++ b/gcc/combine.c
+@@ -4381,6 +4381,14 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int last,
  					 mode);
  	    }
  
@@ -26,7 +37,7 @@
  	  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
+@@ -4392,6 +4400,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int last,
  				 gen_lowpart_for_combine (mode, op0),
  				 const1_rtx);
  	    }
@@ -34,8 +45,62 @@
  
  	  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
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index d22f34b..4ecb6e9 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -1337,6 +1337,17 @@ m32rle-*-linux*)
+ 		thread_file='posix'
+ 	fi
+ 	;;
++# JBG
++nios2-*-elf*_eb)
++	tm_file="elfos.h nios2/big.h ${tm_file}"
++	;;
++nios2-*-elf*)
++	tm_file="elfos.h ${tm_file}"
++	;;
++nios2-*-uclibc*)	# Altera Nios2 running uClinux with uClibc
++	tm_file="elfos.h ${tm_file} nios2/nios2-uclibc.h"
++	tmake_file=nios2/t-nios2-uclibc
++	;;
+ # m68hc11 and m68hc12 share the same machine description.
+ m68hc11-*-*|m6811-*-*)
+ 	tm_file="dbxelf.h elfos.h m68hc11/m68hc11.h"
+diff --git a/gcc/config/nios2/big.h b/gcc/config/nios2/big.h
+new file mode 100644
+index 0000000..b7b1731
+--- /dev/null
++++ b/gcc/config/nios2/big.h
+@@ -0,0 +1,23 @@
++/*
++  big.h - Additional definitions for nios2 targets that default to big-endian
++
++  Copyright (C) 2006 Altera
++
++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_ENDIAN_DEFAULT BIG_ENDIAN_FLAG
+diff --git a/gcc/config/nios2/crti.asm b/gcc/config/nios2/crti.asm
+new file mode 100644
+index 0000000..1fcfeb2
+--- /dev/null
++++ b/gcc/config/nios2/crti.asm
 @@ -0,0 +1,88 @@
 +/*
 +  Copyright (C) 2003 
@@ -125,8 +190,11 @@
 +	mov	fp, sp
 +	
 +
---- gcc-3.4.3/gcc/config/nios2/crtn.asm
-+++ gcc-3.4.3-nios2/gcc/config/nios2/crtn.asm
+diff --git a/gcc/config/nios2/crtn.asm b/gcc/config/nios2/crtn.asm
+new file mode 100644
+index 0000000..e337480
+--- /dev/null
++++ b/gcc/config/nios2/crtn.asm
 @@ -0,0 +1,70 @@
 +/*
 +  Copyright (C) 2003 
@@ -198,8 +266,11 @@
 +	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
+diff --git a/gcc/config/nios2/lib2-divmod-hi.c b/gcc/config/nios2/lib2-divmod-hi.c
+new file mode 100644
+index 0000000..10bd6e4
+--- /dev/null
++++ b/gcc/config/nios2/lib2-divmod-hi.c
 @@ -0,0 +1,123 @@
 +
 +/* We include auto-host.h here to get HAVE_GAS_HIDDEN.  This is
@@ -324,8 +395,11 @@
 +  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
+diff --git a/gcc/config/nios2/lib2-divmod.c b/gcc/config/nios2/lib2-divmod.c
+new file mode 100644
+index 0000000..00e730d
+--- /dev/null
++++ b/gcc/config/nios2/lib2-divmod.c
 @@ -0,0 +1,126 @@
 +
 +/* We include auto-host.h here to get HAVE_GAS_HIDDEN.  This is
@@ -453,8 +527,11 @@
 +  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
+diff --git a/gcc/config/nios2/lib2-divtable.c b/gcc/config/nios2/lib2-divtable.c
+new file mode 100644
+index 0000000..48a7bd7
+--- /dev/null
++++ b/gcc/config/nios2/lib2-divtable.c
 @@ -0,0 +1,46 @@
 +
 +/* We include auto-host.h here to get HAVE_GAS_HIDDEN.  This is
@@ -502,8 +579,11 @@
 +  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
+diff --git a/gcc/config/nios2/lib2-mul.c b/gcc/config/nios2/lib2-mul.c
+new file mode 100644
+index 0000000..8511b33
+--- /dev/null
++++ b/gcc/config/nios2/lib2-mul.c
 @@ -0,0 +1,103 @@
 +/* while we are debugging (ie compile outside of gcc build) 
 +   disable gcc specific headers */
@@ -608,10 +688,16 @@
 +  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 @@
-+
+diff --git a/gcc/config/nios2/nios2-dp-bit.c b/gcc/config/nios2/nios2-dp-bit.c
+new file mode 100644
+index 0000000..4d63748
+--- /dev/null
++++ b/gcc/config/nios2/nios2-dp-bit.c
+@@ -0,0 +1,1655 @@
++
++#ifndef __nios2_big_endian__
++#define FLOAT_BIT_ORDER_MISMATCH
++#endif
 +/* 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
@@ -2263,10 +2349,16 @@
 +
 +#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 @@
+diff --git a/gcc/config/nios2/nios2-fp-bit.c b/gcc/config/nios2/nios2-fp-bit.c
+new file mode 100644
+index 0000000..839ffcc
+--- /dev/null
++++ b/gcc/config/nios2/nios2-fp-bit.c
+@@ -0,0 +1,1655 @@
 +#define FLOAT
++#ifndef __nios2_big_endian__
++#define FLOAT_BIT_ORDER_MISMATCH
++#endif
 +/* 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
@@ -3918,9 +4010,12 @@
 +
 +#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 @@
+diff --git a/gcc/config/nios2/nios2-protos.h b/gcc/config/nios2/nios2-protos.h
+new file mode 100644
+index 0000000..dc75c4f
+--- /dev/null
++++ b/gcc/config/nios2/nios2-protos.h
+@@ -0,0 +1,78 @@
 +/* Subroutines for assembler code output for Altera NIOS 2G NIOS2 version.
 +   Copyright (C) 2003 Altera 
 +   Contributed by Jonah Graham (jgraham@altera.com).
@@ -3951,7 +4046,8 @@
 +extern void expand_prologue (void);
 +extern void expand_epilogue (bool);
 +extern void function_profiler (FILE *, int);
-+
++extern enum reg_class reg_class_from_constraint (char, const char *);
++extern void nios2_register_target_pragmas (void);
 +
 +#ifdef RTX_CODE
 +extern int nios2_legitimate_address (rtx, enum machine_mode, int);
@@ -3975,11 +4071,18 @@
 +extern int custom_insn_opcode (rtx, enum machine_mode);
 +extern int rdwrctl_operand (rtx, enum machine_mode);
 +
++/* custom fpu instruction output */
++extern const char *nios2_output_fpu_insn_cmps (rtx, enum rtx_code);
++extern const char *nios2_output_fpu_insn_cmpd (rtx, enum rtx_code);
++
 +# 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 nios2_must_pass_in_stack (enum machine_mode, tree);
 +extern int function_arg_partial_nregs (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
++extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
++extern int nios2_function_arg_padding (enum machine_mode, tree);
++extern int nios2_block_reg_padding (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);
 +
@@ -3991,12 +4094,96 @@
 +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 @@
+diff --git a/gcc/config/nios2/nios2-uclibc.h b/gcc/config/nios2/nios2-uclibc.h
+new file mode 100644
+index 0000000..af98cdd
+--- /dev/null
++++ b/gcc/config/nios2/nios2-uclibc.h
+@@ -0,0 +1,75 @@
++#ifdef USE_UCLIBC
++
++#undef TARGET_SWITCHES
++#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") },			\
++    { "stack-check", STACK_CHECK_FLAG,				\
++      N_("Enable stack limit checking.") },				\
++    { "no-stack-check", -STACK_CHECK_FLAG,				\
++      N_("Disable stack limit checking (default).") },				\
++    { "reverse-bitfields", REVERSE_BITFIELDS_FLAG,          \
++      N_("Reverse the order of bitfields in a struct.") },      \
++    { "no-reverse-bitfields", -REVERSE_BITFIELDS_FLAG,          \
++      N_("Use the normal order of bitfields in a struct (default).") }, \
++    { "eb", BIG_ENDIAN_FLAG,                                            \
++      N_("Use big-endian byte order") },                                \
++    { "el", -BIG_ENDIAN_FLAG,                                           \
++      N_("Use little-endian byte order") },                             \
++    { "", TARGET_DEFAULT, 0 }				\
++}
++
++/* The GNU C++ standard library requires that these macros be defined.  */
++#undef CPLUSPLUS_CPP_SPEC
++#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
++
++#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=} \
++ crti%O%s crtbegin%O%s \
++"
++
++#undef ENDFILE_SPEC 
++#define ENDFILE_SPEC \
++ " crtend%O%s crtn%O%s"
++
++#endif /* USE_UCLIBC */
+diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c
+new file mode 100644
+index 0000000..8723a86
+--- /dev/null
++++ b/gcc/config/nios2/nios2.c
+@@ -0,0 +1,4694 @@
 +/* Subroutines for assembler code output for Altera NIOS 2G NIOS2 version.
-+   Copyright (C) 2003 Altera
-+   Contributed by Jonah Graham (jgraham@altera.com).
++   Copyright (C) 2005 Altera
++   Contributed by Jonah Graham (jgraham@altera.com) and Will Reece (wreece@altera.com).
 +
 +This file is part of GNU CC.
 +
@@ -4043,6 +4230,8 @@
 +#include "optabs.h"
 +#include "target.h"
 +#include "target-def.h"
++#include "c-pragma.h"           /* for c_register_pragma */
++#include "cpplib.h"             /* for CPP_NUMBER */
 +
 +/* local prototypes */
 +static bool nios2_rtx_costs (rtx, int, int, int *);
@@ -4055,6 +4244,16 @@
 +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);
++
++/* 0 --> no #pragma seen
++   1 --> in scope of #pragma reverse_bitfields
++   -1 --> in scope of #pragma no_reverse_bitfields */
++static int nios2_pragma_reverse_bitfields_flag = 0;
++static void nios2_pragma_reverse_bitfields (struct cpp_reader *);
++static void nios2_pragma_no_reverse_bitfields (struct cpp_reader *);
++static tree nios2_handle_struct_attribute (tree *, tree, tree, int, bool *);
++static void nios2_insert_attributes (tree, tree *);
++static bool nios2_reverse_bitfield_layout_p (tree record_type);
 +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);
@@ -4076,6 +4275,9 @@
 +#undef  TARGET_SECTION_TYPE_FLAGS
 +#define TARGET_SECTION_TYPE_FLAGS  nios2_section_type_flags
 +
++#undef TARGET_REVERSE_BITFIELD_LAYOUT_P
++#define TARGET_REVERSE_BITFIELD_LAYOUT_P nios2_reverse_bitfield_layout_p
++
 +#undef TARGET_INIT_BUILTINS
 +#define TARGET_INIT_BUILTINS nios2_init_builtins
 +#undef TARGET_EXPAND_BUILTIN
@@ -4087,6 +4289,24 @@
 +#undef TARGET_RTX_COSTS
 +#define TARGET_RTX_COSTS nios2_rtx_costs
 +
++const struct attribute_spec nios2_attribute_table[] =
++{
++  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
++  { "reverse_bitfields",    0, 0, false, false,  false, nios2_handle_struct_attribute },
++  { "no_reverse_bitfields", 0, 0, false, false,  false, nios2_handle_struct_attribute },
++  { "pragma_reverse_bitfields",    0, 0, false, false,  false, NULL },
++  { "pragma_no_reverse_bitfields", 0, 0, false, false,  false, NULL },
++  { NULL,        0, 0, false, false, false, NULL }
++};
++
++#undef TARGET_ATTRIBUTE_TABLE
++#define TARGET_ATTRIBUTE_TABLE nios2_attribute_table
++
++#undef  TARGET_INSERT_ATTRIBUTES
++#define TARGET_INSERT_ATTRIBUTES nios2_insert_attributes
++
++/* ??? Might want to redefine TARGET_RETURN_IN_MSB here to handle
++   big-endian case; depends on what ABI we choose. */
 +
 +struct gcc_target targetm = TARGET_INITIALIZER;
 +
@@ -4125,11 +4345,27 @@
 +
 +
 +/***************************************
-+ * Section encodings
++ * Register Classes
 + ***************************************/
 +
++enum reg_class 
++reg_class_from_constraint (char chr, const char *str)
++{
++  if (chr == 'D' && ISDIGIT (str[1]) && ISDIGIT (str[2]))
++    {
++      int regno;
++      int ones = str[2] - '0';
++      int tens = str[1] - '0';
++      
++      regno = ones + (10 * tens);
++      if (regno < 0 || regno > 31)
++        return NO_REGS;
 +
++      return D00_REG + regno;
++    }
 +
++  return NO_REGS;
++}
 +
 +
 +/***************************************
@@ -4239,7 +4475,7 @@
 +{
 +  int i;
 +  HOST_WIDE_INT total_frame_size;
-+  int cfa_store_offset;
++  int cfa_store_offset = 0;
 +  rtx insn;
 +  rtx cfa_store_reg = 0;
 +
@@ -4304,6 +4540,11 @@
 +	      = cfun->machine->frame.save_regs_offset
 +		+ cfun->machine->frame.save_reg_rounded;
 +	}
++
++      if (current_function_limit_stack)
++	{
++	  emit_insn (gen_stack_overflow_detect_and_trap ());
++	}
 +    }
 +
 +  if (MUST_SAVE_REGISTER (RA_REGNO))
@@ -4433,17 +4674,11 @@
 + * ----------------------- */
 +
 +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);
++function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
++{
++  fprintf (file, "\tmov\tr8, ra\n");
 +  fprintf (file, "\tcall\tmcount\n");
-+  fprintf (file, "\tmov\tra, r9\n");
-+  fprintf (file, "\t%s mcount end\n", ASM_COMMENT_START);
++  fprintf (file, "\tmov\tra, r8\n");
 +}
 +
 +
@@ -4593,13 +4828,490 @@
 + *
 + ***************************************/
 +
++/*
++ * Try to take a bit of tedium out of the __builtin_custom_<blah>
++ * builtin functions, too.
++ */
++
++#define NIOS2_FOR_ALL_CUSTOM_BUILTINS \
++  NIOS2_DO_BUILTIN (N,    n,    n    ) \
++  NIOS2_DO_BUILTIN (NI,   ni,   nX   ) \
++  NIOS2_DO_BUILTIN (NF,   nf,   nX   ) \
++  NIOS2_DO_BUILTIN (NP,   np,   nX   ) \
++  NIOS2_DO_BUILTIN (NII,  nii,  nXX  ) \
++  NIOS2_DO_BUILTIN (NIF,  nif,  nXX  ) \
++  NIOS2_DO_BUILTIN (NIP,  nip,  nXX  ) \
++  NIOS2_DO_BUILTIN (NFI,  nfi,  nXX  ) \
++  NIOS2_DO_BUILTIN (NFF,  nff,  nXX  ) \
++  NIOS2_DO_BUILTIN (NFP,  nfp,  nXX  ) \
++  NIOS2_DO_BUILTIN (NPI,  npi,  nXX  ) \
++  NIOS2_DO_BUILTIN (NPF,  npf,  nXX  ) \
++  NIOS2_DO_BUILTIN (NPP,  npp,  nXX  ) \
++  NIOS2_DO_BUILTIN (IN,   in,   Xn   ) \
++  NIOS2_DO_BUILTIN (INI,  ini,  XnX  ) \
++  NIOS2_DO_BUILTIN (INF,  inf,  XnX  ) \
++  NIOS2_DO_BUILTIN (INP,  inp,  XnX  ) \
++  NIOS2_DO_BUILTIN (INII, inii, XnXX ) \
++  NIOS2_DO_BUILTIN (INIF, inif, XnXX ) \
++  NIOS2_DO_BUILTIN (INIP, inip, XnXX ) \
++  NIOS2_DO_BUILTIN (INFI, infi, XnXX ) \
++  NIOS2_DO_BUILTIN (INFF, inff, XnXX ) \
++  NIOS2_DO_BUILTIN (INFP, infp, XnXX ) \
++  NIOS2_DO_BUILTIN (INPI, inpi, XnXX ) \
++  NIOS2_DO_BUILTIN (INPF, inpf, XnXX ) \
++  NIOS2_DO_BUILTIN (INPP, inpp, XnXX ) \
++  NIOS2_DO_BUILTIN (FN,   fn,   Xn   ) \
++  NIOS2_DO_BUILTIN (FNI,  fni,  XnX  ) \
++  NIOS2_DO_BUILTIN (FNF,  fnf,  XnX  ) \
++  NIOS2_DO_BUILTIN (FNP,  fnp,  XnX  ) \
++  NIOS2_DO_BUILTIN (FNII, fnii, XnXX ) \
++  NIOS2_DO_BUILTIN (FNIF, fnif, XnXX ) \
++  NIOS2_DO_BUILTIN (FNIP, fnip, XnXX ) \
++  NIOS2_DO_BUILTIN (FNFI, fnfi, XnXX ) \
++  NIOS2_DO_BUILTIN (FNFF, fnff, XnXX ) \
++  NIOS2_DO_BUILTIN (FNFP, fnfp, XnXX ) \
++  NIOS2_DO_BUILTIN (FNPI, fnpi, XnXX ) \
++  NIOS2_DO_BUILTIN (FNPF, fnpf, XnXX ) \
++  NIOS2_DO_BUILTIN (FNPP, fnpp, XnXX ) \
++  NIOS2_DO_BUILTIN (PN,   pn,   Xn   ) \
++  NIOS2_DO_BUILTIN (PNI,  pni,  XnX  ) \
++  NIOS2_DO_BUILTIN (PNF,  pnf,  XnX  ) \
++  NIOS2_DO_BUILTIN (PNP,  pnp,  XnX  ) \
++  NIOS2_DO_BUILTIN (PNII, pnii, XnXX ) \
++  NIOS2_DO_BUILTIN (PNIF, pnif, XnXX ) \
++  NIOS2_DO_BUILTIN (PNIP, pnip, XnXX ) \
++  NIOS2_DO_BUILTIN (PNFI, pnfi, XnXX ) \
++  NIOS2_DO_BUILTIN (PNFF, pnff, XnXX ) \
++  NIOS2_DO_BUILTIN (PNFP, pnfp, XnXX ) \
++  NIOS2_DO_BUILTIN (PNPI, pnpi, XnXX ) \
++  NIOS2_DO_BUILTIN (PNPF, pnpf, XnXX ) \
++  NIOS2_DO_BUILTIN (PNPP, pnpp, XnXX )
++
 +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= */
 +
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++static const char *NIOS2_CONCAT (nios2_output_fpu_insn_, insn) (rtx); \
++static void NIOS2_CONCAT (nios2_pragma_, insn) (struct cpp_reader *); \
++static void NIOS2_CONCAT (nios2_pragma_no_, insn) (struct cpp_reader *);
++NIOS2_FOR_ALL_FPU_INSNS
++
++nios2_fpu_info nios2_fpu_insns[nios2_fpu_max_insn] = {
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++  { NIOS2_STRINGIFY (opt), \
++    NIOS2_STRINGIFY (insn), \
++    NIOS2_STRINGIFY (args), \
++    0, \
++    -1, \
++    NIOS2_CONCAT (nios2_output_fpu_insn_, insn), \
++    "custom_" NIOS2_STRINGIFY (opt), \
++    NIOS2_CONCAT (nios2_pragma_, insn), \
++    "no_custom_" NIOS2_STRINGIFY (opt), \
++    NIOS2_CONCAT (nios2_pragma_no_, insn), \
++    0, \
++    0, \
++    0, \
++    0, \
++    0 },
++  NIOS2_FOR_ALL_FPU_INSNS
++};
++
++const char *nios2_custom_fpu_cfg_string;
++
++static const char *builtin_custom_seen[256];
++
++static void
++nios2_custom_switch (const char *parameter, int *value, const char *opt)
++{
++  /*
++   * We only document values from 0-255, but we secretly allow -1 so
++   * that the -mno-custom-<opt> switches work.
++   */
++  if (parameter && *parameter)
++    {
++      char *endptr;
++      long v = strtol (parameter, &endptr, 0);
++      if (*endptr)
++        {
++          error ("switch `-mcustom-%s' value `%s' must be a number between 0 and 255",
++                 opt, parameter);
++        }
++      if (v < -1 || v > 255)
++        {
++          error ("switch `-mcustom-%s' value %ld must be between 0 and 255",
++                 opt, v);
++        }
++      *value = (int)v;
++    }
++}
++
++static void
++nios2_custom_check_insns (int is_pragma)
++{
++  int i;
++  int has_double = 0;
++  int errors = 0;
++  const char *ns[256];
++  int ps[256];
++
++  for (i = 0; i < nios2_fpu_max_insn; i++)
++    {
++      if (nios2_fpu_insns[i].is_double && nios2_fpu_insns[i].N >= 0)
++        {
++          has_double = 1;
++        }
++    }
++
++  if (has_double)
++    {
++      for (i = 0; i < nios2_fpu_max_insn; i++)
++        {
++          if (nios2_fpu_insns[i].needed_by_double
++              && nios2_fpu_insns[i].N < 0)
++            {
++              if (is_pragma)
++                {
++                  error ("either switch `-mcustom-%s' or `#pragma custom_%s' is required for double precision floating point",
++                         nios2_fpu_insns[i].option,
++                         nios2_fpu_insns[i].option);
++                }
++              else
++                {
++                  error ("switch `-mcustom-%s' is required for double precision floating point",
++                         nios2_fpu_insns[i].option);
++                }
++              errors = 1;
++            }
++        }
++    }
++
++  /*
++   * Warn if the user has certain exotic operations that won't get used
++   * without -funsafe-math-optimizations, See expand_builtin () in
++   * bulitins.c.
++   */
++  if (!flag_unsafe_math_optimizations)
++    {
++      for (i = 0; i < nios2_fpu_max_insn; i++)
++        {
++          if (nios2_fpu_insns[i].needs_unsafe && nios2_fpu_insns[i].N >= 0)
++            {
++              warning ("%s%s' has no effect unless -funsafe-math-optimizations is specified",
++                       is_pragma ? "`#pragma custom_" : "switch `-mcustom-",
++                       nios2_fpu_insns[i].option);
++              /* Just one warning per function per compilation unit, please. */
++              nios2_fpu_insns[i].needs_unsafe = 0;
++            }
++        }
++    }
++
++  /*
++   * Warn if the user is trying to use -mcustom-fmins et. al, that won't
++   * get used without -ffinite-math-only.  See fold in fold () in
++   * fold-const.c
++   */
++  if (!flag_finite_math_only)
++    {
++      for (i = 0; i < nios2_fpu_max_insn; i++)
++        {
++          if (nios2_fpu_insns[i].needs_finite && nios2_fpu_insns[i].N >= 0)
++            {
++              warning ("%s%s' has no effect unless -ffinite-math-only is specified",
++                       is_pragma ? "`#pragma custom_" : "switch `-mcustom-",
++                       nios2_fpu_insns[i].option);
++              /* Just one warning per function per compilation unit, please. */
++              nios2_fpu_insns[i].needs_finite = 0;
++            }
++        }
++    }
++
++  /*
++   * Warn the user about double precision divide braindamage until we
++   * can fix it properly.  See the RDIV_EXPR case of expand_expr_real in
++   * expr.c.
++   */
++  {
++    static int warned = 0;
++    if (flag_unsafe_math_optimizations
++        && !optimize_size
++        && nios2_fpu_insns[nios2_fpu_divdf3].N >= 0
++        && !warned)
++      {
++        warning ("%s%s' behaves poorly without -Os",
++                 is_pragma ? "`#pragma custom_" : "switch `-mcustom-",
++                 nios2_fpu_insns[nios2_fpu_divdf3].option);
++        warned = 1;
++      }
++  }
++
++  /*
++   * The following bit of voodoo is lifted from the generated file
++   * insn-opinit.c: to allow #pragmas to work properly, we have to tweak
++   * the optab_table manually -- it only gets initialized once after the
++   * switches are handled and before any #pragmas are seen.
++   */
++  if (is_pragma)
++    {
++      /* Only do this if the optabs have already been defined, not
++         when we're handling command line switches. */
++      addv_optab->handlers[SFmode].insn_code =
++      add_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++      addv_optab->handlers[DFmode].insn_code =
++      add_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++      subv_optab->handlers[SFmode].insn_code =
++      sub_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++      subv_optab->handlers[DFmode].insn_code =
++      sub_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++      smulv_optab->handlers[SFmode].insn_code =
++      smul_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++      smulv_optab->handlers[DFmode].insn_code =
++      smul_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++      sdiv_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++      sdiv_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++      negv_optab->handlers[SFmode].insn_code =
++      neg_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++      negv_optab->handlers[DFmode].insn_code =
++      neg_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++      smin_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++      smin_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++      smax_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++      smax_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++      absv_optab->handlers[SFmode].insn_code =
++      abs_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++      absv_optab->handlers[DFmode].insn_code =
++      abs_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++      sqrt_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++      sqrt_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++      cos_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++      cos_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++      sin_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++      sin_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++      tan_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++      tan_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++      atan_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++      atan_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++      exp_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++      exp_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++      log_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++      log_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++      sfloat_optab->handlers[SFmode][SImode].insn_code = CODE_FOR_nothing;
++      sfloat_optab->handlers[DFmode][SImode].insn_code = CODE_FOR_nothing;
++      ufloat_optab->handlers[SFmode][SImode].insn_code = CODE_FOR_nothing;
++      ufloat_optab->handlers[DFmode][SImode].insn_code = CODE_FOR_nothing;
++      sfix_optab->handlers[SImode][SFmode].insn_code = CODE_FOR_nothing;
++      sfix_optab->handlers[SImode][DFmode].insn_code = CODE_FOR_nothing;
++      ufix_optab->handlers[SImode][SFmode].insn_code = CODE_FOR_nothing;
++      ufix_optab->handlers[SImode][DFmode].insn_code = CODE_FOR_nothing;
++      sext_optab->handlers[DFmode][SFmode].insn_code = CODE_FOR_nothing;
++      trunc_optab->handlers[SFmode][DFmode].insn_code = CODE_FOR_nothing;
++      cmp_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
++      cmp_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
++
++      if (HAVE_addsf3)
++        addv_optab->handlers[SFmode].insn_code =
++        add_optab->handlers[SFmode].insn_code = CODE_FOR_addsf3;
++      if (HAVE_adddf3)
++        addv_optab->handlers[DFmode].insn_code =
++        add_optab->handlers[DFmode].insn_code = CODE_FOR_adddf3;
++      if (HAVE_subsf3)
++        subv_optab->handlers[SFmode].insn_code =
++        sub_optab->handlers[SFmode].insn_code = CODE_FOR_subsf3;
++      if (HAVE_subdf3)
++        subv_optab->handlers[DFmode].insn_code =
++        sub_optab->handlers[DFmode].insn_code = CODE_FOR_subdf3;
++      if (HAVE_mulsf3)
++        smulv_optab->handlers[SFmode].insn_code =
++        smul_optab->handlers[SFmode].insn_code = CODE_FOR_mulsf3;
++      if (HAVE_muldf3)
++        smulv_optab->handlers[DFmode].insn_code =
++        smul_optab->handlers[DFmode].insn_code = CODE_FOR_muldf3;
++      if (HAVE_divsf3)
++        sdiv_optab->handlers[SFmode].insn_code = CODE_FOR_divsf3;
++      if (HAVE_divdf3)
++        sdiv_optab->handlers[DFmode].insn_code = CODE_FOR_divdf3;
++      if (HAVE_negsf2)
++        negv_optab->handlers[SFmode].insn_code =
++        neg_optab->handlers[SFmode].insn_code = CODE_FOR_negsf2;
++      if (HAVE_negdf2)
++        negv_optab->handlers[DFmode].insn_code =
++        neg_optab->handlers[DFmode].insn_code = CODE_FOR_negdf2;
++      if (HAVE_minsf3)
++        smin_optab->handlers[SFmode].insn_code = CODE_FOR_minsf3;
++      if (HAVE_mindf3)
++        smin_optab->handlers[DFmode].insn_code = CODE_FOR_mindf3;
++      if (HAVE_maxsf3)
++        smax_optab->handlers[SFmode].insn_code = CODE_FOR_maxsf3;
++      if (HAVE_maxdf3)
++        smax_optab->handlers[DFmode].insn_code = CODE_FOR_maxdf3;
++      if (HAVE_abssf2)
++        absv_optab->handlers[SFmode].insn_code =
++        abs_optab->handlers[SFmode].insn_code = CODE_FOR_abssf2;
++      if (HAVE_absdf2)
++        absv_optab->handlers[DFmode].insn_code =
++        abs_optab->handlers[DFmode].insn_code = CODE_FOR_absdf2;
++      if (HAVE_sqrtsf2)
++        sqrt_optab->handlers[SFmode].insn_code = CODE_FOR_sqrtsf2;
++      if (HAVE_sqrtdf2)
++        sqrt_optab->handlers[DFmode].insn_code = CODE_FOR_sqrtdf2;
++      if (HAVE_cossf2)
++        cos_optab->handlers[SFmode].insn_code = CODE_FOR_cossf2;
++      if (HAVE_cosdf2)
++        cos_optab->handlers[DFmode].insn_code = CODE_FOR_cosdf2;
++      if (HAVE_sinsf2)
++        sin_optab->handlers[SFmode].insn_code = CODE_FOR_sinsf2;
++      if (HAVE_sindf2)
++        sin_optab->handlers[DFmode].insn_code = CODE_FOR_sindf2;
++      if (HAVE_tansf2)
++        tan_optab->handlers[SFmode].insn_code = CODE_FOR_tansf2;
++      if (HAVE_tandf2)
++        tan_optab->handlers[DFmode].insn_code = CODE_FOR_tandf2;
++      if (HAVE_atansf2)
++        atan_optab->handlers[SFmode].insn_code = CODE_FOR_atansf2;
++      if (HAVE_atandf2)
++        atan_optab->handlers[DFmode].insn_code = CODE_FOR_atandf2;
++      if (HAVE_expsf2)
++        exp_optab->handlers[SFmode].insn_code = CODE_FOR_expsf2;
++      if (HAVE_expdf2)
++        exp_optab->handlers[DFmode].insn_code = CODE_FOR_expdf2;
++      if (HAVE_logsf2)
++        log_optab->handlers[SFmode].insn_code = CODE_FOR_logsf2;
++      if (HAVE_logdf2)
++        log_optab->handlers[DFmode].insn_code = CODE_FOR_logdf2;
++      if (HAVE_floatsisf2)
++        sfloat_optab->handlers[SFmode][SImode].insn_code = CODE_FOR_floatsisf2;
++      if (HAVE_floatsidf2)
++        sfloat_optab->handlers[DFmode][SImode].insn_code = CODE_FOR_floatsidf2;
++      if (HAVE_floatunssisf2)
++        ufloat_optab->handlers[SFmode][SImode].insn_code = CODE_FOR_floatunssisf2;
++      if (HAVE_floatunssidf2)
++        ufloat_optab->handlers[DFmode][SImode].insn_code = CODE_FOR_floatunssidf2;
++      if (HAVE_fixsfsi2)
++        sfix_optab->handlers[SImode][SFmode].insn_code = CODE_FOR_fixsfsi2;
++      if (HAVE_fixdfsi2)
++        sfix_optab->handlers[SImode][DFmode].insn_code = CODE_FOR_fixdfsi2;
++      if (HAVE_fixunssfsi2)
++        ufix_optab->handlers[SImode][SFmode].insn_code = CODE_FOR_fixunssfsi2;
++      if (HAVE_fixunsdfsi2)
++        ufix_optab->handlers[SImode][DFmode].insn_code = CODE_FOR_fixunsdfsi2;
++      if (HAVE_extendsfdf2)
++        sext_optab->handlers[DFmode][SFmode].insn_code = CODE_FOR_extendsfdf2;
++      if (HAVE_truncdfsf2)
++        trunc_optab->handlers[SFmode][DFmode].insn_code = CODE_FOR_truncdfsf2;
++      if (HAVE_cmpsf)
++        cmp_optab->handlers[SFmode].insn_code = CODE_FOR_cmpsf;
++      if (HAVE_cmpdf)
++        cmp_optab->handlers[DFmode].insn_code = CODE_FOR_cmpdf;
++    }
++
++  /* Check for duplicate values of N */
++  for (i = 0; i < 256; i++)
++    {
++      ns[i] = 0;
++      ps[i] = 0;
++    }
++
++  for (i = 0; i < nios2_fpu_max_insn; i++)
++    {
++      int N = nios2_fpu_insns[i].N;
++      if (N >= 0)
++        {
++          if (ns[N])
++            {
++              error ("%s%s' conflicts with %s%s'",
++                     is_pragma ? "`#pragma custom_" : "switch `-mcustom-",
++                     nios2_fpu_insns[i].option,
++                     ps[N] ? "`#pragma custom_" : "switch `-mcustom-",
++                     ns[N]);
++              errors = 1;
++            }
++          else if (builtin_custom_seen[N])
++            {
++              error ("call to `%s' conflicts with %s%s'",
++                     builtin_custom_seen[N],
++                     (nios2_fpu_insns[i].pragma_seen
++                      ? "`#pragma custom_" : "switch `-mcustom-"),
++                     nios2_fpu_insns[i].option);
++              errors = 1;
++            }
++          else
++            {
++              ns[N] = nios2_fpu_insns[i].option;
++              ps[N] = nios2_fpu_insns[i].pragma_seen;
++            }
++        }
++    }
++
++  if (errors)
++    {
++      fatal_error ("conflicting use of -mcustom switches, #pragmas, and/or __builtin_custom_ functions");
++    }
++}
++
++static void
++nios2_handle_custom_fpu_cfg (const char *cfg, int is_pragma)
++{
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++  int opt = nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].N;
++NIOS2_FOR_ALL_FPU_INSNS
++
++  /*
++   * ??? These are just some sample possibilities.  We'll change these
++   * at the last minute to match the capabilities of the actual fpu.
++   */
++  if (!strcasecmp (cfg, "60-1"))
++    {
++      fmuls = 252;
++      fadds = 253;
++      fsubs = 254;
++      flag_single_precision_constant = 1;
++    }
++  else if (!strcasecmp (cfg, "60-2"))
++    {
++      fmuls = 252;
++      fadds = 253;
++      fsubs = 254;
++      fdivs = 255;
++      flag_single_precision_constant = 1;
++    }
++  else if (!strcasecmp (cfg, "72-3"))
++    {
++      floatus = 243;
++      fixsi   = 244;
++      floatis = 245;
++      fcmpgts = 246;
++      fcmples = 249;
++      fcmpeqs = 250;
++      fcmpnes = 251;
++      fmuls   = 252;
++      fadds   = 253;
++      fsubs   = 254;
++      fdivs   = 255;
++      flag_single_precision_constant = 1;
++    }
++  else
++    {
++      warning ("ignoring unrecognized %sfpu-cfg' value `%s'",
++               is_pragma ? "`#pragma custom_" : "switch -mcustom-", cfg);
++    }
++
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++  nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].N = opt;
++NIOS2_FOR_ALL_FPU_INSNS
++
++  /* Guard against errors in the standard configurations. */
++  nios2_custom_check_insns (is_pragma);
++}
++
 +void
 +override_options ()
 +{
++  int i;
++
 +  /* Function to allocate machine-dependent function status.  */
 +  init_machine_status = &nios2_init_machine_status;
 +
@@ -4617,6 +5329,69 @@
 +      target_flags &= ~HAS_MULX_FLAG;
 +    }
 +
++  /* Set up for stack limit checking */
++  if (TARGET_STACK_CHECK)
++    {
++      stack_limit_rtx = gen_rtx_REG(SImode, ET_REGNO);
++    }
++  
++  for (i = 0; i < nios2_fpu_max_insn; i++)
++    {
++      nios2_fpu_insns[i].is_double = (nios2_fpu_insns[i].args[0] == 'd'
++                                      || nios2_fpu_insns[i].args[0] == 'd'
++                                      || nios2_fpu_insns[i].args[0] == 'd');
++      nios2_fpu_insns[i].needed_by_double = (i == nios2_fpu_nios2_fwrx
++                                             || i == nios2_fpu_nios2_fwry
++                                             || i == nios2_fpu_nios2_frdxlo
++                                             || i == nios2_fpu_nios2_frdxhi
++                                             || i == nios2_fpu_nios2_frdy);
++      nios2_fpu_insns[i].needs_unsafe = (i == nios2_fpu_cossf2
++                                         || i == nios2_fpu_cosdf2
++                                         || i == nios2_fpu_sinsf2
++                                         || i == nios2_fpu_sindf2
++                                         || i == nios2_fpu_tansf2
++                                         || i == nios2_fpu_tandf2
++                                         || i == nios2_fpu_atansf2
++                                         || i == nios2_fpu_atandf2
++                                         || i == nios2_fpu_expsf2
++                                         || i == nios2_fpu_expdf2
++                                         || i == nios2_fpu_logsf2
++                                         || i == nios2_fpu_logdf2);
++      nios2_fpu_insns[i].needs_finite = (i == nios2_fpu_minsf3
++                                         || i == nios2_fpu_maxsf3
++                                         || i == nios2_fpu_mindf3
++                                         || i == nios2_fpu_maxdf3);
++    }
++
++  /*
++   * We haven't seen any __builtin_custom functions yet.
++   */
++  for (i = 0; i < 256; i++)
++    {
++      builtin_custom_seen[i] = 0;
++    }
++
++  /*
++   * Set up default handling for floating point custom instructions.
++   *
++   * Putting things in this order means that the -mcustom-fpu-cfg=
++   * switch will always be overridden by individual -mcustom-fadds=
++   * switches, regardless of the order in which they were specified
++   * on the command line.  ??? Remember to document this.
++   */
++  if (nios2_custom_fpu_cfg_string && *nios2_custom_fpu_cfg_string)
++    {
++      nios2_handle_custom_fpu_cfg (nios2_custom_fpu_cfg_string, 0);
++    }
++
++  for (i = 0; i < nios2_fpu_max_insn; i++)
++    {
++      nios2_custom_switch (nios2_fpu_insns[i].value,
++                           &nios2_fpu_insns[i].N,
++                           nios2_fpu_insns[i].option);
++    }
++
++  nios2_custom_check_insns (0);
 +}
 +
 +void
@@ -4926,6 +5701,78 @@
 +  return test;
 +}
 +
++bool have_nios2_fpu_cmp_insn( enum rtx_code cond_t, enum cmp_type cmp_t );
++enum rtx_code get_reverse_cond(enum rtx_code cond_t);
++
++bool
++have_nios2_fpu_cmp_insn( enum rtx_code cond_t, enum cmp_type cmp_t )
++{
++  if (cmp_t == CMP_SF)
++    {
++      switch (cond_t) {
++      case EQ: 
++        return (nios2_fpu_insns[nios2_fpu_nios2_seqsf].N >= 0);
++      case NE: 
++        return (nios2_fpu_insns[nios2_fpu_nios2_snesf].N >= 0);
++      case GT: 
++        return (nios2_fpu_insns[nios2_fpu_nios2_sgtsf].N >= 0);
++      case GE: 
++        return (nios2_fpu_insns[nios2_fpu_nios2_sgesf].N >= 0);
++      case LT: 
++        return (nios2_fpu_insns[nios2_fpu_nios2_sltsf].N >= 0);
++      case LE: 
++        return (nios2_fpu_insns[nios2_fpu_nios2_slesf].N >= 0);
++      default: 
++        break;
++      }
++    }
++  else if (cmp_t == CMP_DF)
++    {
++      switch (cond_t) {
++      case EQ: 
++        return (nios2_fpu_insns[nios2_fpu_nios2_seqdf].N >= 0);
++      case NE: 
++        return (nios2_fpu_insns[nios2_fpu_nios2_snedf].N >= 0);
++      case GT: 
++        return (nios2_fpu_insns[nios2_fpu_nios2_sgtdf].N >= 0);
++      case GE: 
++        return (nios2_fpu_insns[nios2_fpu_nios2_sgedf].N >= 0);
++      case LT: 
++        return (nios2_fpu_insns[nios2_fpu_nios2_sltdf].N >= 0);
++      case LE: 
++        return (nios2_fpu_insns[nios2_fpu_nios2_sledf].N >= 0);
++      default: 
++        break;
++      }
++    }
++
++  return false;
++}
++
++/* Note that get_reverse_cond() is not the same as get_inverse_cond()
++    get_reverse_cond() means that if the operand order is reversed,
++    what is the operand that is needed to generate the same condition?
++*/
++enum rtx_code
++get_reverse_cond(enum rtx_code cond_t)
++{
++	switch (cond_t)
++	{
++     	case GT: return LT;
++        case GE: return LE;
++        case LT: return GT;
++        case LE: return GE;
++        case GTU: return LTU;
++        case GEU: return LEU;
++        case LTU: return GTU;
++        case LEU: return GEU;
++        default: break;
++    }
++
++	return cond_t;
++}
++
++
 +/* 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)
@@ -4981,8 +5828,6 @@
 +  int branch_p;
 +
 +
-+
-+
 +  test = map_test_to_internal_test (test_code);
 +  if (test == ITEST_MAX)
 +    abort ();
@@ -4995,6 +5840,56 @@
 +
 +  branch_p = (destination != 0);
 +
++  /* Handle floating point comparison directly. */
++  if (branch_type == CMP_SF || branch_type == CMP_DF)
++    {
++
++      bool reverse_operands = false;
++
++      enum machine_mode float_mode = (branch_type == CMP_SF) ? SFmode : DFmode;
++
++      if (!register_operand (cmp0, float_mode)
++          || !register_operand (cmp1, float_mode))
++        {
++          abort ();
++        }
++
++      if (branch_p)
++        {
++        test_code = p_info->test_code_reg;
++        reverse_operands = (p_info->reverse_regs);
++      }
++
++      if ( !have_nios2_fpu_cmp_insn(test_code, branch_type) &&
++           have_nios2_fpu_cmp_insn(get_reverse_cond(test_code), branch_type) )
++        {
++          test_code = get_reverse_cond(test_code);
++          reverse_operands = !reverse_operands;
++        }
++      
++      if (reverse_operands)
++        {
++          rtx temp = cmp0;
++          cmp0 = cmp1;
++          cmp1 = temp;
++        }
++
++      if (branch_p)
++        {
++          rtx cond = gen_rtx (test_code, SImode, cmp0, cmp1);
++          rtx label = gen_rtx_LABEL_REF (VOIDmode, destination);
++          rtx insn = gen_rtx_SET (VOIDmode, pc_rtx,
++                                  gen_rtx_IF_THEN_ELSE (VOIDmode,
++                                                        cond, label, pc_rtx));
++          emit_jump_insn (insn);
++        }
++      else
++        {
++          emit_move_insn (result, gen_rtx (test_code, SImode, cmp0, cmp1));
++        }
++      return;
++    }
++
 +  /* We can't, under any circumstances, have const_ints in cmp0
 +     ??? Actually we could have const0 */
 +  if (GET_CODE (cmp0) == CONST_INT)
@@ -5172,10 +6067,10 @@
 +
 +	if (REG_P (op0) && REG_P (op1))
 +	  ret_val = 0;
-+	else if (REG_P (op0) && CONSTANT_P (op1))
++    else if (REG_P (op0) && GET_CODE (op1) == CONST_INT)
 +	  ret_val = REG_OK_FOR_BASE_P2 (op0, strict)
 +	    && SMALL_INT (INTVAL (op1));
-+	else if (REG_P (op1) && CONSTANT_P (op0))
++    else if (REG_P (op1) && GET_CODE (op0) == CONST_INT)
 +	  ret_val = REG_OK_FOR_BASE_P2 (op1, strict)
 +	    && SMALL_INT (INTVAL (op0));
 +	else
@@ -5218,7 +6113,7 @@
 +
 +      /* 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)
++      if (size > 0 && (unsigned HOST_WIDE_INT)size <= nios2_section_threshold)
 +	return true;
 +    }
 +
@@ -5269,12 +6164,226 @@
 +  return flags;
 +}
 +
++/* Handle a #pragma reverse_bitfields */
++static void
++nios2_pragma_reverse_bitfields (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
++{
++  nios2_pragma_reverse_bitfields_flag = 1; /* Reverse */
++}
 +
++/* Handle a #pragma no_reverse_bitfields */
++static void
++nios2_pragma_no_reverse_bitfields (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
++{
++  nios2_pragma_reverse_bitfields_flag = -1; /* Forward */
++}
 +
++/* Handle the various #pragma custom_<switch>s */
++static void
++nios2_pragma_fpu (int *value, const char *opt, int *seen)
++{
++  tree t;
++  if (c_lex (&t) != CPP_NUMBER)
++    {
++      error ("`#pragma custom_%s' value must be a number between 0 and 255",
++             opt);
++      return;
++    }
 +
-+/*****************************************
-+ * Defining the Output Assembler Language
-+ *****************************************/
++  if (TREE_INT_CST_HIGH (t) == 0
++      && TREE_INT_CST_LOW (t) <= 255)
++    {
++      *value = (int)TREE_INT_CST_LOW (t);
++      *seen = 1;
++    }
++  else
++    {
++      error ("`#pragma custom_%s' value must be between 0 and 255", opt);
++    }
++  nios2_custom_check_insns (1);
++}
++
++/* Handle the various #pragma no_custom_<switch>s */
++static void
++nios2_pragma_no_fpu (int *value, const char *opt ATTRIBUTE_UNUSED)
++{
++  *value = -1;
++  nios2_custom_check_insns (1);
++}
++
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++static void \
++NIOS2_CONCAT (nios2_pragma_, insn) \
++  (struct cpp_reader *pfile ATTRIBUTE_UNUSED) \
++{ \
++  nios2_fpu_info *inf = &(nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)]); \
++  nios2_pragma_fpu (&(inf->N), inf->option, &(inf->pragma_seen)); \
++} \
++static void \
++NIOS2_CONCAT (nios2_pragma_no_, insn) \
++  (struct cpp_reader *pfile ATTRIBUTE_UNUSED) \
++{ \
++  nios2_fpu_info *inf = &(nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)]); \
++  nios2_pragma_no_fpu (&(inf->N), inf->option); \
++}
++NIOS2_FOR_ALL_FPU_INSNS
++
++static void
++nios2_pragma_handle_custom_fpu_cfg (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
++{
++  tree t;
++  if (c_lex (&t) != CPP_STRING)
++    {
++      error ("`#pragma custom_fpu_cfg' value must be a string");
++      return;
++    }
++
++  if (TREE_STRING_LENGTH (t) > 0)
++    {
++      nios2_handle_custom_fpu_cfg (TREE_STRING_POINTER (t), 1);
++    }
++}
++
++void
++nios2_register_target_pragmas ()
++{
++  int i;
++
++  c_register_pragma (0, "reverse_bitfields",
++                     nios2_pragma_reverse_bitfields);
++  c_register_pragma (0, "no_reverse_bitfields",
++                     nios2_pragma_no_reverse_bitfields);
++
++  for (i = 0; i < nios2_fpu_max_insn; i++)
++    {
++      nios2_fpu_info *inf = &(nios2_fpu_insns[i]);
++      c_register_pragma (0, inf->pname, inf->pragma);
++      c_register_pragma (0, inf->nopname, inf->nopragma);
++    }
++
++  c_register_pragma (0, "custom_fpu_cfg",
++                     nios2_pragma_handle_custom_fpu_cfg);
++}
++
++/* Handle a "reverse_bitfields" or "no_reverse_bitfields" attribute.
++   ??? What do these attributes mean on a union? */
++static tree
++nios2_handle_struct_attribute (tree *node, tree name,
++                               tree args ATTRIBUTE_UNUSED,
++                               int flags ATTRIBUTE_UNUSED,
++                               bool *no_add_attrs)
++{
++  tree *type = NULL;
++  if (DECL_P (*node))
++    {
++      if (TREE_CODE (*node) == TYPE_DECL)
++        {
++          type = &TREE_TYPE (*node);
++        }
++    }
++  else
++    {
++      type = node;
++    }
++
++  if (!(type && (TREE_CODE (*type) == RECORD_TYPE
++                 || TREE_CODE (*type) == UNION_TYPE)))
++    {
++      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
++      *no_add_attrs = true;
++    }
++
++  else if ((is_attribute_p ("reverse_bitfields", name)
++            && lookup_attribute ("no_reverse_bitfields",
++                                 TYPE_ATTRIBUTES (*type)))
++           || ((is_attribute_p ("no_reverse_bitfields", name)
++                && lookup_attribute ("reverse_bitfields",
++                                     TYPE_ATTRIBUTES (*type)))))
++    {
++      warning ("`%s' incompatible attribute ignored",
++               IDENTIFIER_POINTER (name));
++      *no_add_attrs = true;
++    }
++
++  return NULL_TREE;
++}
++
++/*
++  Add __attribute__ ((pragma_reverse_bitfields)) when in the scope of a
++  #pragma reverse_bitfields, or __attribute__
++  ((pragma_no_reverse_bitfields)) when in the scope of a #pragma
++  no_reverse_bitfields.  This gets called before
++  nios2_handle_struct_attribute above, so we can't just reuse the same
++  attributes.
++*/
++static void
++nios2_insert_attributes (tree node, tree *attr_ptr)
++{
++  tree type = NULL;
++  if (DECL_P (node))
++    {
++      if (TREE_CODE (node) == TYPE_DECL)
++        {
++          type = TREE_TYPE (node);
++        }
++    }
++  else
++    {
++      type = node;
++    }
++
++  if (!type
++      || (TREE_CODE (type) != RECORD_TYPE
++          && TREE_CODE (type) != UNION_TYPE))
++    {
++      /* We can ignore things other than structs & unions */
++      return;
++    }
++
++  if (lookup_attribute ("reverse_bitfields", TYPE_ATTRIBUTES (type))
++      || lookup_attribute ("no_reverse_bitfields", TYPE_ATTRIBUTES (type)))
++    {
++      /* If an attribute is already set, it silently overrides the
++         current #pragma, if any */
++      return;
++    }
++
++  if (nios2_pragma_reverse_bitfields_flag)
++    {
++      const char *id = (nios2_pragma_reverse_bitfields_flag == 1 ?
++                        "pragma_reverse_bitfields" :
++                        "pragma_no_reverse_bitfields");
++      /* No attribute set, and we are in the scope of a #pragma */
++      *attr_ptr = tree_cons (get_identifier (id), NULL, *attr_ptr);
++    }
++}
++
++
++/*
++ * The attributes take precedence over the pragmas, which in turn take
++ * precedence over the compile-time switches.
++ */
++static bool
++nios2_reverse_bitfield_layout_p (tree record_type)
++{
++  return ((TARGET_REVERSE_BITFIELDS
++           && !lookup_attribute ("pragma_no_reverse_bitfields",
++                                 TYPE_ATTRIBUTES (record_type))
++           && !lookup_attribute ("no_reverse_bitfields",
++                                 TYPE_ATTRIBUTES (record_type)))
++          || (lookup_attribute ("pragma_reverse_bitfields",
++                                TYPE_ATTRIBUTES (record_type))
++              && !lookup_attribute ("no_reverse_bitfields",
++                                    TYPE_ATTRIBUTES (record_type)))
++          || lookup_attribute ("reverse_bitfields",
++                               TYPE_ATTRIBUTES (record_type)));
++}
++
++
++/*****************************************
++ * Defining the Output Assembler Language
++ *****************************************/
 +
 +/* -------------- *
 + * Output of Data
@@ -5296,6 +6405,7 @@
 +     H: for %hiadj
 +     L: for %lo
 +     U: for upper half of 32 bit value
++     D: for the upper 32-bits of a 64-bit double value
 + */
 +
 +void
@@ -5338,6 +6448,12 @@
 +	  fprintf (file, "%s", reg_names[REGNO (op)]);
 +	  return;
 +	}
++      else if (letter == 'D')
++        {
++          fprintf (file, "%s", reg_names[REGNO (op)+1]);
++          return;
++        }
++      break;
 +
 +    case CONST_INT:
 +      if (INTVAL (op) == 0 && letter == 'z')
@@ -5379,6 +6495,7 @@
 +	  fprintf (file, ")");
 +	  return;
 +	}
++      break;
 +
 +
 +    case SUBREG:
@@ -5388,6 +6505,7 @@
 +	  output_address (op);
 +	  return;
 +	}
++      break;
 +
 +    case CODE_LABEL:
 +      if (letter == 0)
@@ -5395,6 +6513,7 @@
 +	  output_addr_const (file, op);
 +	  return;
 +	}
++      break;
 +
 +    default:
 +      break;
@@ -5575,6 +6694,431 @@
 +
 +
 +
++/*****************************************************************************
++**
++** custom fpu instruction output
++**
++*****************************************************************************/
++
++static const char *nios2_custom_fpu_insn_zdz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_zsz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_szz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_sss (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_ssz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_iss (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_ddd (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_ddz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_idd (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_siz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_suz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_diz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_duz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_isz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_usz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_idz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_udz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_dsz (rtx, int, const char *);
++static const char *nios2_custom_fpu_insn_sdz (rtx, int, const char *);
++
++static const char *
++nios2_custom_fpu_insn_zdz (rtx insn, int N, const char *opt)
++{
++  static char buf[1024];
++
++  if (N < 0)
++    {
++      fatal_insn ("attempt to use disabled fpu instruction", insn);
++    }
++  if (snprintf (buf, sizeof (buf),
++                "custom\t%d, zero, %%0, %%D0 # %s %%0",
++                N, opt) >= (int)sizeof (buf))
++    {
++      fatal_insn ("buffer overflow", insn);
++    }
++  return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_zsz (rtx insn, int N, const char *opt)
++{
++  static char buf[1024];
++
++  if (N < 0)
++    {
++      fatal_insn ("attempt to use disabled fpu instruction", insn);
++    }
++  if (snprintf (buf, sizeof (buf),
++                "custom\t%d, zero, %%0, zero # %s %%0",
++                N, opt) >= (int)sizeof (buf))
++    {
++      fatal_insn ("buffer overflow", insn);
++    }
++  return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_szz (rtx insn, int N, const char *opt)
++{
++  static char buf[1024];
++
++  if (N < 0)
++    {
++      fatal_insn ("attempt to use disabled fpu instruction", insn);
++    }
++  if (snprintf (buf, sizeof (buf),
++                "custom\t%d, %%0, zero, zero # %s %%0",
++                N, opt) >= (int)sizeof (buf))
++    {
++      fatal_insn ("buffer overflow", insn);
++    }
++  return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_sss (rtx insn, int N, const char *opt)
++{
++  static char buf[1024];
++
++  if (N < 0)
++    {
++      fatal_insn ("attempt to use disabled fpu instruction", insn);
++    }
++  if (snprintf (buf, sizeof (buf),
++                "custom\t%d, %%0, %%1, %%2 # %s %%0, %%1, %%2",
++                N, opt) >= (int)sizeof (buf))
++    {
++      fatal_insn ("buffer overflow", insn);
++    }
++  return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_ssz (rtx insn, int N, const char *opt)
++{
++  static char buf[1024];
++
++  if (N < 0)
++    {
++      fatal_insn ("attempt to use disabled fpu instruction", insn);
++    }
++  if (snprintf (buf, sizeof (buf),
++                "custom\t%d, %%0, %%1, zero # %s %%0, %%1",
++                N, opt) >= (int)sizeof (buf))
++    {
++      fatal_insn ("buffer overflow", insn);
++    }
++  return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_iss (rtx insn, int N, const char *opt)
++{
++  return nios2_custom_fpu_insn_sss (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_ddd (rtx insn, int N, const char *opt)
++{
++  static char buf[1024];
++
++  if (N < 0
++      || nios2_fpu_insns[nios2_fpu_nios2_frdy].N < 0
++      || nios2_fpu_insns[nios2_fpu_nios2_fwrx].N < 0)
++    {
++      fatal_insn ("attempt to use disabled fpu instruction", insn);
++    }
++  if (snprintf (buf, sizeof (buf),
++                "custom\t%d, zero, %%1, %%D1 # fwrx %%1\n\t"
++                "custom\t%d, %%D0, %%2, %%D2 # %s %%0, %%1, %%2\n\t"
++                "custom\t%d, %%0, zero, zero # frdy %%0",
++                nios2_fpu_insns[nios2_fpu_nios2_fwrx].N,
++                N, opt,
++                nios2_fpu_insns[nios2_fpu_nios2_frdy].N) >= (int)sizeof (buf))
++    {
++      fatal_insn ("buffer overflow", insn);
++    }
++  return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_ddz (rtx insn, int N, const char *opt)
++{
++  static char buf[1024];
++
++  if (N < 0 || nios2_fpu_insns[nios2_fpu_nios2_frdy].N < 0)
++    {
++      fatal_insn ("attempt to use disabled fpu instruction", insn);
++    }
++  if (snprintf (buf, sizeof (buf),
++                "custom\t%d, %%D0, %%1, %%D1 # %s %%0, %%1\n\t"
++                "custom\t%d, %%0, zero, zero # frdy %%0",
++                N, opt,
++                nios2_fpu_insns[nios2_fpu_nios2_frdy].N) >= (int)sizeof (buf))
++    {
++      fatal_insn ("buffer overflow", insn);
++    }
++  return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_idd (rtx insn, int N, const char *opt)
++{
++  static char buf[1024];
++
++  if (N < 0 || nios2_fpu_insns[nios2_fpu_nios2_fwrx].N < 0)
++    {
++      fatal_insn ("attempt to use disabled fpu instruction", insn);
++    }
++  if (snprintf (buf, sizeof (buf),
++                "custom\t%d, zero, %%1, %%D1 # fwrx %%1\n\t"
++                "custom\t%d, %%0, %%2, %%D2 # %s %%0, %%1, %%2",
++                nios2_fpu_insns[nios2_fpu_nios2_fwrx].N,
++                N, opt) >= (int)sizeof (buf))
++    {
++      fatal_insn ("buffer overflow", insn);
++    }
++  return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_siz (rtx insn, int N, const char *opt)
++{
++  return nios2_custom_fpu_insn_ssz (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_suz (rtx insn, int N, const char *opt)
++{
++  return nios2_custom_fpu_insn_ssz (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_diz (rtx insn, int N, const char *opt)
++{
++  return nios2_custom_fpu_insn_dsz (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_duz (rtx insn, int N, const char *opt)
++{
++  return nios2_custom_fpu_insn_dsz (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_isz (rtx insn, int N, const char *opt)
++{
++  return nios2_custom_fpu_insn_ssz (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_usz (rtx insn, int N, const char *opt)
++{
++  return nios2_custom_fpu_insn_ssz (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_idz (rtx insn, int N, const char *opt)
++{
++  return nios2_custom_fpu_insn_sdz (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_udz (rtx insn, int N, const char *opt)
++{
++  return nios2_custom_fpu_insn_sdz (insn, N, opt);
++}
++
++static const char *
++nios2_custom_fpu_insn_dsz (rtx insn, int N, const char *opt)
++{
++  static char buf[1024];
++
++  if (N < 0 || nios2_fpu_insns[nios2_fpu_nios2_frdy].N < 0)
++    {
++      fatal_insn ("attempt to use disabled fpu instruction", insn);
++    }
++  if (snprintf (buf, sizeof (buf),
++                "custom\t%d, %%D0, %%1, zero # %s %%0, %%1\n\t"
++                "custom\t%d, %%0, zero, zero # frdy %%0",
++                N, opt,
++                nios2_fpu_insns[nios2_fpu_nios2_frdy].N) >= (int)sizeof (buf))
++    {
++      fatal_insn ("buffer overflow", insn);
++    }
++  return buf;
++}
++
++static const char *
++nios2_custom_fpu_insn_sdz (rtx insn, int N, const char *opt)
++{
++  static char buf[1024];
++
++  if (N < 0)
++    {
++      fatal_insn ("attempt to use disabled fpu instruction", insn);
++    }
++  if (snprintf (buf, sizeof (buf),
++                "custom\t%d, %%0, %%1, %%D1 # %s %%0, %%1",
++                N, opt) >= (int)sizeof (buf))
++    {
++      fatal_insn ("buffer overflow", insn);
++    }
++  return buf;
++}
++
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++static const char * \
++NIOS2_CONCAT (nios2_output_fpu_insn_, insn) (rtx i) \
++{ \
++  return NIOS2_CONCAT (nios2_custom_fpu_insn_, args) \
++           (i, \
++            nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].N, \
++            nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].option); \
++}
++NIOS2_FOR_ALL_FPU_INSNS
++
++
++
++const char *
++nios2_output_fpu_insn_cmps (rtx insn, enum rtx_code cond)
++{
++  static char buf[1024];
++  int N;
++  const char *opt;
++
++  int operandL = 2;
++  int operandR = 3;
++
++  if ( !have_nios2_fpu_cmp_insn(cond, CMP_SF) && 
++       have_nios2_fpu_cmp_insn(get_reverse_cond(cond), CMP_SF) ) {
++
++    int temp = operandL;
++    operandL = operandR;
++    operandR = temp;
++
++    cond = get_reverse_cond(cond);
++  }
++
++  switch (cond)
++    {
++    case EQ:
++      N = nios2_fpu_insns[nios2_fpu_nios2_seqsf].N;
++      opt = "fcmpeqs";
++      break;
++    case NE: 
++      N = nios2_fpu_insns[nios2_fpu_nios2_snesf].N;
++      opt = "fcmpnes";
++      break;
++    case GT: 
++      N = nios2_fpu_insns[nios2_fpu_nios2_sgtsf].N;
++      opt = "fcmpgts"; 
++      break;
++    case GE: 
++      N = nios2_fpu_insns[nios2_fpu_nios2_sgesf].N;
++      opt = "fcmpges";
++      break;
++    case LT:
++      N = nios2_fpu_insns[nios2_fpu_nios2_sltsf].N;
++      opt = "fcmplts";
++      break;
++    case LE:
++      N = nios2_fpu_insns[nios2_fpu_nios2_slesf].N;
++      opt = "fcmples"; break;
++    default: 
++      fatal_insn ("bad single compare", insn);
++    }
++
++  if (N < 0)
++    {
++      fatal_insn ("attempt to use disabled fpu instruction", insn);
++    }
++
++  /*
++   * ??? This raises the whole vexing issue of how to handle
++   * out-of-range branches.  Punt for now, seeing as how nios2-elf-as
++   * doesn't even _try_ to handle out-of-range branches yet!
++   */
++  if (snprintf (buf, sizeof (buf),
++                ".set\tnoat\n\t"
++                "custom\t%d, at, %%%d, %%%d # %s at, %%%d, %%%d\n\t"
++                "bne\tat, zero, %%l1\n\t"
++                ".set\tat",
++                N, operandL, operandR, opt, operandL, operandR) >= (int)sizeof (buf))
++    {
++      fatal_insn ("buffer overflow", insn);
++    }
++  return buf;
++}
++
++const char *
++nios2_output_fpu_insn_cmpd (rtx insn, enum rtx_code cond)
++{
++  static char buf[1024];
++  int N;
++  const char *opt;
++
++  int operandL = 2;
++  int operandR = 3;
++
++  if ( !have_nios2_fpu_cmp_insn(cond, CMP_DF) && 
++       have_nios2_fpu_cmp_insn(get_reverse_cond(cond), CMP_DF) ) {
++
++    int temp = operandL;
++    operandL = operandR;
++    operandR = temp;
++
++    cond = get_reverse_cond(cond);
++  }
++
++  switch (cond)
++    {
++    case EQ: 
++      N = nios2_fpu_insns[nios2_fpu_nios2_seqdf].N; 
++      opt = "fcmpeqd"; 
++      break;
++    case NE: 
++      N = nios2_fpu_insns[nios2_fpu_nios2_snedf].N; 
++      opt = "fcmpned"; 
++      break;
++    case GT: 
++      N = nios2_fpu_insns[nios2_fpu_nios2_sgtdf].N; 
++      opt = "fcmpgtd"; 
++      break;
++    case GE: 
++      N = nios2_fpu_insns[nios2_fpu_nios2_sgedf].N; 
++      opt = "fcmpged"; 
++      break;
++    case LT: 
++      N = nios2_fpu_insns[nios2_fpu_nios2_sltdf].N; 
++      opt = "fcmpltd"; 
++      break;
++    case LE: 
++      N = nios2_fpu_insns[nios2_fpu_nios2_sledf].N; 
++      opt = "fcmpled"; 
++      break;
++    default: 
++      fatal_insn ("bad double compare", insn);
++    }
++
++  if (N < 0 || nios2_fpu_insns[nios2_fpu_nios2_fwrx].N < 0)
++    {
++      fatal_insn ("attempt to use disabled fpu instruction", insn);
++    }
++  if (snprintf (buf, sizeof (buf),
++                ".set\tnoat\n\t"
++                "custom\t%d, zero, %%%d, %%D%d # fwrx %%%d\n\t"
++                "custom\t%d, at, %%%d, %%D%d # %s at, %%%d, %%%d\n\t"
++                "bne\tat, zero, %%l1\n\t"
++                ".set\tat",
++                nios2_fpu_insns[nios2_fpu_nios2_fwrx].N, operandL, operandL, operandL,
++                N, operandR, operandR, operandL, operandR, opt) >= (int)sizeof (buf))
++    {
++      fatal_insn ("buffer overflow", insn);
++    }
++  return buf;
++}
++
 +
 +
 +
@@ -5630,43 +7174,6 @@
 +}
 +
 +
-+/* 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.
@@ -5693,6 +7200,29 @@
 +  return return_rtx;
 +}
 +
++/*
++ * This is just default_must_pass_in_stack from calls.c sans the final
++ * test for padding which isn't needed: we define BLOCK_REG_PADDING
++ * instead.
++ */
++int
++nios2_must_pass_in_stack (enum machine_mode mode, tree type)
++{
++  if (!type)
++    return false;
++
++  /* If the type has variable size...  */
++  if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
++    return true;
++
++  /* If the type is marked as addressable (it is required
++     to be constructed into the stack)...  */
++  if (TREE_ADDRESSABLE (type))
++    return true;
++
++  return false;
++}
++
 +int
 +function_arg_partial_nregs (const CUMULATIVE_ARGS *cum,
 +                            enum machine_mode mode, tree type, 
@@ -5727,6 +7257,74 @@
 +}
 +
 +
++/* 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;
++}
++
++int
++nios2_function_arg_padding_upward (enum machine_mode mode, tree type)
++{
++  /* On little-endian targets, the first byte of every stack argument
++     is passed in the first byte of the stack slot.  */
++  if (!BYTES_BIG_ENDIAN)
++    return 1;
++
++  /* Otherwise, integral types are padded downward: the last byte of a
++     stack argument is passed in the last byte of the stack slot.  */
++  if (type != 0
++      ? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
++      : GET_MODE_CLASS (mode) == MODE_INT)
++    return 0;
++
++  /* Arguments smaller than a stack slot are padded downward.  */
++  if (mode != BLKmode)
++    return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY) ? 1 : 0;
++  else
++    return ((int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT))
++            ? 1 : 0);
++}
++
++int
++nios2_block_reg_padding_upward (enum machine_mode mode, tree type,
++                         int first ATTRIBUTE_UNUSED)
++{
++  /* ??? Do we need to treat floating point specially, ala MIPS? */
++  return nios2_function_arg_padding_upward (mode, type);
++}
++
 +int
 +nios2_return_in_memory (tree type)
 +{
@@ -5803,59 +7401,19 @@
 +  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,
++#undef NIOS2_DO_BUILTIN
++#define NIOS2_DO_BUILTIN(upper, lower, handler) \
++  NIOS2_CONCAT (NIOS2_BUILTIN_CUSTOM_, upper),
++NIOS2_FOR_ALL_CUSTOM_BUILTINS
++
++  NIOS2_FIRST_FPU_INSN,
 +
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++  NIOS2_CONCAT (NIOS2_BUILTIN_FPU_, opt),
++NIOS2_FOR_ALL_FPU_INSNS
++
++  NIOS2_LAST_FPU_INSN,
 +
 +  LIM_NIOS2_BUILTINS
 +};
@@ -5866,8 +7424,8 @@
 +    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));
++    rtx (* expander) (const struct builtin_description *,
++                      tree, rtx, rtx, enum machine_mode, int);
 +};
 +
 +static rtx nios2_expand_STXIO (const struct builtin_description *, 
@@ -5894,6 +7452,45 @@
 +static rtx nios2_expand_custom_XnXX (const struct builtin_description *, 
 +                                     tree, rtx, rtx, enum machine_mode, int);
 +
++static rtx nios2_expand_custom_zdz (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_zsz (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_szz (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_sss (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_ssz (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_iss (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_ddd (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_ddz (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_idd (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_siz (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_suz (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_diz (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_duz (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_isz (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_usz (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_idz (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_udz (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_dsz (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++static rtx nios2_expand_custom_sdz (const struct builtin_description *,
++                                    tree, rtx, rtx, enum machine_mode, int);
++
 +static tree endlink;
 +
 +/* int fn (volatile const void *)
@@ -5916,59 +7513,30 @@
 + */
 +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;
-+
++#undef NIOS2_DO_BUILTIN
++#define NIOS2_DO_BUILTIN(upper, lower, handler) \
++  static tree NIOS2_CONCAT (custom_, lower);
++NIOS2_FOR_ALL_CUSTOM_BUILTINS
++
++static tree custom_zdz;
++static tree custom_zsz;
++static tree custom_szz;
++static tree custom_sss;
++static tree custom_ssz;
++static tree custom_iss;
++static tree custom_ddd;
++static tree custom_ddz;
++static tree custom_idd;
++static tree custom_siz;
++static tree custom_suz;
++static tree custom_diz;
++static tree custom_duz;
++static tree custom_isz;
++static tree custom_usz;
++static tree custom_idz;
++static tree custom_udz;
++static tree custom_dsz;
++static tree custom_sdz;
 +
 +static const struct builtin_description bdesc[] = {
 +    {CODE_FOR_ldbio, "__builtin_ldbio", NIOS2_BUILTIN_LDBIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
@@ -5985,59 +7553,23 @@
 +    {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},
-+
++#undef NIOS2_DO_BUILTIN
++#define NIOS2_DO_BUILTIN(upper, lower, handler) \
++    {NIOS2_CONCAT (CODE_FOR_custom_, lower), \
++     "__builtin_custom_" NIOS2_STRINGIFY (lower), \
++     NIOS2_CONCAT (NIOS2_BUILTIN_CUSTOM_, upper), \
++     &NIOS2_CONCAT (custom_, lower), \
++     NIOS2_CONCAT (nios2_expand_custom_, handler)},
++NIOS2_FOR_ALL_CUSTOM_BUILTINS
++
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++    {NIOS2_CONCAT (CODE_FOR_, insn), \
++     "__builtin_custom_" NIOS2_STRINGIFY (opt), \
++     NIOS2_CONCAT (NIOS2_BUILTIN_FPU_, opt), \
++     &NIOS2_CONCAT (custom_, args), \
++     NIOS2_CONCAT (nios2_expand_custom_, args)},
++NIOS2_FOR_ALL_FPU_INSNS
 +
 +    {0, 0, 0, 0, 0},
 +};
@@ -6396,7 +7928,104 @@
 +  			     def_param (ptr_type_node)
 +  			     endlink))));
 +
++  custom_zdz
++      = build_function_type (void_type_node,
++                             def_param (double_type_node)
++                             endlink));
++
++  custom_zsz
++      = build_function_type (void_type_node,
++                             def_param (float_type_node)
++                             endlink));
++
++  custom_szz
++      = build_function_type (float_type_node,
++                             def_param (void_type_node)
++                             endlink));
++
++  custom_sss
++      = build_function_type (float_type_node,
++                             def_param (float_type_node)
++                             def_param (float_type_node)
++                             endlink)));
++
++  custom_ssz
++      = build_function_type (float_type_node,
++                             def_param (float_type_node)
++                             endlink));
++
++  custom_iss
++      = build_function_type (integer_type_node,
++                             def_param (float_type_node)
++                             def_param (float_type_node)
++                             endlink)));
++
++  custom_ddd
++      = build_function_type (double_type_node,
++                             def_param (double_type_node)
++                             def_param (double_type_node)
++                             endlink)));
++
++  custom_ddz
++      = build_function_type (double_type_node,
++                             def_param (double_type_node)
++                             endlink));
++
++  custom_idd
++      = build_function_type (integer_type_node,
++                             def_param (double_type_node)
++                             def_param (double_type_node)
++                             endlink)));
++
++  custom_siz
++      = build_function_type (float_type_node,
++                             def_param (integer_type_node)
++                             endlink));
++
++  custom_suz
++      = build_function_type (float_type_node,
++                             def_param (unsigned_type_node)
++                             endlink));
++
++  custom_diz
++      = build_function_type (double_type_node,
++                             def_param (integer_type_node)
++                             endlink));
++
++  custom_duz
++      = build_function_type (double_type_node,
++                             def_param (unsigned_type_node)
++                             endlink));
++
++  custom_isz
++      = build_function_type (integer_type_node,
++                             def_param (float_type_node)
++                             endlink));
++
++  custom_usz
++      = build_function_type (unsigned_type_node,
++                             def_param (float_type_node)
++                             endlink));
++
++  custom_idz
++      = build_function_type (integer_type_node,
++                             def_param (double_type_node)
++                             endlink));
++
++  custom_udz
++      = build_function_type (unsigned_type_node,
++                             def_param (double_type_node)
++                             endlink));
++
++  custom_dsz
++      = build_function_type (double_type_node,
++                             def_param (float_type_node)
++                             endlink));
 +
++  custom_sdz
++      = build_function_type (float_type_node,
++                             def_param (double_type_node)
++                             endlink));
 +
 +  /* *INDENT-ON* */
 +
@@ -6424,7 +8053,25 @@
 +
 +  for (d = bdesc; d->name; d++)
 +    if (d->code == fcode)
++      {
++        if (d->code > NIOS2_FIRST_FPU_INSN && d->code < NIOS2_LAST_FPU_INSN)
++          {
++            nios2_fpu_info *inf = &nios2_fpu_insns[d->code - (NIOS2_FIRST_FPU_INSN + 1)];
++            const struct insn_data *idata = &insn_data[d->icode];
++            if (inf->N < 0)
++              {
++                fatal_error ("Cannot call `%s' without specifying switch `-mcustom-%s'",
++                       d->name,
++                       inf->option);
++              }
++            if (inf->args[0] != 'z'
++                && (!target
++                    || !(idata->operand[0].predicate) (target,
++                                                       idata->operand[0].mode)))
++              target = gen_reg_rtx (idata->operand[0].mode);
++          }
 +      return (d->expander) (d, exp, target, subtarget, mode, ignore);
++      }
 +
 +  /* we should have seen one of the functins we registered */
 +  abort ();
@@ -6461,6 +8108,8 @@
 +  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);
 +
++  builtin_custom_seen[INTVAL (opcode)] = d->name;
++  nios2_custom_check_insns (0);
 +  return opcode;
 +}
 +
@@ -6844,15 +8493,397 @@
 +  return 0;
 +}
 +
++static rtx
++nios2_extract_double (const struct insn_data *idata, tree arglist, int index)
++{
++  rtx arg;
++
++  while (index--)
++  {
++    arglist = TREE_CHAIN (arglist);
++  }
++  arg = expand_expr (TREE_VALUE (arglist), NULL_RTX, DFmode, 0);
++  arg = protect_from_queue (arg, 0);
++  if (!(*(idata->operand[index+1].predicate)) (arg, DFmode))
++    {
++      arg = copy_to_mode_reg (DFmode, arg);
++    }
++  return arg;
++}
++
++static rtx
++nios2_extract_float (const struct insn_data *idata, tree arglist, int index)
++{
++  rtx arg;
++
++  while (index--)
++  {
++    arglist = TREE_CHAIN (arglist);
++  }
++  arg = expand_expr (TREE_VALUE (arglist), NULL_RTX, SFmode, 0);
++  arg = protect_from_queue (arg, 0);
++  if (!(*(idata->operand[index+1].predicate)) (arg, SFmode))
++    {
++      arg = copy_to_mode_reg (SFmode, arg);
++    }
++  return arg;
++}
++
++static rtx
++nios2_extract_integer (const struct insn_data *idata, tree arglist, int index)
++{
++  rtx arg;
++
++  while (index--)
++  {
++    arglist = TREE_CHAIN (arglist);
++  }
++  arg = expand_expr (TREE_VALUE (arglist), NULL_RTX, SImode, 0);
++  arg = protect_from_queue (arg, 0);
++  if (!(*(idata->operand[index+1].predicate)) (arg, SImode))
++    {
++      arg = copy_to_mode_reg (SImode, arg);
++    }
++  return protect_from_queue (arg, 0);
++}
++
++static rtx
++nios2_expand_custom_zdz (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 = GEN_FCN (d->icode) (nios2_extract_double (&insn_data[d->icode],
++                                                      arglist, 0));
++  if (pat)
++    emit_insn (pat);
++  return 0;
++}
++
++static rtx
++nios2_expand_custom_zsz (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 = GEN_FCN (d->icode) (nios2_extract_float (&insn_data[d->icode],
++                                                     arglist, 0));
++  if (pat)
++    emit_insn (pat);
++  return 0;
++}
++
++static rtx
++nios2_expand_custom_szz (const struct builtin_description *d,
++                         tree exp ATTRIBUTE_UNUSED,
++                         rtx target,
++                         rtx subtarget ATTRIBUTE_UNUSED,
++                         enum machine_mode mode ATTRIBUTE_UNUSED,
++                         int ignore ATTRIBUTE_UNUSED)
++{
++  rtx pat = GEN_FCN (d->icode) (target);
++  if (pat)
++    emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_sss (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 = GEN_FCN (d->icode) (target,
++                                nios2_extract_float (&insn_data[d->icode],
++                                                     arglist, 0),
++                                nios2_extract_float (&insn_data[d->icode],
++                                                     arglist, 1));
++  if (pat)
++    emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_ssz (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 = GEN_FCN (d->icode) (target,
++                                nios2_extract_float (&insn_data[d->icode],
++                                                     arglist, 0));
++  if (pat)
++    emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_iss (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 = GEN_FCN (d->icode) (target,
++                                nios2_extract_float (&insn_data[d->icode],
++                                                     arglist, 0),
++                                nios2_extract_float (&insn_data[d->icode],
++                                                     arglist, 1));
++  if (pat)
++    emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_ddd (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 = GEN_FCN (d->icode) (target,
++                                nios2_extract_double (&insn_data[d->icode],
++                                                      arglist, 0),
++                                nios2_extract_double (&insn_data[d->icode],
++                                                      arglist, 1));
++  if (pat)
++    emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_ddz (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 = GEN_FCN (d->icode) (target,
++                                nios2_extract_double (&insn_data[d->icode],
++                                                      arglist, 0));
++  if (pat)
++    emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_idd (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 = GEN_FCN (d->icode) (target,
++                                nios2_extract_double (&insn_data[d->icode],
++                                                      arglist, 0),
++                                nios2_extract_double (&insn_data[d->icode],
++                                                      arglist, 1));
++  if (pat)
++    emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_siz (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 = GEN_FCN (d->icode) (target,
++                                nios2_extract_integer (&insn_data[d->icode],
++                                                       arglist, 0));
++  if (pat)
++    emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_suz (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 = GEN_FCN (d->icode) (target,
++                                nios2_extract_integer (&insn_data[d->icode],
++                                                       arglist, 0));
++  if (pat)
++    emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_diz (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 = GEN_FCN (d->icode) (target,
++                                nios2_extract_integer (&insn_data[d->icode],
++                                                       arglist, 0));
++  if (pat)
++    emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_duz (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 = GEN_FCN (d->icode) (target,
++                                nios2_extract_integer (&insn_data[d->icode],
++                                                       arglist, 0));
++  if (pat)
++    emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_isz (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 = GEN_FCN (d->icode) (target,
++                                nios2_extract_float (&insn_data[d->icode],
++                                                     arglist, 0));
++  if (pat)
++    emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_usz (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 = GEN_FCN (d->icode) (target,
++                                nios2_extract_float (&insn_data[d->icode],
++                                                     arglist, 0));
++  if (pat)
++    emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_idz (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 = GEN_FCN (d->icode) (target,
++                                nios2_extract_double (&insn_data[d->icode],
++                                                      arglist, 0));
++  if (pat)
++    emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_udz (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 = GEN_FCN (d->icode) (target,
++                                nios2_extract_double (&insn_data[d->icode],
++                                                      arglist, 0));
++  if (pat)
++    emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_dsz (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 = GEN_FCN (d->icode) (target,
++                                nios2_extract_float (&insn_data[d->icode],
++                                                     arglist, 0));
++  if (pat)
++    emit_insn (pat);
++  return target;
++}
++
++static rtx
++nios2_expand_custom_sdz (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 = GEN_FCN (d->icode) (target,
++                                nios2_extract_double (&insn_data[d->icode],
++                                                      arglist, 0));
++  if (pat)
++    emit_insn (pat);
++  return target;
++}
 +
 +#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 @@
+diff --git a/gcc/config/nios2/nios2.h b/gcc/config/nios2/nios2.h
+new file mode 100644
+index 0000000..500ccf0
+--- /dev/null
++++ b/gcc/config/nios2/nios2.h
+@@ -0,0 +1,1130 @@
 +/* Definitions of target machine for Altera NIOS 2G NIOS2 version.
-+   Copyright (C) 2003 Altera 
-+   Contributed by Jonah Graham (jgraham@altera.com).
++   Copyright (C) 2005 Altera 
++   Contributed by Jonah Graham (jgraham@altera.com) and Will Reece (wreece@altera.com).
 +
 +This file is part of GNU CC.
 +
@@ -6878,7 +8909,10 @@
 +    {						\
 +      builtin_define_std ("NIOS2");		\
 +      builtin_define_std ("nios2");		\
-+      builtin_define ("_GNU_SOURCE");		\
++      if (TARGET_BIG_ENDIAN)                        \
++        builtin_define_std ("nios2_big_endian");    \
++      else                                          \
++        builtin_define_std ("nios2_little_endian"); \
 +    }						\
 +  while (0)
 +#define TARGET_VERSION fprintf (stderr, " (Altera Nios II)")
@@ -6898,6 +8932,10 @@
 +#define INLINE_MEMCPY_FLAG 0x00010
 +#define CACHE_VOLATILE_FLAG 0x0020
 +#define BYPASS_CACHE_FLAG 0x0040
++#define STACK_CHECK_FLAG 0x0080 
++#define REVERSE_BITFIELDS_FLAG 0x0100
++/* Reserve 0x0200 for REVERSE_ENDIAN_FLAG */
++#define BIG_ENDIAN_FLAG 0x0400
 +
 +extern int target_flags;
 +#define TARGET_HAS_DIV (target_flags & HAS_DIV_FLAG)
@@ -6907,6 +8945,9 @@
 +#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_STACK_CHECK (target_flags & STACK_CHECK_FLAG)
++#define TARGET_REVERSE_BITFIELDS (target_flags & REVERSE_BITFIELDS_FLAG)
++#define TARGET_BIG_ENDIAN (target_flags & BIG_ENDIAN_FLAG)
 +
 +#define TARGET_SWITCHES					\
 +{							\
@@ -6942,14 +8983,148 @@
 +      N_("Link with a limited version of the C library") },		\
 +    { "ctors-in-init", 0,			\
 +      "" /* undocumented: N_("Link with static constructors and destructors in init") */ },		\
++    { "stack-check", STACK_CHECK_FLAG,				\
++      N_("Enable stack limit checking.") },				\
++    { "no-stack-check", -STACK_CHECK_FLAG,				\
++      N_("Disable stack limit checking (default).") },				\
++    { "reverse-bitfields", REVERSE_BITFIELDS_FLAG,          \
++      N_("Reverse the order of bitfields in a struct.") },      \
++    { "no-reverse-bitfields", -REVERSE_BITFIELDS_FLAG,          \
++      N_("Use the normal order of bitfields in a struct (default).") }, \
++    { "eb", BIG_ENDIAN_FLAG,                                            \
++      N_("Use big-endian byte order") },                                \
++    { "el", -BIG_ENDIAN_FLAG,                                           \
++      N_("Use little-endian byte order") },                             \
 +    { "", 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= */
 +
++/*
++ * There's a lot of error-prone tedium with all the different
++ * custom floating point instructions.  Try to automate it a bit
++ * to make it easier to deal with.
++ */
++#define NIOS2_STRINGIFY_INNER(x) #x
++#define NIOS2_STRINGIFY(x) NIOS2_STRINGIFY_INNER(x)
++#define NIOS2_CONCAT_INNER(x, y) x ## y
++#define NIOS2_CONCAT(x, y) NIOS2_CONCAT_INNER (x, y)
++
++#define NIOS2_FOR_ALL_FPU_INSNS \
++  NIOS2_FPU_INSN (fwrx,     nios2_fwrx,    zdz) \
++  NIOS2_FPU_INSN (fwry,     nios2_fwry,    zsz) \
++  NIOS2_FPU_INSN (frdxlo,   nios2_frdxlo,  szz) \
++  NIOS2_FPU_INSN (frdxhi,   nios2_frdxhi,  szz) \
++  NIOS2_FPU_INSN (frdy,     nios2_frdy,    szz) \
++\
++  NIOS2_FPU_INSN (fadds,    addsf3,        sss) \
++  NIOS2_FPU_INSN (fsubs,    subsf3,        sss) \
++  NIOS2_FPU_INSN (fmuls,    mulsf3,        sss) \
++  NIOS2_FPU_INSN (fdivs,    divsf3,        sss) \
++  NIOS2_FPU_INSN (fmins,    minsf3,        sss) \
++  NIOS2_FPU_INSN (fmaxs,    maxsf3,        sss) \
++  NIOS2_FPU_INSN (fnegs,    negsf2,        ssz) \
++  NIOS2_FPU_INSN (fabss,    abssf2,        ssz) \
++  NIOS2_FPU_INSN (fsqrts,   sqrtsf2,       ssz) \
++  NIOS2_FPU_INSN (fcoss,    cossf2,        ssz) \
++  NIOS2_FPU_INSN (fsins,    sinsf2,        ssz) \
++  NIOS2_FPU_INSN (ftans,    tansf2,        ssz) \
++  NIOS2_FPU_INSN (fatans,   atansf2,       ssz) \
++  NIOS2_FPU_INSN (fexps,    expsf2,        ssz) \
++  NIOS2_FPU_INSN (flogs,    logsf2,        ssz) \
++  NIOS2_FPU_INSN (fcmplts,  nios2_sltsf,   iss) \
++  NIOS2_FPU_INSN (fcmples,  nios2_slesf,   iss) \
++  NIOS2_FPU_INSN (fcmpgts,  nios2_sgtsf,   iss) \
++  NIOS2_FPU_INSN (fcmpges,  nios2_sgesf,   iss) \
++  NIOS2_FPU_INSN (fcmpeqs,  nios2_seqsf,   iss) \
++  NIOS2_FPU_INSN (fcmpnes,  nios2_snesf,   iss) \
++\
++  NIOS2_FPU_INSN (faddd,    adddf3,        ddd) \
++  NIOS2_FPU_INSN (fsubd,    subdf3,        ddd) \
++  NIOS2_FPU_INSN (fmuld,    muldf3,        ddd) \
++  NIOS2_FPU_INSN (fdivd,    divdf3,        ddd) \
++  NIOS2_FPU_INSN (fmind,    mindf3,        ddd) \
++  NIOS2_FPU_INSN (fmaxd,    maxdf3,        ddd) \
++  NIOS2_FPU_INSN (fnegd,    negdf2,        ddz) \
++  NIOS2_FPU_INSN (fabsd,    absdf2,        ddz) \
++  NIOS2_FPU_INSN (fsqrtd,   sqrtdf2,       ddz) \
++  NIOS2_FPU_INSN (fcosd,    cosdf2,        ddz) \
++  NIOS2_FPU_INSN (fsind,    sindf2,        ddz) \
++  NIOS2_FPU_INSN (ftand,    tandf2,        ddz) \
++  NIOS2_FPU_INSN (fatand,   atandf2,       ddz) \
++  NIOS2_FPU_INSN (fexpd,    expdf2,        ddz) \
++  NIOS2_FPU_INSN (flogd,    logdf2,        ddz) \
++  NIOS2_FPU_INSN (fcmpltd,  nios2_sltdf,   idd) \
++  NIOS2_FPU_INSN (fcmpled,  nios2_sledf,   idd) \
++  NIOS2_FPU_INSN (fcmpgtd,  nios2_sgtdf,   idd) \
++  NIOS2_FPU_INSN (fcmpged,  nios2_sgedf,   idd) \
++  NIOS2_FPU_INSN (fcmpeqd,  nios2_seqdf,   idd) \
++  NIOS2_FPU_INSN (fcmpned,  nios2_snedf,   idd) \
++\
++  NIOS2_FPU_INSN (floatis,  floatsisf2,    siz) \
++  NIOS2_FPU_INSN (floatus,  floatunssisf2, suz) \
++  NIOS2_FPU_INSN (floatid,  floatsidf2,    diz) \
++  NIOS2_FPU_INSN (floatud,  floatunssidf2, duz) \
++  NIOS2_FPU_INSN (fixsi,    fixsfsi2,      isz) \
++  NIOS2_FPU_INSN (fixsu,    fixunssfsi2,   usz) \
++  NIOS2_FPU_INSN (fixdi,    fixdfsi2,      idz) \
++  NIOS2_FPU_INSN (fixdu,    fixunsdfsi2,   udz) \
++  NIOS2_FPU_INSN (fextsd,   extendsfdf2,   dsz) \
++  NIOS2_FPU_INSN (ftruncds, truncdfsf2,    sdz)
++
++enum
++{
++#define NIOS2_FPU_INSN(opt, insn, args) \
++  NIOS2_CONCAT (nios2_fpu_, insn),
++NIOS2_FOR_ALL_FPU_INSNS
++  nios2_fpu_max_insn
++};
++
++struct cpp_reader;
++typedef const char * (*nios2_outputfn) (rtx);
++typedef void (*nios2_pragmafn) (struct cpp_reader *);
++
++typedef struct
++{
++  const char *option;      /* name of switch, e.g. fadds */
++  const char *insnnm;      /* name of gcc insn, e.g. addsf3 */
++  const char *args;        /* args to gcc insn, e.g. sss */
++  const char *value;       /* value of switch as a string */
++  int N;                   /* value of switch as an integer, -1 = not used */
++  nios2_outputfn output;   /* output function for use in .md file */
++  const char *pname;       /* name of corresponding #pragma custom- */
++  nios2_pragmafn pragma;   /* pragma function for register_target_pragmas */
++  const char *nopname;     /* name of corresponding #pragma no-custom- */
++  nios2_pragmafn nopragma; /* pragma function for register_target_pragmas */
++  int is_double;           /* does this insn have any double operands */
++  int needed_by_double;    /* is this insn needed if doubles are used? */
++  int needs_unsafe;        /* does this insn require
++                              -funsafe-math-optimizations to work? */
++  int needs_finite;        /* does this insn require
++                              -ffinite-math-only to work? */
++  int pragma_seen;         /* have we seen the corresponding #pragma? */
++} nios2_fpu_info;
++
++extern nios2_fpu_info nios2_fpu_insns[nios2_fpu_max_insn];
++extern const char *nios2_custom_fpu_cfg_string;
++
++#undef NIOS2_FPU_INSN
++#define NIOS2_FPU_INSN(opt, insn, args) \
++  { \
++    "custom-" NIOS2_STRINGIFY (opt) "=", \
++    &(nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].value), \
++    N_("Integer id (N) of " NIOS2_STRINGIFY (opt) " custom instruction"), \
++    0 \
++  }, \
++  { \
++    "no-custom-" NIOS2_STRINGIFY (opt), \
++    &(nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].value), \
++    N_("Do not use the " NIOS2_STRINGIFY (opt) " custom instruction"), \
++    "-1" \
++  },
++
 +#define TARGET_OPTIONS					\
 +{							\
 +  { "sys=nosys",    &nios2_sys_nosys_string,		\
@@ -6958,12 +9133,19 @@
 +      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},	\
++  NIOS2_FOR_ALL_FPU_INSNS \
++  { "custom-fpu-cfg=", &nios2_custom_fpu_cfg_string,    \
++      N_("Floating point custom instruction configuration name"), 0 },  \
 +}
 +
++/* We're little endian, unless otherwise specified by including big.h */
++#ifndef TARGET_ENDIAN_DEFAULT
++# define TARGET_ENDIAN_DEFAULT 0
++#endif
 +
 +/* Default target_flags if no switches specified.  */
 +#ifndef TARGET_DEFAULT
-+# define TARGET_DEFAULT (HAS_MUL_FLAG | CACHE_VOLATILE_FLAG)
++# define TARGET_DEFAULT (HAS_MUL_FLAG | CACHE_VOLATILE_FLAG | TARGET_ENDIAN_DEFAULT)
 +#endif
 +
 +/* Switch  Recognition by gcc.c.  Add -G xx support */
@@ -6976,13 +9158,27 @@
 +#define CAN_DEBUG_WITHOUT_FP
 + 
 +#define CC1_SPEC "\
-+%{G*}"
++%{G*} %{EB:-meb} %{EL:-mel} %{EB:%{EL:%emay not use both -EB and -EL}}"
++
++#if TARGET_ENDIAN_DEFAULT == 0
++# define ASM_SPEC "\
++%{!EB:%{!meb:-EL}} %{EB|meb:-EB}"
++# define LINK_SPEC "\
++%{!EB:%{!meb:-EL}} %{EB|meb:-EB}"
++# define MULTILIB_DEFAULTS { "EL" }
++#else
++# define ASM_SPEC "\
++%{!EL:%{!mel:-EB}} %{EL|mel:-EL}"
++# define LINK_SPEC "\
++%{!EL:%{!mel:-EB}} %{EL|mel:-EL}"
++# define MULTILIB_DEFAULTS { "EB" }
++#endif
 +
 +#undef LIB_SPEC
 +#define LIB_SPEC \
 +"--start-group %{msmallc: -lsmallc} %{!msmallc: -lc} -lgcc \
 + %{msys-lib=*: -l%*} \
-+ %{!msys-lib=*: -lc } \
++ %{!msys-lib=*: -lnosys -lstack} \
 + --end-group \
 + %{msys-lib=: %eYou need a library name for -msys-lib=} \
 +"
@@ -6990,7 +9186,7 @@
 +
 +#undef STARTFILE_SPEC 
 +#define STARTFILE_SPEC  \
-+"%{msys-crt0=*: %*} %{!msys-crt0=*: crt1%O%s} \
++"%{msys-crt0=*: %*} %{!msys-crt0=*: crt0%O%s} \
 + %{msys-crt0=: %eYou need a C startup file for -msys-crt0=} \
 + %{mctors-in-init: crti%O%s crtbegin%O%s} \
 +"
@@ -7006,8 +9202,13 @@
 +
 +#define DEFAULT_SIGNED_CHAR 1
 +#define BITS_BIG_ENDIAN 0
-+#define BYTES_BIG_ENDIAN 0
-+#define WORDS_BIG_ENDIAN 0
++#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
++#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
++#if defined(__nios2_big_endian__)
++#define LIBGCC2_WORDS_BIG_ENDIAN 1
++#else
++#define LIBGCC2_WORDS_BIG_ENDIAN 0
++#endif
 +#define BITS_PER_UNIT 8
 +#define BITS_PER_WORD 32
 +#define UNITS_PER_WORD 4
@@ -7043,7 +9244,8 @@
 + ************************/
 +
 +/* comparison type */
-+/* ??? currently only CMP_SI is used */
++/* ??? Currently CMP_DI is unused.  CMP_SF and CMP_DF are only used if
++   the corresponding -mcustom-<opcode> switches are present. */
 +enum cmp_type {
 +  CMP_SI,				/* compare four byte integers */
 +  CMP_DI,				/* compare eight byte integers */
@@ -7077,8 +9279,8 @@
 +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
++24    r24 et    Exception Temporary
++25    r25 bt    Breakpoint Temporary
 +26    r26 gp    Global Pointer
 +27    r27 sp    Stack Pointer
 +28    r28 fp    Frame Pointer
@@ -7120,7 +9322,7 @@
 +/*  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,                                \
++/*  40 */  1                                 \
 +    }
 +
 +/* call used is the same as caller saved
@@ -7132,7 +9334,7 @@
 +/*  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,                                \
++/*  40 */  1                                 \
 +    }
 +
 +#define HARD_REGNO_NREGS(REGNO, MODE)            \
@@ -7155,6 +9357,39 @@
 +enum reg_class
 +{
 +    NO_REGS,
++    D00_REG,
++    D01_REG,
++    D02_REG,
++    D03_REG,
++    D04_REG,
++    D05_REG,
++    D06_REG,
++    D07_REG,
++    D08_REG,
++    D09_REG,
++    D10_REG,
++    D11_REG,
++    D12_REG,
++    D13_REG,
++    D14_REG,
++    D15_REG,
++    D16_REG,
++    D17_REG,
++    D18_REG,
++    D19_REG,
++    D20_REG,
++    D21_REG,
++    D22_REG,
++    D23_REG,
++    D24_REG,
++    D25_REG,
++    D26_REG,
++    D27_REG,
++    D28_REG,
++    D29_REG,
++    D30_REG,
++    D31_REG,
++    GP_REGS,
 +    ALL_REGS,
 +    LIM_REG_CLASSES
 +};
@@ -7163,21 +9398,89 @@
 +
 +#define REG_CLASS_NAMES   \
 +    {"NO_REGS",           \
++     "D00_REG",           \
++     "D01_REG",           \
++     "D02_REG",           \
++     "D03_REG",           \
++     "D04_REG",           \
++     "D05_REG",           \
++     "D06_REG",           \
++     "D07_REG",           \
++     "D08_REG",           \
++     "D09_REG",           \
++     "D10_REG",           \
++     "D11_REG",           \
++     "D12_REG",           \
++     "D13_REG",           \
++     "D14_REG",           \
++     "D15_REG",           \
++     "D16_REG",           \
++     "D17_REG",           \
++     "D18_REG",           \
++     "D19_REG",           \
++     "D20_REG",           \
++     "D21_REG",           \
++     "D22_REG",           \
++     "D23_REG",           \
++     "D24_REG",           \
++     "D25_REG",           \
++     "D26_REG",           \
++     "D27_REG",           \
++     "D28_REG",           \
++     "D29_REG",           \
++     "D30_REG",           \
++     "D31_REG",           \
++     "GP_REGS",           \
 +     "ALL_REGS"}
 +
 +#define GENERAL_REGS ALL_REGS
 +
 +#define REG_CLASS_CONTENTS   \
 +/* NO_REGS  */       {{ 0, 0},     \
++/* D00_REG  */        { 1 << 0, 0},    \
++/* D01_REG  */        { 1 << 1, 0},    \
++/* D02_REG  */        { 1 << 2, 0},    \
++/* D03_REG  */        { 1 << 3, 0},    \
++/* D04_REG  */        { 1 << 4, 0},    \
++/* D05_REG  */        { 1 << 5, 0},    \
++/* D06_REG  */        { 1 << 6, 0},    \
++/* D07_REG  */        { 1 << 7, 0},    \
++/* D08_REG  */        { 1 << 8, 0},    \
++/* D09_REG  */        { 1 << 9, 0},    \
++/* D10_REG  */        { 1 << 10, 0},    \
++/* D11_REG  */        { 1 << 11, 0},    \
++/* D12_REG  */        { 1 << 12, 0},    \
++/* D13_REG  */        { 1 << 13, 0},    \
++/* D14_REG  */        { 1 << 14, 0},    \
++/* D15_REG  */        { 1 << 15, 0},    \
++/* D16_REG  */        { 1 << 16, 0},    \
++/* D17_REG  */        { 1 << 17, 0},    \
++/* D18_REG  */        { 1 << 18, 0},    \
++/* D19_REG  */        { 1 << 19, 0},    \
++/* D20_REG  */        { 1 << 20, 0},    \
++/* D21_REG  */        { 1 << 21, 0},    \
++/* D22_REG  */        { 1 << 22, 0},    \
++/* D23_REG  */        { 1 << 23, 0},    \
++/* D24_REG  */        { 1 << 24, 0},    \
++/* D25_REG  */        { 1 << 25, 0},    \
++/* D26_REG  */        { 1 << 26, 0},    \
++/* D27_REG  */        { 1 << 27, 0},    \
++/* D28_REG  */        { 1 << 28, 0},    \
++/* D29_REG  */        { 1 << 29, 0},    \
++/* D30_REG  */        { 1 << 30, 0},    \
++/* D31_REG  */        { 1 << 31, 0},    \
++/* GP_REGS  */        {~0, 0},    \
 +/* ALL_REGS */        {~0,~0}}    \
 +
-+#define REGNO_REG_CLASS(REGNO) ALL_REGS
++#define REGNO_REG_CLASS(REGNO) ((REGNO) <= 31 ? GP_REGS : 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
++/* 'r', is handled automatically */
++#define  REG_CLASS_FROM_CONSTRAINT(CHAR, STR) \
++  reg_class_from_constraint ((CHAR), (STR))
++  
 +
 +#define REGNO_OK_FOR_BASE_P2(REGNO, STRICT) \
 +    ((STRICT) \
@@ -7231,6 +9534,9 @@
 +#define PREFERRED_RELOAD_CLASS(X, CLASS) \
 +    ((CLASS) == NO_REGS ? GENERAL_REGS : (CLASS))
 +
++#define CONSTRAINT_LEN(C, STR) \
++ ((C) == 'D' ? 3 : DEFAULT_CONSTRAINT_LEN ((C), (STR)))
++
 +/* 'S' matches immediates which are in small data 
 +   and therefore can be added to gp to create a 
 +   32-bit value. */
@@ -7338,6 +9644,9 @@
 +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
 +  (function_arg (&CUM, MODE, TYPE, NAMED))
 +
++#define MUST_PASS_IN_STACK(MODE, TYPE) \
++  nios2_must_pass_in_stack ((MODE), (TYPE))
++
 +#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
 +  (function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED))
 +
@@ -7357,6 +9666,15 @@
 +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
 +    (function_arg_advance (&CUM, MODE, TYPE, NAMED))
 +
++#define FUNCTION_ARG_PADDING(MODE, TYPE) \
++  (nios2_function_arg_padding_upward ((MODE), (TYPE)) ? upward : downward)
++
++#define PAD_VARARGS_DOWN \
++  (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
++
++#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
++  (nios2_block_reg_padding_upward ((MODE), (TYPE), (FIRST)) ? upward : downward)
++
 +#define FUNCTION_ARG_REGNO_P(REGNO) \
 +    ((REGNO) >= FIRST_ARG_REGNO && (REGNO) <= LAST_ARG_REGNO)
 +
@@ -7372,8 +9690,9 @@
 + * Generating Code for Profiling
 + * ----------------------------- */
 +
-+#define PROFILE_BEFORE_PROLOGUE
 +
++#define PROFILE_BEFORE_PROLOGUE
++#define NO_PROFILE_COUNTERS 1
 +#define FUNCTION_PROFILER(FILE, LABELNO) \
 +  function_profiler ((FILE), (LABELNO))
 +
@@ -7546,8 +9865,8 @@
 +    "r21", \
 +    "r22", \
 +    "r23", \
-+    "r24", \
-+    "r25", \
++    "et", \
++    "bt", \
 +    "gp", \
 +    "sp", \
 +    "fp", \
@@ -7565,6 +9884,21 @@
 +    "fake_ap", \
 +}
 +
++#define ADDITIONAL_REGISTER_NAMES	\
++{					\
++  {"r0", 0},				\
++  {"r1", 1},				\
++  {"r24", 24},				\
++  {"r25", 25},				\
++  {"r26", 26},				\
++  {"r27", 27},				\
++  {"r28", 28},				\
++  {"r29", 29},				\
++  {"r30", 30},				\
++  {"r31", 31}				\
++}
++
++
 +#define ASM_OUTPUT_OPCODE(STREAM, PTR)\
 +   (PTR) = asm_output_opcode (STREAM, PTR)
 +
@@ -7664,9 +9998,12 @@
 +
 +#define MOVE_MAX 4
 +
++#define STORE_FLAG_VALUE 1
 +#define Pmode SImode
 +#define FUNCTION_MODE QImode
 +
++#define REGISTER_TARGET_PRAGMAS() nios2_register_target_pragmas ();
++
 +#define CASE_VECTOR_MODE Pmode
 +
 +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
@@ -7674,12 +10011,15 @@
 +#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 @@
+diff --git a/gcc/config/nios2/nios2.md b/gcc/config/nios2/nios2.md
+new file mode 100644
+index 0000000..6183247
+--- /dev/null
++++ b/gcc/config/nios2/nios2.md
+@@ -0,0 +1,2867 @@
 +;; Machine Description for Altera NIOS 2G NIOS2 version.
-+;;    Copyright (C) 2003 Altera 
-+;;    Contributed by Jonah Graham (jgraham@altera.com).
++;;    Copyright (C) 2005 Altera 
++;;    Contributed by Jonah Graham (jgraham@altera.com) and Will Reece (wreece@altera.com).
 +;; 
 +;; This file is part of GNU CC.
 +;; 
@@ -7700,12 +10040,43 @@
 +
 +
 +
++
++;*****************************************************************************
++;*
++;* constraint strings
++;*
++;*****************************************************************************
++;
++; We use the following constraint letters for constants
++;
++;  I: -32768 to -32767
++;  J: 0 to 65535
++;  K: $nnnn0000 for some nnnn
++;  L: 0 to 31 (for shift counts)
++;  M: 0
++;  N: 0 to 255 (for custom instruction numbers)
++;  O: 0 to 31 (for control register numbers)
++;
++; We use the following built-in register classes:
++;
++;  r: general purpose register (r0..r31)
++;  m: memory operand
++;
++; Plus, we define the following constraint strings:
++;
++;  S: symbol that is in the "small data" area
++;  Dnn: Dnn_REG (just rnn)
++;
++
++
++
 +;*****************************************************************************
 +;*
 +;* constants
 +;*
 +;*****************************************************************************
 +(define_constants [
++  (ET_REGNO 24)
 +  (GP_REGNO 26)
 +  (SP_REGNO 27)
 +  (FP_REGNO 28)
@@ -7733,7 +10104,26 @@
 +  (UNSPEC_SYNC 9)
 +  (UNSPEC_WRCTL 10)
 +  (UNSPEC_RDCTL 11)
-+  
++  (UNSPEC_TRAP 12)
++  (UNSPEC_STACK_OVERFLOW_DETECT_AND_TRAP 13)
++  (UNSPEC_FCOSS 14)
++  (UNSPEC_FCOSD 15)
++  (UNSPEC_FSINS 16)
++  (UNSPEC_FSIND 17)
++  (UNSPEC_FTANS 18)
++  (UNSPEC_FTAND 19)
++  (UNSPEC_FATANS 20)
++  (UNSPEC_FATAND 21)
++  (UNSPEC_FEXPS 22)
++  (UNSPEC_FEXPD 23)
++  (UNSPEC_FLOGS 24)
++  (UNSPEC_FLOGD 25)
++  (UNSPEC_FWRX 26)
++  (UNSPEC_FWRY 27)
++  (UNSPEC_FRDXLO 28)
++  (UNSPEC_FRDXHI 29)
++  (UNSPEC_FRDY 30)
++  ;; Note that values 100..151 are used by custom instructions, see below.
 +])
 +
 +
@@ -7829,8 +10219,7 @@
 +  [(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))"
++    || reg_or_0_operand (operands[1], QImode))"
 +  "@
 +    stb%o0\\t%z1, %0
 +    ldbu%o1\\t%0, %1
@@ -7856,7 +10245,7 @@
 +
 +(define_insn "stbio"
 +  [(set (match_operand:SI 0 "memory_operand" "=m")
-+	(match_operand:SI 1 "register_operand"   "r"))
++	(match_operand:SI 1 "reg_or_0_operand"   "rM"))
 +   (unspec_volatile:SI [(const_int 0)] UNSPEC_STBIO)]
 +  ""
 +  "stbio\\t%z1, %0"
@@ -7876,8 +10265,7 @@
 +  [(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))"
++    || reg_or_0_operand (operands[1], HImode))"
 +  "@
 +    sth%o0\\t%z1, %0
 +    ldhu%o1\\t%0, %1
@@ -7904,7 +10292,7 @@
 +
 +(define_insn "sthio"
 +  [(set (match_operand:SI 0 "memory_operand" "=m")
-+	(match_operand:SI 1 "register_operand"   "r"))
++	(match_operand:SI 1 "reg_or_0_operand"   "rM"))
 +   (unspec_volatile:SI [(const_int 0)] UNSPEC_STHIO)]
 +  ""
 +  "sthio\\t%z1, %0"
@@ -7923,8 +10311,7 @@
 +  [(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))"
++    || reg_or_0_operand (operands[1], SImode))"
 +  "@
 +    stw%o0\\t%z1, %0
 +    ldw%o1\\t%0, %1
@@ -7945,7 +10332,7 @@
 +
 +(define_insn "stwio"
 +  [(set (match_operand:SI 0 "memory_operand" "=m")
-+	(match_operand:SI 1 "register_operand"   "r"))
++	(match_operand:SI 1 "reg_or_0_operand"   "rM"))
 +   (unspec_volatile:SI [(const_int 0)] UNSPEC_STWIO)]
 +  ""
 +  "stwio\\t%z1, %0"
@@ -7994,26 +10381,30 @@
 +;* 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);
++(define_insn "*extendhisi2"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++        (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))]
++  ""
++  "#")
 +
-+      emit_insn (gen_ashlsi3 (temp, op1, shift));
-+      emit_insn (gen_ashrsi3 (operands[0], temp, shift));
-+      DONE;
-+    }
-+})
++(define_split
++  [(set (match_operand:SI 0 "register_operand" "")
++        (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
++  "reload_completed"
++  [(set (match_dup 0)
++        (and:SI (match_dup 1) (const_int 65535)))
++   (set (match_dup 0)
++        (xor:SI (match_dup 0) (const_int 32768)))
++   (set (match_dup 0)
++        (plus:SI (match_dup 0) (const_int -32768)))]
++  "operands[1] = gen_lowpart (SImode, operands[1]);")
 +
 +(define_insn "extendhisi2_internal"
 +  [(set (match_operand:SI 0 "register_operand" "=r")
@@ -8022,26 +10413,34 @@
 +  "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]);
++})
++
++(define_insn "*extendqihi2"
++  [(set (match_operand:HI 0 "register_operand" "=r")
++        (sign_extend:HI (match_operand:QI 1 "register_operand" "r")))]
++  ""
++  "#")
++
++(define_split
++  [(set (match_operand:HI 0 "register_operand" "")
++        (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
++  "reload_completed"
++  [(set (match_dup 0)
++        (and:SI (match_dup 1) (const_int 255)))
++   (set (match_dup 0)
++        (xor:SI (match_dup 0) (const_int 128)))
++   (set (match_dup 0)
++        (plus:SI (match_dup 0) (const_int -128)))]
++  "operands[0] = gen_lowpart (SImode, operands[0]);
++   operands[1] = gen_lowpart (SImode, 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")
@@ -8056,20 +10455,25 @@
 +	(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);
++(define_insn "*extendqisi2"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++        (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))]
++  ""
++  "#")
 +
-+      emit_insn (gen_ashlsi3 (temp, op1, shift));
-+      emit_insn (gen_ashrsi3 (operands[0], temp, shift));
-+      DONE;
-+    }
-+})
++(define_split
++  [(set (match_operand:SI 0 "register_operand" "")
++        (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
++  "reload_completed"
++  [(set (match_dup 0)
++        (and:SI (match_dup 1) (const_int 255)))
++   (set (match_dup 0)
++        (xor:SI (match_dup 0) (const_int 128)))
++   (set (match_dup 0)
++        (plus:SI (match_dup 0) (const_int -128)))]
++  "operands[1] = gen_lowpart (SImode, operands[1]);")
 +
 +(define_insn "extendqisi2_insn"
 +  [(set (match_operand:SI 0 "register_operand" "=r")
@@ -8080,6 +10484,7 @@
 +
 +
 +
++
 +;*****************************************************************************
 +;*
 +;* Arithmetic Operations
@@ -8094,6 +10499,26 @@
 +  "add%i2\\t%0, %1, %z2"
 +  [(set_attr "type" "alu")])
 +
++(define_insn "addsf3"
++  [(set (match_operand:SF 0 "register_operand"          "=r")
++        (plus:SF (match_operand:SF 1 "register_operand" "%r")
++                 (match_operand:SF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_addsf3].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_addsf3].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "adddf3"
++  [(set (match_operand:DF 0 "register_operand"          "=r")
++        (plus:DF (match_operand:DF 1 "register_operand" "%r")
++                 (match_operand:DF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_adddf3].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_adddf3].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
 +(define_insn "subsi3"
 +  [(set (match_operand:SI 0 "register_operand"           "=r")
 +        (minus:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
@@ -8102,6 +10527,26 @@
 +  "sub\\t%0, %z1, %2"
 +  [(set_attr "type" "alu")])
 +
++(define_insn "subsf3"
++  [(set (match_operand:SF 0 "register_operand"          "=r")
++        (minus:SF (match_operand:SF 1 "register_operand" "r")
++                  (match_operand:SF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_subsf3].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_subsf3].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "subdf3"
++  [(set (match_operand:DF 0 "register_operand"          "=r")
++        (minus:DF (match_operand:DF 1 "register_operand" "r")
++                  (match_operand:DF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_subdf3].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_subdf3].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
 +(define_insn "mulsi3"
 +  [(set (match_operand:SI 0 "register_operand"            "=r,r")
 +        (mult:SI (match_operand:SI 1 "register_operand"    "r,r")
@@ -8110,6 +10555,26 @@
 +  "mul%i2\\t%0, %1, %z2"
 +  [(set_attr "type" "mul")])
 +
++(define_insn "mulsf3"
++  [(set (match_operand:SF 0 "register_operand"          "=r")
++        (mult:SF (match_operand:SF 1 "register_operand" "%r")
++                 (match_operand:SF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_mulsf3].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_mulsf3].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "muldf3"
++  [(set (match_operand:DF 0 "register_operand"          "=r")
++        (mult:DF (match_operand:DF 1 "register_operand" "%r")
++                 (match_operand:DF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_muldf3].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_muldf3].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
 +(define_expand "divsi3"
 +  [(set (match_operand:SI 0 "register_operand"            "=r")
 +        (div:SI (match_operand:SI 1 "register_operand"     "r")
@@ -8136,6 +10601,26 @@
 +  "div\\t%0, %1, %2"
 +  [(set_attr "type" "div")])
 +
++(define_insn "divsf3"
++  [(set (match_operand:SF 0 "register_operand"          "=r")
++        (div:SF (match_operand:SF 1 "register_operand" "r")
++                (match_operand:SF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_divsf3].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_divsf3].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "divdf3"
++  [(set (match_operand:DF 0 "register_operand"          "=r")
++        (div:DF (match_operand:DF 1 "register_operand" "r")
++                (match_operand:DF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_divdf3].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_divdf3].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
 +(define_insn "udivsi3"
 +  [(set (match_operand:SI 0 "register_operand"            "=r")
 +        (udiv:SI (match_operand:SI 1 "register_operand"     "r")
@@ -8167,7 +10652,7 @@
 +  [(set_attr "type" "mul")])
 +
 +
-+(define_expand "mulsidi3"
++(define_expand "mulsidi3_little_endian"
 +    [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0)
 +	  (mult:SI (match_operand:SI 1 "register_operand" "")
 +		   (match_operand:SI 2 "register_operand" "")))
@@ -8175,10 +10660,42 @@
 +	  (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
 +					     (sign_extend:DI (match_dup 2)))
 +				    (const_int 32))))]
-+  "TARGET_HAS_MULX"
++  "TARGET_HAS_MULX && !WORDS_BIG_ENDIAN"
 +  "")
 +
-+(define_expand "umulsidi3"
++(define_expand "mulsidi3_big_endian"
++    [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 4)
++          (mult:SI (match_operand:SI 1 "register_operand" "")
++                   (match_operand:SI 2 "register_operand" "")))
++     (set (subreg:SI (match_dup 0) 0)
++          (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
++                                             (sign_extend:DI (match_dup 2)))
++                                    (const_int 32))))]
++  "TARGET_HAS_MULX && WORDS_BIG_ENDIAN"
++  "")
++
++(define_expand "mulsidi3"
++    [(match_operand:DI 0 "register_operand" "")
++     (match_operand:SI 1 "register_operand" "")
++     (match_operand:SI 2 "register_operand" "")]
++  "TARGET_HAS_MULX"
++  {
++    if (WORDS_BIG_ENDIAN)
++    {
++        emit_insn (gen_mulsidi3_big_endian (operands[0],
++                                            operands[1],
++                                            operands[2]));
++    }
++    else
++    {
++        emit_insn (gen_mulsidi3_little_endian (operands[0],
++                                               operands[1],
++                                               operands[2]));
++    }
++    DONE;
++  })
++
++(define_expand "umulsidi3_little_endian"
 +    [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0)
 +	  (mult:SI (match_operand:SI 1 "register_operand" "")
 +		   (match_operand:SI 2 "register_operand" "")))
@@ -8186,9 +10703,40 @@
 +	  (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
 +					     (zero_extend:DI (match_dup 2)))
 +				    (const_int 32))))]
-+  "TARGET_HAS_MULX"
++  "TARGET_HAS_MULX && !WORDS_BIG_ENDIAN"
++  "")
++
++(define_expand "umulsidi3_big_endian"
++    [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 4)
++          (mult:SI (match_operand:SI 1 "register_operand" "")
++                   (match_operand:SI 2 "register_operand" "")))
++     (set (subreg:SI (match_dup 0) 0)
++          (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
++                                             (zero_extend:DI (match_dup 2)))
++                                    (const_int 32))))]
++  "TARGET_HAS_MULX && WORDS_BIG_ENDIAN"
 +  "")
 +
++(define_expand "umulsidi3"
++    [(match_operand:DI 0 "register_operand" "")
++     (match_operand:SI 1 "register_operand" "")
++     (match_operand:SI 2 "register_operand" "")]
++  "TARGET_HAS_MULX"
++  {
++    if (WORDS_BIG_ENDIAN)
++    {
++        emit_insn (gen_umulsidi3_big_endian (operands[0],
++                                             operands[1],
++                                             operands[2]));
++    }
++    else
++    {
++        emit_insn (gen_umulsidi3_little_endian (operands[0],
++                                                operands[1],
++                                                operands[2]));
++    }
++    DONE;
++  })
 +
 +
 +;*****************************************************************************
@@ -8207,6 +10755,24 @@
 +}
 +  [(set_attr "type" "alu")])
 +
++(define_insn "negsf2"
++  [(set (match_operand:SF 0 "register_operand"          "=r")
++        (neg:SF (match_operand:SF 1 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_negsf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_negsf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "negdf2"
++  [(set (match_operand:DF 0 "register_operand"          "=r")
++        (neg:DF (match_operand:DF 1 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_negdf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_negdf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
 +(define_insn "one_cmplsi2"
 +  [(set (match_operand:SI 0 "register_operand"        "=r")
 +	(not:SI (match_operand:SI 1 "register_operand" "r")))]
@@ -8218,8 +10784,252 @@
 +  [(set_attr "type" "alu")])
 +
 +
++;*****************************************************************************
++;*
++;* Miscellaneous floating point
++;*
++;*****************************************************************************
++(define_insn "nios2_fwrx"
++  [(unspec_volatile [(match_operand:DF 0 "register_operand" "r")] UNSPEC_FWRX)]
++  "nios2_fpu_insns[nios2_fpu_nios2_fwrx].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_nios2_fwrx].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "nios2_fwry"
++  [(unspec_volatile [(match_operand:SF 0 "register_operand" "r")] UNSPEC_FWRY)]
++  "nios2_fpu_insns[nios2_fpu_nios2_fwry].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_nios2_fwry].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "nios2_frdxlo"
++  [(set (match_operand:SF 0 "register_operand" "=r")
++        (unspec_volatile:SF [(const_int 0)] UNSPEC_FRDXLO))]
++  "nios2_fpu_insns[nios2_fpu_nios2_frdxlo].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_nios2_frdxlo].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "nios2_frdxhi"
++  [(set (match_operand:SF 0 "register_operand" "=r")
++        (unspec_volatile:SF [(const_int 0)] UNSPEC_FRDXHI))]
++  "nios2_fpu_insns[nios2_fpu_nios2_frdxhi].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_nios2_frdxhi].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "nios2_frdy"
++  [(set (match_operand:SF 0 "register_operand" "=r")
++        (unspec_volatile:SF [(const_int 0)] UNSPEC_FRDY))]
++  "nios2_fpu_insns[nios2_fpu_nios2_frdy].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_nios2_frdy].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "minsf3"
++  [(set (match_operand:SF 0 "register_operand" "=r")
++        (if_then_else:SF (lt:SF (match_operand:SF 1 "register_operand" "%r")
++                                (match_operand:SF 2 "register_operand" "r"))
++          (match_dup 1)
++          (match_dup 2)))]
++  "nios2_fpu_insns[nios2_fpu_minsf3].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_minsf3].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "mindf3"
++  [(set (match_operand:DF 0 "register_operand" "=r")
++        (if_then_else:DF (lt:DF (match_operand:DF 1 "register_operand" "%r")
++                                (match_operand:DF 2 "register_operand" "r"))
++          (match_dup 1)
++          (match_dup 2)))]
++  "nios2_fpu_insns[nios2_fpu_mindf3].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_mindf3].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "maxsf3"
++  [(set (match_operand:SF 0 "register_operand" "=r")
++        (if_then_else:SF (lt:SF (match_operand:SF 1 "register_operand" "%r")
++                                (match_operand:SF 2 "register_operand" "r"))
++          (match_dup 2)
++          (match_dup 1)))]
++  "nios2_fpu_insns[nios2_fpu_maxsf3].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_maxsf3].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "maxdf3"
++  [(set (match_operand:DF 0 "register_operand" "=r")
++        (if_then_else:DF (lt:DF (match_operand:DF 1 "register_operand" "%r")
++                                (match_operand:DF 2 "register_operand" "r"))
++          (match_dup 2)
++          (match_dup 1)))]
++  "nios2_fpu_insns[nios2_fpu_maxdf3].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_maxdf3].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "abssf2"
++  [(set (match_operand:SF 0 "register_operand" "=r")
++        (abs:SF (match_operand:SF 1 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_abssf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_abssf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "absdf2"
++  [(set (match_operand:DF 0 "register_operand" "=r")
++        (abs:DF (match_operand:DF 1 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_absdf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_absdf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "sqrtsf2"
++  [(set (match_operand:SF 0 "register_operand" "=r")
++        (sqrt:SF (match_operand:SF 1 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_sqrtsf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_sqrtsf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "sqrtdf2"
++  [(set (match_operand:DF 0 "register_operand" "=r")
++        (sqrt:DF (match_operand:DF 1 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_sqrtdf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_sqrtdf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "cossf2"
++  [(set (match_operand:SF 0 "register_operand" "=r")
++        (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FCOSS))]
++  "nios2_fpu_insns[nios2_fpu_cossf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_cossf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "cosdf2"
++  [(set (match_operand:DF 0 "register_operand" "=r")
++        (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FCOSD))]
++  "nios2_fpu_insns[nios2_fpu_cosdf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_cosdf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "sinsf2"
++  [(set (match_operand:SF 0 "register_operand" "=r")
++        (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FSINS))]
++  "nios2_fpu_insns[nios2_fpu_sinsf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_sinsf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "sindf2"
++  [(set (match_operand:DF 0 "register_operand" "=r")
++        (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FSIND))]
++  "nios2_fpu_insns[nios2_fpu_sindf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_sindf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "tansf2"
++  [(set (match_operand:SF 0 "register_operand" "=r")
++        (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FTANS))]
++  "nios2_fpu_insns[nios2_fpu_tansf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_tansf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "tandf2"
++  [(set (match_operand:DF 0 "register_operand" "=r")
++        (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FTAND))]
++  "nios2_fpu_insns[nios2_fpu_tandf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_tandf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "atansf2"
++  [(set (match_operand:SF 0 "register_operand" "=r")
++        (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FATANS))]
++  "nios2_fpu_insns[nios2_fpu_atansf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_atansf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "atandf2"
++  [(set (match_operand:DF 0 "register_operand" "=r")
++        (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FATAND))]
++  "nios2_fpu_insns[nios2_fpu_atandf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_atandf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "expsf2"
++  [(set (match_operand:SF 0 "register_operand" "=r")
++        (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FEXPS))]
++  "nios2_fpu_insns[nios2_fpu_expsf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_expsf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "expdf2"
++  [(set (match_operand:DF 0 "register_operand" "=r")
++        (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FEXPD))]
++  "nios2_fpu_insns[nios2_fpu_expdf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_expdf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "logsf2"
++  [(set (match_operand:SF 0 "register_operand" "=r")
++        (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FLOGS))]
++  "nios2_fpu_insns[nios2_fpu_logsf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_logsf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "logdf2"
++  [(set (match_operand:DF 0 "register_operand" "=r")
++        (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FLOGD))]
++  "nios2_fpu_insns[nios2_fpu_logdf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_logdf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
 +
-+; Logical Operantions
++
++;*****************************************************************************
++;*
++;*  Logical Operantions
++;*
++;*****************************************************************************
 +
 +(define_insn "andsi3"
 +  [(set (match_operand:SI 0 "register_operand"         "=r, r,r")
@@ -8275,7 +11085,12 @@
 +	(ashift:SI (match_operand:SI 1 "register_operand" "r,r")
 +		   (match_operand:SI 2 "shift_operand"    "r,L")))]
 +  ""
-+  "sll%i2\\t%0, %1, %z2"
++
++{
++	if( GET_CODE ( operands[2] ) == CONST_INT && INTVAL( operands[2] ) == 1 )
++		return "add\t%0,%1,%1";
++	return "sll%i2\t%0,%1,%z2";
++}
 +  [(set_attr "type" "shift")])
 +
 +(define_insn "ashrsi3"
@@ -8334,6 +11149,108 @@
 +
 +;*****************************************************************************
 +;*
++;* Converting between floating point and fixed point
++;*
++;*****************************************************************************
++(define_insn "floatsisf2"
++  [(set (match_operand:SF 0 "register_operand" "=r")
++        (float:SF (match_operand:SI 1 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_floatsisf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_floatsisf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "floatsidf2"
++  [(set (match_operand:DF 0 "register_operand" "=r")
++        (float:DF (match_operand:SI 1 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_floatsidf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_floatsidf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "floatunssisf2"
++  [(set (match_operand:SF 0 "register_operand" "=r")
++        (unsigned_float:SF (match_operand:SI 1 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_floatunssisf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_floatunssisf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "floatunssidf2"
++  [(set (match_operand:DF 0 "register_operand" "=r")
++        (unsigned_float:DF (match_operand:SI 1 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_floatunssidf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_floatunssidf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "fixsfsi2"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++        (fix:SI (match_operand:SF 1 "general_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_fixsfsi2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_fixsfsi2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "fixdfsi2"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++        (fix:SI (match_operand:DF 1 "general_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_fixdfsi2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_fixdfsi2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "fixunssfsi2"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++        (unsigned_fix:SI (match_operand:SF 1 "general_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_fixunssfsi2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_fixunssfsi2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "fixunsdfsi2"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++        (unsigned_fix:SI (match_operand:DF 1 "general_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_fixunsdfsi2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_fixunsdfsi2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "extendsfdf2"
++  [(set (match_operand:DF 0 "register_operand" "=r")
++        (float_extend:DF (match_operand:SF 1 "general_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_extendsfdf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_extendsfdf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++(define_insn "truncdfsf2"
++  [(set (match_operand:SF 0 "register_operand" "=r")
++        (float_truncate:SF (match_operand:DF 1 "general_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_truncdfsf2].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_truncdfsf2].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++
++
++
++
++
++
++
++;*****************************************************************************
++;*
 +;* Prologue, Epilogue and Return
 +;*
 +;*****************************************************************************
@@ -8487,7 +11404,7 @@
 +)
 +
 +(define_insn "sibcall_insn"
-+ [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
++ [(call (mem:QI (match_operand:SI 0 "register_operand" "D08"))
 +	(match_operand 1 "" ""))
 +  (return)
 +  (use (match_operand 2 "" ""))]
@@ -8497,7 +11414,7 @@
 +
 +(define_insn "sibcall_value_insn"
 + [(set (match_operand 0 "register_operand" "")
-+       (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
++       (call (mem:QI (match_operand:SI 1 "register_operand" "D08"))
 +	     (match_operand 2 "" "")))
 +  (return)
 +  (use (match_operand 3 "" ""))]
@@ -8569,6 +11486,40 @@
 +  DONE;
 +})
 +
++(define_expand "cmpsf"
++  [(set (cc0)
++        (compare:CC (match_operand:SF 0 "register_operand" "")
++                    (match_operand:SF 1 "register_operand" "")))]
++  "(nios2_fpu_insns[nios2_fpu_nios2_sltsf].N >= 0
++   || nios2_fpu_insns[nios2_fpu_nios2_sgtsf].N >= 0)
++   && (nios2_fpu_insns[nios2_fpu_nios2_sgesf].N >= 0
++   || nios2_fpu_insns[nios2_fpu_nios2_slesf].N >= 0)
++   && nios2_fpu_insns[nios2_fpu_nios2_seqsf].N >= 0
++   && nios2_fpu_insns[nios2_fpu_nios2_snesf].N >= 0"
++{
++  branch_cmp[0] = operands[0];
++  branch_cmp[1] = operands[1];
++  branch_type = CMP_SF;
++  DONE;
++})
++
++(define_expand "cmpdf"
++  [(set (cc0)
++        (compare:CC (match_operand:DF 0 "register_operand" "")
++                    (match_operand:DF 1 "register_operand" "")))]
++  "(nios2_fpu_insns[nios2_fpu_nios2_sltdf].N >= 0
++   || nios2_fpu_insns[nios2_fpu_nios2_sgtdf].N >= 0)   
++   && (nios2_fpu_insns[nios2_fpu_nios2_sgedf].N >= 0
++   || nios2_fpu_insns[nios2_fpu_nios2_sledf].N >= 0)
++   && nios2_fpu_insns[nios2_fpu_nios2_seqdf].N >= 0
++   && nios2_fpu_insns[nios2_fpu_nios2_snedf].N >= 0"
++{
++  branch_cmp[0] = operands[0];
++  branch_cmp[1] = operands[1];
++  branch_type = CMP_DF;
++  DONE;
++})
++
 +
 +;*****************************************************************************
 +;*
@@ -8582,7 +11533,7 @@
 +	       (match_dup 2)))]
 +  ""
 +{
-+  if (branch_type != CMP_SI)
++  if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
 +    FAIL;
 +
 +  /* set up operands from compare.  */
@@ -8594,13 +11545,35 @@
 +})
 +
 +
-+(define_insn "*seq"
++(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_insn "nios2_seqsf"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++        (eq:SI (match_operand:SF 1 "register_operand" "%r")
++               (match_operand:SF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_nios2_seqsf].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_nios2_seqsf].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++
++(define_insn "nios2_seqdf"
 +  [(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")])
++        (eq:SI (match_operand:DF 1 "register_operand" "%r")
++               (match_operand:DF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_nios2_seqdf].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_nios2_seqdf].output) (insn);
++  }
++  [(set_attr "type" "custom")])
 +
 +
 +(define_expand "sne"
@@ -8609,7 +11582,7 @@
 +	       (match_dup 2)))]
 +  ""
 +{
-+  if (branch_type != CMP_SI)
++  if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
 +    FAIL;
 +
 +  /* set up operands from compare.  */
@@ -8630,13 +11603,35 @@
 +  [(set_attr "type" "alu")])
 +
 +
++(define_insn "nios2_snesf"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++        (ne:SI (match_operand:SF 1 "register_operand" "%r")
++               (match_operand:SF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_nios2_snesf].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_nios2_snesf].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++
++(define_insn "nios2_snedf"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++        (ne:SI (match_operand:DF 1 "register_operand" "%r")
++               (match_operand:DF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_nios2_snedf].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_nios2_snedf].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++
 +(define_expand "sgt"
 +  [(set (match_operand:SI 0 "register_operand" "=r")
 +	(gt:SI (match_dup 1)
 +	       (match_dup 2)))]
 +  ""
 +{
-+  if (branch_type != CMP_SI)
++  if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
 +    FAIL;
 +
 +  /* set up operands from compare.  */
@@ -8657,13 +11652,35 @@
 +  [(set_attr "type" "alu")])
 +
 +
++(define_insn "nios2_sgtsf"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++        (gt:SI (match_operand:SF 1 "register_operand" "r")
++               (match_operand:SF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_nios2_sgtsf].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_nios2_sgtsf].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++
++(define_insn "nios2_sgtdf"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++        (gt:SI (match_operand:DF 1 "register_operand" "r")
++               (match_operand:DF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_nios2_sgtdf].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_nios2_sgtdf].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++
 +(define_expand "sge"
 +  [(set (match_operand:SI 0 "register_operand" "=r")
 +	(ge:SI (match_dup 1)
 +	       (match_dup 2)))]
 +  ""
 +{
-+  if (branch_type != CMP_SI)
++  if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
 +    FAIL;
 +
 +  /* set up operands from compare.  */
@@ -8683,13 +11700,36 @@
 +  "cmpge%i2\\t%0, %z1, %z2"
 +  [(set_attr "type" "alu")])
 +
++
++(define_insn "nios2_sgesf"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++        (ge:SI (match_operand:SF 1 "register_operand" "r")
++               (match_operand:SF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_nios2_sgesf].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_nios2_sgesf].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++
++(define_insn "nios2_sgedf"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++        (ge:SI (match_operand:DF 1 "register_operand" "r")
++               (match_operand:DF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_nios2_sgedf].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_nios2_sgedf].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++
 +(define_expand "sle"
 +  [(set (match_operand:SI 0 "register_operand" "=r")
 +	(le:SI (match_dup 1)
 +	       (match_dup 2)))]
 +  ""
 +{
-+  if (branch_type != CMP_SI)
++  if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
 +    FAIL;
 +
 +  /* set up operands from compare.  */
@@ -8710,13 +11750,35 @@
 +  [(set_attr "type" "alu")])
 +
 +
++(define_insn "nios2_slesf"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++        (le:SI (match_operand:SF 1 "register_operand" "r")
++               (match_operand:SF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_nios2_slesf].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_nios2_slesf].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++
++(define_insn "nios2_sledf"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++        (le:SI (match_operand:DF 1 "register_operand" "r")
++               (match_operand:DF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_nios2_sledf].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_nios2_sledf].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++
 +(define_expand "slt"
 +  [(set (match_operand:SI 0 "register_operand" "=r")
 +	(lt:SI (match_dup 1)
 +	       (match_dup 2)))]
 +  ""
 +{
-+  if (branch_type != CMP_SI)
++  if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
 +    FAIL;
 +
 +  /* set up operands from compare.  */
@@ -8737,6 +11799,28 @@
 +  [(set_attr "type" "alu")])
 +
 +
++(define_insn "nios2_sltsf"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++        (lt:SI (match_operand:SF 1 "register_operand" "r")
++               (match_operand:SF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_nios2_sltsf].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_nios2_sltsf].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++
++(define_insn "nios2_sltdf"
++  [(set (match_operand:SI 0 "register_operand"        "=r")
++        (lt:SI (match_operand:DF 1 "register_operand" "r")
++               (match_operand:DF 2 "register_operand" "r")))]
++  "nios2_fpu_insns[nios2_fpu_nios2_sltdf].N >= 0"
++  {
++    return (*nios2_fpu_insns[nios2_fpu_nios2_sltdf].output) (insn);
++  }
++  [(set_attr "type" "custom")])
++
++
 +(define_expand "sgtu"
 +  [(set (match_operand:SI 0 "register_operand" "=r")
 +	(gtu:SI (match_dup 1)
@@ -8865,6 +11949,36 @@
 +  [(set_attr "type" "control")])
 +
 +
++(define_insn "nios2_cbranch_sf"
++  [(set (pc)
++        (if_then_else
++         (match_operator:SI 0 "comparison_operator"
++                            [(match_operand:SF 2 "register_operand" "r")
++                             (match_operand:SF 3 "register_operand" "r")])
++        (label_ref (match_operand 1 "" ""))
++        (pc)))]
++  ""
++  {
++    return nios2_output_fpu_insn_cmps (insn, GET_CODE (operands[0]));
++  }
++  [(set_attr "type" "custom")])
++
++
++(define_insn "nios2_cbranch_df"
++  [(set (pc)
++        (if_then_else
++         (match_operator:SI 0 "comparison_operator"
++                            [(match_operand:DF 2 "register_operand" "r")
++                             (match_operand:DF 3 "register_operand" "r")])
++        (label_ref (match_operand 1 "" ""))
++        (pc)))]
++  ""
++  {
++    return nios2_output_fpu_insn_cmpd (insn, GET_CODE (operands[0]));
++  }
++  [(set_attr "type" "custom")])
++
++
 +(define_expand "beq"
 +  [(set (pc)
 +	(if_then_else (eq:CC (cc0)
@@ -9672,92 +12786,291 @@
 +  "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_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")])
++
++
++
++
++
++
++;*****************************************************************************
++;*
++;* 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 "reg_or_0_operand" "rM")] UNSPEC_WRCTL)]
++  ""
++  "wrctl\\tctl%0, %z1"
++  [(set_attr "type" "control")])
++
++;Used to signal a stack overflow 
++(define_insn "trap"
++  [(unspec_volatile [(const_int 0)] UNSPEC_TRAP)]
++  ""
++  "break\\t3"
++  [(set_attr "type" "control")])
++  
++(define_insn "stack_overflow_detect_and_trap"
++  [(unspec_volatile [(const_int 0)] UNSPEC_STACK_OVERFLOW_DETECT_AND_TRAP)]
++  ""
++  "bgeu\\tsp, et, 1f\;break\\t3\;1:"
++  [(set_attr "type" "control")])
++
++
++;*****************************************************************************
++;*
++;* Peepholes
++;*
++;*****************************************************************************
++
++
++;; Local Variables:
++;; mode: lisp
++;; End:
+diff --git a/gcc/config/nios2/t-nios2 b/gcc/config/nios2/t-nios2
+new file mode 100644
+index 0000000..b92f80a
+--- /dev/null
++++ b/gcc/config/nios2/t-nios2
+@@ -0,0 +1,175 @@
++##
++## 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}
++	echo '#ifndef __nios2_big_endian__' >> ${FPBIT}
++	echo '#define FLOAT_BIT_ORDER_MISMATCH' >> ${FPBIT}
++	echo '#endif' >> ${FPBIT}
++	cat $(srcdir)/config/fp-bit.c >> ${FPBIT}
++
++$(DPBIT): $(srcdir)/config/fp-bit.c Makefile
++	echo ''          >  ${DPBIT}
++	echo '#ifndef __nios2_big_endian__' >> ${DPBIT}
++	echo '#define FLOAT_BIT_ORDER_MISMATCH' >> ${DPBIT}
++	echo '#endif' >> ${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.
++
 +
-+(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")])
++## The BUILD_BE_MULTILIB and BUILD_PG_MULTILIB variables allow the
++## makefile user to enable/disable the generation of the precompiled
++## big endian and profiling libraries. By default, the big endian 
++## libraries are not created on a windows build and the profiling
++## libraries are not created on a Solaris build. All other library 
++## combinations are created by default.
 +
-+(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")])
++# Uncomment to temporarily avoid building big endian and profiling libraries during a Windows build.
++#ifeq ($(DEV_HOST_OS), win32)
++#BUILD_BE_MULTILIB ?= 0
++#BUILD_PG_MULTILIB ?= 0
++#endif
 +
-+(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")])
++#By default, avoid building the profiling libraries during a Solaris build.
++ifeq ($(DEV_HOST_OS), solaris)
++BUILD_PG_MULTILIB ?= 0
++endif
 +
++BUILD_BE_MULTILIB ?= 1
++BUILD_PG_MULTILIB ?= 1
++BUILD_MULTILIB ?= 1
 +
++ifeq ($(BUILD_MULTILIB), 1)
 +
++MULTILIB_OPTIONS = mno-hw-mul mhw-mulx mstack-check mcustom-fpu-cfg=60-1 mcustom-fpu-cfg=60-2
 +
++#Add the profiling flag to the multilib variable if required
++ifeq ($(BUILD_PG_MULTILIB), 1)
++MULTILIB_OPTIONS += pg
++endif
 +
-+
-+;*****************************************************************************
-+;*
-+;* Misc
-+;*
-+;*****************************************************************************
++#Add the big endian flag to the multilib variable if required
++ifeq ($(BUILD_BE_MULTILIB), 1)
++MULTILIB_OPTIONS += EB/EL
++endif
 +
-+(define_insn "nop"
-+  [(const_int 0)]
-+  ""
-+  "nop\\t"
-+  [(set_attr "type" "alu")])
++endif
 +
-+(define_insn "sync"
-+  [(unspec_volatile [(const_int 0)] UNSPEC_SYNC)]
-+  ""
-+  "sync\\t"
-+  [(set_attr "type" "control")])
++## 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 =
 +
-+(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")])
++## 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.
 +
-+(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")])
++ifeq ($(BUILD_MULTILIB), 1)
++ifeq ($(BUILD_BE_MULTILIB), 1)
++MULTILIB_MATCHES = EL=mel EB=meb
++endif
++endif
 +
++##
++## 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*
++##
 +
-+
-+;*****************************************************************************
-+;*
-+;* Peepholes
-+;*
-+;*****************************************************************************
++ifeq ($(BUILD_MULTILIB), 1)
++MULTILIB_EXCEPTIONS = *mno-hw-mul/*mhw-mulx* *mcustom-fpu-cfg=60-1/*mcustom-fpu-cfg=60-2*
++endif
 +
++##
++## 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/nios2/t-nios2
-+++ gcc-3.4.3-nios2/gcc/config/nios2/t-nios2
-@@ -0,0 +1,123 @@
+diff --git a/gcc/config/nios2/t-nios2-uclibc b/gcc/config/nios2/t-nios2-uclibc
+new file mode 100644
+index 0000000..9a303db
+--- /dev/null
++++ b/gcc/config/nios2/t-nios2-uclibc
+@@ -0,0 +1,152 @@
 +##
 +## Compiler flags to use when compiling libgcc2.c.
 +##
@@ -9790,23 +13103,19 @@
 +
 +$(FPBIT): $(srcdir)/config/fp-bit.c Makefile
 +	echo '#define FLOAT'          >  ${FPBIT}
++	echo '#ifndef __nios2_big_endian__' >> ${FPBIT}
++	echo '#define FLOAT_BIT_ORDER_MISMATCH' >> ${FPBIT}
++	echo '#endif' >> ${FPBIT}
 +	cat $(srcdir)/config/fp-bit.c >> ${FPBIT}
 +
 +$(DPBIT): $(srcdir)/config/fp-bit.c Makefile
 +	echo ''          >  ${DPBIT}
++	echo '#ifndef __nios2_big_endian__' >> ${DPBIT}
++	echo '#define FLOAT_BIT_ORDER_MISMATCH' >> ${DPBIT}
++	echo '#endif' >> ${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 
-+
++EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
 +
 +## 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
@@ -9837,7 +13146,31 @@
 +## sets of options: -m68000, -m68020, -msoft-float, -m68000 -msoft-float,
 +## and -m68020 -msoft-float.
 +
-+MULTILIB_OPTIONS = mno-hw-mul mhw-mulx
++
++## The BUILD_BE_MULTILIB and BUILD_PG_MULTILIB variables allow the
++## makefile user to enable/disable the generation of the precompiled
++## big endian and profiling libraries.
++
++# By default, avoid building big endian and profiling libraries
++BUILD_BE_MULTILIB ?= 0
++BUILD_PG_MULTILIB ?= 0
++BUILD_MULTILIB ?= 1
++
++ifeq ($(BUILD_MULTILIB), 1)
++
++MULTILIB_OPTIONS = mno-hw-mul mhw-mulx mstack-check mcustom-fpu-cfg=60-1 mcustom-fpu-cfg=60-2
++
++#Add the profiling flag to the multilib variable if required
++ifeq ($(BUILD_PG_MULTILIB), 1)
++MULTILIB_OPTIONS += pg
++endif
++
++#Add the big endian flag to the multilib variable if required
++ifeq ($(BUILD_BE_MULTILIB), 1)
++MULTILIB_OPTIONS += EB/EL
++endif
++
++endif
 +
 +## MULTILIB_DIRNAMES
 +## If MULTILIB_OPTIONS is used, this variable specifies the directory names
@@ -9858,6 +13191,13 @@
 +## 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.
++
++ifeq ($(BUILD_MULTILIB), 1)
++ifeq ($(BUILD_BE_MULTILIB), 1)
++MULTILIB_MATCHES = EL=mel EB=meb
++endif
++endif
++
 +##
 +## MULTILIB_EXCEPTIONS
 +## Sometimes when there are multiple sets of MULTILIB_OPTIONS being
@@ -9872,7 +13212,9 @@
 +## *mcall-aix/*fleading-underscore* *mlittle/*mcall-aix*
 +##
 +
-+MULTILIB_EXCEPTIONS = *mno-hw-mul/*mhw-mulx*
++ifeq ($(BUILD_MULTILIB), 1)
++MULTILIB_EXCEPTIONS = *mno-hw-mul/*mhw-mulx* *mcustom-fpu-cfg=60-1/*mcustom-fpu-cfg=60-2*
++endif
 +
 +##
 +## MULTILIB_EXTRA_OPTS Sometimes it is desirable that when building
@@ -9881,22 +13223,11 @@
 +## 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
+diff --git a/gcc/cse.c b/gcc/cse.c
+index 72af39a..b36310c 100644
+--- a/gcc/cse.c
++++ b/gcc/cse.c
+@@ -3134,6 +3134,10 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
  #ifdef FLOAT_STORE_FLAG_VALUE
  	  REAL_VALUE_TYPE fsfv;
  #endif
@@ -9907,9 +13238,45 @@
  
  	  /* 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
+diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
+index 4638645..cdb248d 100644
+--- a/gcc/doc/extend.texi
++++ b/gcc/doc/extend.texi
+@@ -2488,6 +2488,33 @@ contents of that register.   The @code{short_call} attribute always places
+ the offset to the function from the call site into the @samp{BL}
+ instruction directly.
+ 
++@item reverse_bitfields/no_reverse_bitfields
++@cindex reverse_bitfields on Altera Nios II
++This attribute specifies the order of bitfield allocation within a
++particular struct on Altera's Nios II processor.  This overrides both
++the @option{-mno-reverse-bitfields} and @option{-mreverse-bitfields}
++switches, as well as any @code{#pragma} that might be present.  It is
++ignored except when present on a struct.
++
++@smallexample
++struct inner
++@{
++  unsigned int a:1;
++  unsigned int b:31;
++@} __attribute__ ((reverse_bitfields));
++
++union outer
++@{
++  struct inner inner;
++  unsigned int val;
++@};
++
++@end smallexample
++
++will cause a to be allocated overlapping the most significant bit of
++val, regardless of any @code{#pragma} or compiler switch.  See the
++@option{-mreverse-bitfields} switch for more examples.
++
+ @item function_vector
+ @cindex calling functions through the function vector on the H8/300 processors
+ Use this attribute on the H8/300, H8/300H, and H8S to indicate that the specified
+@@ -5638,12 +5665,118 @@ to those machines.  Generally these generate calls to specific machine
  instructions, but allow the compiler to schedule those calls.
  
  @menu
@@ -10028,9 +13395,49 @@
  @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.
+@@ -8022,6 +8155,7 @@ we do not recommend the use of pragmas; @xref{Function Attributes},
+ for further explanation.
+ 
+ @menu
++* Altera Nios II Pragmas::
+ * ARM Pragmas::
+ * RS/6000 and PowerPC Pragmas::
+ * Darwin Pragmas::
+@@ -8029,6 +8163,29 @@ for further explanation.
+ * Tru64 Pragmas::
+ @end menu
+ 
++@node Altera Nios II Pragmas
++@subsection Altera Nios II Pragmas
++
++The Altera Nios II target defines two pragmas to control the placement
++of bitfields within a struct.
++
++@table @code
++@item reverse_bitfields
++@cindex pragma, reverse_bitfields
++Cause all subsequent structs to behave as though the -mreverse-bitfields
++compiler switch had been given.  Can be overridden by the
++@code{no_reverse_bitfields} attribute or a subsequent
++@code{#pragma no_reverse_bitfields}.
++
++@item no_reverse_bitfields
++@cindex pragma, no_reverse_bitfields
++Cause all subsequent structs to behave as though the -mno-reverse-bitfields
++compiler switch had been given.  Can be overridden by the
++@code{reverse_bitfields} attribute or a subsequent
++@code{#pragma reverse_bitfields}.
++
++@end table
++
+ @node ARM Pragmas
+ @subsection ARM Pragmas
+ 
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index e683d0c..b34200f 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -337,6 +337,16 @@ in the following sections.
  @item Machine Dependent Options
  @xref{Submodel Options,,Hardware Models and Configurations}.
  
@@ -10040,12 +13447,14 @@
 +-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 }
++-mno-stack-check -mstack-check @gol
++-msys-crt0= -msys-lib= -msys=nosys @gol
++-mreverse-bitfields -mno-reverse-bitfields}
 +
  @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
+@@ -5839,6 +5849,7 @@ machine description.  The default for the options is also defined by
  that macro, which enables you to change the defaults.
  
  @menu
@@ -10053,7 +13462,7 @@
  * M680x0 Options::
  * M68hc1x Options::
  * VAX Options::
-@@ -5871,6 +5880,103 @@ that macro, which enables you to change 
+@@ -5874,6 +5885,290 @@ that macro, which enables you to change the defaults.
  * FRV Options::
  @end menu
  
@@ -10069,7 +13478,6 @@
 +
 +@item -msmallc
 +@opindex msmallc
-+
 +Link with a limited version of the C library, -lsmallc. For more 
 +information see the C Library Documentation.
 +
@@ -10078,7 +13486,6 @@
 +@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.
@@ -10087,7 +13494,6 @@
 +@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. 
@@ -10100,7 +13506,6 @@
 +@itemx -minline-memcpy
 +@opindex mno-inline-memcpy 
 +@opindex minline-memcpy
-+
 +Do not inline memcpy. The default is to inline when -O is on.
 +
 +
@@ -10108,7 +13513,6 @@
 +@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.
 +
@@ -10125,7 +13529,6 @@
 +@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}.
@@ -10133,10 +13536,16 @@
 +The different combinations of @code{mul} and @code{mulx} instructions 
 +generate a different multilib options. 
 +
++@item -mno-stack-check
++@itemx -mstack-check
++@opindex no-stack-check
++@opindex stack-check
++Enables or disables the checking for sufficient memory when 
++items are pushed onto the stack. A checked and non-checked
++version of each of the multilibs is provided.
 +
 +@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
@@ -10145,21 +13554,210 @@
 +@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.
 +
++@item -mno-reverse-bitfields
++@itemx -mreverse-bitfields
++@opindex mno-reverse-bitfields
++@opindex mreverse-bitfields
++When enabled, bitfields within a struct are allocated in reverse order.
++This is useful with legacy code that depends on the (inherently
++non-portable) ordering of bitfields via a union.  Given:
++
++@smallexample
++struct inner
++@{
++  unsigned int a:1;
++  unsigned int b:31;
++@};
++
++union outer
++@{
++  struct inner inner;
++  unsigned int val;
++@};
++
++unsigned int f()
++@{
++  union outer o;
++  o.inner.a = 1;
++  o.inner.b = 0;
++  return o.val;
++@}
++@end smallexample
++
++a call to @code{f} will return 1 when compiled with
++@option{-mno-reverse-bitfields} (the default), or 2147483648 when
++compiled with @option{-mreverse-bitfields}.
++
++For structures that are a multiple of 32 bits wide, the reversal is
++done 32 bits at a time.  For structures that are an odd multiple of 16
++bits wide, the reversal is done 16 bits at a time.  For structures
++that are an odd multiple of 8 bits wide, the reversal is done 8 bits
++at a time.  The size of a structure (as measured by the @code{sizeof}
++operator) never changes between @option{-mno-reverse-bitfields} and
++@option{-mreverse-bitfields}.  Nonetheless, there can be some
++confusing corner cases with structs where the compiler has to add
++additional padding to meet alignment restrictions.  Consider:
++
++@smallexample
++struct inner
++@{
++  unsigned int a:1;
++  unsigned int b:15;
++@};
++
++union outer
++@{
++  struct inner inner;
++  unsigned int val;
++@};
++
++unsigned int f()
++@{
++  union outer o;
++  o.val = 0;
++  o.inner.b = 1;
++  return o.val;
++@}
++@end smallexample
++
++a call to @code{f} will return 2 when compiled with
++@option{-mno-reverse-bitfields} (the default), or 65536 when compiled
++with @option{-mreverse-bitfields}.  This is because @code{sizeof
++(inner)} is 4 in both cases.  In the @option{-mno-reverse-bitfields}
++case, the compiler pads the struct at the end to be 4 bytes long,
++effectively doing:
++
++@smallexample
++struct inner
++@{
++  unsigned int a:1;
++  unsigned int b:15;
++  unsigned int padding:16;
++@};
++@end smallexample
++
++In the @option{-mreverse-bitfields} case, the hidden padding is
++reversed along with everything else, yielding the equivalent of:
++
++@smallexample
++struct inner
++@{
++  unsigned int padding:16;
++  unsigned int b:15;
++  unsigned int a:1;
++@};
++@end smallexample
++
++Of course, if we would rather that @code{sizeof (inner)} was 2, we could
++write the struct as:
++
++@smallexample
++struct inner
++@{
++  unsigned short a:1;
++  unsigned short b:15;
++@};
++@end smallexample
++
++and the padding would go away.
++
++In some cases, especially when using the @code{__packed__} attribute,
++there is no well-defined bit reversal that is possible: the compiler
++will issue an error message in this case.  Consider:
++
++@smallexample
++struct invalid
++@{
++  unsigned int f1:1;
++  unsigned int f2:15;
++  unsigned int f3:4;
++  unsigned int f4:4;
++@} __attribute__ ((__packed__));
++@end smallexample
++
++Since @code{sizeof (invalid)} is 3, we are forced to try reversing
++individual bytes in the struct.  But f2 is more than a byte wide, so
++we can't reverse it and still have it be contiguous.  Similar cases
++occur when dealing with arrays or other large contiguous objects:
++
++@smallexample
++struct invalid2
++@{
++  unsigned char f1[5];
++  unsigned char f2[3];
++@};
++@end smallexample
++
++You'll have to rewrite the affected structs to say exactly what you
++mean in odd cases like that.
++
++Finally, note that individual fields are sized as a whole.  The structs
++
++@smallexample
++struct array1
++@{
++  unsigned char f1[3];
++  unsigned char f2;
++@}
++@end smallexample
++
++and:
++
++@smallexample
++struct array2
++@{
++  unsigned char f1a;
++  unsigned char f1b;
++  unsigned char f1c;
++  unsigned char f2;
++@}
++@end smallexample
++
++are not equivalent.  When compiled with @option{-mreverse-bitfields},
++they behave the same as:
++
++@smallexample
++struct array1r
++@{
++  unsigned char f2;
++  unsigned char f1[3];
++@}
++@end smallexample
++
++and:
++
++@smallexample
++struct array2r
++@{
++  unsigned char f2;
++  unsigned char f1c;
++  unsigned char f1b;
++  unsigned char f1a;
++@}
++@end smallexample
++
++would, respectively, when compiled with
++@option{-mno-reverse-bitfields}.  In particular, f1 is treated as a
++single contiguous 24-bit object for purposes of reversal, while f1a,
++f1b, and f1c are treated as individual 8-bit objects that need not
++(and do not) remain contiguous.  Use caution.
++
 +@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
+diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
+index b73f325..4a134b2 100644
+--- a/gcc/doc/md.texi
++++ b/gcc/doc/md.texi
+@@ -1337,6 +1337,58 @@ However, here is a summary of the machine-dependent constraints
  available on some particular machines.
  
  @table @emph
@@ -10203,9 +13801,577 @@
 +data section and therefore can be added to @code{gp}
 +as a 16-bit immediate to re-create their 32-bit value.
 +
++@item D@var{nn}
++For a given two digit @var{nn} constrains the operand
++to the corresponding register. Example: D02 forces the
++operand into register r2. The side effect of using this
++operand constraint is that reload may not be able to 
++meet the constraint. If reload fails, an error message
++about failing to find any register to spill in the
++D@var{nn}_REG register class will be emitted.
++
 +@end table
 +
 +
  @item ARM family---@file{arm.h}
  @table @code
  @item f
+diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
+index 4527fe4..e7cc581 100644
+--- a/gcc/stor-layout.c
++++ b/gcc/stor-layout.c
+@@ -1435,6 +1435,355 @@ finalize_type_size (tree type)
+     }
+ }
+ 
++static void
++reverse_bitfield_layout (record_layout_info rli)
++{
++  tree field;
++  tree rev_size;
++  unsigned int rev_size_int;
++
++  /*
++   * The size of the words we'll be reversing.  Normally, we reverse
++   * entire SImode words.  However, if the entire struct's size isn't an
++   * exact multiple of the size of SImode, we can reverse HImode or even
++   * QImode pieces.  In the examples below, assume SImode/int is 32
++   * bits, HImode/short is 16 bits, and QImode/char is 8 bits.
++   * Consider:
++   *
++   *   struct s1
++   *   {
++   *     int f1:1;
++   *     int f2:31;
++   *   };
++   *
++   *   struct s2
++   *   {
++   *     int f1:1;
++   *     int f2:15;
++   *   } __attribute__ ((__packed__));
++   *
++   *   struct s3
++   *   {
++   *     short f1:1;
++   *     short f2:15;
++   *   };
++   *
++   *   struct s4
++   *   {
++   *     int f1:1;
++   *     int f2:15;
++   *   };
++   *
++   *   struct s5
++   *   {
++   *     int f1:8;
++   *     int f2:8;
++   *     int f3:4;
++   *     int f4:4;
++   *   } __attribute__ ((__packed__));
++   *
++   *   struct s6
++   *   {
++   *     int f1:1;
++   *     int f2:15;
++   *     int f3:4;
++   *     int f4:4;
++   *     int f5:8;
++   *   };
++   *
++   *   struct s7
++   *   {
++   *     int f1:1;
++   *     int f2:15;
++   *     int f3:4;
++   *     int f4:4;
++   *   } __attribute__ ((__packed__));
++   *
++   *   struct s8
++   *   {
++   *     char f1;
++   *     short f2;
++   *     char f3;
++   *   };
++   *
++   *   struct s9
++   *   {
++   *     char f1;
++   *     short f2;
++   *     char f3;
++   *   } __attribute__ ((__packed__));
++   *
++   *   struct s10
++   *   {
++   *     char f1;
++   *     short f2;
++   *     char f3;
++   *     short f4;
++   *   };
++   *
++   *   struct s11
++   *   {
++   *     char f1[5];
++   *     int f2;
++   *   };
++   *
++   *   struct s12
++   *   {
++   *     char f1[5];
++   *     char f2[3];
++   *     int f3;
++   *   };
++   *
++   *   struct s13
++   *   {
++   *     char f1[3];
++   *     int f2;
++   *   };
++   *
++   *   struct s14
++   *   {
++   *     char f1a;
++   *     char f1b;
++   *     char f1c;
++   *     int f2;
++   *   };
++   *
++   * Then we have:
++   *
++   *   sizeof (struct s1) == 4
++   *   sizeof (struct s2) == 2
++   *   sizeof (struct s3) == 2
++   *   sizeof (struct s4) == 4
++   *   sizeof (struct s5) == 3
++   *   sizeof (struct s6) == 4
++   *   sizeof (struct s7) == 3
++   *   sizeof (struct s8) == 6
++   *   sizeof (struct s9) == 4
++   *   sizeof (struct s10) == 8
++   *   sizeof (struct s11) == 12
++   *   sizeof (struct s12) == 12
++   *
++   * We want the equivalent reversed bitfield structs to be:
++   *
++   *   struct s1r
++   *   {
++   *     int f2:31;
++   *     int f1:1;
++   *   };
++   *
++   *   struct s2r
++   *   {
++   *     int f2:15;
++   *     int f1:1;
++   *   } __attribute__ ((__packed__));
++   *
++   *   struct s3r
++   *   {
++   *     short f2:15;
++   *     short f1:1;
++   *   };
++   *
++   *   struct s4r
++   *   {
++   *     int unnamed:16;
++   *     int f2:15;
++   *     int f1:1;
++   *   };
++   *
++   *   struct s5r
++   *   {
++   *     int f1:8;
++   *     int f2:8;
++   *     int f4:4;
++   *     int f3:4;
++   *   } __attribute__ ((__packed__));
++   *
++   *   struct s6r
++   *   {
++   *     int f5:8;
++   *     int f4:4;
++   *     int f3:4;
++   *     int f2:15;
++   *     int f1:1;
++   *   };
++   *
++   *   struct s7r
++   *   {
++   *     #error cannot reverse bitfield
++   *   } __attribute__ ((__packed__));
++   *
++   *   struct s8r
++   *   {
++   *     char unnamed1;
++   *     char f1;
++   *     short f2;
++   *     char unnamed2;
++   *     char f3;
++   *   };
++   *
++   *   struct s9r
++   *   {
++   *     char f3;
++   *     short f2;
++   *     char f1;
++   *   } __attribute__ ((__packed__));
++   *
++   *   struct s10r
++   *   {
++   *     short f2;
++   *     char unnamed1;
++   *     char f1;
++   *     short f4;
++   *     char unnamed2;
++   *     char f3;
++   *   };
++   *
++   *   struct s11r
++   *   {
++   *     char f1[5];
++   *     int f2;
++   *   };
++   *
++   *   struct s12r
++   *   {
++   *     #error cannot reverse bitfield
++   *   };
++   *
++   *   struct s13r
++   *   {
++   *     char unnamed;
++   *     char f1[3];
++   *     int f2;
++   *   };
++   *
++   *   struct s14r
++   *   {
++   *     char unnamed;
++   *     char f1c;
++   *     char f1b;
++   *     char f1a;
++   *     int f2;
++   *   };
++   *
++   * Note that the s4, s8, s10, s13, and s14 cases produce somewhat
++   * suprising results: the normally hidden padding bytes the compiler
++   * adds are also reversed.  Further note that s13 and s14 are not
++   * equivalent: the f1 field in s13 is 24-bits wide, and is reversed
++   * accordingly, while the three fields f1a, f1b, and f1c in s14 are
++   * reversed as individual bytes.
++   *
++   * The s7 and s12 cases produce an error: we can't reverse a bitfield
++   * that is larger than word size we're reversing.  The error is
++   * suppressed in the s11 case since the field in question and the
++   * field that follows are both word aligned.
++   */
++
++  /*
++   * First, figure out what size words to reverse.  We look at the total
++   * number of bits currently in use by the struct, rounded up to the
++   * next multiple of rli->record_align, to decide.
++   */
++  {
++    int bits_in_use = TREE_INT_CST_LOW (round_up (rli_size_so_far (rli),
++                                                  rli->record_align));
++    unsigned int size;
++    for (size = GET_MODE_BITSIZE (SImode);
++         size >= GET_MODE_BITSIZE (QImode);
++         size /= 2)
++    {
++      if (bits_in_use % size == 0)
++      {
++        break;
++      }
++    }
++    if (size < GET_MODE_BITSIZE (QImode))
++    {
++      /*
++       * rli->record_align should never be less than QImode, even
++       * for packed structs.
++       */
++      abort ();
++    }
++    rev_size = size_int_type (size, bitsizetype);
++    rev_size_int = size;
++  }
++
++  /*
++   * Then, iterate over the fields, reversing them as we go.
++   */
++  for (field = TYPE_FIELDS (rli->t); field; field = TREE_CHAIN (field))
++    {
++      tree type = TREE_TYPE (field);
++      if (TREE_CODE (field) != FIELD_DECL)
++        {
++          continue;
++        }
++      if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
++        {
++          return;
++        }
++      {
++        tree offset = DECL_FIELD_OFFSET (field);
++        tree offset_type = TREE_TYPE (offset);
++        tree bit_offset = DECL_FIELD_BIT_OFFSET (field);
++        tree bit_offset_type = TREE_TYPE (bit_offset);
++        tree bit = bit_from_pos (offset, bit_offset);
++        tree true_size = DECL_SIZE (field);
++        pos_from_bit (&offset, &bit_offset, rev_size_int, bit);
++        bit_offset = size_binop (MINUS_EXPR,
++                                 size_binop (MINUS_EXPR, rev_size, true_size),
++                                 bit_offset);
++        if (TREE_INT_CST_HIGH (bit_offset) != 0)
++        {
++          /*
++           * This happens when a field spans a rev_size boundary (see
++           * example s7 above): rather than try to come up with some
++           * well-defined, but non-intuitive definition for this case,
++           * just issue an error.  It can also happen for large fields,
++           * e.g. arrays or other structs: if these large fields were
++           * already aligned, leave them be; otherwise issue the error
++           * in this case as well.
++           */
++          if ((TREE_INT_CST_HIGH (true_size) != 0
++               || TREE_INT_CST_LOW (true_size) > rev_size_int)
++              && TREE_INT_CST_HIGH (DECL_FIELD_BIT_OFFSET (field)) == 0
++              && TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)) == 0)
++          {
++            tree next_field = TREE_CHAIN (field);
++            if (!next_field)
++            {
++              /* No following field, so we're ok. */
++              continue;
++            }
++            else
++            {
++              tree next_offset = DECL_FIELD_OFFSET (next_field);
++              tree next_bit_offset = DECL_FIELD_BIT_OFFSET (next_field);
++              tree next_bit = bit_from_pos (next_offset, next_bit_offset);
++              pos_from_bit (&next_offset, &next_bit_offset, rev_size_int,
++                            next_bit);
++              if (TREE_INT_CST_HIGH (next_bit_offset) == 0
++                  && TREE_INT_CST_LOW (next_bit_offset) == 0)
++              {
++                /* Following field is aligned wrt rev_size_int boundary,
++                   so we're ok. */
++                continue;
++              }
++            }
++          }
++          error ("unable to reverse bitfields in structure");
++          return;
++        }
++        bit = bit_from_pos (offset, bit_offset);
++        pos_from_bit (&offset, &bit_offset, rli->offset_align, bit);
++        TREE_TYPE (offset) = offset_type;
++        DECL_FIELD_OFFSET (field) = offset;
++        TREE_TYPE (bit_offset) = bit_offset_type;
++        DECL_FIELD_BIT_OFFSET (field) = bit_offset;
++      }
++    }
++}
++
+ /* Do all of the work required to layout the type indicated by RLI,
+    once the fields have been laid out.  This function will call `free'
+    for RLI, unless FREE_P is false.  Passing a value other than false
+@@ -1444,6 +1793,12 @@ finalize_type_size (tree type)
+ void
+ finish_record_layout (record_layout_info rli, int free_p)
+ {
++  /* Optionally reverse the placement of bitfields within the record */
++  if ((* targetm.reverse_bitfield_layout_p) (rli->t))
++    {
++      reverse_bitfield_layout (rli);
++    }
++
+   /* Compute the final size.  */
+   finalize_record_size (rli);
+ 
+diff --git a/gcc/target-def.h b/gcc/target-def.h
+index 32d00ae..bdea4d4 100644
+--- a/gcc/target-def.h
++++ b/gcc/target-def.h
+@@ -300,6 +300,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ #define TARGET_INSERT_ATTRIBUTES hook_void_tree_treeptr
+ #define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P hook_bool_tree_false
+ #define TARGET_MS_BITFIELD_LAYOUT_P hook_bool_tree_false
++#define TARGET_REVERSE_BITFIELD_LAYOUT_P hook_bool_tree_false
+ #define TARGET_RTX_COSTS hook_bool_rtx_int_int_intp_false
+ #define TARGET_MANGLE_FUNDAMENTAL_TYPE hook_constcharptr_tree_null
+ 
+@@ -368,6 +369,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   TARGET_INSERT_ATTRIBUTES,			\
+   TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P,	\
+   TARGET_MS_BITFIELD_LAYOUT_P,			\
++  TARGET_REVERSE_BITFIELD_LAYOUT_P,     \
+   TARGET_INIT_BUILTINS,				\
+   TARGET_EXPAND_BUILTIN,			\
+   TARGET_MANGLE_FUNDAMENTAL_TYPE,		\
+diff --git a/gcc/target.h b/gcc/target.h
+index 59788f9..97bde5f 100644
+--- a/gcc/target.h
++++ b/gcc/target.h
+@@ -295,6 +295,10 @@ struct gcc_target
+      Microsoft Visual C++ bitfield layout rules.  */
+   bool (* ms_bitfield_layout_p) (tree record_type);
+ 
++  /* Return true if bitfields in RECORD_TYPE should be allocated
++     within their base type's bytes starting at the opposite end.  */
++  bool (* reverse_bitfield_layout_p) (tree record_type);
++
+   /* Set up target-specific built-in functions.  */
+   void (* init_builtins) (void);
+ 
+diff --git a/gcc/varasm.c b/gcc/varasm.c
+index 33307e5..d4ed0fc 100644
+--- a/gcc/varasm.c
++++ b/gcc/varasm.c
+@@ -3912,6 +3912,107 @@ array_size_for_constructor (tree val)
+   return tree_low_cst (i, 1);
+ }
+ 
++struct reorder_bitfields_key
++{
++  tree field;
++  tree value;
++};
++
++static int
++reorder_bitfields_compare (const void *x1, const void *x2)
++{
++  const struct reorder_bitfields_key *key1 = x1;
++  const struct reorder_bitfields_key *key2 = x2;
++  int pos1 = int_bit_position (key1->field);
++  int pos2 = int_bit_position (key2->field);
++
++  if (pos1 < pos2)
++  {
++    return -1;
++  }
++  else if (pos1 > pos2)
++  {
++    return 1;
++  }
++  else
++  {
++    /*
++     * No two fields should ever have the same bit_position, so
++     * something is horribly wrong.
++     */
++    abort ();
++  }
++}
++
++static void
++reorder_bitfields (tree *first_field, tree *first_value)
++{
++  struct reorder_bitfields_key *keys;
++  size_t field_count;
++  tree field;
++  tree value;
++  size_t i;
++
++  /*
++   * Find out how many fields are in this record, and allocate an array
++   * of keys to hold them all.
++   */
++  field_count = 0;
++  for (field = *first_field; field; field = TREE_CHAIN (field))
++  {
++    field_count++;
++  }
++  if (field_count < 2)
++  {
++    return;
++  }
++  keys = xmalloc (sizeof (struct reorder_bitfields_key) * field_count);
++
++  /*
++   * Make copies of the existing fields and values (using signed integer
++   * zeros for missing values) in the array of keys.
++   */
++  field = *first_field;
++  value = *first_value;
++  for (i = 0; i < field_count; i++)
++  {
++    keys[i].field = copy_node (field);
++    field = TREE_CHAIN (field);
++    if (value)
++    {
++      keys[i].value = copy_node (value);
++      TREE_PURPOSE (keys[i].value) = keys[i].field;
++      value = TREE_CHAIN (value);
++    }
++    else
++    {
++      keys[i].value = tree_cons (keys[i].field, ssize_int (0), 0);
++    }
++  }
++
++  /*
++   * Sort the array based on position of the fields in the record.
++   */
++  qsort (keys, field_count, sizeof (struct reorder_bitfields_key),
++         reorder_bitfields_compare);
++
++  /*
++   * Build new lists out of the sorted array.
++   */
++  for (i = 0; i < field_count - 1; i++)
++  {
++    TREE_CHAIN (keys[i].field) = keys[i+1].field;
++    TREE_CHAIN (keys[i].value) = keys[i+1].value;
++  }
++  *first_field = keys[0].field;
++  *first_value = keys[0].value;
++
++  /*
++   * Get rid of our array of keys and we're done.
++   */
++  free (keys);
++}
++
+ /* Subroutine of output_constant, used for CONSTRUCTORs (aggregate constants).
+    Generate at least SIZE bytes, padding if necessary.  */
+ 
+@@ -3928,12 +4029,29 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
+   /* Nonzero means BYTE contains part of a byte, to be output.  */
+   int byte_buffer_in_use = 0;
+   int byte = 0;
++  tree first_link = CONSTRUCTOR_ELTS (exp);
+ 
+   if (HOST_BITS_PER_WIDE_INT < BITS_PER_UNIT)
+     abort ();
+ 
+   if (TREE_CODE (type) == RECORD_TYPE)
++  {
++    if ((*targetm.reverse_bitfield_layout_p) (type))
++    {
++      /*
++       * If we're reversing bitfields, we have to reverse the order in
++       * which constructors containing bitfields are output.  The
++       * easiest way to do that is to reorder the constructor elements
++       * and fields to be in memory-order.
++       */
+     field = TYPE_FIELDS (type);
++      reorder_bitfields (&field, &first_link);
++    }
++    else
++    {
++      field = TYPE_FIELDS (type);
++    }
++  }
+ 
+   if (TREE_CODE (type) == ARRAY_TYPE
+       && TYPE_DOMAIN (type) != 0)
+@@ -3948,7 +4066,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
+      There is always a maximum of one element in the chain LINK for unions
+      (even if the initializer in a source program incorrectly contains
+      more one).  */
+-  for (link = CONSTRUCTOR_ELTS (exp);
++  for (link = first_link;
+        link;
+        link = TREE_CHAIN (link),
+        field = field ? TREE_CHAIN (field) : 0)
diff --git a/toolchain/gcc/3.4.6/901-nios2-ctor_dtor.patch b/toolchain/gcc/3.4.6/901-nios2-ctor_dtor.patch
index 87145ad5e..e69de29bb 100644
--- a/toolchain/gcc/3.4.6/901-nios2-ctor_dtor.patch
+++ b/toolchain/gcc/3.4.6/901-nios2-ctor_dtor.patch
@@ -1,52 +0,0 @@
-Index: gcc/gcc/config/nios2/nios2.h
-===================================================================
---- gcc/gcc/config/nios2/nios2.h	(revision 195)
-+++ gcc/gcc/config/nios2/nios2.h	(revision 196)
-@@ -88,8 +88,6 @@
-       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 }				\
- }
- 
-@@ -140,12 +138,12 @@
- #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} \
-+ crti%O%s crtbegin%O%s \
- "
- 
- #undef ENDFILE_SPEC 
- #define ENDFILE_SPEC \
-- "%{mctors-in-init: crtend%O%s crtn%O%s}"
-+ " crtend%O%s crtn%O%s"
- 
- 
- /***********************
-Index: gcc/gcc/config/nios2/t-nios2
-===================================================================
---- gcc/gcc/config/nios2/t-nios2	(revision 195)
-+++ gcc/gcc/config/nios2/t-nios2	(revision 196)
-@@ -36,18 +36,8 @@
- 	echo ''          >  ${DPBIT}
- 	cat $(srcdir)/config/fp-bit.c >> ${DPBIT}
- 
--EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o 
-+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.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
- ##
diff --git a/toolchain/gcc/3.4.6/nios2-config-fix.patch.conditional b/toolchain/gcc/3.4.6/nios2-config-fix.patch.conditional
index 9f1c37868..e69de29bb 100644
--- a/toolchain/gcc/3.4.6/nios2-config-fix.patch.conditional
+++ b/toolchain/gcc/3.4.6/nios2-config-fix.patch.conditional
@@ -1,19 +0,0 @@
---- gcc-3.4.6/gcc/config/t-linux-uclibc	2007-11-07 14:50:34.000000000 +0100
-+++ /dev/null	2007-11-02 12:35:37.750656579 +0100
-@@ -1,5 +0,0 @@
--# 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.6/gcc/config.gcc.orig	2007-11-07 14:50:34.000000000 +0100
-+++ gcc-3.4.6/gcc/config.gcc	2007-11-07 15:32:31.000000000 +0100
-@@ -2334,7 +2334,7 @@
- # 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"
-+*-linux-uclibc*) tm_defines="${tm_defines} USE_UCLIBC"
- esac
- 
- # Support for --with-cpu and related options (and a few unrelated options,
diff --git a/toolchain/gcc/gcc-uclibc-3.x.mk b/toolchain/gcc/gcc-uclibc-3.x.mk
index c6c622a0c..e2210d06c 100644
--- a/toolchain/gcc/gcc-uclibc-3.x.mk
+++ b/toolchain/gcc/gcc-uclibc-3.x.mk
@@ -167,9 +167,6 @@ endif
 	#ifeq ("$(strip $(ARCH))","i386")
 	#toolchain/patch-kernel.sh $(GCC_DIR) toolchain/gcc i386-gcc-soft-float.patch
 	#endif
-endif
-ifeq ("$(strip $(ARCH))","nios2")
-	toolchain/patch-kernel.sh $(GCC_DIR) toolchain/gcc/$(GCC_VERSION) nios2-config-fix.patch.conditional
 endif
 	touch $@
 
-- 
cgit v1.2.3