Index: gcc-4.1.2/gcc/config/nios2/crti.asm
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-4.1.2/gcc/config/nios2/crti.asm	2010-06-30 08:50:26.000000000 +0200
@@ -0,0 +1,97 @@
+/* NOT ASSIGNED TO FSF.  COPYRIGHT ALTERA.  */
+/*
+  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)
+	addi	fp, sp, 8
+	nextpc	r22
+1:	movhi	r2, %hiadj(_GLOBAL_OFFSET_TABLE_ - 1b)
+	addi	r2, r2, %lo(_GLOBAL_OFFSET_TABLE_ - 1b)
+	add	r22, r22, r2
+
+
+	.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)
+	addi	fp, sp, 8
+	nextpc	r22
+1:	movhi	r2, %hiadj(_GLOBAL_OFFSET_TABLE_ - 1b)
+	addi	r2, r2, %lo(_GLOBAL_OFFSET_TABLE_ - 1b)
+	add	r22, r22, r2
+
+
Index: gcc-4.1.2/gcc/config/nios2/crtn.asm
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-4.1.2/gcc/config/nios2/crtn.asm	2010-06-30 08:50:26.000000000 +0200
@@ -0,0 +1,71 @@
+/* NOT ASSIGNED TO FSF.  COPYRIGHT ALTERA.  */
+/*
+  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
+
Index: gcc-4.1.2/gcc/config/nios2/lib2-divmod-hi.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-4.1.2/gcc/config/nios2/lib2-divmod-hi.c	2010-06-30 08:50:26.000000000 +0200
@@ -0,0 +1,133 @@
+
+/* 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"
+#undef gid_t
+#undef pid_t
+#undef rlim_t
+#undef ssize_t
+#undef uid_t
+#undef vfork
+
+
+#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
+
+#ifndef MIN_UNITS_PER_WORD
+#define MIN_UNITS_PER_WORD UNITS_PER_WORD
+#endif
+
+#include "libgcc2.h"
+
+extern HItype __modhi3 (HItype, HItype);
+extern HItype __divhi3 (HItype, HItype);
+extern UHItype __umodhi3 (UHItype, UHItype);
+extern UHItype __udivhi3 (UHItype, UHItype);
+
+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;
+}
+
+
+UHItype
+__udivhi3 (UHItype a, UHItype b)
+{
+  return udivmodhi4 (a, b, 0);
+}
+
+
+UHItype
+__umodhi3 (UHItype a, UHItype b)
+{
+  return udivmodhi4 (a, b, 1);
+}
+
Index: gcc-4.1.2/gcc/config/nios2/lib2-divmod.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-4.1.2/gcc/config/nios2/lib2-divmod.c	2010-06-30 08:50:26.000000000 +0200
@@ -0,0 +1,136 @@
+
+/* 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"
+#undef gid_t
+#undef pid_t
+#undef rlim_t
+#undef ssize_t
+#undef uid_t
+#undef vfork
+
+
+#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
+
+#ifndef MIN_UNITS_PER_WORD
+#define MIN_UNITS_PER_WORD UNITS_PER_WORD
+#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);
+}
+
Index: gcc-4.1.2/gcc/config/nios2/lib2-divtable.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-4.1.2/gcc/config/nios2/lib2-divtable.c	2010-06-30 08:50:26.000000000 +0200
@@ -0,0 +1,52 @@
+
+/* 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"
+#undef gid_t
+#undef pid_t
+#undef rlim_t
+#undef ssize_t
+#undef uid_t
+#undef vfork
+
+
+#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,
+};
+
Index: gcc-4.1.2/gcc/config/nios2/lib2-mul.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-4.1.2/gcc/config/nios2/lib2-mul.c	2010-06-30 08:50:26.000000000 +0200
@@ -0,0 +1,113 @@
+/* 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"
+#undef gid_t
+#undef pid_t
+#undef rlim_t
+#undef ssize_t
+#undef uid_t
+#undef vfork
+
+
+#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
+
+#ifndef MIN_UNITS_PER_WORD
+#define MIN_UNITS_PER_WORD UNITS_PER_WORD
+#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
Index: gcc-4.1.2/gcc/config/nios2/linux-atomic.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-4.1.2/gcc/config/nios2/linux-atomic.c	2010-06-30 08:50:26.000000000 +0200
@@ -0,0 +1,302 @@
+/* Linux-specific atomic operations for Nios II Linux.
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 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 into combinations with other programs,
+and to distribute those combinations 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 a combine
+executable.)
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+#include <asm/unistd.h>
+#define EFAULT  14
+#define EBUSY   16
+#define ENOSYS  38
+
+/* We implement byte, short and int versions of each atomic operation
+   using the kernel helper defined below.  There is no support for
+   64-bit operations yet.  */
+
+/* Crash a userspace program with SIGSEV.  */
+#define ABORT_INSTRUCTION asm ("stw zero, 0(zero)")
+
+/* Kernel helper for compare-and-exchange a 32-bit value.  */
+static inline long
+__kernel_cmpxchg (int oldval, int newval, int *mem)
+{
+  register int r2 asm ("r2") = __NR_nios2cmpxchg;
+  register unsigned long lws_mem asm("r4") = (unsigned long) (mem);
+  register int lws_old asm("r5") = oldval;
+  register int lws_new asm("r6") = newval;
+  register int err asm ("r7");
+  asm volatile ("trap"
+		: "=r" (r2), "=r" (err)
+		: "r" (r2), "r" (lws_mem), "r" (lws_old), "r" (lws_new)
+		: "r1", "r3", "r8", "r9", "r10", "r11", "r12", "r13", "r14",
+		  "r15", "r29", "memory");
+
+  /* If the kernel LWS call succeeded (err == 0), r2 contains the old value
+     from memory.  If this value is equal to OLDVAL, the new value was written
+     to memory.  If not, return EBUSY.  */
+  if (__builtin_expect (err, 0))
+    {
+      if(__builtin_expect (r2 == EFAULT || r2 == ENOSYS,0))
+	ABORT_INSTRUCTION;
+    }
+  else
+    {
+      if (__builtin_expect (r2 != oldval, 0))
+	r2 = EBUSY;
+      else
+	r2 = 0;
+    }
+
+  return r2;
+}
+
+#define HIDDEN __attribute__ ((visibility ("hidden")))
+
+/* Big endian masks  */
+#define INVERT_MASK_1 24
+#define INVERT_MASK_2 16
+
+#define MASK_1 0xffu
+#define MASK_2 0xffffu
+
+#define FETCH_AND_OP_WORD(OP, PFX_OP, INF_OP)				\
+  int HIDDEN								\
+  __sync_fetch_and_##OP##_4 (int *ptr, int val)				\
+  {									\
+    int failure, tmp;							\
+									\
+    do {								\
+      tmp = *ptr;							\
+      failure = __kernel_cmpxchg (tmp, PFX_OP tmp INF_OP val, ptr);	\
+    } while (failure != 0);						\
+									\
+    return tmp;								\
+  }
+
+FETCH_AND_OP_WORD (add,   , +)
+FETCH_AND_OP_WORD (sub,   , -)
+FETCH_AND_OP_WORD (or,    , |)
+FETCH_AND_OP_WORD (and,   , &)
+FETCH_AND_OP_WORD (xor,   , ^)
+FETCH_AND_OP_WORD (nand, ~, &)
+
+#define NAME_oldval(OP, WIDTH) __sync_fetch_and_##OP##_##WIDTH
+#define NAME_newval(OP, WIDTH) __sync_##OP##_and_fetch_##WIDTH
+
+/* Implement both __sync_<op>_and_fetch and __sync_fetch_and_<op> for
+   subword-sized quantities.  */
+
+#define SUBWORD_SYNC_OP(OP, PFX_OP, INF_OP, TYPE, WIDTH, RETURN)	\
+  TYPE HIDDEN								\
+  NAME##_##RETURN (OP, WIDTH) (TYPE *ptr, TYPE val)			\
+  {									\
+    int *wordptr = (int *) ((unsigned long) ptr & ~3);			\
+    unsigned int mask, shift, oldval, newval;				\
+    int failure;							\
+									\
+    shift = (((unsigned long) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH;	\
+    mask = MASK_##WIDTH << shift;					\
+									\
+    do {								\
+      oldval = *wordptr;						\
+      newval = ((PFX_OP ((oldval & mask) >> shift)			\
+                 INF_OP (unsigned int) val) << shift) & mask;		\
+      newval |= oldval & ~mask;						\
+      failure = __kernel_cmpxchg (oldval, newval, wordptr);		\
+    } while (failure != 0);						\
+									\
+    return (RETURN & mask) >> shift;					\
+  }
+
+SUBWORD_SYNC_OP (add,   , +, short, 2, oldval)
+SUBWORD_SYNC_OP (sub,   , -, short, 2, oldval)
+SUBWORD_SYNC_OP (or,    , |, short, 2, oldval)
+SUBWORD_SYNC_OP (and,   , &, short, 2, oldval)
+SUBWORD_SYNC_OP (xor,   , ^, short, 2, oldval)
+SUBWORD_SYNC_OP (nand, ~, &, short, 2, oldval)
+
+SUBWORD_SYNC_OP (add,   , +, char, 1, oldval)
+SUBWORD_SYNC_OP (sub,   , -, char, 1, oldval)
+SUBWORD_SYNC_OP (or,    , |, char, 1, oldval)
+SUBWORD_SYNC_OP (and,   , &, char, 1, oldval)
+SUBWORD_SYNC_OP (xor,   , ^, char, 1, oldval)
+SUBWORD_SYNC_OP (nand, ~, &, char, 1, oldval)
+
+#define OP_AND_FETCH_WORD(OP, PFX_OP, INF_OP)				\
+  int HIDDEN								\
+  __sync_##OP##_and_fetch_4 (int *ptr, int val)				\
+  {									\
+    int tmp, failure;							\
+									\
+    do {								\
+      tmp = *ptr;							\
+      failure = __kernel_cmpxchg (tmp, PFX_OP tmp INF_OP val, ptr);	\
+    } while (failure != 0);						\
+									\
+    return PFX_OP tmp INF_OP val;					\
+  }
+
+OP_AND_FETCH_WORD (add,   , +)
+OP_AND_FETCH_WORD (sub,   , -)
+OP_AND_FETCH_WORD (or,    , |)
+OP_AND_FETCH_WORD (and,   , &)
+OP_AND_FETCH_WORD (xor,   , ^)
+OP_AND_FETCH_WORD (nand, ~, &)
+
+SUBWORD_SYNC_OP (add,   , +, short, 2, newval)
+SUBWORD_SYNC_OP (sub,   , -, short, 2, newval)
+SUBWORD_SYNC_OP (or,    , |, short, 2, newval)
+SUBWORD_SYNC_OP (and,   , &, short, 2, newval)
+SUBWORD_SYNC_OP (xor,   , ^, short, 2, newval)
+SUBWORD_SYNC_OP (nand, ~, &, short, 2, newval)
+
+SUBWORD_SYNC_OP (add,   , +, char, 1, newval)
+SUBWORD_SYNC_OP (sub,   , -, char, 1, newval)
+SUBWORD_SYNC_OP (or,    , |, char, 1, newval)
+SUBWORD_SYNC_OP (and,   , &, char, 1, newval)
+SUBWORD_SYNC_OP (xor,   , ^, char, 1, newval)
+SUBWORD_SYNC_OP (nand, ~, &, char, 1, newval)
+
+int HIDDEN
+__sync_val_compare_and_swap_4 (int *ptr, int oldval, int newval)
+{
+  int actual_oldval, fail;
+
+  while (1)
+    {
+      actual_oldval = *ptr;
+
+      if (oldval != actual_oldval)
+	return actual_oldval;
+
+      fail = __kernel_cmpxchg (actual_oldval, newval, ptr);
+
+      if (!fail)
+	return oldval;
+    }
+}
+
+#define SUBWORD_VAL_CAS(TYPE, WIDTH)					\
+  TYPE HIDDEN								\
+  __sync_val_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval,		\
+				       TYPE newval)			\
+  {									\
+    int *wordptr = (int *)((unsigned long) ptr & ~3), fail;		\
+    unsigned int mask, shift, actual_oldval, actual_newval;		\
+									\
+    shift = (((unsigned long) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH;	\
+    mask = MASK_##WIDTH << shift;					\
+									\
+    while (1)								\
+      {									\
+	actual_oldval = *wordptr;					\
+									\
+	if (((actual_oldval & mask) >> shift) != (unsigned int) oldval)	\
+          return (actual_oldval & mask) >> shift;			\
+									\
+	actual_newval = (actual_oldval & ~mask)				\
+			| (((unsigned int) newval << shift) & mask);	\
+									\
+	fail = __kernel_cmpxchg (actual_oldval, actual_newval,		\
+				 wordptr);				\
+									\
+	if (!fail)							\
+	  return oldval;						\
+      }									\
+  }
+
+SUBWORD_VAL_CAS (short, 2)
+SUBWORD_VAL_CAS (char,  1)
+
+typedef unsigned char bool;
+
+bool HIDDEN
+__sync_bool_compare_and_swap_4 (int *ptr, int oldval, int newval)
+{
+  int failure = __kernel_cmpxchg (oldval, newval, ptr);
+  return (failure == 0);
+}
+
+#define SUBWORD_BOOL_CAS(TYPE, WIDTH)					\
+  bool HIDDEN								\
+  __sync_bool_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval,		\
+					TYPE newval)			\
+  {									\
+    TYPE actual_oldval							\
+      = __sync_val_compare_and_swap_##WIDTH (ptr, oldval, newval);	\
+    return (oldval == actual_oldval);					\
+  }
+
+SUBWORD_BOOL_CAS (short, 2)
+SUBWORD_BOOL_CAS (char,  1)
+
+int HIDDEN
+__sync_lock_test_and_set_4 (int *ptr, int val)
+{
+  int failure, oldval;
+
+  do {
+    oldval = *ptr;
+    failure = __kernel_cmpxchg (oldval, val, ptr);
+  } while (failure != 0);
+
+  return oldval;
+}
+
+#define SUBWORD_TEST_AND_SET(TYPE, WIDTH)				\
+  TYPE HIDDEN								\
+  __sync_lock_test_and_set_##WIDTH (TYPE *ptr, TYPE val)		\
+  {									\
+    int failure;							\
+    unsigned int oldval, newval, shift, mask;				\
+    int *wordptr = (int *) ((unsigned long) ptr & ~3);			\
+									\
+    shift = (((unsigned long) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH;	\
+    mask = MASK_##WIDTH << shift;					\
+									\
+    do {								\
+      oldval = *wordptr;						\
+      newval = (oldval & ~mask)						\
+	       | (((unsigned int) val << shift) & mask);		\
+      failure = __kernel_cmpxchg (oldval, newval, wordptr);		\
+    } while (failure != 0);						\
+									\
+    return (oldval & mask) >> shift;					\
+  }
+
+SUBWORD_TEST_AND_SET (short, 2)
+SUBWORD_TEST_AND_SET (char,  1)
+
+#define SYNC_LOCK_RELEASE(TYPE, WIDTH)					\
+  void HIDDEN								\
+  __sync_lock_release_##WIDTH (TYPE *ptr)				\
+  {									\
+    *ptr = 0;								\
+  }
+
+SYNC_LOCK_RELEASE (int,   4)
+SYNC_LOCK_RELEASE (short, 2)
+SYNC_LOCK_RELEASE (char,  1)
Index: gcc-4.1.2/gcc/config/nios2/linux-unwind.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-4.1.2/gcc/config/nios2/linux-unwind.h	2010-06-30 08:50:26.000000000 +0200
@@ -0,0 +1,166 @@
+/* DWARF2 EH unwinding support for NIOS2 Linux.
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 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.)
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+#ifndef inhibit_libc
+
+/* Do code reading to identify a signal frame, and set the frame
+   state data appropriately.  See unwind-dw2.c for the structs.  */
+
+#include <signal.h>
+#include <asm/unistd.h>
+
+/* Unfortunately the kernel headers define the wrong shape of the
+   register file, so we define our own version here.  This problem has
+   been reported.  */
+
+struct nios2_mcontext
+{
+  int version; /* 2 */
+  unsigned seq_regs[23];  /* regs 1..23 */
+  unsigned ra; /* Return address, r31 */
+  unsigned fp; /* Frame pointer, r28 */
+  unsigned gp; /* Global pointer, r26 */
+  unsigned pad1;
+  unsigned ea; /* Exception return address (pc) */
+  unsigned sp; /* Stack pointer, r27 */
+  unsigned pad2;
+  /* Note r24, r25, r29, r30 are reserved registers */
+};
+
+/* The kernel's definition of this structure also doesn't match
+   reality.  Again, this has been reported. */
+
+struct nios2_ucontext {
+  unsigned long uc_flags;
+  unsigned pad1;
+  void	  *uc_link;
+  stack_t       uc_stack;
+  struct siginfo info;
+  struct nios2_mcontext uc_mcontext;
+};
+
+#define MD_FALLBACK_FRAME_STATE_FOR nios2_fallback_frame_state
+
+static _Unwind_Reason_Code
+nios2_fallback_frame_state (struct _Unwind_Context *context,
+			    _Unwind_FrameState *fs)
+{
+  u_int32_t *pc = (u_int32_t *) context->ra;
+  _Unwind_Ptr new_cfa;
+  int i;
+
+  /* movi r2,(sigreturn/rt_sigreturn)
+     trap  */
+  if (pc[1] != 0x003b683a) /* trap */
+    return _URC_END_OF_STACK;
+
+#define NIOS2_REG(NUM,NAME)					\
+      (fs->regs.reg[NUM].how = REG_SAVED_OFFSET,		\
+       fs->regs.reg[NUM].loc.offset = (_Unwind_Ptr)&regs->NAME - new_cfa)
+
+  if (pc[0] == (0x00800004 | (__NR_sigreturn << 6)))
+    {
+      struct sigframe {
+	u_int32_t trampoline[2];
+	u_int32_t pad1;
+	u_int32_t pad2;
+	struct sigcontext ctx;
+      } *rt_ = context->ra;
+      struct pt_regs *regs = &rt_->ctx.regs;
+
+      /* The CFA is the user's incoming stack pointer value.  */
+      new_cfa = (_Unwind_Ptr)regs->sp;
+      fs->cfa_how = CFA_REG_OFFSET;
+      fs->cfa_reg = STACK_POINTER_REGNUM;
+      fs->cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa;
+
+      /* Regs 1..15 */
+      NIOS2_REG (1, r1);
+      NIOS2_REG (2, r2);
+      NIOS2_REG (3, r3);
+      NIOS2_REG (4, r4);
+      NIOS2_REG (5, r5);
+      NIOS2_REG (6, r6);
+      NIOS2_REG (7, r7);
+      NIOS2_REG (8, r8);
+      NIOS2_REG (9, r9);
+      NIOS2_REG (10, r10);
+      NIOS2_REG (11, r11);
+      NIOS2_REG (12, r12);
+      NIOS2_REG (13, r13);
+      NIOS2_REG (14, r14);
+      NIOS2_REG (15, r15);
+
+      /* Regs 16..23 are not saved here.  They are callee saved or
+	 special.  */
+
+      /* The random registers.  */
+      NIOS2_REG (RA_REGNO, ra);
+      NIOS2_REG (FP_REGNO, fp);
+      NIOS2_REG (GP_REGNO, gp);
+      NIOS2_REG (SIGNAL_UNWIND_RETURN_COLUMN, ea);
+
+      fs->retaddr_column = SIGNAL_UNWIND_RETURN_COLUMN;
+
+      return _URC_NO_REASON;
+    }
+  else if (pc[0] == (0x00800004 | (__NR_rt_sigreturn << 6)))
+    {
+      struct sigframe {
+	u_int32_t trampoline[2];
+	struct nios2_ucontext sigctx;
+      } *rt_ = context->ra;
+      struct nios2_mcontext *regs = &rt_->sigctx.uc_mcontext;
+
+      if (regs->version != 2)
+	return _URC_END_OF_STACK;
+
+      /* The CFA is the user's incoming stack pointer value.  */
+      new_cfa = (_Unwind_Ptr)regs->sp;
+      fs->cfa_how = CFA_REG_OFFSET;
+      fs->cfa_reg = STACK_POINTER_REGNUM;
+      fs->cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa;
+
+      /* The sequential registers.  */
+      for (i = 1; i != 24; i++)
+	NIOS2_REG (i, seq_regs[i-1]);
+
+      /* The random registers.  */
+      NIOS2_REG (RA_REGNO, ra);
+      NIOS2_REG (FP_REGNO, fp);
+      NIOS2_REG (GP_REGNO, gp);
+      NIOS2_REG (SIGNAL_UNWIND_RETURN_COLUMN, ea);
+
+      fs->retaddr_column = SIGNAL_UNWIND_RETURN_COLUMN;
+
+      return _URC_NO_REASON;
+    }
+#undef NIOS2_REG
+  return _URC_END_OF_STACK;
+}
+#endif
Index: gcc-4.1.2/gcc/config/nios2/linux.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-4.1.2/gcc/config/nios2/linux.h	2010-06-30 08:50:26.000000000 +0200
@@ -0,0 +1,58 @@
+/* Definitions for Nios II running Linux-based GNU systems with
+   ELF format.
+   Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2008
+   Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+#undef LIB_SPEC
+#define LIB_SPEC "-lc \
+ %{pthread:-lpthread}"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+"%{!shared: crt1.o%s} \
+ crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+"%{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s"
+
+#define TARGET_OS_CPP_BUILTINS()                \
+  do                                            \
+    {                                           \
+      LINUX_TARGET_OS_CPP_BUILTINS();           \
+      if (flag_pic)                             \
+        {                                       \
+          builtin_define ("__PIC__");           \
+          builtin_define ("__pic__");           \
+        }                                       \
+    }                                           \
+  while (0)
+
+#undef SYSROOT_SUFFIX_SPEC
+#define SYSROOT_SUFFIX_SPEC \
+  "%{EB:/EB}"
+
+#undef LINK_SPEC
+#define LINK_SPEC LINK_SPEC_ENDIAN \
+  " %{shared:-shared} \
+    %{static:-Bstatic} \
+    %{rdynamic:-export-dynamic}"
+
+#define MD_UNWIND_SUPPORT "config/nios2/linux-unwind.h"
Index: gcc-4.1.2/gcc/config/nios2/nios2-protos.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-4.1.2/gcc/config/nios2/nios2-protos.h	2010-06-30 08:50:26.000000000 +0200
@@ -0,0 +1,92 @@
+/* NOT ASSIGNED TO FSF.  COPYRIGHT ALTERA.  */
+/* 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);
+extern enum reg_class reg_class_from_constraint (char, const char *);
+extern void nios2_register_target_pragmas (void);
+
+#ifdef RTX_CODE
+extern int nios2_legitimate_address (rtx, enum machine_mode, int);
+extern int nios2_legitimate_constant (rtx);
+extern void nios2_print_operand (FILE *, rtx, int);
+extern void nios2_print_operand_address (FILE *, rtx);
+extern rtx nios2_legitimize_address (rtx, rtx, enum machine_mode);
+extern bool nios2_legitimate_pic_operand_p (rtx);
+
+extern int nios2_emit_move_sequence (rtx *, enum machine_mode);
+extern int nios2_emit_expensive_div (rtx *, enum machine_mode);
+extern void nios2_adjust_call_address (rtx *);
+
+extern rtx nios2_get_return_address (int);
+extern void nios2_set_return_address (rtx, rtx);
+
+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 call_operand (rtx, enum machine_mode);
+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);
+
+/* custom fpu instruction output */
+extern const char *nios2_output_fpu_insn_cmps (rtx, enum rtx_code);
+extern const char *nios2_output_fpu_insn_cmpd (rtx, enum rtx_code);
+
+# ifdef HAVE_MACHINE_MODES
+#  if defined TREE_CODE
+extern rtx function_arg (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
+extern bool nios2_must_pass_in_stack (enum machine_mode, tree);
+extern int function_arg_partial_nregs (const CUMULATIVE_ARGS *,
+				       enum machine_mode, tree, int);
+extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree,
+				  int);
+extern int nios2_function_arg_padding (enum machine_mode, tree);
+extern int nios2_function_arg_padding_upward (enum machine_mode, tree);
+extern int nios2_block_reg_padding (enum machine_mode, tree, int);
+extern int nios2_block_reg_padding_upward (enum machine_mode, tree, int);
+extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
+extern void nios2_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
+					  tree, int *, int);
+
+#  endif /* TREE_CODE */
+# endif /* HAVE_MACHINE_MODES */
+#endif
+
+#ifdef TREE_CODE
+extern int nios2_return_in_memory (tree);
+
+#endif /* TREE_CODE */
Index: gcc-4.1.2/gcc/config/nios2/nios2.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-4.1.2/gcc/config/nios2/nios2.c	2010-06-30 08:52:12.000000000 +0200
@@ -0,0 +1,4937 @@
+/* NOT ASSIGNED TO FSF.  COPYRIGHT ALTERA.  */
+/* Subroutines for assembler code output for Altera NIOS 2G NIOS2 version.
+   Copyright (C) 2005 Altera
+   Contributed by Jonah Graham (jgraham@altera.com), Will Reece (wreece@altera.com),
+   and Jeff DaSilva (jdasilva@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 "integrate.h"
+#include "ggc.h"
+#include "reload.h"
+#include "debug.h"
+#include "optabs.h"
+#include "target.h"
+#include "target-def.h"
+#include "c-pragma.h"           /* For c_register_pragma.  */
+#include "cpplib.h"             /* For CPP_NUMBER.  */
+#include "c-tree.h"             /* For builtin_function.  */
+
+/* Local prototypes.  */
+static bool nios2_rtx_costs (rtx, int, int, int *);
+
+static void nios2_asm_function_prologue (FILE *, HOST_WIDE_INT);
+static int nios2_issue_rate (void);
+static struct machine_function *nios2_init_machine_status (void);
+static bool nios2_in_small_data_p (tree);
+static void save_reg (int, HOST_WIDE_INT);
+static void restore_reg (int, HOST_WIDE_INT);
+static unsigned int nios2_section_type_flags (tree, const char *, int);
+
+/* 0 --> no #pragma seen
+   1 --> in scope of #pragma reverse_bitfields
+   -1 --> in scope of #pragma no_reverse_bitfields.  */
+static int nios2_pragma_reverse_bitfields_flag = 0;
+static void nios2_pragma_reverse_bitfields (struct cpp_reader *);
+static void nios2_pragma_no_reverse_bitfields (struct cpp_reader *);
+static tree nios2_handle_struct_attribute (tree *, tree, tree, int, bool *);
+static void nios2_insert_attributes (tree, tree *);
+static void nios2_load_pic_register (void);
+static bool nios2_cannot_force_const_mem (rtx);
+bool nios2_legitimate_pic_operand_p (rtx x);
+static rtx nios2_legitimize_pic_address (rtx orig, enum machine_mode mode,
+					 rtx reg);
+rtx nios2_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode);
+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 int nios2_arg_partial_bytes (CUMULATIVE_ARGS *cum,
+				    enum machine_mode mode, tree type,
+				    bool named ATTRIBUTE_UNUSED);
+static bool nios2_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
+				     enum machine_mode mode ATTRIBUTE_UNUSED,
+				     tree type, bool named ATTRIBUTE_UNUSED);
+static void nios2_encode_section_info (tree, rtx, int);
+int nios2_function_arg_padding_upward (enum machine_mode mode, tree type);
+int nios2_block_reg_padding_upward (enum machine_mode mode, tree type,
+                                    int first ATTRIBUTE_UNUSED);
+static void nios2_output_dwarf_dtprel (FILE *fuke, int size, rtx x);
+
+/* Initialize the GCC target structure.  */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue
+
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
+
+#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_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE nios2_pass_by_reference
+
+#undef TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES nios2_arg_partial_bytes
+
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
+
+#undef TARGET_SETUP_INCOMING_VARARGS
+#define TARGET_SETUP_INCOMING_VARARGS nios2_setup_incoming_varargs
+
+#undef TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
+
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS nios2_rtx_costs
+
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS true
+
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM nios2_cannot_force_const_mem
+
+#undef TARGET_ASM_OUTPUT_DWARF_DTPREL
+#define TARGET_ASM_OUTPUT_DWARF_DTPREL nios2_output_dwarf_dtprel
+
+const struct attribute_spec nios2_attribute_table[] =
+{
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+  { "reverse_bitfields",    0, 0, false, false,  false,
+    nios2_handle_struct_attribute },
+  { "no_reverse_bitfields", 0, 0, false, false,  false,
+    nios2_handle_struct_attribute },
+  { NULL,        0, 0, false, false, false, NULL }
+};
+
+#undef TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE nios2_attribute_table
+
+#undef  TARGET_INSERT_ATTRIBUTES
+#define TARGET_INSERT_ATTRIBUTES nios2_insert_attributes
+
+/* ??? Might want to redefine TARGET_RETURN_IN_MSB here to handle
+   big-endian case; depends on what ABI we choose.  */
+
+struct gcc_target targetm = TARGET_INITIALIZER;
+
+
+
+/* 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 (())
+{
+  unsigned HOST_WIDE_INT save_mask; /* Mask of registers to save */
+  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.  */
+  long save_regs_offset; /* Offset from new sp to store gp registers.  */
+  int initialized;       /* != 0 if frame size already calculated.  */
+};
+
+struct machine_function
+GTY (())
+{
+
+  /* Current frame information, calculated by compute_frame_size.  */
+  struct nios2_frame_info frame;
+};
+
+/* Supported TLS relocations.  */
+
+enum tls_reloc {
+  TLS_GD16,
+  TLS_LDM16,
+  TLS_LDO16,
+  TLS_IE16,
+  TLS_LE16
+};
+
+#define IS_UNSPEC_TLS(x) ((x)>=UNSPEC_TLS && (x)<=UNSPEC_ADD_TLS_LDO)
+
+
+
+/***************************************
+ * Register Classes
+ ***************************************/
+
+enum reg_class
+reg_class_from_constraint (char chr, const char *str)
+{
+  if (chr == 'D' && ISDIGIT (str[1]) && ISDIGIT (str[2]))
+    {
+      int regno;
+      int ones = str[2] - '0';
+      int tens = str[1] - '0';
+
+      regno = ones + (10 * tens);
+      if (regno < 0 || regno > 31)
+        return NO_REGS;
+
+      return D00_REG + regno;
+    }
+
+  return NO_REGS;
+}
+
+
+/***************************************
+ * 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 void
+save_reg (int regno, HOST_WIDE_INT offset)
+{
+  rtx reg = gen_rtx_REG (SImode, regno);
+  rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
+
+  rtx pattern = gen_rtx_SET (SImode, gen_frame_mem (Pmode, addr), reg);
+  rtx insn = emit_insn (pattern);
+  RTX_FRAME_RELATED_P (insn) = 1;
+}
+
+static void
+restore_reg (int regno, HOST_WIDE_INT offset)
+{
+  rtx reg = gen_rtx_REG (SImode, regno);
+  rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
+
+  rtx pattern = gen_rtx_SET (SImode, reg, gen_frame_mem (Pmode, addr));
+  emit_insn (pattern);
+}
+
+
+void
+expand_prologue (void)
+{
+  int ix;
+  HOST_WIDE_INT total_frame_size = compute_frame_size ();
+  HOST_WIDE_INT sp_offset; /* offset from base_reg to final stack value */
+  HOST_WIDE_INT fp_offset; /* offset from base_reg to final fp value */
+  HOST_WIDE_INT save_offset;
+  rtx insn;
+  unsigned HOST_WIDE_INT save_mask;
+
+  total_frame_size = compute_frame_size ();
+
+  /* Decrement the stack pointer */
+  if (TOO_BIG_OFFSET (total_frame_size))
+    {
+      /* We need an intermediary point, this will point at the spill
+	 block */
+      insn = emit_insn
+	(gen_add3_insn (stack_pointer_rtx,
+			stack_pointer_rtx,
+			GEN_INT (cfun->machine->frame.save_regs_offset
+				 - total_frame_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+
+      fp_offset = 0;
+      sp_offset = -cfun->machine->frame.save_regs_offset;
+    }
+  else if (total_frame_size)
+    {
+      insn = emit_insn (gen_add3_insn (stack_pointer_rtx,
+				       stack_pointer_rtx,
+				       GEN_INT (-total_frame_size)));
+      RTX_FRAME_RELATED_P (insn) = 1;
+      fp_offset = cfun->machine->frame.save_regs_offset;
+      sp_offset = 0;
+    }
+  else
+    fp_offset = sp_offset = 0;
+
+  if (current_function_limit_stack)
+    emit_insn (gen_stack_overflow_detect_and_trap ());
+
+  save_offset = fp_offset + cfun->machine->frame.save_reg_size;
+  save_mask = cfun->machine->frame.save_mask;
+
+  for (ix = 32; ix--;)
+    if (save_mask & ((unsigned HOST_WIDE_INT)1 << ix))
+      {
+	save_offset -= 4;
+	save_reg (ix, save_offset);
+      }
+
+  if (frame_pointer_needed)
+    {
+      insn = emit_insn (gen_add3_insn (hard_frame_pointer_rtx,
+				       stack_pointer_rtx,
+				       GEN_INT (fp_offset)));
+
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  if (sp_offset)
+    {
+      rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
+      emit_insn (gen_rtx_SET (Pmode, tmp, GEN_INT (sp_offset)));
+
+      insn = emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
+				       tmp));
+      if (!frame_pointer_needed)
+	{
+	  /* Attache a note indicating what just happened */
+	  rtx note = gen_rtx_SET (Pmode, stack_pointer_rtx,
+				  gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+						GEN_INT (sp_offset)));
+	  REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+					      note, REG_NOTES (insn));
+	  RTX_FRAME_RELATED_P (insn) = 1;
+	}
+      if (current_function_limit_stack)
+	emit_insn (gen_stack_overflow_detect_and_trap ());
+    }
+
+  /* Load the PIC register if needed.  */
+  if (current_function_uses_pic_offset_table)
+    nios2_load_pic_register ();
+
+  /* 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 ix;
+  HOST_WIDE_INT total_frame_size = compute_frame_size ();
+  unsigned HOST_WIDE_INT save_mask;
+  HOST_WIDE_INT sp_adjust;
+  HOST_WIDE_INT save_offset;
+
+  if (!sibcall_p && nios2_can_use_return_insn ())
+    {
+      insn = emit_jump_insn (gen_return ());
+      return;
+    }
+
+  emit_insn (gen_blockage ());
+
+  if (frame_pointer_needed)
+    {
+      /* Recover the stack pointer.  */
+      emit_insn (gen_rtx_SET (Pmode, stack_pointer_rtx,
+			      hard_frame_pointer_rtx));
+      save_offset = 0;
+      sp_adjust = total_frame_size - cfun->machine->frame.save_regs_offset;
+    }
+  else if (TOO_BIG_OFFSET (total_frame_size))
+    {
+      rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
+
+      emit_insn
+	(gen_rtx_SET
+	 (Pmode, tmp, GEN_INT (cfun->machine->frame.save_regs_offset)));
+      emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, tmp));
+      save_offset = 0;
+      sp_adjust = total_frame_size - cfun->machine->frame.save_regs_offset;
+    }
+  else
+    {
+      save_offset = cfun->machine->frame.save_regs_offset;
+      sp_adjust = total_frame_size;
+    }
+
+  save_mask = cfun->machine->frame.save_mask;
+  save_offset += cfun->machine->frame.save_reg_size;
+
+  for (ix = 32; ix--;)
+    if (save_mask & ((unsigned HOST_WIDE_INT)1 << ix))
+      {
+	save_offset -= 4;
+	restore_reg (ix, save_offset);
+      }
+
+  if (sp_adjust)
+    emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
+			      GEN_INT (sp_adjust)));
+
+  /* Add in the __builtin_eh_return stack adjustment.  */
+  if (current_function_calls_eh_return)
+    emit_insn (gen_add3_insn (stack_pointer_rtx,
+			      stack_pointer_rtx,
+			      EH_RETURN_STACKADJ_RTX));
+
+  if (!sibcall_p)
+    insn = emit_jump_insn
+      (gen_return_from_epilogue (gen_rtx_REG (Pmode, RA_REGNO)));
+}
+
+/* Implement RETURN_ADDR_RTX.  Note, we do not support moving
+   back to a previous frame.  */
+rtx
+nios2_get_return_address (int count)
+{
+  if (count != 0)
+    return const0_rtx;
+
+  return get_hard_reg_initial_val (Pmode, RA_REGNO);
+}
+
+/* Emit code to change the current function's return address to
+   ADDRESS.  SCRATCH is available as a scratch register, if needed.
+   ADDRESS and SCRATCH are both word-mode GPRs.  */
+
+void
+nios2_set_return_address (rtx address, rtx scratch)
+{
+  compute_frame_size ();
+  if ((cfun->machine->frame.save_mask >> RA_REGNO) & 1)
+    {
+      HOST_WIDE_INT offset = cfun->machine->frame.save_reg_size - 4;
+      rtx base;
+
+      if (frame_pointer_needed)
+	base = hard_frame_pointer_rtx;
+      else
+	{
+	  base = stack_pointer_rtx;
+	  offset += cfun->machine->frame.save_regs_offset;
+
+	  if (TOO_BIG_OFFSET (offset))
+	    {
+	      emit_insn (gen_rtx_SET (Pmode, scratch, GEN_INT (offset)));
+	      emit_insn (gen_add3_insn (scratch, scratch, base));
+	      base = scratch;
+	      offset = 0;
+	    }
+	}
+      if (offset)
+	base = gen_rtx_PLUS (Pmode, base, GEN_INT (offset));
+      emit_insn (gen_rtx_SET (Pmode, gen_rtx_MEM (Pmode, base), address));
+    }
+  else
+    emit_insn (gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, RA_REGNO), address));
+}
+
+bool
+nios2_function_ok_for_sibcall (tree a ATTRIBUTE_UNUSED, tree b ATTRIBUTE_UNUSED)
+{
+  return true;
+}
+
+
+
+
+
+/* ----------------------- *
+ * Profiling
+ * ----------------------- */
+
+void
+function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
+{
+  fprintf (file, "\tmov\tr8, ra\n");
+  if (flag_pic)
+    {
+      fprintf (file, "\tnextpc\tr2\n");
+      fprintf (file, "\t1: movhi\tr3, %%hiadj(_GLOBAL_OFFSET_TABLE_ - 1b)\n");
+      fprintf (file, "\taddi\tr3, r3, %%lo(_GLOBAL_OFFSET_TABLE_ - 1b)\n");
+      fprintf (file, "\tadd\tr2, r2, r3\n");
+      fprintf (file, "\tldw\tr2, %%call(_mcount)(r2)\n");
+      fprintf (file, "\tcallr\tr2\n");
+    }
+  else
+    fprintf (file, "\tcall\t_mcount\n");
+  fprintf (file, "\tmov\tra, r8\n");
+}
+
+
+/***************************************
+ * 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 initialized = %d\n", ASM_COMMENT_START,
+           cfun->machine->frame.initialized);
+  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 true if RENOG should be saved in a prologue.  */
+
+static bool
+save_reg_p (unsigned regno)
+{
+  gcc_assert (GP_REGNO_P (regno));
+
+  if (regs_ever_live[regno] && !call_used_regs[regno])
+    return true;
+
+  if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
+    return true;
+
+  if (regno == PIC_OFFSET_TABLE_REGNUM
+      && current_function_uses_pic_offset_table)
+    return true;
+
+  if (regno == RA_REGNO && regs_ever_live[RA_REGNO])
+    return true;
+
+  return false;
+}
+
+/* Return the bytes needed to compute the frame pointer from the current
+   stack pointer.  */
+
+HOST_WIDE_INT
+compute_frame_size (void)
+{
+  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 out_args_size;  /* # bytes needed for outgoing args. */
+  unsigned HOST_WIDE_INT save_mask = 0;
+
+  if (cfun->machine->frame.initialized)
+    return cfun->machine->frame.total_size;
+
+  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; GP_REGNO_P (regno); regno++)
+    if (save_reg_p (regno))
+      {
+	save_mask |= (unsigned HOST_WIDE_INT)1 << regno;
+	save_reg_size += 4;
+      }
+
+  /* If we call eh_return, we need to save the EH data registers.  */
+  if (current_function_calls_eh_return)
+    {
+      unsigned i;
+      unsigned r;
+
+      for (i = 0; (r = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++)
+	if (!(save_mask & (1 << r)))
+	  {
+	    save_mask |= 1 << r;
+	    save_reg_size += 4;
+	  }
+    }
+
+  save_reg_size = STACK_ALIGN (save_reg_size);
+  total_size += save_reg_size;
+
+  total_size += STACK_ALIGN (current_function_pretend_args_size);
+
+  /* Save other computed information.  */
+  cfun->machine->frame.save_mask = save_mask;
+  cfun->machine->frame.total_size = total_size;
+  cfun->machine->frame.var_size = var_size;
+  cfun->machine->frame.args_size = out_args_size;
+  cfun->machine->frame.save_reg_size = save_reg_size;
+  cfun->machine->frame.initialized = reload_completed;
+
+  cfun->machine->frame.save_regs_offset = out_args_size + var_size;
+
+  return total_size;
+}
+
+
+int
+nios2_initial_elimination_offset (int from, int to)
+{
+  int offset;
+
+  compute_frame_size ();
+
+  /* Set OFFSET to the offset from the stack pointer.  */
+  switch (from)
+    {
+    case FRAME_POINTER_REGNUM:
+      offset = cfun->machine->frame.args_size;
+      break;
+
+    case ARG_POINTER_REGNUM:
+      offset = cfun->machine->frame.total_size;
+      offset -= current_function_pretend_args_size;
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+    /* If we are asked for the frame pointer offset, then adjust OFFSET
+       by the offset from the frame pointer to the stack pointer.  */
+    if (to == HARD_FRAME_POINTER_REGNUM)
+      offset -= cfun->machine->frame.save_regs_offset;
+
+    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 (void)
+{
+  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;
+}
+
+
+
+
+
+/* Try to take a bit of tedium out of the __builtin_custom_<blah>
+   builtin functions, too.  */
+
+#define NIOS2_FOR_ALL_CUSTOM_BUILTINS \
+  NIOS2_DO_BUILTIN (N,    n,    n    ) \
+  NIOS2_DO_BUILTIN (NI,   ni,   nX   ) \
+  NIOS2_DO_BUILTIN (NF,   nf,   nX   ) \
+  NIOS2_DO_BUILTIN (NP,   np,   nX   ) \
+  NIOS2_DO_BUILTIN (NII,  nii,  nXX  ) \
+  NIOS2_DO_BUILTIN (NIF,  nif,  nXX  ) \
+  NIOS2_DO_BUILTIN (NIP,  nip,  nXX  ) \
+  NIOS2_DO_BUILTIN (NFI,  nfi,  nXX  ) \
+  NIOS2_DO_BUILTIN (NFF,  nff,  nXX  ) \
+  NIOS2_DO_BUILTIN (NFP,  nfp,  nXX  ) \
+  NIOS2_DO_BUILTIN (NPI,  npi,  nXX  ) \
+  NIOS2_DO_BUILTIN (NPF,  npf,  nXX  ) \
+  NIOS2_DO_BUILTIN (NPP,  npp,  nXX  ) \
+  NIOS2_DO_BUILTIN (IN,   in,   Xn   ) \
+  NIOS2_DO_BUILTIN (INI,  ini,  XnX  ) \
+  NIOS2_DO_BUILTIN (INF,  inf,  XnX  ) \
+  NIOS2_DO_BUILTIN (INP,  inp,  XnX  ) \
+  NIOS2_DO_BUILTIN (INII, inii, XnXX ) \
+  NIOS2_DO_BUILTIN (INIF, inif, XnXX ) \
+  NIOS2_DO_BUILTIN (INIP, inip, XnXX ) \
+  NIOS2_DO_BUILTIN (INFI, infi, XnXX ) \
+  NIOS2_DO_BUILTIN (INFF, inff, XnXX ) \
+  NIOS2_DO_BUILTIN (INFP, infp, XnXX ) \
+  NIOS2_DO_BUILTIN (INPI, inpi, XnXX ) \
+  NIOS2_DO_BUILTIN (INPF, inpf, XnXX ) \
+  NIOS2_DO_BUILTIN (INPP, inpp, XnXX ) \
+  NIOS2_DO_BUILTIN (FN,   fn,   Xn   ) \
+  NIOS2_DO_BUILTIN (FNI,  fni,  XnX  ) \
+  NIOS2_DO_BUILTIN (FNF,  fnf,  XnX  ) \
+  NIOS2_DO_BUILTIN (FNP,  fnp,  XnX  ) \
+  NIOS2_DO_BUILTIN (FNII, fnii, XnXX ) \
+  NIOS2_DO_BUILTIN (FNIF, fnif, XnXX ) \
+  NIOS2_DO_BUILTIN (FNIP, fnip, XnXX ) \
+  NIOS2_DO_BUILTIN (FNFI, fnfi, XnXX ) \
+  NIOS2_DO_BUILTIN (FNFF, fnff, XnXX ) \
+  NIOS2_DO_BUILTIN (FNFP, fnfp, XnXX ) \
+  NIOS2_DO_BUILTIN (FNPI, fnpi, XnXX ) \
+  NIOS2_DO_BUILTIN (FNPF, fnpf, XnXX ) \
+  NIOS2_DO_BUILTIN (FNPP, fnpp, XnXX ) \
+  NIOS2_DO_BUILTIN (PN,   pn,   Xn   ) \
+  NIOS2_DO_BUILTIN (PNI,  pni,  XnX  ) \
+  NIOS2_DO_BUILTIN (PNF,  pnf,  XnX  ) \
+  NIOS2_DO_BUILTIN (PNP,  pnp,  XnX  ) \
+  NIOS2_DO_BUILTIN (PNII, pnii, XnXX ) \
+  NIOS2_DO_BUILTIN (PNIF, pnif, XnXX ) \
+  NIOS2_DO_BUILTIN (PNIP, pnip, XnXX ) \
+  NIOS2_DO_BUILTIN (PNFI, pnfi, XnXX ) \
+  NIOS2_DO_BUILTIN (PNFF, pnff, XnXX ) \
+  NIOS2_DO_BUILTIN (PNFP, pnfp, XnXX ) \
+  NIOS2_DO_BUILTIN (PNPI, pnpi, XnXX ) \
+  NIOS2_DO_BUILTIN (PNPF, pnpf, XnXX ) \
+  NIOS2_DO_BUILTIN (PNPP, pnpp, XnXX )
+
+#undef NIOS2_FPU_INSN
+#define NIOS2_FPU_INSN(opt, insn, args) \
+static const char *NIOS2_CONCAT (nios2_output_fpu_insn_, insn) (rtx); \
+static void NIOS2_CONCAT (nios2_pragma_, insn) (struct cpp_reader *); \
+static void NIOS2_CONCAT (nios2_pragma_no_, insn) (struct cpp_reader *); \
+int NIOS2_CONCAT (nios2_custom_, opt) = -1;
+NIOS2_FOR_ALL_FPU_INSNS
+
+nios2_fpu_info nios2_fpu_insns[nios2_fpu_max_insn] = {
+#undef NIOS2_FPU_INSN
+#define NIOS2_FPU_INSN(opt, insn, args) \
+  { NIOS2_STRINGIFY (opt), \
+    NIOS2_STRINGIFY (insn), \
+    NIOS2_STRINGIFY (args), \
+    -1, \
+    NIOS2_CONCAT (nios2_output_fpu_insn_, insn), \
+    "custom_" NIOS2_STRINGIFY (opt), \
+    NIOS2_CONCAT (nios2_pragma_, insn), \
+    "no_custom_" NIOS2_STRINGIFY (opt), \
+    NIOS2_CONCAT (nios2_pragma_no_, insn), \
+    0, \
+    0, \
+    0, \
+    0, \
+    0, \
+    &NIOS2_CONCAT (nios2_custom_, opt) },
+  NIOS2_FOR_ALL_FPU_INSNS
+};
+
+const char *nios2_custom_fpu_cfg_string;
+
+static const char *builtin_custom_seen[256];
+
+static void
+nios2_custom_switch (int parameter, int *value, const char *opt)
+{
+  /* We only document values from 0-255, but we secretly allow -1 so
+   * that the -mno-custom-<opt> switches work.  */
+  if (parameter != -1)
+    {
+      if (parameter < -1 || parameter > 255)
+        error ("switch `-mcustom-%s' value %ld must be between 0 and 255",
+               opt, parameter);
+      *value = (int)parameter;
+    }
+}
+
+static void
+nios2_custom_check_insns (int is_pragma)
+{
+  int i;
+  int has_double = 0;
+  int errors = 0;
+  const char *ns[256];
+  int ps[256];
+
+  for (i = 0; i < nios2_fpu_max_insn; i++)
+    if (nios2_fpu_insns[i].is_double && nios2_fpu_insns[i].N >= 0)
+      has_double = 1;
+
+  if (has_double)
+    {
+      for (i = 0; i < nios2_fpu_max_insn; i++)
+        {
+          if (nios2_fpu_insns[i].needed_by_double
+              && nios2_fpu_insns[i].N < 0)
+            {
+              if (is_pragma)
+                error ("either switch `-mcustom-%s' or `#pragma custom_%s' is "
+		       "required for double precision floating point",
+                       nios2_fpu_insns[i].option,
+                       nios2_fpu_insns[i].option);
+              else
+                error ("switch `-mcustom-%s' is required for double precision "
+		       "floating point",
+                       nios2_fpu_insns[i].option);
+              errors = 1;
+            }
+        }
+    }
+
+  /* Warn if the user has certain exotic operations that won't get used
+     without -funsafe-math-optimizations, See expand_builtin () in
+     bulitins.c.  */
+  if (!flag_unsafe_math_optimizations)
+    {
+      for (i = 0; i < nios2_fpu_max_insn; i++)
+        {
+          if (nios2_fpu_insns[i].needs_unsafe && nios2_fpu_insns[i].N >= 0)
+            {
+              warning (0, "%s%s' has no effect unless "
+		       "-funsafe-math-optimizations is specified",
+                       is_pragma ? "`#pragma custom_" : "switch `-mcustom-",
+                       nios2_fpu_insns[i].option);
+              /* Just one warning per function per compilation unit, please.  */
+              nios2_fpu_insns[i].needs_unsafe = 0;
+            }
+        }
+    }
+
+  /* Warn if the user is trying to use -mcustom-fmins et. al, that won't
+     get used without -ffinite-math-only.  See fold in fold () in
+     fold-const.c.  */
+  if (!flag_finite_math_only)
+    {
+      for (i = 0; i < nios2_fpu_max_insn; i++)
+        {
+          if (nios2_fpu_insns[i].needs_finite && nios2_fpu_insns[i].N >= 0)
+            {
+              warning (0, "%s%s' has no effect unless -ffinite-math-only "
+		       "is specified",
+                       is_pragma ? "`#pragma custom_" : "switch `-mcustom-",
+                       nios2_fpu_insns[i].option);
+              /* Just one warning per function per compilation unit, please.  */
+              nios2_fpu_insns[i].needs_finite = 0;
+            }
+        }
+    }
+
+  /* Warn the user about double precision divide braindamage until we
+     can fix it properly.  See the RDIV_EXPR case of expand_expr_real in
+     expr.c.  */
+  {
+    static int warned = 0;
+    if (flag_unsafe_math_optimizations
+        && !optimize_size
+        && nios2_fpu_insns[nios2_fpu_divdf3].N >= 0
+        && !warned)
+      {
+        warning (0, "%s%s' behaves poorly without -Os",
+                 is_pragma ? "`#pragma custom_" : "switch `-mcustom-",
+                 nios2_fpu_insns[nios2_fpu_divdf3].option);
+        warned = 1;
+      }
+  }
+
+  /* The following bit of voodoo is lifted from the generated file
+     insn-opinit.c: to allow #pragmas to work properly, we have to tweak
+     the optab_table manually -- it only gets initialized once after the
+     switches are handled and before any #pragmas are seen.  */
+  if (is_pragma)
+    {
+      /* Only do this if the optabs have already been defined, not
+         when we're handling command line switches.  */
+      addv_optab->handlers[SFmode].insn_code =
+      add_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
+      addv_optab->handlers[DFmode].insn_code =
+      add_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
+      subv_optab->handlers[SFmode].insn_code =
+      sub_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
+      subv_optab->handlers[DFmode].insn_code =
+      sub_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
+      smulv_optab->handlers[SFmode].insn_code =
+      smul_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
+      smulv_optab->handlers[DFmode].insn_code =
+      smul_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
+      sdiv_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
+      sdiv_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
+      negv_optab->handlers[SFmode].insn_code =
+      neg_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
+      negv_optab->handlers[DFmode].insn_code =
+      neg_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
+      smin_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
+      smin_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
+      smax_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
+      smax_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
+      absv_optab->handlers[SFmode].insn_code =
+      abs_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
+      absv_optab->handlers[DFmode].insn_code =
+      abs_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
+      sqrt_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
+      sqrt_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
+      cos_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
+      cos_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
+      sin_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
+      sin_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
+      tan_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
+      tan_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
+      atan_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
+      atan_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
+      exp_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
+      exp_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
+      log_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
+      log_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
+      sfloat_optab->handlers[SFmode][SImode].insn_code = CODE_FOR_nothing;
+      sfloat_optab->handlers[DFmode][SImode].insn_code = CODE_FOR_nothing;
+      ufloat_optab->handlers[SFmode][SImode].insn_code = CODE_FOR_nothing;
+      ufloat_optab->handlers[DFmode][SImode].insn_code = CODE_FOR_nothing;
+      sfix_optab->handlers[SImode][SFmode].insn_code = CODE_FOR_nothing;
+      sfix_optab->handlers[SImode][DFmode].insn_code = CODE_FOR_nothing;
+      ufix_optab->handlers[SImode][SFmode].insn_code = CODE_FOR_nothing;
+      ufix_optab->handlers[SImode][DFmode].insn_code = CODE_FOR_nothing;
+      sext_optab->handlers[DFmode][SFmode].insn_code = CODE_FOR_nothing;
+      trunc_optab->handlers[SFmode][DFmode].insn_code = CODE_FOR_nothing;
+      cmp_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
+      cmp_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
+
+      if (HAVE_addsf3)
+        addv_optab->handlers[SFmode].insn_code =
+        add_optab->handlers[SFmode].insn_code = CODE_FOR_addsf3;
+      if (HAVE_adddf3)
+        addv_optab->handlers[DFmode].insn_code =
+        add_optab->handlers[DFmode].insn_code = CODE_FOR_adddf3;
+      if (HAVE_subsf3)
+        subv_optab->handlers[SFmode].insn_code =
+        sub_optab->handlers[SFmode].insn_code = CODE_FOR_subsf3;
+      if (HAVE_subdf3)
+        subv_optab->handlers[DFmode].insn_code =
+        sub_optab->handlers[DFmode].insn_code = CODE_FOR_subdf3;
+      if (HAVE_mulsf3)
+        smulv_optab->handlers[SFmode].insn_code =
+        smul_optab->handlers[SFmode].insn_code = CODE_FOR_mulsf3;
+      if (HAVE_muldf3)
+        smulv_optab->handlers[DFmode].insn_code =
+        smul_optab->handlers[DFmode].insn_code = CODE_FOR_muldf3;
+      if (HAVE_divsf3)
+        sdiv_optab->handlers[SFmode].insn_code = CODE_FOR_divsf3;
+      if (HAVE_divdf3)
+        sdiv_optab->handlers[DFmode].insn_code = CODE_FOR_divdf3;
+      if (HAVE_negsf2)
+        negv_optab->handlers[SFmode].insn_code =
+        neg_optab->handlers[SFmode].insn_code = CODE_FOR_negsf2;
+      if (HAVE_negdf2)
+        negv_optab->handlers[DFmode].insn_code =
+        neg_optab->handlers[DFmode].insn_code = CODE_FOR_negdf2;
+      if (HAVE_minsf3)
+        smin_optab->handlers[SFmode].insn_code = CODE_FOR_minsf3;
+      if (HAVE_mindf3)
+        smin_optab->handlers[DFmode].insn_code = CODE_FOR_mindf3;
+      if (HAVE_maxsf3)
+        smax_optab->handlers[SFmode].insn_code = CODE_FOR_maxsf3;
+      if (HAVE_maxdf3)
+        smax_optab->handlers[DFmode].insn_code = CODE_FOR_maxdf3;
+      if (HAVE_abssf2)
+        absv_optab->handlers[SFmode].insn_code =
+        abs_optab->handlers[SFmode].insn_code = CODE_FOR_abssf2;
+      if (HAVE_absdf2)
+        absv_optab->handlers[DFmode].insn_code =
+        abs_optab->handlers[DFmode].insn_code = CODE_FOR_absdf2;
+      if (HAVE_sqrtsf2)
+        sqrt_optab->handlers[SFmode].insn_code = CODE_FOR_sqrtsf2;
+      if (HAVE_sqrtdf2)
+        sqrt_optab->handlers[DFmode].insn_code = CODE_FOR_sqrtdf2;
+      if (HAVE_cossf2)
+        cos_optab->handlers[SFmode].insn_code = CODE_FOR_cossf2;
+      if (HAVE_cosdf2)
+        cos_optab->handlers[DFmode].insn_code = CODE_FOR_cosdf2;
+      if (HAVE_sinsf2)
+        sin_optab->handlers[SFmode].insn_code = CODE_FOR_sinsf2;
+      if (HAVE_sindf2)
+        sin_optab->handlers[DFmode].insn_code = CODE_FOR_sindf2;
+      if (HAVE_tansf2)
+        tan_optab->handlers[SFmode].insn_code = CODE_FOR_tansf2;
+      if (HAVE_tandf2)
+        tan_optab->handlers[DFmode].insn_code = CODE_FOR_tandf2;
+      if (HAVE_atansf2)
+        atan_optab->handlers[SFmode].insn_code = CODE_FOR_atansf2;
+      if (HAVE_atandf2)
+        atan_optab->handlers[DFmode].insn_code = CODE_FOR_atandf2;
+      if (HAVE_expsf2)
+        exp_optab->handlers[SFmode].insn_code = CODE_FOR_expsf2;
+      if (HAVE_expdf2)
+        exp_optab->handlers[DFmode].insn_code = CODE_FOR_expdf2;
+      if (HAVE_logsf2)
+        log_optab->handlers[SFmode].insn_code = CODE_FOR_logsf2;
+      if (HAVE_logdf2)
+        log_optab->handlers[DFmode].insn_code = CODE_FOR_logdf2;
+      if (HAVE_floatsisf2)
+        sfloat_optab->handlers[SFmode][SImode].insn_code = CODE_FOR_floatsisf2;
+      if (HAVE_floatsidf2)
+        sfloat_optab->handlers[DFmode][SImode].insn_code = CODE_FOR_floatsidf2;
+      if (HAVE_floatunssisf2)
+        ufloat_optab->handlers[SFmode][SImode].insn_code = CODE_FOR_floatunssisf2;
+      if (HAVE_floatunssidf2)
+        ufloat_optab->handlers[DFmode][SImode].insn_code = CODE_FOR_floatunssidf2;
+      if (HAVE_fixsfsi2)
+        sfix_optab->handlers[SImode][SFmode].insn_code = CODE_FOR_fixsfsi2;
+      if (HAVE_fixdfsi2)
+        sfix_optab->handlers[SImode][DFmode].insn_code = CODE_FOR_fixdfsi2;
+      if (HAVE_fixunssfsi2)
+        ufix_optab->handlers[SImode][SFmode].insn_code = CODE_FOR_fixunssfsi2;
+      if (HAVE_fixunsdfsi2)
+        ufix_optab->handlers[SImode][DFmode].insn_code = CODE_FOR_fixunsdfsi2;
+      if (HAVE_extendsfdf2)
+        sext_optab->handlers[DFmode][SFmode].insn_code = CODE_FOR_extendsfdf2;
+      if (HAVE_truncdfsf2)
+        trunc_optab->handlers[SFmode][DFmode].insn_code = CODE_FOR_truncdfsf2;
+      if (HAVE_cmpsf)
+        cmp_optab->handlers[SFmode].insn_code = CODE_FOR_cmpsf;
+      if (HAVE_cmpdf)
+        cmp_optab->handlers[DFmode].insn_code = CODE_FOR_cmpdf;
+    }
+
+  /* Check for duplicate values of N.  */
+  for (i = 0; i < 256; i++)
+    {
+      ns[i] = 0;
+      ps[i] = 0;
+    }
+
+  for (i = 0; i < nios2_fpu_max_insn; i++)
+    {
+      int N = nios2_fpu_insns[i].N;
+      if (N >= 0)
+        {
+          if (ns[N])
+            {
+              error ("%s%s' conflicts with %s%s'",
+                     is_pragma ? "`#pragma custom_" : "switch `-mcustom-",
+                     nios2_fpu_insns[i].option,
+                     ps[N] ? "`#pragma custom_" : "switch `-mcustom-",
+                     ns[N]);
+              errors = 1;
+            }
+          else if (builtin_custom_seen[N])
+            {
+              error ("call to `%s' conflicts with %s%s'",
+                     builtin_custom_seen[N],
+                     (nios2_fpu_insns[i].pragma_seen
+                      ? "`#pragma custom_" : "switch `-mcustom-"),
+                     nios2_fpu_insns[i].option);
+              errors = 1;
+            }
+          else
+            {
+              ns[N] = nios2_fpu_insns[i].option;
+              ps[N] = nios2_fpu_insns[i].pragma_seen;
+            }
+        }
+    }
+
+  if (errors)
+    fatal_error ("conflicting use of -mcustom switches, #pragmas, and/or "
+		 "__builtin_custom_ functions");
+}
+
+static void
+nios2_handle_custom_fpu_cfg (const char *cfg, int is_pragma)
+{
+#undef NIOS2_FPU_INSN
+#define NIOS2_FPU_INSN(opt, insn, args) \
+  int opt = nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].N;
+NIOS2_FOR_ALL_FPU_INSNS
+
+  /*
+   * ??? These are just some sample possibilities.  We'll change these
+   * at the last minute to match the capabilities of the actual fpu.
+   */
+  if (!strcasecmp (cfg, "60-1"))
+    {
+      fmuls = 252;
+      fadds = 253;
+      fsubs = 254;
+      flag_single_precision_constant = 1;
+    }
+  else if (!strcasecmp (cfg, "60-2"))
+    {
+      fmuls = 252;
+      fadds = 253;
+      fsubs = 254;
+      fdivs = 255;
+      flag_single_precision_constant = 1;
+    }
+  else if (!strcasecmp (cfg, "72-3"))
+    {
+      floatus = 243;
+      fixsi   = 244;
+      floatis = 245;
+      fcmpgts = 246;
+      fcmples = 249;
+      fcmpeqs = 250;
+      fcmpnes = 251;
+      fmuls   = 252;
+      fadds   = 253;
+      fsubs   = 254;
+      fdivs   = 255;
+      flag_single_precision_constant = 1;
+    }
+  else
+    warning (0, "ignoring unrecognized %sfpu-cfg' value `%s'",
+             is_pragma ? "`#pragma custom_" : "switch -mcustom-", cfg);
+
+#undef NIOS2_FPU_INSN
+#define NIOS2_FPU_INSN(opt, insn, args) \
+  nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].N = opt;
+NIOS2_FOR_ALL_FPU_INSNS
+
+  /* Guard against errors in the standard configurations.  */
+  nios2_custom_check_insns (is_pragma);
+}
+
+void
+override_options (void)
+{
+  int i;
+
+  /* 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 we don't have mul, we don't have mulx either!  */
+  if (!TARGET_HAS_MUL && TARGET_HAS_MULX)
+    target_flags &= ~MASK_HAS_MULX;
+
+  /* Set up for stack limit checking.  */
+  if (TARGET_STACK_CHECK)
+    stack_limit_rtx = gen_rtx_REG(SImode, ET_REGNO);
+
+  for (i = 0; i < nios2_fpu_max_insn; i++)
+    {
+      nios2_fpu_insns[i].is_double = (nios2_fpu_insns[i].args[0] == 'd'
+                                      || nios2_fpu_insns[i].args[0] == 'd'
+                                      || nios2_fpu_insns[i].args[0] == 'd');
+      nios2_fpu_insns[i].needed_by_double = (i == nios2_fpu_nios2_fwrx
+                                             || i == nios2_fpu_nios2_fwry
+                                             || i == nios2_fpu_nios2_frdxlo
+                                             || i == nios2_fpu_nios2_frdxhi
+                                             || i == nios2_fpu_nios2_frdy);
+      nios2_fpu_insns[i].needs_unsafe = (i == nios2_fpu_cossf2
+                                         || i == nios2_fpu_cosdf2
+                                         || i == nios2_fpu_sinsf2
+                                         || i == nios2_fpu_sindf2
+                                         || i == nios2_fpu_tansf2
+                                         || i == nios2_fpu_tandf2
+                                         || i == nios2_fpu_atansf2
+                                         || i == nios2_fpu_atandf2
+                                         || i == nios2_fpu_expsf2
+                                         || i == nios2_fpu_expdf2
+                                         || i == nios2_fpu_logsf2
+                                         || i == nios2_fpu_logdf2);
+      nios2_fpu_insns[i].needs_finite = (i == nios2_fpu_minsf3
+                                         || i == nios2_fpu_maxsf3
+                                         || i == nios2_fpu_mindf3
+                                         || i == nios2_fpu_maxdf3);
+    }
+
+  /* We haven't seen any __builtin_custom functions yet.  */
+  for (i = 0; i < 256; i++)
+    builtin_custom_seen[i] = 0;
+
+  /* Set up default handling for floating point custom instructions.
+
+     Putting things in this order means that the -mcustom-fpu-cfg=
+     switch will always be overridden by individual -mcustom-fadds=
+     switches, regardless of the order in which they were specified
+     on the command line.  ??? Remember to document this.  */
+  if (nios2_custom_fpu_cfg_string && *nios2_custom_fpu_cfg_string)
+    nios2_handle_custom_fpu_cfg (nios2_custom_fpu_cfg_string, 0);
+
+  for (i = 0; i < nios2_fpu_max_insn; i++)
+    nios2_custom_switch (*nios2_fpu_insns[i].pN,
+                         &nios2_fpu_insns[i].N,
+                         nios2_fpu_insns[i].option);
+
+  nios2_custom_check_insns (0);
+}
+
+void
+optimization_options (int level, int size)
+{
+  if (level || size)
+    target_flags |= MASK_INLINE_MEMCPY;
+
+  if (level >= 3 && !size)
+    target_flags |= MASK_FAST_SW_DIV;
+}
+
+/* Allocate a chunk of memory for per-function machine-dependent data.  */
+static struct machine_function *
+nios2_init_machine_status (void)
+{
+  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.
+ ***************************************/
+
+/* Return TRUE if X references a SYMBOL_REF.  */
+static int
+symbol_mentioned_p (rtx x)
+{
+  const char * fmt;
+  int i;
+
+  if (GET_CODE (x) == SYMBOL_REF)
+    return 1;
+
+  /* UNSPEC_TLS entries for a symbol include the SYMBOL_REF, but they
+     are constant offsets, not symbols.  */
+  if (GET_CODE (x) == UNSPEC && IS_UNSPEC_TLS (XINT (x, 1)))
+    return 0;
+
+  fmt = GET_RTX_FORMAT (GET_CODE (x));
+
+  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'E')
+        {
+          int j;
+
+          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+            if (symbol_mentioned_p (XVECEXP (x, i, j)))
+              return 1;
+        }
+      else if (fmt[i] == 'e' && symbol_mentioned_p (XEXP (x, i)))
+        return 1;
+    }
+
+  return 0;
+}
+
+/* Return TRUE if X references a LABEL_REF.  */
+static int
+label_mentioned_p (rtx x)
+{
+  const char * fmt;
+  int i;
+
+  if (GET_CODE (x) == LABEL_REF)
+    return 1;
+
+  /* UNSPEC_TLS entries for a symbol include a LABEL_REF for the referencing
+     instruction, but they are constant offsets, not symbols.  */
+  if (GET_CODE (x) == UNSPEC && IS_UNSPEC_TLS (XINT (x, 1)))
+    return 0;
+
+  fmt = GET_RTX_FORMAT (GET_CODE (x));
+  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'E')
+        {
+          int j;
+
+          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+            if (label_mentioned_p (XVECEXP (x, i, j)))
+              return 1;
+        }
+      else if (fmt[i] == 'e' && label_mentioned_p (XEXP (x, i)))
+        return 1;
+    }
+
+  return 0;
+}
+
+static int
+tls_mentioned_p (rtx x)
+{
+  switch (GET_CODE (x))
+    {
+    case CONST:
+      return tls_mentioned_p (XEXP (x, 0));
+
+    case UNSPEC:
+      if (IS_UNSPEC_TLS (XINT (x, 1)))
+        return 1;
+
+    default:
+      return 0;
+    }
+}
+
+/* Helper for nios2_tls_referenced_p.  */
+
+static int
+nios2_tls_operand_p_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
+{
+  if (GET_CODE (*x) == SYMBOL_REF)
+    return SYMBOL_REF_TLS_MODEL (*x) != 0;
+
+  /* Don't recurse into UNSPEC_TLS looking for TLS symbols; these are
+     TLS offsets, not real symbol references.  */
+  if (GET_CODE (*x) == UNSPEC
+      && IS_UNSPEC_TLS (XINT (*x, 1)))
+    return -1;
+
+  return 0;
+}
+
+/* Return TRUE if X contains any TLS symbol references.  */
+
+static bool
+nios2_tls_referenced_p (rtx x)
+{
+  if (! TARGET_HAVE_TLS)
+    return false;
+
+  return for_each_rtx (&x, nios2_tls_operand_p_1, NULL);
+}
+
+static bool
+nios2_cannot_force_const_mem (rtx x)
+{
+  return nios2_tls_referenced_p (x);
+}
+
+/* Emit a call to __tls_get_addr.  TI is the argument to this function.  RET is
+   an RTX for the return value location.  The entire insn sequence is
+   returned.  */
+
+static GTY(()) rtx nios2_tls_symbol;
+
+static rtx
+nios2_call_tls_get_addr (rtx ti)
+{
+  rtx arg = gen_rtx_REG (Pmode, FIRST_ARG_REGNO);
+  rtx ret = gen_rtx_REG (Pmode, FIRST_RETVAL_REGNO);
+  rtx fn, insn;
+
+  if (!nios2_tls_symbol)
+    nios2_tls_symbol = init_one_libfunc ("__tls_get_addr");
+
+  emit_insn (gen_rtx_SET (Pmode, arg, ti));
+  fn = gen_rtx_MEM (QImode, nios2_tls_symbol);
+  insn = emit_call_insn (gen_call_value (ret, fn, const0_rtx));
+  CONST_OR_PURE_CALL_P (insn) = 1;
+  use_reg (&CALL_INSN_FUNCTION_USAGE (insn), ret);
+  use_reg (&CALL_INSN_FUNCTION_USAGE (insn), arg);
+
+  return ret;
+}
+
+/* Generate the code to access LOC, a thread local SYMBOL_REF.  The
+   return value will be a valid address and move_operand (either a REG
+   or a LO_SUM).  */
+
+static rtx
+nios2_legitimize_tls_address (rtx loc)
+{
+  rtx dest = gen_reg_rtx (Pmode);
+  rtx ret, tmp1;
+  enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
+
+  switch (model)
+    {
+    case TLS_MODEL_GLOBAL_DYNAMIC:
+      tmp1 = gen_reg_rtx (Pmode);
+      emit_insn (gen_add_tls_gd (tmp1, pic_offset_table_rtx, loc));
+      current_function_uses_pic_offset_table = 1;
+      ret = nios2_call_tls_get_addr (tmp1);
+      emit_insn (gen_rtx_SET (Pmode, dest, ret));
+      break;
+
+    case TLS_MODEL_LOCAL_DYNAMIC:
+      tmp1 = gen_reg_rtx (Pmode);
+      emit_insn (gen_add_tls_ldm (tmp1, pic_offset_table_rtx, loc));
+      current_function_uses_pic_offset_table = 1;
+      ret = nios2_call_tls_get_addr (tmp1);
+
+      emit_insn (gen_add_tls_ldo (dest, ret, loc));
+
+      break;
+
+    case TLS_MODEL_INITIAL_EXEC:
+      tmp1 = gen_reg_rtx (Pmode);
+      emit_insn (gen_load_tls_ie (tmp1, pic_offset_table_rtx, loc));
+      current_function_uses_pic_offset_table = 1;
+      emit_insn (gen_add3_insn (dest,
+				gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM),
+				tmp1));
+      break;
+
+    case TLS_MODEL_LOCAL_EXEC:
+      emit_insn (gen_add_tls_le (dest,
+				 gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM),
+				 loc));
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  return dest;
+}
+
+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);
+    }
+
+  /* Recognize the case where from is a reference to thread-local
+     data and load its address to a register.  */
+  if (nios2_tls_referenced_p (from))
+    {
+      rtx tmp = from;
+      rtx addend = NULL;
+
+      if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
+        {
+          addend = XEXP (XEXP (tmp, 0), 1);
+          tmp = XEXP (XEXP (tmp, 0), 0);
+        }
+
+      gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
+      gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
+
+      tmp = nios2_legitimize_tls_address (tmp);
+      if (addend)
+	{
+          tmp = gen_rtx_PLUS (SImode, tmp, addend);
+          tmp = force_operand (tmp, to);
+        }
+      from = tmp;
+    }
+  else if (flag_pic && (CONSTANT_P (from) || symbol_mentioned_p (from) ||
+			label_mentioned_p (from)))
+    from = nios2_legitimize_pic_address (from, SImode,
+					 (no_new_pseudos ? to : 0));
+
+  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.  */
+  gcc_assert (mode == SImode);
+
+  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;
+}
+
+/* The function with address *ADDR is being called.  If the address
+   needs to be loaded from the GOT, emit the instruction to do so and
+   update *ADDR to point to the rtx for the loaded value.  */
+
+void
+nios2_adjust_call_address (rtx *addr)
+{
+  if (flag_pic
+      && (GET_CODE (*addr) == SYMBOL_REF || GET_CODE (*addr) == LABEL_REF))
+    {
+      rtx addr_orig;
+      current_function_uses_pic_offset_table = 1;
+      addr_orig = *addr;
+      *addr = gen_reg_rtx (GET_MODE (addr_orig));
+      emit_insn (gen_pic_load_call_addr (*addr,
+					 pic_offset_table_rtx, addr_orig));
+    }
+}
+
+/* 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;
+}
+
+bool have_nios2_fpu_cmp_insn( enum rtx_code cond_t, enum cmp_type cmp_t );
+enum rtx_code get_reverse_cond(enum rtx_code cond_t);
+
+bool
+have_nios2_fpu_cmp_insn( enum rtx_code cond_t, enum cmp_type cmp_t )
+{
+  if (cmp_t == CMP_SF)
+    {
+      switch (cond_t)
+	{
+        case EQ:
+          return (nios2_fpu_insns[nios2_fpu_nios2_seqsf].N >= 0);
+        case NE:
+          return (nios2_fpu_insns[nios2_fpu_nios2_snesf].N >= 0);
+        case GT:
+          return (nios2_fpu_insns[nios2_fpu_nios2_sgtsf].N >= 0);
+        case GE:
+          return (nios2_fpu_insns[nios2_fpu_nios2_sgesf].N >= 0);
+        case LT:
+          return (nios2_fpu_insns[nios2_fpu_nios2_sltsf].N >= 0);
+        case LE:
+          return (nios2_fpu_insns[nios2_fpu_nios2_slesf].N >= 0);
+        default:
+          break;
+        }
+    }
+  else if (cmp_t == CMP_DF)
+    {
+      switch (cond_t)
+	{
+	case EQ:
+	  return (nios2_fpu_insns[nios2_fpu_nios2_seqdf].N >= 0);
+	case NE:
+	  return (nios2_fpu_insns[nios2_fpu_nios2_snedf].N >= 0);
+	case GT:
+	  return (nios2_fpu_insns[nios2_fpu_nios2_sgtdf].N >= 0);
+	case GE:
+	  return (nios2_fpu_insns[nios2_fpu_nios2_sgedf].N >= 0);
+	case LT:
+	  return (nios2_fpu_insns[nios2_fpu_nios2_sltdf].N >= 0);
+	case LE:
+	  return (nios2_fpu_insns[nios2_fpu_nios2_sledf].N >= 0);
+	default:
+	  break;
+      }
+    }
+
+  return false;
+}
+
+/* Note that get_reverse_cond() is not the same as get_inverse_cond()
+   get_reverse_cond() means that if the operand order is reversed,
+   what is the operand that is needed to generate the same condition?  */
+enum rtx_code
+get_reverse_cond(enum rtx_code cond_t)
+{
+  switch (cond_t)
+    {
+      case GT: return LT;
+      case GE: return LE;
+      case LT: return GT;
+      case LE: return GE;
+      case GTU: return LTU;
+      case GEU: return LEU;
+      case LTU: return GTU;
+      case LEU: return GEU;
+      default: break;
+    }
+
+  return cond_t;
+}
+
+
+/* Generate the code to compare (and possibly branch) two integer values
+   TEST_CODE is the comparison code we are trying to emulate
+     (or implement directly)
+   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);
+  gcc_assert (test != ITEST_MAX);
+
+  p_info = &info[(int) test];
+
+  mode = GET_MODE (cmp0);
+  if (mode == VOIDmode)
+    mode = GET_MODE (cmp1);
+
+  branch_p = (destination != 0);
+
+  /* Handle floating point comparison directly. */
+  if (branch_type == CMP_SF || branch_type == CMP_DF)
+    {
+
+      bool reverse_operands = false;
+
+      enum machine_mode float_mode = (branch_type == CMP_SF) ? SFmode : DFmode;
+
+      gcc_assert (register_operand (cmp0, float_mode) &&
+	          register_operand (cmp1, float_mode));
+
+      if (branch_p)
+	{
+          test_code = p_info->test_code_reg;
+          reverse_operands = (p_info->reverse_regs);
+        }
+
+      if (!have_nios2_fpu_cmp_insn(test_code, branch_type) &&
+           have_nios2_fpu_cmp_insn(get_reverse_cond(test_code), branch_type) )
+        {
+          test_code = get_reverse_cond(test_code);
+          reverse_operands = !reverse_operands;
+        }
+
+      if (reverse_operands)
+        {
+          rtx temp = cmp0;
+          cmp0 = cmp1;
+          cmp1 = temp;
+        }
+
+      if (branch_p)
+        {
+          rtx cond = gen_rtx_fmt_ee (test_code, SImode, cmp0, cmp1);
+          rtx label = gen_rtx_LABEL_REF (VOIDmode, destination);
+          rtx insn = gen_rtx_SET (VOIDmode, pc_rtx,
+                                  gen_rtx_IF_THEN_ELSE (VOIDmode,
+                                                        cond, label, pc_rtx));
+          emit_jump_insn (insn);
+        }
+      else
+        emit_move_insn (result, gen_rtx_fmt_ee (test_code, SImode, cmp0,
+						cmp1));
+      return;
+    }
+
+  /* We can't, under any circumstances, have const_ints in cmp0
+     ??? Actually we could have const0.  */
+  if (GET_CODE (cmp0) == CONST_INT)
+    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.  */
+          gcc_assert ((p_info->unsignedp
+                       ? (unsigned HOST_WIDE_INT) new >
+                       (unsigned HOST_WIDE_INT) INTVAL (cmp1)
+                       : new > INTVAL (cmp1)) == (p_info->const_add > 0));
+
+          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_fmt_ee (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_fmt_ee (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_fmt_ee (p_info->test_code_reg, mode, cmp0, cmp1));
+      else
+        emit_move_insn (result,
+                        gen_rtx_fmt_ee (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_fmt_ee (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_constant (rtx x)
+{
+  switch (GET_CODE (x))
+    {
+    case SYMBOL_REF:
+      return !SYMBOL_REF_TLS_MODEL (x);
+    case CONST:
+      {
+	rtx op = XEXP (x, 0);
+	if (GET_CODE (op) != PLUS)
+	  return false;
+	return nios2_legitimate_constant (XEXP (op, 0))
+	  && nios2_legitimate_constant (XEXP (op, 1));
+      }
+    default:
+      return true;
+    }
+}
+
+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_TLS_MODEL (operand))
+	break;
+
+      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) && GET_CODE (op1) == CONST_INT)
+          ret_val = REG_OK_FOR_BASE_P2 (op0, strict)
+            && SMALL_INT (INTVAL (op1));
+        else if (REG_P (op1) && GET_CODE (op0) == CONST_INT)
+          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 && (unsigned HOST_WIDE_INT)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);
+
+  if (strcmp (name, ".sbss") == 0
+      || strncmp (name, ".sbss.", 6) == 0
+      || strcmp (name, ".sdata") == 0
+      || strncmp (name, ".sdata.", 7) == 0)
+    flags |= SECTION_SMALL;
+
+  return flags;
+}
+
+/* Handle a #pragma reverse_bitfields.  */
+static void
+nios2_pragma_reverse_bitfields (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
+{
+  nios2_pragma_reverse_bitfields_flag = 1; /* Reverse */
+}
+
+/* Handle a #pragma no_reverse_bitfields.  */
+static void
+nios2_pragma_no_reverse_bitfields (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
+{
+  nios2_pragma_reverse_bitfields_flag = -1; /* Forward */
+}
+
+/* Handle the various #pragma custom_<switch>s.  */
+static void
+nios2_pragma_fpu (int *value, const char *opt, int *seen)
+{
+  tree t;
+  if (c_lex (&t) != CPP_NUMBER)
+    {
+      error ("`#pragma custom_%s' value must be a number between 0 and 255",
+             opt);
+      return;
+    }
+
+  if (TREE_INT_CST_HIGH (t) == 0
+      && TREE_INT_CST_LOW (t) <= 255)
+    {
+      *value = (int)TREE_INT_CST_LOW (t);
+      *seen = 1;
+    }
+  else
+    error ("`#pragma custom_%s' value must be between 0 and 255", opt);
+  nios2_custom_check_insns (1);
+}
+
+/* Handle the various #pragma no_custom_<switch>s.  */
+static void
+nios2_pragma_no_fpu (int *value, const char *opt ATTRIBUTE_UNUSED)
+{
+  *value = -1;
+  nios2_custom_check_insns (1);
+}
+
+#undef NIOS2_FPU_INSN
+#define NIOS2_FPU_INSN(opt, insn, args) \
+static void \
+NIOS2_CONCAT (nios2_pragma_, insn) \
+  (struct cpp_reader *pfile ATTRIBUTE_UNUSED) \
+{ \
+  nios2_fpu_info *inf = &(nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)]); \
+  nios2_pragma_fpu (&(inf->N), inf->option, &(inf->pragma_seen)); \
+} \
+static void \
+NIOS2_CONCAT (nios2_pragma_no_, insn) \
+  (struct cpp_reader *pfile ATTRIBUTE_UNUSED) \
+{ \
+  nios2_fpu_info *inf = &(nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)]); \
+  nios2_pragma_no_fpu (&(inf->N), inf->option); \
+}
+NIOS2_FOR_ALL_FPU_INSNS
+
+static void
+nios2_pragma_handle_custom_fpu_cfg (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
+{
+  tree t;
+  if (c_lex (&t) != CPP_STRING)
+    {
+      error ("`#pragma custom_fpu_cfg' value must be a string");
+      return;
+    }
+
+  if (TREE_STRING_LENGTH (t) > 0)
+    nios2_handle_custom_fpu_cfg (TREE_STRING_POINTER (t), 1);
+}
+
+void
+nios2_register_target_pragmas (void)
+{
+  int i;
+
+  c_register_pragma (0, "reverse_bitfields",
+                     nios2_pragma_reverse_bitfields);
+  c_register_pragma (0, "no_reverse_bitfields",
+                     nios2_pragma_no_reverse_bitfields);
+
+  for (i = 0; i < nios2_fpu_max_insn; i++)
+    {
+      nios2_fpu_info *inf = &(nios2_fpu_insns[i]);
+      c_register_pragma (0, inf->pname, inf->pragma);
+      c_register_pragma (0, inf->nopname, inf->nopragma);
+    }
+
+  c_register_pragma (0, "custom_fpu_cfg",
+                     nios2_pragma_handle_custom_fpu_cfg);
+}
+
+/* Handle a "reverse_bitfields" or "no_reverse_bitfields" attribute.
+   ??? What do these attributes mean on a union?  */
+static tree
+nios2_handle_struct_attribute (tree *node, tree name,
+                               tree args ATTRIBUTE_UNUSED,
+                               int flags ATTRIBUTE_UNUSED,
+                               bool *no_add_attrs)
+{
+  tree *type = NULL;
+  if (DECL_P (*node))
+    {
+      if (TREE_CODE (*node) == TYPE_DECL)
+        type = &TREE_TYPE (*node);
+    }
+  else
+    type = node;
+
+  if (!(type && (TREE_CODE (*type) == RECORD_TYPE
+                 || TREE_CODE (*type) == UNION_TYPE)))
+    {
+      warning (0, "`%s' attribute ignored", IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  else if ((is_attribute_p ("reverse_bitfields", name)
+            && lookup_attribute ("no_reverse_bitfields",
+                                 TYPE_ATTRIBUTES (*type)))
+           || ((is_attribute_p ("no_reverse_bitfields", name)
+                && lookup_attribute ("reverse_bitfields",
+                                     TYPE_ATTRIBUTES (*type)))))
+    {
+      warning (0, "`%s' incompatible attribute ignored",
+               IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+/* Add __attribute__ ((pragma_reverse_bitfields)) when in the scope of a
+   #pragma reverse_bitfields, or __attribute__
+   ((pragma_no_reverse_bitfields)) when in the scope of a #pragma
+   no_reverse_bitfields.  This gets called before
+   nios2_handle_struct_attribute above, so we can't just reuse the same
+   attributes.  */
+static void
+nios2_insert_attributes (tree node, tree *attr_ptr)
+{
+  tree type = NULL;
+  if (DECL_P (node))
+    {
+      if (TREE_CODE (node) == TYPE_DECL)
+        type = TREE_TYPE (node);
+    }
+  else
+    type = node;
+
+  if (!type
+      || (TREE_CODE (type) != RECORD_TYPE
+          && TREE_CODE (type) != UNION_TYPE))
+    {
+      /* We can ignore things other than structs & unions.  */
+      return;
+    }
+
+  if (lookup_attribute ("reverse_bitfields", TYPE_ATTRIBUTES (type))
+      || lookup_attribute ("no_reverse_bitfields", TYPE_ATTRIBUTES (type)))
+    {
+      /* If an attribute is already set, it silently overrides the
+         current #pragma, if any.  */
+      return;
+    }
+
+  if (nios2_pragma_reverse_bitfields_flag)
+    {
+      const char *id = (nios2_pragma_reverse_bitfields_flag == 1 ?
+                        "pragma_reverse_bitfields" :
+                        "pragma_no_reverse_bitfields");
+      /* No attribute set, and we are in the scope of a #pragma.  */
+      *attr_ptr = tree_cons (get_identifier (id), NULL, *attr_ptr);
+    }
+}
+
+/*****************************************
+ * Position Independent Code
+ *****************************************/
+
+/* Emit code to load the PIC register.  */
+
+static void
+nios2_load_pic_register (void)
+{
+  rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
+
+  emit_insn (gen_load_got_register (pic_offset_table_rtx, tmp));
+  emit_insn (gen_add3_insn (pic_offset_table_rtx, pic_offset_table_rtx, tmp));
+}
+
+/* Nonzero if the constant value X is a legitimate general operand
+   when generating PIC code.  It is given that flag_pic is on and
+   that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
+
+bool
+nios2_legitimate_pic_operand_p (rtx x)
+{
+  rtx inner;
+
+  /* UNSPEC_TLS is always PIC.  */
+  if (tls_mentioned_p (x))
+    return true;
+
+  if (GET_CODE (x) == SYMBOL_REF)
+    return false;
+  if (GET_CODE (x) == LABEL_REF)
+    return false;
+  if (GET_CODE (x) == CONST)
+    {
+      inner = XEXP (x, 0);
+      if (GET_CODE (inner) == PLUS &&
+          GET_CODE (XEXP (inner, 0)) == SYMBOL_REF &&
+	  GET_CODE (XEXP (inner, 1)) == CONST)
+	return false;
+    }
+  return true;
+}
+
+rtx
+nios2_legitimize_pic_address (rtx orig,
+			      enum machine_mode mode ATTRIBUTE_UNUSED, rtx reg)
+{
+  if (GET_CODE (orig) == SYMBOL_REF
+      || GET_CODE (orig) == LABEL_REF)
+    {
+      if (reg == 0)
+	{
+	  gcc_assert (!no_new_pseudos);
+	  reg = gen_reg_rtx (Pmode);
+	}
+
+      emit_insn (gen_pic_load_addr (reg, pic_offset_table_rtx, orig));
+
+      current_function_uses_pic_offset_table = 1;
+
+      return reg;
+    }
+  else if (GET_CODE (orig) == CONST)
+    {
+      rtx base, offset;
+
+      if (GET_CODE (XEXP (orig, 0)) == PLUS
+	  && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
+	return orig;
+
+      if (GET_CODE (XEXP (orig, 0)) == UNSPEC
+	  && IS_UNSPEC_TLS (XINT (XEXP (orig, 0), 1)))
+	return orig;
+
+      if (reg == 0)
+	{
+	  gcc_assert (!no_new_pseudos);
+	  reg = gen_reg_rtx (Pmode);
+	}
+
+      gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
+
+      base = nios2_legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode,
+					   reg);
+      offset = nios2_legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
+					     base == reg ? 0 : reg);
+
+      if (GET_CODE (offset) == CONST_INT)
+	return plus_constant (base, INTVAL (offset));
+
+      return gen_rtx_PLUS (Pmode, base, offset);
+    }
+
+  return orig;
+}
+
+/* Test for various thread-local symbols.  */
+
+/* Return TRUE if X is a thread-local symbol.  */
+
+static bool
+nios2_tls_symbol_p (rtx x)
+{
+  if (! TARGET_HAVE_TLS)
+    return false;
+
+  if (GET_CODE (x) != SYMBOL_REF)
+    return false;
+
+  return SYMBOL_REF_TLS_MODEL (x) != 0;
+}
+
+rtx
+nios2_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
+{
+  if (nios2_tls_symbol_p (x))
+    return nios2_legitimize_tls_address (x);
+
+  if (flag_pic)
+    {
+      /* We need to find and carefully transform any SYMBOL and LABEL
+         references; so go back to the original address expression.  */
+      rtx new_x = nios2_legitimize_pic_address (orig_x, mode, NULL_RTX);
+
+      if (new_x != orig_x)
+        x = new_x;
+    }
+
+  return x;
+}
+
+/*****************************************
+ * 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
+     D: for the upper 32-bits of a 64-bit double 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 && 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;
+        }
+      else if (letter == 'D')
+        {
+          fprintf (file, "%s", reg_names[REGNO (op)+1]);
+          return;
+        }
+      break;
+
+    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;
+        }
+      break;
+
+
+    case SUBREG:
+    case MEM:
+      if (letter == 0)
+        {
+          output_address (op);
+          return;
+        }
+      break;
+
+    case CODE_LABEL:
+      if (letter == 0)
+        {
+          output_addr_const (file, op);
+          return;
+        }
+      break;
+
+    default:
+      break;
+    }
+
+  fprintf (stderr, "Missing way to print (%c) ", letter);
+  debug_rtx (op);
+  gcc_unreachable ();
+}
+
+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);
+  gcc_unreachable ();
+}
+
+
+
+/****************************
+ * Debug information
+ ****************************/
+
+static void
+nios2_output_dwarf_dtprel (FILE *file, int size, rtx x)
+{
+  gcc_assert (size == 4);
+  fputs ("\t.4byte\t%tls_ldo(", file);
+  output_addr_const (file, x);
+  fputs (")", file);
+}
+
+
+/****************************
+ * Predicates
+ ****************************/
+
+/* An operand to a call or sibcall.  This must be an immediate operand
+   or a register.  */
+int
+call_operand (rtx x, enum machine_mode mode)
+{
+  return (immediate_operand (x, mode)
+	  || register_operand (x, mode));
+}
+
+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));
+}
+
+
+
+
+/*****************************************************************************
+**
+** custom fpu instruction output
+**
+*****************************************************************************/
+
+static const char *nios2_custom_fpu_insn_zdz (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_zsz (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_szz (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_sss (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_ssz (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_iss (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_ddd (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_ddz (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_idd (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_siz (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_suz (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_diz (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_duz (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_isz (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_usz (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_idz (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_udz (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_dsz (rtx, int, const char *);
+static const char *nios2_custom_fpu_insn_sdz (rtx, int, const char *);
+
+static const char *
+nios2_custom_fpu_insn_zdz (rtx insn, int N, const char *opt)
+{
+  static char buf[1024];
+
+  if (N < 0)
+    fatal_insn ("attempt to use disabled fpu instruction", insn);
+  if (snprintf (buf, sizeof (buf),
+                "custom\t%d, zero, %%0, %%D0 # %s %%0",
+                N, opt) >= (int)sizeof (buf))
+    fatal_insn ("buffer overflow", insn);
+  return buf;
+}
+
+static const char *
+nios2_custom_fpu_insn_zsz (rtx insn, int N, const char *opt)
+{
+  static char buf[1024];
+
+  if (N < 0)
+    fatal_insn ("attempt to use disabled fpu instruction", insn);
+  if (snprintf (buf, sizeof (buf),
+                "custom\t%d, zero, %%0, zero # %s %%0",
+                N, opt) >= (int)sizeof (buf))
+    fatal_insn ("buffer overflow", insn);
+  return buf;
+}
+
+static const char *
+nios2_custom_fpu_insn_szz (rtx insn, int N, const char *opt)
+{
+  static char buf[1024];
+
+  if (N < 0)
+    fatal_insn ("attempt to use disabled fpu instruction", insn);
+  if (snprintf (buf, sizeof (buf),
+                "custom\t%d, %%0, zero, zero # %s %%0",
+                N, opt) >= (int)sizeof (buf))
+    fatal_insn ("buffer overflow", insn);
+  return buf;
+}
+
+static const char *
+nios2_custom_fpu_insn_sss (rtx insn, int N, const char *opt)
+{
+  static char buf[1024];
+
+  if (N < 0)
+    fatal_insn ("attempt to use disabled fpu instruction", insn);
+  if (snprintf (buf, sizeof (buf),
+                "custom\t%d, %%0, %%1, %%2 # %s %%0, %%1, %%2",
+                N, opt) >= (int)sizeof (buf))
+    fatal_insn ("buffer overflow", insn);
+  return buf;
+}
+
+static const char *
+nios2_custom_fpu_insn_ssz (rtx insn, int N, const char *opt)
+{
+  static char buf[1024];
+
+  if (N < 0)
+    fatal_insn ("attempt to use disabled fpu instruction", insn);
+  if (snprintf (buf, sizeof (buf),
+                "custom\t%d, %%0, %%1, zero # %s %%0, %%1",
+                N, opt) >= (int)sizeof (buf))
+    fatal_insn ("buffer overflow", insn);
+  return buf;
+}
+
+static const char *
+nios2_custom_fpu_insn_iss (rtx insn, int N, const char *opt)
+{
+  return nios2_custom_fpu_insn_sss (insn, N, opt);
+}
+
+static const char *
+nios2_custom_fpu_insn_ddd (rtx insn, int N, const char *opt)
+{
+  static char buf[1024];
+
+  if (N < 0
+      || nios2_fpu_insns[nios2_fpu_nios2_frdy].N < 0
+      || nios2_fpu_insns[nios2_fpu_nios2_fwrx].N < 0)
+    fatal_insn ("attempt to use disabled fpu instruction", insn);
+  if (snprintf (buf, sizeof (buf),
+                "custom\t%d, zero, %%1, %%D1 # fwrx %%1\n\t"
+                "custom\t%d, %%D0, %%2, %%D2 # %s %%0, %%1, %%2\n\t"
+                "custom\t%d, %%0, zero, zero # frdy %%0",
+                nios2_fpu_insns[nios2_fpu_nios2_fwrx].N,
+                N, opt,
+                nios2_fpu_insns[nios2_fpu_nios2_frdy].N) >= (int)sizeof (buf))
+    fatal_insn ("buffer overflow", insn);
+  return buf;
+}
+
+static const char *
+nios2_custom_fpu_insn_ddz (rtx insn, int N, const char *opt)
+{
+  static char buf[1024];
+
+  if (N < 0 || nios2_fpu_insns[nios2_fpu_nios2_frdy].N < 0)
+    fatal_insn ("attempt to use disabled fpu instruction", insn);
+  if (snprintf (buf, sizeof (buf),
+                "custom\t%d, %%D0, %%1, %%D1 # %s %%0, %%1\n\t"
+                "custom\t%d, %%0, zero, zero # frdy %%0",
+                N, opt,
+                nios2_fpu_insns[nios2_fpu_nios2_frdy].N) >= (int)sizeof (buf))
+    fatal_insn ("buffer overflow", insn);
+  return buf;
+}
+
+static const char *
+nios2_custom_fpu_insn_idd (rtx insn, int N, const char *opt)
+{
+  static char buf[1024];
+
+  if (N < 0 || nios2_fpu_insns[nios2_fpu_nios2_fwrx].N < 0)
+    fatal_insn ("attempt to use disabled fpu instruction", insn);
+  if (snprintf (buf, sizeof (buf),
+                "custom\t%d, zero, %%1, %%D1 # fwrx %%1\n\t"
+                "custom\t%d, %%0, %%2, %%D2 # %s %%0, %%1, %%2",
+                nios2_fpu_insns[nios2_fpu_nios2_fwrx].N,
+                N, opt) >= (int)sizeof (buf))
+    fatal_insn ("buffer overflow", insn);
+  return buf;
+}
+
+static const char *
+nios2_custom_fpu_insn_siz (rtx insn, int N, const char *opt)
+{
+  return nios2_custom_fpu_insn_ssz (insn, N, opt);
+}
+
+static const char *
+nios2_custom_fpu_insn_suz (rtx insn, int N, const char *opt)
+{
+  return nios2_custom_fpu_insn_ssz (insn, N, opt);
+}
+
+static const char *
+nios2_custom_fpu_insn_diz (rtx insn, int N, const char *opt)
+{
+  return nios2_custom_fpu_insn_dsz (insn, N, opt);
+}
+
+static const char *
+nios2_custom_fpu_insn_duz (rtx insn, int N, const char *opt)
+{
+  return nios2_custom_fpu_insn_dsz (insn, N, opt);
+}
+
+static const char *
+nios2_custom_fpu_insn_isz (rtx insn, int N, const char *opt)
+{
+  return nios2_custom_fpu_insn_ssz (insn, N, opt);
+}
+
+static const char *
+nios2_custom_fpu_insn_usz (rtx insn, int N, const char *opt)
+{
+  return nios2_custom_fpu_insn_ssz (insn, N, opt);
+}
+
+static const char *
+nios2_custom_fpu_insn_idz (rtx insn, int N, const char *opt)
+{
+  return nios2_custom_fpu_insn_sdz (insn, N, opt);
+}
+
+static const char *
+nios2_custom_fpu_insn_udz (rtx insn, int N, const char *opt)
+{
+  return nios2_custom_fpu_insn_sdz (insn, N, opt);
+}
+
+static const char *
+nios2_custom_fpu_insn_dsz (rtx insn, int N, const char *opt)
+{
+  static char buf[1024];
+
+  if (N < 0 || nios2_fpu_insns[nios2_fpu_nios2_frdy].N < 0)
+    fatal_insn ("attempt to use disabled fpu instruction", insn);
+  if (snprintf (buf, sizeof (buf),
+                "custom\t%d, %%D0, %%1, zero # %s %%0, %%1\n\t"
+                "custom\t%d, %%0, zero, zero # frdy %%0",
+                N, opt,
+                nios2_fpu_insns[nios2_fpu_nios2_frdy].N) >= (int)sizeof (buf))
+    fatal_insn ("buffer overflow", insn);
+  return buf;
+}
+
+static const char *
+nios2_custom_fpu_insn_sdz (rtx insn, int N, const char *opt)
+{
+  static char buf[1024];
+
+  if (N < 0)
+    fatal_insn ("attempt to use disabled fpu instruction", insn);
+  if (snprintf (buf, sizeof (buf),
+                "custom\t%d, %%0, %%1, %%D1 # %s %%0, %%1",
+                N, opt) >= (int)sizeof (buf))
+    fatal_insn ("buffer overflow", insn);
+  return buf;
+}
+
+#undef NIOS2_FPU_INSN
+#define NIOS2_FPU_INSN(opt, insn, args) \
+static const char * \
+NIOS2_CONCAT (nios2_output_fpu_insn_, insn) (rtx i) \
+{ \
+  return NIOS2_CONCAT (nios2_custom_fpu_insn_, args) \
+           (i, \
+            nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].N, \
+            nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].option); \
+}
+NIOS2_FOR_ALL_FPU_INSNS
+
+
+
+const char *
+nios2_output_fpu_insn_cmps (rtx insn, enum rtx_code cond)
+{
+  static char buf[1024];
+  int N;
+  const char *opt;
+
+  int operandL = 2;
+  int operandR = 3;
+
+  if (!have_nios2_fpu_cmp_insn(cond, CMP_SF) &&
+       have_nios2_fpu_cmp_insn(get_reverse_cond(cond), CMP_SF) ) {
+
+    int temp = operandL;
+    operandL = operandR;
+    operandR = temp;
+
+    cond = get_reverse_cond(cond);
+  }
+
+  switch (cond)
+    {
+    case EQ:
+      N = nios2_fpu_insns[nios2_fpu_nios2_seqsf].N;
+      opt = "fcmpeqs";
+      break;
+    case NE:
+      N = nios2_fpu_insns[nios2_fpu_nios2_snesf].N;
+      opt = "fcmpnes";
+      break;
+    case GT:
+      N = nios2_fpu_insns[nios2_fpu_nios2_sgtsf].N;
+      opt = "fcmpgts";
+      break;
+    case GE:
+      N = nios2_fpu_insns[nios2_fpu_nios2_sgesf].N;
+      opt = "fcmpges";
+      break;
+    case LT:
+      N = nios2_fpu_insns[nios2_fpu_nios2_sltsf].N;
+      opt = "fcmplts";
+      break;
+    case LE:
+      N = nios2_fpu_insns[nios2_fpu_nios2_slesf].N;
+      opt = "fcmples"; break;
+    default:
+      fatal_insn ("bad single compare", insn);
+    }
+
+  if (N < 0)
+    fatal_insn ("attempt to use disabled fpu instruction", insn);
+
+  /* ??? This raises the whole vexing issue of how to handle
+     out-of-range branches.  Punt for now, seeing as how nios2-elf-as
+     doesn't even _try_ to handle out-of-range branches yet!  */
+  if (snprintf (buf, sizeof (buf),
+                ".set\tnoat\n\t"
+                "custom\t%d, at, %%%d, %%%d # %s at, %%%d, %%%d\n\t"
+                "bne\tat, zero, %%l1\n\t"
+                ".set\tat",
+                N, operandL, operandR, opt, operandL, operandR
+	       ) >= (int)sizeof (buf))
+    fatal_insn ("buffer overflow", insn);
+  return buf;
+}
+
+const char *
+nios2_output_fpu_insn_cmpd (rtx insn, enum rtx_code cond)
+{
+  static char buf[1024];
+  int N;
+  const char *opt;
+
+  int operandL = 2;
+  int operandR = 3;
+
+  if ( !have_nios2_fpu_cmp_insn(cond, CMP_DF) &&
+       have_nios2_fpu_cmp_insn(get_reverse_cond(cond), CMP_DF) )
+    {
+
+      int temp = operandL;
+      operandL = operandR;
+      operandR = temp;
+
+      cond = get_reverse_cond(cond);
+    }
+
+  switch (cond)
+    {
+    case EQ:
+      N = nios2_fpu_insns[nios2_fpu_nios2_seqdf].N;
+      opt = "fcmpeqd";
+      break;
+    case NE:
+      N = nios2_fpu_insns[nios2_fpu_nios2_snedf].N;
+      opt = "fcmpned";
+      break;
+    case GT:
+      N = nios2_fpu_insns[nios2_fpu_nios2_sgtdf].N;
+      opt = "fcmpgtd";
+      break;
+    case GE:
+      N = nios2_fpu_insns[nios2_fpu_nios2_sgedf].N;
+      opt = "fcmpged";
+      break;
+    case LT:
+      N = nios2_fpu_insns[nios2_fpu_nios2_sltdf].N;
+      opt = "fcmpltd";
+      break;
+    case LE:
+      N = nios2_fpu_insns[nios2_fpu_nios2_sledf].N;
+      opt = "fcmpled";
+      break;
+    default:
+      fatal_insn ("bad double compare", insn);
+    }
+
+  if (N < 0 || nios2_fpu_insns[nios2_fpu_nios2_fwrx].N < 0)
+    fatal_insn ("attempt to use disabled fpu instruction", insn);
+  if (snprintf (buf, sizeof (buf),
+                ".set\tnoat\n\t"
+                "custom\t%d, zero, %%%d, %%D%d # fwrx %%%d\n\t"
+                "custom\t%d, at, %%%d, %%D%d # %s at, %%%d, %%%d\n\t"
+                "bne\tat, zero, %%l1\n\t"
+                ".set\tat",
+                nios2_fpu_insns[nios2_fpu_nios2_fwrx].N, operandL, operandL,
+		operandL, N, operandR, operandR, opt, operandL, operandR
+	       ) >= (int)sizeof (buf))
+    fatal_insn ("buffer overflow", insn);
+  return buf;
+}
+
+
+
+
+/*****************************************************************************
+**
+** Instruction scheduler
+**
+*****************************************************************************/
+static int
+nios2_issue_rate (void)
+{
+#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;
+}
+
+
+/* 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;
+}
+
+/* Return number of bytes, at the beginning of the argument, that must be
+   put in registers.  0 is the argument is entirely in registers or entirely
+   in memory.  */
+
+static int
+nios2_arg_partial_bytes (CUMULATIVE_ARGS *cum,
+                         enum machine_mode mode, tree type,
+                         bool 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) * UNITS_PER_WORD;
+  else
+    return 0;
+}
+
+static bool
+nios2_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
+			 enum machine_mode mode ATTRIBUTE_UNUSED,
+			 tree type ATTRIBUTE_UNUSED,
+			 bool named ATTRIBUTE_UNUSED)
+{
+  return false;
+}
+
+
+/* Update the data in CUM to advance over an argument
+   of mode MODE and data type TYPE.
+   (TYPE is null for libcalls where that information may not be available.)  */
+
+void
+function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+                      tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
+{
+  HOST_WIDE_INT param_size;
+
+  if (mode == BLKmode)
+    {
+      param_size = int_size_in_bytes (type);
+      if (param_size < 0)
+        internal_error
+          ("Do not know how to handle large structs or variable length types");
+    }
+  else
+    param_size = GET_MODE_SIZE (mode);
+
+  /* Convert to words (round up).  */
+  param_size = (3 + param_size) / 4;
+
+  if (cum->regs_used + param_size > NUM_ARG_REGS)
+    cum->regs_used = NUM_ARG_REGS;
+  else
+    cum->regs_used += param_size;
+
+  return;
+}
+
+int
+nios2_function_arg_padding_upward (enum machine_mode mode, tree type)
+{
+  /* On little-endian targets, the first byte of every stack argument
+     is passed in the first byte of the stack slot.  */
+  if (!BYTES_BIG_ENDIAN)
+    return 1;
+
+  /* Otherwise, integral types are padded downward: the last byte of a
+     stack argument is passed in the last byte of the stack slot.  */
+  if (type != 0
+      ? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
+      : GET_MODE_CLASS (mode) == MODE_INT)
+    return 0;
+
+  /* Arguments smaller than a stack slot are padded downward.  */
+  if (mode != BLKmode)
+    return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY) ? 1 : 0;
+  else
+    return ((int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT))
+            ? 1 : 0);
+}
+
+int
+nios2_block_reg_padding_upward (enum machine_mode mode, tree type,
+                         int first ATTRIBUTE_UNUSED)
+{
+  /* ??? Do we need to treat floating point specially, ala MIPS?  */
+  return nios2_function_arg_padding_upward (mode, type);
+}
+
+int
+nios2_return_in_memory (tree type)
+{
+  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.  */
+void
+nios2_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
+                              enum machine_mode mode, tree type,
+                              int *pretend_size, int second_time)
+{
+  CUMULATIVE_ARGS local_cum;
+  int regs_to_push;
+  int pret_size;
+
+  local_cum = *cum;
+  FUNCTION_ARG_ADVANCE (local_cum, mode, type, 1);
+
+  regs_to_push = NUM_ARG_REGS - local_cum.regs_used;
+
+  if (!second_time)
+    {
+      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 ());
+        }
+    }
+
+  pret_size = regs_to_push * UNITS_PER_WORD;
+
+  if (pret_size)
+    *pretend_size = pret_size;
+}
+
+
+
+/*****************************************************************************
+**
+** 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,
+
+#undef NIOS2_DO_BUILTIN
+#define NIOS2_DO_BUILTIN(upper, lower, handler) \
+  NIOS2_CONCAT (NIOS2_BUILTIN_CUSTOM_, upper),
+NIOS2_FOR_ALL_CUSTOM_BUILTINS
+
+  NIOS2_FIRST_FPU_INSN,
+
+#undef NIOS2_FPU_INSN
+#define NIOS2_FPU_INSN(opt, insn, args) \
+  NIOS2_CONCAT (NIOS2_BUILTIN_FPU_, opt),
+NIOS2_FOR_ALL_FPU_INSNS
+
+  NIOS2_LAST_FPU_INSN,
+
+  LIM_NIOS2_BUILTINS
+};
+
+struct builtin_description
+{
+    const enum insn_code icode;
+    const char *const name;
+    const enum nios2_builtins code;
+    const tree *type;
+    rtx (* expander) (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 rtx nios2_expand_custom_zdz (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_zsz (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_szz (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_sss (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_ssz (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_iss (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_ddd (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_ddz (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_idd (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_siz (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_suz (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_diz (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_duz (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_isz (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_usz (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_idz (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_udz (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_dsz (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+static rtx nios2_expand_custom_sdz (const struct builtin_description *,
+                                    tree, rtx, rtx, enum machine_mode, int);
+
+static tree endlink;
+
+/* int fn (volatile const void *)
+ */
+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;
+
+#undef NIOS2_DO_BUILTIN
+#define NIOS2_DO_BUILTIN(upper, lower, handler) \
+  static tree NIOS2_CONCAT (custom_, lower);
+NIOS2_FOR_ALL_CUSTOM_BUILTINS
+
+static tree custom_zdz;
+static tree custom_zsz;
+static tree custom_szz;
+static tree custom_sss;
+static tree custom_ssz;
+static tree custom_iss;
+static tree custom_ddd;
+static tree custom_ddz;
+static tree custom_idd;
+static tree custom_siz;
+static tree custom_suz;
+static tree custom_diz;
+static tree custom_duz;
+static tree custom_isz;
+static tree custom_usz;
+static tree custom_idz;
+static tree custom_udz;
+static tree custom_dsz;
+static tree custom_sdz;
+
+static const struct builtin_description bdesc[] = {
+    {CODE_FOR_ldbio, "__builtin_ldbio", NIOS2_BUILTIN_LDBIO,
+     &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
+    {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},
+
+#undef NIOS2_DO_BUILTIN
+#define NIOS2_DO_BUILTIN(upper, lower, handler) \
+    {NIOS2_CONCAT (CODE_FOR_custom_, lower), \
+     "__builtin_custom_" NIOS2_STRINGIFY (lower), \
+     NIOS2_CONCAT (NIOS2_BUILTIN_CUSTOM_, upper), \
+     &NIOS2_CONCAT (custom_, lower), \
+     NIOS2_CONCAT (nios2_expand_custom_, handler)},
+NIOS2_FOR_ALL_CUSTOM_BUILTINS
+
+#undef NIOS2_FPU_INSN
+#define NIOS2_FPU_INSN(opt, insn, args) \
+    {NIOS2_CONCAT (CODE_FOR_, insn), \
+     "__builtin_custom_" NIOS2_STRINGIFY (opt), \
+     NIOS2_CONCAT (NIOS2_BUILTIN_FPU_, opt), \
+     &NIOS2_CONCAT (custom_, args), \
+     NIOS2_CONCAT (nios2_expand_custom_, args)},
+NIOS2_FOR_ALL_FPU_INSNS
+
+    {0, 0, 0, 0, 0},
+};
+
+static void
+nios2_init_builtins (void)
+{
+  const struct builtin_description *d;
+
+
+  endlink = void_list_node;
+
+  /* int fn (volatile const void *)
+   */
+  int_ftype_volatile_const_void_p = build_function_type (
+    integer_type_node,
+    tree_cons (NULL_TREE,
+	       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,
+    tree_cons (NULL_TREE,
+	       build_qualified_type (ptr_type_node, TYPE_QUAL_VOLATILE),
+               tree_cons (NULL_TREE, 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,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink));
+
+  /* void fn (int, int)
+   */
+  void_ftype_int_int
+      = build_function_type (void_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink)));
+
+  custom_n
+      = build_function_type (void_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink));
+  custom_ni
+      = build_function_type (void_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink)));
+  custom_nf
+      = build_function_type (void_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink)));
+  custom_np
+      = build_function_type (void_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             endlink)));
+  custom_nii
+      = build_function_type (void_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink))));
+  custom_nif
+      = build_function_type (void_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink))));
+  custom_nip
+      = build_function_type (void_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             endlink))));
+  custom_nfi
+      = build_function_type (void_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink))));
+  custom_nff
+      = build_function_type (void_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink))));
+  custom_nfp
+      = build_function_type (void_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             endlink))));
+  custom_npi
+      = build_function_type (void_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink))));
+  custom_npf
+      = build_function_type (void_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink))));
+  custom_npp
+      = build_function_type (void_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             endlink))));
+
+  custom_in
+      = build_function_type (integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink));
+  custom_ini
+      = build_function_type (integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink)));
+  custom_inf
+      = build_function_type (integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink)));
+  custom_inp
+      = build_function_type (integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             endlink)));
+  custom_inii
+      = build_function_type (integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink))));
+  custom_inif
+      = build_function_type (integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink))));
+  custom_inip
+      = build_function_type (integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             endlink))));
+  custom_infi
+      = build_function_type (integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink))));
+  custom_inff
+      = build_function_type (integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink))));
+  custom_infp
+      = build_function_type (integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             endlink))));
+  custom_inpi
+      = build_function_type (integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink))));
+  custom_inpf
+      = build_function_type (integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink))));
+  custom_inpp
+      = build_function_type (integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             endlink))));
+
+  custom_fn
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink));
+  custom_fni
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink)));
+  custom_fnf
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink)));
+  custom_fnp
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             endlink)));
+  custom_fnii
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink))));
+  custom_fnif
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink))));
+  custom_fnip
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             endlink))));
+  custom_fnfi
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink))));
+  custom_fnff
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink))));
+  custom_fnfp
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             endlink))));
+  custom_fnpi
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink))));
+  custom_fnpf
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink))));
+  custom_fnpp
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             endlink))));
+
+
+  custom_pn
+      = build_function_type (ptr_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink));
+  custom_pni
+      = build_function_type (ptr_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink)));
+  custom_pnf
+      = build_function_type (ptr_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink)));
+  custom_pnp
+      = build_function_type (ptr_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             endlink)));
+  custom_pnii
+      = build_function_type (ptr_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink))));
+  custom_pnif
+      = build_function_type (ptr_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink))));
+  custom_pnip
+      = build_function_type (ptr_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             endlink))));
+  custom_pnfi
+      = build_function_type (ptr_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink))));
+  custom_pnff
+      = build_function_type (ptr_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink))));
+  custom_pnfp
+      = build_function_type (ptr_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             endlink))));
+  custom_pnpi
+      = build_function_type (ptr_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink))));
+  custom_pnpf
+      = build_function_type (ptr_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink))));
+  custom_pnpp
+      = build_function_type (ptr_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             tree_cons (NULL_TREE, ptr_type_node,
+                             endlink))));
+
+  custom_zdz
+      = build_function_type (void_type_node,
+                             tree_cons (NULL_TREE, double_type_node,
+                             endlink));
+
+  custom_zsz
+      = build_function_type (void_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink));
+
+  custom_szz
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, void_type_node,
+                             endlink));
+
+  custom_sss
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink)));
+
+  custom_ssz
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink));
+
+  custom_iss
+      = build_function_type (integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink)));
+
+  custom_ddd
+      = build_function_type (double_type_node,
+                             tree_cons (NULL_TREE, double_type_node,
+                             tree_cons (NULL_TREE, double_type_node,
+                             endlink)));
+
+  custom_ddz
+      = build_function_type (double_type_node,
+                             tree_cons (NULL_TREE, double_type_node,
+                             endlink));
+
+  custom_idd
+      = build_function_type (integer_type_node,
+                             tree_cons (NULL_TREE, double_type_node,
+                             tree_cons (NULL_TREE, double_type_node,
+                             endlink)));
+
+  custom_siz
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink));
+
+  custom_suz
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, unsigned_type_node,
+                             endlink));
+
+  custom_diz
+      = build_function_type (double_type_node,
+                             tree_cons (NULL_TREE, integer_type_node,
+                             endlink));
+
+  custom_duz
+      = build_function_type (double_type_node,
+                             tree_cons (NULL_TREE, unsigned_type_node,
+                             endlink));
+
+  custom_isz
+      = build_function_type (integer_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink));
+
+  custom_usz
+      = build_function_type (unsigned_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink));
+
+  custom_idz
+      = build_function_type (integer_type_node,
+                             tree_cons (NULL_TREE, double_type_node,
+                             endlink));
+
+  custom_udz
+      = build_function_type (unsigned_type_node,
+                             tree_cons (NULL_TREE, double_type_node,
+                             endlink));
+
+  custom_dsz
+      = build_function_type (double_type_node,
+                             tree_cons (NULL_TREE, float_type_node,
+                             endlink));
+
+  custom_sdz
+      = build_function_type (float_type_node,
+                             tree_cons (NULL_TREE, double_type_node,
+                             endlink));
+
+
+  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)
+      {
+        if (d->code > NIOS2_FIRST_FPU_INSN && d->code < NIOS2_LAST_FPU_INSN)
+          {
+            nios2_fpu_info *inf = &nios2_fpu_insns[d->code -
+					           (NIOS2_FIRST_FPU_INSN + 1)];
+            const struct insn_data *idata = &insn_data[d->icode];
+            if (inf->N < 0)
+              fatal_error ("Cannot call `%s' without specifying switch"
+			   " `-mcustom-%s'",
+                           d->name,
+                           inf->option);
+            if (inf->args[0] != 'z'
+                && (!target
+                    || !(idata->operand[0].predicate) (target,
+                                                       idata->operand[0].mode)))
+              target = gen_reg_rtx (idata->operand[0].mode);
+          }
+        return (d->expander) (d, exp, target, subtarget, mode, ignore);
+      }
+
+  /* We should have seen one of the functins we registered.  */
+  gcc_unreachable ();
+}
+
+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);
+
+  if (!(*insn_data[d->icode].operand[op].predicate) (opcode, mode))
+    error ("Custom instruction opcode must be compile time constant in the "
+	   "range 0-255 for %s", d->name);
+
+  builtin_custom_seen[INTVAL (opcode)] = d->name;
+  nios2_custom_check_insns (0);
+  return opcode;
+}
+
+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);
+
+  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.  */
+  gcc_assert (insn_data[d->icode].n_operands == 1);
+
+  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.  */
+  gcc_assert (insn_data[d->icode].n_operands == 2);
+
+  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.  */
+  gcc_assert (insn_data[d->icode].n_operands == 2);
+
+  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.  */
+  gcc_assert (insn_data[d->icode].n_operands == 3);
+
+  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.  */
+  gcc_assert (insn_data[d->icode].n_operands == 3);
+
+  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.  */
+  gcc_assert (insn_data[d->icode].n_operands == 4);
+
+  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.  */
+  gcc_assert (insn_data[icode].n_operands == 2);
+
+  /* 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 = 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);
+
+    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.  */
+  gcc_assert (insn_data[icode].n_operands == 2);
+
+  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 = 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.  */
+  gcc_assert (insn_data[icode].n_operands == 2);
+
+  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);
+
+    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.  */
+  gcc_assert (insn_data[icode].n_operands == 2);
+
+  /* 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);
+
+    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);
+
+    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;
+}
+
+static rtx
+nios2_extract_double (const struct insn_data *idata, tree arglist, int index)
+{
+  rtx arg;
+
+  while (index--)
+    arglist = TREE_CHAIN (arglist);
+  arg = expand_expr (TREE_VALUE (arglist), NULL_RTX, DFmode, 0);
+  if (!(*(idata->operand[index+1].predicate)) (arg, DFmode))
+    arg = copy_to_mode_reg (DFmode, arg);
+  return arg;
+}
+
+static rtx
+nios2_extract_float (const struct insn_data *idata, tree arglist, int index)
+{
+  rtx arg;
+
+  while (index--)
+    arglist = TREE_CHAIN (arglist);
+  arg = expand_expr (TREE_VALUE (arglist), NULL_RTX, SFmode, 0);
+  if (!(*(idata->operand[index+1].predicate)) (arg, SFmode))
+    arg = copy_to_mode_reg (SFmode, arg);
+  return arg;
+}
+
+static rtx
+nios2_extract_integer (const struct insn_data *idata, tree arglist, int index)
+{
+  rtx arg;
+
+  while (index--)
+    arglist = TREE_CHAIN (arglist);
+  arg = expand_expr (TREE_VALUE (arglist), NULL_RTX, SImode, 0);
+  if (!(*(idata->operand[index+1].predicate)) (arg, SImode))
+    arg = copy_to_mode_reg (SImode, arg);
+  return arg;
+}
+
+static rtx
+nios2_expand_custom_zdz (const struct builtin_description *d,
+                         tree exp,
+                         rtx target ATTRIBUTE_UNUSED,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (nios2_extract_double (&insn_data[d->icode],
+                                                      arglist, 0));
+  if (pat)
+    emit_insn (pat);
+  return 0;
+}
+
+static rtx
+nios2_expand_custom_zsz (const struct builtin_description *d,
+                         tree exp,
+                         rtx target ATTRIBUTE_UNUSED,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (nios2_extract_float (&insn_data[d->icode],
+                                                     arglist, 0));
+  if (pat)
+    emit_insn (pat);
+  return 0;
+}
+
+static rtx
+nios2_expand_custom_szz (const struct builtin_description *d,
+                         tree exp ATTRIBUTE_UNUSED,
+                         rtx target,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  rtx pat = GEN_FCN (d->icode) (target);
+  if (pat)
+    emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_sss (const struct builtin_description *d,
+                         tree exp,
+                         rtx target,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (target,
+                                nios2_extract_float (&insn_data[d->icode],
+                                                     arglist, 0),
+                                nios2_extract_float (&insn_data[d->icode],
+                                                     arglist, 1));
+  if (pat)
+    emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_ssz (const struct builtin_description *d,
+                         tree exp,
+                         rtx target,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (target,
+                                nios2_extract_float (&insn_data[d->icode],
+                                                     arglist, 0));
+  if (pat)
+    emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_iss (const struct builtin_description *d,
+                         tree exp,
+                         rtx target,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (target,
+                                nios2_extract_float (&insn_data[d->icode],
+                                                     arglist, 0),
+                                nios2_extract_float (&insn_data[d->icode],
+                                                     arglist, 1));
+  if (pat)
+    emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_ddd (const struct builtin_description *d,
+                         tree exp,
+                         rtx target,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (target,
+                                nios2_extract_double (&insn_data[d->icode],
+                                                      arglist, 0),
+                                nios2_extract_double (&insn_data[d->icode],
+                                                      arglist, 1));
+  if (pat)
+    emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_ddz (const struct builtin_description *d,
+                         tree exp,
+                         rtx target,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (target,
+                                nios2_extract_double (&insn_data[d->icode],
+                                                      arglist, 0));
+  if (pat)
+    emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_idd (const struct builtin_description *d,
+                         tree exp,
+                         rtx target,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (target,
+                                nios2_extract_double (&insn_data[d->icode],
+                                                      arglist, 0),
+                                nios2_extract_double (&insn_data[d->icode],
+                                                      arglist, 1));
+  if (pat)
+    emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_siz (const struct builtin_description *d,
+                         tree exp,
+                         rtx target,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (target,
+                                nios2_extract_integer (&insn_data[d->icode],
+                                                       arglist, 0));
+  if (pat)
+    emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_suz (const struct builtin_description *d,
+                         tree exp,
+                         rtx target,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (target,
+                                nios2_extract_integer (&insn_data[d->icode],
+                                                       arglist, 0));
+  if (pat)
+    emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_diz (const struct builtin_description *d,
+                         tree exp,
+                         rtx target,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (target,
+                                nios2_extract_integer (&insn_data[d->icode],
+                                                       arglist, 0));
+  if (pat)
+    emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_duz (const struct builtin_description *d,
+                         tree exp,
+                         rtx target,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (target,
+                                nios2_extract_integer (&insn_data[d->icode],
+                                                       arglist, 0));
+  if (pat)
+    emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_isz (const struct builtin_description *d,
+                         tree exp,
+                         rtx target,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (target,
+                                nios2_extract_float (&insn_data[d->icode],
+                                                     arglist, 0));
+  if (pat)
+    emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_usz (const struct builtin_description *d,
+                         tree exp,
+                         rtx target,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (target,
+                                nios2_extract_float (&insn_data[d->icode],
+                                                     arglist, 0));
+  if (pat)
+    emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_idz (const struct builtin_description *d,
+                         tree exp,
+                         rtx target,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (target,
+                                nios2_extract_double (&insn_data[d->icode],
+                                                      arglist, 0));
+  if (pat)
+    emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_udz (const struct builtin_description *d,
+                         tree exp,
+                         rtx target,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (target,
+                                nios2_extract_double (&insn_data[d->icode],
+                                                      arglist, 0));
+  if (pat)
+    emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_dsz (const struct builtin_description *d,
+                         tree exp,
+                         rtx target,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (target,
+                                nios2_extract_float (&insn_data[d->icode],
+                                                     arglist, 0));
+  if (pat)
+    emit_insn (pat);
+  return target;
+}
+
+static rtx
+nios2_expand_custom_sdz (const struct builtin_description *d,
+                         tree exp,
+                         rtx target,
+                         rtx subtarget ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED,
+                         int ignore ATTRIBUTE_UNUSED)
+{
+  tree arglist = TREE_OPERAND (exp, 1);
+  rtx pat = GEN_FCN (d->icode) (target,
+                                nios2_extract_double (&insn_data[d->icode],
+                                                      arglist, 0));
+  if (pat)
+    emit_insn (pat);
+  return target;
+}
+
+#include "gt-nios2.h"
+
Index: gcc-4.1.2/gcc/config/nios2/nios2.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-4.1.2/gcc/config/nios2/nios2.h	2010-06-30 08:50:26.000000000 +0200
@@ -0,0 +1,1064 @@
+/* NOT ASSIGNED TO FSF.  COPYRIGHT ALTERA.  */
+/* Definitions of target machine for Altera NIOS 2G NIOS2 version.
+   Copyright (C) 2007 Altera
+   Contributed by Jonah Graham (jgraham@altera.com),
+   Will Reece (wreece@altera.com), and Jeff DaSilva (jdasilva@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");                 \
+      if (TARGET_BIG_ENDIAN)                        \
+        builtin_define_std ("nios2_big_endian");    \
+      else                                          \
+        builtin_define_std ("nios2_little_endian"); \
+    }                                               \
+  while (0)
+#define TARGET_VERSION fprintf (stderr, " (Altera Nios II)")
+
+
+
+
+
+/*********************************
+ * Run-time Target Specification
+ *********************************/
+
+extern int target_flags;
+
+/*
+ * There's a lot of error-prone tedium with all the different
+ * custom floating point instructions.  Try to automate it a bit
+ * to make it easier to deal with.
+ */
+#define NIOS2_STRINGIFY_INNER(x) #x
+#define NIOS2_STRINGIFY(x) NIOS2_STRINGIFY_INNER(x)
+#define NIOS2_CONCAT_INNER(x, y) x ## y
+#define NIOS2_CONCAT(x, y) NIOS2_CONCAT_INNER (x, y)
+
+#define NIOS2_FOR_ALL_FPU_INSNS \
+  NIOS2_FPU_INSN (fwrx,     nios2_fwrx,    zdz) \
+  NIOS2_FPU_INSN (fwry,     nios2_fwry,    zsz) \
+  NIOS2_FPU_INSN (frdxlo,   nios2_frdxlo,  szz) \
+  NIOS2_FPU_INSN (frdxhi,   nios2_frdxhi,  szz) \
+  NIOS2_FPU_INSN (frdy,     nios2_frdy,    szz) \
+\
+  NIOS2_FPU_INSN (fadds,    addsf3,        sss) \
+  NIOS2_FPU_INSN (fsubs,    subsf3,        sss) \
+  NIOS2_FPU_INSN (fmuls,    mulsf3,        sss) \
+  NIOS2_FPU_INSN (fdivs,    divsf3,        sss) \
+  NIOS2_FPU_INSN (fmins,    minsf3,        sss) \
+  NIOS2_FPU_INSN (fmaxs,    maxsf3,        sss) \
+  NIOS2_FPU_INSN (fnegs,    negsf2,        ssz) \
+  NIOS2_FPU_INSN (fabss,    abssf2,        ssz) \
+  NIOS2_FPU_INSN (fsqrts,   sqrtsf2,       ssz) \
+  NIOS2_FPU_INSN (fcoss,    cossf2,        ssz) \
+  NIOS2_FPU_INSN (fsins,    sinsf2,        ssz) \
+  NIOS2_FPU_INSN (ftans,    tansf2,        ssz) \
+  NIOS2_FPU_INSN (fatans,   atansf2,       ssz) \
+  NIOS2_FPU_INSN (fexps,    expsf2,        ssz) \
+  NIOS2_FPU_INSN (flogs,    logsf2,        ssz) \
+  NIOS2_FPU_INSN (fcmplts,  nios2_sltsf,   iss) \
+  NIOS2_FPU_INSN (fcmples,  nios2_slesf,   iss) \
+  NIOS2_FPU_INSN (fcmpgts,  nios2_sgtsf,   iss) \
+  NIOS2_FPU_INSN (fcmpges,  nios2_sgesf,   iss) \
+  NIOS2_FPU_INSN (fcmpeqs,  nios2_seqsf,   iss) \
+  NIOS2_FPU_INSN (fcmpnes,  nios2_snesf,   iss) \
+\
+  NIOS2_FPU_INSN (faddd,    adddf3,        ddd) \
+  NIOS2_FPU_INSN (fsubd,    subdf3,        ddd) \
+  NIOS2_FPU_INSN (fmuld,    muldf3,        ddd) \
+  NIOS2_FPU_INSN (fdivd,    divdf3,        ddd) \
+  NIOS2_FPU_INSN (fmind,    mindf3,        ddd) \
+  NIOS2_FPU_INSN (fmaxd,    maxdf3,        ddd) \
+  NIOS2_FPU_INSN (fnegd,    negdf2,        ddz) \
+  NIOS2_FPU_INSN (fabsd,    absdf2,        ddz) \
+  NIOS2_FPU_INSN (fsqrtd,   sqrtdf2,       ddz) \
+  NIOS2_FPU_INSN (fcosd,    cosdf2,        ddz) \
+  NIOS2_FPU_INSN (fsind,    sindf2,        ddz) \
+  NIOS2_FPU_INSN (ftand,    tandf2,        ddz) \
+  NIOS2_FPU_INSN (fatand,   atandf2,       ddz) \
+  NIOS2_FPU_INSN (fexpd,    expdf2,        ddz) \
+  NIOS2_FPU_INSN (flogd,    logdf2,        ddz) \
+  NIOS2_FPU_INSN (fcmpltd,  nios2_sltdf,   idd) \
+  NIOS2_FPU_INSN (fcmpled,  nios2_sledf,   idd) \
+  NIOS2_FPU_INSN (fcmpgtd,  nios2_sgtdf,   idd) \
+  NIOS2_FPU_INSN (fcmpged,  nios2_sgedf,   idd) \
+  NIOS2_FPU_INSN (fcmpeqd,  nios2_seqdf,   idd) \
+  NIOS2_FPU_INSN (fcmpned,  nios2_snedf,   idd) \
+\
+  NIOS2_FPU_INSN (floatis,  floatsisf2,    siz) \
+  NIOS2_FPU_INSN (floatus,  floatunssisf2, suz) \
+  NIOS2_FPU_INSN (floatid,  floatsidf2,    diz) \
+  NIOS2_FPU_INSN (floatud,  floatunssidf2, duz) \
+  NIOS2_FPU_INSN (fixsi,    fixsfsi2,      isz) \
+  NIOS2_FPU_INSN (fixsu,    fixunssfsi2,   usz) \
+  NIOS2_FPU_INSN (fixdi,    fixdfsi2,      idz) \
+  NIOS2_FPU_INSN (fixdu,    fixunsdfsi2,   udz) \
+  NIOS2_FPU_INSN (fextsd,   extendsfdf2,   dsz) \
+  NIOS2_FPU_INSN (ftruncds, truncdfsf2,    sdz)
+
+enum
+{
+#define NIOS2_FPU_INSN(opt, insn, args) \
+  NIOS2_CONCAT (nios2_fpu_, insn),
+NIOS2_FOR_ALL_FPU_INSNS
+  nios2_fpu_max_insn
+};
+
+struct cpp_reader;
+typedef const char * (*nios2_outputfn) (rtx);
+typedef void (*nios2_pragmafn) (struct cpp_reader *);
+
+typedef struct
+{
+  const char *option;      /* name of switch, e.g. fadds */
+  const char *insnnm;      /* name of gcc insn, e.g. addsf3 */
+  const char *args;        /* args to gcc insn, e.g. sss */
+  int N;                   /* value of switch as an integer, -1 = not used */
+  nios2_outputfn output;   /* output function for use in .md file */
+  const char *pname;       /* name of corresponding #pragma custom- */
+  nios2_pragmafn pragma;   /* pragma function for register_target_pragmas */
+  const char *nopname;     /* name of corresponding #pragma no-custom- */
+  nios2_pragmafn nopragma; /* pragma function for register_target_pragmas */
+  int is_double;           /* does this insn have any double operands */
+  int needed_by_double;    /* is this insn needed if doubles are used? */
+  int needs_unsafe;        /* does this insn require
+                              -funsafe-math-optimizations to work? */
+  int needs_finite;        /* does this insn require
+                              -ffinite-math-only to work? */
+  int pragma_seen;         /* have we seen the corresponding #pragma? */
+  int* pN;                 /* pointer to the value as set by the option
+			      parser.  */
+} nios2_fpu_info;
+
+extern nios2_fpu_info nios2_fpu_insns[nios2_fpu_max_insn];
+extern const char *nios2_custom_fpu_cfg_string;
+
+#undef NIOS2_FPU_INSN
+#define NIOS2_FPU_INSN(opt, insn, args) \
+  extern int NIOS2_CONCAT (nios2_custom_, opt);
+NIOS2_FOR_ALL_FPU_INSNS
+
+/* We're little endian, unless otherwise specified by defining BIG_ENDIAN_FLAG
+*/
+#ifndef TARGET_ENDIAN_DEFAULT
+# define TARGET_ENDIAN_DEFAULT 0
+#endif
+
+/* Default target_flags if no switches specified.  */
+#ifndef TARGET_DEFAULT
+# define TARGET_DEFAULT (MASK_HAS_MUL | \
+			 TARGET_ENDIAN_DEFAULT)
+#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*} %{EB:-meb} %{EL:-mel} %{EB:%{EL:%emay not use both -EB and -EL}}"
+
+#if TARGET_ENDIAN_DEFAULT == 0
+# define ASM_SPEC "\
+%{!EB:%{!meb:-EL}} %{EB|meb:-EB}"
+# define LINK_SPEC_ENDIAN "\
+%{!EB:%{!meb:-EL}} %{EB|meb:-EB}"
+# define MULTILIB_DEFAULTS { "EL" }
+#else
+# define ASM_SPEC "\
+%{!EL:%{!mel:-EB}} %{EL|mel:-EL}"
+# define LINK_SPEC_ENDIAN "\
+%{!EL:%{!mel:-EB}} %{EL|mel:-EL}"
+# define MULTILIB_DEFAULTS { "EB" }
+#endif
+
+#define LINK_SPEC LINK_SPEC_ENDIAN \
+  " %{shared:-shared} \
+    %{static:-Bstatic}"
+
+#undef LIB_SPEC
+#define LIB_SPEC \
+"--start-group -lc -lgcc \
+ -lnosys -lstack \
+ --end-group \
+"
+
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC  \
+"crt0%O%s"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ ""
+
+
+/***********************
+ * Storage Layout
+ ***********************/
+
+#define DEFAULT_SIGNED_CHAR 1
+#define BITS_BIG_ENDIAN 0
+#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
+#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
+#if defined(__nios2_big_endian__)
+#define LIBGCC2_WORDS_BIG_ENDIAN 1
+#else
+#define LIBGCC2_WORDS_BIG_ENDIAN 0
+#endif
+#define BITS_PER_UNIT 8
+#define BITS_PER_WORD 32
+#define UNITS_PER_WORD 4
+#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 CMP_DI is unused.  CMP_SF and CMP_DF are only used if
+   the corresponding -mcustom-<opcode> switches are present. */
+enum cmp_type {
+  CMP_SI,                               /* compare four byte integers */
+  CMP_DI,                               /* compare eight byte integers */
+  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
+21    r21 sc    Static Chain (Callee Saved)
+                ??? Does $sc want to be caller or callee
+                saved. If caller, 15, else 21.
+22    r22       Global Offset Table pointer
+23    r23       Thread pointer
+24    r24 et    Exception Temporary
+25    r25 bt    Breakpoint Temporary
+26    r26 gp    Global Pointer
+27    r27 sp    Stack Pointer
+28    r28 fp    Frame Pointer
+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    fake_fp  Fake Frame Pointer which will always be eliminated.
+39    fake_ap  Fake Argument Pointer which will always be eliminated.
+
+40             First Pseudo Register
+
+
+The definitions for all the hard register numbers
+are located in nios2.md.
+*/
+
+#define ET_REGNO (24)
+#define GP_REGNO (26)
+#define SP_REGNO (27)
+#define FP_REGNO (28)
+#define EA_REGNO (29)
+#define RA_REGNO (31)
+#define FIRST_RETVAL_REGNO (2)
+#define LAST_RETVAL_REGNO (3)
+#define FIRST_ARG_REGNO (4)
+#define LAST_ARG_REGNO (7)
+#define SC_REGNO (21)
+#define PC_REGNO (37)
+#define FAKE_FP_REGNO (38)
+#define FAKE_AP_REGNO (39)
+
+#define FIRST_PSEUDO_REGISTER 40
+#define NUM_ARG_REGS (LAST_ARG_REGNO - FIRST_ARG_REGNO + 1)
+
+
+
+#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, 1, 1, 1, 1, 1, 1, 0, 1,     \
+/*  30 */  1, 0, 1, 1, 1, 1, 1, 1, 1, 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, 1, 1, 1, 1, 1, 1, 0, 1,     \
+/*  30 */  1, 0, 1, 1, 1, 1, 1, 1, 1, 1,     \
+    }
+
+#define THREAD_POINTER_REGNUM 23
+
+#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,
+    D00_REG,
+    D01_REG,
+    D02_REG,
+    D03_REG,
+    D04_REG,
+    D05_REG,
+    D06_REG,
+    D07_REG,
+    D08_REG,
+    D09_REG,
+    D10_REG,
+    D11_REG,
+    D12_REG,
+    D13_REG,
+    D14_REG,
+    D15_REG,
+    D16_REG,
+    D17_REG,
+    D18_REG,
+    D19_REG,
+    D20_REG,
+    D21_REG,
+    D22_REG,
+    D23_REG,
+    D24_REG,
+    D25_REG,
+    D26_REG,
+    D27_REG,
+    D28_REG,
+    D29_REG,
+    D30_REG,
+    D31_REG,
+    SIB_REGS,
+    GP_REGS,
+    ALL_REGS,
+    LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+#define REG_CLASS_NAMES   \
+    {"NO_REGS",           \
+     "D00_REG",           \
+     "D01_REG",           \
+     "D02_REG",           \
+     "D03_REG",           \
+     "D04_REG",           \
+     "D05_REG",           \
+     "D06_REG",           \
+     "D07_REG",           \
+     "D08_REG",           \
+     "D09_REG",           \
+     "D10_REG",           \
+     "D11_REG",           \
+     "D12_REG",           \
+     "D13_REG",           \
+     "D14_REG",           \
+     "D15_REG",           \
+     "D16_REG",           \
+     "D17_REG",           \
+     "D18_REG",           \
+     "D19_REG",           \
+     "D20_REG",           \
+     "D21_REG",           \
+     "D22_REG",           \
+     "D23_REG",           \
+     "D24_REG",           \
+     "D25_REG",           \
+     "D26_REG",           \
+     "D27_REG",           \
+     "D28_REG",           \
+     "D29_REG",           \
+     "D30_REG",           \
+     "D31_REG",           \
+     "SIB_REGS",	  \
+     "GP_REGS",           \
+     "ALL_REGS"}
+
+#define GENERAL_REGS ALL_REGS
+
+#define REG_CLASS_CONTENTS   \
+/* NO_REGS  */       {{ 0, 0},     \
+/* D00_REG  */        { 1 << 0, 0},    \
+/* D01_REG  */        { 1 << 1, 0},    \
+/* D02_REG  */        { 1 << 2, 0},    \
+/* D03_REG  */        { 1 << 3, 0},    \
+/* D04_REG  */        { 1 << 4, 0},    \
+/* D05_REG  */        { 1 << 5, 0},    \
+/* D06_REG  */        { 1 << 6, 0},    \
+/* D07_REG  */        { 1 << 7, 0},    \
+/* D08_REG  */        { 1 << 8, 0},    \
+/* D09_REG  */        { 1 << 9, 0},    \
+/* D10_REG  */        { 1 << 10, 0},    \
+/* D11_REG  */        { 1 << 11, 0},    \
+/* D12_REG  */        { 1 << 12, 0},    \
+/* D13_REG  */        { 1 << 13, 0},    \
+/* D14_REG  */        { 1 << 14, 0},    \
+/* D15_REG  */        { 1 << 15, 0},    \
+/* D16_REG  */        { 1 << 16, 0},    \
+/* D17_REG  */        { 1 << 17, 0},    \
+/* D18_REG  */        { 1 << 18, 0},    \
+/* D19_REG  */        { 1 << 19, 0},    \
+/* D20_REG  */        { 1 << 20, 0},    \
+/* D21_REG  */        { 1 << 21, 0},    \
+/* D22_REG  */        { 1 << 22, 0},    \
+/* D23_REG  */        { 1 << 23, 0},    \
+/* D24_REG  */        { 1 << 24, 0},    \
+/* D25_REG  */        { 1 << 25, 0},    \
+/* D26_REG  */        { 1 << 26, 0},    \
+/* D27_REG  */        { 1 << 27, 0},    \
+/* D28_REG  */        { 1 << 28, 0},    \
+/* D29_REG  */        { 1 << 29, 0},    \
+/* D30_REG  */        { 1 << 30, 0},    \
+/* D31_REG  */        { 1 << 31, 0},    \
+/* SIB_REGS */	      { 0xfe0c, 0}, 	\
+/* GP_REGS  */        {~0, 0},    \
+/* ALL_REGS */        {~0,~0}}    \
+
+#define GP_REGNO_P(REGNO) ((REGNO) < 32)
+#define REGNO_REG_CLASS(REGNO) (GP_REGNO_P (REGNO) ? GP_REGS : ALL_REGS)
+
+#define BASE_REG_CLASS ALL_REGS
+#define INDEX_REG_CLASS ALL_REGS
+
+/* 'r', is handled automatically */
+#define REG_CLASS_FROM_LETTER(C) ((C) == 'j' ? SIB_REGS : NO_REGS)
+
+#define  REG_CLASS_FROM_CONSTRAINT(CHAR, STR) \
+  ((CHAR) == 'j' ? SIB_REGS : 			\
+   reg_class_from_constraint ((CHAR), (STR)))
+
+
+#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))
+
+#define CONSTRAINT_LEN(C, STR) \
+ ((C) == 'D' ? 3 : DEFAULT_CONSTRAINT_LEN ((C), (STR)))
+
+/* 'S' matches immediates which are in small data
+   and therefore can be added to gp to create a
+   32-bit value. */
+#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)
+
+
+/**********************************
+ * 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 0
+#define FIRST_PARM_OFFSET(FUNDECL) 0
+
+/* Before the prologue, RA lives in r31.  */
+#define INCOMING_RETURN_ADDR_RTX  gen_rtx_REG (VOIDmode, RA_REGNO)
+#define RETURN_ADDR_RTX(C,F) nios2_get_return_address (C)
+
+/* -------------------------------------- *
+ * 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
+
+/* The DWARF 2 CFA column which tracks the return address from a
+   signal handler context.  */
+#define SIGNAL_UNWIND_RETURN_COLUMN EA_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
+/* the argumnet pointer needs to always be eliminated
+   so it is set to a fake hard register. */
+#define ARG_POINTER_REGNUM FAKE_AP_REGNO
+
+/* The CFA includes the pretend args */
+#define ARG_POINTER_CFA_OFFSET(FNDECL) \
+  (gcc_assert ((FNDECL) == current_function_decl), \
+   FIRST_PARM_OFFSET (FNDECL) + current_function_pretend_args_size)
+
+/* ----------------------------------------- *
+ * 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},                    \
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},                         \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
+
+#define CAN_ELIMINATE(FROM, TO)  \
+  ((TO) == STACK_POINTER_REGNUM ? ! frame_pointer_needed : 1)
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+        (OFFSET) = nios2_initial_elimination_offset ((FROM), (TO))
+
+/* 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_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_PADDING(MODE, TYPE) \
+  (nios2_function_arg_padding_upward ((MODE), (TYPE)) ? upward : downward)
+
+#define PAD_VARARGS_DOWN \
+  (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
+
+#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
+  (nios2_block_reg_padding_upward ((MODE), (TYPE), (FIRST)) ? upward : \
+   downward)
+
+#define FUNCTION_ARG_REGNO_P(REGNO) \
+    ((REGNO) >= FIRST_ARG_REGNO && (REGNO) <= LAST_ARG_REGNO)
+
+/* ----------------------------- *
+ * Generating Code for Profiling
+ * ----------------------------- */
+
+
+#define PROFILE_BEFORE_PROLOGUE
+#define NO_PROFILE_COUNTERS 1
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+  function_profiler ((FILE), (LABELNO))
+
+/* --------------------------------------- *
+ * Passing Function Arguments on the Stack
+ * --------------------------------------- */
+
+#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)      \
+  do                                                \
+    {                                               \
+      X = nios2_legitimize_address (X, OLDX, MODE); \
+      if (memory_address_p (MODE, X))               \
+        goto WIN;                                   \
+    }                                               \
+  while (0)
+
+#define CONSTANT_ADDRESS_P(X) \
+  (CONSTANT_P (X) && nios2_legitimate_address (X, Pmode, 0))
+
+#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) nios2_legitimate_constant (X)
+
+/* 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.  gp relative access cannot be used in
+   position independent code.  gp relative access cannot be used for externally
+   defined symbols, because the compilation unit which defines the symbol may
+   place it in a section that cannot be reached from gp.  */
+#define SYMBOL_REF_IN_NIOS2_SMALL_DATA_P(RTX) \
+   (!flag_pic && SYMBOL_REF_SMALL_P(RTX) && !SYMBOL_REF_WEAK_DECL_P(RTX) && \
+    !SYMBOL_REF_EXTERNAL_P(RTX) && SYMBOL_REF_TLS_MODEL(RTX)==0)
+
+/*****************
+ * 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
+
+/***************************
+ * Position Independent Code
+ ***************************/
+
+#define PIC_OFFSET_TABLE_REGNUM 22
+
+#define LEGITIMATE_PIC_OPERAND_P(X) nios2_legitimate_pic_operand_p (X)
+
+/*****************************************
+ * 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
+ * -------------- */
+
+/* -------------------------------- *
+ * 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", \
+    "et", \
+    "bt", \
+    "gp", \
+    "sp", \
+    "fp", \
+    "ta", \
+    "ba", \
+    "ra", \
+    "status", \
+    "estatus", \
+    "bstatus", \
+    "ipri", \
+    "ecause", \
+    "pc", \
+    "fake_fp", \
+    "fake_ap", \
+}
+
+#define ADDITIONAL_REGISTER_NAMES       \
+{                                       \
+  {"r0", 0},                            \
+  {"r1", 1},                            \
+  {"r24", 24},                          \
+  {"r25", 25},                          \
+  {"r26", 26},                          \
+  {"r27", 27},                          \
+  {"r28", 28},                          \
+  {"r29", 29},                          \
+  {"r30", 30},                          \
+  {"r31", 31}                           \
+}
+
+
+#define ASM_OUTPUT_OPCODE(STREAM, PTR)\
+   (PTR) = asm_output_opcode (STREAM, PTR)
+
+#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)
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL)\
+do { fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), STREAM); \
+     fprintf (STREAM, ".L%u-.L%u\n", (unsigned) (VALUE), (unsigned) (REL)); \
+   } 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                                                                      \
+{                                                                       \
+  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)
+
+/* Put the jump tables in .text because when using position independent code,
+   Nios II elf has no relocation that can represent arbitrary differences
+   between symbols in different sections.  */
+#define JUMP_TABLES_IN_TEXT_SECTION 1
+
+/* Exception Handling */
+
+/* Describe __builtin_eh_return */
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, LAST_RETVAL_REGNO)
+#define EH_RETURN_DATA_REGNO(N) ((N) <= (LAST_ARG_REGNO - FIRST_ARG_REGNO) \
+				 ? (N) + FIRST_ARG_REGNO : INVALID_REGNUM)
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL)		\
+  (!flag_pic ? DW_EH_PE_sdata4					\
+   /* FIXME: These get expanded to dynamic relocs, which is  wrong  */ \
+   /* : !(GLOBAL) ? DW_EH_PE_pcrel | DW_EH_PE_sdata4	*/	\
+   : DW_EH_PE_aligned)
+
+/***************************
+ * Miscellaneous Parameters
+ ***************************/
+
+#define MOVE_MAX 4
+
+#define STORE_FLAG_VALUE 1
+#define Pmode SImode
+#define FUNCTION_MODE QImode
+
+#define REGISTER_TARGET_PRAGMAS() nios2_register_target_pragmas ()
+
+#define CASE_VECTOR_MODE Pmode
+
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+#define LOAD_EXTEND_OP(MODE) (ZERO_EXTEND)
+
+#define WORD_REGISTER_OPERATIONS
Index: gcc-4.1.2/gcc/config/nios2/nios2.md
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-4.1.2/gcc/config/nios2/nios2.md	2010-06-30 08:50:26.000000000 +0200
@@ -0,0 +1,3012 @@
+;; NOT ASSIGNED TO FSF.  COPYRIGHT ALTERA.
+;;
+;; Machine Description for Altera NIOS 2G NIOS2 version.
+;;    Copyright (C) 2005 Altera
+;;    Contributed by Jonah Graham (jgraham@altera.com) and
+;;      Will Reece (wreece@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.  */
+
+
+
+
+;*****************************************************************************
+;*
+;* constraint strings
+;*
+;*****************************************************************************
+;
+; We use the following constraint letters for constants
+;
+;  I: -32768 to -32767
+;  J: 0 to 65535
+;  K: $nnnn0000 for some nnnn
+;  L: 0 to 31 (for shift counts)
+;  M: 0
+;  N: 0 to 255 (for custom instruction numbers)
+;  O: 0 to 31 (for control register numbers)
+;
+; We use the following built-in register classes:
+;
+;  r: general purpose register (r0..r31)
+;  m: memory operand
+;
+; Plus, we define the following constraint strings:
+;
+;  S: symbol that is in the "small data" area
+;  Dnn: Dnn_REG (just rnn)
+;
+
+
+
+;*****************************************************************************
+;*
+;* constants
+;*
+;*****************************************************************************
+(define_constants [
+  (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)
+  (UNSPEC_TRAP 12)
+  (UNSPEC_STACK_OVERFLOW_DETECT_AND_TRAP 13)
+  (UNSPEC_FCOSS 14)
+  (UNSPEC_FCOSD 15)
+  (UNSPEC_FSINS 16)
+  (UNSPEC_FSIND 17)
+  (UNSPEC_FTANS 18)
+  (UNSPEC_FTAND 19)
+  (UNSPEC_FATANS 20)
+  (UNSPEC_FATAND 21)
+  (UNSPEC_FEXPS 22)
+  (UNSPEC_FEXPD 23)
+  (UNSPEC_FLOGS 24)
+  (UNSPEC_FLOGD 25)
+  (UNSPEC_FWRX 26)
+  (UNSPEC_FWRY 27)
+  (UNSPEC_FRDXLO 28)
+  (UNSPEC_FRDXHI 29)
+  (UNSPEC_FRDY 30)
+  (UNSPEC_LOAD_GOT_REGISTER 31)
+  (UNSPEC_PIC_SYM 32)
+  (UNSPEC_PIC_CALL_SYM 33)
+  (UNSPEC_TLS 34)
+  (UNSPEC_TLS_LDM 35)
+  (UNSPEC_LOAD_TLS_IE 36)
+  (UNSPEC_ADD_TLS_LE 37)
+  (UNSPEC_ADD_TLS_GD 38)
+  (UNSPEC_ADD_TLS_LDM 39)
+  (UNSPEC_ADD_TLS_LDO 40)
+
+  (UNSPEC_EH_RETURN 41)
+
+  ;; Note that values 100..151 are used by custom instructions, see below.
+])
+
+
+
+;*****************************************************************************
+;*
+;* 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)
+    || reg_or_0_operand (operands[1], QImode))"
+  "@
+    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 "reg_or_0_operand"   "rM"))
+   (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)
+    || reg_or_0_operand (operands[1], HImode))"
+  "@
+    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 "reg_or_0_operand"   "rM"))
+   (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)
+    || reg_or_0_operand (operands[1], SImode))"
+  "@
+    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 "reg_or_0_operand"   "rM"))
+   (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" "")))]
+  ""
+{
+})
+
+(define_insn "*extendhisi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))]
+  ""
+  "#")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+        (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
+  "reload_completed"
+  [(set (match_dup 0)
+        (and:SI (match_dup 1) (const_int 65535)))
+   (set (match_dup 0)
+        (xor:SI (match_dup 0) (const_int 32768)))
+   (set (match_dup 0)
+        (plus:SI (match_dup 0) (const_int -32768)))]
+  "operands[1] = gen_lowpart (SImode, operands[1]);")
+
+(define_insn "extendhisi2_internal"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (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" "")))]
+  ""
+{
+})
+
+(define_insn "*extendqihi2"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+        (sign_extend:HI (match_operand:QI 1 "register_operand" "r")))]
+  ""
+  "#")
+
+(define_split
+  [(set (match_operand:HI 0 "register_operand" "")
+        (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
+  "reload_completed"
+  [(set (match_dup 0)
+        (and:SI (match_dup 1) (const_int 255)))
+   (set (match_dup 0)
+        (xor:SI (match_dup 0) (const_int 128)))
+   (set (match_dup 0)
+        (plus:SI (match_dup 0) (const_int -128)))]
+  "operands[0] = gen_lowpart (SImode, operands[0]);
+   operands[1] = gen_lowpart (SImode, operands[1]);")
+
+
+
+(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" "")))]
+  ""
+{
+})
+
+(define_insn "*extendqisi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))]
+  ""
+  "#")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "")
+        (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
+  "reload_completed"
+  [(set (match_dup 0)
+        (and:SI (match_dup 1) (const_int 255)))
+   (set (match_dup 0)
+        (xor:SI (match_dup 0) (const_int 128)))
+   (set (match_dup 0)
+        (plus:SI (match_dup 0) (const_int -128)))]
+  "operands[1] = gen_lowpart (SImode, operands[1]);")
+
+(define_insn "extendqisi2_insn"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (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 "addsf3"
+  [(set (match_operand:SF 0 "register_operand"          "=r")
+        (plus:SF (match_operand:SF 1 "register_operand" "%r")
+                 (match_operand:SF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_addsf3].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_addsf3].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "adddf3"
+  [(set (match_operand:DF 0 "register_operand"          "=r")
+        (plus:DF (match_operand:DF 1 "register_operand" "%r")
+                 (match_operand:DF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_adddf3].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_adddf3].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "subsi3"
+  [(set (match_operand:SI 0 "register_operand"           "=r")
+        (minus:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
+                  (match_operand:SI 2 "register_operand"  "r")))]
+  ""
+  "sub\\t%0, %z1, %2"
+  [(set_attr "type" "alu")])
+
+(define_insn "subsf3"
+  [(set (match_operand:SF 0 "register_operand"          "=r")
+        (minus:SF (match_operand:SF 1 "register_operand" "r")
+                  (match_operand:SF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_subsf3].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_subsf3].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "subdf3"
+  [(set (match_operand:DF 0 "register_operand"          "=r")
+        (minus:DF (match_operand:DF 1 "register_operand" "r")
+                  (match_operand:DF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_subdf3].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_subdf3].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "mulsi3"
+  [(set (match_operand:SI 0 "register_operand"            "=r,r")
+        (mult:SI (match_operand:SI 1 "register_operand"    "r,r")
+                 (match_operand:SI 2 "arith_operand"       "r,I")))]
+  "TARGET_HAS_MUL"
+  "mul%i2\\t%0, %1, %z2"
+  [(set_attr "type" "mul")])
+
+(define_insn "mulsf3"
+  [(set (match_operand:SF 0 "register_operand"          "=r")
+        (mult:SF (match_operand:SF 1 "register_operand" "%r")
+                 (match_operand:SF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_mulsf3].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_mulsf3].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "muldf3"
+  [(set (match_operand:DF 0 "register_operand"          "=r")
+        (mult:DF (match_operand:DF 1 "register_operand" "%r")
+                 (match_operand:DF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_muldf3].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_muldf3].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_expand "divsi3"
+  [(set (match_operand:SI 0 "register_operand"            "=r")
+        (div:SI (match_operand:SI 1 "register_operand"     "r")
+                (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 "divsf3"
+  [(set (match_operand:SF 0 "register_operand"          "=r")
+        (div:SF (match_operand:SF 1 "register_operand" "r")
+                (match_operand:SF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_divsf3].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_divsf3].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "divdf3"
+  [(set (match_operand:DF 0 "register_operand"          "=r")
+        (div:DF (match_operand:DF 1 "register_operand" "r")
+                (match_operand:DF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_divdf3].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_divdf3].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "udivsi3"
+  [(set (match_operand:SI 0 "register_operand"            "=r")
+        (udiv:SI (match_operand:SI 1 "register_operand"     "r")
+                (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_little_endian"
+    [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0)
+          (mult:SI (match_operand:SI 1 "register_operand" "")
+                   (match_operand:SI 2 "register_operand" "")))
+     (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 && !WORDS_BIG_ENDIAN"
+  "")
+
+(define_expand "mulsidi3_big_endian"
+    [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 4)
+          (mult:SI (match_operand:SI 1 "register_operand" "")
+                   (match_operand:SI 2 "register_operand" "")))
+     (set (subreg:SI (match_dup 0) 0)
+          (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
+                                             (sign_extend:DI (match_dup 2)))
+                                    (const_int 32))))]
+  "TARGET_HAS_MULX && WORDS_BIG_ENDIAN"
+  "")
+
+(define_expand "mulsidi3"
+    [(match_operand:DI 0 "register_operand" "")
+     (match_operand:SI 1 "register_operand" "")
+     (match_operand:SI 2 "register_operand" "")]
+  "TARGET_HAS_MULX"
+  {
+    if (WORDS_BIG_ENDIAN)
+    {
+        emit_insn (gen_mulsidi3_big_endian (operands[0],
+                                            operands[1],
+                                            operands[2]));
+    }
+    else
+    {
+        emit_insn (gen_mulsidi3_little_endian (operands[0],
+                                               operands[1],
+                                               operands[2]));
+    }
+    DONE;
+  })
+
+(define_expand "umulsidi3_little_endian"
+    [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0)
+          (mult:SI (match_operand:SI 1 "register_operand" "")
+                   (match_operand:SI 2 "register_operand" "")))
+     (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 && !WORDS_BIG_ENDIAN"
+  "")
+
+(define_expand "umulsidi3_big_endian"
+    [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 4)
+          (mult:SI (match_operand:SI 1 "register_operand" "")
+                   (match_operand:SI 2 "register_operand" "")))
+     (set (subreg:SI (match_dup 0) 0)
+          (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
+                                             (zero_extend:DI (match_dup 2)))
+                                    (const_int 32))))]
+  "TARGET_HAS_MULX && WORDS_BIG_ENDIAN"
+  "")
+
+(define_expand "umulsidi3"
+    [(match_operand:DI 0 "register_operand" "")
+     (match_operand:SI 1 "register_operand" "")
+     (match_operand:SI 2 "register_operand" "")]
+  "TARGET_HAS_MULX"
+  {
+    if (WORDS_BIG_ENDIAN)
+    {
+        emit_insn (gen_umulsidi3_big_endian (operands[0],
+                                             operands[1],
+                                             operands[2]));
+    }
+    else
+    {
+        emit_insn (gen_umulsidi3_little_endian (operands[0],
+                                                operands[1],
+                                                operands[2]));
+    }
+    DONE;
+  })
+
+
+;*****************************************************************************
+;*
+;* 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 "negsf2"
+  [(set (match_operand:SF 0 "register_operand"          "=r")
+        (neg:SF (match_operand:SF 1 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_negsf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_negsf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "negdf2"
+  [(set (match_operand:DF 0 "register_operand"          "=r")
+        (neg:DF (match_operand:DF 1 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_negdf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_negdf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "one_cmplsi2"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+        (not:SI (match_operand:SI 1 "register_operand" "r")))]
+  ""
+{
+  operands[2] = const0_rtx;
+  return "nor\\t%0, %z2, %1";
+}
+  [(set_attr "type" "alu")])
+
+
+;*****************************************************************************
+;*
+;* Miscellaneous floating point
+;*
+;*****************************************************************************
+(define_insn "nios2_fwrx"
+  [(unspec_volatile [(match_operand:DF 0 "register_operand" "r")] UNSPEC_FWRX)]
+  "nios2_fpu_insns[nios2_fpu_nios2_fwrx].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_nios2_fwrx].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "nios2_fwry"
+  [(unspec_volatile [(match_operand:SF 0 "register_operand" "r")] UNSPEC_FWRY)]
+  "nios2_fpu_insns[nios2_fpu_nios2_fwry].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_nios2_fwry].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "nios2_frdxlo"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+        (unspec_volatile:SF [(const_int 0)] UNSPEC_FRDXLO))]
+  "nios2_fpu_insns[nios2_fpu_nios2_frdxlo].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_nios2_frdxlo].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "nios2_frdxhi"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+        (unspec_volatile:SF [(const_int 0)] UNSPEC_FRDXHI))]
+  "nios2_fpu_insns[nios2_fpu_nios2_frdxhi].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_nios2_frdxhi].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "nios2_frdy"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+        (unspec_volatile:SF [(const_int 0)] UNSPEC_FRDY))]
+  "nios2_fpu_insns[nios2_fpu_nios2_frdy].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_nios2_frdy].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "minsf3"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+        (if_then_else:SF (lt:SF (match_operand:SF 1 "register_operand" "%r")
+                                (match_operand:SF 2 "register_operand" "r"))
+          (match_dup 1)
+          (match_dup 2)))]
+  "nios2_fpu_insns[nios2_fpu_minsf3].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_minsf3].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "mindf3"
+  [(set (match_operand:DF 0 "register_operand" "=r")
+        (if_then_else:DF (lt:DF (match_operand:DF 1 "register_operand" "%r")
+                                (match_operand:DF 2 "register_operand" "r"))
+          (match_dup 1)
+          (match_dup 2)))]
+  "nios2_fpu_insns[nios2_fpu_mindf3].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_mindf3].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "maxsf3"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+        (if_then_else:SF (lt:SF (match_operand:SF 1 "register_operand" "%r")
+                                (match_operand:SF 2 "register_operand" "r"))
+          (match_dup 2)
+          (match_dup 1)))]
+  "nios2_fpu_insns[nios2_fpu_maxsf3].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_maxsf3].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "maxdf3"
+  [(set (match_operand:DF 0 "register_operand" "=r")
+        (if_then_else:DF (lt:DF (match_operand:DF 1 "register_operand" "%r")
+                                (match_operand:DF 2 "register_operand" "r"))
+          (match_dup 2)
+          (match_dup 1)))]
+  "nios2_fpu_insns[nios2_fpu_maxdf3].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_maxdf3].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "abssf2"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+        (abs:SF (match_operand:SF 1 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_abssf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_abssf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "absdf2"
+  [(set (match_operand:DF 0 "register_operand" "=r")
+        (abs:DF (match_operand:DF 1 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_absdf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_absdf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "sqrtsf2"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+        (sqrt:SF (match_operand:SF 1 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_sqrtsf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_sqrtsf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "sqrtdf2"
+  [(set (match_operand:DF 0 "register_operand" "=r")
+        (sqrt:DF (match_operand:DF 1 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_sqrtdf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_sqrtdf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "cossf2"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+        (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FCOSS))]
+  "nios2_fpu_insns[nios2_fpu_cossf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_cossf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "cosdf2"
+  [(set (match_operand:DF 0 "register_operand" "=r")
+        (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FCOSD))]
+  "nios2_fpu_insns[nios2_fpu_cosdf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_cosdf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "sinsf2"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+        (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FSINS))]
+  "nios2_fpu_insns[nios2_fpu_sinsf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_sinsf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "sindf2"
+  [(set (match_operand:DF 0 "register_operand" "=r")
+        (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FSIND))]
+  "nios2_fpu_insns[nios2_fpu_sindf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_sindf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "tansf2"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+        (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FTANS))]
+  "nios2_fpu_insns[nios2_fpu_tansf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_tansf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "tandf2"
+  [(set (match_operand:DF 0 "register_operand" "=r")
+        (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FTAND))]
+  "nios2_fpu_insns[nios2_fpu_tandf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_tandf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "atansf2"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+        (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FATANS))]
+  "nios2_fpu_insns[nios2_fpu_atansf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_atansf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "atandf2"
+  [(set (match_operand:DF 0 "register_operand" "=r")
+        (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FATAND))]
+  "nios2_fpu_insns[nios2_fpu_atandf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_atandf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "expsf2"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+        (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FEXPS))]
+  "nios2_fpu_insns[nios2_fpu_expsf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_expsf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "expdf2"
+  [(set (match_operand:DF 0 "register_operand" "=r")
+        (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FEXPD))]
+  "nios2_fpu_insns[nios2_fpu_expdf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_expdf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "logsf2"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+        (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FLOGS))]
+  "nios2_fpu_insns[nios2_fpu_logsf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_logsf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "logdf2"
+  [(set (match_operand:DF 0 "register_operand" "=r")
+        (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FLOGD))]
+  "nios2_fpu_insns[nios2_fpu_logdf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_logdf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+
+;*****************************************************************************
+;*
+;*  Logical Operantions
+;*
+;*****************************************************************************
+
+(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")))]
+  ""
+
+{
+        if( GET_CODE ( operands[2] ) == CONST_INT && INTVAL( operands[2] ) == 1 )
+                return "add\t%0,%1,%1";
+        return "sll%i2\t%0,%1,%z2";
+}
+  [(set_attr "type" "shift")])
+
+(define_insn "ashrsi3"
+  [(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")])
+
+
+
+
+;*****************************************************************************
+;*
+;* Converting between floating point and fixed point
+;*
+;*****************************************************************************
+(define_insn "floatsisf2"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+        (float:SF (match_operand:SI 1 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_floatsisf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_floatsisf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "floatsidf2"
+  [(set (match_operand:DF 0 "register_operand" "=r")
+        (float:DF (match_operand:SI 1 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_floatsidf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_floatsidf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "floatunssisf2"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+        (unsigned_float:SF (match_operand:SI 1 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_floatunssisf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_floatunssisf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "floatunssidf2"
+  [(set (match_operand:DF 0 "register_operand" "=r")
+        (unsigned_float:DF (match_operand:SI 1 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_floatunssidf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_floatunssidf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "fixsfsi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (fix:SI (match_operand:SF 1 "general_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_fixsfsi2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_fixsfsi2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "fixdfsi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (fix:SI (match_operand:DF 1 "general_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_fixdfsi2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_fixdfsi2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "fixunssfsi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (unsigned_fix:SI (match_operand:SF 1 "general_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_fixunssfsi2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_fixunssfsi2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "fixunsdfsi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (unsigned_fix:SI (match_operand:DF 1 "general_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_fixunsdfsi2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_fixunsdfsi2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "extendsfdf2"
+  [(set (match_operand:DF 0 "register_operand" "=r")
+        (float_extend:DF (match_operand:SF 1 "general_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_extendsfdf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_extendsfdf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+(define_insn "truncdfsf2"
+  [(set (match_operand:SF 0 "register_operand" "=r")
+        (float_truncate:SF (match_operand:DF 1 "general_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_truncdfsf2].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_truncdfsf2].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+
+
+
+
+
+
+
+;*****************************************************************************
+;*
+;* Prologue, Epilogue and Return
+;*
+;*****************************************************************************
+
+(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")])
+
+;; This is used in compiling the unwind routines.
+(define_expand "eh_return"
+  [(use (match_operand 0 "general_operand"))]
+  ""
+{
+  if (GET_MODE (operands[0]) != Pmode)
+    operands[0] = convert_to_mode (Pmode, operands[0], 0);
+  emit_insn (gen_eh_set_ra (operands[0]));
+
+  DONE;
+})
+
+;; Clobber the return address on the stack.  We can't expand this
+;; until we know where it will be put in the stack frame.
+
+(define_insn "eh_set_ra"
+  [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
+   (clobber (match_scratch:SI 1 "=&r"))]
+ ""
+  "#")
+
+(define_split
+  [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
+   (clobber (match_scratch 1))]
+  "reload_completed"
+  [(const_int 0)]
+{
+  nios2_set_return_address (operands[0], operands[1]);
+  DONE;
+})
+
+
+;*****************************************************************************
+;*
+;* 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_expand "call"
+  [(parallel [(call (match_operand 0 "" "")
+                    (match_operand 1 "" ""))
+              (clobber (reg:SI 31))])]
+  ""
+  {
+    nios2_adjust_call_address (&XEXP (operands[0], 0));
+  }
+)
+
+(define_expand "call_value"
+  [(parallel [(set (match_operand 0 "" "")
+                   (call (match_operand 1 "" "")
+                         (match_operand 2 "" "")))
+              (clobber (reg:SI 31))])]
+  ""
+  {
+    nios2_adjust_call_address (&XEXP (operands[1], 0));
+  }
+)
+
+(define_insn "*call"
+  [(call (mem:QI (match_operand:SI 0 "call_operand" "i,r"))
+         (match_operand 1 "" ""))
+   (clobber (reg:SI 31))]
+  ""
+  "@
+   call\\t%0
+   callr\\t%0"
+  [(set_attr "type" "control,control")])
+
+(define_insn "*call_value"
+  [(set (match_operand 0 "" "")
+        (call (mem:QI (match_operand:SI 1 "call_operand" "i,r"))
+              (match_operand 2 "" "")))
+   (clobber (reg:SI 31))]
+  ""
+  "@
+   call\\t%1
+   callr\\t%1"
+  [(set_attr "type" "control,control")])
+
+(define_expand "sibcall"
+  [(parallel [(call (match_operand 0 "" "")
+                    (match_operand 1 "" ""))
+              (return)])]
+  ""
+  {
+    nios2_adjust_call_address (&XEXP (operands[0], 0));
+  }
+)
+
+(define_expand "sibcall_value"
+  [(parallel [(set (match_operand 0 "" "")
+                   (call (match_operand 1 "" "")
+                         (match_operand 2 "" "")))
+              (return)])]
+  ""
+  {
+    nios2_adjust_call_address (&XEXP (operands[1], 0));
+  }
+)
+
+(define_insn "*sibcall"
+ [(call (mem:QI (match_operand:SI 0 "call_operand" "i,j"))
+        (match_operand 1 "" ""))
+  (return)]
+  ""
+  "@
+   jmpi\\t%0
+   jmp\\t%0"
+)
+
+(define_insn "*sibcall_value"
+ [(set (match_operand 0 "register_operand" "")
+       (call (mem:QI (match_operand:SI 1 "call_operand" "i,j"))
+             (match_operand 2 "" "")))
+  (return)]
+  ""
+  "@
+   jmpi\\t%1
+   jmp\\t%1"
+)
+
+
+
+
+(define_expand "tablejump"
+  [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
+              (use (label_ref (match_operand 1 "" "")))])]
+  ""
+  {
+    if (flag_pic)
+      {
+        /* Hopefully, CSE will eliminate this copy.  */
+        rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
+        rtx reg2 = gen_reg_rtx (SImode);
+
+        emit_insn (gen_addsi3 (reg2, operands[0], reg1));
+        operands[0] = reg2;
+      }
+  }
+)
+
+(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;
+})
+
+(define_expand "cmpsf"
+  [(set (cc0)
+        (compare:CC (match_operand:SF 0 "register_operand" "")
+                    (match_operand:SF 1 "register_operand" "")))]
+  "(nios2_fpu_insns[nios2_fpu_nios2_sltsf].N >= 0
+   || nios2_fpu_insns[nios2_fpu_nios2_sgtsf].N >= 0)
+   && (nios2_fpu_insns[nios2_fpu_nios2_sgesf].N >= 0
+   || nios2_fpu_insns[nios2_fpu_nios2_slesf].N >= 0)
+   && nios2_fpu_insns[nios2_fpu_nios2_seqsf].N >= 0
+   && nios2_fpu_insns[nios2_fpu_nios2_snesf].N >= 0"
+{
+  branch_cmp[0] = operands[0];
+  branch_cmp[1] = operands[1];
+  branch_type = CMP_SF;
+  DONE;
+})
+
+(define_expand "cmpdf"
+  [(set (cc0)
+        (compare:CC (match_operand:DF 0 "register_operand" "")
+                    (match_operand:DF 1 "register_operand" "")))]
+  "(nios2_fpu_insns[nios2_fpu_nios2_sltdf].N >= 0
+   || nios2_fpu_insns[nios2_fpu_nios2_sgtdf].N >= 0)
+   && (nios2_fpu_insns[nios2_fpu_nios2_sgedf].N >= 0
+   || nios2_fpu_insns[nios2_fpu_nios2_sledf].N >= 0)
+   && nios2_fpu_insns[nios2_fpu_nios2_seqdf].N >= 0
+   && nios2_fpu_insns[nios2_fpu_nios2_snedf].N >= 0"
+{
+  branch_cmp[0] = operands[0];
+  branch_cmp[1] = operands[1];
+  branch_type = CMP_DF;
+  DONE;
+})
+
+
+;*****************************************************************************
+;*
+;* 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 && branch_type != CMP_SF && branch_type != CMP_DF)
+    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_insn "nios2_seqsf"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+        (eq:SI (match_operand:SF 1 "register_operand" "%r")
+               (match_operand:SF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_nios2_seqsf].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_nios2_seqsf].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+
+(define_insn "nios2_seqdf"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+        (eq:SI (match_operand:DF 1 "register_operand" "%r")
+               (match_operand:DF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_nios2_seqdf].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_nios2_seqdf].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+
+(define_expand "sne"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (ne:SI (match_dup 1)
+               (match_dup 2)))]
+  ""
+{
+  if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
+    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_insn "nios2_snesf"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+        (ne:SI (match_operand:SF 1 "register_operand" "%r")
+               (match_operand:SF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_nios2_snesf].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_nios2_snesf].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+
+(define_insn "nios2_snedf"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+        (ne:SI (match_operand:DF 1 "register_operand" "%r")
+               (match_operand:DF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_nios2_snedf].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_nios2_snedf].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+
+(define_expand "sgt"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (gt:SI (match_dup 1)
+               (match_dup 2)))]
+  ""
+{
+  if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
+    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_insn "nios2_sgtsf"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+        (gt:SI (match_operand:SF 1 "register_operand" "r")
+               (match_operand:SF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_nios2_sgtsf].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_nios2_sgtsf].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+
+(define_insn "nios2_sgtdf"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+        (gt:SI (match_operand:DF 1 "register_operand" "r")
+               (match_operand:DF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_nios2_sgtdf].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_nios2_sgtdf].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+
+(define_expand "sge"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (ge:SI (match_dup 1)
+               (match_dup 2)))]
+  ""
+{
+  if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
+    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_insn "nios2_sgesf"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+        (ge:SI (match_operand:SF 1 "register_operand" "r")
+               (match_operand:SF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_nios2_sgesf].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_nios2_sgesf].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+
+(define_insn "nios2_sgedf"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+        (ge:SI (match_operand:DF 1 "register_operand" "r")
+               (match_operand:DF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_nios2_sgedf].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_nios2_sgedf].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+
+(define_expand "sle"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (le:SI (match_dup 1)
+               (match_dup 2)))]
+  ""
+{
+  if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
+    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_insn "nios2_slesf"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+        (le:SI (match_operand:SF 1 "register_operand" "r")
+               (match_operand:SF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_nios2_slesf].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_nios2_slesf].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+
+(define_insn "nios2_sledf"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+        (le:SI (match_operand:DF 1 "register_operand" "r")
+               (match_operand:DF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_nios2_sledf].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_nios2_sledf].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+
+(define_expand "slt"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (lt:SI (match_dup 1)
+               (match_dup 2)))]
+  ""
+{
+  if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
+    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_insn "nios2_sltsf"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+        (lt:SI (match_operand:SF 1 "register_operand" "r")
+               (match_operand:SF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_nios2_sltsf].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_nios2_sltsf].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+
+(define_insn "nios2_sltdf"
+  [(set (match_operand:SI 0 "register_operand"        "=r")
+        (lt:SI (match_operand:DF 1 "register_operand" "r")
+               (match_operand:DF 2 "register_operand" "r")))]
+  "nios2_fpu_insns[nios2_fpu_nios2_sltdf].N >= 0"
+  {
+    return (*nios2_fpu_insns[nios2_fpu_nios2_sltdf].output) (insn);
+  }
+  [(set_attr "type" "custom")])
+
+
+(define_expand "sgtu"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (gtu:SI (match_dup 1)
+                (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_insn "nios2_cbranch_sf"
+  [(set (pc)
+        (if_then_else
+         (match_operator:SI 0 "comparison_operator"
+                            [(match_operand:SF 2 "register_operand" "r")
+                             (match_operand:SF 3 "register_operand" "r")])
+        (label_ref (match_operand 1 "" ""))
+        (pc)))]
+  ""
+  {
+    return nios2_output_fpu_insn_cmps (insn, GET_CODE (operands[0]));
+  }
+  [(set_attr "type" "custom")])
+
+
+(define_insn "nios2_cbranch_df"
+  [(set (pc)
+        (if_then_else
+         (match_operator:SI 0 "comparison_operator"
+                            [(match_operand:DF 2 "register_operand" "r")
+                             (match_operand:DF 3 "register_operand" "r")])
+        (label_ref (match_operand 1 "" ""))
+        (pc)))]
+  ""
+  {
+    return nios2_output_fpu_insn_cmpd (insn, GET_CODE (operands[0]));
+  }
+  [(set_attr "type" "custom")])
+
+
+(define_expand "beq"
+  [(set (pc)
+        (if_then_else (eq:CC (cc0)
+                             (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];
+
+  gcc_assert (INTVAL (operands[3]) >= 4);
+
+  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 "reg_or_0_operand" "rM")]
+    UNSPEC_WRCTL)]
+  ""
+  "wrctl\\tctl%0, %z1"
+  [(set_attr "type" "control")])
+
+;Used to signal a stack overflow
+(define_insn "trap"
+  [(unspec_volatile [(const_int 0)] UNSPEC_TRAP)]
+  ""
+  "break\\t3"
+  [(set_attr "type" "control")])
+
+(define_insn "stack_overflow_detect_and_trap"
+  [(unspec_volatile [(const_int 0)] UNSPEC_STACK_OVERFLOW_DETECT_AND_TRAP)]
+  ""
+  "bgeu\\tsp, et, 1f\;break\\t3\;1:"
+  [(set_attr "type" "control")])
+
+;Load the GOT register.
+(define_insn "load_got_register"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+	 (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))
+   (set (match_operand:SI 1 "register_operand" "=r")
+	 (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))]
+  ""
+  "nextpc\\t%0
+\\t1:
+\\tmovhi\\t%1, %%hiadj(_GLOBAL_OFFSET_TABLE_ - 1b)
+\\taddi\\t%1, %1, %%lo(_GLOBAL_OFFSET_TABLE_ - 1b)"
+  [(set_attr "length" "12")])
+
+;; When generating pic, we need to load the symbol offset into a register.
+;; So that the optimizer does not confuse this with a normal symbol load
+;; we use an unspec.  The offset will be loaded from a constant pool entry,
+;; since that is the only type of relocation we can use.
+
+;; The rather odd constraints on the following are to force reload to leave
+;; the insn alone, and to force the minipool generation pass to then move
+;; the GOT symbol to memory.
+
+;; FIXME:these uses look unnecessary.
+(define_insn "pic_load_addr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
+                    (match_operand:SI 2 "" "mX")] UNSPEC_PIC_SYM))
+  (use (match_dup 1))]
+  "flag_pic"
+  "ldw\\t%0, %%got(%2)(%1)")
+
+(define_insn "pic_load_call_addr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
+                    (match_operand:SI 2 "" "mX")] UNSPEC_PIC_CALL_SYM))
+   (use (match_dup 1))]
+  "flag_pic"
+  "ldw\\t%0, %%call(%2)(%1)")
+
+;; TLS support
+
+(define_insn "add_tls_gd"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
+		   (match_operand:SI 2 "" "mX")] UNSPEC_ADD_TLS_GD))]
+  ""
+  "addi\t%0, %1, %%tls_gd(%2)")
+
+(define_insn "load_tls_ie"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
+		    (match_operand:SI 2 "" "mX")] UNSPEC_LOAD_TLS_IE))]
+  ""
+  "ldw\t%0, %%tls_ie(%2)(%1)")
+
+(define_insn "add_tls_ldm"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
+		    (match_operand:SI 2 "" "mX")] UNSPEC_ADD_TLS_LDM))]
+  ""
+  "addi\t%0, %1, %%tls_ldm(%2)")
+
+(define_insn "add_tls_ldo"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
+		    (match_operand:SI 2 "" "mX")] UNSPEC_ADD_TLS_LDO))]
+  ""
+  "addi\t%0, %1, %%tls_ldo(%2)")
+
+(define_insn "add_tls_le"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
+		    (match_operand:SI 2 "" "mX")] UNSPEC_ADD_TLS_LE))]
+  ""
+  "addi\t%0, %1, %%tls_le(%2)")
+
+
+;*****************************************************************************
+;*
+;* Peepholes
+;*
+;*****************************************************************************
+
+
+;; Local Variables:
+;; mode: lisp
+;; End:
Index: gcc-4.1.2/gcc/config/nios2/nios2.opt
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-4.1.2/gcc/config/nios2/nios2.opt	2010-06-30 08:50:26.000000000 +0200
@@ -0,0 +1,519 @@
+; NOT ASSIGNED TO FSF.  COPYRIGHT ALTERA.
+; Options for the Nios II port of the compiler.
+
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING.  If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+mhw-div
+Target Report Mask(HAS_DIV)
+Enable DIV, DIVU
+
+mhw-mul
+Target Report Mask(HAS_MUL)
+Enable MUL instructions
+
+mhw-mulx
+Target Report Mask(HAS_MULX)
+Enable MULX instructions, assume fast shifter
+
+mfast-sw-div
+Target Report Mask(FAST_SW_DIV)
+Use table based fast divide (default at -O3)
+
+minline-memory
+Target Report Mask(INLINE_MEMCPY)
+Inline small memcpy (default when optimizing)
+
+mbypass-cache
+Target Report Mask(BYPASS_CACHE)
+All ld/st instructions use io variants
+
+mstack-check
+Target Report Mask(STACK_CHECK)
+Enable stack limit checking
+
+mreverse-bitfields
+Target Report Mask(REVERSE_BITFIELDS)
+Reverse the order of bitfields in a struct
+
+meb
+Target Report RejectNegative Mask(BIG_ENDIAN)
+Use big-endian byte order
+
+mel
+Target Report RejectNegative InverseMask(BIG_ENDIAN)
+Use little-endian byte order
+
+mcustom-fpu-cfg=
+Target RejectNegative Joined Var(nios2_custom_fpu_cfg_string) VarExists
+Floating point custom instruction configuration name
+
+mno-custom-ftruncds
+Target Report RejectNegative Var(nios2_custom_ftruncds, -1) VarExists
+Do not use the ftruncds custom instruction
+
+mcustom-ftruncds=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_ftruncds) VarExists
+Integer id (N) of ftruncds custom instruction
+
+mno-custom-fextsd
+Target Report RejectNegative Var(nios2_custom_fextsd, -1) VarExists
+Do not use the fextsd custom instruction
+
+mcustom-fextsd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fextsd) VarExists
+Integer id (N) of fextsd custom instruction
+
+mno-custom-fixdu
+Target Report RejectNegative Var(nios2_custom_fixdu, -1) VarExists
+Do not use the fixdu custom instruction
+
+mcustom-fixdu=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fixdu) VarExists
+Integer id (N) of fixdu custom instruction
+
+mno-custom-fixdi
+Target Report RejectNegative Var(nios2_custom_fixdi, -1) VarExists
+Do not use the fixdi custom instruction
+
+mcustom-fixdi=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fixdi) VarExists
+Integer id (N) of fixdi custom instruction
+
+mno-custom-fixsu
+Target Report RejectNegative Var(nios2_custom_fixsu, -1) VarExists
+Do not use the fixsu custom instruction
+
+mcustom-fixsu=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fixsu) VarExists
+Integer id (N) of fixsu custom instruction
+
+mno-custom-fixsi
+Target Report RejectNegative Var(nios2_custom_fixsi, -1) VarExists
+Do not use the fixsi custom instruction
+
+mcustom-fixsi=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fixsi) VarExists
+Integer id (N) of fixsi custom instruction
+
+mno-custom-floatud
+Target Report RejectNegative Var(nios2_custom_floatud, -1) VarExists
+Do not use the floatud custom instruction
+
+mcustom-floatud=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_floatud) VarExists
+Integer id (N) of floatud custom instruction
+
+mno-custom-floatid
+Target Report RejectNegative Var(nios2_custom_floatid, -1) VarExists
+Do not use the floatid custom instruction
+
+mcustom-floatid=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_floatid) VarExists
+Integer id (N) of floatid custom instruction
+
+mno-custom-floatus
+Target Report RejectNegative Var(nios2_custom_floatus, -1) VarExists
+Do not use the floatus custom instruction
+
+mcustom-floatus=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_floatus) VarExists
+Integer id (N) of floatus custom instruction
+
+mno-custom-floatis
+Target Report RejectNegative Var(nios2_custom_floatis, -1) VarExists
+Do not use the floatis custom instruction
+
+mcustom-floatis=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_floatis) VarExists
+Integer id (N) of floatis custom instruction
+
+mno-custom-fcmpned
+Target Report RejectNegative Var(nios2_custom_fcmpned, -1) VarExists
+Do not use the fcmpned custom instruction
+
+mcustom-fcmpned=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpned) VarExists
+Integer id (N) of fcmpned custom instruction
+
+mno-custom-fcmpeqd
+Target Report RejectNegative Var(nios2_custom_fcmpeqd, -1) VarExists
+Do not use the fcmpeqd custom instruction
+
+mcustom-fcmpeqd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpeqd) VarExists
+Integer id (N) of fcmpeqd custom instruction
+
+mno-custom-fcmpged
+Target Report RejectNegative Var(nios2_custom_fcmpged, -1) VarExists
+Do not use the fcmpged custom instruction
+
+mcustom-fcmpged=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpged) VarExists
+Integer id (N) of fcmpged custom instruction
+
+mno-custom-fcmpgtd
+Target Report RejectNegative Var(nios2_custom_fcmpgtd, -1) VarExists
+Do not use the fcmpgtd custom instruction
+
+mcustom-fcmpgtd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpgtd) VarExists
+Integer id (N) of fcmpgtd custom instruction
+
+mno-custom-fcmpled
+Target Report RejectNegative Var(nios2_custom_fcmpled, -1) VarExists
+Do not use the fcmpled custom instruction
+
+mcustom-fcmpled=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpled) VarExists
+Integer id (N) of fcmpled custom instruction
+
+mno-custom-fcmpltd
+Target Report RejectNegative Var(nios2_custom_fcmpltd, -1) VarExists
+Do not use the fcmpltd custom instruction
+
+mcustom-fcmpltd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpltd) VarExists
+Integer id (N) of fcmpltd custom instruction
+
+mno-custom-flogd
+Target Report RejectNegative Var(nios2_custom_flogd, -1) VarExists
+Do not use the flogd custom instruction
+
+mcustom-flogd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_flogd) VarExists
+Integer id (N) of flogd custom instruction
+
+mno-custom-fexpd
+Target Report RejectNegative Var(nios2_custom_fexpd, -1) VarExists
+Do not use the fexpd custom instruction
+
+mcustom-fexpd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fexpd) VarExists
+Integer id (N) of fexpd custom instruction
+
+mno-custom-fatand
+Target Report RejectNegative Var(nios2_custom_fatand, -1) VarExists
+Do not use the fatand custom instruction
+
+mcustom-fatand=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fatand) VarExists
+Integer id (N) of fatand custom instruction
+
+mno-custom-ftand
+Target Report RejectNegative Var(nios2_custom_ftand, -1) VarExists
+Do not use the ftand custom instruction
+
+mcustom-ftand=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_ftand) VarExists
+Integer id (N) of ftand custom instruction
+
+mno-custom-fsind
+Target Report RejectNegative Var(nios2_custom_fsind, -1) VarExists
+Do not use the fsind custom instruction
+
+mcustom-fsind=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsind) VarExists
+Integer id (N) of fsind custom instruction
+
+mno-custom-fcosd
+Target Report RejectNegative Var(nios2_custom_fcosd, -1) VarExists
+Do not use the fcosd custom instruction
+
+mcustom-fcosd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcosd) VarExists
+Integer id (N) of fcosd custom instruction
+
+mno-custom-fsqrtd
+Target Report RejectNegative Var(nios2_custom_fsqrtd, -1) VarExists
+Do not use the fsqrtd custom instruction
+
+mcustom-fsqrtd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsqrtd) VarExists
+Integer id (N) of fsqrtd custom instruction
+
+mno-custom-fabsd
+Target Report RejectNegative Var(nios2_custom_fabsd, -1) VarExists
+Do not use the fabsd custom instruction
+
+mcustom-fabsd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fabsd) VarExists
+Integer id (N) of fabsd custom instruction
+
+mno-custom-fnegd
+Target Report RejectNegative Var(nios2_custom_fnegd, -1) VarExists
+Do not use the fnegd custom instruction
+
+mcustom-fnegd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fnegd) VarExists
+Integer id (N) of fnegd custom instruction
+
+mno-custom-fmaxd
+Target Report RejectNegative Var(nios2_custom_fmaxd, -1) VarExists
+Do not use the fmaxd custom instruction
+
+mcustom-fmaxd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmaxd) VarExists
+Integer id (N) of fmaxd custom instruction
+
+mno-custom-fmind
+Target Report RejectNegative Var(nios2_custom_fmind, -1) VarExists
+Do not use the fmind custom instruction
+
+mcustom-fmind=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmind) VarExists
+Integer id (N) of fmind custom instruction
+
+mno-custom-fdivd
+Target Report RejectNegative Var(nios2_custom_fdivd, -1) VarExists
+Do not use the fdivd custom instruction
+
+mcustom-fdivd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fdivd) VarExists
+Integer id (N) of fdivd custom instruction
+
+mno-custom-fmuld
+Target Report RejectNegative Var(nios2_custom_fmuld, -1) VarExists
+Do not use the fmuld custom instruction
+
+mcustom-fmuld=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmuld) VarExists
+Integer id (N) of fmuld custom instruction
+
+mno-custom-fsubd
+Target Report RejectNegative Var(nios2_custom_fsubd, -1) VarExists
+Do not use the fsubd custom instruction
+
+mcustom-fsubd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsubd) VarExists
+Integer id (N) of fsubd custom instruction
+
+mno-custom-faddd
+Target Report RejectNegative Var(nios2_custom_faddd, -1) VarExists
+Do not use the faddd custom instruction
+
+mcustom-faddd=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_faddd) VarExists
+Integer id (N) of faddd custom instruction
+
+mno-custom-fcmpnes
+Target Report RejectNegative Var(nios2_custom_fcmpnes, -1) VarExists
+Do not use the fcmpnes custom instruction
+
+mcustom-fcmpnes=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpnes) VarExists
+Integer id (N) of fcmpnes custom instruction
+
+mno-custom-fcmpeqs
+Target Report RejectNegative Var(nios2_custom_fcmpeqs, -1) VarExists
+Do not use the fcmpeqs custom instruction
+
+mcustom-fcmpeqs=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpeqs) VarExists
+Integer id (N) of fcmpeqs custom instruction
+
+mno-custom-fcmpges
+Target Report RejectNegative Var(nios2_custom_fcmpges, -1) VarExists
+Do not use the fcmpges custom instruction
+
+mcustom-fcmpges=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpges) VarExists
+Integer id (N) of fcmpges custom instruction
+
+mno-custom-fcmpgts
+Target Report RejectNegative Var(nios2_custom_fcmpgts, -1) VarExists
+Do not use the fcmpgts custom instruction
+
+mcustom-fcmpgts=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmpgts) VarExists
+Integer id (N) of fcmpgts custom instruction
+
+mno-custom-fcmples
+Target Report RejectNegative Var(nios2_custom_fcmples, -1) VarExists
+Do not use the fcmples custom instruction
+
+mcustom-fcmples=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmples) VarExists
+Integer id (N) of fcmples custom instruction
+
+mno-custom-fcmplts
+Target Report RejectNegative Var(nios2_custom_fcmplts, -1) VarExists
+Do not use the fcmplts custom instruction
+
+mcustom-fcmplts=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcmplts) VarExists
+Integer id (N) of fcmplts custom instruction
+
+mno-custom-flogs
+Target Report RejectNegative Var(nios2_custom_flogs, -1) VarExists
+Do not use the flogs custom instruction
+
+mcustom-flogs=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_flogs) VarExists
+Integer id (N) of flogs custom instruction
+
+mno-custom-fexps
+Target Report RejectNegative Var(nios2_custom_fexps, -1) VarExists
+Do not use the fexps custom instruction
+
+mcustom-fexps=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fexps) VarExists
+Integer id (N) of fexps custom instruction
+
+mno-custom-fatans
+Target Report RejectNegative Var(nios2_custom_fatans, -1) VarExists
+Do not use the fatans custom instruction
+
+mcustom-fatans=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fatans) VarExists
+Integer id (N) of fatans custom instruction
+
+mno-custom-ftans
+Target Report RejectNegative Var(nios2_custom_ftans, -1) VarExists
+Do not use the ftans custom instruction
+
+mcustom-ftans=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_ftans) VarExists
+Integer id (N) of ftans custom instruction
+
+mno-custom-fsins
+Target Report RejectNegative Var(nios2_custom_fsins, -1) VarExists
+Do not use the fsins custom instruction
+
+mcustom-fsins=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsins) VarExists
+Integer id (N) of fsins custom instruction
+
+mno-custom-fcoss
+Target Report RejectNegative Var(nios2_custom_fcoss, -1) VarExists
+Do not use the fcoss custom instruction
+
+mcustom-fcoss=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fcoss) VarExists
+Integer id (N) of fcoss custom instruction
+
+mno-custom-fsqrts
+Target Report RejectNegative Var(nios2_custom_fsqrts, -1) VarExists
+Do not use the fsqrts custom instruction
+
+mcustom-fsqrts=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsqrts) VarExists
+Integer id (N) of fsqrts custom instruction
+
+mno-custom-fabss
+Target Report RejectNegative Var(nios2_custom_fabss, -1) VarExists
+Do not use the fabss custom instr
+
+mcustom-fabss=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fabss) VarExists
+Integer id (N) of fabss custom instruction
+
+mno-custom-fnegs
+Target Report RejectNegative Var(nios2_custom_fnegs, -1) VarExists
+Do not use the fnegs custom instruction
+
+mcustom-fnegs=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fnegs) VarExists
+Integer id (N) of fnegs custom instruction
+
+mno-custom-fmaxs
+Target Report RejectNegative Var(nios2_custom_fmaxs, -1) VarExists
+Do not use the fmaxs custom instruction
+
+mcustom-fmaxs=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmaxs) VarExists
+Integer id (N) of fmaxs custom instruction
+
+mno-custom-fmins
+Target Report RejectNegative Var(nios2_custom_fmins, -1) VarExists
+Do not use the fmins custom instruction
+
+mcustom-fmins=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmins) VarExists
+Integer id (N) of fmins custom instruction
+
+mno-custom-fdivs
+Target Report RejectNegative Var(nios2_custom_fdivs, -1) VarExists
+Do not use the fdivs custom instruction
+
+mcustom-fdivs=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fdivs) VarExists
+Integer id (N) of fdivs custom instruction
+
+mno-custom-fmuls
+Target Report RejectNegative Var(nios2_custom_fmuls, -1) VarExists
+Do not use the fmuls custom instruction
+
+mcustom-fmuls=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fmuls) VarExists
+Integer id (N) of fmuls custom instruction
+
+mno-custom-fsubs
+Target Report RejectNegative Var(nios2_custom_fsubs, -1) VarExists
+Do not use the fsubs custom instruction
+
+mcustom-fsubs=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fsubs) VarExists
+Integer id (N) of fsubs custom instruction
+
+mno-custom-fadds
+Target Report RejectNegative Var(nios2_custom_fadds, -1) VarExists
+Do not use the fadds custom instruction
+
+mcustom-fadds=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fadds) VarExists
+Integer id (N) of fadds custom instruction
+
+mno-custom-frdy
+Target Report RejectNegative Var(nios2_custom_frdy, -1) VarExists
+Do not use the frdy custom instruction
+
+mcustom-frdy=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_frdy) VarExists
+Integer id (N) of frdy custom instruction
+
+mno-custom-frdxhi
+Target Report RejectNegative Var(nios2_custom_frdxhi, -1) VarExists
+Do not use the frdxhi custom instruction
+
+mcustom-frdxhi=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_frdxhi) VarExists
+Integer id (N) of frdxhi custom instruction
+
+mno-custom-frdxlo
+Target Report RejectNegative Var(nios2_custom_frdxlo, -1) VarExists
+Do not use the frdxlo custom instruction
+
+mcustom-frdxlo=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_frdxlo) VarExists
+Integer id (N) of frdxlo custom instruction
+
+mno-custom-fwry
+Target Report RejectNegative Var(nios2_custom_fwry, -1) VarExists
+Do not use the fwry custom instruction
+
+mcustom-fwry=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fwry) VarExists
+Integer id (N) of fwry custom instruction
+
+mno-custom-fwrx
+Target Report RejectNegative Var(nios2_custom_fwrx, -1) VarExists
+Do not use the fwrx custom instruction
+
+mcustom-fwrx=
+Target Report RejectNegative Joined UInteger Var(nios2_custom_fwrx) VarExists
+Integer id (N) of fwrx custom instruction
Index: gcc-4.1.2/gcc/config/nios2/t-linux
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-4.1.2/gcc/config/nios2/t-linux	2010-06-30 08:50:26.000000000 +0200
@@ -0,0 +1,9 @@
+# Soft-float functions go in glibc only, to facilitate the possible
+# future addition of exception and rounding mode support integrated
+# with <fenv.h>.
+
+FPBIT=
+DPBIT=
+LIB2FUNCS_EXCLUDE = _floatdidf _floatdisf _fixunsdfsi _fixunssfsi \
+  _fixunsdfdi _fixdfdi _fixunssfdi _fixsfdi _floatundidf _floatundisf
+LIB2FUNCS_EXTRA += $(srcdir)/config/nios2/linux-atomic.c
Index: gcc-4.1.2/gcc/config/nios2/t-nios2
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-4.1.2/gcc/config/nios2/t-nios2	2010-06-30 08:50:26.000000000 +0200
@@ -0,0 +1,176 @@
+##
+## 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=fp-bit.c
+DPBIT=dp-bit.c
+
+TARGET_LIBGCC2_CFLAGS = -O2 -fpic
+
+# FLOAT_ONLY - no doubles
+# SMALL_MACHINE - QI/HI is faster than SI
+#     Actually SMALL_MACHINE uses chars and shorts instead of ints
+#     since ints (16-bit ones as they are today) are at least as fast
+#     as chars and shorts, don't define SMALL_MACHINE
+# CMPtype - type returned by FP compare, i.e. INT (hard coded in fp-bit - see code )
+
+$(FPBIT): $(srcdir)/config/fp-bit.c Makefile
+	echo '#define FLOAT'          >  ${FPBIT}
+	echo '#ifndef __nios2_big_endian__' >> ${FPBIT}
+	echo '#define FLOAT_BIT_ORDER_MISMATCH' >> ${FPBIT}
+	echo '#endif' >> ${FPBIT}
+	cat $(srcdir)/config/fp-bit.c >> ${FPBIT}
+
+$(DPBIT): $(srcdir)/config/fp-bit.c Makefile
+	echo ''          >  ${DPBIT}
+	echo '#ifndef __nios2_big_endian__' >> ${DPBIT}
+	echo '#define FLOAT_BIT_ORDER_MISMATCH' >> ${DPBIT}
+	echo '#endif' >> ${DPBIT}
+	cat $(srcdir)/config/fp-bit.c >> ${DPBIT}
+
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o crtbeginS.o \
+		       crtbeginT.o crtendS.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.
+
+
+## The BUILD_BE_MULTILIB and BUILD_PG_MULTILIB variables allow the
+## makefile user to enable/disable the generation of the precompiled
+## big endian and profiling libraries. By default, the big endian
+## libraries are not created on a windows build and the profiling
+## libraries are not created on a Solaris build. All other library
+## combinations are created by default.
+
+# Uncomment to temporarily avoid building big endian and profiling libraries during a Windows build.
+#ifeq ($(DEV_HOST_OS), win32)
+#BUILD_BE_MULTILIB ?= 0
+#BUILD_PG_MULTILIB ?= 0
+#endif
+
+#By default, avoid building the profiling libraries during a Solaris build.
+ifeq ($(DEV_HOST_OS), solaris)
+BUILD_PG_MULTILIB ?= 0
+endif
+
+BUILD_BE_MULTILIB ?= 0
+BUILD_PG_MULTILIB ?= 1
+BUILD_MULTILIB ?= 0
+
+ifeq ($(BUILD_MULTILIB), 1)
+
+MULTILIB_OPTIONS = mno-hw-mul mhw-mulx mstack-check mcustom-fpu-cfg=60-1 mcustom-fpu-cfg=60-2
+
+#Add the profiling flag to the multilib variable if required
+ifeq ($(BUILD_PG_MULTILIB), 1)
+MULTILIB_OPTIONS += pg
+endif
+
+#Add the big endian flag to the multilib variable if required
+ifeq ($(BUILD_BE_MULTILIB), 1)
+MULTILIB_OPTIONS += EB/EL
+endif
+
+endif
+
+## MULTILIB_DIRNAMES
+## If MULTILIB_OPTIONS is used, this variable specifies the directory names
+## 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.
+
+ifeq ($(BUILD_MULTILIB), 1)
+ifeq ($(BUILD_BE_MULTILIB), 1)
+MULTILIB_MATCHES = EL=mel EB=meb
+endif
+endif
+
+##
+## MULTILIB_EXCEPTIONS
+## Sometimes when there are multiple sets of MULTILIB_OPTIONS being
+## specified, there are combinations that should not be built.  In that
+## case, set MULTILIB_EXCEPTIONS to be all of the switch exceptions in
+## shell case syntax that should not be built.
+## For example, in the PowerPC embedded ABI support, it is not desirable to
+## build libraries compiled with the -mcall-aix option and either of the
+## -fleading-underscore or -mlittle options at the same time.  Therefore
+## MULTILIB_EXCEPTIONS is set to
+##
+## *mcall-aix/*fleading-underscore* *mlittle/*mcall-aix*
+##
+
+ifeq ($(BUILD_MULTILIB), 1)
+MULTILIB_EXCEPTIONS = *mno-hw-mul/*mhw-mulx* *mcustom-fpu-cfg=60-1/*mcustom-fpu-cfg=60-2*
+endif
+
+##
+## MULTILIB_EXTRA_OPTS Sometimes it is desirable that when building
+## multiple versions of libgcc.a certain options should always be passed on
+## to the compiler.  In that case, set MULTILIB_EXTRA_OPTS to be the list
+## of options to be used for all builds.
+##