1*10f7d4d5SPhilippe Mathieu-Daudé /* 2*10f7d4d5SPhilippe Mathieu-Daudé * Atomic helper templates 3*10f7d4d5SPhilippe Mathieu-Daudé * Included from tcg-runtime.c and cputlb.c. 4*10f7d4d5SPhilippe Mathieu-Daudé * 5*10f7d4d5SPhilippe Mathieu-Daudé * Copyright (c) 2016 Red Hat, Inc 6*10f7d4d5SPhilippe Mathieu-Daudé * 7*10f7d4d5SPhilippe Mathieu-Daudé * This library is free software; you can redistribute it and/or 8*10f7d4d5SPhilippe Mathieu-Daudé * modify it under the terms of the GNU Lesser General Public 9*10f7d4d5SPhilippe Mathieu-Daudé * License as published by the Free Software Foundation; either 10*10f7d4d5SPhilippe Mathieu-Daudé * version 2 of the License, or (at your option) any later version. 11*10f7d4d5SPhilippe Mathieu-Daudé * 12*10f7d4d5SPhilippe Mathieu-Daudé * This library is distributed in the hope that it will be useful, 13*10f7d4d5SPhilippe Mathieu-Daudé * but WITHOUT ANY WARRANTY; without even the implied warranty of 14*10f7d4d5SPhilippe Mathieu-Daudé * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15*10f7d4d5SPhilippe Mathieu-Daudé * Lesser General Public License for more details. 16*10f7d4d5SPhilippe Mathieu-Daudé * 17*10f7d4d5SPhilippe Mathieu-Daudé * You should have received a copy of the GNU Lesser General Public 18*10f7d4d5SPhilippe Mathieu-Daudé * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19*10f7d4d5SPhilippe Mathieu-Daudé */ 20*10f7d4d5SPhilippe Mathieu-Daudé 21*10f7d4d5SPhilippe Mathieu-Daudé #if DATA_SIZE == 16 22*10f7d4d5SPhilippe Mathieu-Daudé # define SUFFIX o 23*10f7d4d5SPhilippe Mathieu-Daudé # define DATA_TYPE Int128 24*10f7d4d5SPhilippe Mathieu-Daudé # define BSWAP bswap128 25*10f7d4d5SPhilippe Mathieu-Daudé #elif DATA_SIZE == 8 26*10f7d4d5SPhilippe Mathieu-Daudé # define SUFFIX q 27*10f7d4d5SPhilippe Mathieu-Daudé # define DATA_TYPE uint64_t 28*10f7d4d5SPhilippe Mathieu-Daudé # define BSWAP bswap64 29*10f7d4d5SPhilippe Mathieu-Daudé #elif DATA_SIZE == 4 30*10f7d4d5SPhilippe Mathieu-Daudé # define SUFFIX l 31*10f7d4d5SPhilippe Mathieu-Daudé # define DATA_TYPE uint32_t 32*10f7d4d5SPhilippe Mathieu-Daudé # define BSWAP bswap32 33*10f7d4d5SPhilippe Mathieu-Daudé #elif DATA_SIZE == 2 34*10f7d4d5SPhilippe Mathieu-Daudé # define SUFFIX w 35*10f7d4d5SPhilippe Mathieu-Daudé # define DATA_TYPE uint16_t 36*10f7d4d5SPhilippe Mathieu-Daudé # define BSWAP bswap16 37*10f7d4d5SPhilippe Mathieu-Daudé #elif DATA_SIZE == 1 38*10f7d4d5SPhilippe Mathieu-Daudé # define SUFFIX b 39*10f7d4d5SPhilippe Mathieu-Daudé # define DATA_TYPE uint8_t 40*10f7d4d5SPhilippe Mathieu-Daudé # define BSWAP 41*10f7d4d5SPhilippe Mathieu-Daudé #else 42*10f7d4d5SPhilippe Mathieu-Daudé # error unsupported data size 43*10f7d4d5SPhilippe Mathieu-Daudé #endif 44*10f7d4d5SPhilippe Mathieu-Daudé 45*10f7d4d5SPhilippe Mathieu-Daudé #if DATA_SIZE >= 4 46*10f7d4d5SPhilippe Mathieu-Daudé # define ABI_TYPE DATA_TYPE 47*10f7d4d5SPhilippe Mathieu-Daudé #else 48*10f7d4d5SPhilippe Mathieu-Daudé # define ABI_TYPE uint32_t 49*10f7d4d5SPhilippe Mathieu-Daudé #endif 50*10f7d4d5SPhilippe Mathieu-Daudé 51*10f7d4d5SPhilippe Mathieu-Daudé /* Define host-endian atomic operations. Note that END is used within 52*10f7d4d5SPhilippe Mathieu-Daudé the ATOMIC_NAME macro, and redefined below. */ 53*10f7d4d5SPhilippe Mathieu-Daudé #if DATA_SIZE == 1 54*10f7d4d5SPhilippe Mathieu-Daudé # define END 55*10f7d4d5SPhilippe Mathieu-Daudé #elif defined(HOST_WORDS_BIGENDIAN) 56*10f7d4d5SPhilippe Mathieu-Daudé # define END _be 57*10f7d4d5SPhilippe Mathieu-Daudé #else 58*10f7d4d5SPhilippe Mathieu-Daudé # define END _le 59*10f7d4d5SPhilippe Mathieu-Daudé #endif 60*10f7d4d5SPhilippe Mathieu-Daudé 61*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr, 62*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE cmpv, ABI_TYPE newv EXTRA_ARGS) 63*10f7d4d5SPhilippe Mathieu-Daudé { 64*10f7d4d5SPhilippe Mathieu-Daudé DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; 65*10f7d4d5SPhilippe Mathieu-Daudé return atomic_cmpxchg__nocheck(haddr, cmpv, newv); 66*10f7d4d5SPhilippe Mathieu-Daudé } 67*10f7d4d5SPhilippe Mathieu-Daudé 68*10f7d4d5SPhilippe Mathieu-Daudé #if DATA_SIZE >= 16 69*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS) 70*10f7d4d5SPhilippe Mathieu-Daudé { 71*10f7d4d5SPhilippe Mathieu-Daudé DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP; 72*10f7d4d5SPhilippe Mathieu-Daudé __atomic_load(haddr, &val, __ATOMIC_RELAXED); 73*10f7d4d5SPhilippe Mathieu-Daudé return val; 74*10f7d4d5SPhilippe Mathieu-Daudé } 75*10f7d4d5SPhilippe Mathieu-Daudé 76*10f7d4d5SPhilippe Mathieu-Daudé void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr, 77*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE val EXTRA_ARGS) 78*10f7d4d5SPhilippe Mathieu-Daudé { 79*10f7d4d5SPhilippe Mathieu-Daudé DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; 80*10f7d4d5SPhilippe Mathieu-Daudé __atomic_store(haddr, &val, __ATOMIC_RELAXED); 81*10f7d4d5SPhilippe Mathieu-Daudé } 82*10f7d4d5SPhilippe Mathieu-Daudé #else 83*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, 84*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE val EXTRA_ARGS) 85*10f7d4d5SPhilippe Mathieu-Daudé { 86*10f7d4d5SPhilippe Mathieu-Daudé DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; 87*10f7d4d5SPhilippe Mathieu-Daudé return atomic_xchg__nocheck(haddr, val); 88*10f7d4d5SPhilippe Mathieu-Daudé } 89*10f7d4d5SPhilippe Mathieu-Daudé 90*10f7d4d5SPhilippe Mathieu-Daudé #define GEN_ATOMIC_HELPER(X) \ 91*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \ 92*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE val EXTRA_ARGS) \ 93*10f7d4d5SPhilippe Mathieu-Daudé { \ 94*10f7d4d5SPhilippe Mathieu-Daudé DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \ 95*10f7d4d5SPhilippe Mathieu-Daudé return atomic_##X(haddr, val); \ 96*10f7d4d5SPhilippe Mathieu-Daudé } \ 97*10f7d4d5SPhilippe Mathieu-Daudé 98*10f7d4d5SPhilippe Mathieu-Daudé GEN_ATOMIC_HELPER(fetch_add) 99*10f7d4d5SPhilippe Mathieu-Daudé GEN_ATOMIC_HELPER(fetch_and) 100*10f7d4d5SPhilippe Mathieu-Daudé GEN_ATOMIC_HELPER(fetch_or) 101*10f7d4d5SPhilippe Mathieu-Daudé GEN_ATOMIC_HELPER(fetch_xor) 102*10f7d4d5SPhilippe Mathieu-Daudé GEN_ATOMIC_HELPER(add_fetch) 103*10f7d4d5SPhilippe Mathieu-Daudé GEN_ATOMIC_HELPER(and_fetch) 104*10f7d4d5SPhilippe Mathieu-Daudé GEN_ATOMIC_HELPER(or_fetch) 105*10f7d4d5SPhilippe Mathieu-Daudé GEN_ATOMIC_HELPER(xor_fetch) 106*10f7d4d5SPhilippe Mathieu-Daudé 107*10f7d4d5SPhilippe Mathieu-Daudé #undef GEN_ATOMIC_HELPER 108*10f7d4d5SPhilippe Mathieu-Daudé #endif /* DATA SIZE >= 16 */ 109*10f7d4d5SPhilippe Mathieu-Daudé 110*10f7d4d5SPhilippe Mathieu-Daudé #undef END 111*10f7d4d5SPhilippe Mathieu-Daudé 112*10f7d4d5SPhilippe Mathieu-Daudé #if DATA_SIZE > 1 113*10f7d4d5SPhilippe Mathieu-Daudé 114*10f7d4d5SPhilippe Mathieu-Daudé /* Define reverse-host-endian atomic operations. Note that END is used 115*10f7d4d5SPhilippe Mathieu-Daudé within the ATOMIC_NAME macro. */ 116*10f7d4d5SPhilippe Mathieu-Daudé #ifdef HOST_WORDS_BIGENDIAN 117*10f7d4d5SPhilippe Mathieu-Daudé # define END _le 118*10f7d4d5SPhilippe Mathieu-Daudé #else 119*10f7d4d5SPhilippe Mathieu-Daudé # define END _be 120*10f7d4d5SPhilippe Mathieu-Daudé #endif 121*10f7d4d5SPhilippe Mathieu-Daudé 122*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr, 123*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE cmpv, ABI_TYPE newv EXTRA_ARGS) 124*10f7d4d5SPhilippe Mathieu-Daudé { 125*10f7d4d5SPhilippe Mathieu-Daudé DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; 126*10f7d4d5SPhilippe Mathieu-Daudé return BSWAP(atomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv))); 127*10f7d4d5SPhilippe Mathieu-Daudé } 128*10f7d4d5SPhilippe Mathieu-Daudé 129*10f7d4d5SPhilippe Mathieu-Daudé #if DATA_SIZE >= 16 130*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS) 131*10f7d4d5SPhilippe Mathieu-Daudé { 132*10f7d4d5SPhilippe Mathieu-Daudé DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP; 133*10f7d4d5SPhilippe Mathieu-Daudé __atomic_load(haddr, &val, __ATOMIC_RELAXED); 134*10f7d4d5SPhilippe Mathieu-Daudé return BSWAP(val); 135*10f7d4d5SPhilippe Mathieu-Daudé } 136*10f7d4d5SPhilippe Mathieu-Daudé 137*10f7d4d5SPhilippe Mathieu-Daudé void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr, 138*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE val EXTRA_ARGS) 139*10f7d4d5SPhilippe Mathieu-Daudé { 140*10f7d4d5SPhilippe Mathieu-Daudé DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; 141*10f7d4d5SPhilippe Mathieu-Daudé val = BSWAP(val); 142*10f7d4d5SPhilippe Mathieu-Daudé __atomic_store(haddr, &val, __ATOMIC_RELAXED); 143*10f7d4d5SPhilippe Mathieu-Daudé } 144*10f7d4d5SPhilippe Mathieu-Daudé #else 145*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, 146*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE val EXTRA_ARGS) 147*10f7d4d5SPhilippe Mathieu-Daudé { 148*10f7d4d5SPhilippe Mathieu-Daudé DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; 149*10f7d4d5SPhilippe Mathieu-Daudé return BSWAP(atomic_xchg__nocheck(haddr, BSWAP(val))); 150*10f7d4d5SPhilippe Mathieu-Daudé } 151*10f7d4d5SPhilippe Mathieu-Daudé 152*10f7d4d5SPhilippe Mathieu-Daudé #define GEN_ATOMIC_HELPER(X) \ 153*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \ 154*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE val EXTRA_ARGS) \ 155*10f7d4d5SPhilippe Mathieu-Daudé { \ 156*10f7d4d5SPhilippe Mathieu-Daudé DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \ 157*10f7d4d5SPhilippe Mathieu-Daudé return BSWAP(atomic_##X(haddr, BSWAP(val))); \ 158*10f7d4d5SPhilippe Mathieu-Daudé } 159*10f7d4d5SPhilippe Mathieu-Daudé 160*10f7d4d5SPhilippe Mathieu-Daudé GEN_ATOMIC_HELPER(fetch_and) 161*10f7d4d5SPhilippe Mathieu-Daudé GEN_ATOMIC_HELPER(fetch_or) 162*10f7d4d5SPhilippe Mathieu-Daudé GEN_ATOMIC_HELPER(fetch_xor) 163*10f7d4d5SPhilippe Mathieu-Daudé GEN_ATOMIC_HELPER(and_fetch) 164*10f7d4d5SPhilippe Mathieu-Daudé GEN_ATOMIC_HELPER(or_fetch) 165*10f7d4d5SPhilippe Mathieu-Daudé GEN_ATOMIC_HELPER(xor_fetch) 166*10f7d4d5SPhilippe Mathieu-Daudé 167*10f7d4d5SPhilippe Mathieu-Daudé #undef GEN_ATOMIC_HELPER 168*10f7d4d5SPhilippe Mathieu-Daudé 169*10f7d4d5SPhilippe Mathieu-Daudé /* Note that for addition, we need to use a separate cmpxchg loop instead 170*10f7d4d5SPhilippe Mathieu-Daudé of bswaps for the reverse-host-endian helpers. */ 171*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE ATOMIC_NAME(fetch_add)(CPUArchState *env, target_ulong addr, 172*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE val EXTRA_ARGS) 173*10f7d4d5SPhilippe Mathieu-Daudé { 174*10f7d4d5SPhilippe Mathieu-Daudé DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; 175*10f7d4d5SPhilippe Mathieu-Daudé DATA_TYPE ldo, ldn, ret, sto; 176*10f7d4d5SPhilippe Mathieu-Daudé 177*10f7d4d5SPhilippe Mathieu-Daudé ldo = atomic_read__nocheck(haddr); 178*10f7d4d5SPhilippe Mathieu-Daudé while (1) { 179*10f7d4d5SPhilippe Mathieu-Daudé ret = BSWAP(ldo); 180*10f7d4d5SPhilippe Mathieu-Daudé sto = BSWAP(ret + val); 181*10f7d4d5SPhilippe Mathieu-Daudé ldn = atomic_cmpxchg__nocheck(haddr, ldo, sto); 182*10f7d4d5SPhilippe Mathieu-Daudé if (ldn == ldo) { 183*10f7d4d5SPhilippe Mathieu-Daudé return ret; 184*10f7d4d5SPhilippe Mathieu-Daudé } 185*10f7d4d5SPhilippe Mathieu-Daudé ldo = ldn; 186*10f7d4d5SPhilippe Mathieu-Daudé } 187*10f7d4d5SPhilippe Mathieu-Daudé } 188*10f7d4d5SPhilippe Mathieu-Daudé 189*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE ATOMIC_NAME(add_fetch)(CPUArchState *env, target_ulong addr, 190*10f7d4d5SPhilippe Mathieu-Daudé ABI_TYPE val EXTRA_ARGS) 191*10f7d4d5SPhilippe Mathieu-Daudé { 192*10f7d4d5SPhilippe Mathieu-Daudé DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; 193*10f7d4d5SPhilippe Mathieu-Daudé DATA_TYPE ldo, ldn, ret, sto; 194*10f7d4d5SPhilippe Mathieu-Daudé 195*10f7d4d5SPhilippe Mathieu-Daudé ldo = atomic_read__nocheck(haddr); 196*10f7d4d5SPhilippe Mathieu-Daudé while (1) { 197*10f7d4d5SPhilippe Mathieu-Daudé ret = BSWAP(ldo) + val; 198*10f7d4d5SPhilippe Mathieu-Daudé sto = BSWAP(ret); 199*10f7d4d5SPhilippe Mathieu-Daudé ldn = atomic_cmpxchg__nocheck(haddr, ldo, sto); 200*10f7d4d5SPhilippe Mathieu-Daudé if (ldn == ldo) { 201*10f7d4d5SPhilippe Mathieu-Daudé return ret; 202*10f7d4d5SPhilippe Mathieu-Daudé } 203*10f7d4d5SPhilippe Mathieu-Daudé ldo = ldn; 204*10f7d4d5SPhilippe Mathieu-Daudé } 205*10f7d4d5SPhilippe Mathieu-Daudé } 206*10f7d4d5SPhilippe Mathieu-Daudé #endif /* DATA_SIZE >= 16 */ 207*10f7d4d5SPhilippe Mathieu-Daudé 208*10f7d4d5SPhilippe Mathieu-Daudé #undef END 209*10f7d4d5SPhilippe Mathieu-Daudé #endif /* DATA_SIZE > 1 */ 210*10f7d4d5SPhilippe Mathieu-Daudé 211*10f7d4d5SPhilippe Mathieu-Daudé #undef BSWAP 212*10f7d4d5SPhilippe Mathieu-Daudé #undef ABI_TYPE 213*10f7d4d5SPhilippe Mathieu-Daudé #undef DATA_TYPE 214*10f7d4d5SPhilippe Mathieu-Daudé #undef SUFFIX 215*10f7d4d5SPhilippe Mathieu-Daudé #undef DATA_SIZE 216