< 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 >