< 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,10 +1167,62 @@
#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 >