Changeset 104795 in vbox for trunk/include
- Timestamp:
- May 27, 2024 8:08:37 PM (8 months ago)
- Location:
- trunk/include/iprt
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/asm.h
r103082 r104795 2560 2560 */ 2561 2561 DECLINLINE(bool) ASMAtomicCmpXchgU128U(volatile RTUINT128U *pu128, const RTUINT128U u128New, 2562 2562 const RTUINT128U u128Old, PRTUINT128U pu128Old) RT_NOTHROW_DEF 2563 2563 { 2564 2564 # if (defined(__clang_major__) || defined(__GNUC__)) && defined(RT_ARCH_ARM64) … … 3523 3523 3524 3524 3525 /** @def RTASM_HAVE_READ_U128 3526 * Defined in the target architecture supports atomic reading of 128-bit 3527 * integers. 3528 * 3529 * The define value is zero if both ordered and unordered reads are implemented 3530 * using ASMAtomicCmpXchgU128v2(). It is 1 if unordered reads are done natively 3531 * w/o cmpxchg and 3 if both variants are done natively w/o cmpxchg. 3532 * 3533 * @note AMD64: Caller must check for cmpxchg16b support before use and make 3534 * sure variables are writable (won't be changed). 3535 * @sa RTASM_HAVE_CMP_XCHG_U128, RTASM_HAVE_WRITE_U128 3536 */ 3537 #if defined(RT_ARCH_ARM64) || defined(DOXYGEN_RUNNING) 3538 # define RTASM_HAVE_READ_U128 3 3539 #elif defined(RTASM_HAVE_CMP_XCHG_U128) 3540 # define RTASM_HAVE_READ_U128 0 3541 #endif 3542 3543 #ifdef RTASM_HAVE_READ_U128 3544 3545 /** 3546 * Atomically reads an unsigned 128-bit value, ordered. 3547 * 3548 * @returns Current *pu128 value 3549 * @param pu128 Pointer to the 128-bit variable to read. 3550 * The memory pointed to must be writable. 3551 * 3552 * @remarks AMD64: Requires the memory to be both readable and writable. 3553 * @remarks AMD64: Requires support for cmpxchg16b. 3554 */ 3555 DECLINLINE(uint128_t) ASMAtomicReadU128(volatile uint128_t RT_FAR *pu128) RT_NOTHROW_DEF 3556 { 3557 Assert(!((uintptr_t)pu128 & 15)); 3558 # if defined(__GNUC__) && defined(RT_ARCH_ARM64) 3559 RTUINT128U u128Ret; 3560 __asm__ __volatile__("Lstart_ASMAtomicReadU128_%=:\n\t" 3561 RTASM_ARM_DMB_SY 3562 "ldp %[uRetLo], %[uRetHi], %[pMem]\n\t" 3563 RTASM_ARM_DMB_SY 3564 : [uRetHi] "=r" (u128Ret.s.Hi) 3565 , [uRetLo] "=r" (u128Ret.s.Lo) 3566 : [pMem] "Q" (*pu128) 3567 : ); 3568 return u128Ret.u; 3569 # else 3570 uint128_t u128Ret; 3571 ASMAtomicCmpXchgU128v2(pu128, 0, 0, 0, 0, &u128Ret); 3572 return u128Ret; 3573 # endif 3574 } 3575 3576 /** 3577 * Atomically reads an unsigned 128-bit value, ordered. 3578 * 3579 * @returns Current *pu128 value 3580 * @param pu128 Pointer to the 128-bit variable to read. 3581 * The memory pointed to must be writable. 3582 * 3583 * @remarks AMD64: Requires the memory to be both readable and writable. 3584 * @remarks AMD64: Requires support for cmpxchg16b. 3585 */ 3586 DECLINLINE(RTUINT128U) ASMAtomicReadU128U(volatile RTUINT128U RT_FAR *pu128) RT_NOTHROW_DEF 3587 { 3588 Assert(!((uintptr_t)pu128 & 15)); 3589 RTUINT128U u128Ret; 3590 # if defined(__GNUC__) && defined(RT_ARCH_ARM64) 3591 __asm__ __volatile__("Lstart_ASMAtomicReadU128U_%=:\n\t" 3592 RTASM_ARM_DMB_SY 3593 "ldp %[uRetLo], %[uRetHi], %[pMem]\n\t" 3594 RTASM_ARM_DMB_SY 3595 : [uRetHi] "=r" (u128Ret.s.Hi) 3596 , [uRetLo] "=r" (u128Ret.s.Lo) 3597 : [pMem] "Q" (*pu128) 3598 : ); 3599 return u128Ret; 3600 # else 3601 ASMAtomicCmpXchgU128v2(&pu128->u, 0, 0, 0, 0, &u128Ret.u); 3602 return u128Ret; 3603 # endif 3604 } 3605 3606 3607 /** 3608 * Atomically reads an unsigned 128-bit value, unordered. 3609 * 3610 * @returns Current *pu128 value 3611 * @param pu128 Pointer to the 128-bit variable to read. 3612 * The memory pointed to must be writable. 3613 * 3614 * @remarks AMD64: Requires the memory to be both readable and writable. 3615 * @remarks AMD64: Requires support for cmpxchg16b. 3616 * @remarks AMD64: Is ordered. 3617 */ 3618 DECLINLINE(uint128_t) ASMAtomicUoReadU128(volatile uint128_t RT_FAR *pu128) RT_NOTHROW_DEF 3619 { 3620 Assert(!((uintptr_t)pu128 & 15)); 3621 # if defined(__GNUC__) && defined(RT_ARCH_ARM64) 3622 RTUINT128U u128Ret; 3623 __asm__ __volatile__("Lstart_ASMAtomicUoReadU128_%=:\n\t" 3624 "ldp %[uRetLo], %[uRetHi], %[pMem]\n\t" 3625 : [uRetHi] "=r" (u128Ret.s.Hi) 3626 , [uRetLo] "=r" (u128Ret.s.Lo) 3627 : [pMem] "Q" (*pu128) 3628 : ); 3629 return u128Ret.u; 3630 3631 # elif defined(RT_ARCH_AMD64) && 0 3632 /* This doesn't work because __m128i can't be made volatile and we're not 3633 able to force MSC (2019) to emit _mm_load_si128 (besides it emits movdqu 3634 instead of movdqa). */ 3635 __m128i uTmpSse = _mm_load_si128((__m128i volatile *)pu128); 3636 __m128i uTmpSseHi = _mm_srli_si128(uTmpSse, 64 / 8); 3637 RTUINT128U u128Ret; 3638 u128Ret.s.Lo = (uint64_t)_mm_cvtsi128_si64(uTmpSse); 3639 u128Ret.s.Hi = (uint64_t)_mm_cvtsi128_si64(uTmpSseHi); 3640 return u128Ret.u; 3641 3642 # else 3643 return ASMAtomicReadU128(pu128); 3644 # endif 3645 } 3646 3647 /** 3648 * Atomically reads an unsigned 128-bit value, unordered. 3649 * 3650 * @returns Current *pu128 value 3651 * @param pu128 Pointer to the 128-bit variable to read. 3652 * The memory pointed to must be writable. 3653 * 3654 * @remarks AMD64: Requires the memory to be both readable and writable. 3655 * @remarks AMD64: Requires support for cmpxchg16b. 3656 * @remarks AMD64: Is ordered. 3657 */ 3658 DECLINLINE(RTUINT128U) ASMAtomicUoReadU128U(volatile RTUINT128U RT_FAR *pu128) RT_NOTHROW_DEF 3659 { 3660 Assert(!((uintptr_t)pu128 & 15)); 3661 # if defined(__GNUC__) && defined(RT_ARCH_ARM64) 3662 RTUINT128U u128Ret; 3663 __asm__ __volatile__("Lstart_ASMAtomicUoReadU128U_%=:\n\t" 3664 "ldp %[uRetLo], %[uRetHi], %[pMem]\n\t" 3665 : [uRetHi] "=r" (u128Ret.s.Hi) 3666 , [uRetLo] "=r" (u128Ret.s.Lo) 3667 : [pMem] "Q" (*pu128) 3668 : ); 3669 return u128Ret; 3670 # else 3671 return ASMAtomicReadU128U(pu128); 3672 # endif 3673 } 3674 3675 #endif /* RTASM_HAVE_READ_U128 */ 3676 3525 3677 /** 3526 3678 * Atomically reads a size_t value, ordered. … … 4052 4204 } 4053 4205 4206 4207 /** @def RTASM_HAVE_WRITE_U128 4208 * Defined in the target architecture supports atomic of 128-bit integers. 4209 * 4210 * The define value is zero if both ordered and unordered writes are implemented 4211 * using ASMAtomicCmpXchgU128v2(). It is 1 if unordered writes are done 4212 * natively w/o cmpxchg and 3 if both variants are done natively w/o cmpxchg. 4213 * 4214 * @note AMD64: Caller must check for cmpxchg16b support before use. 4215 * @sa RTASM_HAVE_CMP_XCHG_U128 4216 */ 4217 #if defined(RT_ARCH_ARM64) || defined(DOXYGEN_RUNNING) 4218 # define RTASM_HAVE_WRITE_U128 3 4219 #elif defined(RTASM_HAVE_CMP_XCHG_U128) 4220 # define RTASM_HAVE_WRITE_U128 0 4221 #endif 4222 4223 #ifdef RTASM_HAVE_WRITE_U128 4224 4225 /** 4226 * Atomically writes an unsigned 128-bit value, ordered. 4227 * 4228 * @param pu128 Pointer to the variable to overwrite. Must be aligned 4229 * on 16 byte boundrary. 4230 * @param u64Hi The high 64 bits of the new value. 4231 * @param u64Lo The low 64 bits of the new value. 4232 */ 4233 DECLINLINE(void) ASMAtomicWriteU128v2(volatile uint128_t *pu128, const uint64_t u64Hi, const uint64_t u64Lo) RT_NOTHROW_DEF 4234 { 4235 Assert(!((uintptr_t)pu128 & 15)); 4236 # if defined(__GNUC__) && defined(RT_ARCH_ARM64) 4237 __asm__ __volatile__("Lstart_ASMAtomicWriteU128v2_%=:\n\t" 4238 # if 0 && defined(RTASM_ARM64_USE_FEAT_LSE128) /** @todo hw support? test + debug */ 4239 RTASM_ARM_DMB_SY 4240 "swpp %[uValueLo], %[uValueHi], %[pMem]\n\t" 4241 # else 4242 RTASM_ARM_DMB_SY 4243 "stp %[uValueLo], %[uValueHi], %[pMem]\n\t" 4244 "dmb sy\n\t" 4245 # endif 4246 : [pMem] "+Q" (*pu128) 4247 : [uValueHi] "r" (u64Hi) 4248 , [uValueLo] "r" (u64Lo) 4249 : ); 4250 4251 # else 4252 RTUINT128U u128Old; 4253 # ifdef RT_COMPILER_WITH_128BIT_INT_TYPES 4254 u128Old.u = *pu128; 4255 # else 4256 u128Old.u.Lo = pu128->Lo; 4257 u128Old.u.Hi = pu128->Hi; 4258 # endif 4259 while (!ASMAtomicCmpXchgU128v2(pu128, u64Hi, u64Lo, u128Old.s.Hi, u128Old.s.Lo, &u128Old.u)) 4260 { } 4261 # endif 4262 } 4263 4264 4265 /** 4266 * Atomically writes an unsigned 128-bit value, ordered. 4267 * 4268 * @param pu128 Pointer to the variable to overwrite. Must be aligned 4269 * on 16 byte boundrary. 4270 * @param u64Hi The high 64 bits of the new value. 4271 * @param u64Lo The low 64 bits of the new value. 4272 * @note This is ordered on AMD64. 4273 */ 4274 DECLINLINE(void) ASMAtomicUoWriteU128v2(volatile uint128_t *pu128, const uint64_t u64Hi, const uint64_t u64Lo) RT_NOTHROW_DEF 4275 { 4276 Assert(!((uintptr_t)pu128 & 15)); 4277 # if defined(__GNUC__) && defined(RT_ARCH_ARM64) 4278 __asm__ __volatile__("Lstart_ASMAtomicUoWriteU128v2_%=:\n\t" 4279 "stp %[uValueLo], %[uValueHi], %[pMem]\n\t" 4280 : [pMem] "+Q" (*pu128) 4281 : [uValueHi] "r" (u64Hi) 4282 , [uValueLo] "r" (u64Lo) 4283 : ); 4284 4285 # else 4286 RTUINT128U u128Old; 4287 # ifdef RT_COMPILER_WITH_128BIT_INT_TYPES 4288 u128Old.u = *pu128; 4289 # else 4290 u128Old.u.Lo = pu128->Lo; 4291 u128Old.u.Hi = pu128->Hi; 4292 # endif 4293 while (!ASMAtomicCmpXchgU128v2(pu128, u64Hi, u64Lo, u128Old.s.Hi, u128Old.s.Lo, &u128Old.u)) 4294 { } 4295 # endif 4296 } 4297 4298 4299 /** 4300 * Atomically writes an unsigned 128-bit value, ordered. 4301 * 4302 * @param pu128 Pointer to the variable to overwrite. Must be aligned 4303 * on 16 byte boundrary. 4304 * @param u128 The the new value. 4305 */ 4306 DECLINLINE(void) ASMAtomicWriteU128(volatile uint128_t *pu128, const uint128_t u128) RT_NOTHROW_DEF 4307 { 4308 # ifdef RT_COMPILER_WITH_128BIT_INT_TYPES 4309 ASMAtomicWriteU128v2(pu128, (uint64_t)(u128 >> 64), (uint64_t)u128); 4310 # else 4311 ASMAtomicWriteU128v2(pu128, u128.Hi, u128.Lo); 4312 # endif 4313 } 4314 4315 4316 /** 4317 * Atomically writes an unsigned 128-bit value, unordered. 4318 * 4319 * @param pu128 Pointer to the variable to overwrite. Must be aligned 4320 * on 16 byte boundrary. 4321 * @param u128 The the new value. 4322 * @note This is ordered on AMD64. 4323 */ 4324 DECLINLINE(void) ASMAtomicUoWriteU128(volatile uint128_t *pu128, const uint128_t u128) RT_NOTHROW_DEF 4325 { 4326 # ifdef RT_COMPILER_WITH_128BIT_INT_TYPES 4327 ASMAtomicUoWriteU128v2(pu128, (uint64_t)(u128 >> 64), (uint64_t)u128); 4328 # else 4329 ASMAtomicUoWriteU128v2(pu128, u128.Hi, u128.Lo); 4330 # endif 4331 } 4332 4333 4334 /** 4335 * Atomically writes an unsigned 128-bit value, ordered. 4336 * 4337 * @param pu128 Pointer to the variable to overwrite. Must be aligned 4338 * on 16 byte boundrary. 4339 * @param u128 The the new value. 4340 */ 4341 DECLINLINE(void) ASMAtomicWriteU128U(volatile RTUINT128U *pu128, const RTUINT128U u128) RT_NOTHROW_DEF 4342 { 4343 ASMAtomicWriteU128v2(&pu128->u, u128.s.Hi, u128.s.Lo); 4344 } 4345 4346 4347 /** 4348 * Atomically writes an unsigned 128-bit value, unordered. 4349 * 4350 * @param pu128 Pointer to the variable to overwrite. Must be aligned 4351 * on 16 byte boundrary. 4352 * @param u128 The the new value. 4353 * @note This is ordered on AMD64. 4354 */ 4355 DECLINLINE(void) ASMAtomicUoWriteU128U(volatile RTUINT128U *pu128, const RTUINT128U u128) RT_NOTHROW_DEF 4356 { 4357 ASMAtomicUoWriteU128v2(&pu128->u, u128.s.Hi, u128.s.Lo); 4358 } 4359 4360 #endif /* RTASM_HAVE_WRITE_U128 */ 4054 4361 4055 4362 /** -
trunk/include/iprt/types.h
r101140 r104795 496 496 /** 497 497 * 128-bit unsigned integer union. 498 * 499 * @note This is not necessarily automatically 16 byte aligned. Sorry. 498 500 */ 499 501 #pragma pack(1)
Note:
See TracChangeset
for help on using the changeset viewer.