klibc now runs on the CRIS archtitecture. The patch below is against
0.146. Most of the changes are trivial but the new files in libgcc
requires some comments.
__negdi2.c: The CRIS port fallbacks to C-code for negdi2. The code in
__negdi2.c is copied from libgcc2.c but with modified typenames.
I would really appreciate if someone could check if it seams sane.
crisarith.c: CRIS has no built-in division instruction so there
are lots of C-code to implement Div and Mod. crisarith.c implements
all this (copied from arith.c in libgcc). This file is only relevant
for CRIS so maybe it should be in some other directory?
/Mikael (Linux CRIS maintainer, not subscribed to klibc list)
--- ./klibc/arch/cris/MCONFIG Thu Jun 10 10:06:20 2004
+++ ../klibc-0.146-modified/klibc/arch/cris/MCONFIG Wed Jun 23 10:57:33
2004
@@ -15,7 +15,16 @@
# calls, and work on the memory models for this architecture
# 224 MB - normal binaries start at 0
# (lib?)gcc on cris seems to insist on producing .init and .fini sections
-SHAREDFLAGS = --section-start .init=0x0e000100
+SHAREDFLAGS = -Wl,--section-start,.init=0x0e000100
+
+# The CRIS compiler needs an -iprefix to find libgcc includes when
+# nostdinc is used. It also needs -mlinux to compile linux applications.
+INCLUDE_PREFIX = $(shell $(CC) -print-libgcc-file-name | sed -e
s/libgcc.a//)
+ARCHREQFLAGS = -iprefix $(INCLUDE_PREFIX) -mlinux
# How to tell the linker main() is the entrypoint
EMAIN := -e _main
+
+# Use gcc to link to get all the flags correct
+LD = cris-gcc
+LDFLAGS += -mlinux -nostdlib
\ No newline at end of file
diff -urN ./klibc/arch/cris/Makefile.inc
../klibc-0.146-modified/klibc/arch/cris/Makefile.inc
--- ./klibc/arch/cris/Makefile.inc Thu Jun 10 08:59:15 2004
+++ ../klibc-0.146-modified/klibc/arch/cris/Makefile.inc Wed Jun 23
09:45:12 2004
@@ -14,6 +14,8 @@
libgcc/__moddi3.o \
libgcc/__udivdi3.o \
libgcc/__umoddi3.o \
- libgcc/__udivmoddi4.o
+ libgcc/__udivmoddi4.o \
+ libgcc/__negdi2.o \
+ libgcc/crisarith.o
archclean:
diff -urN ./klibc/arch/cris/crt0.S
../klibc-0.146-modified/klibc/arch/cris/crt0.S
--- ./klibc/arch/cris/crt0.S Thu Jun 10 08:59:15 2004
+++ ../klibc-0.146-modified/klibc/arch/cris/crt0.S Wed Jun 23 09:21:00
2004
@@ -10,9 +10,9 @@
.text
.balign 4
- .type __start,@function
- .globl __start
-__start:
+ .type _start,@function
+ .globl _start
+_start:
/* Save the address of the ELF argument array */
move.d $sp,$r10 /* Address of ELF arguments */
@@ -21,8 +21,8 @@
/* Set up a dummy stack frame to keep gcc from getting confused */
push $r11
- jump ___libc_init
+ jump __libc_init
push $r11
- .size __start, .-__start
+ .size _start, .-_start
diff -urN ./klibc/arch/cris/setjmp.S
../klibc-0.146-modified/klibc/arch/cris/setjmp.S
--- ./klibc/arch/cris/setjmp.S Thu Jun 10 20:31:54 2004
+++ ../klibc-0.146-modified/klibc/arch/cris/setjmp.S Wed Jun 23 09:59:57
2004
@@ -13,25 +13,25 @@
.text
.balign 4
- .globl _setjmp
- .type _setjmp, @function
-_setjmp:
+ .globl setjmp
+ .type setjmp, @function
+setjmp:
movem $r8,[$r10+] /* Save $r8..$r0 at $r10... */
move.d $sp,[$r10+]
move $srp,[$r10]
ret
moveq 0,$r10
- .size _setjmp,.-_setjmp
+ .size setjmp,.-setjmp
.text
.balign 4
- .globl _longjmp
- .type _longjmp, @function
-_longjmp:
+ .globl longjmp
+ .type longjmp, @function
+longjmp:
movem [$r10+],$r8 /* Load $r8..$r0 from $r10... */
move.d [$r10+],$sp
jump [$r10]
- move.d $r11,$r10
+ move.d $r11,$r10
- .size _longjmp,.-_longjmp
+ .size longjmp,.-longjmp
diff -urN ./klibc/arch/cris/syscall.S
../klibc-0.146-modified/klibc/arch/cris/syscall.S
--- ./klibc/arch/cris/syscall.S Thu Jun 10 08:59:15 2004
+++ ../klibc-0.146-modified/klibc/arch/cris/syscall.S Wed Jun 23 10:36:07
2004
@@ -9,9 +9,9 @@
.section ".text","ax"
.balign 4
- .globl ___syscall_common
- .type ___syscall_common,@function
-___syscall_common:
+ .globl __syscall_common
+ .type __syscall_common,@function
+__syscall_common:
push $srp
move [$sp+4],$mof
move [$sp+8],$srp
@@ -19,11 +19,12 @@
cmp.d -4096,$r10
blt 1f
- neg.d $r10,$r11
- move.d $r11,[_errno]
+ neg.d $r10,$r11
+ move.d $r11,[errno]
moveq -1,$r10
1:
- jump [sp+]
- nop
+ pop $srp
+ ret
+ nop
- .size ___syscall_common,.-___syscall_common
+ .size __syscall_common,.-__syscall_common
diff -urN ./klibc/arch/cris/sysstub.ph
../klibc-0.146-modified/klibc/arch/cris/sysstub.ph
--- ./klibc/arch/cris/sysstub.ph Thu Jun 10 08:59:15 2004
+++ ../klibc-0.146-modified/klibc/arch/cris/sysstub.ph Wed Jun 23 10:25:49
2004
@@ -12,17 +12,17 @@
print OUT "#include <asm/unistd.h>\n";
print OUT "\n";
print OUT "\t.text\n";
- print OUT "\t.type\t_${fname},\@function\n";
- print OUT "\t.globl\t_${fname}\n";
+ print OUT "\t.type\t${fname},\@function\n";
+ print OUT "\t.globl\t${fname}\n";
print OUT "\t.balign\t4\n";
- print OUT "_${fname}:\n";
- print OUT "\tjump\t___syscall_common\n";
+ print OUT "${fname}:\n";
print OUT "#if __NR_${sname} <= 31\n";
print OUT "\t moveq\t__NR_${sname}, \$r9\n";
print OUT "#else\n";
print OUT "\t move.d\t__NR_${sname}, \$r9\n";
print OUT "#endif\n";
- print OUT "\t.size _${fname},.-_${fname}\n";
+ print OUT "\tjump\t__syscall_common\n";
+ print OUT "\t.size ${fname},.-${fname}\n";
close(OUT);
}
diff -urN ./klibc/libgcc/__negdi2.c
../klibc-0.146-modified/klibc/libgcc/__negdi2.c
--- ./klibc/libgcc/__negdi2.c Thu Jan 1 01:00:00 1970
+++ ../klibc-0.146-modified/klibc/libgcc/__negdi2.c Wed Jun 23 09:42:14
2004
@@ -0,0 +1,24 @@
+#include <stdint.h>
+#include <stddef.h>
+
+struct DWstruct {int32_t low, high;};
+
+typedef union
+{
+ struct DWstruct s;
+ int64_t ll;
+} DWunion;
+
+
+__negdi2 (int64_t u)
+{
+ DWunion w;
+ DWunion uu;
+
+ uu.ll = u;
+
+ w.s.low = -uu.s.low;
+ w.s.high = -uu.s.high - ((uint32_t) w.s.low > 0);
+
+ return w.ll;
+}
diff -urN ./klibc/libgcc/crisarith.c
../klibc-0.146-modified/klibc/libgcc/crisarith.c
--- ./klibc/libgcc/crisarith.c Thu Jan 1 01:00:00 1970
+++ ../klibc-0.146-modified/klibc/libgcc/crisarith.c Wed Jun 23 09:59:22
2004
@@ -0,0 +1,256 @@
+/* Signed and unsigned multiplication and division and modulus for CRIS.
+ Contributed by Axis Communications.
+ Written by Hans-Peter Nilsson <hp@axis.se>, c:a 1992.
+
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 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.)
+
+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, some of
+ which are compiled with GCC, this library does not by itself cause
+ the resulting object or executable to be covered by the GNU General
+ Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file or object might be covered by the GNU General
+ Public License. */
+
+
+/* Note that we provide prototypes for all "const" functions, to
attach
+ the const attribute. This is necessary in 2.7.2 - adding the
+ attribute to the function *definition* is a syntax error.
+ This did not work with e.g. 2.1; back then, the return type had to
+ be "const". */
+
+#define LZ(v) __extension__ \
+ ({ int tmp_; __asm__ ("lz %1,%0" : "=r" (tmp_) :
"r" (v)); tmp_; })
+
+/* Result type of divmod worker function. */
+struct quot_rem
+ {
+ long quot;
+ long rem;
+ };
+
+/* This is the worker function for div and mod. It is inlined into the
+ respective library function. */
+static __inline__ struct quot_rem
+do_31div (unsigned long a, unsigned long b)
+ __attribute__ ((__const__, __always_inline__));
+
+static __inline__ struct quot_rem
+do_31div (unsigned long a, unsigned long b)
+{
+ /* Adjust operands and result if a is 31 bits. */
+ long extra = 0;
+ int quot_digits = 0;
+
+ if (b == 0)
+ {
+ struct quot_rem ret;
+ ret.quot = 0xffffffff;
+ ret.rem = 0xffffffff;
+ return ret;
+ }
+
+ if (a < b)
+ return (struct quot_rem) { 0, a };
+
+ if (b <= a)
+ {
+ quot_digits = LZ (b) - LZ (a);
+ quot_digits += (a >= (b << quot_digits));
+ b <<= quot_digits;
+ }
+
+ /* Is a 31 bits? Note that bit 31 is handled by the caller. */
+ if (a & 0x40000000)
+ {
+ /* Then make b:s highest bit max 0x40000000, because it must have
+ been 0x80000000 to be 1 bit higher than a. */
+ b >>= 1;
+
+ /* Adjust a to be maximum 0x3fffffff, i.e. two upper bits zero. */
+ if (a >= b)
+ {
+ a -= b;
+ extra = 1 << (quot_digits - 1);
+ }
+ else
+ {
+ a -= b >> 1;
+
+ /* Remember that we adjusted a by subtracting b * 2 ** Something.
*/
+ extra = 1 << quot_digits;
+ }
+
+ /* The number of quotient digits will be one less, because
+ we just adjusted b. */
+ quot_digits--;
+ }
+
+ /* Now do the division part. */
+
+ /* Subtract b and add ones to the right when a >= b
+ i.e. "a - (b - 1) == (a - b) + 1". */
+ b--;
+
+#define DS __asm__ ("dstep %2,%0" : "=r" (a) :
"0" (a), "r" (b))
+
+ switch (quot_digits)
+ {
+ case 32: DS; case 31: DS; case 30: DS; case 29: DS;
+ case 28: DS; case 27: DS; case 26: DS; case 25: DS;
+ case 24: DS; case 23: DS; case 22: DS; case 21: DS;
+ case 20: DS; case 19: DS; case 18: DS; case 17: DS;
+ case 16: DS; case 15: DS; case 14: DS; case 13: DS;
+ case 12: DS; case 11: DS; case 10: DS; case 9: DS;
+ case 8: DS; case 7: DS; case 6: DS; case 5: DS;
+ case 4: DS; case 3: DS; case 2: DS; case 1: DS;
+ case 0:;
+ }
+
+ {
+ struct quot_rem ret;
+ ret.quot = (a & ((1 << quot_digits) - 1)) + extra;
+ ret.rem = a >> quot_digits;
+ return ret;
+ }
+}
+
+/* Note that unsigned and signed division both build when L_divsi3, but
+ the unsigned variant is then inlined, as with do_31div above. */
+unsigned long
+__Udiv (unsigned long a, unsigned long b)
+ __attribute__ ((__const__, __always_inline__));
+
+unsigned long
+__Udiv (unsigned long a, unsigned long b)
+{
+ long extra = 0;
+
+ /* Adjust operands and result, if a and/or b is 32 bits. */
+ /* Effectively: b & 0x80000000. */
+ if ((long) b < 0)
+ return a >= b;
+
+ /* Effectively: a & 0x80000000. */
+ if ((long) a < 0)
+ {
+ int tmp = 0;
+
+ if (b == 0)
+ return 0xffffffff;
+ tmp = LZ (b);
+
+ if ((b << tmp) > a)
+ {
+ extra = 1 << (tmp-1);
+ a -= b << (tmp - 1);
+ }
+ else
+ {
+ extra = 1 << tmp;
+ a -= b << tmp;
+ }
+ }
+
+ return do_31div (a, b).quot+extra;
+}
+
+
+long
+__Div (long a, long b) __attribute__ ((__const__));
+
+long
+__Div (long a, long b)
+{
+ long sign;
+ long result;
+
+ /* Do *not* call do_31div since abs (-2147483648) == 2147483648
+ <=> abs (-0x80000000) == 0x80000000
+ which is still 32 bits. */
+
+ sign = a ^ b;
+ result = __Udiv (__builtin_labs (a), __builtin_labs (b));
+
+ return (sign < 0) ? -result : result;
+}
+
+
+/* Note that unsigned and signed modulus both build when L_modsi3, but
+ then the unsigned variant is inlined, as with do_31div above. */
+unsigned long
+__Umod (unsigned long a, unsigned long b)
+ __attribute__ ((__const__, __always_inline__));
+
+unsigned long
+__Umod (unsigned long a, unsigned long b)
+{
+ /* Adjust operands and result if a and/or b is 32 bits. */
+ if ((long) b < 0)
+ return a >= b ? a - b : a;
+
+ if ((long) a < 0)
+ {
+ int tmp = 0;
+
+ if (b == 0)
+ return a;
+ tmp = LZ (b);
+
+ if ((b << tmp) > a)
+ {
+ a -= b << (tmp - 1);
+ }
+ else
+ {
+ a -= b << tmp;
+ }
+ }
+
+ return do_31div (a, b).rem;
+}
+
+long
+__Mod (long a, long b) __attribute__ ((__const__));
+
+long
+__Mod (long a, long b)
+{
+ long result;
+
+ result = __Umod (__builtin_labs (a), __builtin_labs (b));
+
+ return (a < 0) ? -result : result;
+}
+
+/*
+ * Local variables:
+ * eval: (c-set-style "gnu")
+ * indent-tabs-mode: t
+ * End:
+ */