Assembly 为什么MSVC std::atomic使用ldrexd而不是ldrd?
MSVC为32位ARM定义了Assembly 为什么MSVC std::atomic使用ldrexd而不是ldrd?,assembly,visual-c++,arm,stdatomic,Assembly,Visual C++,Arm,Stdatomic,MSVC为32位ARM定义了\uuuu ldrexd固有特性。它发出ldrexd指令。 MSVC还为所有内容定义了内在的\uu iso\u volatile\u load64。它在32位ARM上发出ldrd指令 MSVC为32位ARM提供了一种特殊情况,即精确地使用\uuuu ldrexd而不是\uuu iso\u volatile\u load64,请参见: \u NODISCARD _tyload()const noexcept{//load具有顺序一致性 const auto _Mem=_
\uuuu ldrexd
固有特性。它发出ldrexd
指令。
MSVC还为所有内容定义了内在的\uu iso\u volatile\u load64
。它在32位ARM上发出ldrd
指令
MSVC为32位ARM提供了一种特殊情况,即精确地使用\uuuu ldrexd
而不是\uuu iso\u volatile\u load64
,请参见:
\u NODISCARD _tyload()const noexcept{//load具有顺序一致性
const auto _Mem=_原子地址_as(_存储器);
long long_作为_字节;
#ifdef_M_臂
_As_字节=u ldrexd(_Mem);
_记忆障碍();
#否则
_As_字节=uu iso_volatile_load64(_Mem);
_编译器或内存屏障();
#恩迪夫
返回reinterpret_cast(_为_字节);
}
在哪些情况下,
\uuuuuLDREXD
优于\uuuuLDRD
?在arm文档中明确定义了ldrexd vs ldrd,以及它的作用。ldrex并不优于,因为它有一个特殊的用途,它将被访问的域留在或保持在独占访问域中。接下来是一个记忆障碍,这很有趣。我曾看到ldrex/strex被误解并被错误使用,因此这里可能是这种情况,或者这是具有特定用途的事物组合的一部分。两者都将执行64位对齐读取。如文件所述,一方设置独占访问,另一方不设置。(假设这些函数/定义成为实际指令)您不了解arm文档的哪一部分。armv7-a文档在软件方面比armv6做得更好。但您希望获得axi文档,以了解真正的区别是什么,以及专用访问与非专用访问的硬件要求(芯片供应商或arm的一级缓存等)是什么。在arms网站上也很容易找到。@old_timer,从文档中可以看出,在这里使用ldrexd
毫无意义,所以我在外面寻找真相。(我也不是为arm开发,我只是对它感兴趣,因为我将来可能需要代码中的支持)它对我来说也没有意义。微软对此有何评论?目前尚无答案。而且:strexd
甚至不能作为一个内在的,因此\uuuu ldrexd
显然是为这个用途而公开的。arm文档中明确定义了ldrd和ldrd,以及它的作用。ldrex并不优于,因为它有一个特殊的用途,它将被访问的域留在或保持在独占访问域中。接下来是一个记忆障碍,这很有趣。我曾看到ldrex/strex被误解并被错误使用,因此这里可能是这种情况,或者这是具有特定用途的事物组合的一部分。两者都将执行64位对齐读取。如文件所述,一方设置独占访问,另一方不设置。(假设这些函数/定义成为实际指令)您不了解arm文档的哪一部分。armv7-a文档在软件方面比armv6做得更好。但您希望获得axi文档,以了解真正的区别是什么,以及专用访问与非专用访问的硬件要求(芯片供应商或arm的一级缓存等)是什么。在arms网站上也很容易找到。@old_timer,从文档中可以看出,在这里使用ldrexd
毫无意义,所以我在外面寻找真相。(我也不是为arm开发,我只是对它感兴趣,因为我将来可能需要代码中的支持)它对我来说也没有意义。微软对此有何评论?目前尚无答案。而且:strexd
甚至不能作为一个内在版本使用,因此\uuuu ldrexd
显然暴露了这种用法
_NODISCARD _Ty load() const noexcept { // load with sequential consistency
const auto _Mem = _Atomic_address_as<long long>(_Storage);
long long _As_bytes;
#ifdef _M_ARM
_As_bytes = __ldrexd(_Mem);
_Memory_barrier();
#else
_As_bytes = __iso_volatile_load64(_Mem);
_Compiler_or_memory_barrier();
#endif
return reinterpret_cast<_Ty&>(_As_bytes);
}