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