xref: /plan9-contrib/sys/src/libc/riscv/atom.s (revision daa84c13685faaac204752d173a8404108c32ce7)
1ce95e1b3SDavid du Colombier/*
2ce95e1b3SDavid du Colombier *	RISC-V atomic operations
3ce95e1b3SDavid du Colombier *	assumes A extension
4ce95e1b3SDavid du Colombier */
5ce95e1b3SDavid du Colombier
6ce95e1b3SDavid du Colombier#define LINK	R1
7ce95e1b3SDavid du Colombier#define SP	R2
8ce95e1b3SDavid du Colombier#define ARG	8
9ce95e1b3SDavid du Colombier
10ce95e1b3SDavid du Colombier#define SYNC	WORD $0xf	/* FENCE */
11ce95e1b3SDavid du Colombier#define LRW(rs2, rs1, rd) \
12ce95e1b3SDavid du Colombier	WORD $((2<<27)|(    0<<20)|((rs1)<<15)|(2<<12)|((rd)<<7)|057)
13ce95e1b3SDavid du Colombier#define SCW(rs2, rs1, rd) \
14ce95e1b3SDavid du Colombier	WORD $((3<<27)|((rs2)<<20)|((rs1)<<15)|(2<<12)|((rd)<<7)|057)
15ce95e1b3SDavid du Colombier
16ce95e1b3SDavid du ColombierTEXT ainc(SB), 1, $-4			/* long ainc(long *); */
17ce95e1b3SDavid du Colombier	MOVW	R(ARG), R12		/* address of counter */
18ce95e1b3SDavid du Colombier	SYNC
19ce95e1b3SDavid du Colombierloop:
20ce95e1b3SDavid du Colombier	MOVW	$1, R13
21ce95e1b3SDavid du Colombier	LRW(0, 12, ARG)	// LR_W	R0, R12, R(ARG) /* (R12) -> R(ARG) */
22ce95e1b3SDavid du Colombier	ADD	R(ARG), R13
23ce95e1b3SDavid du Colombier	MOVW	R13, R(ARG)		/* return new value */
24ce95e1b3SDavid du Colombier	SCW(13, 12, 14)	// SC_W	R13, R12, R14 /* R13 -> (R12) maybe, R14=0 if ok */
25ce95e1b3SDavid du Colombier	BNE	R14, loop
26*daa84c13SDavid du Colombier	SYNC
27ce95e1b3SDavid du Colombier	RET
28ce95e1b3SDavid du Colombier
29ce95e1b3SDavid du ColombierTEXT adec(SB), 1, $-4			/* long adec(long*); */
30ce95e1b3SDavid du Colombier	MOVW	R(ARG), R12		/* address of counter */
31ce95e1b3SDavid du Colombier	SYNC
32ce95e1b3SDavid du Colombierloop1:
33ce95e1b3SDavid du Colombier	MOVW	$-1, R13
34ce95e1b3SDavid du Colombier	LRW(0, 12, ARG)	// LR_W	R0, R12, R(ARG) /* (R12) -> R(ARG) */
35ce95e1b3SDavid du Colombier	ADD	R(ARG), R13
36ce95e1b3SDavid du Colombier	MOVW	R13, R(ARG)		/* return new value */
37ce95e1b3SDavid du Colombier	SCW(13, 12, 14)	// SC_W R13, R12, R14 /* R13 -> (R12) maybe, R14=0 if ok */
38ce95e1b3SDavid du Colombier	BNE	R14, loop1
39*daa84c13SDavid du Colombier	SYNC
40ce95e1b3SDavid du Colombier	RET
41ce95e1b3SDavid du Colombier
42ce95e1b3SDavid du Colombier/*
43ce95e1b3SDavid du Colombier * int cas(uint* p, int ov, int nv);
44ce95e1b3SDavid du Colombier *
45ce95e1b3SDavid du Colombier * compare-and-swap: atomically set *addr to nv only if it contains ov,
46ce95e1b3SDavid du Colombier * and returns the old value.  this version returns 0 on success, -1 on failure
47ce95e1b3SDavid du Colombier * instead.
48ce95e1b3SDavid du Colombier */
49ce95e1b3SDavid du ColombierTEXT cas(SB), 1, $-4
50ce95e1b3SDavid du ColombierTEXT casp(SB), 1, $-4
51ce95e1b3SDavid du Colombier	MOVW	ov+4(FP), R12
52ce95e1b3SDavid du Colombier	MOVW	nv+8(FP), R13
53ce95e1b3SDavid du Colombier	SYNC
54ce95e1b3SDavid du Colombierspincas:
55ce95e1b3SDavid du Colombier	LRW(0, ARG, 14)	// LR_W	R0, R(ARG), R14 /* (R(ARG)) -> R14 */
56ce95e1b3SDavid du Colombier	BNE	R12, R14, fail
57ce95e1b3SDavid du Colombier	SCW(13, ARG, 14) // SC_W R13, R(ARG), R14 /* R13 -> (R(ARG)) maybe, R14=0 if ok */
58ce95e1b3SDavid du Colombier	BNE	R14, spincas	/* R14 != 0 means store failed */
59ce95e1b3SDavid du Colombier	MOVW	$1, R(ARG)
60ce95e1b3SDavid du Colombier	RET
61ce95e1b3SDavid du Colombierfail:
62ce95e1b3SDavid du Colombier	MOVW	R0, R(ARG)
63ce95e1b3SDavid du Colombier	RET
64