有没有办法增加 xmm 寄存器中的值?
Is there a way to increase a value in a xmm register?
我想知道,有没有办法增加 xmm 寄存器中的值,或者只能将一个值移入一个值?
我的意思是,你可以这样做:
inc eax
或者像这样:
inc [ebp+7F00F000]
有没有办法用 xmm 做同样的事情?
我试过一些类似的东西,但是......它不起作用
inc [rbx+08]
movss xmm1,[rbx+08]
我什至尝试过一些非常愚蠢的方法,但也没有用
push edx
pextrw edx,xmm2,0
add edx,1
mov [rbx+08],edx
movss xmm1,[rbx+08]
pop edx
简而言之,不,不是你想的那样。
在 SSE 下,所有原始的 XMM 寄存器都是浮点寄存器。浮点数没有自增运算
SSE2增加了一些整型寄存器,但还是没有增量。这些寄存器和添加的运算实际上是为高速算术运算而设计的,包括点积、四舍五入的精确积等。
递增运算是您期望应用于通用寄存器或累加器的东西。
您可能会发现 this set of slides 在总体概述和功能方面有些信息。
xmm regs 没有 inc
等价物,也没有 paddw
的立即操作数形式(因此也没有 add eax, 1
等价物)。
paddw
(and other element sizes) are only available with xmm/m128 source operands. So if you want to increment one element of a vector, you need to load a constant from memory, .
例如增加 xmm0 的所有元素的最便宜的方法是:
; outside the loop
pcmpeqw xmm1,xmm1 # xmm1 = all-ones = -1
; inside the loop
psubw xmm0, xmm1 ; xmm0 -= -1 (in each element). i.e. xmm0++
或者
paddw xmm0, [ones] ; where ones is a static constant.
如果构建常量需要多于两条指令,或者寄存器压力有问题,那么从内存中加载常量可能是个好主意。
如果你想构造一个常量来仅递增低 32 位元素,例如,你可以使用字节移位将其他元素归零:
; hoisted out of the loop
pcmpeqw xmm1,xmm1 # xmm1 = all-ones = -1
psrldq xmm1, 12 # xmm1 = [ 0 0 0 -1 ]
; in the loop
psubd xmm0, xmm1
如果您的尝试应该只是增加 xmm2 中的低 16 位元素,那么是的,这是一个愚蠢的尝试。 IDK 你正在做什么存储到 [rbx+8]
然后加载到 xmm1(将高 96 位归零)。
以下是如何以不那么笨的方式编写 xmm -> gp -> xmm 往返。 (与具有矢量常数的 paddw
相比仍然很糟糕)。
# don't push/pop. Instead, pick a register you can clobber without saving/restoring
movd edx, xmm2 # this is the cheapest way to get the low 16. It doesn't matter that we also get the element 1 as garbage in the high half of edx
inc edx # we only care about dx, but this is still the most efficient instruction
pinsrw xmm2, edx, 0 # normally you'd just use movd again, but we actually want to merge with the old contents.
如果您想使用 16 位以外的元素,您可以使用 SSE4.1 pinsrb
/d
/q
,或者使用 movd
和随机播放。
参见 Agner Fog's Optimize Assembly guide for more good tips on how to use SSE vectors. Also other links in the x86 标签 wiki。
我想知道,有没有办法增加 xmm 寄存器中的值,或者只能将一个值移入一个值?
我的意思是,你可以这样做:
inc eax
或者像这样:
inc [ebp+7F00F000]
有没有办法用 xmm 做同样的事情?
我试过一些类似的东西,但是......它不起作用
inc [rbx+08]
movss xmm1,[rbx+08]
我什至尝试过一些非常愚蠢的方法,但也没有用
push edx
pextrw edx,xmm2,0
add edx,1
mov [rbx+08],edx
movss xmm1,[rbx+08]
pop edx
简而言之,不,不是你想的那样。
在 SSE 下,所有原始的 XMM 寄存器都是浮点寄存器。浮点数没有自增运算
SSE2增加了一些整型寄存器,但还是没有增量。这些寄存器和添加的运算实际上是为高速算术运算而设计的,包括点积、四舍五入的精确积等。
递增运算是您期望应用于通用寄存器或累加器的东西。
您可能会发现 this set of slides 在总体概述和功能方面有些信息。
xmm regs 没有 inc
等价物,也没有 paddw
的立即操作数形式(因此也没有 add eax, 1
等价物)。
paddw
(and other element sizes) are only available with xmm/m128 source operands. So if you want to increment one element of a vector, you need to load a constant from memory,
例如增加 xmm0 的所有元素的最便宜的方法是:
; outside the loop
pcmpeqw xmm1,xmm1 # xmm1 = all-ones = -1
; inside the loop
psubw xmm0, xmm1 ; xmm0 -= -1 (in each element). i.e. xmm0++
或者
paddw xmm0, [ones] ; where ones is a static constant.
如果构建常量需要多于两条指令,或者寄存器压力有问题,那么从内存中加载常量可能是个好主意。
如果你想构造一个常量来仅递增低 32 位元素,例如,你可以使用字节移位将其他元素归零:
; hoisted out of the loop
pcmpeqw xmm1,xmm1 # xmm1 = all-ones = -1
psrldq xmm1, 12 # xmm1 = [ 0 0 0 -1 ]
; in the loop
psubd xmm0, xmm1
如果您的尝试应该只是增加 xmm2 中的低 16 位元素,那么是的,这是一个愚蠢的尝试。 IDK 你正在做什么存储到 [rbx+8]
然后加载到 xmm1(将高 96 位归零)。
以下是如何以不那么笨的方式编写 xmm -> gp -> xmm 往返。 (与具有矢量常数的 paddw
相比仍然很糟糕)。
# don't push/pop. Instead, pick a register you can clobber without saving/restoring
movd edx, xmm2 # this is the cheapest way to get the low 16. It doesn't matter that we also get the element 1 as garbage in the high half of edx
inc edx # we only care about dx, but this is still the most efficient instruction
pinsrw xmm2, edx, 0 # normally you'd just use movd again, but we actually want to merge with the old contents.
如果您想使用 16 位以外的元素,您可以使用 SSE4.1 pinsrb
/d
/q
,或者使用 movd
和随机播放。
参见 Agner Fog's Optimize Assembly guide for more good tips on how to use SSE vectors. Also other links in the x86 标签 wiki。