OSDN Git Service

Add NIOS2 support. Code from SourceyG++.
authorMasaki Muranaka <monaka@monami-ya.jp>
Sun, 18 May 2014 16:12:00 +0000 (01:12 +0900)
committerMasaki Muranaka <monaka@monami-ya.jp>
Sun, 18 May 2014 16:12:00 +0000 (01:12 +0900)
13 files changed:
libgcc/config.host
libgcc/config/nios2/crti.S [new file with mode: 0644]
libgcc/config/nios2/crtn.S [new file with mode: 0644]
libgcc/config/nios2/lib2-divmod-hi.c [new file with mode: 0644]
libgcc/config/nios2/lib2-divmod.c [new file with mode: 0644]
libgcc/config/nios2/lib2-divtable.c [new file with mode: 0644]
libgcc/config/nios2/lib2-mul.c [new file with mode: 0644]
libgcc/config/nios2/lib2-nios2.h [new file with mode: 0644]
libgcc/config/nios2/linux-atomic.c [new file with mode: 0644]
libgcc/config/nios2/linux-unwind.h [new file with mode: 0644]
libgcc/config/nios2/t-linux [new file with mode: 0644]
libgcc/config/nios2/t-nios2 [new file with mode: 0644]
libgcc/config/nios2/tramp.c [new file with mode: 0644]

index d8e7255..6cb1651 100644 (file)
@@ -135,6 +135,9 @@ mips*-*-*)
        cpu_type=mips
        tmake_file=mips/t-mips
        ;;
+nios2*-*-*)
+        cpu_type=nios2
+        ;;
 powerpc*-*-*)
        cpu_type=rs6000
        ;;
@@ -829,6 +832,15 @@ moxie-*-rtems*)
        # 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"
        ;;
diff --git a/libgcc/config/nios2/crti.S b/libgcc/config/nios2/crti.S
new file mode 100644 (file)
index 0000000..4f17f19
--- /dev/null
@@ -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
+
diff --git a/libgcc/config/nios2/crtn.S b/libgcc/config/nios2/crtn.S
new file mode 100644 (file)
index 0000000..71ef2a0
--- /dev/null
@@ -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
+
diff --git a/libgcc/config/nios2/lib2-divmod-hi.c b/libgcc/config/nios2/lib2-divmod-hi.c
new file mode 100644 (file)
index 0000000..6efe9eb
--- /dev/null
@@ -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);
+}
+
diff --git a/libgcc/config/nios2/lib2-divmod.c b/libgcc/config/nios2/lib2-divmod.c
new file mode 100644 (file)
index 0000000..cd1a674
--- /dev/null
@@ -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);
+}
+
diff --git a/libgcc/config/nios2/lib2-divtable.c b/libgcc/config/nios2/lib2-divtable.c
new file mode 100644 (file)
index 0000000..8c003f9
--- /dev/null
@@ -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,
+};
+
diff --git a/libgcc/config/nios2/lib2-mul.c b/libgcc/config/nios2/lib2-mul.c
new file mode 100644 (file)
index 0000000..6fc4581
--- /dev/null
@@ -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;
+}
diff --git a/libgcc/config/nios2/lib2-nios2.h b/libgcc/config/nios2/lib2-nios2.h
new file mode 100644 (file)
index 0000000..81bf37e
--- /dev/null
@@ -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 */
diff --git a/libgcc/config/nios2/linux-atomic.c b/libgcc/config/nios2/linux-atomic.c
new file mode 100644 (file)
index 0000000..c51c3f1
--- /dev/null
@@ -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)
diff --git a/libgcc/config/nios2/linux-unwind.h b/libgcc/config/nios2/linux-unwind.h
new file mode 100644 (file)
index 0000000..552854d
--- /dev/null
@@ -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
diff --git a/libgcc/config/nios2/t-linux b/libgcc/config/nios2/t-linux
new file mode 100644 (file)
index 0000000..1fa581e
--- /dev/null
@@ -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
diff --git a/libgcc/config/nios2/t-nios2 b/libgcc/config/nios2/t-nios2
new file mode 100644 (file)
index 0000000..1dd2116
--- /dev/null
@@ -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 
+
diff --git a/libgcc/config/nios2/tramp.c b/libgcc/config/nios2/tramp.c
new file mode 100644 (file)
index 0000000..0c2b590
--- /dev/null
@@ -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");
+}