diff options
Diffstat (limited to 'src/thread')
| -rw-r--r-- | src/thread/sh/__set_thread_area.c | 40 | ||||
| -rw-r--r-- | src/thread/sh/__set_thread_area.s | 0 | ||||
| -rw-r--r-- | src/thread/sh/atomics.s | 65 | 
3 files changed, 105 insertions, 0 deletions
diff --git a/src/thread/sh/__set_thread_area.c b/src/thread/sh/__set_thread_area.c new file mode 100644 index 00000000..9c47f78d --- /dev/null +++ b/src/thread/sh/__set_thread_area.c @@ -0,0 +1,40 @@ +#include "pthread_impl.h" +#include "libc.h" +#include <elf.h> + +/* Also perform sh-specific init */ + +#define CPU_HAS_LLSC 0x0040 +#define CPU_HAS_CAS_L 0x0400 + +__attribute__((__visibility__("hidden"))) +extern const char __sh_cas_gusa[], __sh_cas_llsc[], __sh_cas_imask[], __sh_cas_cas_l[]; + +__attribute__((__visibility__("hidden"))) +const void *__sh_cas_ptr; + +__attribute__((__visibility__("hidden"))) +unsigned __sh_nommu; + +int __set_thread_area(void *p) +{ +	size_t *aux; +	__asm__ __volatile__ ( "ldc %0, gbr" : : "r"(p) : "memory" ); +#ifndef __SH4A__ +	__sh_cas_ptr = __sh_cas_gusa; +#if !defined(__SH3__) && !defined(__SH4__) +	for (aux=libc.auxv; *aux; aux+=2) { +		if (*aux != AT_PLATFORM) continue; +		const char *s = (void *)aux[1]; +		if (s[0]!='s' || s[1]!='h' || s[2]!='2' || s[3]-'0'<10u) break; +		__sh_cas_ptr = __sh_cas_imask; +		__sh_nommu = 1; +	} +#endif +	if (__hwcap & CPU_HAS_CAS_L) +		__sh_cas_ptr = __sh_cas_cas_l; +	else if (__hwcap & CPU_HAS_LLSC) +		__sh_cas_ptr = __sh_cas_llsc; +#endif +	return 0; +} diff --git a/src/thread/sh/__set_thread_area.s b/src/thread/sh/__set_thread_area.s deleted file mode 100644 index e69de29b..00000000 --- a/src/thread/sh/__set_thread_area.s +++ /dev/null diff --git a/src/thread/sh/atomics.s b/src/thread/sh/atomics.s new file mode 100644 index 00000000..3b58cccc --- /dev/null +++ b/src/thread/sh/atomics.s @@ -0,0 +1,65 @@ +/* Contract for all versions is same as cas.l r2,r3,@r0 + * pr and r1 are also clobbered (by jsr & r1 as temp). + * r0,r2,r4-r15 must be preserved. + * r3 contains result (==r2 iff cas succeeded). */ + +	.align 2 +.global __sh_cas_gusa +.hidden __sh_cas_gusa +__sh_cas_gusa: +	mov.l r5,@-r15 +	mov.l r4,@-r15 +	mov r0,r4 +	mova 1f,r0 +	mov r15,r1 +	mov #(0f-1f),r15 +0:	mov.l @r4,r5 +	cmp/eq r5,r2 +	bf 1f +	mov.l r3,@r4 +1:	mov r1,r15 +	mov r5,r3 +	mov r4,r0 +	mov.l @r15+,r4 +	rts +	 mov.l @r15+,r5 + +.global __sh_cas_llsc +.hidden __sh_cas_llsc +__sh_cas_llsc: +	mov r0,r1 +	synco +0:	movli.l @r1,r0 +	cmp/eq r0,r2 +	bf 1f +	mov r3,r0 +	movco.l r0,@r1 +	bf 0b +	mov r2,r0 +1:	synco +	mov r0,r3 +	rts +	 mov r1,r0 + +.global __sh_cas_imask +.hidden __sh_cas_imask +__sh_cas_imask: +	mov r0,r1 +	stc sr,r0 +	mov.l r0,@-r15 +	or #0xf0,r0 +	ldc r0,sr +	mov.l @r1,r0 +	cmp/eq r0,r2 +	bf 1f +	mov.l r3,@r1 +1:	ldc.l @r15+,sr +	mov r0,r3 +	rts +	 mov r1,r0 + +.global __sh_cas_cas_l +.hidden __sh_cas_cas_l +__sh_cas_cas_l: +	rts +	 .word 0x2323 /* cas.l r2,r3,@r0 */  | 
