mailing list of musl libc
 help / color / mirror / code / Atom feed
133956734d0d96c7b0e1b5dc52512ac785172eb2 blob 3563 bytes (raw)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
 
#include "libc.h"

#define LLSC_CLOBBERS   "r0", "t", "memory"
#define LLSC_START(mem) "synco\n"  \
	"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__(
			"	synco\n"
			"	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);
	}
}
debug log:

solving 1339567 ...
found 1339567 in https://git.vuxu.org/mirror/musl/

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).