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