| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Atomic helper templates | 
					
						
							|  |  |  |  * Included from tcg-runtime.c and cputlb.c. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2016 Red Hat, Inc | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This library is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							| 
									
										
										
										
											2019-01-23 15:08:56 +01:00
										 |  |  |  * version 2.1 of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  * Lesser General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-21 13:24:26 -04:00
										 |  |  | #include "qemu/plugin.h"
 | 
					
						
							| 
									
										
										
										
											2018-05-22 18:26:52 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-29 21:10:59 -07:00
										 |  |  | #if DATA_SIZE == 16
 | 
					
						
							|  |  |  | # define SUFFIX     o
 | 
					
						
							|  |  |  | # define DATA_TYPE  Int128
 | 
					
						
							|  |  |  | # define BSWAP      bswap128
 | 
					
						
							| 
									
										
										
										
											2018-05-22 18:26:52 -04:00
										 |  |  | # define SHIFT      4
 | 
					
						
							| 
									
										
										
										
											2016-06-29 21:10:59 -07:00
										 |  |  | #elif DATA_SIZE == 8
 | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | # define SUFFIX     q
 | 
					
						
							| 
									
										
										
										
											2021-07-16 08:17:18 -07:00
										 |  |  | # define DATA_TYPE  aligned_uint64_t
 | 
					
						
							|  |  |  | # define SDATA_TYPE aligned_int64_t
 | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | # define BSWAP      bswap64
 | 
					
						
							| 
									
										
										
										
											2018-05-22 18:26:52 -04:00
										 |  |  | # define SHIFT      3
 | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | #elif DATA_SIZE == 4
 | 
					
						
							|  |  |  | # define SUFFIX     l
 | 
					
						
							|  |  |  | # define DATA_TYPE  uint32_t
 | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  | # define SDATA_TYPE int32_t
 | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | # define BSWAP      bswap32
 | 
					
						
							| 
									
										
										
										
											2018-05-22 18:26:52 -04:00
										 |  |  | # define SHIFT      2
 | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | #elif DATA_SIZE == 2
 | 
					
						
							|  |  |  | # define SUFFIX     w
 | 
					
						
							|  |  |  | # define DATA_TYPE  uint16_t
 | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  | # define SDATA_TYPE int16_t
 | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | # define BSWAP      bswap16
 | 
					
						
							| 
									
										
										
										
											2018-05-22 18:26:52 -04:00
										 |  |  | # define SHIFT      1
 | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | #elif DATA_SIZE == 1
 | 
					
						
							|  |  |  | # define SUFFIX     b
 | 
					
						
							|  |  |  | # define DATA_TYPE  uint8_t
 | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  | # define SDATA_TYPE int8_t
 | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | # define BSWAP
 | 
					
						
							| 
									
										
										
										
											2018-05-22 18:26:52 -04:00
										 |  |  | # define SHIFT      0
 | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | #else
 | 
					
						
							|  |  |  | # error unsupported data size
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if DATA_SIZE >= 4
 | 
					
						
							|  |  |  | # define ABI_TYPE  DATA_TYPE
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | # define ABI_TYPE  uint32_t
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Define host-endian atomic operations.  Note that END is used within
 | 
					
						
							|  |  |  |    the ATOMIC_NAME macro, and redefined below.  */ | 
					
						
							|  |  |  | #if DATA_SIZE == 1
 | 
					
						
							|  |  |  | # define END
 | 
					
						
							| 
									
										
										
										
											2022-03-23 19:57:17 +04:00
										 |  |  | #elif HOST_BIG_ENDIAN
 | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | # define END  _be
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | # define END  _le
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-07 17:57:02 +02:00
										 |  |  | ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, abi_ptr addr, | 
					
						
							| 
									
										
										
										
											2021-07-16 15:57:02 -07:00
										 |  |  |                               ABI_TYPE cmpv, ABI_TYPE newv, | 
					
						
							| 
									
										
										
										
											2021-07-25 12:06:49 -10:00
										 |  |  |                               MemOpIdx oi, uintptr_t retaddr) | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-09-12 17:34:23 +02:00
										 |  |  |     DATA_TYPE *haddr = atomic_mmu_lookup(env_cpu(env), addr, oi, | 
					
						
							|  |  |  |                                          DATA_SIZE, retaddr); | 
					
						
							| 
									
										
										
										
											2018-05-22 18:26:52 -04:00
										 |  |  |     DATA_TYPE ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-15 16:31:47 -07:00
										 |  |  | #if DATA_SIZE == 16
 | 
					
						
							|  |  |  |     ret = atomic16_cmpxchg(haddr, cmpv, newv); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2020-09-23 11:56:46 +01:00
										 |  |  |     ret = qatomic_cmpxchg__nocheck(haddr, cmpv, newv); | 
					
						
							| 
									
										
										
										
											2018-08-15 16:31:47 -07:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-11-14 10:34:20 +01:00
										 |  |  |     ATOMIC_MMU_CLEANUP; | 
					
						
							| 
									
										
										
										
											2021-07-26 08:19:40 -10:00
										 |  |  |     atomic_trace_rmw_post(env, addr, oi); | 
					
						
							| 
									
										
										
										
											2017-11-14 10:34:20 +01:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-19 17:45:47 -07:00
										 |  |  | #if DATA_SIZE < 16
 | 
					
						
							| 
									
										
										
										
											2023-08-07 17:57:02 +02:00
										 |  |  | ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, abi_ptr addr, ABI_TYPE val, | 
					
						
							| 
									
										
										
										
											2021-07-25 12:06:49 -10:00
										 |  |  |                            MemOpIdx oi, uintptr_t retaddr) | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-09-12 17:34:23 +02:00
										 |  |  |     DATA_TYPE *haddr = atomic_mmu_lookup(env_cpu(env), addr, oi, | 
					
						
							|  |  |  |                                          DATA_SIZE, retaddr); | 
					
						
							| 
									
										
										
										
											2018-05-22 18:26:52 -04:00
										 |  |  |     DATA_TYPE ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-23 11:56:46 +01:00
										 |  |  |     ret = qatomic_xchg__nocheck(haddr, val); | 
					
						
							| 
									
										
										
										
											2017-11-14 10:34:20 +01:00
										 |  |  |     ATOMIC_MMU_CLEANUP; | 
					
						
							| 
									
										
										
										
											2021-07-26 08:19:40 -10:00
										 |  |  |     atomic_trace_rmw_post(env, addr, oi); | 
					
						
							| 
									
										
										
										
											2017-11-14 10:34:20 +01:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define GEN_ATOMIC_HELPER(X)                                        \
 | 
					
						
							| 
									
										
										
										
											2023-08-07 17:57:02 +02:00
										 |  |  | ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, abi_ptr addr,            \ | 
					
						
							| 
									
										
										
										
											2021-07-25 12:06:49 -10:00
										 |  |  |                         ABI_TYPE val, MemOpIdx oi, uintptr_t retaddr) \ | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | {                                                                   \ | 
					
						
							| 
									
										
										
										
											2023-05-19 17:54:18 -07:00
										 |  |  |     DATA_TYPE *haddr, ret;                                          \ | 
					
						
							| 
									
										
										
										
											2023-09-12 17:34:23 +02:00
										 |  |  |     haddr = atomic_mmu_lookup(env_cpu(env), addr, oi, DATA_SIZE, retaddr);   \ | 
					
						
							| 
									
										
										
										
											2020-09-23 11:56:46 +01:00
										 |  |  |     ret = qatomic_##X(haddr, val);                                  \ | 
					
						
							| 
									
										
										
										
											2017-11-14 10:34:20 +01:00
										 |  |  |     ATOMIC_MMU_CLEANUP;                                             \ | 
					
						
							| 
									
										
										
										
											2021-07-26 08:19:40 -10:00
										 |  |  |     atomic_trace_rmw_post(env, addr, oi);                           \ | 
					
						
							| 
									
										
										
										
											2017-11-14 10:34:20 +01:00
										 |  |  |     return ret;                                                     \ | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER(fetch_add) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER(fetch_and) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER(fetch_or) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER(fetch_xor) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER(add_fetch) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER(and_fetch) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER(or_fetch) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER(xor_fetch) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef GEN_ATOMIC_HELPER
 | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-16 17:49:09 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * These helpers are, as a whole, full barriers.  Within the helper, | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  |  * the leading barrier is explicit and the trailing barrier is within | 
					
						
							|  |  |  |  * cmpxchg primitive. | 
					
						
							| 
									
										
										
										
											2018-05-22 18:26:52 -04:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Trace this load + RMW loop as a single RMW op. This way, regardless | 
					
						
							|  |  |  |  * of CF_PARALLEL's value, we'll trace just a read and a write. | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | #define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET)                \
 | 
					
						
							| 
									
										
										
										
											2023-08-07 17:57:02 +02:00
										 |  |  | ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, abi_ptr addr,            \ | 
					
						
							| 
									
										
										
										
											2021-07-25 12:06:49 -10:00
										 |  |  |                         ABI_TYPE xval, MemOpIdx oi, uintptr_t retaddr) \ | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  | {                                                                   \ | 
					
						
							| 
									
										
										
										
											2023-05-19 17:54:18 -07:00
										 |  |  |     XDATA_TYPE *haddr, cmp, old, new, val = xval;                   \ | 
					
						
							| 
									
										
										
										
											2023-09-12 17:34:23 +02:00
										 |  |  |     haddr = atomic_mmu_lookup(env_cpu(env), addr, oi, DATA_SIZE, retaddr);   \ | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  |     smp_mb();                                                       \ | 
					
						
							| 
									
										
										
										
											2020-09-23 11:56:46 +01:00
										 |  |  |     cmp = qatomic_read__nocheck(haddr);                             \ | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  |     do {                                                            \ | 
					
						
							|  |  |  |         old = cmp; new = FN(old, val);                              \ | 
					
						
							| 
									
										
										
										
											2020-09-23 11:56:46 +01:00
										 |  |  |         cmp = qatomic_cmpxchg__nocheck(haddr, old, new);            \ | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  |     } while (cmp != old);                                           \ | 
					
						
							|  |  |  |     ATOMIC_MMU_CLEANUP;                                             \ | 
					
						
							| 
									
										
										
										
											2021-07-26 08:19:40 -10:00
										 |  |  |     atomic_trace_rmw_post(env, addr, oi);                           \ | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  |     return RET;                                                     \ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(fetch_smin, MIN, SDATA_TYPE, old) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(fetch_umin, MIN,  DATA_TYPE, old) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(fetch_smax, MAX, SDATA_TYPE, old) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(fetch_umax, MAX,  DATA_TYPE, old) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(smin_fetch, MIN, SDATA_TYPE, new) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(umin_fetch, MIN,  DATA_TYPE, new) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(smax_fetch, MAX, SDATA_TYPE, new) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(umax_fetch, MAX,  DATA_TYPE, new) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef GEN_ATOMIC_HELPER_FN
 | 
					
						
							| 
									
										
										
										
											2023-05-19 17:45:47 -07:00
										 |  |  | #endif /* DATA SIZE < 16 */
 | 
					
						
							| 
									
										
										
										
											2016-06-29 21:10:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | #undef END
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if DATA_SIZE > 1
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Define reverse-host-endian atomic operations.  Note that END is used
 | 
					
						
							|  |  |  |    within the ATOMIC_NAME macro.  */ | 
					
						
							| 
									
										
										
										
											2022-03-23 19:57:17 +04:00
										 |  |  | #if HOST_BIG_ENDIAN
 | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | # define END  _le
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | # define END  _be
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-07 17:57:02 +02:00
										 |  |  | ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, abi_ptr addr, | 
					
						
							| 
									
										
										
										
											2021-07-16 15:57:02 -07:00
										 |  |  |                               ABI_TYPE cmpv, ABI_TYPE newv, | 
					
						
							| 
									
										
										
										
											2021-07-25 12:06:49 -10:00
										 |  |  |                               MemOpIdx oi, uintptr_t retaddr) | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-09-12 17:34:23 +02:00
										 |  |  |     DATA_TYPE *haddr = atomic_mmu_lookup(env_cpu(env), addr, oi, | 
					
						
							|  |  |  |                                          DATA_SIZE, retaddr); | 
					
						
							| 
									
										
										
										
											2018-05-22 18:26:52 -04:00
										 |  |  |     DATA_TYPE ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-15 16:31:47 -07:00
										 |  |  | #if DATA_SIZE == 16
 | 
					
						
							|  |  |  |     ret = atomic16_cmpxchg(haddr, BSWAP(cmpv), BSWAP(newv)); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2020-09-23 11:56:46 +01:00
										 |  |  |     ret = qatomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv)); | 
					
						
							| 
									
										
										
										
											2018-08-15 16:31:47 -07:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-11-14 10:34:20 +01:00
										 |  |  |     ATOMIC_MMU_CLEANUP; | 
					
						
							| 
									
										
										
										
											2021-07-26 08:19:40 -10:00
										 |  |  |     atomic_trace_rmw_post(env, addr, oi); | 
					
						
							| 
									
										
										
										
											2017-11-14 10:34:20 +01:00
										 |  |  |     return BSWAP(ret); | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-19 17:45:47 -07:00
										 |  |  | #if DATA_SIZE < 16
 | 
					
						
							| 
									
										
										
										
											2023-08-07 17:57:02 +02:00
										 |  |  | ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, abi_ptr addr, ABI_TYPE val, | 
					
						
							| 
									
										
										
										
											2021-07-25 12:06:49 -10:00
										 |  |  |                            MemOpIdx oi, uintptr_t retaddr) | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-09-12 17:34:23 +02:00
										 |  |  |     DATA_TYPE *haddr = atomic_mmu_lookup(env_cpu(env), addr, oi, | 
					
						
							|  |  |  |                                          DATA_SIZE, retaddr); | 
					
						
							| 
									
										
										
										
											2018-05-22 18:26:52 -04:00
										 |  |  |     ABI_TYPE ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-23 11:56:46 +01:00
										 |  |  |     ret = qatomic_xchg__nocheck(haddr, BSWAP(val)); | 
					
						
							| 
									
										
										
										
											2017-11-14 10:34:20 +01:00
										 |  |  |     ATOMIC_MMU_CLEANUP; | 
					
						
							| 
									
										
										
										
											2021-07-26 08:19:40 -10:00
										 |  |  |     atomic_trace_rmw_post(env, addr, oi); | 
					
						
							| 
									
										
										
										
											2017-11-14 10:34:20 +01:00
										 |  |  |     return BSWAP(ret); | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define GEN_ATOMIC_HELPER(X)                                        \
 | 
					
						
							| 
									
										
										
										
											2023-08-07 17:57:02 +02:00
										 |  |  | ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, abi_ptr addr,            \ | 
					
						
							| 
									
										
										
										
											2021-07-25 12:06:49 -10:00
										 |  |  |                         ABI_TYPE val, MemOpIdx oi, uintptr_t retaddr) \ | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | {                                                                   \ | 
					
						
							| 
									
										
										
										
											2023-05-19 17:54:18 -07:00
										 |  |  |     DATA_TYPE *haddr, ret;                                          \ | 
					
						
							| 
									
										
										
										
											2023-09-12 17:34:23 +02:00
										 |  |  |     haddr = atomic_mmu_lookup(env_cpu(env), addr, oi, DATA_SIZE, retaddr);   \ | 
					
						
							| 
									
										
										
										
											2020-09-23 11:56:46 +01:00
										 |  |  |     ret = qatomic_##X(haddr, BSWAP(val));                           \ | 
					
						
							| 
									
										
										
										
											2017-11-14 10:34:20 +01:00
										 |  |  |     ATOMIC_MMU_CLEANUP;                                             \ | 
					
						
							| 
									
										
										
										
											2021-07-26 08:19:40 -10:00
										 |  |  |     atomic_trace_rmw_post(env, addr, oi);                           \ | 
					
						
							| 
									
										
										
										
											2017-11-14 10:34:20 +01:00
										 |  |  |     return BSWAP(ret);                                              \ | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER(fetch_and) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER(fetch_or) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER(fetch_xor) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER(and_fetch) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER(or_fetch) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER(xor_fetch) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef GEN_ATOMIC_HELPER
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  | /* These helpers are, as a whole, full barriers.  Within the helper,
 | 
					
						
							|  |  |  |  * the leading barrier is explicit and the trailing barrier is within | 
					
						
							|  |  |  |  * cmpxchg primitive. | 
					
						
							| 
									
										
										
										
											2018-05-22 18:26:52 -04:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Trace this load + RMW loop as a single RMW op. This way, regardless | 
					
						
							|  |  |  |  * of CF_PARALLEL's value, we'll trace just a read and a write. | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | #define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET)                \
 | 
					
						
							| 
									
										
										
										
											2023-08-07 17:57:02 +02:00
										 |  |  | ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, abi_ptr addr,            \ | 
					
						
							| 
									
										
										
										
											2021-07-25 12:06:49 -10:00
										 |  |  |                         ABI_TYPE xval, MemOpIdx oi, uintptr_t retaddr) \ | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  | {                                                                   \ | 
					
						
							| 
									
										
										
										
											2023-05-19 17:54:18 -07:00
										 |  |  |     XDATA_TYPE *haddr, ldo, ldn, old, new, val = xval;              \ | 
					
						
							| 
									
										
										
										
											2023-09-12 17:34:23 +02:00
										 |  |  |     haddr = atomic_mmu_lookup(env_cpu(env), addr, oi, DATA_SIZE, retaddr);   \ | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  |     smp_mb();                                                       \ | 
					
						
							| 
									
										
										
										
											2020-09-23 11:56:46 +01:00
										 |  |  |     ldn = qatomic_read__nocheck(haddr);                             \ | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  |     do {                                                            \ | 
					
						
							|  |  |  |         ldo = ldn; old = BSWAP(ldo); new = FN(old, val);            \ | 
					
						
							| 
									
										
										
										
											2020-09-23 11:56:46 +01:00
										 |  |  |         ldn = qatomic_cmpxchg__nocheck(haddr, ldo, BSWAP(new));     \ | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  |     } while (ldo != ldn);                                           \ | 
					
						
							|  |  |  |     ATOMIC_MMU_CLEANUP;                                             \ | 
					
						
							| 
									
										
										
										
											2021-07-26 08:19:40 -10:00
										 |  |  |     atomic_trace_rmw_post(env, addr, oi);                           \ | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  |     return RET;                                                     \ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(fetch_smin, MIN, SDATA_TYPE, old) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(fetch_umin, MIN,  DATA_TYPE, old) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(fetch_smax, MAX, SDATA_TYPE, old) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(fetch_umax, MAX,  DATA_TYPE, old) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(smin_fetch, MIN, SDATA_TYPE, new) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(umin_fetch, MIN,  DATA_TYPE, new) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(smax_fetch, MAX, SDATA_TYPE, new) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(umax_fetch, MAX,  DATA_TYPE, new) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  | /* Note that for addition, we need to use a separate cmpxchg loop instead
 | 
					
						
							|  |  |  |    of bswaps for the reverse-host-endian helpers.  */ | 
					
						
							|  |  |  | #define ADD(X, Y)   (X + Y)
 | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(fetch_add, ADD, DATA_TYPE, old) | 
					
						
							|  |  |  | GEN_ATOMIC_HELPER_FN(add_fetch, ADD, DATA_TYPE, new) | 
					
						
							|  |  |  | #undef ADD
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  | #undef GEN_ATOMIC_HELPER_FN
 | 
					
						
							| 
									
										
										
										
											2023-05-19 17:45:47 -07:00
										 |  |  | #endif /* DATA_SIZE < 16 */
 | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #undef END
 | 
					
						
							|  |  |  | #endif /* DATA_SIZE > 1 */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef BSWAP
 | 
					
						
							|  |  |  | #undef ABI_TYPE
 | 
					
						
							|  |  |  | #undef DATA_TYPE
 | 
					
						
							| 
									
										
										
										
											2018-05-10 18:10:57 +01:00
										 |  |  | #undef SDATA_TYPE
 | 
					
						
							| 
									
										
										
										
											2016-06-28 11:37:27 -07:00
										 |  |  | #undef SUFFIX
 | 
					
						
							|  |  |  | #undef DATA_SIZE
 | 
					
						
							| 
									
										
										
										
											2018-05-22 18:26:52 -04:00
										 |  |  | #undef SHIFT
 |