xmm regs 没有 inc 等效项,paddw 也没有立即操作数形式(因此也没有 add eax, 1 等效项)。
paddw (and other element sizes) 仅适用于 xmm/m128 源操作数。所以如果你想增加一个向量的一个元素,你需要从内存中加载一个常量or generate it on the fly。
例如增加 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 指南,了解有关如何使用 SSE 向量的更多好技巧。还有x86 标签维基中的其他链接。