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