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 DATA_TYPE ret
= atomic_cmpxchg__nocheck(haddr
, cmpv
, newv
);
71 ABI_TYPE
ATOMIC_NAME(ld
)(CPUArchState
*env
, target_ulong addr EXTRA_ARGS
)
73 DATA_TYPE val
, *haddr
= ATOMIC_MMU_LOOKUP
;
74 __atomic_load(haddr
, &val
, __ATOMIC_RELAXED
);
79 void ATOMIC_NAME(st
)(CPUArchState
*env
, target_ulong addr
,
80 ABI_TYPE val EXTRA_ARGS
)
82 DATA_TYPE
*haddr
= ATOMIC_MMU_LOOKUP
;
83 __atomic_store(haddr
, &val
, __ATOMIC_RELAXED
);
87 ABI_TYPE
ATOMIC_NAME(xchg
)(CPUArchState
*env
, target_ulong addr
,
88 ABI_TYPE val EXTRA_ARGS
)
90 DATA_TYPE
*haddr
= ATOMIC_MMU_LOOKUP
;
91 DATA_TYPE ret
= atomic_xchg__nocheck(haddr
, val
);
96 #define GEN_ATOMIC_HELPER(X) \
97 ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
98 ABI_TYPE val EXTRA_ARGS) \
100 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
101 DATA_TYPE ret = atomic_##X(haddr, val); \
102 ATOMIC_MMU_CLEANUP; \
106 GEN_ATOMIC_HELPER(fetch_add
)
107 GEN_ATOMIC_HELPER(fetch_and
)
108 GEN_ATOMIC_HELPER(fetch_or
)
109 GEN_ATOMIC_HELPER(fetch_xor
)
110 GEN_ATOMIC_HELPER(add_fetch
)
111 GEN_ATOMIC_HELPER(and_fetch
)
112 GEN_ATOMIC_HELPER(or_fetch
)
113 GEN_ATOMIC_HELPER(xor_fetch
)
115 #undef GEN_ATOMIC_HELPER
116 #endif /* DATA SIZE >= 16 */
122 /* Define reverse-host-endian atomic operations. Note that END is used
123 within the ATOMIC_NAME macro. */
124 #ifdef HOST_WORDS_BIGENDIAN
130 ABI_TYPE
ATOMIC_NAME(cmpxchg
)(CPUArchState
*env
, target_ulong addr
,
131 ABI_TYPE cmpv
, ABI_TYPE newv EXTRA_ARGS
)
133 DATA_TYPE
*haddr
= ATOMIC_MMU_LOOKUP
;
134 DATA_TYPE ret
= atomic_cmpxchg__nocheck(haddr
, BSWAP(cmpv
), BSWAP(newv
));
140 ABI_TYPE
ATOMIC_NAME(ld
)(CPUArchState
*env
, target_ulong addr EXTRA_ARGS
)
142 DATA_TYPE val
, *haddr
= ATOMIC_MMU_LOOKUP
;
143 __atomic_load(haddr
, &val
, __ATOMIC_RELAXED
);
148 void ATOMIC_NAME(st
)(CPUArchState
*env
, target_ulong addr
,
149 ABI_TYPE val EXTRA_ARGS
)
151 DATA_TYPE
*haddr
= ATOMIC_MMU_LOOKUP
;
153 __atomic_store(haddr
, &val
, __ATOMIC_RELAXED
);
157 ABI_TYPE
ATOMIC_NAME(xchg
)(CPUArchState
*env
, target_ulong addr
,
158 ABI_TYPE val EXTRA_ARGS
)
160 DATA_TYPE
*haddr
= ATOMIC_MMU_LOOKUP
;
161 ABI_TYPE ret
= atomic_xchg__nocheck(haddr
, BSWAP(val
));
166 #define GEN_ATOMIC_HELPER(X) \
167 ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
168 ABI_TYPE val EXTRA_ARGS) \
170 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
171 DATA_TYPE ret = atomic_##X(haddr, BSWAP(val)); \
172 ATOMIC_MMU_CLEANUP; \
176 GEN_ATOMIC_HELPER(fetch_and
)
177 GEN_ATOMIC_HELPER(fetch_or
)
178 GEN_ATOMIC_HELPER(fetch_xor
)
179 GEN_ATOMIC_HELPER(and_fetch
)
180 GEN_ATOMIC_HELPER(or_fetch
)
181 GEN_ATOMIC_HELPER(xor_fetch
)
183 #undef GEN_ATOMIC_HELPER
185 /* Note that for addition, we need to use a separate cmpxchg loop instead
186 of bswaps for the reverse-host-endian helpers. */
187 ABI_TYPE
ATOMIC_NAME(fetch_add
)(CPUArchState
*env
, target_ulong addr
,
188 ABI_TYPE val EXTRA_ARGS
)
190 DATA_TYPE
*haddr
= ATOMIC_MMU_LOOKUP
;
191 DATA_TYPE ldo
, ldn
, ret
, sto
;
193 ldo
= atomic_read__nocheck(haddr
);
196 sto
= BSWAP(ret
+ val
);
197 ldn
= atomic_cmpxchg__nocheck(haddr
, ldo
, sto
);
206 ABI_TYPE
ATOMIC_NAME(add_fetch
)(CPUArchState
*env
, target_ulong addr
,
207 ABI_TYPE val EXTRA_ARGS
)
209 DATA_TYPE
*haddr
= ATOMIC_MMU_LOOKUP
;
210 DATA_TYPE ldo
, ldn
, ret
, sto
;
212 ldo
= atomic_read__nocheck(haddr
);
214 ret
= BSWAP(ldo
) + val
;
216 ldn
= atomic_cmpxchg__nocheck(haddr
, ldo
, sto
);
224 #endif /* DATA_SIZE >= 16 */
227 #endif /* DATA_SIZE > 1 */