1ce95e1b3SDavid du Colombier/* 2ce95e1b3SDavid du Colombier * RISC-V atomic operations 3ce95e1b3SDavid du Colombier * assumes A extension 4ce95e1b3SDavid du Colombier */ 5ce95e1b3SDavid du Colombier 6ce95e1b3SDavid du Colombier#define LINK R1 7ce95e1b3SDavid du Colombier#define SP R2 8ce95e1b3SDavid du Colombier#define ARG 8 9ce95e1b3SDavid du Colombier 10ce95e1b3SDavid du Colombier#define SYNC WORD $0xf /* FENCE */ 11ce95e1b3SDavid du Colombier#define LRW(rs2, rs1, rd) \ 12ce95e1b3SDavid du Colombier WORD $((2<<27)|( 0<<20)|((rs1)<<15)|(2<<12)|((rd)<<7)|057) 13ce95e1b3SDavid du Colombier#define SCW(rs2, rs1, rd) \ 14ce95e1b3SDavid du Colombier WORD $((3<<27)|((rs2)<<20)|((rs1)<<15)|(2<<12)|((rd)<<7)|057) 15ce95e1b3SDavid du Colombier 16ce95e1b3SDavid du ColombierTEXT ainc(SB), 1, $-4 /* long ainc(long *); */ 17ce95e1b3SDavid du Colombier MOVW R(ARG), R12 /* address of counter */ 18ce95e1b3SDavid du Colombier SYNC 19ce95e1b3SDavid du Colombierloop: 20ce95e1b3SDavid du Colombier MOVW $1, R13 21ce95e1b3SDavid du Colombier LRW(0, 12, ARG) // LR_W R0, R12, R(ARG) /* (R12) -> R(ARG) */ 22ce95e1b3SDavid du Colombier ADD R(ARG), R13 23ce95e1b3SDavid du Colombier MOVW R13, R(ARG) /* return new value */ 24ce95e1b3SDavid du Colombier SCW(13, 12, 14) // SC_W R13, R12, R14 /* R13 -> (R12) maybe, R14=0 if ok */ 25ce95e1b3SDavid du Colombier BNE R14, loop 26*daa84c13SDavid du Colombier SYNC 27ce95e1b3SDavid du Colombier RET 28ce95e1b3SDavid du Colombier 29ce95e1b3SDavid du ColombierTEXT adec(SB), 1, $-4 /* long adec(long*); */ 30ce95e1b3SDavid du Colombier MOVW R(ARG), R12 /* address of counter */ 31ce95e1b3SDavid du Colombier SYNC 32ce95e1b3SDavid du Colombierloop1: 33ce95e1b3SDavid du Colombier MOVW $-1, R13 34ce95e1b3SDavid du Colombier LRW(0, 12, ARG) // LR_W R0, R12, R(ARG) /* (R12) -> R(ARG) */ 35ce95e1b3SDavid du Colombier ADD R(ARG), R13 36ce95e1b3SDavid du Colombier MOVW R13, R(ARG) /* return new value */ 37ce95e1b3SDavid du Colombier SCW(13, 12, 14) // SC_W R13, R12, R14 /* R13 -> (R12) maybe, R14=0 if ok */ 38ce95e1b3SDavid du Colombier BNE R14, loop1 39*daa84c13SDavid du Colombier SYNC 40ce95e1b3SDavid du Colombier RET 41ce95e1b3SDavid du Colombier 42ce95e1b3SDavid du Colombier/* 43ce95e1b3SDavid du Colombier * int cas(uint* p, int ov, int nv); 44ce95e1b3SDavid du Colombier * 45ce95e1b3SDavid du Colombier * compare-and-swap: atomically set *addr to nv only if it contains ov, 46ce95e1b3SDavid du Colombier * and returns the old value. this version returns 0 on success, -1 on failure 47ce95e1b3SDavid du Colombier * instead. 48ce95e1b3SDavid du Colombier */ 49ce95e1b3SDavid du ColombierTEXT cas(SB), 1, $-4 50ce95e1b3SDavid du ColombierTEXT casp(SB), 1, $-4 51ce95e1b3SDavid du Colombier MOVW ov+4(FP), R12 52ce95e1b3SDavid du Colombier MOVW nv+8(FP), R13 53ce95e1b3SDavid du Colombier SYNC 54ce95e1b3SDavid du Colombierspincas: 55ce95e1b3SDavid du Colombier LRW(0, ARG, 14) // LR_W R0, R(ARG), R14 /* (R(ARG)) -> R14 */ 56ce95e1b3SDavid du Colombier BNE R12, R14, fail 57ce95e1b3SDavid du Colombier SCW(13, ARG, 14) // SC_W R13, R(ARG), R14 /* R13 -> (R(ARG)) maybe, R14=0 if ok */ 58ce95e1b3SDavid du Colombier BNE R14, spincas /* R14 != 0 means store failed */ 59ce95e1b3SDavid du Colombier MOVW $1, R(ARG) 60ce95e1b3SDavid du Colombier RET 61ce95e1b3SDavid du Colombierfail: 62ce95e1b3SDavid du Colombier MOVW R0, R(ARG) 63ce95e1b3SDavid du Colombier RET 64