Расширения SSE/AVX предоставляют инструкции для паралелльных операций с плавающей точкой:
addps
: складывает 4 дорожки операндов с 32-разрядными числами с плавающей точкой
addpd
: складывает 2 дорожки операндов с 64-разрядными числами с плавающей точкой
vaddps
: складывает 4 дорожки (128-битная версия) или 8 дорожек (256-битная версия) с 32-разрядными числами с плавающей точкой
vaddpd
: складывает 2 дорожки (128-битная версия) или 4 дорожки (256-битная версия) с 64-разрядными числами с плавающей точкой
subps
: вычитает 4 дорожки операндов с 32-разрядными числами с плавающей точкой
subpd
: вычитает 2 дорожки операндов с 64-разрядными числами с плавающей точкой
vsubps
: вычитает 4 дорожки (128-битная версия) или 8 дорожек (256-битная версия) с 32-разрядными числами с плавающей точкой
vsubpd
: вычитает 2 дорожки (128-битная версия) или 4 дорожки (256-битная версия) с 64-разрядными числами с плавающей точкой
mulps
: перемножает 4 дорожки операндов с 32-разрядными числами с плавающей точкой
mulpd
: перемножает 2 дорожки операндов с 64-разрядными числами с плавающей точкой
vmulps
: перемножает 4 дорожки (128-битная версия) или 8 дорожек (256-битная версия) с 32-разрядными числами с плавающей точкой
vmulpd
: перемножает 2 дорожки (128-битная версия) или 4 дорожки (256-битная версия) с 64-разрядными числами с плавающей точкой
divps
: делит 4 дорожки операндов с 32-разрядными числами с плавающей точкой
divpd
: делит 2 дорожки операндов с 64-разрядными числами с плавающей точкой
vdivps
: делит 4 дорожки (128-битная версия) или 8 дорожек (256-битная версия) с 32-разрядными числами с плавающей точкой
vdivpd
: делит 2 дорожки (128-битная версия) или 4 дорожки (256-битная версия) с 64-разрядными числами с плавающей точкой
maxps
: вычисляет максимальное в каждой из 4 пар чисел с плавающей точкой одинарной точности
maxpd
: вычисляет максимальное в каждой из 2 пар чисел с плавающей точкой двойной точности
vmaxps
: вычисляет максимальное в каждой из 4 (для 128-битной версии) или 8 (для 256-битной версии) пар чисел с плавающей точкой одинарной точности
vmaxpd
: вычисляет максимальное в каждой из 2 (для 128-битной версии) или 4 (для 256-битной версии) пар чисел с плавающей точкой двойной точности
minps
: вычисляет минимальное в каждой из 4 пар чисел с плавающей точкой одинарной точности
minpd
: вычисляет минимальное в каждой из 2 пар чисел с плавающей точкой двойной точности
vminps
: вычисляет минимальное в каждой из 4 (для 128-битной версии) или 8 (для 256-битной версии) пар чисел с плавающей точкой одинарной точности
vminpd
: вычисляет минимальное в каждой из 2 (для 128-битной версии) или 4 (для 256-битной версии) пар чисел с плавающей точкой двойной точности
sqrtps
: вычисляет квадратный корень для каждого из 4 чисел с плавающей точкой одинарной точности
sqrtpd
: вычисляет квадратный корень для 2 чисел с плавающей точкой двойной точности
vsqrtps
: вычисляет квадратный корень для каждого из 4 (для 128-битной версии) или 8 (для 256-битной версии) чисел с плавающей точкой одинарной точности
vsqrtpd
: вычисляет квадратный корень для каждого из 2 (для 128-битной версии) или 4 (для 256-битной версии) чисел с плавающей точкой двойной точности
rsqrtps
: вычисляет приблизительно обратный квадратный корень для каждого из 4 чисел с плавающей точкой одинарной точности
vrsqrtps
: вычисляет приблизительно обратный квадратный корень для каждого из 4 (для 128-битной версии) или 8 (для 256-битной версии) чисел с плавающей точкой одинарной точности
Общий синтаксис инструкций на примере v(addps)
:
addps xmmsrc/mem128, xmmdest vaddps xmmsrc2/mem128, xmmsrc1, xmmdest vaddps ymmsrc2/mem256, ymmsrc1, ymmdest
Инструкции вычисления квадратного корня принимают два операнда:
sqrtps xmmsrc/mem128, xmmdest vsqrtps xmmsrc/mem128, xmmdest vsqrtps ymmsrc/mem256, ymmdest
Применение инструкций на примере сложения:
.globl main .data nums0: .single 1.1, 2.2, 3.3, 4.4 nums1: .single 1.2, 2.3, 3.4, 4.5 format_str: .asciz "%.1f, %.1f, %.1f, %.1f\n" .text main: subq $8, %rsp # выравниваение по 16 байтам для функции printf movaps nums0, %xmm0 movaps nums1, %xmm1 vaddps %xmm1, %xmm0, %xmm5 # xmm5 = xmm0+xmm1 # выводим данные на консоль movss %xmm5, %xmm0 # помещаем число float в регистр для передачи в функцию printf cvtss2sd %xmm0, %xmm0 # преобразуем float в double psrldq $4, %xmm5 # сдвиг вправо на 4 байта для получения следующего числа movss %xmm5, %xmm1 cvtss2sd %xmm1, %xmm1 psrldq $4, %xmm5 movss %xmm5, %xmm2 cvtss2sd %xmm2, %xmm2 psrldq $4, %xmm5 movss %xmm5, %xmm3 cvtss2sd %xmm3, %xmm3 movq $format_str, %rdi call printf addq $8, %rsp ret
Здесь складываются два вектора 32-разрядных чисел nums0 и nums1. Для упрощения тестирования для вывода результата на консоль здесь используется функция printf
. Компиляция и консольный вывод программы:
root@Eugene:~/asm# gcc -static hello.s -o hello root@Eugene:~/asm# ./hello 2.3, 4.5, 6.7, 8.9 root@Eugene:~/asm#