xref: /plan9-contrib/sys/src/libc/riscv64/atom.s (revision ce95e1b3727b9cb1c223ffbed69aff21a8ced255)
1/*
2 *	RISC-V atomic operations
3 *	assumes A extension
4 *	LR/SC only work on cached regions
5 */
6
7#define ARG	8
8
9#define MASK(w)	((1<<(w))-1)
10#define FENCE	WORD $(0xf | MASK(8)<<20)  /* all i/o, mem ops before & after */
11#define AQ	(1<<26)			/* acquire */
12#define RL	(1<<25)			/* release */
13#define LRW(rs1, rd) \
14	WORD $((2<<27)|(    0<<20)|((rs1)<<15)|(2<<12)|((rd)<<7)|057|AQ)
15#define SCW(rs2, rs1, rd) \
16	WORD $((3<<27)|((rs2)<<20)|((rs1)<<15)|(2<<12)|((rd)<<7)|057|AQ|RL)
17#define LRD(rs1, rd) \
18	WORD $((2<<27)|(    0<<20)|((rs1)<<15)|(3<<12)|((rd)<<7)|057|AQ)
19#define SCD(rs2, rs1, rd) \
20	WORD $((3<<27)|((rs2)<<20)|((rs1)<<15)|(3<<12)|((rd)<<7)|057|AQ|RL)
21
22
23TEXT adec(SB), 1, $-4			/* long adec(long*); */
24	MOV	$-1, R9
25	JMP	ainctop
26TEXT ainc(SB), 1, $-4			/* long ainc(long *); */
27	MOV	$1, R9
28ainctop:
29	MOV	R(ARG), R12		/* address of counter */
30	FENCE
31loop:
32	LRW(12, ARG)			/* (R12) -> R(ARG) */
33	ADD	R9, R(ARG)		/* return new value */
34	SCW(ARG, 12, 14)		/* R(ARG) -> (R12) maybe, R14=0 if ok */
35	BNE	R14, loop
36	FENCE
37	RET
38
39/*
40 * int cas(uint* p, int ov, int nv);
41 *
42 * compare-and-swap: atomically set *addr to nv only if it contains ov,
43 * and returns the old value.  this version returns 0 on failure, 1 on success
44 * instead.
45 */
46TEXT cas(SB), 1, $-4
47	MOVWU	ov+XLEN(FP), R12
48	MOVWU	nv+(XLEN+4)(FP), R13
49	FENCE
50spincas:
51	LRW(ARG, 14)		/* (R(ARG)) -> R14 */
52	SLL	$32, R14
53	SRL	$32, R14	/* don't sign extend */
54	BNE	R12, R14, fail
55	SCW(13, ARG, 14)	/* R13 -> (R(ARG)) maybe, R14=0 if ok */
56	BNE	R14, spincas	/* R14 != 0 means store failed */
57	MOV	$1, R(ARG)
58	RET
59fail:
60	MOV	R0, R(ARG)
61	RET
62
63/*
64 * int	casp(void **p, void *ov, void *nv);
65 */
66TEXT casp(SB), 1, $-4
67	MOV	ov+XLEN(FP), R12
68	MOV	nv+(2*XLEN)(FP), R13
69	FENCE
70spincasp:
71	LRD(ARG, 14)		/* (R(ARG)) -> R14 */
72	BNE	R12, R14, failp
73	SCD(13, ARG, 14)	/* R13 -> (R(ARG)) maybe, R14=0 if ok */
74	BNE	R14, spincasp	/* R14 != 0 means store failed */
75	MOV	$1, R(ARG)
76	RET
77failp:
78	MOV	R0, R(ARG)
79	RET
80