1*e4751d34SPhilippe Mathieu-Daudé/*
2*e4751d34SPhilippe Mathieu-Daudé * SPDX-License-Identifier: GPL-2.0-or-later
3*e4751d34SPhilippe Mathieu-Daudé * Atomic store insert into 128-bit, AArch64 version.
4*e4751d34SPhilippe Mathieu-Daudé *
5*e4751d34SPhilippe Mathieu-Daudé * Copyright (C) 2023 Linaro, Ltd.
6*e4751d34SPhilippe Mathieu-Daudé */
7*e4751d34SPhilippe Mathieu-Daudé
8*e4751d34SPhilippe Mathieu-Daudé#ifndef AARCH64_STORE_INSERT_AL16_H
9*e4751d34SPhilippe Mathieu-Daudé#define AARCH64_STORE_INSERT_AL16_H
10*e4751d34SPhilippe Mathieu-Daudé
11*e4751d34SPhilippe Mathieu-Daudé/**
12*e4751d34SPhilippe Mathieu-Daudé * store_atom_insert_al16:
13*e4751d34SPhilippe Mathieu-Daudé * @p: host address
14*e4751d34SPhilippe Mathieu-Daudé * @val: shifted value to store
15*e4751d34SPhilippe Mathieu-Daudé * @msk: mask for value to store
16*e4751d34SPhilippe Mathieu-Daudé *
17*e4751d34SPhilippe Mathieu-Daudé * Atomically store @val to @p masked by @msk.
18*e4751d34SPhilippe Mathieu-Daudé */
19*e4751d34SPhilippe Mathieu-Daudéstatic inline void ATTRIBUTE_ATOMIC128_OPT
20*e4751d34SPhilippe Mathieu-Daudéstore_atom_insert_al16(Int128 *ps, Int128 val, Int128 msk)
21*e4751d34SPhilippe Mathieu-Daudé{
22*e4751d34SPhilippe Mathieu-Daudé    /*
23*e4751d34SPhilippe Mathieu-Daudé     * GCC only implements __sync* primitives for int128 on aarch64.
24*e4751d34SPhilippe Mathieu-Daudé     * We can do better without the barriers, and integrating the
25*e4751d34SPhilippe Mathieu-Daudé     * arithmetic into the load-exclusive/store-conditional pair.
26*e4751d34SPhilippe Mathieu-Daudé     */
27*e4751d34SPhilippe Mathieu-Daudé    uint64_t tl, th, vl, vh, ml, mh;
28*e4751d34SPhilippe Mathieu-Daudé    uint32_t fail;
29*e4751d34SPhilippe Mathieu-Daudé
30*e4751d34SPhilippe Mathieu-Daudé    qemu_build_assert(!HOST_BIG_ENDIAN);
31*e4751d34SPhilippe Mathieu-Daudé    vl = int128_getlo(val);
32*e4751d34SPhilippe Mathieu-Daudé    vh = int128_gethi(val);
33*e4751d34SPhilippe Mathieu-Daudé    ml = int128_getlo(msk);
34*e4751d34SPhilippe Mathieu-Daudé    mh = int128_gethi(msk);
35*e4751d34SPhilippe Mathieu-Daudé
36*e4751d34SPhilippe Mathieu-Daudé    asm("0: ldxp %[l], %[h], %[mem]\n\t"
37*e4751d34SPhilippe Mathieu-Daudé        "bic %[l], %[l], %[ml]\n\t"
38*e4751d34SPhilippe Mathieu-Daudé        "bic %[h], %[h], %[mh]\n\t"
39*e4751d34SPhilippe Mathieu-Daudé        "orr %[l], %[l], %[vl]\n\t"
40*e4751d34SPhilippe Mathieu-Daudé        "orr %[h], %[h], %[vh]\n\t"
41*e4751d34SPhilippe Mathieu-Daudé        "stxp %w[f], %[l], %[h], %[mem]\n\t"
42*e4751d34SPhilippe Mathieu-Daudé        "cbnz %w[f], 0b\n"
43*e4751d34SPhilippe Mathieu-Daudé        : [mem] "+Q"(*ps), [f] "=&r"(fail), [l] "=&r"(tl), [h] "=&r"(th)
44*e4751d34SPhilippe Mathieu-Daudé        : [vl] "r"(vl), [vh] "r"(vh), [ml] "r"(ml), [mh] "r"(mh));
45*e4751d34SPhilippe Mathieu-Daudé}
46*e4751d34SPhilippe Mathieu-Daudé
47*e4751d34SPhilippe Mathieu-Daudé#endif /* AARCH64_STORE_INSERT_AL16_H */
48