Patchwork [2/5] Altera Nios II: libgcc

login
register
mail settings
Submitter Chung-Lin Tang
Date April 18, 2013, 1:49 p.m.
Message ID <516FF9D8.80903@codesourcery.com>
Download mbox | patch
Permalink /patch/237642/
State New
Headers show

Comments

Chung-Lin Tang - April 18, 2013, 1:49 p.m.
These are patches for libgcc.

2013-04-18  Sandra Loosemore  <sandra@codesourcery.com>
            Chung-Lin Tang  <cltang@codesourcery.com>
            Based on patches from Altera Corporation

        * config.host (nios2-*-*,nios2-*-linux*): Add nios2 host cases.
        * config/nios2/lib2-nios2.h: New file.
        * config/nios2/lib2-divmod-hi.c: New file.
        * config/nios2/linux-unwind.h: New file.
        * config/nios2/lib2-divmod.c: New file.
        * config/nios2/linux-atomic.c: New file.
        * config/nios2/t-nios2: New file.
        * config/nios2/crti.asm: New file.
        * config/nios2/t-linux: New file.
        * config/nios2/lib2-divtable.c: New file.
        * config/nios2/lib2-mul.c: New file.
        * config/nios2/tramp.c: New file.
        * config/nios2/crtn.asm: New file.
Joseph S. Myers - April 25, 2013, 8 p.m.
On Thu, 18 Apr 2013, Chung-Lin Tang wrote:

> +nios2-*-linux*)
> +	tmake_file="$tmake_file nios2/t-nios2 nios2/t-linux t-libgcc-pic t-slibgcc-libgcc"
> +	extra_parts="$extra_parts crti.o crtn.o"
> +	md_unwind_header=nios2/linux-unwind.h
> +	;;
> +nios2-*-*)
> +	tmake_file="$tmake_file nios2/t-nios2 t-fdpbit"
> +	extra_parts="$extra_parts crti.o crtn.o"
> +	;;

As I understand it, the port uses soft-fp in glibc so doesn't need it in 
libgcc for nios2-*-linux*.  But why use the old fp-bit in libgcc for bare 
metal (use of t-fdpbit here), rather than soft-fp?

> Index: libgcc/config/nios2/lib2-nios2.h
> ===================================================================
> --- libgcc/config/nios2/lib2-nios2.h	(revision 0)
> +++ libgcc/config/nios2/lib2-nios2.h	(revision 409063)
> @@ -0,0 +1,49 @@
> +/* Integer arithmetic support for Altera Nios II.
> +   
> +   Copyright (C) 2012 Free Software Foundation, Inc.

GCC now uses copyright year ranges <year>-2013 everywhere, automatically 
updated in all files at the start of the year.  So a single range 
<year>-2013 should be used in all new files in all patches for this port.

> +/* 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");

Consistently use a space between "asm" and '('; you're missing some here.

> +      if(__builtin_expect (r2 == EFAULT || r2 == ENOSYS,0))

Space between "if" and '('.  You may want to check the patches more 
generally for such missing spaces before '('....

> Index: libgcc/config/nios2/t-nios2
> ===================================================================
> --- libgcc/config/nios2/t-nios2	(revision 0)
> +++ libgcc/config/nios2/t-nios2	(revision 409063)
> @@ -0,0 +1,18 @@
> +LIB2ADD += $(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 \
> +	   $(srcdir)/config/nios2/tramp.c
> +
> +# We have some non *.S named assembly files
> +CUSTOM_CRTIN = yes

But why the special naming?  No other architecture has .asm files in 
libgcc so I think you should just name them *.S and then eliminate special 
rules as far as possible.

> +#ifdef linux

Use __linux__ rather than legacy user-namespace predefines.

> +void __trampoline_setup (unsigned int *addr,

Return type on separate line from function name.

> +			 void *fnptr,
> +			 void *chainptr)
> +{
> +  unsigned int fn = (unsigned int)fnptr;
> +  unsigned int chain = (unsigned int)chainptr;

Missing spaces in casts.

> +	.file	"crtn.asm"

Such .file directives in libgcc assembly sources should generally be 
avoided; see <http://gcc.gnu.org/ml/gcc-patches/2008-07/msg00123.html> for 
rationale.

Patch

Index: libgcc/config.host
===================================================================
--- libgcc/config.host	(revision 407083)
+++ libgcc/config.host	(revision 409063)
@@ -137,6 +137,9 @@ 
 	cpu_type=mips
 	tmake_file=mips/t-mips
 	;;
+nios2*-*-*)
+	cpu_type=nios2
+	;;
 powerpc*-*-*)
 	cpu_type=rs6000
 	;;
@@ -814,6 +817,15 @@ 
 	# Don't use default.
 	extra_parts=
 	;;
+nios2-*-linux*)
+	tmake_file="$tmake_file nios2/t-nios2 nios2/t-linux t-libgcc-pic t-slibgcc-libgcc"
+	extra_parts="$extra_parts crti.o crtn.o"
+	md_unwind_header=nios2/linux-unwind.h
+	;;
+nios2-*-*)
+	tmake_file="$tmake_file nios2/t-nios2 t-fdpbit"
+	extra_parts="$extra_parts crti.o crtn.o"
+	;;
 pdp11-*-*)
 	tmake_file="pdp11/t-pdp11 t-fdpbit"
 	;;
Index: libgcc/config/nios2/lib2-nios2.h
===================================================================
--- libgcc/config/nios2/lib2-nios2.h	(revision 0)
+++ libgcc/config/nios2/lib2-nios2.h	(revision 409063)
@@ -0,0 +1,49 @@ 
+/* Integer arithmetic support for Altera Nios II.
+   
+   Copyright (C) 2012 Free Software Foundation, Inc.
+   Contributed by Altera and Mentor Graphics, Inc.
+
+   This file is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 3, or (at your option) any
+   later version.
+   
+   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.
+   
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+   
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>. */
+
+#ifndef LIB2_NIOS2_H
+#define LIB2_NIOS2_H
+
+/* Types.  */
+
+typedef char QItype __attribute__ ((mode (QI)));
+typedef unsigned char UQItype __attribute__ ((mode (QI)));
+typedef short HItype __attribute__ ((mode (HI)));
+typedef unsigned short UHItype __attribute__ ((mode (HI)));
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef int word_type __attribute__ ((mode (__word__)));
+
+/* Exported functions.  */
+extern SItype __divsi3 (SItype, SItype);
+extern SItype __modsi3 (SItype, SItype);
+extern SItype __udivsi3 (SItype, SItype);
+extern SItype __umodsi3 (SItype, SItype);
+extern HItype __divhi3 (HItype, HItype);
+extern HItype __modhi3 (HItype, HItype);
+extern UHItype __udivhi3 (UHItype, UHItype);
+extern UHItype __umodhi3 (UHItype, UHItype);
+extern SItype __mulsi3 (SItype, SItype);
+
+#endif /* LIB2_NIOS2_H */
Index: libgcc/config/nios2/lib2-divmod-hi.c
===================================================================
--- libgcc/config/nios2/lib2-divmod-hi.c	(revision 0)
+++ libgcc/config/nios2/lib2-divmod-hi.c	(revision 409063)
@@ -0,0 +1,116 @@ 
+/* Copyright (C) 2012 Free Software Foundation, Inc.
+   Contributed by Altera and Mentor Graphics, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "lib2-nios2.h"
+
+/* 16-bit HI divide and modulo as used in Nios II.  */
+
+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: libgcc/config/nios2/linux-unwind.h
===================================================================
--- libgcc/config/nios2/linux-unwind.h	(revision 0)
+++ libgcc/config/nios2/linux-unwind.h	(revision 409063)
@@ -0,0 +1,179 @@ 
+/* DWARF2 EH unwinding support for Nios II Linux.
+   Copyright (C) 2008, 2012 Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#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.
+   The corresponding bits in the Linux kernel are in
+   arch/nios2/kernel/signal.c.  */
+
+#include <signal.h>
+#include <asm/unistd.h>
+
+/* Exactly the same layout as the kernel structures, unique names.  */
+struct nios2_mcontext {
+  int version;
+#ifdef __uClinux__
+  int status_extension;
+#endif
+  int gregs[32];
+};
+
+struct nios2_ucontext {
+  unsigned long uc_flags;
+  struct ucontext *uc_link;
+  stack_t uc_stack;
+  struct nios2_mcontext uc_mcontext;
+  sigset_t uc_sigmask;	/* mask last for extensibility */
+};
+
+#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;
+
+  /* The expected sequence of instructions for regular Linux is:
+       movi r2,(sigreturn/rt_sigreturn)
+       trap
+     On uClinux, we expect:
+       movi r3,(sigreturn/rt_sigreturn)
+       mov r2, r0
+       trap
+     Check for the trap first.  */
+  if (1
+#ifndef __uClinux__
+      && pc[1] != 0x003b683a
+#else
+      && pc[2] != 0x003b683a
+#endif
+      )
+    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 (1
+#ifndef __uClinux__
+      && pc[0] == (0x00800004 | (__NR_sigreturn << 6))
+#else
+      && pc[0] == (0x00c00004 | (__NR_sigreturn << 6))
+      && pc[1] == 0x0005883a
+#endif
+      )
+    {
+      struct sigframe {
+	char retcode[12];
+	unsigned long extramask[1];
+	struct sigcontext sc;
+      } *rt_ = context->ra;
+      struct pt_regs *regs = &rt_->sc.regs;
+
+      /* The CFA is the user's incoming stack pointer value.  */
+      new_cfa = (_Unwind_Ptr)(regs->sp);
+      fs->regs.cfa_how = CFA_REG_OFFSET;
+      fs->regs.cfa_reg = STACK_POINTER_REGNUM;
+      fs->regs.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 (EA_REGNO, ea);
+      
+      fs->retaddr_column = EA_REGNO;
+      fs->signal_frame = 1;
+      
+      return _URC_NO_REASON;
+    }
+  else if (1
+#ifndef __uClinux__
+	   && pc[0] == (0x00800004 | (__NR_rt_sigreturn << 6))
+#else
+	   && pc[0] == (0x00c00004 | (__NR_rt_sigreturn << 6))
+	   && pc[1] == 0x0005883a
+#endif
+	   )
+    {
+      struct rt_sigframe {
+	char retcode[12];
+	siginfo_t info;
+	struct nios2_ucontext uc;
+      } *rt_ = context->ra;
+      struct nios2_mcontext *regs = &rt_->uc.uc_mcontext;
+      int i;
+
+      /* MCONTEXT_VERSION is defined to 2 in the kernel.  */
+      if (regs->version != 2)
+	return _URC_END_OF_STACK;
+
+      /* The CFA is the user's incoming stack pointer value.  */
+      new_cfa = (_Unwind_Ptr)regs->gregs[28];
+      fs->regs.cfa_how = CFA_REG_OFFSET;
+      fs->regs.cfa_reg = STACK_POINTER_REGNUM;
+      fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa;
+
+      /* The sequential registers.  */
+      for (i = 1; i < 24; i++)
+	NIOS2_REG (i, gregs[i-1]);
+      
+      /* The random registers.  The kernel stores these in a funny order
+	 in the gregs array.  */
+      NIOS2_REG (RA_REGNO, gregs[23]);
+      NIOS2_REG (FP_REGNO, gregs[24]);
+      NIOS2_REG (GP_REGNO, gregs[25]);
+      NIOS2_REG (EA_REGNO, gregs[27]);
+      
+      fs->retaddr_column = EA_REGNO;
+      fs->signal_frame = 1;
+      
+      return _URC_NO_REASON;
+    }
+#undef NIOS2_REG
+  return _URC_END_OF_STACK;
+}
+#endif
Index: libgcc/config/nios2/lib2-divmod.c
===================================================================
--- libgcc/config/nios2/lib2-divmod.c	(revision 0)
+++ libgcc/config/nios2/lib2-divmod.c	(revision 409063)
@@ -0,0 +1,116 @@ 
+/* Copyright (C) 2012 Free Software Foundation, Inc.
+   Contributed by Altera and Mentor Graphics, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "lib2-nios2.h"
+
+/* 32-bit SI divide and modulo as used in Nios II.  */
+
+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: libgcc/config/nios2/linux-atomic.c
===================================================================
--- libgcc/config/nios2/linux-atomic.c	(revision 0)
+++ libgcc/config/nios2/linux-atomic.c	(revision 409063)
@@ -0,0 +1,302 @@ 
+/* Linux-specific atomic operations for Nios II Linux.
+   Copyright (C) 2008, 2012 Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#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")))
+
+#ifdef nios2_little_endian
+#define INVERT_MASK_1 0
+#define INVERT_MASK_2 0
+#else
+#define INVERT_MASK_1 24
+#define INVERT_MASK_2 16
+#endif
+
+#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,   , +, unsigned short, 2, oldval)
+SUBWORD_SYNC_OP (sub,   , -, unsigned short, 2, oldval)
+SUBWORD_SYNC_OP (or,    , |, unsigned short, 2, oldval)
+SUBWORD_SYNC_OP (and,   , &, unsigned short, 2, oldval)
+SUBWORD_SYNC_OP (xor,   , ^, unsigned short, 2, oldval)
+SUBWORD_SYNC_OP (nand, ~, &, unsigned short, 2, oldval)
+
+SUBWORD_SYNC_OP (add,   , +, unsigned char, 1, oldval)
+SUBWORD_SYNC_OP (sub,   , -, unsigned char, 1, oldval)
+SUBWORD_SYNC_OP (or,    , |, unsigned char, 1, oldval)
+SUBWORD_SYNC_OP (and,   , &, unsigned char, 1, oldval)
+SUBWORD_SYNC_OP (xor,   , ^, unsigned char, 1, oldval)
+SUBWORD_SYNC_OP (nand, ~, &, unsigned 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,   , +, unsigned short, 2, newval)
+SUBWORD_SYNC_OP (sub,   , -, unsigned short, 2, newval)
+SUBWORD_SYNC_OP (or,    , |, unsigned short, 2, newval)
+SUBWORD_SYNC_OP (and,   , &, unsigned short, 2, newval)
+SUBWORD_SYNC_OP (xor,   , ^, unsigned short, 2, newval)
+SUBWORD_SYNC_OP (nand, ~, &, unsigned short, 2, newval)
+
+SUBWORD_SYNC_OP (add,   , +, unsigned char, 1, newval)
+SUBWORD_SYNC_OP (sub,   , -, unsigned char, 1, newval)
+SUBWORD_SYNC_OP (or,    , |, unsigned char, 1, newval)
+SUBWORD_SYNC_OP (and,   , &, unsigned char, 1, newval)
+SUBWORD_SYNC_OP (xor,   , ^, unsigned char, 1, newval)
+SUBWORD_SYNC_OP (nand, ~, &, unsigned 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 (unsigned short, 2)
+SUBWORD_VAL_CAS (unsigned 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 (unsigned short, 2)
+SUBWORD_BOOL_CAS (unsigned 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 (unsigned short, 2)
+SUBWORD_TEST_AND_SET (unsigned char,  1)
+
+#define SYNC_LOCK_RELEASE(TYPE, WIDTH)					\
+  void HIDDEN								\
+  __sync_lock_release_##WIDTH (TYPE *ptr)				\
+  {									\
+    /* All writes before this point must be seen before we release	\
+       the lock itself.  */						\
+    __builtin_sync ();							\
+    *ptr = 0;								\
+  }
+
+SYNC_LOCK_RELEASE (int,   4)
+SYNC_LOCK_RELEASE (short, 2)
+SYNC_LOCK_RELEASE (char,  1)
Index: libgcc/config/nios2/t-nios2
===================================================================
--- libgcc/config/nios2/t-nios2	(revision 0)
+++ libgcc/config/nios2/t-nios2	(revision 409063)
@@ -0,0 +1,18 @@ 
+LIB2ADD += $(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 \
+	   $(srcdir)/config/nios2/tramp.c
+
+# We have some non *.S named assembly files
+CUSTOM_CRTIN = yes
+
+# 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 
+
Index: libgcc/config/nios2/crti.asm
===================================================================
--- libgcc/config/nios2/crti.asm	(revision 0)
+++ libgcc/config/nios2/crti.asm	(revision 409063)
@@ -0,0 +1,88 @@ 
+/* Copyright (C) 2012 Free Software Foundation, Inc.
+   Contributed by Jonah Graham (jgraham@altera.com).
+   Contributed by Mentor Graphics, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+
+/* 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
+#ifdef linux
+	nextpc	r22
+1:	movhi	r2, %hiadj(_GLOBAL_OFFSET_TABLE_ - 1b)
+	addi	r2, r2, %lo(_GLOBAL_OFFSET_TABLE_ - 1b)
+	add	r22, r22, r2
+#endif
+	
+	
+	.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
+#ifdef linux
+	nextpc	r22
+1:	movhi	r2, %hiadj(_GLOBAL_OFFSET_TABLE_ - 1b)
+	addi	r2, r2, %lo(_GLOBAL_OFFSET_TABLE_ - 1b)
+	add	r22, r22, r2
+#endif
+
Index: libgcc/config/nios2/t-linux
===================================================================
--- libgcc/config/nios2/t-linux	(revision 0)
+++ libgcc/config/nios2/t-linux	(revision 409063)
@@ -0,0 +1,7 @@ 
+# Soft-float functions go in glibc only, to facilitate the possible
+# future addition of exception and rounding mode support integrated
+# with <fenv.h>.
+
+LIB2FUNCS_EXCLUDE = _floatdidf _floatdisf _fixunsdfsi _fixunssfsi \
+  _fixunsdfdi _fixdfdi _fixunssfdi _fixsfdi _floatundidf _floatundisf
+LIB2ADD += $(srcdir)/config/nios2/linux-atomic.c
Index: libgcc/config/nios2/lib2-divtable.c
===================================================================
--- libgcc/config/nios2/lib2-divtable.c	(revision 0)
+++ libgcc/config/nios2/lib2-divtable.c	(revision 409063)
@@ -0,0 +1,60 @@ 
+/* Copyright (C) 2012 Free Software Foundation, Inc.
+   Contributed by Altera and Mentor Graphics, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "lib2-nios2.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: libgcc/config/nios2/lib2-mul.c
===================================================================
--- libgcc/config/nios2/lib2-mul.c	(revision 0)
+++ libgcc/config/nios2/lib2-mul.c	(revision 409063)
@@ -0,0 +1,42 @@ 
+/* Copyright (C) 2012 Free Software Foundation, Inc.
+   Contributed by Altera and Mentor Graphics, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "lib2-nios2.h"
+
+/* 32-bit SI multiply for Nios II.  */
+
+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;
+}
Index: libgcc/config/nios2/tramp.c
===================================================================
--- libgcc/config/nios2/tramp.c	(revision 0)
+++ libgcc/config/nios2/tramp.c	(revision 409063)
@@ -0,0 +1,62 @@ 
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+   Contributed by Altera and Mentor Graphics, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* Set up trampolines.
+   R12 is the static chain register.
+   R2 is AT, the assembler temporary.
+   The trampoline code looks like:
+	movhi	r12,%hi(chain)
+	ori	r12,%lo(chain)
+	movhi	r2,%hi(fn)
+	ori	r2,%lo(fn)
+	jmp	r2
+*/
+
+#define SC_REGNO 12
+
+#define MOVHI(reg,imm16) \
+  (((reg) << 22) | ((imm16) << 6) | 0x34)
+#define ORI(reg,imm16) \
+  (((reg) << 27) | ((reg) << 22) | ((imm16) << 6) | 0x14)
+#define JMP(reg) \
+  (((reg) << 27) | (0x0d << 11) | 0x3a)
+	
+void __trampoline_setup (unsigned int *addr,
+			 void *fnptr,
+			 void *chainptr)
+{
+  unsigned int fn = (unsigned int)fnptr;
+  unsigned int chain = (unsigned int)chainptr;
+  int i;
+
+  addr[0] = MOVHI (SC_REGNO, ((chain >> 16) & 0xffff));
+  addr[1] = ORI (SC_REGNO, (chain & 0xffff));
+  addr[2] = MOVHI (2, ((fn >> 16) & 0xffff));
+  addr[3] = ORI (2, (fn & 0xffff));
+  addr[4] = JMP (2);
+
+  /* Flush the caches.
+     See Example 9-4 in the Nios II Software Developer's Handbook.  */
+  for (i = 0; i < 5; i++)
+    asm volatile ("flushd 0(%0); flushi %0" :: "r"(addr + i) : "memory");
+  asm volatile ("flushp" ::: "memory");
+}
Index: libgcc/config/nios2/crtn.asm
===================================================================
--- libgcc/config/nios2/crtn.asm	(revision 0)
+++ libgcc/config/nios2/crtn.asm	(revision 409063)
@@ -0,0 +1,60 @@ 
+/* Copyright (C) 2012 Free Software Foundation, Inc.
+   Contributed by Jonah Graham (jgraham@altera.com).
+   Contributed by Mentor Graphics, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+
+/* 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
+