- •«Расширение
- •Введение
- •1. Общее представление о sse
- •1.1. Simd-регистры с плавающей точкой
- •1.2. Тип данных simd с плавающей точкой
- •1.3. Модель выполнения simd
- •1.4. Формат данных в памяти
- •1.5. Формат данных simd регистра с плавающей точкой
- •1.6. Simd-регистр состояния и управления
- •1.7. Поле управления округлением
- •1.8. Режим Flush To Zero
- •2. Команды Потокового Расширения simd
- •2.1. Операнды команд
- •3. Обзор simd-команд
- •3.1. Команды копирования данных
- •3.2. Арифметические команды
- •3.2.1. Команды упакованного/скалярного сложения и вычитания
- •3.2.2. Команды упакованного/скалярного умножения и деления
- •3.2.3. Команды упакованного/скалярного вычисления квадратных корней
- •3.2.4. Команды упакованного/скалярного нахождения минимума и максимума
- •3.3. Команды сравнения
- •3.4. Команды преобразования типов данных
- •3.5. Логические команды
- •3.6. Дополнительные команды simd над целыми
- •3.7. Команды перестановки
- •3.8. Команды управления состоянием
- •3.9. Команды управления кэшированием
- •3.9.1 Некэширующие команды записи в память
- •3.9.2 Упреждающее кэширование
- •3.9.3 Принудительная запись
- •4. Таблица команд sse и генерируемых исключений
- •Список использованной литературы и других источников
3.2.4. Команды упакованного/скалярного нахождения минимума и максимума
Команды нахождения минимума и максимума производят попарное сравнение соответствующих элементов двух операндов и записывают минимальные или максимальные значения в выходной операнд. Входной операнд для этих команд может располагаться либо в XMM-регистре, либо в памяти. Выходной операнд должен обязательно находиться в XMM-регистре. Поддерживаются как параллельные, так и скалярные операции (MAXPS (Maximum packed, single-precision, floating-point), MAXSS, MINPS и MINSS).
MAXPS:
xmm1[31-0] = (xmm1[31-0] == NaN) ? xmm1[31-0]:
(xmm2[31-0] == NaN) ? xmm1[31-0]:
(xmm1[31-0] > xmm2/m128[31-0]) ? xmm1[31-0] : xmm2/m128[31-0]);
xmm1[63-32] = (xmm1[63-32] == NaN) ? xmm1[63-32]:
(xmm2[63-32] == NaN) ? xmm1[63-32]:
(xmm1[63-32] > xmm2/m128[63-32]) ? xmm1[63-32] : xmm2/m128[63-32]);
xmm1[95-64] = (xmm1[95-64] == NaN) ? xmm1[95-64]:
(xmm2[95-64] == NaN) ? xmm1[95-64]:
(xmm1[95-64] > xmm2/m128[95-64]) ? xmm1[95-64] : xmm2/m128[95-64]);
xmm1[127-96] = (xmm1[127-96] == NaN) ? xmm1[127-96]:
(xmm2[127-96] == NaN) ? xmm1[127-96]:
(xmm1[127-96]>xmm2/m128[127-96])?xmm1[127-96]: xmm2/m128[127-96]);
MAXSS:
xmm1[31-0] = (xmm1[31-0] == NaN) ? xmm1[31-0]:
(xmm2[31-0] == NaN) ? xmm1[31-0]:
(xmm1[31-0] > xmm2/m128[31-0]) ? xmm1[31-0] : xmm2/m128[31-0]);
xmm1[63-32] = xmm1[63-32];
xmm1[95-64] = xmm1[95-64];
xmm1[127-96] = xmm1[127-96];
MINPS:
xmm1[31-0] = (xmm1[31-0] == NaN) ? xmm1[31-0]:
(xmm2[31-0] == NaN) ? xmm1[31-0]:
(xmm1[31-0] < xmm2/m128[31-0]) ? xmm1[31-0] : xmm2/m128[31-0]);
xmm1[63-32] = (xmm1[63-32] == NaN) ? xmm1[63-32]:
(xmm2[63-32] == NaN) ? xmm1[63-32]:
(xmm1[63-32] < xmm2/m128[63-32]) ? xmm1[63-32] : xmm2/m128[63-32]);
xmm1[95-64] = (xmm1[95-64] == NaN) ? xmm1[95-64]:
(xmm2[95-64] == NaN) ? xmm1[95-64]:
(xmm1[95-64] < xmm2/m128[95-64]) ? xmm1[95-64] : xmm2/m128[95-64]);
xmm1[127-96] = (xmm1[127-96] == NaN) ? xmm1[127-96]:
(xmm2[127-96] == NaN) ? xmm1[127-96]:
(xmm1[127-96]< xmm2/m128[127-96])?xmm1[127-96]: xmm2/m128[127-96]);
MINSS:
xmm1[31-0] = (xmm1[31-0] == NaN) ? xmm1[31-0]:
(xmm2[31-0] == NaN) ? xmm1[31-0]:
(xmm1[31-0] < xmm2/m128[31-0]) ? xmm1[31-0] : xmm2/m128[31-0]);
xmm1[63-32] = xmm1[63-32];
xmm1[95-64] = xmm1[95-64];
xmm1[127-96] = xmm1[127-96];
3.3. Команды сравнения
Команды сравнения попарно сравнивают все четыре соответствующих FP‑элемента двух операндов (для скалярного варианта команд – только младшие элементы) и проверяют выполнение арифметического условия, специфичного для каждой команды. Если для сравниваемой пары условие выполняется, то в соответствующие 32 разряда выходного операнда записывается маска из всех единиц, в противном случае – маска из нулей. Получаемая в результате двоичная маска обычно используется при логических операциях с объектами. Входной операнд может располагаться либо в XMM регистре, либо в памяти. Выходным операндом должен быть XMM регистр (SIMD регистр).
Команды сравнения:
Команда CMPPS (Compare packed, single-precision, floating-point) сравнивает четыре пары упакованных чисел одинарной точности с плавающей точкой, используя непосредственный операнд как предикат, возвращает как результат в каждом поле SP все "1" (32-битовая маска) или все "0". Команда поддерживает набор условий (см. табл. 4), которые передаются ей в качестве третьего операнда.
switch (imm8)
{
case eq : op = eq; break;
case lt : op = lt; break;
case le : op = le; break;
case unord : op = unord; break;
case neq : op = neq; break;
case nlt : op = nlt; break;
case nle : op = nle; break;
case ord : op = ord; break;
default : raise(INVALID_OPCODE); break;
}
cmp0 = op(xmm1[31-0], xmm2/m128[31-0] );
cmp1 = op(xmm1[63-32], xmm2/m128[63-32] );
cmp2 = op(xmm1[95-64], xmm2/m128[95-64] );
cmp3 = op(xmm1[127-96], xmm2/m128[127-96]);
xmm1[31-0] = cmp0 ? 0xFFFFFFFF : 0x00000000;
xmm1[63-32] = cmp1 ? 0xFFFFFFFF : 0x00000000;
xmm1[95-64] = cmp2 ? 0xFFFFFFFF : 0x00000000;
xmm1[127-96] = cmp3 ? 0xFFFFFFFF : 0x00000000;
Команда CMPSS (Compare scalar single-precision, floating-point) сравнивает младшую пару упакованных чисел, используя непосредственный операнд как предикат (как и в CMPPS), возвращает как результат в младшем поле SP 32-битовую маску из всех "1" или всех "0".
switch (imm8)
{
case eq : op = eq; break;
case lt : op = lt; break;
case le : op = le; break;
case unord : op = unord; break;
case neq : op = neq; break;
case nlt : op = nlt; break;
case nle : op = nle; break;
case ord : op = ord; break;
default : raise(INVALID_OPCODE); break;
}
cmp0 = op(xmm1[31-0], xmm2/m32[31-0] );
xmm1[31-0] = cmp0 ? 0xFFFFFFFF : 0x00000000;
xmm1[63-32] = xmm2[63-32];
xmm1[95-64] = xmm2[95-64]
xmm1[127-96] =xmm2[127-96]
Эквивалентная форма |
Фактическая форма |
Тип сравнения |
CMPEQ[PS,SS] xmm1,xmm2 CMPLT[PS,SS] xmm1,xmm2 CMPLE[PS,SS] xmm1,xmm2 CMPUNORD[PS,SS] xmm1,xmm2 CMPNEQ[PS,SS] xmm1,xmm2 CMPNLT[PS,SS] xmm1,xmm2 CMPNLE[PS,SS] xmm1,xmm2 CMPORD[PS,SS] xmm1,xmm2 |
CMP[PS,SS] xmm1,xmm2,0 CMP[PS,SS] xmm1,xmm2,1 CMP[PS,SS] xmm1,xmm2,2 CMP[PS,SS] xmm1,xmm2,3 CMP[PS,SS] xmm1,xmm2,4 CMP[PS,SS] xmm1,xmm2,5 CMP[PS,SS] xmm1,xmm2,6 CMP[PS,SS] xmm1,xmm2,7 |
равно меньше меньше или равно неупорядочены не равно не меньше не меньше или равно упорядочены |
Таблица 7. Две формы записи команд сравненияCMP[PS,SS].
Команда COMISS (Compare scalar single-precision, floating-point ordered and set EFLAGS) сравнивает младшую пару упакованных чисел, и устанавливает флаги ZF, PF, и CF в регистре флагов EFLAGS (флаги OF, SF, и AF сбрасываются).
switch (xmm1[31-0]<>xmm2/m32[31-0])
{
case UNORDERED : ZF,PF,CF = 111; break;
case GREATER_THAN : ZF,PF,CF = 000; break;
case LESS_THAN : ZF,PF,CF = 001; break;
case EQUAL : ZF,PF,CF = 100; break;
}
Команда UCOMISS (Unordered compare scalar single-precision, floating-point ordered and set EFLAGS) сравнивает младшую пару упакованных чисел, и устанавливает флаги ZF, PF, и CF в регистре флагов EFLAGS (флаги OF, SF, и AF сбрасываются).
switch (xmm1[31-0]<>xmm2/m32[31-0])
{
case UNORDERED : ZF,PF,CF = 111; break;
case GREATER_THAN : ZF,PF,CF = 000; break;
case LESS_THAN : ZF,PF,CF = 001; break;
case EQUAL : ZF,PF,CF = 100; break;
}
При этом COMISS реализует исключение типа #1, если хотя бы один из операндов не число (SnaN или QnaN), а UCOMISS – если элемент одного из операндов является SnaN.