diff options
| author | Rich Felker <dalias@aerifal.cx> | 2014-02-27 22:03:25 -0500 | 
|---|---|---|
| committer | Rich Felker <dalias@aerifal.cx> | 2014-02-27 22:03:25 -0500 | 
| commit | aacd348637e38795dd7ae3c7c8c908d8c0cd24fd (patch) | |
| tree | 3055797eea08dafe99dcdbd1e7efabd44bcb723b /arch/sh/src | |
| parent | b9f7f2e8762922a1a24d41358164ebe9ae437e31 (diff) | |
| download | musl-aacd348637e38795dd7ae3c7c8c908d8c0cd24fd.tar.gz | |
rename superh port to "sh" for consistency
linux, gcc, etc. all use "sh" as the name for the superh arch. there
was already some inconsistency internally in musl: the dynamic linker
was searching for "ld-musl-sh.path" as its path file despite its own
name being "ld-musl-superh.so.1". there was some sentiment in both
directions as to how to resolve the inconsistency, but overall "sh"
was favored.
Diffstat (limited to 'arch/sh/src')
| -rw-r--r-- | arch/sh/src/__fpsrc_values.c | 2 | ||||
| -rw-r--r-- | arch/sh/src/atomic.c | 146 | 
2 files changed, 148 insertions, 0 deletions
diff --git a/arch/sh/src/__fpsrc_values.c b/arch/sh/src/__fpsrc_values.c new file mode 100644 index 00000000..56056617 --- /dev/null +++ b/arch/sh/src/__fpsrc_values.c @@ -0,0 +1,2 @@ +/* used by gcc for switching the FPU between single and double precision */ +const unsigned long __fpscr_values[2] = { 0, 0x80000 }; diff --git a/arch/sh/src/atomic.c b/arch/sh/src/atomic.c new file mode 100644 index 00000000..d29b0538 --- /dev/null +++ b/arch/sh/src/atomic.c @@ -0,0 +1,146 @@ +#include "libc.h" + +#define LLSC_CLOBBERS   "r0", "t", "memory" +#define LLSC_START(mem)            \ +	"0:	movli.l @" mem ", r0\n" +#define LLSC_END(mem)              \ +	"1:	movco.l r0, @" mem "\n"    \ +	"	bf 0b\n"                   \ +	"	synco\n" + +/* gusa is a hack in the kernel which lets you create a sequence of instructions + * which will be restarted if the process is preempted in the middle of the + * sequence. It will do for implementing atomics on non-smp systems. ABI is: + * r0  = address of first instruction after the atomic sequence + * r1  = original stack pointer + * r15 = -1 * length of atomic sequence in bytes + */ +#define GUSA_CLOBBERS   "r0", "r1", "memory" +#define GUSA_START(mem,old,nop)    \ +	"	.align 2\n"                \ +	"	mova 1f, r0\n"             \ +	nop                            \ +	"	mov r15, r1\n"             \ +	"	mov #(0f-1f), r15\n"       \ +	"0:	mov.l @" mem ", " old "\n" +/* the target of mova must be 4 byte aligned, so we may need a nop */ +#define GUSA_START_ODD(mem,old)  GUSA_START(mem,old,"") +#define GUSA_START_EVEN(mem,old) GUSA_START(mem,old,"\tnop\n") +#define GUSA_END(mem,new)          \ +	"	mov.l " new ", @" mem "\n" \ +	"1:	mov r1, r15\n" + +#define CPU_HAS_LLSC 0x0040 + +int __sh_cas(volatile int *p, int t, int s) +{ +	int old; +	if (__hwcap & CPU_HAS_LLSC) { +		__asm__ __volatile__( +			LLSC_START("%1") +			"	mov r0, %0\n" +			"	cmp/eq %0, %2\n" +			"	bf 1f\n" +			"	mov %3, r0\n" +			LLSC_END("%1") +			: "=&r"(old) : "r"(p), "r"(t), "r"(s) : LLSC_CLOBBERS); +	} else { +		__asm__ __volatile__( +			GUSA_START_EVEN("%1", "%0") +			"	cmp/eq %0, %2\n" +			"	bf 1f\n" +			GUSA_END("%1", "%3") +			: "=&r"(old) : "r"(p), "r"(t), "r"(s) : GUSA_CLOBBERS, "t"); +	} +	return old; +} + +int __sh_swap(volatile int *x, int v) +{ +	int old; +	if (__hwcap & CPU_HAS_LLSC) { +		__asm__ __volatile__( +			LLSC_START("%1") +			"	mov r0, %0\n" +			"	mov %2, r0\n" +			LLSC_END("%1") +			: "=&r"(old) : "r"(x), "r"(v) : LLSC_CLOBBERS); +	} else { +		__asm__ __volatile__( +			GUSA_START_EVEN("%1", "%0") +			GUSA_END("%1", "%2") +			: "=&r"(old) : "r"(x), "r"(v) : GUSA_CLOBBERS); +	} +	return old; +} + +int __sh_fetch_add(volatile int *x, int v) +{ +	int old, dummy; +	if (__hwcap & CPU_HAS_LLSC) { +		__asm__ __volatile__( +			LLSC_START("%1") +			"	mov r0, %0\n" +			"	add %2, r0\n" +			LLSC_END("%1") +			: "=&r"(old) : "r"(x), "r"(v) : LLSC_CLOBBERS); +	} else { +		__asm__ __volatile__( +			GUSA_START_EVEN("%2", "%0") +			"	mov %0, %1\n" +			"	add %3, %1\n" +			GUSA_END("%2", "%1") +			: "=&r"(old), "=&r"(dummy) : "r"(x), "r"(v) : GUSA_CLOBBERS); +	} +	return old; +} + +void __sh_store(volatile int *p, int x) +{ +	if (__hwcap & CPU_HAS_LLSC) { +		__asm__ __volatile__( +			"	mov.l %1, @%0\n" +			"	synco\n" +			: : "r"(p), "r"(x) : "memory"); +	} else { +		__asm__ __volatile__( +			"	mov.l %1, @%0\n" +			: : "r"(p), "r"(x) : "memory"); +	} +} + +void __sh_and(volatile int *x, int v) +{ +	int dummy; +	if (__hwcap & CPU_HAS_LLSC) { +		__asm__ __volatile__( +			LLSC_START("%0") +			"	and %1, r0\n" +			LLSC_END("%0") +			: : "r"(x), "r"(v) : LLSC_CLOBBERS); +	} else { +		__asm__ __volatile__( +			GUSA_START_ODD("%1", "%0") +			"	and %2, %0\n" +			GUSA_END("%1", "%0") +			: "=&r"(dummy) : "r"(x), "r"(v) : GUSA_CLOBBERS); +	} +} + +void __sh_or(volatile int *x, int v) +{ +	int dummy; +	if (__hwcap & CPU_HAS_LLSC) { +		__asm__ __volatile__( +			LLSC_START("%0") +			"	or %1, r0\n" +			LLSC_END("%0") +			: : "r"(x), "r"(v) : LLSC_CLOBBERS); +	} else { +		__asm__ __volatile__( +			GUSA_START_ODD("%1", "%0") +			"	or %2, %0\n" +			GUSA_END("%1", "%0") +			: "=&r"(dummy) : "r"(x), "r"(v) : GUSA_CLOBBERS); +	} +}  | 
