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