xref: /haiku/src/system/libroot/os/arch/m68k/atomic.S (revision 020cbad9d40235a2c50a81a42d69912a5ff8fbc4)
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 * but use d0/d1 for int64 and small structs.
90 * d0 MSB, d1 LSB
91 */
92#warning M68K: 68060 doesn't have CAS2: use spinlock ??
93/* see http://retropc.net/x68000/software/develop/as/has060/m68k.htm */
94
95/* int64	atomic_add64(vint64 *value, int64 addValue) */
96FUNCTION(atomic_add64):
97		movem.l	%d2-%d3/%a2,-(%a7)
98		move.l	(4,%a7),%a2
99		lea.l	(4,%a2),%a1
100		// addValue
101		move.l	(12,%a7),%d3	/*LSB*/
102		move.l	(8,%a7),%d2		/*MSB*/
103miss5:	// old value
104		move.l	(%a1),%d1		/*LSB*/
105		move.l	(%a2),%d0		/*MSB*/
106		add.l	%d1,%d3
107		addx.l	%d0,%d2
108		cas2.l	%d0:%d1,%d2:%d3,(%a2):(%a1)
109		bne		miss5
110		// return value d0:d1
111		movem.l	(%a7)+,%d2-%d3/%a2
112		rts
113
114/* int64	atomic_and64(vint64 *value, int64 andValue) */
115FUNCTION(atomic_and64):
116		movem.l	%d2-%d3/%a2,-(%a7)
117		move.l	(4,%a7),%a2
118		lea.l	(4,%a2),%a1
119		// addValue
120		move.l	(12,%a7),%d3	/*LSB*/
121		move.l	(8,%a7),%d2		/*MSB*/
122miss6:	// old value
123		move.l	(%a1),%d1		/*LSB*/
124		move.l	(%a2),%d0		/*MSB*/
125		and.l	%d1,%d3
126		and.l	%d0,%d2
127		cas2.l	%d0:%d1,%d2:%d3,(%a2):(%a1)
128		bne		miss6
129		// return value d0:d1
130		movem.l	(%a7)+,%d2-%d3/%a2
131		rts
132
133/* int64	atomic_or64(vint64 *value, int64 orValue) */
134FUNCTION(atomic_or64):
135		movem.l	%d2-%d3/%a2,-(%a7)
136		move.l	(4,%a7),%a2
137		lea.l	(4,%a2),%a1
138		// addValue
139		move.l	(12,%a7),%d3	/*LSB*/
140		move.l	(8,%a7),%d2		/*MSB*/
141miss7:	// old value
142		move.l	(%a1),%d1		/*LSB*/
143		move.l	(%a2),%d0		/*MSB*/
144		or.l	%d1,%d3
145		or.l	%d0,%d2
146		cas2.l	%d0:%d1,%d2:%d3,(%a2):(%a1)
147		bne		miss7
148		// return value d0:d1
149		movem.l	(%a7)+,%d2-%d3/%a2
150		rts
151
152/* int64	atomic_set64(vint64 *value, int64 newValue) */
153FUNCTION(atomic_set64):
154		movem.l	%d2-%d3/%a2,-(%a7)
155		move.l	(4,%a7),%a2
156		lea.l	(4,%a2),%a1
157		// new value
158		move.l	(12,%a7),%d3	/*LSB*/
159		move.l	(8,%a7),%d2		/*MSB*/
160		// old value
161		move.l	(%a1),%d1		/*LSB*/
162		move.l	(%a2),%d0		/*MSB*/
163miss8:	cas2.l	%d0:%d1,%d2:%d3,(%a2):(%a1)
164		bne		miss8
165		// return value d0:d1
166		movem.l	(%a7)+,%d2-%d3/%a2
167		rts
168
169/* int64	atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst) */
170FUNCTION(atomic_test_and_set64):
171		movem.l	%d2-%d3/%a2,-(%a7)
172		move.l	(4,%a7),%a2
173		lea.l	(4,%a2),%a1
174		// new value
175		move.l	(12,%a7),%d3	/*LSB*/
176		move.l	(8,%a7),%d2		/*MSB*/
177		// test against value
178		move.l	(20,%a7),%d1	/*LSB*/
179		move.l	(16,%a7),%d0	/*MSB*/
180		cas2.l	%d0:%d1,%d2:%d3,(%a2):(%a1)
181		// return value d0:d1
182		movem.l	(%a7)+,%d2-%d3/%a2
183		rts
184
185/* int64	atomic_get64(vint64 *value) */
186FUNCTION(atomic_get64):
187		movem.l	%d2-%d3/%a2,-(%a7)
188		move.l	(4,%a7),%a2
189		lea.l	(4,%a2),%a1
190		move.l	(%a1),%d1	/*LSB*/
191		move.l	(%a2),%d0		/*MSB*/
192		move.l	%d1,%d3
193		move.l	%d0,%d2
194		// we must use cas... so we change to the same value if matching,
195		// else we get the correct one anyway
196		cas2.l	%d0:%d1,%d2:%d3,(%a2):(%a1)
197		// return value
198		movem.l	(%a7)+,%d2-%d3/%a2
199		rts
200
201