--- gcc-3.4.3/gcc/Makefile.in
+++ gcc-3.4.3-nios2/gcc/Makefile.in
@@ -3085,7 +3085,7 @@ install-mkheaders: stmp-int-hdrs $(STMP_
 	  $(INSTALL_DATA) $(srcdir)/README-fixinc \
 	    $(DESTDIR)$(itoolsdatadir)/include/README ; \
 	  $(INSTALL_SCRIPT) fixinc.sh $(DESTDIR)$(itoolsdir)/fixinc.sh ; \
-	  $(INSTALL_PROGRAM) fixinc/fixincl $(DESTDIR)$(itoolsdir)/fixincl ; \
+	  $(INSTALL_PROGRAM) fixinc/fixincl$(build_exeext) $(DESTDIR)$(itoolsdir)/fixincl$(build_exeext) ; \
 	  $(INSTALL_DATA) $(srcdir)/gsyslimits.h \
 	    $(DESTDIR)$(itoolsdatadir)/gsyslimits.h ; \
 	else :; fi
--- gcc-3.4.3/gcc/combine.c
+++ gcc-3.4.3-nios2/gcc/combine.c
@@ -4380,6 +4380,14 @@ combine_simplify_rtx (rtx x, enum machin
 					 mode);
 	    }
 
+#ifndef __nios2__
+/* This screws up Nios II in this test case:
+
+if (x & 1)
+  return 2;
+else
+  return 3;
+*/
 	  else if (STORE_FLAG_VALUE == 1
 		   && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
 		   && op1 == const0_rtx
@@ -4391,6 +4399,7 @@ combine_simplify_rtx (rtx x, enum machin
 				 gen_lowpart_for_combine (mode, op0),
 				 const1_rtx);
 	    }
+#endif
 
 	  else if (STORE_FLAG_VALUE == 1
 		   && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
--- gcc-3.4.3/gcc/config/nios2/crti.asm
+++ gcc-3.4.3-nios2/gcc/config/nios2/crti.asm
@@ -0,0 +1,88 @@
+/*
+  Copyright (C) 2003 
+ by Jonah Graham (jgraham@altera.com)
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs without any restriction coming from the use of this
+file.  (The General Public License restrictions do apply in other
+respects; for example, they cover modification of the file, and
+distribution when not linked into another program.)
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.
+
+
+This file just make a stack frame for the contents of the .fini and
+.init sections.  Users may put any desired instructions in those
+sections.
+
+
+While technically any code can be put in the init and fini sections
+most stuff will not work other than stuff which obeys the call frame
+and ABI. All the call-preserved registers are saved, the call clobbered
+registers should have been saved by the code calling init and fini.
+
+See crtstuff.c for an example of code that inserts itself in the 
+init and fini sections. 
+
+See crt0.s for the code that calls init and fini.
+*/
+
+	.file	"crti.asm"
+
+	.section	".init"
+	.align 2
+	.global	_init
+_init:
+	addi	sp, sp, -48
+	stw	ra, 44(sp)
+	stw	r23, 40(sp)
+	stw	r22, 36(sp)
+	stw	r21, 32(sp)
+	stw	r20, 28(sp)
+	stw	r19, 24(sp)
+	stw	r18, 20(sp)
+	stw	r17, 16(sp)
+	stw	r16, 12(sp)
+	stw	fp, 8(sp)
+	mov	fp, sp
+	
+	
+	.section	".fini"
+	.align	2
+	.global	_fini
+_fini:
+	addi	sp, sp, -48
+	stw	ra, 44(sp)
+	stw	r23, 40(sp)
+	stw	r22, 36(sp)
+	stw	r21, 32(sp)
+	stw	r20, 28(sp)
+	stw	r19, 24(sp)
+	stw	r18, 20(sp)
+	stw	r17, 16(sp)
+	stw	r16, 12(sp)
+	stw	fp, 8(sp)
+	mov	fp, sp
+	
+
--- gcc-3.4.3/gcc/config/nios2/crtn.asm
+++ gcc-3.4.3-nios2/gcc/config/nios2/crtn.asm
@@ -0,0 +1,70 @@
+/*
+  Copyright (C) 2003 
+ by Jonah Graham (jgraham@altera.com)
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs without any restriction coming from the use of this
+file.  (The General Public License restrictions do apply in other
+respects; for example, they cover modification of the file, and
+distribution when not linked into another program.)
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+   As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.
+
+
+This file just makes sure that the .fini and .init sections do in
+fact return.  Users may put any desired instructions in those sections.
+This file is the last thing linked into any executable.
+*/	
+	.file	"crtn.asm"
+
+
+
+	.section	".init"
+	ldw	ra, 44(sp)
+	ldw	r23, 40(sp)
+	ldw	r22, 36(sp)
+	ldw	r21, 32(sp)
+	ldw	r20, 28(sp)
+	ldw	r19, 24(sp)
+	ldw	r18, 20(sp)
+	ldw	r17, 16(sp)
+	ldw	r16, 12(sp)
+	ldw	fp, 8(sp)
+	addi	sp, sp, -48
+	ret
+	
+	.section	".fini"
+	ldw	ra, 44(sp)
+	ldw	r23, 40(sp)
+	ldw	r22, 36(sp)
+	ldw	r21, 32(sp)
+	ldw	r20, 28(sp)
+	ldw	r19, 24(sp)
+	ldw	r18, 20(sp)
+	ldw	r17, 16(sp)
+	ldw	r16, 12(sp)
+	ldw	fp, 8(sp)
+	addi	sp, sp, -48
+	ret
+	
--- gcc-3.4.3/gcc/config/nios2/lib2-divmod-hi.c
+++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divmod-hi.c
@@ -0,0 +1,123 @@
+
+/* We include auto-host.h here to get HAVE_GAS_HIDDEN.  This is
+   supposedly valid even though this is a "target" file.  */
+#include "auto-host.h"
+
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+
+
+/* Don't use `fancy_abort' here even if config.h says to use it.  */
+#ifdef abort
+#undef abort
+#endif
+
+
+#ifdef HAVE_GAS_HIDDEN
+#define ATTRIBUTE_HIDDEN  __attribute__ ((__visibility__ ("hidden")))
+#else
+#define ATTRIBUTE_HIDDEN
+#endif
+
+#include "libgcc2.h"
+
+extern HItype __modhi3 (HItype, HItype);
+extern HItype __divhi3 (HItype, HItype);
+extern HItype __umodhi3 (HItype, HItype);
+extern HItype __udivhi3 (HItype, HItype);
+
+static UHItype udivmodhi4(UHItype, UHItype, word_type);
+
+static UHItype
+udivmodhi4(UHItype num, UHItype den, word_type modwanted)
+{
+  UHItype bit = 1;
+  UHItype res = 0;
+
+  while (den < num && bit && !(den & (1L<<15)))
+    {
+      den <<=1;
+      bit <<=1;
+    }
+  while (bit)
+    {
+      if (num >= den)
+	{
+	  num -= den;
+	  res |= bit;
+	}
+      bit >>=1;
+      den >>=1;
+    }
+  if (modwanted) return num;
+  return res;
+}
+
+
+HItype
+__divhi3 (HItype a, HItype b)
+{
+  word_type neg = 0;
+  HItype res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = !neg;
+    }
+
+  if (b < 0)
+    {
+      b = -b;
+      neg = !neg;
+    }
+
+  res = udivmodhi4 (a, b, 0);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+
+HItype
+__modhi3 (HItype a, HItype b)
+{
+  word_type neg = 0;
+  HItype res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = 1;
+    }
+
+  if (b < 0)
+    b = -b;
+
+  res = udivmodhi4 (a, b, 1);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+
+HItype
+__udivhi3 (HItype a, HItype b)
+{
+  return udivmodhi4 (a, b, 0);
+}
+
+
+HItype
+__umodhi3 (HItype a, HItype b)
+{
+  return udivmodhi4 (a, b, 1);
+}
+
--- gcc-3.4.3/gcc/config/nios2/lib2-divmod.c
+++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divmod.c
@@ -0,0 +1,126 @@
+
+/* We include auto-host.h here to get HAVE_GAS_HIDDEN.  This is
+   supposedly valid even though this is a "target" file.  */
+#include "auto-host.h"
+
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+
+
+/* Don't use `fancy_abort' here even if config.h says to use it.  */
+#ifdef abort
+#undef abort
+#endif
+
+
+#ifdef HAVE_GAS_HIDDEN
+#define ATTRIBUTE_HIDDEN  __attribute__ ((__visibility__ ("hidden")))
+#else
+#define ATTRIBUTE_HIDDEN
+#endif
+
+#include "libgcc2.h"
+
+extern SItype __modsi3 (SItype, SItype);
+extern SItype __divsi3 (SItype, SItype);
+extern SItype __umodsi3 (SItype, SItype);
+extern SItype __udivsi3 (SItype, SItype);
+
+static USItype udivmodsi4(USItype, USItype, word_type);
+
+/* 16-bit SI divide and modulo as used in NIOS */
+
+
+static USItype
+udivmodsi4(USItype num, USItype den, word_type modwanted)
+{
+  USItype bit = 1;
+  USItype res = 0;
+
+  while (den < num && bit && !(den & (1L<<31)))
+    {
+      den <<=1;
+      bit <<=1;
+    }
+  while (bit)
+    {
+      if (num >= den)
+	{
+	  num -= den;
+	  res |= bit;
+	}
+      bit >>=1;
+      den >>=1;
+    }
+  if (modwanted) return num;
+  return res;
+}
+
+
+SItype
+__divsi3 (SItype a, SItype b)
+{
+  word_type neg = 0;
+  SItype res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = !neg;
+    }
+
+  if (b < 0)
+    {
+      b = -b;
+      neg = !neg;
+    }
+
+  res = udivmodsi4 (a, b, 0);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+
+SItype
+__modsi3 (SItype a, SItype b)
+{
+  word_type neg = 0;
+  SItype res;
+
+  if (a < 0)
+    {
+      a = -a;
+      neg = 1;
+    }
+
+  if (b < 0)
+    b = -b;
+
+  res = udivmodsi4 (a, b, 1);
+
+  if (neg)
+    res = -res;
+
+  return res;
+}
+
+
+SItype
+__udivsi3 (SItype a, SItype b)
+{
+  return udivmodsi4 (a, b, 0);
+}
+
+
+SItype
+__umodsi3 (SItype a, SItype b)
+{
+  return udivmodsi4 (a, b, 1);
+}
+
--- gcc-3.4.3/gcc/config/nios2/lib2-divtable.c
+++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divtable.c
@@ -0,0 +1,46 @@
+
+/* We include auto-host.h here to get HAVE_GAS_HIDDEN.  This is
+   supposedly valid even though this is a "target" file.  */
+#include "auto-host.h"
+
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+
+
+/* Don't use `fancy_abort' here even if config.h says to use it.  */
+#ifdef abort
+#undef abort
+#endif
+
+
+#ifdef HAVE_GAS_HIDDEN
+#define ATTRIBUTE_HIDDEN  __attribute__ ((__visibility__ ("hidden")))
+#else
+#define ATTRIBUTE_HIDDEN
+#endif
+
+#include "libgcc2.h"
+
+UQItype __divsi3_table[] =
+{
+  0, 0/1, 0/2, 0/3, 0/4, 0/5, 0/6, 0/7, 0/8, 0/9, 0/10, 0/11, 0/12, 0/13, 0/14, 0/15,
+  0, 1/1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10, 1/11, 1/12, 1/13, 1/14, 1/15,
+  0, 2/1, 2/2, 2/3, 2/4, 2/5, 2/6, 2/7, 2/8, 2/9, 2/10, 2/11, 2/12, 2/13, 2/14, 2/15,
+  0, 3/1, 3/2, 3/3, 3/4, 3/5, 3/6, 3/7, 3/8, 3/9, 3/10, 3/11, 3/12, 3/13, 3/14, 3/15,
+  0, 4/1, 4/2, 4/3, 4/4, 4/5, 4/6, 4/7, 4/8, 4/9, 4/10, 4/11, 4/12, 4/13, 4/14, 4/15,
+  0, 5/1, 5/2, 5/3, 5/4, 5/5, 5/6, 5/7, 5/8, 5/9, 5/10, 5/11, 5/12, 5/13, 5/14, 5/15,
+  0, 6/1, 6/2, 6/3, 6/4, 6/5, 6/6, 6/7, 6/8, 6/9, 6/10, 6/11, 6/12, 6/13, 6/14, 6/15,
+  0, 7/1, 7/2, 7/3, 7/4, 7/5, 7/6, 7/7, 7/8, 7/9, 7/10, 7/11, 7/12, 7/13, 7/14, 7/15,
+  0, 8/1, 8/2, 8/3, 8/4, 8/5, 8/6, 8/7, 8/8, 8/9, 8/10, 8/11, 8/12, 8/13, 8/14, 8/15,
+  0, 9/1, 9/2, 9/3, 9/4, 9/5, 9/6, 9/7, 9/8, 9/9, 9/10, 9/11, 9/12, 9/13, 9/14, 9/15,
+  0, 10/1, 10/2, 10/3, 10/4, 10/5, 10/6, 10/7, 10/8, 10/9, 10/10, 10/11, 10/12, 10/13, 10/14, 10/15,
+  0, 11/1, 11/2, 11/3, 11/4, 11/5, 11/6, 11/7, 11/8, 11/9, 11/10, 11/11, 11/12, 11/13, 11/14, 11/15,
+  0, 12/1, 12/2, 12/3, 12/4, 12/5, 12/6, 12/7, 12/8, 12/9, 12/10, 12/11, 12/12, 12/13, 12/14, 12/15,
+  0, 13/1, 13/2, 13/3, 13/4, 13/5, 13/6, 13/7, 13/8, 13/9, 13/10, 13/11, 13/12, 13/13, 13/14, 13/15,
+  0, 14/1, 14/2, 14/3, 14/4, 14/5, 14/6, 14/7, 14/8, 14/9, 14/10, 14/11, 14/12, 14/13, 14/14, 14/15,
+  0, 15/1, 15/2, 15/3, 15/4, 15/5, 15/6, 15/7, 15/8, 15/9, 15/10, 15/11, 15/12, 15/13, 15/14, 15/15,
+};
+
--- gcc-3.4.3/gcc/config/nios2/lib2-mul.c
+++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-mul.c
@@ -0,0 +1,103 @@
+/* while we are debugging (ie compile outside of gcc build) 
+   disable gcc specific headers */
+#ifndef DEBUG_MULSI3
+
+
+/* We include auto-host.h here to get HAVE_GAS_HIDDEN.  This is
+   supposedly valid even though this is a "target" file.  */
+#include "auto-host.h"
+
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+
+
+/* Don't use `fancy_abort' here even if config.h says to use it.  */
+#ifdef abort
+#undef abort
+#endif
+
+
+#ifdef HAVE_GAS_HIDDEN
+#define ATTRIBUTE_HIDDEN  __attribute__ ((__visibility__ ("hidden")))
+#else
+#define ATTRIBUTE_HIDDEN
+#endif
+
+#include "libgcc2.h"
+
+#else
+#define SItype int
+#define USItype unsigned int
+#endif
+
+
+extern SItype __mulsi3 (SItype, SItype);
+
+SItype
+__mulsi3 (SItype a, SItype b)
+{
+  SItype res = 0;
+  USItype cnt = a;
+  
+  while (cnt)
+    {
+      if (cnt & 1)
+        {
+	  res += b;	  
+	}
+      b <<= 1;
+      cnt >>= 1;
+    }
+    
+  return res;
+}
+/*
+TODO: Choose best alternative implementation.
+
+SItype
+__divsi3 (SItype a, SItype b)
+{
+  SItype res = 0;
+  USItype cnt = 0;
+  
+  while (cnt < 32)
+    {
+      if (a & (1L << cnt))
+        {
+	  res += b;	  
+	}
+      b <<= 1;
+      cnt++;
+    }
+    
+  return res;
+}
+*/
+
+
+#ifdef DEBUG_MULSI3
+
+int
+main ()
+{
+  int i, j;
+  int error = 0;
+  
+  for (i = -1000; i < 1000; i++)
+    for (j = -1000; j < 1000; j++)
+      {
+	int expect = i * j;
+	int actual = A__divsi3 (i, j);
+	if (expect != actual)
+	  {
+	    printf ("error: %d * %d = %d not %d\n", i, j, expect, actual);
+	    error = 1;
+	  }
+      }
+
+  return error;
+}
+#endif
--- gcc-3.4.3/gcc/config/nios2/nios2-dp-bit.c
+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-dp-bit.c
@@ -0,0 +1,1652 @@
+
+/* This is a software floating point library which can be used
+   for targets without hardware floating point. 
+   Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004
+   Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs without any restriction coming from the use of this
+file.  (The General Public License restrictions do apply in other
+respects; for example, they cover modification of the file, and
+distribution when not linked into another program.)
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with other files,
+   some of which are compiled with GCC, to produce an executable,
+   this library does not by itself cause the resulting executable
+   to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+/* This implements IEEE 754 format arithmetic, but does not provide a
+   mechanism for setting the rounding mode, or for generating or handling
+   exceptions.
+
+   The original code by Steve Chamberlain, hacked by Mark Eichin and Jim
+   Wilson, all of Cygnus Support.  */
+
+/* The intended way to use this file is to make two copies, add `#define FLOAT'
+   to one copy, then compile both copies and add them to libgcc.a.  */
+
+#include "tconfig.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "config/fp-bit.h"
+
+/* The following macros can be defined to change the behavior of this file:
+   FLOAT: Implement a `float', aka SFmode, fp library.  If this is not
+     defined, then this file implements a `double', aka DFmode, fp library.
+   FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e.
+     don't include float->double conversion which requires the double library.
+     This is useful only for machines which can't support doubles, e.g. some
+     8-bit processors.
+   CMPtype: Specify the type that floating point compares should return.
+     This defaults to SItype, aka int.
+   US_SOFTWARE_GOFAST: This makes all entry points use the same names as the
+     US Software goFast library.
+   _DEBUG_BITFLOAT: This makes debugging the code a little easier, by adding
+     two integers to the FLO_union_type.
+   NO_DENORMALS: Disable handling of denormals.
+   NO_NANS: Disable nan and infinity handling
+   SMALL_MACHINE: Useful when operations on QIs and HIs are faster
+     than on an SI */
+
+/* We don't currently support extended floats (long doubles) on machines
+   without hardware to deal with them.
+
+   These stubs are just to keep the linker from complaining about unresolved
+   references which can be pulled in from libio & libstdc++, even if the
+   user isn't using long doubles.  However, they may generate an unresolved
+   external to abort if abort is not used by the function, and the stubs
+   are referenced from within libc, since libgcc goes before and after the
+   system library.  */
+
+#ifdef DECLARE_LIBRARY_RENAMES
+  DECLARE_LIBRARY_RENAMES
+#endif
+
+#ifdef EXTENDED_FLOAT_STUBS
+extern void abort (void);
+void __extendsfxf2 (void) { abort(); }
+void __extenddfxf2 (void) { abort(); }
+void __truncxfdf2 (void) { abort(); }
+void __truncxfsf2 (void) { abort(); }
+void __fixxfsi (void) { abort(); }
+void __floatsixf (void) { abort(); }
+void __addxf3 (void) { abort(); }
+void __subxf3 (void) { abort(); }
+void __mulxf3 (void) { abort(); }
+void __divxf3 (void) { abort(); }
+void __negxf2 (void) { abort(); }
+void __eqxf2 (void) { abort(); }
+void __nexf2 (void) { abort(); }
+void __gtxf2 (void) { abort(); }
+void __gexf2 (void) { abort(); }
+void __lexf2 (void) { abort(); }
+void __ltxf2 (void) { abort(); }
+
+void __extendsftf2 (void) { abort(); }
+void __extenddftf2 (void) { abort(); }
+void __trunctfdf2 (void) { abort(); }
+void __trunctfsf2 (void) { abort(); }
+void __fixtfsi (void) { abort(); }
+void __floatsitf (void) { abort(); }
+void __addtf3 (void) { abort(); }
+void __subtf3 (void) { abort(); }
+void __multf3 (void) { abort(); }
+void __divtf3 (void) { abort(); }
+void __negtf2 (void) { abort(); }
+void __eqtf2 (void) { abort(); }
+void __netf2 (void) { abort(); }
+void __gttf2 (void) { abort(); }
+void __getf2 (void) { abort(); }
+void __letf2 (void) { abort(); }
+void __lttf2 (void) { abort(); }
+#else	/* !EXTENDED_FLOAT_STUBS, rest of file */
+
+/* IEEE "special" number predicates */
+
+#ifdef NO_NANS
+
+#define nan() 0
+#define isnan(x) 0
+#define isinf(x) 0
+#else
+
+#if   defined L_thenan_sf
+const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
+#elif defined L_thenan_df
+const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} };
+#elif defined L_thenan_tf
+const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
+#elif defined TFLOAT
+extern const fp_number_type __thenan_tf;
+#elif defined FLOAT
+extern const fp_number_type __thenan_sf;
+#else
+extern const fp_number_type __thenan_df;
+#endif
+
+INLINE
+static fp_number_type *
+nan (void)
+{
+  /* Discard the const qualifier...  */
+#ifdef TFLOAT
+  return (fp_number_type *) (& __thenan_tf);
+#elif defined FLOAT  
+  return (fp_number_type *) (& __thenan_sf);
+#else
+  return (fp_number_type *) (& __thenan_df);
+#endif
+}
+
+INLINE
+static int
+isnan ( fp_number_type *  x)
+{
+  return x->class == CLASS_SNAN || x->class == CLASS_QNAN;
+}
+
+INLINE
+static int
+isinf ( fp_number_type *  x)
+{
+  return x->class == CLASS_INFINITY;
+}
+
+#endif /* NO_NANS */
+
+INLINE
+static int
+iszero ( fp_number_type *  x)
+{
+  return x->class == CLASS_ZERO;
+}
+
+INLINE 
+static void
+flip_sign ( fp_number_type *  x)
+{
+  x->sign = !x->sign;
+}
+
+extern FLO_type pack_d ( fp_number_type * );
+
+#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
+FLO_type
+pack_d ( fp_number_type *  src)
+{
+  FLO_union_type dst;
+  fractype fraction = src->fraction.ll;	/* wasn't unsigned before? */
+  int sign = src->sign;
+  int exp = 0;
+
+  if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src)))
+    {
+      /* We can't represent these values accurately.  By using the
+	 largest possible magnitude, we guarantee that the conversion
+	 of infinity is at least as big as any finite number.  */
+      exp = EXPMAX;
+      fraction = ((fractype) 1 << FRACBITS) - 1;
+    }
+  else if (isnan (src))
+    {
+      exp = EXPMAX;
+      if (src->class == CLASS_QNAN || 1)
+	{
+#ifdef QUIET_NAN_NEGATED
+	  fraction |= QUIET_NAN - 1;
+#else
+	  fraction |= QUIET_NAN;
+#endif
+	}
+    }
+  else if (isinf (src))
+    {
+      exp = EXPMAX;
+      fraction = 0;
+    }
+  else if (iszero (src))
+    {
+      exp = 0;
+      fraction = 0;
+    }
+  else if (fraction == 0)
+    {
+      exp = 0;
+    }
+  else
+    {
+      if (src->normal_exp < NORMAL_EXPMIN)
+	{
+#ifdef NO_DENORMALS
+	  /* Go straight to a zero representation if denormals are not
+ 	     supported.  The denormal handling would be harmless but
+ 	     isn't unnecessary.  */
+	  exp = 0;
+	  fraction = 0;
+#else /* NO_DENORMALS */
+	  /* This number's exponent is too low to fit into the bits
+	     available in the number, so we'll store 0 in the exponent and
+	     shift the fraction to the right to make up for it.  */
+
+	  int shift = NORMAL_EXPMIN - src->normal_exp;
+
+	  exp = 0;
+
+	  if (shift > FRAC_NBITS - NGARDS)
+	    {
+	      /* No point shifting, since it's more that 64 out.  */
+	      fraction = 0;
+	    }
+	  else
+	    {
+	      int lowbit = (fraction & (((fractype)1 << shift) - 1)) ? 1 : 0;
+	      fraction = (fraction >> shift) | lowbit;
+	    }
+	  if ((fraction & GARDMASK) == GARDMSB)
+	    {
+	      if ((fraction & (1 << NGARDS)))
+		fraction += GARDROUND + 1;
+	    }
+	  else
+	    {
+	      /* Add to the guards to round up.  */
+	      fraction += GARDROUND;
+	    }
+	  /* Perhaps the rounding means we now need to change the
+             exponent, because the fraction is no longer denormal.  */
+	  if (fraction >= IMPLICIT_1)
+	    {
+	      exp += 1;
+	    }
+	  fraction >>= NGARDS;
+#endif /* NO_DENORMALS */
+	}
+      else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
+	       && src->normal_exp > EXPBIAS)
+	{
+	  exp = EXPMAX;
+	  fraction = 0;
+	}
+      else
+	{
+	  exp = src->normal_exp + EXPBIAS;
+	  if (!ROUND_TOWARDS_ZERO)
+	    {
+	      /* IF the gard bits are the all zero, but the first, then we're
+		 half way between two numbers, choose the one which makes the
+		 lsb of the answer 0.  */
+	      if ((fraction & GARDMASK) == GARDMSB)
+		{
+		  if (fraction & (1 << NGARDS))
+		    fraction += GARDROUND + 1;
+		}
+	      else
+		{
+		  /* Add a one to the guards to round up */
+		  fraction += GARDROUND;
+		}
+	      if (fraction >= IMPLICIT_2)
+		{
+		  fraction >>= 1;
+		  exp += 1;
+		}
+	    }
+	  fraction >>= NGARDS;
+
+	  if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX)
+	    {
+	      /* Saturate on overflow.  */
+	      exp = EXPMAX;
+	      fraction = ((fractype) 1 << FRACBITS) - 1;
+	    }
+	}
+    }
+
+  /* We previously used bitfields to store the number, but this doesn't
+     handle little/big endian systems conveniently, so use shifts and
+     masks */
+#ifdef FLOAT_BIT_ORDER_MISMATCH
+  dst.bits.fraction = fraction;
+  dst.bits.exp = exp;
+  dst.bits.sign = sign;
+#else
+# if defined TFLOAT && defined HALFFRACBITS
+ {
+   halffractype high, low, unity;
+   int lowsign, lowexp;
+
+   unity = (halffractype) 1 << HALFFRACBITS;
+
+   /* Set HIGH to the high double's significand, masking out the implicit 1.
+      Set LOW to the low double's full significand.  */
+   high = (fraction >> (FRACBITS - HALFFRACBITS)) & (unity - 1);
+   low = fraction & (unity * 2 - 1);
+
+   /* Get the initial sign and exponent of the low double.  */
+   lowexp = exp - HALFFRACBITS - 1;
+   lowsign = sign;
+
+   /* HIGH should be rounded like a normal double, making |LOW| <=
+      0.5 ULP of HIGH.  Assume round-to-nearest.  */
+   if (exp < EXPMAX)
+     if (low > unity || (low == unity && (high & 1) == 1))
+       {
+	 /* Round HIGH up and adjust LOW to match.  */
+	 high++;
+	 if (high == unity)
+	   {
+	     /* May make it infinite, but that's OK.  */
+	     high = 0;
+	     exp++;
+	   }
+	 low = unity * 2 - low;
+	 lowsign ^= 1;
+       }
+
+   high |= (halffractype) exp << HALFFRACBITS;
+   high |= (halffractype) sign << (HALFFRACBITS + EXPBITS);
+
+   if (exp == EXPMAX || exp == 0 || low == 0)
+     low = 0;
+   else
+     {
+       while (lowexp > 0 && low < unity)
+	 {
+	   low <<= 1;
+	   lowexp--;
+	 }
+
+       if (lowexp <= 0)
+	 {
+	   halffractype roundmsb, round;
+	   int shift;
+
+	   shift = 1 - lowexp;
+	   roundmsb = (1 << (shift - 1));
+	   round = low & ((roundmsb << 1) - 1);
+
+	   low >>= shift;
+	   lowexp = 0;
+
+	   if (round > roundmsb || (round == roundmsb && (low & 1) == 1))
+	     {
+	       low++;
+	       if (low == unity)
+		 /* LOW rounds up to the smallest normal number.  */
+		 lowexp++;
+	     }
+	 }
+
+       low &= unity - 1;
+       low |= (halffractype) lowexp << HALFFRACBITS;
+       low |= (halffractype) lowsign << (HALFFRACBITS + EXPBITS);
+     }
+   dst.value_raw = ((fractype) high << HALFSHIFT) | low;
+ }
+# else
+  dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1);
+  dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS;
+  dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS);
+# endif
+#endif
+
+#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
+#ifdef TFLOAT
+  {
+    qrtrfractype tmp1 = dst.words[0];
+    qrtrfractype tmp2 = dst.words[1];
+    dst.words[0] = dst.words[3];
+    dst.words[1] = dst.words[2];
+    dst.words[2] = tmp2;
+    dst.words[3] = tmp1;
+  }
+#else
+  {
+    halffractype tmp = dst.words[0];
+    dst.words[0] = dst.words[1];
+    dst.words[1] = tmp;
+  }
+#endif
+#endif
+
+  return dst.value;
+}
+#endif
+
+#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf)
+void
+unpack_d (FLO_union_type * src, fp_number_type * dst)
+{
+  /* We previously used bitfields to store the number, but this doesn't
+     handle little/big endian systems conveniently, so use shifts and
+     masks */
+  fractype fraction;
+  int exp;
+  int sign;
+
+#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
+  FLO_union_type swapped;
+
+#ifdef TFLOAT
+  swapped.words[0] = src->words[3];
+  swapped.words[1] = src->words[2];
+  swapped.words[2] = src->words[1];
+  swapped.words[3] = src->words[0];
+#else
+  swapped.words[0] = src->words[1];
+  swapped.words[1] = src->words[0];
+#endif
+  src = &swapped;
+#endif
+  
+#ifdef FLOAT_BIT_ORDER_MISMATCH
+  fraction = src->bits.fraction;
+  exp = src->bits.exp;
+  sign = src->bits.sign;
+#else
+# if defined TFLOAT && defined HALFFRACBITS
+ {
+   halffractype high, low;
+   
+   high = src->value_raw >> HALFSHIFT;
+   low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1);
+
+   fraction = high & ((((fractype)1) << HALFFRACBITS) - 1);
+   fraction <<= FRACBITS - HALFFRACBITS;
+   exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
+   sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1;
+
+   if (exp != EXPMAX && exp != 0 && low != 0)
+     {
+       int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
+       int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1;
+       int shift;
+       fractype xlow;
+
+       xlow = low & ((((fractype)1) << HALFFRACBITS) - 1);
+       if (lowexp)
+	 xlow |= (((halffractype)1) << HALFFRACBITS);
+       else
+	 lowexp = 1;
+       shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp);
+       if (shift > 0)
+	 xlow <<= shift;
+       else if (shift < 0)
+	 xlow >>= -shift;
+       if (sign == lowsign)
+	 fraction += xlow;
+       else if (fraction >= xlow)
+	 fraction -= xlow;
+       else
+	 {
+	   /* The high part is a power of two but the full number is lower.
+	      This code will leave the implicit 1 in FRACTION, but we'd
+	      have added that below anyway.  */
+	   fraction = (((fractype) 1 << FRACBITS) - xlow) << 1;
+	   exp--;
+	 }
+     }
+ }
+# else
+  fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1);
+  exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1);
+  sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1;
+# endif
+#endif
+
+  dst->sign = sign;
+  if (exp == 0)
+    {
+      /* Hmm.  Looks like 0 */
+      if (fraction == 0
+#ifdef NO_DENORMALS
+	  || 1
+#endif
+	  )
+	{
+	  /* tastes like zero */
+	  dst->class = CLASS_ZERO;
+	}
+      else
+	{
+	  /* Zero exponent with nonzero fraction - it's denormalized,
+	     so there isn't a leading implicit one - we'll shift it so
+	     it gets one.  */
+	  dst->normal_exp = exp - EXPBIAS + 1;
+	  fraction <<= NGARDS;
+
+	  dst->class = CLASS_NUMBER;
+#if 1
+	  while (fraction < IMPLICIT_1)
+	    {
+	      fraction <<= 1;
+	      dst->normal_exp--;
+	    }
+#endif
+	  dst->fraction.ll = fraction;
+	}
+    }
+  else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX)
+    {
+      /* Huge exponent*/
+      if (fraction == 0)
+	{
+	  /* Attached to a zero fraction - means infinity */
+	  dst->class = CLASS_INFINITY;
+	}
+      else
+	{
+	  /* Nonzero fraction, means nan */
+#ifdef QUIET_NAN_NEGATED
+	  if ((fraction & QUIET_NAN) == 0)
+#else
+	  if (fraction & QUIET_NAN)
+#endif
+	    {
+	      dst->class = CLASS_QNAN;
+	    }
+	  else
+	    {
+	      dst->class = CLASS_SNAN;
+	    }
+	  /* Keep the fraction part as the nan number */
+	  dst->fraction.ll = fraction;
+	}
+    }
+  else
+    {
+      /* Nothing strange about this number */
+      dst->normal_exp = exp - EXPBIAS;
+      dst->class = CLASS_NUMBER;
+      dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1;
+    }
+}
+#endif /* L_unpack_df || L_unpack_sf */
+
+#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
+static fp_number_type *
+_fpadd_parts (fp_number_type * a,
+	      fp_number_type * b,
+	      fp_number_type * tmp)
+{
+  intfrac tfraction;
+
+  /* Put commonly used fields in local variables.  */
+  int a_normal_exp;
+  int b_normal_exp;
+  fractype a_fraction;
+  fractype b_fraction;
+
+  if (isnan (a))
+    {
+      return a;
+    }
+  if (isnan (b))
+    {
+      return b;
+    }
+  if (isinf (a))
+    {
+      /* Adding infinities with opposite signs yields a NaN.  */
+      if (isinf (b) && a->sign != b->sign)
+	return nan ();
+      return a;
+    }
+  if (isinf (b))
+    {
+      return b;
+    }
+  if (iszero (b))
+    {
+      if (iszero (a))
+	{
+	  *tmp = *a;
+	  tmp->sign = a->sign & b->sign;
+	  return tmp;
+	}
+      return a;
+    }
+  if (iszero (a))
+    {
+      return b;
+    }
+
+  /* Got two numbers. shift the smaller and increment the exponent till
+     they're the same */
+  {
+    int diff;
+
+    a_normal_exp = a->normal_exp;
+    b_normal_exp = b->normal_exp;
+    a_fraction = a->fraction.ll;
+    b_fraction = b->fraction.ll;
+
+    diff = a_normal_exp - b_normal_exp;
+
+    if (diff < 0)
+      diff = -diff;
+    if (diff < FRAC_NBITS)
+      {
+	/* ??? This does shifts one bit at a time.  Optimize.  */
+	while (a_normal_exp > b_normal_exp)
+	  {
+	    b_normal_exp++;
+	    LSHIFT (b_fraction);
+	  }
+	while (b_normal_exp > a_normal_exp)
+	  {
+	    a_normal_exp++;
+	    LSHIFT (a_fraction);
+	  }
+      }
+    else
+      {
+	/* Somethings's up.. choose the biggest */
+	if (a_normal_exp > b_normal_exp)
+	  {
+	    b_normal_exp = a_normal_exp;
+	    b_fraction = 0;
+	  }
+	else
+	  {
+	    a_normal_exp = b_normal_exp;
+	    a_fraction = 0;
+	  }
+      }
+  }
+
+  if (a->sign != b->sign)
+    {
+      if (a->sign)
+	{
+	  tfraction = -a_fraction + b_fraction;
+	}
+      else
+	{
+	  tfraction = a_fraction - b_fraction;
+	}
+      if (tfraction >= 0)
+	{
+	  tmp->sign = 0;
+	  tmp->normal_exp = a_normal_exp;
+	  tmp->fraction.ll = tfraction;
+	}
+      else
+	{
+	  tmp->sign = 1;
+	  tmp->normal_exp = a_normal_exp;
+	  tmp->fraction.ll = -tfraction;
+	}
+      /* and renormalize it */
+
+      while (tmp->fraction.ll < IMPLICIT_1 && tmp->fraction.ll)
+	{
+	  tmp->fraction.ll <<= 1;
+	  tmp->normal_exp--;
+	}
+    }
+  else
+    {
+      tmp->sign = a->sign;
+      tmp->normal_exp = a_normal_exp;
+      tmp->fraction.ll = a_fraction + b_fraction;
+    }
+  tmp->class = CLASS_NUMBER;
+  /* Now the fraction is added, we have to shift down to renormalize the
+     number */
+
+  if (tmp->fraction.ll >= IMPLICIT_2)
+    {
+      LSHIFT (tmp->fraction.ll);
+      tmp->normal_exp++;
+    }
+  return tmp;
+
+}
+
+FLO_type
+add (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  fp_number_type tmp;
+  fp_number_type *res;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  res = _fpadd_parts (&a, &b, &tmp);
+
+  return pack_d (res);
+}
+
+FLO_type
+sub (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  fp_number_type tmp;
+  fp_number_type *res;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  b.sign ^= 1;
+
+  res = _fpadd_parts (&a, &b, &tmp);
+
+  return pack_d (res);
+}
+#endif /* L_addsub_sf || L_addsub_df */
+
+#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
+static inline __attribute__ ((__always_inline__)) fp_number_type *
+_fpmul_parts ( fp_number_type *  a,
+	       fp_number_type *  b,
+	       fp_number_type * tmp)
+{
+  fractype low = 0;
+  fractype high = 0;
+
+  if (isnan (a))
+    {
+      a->sign = a->sign != b->sign;
+      return a;
+    }
+  if (isnan (b))
+    {
+      b->sign = a->sign != b->sign;
+      return b;
+    }
+  if (isinf (a))
+    {
+      if (iszero (b))
+	return nan ();
+      a->sign = a->sign != b->sign;
+      return a;
+    }
+  if (isinf (b))
+    {
+      if (iszero (a))
+	{
+	  return nan ();
+	}
+      b->sign = a->sign != b->sign;
+      return b;
+    }
+  if (iszero (a))
+    {
+      a->sign = a->sign != b->sign;
+      return a;
+    }
+  if (iszero (b))
+    {
+      b->sign = a->sign != b->sign;
+      return b;
+    }
+
+  /* Calculate the mantissa by multiplying both numbers to get a
+     twice-as-wide number.  */
+  {
+#if defined(NO_DI_MODE) || defined(TFLOAT)
+    {
+      fractype x = a->fraction.ll;
+      fractype ylow = b->fraction.ll;
+      fractype yhigh = 0;
+      int bit;
+
+      /* ??? This does multiplies one bit at a time.  Optimize.  */
+      for (bit = 0; bit < FRAC_NBITS; bit++)
+	{
+	  int carry;
+
+	  if (x & 1)
+	    {
+	      carry = (low += ylow) < ylow;
+	      high += yhigh + carry;
+	    }
+	  yhigh <<= 1;
+	  if (ylow & FRACHIGH)
+	    {
+	      yhigh |= 1;
+	    }
+	  ylow <<= 1;
+	  x >>= 1;
+	}
+    }
+#elif defined(FLOAT) 
+    /* Multiplying two USIs to get a UDI, we're safe.  */
+    {
+      UDItype answer = (UDItype)a->fraction.ll * (UDItype)b->fraction.ll;
+      
+      high = answer >> BITS_PER_SI;
+      low = answer;
+    }
+#else
+    /* fractype is DImode, but we need the result to be twice as wide.
+       Assuming a widening multiply from DImode to TImode is not
+       available, build one by hand.  */
+    {
+      USItype nl = a->fraction.ll;
+      USItype nh = a->fraction.ll >> BITS_PER_SI;
+      USItype ml = b->fraction.ll;
+      USItype mh = b->fraction.ll >> BITS_PER_SI;
+      UDItype pp_ll = (UDItype) ml * nl;
+      UDItype pp_hl = (UDItype) mh * nl;
+      UDItype pp_lh = (UDItype) ml * nh;
+      UDItype pp_hh = (UDItype) mh * nh;
+      UDItype res2 = 0;
+      UDItype res0 = 0;
+      UDItype ps_hh__ = pp_hl + pp_lh;
+      if (ps_hh__ < pp_hl)
+	res2 += (UDItype)1 << BITS_PER_SI;
+      pp_hl = (UDItype)(USItype)ps_hh__ << BITS_PER_SI;
+      res0 = pp_ll + pp_hl;
+      if (res0 < pp_ll)
+	res2++;
+      res2 += (ps_hh__ >> BITS_PER_SI) + pp_hh;
+      high = res2;
+      low = res0;
+    }
+#endif
+  }
+
+  tmp->normal_exp = a->normal_exp + b->normal_exp
+    + FRAC_NBITS - (FRACBITS + NGARDS);
+  tmp->sign = a->sign != b->sign;
+  while (high >= IMPLICIT_2)
+    {
+      tmp->normal_exp++;
+      if (high & 1)
+	{
+	  low >>= 1;
+	  low |= FRACHIGH;
+	}
+      high >>= 1;
+    }
+  while (high < IMPLICIT_1)
+    {
+      tmp->normal_exp--;
+
+      high <<= 1;
+      if (low & FRACHIGH)
+	high |= 1;
+      low <<= 1;
+    }
+  /* rounding is tricky. if we only round if it won't make us round later.  */
+#if 0
+  if (low & FRACHIGH2)
+    {
+      if (((high & GARDMASK) != GARDMSB)
+	  && (((high + 1) & GARDMASK) == GARDMSB))
+	{
+	  /* don't round, it gets done again later.  */
+	}
+      else
+	{
+	  high++;
+	}
+    }
+#endif
+  if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB)
+    {
+      if (high & (1 << NGARDS))
+	{
+	  /* half way, so round to even */
+	  high += GARDROUND + 1;
+	}
+      else if (low)
+	{
+	  /* but we really weren't half way */
+	  high += GARDROUND + 1;
+	}
+    }
+  tmp->fraction.ll = high;
+  tmp->class = CLASS_NUMBER;
+  return tmp;
+}
+
+FLO_type
+multiply (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  fp_number_type tmp;
+  fp_number_type *res;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  res = _fpmul_parts (&a, &b, &tmp);
+
+  return pack_d (res);
+}
+#endif /* L_mul_sf || L_mul_df */
+
+#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
+static inline __attribute__ ((__always_inline__)) fp_number_type *
+_fpdiv_parts (fp_number_type * a,
+	      fp_number_type * b)
+{
+  fractype bit;
+  fractype numerator;
+  fractype denominator;
+  fractype quotient;
+
+  if (isnan (a))
+    {
+      return a;
+    }
+  if (isnan (b))
+    {
+      return b;
+    }
+
+  a->sign = a->sign ^ b->sign;
+
+  if (isinf (a) || iszero (a))
+    {
+      if (a->class == b->class)
+	return nan ();
+      return a;
+    }
+
+  if (isinf (b))
+    {
+      a->fraction.ll = 0;
+      a->normal_exp = 0;
+      return a;
+    }
+  if (iszero (b))
+    {
+      a->class = CLASS_INFINITY;
+      return a;
+    }
+
+  /* Calculate the mantissa by multiplying both 64bit numbers to get a
+     128 bit number */
+  {
+    /* quotient =
+       ( numerator / denominator) * 2^(numerator exponent -  denominator exponent)
+     */
+
+    a->normal_exp = a->normal_exp - b->normal_exp;
+    numerator = a->fraction.ll;
+    denominator = b->fraction.ll;
+
+    if (numerator < denominator)
+      {
+	/* Fraction will be less than 1.0 */
+	numerator *= 2;
+	a->normal_exp--;
+      }
+    bit = IMPLICIT_1;
+    quotient = 0;
+    /* ??? Does divide one bit at a time.  Optimize.  */
+    while (bit)
+      {
+	if (numerator >= denominator)
+	  {
+	    quotient |= bit;
+	    numerator -= denominator;
+	  }
+	bit >>= 1;
+	numerator *= 2;
+      }
+
+    if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB)
+      {
+	if (quotient & (1 << NGARDS))
+	  {
+	    /* half way, so round to even */
+	    quotient += GARDROUND + 1;
+	  }
+	else if (numerator)
+	  {
+	    /* but we really weren't half way, more bits exist */
+	    quotient += GARDROUND + 1;
+	  }
+      }
+
+    a->fraction.ll = quotient;
+    return (a);
+  }
+}
+
+FLO_type
+divide (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  fp_number_type *res;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  res = _fpdiv_parts (&a, &b);
+
+  return pack_d (res);
+}
+#endif /* L_div_sf || L_div_df */
+
+#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \
+    || defined(L_fpcmp_parts_tf)
+/* according to the demo, fpcmp returns a comparison with 0... thus
+   a<b -> -1
+   a==b -> 0
+   a>b -> +1
+ */
+
+int
+__fpcmp_parts (fp_number_type * a, fp_number_type * b)
+{
+#if 0
+  /* either nan -> unordered. Must be checked outside of this routine.  */
+  if (isnan (a) && isnan (b))
+    {
+      return 1;			/* still unordered! */
+    }
+#endif
+
+  if (isnan (a) || isnan (b))
+    {
+      return 1;			/* how to indicate unordered compare? */
+    }
+  if (isinf (a) && isinf (b))
+    {
+      /* +inf > -inf, but +inf != +inf */
+      /* b    \a| +inf(0)| -inf(1)
+       ______\+--------+--------
+       +inf(0)| a==b(0)| a<b(-1)
+       -------+--------+--------
+       -inf(1)| a>b(1) | a==b(0)
+       -------+--------+--------
+       So since unordered must be nonzero, just line up the columns...
+       */
+      return b->sign - a->sign;
+    }
+  /* but not both...  */
+  if (isinf (a))
+    {
+      return a->sign ? -1 : 1;
+    }
+  if (isinf (b))
+    {
+      return b->sign ? 1 : -1;
+    }
+  if (iszero (a) && iszero (b))
+    {
+      return 0;
+    }
+  if (iszero (a))
+    {
+      return b->sign ? 1 : -1;
+    }
+  if (iszero (b))
+    {
+      return a->sign ? -1 : 1;
+    }
+  /* now both are "normal".  */
+  if (a->sign != b->sign)
+    {
+      /* opposite signs */
+      return a->sign ? -1 : 1;
+    }
+  /* same sign; exponents? */
+  if (a->normal_exp > b->normal_exp)
+    {
+      return a->sign ? -1 : 1;
+    }
+  if (a->normal_exp < b->normal_exp)
+    {
+      return a->sign ? 1 : -1;
+    }
+  /* same exponents; check size.  */
+  if (a->fraction.ll > b->fraction.ll)
+    {
+      return a->sign ? -1 : 1;
+    }
+  if (a->fraction.ll < b->fraction.ll)
+    {
+      return a->sign ? 1 : -1;
+    }
+  /* after all that, they're equal.  */
+  return 0;
+}
+#endif
+
+#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf)
+CMPtype
+compare (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  return __fpcmp_parts (&a, &b);
+}
+#endif /* L_compare_sf || L_compare_df */
+
+#ifndef US_SOFTWARE_GOFAST
+
+/* These should be optimized for their specific tasks someday.  */
+
+#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf)
+CMPtype
+_eq_f2 (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  if (isnan (&a) || isnan (&b))
+    return 1;			/* false, truth == 0 */
+
+  return __fpcmp_parts (&a, &b) ;
+}
+#endif /* L_eq_sf || L_eq_df */
+
+#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf)
+CMPtype
+_ne_f2 (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  if (isnan (&a) || isnan (&b))
+    return 1;			/* true, truth != 0 */
+
+  return  __fpcmp_parts (&a, &b) ;
+}
+#endif /* L_ne_sf || L_ne_df */
+
+#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf)
+CMPtype
+_gt_f2 (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  if (isnan (&a) || isnan (&b))
+    return -1;			/* false, truth > 0 */
+
+  return __fpcmp_parts (&a, &b);
+}
+#endif /* L_gt_sf || L_gt_df */
+
+#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf)
+CMPtype
+_ge_f2 (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  if (isnan (&a) || isnan (&b))
+    return -1;			/* false, truth >= 0 */
+  return __fpcmp_parts (&a, &b) ;
+}
+#endif /* L_ge_sf || L_ge_df */
+
+#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf)
+CMPtype
+_lt_f2 (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  if (isnan (&a) || isnan (&b))
+    return 1;			/* false, truth < 0 */
+
+  return __fpcmp_parts (&a, &b);
+}
+#endif /* L_lt_sf || L_lt_df */
+
+#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf)
+CMPtype
+_le_f2 (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  if (isnan (&a) || isnan (&b))
+    return 1;			/* false, truth <= 0 */
+
+  return __fpcmp_parts (&a, &b) ;
+}
+#endif /* L_le_sf || L_le_df */
+
+#endif /* ! US_SOFTWARE_GOFAST */
+
+#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf)
+CMPtype
+_unord_f2 (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  return (isnan (&a) || isnan (&b));
+}
+#endif /* L_unord_sf || L_unord_df */
+
+#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf)
+FLO_type
+si_to_float (SItype arg_a)
+{
+  fp_number_type in;
+
+  in.class = CLASS_NUMBER;
+  in.sign = arg_a < 0;
+  if (!arg_a)
+    {
+      in.class = CLASS_ZERO;
+    }
+  else
+    {
+      in.normal_exp = FRACBITS + NGARDS;
+      if (in.sign) 
+	{
+	  /* Special case for minint, since there is no +ve integer
+	     representation for it */
+	  if (arg_a == (- MAX_SI_INT - 1))
+	    {
+	      return (FLO_type)(- MAX_SI_INT - 1);
+	    }
+	  in.fraction.ll = (-arg_a);
+	}
+      else
+	in.fraction.ll = arg_a;
+
+      while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
+	{
+	  in.fraction.ll <<= 1;
+	  in.normal_exp -= 1;
+	}
+    }
+  return pack_d (&in);
+}
+#endif /* L_si_to_sf || L_si_to_df */
+
+#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf)
+FLO_type
+usi_to_float (USItype arg_a)
+{
+  fp_number_type in;
+
+  in.sign = 0;
+  if (!arg_a)
+    {
+      in.class = CLASS_ZERO;
+    }
+  else
+    {
+      in.class = CLASS_NUMBER;
+      in.normal_exp = FRACBITS + NGARDS;
+      in.fraction.ll = arg_a;
+
+      while (in.fraction.ll > ((fractype)1 << (FRACBITS + NGARDS)))
+        {
+          in.fraction.ll >>= 1;
+          in.normal_exp += 1;
+        }
+      while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
+	{
+	  in.fraction.ll <<= 1;
+	  in.normal_exp -= 1;
+	}
+    }
+  return pack_d (&in);
+}
+#endif
+
+#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si)
+SItype
+float_to_si (FLO_type arg_a)
+{
+  fp_number_type a;
+  SItype tmp;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &a);
+
+  if (iszero (&a))
+    return 0;
+  if (isnan (&a))
+    return 0;
+  /* get reasonable MAX_SI_INT...  */
+  if (isinf (&a))
+    return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
+  /* it is a number, but a small one */
+  if (a.normal_exp < 0)
+    return 0;
+  if (a.normal_exp > BITS_PER_SI - 2)
+    return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
+  tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
+  return a.sign ? (-tmp) : (tmp);
+}
+#endif /* L_sf_to_si || L_df_to_si */
+
+#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi)
+#if defined US_SOFTWARE_GOFAST || defined(L_tf_to_usi)
+/* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines,
+   we also define them for GOFAST because the ones in libgcc2.c have the
+   wrong names and I'd rather define these here and keep GOFAST CYG-LOC's
+   out of libgcc2.c.  We can't define these here if not GOFAST because then
+   there'd be duplicate copies.  */
+
+USItype
+float_to_usi (FLO_type arg_a)
+{
+  fp_number_type a;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &a);
+
+  if (iszero (&a))
+    return 0;
+  if (isnan (&a))
+    return 0;
+  /* it is a negative number */
+  if (a.sign)
+    return 0;
+  /* get reasonable MAX_USI_INT...  */
+  if (isinf (&a))
+    return MAX_USI_INT;
+  /* it is a number, but a small one */
+  if (a.normal_exp < 0)
+    return 0;
+  if (a.normal_exp > BITS_PER_SI - 1)
+    return MAX_USI_INT;
+  else if (a.normal_exp > (FRACBITS + NGARDS))
+    return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS));
+  else
+    return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
+}
+#endif /* US_SOFTWARE_GOFAST */
+#endif /* L_sf_to_usi || L_df_to_usi */
+
+#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf)
+FLO_type
+negate (FLO_type arg_a)
+{
+  fp_number_type a;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &a);
+
+  flip_sign (&a);
+  return pack_d (&a);
+}
+#endif /* L_negate_sf || L_negate_df */
+
+#ifdef FLOAT
+
+#if defined(L_make_sf)
+SFtype
+__make_fp(fp_class_type class,
+	     unsigned int sign,
+	     int exp, 
+	     USItype frac)
+{
+  fp_number_type in;
+
+  in.class = class;
+  in.sign = sign;
+  in.normal_exp = exp;
+  in.fraction.ll = frac;
+  return pack_d (&in);
+}
+#endif /* L_make_sf */
+
+#ifndef FLOAT_ONLY
+
+/* This enables one to build an fp library that supports float but not double.
+   Otherwise, we would get an undefined reference to __make_dp.
+   This is needed for some 8-bit ports that can't handle well values that
+   are 8-bytes in size, so we just don't support double for them at all.  */
+
+#if defined(L_sf_to_df)
+DFtype
+sf_to_df (SFtype arg_a)
+{
+  fp_number_type in;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &in);
+
+  return __make_dp (in.class, in.sign, in.normal_exp,
+		    ((UDItype) in.fraction.ll) << F_D_BITOFF);
+}
+#endif /* L_sf_to_df */
+
+#if defined(L_sf_to_tf) && defined(TMODES)
+TFtype
+sf_to_tf (SFtype arg_a)
+{
+  fp_number_type in;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &in);
+
+  return __make_tp (in.class, in.sign, in.normal_exp,
+		    ((UTItype) in.fraction.ll) << F_T_BITOFF);
+}
+#endif /* L_sf_to_df */
+
+#endif /* ! FLOAT_ONLY */
+#endif /* FLOAT */
+
+#ifndef FLOAT
+
+extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype);
+
+#if defined(L_make_df)
+DFtype
+__make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac)
+{
+  fp_number_type in;
+
+  in.class = class;
+  in.sign = sign;
+  in.normal_exp = exp;
+  in.fraction.ll = frac;
+  return pack_d (&in);
+}
+#endif /* L_make_df */
+
+#if defined(L_df_to_sf)
+SFtype
+df_to_sf (DFtype arg_a)
+{
+  fp_number_type in;
+  USItype sffrac;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &in);
+
+  sffrac = in.fraction.ll >> F_D_BITOFF;
+
+  /* We set the lowest guard bit in SFFRAC if we discarded any non
+     zero bits.  */
+  if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0)
+    sffrac |= 1;
+
+  return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
+}
+#endif /* L_df_to_sf */
+
+#if defined(L_df_to_tf) && defined(TMODES) \
+    && !defined(FLOAT) && !defined(TFLOAT)
+TFtype
+df_to_tf (DFtype arg_a)
+{
+  fp_number_type in;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &in);
+
+  return __make_tp (in.class, in.sign, in.normal_exp,
+		    ((UTItype) in.fraction.ll) << D_T_BITOFF);
+}
+#endif /* L_sf_to_df */
+
+#ifdef TFLOAT
+#if defined(L_make_tf)
+TFtype
+__make_tp(fp_class_type class,
+	     unsigned int sign,
+	     int exp, 
+	     UTItype frac)
+{
+  fp_number_type in;
+
+  in.class = class;
+  in.sign = sign;
+  in.normal_exp = exp;
+  in.fraction.ll = frac;
+  return pack_d (&in);
+}
+#endif /* L_make_tf */
+
+#if defined(L_tf_to_df)
+DFtype
+tf_to_df (TFtype arg_a)
+{
+  fp_number_type in;
+  UDItype sffrac;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &in);
+
+  sffrac = in.fraction.ll >> D_T_BITOFF;
+
+  /* We set the lowest guard bit in SFFRAC if we discarded any non
+     zero bits.  */
+  if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0)
+    sffrac |= 1;
+
+  return __make_dp (in.class, in.sign, in.normal_exp, sffrac);
+}
+#endif /* L_tf_to_df */
+
+#if defined(L_tf_to_sf)
+SFtype
+tf_to_sf (TFtype arg_a)
+{
+  fp_number_type in;
+  USItype sffrac;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &in);
+
+  sffrac = in.fraction.ll >> F_T_BITOFF;
+
+  /* We set the lowest guard bit in SFFRAC if we discarded any non
+     zero bits.  */
+  if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0)
+    sffrac |= 1;
+
+  return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
+}
+#endif /* L_tf_to_sf */
+#endif /* TFLOAT */
+
+#endif /* ! FLOAT */
+#endif /* !EXTENDED_FLOAT_STUBS */
--- gcc-3.4.3/gcc/config/nios2/nios2-fp-bit.c
+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-fp-bit.c
@@ -0,0 +1,1652 @@
+#define FLOAT
+/* This is a software floating point library which can be used
+   for targets without hardware floating point. 
+   Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004
+   Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs without any restriction coming from the use of this
+file.  (The General Public License restrictions do apply in other
+respects; for example, they cover modification of the file, and
+distribution when not linked into another program.)
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with other files,
+   some of which are compiled with GCC, to produce an executable,
+   this library does not by itself cause the resulting executable
+   to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+/* This implements IEEE 754 format arithmetic, but does not provide a
+   mechanism for setting the rounding mode, or for generating or handling
+   exceptions.
+
+   The original code by Steve Chamberlain, hacked by Mark Eichin and Jim
+   Wilson, all of Cygnus Support.  */
+
+/* The intended way to use this file is to make two copies, add `#define FLOAT'
+   to one copy, then compile both copies and add them to libgcc.a.  */
+
+#include "tconfig.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "config/fp-bit.h"
+
+/* The following macros can be defined to change the behavior of this file:
+   FLOAT: Implement a `float', aka SFmode, fp library.  If this is not
+     defined, then this file implements a `double', aka DFmode, fp library.
+   FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e.
+     don't include float->double conversion which requires the double library.
+     This is useful only for machines which can't support doubles, e.g. some
+     8-bit processors.
+   CMPtype: Specify the type that floating point compares should return.
+     This defaults to SItype, aka int.
+   US_SOFTWARE_GOFAST: This makes all entry points use the same names as the
+     US Software goFast library.
+   _DEBUG_BITFLOAT: This makes debugging the code a little easier, by adding
+     two integers to the FLO_union_type.
+   NO_DENORMALS: Disable handling of denormals.
+   NO_NANS: Disable nan and infinity handling
+   SMALL_MACHINE: Useful when operations on QIs and HIs are faster
+     than on an SI */
+
+/* We don't currently support extended floats (long doubles) on machines
+   without hardware to deal with them.
+
+   These stubs are just to keep the linker from complaining about unresolved
+   references which can be pulled in from libio & libstdc++, even if the
+   user isn't using long doubles.  However, they may generate an unresolved
+   external to abort if abort is not used by the function, and the stubs
+   are referenced from within libc, since libgcc goes before and after the
+   system library.  */
+
+#ifdef DECLARE_LIBRARY_RENAMES
+  DECLARE_LIBRARY_RENAMES
+#endif
+
+#ifdef EXTENDED_FLOAT_STUBS
+extern void abort (void);
+void __extendsfxf2 (void) { abort(); }
+void __extenddfxf2 (void) { abort(); }
+void __truncxfdf2 (void) { abort(); }
+void __truncxfsf2 (void) { abort(); }
+void __fixxfsi (void) { abort(); }
+void __floatsixf (void) { abort(); }
+void __addxf3 (void) { abort(); }
+void __subxf3 (void) { abort(); }
+void __mulxf3 (void) { abort(); }
+void __divxf3 (void) { abort(); }
+void __negxf2 (void) { abort(); }
+void __eqxf2 (void) { abort(); }
+void __nexf2 (void) { abort(); }
+void __gtxf2 (void) { abort(); }
+void __gexf2 (void) { abort(); }
+void __lexf2 (void) { abort(); }
+void __ltxf2 (void) { abort(); }
+
+void __extendsftf2 (void) { abort(); }
+void __extenddftf2 (void) { abort(); }
+void __trunctfdf2 (void) { abort(); }
+void __trunctfsf2 (void) { abort(); }
+void __fixtfsi (void) { abort(); }
+void __floatsitf (void) { abort(); }
+void __addtf3 (void) { abort(); }
+void __subtf3 (void) { abort(); }
+void __multf3 (void) { abort(); }
+void __divtf3 (void) { abort(); }
+void __negtf2 (void) { abort(); }
+void __eqtf2 (void) { abort(); }
+void __netf2 (void) { abort(); }
+void __gttf2 (void) { abort(); }
+void __getf2 (void) { abort(); }
+void __letf2 (void) { abort(); }
+void __lttf2 (void) { abort(); }
+#else	/* !EXTENDED_FLOAT_STUBS, rest of file */
+
+/* IEEE "special" number predicates */
+
+#ifdef NO_NANS
+
+#define nan() 0
+#define isnan(x) 0
+#define isinf(x) 0
+#else
+
+#if   defined L_thenan_sf
+const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
+#elif defined L_thenan_df
+const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} };
+#elif defined L_thenan_tf
+const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
+#elif defined TFLOAT
+extern const fp_number_type __thenan_tf;
+#elif defined FLOAT
+extern const fp_number_type __thenan_sf;
+#else
+extern const fp_number_type __thenan_df;
+#endif
+
+INLINE
+static fp_number_type *
+nan (void)
+{
+  /* Discard the const qualifier...  */
+#ifdef TFLOAT
+  return (fp_number_type *) (& __thenan_tf);
+#elif defined FLOAT  
+  return (fp_number_type *) (& __thenan_sf);
+#else
+  return (fp_number_type *) (& __thenan_df);
+#endif
+}
+
+INLINE
+static int
+isnan ( fp_number_type *  x)
+{
+  return x->class == CLASS_SNAN || x->class == CLASS_QNAN;
+}
+
+INLINE
+static int
+isinf ( fp_number_type *  x)
+{
+  return x->class == CLASS_INFINITY;
+}
+
+#endif /* NO_NANS */
+
+INLINE
+static int
+iszero ( fp_number_type *  x)
+{
+  return x->class == CLASS_ZERO;
+}
+
+INLINE 
+static void
+flip_sign ( fp_number_type *  x)
+{
+  x->sign = !x->sign;
+}
+
+extern FLO_type pack_d ( fp_number_type * );
+
+#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
+FLO_type
+pack_d ( fp_number_type *  src)
+{
+  FLO_union_type dst;
+  fractype fraction = src->fraction.ll;	/* wasn't unsigned before? */
+  int sign = src->sign;
+  int exp = 0;
+
+  if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src)))
+    {
+      /* We can't represent these values accurately.  By using the
+	 largest possible magnitude, we guarantee that the conversion
+	 of infinity is at least as big as any finite number.  */
+      exp = EXPMAX;
+      fraction = ((fractype) 1 << FRACBITS) - 1;
+    }
+  else if (isnan (src))
+    {
+      exp = EXPMAX;
+      if (src->class == CLASS_QNAN || 1)
+	{
+#ifdef QUIET_NAN_NEGATED
+	  fraction |= QUIET_NAN - 1;
+#else
+	  fraction |= QUIET_NAN;
+#endif
+	}
+    }
+  else if (isinf (src))
+    {
+      exp = EXPMAX;
+      fraction = 0;
+    }
+  else if (iszero (src))
+    {
+      exp = 0;
+      fraction = 0;
+    }
+  else if (fraction == 0)
+    {
+      exp = 0;
+    }
+  else
+    {
+      if (src->normal_exp < NORMAL_EXPMIN)
+	{
+#ifdef NO_DENORMALS
+	  /* Go straight to a zero representation if denormals are not
+ 	     supported.  The denormal handling would be harmless but
+ 	     isn't unnecessary.  */
+	  exp = 0;
+	  fraction = 0;
+#else /* NO_DENORMALS */
+	  /* This number's exponent is too low to fit into the bits
+	     available in the number, so we'll store 0 in the exponent and
+	     shift the fraction to the right to make up for it.  */
+
+	  int shift = NORMAL_EXPMIN - src->normal_exp;
+
+	  exp = 0;
+
+	  if (shift > FRAC_NBITS - NGARDS)
+	    {
+	      /* No point shifting, since it's more that 64 out.  */
+	      fraction = 0;
+	    }
+	  else
+	    {
+	      int lowbit = (fraction & (((fractype)1 << shift) - 1)) ? 1 : 0;
+	      fraction = (fraction >> shift) | lowbit;
+	    }
+	  if ((fraction & GARDMASK) == GARDMSB)
+	    {
+	      if ((fraction & (1 << NGARDS)))
+		fraction += GARDROUND + 1;
+	    }
+	  else
+	    {
+	      /* Add to the guards to round up.  */
+	      fraction += GARDROUND;
+	    }
+	  /* Perhaps the rounding means we now need to change the
+             exponent, because the fraction is no longer denormal.  */
+	  if (fraction >= IMPLICIT_1)
+	    {
+	      exp += 1;
+	    }
+	  fraction >>= NGARDS;
+#endif /* NO_DENORMALS */
+	}
+      else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
+	       && src->normal_exp > EXPBIAS)
+	{
+	  exp = EXPMAX;
+	  fraction = 0;
+	}
+      else
+	{
+	  exp = src->normal_exp + EXPBIAS;
+	  if (!ROUND_TOWARDS_ZERO)
+	    {
+	      /* IF the gard bits are the all zero, but the first, then we're
+		 half way between two numbers, choose the one which makes the
+		 lsb of the answer 0.  */
+	      if ((fraction & GARDMASK) == GARDMSB)
+		{
+		  if (fraction & (1 << NGARDS))
+		    fraction += GARDROUND + 1;
+		}
+	      else
+		{
+		  /* Add a one to the guards to round up */
+		  fraction += GARDROUND;
+		}
+	      if (fraction >= IMPLICIT_2)
+		{
+		  fraction >>= 1;
+		  exp += 1;
+		}
+	    }
+	  fraction >>= NGARDS;
+
+	  if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX)
+	    {
+	      /* Saturate on overflow.  */
+	      exp = EXPMAX;
+	      fraction = ((fractype) 1 << FRACBITS) - 1;
+	    }
+	}
+    }
+
+  /* We previously used bitfields to store the number, but this doesn't
+     handle little/big endian systems conveniently, so use shifts and
+     masks */
+#ifdef FLOAT_BIT_ORDER_MISMATCH
+  dst.bits.fraction = fraction;
+  dst.bits.exp = exp;
+  dst.bits.sign = sign;
+#else
+# if defined TFLOAT && defined HALFFRACBITS
+ {
+   halffractype high, low, unity;
+   int lowsign, lowexp;
+
+   unity = (halffractype) 1 << HALFFRACBITS;
+
+   /* Set HIGH to the high double's significand, masking out the implicit 1.
+      Set LOW to the low double's full significand.  */
+   high = (fraction >> (FRACBITS - HALFFRACBITS)) & (unity - 1);
+   low = fraction & (unity * 2 - 1);
+
+   /* Get the initial sign and exponent of the low double.  */
+   lowexp = exp - HALFFRACBITS - 1;
+   lowsign = sign;
+
+   /* HIGH should be rounded like a normal double, making |LOW| <=
+      0.5 ULP of HIGH.  Assume round-to-nearest.  */
+   if (exp < EXPMAX)
+     if (low > unity || (low == unity && (high & 1) == 1))
+       {
+	 /* Round HIGH up and adjust LOW to match.  */
+	 high++;
+	 if (high == unity)
+	   {
+	     /* May make it infinite, but that's OK.  */
+	     high = 0;
+	     exp++;
+	   }
+	 low = unity * 2 - low;
+	 lowsign ^= 1;
+       }
+
+   high |= (halffractype) exp << HALFFRACBITS;
+   high |= (halffractype) sign << (HALFFRACBITS + EXPBITS);
+
+   if (exp == EXPMAX || exp == 0 || low == 0)
+     low = 0;
+   else
+     {
+       while (lowexp > 0 && low < unity)
+	 {
+	   low <<= 1;
+	   lowexp--;
+	 }
+
+       if (lowexp <= 0)
+	 {
+	   halffractype roundmsb, round;
+	   int shift;
+
+	   shift = 1 - lowexp;
+	   roundmsb = (1 << (shift - 1));
+	   round = low & ((roundmsb << 1) - 1);
+
+	   low >>= shift;
+	   lowexp = 0;
+
+	   if (round > roundmsb || (round == roundmsb && (low & 1) == 1))
+	     {
+	       low++;
+	       if (low == unity)
+		 /* LOW rounds up to the smallest normal number.  */
+		 lowexp++;
+	     }
+	 }
+
+       low &= unity - 1;
+       low |= (halffractype) lowexp << HALFFRACBITS;
+       low |= (halffractype) lowsign << (HALFFRACBITS + EXPBITS);
+     }
+   dst.value_raw = ((fractype) high << HALFSHIFT) | low;
+ }
+# else
+  dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1);
+  dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS;
+  dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS);
+# endif
+#endif
+
+#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
+#ifdef TFLOAT
+  {
+    qrtrfractype tmp1 = dst.words[0];
+    qrtrfractype tmp2 = dst.words[1];
+    dst.words[0] = dst.words[3];
+    dst.words[1] = dst.words[2];
+    dst.words[2] = tmp2;
+    dst.words[3] = tmp1;
+  }
+#else
+  {
+    halffractype tmp = dst.words[0];
+    dst.words[0] = dst.words[1];
+    dst.words[1] = tmp;
+  }
+#endif
+#endif
+
+  return dst.value;
+}
+#endif
+
+#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf)
+void
+unpack_d (FLO_union_type * src, fp_number_type * dst)
+{
+  /* We previously used bitfields to store the number, but this doesn't
+     handle little/big endian systems conveniently, so use shifts and
+     masks */
+  fractype fraction;
+  int exp;
+  int sign;
+
+#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
+  FLO_union_type swapped;
+
+#ifdef TFLOAT
+  swapped.words[0] = src->words[3];
+  swapped.words[1] = src->words[2];
+  swapped.words[2] = src->words[1];
+  swapped.words[3] = src->words[0];
+#else
+  swapped.words[0] = src->words[1];
+  swapped.words[1] = src->words[0];
+#endif
+  src = &swapped;
+#endif
+  
+#ifdef FLOAT_BIT_ORDER_MISMATCH
+  fraction = src->bits.fraction;
+  exp = src->bits.exp;
+  sign = src->bits.sign;
+#else
+# if defined TFLOAT && defined HALFFRACBITS
+ {
+   halffractype high, low;
+   
+   high = src->value_raw >> HALFSHIFT;
+   low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1);
+
+   fraction = high & ((((fractype)1) << HALFFRACBITS) - 1);
+   fraction <<= FRACBITS - HALFFRACBITS;
+   exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
+   sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1;
+
+   if (exp != EXPMAX && exp != 0 && low != 0)
+     {
+       int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
+       int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1;
+       int shift;
+       fractype xlow;
+
+       xlow = low & ((((fractype)1) << HALFFRACBITS) - 1);
+       if (lowexp)
+	 xlow |= (((halffractype)1) << HALFFRACBITS);
+       else
+	 lowexp = 1;
+       shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp);
+       if (shift > 0)
+	 xlow <<= shift;
+       else if (shift < 0)
+	 xlow >>= -shift;
+       if (sign == lowsign)
+	 fraction += xlow;
+       else if (fraction >= xlow)
+	 fraction -= xlow;
+       else
+	 {
+	   /* The high part is a power of two but the full number is lower.
+	      This code will leave the implicit 1 in FRACTION, but we'd
+	      have added that below anyway.  */
+	   fraction = (((fractype) 1 << FRACBITS) - xlow) << 1;
+	   exp--;
+	 }
+     }
+ }
+# else
+  fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1);
+  exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1);
+  sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1;
+# endif
+#endif
+
+  dst->sign = sign;
+  if (exp == 0)
+    {
+      /* Hmm.  Looks like 0 */
+      if (fraction == 0
+#ifdef NO_DENORMALS
+	  || 1
+#endif
+	  )
+	{
+	  /* tastes like zero */
+	  dst->class = CLASS_ZERO;
+	}
+      else
+	{
+	  /* Zero exponent with nonzero fraction - it's denormalized,
+	     so there isn't a leading implicit one - we'll shift it so
+	     it gets one.  */
+	  dst->normal_exp = exp - EXPBIAS + 1;
+	  fraction <<= NGARDS;
+
+	  dst->class = CLASS_NUMBER;
+#if 1
+	  while (fraction < IMPLICIT_1)
+	    {
+	      fraction <<= 1;
+	      dst->normal_exp--;
+	    }
+#endif
+	  dst->fraction.ll = fraction;
+	}
+    }
+  else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX)
+    {
+      /* Huge exponent*/
+      if (fraction == 0)
+	{
+	  /* Attached to a zero fraction - means infinity */
+	  dst->class = CLASS_INFINITY;
+	}
+      else
+	{
+	  /* Nonzero fraction, means nan */
+#ifdef QUIET_NAN_NEGATED
+	  if ((fraction & QUIET_NAN) == 0)
+#else
+	  if (fraction & QUIET_NAN)
+#endif
+	    {
+	      dst->class = CLASS_QNAN;
+	    }
+	  else
+	    {
+	      dst->class = CLASS_SNAN;
+	    }
+	  /* Keep the fraction part as the nan number */
+	  dst->fraction.ll = fraction;
+	}
+    }
+  else
+    {
+      /* Nothing strange about this number */
+      dst->normal_exp = exp - EXPBIAS;
+      dst->class = CLASS_NUMBER;
+      dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1;
+    }
+}
+#endif /* L_unpack_df || L_unpack_sf */
+
+#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
+static fp_number_type *
+_fpadd_parts (fp_number_type * a,
+	      fp_number_type * b,
+	      fp_number_type * tmp)
+{
+  intfrac tfraction;
+
+  /* Put commonly used fields in local variables.  */
+  int a_normal_exp;
+  int b_normal_exp;
+  fractype a_fraction;
+  fractype b_fraction;
+
+  if (isnan (a))
+    {
+      return a;
+    }
+  if (isnan (b))
+    {
+      return b;
+    }
+  if (isinf (a))
+    {
+      /* Adding infinities with opposite signs yields a NaN.  */
+      if (isinf (b) && a->sign != b->sign)
+	return nan ();
+      return a;
+    }
+  if (isinf (b))
+    {
+      return b;
+    }
+  if (iszero (b))
+    {
+      if (iszero (a))
+	{
+	  *tmp = *a;
+	  tmp->sign = a->sign & b->sign;
+	  return tmp;
+	}
+      return a;
+    }
+  if (iszero (a))
+    {
+      return b;
+    }
+
+  /* Got two numbers. shift the smaller and increment the exponent till
+     they're the same */
+  {
+    int diff;
+
+    a_normal_exp = a->normal_exp;
+    b_normal_exp = b->normal_exp;
+    a_fraction = a->fraction.ll;
+    b_fraction = b->fraction.ll;
+
+    diff = a_normal_exp - b_normal_exp;
+
+    if (diff < 0)
+      diff = -diff;
+    if (diff < FRAC_NBITS)
+      {
+	/* ??? This does shifts one bit at a time.  Optimize.  */
+	while (a_normal_exp > b_normal_exp)
+	  {
+	    b_normal_exp++;
+	    LSHIFT (b_fraction);
+	  }
+	while (b_normal_exp > a_normal_exp)
+	  {
+	    a_normal_exp++;
+	    LSHIFT (a_fraction);
+	  }
+      }
+    else
+      {
+	/* Somethings's up.. choose the biggest */
+	if (a_normal_exp > b_normal_exp)
+	  {
+	    b_normal_exp = a_normal_exp;
+	    b_fraction = 0;
+	  }
+	else
+	  {
+	    a_normal_exp = b_normal_exp;
+	    a_fraction = 0;
+	  }
+      }
+  }
+
+  if (a->sign != b->sign)
+    {
+      if (a->sign)
+	{
+	  tfraction = -a_fraction + b_fraction;
+	}
+      else
+	{
+	  tfraction = a_fraction - b_fraction;
+	}
+      if (tfraction >= 0)
+	{
+	  tmp->sign = 0;
+	  tmp->normal_exp = a_normal_exp;
+	  tmp->fraction.ll = tfraction;
+	}
+      else
+	{
+	  tmp->sign = 1;
+	  tmp->normal_exp = a_normal_exp;
+	  tmp->fraction.ll = -tfraction;
+	}
+      /* and renormalize it */
+
+      while (tmp->fraction.ll < IMPLICIT_1 && tmp->fraction.ll)
+	{
+	  tmp->fraction.ll <<= 1;
+	  tmp->normal_exp--;
+	}
+    }
+  else
+    {
+      tmp->sign = a->sign;
+      tmp->normal_exp = a_normal_exp;
+      tmp->fraction.ll = a_fraction + b_fraction;
+    }
+  tmp->class = CLASS_NUMBER;
+  /* Now the fraction is added, we have to shift down to renormalize the
+     number */
+
+  if (tmp->fraction.ll >= IMPLICIT_2)
+    {
+      LSHIFT (tmp->fraction.ll);
+      tmp->normal_exp++;
+    }
+  return tmp;
+
+}
+
+FLO_type
+add (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  fp_number_type tmp;
+  fp_number_type *res;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  res = _fpadd_parts (&a, &b, &tmp);
+
+  return pack_d (res);
+}
+
+FLO_type
+sub (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  fp_number_type tmp;
+  fp_number_type *res;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  b.sign ^= 1;
+
+  res = _fpadd_parts (&a, &b, &tmp);
+
+  return pack_d (res);
+}
+#endif /* L_addsub_sf || L_addsub_df */
+
+#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
+static inline __attribute__ ((__always_inline__)) fp_number_type *
+_fpmul_parts ( fp_number_type *  a,
+	       fp_number_type *  b,
+	       fp_number_type * tmp)
+{
+  fractype low = 0;
+  fractype high = 0;
+
+  if (isnan (a))
+    {
+      a->sign = a->sign != b->sign;
+      return a;
+    }
+  if (isnan (b))
+    {
+      b->sign = a->sign != b->sign;
+      return b;
+    }
+  if (isinf (a))
+    {
+      if (iszero (b))
+	return nan ();
+      a->sign = a->sign != b->sign;
+      return a;
+    }
+  if (isinf (b))
+    {
+      if (iszero (a))
+	{
+	  return nan ();
+	}
+      b->sign = a->sign != b->sign;
+      return b;
+    }
+  if (iszero (a))
+    {
+      a->sign = a->sign != b->sign;
+      return a;
+    }
+  if (iszero (b))
+    {
+      b->sign = a->sign != b->sign;
+      return b;
+    }
+
+  /* Calculate the mantissa by multiplying both numbers to get a
+     twice-as-wide number.  */
+  {
+#if defined(NO_DI_MODE) || defined(TFLOAT)
+    {
+      fractype x = a->fraction.ll;
+      fractype ylow = b->fraction.ll;
+      fractype yhigh = 0;
+      int bit;
+
+      /* ??? This does multiplies one bit at a time.  Optimize.  */
+      for (bit = 0; bit < FRAC_NBITS; bit++)
+	{
+	  int carry;
+
+	  if (x & 1)
+	    {
+	      carry = (low += ylow) < ylow;
+	      high += yhigh + carry;
+	    }
+	  yhigh <<= 1;
+	  if (ylow & FRACHIGH)
+	    {
+	      yhigh |= 1;
+	    }
+	  ylow <<= 1;
+	  x >>= 1;
+	}
+    }
+#elif defined(FLOAT) 
+    /* Multiplying two USIs to get a UDI, we're safe.  */
+    {
+      UDItype answer = (UDItype)a->fraction.ll * (UDItype)b->fraction.ll;
+      
+      high = answer >> BITS_PER_SI;
+      low = answer;
+    }
+#else
+    /* fractype is DImode, but we need the result to be twice as wide.
+       Assuming a widening multiply from DImode to TImode is not
+       available, build one by hand.  */
+    {
+      USItype nl = a->fraction.ll;
+      USItype nh = a->fraction.ll >> BITS_PER_SI;
+      USItype ml = b->fraction.ll;
+      USItype mh = b->fraction.ll >> BITS_PER_SI;
+      UDItype pp_ll = (UDItype) ml * nl;
+      UDItype pp_hl = (UDItype) mh * nl;
+      UDItype pp_lh = (UDItype) ml * nh;
+      UDItype pp_hh = (UDItype) mh * nh;
+      UDItype res2 = 0;
+      UDItype res0 = 0;
+      UDItype ps_hh__ = pp_hl + pp_lh;
+      if (ps_hh__ < pp_hl)
+	res2 += (UDItype)1 << BITS_PER_SI;
+      pp_hl = (UDItype)(USItype)ps_hh__ << BITS_PER_SI;
+      res0 = pp_ll + pp_hl;
+      if (res0 < pp_ll)
+	res2++;
+      res2 += (ps_hh__ >> BITS_PER_SI) + pp_hh;
+      high = res2;
+      low = res0;
+    }
+#endif
+  }
+
+  tmp->normal_exp = a->normal_exp + b->normal_exp
+    + FRAC_NBITS - (FRACBITS + NGARDS);
+  tmp->sign = a->sign != b->sign;
+  while (high >= IMPLICIT_2)
+    {
+      tmp->normal_exp++;
+      if (high & 1)
+	{
+	  low >>= 1;
+	  low |= FRACHIGH;
+	}
+      high >>= 1;
+    }
+  while (high < IMPLICIT_1)
+    {
+      tmp->normal_exp--;
+
+      high <<= 1;
+      if (low & FRACHIGH)
+	high |= 1;
+      low <<= 1;
+    }
+  /* rounding is tricky. if we only round if it won't make us round later.  */
+#if 0
+  if (low & FRACHIGH2)
+    {
+      if (((high & GARDMASK) != GARDMSB)
+	  && (((high + 1) & GARDMASK) == GARDMSB))
+	{
+	  /* don't round, it gets done again later.  */
+	}
+      else
+	{
+	  high++;
+	}
+    }
+#endif
+  if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB)
+    {
+      if (high & (1 << NGARDS))
+	{
+	  /* half way, so round to even */
+	  high += GARDROUND + 1;
+	}
+      else if (low)
+	{
+	  /* but we really weren't half way */
+	  high += GARDROUND + 1;
+	}
+    }
+  tmp->fraction.ll = high;
+  tmp->class = CLASS_NUMBER;
+  return tmp;
+}
+
+FLO_type
+multiply (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  fp_number_type tmp;
+  fp_number_type *res;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  res = _fpmul_parts (&a, &b, &tmp);
+
+  return pack_d (res);
+}
+#endif /* L_mul_sf || L_mul_df */
+
+#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
+static inline __attribute__ ((__always_inline__)) fp_number_type *
+_fpdiv_parts (fp_number_type * a,
+	      fp_number_type * b)
+{
+  fractype bit;
+  fractype numerator;
+  fractype denominator;
+  fractype quotient;
+
+  if (isnan (a))
+    {
+      return a;
+    }
+  if (isnan (b))
+    {
+      return b;
+    }
+
+  a->sign = a->sign ^ b->sign;
+
+  if (isinf (a) || iszero (a))
+    {
+      if (a->class == b->class)
+	return nan ();
+      return a;
+    }
+
+  if (isinf (b))
+    {
+      a->fraction.ll = 0;
+      a->normal_exp = 0;
+      return a;
+    }
+  if (iszero (b))
+    {
+      a->class = CLASS_INFINITY;
+      return a;
+    }
+
+  /* Calculate the mantissa by multiplying both 64bit numbers to get a
+     128 bit number */
+  {
+    /* quotient =
+       ( numerator / denominator) * 2^(numerator exponent -  denominator exponent)
+     */
+
+    a->normal_exp = a->normal_exp - b->normal_exp;
+    numerator = a->fraction.ll;
+    denominator = b->fraction.ll;
+
+    if (numerator < denominator)
+      {
+	/* Fraction will be less than 1.0 */
+	numerator *= 2;
+	a->normal_exp--;
+      }
+    bit = IMPLICIT_1;
+    quotient = 0;
+    /* ??? Does divide one bit at a time.  Optimize.  */
+    while (bit)
+      {
+	if (numerator >= denominator)
+	  {
+	    quotient |= bit;
+	    numerator -= denominator;
+	  }
+	bit >>= 1;
+	numerator *= 2;
+      }
+
+    if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB)
+      {
+	if (quotient & (1 << NGARDS))
+	  {
+	    /* half way, so round to even */
+	    quotient += GARDROUND + 1;
+	  }
+	else if (numerator)
+	  {
+	    /* but we really weren't half way, more bits exist */
+	    quotient += GARDROUND + 1;
+	  }
+      }
+
+    a->fraction.ll = quotient;
+    return (a);
+  }
+}
+
+FLO_type
+divide (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  fp_number_type *res;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  res = _fpdiv_parts (&a, &b);
+
+  return pack_d (res);
+}
+#endif /* L_div_sf || L_div_df */
+
+#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \
+    || defined(L_fpcmp_parts_tf)
+/* according to the demo, fpcmp returns a comparison with 0... thus
+   a<b -> -1
+   a==b -> 0
+   a>b -> +1
+ */
+
+int
+__fpcmp_parts (fp_number_type * a, fp_number_type * b)
+{
+#if 0
+  /* either nan -> unordered. Must be checked outside of this routine.  */
+  if (isnan (a) && isnan (b))
+    {
+      return 1;			/* still unordered! */
+    }
+#endif
+
+  if (isnan (a) || isnan (b))
+    {
+      return 1;			/* how to indicate unordered compare? */
+    }
+  if (isinf (a) && isinf (b))
+    {
+      /* +inf > -inf, but +inf != +inf */
+      /* b    \a| +inf(0)| -inf(1)
+       ______\+--------+--------
+       +inf(0)| a==b(0)| a<b(-1)
+       -------+--------+--------
+       -inf(1)| a>b(1) | a==b(0)
+       -------+--------+--------
+       So since unordered must be nonzero, just line up the columns...
+       */
+      return b->sign - a->sign;
+    }
+  /* but not both...  */
+  if (isinf (a))
+    {
+      return a->sign ? -1 : 1;
+    }
+  if (isinf (b))
+    {
+      return b->sign ? 1 : -1;
+    }
+  if (iszero (a) && iszero (b))
+    {
+      return 0;
+    }
+  if (iszero (a))
+    {
+      return b->sign ? 1 : -1;
+    }
+  if (iszero (b))
+    {
+      return a->sign ? -1 : 1;
+    }
+  /* now both are "normal".  */
+  if (a->sign != b->sign)
+    {
+      /* opposite signs */
+      return a->sign ? -1 : 1;
+    }
+  /* same sign; exponents? */
+  if (a->normal_exp > b->normal_exp)
+    {
+      return a->sign ? -1 : 1;
+    }
+  if (a->normal_exp < b->normal_exp)
+    {
+      return a->sign ? 1 : -1;
+    }
+  /* same exponents; check size.  */
+  if (a->fraction.ll > b->fraction.ll)
+    {
+      return a->sign ? -1 : 1;
+    }
+  if (a->fraction.ll < b->fraction.ll)
+    {
+      return a->sign ? 1 : -1;
+    }
+  /* after all that, they're equal.  */
+  return 0;
+}
+#endif
+
+#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf)
+CMPtype
+compare (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  return __fpcmp_parts (&a, &b);
+}
+#endif /* L_compare_sf || L_compare_df */
+
+#ifndef US_SOFTWARE_GOFAST
+
+/* These should be optimized for their specific tasks someday.  */
+
+#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf)
+CMPtype
+_eq_f2 (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  if (isnan (&a) || isnan (&b))
+    return 1;			/* false, truth == 0 */
+
+  return __fpcmp_parts (&a, &b) ;
+}
+#endif /* L_eq_sf || L_eq_df */
+
+#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf)
+CMPtype
+_ne_f2 (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  if (isnan (&a) || isnan (&b))
+    return 1;			/* true, truth != 0 */
+
+  return  __fpcmp_parts (&a, &b) ;
+}
+#endif /* L_ne_sf || L_ne_df */
+
+#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf)
+CMPtype
+_gt_f2 (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  if (isnan (&a) || isnan (&b))
+    return -1;			/* false, truth > 0 */
+
+  return __fpcmp_parts (&a, &b);
+}
+#endif /* L_gt_sf || L_gt_df */
+
+#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf)
+CMPtype
+_ge_f2 (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  if (isnan (&a) || isnan (&b))
+    return -1;			/* false, truth >= 0 */
+  return __fpcmp_parts (&a, &b) ;
+}
+#endif /* L_ge_sf || L_ge_df */
+
+#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf)
+CMPtype
+_lt_f2 (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  if (isnan (&a) || isnan (&b))
+    return 1;			/* false, truth < 0 */
+
+  return __fpcmp_parts (&a, &b);
+}
+#endif /* L_lt_sf || L_lt_df */
+
+#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf)
+CMPtype
+_le_f2 (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  if (isnan (&a) || isnan (&b))
+    return 1;			/* false, truth <= 0 */
+
+  return __fpcmp_parts (&a, &b) ;
+}
+#endif /* L_le_sf || L_le_df */
+
+#endif /* ! US_SOFTWARE_GOFAST */
+
+#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf)
+CMPtype
+_unord_f2 (FLO_type arg_a, FLO_type arg_b)
+{
+  fp_number_type a;
+  fp_number_type b;
+  FLO_union_type au, bu;
+
+  au.value = arg_a;
+  bu.value = arg_b;
+
+  unpack_d (&au, &a);
+  unpack_d (&bu, &b);
+
+  return (isnan (&a) || isnan (&b));
+}
+#endif /* L_unord_sf || L_unord_df */
+
+#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf)
+FLO_type
+si_to_float (SItype arg_a)
+{
+  fp_number_type in;
+
+  in.class = CLASS_NUMBER;
+  in.sign = arg_a < 0;
+  if (!arg_a)
+    {
+      in.class = CLASS_ZERO;
+    }
+  else
+    {
+      in.normal_exp = FRACBITS + NGARDS;
+      if (in.sign) 
+	{
+	  /* Special case for minint, since there is no +ve integer
+	     representation for it */
+	  if (arg_a == (- MAX_SI_INT - 1))
+	    {
+	      return (FLO_type)(- MAX_SI_INT - 1);
+	    }
+	  in.fraction.ll = (-arg_a);
+	}
+      else
+	in.fraction.ll = arg_a;
+
+      while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
+	{
+	  in.fraction.ll <<= 1;
+	  in.normal_exp -= 1;
+	}
+    }
+  return pack_d (&in);
+}
+#endif /* L_si_to_sf || L_si_to_df */
+
+#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf)
+FLO_type
+usi_to_float (USItype arg_a)
+{
+  fp_number_type in;
+
+  in.sign = 0;
+  if (!arg_a)
+    {
+      in.class = CLASS_ZERO;
+    }
+  else
+    {
+      in.class = CLASS_NUMBER;
+      in.normal_exp = FRACBITS + NGARDS;
+      in.fraction.ll = arg_a;
+
+      while (in.fraction.ll > ((fractype)1 << (FRACBITS + NGARDS)))
+        {
+          in.fraction.ll >>= 1;
+          in.normal_exp += 1;
+        }
+      while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
+	{
+	  in.fraction.ll <<= 1;
+	  in.normal_exp -= 1;
+	}
+    }
+  return pack_d (&in);
+}
+#endif
+
+#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si)
+SItype
+float_to_si (FLO_type arg_a)
+{
+  fp_number_type a;
+  SItype tmp;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &a);
+
+  if (iszero (&a))
+    return 0;
+  if (isnan (&a))
+    return 0;
+  /* get reasonable MAX_SI_INT...  */
+  if (isinf (&a))
+    return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
+  /* it is a number, but a small one */
+  if (a.normal_exp < 0)
+    return 0;
+  if (a.normal_exp > BITS_PER_SI - 2)
+    return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
+  tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
+  return a.sign ? (-tmp) : (tmp);
+}
+#endif /* L_sf_to_si || L_df_to_si */
+
+#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi)
+#if defined US_SOFTWARE_GOFAST || defined(L_tf_to_usi)
+/* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines,
+   we also define them for GOFAST because the ones in libgcc2.c have the
+   wrong names and I'd rather define these here and keep GOFAST CYG-LOC's
+   out of libgcc2.c.  We can't define these here if not GOFAST because then
+   there'd be duplicate copies.  */
+
+USItype
+float_to_usi (FLO_type arg_a)
+{
+  fp_number_type a;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &a);
+
+  if (iszero (&a))
+    return 0;
+  if (isnan (&a))
+    return 0;
+  /* it is a negative number */
+  if (a.sign)
+    return 0;
+  /* get reasonable MAX_USI_INT...  */
+  if (isinf (&a))
+    return MAX_USI_INT;
+  /* it is a number, but a small one */
+  if (a.normal_exp < 0)
+    return 0;
+  if (a.normal_exp > BITS_PER_SI - 1)
+    return MAX_USI_INT;
+  else if (a.normal_exp > (FRACBITS + NGARDS))
+    return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS));
+  else
+    return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
+}
+#endif /* US_SOFTWARE_GOFAST */
+#endif /* L_sf_to_usi || L_df_to_usi */
+
+#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf)
+FLO_type
+negate (FLO_type arg_a)
+{
+  fp_number_type a;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &a);
+
+  flip_sign (&a);
+  return pack_d (&a);
+}
+#endif /* L_negate_sf || L_negate_df */
+
+#ifdef FLOAT
+
+#if defined(L_make_sf)
+SFtype
+__make_fp(fp_class_type class,
+	     unsigned int sign,
+	     int exp, 
+	     USItype frac)
+{
+  fp_number_type in;
+
+  in.class = class;
+  in.sign = sign;
+  in.normal_exp = exp;
+  in.fraction.ll = frac;
+  return pack_d (&in);
+}
+#endif /* L_make_sf */
+
+#ifndef FLOAT_ONLY
+
+/* This enables one to build an fp library that supports float but not double.
+   Otherwise, we would get an undefined reference to __make_dp.
+   This is needed for some 8-bit ports that can't handle well values that
+   are 8-bytes in size, so we just don't support double for them at all.  */
+
+#if defined(L_sf_to_df)
+DFtype
+sf_to_df (SFtype arg_a)
+{
+  fp_number_type in;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &in);
+
+  return __make_dp (in.class, in.sign, in.normal_exp,
+		    ((UDItype) in.fraction.ll) << F_D_BITOFF);
+}
+#endif /* L_sf_to_df */
+
+#if defined(L_sf_to_tf) && defined(TMODES)
+TFtype
+sf_to_tf (SFtype arg_a)
+{
+  fp_number_type in;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &in);
+
+  return __make_tp (in.class, in.sign, in.normal_exp,
+		    ((UTItype) in.fraction.ll) << F_T_BITOFF);
+}
+#endif /* L_sf_to_df */
+
+#endif /* ! FLOAT_ONLY */
+#endif /* FLOAT */
+
+#ifndef FLOAT
+
+extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype);
+
+#if defined(L_make_df)
+DFtype
+__make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac)
+{
+  fp_number_type in;
+
+  in.class = class;
+  in.sign = sign;
+  in.normal_exp = exp;
+  in.fraction.ll = frac;
+  return pack_d (&in);
+}
+#endif /* L_make_df */
+
+#if defined(L_df_to_sf)
+SFtype
+df_to_sf (DFtype arg_a)
+{
+  fp_number_type in;
+  USItype sffrac;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &in);
+
+  sffrac = in.fraction.ll >> F_D_BITOFF;
+
+  /* We set the lowest guard bit in SFFRAC if we discarded any non
+     zero bits.  */
+  if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0)
+    sffrac |= 1;
+
+  return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
+}
+#endif /* L_df_to_sf */
+
+#if defined(L_df_to_tf) && defined(TMODES) \
+    && !defined(FLOAT) && !defined(TFLOAT)
+TFtype
+df_to_tf (DFtype arg_a)
+{
+  fp_number_type in;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &in);
+
+  return __make_tp (in.class, in.sign, in.normal_exp,
+		    ((UTItype) in.fraction.ll) << D_T_BITOFF);
+}
+#endif /* L_sf_to_df */
+
+#ifdef TFLOAT
+#if defined(L_make_tf)
+TFtype
+__make_tp(fp_class_type class,
+	     unsigned int sign,
+	     int exp, 
+	     UTItype frac)
+{
+  fp_number_type in;
+
+  in.class = class;
+  in.sign = sign;
+  in.normal_exp = exp;
+  in.fraction.ll = frac;
+  return pack_d (&in);
+}
+#endif /* L_make_tf */
+
+#if defined(L_tf_to_df)
+DFtype
+tf_to_df (TFtype arg_a)
+{
+  fp_number_type in;
+  UDItype sffrac;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &in);
+
+  sffrac = in.fraction.ll >> D_T_BITOFF;
+
+  /* We set the lowest guard bit in SFFRAC if we discarded any non
+     zero bits.  */
+  if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0)
+    sffrac |= 1;
+
+  return __make_dp (in.class, in.sign, in.normal_exp, sffrac);
+}
+#endif /* L_tf_to_df */
+
+#if defined(L_tf_to_sf)
+SFtype
+tf_to_sf (TFtype arg_a)
+{
+  fp_number_type in;
+  USItype sffrac;
+  FLO_union_type au;
+
+  au.value = arg_a;
+  unpack_d (&au, &in);
+
+  sffrac = in.fraction.ll >> F_T_BITOFF;
+
+  /* We set the lowest guard bit in SFFRAC if we discarded any non
+     zero bits.  */
+  if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0)
+    sffrac |= 1;
+
+  return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
+}
+#endif /* L_tf_to_sf */
+#endif /* TFLOAT */
+
+#endif /* ! FLOAT */
+#endif /* !EXTENDED_FLOAT_STUBS */
--- gcc-3.4.3/gcc/config/nios2/nios2-protos.h
+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-protos.h
@@ -0,0 +1,70 @@
+/* Subroutines for assembler code output for Altera NIOS 2G NIOS2 version.
+   Copyright (C) 2003 Altera 
+   Contributed by Jonah Graham (jgraham@altera.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+extern void dump_frame_size (FILE *);
+extern HOST_WIDE_INT compute_frame_size (void);
+extern int nios2_initial_elimination_offset (int, int);
+extern void override_options (void);
+extern void optimization_options (int, int);
+extern int nios2_can_use_return_insn (void);
+extern void expand_prologue (void);
+extern void expand_epilogue (bool);
+extern void function_profiler (FILE *, int);
+
+
+#ifdef RTX_CODE
+extern int nios2_legitimate_address (rtx, enum machine_mode, int);
+extern void nios2_print_operand (FILE *, rtx, int);
+extern void nios2_print_operand_address (FILE *, rtx);
+
+extern int nios2_emit_move_sequence (rtx *, enum machine_mode);
+extern int nios2_emit_expensive_div (rtx *, enum machine_mode);
+
+extern void gen_int_relational (enum rtx_code, rtx, rtx, rtx, rtx);
+extern void gen_conditional_move (rtx *, enum machine_mode);
+extern const char *asm_output_opcode (FILE *, const char *);
+
+/* predicates */
+extern int arith_operand (rtx, enum machine_mode);
+extern int uns_arith_operand (rtx, enum machine_mode);
+extern int logical_operand (rtx, enum machine_mode);
+extern int shift_operand (rtx, enum machine_mode);
+extern int reg_or_0_operand (rtx, enum machine_mode);
+extern int equality_op (rtx, enum machine_mode);
+extern int custom_insn_opcode (rtx, enum machine_mode);
+extern int rdwrctl_operand (rtx, enum machine_mode);
+
+# ifdef HAVE_MACHINE_MODES
+#  if defined TREE_CODE
+extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
+extern rtx function_arg (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
+extern int function_arg_partial_nregs (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
+extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
+extern int nios2_setup_incoming_varargs (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
+
+#  endif /* TREE_CODE */
+# endif	/* HAVE_MACHINE_MODES */
+#endif
+
+#ifdef TREE_CODE
+extern int nios2_return_in_memory (tree);
+
+#endif /* TREE_CODE */
--- gcc-3.4.3/gcc/config/nios2/nios2.c
+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.c
@@ -0,0 +1,2853 @@
+/* Subroutines for assembler code output for Altera NIOS 2G NIOS2 version.
+   Copyright (C) 2003 Altera
+   Contributed by Jonah Graham (jgraham@altera.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#include <stdio.h>
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "tree.h"
+#include "tm_p.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "output.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "recog.h"
+#include "expr.h"
+#include "toplev.h"
+#include "basic-block.h"
+#include "function.h"
+#include "ggc.h"
+#include "reload.h"
+#include "debug.h"
+#include "optabs.h"
+#include "target.h"
+#include "target-def.h"
+
+/* local prototypes */
+static bool nios2_rtx_costs (rtx, int, int, int *);
+
+static void nios2_asm_function_prologue (FILE *, HOST_WIDE_INT);
+static int nios2_use_dfa_pipeline_interface (void);
+static int nios2_issue_rate (void);
+static struct machine_function *nios2_init_machine_status (void);
+static bool nios2_in_small_data_p (tree);
+static rtx save_reg (int, HOST_WIDE_INT, rtx);
+static rtx restore_reg (int, HOST_WIDE_INT);
+static unsigned int nios2_section_type_flags (tree, const char *, int);
+static void nios2_init_builtins (void);
+static rtx nios2_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
+static bool nios2_function_ok_for_sibcall (tree, tree);
+static void nios2_encode_section_info (tree, rtx, int);
+
+/* Initialize the GCC target structure.  */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue
+
+#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
+#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE \
+ nios2_use_dfa_pipeline_interface
+#undef TARGET_SCHED_ISSUE_RATE
+#define TARGET_SCHED_ISSUE_RATE nios2_issue_rate
+#undef TARGET_IN_SMALL_DATA_P
+#define TARGET_IN_SMALL_DATA_P nios2_in_small_data_p
+#undef  TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO nios2_encode_section_info
+#undef  TARGET_SECTION_TYPE_FLAGS
+#define TARGET_SECTION_TYPE_FLAGS  nios2_section_type_flags
+
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS nios2_init_builtins
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN nios2_expand_builtin
+
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL nios2_function_ok_for_sibcall
+
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS nios2_rtx_costs
+
+
+struct gcc_target targetm = TARGET_INITIALIZER;
+
+
+
+/* Threshold for data being put into the small data/bss area, instead
+   of the normal data area (references to the small data/bss area take
+   1 instruction, and use the global pointer, references to the normal
+   data area takes 2 instructions).  */
+unsigned HOST_WIDE_INT nios2_section_threshold = NIOS2_DEFAULT_GVALUE;
+
+
+/* Structure to be filled in by compute_frame_size with register
+   save masks, and offsets for the current function.  */
+
+struct nios2_frame_info
+GTY (())
+{
+  long total_size;		/* # bytes that the entire frame takes up */
+  long var_size;		/* # bytes that variables take up */
+  long args_size;		/* # bytes that outgoing arguments take up */
+  int save_reg_size;		/* # bytes needed to store gp regs */
+  int save_reg_rounded;		/* # bytes needed to store gp regs */
+  long save_regs_offset;	/* offset from new sp to store gp registers */
+  int initialized;		/* != 0 if frame size already calculated */
+  int num_regs;			/* number of gp registers saved */
+};
+
+struct machine_function
+GTY (())
+{
+
+  /* Current frame information, calculated by compute_frame_size.  */
+  struct nios2_frame_info frame;
+};
+
+
+/***************************************
+ * Section encodings
+ ***************************************/
+
+
+
+
+
+/***************************************
+ * Stack Layout and Calling Conventions
+ ***************************************/
+
+
+#define TOO_BIG_OFFSET(X) ((X) > ((1 << 15) - 1))
+#define TEMP_REG_NUM 8
+
+static void
+nios2_asm_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
+{
+  if (flag_verbose_asm || flag_debug_asm)
+    {
+      compute_frame_size ();
+      dump_frame_size (file);
+    }
+}
+
+static rtx
+save_reg (int regno, HOST_WIDE_INT offset, rtx cfa_store_reg)
+{
+  rtx insn, stack_slot;
+
+  stack_slot = gen_rtx_PLUS (SImode,
+			     cfa_store_reg,
+			     GEN_INT (offset));
+
+  insn = emit_insn (gen_rtx_SET (SImode,
+				 gen_rtx_MEM (SImode, stack_slot),
+				 gen_rtx_REG (SImode, regno)));
+
+  RTX_FRAME_RELATED_P (insn) = 1;
+
+  return insn;
+}
+
+static rtx
+restore_reg (int regno, HOST_WIDE_INT offset)
+{
+  rtx insn, stack_slot;
+
+  if (TOO_BIG_OFFSET (offset))
+    {
+      stack_slot = gen_rtx_REG (SImode, TEMP_REG_NUM);
+      insn = emit_insn (gen_rtx_SET (SImode,
+				     stack_slot,
+				     GEN_INT (offset)));
+
+      insn = emit_insn (gen_rtx_SET (SImode,
+				     stack_slot,
+                                     gen_rtx_PLUS (SImode,
+				                   stack_slot,
+				                   stack_pointer_rtx)));
+    }
+  else
+    {
+      stack_slot = gen_rtx_PLUS (SImode,
+			         stack_pointer_rtx,
+				 GEN_INT (offset));
+    }
+
+  stack_slot = gen_rtx_MEM (SImode, stack_slot);
+
+  insn = emit_move_insn (gen_rtx_REG (SImode, regno), stack_slot);
+
+  return insn;
+}
+
+
+/* There are two possible paths for prologue expansion,
+- the first is if the total frame size is < 2^15-1. In that
+case all the immediates will fit into the 16-bit immediate
+fields.
+- the second is when the frame size is too big, in that
+case an additional temporary register is used, first 
+as a cfa_temp to offset the sp, second as the cfa_store
+register.
+
+See the comment above dwarf2out_frame_debug_expr in 
+dwarf2out.c for more explanation of the "rules."
+
+
+Case 1:
+Rule #  Example Insn                       Effect
+2  	addi	sp, sp, -total_frame_size  cfa.reg=sp, cfa.offset=total_frame_size
+                                           cfa_store.reg=sp, cfa_store.offset=total_frame_size
+12  	stw	ra, offset(sp)		   
+12  	stw	r16, offset(sp)
+1  	mov	fp, sp
+  
+Case 2: 
+Rule #  Example Insn                       Effect
+6 	movi	r8, total_frame_size       cfa_temp.reg=r8, cfa_temp.offset=total_frame_size
+2  	sub	sp, sp, r8                 cfa.reg=sp, cfa.offset=total_frame_size
+                                           cfa_store.reg=sp, cfa_store.offset=total_frame_size
+5   	add	r8, r8, sp                 cfa_store.reg=r8, cfa_store.offset=0
+12  	stw	ra, offset(r8)
+12  	stw	r16, offset(r8)
+1  	mov	fp, sp
+
+*/
+
+void
+expand_prologue ()
+{
+  int i;
+  HOST_WIDE_INT total_frame_size;
+  int cfa_store_offset;
+  rtx insn;
+  rtx cfa_store_reg = 0;
+
+  total_frame_size = compute_frame_size ();
+
+  if (total_frame_size)
+    {
+
+      if (TOO_BIG_OFFSET (total_frame_size)) 
+	{
+	    /* cfa_temp and cfa_store_reg are the same register,
+	       cfa_store_reg overwrites cfa_temp */
+	    cfa_store_reg = gen_rtx_REG (SImode, TEMP_REG_NUM);
+	    insn = emit_insn (gen_rtx_SET (SImode,
+					   cfa_store_reg,
+					   GEN_INT (total_frame_size)));
+
+	    RTX_FRAME_RELATED_P (insn) = 1;
+
+
+	    insn = gen_rtx_SET (SImode,
+				stack_pointer_rtx,
+				gen_rtx_MINUS (SImode,
+					       stack_pointer_rtx,
+					       cfa_store_reg));
+
+	    insn = emit_insn (insn);
+	    RTX_FRAME_RELATED_P (insn) = 1;
+
+
+	    /* if there are no registers to save, I don't need to
+	       create a cfa_store */
+	    if (cfun->machine->frame.save_reg_size) 
+	      {
+		insn = gen_rtx_SET (SImode,
+				    cfa_store_reg,
+				    gen_rtx_PLUS (SImode,
+						  cfa_store_reg,
+						  stack_pointer_rtx));
+
+		insn = emit_insn (insn);
+		RTX_FRAME_RELATED_P (insn) = 1;
+	      }
+
+	    cfa_store_offset 
+	      = total_frame_size 
+		- (cfun->machine->frame.save_regs_offset
+		   + cfun->machine->frame.save_reg_rounded);
+	}
+      else
+	{
+	    insn = gen_rtx_SET (SImode,
+				stack_pointer_rtx,
+				gen_rtx_PLUS (SImode,
+					      stack_pointer_rtx,
+					      GEN_INT (-total_frame_size)));
+	    insn = emit_insn (insn);
+	    RTX_FRAME_RELATED_P (insn) = 1;
+
+	    cfa_store_reg = stack_pointer_rtx;
+	    cfa_store_offset 
+	      = cfun->machine->frame.save_regs_offset
+		+ cfun->machine->frame.save_reg_rounded;
+	}
+    }
+
+  if (MUST_SAVE_REGISTER (RA_REGNO))
+    {
+      cfa_store_offset -= 4;
+      save_reg (RA_REGNO, cfa_store_offset, cfa_store_reg);
+    }
+  if (MUST_SAVE_REGISTER (FP_REGNO))
+    {
+      cfa_store_offset -= 4;
+      save_reg (FP_REGNO, cfa_store_offset, cfa_store_reg);
+    }
+
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    {
+      if (MUST_SAVE_REGISTER (i) && i != FP_REGNO && i != RA_REGNO)
+	{
+	  cfa_store_offset -= 4;
+	  save_reg (i, cfa_store_offset, cfa_store_reg);
+	}
+    }
+
+  if (frame_pointer_needed)
+    {
+      insn = emit_insn (gen_rtx_SET (SImode,
+				     gen_rtx_REG (SImode, FP_REGNO),
+				     gen_rtx_REG (SImode, SP_REGNO)));
+
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  /* If we are profiling, make sure no instructions are scheduled before
+     the call to mcount.  */
+  if (current_function_profile)
+    emit_insn (gen_blockage ());
+}
+
+void
+expand_epilogue (bool sibcall_p)
+{
+  rtx insn;
+  int i;
+  HOST_WIDE_INT total_frame_size;
+  int register_store_offset;
+
+  total_frame_size = compute_frame_size ();
+
+  if (!sibcall_p && nios2_can_use_return_insn ())
+    {
+      insn = emit_jump_insn (gen_return ());
+      return;
+    }
+
+  emit_insn (gen_blockage ());
+
+  register_store_offset =
+    cfun->machine->frame.save_regs_offset +
+    cfun->machine->frame.save_reg_rounded;
+
+  if (MUST_SAVE_REGISTER (RA_REGNO))
+    {
+      register_store_offset -= 4;
+      restore_reg (RA_REGNO, register_store_offset);
+    }
+
+  if (MUST_SAVE_REGISTER (FP_REGNO))
+    {
+      register_store_offset -= 4;
+      restore_reg (FP_REGNO, register_store_offset);
+    }
+
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    {
+      if (MUST_SAVE_REGISTER (i) && i != FP_REGNO && i != RA_REGNO)
+	{
+	  register_store_offset -= 4;
+	  restore_reg (i, register_store_offset);
+	}
+    }
+
+  if (total_frame_size)
+    {
+      rtx sp_adjust;
+
+      if (TOO_BIG_OFFSET (total_frame_size))
+        {
+	  sp_adjust = gen_rtx_REG (SImode, TEMP_REG_NUM);
+	  insn = emit_insn (gen_rtx_SET (SImode,
+					 sp_adjust,
+					 GEN_INT (total_frame_size)));
+
+      	}
+      else
+        {
+	  sp_adjust = GEN_INT (total_frame_size);
+	}
+
+      insn = gen_rtx_SET (SImode,
+			  stack_pointer_rtx,
+			  gen_rtx_PLUS (SImode,
+					stack_pointer_rtx,
+					sp_adjust));
+      insn = emit_insn (insn);
+    }
+
+
+  if (!sibcall_p)
+    {
+      insn = emit_jump_insn (gen_return_from_epilogue (gen_rtx (REG, Pmode,
+								RA_REGNO)));
+    }
+}
+
+
+bool
+nios2_function_ok_for_sibcall (tree a ATTRIBUTE_UNUSED, tree b ATTRIBUTE_UNUSED)
+{
+  return true;
+}
+
+
+
+
+
+/* ----------------------- *
+ * Profiling
+ * ----------------------- */
+
+void
+function_profiler (FILE *file, int labelno)
+{
+  fprintf (file, "\t%s mcount begin, label: .LP%d\n", 
+           ASM_COMMENT_START, labelno);
+  fprintf (file, "\tnextpc\tr8\n");
+  fprintf (file, "\tmov\tr9, ra\n");
+  fprintf (file, "\tmovhi\tr10, %%hiadj(.LP%d)\n", labelno);
+  fprintf (file, "\taddi\tr10, r10, %%lo(.LP%d)\n", labelno);
+  fprintf (file, "\tcall\tmcount\n");
+  fprintf (file, "\tmov\tra, r9\n");
+  fprintf (file, "\t%s mcount end\n", ASM_COMMENT_START);
+}
+
+
+/***************************************
+ * Stack Layout
+ ***************************************/
+
+
+void
+dump_frame_size (FILE *file)
+{
+  fprintf (file, "\t%s Current Frame Info\n", ASM_COMMENT_START);
+
+  fprintf (file, "\t%s total_size = %ld\n", ASM_COMMENT_START,
+	   cfun->machine->frame.total_size);
+  fprintf (file, "\t%s var_size = %ld\n", ASM_COMMENT_START,
+	   cfun->machine->frame.var_size);
+  fprintf (file, "\t%s args_size = %ld\n", ASM_COMMENT_START,
+	   cfun->machine->frame.args_size);
+  fprintf (file, "\t%s save_reg_size = %d\n", ASM_COMMENT_START,
+	   cfun->machine->frame.save_reg_size);
+  fprintf (file, "\t%s save_reg_rounded = %d\n", ASM_COMMENT_START,
+	   cfun->machine->frame.save_reg_rounded);
+  fprintf (file, "\t%s initialized = %d\n", ASM_COMMENT_START,
+	   cfun->machine->frame.initialized);
+  fprintf (file, "\t%s num_regs = %d\n", ASM_COMMENT_START,
+	   cfun->machine->frame.num_regs);
+  fprintf (file, "\t%s save_regs_offset = %ld\n", ASM_COMMENT_START,
+	   cfun->machine->frame.save_regs_offset);
+  fprintf (file, "\t%s current_function_is_leaf = %d\n", ASM_COMMENT_START,
+	   current_function_is_leaf);
+  fprintf (file, "\t%s frame_pointer_needed = %d\n", ASM_COMMENT_START,
+	   frame_pointer_needed);
+  fprintf (file, "\t%s pretend_args_size = %d\n", ASM_COMMENT_START,
+	   current_function_pretend_args_size);
+
+}
+
+
+/* Return the bytes needed to compute the frame pointer from the current
+   stack pointer.
+*/
+
+HOST_WIDE_INT
+compute_frame_size ()
+{
+  unsigned int regno;
+  HOST_WIDE_INT var_size;	/* # of var. bytes allocated */
+  HOST_WIDE_INT total_size;	/* # bytes that the entire frame takes up */
+  HOST_WIDE_INT save_reg_size;	/* # bytes needed to store callee save regs */
+  HOST_WIDE_INT save_reg_rounded;	
+    /* # bytes needed to store callee save regs (rounded) */
+  HOST_WIDE_INT out_args_size;	/* # bytes needed for outgoing args */
+
+  save_reg_size = 0;
+  var_size = STACK_ALIGN (get_frame_size ());
+  out_args_size = STACK_ALIGN (current_function_outgoing_args_size);
+
+  total_size = var_size + out_args_size;
+
+  /* Calculate space needed for gp registers.  */
+  for (regno = 0; regno <= FIRST_PSEUDO_REGISTER; regno++)
+    {
+      if (MUST_SAVE_REGISTER (regno))
+	{
+	  save_reg_size += 4;
+	}
+    }
+
+  save_reg_rounded = STACK_ALIGN (save_reg_size);
+  total_size += save_reg_rounded;
+
+  total_size += STACK_ALIGN (current_function_pretend_args_size);
+
+  /* Save other computed information.  */
+  cfun->machine->frame.total_size = total_size;
+  cfun->machine->frame.var_size = var_size;
+  cfun->machine->frame.args_size = current_function_outgoing_args_size;
+  cfun->machine->frame.save_reg_size = save_reg_size;
+  cfun->machine->frame.save_reg_rounded = save_reg_rounded;
+  cfun->machine->frame.initialized = reload_completed;
+  cfun->machine->frame.num_regs = save_reg_size / UNITS_PER_WORD;
+
+  cfun->machine->frame.save_regs_offset
+    = save_reg_rounded ? current_function_outgoing_args_size + var_size : 0;
+
+  return total_size;
+}
+
+
+int
+nios2_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED)
+{
+  int offset;
+
+  /* Set OFFSET to the offset from the stack pointer.  */
+  switch (from)
+    {
+    case FRAME_POINTER_REGNUM:
+      offset = 0;
+      break;
+
+    case ARG_POINTER_REGNUM:
+      compute_frame_size ();
+      offset = cfun->machine->frame.total_size;
+      offset -= current_function_pretend_args_size;
+      break;
+
+    case RETURN_ADDRESS_POINTER_REGNUM:
+      compute_frame_size ();
+      /* since the return address is always the first of the
+         saved registers, return the offset to the beginning
+         of the saved registers block */
+      offset = cfun->machine->frame.save_regs_offset;
+      break;
+
+    default:
+      abort ();
+    }
+
+  return offset;
+}
+
+/* Return nonzero if this function is known to have a null epilogue.
+   This allows the optimizer to omit jumps to jumps if no stack
+   was created.  */
+int
+nios2_can_use_return_insn ()
+{
+  if (!reload_completed)
+    return 0;
+
+  if (regs_ever_live[RA_REGNO] || current_function_profile)
+    return 0;
+
+  if (cfun->machine->frame.initialized)
+    return cfun->machine->frame.total_size == 0;
+
+  return compute_frame_size () == 0;
+}
+
+
+
+
+
+/***************************************
+ *
+ ***************************************/
+
+const char *nios2_sys_nosys_string;    /* for -msys=nosys */
+const char *nios2_sys_lib_string;    /* for -msys-lib= */
+const char *nios2_sys_crt0_string;    /* for -msys-crt0= */
+
+void
+override_options ()
+{
+  /* Function to allocate machine-dependent function status.  */
+  init_machine_status = &nios2_init_machine_status;
+
+  nios2_section_threshold 
+    = g_switch_set ? g_switch_value : NIOS2_DEFAULT_GVALUE;
+
+  if (nios2_sys_nosys_string && *nios2_sys_nosys_string)
+    {
+      error ("invalid option '-msys=nosys%s'", nios2_sys_nosys_string);
+    }
+
+  /* If we don't have mul, we don't have mulx either! */
+  if (!TARGET_HAS_MUL && TARGET_HAS_MULX) 
+    {
+      target_flags &= ~HAS_MULX_FLAG;
+    }
+
+}
+
+void
+optimization_options (int level, int size)
+{
+  if (level || size)
+    {
+      target_flags |= INLINE_MEMCPY_FLAG;
+    }
+
+  if (level >= 3 && !size)
+    {
+      target_flags |= FAST_SW_DIV_FLAG;
+    }
+}
+
+/* Allocate a chunk of memory for per-function machine-dependent data.  */
+static struct machine_function *
+nios2_init_machine_status ()
+{
+  return ((struct machine_function *)
+	  ggc_alloc_cleared (sizeof (struct machine_function)));
+}
+
+
+
+/*****************
+ * Describing Relative Costs of Operations
+ *****************/
+
+/* Compute a (partial) cost for rtx X.  Return true if the complete
+   cost has been computed, and false if subexpressions should be
+   scanned.  In either case, *TOTAL contains the cost result.  */
+
+
+
+static bool
+nios2_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total)
+{
+  switch (code)
+    {
+      case CONST_INT:
+	if (INTVAL (x) == 0)
+	  {
+	    *total = COSTS_N_INSNS (0);
+	    return true;
+	  }
+	else if (SMALL_INT (INTVAL (x))
+		|| SMALL_INT_UNSIGNED (INTVAL (x))
+		|| UPPER16_INT (INTVAL (x)))
+	  {
+	    *total = COSTS_N_INSNS (2);
+	    return true;
+	  }
+	else
+	  {
+	    *total = COSTS_N_INSNS (4);
+	    return true;
+	  }
+
+      case LABEL_REF:
+      case SYMBOL_REF:
+	/* ??? gp relative stuff will fit in here */
+	/* fall through */
+      case CONST:
+      case CONST_DOUBLE:
+	{
+	  *total = COSTS_N_INSNS (4);
+	  return true;
+	}
+
+      case MULT:
+	{
+	  *total = COSTS_N_INSNS (1);
+	  return false;
+	}
+      case SIGN_EXTEND:
+	{
+	  *total = COSTS_N_INSNS (3);
+	  return false;
+	}
+      case ZERO_EXTEND:
+	{
+	  *total = COSTS_N_INSNS (1);
+	  return false;
+	}
+
+    default:
+      return false;
+    }
+}
+
+
+/***************************************
+ * INSTRUCTION SUPPORT
+ *
+ * These functions are used within the Machine Description to
+ * handle common or complicated output and expansions from
+ * instructions.
+ ***************************************/
+
+int
+nios2_emit_move_sequence (rtx *operands, enum machine_mode mode)
+{
+  rtx to = operands[0];
+  rtx from = operands[1];
+
+  if (!register_operand (to, mode) && !reg_or_0_operand (from, mode))
+    {
+      if (no_new_pseudos)
+	internal_error ("Trying to force_reg no_new_pseudos == 1");
+      from = copy_to_mode_reg (mode, from);
+    }
+
+  operands[0] = to;
+  operands[1] = from;
+  return 0;
+}
+
+/* Divide Support */
+
+/*
+  If -O3 is used, we want to output a table lookup for
+  divides between small numbers (both num and den >= 0
+  and < 0x10). The overhead of this method in the worse
+  case is 40 bytes in the text section (10 insns) and
+  256 bytes in the data section. Additional divides do
+  not incur additional penalties in the data section.
+
+  Code speed is improved for small divides by about 5x
+  when using this method in the worse case (~9 cycles
+  vs ~45). And in the worse case divides not within the
+  table are penalized by about 10% (~5 cycles vs ~45).
+  However in the typical case the penalty is not as bad
+  because doing the long divide in only 45 cycles is
+  quite optimistic.
+
+  ??? It would be nice to have some benchmarks other
+  than Dhrystone to back this up.
+
+  This bit of expansion is to create this instruction
+  sequence as rtl.
+	or	$8, $4, $5
+	slli	$9, $4, 4
+	cmpgeui	$3, $8, 16
+	beq	$3, $0, .L3
+	or	$10, $9, $5
+	add	$12, $11, divide_table
+	ldbu	$2, 0($12)
+	br	.L1
+.L3:
+	call	slow_div
+.L1:
+#	continue here with result in $2
+
+  ??? Ideally I would like the emit libcall block to contain
+  all of this code, but I don't know how to do that. What it
+  means is that if the divide can be eliminated, it may not
+  completely disappear.
+
+  ??? The __divsi3_table label should ideally be moved out
+  of this block and into a global. If it is placed into the
+  sdata section we can save even more cycles by doing things
+  gp relative.
+*/
+int
+nios2_emit_expensive_div (rtx *operands, enum machine_mode mode)
+{
+  rtx or_result, shift_left_result;
+  rtx lookup_value;
+  rtx lab1, lab3;
+  rtx insns;
+  rtx libfunc;
+  rtx final_result;
+  rtx tmp;
+
+  /* it may look a little generic, but only SImode
+     is supported for now */
+  if (mode != SImode)
+    abort ();
+
+  libfunc = sdiv_optab->handlers[(int) SImode].libfunc;
+
+
+
+  lab1 = gen_label_rtx ();
+  lab3 = gen_label_rtx ();
+
+  or_result = expand_simple_binop (SImode, IOR,
+				   operands[1], operands[2],
+				   0, 0, OPTAB_LIB_WIDEN);
+
+  emit_cmp_and_jump_insns (or_result, GEN_INT (15), GTU, 0,
+			   GET_MODE (or_result), 0, lab3);
+  JUMP_LABEL (get_last_insn ()) = lab3;
+
+  shift_left_result = expand_simple_binop (SImode, ASHIFT,
+					   operands[1], GEN_INT (4),
+					   0, 0, OPTAB_LIB_WIDEN);
+
+  lookup_value = expand_simple_binop (SImode, IOR,
+				      shift_left_result, operands[2],
+				      0, 0, OPTAB_LIB_WIDEN);
+
+  convert_move (operands[0],
+		gen_rtx (MEM, QImode,
+			 gen_rtx (PLUS, SImode,
+				  lookup_value,
+				  gen_rtx_SYMBOL_REF (SImode, "__divsi3_table"))),
+		1);
+
+
+  tmp = emit_jump_insn (gen_jump (lab1));
+  JUMP_LABEL (tmp) = lab1;
+  emit_barrier ();
+
+  emit_label (lab3);
+  LABEL_NUSES (lab3) = 1;
+
+  start_sequence ();
+  final_result = emit_library_call_value (libfunc, NULL_RTX,
+					  LCT_CONST, SImode, 2,
+					  operands[1], SImode,
+					  operands[2], SImode);
+
+
+  insns = get_insns ();
+  end_sequence ();
+  emit_libcall_block (insns, operands[0], final_result,
+		      gen_rtx (DIV, SImode, operands[1], operands[2]));
+
+  emit_label (lab1);
+  LABEL_NUSES (lab1) = 1;
+  return 1;
+}
+
+/* Branches/Compares */
+
+/* the way of handling branches/compares
+   in gcc is heavily borrowed from MIPS */
+
+enum internal_test
+{
+  ITEST_EQ,
+  ITEST_NE,
+  ITEST_GT,
+  ITEST_GE,
+  ITEST_LT,
+  ITEST_LE,
+  ITEST_GTU,
+  ITEST_GEU,
+  ITEST_LTU,
+  ITEST_LEU,
+  ITEST_MAX
+};
+
+static enum internal_test map_test_to_internal_test (enum rtx_code);
+
+/* Cached operands, and operator to compare for use in set/branch/trap
+   on condition codes.  */
+rtx branch_cmp[2];
+enum cmp_type branch_type;
+
+/* Make normal rtx_code into something we can index from an array */
+
+static enum internal_test
+map_test_to_internal_test (enum rtx_code test_code)
+{
+  enum internal_test test = ITEST_MAX;
+
+  switch (test_code)
+    {
+    case EQ:
+      test = ITEST_EQ;
+      break;
+    case NE:
+      test = ITEST_NE;
+      break;
+    case GT:
+      test = ITEST_GT;
+      break;
+    case GE:
+      test = ITEST_GE;
+      break;
+    case LT:
+      test = ITEST_LT;
+      break;
+    case LE:
+      test = ITEST_LE;
+      break;
+    case GTU:
+      test = ITEST_GTU;
+      break;
+    case GEU:
+      test = ITEST_GEU;
+      break;
+    case LTU:
+      test = ITEST_LTU;
+      break;
+    case LEU:
+      test = ITEST_LEU;
+      break;
+    default:
+      break;
+    }
+
+  return test;
+}
+
+/* Generate the code to compare (and possibly branch) two integer values
+   TEST_CODE is the comparison code we are trying to emulate 
+     (or implement directly)
+   RESULT is where to store the result of the comparison, 
+     or null to emit a branch
+   CMP0 CMP1 are the two comparison operands
+   DESTINATION is the destination of the branch, or null to only compare
+   */
+
+void
+gen_int_relational (enum rtx_code test_code, /* relational test (EQ, etc) */
+		    rtx result,		/* result to store comp. or 0 if branch */
+		    rtx cmp0,		/* first operand to compare */
+		    rtx cmp1,		/* second operand to compare */
+		    rtx destination)	/* destination of the branch, or 0 if compare */
+{
+  struct cmp_info
+  {
+    /* for register (or 0) compares */
+    enum rtx_code test_code_reg;	/* code to use in instruction (LT vs. LTU) */
+    int reverse_regs;		/* reverse registers in test */
+
+    /* for immediate compares */
+    enum rtx_code test_code_const;	
+         /* code to use in instruction (LT vs. LTU) */
+    int const_low;		/* low bound of constant we can accept */
+    int const_high;		/* high bound of constant we can accept */
+    int const_add;		/* constant to add */
+
+    /* generic info */
+    int unsignedp;		/* != 0 for unsigned comparisons.  */
+  };
+
+  static const struct cmp_info info[(int) ITEST_MAX] = {
+
+    {EQ, 0, EQ, -32768, 32767, 0, 0}, /* EQ  */
+    {NE, 0, NE, -32768, 32767, 0, 0}, /* NE  */
+
+    {LT, 1, GE, -32769, 32766, 1, 0}, /* GT  */
+    {GE, 0, GE, -32768, 32767, 0, 0}, /* GE  */
+    {LT, 0, LT, -32768, 32767, 0, 0}, /* LT  */
+    {GE, 1, LT, -32769, 32766, 1, 0}, /* LE  */
+
+    {LTU, 1, GEU, 0, 65534, 1, 0}, /* GTU */
+    {GEU, 0, GEU, 0, 65535, 0, 0}, /* GEU */
+    {LTU, 0, LTU, 0, 65535, 0, 0}, /* LTU */
+    {GEU, 1, LTU, 0, 65534, 1, 0}, /* LEU */
+  };
+
+  enum internal_test test;
+  enum machine_mode mode;
+  const struct cmp_info *p_info;
+  int branch_p;
+
+
+
+
+  test = map_test_to_internal_test (test_code);
+  if (test == ITEST_MAX)
+    abort ();
+
+  p_info = &info[(int) test];
+
+  mode = GET_MODE (cmp0);
+  if (mode == VOIDmode)
+    mode = GET_MODE (cmp1);
+
+  branch_p = (destination != 0);
+
+  /* We can't, under any circumstances, have const_ints in cmp0
+     ??? Actually we could have const0 */
+  if (GET_CODE (cmp0) == CONST_INT)
+    cmp0 = force_reg (mode, cmp0);
+
+  /* if the comparison is against an int not in legal range
+     move it into a register */
+  if (GET_CODE (cmp1) == CONST_INT)
+    {
+      HOST_WIDE_INT value = INTVAL (cmp1);
+
+      if (value < p_info->const_low || value > p_info->const_high)
+	cmp1 = force_reg (mode, cmp1);
+    }
+
+  /* Comparison to constants, may involve adding 1 to change a GT into GE.
+     Comparison between two registers, may involve switching operands.  */
+  if (GET_CODE (cmp1) == CONST_INT)
+    {
+      if (p_info->const_add != 0)
+	{
+	  HOST_WIDE_INT new = INTVAL (cmp1) + p_info->const_add;
+
+	  /* If modification of cmp1 caused overflow,
+	     we would get the wrong answer if we follow the usual path;
+	     thus, x > 0xffffffffU would turn into x > 0U.  */
+	  if ((p_info->unsignedp
+	       ? (unsigned HOST_WIDE_INT) new >
+	       (unsigned HOST_WIDE_INT) INTVAL (cmp1)
+	       : new > INTVAL (cmp1)) != (p_info->const_add > 0))
+	    {
+	      /* ??? This case can never happen with the current numbers,
+	         but I am paranoid and would rather an abort than
+	         a bug I will never find */
+	      abort ();
+	    }
+	  else
+	    cmp1 = GEN_INT (new);
+	}
+    }
+
+  else if (p_info->reverse_regs)
+    {
+      rtx temp = cmp0;
+      cmp0 = cmp1;
+      cmp1 = temp;
+    }
+
+
+
+  if (branch_p)
+    {
+      if (register_operand (cmp0, mode) && register_operand (cmp1, mode))
+	{
+	  rtx insn;
+	  rtx cond = gen_rtx (p_info->test_code_reg, mode, cmp0, cmp1);
+	  rtx label = gen_rtx_LABEL_REF (VOIDmode, destination);
+
+	  insn = gen_rtx_SET (VOIDmode, pc_rtx,
+			      gen_rtx_IF_THEN_ELSE (VOIDmode,
+						    cond, label, pc_rtx));
+	  emit_jump_insn (insn);
+	}
+      else
+	{
+	  rtx cond, label;
+
+	  result = gen_reg_rtx (mode);
+
+	  emit_move_insn (result,
+			  gen_rtx (p_info->test_code_const, mode, cmp0,
+				   cmp1));
+
+	  cond = gen_rtx (NE, mode, result, const0_rtx);
+	  label = gen_rtx_LABEL_REF (VOIDmode, destination);
+
+	  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
+				       gen_rtx_IF_THEN_ELSE (VOIDmode,
+							     cond,
+							     label, pc_rtx)));
+	}
+    }
+  else
+    {
+      if (register_operand (cmp0, mode) && register_operand (cmp1, mode))
+	{
+	  emit_move_insn (result,
+			  gen_rtx (p_info->test_code_reg, mode, cmp0, cmp1));
+	}
+      else
+	{
+	  emit_move_insn (result,
+			  gen_rtx (p_info->test_code_const, mode, cmp0,
+				   cmp1));
+	}
+    }
+
+}
+
+
+/* ??? For now conditional moves are only supported
+   when the mode of the operands being compared are
+   the same as the ones being moved */
+
+void
+gen_conditional_move (rtx *operands, enum machine_mode mode)
+{
+  rtx insn, cond;
+  rtx cmp_reg = gen_reg_rtx (mode);
+  enum rtx_code cmp_code = GET_CODE (operands[1]);
+  enum rtx_code move_code = EQ;
+
+  /* emit a comparison if it is not "simple".
+     Simple comparisons are X eq 0 and X ne 0 */
+  if ((cmp_code == EQ || cmp_code == NE) && branch_cmp[1] == const0_rtx)
+    {
+      cmp_reg = branch_cmp[0];
+      move_code = cmp_code;
+    }
+  else if ((cmp_code == EQ || cmp_code == NE) && branch_cmp[0] == const0_rtx)
+    {
+      cmp_reg = branch_cmp[1];
+      move_code = cmp_code == EQ ? NE : EQ;
+    }
+  else
+    gen_int_relational (cmp_code, cmp_reg, branch_cmp[0], branch_cmp[1],
+			NULL_RTX);
+
+  cond = gen_rtx (move_code, VOIDmode, cmp_reg, CONST0_RTX (mode));
+  insn = gen_rtx_SET (mode, operands[0],
+		      gen_rtx_IF_THEN_ELSE (mode,
+					    cond, operands[2], operands[3]));
+  emit_insn (insn);
+}
+
+/*******************
+ * Addressing Modes
+ *******************/
+
+int
+nios2_legitimate_address (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED, 
+                          int strict)
+{
+  int ret_val = 0;
+
+  switch (GET_CODE (operand))
+    {
+      /* direct.  */
+    case SYMBOL_REF:
+      if (SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (operand))
+        {
+          ret_val = 1;
+          break;
+	}
+      /* else, fall through */
+    case LABEL_REF:
+    case CONST_INT:
+    case CONST:
+    case CONST_DOUBLE:
+      /* ??? In here I need to add gp addressing */
+      ret_val = 0;
+
+      break;
+
+      /* Register indirect.  */
+    case REG:
+      ret_val = REG_OK_FOR_BASE_P2 (operand, strict);
+      break;
+
+      /* Register indirect with displacement */
+    case PLUS:
+      {
+	rtx op0 = XEXP (operand, 0);
+	rtx op1 = XEXP (operand, 1);
+
+	if (REG_P (op0) && REG_P (op1))
+	  ret_val = 0;
+	else if (REG_P (op0) && CONSTANT_P (op1))
+	  ret_val = REG_OK_FOR_BASE_P2 (op0, strict)
+	    && SMALL_INT (INTVAL (op1));
+	else if (REG_P (op1) && CONSTANT_P (op0))
+	  ret_val = REG_OK_FOR_BASE_P2 (op1, strict)
+	    && SMALL_INT (INTVAL (op0));
+	else
+	  ret_val = 0;
+      }
+      break;
+
+    default:
+      ret_val = 0;
+      break;
+    }
+
+  return ret_val;
+}
+
+/* Return true if EXP should be placed in the small data section.  */
+
+static bool
+nios2_in_small_data_p (tree exp)
+{
+  /* We want to merge strings, so we never consider them small data.  */
+  if (TREE_CODE (exp) == STRING_CST)
+    return false;
+
+  if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
+    {
+      const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
+      /* ??? these string names need moving into 
+         an array in some header file */
+      if (nios2_section_threshold > 0
+          && (strcmp (section, ".sbss") == 0
+	      || strncmp (section, ".sbss.", 6) == 0
+	      || strcmp (section, ".sdata") == 0
+	      || strncmp (section, ".sdata.", 7) == 0))
+	return true;
+    }
+  else if (TREE_CODE (exp) == VAR_DECL)
+    {
+      HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
+
+      /* If this is an incomplete type with size 0, then we can't put it
+         in sdata because it might be too big when completed.  */
+      if (size > 0 && size <= nios2_section_threshold)
+	return true;
+    }
+
+  return false;
+}
+
+static void
+nios2_encode_section_info (tree decl, rtx rtl, int first)
+{
+
+  rtx symbol;
+  int flags;
+
+  default_encode_section_info (decl, rtl, first);
+  
+  /* Careful not to prod global register variables.  */
+  if (GET_CODE (rtl) != MEM)
+    return;
+  symbol = XEXP (rtl, 0);
+  if (GET_CODE (symbol) != SYMBOL_REF)
+    return;
+
+  flags = SYMBOL_REF_FLAGS (symbol);
+    
+  /* We don't want weak variables to be addressed with gp in case they end up with
+     value 0 which is not within 2^15 of $gp */
+  if (DECL_P (decl) && DECL_WEAK (decl))
+    flags |= SYMBOL_FLAG_WEAK_DECL;
+
+  SYMBOL_REF_FLAGS (symbol) = flags;
+}
+
+
+static unsigned int
+nios2_section_type_flags (tree decl, const char *name, int reloc)
+{
+  unsigned int flags;
+
+  flags = default_section_type_flags (decl, name, reloc);
+
+  /* ??? these string names need moving into an array in some header file */
+  if (strcmp (name, ".sbss") == 0
+      || strncmp (name, ".sbss.", 6) == 0
+      || strcmp (name, ".sdata") == 0
+      || strncmp (name, ".sdata.", 7) == 0)
+    flags |= SECTION_SMALL;
+
+  return flags;
+}
+
+
+
+
+/*****************************************
+ * Defining the Output Assembler Language
+ *****************************************/
+
+/* -------------- *
+ * Output of Data
+ * -------------- */
+
+
+/* -------------------------------- *
+ * Output of Assembler Instructions
+ * -------------------------------- */
+
+
+/* print the operand OP to file stream
+   FILE modified by LETTER. LETTER
+   can be one of:
+     i: print "i" if OP is an immediate, except 0
+     o: print "io" if OP is volatile
+
+     z: for const0_rtx print $0 instead of 0
+     H: for %hiadj
+     L: for %lo
+     U: for upper half of 32 bit value
+ */
+
+void
+nios2_print_operand (FILE *file, rtx op, int letter)
+{
+
+  switch (letter)
+    {
+    case 'i':
+      if (CONSTANT_P (op) && (op != const0_rtx))
+	fprintf (file, "i");
+      return;
+
+    case 'o':
+      if (GET_CODE (op) == MEM
+          && ((MEM_VOLATILE_P (op) && !TARGET_CACHE_VOLATILE)
+              || TARGET_BYPASS_CACHE))
+	fprintf (file, "io");
+      return;
+
+    default:
+      break;
+    }
+
+  if (comparison_operator (op, VOIDmode))
+    {
+      if (letter == 0)
+	{
+	  fprintf (file, "%s", GET_RTX_NAME (GET_CODE (op)));
+	  return;
+	}
+    }
+
+
+  switch (GET_CODE (op))
+    {
+    case REG:
+      if (letter == 0 || letter == 'z')
+	{
+	  fprintf (file, "%s", reg_names[REGNO (op)]);
+	  return;
+	}
+
+    case CONST_INT:
+      if (INTVAL (op) == 0 && letter == 'z')
+	{
+	  fprintf (file, "zero");
+	  return;
+	}
+      else if (letter == 'U')
+	{
+	  HOST_WIDE_INT val = INTVAL (op);
+	  rtx new_op;
+	  val = (val / 65536) & 0xFFFF;
+	  new_op = GEN_INT (val);
+	  output_addr_const (file, new_op);
+	  return;
+	}
+
+      /* else, fall through */
+    case CONST:
+    case LABEL_REF:
+    case SYMBOL_REF:
+    case CONST_DOUBLE:
+      if (letter == 0 || letter == 'z')
+	{
+	  output_addr_const (file, op);
+	  return;
+	}
+      else if (letter == 'H')
+	{
+	  fprintf (file, "%%hiadj(");
+	  output_addr_const (file, op);
+	  fprintf (file, ")");
+	  return;
+	}
+      else if (letter == 'L')
+	{
+	  fprintf (file, "%%lo(");
+	  output_addr_const (file, op);
+	  fprintf (file, ")");
+	  return;
+	}
+
+
+    case SUBREG:
+    case MEM:
+      if (letter == 0)
+	{
+	  output_address (op);
+	  return;
+	}
+
+    case CODE_LABEL:
+      if (letter == 0)
+	{
+	  output_addr_const (file, op);
+	  return;
+	}
+
+    default:
+      break;
+    }
+
+  fprintf (stderr, "Missing way to print (%c) ", letter);
+  debug_rtx (op);
+  abort ();
+}
+
+static int gprel_constant (rtx);
+
+static int
+gprel_constant (rtx op)
+{
+  if (GET_CODE (op) == SYMBOL_REF
+      && SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (op))
+    {
+      return 1;
+    }
+  else if (GET_CODE (op) == CONST
+           && GET_CODE (XEXP (op, 0)) == PLUS)
+    {
+      return gprel_constant (XEXP (XEXP (op, 0), 0));
+    }
+  else
+    {
+      return 0;
+    }
+}
+
+void
+nios2_print_operand_address (FILE *file, rtx op)
+{
+  switch (GET_CODE (op))
+    {
+    case CONST:
+    case CONST_INT:
+    case LABEL_REF:
+    case CONST_DOUBLE:
+    case SYMBOL_REF:
+      if (gprel_constant (op))
+        {
+          fprintf (file, "%%gprel(");
+          output_addr_const (file, op);
+          fprintf (file, ")(%s)", reg_names[GP_REGNO]);
+          return;
+        }
+
+      break;
+
+    case PLUS:
+      {
+	rtx op0 = XEXP (op, 0);
+	rtx op1 = XEXP (op, 1);
+
+	if (REG_P (op0) && CONSTANT_P (op1))
+	  {
+	    output_addr_const (file, op1);
+	    fprintf (file, "(%s)", reg_names[REGNO (op0)]);
+	    return;
+	  }
+	else if (REG_P (op1) && CONSTANT_P (op0))
+	  {
+	    output_addr_const (file, op0);
+	    fprintf (file, "(%s)", reg_names[REGNO (op1)]);
+	    return;
+	  }
+      }
+      break;
+
+    case REG:
+      fprintf (file, "0(%s)", reg_names[REGNO (op)]);
+      return;
+
+    case MEM:
+      {
+	rtx base = XEXP (op, 0);
+	PRINT_OPERAND_ADDRESS (file, base);
+	return;
+      }
+    default:
+      break;
+    }
+
+  fprintf (stderr, "Missing way to print address\n");
+  debug_rtx (op);
+  abort ();
+}
+
+
+
+
+
+/****************************
+ * Predicates
+ ****************************/
+
+int
+arith_operand (rtx op, enum machine_mode mode)
+{
+  if (GET_CODE (op) == CONST_INT && SMALL_INT (INTVAL (op)))
+    return 1;
+
+  return register_operand (op, mode);
+}
+
+int
+uns_arith_operand (rtx op, enum machine_mode mode)
+{
+  if (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (INTVAL (op)))
+    return 1;
+
+  return register_operand (op, mode);
+}
+
+int
+logical_operand (rtx op, enum machine_mode mode)
+{
+  if (GET_CODE (op) == CONST_INT
+      && (SMALL_INT_UNSIGNED (INTVAL (op)) || UPPER16_INT (INTVAL (op))))
+    return 1;
+
+  return register_operand (op, mode);
+}
+
+int
+shift_operand (rtx op, enum machine_mode mode)
+{
+  if (GET_CODE (op) == CONST_INT && SHIFT_INT (INTVAL (op)))
+    return 1;
+
+  return register_operand (op, mode);
+}
+
+int
+rdwrctl_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return GET_CODE (op) == CONST_INT && RDWRCTL_INT (INTVAL (op));
+}
+
+/* Return truth value of whether OP is a register or the constant 0. */
+
+int
+reg_or_0_operand (rtx op, enum machine_mode mode)
+{
+  switch (GET_CODE (op))
+    {
+    case CONST_INT:
+      return INTVAL (op) == 0;
+
+    case CONST_DOUBLE:
+      return op == CONST0_RTX (mode);
+
+    default:
+      break;
+    }
+
+  return register_operand (op, mode);
+}
+
+
+int
+equality_op (rtx op, enum machine_mode mode)
+{
+  if (mode != GET_MODE (op))
+    return 0;
+
+  return GET_CODE (op) == EQ || GET_CODE (op) == NE;
+}
+
+int
+custom_insn_opcode (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return GET_CODE (op) == CONST_INT && CUSTOM_INSN_OPCODE (INTVAL (op));
+}
+
+
+
+
+
+
+
+/*****************************************************************************
+**
+** instruction scheduler
+**
+*****************************************************************************/
+static int
+nios2_use_dfa_pipeline_interface ()
+{
+  return 1;
+}
+
+
+static int
+nios2_issue_rate ()
+{
+#ifdef MAX_DFA_ISSUE_RATE
+  return MAX_DFA_ISSUE_RATE;
+#else
+  return 1;
+#endif
+}
+
+
+const char *
+asm_output_opcode (FILE *file ATTRIBUTE_UNUSED, 
+                   const char *ptr ATTRIBUTE_UNUSED)
+{
+  const char *p;
+
+  p = ptr;
+  return ptr;
+}
+
+
+
+/*****************************************************************************
+**
+** function arguments
+**
+*****************************************************************************/
+
+void
+init_cumulative_args (CUMULATIVE_ARGS *cum, 
+                      tree fntype ATTRIBUTE_UNUSED, 
+                      rtx libname ATTRIBUTE_UNUSED, 
+                      tree fndecl ATTRIBUTE_UNUSED, 
+                      int n_named_args ATTRIBUTE_UNUSED)
+{
+  cum->regs_used = 0;
+}
+
+
+/* Update the data in CUM to advance over an argument
+   of mode MODE and data type TYPE.
+   (TYPE is null for libcalls where that information may not be available.)  */
+
+void
+function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, 
+                      tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
+{
+  HOST_WIDE_INT param_size;
+
+  if (mode == BLKmode)
+    {
+      param_size = int_size_in_bytes (type);
+      if (param_size < 0)
+	internal_error
+	  ("Do not know how to handle large structs or variable length types");
+    }
+  else
+    {
+      param_size = GET_MODE_SIZE (mode);
+    }
+
+  /* convert to words (round up) */
+  param_size = (3 + param_size) / 4;
+
+  if (cum->regs_used + param_size > NUM_ARG_REGS)
+    {
+      cum->regs_used = NUM_ARG_REGS;
+    }
+  else
+    {
+      cum->regs_used += param_size;
+    }
+
+  return;
+}
+
+/* Define where to put the arguments to a function.  Value is zero to
+   push the argument on the stack, or a hard register in which to
+   store the argument.
+
+   MODE is the argument's machine mode.
+   TYPE is the data type of the argument (as a tree).
+   This is null for libcalls where that information may
+   not be available.
+   CUM is a variable of type CUMULATIVE_ARGS which gives info about
+   the preceding args and about the function being called.
+   NAMED is nonzero if this argument is a named parameter
+   (otherwise it is an extra parameter matching an ellipsis).  */
+rtx
+function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, 
+              tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
+{
+  rtx return_rtx = NULL_RTX;
+
+  if (cum->regs_used < NUM_ARG_REGS)
+    {
+      return_rtx = gen_rtx_REG (mode, FIRST_ARG_REGNO + cum->regs_used);
+    }
+
+  return return_rtx;
+}
+
+int
+function_arg_partial_nregs (const CUMULATIVE_ARGS *cum,
+                            enum machine_mode mode, tree type, 
+                            int named ATTRIBUTE_UNUSED)
+{
+  HOST_WIDE_INT param_size;
+
+  if (mode == BLKmode)
+    {
+      param_size = int_size_in_bytes (type);
+      if (param_size < 0)
+	internal_error
+	  ("Do not know how to handle large structs or variable length types");
+    }
+  else
+    {
+      param_size = GET_MODE_SIZE (mode);
+    }
+
+  /* convert to words (round up) */
+  param_size = (3 + param_size) / 4;
+
+  if (cum->regs_used < NUM_ARG_REGS
+      && cum->regs_used + param_size > NUM_ARG_REGS)
+    {
+      return NUM_ARG_REGS - cum->regs_used;
+    }
+  else
+    {
+      return 0;
+    }
+}
+
+
+int
+nios2_return_in_memory (tree type)
+{
+  int res = ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD))
+  	     || (int_size_in_bytes (type) == -1));
+
+  return res;
+}
+
+/* ??? It may be possible to eliminate the copyback and implement
+       my own va_arg type, but that is more work for now. */
+int
+nios2_setup_incoming_varargs (const CUMULATIVE_ARGS *cum, 
+                              enum machine_mode mode, tree type, 
+                              int no_rtl)
+{
+  CUMULATIVE_ARGS local_cum;
+  int regs_to_push;
+
+  local_cum = *cum;
+  FUNCTION_ARG_ADVANCE (local_cum, mode, type, 1);
+
+  regs_to_push = NUM_ARG_REGS - local_cum.regs_used;
+
+  if (!no_rtl)
+    {
+      if (regs_to_push > 0)
+	{
+	  rtx ptr, mem;
+
+	  ptr = virtual_incoming_args_rtx;
+	  mem = gen_rtx_MEM (BLKmode, ptr);
+
+	  /* va_arg is an array access in this case, which causes
+	     it to get MEM_IN_STRUCT_P set.  We must set it here
+	     so that the insn scheduler won't assume that these
+	     stores can't possibly overlap with the va_arg loads.  */
+	  MEM_SET_IN_STRUCT_P (mem, 1);
+
+	  emit_insn (gen_blockage ());
+	  move_block_from_reg (local_cum.regs_used + FIRST_ARG_REGNO, mem,
+			       regs_to_push);
+	  emit_insn (gen_blockage ());
+	}
+    }
+
+  return regs_to_push * UNITS_PER_WORD;
+
+}
+
+
+
+/*****************************************************************************
+**
+** builtins
+**
+** This method for handling builtins is from CSP where _many_ more types of
+** expanders have already been written. Check there first before writing
+** new ones.
+**
+*****************************************************************************/
+
+enum nios2_builtins
+{
+  NIOS2_BUILTIN_LDBIO,
+  NIOS2_BUILTIN_LDBUIO,
+  NIOS2_BUILTIN_LDHIO,
+  NIOS2_BUILTIN_LDHUIO,
+  NIOS2_BUILTIN_LDWIO,
+  NIOS2_BUILTIN_STBIO,
+  NIOS2_BUILTIN_STHIO,
+  NIOS2_BUILTIN_STWIO,
+  NIOS2_BUILTIN_SYNC,
+  NIOS2_BUILTIN_RDCTL,
+  NIOS2_BUILTIN_WRCTL,
+
+  NIOS2_BUILTIN_CUSTOM_N,
+  NIOS2_BUILTIN_CUSTOM_NI,
+  NIOS2_BUILTIN_CUSTOM_NF,
+  NIOS2_BUILTIN_CUSTOM_NP,
+  NIOS2_BUILTIN_CUSTOM_NII,
+  NIOS2_BUILTIN_CUSTOM_NIF,
+  NIOS2_BUILTIN_CUSTOM_NIP,
+  NIOS2_BUILTIN_CUSTOM_NFI,
+  NIOS2_BUILTIN_CUSTOM_NFF,
+  NIOS2_BUILTIN_CUSTOM_NFP,
+  NIOS2_BUILTIN_CUSTOM_NPI,
+  NIOS2_BUILTIN_CUSTOM_NPF,
+  NIOS2_BUILTIN_CUSTOM_NPP,
+  NIOS2_BUILTIN_CUSTOM_IN,
+  NIOS2_BUILTIN_CUSTOM_INI,
+  NIOS2_BUILTIN_CUSTOM_INF,
+  NIOS2_BUILTIN_CUSTOM_INP,
+  NIOS2_BUILTIN_CUSTOM_INII,
+  NIOS2_BUILTIN_CUSTOM_INIF,
+  NIOS2_BUILTIN_CUSTOM_INIP,
+  NIOS2_BUILTIN_CUSTOM_INFI,
+  NIOS2_BUILTIN_CUSTOM_INFF,
+  NIOS2_BUILTIN_CUSTOM_INFP,
+  NIOS2_BUILTIN_CUSTOM_INPI,
+  NIOS2_BUILTIN_CUSTOM_INPF,
+  NIOS2_BUILTIN_CUSTOM_INPP,
+  NIOS2_BUILTIN_CUSTOM_FN,
+  NIOS2_BUILTIN_CUSTOM_FNI,
+  NIOS2_BUILTIN_CUSTOM_FNF,
+  NIOS2_BUILTIN_CUSTOM_FNP,
+  NIOS2_BUILTIN_CUSTOM_FNII,
+  NIOS2_BUILTIN_CUSTOM_FNIF,
+  NIOS2_BUILTIN_CUSTOM_FNIP,
+  NIOS2_BUILTIN_CUSTOM_FNFI,
+  NIOS2_BUILTIN_CUSTOM_FNFF,
+  NIOS2_BUILTIN_CUSTOM_FNFP,
+  NIOS2_BUILTIN_CUSTOM_FNPI,
+  NIOS2_BUILTIN_CUSTOM_FNPF,
+  NIOS2_BUILTIN_CUSTOM_FNPP,
+  NIOS2_BUILTIN_CUSTOM_PN,
+  NIOS2_BUILTIN_CUSTOM_PNI,
+  NIOS2_BUILTIN_CUSTOM_PNF,
+  NIOS2_BUILTIN_CUSTOM_PNP,
+  NIOS2_BUILTIN_CUSTOM_PNII,
+  NIOS2_BUILTIN_CUSTOM_PNIF,
+  NIOS2_BUILTIN_CUSTOM_PNIP,
+  NIOS2_BUILTIN_CUSTOM_PNFI,
+  NIOS2_BUILTIN_CUSTOM_PNFF,
+  NIOS2_BUILTIN_CUSTOM_PNFP,
+  NIOS2_BUILTIN_CUSTOM_PNPI,
+  NIOS2_BUILTIN_CUSTOM_PNPF,
+  NIOS2_BUILTIN_CUSTOM_PNPP,
+
+
+  LIM_NIOS2_BUILTINS
+};
+
+struct builtin_description
+{
+    const enum insn_code icode;
+    const char *const name;
+    const enum nios2_builtins code;
+    const tree *type;
+    rtx (* expander) PARAMS ((const struct builtin_description *,
+                              tree, rtx, rtx, enum machine_mode, int));
+};
+
+static rtx nios2_expand_STXIO (const struct builtin_description *, 
+                               tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_LDXIO (const struct builtin_description *, 
+                               tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_sync (const struct builtin_description *, 
+                              tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_rdctl (const struct builtin_description *, 
+                               tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_wrctl (const struct builtin_description *, 
+                               tree, rtx, rtx, enum machine_mode, int);
+
+static rtx nios2_expand_custom_n (const struct builtin_description *, 
+                                  tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_Xn (const struct builtin_description *, 
+                                   tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_nX (const struct builtin_description *, 
+                                   tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_XnX (const struct builtin_description *, 
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_nXX (const struct builtin_description *, 
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_XnXX (const struct builtin_description *, 
+                                     tree, rtx, rtx, enum machine_mode, int);
+
+static tree endlink;
+
+/* int fn (volatile const void *)
+ */
+static tree int_ftype_volatile_const_void_p;
+
+/* int fn (int)
+ */
+static tree int_ftype_int;
+
+/* void fn (int, int)
+ */
+static tree void_ftype_int_int;
+
+/* void fn (volatile void *, int)
+ */
+static tree void_ftype_volatile_void_p_int;
+
+/* void fn (void)
+ */
+static tree void_ftype_void;
+
+static tree custom_n;
+static tree custom_ni;
+static tree custom_nf;
+static tree custom_np;
+static tree custom_nii;
+static tree custom_nif;
+static tree custom_nip;
+static tree custom_nfi;
+static tree custom_nff;
+static tree custom_nfp;
+static tree custom_npi;
+static tree custom_npf;
+static tree custom_npp;
+static tree custom_in;
+static tree custom_ini;
+static tree custom_inf;
+static tree custom_inp;
+static tree custom_inii;
+static tree custom_inif;
+static tree custom_inip;
+static tree custom_infi;
+static tree custom_inff;
+static tree custom_infp;
+static tree custom_inpi;
+static tree custom_inpf;
+static tree custom_inpp;
+static tree custom_fn;
+static tree custom_fni;
+static tree custom_fnf;
+static tree custom_fnp;
+static tree custom_fnii;
+static tree custom_fnif;
+static tree custom_fnip;
+static tree custom_fnfi;
+static tree custom_fnff;
+static tree custom_fnfp;
+static tree custom_fnpi;
+static tree custom_fnpf;
+static tree custom_fnpp;
+static tree custom_pn;
+static tree custom_pni;
+static tree custom_pnf;
+static tree custom_pnp;
+static tree custom_pnii;
+static tree custom_pnif;
+static tree custom_pnip;
+static tree custom_pnfi;
+static tree custom_pnff;
+static tree custom_pnfp;
+static tree custom_pnpi;
+static tree custom_pnpf;
+static tree custom_pnpp;
+
+
+static const struct builtin_description bdesc[] = {
+    {CODE_FOR_ldbio, "__builtin_ldbio", NIOS2_BUILTIN_LDBIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
+    {CODE_FOR_ldbuio, "__builtin_ldbuio", NIOS2_BUILTIN_LDBUIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
+    {CODE_FOR_ldhio, "__builtin_ldhio", NIOS2_BUILTIN_LDHIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
+    {CODE_FOR_ldhuio, "__builtin_ldhuio", NIOS2_BUILTIN_LDHUIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
+    {CODE_FOR_ldwio, "__builtin_ldwio", NIOS2_BUILTIN_LDWIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
+
+    {CODE_FOR_stbio, "__builtin_stbio", NIOS2_BUILTIN_STBIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO},
+    {CODE_FOR_sthio, "__builtin_sthio", NIOS2_BUILTIN_STHIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO},
+    {CODE_FOR_stwio, "__builtin_stwio", NIOS2_BUILTIN_STWIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO},
+
+    {CODE_FOR_sync, "__builtin_sync", NIOS2_BUILTIN_SYNC, &void_ftype_void, nios2_expand_sync},
+    {CODE_FOR_rdctl, "__builtin_rdctl", NIOS2_BUILTIN_RDCTL, &int_ftype_int, nios2_expand_rdctl},
+    {CODE_FOR_wrctl, "__builtin_wrctl", NIOS2_BUILTIN_WRCTL, &void_ftype_int_int, nios2_expand_wrctl},
+
+    {CODE_FOR_custom_n, "__builtin_custom_n", NIOS2_BUILTIN_CUSTOM_N, &custom_n, nios2_expand_custom_n},
+    {CODE_FOR_custom_ni, "__builtin_custom_ni", NIOS2_BUILTIN_CUSTOM_NI, &custom_ni, nios2_expand_custom_nX},
+    {CODE_FOR_custom_nf, "__builtin_custom_nf", NIOS2_BUILTIN_CUSTOM_NF, &custom_nf, nios2_expand_custom_nX},
+    {CODE_FOR_custom_np, "__builtin_custom_np", NIOS2_BUILTIN_CUSTOM_NP, &custom_np, nios2_expand_custom_nX},
+    {CODE_FOR_custom_nii, "__builtin_custom_nii", NIOS2_BUILTIN_CUSTOM_NII, &custom_nii, nios2_expand_custom_nXX},
+    {CODE_FOR_custom_nif, "__builtin_custom_nif", NIOS2_BUILTIN_CUSTOM_NIF, &custom_nif, nios2_expand_custom_nXX},
+    {CODE_FOR_custom_nip, "__builtin_custom_nip", NIOS2_BUILTIN_CUSTOM_NIP, &custom_nip, nios2_expand_custom_nXX},
+    {CODE_FOR_custom_nfi, "__builtin_custom_nfi", NIOS2_BUILTIN_CUSTOM_NFI, &custom_nfi, nios2_expand_custom_nXX},
+    {CODE_FOR_custom_nff, "__builtin_custom_nff", NIOS2_BUILTIN_CUSTOM_NFF, &custom_nff, nios2_expand_custom_nXX},
+    {CODE_FOR_custom_nfp, "__builtin_custom_nfp", NIOS2_BUILTIN_CUSTOM_NFP, &custom_nfp, nios2_expand_custom_nXX},
+    {CODE_FOR_custom_npi, "__builtin_custom_npi", NIOS2_BUILTIN_CUSTOM_NPI, &custom_npi, nios2_expand_custom_nXX},
+    {CODE_FOR_custom_npf, "__builtin_custom_npf", NIOS2_BUILTIN_CUSTOM_NPF, &custom_npf, nios2_expand_custom_nXX},
+    {CODE_FOR_custom_npp, "__builtin_custom_npp", NIOS2_BUILTIN_CUSTOM_NPP, &custom_npp, nios2_expand_custom_nXX},
+    {CODE_FOR_custom_in, "__builtin_custom_in", NIOS2_BUILTIN_CUSTOM_IN, &custom_in, nios2_expand_custom_Xn},
+    {CODE_FOR_custom_ini, "__builtin_custom_ini", NIOS2_BUILTIN_CUSTOM_INI, &custom_ini, nios2_expand_custom_XnX},
+    {CODE_FOR_custom_inf, "__builtin_custom_inf", NIOS2_BUILTIN_CUSTOM_INF, &custom_inf, nios2_expand_custom_XnX},
+    {CODE_FOR_custom_inp, "__builtin_custom_inp", NIOS2_BUILTIN_CUSTOM_INP, &custom_inp, nios2_expand_custom_XnX},
+    {CODE_FOR_custom_inii, "__builtin_custom_inii", NIOS2_BUILTIN_CUSTOM_INII, &custom_inii, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_inif, "__builtin_custom_inif", NIOS2_BUILTIN_CUSTOM_INIF, &custom_inif, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_inip, "__builtin_custom_inip", NIOS2_BUILTIN_CUSTOM_INIP, &custom_inip, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_infi, "__builtin_custom_infi", NIOS2_BUILTIN_CUSTOM_INFI, &custom_infi, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_inff, "__builtin_custom_inff", NIOS2_BUILTIN_CUSTOM_INFF, &custom_inff, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_infp, "__builtin_custom_infp", NIOS2_BUILTIN_CUSTOM_INFP, &custom_infp, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_inpi, "__builtin_custom_inpi", NIOS2_BUILTIN_CUSTOM_INPI, &custom_inpi, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_inpf, "__builtin_custom_inpf", NIOS2_BUILTIN_CUSTOM_INPF, &custom_inpf, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_inpp, "__builtin_custom_inpp", NIOS2_BUILTIN_CUSTOM_INPP, &custom_inpp, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_fn, "__builtin_custom_fn", NIOS2_BUILTIN_CUSTOM_FN, &custom_fn, nios2_expand_custom_Xn},
+    {CODE_FOR_custom_fni, "__builtin_custom_fni", NIOS2_BUILTIN_CUSTOM_FNI, &custom_fni, nios2_expand_custom_XnX},
+    {CODE_FOR_custom_fnf, "__builtin_custom_fnf", NIOS2_BUILTIN_CUSTOM_FNF, &custom_fnf, nios2_expand_custom_XnX},
+    {CODE_FOR_custom_fnp, "__builtin_custom_fnp", NIOS2_BUILTIN_CUSTOM_FNP, &custom_fnp, nios2_expand_custom_XnX},
+    {CODE_FOR_custom_fnii, "__builtin_custom_fnii", NIOS2_BUILTIN_CUSTOM_FNII, &custom_fnii, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_fnif, "__builtin_custom_fnif", NIOS2_BUILTIN_CUSTOM_FNIF, &custom_fnif, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_fnip, "__builtin_custom_fnip", NIOS2_BUILTIN_CUSTOM_FNIP, &custom_fnip, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_fnfi, "__builtin_custom_fnfi", NIOS2_BUILTIN_CUSTOM_FNFI, &custom_fnfi, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_fnff, "__builtin_custom_fnff", NIOS2_BUILTIN_CUSTOM_FNFF, &custom_fnff, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_fnfp, "__builtin_custom_fnfp", NIOS2_BUILTIN_CUSTOM_FNFP, &custom_fnfp, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_fnpi, "__builtin_custom_fnpi", NIOS2_BUILTIN_CUSTOM_FNPI, &custom_fnpi, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_fnpf, "__builtin_custom_fnpf", NIOS2_BUILTIN_CUSTOM_FNPF, &custom_fnpf, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_fnpp, "__builtin_custom_fnpp", NIOS2_BUILTIN_CUSTOM_FNPP, &custom_fnpp, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_pn, "__builtin_custom_pn", NIOS2_BUILTIN_CUSTOM_PN, &custom_pn, nios2_expand_custom_Xn},
+    {CODE_FOR_custom_pni, "__builtin_custom_pni", NIOS2_BUILTIN_CUSTOM_PNI, &custom_pni, nios2_expand_custom_XnX},
+    {CODE_FOR_custom_pnf, "__builtin_custom_pnf", NIOS2_BUILTIN_CUSTOM_PNF, &custom_pnf, nios2_expand_custom_XnX},
+    {CODE_FOR_custom_pnp, "__builtin_custom_pnp", NIOS2_BUILTIN_CUSTOM_PNP, &custom_pnp, nios2_expand_custom_XnX},
+    {CODE_FOR_custom_pnii, "__builtin_custom_pnii", NIOS2_BUILTIN_CUSTOM_PNII, &custom_pnii, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_pnif, "__builtin_custom_pnif", NIOS2_BUILTIN_CUSTOM_PNIF, &custom_pnif, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_pnip, "__builtin_custom_pnip", NIOS2_BUILTIN_CUSTOM_PNIP, &custom_pnip, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_pnfi, "__builtin_custom_pnfi", NIOS2_BUILTIN_CUSTOM_PNFI, &custom_pnfi, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_pnff, "__builtin_custom_pnff", NIOS2_BUILTIN_CUSTOM_PNFF, &custom_pnff, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_pnfp, "__builtin_custom_pnfp", NIOS2_BUILTIN_CUSTOM_PNFP, &custom_pnfp, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_pnpi, "__builtin_custom_pnpi", NIOS2_BUILTIN_CUSTOM_PNPI, &custom_pnpi, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_pnpf, "__builtin_custom_pnpf", NIOS2_BUILTIN_CUSTOM_PNPF, &custom_pnpf, nios2_expand_custom_XnXX},
+    {CODE_FOR_custom_pnpp, "__builtin_custom_pnpp", NIOS2_BUILTIN_CUSTOM_PNPP, &custom_pnpp, nios2_expand_custom_XnXX},
+
+
+    {0, 0, 0, 0, 0},
+};
+
+/* This does not have a closing bracket on purpose (see use) */
+#define def_param(TYPE) \
+  tree_cons (NULL_TREE, TYPE,
+
+static void
+nios2_init_builtins ()
+{
+  const struct builtin_description *d;
+
+
+  endlink = void_list_node;
+
+  /* Special indenting here because one of the brackets is in def_param */
+  /* *INDENT-OFF* */
+
+  /* int fn (volatile const void *)
+   */
+  int_ftype_volatile_const_void_p
+    = build_function_type (integer_type_node,
+			   def_param (build_qualified_type (ptr_type_node,
+			                                    TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE))
+			   endlink));
+
+
+  /* void fn (volatile void *, int)
+   */
+  void_ftype_volatile_void_p_int
+    = build_function_type (void_type_node,
+			   def_param (build_qualified_type (ptr_type_node,
+			                                    TYPE_QUAL_VOLATILE))
+			   def_param (integer_type_node)
+			   endlink)));
+
+  /* void fn (void)
+   */
+  void_ftype_void
+      = build_function_type (void_type_node,
+                             endlink);
+
+  /* int fn (int)
+   */
+  int_ftype_int
+      = build_function_type (integer_type_node,
+                             def_param (integer_type_node)
+                             endlink));
+
+  /* void fn (int, int)
+   */
+  void_ftype_int_int
+      = build_function_type (void_type_node,
+                             def_param (integer_type_node)
+                             def_param (integer_type_node)
+                             endlink)));
+
+
+#define CUSTOM_NUM def_param (integer_type_node)
+
+  custom_n
+      = build_function_type (void_type_node,
+  			     CUSTOM_NUM
+  			     endlink));
+  custom_ni
+      = build_function_type (void_type_node,
+  			     CUSTOM_NUM
+  			     def_param (integer_type_node)
+  			     endlink)));
+  custom_nf
+      = build_function_type (void_type_node,
+  			     CUSTOM_NUM
+  			     def_param (float_type_node)
+  			     endlink)));
+  custom_np
+      = build_function_type (void_type_node,
+  			     CUSTOM_NUM
+  			     def_param (ptr_type_node)
+  			     endlink)));
+  custom_nii
+      = build_function_type (void_type_node,
+  			     CUSTOM_NUM
+  			     def_param (integer_type_node)
+  			     def_param (integer_type_node)
+  			     endlink))));
+  custom_nif
+      = build_function_type (void_type_node,
+  			     CUSTOM_NUM
+  			     def_param (integer_type_node)
+  			     def_param (float_type_node)
+  			     endlink))));
+  custom_nip
+      = build_function_type (void_type_node,
+  			     CUSTOM_NUM
+  			     def_param (integer_type_node)
+  			     def_param (ptr_type_node)
+  			     endlink))));
+  custom_nfi
+      = build_function_type (void_type_node,
+  			     CUSTOM_NUM
+  			     def_param (float_type_node)
+  			     def_param (integer_type_node)
+  			     endlink))));
+  custom_nff
+      = build_function_type (void_type_node,
+  			     CUSTOM_NUM
+  			     def_param (float_type_node)
+  			     def_param (float_type_node)
+  			     endlink))));
+  custom_nfp
+      = build_function_type (void_type_node,
+  			     CUSTOM_NUM
+  			     def_param (float_type_node)
+  			     def_param (ptr_type_node)
+  			     endlink))));
+  custom_npi
+      = build_function_type (void_type_node,
+  			     CUSTOM_NUM
+  			     def_param (ptr_type_node)
+  			     def_param (integer_type_node)
+  			     endlink))));
+  custom_npf
+      = build_function_type (void_type_node,
+  			     CUSTOM_NUM
+  			     def_param (ptr_type_node)
+  			     def_param (float_type_node)
+  			     endlink))));
+  custom_npp
+      = build_function_type (void_type_node,
+  			     CUSTOM_NUM
+  			     def_param (ptr_type_node)
+  			     def_param (ptr_type_node)
+  			     endlink))));
+
+  custom_in
+      = build_function_type (integer_type_node,
+  			     CUSTOM_NUM
+  			     endlink));
+  custom_ini
+      = build_function_type (integer_type_node,
+  			     CUSTOM_NUM
+  			     def_param (integer_type_node)
+  			     endlink)));
+  custom_inf
+      = build_function_type (integer_type_node,
+  			     CUSTOM_NUM
+  			     def_param (float_type_node)
+  			     endlink)));
+  custom_inp
+      = build_function_type (integer_type_node,
+  			     CUSTOM_NUM
+  			     def_param (ptr_type_node)
+  			     endlink)));
+  custom_inii
+      = build_function_type (integer_type_node,
+  			     CUSTOM_NUM
+  			     def_param (integer_type_node)
+  			     def_param (integer_type_node)
+  			     endlink))));
+  custom_inif
+      = build_function_type (integer_type_node,
+  			     CUSTOM_NUM
+  			     def_param (integer_type_node)
+  			     def_param (float_type_node)
+  			     endlink))));
+  custom_inip
+      = build_function_type (integer_type_node,
+  			     CUSTOM_NUM
+  			     def_param (integer_type_node)
+  			     def_param (ptr_type_node)
+  			     endlink))));
+  custom_infi
+      = build_function_type (integer_type_node,
+  			     CUSTOM_NUM
+  			     def_param (float_type_node)
+  			     def_param (integer_type_node)
+  			     endlink))));
+  custom_inff
+      = build_function_type (integer_type_node,
+  			     CUSTOM_NUM
+  			     def_param (float_type_node)
+  			     def_param (float_type_node)
+  			     endlink))));
+  custom_infp
+      = build_function_type (integer_type_node,
+  			     CUSTOM_NUM
+  			     def_param (float_type_node)
+  			     def_param (ptr_type_node)
+  			     endlink))));
+  custom_inpi
+      = build_function_type (integer_type_node,
+  			     CUSTOM_NUM
+  			     def_param (ptr_type_node)
+  			     def_param (integer_type_node)
+  			     endlink))));
+  custom_inpf
+      = build_function_type (integer_type_node,
+  			     CUSTOM_NUM
+  			     def_param (ptr_type_node)
+  			     def_param (float_type_node)
+  			     endlink))));
+  custom_inpp
+      = build_function_type (integer_type_node,
+  			     CUSTOM_NUM
+  			     def_param (ptr_type_node)
+  			     def_param (ptr_type_node)
+  			     endlink))));
+
+  custom_fn
+      = build_function_type (float_type_node,
+  			     CUSTOM_NUM
+  			     endlink));
+  custom_fni
+      = build_function_type (float_type_node,
+  			     CUSTOM_NUM
+  			     def_param (integer_type_node)
+  			     endlink)));
+  custom_fnf
+      = build_function_type (float_type_node,
+  			     CUSTOM_NUM
+  			     def_param (float_type_node)
+  			     endlink)));
+  custom_fnp
+      = build_function_type (float_type_node,
+  			     CUSTOM_NUM
+  			     def_param (ptr_type_node)
+  			     endlink)));
+  custom_fnii
+      = build_function_type (float_type_node,
+  			     CUSTOM_NUM
+  			     def_param (integer_type_node)
+  			     def_param (integer_type_node)
+  			     endlink))));
+  custom_fnif
+      = build_function_type (float_type_node,
+  			     CUSTOM_NUM
+  			     def_param (integer_type_node)
+  			     def_param (float_type_node)
+  			     endlink))));
+  custom_fnip
+      = build_function_type (float_type_node,
+  			     CUSTOM_NUM
+  			     def_param (integer_type_node)
+  			     def_param (ptr_type_node)
+  			     endlink))));
+  custom_fnfi
+      = build_function_type (float_type_node,
+  			     CUSTOM_NUM
+  			     def_param (float_type_node)
+  			     def_param (integer_type_node)
+  			     endlink))));
+  custom_fnff
+      = build_function_type (float_type_node,
+  			     CUSTOM_NUM
+  			     def_param (float_type_node)
+  			     def_param (float_type_node)
+  			     endlink))));
+  custom_fnfp
+      = build_function_type (float_type_node,
+  			     CUSTOM_NUM
+  			     def_param (float_type_node)
+  			     def_param (ptr_type_node)
+  			     endlink))));
+  custom_fnpi
+      = build_function_type (float_type_node,
+  			     CUSTOM_NUM
+  			     def_param (ptr_type_node)
+  			     def_param (integer_type_node)
+  			     endlink))));
+  custom_fnpf
+      = build_function_type (float_type_node,
+  			     CUSTOM_NUM
+  			     def_param (ptr_type_node)
+  			     def_param (float_type_node)
+  			     endlink))));
+  custom_fnpp
+      = build_function_type (float_type_node,
+  			     CUSTOM_NUM
+  			     def_param (ptr_type_node)
+  			     def_param (ptr_type_node)
+  			     endlink))));
+
+
+  custom_pn
+      = build_function_type (ptr_type_node,
+  			     CUSTOM_NUM
+  			     endlink));
+  custom_pni
+      = build_function_type (ptr_type_node,
+  			     CUSTOM_NUM
+  			     def_param (integer_type_node)
+  			     endlink)));
+  custom_pnf
+      = build_function_type (ptr_type_node,
+  			     CUSTOM_NUM
+  			     def_param (float_type_node)
+  			     endlink)));
+  custom_pnp
+      = build_function_type (ptr_type_node,
+  			     CUSTOM_NUM
+  			     def_param (ptr_type_node)
+  			     endlink)));
+  custom_pnii
+      = build_function_type (ptr_type_node,
+  			     CUSTOM_NUM
+  			     def_param (integer_type_node)
+  			     def_param (integer_type_node)
+  			     endlink))));
+  custom_pnif
+      = build_function_type (ptr_type_node,
+  			     CUSTOM_NUM
+  			     def_param (integer_type_node)
+  			     def_param (float_type_node)
+  			     endlink))));
+  custom_pnip
+      = build_function_type (ptr_type_node,
+  			     CUSTOM_NUM
+  			     def_param (integer_type_node)
+  			     def_param (ptr_type_node)
+  			     endlink))));
+  custom_pnfi
+      = build_function_type (ptr_type_node,
+  			     CUSTOM_NUM
+  			     def_param (float_type_node)
+  			     def_param (integer_type_node)
+  			     endlink))));
+  custom_pnff
+      = build_function_type (ptr_type_node,
+  			     CUSTOM_NUM
+  			     def_param (float_type_node)
+  			     def_param (float_type_node)
+  			     endlink))));
+  custom_pnfp
+      = build_function_type (ptr_type_node,
+  			     CUSTOM_NUM
+  			     def_param (float_type_node)
+  			     def_param (ptr_type_node)
+  			     endlink))));
+  custom_pnpi
+      = build_function_type (ptr_type_node,
+  			     CUSTOM_NUM
+  			     def_param (ptr_type_node)
+  			     def_param (integer_type_node)
+  			     endlink))));
+  custom_pnpf
+      = build_function_type (ptr_type_node,
+  			     CUSTOM_NUM
+  			     def_param (ptr_type_node)
+  			     def_param (float_type_node)
+  			     endlink))));
+  custom_pnpp
+      = build_function_type (ptr_type_node,
+  			     CUSTOM_NUM
+  			     def_param (ptr_type_node)
+  			     def_param (ptr_type_node)
+  			     endlink))));
+
+
+
+  /* *INDENT-ON* */
+
+
+  for (d = bdesc; d->name; d++)
+    {
+      builtin_function (d->name, *d->type, d->code,
+			BUILT_IN_MD, NULL, NULL);
+    }
+}
+
+/* Expand an expression EXP that calls a built-in function,
+   with result going to TARGET if that's convenient
+   (and in mode MODE if that's convenient).
+   SUBTARGET may be used as the target for computing one of EXP's operands.
+   IGNORE is nonzero if the value is to be ignored.  */
+
+static rtx
+nios2_expand_builtin (tree exp, rtx target, rtx subtarget, 
+                      enum machine_mode mode, int ignore)
+{
+  const struct builtin_description *d;
+  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+
+  for (d = bdesc; d->name; d++)
+    if (d->code == fcode)
+      return (d->expander) (d, exp, target, subtarget, mode, ignore);
+
+  /* we should have seen one of the functins we registered */
+  abort ();
+}
+
+static rtx nios2_create_target (const struct builtin_description *, rtx);
+
+
+static rtx
+nios2_create_target (const struct builtin_description *d, rtx target)
+{
+  if (!target
+      || !(*insn_data[d->icode].operand[0].predicate) (target,
+                                                       insn_data[d->icode].operand[0].mode))
+    {
+      target = gen_reg_rtx (insn_data[d->icode].operand[0].mode);
+    }
+
+  return target;
+}
+
+
+static rtx nios2_extract_opcode (const struct builtin_description *, int, tree);
+static rtx nios2_extract_operand (const struct builtin_description *, int, int, tree);
+
+static rtx
+nios2_extract_opcode (const struct builtin_description *d, int op, tree arglist)
+{
+  enum machine_mode mode = insn_data[d->icode].operand[op].mode;
+  tree arg = TREE_VALUE (arglist);
+  rtx opcode = expand_expr (arg, NULL_RTX, mode, 0);
+  opcode = protect_from_queue (opcode, 0);
+
+  if (!(*insn_data[d->icode].operand[op].predicate) (opcode, mode))
+    error ("Custom instruction opcode must be compile time constant in the range 0-255 for %s", d->name);
+
+  return opcode;
+}
+
+static rtx
+nios2_extract_operand (const struct builtin_description *d, int op, int argnum, tree arglist)
+{
+  enum machine_mode mode = insn_data[d->icode].operand[op].mode;
+  tree arg = TREE_VALUE (arglist);
+  rtx operand = expand_expr (arg, NULL_RTX, mode, 0);
+  operand = protect_from_queue (operand, 0);
+
+  if (!(*insn_data[d->icode].operand[op].predicate) (operand, mode))
+    operand = copy_to_mode_reg (mode, operand);
+
+  /* ??? Better errors would be nice */
+  if (!(*insn_data[d->icode].operand[op].predicate) (operand, mode))
+    error ("Invalid argument %d to %s", argnum, d->name);
+
+  return operand;
+}
+
+
+static rtx
+nios2_expand_custom_n (const struct builtin_description *d, tree exp, 
+                       rtx target ATTRIBUTE_UNUSED, rtx subtarget ATTRIBUTE_UNUSED, 
+                       enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat;
+  rtx opcode;
+
+  /* custom_n should have exactly one operand */
+  if (insn_data[d->icode].n_operands != 1)
+    abort ();
+
+  opcode = nios2_extract_opcode (d, 0, arglist);
+
+  pat = GEN_FCN (d->icode) (opcode);
+  if (!pat)
+    return 0;
+  emit_insn (pat);
+  return 0;
+}
+
+static rtx
+nios2_expand_custom_Xn (const struct builtin_description *d, tree exp, 
+                        rtx target, rtx subtarget ATTRIBUTE_UNUSED, 
+                        enum machine_mode mode ATTRIBUTE_UNUSED, 
+                        int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat;
+  rtx opcode;
+
+  /* custom_Xn should have exactly two operands */
+  if (insn_data[d->icode].n_operands != 2)
+    abort ();
+
+  target = nios2_create_target (d, target);
+  opcode = nios2_extract_opcode (d, 1, arglist);
+
+  pat = GEN_FCN (d->icode) (target, opcode);
+  if (!pat)
+    return 0;
+  emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_nX (const struct builtin_description *d, tree exp, 
+                        rtx target ATTRIBUTE_UNUSED, rtx subtarget ATTRIBUTE_UNUSED, 
+                        enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat;
+  rtx opcode;
+  rtx operands[1];
+  int i;
+
+
+  /* custom_nX should have exactly two operands */
+  if (insn_data[d->icode].n_operands != 2)
+    abort ();
+
+  opcode = nios2_extract_opcode (d, 0, arglist);
+  for (i = 0; i < 1; i++)
+    {
+      arglist = TREE_CHAIN (arglist);
+      operands[i] = nios2_extract_operand (d, i + 1, i + 1, arglist);
+    }
+
+  pat = GEN_FCN (d->icode) (opcode, operands[0]);
+  if (!pat)
+    return 0;
+  emit_insn (pat);
+  return 0;
+}
+
+static rtx
+nios2_expand_custom_XnX (const struct builtin_description *d, tree exp, rtx target, 
+                         rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, 
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat;
+  rtx opcode;
+  rtx operands[1];
+  int i;
+
+  /* custom_Xn should have exactly three operands */
+  if (insn_data[d->icode].n_operands != 3)
+    abort ();
+
+  target = nios2_create_target (d, target);
+  opcode = nios2_extract_opcode (d, 1, arglist);
+
+  for (i = 0; i < 1; i++)
+    {
+      arglist = TREE_CHAIN (arglist);
+      operands[i] = nios2_extract_operand (d, i + 2, i + 1, arglist);
+    }
+
+  pat = GEN_FCN (d->icode) (target, opcode, operands[0]);
+
+  if (!pat)
+    return 0;
+  emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_nXX (const struct builtin_description *d, tree exp, rtx target ATTRIBUTE_UNUSED, 
+                         rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, 
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat;
+  rtx opcode;
+  rtx operands[2];
+  int i;
+
+
+  /* custom_nX should have exactly three operands */
+  if (insn_data[d->icode].n_operands != 3)
+    abort ();
+
+  opcode = nios2_extract_opcode (d, 0, arglist);
+  for (i = 0; i < 2; i++)
+    {
+      arglist = TREE_CHAIN (arglist);
+      operands[i] = nios2_extract_operand (d, i + 1, i + 1, arglist);
+    }
+
+  pat = GEN_FCN (d->icode) (opcode, operands[0], operands[1]);
+  if (!pat)
+    return 0;
+  emit_insn (pat);
+  return 0;
+}
+
+static rtx
+nios2_expand_custom_XnXX (const struct builtin_description *d, tree exp, rtx target, 
+                          rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, 
+                          int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat;
+  rtx opcode;
+  rtx operands[2];
+  int i;
+
+
+  /* custom_XnX should have exactly four operands */
+  if (insn_data[d->icode].n_operands != 4)
+    abort ();
+
+  target = nios2_create_target (d, target);
+  opcode = nios2_extract_opcode (d, 1, arglist);
+  for (i = 0; i < 2; i++)
+    {
+      arglist = TREE_CHAIN (arglist);
+      operands[i] = nios2_extract_operand (d, i + 2, i + 1, arglist);
+    }
+
+  pat = GEN_FCN (d->icode) (target, opcode, operands[0], operands[1]);
+
+  if (!pat)
+    return 0;
+  emit_insn (pat);
+  return target;
+}
+
+
+
+static rtx
+nios2_expand_STXIO (const struct builtin_description *d, tree exp, rtx target ATTRIBUTE_UNUSED, 
+                    rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, 
+                    int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat;
+  rtx store_dest, store_val;
+  enum insn_code icode = d->icode;
+
+  /* stores should have exactly two operands */
+  if (insn_data[icode].n_operands != 2)
+    abort ();
+
+  /* process the destination of the store */
+  {
+    enum machine_mode mode = insn_data[icode].operand[0].mode;
+    tree arg = TREE_VALUE (arglist);
+    store_dest = expand_expr (arg, NULL_RTX, VOIDmode, 0);
+    store_dest = protect_from_queue (store_dest, 0);
+
+    store_dest = gen_rtx_MEM (mode, copy_to_mode_reg (Pmode, store_dest));
+
+    /* ??? Better errors would be nice */
+    if (!(*insn_data[icode].operand[0].predicate) (store_dest, mode))
+      error ("Invalid argument 1 to %s", d->name);
+  }
+
+
+  /* process the value to store */
+  {
+    enum machine_mode mode = insn_data[icode].operand[1].mode;
+    tree arg = TREE_VALUE (TREE_CHAIN (arglist));
+    store_val = expand_expr (arg, NULL_RTX, mode, 0);
+    store_val = protect_from_queue (store_val, 0);
+
+    if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
+      store_val = copy_to_mode_reg (mode, store_val);
+
+    /* ??? Better errors would be nice */
+    if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
+      error ("Invalid argument 2 to %s", d->name);
+  }
+
+  pat = GEN_FCN (d->icode) (store_dest, store_val);
+  if (!pat)
+    return 0;
+  emit_insn (pat);
+  return 0;
+}
+
+
+static rtx
+nios2_expand_LDXIO (const struct builtin_description * d, tree exp, rtx target, 
+                    rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, 
+                    int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat;
+  rtx ld_src;
+  enum insn_code icode = d->icode;
+
+  /* loads should have exactly two operands */
+  if (insn_data[icode].n_operands != 2)
+    abort ();
+
+  target = nios2_create_target (d, target);
+
+  {
+    enum machine_mode mode = insn_data[icode].operand[1].mode;
+    tree arg = TREE_VALUE (arglist);
+    ld_src = expand_expr (arg, NULL_RTX, VOIDmode, 0);
+    ld_src = protect_from_queue (ld_src, 0);
+
+    ld_src = gen_rtx_MEM (mode, copy_to_mode_reg (Pmode, ld_src));
+
+    /* ??? Better errors would be nice */
+    if (!(*insn_data[icode].operand[1].predicate) (ld_src, mode))
+      {
+        error ("Invalid argument 1 to %s", d->name);
+      }
+  }
+
+  pat = GEN_FCN (d->icode) (target, ld_src);
+  if (!pat)
+    return 0;
+  emit_insn (pat);
+  return target;
+}
+
+
+static rtx
+nios2_expand_sync (const struct builtin_description * d ATTRIBUTE_UNUSED, 
+                   tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED, 
+                   rtx subtarget ATTRIBUTE_UNUSED, 
+                   enum machine_mode mode ATTRIBUTE_UNUSED, 
+                   int ignore ATTRIBUTE_UNUSED)
+{
+  emit_insn (gen_sync ());
+  return 0;
+}
+
+static rtx
+nios2_expand_rdctl (const struct builtin_description * d ATTRIBUTE_UNUSED, 
+                   tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED, 
+                   rtx subtarget ATTRIBUTE_UNUSED, 
+                   enum machine_mode mode ATTRIBUTE_UNUSED, 
+                   int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat;
+  rtx rdctl_reg;
+  enum insn_code icode = d->icode;
+
+  /* rdctl should have exactly two operands */
+  if (insn_data[icode].n_operands != 2)
+    abort ();
+
+  target = nios2_create_target (d, target);
+
+  {
+    enum machine_mode mode = insn_data[icode].operand[1].mode;
+    tree arg = TREE_VALUE (arglist);
+    rdctl_reg = expand_expr (arg, NULL_RTX, VOIDmode, 0);
+    rdctl_reg = protect_from_queue (rdctl_reg, 0);
+
+    if (!(*insn_data[icode].operand[1].predicate) (rdctl_reg, mode))
+      {
+        error ("Control register number must be in range 0-31 for %s", d->name);
+      }
+  }
+
+  pat = GEN_FCN (d->icode) (target, rdctl_reg);
+  if (!pat)
+    return 0;
+  emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_wrctl (const struct builtin_description * d ATTRIBUTE_UNUSED, 
+                   tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED, 
+                   rtx subtarget ATTRIBUTE_UNUSED, 
+                   enum machine_mode mode ATTRIBUTE_UNUSED, 
+                   int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat;
+  rtx wrctl_reg, store_val;
+  enum insn_code icode = d->icode;
+
+  /* stores should have exactly two operands */
+  if (insn_data[icode].n_operands != 2)
+    abort ();
+
+  /* process the destination of the store */
+  {
+    enum machine_mode mode = insn_data[icode].operand[0].mode;
+    tree arg = TREE_VALUE (arglist);
+    wrctl_reg = expand_expr (arg, NULL_RTX, VOIDmode, 0);
+    wrctl_reg = protect_from_queue (wrctl_reg, 0);
+
+    if (!(*insn_data[icode].operand[0].predicate) (wrctl_reg, mode))
+      error ("Control register number must be in range 0-31 for %s", d->name);
+  }
+
+
+  /* process the value to store */
+  {
+    enum machine_mode mode = insn_data[icode].operand[1].mode;
+    tree arg = TREE_VALUE (TREE_CHAIN (arglist));
+    store_val = expand_expr (arg, NULL_RTX, mode, 0);
+    store_val = protect_from_queue (store_val, 0);
+
+    if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
+      store_val = copy_to_mode_reg (mode, store_val);
+
+    /* ??? Better errors would be nice */
+    if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
+      error ("Invalid argument 2 to %s", d->name);
+  }
+
+  pat = GEN_FCN (d->icode) (wrctl_reg, store_val);
+  if (!pat)
+    return 0;
+  emit_insn (pat);
+  return 0;
+}
+
+
+#include "gt-nios2.h"
+
--- gcc-3.4.3/gcc/config/nios2/nios2.h
+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.h
@@ -0,0 +1,824 @@
+/* Definitions of target machine for Altera NIOS 2G NIOS2 version.
+   Copyright (C) 2003 Altera 
+   Contributed by Jonah Graham (jgraham@altera.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+
+#define TARGET_CPU_CPP_BUILTINS()		\
+  do						\
+    {						\
+      builtin_define_std ("NIOS2");		\
+      builtin_define_std ("nios2");		\
+      builtin_define ("_GNU_SOURCE");		\
+    }						\
+  while (0)
+#define TARGET_VERSION fprintf (stderr, " (Altera Nios II)")
+
+
+
+
+
+/*********************************
+ * Run-time Target Specification
+ *********************************/
+
+#define HAS_DIV_FLAG 0x0001
+#define HAS_MUL_FLAG 0x0002
+#define HAS_MULX_FLAG 0x0004
+#define FAST_SW_DIV_FLAG 0x0008
+#define INLINE_MEMCPY_FLAG 0x00010
+#define CACHE_VOLATILE_FLAG 0x0020
+#define BYPASS_CACHE_FLAG 0x0040
+
+extern int target_flags;
+#define TARGET_HAS_DIV (target_flags & HAS_DIV_FLAG)
+#define TARGET_HAS_MUL (target_flags & HAS_MUL_FLAG)
+#define TARGET_HAS_MULX (target_flags & HAS_MULX_FLAG)
+#define TARGET_FAST_SW_DIV (target_flags & FAST_SW_DIV_FLAG)
+#define TARGET_INLINE_MEMCPY (target_flags & INLINE_MEMCPY_FLAG)
+#define TARGET_CACHE_VOLATILE (target_flags & CACHE_VOLATILE_FLAG)
+#define TARGET_BYPASS_CACHE (target_flags & BYPASS_CACHE_FLAG)
+
+#define TARGET_SWITCHES					\
+{							\
+    { "hw-div", HAS_DIV_FLAG,				\
+      N_("Enable DIV, DIVU") },				\
+    { "no-hw-div", -HAS_DIV_FLAG,			\
+      N_("Disable DIV, DIVU (default)") },		\
+    { "hw-mul", HAS_MUL_FLAG,				\
+      N_("Enable MUL instructions (default)") },				\
+    { "hw-mulx", HAS_MULX_FLAG,				\
+      N_("Enable MULX instructions, assume fast shifter") },				\
+    { "no-hw-mul", -HAS_MUL_FLAG,			\
+      N_("Disable MUL instructions") },		\
+    { "no-hw-mulx", -HAS_MULX_FLAG,			\
+      N_("Disable MULX instructions, assume slow shifter (default and implied by -mno-hw-mul)") },		\
+    { "fast-sw-div", FAST_SW_DIV_FLAG,				\
+      N_("Use table based fast divide (default at -O3)") },				\
+    { "no-fast-sw-div", -FAST_SW_DIV_FLAG,			\
+      N_("Don't use table based fast divide ever") },		\
+    { "inline-memcpy", INLINE_MEMCPY_FLAG,				\
+      N_("Inline small memcpy (default when optimizing)") },				\
+    { "no-inline-memcpy", -INLINE_MEMCPY_FLAG,			\
+      N_("Don't Inline small memcpy") },		\
+    { "cache-volatile", CACHE_VOLATILE_FLAG,				\
+      N_("Volatile accesses use non-io variants of instructions (default)") },				\
+    { "no-cache-volatile", -CACHE_VOLATILE_FLAG,			\
+      N_("Volatile accesses use io variants of instructions") },		\
+    { "bypass-cache", BYPASS_CACHE_FLAG,				\
+      N_("All ld/st instructins use io variants") },				\
+    { "no-bypass-cache", -BYPASS_CACHE_FLAG,			\
+      N_("All ld/st instructins do not use io variants (default)") },		\
+    { "smallc", 0,			\
+      N_("Link with a limited version of the C library") },		\
+    { "ctors-in-init", 0,			\
+      "" /* undocumented: N_("Link with static constructors and destructors in init") */ },		\
+    { "", TARGET_DEFAULT, 0 }				\
+}
+
+
+extern const char *nios2_sys_nosys_string;    /* for -msys=nosys */
+extern const char *nios2_sys_lib_string;    /* for -msys-lib= */
+extern const char *nios2_sys_crt0_string;    /* for -msys-crt0= */
+
+#define TARGET_OPTIONS					\
+{							\
+  { "sys=nosys",    &nios2_sys_nosys_string,		\
+      N_("Use stub versions of OS library calls (default)"), 0},	\
+  { "sys-lib=",    &nios2_sys_lib_string,		\
+      N_("Name of System Library to link against. (Converted to a -l option)"), 0},	\
+  { "sys-crt0=",    &nios2_sys_crt0_string,		\
+      N_("Name of the startfile. (default is a crt0 for the ISS only)"), 0},	\
+}
+
+
+/* Default target_flags if no switches specified.  */
+#ifndef TARGET_DEFAULT
+# define TARGET_DEFAULT (HAS_MUL_FLAG | CACHE_VOLATILE_FLAG)
+#endif
+
+/* Switch  Recognition by gcc.c.  Add -G xx support */
+#undef  SWITCH_TAKES_ARG
+#define SWITCH_TAKES_ARG(CHAR)						\
+  (DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G')
+
+#define OVERRIDE_OPTIONS override_options ()
+#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) optimization_options (LEVEL, SIZE)
+#define CAN_DEBUG_WITHOUT_FP
+ 
+#define CC1_SPEC "\
+%{G*}"
+
+#undef LIB_SPEC
+#define LIB_SPEC \
+"--start-group %{msmallc: -lsmallc} %{!msmallc: -lc} -lgcc \
+ %{msys-lib=*: -l%*} \
+ %{!msys-lib=*: -lc } \
+ --end-group \
+ %{msys-lib=: %eYou need a library name for -msys-lib=} \
+"
+
+
+#undef STARTFILE_SPEC 
+#define STARTFILE_SPEC  \
+"%{msys-crt0=*: %*} %{!msys-crt0=*: crt1%O%s} \
+ %{msys-crt0=: %eYou need a C startup file for -msys-crt0=} \
+ %{mctors-in-init: crti%O%s crtbegin%O%s} \
+"
+
+#undef ENDFILE_SPEC 
+#define ENDFILE_SPEC \
+ "%{mctors-in-init: crtend%O%s crtn%O%s}"
+
+
+/***********************
+ * Storage Layout
+ ***********************/
+
+#define DEFAULT_SIGNED_CHAR 1
+#define BITS_BIG_ENDIAN 0
+#define BYTES_BIG_ENDIAN 0
+#define WORDS_BIG_ENDIAN 0
+#define BITS_PER_UNIT 8
+#define BITS_PER_WORD 32
+#define UNITS_PER_WORD 4
+#define POINTER_SIZE 32
+#define BIGGEST_ALIGNMENT 32
+#define STRICT_ALIGNMENT 1
+#define FUNCTION_BOUNDARY 32
+#define PARM_BOUNDARY 32
+#define STACK_BOUNDARY 32
+#define PREFERRED_STACK_BOUNDARY 32
+#define MAX_FIXED_MODE_SIZE 64
+
+#define CONSTANT_ALIGNMENT(EXP, ALIGN)				\
+  ((TREE_CODE (EXP) == STRING_CST) 				\
+   && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
+
+
+/**********************
+ * Layout of Source Language Data Types
+ **********************/
+
+#define INT_TYPE_SIZE 32
+#define SHORT_TYPE_SIZE 16
+#define LONG_TYPE_SIZE 32
+#define LONG_LONG_TYPE_SIZE 64
+#define FLOAT_TYPE_SIZE 32
+#define DOUBLE_TYPE_SIZE 64
+#define LONG_DOUBLE_TYPE_SIZE DOUBLE_TYPE_SIZE
+
+
+/*************************
+ * Condition Code Status
+ ************************/
+
+/* comparison type */
+/* ??? currently only CMP_SI is used */
+enum cmp_type {
+  CMP_SI,				/* compare four byte integers */
+  CMP_DI,				/* compare eight byte integers */
+  CMP_SF,				/* compare single precision floats */
+  CMP_DF,				/* compare double precision floats */
+  CMP_MAX				/* max comparison type */
+};
+
+extern GTY(()) rtx branch_cmp[2];	/* operands for compare */
+extern enum cmp_type branch_type;	/* what type of branch to use */
+
+/**********************
+ * Register Usage
+ **********************/
+
+/* ---------------------------------- *
+ * Basic Characteristics of Registers
+ * ---------------------------------- */
+
+/*
+Register Number
+      Register Name
+          Alternate Name
+                Purpose
+0     r0  zero  always zero
+1     r1  at    Assembler Temporary
+2-3   r2-r3     Return Location
+4-7   r4-r7     Register Arguments
+8-15  r8-r15    Caller Saved Registers
+16-22 r16-r22   Callee Saved Registers
+23    r23 sc    Static Chain (Callee Saved)
+                ??? Does $sc want to be caller or callee 
+                saved. If caller, 15, else 23. 
+24    r24       Exception Temporary
+25    r25       Breakpoint Temporary
+26    r26 gp    Global Pointer
+27    r27 sp    Stack Pointer
+28    r28 fp    Frame Pointer
+29    r29 ea    Exception Return Address
+30    r30 ba    Breakpoint Return Address
+31    r31 ra    Return Address
+
+32    ctl0 status
+33    ctl1 estatus STATUS saved by exception ? 	
+34    ctl2 bstatus STATUS saved by break ? 	
+35    ctl3 ipri    Interrupt Priority Mask ?	
+36    ctl4 ecause  Exception Cause ? 	
+
+37         pc   Not an actual register	
+
+38    rap      Return address pointer, this does not
+                   actually exist and will be eliminated
+
+39    fake_fp  Fake Frame Pointer which will always be eliminated.
+40    fake_ap  Fake Argument Pointer which will always be eliminated.
+
+41             First Pseudo Register
+
+
+The definitions for all the hard register numbers
+are located in nios2.md.
+*/
+
+#define FIRST_PSEUDO_REGISTER 41
+#define NUM_ARG_REGS (LAST_ARG_REGNO - FIRST_ARG_REGNO + 1)
+
+
+
+/* also see CONDITIONAL_REGISTER_USAGE */
+#define FIXED_REGISTERS			     \
+    {					     \
+/*        +0  1  2  3  4  5  6  7  8  9 */   \
+/*   0 */  1, 1, 0, 0, 0, 0, 0, 0, 0, 0,     \
+/*  10 */  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     \
+/*  20 */  0, 0, 0, 0, 1, 1, 1, 1, 0, 1,     \
+/*  30 */  1, 0, 1, 1, 1, 1, 1, 1, 1, 1,     \
+/*  40 */  1,                                \
+    }
+
+/* call used is the same as caller saved
+   + fixed regs + args + ret vals */
+#define CALL_USED_REGISTERS		     \
+    { 					     \
+/*        +0  1  2  3  4  5  6  7  8  9 */   \
+/*   0 */  1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     \
+/*  10 */  1, 1, 1, 1, 1, 1, 0, 0, 0, 0,     \
+/*  20 */  0, 0, 0, 0, 1, 1, 1, 1, 0, 1,     \
+/*  30 */  1, 0, 1, 1, 1, 1, 1, 1, 1, 1,     \
+/*  40 */  1,                                \
+    }
+
+#define HARD_REGNO_NREGS(REGNO, MODE)            \
+   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)  \
+    / UNITS_PER_WORD)
+
+/* --------------------------- *
+ * How Values Fit in Registers
+ * --------------------------- */
+
+#define HARD_REGNO_MODE_OK(REGNO, MODE) 1
+
+#define MODES_TIEABLE_P(MODE1, MODE2) 1
+
+
+/*************************
+ * Register Classes
+ *************************/
+
+enum reg_class
+{
+    NO_REGS,
+    ALL_REGS,
+    LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+#define REG_CLASS_NAMES   \
+    {"NO_REGS",           \
+     "ALL_REGS"}
+
+#define GENERAL_REGS ALL_REGS
+
+#define REG_CLASS_CONTENTS   \
+/* NO_REGS  */       {{ 0, 0},     \
+/* ALL_REGS */        {~0,~0}}    \
+
+#define REGNO_REG_CLASS(REGNO) ALL_REGS
+
+#define BASE_REG_CLASS ALL_REGS
+#define INDEX_REG_CLASS ALL_REGS
+
+/* only one reg class, 'r', is handled automatically */
+#define REG_CLASS_FROM_LETTER(CHAR) NO_REGS
+
+#define REGNO_OK_FOR_BASE_P2(REGNO, STRICT) \
+    ((STRICT) \
+     ? (REGNO) < FIRST_PSEUDO_REGISTER \
+     : (REGNO) < FIRST_PSEUDO_REGISTER || (reg_renumber && reg_renumber[REGNO] < FIRST_PSEUDO_REGISTER))
+
+#define REGNO_OK_FOR_INDEX_P2(REGNO, STRICT) \
+    (REGNO_OK_FOR_BASE_P2 (REGNO, STRICT))
+
+#define REGNO_OK_FOR_BASE_P(REGNO) \
+    (REGNO_OK_FOR_BASE_P2 (REGNO, 1))
+
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
+    (REGNO_OK_FOR_INDEX_P2 (REGNO, 1))
+
+#define REG_OK_FOR_BASE_P2(X, STRICT)                                   \
+    (STRICT                                                             \
+     ? REGNO_OK_FOR_BASE_P2 (REGNO (X), 1)                              \
+     : REGNO_OK_FOR_BASE_P2 (REGNO (X), 1) || REGNO(X) >= FIRST_PSEUDO_REGISTER)
+
+#define REG_OK_FOR_INDEX_P2(X, STRICT)                                  \
+    (STRICT                                                             \
+     ? REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1)                             \
+     : REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1) || REGNO(X) >= FIRST_PSEUDO_REGISTER)
+
+#define CLASS_MAX_NREGS(CLASS, MODE)             \
+   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1)  \
+    / UNITS_PER_WORD)
+
+
+#define SMALL_INT(X) ((unsigned HOST_WIDE_INT) ((X) + 0x8000) < 0x10000)
+#define SMALL_INT_UNSIGNED(X) ((unsigned HOST_WIDE_INT) (X) < 0x10000)
+#define UPPER16_INT(X) (((X) & 0xffff) == 0)
+#define SHIFT_INT(X) ((X) >= 0 && (X) <= 31)
+#define RDWRCTL_INT(X) ((X) >= 0 && (X) <= 31)
+#define CUSTOM_INSN_OPCODE(X) ((X) >= 0 && (X) <= 255)
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C)			\
+ (							\
+  (C) == 'I' ? SMALL_INT (VALUE) :			\
+  (C) == 'J' ? SMALL_INT_UNSIGNED (VALUE) :		\
+  (C) == 'K' ? UPPER16_INT (VALUE) :         		\
+  (C) == 'L' ? SHIFT_INT (VALUE) :			\
+  (C) == 'M' ? (VALUE) == 0 :				\
+  (C) == 'N' ? CUSTOM_INSN_OPCODE (VALUE) :		\
+  (C) == 'O' ? RDWRCTL_INT (VALUE) :			\
+  0)
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0
+
+#define PREFERRED_RELOAD_CLASS(X, CLASS) \
+    ((CLASS) == NO_REGS ? GENERAL_REGS : (CLASS))
+
+/* 'S' matches immediates which are in small data 
+   and therefore can be added to gp to create a 
+   32-bit value. */
+#define EXTRA_CONSTRAINT(VALUE, C)		\
+  ((C) == 'S' 					\
+   && (GET_CODE (VALUE) == SYMBOL_REF)   	\
+   && SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (VALUE))
+
+
+
+
+/* Say that the epilogue uses the return address register.  Note that
+   in the case of sibcalls, the values "used by the epilogue" are
+   considered live at the start of the called function.  */
+#define EPILOGUE_USES(REGNO) ((REGNO) == RA_REGNO)
+
+
+#define DEFAULT_MAIN_RETURN  c_expand_return (integer_zero_node)
+
+/**********************************
+ * Trampolines for Nested Functions
+ ***********************************/
+
+#define TRAMPOLINE_TEMPLATE(FILE) \
+    error ("trampolines not yet implemented")
+#define TRAMPOLINE_SIZE 20
+#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
+    error ("trampolines not yet implemented")
+
+/***************************
+ * Stack Layout and Calling Conventions
+ ***************************/
+
+/* ------------------ *
+ * Basic Stack Layout
+ * ------------------ */
+
+/* The downward variants are used by the compiler,
+   the upward ones serve as documentation */
+#define STACK_GROWS_DOWNWARD
+#define FRAME_GROWS_UPWARD
+#define ARGS_GROW_UPWARD
+
+#define STARTING_FRAME_OFFSET current_function_outgoing_args_size
+#define FIRST_PARM_OFFSET(FUNDECL) 0
+
+/* Before the prologue, RA lives in r31.  */
+#define INCOMING_RETURN_ADDR_RTX  gen_rtx_REG (VOIDmode, RA_REGNO)
+
+/* -------------------------------------- *
+ * Registers That Address the Stack Frame
+ * -------------------------------------- */
+
+#define STACK_POINTER_REGNUM SP_REGNO
+#define STATIC_CHAIN_REGNUM SC_REGNO
+#define PC_REGNUM PC_REGNO
+#define DWARF_FRAME_RETURN_COLUMN RA_REGNO
+
+/* Base register for access to local variables of the function.  We
+   pretend that the frame pointer is a non-existent hard register, and 
+   then eliminate it to HARD_FRAME_POINTER_REGNUM. */
+#define FRAME_POINTER_REGNUM FAKE_FP_REGNO
+
+#define HARD_FRAME_POINTER_REGNUM FP_REGNO
+#define RETURN_ADDRESS_POINTER_REGNUM RAP_REGNO
+/* the argumnet pointer needs to always be eliminated
+   so it is set to a fake hard register. */
+#define ARG_POINTER_REGNUM FAKE_AP_REGNO
+
+/* ----------------------------------------- *
+ * Eliminating Frame Pointer and Arg Pointer
+ * ----------------------------------------- */
+
+#define FRAME_POINTER_REQUIRED 0
+
+#define ELIMINABLE_REGS							\
+{{ ARG_POINTER_REGNUM,   STACK_POINTER_REGNUM},				\
+ { ARG_POINTER_REGNUM,   HARD_FRAME_POINTER_REGNUM},			\
+ { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM},		\
+ { RETURN_ADDRESS_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},		\
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},				\
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
+
+#define CAN_ELIMINATE(FROM, TO)	1
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+	(OFFSET) = nios2_initial_elimination_offset ((FROM), (TO))
+
+#define MUST_SAVE_REGISTER(regno) \
+ ((regs_ever_live[regno] && !call_used_regs[regno])			\
+  || (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)	\
+  || (regno == RA_REGNO && regs_ever_live[RA_REGNO]))
+
+/* Treat LOC as a byte offset from the stack pointer and round it up
+   to the next fully-aligned offset.  */
+#define STACK_ALIGN(LOC)						\
+  (((LOC) + ((PREFERRED_STACK_BOUNDARY / 8) - 1)) & ~((PREFERRED_STACK_BOUNDARY / 8) - 1))
+
+
+/* ------------------------------ *
+ * Passing Arguments in Registers
+ * ------------------------------ */
+
+/* see nios2.c */
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+  (function_arg (&CUM, MODE, TYPE, NAMED))
+
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
+  (function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED))
+
+#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) 0
+
+#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) 0
+
+typedef struct nios2_args
+{
+    int regs_used;
+} CUMULATIVE_ARGS;
+
+/* This is to initialize the above unused CUM data type */
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
+    (init_cumulative_args (&CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS))
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+    (function_arg_advance (&CUM, MODE, TYPE, NAMED))
+
+#define FUNCTION_ARG_REGNO_P(REGNO) \
+    ((REGNO) >= FIRST_ARG_REGNO && (REGNO) <= LAST_ARG_REGNO)
+
+#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL)   \
+  {								    \
+    int pret_size = nios2_setup_incoming_varargs (&(CUM), (MODE),	    \
+						(TYPE), (NO_RTL));  \
+    if (pret_size)						    \
+      (PRETEND_SIZE) = pret_size;				    \
+  }
+
+/* ----------------------------- *
+ * Generating Code for Profiling
+ * ----------------------------- */
+
+#define PROFILE_BEFORE_PROLOGUE
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+  function_profiler ((FILE), (LABELNO))
+
+/* --------------------------------------- *
+ * Passing Function Arguments on the Stack
+ * --------------------------------------- */
+
+#define PROMOTE_PROTOTYPES 1
+
+#define PUSH_ARGS 0
+#define ACCUMULATE_OUTGOING_ARGS 1
+
+#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACKSIZE) 0
+
+/* --------------------------------------- *
+ * How Scalar Function Values Are Returned
+ * --------------------------------------- */
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+    gen_rtx(REG, TYPE_MODE(VALTYPE), FIRST_RETVAL_REGNO)
+
+#define LIBCALL_VALUE(MODE) \
+    gen_rtx(REG, MODE, FIRST_RETVAL_REGNO)
+
+#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == FIRST_RETVAL_REGNO)
+
+/* ----------------------------- *
+ * How Large Values Are Returned
+ * ----------------------------- */
+
+
+#define RETURN_IN_MEMORY(TYPE)	\
+  nios2_return_in_memory (TYPE)
+
+
+#define STRUCT_VALUE 0
+
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/*******************
+ * Addressing Modes
+ *******************/
+
+
+#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)
+
+#define CONSTANT_ADDRESS_P(X) (CONSTANT_P (X))
+
+#define MAX_REGS_PER_ADDRESS 1
+
+/* Go to ADDR if X is a valid address.  */
+#ifndef REG_OK_STRICT
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)        \
+    {                                                  \
+        if (nios2_legitimate_address ((X), (MODE), 0))  \
+            goto ADDR;                                 \
+    }
+#else
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)        \
+    {                                                  \
+        if (nios2_legitimate_address ((X), (MODE), 1))  \
+            goto ADDR;                                 \
+    }
+#endif
+
+#ifndef REG_OK_STRICT
+#define REG_OK_FOR_BASE_P(X)   REGNO_OK_FOR_BASE_P2 (REGNO (X), 0)
+#define REG_OK_FOR_INDEX_P(X)  REGNO_OK_FOR_INDEX_P2 (REGNO (X), 0)
+#else
+#define REG_OK_FOR_BASE_P(X)   REGNO_OK_FOR_BASE_P2 (REGNO (X), 1)
+#define REG_OK_FOR_INDEX_P(X)  REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1)
+#endif
+
+#define LEGITIMATE_CONSTANT_P(X) 1
+
+/* Nios II has no mode dependent addresses.  */
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
+
+/* Set if this has a weak declaration  */
+#define SYMBOL_FLAG_WEAK_DECL	(1 << SYMBOL_FLAG_MACH_DEP_SHIFT)
+#define SYMBOL_REF_WEAK_DECL_P(RTX) \
+  ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_WEAK_DECL) != 0)
+
+
+/* true if a symbol is both small and not weak. In this case, gp
+   relative access can be used */
+#define SYMBOL_REF_IN_NIOS2_SMALL_DATA_P(RTX) \
+   (SYMBOL_REF_SMALL_P(RTX) && !SYMBOL_REF_WEAK_DECL_P(RTX))
+
+/*****************
+ * Describing Relative Costs of Operations
+ *****************/
+
+#define SLOW_BYTE_ACCESS 1
+
+/* It is as good to call a constant function address as to call an address
+   kept in a register.
+   ??? Not true anymore really. Now that call cannot address full range
+   of memory callr may need to be used */
+
+#define NO_FUNCTION_CSE
+#define NO_RECURSIVE_FUNCTION_CSE
+
+
+
+/*****************************************
+ * Defining the Output Assembler Language
+ *****************************************/
+
+/* ------------------------------------------ *
+ * The Overall Framework of an Assembler File
+ * ------------------------------------------ */
+
+#define ASM_APP_ON "#APP\n"
+#define ASM_APP_OFF "#NO_APP\n"
+
+#define ASM_COMMENT_START "# "
+
+/* ------------------------------- *
+ * Output and Generation of Labels
+ * ------------------------------- */
+
+#define GLOBAL_ASM_OP "\t.global\t"
+
+
+/* -------------- *
+ * Output of Data
+ * -------------- */
+
+#define DWARF2_UNWIND_INFO 0
+
+
+/* -------------------------------- *
+ * Assembler Commands for Alignment
+ * -------------------------------- */
+
+#define ASM_OUTPUT_ALIGN(FILE, LOG) \
+  do { \
+    fprintf ((FILE), "%s%d\n", ALIGN_ASM_OP, (LOG)); \
+  } while (0)
+
+
+/* -------------------------------- *
+ * Output of Assembler Instructions
+ * -------------------------------- */
+
+#define REGISTER_NAMES \
+{ \
+    "zero", \
+    "at", \
+    "r2", \
+    "r3", \
+    "r4", \
+    "r5", \
+    "r6", \
+    "r7", \
+    "r8", \
+    "r9", \
+    "r10", \
+    "r11", \
+    "r12", \
+    "r13", \
+    "r14", \
+    "r15", \
+    "r16", \
+    "r17", \
+    "r18", \
+    "r19", \
+    "r20", \
+    "r21", \
+    "r22", \
+    "r23", \
+    "r24", \
+    "r25", \
+    "gp", \
+    "sp", \
+    "fp", \
+    "ta", \
+    "ba", \
+    "ra", \
+    "status", \
+    "estatus", \
+    "bstatus", \
+    "ipri", \
+    "ecause", \
+    "pc", \
+    "rap", \
+    "fake_fp", \
+    "fake_ap", \
+}
+
+#define ASM_OUTPUT_OPCODE(STREAM, PTR)\
+   (PTR) = asm_output_opcode (STREAM, PTR)
+
+#define PRINT_OPERAND(STREAM, X, CODE) \
+    nios2_print_operand (STREAM, X, CODE)
+
+#define PRINT_OPERAND_ADDRESS(STREAM, X) \
+    nios2_print_operand_address (STREAM, X)
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)  \
+do { fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), FILE); \
+     fprintf (FILE, ".L%u\n", (unsigned) (VALUE));               \
+   } while (0)
+
+
+/* ------------ *
+ * Label Output
+ * ------------ */
+
+
+/* ---------------------------------------------------- *
+ * Dividing the Output into Sections (Texts, Data, ...)
+ * ---------------------------------------------------- */
+
+/* Output before read-only data.  */
+#define TEXT_SECTION_ASM_OP ("\t.section\t.text")
+
+/* Output before writable data.  */
+#define DATA_SECTION_ASM_OP ("\t.section\t.data")
+
+
+/* Default the definition of "small data" to 8 bytes. */
+/* ??? How come I can't use HOST_WIDE_INT here? */
+extern unsigned long nios2_section_threshold;
+#define NIOS2_DEFAULT_GVALUE 8
+
+
+
+/* This says how to output assembler code to declare an
+   uninitialized external linkage data object.  Under SVR4,
+   the linker seems to want the alignment of data objects
+   to depend on their types.  We do exactly that here.  */
+
+#undef COMMON_ASM_OP
+#define COMMON_ASM_OP	"\t.comm\t"
+
+#undef  ASM_OUTPUT_ALIGNED_COMMON
+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN)		\
+do 									\
+{									\
+  if ((SIZE) <= nios2_section_threshold)				\
+    {									\
+      named_section (0, ".sbss", 0);					\
+      (*targetm.asm_out.globalize_label) (FILE, NAME);			\
+      ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object");			\
+      if (!flag_inhibit_size_directive)					\
+	ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE);			\
+      ASM_OUTPUT_ALIGN ((FILE), exact_log2((ALIGN) / BITS_PER_UNIT));	\
+      ASM_OUTPUT_LABEL(FILE, NAME);					\
+      ASM_OUTPUT_SKIP((FILE), (SIZE) ? (SIZE) : 1);			\
+    }									\
+  else									\
+    {									\
+      fprintf ((FILE), "%s", COMMON_ASM_OP);				\
+      assemble_name ((FILE), (NAME));					\
+      fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT);	\
+    }									\
+}									\
+while (0)
+
+
+/* This says how to output assembler code to declare an
+   uninitialized internal linkage data object.  Under SVR4,
+   the linker seems to want the alignment of data objects
+   to depend on their types.  We do exactly that here.  */
+
+#undef  ASM_OUTPUT_ALIGNED_LOCAL
+#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN)		\
+do {									\
+  if ((SIZE) <= nios2_section_threshold)				\
+    named_section (0, ".sbss", 0);					\
+  else									\
+    named_section (0, ".bss", 0);					\
+  ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object");			\
+  if (!flag_inhibit_size_directive)					\
+    ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE);			\
+  ASM_OUTPUT_ALIGN ((FILE), exact_log2((ALIGN) / BITS_PER_UNIT));	\
+  ASM_OUTPUT_LABEL(FILE, NAME);						\
+  ASM_OUTPUT_SKIP((FILE), (SIZE) ? (SIZE) : 1);				\
+} while (0)
+
+
+
+/***************************
+ * Miscellaneous Parameters
+ ***************************/
+
+#define MOVE_MAX 4
+
+#define Pmode SImode
+#define FUNCTION_MODE QImode
+
+#define CASE_VECTOR_MODE Pmode
+
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+#define LOAD_EXTEND_OP(MODE) (ZERO_EXTEND)
+
+#define WORD_REGISTER_OPERATIONS
--- gcc-3.4.3/gcc/config/nios2/nios2.md
+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.md
@@ -0,0 +1,2078 @@
+;; Machine Description for Altera NIOS 2G NIOS2 version.
+;;    Copyright (C) 2003 Altera 
+;;    Contributed by Jonah Graham (jgraham@altera.com).
+;; 
+;; This file is part of GNU CC.
+;; 
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;; 
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;; 
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING.  If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.  */
+
+
+
+;*****************************************************************************
+;*
+;* constants
+;*
+;*****************************************************************************
+(define_constants [
+  (GP_REGNO 26)
+  (SP_REGNO 27)
+  (FP_REGNO 28)
+  (RA_REGNO 31)
+  (RAP_REGNO 38)
+  (FIRST_RETVAL_REGNO 2)
+  (LAST_RETVAL_REGNO 3)
+  (FIRST_ARG_REGNO 4)
+  (LAST_ARG_REGNO 7)
+  (SC_REGNO 23)
+  (PC_REGNO 37)
+  (FAKE_FP_REGNO 39)
+  (FAKE_AP_REGNO 40)
+
+
+  (UNSPEC_BLOCKAGE 0)
+  (UNSPEC_LDBIO 1)
+  (UNSPEC_LDBUIO 2)
+  (UNSPEC_LDHIO 3)
+  (UNSPEC_LDHUIO 4)
+  (UNSPEC_LDWIO 5)
+  (UNSPEC_STBIO 6)
+  (UNSPEC_STHIO 7)
+  (UNSPEC_STWIO 8)
+  (UNSPEC_SYNC 9)
+  (UNSPEC_WRCTL 10)
+  (UNSPEC_RDCTL 11)
+  
+])
+
+
+
+;*****************************************************************************
+;*
+;* instruction scheduler
+;*
+;*****************************************************************************
+
+; No schedule info is currently available, using an assumption that no
+; instruction can use the results of the previous instruction without
+; incuring a stall.
+
+; length of an instruction (in bytes)
+(define_attr "length" "" (const_int 4))
+(define_attr "type" "unknown,complex,control,alu,cond_alu,st,ld,shift,mul,div,custom" (const_string "complex"))
+
+(define_asm_attributes
+ [(set_attr "length" "4")
+  (set_attr "type" "complex")])
+
+(define_automaton "nios2")
+(automata_option "v")
+;(automata_option "no-minimization")
+(automata_option "ndfa")
+
+; The nios2 pipeline is fairly straightforward for the fast model.
+; Every alu operation is pipelined so that an instruction can
+; be issued every cycle. However, there are still potential
+; stalls which this description tries to deal with.
+
+(define_cpu_unit "cpu" "nios2")
+
+(define_insn_reservation "complex" 1
+  (eq_attr "type" "complex")
+  "cpu")
+
+(define_insn_reservation "control" 1
+  (eq_attr "type" "control")
+  "cpu")
+
+(define_insn_reservation "alu" 1
+  (eq_attr "type" "alu")
+  "cpu")
+
+(define_insn_reservation "cond_alu" 1
+  (eq_attr "type" "cond_alu")
+  "cpu")
+
+(define_insn_reservation "st" 1
+  (eq_attr "type" "st")
+  "cpu")
+  
+(define_insn_reservation "custom" 1
+  (eq_attr "type" "custom")
+  "cpu")
+
+; shifts, muls and lds have three cycle latency
+(define_insn_reservation "ld" 3
+  (eq_attr "type" "ld")
+  "cpu")
+
+(define_insn_reservation "shift" 3
+  (eq_attr "type" "shift")
+  "cpu")
+
+(define_insn_reservation "mul" 3
+  (eq_attr "type" "mul")
+  "cpu")
+
+(define_insn_reservation "div" 1
+  (eq_attr "type" "div")
+  "cpu")
+
+
+;*****************************************************************************
+;*
+;* MOV Instructions
+;*
+;*****************************************************************************
+
+(define_expand "movqi"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "")
+        (match_operand:QI 1 "general_operand" ""))]
+  ""
+{
+  if (nios2_emit_move_sequence (operands, QImode))
+    DONE;
+})
+
+(define_insn "movqi_internal"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=m, r,r, r")
+        (match_operand:QI 1 "general_operand"       "rM,m,rM,I"))]
+  "(register_operand (operands[0], QImode)
+    || register_operand (operands[1], QImode)
+    || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
+  "@
+    stb%o0\\t%z1, %0
+    ldbu%o1\\t%0, %1
+    mov\\t%0, %z1
+    movi\\t%0, %1"
+  [(set_attr "type" "st,ld,alu,alu")])
+
+(define_insn "ldbio"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec_volatile:SI [(const_int 0)] UNSPEC_LDBIO))
+   (use (match_operand:SI 1 "memory_operand" "m"))]
+  ""
+  "ldbio\\t%0, %1"
+  [(set_attr "type" "ld")])
+
+(define_insn "ldbuio"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec_volatile:SI [(const_int 0)] UNSPEC_LDBUIO))
+   (use (match_operand:SI 1 "memory_operand" "m"))]
+  ""
+  "ldbuio\\t%0, %1"
+  [(set_attr "type" "ld")])
+
+(define_insn "stbio"
+  [(set (match_operand:SI 0 "memory_operand" "=m")
+	(match_operand:SI 1 "register_operand"   "r"))
+   (unspec_volatile:SI [(const_int 0)] UNSPEC_STBIO)]
+  ""
+  "stbio\\t%z1, %0"
+  [(set_attr "type" "st")])
+
+
+(define_expand "movhi"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "")
+        (match_operand:HI 1 "general_operand" ""))]
+  ""
+{
+  if (nios2_emit_move_sequence (operands, HImode))
+    DONE;
+})
+
+(define_insn "movhi_internal"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=m, r,r, r,r")
+        (match_operand:HI 1 "general_operand"       "rM,m,rM,I,J"))]
+  "(register_operand (operands[0], HImode)
+    || register_operand (operands[1], HImode)
+    || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
+  "@
+    sth%o0\\t%z1, %0
+    ldhu%o1\\t%0, %1
+    mov\\t%0, %z1
+    movi\\t%0, %1
+    movui\\t%0, %1"
+  [(set_attr "type" "st,ld,alu,alu,alu")])
+
+(define_insn "ldhio"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec_volatile:SI [(const_int 0)] UNSPEC_LDHIO))
+   (use (match_operand:SI 1 "memory_operand" "m"))]
+  ""
+  "ldhio\\t%0, %1"
+  [(set_attr "type" "ld")])
+
+(define_insn "ldhuio"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec_volatile:SI [(const_int 0)] UNSPEC_LDHUIO))
+   (use (match_operand:SI 1 "memory_operand" "m"))]
+  ""
+  "ldhuio\\t%0, %1"
+  [(set_attr "type" "ld")])
+
+(define_insn "sthio"
+  [(set (match_operand:SI 0 "memory_operand" "=m")
+	(match_operand:SI 1 "register_operand"   "r"))
+   (unspec_volatile:SI [(const_int 0)] UNSPEC_STHIO)]
+  ""
+  "sthio\\t%z1, %0"
+  [(set_attr "type" "st")])
+
+(define_expand "movsi"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "")
+        (match_operand:SI 1 "general_operand" ""))]
+  ""
+{
+  if (nios2_emit_move_sequence (operands, SImode))
+    DONE;
+})
+
+(define_insn "movsi_internal"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r, r,r,r,r")
+        (match_operand:SI 1 "general_operand"       "rM,m,rM,I,J,S,i"))]
+  "(register_operand (operands[0], SImode)
+    || register_operand (operands[1], SImode)
+    || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
+  "@
+    stw%o0\\t%z1, %0
+    ldw%o1\\t%0, %1
+    mov\\t%0, %z1
+    movi\\t%0, %1
+    movui\\t%0, %1
+    addi\\t%0, gp, %%gprel(%1)
+    movhi\\t%0, %H1\;addi\\t%0, %0, %L1"
+  [(set_attr "type" "st,ld,alu,alu,alu,alu,alu")])
+
+(define_insn "ldwio"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec_volatile:SI [(const_int 0)] UNSPEC_LDWIO))
+   (use (match_operand:SI 1 "memory_operand" "m"))]
+  ""
+  "ldwio\\t%0, %1"
+  [(set_attr "type" "ld")])
+
+(define_insn "stwio"
+  [(set (match_operand:SI 0 "memory_operand" "=m")
+	(match_operand:SI 1 "register_operand"   "r"))
+   (unspec_volatile:SI [(const_int 0)] UNSPEC_STWIO)]
+  ""
+  "stwio\\t%z1, %0"
+  [(set_attr "type" "st")])
+
+
+
+;*****************************************************************************
+;*
+;* zero extension
+;*
+;*****************************************************************************
+
+
+(define_insn "zero_extendhisi2"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+  ""
+  "@
+    andi\\t%0, %1, 0xffff
+    ldhu%o1\\t%0, %1"
+  [(set_attr "type"	"alu,ld")])
+
+(define_insn "zero_extendqihi2"
+  [(set (match_operand:HI 0 "register_operand" "=r,r")
+	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
+  ""
+  "@
+    andi\\t%0, %1, 0xff
+    ldbu%o1\\t%0, %1"
+  [(set_attr "type"	"alu,ld")])
+
+(define_insn "zero_extendqisi2"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
+  ""
+  "@
+    andi\\t%0, %1, 0xff
+    ldbu%o1\\t%0, %1"
+  [(set_attr "type"	"alu,ld")])
+
+
+
+;*****************************************************************************
+;*
+;* sign extension
+;*
+;*****************************************************************************
+
+(define_expand "extendhisi2"
+  [(set (match_operand:SI 0 "register_operand" "")
+	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
+  ""
+{
+  if (optimize && GET_CODE (operands[1]) == MEM)
+    operands[1] = force_not_mem (operands[1]);
+
+  if (GET_CODE (operands[1]) != MEM)
+    {
+      rtx op1   = gen_lowpart (SImode, operands[1]);
+      rtx temp  = gen_reg_rtx (SImode);
+      rtx shift = GEN_INT (16);
+
+      emit_insn (gen_ashlsi3 (temp, op1, shift));
+      emit_insn (gen_ashrsi3 (operands[0], temp, shift));
+      DONE;
+    }
+})
+
+(define_insn "extendhisi2_internal"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
+  ""
+  "ldh%o1\\t%0, %1"
+  [(set_attr "type"	"ld")])
+
+(define_expand "extendqihi2"
+  [(set (match_operand:HI 0 "register_operand" "")
+	(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))]
+  ""
+{
+  if (optimize && GET_CODE (operands[1]) == MEM)
+    operands[1] = force_not_mem (operands[1]);
+
+  if (GET_CODE (operands[1]) != MEM)
+    {
+      rtx op0   = gen_lowpart (SImode, operands[0]);
+      rtx op1   = gen_lowpart (SImode, operands[1]);
+      rtx temp  = gen_reg_rtx (SImode);
+      rtx shift = GEN_INT (24);
+
+      emit_insn (gen_ashlsi3 (temp, op1, shift));
+      emit_insn (gen_ashrsi3 (op0, temp, shift));
+      DONE;
+    }
+})
+
+(define_insn "extendqihi2_internal"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+	(sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
+  ""
+  "ldb%o1\\t%0, %1"
+  [(set_attr "type"	"ld")])
+
+
+(define_expand "extendqisi2"
+  [(set (match_operand:SI 0 "register_operand" "")
+	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
+  ""
+{
+  if (optimize && GET_CODE (operands[1]) == MEM)
+    operands[1] = force_not_mem (operands[1]);
+
+  if (GET_CODE (operands[1]) != MEM)
+    {
+      rtx op1   = gen_lowpart (SImode, operands[1]);
+      rtx temp  = gen_reg_rtx (SImode);
+      rtx shift = GEN_INT (24);
+
+      emit_insn (gen_ashlsi3 (temp, op1, shift));
+      emit_insn (gen_ashrsi3 (operands[0], temp, shift));
+      DONE;
+    }
+})
+
+(define_insn "extendqisi2_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
+  ""
+  "ldb%o1\\t%0, %1"
+  [(set_attr "type"	"ld")])
+
+
+
+;*****************************************************************************
+;*
+;* Arithmetic Operations
+;*
+;*****************************************************************************
+
+(define_insn "addsi3"
+  [(set (match_operand:SI 0 "register_operand"          "=r,r")
+        (plus:SI (match_operand:SI 1 "register_operand" "%r,r")
+                 (match_operand:SI 2 "arith_operand"     "r,I")))]
+  ""
+  "add%i2\\t%0, %1, %z2"
+  [(set_attr "type" "alu")])
+
+(define_insn "subsi3"
+  [(set (match_operand:SI 0 "register_operand"           "=r")
+        (minus:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
+                  (match_operand:SI 2 "register_operand"  "r")))]
+  ""
+  "sub\\t%0, %z1, %2"
+  [(set_attr "type" "alu")])
+
+(define_insn "mulsi3"
+  [(set (match_operand:SI 0 "register_operand"            "=r,r")
+        (mult:SI (match_operand:SI 1 "register_operand"    "r,r")
+                 (match_operand:SI 2 "arith_operand"       "r,I")))]
+  "TARGET_HAS_MUL"
+  "mul%i2\\t%0, %1, %z2"
+  [(set_attr "type" "mul")])
+
+(define_expand "divsi3"
+  [(set (match_operand:SI 0 "register_operand"            "=r")
+        (div:SI (match_operand:SI 1 "register_operand"     "r")
+                (match_operand:SI 2 "register_operand"     "r")))]
+  ""
+{
+  if (!TARGET_HAS_DIV)
+    {
+      if (!TARGET_FAST_SW_DIV)
+	FAIL;
+      else
+        {
+	  if (nios2_emit_expensive_div (operands, SImode))
+	    DONE;
+	}
+    }
+})
+
+(define_insn "divsi3_insn"
+  [(set (match_operand:SI 0 "register_operand"            "=r")
+        (div:SI (match_operand:SI 1 "register_operand"     "r")
+                (match_operand:SI 2 "register_operand"     "r")))]
+  "TARGET_HAS_DIV"
+  "div\\t%0, %1, %2"
+  [(set_attr "type" "div")])
+
+(define_insn "udivsi3"
+  [(set (match_operand:SI 0 "register_operand"            "=r")
+        (udiv:SI (match_operand:SI 1 "register_operand"     "r")
+                (match_operand:SI 2 "register_operand"     "r")))]
+  "TARGET_HAS_DIV"
+  "divu\\t%0, %1, %2"
+  [(set_attr "type" "div")])
+
+(define_insn "smulsi3_highpart"
+  [(set (match_operand:SI 0 "register_operand"                            "=r")
+	(truncate:SI
+	 (lshiftrt:DI
+	  (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand"  "r"))
+		   (sign_extend:DI (match_operand:SI 2 "register_operand"  "r")))
+	  (const_int 32))))]
+  "TARGET_HAS_MULX"
+  "mulxss\\t%0, %1, %2"
+  [(set_attr "type" "mul")])
+
+(define_insn "umulsi3_highpart"
+  [(set (match_operand:SI 0 "register_operand"                            "=r")
+	(truncate:SI
+	 (lshiftrt:DI
+	  (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"  "r"))
+		   (zero_extend:DI (match_operand:SI 2 "register_operand"  "r")))
+	  (const_int 32))))]
+  "TARGET_HAS_MULX"
+  "mulxuu\\t%0, %1, %2"
+  [(set_attr "type" "mul")])
+
+
+(define_expand "mulsidi3"
+    [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0)
+	  (mult:SI (match_operand:SI 1 "register_operand" "")
+		   (match_operand:SI 2 "register_operand" "")))
+     (set (subreg:SI (match_dup 0) 4)
+	  (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
+					     (sign_extend:DI (match_dup 2)))
+				    (const_int 32))))]
+  "TARGET_HAS_MULX"
+  "")
+
+(define_expand "umulsidi3"
+    [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0)
+	  (mult:SI (match_operand:SI 1 "register_operand" "")
+		   (match_operand:SI 2 "register_operand" "")))
+     (set (subreg:SI (match_dup 0) 4)
+	  (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
+					     (zero_extend:DI (match_dup 2)))
+				    (const_int 32))))]
+  "TARGET_HAS_MULX"
+  "")
+
+
+
+;*****************************************************************************
+;*
+;* Negate and ones complement
+;*
+;*****************************************************************************
+
+(define_insn "negsi2"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+	(neg:SI (match_operand:SI 1 "register_operand" "r")))]
+  ""
+{
+  operands[2] = const0_rtx;
+  return "sub\\t%0, %z2, %1";
+}
+  [(set_attr "type" "alu")])
+
+(define_insn "one_cmplsi2"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+	(not:SI (match_operand:SI 1 "register_operand" "r")))]
+  ""
+{
+  operands[2] = const0_rtx;
+  return "nor\\t%0, %z2, %1";
+}
+  [(set_attr "type" "alu")])
+
+
+
+; Logical Operantions
+
+(define_insn "andsi3"
+  [(set (match_operand:SI 0 "register_operand"         "=r, r,r")
+        (and:SI (match_operand:SI 1 "register_operand" "%r, r,r")
+                (match_operand:SI 2 "logical_operand"   "rM,J,K")))]
+  ""
+  "@
+    and\\t%0, %1, %z2
+    and%i2\\t%0, %1, %2
+    andh%i2\\t%0, %1, %U2"
+  [(set_attr "type" "alu")])
+
+(define_insn "iorsi3"
+  [(set (match_operand:SI 0 "register_operand"          "=r, r,r")
+        (ior:SI (match_operand:SI 1 "register_operand"  "%r, r,r")
+                (match_operand:SI 2 "logical_operand"    "rM,J,K")))]
+  ""
+  "@
+    or\\t%0, %1, %z2
+    or%i2\\t%0, %1, %2
+    orh%i2\\t%0, %1, %U2"
+  [(set_attr "type" "alu")])
+
+(define_insn "*norsi3"
+  [(set (match_operand:SI 0 "register_operand"                  "=r")
+        (and:SI (not:SI (match_operand:SI 1 "register_operand"  "%r"))
+                (not:SI (match_operand:SI 2 "reg_or_0_operand"   "rM"))))]
+  ""
+  "nor\\t%0, %1, %z2"
+  [(set_attr "type" "alu")])
+
+(define_insn "xorsi3"
+  [(set (match_operand:SI 0 "register_operand"          "=r, r,r")
+        (xor:SI (match_operand:SI 1 "register_operand"  "%r, r,r")
+                (match_operand:SI 2 "logical_operand"    "rM,J,K")))]
+  ""
+  "@
+    xor\\t%0, %1, %z2
+    xor%i2\\t%0, %1, %2
+    xorh%i2\\t%0, %1, %U2"
+  [(set_attr "type" "alu")])
+
+
+
+;*****************************************************************************
+;*
+;* Shifts
+;*
+;*****************************************************************************
+
+(define_insn "ashlsi3"
+  [(set (match_operand:SI 0 "register_operand"           "=r,r")
+	(ashift:SI (match_operand:SI 1 "register_operand" "r,r")
+		   (match_operand:SI 2 "shift_operand"    "r,L")))]
+  ""
+  "sll%i2\\t%0, %1, %z2"
+  [(set_attr "type" "shift")])
+
+(define_insn "ashrsi3"
+  [(set (match_operand:SI 0 "register_operand"             "=r,r")
+	(ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
+		     (match_operand:SI 2 "shift_operand"    "r,L")))]
+  ""
+  "sra%i2\\t%0, %1, %z2"
+  [(set_attr "type" "shift")])
+
+(define_insn "lshrsi3"
+  [(set (match_operand:SI 0 "register_operand"             "=r,r")
+	(lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
+		     (match_operand:SI 2 "shift_operand"    "r,L")))]
+  ""
+  "srl%i2\\t%0, %1, %z2"
+  [(set_attr "type" "shift")])
+
+(define_insn "rotlsi3"
+  [(set (match_operand:SI 0 "register_operand"           "=r,r")
+	(rotate:SI (match_operand:SI 1 "register_operand" "r,r")
+		   (match_operand:SI 2 "shift_operand"    "r,L")))]
+  ""
+  "rol%i2\\t%0, %1, %z2"
+  [(set_attr "type" "shift")])
+
+(define_insn "rotrsi3"
+  [(set (match_operand:SI 0 "register_operand"             "=r,r")
+	(rotatert:SI (match_operand:SI 1 "register_operand" "r,r")
+		     (match_operand:SI 2 "register_operand" "r,r")))]
+  ""
+  "ror\\t%0, %1, %2"
+  [(set_attr "type" "shift")])
+
+(define_insn "*shift_mul_constants"
+  [(set (match_operand:SI 0 "register_operand"                     "=r")
+	(ashift:SI (mult:SI (match_operand:SI 1 "register_operand"  "r")
+		            (match_operand:SI 2 "const_int_operand" "I"))
+		   (match_operand:SI 3          "const_int_operand" "I")))]
+  "TARGET_HAS_MUL && SMALL_INT (INTVAL (operands[2]) << INTVAL (operands[3]))"
+{
+  HOST_WIDE_INT mul = INTVAL (operands[2]) << INTVAL (operands[3]);
+  rtx ops[3];
+  
+  ops[0] = operands[0];
+  ops[1] = operands[1];
+  ops[2] = GEN_INT (mul);
+  
+  output_asm_insn ("muli\t%0, %1, %2", ops);
+  return "";
+}
+  [(set_attr "type" "mul")])
+
+
+
+
+;*****************************************************************************
+;*
+;* Prologue, Epilogue and Return
+;*
+;*****************************************************************************
+
+(define_expand "prologue"
+  [(const_int 1)]
+  ""
+{
+  expand_prologue ();
+  DONE;
+})
+
+(define_expand "epilogue"
+  [(return)]
+  ""
+{
+  expand_epilogue (false);
+  DONE;
+})
+
+(define_expand "sibcall_epilogue"
+  [(return)]
+  ""
+{
+  expand_epilogue (true);
+  DONE;
+})
+
+(define_insn "return"
+  [(return)]
+  "reload_completed && nios2_can_use_return_insn ()"
+  "ret\\t"
+)
+
+(define_insn "return_from_epilogue"
+  [(use (match_operand 0 "pmode_register_operand" ""))
+   (return)]
+  "reload_completed"
+  "ret\\t"
+)
+
+;; Block any insns from being moved before this point, since the
+;; profiling call to mcount can use various registers that aren't
+;; saved or used to pass arguments.
+
+(define_insn "blockage"
+  [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)]
+  ""
+  ""
+  [(set_attr "type" "unknown")
+   (set_attr "length" "0")])
+
+
+
+;*****************************************************************************
+;*
+;* Jumps and Calls
+;*
+;*****************************************************************************
+
+(define_insn "indirect_jump"
+  [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
+  ""
+  "jmp\\t%0"
+  [(set_attr "type" "control")])
+
+(define_insn "jump"
+  [(set (pc)
+        (label_ref (match_operand 0 "" "")))]
+  ""
+  "br\\t%0"
+  [(set_attr "type" "control")])
+
+
+(define_insn "indirect_call"
+  [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
+         (match_operand 1 "" ""))
+   (clobber (reg:SI RA_REGNO))]
+  ""
+  "callr\\t%0"
+  [(set_attr "type" "control")])
+
+(define_insn "indirect_call_value"
+  [(set (match_operand 0 "" "")
+        (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
+              (match_operand 2 "" "")))
+   (clobber (reg:SI RA_REGNO))]
+  ""
+  "callr\\t%1"
+)
+
+(define_expand "call"
+  [(parallel [(call (match_operand 0 "" "")
+                    (match_operand 1 "" ""))
+              (clobber (reg:SI RA_REGNO))])]
+  ""
+  "")
+
+(define_expand "call_value"
+  [(parallel [(set (match_operand 0 "" "")
+                   (call (match_operand 1 "" "")
+                         (match_operand 2 "" "")))
+              (clobber (reg:SI RA_REGNO))])]
+  ""
+  "")
+
+(define_insn "*call"
+  [(call (mem:QI (match_operand:SI 0 "immediate_operand" "i"))
+         (match_operand 1 "" ""))
+   (clobber (match_operand:SI 2 "register_operand" "=r"))]
+  ""
+  "call\\t%0"
+  [(set_attr "type" "control")])
+
+(define_insn "*call_value"
+  [(set (match_operand 0 "" "")
+        (call (mem:QI (match_operand:SI 1 "immediate_operand" "i"))
+              (match_operand 2 "" "")))
+   (clobber (match_operand:SI 3 "register_operand" "=r"))]
+  ""
+  "call\\t%1"
+  [(set_attr "type" "control")])
+
+(define_expand "sibcall"
+  [(parallel [(call (match_operand 0 "" "")
+		    (match_operand 1 "" ""))
+	      (return)
+	      (use (match_operand 2 "" ""))])]
+  ""
+  {
+    XEXP (operands[0], 0) = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
+
+    if (operands[2] == NULL_RTX)
+      operands[2] = const0_rtx;
+  }
+)
+
+(define_expand "sibcall_value"
+  [(parallel [(set (match_operand 0 "" "")
+		   (call (match_operand 1 "" "")
+			 (match_operand 2 "" "")))
+	      (return)
+	      (use (match_operand 3 "" ""))])]
+  ""
+  {
+    XEXP (operands[1], 0) = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
+
+    if (operands[3] == NULL_RTX)
+      operands[3] = const0_rtx;
+  }
+)
+
+(define_insn "sibcall_insn"
+ [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
+	(match_operand 1 "" ""))
+  (return)
+  (use (match_operand 2 "" ""))]
+  ""
+  "jmp\\t%0"
+)
+
+(define_insn "sibcall_value_insn"
+ [(set (match_operand 0 "register_operand" "")
+       (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
+	     (match_operand 2 "" "")))
+  (return)
+  (use (match_operand 3 "" ""))]
+  ""
+  "jmp\\t%1"
+)
+
+
+
+
+(define_expand "tablejump"
+  [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
+              (use (label_ref (match_operand 1 "" "")))])]
+  ""
+  ""
+)
+
+(define_insn "*tablejump"
+  [(set (pc)
+	(match_operand:SI 0 "register_operand" "r"))
+   (use (label_ref (match_operand 1 "" "")))]
+  ""
+  "jmp\\t%0"
+  [(set_attr "type" "control")])
+
+
+
+;*****************************************************************************
+;*
+;* Comparisons
+;*
+;*****************************************************************************
+;; Flow here is rather complex (based on MIPS):
+;;
+;;  1)	The cmp{si,di,sf,df} routine is called.  It deposits the
+;;	arguments into the branch_cmp array, and the type into
+;;	branch_type.  No RTL is generated.
+;;
+;;  2)	The appropriate branch define_expand is called, which then
+;;	creates the appropriate RTL for the comparison and branch.
+;;	Different CC modes are used, based on what type of branch is
+;;	done, so that we can constrain things appropriately.  There
+;;	are assumptions in the rest of GCC that break if we fold the
+;;	operands into the branchs for integer operations, and use cc0
+;;	for floating point, so we use the fp status register instead.
+;;	If needed, an appropriate temporary is created to hold the
+;;	of the integer compare.
+
+(define_expand "cmpsi"
+  [(set (cc0)
+	(compare:CC (match_operand:SI 0 "register_operand" "")
+		    (match_operand:SI 1 "arith_operand" "")))]
+  ""
+{
+  branch_cmp[0] = operands[0];
+  branch_cmp[1] = operands[1];
+  branch_type = CMP_SI;
+  DONE;
+})
+
+(define_expand "tstsi"
+  [(set (cc0)
+	(match_operand:SI 0 "register_operand" ""))]
+  ""
+{
+  branch_cmp[0] = operands[0];
+  branch_cmp[1] = const0_rtx;
+  branch_type = CMP_SI;
+  DONE;
+})
+
+
+;*****************************************************************************
+;*
+;* setting a register from a comparison
+;*
+;*****************************************************************************
+
+(define_expand "seq"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(eq:SI (match_dup 1)
+	       (match_dup 2)))]
+  ""
+{
+  if (branch_type != CMP_SI)
+    FAIL;
+
+  /* set up operands from compare.  */
+  operands[1] = branch_cmp[0];
+  operands[2] = branch_cmp[1];
+
+  gen_int_relational (EQ, operands[0], operands[1], operands[2], NULL_RTX);
+  DONE;
+})
+
+
+(define_insn "*seq"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+	(eq:SI (match_operand:SI 1 "reg_or_0_operand" "%rM")
+	       (match_operand:SI 2 "arith_operand"     "rI")))]
+  ""
+  "cmpeq%i2\\t%0, %z1, %z2"
+  [(set_attr "type" "alu")])
+
+
+(define_expand "sne"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ne:SI (match_dup 1)
+	       (match_dup 2)))]
+  ""
+{
+  if (branch_type != CMP_SI)
+    FAIL;
+
+  /* set up operands from compare.  */
+  operands[1] = branch_cmp[0];
+  operands[2] = branch_cmp[1];
+
+  gen_int_relational (NE, operands[0], operands[1], operands[2], NULL_RTX);
+  DONE;
+})
+
+
+(define_insn "*sne"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+	(ne:SI (match_operand:SI 1 "reg_or_0_operand" "%rM")
+	       (match_operand:SI 2 "arith_operand"     "rI")))]
+  ""
+  "cmpne%i2\\t%0, %z1, %z2"
+  [(set_attr "type" "alu")])
+
+
+(define_expand "sgt"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(gt:SI (match_dup 1)
+	       (match_dup 2)))]
+  ""
+{
+  if (branch_type != CMP_SI)
+    FAIL;
+
+  /* set up operands from compare.  */
+  operands[1] = branch_cmp[0];
+  operands[2] = branch_cmp[1];
+
+  gen_int_relational (GT, operands[0], operands[1], operands[2], NULL_RTX);
+  DONE;
+})
+
+
+(define_insn "*sgt"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+	(gt:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
+	       (match_operand:SI 2 "reg_or_0_operand"  "rM")))]
+  ""
+  "cmplt\\t%0, %z2, %z1"
+  [(set_attr "type" "alu")])
+
+
+(define_expand "sge"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ge:SI (match_dup 1)
+	       (match_dup 2)))]
+  ""
+{
+  if (branch_type != CMP_SI)
+    FAIL;
+
+  /* set up operands from compare.  */
+  operands[1] = branch_cmp[0];
+  operands[2] = branch_cmp[1];
+
+  gen_int_relational (GE, operands[0], operands[1], operands[2], NULL_RTX);
+  DONE;
+})
+
+
+(define_insn "*sge"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+	(ge:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
+	       (match_operand:SI 2 "arith_operand"     "rI")))]
+  ""
+  "cmpge%i2\\t%0, %z1, %z2"
+  [(set_attr "type" "alu")])
+
+(define_expand "sle"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(le:SI (match_dup 1)
+	       (match_dup 2)))]
+  ""
+{
+  if (branch_type != CMP_SI)
+    FAIL;
+
+  /* set up operands from compare.  */
+  operands[1] = branch_cmp[0];
+  operands[2] = branch_cmp[1];
+
+  gen_int_relational (LE, operands[0], operands[1], operands[2], NULL_RTX);
+  DONE;
+})
+
+
+(define_insn "*sle"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+	(le:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
+	       (match_operand:SI 2 "reg_or_0_operand"  "rM")))]
+  ""
+  "cmpge\\t%0, %z2, %z1"
+  [(set_attr "type" "alu")])
+
+
+(define_expand "slt"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(lt:SI (match_dup 1)
+	       (match_dup 2)))]
+  ""
+{
+  if (branch_type != CMP_SI)
+    FAIL;
+
+  /* set up operands from compare.  */
+  operands[1] = branch_cmp[0];
+  operands[2] = branch_cmp[1];
+
+  gen_int_relational (LT, operands[0], operands[1], operands[2], NULL_RTX);
+  DONE;
+})
+
+
+(define_insn "*slt"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+	(lt:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
+	       (match_operand:SI 2 "arith_operand"     "rI")))]
+  ""
+  "cmplt%i2\\t%0, %z1, %z2"
+  [(set_attr "type" "alu")])
+
+
+(define_expand "sgtu"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(gtu:SI (match_dup 1)
+	        (match_dup 2)))]
+  ""
+{
+  if (branch_type != CMP_SI)
+    FAIL;
+
+  /* set up operands from compare.  */
+  operands[1] = branch_cmp[0];
+  operands[2] = branch_cmp[1];
+
+  gen_int_relational (GTU, operands[0], operands[1], operands[2], NULL_RTX);
+  DONE;
+})
+
+
+(define_insn "*sgtu"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+	(gtu:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
+	        (match_operand:SI 2 "reg_or_0_operand"  "rM")))]
+  ""
+  "cmpltu\\t%0, %z2, %z1"
+  [(set_attr "type" "alu")])
+
+
+(define_expand "sgeu"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(geu:SI (match_dup 1)
+	        (match_dup 2)))]
+  ""
+{
+  if (branch_type != CMP_SI)
+    FAIL;
+
+  /* set up operands from compare.  */
+  operands[1] = branch_cmp[0];
+  operands[2] = branch_cmp[1];
+
+  gen_int_relational (GEU, operands[0], operands[1], operands[2], NULL_RTX);
+  DONE;
+})
+
+
+(define_insn "*sgeu"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+	(geu:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
+	        (match_operand:SI 2 "uns_arith_operand"     "rJ")))]
+  ""
+  "cmpgeu%i2\\t%0, %z1, %z2"
+  [(set_attr "type" "alu")])
+
+(define_expand "sleu"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(leu:SI (match_dup 1)
+	        (match_dup 2)))]
+  ""
+{
+  if (branch_type != CMP_SI)
+    FAIL;
+
+  /* set up operands from compare.  */
+  operands[1] = branch_cmp[0];
+  operands[2] = branch_cmp[1];
+
+  gen_int_relational (LEU, operands[0], operands[1], operands[2], NULL_RTX);
+  DONE;
+})
+
+
+(define_insn "*sleu"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+	(leu:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
+	        (match_operand:SI 2 "reg_or_0_operand"  "rM")))]
+  ""
+  "cmpgeu\\t%0, %z2, %z1"
+  [(set_attr "type" "alu")])
+
+
+(define_expand "sltu"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ltu:SI (match_dup 1)
+	        (match_dup 2)))]
+  ""
+{
+  if (branch_type != CMP_SI)
+    FAIL;
+
+  /* set up operands from compare.  */
+  operands[1] = branch_cmp[0];
+  operands[2] = branch_cmp[1];
+
+  gen_int_relational (LTU, operands[0], operands[1], operands[2], NULL_RTX);
+  DONE;
+})
+
+
+(define_insn "*sltu"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+	(ltu:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
+	        (match_operand:SI 2 "uns_arith_operand"     "rJ")))]
+  ""
+  "cmpltu%i2\\t%0, %z1, %z2"
+  [(set_attr "type" "alu")])
+
+
+
+
+;*****************************************************************************
+;*
+;* branches
+;*
+;*****************************************************************************
+
+(define_insn "*cbranch"
+  [(set (pc)
+	(if_then_else
+         (match_operator:SI 0 "comparison_operator"
+			    [(match_operand:SI 2 "reg_or_0_operand" "rM")
+			     (match_operand:SI 3 "reg_or_0_operand" "rM")])
+        (label_ref (match_operand 1 "" ""))
+        (pc)))]
+  ""
+  "b%0\\t%z2, %z3, %l1"
+  [(set_attr "type" "control")])
+
+
+(define_expand "beq"
+  [(set (pc)
+	(if_then_else (eq:CC (cc0)
+			     (const_int 0))
+		      (label_ref (match_operand 0 "" ""))
+		      (pc)))]
+  ""
+{
+  gen_int_relational (EQ, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
+  DONE;
+})
+
+
+(define_expand "bne"
+  [(set (pc)
+	(if_then_else (ne:CC (cc0)
+			     (const_int 0))
+		      (label_ref (match_operand 0 "" ""))
+		      (pc)))]
+  ""
+{
+  gen_int_relational (NE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
+  DONE;
+})
+
+
+(define_expand "bgt"
+  [(set (pc)
+	(if_then_else (gt:CC (cc0)
+			     (const_int 0))
+		      (label_ref (match_operand 0 "" ""))
+		      (pc)))]
+  ""
+{
+  gen_int_relational (GT, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
+  DONE;
+})
+
+(define_expand "bge"
+  [(set (pc)
+	(if_then_else (ge:CC (cc0)
+			     (const_int 0))
+		      (label_ref (match_operand 0 "" ""))
+		      (pc)))]
+  ""
+{
+  gen_int_relational (GE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
+  DONE;
+})
+
+(define_expand "ble"
+  [(set (pc)
+	(if_then_else (le:CC (cc0)
+			     (const_int 0))
+		      (label_ref (match_operand 0 "" ""))
+		      (pc)))]
+  ""
+{
+  gen_int_relational (LE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
+  DONE;
+})
+
+(define_expand "blt"
+  [(set (pc)
+	(if_then_else (lt:CC (cc0)
+			     (const_int 0))
+		      (label_ref (match_operand 0 "" ""))
+		      (pc)))]
+  ""
+{
+  gen_int_relational (LT, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
+  DONE;
+})
+
+
+(define_expand "bgtu"
+  [(set (pc)
+	(if_then_else (gtu:CC (cc0)
+		 	      (const_int 0))
+		      (label_ref (match_operand 0 "" ""))
+		      (pc)))]
+  ""
+{
+  gen_int_relational (GTU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
+  DONE;
+})
+
+(define_expand "bgeu"
+  [(set (pc)
+	(if_then_else (geu:CC (cc0)
+			      (const_int 0))
+		      (label_ref (match_operand 0 "" ""))
+		      (pc)))]
+  ""
+{
+  gen_int_relational (GEU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
+  DONE;
+})
+
+(define_expand "bleu"
+  [(set (pc)
+	(if_then_else (leu:CC (cc0)
+			      (const_int 0))
+		      (label_ref (match_operand 0 "" ""))
+		      (pc)))]
+  ""
+{
+  gen_int_relational (LEU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
+  DONE;
+})
+
+(define_expand "bltu"
+  [(set (pc)
+	(if_then_else (ltu:CC (cc0)
+			      (const_int 0))
+		      (label_ref (match_operand 0 "" ""))
+		      (pc)))]
+  ""
+{
+  gen_int_relational (LTU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
+  DONE;
+})
+
+
+;*****************************************************************************
+;*
+;* String and Block Operations
+;*
+;*****************************************************************************
+
+; ??? This is all really a hack to get Dhrystone to work as fast as possible
+;     things to be fixed:
+;        * let the compiler core handle all of this, for that to work the extra
+;          aliasing needs to be addressed.
+;        * we use three temporary registers for loading and storing to ensure no
+;          ld use stalls, this is excessive, because after the first ld/st only
+;          two are needed. Only two would be needed all the way through if 
+;          we could schedule with other code. Consider:
+;           1  ld $1, 0($src)
+;           2  ld $2, 4($src)
+;           3  ld $3, 8($src)
+;           4  st $1, 0($dest)
+;           5  ld $1, 12($src)
+;           6  st $2, 4($src)
+;           7  etc.
+;          The first store has to wait until 4. If it does not there will be one
+;          cycle of stalling. However, if any other instruction could be placed
+;          between 1 and 4, $3 would not be needed.
+;        * In small we probably don't want to ever do this ourself because there
+;          is no ld use stall.
+
+(define_expand "movstrsi"
+  [(parallel [(set (match_operand:BLK 0 "general_operand"  "")
+		   (match_operand:BLK 1 "general_operand"  ""))
+	      (use (match_operand:SI 2 "const_int_operand" ""))
+	      (use (match_operand:SI 3 "const_int_operand" ""))
+	      (clobber (match_scratch:SI 4                "=&r"))
+	      (clobber (match_scratch:SI 5                "=&r"))
+	      (clobber (match_scratch:SI 6                "=&r"))])]
+  "TARGET_INLINE_MEMCPY"
+{
+  rtx ld_addr_reg, st_addr_reg;
+
+  /* If the predicate for op2 fails in expr.c:emit_block_move_via_movstr 
+     it trys to copy to a register, but does not re-try the predicate.
+     ??? Intead of fixing expr.c, I fix it here. */
+  if (!const_int_operand (operands[2], SImode))
+    FAIL;
+
+  /* ??? there are some magic numbers which need to be sorted out here.
+         the basis for them is not increasing code size hugely or going
+         out of range of offset addressing */
+  if (INTVAL (operands[3]) < 4)
+    FAIL;
+  if (!optimize
+      || (optimize_size && INTVAL (operands[2]) > 12)
+      || (optimize < 3 && INTVAL (operands[2]) > 100)
+      || INTVAL (operands[2]) > 200)
+    FAIL;
+
+  st_addr_reg
+    = replace_equiv_address (operands[0],
+			     copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
+  ld_addr_reg
+    = replace_equiv_address (operands[1],
+			     copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
+  emit_insn (gen_movstrsi_internal (st_addr_reg, ld_addr_reg,
+				    operands[2], operands[3]));
+
+  DONE;
+})
+
+
+(define_insn "movstrsi_internal"
+  [(set (match_operand:BLK 0 "memory_operand"   "=o")
+	(match_operand:BLK 1 "memory_operand"    "o"))
+   (use (match_operand:SI 2 "const_int_operand"  "i"))
+   (use (match_operand:SI 3 "const_int_operand"  "i"))
+   (clobber (match_scratch:SI 4                "=&r"))
+   (clobber (match_scratch:SI 5                "=&r"))
+   (clobber (match_scratch:SI 6                "=&r"))]
+  "TARGET_INLINE_MEMCPY"
+{
+  int ld_offset = INTVAL (operands[2]);
+  int ld_len = INTVAL (operands[2]);
+  int ld_reg = 0;
+  rtx ld_addr_reg = XEXP (operands[1], 0);
+  int st_offset = INTVAL (operands[2]);
+  int st_len = INTVAL (operands[2]);
+  int st_reg = 0;
+  rtx st_addr_reg = XEXP (operands[0], 0);
+  int delay_count = 0;
+  
+  /* ops[0] is the address used by the insn
+     ops[1] is the register being loaded or stored */
+  rtx ops[2];
+  
+  if (INTVAL (operands[3]) < 4)
+    abort ();
+  
+  while (ld_offset >= 4)
+    {
+      /* if the load use delay has been met, I can start
+         storing */
+      if (delay_count >= 3)
+        {
+	  ops[0] = gen_rtx (MEM, SImode, 
+			    plus_constant (st_addr_reg, st_len - st_offset));
+	  ops[1] = operands[st_reg + 4];			 
+	  output_asm_insn ("stw\t%1, %0", ops);
+	  
+	  st_reg = (st_reg + 1) % 3;
+	  st_offset -= 4;
+        }
+    
+      ops[0] = gen_rtx (MEM, SImode, 
+			plus_constant (ld_addr_reg, ld_len - ld_offset));
+      ops[1] = operands[ld_reg + 4];			 
+      output_asm_insn ("ldw\t%1, %0", ops);
+      
+      ld_reg = (ld_reg + 1) % 3;
+      ld_offset -= 4;
+      delay_count++;
+    }
+  
+  if (ld_offset >= 2)
+    {
+      /* if the load use delay has been met, I can start
+         storing */
+      if (delay_count >= 3)
+        {
+	  ops[0] = gen_rtx (MEM, SImode, 
+			    plus_constant (st_addr_reg, st_len - st_offset));
+	  ops[1] = operands[st_reg + 4];			 
+	  output_asm_insn ("stw\t%1, %0", ops);
+	  
+	  st_reg = (st_reg + 1) % 3;
+	  st_offset -= 4;
+        }
+    
+      ops[0] = gen_rtx (MEM, HImode, 
+			plus_constant (ld_addr_reg, ld_len - ld_offset));
+      ops[1] = operands[ld_reg + 4];			 
+      output_asm_insn ("ldh\t%1, %0", ops);
+      
+      ld_reg = (ld_reg + 1) % 3;
+      ld_offset -= 2;
+      delay_count++;
+    }
+  
+  if (ld_offset >= 1)
+    {
+      /* if the load use delay has been met, I can start
+         storing */
+      if (delay_count >= 3)
+        {
+	  ops[0] = gen_rtx (MEM, SImode, 
+			    plus_constant (st_addr_reg, st_len - st_offset));
+	  ops[1] = operands[st_reg + 4];			 
+	  output_asm_insn ("stw\t%1, %0", ops);
+	  
+	  st_reg = (st_reg + 1) % 3;
+	  st_offset -= 4;
+        }
+    
+      ops[0] = gen_rtx (MEM, QImode, 
+			plus_constant (ld_addr_reg, ld_len - ld_offset));
+      ops[1] = operands[ld_reg + 4];			 
+      output_asm_insn ("ldb\t%1, %0", ops);
+      
+      ld_reg = (ld_reg + 1) % 3;
+      ld_offset -= 1;
+      delay_count++;
+    }
+
+    while (st_offset >= 4)
+      {
+	ops[0] = gen_rtx (MEM, SImode, 
+			  plus_constant (st_addr_reg, st_len - st_offset));
+	ops[1] = operands[st_reg + 4];			 
+	output_asm_insn ("stw\t%1, %0", ops);
+
+	st_reg = (st_reg + 1) % 3;
+	st_offset -= 4;
+      }
+  
+    while (st_offset >= 2)
+      {
+	ops[0] = gen_rtx (MEM, HImode, 
+			  plus_constant (st_addr_reg, st_len - st_offset));
+	ops[1] = operands[st_reg + 4];			 
+	output_asm_insn ("sth\t%1, %0", ops);
+
+	st_reg = (st_reg + 1) % 3;
+	st_offset -= 2;
+      }
+  
+    while (st_offset >= 1)
+      {
+	ops[0] = gen_rtx (MEM, QImode, 
+			  plus_constant (st_addr_reg, st_len - st_offset));
+	ops[1] = operands[st_reg + 4];			 
+	output_asm_insn ("stb\t%1, %0", ops);
+
+	st_reg = (st_reg + 1) % 3;
+	st_offset -= 1;
+      }
+  
+  return "";
+}
+; ??? lengths are not being used yet, but I will probably forget
+; to update this once I am using lengths, so set it to something
+; definetely big enough to cover it. 400 allows for 200 bytes
+; of motion.
+  [(set_attr "length" "400")])
+
+
+
+;*****************************************************************************
+;*
+;* Custom instructions
+;*
+;*****************************************************************************
+
+(define_constants [
+  (CUSTOM_N 100)
+  (CUSTOM_NI 101)
+  (CUSTOM_NF 102)
+  (CUSTOM_NP 103)
+  (CUSTOM_NII 104)
+  (CUSTOM_NIF 105)
+  (CUSTOM_NIP 106)
+  (CUSTOM_NFI 107)
+  (CUSTOM_NFF 108)
+  (CUSTOM_NFP 109)
+  (CUSTOM_NPI 110)
+  (CUSTOM_NPF 111)
+  (CUSTOM_NPP 112)
+  (CUSTOM_IN 113)
+  (CUSTOM_INI 114)
+  (CUSTOM_INF 115)
+  (CUSTOM_INP 116)
+  (CUSTOM_INII 117)
+  (CUSTOM_INIF 118)
+  (CUSTOM_INIP 119)
+  (CUSTOM_INFI 120)
+  (CUSTOM_INFF 121)
+  (CUSTOM_INFP 122)
+  (CUSTOM_INPI 123)
+  (CUSTOM_INPF 124)
+  (CUSTOM_INPP 125)
+  (CUSTOM_FN 126)
+  (CUSTOM_FNI 127)
+  (CUSTOM_FNF 128)
+  (CUSTOM_FNP 129)
+  (CUSTOM_FNII 130)
+  (CUSTOM_FNIF 131)
+  (CUSTOM_FNIP 132)
+  (CUSTOM_FNFI 133)
+  (CUSTOM_FNFF 134)
+  (CUSTOM_FNFP 135)
+  (CUSTOM_FNPI 136)
+  (CUSTOM_FNPF 137)
+  (CUSTOM_FNPP 138)
+  (CUSTOM_PN 139)
+  (CUSTOM_PNI 140)
+  (CUSTOM_PNF 141)
+  (CUSTOM_PNP 142)
+  (CUSTOM_PNII 143)
+  (CUSTOM_PNIF 144)
+  (CUSTOM_PNIP 145)
+  (CUSTOM_PNFI 146)
+  (CUSTOM_PNFF 147)
+  (CUSTOM_PNFP 148)
+  (CUSTOM_PNPI 149)
+  (CUSTOM_PNPF 150)
+  (CUSTOM_PNPP 151)
+])
+
+
+(define_insn "custom_n"
+  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")] CUSTOM_N)]
+  ""
+  "custom\\t%0, zero, zero, zero"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_ni"
+  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
+                     (match_operand:SI 1 "register_operand"   "r")] CUSTOM_NI)]
+  ""
+  "custom\\t%0, zero, %1, zero"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_nf"
+  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
+                     (match_operand:SF 1 "register_operand"   "r")] CUSTOM_NF)]
+  ""
+  "custom\\t%0, zero, %1, zero"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_np"
+  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
+                     (match_operand:SI 1 "register_operand"   "r")] CUSTOM_NP)]
+  ""
+  "custom\\t%0, zero, %1, zero"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_nii"
+  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
+                     (match_operand:SI 1 "register_operand"   "r")
+                     (match_operand:SI 2 "register_operand"   "r")] CUSTOM_NII)]
+  ""
+  "custom\\t%0, zero, %1, %2"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_nif"
+  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
+                     (match_operand:SI 1 "register_operand"   "r")
+                     (match_operand:SF 2 "register_operand"   "r")] CUSTOM_NIF)]
+  ""
+  "custom\\t%0, zero, %1, %2"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_nip"
+  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
+                     (match_operand:SI 1 "register_operand"   "r")
+                     (match_operand:SI 2 "register_operand"   "r")] CUSTOM_NIP)]
+  ""
+  "custom\\t%0, zero, %1, %2"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_nfi"
+  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
+                     (match_operand:SF 1 "register_operand"   "r")
+                     (match_operand:SI 2 "register_operand"   "r")] CUSTOM_NFI)]
+  ""
+  "custom\\t%0, zero, %1, %2"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_nff"
+  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
+                     (match_operand:SF 1 "register_operand"   "r")
+                     (match_operand:SF 2 "register_operand"   "r")] CUSTOM_NFF)]
+  ""
+  "custom\\t%0, zero, %1, %2"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_nfp"
+  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
+                     (match_operand:SF 1 "register_operand"   "r")
+                     (match_operand:SI 2 "register_operand"   "r")] CUSTOM_NFP)]
+  ""
+  "custom\\t%0, zero, %1, %2"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_npi"
+  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
+                     (match_operand:SI 1 "register_operand"   "r")
+                     (match_operand:SI 2 "register_operand"   "r")] CUSTOM_NPI)]
+  ""
+  "custom\\t%0, zero, %1, %2"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_npf"
+  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
+                     (match_operand:SI 1 "register_operand"   "r")
+                     (match_operand:SF 2 "register_operand"   "r")] CUSTOM_NPF)]
+  ""
+  "custom\\t%0, zero, %1, %2"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_npp"
+  [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
+                     (match_operand:SI 1 "register_operand"   "r")
+                     (match_operand:SI 2 "register_operand"   "r")] CUSTOM_NPP)]
+  ""
+  "custom\\t%0, zero, %1, %2"
+  [(set_attr "type" "custom")])
+
+
+
+(define_insn "custom_in"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_IN))]
+  ""
+  "custom\\t%1, %0, zero, zero"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_ini"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")] CUSTOM_INI))]
+  ""
+  "custom\\t%1, %0, %2, zero"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_inf"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SF 2 "register_operand"   "r")] CUSTOM_INF))]
+  ""
+  "custom\\t%1, %0, %2, zero"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_inp"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")] CUSTOM_INP))]
+  ""
+  "custom\\t%1, %0, %2, zero"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_inii"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_INII))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_inif"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_INIF))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_inip"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_INIP))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_infi"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SF 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_INFI))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_inff"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SF 2 "register_operand"   "r")
+                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_INFF))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_infp"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SF 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_INFP))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_inpi"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_INPI))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_inpf"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_INPF))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_inpp"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_INPP))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+
+
+
+
+(define_insn "custom_fn"
+  [(set (match_operand:SF 0 "register_operand"   "=r")
+        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_FN))]
+  ""
+  "custom\\t%1, %0, zero, zero"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_fni"
+  [(set (match_operand:SF 0 "register_operand"   "=r")
+        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")] CUSTOM_FNI))]
+  ""
+  "custom\\t%1, %0, %2, zero"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_fnf"
+  [(set (match_operand:SF 0 "register_operand"   "=r")
+        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SF 2 "register_operand"   "r")] CUSTOM_FNF))]
+  ""
+  "custom\\t%1, %0, %2, zero"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_fnp"
+  [(set (match_operand:SF 0 "register_operand"   "=r")
+        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")] CUSTOM_FNP))]
+  ""
+  "custom\\t%1, %0, %2, zero"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_fnii"
+  [(set (match_operand:SF 0 "register_operand"   "=r")
+        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_FNII))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_fnif"
+  [(set (match_operand:SF 0 "register_operand"   "=r")
+        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_FNIF))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_fnip"
+  [(set (match_operand:SF 0 "register_operand"   "=r")
+        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_FNIP))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_fnfi"
+  [(set (match_operand:SF 0 "register_operand"   "=r")
+        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SF 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_FNFI))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_fnff"
+  [(set (match_operand:SF 0 "register_operand"   "=r")
+        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SF 2 "register_operand"   "r")
+                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_FNFF))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_fnfp"
+  [(set (match_operand:SF 0 "register_operand"   "=r")
+        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SF 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_FNFP))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_fnpi"
+  [(set (match_operand:SF 0 "register_operand"   "=r")
+        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_FNPI))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_fnpf"
+  [(set (match_operand:SF 0 "register_operand"   "=r")
+        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_FNPF))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_fnpp"
+  [(set (match_operand:SF 0 "register_operand"   "=r")
+        (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_FNPP))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+
+
+(define_insn "custom_pn"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_PN))]
+  ""
+  "custom\\t%1, %0, zero, zero"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_pni"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")] CUSTOM_PNI))]
+  ""
+  "custom\\t%1, %0, %2, zero"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_pnf"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SF 2 "register_operand"   "r")] CUSTOM_PNF))]
+  ""
+  "custom\\t%1, %0, %2, zero"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_pnp"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")] CUSTOM_PNP))]
+  ""
+  "custom\\t%1, %0, %2, zero"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_pnii"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_PNII))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_pnif"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_PNIF))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_pnip"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_PNIP))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_pnfi"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SF 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_PNFI))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_pnff"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SF 2 "register_operand"   "r")
+                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_PNFF))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_pnfp"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SF 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_PNFP))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_pnpi"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_PNPI))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_pnpf"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SF 3 "register_operand"   "r")] CUSTOM_PNPF))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+(define_insn "custom_pnpp"
+  [(set (match_operand:SI 0 "register_operand"   "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
+                          (match_operand:SI 2 "register_operand"   "r")
+                          (match_operand:SI 3 "register_operand"   "r")] CUSTOM_PNPP))]
+  ""
+  "custom\\t%1, %0, %2, %3"
+  [(set_attr "type" "custom")])
+
+
+
+
+
+
+;*****************************************************************************
+;*
+;* Misc
+;*
+;*****************************************************************************
+
+(define_insn "nop"
+  [(const_int 0)]
+  ""
+  "nop\\t"
+  [(set_attr "type" "alu")])
+
+(define_insn "sync"
+  [(unspec_volatile [(const_int 0)] UNSPEC_SYNC)]
+  ""
+  "sync\\t"
+  [(set_attr "type" "control")])
+
+
+(define_insn "rdctl"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")] UNSPEC_RDCTL))]
+  ""
+  "rdctl\\t%0, ctl%1"
+  [(set_attr "type" "control")])
+
+(define_insn "wrctl"
+  [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand"  "O")
+                        (match_operand:SI 1 "register_operand" "r")] UNSPEC_WRCTL)]
+  ""
+  "wrctl\\tctl%0, %1"
+  [(set_attr "type" "control")])
+
+
+
+;*****************************************************************************
+;*
+;* Peepholes
+;*
+;*****************************************************************************
+
+
--- gcc-3.4.3/gcc/config/nios2/t-nios2
+++ gcc-3.4.3-nios2/gcc/config/nios2/t-nios2
@@ -0,0 +1,123 @@
+##
+## Compiler flags to use when compiling libgcc2.c.
+##
+## LIB2FUNCS_EXTRA
+## A list of source file names to be compiled or assembled and inserted into libgcc.a.
+
+LIB2FUNCS_EXTRA=$(srcdir)/config/nios2/lib2-divmod.c \
+  $(srcdir)/config/nios2/lib2-divmod-hi.c \
+  $(srcdir)/config/nios2/lib2-divtable.c \
+  $(srcdir)/config/nios2/lib2-mul.c
+
+##
+## Floating Point Emulation
+## To have GCC include software floating point libraries in libgcc.a define FPBIT
+## and DPBIT along with a few rules as follows:
+##
+## # We want fine grained libraries, so use the new code
+## # to build the floating point emulation libraries.
+FPBIT=$(srcdir)/config/nios2/nios2-fp-bit.c
+DPBIT=$(srcdir)/config/nios2/nios2-dp-bit.c
+
+TARGET_LIBGCC2_CFLAGS = -O2
+
+# FLOAT_ONLY - no doubles
+# SMALL_MACHINE - QI/HI is faster than SI
+#     Actually SMALL_MACHINE uses chars and shorts instead of ints
+#     since ints (16-bit ones as they are today) are at least as fast
+#     as chars and shorts, don't define SMALL_MACHINE
+# CMPtype - type returned by FP compare, i.e. INT (hard coded in fp-bit - see code )
+
+$(FPBIT): $(srcdir)/config/fp-bit.c Makefile
+	echo '#define FLOAT'          >  ${FPBIT}
+	cat $(srcdir)/config/fp-bit.c >> ${FPBIT}
+
+$(DPBIT): $(srcdir)/config/fp-bit.c Makefile
+	echo ''          >  ${DPBIT}
+	cat $(srcdir)/config/fp-bit.c >> ${DPBIT}
+
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o 
+
+# Assemble startup files. 
+$(T)crti.o: $(srcdir)/config/nios2/crti.asm $(GCC_PASSES) 
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/nios2/crti.asm 
+
+$(T)crtn.o: $(srcdir)/config/nios2/crtn.asm $(GCC_PASSES) 
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/nios2/crtn.asm 
+
+
+## You may need to provide additional #defines at the beginning of
+## fp-bit.c and dp-bit.c to control target endianness and other options
+##
+## CRTSTUFF_T_CFLAGS
+## Special flags used when compiling crtstuff.c.  See Initialization.
+##
+## CRTSTUFF_T_CFLAGS_S
+## Special flags used when compiling crtstuff.c for shared linking.  Used
+## if you use crtbeginS.o and crtendS.o in EXTRA-PARTS. See Initialization.
+##
+## MULTILIB_OPTIONS
+## For some targets, invoking GCC in different ways produces objects that
+## can not be linked together.  For example, for some targets GCC produces
+## both big and little endian code.  For these targets, you must arrange
+## for multiple versions of libgcc.a to be compiled, one for each set of
+## incompatible options.  When GCC invokes the linker, it arranges to link
+## in the right version of libgcc.a, based on the command line options
+## used.
+## The MULTILIB_OPTIONS macro lists the set of options for which special
+## versions of libgcc.a must be built.  Write options that are mutually
+## incompatible side by side, separated by a slash.  Write options that may
+## be used together separated by a space.  The build procedure will build
+## all combinations of compatible options.
+##
+## For example, if you set MULTILIB_OPTIONS to m68000/m68020 msoft-float,
+## Makefile will build special versions of libgcc.a using the following
+## sets of options: -m68000, -m68020, -msoft-float, -m68000 -msoft-float,
+## and -m68020 -msoft-float.
+
+MULTILIB_OPTIONS = mno-hw-mul mhw-mulx
+
+## MULTILIB_DIRNAMES
+## If MULTILIB_OPTIONS is used, this variable specifies the directory names
+## that should be used to hold the various libraries.  Write one element in
+## MULTILIB_DIRNAMES for each element in MULTILIB_OPTIONS. If
+## MULTILIB_DIRNAMES is not used, the default value will be
+## MULTILIB_OPTIONS, with all slashes treated as spaces.
+## For example, if MULTILIB_OPTIONS is set to m68000/m68020 msoft-float,
+## then the default value of MULTILIB_DIRNAMES is m68000 m68020
+## msoft-float.  You may specify a different value if you desire a
+## different set of directory names.
+
+# MULTILIB_DIRNAMES =
+
+## MULTILIB_MATCHES
+## Sometimes the same option may be written in two different ways.  If an
+## option is listed in MULTILIB_OPTIONS, GCC needs to know about any
+## synonyms.  In that case, set MULTILIB_MATCHES to a list of items of the
+## form option=option to describe all relevant synonyms.  For example,
+## m68000=mc68000 m68020=mc68020.
+##
+## MULTILIB_EXCEPTIONS
+## Sometimes when there are multiple sets of MULTILIB_OPTIONS being
+## specified, there are combinations that should not be built.  In that
+## case, set MULTILIB_EXCEPTIONS to be all of the switch exceptions in
+## shell case syntax that should not be built.
+## For example, in the PowerPC embedded ABI support, it is not desirable to
+## build libraries compiled with the -mcall-aix option and either of the
+## -fleading-underscore or -mlittle options at the same time.  Therefore
+## MULTILIB_EXCEPTIONS is set to
+##
+## *mcall-aix/*fleading-underscore* *mlittle/*mcall-aix*
+##
+
+MULTILIB_EXCEPTIONS = *mno-hw-mul/*mhw-mulx*
+
+##
+## MULTILIB_EXTRA_OPTS Sometimes it is desirable that when building
+## multiple versions of libgcc.a certain options should always be passed on
+## to the compiler.  In that case, set MULTILIB_EXTRA_OPTS to be the list
+## of options to be used for all builds.
+##
+
--- gcc-3.4.3/gcc/config.gcc
+++ gcc-3.4.3-nios2/gcc/config.gcc
@@ -1321,6 +1321,10 @@ m32rle-*-linux*)
 		thread_file='posix'
 	fi
 	;;
+# JBG
+nios2-*-* | nios2-*-*)
+	tm_file="elfos.h ${tm_file}"
+	;;
 # m68hc11 and m68hc12 share the same machine description.
 m68hc11-*-*|m6811-*-*)
 	tm_file="dbxelf.h elfos.h m68hc11/m68hc11.h"
--- gcc-3.4.3/gcc/cse.c
+++ gcc-3.4.3-nios2/gcc/cse.c
@@ -3134,6 +3134,10 @@ find_comparison_args (enum rtx_code code
 #ifdef FLOAT_STORE_FLAG_VALUE
 	  REAL_VALUE_TYPE fsfv;
 #endif
+#ifdef __nios2__
+	  if (p->is_const)
+	    break;
+#endif
 
 	  /* If the entry isn't valid, skip it.  */
 	  if (! exp_equiv_p (p->exp, p->exp, 1, 0))
--- gcc-3.4.3/gcc/doc/extend.texi
+++ gcc-3.4.3-nios2/gcc/doc/extend.texi
@@ -5636,12 +5636,118 @@ to those machines.  Generally these gene
 instructions, but allow the compiler to schedule those calls.
 
 @menu
+* Altera Nios II Built-in Functions::
 * Alpha Built-in Functions::
 * ARM Built-in Functions::
 * X86 Built-in Functions::
 * PowerPC AltiVec Built-in Functions::
 @end menu
 
+@node Altera Nios II Built-in Functions
+@subsection Altera Nios II Built-in Functions
+
+These built-in functions are available for the Altera Nios II
+family of processors.
+
+The following built-in functions are always available.  They
+all generate the machine instruction that is part of the name.
+
+@example
+int __builtin_ldbio (volatile const void *)
+int __builtin_ldbuio (volatile const void *)
+int __builtin_ldhio (volatile const void *)
+int __builtin_ldhuio (volatile const void *)
+int __builtin_ldwio (volatile const void *)
+void __builtin_stbio (volatile void *, int)
+void __builtin_sthio (volatile void *, int)
+void __builtin_stwio (volatile void *, int)
+void __builtin_sync (void)
+int __builtin_rdctl (int) 
+void __builtin_wrctl (int, int)
+@end example
+
+The following built-in functions are always available.  They
+all generate a Nios II Custom Instruction. The name of the 
+function represents the types that the function takes and 
+returns. The letter before the @code{n} is the return type
+or void if absent. The @code{n} represnts the first parameter
+to all the custom instructions, the custom instruction number.
+The two letters after the @code{n} represent the up to two 
+parameters to the function.
+
+The letters reprsent the following data types:
+@table @code
+@item <no letter>
+@code{void} for return type and no parameter for parameter types.
+
+@item i
+@code{int} for return type and parameter type
+
+@item f
+@code{float} for return type and parameter type
+
+@item p
+@code{void *} for return type and parameter type
+
+@end table
+
+And the function names are:
+@example
+void __builtin_custom_n (void)
+void __builtin_custom_ni (int)
+void __builtin_custom_nf (float)
+void __builtin_custom_np (void *)
+void __builtin_custom_nii (int, int)
+void __builtin_custom_nif (int, float)
+void __builtin_custom_nip (int, void *)
+void __builtin_custom_nfi (float, int)
+void __builtin_custom_nff (float, float)
+void __builtin_custom_nfp (float, void *)
+void __builtin_custom_npi (void *, int)
+void __builtin_custom_npf (void *, float)
+void __builtin_custom_npp (void *, void *)
+int __builtin_custom_in (void)
+int __builtin_custom_ini (int)
+int __builtin_custom_inf (float)
+int __builtin_custom_inp (void *)
+int __builtin_custom_inii (int, int)
+int __builtin_custom_inif (int, float)
+int __builtin_custom_inip (int, void *)
+int __builtin_custom_infi (float, int)
+int __builtin_custom_inff (float, float)
+int __builtin_custom_infp (float, void *)
+int __builtin_custom_inpi (void *, int)
+int __builtin_custom_inpf (void *, float)
+int __builtin_custom_inpp (void *, void *)
+float __builtin_custom_fn (void)
+float __builtin_custom_fni (int)
+float __builtin_custom_fnf (float)
+float __builtin_custom_fnp (void *)
+float __builtin_custom_fnii (int, int)
+float __builtin_custom_fnif (int, float)
+float __builtin_custom_fnip (int, void *)
+float __builtin_custom_fnfi (float, int)
+float __builtin_custom_fnff (float, float)
+float __builtin_custom_fnfp (float, void *)
+float __builtin_custom_fnpi (void *, int)
+float __builtin_custom_fnpf (void *, float)
+float __builtin_custom_fnpp (void *, void *)
+void * __builtin_custom_pn (void)
+void * __builtin_custom_pni (int)
+void * __builtin_custom_pnf (float)
+void * __builtin_custom_pnp (void *)
+void * __builtin_custom_pnii (int, int)
+void * __builtin_custom_pnif (int, float)
+void * __builtin_custom_pnip (int, void *)
+void * __builtin_custom_pnfi (float, int)
+void * __builtin_custom_pnff (float, float)
+void * __builtin_custom_pnfp (float, void *)
+void * __builtin_custom_pnpi (void *, int)
+void * __builtin_custom_pnpf (void *, float)
+void * __builtin_custom_pnpp (void *, void *)
+@end example
+
+
 @node Alpha Built-in Functions
 @subsection Alpha Built-in Functions
 
--- gcc-3.4.3/gcc/doc/invoke.texi
+++ gcc-3.4.3-nios2/gcc/doc/invoke.texi
@@ -337,6 +337,14 @@ in the following sections.
 @item Machine Dependent Options
 @xref{Submodel Options,,Hardware Models and Configurations}.
 
+@emph{Altera Nios II Options}
+@gccoptlist{-msmallc -mno-bypass-cache -mbypass-cache @gol
+-mno-cache-volatile -mcache-volatile -mno-inline-memcpy @gol 
+-minline-memcpy -mno-fast-sw-div -mfast-sw-div @gol
+-mhw-mul -mno-hw-mul -mhw-mulx -mno-hw-mulx @gol
+-mno-hw-div -mhw-div @gol
+-msys-crt0= -msys-lib= -msys=nosys }
+
 @emph{M680x0 Options}
 @gccoptlist{-m68000  -m68020  -m68020-40  -m68020-60  -m68030  -m68040 @gol
 -m68060  -mcpu32  -m5200  -m68881  -mbitfield  -mc68000  -mc68020   @gol
@@ -5836,6 +5844,7 @@ machine description.  The default for th
 that macro, which enables you to change the defaults.
 
 @menu
+* Altera Nios II Options::
 * M680x0 Options::
 * M68hc1x Options::
 * VAX Options::
@@ -5871,6 +5880,103 @@ that macro, which enables you to change 
 * FRV Options::
 @end menu
 
+
+@node Altera Nios II Options
+@subsection Altera Nios II Options
+@cindex Altera Nios II options
+
+These are the @samp{-m} options defined for the Altera Nios II 
+processor.
+
+@table @gcctabopt
+
+@item -msmallc
+@opindex msmallc
+
+Link with a limited version of the C library, -lsmallc. For more 
+information see the C Library Documentation.
+
+
+@item -mbypass-cache
+@itemx -mno-bypass-cache
+@opindex mno-bypass-cache
+@opindex mbypass-cache
+
+Force all load and store instructions to always bypass cache by 
+using io variants of the instructions. The default is to not
+bypass the cache.
+
+@item -mno-cache-volatile 
+@itemx -mcache-volatile       
+@opindex mcache-volatile 
+@opindex mno-cache-volatile
+
+Volatile memory access bypass the cache using the io variants of 
+the ld and st instructions. The default is to cache volatile 
+accesses. 
+
+-mno-cache-volatile is deprecated and will be deleted in a 
+future GCC release.
+
+
+@item -mno-inline-memcpy
+@itemx -minline-memcpy
+@opindex mno-inline-memcpy 
+@opindex minline-memcpy
+
+Do not inline memcpy. The default is to inline when -O is on.
+
+
+@item -mno-fast-sw-div
+@itemx -mfast-sw-div
+@opindex mno-fast-sw-div
+@opindex mfast-sw-div
+
+Do no use table based fast divide for small numbers. The default 
+is to use the fast divide at -O3 and above.
+
+
+@item -mno-hw-mul
+@itemx -mhw-mul
+@itemx -mno-hw-mulx
+@itemx -mhw-mulx
+@itemx -mno-hw-div
+@itemx -mhw-div
+@opindex mno-hw-mul
+@opindex mhw-mul
+@opindex mno-hw-mulx
+@opindex mhw-mulx
+@opindex mno-hw-div
+@opindex mhw-div
+
+Enable or disable emitting @code{mul}, @code{mulx} and @code{div} family of 
+instructions by the compiler. The default is to emit @code{mul}
+and not emit @code{div} and @code{mulx}.
+
+The different combinations of @code{mul} and @code{mulx} instructions 
+generate a different multilib options. 
+
+
+@item -msys-crt0=@var{startfile}
+@opindex msys-crt0
+
+@var{startfile} is the file name  of the startfile (crt0) to use 
+when linking. The default is crt0.o that comes with libgloss
+and is only suitable for use with the instruction set
+simulator.
+
+@item -msys-lib=@var{systemlib}
+@itemx -msys-lib=nosys
+@opindex msys-lib
+
+@var{systemlib} is the library name of the library which provides
+the system calls required by the C library, e.g. @code{read}, @code{write}
+etc. The default is to use nosys, this library provides
+stub implementations of the calls and is part of libgloss.
+
+@end table
+
+
 @node M680x0 Options
 @subsection M680x0 Options
 @cindex M680x0 options
--- gcc-3.4.3/gcc/doc/md.texi
+++ gcc-3.4.3-nios2/gcc/doc/md.texi
@@ -1335,6 +1335,49 @@ However, here is a summary of the machin
 available on some particular machines.
 
 @table @emph
+
+@item Altera Nios II family---@file{nios2.h}
+@table @code
+
+@item I
+Integer that is valid as an immediate operand in an
+instruction taking a signed 16-bit number. Range
+@minus{}32768 to 32767.
+
+@item J
+Integer that is valid as an immediate operand in an
+instruction taking an unsigned 16-bit number. Range
+0 to 65535.
+
+@item K
+Integer that is valid as an immediate operand in an
+instruction taking only the upper 16-bits of a
+32-bit number. Range 32-bit numbers with the lower
+16-bits being 0.
+
+@item L
+Integer that is valid as an immediate operand for a 
+shift instruction. Range 0 to 31.
+
+
+@item M
+Integer that is valid as an immediate operand for
+only the value 0. Can be used in conjunction with
+the format modifier @code{z} to use @code{r0}
+instead of @code{0} in the assembly output.
+
+@item N
+Integer that is valid as an immediate operand for
+a custom instruction opcode. Range 0 to 255.
+
+@item S
+Matches immediates which are addresses in the small
+data section and therefore can be added to @code{gp}
+as a 16-bit immediate to re-create their 32-bit value.
+
+@end table
+
+
 @item ARM family---@file{arm.h}
 @table @code
 @item f
