1/* 2 * SPDX-License-Identifier: GPL-2.0-or-later 3 * Atomic extract 64 from 128-bit, AArch64 version. 4 * 5 * Copyright (C) 2023 Linaro, Ltd. 6 */ 7 8#ifndef AARCH64_LOAD_EXTRACT_AL16_AL8_H 9#define AARCH64_LOAD_EXTRACT_AL16_AL8_H 10 11#include "host/cpuinfo.h" 12#include "tcg/debug-assert.h" 13 14/** 15 * load_atom_extract_al16_or_al8: 16 * @pv: host address 17 * @s: object size in bytes, @s <= 8. 18 * 19 * Load @s bytes from @pv, when pv % s != 0. If [p, p+s-1] does not 20 * cross an 16-byte boundary then the access must be 16-byte atomic, 21 * otherwise the access must be 8-byte atomic. 22 */ 23static inline uint64_t load_atom_extract_al16_or_al8(void *pv, int s) 24{ 25 uintptr_t pi = (uintptr_t)pv; 26 __int128_t *ptr_align = (__int128_t *)(pi & ~7); 27 int shr = (pi & 7) * 8; 28 uint64_t l, h; 29 30 /* 31 * With FEAT_LSE2, LDP is single-copy atomic if 16-byte aligned 32 * and single-copy atomic on the parts if 8-byte aligned. 33 * All we need do is align the pointer mod 8. 34 */ 35 tcg_debug_assert(HAVE_ATOMIC128_RO); 36 asm("ldp %0, %1, %2" : "=r"(l), "=r"(h) : "m"(*ptr_align)); 37 return (l >> shr) | (h << (-shr & 63)); 38} 39 40#endif /* AARCH64_LOAD_EXTRACT_AL16_AL8_H */ 41