1 /*
2  * Copyright (C) 2006-2008 by Marc Boris Duerner
3  * Copyright (C) 2006 by Aloysius Indrayanto
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * As a special exception, you may use this file as part of a free
11  * software library without restriction. Specifically, if other files
12  * instantiate templates or use macros or inline functions from this
13  * file, or you compile this file and link it with other files to
14  * produce an executable, this file does not by itself cause the
15  * resulting executable to be covered by the GNU General Public
16  * License. This exception does not however invalidate any other
17  * reasons why the executable file might be covered by the GNU Library
18  * General Public License.
19  *
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * Lesser General Public License for more details.
24  *
25  * You should have received a copy of the GNU Lesser General Public
26  * License along with this library; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
28  */
29 
30 #include <cxxtools/atomicity.gcc.mips.h>
31 #include <csignal>
32 
33 namespace cxxtools {
34 
atomicGet(volatile atomic_t & val)35 atomic_t atomicGet(volatile atomic_t& val)
36 {
37     asm volatile ("" : : : "memory");
38     return val;
39 }
40 
41 
atomicSet(volatile atomic_t & val,atomic_t n)42 void atomicSet(volatile atomic_t& val, atomic_t n)
43 {
44     val = n;
45     asm volatile ("" : : : "memory");
46 }
47 
48 
atomicIncrement(volatile atomic_t & val)49 atomic_t atomicIncrement(volatile atomic_t& val)
50 {
51     atomic_t tmp, result = 0;
52 
53     asm volatile ("    .set    mips32\n"
54                   "1:  ll      %0, %2\n"
55                   "    addu    %1, %0, 1\n"
56                   "    sc      %1, %2\n"
57                   "    beqz    %1, 1b\n"
58                   "    .set    mips0\n"
59                   : "=&r" (result), "=&r" (tmp), "=m" (val)
60                   : "m" (val));
61     return result + 1;
62 }
63 
64 
atomicDecrement(volatile atomic_t & val)65 atomic_t atomicDecrement(volatile atomic_t& val)
66 {
67     atomic_t tmp, result = 0;
68 
69     asm volatile ("    .set    mips32\n"
70                             "1:  ll      %0, %2\n"
71                             "    subu    %1, %0, 1\n"
72                             "    sc      %1, %2\n"
73                             "    beqz    %1, 1b\n"
74                             "    .set    mips0\n"
75                             : "=&r" (result), "=&r" (tmp), "=m" (val)
76                             : "m" (val));
77     return result - 1;
78 }
79 
80 
atomicCompareExchange(volatile atomic_t & dest,atomic_t exch,atomic_t comp)81 atomic_t atomicCompareExchange(volatile atomic_t& dest, atomic_t exch, atomic_t comp)
82 {
83     atomic_t old, tmp;
84 
85     asm volatile ("    .set    mips32\n"
86                             "1:  ll      %0, %2\n"
87                             "    bne     %0, %5, 2f\n"
88                             "    move    %1, %4\n"
89                             "    sc      %1, %2\n"
90                             "    beqz    %1, 1b\n"
91                             "2:  .set    mips0\n"
92                             : "=&r" (old), "=&r" (tmp), "=m" (dest)
93                             : "m" (dest), "r" (exch), "r" (comp));
94     return(old);
95 }
96 
97 
atomicCompareExchange(void * volatile & dest,void * exch,void * comp)98 void* atomicCompareExchange(void* volatile& dest, void* exch, void* comp)
99 {
100     atomic_t* old;
101     atomic_t* tmp;
102 
103     asm volatile ("    .set    mips32\n"
104                             "1:  ll      %0, %2\n"
105                             "    bne     %0, %5, 2f\n"
106                             "    move    %1, %4\n"
107                             "    sc      %1, %2\n"
108                             "    beqz    %1, 1b\n"
109                             "2:  .set    mips0\n"
110                             : "=&r" (old), "=&r" (tmp), "=m" (dest)
111                             : "m" (dest), "r" (exch), "r" (comp));
112     return(old);
113 }
114 
115 
atomicExchange(volatile atomic_t & dest,atomic_t exch)116 atomic_t atomicExchange(volatile atomic_t& dest, atomic_t exch)
117 {
118     atomic_t result, tmp;
119 
120     asm volatile ("    .set    mips32\n"
121                             "1:  ll      %0, %2\n"
122                             "    move    %1, %4\n"
123                             "    sc      %1, %2\n"
124                             "    beqz    %1, 1b\n"
125                             "    .set    mips0\n"
126                             : "=&r" (result), "=&r" (tmp), "=m" (dest)
127                             : "m" (dest), "r" (exch));
128     return(result);
129 }
130 
131 
atomicExchange(void * volatile & val,void * exch)132 void* atomicExchange(void* volatile& val, void* exch)
133 {
134     atomic_t* result, tmp;
135 
136     asm volatile ("    .set    mips32\n"
137                     "1:  ll      %0, %2\n"
138                     "    move    %1, %4\n"
139                     "    sc      %1, %2\n"
140                     "    beqz    %1, 1b\n"
141                     "    .set    mips0\n"
142                     : "=&r" (result), "=&r" (tmp), "=m" (val)
143                     : "m" (val), "r" (exch));
144     return(result);
145 }
146 
147 
atomicExchangeAdd(volatile atomic_t & dest,atomic_t add)148 atomic_t atomicExchangeAdd(volatile atomic_t& dest, atomic_t add)
149 {
150     atomic_t result, tmp;
151 
152     asm volatile ("    .set    mips32\n"
153                             "1:  ll      %0, %2\n"
154                             "    addu    %1, %0, %4\n"
155                             "    sc      %1, %2\n"
156                             "    beqz    %1, 1b\n"
157                             "    .set    mips0\n"
158                             : "=&r" (result), "=&r" (tmp), "=m" (dest)
159                             : "m" (dest), "r" (add));
160     return result;
161 }
162 
163 } // namespace cxxtools
164