diff options
| -rw-r--r-- | recipes/gcc/gcc-4.1.2.inc | 6 | ||||
| -rw-r--r-- | recipes/gcc/gcc-4.1.2/gcc-config-nios2.patch | 41 | ||||
| -rw-r--r-- | recipes/gcc/gcc-4.1.2/gcc-nios2.patch | 11017 | ||||
| -rw-r--r-- | recipes/gcc/gcc-4.1.2/nios2-lib-flags.patch | 10 |
4 files changed, 11074 insertions, 0 deletions
diff --git a/recipes/gcc/gcc-4.1.2.inc b/recipes/gcc/gcc-4.1.2.inc index e89a8de241..3b6cf30913 100644 --- a/recipes/gcc/gcc-4.1.2.inc +++ b/recipes/gcc/gcc-4.1.2.inc @@ -33,6 +33,12 @@ SRC_URI = "${GNU_MIRROR}/gcc/gcc-${PV}/gcc-${PV}.tar.bz2;name=archive \ SRC_URI_append_sh3 = " file://sh3-installfix-fixheaders.patch " +SRC_URI_append_nios2 = " \ + file://gcc-nios2.patch \ + file://gcc-config-nios2.patch \ + file://nios2-lib-flags.patch \ + " + SRC_URI_avr32 = "http://www.angstrom-distribution.org/unstable/sources/gcc-4.1.2-atmel.1.1.0.tar.gz;name=atmel \ # file://100-uclibc-conf.patch \ # file://200-uclibc-locale.patch \ diff --git a/recipes/gcc/gcc-4.1.2/gcc-config-nios2.patch b/recipes/gcc/gcc-4.1.2/gcc-config-nios2.patch new file mode 100644 index 0000000000..1cd5a955d3 --- /dev/null +++ b/recipes/gcc/gcc-4.1.2/gcc-config-nios2.patch @@ -0,0 +1,41 @@ +Index: gcc-4.1.2/config.sub +=================================================================== +--- gcc-4.1.2.orig/config.sub 2010-05-27 15:30:45.069455792 +0200 ++++ gcc-4.1.2/config.sub 2010-05-27 15:36:32.868205558 +0200 +@@ -267,6 +267,7 @@ + | mn10200 | mn10300 \ + | mt \ + | msp430 \ ++ | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ +@@ -349,6 +350,7 @@ + | mmix-* \ + | mt-* \ + | msp430-* \ ++ | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ +Index: gcc-4.1.2/gcc/config.gcc +=================================================================== +--- gcc-4.1.2.orig/gcc/config.gcc 2010-05-27 15:30:45.039455207 +0200 ++++ gcc-4.1.2/gcc/config.gcc 2010-05-27 15:33:26.249455379 +0200 +@@ -1597,6 +1597,16 @@ + tm_file="dbxelf.h elfos.h svr4.h ${tm_file}" + tmake_file="${tmake_file} mt/t-mt" + ;; ++nios2-*-*) ++ tm_file="elfos.h ${tm_file}" ++ tmake_file="${tmake_file} nios2/t-nios2" ++ case ${target} in ++ nios2-*-linux*) ++ tm_file="${tm_file} linux.h nios2/linux.h" ++ tmake_file="${tmake_file} nios2/t-linux" ++ ;; ++ esac ++ ;; + ns32k-*-netbsdelf*) + echo "GCC does not yet support the ${target} target"; exit 1 + ;; diff --git a/recipes/gcc/gcc-4.1.2/gcc-nios2.patch b/recipes/gcc/gcc-4.1.2/gcc-nios2.patch new file mode 100644 index 0000000000..80a46b7751 --- /dev/null +++ b/recipes/gcc/gcc-4.1.2/gcc-nios2.patch @@ -0,0 +1,11017 @@ +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)®s->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 = (_ |
