1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#if DATA_SIZE == 16
22# define SUFFIX o
23# define DATA_TYPE Int128
24# define BSWAP bswap128
25#elif DATA_SIZE == 8
26# define SUFFIX q
27# define DATA_TYPE uint64_t
28# define BSWAP bswap64
29#elif DATA_SIZE == 4
30# define SUFFIX l
31# define DATA_TYPE uint32_t
32# define BSWAP bswap32
33#elif DATA_SIZE == 2
34# define SUFFIX w
35# define DATA_TYPE uint16_t
36# define BSWAP bswap16
37#elif DATA_SIZE == 1
38# define SUFFIX b
39# define DATA_TYPE uint8_t
40# define BSWAP
41#else
42# error unsupported data size
43#endif
44
45#if DATA_SIZE >= 4
46# define ABI_TYPE DATA_TYPE
47#else
48# define ABI_TYPE uint32_t
49#endif
50
51
52
53#if DATA_SIZE == 1
54# define END
55#elif defined(HOST_WORDS_BIGENDIAN)
56# define END _be
57#else
58# define END _le
59#endif
60
61ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
62 ABI_TYPE cmpv, ABI_TYPE newv EXTRA_ARGS)
63{
64 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
65 return atomic_cmpxchg__nocheck(haddr, cmpv, newv);
66}
67
68#if DATA_SIZE >= 16
69ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
70{
71 DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
72 __atomic_load(haddr, &val, __ATOMIC_RELAXED);
73 return val;
74}
75
76void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
77 ABI_TYPE val EXTRA_ARGS)
78{
79 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
80 __atomic_store(haddr, &val, __ATOMIC_RELAXED);
81}
82#else
83ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
84 ABI_TYPE val EXTRA_ARGS)
85{
86 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
87 return atomic_xchg__nocheck(haddr, val);
88}
89
90#define GEN_ATOMIC_HELPER(X) \
91ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
92 ABI_TYPE val EXTRA_ARGS) \
93{ \
94 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
95 return atomic_##X(haddr, val); \
96} \
97
98GEN_ATOMIC_HELPER(fetch_add)
99GEN_ATOMIC_HELPER(fetch_and)
100GEN_ATOMIC_HELPER(fetch_or)
101GEN_ATOMIC_HELPER(fetch_xor)
102GEN_ATOMIC_HELPER(add_fetch)
103GEN_ATOMIC_HELPER(and_fetch)
104GEN_ATOMIC_HELPER(or_fetch)
105GEN_ATOMIC_HELPER(xor_fetch)
106
107#undef GEN_ATOMIC_HELPER
108#endif
109
110#undef END
111
112#if DATA_SIZE > 1
113
114
115
116#ifdef HOST_WORDS_BIGENDIAN
117# define END _le
118#else
119# define END _be
120#endif
121
122ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
123 ABI_TYPE cmpv, ABI_TYPE newv EXTRA_ARGS)
124{
125 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
126 return BSWAP(atomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv)));
127}
128
129#if DATA_SIZE >= 16
130ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
131{
132 DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
133 __atomic_load(haddr, &val, __ATOMIC_RELAXED);
134 return BSWAP(val);
135}
136
137void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
138 ABI_TYPE val EXTRA_ARGS)
139{
140 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
141 val = BSWAP(val);
142 __atomic_store(haddr, &val, __ATOMIC_RELAXED);
143}
144#else
145ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
146 ABI_TYPE val EXTRA_ARGS)
147{
148 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
149 return BSWAP(atomic_xchg__nocheck(haddr, BSWAP(val)));
150}
151
152#define GEN_ATOMIC_HELPER(X) \
153ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
154 ABI_TYPE val EXTRA_ARGS) \
155{ \
156 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
157 return BSWAP(atomic_##X(haddr, BSWAP(val))); \
158}
159
160GEN_ATOMIC_HELPER(fetch_and)
161GEN_ATOMIC_HELPER(fetch_or)
162GEN_ATOMIC_HELPER(fetch_xor)
163GEN_ATOMIC_HELPER(and_fetch)
164GEN_ATOMIC_HELPER(or_fetch)
165GEN_ATOMIC_HELPER(xor_fetch)
166
167#undef GEN_ATOMIC_HELPER
168
169
170
171ABI_TYPE ATOMIC_NAME(fetch_add)(CPUArchState *env, target_ulong addr,
172 ABI_TYPE val EXTRA_ARGS)
173{
174 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
175 DATA_TYPE ldo, ldn, ret, sto;
176
177 ldo = atomic_read__nocheck(haddr);
178 while (1) {
179 ret = BSWAP(ldo);
180 sto = BSWAP(ret + val);
181 ldn = atomic_cmpxchg__nocheck(haddr, ldo, sto);
182 if (ldn == ldo) {
183 return ret;
184 }
185 ldo = ldn;
186 }
187}
188
189ABI_TYPE ATOMIC_NAME(add_fetch)(CPUArchState *env, target_ulong addr,
190 ABI_TYPE val EXTRA_ARGS)
191{
192 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
193 DATA_TYPE ldo, ldn, ret, sto;
194
195 ldo = atomic_read__nocheck(haddr);
196 while (1) {
197 ret = BSWAP(ldo) + val;
198 sto = BSWAP(ret);
199 ldn = atomic_cmpxchg__nocheck(haddr, ldo, sto);
200 if (ldn == ldo) {
201 return ret;
202 }
203 ldo = ldn;
204 }
205}
206#endif
207
208#undef END
209#endif
210
211#undef BSWAP
212#undef ABI_TYPE
213#undef DATA_TYPE
214#undef SUFFIX
215#undef DATA_SIZE
216