xref: /haiku/src/system/libroot/os/arch/m68k/atomic.S (revision 6e927a5fc080cb934e7584454f472cacf4c3e361)
1/*
2** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3** Distributed under the terms of the OpenBeOS License.
4*/
5
6/*
7 * gcc/config/m68k/m68k.h:CALL_USED_REGISTERS:
8 * d0,d1,a0,a1 are scratch regs, not to be saved.
9 */
10
11/*
12 * see http://mail-index.netbsd.org/amiga/1995/06/
13 * for concerns about TAS, CAS and Amiga.
14 * I suppose as long as we don't use it on a variable in
15 * chip ram it shouldn't be a problem, and since we don't
16 * have any SMP Amiga anyway it should be ok.
17 */
18
19#define FUNCTION(x) .global x; .type x,@function; x
20
21.text
22
23/* int atomic_add(int *value, int increment)
24 */
25FUNCTION(atomic_add):
26		move.l	(4,%a7),%a0
27		move.l	(%a0),%d0
28miss1:	move.l	%d0,%d1
29		add.l	(8,%a7),%d1
30		cas.l	%d0,%d1,(%a0)
31		bne		miss1
32		// d0 = old value
33		rts
34
35/* int atomic_and(int *value, int andValue)
36 */
37FUNCTION(atomic_and):
38		move.l	(4,%a7),%a0
39		move.l	(%a0),%d0
40miss2:	move.l	%d0,%d1
41		and.l	(8,%a7),%d1
42		cas.l	%d0,%d1,(%a0)
43		bne		miss2
44		// d0 = old value
45		rts
46
47/* int atomic_or(int *value, int orValue)
48 */
49FUNCTION(atomic_or):
50		move.l	(4,%a7),%a0
51		move.l	(%a0),%d0
52miss3:	move.l	%d0,%d1
53		or.l	(8,%a7),%d1
54		cas.l	%d0,%d1,(%a0)
55		bne		miss3
56		rts
57
58/* int atomic_set(int *value, int setTo)
59 */
60FUNCTION(atomic_set):
61		move.l	(4,%a7),%a0
62		move.l	(%a0),%d0
63		move.l	(8,%a7),%d1
64miss4:	cas.l	%d0,%d1,(%a0)
65		bne		miss4
66		rts
67
68/* int atomic_test_and_set(int *value, int setTo, int testValue)
69 */
70FUNCTION(atomic_test_and_set):
71		move.l	(4,%a7),%a0
72		move.l	(8,%a7),%d1
73		move.l	(12,%a7),%d0
74		cas.l	%d0,%d1,(%a0)
75		rts
76
77/* int atomic_get(int *value)
78 */
79FUNCTION(atomic_get):
80		move.l	(4,%a7),%a0
81		move.l	(%a0),%d0
82		move.l	%d0,%d1
83		cas.l	%d0,%d1,(%a0)
84		// we must use cas... so we change to the same value if matching,
85		// else we get the correct one anyway
86		rts
87
88/* m68k elf convention is to return structs in (a0) */
89/* other conventions use d0/d1 but which is MSB ?? */
90#warning M68K: 68060 doesn't have CAS2: use spinlock ??
91/* see http://retropc.net/x68000/software/develop/as/has060/m68k.htm */
92
93/* int64	atomic_add64(vint64 *value, int64 addValue) */
94FUNCTION(atomic_add64):
95		move.l	%d2,-(%a7)
96		move.l	%d3,-(%a7)
97		move.l	%a2,-(%a7)
98		move.l	(4,%a7),%a1
99		lea.l	(4,%a1),%a2
100		// addValue
101		move.l	(12,%a7),%d2	/*LSB*/
102		move.l	(8,%a7),%d3		/*MSB*/
103miss5:	// old value
104		move.l	(4,%a1),%d0		/*LSB*/
105		move.l	(%a1),%d1		/*MSB*/
106		add.l	%d0,%d2
107		addx.l	%d1,%d3
108		cas2.l	%d0:%d1,%d2:%d3,(%a2):(%a1)
109		bne		miss5
110		// return value
111		move.l	%d0,(4,%a0)
112		move.l	%d1,(%a0)
113		move.l	(%a7)+,%a2
114		move.l	(%a7)+,%d3
115		move.l	(%a7)+,%d2
116		rts
117
118/* int64	atomic_and64(vint64 *value, int64 andValue) */
119FUNCTION(atomic_and64):
120		move.l	%d2,-(%a7)
121		move.l	%d3,-(%a7)
122		move.l	%a2,-(%a7)
123		move.l	(4,%a7),%a1
124		lea.l	(4,%a1),%a2
125		// addValue
126		move.l	(12,%a7),%d2	/*LSB*/
127		move.l	(8,%a7),%d3		/*MSB*/
128miss6:	// old value
129		move.l	(4,%a1),%d0		/*LSB*/
130		move.l	(%a1),%d1		/*MSB*/
131		and.l	%d0,%d2
132		and.l	%d1,%d3
133		cas2.l	%d0:%d1,%d2:%d3,(%a2):(%a1)
134		bne		miss6
135		// return value
136		move.l	%d0,(4,%a0)
137		move.l	%d1,(%a0)
138		move.l	(%a7)+,%a2
139		move.l	(%a7)+,%d3
140		move.l	(%a7)+,%d2
141		rts
142
143/* int64	atomic_or64(vint64 *value, int64 orValue) */
144FUNCTION(atomic_or64):
145		move.l	%d2,-(%a7)
146		move.l	%d3,-(%a7)
147		move.l	%a2,-(%a7)
148		move.l	(4,%a7),%a1
149		lea.l	(4,%a1),%a2
150		// addValue
151		move.l	(12,%a7),%d2	/*LSB*/
152		move.l	(8,%a7),%d3		/*MSB*/
153miss7:	// old value
154		move.l	(4,%a1),%d0		/*LSB*/
155		move.l	(%a1),%d1		/*MSB*/
156		or.l	%d0,%d2
157		or.l	%d1,%d3
158		cas2.l	%d0:%d1,%d2:%d3,(%a2):(%a1)
159		bne		miss7
160		// return value
161		move.l	%d0,(4,%a0)
162		move.l	%d1,(%a0)
163		move.l	(%a7)+,%a2
164		move.l	(%a7)+,%d3
165		move.l	(%a7)+,%d2
166		rts
167
168/* int64	atomic_set64(vint64 *value, int64 newValue) */
169FUNCTION(atomic_set64):
170		move.l	%d2,-(%a7)
171		move.l	%d3,-(%a7)
172		move.l	%a2,-(%a7)
173		move.l	(4,%a7),%a1
174		lea.l	(4,%a1),%a2
175		// new value
176		move.l	(12,%a7),%d2	/*LSB*/
177		move.l	(8,%a7),%d3		/*MSB*/
178		// old value
179		move.l	(4,%a1),%d0		/*LSB*/
180		move.l	(%a1),%d1		/*MSB*/
181miss8:	cas2.l	%d0:%d1,%d2:%d3,(%a2):(%a1)
182		bne		miss8
183		// return value
184		move.l	%d0,(4,%a0)
185		move.l	%d1,(%a0)
186		move.l	(%a7)+,%a2
187		move.l	(%a7)+,%d3
188		move.l	(%a7)+,%d2
189		rts
190
191/* int64	atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst) */
192FUNCTION(atomic_test_and_set64):
193		move.l	%d2,-(%a7)
194		move.l	%d3,-(%a7)
195		move.l	%a2,-(%a7)
196		move.l	(4,%a7),%a1
197		lea.l	(4,%a1),%a2
198		// new value
199		move.l	(12,%a7),%d2	/*LSB*/
200		move.l	(8,%a7),%d3		/*MSB*/
201		// test against value
202		move.l	(20,%a7),%d0	/*LSB*/
203		move.l	(16,%a7),%d1	/*MSB*/
204		cas2.l	%d0:%d1,%d2:%d3,(%a2):(%a1)
205		// return value
206		move.l	%d0,(4,%a0)
207		move.l	%d1,(%a0)
208		move.l	(%a7)+,%a2
209		move.l	(%a7)+,%d3
210		move.l	(%a7)+,%d2
211		rts
212
213/* int64	atomic_get64(vint64 *value) */
214FUNCTION(atomic_get64):
215		move.l	%d2,-(%a7)
216		move.l	%d3,-(%a7)
217		move.l	%a2,-(%a7)
218		move.l	(4,%a7),%a1
219		lea.l	(4,%a1),%a2
220		move.l	(4,%a1),%d0	/*LSB*/
221		move.l	(%a1),%d1		/*MSB*/
222		move.l	%d0,%d2
223		move.l	%d1,%d3
224		// we must use cas... so we change to the same value if matching,
225		// else we get the correct one anyway
226		cas2.l	%d0:%d1,%d2:%d3,(%a2):(%a1)
227		// return value
228		move.l	%d0,(4,%a0)
229		move.l	%d1,(%a0)
230		move.l	(%a7)+,%a2
231		move.l	(%a7)+,%d3
232		move.l	(%a7)+,%d2
233		rts
234
235