// RV64 lock helper // there is 2 part: read and write // write return 0 on success, 1 on fail (value has been changed) .text .align 4 .global rv64_lock_xchg_dd .global rv64_lock_xchg_d .global rv64_lock_storeifnull .global rv64_lock_storeifnull_d .global rv64_lock_storeifref .global rv64_lock_storeifref_d .global rv64_lock_storeifref2_d .global rv64_lock_decifnot0b .global rv64_lock_storeb .global rv64_lock_incif0 .global rv64_lock_decifnot0 .global rv64_lock_store .global rv64_lock_store_dd .global rv64_lock_cas_d .global rv64_lock_cas_dd .global rv64_lock_get_b .global rv64_lock_get_d .global rv64_lock_get_dd rv64_lock_xchg_dd: // address is a0, value is a1, return old value in a0 amoswap.d.aqrl a0, a1, (a0) ret rv64_lock_xchg_d: // address is a0, value is a1, return old value in a0 amoswap.w.aqrl a0, a1, (a0) ret rv64_lock_storeifnull: // address is a0, value is a1, a1 store to a0 only if [a0] is 0. return old [a0] value fence rw, rw 1: lr.d a2, (a0) bnez a2, 2f sc.d a3, a1, (a0) bnez a3, 1b 2: mv a0, a2 ret rv64_lock_storeifnull_d: // address is a0, value is a1, a1 store to a0 only if [a0] is 0. return old [a0] value fence rw, rw 1: lr.w a2, (a0) bnez a2, 2f sc.w a3, a1, (a0) bnez a3, 1b 2: mv a0, a2 ret rv64_lock_storeifref: // address is a0, value is a1, a1 store to a0 only if [a0] is a2. return new [a0] value (so a1 or old value) fence rw, rw 1: lr.d a3, (a0) bne a2, a3, 2f sc.d a4, a1, (a0) bnez a4, 1b fence rw, rw mv a0, a1 ret 2: fence rw, rw mv a0, a3 ret rv64_lock_storeifref_d: // address is a0, value is a1, a1 store to a0 only if [a0] is a2. return new [a0] value (so a1 or old value) fence rw, rw 1: lr.w a3, (a0) bne a2, a3, 2f sc.w a4, a1, (a0) bnez a4, 1b mv a0, a1 ret 2: mv a0, a3 ret rv64_lock_storeifref2_d: // address is a0, value is a1, a1 store to a0 only if [a0] is a2. return old [a0] value fence rw, rw 1: lr.w a3, (a0) bne a2, a3, 2f sc.w a4, a1, (a0) bnez a4, 1b 2: mv a0, a3 ret rv64_lock_decifnot0b: fence rw, rw andi a3, a0, 3 andi a0, a0, ~3 slli a3, a3, 1 //TODO: make a jump table less hacky! la a4, table add a4, a4, a3 jr a4, 10 table: j 1f j rv64_lock_decifnot0b_1 // all those are compressed j rv64_lock_decifnot0b_2 j rv64_lock_decifnot0b_3 1: lr.w a1, (a0) andi a3, a1, 0xff beqz a3, 2f addi a3, a3, -1 andi a1, a1, ~0xff or a1, a1, a3 sc.w a2, a1, (a0) bnez a2, 1b 2: ret rv64_lock_decifnot0b_1: li a4, 0xffff00ff 1: lr.w a1, (a0) srli a3, a1, 8 andi a3, a3, 0xff beqz a3, 2f addi a3, a3, -1 and a1, a1, a4 slli a3, a3, 8 or a1, a1, a3 sc.w a2, a1, (a0) bnez a2, 1b 2: ret rv64_lock_decifnot0b_2: li a4, 0xff00ffff 1: lr.w a1, (a0) srli a3, a1, 16 andi a3, a3, 0xff beqz a3, 2f addi a3, a3, -1 and a1, a1, a4 slli a3, a3, 16 or a1, a1, a3 sc.w a2, a1, (a0) bnez a2, 1b 2: ret rv64_lock_decifnot0b_3: li a4, 0x00ffffff 1: lr.w a1, (a0) srli a3, a1, 24 andi a3, a3, 0xff beqz a3, 2f addi a3, a3, -1 and a1, a1, a4 slli a3, a3, 24 or a1, a1, a3 sc.w a2, a1, (a0) bnez a2, 1b 2: ret rv64_lock_storeb: sb a1, 0(a0) fence rw, rw ret rv64_lock_decifnot0: fence rw, rw 1: lr.w a1, (a0) beqz a1, 2f addi a1, a1, -1 sc.w a2, a1, (a0) bnez a2, 1b 2: mv a0, a1 ret rv64_lock_incif0: fence rw, rw 1: lr.w a1, (a0) bnez a1, 2f addi a1, a1, 1 sc.w a2, a1, (a0) bnez a2, 1b 2: mv a0, a1 ret rv64_lock_store: sw a1, 0(a0) fence rw, rw ret rv64_lock_store_dd: sd a1, 0(a0) fence rw, rw ret rv64_lock_cas_d: lr.w t0, (a0) bne t0, a1, 1f sc.w a0, a2, (a0) ret 1: li a0, 1 ret rv64_lock_cas_dd: lr.d t0, (a0) bne t0, a1, 1f sc.d a0, a2, (a0) ret 1: li a0, 1 ret rv64_lock_get_b: fence rw, rw lb a0, 0(a0) ret rv64_lock_get_d: fence rw, rw lw a0, 0(a0) ret rv64_lock_get_dd: fence rw, rw ld a0, 0(a0) ret