< prev index next >

src/cpu/aarch64/vm/assembler_aarch64.hpp

Print this page
rev 10243 : 8150394: aarch64: add support for 8.1 LSE CAS instructions
Reviewed-by: aph
Contributed-by: ananth.jasty@caviumnetworks.com, edward.nevill@linaro.org

*** 1167,1176 **** --- 1167,1228 ---- #undef INSN2 #undef INSN3 #undef INSN4 #undef INSN_FOO + // 8.1 Compare and swap extensions + void compare_and_swap(Register Rs, Register Rt, Register Rn, + enum operand_size sz, int a, int r, int op=1) { + starti; + if (op == 0) { // Pair + assert(sz == word || sz == xword, "invalid size"); + /* The size bit is in bit 30, not 31 */ + sz = (operand_size)(sz == word ? 0b00:0b01); + } + f(sz, 31, 30), f(0b001000, 29, 24), f(1, 23), f(a, 22), f(1, 21); + rf(Rs, 16), f(r, 15), f(0b11111, 14, 10), rf(Rn, 5), rf(Rt, 0); + } + + // Export these parameterised versions for use in cmpxchg + // sz, a, and r may be passed as parameters + void cas_load(operand_size sz, Register Rt, Register Rn, int a) { + load_store_exclusive((Register)0b11111, Rt, (Register)0b11111, + Rn, sz, 0b010, a); + } + void cas_store(operand_size sz, Register Rs, + Register Rt, Register Rn, int r) { + load_store_exclusive(Rs, Rt, (Register)0b1111, Rn, sz, 0b000, r); + } + + // CAS + #define INSN(NAME, a, r) \ + void NAME(operand_size sz, Register Rs, Register Rt, Register Rn) { \ + assert(Rs != Rn && Rs != Rt, "unpredictable instruction"); \ + compare_and_swap(Rs, Rt, Rn, sz, a, r); \ + } + INSN(cas, 0, 0) + INSN(casa, 1, 0) + INSN(casl, 0, 1) + INSN(casal, 1, 1) + #undef INSN + + // CASP + #define INSN(NAME, a, r) \ + void NAME(operand_size sz, Register Rs, Register Rs1, \ + Register Rt, Register Rt1, Register Rn) { \ + assert((Rs->encoding() & 1) == 0 && (Rt->encoding() & 1) == 0 && \ + Rs->successor() == Rs1 && Rt->successor() == Rt1 && \ + Rs != Rn && Rs1 != Rn && Rs != Rt, "invalid registers"); \ + assert(sz == word || sz == xword, "invalid size"); \ + compare_and_swap(Rs, Rt, Rn, sz, a, r, 0); \ + } + INSN(casp, 0, 0) + INSN(caspa, 1, 0) + INSN(caspl, 0, 1) + INSN(caspal, 1, 1) + #undef INSN + // Load register (literal) #define INSN(NAME, opc, V) \ void NAME(Register Rt, address dest) { \ long offset = (dest - pc()) >> 2; \ starti; \
< prev index next >