Funções Matemáticas Vetoriais com SSE e AVX em Assembly NASM
As extensões SSE e AVX incluem um conjunto de instruções para realizar operações matemáticas comuns em vetores, como cálculo de média, busca por valores máximos e mínimos, e obtenção do valor absoluto.
Cálculo de Média
As instruções (v)pavgb e (v)pavgw calculam a média aritmética dos elementos correspondentes de dois vetores.
pavgb xmmdest, xmmsrc/mem128
vpavgb xmmdest, xmmsrc1, xmmsrc2/mem128
vpavgb ymmdest, ymmsrc1, ymmsrc2/mem256
pavgw xmmdest, xmmsrc/mem128
vpavgw xmmdest, xmmsrc1, xmmsrc2/mem128
vpavgw ymmdest, ymmsrc1, ymmsrc2/mem256A instrução (v)pavgb opera em bytes, calculando a média para cada par de bytes nas 16 pistas (para 128 bits) ou 32 pistas (para 256 bits). De forma análoga, (v)pavgw opera em words (16 bits) em 8 ou 16 pistas.
Se a soma dos dois valores for ímpar, o resultado é arredondado para cima. Matematicamente, a operação é (a + b + 1) / 2.
O exemplo a seguir para Linux demonstra o cálculo da média.
global main
extern printf
section .data
nums0 dw 3, 4, 6, 7
nums1 dw 2, 3, 4, 5
format_str db "%d, %d, %d, %d", 10, 0
section .text
main:
sub rsp, 8
movaps xmm0, [nums0]
movaps xmm1, [nums1]
pavgw xmm0, xmm1 ; XMM0 = (XMM0 + XMM1 + 1) / 2
; Resultado em XMM0: [3, 4, 5, 6]
; (3+2+1)/2=3, (4+3+1)/2=4, (6+4)/2=5, (7+5)/2=6
; Exibe os dados no console
movd esi, xmm0
psrldq xmm0, 4
movd edx, xmm0
psrldq xmm0, 4
movd ecx, xmm0
psrldq xmm0, 4
movd r8d, xmm0
mov rdi, format_str
xor rax, rax
call printf
add rsp, 8
retResultado da execução:
$ nasm -f elf64 hello.asm -o hello.o $ gcc -static hello.o -o hello $ ./hello 3, 4, 5, 6
Valores Máximos e Mínimos
A partir do SSE4.1, foram adicionadas instruções para encontrar o valor máximo ou mínimo entre os elementos correspondentes de dois vetores.
Para encontrar o máximo:
(v)pmaxsb,(v)pmaxsw,(v)pmaxsd,vpmaxsq: Para inteiros com sinal de 8, 16, 32 e 64 bits.(v)pmaxub,(v)pmaxuw,(v)pmaxud,vpmaxuq: Para inteiros sem sinal de 8, 16, 32 e 64 bits.
Para encontrar o mínimo:
(v)pminsb,(v)pminsw,(v)pminsd,vpminsq: Para inteiros com sinal.(v)pminub,(v)pminuw,(v)pminud,vpminuq: Para inteiros sem sinal.
A sintaxe geral, exemplificada com (v)pmaxuw, é:
pmaxuw xmmdest, xmmsrc/mem128
vpmaxuw xmmdest, xmmsrc1, xmmsrc2/mem128
vpmaxuw ymmdest, ymmsrc1, ymmsrc2/mem256Essas instruções comparam cada par de elementos nas pistas dos operandos e copiam o maior (ou menor) valor para a pista correspondente do registrador de destino.
O exemplo a seguir para Linux encontra os valores máximos em cada pista.
global main
extern printf
section .data
nums0 dd 2, 3, 8, 9
nums1 dd 4, 5, 6, 7
format_str db "%d, %d, %d, %d", 10, 0
section .text
main:
sub rsp, 8
movaps xmm0, [nums0]
movaps xmm1, [nums1]
pmaxud xmm0, xmm1 ; Compara XMM0 e XMM1, armazena os máximos em XMM0
; Resultado em XMM0: [4, 5, 8, 9]
; Exibe os dados no console
movd esi, xmm0
psrldq xmm0, 4
movd edx, xmm0
psrldq xmm0, 4
movd ecx, xmm0
psrldq xmm0, 4
movd r8d, xmm0
mov rdi, format_str
xor rax, rax
call printf
add rsp, 8
retResultado da execução:
$ nasm -f elf64 hello.asm -o hello.o $ gcc -static hello.o -o hello $ ./hello 4, 5, 8, 9
Valor Absoluto
As extensões SSE/AVX também fornecem instruções para calcular o valor absoluto de inteiros com sinal: (v)pabsb (bytes), (v)pabsw (words) e (v)pabsd (dwords).
A sintaxe é a seguinte:
pabsb xmmdest, xmmsrc/mem128
vpabsb xmmdest, xmmsrc/mem128
vpabsb ymmdest, ymmsrc/mem256
pabsw xmmdest, xmmsrc/mem128
vpabsw xmmdest, xmmsrc/mem128
vpabsw ymmdest, ymmsrc/mem256
pabsd xmmdest, xmmsrc/mem128
vpabsd xmmdest, xmmsrc/mem128
vpabsd ymmdest, ymmsrc/mem256Essas instruções calculam o valor absoluto de cada elemento no operando de origem e armazenam o resultado no operando de destino. As versões SSE (pabs*) não modificam os 128 bits superiores dos registradores YMM, enquanto as versões AVX de 128 bits (vpabs*) preenchem esses bits com zeros.
Resumo
- As instruções
pavgcalculam a média de elementos correspondentes em dois vetores, com arredondamento para cima. - As instruções
pmaxepminrealizam comparações paralelas para encontrar os valores máximos ou mínimos entre dois vetores. - As instruções
pabscalculam o valor absoluto de múltiplos inteiros com sinal de uma só vez.