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