如何从内存中的地址检索单个字节并将其值作为浮点数移动到xmm寄存器中? (例如,如果在地址位置有一个字节123,我希望能够使用sse指令对此值123 + 5等进行浮点运算。)
我是大会的新手,我希望这个问题有意义。我已经尝试了一些比较随机的事情(例如先移至al
并从那里移至xmm-但不知道如何继续转换为float ...);也许有人可以指出我正确的方向?
答案 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
指令。