xref: /plan9-contrib/sys/src/libc/arm/tas.s (revision 43fc641d02286a1fe4c6ca8065ef945254a88744)
1*43fc641dSDavid du Colombier#define DMB	MCR 15, 0, R0, C7, C10, 5
2*43fc641dSDavid du Colombier#define	STREX(f,tp,r) WORD $(0xe<<28|0x01800f90 | (tp)<<16 | (r)<<12 | (f)<<0)
3*43fc641dSDavid du Colombier#define	LDREX(fp,t)   WORD $(0xe<<28|0x01900f9f | (fp)<<16 | (t)<<12)
4*43fc641dSDavid du Colombier#define	CLREX	WORD	$0xf57ff01f
5*43fc641dSDavid du Colombier
6*43fc641dSDavid du ColombierTEXT	_tas(SB), $-4			/* _tas(ulong *) */
7*43fc641dSDavid du Colombier	/* returns old (R0) after modifying (R0) */
8*43fc641dSDavid du Colombier	MOVW	R0,R5
9*43fc641dSDavid du Colombier	MOVW	$0, R0
10*43fc641dSDavid du Colombier	DMB
11*43fc641dSDavid du Colombier
12*43fc641dSDavid du Colombier	MOVW	$1,R2		/* new value of (R0) */
13*43fc641dSDavid du Colombiertas1:
14*43fc641dSDavid du Colombier	LDREX(5,1)		/* LDREX 0(R5),R1 */
15*43fc641dSDavid du Colombier	CMP.S	$0, R1		/* old value non-zero (lock taken)? */
16*43fc641dSDavid du Colombier	BNE	lockbusy	/* we lose */
17*43fc641dSDavid du Colombier	STREX(2,5,4)		/* STREX R2,(R5),R4 */
18*43fc641dSDavid du Colombier	CMP.S	$0, R4
19*43fc641dSDavid du Colombier	BNE	tas1		/* strex failed? try again */
20*43fc641dSDavid du Colombier	MOVW	$0, R0
21*43fc641dSDavid du Colombier	DMB
22*43fc641dSDavid du Colombier	MOVW	R1, R0
23*43fc641dSDavid du Colombier	RET
24*43fc641dSDavid du Colombierlockbusy:
25*43fc641dSDavid du Colombier	CLREX
26*43fc641dSDavid du Colombier	MOVW	$0, R0
27*43fc641dSDavid du Colombier	DMB
28*43fc641dSDavid du Colombier	MOVW	R1, R0
2980ee5cbfSDavid du Colombier	RET
30