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