将单个字节从存储器移动到浮点数的xmm寄存器

时间:2018-07-29 16:25:42

标签: assembly x86 sse simd

如何从内存中的地址检索单个字节并将其作为浮点数移动到xmm寄存器中? (例如,如果在地址位置有一个字节123,我希望能够使用sse指令对此值123 + 5等进行浮点运算。)

我是大会的新手,我希望这个问题有意义。我已经尝试了一些比较随机的事情(例如先移至al并从那里移至xmm-但不知道如何继续转换为float ...);也许有人可以指出我正确的方向?

1 个答案:

答案 0 :(得分:4)

一种显而易见的标量方式,就像您从编译器(http://godbolt.org/)中获得的一样:

movzx     eax,  byte [mem]         ; zero extend.  Use movsx to sign-extend
cvtsi2ss  xmm0, eax

这在桑迪布里奇(Sandybridge)家庭上总共花费了3英镑。 (cvtsi2ss是2)。

请注意,cvtsi2ss的设计很差,并且会合并到XMM0的旧值中,因此它具有错误的依赖性。 gcc倾向于首先pxor xmm0,xmm0来打破依赖关系,但是如果最近没有使用XMM0,那应该没问题。使用AVX,您可以将一个XMM寄存器清零,然后将其重复用作多次转换的安全无依赖源。

vxorps   xmm0, xmm0, xmm0

;then repeated multiple times:
vcvtsi2ss  xmm1, xmm0, eax       ; xmm1 is write-only, no false dep

如果SSE4.1可用,并且可以在所需的字节之后读取3个字节(读取未映射的页面不会出现段错误,并且没有来自缓存行或页面拆分的性能问题),则可以执行以下操作:

pmovzxbd    xmm0,  dword [mem]       ; byte->dword packed zero extend
cvtdq2ps    xmm1,  xmm0              ; packed-convert of int32 to float

这在SnB系列上总共花费了2 uop:pmovzx/sx(具有XMM目标)可以对负载进行微熔合。 (但不是AVX2 YMM版本)。 (http://agner.org/optimize/)。

当然,如果您实际上想 转换4个连续的字节,则这非常好。否则,如果您进行了多次转换,则可能会改组cvt指令。