From 1583fb7f92973cdbba391bd32a1b42cbdb5839b8 Mon Sep 17 00:00:00 2001 From: Peter Kjellerstedt Date: Thu, 23 Feb 2006 17:21:39 +0000 Subject: Added support for the new CRISv32 architecture. --- Rules.mak | 1 + extra/Configs/Config.cris | 5 ++ include/elf.h | 6 ++ ldso/ldso/cris/dl-startup.h | 35 +++++++-- ldso/ldso/cris/dl-sysdep.h | 24 ++++++ ldso/ldso/cris/resolve.S | 88 ++++++++++++++++------ libc/sysdeps/linux/cris/__longjmp.S | 33 ++++++-- libc/sysdeps/linux/cris/bits/termios.h | 5 ++ libc/sysdeps/linux/cris/clone.S | 21 ++++-- libc/sysdeps/linux/cris/setjmp.S | 33 ++++++-- libc/sysdeps/linux/cris/syscall.S | 23 +++++- libc/sysdeps/linux/cris/sysdep.S | 31 +++++--- libc/sysdeps/linux/cris/sysdep.h | 46 +++++++++-- .../linuxthreads.old/sysdeps/cris/pt-machine.h | 24 +++--- 14 files changed, 299 insertions(+), 76 deletions(-) diff --git a/Rules.mak b/Rules.mak index 2a647b138..f31475e1e 100644 --- a/Rules.mak +++ b/Rules.mak @@ -244,6 +244,7 @@ endif ifeq ($(TARGET_ARCH),cris) CPU_LDFLAGS-$(CONFIG_CRIS)+=-mcrislinux + CPU_LDFLAGS-$(CONFIG_CRISV32)+=-mcrislinux CPU_CFLAGS-$(CONFIG_CRIS)+=-mlinux PICFLAG:=-fpic PIEFLAG_NAME:=-fpie diff --git a/extra/Configs/Config.cris b/extra/Configs/Config.cris index 0e52ef9d7..f6e2e3c05 100644 --- a/extra/Configs/Config.cris +++ b/extra/Configs/Config.cris @@ -26,9 +26,14 @@ choice These are the possible settings: - CRIS Generic support for Axis' CRIS architecture. + - CRISv32 Support for Axis' CRISv32 architecture. config CONFIG_CRIS select ARCH_HAS_MMU bool "CRIS" +config CONFIG_CRISV32 + select ARCH_HAS_MMU + bool "CRISv32" + endchoice diff --git a/include/elf.h b/include/elf.h index e1dae0962..44fcb2370 100644 --- a/include/elf.h +++ b/include/elf.h @@ -2591,6 +2591,12 @@ typedef Elf32_Addr Elf32_Conflict; #define R_390_NUM 61 +/* CRIS flags. */ +#define EF_CRIS_VARIANT_MASK 0x0000000e +#define EF_CRIS_VARIANT_ANY_V0_V10 0x00000000 +#define EF_CRIS_VARIANT_V32 0x00000002 +#define EF_CRIS_VARIANT_COMMON_V10_V32 0x00000004 + /* CRIS relocations. */ #define R_CRIS_NONE 0 #define R_CRIS_8 1 diff --git a/ldso/ldso/cris/dl-startup.h b/ldso/ldso/cris/dl-startup.h index 3274b41a5..417cb5096 100644 --- a/ldso/ldso/cris/dl-startup.h +++ b/ldso/ldso/cris/dl-startup.h @@ -4,22 +4,43 @@ /* This code fixes the stack pointer so that the dynamic linker * can find argc, argv and auxvt (Auxillary Vector Table). */ +#ifdef __arch_v32 + +asm("" \ +" .text\n" \ +" .globl _start\n" \ +" .type _start,@function\n" \ +"_start:\n" \ +" move.d $sp,$r10\n" \ +" lapc _dl_start,$r9\n" \ +" jsr $r9\n" \ +" nop\n" \ +" moveq 0,$r8\n" \ +" jump $r10\n" \ +" move $r8,$srp\n" \ +" .size _start,.-_start\n" \ +" .previous\n" \ +); + +#else + asm("" \ " .text\n" \ " .globl _start\n" \ " .type _start,@function\n" \ "_start:\n" \ -" move.d $sp,$r10\n" \ -" move.d $pc,$r9\n" \ -" add.d _dl_start - ., $r9\n" \ -" jsr $r9\n" \ -" moveq 0,$r8\n" \ -" move $r8,$srp\n" \ -" jump $r10\n" \ +" move.d $sp,$r10\n" \ +" move.d $pc,$r9\n" \ +" add.d _dl_start - ., $r9\n" \ +" jsr $r9\n" \ +" moveq 0,$r8\n" \ +" move $r8,$srp\n" \ +" jump $r10\n" \ " .size _start,.-_start\n" \ " .previous\n" \ ); +#endif /* __arch_v32 */ /* Get a pointer to the argv array. On many platforms this can be just * the address if the first argument, on other platforms we need to diff --git a/ldso/ldso/cris/dl-sysdep.h b/ldso/ldso/cris/dl-sysdep.h index b58f5e0a3..b5fa89035 100644 --- a/ldso/ldso/cris/dl-sysdep.h +++ b/ldso/ldso/cris/dl-sysdep.h @@ -68,8 +68,32 @@ elf_machine_load_address(void) { Elf32_Addr gotaddr_diff; +#ifdef __arch_v32 + extern char ___CRISv32_dummy[] __asm__ ("_dl_start"); + + __asm__ ("addo.w _dl_start:GOT16,$r0,$acr\n\t" + "lapc _dl_start,%0\n\t" + "sub.d [$acr],%0" + /* For v32, we need to force GCC to have R0 loaded with + _GLOBAL_OFFSET_TABLE_ at this point, which might not + otherwise have happened in the caller. (For v10, it's + loaded for non-global variables too, so we don't need + anything special there.) We accomplish this by faking the + address of a global variable (as seen by GCC) as input to + the asm; that address calculation goes through the GOT. + Use of this function happens before we've filled in the + GOT, so the address itself will not be correctly + calculated, therefore we don't use any symbol whose + address may be re-used later on. Let's just reuse the + _dl_start symbol, faking it as a global by renaming it as + another variable through an asm. */ + : "=r" (gotaddr_diff) + : "g" (___CRISv32_dummy) + : "acr"); +#else __asm__ ("sub.d [$r0+_dl_start:GOT16],$r0,%0\n\t" "add.d _dl_start:GOTOFF,%0" : "=r" (gotaddr_diff)); +#endif return gotaddr_diff; } diff --git a/ldso/ldso/cris/resolve.S b/ldso/ldso/cris/resolve.S index 9d2f079fe..9ca27b5ef 100644 --- a/ldso/ldso/cris/resolve.S +++ b/ldso/ldso/cris/resolve.S @@ -17,33 +17,73 @@ .globl _dl_linux_resolve .type _dl_linux_resolve,@function +#ifdef __arch_v32 + +_dl_linux_resolve: + subq 4,$sp + move.d $r0,[$sp] + subq 4,$sp + move.d $r13,[$sp] + subq 4,$sp + move.d $r12,[$sp] + subq 4,$sp + move.d $r11,[$sp] + subq 4,$sp + addoq 5*4,$sp,$acr + move.d $r10,[$sp] + subq 4,$sp + move $mof,$r10 + move.d $r9,[$sp] + subq 4,$sp + move.d [$acr],$r11 + move $srp,[$sp] + lapc _GLOBAL_OFFSET_TABLE_,$r0 + move.d _dl_linux_resolver:PLTG,$r9 + add.d $r0,$r9 + jsr $r9 + nop + move.d $r10,$acr + move [$sp+],$srp + move.d [$sp+],$r9 + move.d [$sp+],$r10 + move.d [$sp+],$r11 + move.d [$sp+],$r12 + move.d [$sp+],$r13 + move.d [$sp+],$r0 + jump $acr + addq 4,$sp + +#else + _dl_linux_resolve: - push $r13 - push $r12 - push $r11 - push $r10 - push $r9 - push $r0 - push $srp - move.d [$sp+7*4],$r11 - move $mof,$r10 + push $r13 + push $r12 + push $r11 + push $r10 + push $r9 + push $r0 + push $srp + move.d [$sp+7*4],$r11 + move $mof,$r10 #ifdef __PIC__ - move.d $pc,$r0 - sub.d .:GOTOFF,$r0 - move.d _dl_linux_resolver:PLTG,$r9 - add.d $r0,$r9 - jsr $r9 + move.d $pc,$r0 + sub.d .:GOTOFF,$r0 + move.d _dl_linux_resolver:PLTG,$r9 + add.d $r0,$r9 + jsr $r9 #else - jsr _dl_linux_resolver + jsr _dl_linux_resolver #endif - move.d $r10,[$sp+7*4] - pop $srp - pop $r0 - pop $r9 - pop $r10 - pop $r11 - pop $r12 - pop $r13 - jump [$sp+] + move.d $r10,[$sp+7*4] + pop $srp + pop $r0 + pop $r9 + pop $r10 + pop $r11 + pop $r12 + pop $r13 + jump [$sp+] + +#endif /* __arch_v32 */ .size _dl_linux_resolve, . - _dl_linux_resolve diff --git a/libc/sysdeps/linux/cris/__longjmp.S b/libc/sysdeps/linux/cris/__longjmp.S index 8c7ca6eaa..52a986fd9 100644 --- a/libc/sysdeps/linux/cris/__longjmp.S +++ b/libc/sysdeps/linux/cris/__longjmp.S @@ -1,5 +1,5 @@ /* longjmp for CRIS. - Copyright (C) 2001 Free Software Foundation, Inc. + Copyright (C) 2001, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -23,17 +23,40 @@ #define _ASM #include + .syntax no_register_prefix + /* Saving and restoring CCR is meaningless, so we don't do it. */ ENTRY (__longjmp) /* Note that r10 = jmp_buf, r11 = retval. */ - move [$r10+16*4],$srp - test.d $r11 +#ifdef __arch_v32 + + /* We don't restore the call-clobbered registers for v32; + their space (corresponding to v10) is now defined as + reserved. */ + movem [r10],r9 + addq 14*4,r10 + cmpq 0,r11 + beq 0f + move.d [r10+],sp + + move.d r11,r9 +0: + move.d [r10+],acr + jump acr + move [r10],srp + +#else + + move [r10+16*4],srp + test.d r11 beq 0f /* Already a 1 in place. */ nop /* Offset for r9, the return value (see setjmp). */ - move.d $r11,[$r10+6*4] + move.d r11,[r10+6*4] 0: - movem [$r10],$pc + movem [r10],pc + +#endif END (__longjmp) libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/cris/bits/termios.h b/libc/sysdeps/linux/cris/bits/termios.h index ab63aaa83..63ca4ea93 100644 --- a/libc/sysdeps/linux/cris/bits/termios.h +++ b/libc/sysdeps/linux/cris/bits/termios.h @@ -161,7 +161,12 @@ struct termios #define B921600 0010005 #define B1843200 0010006 #define B6250000 0010007 +#ifdef __arch_v32 +#define B12500000 0010010 +#define __MAX_BAUD B12500000 +#else #define __MAX_BAUD B6250000 +#endif #ifdef __USE_MISC # define CIBAUD 002003600000 /* input baud rate (not used) */ # define CMSPAR 010000000000 /* mark or space (stick) parity */ diff --git a/libc/sysdeps/linux/cris/clone.S b/libc/sysdeps/linux/cris/clone.S index a3b1cff7e..9e284fe0a 100644 --- a/libc/sysdeps/linux/cris/clone.S +++ b/libc/sysdeps/linux/cris/clone.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2001 Free Software Foundation, Inc. +/* Copyright (C) 2001, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -17,9 +17,10 @@ Boston, MA 02111-1307, USA. */ #include -#include #include #include "sysdep.h" +#define _ERRNO_H 1 +#include /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ @@ -29,12 +30,13 @@ ENTRY (clone) /* Sanity check arguments: No NULL function pointers. Allow a NULL stack pointer though; it makes the kernel allocate stack. */ - test.d r10 + cmpq 0,r10 beq 1f nop /* We need to muck with a few registers. */ - movem r1,[sp=sp-8] + subq 8,sp + movem r1,[sp] /* Save the function pointer and argument. We can't save them onto the new stack since it can be NULL. */ @@ -48,7 +50,7 @@ ENTRY (clone) /* Do the system call. */ movu.w SYS_ify (clone),r9 break 13 - test.d r10 + cmpq 0,r10 beq .Lthread_start nop @@ -65,15 +67,22 @@ ENTRY (clone) /* Terminate frame pointers here. */ moveq 0,r8 +#ifdef __arch_v32 + /* Is this the right place for an argument? */ + jsr r0 + move.d r1,r10 +#else /* I've told you once. */ move.d r1,r10 jsr r0 +#endif SETUP_PIC PLTCALL (HIDDEN_JUMPTARGET(_exit)) /* Die horribly. */ - test.d [6809] + move.d 6809,r13 + test.d [r13] /* Stop the unstoppable. */ 9: diff --git a/libc/sysdeps/linux/cris/setjmp.S b/libc/sysdeps/linux/cris/setjmp.S index 0c5608fbd..e7bb6358a 100644 --- a/libc/sysdeps/linux/cris/setjmp.S +++ b/libc/sysdeps/linux/cris/setjmp.S @@ -1,5 +1,5 @@ /* setjmp for CRIS. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -18,14 +18,28 @@ Boston, MA 02111-1307, USA. */ #include "sysdep.h" -#define _ASM #define _SETJMP_H +#define _ASM #include .syntax no_register_prefix ENTRY (__sigsetjmp) .Local__sigsetjmp: + +#ifdef __arch_v32 + + moveq 1,r9 + move.d r10,r12 + addq 14*4,r12 + movem r9,[r10] + lapc 0f,r13 + move.d sp,[r12+] + move.d r13,[r12+] + move srp,[r12+] + +#else + moveq 1,r9 movem sp,[r10+1*4] #ifdef __PIC__ @@ -36,6 +50,15 @@ ENTRY (__sigsetjmp) #endif move.d r9,[r10] move srp,[r10+16*4] + +#endif + +/* Saving and restoring CCR is meaningless, so we don't do it. */ + +/* Saving registers would complicate the implementation, but we + can get away with not setting up R0 here since we know that + __sigjmp_save is a local symbol; it doesn't have a PLT (which + would have required GOT in R0 at the time of the jump). */ PLTJUMP (__sigjmp_save) 0: /* This is where longjmp returns. (Don't use "ret" - it's a macro. */ Ret @@ -59,9 +82,3 @@ ENTRY (setjmp) ba .Local__sigsetjmp moveq 1,r11 END (setjmp) - -/* -weak_extern (__setjmp) -weak_extern (_setjmp) -weak_extern (setjmp) -*/ diff --git a/libc/sysdeps/linux/cris/syscall.S b/libc/sysdeps/linux/cris/syscall.S index 1a32108d7..d4b052e8e 100644 --- a/libc/sysdeps/linux/cris/syscall.S +++ b/libc/sysdeps/linux/cris/syscall.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -23,6 +23,26 @@ /* Make syscall (callno, ...) into a system call. */ ENTRY (syscall) +#ifdef __arch_v32 + subq 4,sp + move.d r10,r9 + move srp,[sp] + addoq 8,sp,acr + move.d r11,r10 + move [acr],mof + addoq 12,sp,acr + move.d r12,r11 + move [acr],srp + addoq 4,sp,acr + move.d r13,r12 + move.d [acr],r13 + break 13 + cmps.w -4096,r10 + bhs 0f + move [sp+],srp + Ret + nop +#else push srp move.d r10,r9 move.d r11,r10 @@ -37,4 +57,5 @@ ENTRY (syscall) pop srp Ret nop +#endif PSEUDO_END (syscall) diff --git a/libc/sysdeps/linux/cris/sysdep.S b/libc/sysdeps/linux/cris/sysdep.S index 30d77df15..4e558153b 100644 --- a/libc/sysdeps/linux/cris/sysdep.S +++ b/libc/sysdeps/linux/cris/sysdep.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2001 Free Software Foundation, Inc. +/* Copyright (C) 2001, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -25,11 +25,9 @@ .type C_SYMBOL_NAME(errno),@object .lcomm C_SYMBOL_NAME(errno),4 + .weak errno errno = _errno - /* weak_alias (errno, _errno) */ - - /* The syscall stubs jump here when they detect an error, bot for PIC and non-PIC. */ @@ -39,25 +37,38 @@ ENTRY (__syscall_error) neg.d r10,r10 #ifdef __UCLIBC_HAS_THREADS__ - push r10 - push srp + subq 4,sp + move.d r10,[sp] + subq 4,sp + move srp,[sp] /* Note that __syscall_error is only visible within this library, and no-one passes it on as a pointer, so can assume that R0 (GOT pointer) is correctly set up. */ - PLTCALL (__errno_location) + PLTCALL (HIDDEN_JUMPTARGET(__errno_location)) - pop srp - pop r11 + move [sp+],srp + move.d [sp+],r11 move.d r11,[r10] #else /* not __UCLIBC_HAS_THREADS__ */ +#ifdef __arch_v32 +# ifdef __PIC__ + addo.d C_SYMBOL_NAME(errno:GOT),r0,acr + move.d [acr],r9 + move.d r10,[r9] +# else /* not __PIC__ */ + lapc C_SYMBOL_NAME(errno),acr + move.d r10,[r9] +# endif /* not __PIC__ */ +#else /* not __arch_v32 */ # ifdef __PIC__ move.d [r0+C_SYMBOL_NAME(errno:GOT)],r9 move.d r10,[r9] # else move.d r10,[C_SYMBOL_NAME(errno)] # endif +#endif /* not __arch_v32 */ #endif /* __UCLIBC_HAS_THREADS__ */ #ifdef __PIC__ @@ -69,7 +80,7 @@ ENTRY (__syscall_error) moveq -1,r10 Ret - pop r0 + move.d [sp+],r0 #else Ret moveq -1,r10 diff --git a/libc/sysdeps/linux/cris/sysdep.h b/libc/sysdeps/linux/cris/sysdep.h index 08cf6221c..593e7772e 100644 --- a/libc/sysdeps/linux/cris/sysdep.h +++ b/libc/sysdeps/linux/cris/sysdep.h @@ -40,8 +40,14 @@ #define END(sym) #endif +#undef SYS_ify +#define SYS_ify(syscall_name) (__NR_##syscall_name) + #ifdef __ASSEMBLER__ +#undef SYS_ify +#define SYS_ify(syscall_name) __NR_##syscall_name + /* Syntactic details of assembly-code. */ /* It is *not* generally true that "ELF uses byte-counts for .align, most @@ -58,6 +64,37 @@ /* The non-PIC jump is preferred, since it does not stall, and does not invoke generation of a PLT. These macros assume that $r0 is set up as GOT register. */ +#ifdef __arch_v32 +#ifdef __PIC__ +#define PLTJUMP(_x) \ + ba C_SYMBOL_NAME (_x):PLT @ \ + nop + +#define PLTCALL(_x) \ + bsr C_SYMBOL_NAME (_x):PLT @ \ + nop + +#define SETUP_PIC \ + subq 4,$sp @ \ + move.d $r0,[$sp] @ \ + lapc _GLOBAL_OFFSET_TABLE_,$r0 + +#define TEARDOWN_PIC move.d [$sp+],$r0 +#else +#define PLTJUMP(_x) \ + ba C_SYMBOL_NAME (_x) @ \ + nop + +#define PLTCALL(_x) \ + bsr C_SYMBOL_NAME (_x) @ \ + nop + +#define SETUP_PIC +#define TEARDOWN_PIC +#endif + +#else + #ifdef __PIC__ #define PLTJUMP(_x) \ add.d C_SYMBOL_NAME (_x):PLT,$pc @@ -78,14 +115,15 @@ #define TEARDOWN_PIC #endif +#endif /* __arch_v32 */ + /* Define an entry point visible from C. */ #define ENTRY(name) \ .text @ \ ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (name) @ \ ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME (name), function) @ \ .align ALIGNARG (2) @ \ - C_LABEL(name) @ \ - CALL_MCOUNT + C_LABEL(name) #undef END #define END(name) \ @@ -107,9 +145,5 @@ PLTJUMP (__syscall_error) @ \ END (name) -/* If compiled for profiling, do nothing */ -#define CALL_MCOUNT /* Do nothing. */ - - #endif /* __ASSEMBLER__ */ #endif /* _SYSDEP_H_ */ diff --git a/libpthread/linuxthreads.old/sysdeps/cris/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/cris/pt-machine.h index 431da7101..a287e866a 100644 --- a/libpthread/linuxthreads.old/sysdeps/cris/pt-machine.h +++ b/libpthread/linuxthreads.old/sysdeps/cris/pt-machine.h @@ -18,16 +18,10 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - #ifndef PT_EI # define PT_EI extern inline __attribute__ ((always_inline)) #endif -extern long int testandset (int *spinlock); -extern int __compare_and_swap (long int *p, long int oldval, long int newval); - PT_EI long int testandset (int *spinlock) { @@ -35,6 +29,19 @@ testandset (int *spinlock) /* Note the use of a dummy output of *spinlock to expose the write. The memory barrier is to stop *other* writes being moved past this code. */ + +#ifdef __arch_v32 + __asm__ __volatile__("clearf p\n" + "0:\n\t" + "movu.b [%2],%0\n\t" + "ax\n\t" + "move.b %3,[%2]\n\t" + "bcs 0b\n\t" + "clearf p" + : "=&r" (ret), "=m" (*spinlock) + : "r" (spinlock), "r" ((int) 1), "m" (*spinlock) + : "memory"); +#else /* not __arch_v32 */ __asm__ __volatile__("clearf\n" "0:\n\t" "movu.b [%2],%0\n\t" @@ -43,8 +50,9 @@ testandset (int *spinlock) "bwf 0b\n\t" "clearf" : "=&r" (ret), "=m" (*spinlock) - : "r" (spinlock), "r" ((int) 1) + : "r" (spinlock), "r" ((int) 1), "m" (*spinlock) : "memory"); +#endif /* __arch_v32 */ return ret; } @@ -54,5 +62,3 @@ testandset (int *spinlock) I don't trust register variables, so let's do this the safe way. */ #define CURRENT_STACK_FRAME \ ({ char *sp; __asm__ ("move.d $sp,%0" : "=rm" (sp)); sp; }) - -#endif /* pt-machine.h */ -- cgit v1.2.3