Инструкции (v)pavgb и (v)pavgw вычисляют среднее значение двух соответствующих дорожек операндов:
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/mem256
128-битные инструкции pavgb
и vpavgb
берут два байта из соответствующих 16 дорожек первого и второго операндах и вычисляют среднее этих двух чисел. Среднее
значение помещается в первый операнд.
256-битный вариант инструкции vpavgb
вычисляет средние значения для 32 дорожек.
128-битные инструкции pavgw
и vpavgw
вычисляют 8 средних значений для каждой пары слов из 8 дорожек первого и второго операнда.
256-битный вариант инструкции vpavgw
вычисляет средние значения для 16 дорожек.
Если результат дробный, то он округляется.
Пример применения на Linux:
global main extern printf section .data nums0 dd 3, 4, 6, 7 nums1 dd 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) / 2 ; XMM0 = 3, 4, 5, 6 ; выводим данные на консоль 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 call printf add rsp, 8 ret
Пример работы:
root@Eugene:~/asm# nasm -f elf64 hello.asm -o hello.o root@Eugene:~/asm# gcc -static hello.o -o hello root@Eugene:~/asm# ./hello 3, 4, 5, 6 root@Eugene:~/asm#
Расширения SSE4.1 добавили восемь инструкций для поиска минимума и максимума из двух соответствующих дорожек:
(v)pmaxsb
: выбирает максимальное однобайтовое число со знаком из соответствующих дорожек операндов.
(v)pmaxsw
: выбирает максимальное 16-битное число со знаком из соответствующих дорожек операндов.
(v)pmaxsd
: выбирает максимальное 32-битное число со знаком (sdword).
vpmaxsq
: выбирает максимальное 64-битное число со знаком.
(v)pmaxub
: выбирает максимальное беззнаковое 8-битное число из соответствующих дорожек операндов.
(v)pmaxuw
: выбирает максимальное беззнаковое 16-битное число.
(v)pmaxud
: выбирает максимальное беззнаковое 32-битное число.
vpmaxuq
: выбирает максимальное беззнаковое 64-битное число.
(v)pminsb
: выбирает минимальное однобайтовое число со знаком из соответствующих дорожек операндов.
(v)pminsw
: выбирает минимальное 16-битное число со знаком из соответствующих дорожек операндов.
(v)pminsd
: выбирает минимальное 32-битное число со знаком (sdword).
vpminsq
: выбирает минимальное 64-битное число со знаком.
(v)pminub
: выбирает минимальное беззнаковое 8-битное число из соответствующих дорожек операндов.
(v)pminuw
: выбирает минимальное беззнаковое 16-битное число.
(v)pminud
: выбирает минимальное беззнаковое 32-битное число.
vpminuq
: выбирает минимальное беззнаковое 64-битное число.
Общий синтаксис инструкций на примере pmaxuw
и vpmaxuw
(остальные инструкции имеют аналогичный синтаксис)
pmaxuw xmmdest, xmmsrc/mem128 vpmaxuw xmmdest, xmmsrc1, xmmsrc2/mem128 vpmaxuw ymmdest, ymmsrc1, ymmsrc2/mem256
Эти инструкции сканируют дорожки пары 128- или 256-битных операндов и копируют максимальное или минимальное значение из этой дорожки в ту же дорожку первого операнда. Пример нахожжения максимальных слов в дорожках в программе на Linux:
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 ; XMM0 = (XMM0 + XMM1) / 2 ; XMM0 = 4, 5, 8, 9 ; выводим данные на консоль 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 call printf add rsp, 8 ret
Пример работы:
root@Eugene:~/asm# nasm -f elf64 hello.asm -o hello.o root@Eugene:~/asm# gcc -static hello.o -o hello root@Eugene:~/asm# ./hello 4, 5, 8, 9 root@Eugene:~/asm#
SSE/AVX предоставляют несколько инструкций для вычисления абсолютных значений целых чисел со знаком: (v)pabsb
(для байтов), (v)pabsw
(для слов) и
(v)pabsd
(для двойных слов). Их синтаксис:
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/mem256
Инструкции pabsb, pabsw и pabsd не изменяют старшие 128 битов регистров YMM, а 128-битные версии инструкций vpabsb, vpabsw и vpabsd заполняют нулями старшие 128 битов регистров YMM.