fixed tests
[mono.git] / mono / io-layer / atomic.h
index 85e86b1577e1c2d6f0237129f811bb0abd24a838..8fff350ab987067aabd15a2541e83046bb89d8fc 100644 (file)
@@ -588,6 +588,7 @@ static inline gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 ex
        __asm__ __volatile__ (    "0:\n\t"
                                  "ldr %1, [%2]\n\t"
                                  "cmp %1, %4\n\t"
+                                 "mov %0, %1\n\t"
                                  "bne 1f\n\t"
                                  "swp %0, %3, [%2]\n\t"
                                  "cmp %0, %1\n\t"
@@ -608,6 +609,7 @@ static inline gpointer InterlockedCompareExchangePointer(volatile gpointer *dest
        __asm__ __volatile__ (    "0:\n\t"
                                  "ldr %1, [%2]\n\t"
                                  "cmp %1, %4\n\t"
+                                 "mov %0, %1\n\t"
                                  "bne 1f\n\t"
                                  "swpeq %0, %3, [%2]\n\t"
                                  "cmp %0, %1\n\t"
@@ -869,12 +871,12 @@ static inline gint32 InterlockedDecrement(volatile gint32 *val)
        
        __asm__ __volatile__ (
                "1:     ldl_l %0, %1\n"
-               "       addl %0, %3, %0\n"
+               "       subl %0, %3, %0\n"
                "       mov %0, %2\n"
                "       stl_c %0, %1\n"
                "       beq %0, 1b\n"
                : "=&r" (temp), "=m" (*val), "=r" (cur)
-               : "Ir" (-1), "m" (*val));
+               : "Ir" (1), "m" (*val));
        return(cur);
 }
 
@@ -922,6 +924,88 @@ static inline gint32 InterlockedExchangeAdd(volatile gint32 *val, gint32 add)
        return(ret);
 }
 
+#elif defined(__mips__)
+#define WAPI_ATOMIC_ASM
+
+static inline gint32 InterlockedIncrement(volatile gint32 *val)
+{
+       gint32 tmp, result = 0;
+
+       __asm__ __volatile__ ("    .set    mips32\n"
+                             "1:  ll      %0, %2\n"
+                             "    addu    %1, %0, 1\n"
+                              "    sc      %1, %2\n"
+                             "    beqz    %1, 1b\n"
+                             "    .set    mips0\n"
+                             : "=&r" (result), "=&r" (tmp), "=m" (*val)
+                             : "m" (*val));
+       return result + 1;
+}
+
+static inline gint32 InterlockedDecrement(volatile gint32 *val)
+{
+       gint32 tmp, result = 0;
+
+       __asm__ __volatile__ ("    .set    mips32\n"
+                             "1:  ll      %0, %2\n"
+                             "    subu    %1, %0, 1\n"
+                              "    sc      %1, %2\n"
+                             "    beqz    %1, 1b\n"
+                             "    .set    mips0\n"
+                             : "=&r" (result), "=&r" (tmp), "=m" (*val)
+                             : "m" (*val));
+       return result - 1;
+}
+
+#define InterlockedCompareExchangePointer(dest,exch,comp) InterlockedCompareExchange((volatile gint32 *)(dest), (gint32)(exch), (gint32)(comp))
+
+static inline gint32 InterlockedCompareExchange(volatile gint32 *dest,
+                                               gint32 exch, gint32 comp) {
+       gint32 old, tmp;
+
+       __asm__ __volatile__ ("    .set    mips32\n"
+                             "1:  ll      %0, %2\n"
+                             "    bne     %0, %5, 2f\n"
+                             "    move    %1, %4\n"
+                              "    sc      %1, %2\n"
+                             "    beqz    %1, 1b\n"
+                             "2:  .set    mips0\n"
+                             : "=&r" (old), "=&r" (tmp), "=m" (*dest)
+                             : "m" (*dest), "r" (exch), "r" (comp));
+       return(old);
+}
+
+static inline gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch)
+{
+       gint32 result, tmp;
+
+       __asm__ __volatile__ ("    .set    mips32\n"
+                             "1:  ll      %0, %2\n"
+                             "    move    %1, %4\n"
+                              "    sc      %1, %2\n"
+                             "    beqz    %1, 1b\n"
+                             "    .set    mips0\n"
+                             : "=&r" (result), "=&r" (tmp), "=m" (*dest)
+                             : "m" (*dest), "r" (exch));
+       return(result);
+}
+#define InterlockedExchangePointer(dest,exch) InterlockedExchange((volatile gint32 *)(dest), (gint32)(exch))
+
+static inline gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
+{
+        gint32 result, tmp;
+
+       __asm__ __volatile__ ("    .set    mips32\n"
+                             "1:  ll      %0, %2\n"
+                             "    addu    %1, %0, %4\n"
+                              "    sc      %1, %2\n"
+                             "    beqz    %1, 1b\n"
+                             "    .set    mips0\n"
+                             : "=&r" (result), "=&r" (tmp), "=m" (*dest)
+                             : "m" (*dest), "r" (add));
+        return result;
+}
+
 #else
 
 extern gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 exch, gint32 comp);