0a2853251eb3f0f52278847ccefb237cb690dc09
[cacao.git] / src / mm / boehm-gc / libatomic_ops-1.2 / src / atomic_ops / sysdeps / gcc / mips.h
1 /* 
2  * Copyright (c) 2005,2007  Thiemo Seufer <ths@networkno.de>
3  *
4  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
6  *
7  * Permission is hereby granted to use or copy this program
8  * for any purpose,  provided the above notices are retained on all copies.
9  * Permission to modify the code and to distribute modified code is granted,
10  * provided the above notices are retained, and a notice that the code was
11  * modified is included with the above copyright notice.
12  */
13
14 #include "../all_aligned_atomic_load_store.h"
15 #include "../acquire_release_volatile.h"
16 #include "../test_and_set_t_is_ao_t.h"
17 #include "../standard_ao_double_t.h"
18
19 /* Data dependence does not imply read ordering.  */
20 #define AO_NO_DD_ORDERING
21
22 AO_INLINE void
23 AO_nop_full()
24 {
25   __asm__ __volatile__(
26       "       .set push           \n"
27       "       .set mips2          \n"
28       "       .set noreorder      \n"
29       "       .set nomacro        \n"
30       "       sync                \n"
31       "       .set pop              "
32       : : : "memory");
33 }
34
35 #define AO_HAVE_nop_full
36
37 AO_INLINE int
38 AO_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val)
39 {
40   register int was_equal = 0;
41   register int temp;
42
43   __asm__ __volatile__(
44       "       .set push           \n"
45       "       .set mips2          \n"
46       "       .set noreorder      \n"
47       "       .set nomacro        \n"
48       "1:     ll      %0, %1      \n"
49       "       bne     %0, %4, 2f  \n"
50       "        move   %0, %3      \n"
51       "       sc      %0, %1      \n"
52       "       .set pop            \n"
53       "       beqz    %0, 1b      \n"
54       "       li      %2, 1       \n"
55       "2:                           "
56       : "=&r" (temp), "+R" (*addr), "+r" (was_equal)
57       : "r" (new_val), "r" (old)
58       : "memory");
59   return was_equal;
60 }
61
62 #define AO_HAVE_compare_and_swap
63
64 AO_INLINE int
65 AO_compare_and_swap_acquire(volatile AO_t *addr, AO_t old, AO_t new_val) {
66   int result = AO_compare_and_swap(addr, old, new_val);
67   AO_nop_full();
68   return result;
69 }
70
71 #define AO_HAVE_compare_and_swap_acquire
72
73 AO_INLINE int
74 AO_compare_and_swap_release(volatile AO_t *addr, AO_t old, AO_t new_val) {
75   AO_nop_full();
76   return AO_compare_and_swap(addr, old, new_val);
77 }
78
79 #define AO_HAVE_compare_and_swap_release
80
81 AO_INLINE int
82 AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) {
83   AO_t result;
84   AO_nop_full();
85   result = AO_compare_and_swap(addr, old, new_val);
86   AO_nop_full();
87   return result;
88 }
89
90 #define AO_HAVE_compare_and_swap_full
91
92 /*
93  * FIXME: We should also implement fetch_and_add and or primitives
94  * directly.
95  */
96
97 #include "../ao_t_is_int.h"