将单个字节从内存移动到 xmm 寄存器作为 float
Move single byte from memory to xmm register as float
如何从内存中的地址检索单个字节并将其 值 作为浮点数移动到 xmm 寄存器中? (例如,如果在地址位置有一个字节 123,我希望能够使用 sse 指令对该值、123+5 等进行浮点运算。)
我是汇编的新手,我希望这个问题是有道理的。我已经相当随机地尝试了几件事(例如首先移动到 al
然后从那里移动到 xmm - 但不知道如何继续转换为 float ...);也许有人可以指出正确的方向?
明显的标量方式,就像您从编译器中获得的那样 (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 个微指令:pmovzx/sx
XMM 目的地可以微熔断负载。 (但不是 AVX2 YMM 版本)。 (http://agner.org/optimize/).
当然,如果您确实想要转换 4 个连续的字节,这当然很棒。否则,如果您有多个转化,您可能会随机设置 cvt
指令。
如何从内存中的地址检索单个字节并将其 值 作为浮点数移动到 xmm 寄存器中? (例如,如果在地址位置有一个字节 123,我希望能够使用 sse 指令对该值、123+5 等进行浮点运算。)
我是汇编的新手,我希望这个问题是有道理的。我已经相当随机地尝试了几件事(例如首先移动到 al
然后从那里移动到 xmm - 但不知道如何继续转换为 float ...);也许有人可以指出正确的方向?
明显的标量方式,就像您从编译器中获得的那样 (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 个微指令:pmovzx/sx
XMM 目的地可以微熔断负载。 (但不是 AVX2 YMM 版本)。 (http://agner.org/optimize/).
当然,如果您确实想要转换 4 个连续的字节,这当然很棒。否则,如果您有多个转化,您可能会随机设置 cvt
指令。