2 * Atomic helper templates
3 * Included from tcg-runtime.c and cputlb.c.
5 * Copyright (c) 2016 Red Hat, Inc
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
23 # define DATA_TYPE Int128
24 # define BSWAP bswap128
27 # define DATA_TYPE uint64_t
28 # define BSWAP bswap64
31 # define DATA_TYPE uint32_t
32 # define BSWAP bswap32
35 # define DATA_TYPE uint16_t
36 # define BSWAP bswap16
39 # define DATA_TYPE uint8_t
42 # error unsupported data size
46 # define ABI_TYPE DATA_TYPE
48 # define ABI_TYPE uint32_t
51 /* Define host-endian atomic operations. Note that END is used within
52 the ATOMIC_NAME macro, and redefined below. */
55 #elif defined(HOST_WORDS_BIGENDIAN)
61 ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
62 ABI_TYPE cmpv, ABI_TYPE newv EXTRA_ARGS)
64 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
65 return atomic_cmpxchg__nocheck(haddr, cmpv, newv);
69 ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
71 DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
72 __atomic_load(haddr, &val, __ATOMIC_RELAXED);
76 void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
77 ABI_TYPE val EXTRA_ARGS)
79 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
80 __atomic_store(haddr, &val, __ATOMIC_RELAXED);
83 ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
84 ABI_TYPE val EXTRA_ARGS)
86 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
87 return atomic_xchg__nocheck(haddr, val);
90 #define GEN_ATOMIC_HELPER(X) \
91 ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
92 ABI_TYPE val EXTRA_ARGS) \
94 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
95 return atomic_##X(haddr, val); \
98 GEN_ATOMIC_HELPER(fetch_add)
99 GEN_ATOMIC_HELPER(fetch_and)
100 GEN_ATOMIC_HELPER(fetch_or)
101 GEN_ATOMIC_HELPER(fetch_xor)
102 GEN_ATOMIC_HELPER(add_fetch)
103 GEN_ATOMIC_HELPER(and_fetch)
104 GEN_ATOMIC_HELPER(or_fetch)
105 GEN_ATOMIC_HELPER(xor_fetch)
107 #undef GEN_ATOMIC_HELPER
108 #endif /* DATA SIZE >= 16 */
114 /* Define reverse-host-endian atomic operations. Note that END is used
115 within the ATOMIC_NAME macro. */
116 #ifdef HOST_WORDS_BIGENDIAN
122 ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
123 ABI_TYPE cmpv, ABI_TYPE newv EXTRA_ARGS)
125 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
126 return BSWAP(atomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv)));
130 ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
132 DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
133 __atomic_load(haddr, &val, __ATOMIC_RELAXED);
137 void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
138 ABI_TYPE val EXTRA_ARGS)
140 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
142 __atomic_store(haddr, &val, __ATOMIC_RELAXED);
145 ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
146 ABI_TYPE val EXTRA_ARGS)
148 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
149 return BSWAP(atomic_xchg__nocheck(haddr, BSWAP(val)));
152 #define GEN_ATOMIC_HELPER(X) \
153 ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
154 ABI_TYPE val EXTRA_ARGS) \
156 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
157 return BSWAP(atomic_##X(haddr, BSWAP(val))); \
160 GEN_ATOMIC_HELPER(fetch_and)
161 GEN_ATOMIC_HELPER(fetch_or)
162 GEN_ATOMIC_HELPER(fetch_xor)
163 GEN_ATOMIC_HELPER(and_fetch)
164 GEN_ATOMIC_HELPER(or_fetch)
165 GEN_ATOMIC_HELPER(xor_fetch)
167 #undef GEN_ATOMIC_HELPER
169 /* Note that for addition, we need to use a separate cmpxchg loop instead
170 of bswaps for the reverse-host-endian helpers. */
171 ABI_TYPE ATOMIC_NAME(fetch_add)(CPUArchState *env, target_ulong addr,
172 ABI_TYPE val EXTRA_ARGS)
174 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
175 DATA_TYPE ldo, ldn, ret, sto;
177 ldo = atomic_read__nocheck(haddr);
180 sto = BSWAP(ret + val);
181 ldn = atomic_cmpxchg__nocheck(haddr, ldo, sto);
189 ABI_TYPE ATOMIC_NAME(add_fetch)(CPUArchState *env, target_ulong addr,
190 ABI_TYPE val EXTRA_ARGS)
192 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
193 DATA_TYPE ldo, ldn, ret, sto;
195 ldo = atomic_read__nocheck(haddr);
197 ret = BSWAP(ldo) + val;
199 ldn = atomic_cmpxchg__nocheck(haddr, ldo, sto);
206 #endif /* DATA_SIZE >= 16 */
209 #endif /* DATA_SIZE > 1 */